We’ll get started at 18:05

harder rop

6447 week9

good faith policy

we expect a high standard of professionalism from you at all times while you are taking any of our courses. We expect all students to act in good faith at all times

TLDR: Don’t be a dick jerk

sec.edu.au/good-faith-policy

doing more with rop

calling functions

it’s not just syscalls for execve("/bin/sh", NULL, NULL)

  • won’t always be calling assembly instructions
  • generally you’ll have access to many more functions
  • probably won’t get exactly what you want

malloc, printf, mmap can all leverage other exploits

www

write-what-where gadgets

  • basically a write primitive as a gadget
    • register 1: the target address
    • register 2: the value to write
mov [register1], register2

using the stack

we can still use the stack to store stuff

  • that’s where our payload (padding) is
    • we can already write to it (most of the time)
    mov rax, esp
    sub rax, 10
    mov rbx, rax

not just mov (add, mul, push, xchg?)

stack pivots

my buffer is too small

the problem

we can’t get a full payload

  • we have an overflowable buffer
  • overflow isn’t large enough for a full ROP payload

think back to egghunters in shellcode

the solution

  • we could:
    • jump back earlier in the current buffer
    • jump into a bigger buffer (harder/better?)

a.k.a we pivot the stack

stack pivot example

vuln(){
    char buff[16];
    fgets(buff,24,stdin);
}

here, we only have enough room to overwrite a single address

in memory

    [  XXXXXXXX  ] *we cannot write here*
    [   GADGET   ] <- stored return pointer
    [  AAAAAAAA  ] <- stored frame pointer
    [  AAAAAAAA  ] <- padding
    [  AAAAAAAA  ]
    [  AAAAAAAA  ]
    [  AAAAAAAA  ]

we can overwrite the return address, but can only execute one instruction?

stack pivot in action

GADGET_1 = sub rsp, 48

[ GADGET_1 ] <- rsp points here 
[ AAAAAAAA ]
[ AAAAAAAA ]
[ AAAAAAAA ]
[ AAAAAAAA ]
[ AAAAAAAA ]
[ GADGET_2 ] <- start of our payload 

GADGET_1 gets invoked

stack pivot in action

gadget moves rsp to point at the start of our payload

[ GADGET_1 ]
[ AAAAAAAA ]
[ AAAAAAAA ]
[ AAAAAAAA ]
[ AAAAAAAA ]
[ AAAAAAAA ]
[ GADGET_2 ] <- rsp points here 

stack pivot in action

so put our ROPChain as our “padding”

[ GADGET_1 ] <- ESP points here 
[ GADGET_8 ] <- int 0x80
[ GADGET_7 ] <- xor esi, esi; ret
[ GADGET_5 ] <- xor edx, edx; ret
[ GADGET_4 ] <- mov ecx, 0x12345678; ret
[ GADGET_3 ] <- mov ebx, 0x12345678; ret
[ GADGET_2 ] <- mov eax, 11; ret

other stack pivots

it could be the same buffer or another one

  • if it’s another buffer, you’ll just need to move esp more
  • or directly change it’s value (with a leak maybe?)

stack-pivots (extreme!!)

  • what if we only had a single byte overflow
  • e.g. we overwrite one byte of EBP
int vuln() {
    char buffer[100];
    fgets(buffer, 101, stdin);

    return 0;
}

how2exploit?

how realistic is this?

why is this vulnerable?

int vuln(char *s) {
    char buffer[100];
    memset(buffer, 0, sizeof(buffer));
    strncat(buffer, s, sizeof(buffer));
    return 0;
}

what is the bug?

these should be sizeof(buffer) - 1

int vuln(char *s) {
    char buffer[100];
    //                vvvvvvvvvvvvvv
    memset(buffer, 0, sizeof(buffer));
    strncat(buffer, s, sizeof(buffer));
    //                 ^^^^^^^^^^^^^^
    return 0;
}

how to exploit this?

its only one byte

0xFFFF [ ABCDEFGH ] <- stored EIP
0xFFFC [ FFFFFFFF ] <- stored EBP
0xFFF8 [ AAAAAAAA ]
0xFFF4 [ AAAAAAAA ]
0xFFF0 [ AAAAAAAA ]

leave and ret

what do leave and ret do?

leave:
    mov rsp, rbp    // rsp = rbp
    pop rbp         // rbp = old_rbp

ret:
    pop rax         // rax = stored_rip
    call rax        // jump rax

the overflow

overflow into least significant byte

0xFFFF [ ABCDEFGH ]
0xFFFC [ FFFFFFF0 ] <- partial overwrite
0xFFF8 [ AAAAAAAA ]
0xFFF4 [ AAAAAAAA ]
0xFFF0 [ AAAAAAAA ]

redirecting program flow

once we leave, ESP points to 0xFFF0

0xFFFF [ ABCDEFGH ]
0xFFFC [ FFFFFFF0 ]
0xFFF8 [ AAAAAAAA ]
0xFFF4 [ AAAAAAAA ]
0xFFF0 [ AAAAAAAA ] <- rsp points here (execution resumes here)

srop

sig-return oriented programming

what is sigreturn

how kernel returns execution to program after signal

  • when a signal is invoked, the context (e.g. registers) are all pushed to the stack

  • the signal-handler may modify them, etc

  • these values are restored using sigreturn (a syscall)

so how could we exploit this

we fake a sigreturn

  • sigreturn restores the values of registers based on content stored on the stack (we control the stack)

  • what if we pushed our own fake “context” (register values) onto the stack, and triggerd a sigreturn?

  • we could control all of the register values?

revision

need help?

  • any content you want covered?

  • any challenges you want me to demo?

tutorial