InjectionLibrary
ManualMap.cs
namespace InjectionLibrary
{
using JLibrary.PortableExecutable;
using JLibrary.Tools;
using JLibrary.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
internal clast ManualMap : InjectionMethod
{
private static readonly byte[] DLLMAIN_STUB = new byte[] {
0x68, 0, 0, 0, 0, 0x68, 1, 0, 0, 0, 0x68, 0, 0, 0, 0, 0xff,
0x54, 0x24, 0x10, 0xc3
};
private static readonly IntPtr FN_ACTIVATEACTCTX = WinAPI.GetProcAddress(H_KERNEL32, "ActivateActCtx");
private static readonly IntPtr FN_CREATEACTCTXA = WinAPI.GetProcAddress(H_KERNEL32, "CreateActCtxA");
private static readonly IntPtr FN_DEACTIVATEACTCTX = WinAPI.GetProcAddress(H_KERNEL32, "DeactivateActCtx");
private static readonly IntPtr FN_GETMODULEHANDLEA = WinAPI.GetProcAddress(H_KERNEL32, "GetModuleHandleA");
private static readonly IntPtr FN_LOADLIBRARYA = WinAPI.GetProcAddress(H_KERNEL32, "LoadLibraryA");
private static readonly IntPtr FN_RELEASEACTCTX = WinAPI.GetProcAddress(H_KERNEL32, "ReleaseActCtx");
private static readonly IntPtr H_KERNEL32 = WinAPI.GetModuleHandleA("KERNEL32.dll");
private static readonly byte[] RESOLVER_STUB = new byte[] {
0x55, 0x8b, 0xec, 0x83, 0xec, 60, 0x8b, 0xcc, 0x8b, 0xd1, 0x83, 0xc2, 60, 0xc7, 1, 0,
0, 0, 0, 0x83, 0xc1, 4, 0x3b, 0xca, 0x7e, 0xf3, 0xc6, 4, 0x24, 0x20, 0xb9, 0,
0, 0, 0, 0x89, 0x4c, 0x24, 8, 0xb9, 0, 0, 0, 0, 0x89, 0x4c, 0x24, 40,
0xb9, 0, 0, 0, 0, 0x89, 0x4c, 0x24, 0x2c, 0x54, 0xe8, 0, 0, 0, 0, 0x83,
0x38, 0xff, 15, 0x84, 0x89, 0, 0, 0, 0x89, 0x44, 0x24, 0x30, 0x8b, 0xcc, 0x83, 0xc1,
0x20, 0x51, 80, 0xe8, 0, 0, 0, 0, 0x83, 0xf8, 0, 0x74, 0x6b, 0xc6, 0x44, 0x24,
0x24, 1, 0x8b, 0x4c, 0x24, 40, 0x83, 0xf9, 0, 0x7e, 0x3e, 0x83, 0xe9, 1, 0x89, 0x4c,
0x24, 40, 0x8b, 0x4c, 0x24, 0x24, 0x83, 0xf9, 0, 0x74, 0x2e, 0xff, 0x74, 0x24, 0x2c, 0xe8,
0, 0, 0, 0, 0x83, 0xf8, 0, 0x75, 9, 0xff, 0x74, 0x24, 0x2c, 0xe8, 0, 0,
0, 0, 0x89, 0x44, 0x24, 0x24, 0x8b, 0x4c, 0x24, 0x2c, 0x8a, 1, 0x83, 0xc1, 1, 60,
0, 0x75, 0xf7, 0x89, 0x4c, 0x24, 0x2c, 0xeb, 0xb9, 0x8b, 0x44, 0x24, 0x24, 0xb9, 1, 0,
0, 0, 0x23, 0xc1, 0x89, 0x4c, 0x24, 0x24, 0x83, 0xf9, 0, 0x75, 20, 0xff, 0x74, 0x24,
0x20, 0x6a, 0, 0xe8, 0, 0, 0, 0, 0xff, 0x74, 0x24, 0x30, 0xe8, 0, 0, 0,
0, 0x8b, 0x44, 0x24, 0x24, 0x8b, 0xe5, 0x5d, 0xc3
};
private static byte[] ExtractManifest(JLibrary.PortableExecutable.PortableExecutable image)
{
byte[] data = null;
ResourceWalker walker = new ResourceWalker(image);
ResourceWalker.ResourceDirectory directory = null;
for (int i = 0; (i < walker.Root.Directories.Length) && (directory == null); i++)
{
if (walker.Root.Directories[i].Id == 0x18L)
{
directory = walker.Root.Directories[i];
}
}
if (((directory != null) && (directory.Directories.Length > 0)) && (IsManifestResource(directory.Directories[0].Id) && (directory.Directories[0].Files.Length == 1)))
{
data = directory.Directories[0].Files[0].GetData();
}
return data;
}
private static uint FindEntryPoint(IntPtr hProcess, IntPtr hModule)
{
if (hProcess.IsNull() || hProcess.Compare(-1L))
{
throw new ArgumentException("Invalid process handle.", "hProcess");
}
if (hModule.IsNull())
{
throw new ArgumentException("Invalid module handle.", "hModule");
}
byte[] buffer = WinAPI.ReadRemoteMemory(hProcess, hModule, (uint) Marshal.SizeOf(typeof(IMAGE_DOS_HEADER)));
if (buffer != null)
{
ushort num = BitConverter.ToUInt16(buffer, 0);
uint num2 = BitConverter.ToUInt32(buffer, 60);
if (num == 0x5a4d)
{
byte[] buffer2 = WinAPI.ReadRemoteMemory(hProcess, hModule.Add((long) num2), (uint) Marshal.SizeOf(typeof(IMAGE_NT_HEADER32)));
if ((buffer2 != null) && (BitConverter.ToUInt32(buffer2, 0) == 0x4550))
{
IMAGE_NT_HEADER32 result = new IMAGE_NT_HEADER32();
using (UnmanagedBuffer buffer3 = new UnmanagedBuffer(0x100))
{
if (buffer3.Translate(buffer2, out result))
{
return result.OptionalHeader.AddressOfEntryPoint;
}
}
}
}
}
return 0;
}
private static IntPtr GetRemoteModuleHandle(string module, int processId)
{
IntPtr zero = IntPtr.Zero;
Process processById = Process.GetProcessById(processId);
for (int i = 0; (i < processById.Modules.Count) && zero.IsNull(); i++)
{
if (processById.Modules[i].ModuleName.ToLower() == module.ToLower())
{
zero = processById.Modules[i].BaseAddress;
}
}
return zero;
}
public override IntPtr Inject(JLibrary.PortableExecutable.PortableExecutable image, IntPtr hProcess)
{
this.ClearErrors();
try
{
return MapModule(Utils.DeepClone(image), hProcess, true);
}
catch (Exception exception)
{
this.SetLastError(exception);
return IntPtr.Zero;
}
}
public override IntPtr Inject(string dllPath, IntPtr hProcess)
{
IntPtr zero;
this.ClearErrors();
try
{
using (JLibrary.PortableExecutable.PortableExecutable executable = new JLibrary.PortableExecutable.PortableExecutable(dllPath))
{
zero = this.Inject(executable, hProcess);
}
}
catch (Exception exception)
{
this.SetLastError(exception);
zero = IntPtr.Zero;
}
return zero;
}
public override IntPtr[] InjectAll(JLibrary.PortableExecutable.PortableExecutable[] images, IntPtr hProcess)
{
this.ClearErrors();
return Array.ConvertAll(images, pe => this.Inject(pe, hProcess));
}
public override IntPtr[] InjectAll(string[] dllPaths, IntPtr hProcess)
{
this.ClearErrors();
return Array.ConvertAll(dllPaths, dp => this.Inject(dp, hProcess));
}
private static bool IsManifestResource(int id)
{
switch (((uint) id))
{
case 1:
case 2:
case 3:
return true;
}
return false;
}
private static bool LoadDependencies(JLibrary.PortableExecutable.PortableExecutable image, IntPtr hProcess, int processId)
{
List list = new List();
string lpBuffer = string.Empty;
bool flag = false;
foreach (IMAGE_IMPORT_DESCRIPTOR image_import_descriptor in image.EnumImports())
{
if ((image.ReadString((long) image.GetPtrFromRVA(image_import_descriptor.Name), SeekOrigin.Begin, out lpBuffer, -1, null) && !string.IsNullOrEmpty(lpBuffer)) && GetRemoteModuleHandle(lpBuffer, processId).IsNull())
{
list.Add(lpBuffer);
}
}
if (list.Count > 0)
{
byte[] data = ExtractManifest(image);
string str2 = string.Empty;
if (data == null)
{
if (string.IsNullOrEmpty(image.FileLocation) || !File.Exists(Path.Combine(Path.GetDirectoryName(image.FileLocation), Path.GetFileName(image.FileLocation) + ".manifest")))
{
IntPtr[] ptrArray = InjectionMethod.Create(InjectionMethodType.Standard).InjectAll(list.ToArray(), hProcess);
foreach (IntPtr ptr in ptrArray)
{
if (ptr.IsNull())
{
return false;
}
}
return true;
}
str2 = Path.Combine(Path.GetDirectoryName(image.FileLocation), Path.GetFileName(image.FileLocation) + ".manifest");
}
else
{
str2 = Utils.WriteTempData(data);
}
if (string.IsNullOrEmpty(str2))
{
return false;
}
IntPtr ptr2 = WinAPI.VirtualAllocEx(hProcess, IntPtr.Zero, (uint) RESOLVER_STUB.Length, 0x3000, 0x40);
IntPtr lpAddress = WinAPI.CreateRemotePointer(hProcess, Encoding.ASCII.GetBytes(str2 + "\0"), 4);
IntPtr ptr4 = WinAPI.CreateRemotePointer(hProcess, Encoding.ASCII.GetBytes(string.Join("\0", list.ToArray()) + "\0"), 4);
if (!ptr2.IsNull())
{
byte[] array = (byte[]) RESOLVER_STUB.Clone();
uint lpNumberOfBytesRead = 0;
BitConverter.GetBytes(FN_CREATEACTCTXA.Subtract(ptr2.Add(((long) 0x3fL))).ToInt32()).CopyTo(array, 0x3b);
BitConverter.GetBytes(FN_ACTIVATEACTCTX.Subtract(ptr2.Add(((long) 0x58L))).ToInt32()).CopyTo(array, 0x54);
BitConverter.GetBytes(FN_GETMODULEHANDLEA.Subtract(ptr2.Add(((long) 0x84L))).ToInt32()).CopyTo(array, 0x80);
BitConverter.GetBytes(FN_LOADLIBRARYA.Subtract(ptr2.Add(((long) 0x92L))).ToInt32()).CopyTo(array, 0x8e);
BitConverter.GetBytes(FN_DEACTIVATEACTCTX.Subtract(ptr2.Add(((long) 200L))).ToInt32()).CopyTo(array, 0xc4);
BitConverter.GetBytes(FN_RELEASEACTCTX.Subtract(ptr2.Add(((long) 0xd1L))).ToInt32()).CopyTo(array, 0xcd);
BitConverter.GetBytes(lpAddress.ToInt32()).CopyTo(array, 0x1f);
BitConverter.GetBytes(list.Count).CopyTo(array, 40);
BitConverter.GetBytes(ptr4.ToInt32()).CopyTo(array, 0x31);
if (WinAPI.WriteProcessMemory(hProcess, ptr2, array, array.Length, out lpNumberOfBytesRead) && (lpNumberOfBytesRead == array.Length))
{
uint num2 = WinAPI.RunThread(hProcess, ptr2, 0, 0x1388);
flag = (num2 != uint.MaxValue) && (num2 != 0);
}
WinAPI.VirtualFreeEx(hProcess, ptr4, 0, 0x8000);
WinAPI.VirtualFreeEx(hProcess, lpAddress, 0, 0x8000);
WinAPI.VirtualFreeEx(hProcess, ptr2, 0, 0x8000);
}
}
return flag;
}
private static IntPtr MapModule(JLibrary.PortableExecutable.PortableExecutable image, IntPtr hProcess, bool preserveHeaders = false)
{
if (hProcess.IsNull() || hProcess.Compare(-1L))
{
throw new ArgumentException("Invalid process handle.", "hProcess");
}
if (image == null)
{
throw new ArgumentException("Cannot map a non-existant PE Image.", "image");
}
int processId = WinAPI.GetProcessId(hProcess);
if (processId == 0)
{
throw new ArgumentException("Provided handle doesn't have sufficient permissions to inject", "hProcess");
}
IntPtr zero = IntPtr.Zero;
IntPtr ptr = IntPtr.Zero;
uint lpNumberOfBytesRead = 0;
try
{
zero = WinAPI.VirtualAllocEx(hProcess, IntPtr.Zero, image.NTHeader.OptionalHeader.SizeOfImage, 0x3000, 4);
if (zero.IsNull())
{
throw new InvalidOperationException("Unable to allocate memory in the remote process.");
}
PatchRelocations(image, zero);
LoadDependencies(image, hProcess, processId);
PatchImports(image, hProcess, processId);
if (preserveHeaders)
{
long num3 = (long) (((image.DOSHeader.e_lfanew + Marshal.SizeOf(typeof(IMAGE_FILE_HEADER))) + ((long) 4L)) + image.NTHeader.FileHeader.SizeOfOptionalHeader);
byte[] buffer = new byte[num3];
if (image.Read(0L, SeekOrigin.Begin, buffer))
{
WinAPI.WriteProcessMemory(hProcess, zero, buffer, buffer.Length, out lpNumberOfBytesRead);
}
}
MapSections(image, hProcess, zero);
if (image.NTHeader.OptionalHeader.AddressOfEntryPoint 0))
{
IntPtr hModule = IntPtr.Zero;
object lpProcName = null;
if ((image_thunk_data.u1.Ordinal & 0x80000000) == 0)
{
if (!image.ReadString((long) (image.GetPtrFromRVA(image_thunk_data.u1.AddressOfData) + 2), SeekOrigin.Begin, out str2, -1, null))
{
throw image.GetLastError();
}
lpProcName = str2;
}
else
{
lpProcName = (ushort) (image_thunk_data.u1.Ordinal & 0xffff);
}
if (!(hModule = WinAPI.GetModuleHandleA(lpBuffer)).IsNull())
{
IntPtr ptr = lpProcName.GetType().Equals(typeof(string)) ? WinAPI.GetProcAddress(hModule, (string) lpProcName) : WinAPI.GetProcAddress(hModule, (uint) (((ushort) lpProcName) & 0xffff));
if (!ptr.IsNull())
{
hModule = zero.Add((long) ptr.Subtract(((long) hModule.ToInt32())).ToInt32());
}
}
else
{
hModule = WinAPI.GetProcAddressEx(hProcess, zero, lpProcName);
}
if (hModule.IsNull())
{
throw new EntryPointNotFoundException(string.Format("Unable to locate imported function '{0}' from module '{1}' in the remote process.", str2, lpBuffer));
}
image.Write((long) ptrFromRVA, SeekOrigin.Begin, hModule.ToInt32());
ptrFromRVA += num2;
}
}
}
}
private static void PatchRelocations(JLibrary.PortableExecutable.PortableExecutable image, IntPtr pAlloc)
{
IMAGE_DATA_DIRECTORY image_data_directory = image.NTHeader.OptionalHeader.DataDirectory[5];
if (image_data_directory.Size > 0)
{
IMAGE_BASE_RELOCATION image_base_relocation;
uint num = 0;
uint num2 = ((uint) pAlloc.ToInt32()) - image.NTHeader.OptionalHeader.ImageBase;
uint ptrFromRVA = image.GetPtrFromRVA(image_data_directory.VirtualAddress);
uint num4 = (uint) Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION));
while ((num < image_data_directory.Size) && image.Read((long) ptrFromRVA, SeekOrigin.Begin, out image_base_relocation))
{
int num5 = (int) ((image_base_relocation.SizeOfBlock - num4) / 2);
uint num6 = image.GetPtrFromRVA(image_base_relocation.VirtualAddress);
for (int i = 0; i < num5; i++)
{
ushort num7;
if (image.Read((ptrFromRVA + num4) + (i > 12) & 3) != 0))
{
uint num8;
uint num10 = num6 + ((uint) (num7 & 0xfff));
if (!image.Read((long) num10, SeekOrigin.Begin, out num8))
{
throw image.GetLastError();
}
image.Write(-4L, SeekOrigin.Current, num8 + num2);
}
}
num += image_base_relocation.SizeOfBlock;
ptrFromRVA += image_base_relocation.SizeOfBlock;
}
}
}
public override bool Unload(IntPtr hModule, IntPtr hProcess)
{
this.ClearErrors();
if (hModule.IsNull())
{
throw new ArgumentNullException("hModule", "Invalid module handle");
}
if (hProcess.IsNull() || hProcess.Compare(-1L))
{
throw new ArgumentException("Invalid process handle.", "hProcess");
}
IntPtr zero = IntPtr.Zero;
uint lpNumberOfBytesRead = 0;
try
{
uint num2 = FindEntryPoint(hProcess, hModule);
if (num2 != 0)
{
byte[] array = (byte[]) DLLMAIN_STUB.Clone();
BitConverter.GetBytes(hModule.ToInt32()).CopyTo(array, 11);
BitConverter.GetBytes((uint) 0).CopyTo(array, 6);
BitConverter.GetBytes((uint) 0x3e8).CopyTo(array, 1);
zero = WinAPI.VirtualAllocEx(hProcess, IntPtr.Zero, (uint) DLLMAIN_STUB.Length, 0x3000, 0x40);
if (zero.IsNull() || (!WinAPI.WriteProcessMemory(hProcess, zero, array, array.Length, out lpNumberOfBytesRead) || (lpNumberOfBytesRead != array.Length)))
{
throw new InvalidOperationException("Unable to write stub to the remote process.");
}
IntPtr hObject = WinAPI.CreateRemoteThread(hProcess, 0, 0, zero, (uint) hModule.Add(((long) num2)).ToInt32(), 0, 0);
if (WinAPI.WaitForSingleObject(hObject, 0x1388) == 0L)
{
WinAPI.VirtualFreeEx(hProcess, zero, 0, 0x8000);
WinAPI.CloseHandle(hObject);
return WinAPI.VirtualFreeEx(hProcess, hModule, 0, 0x8000);
}
return false;
}
return WinAPI.VirtualFreeEx(hProcess, hModule, 0, 0x8000);
}
catch (Exception exception)
{
this.SetLastError(exception);
return false;
}
}
public override bool[] UnloadAll(IntPtr[] hModules, IntPtr hProcess)
{
this.ClearErrors();
if (hModules == null)
{
throw new ArgumentNullException("hModules", "Parameter cannot be null.");
}
if (hProcess.IsNull() || hProcess.Compare(-1L))
{
throw new ArgumentOutOfRangeException("hProcess", "Invalid process handle specified.");
}
try
{
bool[] flagArray = new bool[hModules.Length];
for (int i = 0; i < hModules.Length; i++)
{
flagArray[i] = this.Unload(hModules[i], hProcess);
}
return flagArray;
}
catch (Exception exception)
{
this.SetLastError(exception);
return null;
}
}
}
}