Beispiel #1
0
        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);
            }
        }
Beispiel #2
0
 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[])
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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());
        }
Beispiel #9
0
        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));
        }
Beispiel #11
0
        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);
                }
            }
        }
Beispiel #12
0
            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);
            }
Beispiel #13
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;
        }
Beispiel #14
0
        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);
        }
Beispiel #15
0
        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());
        }
Beispiel #16
0
 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);
 }
Beispiel #17
0
        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);
        }
Beispiel #18
0
        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;
        }
Beispiel #19
0
        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;
            }
        }
Beispiel #20
0
        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);
        }
Beispiel #21
0
        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);
        }
Beispiel #22
0
        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;
            }
        }
Beispiel #23
0
        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);
        }
Beispiel #24
0
        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);
        }
Beispiel #25
0
        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);
        }
Beispiel #26
0
        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);
        }
Beispiel #27
0
        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);
        }
Beispiel #28
0
 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;
 }