I'm trying to write a trampoline function/hook for a misbehaving function in a DLL (Windows, 32 bit, no source available). After failing to do it the "traditional" way, I noticed that the function is a virtual member function of a class and therefore should have an entry in a vtable, which I found. When I then tried to overwrite that to point to my gateway function instead, nothing happened and the entry remained unchanged when looking at it with a debugger. I know that the function that does the overwriting works as expected and from what I can tell, there are no errors when trying to do the writing.
Here's the overwriting function for reference. Not the cleanest piece of programming, but it works. data
is the address of my gateway function in this case.
void writeToMem(DWORD addr, BYTE *data, const size_t len, BYTE *oldData)
{
DWORD oldProtect, newProtect;
VirtualProtect((LPVOID)addr, len, PAGE_READWRITE, &oldProtect);
if (oldData != NULL)
{
memcpy(oldData, (LPVOID)addr, len);
}
memcpy((LPVOID)addr, data, len);
VirtualProtect((LPVOID)addr, len, oldProtect, &newProtect);
}
When I use this to overwrite CALL
s in the .text section this works fine, but when I try to change the vtable in the .rdata section, nothing seems to happen. According to the docs, there shouldn't be too much of a difference except for the initial protection, which I'm already changing, and the characteristics (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
for .rdata and IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IIMAGE_SCN_MEM_READ
for .text). As for the latter, I couldn't find anything in the docs ore elsewhere on what the implications of these flags are.
Where is the difference between the .rdata and the .text section that prevens me from writing to it?