首页
社区
课程
招聘
[原创]PC微信逆向--实现消息防撤回
2020-3-11 09:54 12798

[原创]PC微信逆向--实现消息防撤回

2020-3-11 09:54
12798

自从聊天软件消息撤回功能问世后,对于撤回的消息,我们对它一直有种强烈的好奇感。“Ta刚撤回了什么?是骂我的话?还是说喜欢我?还是把发给其他人的消息误发给了我?好气呀,都看不到了...”这是我们看到消息被撤回后的内心独白。但是今天,看完了本篇文章你就可以说:

 

 

我们看一下效果图,撤回的消息被我们看到了,相当于防(防止)撤回

 

 

好了,看完效果,接下来我们看一下怎么找到它的位置,并用代码hook它。

 

本文用到的软件工具:

  • 微信 2.8.0.121
  • Cheat Engine 7.0(用于内存搜索,下文简称CE)
  • Ollydbg吾爱破解版(用于动态调试,下文简称OD)
  • Visual Studio 2017(用于编写Hook代码,下文简称VS)

用CE打开微信进程

 

 

用另一个微信号给在电脑登录的微信号随机发一条消息,勾选UTF-16选项,然后在CE中搜索消息内容

 

 

撤回消息,看到一条xml消息,双击它添加到地址列表

 

 

打开OD,附加微信进程,用dd命令定位到上面的那个地址

 

 

再给电脑登录那个微信号发一条消息,然后在上面那个地址下内存写入断点。为什么是内存写入断点?因为我们上文亲眼目睹了消息撤回后这个地址的字符串被改写了。

 

下好断点后再把消息撤回,此时断点被触发,微信被断下,断下后,删除内存断点。在堆栈里寻找我们想要的内容,看到一个包含撤回提示wxid撤回内容的call

 

 

在反汇编窗口中跟随这个call,点击这个call,按F2在该call下断点,按F9继续运行。再给在电脑登录那个微信号发一条消息并撤回,该call断下

 

 

说明,这个call就是我们要找的消息撤回的位置,而且它有我们想要的数据

 

 

找到了call,来整理一下该call的数据,数据都是存在堆栈里,所以有:

  • esp + 0x4 :撤回消息的提示
  • esp + 0x50 : 撤回消息人的wxid
  • esp + 0x78 : 撤回消息的内容

接下来编写一个dll,来hook这个call,读取esp偏移地址的数据。

 

在VS创建一个dll项目,核心代码如下:

#include "resource.h"
#include "hook.h"
#include "module.h"
#include <wchar.h>
INT_PTR CALLBACK Dlgproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void DlgThread(HMODULE hInstance);

#define REVOCK_CALL_RVA 0x28c33f
#define REVOCK_CALL_TARGET_RVA 0x28ccd0

DWORD revockCallVA = 0;
DWORD revockCallTargetVA = 0;
DWORD revockCallJmpBackVA = 0;

DWORD wechatWinAddr = 0;
BYTE backCode[5];

HWND m_dialog_hwnd;
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    CreateThread(NULL, 0, LPTHREAD_START_ROUTINE(DlgThread), hModule, 0, NULL);
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

void OnRevock(DWORD esp) {
  wchar_t *tips = *(wchar_t **)(esp + 0x4);
  wchar_t *msg = *(wchar_t **)(esp + 0x78);
  if (NULL != tips) {
    WCHAR buffer[0x8192];
    wchar_t* pos = wcsstr(tips, L"撤回了一条消息");
    if (pos!= NULL && NULL != msg) {
      swprintf_s(buffer, L"%s,内容:%s",tips, msg);
      SetDlgItemText(m_dialog_hwnd, IDC_EDIT1, buffer);
    }
  }

}
DWORD tEsp = 0;
_declspec(naked) void _OnRevock() {
    __asm {
        mov tEsp, esp
        pushad
    }
    OnRevock(tEsp);
    __asm {
        popad
        call revockCallTargetVA
        jmp revockCallJmpBackVA
    }
}

void DlgThread(HMODULE hInstance) {
  DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, Dlgproc);
}

INT_PTR CALLBACK Dlgproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  switch (uMsg) {
    case WM_INITDIALOG: {
      m_dialog_hwnd = hWnd;
      wechatWinAddr = GetWxModuleAddress();
      revockCallVA = wechatWinAddr + REVOCK_CALL_RVA;
      revockCallTargetVA = wechatWinAddr + REVOCK_CALL_TARGET_RVA;

      revockCallJmpBackVA = revockCallVA + 5;
      StartHook5(wechatWinAddr+REVOCK_CALL_RVA,backCode,_OnRevock);
    }
    break;
    case WM_CLOSE:
      Unhook5(wechatWinAddr + REVOCK_CALL_RVA, backCode);
      EndDialog(hWnd, TRUE);
      break;
  }
  return 0;
  }

Hook相关代码:

int StartHook5(DWORD hookAddr, BYTE backCode[5], void(*FuncBeCall)()) {
    DWORD jmpAddr = (DWORD)FuncBeCall - (hookAddr + 5);

    BYTE jmpCode[5];
    *(jmpCode + 0) = 0xE9;
    *(DWORD *)(jmpCode + 1) = jmpAddr;
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, NULL, GetCurrentProcessId());
    //备份被替换的
    if (ReadProcessMemory(hProcess, (LPVOID)hookAddr, backCode, 5, NULL) == 0) {
        return -1;
    }
    //写入jmp指令
    if (WriteProcessMemory(hProcess, (LPVOID)hookAddr, jmpCode, 5, NULL) == 0) {
        return -1;
    }

    return 0;
}

int Unhook5(DWORD hookAddr, BYTE backCode[5]) {
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, NULL, GetCurrentProcessId());
    if (WriteProcessMemory(hProcess, (LPVOID)hookAddr, backCode, 5, NULL) == 0) {
        return -1;
    }
    return 0;
}

代码写完后,生成dll,把它注入到微信进程,防撤回消息就能实现了。

 

总结:微信版本一直会变化,相应的hook地址也会改变,但是有了这个思路,它更新版本,我们也能快速的找到call。这个消息撤回的call也比较好找,像我这样初学逆向的朋友可以尝试自己找一下。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
点赞5
打赏
分享
最新回复 (26)
雪    币: 21619
活跃值: (3602)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
huangyalei 2020-3-11 11:37
2
0
图片看不到
雪    币: 29414
活跃值: (18600)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 8 2020-3-11 12:01
3
0
huangyalei 图片看不到
开始图片是外链,速度慢,脚本处理了一下,图片已放到论坛本地,正常了。
雪    币: 2676
活跃值: (3446)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
luoyesiqiu 3 2020-3-11 12:06
4
0
kanxue 开始图片是外链,速度慢,脚本处理了一下,图片已放到论坛本地,正常了。
谢谢处理,辛苦了
雪    币: 200
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xiaoxinfeng 2020-3-11 12:07
5
0
奈何只会易语言、、不过C看的是真的舒服  连寄存器都直接可以调用, 
最后于 2020-3-11 12:07 被xiaoxinfeng编辑 ,原因:
雪    币: 2676
活跃值: (3446)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
luoyesiqiu 3 2020-3-11 12:18
6
0
xiaoxinfeng 奈何只会易语言、、不过C看的是真的舒服&nbsp; 连寄存器都直接可以调用,&nbsp;
C语言大法好
雪    币: 6107
活跃值: (2710)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
a圣a 2020-3-11 16:47
7
0
思路清晰,处理方法很直接。
雪    币: 83
活跃值: (1037)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
killpy 2 2020-3-11 20:44
8
0
感谢
雪    币: 6814
活跃值: (2615)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lyghost 2020-3-12 07:59
9
0
不错,分析的很详细
雪    币: 41
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
桃木剑 2020-3-12 09:46
10
0
生成dll可否发一份呢
雪    币: 2676
活跃值: (3446)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
luoyesiqiu 3 2020-3-12 20:44
11
0

可以

最后于 2020-3-14 00:26 被luoyesiqiu编辑 ,原因:
上传的附件:
雪    币: 364
活跃值: (1336)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
wujimaa 1 2020-3-13 09:19
12
0
已读
雪    币: 2510
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_xghoecki 2020-3-13 18:04
13
1
感谢分享
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
驴哥。。。 2020-3-14 09:18
14
0
能发一下整个代码吗,谢谢大哥
雪    币: 2676
活跃值: (3446)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
luoyesiqiu 3 2020-3-14 10:17
15
0
驴哥。。。 能发一下整个代码吗,谢谢大哥

https://www.lanzous.com/ia8dmib

雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
驴哥。。。 2020-3-14 14:27
16
0
谢谢大哥
雪    币: 14
活跃值: (263)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ZwTrojan 2020-3-16 10:56
17
0
为什么要搜索808080
雪    币: 187
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
skyhyko 2020-3-17 21:59
18
0
为什么我按照楼主的方法找不到这个call,而且好几个call里都有 "撤回了一条消息"
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
驴哥。。。 2020-3-19 14:11
19
0
为什么我算出来的是0x28b33f,难道return (DWORD)LoadLibraryW(L"WeChatWin.dll");返回的地址有0x1000是空的吗,球楼主大大解答
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_nwbuluhm 2020-3-21 16:50
20
0
楼主,我想弄一个把别人发来的图片都保存的HOOK功能, 开始的想法是直接在微信的FileStorage\Image目录下把加密的图片解密出来, 在进行保存,  可是发现一个情况, 就是别人发来的图片, 原图不是百分百会自动保存成加密文件的, 有时候需要点开图片,查过看大图他才会自动保存下来. 我是拿着别人在发的视频教程新开始学习的. 是个新萌, 请问.楼主对于这个自动保存别人发的图片功能,有什么好的文案或建议吗?  
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
ArlenLT 2020-3-23 07:35
21
0
楼主你好,我想请教一下这两行是指什么,怎么算出来的。
#define REVOCK_CALL_RVA 0x28c33f
#define REVOCK_CALL_TARGET_RVA 0x28ccd0
雪    币: 20
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yangsenzz 2020-3-23 17:26
22
0
 挺详细的,感谢
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
财有帅 2020-3-23 17:53
23
0
高手
雪    币: 9
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
葡萄成熟时 2021-10-19 10:27
24
0
大哥,能发一下完整代码吗?
雪    币: 9
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
葡萄成熟时 2021-10-19 10:28
25
0
https://www.lanzous.com/ia8dmib这个网址失效了
游客
登录 | 注册 方可回帖
返回