0

My Rust code needs to make winapi FFIs and I see winapi-rs is very popular. What I need now, is to see the actual instructions of these FFIs. The binary object files are available on github (for example GLU32).

Just as an example, it contains a 663 bytes object file dsjfbs00001.o, which I'd like to disassemble and see the instructions. I've tried without giving an offset (which means it starts at 0):

objdump -b binary -Mintel,x86-64 -m i386 -D dsjfbs00001.o

This line comes from the similar question Disassembling A Flat Binary File Using objdump and I get this output (I show just the first 16 lines, it goes on for 247 lines):

dsjfbs00001.o:     file format binary


Disassembly of section .data:

00000000 <.data>:
   0:   64 86 07                xchg   BYTE PTR fs:[rdi],al
   3:   00 00                   add    BYTE PTR [rax],al
   5:   00 00                   add    BYTE PTR [rax],al
   7:   00 84 01 00 00 0a 00    add    BYTE PTR [rcx+rax*1+0xa0000],al
   e:   00 00                   add    BYTE PTR [rax],al
  10:   00 00                   add    BYTE PTR [rax],al
  12:   04 00                   add    al,0x0
  14:   2e 74 65                cs je  0x7c
  17:   78 74                   js     0x8d
        ...

I have some knowledge about assembler, but here I'm at a loss. The executable code obviously doesn't start at 0 so I wonder how can I discover the correct offset?

The output shows that this is the .data section. But how does it tell this? It this a guess? A hexdump returns exactly the same bytes with no header bytes (i.e. such as an elf file would have):

0000000 8664 0007 0000 0000 0184 0000 000a 0000
0000010 0000 0004 742e 7865 0074 0000 0000 0000

Endianness aside, it starts with 0x64, 0x86, 0x07, as seen above for the xchg opcode. So how can it tell it's a .data section? And then... where's the .text section I'm interested in? It never says there's one.

From all of this I deduce that without an actual offset it's impossible to tell where the entry point is. Actually, the initial ~600 bytes contain many zeroes, while the last ~60 bytes have the typical entropy you'd expect from executable code. But I don't know how to determine this offset exactly by searching in the winapi-rs repo (the *.def files look useless to me, they just list the available routine names).

And as an additional question, would it be feasible to create those file on my own? Can't I just take/write some assembly code, produce an object file with NASM or similar, and use that for FFIs from my Rust code? Is this even possible?

Where would I start doing something like this, if I don't even have C/C++ WinAPI header files or Visual Studio?

BTW: I really need just some ~10 functions of GLU32, not the whole winapi.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
pid
  • 11,472
  • 6
  • 34
  • 63
  • You have chosen a raw binary format which has no sections so objdump invents one for you. – Jester Mar 14 '22 at 23:36
  • 2
    Checking with a hex dump tool it isn't a flat binary file it does have structure and the initial `64 86` is probably a signature for x86-64. I assume there is documentation for this format somewhere. – Jester Mar 15 '22 at 00:05
  • 1
    Looks like object code in COFF format. The hex dump likely shows the [`IMAGE_FILE_HEADER`](https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_file_header) (`0x8664` is a valid machine ID, 7 seems like a reasonable section count, and the remaining fields seem reasonable as well). While it's not clear from the question, what problem you are trying to solve, it all sounds like you're re-inventing what [`raw_dylib`](https://doc.rust-lang.org/beta/unstable-book/language-features/raw-dylib.html) is doing. – IInspectable Mar 15 '22 at 10:25
  • Indeed, the mingw objdump properly decodes the contents without the `-b binary -D`. – Jester Mar 15 '22 at 12:00
  • To both, Jester and IInspectable, thank you for your time and attention. You've already given me several directions I can explore! – pid Mar 15 '22 at 19:16

0 Answers0