/// <summary>Получить информацию по импорту</summary> /// <param name="offset">Сдвиг по PE файлу</param> /// <param name="isRva">Получить импорт по Relative Virtual Address адресу. В противном случае передаётся Virtual Address</param> /// <returns>Структура</returns> private WinNT.IMAGE_IMPORT_BY_NAME GetImageImport(UInt32 offset, Boolean isRva) { PEHeader header = this.Directory.Parent.Header; UInt64 forwarderString; if (header.Is64Bit) { WinNT.IMAGE_THUNK_DATA64 thunk64 = header.PtrToStructure <WinNT.IMAGE_THUNK_DATA64>(offset); forwarderString = thunk64.ForwarderString; //TODO: Вот тут может быть ошибка } else { WinNT.IMAGE_THUNK_DATA32 thunk32 = header.PtrToStructure <WinNT.IMAGE_THUNK_DATA32>(offset); forwarderString = thunk32.ForwarderString; } WinNT.IMAGE_IMPORT_BY_NAME result; if ((forwarderString & 0x80000000) != 0) { result = new WinNT.IMAGE_IMPORT_BY_NAME() { Hint = (UInt16)(forwarderString & 0x7FFFFFFF), Name = null, }; } else if ((forwarderString & 0x8000000000000000) != 0) { result = new WinNT.IMAGE_IMPORT_BY_NAME() { Hint = (UInt16)(forwarderString & 0x7FFFFFFFFFFFFFFF), Name = null, }; } else { if (!isRva) { UInt64 imageBase; if (header.Is64Bit) { imageBase = header.HeaderNT64.OptionalHeader.ImageBase; } else { imageBase = header.HeaderNT32.OptionalHeader.ImageBase; } forwarderString -= imageBase; } result = header.PtrToStructure <WinNT.IMAGE_IMPORT_BY_NAME>((UInt32)forwarderString); } return(result); }
/// <summary>Get fat method header sections</summary> /// <returns>Method header sections</returns> public IEnumerable <MethodSection> GetSections() { UInt32 padding = this.Row.RVA + this.Header.HeaderSize; UInt32 methodLength = this.Header.CodeSize; if ((this.Header.Format & Cor.CorILMethod.FatFormat) == Cor.CorILMethod.FatFormat && (this.Header.Format & Cor.CorILMethod.MoreSects) == Cor.CorILMethod.MoreSects) { padding += methodLength; PEHeader header = this.Row.Row.Table.Root.Parent.Parent.Parent.Header; Boolean moreSections = true; while (moreSections) { //Each section should start on a 4 byte boundary //so let's read from the stream until we find the next boundary. padding = NativeMethods.AlignToInt(padding); Cor.CorILMethodSection section = header.PtrToStructure <Cor.CorILMethodSection>(padding); padding += MethodBody.SizeOfMethodSection; //I have never seen anything else than an exception handling section... //According to the documentation "Currently, the method data sections //are only used for exception tables." if ((section.Kind & Cor.CorILMethod_Sect.EHTable) != Cor.CorILMethod_Sect.EHTable) { throw new NotImplementedException("Only exception table supported"); } //Check whether more sections follow after this one. moreSections = section.HasMoreSections; Cor.CorILMethodExceptionFat[] fat = new Cor.CorILMethodExceptionFat[section.IsFatFormat ? section.ClauseNumber : 0]; Cor.CorILMethodExceptionSmall[] small = new Cor.CorILMethodExceptionSmall[section.IsFatFormat ? 0 : section.ClauseNumber]; //Let's read the clauses... for (Int32 clauseIndex = 0; clauseIndex < section.ClauseNumber; clauseIndex++) { //The structure of the clauses are the same in both Fat and //Small format, only the sizes are different. if (section.IsFatFormat) { fat[clauseIndex] = header.PtrToStructure <Cor.CorILMethodExceptionFat>(padding); padding += MethodBody.SizeOfMethodExceptionFat; } else { small[clauseIndex] = header.PtrToStructure <Cor.CorILMethodExceptionSmall>(padding); padding += MethodBody.SizeOfMethodExceptionSmall; } } yield return(new MethodSection(section, fat, small)); } } }