InjectDotnet 0.4.0
Requires NuGet 3.2 or higher.
dotnet add package InjectDotnet --version 0.4.0
NuGet\Install-Package InjectDotnet -Version 0.4.0
<PackageReference Include="InjectDotnet" Version="0.4.0" />
paket add InjectDotnet --version 0.4.0
#r "nuget: InjectDotnet, 0.4.0"
// Install InjectDotnet as a Cake Addin
#addin nuget:?package=InjectDotnet&version=0.4.0
// Install InjectDotnet as a Cake Tool
#tool nuget:?package=InjectDotnet&version=0.4.0
InjectDotnet
Inject a .NET Core dll into a native Win32 or Win64 process. InjectDotnet is a library, not a standalone application. This allows developers/hackers to pass any argument to the injected dll, not just a string. There are two complementary libraries:
- InjectDotnet: Injects a managed dll into a native process.
- InjectDotnet.NativeHelper: Referenced by the injected dll and provides methods for hooking native functions.
Add InjectDotnet to your injector, and add InjectDotnet.NativeHelper to your injected dll.
**IMPORTANT** Your projects myst be configures x64 or x86, not AnyCPU!!
No Unmanaged Libraries
Unlike other dotnet dll injectors, this one does not rely on a native dll to load the runtime in the target process. Loading and executing the injected dll is accomplished by hand-written assembly instructions that are written directly into the target process' memory space and executed.
Inject Into Running Processes
InjectDotnet Supports injecting managed Dlls into running processes using the traditional CreateRemoteThread()
method.
It's as simple as the following example.
var target = Process.GetProcessesByName("target");
target.Inject(
"InjectedDll.runtimeconfig.json",
"InjectedDll.dll",
"InjectedDll.HookDemo, InjectedDll, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"Bootstrap",
"this is an argument passed to the injected dll's Bootstrap() method");
You may optionally wait for bootstrap method to return to receive it's return code, and the injector supports passing structs with additional data to the injected dll (see the samples prokjects).
Injecting into .NET Targets
InjectDotnet supports injecting into managed target processes, but there are some limitations.
- The injected Dll's required frameworks must be compatible with the frameworks loaded by the runtime already in the target process. For instance, you cannot inject a .NET 7 dll into a .NET 6 target process.
- When injected into a .NET Core process, the injected Dll will be loaded into that process' AppDomain.
- You can inject into a .NET Framwork process, but the injected .NET Core Dll cannot access the target's AppDomain.
- Injecting into self-contained apps is supported, but single-file apps are not supported. Self-contained apps are more strict about which frameworks can be loaded. Portable apps can run code from older frameworks, but self-contained apps can only run code from the framework version that published it.
- Injecting into a new managed process at startup is not supported.
If Inject()
fails to load the CLR in the target process, it returns the host fxr error code. Inject()
must be called with waitForReturn: true
for the error code to be returned.
Inject Into a New Process at Startup
InjectDotnet supports injecting managed Dlls at the entry point of a process using its built-in debugger.
It's as simple as the following example.
var debugger = new Debugger("target.exe", arguments: null);
debugger.InjectStartup(
"InjectedDll.runtimeconfig.json",
"InjectedDll.dll",
"InjectedDll.HookDemo, InjectedDll, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"Bootstrap",
"this is an argument passed to the injected dll's Bootstrap() method");
await debugger.ResumeProcessAsync();
The debugger supports all win32 debug events, and you may use them to, for example, receive data from the injected dll via OutputDebugString.
Hooking Native Functions
InjectDotnet.NativeHelper supports three different hooking methods:
Hook Type | Description |
---|---|
ImportHook | Replaces the hooked function's import address table entry in the target module with a pointer to the hooking function. |
JumpHook | Overwrite's the first instruction(s) of the hooked function with a jump to a Trampoline. |
BreakpointHook | Sets a hardware breakpoint at the hooked function's first instruction and uses a vectored exception handler to intercept execution. |
See the samples for useage.
There are two sample projects:
- InjectedDll - A .NET 7.0 dll to be injected into a native process and uses
InjectDotnet.NativeHelper
to hook native functions. - InjectIntoRunning - The program that uses
InjectDotnet
to injectInjectedDll
into HxD.exe and pass it two strings and a png image as arguments. ExecutesInjectedDll.HookDemo.Bootstrap
after injection. - InjectAtStartup - The program that uses
InjectDotnet
to debug HxD.exe and injectInjectedDll
at its entry point. ExecutesInjectedDll.HookDemo.Bootstrap
after injection.
SampleInjected.Program.Bootstrap
loads the two strings and the png image from native memory, frees the native memory, and then opens a System.Windows.Forms.Form
to display the strings and image.
It also hooks the WriteFile
function imported by notepad.exe from kernel32.dll and the CreateFileW
function exported by kernel32.dll.
Debugging Injected Dlls with Visual Studio
Ther are two ways to debug injected .NET dlls in Visual Studio
Method 1: Set a Native Executable as the Debug Target
- In Visual Studio, navigate to the injected dll's properties > Debug > Open debug launch profiles UI
- Create a new "Executable" profile.
- Enter the native executable into which this dll will be injected and any command line arguments. Save.
- Choose the newly-created debug profile and launch the debugger.
- Execute
SampleInjector.exe
to perform the injection
Method 2: Attaching to Injected Process
- Build
SampleInjected
andSampleInjector
targeting the platform of your Windows PC - Start the target native process (notepad.exe in the sample)
- With the
SampleInjected
project open, attach the Visual Studio debugger the target process- Debug > Attach to Process of
Ctrl+Alt+P
- Select the .NET Core Debugger
- Next to "Attach to:", click "Select"
- Select "Debug these code types"
- Choose "Managed (.NET Core, .NET 5+)"
- Choose the target process. (easiest accomplished by clicking "Select Window" and clicking on the target's window)
- Click "Attach"
- Debug > Attach to Process of
- Execute
SampleInjector.exe
to perform the injection
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0-windows7.0 is compatible. net7.0-windows was computed. net8.0-windows was computed. net8.0-windows7.0 is compatible. |
-
net6.0-windows7.0
- No dependencies.
-
net8.0-windows7.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
0.4.0 | 200 | 12/13/2023 |
0.3.3 | 76 | 12/10/2023 |
0.3.2 | 467 | 11/14/2023 |
0.3.1 | 77 | 11/10/2023 |
0.3.0 | 75 | 11/10/2023 |
0.2.1 | 98 | 10/30/2023 |
0.2.0 | 128 | 6/8/2023 |
0.1.2.2 | 116 | 6/8/2023 |
0.1.2.1 | 116 | 6/5/2023 |
0.1.2 | 108 | 6/5/2023 |
0.1.1.2 | 112 | 6/5/2023 |
0.1.1.1 | 109 | 6/5/2023 |
0.1.1 | 107 | 6/5/2023 |
0.1.0 | 111 | 6/4/2023 |