C++ DLL注入微信实现自动接收、发送消息
用了半个暑假学C++,hook WX,成功调用发送消息call,接收消息响应call。在B站参考了Hezone和Hellmessage两位大神的视频,虽然WX更新较快,汇编代码已经面目全非,但思路很有启发性。写篇文章记下实现过程,方便日后复习。
用到的工具有:visual studio,cheat engine,ollydbg。
写一个DLL
这个DLL相当于我们的间谍,潜入WX内部,然后和外部主程序通信进行相应操作。
- 打开VS,创建新项目,选择”动态链接库“
创建了一个名为Dll1的DLL,dllmain.cpp里有vs为我们准备好的DLL程序入口。
我们的执行的代码要在DLL_PROCESS_ATTACH下面写。
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
switch (ul_reason_for_call)
case DLL_PROCESS_ATTACH:
/*我们的代码,注入DLL后会执行*/
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
return TRUE;
先打开头文件pch.h,然后写上
#include <windows.h>
再回到dllmain,加一个弹窗。
case DLL_PROCESS_ATTACH:
/*我们的代码,注入DLL后会执行*/
MessageBox(0,L"成功潜入微信内部!",L"报告主人",NULL);
按F5生成。
打开项目目录下的Debug文件夹,我们可以看到我们生成的Dll1.dll和Dll1.pdb。
DLL注入程序
写完简单的DLL,然后写一个Inject DLL 注入程序(exe),用远程线程注入的方法,把自己的DLL注入到WX进程。
我们再创建一个新项目,选择“控制台程序”,将项目命名为Inject。
方法是先通过WX程序的Pid,调用OpenProcess用可获得的所有权限打开进程,再用VirtualAllocEx在WX进程的地址空间开辟一块内存,调用WriteProcessMemory把我们写的DLL的路径写到WX的内存里。 [1]
我们要想办法创建一个远程线程(CreateRemoteThreadEx),让线程执行“LoadLibrary"让微信载入我们的DLL。我们不能直接&LoadLibrary取到函数地址然后传过去让线程执行,因为我们的注入程序的LoadLibrary地址和WX地址空间的LoadLibrary地址不一致。所以我们要用GetProcAddress获取LoadLibrary的地址。
完整代码如下:
int main() {
DWORD pid = 0;
scanf("%d",pid);
HANDLE hprocess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
if (!hprocess) {
std::cout << "can not get handle" << std::endl;
return 1;
SIZE_T PathSize = (strlen(DLLPath) + 1) * sizeof(TCHAR);
LPVOID StartAddress = VirtualAllocEx(hprocess, NULL, PathSize, MEM_COMMIT, PAGE_READWRITE);
if (!StartAddress) {
std::cout << "开辟内存失败" << std::endl;
return 1;
if (!WriteProcessMemory(hprocess, StartAddress, DLLPath, PathSize, NULL)) {
std::cout << "无法写入DLL路径" << std::endl;
return 1;
PTHREAD_START_ROUTINE pfnStartAddress = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "LoadLibraryA");
if (!pfnStartAddress) {
std::cout << "无法获取函数地址" << std::endl;
return 1;
HANDLE hThread = CreateRemoteThreadEx(hprocess, NULL, NULL, pfnStartAddress, StartAddress, NULL, NULL, NULL);
if (!hThread) {
std::cout << "创建线程失败" << std::endl;
return 1;
//WaitForSingleObject(hThread, INFINITE);//等待DLL结束
std::cout << "注入成功!\n";
CloseHandle(hThread);
CloseHandle(hprocess);
return 0;
然后生成。
登录WX,我们再在cmd输入tasklist,找到WeChat.exe,这个WX的主进程,记下PID,之后运行我我们写的Inject.exe,输入pid。
成功显示,任务栏下方还光明正大的表示成WX的图标,真是血统正宗!
还是来更新一下,做个预告吧。
上面我们让我们的DLL注入到WX里了,这相当于我们光明正大的闯进了他的房子,可以为所欲为!
是的,我们的DLL可以像操作自己的内存一样,读取修改WX的内存,甚至调用和修改他的执行代码!
接下来会以获取到用户信息,如昵称,WX号,电话号码,头像等,讲怎么读取他的内存。
经评论区知友好心提醒,怕被抓,所以
#define WX 微信
我又回来啦!
DLL读取用户信息
登录微信后,打开CE,添加微信。
将Value Type改成String,然后输入我们的微信号,一定要一字符不差。
然后first scan扫描,会发现两个绿色的地址。绿色就代表着这个地址的相对位置是不变的,因为我们的微信号、手机号这些,登录之后就不会变化,所以这两个地址符合我们的条件。把他们添加到下栏。
鼠标悬停在上面可以看到,如果你的绿色地址和我一样是一个dll加一个十六进制数,那么后面的0x1D29B60就是我们要找的偏移量。我们可以用WeChatWin.dll基址加上偏移量,就能得出每次运行微信后,微信号的地址。
如果你只是个绿色的地址,那就点击add address manually,输入WeChatWin.dll,然后OK,下栏会多出一个以4个0结尾的地址,这就是这次启动微信WeChatWin.dll的值。
打开计算器,选程序员模式,换到十六进制,用刚刚的一个绿色地址和这个值相减,得出的数值便是偏移。
得到偏移后,找个踏实的地方记下来,以免丢失,又要重新来过。可以直接define到我们的DLL源码里。
用同样方法可以找出微信昵称和电话号码、微信头像什么的。
所以,要获取微信号的地址,只要获取WeChatWin模块基址和偏移然后相加,我们已经找到偏移,怎么让dll知道基址呢?
因为这会我们的DLL已经注入进去,是和WeChatWin.dll等同属一个进程,所以我们可以直接调用GetModuleHandle:
GetModuleHandle(L"WeChatWin.dll");
为了方便易理解,我们封装成函数:
HMODULE GetWechatWin() {
return GetModuleHandle(L"WeChatWin.dll");