Beispiel #1
0
        private void ReadStringTable(BinaryReader reader, uint offset, uint rsrcStart)
        {
            reader.BaseStream.Seek((long)((offset & 0x7FFFFFFF) + rsrcStart), SeekOrigin.Begin);
            IMAGE_RESOURCE_DIRECTORY rootDir = reader.ReadStruct <IMAGE_RESOURCE_DIRECTORY> ();
            int num = (int)(rootDir.NumberOfIdEntries + rootDir.NumberOfNamedEntries);

            IMAGE_RESOURCE_DIRECTORY_ENTRY[] entries = new IMAGE_RESOURCE_DIRECTORY_ENTRY[num];
            for (int i = 0; i < num; i++)
            {
                entries [i] = reader.ReadStruct <IMAGE_RESOURCE_DIRECTORY_ENTRY> ();
            }
            for (int i = 0; i < num; i++)
            {
                uint dirOffset = entries [i].OffsetToData & 0x7FFFFFFF;
                reader.BaseStream.Seek((long)(dirOffset + rsrcStart), SeekOrigin.Begin);
                reader.ReadStruct <IMAGE_RESOURCE_DIRECTORY> ();
                IMAGE_RESOURCE_DIRECTORY_ENTRY languageEntry = reader.ReadStruct <IMAGE_RESOURCE_DIRECTORY_ENTRY> ();
                reader.BaseStream.Seek((long)(languageEntry.OffsetToData + rsrcStart), SeekOrigin.Begin);
                IMAGE_RESOURCE_DATA_ENTRY dataEntry = reader.ReadStruct <IMAGE_RESOURCE_DATA_ENTRY> ();
                reader.BaseStream.Seek((long)dataEntry.OffsetToData, SeekOrigin.Begin);
                int blockId = (int)((entries [i].Name - 1u) * 16);

                for (int j = 0; j < 16; j++)
                {
                    int length = (int)(reader.ReadUInt16() * 2);
                    if (length != 0)
                    {
                        byte[] bytes = reader.ReadBytes(length);
                        string str   = Encoding.Unicode.GetString(bytes);
                        Strings.Add(blockId + j, str);
                    }
                }
            }
        }
Beispiel #2
0
        private void ReadXML(BinaryReader reader, uint offset, uint rsrcStart)
        {
            reader.BaseStream.Seek((long)((offset & 0x7FFFFFFF) + rsrcStart), SeekOrigin.Begin);
            IMAGE_RESOURCE_DIRECTORY rootDir = reader.ReadStruct <IMAGE_RESOURCE_DIRECTORY> ();
            int num = (int)(rootDir.NumberOfIdEntries + rootDir.NumberOfNamedEntries);

            IMAGE_RESOURCE_DIRECTORY_ENTRY[] entries = new IMAGE_RESOURCE_DIRECTORY_ENTRY[num];
            for (int i = 0; i < num; i++)
            {
                entries [i] = reader.ReadStruct <IMAGE_RESOURCE_DIRECTORY_ENTRY> ();
            }
            for (int j = 0; j < num; j++)
            {
                uint dirOffset = entries [j].OffsetToData & 0x7FFFFFFF;
                reader.BaseStream.Seek((long)(dirOffset + rsrcStart), SeekOrigin.Begin);
                reader.ReadStruct <IMAGE_RESOURCE_DIRECTORY> ();
                IMAGE_RESOURCE_DIRECTORY_ENTRY languageEntry = reader.ReadStruct <IMAGE_RESOURCE_DIRECTORY_ENTRY> ();
                reader.BaseStream.Seek((long)(languageEntry.OffsetToData + rsrcStart), SeekOrigin.Begin);
                IMAGE_RESOURCE_DATA_ENTRY dataEntry = reader.ReadStruct <IMAGE_RESOURCE_DATA_ENTRY> ();
                reader.BaseStream.Seek((long)dataEntry.OffsetToData, SeekOrigin.Begin);
                byte[] xmlBytes = reader.ReadBytes((int)dataEntry.Size);
                int    idx      = 0;
                int    count    = xmlBytes.Length;
                if (xmlBytes[0] == 0xFF && xmlBytes[1] == 0xFE)                 //Skip BOM
                {
                    idx    = 2;
                    count -= 2;
                }
                try {
                    Infocards.Add((int)entries [j].Name, Encoding.Unicode.GetString(xmlBytes, idx, count));
                } catch (Exception) {
                    FLLog.Error("Infocards", "Infocard Corrupt: " + entries[j].Name);
                }
            }
        }
Beispiel #3
0
        public ResourceTable(Stream stream, long rsrcSectionRVA, long?rsrcSectionFileAddress = null)
        {
#if COVERAGE_TEST && USE_SIZE
            if (rsrcSectionFileAddress == null)
            {
                Init(stream.Position, stream.Length);
            }
#endif
            SectionRVA = rsrcSectionRVA;
            var SectionPA = rsrcSectionFileAddress ?? stream.Position;
            using (var br = new BinaryReader(stream, Encoding.Default, true))
            {
                Header = br.ReadStruct <IMAGE_RESOURCE_DIRECTORY>();
#if COVERAGE_TEST && USE_SIZE
                RemoveBack(br.BaseStream.Position, typeof(IMAGE_RESOURCE_DIRECTORY));
#endif
                void InitEntries(ref List <ResourceDirectoryEntry> entryPointers, ref List <object> entryValues, int count)
                {
                    entryPointers = new List <ResourceDirectoryEntry>(count);
                    entryValues   = new List <object>(count);
                    for (int i = 0; i < count; i++)
                    {
                        entryPointers.Add(new ResourceDirectoryEntry(br.BaseStream, SectionPA));
                    }
                }

                InitEntries(ref NamedEntryPointers, ref NamedEntries, Header.NumberOfNameEntries);
                InitEntries(ref IDEntryPointers, ref IDEntries, Header.NumberOfIDEntries);

                void ReadEntries(ref List <ResourceDirectoryEntry> entryPointers, ref List <object> entryValues)
                {
                    foreach (var pointer in entryPointers)
                    {
                        br.BaseStream.Seek(SectionPA + pointer.header.DataOffset, SeekOrigin.Begin);
                        if (pointer.header.IsTable)
                        {
                            entryValues.Add(new ResourceTable(br.BaseStream, SectionRVA, SectionPA));
                        }
                        else
                        {
                            entryValues.Add(new ResourceDataEntry(br.BaseStream, SectionRVA, SectionPA));
                        }
                    }
                }

                ReadEntries(ref NamedEntryPointers, ref NamedEntries);
                ReadEntries(ref IDEntryPointers, ref IDEntries);

#if COVERAGE_TEST && USE_SIZE
                if (rsrcSectionFileAddress == null)
                {
                    System.Diagnostics.Debug.Write(Report());
                }
#endif
            }
        }
        public static IMAGE_RESOURCE_DIRECTORY Deserialize(MultiPartFile file)
        {
            IMAGE_RESOURCE_DIRECTORY ird = new IMAGE_RESOURCE_DIRECTORY();

            ird.Characteristics      = file.ReadUInt32();
            ird.TimeDateStamp        = file.ReadUInt32();
            ird.MajorVersion         = file.ReadUInt16();
            ird.MinorVersion         = file.ReadUInt16();
            ird.NumberOfNamedEntries = file.ReadUInt16();
            ird.NumberOfIdEntries    = file.ReadUInt16();

            return(ird);
        }
Beispiel #5
0
        public void ImageResourceDirectoryConstructorWorks_Test()
        {
            var resourceDirectory = new IMAGE_RESOURCE_DIRECTORY(RawStructures.RawResourceDirectory, 2, 2);

            Assert.Equal((uint)0x33221100, resourceDirectory.Characteristics);
            Assert.Equal((uint)0x77665544, resourceDirectory.TimeDateStamp);
            Assert.Equal((ushort)0x9988, resourceDirectory.MajorVersion);
            Assert.Equal((ushort)0xbbaa, resourceDirectory.MinorVersion);
            Assert.Equal((ushort)0x0001, resourceDirectory.NumberOfNameEntries);
            Assert.Equal((ushort)0x0001, resourceDirectory.NumberOfIdEntries);
            Assert.Equal((uint)0x44332211, resourceDirectory.DirectoryEntries[0].Name);
            Assert.Equal(0x88776655, resourceDirectory.DirectoryEntries[0].OffsetToData);
            Assert.Equal((uint)0x44332222 & 0xFFFF, resourceDirectory.DirectoryEntries[1].ID);
            Assert.Equal(0x88776622, resourceDirectory.DirectoryEntries[1].OffsetToData);
        }
Beispiel #6
0
        private static void DoResourceDirectoryRead(BlobReader resourceReaderExternal, uint startOffset, Action <object, uint, bool> entry)
        {
            // Create a copy of the Mu, so that we don't allow the delegate to affect its state
            BlobReader resourceReader = resourceReaderExternal;

            resourceReader.Offset = checked ((int)startOffset);
            IMAGE_RESOURCE_DIRECTORY directory = new IMAGE_RESOURCE_DIRECTORY(ref resourceReader);

            for (uint i = 0; i < directory.NumberOfNamedEntries + directory.NumberOfIdEntries; i++)
            {
                IMAGE_RESOURCE_DIRECTORY_ENTRY directoryEntry = new IMAGE_RESOURCE_DIRECTORY_ENTRY(ref resourceReader);

                object name;
                if ((directoryEntry.Name & 0x80000000) != 0)
                {
                    int oldPosition = resourceReader.Offset;

                    // This is a named entry, read the string
                    uint nameOffset = directoryEntry.Name & ~0x80000000;

                    resourceReader.Offset = checked ((int)nameOffset);
                    ushort stringLen     = resourceReader.ReadUInt16();
                    char[] newStringData = new char[stringLen];
                    for (int iStr = 0; iStr < stringLen; iStr++)
                    {
                        newStringData[iStr] = (char)resourceReader.ReadUInt16();
                    }
                    name = new string(newStringData);
                    // And then reset back to read more things.
                    resourceReader.Offset = oldPosition;
                }
                else
                {
                    name = checked ((ushort)directoryEntry.Name);
                }

                uint offset      = directoryEntry.OffsetToData;
                bool isDirectory = false;
                if ((offset & 0x80000000) != 0)
                {
                    offset     &= ~0x80000000;
                    isDirectory = true;
                }

                entry(name, offset, isDirectory);
            }
        }
Beispiel #7
0
    // **************************************
    // this is a re-entrant procedure
    // ird must always arrive pointing to a resource directory

// For now, this assumes all offsets are relative to the start
// of the resource section (opinions seem to differ on this)
#if NO
    int GetResource(
        string cs,
        IMAGE_RESOURCE_DIRECTORY ird,
        uint de,    // value to subtract from ".link" offsets// s
        uint ss,    // section size
        uint offset // offset to resource section
        )
    {
        int  n;
        uint p;
        IMAGE_RESOURCE_DATA_ENTRY Ptr      pirde;
        IMAGE_RESOURCE_DIRECTORY_ENTRY Ptr irde;
        IMAGE_RESOURCE_DIRECTORY_STRING    ids;

        Static fResult As Long;
        Static lvl As     Long;   // recursion level
        Static rp As      Dword;  // resource pointer
        Static rid As     Dword;
        Static typ As     Dword;
        Static ns As      String;

        if (lvl = 0)
        {
            rp = StrPtr(cs);
        }                                 // = ird // save pointer to start of resource section
        ++lvl;

        irde = ird + SizeOf(IMAGE_RESOURCE_DIRECTORY);

        //  The named entries are case insensitive strings, sorted in ascending order.
        //  The entries with 16-bit IDs follow these and are also sorted in ascending order.
        For n = 1 To @ird.NumberOfNamedEntries + @ird.NumberOfIdEntries

                if ((n <= @ird.NumberOfNamedEntries)And(@irde.NameID And % IMAGE_RESOURCE_NAME_IS_STRING))
        {
            // the name is a string
            p = rp + (@irde.NameID And & H7FFFFFFF)                                 // offset is relative to start of resource section

                rid           = 0                                                   // assign invalid value as a flag
                           ns = Remove$(Peek$(p + 2, CvWrd(Peek$(p, 2)) * 2), $Nul) // unicode string
                                if (UCase$(ns) = "TYPELIB")
            {
                fResult = 1                                       // found TypeLib data
            }
Beispiel #8
0
        public void WriteResources(ISymbolNode nodeAssociatedWithDataBuilder, ref ObjectDataBuilder dataBuilder)
        {
            Debug.Assert(dataBuilder.CountBytes == 0);

            SortedDictionary <string, List <ObjectDataBuilder.Reservation> > nameTable = new SortedDictionary <string, List <ObjectDataBuilder.Reservation> >();
            Dictionary <ResLanguage, int> dataEntryTable = new Dictionary <ResLanguage, int>();
            List <Tuple <ResType, ObjectDataBuilder.Reservation> >     resTypes     = new List <Tuple <ResType, ObjectDataBuilder.Reservation> >();
            List <Tuple <ResName, ObjectDataBuilder.Reservation> >     resNames     = new List <Tuple <ResName, ObjectDataBuilder.Reservation> >();
            List <Tuple <ResLanguage, ObjectDataBuilder.Reservation> > resLanguages = new List <Tuple <ResLanguage, ObjectDataBuilder.Reservation> >();

            IMAGE_RESOURCE_DIRECTORY.Write(ref dataBuilder, checked ((ushort)_resTypeHeadName.Count), checked ((ushort)_resTypeHeadID.Count));
            foreach (KeyValuePair <string, ResType> res in _resTypeHeadName)
            {
                resTypes.Add(new Tuple <ResType, ObjectDataBuilder.Reservation>(res.Value, IMAGE_RESOURCE_DIRECTORY_ENTRY.Write(ref dataBuilder, res.Key, nameTable)));
            }
            foreach (KeyValuePair <ushort, ResType> res in _resTypeHeadID)
            {
                resTypes.Add(new Tuple <ResType, ObjectDataBuilder.Reservation>(res.Value, IMAGE_RESOURCE_DIRECTORY_ENTRY.Write(ref dataBuilder, res.Key)));
            }

            foreach (Tuple <ResType, ObjectDataBuilder.Reservation> type in resTypes)
            {
                dataBuilder.EmitUInt(type.Item2, (uint)dataBuilder.CountBytes | 0x80000000);
                IMAGE_RESOURCE_DIRECTORY.Write(ref dataBuilder, checked ((ushort)type.Item1.NameHeadName.Count), checked ((ushort)type.Item1.NameHeadID.Count));

                foreach (KeyValuePair <string, ResName> res in type.Item1.NameHeadName)
                {
                    resNames.Add(new Tuple <ResName, ObjectDataBuilder.Reservation>(res.Value, IMAGE_RESOURCE_DIRECTORY_ENTRY.Write(ref dataBuilder, res.Key, nameTable)));
                }
                foreach (KeyValuePair <ushort, ResName> res in type.Item1.NameHeadID)
                {
                    resNames.Add(new Tuple <ResName, ObjectDataBuilder.Reservation>(res.Value, IMAGE_RESOURCE_DIRECTORY_ENTRY.Write(ref dataBuilder, res.Key)));
                }
            }

            foreach (Tuple <ResName, ObjectDataBuilder.Reservation> type in resNames)
            {
                dataBuilder.EmitUInt(type.Item2, (uint)dataBuilder.CountBytes | 0x80000000);
                IMAGE_RESOURCE_DIRECTORY.Write(ref dataBuilder, 0, checked ((ushort)type.Item1.Languages.Count));
                foreach (KeyValuePair <ushort, ResLanguage> res in type.Item1.Languages)
                {
                    resLanguages.Add(new Tuple <ResLanguage, ObjectDataBuilder.Reservation>(res.Value, IMAGE_RESOURCE_DIRECTORY_ENTRY.Write(ref dataBuilder, res.Key)));
                }
            }

            // Emit name table
            dataBuilder.PadAlignment(2); // name table is 2 byte aligned
            foreach (KeyValuePair <string, List <ObjectDataBuilder.Reservation> > name in nameTable)
            {
                foreach (ObjectDataBuilder.Reservation reservation in name.Value)
                {
                    dataBuilder.EmitUInt(reservation, (uint)dataBuilder.CountBytes | 0x80000000);
                }

                dataBuilder.EmitUShort(checked ((ushort)name.Key.Length));
                foreach (char c in name.Key)
                {
                    dataBuilder.EmitUShort((ushort)c);
                }
            }

            // Emit byte arrays of resource data, capture the offsets
            foreach (Tuple <ResLanguage, ObjectDataBuilder.Reservation> language in resLanguages)
            {
                dataBuilder.PadAlignment(4); // Data in resource files is 4 byte aligned
                dataEntryTable.Add(language.Item1, dataBuilder.CountBytes);
                dataBuilder.EmitBytes(language.Item1.DataEntry);
            }

            dataBuilder.PadAlignment(4); // resource data entries are 4 byte aligned
            foreach (Tuple <ResLanguage, ObjectDataBuilder.Reservation> language in resLanguages)
            {
                dataBuilder.EmitInt(language.Item2, dataBuilder.CountBytes);
                IMAGE_RESOURCE_DATA_ENTRY.Write(ref dataBuilder, nodeAssociatedWithDataBuilder, dataEntryTable[language.Item1], language.Item1.DataEntry.Length);
            }
            dataBuilder.PadAlignment(4); // resource data entries are 4 byte aligned
        }
Beispiel #9
0
// **************************************
// this is a re-entrant procedure
// ird must always arrive pointing to a resource directory

// For now, this assumes all offsets are relative to the start
// of the resource section (opinions seem to differ on this)
int GetResource( 
	string cs, 
	IMAGE_RESOURCE_DIRECTORY ird, 
	uint de,     // value to subtract from ".link" offsets// s
	uint ss ,   // section size
	uint offset   // offset to resource section
	)
{

Long n;
Dword p;
IMAGE_RESOURCE_DATA_ENTRY Ptr pirde;
IMAGE_RESOURCE_DIRECTORY_ENTRY Ptr irde;
IMAGE_RESOURCE_DIRECTORY_STRING ids;

Static fResult	As Long  ;
Static lvl		As Long	 ;// recursion level
Static rp		As Dword ;// resource pointer
Static rid		As Dword ;
Static typ		As Dword ;
Static ns		As String;

	if (lvl = 0) { rp = StrPtr(cs); } // = ird // save pointer to start of resource section
	Incr lvl

	irde = ird + SizeOf(IMAGE_RESOURCE_DIRECTORY);

	//  The named entries are case insensitive strings, sorted in ascending order.
	//  The entries with 16-bit IDs follow these and are also sorted in ascending order.
	For n = 1 To @ird.NumberOfNamedEntries + @ird.NumberOfIdEntries

		if ((n <= @ird.NumberOfNamedEntries) And (@irde.NameID And %IMAGE_RESOURCE_NAME_IS_STRING)) {
			// the name is a string
			p = rp + (@irde.NameID And &H7FFFFFFF)  // offset is relative to start of resource section

			rid = 0 // assign invalid value as a flag
			ns = Remove$(Peek$(p + 2, CvWrd(Peek$(p, 2)) * 2), $Nul) // unicode string
			if (UCase$(ns) = "TYPELIB") { fResult = 1 // found TypeLib data

		} else if  ((n > @ird.NumberOfNamedEntries) And (@irde.NameID And %IMAGE_RESOURCE_NAME_IS_STRING) = 0) {

			// it// s a 16-bit ID number
			p = LoWrd(@irde.NameID)
			if (lvl = 1) {
				typ = p
			} else if  (lvl = 2) {
				ns = ""
				rid = p
			} else if  (lvl = 3) {
			}

		}

		p = (@irde.Offset And &H7FFFFFFF)

		if ((@irde.Offset And %IMAGE_RESOURCE_DATA_IS_DIRECTORY)) { // it// s a subdirectory
			p = GetResource(cs, rp + p, de, ss, Offset)

		} else {    // it// s actual resource data
			// get offset in PE file to ImageResourceDirectoryEntry structure
			pirde = rp + p

			if (fResult = 1) {
				Incr fResult
				// @pirde.OffsetToData is the RVA to the resource data
				cs = Mid$(cs, @pirde.OffsetToData - de - Offset + 1, @pirde.Size)
			}

		}

		if (fResult == 2)
            break;
		irde = irde + SizeOf(IMAGE_RESOURCE_DIRECTORY_ENTRY);

	Next n

	-- lvl;
	if (lvl) {
		Function = ird;
	} else {
		Function = fResult;
		fResult = 0;
	}

        } // GetResource

// ***************************************
//  gets TypeLib data from a PE file// s resource section
int GetTypeLibData(string cs, string fs)
{
    //#Register All
    FileStream  ff;// file handle
    Long n;
    Long fTlb;
    DosHeader DosHdr;
    PEHeader  pPH;
    SectionInfo si;
    OptHeader pOH;
    SectionHeader pSH;
    DataDir  pDD;


	// --------------------------------------
	// get the Typelib data
	try
    {
		ff = FreeFile();
        ff = new FileStream(fs, FileMode.Open, FileAccess.Read, FileShare.Read);
        
        byte[] cs = new byte[2048];
        ff.Read(cs, 0, cs.Length);

		// ----------------------------------
		// get PE signature if present
		LSet DosHdr = cs;
		if ((Left$(cs, 2) = $PeMZ) &&  (Mid$(cs, DosHdr.lfanew + 1, 4) = $PePE32)) {

			Decr fTlb // disable loading the file below
			pPH = StrPtr(cs) + DosHdr.lfanew + 4;
			pOH = pPH + SizeOf(PEHeader);

			// "pOH.NumberOfRvaAndSizes" is the number of entries, not the size of the array, as someone once wrote
			if (ResourceSection > @pOH.NumberOfRvaAndSizes) return;

			pDD = pOH + SizeOf(OptHeader) + ((ResourceSection - 1) * SizeOf(DataDir));
			si.dRVA = @pDD.RVA      ;
			si.dSize = @pDD.DirSize ;


			// find the section which matches si.dRVA in the section table
			pSH = pOH + SizeOf(OptHeader) + (@pOH.NumberOfRvaAndSizes * SizeOf(DataDir));
			For (int n = 1; n <= @pPH.NumberOfSections; ++n) {
				if ((si.dRVA => @pSH.RVA) && (si.dRVA < @pSH.RVA + @pSH.SizeOfRawData)) {
					si.SectName         = @pSH.SectName;
					si.VirtSize         = @pSH.VirtSize;             // size of unpadded section
					si.RVA              = @pSH.RVA;                  // @pSH.RVA is the offset to section when loaded
					si.RamAdd           = @pOH.ImageBase + @pSH.RVA; // section// s RAM address (for example: &H401000)
					si.SizeOfRawData    = @pSH.SizeOfRawData;        // size after padding to section alignment
					si.PtrToRawData     = @pSH.PtrToRawData;         // zero-based file offset to section
					si.StrPos           = @pSH.PtrToRawData + 1;     // one-based file offset to section
					si.EndPos           = si.StrPos + si.SizeOfRawData;
					si.Delta            = si.RVA - si.PtrToRawData;  // value to subtract from RVAs to get file offsets
					si.Characteristics  = @pSH.Characteristics;

					break;

				}

				pSH = pSH + SizeOf(SectionHeader); // advance pSH to next section header

			}

			// get TypeLib resource
			ff.Position = si.StrPos;
			cs = new byte[si.SizeOfRawData];
            ff.Read(cs, 0, cs.Length);
			if (GetResource(cs, StrPtr(cs), si.Delta, si.SizeOfRawData, si.PtrToRawData) = 0) {
				Reset cs
				UpdateLog( "No TypeLib data found in: " + fs);
			}

		}


		if (Left$(cs, 4) == "MSFT") { // it's a "tlb" (TypeLib) file
			++fTlb
			Function = 1
		} else if  (Left$(cs, 4) = "SLTG") {
			Incr fTlb
			Function = 2
		}

		if (fTlb > 0) {
			Seek# ff, 1
			Get$ #ff, Lof(ff), cs
		}

		ff.Close ();
    } catch
    {
		UpdateLog ("Error opening input file: " + fs);
		return;
	}
    
} // GetTypeLibData
Beispiel #10
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;
                    }
                }
            }
        }