#include "stdafx.h" #include<shlobj.h> #define GET_VIRTUAL_FROM_EXPORT(fun,offset) / (DWORD*)((DWORD)((ULONG)(fun) + (ULONG)( *(ULONG*)((BYTE*)(fun) + 1) ) + 5 + (offset))) void StartDetour(); void StopDetour(); #pragma data_seg(".WXW") HHOOK hhook = NULL; // a handle of hook #pragma data_seg() #pragma comment(linker,"/section:.WXW,rws") HANDLE g_hInstance = NULL; BYTE JmpInstruction[5] = {0xe9};//CallTargetJmp2Detour DWORD *posJmpOffset = NULL;//Back2TargetOffset BYTE OldInstruction[5]; // 该函数共16个字节 extern "C" __declspec(dllexport) int __declspec(naked) Trampoline(){ __asm{ mov edi,edi push ebp mov ebp,esp ;下5个字节被插入的跳转指令覆盖,然后就跳转了 nop nop nop nop nop xor eax,eax pop esp ret 0x10 } } extern "C" __declspec(dllexport) int WINAPI DetourSHFormatDrive(HWND hwnd, UINT drive, UINT fmtID, UINT options) { int rets = 0; // 在调用目标函数之前做些操作 MessageBox(NULL, "Start", "notice", MB_OK); // 跳到Trampoline _asm{ push options push fmtID push drive push hwnd lea eax, Trampoline call eax mov dword ptr [rets], eax } // 目标函数返回后做一些操作 MessageBox(NULL, "Finish", "notice", MB_OK); //StopDetour(); return rets; } void StartDetour() { DWORD dwOld; posJmpOffset = (DWORD *)(JmpInstruction + 1); // "DetourSHFormatDrive"是钩子函数的导出项跳转指令地址,"SHFormatDrive"是格式化函数首指令地址. *posJmpOffset = DWORD((ULONG)DetourSHFormatDrive - (ULONG)SHFormatDrive - 5); VirtualProtect(SHFormatDrive, 5, PAGE_EXECUTE_READWRITE, &dwOld); memcpy(OldInstruction,SHFormatDrive,5); WriteProcessMemory(GetCurrentProcess() , SHFormatDrive, JmpInstruction, 5, &dwOld); VirtualProtect(SHFormatDrive, 5, dwOld, NULL); VirtualProtect(Trampoline, 16, PAGE_EXECUTE_READWRITE, &dwOld); // "Trampoline"是跳板函数导出项跳转指令地址. // 对Trampoline偏移6字节处的双字修改为真正的跳板返回跳转偏移 posJmpOffset = (DWORD *)(JmpInstruction + 1); // 将跳转偏移清零 memset(posJmpOffset, 0, 4); WriteProcessMemory(GetCurrentProcess() ,GET_VIRTUAL_FROM_EXPORT(Trampoline,5), JmpInstruction, 5, &dwOld); *posJmpOffset = DWORD((DWORD)SHFormatDrive + 5 - (DWORD)GET_VIRTUAL_FROM_EXPORT(Trampoline,10)); WriteProcessMemory(GetCurrentProcess() ,GET_VIRTUAL_FROM_EXPORT(Trampoline,5), JmpInstruction, 5, &dwOld); VirtualProtect(Trampoline, 16, dwOld, NULL); } void StopDetour() { DWORD dwOld; VirtualProtect(SHFormatDrive, 5, PAGE_EXECUTE_READWRITE, &dwOld); WriteProcessMemory(GetCurrentProcess() , SHFormatDrive, OldInstruction, 5, &dwOld); VirtualProtect(SHFormatDrive, 5, dwOld, NULL); } LRESULT CALLBACK MyShellProc (int nCode, WPARAM wParam, LPARAM lParam){ return CallNextHookEx(hhook, nCode, wParam, lParam); } extern"C" __declspec( dllexport ) BOOL InstallHook(){ hhook = ::SetWindowsHookEx( WH_GETMESSAGE , MyShellProc ,(HINSTANCE)g_hInstance, 0); if(hhook != NULL){ return TRUE; } return FALSE; } extern"C" __declspec( dllexport ) void UninstallHook(){ if(hhook != NULL){ UnhookWindowsHookEx(hhook); hhook = NULL; } } BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { //OutputDebugString("dllmain..."); //__asm int 3 g_hInstance = hModule; switch (ul_reason_for_call){ case DLL_PROCESS_ATTACH: StartDetour(); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } return TRUE; } 建立远线程将该DLL导入目标线程,也可以调用InstallHook()用全局消息钩子载入,导入后会执行StartDetour() 将格式化操作拦截,这里只是简单的在格式化之前和之后加入一个对话框。 补充一点,在系统开了数据执行保护(DEP)的时候,若通过远程线程注入,必须将跳板函数和钩子函数导出,若系统有修改系统函数的IAT,则可以通过全局消息钩子注入。
09-24