初探arm-pwn
ARM-PWN学习
环境配置
### 安装插件
关于异构的环境配置大家可以参考这篇文章,真的超级详细,arm,aarch64,powerpc,mips等等架构也有都,超级nice 传送门
关于arm架构,首先需要安装qeum其中包括qemu-user和qemu-user-static,qemu-system可以安装也可以不安装,接着安装调试工具gdb-multiarch,然后就可以通过qeum启动arm架构的程序来调试了
1 | sudo apt-get install qemu-user qemu-user-static |
启动程序
如果要启动一个名为pwn的arm架构的动态程序,命令应该为
1 | qemu-arm -L /path/to/lib ./pwn |
其中-L后面跟的参数为路径,不知道的话可以通过 file pwn 来查看一下所需路径以及ld
如果想要调试的话可以通过
1 | qemu-arm -L /path/to/lib -g 1234./pwn |
其中-g后面的参数为调试时要attach的端口,运行后pwn程序会等待gdb来attach连接,然后就可以调试了
1 | gdb-multiarch |
如果是静态编译的程序的话就不需要-L来设置路径了
如果是其他架构的程序的话,只需要把qemu-arm改为对应的架构即可,如qemu-arrch64等等
调试方法
exp调试:
1 | context(arch='arm', os='linux', log_level='debug')#设置对应的arch |
但是即使这样,还是的每次自己另外打开一个端口然后attach连接,还得让程序运行到自己想要运行的地方,这也太麻烦了,有没有简便的方法呢,有的兄弟有的
1 | from pwn import * |
其中
1 | def ggg(): |
可以让你在运行脚本的时候自动打开一个终端并连接,然后在你指定的地方下断点并运行到断点处,这就很方便了,大家记得自己修改端口号,架构设置,程序名称,断点,如果开启了PIE的话,可以把断点设置改为b *rebase(offset)
在qemu里运行arm架构的程序的话,就算开启了PIE,也是每次固定从一个偏移开始,和没开没什么区别,而且libc的地址每次也是固定的,不会有变动,当然如果是真机的话肯定是随机的,如果远程也是用qemu跑的话,可以直接使用libc而不用泄露,这给做题降低了很多难度
aarch64架构的libc就是随机的了,虽然网上也有说不随机的文章,可能版本不一样了吧,我在本地qemu运行aarch64程序调试的时候libc是随机的 ) (
指令学习
arm和aarch64都是通过寄存器传参的,没有像x86那样通过栈传参的形况
arm
R0~R3
依次用来传递函数调用参数,R0
还用来保存函数返回结果,R7
存放系统调用号,R11(FP)
相当于rbp
,
R13(SP)
相当于rsp
,R14(LR)
用来存放函数返回地址,R15(PC)
相当于rip
,x64
函数返回的时候大多是通过leave ret
来返回的,而arm是通过
1 | sub sp, r11, #4 将r11减4的值传给sp |
来进行栈回溯的,当然我们熟悉的pop
和push
指令也都有
arm中没有call funk的汇编,只有B funk,BL funk,BX funk, BLX funk来进行跳转
B就相当于jmp,一般形况下BL相当于call,BL会跳转到指定位置执行代码,然后将当前位置的PC值保存到LR中,也就是将返回地址保存到了LR中
然后是ldr(加载指令)和str(存储指令)这两个指令的含义
1 | ldr r2, [r1], #-2 将r1地址中的值传给r2,然后r1-=2 |
大概例子就这样,不懂的可以拷打AI,因为我也不是很懂,参考于这里
aarch64
X0 ~ X7
用来依次传递参数,X0
存放着函数返回值,X8
常用来存放系统调用号或一些函数的返回结果,x32
是PC寄存器,栈顶是X31(SP)
寄存器,栈帧是X29(FP)
寄存器,X30(LR)
存放着函数的返回地址
对于B类的跳转指令,新增了BR指令,可以向寄存器里的地址跳转,这里不再叙述,详细可以参考这位大佬的文章这里
值得留意的是,aarch64
中没有了pop
和push
指令,而是通过STP
和LDP
来实现的
1 | stp x29, x30, [sp, #-0x50]! 将x29的值push到sp-0X50处,将x30的值push到sp-0x50+0x8处,然后sp-=0x50(如果后面没有!号的话,sp不变) |
诸如此类的使用方式
aarch64
中有ret指令,但ret
并不是将是sp
中的值pop
出来当作下一条指令执行,而是ret
到LR(x30)
中储存的地址继续执行
题目学习
题目下载可以从这里下载,这里就不讲解了,只放个exp供大家参考
arm
jarvisoj typo
1 | from pwn import * |
Codegate2018 melong
1 | from pwn import * |
Root Me : stack_buffer_overflow_basic
1 | from pwn import * |
Root Me : stack_spraying
这个题在最后执行system的时候老是报错,不知道是什么原因,懒得深究了
1 | from pwn import * |
Root Me : use_after_free
1 | from pwn import * |
aarch64
上海骇极杯 2018 baby_arm
1 | from pwn import * |
2021 DASCTF 1月赛 ememarm
1 | from pwn import * |
最近做习惯了打IO用FSOP的堆体,上述两个堆题劫持got表的题都不太会做了,特别是ememarm,看着exp很短,细究起来对于数据的构造还是很巧妙的,强烈推荐()~~