Windows 系统API通常前5字节为固定的,因此改成JMP刚好合适:
mov edi, edi
push ebp
mov ebp, esp
我要介绍的方法用了很久,稳定性相当不错的说。
定义一个中继函数 用来跳转到原函数+5字节处。
定义一个假函数,用来处理参数,然后返还给中继函数,假函数中可以伪造参数以及返回值。。你懂得
需要注意函数在代码段,需要修改内存属性,否则写入不了jmp指令。
DWORD GetApiAddress(char* ApiName, char* moudleName)
{
return (DWORD)::GetProcAddress(::GetModuleHandleA(moudleName), ApiName);
}
DWORD org_saveMessageBoxAdreesAdd5Byte = 0;
__declspec(naked) int __stdcall TmpMessageBoxA(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType)
{
__asm {
mov edi, edi
push ebp
mov ebp, esp
jmp org_saveMessageBoxAdreesAdd5Byte
}
}
int __stdcall HookIngMessageBoxA(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType)
{
return TmpMessageBoxA(hWnd, "已经被修改指令的MessageBoxA", lpCaption, uType);
}
bool IsHook = false;
void CMFCApplication1App::HookMessage()
{
if (IsHook == false)
{
DWORD _gMessageBoxA = GetApiAddress("MessageBoxA", "user32.dll");
DWORD oldProtect = 0;
::VirtualProtect((LPVOID)_gMessageBoxA, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
::VirtualProtect((LPVOID)TmpMessageBoxA, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
org_saveMessageBoxAdreesAdd5Byte = _gMessageBoxA + 5;
DWORD jmp_code = (DWORD)HookIngMessageBoxA - _gMessageBoxA - 5;
*((byte*)(_gMessageBoxA)) = 0xe9;
*((DWORD*)(_gMessageBoxA + 1)) = jmp_code;
IsHook = true;
}
::MessageBoxA(NULL, "txt", "测试", 0);
}
