Как преобразовать формат PE (Portable Executable) в ELF в Linux - PullRequest
8 голосов
/ 02 апреля 2010

Какой лучший инструмент для преобразования двоичных файлов PE в двоичные файлы ELF?

Ниже приводится краткое объяснение этого вопроса:

  1. Предположим, у меня есть простая программа на Си.
  2. Я скомпилировал его, используя gcc для Linux (это дает ELF), и используя 'i586-mingw32msvc-gcc' для Windows (это дает двоичный файл PE).
  3. Я хочу проанализировать эти два двоичных файла на предмет сходства, используя инструмент статического анализа Bitblaze - vine (http://bitblaze.cs.berkeley.edu/vine.html)
  4. Теперь лоза не имеет хорошей поддержки для двоичных файлов PE, поэтому я хотел преобразовать PE-> ELF, а затем продолжить сравнение / анализ.

Поскольку весь анализ должен выполняться в Linux, я бы предпочел утилиту / инструмент, работающий в Linux.

Спасибо

Ответы [ 3 ]

11 голосов
/ 12 ноября 2014

Возможно перестроить EXE как бинарный файл ELF, но полученный бинарный файл очень скоро выйдет из строя из-за отсутствия операционной системы.

Вот один из способов сделать это.

Краткое описание

  1. Дамп заголовков разделов файла EXE.
  2. Извлечение необработанных данных раздела из EXE.
  3. Инкапсуляция необработанных данных раздела в фрагментах сценария компоновщика GNU.
  4. Напишите сценарий компоновщика для создания двоичного файла ELF, включая сценарии из предыдущего шага.
  5. Запустите ld со скриптом компоновщика, чтобы создать файл ELF.
  6. Запустите новую программу и посмотрите, как она работает, поскольку она не работает в Windows (и пытается вызвать функции из таблицы адресов импорта, которая не существует).

Подробный пример

  1. Дамп заголовков разделов файла EXE. Для этого я использую objdump из пакета mingw кросс-компилятора.

    $ 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. Используйте dd (или шестнадцатеричный редактор) для извлечения необработанных данных раздела из EXE. Здесь я просто собираюсь скопировать разделы кода и данных (в этом примере с именами AUTO и DGROUP). Вы можете скопировать дополнительные разделы.

    $ 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
    

    Обратите внимание, я преобразовал смещения файлов и размеры разделов из шестнадцатеричного в десятичное для использования в качестве skip и count, но я использую размер блока 512 байт в dd, чтобы ускорить процесс (пример: 0x0400 = 1024 байта = 2 блока @ 512 байтов).

  3. Инкапсулировать необработанные данные раздела в фрагменты сценариев компоновщика GNU ld (используя директиву BYTE). Это будет использоваться для заполнения разделов.

    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. Напишите сценарий компоновщика для создания двоичного файла ELF, включая сценарии из предыдущего шага. Примечание. Я также выделил место для раздела неинициализированных данных (.bss).

    start = 0x516DE8;
    ENTRY(start)
    OUTPUT_FORMAT("elf32-i386")
    SECTIONS {
        .text 0x401000 :
        {
            INCLUDE "code.ld";
        }
        .data 0x576000 :
        {
            INCLUDE "data.ld";
        }
        .bss 0x5A2000 :
        {
            . = . + 0x0E7800;
        }
    }
    
  5. Запустите скрипт компоновщика с GNU ld, чтобы создать файл ELF. Примечание. Мне нужно использовать режим эмуляции elf_i386, поскольку я использую 64-разрядную версию Linux, в противном случае будет получен 64-разрядный файл ELF.

    $ 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. Запустите новую программу и посмотрите, как она работает, поскольку она не работает в 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 для этого местоположения:

    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
    

Для переноса двоичных файлов в Linux это несколько бессмысленно, учитывая проект Wine. Для ситуаций, подобных ОП, это может быть уместно.

2 голосов
/ 09 декабря 2015

Я нашел более простой способ сделать это. Используйте команду strip.

Пример

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

Параметр -N xxxxxxx указывает полосе обрезать только символ с именем xxxxxxx, который, как мы надеемся, отсутствует в файле. -O elf32-i386 может записать файл в этом формате.

Чтобы увидеть поддерживаемые форматы, запустите

strip --info

Я использую команду strip из mxe , которая в моей системе фактически называется /opt/mxe/usr/bin/i686-w64-mingw32.static-strip.

2 голосов
/ 13 марта 2011

Я не знаю, полностью ли это соответствует вашим потребностям, но есть ли у вас возможность кросс-компиляции с вашей версией gcc для MinGW?

Я имею в виду: скажите: удовлетворяет ли это вашим потребностям, чтобы i586-mingw32msvc-gcc компилировался напрямую в двоичные файлы формата ELF (вместо PE, которые вы получаете в настоящее время). Описание того, как действовать в другом направлении, можно найти здесь - я полагаю, это будет немного хакерским, но вполне возможно сделать эту работу для вас в другом направлении (я должен признать, что у меня нет ' т пробовал).

...