ARM64汇编01 - 环境搭建

news2024/11/19 2:32:46

arm官方手册

由于市面上几乎没有arm相关书籍,所以推荐看官方文档。虽然是英文的,看不下去也要硬看,毕竟搞这方面的还是得有啃英文文档/书籍的能力。

另外,再推荐一个翻译网站:https://www.deepl.com/zh/translator

arm 手册下载地址:

https://developer.arm.com/documentation/ddi0487/latest

https://developer.arm.com/documentation/ddi0602/2023-12/?lang=en

开发环境

使用 kali + vscode + ndk-build。

ndk-build 可以使用 android studio 下载。

开发目录结构:

ARM64 
 |-- Android.mk
 |-- Application.mk
 |-- arm64.c
 |-- build.sh
 |-- push.sh
 |-- connect.sh

关于 Android.mk 与 Application.mk 的知识,可以参照官方文档:

https://developer.android.com/ndk/guides/build?hl=zh-cn

这里只简单介绍必要的。

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

#LOCAL_ARM_MODE := arm

LOCAL_MODULE := arm64

LOCAL_SRC_FILES := arm64.c

include $(BUILD_EXECUTABLE)

#include #(BUILD_SHARED_LIBRARY)
  • LOCAL_PATH:此变量用于指定当前文件的路径。必须在 Android.mk 文件开头定义此变量。

  • CLEAR_VARS:此变量用于清除LOCAL_PATH变量外的许多LOCAL_***变量(例如:LOCAL_MODULE、LOCAL_SRC_FILES等)。这是非常有必要的,因为所有的编译文件都在同一个GUN MKAE执行环境中,所有的变量都是全局变量,不清除容易引起解析错误。

  • LOCAL_MODULE:此变量用于存储模块名称。指定的名称在所有模块名称中必须唯一,并且不得包含任何空格。

  • LOCAL_ARM_MODE:默认情况下,构建系统会以 thumb 模式生成 ARM 目标二进制文件,其中每条指令都是 16 位宽,并与 thumb/ 目录中的 STL 库链接。将此变量定义为 arm 会强制构建系统以 32 位 arm 模式生成模块的对象文件。

  • LOCAL_SRC_FILES:此变量包含构建系统生成模块时所用的源文件列表。

  • BUILD_EXECUTABLE:根据您列出的源文件构建目标可执行文件。

  • BUILD_SHARED_LIBRARY:根据您列出的源文件构建目标共享库。

Application.mk

APP_ABI := arm64-v8a
APP_BUILD_SCRIPT := Android.mk
APP_PLATFORM := android-26
  • APP_ABI:默认情况下,NDK 构建系统会为所有非弃用 ABI 生成代码。您可以使用 APP_ABI 设置为特定 ABI 生成代码。

    指令集
    32 位 ARMv7APP_ABI := armeabi-v7a
    64 位 ARMv8 (AArch64)APP_ABI := arm64-v8a
    x86APP_ABI := x86
    x86-64APP_ABI := x86_64
    所有支持的 ABI(默认)APP_ABI := all
  • APP_BUILD_SCRIPT:默认情况下,ndk-build 假定 Android.mk 文件位于项目根目录的相对路径 jni/Android.mk 中。如需从其他位置加载 Android.mk 文件,请将 APP_BUILD_SCRIPT 设置为 Android.mk 文件的绝对路径。

  • APP_PLATFORM:APP_PLATFORM 会声明构建此应用所面向的 Android API 级别,并对应于应用的 minSdkVersion。例如, android-16 说明无法运行在低于Android 4.1(API 级别 16)的设备上。

arm64.c

#include <stdio.h>

int main()
{

    while (1)
    {
        getchar();
        printf("hello\n");
    }

    return 0;
}

这里就是我们的测试代码,会将它编译成可执行文件,然后push到设备上去运行。我们可以使用 IDA 来观察汇编代码。

build.sh

export ANDROID_NDK=/root/Android/Sdk/ndk/21.4.7075529

$ANDROID_NDK/ndk-build NDK_PROJECT_PATH=. NDK_APPLICATION_MK=Application.mk

ndk-build 脚本位于 NDK 安装目录顶层。所以我们定义一个变量表示其目录,然后直接使用即可。

  • NDK_APPLICATION_MK=<file> :使用 NDK_APPLICATION_MK 变量指向的特定 Application.mk 文件进行构建。

  • 如果Android.mkApplication.mk所在目录的名字不是jni,需要通过变量指定 :NDK_PROJECT_PATH=.

push.sh

adb connect 192.168.3.12:5555
adb push obj/local/arm64-v8a/arm64 /data/local/tmp/arm64
adb shell "chmod 777 /data/local/tmp/arm64"

将生成的可执行文件 push 到 设备的指定位置。

注意生成的可执行文件有两个:

├── libs
│   └── arm64-v8a
│       └── arm64
├── obj
│   └── local
│       └── arm64-v8a
│           ├── arm64
│           └── objs
│               └── arm64
│                   ├── arm64.o
│                   └── arm64.o.d

obj/local/arm64-v8a/arm64 这个可执行文件是带调试信息的。

libs/arm64-v8a/arm64 这个可执行文件是经过 strip 了的,不带符号与调试信息。

我们学习时使用带调试信息的即可。

connect.sh

adb connect 192.168.3.12:5555
#adb shell "/data/local/tmp/android_server64"

连接设备,打开 IDA 的 server。

然后我们在有 IDA 的主机上连接设备,转发端口,就可以进行调试了。

LOCAL_ARM_MODE

前面我们说了,这个选项是用来表明生成的目标文件里面,它的汇编代码是使用 arm 还是 thumb 指令。

我们测试一下 arm 的效果:

LOCAL_ARM_MODE := arm

其main函数汇编如下:

.text:0000000000000714                               ; =============== S U B R O U T I N E =======================================
.text:0000000000000714
.text:0000000000000714                               ; Attributes: noreturn bp-based frame
.text:0000000000000714
.text:0000000000000714                               ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:0000000000000714                               EXPORT main
.text:0000000000000714                               main                                    ; DATA XREF: LOAD:0000000000000438↑o
.text:0000000000000714                                                                       ; .got:main_ptr↓o
.text:0000000000000714
.text:0000000000000714                               var_10= -0x10
.text:0000000000000714                               var_s0=  0
.text:0000000000000714
.text:0000000000000714                               ; __unwind {
.text:0000000000000714 F3 0F 1E F8                   STR             X19, [SP,#-0x10+var_10]!
.text:0000000000000718 FD 7B 01 A9                   STP             X29, X30, [SP,#0x10+var_s0]
.text:000000000000071C FD 43 00 91                   ADD             X29, SP, #0x10
.text:0000000000000720 13 00 00 90 73 E2 1C 91       ADRL            X19, aHello             ; "hello"
.text:0000000000000720
.text:0000000000000728
.text:0000000000000728                               loc_728                                 ; CODE XREF: main+20↓j
.text:0000000000000728 C6 FF FF 97                   BL              .getchar
.text:0000000000000728
.text:000000000000072C E0 03 13 AA                   MOV             X0, X19                 ; s
.text:0000000000000730 CC FF FF 97                   BL              .puts
.text:0000000000000730
.text:0000000000000734 FD FF FF 17                   B               loc_728
.text:0000000000000734                               ; } // starts at 714
.text:0000000000000734
.text:0000000000000734                               ; End of function main
.text:0000000000000734
.text:0000000000000734                               ; .text ends
.text:0000000000000734

可以看到都是 4 个字节的指令,除了 ADRL ,查看文档发现并没有这个指令。网上搜索了一下,发现这是一个伪指令,最终会将其转换为两条加载指令。所以,算下来,main 函数体的指令其实都是4个指令的。

再测试一下 thumb 指令的效果:

LOCAL_ARM_MODE := thumb

发现,指令并没有变化,这是为啥呢?我们看下面这个表:

可以看到,thumb 指令只存在于 armeabi-v7a 里面。

现在的应用在googleplay与国内商店的推动下,都已采用了 arm64-v8a,所以我们可以不用太关心 thumb 指令了。

想要看一下 thumb 指令,我们在 Application.mk 里面设置一下:

APP_ABI := arm64-v8a armeabi-v7a

这样就可以生成两个可执行文件,使用 ida 打开 armeabi-v7a 下的文件,查看其 main 函数:

.text:000005FC                               ; =============== S U B R O U T I N E =======================================
.text:000005FC
.text:000005FC                               ; Attributes: noreturn bp-based frame
.text:000005FC
.text:000005FC                               ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:000005FC                               EXPORT main
.text:000005FC                               main                                    ; DATA XREF: .text:000005A8↑o
.text:000005FC                                                                       ; .got:main_ptr↓o
.text:000005FC                               ; __unwind {
.text:000005FC D0 B5                         PUSH            {R4,R6,R7,LR}
.text:000005FE 02 AF                         ADD             R7, SP, #8
.text:00000600 03 4C                         LDR             R4, =(aHello - 0x606)   ; "hello"
.text:00000602 7C 44                         ADD             R4, PC                  ; "hello"
.text:00000602
.text:00000604
.text:00000604                               loc_604                                 ; CODE XREF: main+12↓j
.text:00000604 FF F7 9C EF                   BLX             getchar
.text:00000604
.text:00000608 20 46                         MOV             R0, R4                  ; s
.text:0000060A FF F7 A0 EF                   BLX             puts
.text:0000060A
.text:0000060E F9 E7                         B               loc_604
.text:0000060E
.text:0000060E                               ; End of function main
.text:0000060E
.text:0000060E                               ; ---------------------------------------------------------------------------

非常明显的变长指令,毕竟 thumb 指令的出现就是为了减少指令的长度。

调试一下这个程序,可以从寄存器窗口观察到 T flag 的值是1:

有些情况下,如果程序加了壳,或者说搞了自解密,可能会导致 IDA 错误识别指令。本来是 thumb 却识别成了 arm,或者反过来将 arm 识别成了 thumb。这个时候就需要我们手动将指令模式改过来。

在对应汇编位置,我们按 ALT + G 快捷键即可更改指令编码格式:

将 T 的值改成 1 就是 thumb 格式,改成 0 就是 arm 格式。

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

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

相关文章

git报错:Failed to connect to github.com port 443: Timed out

git提交报错 git报错&#xff1a;Failed to connect to github.com port 443: Timed out解决办法 使用ping github.com 发现ping不通修改hosts文件&#xff0c;让主机跳过DNS服务器 直接根据hosts配置信息进行替换域名在ipaddress.com查询Github真实IP地址 打开hosts文件 添加…

【Java SE】基础知识回顾——【13.线程 | 同步】

【线程 同步】 第一章 Thread 1.1 Thread类 /*** author 270* 获取线程的名称&#xff1a;* 1.使用Thread中的方法getName()* String getName() 返回该线程的名称* 2.可以获取到当前正在执行的线程&#xff0c;使用线程中的方法getName()获…

【年度TikTok电商数据解析】火遍全网!出单率超高!这个产品会成为2024年卖家新宠吗?

随着大众对口腔健康越来越重视&#xff0c;消费者对漱口水、牙线、口腔清新剂等口腔卫生产品形成深度依赖。 当然&#xff0c;这一趋势对于我们TikTok爆款商机打造息息相关。 然而&#xff0c;在目前的口腔护理赛道&#xff0c;高露洁、宝洁、飞利浦等巨头盘踞&#xff0c;掌握…

Spring重要知识点

一、Spring中相关概念 1.IOC 控制反转 IoC&#xff08;Inverse of Control:控制反转&#xff09;是⼀种设计思想&#xff0c;就是将原本在程序中⼿动创建对象的控制权&#xff0c;交由Spring框架来管理。IoC 在其他语⾔中也有应⽤&#xff0c;并⾮ Spring 所独有。 IoC 容器…

政务服务场景为何要打造AI交互数字人?

随着Chat GPT兴起&#xff0c;越来越多服务场景通过AI交互数字人以多模态交互形式实现人机交互。如近日昆山市档案馆推出了AI交互数字人“昆兰”&#xff0c;数字人设置于市档案馆一楼大厅入口处&#xff0c;市民可以与AI交互数字人进行实时问答交流&#xff0c;了解总书记关于…

使用 Docker 部署 的WAF: 雷池社区版

Web应用防火墙&#xff08;WAF&#xff09;是保护网站不受恶意攻击的关键组件。 使用 Docker 部署雷池社区版&#xff0c;可以大大简化安全管理工作。 一、WAF 雷池社区版简介 雷池社区版是一种流行的开源 Web 应用防火墙&#xff0c;它提供基本的安全保护&#xff0c;如防止…

【C++】:STL序列式容器list源码剖析

一、list概述 总的来说&#xff1a;环形双向链表 特点&#xff1a; 底层是使用链表实现的&#xff0c;支持双向顺序访问 在list中任何位置进行插入和删除的速度都很快 不支持随机访问&#xff0c;为了访问一个元素&#xff0c;必须遍历整个容器 与其他容器相比&#xff0c;额外…

小蓝和小桥的挑战*

题目 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int t sc.nextInt();sc.nextLine();while(t-- > 0) {int n sc.nextInt();sc.nextLine();int[] a new int[n];for(int i0;i<n;i)a[i…

【码银送书第十一期】《自然语言生成SQL与知识图谱问答实战》

语义解析技术可以提高人机交互的效率和准确性&#xff0c;在自然语言处理、数据分析、智能客服、智能家居等领域都有广泛的应用前景。特别是在大数据时代&#xff0c;语义解析能够帮助企业更快速地从大量的数据中获取有用的信息&#xff0c;从而提高决策效率。 01 语义解析的应…

34、StoHisNet:CNN+Transformer结合首次用于胃病理图像4分类[奔狼怎配质疑雄狮!]

本文由贵州大学医学院&#xff0c;贵州省人民医院医学影像教研室&#xff0c;精密影像诊疗国际示范合作基地&#xff0c;贵州大学计算机科学与技术学院&#xff0c;清华大学北京信息科学与技术国家研究中心&#xff0c;共同合作&#xff0c;于2022年5月28日发表于<Computer …

我的最爱,人类的未来

ATLAS (Boston Dynamics&#xff1a;波士顿动力公司) Atlas是由波士顿动力公司设计的一种跳跃式、后空翻类人机器人&#xff0c;它使用深度传感器进行实时感知&#xff0c;并使用模型预测控制技术来改善运动。Atlas 高 5 英尺&#xff0c;重 190 磅&#xff0c;拥有三台机载计算…

VBA窗体跟随活动单元格【简易版】(2/2)

上一篇博客&#xff08;文章连接如下&#xff09;中使用工作表事件Worksheet_SelectionChange实现了窗体跟随活动单元格的动态效果。 VBA窗体跟随活动单元格【简易版】(1/2) 为了在用户滚动工作表窗体之后仍能够实现跟随效果&#xff0c;需要使用Application.Windows(1).Visibl…

数据结构Java版(3)——队列Queue

一、概念 队列也是一种线性数据结构&#xff0c;最主要的特点是入队列顺序和出队列顺序是相同的&#xff0c;操作时在队尾入队&#xff0c;在队首出队。在Java中给我们提供了一个泛型队列——Queue&#xff0c;其中最常用的方法有&#xff1a; void offer()&#xff1a;入队E …

Ubuntu下将nvidia-smi封装为GUI界面,实时查看显卡信息

和win系统不同的是&#xff0c;在Ubuntu端&#xff0c;系统级的系统监视器中&#xff0c;只能查看内存、CPU和网络状态&#xff0c;并不能查看GPU状态 而使用NVIDIA显卡的朋友都知道一条指令 nvidia-smi 在终端运行后即可查看显卡信息、资源占用情况等 但是这样会占用终端&am…

轮胎侧偏刚度线性插值方法

一、trucksim取数据 步骤一 步骤二 二、数据导入到matlab中 利用simulink的look up table模块 1是侧偏角&#xff1b;2是垂直载荷&#xff1b;输出是侧向力。 侧向力除以侧偏角就是实时的侧偏刚度。

排序:计数排序

目录 思想&#xff1a; 操作步骤&#xff1a; 思路&#xff1a; 注意事项&#xff1a; 优缺点&#xff1a; 代码解析&#xff1a; 完整代码展示&#xff1a; 思想&#xff1a; 计数排序又称为鸽巢原理&#xff0c;是对哈希直接定址法的变形应用。 操作步骤&#xff…

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用Binning像素合并功能(C#)

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用Binning像素合并功能&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机NEOAPI SDK和短曝光功能的技术背景Baumer工业相机通过CameraExplorer软件使用Binning功能Baumer工业相机通过NEOAPI SDK使用Binning功能1.引用合…

2018年认证杯SPSSPRO杯数学建模C题(第二阶段)机械零件加工过程中的位置识别全过程文档及程序

2018年认证杯SPSSPRO杯数学建模 基于轮廓提取与图像配准的零件定位问题研究 C题 机械零件加工过程中的位置识别 原题再现&#xff1a; 在工业制造自动生产线中&#xff0c;在装夹、包装等工序中需要根据图像处理利用计算机自动智能识别零件位置&#xff0c;并由机械手将零件…

python数字图像处理基础(九)——特征匹配

目录 蛮力匹配&#xff08;ORB匹配&#xff09;RANSAC算法全景图像拼接 蛮力匹配&#xff08;ORB匹配&#xff09; Brute-Force匹配非常简单&#xff0c;首先在第一幅图像中选取一个关键点然后依次与第二幅图像的每个关键点进行&#xff08;描述符&#xff09;距离测试&#x…

爆推联盟,推广接单平台定制开发(智创有术)

爆推联盟官网、推广接单平台、很多朋友问我做项目要怎么做&#xff0c;项目怎么选&#xff1f;那些项目比较稳定靠谱&#xff0c;赚钱还不错的平台&#xff0c;其实网上的项目很多&#xff0c;别说做&#xff0c;看都看不过来&#xff0c;我们做项目最主要的就是稳定嘛&#xf…