passself 2025-02-06 18:14 采纳率: 42.9%
浏览 12
已结题

android 方法是否被frida hook

android 中如何检测某个java方法是否被 frida hook了,在native cpp中实现。

目前做到 在cpp中获取到了java 方法的artmethod的地址,尝试了一下获取获取这个函数的前几位对比hook 和非hook的区别,发现没有区别。以下是未成功的代码:

const uint8_t fridaHookSignature[] = {0xd6, 0x1f, 0x02, 0x00, 0x58, 0x00, 0x00, 0x50}; 
uintptr_t addr = (uintptr_t)p + entry_point_offset;
    unsigned int *ins1_ptr = (unsigned int *)addr;

    // 假设方法起始地址 methodAddr,我们要检查该地址的开头是否有 Frida 插入的代码
    uint8_t buffer[8];  // 用于存储读取的内存内容

    // 读取函数开头的内存内容
    memcpy(buffer, reinterpret_cast<void*>(ins1_ptr), sizeof(buffer));

    printBuffer(buffer,sizeof(buffer));
    // 检查读取到的内存内容是否与 Frida 的代码签名匹配
    if (memcmp(buffer, fridaHookSignature, sizeof(fridaHookSignature)) == 0) {
        //cout << "Frida Hook detected!" << std::endl;
        LOGD("Frida Hook detected!");
        //return true;  // 找到 Frida 插入的代码
    }else{
        LOGD("no Frida Hook detected!");
    }

想集思广益一下是否还有其他思路,frida的hook原理,理论上也是替换函数入口.

  • 写回答

5条回答 默认 最新

  • GISer Liu 2025-02-07 23:55
    关注

    该回答引用自GPT-deepseek, 由博主 GISer Liu 编写:

    问题分析

    用户希望在Android的Native层(C++)中检测某个Java方法是否被Frida Hook。用户已经尝试通过比较函数入口处的内存内容来判断是否被Hook,但发现Hook和非Hook的情况下内存内容没有区别,因此该方法未能成功。

    Frida Hook原理

    Frida是一个动态插桩工具,它通过修改目标进程的内存来实现Hook。具体来说,Frida会替换目标函数的入口点,使其跳转到Frida的代理函数,从而拦截和修改函数的执行流程。Frida通常使用以下几种方式来实现Hook:

    1. Inline Hook:直接修改目标函数的指令,使其跳转到代理函数。
    2. GOT/PLT Hook:修改全局偏移表(GOT)或过程链接表(PLT)中的函数指针。
    3. Trampoline Hook:在目标函数前插入跳转指令,跳转到代理函数。

    当前代码的问题

    用户当前的代码尝试通过比较函数入口处的内存内容来判断是否被Hook,但这种方法可能不适用于所有情况,原因如下:

    1. Frida的Hook方式多样:Frida可能使用不同的Hook方式,导致函数入口处的内存内容不一定有明显的特征。
    2. 内存保护机制:某些情况下,内存可能是只读的,或者被其他保护机制保护,导致无法直接读取或修改。

    解决方案

    为了更可靠地检测Frida Hook,可以考虑以下几种方法:

    1. 检查函数入口点的跳转指令

    Frida通常会插入跳转指令(如JMP)来重定向函数执行流程。可以通过检查函数入口点是否存在跳转指令来判断是否被Hook。

    #include <stdint.h>
    #include <string.h>
    #include <android/log.h>
    
    #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "FridaDetect", __VA_ARGS__)
    
    bool isFridaHooked(uintptr_t methodAddr) {
        // 假设Frida插入的跳转指令为 JMP rel32 (0xE9)
        const uint8_t jmpInstruction = 0xE9;
    
        // 读取函数入口点的第一个字节
        uint8_t firstByte = *reinterpret_cast<uint8_t*>(methodAddr);
    
        // 检查是否为跳转指令
        if (firstByte == jmpInstruction) {
            LOGD("Frida Hook detected!");
            return true;
        } else {
            LOGD("No Frida Hook detected!");
            return false;
        }
    }
    

    2. 检查函数入口点的代码签名

    如果Frida使用了特定的代码签名,可以通过比较函数入口点的代码签名来判断是否被Hook。但需要注意,Frida可能会使用不同的签名。

    bool isFridaHooked(uintptr_t methodAddr) {
        // 假设Frida插入的代码签名
        const uint8_t fridaSignature[] = {0xE9, 0x00, 0x00, 0x00, 0x00}; // JMP rel32
        const size_t signatureSize = sizeof(fridaSignature);
    
        // 读取函数入口点的内存内容
        uint8_t buffer[signatureSize];
        memcpy(buffer, reinterpret_cast<void*>(methodAddr), signatureSize);
    
        // 检查是否匹配Frida的代码签名
        if (memcmp(buffer, fridaSignature, signatureSize) == 0) {
            LOGD("Frida Hook detected!");
            return true;
        } else {
            LOGD("No Frida Hook detected!");
            return false;
        }
    }
    

    3. 使用反调试技术

    Frida通常需要附加到目标进程才能进行Hook,因此可以通过反调试技术来检测Frida的存在。例如,检查/proc/self/status中的TracerPid字段,如果该字段不为0,则说明有调试器附加。

    #include <stdio.h>
    #include <string.h>
    #include <android/log.h>
    
    #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "FridaDetect", __VA_ARGS__)
    
    bool isFridaAttached() {
        FILE *fp = fopen("/proc/self/status", "r");
        if (fp == nullptr) {
            LOGD("Failed to open /proc/self/status");
            return false;
        }
    
        char line[128];
        while (fgets(line, sizeof(line), fp)) {
            if (strstr(line, "TracerPid:") != nullptr) {
                int tracerPid = atoi(line + 10);
                fclose(fp);
                if (tracerPid != 0) {
                    LOGD("Frida attached (TracerPid: %d)", tracerPid);
                    return true;
                } else {
                    LOGD("No Frida attached");
                    return false;
                }
            }
        }
    
        fclose(fp);
        LOGD("No Frida attached");
        return false;
    }
    

    总结

    通过检查函数入口点的跳转指令、代码签名以及使用反调试技术,可以更可靠地检测Frida Hook。需要注意的是,Frida的Hook方式可能会不断变化,因此在实际应用中可能需要结合多种检测方法来提高检测的准确性。

    参考

    希望这些方法能够帮助您解决问题!如果有其他问题,欢迎继续讨论。

    如果该回答解决了您的问题,请采纳!如果没有,请私信联系或评论您的疑惑

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 7月11日
  • 已采纳回答 7月3日
  • 创建了问题 2月6日