mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-27 23:37:04 -05:00
patterns/ne: Adding pattern file for NE executables (#58)
* Update pe.hexpat Implementing a number of things and fixing others * Update pe.hexpat Adding the readonlyData pattern * Update pe.hexpat Testing putting the number of tabs on Github to 4 instead of 8 (so that comments on the code for the Sections don't break) * Update pe.hexpat Reverting change that turned out to be needless * Update pe.hexpat Actually sending the `products[while($ != richHeaderEndPosition)]` to `products[while($ < richHeaderEndPosition)]` change * Add files via upload Adding NE test file * Add files via upload Adding NE pattern file * Update ne.hexpat Fixing the error with the entry table assignment * Update README.md Added the NE pattern file to the list of patterns
This commit is contained in:
@@ -11,6 +11,7 @@ Hex patterns, include patterns and magic files for the use with the ImHex Hex Ed
|
|||||||
| BMP | `image/bmp` | [`patterns/bmp.hexpat`](patterns/bmp.hexpat) | OS2/Windows Bitmap files |
|
| BMP | `image/bmp` | [`patterns/bmp.hexpat`](patterns/bmp.hexpat) | OS2/Windows Bitmap files |
|
||||||
| ELF | `application/x-executable` | [`patterns/elf.hexpat`](patterns/elf.hexpat) | ELF header in elf binaries |
|
| ELF | `application/x-executable` | [`patterns/elf.hexpat`](patterns/elf.hexpat) | ELF header in elf binaries |
|
||||||
| PE | `application/x-dosexec` | [`patterns/pe.hexpat`](patterns/pe.hexpat) | PE header, COFF header, Standard COFF fields and Windows Specific fields |
|
| PE | `application/x-dosexec` | [`patterns/pe.hexpat`](patterns/pe.hexpat) | PE header, COFF header, Standard COFF fields and Windows Specific fields |
|
||||||
|
| NE | | [`patterns/ne.hexpat`](patterns/ne.hexpat) | NE header and Standard NE fields |
|
||||||
| Intel HEX | | [`patterns/intel_hex.hexpat`](patterns/intel_hex.hexpat) | [Intel hexadecimal object file format definition]("https://en.wikipedia.org/wiki/Intel_HEX") |
|
| Intel HEX | | [`patterns/intel_hex.hexpat`](patterns/intel_hex.hexpat) | [Intel hexadecimal object file format definition]("https://en.wikipedia.org/wiki/Intel_HEX") |
|
||||||
| MIDI | `audio/midi` | [`patterns/midi.hexpat`](patterns/midi.hexpat) | MIDI header, event fields provided |
|
| MIDI | `audio/midi` | [`patterns/midi.hexpat`](patterns/midi.hexpat) | MIDI header, event fields provided |
|
||||||
| WAV | `audio/wav` | [`patterns/wav.hexpat`](patterns/wav.hexpat) | RIFF header, WAVE header, PCM header |
|
| WAV | `audio/wav` | [`patterns/wav.hexpat`](patterns/wav.hexpat) | RIFF header, WAVE header, PCM header |
|
||||||
|
|||||||
264
patterns/ne.hexpat
Normal file
264
patterns/ne.hexpat
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
#include <std/mem.pat>
|
||||||
|
|
||||||
|
#pragma bitfield_order right_to_left
|
||||||
|
|
||||||
|
struct DOSHeader {
|
||||||
|
char signature[2];
|
||||||
|
u16 lastPageSize;
|
||||||
|
u16 numberOfPages;
|
||||||
|
u16 relocations;
|
||||||
|
u16 headerSizeInParagraphs;
|
||||||
|
u16 minimumAllocatedParagraphs;
|
||||||
|
u16 maximumAllocatedParagraphs;
|
||||||
|
u16 initialSSValue;
|
||||||
|
u16 initialRelativeSPValue;
|
||||||
|
u16 checksum;
|
||||||
|
u16 initialRelativeIPValue;
|
||||||
|
u16 initialCSValue;
|
||||||
|
u16 relocationsTablePointer;
|
||||||
|
u16 overlayNumber;
|
||||||
|
u8 overlayInformation[0x20];
|
||||||
|
u32 neHeaderPointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
u16 dosMessageOffset;
|
||||||
|
u16 pointedCodeOffset;
|
||||||
|
|
||||||
|
fn finddosmessage() {
|
||||||
|
for (u8 i = 0, $+i < std::mem::read_unsigned(0x3C, 4), i = i + 1) {
|
||||||
|
if (std::mem::read_unsigned($+i, 1) == 0xBA) { // MOV instruction
|
||||||
|
dosMessageOffset = std::mem::read_unsigned($+i+1, 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fn findpointingcode() {
|
||||||
|
for (u8 i = 0, $+i < std::mem::read_unsigned(0x3C, 4), i = i + 1) {
|
||||||
|
if (std::mem::read_unsigned($+i, 1) == 0xE8) { // CALL instruction
|
||||||
|
pointedCodeOffset = std::mem::read_unsigned($+i+1, 2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
fn isdosdata(char c) {
|
||||||
|
return c == 0x0D || c == '$';
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DOSStub {
|
||||||
|
if (findpointingcode()) {
|
||||||
|
u8 pointingCode[3];
|
||||||
|
u8 code[while(std::mem::read_unsigned($, 1) != 0x00)] @ addressof(this) + pointedCodeOffset + 3;
|
||||||
|
char message[while(!isdosdata(std::mem::read_unsigned($, 1)))];
|
||||||
|
char data[while(std::mem::read_string($-1, 1) != "$")];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
finddosmessage();
|
||||||
|
if (dosMessageOffset > 0) {
|
||||||
|
u8 code[while($ != addressof(this) + dosMessageOffset)];
|
||||||
|
char message[while(!isdosdata(std::mem::read_unsigned($, 1)))];
|
||||||
|
char data[while(std::mem::read_string($-1, 1) != "$")];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char code[while(std::mem::read_unsigned($, 1) != 0x00)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FileHeader {
|
||||||
|
DOSHeader dosHeader;
|
||||||
|
DOSStub dosStub @ dosHeader.headerSizeInParagraphs * 16;
|
||||||
|
};
|
||||||
|
|
||||||
|
FileHeader fileHeader @ 0x00;
|
||||||
|
|
||||||
|
enum DGroupType : u8 {
|
||||||
|
NoAutoData,
|
||||||
|
SingleData,
|
||||||
|
MultipleData,
|
||||||
|
Null
|
||||||
|
};
|
||||||
|
|
||||||
|
fn formatDGroupType(u8 value) {
|
||||||
|
DGroupType dgroup = value;
|
||||||
|
|
||||||
|
return dgroup;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum AppType : u8 {
|
||||||
|
None,
|
||||||
|
Fullscreen,
|
||||||
|
WinPMCompatible,
|
||||||
|
UsesWinPM
|
||||||
|
};
|
||||||
|
|
||||||
|
fn formatAppType(u8 value) {
|
||||||
|
AppType app = value;
|
||||||
|
|
||||||
|
return app;
|
||||||
|
};
|
||||||
|
|
||||||
|
bitfield ProgramFlags {
|
||||||
|
dGroupType : 2 [[format("formatDGroupType")]];
|
||||||
|
globalInitialization : 1;
|
||||||
|
protectedModeOnly : 1;
|
||||||
|
instructions86 : 1;
|
||||||
|
instructions286 : 1;
|
||||||
|
instructions386 : 1;
|
||||||
|
instructionsX87 : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
bitfield ApplicationFlags {
|
||||||
|
applicationType : 2 [[format("formatAppType")]];
|
||||||
|
padding : 1;
|
||||||
|
os2Application : 1;
|
||||||
|
reserved : 1;
|
||||||
|
imageError : 1;
|
||||||
|
nonConforming : 1;
|
||||||
|
dll : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum OSType : u8 {
|
||||||
|
Unknown = 0x00,
|
||||||
|
OS2 = 0x01,
|
||||||
|
Win16 = 0x02,
|
||||||
|
DOS4 = 0x03,
|
||||||
|
Win32 = 0x04,
|
||||||
|
BorlandOSServices = 0x05,
|
||||||
|
PharlapDOSExtenderOS2 = 0x81,
|
||||||
|
PharlapDOSExtenderWindows = 0x82
|
||||||
|
};
|
||||||
|
|
||||||
|
bitfield OS2EXEFlags {
|
||||||
|
longFilename : 1;
|
||||||
|
protectedMode : 1;
|
||||||
|
proportionalFonts : 1;
|
||||||
|
gangloadArea : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NEHeader {
|
||||||
|
char signature[2];
|
||||||
|
u8 majorLinkerVersion;
|
||||||
|
u8 minorLinkerVersion;
|
||||||
|
u16 entryTableOffset;
|
||||||
|
u16 entryTableLength;
|
||||||
|
u32 fileCRC;
|
||||||
|
ProgramFlags programFlags;
|
||||||
|
ApplicationFlags appFlags;
|
||||||
|
u16 autoDataSegmentIndex;
|
||||||
|
u16 initHeapSize;
|
||||||
|
u16 initStackSize;
|
||||||
|
u32 entryPoint;
|
||||||
|
u32 initialStackPointer;
|
||||||
|
u16 segmentCount;
|
||||||
|
u16 moduleReferenceCount;
|
||||||
|
u16 nonResidentNamesTableSize;
|
||||||
|
u16 segmentTableOffset;
|
||||||
|
u16 resourceTableOffset;
|
||||||
|
u16 residentNamesTableOffset;
|
||||||
|
u16 moduleReferenceTableOffset;
|
||||||
|
u16 importedNamesTableOffset;
|
||||||
|
u8 *nonResidentNamesTablePointer[nonResidentNamesTableSize] : u32;
|
||||||
|
u16 moveableEntryCount;
|
||||||
|
u16 fileAlignmentSizeShiftCount;
|
||||||
|
u16 resourceCount;
|
||||||
|
OSType targetOS;
|
||||||
|
OS2EXEFlags os2ExeFlags;
|
||||||
|
u16 thunksReturnOffset;
|
||||||
|
u16 segmentReferenceThunksOffset;
|
||||||
|
u16 minimumCodeSwapAreaSize;
|
||||||
|
u8 expectedMinorWindowsVersion;
|
||||||
|
u8 expectedMajorWindowsVersion;
|
||||||
|
};
|
||||||
|
|
||||||
|
NEHeader neHeader @ fileHeader.dosHeader.neHeaderPointer;
|
||||||
|
|
||||||
|
bitfield SegmentTableFlags {
|
||||||
|
dataSegment : 1;
|
||||||
|
typeMask : 2;
|
||||||
|
padding : 1;
|
||||||
|
moveable : 1;
|
||||||
|
padding : 1;
|
||||||
|
preloaded : 1;
|
||||||
|
padding : 1;
|
||||||
|
containsRelocationInfo : 1;
|
||||||
|
padding : 1;
|
||||||
|
discardPriority : 4;
|
||||||
|
} [[right_to_left]];
|
||||||
|
|
||||||
|
struct SegmentTable {
|
||||||
|
u16 segmentDataPointer;
|
||||||
|
u16 segmentLength;
|
||||||
|
SegmentTableFlags segmentTableFlags;
|
||||||
|
u16 minimumAllocationSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
SegmentTable segmentTable[neHeader.segmentCount] @ addressof(neHeader) + neHeader.segmentTableOffset;
|
||||||
|
|
||||||
|
bitfield BlockFlags {
|
||||||
|
padding : 4;
|
||||||
|
moveable : 1;
|
||||||
|
shared : 1;
|
||||||
|
preload : 1;
|
||||||
|
padding : 9;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ResourceTypeInformationBlock {
|
||||||
|
u8 *resourcePointer : u16;
|
||||||
|
u16 resourceLength;
|
||||||
|
BlockFlags flags;
|
||||||
|
u16 resourceID;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ResourceRecord {
|
||||||
|
u16 typeID;
|
||||||
|
u16 numberOfResources;
|
||||||
|
u32 reserved;
|
||||||
|
ResourceTypeInformationBlock blocks[numberOfResources];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ResourceTable {
|
||||||
|
u16 alignmentShiftCount;
|
||||||
|
ResourceRecord records[neHeader.resourceTableEntryCount];
|
||||||
|
u8 stringLength;
|
||||||
|
char string[stringLength];
|
||||||
|
};
|
||||||
|
|
||||||
|
ResourceTable resourceTable[neHeader.resourceCount] @ addressof(neHeader) + neHeader.resourceTableOffset;
|
||||||
|
|
||||||
|
struct ResidentName {
|
||||||
|
u8 stringLength;
|
||||||
|
char string[stringLength];
|
||||||
|
u16 ordinalNumber;
|
||||||
|
};
|
||||||
|
|
||||||
|
ResidentName residentNameTable[while($+1 < addressof(neHeader) + neHeader.moduleReferenceTableOffset)] @ addressof(neHeader) + neHeader.residentNamesTableOffset;
|
||||||
|
|
||||||
|
struct ModuleReference {
|
||||||
|
u16 moduleNameOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
ModuleReference moduleReferenceTable[neHeader.moduleReferenceCount] @ addressof(neHeader) + neHeader.moduleReferenceTableOffset;
|
||||||
|
|
||||||
|
struct ImportedNameTable {
|
||||||
|
u8 stringLength;
|
||||||
|
char string[stringLength];
|
||||||
|
};
|
||||||
|
|
||||||
|
ImportedNameTable importedNameTable[while($ < addressof(neHeader) + neHeader.entryTableOffset)] @ addressof(neHeader) + neHeader.importedNamesTableOffset;
|
||||||
|
|
||||||
|
enum EntryDataType : u8 {
|
||||||
|
Unused,
|
||||||
|
Fixed = 0x01 ... 0xFE,
|
||||||
|
Moveable
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EntryTable {
|
||||||
|
u8 entryCount;
|
||||||
|
EntryDataType segmentIndicator;
|
||||||
|
};
|
||||||
|
|
||||||
|
EntryTable entryTable[neHeader.entryTableLength/2] @ addressof(neHeader) + neHeader.entryTableOffset;
|
||||||
BIN
tests/patterns/test_data/ne.hexpat.exe
Normal file
BIN
tests/patterns/test_data/ne.hexpat.exe
Normal file
Binary file not shown.
Reference in New Issue
Block a user