Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Library updates and compat fixes #15

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# http://editorconfig.org
root = true

[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.cs]
csharp_new_line_before_open_brace = all
end_of_line = crlf
154 changes: 154 additions & 0 deletions Source/Reloaded.Injector/CompatUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using Reloaded.Memory;
using Reloaded.Memory.Buffers;
using Reloaded.Memory.Buffers.Structs;
using Reloaded.Memory.Structs;
using Reloaded.Memory.Utilities;
//using static Reloaded.Injector.Kernel32.Kernel32;
using K32 = Reloaded.Memory.Native.Windows.Kernel32;

namespace Reloaded.Injector {
internal static class CompatUtils { //for back compat with other reload modules

public static unsafe long AddBytes(this CircularBuffer buffer, Span<byte> bytes) {
fixed (byte* ptr = bytes) {
return (long)buffer.Add(ptr, (uint)bytes.Length);
}

}
}

public class PrivateMemoryBufferCompat : IDisposable {

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public MemoryAllocation Allocate(Process proc, nuint length, nuint baseStartAddy = 0) {

nuint num = K32.VirtualAllocEx(proc.Handle, baseStartAddy, length, K32.MEM_ALLOCATION_TYPE.MEM_COMMIT | K32.MEM_ALLOCATION_TYPE.MEM_RESERVE, K32.MEM_PROTECTION.PAGE_EXECUTE_READWRITE);
if (num != 0) {
return new MemoryAllocation(num, length);
}
throw new Exception();

}



public PrivateMemoryBufferCompat(Process proc, nuint size, bool isPrivateAlloc = false) {
IsPrivateAlloc = isPrivateAlloc;
memory = new ExternalMemory(proc);
if (!IsPrivateAlloc)
alloc = memory.Allocate(size);
else
palloc = Buffers.AllocatePrivateMemory(new Reloaded.Memory.Buffers.Structs.Params.BufferAllocatorSettings { TargetProcess = proc, MinAddress = Shellcode.minimumAddress, MaxAddress = (nuint)UInt64.MaxValue, Size = (uint)size, RetryCount = Shellcode.retryCount });
}
private bool IsPrivateAlloc;
public nuint BaseAddress => IsPrivateAlloc ? palloc.BaseAddress : alloc.Address;
public nuint AllocSize => IsPrivateAlloc ? palloc.Size : alloc.Length;
private MemoryAllocation alloc;
private PrivateAllocation palloc;
//private PrivateAllocation memory;
private ExternalMemory memory;
private bool disposedValue;
private nuint nextFreeBlockOffset = 0;

protected virtual void Dispose(bool disposing) {
if (!disposedValue) {
if (disposing) {

}
if (IsPrivateAlloc)
palloc.Dispose();
else
memory.Free(alloc);

disposedValue = true;
}
}

private object writeLock = new();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static nuint GetSize<T>(bool marshalElement) {
if (!marshalElement)
return (nuint)Unsafe.SizeOf<T>();


return (nuint)Marshal.SizeOf<T>();
}

//
// Summary:
// Writes your own structure address into process' memory and gives you the address
// to which the structure has been directly written to.
//
// Parameters:
// bytesToWrite:
// A structure to be converted into individual bytes to be written onto the buffer.
//
// marshalElement:
// Set this to true to marshal the given parameter before writing it to the buffer,
// else false.
//
// alignment:
// The memory alignment of the item to be added to the buffer.
//
// Returns:
// Pointer to the newly written structure in memory. Null pointer, if it cannot
// fit into the buffer.
public nuint Add<TStructure>(ref TStructure bytesToWrite, bool marshalElement = false) where TStructure : unmanaged {
if (marshalElement)
return AddMarshalled(bytesToWrite);
var writePos = SecureWriteMemLoc(bytesToWrite, marshalElement);
memory.Write(writePos, bytesToWrite);
return writePos;
}
private nuint AddMarshalled<TStructure>(TStructure bytesToWrite) {
var writePos = SecureWriteMemLoc(bytesToWrite, true);
memory.WriteWithMarshalling(writePos, bytesToWrite);
return writePos;
}
private nuint SecureWriteMemLoc<TStructure>(TStructure bytesToWrite, bool marshalElement) => SecureWriteMemLoc(GetSize<TStructure>(marshalElement));

private nuint SecureWriteMemLoc(nuint size) {
lock (writeLock) {
var writePos = nextFreeBlockOffset;
if (size + nextFreeBlockOffset > AllocSize)
throw new InsufficientMemoryException($"Tried to allocate: {size} and total size for our allocation is: {AllocSize} and next free block offset: {nextFreeBlockOffset}");
nextFreeBlockOffset += size;
var addy = writePos + BaseAddress;
return addy;
}
}
public nuint Add<TStructure>(ref TStructure bytesToWrite) where TStructure : struct {
return AddMarshalled(bytesToWrite);
}

public nuint Add(Span<byte> bytesToWrite) => AddBytes(bytesToWrite);
public nuint AddBytes(Span<byte> bytesToWrite) {
var writePos = SecureWriteMemLoc((nuint)bytesToWrite.Length);
memory.WriteRaw(writePos, bytesToWrite);
return writePos;
}




// TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
~PrivateMemoryBufferCompat() {
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: false);
}

public void Dispose() {
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
48 changes: 31 additions & 17 deletions Source/Reloaded.Injector/Injector.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using System;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using Reloaded.Injector.Exceptions;
using Reloaded.Injector.Interop;
using Reloaded.Memory.Sources;
using Reloaded.Memory;
using Reloaded.Memory.Structs;
using Reloaded.Memory.Utilities;
using static Reloaded.Injector.Kernel32.Kernel32;

Expand All @@ -26,7 +29,9 @@ public class Injector : IDisposable
/// </summary>
public Shellcode ShellCode { get; private set; } /* Call GetProcAddress and LoadLibraryW in remote process. */

private CircularBuffer _circularBuffer; /* Used for calling foreign functions. */
private PrivateMemoryBufferCompat _circularBuffer; /* Used for calling foreign functions. */
//private MemoryAllocation _circularBufferSource;

private Process _process; /* Process to DLL Inject into. */

/// <summary>
Expand All @@ -36,11 +41,12 @@ public class Injector : IDisposable
public Injector(Process process)
{
// Initiate target process.
_process = process;
_circularBuffer = new CircularBuffer(4096, new ExternalMemory(process));
ShellCode = new Shellcode(process);
_process = process;
_procMemory = new ExternalMemory(process);
_circularBuffer = new(process, Shellcode.CircularBufferSize);
ShellCode = new Shellcode(process);
}

private ExternalMemory _procMemory;
~Injector()
{
Dispose();
Expand All @@ -49,24 +55,26 @@ public Injector(Process process)
/// <inheritdoc/>
public void Dispose()
{
_circularBuffer?.Dispose();

ShellCode?.Dispose();
_circularBuffer?.Dispose();
GC.SuppressFinalize(this);
}

/// <summary>
/// Injects a DLL into the target process.
/// </summary>
/// <param name="modulePath">The absolute path to your DLL to be injected.</param>
/// <param name="msTimeout">Miliseconds to potentially wait for things like module loading on a new proc.</param>
/// <remarks>This function executes LoadLibraryW inside the remote process.</remarks>
/// <exception cref="DllInjectorException">The target process is not running.</exception>
/// <returns>The address/handle of the loaded in library inside the target process. Zero if the operation failed.</returns>
public long Inject(string modulePath)
public long Inject(string modulePath, int msTimeout=3000)
{
// Error checking.
AssertProcessNotRunning();

var moduleHandle = IsAbsolutePath(modulePath) ? GetModuleHandleFromPath(modulePath) : GetModuleHandleFromName(modulePath);
var moduleHandle = IsAbsolutePath(modulePath) ? GetModuleHandleFromPath(modulePath, msTimeout) : GetModuleHandleFromName(modulePath, msTimeout);
if (moduleHandle != IntPtr.Zero)
return (long)moduleHandle;

Expand Down Expand Up @@ -110,10 +118,16 @@ public long GetFunctionAddress(string module, string functionToExecute)
/// A parameter must be passed and the target method must expect it. This is a limitation of CreateRemoteThread.
/// </remarks>
/// <returns>A 32bit truncated exit code/return value. CreateRemoteThread does not support 64bit returns.</returns>
public int CallFunction<TStruct>(string module, string functionToExecute, TStruct parameter = default, bool marshalParameter = false)
public unsafe int CallFunction<TStruct>(string module, string functionToExecute, TStruct parameter = default) where TStruct : struct
{

var parameterPtr = _circularBuffer.Add(ref parameter);
return CallFunctionPtr(module, functionToExecute, (UInt64)parameterPtr);
}
public int CallFunction<TStruct>(string module, string functionToExecute, TStruct parameter = default, bool marshalParameter = false) where TStruct : unmanaged
{
var parameterPtr = _circularBuffer.Add(ref parameter, marshalParameter);
return CallFunction(module, functionToExecute, (long)parameterPtr);
return CallFunctionPtr(module, functionToExecute, (UInt64)parameterPtr);
}

/// <summary>
Expand All @@ -123,7 +137,7 @@ public int CallFunction<TStruct>(string module, string functionToExecute, TStruc
/// <param name="functionToExecute">The function of that module to be executed.</param>
/// <param name="parameterPtr">Raw value/pointer to parameter to pass to the target function.</param>
/// <returns>A 32bit truncated exit code/return value. CreateRemoteThread does not support 64bit returns.</returns>
public int CallFunction(string module, string functionToExecute, long parameterPtr)
public int CallFunctionPtr(string module, string functionToExecute, UInt64 parameterPtr)
{
long methodAddress = GetFunctionAddress(module, functionToExecute);
return CallRemoteFunction(_process.Handle, (IntPtr)methodAddress, (IntPtr) parameterPtr);
Expand Down Expand Up @@ -151,10 +165,10 @@ public bool Eject(string module)
/// </summary>
/// <param name="modulePath">The absolute path of the module (including extension).</param>
/// <returns>0 if the operation fails, else an address.</returns>
public IntPtr GetModuleHandleFromPath(string modulePath)
public IntPtr GetModuleHandleFromPath(string modulePath, int msTimeout=3000)
{
string fullPath = Path.GetFullPath(modulePath);
foreach (var module in Safety.TryGetModules(_process))
foreach (var module in Safety.TryGetModules(_process, msTimeout))
{
if (Path.GetFullPath(module.ModulePath) == fullPath)
return module.BaseAddress;
Expand All @@ -168,9 +182,9 @@ public IntPtr GetModuleHandleFromPath(string modulePath)
/// </summary>
/// <param name="moduleName">The name of the module (including extension).</param>
/// <returns>0 if the operation fails, else an address.</returns>
public IntPtr GetModuleHandleFromName(string moduleName)
public IntPtr GetModuleHandleFromName(string moduleName, int msTimeout=3000)
{
foreach (var module in Safety.TryGetModules(_process))
foreach (var module in Safety.TryGetModules(_process, msTimeout))
{
if (Path.GetFileName(module.ModulePath) == moduleName)
return module.BaseAddress;
Expand Down
11 changes: 6 additions & 5 deletions Source/Reloaded.Injector/Reloaded.Injector.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0; NET472</TargetFrameworks>
Expand All @@ -13,9 +13,10 @@
<RepositoryUrl>https://github.com/Reloaded-Project/Reloaded.Injector</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Version>1.2.5</Version>
<Version>1.2.117</Version>
<Copyright>LGPLV3</Copyright>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<LangVersion>Preview</LangVersion>
<PackageIcon>Icon.png</PackageIcon>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
Expand All @@ -32,12 +33,12 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="PeNet" Version="0.8.1" />
<PackageReference Include="Reloaded.Assembler" Version="1.0.14">
<PackageReference Include="PeNet" Version="4.0.1" />
<PackageReference Include="Reloaded.Assembler" Version="1.0.15">
<IncludeAssets>All</IncludeAssets>
<PrivateAssets>None</PrivateAssets>
</PackageReference>
<PackageReference Include="Reloaded.Memory.Buffers" Version="2.0.0" />
<PackageReference Include="Reloaded.Memory.Buffers" Version="3.0.4" />
</ItemGroup>

</Project>
Loading