如果只有一个包可以得到那些东西(Unity游戏【废弃】)

【废弃】

可以运行 可以hook 可以得到哪些东西

目前这个并没有啥稀奇的,基本没啥用。

il2cpp相关的

起始地址和大小

const m = Process.getModuleByName("libil2cpp.so");
console.log("name =", m.name);
console.log("base =", m.base);
console.log("size =", m.size);
console.log("path =", m.path);

========
name = libil2cpp.so
base = 0x8000000
size = 42426368
path = /data/app/com.oakever.jigsawcard-1/lib/arm/libil2cpp.so

2.获取到il2cpp的

const il2cpp = "libil2cpp.so";

[//]: # (打印的是:libil2cpp.so 这个动态库的“导出符号(exported symbols)列表”。)
const exps = Module.enumerateExportsSync(il2cpp)
  .filter(e => e.type === "function" && e.name.startsWith("il2cpp_"))
  .map(e => e.name);

console.log("il2cpp exports count =", exps.length);

// 只看你关心的几个关键词
["class_get_methods", "method_get_", "class_get_name", "class_get_namespace", "method_get_name"].forEach(k => {
  const hit = exps.filter(n => n.includes(k));
  console.log("\n== contains:", k, "==");
  hit.slice(0, 50).forEach(n => console.log(" ", n));
});

运行结果:

il2cpp exports count = 240 == contains: class_get_methods == il2cpp_class_get_methods == contains: method_get_ == il2cpp_method_get_flags il2cpp_method_get_declaring_type il2cpp_method_get_object il2cpp_method_get_from_reflection il2cpp_method_get_param il2cpp_method_get_class il2cpp_method_get_return_type il2cpp_method_get_param_count il2cpp_method_get_name il2cpp_method_get_token il2cpp_method_get_param_name == contains: class_get_name == il2cpp_class_get_name il2cpp_class_get_namespace == contains: class_get_namespace == il2cpp_class_get_namespace == contains: method_get_name == il2cpp_method_get_name

3.查看调用的方法,来推断有哪些类名和方法

这个计没有用,不能提供什么东西。

'use strict';

(function () {

    console.log("🚀 il2cpp Invoke resolver starting...");

    const il2cpp = Process.findModuleByName("libil2cpp.so");
    if (!il2cpp) {
        console.log("❌ libil2cpp.so not found");
        throw new Error("abort");
    }

    console.log("✅ libil2cpp.so @", il2cpp.base, "size =", il2cpp.size);

    function mustExport(name) {
        const p = Module.findExportByName("libil2cpp.so", name);
        if (!p) {
            console.log("❌ missing export:", name);
            throw new Error("abort");
        }
        return p;
    }

    const f_getMethodName = new NativeFunction(
        mustExport("il2cpp_method_get_name"),
        'pointer',
        ['pointer']
    );

    const f_getMethodClass = new NativeFunction(
        mustExport("il2cpp_method_get_class"),
        'pointer',
        ['pointer']
    );

    const f_getClassName = new NativeFunction(
        mustExport("il2cpp_class_get_name"),
        'pointer',
        ['pointer']
    );

    const f_getClassNamespace = new NativeFunction(
        mustExport("il2cpp_class_get_namespace"),
        'pointer',
        ['pointer']
    );

    const invoke = Module.findExportByName("libil2cpp.so", "il2cpp_runtime_invoke");
    if (!invoke) {
        console.log("❌ il2cpp_runtime_invoke not found");
        throw new Error("abort");
    }

    console.log("✅ hook il2cpp_runtime_invoke @", invoke);

    const seen = {};

    Interceptor.attach(invoke, {
        onEnter(args) {
            try {
                const method = args[0];
                const obj = args[1];
                if (obj.isNull()) return;

                const key = method.toString();
                if (seen[key]) return;
                seen[key] = true;

                const namePtr = f_getMethodName(method);
                const klass = f_getMethodClass(method);
                const classNamePtr = f_getClassName(klass);
                const nsPtr = f_getClassNamespace(klass);

                const methodName = namePtr.readCString();
                const className = classNamePtr.readCString();
                const ns = nsPtr.readCString();

                console.log(
                    `🎯 FOUND → ${ns}.${className}::${methodName}`,
                    "method =", method
                );

            } catch (e) {
                // 静默,防止影响运行
            }
        }
    });

})();

4.通过他们来获取整个类的信息

通过上面推断来的信息,我们推断出整个类

//🎯 FOUND → .UI_LoadingBar::.ctor method = 0x7b22aab8

'use strict';

const IL2CPP = "libil2cpp.so";
const addrX = "0x7b22aab8";
const TARGET_METHODINFO = ptr(addrX);

// ================= helpers =================

function cstr(p) { return p.isNull() ? "" : p.readCString(); }

function normalizeArm32Thumb(p) {
  if (Process.arch === "arm" && !p.isNull() && p.and(1).toInt32() === 1) {
    return p.and(ptr("0xfffffffe"));
  }
  return p;
}

function isExecutableCodePtr(p) {
  if (p.isNull()) return false;
  const r = Process.findRangeByAddress(p);
  if (!r) return false;
  return r.protection.indexOf("x") !== -1;
}

function exp(name) {
  const p = Module.findExportByName(IL2CPP, name);
  if (!p) throw new Error("missing export: " + name);
  return p;
}

// ================= module =================

const il2cppMod = Process.getModuleByName(IL2CPP);
const IL2CPP_BASE = il2cppMod.base;

console.log("[*] libil2cpp.so base =", IL2CPP_BASE);
console.log("[*] libil2cpp.so path =", il2cppMod.path);

// ================= il2cpp API =================

const il2cpp_class_get_methods =
  new NativeFunction(exp("il2cpp_class_get_methods"), "pointer", ["pointer", "pointer"]);

const il2cpp_class_get_name =
  new NativeFunction(exp("il2cpp_class_get_name"), "pointer", ["pointer"]);

const il2cpp_class_get_namespace =
  new NativeFunction(exp("il2cpp_class_get_namespace"), "pointer", ["pointer"]);

const il2cpp_method_get_name =
  new NativeFunction(exp("il2cpp_method_get_name"), "pointer", ["pointer"]);

const il2cpp_method_get_class =
  new NativeFunction(exp("il2cpp_method_get_class"), "pointer", ["pointer"]);

const il2cpp_class_get_nested_types =
  new NativeFunction(exp("il2cpp_class_get_nested_types"), "pointer", ["pointer", "pointer"]);

// ================= MethodInfo impl resolver =================

function getMethodImplFromMethodInfo(methodInfo) {
  methodInfo = ptr(methodInfo);

  const candidates = [
    0x0, 0x4, 0x8, 0xC,
    0x10, 0x14, 0x18, 0x1C,
    0x20, 0x24, 0x28, 0x2C,
    0x30, 0x34, 0x38, 0x3C
  ];

  for (const off of candidates) {
    let p;
    try {
      p = methodInfo.add(off).readPointer();
    } catch (e) {
      continue;
    }
    const real = normalizeArm32Thumb(p);
    if (isExecutableCodePtr(real)) return real;
  }

  return NULL;
}

function toIl2cppOffset(codePtr) {
  const real = normalizeArm32Thumb(ptr(codePtr));
  return real.sub(IL2CPP_BASE);
}

// ================= nested dumper (recursive) =================

function dumpNestedRecursive(klass, depth) {

  const iter = Memory.alloc(Process.pointerSize);
  iter.writePointer(NULL);

  let nested;

  while (!(nested = il2cpp_class_get_nested_types(klass, iter)).isNull()) {

    const ns = cstr(il2cpp_class_get_namespace(nested));
    const name = cstr(il2cpp_class_get_name(nested));

    const indent = "  ".repeat(depth);

    console.log(`\n${indent}--- Nested: ${ns}.${name} ---`);

    // dump its methods
    const it2 = Memory.alloc(Process.pointerSize);
    it2.writePointer(NULL);

    let m;
    while (!(m = il2cpp_class_get_methods(nested, it2)).isNull()) {

      const methodName = cstr(il2cpp_method_get_name(m));
      const impl = getMethodImplFromMethodInfo(m);

      if (!impl.isNull()) {
        const off = toIl2cppOffset(impl);
        console.log(`${indent}   ${methodName} -> ${impl} (offset ${off})`);
      } else {
        console.log(`${indent}   ${methodName} -> NULL`);
      }
    }

    // 递归继续查嵌套
    dumpNestedRecursive(nested, depth + 1);
  }
}

// ================= main class dump =================

function dumpClassMethodsFromMethodInfo(methodInfo) {

  const mi = ptr(methodInfo);
  const klass = il2cpp_method_get_class(mi);

  const ns = cstr(il2cpp_class_get_namespace(klass));
  const cn = cstr(il2cpp_class_get_name(klass));

  console.log("\n==============================");
  console.log(`Class: ${ns}.${cn}`);
  console.log("MethodInfo* =", mi);
  console.log("klass       =", klass);
  console.log("==============================\n");

  const iter = Memory.alloc(Process.pointerSize);
  iter.writePointer(NULL);

  let idx = 0;
  let m;

  while (!(m = il2cpp_class_get_methods(klass, iter)).isNull()) {

    const name = cstr(il2cpp_method_get_name(m));
    const impl = getMethodImplFromMethodInfo(m);

    idx++;

    if (!impl.isNull()) {
      const off = toIl2cppOffset(impl);
      console.log(`${String(idx).padStart(3)}  ${name}  ->  ${impl} (offset ${off})`);
    } else {
      console.log(`${String(idx).padStart(3)}  ${name}  ->  NULL`);
    }
  }

  // ⭐ 自动打印 nested classes(包括协程类)
  dumpNestedRecursive(klass, 1);

  console.log("\n[*] Tip: offset 可直接在 IDA 中跳转(imagebase=0)");

  return { klass, ns, cn };
}

// ================= run =================

dumpClassMethodsFromMethodInfo(TARGET_METHODINFO);

console.log("[+] done.");

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容