SpenserCai / GoWxDump

SharpWxDump的Go语言版。微信客户端取证,获取信息(微信号、手机号、昵称),微信聊天记录分析(Top N聊天的人、统计聊天最频繁的好友排行、关键词列表搜索等)
GNU General Public License v3.0
1.39k stars 167 forks source link

好像wechat是64位应用了 #26

Open jjnetcn opened 1 year ago

jjnetcn commented 1 year ago

按照msdn的说法, https://learn.microsoft.com/zh-cn/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot?redirectedfrom=MSDN CreateToolhelp32Snapshot函数在遍历进程模块的时候, 如果指定的进程是 64 位进程,并且调用方是 32 位进程,则此函数将失败,最后一个错误代码 ERROR_PARTIAL_COPY ( 299) 。 这个错误也就是 Only part of a ReadProcessMemory or WriteProcessMemory request was complete

wechat现在升级成了64位应用, 所以GetWeChatWinModule调用CreateToolhelp32Snapshot时报错误 GetWeChatWinModule error: Only part of a ReadProcessMemory or WriteProcessMemory request was complete

修改build.bat, set GOARCH=amd64, 同时升级gcc lib 64位, 如TDM-GCC-64或mingw64, 后编译, 不过此时因为没有版本信息, OffSetMap的数组越界, 不过64位的versionlist offset可能需要重新分析一边了

jjnetcn commented 1 year ago

增加64位地址取值函数, 64位下调用 GetWeChatKey64,而不是调用GetWeChatKey func GetWeChatKey64(process windows.Handle, offset uintptr) (string, error) { var buffer = make([]byte, 8) err := windows.ReadProcessMemory(process, offset, &buffer[0], 8, nil) if err != nil { return "", err } var num = 32 var buffer2 = make([]byte, num) offset2 := uintptr ( (uint64(buffer[7]) << 56) + (uint64(buffer[6]) << 48) + (uint64(buffer[5]) << 40) + (uint64(buffer[4]) << 32) + (uint64(buffer[3]) << 24) + (uint64(buffer[2]) << 16) + (uint64(buffer[1]) << 8) + (uint64(buffer[0]) << 0) ) err = windows.ReadProcessMemory(process, offset2, &buffer2[0], uintptr(num), nil) if err != nil { return "", err } // 将byte数组转成hex字符串,并转成大写 key := hex.EncodeToString(buffer2) key = strings.ToUpper(key) return key, nil }

version_list.go 增加新版本 3.9.5.81 2023/6/13当前最新64位版 "3.9.5.81": { 0x3ACB650, // nick 0x3ACB7B8, // account 0x3ACB6F8, // mobile 38986104, 0x3ACBCB0, // key },

luomo5 commented 1 year ago

SharpWxDump最新版本微信也获取不到了,有没办法修改下

SpenserCai commented 1 year ago

增加64位地址取值函数, 64位下调用 GetWeChatKey64,而不是调用GetWeChatKey func GetWeChatKey64(process windows.Handle, offset uintptr) (string, error) { var buffer = make([]byte, 8) err := windows.ReadProcessMemory(process, offset, &buffer[0], 8, nil) if err != nil { return "", err } var num = 32 var buffer2 = make([]byte, num) offset2 := uintptr ( (uint64(buffer[7]) << 56) + (uint64(buffer[6]) << 48) + (uint64(buffer[5]) << 40) + (uint64(buffer[4]) << 32) + (uint64(buffer[3]) << 24) + (uint64(buffer[2]) << 16) + (uint64(buffer[1]) << 8) + (uint64(buffer[0]) << 0) ) err = windows.ReadProcessMemory(process, offset2, &buffer2[0], uintptr(num), nil) if err != nil { return "", err } // 将byte数组转成hex字符串,并转成大写 key := hex.EncodeToString(buffer2) key = strings.ToUpper(key) return key, nil }

version_list.go 增加新版本 3.9.5.81 2023/6/13当前最新64位版 "3.9.5.81": { 0x3ACB650, // nick 0x3ACB7B8, // account 0x3ACB6F8, // mobile 38986104, 0x3ACBCB0, // key },

非常感谢,这个可以测试后提交pr,我merge后会发布最新版本哈

jjnetcn commented 1 year ago

具体的4处修改:修改ARCHamd64, 下载64位的库否则gcc会提示二进制不兼容,修改间接根据地址取key的函数以及调用者,同时增加了最新版本的几个偏移参数,试着编译了一下, 在最新的3.9.5.81可以用, 这几个地址是没有问题的,当然只是试了下show_info功能, 没有去看其他功能。 另外,编译出的64位pe, 在遍历32位wechat进程的模块时候,也遍历不到WeChatWin.dll(没有报错,但是列出的模块异常少就结束了,另外我自己本地改过标准if (Module32First) { do {..} while( Module32Next)}这种标准框架,不清楚只是调用module32next是不是有问题或者兼容性如何), 而32位的程序去遍历64位的wechat直接报了299错误。 也就是说: 32位的wechat必须用32位的程序才能找到模块,64位亦然。所以结论可能需要编译两个版本, 一个32位的针对32位的wechat,一个针对64位的。 对go语言不熟, 一边问chatgpt一边试着改的,代码质量不高, 就不提pr了

jjnetcn commented 1 year ago

补充一下: 根据查阅资料, PsApi系列的enumProcessModules,以及kernel系列的Module32First/Module32Next 确实只能枚举跟自身位数相同的进程的模块, 即要遍历32位进程需要把程序编译成32位模式,反之亦然。 但是PsApi系列还有一个函数enumProcessModulesEx , 可以通过设置flags来枚举32,64或者两者的exe的模块,也就是用这个api替换掉就可以只编译成32位程序, 唯一需要的就是在读间接地址key的时候需要判断exe的版本来决定地址读4个字节还是8个字节。 晚上我回家试试,看能不能编一个通用的版本

jjnetcn commented 1 year ago

32位程序用常规方法无法列举出64位模块, 已提交了个pr, 采用wow64ex库, 临时切换到64位模式下调用64位系统调用来实现, 做了下实验,在32位微信和最新的64位微信上都能获取了,因该问题不大了

xaoyaoo commented 1 year ago

非常厉害,根据你说的进行了修改,能用了,解密也正常

saucer-man commented 1 year ago

可以只编译成64位版本的吗?

Eyion commented 11 months ago

编译好的版本能分享一下吗?不会编译呀