Post Memory Corruption

Memory Analysis

Jonathan Brossard

CEO – Toucan System

jonathan@ toucan-system.com

Who am I ?

(a bit of self promotion ;)

-Security Research Engineer, CEO @ Toucan System (French Company).

-Known online as endrazine (irc, twitter...)

-Met some of you on irc.

-Currently lives in Sydney (pentester for CBA).

-Speaker at several conferences : Defcon/HITB/HES/Ruxcon/h2hc...

-Organiser of the Hackito Ergo Sum conference (Paris).

I don't reverse plain text

Agenda

A few basics

Being environment aware

PMCMA Design

Extending Pmcma

•Stack desynchronization

What's pmcma ?

It's a debugger, for Linux (maybe one day *NIX) ptrace() based.

Pmcma allows to find and test exploitation scenarios.

Pmcma's output is a roadmap to exploitation, not exploit code.

Tells you if a given bug triggering an invalid memory access is a vulnerability, if it is exploitable with the state of the art, and how to exploit it.

What's pmcma ?

DEMO

Tool available at http://www.pmcma.org

A FEW BASICS

How do applications

crash ?

*Stack corruptions -> stack overflows, usually now detected because of SSP | studied a LOT

*Signal 6 -> assert(),abort(): unexpected execution paths (assert() in particular), heap corruptions

*Segfault (Signal 11) -> Invalid memory access

Invalid memory access

-trying to read a page not readable. often not mapped at all.

-trying to write to a page not writable. often not mapped at all.

-trying to execute a page not executable. often not mapped at all.

Why do they happen ?

Because of any kind of miscomputation, really :

-integer overflows in loop counters or destination registers when copying/initializing data, casting errors when extending registers or

-uninitialised memory, dangling pointers

-variable misuse

-heap overflows (when inadvertently overwriting a function ptr)

-missing format strings

-overflows in heap, .data, .bss, or any other writable section (including shared libraries).

-stack overflows when no stack cookies are present...

Exploiting invalid exec

Trivial, really. Eg :

call eax

with eax fully user controled

Invalid memory reads (1/2)

Eg :

CVE-2011-0761 (Perl)

cmp BYTE PTR [ebx+0x8],0x9

Invalid memory reads (2/2)

Eg :

CVE-2011-0764 (t1lib)

fld QWORD PTR [eax+0x8]

Exploiting invalid memory

reads ?

-usually plain not exploitable

-won't allow us to modify the memory of the mapping directly

-in theory : we could perform a user controled read, to trigger a second (better) bug.

Invalid memory writes

Eg :

CVE-2011-1824 (Opera)

mov DWORD PTR [ebx+edx*1],eax

How to...

To exploit invalid writes, we need to find ways to transform an arbitray write into an arbitrary exec.

The most obvious targets are function

pointers.

Exploiting invalid memory

writes : scenario

-Target a known function pointer (typically : .dtors, GOT entry...).

Can be prevented at compile time :

no .dtors, static GOT...

-Target function pointers in the whole binary ?

-Overwrite a given location to trigger an other bug (eg : stack overflow)

Being environment aware

Problems to take into

account

-Kernel : ASLR ? NX ?

-Compilation/linking : RELRO (partial/full) ? no .dtors section ? SSP ?

FORTIFY_SOURCE ?

=> Pmcma needs to mesure/detect those features

ASLR

Major problem when chosing an exploitation strategy.

ASLR : not perfect

-Prelinking (default on Fedora) breaks ASLR

-All kernels don't have the same randomization strength.

-Non PIE binaries

=> Truth is : we need better tools to test it !

Testing ASLR

-Run a binary X times (say X=100) -Stop execution after loading

-Record mappings.

=> Compare mappings, deduce randomization

DEMO : being environment aware

PMCMA DESIGN

GOALS

-We want to test overwriting different memory locations inside a process and see if they have an influence over the flow of execution

-We want to scale to big applications (web browsers, network deamons...)

-We want a decent execution time

mk_fork()

The idea :

-We start analysing after a SEGFAULT -We make the process fork() (many

many times)

-Inside each offspring, we overwrite a different memory location

mk_fork() : benefits

Mapping looks « just like » it will when actually exploiting a binary

No ASLR/mapping replication problem

Exhaustive and hopefully fast

How to force a process to

fork ?

1)Find a +X location mapped in memory.

2)Save registers

3)Use ptrace() to inject fork() shellcode.

4)Modify registers so eip points to shellcode.

5)Execute shellcode.

6)Wait() for both original process and offspring.

7)Restore bytes in both processes.

8)Restore registers in both processes.

Forking shellcode

;forking shellcode:

xor eax,eax

00000000

6631C0

00000003

B002

mov al,0x2

00000005

CD80

int 0x80

mk_fork()

Original process

Executable

Writable

Executable

…

Offspring 2

Executable

Writable

 

 

 

Executable

 

 

 

 

 

 

 

 

 

Offspring 1

…

 

 

 

 

Executable

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Writable

 

 

 

 

 

 

Executable

…

mk_fork()

Offspring 1

Executable

Writable

Executable

…

mk_fork()

Offspring 2

Executable

Executable

…

mk_fork()

Offspring n

Executable

Writable

Executable

…

mk_fork() : PROS

-allows for multiple tests out of a single process

-fast, efficient (no recording of memory snapshots)

-no need to use breakpoints

-no single stepping

mk_fork() : CONS

-Dealing with offsprings termination ? (Zombie processes)

-I/O, IPC, network sockets will be in unpredictable state

-Hence syscalls will get wrong too (!!)