рдпреВрдирд┐рдЯреА рдЧреЗрдо рдХреЗ рд▓рд┐рдП рдореЙрдбреНрд╕ рдХреИрд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рднрд╛рдЧ 1: рдЦреЗрд▓ рдХреЛрдб рдореЗрдВ рд╣реЛ рд░рд╣реА рд╣реИ

рдЕрдзрд┐рдХрд╛рдВрд╢ рдЦреЗрд▓реЛрдВ рдореЗрдВ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рдЖрдзреБрдирд┐рдХ рд╕рдорд░реНрдерди рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рд▓рдЧрд╛рддрд╛рд░ рдЦрдмрд░реЗрдВ рдЖрддреА рд╣реИрдВ рдХрд┐ рдХреИрд╕реЗ рдореЙрдбреЗрдо рдЦреЗрд▓реЛрдВ рдореЗрдВ рдХреБрдЫ рдирдпрд╛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред рдЖрдорддреМрд░ рдкрд░ рд╣рдо рдореЙрдбрд▓, рдмрдирд╛рд╡рдЯ рдпрд╛ рд╕рдВрдЧреАрдд рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ , рд▓реЗрдХрд┐рди рдирдП рдЧреЗрдо рдореИрдХреЗрдирд┐рдХреНрд╕ рдХреЗ рдкреВрд░реНрдг-рднрд╛рдЧ рднреА рд╣реИрдВ, рдЕрд░реНрдерд╛рдд modders рдЧреЗрдо рдХреЛрдб рдореЗрдВ рдПрдореНрдмреЗрдбреЗрдб рд╣реИрдВ рдФрд░ рдЖрдВрддрд░рд┐рдХ рд▓реЙрдЬрд┐рдХ рдХреЛ рдмрджрд▓рддреЗ рд╣реИрдВред


рдореИрдВ рдореЙрдб рдХреЗ рд╕рд╛рде рдмреАрдЯ рд╕реЗрдмрд░ рдЦреЗрд▓рддрд╛ рд╣реВрдВ, рдФрд░ рдХреБрдЫ рдмрд┐рдВрджреБ рдкрд░ рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ рд▓рд┐рдЦрдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рдЧрдпрд╛ рд╣реИред рдмреАрдЯ рдХреГрдкрд╛рдг рдПрдХрддрд╛ рдкрд░ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдЗрд╕рдХреЗ рдХреЛрдб рдореЗрдВ рд╡рд┐рд▓рдореНрдм рдХрд░ рджрд┐рдпрд╛, рдореМрдЬреВрджрд╛ рдореЙрдбреНрд╕ рдХрд╛ рдХреЛрдб, рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдпрд╛ рдХрд┐ рд╡рд╣рд╛рдВ рд╕рдм рдХреБрдЫ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рд▓реЗрдЦ рд▓рд┐рдЦрд╛ред рдпрд╣ рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╕рд╛рдордЧреНрд░реА рдирд┐рдХрд▓рд╛, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдЗрд╕реЗ рджреЛ рднрд╛рдЧреЛрдВ рдореЗрдВ рддреЛрдбрд╝ рджрд┐рдпрд╛ред рдЗрд╕ рднрд╛рдЧ рдореЗрдВ, рд╣рдо рдЗрд╕ рдмрд╛рдд рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗ рдХрд┐ рдЧреЗрдо рд▓реЙрдиреНрдЪ рдХреЛ рдерд░реНрдб-рдкрд╛рд░реНрдЯреА рдореЛрдб рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рди рддрд░реАрдХреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: рдЧреЗрдо рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдФрд░ рдЗрдВрдЬрди рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдирд╛, dll рдЖрдпрд╛рдд рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдкрддреЗ рдХреЛ рдЦрд░рд╛рдм рдХрд░рдирд╛, рдФрд░ рд▓реЛрдбрд┐рдВрдЧ рдореЛрдиреЛ рд░рдирдЯрд╛рдЗрдо рдХреЗ рд╕рд╛рде рд╣рд╕реНрддрдХреНрд╖реЗрдк рдХрд░рдирд╛ред



рдЫрд╡рд┐ рд╕реНрд░реЛрдд: 1 , 2


рдмреАрдЯ рдХреГрдкрд╛рдг рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ


Beat Saber VR-. , , , , Beat Saber. , , , Youtube:



, Beat Saber тАФ . , , - , , , . - . тАФ - .


, Beat Saber : Beat Saber Modding Group (BSMG). , .



. тАФ , GitHub, . , , , . , , GitHub.


Unity


Beat Saber Unity. Unity C# тАФ . C# тАФ , .NET (managed .NET assemblies) тАФ dll-, (Common Intermediate Language, CIL IL). C++, тАФ , тАФ C#. , Unity , CIL- . Unity Mono.


Mono тАФ (Common Language Infrastructure, CLI) . Mono Windows, Linux, macOS, . 2001 Ximian, 2003 Novell, 2011 Attachmate. Attachmate , Mono Mono, Xamarin, 2016 Microsoft.


, C C++, , Lua. C# , тАЬтАЭ, , JIT- . :



Mono.


( ) тАФ dll- ( .NET-), . , Beat Saber . BSIPA.


BSIPA



BSIPA (Beat Saber Illusion Plugin Architecture) тАФ , Beat Saber , . .


BSIPA C# ( ) IPA. .. Unity Beat Saber. BSIPA : IPA, IPA.Loader IPA.Injector. , , .


IPA.exe


тЖТ


ModAssistant , , , . BSIPA, IPA.exe. , , . , -, , : , - , . :


Beat Saber_Data\Managed\I18N.dll
Beat Saber_Data\Managed\I18N.West.dll
Beat Saber_Data\Managed\IPA.Injector.dll
Beat Saber_Data\Managed\IPA.Injector.pdb
Beat Saber_Data\Managed\IPA.Loader.dll
Beat Saber_Data\Managed\IPA.Loader.pdb
Beat Saber_Data\Managed\IPA.Loader.xml
Beat Saber_Data\Managed\Microsoft.CSharp.dll
Beat Saber_Data\Managed\System.Runtime.Serialization.dll
Libs\0Harmony.1.2.0.1.dll
Libs\Ionic.Zip.1.9.1.8.dll
Libs\Mono.Cecil.0.10.4.0.dll
Libs\Mono.Cecil.Mdb.0.10.4.0.dll
Libs\Mono.Cecil.Pdb.0.10.4.0.dll
Libs\Mono.Cecil.Rocks.0.10.4.0.dll
Libs\Newtonsoft.Json.12.0.0.0.dll
Libs\SemVer.1.2.0.0.dll
winhttp.dll

BSIPA, : IPA.Loader.dll IPA.Injector.dll. , . .


IPA.Loader.dll


, . PluginLoader, PluginManager PluginComponent. PluginLoader тАФ , Plugins. IPA , . BSIPA : Loader , , .


PluginManager : , .


PluginComponent тАФ Unity, , . , ( - , , ), PluginComponent . .


IPA.Injector.dll


тЖТ


Injector , . : BSIPA .


if (AntiPiracy.IsInvalid(Environment.CurrentDirectory))
{
    loader.Error("Invalid installation; please buy the game to run BSIPA.");
    return;
}

, , , : SmartSteamEmu.ini, BSteam crack.dll, HUHUVR_steam_api64.dll .


public static bool IsInvalid(string path)
{
    var dataPlugins = Path.Combine(GameVersionEarly.ResolveDataPath(path), "Plugins");
    return 
        File.Exists(Path.Combine(path, "IGG-GAMES.COM.url")) ||
        File.Exists(Path.Combine(path, "SmartSteamEmu.ini")) ||
        File.Exists(Path.Combine(path, "GAMESTORRENT.CO.url")) ||
        File.Exists(Path.Combine(dataPlugins, "BSteam crack.dll")) ||
        File.Exists(Path.Combine(dataPlugins, "HUHUVR_steam_api64.dll")) ||
        Directory.GetFiles(dataPlugins, "*.ini", SearchOption.TopDirectoryOnly).Length > 0;
}

, BSIPA . , , . BSIPA , , .


IPA.Injector : Mono.Cecil ( ). : Jb Evain, Novell Mono, Microsoft, Visual Studio Tools for Unity. Mono.Cecil 2004 , .. Mono. .NET-: IL-, .


IPA.Injector Mono.Cecil, UnityEngine.CoreModule.dll. C# ( ) Unity. , GameObject ( , , ) MonoBehaviour ( , PluginComponent). IPA.Injector UnityEngine.CoreModule.dll UnityEngine.Application ( , ), :


var unityAsmDef = AssemblyDefinition.ReadAssembly(unityPath, new ReaderParameters { ... });
var unityModDef = unityAsmDef.MainModule;
var application = unityModDef.GetType("UnityEngine", "Application");

MethodDefinition cctor = null;
foreach (var m in application.Methods)
    if (m.IsRuntimeSpecialName && m.Name == ".cctor")
        cctor = m;

var createBootstrapper = unityModDef.ImportReference(((Action)CreateBootstrapper).Method);

if (cctor == null)
{
    cctor = new MethodDefinition(".cctor", ...);
    application.Methods.Add(cctor);

    var ilp = cctor.Body.GetILProcessor();
    ilp.Emit(OpCodes.Call, cbs);
    ilp.Emit(OpCodes.Ret);
}
else
{
    var ilp = cctor.Body.GetILProcessor();
    ilp.Replace(cctor.Body.Instructions[0], ilp.Create(OpCodes.Call, cbs));
    ilp.Replace(cctor.Body.Instructions[1], ilp.Create(OpCodes.Ret));
}

, Unity 2019.3.0f3 Application , , . Injector , , .


Application ( UnityEngine.CoreModule.dll):


static Application()
{
  IPA.Injector.Injector.CreateBootstrapper();
}

CreateBootstrapper Bootstrapper:


private static void CreateBootstrapper()
{
    ...
    var bootstrapper = new GameObject("NonDestructiveBootstrapper")
            .AddComponent<Bootstrapper>();
    bootstrapper.Destroyed += Bootstrapper_Destroyed;
}

:


internal class Bootstrapper : MonoBehaviour
{
    public event Action Destroyed = delegate {};

    public void Start()
    {
        Destroy(gameObject);
    }

    public void OnDestroy()
    {
        Destroyed();
    }
}

Start Awake, Awake , , Start ( ). . Bootstrapper Start , . OnDestroy , CreateBootstrapper:


private static void Bootstrapper_Destroyed()
{
    // wait for plugins to finish loading
    pluginAsyncLoadTask.Wait();
    permissionFixTask.Wait();

    PluginComponent.Create();
}

PluginComponent. , , PluginComponent OnDestroy. : , тАФ Start , , , . , Unity- .


, Application (.. .NET- Unity), PluginComponent Plugins. , Beat Saber, Unity.


IPA.Injector тАФ MainAssembly.dll. Beat Saber. Mono.Cecil IPA.Injector sealed . . , .


BSIPA, IPA, . IPA.exe Injector, UnityEngine.CoreModule.dll, . тАФ , , IPA.exe . BSIPA , , , IPA.exe BSIPA . Injector .


Unity Doorstop



Unity UnityDoorstop-BSIPA. BSIPA C. UnityDoorstop-BSIPA ( ) тАФ , . UnityDoorstop-BSIPA Doorstop. Doorstop тАЬRun managed code before Unity does!тАЭ, тАЬ , Unity тАЭ. , тАЬ тАЭ тАФ C#. , Unity C++, Unity тАФ C#. , Doorstop - , Unity , C#- тАФ .


Unity (, Beat Saber.exe), UnityPlayer.dll. Unity- . , , UnityPlayer GetProcAddress kernel32.dll. GetProcAddress тАФ WinAPI, . Unity, , BSIPA Doorstop, UnityPlayer - :


mono_dll = LoadLibrary(тАЬMono.dllтАЭ);
init_mono = GetProcAddress(mono_dll, тАЭmono_jit_init_versionтАЭ);
mono = init_mono(...);
//   mono,      

mono_jit_init_version тАФ , Mono. . Doorstop . .


1. GetProcAddress


Doorstop.dll , DllMain , reasonForDllLoad == DLL_PROCESS_ATTACH, , :


HMODULE targetModule = GetModuleHandleA("UnityPlayer");
iat_hook(targetModule, "kernel32.dll", &GetProcAddress, &hookGetProcAddress);

DllMain, iat_hook


UnityPlayer.dll, (Import Address Table, IAT), GetProcAddress kernel32.dll hookGetProcAddress Doorstop.dll. hookGetProcAddress :


void * WINAPI hookGetProcAddress(HMODULE module, char const *name)
{
    if (lstrcmpA(name, "mono_jit_init_version") == 0)
    {
        init(module);
        return (void*)&ownMonoJitInitVersion;
    }
    return (void*)GetProcAddress(module, name);
}

hookGetProcAddress


IAT Hooking . , hookGetProcAddress GetProcAddress. - , . mono_jit_init_version, hookGetProcAddress GetProcAddress , , . mono_jit_init_version, ownMonoJitInitVersion. , - , mono_jit_init_version, Mono GetProcAddress ( init(module);):


/**
* \brief Loads Mono C API function pointers so that the above definitions can be called.
* \param monoLib Mono.dll module.
*/
inline void loadMonoFunctions(HMODULE monoLib)
{
    // Enjoy the fact that C allows such sloppy casting
    // In C++ you would have to cast to the precise function pointer type
#define GET_MONO_PROC(name) name = (void*)GetProcAddress(monoLib, #name)

    // Find and assign all our functions that we are going to use
    GET_MONO_PROC(mono_debug_domain_create);
    GET_MONO_PROC(mono_domain_assembly_open);
    GET_MONO_PROC(mono_assembly_get_image);
    GET_MONO_PROC(mono_runtime_invoke);
    GET_MONO_PROC(mono_debug_init);
    GET_MONO_PROC(mono_jit_init_version);
    GET_MONO_PROC(mono_jit_parse_options);
    GET_MONO_PROC(mono_method_desc_new);
    GET_MONO_PROC(mono_method_desc_search_in_image);
    GET_MONO_PROC(mono_method_signature);
    GET_MONO_PROC(mono_signature_get_param_count);
    GET_MONO_PROC(mono_array_new);
    GET_MONO_PROC(mono_get_string_class);
    GET_MONO_PROC(mono_string_new_utf16);
    GET_MONO_PROC(mono_gc_wbarrier_set_arrayref);
    GET_MONO_PROC(mono_array_addr_with_size);
    GET_MONO_PROC(mono_object_to_string);
    GET_MONO_PROC(mono_string_to_utf8);
    GET_MONO_PROC(mono_dllmap_insert);
    GET_MONO_PROC(mono_free);
}

2. mono_jit_init_version


ownMonoJitInitVersion mono_jit_init_version, Mono. Mono IPA.Injector.dll Main. () ownMonoJitInitVersion :


void *ownMonoJitInitVersion(const char *root_domain_name, const char *runtime_version)
{
    void *domain = mono_jit_init_version(root_domain_name, runtime_version);

    // Load our custom assembly into the domain
    void *assembly = mono_domain_assembly_open(domain, dll_path); // dll_path -    IPA.Inhector.dll

    // Get assembly's image that contains CIL code
    void *image = mono_assembly_get_image(assembly);

    // Create a descriptor for a random Main method
    void *desc = mono_method_desc_new("*:Main", FALSE);

    // Find the first possible Main method in the assembly
    void *method = mono_method_desc_search_in_image(desc, image);

    mono_runtime_invoke(method, NULL, args, &exception);

    return domain;
}

ownMonoJitInitVersion


, IPA.Injector , Beat Saber. , IPA.Injector , ownMonoJitInitVersion Mono Unity. Unity , - . mono_jit_init_version, Mono . Unity ownMonoJitInitVersion, Mono тАФ , Mono - .


winhttp.dll


. -, Doorstop Doorstop.dll. , IPA.exe :


Beat Saber_Data\Managed\I18N.dll
Beat Saber_Data\Managed\I18N.West.dll
Beat Saber_Data\Managed\IPA.Injector.dll
Beat Saber_Data\Managed\IPA.Injector.pdb
Beat Saber_Data\Managed\IPA.Loader.dll
Beat Saber_Data\Managed\IPA.Loader.pdb
Beat Saber_Data\Managed\IPA.Loader.xml
Beat Saber_Data\Managed\Microsoft.CSharp.dll
Beat Saber_Data\Managed\System.Runtime.Serialization.dll
Libs\0Harmony.1.2.0.1.dll
Libs\Ionic.Zip.1.9.1.8.dll
Libs\Mono.Cecil.0.10.4.0.dll
Libs\Mono.Cecil.Mdb.0.10.4.0.dll
Libs\Mono.Cecil.Pdb.0.10.4.0.dll
Libs\Mono.Cecil.Rocks.0.10.4.0.dll
Libs\Newtonsoft.Json.12.0.0.0.dll
Libs\SemVer.1.2.0.0.dll
winhttp.dll

, Doorstop.dll . -, Doorstop.dll , Beat Saber Unity , ? : Doorstop.dll , Unity, , . winhttp.dll тАФ Windows http- ( C:/Windows/System32). Unity , winhttp.dll, Unity Windows winhttp.dll , Unity .


Doorstop : winhttp.dll. Doorstop, GetProcAddress mono_jit_init_version, (Export Address Table) , winhttp.dll. Windows , Windows , , , , System32. Windows . winhttp ( LoadLibrary) ( GetProcAddress). : 16, тАФ 960.


IPA BSIPA proxy.c, , , GetProcAddress. IPA PowerShell, BSIPA тАФ Python. : proxy.c.


DLL Search Order Hijacking .



.


  • IPA.exe. . .
  • (Beat Saber.exe).
  • Windows , Unity. тАФ winhttp.dll. Windows winhttp.dll .
  • winhttp.dll Doorstop. GetProcAddress kernel32.dll hookGetProcAddress.
  • UnityPlayer.dll, C++.
  • Unity GetProcAddress, mono_jit_init_version. GetProcAddress, ownMonoJitInitVersion.
  • ownMonoJitInitVersion Mono.
  • ownMonoJitInitVersion Mono, IPA.Injector.dll Main .
  • IPA.Injector Mono.Cecil Application UnityEngine.CoreModule.dll , Beat Saber.
  • ownMonoJitInitVersion Mono Unity.
  • Unity Mono, , C#.
  • Application . Beat Saber.
  • Unity Mono, Beat Saber.
  • .

2


. , Windows Unity Beat Saber. , BSIPA тАФ , , , , Unity-.


Beat Saber: , , , Harmony тАФ C#-, RimWorld, BATTLETECH, Cities: Skylines, Kerbal Space Program, Oxygen Not Included, Stardew Valley, Subnautica .



BSMG DaNike , Discord , Doorstop winhttp.dll. , , , .


All Articles