Cydia Substrate入门---hook native代码

主要介绍如何使用Cydia Substrate去hook native代码。本文是抄袭的,当作个人笔记。
1.建立project,选择No Activity;
2.在app-main下建立jni文件夹;
3.将cydia_substrate-r2下的substrate.h、libsubstrate.so和libsubstrate-dvm.so三个文件放入jni目录中,这里要注意根据架构的不同,选择x86或ARM目录下的libsubstrate.so和libsubstrate-dvm.so
4.同样在jni目录下建立test.cy.cpp(一定要记得带‘cy’)和Android.mk两个文件;
5.test.cy.cpp内容:

#include "substrate.h"
#include 
#include 
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "HookGetSpeed", __VA_ARGS__)
#define LIB "/data/app-lib/com.shandagames.bop-1/libShellClient.so"

MSConfig(MSFilterExecutable,"/system/bin/app_process")
//MSConfig(MSFilterLibrary, "libdvm.so");

int (* old_getSpeed)(void);
int  new_getSpeed(void * CCharacter){
    LOGD("getSpeed %d",(&CCharacter + 28));
    return 1;
}


int (* old_SpeedUp)(int);
int new_SpeedUp(int a2){
    LOGD("a2 : %d",a2);
    return old_SpeedUp(a2);
}

int (* old_SetScale)(int,float);
int new_SetScale(int result,float a2){
    LOGD("result : %d",result);
    LOGD("a2 : %d",a2);
    *(float *)(result + 1136) = a2;
    return result;
}


//通过so库的绝对路径和函数名,找到其函数的映射地址
void* lookup_symbol(char* libraryname,char* symbolname)
{
    //获取so库的句柄
    void *handle = dlopen(libraryname, RTLD_GLOBAL | RTLD_NOW);
    if (handle != NULL){
        LOGD("dlopen success");
        void * symbol = dlsym(handle, symbolname);
        if (symbol != NULL){

            LOGD("dlsym %s success",symbolname);
            return symbol;
        }else{
            LOGD("dl error: %s", dlerror());
            return NULL;
        }
    }else{
        LOGD("dlopen %s faile",libraryname);
        return NULL;
    }
}

MSInitialize
{
    //获取hook函数的地址,最好不要用下面MS提供的方法
    void * symbol = lookup_symbol(LIB,"_ZN16CGameSceneClient8SetScaleEf");
    if(symbol != NULL){
        LOGD("symbol address is 0x%08X",&symbol);
        //这里将旧函数的入口(参数一)指向hello(参数三),然后执行新函数(参数二)
        MSHookFunction(symbol, (void *)&new_SetScale, (void **)&old_SetScale);
        LOGD("MSHookFunction finish");
    }
}

使用官方提供的方法有时候不能获取到symbol。
6.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    := test.cy #生成的模块名
LOCAL_SRC_FILES := test.cy.cpp #源文件名
LOCAL_LDLIBS := -llog
LOCAL_LDLIBS += -L$(LOCAL_PATH) -lsubstrate-dvm -lsubstrate
include $(BUILD_SHARED_LIBRARY)

7.修改project下面的local.properties文件,末尾增加ndk路径
8.修改gradle.properties文件,末尾增加:

android.useDeprecatedNdk=true

9.修改app下的build.gradle文件
defaultConfig{}中增加ndk设置

ndk{
            moduleName "test.cy"
            ldLibs "substrate"
            ldLibs "substrate-dvm"
        }

因为要手动ndk-build,需要在android{}中增加jni和jniLibs路径说明:

sourceSets {
    main {
        jni.srcDirs = []
        jniLibs.srcDirs = ['src/main/libs']

}
}

jni.srcDirs = [] 表示禁止as自动ndk编译,采用手动ndk-build

jniLibs.srcDirs = [‘src/main/libs’] 表示经过ndk-build编译后的so路径

10.OK,接下来手动ndk-build吧,teminal下,进入到app/src/main/jni目录,因为是x86平台的编译,所以输入时需要带参数:
D:\MyCandy\app\src\main\jni>ndk-build APP_ABI=”x86″

11.模拟器安装好com.saurik.substrate_0.9.4010.apk,运行,并给予Root权限;
注意在AndroidManifest.xml中添加权限:

https://koz.io/android-substrate-c-hooking/
http://mybeibei.net/1051.html
http://www.cydiasubstrate.com/id/73e45fe5-4525-4de7-ac14-6016652cc1b8/
https://blog.csdn.net/jk38687587/article/details/51498062

你可能感兴趣的:(Cydia Substrate入门---hook native代码)