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
#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
#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
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码

    暂无评论内容

随机文章