Skip to content

Extracting Linux ELF binaries

extremecoders-re edited this page Mar 28, 2020 · 6 revisions

Pyinstxtractor can also extract Pyinstaller generated ELFs but you need to remove a part of the ELF at the end. The steps are shown below.

1. List the sections headers in the ELF

Using readelf list the section headers.

$ readelf -s test
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
  [ 3] .note.gnu.build-i NOTE             000000000040023c  0000023c
       0000000000000024  0000000000000000   A       0     0     4

--- [ snip ] ---

  [24] .data             PROGBITS         0000000000607a00  00007a00
       0000000000000010  0000000000000000  WA       0     0     8
  [25] .bss              NOBITS           0000000000607a40  00007a10
       0000000000010328  0000000000000000  WA       0     0     64
  [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
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

Note the size and offset of the pydata section at the end. In this example size=0xa3b2b6 and offset=0x7a50

2. Carve out a new file excluding everything after pydata

Using the size and offset found earlier carve out a new file. You can use dd. This may take some time to complete.

$ dd if=test ibs=1 count=$((0xa3b2b6+0x7a50)) obs=2M of=test-carved

Alternatively, instead of dd you can use truncate to remove the section(s) after pydata. In this example, the shstrtab section is located immediately after pydata at an offset of 0xa42d06. We want to remove everything starting from this offset.

$ truncate -s $((0xa42d06)) test

Note that if you use truncate the original file is overwritten, so make sure to make a copy if necessary.

3. Extract

You can now run pyinstxtractor on the carved-out/truncated file.

$ python pyinstxtractor/pyinstxtractor.py test-carved
[+] Processing test-carved
[+] 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: test-carved

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

Clone this wiki locally