123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- import {DUMP_FILE_PATH, soName} from "./dumpconfig";
- import {il2cppApi} from "./il2cpp/il2cppApi";
- import {log} from "./logger";
- let classAllCount = 0;
- let file = new File(DUMP_FILE_PATH, "wb");
- let il2cpp_got = false;
- let once =false;
- export var dumper = {
- waitInject: function () {
- log("waitInject");
- let open = Module.findExportByName(null, "open");
- //fopen替换
- log("等待Il2cpp:" + open);
- if (open != null) {
- Interceptor.attach(open, {
- onEnter: function (args) {
- let path = args[0].readCString();
- // log("path:" + path);
- if (path.indexOf(soName) !== -1) {
- this.hook = true;
- }
- },
- onLeave: function (retval) {
- // log("this.hook:" + this.hook);
- if (this.hook) {
- il2cpp_got = true;
- // Interceptor.detachAll();
- dumper.start();
- }
- }
- })
- }
- },
- start: function () {
- let module = Process.findModuleByName(soName);
- log("module:"+module);
- if (module == null) {
- if (il2cpp_got) {
- setTimeout(function () {
- //执行
- dumper.start();
- }, 5000);
- return;
- }
- this.waitInject();
- return
- }
- //延迟一下
- log("module "+module.path +" addr "+module.base);
- setTimeout(function (){
- if (once){
- return
- }
- once=true;
- module = Process.findModuleByName(soName);
- let baseAddress = module.base;
- log("base address:" + baseAddress);
- let domain = il2cppApi.il2cpp_domain_get();
- let size_t = Memory.alloc(Process.pointerSize);
- log("domain:" + domain + " baseAddress:" + baseAddress);
- //可能还没加载
- let assemblies = il2cppApi.il2cpp_domain_get_assemblies(domain, size_t);
- let assemblies_count = size_t.readInt();
- log("assemblies_count:" + assemblies_count + " pointerSize:" + Process.pointerSize
- + " assemblies:" + assemblies);
- if (assemblies_count===0){
- setTimeout(function (){
- this.start();
- },2000);
- return;
- }
- let il2CppImageArray = new Array();
- for (let i = 0; i < assemblies_count; i++) {
- let assembly = assemblies.add(Process.pointerSize * i).readPointer();
- let Il2CppImage = il2cppApi.il2cpp_assembly_get_image(assembly);
- let typeStart = Il2CppImage.typeStart();
- log("typeStart:" + typeStart + " name:" + Il2CppImage.nameNoExt()+" typeCount:"+Il2CppImage.typeCount());
- dumper.out(" // Image :" + i + " " + Il2CppImage.nameNoExt() + " - " + Il2CppImage.typeStart() + "\n")
- il2CppImageArray.push(Il2CppImage);
- }
- for (let i = 0; i < il2CppImageArray.length; i++) {
- log("process: " + (i + 1) + "/" + assemblies_count);
- let Il2CppImage = il2CppImageArray[i];
- let nameNoExt = Il2CppImage.nameNoExt();
- let start = Il2CppImage.typeStart();
- let class_count = Il2CppImage.typeCount();
- // log("name:"+nameNoExt +" start:"+start +" count:"+class_count)
- // if (nameNoExt === "Assembly-CSharp") {
- // // dll
- // this.out("\n//assembly Image -->:" + nameNoExt + " startIndex:" + start + " typeCount:" + class_count);
- dumper.findAllClass(Il2CppImage);
- // }
- }
- log("dump end")
- log("classAllCount:" + classAllCount);
- // log("nativeFunNotExistMap:" + il2cppApi.nativeFunNotExistMap.size);
- if (il2cppApi.nativeFunNotExistMap.size > 0) {
- log("some NativeFun is un exist ,parser will be not accurate :");
- il2cppApi.nativeFunNotExistMap.forEach(function (value, key) {
- log(key + "");
- })
- }
- log("module "+module.path +" addr "+module.base);
- },20000);
- },
- findAllClass: function (il2cppImage) {
- let class_count = il2cppImage.typeCount();
- classAllCount = classAllCount + class_count;
- log("findAllClass "+il2cppImage.name()+" class_count:" + class_count)
- for (let i = 0; i < class_count; i++) {
- log("class process:"+i +"/"+class_count)
- let il2CppClass = il2cppImage.getClass(i);
- let il2CppType = il2CppClass.getType();
- let declaringType = il2CppClass.getDeclaringType();
- if (!declaringType.isNull()) {
- // log("declaringType:" + declaringType.name() + " class:" + il2CppClass.name());
- }
- this.dumpType(il2CppType);
- }
- },
- dumpType: function (il2CppType) {
- let klass = il2cppApi.il2cpp_class_from_type(il2CppType);
- let il2CppImage = il2cppApi.il2cpp_class_get_image(klass);
- this.out("\n//Namespace:" + klass.namespaze() + " Image->" + il2CppImage.name() + "\n")
- let flags = klass.flags();
- let Serializable = flags & tabledefs.TYPE_ATTRIBUTE_SERIALIZABLE;
- if (Serializable) {
- this.out('[Serializable]\n')
- }
- let visibility = flags & tabledefs.TYPE_ATTRIBUTE_VISIBILITY_MASK;
- switch (visibility) {
- case tabledefs.TYPE_ATTRIBUTE_PUBLIC:
- case tabledefs.TYPE_ATTRIBUTE_NESTED_PUBLIC:
- this.out("public ")
- break;
- case tabledefs.TYPE_ATTRIBUTE_NOT_PUBLIC:
- case tabledefs.TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
- case tabledefs.TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
- this.out("internal ")
- break;
- case tabledefs.TYPE_ATTRIBUTE_NESTED_PRIVATE:
- this.out("private ")
- break;
- case tabledefs.TYPE_ATTRIBUTE_NESTED_FAMILY:
- this.out("protected ")
- break;
- case tabledefs.TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
- this.out("protected internal ")
- break;
- }
- let isValuetype = klass.valueType();
- let IsEnum = klass.enumType();
- if (flags & tabledefs.TYPE_ATTRIBUTE_ABSTRACT && flags & tabledefs.TYPE_ATTRIBUTE_SEALED) {
- this.out("static ")
- } else if (!(flags & tabledefs.TYPE_ATTRIBUTE_INTERFACE) && flags & tabledefs.TYPE_ATTRIBUTE_ABSTRACT) {
- this.out("abstract ")
- } else if (!isValuetype && !IsEnum && flags & tabledefs.TYPE_ATTRIBUTE_SEALED) {
- this.out("sealed ")
- }
- if (flags & tabledefs.TYPE_ATTRIBUTE_INTERFACE) {
- this.out("interface ")
- } else if (IsEnum) {
- this.out("enum ")
- } else if (isValuetype) {
- this.out("struct ");
- } else {
- this.out("class ");
- }
- let name = klass.name();
- //获取泛型
- if (name.indexOf("`") !== -1) {
- let split = name.split("`");
- name = split[0];
- name = name + klass.getGenericName();
- }
- this.out(name + " ");
- let klass_parent = klass.parent();
- //父类
- let hasParent = false;
- if (!isValuetype && !IsEnum && !klass_parent.isNull()) {
- let parent_cls_type = klass_parent.getType();
- let typeEnum = parent_cls_type.getTypeEnum();
- if (typeEnum === Il2CppTypeEnum.IL2CPP_TYPE_OBJECT) {
- //not out
- } else {
- hasParent = true;
- this.out(": " + klass_parent.name());
- }
- }
- //实现接口类
- let iter = Memory.alloc(Process.pointerSize);
- let interfaces;
- while (!(interfaces = klass.getInterfaces(iter)).isNull()) {
- let interfaces_name = interfaces.name();
- if (interfaces_name.indexOf("`") !== -1) {
- let split = interfaces_name.split("`");
- interfaces_name = split[0];
- interfaces_name = interfaces_name + interfaces.getGenericName();
- }
- if (!hasParent) {
- this.out(": " + interfaces_name)
- hasParent = true;
- } else {
- this.out(", " + interfaces_name);
- }
- }
- this.out("\n{\n")
- this.dumpFiled(klass);
- this.dumpPropertyInfo(klass);
- this.dumpMethod(klass);
- this.out("\n}");
- },
- dumpMethod: function (klass) {
- let iter = Memory.alloc(Process.pointerSize);
- let methodInfo;
- let isFirst = true;
- let baseAddr = Module.findBaseAddress(soName);
- while (!(methodInfo = klass.getMethods(iter)).isNull()) {
- if (isFirst) {
- this.out("\n\t//methods\n");
- isFirst = false;
- }
- let methodPointer = methodInfo.getMethodPointer();
- let generic = methodInfo.is_generic();
- let inflated = methodInfo.is_inflated();
- // log("generic:"+generic +" inflated:"+inflated +"name:"+methodInfo.name());
- if (!methodPointer.isNull()) {
- let number = methodPointer - baseAddr;
- if (number===0x4CC8B94){
- let nativePointer = klass.add(16).readPointer();
- logHHex(nativePointer);
- log("class :"+klass.name()+ "length:"+klass.name().length);
- }
- this.out("\t// RVA: 0x" + number.toString(16).toUpperCase());
- this.out(" VA: 0x");
- this.out(methodPointer.toString(16).toUpperCase());
- } else {
- this.out("\t// RVA: 0x VA: 0x0");
- }
- //非必须
- // log("slot:" + methodInfo.getSlot());
- // if (methodInfo.getSlot() !== 65535) {
- // this.out(" Slot: " + methodInfo.getSlot());
- // }
- this.out("\n\t");
- let methodModifier = utils.get_method_modifier(methodInfo.getFlags());
- this.out(methodModifier);
- let returnType = methodInfo.getReturnType();
- let return_cls = il2cppApi.il2cpp_class_from_type(returnType);
- this.out(return_cls.name() + " " + methodInfo.name() + "(");
- let paramCount = methodInfo.getParamCount();
- // log("paramCount:" + paramCount);
- if (paramCount > 0) {
- for (let i = 0; i < paramCount; i++) {
- let paramType = methodInfo.getParam(i);
- let paramCls = il2cppApi.il2cpp_class_from_type(paramType);
- let name = paramCls.name();
- //获取泛型
- if (name.indexOf("`") !== -1) {
- let split = name.split("`");
- name = split[0];
- name = name + paramCls.getGenericName();
- }
- this.out(name + " " + methodInfo.getParamName(i));
- if (i + 1 !== paramCount) {
- this.out(", ");
- } else {
- this.out(") { }\n");
- }
- }
- } else {
- this.out("){ }\n");
- }
- }
- },
- dumpPropertyInfo: function (klass) {
- let iter = Memory.alloc(Process.pointerSize);
- let propertyInfo;
- let isFirst = true;
- while (!(propertyInfo = klass.getProperties(iter)).isNull()) {
- if (isFirst) {
- this.out("\n\t// Properties\n");
- isFirst = false;
- }
- this.out("\t");
- //获取getSet
- // log(" dumpPropertyInfo get:" + propertyInfo.getMethod().isNull());
- let pro_class;
- let method = propertyInfo.getMethod();
- let setMethod = propertyInfo.setMethod();
- if (method.isNull() && setMethod.isNull()) {
- continue;
- }
- if (!method.isNull()) {
- let methodModifier = utils.get_method_modifier(method.getFlags());
- // let methodPointer = method.getMethodPointer()
- // log("methodModifier:" + methodModifier + " methodPointer:" + methodPointer);
- this.out(methodModifier);
- pro_class = il2cppApi.il2cpp_class_from_type(method.getReturnType());
- } else if (!setMethod.isNull()) {
- let setModifier = utils.get_method_modifier(setMethod.getFlags());
- this.out(setModifier);
- pro_class = il2cppApi.il2cpp_class_from_type(setMethod.getReturnType());
- }
- // log("pro_class:"+pro_class +"propertyInfo:"+propertyInfo.getName() +" method:"+method +" setMethod:"+setMethod)
- this.out(pro_class.name() + " " + propertyInfo.getName() + " { ");
- if (!method.isNull()) {
- this.out("get; ");
- }
- if (!setMethod.isNull()) {
- this.out("set; ");
- }
- this.out("}\n");
- }
- },
- dumpFiled: function (klass) {
- // log("dumpFiled class :" + klass.name())
- let filedCount = klass.filedCount();
- // log("fieldCount:" + filedCount);
- if (filedCount > 0) {
- let iter = Memory.alloc(Process.pointerSize);
- let filedInfo;
- this.out("\t//Fileds\n");
- while (!(filedInfo = klass.getFieldsInfo(iter)).isNull()) {
- let flags = filedInfo.getFlags();
- this.out("\t")
- let access = flags & tabledefs.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
- switch (access) {
- case tabledefs.FIELD_ATTRIBUTE_PRIVATE:
- this.out("private ")
- break;
- case tabledefs.FIELD_ATTRIBUTE_PUBLIC:
- this.out("public ")
- break;
- case tabledefs.FIELD_ATTRIBUTE_FAMILY:
- this.out("protected ")
- break;
- case tabledefs.FIELD_ATTRIBUTE_ASSEMBLY:
- case tabledefs.FIELD_ATTRIBUTE_FAM_AND_ASSEM:
- this.out("internal ")
- break;
- case tabledefs.FIELD_ATTRIBUTE_FAM_OR_ASSEM:
- this.out("protected internal ")
- break;
- }
- if (flags & tabledefs.FIELD_ATTRIBUTE_LITERAL) {
- this.out("const ")
- } else {
- if (flags & tabledefs.FIELD_ATTRIBUTE_STATIC) {
- this.out("static ")
- }
- if (flags & tabledefs.FIELD_ATTRIBUTE_INIT_ONLY) {
- this.out("readonly ")
- }
- }
- let fieldClass = filedInfo.getFiledClass();
- let name = fieldClass.name(); //参数名
- let offset = filedInfo.getOffset();//偏移
- // //如果是泛型变量则进行补充
- if (name.indexOf("`") !== -1) { //`1 `2 `3 说明是泛型类型 解析泛型变量
- let genericName = fieldClass.getGenericName();
- let split = name.split("`");
- name = split[0];
- name = name + genericName;
- }
- this.out(name + " " + filedInfo.getFiledName());
- //获取常量的初始值
- // let filed_info_cpp_type = filedInfo.getType(); //获取变量参数类型
- // log("filed_info_cpp_type:" + filed_info_cpp_type.getTypeEnum() + name + " " + filedInfo.getFiledName());
- if (flags & tabledefs.FIELD_ATTRIBUTE_LITERAL) {
- // let staticValue = filedInfo.getStaticValue();
- // if (staticValue !== null) {
- // this.out(" = " + staticValue + ";\n");
- // }
- this.out(";\n");
- } else {
- this.out(" ;// 0x" + offset.toString(16).toUpperCase() + "\n");
- }
- }
- }
- },
- out: function (string) {
- file.write(string);
- file.flush();
- }
- }
|