#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,则可以通过全局消息钩子注入。
Detours模拟
最新推荐文章于 2025-07-11 11:28:30 发布