private void ReadEntryChildren(ResDirectoryEntry dirEntry, Stream peStream, long virtualAddress, long baseOffset, ref int nextId) { // read the child node(s) if (dirEntry.entry.DataIsDirectory) { // note: offset from beginning of section. peStream.Seek(baseOffset + dirEntry.entry.OffsetToDirectory, SeekOrigin.Begin); dirEntry.child = ReadDirectory(peStream, virtualAddress, baseOffset, dirEntry.id, ref nextId); } else { // note: offset from beginning of section. peStream.Seek(baseOffset + dirEntry.entry.OffsetToData, SeekOrigin.Begin); var dataEntry = peStream.Read <IMAGE_RESOURCE_DATA_ENTRY>(); // decode the RVA to file offset long realDataAddr = baseOffset + dataEntry.OffsetToData - virtualAddress; peStream.Seek(realDataAddr, SeekOrigin.Begin); var dataBytes = new byte[dataEntry.Size]; peStream.Read(dataBytes, 0, dataBytes.Length); string type, name; int localeId; GetResourceInfo(dirEntry, out type, out name, out localeId); int dataId = nextId++; _data.Add(dataId, new PeResourceData(type, name, localeId, dataBytes)); dirEntry.child = dataId; } }
private void GetResourceInfo(ResDirectoryEntry dataEntry, out string type, out string name, out int localeId) { Debug.Assert(!dataEntry.IsSubdirectory, "attempted to get type/name/locale of resource directory node."); localeId = dataEntry.entry.Id; ResDirectory localeDir = _directories[dataEntry.ownerDirectory]; ResDirectoryEntry nameEntry = _entries[localeDir.parentEntry]; name = nameEntry.name; ResDirectory nameDirectory = _directories[nameEntry.ownerDirectory]; ResDirectoryEntry typeEntry = _entries[nameDirectory.parentEntry]; type = typeEntry.name; }
private int ReadDirectory(Stream peStream, long virtualAddress, long baseOffset, int parentId, ref int nextId) { int dirId = nextId++; var dirInfo = new ResDirectory(); dirInfo.id = dirId; dirInfo.parentEntry = parentId; _directories.Add(dirId, dirInfo); dirInfo.directory = peStream.Read <IMAGE_RESOURCE_DIRECTORY>(); int nChildren = dirInfo.directory.NumberOfIdEntries + dirInfo.directory.NumberOfNamedEntries; dirInfo.childMappings = new int[nChildren]; // read the directory table rows for (int i = 0; i < nChildren; i++) { int entryId = nextId++; var dirEntry = new ResDirectoryEntry(); dirEntry.id = entryId; dirEntry.ownerDirectory = dirId; dirInfo.childMappings[i] = entryId; dirEntry.entry = peStream.Read <IMAGE_RESOURCE_DIRECTORY_ENTRY>(); _entries.Add(entryId, dirEntry); } // read the child data. for (int i = 0; i < nChildren; i++) { ResDirectoryEntry dirEntry = _entries[dirInfo.childMappings[i]]; ReadEntryName(dirEntry, peStream, virtualAddress, baseOffset); ReadEntryChildren(dirEntry, peStream, virtualAddress, baseOffset, ref nextId); } return(dirId); }
private IEnumerable <PeResourceData> GetAllChildDatas(ResDirectoryEntry entry) { if (entry.IsSubdirectory) { // subdirectory, recursively yield the data var dir = _directories[entry.child]; for (int i = 0; i < dir.NumChildren; i++) { var childEntry = _entries[dir.childMappings[i]]; foreach (var data in GetAllChildDatas(childEntry)) { yield return(data); } } } else { // leaf node, just yield the data yield return(_data[entry.child]); } }
private void ReadEntryName(ResDirectoryEntry dirEntry, Stream peStream, long virtualAddress, long baseOffset) { // read the name if (dirEntry.entry.NameIsString) { // note: offset from beginning of section. peStream.Seek(baseOffset + dirEntry.entry.NameOffset, SeekOrigin.Begin); int nChars = peStream.Read <short>(); // names are in "Unicode" (UTF-16LE, wchar_t) int nBytes = nChars * 2; var nameBytes = new byte[nBytes]; peStream.Read(nameBytes, 0, nBytes); dirEntry.name = Encoding.Unicode.GetString(nameBytes); } else { dirEntry.name = dirEntry.entry.Id.ToString(); } }
private int ReadDirectory(Stream peStream, long baseAddress, long virtualAddress, ref int nextId) { int dirId = nextId++; var dirInfo = new ResDirectory(); _directories.Add(dirId, dirInfo); dirInfo.directory = peStream.Read <IMAGE_RESOURCE_DIRECTORY>(); int nChildren = dirInfo.directory.NumberOfIdEntries + dirInfo.directory.NumberOfNamedEntries; dirInfo.childMappings = new int[nChildren]; for (int i = 0; i < nChildren; i++) { int entryId = nextId++; var dirEntry = new ResDirectoryEntry(); _entries.Add(entryId, dirEntry); dirInfo.childMappings[i] = entryId; dirEntry.entry = peStream.Read <IMAGE_RESOURCE_DIRECTORY_ENTRY>(); // preserve the current stream position while we read child data var curOffset = peStream.Position; // read the name if (dirEntry.entry.NameIsString) { // note: offset from beginning of section. peStream.Seek(baseAddress + dirEntry.entry.NameOffset, SeekOrigin.Begin); int nChars = peStream.Read <short>(); // names are in "Unicode" int nBytes = nChars * 2; var nameBytes = new byte[nBytes]; peStream.Read(nameBytes, 0, nBytes); dirEntry.name = Encoding.Unicode.GetString(nameBytes); } else { dirEntry.name = dirEntry.entry.Id.ToString(); } // read the child node(s) if (dirEntry.entry.DataIsDirectory) { // note: offset from beginning of section. peStream.Seek(baseAddress + dirEntry.entry.OffsetToDirectory, SeekOrigin.Begin); dirEntry.child = ReadDirectory(peStream, baseAddress, virtualAddress, ref nextId); } else { // note: offset from beginning of section. peStream.Seek(baseAddress + dirEntry.entry.OffsetToData, SeekOrigin.Begin); var dataEntry = peStream.Read <IMAGE_RESOURCE_DATA_ENTRY>(); // decode the RVA... long realDataAddr = baseAddress + dataEntry.OffsetToData - virtualAddress; peStream.Seek(realDataAddr, SeekOrigin.Begin); var dataBytes = new byte[dataEntry.Size]; peStream.Read(dataBytes, 0, dataBytes.Length); int dataId = nextId++; _data.Add(dataId, dataBytes); dirEntry.child = dataId; } peStream.Seek(curOffset, SeekOrigin.Begin); } return(dirId); }