14

What's the best tool for converting PE binaries to ELF binaries?

Following is a brief motivation for this question:

  1. Suppose I have a simple C program.
  2. I compiled it using gcc for linux(this gives ELF), and using 'i586-mingw32msvc-gcc' for Windows(this gives a PE binary).
  3. I want to analyze these two binaries for similarities, using Bitblaze's static analysis tool - vine(http://bitblaze.cs.berkeley.edu/vine.html)
  4. Now vine doesn't have a good support for PE binaries, so I wanted to convert PE->ELF, and then carry on with my comparison/analysis.

Since all the analysis has to run on Linux, I would prefer a utility/tool that runs on Linux.

Thanks

6
  • Hi, Aman! Do you want to run Windows binaries on Linux? Converting the executable from PE to ELF isn't a solution! Commented Apr 4, 2010 at 2:36
  • @SiuChingPong: I want to compare the two, I have updated the description, so that people can pitch in with answers. Commented Apr 4, 2010 at 22:24
  • @Aman: I see. Your question is much clearer now. I don't think I'm familiar with the topic enough for answering your question, but I can give you some suggestions the best I can. I visited the link you posted, nowhere mentioned anything about PE or ELF, so may be it works for PE too. Just compile it using MinGW or Cygwin to have a try. Do you know what a "code section" of a binary is? I think if you can extract it and save it to a file, Vine may be able to analyze this "bare binary". Here are some keywords that may be useful: binutils, objdump, objcopy, nm, readelf, ld, lld, ar, as. Commented Apr 5, 2010 at 1:46
  • 2
    Please don't forget to +1 my comments if you find them useful :-). Commented Apr 5, 2010 at 1:47
  • @SiuChingPong: when I ran vine's analysis, there's a warning message that says the tool is not ready for PE binaries. Commented Apr 5, 2010 at 5:17

3 Answers 3

14

It is possible to rebuild an EXE as an ELF binary, but the resulting binary will segfault very soon after loading, due to the missing operating system.

Here's one method of doing it.

Summary

  1. Dump the section headers of the EXE file.
  2. Extract the raw section data from the EXE.
  3. Encapsulate the raw section data in GNU linker script snippets.
  4. Write a linker script to build an ELF binary, including those scripts from the previous step.
  5. Run ld with the linker script to produce the ELF file.
  6. Run the new program, and watch it segfault as it's not running on Windows (and it tries to call functions in the Import Address Table, which doesn't exist).

Detailed Example

  1. Dump the section headers of the EXE file. I'm using objdump from the mingw cross compiler package to do this.

     $ i686-pc-mingw32-objdump -h trek.exe trek.exe: file format pei-i386 Sections: Idx Name Size VMA LMA File off Algn 0 AUTO 00172600 00401000 00401000 00000400 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .idata 00001400 00574000 00574000 00172a00 2**2 CONTENTS, ALLOC, LOAD, DATA 2 DGROUP 0002b600 00576000 00576000 00173e00 2**2 CONTENTS, ALLOC, LOAD, DATA 3 .bss 000e7800 005a2000 005a2000 00000000 2**2 ALLOC 4 .reloc 00013000 0068a000 0068a000 0019f400 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 5 .rsrc 00000a00 0069d000 0069d000 001b2400 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 
  2. Use dd (or a hex editor) to extract the raw section data from the EXE. Here, I'm just going to copy the code and data sections (named AUTO and DGROUP in this example). You may want to copy additional sections though.

     $ dd bs=512 skip=2 count=2963 if=trek.exe of=code.bin $ dd bs=512 skip=2975 count=347 if=trek.exe of=data.bin 

    Note, I've converted the file offsets and section sizes from hex to decimal to use as skip and count, but I'm using a block size of 512 bytes in dd to speed up the process (example: 0x0400 = 1024 bytes = 2 blocks @ 512 bytes).

  3. Encapsulate the raw section data in GNU ld linker scripts snippets (using the BYTE directive). This will be used to populate the sections.

     cat code.bin | hexdump -v -e '"BYTE(0x" 1/1 "%02X" ")\n"' >code.ld cat data.bin | hexdump -v -e '"BYTE(0x" 1/1 "%02X" ")\n"' >data.ld 
  4. Write a linker script to build an ELF binary, including those scripts from the previous step. Note I've also set aside space for the uninitialized data (.bss) section.

     start = 0x516DE8; ENTRY(start) OUTPUT_FORMAT("elf32-i386") SECTIONS { .text 0x401000 : { INCLUDE "code.ld"; } .data 0x576000 : { INCLUDE "data.ld"; } .bss 0x5A2000 : { . = . + 0x0E7800; } } 
  5. Run the linker script with GNU ld to produce the ELF file. Note I have to use an emulation mode elf_i386 since I'm using 64-bit Linux, otherwise a 64-bit ELF would be produced.

     $ ld -o elf_trek -m elf_i386 elf_trek.ld ld: warning: elf_trek.ld contains output sections; did you forget -T? $ file elf_trek elf_trek: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped 
  6. Run the new program, and watch it segfault as it's not running on Windows.

     $ gdb elf_trek (gdb) run Starting program: /home/quasar/src/games/botf/elf_trek Program received signal SIGSEGV, Segmentation fault. 0x0051d8e6 in ?? () (gdb) bt \#0 0x0051d8e6 in ?? () \#1 0x00000000 in ?? () (gdb) x/i $eip => 0x51d8e6: sub (%edx),%eax (gdb) quit 

    IDA Pro output for that location:

     0051D8DB ; size_t stackavail(void) 0051D8DB proc stackavail near 0051D8DB push edx 0051D8DC call [ds:off_5A0588] 0051D8E2 mov edx, eax 0051D8E4 mov eax, esp 0051D8E6 sub eax, [edx] 0051D8E8 pop edx 0051D8E9 retn 0051D8E9 endp stackavail 

For porting binaries to Linux, this is kind of pointless, given the Wine project. For situations like the OP's, it may be appropriate.

Sign up to request clarification or add additional context in comments.

Comments

6

I've found a simpler way to do this. Use the strip command.

Example

strip -O elf32-i386 -o myprogram.elf myprogram.exe 

The -O elf32-i386 has it write out the file in that format.

To see supported formats run

strip --info 

I am using the strip command from mxe, which on my system is actually named /opt/mxe/usr/bin/i686-w64-mingw32.static-strip.

Comments

2

I don't know whether this totally fits your needs, but is it an option for you to cross-compile with your MinGW version of gcc?

I mean do say: does it suit your needs to have i586-mingw32msvc-gcc compile direct to ELF format binaries (instead of the PEs you're currently getting). A description of how to do things in the other direction can be found here - I imagine it will be a little hacky but entirely possible to make this work for you in the other direction (I must admit I haven't tried it).

2 Comments

Your "here" link is a 404
here (if someone could edit the post would be nice)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.