如果仅仅是java层hook的话,建议使用xposed框架即可,如果要hook so层的东西,就不得考虑用下cydia了。折腾了几天cydia,java层hook能够成功,系统so hook也能成功,但是hook三方库总是失败,原因不明,有时间继续折腾。以下仅仅是cydia hook java和系统so的步骤列表,以防自己忘记。
1、hook java层
1、新建Android工程,使用空Activity即可。
2、拷贝cydia sdk包中的substrate-api.jar到libs目录
3、修改AndroidManiFest.xml,增加cydia相关内容
<uses-permission android:name="cydia.permission.SUBSTRATE"/> <application .....> <meta-data android:name="com.saurik.substrate.main" android:value=".Main"/><!--自己写的hook类名--> </application>
5、编写hook类,格式如下
public class Main { static void initialize(){ MS.hookClassLoad("xxxxxxx", new MS.ClassLoadHook() { public void classLoaded(Class<?> _class) { Constructor method = null; method method = _class.getConstructor(...) //反射得到方法 if (method != null) { MS.hookMethod(_class, method, new MS.MethodAlteration() { public Object invoked(Object _this, Object... args) throws Throwable { //_this是当前类 //args是参数,可以修改参数后调用老类 args[0]=... return invoke(_this, host, port); } }); } } }); } }
编译得到apk安装即可。
2、Hook So层
1、新建工程,使用空Activity即可
2、新建jni目录,把cydia sdk中的substrate.h、libsubstrate.so和libsubstrate-dvm.so拷贝到jni目录下
3、新建module.cy.cpp,格式如下
#include <android/log.h> #include <substrate.h> #include <stdio.h> #define LOG_TAG "XLZH" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) void cigi_hook(void *orig_fcn, void* new_fcn, void **orig_fcn_ptr) { MSHookFunction(orig_fcn, new_fcn, orig_fcn_ptr); } MSConfig(MSFilterExecutable, "/system/bin/app_process") int (*original_getAge)(void); int replaced_getAge(void) { return 99; } int (*original_arc4random)(void); int replaced_arc4random(void) { return 1234; } void* lookup_symbol(char* libraryname,char* symbolname) { void *imagehandle = dlopen(libraryname, RTLD_GLOBAL | RTLD_NOW); if (imagehandle != NULL){ void * sym = dlsym(imagehandle, symbolname); if (sym != NULL){ return sym; } else{ LOGI("(lookup_symbol) dlsym didn't work"); return NULL; } } else{ LOGI("(lookup_symbol) dlerror: %s",dlerror()); return NULL; } } void * get_base_of_lib_from_maps(char *soname) { void *imagehandle = dlopen(soname, RTLD_LOCAL | RTLD_LAZY); if (soname == NULL) return NULL; if (imagehandle == NULL){ return NULL; } uintptr_t * irc = NULL; FILE *f = NULL; char line[200] = {0}; char *state = NULL; char *tok = NULL; char * baseAddr = NULL; if ((f = fopen("/proc/self/maps", "r")) == NULL) return NULL; while (fgets(line, 199, f) != NULL) { tok = strtok_r(line, "-", &state); baseAddr = tok; tok = strtok_r(NULL, "\t ", &state); tok = strtok_r(NULL, "\t ", &state); // "r-xp" field tok = strtok_r(NULL, "\t ", &state); // "0000000" field tok = strtok_r(NULL, "\t ", &state); // "01:02" field tok = strtok_r(NULL, "\t ", &state); // "133224" field tok = strtok_r(NULL, "\t ", &state); // path field if (tok != NULL) { int i; for (i = (int)strlen(tok)-1; i >= 0; --i) { if (!(tok[i] == ' ' || tok[i] == '\r' || tok[i] == '\n' || tok[i] == '\t')) break; tok[i] = 0; } { size_t toklen = strlen(tok); size_t solen = strlen(soname); if (toklen > 0) { if (toklen >= solen && strcmp(tok + (toklen - solen), soname) == 0) { fclose(f); return (uintptr_t*)strtoll(baseAddr,NULL,16); } } } } } fclose(f); return NULL; } void * get_base_of_lib_from_soinfo(char *soname) { if (soname == NULL) return NULL; void *imagehandle = dlopen(soname, RTLD_LOCAL | RTLD_LAZY); if (imagehandle == NULL){ return NULL; } char *basename; char *searchname; int i; void * libdl_ptr=dlopen("libdl.so",3); basename = strrchr(soname,'/'); searchname = basename ? basename +1 : soname; for(i =(int) libdl_ptr; i!=NULL; i=*(int*)(i+164)){ if(!strcmp(searchname,(char*)i)){ unsigned int *lbase= (unsigned int*)i+140; void * baseaddr = (void*)*lbase; return baseaddr; } } return NULL; } MSInitialize { cigi_hook((void *)arc4random,(void*)&replaced_arc4random,(void**)&original_arc4random); // // void * getAgeSym = lookup_symbol("/data/data/com.example.targetapp/lib/libtargetlib.so","getAge"); // void* lib_base = get_base_of_lib_from_maps("/data/data/com.example.cydiahooktarget/lib/libtargetLib.so"); //// void* lib_base = get_base_of_lib_from_soinfo("/data/data/com.example.cydiahooktarget/lib/libtargetLib.so"); // LOGI("lib base is %p",lib_base); // if (lib_base!=NULL){ // void * getAgeSym = (unsigned char *)lib_base + 0xE49; // LOGI("getAge() should be at %p. Let's hook it",getAgeSym); // cigi_hook(getAgeSym,(void*)&replaced_getAge,(void**)&original_getAge); // } void * getAgeSym = lookup_symbol("/data/data/com.example.cydiahooktarget/lib/libtargetLib.so","getAge"); cigi_hook(getAgeSym,(void*)&replaced_getAge,(void**)&original_getAge); }
4、编写Android.mk文件,内容如下
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE:= substrate-dvm LOCAL_SRC_FILES := libsubstrate-dvm.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE:= substrate LOCAL_SRC_FILES := libsubstrate.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := module.cy #生成的模块名 LOCAL_SRC_FILES := module.cy.cpp #源文件名 LOCAL_LDLIBS += -L$(LOCAL_PATH) -llog -lsubstrate -lsubstrate-dvm include $(BUILD_SHARED_LIBRARY)
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE:= substrate-dvm LOCAL_SRC_FILES := libsubstrate-dvm.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE:= substrate LOCAL_SRC_FILES := libsubstrate.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := module.cy #生成的模块名 LOCAL_SRC_FILES := module.cy.cpp #源文件名 LOCAL_LDLIBS += -L$(LOCAL_PATH) -llog -lsubstrate -lsubstrate-dvm include $(BUILD_SHARED_LIBRARY)
5、终端进入jni目录,执行ndk-build APP_ABI="armeabi";
6、修改local.properties,指定sdk目录,如下
sdk.dir=D\:\\sdk
ndk.dir=D\:\\android-ndk-r13b
7、修改gradle.properties文件,增加内容如下
android.useDeprecatedNdk=true
8、修改build.gradle文件,增加在defaultConfig中增加ndk选项,同级增加sourceSet,如下
apply plugin: 'com.android.application' android { compileSdkVersion 25 buildToolsVersion "25.0.2" defaultConfig { applicationId "com.example.cydianativehook" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" ndk{ moduleName "module.cy" ldLibs "substrate" ldLibs "substrate-dvm" ldLibs "log" } } sourceSets{ main{ jni.srcDirs = [] jniLibs.srcDirs=['src/main/libs'] } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.3.0' testCompile 'junit:junit:4.12' }
9、编译成apk,安装即可.