/** * WeChat 3.2.1.121 * > Special thanks to: @cixingguangming55555 老张学技术 * * Credit: https://github.com/cixingguangming55555/wechat-bot * Source: https://pan.baidu.com/s/1OmX2lxNOYHyGsl_3ByhsoA * 《源码3.2.1.121》提取码: 1rfa * WeChat: https://pan.baidu.com/share/init?surl=IHRM2OMvrLyuCz5MRbigGg * 微信:3.2.1.121 提取码: cscn */ //https://blog.csdn.net/iloveitvm/article/details/109119687 frida学习 //const { isNullishCoalesce } = require("typescript") //3.6.0.18 const offset = { /**---nick call */ chatroom_member_nick_call_offset_v6:0x3E47B0,//3.6.0.18 chatroom_member_nick_esi_offset_v6:0x22553D4, /**-- nick call */ node_offset: 0x222f3bc,//0x1db9728 -- 3.3.0.155 handle_offset: 0x4c, send_txt_call_offset: 0x4BE7B0,//0x3e3b80 hook_point: 0x4E94F2,//0x4E9464,//3.3.0.115 = 0x40d3b1 chatroom_node_offset: 0xad8, nickname_offset: 0x222EBB4, wxid_offset: 0x222F020, head_img_url_offset: 0x222EE94, is_logged_in_offset: 0x1DDF9D4, hook_on_login_offset: 0x51B790, hook_on_logout_offset: 0x51C2C0, hook_get_login_qr_offset: 0x4B6020, hook_check_login_qr_offset: 0x478B90, hook_save_login_qr_info_offset: 0x3DB2E0, get_login_wnd_offset: 0x1DB96A4, get_qr_login_data_offset: 0x282160, get_qr_login_call_offset: 0x286930, //-------3.6.0.18 send pic send_picmsg_call_offset0:0x9A1C0,//assign value to ecx send_picmsg_call_offset1: 0x4BE160,//0x5ccb50, send_picmsg_call_ecx:0x222F0F0, //-------3.6.0.18 send pic /*send_picmsg_call_offset2: 0x6f5c0, send_picmsg_call_offset3: 0x3e3490,*/ send_attatch_ecx_offset:0x1D8FA8C, send_attatch_call_offset0: 0x9A1C0, send_attatch_call_offset1: 0x701DC0,//0x701CD0,//701CD0 send_attatch_call_offset2: 0x4BA5F0,//4B A5F0 send_attatch_call_offset3: 0xC95A0, send_attatch_call_offset4: 0x94200, send_attatch_call_offset5: 0x3C4950, send_attatch_call_offset6: 0x63B4F0, send_attatch_call_para1: 0x1D8F248, send_attatch_call_para2: 0x19a7350, chatroom_member_nick_call_offset1: 0x558cb0, chatroom_member_nick_call_offset2: 0x3b0fe0, chatroom_member_nick_call_offset3: 0x55f6e0, chatroom_member_nick_call_offset4: 0x34cb10, }; //3.3.0.115 /*------------------global-------------------------------------------*/ const availableVersion = 1661337618////3.3.0.115 ==1661141107 const moduleBaseAddress = Module.getBaseAddress('WeChatWin.dll') const moduleLoad = Module.load('WeChatWin.dll') //1575CF98 const g_EDIPtr = moduleBaseAddress.add(0x222f38c).readPointer().add(0xD70).readPointer()// const g_EDIU32 = moduleBaseAddress.add(0x222f38c).readPointer().add(0xD70).readU32() let currentVersion = 0 let nodeList = [] //for contact let contactList = [] //for contact let chatroomNodeList = [] //for chatroom let chatroomMemberList = []//for chatroom let loggedIn = false /*------------------global-------------------------------------------*/ //开启日志 3.6.0.18 // //[0x221c330+wechatwin.dll]+0xf8 // 20220504 let g_initTestAsm = null let g_BufferEbp2C = null let g_initECXU32 = null let g_initECXPtr = null let g_initEBXPtr = null let g_initEBX = null let g_attatchEBP210Buffer = null let g_attatchPathPtr = null let g_attatchPath = null let g_attatchEBPAc = null let g_attatchEBPAcBufPtr = null let g_attatchContactIdPtr = null //let g_attatchECXBuffer = null let g_attatchESIU32 = null let g_initECXTempPtr = null const initGlobal = ( (contactId,attatchFile)=> { //const base = moduleBaseAddress.add(0x222f38c).readPointer() //g_EDI = base.add(0xD70).readPointer()//0x438+0x938 console.log('------------g_attatchEBPAc',g_attatchEBPAc) console.log('------------g_EDIU32',g_EDIU32) g_initTestAsm = Memory.alloc(Process.pageSize) console.log('------------address',g_initTestAsm) g_initECXPtr = g_EDIPtr.add(0xB80).readPointer().add(0x1640) g_initECXTempPtr = g_EDIPtr.add(0xB88).readPointer() g_initECXU32 = g_initECXPtr.toInt32() g_attatchESIU32 = g_EDIU32 console.log('------------g_initECXU32',g_initECXU32) console.log('------------g_initESIU32',g_attatchESIU32) //console.log('==========g_initECXPtr',g_initECXPtr) //console.log('==========g_EDIU32',g_EDIU32) //g_attatchECXBuffer = Memory.alloc(0x1024) //Memory.copy(g_attatchECXBuffer, g_initECXPtr, 0x1024) g_BufferEbp2C = Memory.alloc(0x48) //g_initEBX = moduleBaseAddress.add(0x2251724).readPointer().readPointer() //g_initEBXPtr = Memory.alloc(0x14).writePointer(g_initEBX) //g_initEBXPtr.add(0x08).writePointer(g_BufferEbp2C) g_attatchPathPtr = Memory.alloc(attatchFile.length * 2 + 2) g_attatchPathPtr.writeUtf16String(attatchFile) g_attatchPath = Memory.alloc(0x28) g_attatchPath.writePointer(g_attatchPathPtr).add(0x04) .writeU32(attatchFile.length * 2).add(0x04) .writeU32(attatchFile.length * 2).add(0x04) /*---------------------------------ebp-210----------------*/ g_attatchEBP210Buffer = Memory.alloc(0x48) g_attatchEBP210Buffer.writeU32(0x3) g_attatchEBP210Buffer.add(0x4).writePointer(g_attatchPathPtr) g_attatchEBP210Buffer.add(0x8).writeU32(attatchFile.length * 2) g_attatchEBP210Buffer.add(0xC).writeU32(attatchFile.length * 2) g_attatchEBP210Buffer.add(0x2C).writeU32(moduleBaseAddress.add(0x2ECE87).toInt32()) //console.log('------------g_attatchEBP210Buffer',g_attatchEBP210Buffer) /*---------------------------------ebp-210----------------*/ //g_attatchContactIdPtr = Memory.alloc(0x4) //g_attatchContactIdPtr.writeUtf16String(contactId) //console.log('------------g_attatchEBP210Buffer',g_attatchEBP210Buffer) g_attatchEBPAc = Memory.alloc(0x140) //g_attatchEBPAcBufPtr = Memory.alloc(0x100) //g_attatchEBPAc.writePointer(g_attatchEBP210Buffer) //g_attatchEBPAc.add(0x4).writePointer(g_attatchEBPAcBufPtr) //g_attatchEBPAc.add(0x8).writePointer(g_attatchEBPAcBufPtr) g_attatchEBPAc.add(0x10).writeU32(g_EDIU32) console.log('------------g_attatchEBPAc',g_attatchEBPAc) /*g_attatchECXBuffer.add(0x18).writePointer(g_attatchContactIdPtr) g_attatchECXBuffer.add(0x1C).writeU32(contactId.length*2) .add(0x04).writeU32(contactId.length*2)*/ //g_attatchESIU32 = g_EDI.toInt32() //console.log('------------g_attatchESIU32',g_attatchESIU32) //console.log('==========g_attatchECXBuffer',g_attatchECXBuffer) Memory.patchCode(g_initTestAsm, Process.pageSize, code => { var cw = new X86Writer(code, { pc: g_initTestAsm }) cw.putPushfx() cw.putPushax() //cw.putMovRegAddress('eax', g_attatchEBP210Buffer) /*cw.putMovRegAddress('edi',g_EDIPtr) cw.putMovRegReg('esi','edi') cw.putMovRegAddress('eax',g_BufferEbp2C) cw.putMovRegAddress('ecx',g_initECXTempPtr) cw.putPushReg('eax') cw.putCallAddress(moduleBaseAddress.add(0x131bb0))*/ //cw.putMovRegOffsetPtrU32('ebp', -20, 0) /*cw.putPushU32(0) cw.putMovRegAddress('eax', g_attatchPathPtr) cw.putPushReg('eax') cw.putPushU32(3) cw.putMovRegAddress('ecx', g_attatchEBP210Buffer) cw.putCallAddress(moduleBaseAddress.add(0x130220))*/ /*cw.putMovRegAddress('edi', g_attatchEBPAc)//后面要用的的ebp-2c cw.putMovRegAddress('ecx', g_attatchEBP210Buffer) cw.putPushReg('ecx') cw.putMovRegU32('eax',0) cw.putPushReg('eax')//push eax cw.putMovRegReg('ecx', 'edi') cw.putMovRegAddress('esi',g_attatchPathPtr) cw.putCallAddress(moduleBaseAddress.add(0x138880))*/ /*cw.putSubRegImm('esp',0x14) cw.putMovRegU32('ecx',g_initECXU32) cw.putMovRegU32('esi',g_attatchESIU32) cw.putMovRegAddress('eax', g_attatchEBPAc) cw.putPushReg('eax') cw.putCallAddress(moduleBaseAddress.add(0x173620))*/ //cw.putCallAddress(moduleBaseAddress.add(0x522590)) /** g_attatchEBPAc*/ //cw.putMovRegNearPtr('eax', g_attatchEBPAc) //cw.putMovNearPtrReg(g_attatchEBPAc.add(0xc), 'eax') /** g_attatchEBPAc*/ //cw.putMovRegAddress('ebx', g_initEBXPtr) //cw.putMovRegU32('edi', g_EDI.toInt32()) //cw.putMovRegU32('esi', g_EDI.toInt32()) /*cw.putMovRegU32('ecx', g_initECX) cw.putMovRegAddress('eax', g_BufferEbp2C) cw.putPushReg('eax') cw.putCallAddress(moduleBaseAddress.add(0x131BB0))*/ cw.putPopax() cw.putPopfx() cw.putRet() cw.flush() }) const nativeativeFunction = new NativeFunction(ptr(g_initTestAsm), 'void', []) nativeativeFunction() }) let g_personal_detail_ebx =null let g_personal_detail_asm =null let g_personal_wxid = null let g_personal_wxid_ptr = null const getOldTest = ( (wxid) => {//personal detail g_personal_detail_asm = Memory.alloc(Process.pageSize) g_personal_detail_ebx = moduleBaseAddress.add(0x222F38C).readPointer().add(0xFB8).toInt32() g_personal_wxid_ptr=Memory.alloc(wxid.length * 2 + 2) g_personal_wxid_ptr.writeUtf16String(wxid) g_personal_wxid=Memory.alloc(0x14) g_personal_wxid.writePointer(ptr(g_personal_wxid_ptr)).add(0x04) .writeU32(wxid.length*2).add(0x04) .writeU32(wxid.length*2).add(0x08) console.log('-----------address----------',g_personal_detail_asm) Memory.patchCode(g_personal_detail_asm, Process.pageSize, code => { var cw = new X86Writer(code, { pc: g_personal_detail_asm }) cw.putPushfx() cw.putPushax() cw.putCallAddress(moduleBaseAddress.add(0x9A000)) //78BA9ACE | E8 2D05D6FF | call wechatwin.7890A000 | cw.putMovRegU32('ebx', g_personal_detail_ebx) cw.putMovRegReg('esi','eax') cw.putPushReg('ebx') cw.putSubRegImm('esp',0x14) cw.putMovRegAddress('eax', g_personal_wxid) cw.putMovRegReg('ecx','esp') cw.putPushReg('eax') cw.putCallAddress(moduleBaseAddress.add(0x701DC0)) cw.putMovRegReg('ecx','esi') cw.putCallAddress(moduleBaseAddress.add(0x4024A0)) cw.putPopax() cw.putPopfx() cw.putRet() cw.flush() }) const nativeativeFunction = new NativeFunction(ptr(g_personal_detail_asm), 'void', []) nativeativeFunction() }) // const writeLogNativeCallback = (() => { // const nativeCallback = new NativeCallback(() => { }, 'void', []) // const nativeCallFunction = new NativeFunction(nativeCallback, 'void', []) // Interceptor.attach( // moduleBaseAddress.add(0x7008A4), // { // onEnter() { // const addr = this.context.eax//.sub(0x114)//0xc30-0x08 // if(addr >0){ // const log = ptr(addr).readAnsiString() // } // } // }) // return nativeCallback // })() /** * test call */ let attatchTestAsm = null let attatchTestEbp2C = null let attatchGlobalEDI = null let attatchGlobalEDIB88 = null let attatchTestEBX = null let g_tempEcx = null let attatchFirstECX = null //let attatchFirstECX = null let gattatchFilePtr=null let gattatchFile = null let gattatchReceiveIdPtr=null let gattatchReceiveId=null let attatchEAX3B0Buf=null let attatchESIbuf = null const getWxTest = ( (contactId,filePath)=>{ //const nativeativeFunction = new NativeFunction(ptr(addr), 'void', []) //nativeativeFunction() attatchTestAsm = Memory.alloc(Process.pageSize) console.log('----------------address',attatchTestAsm) attatchTestEbp2C = Memory.alloc(0xC) attatchGlobalEDI = moduleBaseAddress.add(0x222f38c).readPointer() .add(0x938).add(0x438).readPointer() attatchGlobalEDIB88 = attatchGlobalEDI.add(0xB88).readPointer() attatchTestEBX = Memory.alloc(0x4) attatchTestEBX.writePointer(attatchGlobalEDI) console.log('----------------attatchGlobalEDI',attatchGlobalEDI) console.log('----------------attatchGlobalEDIB88',attatchGlobalEDIB88) attatchFirstECX = Memory.alloc(0x28) //const attatchSecondEcx = Memory.alloc(0x14) const contactIdLength = contactId.length * 2 + 2//edx const contractIdActLength = contactId.length gattatchReceiveIdPtr=Memory.alloc(contactId.length * 2 + 2) gattatchReceiveIdPtr.writeUtf16String(contactId) gattatchReceiveId=Memory.alloc(0x14) gattatchReceiveId.writePointer(ptr(gattatchReceiveIdPtr)).add(0x04) .writeU32(contactId.length*2).add(0x04) .writeU32(contactId.length*2).add(0x08) //console.log('----------------attatchGlobalEDIB88',attatchGlobalEDIB88) //return /*console.log(hexdump(attatchTestEBX, { offset: 0, length: 0x40, header: true, ansi: true })) return*/ gattatchFilePtr=Memory.alloc(filePath.length * 2 + 2) gattatchFilePtr.writeUtf16String(filePath) gattatchFile=Memory.alloc(0x14) gattatchFile.writePointer(ptr(gattatchFilePtr)).add(0x04) .writeU32(filePath.length*2).add(0x04) .writeU32(filePath.length*2).add(0x08) const attatchLastECX = moduleBaseAddress.add(0x222f170).toInt32() attatchEAX3B0Buf = Memory.alloc(0x3B0) g_tempEcx = Memory.alloc(0x4) //g_tempEcx1 = Memory.alloc(0x4) attatchESIbuf = Memory.alloc(0x100) attatchESIbuf.add(0x0).writeU32(3) attatchESIbuf.add(0x4).writePointer(gattatchFilePtr) attatchESIbuf.add(0x8).writeU32(filePath.length*2) attatchESIbuf.add(0xc).writeU32(filePath.length*2) Memory.patchCode(attatchTestAsm, Process.pageSize, code => { var cw = new X86Writer(code, { pc: attatchTestAsm }) cw.putPushfx() cw.putPushax() //cw.putMovRegU32('edi',attatchGlobalEDI) cw.putMovRegAddress('esi',attatchESIbuf) cw.putMovRegAddress('ecx', attatchFirstECX.add(0x14)) cw.putMovRegAddress('eax', gattatchFile) cw.putPushReg('eax') cw.putCallAddress(moduleBaseAddress.add(0x701DC0)) cw.putMovRegAddress('ecx', attatchFirstECX) cw.putMovRegU32('eax', contactIdLength) cw.putPushReg('eax') cw.putPushU32(0) cw.putCallAddress(moduleBaseAddress.add(0x1a11c83)) cw.putAddRegImm('esp', 0x8) cw.putMovRegReg('edx','eax') cw.putMovNearPtrReg(attatchFirstECX,'edx') cw.putMovRegU32('edi', contactIdLength) cw.putPushReg('edi') cw.putMovRegAddress('eax', gattatchReceiveIdPtr)//ebp-58 cw.putPushReg('eax') cw.putMovRegNearPtr('eax',attatchFirstECX) cw.putPushReg('eax') cw.putCallAddress(moduleBaseAddress.add(0x1a1047a)) cw.putAddRegImm('esp', 0x0c) //cw.putMovRegNearPtr('ecx',attatchFirstECX) //cw.putAddRegImm('esp', 0x0c) //cw.putMovRegU32('edx', 0) //cw.putMovRegRegPtr('eax', 'ecx') //cw.putMovNearPtrReg(attatchFirstECX.add(0x04),'edi') cw.putMovRegU32('edi',contactId.length * 2) cw.putMovRegU32('ecx', attatchLastECX) cw.putMovRegAddress('eax', attatchEAX3B0Buf) cw.putPushReg('eax') cw.putCallAddress(moduleBaseAddress.add(0x392260)) cw.putMovRegAddress('ecx', attatchEAX3B0Buf) cw.putCallAddress(moduleBaseAddress.add(0x94200)) cw.putPopax() cw.putPopfx() cw.putRet() cw.flush() }) const nativeativeFunction = new NativeFunction(ptr(attatchTestAsm), 'void', []) nativeativeFunction() }) // 001 const getTestInfoFunction = ((addr) => { const nativeativeFunction = new NativeFunction(ptr(addr), 'void', []) nativeativeFunction() //00CFE484 /*MemoryAccessMonitor.enable({base:ptr(addr),size:0x01}, { onAccess(details){ console.log('============') console.log(details.operation) console.log(details.from) console.log(details.address) console.log('============') } })*/ }) // 002get global data const isLoggedInFunction = (() => { loggedIn = moduleBaseAddress.add(offset.is_logged_in_offset).readU32() return !!loggedIn }) // 003get myself info const getBaseNodeAddress = (() => { return moduleBaseAddress.add(offset.node_offset).readPointer() }) // 004 const getHeaderNodeAddress = (() => { const baseAddress = getBaseNodeAddress() //console.log('baseAddress',baseAddress) if (baseAddress.isNull()) { return baseAddress } //console.log('HeaderNodeAddress',baseAddress.add(offset.handle_offset).readPointer()) return baseAddress.add(offset.handle_offset).readPointer() }) // 005 const getChatroomNodeAddress = (() => { const baseAddress= moduleBaseAddress.add(0x222f3fc).readPointer() if (baseAddress.isNull()) { return baseAddress } return baseAddress.add(offset.chatroom_node_offset).readPointer() }) // 006 const getMyselfInfoFunction = (() => { let ptr = 0 let wx_code = '' let wx_id = '' let wx_name = '' let head_img_url = '' wx_id = readString(moduleBaseAddress.add(offset.wxid_offset)) wx_code = wx_id wx_name = readString(moduleBaseAddress.add(offset.nickname_offset)) head_img_url = readString(moduleBaseAddress.add(offset.head_img_url_offset)) const myself = { id: wx_id, code: wx_code, name: wx_name, head_img_url: head_img_url, }; return JSON.stringify(myself) }) // 007 缺失,请标注已废弃或者其他原因 const getMyselfIdFunction = (() => { let wx_id = readString(moduleBaseAddress.add(offset.wxid_offset)) return wx_id }) // 008chatroom member const chatroomRecurse = ((node) => { const chatroomNodeAddress = getChatroomNodeAddress() if (chatroomNodeAddress.isNull()) { return } if (node.equals(chatroomNodeAddress)) { return } for (const item in chatroomNodeList) { if (node.equals(chatroomNodeList[item])) { return } } chatroomNodeList.push(node) const roomid = readWideString(node.add(0x10)) const len = node.add(0x50).readU32() // //const memberJson={} if (len > 4) {// const memberStr = readString(node.add(0x40)) if (memberStr.length > 0) { const memberList = memberStr.split(/[\\^][G]/) const memberJson = { roomid: roomid, roomMember: memberList } chatroomMemberList.push(memberJson) } } const leftNode = node.add(0x0).readPointer() const centerNode = node.add(0x04).readPointer() const rightNode = node.add(0x08).readPointer() chatroomRecurse(leftNode) chatroomRecurse(centerNode) chatroomRecurse(rightNode) const allChatroomMemberJson = chatroomMemberList return allChatroomMemberJson }) // std::string // const str = readStringPtr(ptr).readUtf8String() const readStringPtr = (address) => { const addr = ptr(address) const size = addr.add(16).readU32() const capacity = addr.add(20).readU32() addr.ptr = addr addr.size = size addr.capacity = capacity if (capacity > 15 && !addr.readPointer().isNull()) { addr.ptr = addr.readPointer() } addr.ptr._readCString = addr.ptr.readCString addr.ptr._readAnsiString = addr.ptr.readAnsiString addr.ptr._readUtf8String = addr.ptr.readUtf8String addr.readCString = () => { return addr.size ? addr.ptr._readCString(addr.size) : '' } addr.readAnsiString = () => { return addr.size ? addr.ptr._readAnsiString(addr.size) : '' } addr.readUtf8String = () => { return addr.size ? addr.ptr._readUtf8String(addr.size) : '' } // console.log('readStringPtr() address:',address,' -> str ptr:', addr.ptr, 'size:', addr.size, 'capacity:', addr.capacity) // console.log('readStringPtr() str:' , addr.readUtf8String()) // console.log('readStringPtr() address:', addr,'dump:', addr.readByteArray(24)) return addr } // std::wstring // const wstr = readWStringPtr(ptr).readUtf16String() const readWStringPtr = (address) => { const addr = ptr(address) const size = addr.add(4).readU32() const capacity = addr.add(8).readU32() addr.ptr = addr.readPointer() addr.size = size addr.capacity = capacity addr.ptr._readUtf16String = addr.ptr.readUtf16String addr.readUtf16String = () => { return addr.size ? addr.ptr._readUtf16String(addr.size * 2) : '' } // console.log('readWStringPtr() address:',address,' -> ptr:', addr.ptr, 'size:', addr.size, 'capacity:', addr.capacity) // console.log('readWStringPtr() str:' , `"${addr.readUtf16String()}"`,'\n',addr.ptr.readByteArray(addr.size*2+2),'\n') // console.log('readWStringPtr() address:', addr,'dump:', addr.readByteArray(16),'\n') return addr } const readString = (address) => { return readStringPtr(address).readUtf8String() } const readWideString = (address) => { return readWStringPtr(address).readUtf16String() } const recurseNew = ((node) => { const headerNodeAddress = getHeaderNodeAddress() if (headerNodeAddress.isNull()) { return } if (node.equals(headerNodeAddress)) { return } for (const item in nodeList) { if (node.equals(nodeList[item])) { return } } nodeList.push(node) const id = readString(node.add(0x8)) //wxid, format relates to registration method const wxid = readWideString(node.add(0x30)) //console.log('-----------',wxid) //custom id, if not set return null, and use wxid which should be custom id //const wx_code = readWideString(node.add(0x4c)) || readWideString(node.add(0x38)) //custom Nickname const name = readWideString(node.add(0x8c)) //alias aka 'remark' in wechat //const alias = readWideString(node.add(0x80)) //avatarUrl //const avatar = readWideString(node.add(0x138)) //const avatar = Memory.readUtf16String(node.add(0x138).readPointer()) //contact gender //const gender = node.add(0x18C).readU32() const contactJson = { id1:id, id: wxid, name:name, /*code: wx_code, name: name, alias: alias, avatarUrl: avatar, gender: gender,*/ } contactList.push(contactJson) const leftNode = node.add(0x0).readPointer() const centerNode = node.add(0x04).readPointer() //const rightNode = node.add(0x08).readPointer() recurseNew(leftNode) recurseNew(centerNode) //recurse(rightNode) const allContactJson = contactList return allContactJson }) //contact const recurse = ((node) => { const headerNodeAddress = getHeaderNodeAddress() if (headerNodeAddress.isNull()) { return } if (node.equals(headerNodeAddress)) { return } for (const item in nodeList) { if (node.equals(nodeList[item])) { return } } nodeList.push(node) //wxid, format relates to registration method const wxid = readWideString(node.add(0x38)) //custom id, if not set return null, and use wxid which should be custom id const wx_code = readWideString(node.add(0x4c)) || readWideString(node.add(0x38)) //custom Nickname const name = readWideString(node.add(0x94)) //alias aka 'remark' in wechat const alias = readWideString(node.add(0x80)) //avatarUrl const avatar = readWideString(node.add(0x138)) //const avatar = Memory.readUtf16String(node.add(0x138).readPointer()) //contact gender const gender = node.add(0x18C).readU32() const contactJson = { id: wxid, code: wx_code, name: name, alias: alias, avatarUrl: avatar, gender: gender, } contactList.push(contactJson) const leftNode = node.add(0x0).readPointer() const centerNode = node.add(0x04).readPointer() const rightNode = node.add(0x08).readPointer() recurse(leftNode) recurse(centerNode) recurse(rightNode) const allContactJson = contactList return allContactJson }) // 009 const getChatroomMemberInfoFunction = (() => { const chatroomNodeAddress = getChatroomNodeAddress() if (chatroomNodeAddress.isNull()) { return '[]' } const node = chatroomNodeAddress.add(0x0).readPointer() const ret = chatroomRecurse(node) const cloneRet = JSON.stringify(ret) chatroomNodeList.length = 0//empty chatroomMemberList.length = 0 //empty return cloneRet }) // 010 const getWechatVersionFunction = (() => { if (currentVersion) { return currentVersion } const pattern = '55 8B ?? 83 ?? ?? A1 ?? ?? ?? ?? 83 ?? ?? 85 ?? 7F ?? 8D ?? ?? E8 ?? ?? ?? ?? 84 ?? 74 ?? 8B ?? ?? ?? 85 ?? 75 ?? E8 ?? ?? ?? ?? 0F ?? ?? 0D ?? ?? ?? ?? A3 ?? ?? ?? ?? A3 ?? ?? ?? ?? 8B ?? 5D C3' const results = Memory.scanSync(moduleLoad.base, moduleLoad.size, pattern) if (results.length == 0) { return 0 } const addr = results[0].address const ret = addr.add(0x07).readPointer() const ver = ret.add(0x0).readU32() currentVersion = ver return ver }) // 011 const getWechatVersionStringFunction = ((ver = getWechatVersionFunction()) => { if (!ver) { return '0.0.0.0' } const vers = [] vers.push((ver >> 24) & 255 - 0x60) vers.push((ver >> 16) & 255) vers.push((ver >> 8) & 255) vers.push(ver & 255) return vers.join('.') }) // 012 const checkSupportedFunction = (() => { const ver = getWechatVersionFunction() return ver == availableVersion }) // 013 const isSupported = checkSupportedFunction() if (!isSupported) { throw new Error(`Wechat version not supported. \nWechat version: ${getWechatVersionStringFunction()}, supported version: ${getWechatVersionStringFunction(availableVersion)}`) } // 014 const getContactNativeFunction = (() => { const headerNodeAddress = getHeaderNodeAddress() //console.log('headerNodeAddress',headerNodeAddress) if (headerNodeAddress.isNull()) { return '[]' } const node = headerNodeAddress.add(0x0).readPointer() const ret = recurseNew(node) //console.log(ret) console.log('getContactNativeFunction:',ret.length) /*for (let item of ret){ console.log(JSON.stringify(item)) }*/ //console.log(ret.contact) const cloneRet = JSON.stringify(ret) nodeList.length = 0 contactList.length = 0 return cloneRet }) // 015 const hookLogoutEventCallback = (() => { const nativeCallback = new NativeCallback(() => { }, 'void', ['int32']) const nativeativeFunction = new NativeFunction(nativeCallback, 'void', ['int32']) Interceptor.attach(moduleBaseAddress.add(offset.hook_on_logout_offset), { onEnter: function (args) { const bySrv = args[0].toInt32() setImmediate(() => nativeativeFunction(bySrv)) } }) return nativeCallback })() // 016 const hookLoginEventCallback = (() => { const nativeCallback = new NativeCallback(() => { }, 'void', []) const nativeativeFunction = new NativeFunction(nativeCallback, 'void', []) Interceptor.attach(moduleBaseAddress.add(offset.hook_on_login_offset), { onLeave: function (retval) { isLoggedInFunction() setImmediate(() => nativeativeFunction()) return retval } }) setTimeout(() => { if (isLoggedInFunction()) { setImmediate(() => nativeativeFunction()) } }, 500); return nativeCallback })() // 017 const checkQRLoginNativeCallback = (() => { const nativeCallback = new NativeCallback(() => { }, 'void', ['int32', 'pointer', 'pointer', 'pointer', 'pointer', 'pointer', 'int32', 'pointer']) const nativeativeFunction = new NativeFunction(nativeCallback, 'void', ['int32', 'pointer', 'pointer', 'pointer', 'pointer', 'pointer', 'int32', 'pointer']) // const json = { // status, // uuid, // wxid, // avatarUrl, // nickname, // phoneType, // phoneClientVer, // pairWaitTip, // } const callback = { onLeave: function (retval) { const json = getQrcodeLoginData() if (json.status == 0) { // 当状态为 0 时,即未扫码。而其他状态会触发另一个方法,拥有更多数据。 ret(json) } return retval }, } const ret = (json) => { const arr = [ json.status || 0, Memory.allocUtf8String(json.uuid ? `http://weixin.qq.com/x/${json.uuid}` : ''), Memory.allocUtf8String(json.wxid || ''), Memory.allocUtf8String(json.avatarUrl || ''), Memory.allocUtf8String(json.nickname || ''), Memory.allocUtf8String(json.phoneType || ''), json.phoneClientVer || 0, Memory.allocUtf8String(json.pairWaitTip || ''), ] setImmediate(() => nativeativeFunction(...arr)) } Interceptor.attach(moduleBaseAddress.add(offset.hook_get_login_qr_offset), callback) Interceptor.attach(moduleBaseAddress.add(offset.hook_check_login_qr_offset), callback) Interceptor.attach(moduleBaseAddress.add(offset.hook_save_login_qr_info_offset), { onEnter: function () { const qrNotify = this.context['ebp'].sub(72) const uuid = readString(qrNotify.add(4).readPointer()) const wxid = readString(qrNotify.add(8).readPointer()) const status = qrNotify.add(16).readUInt() const avatarUrl = readString(qrNotify.add(24).readPointer()) const nickname = readString(qrNotify.add(28).readPointer()) const pairWaitTip = readString(qrNotify.add(32).readPointer()) const phoneClientVer = qrNotify.add(40).readUInt() const phoneType = readString(qrNotify.add(44).readPointer()) const json = { status, uuid, wxid, avatarUrl, nickname, phoneType, phoneClientVer, pairWaitTip, } ret(json) }, onLeave: function (retval) { return retval }, }) if (!isLoggedInFunction()) { setTimeout(() => { const json = getQrcodeLoginData() ret(json) }, 100); } return nativeCallback })() // 018 const getQrcodeLoginData = () => { const getQRCodeLoginMgr = new NativeFunction(moduleBaseAddress.add(offset.get_qr_login_data_offset), 'pointer', []) const qlMgr = getQRCodeLoginMgr() const json = { status: 0, uuid: '', wxid: '', avatarUrl: '', } if (!qlMgr.isNull()) { json.uuid = readString(qlMgr.add(8)) json.status = qlMgr.add(40).readUInt() json.wxid = readString(qlMgr.add(44)) json.avatarUrl = readString(qlMgr.add(92)) } return json } /** * 20220504 writelog * 7A566D72 | FFB5 ECFEFFFF | push dword ptr ss:[ebp-114] | 【3.6.0.18】写日志,这个里面就是日志内容 7A566D78 | FFB5 E8FEFFFF | push dword ptr ss:[ebp-118] | */ /*const writeLogNativeCallback = (() => { const nativeCallback = new NativeCallback(() => { }, 'void', []) const nativeCallFunction = new NativeFunction(nativeCallback, 'void', []) Interceptor.attach( moduleBaseAddress.add(0x1576D7E), { onEnter() { const addr = this.context.ebp.sub(0x114)//0xc30-0x08 console.log('-------',addr) } }) return nativeCallback })()*/ /** * @Hook: recvMsg -> recvMsgNativeCallback */ // 019 const recvMsgNativeCallback = (() => { const nativeCallback = new NativeCallback(() => { }, 'void', ['int32', 'pointer', 'pointer', 'pointer', 'pointer', 'int32']) const nativeativeFunction = new NativeFunction(nativeCallback, 'void', ['int32', 'pointer', 'pointer', 'pointer', 'pointer', 'int32']) Interceptor.attach( moduleBaseAddress.add(offset.hook_point), { onEnter() { const addr = this.context.eax//0xc30-0x08 const msgType = addr.add(0x38).readU32() const isMyMsg = addr.add(0x3C).readU32()//add isMyMsg if (msgType > 0) { const talkerIdPtr = addr.add(0x48).readPointer() //console.log('txt msg',talkerIdPtr.readUtf16String()) const talkerIdLen = addr.add(0x48 + 0x04).readU32() * 2 + 2 const myTalkerIdPtr = Memory.alloc(talkerIdLen) Memory.copy(myTalkerIdPtr, talkerIdPtr, talkerIdLen) let contentPtr = null let contentLen = 0 let myContentPtr = null if (msgType == 3) {// pic path let thumbPtr = addr.add(0x198).readPointer(); let hdPtr = addr.add(0x1ac).readPointer(); let thumbPath = thumbPtr.readUtf16String(); let hdPath = hdPtr.readUtf16String(); let picData = [ thumbPath,// PUPPET.types.Image.Unknown thumbPath,// PUPPET.types.Image.Thumbnail hdPath,// PUPPET.types.Image.HD hdPath// PUPPET.types.Image.Artwork ] let content = JSON.stringify(picData); myContentPtr = Memory.allocUtf16String(content); } else { contentPtr = addr.add(0x70).readPointer() contentLen = addr.add(0x70 + 0x04).readU32() * 2 + 2 myContentPtr = Memory.alloc(contentLen) Memory.copy(myContentPtr, contentPtr, contentLen) } // console.log('----------------------------------------') // console.log(msgType) // console.log(contentPtr.readUtf16String()) // console.log('----------------------------------------') const groupMsgAddr = addr.add(0x170).readU32() //* 2 + 2 let myGroupMsgSenderIdPtr = null if (groupMsgAddr == 0) {//weChatPublic is zero,type is 49 myGroupMsgSenderIdPtr = Memory.alloc(0x10) myGroupMsgSenderIdPtr.writeUtf16String("null") } else { const groupMsgSenderIdPtr = addr.add(0x170).readPointer() const groupMsgSenderIdLen = addr.add(0x170 + 0x04).readU32() * 2 + 2 myGroupMsgSenderIdPtr = Memory.alloc(groupMsgSenderIdLen) Memory.copy(myGroupMsgSenderIdPtr, groupMsgSenderIdPtr, groupMsgSenderIdLen) } const xmlNullPtr = addr.add(0x1ec).readU32() let myXmlContentPtr = null if (xmlNullPtr == 0) { myXmlContentPtr = Memory.alloc(0x10) myXmlContentPtr.writeUtf16String("null") } else { const xmlContentPtr = addr.add(0x1ec).readPointer() const xmlContentLen = addr.add(0x1ec + 0x04).readU32() * 2 + 2 myXmlContentPtr = Memory.alloc(xmlContentLen) Memory.copy(myXmlContentPtr, xmlContentPtr, xmlContentLen) } setImmediate(() => nativeativeFunction(msgType, myTalkerIdPtr, myContentPtr, myGroupMsgSenderIdPtr, myXmlContentPtr, isMyMsg)) } } }) return nativeCallback })() let msgStruct = null let msgstrPtr = null const initmsgStruct = ((str) => { msgstrPtr = Memory.alloc(str.length * 2 + 1) msgstrPtr.writeUtf16String(str) msgStruct = Memory.alloc(0x14) // returns a NativePointer msgStruct .writePointer(msgstrPtr).add(0x04) .writeU32(str.length * 2).add(0x04) .writeU32(str.length * 2).add(0x04) .writeU32(0).add(0x04) .writeU32(0) return msgStruct }) let retidNullStruct = null let retidNullPtr = null const initNullIdStruct = ((str) => { retidNullPtr = Memory.alloc(str.length * 2 + 1) retidNullPtr.writeUtf16String(str) retidNullStruct = Memory.alloc(0x14) // returns a NativePointer retidNullStruct .writePointer(retidNullPtr).add(0x04) .writeU32(str.length * 2).add(0x04) .writeU32(str.length * 2).add(0x04) .writeU32(0).add(0x04) .writeU32(0) return retidNullStruct }) let retidStruct = null let retidPtr = null const initidStruct = ((str) => { retidPtr = Memory.alloc(str.length * 2 + 1) retidPtr.writeUtf16String(str) retidStruct = Memory.alloc(0x14) // returns a NativePointer retidStruct .writePointer(retidPtr).add(0x04) .writeU32(str.length * 2).add(0x04) .writeU32(str.length * 2).add(0x04) .writeU32(0).add(0x04) .writeU32(0) return retidStruct }) let retPtr = null let retStruct = null const initStruct = ((str) => { retPtr = Memory.alloc(str.length * 2 + 1) retPtr.writeUtf16String(str) retStruct = Memory.alloc(0x14) // returns a NativePointer retStruct .writePointer(retPtr).add(0x04) .writeU32(str.length * 2).add(0x04) .writeU32(str.length * 2).add(0x04) .writeU32(0).add(0x04) .writeU32(0) return retStruct }) /** * at msg structure */ let atStruct = null const initAtMsgStruct = ((wxidStruct) => { atStruct = Memory.alloc(0x10) atStruct.writePointer(wxidStruct).add(0x04) .writeU32(wxidStruct.toInt32() + 0x14).add(0x04)//0x14 = sizeof(wxid structure) .writeU32(wxidStruct.toInt32() + 0x14).add(0x04) .writeU32(0) return atStruct }) let nickRoomIdV6 = null let nullEdiWxidStructV6 = null let nickMemberIdStructV6 = null let memberNickBuffAsmV6 = null let nickResultEdiV6 = null const getChatroomMemberNickInfoV1Function=((memberId, roomId)=>{ nickRoomIdV6 = initidStruct(roomId) nullEdiWxidStructV6 = initNullIdStruct('') nickMemberIdStructV6 = initStruct(memberId) memberNickBuffAsmV6 = Memory.alloc(Process.pageSize) console.log('-----',memberNickBuffAsmV6) const tmp = (moduleBaseAddress.add( offset.chatroom_member_nick_esi_offset_v6 )).readU32() console.log('=======tmp',tmp) Memory.patchCode(memberNickBuffAsmV6, Process.pageSize, code => { var cw = new X86Writer(code, { pc: memberNickBuffAsmV6 }) cw.putPushfx(); cw.putPushax(); cw.putMovRegAddress('edi', nullEdiWxidStructV6) cw.putMovRegAddress('eax', nickMemberIdStructV6) cw.putMovRegAddress('ebx', nickRoomIdV6) cw.putMovRegAddress('esi', ptr(tmp)) cw.putPushReg('edi') cw.putPushReg('eax') cw.putPushReg('ebx') cw.putMovRegAddress('ecx', ptr(tmp)) cw.putCallAddress(moduleBaseAddress.add( offset.chatroom_member_nick_call_offset_v6 )) //cw.putMovNearPtrReg(nickResultEdiV6, 'edi') cw.putPopax() cw.putPopfx() cw.putRet() cw.flush() }) const nativeativeFunction = new NativeFunction(ptr(memberNickBuffAsmV6), 'void', []) nativeativeFunction() console.log('---------nullEdiWxidStructV6',nullEdiWxidStructV6) const nickha = readWideString(nullEdiWxidStructV6) console.log('-----------------') console.log(nickha) console.log('-----------------') return readWideString(nullEdiWxidStructV6) }) //get nick from chatroom let nickRoomId = null let nickMemberId = null let nickStructPtr = null let nickBuff = null let memberNickBuffAsm = null let nickRetAddr = null // 020 const getChatroomMemberNickInfoFunction = ((memberId, roomId) => { nickBuff = Memory.alloc(0x7e4) nickRetAddr = Memory.alloc(0x04) memberNickBuffAsm = Memory.alloc(Process.pageSize) nickRoomId = initidStruct(roomId) nickMemberId = initStruct(memberId) nickStructPtr = initmsgStruct('') Memory.patchCode(memberNickBuffAsm, Process.pageSize, code => { var cw = new X86Writer(code, { pc: memberNickBuffAsm }) cw.putPushfx(); cw.putPushax(); /*cw.putMovRegAddress('ebx', nickStructPtr) cw.putMovRegAddress('esi', nickMemberId) cw.putMovRegAddress('edi', nickRoomId) cw.putMovRegAddress('ecx', nickBuff) cw.putCallAddress(moduleBaseAddress.add( offset.chatroom_member_nick_call_offset1 )) cw.putMovRegAddress('eax', nickBuff) cw.putPushReg('eax') cw.putPushReg('esi') cw.putCallAddress(moduleBaseAddress.add( offset.chatroom_member_nick_call_offset2 )) cw.putMovRegReg('ecx', 'eax') cw.putCallAddress(moduleBaseAddress.add( offset.chatroom_member_nick_call_offset3 )) cw.putPushU32(1) cw.putPushReg('ebx') cw.putMovRegReg('edx', 'edi') cw.putMovRegAddress('ecx', nickBuff) cw.putCallAddress(moduleBaseAddress.add( offset.chatroom_member_nick_call_offset4 )) cw.putAddRegImm('esp', 0x08) cw.putMovNearPtrReg(nickRetAddr, 'ebx')*/ cw.putMovRegAddress('edi', nickRoomId) cw.putMovRegAddress('eax', nickBuff) cw.putMovRegReg('edx', 'edi') cw.putPushReg('eax') cw.putMovRegAddress('ecx', nickMemberId) cw.putCallAddress(moduleBaseAddress.add(0x404500)) cw.putAddRegImm('esp', 0x04) //cw.putMovNearPtrReg(nickRetAddr, 'ebx') //lea eax, buf cw.putPopax() cw.putPopfx() cw.putRet() cw.flush() }) const nativeativeFunction = new NativeFunction(ptr(memberNickBuffAsm), 'void', []) nativeativeFunction() const nickname = readWideString(nickBuff); // console.log('--------nickname',nickname) return readWideString(nickBuff); //return readWideString(nickRetAddr.readPointer()) }) /** * send attatch */ let attatchWxid = null let attatchPath = null let attatchPathPtr = null let attatchAsm = null let attatchBuf = null let attatchReceiveIdPtr=null let attatchReceiveId = null let attatchSendId = null let attatchSendIdPtr = null /* let attatchEbp2C = null let attatchEDIPtr = null let attatchEDIU32 = null let attatchECX = null let attatchEbp210 = null let attatchEbpAc = null*/ let attatchEbp11E8 = null let attatchEbpCC = null let attatchEbp368 = null let attatchEAX = null let sFileName = null let fileNamePtr = null let attatchEbp84 = null let attatchECX = null /** * param {78EDBC86 | 8B80 38040000 | mov eax,dword ptr ds:[eax+438] | 78EDBC8C | 8BB0 800B0000 | mov esi,dword ptr ds:[eax+B80] |} sendWxid */ // 021 const sendAttatchMsgNativeFunction = ((contactId, senderId,path,filename,size) => { attatchAsm = Memory.alloc(Process.pageSize) console.log('--------------address',attatchAsm) fileNamePtr=Memory.alloc(filename.length * 2 + 2) fileNamePtr.writeUtf16String(filename) sFileName=Memory.alloc(0x14) sFileName.writePointer(ptr(fileNamePtr)).add(0x04) .writeU32(fileNamePtr.length*2).add(0x04) .writeU32(fileNamePtr.length*2).add(0x08) //const fileSize = size.toInt32() attatchReceiveIdPtr=Memory.alloc(contactId.length * 2 + 2) attatchReceiveIdPtr.writeUtf16String(contactId) attatchReceiveId=Memory.alloc(0x14) attatchReceiveId.writePointer(ptr(attatchReceiveIdPtr)).add(0x04) .writeU32(contactId.length*2).add(0x04) .writeU32(contactId.length*2).add(0x08) attatchSendIdPtr=Memory.alloc(senderId.length * 2 + 2) attatchSendIdPtr.writeUtf16String(senderId) attatchSendId=Memory.alloc(0x14) attatchSendId.writePointer(ptr(attatchSendIdPtr)).add(0x04) .writeU32(senderId.length*2).add(0x04) .writeU32(senderId.length*2).add(0x08) attatchPathPtr = Memory.alloc(path.length * 2 + 2) attatchPathPtr.writeUtf16String(path) attatchPath = Memory.alloc(0x28) attatchPath.writePointer(attatchPathPtr).add(0x04) .writeU32(path.length * 2).add(0x04) .writeU32(path.length * 2).add(0x04) attatchEbp11E8 = Memory.alloc(0xBE4) attatchEbpCC = Memory.alloc(0x14) attatchEbp368 = Memory.alloc(0x290) attatchEbp84 = Memory.alloc(0x18) attatchEAX = Memory.alloc(0x18) attatchECX = moduleBaseAddress.add(0x222f178).toInt32() //console.log('basename',path.basename(path)) //return /** * -------------buffer------------------------------- */ Memory.patchCode(attatchAsm, Process.pageSize, code => { var cw = new X86Writer(code, { pc: attatchAsm }) cw.putPushfx() cw.putPushax() cw.putMovRegAddress('ecx', attatchEbp11E8) cw.putCallAddress(moduleBaseAddress.add(0xE1590)) cw.putPushU32(-1) cw.putPushU32(moduleBaseAddress.add(0x1E1B3C0).toInt32()) cw.putMovRegAddress('ecx', attatchEbp11E8.add(0x4))//11e4 cw.putCallAddress(moduleBaseAddress.add(0x702410))//write appid // cw.putCallAddress(moduleBaseAddress.add(0x702410))//write appid /** * 78482B8D | 6A FF | push FFFFFFFF | 78482B8F | 68 B895E979 | push wechatwin.79E995B8 | 79E995B8:L"0" 78482B94 | 8D8D 48EEFFFF | lea ecx,dword ptr ss:[ebp-11B8] | 78482B9A | E8 71F83600 | call wechatwin.787F2410 | 此处继续写ebp-11b8 */ cw.putPushU32(-1) cw.putPushU32(moduleBaseAddress.add(0x1DA95B8).toInt32()) cw.putMovRegAddress('ecx', attatchEbp11E8.add(0x30))//11B8 cw.putCallAddress(moduleBaseAddress.add(0x702410)) cw.putMovRegU32('eax',0x6) cw.putMovNearPtrReg(attatchEbp11E8.add(0x80), 'eax')//1168 cw.putMovRegU32('eax',size)//file size cw.putMovNearPtrReg(attatchEbp11E8.add(0x108), 'eax')//10e0 cw.putMovRegAddress('eax', sFileName) cw.putPushReg('eax') cw.putMovRegAddress('ecx', attatchEbp11E8.add(0x44))//11a4=0x11e8-0x160 cw.putCallAddress(moduleBaseAddress.add(0x702980))//write filename cw.putMovRegAddress('eax', attatchSendId) cw.putPushReg('eax') cw.putMovRegAddress('ecx', attatchEbp11E8.add(0x160))//1088=0x11e8-0x160 cw.putCallAddress(moduleBaseAddress.add(0x702980)) cw.putMovRegAddress('eax', attatchEbpCC) cw.putPushReg('eax') cw.putMovRegAddress('ecx', attatchEbp11E8) cw.putCallAddress(moduleBaseAddress.add(0x617C30)) cw.putMovRegAddress('ecx', attatchEbp368) cw.putCallAddress(moduleBaseAddress.add(0x954F0)) cw.putPushU32(-1) cw.putPushU32((moduleBaseAddress.add(0x1D8F248)).toInt32()) cw.putMovRegAddress('ecx', attatchEbp84) cw.putCallAddress(moduleBaseAddress.add(0x701CD0)) cw.putMovRegAddress('ecx', attatchPath) cw.putPushU32(0x6) cw.putMovRegAddress('edx', attatchEbp11E8.add(0x160))//1088 //cw.putMovRegAddress('eax',attatchEAX) cw.putPushReg('ecx') cw.putPushReg('eax') cw.putMovRegAddress('eax',attatchEbpCC) cw.putPushReg('eax') cw.putMovRegAddress('eax',attatchReceiveId) cw.putPushReg('eax') cw.putMovRegAddress('ecx', attatchEbp368) cw.putCallAddress(moduleBaseAddress.add(0x391F80)) cw.putAddRegImm('esp', 0x14) cw.putPushU32(moduleBaseAddress.add(0x223EC34).toInt32()) cw.putPushU32(moduleBaseAddress.add(0x223EC34).toInt32()) //cw.putMovRegU32('edx',0xAD0001) 两行代码都可以 cw.putAddRegImm('edx', 0x1) cw.putMovRegAddress('ecx', attatchEbp368) cw.putCallAddress(moduleBaseAddress.add(0x392150)) cw.putAddRegImm('esp', 0x8) //cw.putMovRegAddress('ecx', attatchEbp368) //cw.putCallAddress(moduleBaseAddress.add(0x63B4F0)) // 7B53F178 //cw.putMovRegU32('ecx', attatchEbpCC.add(0x3c).toInt32())//ebp-90 //cw.putMovNearPtrReg(attatchEbpCC.add(0x64), 'eax')//ebp-68 //cw.putAddRegImm('ecx', 0x8) //cw.putMovRegAddress('eax', attatchEbp368.add(0x64))//ebp-68 //cw.putMovRegU32('ecx',attatchECX) //cw.putPushReg('eax') //cw.putMovRegAddress('eax', attatchEbpCC.add(0x40))//ebp-8c //cw.putPushReg('eax') //cw.putCallAddress(moduleBaseAddress.add(0xC9D30)) //cw.putCallAddress(moduleBaseAddress.add(0x522590)) //78483063 | E8 28F51800 | call wechatwin.78612590 | //78483039 | 8D8D 98FCFFFF | lea ecx,dword ptr ss:[ebp-368] | //7848303F | E8 AC842A00 | call wechatwin.7872B4F0 | //cw.putMovRegAddress('ecx', attatchEbp368) //cw.putCallAddress(moduleBaseAddress.add(0x63B4F0)) // 78F33099 | 8D8D 34FFFFFF | lea ecx,dword ptr ss:[ebp-CC] | //78F3309F | E8 AC0FD0FF | call wechatwin.78C34050 | //cw.putMovRegAddress('ecx',attatchEbpCC) //cw.putCallAddress(moduleBaseAddress.add(0x94050)) /** * 78F3307F | 8B4D AC | mov ecx,dword ptr ss:[ebp-54] | 78F33082 | 8D85 98FCFFFF | lea eax,dword ptr ss:[ebp-368] | 78F33088 | 50 | push eax | 78F33089 | E8 82DACFFF | call wechatwin.78C30B10 | cw.putMovRegAddress('ecx', attatchEbp54) cw.putMovRegAddress('eax', attatchEbp368) cw.putPushReg('eax') cw.putCallAddress(moduleBaseAddress.add(0x90B10))*/ cw.putPopax() cw.putPopfx() cw.putRet() cw.flush() }) const nativeativeFunction = new NativeFunction(ptr(attatchAsm), 'void', []) nativeativeFunction() /*console.log(hexdump(attatchEbp11E8.add(0x80), { offset: 0, length: 0x40, header: true, ansi: true }))*/ //console.log('') /*console.log(hexdump(attatchEbpCC.add(0x160), { offset: 0, length: 0x64, header: true, ansi: true }))*/ //console.log('-------',attatchEbp1C.readPointer()) //console.log('-------',attatchEbp1C.add(0x4).readPointer()) //console.log('-------',attatchEbp1C.add(0x8).readPointer()) }) /*-----------------send pic 3.6.0.18----------------*/ /*------------------send pic --------------------------*/ let buffwxid = null let imagefilepath = null let pathPtr = null let picWxid = null let picWxidPtr = null let picAsm = null let picbuff = null // 022 const sendPicMsgNativeFunction = ((contactId, path) => { picAsm = Memory.alloc(Process.pageSize) buffwxid = Memory.alloc(0x20) picbuff = Memory.alloc(0x3B0) pathPtr = Memory.alloc(path.length * 2 + 1) pathPtr.writeUtf16String(path) imagefilepath = Memory.alloc(0x24) imagefilepath.writePointer(pathPtr).add(0x04) .writeU32(path.length * 2).add(0x04) .writeU32(path.length * 2).add(0x04) picWxidPtr = Memory.alloc(contactId.length * 2 + 1) picWxidPtr.writeUtf16String(contactId) picWxid = Memory.alloc(0x0c) picWxid.writePointer(ptr(picWxidPtr)).add(0x04) .writeU32(contactId.length * 2).add(0x04) .writeU32(contactId.length * 2).add(0x04) /*const ecxValue = (moduleBaseAddress.add( offset.send_picmsg_call_offset0 )).toInt32() */ const test_offset1 = 0x701DC0; Memory.patchCode(picAsm, Process.pageSize, code => { var cw = new X86Writer(code, { pc: picAsm }) cw.putPushfx(); cw.putPushax(); cw.putCallAddress(moduleBaseAddress.add( offset.send_picmsg_call_offset0 )) cw.putMovRegReg('edx', 'eax')//缓存 cw.putSubRegImm('esp', 0x14) cw.putMovRegAddress('eax', buffwxid) cw.putMovRegReg('ecx', 'esp') cw.putMovRegAddress('edi', imagefilepath) cw.putPushReg('eax') cw.putCallAddress(moduleBaseAddress.add( test_offset1 )) cw.putMovRegReg('ecx', 'edx') cw.putMovRegAddress('eax', picWxid) //=lea cw.putMovRegAddress('edi', imagefilepath) cw.putPushReg('edi') cw.putPushReg('eax') cw.putMovRegAddress('eax', picbuff) cw.putPushReg('eax') cw.putMovRegAddress('edi', picWxid)//edi cw.putCallAddress(moduleBaseAddress.add( offset.send_picmsg_call_offset1 )) /*cw.putCallAddress(moduleBaseAddress.add( offset.send_picmsg_call_offset0 )) cw.putMovRegReg('ecx', 'eax') cw.putMovRegAddress('eax', picWxid) cw.putMovRegAddress('edi', imagefilepath) cw.putPushReg('edi') cw.putPushReg('eax') cw.putMovRegAddress('eax', picbuff) cw.putPushReg('eax') cw.putMovRegAddress('edi', picWxid)//edi cw.putCallAddress(moduleBaseAddress.add( offset.send_picmsg_call_offset1 ))-------ok but exception*/ /*3.3.0.115 cw.putSubRegImm('esp', 0x14) cw.putMovRegAddress('eax', buffwxid) cw.putMovRegReg('ecx', 'esp') cw.putPushReg('eax') cw.putCallAddress(moduleBaseAddress.add( offset.send_picmsg_call_offset1 )) cw.putMovRegAddress('ebx', imagefilepath) cw.putPushReg('ebx') cw.putMovRegAddress('eax', picWxid) cw.putPushReg('eax') cw.putMovRegAddress('eax', picbuff) cw.putPushReg('eax') cw.putCallAddress(moduleBaseAddress.add( offset.send_picmsg_call_offset2 )) cw.putMovRegReg('ecx', 'eax') cw.putCallAddress(moduleBaseAddress.add( offset.send_picmsg_call_offset3 ))*/ cw.putPopax() cw.putPopfx() cw.putRet() cw.flush() }) console.log('----------picAsm',picAsm) const nativeativeFunction = new NativeFunction(ptr(picAsm), 'void', []) nativeativeFunction() }) /*------------------send pic -------------------------- let buffwxid = null let imagefilepath = null let pathPtr = null let picWxid = null let picWxidPtr = null let picAsm = null let picbuff = null const sendPicMsgNativeFunction = ((contactId, path) => { picAsm = Memory.alloc(Process.pageSize) buffwxid = Memory.alloc(0x20) picbuff = Memory.alloc(0x378) pathPtr = Memory.alloc(path.length * 2 + 1) pathPtr.writeUtf16String(path) imagefilepath = Memory.alloc(0x24) imagefilepath.writePointer(pathPtr).add(0x04) .writeU32(path.length * 2).add(0x04) .writeU32(path.length * 2).add(0x04) picWxidPtr = Memory.alloc(contactId.length * 2 + 1) picWxidPtr.writeUtf16String(contactId) picWxid = Memory.alloc(0x0c) picWxid.writePointer(ptr(picWxidPtr)).add(0x04) .writeU32(contactId.length * 2).add(0x04) .writeU32(contactId.length * 2).add(0x04) Memory.patchCode(picAsm, Process.pageSize, code => { var cw = new X86Writer(code, { pc: picAsm }) cw.putPushfx(); cw.putPushax(); cw.putSubRegImm('esp', 0x14) cw.putMovRegAddress('eax', buffwxid) cw.putMovRegReg('ecx', 'esp') cw.putPushReg('eax') cw.putCallAddress(moduleBaseAddress.add( offset.send_picmsg_call_offset1 )) cw.putMovRegAddress('ebx', imagefilepath) cw.putPushReg('ebx') cw.putMovRegAddress('eax', picWxid) cw.putPushReg('eax') cw.putMovRegAddress('eax', picbuff) cw.putPushReg('eax') cw.putCallAddress(moduleBaseAddress.add( offset.send_picmsg_call_offset2 )) cw.putMovRegReg('ecx', 'eax') cw.putCallAddress(moduleBaseAddress.add( offset.send_picmsg_call_offset3 )) cw.putPopax() cw.putPopfx() cw.putRet() cw.flush() }) const nativeativeFunction = new NativeFunction(ptr(picAsm), 'void', []) nativeativeFunction() })*/ /** * send at msg */ let asmAtMsg = null let roomid_, msg_, wxid_, atid_ let ecxBuffer // 023 const sendAtMsgNativeFunction = ((roomId, text, contactId) => { asmAtMsg = Memory.alloc(Process.pageSize) ecxBuffer = Memory.alloc(0x3b0) roomid_ = initStruct(roomId) wxid_ = initidStruct(contactId) msg_ = initmsgStruct(text) atid_ = initAtMsgStruct(wxid_) Memory.patchCode(asmAtMsg, Process.pageSize, code => { var cw = new X86Writer(code, { pc: asmAtMsg }) //cw.putMovRegAddress('eax',roomid) cw.putPushfx(); cw.putPushax(); cw.putPushU32(1) // push cw.putMovRegAddress('edi', atid_) cw.putMovRegAddress('ebx', msg_)//msg_ cw.putPushReg('edi') cw.putPushReg('ebx') //cw.putMovRegRegOffsetPtr('edx', 'ebp', 0x10)//at wxid cw.putMovRegAddress('edx', roomid_)//room_id cw.putMovRegAddress('ecx', ecxBuffer) cw.putCallAddress(moduleBaseAddress.add( offset.send_txt_call_offset )) cw.putAddRegImm('esp', 0xc) cw.putPopax() cw.putPopfx() cw.putRet() cw.flush() }) const atMsgNativeFunction = new NativeFunction(ptr(asmAtMsg), 'void', []) atMsgNativeFunction() }) /** * @Call: sendMsg -> agentSendMsg */ // 024 const sendMsgNativeFunction = (() => { //const asmBuffer = Memory.alloc(/*0x5a8*/0x5f0) // magic number from wechat-bot (laozhang) const asmBuffer = Memory.alloc(0x5f0) const asmSendMsg = Memory.alloc(Process.pageSize) Memory.patchCode(asmSendMsg, Process.pageSize, code => { var cw = new X86Writer(code, { pc: asmSendMsg }) cw.putPushReg('ebp') cw.putMovRegReg('ebp', 'esp') cw.putPushax() cw.putPushfx() cw.putPushU32(1) // push cw.putPushU32(0) // push cw.putMovRegRegOffsetPtr('ebx', 'ebp', 0xc) // arg 1 cw.putPushReg('ebx') // push cw.putMovRegRegOffsetPtr('edx', 'ebp', 0x8) // arg 0 cw.putMovRegAddress('ecx', asmBuffer) //0x3b56a0 3.2.1.121 cw.putCallAddress(moduleBaseAddress.add( offset.send_txt_call_offset )) cw.putAddRegImm('esp', 0xc) cw.putPopfx() cw.putPopax() cw.putMovRegRegPtr('esp', 'ebp') // Huan(202107): why use RegRegPtr? (RegRet will fail) cw.putPopReg('ebp') cw.putRet() cw.flush() }) /*let ins = Instruction.parse(asmSendMsg) for (let i=0; i<20; i++) { console.log(ins.address, '\t', ins.mnemonic, '\t', ins.opStr) ins = Instruction.parse(ins.next) }*/ const asmNativeFunction = new NativeFunction(asmSendMsg, 'void', ['pointer', 'pointer']) const sendMsg = ( talkerId, content, ) => { const talkerIdPtr = Memory.alloc(talkerId.length * 2 + 1) const contentPtr = Memory.alloc(content.length * 2 + 1) talkerIdPtr.writeUtf16String(talkerId) contentPtr.writeUtf16String(content) const sizeOfStringStruct = Process.pointerSize * 5 // + 0xd // allocate space for the struct const talkerIdStruct = Memory.alloc(sizeOfStringStruct) // returns a NativePointer const contentStruct = Memory.alloc(sizeOfStringStruct) // returns a NativePointer talkerIdStruct .writePointer(talkerIdPtr).add(0x4) .writeU32(talkerId.length).add(0x4) .writeU32(talkerId.length * 2) contentStruct .writePointer(contentPtr).add(0x4) .writeU32(content.length).add(0x4) .writeU32(content.length * 2) asmNativeFunction(talkerIdStruct, contentStruct) } /** * Best Practices * https://frida.re/docs/best-practices/ * * There is however a pitfall: the value returned by Memory.allocUtf8String() must be kept alive * – it gets freed as soon as the JavaScript value gets garbage-collected. * * This means it needs to be kept alive for at least the duration of the function-call, * and in some cases even longer; the exact semantics depend on how the API was designed. */ const refHolder = { asmBuffer, asmSendMsg, asmNativeFunction, sendMsg, } return (...args) => refHolder.sendMsg(...args) })() // 025 const callLoginQrcodeFunction = ((forceRefresh = false) => { const json = getQrcodeLoginData() if (!forceRefresh && json.uuid) { return } const callAsm = Memory.alloc(Process.pageSize) const loginWnd = moduleBaseAddress.add(offset.get_login_wnd_offset).readPointer() Memory.patchCode(callAsm, Process.pageSize, code => { var cw = new X86Writer(code, { pc: callAsm }) cw.putPushfx(); cw.putPushax(); cw.putMovRegAddress('ecx', loginWnd) cw.putCallAddress(moduleBaseAddress.add(offset.get_qr_login_call_offset)) cw.putPopax() cw.putPopfx() cw.putRet() cw.flush() }) const nativeativeFunction = new NativeFunction(ptr(callAsm), 'void', []) nativeativeFunction() }) // 026 const agentReadyCallback = (() => { const nativeCallback = new NativeCallback(() => { }, 'void', []) const nativeativeFunction = new NativeFunction(nativeCallback, 'void', []) setTimeout(() => { nativeativeFunction() }, 500); return nativeCallback })() // 027 const SendMiniProgramNativeFunction = ((bg_path_str,send_wxid_str,recv_wxid_str,xmlstr) => { console.log("------------------------------------------------------"); var asmCode=Memory.alloc(Process.pageSize); var ECX_buf=Memory.alloc(0x300); var Buf_EAX=Memory.alloc(0x300); var buf_1=Memory.alloc(0x300); var ptr_to_buf_1=Memory.alloc(0x4).writePointer(buf_1); var buf_2=Memory.alloc(0x300); // var bg_path_str="C:/aaaa.jpg"; var bg_path_Ptr=Memory.alloc(bg_path_str.length * 2 + 1) bg_path_Ptr.writeUtf16String(bg_path_str); var bg_path_Struct = Memory.alloc(0x14) // returns a NativePointer bg_path_Struct.writePointer(bg_path_Ptr).add(0x04) .writeU32(bg_path_str.length * 2).add(0x04) .writeU32(bg_path_str.length * 2).add(0x04) .writeU32(0).add(0x04) .writeU32(0); // var send_wxid_str="wxid_4zr616ir6fi122"; var send_wxid_Ptr=Memory.alloc(send_wxid_str.length * 2 + 1) send_wxid_Ptr.writeUtf16String(send_wxid_str); var send_wxid_Struct = Memory.alloc(0x14) // returns a NativePointer send_wxid_Struct.writePointer(send_wxid_Ptr).add(0x04) .writeU32(send_wxid_str.length * 2).add(0x04) .writeU32(send_wxid_str.length * 2).add(0x04) .writeU32(0).add(0x04) .writeU32(0); // var recv_wxid_str="filehelper"; var recv_wxid_Ptr=Memory.alloc(recv_wxid_str.length * 2 + 1) recv_wxid_Ptr.writeUtf16String(recv_wxid_str); var recv_wxid_Struct = Memory.alloc(0x14) // returns a NativePointer recv_wxid_Struct.writePointer(recv_wxid_Ptr).add(0x04) .writeU32(recv_wxid_str.length * 2).add(0x04) .writeU32(recv_wxid_str.length * 2).add(0x04) .writeU32(0).add(0x04) .writeU32(0); // vvar pXml=initidStruct('wxid_4zr616ir6fi1220腾讯出行服务|加油代驾公交view330https://mp.weixin.qq.com/mp/waerrpage?appid=wx65cc950f42e8fff1&amp;type=upgrade&amp;upgradetype=3#wechat_redirecthttp://mmbiz.qpic.cn/mmbiz_png/NM1fK7leWGPaFnMAe95jbg4sZAI3fkEZWHq69CIk6zA00SGARbmsGTbgLnZUXFoRwjROelKicbSp9K34MaZBuuA/640?wx_fmt=png&wxfrom=200腾讯出行服务|加油代驾公交0gh_ad64296dc8bd@appwx65cc950f42e8fff11http://mmbiz.qpic.cn/mmbiz_png/NM1fK7leWGPaFnMAe95jbg4sZAI3fkEZWHq69CIk6zA00SGARbmsGTbgLnZUXFoRwjROelKicbSp9K34MaZBuuA/640?wx_fmt=png&wxfrom=20002_wx65cc950f42e8fff1_875237370_1644979747_11Window wechat'); var pXml=initidStruct(xmlstr) console.log(send_wxid_Struct); console.log(recv_wxid_Struct); console.log(pXml); console.log("okkk"); console.log("------------------------------------------------------"); Memory.patchCode(asmCode, Process.pageSize, code => { var cw = new X86Writer(code, { pc: asmCode }) cw.putPushfx(); cw.putPushax(); cw.putMovRegReg('ecx', 'ecx'); cw.putMovRegAddress('ecx', ECX_buf); cw.putCallAddress(moduleBaseAddress.add(0x69BB0)); //init ecx cw.putPushU32(0x21); cw.putPushNearPtr(ptr_to_buf_1); //ptr cw.putPushU32(bg_path_Struct.toInt32()); cw.putPushU32(pXml.toInt32()); cw.putPushU32(recv_wxid_Struct.toInt32()); cw.putMovRegAddress('edx', send_wxid_Struct); cw.putMovRegAddress('ecx', ECX_buf); cw.putCallAddress(moduleBaseAddress.add(0x2E2420)); cw.putAddRegImm('esp', 0x14) cw.putPushU32(Buf_EAX.toInt32()); cw.putMovRegAddress('ecx', ECX_buf); cw.putCallAddress(moduleBaseAddress.add(0x94C10)); cw.putPushU32(moduleBaseAddress.add(0x1DCB46C).toInt32()); cw.putPushU32(moduleBaseAddress.add(0x1DCB46C).toInt32()); cw.putMovRegAddress('ecx', ECX_buf); cw.putCallAddress(moduleBaseAddress.add(0x2E2630)); cw.putAddRegImm('esp', 0x8) cw.putPopax(); cw.putPopfx(); cw.putRet(); cw.flush(); }) const nativeativeFunction = new NativeFunction(ptr(asmCode), 'void', []) nativeativeFunction() })