Share
Embed
Advanced exploitation on Linux: ROP and infoleaks
workshop given during hack.lu 2016 conference
exercices can be found on https://github.com/0xmilkmix/training/tree/master/hacklu
Julien Bachmann
October 18, 2016
Transcript
112 slides
-
intro | me • Julien Bachmann / @milkmix_ • Cyber
Security Researcher, Kudelski Security • Guest lecturer in Swiss universities on topics of software exploitation, incident response and malware reverse engineering • Previously • Pentester, incident responder -
software exploitation | rop • Recaps • Intro to ROP
• Bypassing ASLR -
pwn | recaps • Buffer overflow basics • out-of-bound writes
• rewrite saved instructions pointer • redirect process control flow • execute shellcode -
pwn | recaps • Testing • $ ./bof_01 foobar ?
• $ ./bof_01 AAAAAAAAAAAAAAA ? • $ ./bof_01 `python -c ‘print “A”` ? -
pwn | recaps • Stack state at the beginning of
vulnerable() ... &input %eip %ebp buffer ... %ebp -
pwn | recaps • Stack state after call to strcpy()
... &input %eip %ebp AAAA AAAA AAAA %ebp ... -
pwn | recaps • If input is more than 128
bytes ... AAAA AAAA AAAA AAAA AAAA AAAA %ebp ... return address argument -
pwn | recaps • Calling convention on Linux 32 bit
• previous example was using stdcall convention • arguments pushed in reverse order on the stack • callee clean the stack at the end • spot it: ret imm16 -
pwn | recaps • Calling convention on Linux 32 bit
• libc uses cdecl convention • arguments pushed in reverse order on the stack • caller clean the stack at the end • spot it: ret -
pwn | tips • Buffer size calculation • In this
example: get it by reversing the function • Toolbox • MSF pattern_{create, offset}.rb (or bundled in the following) • PEDA / GEF -
pwn | tips • Note for 64 bit exploitation •
Linux addressing is on 48 bits not 64 bits • Meaning maximum canonical address is 0x00007FFFFFFFFFFF • Meaning that you will not get `RIP=0x4141414141414141` but a CPU exception • Break on ret from vulnerable function and check pattern value pointed by RSP -
pwn | tips • In order to start learning exploitation
concepts disable the protections at first • Compilation • remove stack canaries • -fno-stack-protector • OS • disable ASLR system wide for first exercises • # echo 0 > /proc/sys/kernel/randomize_va_space -
pwn | tips • To get a coredump once the
process crash • # echo "core" > /proc/sys/kernel/core_pattern • $ ulimit -c unlimited -
rop | intro • First example only works with all
protections disabled • less likely to happen nowadays on modern systems • maybe if you are lucky or exploiting an embedded system • Protections on multiple layers • compilation • os • Only targeting execution prevention in this workshop -
rop | intro • What do you need to be
able to execute your shellcode ? -
rop | nx • Execution rights ! • memory pages
have access rights • defined in the Page Table Entries • check Intel Developer Manuals -
rop | nx • History • first implementations in August
2004 were software only • ExecShield • W^X • PAX • introduced by Intel in Pentium 4 series • NX bit -
rop | nx • Concept • memory pages should either
contain data or code • rare cases where both can mix • ex: JIT compilers • still, stack and heap can be marked as non-executable most of the time -
rop | nx • Bypass • we cannot add data
in the process and then execute it • so let’s use what is already present ! • ret2libc • rop -
rop | nx | ret2libc • ret2libc • context :
stack is non-executable • libc code is obviously executable • instead of having a shellcode using syscalls, directly call libc functions -
rop | nx | ret2libc • Concept • forge a
stack as the standard execution would • stdcall convention • rewrite execution pointer with function address -
rop | nx | ret2libc • Examples • execute command
line using system • execute process using exec* -
rop | nx | ret2libc • ret2libc!system @“/bin/sh” @system AAAA
AAAA AAAA AAAA AAAA ... %ebp return address argument &input align -
rop | for real • ret2libc next level • calling
a function is fun • but can’t we also directly use instructions or call multiples ? • Return Oriented Programming (ROP) -
rop | famous quote • Dino Dai Zovi • “preventing
the introduction of malicious code is not enough to prevent the execution of malicious computations” -
rop | go go gadgeto • Concept • chain the
execution of simple instructions already in the memory to execute code • simple instructions are called gadgets and are ended by RET • pop eax ; ret • mov [ebx], ecx ; ret -
rop | architecture specificities • Beware • specificity of CISC
architecture (used by Intel processors) • a list of opcodes doesn’t have only one representation • possible to process them at various offsets • concept not applicable on RISC architectures (ARM, MIPS, …) • aligned on 2 bytes for Thumb mode and 4 bytes for standard -
rop | cisc B8 89 41 08 C3 mov eax,
0xc3084189 mov dword ptr [ecx+8], ecx ret -
rop | example • usage examples • write 4 (controlled)
bytes at a controlled address • call function • chain functions calls -
rop | example pop eax ret pop ecx ret mov
[ecx], eax ret + + = write 4 bytes -
rop | chain • In practice • find the gadgets
you need • forge a stack containing their addresses : ROP chain • redirect execution flow to your ROP chain -
rop | find them all • Finding gadgets • Write
your own tools • elfesteem / pefile / capstone • idapython • Existing tools • ropeme, ropper, ropgagdet, rp++, … -
rop | example • Taking our previous example mov dword
ptr [ecx], eax 0x08049668 0xffffdee8 -
rop | example • Taking our previous example • gadget1
: pop eax ; ret • gadget2 : pop ecx ; ret • gadget3 : mov dword ptr [ecx], eax ; ret @gadget 1 AAAA AAAA AAAA ... %ebp return address 0xffffdee8 @gadget 2 0x08049668 @gadget 3 … -
top | example • When vulnerable function returns • eax
= ?? • ecx = ?? @gadget 1 AAAA AAAA AAAA ... esp 0xffffdee8 @gadget 2 0x08049668 @gadget 3 … eip .section .text ... mov eax, 42 ret -
rop | example • After ret instruction • eax =
?? • ecx = ?? @gadget 1 AAAA AAAA AAAA ... esp 0xffffdee8 @gadget 2 0x08049668 @gadget 3 … eip .section .text ... pop eax ret -
rop | example • After pop instruction • eax =
0xffffdee8 • ecx = ?? @gadget 1 AAAA AAAA AAAA ... esp 0xffffdee8 @gadget 2 0x08049668 @gadget 3 … eip .section .text ... pop eax ret -
rop | example • After ret instruction • eax =
0xffffdee8 • ecx = ?? @gadget 1 AAAA AAAA AAAA ... esp 0xffffdee8 @gadget 2 0x08049668 @gadget 3 … eip .section .text ... pop ecx ret -
rop | example • After pop instruction • eax =
0xffffdee8 • ecx = 0x08049668 @gadget 1 AAAA AAAA AAAA ... esp 0xffffdee8 @gadget 2 0x08049668 @gadget 3 … eip .section .text ... pop ecx ret -
rop | example • After ret instruction • eax =
0xffffdee8 • ecx = 0x08049668 @gadget 1 AAAA AAAA AAAA ... esp 0xffffdee8 @gadget 2 0x08049668 @gadget 3 … eip .section .text ... mov dword ptr [ecx], eax ret -
rop | more gadgets • What are useful gadgets ?
• redirect execution to register • stack-pivot • set registers values • read at a memory address • write-what-where • init syscall number • syscall -
rop | pivots • Stack pivoting • we only spoke
about stack based buffer overflow • as such your controlled data is in the stack • other types of exploits might not be as convenient • ex: heap overflow -
rop | pivots • Stack pivoting • ROP chain should
be in the stack • need to change stack pointer register to point to user controlled data • beware: this zone might not be big enough for next calls to push • __kernel_vsyscall crashes usually -
rop | pivots • Examples • mov esp, eax ;
ret • xchg esp, eax ; ret • add esp, #value ; ret -
rop | practice • Demonstration • lets use variation of
previous sample • tp_simple • goal : exit with chosen value • take your VM and follow along • https://github.com/0xmilkmix/training/tree/master/hacklu -
• Step 4 : write functionality in assembly language .section
.text mov eax, 1 mov ebx, 0x42424242 int 0x80 rop | practice -
• Step 5 : requirements • syscall • eax =
0x1 • ebx = 0x42424242 rop | practice -
• Step 6 : define needed instructions • int 0x80
• xor eax, eax • inc eax • pop ebx rop | practice -
• Step 7 : locate gadgets • int 0x80 rop
| practice -
• Step 8 : write exploit • Open your shell
! rop | practice -
• Useful when debugging • break at the end of
the vulnerable function • use si (step into) to go through every instruction • use context to see stack and registers • run vulnerable program through strace to get error messages rop | practice -
• You got it, ROP is about using the code
that’s already present • Now what about the data ? • open(“./super_special_flag”) • address space might not contain super_special_flag rop | bringing data in -
• First idea : use space that is already here
and writable rop | bringing data in -
• Specific sections • .bss or .data • Check that
you have enough place for your data • Note: if you want to call functions such as mprotect remember alignment on page boundary rop | bringing data in -
• Steps 1. use pop gadgets to set registers to
destination and data 2. use mov gadget to write data 3. go back to step 1 rop | bringing data in -
• Write chain for the following call • write(1, “hack.lu”,
7) • on tp_rop • store hack.lu in .data • using only gadgets and not ret2libc technic • https://github.com/0xmilkmix/training/tree/master/hacklu rop | practice -
rop | chaining calls • Sometimes you don’t want to
pop a shell • Maybe you just want to call unlock_door on connected lock • Read content of a file • Bypass seccomp restrictions preventing exec* • Or simply stay out of the radars during an attack/defence CTF -
rop | chaining calls • Calling multiple functions • remember
that they are multiple calling conventions • on 32 bit Linux, libc is mostly using cdecl • which means that the caller has to clean the stack -
• Calling multiple functions • like we saw in ret2libc
part • read • system @read AAAA AAAA AAAA ... %ebp return address 0x1 @buffer 1024 @buffer read args system args @system rop | chaining calls -
• End of read @read AAAA AAAA AAAA ... %esp
0x1 @rbuffer 1024 @ebuffer .section .text read: ... ret eip @system rop | chaining calls -
• Problem • we don’t have the correct arguments •
what would help ? • hint: think gadgets… rop | chaining calls -
• Yes, something to clean the 3 entries we have
in the stack ! • add esp, 0xc ; ret • pop reg1 ; pop reg2 ; pop reg3 ; ret rop | chaining calls -
• Calling multiple functions • using a pop3ret • read
• system @read AAAA … ... %ebp return address 0x1 @buffer 1024 @system @buffer read args system args @pop3ret align rop | chaining calls -
• End of read @read AAAA … ... %esp 0x1
@buffer 1024 @system read args system args @pop3ret .section .text read: ... ret eip @buffer align rop | chaining calls -
• Execution of pop3ret @read AAAA … ... %esp 0x1
@buffer 1024 @system system args @pop3ret .section .text …: pop eax pop ebx pop ecx ret eip @buffer align rop | chaining calls -
• Execution of pop3ret @read AAAA … ... %esp 0x1
@buffer 1024 @system system args @pop3ret .section .text …: pop eax pop ebx pop ecx ret eip @buffer align rop | chaining calls -
• Execution of pop3ret @read AAAA … ... %esp 0x1
@buffer 1024 @system system args @pop3ret .section .text …: pop eax pop ebx pop ecx ret eip @buffer align rop | chaining calls -
• Execution of pop3ret @read AAAA … ... %esp 0x1
@buffer 1024 @system system args @pop3ret .section .text …: pop eax pop ebx pop ecx ret eip @buffer align rop | chaining calls -
• Useful chains • protect / read / shellcode •
dup2 / system • … rop | chaining calls -
• When calling syscalls directly • no need to pop
arguments afterwards since they are passed in registers • Same apply on 64 bit as ABI uses registers to pass parameters also for functions calls • rdi, rsi, rdx, r10, r9, r8 rop | syscalls and 64 bit -
• Detection • ROP can be prevented by ASLR as
we will see in a moment • detection techniques are based on CFI violations • Control Flow Integrity rop | prevention -
rop | prevention • CFI concepts • uses various heuristics
to detect rop chains • high ratio of ret instructions per instructions blocks • shadow stack that validate that ret is returning to instruction following the right call instruction -
rop | prevention • CFI limitations • implementing a shadow
stack degrade performance by at least 30% • as such most implementations are coarse grained • leaving holes that can be exploited • fine grained implementations in some academic r&d projects -
aslr | intro • What do you need if you
want to call a function ? -
• Function address ! • before, code and sections were
loaded at the same address every time • cat /proc/self/maps aslr | intro -
• Concept • Address Space Layout Randomisation • prevent attacker
from using known addresses • ex: return to libc aslr | intro -
• Changes • stack address • heap address • libraries
addresses • main binary address aslr | what is modified -
• Wait, what ? • concept seems ineffective if binary
loading address does not change • still possible to extract gadgets from it • well, some gadgets but not a panacea… • what went wrong? aslr | strange… -
• Requirements • not all binaries (including libraries) are affected
by ASLR • need to be compiled as Position Independant {Executable, Code} • -pie -fPIE • -fPIC aslr | requirements -
• ASLR compatible • list binary headers using readelf •
EXEC : not compatible • DYN : compatible • when in peda use checksec command aslr | checks -
• Other subtleties • three configurations for ASLR • /proc/sys/kernel/randomize_va_space
• 0 : disabled aslr | configuration -
• Other subtleties • 1 : Conservative randomization • stack,
heap, libraries, pie, vdso, mmap() • 2 : full randomization • 1 + memory managed by brk aslr | configuration -
• Methods • brute-force • memory disclosure • binary or
any loaded library not compiled with support for PIE aslr | bypass -
• When lazy or no other possibilities • set the
libc base address to common base • brute-force the remaining 16 bit • only effective on 32 bit systems or if rebasing is built-into the binary • 64 bit Linux has 28 bit of entropy aslr | brute force -
• When the binary is not compiled as position independent
• as said, limited number of gadgets in it • libraries loading address are randomized • but… not the content of the library aslr | disclosure -
system: … … printf: … strcpy: … @??? libc 0xfffc3240
aslr | disclosure -
• Ok, but how to I find it my function
? • generate pattern that appears only once in the library • not present in other ones obviously • need a second vulnerability in the code • memory disclosure aslr | disclosure -
• Usage • extract information using the disclosure • match
it against known value • calculate offset to interesting functions you want to call • or process structure like the GOT aslr | disclosure -
• Variant • highly dependant on the vulnerability you are
exploiting • if able to read /proc/self/maps, extract addresses aslr | disclosure -
• When the main binary is not compiled as position
independent • all text section is loaded at fixed address • this also includes the GOT address aslr | non-pie -
• GOT • Global Offset Table • used as a
mapper to call functions for which loading address is unknown • pretty useful since PIC is mandatory on modern Linux distributions aslr | non-pie -
• GOT • for each offset there is the address
of the corresponding function • filed by the loader when executing the binary • unless lazy binding is used, in this case only once function already called aslr | non-pie -
• GOT • table is specific for each binary •
but : entries can be retrieved using objdump or radare2 • objdump -D ./binary | grep \@plt\>: aslr | dump got -
• Idea • base address of the GOT is known
or has been leaked • read at selected offset to retrieve current address of a function • open the libc binary and retrieve offset from this function • also extract offsets from the desired functions aslr | calculate -
• Details • leaked_address = <value> • libc_base = leaked_address
- offset_leaked_from_base • needed_address = libc_base + offset_needed_from_base aslr | calculate -
• Wait, how do I read the value ? •
as said only a limited number of gadgets in the main binary • still possible to find memory read ones aslr | got gadgets -
• Example of such gadgets • mov eax, [ebx] ;
ret • add eax, [ecx + 0x8042de4c] ; ret • … don’t forget to adjust value in ecx aslr | got gadgets -
• exploit tp_rop_msg • leak useful addresses • gain code
execution • stored shellcode in .data • change page right • execute shellcode • https://github.com/0xmilkmix/training/tree/master/hacklu aslr | practice -
conclusion | outro • Other techniques exists • JOP :
Jump Oriented Programming • SROP : Signal Return Oriented Programming