本帖最后由 从0开始的小小怪 于 2020-9-10 20:06 编辑
最近玩了一个同人手游叫火影战记,最后的一个版本是1.22版,1.22版以前的版本中修改版很多,但因为之前的版本买不了装备所以打算自己动手看看。打开安装包可以发现火影战记中的英雄属性都是明文存放的xml文件,但是修改过后点击开始游戏会闪退。起初以为是安装包签名进行校验了,将安装包重新签名而不修改任何数据则不会出现闪退的情况。而且在游戏的资源目录下可以看到有一个md5的xml文件,初步判断应该是存在对属性资源的校验。
该游戏是用cocos2d制作的,游戏的逻辑都在native层,用ida反编译so文件搜索md5可以看到有几个相关的函数,稍微甄别后估计主要的逻辑在checkMD5函数当中。
可以看到在该函数中存在两次字符串的比较,目测第一次应该是文件名称,第二次则是md5值的比较。在这里因此图方便就不对算法进行分析了,考虑直接hook在libc.so里面的strcmp函数,把正确的md5值打印出来,之后再替换md5值从而过游戏的检测。
随意修改一个英雄的属性后,使用frida编写脚本进行hook,在参数传递的地方注意不能读到不可读的内存区域,否则容易报错。
import frida, sys, os, io
package_id = 'net.zakume.game'
dev = frida.get_usb_device(timeout=1)
process = dev.attach(package_id)
src = '''
function IsNumOrAlphabet(c){
if(c >= '0' || c <= '9')return true;
else if(c >= 'a' || c <= 'z')return true;
return false;
}
var addr = Module.findExportByName(
"libc.so",
"strcmp"
);
Interceptor.attach(addr, {
onEnter: function(args) {
var flag = false;
var str1 = Memory.readCString(ptr(args[0]),3);
var str2 = Memory.readCString(ptr(args[1]),3);
if(IsNumOrAlphabet(str1[0])){
str1 = Memory.readCString(ptr(args[0]),32);
flag = true;
}
if(IsNumOrAlphabet(str2[0])){
str2 = Memory.readCString(ptr(args[1]),32);
flag = true;
}
if(flag){
var obj = {};
obj.str1 = str1;
obj.str2 = str2;
send(obj);
}
}
} )
'''
script = process.create_script(src)def on_message(message, data):
str1 = message['payload']['str1']
str2 = message['payload']['str2']
with open('str.txt','a',encoding = 'utf-8') as f:
if str1.isalnum() and str2.isalnum():
f.write(str1 + ' ' + str2 + '\n')
script.on('message', on_message)
script.load()
sys.stdin.read()
运行脚本之后成功得到了一些字符串,直接拉到最底下可以发现这里存在着两个不匹配的字符串,其中一个是原来文件的md5的值,另一个则是修改过后的文件的md5值。到这里md5的检测已经成功通过了。
将md5的值进行替换后重新进入游戏发现已经不再闪退,但是选好人物之后游戏的资源却加载不出来了
估计游戏应该还存在另外的检测,由于得准备考试,时间的原因研究到这里我便停止了
感兴趣的可以接着试试之后的检测在哪。
|