使用sandhook进行Native Hook

本文详细介绍了在Android平台上使用SandHook框架进行动态函数Hook的实现过程,包括SO文件方法的拦截、Java层数据处理、以及dlopen函数的Hook,以实现在特定库方法执行前后插入自定义逻辑。示例代码展示了如何在arm64架构上获取并传递加密数据到APP进行分析。
摘要由CSDN通过智能技术生成

为什么写这篇笔记

最近在进行so分析,需要将so中一个方法的加密钱的数据获取到,并传到app上获取到进行分析,于是就使用该框架完成了这个功能,在arm64上使用该框架,需要将指针切换为int64即可。

代码

#include <jni.h>
#include <string>
#include <android/log.h>
#include "sandhook_native.h"
#include<dlfcn.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>


#define TAG  "hook"
#define LOGD(...)   NULL
//__android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__)
static JavaVM *g_vm = NULL;
static int tx_seq = 0;
static int rx_seq = 100;

static jobject g_cls = NULL;

static const char *TARGE_LIB_NAME = "libxx.so";


void call_java_data_process(char *data, int len, int seq) {
    JNIEnv *env;
    g_vm->AttachCurrentThread(&env, nullptr);
    if (env) {
        if (g_cls) {
//            LOGD("jcalss find");
            jmethodID cid = env->GetStaticMethodID((jclass) g_cls, "postData", "(I[B)V");
            if (cid) {
//                LOGD("CID:%d", cid);
                jbyteArray arr = env->NewByteArray(len);
                env->SetByteArrayRegion(arr, 0, len, reinterpret_cast<jbyte *>(data));
                env->CallStaticVoidMethod((jclass) g_cls, cid, seq, arr);
                seq++;
            }

        }
    }
//    g_vm->DetachCurrentThread();
}


typedef int (*posthook)(int a1, int a2, int r2_0, int r3_0);

posthook posthookfunction_org = nullptr;
posthook posthookfunction_backup = nullptr;

posthook xorhookfunction_org = nullptr;
posthook xorhookfunction_backup = nullptr;

typedef int (*fieldhook)(int a1);

typedef int (*sha1hook)(int a1, int a2);

sha1hook sha1_org = nullptr;
sha1hook sha1_backup = nullptr;

typedef int (*imeihook)(int a1);

imeihook imei_org = nullptr;
imeihook imei_backup = nullptr;


extern "C" int new_4AA54(int a1) {
//    const char *p = "862790040441175";
    LOGD("imei hook enter");
    int ret = imei_backup(a1);
    if (ret) {
        LOGD("imei output:%s", (char *) ret);
    }

    return ret;
}

extern "C" int new_38734(int a1, int a2) {
    if (a2) {
        char *pdata = (char *) (a2);
        LOGD("sha1 input:%s", pdata);
    }

//     const char *p = "com.jifen.qukan";
//        a2 = int(p);
    int ret = sha1_backup(a1, a2);
    if (ret) {
        LOGD("sha1 output:%s", (char *) ret);
    }

    return ret;
}

extern "C" int new_post(int a1, int a2, int a3, int a4) {
//    LOGD("enter hoook new_post");
    if (a3) {
        char *pdata = (char *) (*(int *) a3);
        int len = (*((int *) a3 + 1));
        tx_seq = tx_seq % 4;
        call_java_data_process(pdata, len, tx_seq);
        tx_seq++;
//        LOGD("hook post data done");
    }

    return posthookfunction_backup(a1, a2, a3, a4);

}

extern "C" int new_xor(int a1, int a2, int a3, int a4) {
    LOGD("enter hoook new_xor");
    int ret = xorhookfunction_backup(a1, a2, a3, a4);
    if (ret) {
        char *pdata = (char *) (ret);
        int len = strlen(pdata);
        call_java_data_process(pdata, len, rx_seq++);
    }

    return ret;
}

void hook_postdata() {
    //得到函数地址
    void *libnativebase = SandGetModuleBase(TARGE_LIB_NAME);

    //hook post data
    unsigned long funaddr = (unsigned long) libnativebase + 0x22454 + 1;
    void *posthookaddr = reinterpret_cast<void *>(funaddr);
    posthookfunction_org = reinterpret_cast<posthook>(posthookaddr);
    posthookfunction_backup = reinterpret_cast<posthook>(SandInlineHook(
            reinterpret_cast<void *>(posthookfunction_org), reinterpret_cast<void *>(new_post)));

    //hosok xor
    unsigned long xorfunaddr = (unsigned long) libnativebase + 0x99F0 + 1;
    void *xorhookaddr = reinterpret_cast<void *>(xorfunaddr);
    xorhookfunction_org = reinterpret_cast<posthook>(xorhookaddr);
    xorhookfunction_backup = reinterpret_cast<posthook>(SandInlineHook(
            reinterpret_cast<void *>(xorhookfunction_org), reinterpret_cast<void *>(new_xor)));

}

typedef void *(*dlopen_hook_fun)(char *, int);

dlopen_hook_fun dlopen_org = nullptr;
dlopen_hook_fun dlopen_backup = nullptr;
//dlopen_hook_fun old_dlopen= nullptr;
//void *(*old_dlopen)(char *,int) = nullptr;
static int g_is_du_load = 0;

void *new_dlopen(char *arg0, int arg1) {
    LOGD("dlopen is called,arg1:,%s,arg2:%d", arg0, arg1);

    if (strstr(arg0, TARGE_LIB_NAME)) {
        g_is_du_load = 1;
    }

    void *pret = dlopen_backup(arg0, arg1);

    if (g_is_du_load) {
        g_is_du_load = 0;
        hook_postdata();
        LOGD("libdu is hooked,arg1:,%s,arg2:%d", arg0, arg1);
    }
    return pret;

}

extern "C" void hook_dlopen() {

    unsigned long dlopen_ddr = (unsigned long) dlopen;
    void *dlopen_hookaddr = reinterpret_cast<void *>(dlopen_ddr);
    dlopen_org = reinterpret_cast<dlopen_hook_fun>(dlopen_hookaddr);
    dlopen_backup = reinterpret_cast<dlopen_hook_fun>(SandInlineHook(
            reinterpret_cast<void *>(dlopen_org), reinterpret_cast<void *>(new_dlopen)));
}


extern "C" void _init(void) {
//    LOGD("go into _init");
}

extern "C" jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    jint result = -1;
    JNIEnv *env = NULL;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return result;
    }
    g_vm = vm;
//LOGD("go into JNI_OnLoad,dlopen 0x%x", dlopen);
    hook_postdata();
//    starthooklibc();

//    activecalltesthook();
//    hook_dlopen();
    return JNI_VERSION_1_6;
}

extern "C" JNIEXPORT jstring JNICALL
Java_com_jifen_qukan_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    const char *p = hello.c_str();
    const char *a = strstr(p, "hookso");
//    LOGD("ret: %d", *a);
    return env->NewStringUTF(p);
}


extern "C" JNIEXPORT void  JNICALL
Java_com_jifen_qukan_MainActivity_cacheCls(
        JNIEnv *env,
        jobject /* this */) {

    jclass clazz = env->FindClass("com/xx/xx/Utils");
    if (env->ExceptionOccurred()) {
        env->ExceptionDescribe();
        env->ExceptionClear();
        LOGD("fail");
        return;
    }
    if (g_cls == NULL) {
        g_cls = env->NewGlobalRef(clazz); //获取全局引用
//        LOGD("GET CLAZZ");
    }
}



extern "C" JNIEXPORT void  JNICALL
Java_com_jifen_qukan_MainActivity_popen(
        JNIEnv *env,
        jobject /* this */, jstring str) {

    FILE *pfile = NULL;
    char buf[0x1000] = {0};
    // 执行命令
//    char* strCatTcp= "cat /proc/net/tcp |grep :5D8A";
    //char* strNetstat="netstat |grep :23946";
    const char *nativeString = env->GetStringUTFChars(str, 0);

    pfile = popen(nativeString, "r");
    if (NULL == pfile) {
        LOGD("popen打开命令失败!\n");
        return;
    }
    // 获取结果
    LOGD("执行[%s]的结果:\n", nativeString);
    while (fgets(buf, sizeof(buf), pfile)) {
        // 执行到这里,判定为调试状态
        LOGD("%s", buf);
    }//while
    LOGD("执行[%s]结束:\n", nativeString);
    pclose(pfile);
    env->ReleaseStringUTFChars(str, nativeString);
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值