$30 off During Our Annual Pro Sale. View Details »

ROP Primer

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.

Bas

February 28, 2015
Tweet

Other Decks in Programming

Transcript

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

    View Slide

  2. CONTENTS
    > THE NEED FOR ROP
    > ROP VS RET2LIBC
    > STRATEGIES
    > EXAMPLE: SHELLCODEME
    // CTF-TEAM.VULNHUB.COM

    View Slide

  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

    View Slide

  4. THE NEED FOR ROP
    CODE EXECUTION
    TO EXPLOIT, WE NEED
    > CONTROL OVER EIP

    View Slide

  5. CODE EXECUTION
    OVERWRITE SAVED RETURN ADDRESS
    TO CONTROL EIP, WE CAN
    OVERWRITE GLOBAL OFFSET POINTER
    OR

    View Slide

  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 :)

    View Slide

  7. EXECUTE SHELLCODE
    ON THE STACK
    HAVE TO STORE SHELLCODE
    SOME WRITABLE DATA SECTION
    OR

    View Slide

  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

    View Slide

  9. WHAT IS ROP?
    > RETURN-ORIENTED-PROGRAMMING
    > RE-USE PIECES OF PROGRAM'S CODE SECTION
    >> CODE SECTION == EXECUTABLE
    // CTF-TEAM.VULNHUB.COM

    View Slide

  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!

    View Slide

  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

    View Slide

  12. INTERMEZZO: BUFFER OVERFLOWS & RET2LIBC
    OBVIOUS VULNERABILITY

    View Slide

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

    View Slide

  14. GDB-PEDA IS OUR FRIEND
    BUT HOW?
    gdb ./vuln core
    START GDB
    USEFUL GDB-PEDA CMD: CHECKSEC
    WE HAVE OVERWRITTEN EIP WITH 'HHHH'

    View Slide

  15. ANATOMY OF A BUFFER OVERFLOW
    objdump -d -M intel ./rop_example
    CALL: SUB ESP, 4
    MOV [ESP], EIP

    View Slide

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

    View Slide

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

    View Slide

  18. MAIN() IS EXECUTED
    LEA: LOAD EFFECTIVE ADDRESS OF BUF
    BUF IS
    ON THE STACK!

    View Slide

  19. THE STACK BEFORE READ()
    100
    132
    116
    BUF
    < RETURN ADDR
    ESP
    128

    View Slide

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

    View Slide

  21. MAIN() WANTS TO RETURN
    BUT WE HAVE
    OVERWRITTEN
    THE SAVED RETURN
    ADDRESS!

    View Slide

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

    View Slide

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

    View Slide

  24. EXECUTE OUR CODE
    BUT WE CAN RETURN-TO-LIBC
    echo 0 > /proc/sys/kernel/randomize_va_space
    DISABLE ASLR:
    STACK IS NOT EXECUTABLE

    View Slide

  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?

    View Slide

  26. THE STACK AFTER NORMAL CALL
    100
    112
    108
    104
    ESP < RETURN ADDR
    < ARG1
    < ARG2
    STACK LAYOUT AT TOP OF FUNCTION

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  30. EXPLOIT

    View Slide

  31. #FAIL! DEBUG TIME
    USE THE COREDUMP, LUKE
    MAKE BINARY CRASH BEFORE SYSTEM() IS CALLED
    BY REPLACING THE ADDRESS WITH 'BBBB'

    View Slide

  32. GDB'S STACK IS DIFFERENT
    LOCATION OF STACK IS DIFFERENT! UPDATE
    EXPLOIT WITH NEW POINTER

    View Slide

  33. IT'S ALIVE!
    IMPORTANT: KEEP SHELL ALIVE WITH CAT
    (python exploit.py; cat) | ./vuln
    FAKE RETURN ADDR!
    BINARY STILL CRASHES:

    View Slide

  34. ROP CHAINS CAN LOOK VERY SIMILAR TO THE
    STACK LAYOUT WE USED FOR RET2LIBC
    ROP >
    ^ RET2LIBC

    View Slide

  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

    View Slide

  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

    View Slide

  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 # ;)

    View Slide

  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:

    View Slide

  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! =)

    View Slide

  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

    View Slide

  41. MANY STRATEGIES EXIST
    RE-USE OPEN/READ/WRITE TO GRAB THE FLAG
    MAKE MEMORY WRITEABLE & EXECUTABLE
    TWO EXAMPLES:

    View Slide

  42. ROP EXAMPLE - SHELLCODEME
    WHAT ARE WE UP AGAINST?
    OBVIOUS VULNERABILITY =)

    View Slide

  43. ROP EXAMPLE - SHELLCODEME
    # disassemble binary
    $ objdump -d -M intel ./shellcodeme > shellcodeme.out
    FIRST, DISASSEMBLE BINARY
    LAUNCH GDB & OVERFLOW THAT BUF!

    View Slide

  44. TRICKY STACK LAYOUT
    RESTORE THE STACK SO THAT ESP POINTS TO INPUT
    INSPECT REGISTERS!
    EBP POINTS TO
    INPUT+16

    View Slide

  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

    View Slide

  46. FIRST ROP GADGET
    BOOM

    View Slide

  47. TAKE A STEP BACK
    HOW ARE WE GOING TO EXPLOIT THIS WITH ROP?
    THE BINARY ALREADY HAS TWO USEFUL FUNCTIONS:
    MPROTECT & READ

    View Slide

  48. MPROTECT CHANGES MEMORY
    PROTECTION FLAGS
    LET'S USE MPROTECT TO MAKE A
    SECTION OF MEMORY EXECUTABLE

    View Slide

  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

    View Slide

  50. LET'S START WITH MPROTECT
    THE ADDRESS OF MPROTECT WAS TAKEN FROM THE
    DISASSEMBLY OUTPUT

    View Slide

  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

    View Slide

  52. SUCCESS!
    EIP='FAKE'
    VMMAP >
    ^ 0x20000000 = RWX!

    View Slide

  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

    View Slide

  54. USING GDB-PEDA TO LOCATE PPPR
    gdb-peda$ ropgadget
    GDB LOCATED SEVERAL GADGETS
    WE'LL USE 0x804855D

    View Slide

  55. UPDATE THE POC & RUN IT
    $ python rop1.py > in
    $ gdb ./shellcodeme
    gdb-peda$ r BOOM

    View Slide

  56. ADD IN READ()
    SUPPLY “SHELLCODE” CONSISTING OF INT 3
    INT 3

    View Slide

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

    View Slide

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

    View Slide

  59. SHELL HAS LANDED!

    View Slide

  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

    View Slide

  61. ROP PRIMER
    // CTF-TEAM.VULNHUB.COM
    BY @BARREBAS // BARREBAS.GITHUB.IO

    View Slide