|
|
|
@ -13,9 +13,12 @@ namespace ligma
|
|
|
|
|
ligma::utils::on_image_load("libil2cpp.so", callback);
|
|
|
|
|
ligma::utils::on_image_load("libxlua.so", [&](const std::uintptr_t module_base)
|
|
|
|
|
{
|
|
|
|
|
LOGI("libxlua.so base = %p", module_base);
|
|
|
|
|
// install lua hooks when libxlua.so gets loaded...
|
|
|
|
|
loadbufferx = dlsym(reinterpret_cast<void*>(module_base), "luaL_loadbufferx");
|
|
|
|
|
ligma::hook::make_hook(loadbufferx, reinterpret_cast<void*>(&loadbufferx_hook));
|
|
|
|
|
ligma::hook::make_hook(
|
|
|
|
|
dlsym(reinterpret_cast<void*>(module_base), "luaL_loadbufferx"),
|
|
|
|
|
reinterpret_cast<void*>(&load_bufferx_hook)
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// these hooks can be registered at anytime.
|
|
|
|
@ -32,7 +35,7 @@ namespace ligma
|
|
|
|
|
// dont let a single lua script load!
|
|
|
|
|
//
|
|
|
|
|
__attribute__((noinline))
|
|
|
|
|
int loadbufferx_hook(void* L, const char* buff, size_t sz, const char* name, const char* mode)
|
|
|
|
|
int load_bufferx_hook(void* L, const char* buff, size_t sz, const char* name, const char* mode)
|
|
|
|
|
{ return NULL; }
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
@ -43,10 +46,11 @@ namespace ligma
|
|
|
|
|
FILE* fopen_hook(const char* path, const char* mode)
|
|
|
|
|
{
|
|
|
|
|
if (strstr(path, ".apk")) // support older versions of android.
|
|
|
|
|
{
|
|
|
|
|
path = "/data/app/base_orig.apk";
|
|
|
|
|
LOGI("spoofed base.apk to original apk!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// no need to be opening my .so :)
|
|
|
|
|
if (strstr(path, "libligma.so"))
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
fopen_mutex.lock();
|
|
|
|
|
ligma::hook::disable(fopen_ptr);
|
|
|
|
@ -57,7 +61,7 @@ namespace ligma
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// this is used to gain code execution exactly when il2cpp.so is loaded...
|
|
|
|
|
// this is used to gain code execution exactly when a module is loaded (for the first time)
|
|
|
|
|
//
|
|
|
|
|
__attribute__((noinline))
|
|
|
|
|
void* dlopen_hook(const char* filename, int flags)
|
|
|
|
@ -65,18 +69,21 @@ namespace ligma
|
|
|
|
|
dlopen_mutex.lock();
|
|
|
|
|
ligma::hook::disable(dlopen_ptr);
|
|
|
|
|
const auto result = dlopen(filename, reinterpret_cast<int>(RTLD_NEXT));
|
|
|
|
|
if(ligma::utils::get_callbacks()->size()) // only enable hook if we still have callbacks...
|
|
|
|
|
if(ligma::utils::get_callbacks()->size())
|
|
|
|
|
ligma::hook::enable(dlopen_ptr);
|
|
|
|
|
dlopen_mutex.unlock();
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// if there is a callback for this module, call it and remove it from the map.
|
|
|
|
|
// if there is a callback for this module, call it and then remove it.
|
|
|
|
|
//
|
|
|
|
|
const auto callback = ligma::utils::get_callbacks()->find(filename);
|
|
|
|
|
if (callback != ligma::utils::get_callbacks()->end())
|
|
|
|
|
for (const auto& [file_key, callback] : *ligma::utils::get_callbacks())
|
|
|
|
|
{
|
|
|
|
|
if (strstr(filename, file_key.c_str()))
|
|
|
|
|
{
|
|
|
|
|
callback->second(reinterpret_cast<std::uintptr_t>(result));
|
|
|
|
|
ligma::utils::get_callbacks()->erase(filename);
|
|
|
|
|
callback(reinterpret_cast<std::uintptr_t>(result));
|
|
|
|
|
ligma::utils::get_callbacks()->erase(file_key);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
@ -100,10 +107,8 @@ namespace ligma
|
|
|
|
|
strcmp(name, "ro.build.fingerprint") != 0 &&
|
|
|
|
|
strcmp(name, "ro.revision") != 0 &&
|
|
|
|
|
strcmp(name, "ro.build.version.sdk") != 0)
|
|
|
|
|
{
|
|
|
|
|
LOGI("spoofed hwid = %s, to = %s", value, HWID_VALUE);
|
|
|
|
|
value = HWID_VALUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return strlen(value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|