This was a fun question to explore.
I tried the exploit and I got the same output. I just got a SegFault but was expecting "entered secret function" and a SegFault.
$ python -c "print 'a' * 68 + 'b' * 4 + '\x8b\x84\x04\x08'" > exploit.txt $ ./overflowtest < exploit.txt aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbb�� Segmentation fault (core dumped)
I opened up the program using gdb and tried to understand what is happening. I set a breakpoint at return_input.
$ gdb -q overflowtest Reading symbols from overflowtest...(no debugging symbols found)...done. gdb-peda$ b return_input Breakpoint 1 at 0x80484aa gdb-peda$ run < exploit.txt
Look at the following state:
[-------------------------------------code-------------------------------------] 0x80484ca <return_input+38>: add esp,0x10 0x80484cd <return_input+41>: nop 0x80484ce <return_input+42>: leave => 0x80484cf <return_input+43>: ret 0x80484d0 <main>: lea ecx,[esp+0x4] 0x80484d4 <main+4>: and esp,0xfffffff0 0x80484d7 <main+7>: push DWORD PTR [ecx-0x4] 0x80484da <main+10>: push ebp [------------------------------------stack-------------------------------------] 0000| 0xffffcc7c --> 0x804848b (<secret>: push ebp) 0004| 0xffffcc80 --> 0xf7fa7300 --> 0xf7f50447 ("ISO-10646/UCS2/") 0008| 0xffffcc84 --> 0xffffcca0 --> 0x1 0012| 0xffffcc88 --> 0x0 0016| 0xffffcc8c --> 0xf7e0d637 (<__libc_start_main+247>: add esp,0x10) 0020| 0xffffcc90 --> 0xf7fa7000 --> 0x1b1db0 0024| 0xffffcc94 --> 0xf7fa7000 --> 0x1b1db0 0028| 0xffffcc98 --> 0x0 [------------------------------------------------------------------------------]
Notice that the next instruction to be executed is the ret instruction. The top of the stack has the address of secret. This is exactly what we wanted. So, no problems till here.
The following is the gdb-peda state just before the printf inside secret function is executed.
[-------------------------------------code-------------------------------------] 0x804848e <secret+3>: sub esp,0x8 0x8048491 <secret+6>: sub esp,0xc 0x8048494 <secret+9>: push 0x8048580 => 0x8048499 <secret+14>: call 0x8048340 <printf@plt> 0x804849e <secret+19>: add esp,0x10 0x80484a1 <secret+22>: nop 0x80484a2 <secret+23>: leave 0x80484a3 <secret+24>: ret Guessed arguments: arg[0]: 0x8048580 ("entered secret function") arg[1]: 0x61616161 ('aaaa') [------------------------------------stack-------------------------------------] 0000| 0xffffcc64 --> 0x8048580 ("entered secret function") 0004| 0xffffcc68 ('a' <repeats 16 times>, "bbbbbbbb") 0008| 0xffffcc6c ('a' <repeats 12 times>, "bbbbbbbb") 0012| 0xffffcc70 ("aaaaaaaabbbbbbbb")
Now, printf will get executed. The top of stack has the Address of the string it has to print. All good till now.
I executed printf and checked for "entered secret function" output.
gdb-peda$ ni
Here is the problem. Even if printf got executed, the string didn't get printed on the console.
So, we can conclude that the exploitation was done properly.
Let us understand why printf didn't print that string to console output.
printf and many such output functions work in the following manner.
When printf is executed, the contents inside it is not directly printed out on the console. Instead, it is buffered in a buffer.
printf("entered secret function") ------------------------> [ OUTPUT_BUFFER ]----------------> console / (Standard Output)
Later, the buffer is flushed and everything is printed out on the console.
As explained in this answer, the buffer gets flushed only when certain conditions are reached.
- The buffer is flushed if it is full.
- It is flushed if newline is encountered.
- It is flushed if the program comes to an end.
- It is flushed if we force flush it using the fflush function.
Coming back to the question at hand,
The printf("entered secret function") is executed and the string is put into the OUTPUT_BUFFER.
If the overflowtest terminated normally, the OUTPUT_BUFFER would have got flushed. But because of the exploit, it got terminated because of a SegFault. So, the buffer was not flushed. So, you didn't see "entered secret function" .
The puts function doesn't work like this. It appends a \n / newline character to the string. So, that string is immediately seen on the console.
So, if you want to see "entered secret function", then add a newline character to it - "entered secret function\n" or add a fflush(stdout) after printf.
I hope I has answered your question.
If anything is not clear, please leave a comment below.
gdb
to debug your program and see if everything is where you think it is.for
if
else
while
do...while
switch
case
default
via a single blank line 3) separate functions by 2 or 3 blank lines (be consistent)main()
they are:int main( void )
andint main( int argc, char *argv[[] )
Notice they all have a return type ofint
, notvoid
scanf()
with either the '%s' and/or the%[...]
input format specifiers, always include a MAX CHARACTERS modifier that is 1 less than the length of the input buffer. This is because both of those specifiers always append a NUL byte to the input. This also avoids any possibility of a buffer overflow. 2) always check the returned value (not the parameter values) to assure the operation was successful