Search code examples
assemblyreverse-engineeringmemory-addressportable-executablecheat-engine

Find an instruction in an executable file, given its address in a running process?


I'm modifying an old abandonware game to have infinite lives.

The Address that has the instruction dec ecx is not the same as its position in the .exe debugged.

I remembered that an old friend of mine told me once that there was a formula to get the "true" address with the instruction inside the .exe. Cheat engine gives me the Memory Address. I remember that in the math formula, I needed to get the Module, in OllyDbg i get it. But i can't remember the formula. Somebody know how is that math formula? The formula it's very simple! There's another way to get the file position to permanently modify the .exe?


Solution

  • There's a "formula" but you'll actually need to look inside the executable file (although this formula can be simplified based on some assumptions).

    1. Get the in memory address (Virtual Address) of the instruction / data you are interested in. [VA]
    2. Get the base address of the module where the instruction / data lies. [MODBASE]
    3. Subtract MODBASE from VA, you obtain what is called a Relative Virtual Address [RVA]:
      • VA - MODBASE = RVA
    4. Open the binary file (e.g. *.exe or *.dll) with a PE file parser / editor and look at the section headers.
    5. Find in which section your RVA lies.
    6. Once you have found the section in which the RVA is, obtain the section Relative Virtual Address. [SECRVA].
    7. Subtract SECRVA from RVA, you then obtain an [OFFSET].
      • RVA - SECRVA = OFFSET
    8. Get the RawAddress [SECRAWADDR] of the section you found at 5.
    9. Add [OFFSET] to [SECRAWADDR], the result is the offset of the instruction / data you are searching for in the binary file.
      • OFFSET + SECRAWADDR = INSDATAOFFSET (offset of the instruction or data in the file on disk).

    Assumption

    Usually (I insist on usually, sometimes it is not the case), [SECRVA] will be 0x1000 for the first section - which happens to be the code section - and its [SECRAWADDR] will be 0x400.

    So if you are searching for the offset of an instruction based on its address in memory, you can usually assume that:

    • SECRVA = 0x1000
    • SECRAWADDR = 0x400

    Example

    Example based on cmd.exe.

    Let's say I'm searching for this code at 0x1C34B0 when the program is loaded into memory:

    CPU Disasm
    Address   Hex dump          Command                                  Comments
    001C34B0  /$  E8 B3040000   CALL 001C3968
    001C34B5  \.^ E9 2EFEFFFF   JMP 001C32E8
    

    Notice the instruction opcodes (bytes) are: 0xE8B3040000

    1. VA = 0x1C34B0
    2. Searching for the module base in memory (use a debugger or ProcessExplorer; the interesting column here is simply called "Base" in process explorer.):

    CMD Base address

    • MODBASE = 0x1B0000

      1. VA - MODBASE = RVA ; 0x1C34B0 - 0x1B0000 = 0x134B0; RVA = 0x134B0

      2. Opening binary file in PE editor (I use CFF explorer):

    Section headers

    1. Let see in which section 0x134B0 lies:

    first section is .text, its Virtual Address is 0x1000 and its Virtual Size is 0x23E4C (so the end of the section is at 0x1000 + 0x23E4C = 0x24E4C).

    Is 0x134B0 between 0x1000 and 0x24E4C?

    • 0x1000 >= 0x134B0 < 0x24E4C -> True: so the address lies in the .text section.

    Note: repeat the same process for each section until you have found the right one.

    1. SECRVA = 0x1000 (section Virtual Address)

    2. RVA - SECRVA = OFFSET ; 0x134B0 - 0x1000 = 0x124B0

    3. SECRAWADDR = 0x400 (section Raw Address)

    4. OFFSET + SECRAWADDR = INSDATAOFFSET ; 0x124B0 + 0x400 = 0x128B0

    If we look at 0x128B0 in the file we have:

    Offset in binary file

    So we have found exactly the same bytes in file (0xE8B3040000) than in memory.