Code Injection Reverse Engineering

About me

  • Drake Petersen
  • CS major, A*ES minor 
  • Graduating
  • Co-instruct CMSC389J
  • drakemp@termail.umd.edu
  • gitlab.com/drakemp
  • OS: Mint MATE/i3 (I call it a Mojito)
  • Editor: Emacs/Vim
    • Emacs is the best OS,
    • Vim is the best editor
  • Disassembler: All of them. 

 

Agenda

  • ELF Format
  • Code Injection
  • Demo
  • Reversing Tools
  • Dynamic Tools
  • Reversing the Demo
  • Challenge

ELF Format

Let's go byte by byte!

$ xxd stackoverflow | head
00000000: 7f45 4c46 0101 0100 0000 0000 0000 0000  .ELF............
00000010: 0200 0300 0100 0000 3084 0408 3400 0000  ........0...4...
00000020: 8c21 0000 0000 0000 3400 2000 0900 2800  .!......4. ...(.
00000030: 2300 2200 0600 0000 3400 0000 3480 0408  #.".....4...4...
00000040: 3480 0408 2001 0000 2001 0000 0400 0000  4... ... .......
00000050: 0400 0000 0300 0000 5401 0000 5481 0408  ........T...T...
00000060: 5481 0408 1300 0000 1300 0000 0400 0000  T...............
00000070: 0100 0000 0100 0000 0000 0000 0080 0408  ................
00000080: 0080 0408 5808 0000 5808 0000 0500 0000  ....X...X.......
00000090: 0010 0000 0100 0000 0c0f 0000 0c9f 0408  ................

Not actually, that's too painful

ELF Header

#define EI_NIDENT 16

typedef struct {
        unsigned char e_ident[EI_NIDENT];
        Elf32_Half    e_type;
        Elf32_Half    e_machine;
        Elf32_Word    e_version;
        Elf32_Addr    e_entry;
        Elf32_Off     e_phoff;
        Elf32_Off     e_shoff;
        Elf32_Word    e_flags;
        Elf32_Half    e_ehsize;
        Elf32_Half    e_phentsize;
        Elf32_Half    e_phnum;
        Elf32_Half    e_shentsize;
        Elf32_Half    e_shnum;
        Elf32_Half    e_shtrndx;
} Elf32_Ehdr;
$ readelf -h a.out       ###Output modified slightly  
  Magic:   7f 45 4c 46               \x7fELF
  Class:                             ELF32
  Data:                              little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x8048430
  Start of program headers:          52 
  Start of section headers:          8588 
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         9
  Size of section headers:           40 (bytes)
  Number of section headers:         35
  Section header string table index: 34

e_ -- elf

ph -- program header

sh -- section header

off -- offset

ent -- entry

e_shentsize ?

e_shnum ?

e_phentsize ?

e_shtrndx ?*

Section Header

TRY: 

$ readelf -S /bin/bash

### modified output 
  [Nr] Name              Type      
  [ 0]                   NULL      
  [ 1] .interp           PROGBITS  
  [ 2] .note.ABI-tag     NOTE      
  [ 3] .note.gnu.build-i NOTE      
  [ 4] .gnu.hash         GNU_HASH  
  [ 5] .dynsym           DYNSYM    
  [ 6] .dynstr           STRTAB    
  [ 7] .gnu.version      VERSYM    
  [ 8] .gnu.version_r    VERNEED   
  [ 9] .rela.dyn         RELA      
  [10] .rela.plt         RELA      
  [11] .init             PROGBITS  
  [12] .plt              PROGBITS  
  [13] .plt.got          PROGBITS  
  [14] .text             PROGBITS  
  [15] .fini             PROGBITS  
  [16] .rodata           PROGBITS  
  [17] .eh_frame_hdr     PROGBITS  
  [18] .eh_frame         PROGBITS  
  [19] .init_array       INIT_ARRAY
  [20] .fini_array       FINI_ARRAY
  [21] .data.rel.ro      PROGBITS  
  [22] .dynamic          DYNAMIC   
  [23] .got              PROGBITS  
  [24] .data             PROGBITS  
  [25] .bss              NOBITS    
  [26] .gnu_debuglink    PROGBITS  
  [27] .shstrtab         STRTAB 

What is a section header?

 

 

 

 

What are some sections that are useful to us?

 

    .text

    .got

    .data

   A well defined header that gives information on a section of the binary which is unstructured.

Program Header

Program headers indicates how segments required for execution are to be loaded into virtual memory.

 

There exists a Sections to Segment mapping that specifies which sections are part of which segments. 

 

Most disassemblers do all analysis based on virtual addressing

Binary Layout

Does it matter where the Program and Section headers are in the binary?

 

Where must the ELF Header always exist?

 

Are all Section or Program headers needed?

 

Code Injection

LD_PRELOAD

Without modifying any binary directly we can force our evil library to load before anything else! 

We want our library here!

Static linking stage

Dynamic linking stage

LD_PRELOAD example

#define _GNU_SOURCE
/* Most imports for things you might need, Do Not Delete any */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/fcntl.h>
#include <dlfcn.h>
#include <dirent.h>

/* Compile: gcc -Wall -fPIC -shared -o evil.so framework.c -ldl */
/* -ldl must be last!!! */

static int (*o_open)(const char *, int);
static void init (void) __attribute__ ((constructor));

/* loaded and executed when ld runs */
void init(void){
        /* Get handle on original open */
        o_open=dlsym(RTLD_NEXT, "open");
}

/* Try: LD_PRELOAD=./evil.so cat framework.c */
int open(const char *pathname, int flags, ...){
        /* example */
        printf("Hello world\n");

        /* Your code here */

        /* Preserve functionality */
        return o_open(pathname, flags);
}

Imports for libraries we want to use or hook

SO compile flags

Dynamic set up 

The Hook:

  • Do what we want
  • Call original

Inject into a binary

This is where I recommend this book for more in depth on everything we've done today and more!

 

Simple injection technique is found in chapter 7.

Chapter 7 / Injecting a Code Section

Shell code!

Keep it simple! Library calls are going to make things harder.

 

ENTRY_POINT should be replaced with the entry point of the binary being injected into.

 

All code is available here:

https://practicalbinaryanalysis.com/file/pba-code.tar.gz

/* $ nasm -f bin -o hello.bin hello.s */
/* $ ./elfinject ls.entry hello.bin \
   ".injected" 0x800000 -1 */

BITS 64

SECTION .text
global main

main:
    push rax
    push rcx
    push rdx
    push rsi
    push rdi
    push r11
    
    mov rax, 1 ;write
    mov rdi, 1 ;stdout
    lea rsi, [rel $+hello-$]
    mov rdx, [rel $+len-$]
    syscall

    pop r11
    pop rdi
    pop rsi
    pop rdx
    pop rcx
    pop rax

    push ENTRY_POINT
    ret

hello: db "Hello World", 0x21, 0x0a
len: dd 13

Demo

Better Demo

Hello world is cool, but what about something more interesting?

 

Binary available here:

ter.ps/csecRE

Disassembly tools

Binary Ninja

We can use binja to disassemble and it is the best looking one!

 

Has many plugins, built on python, the Sublime of disassembly

 

 

IDA

IDA is the oldest, works well on windows binaries, detects structures, colors are customizable (if you're into that)

 

Little harder to use, but you get more analysis tools in the background. Basically operates the same way you would Binja

 

Emacs of disassembly

Radare2

Originally written as a hexeditor, grew into a massive disassembler

/debugger/forensics tool all at the same time. 

 

Really hard to use, super powerful, can do pretty much anything. CLI, no good GUI

 

Vim of disassembly plus a toaster&blender&knife set.

Ghidra

Open source Disassembler recently released by the NSA. 

 

Decompilation feature that would cost a lot of money otherwise

 

 

Traces

Ltrace

Library Trace -

Allows us to see the libc calls in the order they are called, as well as arguments to each call

Opening

Malloc

Output

Return values

Strace

System trace -

Similar to ltrace, shows all system calls made by the process in the order they occur and arguments to them.

What is all of this?

What about these?

Syscalls that set up the running process

Syscalls from our process

Ptrace

How does strace and ltrace work?

What can ptrace do?

And a lot more!

Reverse the Demo

We know there's a bind shell

What tools should we use to reverse this binary?

 

Thinks we want to know:

  • Where is the injected code
  • How is it called?
  • What does it actually do?

This is the reversing part btw

Challenge!

This is not a code injection

This is a CTF style challenge, figure out the input to produce the special output.

 

This is has many hints and things to find as you reverse it so that you learn more than you struggle!

CSEC - RE

By Drake P

CSEC - RE

  • 145