luckfollowme arm 学习篇(3) - NDK 交叉编译
# luckfollowme arm 学习篇(3) - NDK 交叉编译之前带大伙用 **cmake**配置 **CMakeLists.txt** 。
然后依然可以正常编译 **window** 的可执行文件
可我们的主要目标是学习 **arm hook** 那么只构建 **windows** 的可执行文件肯定是不行的。
这时候就需要我们的 **ndk 的交叉编译工具**了
**交叉编译** 您可以理解成 可以在 windows 环境下构建 基于 linux 等其他平台的二进制文件。
### ABI 介绍
在构建之前,我说一下 abi。
abi 个人理解就是 cpu 架构生成的指令集
我们需要在编译的时候指定下 abi (arch) 。
abi 可以指定大概4种:
x86
x86_64
armeabi-v7a
arm64-v8a
后续我们会编译可能会指定 abi 生成,稍微注意一下即可。
## NDK 交叉编译工具
上一章也提到了 **ndk cmaketoolchain**
具体参考: https://developer.android.google.cn/ndk/guides/cmake?hl=zh-cn
要通过 ndk cmake 使用交叉工具链 参考:
https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-android
**在CMake 3.21 之后,貌似内置了 NDK 交叉编译工具链的支持,所以您只需要简单的参数即可**
```
-DCMAKE_SYSTEM_NAME=Android # 启动 android 的交叉编译环境
-DCMAKE_ANDROID_NDK=${HOME}/Android/Sdk/ndk/22.1.7171670 #设置使用的ndk路径
-DCMAKE_ANDROID_ARCH_ABI= x86|x86_64|armeabi-v7a|arm64-v8a # 设置abi arch
-DCMAKE_SYSTEM_VERSION=21 # 设置android api 级别 有些 api不支持 arm64 21 算是最小支持arm64版本了
-DCMAKE_BUILD_TYPE=DEBUG|RELEASE # 编译是否优化
```
当然,我写了个**python**脚本 能够快速编译 **x86 x86_64 armeabi-v7a arm64-v8a** 等不同 **arch** 的二进制文件
```python
import os
import shutil
import subprocess
abis = ["x86", "x86_64", "armeabi-v7a", "arm64-v8a"]
class AndroidPlatformBuilder(object):
cmake_args = list()
cmake_build_type = "Debug"# "Debug|Release"
project_dir = ""
platform = "android"
arch = ""
android_api_level = 21
def __init__(self, android_nkd_dir, cmake_dir, arch, target_name ,project_dir="") -> None:
# 如何没有写项目路径 默认上一层路径
self.project_dir = project_dir if project_dir else os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
self.arch = arch
self.target_name = target_name
self.cmake_build_dir = os.path.normpath(f"{self.project_dir}/build/cmake-build-android-{arch}")
self.build_output_dir = os.path.normpath(f"{self.project_dir}/build/{arch}")
self.cmake = cmake_dir
if arch == "armeabi-v7a" or arch == "x86":
self.android_api_level = 19
# cmake android 构建参数
self.cmake_args += [
"-DCMAKE_SYSTEM_NAME=Android", # 启用android 交叉编译
f"-DCMAKE_C_COMPILER=clang", # ndk 是使用 clang 进行编译的
f"-DCMAKE_CXX_COMPILER=clang++",
f"-DCMAKE_BUILD_TYPE={self.cmake_build_type}",# debug 调试信息多点 不会被优化 release 是最终优化版本
f"-DCMAKE_ANDROID_NDK={android_nkd_dir}", # ndk 路径
f"-DCMAKE_SYSTEM_VERSION={self.android_api_level}", # arm64 架构是在 Android 5.0 (API level 21) 开始支持的
f"-DCMAKE_ANDROID_ARCH_ABI={self.arch}" # android arch abi
]
def build(self):
# 0.清空缓存
if os.path.exists(self.cmake_build_dir):
shutil.rmtree(self.cmake_build_dir)
# 1.构建 adnroidcmake 项目
cmake_cmd_options = ["-S {}".format(self.project_dir), "-B {}".format(self.cmake_build_dir)]
cmd = + cmake_cmd_options + self.cmake_args
# 集合转换 string 命令
cmd = " ".join(cmd)
print(cmd)
os.system(cmd)
# 2. 根据cmake 项目 构建二进制文件
if not os.path.exists(self.build_output_dir):
os.makedirs(self.build_output_dir)
subprocess.run(["cmake", "--build", "."], cwd=self.cmake_build_dir,check=True)
print("cmake --build .")
shutil.copyfile(f"{self.cmake_build_dir}/{self.target_name}",f"{self.build_output_dir}/{self.target_name}")
if __name__ == "__main__":
ndk_path = r"C:\Users\hp\AppData\Local\Android\Sdk\ndk\25.1.8937393".replace('\\',"/")
cmake_path = r"F:\c++\msys2\mingw64\bin\cmake".replace('\\',"/")
print("ndk_path:", ndk_path)
print("cmake_path:", cmake_path)
for abi in abis:
# target_name 是 add_executable 中生成的执行程序名称
builder = AndroidPlatformBuilder(android_nkd_dir=ndk_path, cmake_dir=cmake_path, arch=abi,target_name="InlineHookPratice")
builder.build()
```
您把他复制到我图中所示的地方:
</p>
</p>
**修改 您的 NDK_PATH CMAKE_PATH 以及 CMakeLists 中您最终构建的可执行程序的 target_name**
</p>
</p>
执行后,您的build 目录下应该会有以下文件:
</p>
</p>
## 浏览arm64
我们将生成的 **arm64-v8a** 中的文件 拖入到 **ida pro** 中,然后搜索 **main** 方法。 您应该就可以看到 对应的 **hello world** 字样
由于用到 std:: 里面的东西 生成的内容很多,导致我看点迷糊。
下章教程我们还是弄个简单的分析吧。 从第一篇看到第三篇很全面虽然看不懂,但是也学习了些内容
luckfollowme是什么意思 感谢分享 感谢楼主分享! 不行不行不行 这样如果头文件多 就出BUG 受益匪浅,感谢楼主
页:
[1]