From 0863b886ab7250c129b5ceeabd3f4779f9749a5d Mon Sep 17 00:00:00 2001 From: choogoo <104893934+choogoo@users.noreply.github.com> Date: Tue, 11 Jul 2023 13:51:58 +0800 Subject: [PATCH 1/6] 3.9.2.23 init (#180) * 3.9.2.23 initt * Update init-agent-script.js * 3.9.2.23 adapter --- src/agents/agent-script-3.6.0.18.js | 472 ++-- .../agent-script-3.9.2.23-laozhang-raw.js | 801 +++++++ src/agents/agent-script-3.9.2.23-new.js | 1964 +++++++++++++++++ src/init-agent-script.js | 1631 +++++++------- src/wechat-sidecar.ts | 16 +- 5 files changed, 3791 insertions(+), 1093 deletions(-) create mode 100644 src/agents/agent-script-3.9.2.23-laozhang-raw.js create mode 100644 src/agents/agent-script-3.9.2.23-new.js diff --git a/src/agents/agent-script-3.6.0.18.js b/src/agents/agent-script-3.6.0.18.js index b0dc6b1..6ae2c78 100644 --- a/src/agents/agent-script-3.6.0.18.js +++ b/src/agents/agent-script-3.6.0.18.js @@ -17,8 +17,8 @@ const offset = { /**---nick call */ - chatroom_member_nick_call_offset_v6:0x3E47B0,//3.6.0.18 - chatroom_member_nick_esi_offset_v6:0x22553D4, + 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, @@ -38,13 +38,13 @@ const offset = { 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_offset0: 0x9A1C0,//assign value to ecx send_picmsg_call_offset1: 0x4BE160,//0x5ccb50, - send_picmsg_call_ecx:0x222F0F0, + 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_ecx_offset: 0x1D8FA8C, send_attatch_call_offset0: 0x9A1C0, send_attatch_call_offset1: 0x701DC0,//0x701CD0,//701CD0 send_attatch_call_offset2: 0x4BA5F0,//4B A5F0 @@ -63,13 +63,13 @@ const offset = { /*------------------global-------------------------------------------*/ -const availableVersion = 1661337618////3.3.0.115 ==1661141107 +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() +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 @@ -88,46 +88,46 @@ let loggedIn = false 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_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_attatchPathPtr = null +let g_attatchPath = null +let g_attatchEBPAc = null +let g_attatchEBPAcBufPtr = null -let g_attatchContactIdPtr = null +let g_attatchContactIdPtr = null //let g_attatchECXBuffer = null -let g_attatchESIU32 = null +let g_attatchESIU32 = null -let g_initECXTempPtr = null -const initGlobal = ( (contactId,attatchFile)=> { +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) + console.log('------------g_attatchEBPAc', g_attatchEBPAc) + console.log('------------g_EDIU32', g_EDIU32) g_initTestAsm = Memory.alloc(Process.pageSize) - console.log('------------address',g_initTestAsm) - + 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 + g_attatchESIU32 = g_EDIU32 + + console.log('------------g_initECXU32', g_initECXU32) + console.log('------------g_initESIU32', g_attatchESIU32) - 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() @@ -150,7 +150,7 @@ const initGlobal = ( (contactId,attatchFile)=> { 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) @@ -160,17 +160,17 @@ const initGlobal = ( (contactId,attatchFile)=> { //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) - + 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) @@ -188,7 +188,7 @@ const initGlobal = ( (contactId,attatchFile)=> { cw.putCallAddress(moduleBaseAddress.add(0x131bb0))*/ //cw.putMovRegOffsetPtrU32('ebp', -20, 0) - + /*cw.putPushU32(0) cw.putMovRegAddress('eax', g_attatchPathPtr) cw.putPushReg('eax') @@ -241,24 +241,24 @@ const initGlobal = ( (contactId,attatchFile)=> { }) -let g_personal_detail_ebx =null -let g_personal_detail_asm =null +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 +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 = Memory.alloc(wxid.length * 2 + 2) g_personal_wxid_ptr.writeUtf16String(wxid) - g_personal_wxid=Memory.alloc(0x14) + 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) + .writeU32(wxid.length * 2).add(0x04) + .writeU32(wxid.length * 2).add(0x08) - console.log('-----------address----------',g_personal_detail_asm) + 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 }) @@ -269,14 +269,14 @@ const getOldTest = ( (wxid) => {//personal detail //78BA9ACE | E8 2D05D6FF | call wechatwin.7890A000 | cw.putMovRegU32('ebx', g_personal_detail_ebx) - cw.putMovRegReg('esi','eax') + cw.putMovRegReg('esi', 'eax') cw.putPushReg('ebx') - cw.putSubRegImm('esp',0x14) + cw.putSubRegImm('esp', 0x14) cw.putMovRegAddress('eax', g_personal_wxid) - cw.putMovRegReg('ecx','esp') + cw.putMovRegReg('ecx', 'esp') cw.putPushReg('eax') cw.putCallAddress(moduleBaseAddress.add(0x701DC0)) - cw.putMovRegReg('ecx','esi') + cw.putMovRegReg('ecx', 'esi') cw.putCallAddress(moduleBaseAddress.add(0x4024A0)) cw.putPopax() @@ -313,33 +313,33 @@ const getOldTest = ( (wxid) => {//personal detail * test call */ let attatchTestAsm = null -let attatchTestEbp2C = null -let attatchGlobalEDI = null -let attatchGlobalEDIB88 = 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 gattatchFilePtr = null let gattatchFile = null -let gattatchReceiveIdPtr=null -let gattatchReceiveId=null -let attatchEAX3B0Buf=null +let gattatchReceiveIdPtr = null +let gattatchReceiveId = null +let attatchEAX3B0Buf = null -let attatchESIbuf = null -const getWxTest = ( (contactId,filePath)=>{ +let attatchESIbuf = null +const getWxTest = ((contactId, filePath) => { //const nativeativeFunction = new NativeFunction(ptr(addr), 'void', []) //nativeativeFunction() attatchTestAsm = Memory.alloc(Process.pageSize) - console.log('----------------address',attatchTestAsm) + console.log('----------------address', attatchTestAsm) attatchTestEbp2C = Memory.alloc(0xC) attatchGlobalEDI = moduleBaseAddress.add(0x222f38c).readPointer() - .add(0x938).add(0x438).readPointer() + .add(0x938).add(0x438).readPointer() attatchGlobalEDIB88 = attatchGlobalEDI.add(0xB88).readPointer() - attatchTestEBX = Memory.alloc(0x4) + attatchTestEBX = Memory.alloc(0x4) attatchTestEBX.writePointer(attatchGlobalEDI) - console.log('----------------attatchGlobalEDI',attatchGlobalEDI) - console.log('----------------attatchGlobalEDIB88',attatchGlobalEDIB88) + console.log('----------------attatchGlobalEDI', attatchGlobalEDI) + console.log('----------------attatchGlobalEDIB88', attatchGlobalEDIB88) attatchFirstECX = Memory.alloc(0x28) //const attatchSecondEcx = Memory.alloc(0x14) @@ -348,13 +348,13 @@ const getWxTest = ( (contactId,filePath)=>{ const contractIdActLength = contactId.length - gattatchReceiveIdPtr=Memory.alloc(contactId.length * 2 + 2) + gattatchReceiveIdPtr = Memory.alloc(contactId.length * 2 + 2) gattatchReceiveIdPtr.writeUtf16String(contactId) - gattatchReceiveId=Memory.alloc(0x14) + gattatchReceiveId = Memory.alloc(0x14) gattatchReceiveId.writePointer(ptr(gattatchReceiveIdPtr)).add(0x04) - .writeU32(contactId.length*2).add(0x04) - .writeU32(contactId.length*2).add(0x08) + .writeU32(contactId.length * 2).add(0x04) + .writeU32(contactId.length * 2).add(0x08) //console.log('----------------attatchGlobalEDIB88',attatchGlobalEDIB88) //return /*console.log(hexdump(attatchTestEBX, { @@ -365,56 +365,56 @@ const getWxTest = ( (contactId,filePath)=>{ })) return*/ - gattatchFilePtr=Memory.alloc(filePath.length * 2 + 2) + gattatchFilePtr = Memory.alloc(filePath.length * 2 + 2) gattatchFilePtr.writeUtf16String(filePath) - gattatchFile=Memory.alloc(0x14) + gattatchFile = Memory.alloc(0x14) gattatchFile.writePointer(ptr(gattatchFilePtr)).add(0x04) - .writeU32(filePath.length*2).add(0x04) - .writeU32(filePath.length*2).add(0x08) + .writeU32(filePath.length * 2).add(0x04) + .writeU32(filePath.length * 2).add(0x08) const attatchLastECX = moduleBaseAddress.add(0x222f170).toInt32() - attatchEAX3B0Buf = Memory.alloc(0x3B0) + attatchEAX3B0Buf = Memory.alloc(0x3B0) - g_tempEcx = Memory.alloc(0x4) + 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) - + 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('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.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.putMovRegNearPtr('eax', attatchFirstECX) cw.putPushReg('eax') cw.putCallAddress(moduleBaseAddress.add(0x1a1047a)) cw.putAddRegImm('esp', 0x0c) @@ -424,7 +424,7 @@ const getWxTest = ( (contactId,filePath)=>{ //cw.putMovRegU32('edx', 0) //cw.putMovRegRegPtr('eax', 'ecx') //cw.putMovNearPtrReg(attatchFirstECX.add(0x04),'edi') - cw.putMovRegU32('edi',contactId.length * 2) + cw.putMovRegU32('edi', contactId.length * 2) cw.putMovRegU32('ecx', attatchLastECX) cw.putMovRegAddress('eax', attatchEAX3B0Buf) cw.putPushReg('eax') @@ -451,8 +451,8 @@ const getTestInfoFunction = ((addr) => { nativeativeFunction() //00CFE484 - - + + /*MemoryAccessMonitor.enable({base:ptr(addr),size:0x01}, { onAccess(details){ console.log('============') @@ -492,7 +492,7 @@ const getHeaderNodeAddress = (() => { // 005 const getChatroomNodeAddress = (() => { - const baseAddress= moduleBaseAddress.add(0x222f3fc).readPointer() + const baseAddress = moduleBaseAddress.add(0x222f3fc).readPointer() if (baseAddress.isNull()) { return baseAddress } @@ -530,7 +530,7 @@ const getMyselfInfoFunction = (() => { const getMyselfIdFunction = (() => { let wx_id = readString(moduleBaseAddress.add(offset.wxid_offset)) - + return wx_id }) @@ -668,9 +668,9 @@ const recurseNew = ((node) => { //const gender = node.add(0x18C).readU32() const contactJson = { - id1:id, + id1: id, id: wxid, - name:name, + name: name, /*code: wx_code, name: name, alias: alias, @@ -812,7 +812,7 @@ if (!isSupported) { const getContactNativeFunction = (() => { const headerNodeAddress = getHeaderNodeAddress() //console.log('headerNodeAddress',headerNodeAddress) - + if (headerNodeAddress.isNull()) { return '[]' } const node = headerNodeAddress.add(0x0).readPointer() @@ -820,7 +820,7 @@ const getContactNativeFunction = (() => { //console.log(ret) - console.log('getContactNativeFunction:',ret.length) + // console.log('getContactNativeFunction:',ret.length) /*for (let item of ret){ console.log(JSON.stringify(item)) }*/ @@ -998,7 +998,7 @@ const getQrcodeLoginData = () => { // 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']) @@ -1006,79 +1006,85 @@ const recvMsgNativeCallback = (() => { 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) + let addr + let msgType = 0 + let isMyMsg = 0 + let curTime = new Date() + try { + addr = this.context.eax//0xc30-0x08 + msgType = addr.add(0x38).readU32() + 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)) } - - setImmediate(() => nativeativeFunction(msgType, myTalkerIdPtr, myContentPtr, myGroupMsgSenderIdPtr, myXmlContentPtr, isMyMsg)) + } catch (err) { + console.error(curTime,'recvMsgNativeCallback at onEnter err:', err) } } }) @@ -1182,17 +1188,17 @@ let nickMemberIdStructV6 = null let memberNickBuffAsmV6 = null let nickResultEdiV6 = null -const getChatroomMemberNickInfoV1Function=((memberId, roomId)=>{ +const getChatroomMemberNickInfoV1Function = ((memberId, roomId) => { nickRoomIdV6 = initidStruct(roomId) nullEdiWxidStructV6 = initNullIdStruct('') nickMemberIdStructV6 = initStruct(memberId) memberNickBuffAsmV6 = Memory.alloc(Process.pageSize) - console.log('-----',memberNickBuffAsmV6) + console.log('-----', memberNickBuffAsmV6) const tmp = (moduleBaseAddress.add( offset.chatroom_member_nick_esi_offset_v6 )).readU32() - console.log('=======tmp',tmp) + console.log('=======tmp', tmp) Memory.patchCode(memberNickBuffAsmV6, Process.pageSize, code => { var cw = new X86Writer(code, { pc: memberNickBuffAsmV6 }) cw.putPushfx(); @@ -1202,19 +1208,19 @@ const getChatroomMemberNickInfoV1Function=((memberId, roomId)=>{ 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() @@ -1226,7 +1232,7 @@ const getChatroomMemberNickInfoV1Function=((memberId, roomId)=>{ const nativeativeFunction = new NativeFunction(ptr(memberNickBuffAsmV6), 'void', []) nativeativeFunction() - console.log('---------nullEdiWxidStructV6',nullEdiWxidStructV6) + console.log('---------nullEdiWxidStructV6', nullEdiWxidStructV6) const nickha = readWideString(nullEdiWxidStructV6) console.log('-----------------') @@ -1297,7 +1303,7 @@ const getChatroomMemberNickInfoFunction = ((memberId, roomId) => { cw.putAddRegImm('esp', 0x04) //cw.putMovNearPtrReg(nickRetAddr, 'ebx') //lea eax, buf - + cw.putPopax() cw.putPopfx() cw.putRet() @@ -1324,7 +1330,7 @@ let attatchPathPtr = null let attatchAsm = null let attatchBuf = null -let attatchReceiveIdPtr=null +let attatchReceiveIdPtr = null let attatchReceiveId = null let attatchSendId = null @@ -1340,15 +1346,15 @@ let attatchEbp210 = null let attatchEbpAc = null*/ let attatchEbp11E8 = null -let attatchEbpCC = null -let attatchEbp368 = null -let attatchEAX = null +let attatchEbpCC = null +let attatchEbp368 = null +let attatchEAX = null let sFileName = null let fileNamePtr = null let attatchEbp84 = null -let attatchECX = null +let attatchECX = null /** @@ -1358,37 +1364,37 @@ param {78EDBC86 | 8B80 38040000 | mov eax,dword ptr ds:[eax+438] */ // 021 -const sendAttatchMsgNativeFunction = ((contactId, senderId,path,filename,size) => { +const sendAttatchMsgNativeFunction = ((contactId, senderId, path, filename, size) => { attatchAsm = Memory.alloc(Process.pageSize) - console.log('--------------address',attatchAsm) + console.log('--------------address', attatchAsm) - fileNamePtr=Memory.alloc(filename.length * 2 + 2) + fileNamePtr = Memory.alloc(filename.length * 2 + 2) fileNamePtr.writeUtf16String(filename) - sFileName=Memory.alloc(0x14) + sFileName = Memory.alloc(0x14) sFileName.writePointer(ptr(fileNamePtr)).add(0x04) - .writeU32(fileNamePtr.length*2).add(0x04) - .writeU32(fileNamePtr.length*2).add(0x08) + .writeU32(fileNamePtr.length * 2).add(0x04) + .writeU32(fileNamePtr.length * 2).add(0x08) //const fileSize = size.toInt32() - attatchReceiveIdPtr=Memory.alloc(contactId.length * 2 + 2) + attatchReceiveIdPtr = Memory.alloc(contactId.length * 2 + 2) attatchReceiveIdPtr.writeUtf16String(contactId) - attatchReceiveId=Memory.alloc(0x14) + attatchReceiveId = Memory.alloc(0x14) attatchReceiveId.writePointer(ptr(attatchReceiveIdPtr)).add(0x04) - .writeU32(contactId.length*2).add(0x04) - .writeU32(contactId.length*2).add(0x08) + .writeU32(contactId.length * 2).add(0x04) + .writeU32(contactId.length * 2).add(0x08) - attatchSendIdPtr=Memory.alloc(senderId.length * 2 + 2) + attatchSendIdPtr = Memory.alloc(senderId.length * 2 + 2) attatchSendIdPtr.writeUtf16String(senderId) - attatchSendId=Memory.alloc(0x14) + attatchSendId = Memory.alloc(0x14) attatchSendId.writePointer(ptr(attatchSendIdPtr)).add(0x04) - .writeU32(senderId.length*2).add(0x04) - .writeU32(senderId.length*2).add(0x08) + .writeU32(senderId.length * 2).add(0x04) + .writeU32(senderId.length * 2).add(0x08) attatchPathPtr = Memory.alloc(path.length * 2 + 2) attatchPathPtr.writeUtf16String(path) @@ -1399,16 +1405,16 @@ const sendAttatchMsgNativeFunction = ((contactId, senderId,path,filename,size) = .writeU32(path.length * 2).add(0x04) attatchEbp11E8 = Memory.alloc(0xBE4) - attatchEbpCC = Memory.alloc(0x14) + attatchEbpCC = Memory.alloc(0x14) attatchEbp368 = Memory.alloc(0x290) - attatchEbp84 = Memory.alloc(0x18) - attatchEAX = Memory.alloc(0x18) + attatchEbp84 = Memory.alloc(0x18) + attatchEAX = Memory.alloc(0x18) attatchECX = moduleBaseAddress.add(0x222f178).toInt32() //console.log('basename',path.basename(path)) //return - + /** * -------------buffer------------------------------- */ @@ -1425,23 +1431,23 @@ const sendAttatchMsgNativeFunction = ((contactId, senderId,path,filename,size) = 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.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.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) @@ -1453,8 +1459,8 @@ const sendAttatchMsgNativeFunction = ((contactId, senderId,path,filename,size) = 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) @@ -1475,10 +1481,10 @@ const sendAttatchMsgNativeFunction = ((contactId, senderId,path,filename,size) = cw.putPushReg('ecx') cw.putPushReg('eax') - cw.putMovRegAddress('eax',attatchEbpCC) + cw.putMovRegAddress('eax', attatchEbpCC) cw.putPushReg('eax') - cw.putMovRegAddress('eax',attatchReceiveId) + cw.putMovRegAddress('eax', attatchReceiveId) cw.putPushReg('eax') cw.putMovRegAddress('ecx', attatchEbp368) @@ -1503,7 +1509,7 @@ const sendAttatchMsgNativeFunction = ((contactId, senderId,path,filename,size) = //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 @@ -1518,8 +1524,8 @@ const sendAttatchMsgNativeFunction = ((contactId, senderId,path,filename,size) = //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 | + // 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)) @@ -1607,7 +1613,7 @@ const sendPicMsgNativeFunction = ((contactId, path) => { offset.send_picmsg_call_offset0 )) cw.putMovRegReg('edx', 'eax')//缓存 - + cw.putSubRegImm('esp', 0x14) cw.putMovRegAddress('eax', buffwxid) cw.putMovRegReg('ecx', 'esp') @@ -1681,7 +1687,7 @@ const sendPicMsgNativeFunction = ((contactId, path) => { }) - console.log('----------picAsm',picAsm) + console.log('----------picAsm', picAsm) const nativeativeFunction = new NativeFunction(ptr(picAsm), 'void', []) nativeativeFunction() @@ -1950,18 +1956,18 @@ const agentReadyCallback = (() => { })() // 027 -const SendMiniProgramNativeFunction = ((bg_path_str,send_wxid_str,recv_wxid_str,xmlstr) => { +const SendMiniProgramNativeFunction = ((bg_path_str, send_wxid_str, recv_wxid_str, xmlstr) => { console.log("------------------------------------------------------"); - var asmCode=Memory.alloc(Process.pageSize); + 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 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) + // 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) @@ -1970,8 +1976,8 @@ const SendMiniProgramNativeFunction = ((bg_path_str,send_wxid_str,recv_wxid_str, .writeU32(0).add(0x04) .writeU32(0); - // var send_wxid_str="wxid_4zr616ir6fi122"; - var send_wxid_Ptr=Memory.alloc(send_wxid_str.length * 2 + 1) + // 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) @@ -1980,8 +1986,8 @@ const SendMiniProgramNativeFunction = ((bg_path_str,send_wxid_str,recv_wxid_str, .writeU32(0).add(0x04) .writeU32(0); - // var recv_wxid_str="filehelper"; - var recv_wxid_Ptr=Memory.alloc(recv_wxid_str.length * 2 + 1) + // 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) @@ -1990,9 +1996,9 @@ const SendMiniProgramNativeFunction = ((bg_path_str,send_wxid_str,recv_wxid_str, .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'); + // 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) + var pXml = initidStruct(xmlstr) console.log(send_wxid_Struct); console.log(recv_wxid_Struct); diff --git a/src/agents/agent-script-3.9.2.23-laozhang-raw.js b/src/agents/agent-script-3.9.2.23-laozhang-raw.js new file mode 100644 index 0000000..5d9cddc --- /dev/null +++ b/src/agents/agent-script-3.9.2.23-laozhang-raw.js @@ -0,0 +1,801 @@ +/** + * 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.9.2.23 + +const offset = { + + + hook_point: 0xd19a0b, //3.9.2.23 + + myselfinfo: { + offset: 0x2FFD484, //老版本微信号偏移,后面的地址,都要在这个偏移上增加 + //wxid_len:0x10, + head_img_url: 0x2D8, + head_img_url_len: 0x2E8, + wx_nick_name: 0x10C, + wxcode_new: 0x64, //新版本微信号 + //wxcode_len:0x74 + wxid_len_offset: 0x4D4 + }, + + contactInfo: { + nodeOffset: 0x2FFDD7C, + nodeRootOffset: 0x64 + }, + chatroomInfo: { + nodeOffset: 0x2FFDDC8, + nodeRootOffset: 0x8c8 + }, + sendTxtMsg: { + callOffset: 0xCE6C80 + }, + sendPicMsg: { + call1: 0x768140, + call2: 0xf59e40, + call3: 0xce6640 + } +}; + + + +/*------------------global-------------------------------------------*/ +const availableVersion = 1661534743 ////3.9.2.23 ==0x63090217 + +const moduleBaseAddress = Module.getBaseAddress('WeChatWin.dll') +const moduleLoad = Module.load('WeChatWin.dll') +//1575CF98 + + +/*---------------base -------------------------*/ + +let retidPtr=null +let retidStruct=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 +}) + +let msgstrPtr=null +let msgStruct=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 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 +}) +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() +} + + +/*-----------------base-------------------------*/ + +let currentVersion = 0 + +let nodeList = [] //for contact +let contactList = [] //for contact + +let chatroomNodeList = [] //for chatroom +let chatroomMemberList = [] //for chatroom +let loggedIn = false + + + +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('.') +}) + +const checkSupportedFunction = (() => { + const ver = getWechatVersionFunction() + return ver == availableVersion +}) + +// 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.ecx //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(0x1f0).readU32() //3.9.2.23 + let myXmlContentPtr = null + if (xmlNullPtr == 0) { + + myXmlContentPtr = Memory.alloc(0x10) + myXmlContentPtr.writeUtf16String("null") + + } else { + const xmlContentPtr = addr.add(0x1f0).readPointer() //3.9.2.23 + + const xmlContentLen = addr.add(0x1f0 + 0x04).readU32() * 2 + 2 + myXmlContentPtr = Memory.alloc(xmlContentLen) + Memory.copy(myXmlContentPtr, xmlContentPtr, xmlContentLen) + } + + setImmediate(() => nativeativeFunction(msgType, myTalkerIdPtr, myContentPtr, myGroupMsgSenderIdPtr, myXmlContentPtr, isMyMsg)) + } + } + }) + return nativeCallback +})() + + +const getBaseNodeAddress = (() => { + return moduleBaseAddress.add(offset.contactInfo.nodeOffset).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.contactInfo.nodeRootOffset).readPointer() +}) + +const getMyselfInfoFunction = (() => { + + let ptr = 0 + let wx_code = '' + let wx_id = '' + let wx_name = '' + let head_img_url = '' + + const base = moduleBaseAddress.add(offset.myselfinfo.offset) + const wxid_len = base.add(offset.myselfinfo.wxid_len_offset).readU32() + + if (wxid_len === 0x13) { // 新版本微信 + wx_id = base.readPointer().readAnsiString(wxid_len) + wx_code = base.add(offset.myselfinfo.wxcode_new).readAnsiString() + } else { + wx_id = readString(base) + wx_code = wx_id + } + + + wx_name = readString(base.add(offset.myselfinfo.wx_nick_name)) + const img_addr = base.add(offset.myselfinfo.head_img_url).readPointer() + const img_len = base.add(offset.myselfinfo.head_img_url_len).readU32() + + head_img_url = img_addr.readAnsiString(img_len) + + const myself = { + id: wx_id, + code: wx_code, + name: wx_name, + head_img_url: head_img_url, + }; + + return JSON.stringify(myself) + +}) + + +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 + +}) + + +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 +}) + + +const getChatroomNodeAddress = (() => { + const baseAddress = moduleBaseAddress.add(offset.chatroomInfo.nodeOffset).readPointer() + if (baseAddress.isNull()) { + return baseAddress + } + return baseAddress.add(offset.chatroomInfo.nodeRootOffset).readPointer() +}) + +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(0x54).readU32() // + //const memberJson={} + if (len > 4) { // + const memberStr = readString(node.add(0x44)) + 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 +}) + +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 +}) + + + +/** + * sendMsgNativeFunction + * send text message + * @param {string} talkerId = wxid or roomid + * @param {string} content + */ +const sendMsgNativeFunction = ((talkerId, content) => { + + const txtAsm = Memory.alloc(Process.pageSize) + //const buffwxid = Memory.alloc(0x20) + + + let wxidPtr = Memory.alloc(talkerId.length * 2 + 2) + wxidPtr.writeUtf16String(talkerId) + + let picWxid = Memory.alloc(0x0c) + picWxid.writePointer(ptr(wxidPtr)).add(0x04) + .writeU32(talkerId.length * 2).add(0x04) + .writeU32(talkerId.length * 2).add(0x04) + + let contentPtr = Memory.alloc(content.length * 2 + 2) + contentPtr.writeUtf16String(content) + + const sizeOfStringStruct = Process.pointerSize * 5 + let contentStruct = Memory.alloc(sizeOfStringStruct) + + contentStruct + .writePointer(contentPtr).add(0x4) + .writeU32(content.length).add(0x4) + .writeU32(content.length * 2) + + + const ecxBuffer = Memory.alloc(0x2d8) + + Memory.patchCode(txtAsm, Process.pageSize, code => { + var cw = new X86Writer(code, { + pc: txtAsm + }) + cw.putPushfx() + cw.putPushax() + + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x1) + cw.putPushU32(0x0) + + //cw.putMovRegReg + + cw.putMovRegAddress('eax', contentStruct) + cw.putPushReg('eax') + + cw.putMovRegAddress('edx', picWxid) //room_id + + cw.putMovRegAddress('ecx', ecxBuffer) + cw.putCallAddress(moduleBaseAddress.add( + offset.sendTxtMsg.callOffset + )) + + cw.putAddRegImm('esp', 0x18) + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() + + }) + + console.log('----------txtAsm', txtAsm) + const nativeativeFunction = new NativeFunction(ptr(txtAsm), 'void', []) + nativeativeFunction() + +}) + + +let asmAtMsg = null +let roomid_, msg_, wxid_, atid_ +let ecxBuffer +const sendAtMsgNativeFunction = ((roomId, text, contactId,nickname) => { + + asmAtMsg = Memory.alloc(Process.pageSize) + ecxBuffer = Memory.alloc(0x3b0) + + const atContent = '@'+nickname+' '+text + + roomid_ = initStruct(roomId) + wxid_ = initidStruct(contactId) + msg_ = initmsgStruct(atContent) + atid_ = initAtMsgStruct(wxid_) + + Memory.patchCode(asmAtMsg, Process.pageSize, code => { + var cw = new X86Writer(code, { + pc: asmAtMsg + }) + cw.putPushfx() + cw.putPushax() + + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x1) + //cw.putPushU32(0x0) + cw.putMovRegAddress('eax', atid_) + cw.putPushReg('eax') + + //cw.putMovRegReg + + cw.putMovRegAddress('eax', msg_) + cw.putPushReg('eax') + + cw.putMovRegAddress('edx', roomid_) //room_id + + cw.putMovRegAddress('ecx', ecxBuffer) + cw.putCallAddress(moduleBaseAddress.add( + offset.sendTxtMsg.callOffset + )) + + cw.putAddRegImm('esp', 0x18) + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() + + }) + + //console.log('----------txtAsm', asmAtMsg) + const nativeativeFunction = new NativeFunction(ptr(asmAtMsg), 'void', []) + nativeativeFunction() + +}) + +/** + * + * @param {*} contactId + * @param {*} path + */ +const sendPicMsgNativeFunction = ((contactId, path) => { + + const picAsm = Memory.alloc(Process.pageSize) + const buffwxid = Memory.alloc(0x20) + const picbuff = Memory.alloc(0x2D8) + + let pathPtr = Memory.alloc(path.length * 2 + 1) + pathPtr.writeUtf16String(path) + + let imagefilepath = Memory.alloc(0x24) + imagefilepath.writePointer(pathPtr).add(0x04) + .writeU32(path.length * 2).add(0x04) + .writeU32(path.length * 2).add(0x04) + + let picWxidPtr = Memory.alloc(contactId.length * 2 + 1) + picWxidPtr.writeUtf16String(contactId) + + let picWxid = Memory.alloc(0x0c) + picWxid.writePointer(ptr(picWxidPtr)).add(0x04) + .writeU32(contactId.length * 2).add(0x04) + .writeU32(contactId.length * 2).add(0x04) + + + //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.sendPicMsg.call1 + )) + 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( + offset.sendPicMsg.call2 + )) + + 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.sendPicMsg.call3 + )) + + + + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() + + }) + + //console.log('----------picAsm',picAsm) + const nativeativeFunction = new NativeFunction(ptr(picAsm), 'void', []) + nativeativeFunction() + +}) + + + + +let memberNickBuffAsm = null +let nickRoomId = null +let nickMemberId = null +let nickBuff = null +const getChatroomMemberNickInfoFunction = ((memberId, roomId) => { + + nickBuff = Memory.alloc(0x7e4) + //const nickRetAddr = Memory.alloc(0x04) + memberNickBuffAsm = Memory.alloc(Process.pageSize) + //console.log('asm address----------',memberNickBuffAsm) + nickRoomId = initidStruct(roomId) + //console.log('nick room id',nickRoomId) + nickMemberId = initStruct(memberId) + + //console.log('nick nickMemberId id',nickMemberId) + //const nickStructPtr = initmsgStruct('') + + Memory.patchCode(memberNickBuffAsm, Process.pageSize, code => { + var cw = new X86Writer(code, { + pc: memberNickBuffAsm + }) + cw.putPushfx() + cw.putPushax() + cw.putMovRegAddress('edi', nickRoomId) + cw.putMovRegAddress('eax', nickBuff) + cw.putMovRegReg('edx', 'edi') + cw.putPushReg('eax') + cw.putMovRegAddress('ecx', nickMemberId) + cw.putCallAddress(moduleBaseAddress.add(0xC06F10)) + cw.putAddRegImm('esp', 0x04) + 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) +}) + + diff --git a/src/agents/agent-script-3.9.2.23-new.js b/src/agents/agent-script-3.9.2.23-new.js new file mode 100644 index 0000000..f706c38 --- /dev/null +++ b/src/agents/agent-script-3.9.2.23-new.js @@ -0,0 +1,1964 @@ +/** + * > Special thanks to: @cixingguangming55555 老张学技术 + * + * Credit: https://github.com/cixingguangming55555/wechat-bot + */ + +//https://blog.csdn.net/iloveitvm/article/details/109119687 frida学习 + +//const { isNullishCoalesce } = require("typescript") + +//3.9.2.23 + +// 偏移地址集合 done +const offset = { + hook_point: 0xd19a0b, //3.9.2.23 + myselfinfo: { + offset: 0x2FFD484, //老版本微信号偏移,后面的地址,都要在这个偏移上增加 + //wxid_len:0x10, + head_img_url: 0x2D8, + head_img_url_len: 0x2E8, + wx_nick_name: 0x10C, + wxcode_new: 0x64, //新版本微信号 + //wxcode_len:0x74 + wxid_len_offset: 0x4D4 + }, + contactInfo: { + nodeOffset: 0x2FFDD7C, + nodeRootOffset: 0x64 + }, + chatroomInfo: { + nodeOffset: 0x2FFDDC8, + nodeRootOffset: 0x8c8 + }, + sendTxtMsg: { + callOffset: 0xCE6C80 + }, + sendPicMsg: { + call1: 0x768140, + call2: 0xf59e40, + call3: 0xce6640 + } +}; +//3.9.2.23 + +// 全局配置 done +/*------------------global-------------------------------------------*/ +const availableVersion = 1661534743 ////3.9.2.23 ==0x63090217 + +const moduleBaseAddress = Module.getBaseAddress('WeChatWin.dll') +const moduleLoad = Module.load('WeChatWin.dll') +//1575CF98 + +// 全局变量 tbd +const g_EDIPtr = moduleBaseAddress.add(0x222f38c).readPointer().add(0xD70).readPointer()// +const g_EDIU32 = moduleBaseAddress.add(0x222f38c).readPointer().add(0xD70).readU32() + +/*------------------global-------------------------------------------*/ + +/*---------------base -------------------------*/ + +// done +let retidPtr=null +let retidStruct=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 +}) + +// done +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 +}) + +// done +let msgstrPtr=null +let msgStruct=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 +}) + +// tbd +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 +}) + +// done +/** +* 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 +}) + +// done +// 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 +} + +// done +const readString = (address) => { + return readStringPtr(address).readUtf8String() +} + +// done +const readWideString = (address) => { + return readWStringPtr(address).readUtf16String() +} + +/*-----------------base-------------------------*/ + +let currentVersion = 0 + +let nodeList = [] //for contact +let contactList = [] //for contact + +let chatroomNodeList = [] //for chatroom +let chatroomMemberList = []//for chatroom +let loggedIn = false + +//开启日志 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 +}) + +// 007 缺失,请标注已废弃或者其他原因 +const getMyselfIdFunction = (() => { + + let wx_id = readString(moduleBaseAddress.add(offset.wxid_offset)) + + return wx_id + +}) + +// 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 +} + +//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 + +}) + +// 010 done +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 done +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 done +const checkSupportedFunction = (() => { + const ver = getWechatVersionFunction() + return ver == availableVersion +}) + +/** + * @Hook: recvMsg -> recvMsgNativeCallback + */ + +// 019 done +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.ecx //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(0x1f0).readU32() //3.9.2.23 + let myXmlContentPtr = null + if (xmlNullPtr == 0) { + + myXmlContentPtr = Memory.alloc(0x10) + myXmlContentPtr.writeUtf16String("null") + + } else { + const xmlContentPtr = addr.add(0x1f0).readPointer() //3.9.2.23 + + const xmlContentLen = addr.add(0x1f0 + 0x04).readU32() * 2 + 2 + myXmlContentPtr = Memory.alloc(xmlContentLen) + Memory.copy(myXmlContentPtr, xmlContentPtr, xmlContentLen) + } + + setImmediate(() => nativeativeFunction(msgType, myTalkerIdPtr, myContentPtr, myGroupMsgSenderIdPtr, myXmlContentPtr, isMyMsg)) + } + } + }) + return nativeCallback +})() + +// 003get myself info done +const getBaseNodeAddress = (() => { + return moduleBaseAddress.add(offset.contactInfo.nodeOffset).readPointer() +}) + +// 004 done +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.contactInfo.nodeRootOffset).readPointer() +}) + +// 006 done +const getMyselfInfoFunction = (() => { + + let ptr = 0 + let wx_code = '' + let wx_id = '' + let wx_name = '' + let head_img_url = '' + + const base = moduleBaseAddress.add(offset.myselfinfo.offset) + const wxid_len = base.add(offset.myselfinfo.wxid_len_offset).readU32() + + if (wxid_len === 0x13) { // 新版本微信 + wx_id = base.readPointer().readAnsiString(wxid_len) + wx_code = base.add(offset.myselfinfo.wxcode_new).readAnsiString() + } else { + wx_id = readString(base) + wx_code = wx_id + } + + + wx_name = readString(base.add(offset.myselfinfo.wx_nick_name)) + const img_addr = base.add(offset.myselfinfo.head_img_url).readPointer() + const img_len = base.add(offset.myselfinfo.head_img_url_len).readU32() + + head_img_url = img_addr.readAnsiString(img_len) + + const myself = { + id: wx_id, + code: wx_code, + name: wx_name, + head_img_url: head_img_url, + }; + + return JSON.stringify(myself) + +}) + +// done +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 + +}) + +// done ? +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 +}) + +// 005 done +const getChatroomNodeAddress = (() => { + const baseAddress = moduleBaseAddress.add(offset.chatroomInfo.nodeOffset).readPointer() + if (baseAddress.isNull()) { + return baseAddress + } + return baseAddress.add(offset.chatroomInfo.nodeRootOffset).readPointer() +}) + +// 008chatroom member done +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(0x54).readU32() // + //const memberJson={} + if (len > 4) { // + const memberStr = readString(node.add(0x44)) + 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 +}) + +// 009 done +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 +}) + +// 024 done +/** + * sendMsgNativeFunction + * send text message + * @param {string} talkerId = wxid or roomid + * @param {string} content + */ + const sendMsgNativeFunction = ((talkerId, content) => { + + const txtAsm = Memory.alloc(Process.pageSize) + //const buffwxid = Memory.alloc(0x20) + + + let wxidPtr = Memory.alloc(talkerId.length * 2 + 2) + wxidPtr.writeUtf16String(talkerId) + + let picWxid = Memory.alloc(0x0c) + picWxid.writePointer(ptr(wxidPtr)).add(0x04) + .writeU32(talkerId.length * 2).add(0x04) + .writeU32(talkerId.length * 2).add(0x04) + + let contentPtr = Memory.alloc(content.length * 2 + 2) + contentPtr.writeUtf16String(content) + + const sizeOfStringStruct = Process.pointerSize * 5 + let contentStruct = Memory.alloc(sizeOfStringStruct) + + contentStruct + .writePointer(contentPtr).add(0x4) + .writeU32(content.length).add(0x4) + .writeU32(content.length * 2) + + + const ecxBuffer = Memory.alloc(0x2d8) + + Memory.patchCode(txtAsm, Process.pageSize, code => { + var cw = new X86Writer(code, { + pc: txtAsm + }) + cw.putPushfx() + cw.putPushax() + + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x1) + cw.putPushU32(0x0) + + //cw.putMovRegReg + + cw.putMovRegAddress('eax', contentStruct) + cw.putPushReg('eax') + + cw.putMovRegAddress('edx', picWxid) //room_id + + cw.putMovRegAddress('ecx', ecxBuffer) + cw.putCallAddress(moduleBaseAddress.add( + offset.sendTxtMsg.callOffset + )) + + cw.putAddRegImm('esp', 0x18) + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() + + }) + + console.log('----------txtAsm', txtAsm) + const nativeativeFunction = new NativeFunction(ptr(txtAsm), 'void', []) + nativeativeFunction() + +}) + +// 023 done +/** +* send at msg +*/ +let asmAtMsg = null +let roomid_, msg_, wxid_, atid_ +let ecxBuffer +const sendAtMsgNativeFunction = ((roomId, text, contactId,nickname) => { + + asmAtMsg = Memory.alloc(Process.pageSize) + ecxBuffer = Memory.alloc(0x3b0) + + const atContent = '@'+nickname+' '+text + + roomid_ = initStruct(roomId) + wxid_ = initidStruct(contactId) + msg_ = initmsgStruct(atContent) + atid_ = initAtMsgStruct(wxid_) + + Memory.patchCode(asmAtMsg, Process.pageSize, code => { + var cw = new X86Writer(code, { + pc: asmAtMsg + }) + cw.putPushfx() + cw.putPushax() + + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x1) + //cw.putPushU32(0x0) + cw.putMovRegAddress('eax', atid_) + cw.putPushReg('eax') + + //cw.putMovRegReg + + cw.putMovRegAddress('eax', msg_) + cw.putPushReg('eax') + + cw.putMovRegAddress('edx', roomid_) //room_id + + cw.putMovRegAddress('ecx', ecxBuffer) + cw.putCallAddress(moduleBaseAddress.add( + offset.sendTxtMsg.callOffset + )) + + cw.putAddRegImm('esp', 0x18) + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() + + }) + + //console.log('----------txtAsm', asmAtMsg) + const nativeativeFunction = new NativeFunction(ptr(asmAtMsg), 'void', []) + nativeativeFunction() + +}) + +// 022 done +/** + * + * @param {*} contactId + * @param {*} path + */ + const sendPicMsgNativeFunction = ((contactId, path) => { + + const picAsm = Memory.alloc(Process.pageSize) + const buffwxid = Memory.alloc(0x20) + const picbuff = Memory.alloc(0x2D8) + + let pathPtr = Memory.alloc(path.length * 2 + 1) + pathPtr.writeUtf16String(path) + + let imagefilepath = Memory.alloc(0x24) + imagefilepath.writePointer(pathPtr).add(0x04) + .writeU32(path.length * 2).add(0x04) + .writeU32(path.length * 2).add(0x04) + + let picWxidPtr = Memory.alloc(contactId.length * 2 + 1) + picWxidPtr.writeUtf16String(contactId) + + let picWxid = Memory.alloc(0x0c) + picWxid.writePointer(ptr(picWxidPtr)).add(0x04) + .writeU32(contactId.length * 2).add(0x04) + .writeU32(contactId.length * 2).add(0x04) + + + //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.sendPicMsg.call1 + )) + 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( + offset.sendPicMsg.call2 + )) + + 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.sendPicMsg.call3 + )) + + + + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() + + }) + + //console.log('----------picAsm',picAsm) + const nativeativeFunction = new NativeFunction(ptr(picAsm), 'void', []) + nativeativeFunction() + +}) + +// 020 done +let memberNickBuffAsm = null +let nickRoomId = null +let nickMemberId = null +let nickBuff = null +const getChatroomMemberNickInfoFunction = ((memberId, roomId) => { + + nickBuff = Memory.alloc(0x7e4) + //const nickRetAddr = Memory.alloc(0x04) + memberNickBuffAsm = Memory.alloc(Process.pageSize) + //console.log('asm address----------',memberNickBuffAsm) + nickRoomId = initidStruct(roomId) + //console.log('nick room id',nickRoomId) + nickMemberId = initStruct(memberId) + + //console.log('nick nickMemberId id',nickMemberId) + //const nickStructPtr = initmsgStruct('') + + Memory.patchCode(memberNickBuffAsm, Process.pageSize, code => { + var cw = new X86Writer(code, { + pc: memberNickBuffAsm + }) + cw.putPushfx() + cw.putPushax() + cw.putMovRegAddress('edi', nickRoomId) + cw.putMovRegAddress('eax', nickBuff) + cw.putMovRegReg('edx', 'edi') + cw.putPushReg('eax') + cw.putMovRegAddress('ecx', nickMemberId) + cw.putCallAddress(moduleBaseAddress.add(0xC06F10)) + cw.putAddRegImm('esp', 0x04) + 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) +}) + +// 013 +const isSupported = checkSupportedFunction() + +if (!isSupported) { + throw new Error(`Wechat version not supported. \nWechat version: ${getWechatVersionStringFunction()}, supported version: ${getWechatVersionStringFunction(availableVersion)}`) +} + +// 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 +})()*/ + +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) +}) + +/** +* 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 -------------------------- +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() + +})*/ + +// 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() + + +}) \ No newline at end of file diff --git a/src/init-agent-script.js b/src/init-agent-script.js index 6ae2c78..f706c38 100644 --- a/src/init-agent-script.js +++ b/src/init-agent-script.js @@ -1,75 +1,197 @@ /** - * 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 +//3.9.2.23 +// 偏移地址集合 done 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, + hook_point: 0xd19a0b, //3.9.2.23 + myselfinfo: { + offset: 0x2FFD484, //老版本微信号偏移,后面的地址,都要在这个偏移上增加 + //wxid_len:0x10, + head_img_url: 0x2D8, + head_img_url_len: 0x2E8, + wx_nick_name: 0x10C, + wxcode_new: 0x64, //新版本微信号 + //wxcode_len:0x74 + wxid_len_offset: 0x4D4 + }, + contactInfo: { + nodeOffset: 0x2FFDD7C, + nodeRootOffset: 0x64 + }, + chatroomInfo: { + nodeOffset: 0x2FFDDC8, + nodeRootOffset: 0x8c8 + }, + sendTxtMsg: { + callOffset: 0xCE6C80 + }, + sendPicMsg: { + call1: 0x768140, + call2: 0xf59e40, + call3: 0xce6640 + } }; -//3.3.0.115 - +//3.9.2.23 +// 全局配置 done /*------------------global-------------------------------------------*/ -const availableVersion = 1661337618////3.3.0.115 ==1661141107 +const availableVersion = 1661534743 ////3.9.2.23 ==0x63090217 const moduleBaseAddress = Module.getBaseAddress('WeChatWin.dll') const moduleLoad = Module.load('WeChatWin.dll') //1575CF98 + +// 全局变量 tbd const g_EDIPtr = moduleBaseAddress.add(0x222f38c).readPointer().add(0xD70).readPointer()// const g_EDIU32 = moduleBaseAddress.add(0x222f38c).readPointer().add(0xD70).readU32() + +/*------------------global-------------------------------------------*/ + +/*---------------base -------------------------*/ + +// done +let retidPtr=null +let retidStruct=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 +}) + +// done +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 +}) + +// done +let msgstrPtr=null +let msgStruct=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 +}) + +// tbd +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 +}) + +// done +/** +* 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 +}) + +// done +// 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 +} + +// done +const readString = (address) => { + return readStringPtr(address).readUtf8String() +} + +// done +const readWideString = (address) => { + return readWStringPtr(address).readUtf16String() +} + +/*-----------------base-------------------------*/ + let currentVersion = 0 let nodeList = [] //for contact @@ -79,8 +201,6 @@ let chatroomNodeList = [] //for chatroom let chatroomMemberList = []//for chatroom let loggedIn = false -/*------------------global-------------------------------------------*/ - //开启日志 3.6.0.18 // //[0x221c330+wechatwin.dll]+0xf8 // 20220504 @@ -472,60 +592,6 @@ const isLoggedInFunction = (() => { 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 = (() => { @@ -535,76 +601,6 @@ const getMyselfIdFunction = (() => { }) -// 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) => { @@ -624,15 +620,8 @@ const readWStringPtr = (address) => { return addr } -const readString = (address) => { - return readStringPtr(address).readUtf8String() -} - -const readWideString = (address) => { - return readWStringPtr(address).readUtf16String() -} - -const recurseNew = ((node) => { +//contact +const recurse = ((node) => { const headerNodeAddress = getHeaderNodeAddress() if (headerNodeAddress.isNull()) { return } @@ -646,17 +635,262 @@ const recurseNew = ((node) => { nodeList.push(node) - const id = readString(node.add(0x8)) //wxid, format relates to registration method - const wxid = readWideString(node.add(0x30)) - //console.log('-----------',wxid) - + 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)) + const wx_code = readWideString(node.add(0x4c)) || readWideString(node.add(0x38)) //custom Nickname - const name = readWideString(node.add(0x8c)) + 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 + +}) + +// 010 done +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 done +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 done +const checkSupportedFunction = (() => { + const ver = getWechatVersionFunction() + return ver == availableVersion +}) + +/** + * @Hook: recvMsg -> recvMsgNativeCallback + */ + +// 019 done +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.ecx //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(0x1f0).readU32() //3.9.2.23 + let myXmlContentPtr = null + if (xmlNullPtr == 0) { + + myXmlContentPtr = Memory.alloc(0x10) + myXmlContentPtr.writeUtf16String("null") + + } else { + const xmlContentPtr = addr.add(0x1f0).readPointer() //3.9.2.23 + + const xmlContentLen = addr.add(0x1f0 + 0x04).readU32() * 2 + 2 + myXmlContentPtr = Memory.alloc(xmlContentLen) + Memory.copy(myXmlContentPtr, xmlContentPtr, xmlContentLen) + } + + setImmediate(() => nativeativeFunction(msgType, myTalkerIdPtr, myContentPtr, myGroupMsgSenderIdPtr, myXmlContentPtr, isMyMsg)) + } + } + }) + return nativeCallback +})() + +// 003get myself info done +const getBaseNodeAddress = (() => { + return moduleBaseAddress.add(offset.contactInfo.nodeOffset).readPointer() +}) + +// 004 done +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.contactInfo.nodeRootOffset).readPointer() +}) + +// 006 done +const getMyselfInfoFunction = (() => { + + let ptr = 0 + let wx_code = '' + let wx_id = '' + let wx_name = '' + let head_img_url = '' + + const base = moduleBaseAddress.add(offset.myselfinfo.offset) + const wxid_len = base.add(offset.myselfinfo.wxid_len_offset).readU32() + + if (wxid_len === 0x13) { // 新版本微信 + wx_id = base.readPointer().readAnsiString(wxid_len) + wx_code = base.add(offset.myselfinfo.wxcode_new).readAnsiString() + } else { + wx_id = readString(base) + wx_code = wx_id + } + + + wx_name = readString(base.add(offset.myselfinfo.wx_nick_name)) + const img_addr = base.add(offset.myselfinfo.head_img_url).readPointer() + const img_len = base.add(offset.myselfinfo.head_img_url_len).readU32() + + head_img_url = img_addr.readAnsiString(img_len) + + const myself = { + id: wx_id, + code: wx_code, + name: wx_name, + head_img_url: head_img_url, + }; + + return JSON.stringify(myself) + +}) + +// done +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)) @@ -693,112 +927,361 @@ const recurseNew = ((node) => { }) - -//contact -const recurse = ((node) => { +// done ? +const getContactNativeFunction = (() => { const headerNodeAddress = getHeaderNodeAddress() - if (headerNodeAddress.isNull()) { return } + //console.log('headerNodeAddress',headerNodeAddress) - if (node.equals(headerNodeAddress)) { return } + if (headerNodeAddress.isNull()) { + return '[]' + } - for (const item in nodeList) { - if (node.equals(nodeList[item])) { + 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 +}) + +// 005 done +const getChatroomNodeAddress = (() => { + const baseAddress = moduleBaseAddress.add(offset.chatroomInfo.nodeOffset).readPointer() + if (baseAddress.isNull()) { + return baseAddress + } + return baseAddress.add(offset.chatroomInfo.nodeRootOffset).readPointer() +}) + +// 008chatroom member done +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)) - nodeList.push(node) - //wxid, format relates to registration method - const wxid = readWideString(node.add(0x38)) + const len = node.add(0x54).readU32() // + //const memberJson={} + if (len > 4) { // + const memberStr = readString(node.add(0x44)) + 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 +}) + +// 009 done +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 +}) + +// 024 done +/** + * sendMsgNativeFunction + * send text message + * @param {string} talkerId = wxid or roomid + * @param {string} content + */ + const sendMsgNativeFunction = ((talkerId, content) => { + + const txtAsm = Memory.alloc(Process.pageSize) + //const buffwxid = Memory.alloc(0x20) + + + let wxidPtr = Memory.alloc(talkerId.length * 2 + 2) + wxidPtr.writeUtf16String(talkerId) + + let picWxid = Memory.alloc(0x0c) + picWxid.writePointer(ptr(wxidPtr)).add(0x04) + .writeU32(talkerId.length * 2).add(0x04) + .writeU32(talkerId.length * 2).add(0x04) + + let contentPtr = Memory.alloc(content.length * 2 + 2) + contentPtr.writeUtf16String(content) + + const sizeOfStringStruct = Process.pointerSize * 5 + let contentStruct = Memory.alloc(sizeOfStringStruct) + + contentStruct + .writePointer(contentPtr).add(0x4) + .writeU32(content.length).add(0x4) + .writeU32(content.length * 2) + + + const ecxBuffer = Memory.alloc(0x2d8) + + Memory.patchCode(txtAsm, Process.pageSize, code => { + var cw = new X86Writer(code, { + pc: txtAsm + }) + cw.putPushfx() + cw.putPushax() + + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x1) + cw.putPushU32(0x0) + + //cw.putMovRegReg + + cw.putMovRegAddress('eax', contentStruct) + cw.putPushReg('eax') + + cw.putMovRegAddress('edx', picWxid) //room_id + + cw.putMovRegAddress('ecx', ecxBuffer) + cw.putCallAddress(moduleBaseAddress.add( + offset.sendTxtMsg.callOffset + )) + + cw.putAddRegImm('esp', 0x18) + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() + + }) + + console.log('----------txtAsm', txtAsm) + const nativeativeFunction = new NativeFunction(ptr(txtAsm), 'void', []) + nativeativeFunction() + +}) + +// 023 done +/** +* send at msg +*/ +let asmAtMsg = null +let roomid_, msg_, wxid_, atid_ +let ecxBuffer +const sendAtMsgNativeFunction = ((roomId, text, contactId,nickname) => { + + asmAtMsg = Memory.alloc(Process.pageSize) + ecxBuffer = Memory.alloc(0x3b0) + + const atContent = '@'+nickname+' '+text + + roomid_ = initStruct(roomId) + wxid_ = initidStruct(contactId) + msg_ = initmsgStruct(atContent) + atid_ = initAtMsgStruct(wxid_) + + Memory.patchCode(asmAtMsg, Process.pageSize, code => { + var cw = new X86Writer(code, { + pc: asmAtMsg + }) + cw.putPushfx() + cw.putPushax() + + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x1) + //cw.putPushU32(0x0) + cw.putMovRegAddress('eax', atid_) + cw.putPushReg('eax') + + //cw.putMovRegReg + + cw.putMovRegAddress('eax', msg_) + cw.putPushReg('eax') + + cw.putMovRegAddress('edx', roomid_) //room_id + + cw.putMovRegAddress('ecx', ecxBuffer) + cw.putCallAddress(moduleBaseAddress.add( + offset.sendTxtMsg.callOffset + )) + + cw.putAddRegImm('esp', 0x18) + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() + + }) + + //console.log('----------txtAsm', asmAtMsg) + const nativeativeFunction = new NativeFunction(ptr(asmAtMsg), 'void', []) + nativeativeFunction() + +}) + +// 022 done +/** + * + * @param {*} contactId + * @param {*} path + */ + const sendPicMsgNativeFunction = ((contactId, path) => { + + const picAsm = Memory.alloc(Process.pageSize) + const buffwxid = Memory.alloc(0x20) + const picbuff = Memory.alloc(0x2D8) + + let pathPtr = Memory.alloc(path.length * 2 + 1) + pathPtr.writeUtf16String(path) + + let imagefilepath = Memory.alloc(0x24) + imagefilepath.writePointer(pathPtr).add(0x04) + .writeU32(path.length * 2).add(0x04) + .writeU32(path.length * 2).add(0x04) + + let picWxidPtr = Memory.alloc(contactId.length * 2 + 1) + picWxidPtr.writeUtf16String(contactId) + + let picWxid = Memory.alloc(0x0c) + picWxid.writePointer(ptr(picWxidPtr)).add(0x04) + .writeU32(contactId.length * 2).add(0x04) + .writeU32(contactId.length * 2).add(0x04) - //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)) + //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.sendPicMsg.call1 + )) + cw.putMovRegReg('edx', 'eax') //缓存 - //alias aka 'remark' in wechat - const alias = readWideString(node.add(0x80)) + cw.putSubRegImm('esp', 0x14) + cw.putMovRegAddress('eax', buffwxid) + cw.putMovRegReg('ecx', 'esp') + cw.putMovRegAddress('edi', imagefilepath) + cw.putPushReg('eax') + cw.putCallAddress(moduleBaseAddress.add( + offset.sendPicMsg.call2 + )) - //avatarUrl - const avatar = readWideString(node.add(0x138)) - //const avatar = Memory.readUtf16String(node.add(0x138).readPointer()) - //contact gender - const gender = node.add(0x18C).readU32() + 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') - const contactJson = { - id: wxid, - code: wx_code, - name: name, - alias: alias, - avatarUrl: avatar, - gender: gender, - } + cw.putMovRegAddress('edi', picWxid) //edi + cw.putCallAddress(moduleBaseAddress.add( + offset.sendPicMsg.call3 + )) - 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) + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() - const allContactJson = contactList - return allContactJson + }) + + //console.log('----------picAsm',picAsm) + const nativeativeFunction = new NativeFunction(ptr(picAsm), 'void', []) + nativeativeFunction() }) -// 009 -const getChatroomMemberInfoFunction = (() => { - const chatroomNodeAddress = getChatroomNodeAddress() - if (chatroomNodeAddress.isNull()) { return '[]' } +// 020 done +let memberNickBuffAsm = null +let nickRoomId = null +let nickMemberId = null +let nickBuff = null +const getChatroomMemberNickInfoFunction = ((memberId, roomId) => { - const node = chatroomNodeAddress.add(0x0).readPointer() - const ret = chatroomRecurse(node) + nickBuff = Memory.alloc(0x7e4) + //const nickRetAddr = Memory.alloc(0x04) + memberNickBuffAsm = Memory.alloc(Process.pageSize) + //console.log('asm address----------',memberNickBuffAsm) + nickRoomId = initidStruct(roomId) + //console.log('nick room id',nickRoomId) + nickMemberId = initStruct(memberId) - const cloneRet = JSON.stringify(ret) - chatroomNodeList.length = 0//empty - chatroomMemberList.length = 0 //empty - return cloneRet -}) + //console.log('nick nickMemberId id',nickMemberId) + //const nickStructPtr = initmsgStruct('') -// 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 -}) + Memory.patchCode(memberNickBuffAsm, Process.pageSize, code => { + var cw = new X86Writer(code, { + pc: memberNickBuffAsm + }) + cw.putPushfx() + cw.putPushax() + cw.putMovRegAddress('edi', nickRoomId) + cw.putMovRegAddress('eax', nickBuff) + cw.putMovRegReg('edx', 'edi') + cw.putPushReg('eax') + cw.putMovRegAddress('ecx', nickMemberId) + cw.putCallAddress(moduleBaseAddress.add(0xC06F10)) + cw.putAddRegImm('esp', 0x04) + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() -// 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 + const nativeativeFunction = new NativeFunction(ptr(memberNickBuffAsm), 'void', []) + nativeativeFunction() + + const nickname = readWideString(nickBuff) + console.log('----nickname', nickname) + return readWideString(nickBuff) }) // 013 @@ -808,30 +1291,6 @@ 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']) @@ -973,214 +1432,23 @@ const getQrcodeLoginData = () => { /** * 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() { - let addr - let msgType = 0 - let isMyMsg = 0 - let curTime = new Date() - try { - addr = this.context.eax//0xc30-0x08 - msgType = addr.add(0x38).readU32() - 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)) - } - } catch (err) { - console.error(curTime,'recvMsgNativeCallback at onEnter err:', err) - } - } - }) - 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) + 7A566D78 | FFB5 E8FEFFFF | push dword ptr ss:[ebp-118] | + */ +/*const writeLogNativeCallback = (() => { + const nativeCallback = new NativeCallback(() => { }, 'void', []) + const nativeCallFunction = new NativeFunction(nativeCallback, 'void', []) - 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 -}) + Interceptor.attach( + moduleBaseAddress.add(0x1576D7E), + { + onEnter() { + const addr = this.context.ebp.sub(0x114)//0xc30-0x08 + console.log('-------',addr) + + } + }) + return nativeCallback +})()*/ let nickRoomIdV6 = null let nullEdiWxidStructV6 = null @@ -1241,86 +1509,6 @@ const getChatroomMemberNickInfoV1Function = ((memberId, roomId) => { 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 */ @@ -1567,131 +1755,6 @@ const sendAttatchMsgNativeFunction = ((contactId, senderId, path, filename, size //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 @@ -1764,156 +1827,6 @@ const sendPicMsgNativeFunction = ((contactId, path) => { 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) => { diff --git a/src/wechat-sidecar.ts b/src/wechat-sidecar.ts index 8e73d49..4b8ec6c 100644 --- a/src/wechat-sidecar.ts +++ b/src/wechat-sidecar.ts @@ -37,6 +37,7 @@ import { codeRoot } from './cjs.js' const supportedVersions = { v330115:'3.3.0.115', v360000:'3.6.0.18', + v39223:'3.9.2.23', } // let initAgentScript = fs.readFileSync(path.join( @@ -58,7 +59,7 @@ try { // await detach(wechatVersion) - const currentVersion = '3.6.0.18' + const currentVersion = '3.9.2.23' switch (currentVersion) { case supportedVersions.v330115: @@ -82,6 +83,19 @@ try { 'init-agent-script.js', ), 'utf-8') break + case supportedVersions.v39223: + // initAgentScript = fs.readFileSync(path.join( + // codeRoot, + // 'src', + // 'agents', + // 'agent-script-3.6.0.18.js', + // ), 'utf-8') + initAgentScript = fs.readFileSync(path.join( + codeRoot, + 'src', + 'init-agent-script.js', + ), 'utf-8') + break default: throw new Error(`Wechat version not supported. \nWechat version: ${currentVersion}, supported version: ${JSON.stringify(supportedVersions)}`) } From ad0e0e319e31e0f91ed48ac9dd7b95958ac183ef Mon Sep 17 00:00:00 2001 From: choogoo <104893934+choogoo@users.noreply.github.com> Date: Tue, 11 Jul 2023 21:22:08 +0800 Subject: [PATCH 2/6] 3.9.2.23 init (#182) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 3.9.2.23 initt * Update init-agent-script.js * 3.9.2.23 adapter * 适配3.9.2.23 * Delete agent-script-3.9.2.23-new.js --- ...9.2.23-new.js => agent-script-3.9.2.23.js} | 1845 ++++++++--------- src/init-agent-script.js | 1845 ++++++++--------- 2 files changed, 1780 insertions(+), 1910 deletions(-) rename src/agents/{agent-script-3.9.2.23-new.js => agent-script-3.9.2.23.js} (95%) diff --git a/src/agents/agent-script-3.9.2.23-new.js b/src/agents/agent-script-3.9.2.23.js similarity index 95% rename from src/agents/agent-script-3.9.2.23-new.js rename to src/agents/agent-script-3.9.2.23.js index f706c38..9c97f9a 100644 --- a/src/agents/agent-script-3.9.2.23-new.js +++ b/src/agents/agent-script-3.9.2.23.js @@ -8,11 +8,14 @@ //const { isNullishCoalesce } = require("typescript") -//3.9.2.23 +// wechat:3.9.2.23 -// 偏移地址集合 done +// 028 done const offset = { + + hook_point: 0xd19a0b, //3.9.2.23 + myselfinfo: { offset: 0x2FFD484, //老版本微信号偏移,后面的地址,都要在这个偏移上增加 //wxid_len:0x10, @@ -23,6 +26,7 @@ const offset = { //wxcode_len:0x74 wxid_len_offset: 0x4D4 }, + contactInfo: { nodeOffset: 0x2FFDD7C, nodeRootOffset: 0x64 @@ -40,25 +44,20 @@ const offset = { call3: 0xce6640 } }; -//3.9.2.23 -// 全局配置 done +// 029 done /*------------------global-------------------------------------------*/ const availableVersion = 1661534743 ////3.9.2.23 ==0x63090217 const moduleBaseAddress = Module.getBaseAddress('WeChatWin.dll') const moduleLoad = Module.load('WeChatWin.dll') -//1575CF98 - -// 全局变量 tbd +// tbd const g_EDIPtr = moduleBaseAddress.add(0x222f38c).readPointer().add(0xD70).readPointer()// const g_EDIU32 = moduleBaseAddress.add(0x222f38c).readPointer().add(0xD70).readU32() - /*------------------global-------------------------------------------*/ /*---------------base -------------------------*/ - -// done +// 030 done let retidPtr=null let retidStruct=null const initidStruct = ((str) => { @@ -78,7 +77,7 @@ const initidStruct = ((str) => { return retidStruct }) -// done +// 031 done let retPtr = null let retStruct = null const initStruct = ((str) => { @@ -98,7 +97,7 @@ const initStruct = ((str) => { return retStruct }) -// done +// 032 done let msgstrPtr=null let msgStruct=null const initmsgStruct = ((str) => { @@ -117,7 +116,23 @@ const initmsgStruct = ((str) => { return msgStruct }) -// tbd +// 034 done +/** +* 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 +}) + +// 033 tbd let retidNullStruct = null let retidNullPtr = null const initNullIdStruct = ((str) => { @@ -137,25 +152,7 @@ const initNullIdStruct = ((str) => { return retidNullStruct }) -// done -/** -* 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 -}) - -// done -// std::string -// const str = readStringPtr(ptr).readUtf8String() +// 035 done const readStringPtr = (address) => { const addr = ptr(address) const size = addr.add(16).readU32() @@ -169,9 +166,15 @@ const readStringPtr = (address) => { 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) : '' } + 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()) @@ -180,913 +183,853 @@ const readStringPtr = (address) => { return addr } -// done +// 036 done const readString = (address) => { return readStringPtr(address).readUtf8String() } -// done +// 037 done const readWideString = (address) => { return readWStringPtr(address).readUtf16String() } +/*-----------------base-------------------------*/ + +// 041 +// 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 +} /*-----------------base-------------------------*/ +// 010 done let currentVersion = 0 -let nodeList = [] //for contact +let nodeList = [] //for contact let contactList = [] //for contact let chatroomNodeList = [] //for chatroom -let chatroomMemberList = []//for chatroom +let chatroomMemberList = [] //for chatroom let loggedIn = false -//开启日志 3.6.0.18 -// //[0x221c330+wechatwin.dll]+0xf8 -// 20220504 +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 +}) -let g_initTestAsm = null -let g_BufferEbp2C = null -let g_initECXU32 = null -let g_initECXPtr = null -let g_initEBXPtr = null -let g_initEBX = null +// 011 done +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('.') +}) -let g_attatchEBP210Buffer = null -let g_attatchPathPtr = null -let g_attatchPath = null -let g_attatchEBPAc = null -let g_attatchEBPAcBufPtr = null +// 012 done +const checkSupportedFunction = (() => { + const ver = getWechatVersionFunction() + return ver == availableVersion +}) -let g_attatchContactIdPtr = null -//let g_attatchECXBuffer = null -let g_attatchESIU32 = null +// 019 done +/** + * @Hook: recvMsg -> recvMsgNativeCallback + */ + const recvMsgNativeCallback = (() => { -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) + const nativeCallback = new NativeCallback(() => {}, 'void', ['int32', 'pointer', 'pointer', 'pointer', 'pointer', 'int32']) + const nativeativeFunction = new NativeFunction(nativeCallback, 'void', ['int32', 'pointer', 'pointer', 'pointer', 'pointer', 'int32']) - 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 + Interceptor.attach( + moduleBaseAddress.add(offset.hook_point), { + onEnter() { + const addr = this.context.ecx //0xc30-0x08 + const msgType = addr.add(0x38).readU32() + const isMyMsg = addr.add(0x3C).readU32() //add isMyMsg - console.log('------------g_initECXU32', g_initECXU32) - console.log('------------g_initESIU32', g_attatchESIU32) + if (msgType > 0) { + const talkerIdPtr = addr.add(0x48).readPointer() + //console.log('txt msg',talkerIdPtr.readUtf16String()) + const talkerIdLen = addr.add(0x48 + 0x04).readU32() * 2 + 2 - //console.log('==========g_initECXPtr',g_initECXPtr) - //console.log('==========g_EDIU32',g_EDIU32) + const myTalkerIdPtr = Memory.alloc(talkerIdLen) + Memory.copy(myTalkerIdPtr, talkerIdPtr, talkerIdLen) - //g_attatchECXBuffer = Memory.alloc(0x1024) - //Memory.copy(g_attatchECXBuffer, g_initECXPtr, 0x1024) - g_BufferEbp2C = Memory.alloc(0x48) + 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) + } - //g_initEBX = moduleBaseAddress.add(0x2251724).readPointer().readPointer() - //g_initEBXPtr = Memory.alloc(0x14).writePointer(g_initEBX) - //g_initEBXPtr.add(0x08).writePointer(g_BufferEbp2C) + // 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 - g_attatchPathPtr = Memory.alloc(attatchFile.length * 2 + 2) - g_attatchPathPtr.writeUtf16String(attatchFile) + myGroupMsgSenderIdPtr = Memory.alloc(0x10) + myGroupMsgSenderIdPtr.writeUtf16String("null") - 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----------------*/ + } else { - //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) + const groupMsgSenderIdPtr = addr.add(0x170).readPointer() + const groupMsgSenderIdLen = addr.add(0x170 + 0x04).readU32() * 2 + 2 + myGroupMsgSenderIdPtr = Memory.alloc(groupMsgSenderIdLen) + Memory.copy(myGroupMsgSenderIdPtr, groupMsgSenderIdPtr, groupMsgSenderIdLen) - /*g_attatchECXBuffer.add(0x18).writePointer(g_attatchContactIdPtr) - g_attatchECXBuffer.add(0x1C).writeU32(contactId.length*2) - .add(0x04).writeU32(contactId.length*2)*/ + } + const xmlNullPtr = addr.add(0x1f0).readU32() //3.9.2.23 + let myXmlContentPtr = null + if (xmlNullPtr == 0) { + myXmlContentPtr = Memory.alloc(0x10) + myXmlContentPtr.writeUtf16String("null") - //g_attatchESIU32 = g_EDI.toInt32() + } else { + const xmlContentPtr = addr.add(0x1f0).readPointer() //3.9.2.23 + const xmlContentLen = addr.add(0x1f0 + 0x04).readU32() * 2 + 2 + myXmlContentPtr = Memory.alloc(xmlContentLen) + Memory.copy(myXmlContentPtr, xmlContentPtr, xmlContentLen) + } - //console.log('------------g_attatchESIU32',g_attatchESIU32) - //console.log('==========g_attatchECXBuffer',g_attatchECXBuffer) + setImmediate(() => nativeativeFunction(msgType, myTalkerIdPtr, myContentPtr, myGroupMsgSenderIdPtr, myXmlContentPtr, isMyMsg)) + } + } + }) + return nativeCallback +})() - Memory.patchCode(g_initTestAsm, Process.pageSize, code => { - var cw = new X86Writer(code, { pc: g_initTestAsm }) - cw.putPushfx() - cw.putPushax() - //cw.putMovRegAddress('eax', g_attatchEBP210Buffer) +// 003 done +const getBaseNodeAddress = (() => { + return moduleBaseAddress.add(offset.contactInfo.nodeOffset).readPointer() +}) - /*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))*/ +// 004 done +const getHeaderNodeAddress = (() => { + const baseAddress = getBaseNodeAddress() + //console.log('baseAddress',baseAddress) + if (baseAddress.isNull()) { + return baseAddress + } - //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))*/ + //console.log('HeaderNodeAddress',baseAddress.add(offset.handle_offset).readPointer()) + return baseAddress.add(offset.contactInfo.nodeRootOffset).readPointer() +}) +// 006 done +const getMyselfInfoFunction = (() => { - /*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))*/ + let ptr = 0 + let wx_code = '' + let wx_id = '' + let wx_name = '' + let head_img_url = '' + const base = moduleBaseAddress.add(offset.myselfinfo.offset) + const wxid_len = base.add(offset.myselfinfo.wxid_len_offset).readU32() - /*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)) + if (wxid_len === 0x13) { // 新版本微信 + wx_id = base.readPointer().readAnsiString(wxid_len) + wx_code = base.add(offset.myselfinfo.wxcode_new).readAnsiString() + } else { + wx_id = readString(base) + wx_code = wx_id + } - /** g_attatchEBPAc*/ - //cw.putMovRegNearPtr('eax', g_attatchEBPAc) - //cw.putMovNearPtrReg(g_attatchEBPAc.add(0xc), 'eax') - /** g_attatchEBPAc*/ + wx_name = readString(base.add(offset.myselfinfo.wx_nick_name)) + const img_addr = base.add(offset.myselfinfo.head_img_url).readPointer() + const img_len = base.add(offset.myselfinfo.head_img_url_len).readU32() - //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))*/ + head_img_url = img_addr.readAnsiString(img_len) - cw.putPopax() - cw.putPopfx() - cw.putRet() - cw.flush() + const myself = { + id: wx_id, + code: wx_code, + name: wx_name, + head_img_url: head_img_url, + }; - }) + return JSON.stringify(myself) - const nativeativeFunction = new NativeFunction(ptr(g_initTestAsm), 'void', []) - nativeativeFunction() }) +// 043 done +const recurseNew = ((node) => { + const headerNodeAddress = getHeaderNodeAddress() + if (headerNodeAddress.isNull()) { + return + } -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 + if (node.equals(headerNodeAddress)) { + return + } - g_personal_detail_asm = Memory.alloc(Process.pageSize) - g_personal_detail_ebx = moduleBaseAddress.add(0x222F38C).readPointer().add(0xFB8).toInt32() + for (const item in nodeList) { + if (node.equals(nodeList[item])) { + return + } + } - 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) + nodeList.push(node) + const id = readString(node.add(0x8)) + //wxid, format relates to registration method + const wxid = readWideString(node.add(0x30)) + //console.log('-----------',wxid) - 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() + //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)) - cw.putCallAddress(moduleBaseAddress.add(0x9A000)) + //custom Nickname + const name = readWideString(node.add(0x8c)) - //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)) + //alias aka 'remark' in wechat + //const alias = readWideString(node.add(0x80)) - cw.putPopax() - cw.putPopfx() - cw.putRet() - cw.flush() + //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,*/ + } - const nativeativeFunction = new NativeFunction(ptr(g_personal_detail_asm), 'void', []) - nativeativeFunction() + 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 writeLogNativeCallback = (() => { -// const nativeCallback = new NativeCallback(() => { }, 'void', []) -// const nativeCallFunction = new NativeFunction(nativeCallback, 'void', []) + const allContactJson = contactList + return allContactJson -// 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 +// 044 done +const getContactNativeFunction = (() => { + const headerNodeAddress = getHeaderNodeAddress() + //console.log('headerNodeAddress',headerNodeAddress) -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) + if (headerNodeAddress.isNull()) { + return '[]' + } - attatchFirstECX = Memory.alloc(0x28) - //const attatchSecondEcx = Memory.alloc(0x14) + const node = headerNodeAddress.add(0x0).readPointer() + const ret = recurseNew(node) - const contactIdLength = contactId.length * 2 + 2//edx - const contractIdActLength = contactId.length + //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 - gattatchReceiveIdPtr = Memory.alloc(contactId.length * 2 + 2) - gattatchReceiveIdPtr.writeUtf16String(contactId) + return cloneRet +}) - 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*/ +// 0xx done +const getChatroomNodeAddress = (() => { + const baseAddress = moduleBaseAddress.add(offset.chatroomInfo.nodeOffset).readPointer() + if (baseAddress.isNull()) { + return baseAddress + } + return baseAddress.add(offset.chatroomInfo.nodeRootOffset).readPointer() +}) - 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() +// 008chatroom member done +const chatroomRecurse = ((node) => { + const chatroomNodeAddress = getChatroomNodeAddress() + if (chatroomNodeAddress.isNull()) { + return + } + if (node.equals(chatroomNodeAddress)) { + return + } -}) -// 001 -const getTestInfoFunction = ((addr) => { - const nativeativeFunction = new NativeFunction(ptr(addr), 'void', []) - nativeativeFunction() + for (const item in chatroomNodeList) { + if (node.equals(chatroomNodeList[item])) { + return + } + } - //00CFE484 + chatroomNodeList.push(node) + const roomid = readWideString(node.add(0x10)) + const len = node.add(0x54).readU32() // + //const memberJson={} + if (len > 4) { // + const memberStr = readString(node.add(0x44)) + if (memberStr.length > 0) { + const memberList = memberStr.split(/[\\^][G]/) + const memberJson = { + roomid: roomid, + roomMember: memberList + } - /*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('============') + chatroomMemberList.push(memberJson) } - })*/ -}) + } -// 002get global data + const leftNode = node.add(0x0).readPointer() + const centerNode = node.add(0x04).readPointer() + const rightNode = node.add(0x08).readPointer() -const isLoggedInFunction = (() => { - loggedIn = moduleBaseAddress.add(offset.is_logged_in_offset).readU32() - return !!loggedIn -}) + chatroomRecurse(leftNode) + chatroomRecurse(centerNode) + chatroomRecurse(rightNode) -// 007 缺失,请标注已废弃或者其他原因 -const getMyselfIdFunction = (() => { + const allChatroomMemberJson = chatroomMemberList + return allChatroomMemberJson +}) - let wx_id = readString(moduleBaseAddress.add(offset.wxid_offset)) +// 009 done +const getChatroomMemberInfoFunction = (() => { + const chatroomNodeAddress = getChatroomNodeAddress() + if (chatroomNodeAddress.isNull()) { + return '[]' + } - return wx_id + 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 }) -// 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') +// 024 done +/** + * sendMsgNativeFunction + * send text message + * @param {string} talkerId = wxid or roomid + * @param {string} content + */ + const sendMsgNativeFunction = ((talkerId, content) => { - return addr -} + const txtAsm = Memory.alloc(Process.pageSize) + //const buffwxid = Memory.alloc(0x20) -//contact -const recurse = ((node) => { - const headerNodeAddress = getHeaderNodeAddress() - if (headerNodeAddress.isNull()) { return } - if (node.equals(headerNodeAddress)) { return } + let wxidPtr = Memory.alloc(talkerId.length * 2 + 2) + wxidPtr.writeUtf16String(talkerId) - for (const item in nodeList) { - if (node.equals(nodeList[item])) { - return - } - } + let picWxid = Memory.alloc(0x0c) + picWxid.writePointer(ptr(wxidPtr)).add(0x04) + .writeU32(talkerId.length * 2).add(0x04) + .writeU32(talkerId.length * 2).add(0x04) + let contentPtr = Memory.alloc(content.length * 2 + 2) + contentPtr.writeUtf16String(content) - nodeList.push(node) - //wxid, format relates to registration method - const wxid = readWideString(node.add(0x38)) + const sizeOfStringStruct = Process.pointerSize * 5 + let contentStruct = Memory.alloc(sizeOfStringStruct) - //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)) + contentStruct + .writePointer(contentPtr).add(0x4) + .writeU32(content.length).add(0x4) + .writeU32(content.length * 2) - //custom Nickname - const name = readWideString(node.add(0x94)) - //alias aka 'remark' in wechat - const alias = readWideString(node.add(0x80)) + const ecxBuffer = Memory.alloc(0x2d8) - //avatarUrl - const avatar = readWideString(node.add(0x138)) - //const avatar = Memory.readUtf16String(node.add(0x138).readPointer()) - //contact gender - const gender = node.add(0x18C).readU32() + Memory.patchCode(txtAsm, Process.pageSize, code => { + var cw = new X86Writer(code, { + pc: txtAsm + }) + cw.putPushfx() + cw.putPushax() - const contactJson = { - id: wxid, - code: wx_code, - name: name, - alias: alias, - avatarUrl: avatar, - gender: gender, - } + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x1) + cw.putPushU32(0x0) - contactList.push(contactJson) + //cw.putMovRegReg - const leftNode = node.add(0x0).readPointer() - const centerNode = node.add(0x04).readPointer() - const rightNode = node.add(0x08).readPointer() + cw.putMovRegAddress('eax', contentStruct) + cw.putPushReg('eax') - recurse(leftNode) - recurse(centerNode) - recurse(rightNode) + cw.putMovRegAddress('edx', picWxid) //room_id - const allContactJson = contactList - return allContactJson + cw.putMovRegAddress('ecx', ecxBuffer) + cw.putCallAddress(moduleBaseAddress.add( + offset.sendTxtMsg.callOffset + )) -}) + cw.putAddRegImm('esp', 0x18) + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() -// 010 done -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 done -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('.') -}) + console.log('----------txtAsm', txtAsm) + const nativeativeFunction = new NativeFunction(ptr(txtAsm), 'void', []) + nativeativeFunction() -// 012 done -const checkSupportedFunction = (() => { - const ver = getWechatVersionFunction() - return ver == availableVersion }) +// 023 done /** - * @Hook: recvMsg -> recvMsgNativeCallback - */ +* send at msg +*/ +let asmAtMsg = null +let roomid_, msg_, wxid_, atid_ +let ecxBuffer +const sendAtMsgNativeFunction = ((roomId, text, contactId,nickname) => { -// 019 done -const recvMsgNativeCallback = (() => { + asmAtMsg = Memory.alloc(Process.pageSize) + ecxBuffer = Memory.alloc(0x3b0) + const atContent = '@'+nickname+' '+text - const nativeCallback = new NativeCallback(() => {}, 'void', ['int32', 'pointer', 'pointer', 'pointer', 'pointer', 'int32']) - const nativeativeFunction = new NativeFunction(nativeCallback, 'void', ['int32', 'pointer', 'pointer', 'pointer', 'pointer', 'int32']) + roomid_ = initStruct(roomId) + wxid_ = initidStruct(contactId) + msg_ = initmsgStruct(atContent) + atid_ = initAtMsgStruct(wxid_) - Interceptor.attach( - moduleBaseAddress.add(offset.hook_point), { - onEnter() { - const addr = this.context.ecx //0xc30-0x08 - const msgType = addr.add(0x38).readU32() - const isMyMsg = addr.add(0x3C).readU32() //add isMyMsg + Memory.patchCode(asmAtMsg, Process.pageSize, code => { + var cw = new X86Writer(code, { + pc: asmAtMsg + }) + cw.putPushfx() + cw.putPushax() - if (msgType > 0) { + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x1) + //cw.putPushU32(0x0) + cw.putMovRegAddress('eax', atid_) + cw.putPushReg('eax') - const talkerIdPtr = addr.add(0x48).readPointer() - //console.log('txt msg',talkerIdPtr.readUtf16String()) - const talkerIdLen = addr.add(0x48 + 0x04).readU32() * 2 + 2 + //cw.putMovRegReg - const myTalkerIdPtr = Memory.alloc(talkerIdLen) - Memory.copy(myTalkerIdPtr, talkerIdPtr, talkerIdLen) + cw.putMovRegAddress('eax', msg_) + cw.putPushReg('eax') + cw.putMovRegAddress('edx', roomid_) //room_id - 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) - } + cw.putMovRegAddress('ecx', ecxBuffer) + cw.putCallAddress(moduleBaseAddress.add( + offset.sendTxtMsg.callOffset + )) - // 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 + cw.putAddRegImm('esp', 0x18) + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() - myGroupMsgSenderIdPtr = Memory.alloc(0x10) - myGroupMsgSenderIdPtr.writeUtf16String("null") + }) - } else { + //console.log('----------txtAsm', asmAtMsg) + const nativeativeFunction = new NativeFunction(ptr(asmAtMsg), 'void', []) + nativeativeFunction() - const groupMsgSenderIdPtr = addr.add(0x170).readPointer() - const groupMsgSenderIdLen = addr.add(0x170 + 0x04).readU32() * 2 + 2 - myGroupMsgSenderIdPtr = Memory.alloc(groupMsgSenderIdLen) - Memory.copy(myGroupMsgSenderIdPtr, groupMsgSenderIdPtr, groupMsgSenderIdLen) +}) - } +// 022 done +/** + * + * @param {*} contactId + * @param {*} path + */ + const sendPicMsgNativeFunction = ((contactId, path) => { - const xmlNullPtr = addr.add(0x1f0).readU32() //3.9.2.23 - let myXmlContentPtr = null - if (xmlNullPtr == 0) { + const picAsm = Memory.alloc(Process.pageSize) + const buffwxid = Memory.alloc(0x20) + const picbuff = Memory.alloc(0x2D8) - myXmlContentPtr = Memory.alloc(0x10) - myXmlContentPtr.writeUtf16String("null") + let pathPtr = Memory.alloc(path.length * 2 + 1) + pathPtr.writeUtf16String(path) - } else { - const xmlContentPtr = addr.add(0x1f0).readPointer() //3.9.2.23 + let imagefilepath = Memory.alloc(0x24) + imagefilepath.writePointer(pathPtr).add(0x04) + .writeU32(path.length * 2).add(0x04) + .writeU32(path.length * 2).add(0x04) - const xmlContentLen = addr.add(0x1f0 + 0x04).readU32() * 2 + 2 - myXmlContentPtr = Memory.alloc(xmlContentLen) - Memory.copy(myXmlContentPtr, xmlContentPtr, xmlContentLen) - } + let picWxidPtr = Memory.alloc(contactId.length * 2 + 1) + picWxidPtr.writeUtf16String(contactId) - setImmediate(() => nativeativeFunction(msgType, myTalkerIdPtr, myContentPtr, myGroupMsgSenderIdPtr, myXmlContentPtr, isMyMsg)) - } - } - }) - return nativeCallback -})() + let picWxid = Memory.alloc(0x0c) + picWxid.writePointer(ptr(picWxidPtr)).add(0x04) + .writeU32(contactId.length * 2).add(0x04) + .writeU32(contactId.length * 2).add(0x04) -// 003get myself info done -const getBaseNodeAddress = (() => { - return moduleBaseAddress.add(offset.contactInfo.nodeOffset).readPointer() -}) -// 004 done -const getHeaderNodeAddress = (() => { - const baseAddress = getBaseNodeAddress() - //console.log('baseAddress',baseAddress) - if (baseAddress.isNull()) { - return baseAddress - } + //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.sendPicMsg.call1 + )) + cw.putMovRegReg('edx', 'eax') //缓存 - //console.log('HeaderNodeAddress',baseAddress.add(offset.handle_offset).readPointer()) - return baseAddress.add(offset.contactInfo.nodeRootOffset).readPointer() -}) + cw.putSubRegImm('esp', 0x14) + cw.putMovRegAddress('eax', buffwxid) + cw.putMovRegReg('ecx', 'esp') + cw.putMovRegAddress('edi', imagefilepath) + cw.putPushReg('eax') + cw.putCallAddress(moduleBaseAddress.add( + offset.sendPicMsg.call2 + )) -// 006 done -const getMyselfInfoFunction = (() => { + 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') - let ptr = 0 - let wx_code = '' - let wx_id = '' - let wx_name = '' - let head_img_url = '' + cw.putMovRegAddress('edi', picWxid) //edi + cw.putCallAddress(moduleBaseAddress.add( + offset.sendPicMsg.call3 + )) - const base = moduleBaseAddress.add(offset.myselfinfo.offset) - const wxid_len = base.add(offset.myselfinfo.wxid_len_offset).readU32() - if (wxid_len === 0x13) { // 新版本微信 - wx_id = base.readPointer().readAnsiString(wxid_len) - wx_code = base.add(offset.myselfinfo.wxcode_new).readAnsiString() - } else { - wx_id = readString(base) - wx_code = wx_id - } + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() - wx_name = readString(base.add(offset.myselfinfo.wx_nick_name)) - const img_addr = base.add(offset.myselfinfo.head_img_url).readPointer() - const img_len = base.add(offset.myselfinfo.head_img_url_len).readU32() + }) - head_img_url = img_addr.readAnsiString(img_len) + //console.log('----------picAsm',picAsm) + const nativeativeFunction = new NativeFunction(ptr(picAsm), 'void', []) + nativeativeFunction() - const myself = { - id: wx_id, - code: wx_code, - name: wx_name, - head_img_url: head_img_url, - }; +}) - return JSON.stringify(myself) +// 020 done +let memberNickBuffAsm = null +let nickRoomId = null +let nickMemberId = null +let nickBuff = null +const getChatroomMemberNickInfoFunction = ((memberId, roomId) => { -}) + nickBuff = Memory.alloc(0x7e4) + //const nickRetAddr = Memory.alloc(0x04) + memberNickBuffAsm = Memory.alloc(Process.pageSize) + //console.log('asm address----------',memberNickBuffAsm) + nickRoomId = initidStruct(roomId) + //console.log('nick room id',nickRoomId) + nickMemberId = initStruct(memberId) -// done -const recurseNew = ((node) => { - const headerNodeAddress = getHeaderNodeAddress() - if (headerNodeAddress.isNull()) { - return - } + //console.log('nick nickMemberId id',nickMemberId) + //const nickStructPtr = initmsgStruct('') - if (node.equals(headerNodeAddress)) { - return - } + Memory.patchCode(memberNickBuffAsm, Process.pageSize, code => { + var cw = new X86Writer(code, { + pc: memberNickBuffAsm + }) + cw.putPushfx() + cw.putPushax() + cw.putMovRegAddress('edi', nickRoomId) + cw.putMovRegAddress('eax', nickBuff) + cw.putMovRegReg('edx', 'edi') + cw.putPushReg('eax') + cw.putMovRegAddress('ecx', nickMemberId) + cw.putCallAddress(moduleBaseAddress.add(0xC06F10)) + cw.putAddRegImm('esp', 0x04) + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() - for (const item in nodeList) { - if (node.equals(nodeList[item])) { - return - } - } + }) + const nativeativeFunction = new NativeFunction(ptr(memberNickBuffAsm), 'void', []) + nativeativeFunction() - nodeList.push(node) - const id = readString(node.add(0x8)) - //wxid, format relates to registration method - const wxid = readWideString(node.add(0x30)) - //console.log('-----------',wxid) + const nickname = readWideString(nickBuff) + console.log('----nickname', nickname) + return readWideString(nickBuff) +}) +/* 由此之后是3.9.2.23中缺失的未实现方法 */ - //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)) +// 038 初始化全局变量 tbd +let g_initTestAsm = null +let g_BufferEbp2C = null +let g_initECXU32 = null +let g_initECXPtr = null +let g_initEBXPtr = null +let g_initEBX = null - //custom Nickname - const name = readWideString(node.add(0x8c)) +let g_attatchEBP210Buffer = null +let g_attatchPathPtr = null +let g_attatchPath = null +let g_attatchEBPAc = null +let g_attatchEBPAcBufPtr = null - //alias aka 'remark' in wechat - //const alias = readWideString(node.add(0x80)) +let g_attatchContactIdPtr = null +//let g_attatchECXBuffer = null +let g_attatchESIU32 = null - //avatarUrl - //const avatar = readWideString(node.add(0x138)) - //const avatar = Memory.readUtf16String(node.add(0x138).readPointer()) - //contact gender - //const gender = node.add(0x18C).readU32() +let g_initECXTempPtr = null +const initGlobal = ((contactId, attatchFile) => { - const contactJson = { - id1: id, - id: wxid, - name: name, - /*code: wx_code, - name: name, - alias: alias, - avatarUrl: avatar, - gender: gender,*/ - } + //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) - contactList.push(contactJson) + 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 - const leftNode = node.add(0x0).readPointer() - const centerNode = node.add(0x04).readPointer() - //const rightNode = node.add(0x08).readPointer() + console.log('------------g_initECXU32', g_initECXU32) + console.log('------------g_initESIU32', g_attatchESIU32) - recurseNew(leftNode) - recurseNew(centerNode) - //recurse(rightNode) - const allContactJson = contactList - return allContactJson + //console.log('==========g_initECXPtr',g_initECXPtr) + //console.log('==========g_EDIU32',g_EDIU32) -}) + //g_attatchECXBuffer = Memory.alloc(0x1024) + //Memory.copy(g_attatchECXBuffer, g_initECXPtr, 0x1024) -// done ? -const getContactNativeFunction = (() => { - const headerNodeAddress = getHeaderNodeAddress() - //console.log('headerNodeAddress',headerNodeAddress) + g_BufferEbp2C = Memory.alloc(0x48) - if (headerNodeAddress.isNull()) { - return '[]' - } + //g_initEBX = moduleBaseAddress.add(0x2251724).readPointer().readPointer() + //g_initEBXPtr = Memory.alloc(0x14).writePointer(g_initEBX) + //g_initEBXPtr.add(0x08).writePointer(g_BufferEbp2C) - const node = headerNodeAddress.add(0x0).readPointer() - const ret = recurseNew(node) + g_attatchPathPtr = Memory.alloc(attatchFile.length * 2 + 2) + g_attatchPathPtr.writeUtf16String(attatchFile) - //console.log(ret) + 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----------------*/ - 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 + //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) - return cloneRet -}) + /*g_attatchECXBuffer.add(0x18).writePointer(g_attatchContactIdPtr) + g_attatchECXBuffer.add(0x1C).writeU32(contactId.length*2) + .add(0x04).writeU32(contactId.length*2)*/ -// 005 done -const getChatroomNodeAddress = (() => { - const baseAddress = moduleBaseAddress.add(offset.chatroomInfo.nodeOffset).readPointer() - if (baseAddress.isNull()) { - return baseAddress - } - return baseAddress.add(offset.chatroomInfo.nodeRootOffset).readPointer() -}) -// 008chatroom member done -const chatroomRecurse = ((node) => { - const chatroomNodeAddress = getChatroomNodeAddress() - if (chatroomNodeAddress.isNull()) { - return - } - if (node.equals(chatroomNodeAddress)) { - return - } + //g_attatchESIU32 = g_EDI.toInt32() - for (const item in chatroomNodeList) { - if (node.equals(chatroomNodeList[item])) { - return - } - } - chatroomNodeList.push(node) - const roomid = readWideString(node.add(0x10)) + //console.log('------------g_attatchESIU32',g_attatchESIU32) + //console.log('==========g_attatchECXBuffer',g_attatchECXBuffer) - const len = node.add(0x54).readU32() // - //const memberJson={} - if (len > 4) { // - const memberStr = readString(node.add(0x44)) - if (memberStr.length > 0) { - const memberList = memberStr.split(/[\\^][G]/) - const memberJson = { - roomid: roomid, - roomMember: memberList - } + Memory.patchCode(g_initTestAsm, Process.pageSize, code => { + var cw = new X86Writer(code, { pc: g_initTestAsm }) + cw.putPushfx() + cw.putPushax() + //cw.putMovRegAddress('eax', g_attatchEBP210Buffer) - chatroomMemberList.push(memberJson) - } + /*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) - const leftNode = node.add(0x0).readPointer() - const centerNode = node.add(0x04).readPointer() - const rightNode = node.add(0x08).readPointer() + /*cw.putPushU32(0) + cw.putMovRegAddress('eax', g_attatchPathPtr) + cw.putPushReg('eax') + cw.putPushU32(3) + cw.putMovRegAddress('ecx', g_attatchEBP210Buffer) + cw.putCallAddress(moduleBaseAddress.add(0x130220))*/ - chatroomRecurse(leftNode) - chatroomRecurse(centerNode) - chatroomRecurse(rightNode) - const allChatroomMemberJson = chatroomMemberList - return allChatroomMemberJson -}) + /*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))*/ -// 009 done -const getChatroomMemberInfoFunction = (() => { - const chatroomNodeAddress = getChatroomNodeAddress() - if (chatroomNodeAddress.isNull()) { - return '[]' - } - const node = chatroomNodeAddress.add(0x0).readPointer() - const ret = chatroomRecurse(node) + /*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)) - const cloneRet = JSON.stringify(ret) - chatroomNodeList.length = 0 //empty - chatroomMemberList.length = 0 //empty - return cloneRet -}) + /** g_attatchEBPAc*/ + //cw.putMovRegNearPtr('eax', g_attatchEBPAc) + //cw.putMovNearPtrReg(g_attatchEBPAc.add(0xc), 'eax') + /** g_attatchEBPAc*/ -// 024 done -/** - * sendMsgNativeFunction - * send text message - * @param {string} talkerId = wxid or roomid - * @param {string} content - */ - const sendMsgNativeFunction = ((talkerId, content) => { - const txtAsm = Memory.alloc(Process.pageSize) - //const buffwxid = Memory.alloc(0x20) + //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() - let wxidPtr = Memory.alloc(talkerId.length * 2 + 2) - wxidPtr.writeUtf16String(talkerId) + }) - let picWxid = Memory.alloc(0x0c) - picWxid.writePointer(ptr(wxidPtr)).add(0x04) - .writeU32(talkerId.length * 2).add(0x04) - .writeU32(talkerId.length * 2).add(0x04) + const nativeativeFunction = new NativeFunction(ptr(g_initTestAsm), 'void', []) + nativeativeFunction() +}) - let contentPtr = Memory.alloc(content.length * 2 + 2) - contentPtr.writeUtf16String(content) +// 039 +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 - const sizeOfStringStruct = Process.pointerSize * 5 - let contentStruct = Memory.alloc(sizeOfStringStruct) + g_personal_detail_asm = Memory.alloc(Process.pageSize) + g_personal_detail_ebx = moduleBaseAddress.add(0x222F38C).readPointer().add(0xFB8).toInt32() - contentStruct - .writePointer(contentPtr).add(0x4) - .writeU32(content.length).add(0x4) - .writeU32(content.length * 2) + 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) - const ecxBuffer = Memory.alloc(0x2d8) + console.log('-----------address----------', g_personal_detail_asm) - Memory.patchCode(txtAsm, Process.pageSize, code => { - var cw = new X86Writer(code, { - pc: txtAsm - }) + Memory.patchCode(g_personal_detail_asm, Process.pageSize, code => { + var cw = new X86Writer(code, { pc: g_personal_detail_asm }) cw.putPushfx() cw.putPushax() - cw.putPushU32(0x0) - cw.putPushU32(0x0) - cw.putPushU32(0x0) - cw.putPushU32(0x1) - cw.putPushU32(0x0) - - //cw.putMovRegReg + cw.putCallAddress(moduleBaseAddress.add(0x9A000)) - cw.putMovRegAddress('eax', contentStruct) + //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.putMovRegAddress('edx', picWxid) //room_id - - cw.putMovRegAddress('ecx', ecxBuffer) - cw.putCallAddress(moduleBaseAddress.add( - offset.sendTxtMsg.callOffset - )) - - cw.putAddRegImm('esp', 0x18) cw.putPopax() cw.putPopfx() cw.putRet() @@ -1094,59 +1037,154 @@ const getChatroomMemberInfoFunction = (() => { }) - console.log('----------txtAsm', txtAsm) - const nativeativeFunction = new NativeFunction(ptr(txtAsm), 'void', []) + const nativeativeFunction = new NativeFunction(ptr(g_personal_detail_asm), 'void', []) nativeativeFunction() + }) -// 023 done +// 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 +// })() + +// 040 /** -* send at msg -*/ -let asmAtMsg = null -let roomid_, msg_, wxid_, atid_ -let ecxBuffer -const sendAtMsgNativeFunction = ((roomId, text, contactId,nickname) => { + * 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 - asmAtMsg = Memory.alloc(Process.pageSize) - ecxBuffer = Memory.alloc(0x3b0) +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) - const atContent = '@'+nickname+' '+text + attatchFirstECX = Memory.alloc(0x28) + //const attatchSecondEcx = Memory.alloc(0x14) - roomid_ = initStruct(roomId) - wxid_ = initidStruct(contactId) - msg_ = initmsgStruct(atContent) - atid_ = initAtMsgStruct(wxid_) + const contactIdLength = contactId.length * 2 + 2//edx + const contractIdActLength = contactId.length - Memory.patchCode(asmAtMsg, Process.pageSize, code => { - var cw = new X86Writer(code, { - pc: asmAtMsg - }) + + 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.putPushU32(0x0) - cw.putPushU32(0x0) - cw.putPushU32(0x0) - cw.putPushU32(0x1) - //cw.putPushU32(0x0) - cw.putMovRegAddress('eax', atid_) + + cw.putMovRegAddress('esi', attatchESIbuf) + + cw.putMovRegAddress('ecx', attatchFirstECX.add(0x14)) + cw.putMovRegAddress('eax', gattatchFile) cw.putPushReg('eax') + cw.putCallAddress(moduleBaseAddress.add(0x701DC0)) - //cw.putMovRegReg - cw.putMovRegAddress('eax', msg_) + cw.putMovRegAddress('ecx', attatchFirstECX) + cw.putMovRegU32('eax', contactIdLength) cw.putPushReg('eax') + cw.putPushU32(0) + cw.putCallAddress(moduleBaseAddress.add(0x1a11c83)) + cw.putAddRegImm('esp', 0x8) - cw.putMovRegAddress('edx', roomid_) //room_id + 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.putMovRegAddress('ecx', ecxBuffer) - cw.putCallAddress(moduleBaseAddress.add( - offset.sendTxtMsg.callOffset - )) + //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.putAddRegImm('esp', 0x18) cw.putPopax() cw.putPopfx() cw.putRet() @@ -1154,134 +1192,103 @@ const sendAtMsgNativeFunction = ((roomId, text, contactId,nickname) => { }) - //console.log('----------txtAsm', asmAtMsg) - const nativeativeFunction = new NativeFunction(ptr(asmAtMsg), 'void', []) + const nativeativeFunction = new NativeFunction(ptr(attatchTestAsm), 'void', []) nativeativeFunction() + }) -// 022 done -/** - * - * @param {*} contactId - * @param {*} path - */ - const sendPicMsgNativeFunction = ((contactId, path) => { +// 001 +const getTestInfoFunction = ((addr) => { + const nativeativeFunction = new NativeFunction(ptr(addr), 'void', []) + nativeativeFunction() - const picAsm = Memory.alloc(Process.pageSize) - const buffwxid = Memory.alloc(0x20) - const picbuff = Memory.alloc(0x2D8) + //00CFE484 - let pathPtr = Memory.alloc(path.length * 2 + 1) - pathPtr.writeUtf16String(path) - let imagefilepath = Memory.alloc(0x24) - imagefilepath.writePointer(pathPtr).add(0x04) - .writeU32(path.length * 2).add(0x04) - .writeU32(path.length * 2).add(0x04) + /*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('============') + } + })*/ - let picWxidPtr = Memory.alloc(contactId.length * 2 + 1) - picWxidPtr.writeUtf16String(contactId) +}) - let picWxid = Memory.alloc(0x0c) - picWxid.writePointer(ptr(picWxidPtr)).add(0x04) - .writeU32(contactId.length * 2).add(0x04) - .writeU32(contactId.length * 2).add(0x04) +// 002 +const isLoggedInFunction = (() => { + loggedIn = moduleBaseAddress.add(offset.is_logged_in_offset).readU32() + return !!loggedIn +}) +// 007 获得当前账号信息 +const getMyselfIdFunction = (() => { - //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.sendPicMsg.call1 - )) - cw.putMovRegReg('edx', 'eax') //缓存 + let wx_id = readString(moduleBaseAddress.add(offset.wxid_offset)) - cw.putSubRegImm('esp', 0x14) - cw.putMovRegAddress('eax', buffwxid) - cw.putMovRegReg('ecx', 'esp') - cw.putMovRegAddress('edi', imagefilepath) - cw.putPushReg('eax') - cw.putCallAddress(moduleBaseAddress.add( - offset.sendPicMsg.call2 - )) + return wx_id - 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.sendPicMsg.call3 - )) +//contact +// 042 +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 + } + } - cw.putPopax() - cw.putPopfx() - cw.putRet() - cw.flush() - }) + nodeList.push(node) + //wxid, format relates to registration method + const wxid = readWideString(node.add(0x38)) - //console.log('----------picAsm',picAsm) - const nativeativeFunction = new NativeFunction(ptr(picAsm), 'void', []) - nativeativeFunction() + //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)) -// 020 done -let memberNickBuffAsm = null -let nickRoomId = null -let nickMemberId = null -let nickBuff = null -const getChatroomMemberNickInfoFunction = ((memberId, roomId) => { + //alias aka 'remark' in wechat + const alias = readWideString(node.add(0x80)) - nickBuff = Memory.alloc(0x7e4) - //const nickRetAddr = Memory.alloc(0x04) - memberNickBuffAsm = Memory.alloc(Process.pageSize) - //console.log('asm address----------',memberNickBuffAsm) - nickRoomId = initidStruct(roomId) - //console.log('nick room id',nickRoomId) - nickMemberId = initStruct(memberId) + //avatarUrl + const avatar = readWideString(node.add(0x138)) + //const avatar = Memory.readUtf16String(node.add(0x138).readPointer()) + //contact gender + const gender = node.add(0x18C).readU32() - //console.log('nick nickMemberId id',nickMemberId) - //const nickStructPtr = initmsgStruct('') + const contactJson = { + id: wxid, + code: wx_code, + name: name, + alias: alias, + avatarUrl: avatar, + gender: gender, + } - Memory.patchCode(memberNickBuffAsm, Process.pageSize, code => { - var cw = new X86Writer(code, { - pc: memberNickBuffAsm - }) - cw.putPushfx() - cw.putPushax() - cw.putMovRegAddress('edi', nickRoomId) - cw.putMovRegAddress('eax', nickBuff) - cw.putMovRegReg('edx', 'edi') - cw.putPushReg('eax') - cw.putMovRegAddress('ecx', nickMemberId) - cw.putCallAddress(moduleBaseAddress.add(0xC06F10)) - cw.putAddRegImm('esp', 0x04) - cw.putPopax() - cw.putPopfx() - cw.putRet() - cw.flush() + contactList.push(contactJson) - }) + const leftNode = node.add(0x0).readPointer() + const centerNode = node.add(0x04).readPointer() + const rightNode = node.add(0x08).readPointer() - const nativeativeFunction = new NativeFunction(ptr(memberNickBuffAsm), 'void', []) - nativeativeFunction() + recurse(leftNode) + recurse(centerNode) + recurse(rightNode) + + const allContactJson = contactList + return allContactJson - const nickname = readWideString(nickBuff) - console.log('----nickname', nickname) - return readWideString(nickBuff) }) // 013 @@ -1428,13 +1435,13 @@ const getQrcodeLoginData = () => { return json } - +// 045 /** * 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 writeLogNativeCallback = (() => { const nativeCallback = new NativeCallback(() => { }, 'void', []) const nativeCallFunction = new NativeFunction(nativeCallback, 'void', []) @@ -1448,8 +1455,9 @@ const getQrcodeLoginData = () => { } }) return nativeCallback -})()*/ +})() +// 046 let nickRoomIdV6 = null let nullEdiWxidStructV6 = null let nickMemberIdStructV6 = null @@ -1509,6 +1517,7 @@ const getChatroomMemberNickInfoV1Function = ((memberId, roomId) => { return readWideString(nullEdiWxidStructV6) }) +// 021 /** * send attatch */ @@ -1550,8 +1559,6 @@ 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) @@ -1755,78 +1762,6 @@ const sendAttatchMsgNativeFunction = ((contactId, senderId, path, filename, size //console.log('-------',attatchEbp1C.add(0x4).readPointer()) //console.log('-------',attatchEbp1C.add(0x8).readPointer()) }) -/*------------------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() - -})*/ // 025 const callLoginQrcodeFunction = ((forceRefresh = false) => { diff --git a/src/init-agent-script.js b/src/init-agent-script.js index f706c38..9c97f9a 100644 --- a/src/init-agent-script.js +++ b/src/init-agent-script.js @@ -8,11 +8,14 @@ //const { isNullishCoalesce } = require("typescript") -//3.9.2.23 +// wechat:3.9.2.23 -// 偏移地址集合 done +// 028 done const offset = { + + hook_point: 0xd19a0b, //3.9.2.23 + myselfinfo: { offset: 0x2FFD484, //老版本微信号偏移,后面的地址,都要在这个偏移上增加 //wxid_len:0x10, @@ -23,6 +26,7 @@ const offset = { //wxcode_len:0x74 wxid_len_offset: 0x4D4 }, + contactInfo: { nodeOffset: 0x2FFDD7C, nodeRootOffset: 0x64 @@ -40,25 +44,20 @@ const offset = { call3: 0xce6640 } }; -//3.9.2.23 -// 全局配置 done +// 029 done /*------------------global-------------------------------------------*/ const availableVersion = 1661534743 ////3.9.2.23 ==0x63090217 const moduleBaseAddress = Module.getBaseAddress('WeChatWin.dll') const moduleLoad = Module.load('WeChatWin.dll') -//1575CF98 - -// 全局变量 tbd +// tbd const g_EDIPtr = moduleBaseAddress.add(0x222f38c).readPointer().add(0xD70).readPointer()// const g_EDIU32 = moduleBaseAddress.add(0x222f38c).readPointer().add(0xD70).readU32() - /*------------------global-------------------------------------------*/ /*---------------base -------------------------*/ - -// done +// 030 done let retidPtr=null let retidStruct=null const initidStruct = ((str) => { @@ -78,7 +77,7 @@ const initidStruct = ((str) => { return retidStruct }) -// done +// 031 done let retPtr = null let retStruct = null const initStruct = ((str) => { @@ -98,7 +97,7 @@ const initStruct = ((str) => { return retStruct }) -// done +// 032 done let msgstrPtr=null let msgStruct=null const initmsgStruct = ((str) => { @@ -117,7 +116,23 @@ const initmsgStruct = ((str) => { return msgStruct }) -// tbd +// 034 done +/** +* 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 +}) + +// 033 tbd let retidNullStruct = null let retidNullPtr = null const initNullIdStruct = ((str) => { @@ -137,25 +152,7 @@ const initNullIdStruct = ((str) => { return retidNullStruct }) -// done -/** -* 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 -}) - -// done -// std::string -// const str = readStringPtr(ptr).readUtf8String() +// 035 done const readStringPtr = (address) => { const addr = ptr(address) const size = addr.add(16).readU32() @@ -169,9 +166,15 @@ const readStringPtr = (address) => { 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) : '' } + 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()) @@ -180,913 +183,853 @@ const readStringPtr = (address) => { return addr } -// done +// 036 done const readString = (address) => { return readStringPtr(address).readUtf8String() } -// done +// 037 done const readWideString = (address) => { return readWStringPtr(address).readUtf16String() } +/*-----------------base-------------------------*/ + +// 041 +// 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 +} /*-----------------base-------------------------*/ +// 010 done let currentVersion = 0 -let nodeList = [] //for contact +let nodeList = [] //for contact let contactList = [] //for contact let chatroomNodeList = [] //for chatroom -let chatroomMemberList = []//for chatroom +let chatroomMemberList = [] //for chatroom let loggedIn = false -//开启日志 3.6.0.18 -// //[0x221c330+wechatwin.dll]+0xf8 -// 20220504 +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 +}) -let g_initTestAsm = null -let g_BufferEbp2C = null -let g_initECXU32 = null -let g_initECXPtr = null -let g_initEBXPtr = null -let g_initEBX = null +// 011 done +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('.') +}) -let g_attatchEBP210Buffer = null -let g_attatchPathPtr = null -let g_attatchPath = null -let g_attatchEBPAc = null -let g_attatchEBPAcBufPtr = null +// 012 done +const checkSupportedFunction = (() => { + const ver = getWechatVersionFunction() + return ver == availableVersion +}) -let g_attatchContactIdPtr = null -//let g_attatchECXBuffer = null -let g_attatchESIU32 = null +// 019 done +/** + * @Hook: recvMsg -> recvMsgNativeCallback + */ + const recvMsgNativeCallback = (() => { -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) + const nativeCallback = new NativeCallback(() => {}, 'void', ['int32', 'pointer', 'pointer', 'pointer', 'pointer', 'int32']) + const nativeativeFunction = new NativeFunction(nativeCallback, 'void', ['int32', 'pointer', 'pointer', 'pointer', 'pointer', 'int32']) - 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 + Interceptor.attach( + moduleBaseAddress.add(offset.hook_point), { + onEnter() { + const addr = this.context.ecx //0xc30-0x08 + const msgType = addr.add(0x38).readU32() + const isMyMsg = addr.add(0x3C).readU32() //add isMyMsg - console.log('------------g_initECXU32', g_initECXU32) - console.log('------------g_initESIU32', g_attatchESIU32) + if (msgType > 0) { + const talkerIdPtr = addr.add(0x48).readPointer() + //console.log('txt msg',talkerIdPtr.readUtf16String()) + const talkerIdLen = addr.add(0x48 + 0x04).readU32() * 2 + 2 - //console.log('==========g_initECXPtr',g_initECXPtr) - //console.log('==========g_EDIU32',g_EDIU32) + const myTalkerIdPtr = Memory.alloc(talkerIdLen) + Memory.copy(myTalkerIdPtr, talkerIdPtr, talkerIdLen) - //g_attatchECXBuffer = Memory.alloc(0x1024) - //Memory.copy(g_attatchECXBuffer, g_initECXPtr, 0x1024) - g_BufferEbp2C = Memory.alloc(0x48) + 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) + } - //g_initEBX = moduleBaseAddress.add(0x2251724).readPointer().readPointer() - //g_initEBXPtr = Memory.alloc(0x14).writePointer(g_initEBX) - //g_initEBXPtr.add(0x08).writePointer(g_BufferEbp2C) + // 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 - g_attatchPathPtr = Memory.alloc(attatchFile.length * 2 + 2) - g_attatchPathPtr.writeUtf16String(attatchFile) + myGroupMsgSenderIdPtr = Memory.alloc(0x10) + myGroupMsgSenderIdPtr.writeUtf16String("null") - 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----------------*/ + } else { - //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) + const groupMsgSenderIdPtr = addr.add(0x170).readPointer() + const groupMsgSenderIdLen = addr.add(0x170 + 0x04).readU32() * 2 + 2 + myGroupMsgSenderIdPtr = Memory.alloc(groupMsgSenderIdLen) + Memory.copy(myGroupMsgSenderIdPtr, groupMsgSenderIdPtr, groupMsgSenderIdLen) - /*g_attatchECXBuffer.add(0x18).writePointer(g_attatchContactIdPtr) - g_attatchECXBuffer.add(0x1C).writeU32(contactId.length*2) - .add(0x04).writeU32(contactId.length*2)*/ + } + const xmlNullPtr = addr.add(0x1f0).readU32() //3.9.2.23 + let myXmlContentPtr = null + if (xmlNullPtr == 0) { + myXmlContentPtr = Memory.alloc(0x10) + myXmlContentPtr.writeUtf16String("null") - //g_attatchESIU32 = g_EDI.toInt32() + } else { + const xmlContentPtr = addr.add(0x1f0).readPointer() //3.9.2.23 + const xmlContentLen = addr.add(0x1f0 + 0x04).readU32() * 2 + 2 + myXmlContentPtr = Memory.alloc(xmlContentLen) + Memory.copy(myXmlContentPtr, xmlContentPtr, xmlContentLen) + } - //console.log('------------g_attatchESIU32',g_attatchESIU32) - //console.log('==========g_attatchECXBuffer',g_attatchECXBuffer) + setImmediate(() => nativeativeFunction(msgType, myTalkerIdPtr, myContentPtr, myGroupMsgSenderIdPtr, myXmlContentPtr, isMyMsg)) + } + } + }) + return nativeCallback +})() - Memory.patchCode(g_initTestAsm, Process.pageSize, code => { - var cw = new X86Writer(code, { pc: g_initTestAsm }) - cw.putPushfx() - cw.putPushax() - //cw.putMovRegAddress('eax', g_attatchEBP210Buffer) +// 003 done +const getBaseNodeAddress = (() => { + return moduleBaseAddress.add(offset.contactInfo.nodeOffset).readPointer() +}) - /*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))*/ +// 004 done +const getHeaderNodeAddress = (() => { + const baseAddress = getBaseNodeAddress() + //console.log('baseAddress',baseAddress) + if (baseAddress.isNull()) { + return baseAddress + } - //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))*/ + //console.log('HeaderNodeAddress',baseAddress.add(offset.handle_offset).readPointer()) + return baseAddress.add(offset.contactInfo.nodeRootOffset).readPointer() +}) +// 006 done +const getMyselfInfoFunction = (() => { - /*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))*/ + let ptr = 0 + let wx_code = '' + let wx_id = '' + let wx_name = '' + let head_img_url = '' + const base = moduleBaseAddress.add(offset.myselfinfo.offset) + const wxid_len = base.add(offset.myselfinfo.wxid_len_offset).readU32() - /*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)) + if (wxid_len === 0x13) { // 新版本微信 + wx_id = base.readPointer().readAnsiString(wxid_len) + wx_code = base.add(offset.myselfinfo.wxcode_new).readAnsiString() + } else { + wx_id = readString(base) + wx_code = wx_id + } - /** g_attatchEBPAc*/ - //cw.putMovRegNearPtr('eax', g_attatchEBPAc) - //cw.putMovNearPtrReg(g_attatchEBPAc.add(0xc), 'eax') - /** g_attatchEBPAc*/ + wx_name = readString(base.add(offset.myselfinfo.wx_nick_name)) + const img_addr = base.add(offset.myselfinfo.head_img_url).readPointer() + const img_len = base.add(offset.myselfinfo.head_img_url_len).readU32() - //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))*/ + head_img_url = img_addr.readAnsiString(img_len) - cw.putPopax() - cw.putPopfx() - cw.putRet() - cw.flush() + const myself = { + id: wx_id, + code: wx_code, + name: wx_name, + head_img_url: head_img_url, + }; - }) + return JSON.stringify(myself) - const nativeativeFunction = new NativeFunction(ptr(g_initTestAsm), 'void', []) - nativeativeFunction() }) +// 043 done +const recurseNew = ((node) => { + const headerNodeAddress = getHeaderNodeAddress() + if (headerNodeAddress.isNull()) { + return + } -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 + if (node.equals(headerNodeAddress)) { + return + } - g_personal_detail_asm = Memory.alloc(Process.pageSize) - g_personal_detail_ebx = moduleBaseAddress.add(0x222F38C).readPointer().add(0xFB8).toInt32() + for (const item in nodeList) { + if (node.equals(nodeList[item])) { + return + } + } - 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) + nodeList.push(node) + const id = readString(node.add(0x8)) + //wxid, format relates to registration method + const wxid = readWideString(node.add(0x30)) + //console.log('-----------',wxid) - 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() + //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)) - cw.putCallAddress(moduleBaseAddress.add(0x9A000)) + //custom Nickname + const name = readWideString(node.add(0x8c)) - //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)) + //alias aka 'remark' in wechat + //const alias = readWideString(node.add(0x80)) - cw.putPopax() - cw.putPopfx() - cw.putRet() - cw.flush() + //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,*/ + } - const nativeativeFunction = new NativeFunction(ptr(g_personal_detail_asm), 'void', []) - nativeativeFunction() + 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 writeLogNativeCallback = (() => { -// const nativeCallback = new NativeCallback(() => { }, 'void', []) -// const nativeCallFunction = new NativeFunction(nativeCallback, 'void', []) + const allContactJson = contactList + return allContactJson -// 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 +// 044 done +const getContactNativeFunction = (() => { + const headerNodeAddress = getHeaderNodeAddress() + //console.log('headerNodeAddress',headerNodeAddress) -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) + if (headerNodeAddress.isNull()) { + return '[]' + } - attatchFirstECX = Memory.alloc(0x28) - //const attatchSecondEcx = Memory.alloc(0x14) + const node = headerNodeAddress.add(0x0).readPointer() + const ret = recurseNew(node) - const contactIdLength = contactId.length * 2 + 2//edx - const contractIdActLength = contactId.length + //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 - gattatchReceiveIdPtr = Memory.alloc(contactId.length * 2 + 2) - gattatchReceiveIdPtr.writeUtf16String(contactId) + return cloneRet +}) - 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*/ +// 0xx done +const getChatroomNodeAddress = (() => { + const baseAddress = moduleBaseAddress.add(offset.chatroomInfo.nodeOffset).readPointer() + if (baseAddress.isNull()) { + return baseAddress + } + return baseAddress.add(offset.chatroomInfo.nodeRootOffset).readPointer() +}) - 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() +// 008chatroom member done +const chatroomRecurse = ((node) => { + const chatroomNodeAddress = getChatroomNodeAddress() + if (chatroomNodeAddress.isNull()) { + return + } + if (node.equals(chatroomNodeAddress)) { + return + } -}) -// 001 -const getTestInfoFunction = ((addr) => { - const nativeativeFunction = new NativeFunction(ptr(addr), 'void', []) - nativeativeFunction() + for (const item in chatroomNodeList) { + if (node.equals(chatroomNodeList[item])) { + return + } + } - //00CFE484 + chatroomNodeList.push(node) + const roomid = readWideString(node.add(0x10)) + const len = node.add(0x54).readU32() // + //const memberJson={} + if (len > 4) { // + const memberStr = readString(node.add(0x44)) + if (memberStr.length > 0) { + const memberList = memberStr.split(/[\\^][G]/) + const memberJson = { + roomid: roomid, + roomMember: memberList + } - /*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('============') + chatroomMemberList.push(memberJson) } - })*/ -}) + } -// 002get global data + const leftNode = node.add(0x0).readPointer() + const centerNode = node.add(0x04).readPointer() + const rightNode = node.add(0x08).readPointer() -const isLoggedInFunction = (() => { - loggedIn = moduleBaseAddress.add(offset.is_logged_in_offset).readU32() - return !!loggedIn -}) + chatroomRecurse(leftNode) + chatroomRecurse(centerNode) + chatroomRecurse(rightNode) -// 007 缺失,请标注已废弃或者其他原因 -const getMyselfIdFunction = (() => { + const allChatroomMemberJson = chatroomMemberList + return allChatroomMemberJson +}) - let wx_id = readString(moduleBaseAddress.add(offset.wxid_offset)) +// 009 done +const getChatroomMemberInfoFunction = (() => { + const chatroomNodeAddress = getChatroomNodeAddress() + if (chatroomNodeAddress.isNull()) { + return '[]' + } - return wx_id + 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 }) -// 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') +// 024 done +/** + * sendMsgNativeFunction + * send text message + * @param {string} talkerId = wxid or roomid + * @param {string} content + */ + const sendMsgNativeFunction = ((talkerId, content) => { - return addr -} + const txtAsm = Memory.alloc(Process.pageSize) + //const buffwxid = Memory.alloc(0x20) -//contact -const recurse = ((node) => { - const headerNodeAddress = getHeaderNodeAddress() - if (headerNodeAddress.isNull()) { return } - if (node.equals(headerNodeAddress)) { return } + let wxidPtr = Memory.alloc(talkerId.length * 2 + 2) + wxidPtr.writeUtf16String(talkerId) - for (const item in nodeList) { - if (node.equals(nodeList[item])) { - return - } - } + let picWxid = Memory.alloc(0x0c) + picWxid.writePointer(ptr(wxidPtr)).add(0x04) + .writeU32(talkerId.length * 2).add(0x04) + .writeU32(talkerId.length * 2).add(0x04) + let contentPtr = Memory.alloc(content.length * 2 + 2) + contentPtr.writeUtf16String(content) - nodeList.push(node) - //wxid, format relates to registration method - const wxid = readWideString(node.add(0x38)) + const sizeOfStringStruct = Process.pointerSize * 5 + let contentStruct = Memory.alloc(sizeOfStringStruct) - //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)) + contentStruct + .writePointer(contentPtr).add(0x4) + .writeU32(content.length).add(0x4) + .writeU32(content.length * 2) - //custom Nickname - const name = readWideString(node.add(0x94)) - //alias aka 'remark' in wechat - const alias = readWideString(node.add(0x80)) + const ecxBuffer = Memory.alloc(0x2d8) - //avatarUrl - const avatar = readWideString(node.add(0x138)) - //const avatar = Memory.readUtf16String(node.add(0x138).readPointer()) - //contact gender - const gender = node.add(0x18C).readU32() + Memory.patchCode(txtAsm, Process.pageSize, code => { + var cw = new X86Writer(code, { + pc: txtAsm + }) + cw.putPushfx() + cw.putPushax() - const contactJson = { - id: wxid, - code: wx_code, - name: name, - alias: alias, - avatarUrl: avatar, - gender: gender, - } + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x1) + cw.putPushU32(0x0) - contactList.push(contactJson) + //cw.putMovRegReg - const leftNode = node.add(0x0).readPointer() - const centerNode = node.add(0x04).readPointer() - const rightNode = node.add(0x08).readPointer() + cw.putMovRegAddress('eax', contentStruct) + cw.putPushReg('eax') - recurse(leftNode) - recurse(centerNode) - recurse(rightNode) + cw.putMovRegAddress('edx', picWxid) //room_id - const allContactJson = contactList - return allContactJson + cw.putMovRegAddress('ecx', ecxBuffer) + cw.putCallAddress(moduleBaseAddress.add( + offset.sendTxtMsg.callOffset + )) -}) + cw.putAddRegImm('esp', 0x18) + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() -// 010 done -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 done -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('.') -}) + console.log('----------txtAsm', txtAsm) + const nativeativeFunction = new NativeFunction(ptr(txtAsm), 'void', []) + nativeativeFunction() -// 012 done -const checkSupportedFunction = (() => { - const ver = getWechatVersionFunction() - return ver == availableVersion }) +// 023 done /** - * @Hook: recvMsg -> recvMsgNativeCallback - */ +* send at msg +*/ +let asmAtMsg = null +let roomid_, msg_, wxid_, atid_ +let ecxBuffer +const sendAtMsgNativeFunction = ((roomId, text, contactId,nickname) => { -// 019 done -const recvMsgNativeCallback = (() => { + asmAtMsg = Memory.alloc(Process.pageSize) + ecxBuffer = Memory.alloc(0x3b0) + const atContent = '@'+nickname+' '+text - const nativeCallback = new NativeCallback(() => {}, 'void', ['int32', 'pointer', 'pointer', 'pointer', 'pointer', 'int32']) - const nativeativeFunction = new NativeFunction(nativeCallback, 'void', ['int32', 'pointer', 'pointer', 'pointer', 'pointer', 'int32']) + roomid_ = initStruct(roomId) + wxid_ = initidStruct(contactId) + msg_ = initmsgStruct(atContent) + atid_ = initAtMsgStruct(wxid_) - Interceptor.attach( - moduleBaseAddress.add(offset.hook_point), { - onEnter() { - const addr = this.context.ecx //0xc30-0x08 - const msgType = addr.add(0x38).readU32() - const isMyMsg = addr.add(0x3C).readU32() //add isMyMsg + Memory.patchCode(asmAtMsg, Process.pageSize, code => { + var cw = new X86Writer(code, { + pc: asmAtMsg + }) + cw.putPushfx() + cw.putPushax() - if (msgType > 0) { + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x0) + cw.putPushU32(0x1) + //cw.putPushU32(0x0) + cw.putMovRegAddress('eax', atid_) + cw.putPushReg('eax') - const talkerIdPtr = addr.add(0x48).readPointer() - //console.log('txt msg',talkerIdPtr.readUtf16String()) - const talkerIdLen = addr.add(0x48 + 0x04).readU32() * 2 + 2 + //cw.putMovRegReg - const myTalkerIdPtr = Memory.alloc(talkerIdLen) - Memory.copy(myTalkerIdPtr, talkerIdPtr, talkerIdLen) + cw.putMovRegAddress('eax', msg_) + cw.putPushReg('eax') + cw.putMovRegAddress('edx', roomid_) //room_id - 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) - } + cw.putMovRegAddress('ecx', ecxBuffer) + cw.putCallAddress(moduleBaseAddress.add( + offset.sendTxtMsg.callOffset + )) - // 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 + cw.putAddRegImm('esp', 0x18) + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() - myGroupMsgSenderIdPtr = Memory.alloc(0x10) - myGroupMsgSenderIdPtr.writeUtf16String("null") + }) - } else { + //console.log('----------txtAsm', asmAtMsg) + const nativeativeFunction = new NativeFunction(ptr(asmAtMsg), 'void', []) + nativeativeFunction() - const groupMsgSenderIdPtr = addr.add(0x170).readPointer() - const groupMsgSenderIdLen = addr.add(0x170 + 0x04).readU32() * 2 + 2 - myGroupMsgSenderIdPtr = Memory.alloc(groupMsgSenderIdLen) - Memory.copy(myGroupMsgSenderIdPtr, groupMsgSenderIdPtr, groupMsgSenderIdLen) +}) - } +// 022 done +/** + * + * @param {*} contactId + * @param {*} path + */ + const sendPicMsgNativeFunction = ((contactId, path) => { - const xmlNullPtr = addr.add(0x1f0).readU32() //3.9.2.23 - let myXmlContentPtr = null - if (xmlNullPtr == 0) { + const picAsm = Memory.alloc(Process.pageSize) + const buffwxid = Memory.alloc(0x20) + const picbuff = Memory.alloc(0x2D8) - myXmlContentPtr = Memory.alloc(0x10) - myXmlContentPtr.writeUtf16String("null") + let pathPtr = Memory.alloc(path.length * 2 + 1) + pathPtr.writeUtf16String(path) - } else { - const xmlContentPtr = addr.add(0x1f0).readPointer() //3.9.2.23 + let imagefilepath = Memory.alloc(0x24) + imagefilepath.writePointer(pathPtr).add(0x04) + .writeU32(path.length * 2).add(0x04) + .writeU32(path.length * 2).add(0x04) - const xmlContentLen = addr.add(0x1f0 + 0x04).readU32() * 2 + 2 - myXmlContentPtr = Memory.alloc(xmlContentLen) - Memory.copy(myXmlContentPtr, xmlContentPtr, xmlContentLen) - } + let picWxidPtr = Memory.alloc(contactId.length * 2 + 1) + picWxidPtr.writeUtf16String(contactId) - setImmediate(() => nativeativeFunction(msgType, myTalkerIdPtr, myContentPtr, myGroupMsgSenderIdPtr, myXmlContentPtr, isMyMsg)) - } - } - }) - return nativeCallback -})() + let picWxid = Memory.alloc(0x0c) + picWxid.writePointer(ptr(picWxidPtr)).add(0x04) + .writeU32(contactId.length * 2).add(0x04) + .writeU32(contactId.length * 2).add(0x04) -// 003get myself info done -const getBaseNodeAddress = (() => { - return moduleBaseAddress.add(offset.contactInfo.nodeOffset).readPointer() -}) -// 004 done -const getHeaderNodeAddress = (() => { - const baseAddress = getBaseNodeAddress() - //console.log('baseAddress',baseAddress) - if (baseAddress.isNull()) { - return baseAddress - } + //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.sendPicMsg.call1 + )) + cw.putMovRegReg('edx', 'eax') //缓存 - //console.log('HeaderNodeAddress',baseAddress.add(offset.handle_offset).readPointer()) - return baseAddress.add(offset.contactInfo.nodeRootOffset).readPointer() -}) + cw.putSubRegImm('esp', 0x14) + cw.putMovRegAddress('eax', buffwxid) + cw.putMovRegReg('ecx', 'esp') + cw.putMovRegAddress('edi', imagefilepath) + cw.putPushReg('eax') + cw.putCallAddress(moduleBaseAddress.add( + offset.sendPicMsg.call2 + )) -// 006 done -const getMyselfInfoFunction = (() => { + 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') - let ptr = 0 - let wx_code = '' - let wx_id = '' - let wx_name = '' - let head_img_url = '' + cw.putMovRegAddress('edi', picWxid) //edi + cw.putCallAddress(moduleBaseAddress.add( + offset.sendPicMsg.call3 + )) - const base = moduleBaseAddress.add(offset.myselfinfo.offset) - const wxid_len = base.add(offset.myselfinfo.wxid_len_offset).readU32() - if (wxid_len === 0x13) { // 新版本微信 - wx_id = base.readPointer().readAnsiString(wxid_len) - wx_code = base.add(offset.myselfinfo.wxcode_new).readAnsiString() - } else { - wx_id = readString(base) - wx_code = wx_id - } + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() - wx_name = readString(base.add(offset.myselfinfo.wx_nick_name)) - const img_addr = base.add(offset.myselfinfo.head_img_url).readPointer() - const img_len = base.add(offset.myselfinfo.head_img_url_len).readU32() + }) - head_img_url = img_addr.readAnsiString(img_len) + //console.log('----------picAsm',picAsm) + const nativeativeFunction = new NativeFunction(ptr(picAsm), 'void', []) + nativeativeFunction() - const myself = { - id: wx_id, - code: wx_code, - name: wx_name, - head_img_url: head_img_url, - }; +}) - return JSON.stringify(myself) +// 020 done +let memberNickBuffAsm = null +let nickRoomId = null +let nickMemberId = null +let nickBuff = null +const getChatroomMemberNickInfoFunction = ((memberId, roomId) => { -}) + nickBuff = Memory.alloc(0x7e4) + //const nickRetAddr = Memory.alloc(0x04) + memberNickBuffAsm = Memory.alloc(Process.pageSize) + //console.log('asm address----------',memberNickBuffAsm) + nickRoomId = initidStruct(roomId) + //console.log('nick room id',nickRoomId) + nickMemberId = initStruct(memberId) -// done -const recurseNew = ((node) => { - const headerNodeAddress = getHeaderNodeAddress() - if (headerNodeAddress.isNull()) { - return - } + //console.log('nick nickMemberId id',nickMemberId) + //const nickStructPtr = initmsgStruct('') - if (node.equals(headerNodeAddress)) { - return - } + Memory.patchCode(memberNickBuffAsm, Process.pageSize, code => { + var cw = new X86Writer(code, { + pc: memberNickBuffAsm + }) + cw.putPushfx() + cw.putPushax() + cw.putMovRegAddress('edi', nickRoomId) + cw.putMovRegAddress('eax', nickBuff) + cw.putMovRegReg('edx', 'edi') + cw.putPushReg('eax') + cw.putMovRegAddress('ecx', nickMemberId) + cw.putCallAddress(moduleBaseAddress.add(0xC06F10)) + cw.putAddRegImm('esp', 0x04) + cw.putPopax() + cw.putPopfx() + cw.putRet() + cw.flush() - for (const item in nodeList) { - if (node.equals(nodeList[item])) { - return - } - } + }) + const nativeativeFunction = new NativeFunction(ptr(memberNickBuffAsm), 'void', []) + nativeativeFunction() - nodeList.push(node) - const id = readString(node.add(0x8)) - //wxid, format relates to registration method - const wxid = readWideString(node.add(0x30)) - //console.log('-----------',wxid) + const nickname = readWideString(nickBuff) + console.log('----nickname', nickname) + return readWideString(nickBuff) +}) +/* 由此之后是3.9.2.23中缺失的未实现方法 */ - //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)) +// 038 初始化全局变量 tbd +let g_initTestAsm = null +let g_BufferEbp2C = null +let g_initECXU32 = null +let g_initECXPtr = null +let g_initEBXPtr = null +let g_initEBX = null - //custom Nickname - const name = readWideString(node.add(0x8c)) +let g_attatchEBP210Buffer = null +let g_attatchPathPtr = null +let g_attatchPath = null +let g_attatchEBPAc = null +let g_attatchEBPAcBufPtr = null - //alias aka 'remark' in wechat - //const alias = readWideString(node.add(0x80)) +let g_attatchContactIdPtr = null +//let g_attatchECXBuffer = null +let g_attatchESIU32 = null - //avatarUrl - //const avatar = readWideString(node.add(0x138)) - //const avatar = Memory.readUtf16String(node.add(0x138).readPointer()) - //contact gender - //const gender = node.add(0x18C).readU32() +let g_initECXTempPtr = null +const initGlobal = ((contactId, attatchFile) => { - const contactJson = { - id1: id, - id: wxid, - name: name, - /*code: wx_code, - name: name, - alias: alias, - avatarUrl: avatar, - gender: gender,*/ - } + //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) - contactList.push(contactJson) + 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 - const leftNode = node.add(0x0).readPointer() - const centerNode = node.add(0x04).readPointer() - //const rightNode = node.add(0x08).readPointer() + console.log('------------g_initECXU32', g_initECXU32) + console.log('------------g_initESIU32', g_attatchESIU32) - recurseNew(leftNode) - recurseNew(centerNode) - //recurse(rightNode) - const allContactJson = contactList - return allContactJson + //console.log('==========g_initECXPtr',g_initECXPtr) + //console.log('==========g_EDIU32',g_EDIU32) -}) + //g_attatchECXBuffer = Memory.alloc(0x1024) + //Memory.copy(g_attatchECXBuffer, g_initECXPtr, 0x1024) -// done ? -const getContactNativeFunction = (() => { - const headerNodeAddress = getHeaderNodeAddress() - //console.log('headerNodeAddress',headerNodeAddress) + g_BufferEbp2C = Memory.alloc(0x48) - if (headerNodeAddress.isNull()) { - return '[]' - } + //g_initEBX = moduleBaseAddress.add(0x2251724).readPointer().readPointer() + //g_initEBXPtr = Memory.alloc(0x14).writePointer(g_initEBX) + //g_initEBXPtr.add(0x08).writePointer(g_BufferEbp2C) - const node = headerNodeAddress.add(0x0).readPointer() - const ret = recurseNew(node) + g_attatchPathPtr = Memory.alloc(attatchFile.length * 2 + 2) + g_attatchPathPtr.writeUtf16String(attatchFile) - //console.log(ret) + 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----------------*/ - 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 + //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) - return cloneRet -}) + /*g_attatchECXBuffer.add(0x18).writePointer(g_attatchContactIdPtr) + g_attatchECXBuffer.add(0x1C).writeU32(contactId.length*2) + .add(0x04).writeU32(contactId.length*2)*/ -// 005 done -const getChatroomNodeAddress = (() => { - const baseAddress = moduleBaseAddress.add(offset.chatroomInfo.nodeOffset).readPointer() - if (baseAddress.isNull()) { - return baseAddress - } - return baseAddress.add(offset.chatroomInfo.nodeRootOffset).readPointer() -}) -// 008chatroom member done -const chatroomRecurse = ((node) => { - const chatroomNodeAddress = getChatroomNodeAddress() - if (chatroomNodeAddress.isNull()) { - return - } - if (node.equals(chatroomNodeAddress)) { - return - } + //g_attatchESIU32 = g_EDI.toInt32() - for (const item in chatroomNodeList) { - if (node.equals(chatroomNodeList[item])) { - return - } - } - chatroomNodeList.push(node) - const roomid = readWideString(node.add(0x10)) + //console.log('------------g_attatchESIU32',g_attatchESIU32) + //console.log('==========g_attatchECXBuffer',g_attatchECXBuffer) - const len = node.add(0x54).readU32() // - //const memberJson={} - if (len > 4) { // - const memberStr = readString(node.add(0x44)) - if (memberStr.length > 0) { - const memberList = memberStr.split(/[\\^][G]/) - const memberJson = { - roomid: roomid, - roomMember: memberList - } + Memory.patchCode(g_initTestAsm, Process.pageSize, code => { + var cw = new X86Writer(code, { pc: g_initTestAsm }) + cw.putPushfx() + cw.putPushax() + //cw.putMovRegAddress('eax', g_attatchEBP210Buffer) - chatroomMemberList.push(memberJson) - } + /*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) - const leftNode = node.add(0x0).readPointer() - const centerNode = node.add(0x04).readPointer() - const rightNode = node.add(0x08).readPointer() + /*cw.putPushU32(0) + cw.putMovRegAddress('eax', g_attatchPathPtr) + cw.putPushReg('eax') + cw.putPushU32(3) + cw.putMovRegAddress('ecx', g_attatchEBP210Buffer) + cw.putCallAddress(moduleBaseAddress.add(0x130220))*/ - chatroomRecurse(leftNode) - chatroomRecurse(centerNode) - chatroomRecurse(rightNode) - const allChatroomMemberJson = chatroomMemberList - return allChatroomMemberJson -}) + /*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))*/ -// 009 done -const getChatroomMemberInfoFunction = (() => { - const chatroomNodeAddress = getChatroomNodeAddress() - if (chatroomNodeAddress.isNull()) { - return '[]' - } - const node = chatroomNodeAddress.add(0x0).readPointer() - const ret = chatroomRecurse(node) + /*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)) - const cloneRet = JSON.stringify(ret) - chatroomNodeList.length = 0 //empty - chatroomMemberList.length = 0 //empty - return cloneRet -}) + /** g_attatchEBPAc*/ + //cw.putMovRegNearPtr('eax', g_attatchEBPAc) + //cw.putMovNearPtrReg(g_attatchEBPAc.add(0xc), 'eax') + /** g_attatchEBPAc*/ -// 024 done -/** - * sendMsgNativeFunction - * send text message - * @param {string} talkerId = wxid or roomid - * @param {string} content - */ - const sendMsgNativeFunction = ((talkerId, content) => { - const txtAsm = Memory.alloc(Process.pageSize) - //const buffwxid = Memory.alloc(0x20) + //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() - let wxidPtr = Memory.alloc(talkerId.length * 2 + 2) - wxidPtr.writeUtf16String(talkerId) + }) - let picWxid = Memory.alloc(0x0c) - picWxid.writePointer(ptr(wxidPtr)).add(0x04) - .writeU32(talkerId.length * 2).add(0x04) - .writeU32(talkerId.length * 2).add(0x04) + const nativeativeFunction = new NativeFunction(ptr(g_initTestAsm), 'void', []) + nativeativeFunction() +}) - let contentPtr = Memory.alloc(content.length * 2 + 2) - contentPtr.writeUtf16String(content) +// 039 +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 - const sizeOfStringStruct = Process.pointerSize * 5 - let contentStruct = Memory.alloc(sizeOfStringStruct) + g_personal_detail_asm = Memory.alloc(Process.pageSize) + g_personal_detail_ebx = moduleBaseAddress.add(0x222F38C).readPointer().add(0xFB8).toInt32() - contentStruct - .writePointer(contentPtr).add(0x4) - .writeU32(content.length).add(0x4) - .writeU32(content.length * 2) + 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) - const ecxBuffer = Memory.alloc(0x2d8) + console.log('-----------address----------', g_personal_detail_asm) - Memory.patchCode(txtAsm, Process.pageSize, code => { - var cw = new X86Writer(code, { - pc: txtAsm - }) + Memory.patchCode(g_personal_detail_asm, Process.pageSize, code => { + var cw = new X86Writer(code, { pc: g_personal_detail_asm }) cw.putPushfx() cw.putPushax() - cw.putPushU32(0x0) - cw.putPushU32(0x0) - cw.putPushU32(0x0) - cw.putPushU32(0x1) - cw.putPushU32(0x0) - - //cw.putMovRegReg + cw.putCallAddress(moduleBaseAddress.add(0x9A000)) - cw.putMovRegAddress('eax', contentStruct) + //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.putMovRegAddress('edx', picWxid) //room_id - - cw.putMovRegAddress('ecx', ecxBuffer) - cw.putCallAddress(moduleBaseAddress.add( - offset.sendTxtMsg.callOffset - )) - - cw.putAddRegImm('esp', 0x18) cw.putPopax() cw.putPopfx() cw.putRet() @@ -1094,59 +1037,154 @@ const getChatroomMemberInfoFunction = (() => { }) - console.log('----------txtAsm', txtAsm) - const nativeativeFunction = new NativeFunction(ptr(txtAsm), 'void', []) + const nativeativeFunction = new NativeFunction(ptr(g_personal_detail_asm), 'void', []) nativeativeFunction() + }) -// 023 done +// 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 +// })() + +// 040 /** -* send at msg -*/ -let asmAtMsg = null -let roomid_, msg_, wxid_, atid_ -let ecxBuffer -const sendAtMsgNativeFunction = ((roomId, text, contactId,nickname) => { + * 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 - asmAtMsg = Memory.alloc(Process.pageSize) - ecxBuffer = Memory.alloc(0x3b0) +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) - const atContent = '@'+nickname+' '+text + attatchFirstECX = Memory.alloc(0x28) + //const attatchSecondEcx = Memory.alloc(0x14) - roomid_ = initStruct(roomId) - wxid_ = initidStruct(contactId) - msg_ = initmsgStruct(atContent) - atid_ = initAtMsgStruct(wxid_) + const contactIdLength = contactId.length * 2 + 2//edx + const contractIdActLength = contactId.length - Memory.patchCode(asmAtMsg, Process.pageSize, code => { - var cw = new X86Writer(code, { - pc: asmAtMsg - }) + + 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.putPushU32(0x0) - cw.putPushU32(0x0) - cw.putPushU32(0x0) - cw.putPushU32(0x1) - //cw.putPushU32(0x0) - cw.putMovRegAddress('eax', atid_) + + cw.putMovRegAddress('esi', attatchESIbuf) + + cw.putMovRegAddress('ecx', attatchFirstECX.add(0x14)) + cw.putMovRegAddress('eax', gattatchFile) cw.putPushReg('eax') + cw.putCallAddress(moduleBaseAddress.add(0x701DC0)) - //cw.putMovRegReg - cw.putMovRegAddress('eax', msg_) + cw.putMovRegAddress('ecx', attatchFirstECX) + cw.putMovRegU32('eax', contactIdLength) cw.putPushReg('eax') + cw.putPushU32(0) + cw.putCallAddress(moduleBaseAddress.add(0x1a11c83)) + cw.putAddRegImm('esp', 0x8) - cw.putMovRegAddress('edx', roomid_) //room_id + 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.putMovRegAddress('ecx', ecxBuffer) - cw.putCallAddress(moduleBaseAddress.add( - offset.sendTxtMsg.callOffset - )) + //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.putAddRegImm('esp', 0x18) cw.putPopax() cw.putPopfx() cw.putRet() @@ -1154,134 +1192,103 @@ const sendAtMsgNativeFunction = ((roomId, text, contactId,nickname) => { }) - //console.log('----------txtAsm', asmAtMsg) - const nativeativeFunction = new NativeFunction(ptr(asmAtMsg), 'void', []) + const nativeativeFunction = new NativeFunction(ptr(attatchTestAsm), 'void', []) nativeativeFunction() + }) -// 022 done -/** - * - * @param {*} contactId - * @param {*} path - */ - const sendPicMsgNativeFunction = ((contactId, path) => { +// 001 +const getTestInfoFunction = ((addr) => { + const nativeativeFunction = new NativeFunction(ptr(addr), 'void', []) + nativeativeFunction() - const picAsm = Memory.alloc(Process.pageSize) - const buffwxid = Memory.alloc(0x20) - const picbuff = Memory.alloc(0x2D8) + //00CFE484 - let pathPtr = Memory.alloc(path.length * 2 + 1) - pathPtr.writeUtf16String(path) - let imagefilepath = Memory.alloc(0x24) - imagefilepath.writePointer(pathPtr).add(0x04) - .writeU32(path.length * 2).add(0x04) - .writeU32(path.length * 2).add(0x04) + /*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('============') + } + })*/ - let picWxidPtr = Memory.alloc(contactId.length * 2 + 1) - picWxidPtr.writeUtf16String(contactId) +}) - let picWxid = Memory.alloc(0x0c) - picWxid.writePointer(ptr(picWxidPtr)).add(0x04) - .writeU32(contactId.length * 2).add(0x04) - .writeU32(contactId.length * 2).add(0x04) +// 002 +const isLoggedInFunction = (() => { + loggedIn = moduleBaseAddress.add(offset.is_logged_in_offset).readU32() + return !!loggedIn +}) +// 007 获得当前账号信息 +const getMyselfIdFunction = (() => { - //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.sendPicMsg.call1 - )) - cw.putMovRegReg('edx', 'eax') //缓存 + let wx_id = readString(moduleBaseAddress.add(offset.wxid_offset)) - cw.putSubRegImm('esp', 0x14) - cw.putMovRegAddress('eax', buffwxid) - cw.putMovRegReg('ecx', 'esp') - cw.putMovRegAddress('edi', imagefilepath) - cw.putPushReg('eax') - cw.putCallAddress(moduleBaseAddress.add( - offset.sendPicMsg.call2 - )) + return wx_id - 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.sendPicMsg.call3 - )) +//contact +// 042 +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 + } + } - cw.putPopax() - cw.putPopfx() - cw.putRet() - cw.flush() - }) + nodeList.push(node) + //wxid, format relates to registration method + const wxid = readWideString(node.add(0x38)) - //console.log('----------picAsm',picAsm) - const nativeativeFunction = new NativeFunction(ptr(picAsm), 'void', []) - nativeativeFunction() + //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)) -// 020 done -let memberNickBuffAsm = null -let nickRoomId = null -let nickMemberId = null -let nickBuff = null -const getChatroomMemberNickInfoFunction = ((memberId, roomId) => { + //alias aka 'remark' in wechat + const alias = readWideString(node.add(0x80)) - nickBuff = Memory.alloc(0x7e4) - //const nickRetAddr = Memory.alloc(0x04) - memberNickBuffAsm = Memory.alloc(Process.pageSize) - //console.log('asm address----------',memberNickBuffAsm) - nickRoomId = initidStruct(roomId) - //console.log('nick room id',nickRoomId) - nickMemberId = initStruct(memberId) + //avatarUrl + const avatar = readWideString(node.add(0x138)) + //const avatar = Memory.readUtf16String(node.add(0x138).readPointer()) + //contact gender + const gender = node.add(0x18C).readU32() - //console.log('nick nickMemberId id',nickMemberId) - //const nickStructPtr = initmsgStruct('') + const contactJson = { + id: wxid, + code: wx_code, + name: name, + alias: alias, + avatarUrl: avatar, + gender: gender, + } - Memory.patchCode(memberNickBuffAsm, Process.pageSize, code => { - var cw = new X86Writer(code, { - pc: memberNickBuffAsm - }) - cw.putPushfx() - cw.putPushax() - cw.putMovRegAddress('edi', nickRoomId) - cw.putMovRegAddress('eax', nickBuff) - cw.putMovRegReg('edx', 'edi') - cw.putPushReg('eax') - cw.putMovRegAddress('ecx', nickMemberId) - cw.putCallAddress(moduleBaseAddress.add(0xC06F10)) - cw.putAddRegImm('esp', 0x04) - cw.putPopax() - cw.putPopfx() - cw.putRet() - cw.flush() + contactList.push(contactJson) - }) + const leftNode = node.add(0x0).readPointer() + const centerNode = node.add(0x04).readPointer() + const rightNode = node.add(0x08).readPointer() - const nativeativeFunction = new NativeFunction(ptr(memberNickBuffAsm), 'void', []) - nativeativeFunction() + recurse(leftNode) + recurse(centerNode) + recurse(rightNode) + + const allContactJson = contactList + return allContactJson - const nickname = readWideString(nickBuff) - console.log('----nickname', nickname) - return readWideString(nickBuff) }) // 013 @@ -1428,13 +1435,13 @@ const getQrcodeLoginData = () => { return json } - +// 045 /** * 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 writeLogNativeCallback = (() => { const nativeCallback = new NativeCallback(() => { }, 'void', []) const nativeCallFunction = new NativeFunction(nativeCallback, 'void', []) @@ -1448,8 +1455,9 @@ const getQrcodeLoginData = () => { } }) return nativeCallback -})()*/ +})() +// 046 let nickRoomIdV6 = null let nullEdiWxidStructV6 = null let nickMemberIdStructV6 = null @@ -1509,6 +1517,7 @@ const getChatroomMemberNickInfoV1Function = ((memberId, roomId) => { return readWideString(nullEdiWxidStructV6) }) +// 021 /** * send attatch */ @@ -1550,8 +1559,6 @@ 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) @@ -1755,78 +1762,6 @@ const sendAttatchMsgNativeFunction = ((contactId, senderId, path, filename, size //console.log('-------',attatchEbp1C.add(0x4).readPointer()) //console.log('-------',attatchEbp1C.add(0x8).readPointer()) }) -/*------------------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() - -})*/ // 025 const callLoginQrcodeFunction = ((forceRefresh = false) => { From 3faaa0b48b502a1941c32d350e57b6a78f5e82e1 Mon Sep 17 00:00:00 2001 From: choogoo <104893934+choogoo@users.noreply.github.com> Date: Thu, 21 Sep 2023 14:54:14 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E9=80=82=E9=85=8D3.9.2.23=20(#185)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 3.9.2.23 initt * Update init-agent-script.js * 3.9.2.23 adapter * 适配3.9.2.23 * Delete agent-script-3.9.2.23-new.js * 适配3.9.2.23 --------- Co-authored-by: LuChao --- package.json | 2 +- src/init-agent-script.js | 1174 ++------------------------------------ src/puppet-xp.ts | 14 +- src/wechat-sidecar.ts | 66 ++- 4 files changed, 84 insertions(+), 1172 deletions(-) diff --git a/package.json b/package.json index 8e9f1dd..ffe22cc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wechaty-puppet-xp", - "version": "1.12.7", + "version": "1.13.0", "description": "Puppet XP for Wechaty", "type": "module", "exports": { diff --git a/src/init-agent-script.js b/src/init-agent-script.js index 9c97f9a..802ce45 100644 --- a/src/init-agent-script.js +++ b/src/init-agent-script.js @@ -1,16 +1,20 @@ /** + * 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") -// wechat:3.9.2.23 +//3.9.2.23 -// 028 done const offset = { @@ -45,19 +49,18 @@ const offset = { } }; -// 029 done + + /*------------------global-------------------------------------------*/ const availableVersion = 1661534743 ////3.9.2.23 ==0x63090217 const moduleBaseAddress = Module.getBaseAddress('WeChatWin.dll') const moduleLoad = Module.load('WeChatWin.dll') -// tbd -const g_EDIPtr = moduleBaseAddress.add(0x222f38c).readPointer().add(0xD70).readPointer()// -const g_EDIU32 = moduleBaseAddress.add(0x222f38c).readPointer().add(0xD70).readU32() -/*------------------global-------------------------------------------*/ +//1575CF98 + /*---------------base -------------------------*/ -// 030 done + let retidPtr=null let retidStruct=null const initidStruct = ((str) => { @@ -77,7 +80,6 @@ const initidStruct = ((str) => { return retidStruct }) -// 031 done let retPtr = null let retStruct = null const initStruct = ((str) => { @@ -97,7 +99,6 @@ const initStruct = ((str) => { return retStruct }) -// 032 done let msgstrPtr=null let msgStruct=null const initmsgStruct = ((str) => { @@ -116,10 +117,6 @@ const initmsgStruct = ((str) => { return msgStruct }) -// 034 done -/** -* at msg structure -*/ let atStruct = null const initAtMsgStruct = ((wxidStruct) => { @@ -131,28 +128,6 @@ const initAtMsgStruct = ((wxidStruct) => { .writeU32(0) return atStruct }) - -// 033 tbd -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 -}) - -// 035 done const readStringPtr = (address) => { const addr = ptr(address) const size = addr.add(16).readU32() @@ -183,18 +158,6 @@ const readStringPtr = (address) => { return addr } -// 036 done -const readString = (address) => { - return readStringPtr(address).readUtf8String() -} - -// 037 done -const readWideString = (address) => { - return readWStringPtr(address).readUtf16String() -} -/*-----------------base-------------------------*/ - -// 041 // std::wstring // const wstr = readWStringPtr(ptr).readUtf16String() const readWStringPtr = (address) => { @@ -216,9 +179,17 @@ const readWStringPtr = (address) => { return addr } +const readString = (address) => { + return readStringPtr(address).readUtf8String() +} + +const readWideString = (address) => { + return readWStringPtr(address).readUtf16String() +} + + /*-----------------base-------------------------*/ -// 010 done let currentVersion = 0 let nodeList = [] //for contact @@ -229,6 +200,7 @@ let chatroomMemberList = [] //for chatroom let loggedIn = false + const getWechatVersionFunction = (() => { if (currentVersion) { return currentVersion @@ -245,7 +217,7 @@ const getWechatVersionFunction = (() => { return ver }) -// 011 done +// 011 const getWechatVersionStringFunction = ((ver = getWechatVersionFunction()) => { if (!ver) { return '0.0.0.0' @@ -258,17 +230,13 @@ const getWechatVersionStringFunction = ((ver = getWechatVersionFunction()) => { return vers.join('.') }) -// 012 done const checkSupportedFunction = (() => { const ver = getWechatVersionFunction() return ver == availableVersion }) -// 019 done -/** - * @Hook: recvMsg -> recvMsgNativeCallback - */ - const recvMsgNativeCallback = (() => { +// 019 +const recvMsgNativeCallback = (() => { const nativeCallback = new NativeCallback(() => {}, 'void', ['int32', 'pointer', 'pointer', 'pointer', 'pointer', 'int32']) @@ -356,12 +324,12 @@ const checkSupportedFunction = (() => { return nativeCallback })() -// 003 done + const getBaseNodeAddress = (() => { return moduleBaseAddress.add(offset.contactInfo.nodeOffset).readPointer() }) -// 004 done +// 004 const getHeaderNodeAddress = (() => { const baseAddress = getBaseNodeAddress() //console.log('baseAddress',baseAddress) @@ -373,7 +341,6 @@ const getHeaderNodeAddress = (() => { return baseAddress.add(offset.contactInfo.nodeRootOffset).readPointer() }) -// 006 done const getMyselfInfoFunction = (() => { let ptr = 0 @@ -411,7 +378,7 @@ const getMyselfInfoFunction = (() => { }) -// 043 done + const recurseNew = ((node) => { const headerNodeAddress = getHeaderNodeAddress() if (headerNodeAddress.isNull()) { @@ -477,7 +444,7 @@ const recurseNew = ((node) => { }) -// 044 done + const getContactNativeFunction = (() => { const headerNodeAddress = getHeaderNodeAddress() //console.log('headerNodeAddress',headerNodeAddress) @@ -503,7 +470,7 @@ const getContactNativeFunction = (() => { return cloneRet }) -// 0xx done + const getChatroomNodeAddress = (() => { const baseAddress = moduleBaseAddress.add(offset.chatroomInfo.nodeOffset).readPointer() if (baseAddress.isNull()) { @@ -512,7 +479,6 @@ const getChatroomNodeAddress = (() => { return baseAddress.add(offset.chatroomInfo.nodeRootOffset).readPointer() }) -// 008chatroom member done const chatroomRecurse = ((node) => { const chatroomNodeAddress = getChatroomNodeAddress() if (chatroomNodeAddress.isNull()) { @@ -560,7 +526,6 @@ const chatroomRecurse = ((node) => { return allChatroomMemberJson }) -// 009 done const getChatroomMemberInfoFunction = (() => { const chatroomNodeAddress = getChatroomNodeAddress() if (chatroomNodeAddress.isNull()) { @@ -576,14 +541,15 @@ const getChatroomMemberInfoFunction = (() => { return cloneRet }) -// 024 done + + /** * sendMsgNativeFunction * send text message * @param {string} talkerId = wxid or roomid * @param {string} content */ - const sendMsgNativeFunction = ((talkerId, content) => { +const sendMsgNativeFunction = ((talkerId, content) => { const txtAsm = Memory.alloc(Process.pageSize) //const buffwxid = Memory.alloc(0x20) @@ -650,10 +616,7 @@ const getChatroomMemberInfoFunction = (() => { }) -// 023 done -/** -* send at msg -*/ + let asmAtMsg = null let roomid_, msg_, wxid_, atid_ let ecxBuffer @@ -710,13 +673,12 @@ const sendAtMsgNativeFunction = ((roomId, text, contactId,nickname) => { }) -// 022 done /** * * @param {*} contactId * @param {*} path */ - const sendPicMsgNativeFunction = ((contactId, path) => { +const sendPicMsgNativeFunction = ((contactId, path) => { const picAsm = Memory.alloc(Process.pageSize) const buffwxid = Memory.alloc(0x20) @@ -788,7 +750,9 @@ const sendAtMsgNativeFunction = ((roomId, text, contactId,nickname) => { }) -// 020 done + + + let memberNickBuffAsm = null let nickRoomId = null let nickMemberId = null @@ -834,1066 +798,8 @@ const getChatroomMemberNickInfoFunction = ((memberId, roomId) => { return readWideString(nickBuff) }) -/* 由此之后是3.9.2.23中缺失的未实现方法 */ - -// 038 初始化全局变量 tbd -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() -}) - -// 039 -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 -// })() - -// 040 -/** - * 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('============') - } - })*/ - -}) - -// 002 const isLoggedInFunction = (() => { - loggedIn = moduleBaseAddress.add(offset.is_logged_in_offset).readU32() - return !!loggedIn -}) - -// 007 获得当前账号信息 -const getMyselfIdFunction = (() => { - - let wx_id = readString(moduleBaseAddress.add(offset.wxid_offset)) - - return wx_id - -}) - -//contact -// 042 -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 - -}) - -// 013 -const isSupported = checkSupportedFunction() - -if (!isSupported) { - throw new Error(`Wechat version not supported. \nWechat version: ${getWechatVersionStringFunction()}, supported version: ${getWechatVersionStringFunction(availableVersion)}`) -} - -// 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 -} - -// 045 -/** - * 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 -})() - -// 046 -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) -}) - -// 021 -/** -* 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 -*/ -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()) -}) - -// 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() - - + // loggedIn = moduleBaseAddress.add(offset.is_logged_in_offset).readU32() + // return !!loggedIn + return true }) \ No newline at end of file diff --git a/src/puppet-xp.ts b/src/puppet-xp.ts index 446ffae..ce4278f 100644 --- a/src/puppet-xp.ts +++ b/src/puppet-xp.ts @@ -108,6 +108,7 @@ class PuppetXp extends PUPPET.Puppet { this.#sidecar = new WeChatSidecar() await attach(this.sidecar) + void this.onLogin() this.sidecar.on('hook', ({ method, args }) => { log.verbose('PuppetXp', 'onHook(%s, %s)', method, JSON.stringify(args)) @@ -141,15 +142,16 @@ class PuppetXp extends PUPPET.Puppet { private async onAgentReady () { log.verbose('PuppetXp', 'onAgentReady()') - const isLoggedIn = await this.sidecar.isLoggedIn() - if (!isLoggedIn) { - await this.sidecar.callLoginQrcode(false) - } + // const isLoggedIn = await this.sidecar.isLoggedIn() + // if (!isLoggedIn) { + // await this.sidecar.callLoginQrcode(false) + // } } private async onLogin () { const selfInfoRaw = JSON.parse(await this.sidecar.getMyselfInfo()) + // console.debug('selfInfoRaw:\n\n\n', selfInfoRaw) const selfInfo: PUPPET.payloads.Contact = { alias: '', avatar: selfInfoRaw.head_img_url, @@ -567,7 +569,7 @@ class PuppetXp extends PUPPET.Puppet { id: roomId, memberIdList: roomMember, ownerId: '', - topic: topic, + topic, } this.roomStore[roomId] = room delete this.contactStore[roomId] @@ -834,7 +836,7 @@ class PuppetXp extends PUPPET.Puppet { } } - if ([PUPPET.types.Message.Video, PUPPET.types.Message.Audio].includes(message?.type || PUPPET.types.Message.Unknown)) { + if ([ PUPPET.types.Message.Video, PUPPET.types.Message.Audio ].includes(message?.type || PUPPET.types.Message.Unknown)) { this.notSupported('Video/`Audio') } return FileBox.fromFile( diff --git a/src/wechat-sidecar.ts b/src/wechat-sidecar.ts index 4b8ec6c..ab02a70 100644 --- a/src/wechat-sidecar.ts +++ b/src/wechat-sidecar.ts @@ -47,7 +47,11 @@ const supportedVersions = { // 'agent-script-3.3.0.115.js', // ), 'utf-8') -let initAgentScript = '' +let initAgentScript = fs.readFileSync(path.join( + codeRoot, + 'src', + 'init-agent-script.js', +), 'utf-8') try { // const wechatVersion = new WeChatVersion() @@ -104,8 +108,8 @@ try { @Sidecar('WeChat.exe', initAgentScript) class WeChatSidecar extends SidecarBody { - @Call(agentTarget('getTestInfoFunction')) - getTestInfo ():Promise { return Ret() } + // @Call(agentTarget('getTestInfoFunction')) + // getTestInfo ():Promise { return Ret() } @Call(agentTarget('getChatroomMemberNickInfoFunction')) getChatroomMemberNickInfo ( @@ -131,10 +135,10 @@ class WeChatSidecar extends SidecarBody { @Call(agentTarget('checkSupportedFunction')) checkSupported ():Promise { return Ret() } - @Call(agentTarget('callLoginQrcodeFunction')) - callLoginQrcode ( - forceRefresh: boolean, - ):Promise { return Ret(forceRefresh) } + // @Call(agentTarget('callLoginQrcodeFunction')) + // callLoginQrcode ( + // forceRefresh: boolean, + // ):Promise { return Ret(forceRefresh) } @Call(agentTarget('getContactNativeFunction')) getContact ():Promise { return Ret() } @@ -181,30 +185,30 @@ class WeChatSidecar extends SidecarBody { @ParamType('int32', 'U32') isMyMsg: number, // add isMyMsg type ) { return Ret(msgType, contactId, text, groupMsgSenderId, xmlContent, isMyMsg) } - @Hook(agentTarget('checkQRLoginNativeCallback')) - checkQRLogin ( - @ParamType('int32', 'U32') status: number, - @ParamType('pointer', 'Utf8String') qrcodeUrl: string, - @ParamType('pointer', 'Utf8String') wxid: string, - @ParamType('pointer', 'Utf8String') avatarUrl: string, - @ParamType('pointer', 'Utf8String') nickname: string, - @ParamType('pointer', 'Utf8String') phoneType: string, - @ParamType('int32', 'U32') phoneClientVer: number, - @ParamType('pointer', 'Utf8String') pairWaitTip: string, - ) { return Ret(status, qrcodeUrl, wxid, avatarUrl, nickname, phoneType, phoneClientVer, pairWaitTip) } - - @Hook(agentTarget('hookLogoutEventCallback')) - logoutEvent ( - @ParamType('int32', 'U32') bySrv: number, - ) { return Ret(bySrv) } - - @Hook(agentTarget('hookLoginEventCallback')) - loginEvent ( - ) { return Ret() } - - @Hook(agentTarget('agentReadyCallback')) - agentReady ( - ) { return Ret() } + // @Hook(agentTarget('checkQRLoginNativeCallback')) + // checkQRLogin ( + // @ParamType('int32', 'U32') status: number, + // @ParamType('pointer', 'Utf8String') qrcodeUrl: string, + // @ParamType('pointer', 'Utf8String') wxid: string, + // @ParamType('pointer', 'Utf8String') avatarUrl: string, + // @ParamType('pointer', 'Utf8String') nickname: string, + // @ParamType('pointer', 'Utf8String') phoneType: string, + // @ParamType('int32', 'U32') phoneClientVer: number, + // @ParamType('pointer', 'Utf8String') pairWaitTip: string, + // ) { return Ret(status, qrcodeUrl, wxid, avatarUrl, nickname, phoneType, phoneClientVer, pairWaitTip) } + + // @Hook(agentTarget('hookLogoutEventCallback')) + // logoutEvent ( + // @ParamType('int32', 'U32') bySrv: number, + // ) { return Ret(bySrv) } + + // @Hook(agentTarget('hookLoginEventCallback')) + // loginEvent ( + // ) { return Ret() } + + // @Hook(agentTarget('agentReadyCallback')) + // agentReady ( + // ) { return Ret() } } From 865ef7fb912cf98e2df58a896ebe509a11836277 Mon Sep 17 00:00:00 2001 From: LuChao Date: Thu, 21 Sep 2023 15:14:07 +0800 Subject: [PATCH 4/6] add 1.3.0 illustrate --- README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 66fdf73..cba69be 100644 --- a/README.md +++ b/README.md @@ -81,9 +81,22 @@ Puppet|xp👍| 登录事件|✅ 依赖协议|Windows +## VERSION SUPPORT + +puppet-xp|wechat| +:---|:---| +>1.11.14|[WeChat-v3.3.0.115](https://github.com/wechaty/wechaty-puppet-xp/releases/download/v0.5/WeChatSetup-v3.3.0.115.exe)| +1.12.x|[WeChat-v3.6.0.18](https://github.com/tom-snow/wechat-windows-versions/releases/download/v3.6.0.18/WeChatSetup-3.6.0.18.exe)| +1.3.x|[WeChat-v3.2.2.23](https://github.com/tom-snow/wechat-windows-versions/releases/download/v3.9.2.23/WeChatSetup-3.9.2.23.exe)| + ## HISTORY -### main v1.12.0 (November 22, 2022) +### next v1.13.0 (September 21, 2023) + +1. This version start to support WeChat v3.9.2.23,need to update WeChat on your pc to 3.9.2.23 +2. [WeChatSetup-v3.2.2.23.exe](https://github.com/tom-snow/wechat-windows-versions/releases/download/v3.9.2.23/WeChatSetup-3.9.2.23.exe) + +### main v1.12.7 (November 22, 2022) 1. This version start to support WeChat v3.6.0.18,need to update WeChat on your pc to 3.6.0.18 2. [WeChatSetup-v3.6.0.18.exe](https://github.com/tom-snow/wechat-windows-versions/releases/download/v3.6.0.18/WeChatSetup-3.6.0.18.exe) From 7bfb22c01a9bd5172f2a944af073fe6dee39530b Mon Sep 17 00:00:00 2001 From: LuChao Date: Thu, 21 Sep 2023 15:21:11 +0800 Subject: [PATCH 5/6] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index cba69be..1a603cf 100644 --- a/README.md +++ b/README.md @@ -84,10 +84,10 @@ Puppet|xp👍| ## VERSION SUPPORT puppet-xp|wechat| -:---|:---| ->1.11.14|[WeChat-v3.3.0.115](https://github.com/wechaty/wechaty-puppet-xp/releases/download/v0.5/WeChatSetup-v3.3.0.115.exe)| -1.12.x|[WeChat-v3.6.0.18](https://github.com/tom-snow/wechat-windows-versions/releases/download/v3.6.0.18/WeChatSetup-3.6.0.18.exe)| -1.3.x|[WeChat-v3.2.2.23](https://github.com/tom-snow/wechat-windows-versions/releases/download/v3.9.2.23/WeChatSetup-3.9.2.23.exe)| +|:---|:---| +|>1.11.14|[WeChat-v3.3.0.115](https://github.com/wechaty/wechaty-puppet-xp/releases/download/v0.5/WeChatSetup-v3.3.0.115.exe)| +|1.12.x|[WeChat-v3.6.0.18](https://github.com/tom-snow/wechat-windows-versions/releases/download/v3.6.0.18/WeChatSetup-3.6.0.18.exe)| +|1.3.x|[WeChat-v3.2.2.23](https://github.com/tom-snow/wechat-windows-versions/releases/download/v3.9.2.23/WeChatSetup-3.9.2.23.exe)| ## HISTORY From e2fe79119b9980c977489f4147d7be513633dcef Mon Sep 17 00:00:00 2001 From: LuChao Date: Thu, 21 Sep 2023 15:22:03 +0800 Subject: [PATCH 6/6] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1a603cf..00dff81 100644 --- a/README.md +++ b/README.md @@ -85,8 +85,8 @@ Puppet|xp👍| puppet-xp|wechat| |:---|:---| -|>1.11.14|[WeChat-v3.3.0.115](https://github.com/wechaty/wechaty-puppet-xp/releases/download/v0.5/WeChatSetup-v3.3.0.115.exe)| -|1.12.x|[WeChat-v3.6.0.18](https://github.com/tom-snow/wechat-windows-versions/releases/download/v3.6.0.18/WeChatSetup-3.6.0.18.exe)| +|1.11.14|[WeChat-v3.3.0.115](https://github.com/wechaty/wechaty-puppet-xp/releases/download/v0.5/WeChatSetup-v3.3.0.115.exe)| +|1.12.7|[WeChat-v3.6.0.18](https://github.com/tom-snow/wechat-windows-versions/releases/download/v3.6.0.18/WeChatSetup-3.6.0.18.exe)| |1.3.x|[WeChat-v3.2.2.23](https://github.com/tom-snow/wechat-windows-versions/releases/download/v3.9.2.23/WeChatSetup-3.9.2.23.exe)| ## HISTORY