Toxocious / Aetherim

A C++ library for accessing Unity's IL2CPP classes, methods, and fields during run-time.
GNU General Public License v3.0
59 stars 15 forks source link

issue: Crash on calling No-Static function #8

Closed NetCKRiters closed 1 year ago

NetCKRiters commented 1 year ago

Steps to reproduce

Game: Sons of the Forest. Class Def:

Issue:

Crash dump:
0x00007FFEF844962E (GameAssembly) il2cpp_gc_has_strict_wbarriers
0x00007FFEF86E3ED6 (GameAssembly) mono_type_size
0x00007FFEF86E3994 (GameAssembly) mono_type_size
0x00007FFF1FD262E3 (redhook) [il2cpp.cpp] il2cpp::CallAddItems 
0x00007FFF1FD750B5 (redhook) [il2cpp.cpp] c_menu::Render 
0x00007FFF1FD73535 (redhook) [il2cpp.cpp] hkPresent 
0x00007FFF15F0632B (UnityPlayer) UnityMain
0x00007FFF1667789C (UnityPlayer) UnityMain
0x00007FFF166727FB (UnityPlayer) UnityMain
0x00007FFF16672767 (UnityPlayer) UnityMain

The last info that i go from the dll is: GetLastError: 'Attempt to access invalid address.' (Address: 00007FFF15CC06DE) Anone see a issue in the code?

Expected behaviour

No crashing.

Game

Sons of ther Forest

Relevant log output

Custom code that i use:
`
Image* get_image(const char* imageName) {
    const auto image = g_wrapper.get_image(imageName);
    if (image) {
        return image;
    }
    return nullptr;
}

Class* get_new_class(const char* imageName, const char* klass, const char* namezpace) {
    const auto image = get_image(imageName);
    const auto class_search = image->get_class(klass, namezpace);
    if (!class_search) {
        return nullptr;
    }
    return class_search;
}

//Get a a static field.
void* get_new_field_static(const char* imageName, const char* klass, const char* namezpace, const char* field) {
    const auto image = g_wrapper.get_image(imageName);
    const auto class_found = image->get_class(klass, namezpace);
    if (class_found != nullptr) {
        auto field_found = player->get_field(field);
        if (field_found != nullptr) {
            auto FieldFinal = field_found->get_as_static();
            if (FieldFinal != nullptr) {
                return FieldFinal;
            }
        }
    }

    return nullptr;
}

//Get a common field.
Field* get_new_field(const char* imageName, const char* klass, const char* namezpace, const char* field) {
    auto class_search = get_new_class(imageName, klass, namezpace);
    if (class_search != nullptr) {
        auto field_found = player->get_field(field);
        if (field_found != nullptr) {
            return field_found;
        }
    }
    return nullptr;
}

//Find a Method as Method*
Method* get_class_method(const char* imageName, const char* klass, const char* namezpace, const char* method) {
    auto cc = get_new_class(imageName, klass, namezpace);
    if (cc) {
        auto mth = cc->get_method(method);
        if (mth != nullptr) {
            return mth;
        }
    }
    return nullptr;
}
`

`
--crash as soon i call this.
void il2cpp::CallAddItems(int type, int amount) {

    const auto get_add_items_types = get_class_method("Sons.dll", "LocalPlayer", "TheForest.Utils", "AddItemsByType");
    if (get_add_items_types != nullptr)
    {
        auto instance = get_new_field_static("Sons.dll", "LocalPlayer", "TheForest.Utils", "_instance");
        if (!instance) {
            LOG_ERROR("Fail to find the LocalPlayer Instance");
            return;
        }

        typedef struct {
            int typeID;
            int amountValue;
        } AddItemsByTypeStruct;

        AddItemsByTypeStruct p = { type, amount };
        void* params = &p;
        get_add_items_types->invoke(
            instance, // instance/object pointer
            &params    // either a void * of params or nullptr
        );

    }
    else {
        LOG_ERROR("il2cpp::CallAddItems(): Faile to find the AddItemsByType() Method");
        return;
    }

}
`
NetCKRiters commented 1 year ago

PD. Im just having issue on the calls, also pls share me how to pull a code, cause im new to github. But i made a custom hook class to just def: ADD_HOO(funtion, target, name).

After some time i confirm i can get the method, and the instance correct:

[INFO - SOF - get_image] get_image(): Sons.dll [INFO - SOF - get_new_class] get_new_class(): LocalPlayer [INFO - SOF - get_class_method] get_class_method(): AddItemsByType [INFO - SOF - get_image] get_image(): Sons.dll [INFO - SOF - get_new_class] get_new_class(): LocalPlayer [INFO - SOF - get_class_method] get_class_method(): AddItemsByType [INFO - SOF - get_class_method] Parameters in Method: 3 [INFO - SOF - get_class_method] [!]typeMask [INFO - SOF - get_class_method] [!]amount [INFO - SOF - get_class_method] [!]preventAutoEquip

At this point, i get the Image, the Class, the Method that i want to invoke. Also i founding the Instance correct: [INFO - SOF - get_image] get_image(): Sons.dll [INFO - SOF - get_new_class] get_new_class(): LocalPlayer [INFO - SOF - get_new_field_static] field_static: ### _instance found [INFO - SOF - CallAddItems] Instance Found Correct it

But im getting the crash still.

Now the crash is just in invoke:

get_add_items_types->invoke(
            instance, // instance/object pointer
            &params    // either a void * of params or nullptr
        );

Can Anyone see the issue?

Toxocious commented 1 year ago

In regards to how you're invoking the method, don't use a ref to params Look at the last two lines in this snippet to see what I'm talking about.

const auto transformClass = Fleiya::Engine::unity_engine_image->get_class( "Transform", "UnityEngine" );

const auto transformGetPos = transformClass->get_method( "get_position" );

const auto playerTransform = instance->fields.Character->fields.thisTransform;
void * params[] = { &new_x, &new_y, &avoid_pos, &script, &ignore_collision, nullptr };
return reinterpret_cast<Vector3 *>( transformClass->invoke_method( transformGetPos, playerTransform, params ) );

In this example, I'm getting the transform class then getting the method pointer to the get_position method then getting the player's transform obj and finally setting method params and then invoking the non-static method

this code works for me on a game that i've played

if it continues to crash due to accessing an invalid address, then i'd verify that you're getting a correct method pointer for whatever function you're trying to call

Toxocious commented 1 year ago

Closing as the issue has been resolved over Discord.