Cydia Substrate是一个代码修改平台,它可以修改任何主进程的代码,不管是用Java还是C/C++(native代码)编写的。但hook三方库总是失败,原因不明。暂只支持到Android4.4

Xposed只支持HOOK app_process中的java函数,因此Cydia Substrate是一款强大而实用的HOOK工具。

Substrate框架的使用:

Java层hook:

1、首先就是在Android设备中安装Cydia Substrate框架的本地服务应用substrate.apk

2、创建一个空的Android工程。由于创建的工程将以插件的形式被加载,所以不需要activity。拷贝cydia sdk包中的substrate-api.jar到libs目录,右键点击,“add as library” ,app模块下的 build.gradle文件会添加:

dependencies{
    ...
    implementation files('libs/substrate-api.jar')

}

3、修改AndroidManiFest.xml,增加cydia相关内容

<permission
        android:name="cydia.permission.SUBSTRATE"
        android:label="modify code from other packages"
        android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS"
        android:protectionLevel="dangerous" />

<uses-permission android:name="cydia.permission.SUBSTRATE"/>

<application
        .....>
    <meta-data android:name="com.saurik.substrate.main"
        android:value=".Main"/><!--自己写的hook类名-->
</application>

4、编写hook类

public class Main {
    static void initialize(){//在模块安装后, Cydia会自动调用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);
                        }
                    });
                }
            }
        });
    }
}

So层hook:

1、新建工程,使用空Activity即可

2、新建jni目录,把cydia sdk中的substrate.h、libsubstrate.so和libsubstrate-dvm.so拷贝到jni目录下;前者是c函数hook依赖库,后者是dvm函数hook依赖库.

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 {//模块安装后, Cydia会自动调用这里的代码,你可以在这里进行hook,也可以以后手动hook
    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)

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,安装即可.

另一篇博客:http://www.colordancer.net/blog/?p=1914

results matching ""

    No results matching ""