Software exploitation : ROP

Software exploitation : ROP

Introduction course on ROP techniques given to 3rd year Bachelor level students.
Corresponding code can be found at:


Julien Bachmann

June 04, 2015


  1. Software exploitation : ROP Julien Bachmann .text .global _start _start:

    push $5 pop %eax cltd pushl %edx push $0x79 push $0x656b2f2e movl %esp,%ebx pushl %ex pushl %ebx pushl %edx int $0x80 mov $100,%dl sub %edx,%esp mov %esp,%ecx xchg %eax,%ebx push %edx push %ecx push %ebx xorl %eax,%eax pushl %eax push $3 pop %eax int $0x80 movb $0xff,0x4(%esp) movl %eax,0xc(%esp)
  2. introduction About Objectives

  3. intro | me Julien Bachmann / @milkmix_ Currently Cyber Security

    Architect, Kudelski Security Guest lecturer at HEIG-VD & Uni-Biel on software exploitation techniques Guest lecturer at UNIMAIL on malware and incident response Past 6 years : SCRT & ilion Security Penetration tester Incident responder
  4. intro | about Pre-requisites Knowledges on operating systems internals C

    and x86 assembly Previous course on software exploitation basics Environment Linux with 32bits binaries No Windows, iOS or Android exploitation today :( Examples
  5. intro | objectives Attack Understanding flaws impacting software Exploitation of

    those Defence Solutions to prevent trivial exploitation
  6. exploitation techniques Recaps Detailled exploitation Protections and bypass techniques

  7. pwn | recaps Buffer overflow basics out-of-bound writes rewrite saved

    instructions pointer redirect process control flow execute shellcode
  8. pwn | recaps Sample program

  9. pwn | recaps Testing $ ./bof_01 foobar ? $ ./bof_01

    AAAAAAAAAAAAAAA ? $ ./bof_01 `python -c ‘print “A”` ?
  10. pwn | recaps Stack state at the beginning of vulnerable()

    ... &input %eip %ebp buffer ...
  11. pwn | recaps Stack state after call to strcpy() ...

    &input %eip %ebp AAAA AAAA AAAA %ebp ...
  12. pwn | recaps If input is more than 128 bytes

    ... AAAA AAAA AAAA AAAA AAAA AAAA %ebp ... return address argument
  13. pwn | recaps Calling convention 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
  14. pwn | recaps Calling convention libc uses cdelc convention arguments

    pushed in reverse order on the stack caller clean the stack at the end spot it: ret
  15. pwn | tips Buffer size calculation In this example: get

    it by reversing the function IDA Pro tips Toolbox MSF pattern_{create, offset}.rb PEDA
  16. pwn | tips In order to learn exploitation concepts disable

    the protections Compilation -fno-stack-protector -z execstack OS echo 0 > /proc/sys/kernel/randomize_va_space
  17. pwn | tips To get a coredump once the process

    crash echo "core" > /proc/sys/kernel/core_pattern ulimit -c unlimited
  18. pwn | tips Check that your shellcode is working

  19. pwn | details In the previous example shellcode address more

    or less known possible to use nop-sled to secure the exploitation
  20. pwn | details Shellcode position in local exploitation environment variable

    command line
  21. pwn | details 0xBFFFFFFF 0x00000000 argv[0] “/bin/sh” env[1] “PATH=...” env[0]

    “USER=...” argv[1] “--version” argv[0] “/bin/sh” 0x00000000 *envp *envp 0x00000000 *argp *argp local var **envp **argp argc @ret ebp ... $ /bin/sh --version
  22. pwn | details What if the address could not be

    calculated? ex: user controlled input stored on the heap Check for references at the moment you take control registers stack
  23. pwn | details RET 2 reg return to register find

    instruction redirecting control flow to stored value jmp eax call ecx
  24. pwn | details POP 2 RET context: address to user-controlled

    buffer is stored in the stack find pop instruction(s) followed by a ret instruction pop useless values ret
  25. pwn | details value @pop/ ret %ebp buffer ... ebp

    return address argument &input After the overflow
  26. pwn | details At the end of the function value

    @pop/ ret eip &input
  27. pwn | details POP value @pop/ ret eip &input eip

    .section .text ... pop eax ret
  28. pwn | details RET value @pop/ ret eip &input eip

    .section .text ... pop eax ret
  29. protections | intro First example only works with all protections

    disabled less likely to happen nowadays maybe if you are lucky or exploiting an old system, … Protections on multiple layers compilation os
  30. protections | intro What was the root cause of this

  31. protections | unsafe ops Unsafe memory copy operation ! leading

    to out-of-bound memory accesses strcpy, strcat, memcpy, gets, scanf, sprintf, realpath, …
  32. protections | unsafe ops Microsoft Safe String API generate compiler

    warnings while using those functions GCC #pragma GCC poison allows to generate error when identifier found in code
  33. protections | unsafe ops GCC FORTIFY_SOURCE if that macro is

    enabled it checks for basic vulnerabilities compile time : static array copied using libc functions execution time : ___strcpy_chk -D_FORTIFY_SOURCE=1 -O2
  34. protections | unsafe ops

  35. protections | unsafe ops

  36. protections | unsafe ops Warning beware of home made memory

    operation functions my_memcopy using a loop …
  37. protections | intro What do you need to be able

    to modify the control flow in this example ?
  38. protections | canary Smash the stack ! need to be

    able to overwrite saved EIP other possibilities, but that will be for another course
  39. protections | canary Detect overflows use canaries, like in the

    mines pro-police in GCC -fstack-protector[strong/-all]
  40. protections | canary Before Pro-Police ... &input %eip %ebp buffer

  41. protections | canary With Pro-Police ... &input %eip %ebp buffer

    ... canary
  42. protections | canary Canary generate random value at process start

    value written in the stack before local variables (simplest use-case) compiler inserts check before ret instruction
  43. protections | canary

  44. protections | canary | bypass How to bypass this ?

    1. on Unix requires to know the value 2. could try a brute-force if entropy is too small 3. use a memory leak vulnerability to retrieve the value
  45. protections | intro What do you need to be able

    to execute your shellcode ?
  46. protections | nx Execution rights ! memory pages have access

    rights defined in the Page Table Entries check Intel Developer Manuals
  47. protections | nx History first implementations in August 2004 were

    software only ExecShield W^X PAX introduced by Intel in Pentium 4 serie NX bit
  48. protections | 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
  49. protections | nx Bypass we cannot add data in the

    process and then execute it so let’s use what is already present ! ret2libc rop
  50. protections | nx | ret2libc ret2libc context : stack is

    non-executable libc code is obviously executable instead of having a shellcode using syscalls, directly call libc functions
  51. protections | nx | ret2libc Concept forge a stack as

    the standard execution would stdcall convention rewrite execution pointer with function address
  52. protections | nx | ret2libc Examples execute command line using

    system execute process using exec*
  53. protections | nx | ret2libc ret2libc!system @“/bin/sh” @system AAAA AAAA

    AAAA AAAA AAAA ... %ebp return address argument &input align
  54. protections | nx | rop ret2libc next level calling a

    function is fun but can’t we also directly use instructions or call multiples ? Return Oriented Programming (ROP)
  55. protections | nx | rop Dino Dai Zovi “preventing the

    introduction of malicious code is not enough to prevent the execution of malicious computations”
  56. protections | nx | rop 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
  57. protections | nx | rop 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, …)
  58. protections | nx | rop B8 89 41 08 C3

    mov eax, 0xc3084189 mov dword ptr [ecx+8], ecx ret
  59. protections | nx | rop usage examples write 4 (controlled)

    bytes at a controlled address call function chain functions calls
  60. protections | nx | rop pop eax ret pop ecx

    ret mov [ecx], eax ret + + = write 4 bytes
  61. protections | nx | rop In practice find the gadgets

    you need forge a stack containing their addresses : ROP chain redirect execution flow to your ROP chain
  62. protections | nx | rop Finding gadgets Write your own

    tools elfesteem / pefile / capstone idapython Existing tools ropeme, ropgagdet, rp++
  63. Taking our previous example protections | nx | rop mov

    dword ptr [ecx], eax 0x08049668 0xffffdee8
  64. protections | nx | rop Taking our previous example gadget1

    : pop eax ; ret gadget2 : pop ecx ; ret gadget3 : mov dword ptr [ecx], eax ; ret @gadget1 AAAA AAAA AAAA ... %ebp return address 0xffffdee8 @gadget2 0x08049668 @gadget3 …
  65. protections | nx | rop When vulnerable function returns eax

    = ?? ecx = ?? @gadget1 AAAA AAAA AAAA ... esp 0xffffdee8 @gadget2 0x08049668 @gadget3 … eip .section .text ... mov eax, 42 ret
  66. protections | nx | rop After ret instruction eax =

    ?? ecx = ?? @gadget1 AAAA AAAA AAAA ... esp 0xffffdee8 @gadget2 0x08049668 @gadget3 … eip .section .text ... pop eax ret
  67. protections | nx | rop After pop instruction eax =

    0xffffdee8 ecx = ?? @gadget1 AAAA AAAA AAAA ... esp 0xffffdee8 @gadget2 0x08049668 @gadget3 … eip .section .text ... pop eax ret
  68. protections | nx | rop After ret instruction eax =

    0xffffdee8 ecx = ?? @gadget1 AAAA AAAA AAAA ... esp 0xffffdee8 @gadget2 0x08049668 @gadget3 … eip .section .text ... pop ecx ret
  69. protections | nx | rop After pop instruction eax =

    0xffffdee8 ecx = 0x08049668 @gadget1 AAAA AAAA AAAA ... esp 0xffffdee8 @gadget2 0x08049668 @gadget3 … eip .section .text ... pop ecx ret
  70. protections | nx | rop After ret instruction eax =

    0xffffdee8 ecx = 0x08049668 @gadget1 AAAA AAAA AAAA ... esp 0xffffdee8 @gadget2 0x08049668 @gadget3 … eip .section .text ... mov dword ptr [ecx], eax ret
  71. protections | nx | rop 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
  72. protections | nx | rop 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
  73. protections | nx | rop Stack pivoting ROP chain should

    be in the stack need to change esp value to point to user controlled data
  74. protections | nx | rop Examples mov esp, eax ;

    ret xchg esp, eax ; ret add esp, #value ; ret
  75. protections | nx | rop Demonstration lets use variation of

    previous sample bof_01_static goal : exit with chosen value take your VM and follow along
  76. protections | nx | rop Step 1 : find the

  77. protections | nx | rop Step 2 : find the

  78. protections | nx | rop Step 3 : define payload

  79. protections | nx | rop Step 4 : write functionality

    in assembly language .section .text mov eax, 1 mov ebx, 0x42424242 int 0x80
  80. protections | nx | rop Step 5 : requirements syscall

    eax = 0x1 ebx = 0x42424242
  81. protections | nx | rop Step 6 : define needed

    instructions int 0x80 xor eax, eax inc eax pop ebx
  82. protections | nx | rop Step 7 : locate gadgets

    int 0x80
  83. protections | nx | rop Step 8 : write exploit

  84. protections | nx | rop Useful when debugging break at

    the end of the vulnerable function set gadget address to 0x41414141 and check the stack layout use si (step into) to go through every instruction
  85. protections | nx | rop Calling multiple functions remember that

    they are multiple calling conventions libc is mostly using cdecl which means that the caller has to clean the stack
  86. protections | nx | rop 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
  87. protections | nx | rop End of read @read AAAA

    AAAA AAAA ... %esp 0x1 @buffer 1024 @buffer .section .text read: ... ret eip @system
  88. protections | nx | rop Problem we don’t have the

    correct arguments what would help ? hint: think gadgets…
  89. protections | nx | rop Yes, something to clean the

    3 entries we have in the stack ! add esp, 0xc ; ret pop reg1 ; pop reg2 ; pop reg3 ; ret
  90. protections | nx | rop Calling multiple functions using a

    pop3ret read system @read AAAA … ... %ebp return address 0x1 @buffer 1024 @system @buffer read args system args @pop3ret align
  91. protections | nx | rop End of read @read AAAA

    … ... %esp 0x1 @buffer 1024 @system read args system args @pop3ret .section .text read: ... ret eip @buffer align
  92. protections | nx | rop 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
  93. protections | nx | rop 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
  94. protections | nx | rop 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
  95. protections | nx | rop 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
  96. protections | nx | rop Detection ROP can be prevented

    by ASLR as we will see in a moment detection techniques are based on CFI violations Control Flow Integrity
  97. protections | nx | rop 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
  98. protections | nx | rop 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
  99. protections | intro What do you need if you want

    to call a function ?
  100. protections | aslr Function address ! before, code and sections

    were loaded at the same address every time cat /proc/self/maps
  101. protections | aslr Concept Address Space Layout Randomisation prevent attacker

    from using known addresses ex: return to libc
  102. protections | aslr | without

  103. protections | aslr | with

  104. protections | aslr Changes stack address heap address libraries addresses

    main binary address
  105. protections | aslr 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?
  106. protections | aslr Requirements not all binaries (including libraries) are

    affected by ASLR need to be compiled as Position Independant {Executable, Code} -pie -fPIE -fPIC
  107. protections | aslr ASLR compatible list binary headers using readelf

    EXEC : not compatible DYN : compatible when in peda use checksec command
  108. protections | aslr

  109. protections | aslr Other subtleties three configurations for ASLR /proc/sys/kernel/randomize_va_space

    0 : disabled
  110. protections | aslr Other subtleties 1 : Conservative randomization stack,

    heap, libraries, pie, vdso, mmap() 2 : full randomization 1 + memory managed by brk
  111. protections | aslr Bypass brute-force memory disclosure missing PIE

  112. protections | aslr | brute-force When lazy or no other

    possibilities set the libc base address to common base brute-force the remaining 16 bits only effective on 32 bits systems or if rebasing is built-into the binary 64bits Linux has 28 bits of entropy
  113. protections | aslr | disclosure 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
  114. protections | aslr | disclosure system: … … printf: …

    strcpy: … @??? libc 0xfffc3240
  115. protections | 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
  116. protections | aslr | disclosure Usage extract information using the

    disclosure match it against known value calculate offset to interesting functions you want to call
  117. protections | aslr | disclosure Variant highly dependant on the

    vulnerability you are exploiting if able to read /proc/self/maps, extract addresses
  118. protections | aslr | npie When the main binary is

    not compiled as position independent all text section is loaded at fixed address this also includes the GOT address
  119. protections | aslr | npie 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 distro
  120. protections | aslr | npie 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
  121. protections | aslr | npie GOT table is specific for

    each binary but : entries can be retrieved using objdump or radare2 objdump -D ./binary | grep \@plt\>:
  122. protections | aslr | npie

  123. protections | aslr | npie

  124. protections | aslr | npie Idea base address of the

    GOT is known in this case 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
  125. protections | aslr | npie Details leaked_address = <value> libc_base

    = leaked_address - offset_leaked_from_base needed_address = libc_base + offset_needed_from_base
  126. protections | aslr | npie 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
  127. protections | aslr | npie Example of such gadgets mov

    eax, [ebx] ; ret add eax, [ecx + 0x8042de4c] ; ret … don’t forget to adjust value in ecx
  128. protections | aslr | npie If we have enough time

    demo on bof_04 demo using PlaidCTF ropasaurusrex
  129. protections | intro What do you need if you want

    to modify data in memory ?
  130. protections | ro Rights to write at that location !

    prevent modifications of the GOT and the like used when vulnerability allows to write anywhere in the memory
  131. protections | ro Concept RELRO RELocation Read Only

  132. protections | ro Partial RELRO -z relro reorder sections to

    prevent overwrite through overflow GOT still writable
  133. protections | ro Full RELRO -z relro -z now like

    the previous one one loader’s job is done GOT/PLT are changed to read-only
  134. conclusion What next ? labs this afternoon, yeah! after that

    play with the concepts by yourself create/join CTF team read books or conferences papers do not hesitate to ask for help
  135. conclusion | books Modern operating systems {Linux, Windows, OSX, Android}

    Internals The Shellcoder’s handbook The art of software security assessment Fuzzing : brute force vulnerability discovery Practical reverse engineering
  136. conclusion | con Insomni’hack AppSec Forum / Cyber Security Conference

    Area41 Infiltrate Defcon BlackHat SSTiC NoSuchCon Usenix
  137. conclusion | wargames

  138. conclusion | ctf Check on Insomni’hack CSAW : dedicated

    to students Nuit du Hack CodeGate RuCTFe …