Featured image of post Pwn Int_overflow

Pwn Int_overflow

一道整型溢出题

前置知识

无符号数回绕

1
unsigned __int8 v3;

v3 变量是一个无符号数的 1 字节整型。它的计算是不会直接溢出的,相反它会截断之前的,比如257 在此会变成 1。
我们可以利用这个对密码长度进行伪造。

pwn

先检查二进制文件的信息:
是 32 位程序。
丢到 ida pro,一个命令行交互程序。输入 1 进入 login 函数,然后会让你输入用户名和密码。
用户名和密码分别用 s 和 buf 来存储。
这里 buf 给得够大,有 512 字节。
到最后调用 check_passwd(buf) 函数 它的逻辑就是用 v3 保存 s 变量的长度,如果它的长度大于等于 3 小于 8 就是正确密码,如果是正确密码就将其复制给 dest 字符串。
注意 v3 是 unsigned __int8 类型,只有一字节大小,可以表示的范围为 0~255! 而 dest 更小了,才 11 字节,相比较形参 s 是可以有 512 字节的,显然可以进行栈溢出操作。
点开 dest 看看函数栈,正如我们所料: 当它的空间溢出后下面就是 esp 和返回地址。
返回哪里好呢,通过 shift+f12 查看字符串发现有 cat flag 串,对其 X 键交叉引用我们找到 what_is_this 函数。显然我们只需要将返回地址跳到这个函数的地址就好了 0x804868b。
但是我们回到 check_passwd 函数,如果要跳到 strcpy 函数中,就需要 v3 为 [3, 8),可是我们要溢出攻击可不够,此时回到最开始的,我们可以借助无符号数回绕来帮助我们。
显然我们只需要让 s 的长度为 256 + 4 就可以让 v3 为 4,完美通过 if 循环。
那么就开始 python 脚本:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from pwn import *

r = remote("61.147.171.105", 65011)
payload = b'a' * (0x14+0x4) + p32(0x804868b) + b'a' * (256 - 0x14 - 4 - 4 + 4)
r.recv()
r.sendline(b'1')
r.recv()
r.sendline(b'name')
r.recv()
r.sendline(payload)
r.interactive()

0x14 + 0x4 个 a 进行溢出,覆盖 dest 字符串和 esp 寄存器的空间,然后通过 p32 转换(注意这个程序是 32 位下的)注入 what_is_this 函数地址。到最后继续添加字符串内容直到为 260 就行了。
然后也是轻松拿到 flag 了。

萌ICP备20241614号