Baby unity3D
IL2CPP就是将Unity3D等转换为IL中间语言,IL中间语言再转换为CPP,CPP为静态语言,运行效率更高。
assets/bin/Data/Managed/etc/global-metadata.dat
发现文件被加密了,利用Frida脚本根据文件头"AF 1B B1 FA "进行dump但是没有找到
源码解密
用IDA搜索了一下global-metadata.dat查找LoadMetaData没有发现字符串
顺着源码Runtime.cpp找到可疑字符串且发现了metadata字符串定位到了关键加密函数进行解密
import struct
f = open('global-metadata.dat', 'rb')
a = ""
a = f.read()
key = [0xF83DA249, 0x15D12772, 0x40C50697, 0x984E2B6B, 0x14EC5FF8, 0xB2E24927,
0x3B8F77AE, 0x472474CD, 0x5B0CE524, 0xA17E1A31, 0x6C60852C, 0xD86AD267, 0x832612B7, 0x1CA03645, 0x5515ABC8,
0xC5FEFF52, 0xFFFFAC00, 0x0FE95CB6, 0x79CF43DD, 0xAA48A3FB, 0xE1D71788, 0x97663D3A, 0xF5CFFEA7, 0xEE617632,
0x4B11A7EE, 0x040EF0B5, 0x0606FC00, 0xC1530FAE, 0x7A827441, 0xFCE91D44, 0x8C4CC1B1, 0x7294C28D, 0x8D976162,
0x8315435A, 0x3917A408, 0xAF7F1327, 0xD4BFAED7, 0x80D0ABFC, 0x63923DC3, 0xB0E6B35A, 0xB815088F, 0x9BACF123,
0xE32411C3, 0xA026100B, 0xBCF2FF58, 0x641C5CFC, 0xC4A2D7DC, 0x99E05DCA, 0x9DC699F7, 0xB76A8621, 0x8E40E03C,
0x28F3C2D4, 0x40F91223, 0x67A952E0, 0x505F3621, 0xBAF13D33, 0xA75B61CC, 0xAB6AEF54, 0xC4DFB60D, 0xD29D873A,
0x57A77146, 0x393F86B8, 0x2A734A54, 0x31A56AF6, 0x0C5D9160, 0xAF83A19A, 0x7FC9B41F, 0xD079EF47, 0xE3295281,
0x5602E3E5, 0xAB915E69, 0x225A1992, 0xA387F6B2, 0x7E981613, 0xFC6CF59A, 0xD34A7378, 0xB608B7D6, 0xA9EB93D9,
0x26DDB218, 0x65F33F5F, 0xF9314442, 0x5D5C0599, 0xEA72E774, 0x1605A502, 0xEC6CBC9F, 0x7F8A1BD1, 0x4DD8CF07,
0x2E6D79E0, 0x6990418F, 0xCF77BAD9, 0xD4FE0147, 0xFEF4A3E8, 0x85C45BDE, 0xB58F8E67, 0xA63EB8D7, 0xC69BD19B,
0xDA442DCA, 0x3C0C1743, 0xE6F39D49, 0x33568804, 0x85EB6320, 0xDA223445, 0x36C4A941, 0xA9185589, 0x71B22D67,
0xF59A2647, 0x3C8B583E, 0xD7717DED, 0xDF05699C, 0x4378367D, 0x1C459339, 0x85133B7F, 0x49800CE2, 0x3666CA0D,
0xAF7AB504, 0x4FF5B8F1, 0xC23772E3, 0x3544F31E, 0x0F673A57, 0xF40600E1, 0x7E967417, 0x15A26203, 0x5F2E34CE,
0x70C7921A, 0xD1C190DF, 0x5BB5DA6B, 0x60979C75, 0x4EA758A4, 0x078FE359, 0x1664639C, 0xAE14E73B, 0x2070FF03]
with open('decrypt', 'wb') as fp:
n = 0
while n < len(a):
num = struct.unpack("<I", a[n:n + 4])[0]
num = num ^ key[(n + n // 0x84) % 0x84]
d = struct.pack('I', num)
fp.write(d)
n = n + 4
frida hook 解密
程序在运行时,解密完成利用Frida进行Hook
frida -U -l 2.js com.nu1l.crack
function frida_Memory(pattern)
{
Java.perform(function ()
{
console.log("头部标识:" + pattern);
var addrArray = Process.enumerateRanges("r--");
for (var i = 0; i < addrArray.length; i++)
{
var addr = addrArray[i];
Memory.scan(addr.base, addr.size, pattern,
{
onMatch: function (address, size)
{
console.log('搜索到 ' + pattern + " 地址是:" + address.toString());
console.log(hexdump(address,
{
offset: 0,
length: 64,
header: true,
ansi: true
}
));
//0x108,0x10C如果不行,换0x100,0x104
var DefinitionsOffset = parseInt(address, 16) + 0x108;
var DefinitionsOffset_size = Memory.readInt(ptr(DefinitionsOffset));
var DefinitionsCount = parseInt(address, 16) + 0x10C;
var DefinitionsCount_size = Memory.readInt(ptr(DefinitionsCount));
//根据两个偏移得出global-metadata大小
var global_metadata_size = DefinitionsOffset_size + DefinitionsCount_size
console.log("大小:", global_metadata_size);
var file = new File("/data/data/" + get_self_process_name() + "/global-metadata.dat", "wb");
file.write(Memory.readByteArray(address, global_metadata_size));
file.flush();
file.close();
console.log('导出完毕...');
},
onComplete: function ()
{
//console.log("搜索完毕")
}
}
);
}
}
);
}
setImmediate(frida_Memory("AF 1B B1 FA")); //global-metadata.dat头部特征
解密后的用IDA.py去导入函数名称和字符串。。最终AES解密得到flag
可以通过frida来hook参数,记录一下
Java.perform(function(){
var soAdrr = Module.findBaseAddress("libil2cpp.so");
var ptrAESEncrypt = soAdrr.add(0x518b54);
Interceptor.attach(ptrAESEncrypt,{
onEnter: function(args){
console.log(("enter ptrAESEncrypt args[0]-> " + args[0]));
console.log(("enter ptrAESEncrypt args[1] text->\n" + hexdump(args[1])));
console.log(("enter ptrAESEncrypt args[2]-> password\n" + hexdump(args[2],{
offset: 12,
length: 12+16 * 2
})));
console.log(("enter ptrAESEncrypt args[3]-> iv\n" + hexdump(args[3],{
offset: 12,
length: 12+16 * 2
})));
},
onLeave: function(args){
}
})
})
riru-il2cppdumper解密
原理
阅读了一下源码,发现其对dlopen函数进行了hook,判断根据调用的dlopen参数是否为il2cpp.so获取其句柄,根据句柄获得版本,使用反射进行dump
gradlew :module:assembleRelease编译riru-il2cppdumper
注意需要设置ndk版本为21.4版本否则会出错Execution failed for task ‘:module:externalNativeBuildRelease’
其次Riru版本要设置为v21.2从网上下了一个