ใ
I'm Jess
A Software Engineer & Linux Enthusiast
Check Out My Portfolio
ใ
A C++ library for accessing Unity's IL2CPP classes, methods, and fields during run-time.
License: GNU General Public License v3.0
ใ
I'm Jess
A Software Engineer & Linux Enthusiast
Check Out My Portfolio
ใ
tl;dr Aetherim should provide a way to hook methods.
Getting method points with Aetherim is extremely simple and can be done very quickly, which would make hooking methods child's play.
I propose implementing Hooks.hpp
, which would aim to provide a wrapper around hooks that would allow integration with custom hook logic in your own code.
Aetherim currently provides helper classes to get and use Unity images, classes, methods, and fields. Where it lacks, however, is having an abstraction around getting, using, and manipulating native GameObjects.
This would be tremendously useful in scenarios where you'd wish to get a specific GameObject and access its fields or methods directly.
It'd be used as a means to easily access Camera objects and would provide ready-to-go WorldToScreen logic, amongst other things.
These would further expand upon the library by adding Method.hpp
and ``Field.hpp` files.
Method.hpp
would implement further support for methods.
Field.hpp
would implement further support for fields.
Really struggling to mod a macOS game
Linux and macOS support
Wine/virtualization
Remove main.cpp
and create generate.cpp
. This file will be used to generate a variety of inclusive .h files which contain valid addresses to classes, methods, and fields.
Would be useful when programming an external program for games and software that uses Unity's IL2CPP framework.
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?
No crashing.
Sons of ther Forest
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
¶ms // either a void * of params or nullptr
);
}
else {
LOG_ERROR("il2cpp::CallAddItems(): Faile to find the AddItemsByType() Method");
return;
}
}
`
Hello sir , i don't currently have any bug with this software. I checked your blog and you are doing an awesome work. I got recently started in reverse engineering il2cpp. Your work is incredibly useful and well explained. Thank you very much for this work.
By the way do you have any discord server where it would be possible to talk about this project and maybe for example giving suggestions , improving this tool and helping each other by providing explanations ?
It should be possible to allow the creation and loading of custom domains from custom .cs
files.
I don't know if this would be useful, but it's likely possible and it extends the usability of Aetherim, so it's worth checking out.
I could also be overthinking this when there's much simpler ways of going about custom C# script execution.
The implementation details for this is rough and incomplete, and comments regarding the issue as a whole would be gratefully appreciated.
We would use IL2CPP's il2cpp_init()
and il2cpp_domain_set()
export to initialize a new domain.
Aetherim doesn't currently expose these for use, but can be added pretty easily. A rough example can be seen here, though may not be 100% correct.
// api definitions
DEF_API( il2cpp_init, int *, (const char * domain_name) );
DEF_API( il2cpp_init_utf16, int *, (const Il2CppChar * domain_name) );
DEF_API( il2cpp_set_domain, void, (void * domain, bool _) );
// address definitions
DEF_ADDR( il2cpp_init, "il2cpp_init", GameAssemblyHandle );
DEF_ADDR( il2cpp_init_utf16, "il2cpp_init_utf16", GameAssemblyHandle );
DEF_ADDR( il2cpp_set_domain, "il2cpp_domain_set", GameAssemblyHandle );
You'd create a new instance of the domain, and when using it, you'd access it as such:
// get ref to the current domain before we create a new one
const original_domain = Il2cpp::get_domain();
// initialize our custom domain
const domain = Il2cpp:init("Aetherim/CustomDomain");
if ( domain != original_domain )
{
// mono_thread_push_appdomain_ref / is there an il2cpp equivalent?
mono_thread_push_appdomain_ref(domain);
const auto custom_domain = Il2cpp::set_domain(domain, false);
if ( custom_domain ) {
// attach the thread to the new domain
Il2cpp::thread_attach( domain );
// perform w/e custom domain logic here
// ...
// reattach to the main thread
Il2cpp::set_domain(original_domain, true);
}
}
Aetherim doesn't provide any support for logging data, errors, warnings, etc.
Ideally, we'd use this primarily to handle logging any exceptions that occur during runtime.
When initialized, check for Aetherim.log
in the game's root directory.
If it exists: truncate its contents (deleting/recreating the file may be quicker, idk yet)
If it doesn't exist: create the file
When we catch any exceptions, ex: if Class->get_field() is called but the field doesn't exist, we log the Image, Namespace, Class, and the name of the field that we tried to get to the logfile.
Example logfile entry:
[Sept. 30, 2023 @ 04:20 AM] Attempted access to non-existent field in Image->Namespace->Class
We can do this for anything, but logs for thrown exceptions are a must.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.