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; } } }
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; } } } }
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; } } } }
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; } } }