I am writing a program where I map an .exe PE file in memory and I "dissect" it. I am disassembling the .text section of the target executable, using the distorm disassembler.

CALL instructions in the disassembly have an offset relative to the RIP register, e.g.: CALL QWORD [RIP+0xf8e].

I am also reading the Import Descriptor Table and I can see all the function calls from various .dlls there.

When using dumpbin.exe with /section:.text /disasm to disassemble the same target .exe, although it shows the same opcodes ff 15 8e 0f 00 00, it somehow translates this RIP offset to the proper (and correct) Win32 function being called (in my program GetCurrentProcessId()), call qword ptr [__imp_GetCurrentProcessId].

My question is how to "map"/resolve each CALL instruction that I see in my disassembly to a specific Win32 API call, like dumpbin does, since I don't run this program inside the debugger and therefore the IAT is not overwritten by the Windows loader to show the proper jmp instruction calling the Windows API. Is it a disassembler issue? Can I deduct this somehow using the various PE structures?

  • As I understand so far, is that the RIP offset is actually an offset from the current instruction location "somewhere" (in memory? in file?), to another location "somewhere". Opening the target exe IDA disassembler and calculating the offset from the resolved memory location back to the call instruction, results in the RIP offset, 0xf8e in my case.
    – servo
    Apr 11, 2021 at 18:18

1 Answer 1


I found a solution and gonna leave it here for future reference.

First, you need to calculate the linear address (the one the binary will have in run-time) from the RIP offset of the jump. Let's say the RIP offset is 0x8fe. You add this, and the offset of the instruction itself (offset from start of .text section) plus the instruction size and you get a number. You then have to add this number to the start of the .text section, but this time, you need to include the SectionAlignment in your calculation. If the RVA of the .text is 0x400 and the SectionAlignment is 0x1000, then the start of the .text will be at Image Base + 0x1000.

Then you get the imported function names from the ILT Import Directory Table. You do this by reading the OriginalFirstThunk pointer to u1.Ordinal and then to Name. For more details look here.

When doing this, you know the order that the imported functions are imported, per dll.

Now, you need to get the FirstThunk RVA, which will point to a NULL location when the file isn't loaded. However, this RVA is the start of the IAT (in run-time). The size of each import is 8 bytes.

For example, if you see that a CALL QWORD PTR [RIP+0xf8e], you calculate this number and you get (say) 0x0000022D932D2008 which is 8 bytes from the start of the IAT, you know that this call calls the second imported function. Since you know the order, you know which function it is.

Your Answer

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

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