64位的Win7下拦截malloc函数

来源:互联网 发布:广州广大淘宝培训 编辑:程序博客网 时间:2024/05/25 23:26

目前大多数项目都在64位系统下开发,很多时候不知道是否malloc溢出,所以我专门花了些时间,写了一个如何拦截malloc的示例程序。


注意该程序必须在64位Release版本下运行,如果是DeBug版本的话,因为编译器没做优化和加了一些debug代码,所以会内存读写报错


// 说明:此test.cpp文件为win7下,对msvcr100.dll动态库中的maollc函数的hook测试文件,//       即拦截win7平台下Release版本的malloc函数// // 作者:过客// 邮箱:386520874@qq.com// 日期:2017.04.17#include "stdafx.h"#include <windows.h>#include <stdlib.h>typedef HANDLE (__stdcall * PFN_GETCURRENTPROCESS)(void);typedef BOOL (__stdcall * PFN_WRITEPROCESSMEMORY)(HANDLE, LPVOID, LPCVOID, SIZE_T, SIZE_T *);typedef DWORD (__stdcall * PFN_GETCURRENTTHREADID)(void);typedef void * (__cdecl * PFN_MALLOC)(size_t _Size);typedef int (__cdecl * PFN_PRINTF)(const char * _Format, ...);//------------------------------------------------#pragma pack(1) //#pragma pack(push, 4) 说明:可以1字节对齐也可以4字节对齐,此处非常重要typedef struct HOOK_PARAM{DWORD pGetCurrentProcess;DWORD pWriteProcessMemory;DWORD pGetCurrentThreadId;DWORD pMalloc;DWORD pPrintf;long long malloc_param_1; //用于保存malloc的输入参数值long long nextIpAddr; //64位地址void * pMallocReturn; //用于保存malloc的返回值DWORD currentThreadId; //用于保存GetCurrentThreadId的返回值char oldCode[20];char newCode[20];char str[100];char str_format[100]; //printf的参数}HOOK_PARAM;#pragma pack() //#pragma pack(pop)//------------------------------------------------void * my_hook_malloc(void *lParam){HOOK_PARAM * p = (HOOK_PARAM *)lParam;PFN_GETCURRENTPROCESS pfnGetCurrentProcess = (PFN_GETCURRENTPROCESS)(p->pGetCurrentProcess);PFN_WRITEPROCESSMEMORY pfnWriteProcessMemory = (PFN_WRITEPROCESSMEMORY)(p->pWriteProcessMemory);PFN_GETCURRENTTHREADID pfnGetCurrentThreadId = (PFN_GETCURRENTTHREADID)(p->pGetCurrentThreadId);PFN_MALLOC pfnMalloc = (PFN_MALLOC)(p->pMalloc);PFN_PRINTF pfnPrintf = (PFN_PRINTF)(p->pPrintf);//恢复API原来的样子,即摘掉API钩子pfnWriteProcessMemory(pfnGetCurrentProcess(), (LPVOID)pfnMalloc, (LPCVOID)(p->oldCode), 20, NULL);//调用正常的mallocp->pMallocReturn = pfnMalloc(p->malloc_param_1);//调用win32 API GetCurrentThreadId()p->currentThreadId = pfnGetCurrentThreadId();//-------------------------------------------------pfnPrintf(p->str_format, p->currentThreadId, p->currentThreadId, p->malloc_param_1, p->malloc_param_1); //将hook到的信息打印出来return p->pMallocReturn; //将malloc申请的内存地址返回}//---------------------------------------int _tmain(int argc, _TCHAR* argv[]){//--------------------------HOOK_PARAM hook_param = {0};::GetCurrentThreadId();HMODULE hKernel32 = LoadLibraryA("kernel32.dll");HMODULE hMsvcr100 = LoadLibraryA("msvcr100.dll");hook_param.pGetCurrentProcess = (DWORD)GetProcAddress(hKernel32, "GetCurrentProcess");hook_param.pWriteProcessMemory = (DWORD)GetProcAddress(hKernel32, "WriteProcessMemory");hook_param.pGetCurrentThreadId = (DWORD)GetProcAddress(hKernel32, "GetCurrentThreadId");hook_param.pMalloc = (DWORD)GetProcAddress(hMsvcr100, "malloc");hook_param.pPrintf = (DWORD)GetProcAddress(hMsvcr100, "printf");hook_param.malloc_param_1 = 0x12345678;//sprintf(hook_param.str, "malloc(): size = ");sprintf(hook_param.str_format, "GetCurrentThreadId() = %%ld = 0x%%X;   malloc(): size = %%ld = 0x%%X;\n");//---------------------------------------------HANDLE hProcess = GetCurrentProcess();int size_Func = 1024 * 1;DWORD dwFunAddr = (DWORD)VirtualAllocEx(hProcess, NULL, size_Func, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); //在进程空间申请内存memset((void *)dwFunAddr, 0, size_Func);int size_Param = sizeof(HOOK_PARAM);DWORD dwParmaAddr = (DWORD)VirtualAllocEx(hProcess, NULL, size_Param, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); //在进程空间申请内存//---------------------------------------------hook_param.newCode[0] = 0x51; //push    rcx //将 char * p = (char *)malloc(0x0637); 的参数 0x0637 入栈hook_param.newCode[1] = 0x68; //0x68: push newcode[2..5],参数先压栈hook_param.newCode[2] = (dwParmaAddr << 24) >> 24;hook_param.newCode[3] = (dwParmaAddr << 16) >> 24;hook_param.newCode[4] = (dwParmaAddr << 8 ) >> 24;hook_param.newCode[5] = (dwParmaAddr << 0 ) >> 24;hook_param.newCode[6] = 0x59; //pop    ecxhook_param.newCode[7] = 0x67; //pop    qword ptr [ecx + 14h] // hook_param.malloc_param_1 = 0x0637; 将malloc(size);的size参数偷偷保存起来hook_param.newCode[8] = 0x8F;hook_param.newCode[9] = 0x41;hook_param.newCode[10] = 0x14;hook_param.newCode[11] = 0x48; //sub    rsp, 20h //目的是平衡栈hook_param.newCode[12] = 0x83;hook_param.newCode[13] = 0xEC;hook_param.newCode[14] = 0x18;int offsetaddr = dwFunAddr - (int)hook_param.pMalloc - 20;hook_param.newCode[15] = 0xE8; //0xE8: call newcode[16..19],然后调用函数 my_hook_mallochook_param.newCode[16] = (offsetaddr << 24) >> 24;hook_param.newCode[17] = (offsetaddr << 16) >> 24;hook_param.newCode[18] = (offsetaddr << 8 ) >> 24;hook_param.newCode[19] = (offsetaddr << 0 ) >> 24;char add_rsp[5] = {0};add_rsp[0] = 0x48; //add    rsp, 20h //目的是平衡栈add_rsp[1] = 0x83;add_rsp[2] = 0xC4;add_rsp[3] = 0x20;add_rsp[4] = 0xC3; //ret//---------------------------------------------SIZE_T dwNumberOfBytesRead = 0;BOOL ret4 = ::ReadProcessMemory(hProcess, (LPCVOID)hook_param.pMalloc, hook_param.oldCode, 20, &dwNumberOfBytesRead); //将malloc函数体原始的前20个字节保存起来,以便hook后恢复BOOL ret5 = ::WriteProcessMemory(hProcess, (LPVOID)hook_param.pMalloc, &hook_param.newCode, 20, &dwNumberOfBytesRead); //在新申请的进程地址空间,写函数my_hook_malloc的参数BOOL ret6 = ::WriteProcessMemory(hProcess, (LPVOID)dwFunAddr, &my_hook_malloc, size_Func, &dwNumberOfBytesRead); //将编译后的函数体写到新申请的进程地址空间BOOL ret7 = ::WriteProcessMemory(hProcess, (LPVOID)(dwFunAddr + 0x8A), &add_rsp, 5, &dwNumberOfBytesRead); //此处目的是为了能正常返回main函数领空, 0x8A是原始函数体的大小BOOL ret8 = ::WriteProcessMemory(hProcess, (LPVOID)dwParmaAddr, &hook_param, size_Param, &dwNumberOfBytesRead);char * p = (char *)malloc(0x0637);sprintf(p, "dddddddd 6666666666: 我hook malloc成功啦! 嚯嚯嚯!");printf("%s\n", p);free(p);CloseHandle(hProcess);return 0;}


0 0
原创粉丝点击