Intro

A linux oriented binary analysis cheatsheet

¡ work in progress - expect regular updates and improvements !

last updated: 18.5.2019 {% include toc.html %}

Resources

Compact ASCII tables

Hex & Decimal

   2 3 4 5 6 7       30 40 50 60 70 80 90 100 110 120
-------------      ---------------------------------
0:   0 @ P ` p     0:    (  2  <  F  P  Z  d   n   x
1: ! 1 A Q a q     1:    )  3  =  G  Q  [  e   o   y
2: " 2 B R b r     2:    *  4  >  H  R  \  f   p   z
3: # 3 C S c s     3: !  +  5  ?  I  S  ]  g   q   {
4: $ 4 D T d t     4: "  ,  6  @  J  T  ^  h   r   |
5: % 5 E U e u     5: #  -  7  A  K  U  _  i   s   }
6: & 6 F V f v     6: $  .  8  B  L  V  `  j   t   ~
7: ' 7 G W g w     7: %  /  9  C  M  W  a  k   u  DEL
8: ( 8 H X h x     8: &  0  :  D  N  X  b  l   v
9: ) 9 I Y i y     9: '  1  ;  E  O  Y  c  m   w
A: * : J Z j z
B: + ; K [ k {
C: , < L \ l |
D: - = M ] m }
E: . > N ^ n ~
F: / ? O _ o DEL

ELF format

Corkami Walkthrough

Example Reference Code

{% highlight c hl_lines=“1 3 4” %} #include

#define FORMAT_STRING “%s” #define MESSAGE “Hello Pizza!\n”

int main(int argc, char *argv[]) { printf(FORMAT_STRING, MESSAGE); return 0; } {% endhighlight %}

Compilation Steps

PREPROCESSING -> COMPILING -> ASSEMBLING -> LINKING

  1. C Preprocessing - will stop earlier and print macros and includes
    $ gcc -E -P <source_file>.c > <preprocessing_output>.i

  2. Compilation - will generate assembly code (intel syntax)
    $ gcc -S -masm=intel <source_file>.c

  3. Assembler # will generate an object file (machine code)
    $ gcc -c <source_file>.c

  4. Linking - incorporates all object files and static libraries in a single binary
    $ gcc <source_file>.c

Resulting files

 <filename>.i   ; preprocessed source
 <filename>.s   ; assembly code
 <filename>.o   ; object file
 <filename>.out ; binary executable

ELF Sections

.init
Performs initialization tasks and it’s the first code to run at startup before jumping to the main entry point.

.fini
Same purpose as .init but runs when the program terminates.

.text
It contains the main program code. This section is executable but not writable.

.rodata
It stores strings constants and is read-only.

.data
It stores default values of initialized values and it is writable.

.bss
It stores uninitialized variables and it is writable.

.got
GOT, or Global Offset Table.
It holds relocations regarding global variables, which are resolved once, at runtime.

.got.plt
It holds relocations about functions absolute addresses and works together with .plt when resolving those references. It is similar to the regular .got, and historically they were the same and has been introduced to mitigate the security weakness of having .got runtime-writable. However .got.plt can be also be runtime-writable when partial-RELRO is enabled and runtime-readonly when full-RELRO is enabled. More information here

.plt
PLT, or Procedure Linkage Table.
It consists of stubs of a well-defined format, made for directing calls from the .text section to the appropriate invoked library location.

.plt.got
This alternative PLT is used when full-RERLO is enabled with the ld option -z now at compile time, telling the dynamic linker that you want to use “now binding.”

.rel Contains information used by the linker when doing static or dynamic relocations.

.dynamic It tells the OS and dynamic linker how to load and set up the binary.

.init_array Contains pointers to functions constructors used during startup (formerly known as .ctors).

.fini_array Contains pointers to functions deconstructors used during (formerly known as .dtors).

ELF static analysis

ELF header

  • dump ELF’s header
    $readelf -h <filename>

Symbols

  • non stripped binary
    $ readelf --syms <filename>.out

  • stripping symbols from a binary
    $ strip --strip-all <filename>.out
    $ readelf --syms <filename>.out

Sections

  • dump all ELF’s sections information
    $readelf --sections --wide <filename>.out

  • dump the .plt section
    $ objdump -M intel --section .plt -d <filename>.out

  • dump the relocs
    $ readelf --relocs <filename>.out

Program headers

  • dump all ELF’s program headers information
    $ readelf --segments --wide <filename>.out

Binary Inspection/Forensic

  • Check magic bytes to obtain file type
    $ file <filename>
  • base64 decode
    $ base64 -d <encoded_file> > <decoded_file>
  • uncompress preview
    $ file -z <compressed_file>
  • uncompress file
    $ tar xvzf <compressed_file>
  • find library dependencies
    $ ldd <filename>
  • dump hex first 128 bytes
    $ xxd -l 128 <filename>
  • dump binary first 128 bytesr
    $ xxd -b -l 128 <filename>
  • dump c-style header first 128 bytes at a 256-bytes offset
    $ xxd -i -s 256 -l 128 <filename>
  • extract 64-bytes long ELF header residing 52 bytes after start, 1 byte a time time
    $ dd skip=52 count=64 if=<input_filename> of=<output_filename> bs=1
  • Calculate total binary file given ELF header only
    total_size = elf_section_header_offset + (elf_section_headers_count * elf_section_header_size)
  • List symbols from object file
    $ nm <filename>
  • List and demangle dynamic symbols from stripped object file
    $ nm -D --demangle <filename>
  • Add current path to the linker environment
    $ export LD_LIBRARY_PATH=`pwd`
  • Trace system calls
    $ strace <filename>`
  • Trace library calls while demangling C++ functions and printing EIP
    $ ltrace -i -C <filename>`

Disassembling

  • simple disassembly of an object file
    $ objdump -M intel -d <filename>.o
  • check relocations inside the object file
    $ readelf --relocs compilation_example.o
  • full binary disassembly
    $ objdump -M intel -d <filename>.out

ELF dynamic analysis

GDB

  • Set a breakpoint
    (gdb) b *0x[address]
  • Show the registers
    (gdb) info registers [specific register]
  • Dump a string at memory address
    (gdb) x/s 0x[memory_address]
  • Dump a four hex words at memory address
    (gdb) x/4xw 0x[memory_address]

Mitigations

Compile-time

  • Partial RELRO
    gcc -g -Wl,-z,relro -o test testcase.c
  • Full RELRO
    gcc -g -Wl,-z,relro,-z,now -o test testcase.c

Binary Injection

  • Assemble a raw binary (removing any ELF overhead and leaving just the code)
    nasm -f bin -o test.bin test.s
  • Inject shellcode into an ELF
    elfinject ps bindshell.bin ".injected" 0x800000 -1