cybrics2021_pwn
膜队友ak rev,
syclover今年也很努力!
gross(done)
逆向
拿到题目就开始逆向, 简单分析, 程序本身main文件是做了个简易的os, 有程序加载运行的功能, 然后programs文件夹内存放的是几个自定义格式的二进制文件, 程序就直接启动了shell, 然后进入运行.
进行分析, 调试+分析, 符号比较全, 逆向难度不太大.
主程序main
main函数比较简洁, 首先使用load_program
函数将自定义格式的文件解析并载入到内存中, 然后设置名字后调用dump_program
打印程序信息, 调用spawn
函数新建一个线程来运行载入进内存的文件, 然后一直在handle_requests
函数运行, 直到所有程序都结束os退出(所有线程都结束程序退出)
函数spawn
中, 在内存中找到了对应程序的起始地址然后开启一个新线程去运行, 以此模拟一个程序运行在os中, 并且通过socket
进行数据通讯, 调用add_process
函数维护一个全局单向链表.bss:0000000000005028 processes
, 这个链表储存所有在这个os中运行起来的程序, 注意这个pea结构体, 这也是线程运行时的参数1,
然后在函数handle_requests
, 首先调用fill_fds
遍历process
并填充满fds
列表, 判断如果没有线程了,程序推出, 不然一直在这里循环,
然后是20行, 查看每个fds
即依次查看每个os内启动的程序, 进入make_syscall函数进行处理.
make_syscall
函数如下:
程序和os通过socket进行通讯, 首先os读取要读取的数据大小, 然后读取数据进来, 其中数据格式是开头为syscall_num
标识系统调用号,后面为对应传入的参数, 以下系统调用还比较明了
系统调用的switch要修复下跳转表,
系统调用4, 这一套操作其实和程序最开始导入programes/shell
一致, 就是再创建一个线程,并放到process
链表中, 然后在handle_requests
函数中循环的时候就有两个程序在os中运行, 会分别处理.
系统调用5, 就是个结束线程并释放掉这个进程的相关内存, 表示os内一个程序推出了.
主程序模拟一个os的流程分析结束, 然后我们应该分析下几个文件.
shell
导入ida64, 二进制文件方式导入, ida会自动分析一部分, 然后编译选项选择gun c++.
按照os中对于程序的解析来看, 这个程序入口点在
code_offste + entry = 0x0400+0x02f5 = 0x06F5
shell_main
函数只有一个参数, 也就是我们前面spawn
函数中看到的pea结构体, 有点类似c++的this指针这里我定义为shell_this
结构体:
简单分析, 发现程序内调用这个syscall_fcn
函数挺多, 这个函数在os中, 我们再回去分析,
syscall_fcn
函数, 基本可以看出来和make_syscall
函数对应, make_syscall
函数是os处理程序的系统调用的, syscall_fcn
是留给程序向os发送系统调用通讯的.
另外这个args
结构体也在程序中被使用到了,定义如下:
然后配合syscall_fcn
函数的分析, 如下的函数基本可以识别为函数调用, 示例write函数(seg000:00000000000005DA write_user
), 其他类似,
于是可以基本分析出来shell_main
函数, 其实就是内置了三个功能, sleep只会暂停一下, exit直接退出, spawn可以发送syscall4:spawn(pname)
启动另一个程序.
实际上能用的功能只是启动其他程序, 于是把剩下几个也得分析了.
programs
这里就基本分析完shell和os了, 剩下的几个分析就非常顺了.
echo 就是个复读机,没啥意思.
cat能实现任意文件读取, 但是限制了字符.
, 读不了flag.txt
,
其实还有个没有
.
的flag, gross2题目的flag, 但是又没给名字, 猜不到文件名字感觉可能他这个出题思路应该是一个flag有., 一个没有, 这样逆向到cat有一个flag, pwn拿到shell一个flag,放题整错了吧…
storage
看起来就不太对的一个文件, 逆向完os的sysccall以后还跟队友说, "我觉得这个改改可以出堆菜单题啊"
, 结果:
storage_main函数, 这里细节还是有些问题, 没调整太好,但是基本可以看到是个堆菜单题,
基本是常规的, 没有啥检测和限制, free里面有个uaf, 随意读取和修改,
利用
就是先从shell切到storage, 然后一个啥检测也没有uaf的洞, 先拿一个0x500的chunk, 仍unsortedbin, 得到main_arean, 然后得到malloc_hook, 通过这个低三位可以查到六个libc, 这里把free_hook改成了puts, 然后远程测试出来一个打印出/bin/sh的就是对的, ubuntu 2.27-1.4就是远程的, puts直接改成system就可以拿到shell了,
ex