WINDOWS 環境下編譯 OLLVM 替換到 NDK 環境

来源:https://www.cnblogs.com/maiiiii/archive/2023/07/14/17553519.html
-Advertisement-
Play Games

原文地址:https://blog.csdn.net/zhanglei5415/article/details/131434931 ## 一、問題 當對含有中文的url字元串,進行NSURL對象包裝時,是不能被識別的。 不會得到期望的NSURL對象,而是返回一個nil 值 ; ```objectiv ...


編譯 OLLVM

環境準備

這裡使用的是AGP 7.2.2NDK 25.2.9519653llvm 14.0.7cmake 3.22.1python39

git

用來下載源碼

python

搞到這一步環境變數里應該已經有python了吧

NDK

AGP 的 7.2.2 版本預設使用的 NDK 版本為21.4.7075529,對應的 LLVM 為9.0.9

ndk

需要根據實際情況選擇 NDK 對應的 LLVM 版本,編譯 OLLVM,LLVM 版本號可以通過Sdk_DIR\ndk\$version\toolchains\llvm\prebuilt\windows-x86_64\AndroidVersion.txt文件看到,如SDK Manager 中的最新版本25.2.9519653為:

14.0.7
based on r450784d1
for additional information on LLVM revision and cherry-picks, see clang_source_info.md

在 module 的build.gradle中指定 NDK 版本

android {
    ndkVersion "25.2.9519653"
}

OLLVM

可以在 github/heroims/obfuscator 倉庫的分支中找到對應的移植源碼,

heroims

13x14x版本也可以在 github/yangyiyu08/ollvm-project 倉庫的對應分支中獲取。14x版本還可以直接在 Releases 中下載作者編譯好的文件,跳過編譯的步驟。但這個文件在我的環境下會有NDK編譯錯誤的情況,我自己編譯出來的文件運行正常。

這裡使用NDK 25.2.9519653,需要下載 14x 的源碼。

CMAKE

AGP 的 7.2.2 版本預設使用的 cmake 版本為3.18.1,在指定 NDK 版本到 25.2.9519653 後,會在編譯時提示需要升級到 3.19 版本以上的信息。所以這裡在編譯前就通過 SDK Manager 下載 3.22.1 版本,並把所在目錄添加到環境變數

同時在build.gradleCMakeLists中修改工程的 cmake 版本。

開始編譯

在源碼的目錄執行以下命令構建 cmake 配置
cmake -S llvm -B build -G Ninja -DLLVM_ENABLE_PROJECTS="clang" -DCMAKE_BUILD_TYPE=Release -DLLVM_INCLUDE_TESTS=OFF -DLLVM_ENABLE_NEW_PASS_MANAGER=OFF

對應的參數:

-G Ninja: 使用 ninja 進行編譯源碼
-DLLVM_ENABLE_PROJECTS="clang": 啟用clang,有多個選擇 但我們只需要clang,官方文檔有說明
-DCMAKE_BUILD_TYPE=Release: 構建 release 版本,比 debug 版本編譯快很多
-DLLVM_INCLUDE_TESTS=OFF: 關閉 llvm 的頭文件測試,也是為了加快編譯速度
-DLLVM_ENABLE_NEW_PASS_MANAGER=OFF: 這個非常重要,llvm-12.x 開始預設使用 newPM進行編譯源碼,導致 ollvm 不起作用!因此,需要加上這個參數禁用掉 newPM。(在每個編譯時增加flag -flegacy-pass-manager 讓 llvm 不走 newPM 編譯也可以,但沒必要)

執行以上命令後若提示 Configuration done. 則配置成功。接下來執行以下命令開始編譯:
cmake --build build -j16

其中-j16為指定的線程數,需要根據 CPU 調整。然後等待編譯完成

waiting...

編譯完成

編譯完成後打開build/bin目錄,找到clang.execlang++.execlang-cl.exe,可以看到三個文件的MD5是相同的。

certutil

編譯後的文件大小為 137MB,對比 NDK 目錄下的 clang.exe 僅有 88.6MB。編譯後的文件可以通過strip clang.exe命令剝離可執行文件減小到 113MB。

替換到 NDK 環境

備份與替換

首先打開當前 NDK 的 llvm 目錄,將clang.execlang++.execlang-cl.exe備份,然後把上一步編譯後的文件複製到當前目錄。

bak

複製 lib 庫

此時編譯會出現找不到libunwind等庫的錯誤,錯誤信息顯示目錄文件不存在

  CMake Error at SDK_DIR/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake:69 (message):
    The C compiler
  
      "SDK_DIR/ndk/25.2.9519653/toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe"
  
    is not able to compile a simple test program.
  
    It fails with the following output:
  
      Change Dir: APPLICATION_DIR/app/.cxx/RelWithDebInfo/703a16l3/arm64-v8a/CMakeFiles/CMakeTmp
      
      Run Build Command(s):SDK_DIR\\cmake\3.22.1\bin\ninja.exe cmTC_c87d1 && [1/2] Building C object CMakeFiles/cmTC_c87d1.dir/testCCompiler.c.o
      [2/2] Linking C executable cmTC_c87d1
      FAILED: cmTC_c87d1 
      cmd.exe /C "cd . && SDK_DIR\\ndk\25.2.9519653\toolchains\llvm\prebuilt\windows-x86_64\bin\clang.exe --target=aarch64-none-linux-android26 --sysroot=SDK_DIR/ndk/25.2.9519653/toolchains/llvm/prebuilt/windows-x86_64/sysroot -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments CMakeFiles/cmTC_c87d1.dir/testCCompiler.c.o -o cmTC_c87d1  -latomic -lm && cd ."
      ld: error: unable to find library -latomic
      ld: error: cannot open SDK_DIR/ndk/25.2.9519653/toolchains/llvm/prebuilt/windows-x86_64/lib/clang/14.0.0/lib/linux/libclang_rt.builtins-aarch64-android.a: No such file or directory
      ld: error: unable to find library -l:libunwind.a
      ld: error: cannot open SDK_DIR/ndk/25.2.9519653/toolchains/llvm/prebuilt/windows-x86_64/lib/clang/14.0.0/lib/linux/libclang_rt.builtins-aarch64-android.a: No such file or directory
      ld: error: unable to find library -l:libunwind.a
      clang: error: linker command failed with exit code 1 (use -v to see invocation)
      ninja: build stopped: subcommand failed.
      
      
  
    
  
    CMake will not be able to correctly generate this project.
  Call Stack (most recent call first):
    CMakeLists.txt:10 (project)

需要把SDK_DIR/ndk/25.2.9519653/toolchains/llvm/prebuilt/windows-x86_64/lib64/目錄下的calng目錄,複製到/lib目錄中,並把clang/14.0.7修改為14.0.0

這裡的14.0.0是根據錯誤日誌中出現的路徑提取出來的,在控制臺中輸入clang -v查看當前 clang 的版本,按照日誌中出現或當前使用的 clang 版本調整。

clang

至此,NDK 中 集成 OLLVM 已經完成了。接下來是配置和使用 OLLVM。

配置 OLLVM

這部分網上參考的文檔很多,這裡也只是簡單介紹一下參數

參數

參數 說明
-mllbm -sub 激活指令替換
-mllvm -sub_loop=3 如果激活了傳遞,則在函數上應用3次。預設值:1
-mllvm -bcf 激活虛假控制流程
-mllvm -bcf_loop=3 如果激活了傳遞,則在函數上應用3次。預設值:1
-mllvm -bcf_prob=40 如果激活了傳遞,基本塊將以40%的概率進行模糊處理。預設值:30
-mllvm -fla 激活控制流扁平化
-mllvm -split 激活基本塊分割。在一起使用時改善展平
-mllvm -split_num=3 如果激活了傳遞,則在每個基本塊上應用3次。預設值:1

拓展參數

heroims在移植 OLLVM 時,集成了Armariris的字元串混淆功能。

參數 說明
-mllvm -sobf 編譯時候添加選項開啟字元串加密
-mllvm -seed= 指定隨機數生成器種子

使用

可以在build.gradle中進行配置,如:

android {
    defaultConfig {
        extrnalNativeBuild {
            cmake {
                cppFlags '-mllvm -fla'
            }
        }
    }
}

也可以在CMakeLists中進行配置,如:

SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mllvm -fla -mllvm -sub -mllvm -sobf")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mllvm -fla -mllvm -sub -mllvm -sobf")

輸出比對

以配置了-fvisibility=hidden -ffunction-sections -fdata-sections 的獲取 updatemark 為例,源碼為:

static jstring getUpdate(JNIEnv *env, jobject clazz) {
    struct stat sb{};
    int updates = 0;
    int updatens = 0;
    if (stat("/data/data", &sb) == -1) {
        //獲取失敗
    } else {
        updatens = (int) sb.st_atim.tv_nsec;
        updates = (int) sb.st_atim.tv_sec;
    }
    std::string idRes = std::to_string(updates) + "." + std::to_string(updatens);
    return env->NewStringUTF(idRes.c_str());
}

before

before

after

after

遇到的問題

虛假控制流程的問題

實際編譯的過程中,增加了-mllvm -bcf參數後,編譯超過半個小時還是沒有完成,移除後正常編譯。
搜索了相關的問題後,發現可能是 ndk 的編譯器優化 flag 在 release 時是 -O2 導致的。

This is specifically an issue with llvm / android-ndk when compiling with thumb mode. You'll either need to disable thumb compilation (annoying) or patch the llvm to not generate this type of instructions; it's not actually an obfuscator-llvm issue.

Potentially try upgrading your ndk as well, though I'm doubtful that will fix this issue. If I have extra time later I can try to find the patch I needed to create for llvm to specifically work around this issue.

但在我這邊,debug 依然是沒有響應,只能是去掉-bcf

CMAKELIST 的 Release 不生效問題

CMAKE_C_FLAGSCMAKE_C_FLAGS_DEBUG配置的參數都可以正常生效,但CMAKE_C_FLAGS_RELEASE配置無法在 release 時生效。只能配置在CMAKE_C_FLAGS中,然後在 CMakeLists 中判斷當前環境是否為 DEBUG。

參考資料


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 博客推行版本更新,成果積累制度,已經寫過的博客還會再次更新,不斷地琢磨,高質量高數量都是要追求的,工匠精神是學習必不可少的精神。因此,大家有何建議歡迎在評論區踴躍發言,你們的支持是我最大的動力,你們敢投,我就敢肝 ...
  • mysql-8安裝教程(windows 64位) 安裝windows 64位mysql-8 第1步,從官網下載mysql-8最新版本 下載 MySQL Community Server 8.0.20,下載地址:https://dev.mysql.com/downloads/mysql/ 第2步,解壓 ...
  • # SQLServer 批量修改或插入 # 場景 今天在工作中遇到這麼一個場景,我需要根據條件對錶A做批量更新或插入。因為條件比較複雜,所以我使用了臨時表B,先把需要更新或插入的數據查詢出來放入臨時表。然後更新表A的某欄位,更新條件是A.id = B.id,更新效果是若記錄存在表A中,則更新表A的字 ...
  • ![file](https://img2023.cnblogs.com/other/2685289/202307/2685289-20230714100921932-1108940383.jpg) ## 用戶案例 | 自如 隨著自如業務的快速發展,不斷增長的調度任務和歷史逾萬的存量任務對平臺穩定性提 ...
  • MySQL資料庫遷移(直接複製文件) - 簡書 (jianshu.com) 看了幾種方法: 1、修改註冊表的 windows下遷移mysql數據 - 程式員丁先生 - 博客園 (cnblogs.com) 2、mysqldump指令將資料庫表/數據保存成xx.sql文件存到本地的 (157條消息) 如 ...
  • #### 先說些廢話 作為一個全棧開發工作者,曾經對公司專職的大數據開發有著濃厚的興趣,所以嘗試學習大數據開發所需要的各種技術棧。 本文就是我在學習過程中記錄下,所遇到的一些大數據面試的提問,僅供參考。 當然,因為時間精力有限,並非所有的問題我都去記錄了答案,如果您不瞭解某些問題或者不認可我記錄的解 ...
  • 1、簡介 人大金倉資料庫(KingbaseES)是面向事務處理類、兼顧分析類應用領域的新型資料庫產品,致力於解決高併發、高可靠數據存儲計算問題,是一款為企事業單位管理信息系統、業務系統量身打造的承載資料庫,目前性能已全面升級,是具有高成熟度的資料庫產品。 2、準備工作 資料庫的安裝包可以在人大金倉官 ...
  • ![](https://img2023.cnblogs.com/blog/3076680/202307/3076680-20230711162608661-1958587529.png) # 1. 一個季度的開始日期和結束日期 ## 1.1. 以yyyyq格式(前面4位是年份,最後1位是季度序號)給 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...