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 );
}