ROP Primer

A1689efe1f28ba07f9b0b0ac3ef21e39?s=47 Bas
February 28, 2015

ROP Primer

A small presentation intended as an introduction to 32-bit return-oriented-program on Linux, with emphasis on CTF.

A1689efe1f28ba07f9b0b0ac3ef21e39?s=128

Bas

February 28, 2015
Tweet

Transcript

  1. BY @BARREBAS ROP PRIMER // CTF-TEAM.VULNHUB.COM

  2. CONTENTS > THE NEED FOR ROP > ROP VS RET2LIBC

    > STRATEGIES > EXAMPLE: SHELLCODEME // CTF-TEAM.VULNHUB.COM
  3. WHAT IS THIS ABOUT? > FOCUS ON BUFFER OVERFLOWS NOT

    ABOUT ALL KINDS OF VULNERABILITIES NOR AN INTRO INTO x86 ASSEMBLY RETURN-ORIENTED-PROGRAMMING IN CAPTURE THE FLAG CHALLENGES // CTF-TEAM.VULNHUB.COM
  4. THE NEED FOR ROP CODE EXECUTION TO EXPLOIT, WE NEED

    > CONTROL OVER EIP
  5. CODE EXECUTION OVERWRITE SAVED RETURN ADDRESS TO CONTROL EIP, WE

    CAN OVERWRITE GLOBAL OFFSET POINTER OR
  6. CODE EXECUTION OVERFLOW A BUFFER ON THE STACK TO OVERWRITE

    SRA, WE MUST LET'S FOCUS ON BUFFER OVERFLOWS, THEY'RE EASIER TO EXPLAIN :)
  7. EXECUTE SHELLCODE ON THE STACK HAVE TO STORE SHELLCODE SOME

    WRITABLE DATA SECTION OR
  8. EXPLOIT MITIGATION SHELLCODE ON STACK SINCE NX/DEP: STACK = NON-EXECUTABLE

    BINARY WILL SEGFAULT AS SOON AS IT STARTS TO EXECUTE CODE FROM NON-EXECUTABLE MEMORY
  9. WHAT IS ROP? > RETURN-ORIENTED-PROGRAMMING > RE-USE PIECES OF PROGRAM'S

    CODE SECTION >> CODE SECTION == EXECUTABLE // CTF-TEAM.VULNHUB.COM
  10. ROP VS RET2LIBC > BOTH ROP AND RET2LIBC USE THE

    STACK TO CONTROL EXECUTION > TO EXECUTE CODE, WE'LL FAKE STACK FRAMES > FOR RET2LIBC, WE FAKE ONLY ONE STACK FRAME > ROP CAN USE THE SAME STACK FRAME LAYOUT TO FAKE CALLS!
  11. LET'S LOOK AT RET2LIBC ASSUME LIBC ADDRESS IS STATIC (NO

    ASLR) OVERFLOW A FUNCTION POINTER OR SAVED RETURN ADDRESS WITH SYSTEM() SPAWN A SHELL CAT FLAG cat flag 2>&1 /bin/sh
  12. INTERMEZZO: BUFFER OVERFLOWS & RET2LIBC OBVIOUS VULNERABILITY

  13. EXAMPLE ENABLE COREDUMPS ulimit -c unlimited CRASH THE BINARY &

    GENERATE CORE
  14. GDB-PEDA IS OUR FRIEND BUT HOW? gdb ./vuln core START

    GDB USEFUL GDB-PEDA CMD: CHECKSEC WE HAVE OVERWRITTEN EIP WITH 'HHHH'
  15. ANATOMY OF A BUFFER OVERFLOW objdump -d -M intel ./rop_example

    CALL: SUB ESP, 4 MOV [ESP], EIP
  16. THE STACK BEFORE THE CALL 100 CALL: SUB ESP, 4

    MOV [ESP], EIP 112 108 104 ESP < SOME VALUE < ARG1 < ARG2 < SOME VALUE
  17. THE STACK AFTER THE CALL 100 CALL: SUB ESP, 4

    MOV [ESP], EIP 112 108 104 ESP < RETURN ADDR < ARG1 < ARG2 < SOME VALUE
  18. MAIN() IS EXECUTED LEA: LOAD EFFECTIVE ADDRESS OF BUF BUF

    IS ON THE STACK!
  19. THE STACK BEFORE READ() 100 132 116 BUF < RETURN

    ADDR ESP 128
  20. THE STACK AFTER READ() 100 132 116 BUF < HHHH

    ESP 128 < AAAABBBB.... < EEEEFFFF....
  21. MAIN() WANTS TO RETURN BUT WE HAVE OVERWRITTEN THE SAVED

    RETURN ADDRESS!
  22. THE STACK BEFORE RET 100 132 116 BUF < HHHH

    ESP 128 < AAAABBBB.... < EEEEFFFF.... RET: MOV EIP, [ESP] ADD ESP, 4
  23. THE STACK AFTER RET 100 132 116 BUF < EIP

    = HHHH! ESP 128 < AAAABBBB.... < EEEEFFFF.... RET: MOV EIP, [ESP] ADD ESP, 4
  24. EXECUTE OUR CODE BUT WE CAN RETURN-TO-LIBC echo 0 >

    /proc/sys/kernel/randomize_va_space DISABLE ASLR: STACK IS NOT EXECUTABLE
  25. GRAB ADDR OF SYSTEM() > WE'RE GOING TO FAKE A

    CALL TO SYSTEM() > A ROP CHAIN LOOKS BASICALLY THE SAME HOW WOULD THE STACK LOOK?
  26. THE STACK AFTER NORMAL CALL 100 112 108 104 ESP

    < RETURN ADDR < ARG1 < ARG2 STACK LAYOUT AT TOP OF FUNCTION
  27. RET2SYSTEM:THE STACK BEFORE RET 100 112 108 104 ESP <

    FAKE RETURN ADDR < ARG1 < SYSTEM() RET WILL TAKE VALUE FOR EIP OFF TOP OF STACK “/bin/sh” RET
  28. 100 112 108 104 ESP < FAKE RETURN ADDR <

    ARG1 < SYSTEM() IDENTICAL STACK LAYOUT AFTER 'NORMAL' CALL! “/bin/sh” RET2SYSTEM:THE STACK AFTER RET RET
  29. STRATEGY > STORE ARGUMENT FOR SYSTEM() ON STACK > OVERWRITE

    SAVED RETURN ADDRESS > SETUP CORRECT STACK LAYOUT TO FAKE A CALL REMEMBER: ASLR IS OFF, STACK ADDR IS FIXED
  30. EXPLOIT

  31. #FAIL! DEBUG TIME USE THE COREDUMP, LUKE MAKE BINARY CRASH

    BEFORE SYSTEM() IS CALLED BY REPLACING THE ADDRESS WITH 'BBBB'
  32. GDB'S STACK IS DIFFERENT LOCATION OF STACK IS DIFFERENT! UPDATE

    EXPLOIT WITH NEW POINTER
  33. IT'S ALIVE! IMPORTANT: KEEP SHELL ALIVE WITH CAT (python exploit.py;

    cat) | ./vuln FAKE RETURN ADDR! BINARY STILL CRASHES:
  34. ROP CHAINS CAN LOOK VERY SIMILAR TO THE STACK LAYOUT

    WE USED FOR RET2LIBC ROP > ^ RET2LIBC
  35. RECYCLE CODE IN EXECUTABLE SECTIONS FUNCTIONS IN GLOBAL OFFSET TABLE

    CODE IN LIBRARIES (E.G. SYSTEM()) GADGETS IN BINARY ASLR MIGHT BE A PROBLEM WE CAN RECYCLE ALL SORT OF CODE
  36. ROP GADGETS: PUTTING THE R IN ROP ROP USES THE

    STACK EXTENSIVELY TO ACHIEVE > CONTROL OVER EIP VIA STATEMENTS > CONTROL OVER STACK RET CODE EXECUTION
  37. A BINARY HAS MANY RETURN OPCODES > RETS ARE PRECEDED

    BY OTHER INSTRUCTIONS > GIVEN ENOUGH GADGETS, WE CAN DO ANYTHING... > PREFERABLY SOMETHING LIKE THIS cat flag # ;)
  38. EXAMPLE GADGET FROM RANDOM BINARY > RETURN TO THIS GADGET

    TO SET SEVERAL REGISTERS > RET @ END MAKES SURE WE DON'T LOSE CONTROL > CORRESPONDING PYTHON CODE:
  39. BUT THIS GADGET CONTAINS MORE GADGETS > WHAT IF WE

    RETURN TO 0x40196, IN THE MIDDLE OF THE STATEMENT? > WE END UP WITH A NEW GADGET: POP R12 RECYCLING! =)
  40. LOCATING GADGETS SEVERAL TOOLS EXIST ROPSHELL.COM GDB-PEDA MY OWN ROPGADGET.PY

    git clone https://github.com/longld/peda.git ~/peda echo "source ~/peda/peda.py" >> ~/.gdbinit
  41. MANY STRATEGIES EXIST RE-USE OPEN/READ/WRITE TO GRAB THE FLAG MAKE

    MEMORY WRITEABLE & EXECUTABLE TWO EXAMPLES:
  42. ROP EXAMPLE - SHELLCODEME WHAT ARE WE UP AGAINST? OBVIOUS

    VULNERABILITY =)
  43. ROP EXAMPLE - SHELLCODEME # disassemble binary $ objdump -d

    -M intel ./shellcodeme > shellcodeme.out FIRST, DISASSEMBLE BINARY LAUNCH GDB & OVERFLOW THAT BUF!
  44. TRICKY STACK LAYOUT RESTORE THE STACK SO THAT ESP POINTS

    TO INPUT INSPECT REGISTERS! EBP POINTS TO INPUT+16
  45. MAKE ESP POINT TO INPUT USE THE LEAVE OPCODE LEAVE:

    MOV ESP, EBP; POP EBP I USUALLY AVOID GADGETS WITH LEAVE, BECAUSE IT MESSES UP ESP AND CAUSES LOSS OF CONTROL OVER EIP
  46. FIRST ROP GADGET BOOM

  47. TAKE A STEP BACK HOW ARE WE GOING TO EXPLOIT

    THIS WITH ROP? THE BINARY ALREADY HAS TWO USEFUL FUNCTIONS: MPROTECT & READ
  48. MPROTECT CHANGES MEMORY PROTECTION FLAGS LET'S USE MPROTECT TO MAKE

    A SECTION OF MEMORY EXECUTABLE
  49. HIGH-LEVEL EXPLOIT OVERVIEW WE'LL BUILD A ROP CHAIN TO 'CALL'

    MPROTECT TO MAKE A SECTION OF MEMORY RWX THEN, 'CALL' READ TO READ STANDARD SHELLCODE FROM STDIN FINALLY, WE'LL RETURN TO OUR NEWLY READ SHELLCODE & SPAWN A SHELL MPROTECT READ
  50. LET'S START WITH MPROTECT THE ADDRESS OF MPROTECT WAS TAKEN

    FROM THE DISASSEMBLY OUTPUT
  51. RUN IT LIVE IN GDB STORE OUTPUT OF ROP1.PY IN

    FILE $ python rop1.py > in RUN GDB-PEDA $ gdb ./shellcodeme START PROGRAM AND USE INPUT FROM FILE gdb-peda$ r <in
  52. SUCCESS! EIP='FAKE' VMMAP > ^ 0x20000000 = RWX!

  53. WHAT ABOUT THE NEXT STEP? STACK LOOKS LIKE THIS: SOLUTION:

    POP POP POP RET > EACH POP WILL ADD 4 TO ESP > FINAL RET WILL PICK UP THE ADDRESS OF THE NEXT GADGET FROM THE STACK
  54. USING GDB-PEDA TO LOCATE PPPR gdb-peda$ ropgadget GDB LOCATED SEVERAL

    GADGETS WE'LL USE 0x804855D
  55. UPDATE THE POC & RUN IT $ python rop1.py >

    in $ gdb ./shellcodeme gdb-peda$ r <in BOOM
  56. ADD IN READ() SUPPLY “SHELLCODE” CONSISTING OF INT 3 INT

    3
  57. MOMENT OF TRUTH & RUN THE EXPLOIT: GRAB SOME SHELLCODE

    TO SPAWN A SHELL
  58. MOMENT OF TRUTH & RUN THE EXPLOIT: GRAB SOME SHELLCODE

    TO SPAWN A SHELL
  59. SHELL HAS LANDED!

  60. THANKS TEAM MEMBERS: NULLMODE, SUPERKOJIMAN, SWAPPAGE, BITVIJAYS, ET0X, HISTORYPEATS SHOUT-OUTS

    TO G0TMI1K, LEONJZA, RASTA_MOUSE & HIGHJACK FOR GOING THROUGH THIS PDF & GIVING FEEDBACK! IMAGES USED: ROPE: HiveHarbingerCOM // LINK SHELL: Chris 73 // LINK RECYCLING SIGN: JoseDLF // LINK
  61. ROP PRIMER // CTF-TEAM.VULNHUB.COM BY @BARREBAS // BARREBAS.GITHUB.IO