在上一篇的“64位的Win7下拦截malloc函数”基础上,测试crt(c运行时)库几个可能会调用malloc的API函数。
注意:该程序必须在64位Release版本下运行,如果是DeBug版本的话,因为编译器没做优化和加了一些debug代码,所以会内存读写报错
// 说明:此test.cpp文件为win7下,对msvcr100.dll动态库中的maollc函数的hook测试文件,
// 即拦截win7平台下Release版本的malloc函数
//
// 作者:过客
// 邮箱:386520874@qq.com
// 日期:2017.04.18
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
//#include <malloc.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的参数
DWORD dwFunAddr;
DWORD dwParmaAddr;
}HOOK_PARAM;
#pragma pack() //#pragma pack(pop)
HOOK_PARAM hook_param = {0}; //全局变量
//------------------------------------------------
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);
//调用正常的malloc
p->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, p->pMallocReturn); //将hook到的信息打印出来
return p->pMallocReturn; //将malloc申请的内存地址返回
}
//------------------挂上API钩子------------------------------
int hook_on(HANDLE hProcess)
{
//--------------------------
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_format, "GetCurrentThreadId() = %%ld = 0x%%X; malloc(): size = %%ld = 0x%%X; ptr = 0x%%X;\n");
//---------------------------------------------
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.dwFunAddr = dwFunAddr;
hook_param.dwParmaAddr = dwParmaAddr;
//---------------------------------------------
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 ecx
hook_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_malloc
hook_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 dwNumberOfBytesWrite = 0;
BOOL ret4 = ::ReadProcessMemory(hProcess, (LPCVOID)hook_param.pMalloc, hook_param.oldCode, 20, &dwNumberOfBytesWrite); //将malloc函数体原始的前20个字节保存起来,以便hook后恢复
BOOL ret5 = ::WriteProcessMemory(hProcess, (LPVOID)hook_param.pMalloc, &hook_param.newCode, 20, &dwNumberOfBytesWrite); //在新申请的进程地址空间,写函数my_hook_malloc的参数
BOOL ret6 = ::WriteProcessMemory(hProcess, (LPVOID)dwFunAddr, &my_hook_malloc, size_Func, &dwNumberOfBytesWrite); //将编译后的函数体写到新申请的进程地址空间
BOOL ret7 = ::WriteProcessMemory(hProcess, (LPVOID)(dwFunAddr + 0x93), &add_rsp, 5, &dwNumberOfBytesWrite); //此处目的是为了能正常返回main函数领空, 0x8A是原始函数体的大小
BOOL ret8 = ::WriteProcessMemory(hProcess, (LPVOID)dwParmaAddr, &hook_param, size_Param, &dwNumberOfBytesWrite);
return 0;
}
//------------------摘掉API钩子------------------------------
int hook_off(HANDLE hProcess)
{
SIZE_T dwNumberOfBytesWrite = 0;
BOOL ret1 = ::WriteProcessMemory(hProcess, (LPVOID)hook_param.pMalloc, &hook_param.oldCode, 20, &dwNumberOfBytesWrite);
BOOL ret2 = VirtualFreeEx(hProcess, (LPVOID)hook_param.dwFunAddr, 0, MEM_RELEASE);
BOOL ret3 = VirtualFreeEx(hProcess, (LPVOID)hook_param.dwParmaAddr, 0, MEM_RELEASE);
return 0;
}
//---------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hProcess = GetCurrentProcess();
//----------------------------------
printf("\n----------------------------------\n");
hook_on(hProcess);
char * p0 = (char *)malloc(0x0637);
printf("malloc(): p=0x%X\n", p0);
sprintf(p0, "dddddddd 6666666666: 我hook malloc成功啦! 嚯嚯嚯!");
printf("%s\n", p0);
free(p0);
hook_off(hProcess);
//----------------------------------
printf("\n--------------new会调用malloc--------------------\n");
hook_on(hProcess);
int * p1 = new int; //new会调用malloc
printf("new int(): p=0x%X\n", p1);
delete p1;
hook_off(hProcess);
//----------------------------------
printf("\n--------------new []会调用malloc--------------------\n");
hook_on(hProcess);
char * p2 = new char[17]; //new []会调用malloc
printf("new char[](): p=0x%X\n", p2);
delete [] p2;
hook_off(hProcess);
//----------------------------------
printf("\n--------------calloc不会调用malloc--------------------\n");
hook_on(hProcess);
char * p3 = (char *)calloc(10, sizeof(char));
printf("calloc(): p=0x%X\n", p3);
free(p3);
hook_off(hProcess);
//----------------------------------
printf("\n--------------realloc会调用malloc--------------------\n");
hook_on(hProcess);
char * p4 = (char *)realloc(NULL, 23); //realloc会调用malloc
printf("realloc(): p=0x%X\n", p4);
free(p4);
hook_off(hProcess);
//----------------------------------
printf("\n--------------strdup会调用malloc--------------------\n");
hook_on(hProcess);
char str[] = "Hello World 1!";
char * p5 = strdup(str); //strdup会调用malloc
printf("strdup(): p=0x%X\n", p5);
free(p5);
hook_off(hProcess);
//----------------------------------
printf("\n--------------wcsdup不会调用malloc--------------------\n");
hook_on(hProcess);
wchar_t str2[] = L"Hello World 2!";
wchar_t * p6 = wcsdup(str2); //wcsdup不会调用malloc
printf("wcsdup(): p=0x%X\n", p6);
free(p6);
hook_off(hProcess);
//----------------------------------
printf("\n--------------_aligned_malloc会调用malloc--------------------\n");
hook_on(hProcess);
char * p7 = (char *)_aligned_malloc(17, 16); //_aligned_malloc会调用malloc
printf("_aligned_malloc(): p=0x%X\n", p7);
_aligned_free(p7);
hook_off(hProcess);
//----------------------------------
printf("\n--------------_aligned_realloc会调用malloc--------------------\n");
hook_on(hProcess);
char * p8 = (char *)_aligned_realloc(NULL, 17, 16); //_aligned_realloc会调用malloc
printf("_aligned_realloc(): p=0x%X\n", p8);
_aligned_free(p8);
hook_off(hProcess);
//----------------------------------
printf("\n--------------_aligned_offset_malloc会调用malloc--------------------\n");
hook_on(hProcess);
char * p9 = (char *)_aligned_offset_malloc(17, 16, 5); //_aligned_offset_malloc会调用malloc
printf("_aligned_offset_malloc(): p=0x%X\n", p9);
_aligned_free(p9);
hook_off(hProcess);
//----------------------------------
printf("\n--------------_aligned_offset_realloc会调用malloc--------------------\n");
hook_on(hProcess);
char * p10 = (char *)_aligned_offset_realloc(NULL, 17, 16, 5); //_aligned_offset_realloc会调用malloc
printf("_aligned_offset_realloc(): p=0x%X\n", p10);
_aligned_free(p10);
hook_off(hProcess);
//----------------------------------
CloseHandle(hProcess);
return 0;
}