Skip to content

Commit

Permalink
rewrite prepare methods
Browse files Browse the repository at this point in the history
  • Loading branch information
Ciremun committed Jan 23, 2024
1 parent 8a86d8d commit e86411d
Show file tree
Hide file tree
Showing 19 changed files with 485 additions and 672 deletions.
35 changes: 0 additions & 35 deletions config.ini

This file was deleted.

169 changes: 10 additions & 159 deletions freedom/clrhost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,9 @@
#import "mscorlib.tlb" auto_rename
using namespace mscorlib;

enum class ClassMethodType : int32_t
{
Load = 0,
Replay = 1,
Score = 2,
CheckFlashlight = 3,
UpdateFlashlight = 4,
CheckTime = 5,
UpdateVariables = 6,
COUNT = 7,
};
constexpr int32_t classmethod_types_count = (int32_t)ClassMethodType::COUNT;

#pragma pack(push)
#pragma pack(4)
struct ClassMethod
{
wchar_t *class_ = 0;
wchar_t *method = 0;
ClassMethodType type = ClassMethodType::COUNT;
uintptr_t address = 0;
uintptr_t found = 0;
};
#pragma pack(pop)

bool prepared_all_methods = false;
bool prepared_methods = false;
int prepared_methods_count = -1;
_AssemblyPtr assembly_ptr = 0;

std::string cm_load_s;
std::string cm_replay_s;
std::string cm_score_s;
std::string cm_checkflashlight_s;
std::string cm_updateflashlight_s;
std::string cm_checktime_s;
std::string cm_updatevariables_s;

static inline std::string get_utf8(const std::wstring &wstr)
{
if (wstr.empty()) return std::string();
Expand All @@ -50,111 +16,13 @@ static inline std::string get_utf8(const std::wstring &wstr)
return res;
}

static inline std::wstring get_utf16(const std::string &str)
{
if (str.empty()) return std::wstring();
int sz = MultiByteToWideChar(CP_UTF8, 0, &str[0], -1, 0, 0);
std::wstring res(sz, 0);
MultiByteToWideChar(CP_UTF8, 0, &str[0], -1, &res[0], sz);
return res;
}

static inline std::string get_utf8_for_classmethod(wchar_t *class_, wchar_t *method, ClassMethodType type)
{
std::wstring colon_colon(L"::");
if (!class_ || !method)
return get_utf8(colon_colon);

std::wstring class_method_type = std::wstring(class_) + colon_colon +
std::wstring(method) + colon_colon +
std::to_wstring((int32_t)type);
return get_utf8(class_method_type);
}

void get_classmethods_from_addrs()
{
ClassMethod classmethods[classmethod_types_count] = {
{.type = ClassMethodType::Load, .address = beatmap_onload_code_start},
{.type = ClassMethodType::Replay, .address = selected_replay_code_start},
{.type = ClassMethodType::Score, .address = score_multiplier_code_start - 0xA},
{.type = ClassMethodType::CheckFlashlight, .address = check_flashlight_code_start},
{.type = ClassMethodType::UpdateFlashlight, .address = update_flashlight_code_start},
{.type = ClassMethodType::CheckTime, .address = check_timewarp_code_start},
{.type = ClassMethodType::UpdateVariables, .address = hom_update_vars_code_start},
};
VARIANT variant;
VariantInit(&variant);
variant.vt = VT_I4;
variant.intVal = (INT)classmethods;
SAFEARRAY* params = SafeArrayCreateVector(VT_VARIANT, 0, 2);
LONG i = 0;
SafeArrayPutElement(params, &i, &variant);
++i;
variant.vt = VT_I4;
variant.intVal = classmethod_types_count;
SafeArrayPutElement(params, &i, &variant);
VARIANT v = invoke_csharp_method(L"Freedom.Utils", L"ClassMethodsFromAddrs", params);
if (variant_ok(&v) && v.intVal == 1)
{
cm_load_s = get_utf8_for_classmethod(classmethods[0].class_, classmethods[0].method, classmethods[0].type);
cm_replay_s = get_utf8_for_classmethod(classmethods[1].class_, classmethods[1].method, classmethods[1].type);
cm_score_s = get_utf8_for_classmethod(classmethods[2].class_, classmethods[2].method, classmethods[2].type);
cm_checkflashlight_s = get_utf8_for_classmethod(classmethods[3].class_, classmethods[3].method, classmethods[3].type);
cm_updateflashlight_s = get_utf8_for_classmethod(classmethods[4].class_, classmethods[4].method, classmethods[4].type);
cm_checktime_s = get_utf8_for_classmethod(classmethods[5].class_, classmethods[5].method, classmethods[5].type);
cm_updatevariables_s = get_utf8_for_classmethod(classmethods[6].class_, classmethods[6].method, classmethods[6].type);
ImGui::SaveIniSettingsToDisk(ImGui::GetIO().IniFilename);
}
SafeArrayDestroy(params);
}

static inline bool set_classmethods_from_strings()
{
VARIANT v;
std::wstring cm_load_ws = get_utf16(cm_load_s);
std::wstring cm_replay_ws = get_utf16(cm_replay_s);
std::wstring cm_score_ws = get_utf16(cm_score_s);
std::wstring cm_checkflashlight_ws = get_utf16(cm_checkflashlight_s);
std::wstring cm_updateflashlight_ws = get_utf16(cm_updateflashlight_s);
std::wstring cm_checktime_ws = get_utf16(cm_checktime_s);
std::wstring cm_updatevariables_ws = get_utf16(cm_updatevariables_s);
#define RETURN_IF_FALSE() if (variant_ok(&v) && v.intVal != 1) return false
v = invoke_csharp_method(L"Freedom.Utils", L"SetClassMethod", cm_load_ws.c_str()); RETURN_IF_FALSE();
v = invoke_csharp_method(L"Freedom.Utils", L"SetClassMethod", cm_replay_ws.c_str()); RETURN_IF_FALSE();
v = invoke_csharp_method(L"Freedom.Utils", L"SetClassMethod", cm_score_ws.c_str()); RETURN_IF_FALSE();
v = invoke_csharp_method(L"Freedom.Utils", L"SetClassMethod", cm_checkflashlight_ws.c_str()); RETURN_IF_FALSE();
v = invoke_csharp_method(L"Freedom.Utils", L"SetClassMethod", cm_updateflashlight_ws.c_str()); RETURN_IF_FALSE();
v = invoke_csharp_method(L"Freedom.Utils", L"SetClassMethod", cm_checktime_ws.c_str()); RETURN_IF_FALSE();
v = invoke_csharp_method(L"Freedom.Utils", L"SetClassMethod", cm_updatevariables_ws.c_str()); RETURN_IF_FALSE();
#undef RETURN_IF_FALSE
ImGui::SaveIniSettingsToDisk(ImGui::GetIO().IniFilename);
FR_INFO("[+] All classmethods are set");
return true;
}

bool prepare_all_methods_fast()
{
if (!set_classmethods_from_strings())
{
FR_INFO("[!] Failed to set some classmethods, fallback to slow method");
return false;
}
VARIANT v = invoke_csharp_method(L"Freedom.Utils", L"prepare_all_methods_fast");
if (variant_ok(&v) && v.intVal == 1)
{
prepared_methods = true;
return true;
}
return false;
}

bool prepare_all_methods_slow()
bool prepare_methods()
{
double s = ImGui::GetTime();
invoke_csharp_method(L"Freedom.Utils", L"prepare_all_methods_slow");
FR_INFO_FMT("Preparing All Methods Slow Took: %lfs", ImGui::GetTime() - s);
prepared_all_methods = true;
prepared_methods = true;
VARIANT v = invoke_csharp_method(L"Freedom.Utils", L"PrepareMethods");
if (variant_ok(&v))
prepared_methods_count = v.intVal;
FR_INFO_FMT("Preparing Methods Took: %lfs", ImGui::GetTime() - s);
return true;
}

Expand All @@ -177,31 +45,26 @@ static inline ICorRuntimeHost* getCorRtHost_byVersion(LPCWSTR sz_runtimeVersion)
FR_INFO("[!] CLRCreateInstance");
return NULL;
}
else FR_INFO("[+] CLRCreateInstance");

if (FAILED(pMetaHost->GetRuntime(sz_runtimeVersion, IID_ICLRRuntimeInfo, (VOID**)&pRuntimeInfo))) {
FR_INFO_FMT("[!] GetRuntime failed: %S", sz_runtimeVersion);
return NULL;
}
else FR_INFO("[+] GetRuntime");

if (FAILED(pRuntimeInfo->IsLoadable(&bLoadable)) || !bLoadable) {
FR_INFO("[!] IsLoadable");
return NULL;
}
else FR_INFO("[+] IsLoadable");

if (FAILED(pRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, (VOID**)&pRuntimeHost))) {
FR_INFO("[!] GetInterface");
return NULL;
}
else FR_INFO("[+] GetInterface");

if (FAILED(pRuntimeHost->Start())) {
FR_INFO("[!] Start");
return NULL;
}
else FR_INFO("[+] Start");
return pRuntimeHost;
}

Expand All @@ -211,14 +74,12 @@ static inline _AppDomainPtr getDefaultDomain(ICorRuntimeHost* pRuntimeHost) {
FR_INFO("[!] GetDefaultDomain");
return NULL;
}
else FR_INFO("[+] GetDefaultDomain");

_AppDomainPtr pDefaultAppDomain = NULL;
if (FAILED(pAppDomainThunk->QueryInterface(__uuidof(_AppDomain), (LPVOID*)&pDefaultAppDomain))) {
FR_INFO("[!] QueryInterface");
return NULL;
}
else FR_INFO("[+] QueryInterface");
return pDefaultAppDomain;
}

Expand All @@ -231,52 +92,42 @@ static inline _AssemblyPtr getAssembly_fromBinary(_AppDomainPtr pDefaultAppDomai
FR_INFO("[!] SafeArrayAccessData");
return NULL;
}
else FR_INFO("[+] SafeArrayAccessData");

memcpy(pvData, rawData, lenRawData);
if (FAILED(SafeArrayUnaccessData(pSafeArray))) {
FR_INFO("[!] SafeArrayUnaccessData");
return NULL;
}
else FR_INFO("[+] SafeArrayUnaccessData");

if (pAssembly = pDefaultAppDomain->Load_3(pSafeArray))
FR_INFO("[+] Load");
else
{
pAssembly = pDefaultAppDomain->Load_3(pSafeArray);
if (!pAssembly) {
FR_INFO("[!] Load");
return NULL;
}
if (FAILED(SafeArrayDestroy(pSafeArray))) {
FR_INFO("[!] SafeArrayDestroy");
return pAssembly;
}
else FR_INFO("[+] SafeArrayDestroy");

return pAssembly;
}

bool load_csharp_assembly()
{
FR_INFO(" --- Try to Fetch .NET Framework v4.0.30319 ---");
ICorRuntimeHost* pRuntimeHost = getCorRtHost_byVersion(L"v4.0.30319");

if (!pRuntimeHost)
return false;

FR_INFO(" --- Execute .NET Module ---");
_MethodInfoPtr pMethodInfo = NULL;
if (auto pDefaultAppDomain = getDefaultDomain(pRuntimeHost))
{
if (assembly_ptr = getAssembly_fromBinary(pDefaultAppDomain, LPBYTE(utils_dll_data), utils_dll_size))
{
FR_INFO("--- Done! ---");
return true;
}
FR_INFO("[!] --- Get Assembly From Binary Failed ---");
FR_INFO("[!] C# Get Assembly From Binary Failed");
return false;
}
FR_INFO("[!] --- Get Default Domain Failed ---");
FR_INFO("[!] C# Get Default Domain Failed");
return false;
}

Expand Down
Loading

0 comments on commit e86411d

Please sign in to comment.