ARM pwn 入门 (1)

news2025/4/19 8:27:48

最近笔者刚刚加入了一个项目组,需要用到ARM架构的东西,和ARM pwn也有一定关系,因此一不做二不休,决定开始学习ARM pwn,顺便熟悉项目前置知识,一举两得。

ARM与x86分属不同架构,指令集不同,需要从头开始学习,本文从寄存器、指令方面对x86-64和ARM架构下的汇编语言做比较与学习。(配图选自清华大学出版社《ARM Cortex-M3与Cortex-M4权威指南》,侵删)

1. 寄存器

寄存器是汇编语言的核心,在x86-64系统中,最为常见的寄存器有以下这些:

64位:
rax, rbx, rcx, rdx
rsi, rdi, rsp, rbp, rip
r8, r9, r10, r11, r12, r13, r14, r15
32位:
eax, ebx, ecx, edx
esi, edi, esp, ebp, eip
r8d, r9d, r10d, r11d, r12d, r13d, r14d, r15d

在大多数程序中,这17个寄存器是最为常用的寄存器,其中rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp, rip有专门的作用,但其中的rax, rbx, rcx, rdx, rsi, rdi功能相对更加灵活,不像rsp只能用于表示栈顶地址,rbp只能用于表示栈帧地址,rip只能用于表示当前指令地址等。另外的8个寄存器则是通用寄存器,想用来干嘛就干嘛。

那么在ARM架构中,寄存器则是以下这些:

64位:
X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12
X13, X14, X15
32位:
R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12
R13, R14, R15

其中R0~R12为通用寄存器,共13个,剩下的3个有特殊用途:

  • R13为栈指针,又称SP,相当于rsp,在物理上实际上有两个栈指针:主栈指针和进程栈指针,一般的进程只有一个栈指针可见。这个也好理解,就好比在x86-64系统中,内核的栈指针和用户进程的栈指针不同一样。
  • R14为链接寄存器,又称LR,用于保存函数调用时的返回值。在x86-64系统中,函数调用的返回值是保存在子函数栈帧的上面,即rbp+8的位置,在ARM系统中,函数调用同样需要将返回地址保存到栈中,因为LR在函数返回时会进行自动更新,如果栈中没有返回地址,那么LR就不知道要更新成什么值了。当然LR的作用不止这些,在后面遇到具体问题时再进行分析。
  • R15为程序计数器,又称PC,可读可写。读操作返回当前指令地址+4(由ARM指令集特性决定,ARM指令集中任何一条指令都是偶数长度,与x86-64不同),写操作会导致执行流跳转。PC的最低有效位(LSB)是一个控制结构,为1时表示进入Thumb状态。当有些时候程序跳转更新PC时需要将新PC值的LSB置1,否则会触发错误异常。这也可以看做是一种程序恶意跳转的保护机制。有时还会将PC作为基址访问数据。

除了这些寄存器之外,两个架构下都各自有各自的特殊寄存器,如x86-64架构下的rflags控制寄存器用于保存程序执行的状态。在ARM中同样具有类似功能的控制寄存器:

  • APSR:应用状态寄存器
  • EPSR:执行状态寄存器
  • IPSR:中断状态寄存器
    上面的三个寄存器可以通过一个组合寄存器PSR访问,在不同的ARM架构中状态寄存器的排布有一定不同:

3个中断-异常屏蔽寄存器的功能较少用到,这里先不进行讨论。
CONTROL寄存器确定了栈指针的选择和线程模式的访问等级,其只能够在特权等级下才能进行修改。


其中具体的细节阐述较为繁琐,不是本文的重点,略过。

另外,在x86-64架构和ARM架构中都有很多的浮点数寄存器,用于进行浮点数计算。在ARM架构中,浮点数寄存器有32个32位寄存器S0~S31,其中可以两两组合访问为D0~D15,如S0S1组合为D0

2. 指令集

ARM的指令集和x86-64有一些相似之处,但也有一些不同,需要注意的是,ARM的立即数前面需要加上#标识,如#0x12345678。下面的指令均为32位系统下的指令。

A. 寄存器传送数据

与x86相同,ARM使用MOV系列指令进行寄存器与寄存器(立即数)之间的数据传送:

  • MOV/MOVS reg1, <reg2/imm8>:赋值reg1reg2/imm8
  • MOVW <reg32>, <imm16>:赋值reg32的低16位为imm16
  • MOVT <reg32>, <imm16>:赋值reg32的高16位为imm16
  • MVN reg1, <reg2>:将reg2的值取反之后赋值给reg1
  • LDR <reg32>, =<imm32>:赋值reg32imm32

备注:
① 这里的指令并不是一条真正的指令,而是一条伪指令。ARM汇编器会将字符数据汇总组成一个称为 “文字池” 的数据块,与x86-64不同,后者如果需要实现将立即数赋值到寄存器,会直接将立即数写死到指令中。这里的LDR指令实际是做了寻址操作,将文字池地址中的数据赋值到寄存器中。如果需要将32位立即数赋值到32位寄存器,可以使用这条指令,也可以将MOVWMOVT指令配合使用分别赋值前16位和后16位。

B. 存储器传送数据

不同于x86使用mov指令可实现寄存器、立即数和内存空间的数据交换,ARM使用单独的指令集进行寄存器和内存空间的数据交换,其中基址可以选择任意一个通用寄存器或PC寄存器,变址也可以使用任意一个通用寄存器,较x86更加灵活:

  • LDRB/LDRH/LDR reg1, [<reg2/PC>, <imm32>]<!>:赋值8/16/32位reg2+imm32地址的数据到reg1,如果指令后面有叹号,表示指令执行后reg2值更新为reg2+imm32,有叹号可等同于 LDRB/LDRH/LDR reg1, [<reg2>], <imm32>,这种形式称为后序指令
  • LDRD reg1, <reg2>, [<reg3/PC>, <imm32>]<!>:赋值64位reg3+imm32地址的数据到reg1reg2,有叹号可等同于 LDRD reg1, <reg2>, [reg3], <imm32>
  • LDRSB/LDRSH reg1, [<reg2/PC>, <imm32>]<!>:有符号传送8/16位reg2+imm32地址的数据到reg1,目标寄存器会进行32位有符号扩展,有叹号可等同于 LDRSB/LDRSH reg1, [<reg2>], <imm32>
  • STRB/STRH/STR reg1, [<reg2>, <imm32>]<!>:保存寄存器reg1的8/16/32位值到reg2+imm32地址,有叹号可等同于 STRB/STRH/STR reg1, [<reg2>], <imm32>
  • STRD reg1, <reg2>, [reg3, <imm32>]<!>:保存寄存器reg1reg2的64位值值到reg3+imm32地址,有叹号可等同于 STRD reg1, <reg2>, [reg3], <imm32>
  • LDRB/LDRH/LDR reg1, [<reg2/PC>, reg3{, LSL <imm>}]:赋值寄存器reg1的值为reg2/PC+(reg3{<<imm})地址处的8/16/32位值
  • LDRD reg1, <reg2>, [<reg3/PC>, <reg4-32>{, LSL <imm>}]:赋值寄存器reg1reg2的值为reg3/PC+(reg4-32{<<imm})地址处的64位值
  • STRB/STRH/STR reg1, [<reg2>, reg3{, LSL <imm>}]:保存寄存器reg1的8/16/32位值到reg2+(reg3{<<imm})地址
  • LDMIA/LDMDB reg1<!>, <reg-list>:将reg1地址的值按照顺序保存到reg-list中的寄存器中,如果reg1后有叹号,则在保存值后自动增加(LDMIA)或减少(LDMDBreg1。如LDMIA R0, {R1-R5}LDMIA R0, {R1, R3, R6-R9}
  • STMIA/STMDB reg1<!>, <reg-list>:向reg1地址存入寄存器组中的多个字。如果reg1后有叹号,则在保存值后自动增加(STMIA)或减少(STMDBreg1

注意:后序指令不能使用PC寻址。

C. 入栈出栈

虽然ARM与x86都使用push和pop指令进行入栈和出栈,但ARM可以实现一条指令多次出入栈。

  • PUSH <reg-list>:将寄存器组中的寄存器值依次入栈,reg-list中可以有PC、LR寄存器。
  • POP <reg-list>:将出栈的值依次存入寄存器组中的寄存器,reg-list中可以有PC、LR寄存器。

D. 算术运算

不同于x86指令的大多数算术运算使用两个寄存器,ARM指令的算数运算指令通常包含3个寄存器,实现运算后的自由赋值而不是x86中必须赋值给目标寄存器且目标寄存器必须参与运算。

  • ADD/SUB reg1, <reg2>, <reg3/imm32>:计算<reg2>(+/-)<reg3/imm32>将结果保存到reg3
  • ADC/SBC reg1, <reg2>, reg3:计算<reg2>(+/-)reg3+(进位/借位)将结果保存到reg3
  • ADC <reg32>, <imm32>:计算reg32+imm32+进位将结果保存到reg32
  • SBC reg1, <reg2>, <imm32>:计算<reg2>-imm32-借位将结果保存到reg1
  • RSB reg1, <reg2>, <reg3/imm32>:计算<reg3/imm>-<reg2>将结果保存到reg1
  • MUL reg1, <reg2>, reg3:计算<reg2>*reg3将结果保存到reg1
  • UDIV/SDIV reg1, <reg2>, reg3:计算<reg2>/reg3(无符号/有符号)将结果保存到reg1,如果除以0,则结果为0
  • MLA reg1, <reg2>, reg3, <reg4-32>:计算reg1=<reg2>*reg3+<reg4-32>
  • MLS reg1, <reg2>, reg3, <reg4-32>:计算reg1=-<reg2>*reg3+<reg4-32>

E. 逻辑运算

ARM支持x86格式的逻辑运算以及3运算符的逻辑运算。

  • AND/ORR/BIC/EOR reg1, <reg2>{, <reg3/imm32>}:如果reg3/imm存在,则表示reg1=<reg2>(&/|/&~/^)<reg3/imm32>,否则表示reg1=reg1(&/|/&~/^)<reg2>(与/或/与非/异或)
  • ORN reg1, <reg2>, <reg3/imm32>:表示reg1=<reg2>|~<reg3/imm32>(或非)

F. 移位运算

  • ASR/LSL/LSR reg1, <reg2>{, <reg3/imm32>}:如果reg3/imm存在,则表示reg1=<reg2>(>>/<<)<reg3/imm32>,否则表示reg1=reg1(>>/<<)<reg2>(算数右移、逻辑左移、逻辑右移)
  • ROR reg1, <reg2>{, reg3}:如果reg3存在,则表示reg1=<reg2>(>>)reg3,否则表示reg1=reg1(>>)<reg2>(循环右移)

G. 符号扩展

对应于x86中的movsx和movzx指令。

  • SXTB/SXTH reg1, <reg2>{, ROR <imm>}:右移<imm>位后有符号扩展<reg2>的低8/16位并赋值给reg1
  • UXTB/UXTH reg1, <reg2>{, ROR <imm>}:右移<imm>位后无符号扩展<reg2>的低8/16位并赋值给reg1

H. 数据反转

将寄存器中的值按字节进行反转。

  • REV reg1, reg2:将reg2中的4字节数据按字节反转后赋值给reg1reg2值不变),原先第0,1,2,3字节的内容被换到了第3,2,1,0字节。
  • REV16 reg1, reg2:将reg2中的4字节以字单位分为高字和低字分别进行反转后赋值给reg1reg2值不变),原先第0,1,2,3字节的内容被换到了第1,0,3,2字节。
  • REVSH reg1, reg2:将reg2中的低2字节反转后有符号扩展赋值给reg1
  • REVH reg1, reg2REV指令的16位表示,只反转低2字节。

I. 位域操作

位域操作允许机器指令对寄存器中的特定位进行处理,在x86中好像是也有这样的指令,只是使用频率太低。

  • BFD reg1, #lsb, #width:将reg1中从第lsb位开始的连续width位清零。
  • BFI reg1, reg2, #lsb, #width:将reg2中最低width位复制到reg1中从lsb位开始的连续width位。
  • CLZ reg1, reg2:计算reg2中高位0的个数并赋值给reg1,多用于浮点数计算。
  • RBIT reg1, reg2:反转reg2寄存器中的所有位并赋值给reg1
  • SBFX/UBFX reg1, reg2, #lsb, #width:取reg2中从第lsb位开始的连续width位并有/无符号扩展,赋值给reg1

J. 比较和测试指令

与x86使用cmp指令和test指令相似,ARM也有关于比较和测试的指令,且实现原理基本相同。

  • CMP reg1, reg2/imm:比较两个寄存器或寄存器与立即数,更新标志位APSR。
  • CMN reg1, reg2/imm:比较reg1-reg2-imm,更新标志位APSR。
  • TST reg1, reg2/imm:参照x86的test指令,相与测试,更新N(负数位)和Z(零)标志
  • TEQ reg1, reg2/imm:异或测试,更新N和Z标志

K. 跳转指令

  • B/B.W <label>:无条件跳转到指定位置,B.W跳转范围更大。
  • BX reg:寄存器跳转。
  • BL <label> / BLX reg:跳转到指定位置/寄存器值,且将返回地址保存到LR寄存器中,类比x86的call指令。一般在函数开头都会首先将BL寄存器的值保存到栈中便于返回时获取。
  • 条件跳转指令族:类比x86指令:
    • BEQ == je
    • BNE == jne
    • BCS/BHS == jc(进位标志为1,可表示无符号大于等于)
    • BCC/BLO == jnc(进位标志为0,可表示无符号小于)
    • BMI == js(负数标志为1)
    • BPL == jns(负数标志为0)
    • BVS == jo(溢出标志为1)
    • BVC == jno(溢出标志为0)
    • BHI == ja(无符号大于)
    • BLS == jbe(无符号小于等于)
    • BGE == jge(有符号大于等于)
    • BLE == jle(有符号小于等于)
    • BGT == jg(有符号大于)
    • BLT == jl(有符号小于)
  • CBZ/CBNZ reg, <label>:比较寄存器的值为0/不为0时跳转(只支持前向跳转)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2900.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用frp搞个内网穿透

使用场景&#xff1a; 在公司用电脑敲代码&#xff0c;环境都是localhost&#xff0c;有时候你要接第三方接口比如支付、或者企业微信的事件回调等&#xff0c;都需要一个公网地址&#xff0c;因为这时候是开发阶段&#xff0c;你即想要公司电脑上运行的环境又想要回调能找到你…

2022年首家民营征信机构浙江同信获企业征信备案公示

2022年首家民营征信机构浙江同信获企业征信备案公示 2022年11月1日&#xff0c;中国人民银行杭州中心支行公示了浙江同信企业征信服务有限公司企业征信机构备案&#xff0c;该机构为浙江省进行备案公示的第九家机构。其他八家分别为芝麻信用管理有限公司、浙江有数数智科技有限…

Transform介绍(1)

文章目录1. transform 方法2. transform 增量模式3. 注册 Transform使用Transform的常见场景有埋点统计、耗时监控、方法替换 通过上图以我们了解下transform的作用&#xff0c;transform在 class 到 dex 之间工作&#xff0c;处理包括 javac 编译后的字节码文件&#xff0c;每…

【Linux内核系列】进程调度

目录 一、为什么要调度 二、调度均衡 三、进程调度框架 3.1 调度队列 3.2 进程唤醒 3.3 调度时机 主动调度&#xff1a; 被动调度&#xff1a; 四、调度算法 4.1 先来先服务调度算法 4.2 最短作业优先调度算法 4.3 高响应比优先调度算法 4.4 时间片轮转调度算法 …

洛谷千题详解 | P1007 独木桥【C++、Pascal语言】

博主主页&#xff1a;Yu仙笙 专栏地址&#xff1a;洛谷千题详解 目录 题目背景 题目描述 输入格式 输出格式 输入输出样例 解析&#xff1a; C源码&#xff1a; Pascal源码&#xff1a; ------------------------------------------------------------------------------------…

NFT 推荐|辛迪加黑市系列第一弹

由 Planet Rift 呈现&#xff01; 塞巴星球的辛迪加已经洗劫了政府&#xff0c;现在是时候揭开补给品的神秘面纱了&#xff01; 辛迪加黑市系列的第一弹包括 30 个由 Planet Rift 宇宙设计的资产。其中首次发售的包含 4 套未来风格的盔甲、3 台彩色自动售货机和其他装备。 别忘…

项目管理之项目干系人

目录 前言 一、项目干系人的重要性 二、项目干系人管理过程 三、识别干系人 1.识别干系人的概念定义 2.识别干系人的输入 3.干系人分类模型 4.识别干系人的工具与技术 5.识别干系人的输出 四、规划干系人管理 1.规划干系人的输入 2.规划干系人的工具与技术 3.规划…

电脑蓝屏是哪里出了问题?不一定要非要重装系统

电脑蓝屏是非常常见的电脑故障现象&#xff0c;导致电脑蓝屏的原因很多&#xff0c;很多人第一时间反应可能是给电脑重装系统&#xff0c;但是有时并不能解决问题。那么电脑蓝屏是哪里出了问题呢&#xff1f;其实导致蓝屏不一定是系统故障&#xff0c;还有很多情况也会出现蓝屏…

Python3,爬虫有多简单,一个库,一行代码,就OK, 你确定不来试试?

爬虫进阶库&#xff1a;Scrapeasy1、 引言2、Scrapeasy2.1 简介2.1.1 Scrap2.1.2 Scrapeasy2.2 安装2.3 代码示例3、总结1、 引言 小屌丝&#xff1a;鱼哥&#xff0c; 我最近在练习写爬虫&#xff0c; 你有没有什么便捷的方式… 小鱼&#xff1a;比如呢&#xff1f; 小屌丝&a…

公众号网课查题接口

公众号网课查题接口 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&#xff08;点击…

【C】自定义类型(二)位段,枚举,联合

&#x1f648;个人主页&#xff1a; 对de起日子 &#x1f449;系列专栏&#xff1a;【C语言–大佬之路】 &#x1f388;今日心语&#xff1a;谨慎的选择自己的生活&#xff0c;不要轻易让自己迷失在各种诱惑里。 前一章我们介绍了结构体&#xff0c;这一章我们来介绍一下内容&a…

大猩猩优化算法(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑…

springboot:整合其它项目

目录 一、集成Druid application.yml 二、集成redis之非注解式开发 pom.xml application.yml RedisConfig ClazzBizImpl.java 三、集成redis之注解缓存开发 RedisConfig RedisConfig 一、集成Druid 在昨天的基础上 参考网址 https://github.com/alibaba/druid/tre…

C---指针

目录指针偏移问题&#xff1a;为什么用指针&#xff1f;1.强制给指针选地址&#xff1a;2.交换两个变量的值指针与数组1.指针数组&#xff1a;数组中的每一项都是个指针2. 指针数组的用法数组指针&#xff1a;一个指向数组的指针函数指针&#xff1a;malloc内存泄露&#xff08…

洛谷千题详解 | P1005 [NOIP2007 提高组] 矩阵取数游戏【C++、 Java、Python语言】

博主主页&#xff1a;Yu仙笙 专栏地址&#xff1a;洛谷千题详解 目录 题目描述 输入格式 输出格式 输入输出样例 解析&#xff1a; C源码&#xff1a; Java源码&#xff1a; Python源码&#xff1a; ----------------------------------------------------------------------…

论文阅读之RETHINKING POSITIONAL ENCODING IN LANGUAGE PRE-TRAINING

文章目录论文阅读总结参考论文阅读 文章大概提出了两个问题&#xff1a; 1.对于原来的transformer或者bert的embedding中&#xff0c;直接将word embedding&#xff08;词向量&#xff09;和positional embedding &#xff08;位置编码&#xff09;相加是不合理的&#xff0c;…

Netty入门——组件(Channel)一

目录一、channel的主要作用二、EventLoop处理io任务代码示例2.1、服务端代码示例2.2、客户端代码示例2.3、服务端和客户端查看控制台输出结果三、ChannelFuture连接问题代码示例3.1、服务端代码示例3.2、客户端代码示例3.3、服务端和客户端查看控制台输出结果3.4、ChannelFutur…

MyBatis的二级缓存

MyBatis的二级缓存 二级缓存是SqlSessionFactory级别&#xff0c;通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存&#xff1b;此后若再次执行相同的查询语句&#xff0c;结果就会从缓存中获取。 二级缓存开启的条件&#xff1a; 1.在核心配置文件中&#x…

软件测试:写一个好的测试用例

测试场景&#xff1a; 为登录功能设计测试用例 测试员为什么要会编测试用例 测试员的目标是要保证系统在各种场景下的功能是符合设计要求的。而测试用例就是测试员想到的测试场景。&#xff08;这也是高级别的测试员即使不会代码也能找到较好工作的原因&#xff09; 编写测试…

数据库2,DQL数据查询语言,表关联关系

目录 DQL数据查询语言 简单查询语句 计算列 别名 distinct消除重复行 条件查询 条件运算符 null值判断 枚举查询 模糊查询 分支查询 函数 字符串函数 聚合函数 排序查询 分组查询Group by 分页查询Limit 表关联关系 一对一关联 一对多与多对一 多对多关联 …