il2cpp的String跟普通的string不太一样,解析的时候需要通过il2cppStringChars转换为一个utf-16的字符串,因为frida支持读取utf-16格式的字符串,所以打印时也可以不需要再去转为utf-8。构造一个il2cppString时,需要il2cpp_string_new函数,这个方法需要一个utf-8的数据,所以最终的实现代码如下
const il2cppStringCharsAddress = Module.findExportByName("libil2cpp.so", 'il2cpp_string_chars')
console.warn("il2cppStringCharsAddress is: " + il2cppStringCharsAddress)
const il2cppStringChars = new NativeFunction(il2cppStringCharsAddress, 'pointer', ['pointer']);
const il2cpp_string_newAddress = Module.findExportByName("libil2cpp.so", 'il2cpp_string_new')
console.warn("il2cpp_string_newAddress is: " + il2cpp_string_newAddress)
const il2cpp_string_new = new NativeFunction(il2cpp_string_newAddress, 'pointer', ['pointer']);
var GetSignatureMD5Hash = libil2cpp_addr.add(0x123456);
console.warn("GetSignatureMD5Hash is: " + GetSignatureMD5Hash)
Interceptor.attach(GetSignatureMD5Hash, {
onEnter: function (args) {
console.warn("onEnter GetSignatureMD5Hash")
},
onLeave: function (retval) {
console.log("onLeave GetSignatureMD5Hash retval:", retval);
const result = il2cppStringChars(retval);
// 使用 Memory 模块进行 UTF-16 到 UTF-8 转换
const utf16 = Memory.readUtf16String(result);
console.log("UTF-16 String: " + utf16);
const utf8String = unescape(encodeURIComponent(utf16));
// 打印 UTF-8 字符串
console.log("UTF-8 String: " + utf8String);
// 修改1:这样也可以实现修改retval的值
// Memory.writeUtf16String(result,"99:99:99:99:99:99:99:99:99:99:99:99:99:99:99:99")
// 修改2:
const newValue = "99:99:99:99:99:99:99:99:99:99:99:99:99:99:99:99";
const cString = Memory.allocUtf8String(newValue);
const modify = il2cpp_string_new(cString);
retval.replace(modify)
}
})