#include "pch.h"
#include "CHook.h"
#include <TlHelp32.h>
#include <stdio.h>
#include <limits.h>
#include <string>
using namespace std;
#define WxReciveMessage 0x40D3BA //接收消息 1
#define WxReciveMessageCall 0x95320 //接收消息 1
//聊天记录偏移
#define MsgTypeOffset 0x38 //消息类型的偏移 1
#define IsPhoneMsg 0x3C //是否是手机发的消息 1
#define MsgContentOffset 0x70 //消息内容的偏移 1
#define MsgSourceOffset 0x1D8 //消息来源的偏移 1
#define WxidOffset 0x48 //微信ID/群ID偏移 1
#define GroupMsgSenderOffset 0x170 //群消息发送者偏移 1
//需要hook的地址
DWORD g_HookAddr=(DWORD)GetModuleHandle(TEXT("WeChatWin.dll")) + WxReciveMessage;
//返回地址
DWORD RetkReciveMsgAddr = (DWORD)GetModuleHandle(TEXT("WeChatWin.dll")) + WxReciveMessage + 5;
//被覆盖的call的地址
DWORD OverReciveMsgCallAddr = (DWORD)GetModuleHandle(TEXT("WeChatWin.dll")) + WxReciveMessageCall;
void SetSehHook()
{
//遍历线程 通过openthread获取到线程环境后设置硬件断点
HANDLE hTool32 = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hTool32!= INVALID_HANDLE_VALUE)
{
//线程环境结构体
THREADENTRY32 thread_entry32;
thread_entry32.dwSize = sizeof(THREADENTRY32);
HANDLE hHookThread = NULL;
//遍历线程
if (Thread32First(hTool32,&thread_entry32))
{
do
{
//如果线程父进程ID为当前进程ID
if (thread_entry32.th32OwnerProcessID==GetCurrentProcessId())
{
hHookThread = OpenThread(THREAD_SET_CONTEXT | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, FALSE, thread_entry32.th32ThreadID);
SuspendThread(hHookThread);//暂停线程
//设置硬件断点
CONTEXT thread_context = { CONTEXT_DEBUG_REGISTERS };
thread_context.Dr0 = g_HookAddr;
thread_context.Dr7 = 0x405;
//设置线程环境 这里抛异常了
DWORD oldprotect;
VirtualProtect((LPVOID)g_HookAddr, 5, PAGE_EXECUTE_READWRITE, &oldprotect);//修改PTE p=1 r/w1=0
SetThreadContext(hHookThread, &thread_context);
ResumeThread(hHookThread);//线程跑起来吧~~~
CloseHandle(hHookThread);
}
} while (Thread32Next(hTool32, &thread_entry32));
}
CloseHandle(hTool32);
}
}
void __declspec(naked) OriginalFunc(void)
{
__asm
{
//调用被覆盖的call
call OverReciveMsgCallAddr;
//跳转到返回地址
jmp RetkReciveMsgAddr;
}
}
LONG NTAPI ExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo)
{
//判断当前异常码是否为硬件断点异常
if (ExceptionInfo->ExceptionRecord->ExceptionCode== EXCEPTION_SINGLE_STEP)
{
//判断发生异常的地址是否和hook的地址一致
if ((DWORD)ExceptionInfo->ExceptionRecord->ExceptionAddress == g_HookAddr)
{
//获取当前线程上下文
PCONTEXT pcontext = ExceptionInfo->ContextRecord;
//获取聊天记录
RecvMsg(pcontext);
//修复EIP
pcontext->Eip=(DWORD)&OriginalFunc;
//异常处理完成 让程序继续执行
return EXCEPTION_CONTINUE_EXECUTION;
}
}
return EXCEPTION_CONTINUE_SEARCH;
}
void RecvMsg(PCONTEXT debug_context)
{
DWORD dwEax = debug_context->Eax;
__asm
{
push dwEax;
call GetMsgFromStack;
}
}
wstring GetMsgByAddress(DWORD memAddress)
{
if (!IsBadReadPtr((void*)memAddress, 4))
{
wstring tmp;
DWORD msgLength = *(DWORD*)(memAddress + 4);
if (msgLength > 0) {
WCHAR* msg = new WCHAR[msgLength + 1]{ 0 };
wmemcpy_s(msg, msgLength + 1, (WCHAR*)(*(DWORD*)memAddress), msgLength + 1);
tmp = msg;
delete[]msg;
}
return tmp;
}
return L"NULL";
}
//聊天记录的消息结构体
struct ChatMessageData
{
int msgtype; //消息类型
int isphonemsg; //是否是手机发的消息
wstring wxid; //微信ID
wstring sender; //消息发送者
wstring content; //消息内容
wstring filepath; //文件路径
wstring source; //消息来源
};
void __stdcall GetMsgFromStack(DWORD r_eax)
{
try
{
ChatMessageData* msg = new ChatMessageData;
//取出消息类型
msg->msgtype = *((DWORD*)(r_eax + MsgTypeOffset));
//取出消息内容
msg->content = GetMsgByAddress(r_eax + MsgContentOffset);
FILE* file;
file = fopen("E:\\log.txt", "ab+");
fwrite(msg->content.c_str(), msg->content.length(),1, file);
fwrite("\r\n", 3, 1, file);
fclose(file);
}
catch (...)
{
OutputDebugStringA("接收聊天记录出现异常.....");
}
}
评论0