/// <summary> /// Obtains the memory address of an assembly. /// </summary> /// <param name="name">The name of the assembly to find the address of.</param> public uint GetProcAddress(string name) { unsafe { IntPtr codeBase = module.codeBase; int idx = -1; uint i; IMAGE_DATA_DIRECTORY directory = module.headers.OptionalHeader.DataDirectory[0]; if (directory.Size == 0) { return(0); } var exports = PointerHelpers.ToStruct <IMAGE_EXPORT_DIRECTORY>(codeBase, directory.VirtualAddress); var nameRef = (uint *)new IntPtr(codeBase.ToInt32() + exports.AddressOfNames); var ordinal = (ushort *)new IntPtr(codeBase.ToInt32() + exports.AddressOfNameOrdinals); for (i = 0; i < exports.NumberOfNames; i++, nameRef++, ordinal++) { var str = codeBase + (int)(*nameRef); string tmp = Marshal.PtrToStringAnsi(str); if (tmp == name) { idx = *ordinal; break; } } var tmpaa = (uint *)(codeBase.ToInt32() + (exports.AddressOfFunctions + (idx * 4))); var addr = (uint)((codeBase.ToInt32()) + (*tmpaa)); return(addr); } }
/// <summary> /// Gets the total amount of modules within an assembly. /// </summary> public int GetModuleCount() { int count = 0; IntPtr codeBase = module.codeBase; IMAGE_DATA_DIRECTORY directory = module.headers.OptionalHeader.DataDirectory[1]; if (directory.Size > 0) { var importDesc = PointerHelpers.ToStruct <IMAGE_IMPORT_DESCRIPTOR>(codeBase, directory.VirtualAddress); while (importDesc.Name > 0) { var str = codeBase + (int)importDesc.Name; string tmp = Marshal.PtrToStringAnsi(str); int handle = Win32Imports.LoadLibrary(tmp); if (handle == -1) { break; } count++; importDesc = PointerHelpers.ToStruct <IMAGE_IMPORT_DESCRIPTOR>(codeBase, (uint)(directory.VirtualAddress + (Marshal.SizeOf(typeof(IMAGE_IMPORT_DESCRIPTOR)) * (count)))); } } return(count); }
/// <summary> /// Relocates pointers so we can allow our injected assembly to be run. /// </summary> /// <param name="delta">The PE code and the old headers before injection.</param> public void PerformBaseRelocation(uint delta) { IntPtr codeBase = module.codeBase; int sizeOfBase = Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION)); IMAGE_DATA_DIRECTORY directory = module.headers.OptionalHeader.DataDirectory[5]; int cnt = 0; if (directory.Size > 0) { var relocation = PointerHelpers.ToStruct <IMAGE_BASE_RELOCATION>(codeBase, directory.VirtualAddress); while (relocation.VirtualAddress > 0) { unsafe { var dest = (IntPtr)(codeBase.ToInt32() + (int)relocation.VirtualAddress); var relInfo = (ushort *)(codeBase.ToInt32() + (int)directory.VirtualAddress + sizeOfBase); uint i; for (i = 0; i < ((relocation.SizeOfBlock - Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION))) / 2); i++, relInfo++) { int type = *relInfo >> 12; int offset = (*relInfo & 0xfff); switch (type) { case 0x00: break; case 0x03: var patchAddrHl = (uint *)((dest) + (offset)); * patchAddrHl += delta; break; } } } cnt += (int)relocation.SizeOfBlock; relocation = PointerHelpers.ToStruct <IMAGE_BASE_RELOCATION>(codeBase, (uint)(directory.VirtualAddress + cnt)); } } }
/// <summary> /// Rebuilds the PE import table after address relocations. /// </summary> public int BuildImportTable() { int ucount = GetModuleCount(); module.modules = Marshal.AllocHGlobal((ucount) * sizeof(int)); int pcount = 0; int result = 1; IntPtr codeBase = module.codeBase; IMAGE_DATA_DIRECTORY directory = module.headers.OptionalHeader.DataDirectory[1]; if (directory.Size > 0) { var importDesc = PointerHelpers.ToStruct <IMAGE_IMPORT_DESCRIPTOR>(codeBase, directory.VirtualAddress); while (importDesc.Name > 0) { var str = codeBase + (int)importDesc.Name; string tmp = Marshal.PtrToStringAnsi(str); unsafe { uint *thunkRef; uint *funcRef; int handle = Win32Imports.LoadLibrary(tmp); if (handle == -1) { result = 0; break; } if (importDesc.CharacteristicsOrOriginalFirstThunk > 0) { IntPtr thunkRefAddr = codeBase + (int)importDesc.CharacteristicsOrOriginalFirstThunk; thunkRef = (uint *)thunkRefAddr; funcRef = (uint *)(codeBase + (int)importDesc.FirstThunk); } else { thunkRef = (uint *)(codeBase + (int)importDesc.FirstThunk); funcRef = (uint *)(codeBase + (int)importDesc.FirstThunk); } for (; *thunkRef > 0; thunkRef++, funcRef++) { if ((*thunkRef & 0x80000000) != 0) { *funcRef = (uint)Win32Imports.GetProcAddress(new IntPtr(handle), new IntPtr(*thunkRef & 0xffff)); } else { var str2 = codeBase + (int)(*thunkRef) + 2; var tmpaa = Marshal.PtrToStringAnsi(str2); * funcRef = Win32Imports.GetProcAddress(new IntPtr(handle), tmpaa); } if (*funcRef == 0) { result = 0; break; } } pcount++; importDesc = PointerHelpers.ToStruct <IMAGE_IMPORT_DESCRIPTOR>(codeBase, directory.VirtualAddress + (uint)(Marshal.SizeOf(typeof(IMAGE_IMPORT_DESCRIPTOR)) * pcount)); } } } return(result); }