[原创]Unity3D手游破盾之旅
工具与环境:
手机: 小米4
系统版本: 4.4.2
Hook 框架: Cydia substrate 和 iqyi的xHook
某易游戏出了一款篮球游戏,试玩了一下,内容就不过多的评价了,出于职业习惯,对它的保护系统倒是很感兴趣。
先行基础是必须会用Cydia substrate这个hook框架,如果不会用请先去论坛搜索教程。
先静态分析一下libmono.so,各种关键函数都搜不到,应该是对so进行处理了,然而,在动态运行时,总要还原的嘛。
先定义MonoImage结构体,后续dump文件时有用。
struct _MonoImage {
int ref_count;
void *raw_data_handle;
char *raw_data;
int raw_data_len;
};
闲话少说,直接上神器Cydia substrate,使用Cydia substrate框架去hook dlopen函数和
hook libmono.so中的mono_image_open_from_data_with_name,启动代码如下:
MSConfig(MSFilterLibrary, "/system/lib/libdvm.so");
Void* (*old_dlopen)(const char *filename, int myflags);
void* new_dlopen( const char *filename, int myflags) {
if(!(strstr(filename, "/system/lib/")))
{
LOGE("[dlopen] The dlopen name : %s.\n", filename);
}
void *handle = NULL;
handle = orig_dlopen(filename, myflags);
if(strstr(filename, "libunity.so")) {
hookU3D();
}
return handle;
}
MSInitialize {
//获取dlopen地址
void *dlopen_addr = get_remote_addr(getpid(), "/system/bin/linker", (void *)dlopen);
//hook dlopen方法
MSHookFunction((void*)dlopen_addr, (void*)&new_dlopen, (void**)&orig_dlopen);
}
//hookU3D函数和替换函数如下:
_MonoImage *(* orig_my_open)(char *data, int32_t data_len, int need_copy, int *status, int refonly, char *name);
_MonoImage* new_ my_open(char *data, int32_t data_len, int need_copy, int *status, int refonly, char *name)
{
_MonoImage *ret = orig_my_open(data, data_len, need_copy, status, refonly, name);
if(strstr(name, "Assembly-CSharp")) {
if(strstr(name, "arp.dl"))
{
saveDllFile(ret->raw_data,data_len, getFilePath(".dll", "Assembly-CSharp").c_str());
}
else {
saveDllFile(ret->raw_data,data_len,getFilePath(".dll","Assembly-CSharp-firstpass").c_str());
}
}
return ret;
}
void hookU3D()
{
void *myhandle = dlopen("libmono.so", RTLD_NOW | RTLD_GLOBAL);
void*addr = dlsym(myhandle, "mono_image_open_from_data_with_name");
MSHookFunction(addr, (void *) new_my_open,(void **) &orig_my_open);
}
不出所料,游戏崩了,通过代码打印出函数所在地址的前8位:
void printOpcode(char *addr)
{
LOGD("Addr %p --> 8 : %02x %02x %02x %02x %02x %02x %02x %02x",addr,addr[0],addr[1],addr[2],addr[3],addr[4],addr[5],addr[6],addr[7]);
LOGD("Addr %p --> 16 : %02x %02x %02x %02x %02x %02x %02x %02x",addr,addr[8],addr[9],addr[10],addr[11],addr[12],addr[13],addr[14],addr[15]);
LOGD("Addr %p --> 24 : %02x %02x %02x %02x %02x %02x %02x %02x",addr,addr[16],addr[17],addr[18],addr[19],addr[20],addr[21],addr[22],addr[23]);
LOGD("Addr %p --> 32 : %02x %02x %02x %02x %02x %02x %02x %02x",addr,addr[24],addr[25],addr[26],addr[27],addr[28],addr[29],addr[30],addr[31]);
}
输出结果:
注意:上传附件及图片大小不得大于30M。
⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。
复制成功
