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 <IMAGE_BASE_RELOCATION>((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 <ushort>((ptrFromRVA + num4) + (i << 1), SeekOrigin.Begin, out num7) && (((num7 >> 12) & 3) != 0)) { uint num8; uint num10 = num6 + ((uint)(num7 & 0xfff)); if (!image.Read <uint>((long)num10, SeekOrigin.Begin, out num8)) { throw image.GetLastError(); } image.Write <uint>(-4L, SeekOrigin.Current, num8 + num2); } } num += image_base_relocation.SizeOfBlock; ptrFromRVA += image_base_relocation.SizeOfBlock; } } }
public ResourceDirectory(PortableExecutable owner, IMAGE_RESOURCE_DIRECTORY_ENTRY entry, bool named, uint root) : base(owner, entry, named, root) { if (!owner.Read <IMAGE_RESOURCE_DIRECTORY>((long)((ulong)(root + (entry.SubdirectoryRva ^ 2147483648u))), SeekOrigin.Begin, out this._base)) { throw owner.GetLastError(); } }
public ResourceFile(PortableExecutable owner, IMAGE_RESOURCE_DIRECTORY_ENTRY entry, bool named, uint root) : base(owner, entry, named, root) { if (!owner.Read <IMAGE_RESOURCE_DATA_ENTRY>((long)((ulong)(this._root + entry.DataEntryRva)), SeekOrigin.Begin, out this._base)) { throw owner.GetLastError(); } }
public ResourceDirectory(PortableExecutable owner, IMAGE_RESOURCE_DIRECTORY_ENTRY entry, bool named, uint root) : base(owner, entry, named, root) { if (!owner.Read(root + (entry.SubdirectoryRva ^ 0x80000000), System.IO.SeekOrigin.Begin, out this._base)) { throw owner.GetLastError(); } }
public virtual IntPtr Inject(JLibrary.PortableExecutable.PortableExecutable image, int processId) { this.ClearErrors(); IntPtr hProcess = WinAPI.OpenProcess(0x43a, false, processId); IntPtr ptr2 = this.Inject(image, hProcess); WinAPI.CloseHandle(hProcess); return(ptr2); }
private static void PatchImports(JLibrary.PortableExecutable.PortableExecutable image, IntPtr hProcess, int processId) { string lpBuffer = string.Empty; string str2 = string.Empty; 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)) { IMAGE_THUNK_DATA image_thunk_data; IntPtr zero = IntPtr.Zero; zero = GetRemoteModuleHandle(lpBuffer, processId); if (zero.IsNull()) { throw new FileNotFoundException(string.Format("Unable to load dependent module '{0}'.", lpBuffer)); } uint ptrFromRVA = image.GetPtrFromRVA(image_import_descriptor.FirstThunkPtr); uint num2 = (uint)Marshal.SizeOf(typeof(IMAGE_THUNK_DATA)); while (image.Read <IMAGE_THUNK_DATA>((long)ptrFromRVA, SeekOrigin.Begin, out image_thunk_data) && (image_thunk_data.u1.AddressOfData > 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 <int>((long)ptrFromRVA, SeekOrigin.Begin, hModule.ToInt32()); ptrFromRVA += num2; } } } }
public override IntPtr Inject(PortableExecutable image, IntPtr hProcess) { ClearErrors(); try { return MapModule(Utils.DeepClone(image), hProcess, true); } catch (Exception e) { SetLastError(e); return IntPtr.Zero; } }
public override IntPtr Inject(JLibrary.PortableExecutable.PortableExecutable image, IntPtr hProcess) { this.ClearErrors(); try { return(MapModule(Utils.DeepClone <JLibrary.PortableExecutable.PortableExecutable>(image), hProcess, true)); } catch (Exception exception) { this.SetLastError(exception); return(IntPtr.Zero); } }
public override IntPtr Inject(string dllPath, IntPtr hProcess) { ClearErrors(); try { using (PortableExecutable img = new PortableExecutable(dllPath)) return Inject(img, hProcess); } catch (Exception e) { SetLastError(e); return IntPtr.Zero; } }
public ResourceWalker(PortableExecutable image) { IMAGE_DATA_DIRECTORY rsrcDir = image.NTHeader.OptionalHeader.DataDirectory[(int)DATA_DIRECTORIES.ResourceTable]; IMAGE_RESOURCE_DIRECTORY rootDir; uint rootAddr = 0; if (rsrcDir.VirtualAddress > 0 && rsrcDir.Size > 0) { if (image.Read((rootAddr = image.GetPtrFromRVA(rsrcDir.VirtualAddress)), System.IO.SeekOrigin.Begin, out rootDir)) this.Root = new ResourceDirectory(image, new IMAGE_RESOURCE_DIRECTORY_ENTRY() { SubdirectoryRva = 0x80000000 }, false, rootAddr); else throw image.GetLastError(); } }
private static void MapSections(JLibrary.PortableExecutable.PortableExecutable image, IntPtr hProcess, IntPtr pModule) { foreach (IMAGE_SECTION_HEADER image_section_header in image.EnumSectionHeaders()) { byte[] buffer = new byte[image_section_header.SizeOfRawData]; if (!image.Read((long)image_section_header.PointerToRawData, SeekOrigin.Begin, buffer)) { throw image.GetLastError(); } if ((image_section_header.Characteristics & 0x2000000) == 0) { uint num; WinAPI.WriteProcessMemory(hProcess, pModule.Add((long)image_section_header.VirtualAddress), buffer, buffer.Length, out num); IntPtr lpAddress = pModule.Add((long)image_section_header.VirtualAddress); WinAPI.VirtualProtectEx(hProcess, lpAddress, image_section_header.SizeOfRawData, image_section_header.Characteristics & 0xffffff, out num); } } }
public override IntPtr Inject(PortableExecutable dll, IntPtr hProcess) { //same as above, write the temp file and defer to the other Inject methods. ClearErrors(); string path = Utils.WriteTempData(dll.ToArray()); IntPtr hModule = IntPtr.Zero; if (!string.IsNullOrEmpty(path)) { hModule = Inject(path, hProcess); try { System.IO.File.Delete(path); } catch { /* nom nom nom */ } } return hModule; }
public void inject(int pID, Byte[] dllbytes) { InjectionMethod method = InjectionMethod.Create(InjectionMethodType.Standard); //InjectionMethodType.Standard //InjectionMethodType.ManualMap //InjectionMethodType.ThreadHijack IntPtr zero = IntPtr.Zero; using (PortableExecutable.PortableExecutable executable = new PortableExecutable.PortableExecutable(dllbytes)) { zero = method.Inject(executable, pID); } if (zero != IntPtr.Zero) { //BAIL HERE - ERROR } else if (method.GetLastError() != null) { //ERROR OCCURED } //SUCCESS }
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); }
public override IntPtr Inject(JLibrary.PortableExecutable.PortableExecutable dll, IntPtr hProcess) { this.ClearErrors(); string str = Utils.WriteTempData(dll.ToArray()); IntPtr zero = IntPtr.Zero; if (!string.IsNullOrEmpty(str)) { zero = this.Inject(str, hProcess); try { File.Delete(str); } catch { } } return(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 ResourceObject(PortableExecutable owner, IMAGE_RESOURCE_DIRECTORY_ENTRY entry, bool named, uint root) { this._owner = owner; this._entry = entry; this.IsNamedResource = named; if (named) { ushort len = 0; if (owner.Read(root + (entry.NameRva & 0x7FFFFFFF), System.IO.SeekOrigin.Begin, out len)) { byte[] unicodeBuffer = new byte[len << 1]; //each unicode character is 2 bytes wide if (owner.Read(0, System.IO.SeekOrigin.Current, unicodeBuffer)) this._name = Encoding.Unicode.GetString(unicodeBuffer); } if (_name == null) throw owner.GetLastError(); } this._root = root; }
public ResourceWalker(PortableExecutable image) { IMAGE_DATA_DIRECTORY iMAGE_DATA_DIRECTORY = image.NTHeader.OptionalHeader.DataDirectory[2]; if (iMAGE_DATA_DIRECTORY.VirtualAddress <= 0u || iMAGE_DATA_DIRECTORY.Size <= 0u) { return; } uint ptrFromRVA; IMAGE_RESOURCE_DIRECTORY iMAGE_RESOURCE_DIRECTORY; if (image.Read <IMAGE_RESOURCE_DIRECTORY>((long)((ulong)(ptrFromRVA = image.GetPtrFromRVA(iMAGE_DATA_DIRECTORY.VirtualAddress))), SeekOrigin.Begin, out iMAGE_RESOURCE_DIRECTORY)) { this.Root = new ResourceWalker.ResourceDirectory(image, new IMAGE_RESOURCE_DIRECTORY_ENTRY { SubdirectoryRva = 2147483648u }, false, ptrFromRVA); return; } throw image.GetLastError(); }
public ResourceWalker(PortableExecutable image) { IMAGE_DATA_DIRECTORY rsrcDir = image.NTHeader.OptionalHeader.DataDirectory[(int)DATA_DIRECTORIES.ResourceTable]; IMAGE_RESOURCE_DIRECTORY rootDir; uint rootAddr = 0; if (rsrcDir.VirtualAddress > 0 && rsrcDir.Size > 0) { if (image.Read((rootAddr = image.GetPtrFromRVA(rsrcDir.VirtualAddress)), System.IO.SeekOrigin.Begin, out rootDir)) { this.Root = new ResourceDirectory(image, new IMAGE_RESOURCE_DIRECTORY_ENTRY() { SubdirectoryRva = 0x80000000 }, false, rootAddr); } else { throw image.GetLastError(); } } }
public ResourceObject(PortableExecutable owner, IMAGE_RESOURCE_DIRECTORY_ENTRY entry, bool named, uint root) { this._owner = owner; this._entry = entry; this.IsNamedResource = named; if (named) { ushort num = 0; if (owner.Read <ushort>((long)((ulong)(root + (entry.NameRva & 2147483647u))), SeekOrigin.Begin, out num)) { byte[] array = new byte[(int)num << 1]; if (owner.Read(0L, SeekOrigin.Current, array)) { this._name = Encoding.Unicode.GetString(array); } } if (this._name == null) { throw owner.GetLastError(); } } this._root = root; }
public ResourceObject(PortableExecutable owner, IMAGE_RESOURCE_DIRECTORY_ENTRY entry, bool named, uint root) { this._owner = owner; this._entry = entry; this.IsNamedResource = named; if (named) { ushort len = 0; if (owner.Read(root + (entry.NameRva & 0x7FFFFFFF), System.IO.SeekOrigin.Begin, out len)) { byte[] unicodeBuffer = new byte[len << 1]; //each unicode character is 2 bytes wide if (owner.Read(0, System.IO.SeekOrigin.Current, unicodeBuffer)) { this._name = Encoding.Unicode.GetString(unicodeBuffer); } } if (_name == null) { throw owner.GetLastError(); } } this._root = root; }
public ResourceDirectory(PortableExecutable owner, IMAGE_RESOURCE_DIRECTORY_ENTRY entry, bool named, uint root) : base(owner, entry, named, root) { if (!owner.Read(root + (entry.SubdirectoryRva ^ 0x80000000), System.IO.SeekOrigin.Begin, out this._base)) throw owner.GetLastError(); }
// Most efficient version, this will be the work horse. private static IntPtr MapModule(PortableExecutable image, IntPtr hProcess, bool preserveHeaders = false) { if (hProcess.IsNull() || hProcess.Compare(-1)) 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 hModule = IntPtr.Zero; IntPtr pStub = IntPtr.Zero; uint nBytes = 0; try { //allocate memory for the image to load into the remote process. hModule = WinAPI.VirtualAllocEx(hProcess, IntPtr.Zero, image.NTHeader.OptionalHeader.SizeOfImage, 0x1000 | 0x2000, 0x04); if (hModule.IsNull()) throw new InvalidOperationException("Unable to allocate memory in the remote process."); PatchRelocations(image, hModule); LoadDependencies(image, hProcess, processId); PatchImports(image, hProcess, processId); if (preserveHeaders) { long szHeader = (image.DOSHeader.e_lfanew + Marshal.SizeOf(typeof(IMAGE_FILE_HEADER)) + sizeof(uint) + image.NTHeader.FileHeader.SizeOfOptionalHeader); byte[] header = new byte[szHeader]; if (image.Read(0, SeekOrigin.Begin, header)) WinAPI.WriteProcessMemory(hProcess, hModule, header, header.Length, out nBytes); } MapSections(image, hProcess, hModule); // some modules don't have an entry point and are purely libraries, mapping them and keeping the handle is just fine // an unlikely scenario with forced injection, but you never know. if (image.NTHeader.OptionalHeader.AddressOfEntryPoint > 0) { var stub = (byte[])DLLMAIN_STUB.Clone(); BitConverter.GetBytes(hModule.ToInt32()).CopyTo(stub, 0x0B); pStub = WinAPI.VirtualAllocEx(hProcess, IntPtr.Zero, (uint)DLLMAIN_STUB.Length, 0x1000 | 0x2000, 0x40); if (pStub.IsNull() || (!WinAPI.WriteProcessMemory(hProcess, pStub, stub, stub.Length, out nBytes) || nBytes != (uint)stub.Length)) throw new InvalidOperationException("Unable to write stub to the remote process."); IntPtr hStubThread = WinAPI.CreateRemoteThread(hProcess, 0, 0, pStub, (uint)(hModule.Add(image.NTHeader.OptionalHeader.AddressOfEntryPoint).ToInt32()), 0, 0); if (WinAPI.WaitForSingleObject(hStubThread, 5000) == 0x0L) { WinAPI.GetExitCodeThread(hStubThread, out nBytes); if (nBytes == 0) { WinAPI.VirtualFreeEx(hProcess, hModule, 0, 0x8000); throw new Exception("Entry method of module reported a failure " + Marshal.GetLastWin32Error().ToString()); } WinAPI.VirtualFreeEx(hProcess, pStub, 0, 0x8000); WinAPI.CloseHandle(hStubThread); } } } catch (Exception e) { if (!hModule.IsNull()) WinAPI.VirtualFreeEx(hProcess, hModule, 0, 0x8000); if (!pStub.IsNull()) WinAPI.VirtualFreeEx(hProcess, hModule, 0, 0x8000); hModule = IntPtr.Zero; throw e; } return hModule; }
/// <summary> /// Inject an existing in-memory PortableExecutable image into a process using a valid existing process handle /// </summary> /// <param name="image">Any valid existing PortableExecutable instance</param> /// <param name="hProcess">Handle to the remote process</param> /// <returns>A valid module handle if the function is successful, or IntPtr.Zero otherwise</returns> public abstract IntPtr Inject(PortableExecutable image, IntPtr hProcess);
/// <summary> /// Inject a collection of PortableExecutable images into a process using a unique process id as an identifier /// </summary> /// <param name="images">An array listing which PortableExecutable instances to inject</param> /// <param name="processId">Unique process identifier</param> /// <returns>An array of the same length as the 'images' parameter containing the module handles for each image, or null if the method failed. Call <see cref="GetLastError"/> for more information</returns> public virtual IntPtr[] InjectAll(PortableExecutable[] images, int processId) { ClearErrors(); IntPtr hProcess = WinAPI.OpenProcess(0x043A, false, processId); IntPtr[] hModules = InjectAll(images, hProcess); WinAPI.CloseHandle(hProcess); return hModules; }
/// <summary> /// Inject a collection of PortableExecutable images into a process using a valid existing process handle /// </summary> /// <param name="images">An array listing which PortableExecutable instances to inject</param> /// <param name="hProcess">Handle to the remote process</param> /// <returns>An array of the same length as the 'images' parameter containing the module handles for each image</returns> public abstract IntPtr[] InjectAll(PortableExecutable[] images, IntPtr hProcess);
/// <summary> /// Inject an existing in-memory PortableExecutable image into a process using a unique process id as an identifier /// </summary> /// <param name="image">Any valid existing PortableExecutable instance</param> /// <param name="processId">Unique process identifier</param> /// <returns>A valid module handle if the function is successful, or IntPtr.Zero otherwise</returns> public virtual IntPtr Inject(PortableExecutable image, int processId) { ClearErrors(); IntPtr hProcess = WinAPI.OpenProcess(0x043A, false, processId); IntPtr hModule = Inject(image, hProcess); WinAPI.CloseHandle(hProcess); return hModule; }
/* * Handles loading of all dependent modules. Iterates the IAT entries and attempts to load (using LoadLibrary) all * of the necessary modules for the main module to function. The manifest is extracted and activation contexts used to * ensure correct loading of Side-By-Side dependencies. */ private static bool LoadDependencies(PortableExecutable image, IntPtr hProcess, int processId) { List<string> neededDependencies = new List<string>(); string curdep = string.Empty; bool success = false; foreach (var desc in image.EnumImports()) { if (image.ReadString(image.GetPtrFromRVA(desc.Name), SeekOrigin.Begin, out curdep) && !string.IsNullOrEmpty(curdep)) { if (GetRemoteModuleHandle(curdep, processId).IsNull()) neededDependencies.Add(curdep); } } if (neededDependencies.Count > 0) //do we actually need to load any new modules? { byte[] bManifest = ExtractManifest(image); string pathManifest = string.Empty; if (bManifest == null) // no internal manifest, may be an external manifest or none at all? { if (!string.IsNullOrEmpty(image.FileLocation) && File.Exists(Path.Combine(Path.GetDirectoryName(image.FileLocation), Path.GetFileName(image.FileLocation) + ".manifest"))) { pathManifest = Path.Combine(Path.GetDirectoryName(image.FileLocation), Path.GetFileName(image.FileLocation) + ".manifest"); } else // no internal or external manifest, presume no side-by-side dependencies. { var standard = InjectionMethod.Create(InjectionMethodType.Standard); var results = standard.InjectAll(neededDependencies.ToArray(), hProcess); foreach (var result in results) if (result.IsNull()) return false; // failed to inject a dependecy, abort mission. return true; // done loading dependencies. } } else { pathManifest = Utils.WriteTempData(bManifest); } if (string.IsNullOrEmpty(pathManifest)) return false; IntPtr pResolverStub = WinAPI.VirtualAllocEx(hProcess, IntPtr.Zero, (uint)RESOLVER_STUB.Length, 0x1000 | 0x2000, 0x40); IntPtr pManifest = WinAPI.CreateRemotePointer(hProcess, Encoding.ASCII.GetBytes(pathManifest + "\0"), 0x04); IntPtr pModules = WinAPI.CreateRemotePointer(hProcess, Encoding.ASCII.GetBytes(string.Join("\0", neededDependencies.ToArray()) + "\0"), 0x04); if (!pResolverStub.IsNull()) { var resolverStub = (byte[])RESOLVER_STUB.Clone(); uint nBytes = 0; // Call patching. Patch the empty function addresses with the runtime addresses. BitConverter.GetBytes(FN_CREATEACTCTXA.Subtract(pResolverStub.Add(0x3F)).ToInt32()).CopyTo(resolverStub, 0x3B); BitConverter.GetBytes(FN_ACTIVATEACTCTX.Subtract(pResolverStub.Add(0x58)).ToInt32()).CopyTo(resolverStub, 0x54); BitConverter.GetBytes(FN_GETMODULEHANDLEA.Subtract(pResolverStub.Add(0x84)).ToInt32()).CopyTo(resolverStub, 0x80); BitConverter.GetBytes(FN_LOADLIBRARYA.Subtract(pResolverStub.Add(0x92)).ToInt32()).CopyTo(resolverStub, 0x8E); BitConverter.GetBytes(FN_DEACTIVATEACTCTX.Subtract(pResolverStub.Add(0xC8)).ToInt32()).CopyTo(resolverStub, 0xC4); BitConverter.GetBytes(FN_RELEASEACTCTX.Subtract(pResolverStub.Add(0xD1)).ToInt32()).CopyTo(resolverStub, 0xCD); // Parameter patching BitConverter.GetBytes(pManifest.ToInt32()).CopyTo(resolverStub, 0x1F); BitConverter.GetBytes(neededDependencies.Count).CopyTo(resolverStub, 0x28); BitConverter.GetBytes(pModules.ToInt32()).CopyTo(resolverStub, 0x31); if (WinAPI.WriteProcessMemory(hProcess, pResolverStub, resolverStub, resolverStub.Length, out nBytes) && nBytes == (uint)resolverStub.Length) { uint result = WinAPI.RunThread(hProcess, pResolverStub, 0, 5000); success = (result != uint.MaxValue && result != 0); } // Cleanup WinAPI.VirtualFreeEx(hProcess, pModules, 0, 0x8000); WinAPI.VirtualFreeEx(hProcess, pManifest, 0, 0x8000); WinAPI.VirtualFreeEx(hProcess, pResolverStub, 0, 0x8000); } } return success; }
public override IntPtr[] InjectAll(PortableExecutable[] images, IntPtr hProcess) { ClearErrors(); return Array.ConvertAll(images, pe => Inject(pe, hProcess)); }
private static void MapSections(PortableExecutable image, IntPtr hProcess, IntPtr pModule) { //very straightforward really. Just iterate through all the sections and map them to their desired virtual addresses in the remote process. //I'm not 100% sure about how well masking the section header characteristics and passing them off as memory protection constants goes. But //so far I haven't hit any issues. (i.e a section header with characteristics "IMAGE_SCN_TYPE_NO_PAD" will set "PAGE_WRITECOPY" memory protection. byte[] databuffer; uint n; foreach (var pSecHd in image.EnumSectionHeaders()) { databuffer = new byte[pSecHd.SizeOfRawData]; if (image.Read(pSecHd.PointerToRawData, SeekOrigin.Begin, databuffer)) { if ((pSecHd.Characteristics & 0x02000000) == 0) //can actually ignore this section (usually the reloc section) { WinAPI.WriteProcessMemory(hProcess, pModule.Add(pSecHd.VirtualAddress), databuffer, databuffer.Length, out n); WinAPI.VirtualProtectEx(hProcess, pModule.Add(pSecHd.VirtualAddress), pSecHd.SizeOfRawData, pSecHd.Characteristics & 0x00FFFFFF, out n); } } else { throw image.GetLastError(); } } }
private static void PatchRelocations(PortableExecutable image, IntPtr pAlloc) { // Base relocations are essentially Microsofts ingenious way of preserving portability in images. // for all absolute address calls/jmps/references...etc, an entry is made into the base relocation // table telling the loader exactly where an "absolute" address is being used. This allows the loader // to iterate through the relocations and patch these absolute values to ensure they are correct when // the image is loaded somewhere that isn't its preferred base address. IMAGE_DATA_DIRECTORY relocDir = image.NTHeader.OptionalHeader.DataDirectory[(int)DATA_DIRECTORIES.BaseRelocTable]; if (relocDir.Size > 0) //check if there are in fact any relocations. { uint n = 0; uint delta = (uint)(pAlloc.ToInt32() - image.NTHeader.OptionalHeader.ImageBase); //The difference in loaded/preferred addresses. uint pReloc = image.GetPtrFromRVA(relocDir.VirtualAddress); uint szReloc = (uint)Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION)); IMAGE_BASE_RELOCATION reloc; while (n < relocDir.Size && image.Read(pReloc, SeekOrigin.Begin, out reloc)) { // A relocation block consists of an IMAGE_BASE_RELOCATION, and an array of WORDs. // To calculate the number of relocations (represented by WORDs), just do some simple math. int nrelocs = (int)((reloc.SizeOfBlock - szReloc) / sizeof(ushort)); uint pageVa = image.GetPtrFromRVA(reloc.VirtualAddress); //The Page RVA for this set of relocations (usually a 4K boundary). ushort vreloc; uint old; for (int i = 0; i < nrelocs; i++) { // There are only 2 types of relocations on Intel machines: ABSOLUTE (padding, nothing needs to be done) and HIGHLOW (0x03) // Highlow means that all 32 bits of the "delta" value need to be added to the relocation value. if (image.Read(pReloc + szReloc + (i << 1), SeekOrigin.Begin, out vreloc) && (vreloc >> 12 & 3) != 0) { uint vp = (uint)(pageVa + (vreloc & 0x0FFF)); if (image.Read<uint>(vp, SeekOrigin.Begin, out old)) image.Write<uint>(-4, SeekOrigin.Current, (uint)(old + delta)); else throw image.GetLastError(); //unlikely, but I hate crashing targets because something in the PE was messed up. } } n += reloc.SizeOfBlock; pReloc += reloc.SizeOfBlock; } } }
public ResourceFile(PortableExecutable owner, IMAGE_RESOURCE_DIRECTORY_ENTRY entry, bool named, uint root) : base(owner, entry, named, root) { if (!owner.Read(_root + entry.DataEntryRva, System.IO.SeekOrigin.Begin, out this._base)) throw owner.GetLastError(); }
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) { return(zero); } byte[] array = (byte[])DLLMAIN_STUB.Clone(); BitConverter.GetBytes(zero.ToInt32()).CopyTo(array, 11); ptr = WinAPI.VirtualAllocEx(hProcess, IntPtr.Zero, (uint)DLLMAIN_STUB.Length, 0x3000, 0x40); if (ptr.IsNull() || (!WinAPI.WriteProcessMemory(hProcess, ptr, 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, ptr, (uint)zero.Add(((long)image.NTHeader.OptionalHeader.AddressOfEntryPoint)).ToInt32(), 0, 0); if (WinAPI.WaitForSingleObject(hObject, 0x1388) != 0L) { return(zero); } WinAPI.GetExitCodeThread(hObject, out lpNumberOfBytesRead); if (lpNumberOfBytesRead == 0) { WinAPI.VirtualFreeEx(hProcess, zero, 0, 0x8000); throw new Exception("Entry method of module reported a failure " + Marshal.GetLastWin32Error().ToString()); } WinAPI.VirtualFreeEx(hProcess, ptr, 0, 0x8000); WinAPI.CloseHandle(hObject); } catch (Exception exception) { if (!zero.IsNull()) { WinAPI.VirtualFreeEx(hProcess, zero, 0, 0x8000); } if (!ptr.IsNull()) { WinAPI.VirtualFreeEx(hProcess, zero, 0, 0x8000); } zero = IntPtr.Zero; throw exception; } return(zero); }
private static bool LoadDependencies(JLibrary.PortableExecutable.PortableExecutable image, IntPtr hProcess, int processId) { List <string> list = new List <string>(); 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); }
public override IntPtr[] InjectAll(PortableExecutable[] dlls, IntPtr hProcess) { ClearErrors(); return InjectAll(Array.ConvertAll<PortableExecutable, string>(dlls, pe => Utils.WriteTempData(pe.ToArray())), hProcess); }
public abstract IntPtr Inject(JLibrary.PortableExecutable.PortableExecutable image, IntPtr hProcess);
private static void PatchImports(PortableExecutable image, IntPtr hProcess, int processId) { string module = string.Empty; string fname = string.Empty; foreach (var desc in image.EnumImports()) { if (image.ReadString(image.GetPtrFromRVA(desc.Name), SeekOrigin.Begin, out module)) { IntPtr pModule = IntPtr.Zero; IntPtr tModule = IntPtr.Zero; //Thanks to FastLoadDependencies, all dependent modules *should* be loaded into the remote process already. pModule = GetRemoteModuleHandle(module, processId); if (pModule.IsNull()) throw new FileNotFoundException(string.Format("Unable to load dependent module '{0}'.", module)); //now have a supposedly valid module handle remote process, all that remains to be done is patch the info. uint pThunk = image.GetPtrFromRVA(desc.FirstThunkPtr); //despite the fact FirstThunk and OriginalFirstThunk are identical within an unmapped PE, only FirstThunk is looked up after mapping. uint szThunk = (uint)Marshal.SizeOf(typeof(IMAGE_THUNK_DATA)); IMAGE_THUNK_DATA thunk; while (image.Read(pThunk, SeekOrigin.Begin, out thunk) && thunk.u1.AddressOfData > 0) //final thunk is signified by a null-filled IMAGE_THUNK_DATA structure. { IntPtr remote = IntPtr.Zero; object procVal = null; if ((thunk.u1.Ordinal & 0x80000000) == 0) //import by name { if (image.ReadString(image.GetPtrFromRVA(thunk.u1.AddressOfData) + 2, SeekOrigin.Begin, out fname)) //get the function name. procVal = fname; else throw image.GetLastError(); //error occurred during memory iteration, this is only a safeguard and shouldn't really ever occur, but the universe loves proving me wrong. } else //import by ordinal. { procVal = (ushort)(thunk.u1.Ordinal & 0xFFFF); } // the following section of code simply aims to reduce overhead. A check is first performed to see if the current module // is loaded in the current process first, if so it simply uses relative addresses to calculate the function address in the remote // process. If the module isn't found in our process, a call to GetProcAddressEx is used to find the remote address. Of course, you // could simply guarantee the first case by calling LoadLibrary internally, but I find that can have unwanted side effects. if (!(remote = WinAPI.GetModuleHandleA(module)).IsNull()) { IntPtr local = procVal.GetType().Equals(typeof(string)) ? WinAPI.GetProcAddress(remote, (string)procVal) : WinAPI.GetProcAddress(remote, (uint)((ushort)procVal) & 0x0000FFFF); if (!local.IsNull()) remote = pModule.Add(local.Subtract(remote.ToInt32()).ToInt32()); } else { remote = WinAPI.GetProcAddressEx(hProcess, pModule, procVal); } if (remote.IsNull()) //alas, couldn't find the function. throw new EntryPointNotFoundException(string.Format("Unable to locate imported function '{0}' from module '{1}' in the remote process.", fname, module)); image.Write<int>(pThunk, SeekOrigin.Begin, remote.ToInt32()); //overwrite the thunk and continue on our merry way. pThunk += szThunk; } } } }
/** * Extract an application manifest from * an executable file's resources. * Returns null if no manifest was found in the executable. */ private static byte[] ExtractManifest(PortableExecutable image) { byte[] manifest = null; ResourceWalker walker = new ResourceWalker(image); ResourceWalker.ResourceDirectory manifestDir = null; for (int i = 0; i < walker.Root.Directories.Length && manifestDir == null; i++) if (walker.Root.Directories[i].Id == Constants.RT_MANIFEST) manifestDir = walker.Root.Directories[i]; if (manifestDir != null && manifestDir.Directories.Length > 0) if (IsManifestResource(manifestDir.Directories[0].Id) && manifestDir.Directories[0].Files.Length == 1) manifest = manifestDir.Directories[0].Files[0].GetData(); return manifest; }