源程序流 -> jmpIn -> 保存寄存器 -> 具体处理 -> 恢复寄存器 -> jmpOut -> 源程序流被跳转指令覆盖的代码可以在 jmpIn之后 或者 jmpOut之前
mov edi, edi
push ebp
mov ebp, esp
三、 可以写 hookProxy 函数,保存和恢复寄存器,统一调用逻辑。
完整代码逻辑:
//.H
#pragma once
__declspec(naked) int Add(int a, int b)
{
_asm
{
mov edi, edi
push ebp
mov ebp, esp
sub esp, 8
mov eax, [ebp+0x08]
mov [ebp-0x08], eax
mov eax, [ebp+0xc]
mov [ebp-0x04], eax
mov eax, [ebp-0x08]
add eax, [ebp-0x04]
mov esp, ebp
pop ebp
ret
}
}
__declspec(naked) void HookProxy()
{
// moved bytes
_asm
{
nop
nop
nop
nop
nop
}
// save registers
//_asm
//{
// pushad
// pushfd
//}
__asm
{
add [esp+0x08], 1
add [esp+0x0c], 1
}
// restore registers
//_asm
//{
// popad
// popfd
//}
// use to jump source func back code
_asm
{
nop
nop
nop
nop
nop
}
}
void InlineHook()
{
// move old bytes
memcpy((BYTE*)HookProxy, (BYTE*)Add, 5);
// rewrite Add the first of 5 bytes to jmp xxxx
BYTE jmpInBuffer[5];
jmpInBuffer[0] = 0xe9;
DWORD* pJmpInOffset = (DWORD*)&jmpInBuffer[1];
*pJmpInOffset = (DWORD)HookProxy - ((DWORD)Add + 5);
memcpy(Add, jmpInBuffer, 5);
// rewrite HookProc the end 0f 5 bytes to jmp xxxx
BYTE jmpOutBuffer[5];
jmpOutBuffer[0] = 0xe9;
DWORD* pJmpOutOffset = (DWORD*)&jmpOutBuffer[1];
BYTE* pJmpBackCode = &((BYTE*)HookProxy)[0xF]; // the pos that the end of 5 bytes
*pJmpOutOffset = ((DWORD)Add + 5) - ((DWORD)pJmpBackCode + 5);
memcpy(pJmpBackCode, jmpOutBuffer, 5);
}
void UnInlineHook()
{
// write back Add the first of 5 bytes
BYTE restoreBuffer[5] = { 0 };
memcpy(restoreBuffer, HookProxy, 5);
memcpy(Add, restoreBuffer, 5);
}
//.CPP
DWORD dwNewProtect = PAGE_EXECUTE_READWRITE;
DWORD oldProtect1;
DWORD oldProtect2;
VirtualProtect((LPVOID)Add, 4096, dwNewProtect, &oldProtect1);
VirtualProtect((LPVOID)HookProxy, 4096, dwNewProtect, &oldProtect2);
InlineHook();
printf("After Hook Result = %d \n", Add(1, 2));
UnInlineHook();
printf("After UnHook Result = %d \n", Add(1, 2));
VirtualProtect((LPVOID)Add, 4096, oldProtect1, &dwNewProtect);
VirtualProtect((LPVOID)HookProxy, 4096, oldProtect2, &dwNewProtect);
四、解析例子
栗子2:
//.H
#pragma pack(1)
typedef struct _JMPCODE
{
BYTE jmp;
DWORD addr;
}JMPCODE, *PJMPCODE;
typedef int (WINAPI *MessageBox_type) (
__in_opt HWND hWnd,
__in_opt LPCSTR lpText,
__in_opt LPCSTR lpCaption,
__in UINT uType);
MessageBox_type RealMessageBox = NULL;
_declspec(naked) int WINAPI MyMessageBox(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
_asm
{
push ebp
mov ebp, esp
}
printf("hwnd:%p lpText:%s lpCaption:%s,uType:%X\n", hWnd, lpText, lpCaption, uType);
_asm
{
mov ebx, RealMessageBox
add ebx, 5
jmp ebx
}
}
void HookMessageBox()
{
RealMessageBox = MessageBoxA;
JMPCODE jumpCode;
jumpCode.jmp = 0xe9;
jumpCode.addr = (DWORD)MyMessageBox - ((DWORD)RealMessageBox + 5);
DWORD dwNewProtect = PAGE_EXECUTE_READWRITE;
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(MessageBoxA, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect);
WriteProcessMemory(GetCurrentProcess(), MessageBoxA, &jumpCode, sizeof(jumpCode), NULL);
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &dwNewProtect);
}
void UnHookMessageBox()
{
// 也可以在Hook的时候保存MessageboxA的前5个字节
BYTE backCode[5] = { 0 };
backCode[0] = 0x8B; // mov edi, edi
backCode[1] = 0xFF;
backCode[2] = 0x55; // push ebp
backCode[3] = 0x8B; // mov ebp, esp
backCode[4] = 0xEC;
DWORD dwNewProtect = PAGE_EXECUTE_READWRITE;
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(MessageBoxA, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect);
WriteProcessMemory(GetCurrentProcess(), MessageBoxA, backCode, sizeof(backCode) / sizeof(backCode[0]), NULL);
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &dwNewProtect);
}
//.CPP
HookMessageBox();
::MessageBoxA(NULL, "HELLO", "WORLD", MB_OK);
UnHookMessageBox();
::MessageBoxA(NULL, "HELLO2", "WORLD2", MB_OK);
执行步骤:
1.把MessageBoxA的前5个字节改写为:jmp xxx(地址是MyMessageBoxA),跳转的指令格式:jmp 相对地址
2.在MessageBoxA中,重新执行原来的汇编指令:(mov edi, edi可忽略)
push ebp
mov ebp, esp
然后执行自己的逻辑
最后再跳转到MessageBoxA中第5个字节的位置继续执行,这里的跳转的指令格式:jmp 16位寄存器
参考:
http://bbs.pediy.com/showthread.php?p=1337589