TransWikia.com

Lifting exported function instructions in PE files

Reverse Engineering Asked on August 8, 2021

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

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.

Answered by Igor Skochinsky on August 8, 2021

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:WindowsSystem32ntdll.dll 46ae8
b8 90 01 00 00 ba 00 03 fe 7f ff 12 c3 90 90 90
:>

Answered by blabb on August 8, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP