il2cpp自动寻址

经验分享,仅适用于小白!

今天尝试用自动更新来重写之前的菜单,发现了一些BUG,这里分享给大家避坑。

1.用新的UtilS.h和Struct.h替换到单目录app/src/main/jni/Includes/目录下

2.新的Utils.h删除了findlibray()和getAbsoluteAddress()函数,这将意味着菜单原始的寻址方式将失效。原因是自动更新函数和这个两个函数共存时会导致一些错误,使Hook函数替换指令时找不到正确函数地址,表现为功能概率有效,多数闪退。(“经观察两者共存时cd内存中的函数头几个字节不会被替换,hook功能失效”)

3.仅适用于适用于il2cpp游戏,支持32位和64位,可根据函数名和字段名自动查找函数地址和字段偏移,只需打包一次,日后游戏更新可继续使用,节省精力。

4.自动更新代码来自Github,已做修复,这里给出使用示例,和注意事项。

5.新Utils.h地址


#pragma once
#include <jni.h>
#include <unistd.h>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include "Logger.h"
#include "Struct.h"
#include <dlfcn.h>

typedef unsigned long DWORD;
static uintptr_t libBase;

bool libLoaded = false;



bool isLibraryLoaded(const char *libraryName) {
    //libLoaded = true;
    char line[512] = {0};
    FILE *fp = fopen(OBFUSCATE("/proc/self/maps"), OBFUSCATE("rt"));
    if (fp != NULL) {
        while (fgets(line, sizeof(line), fp)) {
            std::string a = line;
            if (strstr(line, libraryName)) {
                libLoaded = true;
                return true;
            }
        }
        fclose(fp);
    }
    return false;
}

uintptr_t string2Offset(const char *c) {
    int base = 16;
    // See if this function catches all possibilities.
    // If it doesn't, the function would have to be amended
    // whenever you add a combination of architecture and
    // compiler that is not yet addressed.
    static_assert(sizeof(uintptr_t) == sizeof(unsigned long)
                  || sizeof(uintptr_t) == sizeof(unsigned long long),
                  "Please add string to handle conversion for this architecture.");

    // Now choose the correct function ...
    if (sizeof(uintptr_t) == sizeof(unsigned long)) {
        return strtoul(c, nullptr, base);
    }

    // All other options exhausted, sizeof(uintptr_t) == sizeof(unsigned long long))
    return strtoull(c, nullptr, base);
}

namespace ToastLength {
    inline const int LENGTH_LONG = 1;
    inline const int LENGTH_SHORT = 0;
}










typedef Il2CppClass *(*class_from_name_t)(const Il2CppImage *assembly, const char *name_space,
                                          const char *name);

typedef MethodInfo *(*class_get_method_from_name_t)(Il2CppClass *klass, const char *name,
                                                    int paramcount);

typedef Il2CppDomain *(*domain_get_t)();

typedef const Il2CppAssembly **(*domain_get_assemblies_t)(const Il2CppDomain *domain, size_t *size);

typedef const Il2CppImage *(*assembly_get_image_t)(const Il2CppAssembly *assembly);

typedef const Il2CppAssembly *(*domain_assembly_open_t)(Il2CppDomain *domain, const char *name);

typedef FieldInfo *(*class_get_field_from_name_t)(Il2CppClass *klass, const char *name);


template<typename T>
class Field : FieldInfo {
    bool statik;

    bool CheckStatic() {
        if ((type->attrs & 0x10) == 0)
            return false;

        if ((type->attrs & 0x40) != 0)
            return false;

        if (thread_static = offset == -1)
            LOGI(OBFUSCATE("thread static fields is not supported!"));

        return true;
    }

    bool CheckStaticFieldInfo(FieldInfo *fieldInfo) {
        if ((fieldInfo->type->attrs & 0x10) == 0)
            return false;

        if ((fieldInfo->type->attrs & 0x40) != 0)
            return false;

        if (fieldInfo->offset == -1)
            LOGI(OBFUSCATE("thread static fields is not supported!"));

        return true;
    }

public:
    bool init;
    bool thread_static;
    void *clazz;

    Field(FieldInfo *thiz, void *clas = NULL) {
        if (!CheckStaticFieldInfo(thiz))
            clazz = clas;
        init = (thiz != NULL);
        if (init) {
            parent = thiz->parent;
            offset = thiz->offset;
            name = thiz->name;
            token = thiz->token;
            type = thiz->type;
            statik = CheckStatic();
        }
    }

    DWORD get_offset() {
        return offset;
    }

    T get() {
        if (!init || thread_static) return T();
        if (statik) {
            return *(T *) ((uint64_t) parent->static_fields + offset);
        }
        return *(T *) ((uint64_t) clazz + offset);
    }

    void set(T val) {
        if (!init || thread_static) return;
        if (statik) {
            *(T *) ((uint64_t) parent->static_fields + offset) = val;
            return;
        }
        *(T *) ((uint64_t) clazz + offset) = val;
    }

    operator T() {
        return get();
    }

    void operator=(T val) {
        set(val);
    }

    bool operator==(Field other) {
        if (!init) return false;
        return (type == other.type && parent == other.parent &&
                offset == other.offset && name == other.name && token == other.token);
    }

    T operator()() {
        return get();
    }
};

class LoadClass {
    void *get_il2cpp() {
        void *mod = 0;
        while (!mod) {
            mod = dlopen(OBFUSCATE("libil2cpp.so"), 4);
        }
        return mod;
    }

    Il2CppClass *GetClassFromName(const char *name_space, const char *type_name) {
        auto domain_get = (domain_get_t) dlsym(get_il2cpp(), OBFUSCATE("il2cpp_domain_get"));
        auto dom = domain_get();
        if (!dom) {
            return nullptr;
        }
        size_t assemb_count;
        auto domain_get_assemblies = (domain_get_assemblies_t) dlsym(get_il2cpp(), OBFUSCATE(
                "il2cpp_domain_get_assemblies"));
        const Il2CppAssembly **allAssemb = domain_get_assemblies(dom, &assemb_count);
        auto assembly_get_image = (assembly_get_image_t) dlsym(get_il2cpp(), OBFUSCATE(
                "il2cpp_assembly_get_image"));
        auto class_from_name = (class_from_name_t) dlsym(get_il2cpp(),
                                                         OBFUSCATE("il2cpp_class_from_name"));
        for (int i = 0; i < assemb_count; i++) {
            auto assemb = allAssemb[i];
            auto img = assembly_get_image(assemb);
            if (!img) {
                continue;
            }
            auto klass = class_from_name(img, name_space, type_name);
            if (klass) {
                namespaze_txt = name_space;
                clazz_txt = type_name;
                dllname_txt = img->name;
                dll = img;
                return klass;
            }
        }
        return nullptr;
    }

public:
    const Il2CppImage *dll;
    Il2CppClass *thisclass;
    const char *namespaze_txt;
    const char *clazz_txt;
    const char *dllname_txt;

    LoadClass(const char *namespaze, const char *clazz) {
        thisclass = nullptr;
        do {
            thisclass = GetClassFromName(namespaze, clazz);
        } while (!thisclass);
    }

    LoadClass(const char *namespaze, const char *clazz, const char *dllname) {
        auto domain_assembly_open = (domain_assembly_open_t) dlsym(get_il2cpp(), OBFUSCATE(
                "il2cpp_domain_assembly_open"));
        auto assembly_get_image = (assembly_get_image_t) dlsym(get_il2cpp(), OBFUSCATE(
                "il2cpp_assembly_get_image"));
        auto domain_get = (domain_get_t) dlsym(get_il2cpp(), OBFUSCATE("il2cpp_domain_get"));
        auto class_from_name = (class_from_name_t) dlsym(get_il2cpp(),
                                                         OBFUSCATE("il2cpp_class_from_name"));
        dll = assembly_get_image(domain_assembly_open(domain_get(), dllname));
        thisclass = nullptr;
        do {
            thisclass = class_from_name(dll, namespaze, clazz);
        } while (!thisclass);
    }

    FieldInfo *GetFieldInfoByName(const char *name) {
        auto class_get_field_from_name = (class_get_field_from_name_t) dlsym(get_il2cpp(),
                                                                             OBFUSCATE(
                                                                                     "il2cpp_class_get_field_from_name"));
        return class_get_field_from_name(thisclass, name);
    }

    template<typename T>
    Field<T> GetFieldByName(const char *name) {
        return Field<T>(GetFieldInfoByName(name), (void *) thisclass);
    }

    DWORD GetFieldOffset(const char *name) {
        return GetFieldInfoByName(name)->offset;
    }

    DWORD GetFieldOffset(FieldInfo *filed) {
        return filed->offset;
    }

    MethodInfo *GetMethodInfoByName(const char *name, int paramcount) {
        auto class_get_method_from_name = (class_get_method_from_name_t) dlsym(get_il2cpp(),
                                                                               OBFUSCATE(
                                                                                       "il2cpp_class_get_method_from_name"));
        if (thisclass)
            return class_get_method_from_name(thisclass, name, paramcount);
        else
            return nullptr;
    }

    DWORD GetMethodOffsetByName(const char *name, int paramcount) {
        auto res = GetMethodInfoByName(name, paramcount);
        if (res)
            return (DWORD) GetMethodInfoByName(name, paramcount)->methodPointer;
        else
            return 0;
    }
};

void *get_Method(const char *str) {
    void *(*il2cpp_resolve_icall_0)(const char *str) = nullptr;
    void *h = nullptr;
    while (!h) {
        h = dlopen(OBFUSCATE("libil2cpp.so"), 4);
    }
    do {
        il2cpp_resolve_icall_0 = (void *(*)(const char *)) dlsym(h,
                                                                 OBFUSCATE("il2cpp_resolve_icall"));
    } while (!il2cpp_resolve_icall_0);
    return il2cpp_resolve_icall_0(str);
}

#define InitResolveFunc(x, y) *reinterpret_cast<void **>(&x) = get_Method(y)
#define InitFunc(x, y) if (y != 0) *reinterpret_cast<void **>(&x) = (void *)(y)
#define FieldBN(myfield, type, inst, nameSpacec, clazzz, fieldName, key) Field<type> myfield = (new LoadClass(OBFUSCATE_KEY(nameSpacec, key), OBFUSCATE_KEY(clazzz, key)))->GetFieldByName<type>(OBFUSCATE_KEY(fieldName, key)); myfield.clazz = inst


Struct地址
https://www.123pan.com/s/SIoAjv-8T1Jv.html

6.hook的基本方法没变,只是换了一种寻址方式,由于比较简单,不再具体描述,下面几张图片给出了一些示例。

il2cpp自动寻址插图
THE END
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码

    暂无评论内容

随机文章