Question

At first, I'm a newbie on c++ and debuging. I use CreateProcess api with DEBUG_ONLY_THIS_PROCESS parameter, then wait for CREATE_PROCESS_DEBUG_EVENT. When recived, i check for the Eip register to get the address of the point. And i tought that this point is the Main function's address.

To verify this idea i used ollydbg to see the starting address of the exe. But it wasn't same with mine. The one i found with debug apis is 0x77a364d8, but olly says that it's 0x00401000. Then i didn't stop and checked for the address 0x77a364d8 in olly. I found the address and set a breakpoint there.

Then I reloaded the olly and saw that olly firstly goes 0x77a364d8 address and loades the process and then goes to the 0x00401000 address and waits there. 0x77a364d8 address points some ntdll functions to load process to memory as i see.

If it's true, how can i get the 0x00401000 address by code( c++, i'm a newbie and please cross the t's :) ), and is it the Main function's address or what?

Was it helpful?

Solution

After you receive the CREATE_PROCESS_DEBUG_EVENT you should be able to access the CREATE_PROCESS_DEBUG_INFO member of the union. It has a member called lpStartAddress.

Your debugging event loop should look something like:

DWORD dwContinueDebugStatus = DBG_CONTINUE;
while(dwContinueDebugStatus)
{
    DEBUG_EVENT debugEvt;
    WaitForDebugEvent(&debugEvt, INFINITE);
    switch(debugEvt.dwDebugEventCode)
    {
    case CREATE_PROCESS_DEBUG_EVENT:
        // Grab the main thread entry point.
        LPTHREAD_START_ROUTINE exentry = debugEvt.u.CreateProcessInfo.lpStartAddress;
        break;
        /* Handle the rest of your debug events here. */
    }
    ContinueDebugEvent(debugEvt.dwProcessId, debugEvt.dwThreadId, dwContinueDebugStatus);
}

Edit: A couple things I forgot to mention...

Getting the entry point by any of these means will likely be the CRT function that calls your main(). There isn't a reliable way to get the main() without symbol lookups in using dbghelp.dll.

Also, the book Debugging Applications by John Robbins has a chapter about creating a small debugger with some example code. It is probably the best documentation/example I've found (but I wish it were better). It can be had pretty cheap so it might be worth looking at.

OTHER TIPS

The entry point will not (at least normally) be the same as main. The signature for the entry point is void entrypoint(void);. That has to retrieve the command line, parse it into individual arguments, etc., in preparation for calling main (and there's an entirely separate one that retrieves the rather different "stuff" necessary before calling WinMain in a GUI program).

If you want the actual address of main, you might want to at least try using SymFromName for the names _main and/or _wmain (or, if you might be dealing with a GUI program, WinMain/wWinmain) to get to code that's really part of the target program instead of something from a library module almost nobody has ever even seen.

This is all from memory, so it might contain a few mistakes.

In order to find the entry point address of the EXE in a new process, you need to read this process's PEB field ImageBaseAddress. The PEB is always at a fixed address, but it depends on if your EXE is 32 or 64-bit, which you'll have to determine beforehand (there is a 32-bit PEB for WOW64 but I think it may not be initialized yet at that point).

Note that you can't just fetch this from the EXE because it might be relocated due to ASLR. Once you have this, you can read PE header of the EXE using ReadProcessMemory and get the AddressOfEntryPoint field from the IMAGE_OPTIONAL_HEADER struct. It's an RVA so add it to the base address found earlier, and voila, you have your entry point address.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top