内存劫持
- 本章内存主要涉及 在 其他程序中 申请/读取/修改 执行内存块
- 我们通过劫持目标窗口 回掉函数来 劫持程序的消息
远程线程注入/劫持运行
- 函数运行的本质是 函数地址的执行
- DLL 中的函数在不同设备上有不同的地址
每个程序都有DLL导入表格
- 表格 属性 :函数标志 函数地址
- 在实际程序中(机器码),没有记录函数地址,记录的是函数标志
- 程序运行前 系统填充 DLL表
- 程序运行时 将函数标志替换成函数地址
- 所以我们劫持内存,运行我们插入的代码 要避免使用DLL导入表
CreateRemoteThread
执行的函数的 函数声明是指定的(一个输入,一个返回值)
方案一
- 在远程线程中 注入机器码
- 机器码中不能有DLL的函数
- 机器码中可以有DLL某个函数的函数指针
CreateRemoteThread
远程执行,传输所需DLL的函数指针
方案二
- 我们不注入机器码
- 我们将 我们自己的函数 封装在DLL中
我们直接在远程线程中
CreateRemoteThread
->loadlibrary
加载我们自己的DLL- 注意
loadlibrary
的函数 兼容CreateRemoteThread
所需的函数指针
- 注意
- 这样程序就直接运行我们的
DllMain
void Inject() {
//1. 获取目标进程句柄
DWORD dwPID = 0;
HWND hGame = FindWindowA(NULL, "扫雷");
if (hGame == NULL) {
return;
}
GetWindowThreadProcessId(hGame, &dwPID);
HANDLE hGameProcess = OpenProcess(PROCESS_ALL_ACCESS,
TRUE,
dwPID);
if (hGameProcess == NULL || hGameProcess == INVALID_HANDLE_VALUE) {
return;
}
//2 在目标进程空间中,开辟一块内存,存放待注入的dll路径
LPVOID lpAddr = VirtualAllocEx(hGameProcess,
NULL,
0x1000,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if (lpAddr == NULL) {
return;
}
DWORD dwWritedBytes = 0;
//3 向目标进程的写入注入dll路径
BOOL bRet = WriteProcessMemory(hGameProcess,
lpAddr,
"Superd.dll",
sizeof("Superd.dll"),
&dwWritedBytes);
//4 调用远程线程,使用LoadLibraryA,加载目标dll.
HANDLE hRemoteThread = CreateRemoteThread(hGameProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)LoadLibraryA,
lpAddr,
0,
NULL);
//5 等待DLL 结束运行
WaitForSingleObject(hRemoteThread, INFINITE);
DWORD dwExitCode = 0;
//6 获取DLL句柄
GetExitCodeThread(hRemoteThread, &dwExitCode);
//释放目标进程的注入dll FreeLibrary
CreateRemoteThread(hGameProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)FreeLibrary,
(LPVOID)dwExitCode,
0,
NULL);
}
申请内存空间
- 参见
进程间通信
->virtualallocex
- 注意权限 申请的内存块权限
PAGE_EXECUTE_READWRITE
修改_读取 内存数据
重要函数
FindWindow //根据 窗口class 获取 窗口句柄
getwindowthreadprocessid //根据 窗口句柄 获取 进程句柄
OpenProcess //利用 进程句柄 打开 内存句柄
ReadProcessMemory //读取进程内存
WriteProcessMemory //向进程写入内存
实例
void change_to_god(){
DWORD dwPID = 0;
//根据 窗口名称/窗口class名称 获取 窗口句柄 ,这里是根据 class名称
HWND hGame = FindWindowA(NULL, "摿孭");
//根据 窗口句柄 获取 进程句柄
GetWindowThreadProcessId(hGame, &dwPID);
//根据 进程句柄 获取 内存句柄
HANDLE hGameProcess = OpenProcess(PROCESS_ALL_ACCESS,
FALSE,
dwPID);
//准备写入的数据
BYTE btCode = 0xEB;
//接受 一共写了多少数据
DWORD dwWritedBytes = 0;
//修改数据
BOOL bRet = WriteProcessMemory(hGameProcess,
(LPVOID)0x00403616,
&btCode,
sizeof(BYTE),
&dwWritedBytes);//返回修改了多少数据
}