主要介绍如何使用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 <dlfcn.h>
#include <android/log.h>
#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中添加权限:<uses-permission android:name=”cydia.permission.SUBSTRATE”/>
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