Android本机库中的功能重定向

在本文中,我将讨论如何使用AndHook框架将函数调用重定向到本机库。您可以直接截获公共(导出的函数)和非公共的调用。您可以在此处和框架页面上阅读有关重定向的更多信息


作为示例,我们将考虑其库的实现情况。但是,此框架还允许您进行工作,而无需使用xposed重新构建应用程序。


在本文中,我将使用Windows的Visual Studio和BatchApkTool。可以使用Android Studio代替Visual Studio,甚至可以通过gcc或clang(高级选项)对其进行编译。可以使用apktool代替BatchApkTool。我不会停止详细介绍使用BatchApkTool,因为 处理程序中的工作并不困难。


首先,您需要使用BatchApkTool或apktool解析APK。


现在,从项目页面下载库和头文件,为此,您需要单击此链接和此链接,然后下载适用于您平台的库。(我没有发现Compat的版本与普通版本之间的区别,我个人使用的是普通版本。也许他们会在注释中说明)


设置Visual Studio以使用NDK

Visual Studio Installer :



.


在Visual Studio中创建一个新项目

, , , .


" (Android)", .



:

. : , : < >, API 14 ARM X86, ARM64 X64 21 .
.
-> , :




, , , , .


. .



. .



, .cpp


#include "AndHook.h"

让我们创建JNI_OnLoad函数,在其中注册钩子。
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv* env = NULL;
    jint result = -1;
    LOGD("JNI_OnLoad start!");

    if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
        LOGE("JNI_OnLoad! GetEnv failed");
        return -1;
    }

    RegisterHooks();

    result = JNI_VERSION_1_4;
    LOGD("JNI_OnLoad! finished!");
    return result;
}

RegisterHooks函数本身:


//       #define
#ifdef __arm__
#define Test_Offset 0x1234
#elif __aarch64__
#define Test_Offset 0x1235
#elif __i386__
#define Test_Offset 0x1236
#elif __x86_64__
#define Test_Offset 0x1237
#endif
void (*Old_Test)();
void Test()
{
    LOGD("Test!");
    // Do something
    Old_Test();
}
void (*Old_Test2)();
void Test2()
{
    LOGD("Test2!");
    Old_Test2(); //      Test2
}
void RegisterHooks() {
    const void* libil2cpp = AKGetImageByName("libil2cpp.so"); //     .
    if (libil2cpp == NULL) {
        LOGW("AKGetImageByName return null!");
        return;
    }

    //      
    //  -     IDA/Ghidra
    //    il2cpp-     https://github.com/Perfare/Il2CppDumper
    AKHookFunction(AKFindAnonymity(libil2cpp, Test_Offset), reinterpret_cast<void*>(&Test), reinterpret_cast<void**>(&Old_Test));
    //       Test_Offset   libil2cpp       Test,  .       Old_Test.

    //   
    AKHookFunction(AKFindSymbol(libil2cpp, "Test2"), reinterpret_cast<void*>(&Test2), reinterpret_cast<void**>(&Old_Test2));

    //         :
    void (*Test3)();
    Test3 = reinterpret_cast<void (*)()>(AKFindAnonymity(libil2cpp, 0x12345));
    Test3();

    //      
    const uint8_t data[] = { 0x00, 0xF0, 0x20, 0xE3 }; //  NOP
    AKPatchMemory(reinterpret_cast<const void*>(AKFindAnonymity(libil2cpp, 0x123456)), reinterpret_cast<const void*>(&data), 4);
    //       0x123456

    AKCloseImage(libil2cpp);
}

同样,对于几种架构下的补丁,使用#define也很方便


#ifdef __arm__
#define Patch_Offset 0x1234
#define Patch_Data { 0x00, 0xF0, 0x20, 0xE3 }
#elif __aarch64__
#define Patch_Offset 0x1234
#define Patch_Data { 0x1F, 0x20, 0x03, 0xD5 }
#endif

const uint8_t data[] = Patch_Data;
const size_t len = sizeof(data) / sizeof(uint8_t);
AKPatchMemory(reinterpret_cast<const void*>(AKFindAnonymity(libil2cpp, Patch_Offset)), reinterpret_cast<const void*>(&data), len);

完成代码编写后,必须对其进行编译。
为此,您需要:


选择目标平台


组装项目


如果有多个平台,请重复步骤1-2。


AndHook lib . ( ).


. MainActivity . onCreate MainActivity :


const-string v0, "SharedObject1"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V

SharedObject1 lib .so
il2cpp- MainActivity onCreate smali/com/unity3d/player/UnityPlayerActivity.smali.


.


:
https://github.com/asLody/AndHook/
http://armconverter.com/
http://armconverter.com/hextoarm/


All Articles