简体   繁体   中英

Strange behavior when obtaining addresses of functions

I've yet again been faced with the challenge of a slight hack in my code to accommodate for an unmodifiable library of some poorly written code.

After hours of research (after finding out you cannot pass any sort of state to a function pointer), I need to NOP out the ASM bytes within the function header that reset EAX to 0xCCCCCCCC.

By using the built in VC++ debugger to obtain the 'address' of the function and manually creating an array of bytes entry in cheat engine (which is surprisingly useful for this sort of thing), it successfully pulled up the bytes and I could NOP the 5 byte sequence manually.

However, doing this programmatically is a little different.

When I do any of the following, the address is significantly higher than what the debugger is reporting, this giving me a pointer to the wrong bytes.

unsigned int ptr = reinterpret_cast<unsigned int>(testhack);
unsigned char* tstc = (unsigned char*)&testhack;
FARPROC prc = GetProcAddress(GetModuleHandle("mod.dll"), "testhack"); // Still
                    // returns the incorrect address (same as the previous two)

What is the debugger doing to find the correct address? How can I find the correct address programmatically?

Presumably the function address is in a DLL. In that case what you're seeing is the loader relocating the addresses of for example &testhack into the correct location for the memory in which your program is loaded. The debugger probably already knows about the relocations and is helpfully automatically taking care of that for you, allowing you to modify the bytes.

Unfortunately I'm not aware of any mechanism to work around this, but if you link statically the addresses will be fixed at link time rather than runtime.

Figured it out.

Totally forgot about (what I believe are called) lookup tables. The address I was receiving was the pointer to the lookup table entry, which was a simple 5-byte unconditional JMP to the real function body. All I had to do was get the offset, add it to the end of the lookup table entry, and then I had my correct address.

Here is the code to reach the correct start address of the function.

// Get the lookup table address
const char* ptr = (const char*)&testhack;
// Get the offset (+ 1 byte retrieved as a long)
unsigned int offset = (unsigned int)(*((unsigned int*)(ptr + 1)));
// Add to the original look up pointer, +5 (the offset starts after the
//    end of the instruction)
const char* tst = (const char*)(ptr + offset + 5);

tst then holds the correct address!

As of now, the calling ASM instructions put the pointer to the struct containing the function pointers into EAX. Normally, the callback function would reset EAX. However, I've applied this hack and NOP'd out that part. The first lines of code within the function create a local pointer, and then inline assembly to mov [ptr],eax the address into the pointer. I can then use the pointer normally.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM