public String[] GetProcedures() { unsafe { IntPtr codeBase = this._module.codeBase; IMAGE_DATA_DIRECTORY directory = this._module.headers.OptionalHeader.DataDirectory[0]; if (directory.Size == 0) { return new String[] { } } ; IMAGE_EXPORT_DIRECTORY exports = PointerHelpers.ToStruct <IMAGE_EXPORT_DIRECTORY>(codeBase, directory.VirtualAddress); UInt32 *nameRef = (UInt32 *)new IntPtr(codeBase.ToInt32() + exports.AddressOfNames); UInt16 *ordinal = (UInt16 *)new IntPtr(codeBase.ToInt32() + exports.AddressOfNameOrdinals); String[] result = new String[exports.NumberOfNames]; for (UInt32 i = 0; i < exports.NumberOfNames; i++, nameRef++, ordinal++) { IntPtr str = new IntPtr(codeBase.ToInt32() + (Int32)(*nameRef)); result[i] = Marshal.PtrToStringAnsi(str); } return(result); } }
private static extern bool ReadProcessMemory( IntPtr hProcess, IntPtr lpBaseAddress, out IMAGE_EXPORT_DIRECTORY lpBuffer, int nSize, IntPtr lpNumberOfBytesRead );
IntPtr GetPtrFromFuncName(string funcName) { if (Disposed) { throw new ObjectDisposedException("DLLFromMemory"); } if (string.IsNullOrEmpty(funcName)) { throw new ArgumentException("funcName"); } if (!IsDll) { throw new InvalidOperationException("Loaded Module is not a DLL"); } if (!_initialized) { throw new InvalidOperationException("Dll is not initialized"); } IntPtr pDirectory = PtrAdd(pNTHeaders, Of.IMAGE_NT_HEADERS_OptionalHeader + (Is64BitProcess ? Of64.IMAGE_OPTIONAL_HEADER_ExportTable: Of32.IMAGE_OPTIONAL_HEADER_ExportTable)); IMAGE_DATA_DIRECTORY Directory = PtrRead <IMAGE_DATA_DIRECTORY>(pDirectory); if (Directory.Size == 0) { throw new DllException("Dll has no export table"); } IntPtr pExports = PtrAdd(pCode, Directory.VirtualAddress); IMAGE_EXPORT_DIRECTORY Exports = PtrRead <IMAGE_EXPORT_DIRECTORY>(pExports); if (Exports.NumberOfFunctions == 0 || Exports.NumberOfNames == 0) { throw new DllException("Dll exports no functions"); } IntPtr pNameRef = PtrAdd(pCode, Exports.AddressOfNames); IntPtr pOrdinal = PtrAdd(pCode, Exports.AddressOfNameOrdinals); for (int i = 0; i < Exports.NumberOfNames; i++, pNameRef = PtrAdd(pNameRef, sizeof(uint)), pOrdinal = PtrAdd(pOrdinal, sizeof(ushort))) { uint NameRef = PtrRead <uint>(pNameRef); ushort Ordinal = PtrRead <ushort>(pOrdinal); string curFuncName = Marshal.PtrToStringAnsi(PtrAdd(pCode, NameRef)); if (curFuncName == funcName) { if (Ordinal > Exports.NumberOfFunctions) { throw new DllException("Invalid function ordinal"); } IntPtr pAddressOfFunction = PtrAdd(pCode, (Exports.AddressOfFunctions + (uint)(Ordinal * 4))); return(PtrAdd(pCode, PtrRead <uint>(pAddressOfFunction))); } } throw new DllException("Dll exports no function named " + funcName); }
internal ExportedFunctionsParser( byte[] buff, IMAGE_EXPORT_DIRECTORY exportDirectory, IMAGE_SECTION_HEADER[] sectionHeaders ) : base(buff, 0) { _exportDirectory = exportDirectory; _sectionHeaders = sectionHeaders; }
internal ExportedFunctionsParser Constructor( byte[] buff, IMAGE_EXPORT_DIRECTORY exportDirectory, IMAGE_SECTION_HEADER[] sectionHeaders ) { var target = new ExportedFunctionsParser(buff, exportDirectory, sectionHeaders); return(target); // TODO: add assertions to method ExportedFunctionsParserTest.Constructor(Byte[], IMAGE_EXPORT_DIRECTORY, IMAGE_SECTION_HEADER[]) }
internal PeExportData(IMAGE_SECTION_HEADER header, Stream peStream) { _directory = peStream.Read <IMAGE_EXPORT_DIRECTORY>(); // read the name long nameOffset = (_directory.NameRva - header.VirtualAddress) + header.PointerToRawData; peStream.Seek(nameOffset, SeekOrigin.Begin); Name = peStream.ReadAsciiZeroTerminated(); _exportAddressTable = ReadExportAddresTable(header, peStream); _exportNameTable = ReadExportNameTable(header, peStream); _ordinalTable = ReadOrdinalTable(header, peStream); }
private static IntPtr GetProcAddress(IntPtr lpModuleBase, uint dwFunctionHash) { IMAGE_DOS_HEADER pIDH; IMAGE_NT_HEADERS pINH; pIDH = (IMAGE_DOS_HEADER)Marshal.PtrToStructure(lpModuleBase, typeof(IMAGE_DOS_HEADER)); pINH = (IMAGE_NT_HEADERS)Marshal.PtrToStructure( (IntPtr)((uint)lpModuleBase + pIDH.e_lfanew), typeof(IMAGE_NT_HEADERS)); if (pIDH.e_magic != 0x5A4D) { return(IntPtr.Zero); } if (pINH.Signature != 0x4550) { return(IntPtr.Zero); } IMAGE_EXPORT_DIRECTORY pIED = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure( (IntPtr)((uint)lpModuleBase + pINH.OptionalHeader.ExportTable.VirtualAddress), typeof(IMAGE_EXPORT_DIRECTORY)); uint addrFunctions = (uint)lpModuleBase + pIED.AddressOfFunctions; uint addrNames = (uint)lpModuleBase + pIED.AddressOfNames; uint addrNameOrdinals = (uint)lpModuleBase + pIED.AddressOfNameOrdinals; for (uint i = 0; i < pIED.NumberOfNames; i++) { string pszFunctionName = string.Empty; pszFunctionName = Marshal.PtrToStringAnsi((IntPtr)( (uint)lpModuleBase + (uint)Marshal.ReadInt32((IntPtr)(addrNames + (i * 4))))); if (FNVHash(pszFunctionName) == dwFunctionHash) { IntPtr lpFunctionRet = IntPtr.Zero; lpFunctionRet = (IntPtr)( (uint)lpModuleBase + (uint)Marshal.ReadInt32((IntPtr)((uint)lpModuleBase + pIED.AddressOfFunctions + (4 * Marshal.ReadInt16((IntPtr)((uint)lpModuleBase + pIED.AddressOfNameOrdinals + (i * 2))))))); return(lpFunctionRet); } } return(IntPtr.Zero); }
public void Parse() { var idh = _process.ReadValue <IMAGE_DOS_HEADER>(_module.BaseAddress); if (!idh.isValid) { throw new Exception("Invalid header."); } var exportTable = _process.Is64Bit() ? _process.ReadValue <IMAGE_NT_HEADERS64>(_module.BaseAddress + idh.e_lfanew).OptionalHeader.ExportTable : _process.ReadValue <IMAGE_NT_HEADERS32>(_module.BaseAddress + idh.e_lfanew).OptionalHeader.ExportTable; _ied = _process.ReadValue <IMAGE_EXPORT_DIRECTORY>(_module.BaseAddress + (int)exportTable.VirtualAddress); Exports = new ReadOnlyDictionary <string, IntPtr>(GetExports()); }
public void ImageExportDirectoryConstructorWorks_Test() { var exportDirectory = new IMAGE_EXPORT_DIRECTORY(RawStructures.RawExportDirectory, 2); Assert.Equal((uint)0x33221100, exportDirectory.Characteristics); Assert.Equal((uint)0x77665544, exportDirectory.TimeDateStamp); Assert.Equal((ushort)0x9988, exportDirectory.MajorVersion); Assert.Equal((ushort)0xbbaa, exportDirectory.MinorVersion); Assert.Equal(0xffeeddcc, exportDirectory.Name); Assert.Equal((uint)0x55443322, exportDirectory.Base); Assert.Equal((uint)0x44332211, exportDirectory.NumberOfFunctions); Assert.Equal(0x88776655, exportDirectory.NumberOfNames); Assert.Equal(0xccbbaa99, exportDirectory.AddressOfFunctions); Assert.Equal((uint)0x00ffeedd, exportDirectory.AddressOfNames); Assert.Equal((uint)0x55443322, exportDirectory.AddressOfNameOrdinals); }
/// <summary> /// Получает список функций в модуле /// </summary> /// <param name="process">Выбранный процесс</param> /// <param name="hModule">Адрес модуля</param> /// <returns></returns> public static ModuleFunctionCollection GetModuleFunctions(this Process process, IntPtr hModule) { MemoryManager memory = process.GetMemoryManager(); IMAGE_DOS_HEADER dosHeader = memory.Read <IMAGE_DOS_HEADER>(hModule); IMAGE_NT_HEADERS ntHeader = memory.Read <IMAGE_NT_HEADERS>(hModule + dosHeader.e_lfanew); IMAGE_EXPORT_DIRECTORY exportDirectory = memory.Read <IMAGE_EXPORT_DIRECTORY>(hModule + ntHeader.OptionalHeader.DataDirectory[0].VirtualAddress); ModuleFunction[] functions = new ModuleFunction[exportDirectory.NumberOfNames]; for (int index = 0; index < exportDirectory.NumberOfNames; index++) { string functionName = Encoding.UTF8.GetString(memory.ReadBytes((IntPtr)((uint)hModule + (uint)memory.Read <IntPtr>(hModule + (exportDirectory.AddressOfNames + index * 0x4))), X => X == 0).ToArray()); IntPtr functionAddress = (IntPtr)((uint)hModule + (uint)memory.Read <IntPtr>(hModule + (exportDirectory.AddressOfFunctions + index * 0x4))); functions[index] = new ModuleFunction(functionName, functionAddress); } return(new ModuleFunctionCollection(functions)); }
public UInt32?GetProcAddress(String name) { unsafe { IntPtr codeBase = this._module.codeBase; Int32? idx = null; IMAGE_DATA_DIRECTORY directory = this._module.headers.OptionalHeader.DataDirectory[0]; if (directory.Size == 0) { return(null); } IMAGE_EXPORT_DIRECTORY exports = PointerHelpers.ToStruct <IMAGE_EXPORT_DIRECTORY>(codeBase, directory.VirtualAddress); UInt32 *nameRef = (UInt32 *)new IntPtr(codeBase.ToInt32() + exports.AddressOfNames); UInt16 *ordinal = (UInt16 *)new IntPtr(codeBase.ToInt32() + exports.AddressOfNameOrdinals); for (UInt32 i = 0; i < exports.NumberOfNames; i++, nameRef++, ordinal++) { IntPtr str = new IntPtr(codeBase.ToInt32() + (Int32)(*nameRef)); String tmp = Marshal.PtrToStringAnsi(str); if (tmp == name) { idx = *ordinal; break; } } if (idx.HasValue) { UInt32 *tmpaa = (UInt32 *)(codeBase.ToInt32() + (exports.AddressOfFunctions + (idx.Value * 4))); UInt32 addr = (UInt32)((codeBase.ToInt32()) + (*tmpaa)); return(addr); } else { return(null); } } }
public static bool Inject(int pid, string dllPath) { if (!File.Exists(dllPath)) { return(false); } var hProcess = new SafeHandle(NativeMethods.OpenProcess(NativeMethods.ProcessAccessFlags.All, false, pid)); if (hProcess.IsInvalid) { return(false); } var lpLoadLibraryW = IntPtr.Zero; if (IntPtr.Size == 8 && NativeMethods.IsX86(hProcess)) { var snapshot = new SafeHandle(NativeMethods.CreateToolhelp32Snapshot(SnapshotFlags.Module32 | SnapshotFlags.Module, pid)); if (snapshot.IsInvalid) { return(false); } var me32 = new MODULEENTRY32(); me32.dwSize = (uint)Marshal.SizeOf(me32); if (!NativeMethods.Module32First(snapshot, ref me32)) { return(false); } do { if (me32.szModule.ToUpper() == "KERNEL32.DLL") { // DOS HEADER var dos = new IMAGE_DOS_HEADER(); if (!ReadProcessMemoryEx <IMAGE_DOS_HEADER>(hProcess, me32.hModule, out dos)) { break; } // NT HEADER var nt = new IMAGE_NT_HEADERS32(); if (!ReadProcessMemoryEx <IMAGE_NT_HEADERS32>(hProcess, new IntPtr(me32.hModule.ToInt64() + dos.e_lfanew), out nt)) { break; } // EXPORT TABLE var exports = new IMAGE_EXPORT_DIRECTORY(); if (!ReadProcessMemoryEx <IMAGE_EXPORT_DIRECTORY>(hProcess, new IntPtr(me32.hModule.ToInt64() + nt.OptionalHeader.ExportTable.VirtualAddress), out exports)) { break; } if (exports.NumberOfFunctions <= 0) { break; } var lpAddressOfNames = new byte[exports.NumberOfNames * 4]; var szTemp = new byte[14]; var dwTemp = new byte[4]; int len; if (!ReadProcessMemoryEx(hProcess, new IntPtr(me32.hModule.ToInt64() + exports.AddressOfNames), lpAddressOfNames)) { break; } for (int uIndex = 0; uIndex < exports.NumberOfNames; uIndex++) { if (!ReadProcessMemoryEx(hProcess, new IntPtr(me32.hModule.ToInt64() + BitConverter.ToInt32(lpAddressOfNames, uIndex * 4)), szTemp)) { break; } len = Array.IndexOf <byte>(szTemp, 0); if (len == -1) { len = szTemp.Length; } if (Encoding.ASCII.GetString(szTemp, 0, len) == "LoadLibraryW") { if (!ReadProcessMemoryEx(hProcess, new IntPtr(me32.hModule.ToInt64() + exports.AddressOfFunctions + (uIndex * 4)), dwTemp)) { return(false); } lpLoadLibraryW = new IntPtr(me32.hModule.ToInt64() + BitConverter.ToInt32(dwTemp, 0)); break; } } break; } } while (Module32Next(snapshot, ref me32)); } else { lpLoadLibraryW = NativeMethods.GetProcAddress(NativeMethods.GetModuleHandle("kernel32.dll"), "LoadLibraryW"); } if (lpLoadLibraryW == IntPtr.Zero) { return(false); } dllPath += "\0"; var size = new IntPtr(Encoding.Unicode.GetByteCount(dllPath)); var buff = Encoding.Unicode.GetBytes(dllPath); var hVAlloc = new SafeVMHandle(hProcess, NativeMethods.VirtualAllocEx(hProcess, IntPtr.Zero, size, NativeMethods.AllocationType.Commit, NativeMethods.MemoryProtection.ReadWrite)); if (hVAlloc.IsInvalid) { return(false); } IntPtr lpNumberOfBytesWritten; if (!NativeMethods.WriteProcessMemory(hProcess, hVAlloc, buff, size, out lpNumberOfBytesWritten) && lpNumberOfBytesWritten != size) { return(false); } IntPtr lpThreadId; var hThread = new SafeHandle(NativeMethods.CreateRemoteThread(hProcess, IntPtr.Zero, IntPtr.Zero, lpLoadLibraryW, hVAlloc, 0, out lpThreadId)); if (hThread.IsInvalid) { return(false); } NativeMethods.WaitForSingleObject(hThread, 0xFFFFFFFF); int exitCode; return(NativeMethods.GetExitCodeThread(hThread, out exitCode) && exitCode != 0); }
private ExportDirectory(PortableExecutableImage image, DataDirectory dataDirectory, Location location, IMAGE_EXPORT_DIRECTORY directory, string name, uint[] functionAddresses, uint[] functionNameAddresses, ushort[] functionOrdinals) : base(image, dataDirectory, location) { _name = name; _functionAddresses = functionAddresses; _functionNameAddresses = functionNameAddresses; _functionOrdinals = functionOrdinals; Characteristics = directory.Characteristics; TimeDateStamp = directory.TimeDateStamp; MajorVersion = directory.MajorVersion; MinorVersion = directory.MinorVersion; Name = directory.Name; Base = directory.Base; NumberOfFunctions = directory.NumberOfFunctions; NumberOfNames = directory.NumberOfNames; AddressOfFunctions = directory.AddressOfFunctions; AddressOfNames = directory.AddressOfNames; AddressOfNameOrdinals = directory.AddressOfNameOrdinals; }
private static async Task <ushort[]> BuildFunctionOrdinalsAsync(LocationCalculator calc, Stream stream, IMAGE_EXPORT_DIRECTORY directory) { var offset = calc.RVAToOffset(directory.AddressOfNameOrdinals).ToInt64(); stream.Seek(offset, SeekOrigin.Begin); var results = new ushort[directory.NumberOfNames]; for (var i = 0; i < directory.NumberOfNames; i++) { results[i] = await stream.ReadUInt16Async().ConfigureAwait(false); } return(results); }
private static async Task <string> BuildNameAsync(LocationCalculator calc, Stream stream, IMAGE_EXPORT_DIRECTORY directory) { var builder = new StringBuilder(256); var offset = calc.RVAToOffset(directory.Name).ToInt64(); stream.Seek(offset, SeekOrigin.Begin); while (true) { int value = await stream.ReadByteAsync().ConfigureAwait(false); if (value <= 0) { break; } var c = (char)value; builder.Append(c); } return(builder.ToString()); }
private static bool SafeGetExportFunctionInfo(IntPtr processHandle, IntPtr moduleHandle, IMAGE_EXPORT_DIRECTORY ied, uint[] nameOffsets, uint i, out ExportFunctionInfo functionInfo) { functionInfo = ExportFunctionInfo.Empty; if (!NativeProcess.ReadStringInternal((void *)processHandle, (byte *)moduleHandle + nameOffsets[i], out string functionName, false, Encoding.ASCII)) { return(false); } if (!NativeProcess.ReadUInt16Internal((void *)processHandle, (byte *)moduleHandle + ied.AddressOfNameOrdinals + (i * 2), out ushort ordinal)) { return(false); } if (!NativeProcess.ReadUInt32Internal((void *)processHandle, (byte *)moduleHandle + ied.AddressOfFunctions + (ordinal * 4), out uint addressOffset)) { return(false); } functionInfo = new ExportFunctionInfo((byte *)moduleHandle + addressOffset, functionName, ordinal); return(true); }
private static bool SafeGetExportTableInfo(IntPtr processHandle, IntPtr moduleHandle, out IMAGE_EXPORT_DIRECTORY ied, out uint[] nameOffsets) { ied = default; nameOffsets = Array2.Empty <uint>(); if (!NativeProcess.ReadUInt32Internal((void *)processHandle, (byte *)moduleHandle + 0x3C, out uint ntHeaderOffset)) { return(false); } if (!NativeProcess.Is64BitProcessInternal((void *)processHandle, out bool is64Bit)) { return(false); } uint iedRVA; if (is64Bit) { if (!NativeProcess.ReadUInt32Internal((void *)processHandle, (byte *)moduleHandle + ntHeaderOffset + 0x88, out iedRVA)) { return(false); } } else { if (!NativeProcess.ReadUInt32Internal((void *)processHandle, (byte *)moduleHandle + ntHeaderOffset + 0x78, out iedRVA)) { return(false); } } fixed(void *p = &ied) { if (!NativeProcess.ReadInternal((void *)processHandle, (byte *)moduleHandle + iedRVA, p, IMAGE_EXPORT_DIRECTORY.UnmanagedSize)) { return(false); } } if (ied.NumberOfNames == 0) { return(true); } nameOffsets = new uint[ied.NumberOfNames]; fixed(void *p = nameOffsets) { if (!NativeProcess.ReadInternal((void *)processHandle, (byte *)moduleHandle + ied.AddressOfNames, p, ied.NumberOfNames * 4)) { return(false); } } return(true); }
static void CloneExports(ref PeFile target, PeFile reference, string referencePath, string sectionName) { IMAGE_DATA_DIRECTORY tgtExportDirectory = target.ImageNtHeaders.OptionalHeader.DataDirectory[0]; IMAGE_DATA_DIRECTORY refExportDirectory = reference.ImageNtHeaders.OptionalHeader.DataDirectory[0]; if (!reference.HasValidExportDir) { throw new Exception("Reference DLL has no export directory"); } List <string> forwardNames = new List <string>(); foreach (ExportFunction export in reference.ExportedFunctions) { if (export.HasName) { forwardNames.Add(String.Format("{0}.{1}", referencePath, export.Name)); } else { forwardNames.Add(String.Format("{0}.#{1}", referencePath, export.Ordinal)); } } byte[] nullByte = new byte[1]; byte[] forwardNameBlock = forwardNames.SelectMany( s => Encoding.ASCII.GetBytes(s).Concat(nullByte) ).ToArray(); // Add a new section to hold the new export table uint newSectionSize = (uint)refExportDirectory.Size + (uint)forwardNameBlock.Length; IMAGE_SECTION_HEADER newSection = AddSection(ref target, sectionName, newSectionSize); uint delta = newSection.VirtualAddress - refExportDirectory.VirtualAddress; uint forwardOffset = (uint)(newSection.VirtualAddress + refExportDirectory.Size); // Clear existing export table (optional) // Array.Clear(target.Buff, (int)GetOffset(target.ImageExportDirectory), (int)tgtExportDirectory.Size); // Write our new export table into the section Array.Copy( reference.Buff, GetOffset(reference.ImageExportDirectory), target.Buff, newSection.PointerToRawData, refExportDirectory.Size ); // Add in our forward name block Array.Copy( forwardNameBlock, 0, target.Buff, newSection.PointerToRawData + refExportDirectory.Size, forwardNameBlock.Length ); IMAGE_EXPORT_DIRECTORY newExportDir = new IMAGE_EXPORT_DIRECTORY(target.Buff, newSection.PointerToRawData); newExportDir.AddressOfFunctions += (uint)delta; newExportDir.AddressOfNames += (uint)delta; newExportDir.AddressOfNameOrdinals += (uint)delta; // Link function addresses to forward names uint rawAddressOfFunctions = newExportDir.AddressOfFunctions.RVAtoFileMapping(target.ImageSectionHeaders); for (int i = 0; i < newExportDir.NumberOfFunctions; i++) { string forwardName = forwardNames[i]; uint offset = (uint)(rawAddressOfFunctions + 4 * i); target.Buff.SetUInt32(offset, forwardOffset); forwardOffset += (uint)forwardName.Length + 1; } // Apply delta to export names uint rawAddressOfNames = newExportDir.AddressOfNames.RVAtoFileMapping(target.ImageSectionHeaders); for (int i = 0; i < newExportDir.NumberOfNames; i++) { uint offset = (uint)(rawAddressOfNames + 4 * i); target.Buff.SetUInt32(offset, target.Buff.BytesToUInt32(offset) + delta); } // Correct the image size target.ImageNtHeaders.OptionalHeader.DataDirectory[0].VirtualAddress = newSection.VirtualAddress; target.ImageNtHeaders.OptionalHeader.DataDirectory[0].Size = newSectionSize; return; }
static void Main(string[] args) { bool nometa = false; bool nolabel = false; string mode; string fullpath_out; bool bigendian = false; List <string> mdlanimfiles; if (args.Length == 0) { Console.WriteLine("Split any binary files supported by SA Tools.\n"); Console.WriteLine("-Splitting using an XML template-"); Console.WriteLine("split template <xmlfile> [-data sourcepath] [output path]\n"); Console.WriteLine("-Splitting a binary file with INI data-"); Console.WriteLine("split binary <file> <inifile> [output path]\n"); Console.WriteLine("-Splitting a single item from a binary file without INI data-"); Console.WriteLine("split single <game> <file> <key> <address> <type> [output filename] [-p custom properties] [-name entryName]\n"); Console.WriteLine("-Splitting an NB file-"); Console.WriteLine("split nb <file> [output path] [-ini split ini file]\n"); Console.WriteLine("-Splitting SA2 MDL files-"); Console.WriteLine("split mdl <file> [output path] [-anim animation files]\n"); Console.WriteLine("-Splitting SA2B MDL files-"); Console.WriteLine("split mdl_b <file> [output path] [-anim animation files]\n"); Console.WriteLine("-Splitting dllexport entries from DLL files-"); Console.WriteLine("split dllexport <file> <type> <name> [-id array ID] [output path] [-p numparts]\n"); Console.WriteLine("Common switches: [-nometa], [-nolabel]"); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); return; } for (int u = 2; u < args.Length; u++) { if (args[u] == "-nometa") { nometa = true; } if (args[u] == "-nolabel") { nolabel = true; } } mode = args[0]; System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); switch (mode.ToLowerInvariant()) { case "binary": string fullpath_bin = Path.GetFullPath(args[1]); if (!File.Exists(fullpath_bin)) { Console.WriteLine("File {0} doesn't exist.", fullpath_bin); return; } Console.WriteLine("File: {0}", fullpath_bin); string fullpath_ini = Path.GetFullPath(args[2]); if (!File.Exists(fullpath_ini)) { Console.WriteLine("File {0} doesn't exist.", fullpath_ini); return; } Console.WriteLine("Data mapping: {0}", fullpath_ini); fullpath_out = Path.GetDirectoryName(fullpath_bin); if (args.Length > 3) { fullpath_out = args[3]; if (fullpath_out[fullpath_out.Length - 1] != '/') { fullpath_out = string.Concat(fullpath_out, '/'); } fullpath_out = Path.GetFullPath(fullpath_out); } Console.WriteLine("Output folder: {0}", fullpath_out); if (nometa) { Console.WriteLine("Labels are disabled"); } if (Path.GetExtension(args[1]).ToLowerInvariant() == ".dll") { SplitTools.SplitDLL.SplitDLL.SplitDLLFile(fullpath_bin, fullpath_ini, fullpath_out, nometa, nolabel); } else { SplitTools.Split.SplitBinary.SplitFile(fullpath_bin, fullpath_ini, fullpath_out, nometa, nolabel); } break; case "template": string dataFolder = ""; fullpath_out = ""; if (args.Length < 2) { Console.WriteLine("Insufficient arguments"); return; } if (!File.Exists(Path.GetFullPath(args[1]))) { Console.WriteLine("File {0} doesn't exist", Path.GetFullPath(args[1])); return; } for (int i = 2; i < args.Length; i++) { if (args[i] == "-nolabel") { nolabel = true; } else if (args[i] == "-nometa") { nometa = true; } else if (args[i] == "-data") { dataFolder = args[i + 1]; i++; } else { fullpath_out = args[i]; } } Templates.SplitTemplate template = ProjectFunctions.openTemplateFile(Path.GetFullPath(args[1])); if (template == null) { Console.WriteLine("Failed to open template: {0}", Path.GetFullPath(args[1])); return; } if (dataFolder == "") { dataFolder = ProjectFunctions.GetGamePath(template.GameInfo.GameName); } Console.WriteLine("Data folder: {0}", dataFolder); string iniFolder = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName), "..\\GameConfig", template.GameInfo.DataFolder)); Console.WriteLine("Splitting using template for {0} located at {1}", template.GameInfo.GameName, Path.GetFullPath(args[1])); if (!Directory.Exists(dataFolder)) { Console.WriteLine("\nData folder does not exist: {0}", Path.GetFullPath(dataFolder)); Console.WriteLine("Put your game files in {0} and run split again.", Path.GetFullPath(dataFolder)); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); return; } Console.WriteLine("INI folder: {0}", iniFolder); if (fullpath_out == "") { fullpath_out = Path.Combine(Environment.CurrentDirectory, template.GameInfo.GameName); } Console.WriteLine("Output folder: {0}", fullpath_out); foreach (Templates.SplitEntry splitEntry in template.SplitEntries) { if (!File.Exists(Path.Combine(dataFolder, splitEntry.SourceFile))) { Console.WriteLine("Split source file {0} doesn't exist", Path.Combine(dataFolder, splitEntry.SourceFile)); continue; } Console.WriteLine("\n{0}: {1}: {2}", splitEntry.CmnName == null ? "No description" : splitEntry.CmnName, splitEntry.SourceFile, splitEntry.IniFile + ".ini"); ProjectFunctions.SplitTemplateEntry(splitEntry, null, dataFolder, iniFolder, fullpath_out, true, nometa, nolabel); } if (template.SplitMDLEntries != null) { foreach (Templates.SplitEntryMDL splitEntryMDL in template.SplitMDLEntries) { if (!File.Exists(Path.Combine(dataFolder, splitEntryMDL.ModelFile))) { Console.WriteLine("Split MDL source file {0} doesn't exist", Path.Combine(dataFolder, splitEntryMDL.ModelFile)); continue; } Console.Write("\nSplitting MDL file: {0}", splitEntryMDL.ModelFile); ProjectFunctions.SplitTemplateMDLEntry(splitEntryMDL, null, dataFolder, fullpath_out); } } break; case "single": int startoffset = 0; string game = args[1]; string filepath = args[2]; string outPath = ""; uint key = uint.Parse(args[3], System.Globalization.NumberStyles.HexNumber); int eaddress = int.Parse(args[4], System.Globalization.NumberStyles.HexNumber); string entryName = ""; string props = ""; string etype = args[5]; if (args.Length > 6) { for (int a = 6; a < args.Length; a++) { switch (args[a]) { case "-name": entryName = args[a + 1]; a++; break; case "-offset": startoffset = int.Parse(args[a + 1], System.Globalization.NumberStyles.HexNumber); a++; break; case "-p": props = args[a + 1]; a++; break; default: outPath = args[a]; break; } } } // If no output filename is specified if (outPath == "") { outPath = Path.Combine(Environment.CurrentDirectory, eaddress.ToString("X8")); } // If an output name is specified without a path else if (Path.GetDirectoryName(outPath) == "") { outPath = Path.Combine(Environment.CurrentDirectory, outPath); } // If a path is specified without a filename else if (Path.GetFileName(outPath) == "") { outPath = Path.Combine(outPath, eaddress.ToString("X8")); } Console.WriteLine("Splitting from {0} (key: {1}) in {2}: {3} at {4}, offset: {5}", Path.GetFileName(filepath), key.ToString("X"), game.ToUpperInvariant(), etype, eaddress.ToString("X"), startoffset.ToString("X")); Console.WriteLine("Output path: {0}", Path.GetFullPath(outPath)); SplitTools.Split.SplitBinary.SplitManual(game, filepath, key, eaddress, etype, outPath, props, entryName, nometa, nolabel, startoffset); break; case "nb": case "nb_b": string fullpath_nb = Path.GetFullPath(args[1]); string path_ini = null; if (args[args.Length - 2].ToLowerInvariant() == "-ini") { path_ini = Path.GetFullPath(args[args.Length - 1]); } if (!File.Exists(fullpath_nb)) { Console.WriteLine("File {0} doesn't exist.", fullpath_nb); return; } Console.WriteLine("File: {0}", fullpath_nb); fullpath_out = Path.GetDirectoryName(fullpath_nb); if (args.Length > 2) { fullpath_out = args[2]; if (fullpath_out[fullpath_out.Length - 1] != '/') { fullpath_out = string.Concat(fullpath_out, '/'); } fullpath_out = Path.GetFullPath(fullpath_out); } Console.WriteLine("Output folder: {0}", fullpath_out); SplitTools.Split.SplitNB.SplitNBFile(fullpath_nb, false, fullpath_out, 1, path_ini); break; case "mdl": case "mdl_b": string fullpath_mdl = Path.GetFullPath(args[1]); if (!File.Exists(fullpath_mdl)) { Console.WriteLine("File {0} doesn't exist.", fullpath_mdl); return; } Console.Write("File: {0}", fullpath_mdl); if (mode == "mdl_b") { bigendian = true; Console.Write(" (Big Endian)\n"); } else { Console.Write(System.Environment.NewLine); } fullpath_out = Path.GetDirectoryName(fullpath_mdl); if (args.Length > 1) { fullpath_out = args[2]; if (fullpath_out[fullpath_out.Length - 1] != '/') { fullpath_out = string.Concat(fullpath_out, '/'); } fullpath_out = Path.GetFullPath(fullpath_out); } Console.WriteLine("Output path: {0}", fullpath_out); if (args.Length > 2) { mdlanimfiles = new List <string>(); Console.WriteLine("Animation files:"); for (int u = 3; u < args.Length; u++) { string animpath = Path.GetFullPath(args[u]); if (File.Exists(animpath)) { mdlanimfiles.Add(animpath); Console.WriteLine(animpath); } else { Console.WriteLine("File {0} doesn't exist.", animpath); } } SplitTools.SAArc.sa2MDL.Split(bigendian, fullpath_mdl, fullpath_out, mdlanimfiles.ToArray()); } else { SplitTools.SAArc.sa2MDL.Split(bigendian, fullpath_mdl, fullpath_out, null); } break; case "dllexport": int arrayid = -1; string fullpath_dllex = Path.GetFullPath(args[1]); string type = args[2]; string name = args[3]; string fileOutputPath = ""; if (args.Length > 4) { for (int u = 4; u < args.Length; u++) { if (args[u] == "-id") { arrayid = int.Parse(args[u + 1]); u++; } else { fileOutputPath = args[u]; } } } if (!File.Exists(fullpath_dllex)) { Console.WriteLine("File {0} doesn't exist.", fullpath_dllex); return; } Console.Write("File: {0}", fullpath_dllex); byte[] datafile = File.ReadAllBytes(fullpath_dllex); uint imageBase = SplitTools.HelperFunctions.SetupEXE(ref datafile).Value; Dictionary <string, int> exports; Dictionary <int, string> labels = new Dictionary <int, string>(); { int ptr = BitConverter.ToInt32(datafile, BitConverter.ToInt32(datafile, 0x3c) + 4 + 20 + 96); GCHandle handle = GCHandle.Alloc(datafile, GCHandleType.Pinned); IMAGE_EXPORT_DIRECTORY dir = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure( Marshal.UnsafeAddrOfPinnedArrayElement(datafile, ptr), typeof(IMAGE_EXPORT_DIRECTORY)); handle.Free(); exports = new Dictionary <string, int>(dir.NumberOfFunctions); int nameaddr = dir.AddressOfNames; int ordaddr = dir.AddressOfNameOrdinals; for (int i = 0; i < dir.NumberOfNames; i++) { string namex = datafile.GetCString(BitConverter.ToInt32(datafile, nameaddr), System.Text.Encoding.ASCII); int addr = BitConverter.ToInt32(datafile, dir.AddressOfFunctions + (BitConverter.ToInt16(datafile, ordaddr) * 4)); exports.Add(namex, addr); labels.Add(addr, namex); nameaddr += 4; ordaddr += 2; } Console.Write(" ({0} exports)\n", exports.Count); } if (!exports.ContainsKey(name)) { Console.WriteLine("The export table has no item named {0}", name); return; } int address = exports[name]; // If an array ID is specified, jump to the pointer needed and use it as the address to split if (arrayid != -1) { uint newpointer = ByteConverter.ToUInt32(datafile, address + arrayid * 4); address = (int)(newpointer - imageBase); } Console.WriteLine("{0} {1}:{2}", type, name, address.ToString("X8")); switch (type) { // Landtables case "landtable": case "sa1landtable": case "sadxlandtable": case "sa2landtable": case "sa2blandtable": case "battlelandtable": LandTableFormat landfmt_cur; string landext; switch (type) { case "sa1landtable": landfmt_cur = LandTableFormat.SA1; landext = ".sa1lvl"; break; case "sadxlandtable": landfmt_cur = LandTableFormat.SADX; landext = ".sa1lvl"; break; case "sa2landtable": landfmt_cur = LandTableFormat.SA2; landext = ".sa2lvl"; break; case "sa2blandtable": case "battlelandtable": landfmt_cur = LandTableFormat.SA2B; landext = ".sa2blvl"; break; case "landtable": default: landfmt_cur = LandTableFormat.SADX; landext = ".sa1lvl"; break; } LandTable land = new LandTable(datafile, address, imageBase, landfmt_cur, labels); fileOutputPath = MakePathThatExists(fileOutputPath, land.Name + landext); if (!Directory.Exists(Path.GetDirectoryName(fileOutputPath))) { Directory.CreateDirectory(Path.GetDirectoryName(fileOutputPath)); } land.SaveToFile(fileOutputPath, landfmt_cur, nometa); break; // NJS_OBJECT case "model": case "object": case "basicmodel": case "basicdxmodel": case "chunkmodel": case "gcmodel": { ModelFormat modelfmt_obj; string modelext; switch (type) { case "basicmodel": modelfmt_obj = ModelFormat.Basic; modelext = ".sa1mdl"; break; case "basicdxmodel": modelfmt_obj = ModelFormat.BasicDX; modelext = ".sa1mdl"; break; case "chunkmodel": modelfmt_obj = ModelFormat.Chunk; modelext = ".sa2mdl"; break; case "gcmodel": modelfmt_obj = ModelFormat.GC; modelext = ".sa2bmdl"; break; default: modelfmt_obj = ModelFormat.BasicDX; modelext = ".sa1mdl"; break; } NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, modelfmt_obj, labels, new Dictionary <int, Attach>()); fileOutputPath = MakePathThatExists(fileOutputPath, mdl.Name + modelext); if (!Directory.Exists(Path.GetDirectoryName(fileOutputPath))) { Directory.CreateDirectory(Path.GetDirectoryName(fileOutputPath)); } ModelFile.CreateFile(fileOutputPath, mdl, null, null, null, null, modelfmt_obj, nometa); } break; // NJS_MOTION case "animation": case "motion": int numparts = 0; for (int a = 3; a < args.Length; a++) { if (args[a] == "-p") { numparts = int.Parse(args[a + 1], System.Globalization.NumberStyles.Integer); } } NJS_MOTION ani = new NJS_MOTION(datafile, address, imageBase, numparts, labels); fileOutputPath = MakePathThatExists(fileOutputPath, ani.Name + "saanim"); string outpath = Path.GetDirectoryName(Path.GetFullPath(fileOutputPath)); Console.WriteLine("Output file: {0}", Path.GetFullPath(fileOutputPath)); if (!Directory.Exists(outpath)) { Directory.CreateDirectory(outpath); } ani.Save(fileOutputPath, nometa); break; // Attach case "attach": case "basicattach": case "basicdxattach": case "chunkattach": case "gcattach": { Attach dummy; ModelFormat modelfmt_att; string modelext = ".sa1mdl"; switch (type) { case "basicattach": modelfmt_att = ModelFormat.Basic; modelext = ".sa1mdl"; dummy = new BasicAttach(datafile, address, imageBase, false); break; case "basicdxattach": modelfmt_att = ModelFormat.BasicDX; modelext = ".sa1mdl"; dummy = new BasicAttach(datafile, address, imageBase, true); break; case "chunkattach": modelfmt_att = ModelFormat.Chunk; modelext = ".sa2mdl"; dummy = new ChunkAttach(datafile, address, imageBase); break; case "gcattach": modelfmt_att = ModelFormat.GC; dummy = new SAModel.GC.GCAttach(datafile, address, imageBase); modelext = ".sa2bmdl"; break; default: modelfmt_att = ModelFormat.BasicDX; modelext = ".sa1mdl"; dummy = new BasicAttach(datafile, address, imageBase, true); break; } NJS_OBJECT mdl = new NJS_OBJECT() { Attach = dummy }; fileOutputPath = MakePathThatExists(fileOutputPath, mdl.Name + modelext); if (!Directory.Exists(Path.GetDirectoryName(fileOutputPath))) { Directory.CreateDirectory(Path.GetDirectoryName(fileOutputPath)); } ModelFile.CreateFile(fileOutputPath, mdl, null, null, null, null, modelfmt_att, nometa); } break; default: Console.WriteLine("Unrecognized export type {0}", type); break; } break; default: Console.WriteLine("Incorrect mode specified. Press ENTER to exit."); Console.ReadLine(); return; } }
private static bool GetExportTableInfo(IntPtr processHandle, IntPtr moduleHandle, out IMAGE_EXPORT_DIRECTORY ied, out uint[] nameOffsets) { uint ntHeaderOffset; bool is64Bit; uint iedRVA; ied = default(IMAGE_EXPORT_DIRECTORY); nameOffsets = null; if (!NativeProcess.ReadUInt32Internal(processHandle, (IntPtr)((byte *)moduleHandle + 0x3C), out ntHeaderOffset)) { return(false); } if (!NativeProcess.Is64BitProcessInternal(processHandle, out is64Bit)) { return(false); } if (is64Bit) { if (!NativeProcess.ReadUInt32Internal(processHandle, (IntPtr)((byte *)moduleHandle + ntHeaderOffset + 0x88), out iedRVA)) { return(false); } } else { if (!NativeProcess.ReadUInt32Internal(processHandle, (IntPtr)((byte *)moduleHandle + ntHeaderOffset + 0x78), out iedRVA)) { return(false); } } fixed(void *p = &ied) if (!ReadProcessMemory(processHandle, (IntPtr)((byte *)moduleHandle + iedRVA), p, IMAGE_EXPORT_DIRECTORY.UnmanagedSize, null)) { return(false); } if (ied.NumberOfNames == 0) { return(true); } nameOffsets = new uint[ied.NumberOfNames]; fixed(void *p = nameOffsets) if (!ReadProcessMemory(processHandle, (IntPtr)((byte *)moduleHandle + ied.AddressOfNames), p, ied.NumberOfNames * 4, null)) { return(false); } return(true); }
public PESupport(string LibraryName) { Debug.Assert(LibraryName != null); this.LibraryName = LibraryName; hLibrary = IntPtr.Zero; IntPtr original_hLibrary = LoadLibraryEx(this.LibraryName, IntPtr.Zero, LoadLibraryFlags.DONT_RESOLVE_DLL_REFERENCES); // access violations occur with LOAD_LIBRARY_AS_DATAFILE, but don't with DONT_RESOLVE_DLL_REFERENCES for some reason hLibrary = new IntPtr(original_hLibrary.ToInt32() - original_hLibrary.ToInt32() % 4); // adjust things to a DWORD boundary int error = Marshal.GetLastWin32Error(); if (hLibrary == null && error != 0) { throw new System.ApplicationException("Got error " + error + " when loading library " + LibraryName); } // do some sanity checking dosHeader = (IMAGE_DOS_HEADER)Marshal.PtrToStructure(hLibrary, typeof(IMAGE_DOS_HEADER)); if (!dosHeader.isValid) { throw new System.ApplicationException("Library does not appear to be a valid DOS file!"); } ntHeader = (IMAGE_NT_HEADERS32)Marshal.PtrToStructure(hLibrary + dosHeader.e_lfanew, typeof(IMAGE_NT_HEADERS32)); if (!ntHeader.isValid) { throw new System.ApplicationException("Library NT Header does not appear valid!"); } fileHeader = ntHeader.FileHeader; if (fileHeader.Machine != (UInt16)(MachineType.I386)) { throw new System.ApplicationException("Library appears to be compiled for x64 while this program only supports x86 libraries."); } optionalHeader = ntHeader.OptionalHeader; exports = new Dictionary<int, List<string>>(); // if we don't have an export directory, move on if (optionalHeader.ExportTable.VirtualAddress == 0 || optionalHeader.ExportTable.Size == 0) { FreeLibrary(original_hLibrary); return; } // initialise the export header exportHeader = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(hLibrary + (int)optionalHeader.ExportTable.VirtualAddress, typeof(IMAGE_EXPORT_DIRECTORY)); for (int i = 0; i < exportHeader.NumberOfNames; i++) { // grab the pointer to the next entry in the string table. In C, this would be a char* IntPtr namePtr = (IntPtr)Marshal.PtrToStructure(hLibrary + (int)(exportHeader.AddressOfNames) + (4 * i), typeof(IntPtr)); // dereference the previous char* string name; try { name = Marshal.PtrToStringAnsi(hLibrary + namePtr.ToInt32()); } catch (Exception ex) { name = ""; Console.WriteLine(ex.StackTrace); } // grab the address for this function int address = ((IntPtr)Marshal.PtrToStructure(hLibrary + (int)(exportHeader.AddressOfFunctions) + 4 * i, typeof(IntPtr))).ToInt32(); address += (int)optionalHeader.ImageBase; if (exports.ContainsKey(address)) { exports[address].Add(name); } else { exports[address] = new List<string>(); exports[address].Add(name); } } FreeLibrary(original_hLibrary); }
static void Main(string[] args) { bool nometa = false; bool nolabel = false; string mode; string fullpath_out; bool bigendian = false; List <string> mdlanimfiles; if (args.Length == 0) { Console.WriteLine("Split any binary files supported by SA Tools.\n"); Console.WriteLine("Usage:\n"); Console.WriteLine("-Splitting binary files with INI data-"); Console.WriteLine("split binary <file> <inifile> [output path] [-nometa] [-nolabel]\n"); Console.WriteLine("-Splitting SA1/SADX NB files-"); Console.WriteLine("split nb <file> [output path] -ini [split INI file]\n"); Console.WriteLine("-Splitting SA2 MDL files-"); Console.WriteLine("split mdl <file> [output path] -anim [animation files]\n"); Console.WriteLine("-Splitting SA2B MDL files-"); Console.WriteLine("split mdl_b <file> [output path] -anim [animation files]\n"); Console.WriteLine("-Splitting dllexport entries from DLL files-"); Console.WriteLine("split dllexport <file> <type> <name> [output path] [-p numparts]\n"); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); return; } #if DEBUG if (SplitExtensions(args) == true) { return; } #endif for (int u = 2; u < args.Length; u++) { if (args[u] == "-nometa") { nometa = true; } if (args[u] == "-nolabel") { nolabel = true; } } mode = args[0]; switch (mode.ToLowerInvariant()) { case "binary": string fullpath_bin = Path.GetFullPath(args[1]); if (!File.Exists(fullpath_bin)) { Console.WriteLine("File {0} doesn't exist.", fullpath_bin); return; } Console.WriteLine("File: {0}", fullpath_bin); string fullpath_ini = Path.GetFullPath(args[2]); if (!File.Exists(fullpath_ini)) { Console.WriteLine("File {0} doesn't exist.", fullpath_ini); return; } Console.WriteLine("Data mapping: {0}", fullpath_ini); fullpath_out = Path.GetDirectoryName(fullpath_bin); if (args.Length > 3) { fullpath_out = args[3]; if (fullpath_out[fullpath_out.Length - 1] != '/') { fullpath_out = string.Concat(fullpath_out, '/'); } fullpath_out = Path.GetFullPath(fullpath_out); } Console.WriteLine("Output folder: {0}", fullpath_out); if (nometa) { Console.WriteLine("Labels are disabled"); } if (Path.GetExtension(args[1]).ToLowerInvariant() == ".dll") { SA_Tools.SplitDLL.SplitDLL.SplitDLLFile(fullpath_bin, fullpath_ini, fullpath_out, nometa, nolabel); } else { SA_Tools.Split.Split.SplitFile(fullpath_bin, fullpath_ini, fullpath_out, nometa, nolabel); } break; case "nb": case "nb_b": string fullpath_nb = Path.GetFullPath(args[1]); string path_ini = null; if (args[args.Length - 2].ToLowerInvariant() == "-ini") { path_ini = Path.GetFullPath(args[args.Length - 1]); } if (!File.Exists(fullpath_nb)) { Console.WriteLine("File {0} doesn't exist.", fullpath_nb); return; } Console.WriteLine("File: {0}", fullpath_nb); fullpath_out = Path.GetDirectoryName(fullpath_nb); if (args.Length > 2) { fullpath_out = args[2]; if (fullpath_out[fullpath_out.Length - 1] != '/') { fullpath_out = string.Concat(fullpath_out, '/'); } fullpath_out = Path.GetFullPath(fullpath_out); } Console.WriteLine("Output folder: {0}", fullpath_out); SA_Tools.Split.SplitNB.SplitNBFile(fullpath_nb, false, fullpath_out, 1, path_ini); break; case "mdl": case "mdl_b": string fullpath_mdl = Path.GetFullPath(args[1]); if (!File.Exists(fullpath_mdl)) { Console.WriteLine("File {0} doesn't exist.", fullpath_mdl); return; } Console.Write("File: {0}", fullpath_mdl); if (mode == "mdl_b") { bigendian = true; Console.Write(" (Big Endian)\n"); } else { Console.Write(System.Environment.NewLine); } fullpath_out = Path.GetDirectoryName(fullpath_mdl); if (args.Length > 2) { fullpath_out = args[2]; if (fullpath_out[fullpath_out.Length - 1] != '/') { fullpath_out = string.Concat(fullpath_out, '/'); } fullpath_out = Path.GetFullPath(fullpath_out); } Console.WriteLine("Output path: {0}", fullpath_out); if (args.Length > 3) { mdlanimfiles = new List <string>(); Console.WriteLine("Animation files:"); for (int u = 3; u < args.Length; u++) { string animpath = Path.GetFullPath(args[u]); if (File.Exists(animpath)) { mdlanimfiles.Add(animpath); Console.WriteLine(animpath); } else { Console.WriteLine("File {0} doesn't exist.", animpath); } } SA_Tools.SAArc.sa2MDL.Split(bigendian, fullpath_mdl, fullpath_out, mdlanimfiles.ToArray()); } else { SA_Tools.SAArc.sa2MDL.Split(bigendian, fullpath_mdl, fullpath_out, null); } break; case "dllexport": string fullpath_dllex = Path.GetFullPath(args[1]); string type = args[2]; string name = args[3]; string fileOutputPath = ""; if (args.Length > 4) { for (int i = 4; i < args.Length; i++) { if (args[i].Substring(0, 1) != "-" && args[i - 1].Substring(0, 1) != "-") { fileOutputPath = args[i]; } } } if (!File.Exists(fullpath_dllex)) { Console.WriteLine("File {0} doesn't exist.", fullpath_dllex); return; } Console.Write("File: {0}", fullpath_dllex); byte[] datafile = File.ReadAllBytes(fullpath_dllex); uint imageBase = SA_Tools.HelperFunctions.SetupEXE(ref datafile).Value; Dictionary <string, int> exports; Dictionary <int, string> labels = new Dictionary <int, string>(); { int ptr = BitConverter.ToInt32(datafile, BitConverter.ToInt32(datafile, 0x3c) + 4 + 20 + 96); GCHandle handle = GCHandle.Alloc(datafile, GCHandleType.Pinned); IMAGE_EXPORT_DIRECTORY dir = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure( Marshal.UnsafeAddrOfPinnedArrayElement(datafile, ptr), typeof(IMAGE_EXPORT_DIRECTORY)); handle.Free(); exports = new Dictionary <string, int>(dir.NumberOfFunctions); int nameaddr = dir.AddressOfNames; int ordaddr = dir.AddressOfNameOrdinals; for (int i = 0; i < dir.NumberOfNames; i++) { string namex = datafile.GetCString(BitConverter.ToInt32(datafile, nameaddr), System.Text.Encoding.ASCII); int addr = BitConverter.ToInt32(datafile, dir.AddressOfFunctions + (BitConverter.ToInt16(datafile, ordaddr) * 4)); exports.Add(namex, addr); labels.Add(addr, namex); nameaddr += 4; ordaddr += 2; } Console.Write(" ({0} exports)\n", exports.Count); } if (!exports.ContainsKey(name)) { Console.WriteLine("The export table has no item named {0}", name); return; } int address = exports[name]; Console.WriteLine("{0} {1}:{2}", type, name, address.ToString("X8")); switch (type) { // Landtables case "landtable": case "sa1landtable": case "sadxlandtable": case "sa2landtable": case "sa2blandtable": case "battlelandtable": LandTableFormat landfmt_cur; string landext; switch (type) { case "sa1landtable": landfmt_cur = LandTableFormat.SA1; landext = ".sa1lvl"; break; case "sadxlandtable": landfmt_cur = LandTableFormat.SADX; landext = ".sa1lvl"; break; case "sa2landtable": landfmt_cur = LandTableFormat.SA2; landext = ".sa2lvl"; break; case "sa2blandtable": case "battlelandtable": landfmt_cur = LandTableFormat.SA2B; landext = ".sa2blvl"; break; case "landtable": default: landfmt_cur = LandTableFormat.SADX; landext = ".sa1lvl"; break; } LandTable land = new LandTable(datafile, address, imageBase, landfmt_cur, labels); if (fileOutputPath == "") { fileOutputPath = land.Name + landext; } if (!Directory.Exists(Path.GetDirectoryName(fileOutputPath))) { Directory.CreateDirectory(Path.GetDirectoryName(fileOutputPath)); } land.SaveToFile(fileOutputPath, landfmt_cur, nometa); break; // NJS_OBJECT case "model": case "object": case "basicmodel": case "basicdxmodel": case "chunkmodel": case "gcmodel": { ModelFormat modelfmt_obj; string modelext; switch (type) { case "basicmodel": modelfmt_obj = ModelFormat.Basic; modelext = ".sa1mdl"; break; case "basicdxmodel": modelfmt_obj = ModelFormat.BasicDX; modelext = ".sa1mdl"; break; case "chunkmodel": modelfmt_obj = ModelFormat.Chunk; modelext = ".sa2mdl"; break; case "gcmodel": modelfmt_obj = ModelFormat.GC; modelext = ".sa2bmdl"; break; default: modelfmt_obj = ModelFormat.BasicDX; modelext = ".sa1mdl"; break; } NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, modelfmt_obj, labels, new Dictionary <int, Attach>()); if (fileOutputPath == "") { fileOutputPath = mdl.Name + modelext; } if (!Directory.Exists(Path.GetDirectoryName(fileOutputPath))) { Directory.CreateDirectory(Path.GetDirectoryName(fileOutputPath)); } ModelFile.CreateFile(fileOutputPath, mdl, null, null, null, null, modelfmt_obj, nometa); } break; // NJS_MOTION case "animation": case "motion": int numparts = 0; for (int a = 3; a < args.Length; a++) { if (args[a] == "-p") { numparts = int.Parse(args[a + 1], System.Globalization.NumberStyles.Integer); } } NJS_MOTION ani = new NJS_MOTION(datafile, address, imageBase, numparts, labels); if (fileOutputPath == "") { fileOutputPath = ani.Name + ".saanim"; } string outpath = Path.GetDirectoryName(Path.GetFullPath(fileOutputPath)); Console.WriteLine("Output file: {0}", Path.GetFullPath(fileOutputPath)); if (!Directory.Exists(outpath)) { Directory.CreateDirectory(outpath); } ani.Save(fileOutputPath, nometa); break; default: Console.WriteLine("Unrecognized export type {0}", type); break; } break; default: Console.WriteLine("Incorrect mode specified. Press ENTER to exit."); Console.ReadLine(); return; } }
public unsafe static int ProcGetExpAddress( IntPtr hprocess, IntPtr hmodule, string exportnname) { byte[] Forread = new byte[8]; uint BytesRead = 0; int PEOffset = 0; int ExportDirectoryRVA = 0; int ExportDirectorySize = 0; if (!ReadProcessMemory(hprocess, (IntPtr)((long)hmodule + 0x3C), Forread, 4, ref BytesRead)) { return(-1); } PEOffset = BitConverter.ToInt32(Forread, 0); if (!ReadProcessMemory(hprocess, (IntPtr)((long)hmodule + PEOffset + 0x78), Forread, 8, ref BytesRead)) { return(-1); } try { ExportDirectoryRVA = BitConverter.ToInt32(Forread, 0); ExportDirectorySize = BitConverter.ToInt32(Forread, 4); Forread = new byte[ExportDirectorySize]; if (!ReadProcessMemory(hprocess, (IntPtr)((long)hmodule + ExportDirectoryRVA), Forread, (uint)ExportDirectorySize, ref BytesRead)) { return(-1); } IntPtr ptPoit = Marshal.AllocHGlobal(ExportDirectorySize); Marshal.Copy(Forread, 0, ptPoit, ExportDirectorySize); IMAGE_EXPORT_DIRECTORY IED = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(ptPoit, typeof(IMAGE_EXPORT_DIRECTORY)); Marshal.FreeHGlobal(ptPoit); int[] funcaddresses = new int[IED.NumberOfFunctions]; int[] funcnames = new int[IED.NumberOfNames]; ushort[] ordinals = new ushort[IED.NumberOfFunctions]; byte[] keeper = new byte[IED.NumberOfFunctions * 4]; if (!ReadProcessMemory(hprocess, (IntPtr)((long)hmodule + IED.AddressOfFunctions), keeper, (uint)IED.NumberOfFunctions * 4, ref BytesRead)) { return(-1); } for (int i = 0; i < funcaddresses.Length; i++) { funcaddresses[i] = BitConverter.ToInt32(keeper, i * 4); } if (!ReadProcessMemory(hprocess, (IntPtr)((long)hmodule + IED.AddressOfNames), keeper, (uint)IED.NumberOfNames * 4, ref BytesRead)) { return(-1); } for (int i = 0; i < funcnames.Length; i++) { funcnames[i] = BitConverter.ToInt32(keeper, i * 4); } if (!ReadProcessMemory(hprocess, (IntPtr)((long)hmodule + IED.AddressOfNameOrdinals), keeper, (uint)IED.NumberOfFunctions * 2, ref BytesRead)) { return(-1); } for (int i = 0; i < funcnames.Length; i++) { ordinals[i] = BitConverter.ToUInt16(keeper, i * 2); } // wrong: the first name is CLRCreateInstance for (int i = 0; i < funcnames.Length; i++) { if (funcnames[i] != 0) { byte[] currentchar = new byte[1]; int count = 0; string funcname = ""; while (ReadProcessMemory(hprocess, (IntPtr)((long)hmodule + funcnames[i] + count), currentchar, 1, ref BytesRead) && currentchar[0] != 0) { funcname = funcname + (char)currentchar[0]; count++; } if (funcname == exportnname) { return(funcaddresses[ordinals[i]]); } } } } catch { return(-1); } return(-1); }
public IntPtr GetRemoteProcAddress(IntPtr ptrHandle, IntPtr hBaseAddress, string sProcName) { IMAGE_DOS_HEADER32 dosHeader = new IMAGE_DOS_HEADER32(); uint uiSignature = 0; IMAGE_FILE_HEADER fileHeader = new IMAGE_FILE_HEADER(); IMAGE_OPTIONAL_HEADER32 optHeader32 = new IMAGE_OPTIONAL_HEADER32(); IMAGE_DATA_DIRECTORY exportDirectory = new IMAGE_DATA_DIRECTORY(); IMAGE_EXPORT_DIRECTORY exportTable = new IMAGE_EXPORT_DIRECTORY(); IntPtr ptrFunctionTable = IntPtr.Zero; IntPtr ptrNameTable = IntPtr.Zero; IntPtr ptrOrdinalTable = IntPtr.Zero; if (ptrHandle == IntPtr.Zero || hBaseAddress == IntPtr.Zero) { WriteError("Invalid call."); return(IntPtr.Zero); } IntPtr ptrNumBytesRead = IntPtr.Zero; if (!ReadProcessMemory(ptrHandle, hBaseAddress, &dosHeader, Marshal.SizeOf(dosHeader), out ptrNumBytesRead)) { WriteError("Failed. Error code: " + Marshal.GetLastWin32Error().ToString()); return(IntPtr.Zero); } if (dosHeader.e_magic != 0x5A4D) { WriteError("Image is not a valid DLL. " + dosHeader.e_magic.ToString()); return(IntPtr.Zero); } if (!ReadProcessMemory(ptrHandle, hBaseAddress + (dosHeader.e_lfanew), &uiSignature, Marshal.SizeOf(uiSignature), out ptrNumBytesRead)) { WriteError("Failed. Error code: " + Marshal.GetLastWin32Error().ToString()); return(IntPtr.Zero); } if (uiSignature != 0x4550) { WriteError("Invalid NT signature..."); return(IntPtr.Zero); } if (!ReadProcessMemory(ptrHandle, hBaseAddress + (dosHeader.e_lfanew + Marshal.SizeOf(uiSignature)), &fileHeader, Marshal.SizeOf(fileHeader), out ptrNumBytesRead)) { WriteError("Failed. Error code: " + Marshal.GetLastWin32Error().ToString()); return(IntPtr.Zero); } if (!ReadProcessMemory(ptrHandle, hBaseAddress + (dosHeader.e_lfanew + Marshal.SizeOf(uiSignature) + Marshal.SizeOf(fileHeader)), &optHeader32, Marshal.SizeOf(optHeader32), out ptrNumBytesRead)) { WriteError("Failed. Error code: " + Marshal.GetLastWin32Error().ToString()); return(IntPtr.Zero); } if (optHeader32.NumberOfRvaAndSizes >= 1) { exportDirectory.VirtualAddress = (optHeader32.ExportTable.VirtualAddress); exportDirectory.Size = (optHeader32.ExportTable.Size); } else { WriteError("No export table found."); return(IntPtr.Zero); } if (!ReadProcessMemory(ptrHandle, hBaseAddress + (int)(exportDirectory.VirtualAddress), &exportTable, Marshal.SizeOf(exportTable), out ptrNumBytesRead)) { WriteError("Failed. Error code: " + Marshal.GetLastWin32Error().ToString()); return(IntPtr.Zero); } uint[] uiExportFuncTable = ReadUIntArray(ptrHandle, hBaseAddress + (int)(exportTable.AddressOfFunctions), (int)exportTable.NumberOfFunctions); uint[] uiExportNameTable = ReadUIntArray(ptrHandle, hBaseAddress + (int)(exportTable.AddressOfNames), (int)exportTable.NumberOfNames); short[] usExportOrdinalTable = ReadShortArray(ptrHandle, hBaseAddress + (int)(exportTable.AddressOfNameOrdinals), (int)exportTable.NumberOfNames); for (int i = 0; i < exportTable.NumberOfNames; i++) { if (ReadString(ptrHandle, hBaseAddress + (int)(uiExportNameTable[i])) == sProcName) { return(new IntPtr((int)hBaseAddress + uiExportFuncTable[usExportOrdinalTable[i]])); } } WriteError("Unable to find the provided procedure name!"); return(IntPtr.Zero); }
public unsafe int RandomizeImportTable() { string[] xp_dll_paths = Directory.GetFiles(ImportDirectory).Where(file => Path.GetExtension(file) == ".dll").ToArray(); for (int i = 0; i < xp_dll_paths.Length; i++) { ImportDLL xp_dll = new ImportDLL(); // ImportDLL win8_dll = new ImportDLL(); // xp xp_dll.ModulePath = xp_dll_paths[i]; xp_dll.ModuleName = Path.GetFileNameWithoutExtension(xp_dll.ModulePath).ToUpper(); xp_dll.LoadedAddress = LoadLibraryEx(xp_dll.ModulePath, IntPtr.Zero, 0x1); xp_dll.Functions = new Dictionary <string, IntPtr>(); XP_DLLS.Add(xp_dll); // win8 //win8_dll.ModuleName = xp_dll.ModuleName; //win8_dll.ModulePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.SystemX86), win8_dll.ModuleName); //win8_dll.LoadedAddress = LoadLibraryEx(win8_dll.ModulePath, IntPtr.Zero, 0x00000001); //win8_dll.Functions = new Dictionary<string, IntPtr>(); //WIN8_DLLS.Add(win8_dll); } // walk exports to find functions to use foreach (ImportDLL IDLL in XP_DLLS) { IMAGE_DOS_HEADER pIDH = (IMAGE_DOS_HEADER)Marshal.PtrToStructure(IDLL.LoadedAddress, typeof(IMAGE_DOS_HEADER)); IMAGE_NT_HEADERS32 pINH = (IMAGE_NT_HEADERS32)Marshal.PtrToStructure((IntPtr)(IDLL.LoadedAddress + pIDH.e_lfanew), typeof(IMAGE_NT_HEADERS32)); IMAGE_DATA_DIRECTORY ExportDirectory = pINH.OptionalHeader.ExportTable; IMAGE_EXPORT_DIRECTORY pIED = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(((IntPtr)IDLL.LoadedAddress + (int)ExportDirectory.VirtualAddress), typeof(IMAGE_EXPORT_DIRECTORY)); int NumberOfNamedFunctions = (int)pIED.NumberOfNames; uint *lpAddressOfNames = (uint *)(IDLL.LoadedAddress + (int)pIED.AddressOfNames); uint *lpAddressOfFunctions = (uint *)(IDLL.LoadedAddress + (int)pIED.AddressOfFunctions); uint *lpAddressOfNameOrdinals = (uint *)(IDLL.LoadedAddress + (int)pIED.AddressOfNameOrdinals); for (int i = 0; i < NumberOfNamedFunctions; i++) { uint lpFuncNameRVA = lpAddressOfNames[i]; char * szFuncName = (char *)(IDLL.LoadedAddress + (int)lpFuncNameRVA); string FuncName = Marshal.PtrToStringAnsi((IntPtr)szFuncName); IDLL.Functions.Add(FuncName, GetProcAddress(IDLL.LoadedAddress, FuncName)); } } // generate random amount of modules of which to select the functions from int ModuleCount = Rand.Next(2, 4); List <ImportDLL> AllModules = new List <ImportDLL>(); List <ImportDLL> SelectedModules = new List <ImportDLL>(); foreach (ImportDLL IDLL in XP_DLLS) { AllModules.Add(IDLL); } // Base modules //SelectedModules.Add(XP_DLLS.Where(DLL => DLL.ModuleName == "KERNEL32").First()); //SelectedModules.Add(XP_DLLS.Where(DLL => DLL.ModuleName == "USER32").First()); //SelectedModules.Add(XP_DLLS.Where(DLL => DLL.ModuleName == "GDI32").First()); //SelectedModules.Add(XP_DLLS.Where(DLL => DLL.ModuleName == "OLEAUT32").First()); //SelectedModules.Add(XP_DLLS.Where(DLL => DLL.ModuleName == "MSVCRT").First()); // Randomize modules SelectedModules.AddRange(AllModules.OrderBy(x => Rand.Next()).Take(ModuleCount).ToList()); // Remove any overlapping modules SelectedModules = SelectedModules.Distinct().ToList(); SelectedModules = SelectedModules.OrderBy(x => Rand.Next()).ToList(); // ensure compatability of each imported module function foreach (ImportDLL IDLL in SelectedModules) { int NumberOfFunctions = Rand.Next(60, 90); // IDLL.Functions.Count; // Rand.Next(IDLL.Functions.Count / 16, IDLL.Functions.Count / 12); //if (NumberOfFunctions < 50) // NumberOfFunctions = Rand.Next(IDLL.Functions.Count / 4, IDLL.Functions.Count / 2); //else if (NumberOfFunctions > 50 && NumberOfFunctions < 100) // NumberOfFunctions = Rand.Next(IDLL.Functions.Count / 8, IDLL.Functions.Count / 4); //else if (NumberOfFunctions > 100 && NumberOfFunctions < 200) // NumberOfFunctions = Rand.Next(IDLL.Functions.Count / 12, IDLL.Functions.Count / 4); //else if (NumberOfFunctions > 200 && NumberOfFunctions < 400) // NumberOfFunctions = Rand.Next(IDLL.Functions.Count / 16, IDLL.Functions.Count / 8); //else if (NumberOfFunctions > 400) // NumberOfFunctions = Rand.Next(IDLL.Functions.Count / 8, IDLL.Functions.Count / 4); //if (NumberOfFunctions == 0) // NumberOfFunctions += 1; var SelectedFunctions = IDLL.Functions.OrderBy(x => Rand.Next()).Take(NumberOfFunctions); List <string> CheckedFunctions = new List <string>(); foreach (var Function in SelectedFunctions) { IntPtr hCorrespondingLib = LoadLibraryA(IDLL.ModuleName); IntPtr pFuncCheck = GetProcAddress(hCorrespondingLib, Function.Key); if (null != pFuncCheck && pFuncCheck != IntPtr.Zero && !IsBlacklisted(Function.Key)) { CheckedFunctions.Add(Function.Key); } else { Console.WriteLine("bad function {0}", Function.Key); } FreeLibrary(hCorrespondingLib); } ImportTable.Add(IDLL.ModuleName, CheckedFunctions); } return(SelectedModules.Count); }
public static unsafe IntPtr GetProcAddressR(IntPtr PEPointer, string functionName) { bool is64Bit = false; IMAGE_DOS_HEADER dosHeader = (IMAGE_DOS_HEADER)Marshal.PtrToStructure(PEPointer, typeof(IMAGE_DOS_HEADER)); IntPtr NtHeadersPtr = (IntPtr)((UInt64)PEPointer + (UInt64)dosHeader.e_lfanew); var imageNtHeaders64 = (IMAGE_NT_HEADERS64)Marshal.PtrToStructure(NtHeadersPtr, typeof(IMAGE_NT_HEADERS64)); var imageNtHeaders32 = (IMAGE_NT_HEADERS32)Marshal.PtrToStructure(NtHeadersPtr, typeof(IMAGE_NT_HEADERS32)); if (!imageNtHeaders64.isValid) { throw new ApplicationException("Invalid IMAGE_NT_HEADER signature."); } if (imageNtHeaders64.OptionalHeader.Magic == MagicType.IMAGE_NT_OPTIONAL_HDR64_MAGIC) { is64Bit = true; } IntPtr ExportTablePtr; if (is64Bit) { if ((imageNtHeaders64.FileHeader.Characteristics & 0x2000) != 0x2000) { throw new ApplicationException("File is not a DLL, Exiting."); } ExportTablePtr = (IntPtr)((UInt64)PEPointer + (UInt64)imageNtHeaders64.OptionalHeader.ExportTable.VirtualAddress); } else { if ((imageNtHeaders32.FileHeader.Characteristics & 0x2000) != 0x2000) { throw new ApplicationException("File is not a DLL, Exiting."); } ExportTablePtr = (IntPtr)((UInt64)PEPointer + (UInt64)imageNtHeaders32.OptionalHeader.ExportTable.VirtualAddress); } IMAGE_EXPORT_DIRECTORY ExportTable = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(ExportTablePtr, typeof(IMAGE_EXPORT_DIRECTORY)); for (int i = 0; i < ExportTable.NumberOfNames; i++) { IntPtr NameOffsetPtr = (IntPtr)((ulong)PEPointer + (ulong)ExportTable.AddressOfNames + (ulong)(i * Marshal.SizeOf(typeof(UInt32)))); IntPtr NamePtr = (IntPtr)((ulong)PEPointer + (UInt32)Marshal.PtrToStructure(NameOffsetPtr, typeof(UInt32))); string Name = Marshal.PtrToStringAnsi(NamePtr); if (Name.Contains(functionName)) { IntPtr AddressOfFunctions = (IntPtr)((ulong)PEPointer + (ulong)ExportTable.AddressOfFunctions); IntPtr OrdinalRvaPtr = (IntPtr)((ulong)PEPointer + (ulong)(ExportTable.AddressOfNameOrdinals + (i * Marshal.SizeOf(typeof(UInt16))))); UInt16 FuncIndex = (UInt16)Marshal.PtrToStructure(OrdinalRvaPtr, typeof(UInt16)); IntPtr FuncOffsetLocation = (IntPtr)((ulong)AddressOfFunctions + (ulong)(FuncIndex * Marshal.SizeOf(typeof(UInt32)))); IntPtr FuncLocationInMemory = (IntPtr)((ulong)PEPointer + (UInt32)Marshal.PtrToStructure(FuncOffsetLocation, typeof(UInt32))); return(FuncLocationInMemory); } } return(IntPtr.Zero); }
public PESupport(string LibraryName) { Debug.Assert(LibraryName != null); this.LibraryName = LibraryName; hLibrary = IntPtr.Zero; IntPtr original_hLibrary = LoadLibraryEx(this.LibraryName, IntPtr.Zero, LoadLibraryFlags.DONT_RESOLVE_DLL_REFERENCES); // access violations occur with LOAD_LIBRARY_AS_DATAFILE, but don't with DONT_RESOLVE_DLL_REFERENCES for some reason hLibrary = new IntPtr(original_hLibrary.ToInt32() - original_hLibrary.ToInt32() % 4); // adjust things to a DWORD boundary int error = Marshal.GetLastWin32Error(); if (hLibrary == null && error != 0) { throw new System.ApplicationException("Got error " + error + " when loading library " + LibraryName); } // do some sanity checking dosHeader = (IMAGE_DOS_HEADER)Marshal.PtrToStructure(hLibrary, typeof(IMAGE_DOS_HEADER)); if (!dosHeader.isValid) { throw new System.ApplicationException("Library does not appear to be a valid DOS file!"); } ntHeader = (IMAGE_NT_HEADERS32)Marshal.PtrToStructure(hLibrary + dosHeader.e_lfanew, typeof(IMAGE_NT_HEADERS32)); if (!ntHeader.isValid) { throw new System.ApplicationException("Library NT Header does not appear valid!"); } fileHeader = ntHeader.FileHeader; if (fileHeader.Machine != (UInt16)(MachineType.I386)) { throw new System.ApplicationException("Library appears to be compiled for x64 while this program only supports x86 libraries."); } optionalHeader = ntHeader.OptionalHeader; exports = new Dictionary <int, List <string> >(); // if we don't have an export directory, move on if (optionalHeader.ExportTable.VirtualAddress == 0 || optionalHeader.ExportTable.Size == 0) { FreeLibrary(original_hLibrary); return; } // initialise the export header exportHeader = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(hLibrary + (int)optionalHeader.ExportTable.VirtualAddress, typeof(IMAGE_EXPORT_DIRECTORY)); for (int i = 0; i < exportHeader.NumberOfNames; i++) { // grab the pointer to the next entry in the string table. In C, this would be a char* IntPtr namePtr = (IntPtr)Marshal.PtrToStructure(hLibrary + (int)(exportHeader.AddressOfNames) + (4 * i), typeof(IntPtr)); // dereference the previous char* string name; try { name = Marshal.PtrToStringAnsi(hLibrary + namePtr.ToInt32()); } catch (Exception ex) { name = ""; Console.WriteLine(ex.StackTrace); } // grab the address for this function int address = ((IntPtr)Marshal.PtrToStructure(hLibrary + (int)(exportHeader.AddressOfFunctions) + 4 * i, typeof(IntPtr))).ToInt32(); address += (int)optionalHeader.ImageBase; if (exports.ContainsKey(address)) { exports[address].Add(name); } else { exports[address] = new List <string>(); exports[address].Add(name); } } FreeLibrary(original_hLibrary); }
public PeFile32(IMAGE_DOS_HEADER dosHeader, IMAGE_FILE_HEADER peHeader, IMAGE_OPTIONAL_HEADER32 optionalHeader, IMAGE_EXPORT_DIRECTORY exportDirectory, Dictionary <string, IntPtr> exports) { this.DosHeader = dosHeader; this.PeHeader = peHeader; this.OptionalHeader = optionalHeader; this.ExportDirectory = exportDirectory; Exports = exports; }