潍坊建设网站公司,怎么建设,公司主页怎么制作,网上注册公司在哪个网址注册arm官方手册
由于市面上几乎没有arm相关书籍#xff0c;所以推荐看官方文档。虽然是英文的#xff0c;看不下去也要硬看#xff0c;毕竟搞这方面的还是得有啃英文文档/书籍的能力。
另外#xff0c;再推荐一个翻译网站#xff1a;https://www.deepl.com/zh/translator
…arm官方手册
由于市面上几乎没有arm相关书籍所以推荐看官方文档。虽然是英文的看不下去也要硬看毕竟搞这方面的还是得有啃英文文档/书籍的能力。
另外再推荐一个翻译网站https://www.deepl.com/zh/translator
arm 手册下载地址
https://developer.arm.com/documentation/ddi0487/latest
https://developer.arm.com/documentation/ddi0602/2023-12/?langen
开发环境
使用 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?hlzh-cn
这里只简单介绍必要的。
Android.mk
LOCAL_PATH : $(call my-dir)include $(CLEAR_VARS)#LOCAL_ARM_MODE : armLOCAL_MODULE : arm64LOCAL_SRC_FILES : arm64.cinclude $(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-26APP_ABI默认情况下NDK 构建系统会为所有非弃用 ABI 生成代码。您可以使用 APP_ABI 设置为特定 ABI 生成代码。 指令集值32 位 ARMv7APP_ABI : armeabi-v7a64 位 ARMv8 (AArch64)APP_ABI : arm64-v8ax86APP_ABI : x86x86-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_PLATFORMAPP_PLATFORM 会声明构建此应用所面向的 Android API 级别并对应于应用的 minSdkVersion。例如 android-16 说明无法运行在低于Android 4.1API 级别 16的设备上。 arm64.c
#include stdio.hint 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_MKApplication.mkndk-build 脚本位于 NDK 安装目录顶层。所以我们定义一个变量表示其目录然后直接使用即可。 NDK_APPLICATION_MKfile 使用 NDK_APPLICATION_MK 变量指向的特定 Application.mk 文件进行构建。 如果Android.mk和Application.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.dobj/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,#-0x10var_10]!
.text:0000000000000718 FD 7B 01 A9 STP X29, X30, [SP,#0x10var_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: main20↓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: main12↓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 格式。