0x00 前言
[第四届上海市大学生网络安全大赛]
第一次做到arm的pwn题特地记一下。刚拿到题目时是有点懵的,毕竟之前碰都没碰过,不过大致看了一下感觉挺简单的,溢出点也很明显。不过做之前还是要把环境先搭起来。
0x01 环境配置
作为自带翻车属性的本菜鸡,决定先把环境配在我的服务器上试试水,系统是Ubuntu 16.04
当然我想git,gdb,pwndbg,peda什么的你们应该都有。不过在这里我们还得安装一个gdb-multiarch。
1 | $ sudo apt-get install gdb-multiarch |
这样便可以支持多个架构。
安装 qemu
1 | $ sudo apt-get install qemu-user |
我们通过 qemu 模拟 arm/mips 环境,进而进行运行和调试
安装共享库
因为这个题目文件是动态链接的,所以我们还应该安装对应架构的共享库
看一下文件信息,知道是aarch64的架构,其实题目也说是arm了。。。。
那么我们搜一下共享库
1 | $ apt-cache search "libc6" | grep arm |
安装一下libc6-arm64-cross就好
1 | $ sudo apt-get install libc6-arm64-cross |
安装结束后便可以在/usr/下看到所安装的库
之后用对应的qemu同时用 -L 指定库的路径便可以运行了
1 | $ qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./pwn |
如果是想要调试 使用qemu的 -g 指定端口
1 | $ qemu-aarch64 -g 1111 -L /usr/aarch64-linux-gnu/ ./pwn |
然后使用 gdb-multiarch,remote上去便可以调试了
1 | pwndbg> target remote localhost:1111 |
至此环境配置便已经完成了
0x02 pwn
checksec看一下保护只开了NX
程序载入ida,逻辑挺简单的,主要就是那两个read函数,第一个将输入读入bss段,第二个将输入读入栈中同时也发生了栈溢出,在函数列表里我们也可以看到mprotect函数。到这里思路已经很明显了,将shellcode写入bss段,之后栈溢出控制执行流,通过mprotect函数给bss一个可执行权限,然后跳到bss段执行shellcode便可以getshell了。
思路有了下面就是寻找合适的gadget构建rop链了,其实gadget一开始我是没找到,但中午和我校一位大佬约了顿饭,可能得到了这位大佬的加持,回到宿舍就想着arm下会不会有像linux x86_64下那样有一个万能gadget呢,一找还真有。~~不愧是docupa师傅 ~~
可以很明显看出来我们溢出可以控制x19,x20,x21,x22,x23,x24,x29,x30寄存器,之后在loc_4008AC函数里我们进而控制x0,x1,x2,x3从而达到call mprotect,最后再ret到shellcode就可以了。
这些想明白了,只要能把栈布局好,shellcode没什么问题(本菜鸡找了几条都有点问题),这题基本就过了。
有点难受的就是本菜鸡临时现学的arm汇编,对一些指令还有函数调用出入栈不太熟悉导致一开始偏移算错了。arm的ret居然是x30寄存器,不像x86那样ret栈顶。。。。对不起是我太菜了(ˉ▽ˉ;)…
还有就是loc_4008AC
函数开头的那个LDR X3, [X21,X19,LSL#3]
。一开始我是像x86那样直接把mprotect
函数地址布在想x21寄存器里,后来调试的时候发现x3寄存器并没有变成mprotect函数的地址,又查了一下LDR指令才发现那样执行是将地址为x21+x19*8处的数据放入x3寄存器,这也是为什么在脚本上第一次send会将mprotect函数地址(0x400600)和shellcode一起放入bss段。之后我们只要控制x21寄存器为bss段上存mprotect函数的地址且x19置0,便可以成功的将mprotect函数放入x3寄存器,并执行。
poc
1 | from pwn import* |
getshell