使用PE文件格式 HOOK 其他进程API
2012-06-30 22:02
295 查看
今天研究了一下HOOK 其他进程API的方法
有2个前提
1. 使用远程线程注入, 具体可以参考《Windows核心编程》中22-InjLib里面的代码
2. 更改被注入线程所要调用的API地址
2.1 方法一:实用一个网上一个大牛写的类CHookInfo
HookInfo.h
2.2 使用PE格式修改函数地址
这里要注意部分就是红色部分,要反复调试明白PE格式实际定义。
还学到了一个知识就是,函数地址和函数参数是放在不同的位置的。
参数是放在独立的栈中的。而函数地址是放在另一个地方的,暂时学习就这么多。
以后有又明白的部分再添加。
有2个前提
1. 使用远程线程注入, 具体可以参考《Windows核心编程》中22-InjLib里面的代码
2. 更改被注入线程所要调用的API地址
2.1 方法一:实用一个网上一个大牛写的类CHookInfo
HookInfo.h
typedef struct _HOOKSTRUCT { FARPROC pfFunAddr; //用于保存API函数地址 BYTE OldCode[5]; //保存原API前5个字节 BYTE NewCode[5]; //JMP XXXX其中XXXXJMP的地址 }HOOKSTRUCT; class CHookInfo { public: CHookInfo(TCHAR *strDllName, char *strFunName, DWORD dwMyFunAddr); //HOOK 钩子的构造处理函数 //strDllName用于传入模块文件名 //strFunName用于传入模块里的函数名 //dwMyFunAddr用于传入处理函数的地址(代理函数的地址) virtual ~CHookInfo(); //HOOK 钩子的析构函数 HOOKSTRUCT *pHook; //HOOK结构 void HookStatus(BOOL blnHook); //关闭/打开HOOK状态 }; CHookInfo::CHookInfo(TCHAR *strDllName, char *strFunName, DWORD dwMyFunAddr) { pHook = new HOOKSTRUCT; HMODULE hModule = LoadLibrary(strDllName); //载入strDllName模块 //纪录函数地址 pHook-> pfFunAddr = GetProcAddress(hModule,strFunName); //在strDllName模块里检索strFunName函数的地址,GetProcAddress就是返回strFunName函数的地址 FreeLibrary(hModule); //卸载strDllName模块 if(pHook-> pfFunAddr == NULL) { return ; } //备份原函数的前5个字节,一般的WIN32 API以__stdcall声明的API理论上都可以这样进行HOOK (师傅的注释) memcpy(pHook->OldCode, pHook->pfFunAddr, 5); //memcpy:功能:由pHook-> pfFunAddr所指内存区域复制5个字节到pHook-> OldCode所指内存区域。说明:pHook-> pfFunAddr和pHook-> OldCode所指内存区域不能重叠,函数返回指向pHook-> OldCode的指针。 pHook->NewCode[0] = 0xe9; //构造JMP ,JMP(字节值:0xe9)是汇编指令:程序无条件转移指令 DWORD dwJmpAddr = dwMyFunAddr - (DWORD)pHook->pfFunAddr - 5; //计算JMP地址(我想这里是技术点!) memcpy(&pHook->NewCode[1], &dwJmpAddr, 4); HookStatus(TRUE);//开始进行HOOK } CHookInfo::~CHookInfo() { HookStatus(FALSE);//关闭HOOK恢复原函数 } void CHookInfo::HookStatus(BOOL blnHook) { if(blnHook) { WriteProcessMemory((HANDLE)-1, pHook-> pfFunAddr, pHook-> NewCode, 5, 0);//替换函数地址 : (HANDLE)-1进程的句柄,pHook-> pfFunAddr进程地址,pHook-> NewCode数据存放地址,5数据的长度,0实际数据的长度 } else { WriteProcessMemory((HANDLE)-1, pHook-> pfFunAddr, pHook-> OldCode, 5, 0);//还原函数地址 } }
2.2 使用PE格式修改函数地址
//#pragma comment(lib,"th32.lib") #include "..\CommonFiles\CmnHdr.h" /* See Appendix A. */ #include <tchar.h> #include "trace.h" #include "HookInfo.h" #include <iostream> using namespace std; #include "windows.h" #include "process.h" #include "tlhelp32.h" #include "stdio.h" //#pragma comment(lib, "th32.lib") PIMAGE_DOS_HEADER pDosHeader; PIMAGE_NT_HEADERS pNTHeaders; PIMAGE_OPTIONAL_HEADER pOptHeader; PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor; PIMAGE_THUNK_DATA pThunkData; PIMAGE_IMPORT_BY_NAME pImportByName; HMODULE hMod; // 定义MessageBoxA函数原型 typedef int (WINAPI *PFNMESSAGEBOX)(HWND, LPCSTR, LPCSTR, UINT uType); int WINAPI MessageBoxProxy(IN HWND hWnd, IN LPCSTR lpText, IN LPCSTR lpCaption, IN UINT uType); int * addr = (int *)MessageBoxW; //保存函数的入口地址 int * myaddr = (int *)MessageBoxProxy; void ThreadProc(void *param);//线程函数 int WINAPI MyMessageBox(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) { wcout<<L"hWnd:"<<(int)hWnd<<endl; wcout<<L"lpText:"<<lpText<<endl; wcout<<L"lpCaption:"<<lpCaption<<endl; wcout<<L"uType:"<<uType<<endl<<endl; _TRACE(_T("嘿嘿! 调用了我的MessageBox了\n")); return 0; } void TestTP(); //new messagebox function int WINAPI MessageBoxProxy(IN HWND hWnd, IN LPCSTR lpText, IN LPCSTR lpCaption, IN UINT uType) { //return ((PFNMESSAGEBOX)addr)(NULL, "gxter_test", "gxter_title", 0); //这个地方可以写出对这个API函数的处理代码 _TRACE(_T("哈哈!使用我的Dll了\n")); return 1; } //-------------------------------------------------------主函数开始 BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) { if (fdwReason == DLL_PROCESS_ATTACH) { //_TRACE(_T("00\n")); //_beginthread(ThreadProc,0,NULL); //_TRACE(_T("11\n")); //CHookInfo hookInfo(_T("User32.Dll"), "MessageBoxW", (DWORD)MyMessageBox); TestTP(); while (1) {} _TRACE(_T("22\n")); } return TRUE; } //结束进程的函数 void TestTP() { //------------hook api---------------- //_TRACE(_T("TR 00\n")); hMod = GetModuleHandle(NULL); //_TRACE(_T("TR 11\n")); pDosHeader = (PIMAGE_DOS_HEADER)hMod; pNTHeaders = (PIMAGE_NT_HEADERS)((BYTE *)hMod + pDosHeader->e_lfanew); pOptHeader = (PIMAGE_OPTIONAL_HEADER)&(pNTHeaders->OptionalHeader); pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE *)hMod + pOptHeader->DataDirectory[1].VirtualAddress); //_TRACE(_T("TR 22\n")); while (pImportDescriptor->FirstThunk) { _TRACE(_T("TR 33\n")); char * dllname = (char *)((BYTE *)hMod + pImportDescriptor->Name); TCHAR wszDomain[256]; MultiByteToWideChar(CP_ACP, 0, dllname, strlen(dllname)+1, wszDomain, sizeof(wszDomain)/sizeof(wszDomain[0])); //_TRACE(_T("%s\n"), wszDomain); pThunkData = (PIMAGE_THUNK_DATA)((BYTE *)hMod + pImportDescriptor->OriginalFirstThunk); int no = 1; while (pThunkData->u1.Function) { char * funname = (char *)((BYTE *)hMod + (DWORD)pThunkData->u1.AddressOfData + 2); PDWORD lpAddr = (DWORD *)((BYTE *)hMod + (DWORD)pImportDescriptor->FirstThunk) + (no-1); // 测试代码(HH) TCHAR szUser32[] = _T("USER32.dll"); if (0 == memcmp(szUser32, wszDomain, sizeof(TCHAR)*2)) { _TRACE(_T("*lpAdd:%X PK addr:%X\n"), *lpAddr, addr); } //修改内存的部分 if ((*lpAddr) == (int)addr) { _TRACE(_T("MessageBoxW addr is : %X\n"), *lpAddr); //修改内存页的属性 DWORD dwOLD; MEMORY_BASIC_INFORMATION mbi; VirtualQuery(lpAddr,&mbi,sizeof(mbi)); VirtualProtect(lpAddr,sizeof(DWORD),PAGE_READWRITE,&dwOLD); WriteProcessMemory(GetCurrentProcess(), lpAddr, &myaddr, sizeof(DWORD), NULL); //恢复内存页的属性 //VirtualProtect(lpAddr,sizeof(DWORD),dwOLD,0); } //--------- no ++; pThunkData++; } _TRACE(_T("%s有%d个函数\n"), wszDomain, no); pImportDescriptor++; } _TRACE(_T("TR End\n")); //-------------------HOOK END----------------- }
这里要注意部分就是红色部分,要反复调试明白PE格式实际定义。
还学到了一个知识就是,函数地址和函数参数是放在不同的位置的。
参数是放在独立的栈中的。而函数地址是放在另一个地方的,暂时学习就这么多。
以后有又明白的部分再添加。
相关文章推荐
- 使用pefile解析PE文件格式
- hook其他进程的API
- 使用windbg查看PE文件格式
- HOOK其他进程API和全局HOOK-API
- 请问HOOK自己进程API写函数头写到一半,其他线程执行该API时怎么办?
- Hook或者API高手请进-跨进程获取其他程序的DBGrid内容(其它人做的程序)
- HOOK其他进程API和全局HOOK-API
- 使用createprocess()创建进程打开其他文件方法
- c# 读取其他程序正打开的文件的时“正由另一进程使用,因此该进程无法访问该文件。"的问题解决方法
- C# System.IO.FileStream 读取被其他程序打开的文件提示“文件正由另一进程使用,因此该进程无法访问该文件。”
- C# System.IO.FileStream 读取被其他程序打开的文件提示“文件正由另一进程使用,因此该进程无法访问该文件。”
- hook其他进程的API【转载】
- HOOK其他进程API和全局HOOK-API
- C# System.IO.FileStream 读取被其他程序打开的文件提示“文件正由另一进程使用,因此该进程无法访问该文件。”
- C# System.IO.FileStream 读取被其他程序打开的文件提示“文件正由另一进程使用,因此该进程无法访问该文件。”
- hook其他进程的API
- HOOK其他进程API和全局HOOK-API
- SetWindowsHookEx原理(如何使用钩子,使用钩子hook其他进程的函数)
- hook其他进程的API
- PE文件格式详解