Skip to content

Extracting Linux ELF binaries

extremecoders-re edited this page Sep 10, 2021 · 6 revisions

Pyinstxtractor as of now can natively extract Pyinstaller generated ELF binaries (in the same way as Windows exe) without requiring additional tools. However if you face any errors in the process you can follow the old way described below.

First you need to carve out a part of the ELF first.

The easy way

Using objcopy dump the section named pydata to a file.

$ objcopy --dump-section pydata=pydata.dump testfile.elf

Now you can run pyinstxtractor on the dumped file.

$ python pyinstxtractor.py pydata.dump
[+] Processing pydata.dump
[+] Pyinstaller version: 2.1+
[+] Python version: 37
[+] Length of package: 10728118 bytes
[+] Found 52 files in CArchive
[+] Beginning extraction...please standby
[+] Possible entry point: pyiboot01_bootstrap.pyc
[+] Possible entry point: test.pyc
[+] Found 133 files in PYZ archive
[+] Successfully extracted pyinstaller archive: pydata.dump

You can now use a python decompiler on the pyc files within the extracted directory

The long way

Use readelf to list the section headers.

$ readelf -s testfile.elf
There are 29 section headers, starting at offset 0xa42e08:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000400200  00000200
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.ABI-tag     NOTE             000000000040021c  0000021c
       0000000000000020  0000000000000000   A       0     0     4

--- [ snip ] ---

  [26] .comment          PROGBITS         0000000000000000  00007a10
       0000000000000040  0000000000000001  MS       0     0     1
  [27] pydata            PROGBITS         0000000000000000  00007a50
       0000000000a3b2b6  0000000000000000           0     0     1
  [28] .shstrtab         STRTAB           0000000000000000  00a42d06
       00000000000000ff  0000000000000000           0     0     1

Note the size and offset of the pydata section at the end. In this example, size=0xa3b2b6 and offset=0x7a50. Using the size and offset carve out the part.

$ dd if=testfile.elf bs=1 skip=$((0x7a50)) count=$((0xa3b2b6)) of=pydata.dump

However this will run very slowly since the block size is 1.

Instead, you can split it into two head commands.

$ { head -c $((0x7a50)) >/dev/null; head -c $((0xa3b2b6)); } <testfile.elf >pydata.dump

OR a tail and head.

$ tail -c +$((0x7a50+1)) testfile.elf | head -c $((0xa3b2b6)) >pydata.dump

You can now run pyinstxtractor on the dumped file.

Clone this wiki locally