强网决赛拟态WP
白盒黑盒啥的我一点都不会,只会做点CTF然后给大佬们加油!那些什么简单题就不说了,总结一下比较有意思的。
一、oneaarch
这是个aarch架构的简单堆溢出的题,由于做的时候,本地环境没有搭的太好,也不太会在PIE的时候断点调试,直接就是盲堆,所以花了挺长时间。
另外还说一点的就是本题的设计还不错,是通过字节来进行堆的布置的,也就是只能发送一次数据,然后依据这里面的数据来进行堆的申请与释放,不符合规则的就无法正确操作。如果把这个思路用在x86_64的架构下,那么很多需要泄露地址的堆题直接就没办法做了,还是很有意思的。
但是这里由于qemu模拟的关系,在PIE的条件下,无论启动多少次,程序的基地址还是不变的,相当于是个简单版的PIE+ASLR。而在这题里,由于只能发送一次payload,所以这里我们可以先泄露地址,然后再进行getshell。
1.泄露地址
利用堆溢出修改size进入Unsortedbin泄露地址即可
1 | add(0,0xf8) |
这里泄露地址的时候需要注意一下aarch架构的libc加载的区别,一定是0x4000000000打头的。同时由\x00的截断我们只能获取到后面的几个不是\x00的数据,那么得到数据之后减去偏移再加上0x4000000000即可。
2.getshell
这里就直接贴总的wp了,也就是正常的溢出加劫持fd为free_hook,打free_hook即可。
1 | # -*- coding:UTF-8 -*- |
二、eserver
这题是mips架构的pwn题,由于没有接触过,当时直接现学了一波,后面再把所有架构的pwn题整个汇总把。
栈溢出题,没开canary和NX,按理说应该可以返回到栈上直接执行shellcode。那么本地直接依照调试获取栈地址返回栈上进行shellcode,但是远程的时候需要爆破一下栈地址,也不会太多,因为PIE基本等于不存在,栈地址的起始位置大概率就是0x7ffxx000,应该只需要爆破xx这一个字节,有时候通常也是0x7ffex000,也就是半个字节即可。
此外说一下调试,怕以后忘了。由于开启了PIE,如果直接qemu模拟的话,很难确定函数的位置,不好下断点,所以这里讲一个比较常用到的方法。
调试
由于qemu和开启PIE的mips架构的特性,貌似在栈下面就是共享库的加载地址,这个做了好多实验,都是这样的,不知道为啥,应该是mips架构下开启PIE之后,文件会变成共享库的格式:
再依据共享库加载的特性吧。
所以这里我们直接就能通过add-symbol-file File text_addr
的形式来确定地址。
这里红箭头指向的地方应该就是我们的开启PIE之后的文件加载地址,之后添加即可。
这样在输入函数打印,即可确定
得到如下结果,这样就能方便调试了。
所以这里应该是有两种方法的
1.通过爆破栈进行shellcode利用
(1)编写shellcode
这里讲一下shellcode的编写
①通过栈寄存器sp来取值编写
利用lw指令,通过sp寄存器来从栈上取值赋给对应的参数寄存器,最终效果如下:
对应的汇编生成:
1 | rasm2 -a mips -b 32 -C "lw a0,-0x1e4(sp)" #a |
由于\x00的截断,所以这里选取在sp之前的数据进行获取,其实由于循环的关系,这里也可以通过重复发送数据来将\x00给输入进来,之后发送/bin/sh\x00以及syscall的时候就是用到这个的。
②利用其他寄存器
同理,由于elf_base不变,所以可以通过寄存器减去偏移获取存在bss段上的数据,一样设置,比如下图的a1和s1寄存器。
如下的exp
1 | # -*- coding:UTF-8 -*- |
然后加个爆破脚本即可,爆破elf_base的地址,这里的sp是通过main函数返回之后进入shellcode的sp的地址。