HWSand工控复现
HWS线上赛赛题复现
fmt
首先是个格式化字符串简单题
题目保护全开,libc给了2.31但是是栈题
题目给出了两次格式化字符串的机会,第一次我们可以泄露canary、libc_base、stack_addr、pro_base
1 |
|
但是其中我们只需要泄露libc和stack_addr即可
泄露地址后修改main->__libc_start_main返回地址即可,我们可以通过gdb调试指令bt得知存放在栈上的一个返回值,如下:
1 |
|
下面是整体步骤:
- 泄露libc,stack_addr
- 找到__libc_start_main在栈上的返回地址存放点,我们利用格式化字符串修改其为onegadget即可
exp如下:
1 |
|
ezhttpd
一个简单的服务器实现,可以发送套接字,该程序改自github上的一个项目TinyHttpd
,可以参考一下github上的源码来逆
他的大致功能就是,首先你传递一个套接字,里面包含了头部类型信息、url等,他会对其中的字段进行验证
题目的漏洞点在于base64解密的部分,如下:
1 |
|
这里的v18实际上就是buff丢掉前面Authorization: Basic
十五个字节后的部分,不得不说ida这里编译的确实离谱,然后我们可以看到v12他在我们之前栈上存放的url的上方
1 |
|
而其中我们没有判断v18的大小,所以说这里我们可以通过溢出到url来使得绕过之前url的..
限制,
后面就是来检测咱们的url,他需要满足存在后缀名.css
或.html
等等,所以我们需要在溢出的url中满足该需求
然后到后面我们会有个?的判断,这里会使得url中从?开始截断
1 |
|
然后我们到后面会存在sub_2993
这个函数,里面调用了这样一个函数execl(url, 0)
,该函数属于exec函数簇,大致含义可以说调用新进程,所以我们可以在url中传入/bin/sh
即可实现getshell,但是在此之前它会往我们的url头部添加一个htdocs/
目录,所以我们使用..绕过即可
综上,我们传入的包头应该包含以下内容:
- 后缀名.html
- ../bin/sh
- 使用?来截断url的后缀名
以下是exp
1 |
|
mi
其中涉及到新的malloc实现,名为mimalloc,其大致思想就是申请内存时首先给出整页,类似slub分配器一样,在一块页内空闲块连着空闲块,区别就是这个是虚拟内存而已,且在本题当中存在两个空闲链表,一个相当于热表,我们分配都是从他这里分,也就是free字段,我们还有一个冷表,当我们热表为空的时候,他就会将冷表整个赋值到热表,然后我们继续从中分配,这里记住我们是采用FIFO进行object链接的,并且我们所释放的所有堆块都会首先放入冷表贮存
题目逆向可知存在明显的UAF
1 |
|
因此我们可以首先消耗掉热表,然后再次分配肯定是从之前释放到冷表的块那儿分配,我们可以提前将其fd指针(字符串存在的头八字节)修改为其他字节,例如environ,ret等等
因此本题的思路就是
- 泄露堆地址,libc地址,这里通过uaf来达成,并且堆头部0x240偏移地方存在一个milibcmalloc.so的地址,很方便我们使用,毕竟堆头嘛,再怎么说也得存点东西
- 同样UAF,构造environ堆块,泄露栈地址
- 修改add的返回值,将堆块分配到栈上,然后利用ROP来获取flag
exp如下:
1 |
|
工控决赛赛题复现
Rainforest
题目做下来不知道这名字跟题目有什么关联。
首先是逆向部分,本题的版本为2.31-9.2,算是较为方便的版本,并且栈保护全开,无法写got,可以考虑打malloc/free_hook
题目整体是一个常规的菜单题,每次添加会有一个0x30大小的描述块和0x300大小的内容块
1 |
|
这里有趣的点是他会构造一个链条,也就是说我们如果重复对一个全局数组下标的位置添加的话,他会形成一个头插的链表,然后在show和delete函数的时候会依次进行展示或释放
而本题的一个漏洞点就位于delete函数当中
1 |
|
因此可以看到这是常见的UAF漏洞,其中我们可以看到他的这个描述块是并不清空的,所以我们可以多次利用该块来释放相同的堆块,造成多个堆块同时指向同一个地址
我们的利用手法如下:
- 首先利用UAF来构造指向相同地址的描述块,底层核心思想相同,具体实现则考验到我们对于glibc堆释放分配过程的理解,依据此我们可以分别泄露出heap base和libc base
- 我们可以在大堆块里面构造稍小的堆块,然后将两个重叠堆块均放置于链条上然后修改小堆块的fd指针,达成tcachebinattach,这里我才用写free_hook的方法
思想通了一切都好说,下面exp是打的时候慢慢试出来的,所以其中优化的部分没有细想,可能有些地方比较多余
最终exp如下:(写的时候方便调试换了9,做出来后懒得换回去了
1 |
|
babyvm
题目涉及到protobuf的基础知识
这个说起来也简单,就是类似一种高效版的xml文件,可以将我们的对象进行一个序列化,也就是转成一种串行的字节序列来进行传输,题目逆一下可以发现如下:
1 |
|
这里的main函数就是不断的输出“>”然后我们发送cmd指令,但这里cmd可不是瞎发啊,这里是采用protobuf协议以一种字符串序列来进行传输命令,
然后就是下面的decompile函数
1 |
|
可以发现他是调用另一个函数,到这里我就不准备再点进去看了,因为最近看内核源码看到太多这样的结构,所以我断定他是一个原生态实现的函数,所以不准备点进去逆,由于上下文的环境,大致可以猜测这个函数就是咱们的解码函数,也就是将咱们的序列化串来解析一下
下面就是咱们的主体函数
1 |
|
很明显的一个菜单题,其中我们的漏洞点就是位于delete函数中的悬垂指针
本题主要是考了一个protobuf的用法,以及再ida中寻找相应消息类型的方法,只需要将消息传递搞懂其他就迎刃而解了,因为这个就是一个很简单的2.31UAF,所以本题利用步骤如下:
- 泄露libcbase,heapbase(没什么用)
- 修改free_hook为一段我们的利用链,其中利用setcontext进行栈迁移到free_hook上,然后调用mprotect提升内存段权限调用shellcode即可
整体exp如下:
1 |
|