├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── Bootstrapper ├── .gitignore ├── CMakeLists.txt ├── build.bat ├── build.sh ├── clean.bat ├── include │ ├── README.md │ ├── coreclr_delegates.h │ └── hostfxr.h └── src │ └── library.cpp ├── DemoApplication ├── .gitignore ├── DemoApplication.sln ├── DemoApplication │ ├── DemoApplication.csproj │ └── Program.cs ├── build.bat ├── build.sh └── clean.bat ├── README.md ├── RuntimePatcher ├── .gitignore ├── RuntimePatcher.sln ├── RuntimePatcher │ ├── Lib.cs │ └── RuntimePatcher.csproj ├── build.bat ├── build.sh └── clean.bat ├── _build.bat ├── _build.sh ├── _run.bat ├── _run.sh ├── assets └── banner.gif ├── package-lock.json ├── package.json ├── src ├── agent.ts └── main.ts └── tsconfig.json /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | *.yml text eol=lf 3 | *.json text eol=lf 4 | *.cmake text eol=lf 5 | *.txt text eol=lf 6 | 7 | *.bat text eol=lf 8 | 9 | *.md text eol=lf 10 | 11 | *.h text eol=lf 12 | *.cpp text eol=lf 13 | 14 | *.cs text eol=lf 15 | *.csproj text eol=lf 16 | *.sln text eol=lf 17 | 18 | *.js text eol=lf 19 | *.ts text eol=lf 20 | 21 | *.git* text eol=lf 22 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: [ master ] 5 | pull_request: 6 | branches: [ master ] 7 | workflow_dispatch: 8 | 9 | jobs: 10 | linux-build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v4 15 | 16 | - uses: actions/setup-node@v4 17 | with: 18 | node-version: 22 19 | 20 | - name: Build project 21 | run: ./_build.sh 22 | 23 | - name: Run project without root 24 | run: ./_run.sh 25 | 26 | - name: Run project with root 27 | run: ./_run.sh -a 28 | 29 | windows-build: 30 | runs-on: windows-latest 31 | 32 | steps: 33 | - uses: actions/checkout@v4 34 | 35 | - uses: actions/setup-node@v4 36 | with: 37 | node-version: 22 38 | 39 | - name: Install node packages 40 | run: npm install 41 | 42 | - name: Build project 43 | run: _build.bat 44 | shell: cmd 45 | 46 | - name: Run project 47 | run: _run.bat 48 | shell: cmd 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | 3 | dist 4 | node_modules 5 | -------------------------------------------------------------------------------- /Bootstrapper/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | build 3 | cmake-build-* 4 | -------------------------------------------------------------------------------- /Bootstrapper/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.20) 2 | project(Bootstrapper) 3 | 4 | set(CMAKE_CXX_STANDARD 23) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | 7 | add_library(${PROJECT_NAME} SHARED src/library.cpp) 8 | target_include_directories(${PROJECT_NAME} PRIVATE include) 9 | 10 | if (NOT WIN32) 11 | target_link_libraries(${PROJECT_NAME} PRIVATE dl) 12 | endif () 13 | -------------------------------------------------------------------------------- /Bootstrapper/build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | if not exist build mkdir build 4 | cd build 5 | 6 | set vswhere="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" 7 | set cmakeLookup=call %vswhere% -latest -requires Microsoft.VisualStudio.Component.VC.CMake.Project -find Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe 8 | 9 | for /f "tokens=*" %%i in ('%cmakeLookup%') do set cmake="%%i" 10 | 11 | %cmake% .. 12 | %cmake% --build . --config Release 13 | 14 | cd .. 15 | -------------------------------------------------------------------------------- /Bootstrapper/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | mkdir -p build && cd build 5 | 6 | cmake .. 7 | cmake --build . --config Release 8 | -------------------------------------------------------------------------------- /Bootstrapper/clean.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set DIRECTORIES=build .vs out .idea cmake-build-debug cmake-build-release 4 | 5 | for %%d in (%DIRECTORIES%) do ( 6 | if exist %%d ( 7 | del /s /f /q %%d\*.* 8 | for /f %%f in ('dir /ad /b %%d\') do rd /s /q %%d\%%f 9 | rd %%d 10 | ) 11 | ) 12 | 13 | del CMakeSettings.json 14 | -------------------------------------------------------------------------------- /Bootstrapper/include/README.md: -------------------------------------------------------------------------------- 1 | All these files comes from dotnet sources 2 | 1. [hostfxr.h](https://github.com/dotnet/runtime/blob/main/src/native/corehost/hostfxr.h) 3 | 2. [coreclr_delegates.h](https://github.com/dotnet/runtime/blob/main/src/native/corehost/coreclr_delegates.h) 4 | 5 | Script to update it 6 | ```bash 7 | curl https://raw.githubusercontent.com/dotnet/runtime/main/src/native/corehost/coreclr_delegates.h > coreclr_delegates.h 8 | curl https://raw.githubusercontent.com/dotnet/runtime/main/src/native/corehost/hostfxr.h > hostfxr.h 9 | dos2unix *.h 10 | ``` 11 | -------------------------------------------------------------------------------- /Bootstrapper/include/coreclr_delegates.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | #ifndef HAVE_CORECLR_DELEGATES_H 5 | #define HAVE_CORECLR_DELEGATES_H 6 | 7 | #include 8 | #include 9 | 10 | #ifdef __cplusplus 11 | extern "C" 12 | { 13 | #endif 14 | 15 | #if defined(_WIN32) 16 | #define CORECLR_DELEGATE_CALLTYPE __stdcall 17 | #ifdef _WCHAR_T_DEFINED 18 | typedef wchar_t char_t; 19 | #else 20 | typedef unsigned short char_t; 21 | #endif 22 | #else 23 | #define CORECLR_DELEGATE_CALLTYPE 24 | typedef char char_t; 25 | #endif 26 | 27 | #define UNMANAGEDCALLERSONLY_METHOD ((const char_t*)-1) 28 | 29 | // Signature of delegate returned by coreclr_delegate_type::load_assembly_and_get_function_pointer 30 | typedef int (CORECLR_DELEGATE_CALLTYPE *load_assembly_and_get_function_pointer_fn)( 31 | const char_t *assembly_path /* Fully qualified path to assembly */, 32 | const char_t *type_name /* Assembly qualified type name */, 33 | const char_t *method_name /* Public static method name compatible with delegateType */, 34 | const char_t *delegate_type_name /* Assembly qualified delegate type name or null 35 | or UNMANAGEDCALLERSONLY_METHOD if the method is marked with 36 | the UnmanagedCallersOnlyAttribute. */, 37 | void *reserved /* Extensibility parameter (currently unused and must be 0) */, 38 | /*out*/ void **delegate /* Pointer where to store the function pointer result */); 39 | 40 | // Signature of delegate returned by load_assembly_and_get_function_pointer_fn when delegate_type_name == null (default) 41 | typedef int (CORECLR_DELEGATE_CALLTYPE *component_entry_point_fn)(void *arg, int32_t arg_size_in_bytes); 42 | 43 | typedef int (CORECLR_DELEGATE_CALLTYPE *get_function_pointer_fn)( 44 | const char_t *type_name /* Assembly qualified type name */, 45 | const char_t *method_name /* Public static method name compatible with delegateType */, 46 | const char_t *delegate_type_name /* Assembly qualified delegate type name or null, 47 | or UNMANAGEDCALLERSONLY_METHOD if the method is marked with 48 | the UnmanagedCallersOnlyAttribute. */, 49 | void *load_context /* Extensibility parameter (currently unused and must be 0) */, 50 | void *reserved /* Extensibility parameter (currently unused and must be 0) */, 51 | /*out*/ void **delegate /* Pointer where to store the function pointer result */); 52 | 53 | typedef int (CORECLR_DELEGATE_CALLTYPE *load_assembly_fn)( 54 | const char_t *assembly_path /* Fully qualified path to assembly */, 55 | void *load_context /* Extensibility parameter (currently unused and must be 0) */, 56 | void *reserved /* Extensibility parameter (currently unused and must be 0) */); 57 | 58 | typedef int (CORECLR_DELEGATE_CALLTYPE *load_assembly_bytes_fn)( 59 | const void *assembly_bytes /* Bytes of the assembly to load */, 60 | size_t assembly_bytes_len /* Byte length of the assembly to load */, 61 | const void *symbols_bytes /* Optional. Bytes of the symbols for the assembly */, 62 | size_t symbols_bytes_len /* Optional. Byte length of the symbols for the assembly */, 63 | void *load_context /* Extensibility parameter (currently unused and must be 0) */, 64 | void *reserved /* Extensibility parameter (currently unused and must be 0) */); 65 | 66 | #ifdef __cplusplus 67 | } 68 | #endif // __cplusplus 69 | 70 | #endif // HAVE_CORECLR_DELEGATES_H 71 | -------------------------------------------------------------------------------- /Bootstrapper/include/hostfxr.h: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | #ifndef HAVE_HOSTFXR_H 5 | #define HAVE_HOSTFXR_H 6 | 7 | #include 8 | #include 9 | 10 | #ifdef __cplusplus 11 | extern "C" 12 | { 13 | #endif // __cplusplus 14 | 15 | #if defined(_WIN32) 16 | #define HOSTFXR_CALLTYPE __cdecl 17 | #ifdef _WCHAR_T_DEFINED 18 | typedef wchar_t char_t; 19 | #else 20 | typedef unsigned short char_t; 21 | #endif 22 | #else 23 | #define HOSTFXR_CALLTYPE 24 | typedef char char_t; 25 | #endif 26 | 27 | enum hostfxr_delegate_type 28 | { 29 | hdt_com_activation, 30 | hdt_load_in_memory_assembly, 31 | hdt_winrt_activation, 32 | hdt_com_register, 33 | hdt_com_unregister, 34 | hdt_load_assembly_and_get_function_pointer, 35 | hdt_get_function_pointer, 36 | hdt_load_assembly, 37 | hdt_load_assembly_bytes, 38 | }; 39 | 40 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_main_fn)(const int argc, const char_t **argv); 41 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_main_startupinfo_fn)( 42 | const int argc, 43 | const char_t **argv, 44 | const char_t *host_path, 45 | const char_t *dotnet_root, 46 | const char_t *app_path); 47 | typedef int32_t(HOSTFXR_CALLTYPE* hostfxr_main_bundle_startupinfo_fn)( 48 | const int argc, 49 | const char_t** argv, 50 | const char_t* host_path, 51 | const char_t* dotnet_root, 52 | const char_t* app_path, 53 | int64_t bundle_header_offset); 54 | 55 | typedef void(HOSTFXR_CALLTYPE *hostfxr_error_writer_fn)(const char_t *message); 56 | 57 | // 58 | // Sets a callback which is to be used to write errors to. 59 | // 60 | // Parameters: 61 | // error_writer 62 | // A callback function which will be invoked every time an error is to be reported. 63 | // Or nullptr to unregister previously registered callback and return to the default behavior. 64 | // Return value: 65 | // The previously registered callback (which is now unregistered), or nullptr if no previous callback 66 | // was registered 67 | // 68 | // The error writer is registered per-thread, so the registration is thread-local. On each thread 69 | // only one callback can be registered. Subsequent registrations overwrite the previous ones. 70 | // 71 | // By default no callback is registered in which case the errors are written to stderr. 72 | // 73 | // Each call to the error writer is sort of like writing a single line (the EOL character is omitted). 74 | // Multiple calls to the error writer may occur for one failure. 75 | // 76 | // If the hostfxr invokes functions in hostpolicy as part of its operation, the error writer 77 | // will be propagated to hostpolicy for the duration of the call. This means that errors from 78 | // both hostfxr and hostpolicy will be reporter through the same error writer. 79 | // 80 | typedef hostfxr_error_writer_fn(HOSTFXR_CALLTYPE *hostfxr_set_error_writer_fn)(hostfxr_error_writer_fn error_writer); 81 | 82 | typedef void* hostfxr_handle; 83 | struct hostfxr_initialize_parameters 84 | { 85 | size_t size; 86 | const char_t *host_path; 87 | const char_t *dotnet_root; 88 | }; 89 | 90 | // 91 | // Initializes the hosting components for a dotnet command line running an application 92 | // 93 | // Parameters: 94 | // argc 95 | // Number of argv arguments 96 | // argv 97 | // Command-line arguments for running an application (as if through the dotnet executable). 98 | // Only command-line arguments which are accepted by runtime installation are supported, SDK/CLI commands are not supported. 99 | // For example 'app.dll app_argument_1 app_argument_2`. 100 | // parameters 101 | // Optional. Additional parameters for initialization 102 | // host_context_handle 103 | // On success, this will be populated with an opaque value representing the initialized host context 104 | // 105 | // Return value: 106 | // Success - Hosting components were successfully initialized 107 | // HostInvalidState - Hosting components are already initialized 108 | // 109 | // This function parses the specified command-line arguments to determine the application to run. It will 110 | // then find the corresponding .runtimeconfig.json and .deps.json with which to resolve frameworks and 111 | // dependencies and prepare everything needed to load the runtime. 112 | // 113 | // This function only supports arguments for running an application. It does not support SDK commands. 114 | // 115 | // This function does not load the runtime. 116 | // 117 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_initialize_for_dotnet_command_line_fn)( 118 | int argc, 119 | const char_t **argv, 120 | const struct hostfxr_initialize_parameters *parameters, 121 | /*out*/ hostfxr_handle *host_context_handle); 122 | 123 | // 124 | // Initializes the hosting components using a .runtimeconfig.json file 125 | // 126 | // Parameters: 127 | // runtime_config_path 128 | // Path to the .runtimeconfig.json file 129 | // parameters 130 | // Optional. Additional parameters for initialization 131 | // host_context_handle 132 | // On success, this will be populated with an opaque value representing the initialized host context 133 | // 134 | // Return value: 135 | // Success - Hosting components were successfully initialized 136 | // Success_HostAlreadyInitialized - Config is compatible with already initialized hosting components 137 | // Success_DifferentRuntimeProperties - Config has runtime properties that differ from already initialized hosting components 138 | // HostIncompatibleConfig - Config is incompatible with already initialized hosting components 139 | // 140 | // This function will process the .runtimeconfig.json to resolve frameworks and prepare everything needed 141 | // to load the runtime. It will only process the .deps.json from frameworks (not any app/component that 142 | // may be next to the .runtimeconfig.json). 143 | // 144 | // This function does not load the runtime. 145 | // 146 | // If called when the runtime has already been loaded, this function will check if the specified runtime 147 | // config is compatible with the existing runtime. 148 | // 149 | // Both Success_HostAlreadyInitialized and Success_DifferentRuntimeProperties codes are considered successful 150 | // initializations. In the case of Success_DifferentRuntimeProperties, it is left to the consumer to verify that 151 | // the difference in properties is acceptable. 152 | // 153 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_initialize_for_runtime_config_fn)( 154 | const char_t *runtime_config_path, 155 | const struct hostfxr_initialize_parameters *parameters, 156 | /*out*/ hostfxr_handle *host_context_handle); 157 | 158 | // 159 | // Gets the runtime property value for an initialized host context 160 | // 161 | // Parameters: 162 | // host_context_handle 163 | // Handle to the initialized host context 164 | // name 165 | // Runtime property name 166 | // value 167 | // Out parameter. Pointer to a buffer with the property value. 168 | // 169 | // Return value: 170 | // The error code result. 171 | // 172 | // The buffer pointed to by value is owned by the host context. The lifetime of the buffer is only 173 | // guaranteed until any of the below occur: 174 | // - a 'run' method is called for the host context 175 | // - properties are changed via hostfxr_set_runtime_property_value 176 | // - the host context is closed via 'hostfxr_close' 177 | // 178 | // If host_context_handle is nullptr and an active host context exists, this function will get the 179 | // property value for the active host context. 180 | // 181 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_get_runtime_property_value_fn)( 182 | const hostfxr_handle host_context_handle, 183 | const char_t *name, 184 | /*out*/ const char_t **value); 185 | 186 | // 187 | // Sets the value of a runtime property for an initialized host context 188 | // 189 | // Parameters: 190 | // host_context_handle 191 | // Handle to the initialized host context 192 | // name 193 | // Runtime property name 194 | // value 195 | // Value to set 196 | // 197 | // Return value: 198 | // The error code result. 199 | // 200 | // Setting properties is only supported for the first host context, before the runtime has been loaded. 201 | // 202 | // If the property already exists in the host context, it will be overwritten. If value is nullptr, the 203 | // property will be removed. 204 | // 205 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_set_runtime_property_value_fn)( 206 | const hostfxr_handle host_context_handle, 207 | const char_t *name, 208 | const char_t *value); 209 | 210 | // 211 | // Gets all the runtime properties for an initialized host context 212 | // 213 | // Parameters: 214 | // host_context_handle 215 | // Handle to the initialized host context 216 | // count 217 | // [in] Size of the keys and values buffers 218 | // [out] Number of properties returned (size of keys/values buffers used). If the input value is too 219 | // small or keys/values is nullptr, this is populated with the number of available properties 220 | // keys 221 | // Array of pointers to buffers with runtime property keys 222 | // values 223 | // Array of pointers to buffers with runtime property values 224 | // 225 | // Return value: 226 | // The error code result. 227 | // 228 | // The buffers pointed to by keys and values are owned by the host context. The lifetime of the buffers is only 229 | // guaranteed until any of the below occur: 230 | // - a 'run' method is called for the host context 231 | // - properties are changed via hostfxr_set_runtime_property_value 232 | // - the host context is closed via 'hostfxr_close' 233 | // 234 | // If host_context_handle is nullptr and an active host context exists, this function will get the 235 | // properties for the active host context. 236 | // 237 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_get_runtime_properties_fn)( 238 | const hostfxr_handle host_context_handle, 239 | /*inout*/ size_t * count, 240 | /*out*/ const char_t **keys, 241 | /*out*/ const char_t **values); 242 | 243 | // 244 | // Load CoreCLR and run the application for an initialized host context 245 | // 246 | // Parameters: 247 | // host_context_handle 248 | // Handle to the initialized host context 249 | // 250 | // Return value: 251 | // If the app was successfully run, the exit code of the application. Otherwise, the error code result. 252 | // 253 | // The host_context_handle must have been initialized using hostfxr_initialize_for_dotnet_command_line. 254 | // 255 | // This function will not return until the managed application exits. 256 | // 257 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_run_app_fn)(const hostfxr_handle host_context_handle); 258 | 259 | // 260 | // Gets a typed delegate from the currently loaded CoreCLR or from a newly created one. 261 | // 262 | // Parameters: 263 | // host_context_handle 264 | // Handle to the initialized host context 265 | // type 266 | // Type of runtime delegate requested 267 | // delegate 268 | // An out parameter that will be assigned the delegate. 269 | // 270 | // Return value: 271 | // The error code result. 272 | // 273 | // If the host_context_handle was initialized using hostfxr_initialize_for_runtime_config, 274 | // then all delegate types are supported. 275 | // If the host_context_handle was initialized using hostfxr_initialize_for_dotnet_command_line, 276 | // then only the following delegate types are currently supported: 277 | // hdt_load_assembly_and_get_function_pointer 278 | // hdt_get_function_pointer 279 | // 280 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_get_runtime_delegate_fn)( 281 | const hostfxr_handle host_context_handle, 282 | enum hostfxr_delegate_type type, 283 | /*out*/ void **delegate); 284 | 285 | // 286 | // Closes an initialized host context 287 | // 288 | // Parameters: 289 | // host_context_handle 290 | // Handle to the initialized host context 291 | // 292 | // Return value: 293 | // The error code result. 294 | // 295 | typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_close_fn)(const hostfxr_handle host_context_handle); 296 | 297 | struct hostfxr_dotnet_environment_sdk_info 298 | { 299 | size_t size; 300 | const char_t* version; 301 | const char_t* path; 302 | }; 303 | 304 | struct hostfxr_dotnet_environment_framework_info 305 | { 306 | size_t size; 307 | const char_t* name; 308 | const char_t* version; 309 | const char_t* path; 310 | }; 311 | 312 | struct hostfxr_dotnet_environment_info 313 | { 314 | size_t size; 315 | 316 | const char_t* hostfxr_version; 317 | const char_t* hostfxr_commit_hash; 318 | 319 | size_t sdk_count; 320 | const struct hostfxr_dotnet_environment_sdk_info* sdks; 321 | 322 | size_t framework_count; 323 | const struct hostfxr_dotnet_environment_framework_info* frameworks; 324 | }; 325 | 326 | typedef void(HOSTFXR_CALLTYPE* hostfxr_get_dotnet_environment_info_result_fn)( 327 | const struct hostfxr_dotnet_environment_info* info, 328 | void* result_context); 329 | 330 | // 331 | // Returns available SDKs and frameworks. 332 | // 333 | // Resolves the existing SDKs and frameworks from a dotnet root directory (if 334 | // any), or the global default location. If multi-level lookup is enabled and 335 | // the dotnet root location is different than the global location, the SDKs and 336 | // frameworks will be enumerated from both locations. 337 | // 338 | // The SDKs are sorted in ascending order by version, multi-level lookup 339 | // locations are put before private ones. 340 | // 341 | // The frameworks are sorted in ascending order by name followed by version, 342 | // multi-level lookup locations are put before private ones. 343 | // 344 | // Parameters: 345 | // dotnet_root 346 | // The path to a directory containing a dotnet executable. 347 | // 348 | // reserved 349 | // Reserved for future parameters. 350 | // 351 | // result 352 | // Callback invoke to return the list of SDKs and frameworks. 353 | // Structs and their elements are valid for the duration of the call. 354 | // 355 | // result_context 356 | // Additional context passed to the result callback. 357 | // 358 | // Return value: 359 | // 0 on success, otherwise failure. 360 | // 361 | // String encoding: 362 | // Windows - UTF-16 (pal::char_t is 2 byte wchar_t) 363 | // Non-Windows - UTF-8 (pal::char_t is 1 byte char) 364 | // 365 | typedef int32_t(HOSTFXR_CALLTYPE* hostfxr_get_dotnet_environment_info_fn)( 366 | const char_t* dotnet_root, 367 | void* reserved, 368 | hostfxr_get_dotnet_environment_info_result_fn result, 369 | void* result_context); 370 | 371 | struct hostfxr_framework_result 372 | { 373 | size_t size; 374 | const char_t* name; 375 | const char_t* requested_version; 376 | const char_t* resolved_version; 377 | const char_t* resolved_path; 378 | }; 379 | 380 | struct hostfxr_resolve_frameworks_result 381 | { 382 | size_t size; 383 | 384 | size_t resolved_count; 385 | const struct hostfxr_framework_result* resolved_frameworks; 386 | 387 | size_t unresolved_count; 388 | const struct hostfxr_framework_result* unresolved_frameworks; 389 | }; 390 | 391 | typedef void (HOSTFXR_CALLTYPE* hostfxr_resolve_frameworks_result_fn)( 392 | const struct hostfxr_resolve_frameworks_result* result, 393 | void* result_context); 394 | 395 | // 396 | // Resolves frameworks for a runtime config 397 | // 398 | // Parameters: 399 | // runtime_config_path 400 | // Path to the .runtimeconfig.json file 401 | // parameters 402 | // Optional. Additional parameters for initialization. 403 | // If null or dotnet_root is null, the root corresponding to the running hostfx is used. 404 | // callback 405 | // Optional. Result callback invoked with result of the resolution. 406 | // Structs and their elements are valid for the duration of the call. 407 | // result_context 408 | // Optional. Additional context passed to the result callback. 409 | // 410 | // Return value: 411 | // 0 on success, otherwise failure. 412 | // 413 | // String encoding: 414 | // Windows - UTF-16 (pal::char_t is 2-byte wchar_t) 415 | // Non-Windows - UTF-8 (pal::char_t is 1-byte char) 416 | // 417 | typedef int32_t(HOSTFXR_CALLTYPE* hostfxr_resolve_frameworks_for_runtime_config_fn)( 418 | const char_t* runtime_config_path, 419 | /*opt*/ const struct hostfxr_initialize_parameters* parameters, 420 | /*opt*/ hostfxr_resolve_frameworks_result_fn callback, 421 | /*opt*/ void* result_context); 422 | 423 | #ifdef __cplusplus 424 | } 425 | #endif // __cplusplus 426 | 427 | #endif // HAVE_HOSTFXR_H 428 | -------------------------------------------------------------------------------- /Bootstrapper/src/library.cpp: -------------------------------------------------------------------------------- 1 | #ifdef _WIN32 2 | #define EXPORT __declspec(dllexport) 3 | #include 4 | #else 5 | #define EXPORT __attribute__((visibility("default"))) 6 | #include 7 | #include 8 | #endif 9 | 10 | /// This class helps to manage shared libraries 11 | class Module { 12 | public: 13 | static void *getBaseAddress(const char *library) { 14 | #ifdef _WIN32 15 | auto base = GetModuleHandleA(library); 16 | #else 17 | auto base = dlopen(library, RTLD_LAZY); 18 | #endif 19 | return reinterpret_cast(base); 20 | } 21 | 22 | static void *getExportByName(void *module, const char *name) { 23 | #ifdef _WIN32 24 | auto address = GetProcAddress((HMODULE) module, name); 25 | #else 26 | auto address = dlsym(module, name); 27 | #endif 28 | return reinterpret_cast(address); 29 | } 30 | 31 | template 32 | static T getFunctionByName(void *module, const char *name) { 33 | return reinterpret_cast(getExportByName(module, name)); 34 | } 35 | }; 36 | 37 | #include 38 | #include 39 | 40 | /// This enums represents possible errors to hide it from others 41 | /// useful for debugging 42 | enum class InitializeResult : uint32_t { 43 | Success, 44 | HostFxrLoadError, 45 | InitializeRuntimeConfigError, 46 | GetRuntimeDelegateError, 47 | EntryPointError, 48 | }; 49 | 50 | extern "C" EXPORT InitializeResult bootstrapper_load_assembly( 51 | const char_t *runtime_config_path, 52 | const char_t *assembly_path, 53 | const char_t *type_name, 54 | const char_t *method_name 55 | ) { 56 | /// Get module base address 57 | #ifdef _WIN32 58 | auto libraryName = "hostfxr.dll"; 59 | #else 60 | auto libraryName = "libhostfxr.so"; 61 | #endif 62 | void *module = Module::getBaseAddress(libraryName); 63 | if (!module) { 64 | return InitializeResult::HostFxrLoadError; 65 | } 66 | 67 | /// Obtaining useful exports 68 | auto hostfxr_initialize_for_runtime_config_fptr = 69 | Module::getFunctionByName(module, "hostfxr_initialize_for_runtime_config"); 70 | 71 | auto hostfxr_get_runtime_delegate_fptr = 72 | Module::getFunctionByName(module, "hostfxr_get_runtime_delegate"); 73 | 74 | auto hostfxr_close_fptr = 75 | Module::getFunctionByName(module, "hostfxr_close"); 76 | 77 | /// Load runtime config 78 | hostfxr_handle ctx = nullptr; 79 | int rc = hostfxr_initialize_for_runtime_config_fptr(runtime_config_path, nullptr, &ctx); 80 | 81 | /// Success_HostAlreadyInitialized = 0x00000001 82 | /// @see https://github.com/dotnet/runtime/blob/main/docs/design/features/host-error-codes.md 83 | if (rc != 1 || ctx == nullptr) { 84 | hostfxr_close_fptr(ctx); 85 | return InitializeResult::InitializeRuntimeConfigError; 86 | } 87 | 88 | /// From docs: native function pointer to the requested runtime functionality 89 | void *delegate = nullptr; 90 | int ret = hostfxr_get_runtime_delegate_fptr(ctx, hostfxr_delegate_type::hdt_load_assembly_and_get_function_pointer, 91 | &delegate); 92 | 93 | if (ret != 0 || delegate == nullptr) { 94 | return InitializeResult::GetRuntimeDelegateError; 95 | } 96 | 97 | /// `void *` -> `load_assembly_and_get_function_pointer_fn`, undocumented??? 98 | auto load_assembly_fptr = reinterpret_cast(delegate); 99 | 100 | typedef void (CORECLR_DELEGATE_CALLTYPE *custom_entry_point_fn)(); 101 | custom_entry_point_fn custom = nullptr; 102 | 103 | ret = load_assembly_fptr(assembly_path, type_name, method_name, UNMANAGEDCALLERSONLY_METHOD, nullptr, 104 | (void **) &custom); 105 | 106 | if (ret != 0 || custom == nullptr) { 107 | return InitializeResult::EntryPointError; 108 | } 109 | 110 | custom(); 111 | 112 | hostfxr_close_fptr(ctx); 113 | 114 | return InitializeResult::Success; 115 | } 116 | 117 | #ifndef _WIN32 118 | std::string getEnvVar(const char *name) { 119 | auto val = std::getenv(name); 120 | return val == nullptr ? std::string() : std::string(val); 121 | } 122 | 123 | __attribute__((constructor)) 124 | void initialize_library() { 125 | auto runtime_config_path = getEnvVar("RUNTIME_CONFIG_PATH"); 126 | auto assembly_path = getEnvVar("ASSEMBLY_PATH"); 127 | auto type_name = getEnvVar("TYPE_NAME"); 128 | auto method_name = getEnvVar("METHOD_NAME"); 129 | 130 | if (!runtime_config_path.empty() && !assembly_path.empty() && !type_name.empty() && !method_name.empty()) { 131 | std::thread thread([=] { 132 | sleep(1); 133 | auto ret = bootstrapper_load_assembly( 134 | runtime_config_path.c_str(), 135 | assembly_path.c_str(), 136 | type_name.c_str(), 137 | method_name.c_str() 138 | ); 139 | printf("[+] api.inject() => %d\n", (uint32_t) ret); 140 | }); 141 | thread.detach(); 142 | } 143 | } 144 | #endif 145 | -------------------------------------------------------------------------------- /DemoApplication/.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | dist 3 | */bin 4 | */obj 5 | -------------------------------------------------------------------------------- /DemoApplication/DemoApplication.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.11.35222.181 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DemoApplication", "DemoApplication\DemoApplication.csproj", "{1CF03031-3FF7-43CD-938A-A2AACA5BCB26}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {1CF03031-3FF7-43CD-938A-A2AACA5BCB26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {1CF03031-3FF7-43CD-938A-A2AACA5BCB26}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {1CF03031-3FF7-43CD-938A-A2AACA5BCB26}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {1CF03031-3FF7-43CD-938A-A2AACA5BCB26}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {BF70B7B2-46B7-4831-9DBC-0CFFDE39916E} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /DemoApplication/DemoApplication/DemoApplication.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /DemoApplication/DemoApplication/Program.cs: -------------------------------------------------------------------------------- 1 | namespace DemoApplication 2 | { 3 | internal class Program 4 | { 5 | static void Main() 6 | { 7 | int i = 0; 8 | while (i < 30) 9 | { 10 | F(i++); 11 | Thread.Sleep(1000); 12 | } 13 | } 14 | 15 | static void F(int i) 16 | { 17 | Console.WriteLine($"Number: {i}"); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /DemoApplication/build.bat: -------------------------------------------------------------------------------- 1 | dotnet publish -c Release -r win-x64 -p:PublishDir="%cd%/dist" --self-contained 2 | -------------------------------------------------------------------------------- /DemoApplication/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | dotnet publish -c Release -r linux-x64 -p:PublishDir="$(pwd)/dist" --self-contained 4 | -------------------------------------------------------------------------------- /DemoApplication/clean.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set PROJECT_NAME=DemoApplication 4 | set DIRECTORIES=dist .vs %PROJECT_NAME%\bin %PROJECT_NAME%\obj 5 | 6 | for %%d in (%DIRECTORIES%) do ( 7 | if exist %%d ( 8 | del /s /f /q %%d\*.* 9 | for /f %%f in ('dir /ad /b %%d\') do rd /s /q %%d\%%f 10 | rd %%d 11 | ) 12 | ) 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### net-core-injector 2 | 3 | [![Build Status](https://github.com/StackOverflowExcept1on/net-core-injector/actions/workflows/ci.yml/badge.svg)](https://github.com/StackOverflowExcept1on/net-core-injector/actions/workflows/ci.yml) 4 | 5 | In the following GIF, you can see how the code on the right intercepts the `static void F(int i)` function. 6 | After injecting, the original program starts outputting `1337` to the console instead of the default behavior. 7 | 8 | ![banner](https://i.imgur.com/PzaC0br.gif) 9 | 10 | CLI tool that can replace C# methods in .NET Core applications 11 | 12 | ### Requirements 13 | 14 | - C++ & C# 15 | - Linux: g++, .NET 8: https://dotnet.microsoft.com/en-us/download/dotnet/8.0 16 | - Windows: Visual Studio 2022 with installed C++ & C# build tools: https://visualstudio.microsoft.com/en/vs/ 17 | - Node.js: https://nodejs.org/en/download/ 18 | - frida: https://frida.re 19 | 20 | ### Building 21 | 22 | Open command line and run this script 23 | 24 | - `_build.sh` on Linux 25 | - `_build.bat` on Windows 26 | 27 | It will build 28 | 29 | - Node.js package [net-core-injector](package.json) - DLL-injector written in TypeScript 30 | - [Bootstrapper](Bootstrapper) - helper native library written in C++ to interact with .NET Core runtime 31 | - [DemoApplication](DemoApplication) - test application to demonstrate how it works 32 | - [RuntimePatcher](RuntimePatcher) - code that attaches to [DemoApplication](DemoApplication) 33 | 34 | ### Running 35 | 36 | This script should produce output like the GIF above 37 | 38 | - `_run.sh` on Linux 39 | 40 | Note: If you want to attach to an existing process on Linux, this requires root privileges. In this case, use 41 | `_run.sh -a` (attach). 42 | 43 | - `_run.bat` on Windows 44 | 45 | ### Internal documentation 46 | 47 | It's mostly based on Microsoft documentation: 48 | [Write a custom .NET host to control the .NET runtime from your native code](https://learn.microsoft.com/en-us/dotnet/core/tutorials/netcore-hosting) 49 | 50 | TL;DR: each process that runs on .NET Core uses `hostfxr.dll` or `libhostfxr.so`. This library is loaded in its memory. 51 | 52 | To load a custom C# assembly (also known as a DLL), you need to manipulate with `hostfxr` first. 53 | I did it in [`Bootstrapper/src/library.cpp`](Bootstrapper/src/library.cpp). 54 | 55 | [`net-core-injector/src/main.ts`](src/main.ts) injects `Bootstrapper.dll` into C# process and loads custom assembly 56 | 57 | The following command runs `DemoApplication.exe` on another thread and injects code. 58 | 59 | ``` 60 | start DemoApplication\dist\DemoApplication.exe 61 | 62 | npm start -- inject ^ 63 | DemoApplication.exe ^ 64 | Bootstrapper\build\Release\Bootstrapper.dll ^ 65 | RuntimePatcher\dist\RuntimePatcher.runtimeconfig.json ^ 66 | RuntimePatcher\dist\RuntimePatcher.dll ^ 67 | "RuntimePatcher.Main, RuntimePatcher" "InitializePatches" 68 | ``` 69 | 70 | Then the execution happens in this order: 71 | 72 | 1. get into `DemoApplication.exe` process memory via DLL-injection of `Bootstrapper.dll` 73 | 2. call native C++ code 74 | ```cpp 75 | bootstrapper_load_assembly( 76 | /*runtime_config_path = */"RuntimePatcher\\dist\\RuntimePatcher.runtimeconfig.json", 77 | /*assembly_path = */"RuntimePatcher\\dist\\RuntimePatcher.dll", 78 | /*type_name = */"RuntimePatcher.Main, RuntimePatcher", 79 | /*method_name = */"InitializePatches" 80 | ) 81 | ``` 82 | 3. [`RuntimePatcher/Lib.cs`](RuntimePatcher/RuntimePatcher/Lib.cs) attaches to code of `DemoApplication.exe` 83 | 84 | ### Application in real world 85 | 86 | I injected my DLL into the GitHub Actions security system and received money and a t-shirt from HackerOne 87 | 88 | Also see: https://github.com/StackOverflowExcept1on/how-to-hack-github-actions 89 | 90 | You can use this to mod games written in C# or to patch any software 91 | 92 | ### TODO 93 | 94 | - I don't have macOS device so it's supported for now. External contributors are welcome. 95 | -------------------------------------------------------------------------------- /RuntimePatcher/.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | dist 3 | */bin 4 | */obj 5 | -------------------------------------------------------------------------------- /RuntimePatcher/RuntimePatcher.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.11.35222.181 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RuntimePatcher", "RuntimePatcher\RuntimePatcher.csproj", "{B262C52E-ADBE-4548-8B9B-BDE4A26A67F6}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {B262C52E-ADBE-4548-8B9B-BDE4A26A67F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {B262C52E-ADBE-4548-8B9B-BDE4A26A67F6}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {B262C52E-ADBE-4548-8B9B-BDE4A26A67F6}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {B262C52E-ADBE-4548-8B9B-BDE4A26A67F6}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {3B731D80-E164-4B66-B5CB-F96F42D7C6D6} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /RuntimePatcher/RuntimePatcher/Lib.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using System.Reflection; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace RuntimePatcher 6 | { 7 | public class Main 8 | { 9 | private static Harmony? harmony; 10 | 11 | [UnmanagedCallersOnly] 12 | public static void InitializePatches() 13 | { 14 | Console.WriteLine("Injected!"); 15 | 16 | harmony = new Harmony("com.example.patch"); 17 | harmony.PatchAll(typeof(Main).Assembly); 18 | } 19 | } 20 | 21 | [HarmonyPatch] 22 | public class ProgramPatches 23 | { 24 | static MethodBase TargetMethod() 25 | { 26 | return AccessTools.Method(AccessTools.TypeByName("DemoApplication.Program"), "F"); 27 | } 28 | 29 | [HarmonyPrefix] 30 | static void F(ref int i) 31 | { 32 | i = 1337; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /RuntimePatcher/RuntimePatcher/RuntimePatcher.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /RuntimePatcher/build.bat: -------------------------------------------------------------------------------- 1 | dotnet publish -c Release -p:PublishDir="%cd%/dist" 2 | -------------------------------------------------------------------------------- /RuntimePatcher/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | dotnet publish -c Release -p:PublishDir="$(pwd)/dist" 4 | -------------------------------------------------------------------------------- /RuntimePatcher/clean.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set PROJECT_NAME=RuntimePatcher 4 | set DIRECTORIES=dist .vs %PROJECT_NAME%\bin %PROJECT_NAME%\obj 5 | 6 | for %%d in (%DIRECTORIES%) do ( 7 | if exist %%d ( 8 | del /s /f /q %%d\*.* 9 | for /f %%f in ('dir /ad /b %%d\') do rd /s /q %%d\%%f 10 | rd %%d 11 | ) 12 | ) 13 | -------------------------------------------------------------------------------- /_build.bat: -------------------------------------------------------------------------------- 1 | start npm install 2 | 3 | cd Bootstrapper 4 | call build.bat 5 | cd .. 6 | 7 | cd DemoApplication 8 | call build.bat 9 | cd .. 10 | 11 | cd RuntimePatcher 12 | call build.bat 13 | cd .. 14 | -------------------------------------------------------------------------------- /_build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | npm install 5 | 6 | cd Bootstrapper 7 | ./build.sh 8 | cd .. 9 | 10 | cd DemoApplication 11 | ./build.sh 12 | cd .. 13 | 14 | cd RuntimePatcher 15 | ./build.sh 16 | cd .. 17 | -------------------------------------------------------------------------------- /_run.bat: -------------------------------------------------------------------------------- 1 | start DemoApplication\dist\DemoApplication.exe 2 | npm start -- inject ^ 3 | DemoApplication.exe ^ 4 | Bootstrapper\build\Release\Bootstrapper.dll ^ 5 | RuntimePatcher\dist\RuntimePatcher.runtimeconfig.json ^ 6 | RuntimePatcher\dist\RuntimePatcher.dll ^ 7 | "RuntimePatcher.Main, RuntimePatcher" "InitializePatches" 8 | -------------------------------------------------------------------------------- /_run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | while getopts "a" OPTION 2> /dev/null; do 5 | case ${OPTION} in 6 | a) 7 | DO_ATTACH="yes" 8 | ;; 9 | \?) 10 | break 11 | ;; 12 | esac 13 | done 14 | 15 | if [ "$DO_ATTACH" == "yes" ]; then 16 | set -m 17 | sudo sysctl kernel.yama.ptrace_scope=0 18 | 19 | ./DemoApplication/dist/DemoApplication & 20 | npm start -- inject \ 21 | DemoApplication \ 22 | Bootstrapper/build/libBootstrapper.so \ 23 | RuntimePatcher/dist/RuntimePatcher.runtimeconfig.json \ 24 | RuntimePatcher/dist/RuntimePatcher.dll \ 25 | "RuntimePatcher.Main, RuntimePatcher" \ 26 | "InitializePatches" 27 | fg %1 28 | else 29 | LD_PRELOAD=./Bootstrapper/build/libBootstrapper.so \ 30 | RUNTIME_CONFIG_PATH="$(pwd)/RuntimePatcher/dist/RuntimePatcher.runtimeconfig.json" \ 31 | ASSEMBLY_PATH="$(pwd)/RuntimePatcher/dist/RuntimePatcher.dll" \ 32 | TYPE_NAME="RuntimePatcher.Main, RuntimePatcher" \ 33 | METHOD_NAME="InitializePatches" \ 34 | ./DemoApplication/dist/DemoApplication 35 | fi 36 | -------------------------------------------------------------------------------- /assets/banner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StackOverflowExcept1on/net-core-injector/f62966f3c7163f4faef570f4a871f9ccd2b6be95/assets/banner.gif -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "net-core-injector", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "net-core-injector", 9 | "version": "1.0.0", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "@tsconfig/recommended": "^1.0.8", 13 | "@types/frida-gum": "^18.7.1", 14 | "@types/node": "^22.10.1", 15 | "@types/yargs": "^17.0.33", 16 | "frida": "^16.4.10", 17 | "ts-node": "^10.9.2", 18 | "typescript": "^5.7.2", 19 | "yargs": "^17.7.2" 20 | } 21 | }, 22 | "node_modules/@cspotcode/source-map-support": { 23 | "version": "0.8.1", 24 | "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", 25 | "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", 26 | "dev": true, 27 | "license": "MIT", 28 | "dependencies": { 29 | "@jridgewell/trace-mapping": "0.3.9" 30 | }, 31 | "engines": { 32 | "node": ">=12" 33 | } 34 | }, 35 | "node_modules/@jridgewell/resolve-uri": { 36 | "version": "3.1.2", 37 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 38 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 39 | "dev": true, 40 | "license": "MIT", 41 | "engines": { 42 | "node": ">=6.0.0" 43 | } 44 | }, 45 | "node_modules/@jridgewell/sourcemap-codec": { 46 | "version": "1.5.0", 47 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 48 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 49 | "dev": true, 50 | "license": "MIT" 51 | }, 52 | "node_modules/@jridgewell/trace-mapping": { 53 | "version": "0.3.9", 54 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", 55 | "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", 56 | "dev": true, 57 | "license": "MIT", 58 | "dependencies": { 59 | "@jridgewell/resolve-uri": "^3.0.3", 60 | "@jridgewell/sourcemap-codec": "^1.4.10" 61 | } 62 | }, 63 | "node_modules/@tsconfig/node10": { 64 | "version": "1.0.11", 65 | "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", 66 | "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", 67 | "dev": true, 68 | "license": "MIT" 69 | }, 70 | "node_modules/@tsconfig/node12": { 71 | "version": "1.0.11", 72 | "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", 73 | "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", 74 | "dev": true, 75 | "license": "MIT" 76 | }, 77 | "node_modules/@tsconfig/node14": { 78 | "version": "1.0.3", 79 | "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", 80 | "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", 81 | "dev": true, 82 | "license": "MIT" 83 | }, 84 | "node_modules/@tsconfig/node16": { 85 | "version": "1.0.4", 86 | "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", 87 | "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", 88 | "dev": true, 89 | "license": "MIT" 90 | }, 91 | "node_modules/@tsconfig/recommended": { 92 | "version": "1.0.8", 93 | "resolved": "https://registry.npmjs.org/@tsconfig/recommended/-/recommended-1.0.8.tgz", 94 | "integrity": "sha512-TotjFaaXveVUdsrXCdalyF6E5RyG6+7hHHQVZonQtdlk1rJZ1myDIvPUUKPhoYv+JAzThb2lQJh9+9ZfF46hsA==", 95 | "dev": true, 96 | "license": "MIT" 97 | }, 98 | "node_modules/@types/frida-gum": { 99 | "version": "18.7.1", 100 | "resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-18.7.1.tgz", 101 | "integrity": "sha512-++7xogrG/jWdgC2gEeK8Q2tVTcycWXsFHhGaEa/TfY8u11UTUsn9dF+nr3Lo1rUnFGZssKDhqV4vsHOHgsWiLQ==", 102 | "dev": true, 103 | "license": "MIT" 104 | }, 105 | "node_modules/@types/node": { 106 | "version": "22.10.1", 107 | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz", 108 | "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==", 109 | "dev": true, 110 | "license": "MIT", 111 | "dependencies": { 112 | "undici-types": "~6.20.0" 113 | } 114 | }, 115 | "node_modules/@types/yargs": { 116 | "version": "17.0.33", 117 | "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", 118 | "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", 119 | "dev": true, 120 | "license": "MIT", 121 | "dependencies": { 122 | "@types/yargs-parser": "*" 123 | } 124 | }, 125 | "node_modules/@types/yargs-parser": { 126 | "version": "21.0.3", 127 | "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", 128 | "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", 129 | "dev": true, 130 | "license": "MIT" 131 | }, 132 | "node_modules/acorn": { 133 | "version": "8.12.1", 134 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", 135 | "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", 136 | "dev": true, 137 | "license": "MIT", 138 | "bin": { 139 | "acorn": "bin/acorn" 140 | }, 141 | "engines": { 142 | "node": ">=0.4.0" 143 | } 144 | }, 145 | "node_modules/acorn-walk": { 146 | "version": "8.3.3", 147 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", 148 | "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", 149 | "dev": true, 150 | "license": "MIT", 151 | "dependencies": { 152 | "acorn": "^8.11.0" 153 | }, 154 | "engines": { 155 | "node": ">=0.4.0" 156 | } 157 | }, 158 | "node_modules/ansi-regex": { 159 | "version": "5.0.1", 160 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 161 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 162 | "dev": true, 163 | "license": "MIT", 164 | "engines": { 165 | "node": ">=8" 166 | } 167 | }, 168 | "node_modules/ansi-styles": { 169 | "version": "4.3.0", 170 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 171 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 172 | "dev": true, 173 | "license": "MIT", 174 | "dependencies": { 175 | "color-convert": "^2.0.1" 176 | }, 177 | "engines": { 178 | "node": ">=8" 179 | }, 180 | "funding": { 181 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 182 | } 183 | }, 184 | "node_modules/arg": { 185 | "version": "4.1.3", 186 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", 187 | "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", 188 | "dev": true, 189 | "license": "MIT" 190 | }, 191 | "node_modules/balanced-match": { 192 | "version": "1.0.2", 193 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 194 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 195 | "dev": true, 196 | "license": "MIT" 197 | }, 198 | "node_modules/base64-js": { 199 | "version": "1.5.1", 200 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 201 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 202 | "dev": true, 203 | "funding": [ 204 | { 205 | "type": "github", 206 | "url": "https://github.com/sponsors/feross" 207 | }, 208 | { 209 | "type": "patreon", 210 | "url": "https://www.patreon.com/feross" 211 | }, 212 | { 213 | "type": "consulting", 214 | "url": "https://feross.org/support" 215 | } 216 | ], 217 | "license": "MIT" 218 | }, 219 | "node_modules/bindings": { 220 | "version": "1.5.0", 221 | "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", 222 | "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", 223 | "dev": true, 224 | "license": "MIT", 225 | "dependencies": { 226 | "file-uri-to-path": "1.0.0" 227 | } 228 | }, 229 | "node_modules/bl": { 230 | "version": "4.1.0", 231 | "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", 232 | "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", 233 | "dev": true, 234 | "license": "MIT", 235 | "dependencies": { 236 | "buffer": "^5.5.0", 237 | "inherits": "^2.0.4", 238 | "readable-stream": "^3.4.0" 239 | } 240 | }, 241 | "node_modules/brace-expansion": { 242 | "version": "2.0.1", 243 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 244 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 245 | "dev": true, 246 | "license": "MIT", 247 | "dependencies": { 248 | "balanced-match": "^1.0.0" 249 | } 250 | }, 251 | "node_modules/buffer": { 252 | "version": "5.7.1", 253 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", 254 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", 255 | "dev": true, 256 | "funding": [ 257 | { 258 | "type": "github", 259 | "url": "https://github.com/sponsors/feross" 260 | }, 261 | { 262 | "type": "patreon", 263 | "url": "https://www.patreon.com/feross" 264 | }, 265 | { 266 | "type": "consulting", 267 | "url": "https://feross.org/support" 268 | } 269 | ], 270 | "license": "MIT", 271 | "dependencies": { 272 | "base64-js": "^1.3.1", 273 | "ieee754": "^1.1.13" 274 | } 275 | }, 276 | "node_modules/chownr": { 277 | "version": "1.1.4", 278 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", 279 | "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", 280 | "dev": true, 281 | "license": "ISC" 282 | }, 283 | "node_modules/cliui": { 284 | "version": "8.0.1", 285 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", 286 | "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", 287 | "dev": true, 288 | "license": "ISC", 289 | "dependencies": { 290 | "string-width": "^4.2.0", 291 | "strip-ansi": "^6.0.1", 292 | "wrap-ansi": "^7.0.0" 293 | }, 294 | "engines": { 295 | "node": ">=12" 296 | } 297 | }, 298 | "node_modules/color-convert": { 299 | "version": "2.0.1", 300 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 301 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 302 | "dev": true, 303 | "license": "MIT", 304 | "dependencies": { 305 | "color-name": "~1.1.4" 306 | }, 307 | "engines": { 308 | "node": ">=7.0.0" 309 | } 310 | }, 311 | "node_modules/color-name": { 312 | "version": "1.1.4", 313 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 314 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 315 | "dev": true, 316 | "license": "MIT" 317 | }, 318 | "node_modules/create-require": { 319 | "version": "1.1.1", 320 | "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", 321 | "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", 322 | "dev": true, 323 | "license": "MIT" 324 | }, 325 | "node_modules/decompress-response": { 326 | "version": "6.0.0", 327 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", 328 | "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", 329 | "dev": true, 330 | "license": "MIT", 331 | "dependencies": { 332 | "mimic-response": "^3.1.0" 333 | }, 334 | "engines": { 335 | "node": ">=10" 336 | }, 337 | "funding": { 338 | "url": "https://github.com/sponsors/sindresorhus" 339 | } 340 | }, 341 | "node_modules/deep-extend": { 342 | "version": "0.6.0", 343 | "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", 344 | "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", 345 | "dev": true, 346 | "license": "MIT", 347 | "engines": { 348 | "node": ">=4.0.0" 349 | } 350 | }, 351 | "node_modules/detect-libc": { 352 | "version": "2.0.3", 353 | "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", 354 | "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", 355 | "dev": true, 356 | "license": "Apache-2.0", 357 | "engines": { 358 | "node": ">=8" 359 | } 360 | }, 361 | "node_modules/diff": { 362 | "version": "4.0.2", 363 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 364 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 365 | "dev": true, 366 | "license": "BSD-3-Clause", 367 | "engines": { 368 | "node": ">=0.3.1" 369 | } 370 | }, 371 | "node_modules/emoji-regex": { 372 | "version": "8.0.0", 373 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 374 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 375 | "dev": true, 376 | "license": "MIT" 377 | }, 378 | "node_modules/end-of-stream": { 379 | "version": "1.4.4", 380 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 381 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 382 | "dev": true, 383 | "license": "MIT", 384 | "dependencies": { 385 | "once": "^1.4.0" 386 | } 387 | }, 388 | "node_modules/escalade": { 389 | "version": "3.2.0", 390 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", 391 | "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", 392 | "dev": true, 393 | "license": "MIT", 394 | "engines": { 395 | "node": ">=6" 396 | } 397 | }, 398 | "node_modules/expand-template": { 399 | "version": "2.0.3", 400 | "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", 401 | "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", 402 | "dev": true, 403 | "license": "(MIT OR WTFPL)", 404 | "engines": { 405 | "node": ">=6" 406 | } 407 | }, 408 | "node_modules/file-uri-to-path": { 409 | "version": "1.0.0", 410 | "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", 411 | "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", 412 | "dev": true, 413 | "license": "MIT" 414 | }, 415 | "node_modules/frida": { 416 | "version": "16.4.10", 417 | "resolved": "https://registry.npmjs.org/frida/-/frida-16.4.10.tgz", 418 | "integrity": "sha512-EZvXAkO7zaQh8lL3ZPFMgaE1dG92y+RlSohKSaKiEAZ1VbiHfvbeF8nTUG4NzGXjVs+M5HQj3yp1cTkojqGitw==", 419 | "dev": true, 420 | "hasInstallScript": true, 421 | "license": "LGPL-2.0 WITH WxWindows-exception-3.1", 422 | "dependencies": { 423 | "bindings": "^1.5.0", 424 | "minimatch": "^9.0.3", 425 | "nan": "^2.18.0", 426 | "prebuild-install": "^7.1.1" 427 | }, 428 | "engines": { 429 | "node": ">=16 || 14 >=14.17" 430 | } 431 | }, 432 | "node_modules/fs-constants": { 433 | "version": "1.0.0", 434 | "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", 435 | "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", 436 | "dev": true, 437 | "license": "MIT" 438 | }, 439 | "node_modules/get-caller-file": { 440 | "version": "2.0.5", 441 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 442 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 443 | "dev": true, 444 | "license": "ISC", 445 | "engines": { 446 | "node": "6.* || 8.* || >= 10.*" 447 | } 448 | }, 449 | "node_modules/github-from-package": { 450 | "version": "0.0.0", 451 | "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", 452 | "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", 453 | "dev": true, 454 | "license": "MIT" 455 | }, 456 | "node_modules/ieee754": { 457 | "version": "1.2.1", 458 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 459 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 460 | "dev": true, 461 | "funding": [ 462 | { 463 | "type": "github", 464 | "url": "https://github.com/sponsors/feross" 465 | }, 466 | { 467 | "type": "patreon", 468 | "url": "https://www.patreon.com/feross" 469 | }, 470 | { 471 | "type": "consulting", 472 | "url": "https://feross.org/support" 473 | } 474 | ], 475 | "license": "BSD-3-Clause" 476 | }, 477 | "node_modules/inherits": { 478 | "version": "2.0.4", 479 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 480 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 481 | "dev": true, 482 | "license": "ISC" 483 | }, 484 | "node_modules/ini": { 485 | "version": "1.3.8", 486 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", 487 | "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", 488 | "dev": true, 489 | "license": "ISC" 490 | }, 491 | "node_modules/is-fullwidth-code-point": { 492 | "version": "3.0.0", 493 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 494 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 495 | "dev": true, 496 | "license": "MIT", 497 | "engines": { 498 | "node": ">=8" 499 | } 500 | }, 501 | "node_modules/make-error": { 502 | "version": "1.3.6", 503 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", 504 | "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", 505 | "dev": true, 506 | "license": "ISC" 507 | }, 508 | "node_modules/mimic-response": { 509 | "version": "3.1.0", 510 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", 511 | "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", 512 | "dev": true, 513 | "license": "MIT", 514 | "engines": { 515 | "node": ">=10" 516 | }, 517 | "funding": { 518 | "url": "https://github.com/sponsors/sindresorhus" 519 | } 520 | }, 521 | "node_modules/minimatch": { 522 | "version": "9.0.5", 523 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", 524 | "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", 525 | "dev": true, 526 | "license": "ISC", 527 | "dependencies": { 528 | "brace-expansion": "^2.0.1" 529 | }, 530 | "engines": { 531 | "node": ">=16 || 14 >=14.17" 532 | }, 533 | "funding": { 534 | "url": "https://github.com/sponsors/isaacs" 535 | } 536 | }, 537 | "node_modules/minimist": { 538 | "version": "1.2.8", 539 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 540 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 541 | "dev": true, 542 | "license": "MIT", 543 | "funding": { 544 | "url": "https://github.com/sponsors/ljharb" 545 | } 546 | }, 547 | "node_modules/mkdirp-classic": { 548 | "version": "0.5.3", 549 | "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", 550 | "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", 551 | "dev": true, 552 | "license": "MIT" 553 | }, 554 | "node_modules/nan": { 555 | "version": "2.20.0", 556 | "resolved": "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz", 557 | "integrity": "sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==", 558 | "dev": true, 559 | "license": "MIT" 560 | }, 561 | "node_modules/napi-build-utils": { 562 | "version": "1.0.2", 563 | "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", 564 | "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", 565 | "dev": true, 566 | "license": "MIT" 567 | }, 568 | "node_modules/node-abi": { 569 | "version": "3.67.0", 570 | "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.67.0.tgz", 571 | "integrity": "sha512-bLn/fU/ALVBE9wj+p4Y21ZJWYFjUXLXPi/IewyLZkx3ApxKDNBWCKdReeKOtD8dWpOdDCeMyLh6ZewzcLsG2Nw==", 572 | "dev": true, 573 | "license": "MIT", 574 | "dependencies": { 575 | "semver": "^7.3.5" 576 | }, 577 | "engines": { 578 | "node": ">=10" 579 | } 580 | }, 581 | "node_modules/once": { 582 | "version": "1.4.0", 583 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 584 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 585 | "dev": true, 586 | "license": "ISC", 587 | "dependencies": { 588 | "wrappy": "1" 589 | } 590 | }, 591 | "node_modules/prebuild-install": { 592 | "version": "7.1.2", 593 | "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", 594 | "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", 595 | "dev": true, 596 | "license": "MIT", 597 | "dependencies": { 598 | "detect-libc": "^2.0.0", 599 | "expand-template": "^2.0.3", 600 | "github-from-package": "0.0.0", 601 | "minimist": "^1.2.3", 602 | "mkdirp-classic": "^0.5.3", 603 | "napi-build-utils": "^1.0.1", 604 | "node-abi": "^3.3.0", 605 | "pump": "^3.0.0", 606 | "rc": "^1.2.7", 607 | "simple-get": "^4.0.0", 608 | "tar-fs": "^2.0.0", 609 | "tunnel-agent": "^0.6.0" 610 | }, 611 | "bin": { 612 | "prebuild-install": "bin.js" 613 | }, 614 | "engines": { 615 | "node": ">=10" 616 | } 617 | }, 618 | "node_modules/pump": { 619 | "version": "3.0.0", 620 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 621 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 622 | "dev": true, 623 | "license": "MIT", 624 | "dependencies": { 625 | "end-of-stream": "^1.1.0", 626 | "once": "^1.3.1" 627 | } 628 | }, 629 | "node_modules/rc": { 630 | "version": "1.2.8", 631 | "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", 632 | "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", 633 | "dev": true, 634 | "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", 635 | "dependencies": { 636 | "deep-extend": "^0.6.0", 637 | "ini": "~1.3.0", 638 | "minimist": "^1.2.0", 639 | "strip-json-comments": "~2.0.1" 640 | }, 641 | "bin": { 642 | "rc": "cli.js" 643 | } 644 | }, 645 | "node_modules/readable-stream": { 646 | "version": "3.6.2", 647 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", 648 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", 649 | "dev": true, 650 | "license": "MIT", 651 | "dependencies": { 652 | "inherits": "^2.0.3", 653 | "string_decoder": "^1.1.1", 654 | "util-deprecate": "^1.0.1" 655 | }, 656 | "engines": { 657 | "node": ">= 6" 658 | } 659 | }, 660 | "node_modules/require-directory": { 661 | "version": "2.1.1", 662 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 663 | "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", 664 | "dev": true, 665 | "license": "MIT", 666 | "engines": { 667 | "node": ">=0.10.0" 668 | } 669 | }, 670 | "node_modules/safe-buffer": { 671 | "version": "5.2.1", 672 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 673 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 674 | "dev": true, 675 | "funding": [ 676 | { 677 | "type": "github", 678 | "url": "https://github.com/sponsors/feross" 679 | }, 680 | { 681 | "type": "patreon", 682 | "url": "https://www.patreon.com/feross" 683 | }, 684 | { 685 | "type": "consulting", 686 | "url": "https://feross.org/support" 687 | } 688 | ], 689 | "license": "MIT" 690 | }, 691 | "node_modules/semver": { 692 | "version": "7.6.3", 693 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", 694 | "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", 695 | "dev": true, 696 | "license": "ISC", 697 | "bin": { 698 | "semver": "bin/semver.js" 699 | }, 700 | "engines": { 701 | "node": ">=10" 702 | } 703 | }, 704 | "node_modules/simple-concat": { 705 | "version": "1.0.1", 706 | "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", 707 | "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", 708 | "dev": true, 709 | "funding": [ 710 | { 711 | "type": "github", 712 | "url": "https://github.com/sponsors/feross" 713 | }, 714 | { 715 | "type": "patreon", 716 | "url": "https://www.patreon.com/feross" 717 | }, 718 | { 719 | "type": "consulting", 720 | "url": "https://feross.org/support" 721 | } 722 | ], 723 | "license": "MIT" 724 | }, 725 | "node_modules/simple-get": { 726 | "version": "4.0.1", 727 | "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", 728 | "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", 729 | "dev": true, 730 | "funding": [ 731 | { 732 | "type": "github", 733 | "url": "https://github.com/sponsors/feross" 734 | }, 735 | { 736 | "type": "patreon", 737 | "url": "https://www.patreon.com/feross" 738 | }, 739 | { 740 | "type": "consulting", 741 | "url": "https://feross.org/support" 742 | } 743 | ], 744 | "license": "MIT", 745 | "dependencies": { 746 | "decompress-response": "^6.0.0", 747 | "once": "^1.3.1", 748 | "simple-concat": "^1.0.0" 749 | } 750 | }, 751 | "node_modules/string_decoder": { 752 | "version": "1.3.0", 753 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 754 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 755 | "dev": true, 756 | "license": "MIT", 757 | "dependencies": { 758 | "safe-buffer": "~5.2.0" 759 | } 760 | }, 761 | "node_modules/string-width": { 762 | "version": "4.2.3", 763 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 764 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 765 | "dev": true, 766 | "license": "MIT", 767 | "dependencies": { 768 | "emoji-regex": "^8.0.0", 769 | "is-fullwidth-code-point": "^3.0.0", 770 | "strip-ansi": "^6.0.1" 771 | }, 772 | "engines": { 773 | "node": ">=8" 774 | } 775 | }, 776 | "node_modules/strip-ansi": { 777 | "version": "6.0.1", 778 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 779 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 780 | "dev": true, 781 | "license": "MIT", 782 | "dependencies": { 783 | "ansi-regex": "^5.0.1" 784 | }, 785 | "engines": { 786 | "node": ">=8" 787 | } 788 | }, 789 | "node_modules/strip-json-comments": { 790 | "version": "2.0.1", 791 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 792 | "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", 793 | "dev": true, 794 | "license": "MIT", 795 | "engines": { 796 | "node": ">=0.10.0" 797 | } 798 | }, 799 | "node_modules/tar-fs": { 800 | "version": "2.1.1", 801 | "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", 802 | "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", 803 | "dev": true, 804 | "license": "MIT", 805 | "dependencies": { 806 | "chownr": "^1.1.1", 807 | "mkdirp-classic": "^0.5.2", 808 | "pump": "^3.0.0", 809 | "tar-stream": "^2.1.4" 810 | } 811 | }, 812 | "node_modules/tar-stream": { 813 | "version": "2.2.0", 814 | "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", 815 | "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", 816 | "dev": true, 817 | "license": "MIT", 818 | "dependencies": { 819 | "bl": "^4.0.3", 820 | "end-of-stream": "^1.4.1", 821 | "fs-constants": "^1.0.0", 822 | "inherits": "^2.0.3", 823 | "readable-stream": "^3.1.1" 824 | }, 825 | "engines": { 826 | "node": ">=6" 827 | } 828 | }, 829 | "node_modules/ts-node": { 830 | "version": "10.9.2", 831 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", 832 | "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", 833 | "dev": true, 834 | "license": "MIT", 835 | "dependencies": { 836 | "@cspotcode/source-map-support": "^0.8.0", 837 | "@tsconfig/node10": "^1.0.7", 838 | "@tsconfig/node12": "^1.0.7", 839 | "@tsconfig/node14": "^1.0.0", 840 | "@tsconfig/node16": "^1.0.2", 841 | "acorn": "^8.4.1", 842 | "acorn-walk": "^8.1.1", 843 | "arg": "^4.1.0", 844 | "create-require": "^1.1.0", 845 | "diff": "^4.0.1", 846 | "make-error": "^1.1.1", 847 | "v8-compile-cache-lib": "^3.0.1", 848 | "yn": "3.1.1" 849 | }, 850 | "bin": { 851 | "ts-node": "dist/bin.js", 852 | "ts-node-cwd": "dist/bin-cwd.js", 853 | "ts-node-esm": "dist/bin-esm.js", 854 | "ts-node-script": "dist/bin-script.js", 855 | "ts-node-transpile-only": "dist/bin-transpile.js", 856 | "ts-script": "dist/bin-script-deprecated.js" 857 | }, 858 | "peerDependencies": { 859 | "@swc/core": ">=1.2.50", 860 | "@swc/wasm": ">=1.2.50", 861 | "@types/node": "*", 862 | "typescript": ">=2.7" 863 | }, 864 | "peerDependenciesMeta": { 865 | "@swc/core": { 866 | "optional": true 867 | }, 868 | "@swc/wasm": { 869 | "optional": true 870 | } 871 | } 872 | }, 873 | "node_modules/tunnel-agent": { 874 | "version": "0.6.0", 875 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 876 | "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", 877 | "dev": true, 878 | "license": "Apache-2.0", 879 | "dependencies": { 880 | "safe-buffer": "^5.0.1" 881 | }, 882 | "engines": { 883 | "node": "*" 884 | } 885 | }, 886 | "node_modules/typescript": { 887 | "version": "5.7.2", 888 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", 889 | "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", 890 | "dev": true, 891 | "license": "Apache-2.0", 892 | "bin": { 893 | "tsc": "bin/tsc", 894 | "tsserver": "bin/tsserver" 895 | }, 896 | "engines": { 897 | "node": ">=14.17" 898 | } 899 | }, 900 | "node_modules/undici-types": { 901 | "version": "6.20.0", 902 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", 903 | "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", 904 | "dev": true, 905 | "license": "MIT" 906 | }, 907 | "node_modules/util-deprecate": { 908 | "version": "1.0.2", 909 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 910 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 911 | "dev": true, 912 | "license": "MIT" 913 | }, 914 | "node_modules/v8-compile-cache-lib": { 915 | "version": "3.0.1", 916 | "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", 917 | "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", 918 | "dev": true, 919 | "license": "MIT" 920 | }, 921 | "node_modules/wrap-ansi": { 922 | "version": "7.0.0", 923 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 924 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 925 | "dev": true, 926 | "license": "MIT", 927 | "dependencies": { 928 | "ansi-styles": "^4.0.0", 929 | "string-width": "^4.1.0", 930 | "strip-ansi": "^6.0.0" 931 | }, 932 | "engines": { 933 | "node": ">=10" 934 | }, 935 | "funding": { 936 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 937 | } 938 | }, 939 | "node_modules/wrappy": { 940 | "version": "1.0.2", 941 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 942 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 943 | "dev": true, 944 | "license": "ISC" 945 | }, 946 | "node_modules/y18n": { 947 | "version": "5.0.8", 948 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 949 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 950 | "dev": true, 951 | "license": "ISC", 952 | "engines": { 953 | "node": ">=10" 954 | } 955 | }, 956 | "node_modules/yargs": { 957 | "version": "17.7.2", 958 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", 959 | "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", 960 | "dev": true, 961 | "license": "MIT", 962 | "dependencies": { 963 | "cliui": "^8.0.1", 964 | "escalade": "^3.1.1", 965 | "get-caller-file": "^2.0.5", 966 | "require-directory": "^2.1.1", 967 | "string-width": "^4.2.3", 968 | "y18n": "^5.0.5", 969 | "yargs-parser": "^21.1.1" 970 | }, 971 | "engines": { 972 | "node": ">=12" 973 | } 974 | }, 975 | "node_modules/yargs-parser": { 976 | "version": "21.1.1", 977 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", 978 | "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", 979 | "dev": true, 980 | "license": "ISC", 981 | "engines": { 982 | "node": ">=12" 983 | } 984 | }, 985 | "node_modules/yn": { 986 | "version": "3.1.1", 987 | "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", 988 | "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", 989 | "dev": true, 990 | "license": "MIT", 991 | "engines": { 992 | "node": ">=6" 993 | } 994 | } 995 | } 996 | } 997 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "net-core-injector", 3 | "version": "1.0.0", 4 | "description": "CLI tool that can replace C# methods in .NET Core applications", 5 | "main": "src/main.ts", 6 | "scripts": { 7 | "prepare": "tsc", 8 | "start": "ts-node src/main.ts" 9 | }, 10 | "author": "StackOverflowExcept1on", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "@tsconfig/recommended": "^1.0.8", 14 | "@types/frida-gum": "^18.7.1", 15 | "@types/node": "^22.10.1", 16 | "@types/yargs": "^17.0.33", 17 | "frida": "^16.4.10", 18 | "ts-node": "^10.9.2", 19 | "typescript": "^5.7.2", 20 | "yargs": "^17.7.2" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/agent.ts: -------------------------------------------------------------------------------- 1 | rpc.exports = { 2 | inject: (bootstrapper: string, runtime_config_path: string, assembly_path: string, type_name: string, method_name: string): number => { 3 | const bootstrapperModule = Module.load(bootstrapper); 4 | 5 | const functionPointer = Module.getExportByName(bootstrapperModule.name, "bootstrapper_load_assembly"); 6 | const bootstrapper_load_assembly = new NativeFunction(functionPointer, "uint32", ["pointer", "pointer", "pointer", "pointer"]); 7 | 8 | const allocUtfString = Process.platform === "windows" ? Memory.allocUtf16String : Memory.allocUtf8String; 9 | return bootstrapper_load_assembly( 10 | allocUtfString(runtime_config_path), 11 | allocUtfString(assembly_path), 12 | allocUtfString(type_name), 13 | allocUtfString(method_name), 14 | ); 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import yargs from "yargs"; 2 | import * as frida from "frida"; 3 | import * as fs from "fs"; 4 | import * as path from "path"; 5 | 6 | enum InitializeResult { 7 | Success, 8 | HostFxrLoadError, 9 | InitializeRuntimeConfigError, 10 | GetRuntimeDelegateError, 11 | EntryPointError, 12 | } 13 | 14 | yargs(process.argv.slice(2)) 15 | .scriptName("net-core-injector") 16 | .usage("$0 ") 17 | .command("inject ", "inject C# library into process", (yargs) => { 18 | yargs 19 | .positional("process_name", {type: "string"}) 20 | .positional("bootstrapper", {type: "string"}) 21 | .positional("runtime_config_path", {type: "string"}) 22 | .positional("assembly_path", {type: "string"}) 23 | .positional("type_name", {type: "string"}) 24 | .positional("method_name", {type: "string"}) 25 | }, async (argv: any) => { 26 | const session = await frida.attach(argv.process_name); 27 | 28 | const source = fs.readFileSync("dist/agent.js", "utf8"); 29 | 30 | const script = await session.createScript(source); 31 | await script.load(); 32 | 33 | const api: any = script.exports; 34 | const ret = await api.inject( 35 | path.resolve(argv.bootstrapper), 36 | path.resolve(argv.runtime_config_path), 37 | path.resolve(argv.assembly_path), 38 | argv.type_name, 39 | argv.method_name, 40 | ); 41 | 42 | const initialize_result = InitializeResult[ret] ?? "Unknown"; 43 | console.log(`[*] api.inject() => ${ret} (InitializeResult::${initialize_result})`); 44 | 45 | if (ret !== 0) { 46 | console.log(`An error occurred while injection into ${argv.process_name}`); 47 | } 48 | 49 | await script.unload(); 50 | }) 51 | .demandCommand(1) 52 | .help() 53 | .argv; 54 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/recommended/tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "src/**/*" 8 | ] 9 | } 10 | --------------------------------------------------------------------------------