diff --git a/.gitignore b/.gitignore index 91964ae..49ef813 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ # https://dart.dev/guides/libraries/private-files#pubspeclock. pubspec.lock .vscode/ +test.sql diff --git a/lib/peparse.dart b/lib/peparse.dart index 89502a4..6af86e5 100644 --- a/lib/peparse.dart +++ b/lib/peparse.dart @@ -8,4 +8,6 @@ export 'src/pojo/image_doc_header.dart' show ImageDocHeader; export 'src/pojo/image_nt_header.dart' show ImageNtHeaders32; export 'src/pojo/reader_seeker.dart' show ReaderSeeker; export 'src/pojo/image_section_header.dart' show ImageSectionHeader; +export 'src/pojo/resourse_section.dart' show IMAGE_RESOURCE_DIRECTORY,IMAGE_RESOURCE_DIRECTORY_ENTRY,FileEntry; +export 'src/peparse_base.dart' show PeFile; // TODO: Export any libraries intended for clients of this package. diff --git a/lib/src/peparse_base.dart b/lib/src/peparse_base.dart index e8a6f15..2bc1f5c 100644 --- a/lib/src/peparse_base.dart +++ b/lib/src/peparse_base.dart @@ -1,6 +1,35 @@ -// TODO: Put public facing types in this file. +import 'dart:io'; -/// Checks if you are awesome. Spoiler: you are. -class Awesome { - bool get isAwesome => true; +import './pojo/image_doc_header.dart'; +import './pojo/image_nt_header.dart'; +import './pojo/image_section_header.dart'; +import './pojo/resourse_section.dart'; +import './pojo/reader_seeker.dart'; + +class PeFile { + ImageDocHeader? imageDocHeader; + ImageNtHeaders32? imageNtHeaders; + List imageSectionHeaders = []; + IMAGE_RESOURCE_DIRECTORY? imageResourceDirectory; + + PeFile.parseFile(String filepath) { + File file = File(filepath); + var data = ReaderSeeker(file.readAsBytesSync()); + imageDocHeader = ImageDocHeader(data); + data.seek(imageDocHeader!.elfanew); + imageNtHeaders = ImageNtHeaders32(data); + imageSectionHeaders = []; + for (var i = 0; i < imageNtHeaders!.fileHeader.numberOfSections; i++) { + imageSectionHeaders.add(ImageSectionHeader(data)); + } + var resourse_section = + imageSectionHeaders.firstWhere((element) => element.name == '.rsrc'); + imageResourceDirectory = IMAGE_RESOURCE_DIRECTORY( + resourse_section.pointerToRawData, 0, resourse_section, data); + } + + @override + String toString() { + return '{"imageDocHeader":${imageDocHeader.toString()}, "imageNtHeaders":${imageNtHeaders.toString()}, "imageSectionHeaders":${imageSectionHeaders.toString()}, "imageResourceDirectory":${imageResourceDirectory.toString()}}'; + } } diff --git a/lib/src/pojo/image_section_header.dart b/lib/src/pojo/image_section_header.dart index a5e01fc..3745bbf 100644 --- a/lib/src/pojo/image_section_header.dart +++ b/lib/src/pojo/image_section_header.dart @@ -28,7 +28,8 @@ class ImageSectionHeader { ImageSectionHeader(ReaderSeeker readerSeeker){ _name = readerSeeker.getByte(8); - name = utf8.decode(_name,allowMalformed: true); + _name.removeWhere((element) => element == 0); + name = utf8.decode(_name,allowMalformed: false); var data = readerSeeker.getData(32); misc = data.getUint32(0,Endian.little); virtualAddress = data.getUint32(4,Endian.little); diff --git a/lib/src/pojo/resourse_section.dart b/lib/src/pojo/resourse_section.dart index e69de29..6c15554 100644 --- a/lib/src/pojo/resourse_section.dart +++ b/lib/src/pojo/resourse_section.dart @@ -0,0 +1,95 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import './reader_seeker.dart'; +import './image_section_header.dart'; + +class IMAGE_RESOURCE_DIRECTORY{ + int Characteristics = 0; + int TimeDateStamp = 0; + int MajorVersion = 0; + int MinorVersion = 0; + int NumberOfNamedEntries = 0; + int NumberOfIdEntries = 0; + List Entries = []; + IMAGE_RESOURCE_DIRECTORY(int startOffset,int offset,ImageSectionHeader section,ReaderSeeker readerSeeker){ + readerSeeker.seek(startOffset+offset); + var data = readerSeeker.getData(16); + Characteristics = data.getUint32(0,Endian.little); + TimeDateStamp = data.getUint32(4,Endian.little); + MajorVersion = data.getUint16(8,Endian.little); + MinorVersion = data.getUint16(10,Endian.little); + NumberOfNamedEntries = data.getUint16(12,Endian.little); + NumberOfIdEntries = data.getUint16(14,Endian.little); + + for (var i = 0; i < NumberOfNamedEntries + NumberOfIdEntries; i++) { + Entries.add(IMAGE_RESOURCE_DIRECTORY_ENTRY(readerSeeker)); + } + + for (var i = 0; i < NumberOfNamedEntries + NumberOfIdEntries; i++) { + if (Entries[i].is_folder){ + Entries[i].children = IMAGE_RESOURCE_DIRECTORY(startOffset , Entries[i].OffsetToData,section,readerSeeker); + }else{ + readerSeeker.seek(startOffset + Entries[i].OffsetToData); + Entries[i].fileEntry = FileEntry(readerSeeker); + Entries[i].fileEntry!.real_offset = Entries[i].fileEntry!.offsetToData - section.virtualAddress + section.pointerToRawData; + } + } + } + + @override + String toString(){ + return '{"Characteristics":${Characteristics.toRadixString(16)}, "TimeDateStamp":${TimeDateStamp.toRadixString(16)}, "MajorVersion":${MajorVersion.toRadixString(16)}, "MinorVersion":${MinorVersion.toRadixString(16)}, "NumberOfNamedEntries":${NumberOfNamedEntries.toRadixString(16)}, "NumberOfIdEntries":${NumberOfIdEntries.toRadixString(16)}, "Entries":${Entries}}'; + } + + String toJson(){ + return JsonEncoder().convert(this); + } +} + +class IMAGE_RESOURCE_DIRECTORY_ENTRY{ + int Name = 0; + int OffsetToData = 0; + + bool is_folder = false; + FileEntry? fileEntry = null; + IMAGE_RESOURCE_DIRECTORY? children = null; + IMAGE_RESOURCE_DIRECTORY_ENTRY(ReaderSeeker readerSeeker){ + var data = readerSeeker.getData(8); + Name = data.getUint32(0,Endian.little); + OffsetToData = data.getUint32(4,Endian.little); + is_folder = ((OffsetToData >> 31) & 0x01) == 1; + if (is_folder){ + OffsetToData = OffsetToData & 0x7FFFFFFF; + } + } + + @override + String toString(){ + return '{"Name":${Name.toRadixString(16)}, "OffsetToData":${OffsetToData.toRadixString(16)}, "is_folder":${is_folder}, "fileEntry":${fileEntry}, "children":${children}}'; + } + +} + +class FileEntry{ + int offsetToData = 0; + int size = 0; + int codePage = 0 ; + int reserved = 0 ; + + int real_offset = 0; + + FileEntry(ReaderSeeker readerSeeker){ + var data = readerSeeker.getData(16); + offsetToData = data.getUint32(0,Endian.little); + size = data.getUint32(4,Endian.little); + codePage = data.getUint32(8,Endian.little); + reserved = data.getUint32(12,Endian.little); + } + + @override + String toString(){ + return '{"offsetToData":${offsetToData.toRadixString(16)}, "real_offset":"${real_offset.toRadixString(16)}", "size":${size.toRadixString(16)}, "codePage":${codePage.toRadixString(16)}, "reserved":${reserved.toRadixString(16)}}'; + } + +} \ No newline at end of file