pwnable.kr Writeup Part 1
由于近期事情比较多(人也比较浮躁比较摸),就一直没有去写自己的第一篇 blog,终于东拼西凑挤出时间把 pwnable.kr 的前三个做出来了(从零开始一点点学),于是心血来潮想写成我的第一篇 blog。
Disclaimer
本文主要是记录自己从零开始学习 binary exploit,可能存在大量错误,如有差错请指正。
进度
目前已完成前三个,正在抽时间往后做。
Update 02/24/2020: 做出了第四个,以后更新每个 article 放 5 道题。
Update 11/20/2023: 世事难预料,虽然做出来了,但感觉没有写的动力了。
正文
fd
根据提示Mommy! what is a file descriptor in Linux?
大概可以知道这道题与 file descriptor 有关系。
SSH 到服务器上,可以找到这个题目的源码fd.c
。存在flag
且当前用户组无权访问,有可执行文件fd
与flag
同组,且带有setgid
,因此,要通过fd
获取 flag。研究源代码,在输出 flag 之前,存在一个字符串的对比,需要输入为LETMEWIN
,而在调用它之前有调用 read()函数,通过 man page 可知这个函数是在 file descriptor 中读取到 buffer。通过查阅维基百科可知,file descriptor 中 0 为 stdin。思路是从stdin
通过read()
输入LETMEWIN
。
而在调用read()
之前,有atoi() - 0x1234
,而 atoi 使用了用户输入,目标是使atio() - 0x1234
的值为 0。而atoi()
是将输入的字符串转为整型。那么需要先将 0x1234 转为十进制输入即可。
1 | ./fd 4660 |
collision
通过研究题目给的源代码,可以确定它将用户输入的 char 型(1 byte)变量使用强制类型转换转换为了 int 型(4 bytes),再将其求和。可以将目标的数值除以 5(由于不是整数,得到结果后进行微调即可)转化为二进制再转回 char 型输出其 16 进制即可。
1 | ./col $(echo -e "\xcc\xce\xc5\x06\xc8\xce\xc5\x06\xc8\xce\xc5\x06\xc8\xce\xc5\x06\xc8\xce\xc5\x06") |
bof
查看题目所给出的源码,发现func()
会在特定的条件下开启一个 shell,即key == 0xcafebabe
时,而key
作为传入的参数且为0xdeadbeef
。此时需要从overflowme[32]
着手。通过阅读资料Buffer overflow attacks explained可知,overflowme
是存储在 stack 上的,且 stack 是向低地址扩张的且数组类变量的下标是从低地址向高地址递增的。而从overflowme
到key
有多大并不是很清楚,将服务器上编译完的 binary 拖下来,使用 gdb 进行分析。
1 | gdb bof |
共需要 13*4 = 52 个字符才需能覆盖到原始的 key。因此需要构建一个 payload,然后将其 pipe 到相应的 binary。(刚开始一直是没有 overwrite 成功,最后试了下 pwntools 才成功的,具体原因可参考这里what is the difference between “python -c ‘print’ ” and “(python -c ‘print’; cat)” in linux)
1 | python -c "print('A'*52+'\xbe\xba\xfe\xbe')" > payload |
flag
看题目大概是一个逆向,将 binary 用wget
拖下来,用strings
看一下,发现有UPX!
字样且gdb
无法找到 entry point。判断 binary 使用了 UPX 进行加壳。使用 UPX 工具去壳后即可。
1 | upx -d flag |
TO BE UPDATED
咕咕咕 在做了在做了