2016976438 发表于 2023-4-26 01:09

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:: 里面的东西 生成的内容很多,导致我看点迷糊。

下章教程我们还是弄个简单的分析吧。

bj9ye666 发表于 2023-4-26 07:12

从第一篇看到第三篇很全面虽然看不懂,但是也学习了些内容

池塘春草 发表于 2023-4-26 10:16


luckfollowme是什么意思

xhsj1997 发表于 2023-4-26 22:17

感谢分享

Daneellee 发表于 2023-4-27 10:39

感谢楼主分享!

帝爵 发表于 2024-6-20 10:52

不行不行不行 这样如果头文件多 就出BUG

larryliao 发表于 2024-6-20 11:17

受益匪浅,感谢楼主
页: [1]
查看完整版本: luckfollowme arm 学习篇(3) - NDK 交叉编译