[攻防世界]新手区int_overflow
这个题,题目提示很明显,往整数溢出方向想
先查看文件基本信息,得知是32位程序,且没有canary和PIE
然后看看字符串窗口,看有没有可以利用的字符串,发现system和cat flag,且存在一些需要留意的高危函数,strcpy和read。
点进cat flag发现有一个what_is_this函数直接用了system(“cat flag”),也就是说只要我们想办法调用这个函数,就可以直接拿到flag。
接下来需要找漏洞,最好是可以直接覆盖一个返回地址,覆盖成what_is_this函数的地址。
main里没有什么可疑点,点进login函数,发现密码给的长度很大,read可以读0x199字节,十进制就是409,谁会用这么长的密码?这个长度很可疑,猜测从这里入手。
再进入check_passwd看看
发现限制了密码长度,要求密码长度在(3,8]内,并且还发现有个strcpy(&dest, s),这个函数里的s就是密码的字符串,dest长度0x14,所以s长度远大于dest,这就会导致栈溢出。
思路:
1 | from pwn import * |
payload解释:
- ‘a’*24:用于使dest溢出,首先dest本身距离edp是0x14,十进制是20
在覆盖到返回地址的途中,有一次leave操作,在32位汇编中,leave等价于mov esp,ebp并pop ebp的操作,也就是说,在覆盖到返回地址之前,还有一次出栈,所以需要多覆盖一个ebp的长度,由于是32位,所以是4字节,所以覆盖ebp0x4,十进制是4
总和就是’a’*24 - p32(sys_addr):覆盖返回地址为what_is_this函数的地址,即check_passwd之后直接返回what_is_this函数。
- payload.ljust(260,’a’):由于程序执行到what_is_this函数后我们可以直接得到flag,所以之后怎么运行就不用管了,直接填充一堆’a’来让payload的长度能通过密码长度检测即可。但是显然payload前两部分的长度就超过了密码检测的最大长度8,这个时候就用到了整数溢出
v3即为密码的长度,可以看到它是一个长8位的只有正数的整数即00000000~11111111,就是0到255,当给v8赋值超过255时,比如256,即1 0000 0000,由于v8本身只有8位,所以超过8位的,就会发生高位截断,只会保留低位,所以这个1会被舍弃,v8的值就是0000 0000,而给v8赋值257,它的值就是1,赋值258,它的值就是2。所以只要让payload的长度在(259,264]内,就能让v8的值在(3,8]内,才能通过密码长度检测。