1

I am trying to automate analysis of instructions within exported functions for a .DLL and need to be able to lift the first few instructions for the entry point of each exported function statically from disk without using a debugger.

I retrieve the correct RVA for each exported function (verified by objdump's results):

     $objdump -p examples/MathLibrary.dll
     ...
     Export Table:
     DLL name: MathLibrary.dll
     Ordinal base: 1
     Ordinal      RVA  Name
          1  0x11212  fibonacci_current
          2  0x1118b  fibonacci_index
          3  0x1104b  fibonacci_init
          4  0x11307  fibonacci_next

Then calculate what seems like the correct file offset using:

   fo = exports.address - section.VirtualAddress + section.PointerToRawData

Section refers to .text. Which gives me:

    1 RVA 0x11212 'fibonacci_current' file offset:  1554
    Seeking to offset: 1554 to read 48 bytes.
    Read 14 bytes 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
    2 0x1118b 'fibonacci_index' file offset:  1419
    Seeking to offset: 1419 to read 48 bytes.
    Read 5 bytes 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
    3 0x1104b 'fibonacci_init' file offset:  1099
    Seeking to offset: 1099 to read 48 bytes.
    Read 37 bytes 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
    4 0x11307 'fibonacci_next' file offset:  1799
    Seeking to offset: 1799 to read 48 bytes.
    Read 9 bytes 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0

I'm getting what looks like valid offsets that are located within the .text section however, the bytes there are all 00. This is verified by objdump.

    0001420      0000    0000    0000    0000    0000    0000    0040    4000
    0001440      722e    6c65    636f    0000    05bb    0000    f000    0001
    0001460      0600    0000    9200    0000    0000    0000    0000    0000
    0001500      0000    0000    0040    4200    0000    0000    0000    0000
    0001520      0000    0000    0000    0000    0000    0000    0000    0000
    *
    0002000      cccc    cccc    e9cc    4173    0000    71e9    002e    e900

What am I doing wrong? Is this not where the code is actually located? They aren't being forwarded, so the code is there somewhere. Thanks for your help.

2 Answers 2

1

An RVA is a relative virtual address, it’s not a file offset.

You need to parse the section table to determine how file offsets map to RVAs and use that mapping to find your bytes on disk.

1

if using win32 apis are an option you can try something along this line

the first example command uses cdb to gets rva and bytes for counter checking (something like you do with objdump)

the second is a python script which you can use as refernce to adapt in your language of choice

the third is actual execution and bytes fetched from address

:\>cdb -c "? ntdll!ZwYieldExecution-ntdll;db ntdll!ZwYieldExecution l10;q" cdb | awk "/Reading/,/quit/"
0:000> cdb: Reading initial command '? ntdll!ZwYieldExecution-ntdll;db ntdll!ZwYieldExecution l10;q'
Evaluate expression: 289512 = 00046ae8
77366ae8  b8 90 01 00 00 ba 00 03-fe 7f ff 12 c3 90 90 90  ................
quit:

:\>cat expbyte.py
import ctypes
import sys
if(len(sys.argv) == 3):
    ntstart = ctypes.windll.kernel32.LoadLibraryExW(sys.argv[1],0,2)
    rva = int(sys.argv[2],16)
    buff =[]
    for i in range(0,16,1):
        buff.append(ctypes.c_ubyte.from_address((ntstart+rva+i)).value)
    for i in buff:
        print("%02x " % i, end ="")
else:
    print("usage this script path rva")


:\>expbyte.py c:\Windows\System32\ntdll.dll 46ae8
b8 90 01 00 00 ba 00 03 fe 7f ff 12 c3 90 90 90
:\>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.