远程交互以下。
file 查看文件属性。64 位,LSB 可执行文件。
checksec 查看文件安全属性。开启了 NX 保护,栈上无法执行。
IDA 打开文件查看 main 函数。
代码流程:让用户输入一个整数,再将其存到 nbytes
变量中,之后通过 if 判断用户输入的整数是否大于 10 了,如果大于则终止程序。若为大于 10,则询问用户的名字,并将该名字存储到 buf
缓冲区中。
解题思路:绕过 if 的判断,使 read()
函数溢出,但是输入大于 10 的整数会触发 exit(-1)
而终止程序,所以就需要一个既小于 10 而又大于 10 的整数。
仔细查看 main 函数,在 read()
函数读取时, 将第一次的输入转换成了 unsigned int,即无符号整数。
unsigned int 是是一种无符号整数类型,即其存储的二进制位全部用于表示数值大小,不包含符号位,它的二进制形式是一个纯数值编码,所有位均参与数值计算。例如,在32位系统中 unsigned int 占用4字节(32位),其取值范围为:0 到 2^32 - 1(即 0 到 4,294,967,295)。
但是,当 unsigned int 与有符号整型混合运算时,有符号数可能被隐式转换为无符号数,导致数值语义变化(如 -1 变为 4294967295)。
所以当我们输入-1时,可以成功绕过if,并且程序在执行到read函数时,读取的字节会变成4294967295个字节。
之后就是溢出 read()
函数,覆盖返回地址。
查看 buf 的栈,可以知道溢出的大小为:0x10+8=0x18→24
并且存在 backdoor
地址为:0x400726
编写exp:
from pwn import *r=remote('node5.buuoj.cn',25304)
backdoor_addr=0x400726
payload=b'a'*(0x18)+p64(backdoor_addr)
r.sendlineafter('name','-1')
r.sendline(payload)
r.interactive()
PWN!