Let me be the first to say that this is probably a really bad idea, unless you are very desperate.
On the other hand, this was really fun to write.
Today I wrote some code that patches the first few bytes of user32!MessageBoxExW
, in order to keep a pesky third-party library from showing a prompt when nobody was around to click on it. This overwrites the start of that function with a relative jump to one of my own, which then forwards to a managed function that logs what the message box was trying to tell us.
Actually, this was for a friend’s program. I would probably shy away from doing this if I weren’t only indirectly responsible.
void InstallHook()
{
HMODULE hUser32 = LoadLibrary(L"user32.dll");
PROC pMsgBox = GetProcAddress(hUser32, "MessageBoxExW");
FailIf(pMsgBox == NULL);
// Need to change the memory protection for the
// (read/execute) page in user32.dll before we
//write to it.
MEMORY_BASIC_INFORMATION mbi = {0};
VirtualQuery(pMsgBox, &mbi,
sizeof(MEMORY_BASIC_INFORMATION));
FailIf(!VirtualProtect(mbi.BaseAddress, mbi.RegionSize,
PAGE_READWRITE, &mbi.Protect));
// Copy in the jump instruction... you could of course
// opt to not write this in assembly, but if we've gone this
// far, what's the difference?
__asm
{
// edi <- user32!MessageBoxExW
mov edi, pMsgBox;
// write the opcode for JMP rel32
mov byte ptr [edi], 0xe9;
// eax <- _MessageBoxEx, then
// eax <- _MessageBoxEx - user32!MessageBoxExW
mov eax, offset _MessageBoxEx;
sub eax, edi;
// One byte for jmp, four for the address.
sub eax, 5;
inc edi;
stosd;
};
// Restore the old protection
DWORD oldProtect = 0;
FailIf(!VirtualProtect(mbi.BaseAddress,
mbi.RegionSize, mbi.Protect, &oldProtect));
}
With that in place it’s not hard to erect some managed scaffolding around it, and nobody needs to know your secret. Until they try to run it on an x64, I guess:
static void Main(string[] args)
{
HookMonkey.Install(delegate(MessageBoxInfo mbi)
{
Console.WriteLine(mbi.Text);
return DialogResult.OK;
});
MessageBox.Show("foo bar");
}
You can download some sample code here.