为什么写这篇笔记
最近在进行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
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) {
jmethodID cid = env->GetStaticMethodID((jclass) g_cls, "postData", "(I[B)V");
if (cid) {
jbyteArray arr = env->NewByteArray(len);
env->SetByteArrayRegion(arr, 0, len, reinterpret_cast<jbyte *>(data));
env->CallStaticVoidMethod((jclass) g_cls, cid, seq, arr);
seq++;
}
}
}
}
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) {
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);
}
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) {
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++;
}
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);
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)));
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;
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) {
}
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;
hook_postdata();
return JNI_VERSION_1_6;
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_jifen_qukan_MainActivity_stringFromJNI(
JNIEnv *env,
jobject ) {
std::string hello = "Hello from C++";
const char *p = hello.c_str();
const char *a = strstr(p, "hookso");
return env->NewStringUTF(p);
}
extern "C" JNIEXPORT void JNICALL
Java_com_jifen_qukan_MainActivity_cacheCls(
JNIEnv *env,
jobject ) {
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);
}
}
extern "C" JNIEXPORT void JNICALL
Java_com_jifen_qukan_MainActivity_popen(
JNIEnv *env,
jobject , jstring str) {
FILE *pfile = NULL;
char buf[0x1000] = {0};
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);
}
LOGD("执行[%s]结束:\n", nativeString);
pclose(pfile);
env->ReleaseStringUTFChars(str, nativeString);
}
|