mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-02-04 13:45:28 +00:00
Compare commits
382 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
229e645c8e | ||
|
|
b4606a8b84 | ||
|
|
d11782a87b | ||
|
|
4faaf3d251 | ||
|
|
89dea30211 | ||
|
|
7563634f53 | ||
|
|
d74dcc1d26 | ||
|
|
cd75fd0329 | ||
|
|
0390ee3363 | ||
|
|
64f52698c3 | ||
|
|
8bd4a87f0b | ||
|
|
4ad7c60443 | ||
|
|
d1a6c9be00 | ||
|
|
3c3fd1be50 | ||
|
|
92c5745ac8 | ||
|
|
792de5cda2 | ||
|
|
bfe2381896 | ||
|
|
ded5ecb3ed | ||
|
|
7895b40a77 | ||
|
|
3f2319093f | ||
|
|
3806b383c9 | ||
|
|
84a65e998f | ||
|
|
88049affb5 | ||
|
|
5fd59b9eac | ||
|
|
8288cc7f96 | ||
|
|
063b643597 | ||
|
|
ff4214877e | ||
|
|
847fa7d2ad | ||
|
|
886284b42f | ||
|
|
46776b461b | ||
|
|
e0150d7bb5 | ||
|
|
ad16260c53 | ||
|
|
3cfe9138a5 | ||
|
|
9e43babe0c | ||
|
|
4efbf54edf | ||
|
|
37121a1fd2 | ||
|
|
8a77a8a009 | ||
|
|
1aef137cb2 | ||
|
|
86707b28c0 | ||
|
|
5e42bae77f | ||
|
|
9396804379 | ||
|
|
5613cf9aae | ||
|
|
ff44c717a2 | ||
|
|
42faeb1402 | ||
|
|
7c243ac6ff | ||
|
|
85c6353cba | ||
|
|
c7d049efe2 | ||
|
|
97aabdca33 | ||
|
|
9562a0eaf7 | ||
|
|
04bffd4889 | ||
|
|
a9c71ced47 | ||
|
|
a03bf60ca5 | ||
|
|
02ee94f732 | ||
|
|
0a5ffd247c | ||
|
|
3f4f6a2d07 | ||
|
|
0d22f78b10 | ||
|
|
ca1e3e8e63 | ||
|
|
debb7cde2d | ||
|
|
40c35a5d50 | ||
|
|
971f769031 | ||
|
|
a1a3adfafa | ||
|
|
912b49ecc4 | ||
|
|
dcccd6e313 | ||
|
|
005529f959 | ||
|
|
3d5904c997 | ||
|
|
dcc8915dd2 | ||
|
|
4a589603e4 | ||
|
|
4f16b9d9e8 | ||
|
|
ce7ecc78cc | ||
|
|
9c8a677f13 | ||
|
|
39f2dd88aa | ||
|
|
3b4929a368 | ||
|
|
f290b8462d | ||
|
|
5ce4f3be56 | ||
|
|
a5158f04db | ||
|
|
2aa9f088a4 | ||
|
|
bb37c3f94c | ||
|
|
92b3f14d7b | ||
|
|
2dcd30e346 | ||
|
|
c4ed59dc46 | ||
|
|
81141fb2fa | ||
|
|
58c6f00a6c | ||
|
|
c1f4e42219 | ||
|
|
02b16843e5 | ||
|
|
86bfcc15f9 | ||
|
|
4fab4e71f7 | ||
|
|
b230462860 | ||
|
|
5f49b56c3d | ||
|
|
51482dd225 | ||
|
|
c1cb1a41a9 | ||
|
|
b496c79b34 | ||
|
|
fcad7db5ab | ||
|
|
e1bd26f712 | ||
|
|
0518184786 | ||
|
|
576e234216 | ||
|
|
3c750dac86 | ||
|
|
714cee586d | ||
|
|
cf9cc30d5e | ||
|
|
713b1c83e1 | ||
|
|
ddf289d747 | ||
|
|
ae1edf0f21 | ||
|
|
38665ddbf3 | ||
|
|
2af0f166eb | ||
|
|
aeaeff28d3 | ||
|
|
28948a0511 | ||
|
|
52d190e339 | ||
|
|
d47707c433 | ||
|
|
11bc46ae86 | ||
|
|
d229b23ea6 | ||
|
|
41dc7f7b14 | ||
|
|
dbd8b14cd2 | ||
|
|
3af8adb067 | ||
|
|
5baa470d54 | ||
|
|
1f5d5215f7 | ||
|
|
24c77ecd07 | ||
|
|
2264fc0172 | ||
|
|
00028ac59b | ||
|
|
ad5735a559 | ||
|
|
9411f5044a | ||
|
|
7293d55239 | ||
|
|
31dc347df4 | ||
|
|
d72d0d4dc2 | ||
|
|
7181dc9d5b | ||
|
|
95fa8681fe | ||
|
|
3a63755d96 | ||
|
|
5390970054 | ||
|
|
2b43f2b261 | ||
|
|
4330cd1aac | ||
|
|
fc9dd8a34d | ||
|
|
c64abc15c9 | ||
|
|
fca12c639c | ||
|
|
a1522aabd6 | ||
|
|
9be4b339f8 | ||
|
|
ce1c74aec3 | ||
|
|
e824428e0f | ||
|
|
2fd4a8a9b1 | ||
|
|
82de7e8b8e | ||
|
|
26831b4732 | ||
|
|
a6862925ca | ||
|
|
1e2ce169af | ||
|
|
dda9b3551a | ||
|
|
b1760d3541 | ||
|
|
2c1e087bc6 | ||
|
|
90d5bd52a2 | ||
|
|
26db75853b | ||
|
|
fe5a674518 | ||
|
|
2fe56cd6af | ||
|
|
f26e82d2bc | ||
|
|
65892f067a | ||
|
|
768717d7b3 | ||
|
|
f78b3daf8b | ||
|
|
8a6f481118 | ||
|
|
f420434fd3 | ||
|
|
8e73d7970f | ||
|
|
9699af93bc | ||
|
|
44ca0a94b7 | ||
|
|
b3bf008e31 | ||
|
|
ce5e2982d2 | ||
|
|
7d2edd315c | ||
|
|
8ae0452873 | ||
|
|
e0efc0d9ab | ||
|
|
3ce3b7ca2b | ||
|
|
6997608b63 | ||
|
|
cee7f12974 | ||
|
|
5b4a8d5775 | ||
|
|
a59bedec5d | ||
|
|
3c5d670924 | ||
|
|
7bab251915 | ||
|
|
57e47eee5d | ||
|
|
4f09c57755 | ||
|
|
7c1edab6ca | ||
|
|
f24004c949 | ||
|
|
c4bf3931e2 | ||
|
|
fe13562f3e | ||
|
|
64334d72ea | ||
|
|
a915980187 | ||
|
|
af882fa588 | ||
|
|
7fcaa16835 | ||
|
|
4d640f3cf2 | ||
|
|
25d495b1d0 | ||
|
|
7fd936c4a8 | ||
|
|
fe753fc4fd | ||
|
|
0a4763fcc1 | ||
|
|
e281faf664 | ||
|
|
dcb291c1c6 | ||
|
|
ecd1c93bb9 | ||
|
|
eeb555a6ce | ||
|
|
27d53abd10 | ||
|
|
91eef55173 | ||
|
|
f9e1518da6 | ||
|
|
5b974260cc | ||
|
|
554374b710 | ||
|
|
475669ac1b | ||
|
|
623d1e6a40 | ||
|
|
08fa4a997f | ||
|
|
4e21cf8494 | ||
|
|
2ebbda6852 | ||
|
|
010a6d6e42 | ||
|
|
3b1481879a | ||
|
|
3ddcc3884b | ||
|
|
260ab1ec89 | ||
|
|
69803a999f | ||
|
|
d4a75ed871 | ||
|
|
7394f14218 | ||
|
|
23cd7b9ebd | ||
|
|
477cfee78e | ||
|
|
750cecfdaf | ||
|
|
32a28fba32 | ||
|
|
fe926cbf9a | ||
|
|
d18e65ca6c | ||
|
|
ec67ca605c | ||
|
|
9cb3c963a1 | ||
|
|
8a4caf82bb | ||
|
|
7a5941cfa9 | ||
|
|
690c49ae1f | ||
|
|
c77c095893 | ||
|
|
98ddc65fa2 | ||
|
|
41a7c71b7d | ||
|
|
cb1d3d1db4 | ||
|
|
5ba2a31d7d | ||
|
|
0768a93bcb | ||
|
|
e690c6d0ff | ||
|
|
0c6bf406c1 | ||
|
|
95b5f12226 | ||
|
|
5b4b622834 | ||
|
|
b908b77a34 | ||
|
|
dbba310385 | ||
|
|
0a0ca9ba93 | ||
|
|
8aa574a7c4 | ||
|
|
37ac8c038f | ||
|
|
9b6456a80f | ||
|
|
f6ffd314b1 | ||
|
|
b569c6a6dd | ||
|
|
c84f416973 | ||
|
|
6ebc476d2b | ||
|
|
98c340d94d | ||
|
|
78d80918aa | ||
|
|
e8d7d6b4e7 | ||
|
|
53341b0dc0 | ||
|
|
f64c7d81ad | ||
|
|
197de59089 | ||
|
|
13eb37cc46 | ||
|
|
c21c0ff411 | ||
|
|
72f6af7019 | ||
|
|
6b14321505 | ||
|
|
4fcb719613 | ||
|
|
50915d9100 | ||
|
|
834792bc2d | ||
|
|
04b225711f | ||
|
|
eee4a75353 | ||
|
|
15d0df1a12 | ||
|
|
5c3e8c35c4 | ||
|
|
ac514fce30 | ||
|
|
f7343ea305 | ||
|
|
1435421c3c | ||
|
|
735c0fe367 | ||
|
|
af99cfa6f9 | ||
|
|
525ff009b6 | ||
|
|
ee46167320 | ||
|
|
6fc03403b4 | ||
|
|
760c481d39 | ||
|
|
2c4906534b | ||
|
|
2ed79f3f9c | ||
|
|
7e9be878c4 | ||
|
|
0a5ae3b090 | ||
|
|
70b8c1f9b7 | ||
|
|
b067b671db | ||
|
|
268ccac7e1 | ||
|
|
5e487bc4ba | ||
|
|
ffeda7d60b | ||
|
|
2779d1a489 | ||
|
|
1752815654 | ||
|
|
429ca400e5 | ||
|
|
984853bd66 | ||
|
|
ff2549d4b7 | ||
|
|
d33bb6b4bb | ||
|
|
a3c0eca063 | ||
|
|
10de4ac78e | ||
|
|
895394ebb9 | ||
|
|
349f8d936a | ||
|
|
bbc65391a1 | ||
|
|
751c248657 | ||
|
|
9052cd3cdd | ||
|
|
2736527fc1 | ||
|
|
0c7001acf6 | ||
|
|
9e9be5bf09 | ||
|
|
008e1ad27b | ||
|
|
3e5ae14a54 | ||
|
|
0c28833b14 | ||
|
|
75ef95c6bf | ||
|
|
b906f3c654 | ||
|
|
4b274a454b | ||
|
|
6554005742 | ||
|
|
9f04022afc | ||
|
|
fbab512975 | ||
|
|
c9b3a67c8b | ||
|
|
3169cd6591 | ||
|
|
b116e487d3 | ||
|
|
aa57044bb8 | ||
|
|
fdd578dad9 | ||
|
|
2801520546 | ||
|
|
caaf983b3d | ||
|
|
aaba13530c | ||
|
|
e05ec3bcee | ||
|
|
703a132a61 | ||
|
|
e55226e685 | ||
|
|
9a4e6de5f9 | ||
|
|
a4e55a328c | ||
|
|
2705685f07 | ||
|
|
b7fb17a79f | ||
|
|
ffeb73ab7c | ||
|
|
427dec56e4 | ||
|
|
94ce87d953 | ||
|
|
0dc4f0f11a | ||
|
|
a1d7e65ffb | ||
|
|
61702d9c2a | ||
|
|
5b08bef53f | ||
|
|
53a6588054 | ||
|
|
9855c0c13e | ||
|
|
c5d005bdeb | ||
|
|
1eb844c75b | ||
|
|
7e177f3cbf | ||
|
|
eb91cfbda1 | ||
|
|
54082c1fce | ||
|
|
b5caf6dacf | ||
|
|
f4d1ce5388 | ||
|
|
7d7ec69dc1 | ||
|
|
7208288c00 | ||
|
|
aff3745859 | ||
|
|
e103ddd216 | ||
|
|
41a4965775 | ||
|
|
49a06f513b | ||
|
|
1308f3684b | ||
|
|
c51eccac38 | ||
|
|
09157767bf | ||
|
|
32cc2c708a | ||
|
|
7f2de233fc | ||
|
|
7cb150606c | ||
|
|
87cac010eb | ||
|
|
03926754e7 | ||
|
|
65efda1a7a | ||
|
|
5941d4ca16 | ||
|
|
e77101af89 | ||
|
|
e766be6af9 | ||
|
|
95d1658324 | ||
|
|
9b24550738 | ||
|
|
7947568019 | ||
|
|
399ee98923 | ||
|
|
7b3b4a2ec5 | ||
|
|
09177da620 | ||
|
|
8392cfb2fa | ||
|
|
01face7315 | ||
|
|
5b6f4d65bf | ||
|
|
cd6f8f3db3 | ||
|
|
a9b07ddf1d | ||
|
|
f3710c575b | ||
|
|
1f5ab45a1e | ||
|
|
58d453db11 | ||
|
|
bd426b763c | ||
|
|
2e42efa71f | ||
|
|
58181bd723 | ||
|
|
dcef3115b8 | ||
|
|
4bdc5dc90f | ||
|
|
e33d6b3a0a | ||
|
|
d8ddaccf07 | ||
|
|
ca55ea16f0 | ||
|
|
cb42330e22 | ||
|
|
4e55cf0baa | ||
|
|
abec45c492 | ||
|
|
610e25b98a | ||
|
|
ad11e63338 | ||
|
|
440eb72ae4 | ||
|
|
c4553de302 | ||
|
|
32904b75e4 | ||
|
|
35a4771f89 | ||
|
|
bbb2e9391e | ||
|
|
9dc186f455 | ||
|
|
82b9c03a7e | ||
|
|
f4f9ba9efa | ||
|
|
495864e8e0 | ||
|
|
ac917df519 | ||
|
|
3b12fef948 |
17
.vscode/launch.json
vendored
17
.vscode/launch.json
vendored
@@ -5,12 +5,25 @@
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": ".NET Core Launch (console)",
|
||||
"name": ".NET Core Launch (Test)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/Test/bin/Debug/netcoreapp3.1/Test.dll",
|
||||
"program": "${workspaceFolder}/Test/bin/Debug/net6.0/Test.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/Test",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Launch (ExecutableTest)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/ExecutableTest/bin/Debug/net6.0/ExecutableTest.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/Test",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
|
||||
6
.vscode/tasks.json
vendored
6
.vscode/tasks.json
vendored
@@ -7,7 +7,7 @@
|
||||
"type": "process",
|
||||
"args": [
|
||||
"build",
|
||||
"${workspaceFolder}/Test/Test.csproj",
|
||||
"${workspaceFolder}/BurnOutSharp.sln",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
@@ -19,7 +19,7 @@
|
||||
"type": "process",
|
||||
"args": [
|
||||
"publish",
|
||||
"${workspaceFolder}/Test/Test.csproj",
|
||||
"${workspaceFolder}/BurnOutSharp.sln",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
@@ -32,7 +32,7 @@
|
||||
"args": [
|
||||
"watch",
|
||||
"run",
|
||||
"${workspaceFolder}/Test/Test.csproj",
|
||||
"${workspaceFolder}/BurnOutSharp.sln",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
|
||||
336
BurnOutSharp.Builder/AbstractSyntaxNotationOne.cs
Normal file
336
BurnOutSharp.Builder/AbstractSyntaxNotationOne.cs
Normal file
@@ -0,0 +1,336 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
|
||||
namespace BurnOutSharp.Builder
|
||||
{
|
||||
/// <summary>
|
||||
/// ASN.1 type indicators
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum ASN1Type : byte
|
||||
{
|
||||
#region Modifiers
|
||||
|
||||
V_ASN1_UNIVERSAL = 0x00,
|
||||
V_ASN1_PRIMITIVE_TAG = 0x1F,
|
||||
V_ASN1_CONSTRUCTED = 0x20,
|
||||
V_ASN1_APPLICATION = 0x40,
|
||||
V_ASN1_CONTEXT_SPECIFIC = 0x80,
|
||||
V_ASN1_PRIVATE = 0xC0,
|
||||
|
||||
#endregion
|
||||
|
||||
#region Types
|
||||
|
||||
V_ASN1_EOC = 0x00,
|
||||
V_ASN1_BOOLEAN = 0x01,
|
||||
V_ASN1_INTEGER = 0x02,
|
||||
V_ASN1_BIT_STRING = 0x03,
|
||||
V_ASN1_OCTET_STRING = 0x04,
|
||||
V_ASN1_NULL = 0x05,
|
||||
V_ASN1_OBJECT = 0x06,
|
||||
V_ASN1_OBJECT_DESCRIPTOR = 0x07,
|
||||
V_ASN1_EXTERNAL = 0x08,
|
||||
V_ASN1_REAL = 0x09,
|
||||
V_ASN1_ENUMERATED = 0x0A,
|
||||
V_ASN1_UTF8STRING = 0x0C,
|
||||
V_ASN1_SEQUENCE = 0x10,
|
||||
V_ASN1_SET = 0x11,
|
||||
V_ASN1_NUMERICSTRING = 0x12,
|
||||
V_ASN1_PRINTABLESTRING = 0x13,
|
||||
V_ASN1_T61STRING = 0x14,
|
||||
V_ASN1_TELETEXSTRING = 0x14,
|
||||
V_ASN1_VIDEOTEXSTRING = 0x15,
|
||||
V_ASN1_IA5STRING = 0x16,
|
||||
V_ASN1_UTCTIME = 0x17,
|
||||
V_ASN1_GENERALIZEDTIME = 0x18,
|
||||
V_ASN1_GRAPHICSTRING = 0x19,
|
||||
V_ASN1_ISO64STRING = 0x1A,
|
||||
V_ASN1_VISIBLESTRING = 0x1A,
|
||||
V_ASN1_GENERALSTRING = 0x1B,
|
||||
V_ASN1_UNIVERSALSTRING = 0x1C,
|
||||
V_ASN1_BMPSTRING = 0x1E,
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ASN.1 Parser
|
||||
/// </summary>
|
||||
public class AbstractSyntaxNotationOne
|
||||
{
|
||||
/// <summary>
|
||||
/// Parse a byte array into a DER-encoded ASN.1 structure
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array representing the data</param>
|
||||
/// <param name="pointer">Current pointer into the data</param>
|
||||
/// <returns></returns>
|
||||
public static List<ASN1TypeLengthValue> Parse(byte[] data, int pointer)
|
||||
{
|
||||
// Create the output list to return
|
||||
var topLevelValues = new List<ASN1TypeLengthValue>();
|
||||
|
||||
// Loop through the data and return all top-level values
|
||||
while (pointer < data.Length)
|
||||
{
|
||||
var topLevelValue = new ASN1TypeLengthValue(data, ref pointer);
|
||||
topLevelValues.Add(topLevelValue);
|
||||
}
|
||||
|
||||
return topLevelValues;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ASN.1 type/length/value class that all types are based on
|
||||
/// </summary>
|
||||
public class ASN1TypeLengthValue
|
||||
{
|
||||
/// <summary>
|
||||
/// The ASN.1 type
|
||||
/// </summary>
|
||||
public ASN1Type Type { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Length of the value
|
||||
/// </summary>
|
||||
public ulong Length { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Generic value associated with <see cref="Type"/>
|
||||
/// </summary>
|
||||
public object Value { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Read from the source data array at an index
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array representing data to read</param>
|
||||
/// <param name="index">Index within the array to read at</param>
|
||||
public ASN1TypeLengthValue(byte[] data, ref int index)
|
||||
{
|
||||
// Get the type and modifiers
|
||||
this.Type = (ASN1Type)data[index++];
|
||||
|
||||
// If we have an end indicator, we just return
|
||||
if (this.Type == ASN1Type.V_ASN1_EOC)
|
||||
return;
|
||||
|
||||
// Get the length of the value
|
||||
this.Length = ReadLength(data, ref index);
|
||||
|
||||
// Read the value
|
||||
if (this.Type.HasFlag(ASN1Type.V_ASN1_CONSTRUCTED))
|
||||
{
|
||||
var valueList = new List<ASN1TypeLengthValue>();
|
||||
|
||||
int currentIndex = index;
|
||||
while (index < currentIndex + (int)this.Length)
|
||||
{
|
||||
valueList.Add(new ASN1TypeLengthValue(data, ref index));
|
||||
}
|
||||
|
||||
this.Value = valueList.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Get more granular based on type
|
||||
this.Value = data.ReadBytes(ref index, (int)this.Length);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Format the TLV as a string
|
||||
/// </summary>
|
||||
/// <param name="paddingLevel">Padding level of the item when formatting</param>
|
||||
/// <returns>String representing the TLV, if possible</returns>
|
||||
public string Format(int paddingLevel = 0)
|
||||
{
|
||||
// Create the left-padding string
|
||||
string padding = new string(' ', paddingLevel);
|
||||
|
||||
// If we have an invalid item
|
||||
if (this.Type == 0)
|
||||
return $"{padding}UNKNOWN TYPE";
|
||||
|
||||
// Create the string builder
|
||||
StringBuilder formatBuilder = new StringBuilder();
|
||||
|
||||
// Append the type
|
||||
formatBuilder.Append($"{padding}Type: {this.Type}");
|
||||
if (this.Type == ASN1Type.V_ASN1_EOC)
|
||||
return formatBuilder.ToString();
|
||||
|
||||
// Append the length
|
||||
formatBuilder.Append($", Length: {this.Length}");
|
||||
if (this.Length == 0)
|
||||
return formatBuilder.ToString();
|
||||
|
||||
// If we have a constructed type
|
||||
if (this.Type.HasFlag(ASN1Type.V_ASN1_CONSTRUCTED))
|
||||
{
|
||||
var valueAsObjectArray = this.Value as ASN1TypeLengthValue[];
|
||||
if (valueAsObjectArray == null)
|
||||
{
|
||||
formatBuilder.Append(", Value: [INVALID DATA TYPE]");
|
||||
return formatBuilder.ToString();
|
||||
}
|
||||
|
||||
formatBuilder.Append(", Value:\n");
|
||||
for (int i = 0; i < valueAsObjectArray.Length; i++)
|
||||
{
|
||||
var child = valueAsObjectArray[i];
|
||||
string childString = child.Format(paddingLevel + 1);
|
||||
formatBuilder.Append($"{childString}\n");
|
||||
}
|
||||
|
||||
return formatBuilder.ToString().TrimEnd('\n');
|
||||
}
|
||||
|
||||
// Get the value as a byte array
|
||||
byte[] valueAsByteArray = this.Value as byte[];
|
||||
if (valueAsByteArray == null)
|
||||
{
|
||||
formatBuilder.Append(", Value: [INVALID DATA TYPE]");
|
||||
return formatBuilder.ToString();
|
||||
}
|
||||
|
||||
// If we have a primitive type
|
||||
switch (this.Type)
|
||||
{
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-boolean"/>
|
||||
case ASN1Type.V_ASN1_BOOLEAN:
|
||||
if (this.Length > 1 || valueAsByteArray.Length > 1)
|
||||
formatBuilder.Append($" [Expected length of 1]");
|
||||
|
||||
bool booleanValue = valueAsByteArray[0] == 0x00 ? false : true;
|
||||
formatBuilder.Append($", Value: {booleanValue}");
|
||||
break;
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-integer"/>
|
||||
case ASN1Type.V_ASN1_INTEGER:
|
||||
Array.Reverse(valueAsByteArray);
|
||||
BigInteger integerValue = new BigInteger(valueAsByteArray);
|
||||
formatBuilder.Append($", Value: {integerValue}");
|
||||
break;
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-bit-string"/>
|
||||
case ASN1Type.V_ASN1_BIT_STRING:
|
||||
// TODO: Read into a BitArray and print that out instead?
|
||||
int unusedBits = valueAsByteArray[0];
|
||||
formatBuilder.Append($", Value with {unusedBits} unused bits: {BitConverter.ToString(valueAsByteArray.Skip(1).ToArray()).Replace('-', ' ')}");
|
||||
break;
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-octet-string"/>
|
||||
case ASN1Type.V_ASN1_OCTET_STRING:
|
||||
formatBuilder.Append($", Value: {BitConverter.ToString(valueAsByteArray).Replace('-', ' ')}");
|
||||
break;
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-object-identifier"/>
|
||||
/// <see cref="http://snmpsharpnet.com/index.php/2009/03/02/ber-encoding-and-decoding-oid-values/"/>
|
||||
case ASN1Type.V_ASN1_OBJECT:
|
||||
// Derive array of values
|
||||
ulong[] objectNodes = ObjectIdentifier.ParseDERIntoArray(valueAsByteArray, this.Length);
|
||||
|
||||
// Append the dot and modified OID-IRI notations
|
||||
string dotNotationString = ObjectIdentifier.ParseOIDToDotNotation(objectNodes);
|
||||
string oidIriString = ObjectIdentifier.ParseOIDToOIDIRINotation(objectNodes);
|
||||
formatBuilder.Append($", Value: {dotNotationString} ({oidIriString})");
|
||||
break;
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-utf8string"/>
|
||||
case ASN1Type.V_ASN1_UTF8STRING:
|
||||
formatBuilder.Append($", Value: {Encoding.UTF8.GetString(valueAsByteArray)}");
|
||||
break;
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-printablestring"/>
|
||||
case ASN1Type.V_ASN1_PRINTABLESTRING:
|
||||
formatBuilder.Append($", Value: {Encoding.ASCII.GetString(valueAsByteArray)}");
|
||||
break;
|
||||
|
||||
//case ASN1Type.V_ASN1_T61STRING:
|
||||
case ASN1Type.V_ASN1_TELETEXSTRING:
|
||||
formatBuilder.Append($", Value: {Encoding.ASCII.GetString(valueAsByteArray)}");
|
||||
break;
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-ia5string"/>
|
||||
case ASN1Type.V_ASN1_IA5STRING:
|
||||
formatBuilder.Append($", Value: {Encoding.ASCII.GetString(valueAsByteArray)}");
|
||||
break;
|
||||
|
||||
case ASN1Type.V_ASN1_UTCTIME:
|
||||
string utctimeString = Encoding.ASCII.GetString(valueAsByteArray);
|
||||
if (DateTime.TryParse(utctimeString, out DateTime utctimeDateTime))
|
||||
formatBuilder.Append($", Value: {utctimeDateTime}");
|
||||
else
|
||||
formatBuilder.Append($", Value: {utctimeString}");
|
||||
break;
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-bmpstring"/>
|
||||
case ASN1Type.V_ASN1_BMPSTRING:
|
||||
formatBuilder.Append($", Value: {Encoding.Unicode.GetString(valueAsByteArray)}");
|
||||
break;
|
||||
|
||||
default:
|
||||
formatBuilder.Append($", Value (Unknown Format): {BitConverter.ToString(this.Value as byte[]).Replace('-', ' ')}");
|
||||
break;
|
||||
}
|
||||
|
||||
// Return the formatted string
|
||||
return formatBuilder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the length field for a type
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array representing data to read</param>
|
||||
/// <param name="index">Index within the array to read at</param>
|
||||
/// <returns>The length value read from the array</returns>
|
||||
private static ulong ReadLength(byte[] data, ref int index)
|
||||
{
|
||||
// If we have invalid data, throw an exception
|
||||
if (data == null || index < 0 && index >= data.Length)
|
||||
throw new ArgumentException();
|
||||
|
||||
// Read the first byte, assuming it's the length
|
||||
byte length = data[index++];
|
||||
|
||||
// If the bit 7 is not set, then use the value as it is
|
||||
if ((length & 0x80) == 0)
|
||||
return length;
|
||||
|
||||
// Otherwise, use the value as the number of remaining bytes to read
|
||||
int bytesToRead = length & ~0x80;
|
||||
byte[] bytesRead = data.ReadBytes(ref index, bytesToRead);
|
||||
|
||||
// TODO: Write extensions to read big-endian
|
||||
|
||||
// Reverse the bytes to be in big-endian order
|
||||
Array.Reverse(bytesRead);
|
||||
|
||||
switch (bytesRead.Length)
|
||||
{
|
||||
case 1:
|
||||
return bytesRead[0];
|
||||
case 2:
|
||||
return BitConverter.ToUInt16(bytesRead, 0);
|
||||
case 3:
|
||||
Array.Resize(ref bytesRead, 4);
|
||||
goto case 4;
|
||||
case 4:
|
||||
return BitConverter.ToUInt32(bytesRead, 0);
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
Array.Resize(ref bytesRead, 8);
|
||||
goto case 8;
|
||||
case 8:
|
||||
return BitConverter.ToUInt64(bytesRead, 0);
|
||||
default:
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
26
BurnOutSharp.Builder/BurnOutSharp.Builder.csproj
Normal file
26
BurnOutSharp.Builder/BurnOutSharp.Builder.csproj
Normal file
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
|
||||
<Title>BurnOutSharp.Builder</Title>
|
||||
<AssemblyName>BurnOutSharp.Builder</AssemblyName>
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
<Product>BurnOutSharp</Product>
|
||||
<Copyright>Copyright (c)2022 Matt Nadareski</Copyright>
|
||||
<RepositoryUrl>https://github.com/mnadareski/BurnOutSharp</RepositoryUrl>
|
||||
<Version>2.5</Version>
|
||||
<AssemblyVersion>2.5</AssemblyVersion>
|
||||
<FileVersion>2.5</FileVersion>
|
||||
<IncludeSource>true</IncludeSource>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BurnOutSharp.Models\BurnOutSharp.Models.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
1643
BurnOutSharp.Builder/Extensions.cs
Normal file
1643
BurnOutSharp.Builder/Extensions.cs
Normal file
File diff suppressed because it is too large
Load Diff
107
BurnOutSharp.Builder/LinearExecutable.cs
Normal file
107
BurnOutSharp.Builder/LinearExecutable.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.Models.LinearExecutable;
|
||||
|
||||
namespace BurnOutSharp.Builder
|
||||
{
|
||||
// TODO: Make Stream Data rely on Byte Data
|
||||
public static class LinearExecutable
|
||||
{
|
||||
#region Byte Data
|
||||
|
||||
/// <summary>
|
||||
/// Parse a byte array into a Linear Executable
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array to parse</param>
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <returns>Filled executable on success, null on error</returns>
|
||||
public static Executable ParseExecutable(byte[] data, int offset)
|
||||
{
|
||||
// If the data is invalid
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
// If the offset is out of bounds
|
||||
if (offset < 0 || offset >= data.Length)
|
||||
return null;
|
||||
|
||||
// Cache the current offset
|
||||
int initialOffset = offset;
|
||||
|
||||
// Create a new executable to fill
|
||||
var executable = new Executable();
|
||||
|
||||
// Parse the MS-DOS stub
|
||||
var stub = MSDOS.ParseExecutable(data, offset);
|
||||
if (stub?.Header == null || stub.Header.NewExeHeaderAddr == 0)
|
||||
return null;
|
||||
|
||||
// Set the MS-DOS stub
|
||||
executable.Stub = stub;
|
||||
|
||||
// TODO: Implement LE/LX parsing
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a byte array into a Linear Executable information block
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array to parse</param>
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <returns>Filled information block on success, null on error</returns>
|
||||
private static InformationBlock ParseInformationBlock(byte[] data, int offset)
|
||||
{
|
||||
// TODO: Implement LE/LX information block parsing
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Stream Data
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a Linear Executable
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled executable on success, null on error</returns>
|
||||
public static Executable ParseExecutable(Stream data)
|
||||
{
|
||||
// If the data is invalid
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
// If the offset is out of bounds
|
||||
if (data.Position < 0 || data.Position >= data.Length)
|
||||
return null;
|
||||
|
||||
// Cache the current offset
|
||||
int initialOffset = (int)data.Position;
|
||||
|
||||
// Create a new executable to fill
|
||||
var executable = new Executable();
|
||||
|
||||
// Parse the MS-DOS stub
|
||||
var stub = MSDOS.ParseExecutable(data);
|
||||
if (stub?.Header == null || stub.Header.NewExeHeaderAddr == 0)
|
||||
return null;
|
||||
|
||||
// Set the MS-DOS stub
|
||||
executable.Stub = stub;
|
||||
|
||||
// TODO: Implement LE/LX parsing
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a Linear Executable information block
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled executable header on success, null on error</returns>
|
||||
private static InformationBlock ParseInformationBlock(Stream data)
|
||||
{
|
||||
// TODO: Implement LE/LX information block parsing
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
295
BurnOutSharp.Builder/MSDOS.cs
Normal file
295
BurnOutSharp.Builder/MSDOS.cs
Normal file
@@ -0,0 +1,295 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.Models.MSDOS;
|
||||
|
||||
namespace BurnOutSharp.Builder
|
||||
{
|
||||
// TODO: Make Stream Data rely on Byte Data
|
||||
public static class MSDOS
|
||||
{
|
||||
#region Byte Data
|
||||
|
||||
/// <summary>
|
||||
/// Parse a byte array into an MS-DOS executable
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array to parse</param>
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <returns>Filled executable on success, null on error</returns>
|
||||
public static Executable ParseExecutable(byte[] data, int offset)
|
||||
{
|
||||
// If the data is invalid
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
// If the offset is out of bounds
|
||||
if (offset < 0 || offset >= data.Length)
|
||||
return null;
|
||||
|
||||
// Cache the current offset
|
||||
int initialOffset = offset;
|
||||
|
||||
// Create a new executable to fill
|
||||
var executable = new Executable();
|
||||
|
||||
#region Executable Header
|
||||
|
||||
// Try to parse the executable header
|
||||
var executableHeader = ParseExecutableHeader(data, offset);
|
||||
if (executableHeader == null)
|
||||
return null;
|
||||
|
||||
// Set the executable header
|
||||
executable.Header = executableHeader;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Relocation Table
|
||||
|
||||
// If the offset for the relocation table doesn't exist
|
||||
int tableAddress = initialOffset + executableHeader.RelocationTableAddr;
|
||||
if (tableAddress >= data.Length)
|
||||
return executable;
|
||||
|
||||
// Try to parse the relocation table
|
||||
var relocationTable = ParseRelocationTable(data, tableAddress, executableHeader.RelocationItems);
|
||||
if (relocationTable == null)
|
||||
return null;
|
||||
|
||||
// Set the relocation table
|
||||
executable.RelocationTable = relocationTable;
|
||||
|
||||
#endregion
|
||||
|
||||
// Return the executable
|
||||
return executable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a byte array into an MS-DOS executable header
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array to parse</param>
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <returns>Filled executable header on success, null on error</returns>
|
||||
private static ExecutableHeader ParseExecutableHeader(byte[] data, int offset)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var header = new ExecutableHeader();
|
||||
|
||||
#region Standard Fields
|
||||
|
||||
header.Magic = new byte[2];
|
||||
for (int i = 0; i < header.Magic.Length; i++)
|
||||
{
|
||||
header.Magic[i] = data.ReadByte(ref offset);
|
||||
}
|
||||
if (header.Magic[0] != 'M' || header.Magic[1] != 'Z')
|
||||
return null;
|
||||
|
||||
header.LastPageBytes = data.ReadUInt16(ref offset);
|
||||
header.Pages = data.ReadUInt16(ref offset);
|
||||
header.RelocationItems = data.ReadUInt16(ref offset);
|
||||
header.HeaderParagraphSize = data.ReadUInt16(ref offset);
|
||||
header.MinimumExtraParagraphs = data.ReadUInt16(ref offset);
|
||||
header.MaximumExtraParagraphs = data.ReadUInt16(ref offset);
|
||||
header.InitialSSValue = data.ReadUInt16(ref offset);
|
||||
header.InitialSPValue = data.ReadUInt16(ref offset);
|
||||
header.Checksum = data.ReadUInt16(ref offset);
|
||||
header.InitialIPValue = data.ReadUInt16(ref offset);
|
||||
header.InitialCSValue = data.ReadUInt16(ref offset);
|
||||
header.RelocationTableAddr = data.ReadUInt16(ref offset);
|
||||
header.OverlayNumber = data.ReadUInt16(ref offset);
|
||||
|
||||
#endregion
|
||||
|
||||
// If we don't have enough data for PE extensions
|
||||
if (offset >= data.Length || data.Length - offset < 36)
|
||||
return header;
|
||||
|
||||
#region PE Extensions
|
||||
|
||||
header.Reserved1 = new ushort[4];
|
||||
for (int i = 0; i < header.Reserved1.Length; i++)
|
||||
{
|
||||
header.Reserved1[i] = data.ReadUInt16(ref offset);
|
||||
}
|
||||
header.OEMIdentifier = data.ReadUInt16(ref offset);
|
||||
header.OEMInformation = data.ReadUInt16(ref offset);
|
||||
header.Reserved2 = new ushort[10];
|
||||
for (int i = 0; i < header.Reserved2.Length; i++)
|
||||
{
|
||||
header.Reserved2[i] = data.ReadUInt16(ref offset);
|
||||
}
|
||||
header.NewExeHeaderAddr = data.ReadUInt32(ref offset);
|
||||
|
||||
#endregion
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a byte array into a relocation table
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array to parse</param>
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <param name="count">Number of relocation table entries to read</param>
|
||||
/// <returns>Filled relocation table on success, null on error</returns>
|
||||
private static RelocationEntry[] ParseRelocationTable(byte[] data, int offset, int count)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var relocationTable = new RelocationEntry[count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var entry = new RelocationEntry();
|
||||
entry.Offset = data.ReadUInt16(ref offset);
|
||||
entry.Segment = data.ReadUInt16(ref offset);
|
||||
relocationTable[i] = entry;
|
||||
}
|
||||
|
||||
return relocationTable;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Stream Data
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into an MS-DOS executable
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled executable on success, null on error</returns>
|
||||
public static Executable ParseExecutable(Stream data)
|
||||
{
|
||||
// If the data is invalid
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
// If the offset is out of bounds
|
||||
if (data.Position < 0 || data.Position >= data.Length)
|
||||
return null;
|
||||
|
||||
// Cache the current offset
|
||||
int initialOffset = (int)data.Position;
|
||||
|
||||
// Create a new executable to fill
|
||||
var executable = new Executable();
|
||||
|
||||
#region Executable Header
|
||||
|
||||
// Try to parse the executable header
|
||||
var executableHeader = ParseExecutableHeader(data);
|
||||
if (executableHeader == null)
|
||||
return null;
|
||||
|
||||
// Set the executable header
|
||||
executable.Header = executableHeader;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Relocation Table
|
||||
|
||||
// If the offset for the relocation table doesn't exist
|
||||
int tableAddress = initialOffset + executableHeader.RelocationTableAddr;
|
||||
if (tableAddress >= data.Length)
|
||||
return executable;
|
||||
|
||||
// Try to parse the relocation table
|
||||
data.Seek(tableAddress, SeekOrigin.Begin);
|
||||
var relocationTable = ParseRelocationTable(data, executableHeader.RelocationItems);
|
||||
if (relocationTable == null)
|
||||
return null;
|
||||
|
||||
// Set the relocation table
|
||||
executable.RelocationTable = relocationTable;
|
||||
|
||||
#endregion
|
||||
|
||||
// Return the executable
|
||||
return executable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into an MS-DOS executable header
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled executable header on success, null on error</returns>
|
||||
private static ExecutableHeader ParseExecutableHeader(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var header = new ExecutableHeader();
|
||||
|
||||
#region Standard Fields
|
||||
|
||||
header.Magic = new byte[2];
|
||||
for (int i = 0; i < header.Magic.Length; i++)
|
||||
{
|
||||
header.Magic[i] = data.ReadByteValue();
|
||||
}
|
||||
if (header.Magic[0] != 'M' || header.Magic[1] != 'Z')
|
||||
return null;
|
||||
|
||||
header.LastPageBytes = data.ReadUInt16();
|
||||
header.Pages = data.ReadUInt16();
|
||||
header.RelocationItems = data.ReadUInt16();
|
||||
header.HeaderParagraphSize = data.ReadUInt16();
|
||||
header.MinimumExtraParagraphs = data.ReadUInt16();
|
||||
header.MaximumExtraParagraphs = data.ReadUInt16();
|
||||
header.InitialSSValue = data.ReadUInt16();
|
||||
header.InitialSPValue = data.ReadUInt16();
|
||||
header.Checksum = data.ReadUInt16();
|
||||
header.InitialIPValue = data.ReadUInt16();
|
||||
header.InitialCSValue = data.ReadUInt16();
|
||||
header.RelocationTableAddr = data.ReadUInt16();
|
||||
header.OverlayNumber = data.ReadUInt16();
|
||||
|
||||
#endregion
|
||||
|
||||
// If we don't have enough data for PE extensions
|
||||
if (data.Position >= data.Length || data.Length - data.Position < 36)
|
||||
return header;
|
||||
|
||||
#region PE Extensions
|
||||
|
||||
header.Reserved1 = new ushort[4];
|
||||
for (int i = 0; i < header.Reserved1.Length; i++)
|
||||
{
|
||||
header.Reserved1[i] = data.ReadUInt16();
|
||||
}
|
||||
header.OEMIdentifier = data.ReadUInt16();
|
||||
header.OEMInformation = data.ReadUInt16();
|
||||
header.Reserved2 = new ushort[10];
|
||||
for (int i = 0; i < header.Reserved2.Length; i++)
|
||||
{
|
||||
header.Reserved2[i] = data.ReadUInt16();
|
||||
}
|
||||
header.NewExeHeaderAddr = data.ReadUInt32();
|
||||
|
||||
#endregion
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a relocation table
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <param name="count">Number of relocation table entries to read</param>
|
||||
/// <returns>Filled relocation table on success, null on error</returns>
|
||||
private static RelocationEntry[] ParseRelocationTable(Stream data, int count)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var relocationTable = new RelocationEntry[count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var entry = new RelocationEntry();
|
||||
entry.Offset = data.ReadUInt16();
|
||||
entry.Segment = data.ReadUInt16();
|
||||
relocationTable[i] = entry;
|
||||
}
|
||||
|
||||
return relocationTable;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
958
BurnOutSharp.Builder/NewExecutable.cs
Normal file
958
BurnOutSharp.Builder/NewExecutable.cs
Normal file
@@ -0,0 +1,958 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BurnOutSharp.Models.NewExecutable;
|
||||
|
||||
namespace BurnOutSharp.Builder
|
||||
{
|
||||
// TODO: Make Stream Data rely on Byte Data
|
||||
public static class NewExecutable
|
||||
{
|
||||
#region Byte Data
|
||||
|
||||
/// <summary>
|
||||
/// Parse a byte array into a New Executable
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array to parse</param>
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <returns>Filled executable on success, null on error</returns>
|
||||
public static Executable ParseExecutable(byte[] data, int offset)
|
||||
{
|
||||
// If the data is invalid
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
// If the offset is out of bounds
|
||||
if (offset < 0 || offset >= data.Length)
|
||||
return null;
|
||||
|
||||
// Cache the current offset
|
||||
int initialOffset = offset;
|
||||
|
||||
// Create a new executable to fill
|
||||
var executable = new Executable();
|
||||
|
||||
#region MS-DOS Stub
|
||||
|
||||
// Parse the MS-DOS stub
|
||||
var stub = MSDOS.ParseExecutable(data, offset);
|
||||
if (stub?.Header == null || stub.Header.NewExeHeaderAddr == 0)
|
||||
return null;
|
||||
|
||||
// Set the MS-DOS stub
|
||||
executable.Stub = stub;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Executable Header
|
||||
|
||||
// Try to parse the executable header
|
||||
offset = (int)(initialOffset + stub.Header.NewExeHeaderAddr);
|
||||
var executableHeader = ParseExecutableHeader(data, offset);
|
||||
if (executableHeader == null)
|
||||
return null;
|
||||
|
||||
// Set the executable header
|
||||
executable.Header = executableHeader;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Segment Table
|
||||
|
||||
// If the offset for the segment table doesn't exist
|
||||
int tableAddress = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.SegmentTableOffset;
|
||||
if (tableAddress >= data.Length)
|
||||
return executable;
|
||||
|
||||
// Try to parse the segment table
|
||||
var segmentTable = ParseSegmentTable(data, tableAddress, executableHeader.FileSegmentCount);
|
||||
if (segmentTable == null)
|
||||
return null;
|
||||
|
||||
// Set the segment table
|
||||
executable.SegmentTable = segmentTable;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Resource Table
|
||||
|
||||
// If the offset for the segment table doesn't exist
|
||||
tableAddress = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.SegmentTableOffset;
|
||||
if (tableAddress >= data.Length)
|
||||
return executable;
|
||||
|
||||
// Try to parse the resource table
|
||||
var resourceTable = ParseResourceTable(data, tableAddress, executableHeader.ResourceEntriesCount);
|
||||
if (resourceTable == null)
|
||||
return null;
|
||||
|
||||
// Set the resource table
|
||||
executable.ResourceTable = resourceTable;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Resident-Name Table
|
||||
|
||||
// If the offset for the resident-name table doesn't exist
|
||||
tableAddress = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.ResidentNameTableOffset;
|
||||
int endOffset = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.ModuleReferenceTableOffset;
|
||||
if (tableAddress >= data.Length)
|
||||
return executable;
|
||||
|
||||
// Try to parse the resident-name table
|
||||
var residentNameTable = ParseResidentNameTable(data, tableAddress, endOffset);
|
||||
if (residentNameTable == null)
|
||||
return null;
|
||||
|
||||
// Set the resident-name table
|
||||
executable.ResidentNameTable = residentNameTable;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Module-Reference Table
|
||||
|
||||
// If the offset for the module-reference table doesn't exist
|
||||
tableAddress = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.ModuleReferenceTableOffset;
|
||||
if (tableAddress >= data.Length)
|
||||
return executable;
|
||||
|
||||
// Try to parse the module-reference table
|
||||
var moduleReferenceTable = ParseModuleReferenceTable(data, tableAddress, executableHeader.ModuleReferenceTableSize);
|
||||
if (moduleReferenceTable == null)
|
||||
return null;
|
||||
|
||||
// Set the module-reference table
|
||||
executable.ModuleReferenceTable = moduleReferenceTable;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imported-Name Table
|
||||
|
||||
// If the offset for the imported-name table doesn't exist
|
||||
tableAddress = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.ImportedNamesTableOffset;
|
||||
endOffset = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.EntryTableOffset;
|
||||
if (tableAddress >= data.Length)
|
||||
return executable;
|
||||
|
||||
// Try to parse the imported-name table
|
||||
var importedNameTable = ParseImportedNameTable(data, tableAddress, endOffset);
|
||||
if (importedNameTable == null)
|
||||
return null;
|
||||
|
||||
// Set the imported-name table
|
||||
executable.ImportedNameTable = importedNameTable;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Entry Table
|
||||
|
||||
// If the offset for the entry table doesn't exist
|
||||
tableAddress = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.EntryTableOffset;
|
||||
endOffset = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.EntryTableOffset
|
||||
+ executableHeader.EntryTableSize;
|
||||
if (tableAddress >= data.Length)
|
||||
return executable;
|
||||
|
||||
// Try to parse the entry table
|
||||
var entryTable = ParseEntryTable(data, tableAddress, endOffset);
|
||||
if (entryTable == null)
|
||||
return null;
|
||||
|
||||
// Set the entry table
|
||||
executable.EntryTable = entryTable;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Nonresident-Name Table
|
||||
|
||||
// If the offset for the nonresident-name table doesn't exist
|
||||
tableAddress = initialOffset
|
||||
+ (int)executableHeader.NonResidentNamesTableOffset;
|
||||
endOffset = initialOffset
|
||||
+ (int)executableHeader.NonResidentNamesTableOffset
|
||||
+ executableHeader.NonResidentNameTableSize;
|
||||
if (tableAddress >= data.Length)
|
||||
return executable;
|
||||
|
||||
// Try to parse the nonresident-name table
|
||||
var nonResidentNameTable = ParseNonResidentNameTable(data, tableAddress, endOffset);
|
||||
if (nonResidentNameTable == null)
|
||||
return null;
|
||||
|
||||
// Set the nonresident-name table
|
||||
executable.NonResidentNameTable = nonResidentNameTable;
|
||||
|
||||
#endregion
|
||||
|
||||
return executable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a byte array into a New Executable header
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array to parse</param>
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <returns>Filled executable header on success, null on error</returns>
|
||||
private static ExecutableHeader ParseExecutableHeader(byte[] data, int offset)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var header = new ExecutableHeader();
|
||||
|
||||
header.Magic = new byte[2];
|
||||
for (int i = 0; i < header.Magic.Length; i++)
|
||||
{
|
||||
header.Magic[i] = data.ReadByte(ref offset);
|
||||
}
|
||||
if (header.Magic[0] != 'N' || header.Magic[1] != 'E')
|
||||
return null;
|
||||
|
||||
header.LinkerVersion = data.ReadByte(ref offset);
|
||||
header.LinkerRevision = data.ReadByte(ref offset);
|
||||
header.EntryTableOffset = data.ReadUInt16(ref offset);
|
||||
header.EntryTableSize = data.ReadUInt16(ref offset);
|
||||
header.CrcChecksum = data.ReadUInt32(ref offset);
|
||||
header.FlagWord = (HeaderFlag)data.ReadUInt16(ref offset);
|
||||
header.AutomaticDataSegmentNumber = data.ReadUInt16(ref offset);
|
||||
header.InitialHeapAlloc = data.ReadUInt16(ref offset);
|
||||
header.InitialStackAlloc = data.ReadUInt16(ref offset);
|
||||
header.InitialCSIPSetting = data.ReadUInt32(ref offset);
|
||||
header.InitialSSSPSetting = data.ReadUInt32(ref offset);
|
||||
header.FileSegmentCount = data.ReadUInt16(ref offset);
|
||||
header.ModuleReferenceTableSize = data.ReadUInt16(ref offset);
|
||||
header.NonResidentNameTableSize = data.ReadUInt16(ref offset);
|
||||
header.SegmentTableOffset = data.ReadUInt16(ref offset);
|
||||
header.ResourceTableOffset = data.ReadUInt16(ref offset);
|
||||
header.ResidentNameTableOffset = data.ReadUInt16(ref offset);
|
||||
header.ModuleReferenceTableOffset = data.ReadUInt16(ref offset);
|
||||
header.ImportedNamesTableOffset = data.ReadUInt16(ref offset);
|
||||
header.NonResidentNamesTableOffset = data.ReadUInt32(ref offset);
|
||||
header.MovableEntriesCount = data.ReadUInt16(ref offset);
|
||||
header.SegmentAlignmentShiftCount = data.ReadUInt16(ref offset);
|
||||
header.ResourceEntriesCount = data.ReadUInt16(ref offset);
|
||||
header.TargetOperatingSystem = (OperatingSystem)data.ReadByte(ref offset);
|
||||
header.AdditionalFlags = (OS2Flag)data.ReadByte(ref offset);
|
||||
header.ReturnThunkOffset = data.ReadUInt16(ref offset);
|
||||
header.SegmentReferenceThunkOffset = data.ReadUInt16(ref offset);
|
||||
header.MinCodeSwapAreaSize = data.ReadUInt16(ref offset);
|
||||
header.WindowsSDKRevision = data.ReadByte(ref offset);
|
||||
header.WindowsSDKVersion = data.ReadByte(ref offset);
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a byte array into a segment table
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array to parse</param>
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <param name="count">Number of segment table entries to read</param>
|
||||
/// <returns>Filled segment table on success, null on error</returns>
|
||||
private static SegmentTableEntry[] ParseSegmentTable(byte[] data, int offset, int count)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var segmentTable = new SegmentTableEntry[count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var entry = new SegmentTableEntry();
|
||||
entry.Offset = data.ReadUInt16(ref offset);
|
||||
entry.Length = data.ReadUInt16(ref offset);
|
||||
entry.FlagWord = (SegmentTableEntryFlag)data.ReadUInt16(ref offset);
|
||||
entry.MinimumAllocationSize = data.ReadUInt16(ref offset);
|
||||
segmentTable[i] = entry;
|
||||
}
|
||||
|
||||
return segmentTable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a byte array into a resource table
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array to parse</param>
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <param name="count">Number of resource table entries to read</param>
|
||||
/// <returns>Filled resource table on success, null on error</returns>
|
||||
private static ResourceTable ParseResourceTable(byte[] data, int offset, int count)
|
||||
{
|
||||
int initialOffset = offset;
|
||||
|
||||
// TODO: Use marshalling here instead of building
|
||||
var resourceTable = new ResourceTable();
|
||||
|
||||
resourceTable.AlignmentShiftCount = data.ReadUInt16(ref offset);
|
||||
resourceTable.ResourceTypes = new ResourceTypeInformationEntry[count];
|
||||
for (int i = 0; i < resourceTable.ResourceTypes.Length; i++)
|
||||
{
|
||||
var entry = new ResourceTypeInformationEntry();
|
||||
entry.TypeID = data.ReadUInt16(ref offset);
|
||||
entry.ResourceCount = data.ReadUInt16(ref offset);
|
||||
entry.Reserved = data.ReadUInt32(ref offset);
|
||||
entry.Resources = new ResourceTypeResourceEntry[entry.ResourceCount];
|
||||
for (int j = 0; j < entry.ResourceCount; j++)
|
||||
{
|
||||
// TODO: Should we read and store the resource data?
|
||||
var resource = new ResourceTypeResourceEntry();
|
||||
resource.Offset = data.ReadUInt16(ref offset);
|
||||
resource.Length = data.ReadUInt16(ref offset);
|
||||
resource.FlagWord = (ResourceTypeResourceFlag)data.ReadUInt16(ref offset);
|
||||
resource.ResourceID = data.ReadUInt16(ref offset);
|
||||
resource.Reserved = data.ReadUInt32(ref offset);
|
||||
entry.Resources[j] = resource;
|
||||
}
|
||||
resourceTable.ResourceTypes[i] = entry;
|
||||
}
|
||||
|
||||
// Get the full list of unique string offsets
|
||||
var stringOffsets = resourceTable.ResourceTypes
|
||||
.Where(rt => rt.IsIntegerType() == false)
|
||||
.Select(rt => rt.TypeID)
|
||||
.Union(resourceTable.ResourceTypes
|
||||
.SelectMany(rt => rt.Resources)
|
||||
.Where(r => r.IsIntegerType() == false)
|
||||
.Select(r => r.ResourceID))
|
||||
.Distinct()
|
||||
.OrderBy(o => o)
|
||||
.ToList();
|
||||
|
||||
// Populate the type and name string dictionary
|
||||
resourceTable.TypeAndNameStrings = new Dictionary<ushort, ResourceTypeAndNameString>();
|
||||
for (int i = 0; i < stringOffsets.Count; i++)
|
||||
{
|
||||
int stringOffset = stringOffsets[i] + initialOffset;
|
||||
var str = new ResourceTypeAndNameString();
|
||||
str.Length = data.ReadByte(ref stringOffset);
|
||||
str.Text = data.ReadBytes(ref stringOffset, str.Length);
|
||||
resourceTable.TypeAndNameStrings[stringOffsets[i]] = str;
|
||||
}
|
||||
|
||||
return resourceTable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a byte array into a resident-name table
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array to parse</param>
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <param name="endOffset">First address not part of the resident-name table</param>
|
||||
/// <returns>Filled resident-name table on success, null on error</returns>
|
||||
private static ResidentNameTableEntry[] ParseResidentNameTable(byte[] data, int offset, int endOffset)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var residentNameTable = new List<ResidentNameTableEntry>();
|
||||
|
||||
while (offset < endOffset)
|
||||
{
|
||||
var entry = new ResidentNameTableEntry();
|
||||
entry.Length = data.ReadByte(ref offset);
|
||||
entry.NameString = data.ReadBytes(ref offset, entry.Length);
|
||||
entry.OrdinalNumber = data.ReadUInt16(ref offset);
|
||||
residentNameTable.Add(entry);
|
||||
}
|
||||
|
||||
return residentNameTable.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a byte array into a module-reference table
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array to parse</param>
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <param name="count">Number of module-reference table entries to read</param>
|
||||
/// <returns>Filled module-reference table on success, null on error</returns>
|
||||
private static ModuleReferenceTableEntry[] ParseModuleReferenceTable(byte[] data, int offset, int count)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var moduleReferenceTable = new ModuleReferenceTableEntry[count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var entry = new ModuleReferenceTableEntry();
|
||||
entry.Offset = data.ReadUInt16(ref offset);
|
||||
moduleReferenceTable[i] = entry;
|
||||
}
|
||||
|
||||
return moduleReferenceTable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a byte array into an imported-name table
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array to parse</param>
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <param name="endOffset">First address not part of the imported-name table</param>
|
||||
/// <returns>Filled imported-name table on success, null on error</returns>
|
||||
private static Dictionary<ushort, ImportedNameTableEntry> ParseImportedNameTable(byte[] data, int offset, int endOffset)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var importedNameTable = new Dictionary<ushort, ImportedNameTableEntry>();
|
||||
|
||||
while (offset < endOffset)
|
||||
{
|
||||
ushort currentOffset = (ushort)offset;
|
||||
var entry = new ImportedNameTableEntry();
|
||||
entry.Length = data.ReadByte(ref offset);
|
||||
entry.NameString = data.ReadBytes(ref offset, entry.Length);
|
||||
importedNameTable[currentOffset] = entry;
|
||||
}
|
||||
|
||||
return importedNameTable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a byte array into an entry table
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array to parse</param>
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <param name="endOffset">First address not part of the entry table</param>
|
||||
/// <returns>Filled entry table on success, null on error</returns>
|
||||
private static EntryTableBundle[] ParseEntryTable(byte[] data, int offset, int endOffset)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var entryTable = new List<EntryTableBundle>();
|
||||
|
||||
while (offset < endOffset)
|
||||
{
|
||||
var entry = new EntryTableBundle();
|
||||
entry.EntryCount = data.ReadByte(ref offset);
|
||||
entry.SegmentIndicator = data.ReadByte(ref offset);
|
||||
switch (entry.GetEntryType())
|
||||
{
|
||||
case SegmentEntryType.Unused:
|
||||
break;
|
||||
|
||||
case SegmentEntryType.FixedSegment:
|
||||
entry.FixedFlagWord = (FixedSegmentEntryFlag)data.ReadByte(ref offset);
|
||||
entry.FixedOffset = data.ReadUInt16(ref offset);
|
||||
break;
|
||||
|
||||
case SegmentEntryType.MoveableSegment:
|
||||
entry.MoveableFlagWord = (MoveableSegmentEntryFlag)data.ReadByte(ref offset);
|
||||
entry.MoveableReserved = data.ReadUInt16(ref offset);
|
||||
entry.MoveableSegmentNumber = data.ReadByte(ref offset);
|
||||
entry.MoveableOffset = data.ReadUInt16(ref offset);
|
||||
break;
|
||||
}
|
||||
entryTable.Add(entry);
|
||||
}
|
||||
|
||||
return entryTable.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a byte array into a nonresident-name table
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array to parse</param>
|
||||
/// <param name="offset">Offset into the byte array</param>
|
||||
/// <param name="endOffset">First address not part of the nonresident-name table</param>
|
||||
/// <returns>Filled nonresident-name table on success, null on error</returns>
|
||||
private static NonResidentNameTableEntry[] ParseNonResidentNameTable(byte[] data, int offset, int endOffset)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var residentNameTable = new List<NonResidentNameTableEntry>();
|
||||
|
||||
while (offset < endOffset)
|
||||
{
|
||||
var entry = new NonResidentNameTableEntry();
|
||||
entry.Length = data.ReadByte(ref offset);
|
||||
entry.NameString = data.ReadBytes(ref offset, entry.Length);
|
||||
entry.OrdinalNumber = data.ReadUInt16(ref offset);
|
||||
residentNameTable.Add(entry);
|
||||
}
|
||||
|
||||
return residentNameTable.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Stream Data
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a New Executable
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled executable on success, null on error</returns>
|
||||
public static Executable ParseExecutable(Stream data)
|
||||
{
|
||||
// If the data is invalid
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
// If the offset is out of bounds
|
||||
if (data.Position < 0 || data.Position >= data.Length)
|
||||
return null;
|
||||
|
||||
// Cache the current offset
|
||||
int initialOffset = (int)data.Position;
|
||||
|
||||
// Create a new executable to fill
|
||||
var executable = new Executable();
|
||||
|
||||
#region MS-DOS Stub
|
||||
|
||||
// Parse the MS-DOS stub
|
||||
var stub = MSDOS.ParseExecutable(data);
|
||||
if (stub?.Header == null || stub.Header.NewExeHeaderAddr == 0)
|
||||
return null;
|
||||
|
||||
// Set the MS-DOS stub
|
||||
executable.Stub = stub;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Executable Header
|
||||
|
||||
// Try to parse the executable header
|
||||
data.Seek(initialOffset + stub.Header.NewExeHeaderAddr, SeekOrigin.Begin);
|
||||
var executableHeader = ParseExecutableHeader(data);
|
||||
if (executableHeader == null)
|
||||
return null;
|
||||
|
||||
// Set the executable header
|
||||
executable.Header = executableHeader;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Segment Table
|
||||
|
||||
// If the offset for the segment table doesn't exist
|
||||
int tableAddress = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.SegmentTableOffset;
|
||||
if (tableAddress >= data.Length)
|
||||
return executable;
|
||||
|
||||
// Try to parse the segment table
|
||||
data.Seek(tableAddress, SeekOrigin.Begin);
|
||||
var segmentTable = ParseSegmentTable(data, executableHeader.FileSegmentCount);
|
||||
if (segmentTable == null)
|
||||
return null;
|
||||
|
||||
// Set the segment table
|
||||
executable.SegmentTable = segmentTable;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Resource Table
|
||||
|
||||
// If the offset for the segment table doesn't exist
|
||||
tableAddress = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.SegmentTableOffset;
|
||||
if (tableAddress >= data.Length)
|
||||
return executable;
|
||||
|
||||
// Try to parse the resource table
|
||||
data.Seek(tableAddress, SeekOrigin.Begin);
|
||||
var resourceTable = ParseResourceTable(data, executableHeader.ResourceEntriesCount);
|
||||
if (resourceTable == null)
|
||||
return null;
|
||||
|
||||
// Set the resource table
|
||||
executable.ResourceTable = resourceTable;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Resident-Name Table
|
||||
|
||||
// If the offset for the resident-name table doesn't exist
|
||||
tableAddress = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.ResidentNameTableOffset;
|
||||
int endOffset = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.ModuleReferenceTableOffset;
|
||||
if (tableAddress >= data.Length)
|
||||
return executable;
|
||||
|
||||
// Try to parse the resident-name table
|
||||
data.Seek(tableAddress, SeekOrigin.Begin);
|
||||
var residentNameTable = ParseResidentNameTable(data, endOffset);
|
||||
if (residentNameTable == null)
|
||||
return null;
|
||||
|
||||
// Set the resident-name table
|
||||
executable.ResidentNameTable = residentNameTable;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Module-Reference Table
|
||||
|
||||
// If the offset for the module-reference table doesn't exist
|
||||
tableAddress = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.ModuleReferenceTableOffset;
|
||||
if (tableAddress >= data.Length)
|
||||
return executable;
|
||||
|
||||
// Try to parse the module-reference table
|
||||
data.Seek(tableAddress, SeekOrigin.Begin);
|
||||
var moduleReferenceTable = ParseModuleReferenceTable(data, executableHeader.ModuleReferenceTableSize);
|
||||
if (moduleReferenceTable == null)
|
||||
return null;
|
||||
|
||||
// Set the module-reference table
|
||||
executable.ModuleReferenceTable = moduleReferenceTable;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imported-Name Table
|
||||
|
||||
// If the offset for the imported-name table doesn't exist
|
||||
tableAddress = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.ImportedNamesTableOffset;
|
||||
endOffset = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.EntryTableOffset;
|
||||
if (tableAddress >= data.Length)
|
||||
return executable;
|
||||
|
||||
// Try to parse the imported-name table
|
||||
data.Seek(tableAddress, SeekOrigin.Begin);
|
||||
var importedNameTable = ParseImportedNameTable(data, endOffset);
|
||||
if (importedNameTable == null)
|
||||
return null;
|
||||
|
||||
// Set the imported-name table
|
||||
executable.ImportedNameTable = importedNameTable;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Entry Table
|
||||
|
||||
// If the offset for the imported-name table doesn't exist
|
||||
tableAddress = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.EntryTableOffset;
|
||||
endOffset = initialOffset
|
||||
+ (int)stub.Header.NewExeHeaderAddr
|
||||
+ executableHeader.EntryTableOffset
|
||||
+ executableHeader.EntryTableSize;
|
||||
if (tableAddress >= data.Length)
|
||||
return executable;
|
||||
|
||||
// Try to parse the imported-name table
|
||||
data.Seek(tableAddress, SeekOrigin.Begin);
|
||||
var entryTable = ParseEntryTable(data, endOffset);
|
||||
if (entryTable == null)
|
||||
return null;
|
||||
|
||||
// Set the entry table
|
||||
executable.EntryTable = entryTable;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Nonresident-Name Table
|
||||
|
||||
// If the offset for the nonresident-name table doesn't exist
|
||||
tableAddress = initialOffset
|
||||
+ (int)executableHeader.NonResidentNamesTableOffset;
|
||||
endOffset = initialOffset
|
||||
+ (int)executableHeader.NonResidentNamesTableOffset
|
||||
+ executableHeader.NonResidentNameTableSize;
|
||||
if (tableAddress >= data.Length)
|
||||
return executable;
|
||||
|
||||
// Try to parse the nonresident-name table
|
||||
data.Seek(tableAddress, SeekOrigin.Begin);
|
||||
var nonResidentNameTable = ParseNonResidentNameTable(data, endOffset);
|
||||
if (nonResidentNameTable == null)
|
||||
return null;
|
||||
|
||||
// Set the nonresident-name table
|
||||
executable.NonResidentNameTable = nonResidentNameTable;
|
||||
|
||||
#endregion
|
||||
|
||||
return executable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a New Executable header
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled executable header on success, null on error</returns>
|
||||
private static ExecutableHeader ParseExecutableHeader(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var header = new ExecutableHeader();
|
||||
|
||||
header.Magic = new byte[2];
|
||||
for (int i = 0; i < header.Magic.Length; i++)
|
||||
{
|
||||
header.Magic[i] = data.ReadByteValue();
|
||||
}
|
||||
if (header.Magic[0] != 'N' || header.Magic[1] != 'E')
|
||||
return null;
|
||||
|
||||
header.LinkerVersion = data.ReadByteValue();
|
||||
header.LinkerRevision = data.ReadByteValue();
|
||||
header.EntryTableOffset = data.ReadUInt16();
|
||||
header.EntryTableSize = data.ReadUInt16();
|
||||
header.CrcChecksum = data.ReadUInt32();
|
||||
header.FlagWord = (HeaderFlag)data.ReadUInt16();
|
||||
header.AutomaticDataSegmentNumber = data.ReadUInt16();
|
||||
header.InitialHeapAlloc = data.ReadUInt16();
|
||||
header.InitialStackAlloc = data.ReadUInt16();
|
||||
header.InitialCSIPSetting = data.ReadUInt32();
|
||||
header.InitialSSSPSetting = data.ReadUInt32();
|
||||
header.FileSegmentCount = data.ReadUInt16();
|
||||
header.ModuleReferenceTableSize = data.ReadUInt16();
|
||||
header.NonResidentNameTableSize = data.ReadUInt16();
|
||||
header.SegmentTableOffset = data.ReadUInt16();
|
||||
header.ResourceTableOffset = data.ReadUInt16();
|
||||
header.ResidentNameTableOffset = data.ReadUInt16();
|
||||
header.ModuleReferenceTableOffset = data.ReadUInt16();
|
||||
header.ImportedNamesTableOffset = data.ReadUInt16();
|
||||
header.NonResidentNamesTableOffset = data.ReadUInt32();
|
||||
header.MovableEntriesCount = data.ReadUInt16();
|
||||
header.SegmentAlignmentShiftCount = data.ReadUInt16();
|
||||
header.ResourceEntriesCount = data.ReadUInt16();
|
||||
header.TargetOperatingSystem = (OperatingSystem)data.ReadByteValue();
|
||||
header.AdditionalFlags = (OS2Flag)data.ReadByteValue();
|
||||
header.ReturnThunkOffset = data.ReadUInt16();
|
||||
header.SegmentReferenceThunkOffset = data.ReadUInt16();
|
||||
header.MinCodeSwapAreaSize = data.ReadUInt16();
|
||||
header.WindowsSDKRevision = data.ReadByteValue();
|
||||
header.WindowsSDKVersion = data.ReadByteValue();
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a segment table
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <param name="count">Number of segment table entries to read</param>
|
||||
/// <returns>Filled segment table on success, null on error</returns>
|
||||
private static SegmentTableEntry[] ParseSegmentTable(Stream data, int count)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var segmentTable = new SegmentTableEntry[count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var entry = new SegmentTableEntry();
|
||||
entry.Offset = data.ReadUInt16();
|
||||
entry.Length = data.ReadUInt16();
|
||||
entry.FlagWord = (SegmentTableEntryFlag)data.ReadUInt16();
|
||||
entry.MinimumAllocationSize = data.ReadUInt16();
|
||||
segmentTable[i] = entry;
|
||||
}
|
||||
|
||||
return segmentTable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a resource table
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <param name="count">Number of resource table entries to read</param>
|
||||
/// <returns>Filled resource table on success, null on error</returns>
|
||||
private static ResourceTable ParseResourceTable(Stream data, int count)
|
||||
{
|
||||
long initialOffset = data.Position;
|
||||
|
||||
// TODO: Use marshalling here instead of building
|
||||
var resourceTable = new ResourceTable();
|
||||
|
||||
resourceTable.AlignmentShiftCount = data.ReadUInt16();
|
||||
resourceTable.ResourceTypes = new ResourceTypeInformationEntry[count];
|
||||
for (int i = 0; i < resourceTable.ResourceTypes.Length; i++)
|
||||
{
|
||||
var entry = new ResourceTypeInformationEntry();
|
||||
entry.TypeID = data.ReadUInt16();
|
||||
entry.ResourceCount = data.ReadUInt16();
|
||||
entry.Reserved = data.ReadUInt32();
|
||||
entry.Resources = new ResourceTypeResourceEntry[entry.ResourceCount];
|
||||
for (int j = 0; j < entry.ResourceCount; j++)
|
||||
{
|
||||
// TODO: Should we read and store the resource data?
|
||||
var resource = new ResourceTypeResourceEntry();
|
||||
resource.Offset = data.ReadUInt16();
|
||||
resource.Length = data.ReadUInt16();
|
||||
resource.FlagWord = (ResourceTypeResourceFlag)data.ReadUInt16();
|
||||
resource.ResourceID = data.ReadUInt16();
|
||||
resource.Reserved = data.ReadUInt32();
|
||||
entry.Resources[j] = resource;
|
||||
}
|
||||
resourceTable.ResourceTypes[i] = entry;
|
||||
}
|
||||
|
||||
// Get the full list of unique string offsets
|
||||
var stringOffsets = resourceTable.ResourceTypes
|
||||
.Where(rt => rt.IsIntegerType() == false)
|
||||
.Select(rt => rt.TypeID)
|
||||
.Union(resourceTable.ResourceTypes
|
||||
.SelectMany(rt => rt.Resources)
|
||||
.Where(r => r.IsIntegerType() == false)
|
||||
.Select(r => r.ResourceID))
|
||||
.Distinct()
|
||||
.OrderBy(o => o)
|
||||
.ToList();
|
||||
|
||||
// Populate the type and name string dictionary
|
||||
resourceTable.TypeAndNameStrings = new Dictionary<ushort, ResourceTypeAndNameString>();
|
||||
for (int i = 0; i < stringOffsets.Count; i++)
|
||||
{
|
||||
int stringOffset = (int)(stringOffsets[i] + initialOffset);
|
||||
data.Seek(stringOffset, SeekOrigin.Begin);
|
||||
var str = new ResourceTypeAndNameString();
|
||||
str.Length = data.ReadByteValue();
|
||||
str.Text = data.ReadBytes(str.Length);
|
||||
resourceTable.TypeAndNameStrings[stringOffsets[i]] = str;
|
||||
}
|
||||
|
||||
return resourceTable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a resident-name table
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <param name="endOffset">First address not part of the resident-name table</param>
|
||||
/// <returns>Filled resident-name table on success, null on error</returns>
|
||||
private static ResidentNameTableEntry[] ParseResidentNameTable(Stream data, int endOffset)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var residentNameTable = new List<ResidentNameTableEntry>();
|
||||
|
||||
while (data.Position < endOffset)
|
||||
{
|
||||
var entry = new ResidentNameTableEntry();
|
||||
entry.Length = data.ReadByteValue();
|
||||
entry.NameString = data.ReadBytes(entry.Length);
|
||||
entry.OrdinalNumber = data.ReadUInt16();
|
||||
residentNameTable.Add(entry);
|
||||
}
|
||||
|
||||
return residentNameTable.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a module-reference table
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <param name="count">Number of module-reference table entries to read</param>
|
||||
/// <returns>Filled module-reference table on success, null on error</returns>
|
||||
private static ModuleReferenceTableEntry[] ParseModuleReferenceTable(Stream data, int count)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var moduleReferenceTable = new ModuleReferenceTableEntry[count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var entry = new ModuleReferenceTableEntry();
|
||||
entry.Offset = data.ReadUInt16();
|
||||
moduleReferenceTable[i] = entry;
|
||||
}
|
||||
|
||||
return moduleReferenceTable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into an imported-name table
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <param name="endOffset">First address not part of the imported-name table</param>
|
||||
/// <returns>Filled imported-name table on success, null on error</returns>
|
||||
private static Dictionary<ushort, ImportedNameTableEntry> ParseImportedNameTable(Stream data, int endOffset)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var importedNameTable = new Dictionary<ushort, ImportedNameTableEntry>();
|
||||
|
||||
while (data.Position < endOffset)
|
||||
{
|
||||
ushort currentOffset = (ushort)data.Position;
|
||||
var entry = new ImportedNameTableEntry();
|
||||
entry.Length = data.ReadByteValue();
|
||||
entry.NameString = data.ReadBytes(entry.Length);
|
||||
importedNameTable[currentOffset] = entry;
|
||||
}
|
||||
|
||||
return importedNameTable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into an entry table
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <param name="endOffset">First address not part of the entry table</param>
|
||||
/// <returns>Filled entry table on success, null on error</returns>
|
||||
private static EntryTableBundle[] ParseEntryTable(Stream data, int endOffset)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var entryTable = new List<EntryTableBundle>();
|
||||
|
||||
while (data.Position < endOffset)
|
||||
{
|
||||
var entry = new EntryTableBundle();
|
||||
entry.EntryCount = data.ReadByteValue();
|
||||
entry.SegmentIndicator = data.ReadByteValue();
|
||||
switch (entry.GetEntryType())
|
||||
{
|
||||
case SegmentEntryType.Unused:
|
||||
break;
|
||||
|
||||
case SegmentEntryType.FixedSegment:
|
||||
entry.FixedFlagWord = (FixedSegmentEntryFlag)data.ReadByteValue();
|
||||
entry.FixedOffset = data.ReadUInt16();
|
||||
break;
|
||||
|
||||
case SegmentEntryType.MoveableSegment:
|
||||
entry.MoveableFlagWord = (MoveableSegmentEntryFlag)data.ReadByteValue();
|
||||
entry.MoveableReserved = data.ReadUInt16();
|
||||
entry.MoveableSegmentNumber = data.ReadByteValue();
|
||||
entry.MoveableOffset = data.ReadUInt16();
|
||||
break;
|
||||
}
|
||||
entryTable.Add(entry);
|
||||
}
|
||||
|
||||
return entryTable.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a nonresident-name table
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <param name="endOffset">First address not part of the nonresident-name table</param>
|
||||
/// <returns>Filled nonresident-name table on success, null on error</returns>
|
||||
private static NonResidentNameTableEntry[] ParseNonResidentNameTable(Stream data, int endOffset)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var residentNameTable = new List<NonResidentNameTableEntry>();
|
||||
|
||||
while (data.Position < endOffset)
|
||||
{
|
||||
var entry = new NonResidentNameTableEntry();
|
||||
entry.Length = data.ReadByteValue();
|
||||
entry.NameString = data.ReadBytes(entry.Length);
|
||||
entry.OrdinalNumber = data.ReadUInt16();
|
||||
residentNameTable.Add(entry);
|
||||
}
|
||||
|
||||
return residentNameTable.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
25
BurnOutSharp.Builder/ObjectIdentifier.ASN1.cs
Normal file
25
BurnOutSharp.Builder/ObjectIdentifier.ASN1.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace BurnOutSharp.Builder
|
||||
{
|
||||
#pragma warning disable IDE0011
|
||||
|
||||
/// <summary>
|
||||
/// Methods related to Object Identifiers (OID) and ASN.1 notation
|
||||
/// </summary>
|
||||
public static partial class ObjectIdentifier
|
||||
{
|
||||
/// <summary>
|
||||
/// Parse an OID in separated-value notation into ASN.1 notation
|
||||
/// </summary>
|
||||
/// <param name="values">List of values to check against</param>
|
||||
/// <param name="index">Current index into the list</param>
|
||||
/// <returns>ASN.1 formatted string, if possible</returns>
|
||||
/// <remarks>
|
||||
public static string ParseOIDToASN1Notation(ulong[] values, ref int index)
|
||||
{
|
||||
// TODO: Once the modified OID-IRI formatting is done, make an ASN.1 notation version
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore IDE0011
|
||||
}
|
||||
17172
BurnOutSharp.Builder/ObjectIdentifier.ModifiedOIDIRI.cs
Normal file
17172
BurnOutSharp.Builder/ObjectIdentifier.ModifiedOIDIRI.cs
Normal file
File diff suppressed because it is too large
Load Diff
870
BurnOutSharp.Builder/ObjectIdentifier.OIDIRI.cs
Normal file
870
BurnOutSharp.Builder/ObjectIdentifier.OIDIRI.cs
Normal file
@@ -0,0 +1,870 @@
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BurnOutSharp.Builder
|
||||
{
|
||||
#pragma warning disable IDE0011
|
||||
|
||||
/// <summary>
|
||||
/// Methods related to Object Identifiers (OID) and OID-IRI formatting
|
||||
/// </summary>
|
||||
public static partial class ObjectIdentifier
|
||||
{
|
||||
/// <summary>
|
||||
/// Parse an OID in separated-value notation into OID-IRI notation
|
||||
/// </summary>
|
||||
/// <param name="values">List of values to check against</param>
|
||||
/// <param name="index">Current index into the list</param>
|
||||
/// <returns>OID-IRI formatted string, if possible</returns>
|
||||
/// <see href="http://www.oid-info.com/index.htm"/>
|
||||
public static string ParseOIDToOIDIRINotation(ulong[] values)
|
||||
{
|
||||
// If we have an invalid set of values, we can't do anything
|
||||
if (values == null || values.Length == 0)
|
||||
return null;
|
||||
|
||||
// Set the initial index
|
||||
int index = 0;
|
||||
|
||||
// Get a string builder for the path
|
||||
var nameBuilder = new StringBuilder();
|
||||
|
||||
// Try to parse the standard value
|
||||
string standard = ParseOIDToOIDIRINotation(values, ref index);
|
||||
if (standard == null)
|
||||
return null;
|
||||
|
||||
// Add the standard value to the output
|
||||
nameBuilder.Append(standard);
|
||||
|
||||
// If we have no more items
|
||||
if (index == values.Length)
|
||||
return nameBuilder.ToString();
|
||||
|
||||
// Add trailing items as just values
|
||||
nameBuilder.Append("/");
|
||||
nameBuilder.Append(string.Join("/", values.Skip(index)));
|
||||
|
||||
// Create and return the string
|
||||
return nameBuilder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse an OID in separated-value notation into OID-IRI notation
|
||||
/// </summary>
|
||||
/// <param name="values">List of values to check against</param>
|
||||
/// <param name="index">Current index into the list</param>
|
||||
/// <returns>OID-IRI formatted string, if possible</returns>
|
||||
/// <see href="http://www.oid-info.com/index.htm"/>
|
||||
private static string ParseOIDToOIDIRINotation(ulong[] values, ref int index)
|
||||
{
|
||||
// If we have an invalid set of values, we can't do anything
|
||||
if (values == null || values.Length == 0)
|
||||
return null;
|
||||
|
||||
// If we have an invalid index, we can't do anything
|
||||
if (index < 0 || index >= values.Length)
|
||||
return null;
|
||||
|
||||
#region Start
|
||||
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_0;
|
||||
case 1: goto oid_1;
|
||||
case 2: goto oid_2;
|
||||
default: return $"/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// itu-t, ccitt, itu-r
|
||||
#region 0.*
|
||||
|
||||
oid_0:
|
||||
|
||||
if (index == values.Length) return "/ITU-T";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_0_0;
|
||||
case 2: return "/ITU-T/Administration";
|
||||
case 3: return "/ITU-T/Network-Operator";
|
||||
case 4: return "/ITU-T/Identified-Organization";
|
||||
case 5: return "/ITU-R/R-Recommendation";
|
||||
case 9: return "/ITU-T/Data";
|
||||
default: return $"/ITU-T/{values[index - 1]}";
|
||||
};
|
||||
|
||||
// recommendation
|
||||
#region 0.0.*
|
||||
|
||||
oid_0_0:
|
||||
|
||||
if (index == values.Length) return "/ITU-T/Recommendation";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/ITU-T/Recommendation/A";
|
||||
case 2: return "/ITU-T/Recommendation/B";
|
||||
case 3: return "/ITU-T/Recommendation/C";
|
||||
case 4: return "/ITU-T/Recommendation/D";
|
||||
case 5: return "/ITU-T/Recommendation/E";
|
||||
case 6: return "/ITU-T/Recommendation/F";
|
||||
case 7: return "/ITU-T/Recommendation/G";
|
||||
case 8: return "/ITU-T/Recommendation/H";
|
||||
case 9: return "/ITU-T/Recommendation/I";
|
||||
case 10: return "/ITU-T/Recommendation/J";
|
||||
case 11: return "/ITU-T/Recommendation/K";
|
||||
case 12: return "/ITU-T/Recommendation/L";
|
||||
case 13: return "/ITU-T/Recommendation/M";
|
||||
case 14: return "/ITU-T/Recommendation/N";
|
||||
case 15: return "/ITU-T/Recommendation/O";
|
||||
case 16: return "/ITU-T/Recommendation/P";
|
||||
case 17: return "/ITU-T/Recommendation/Q";
|
||||
case 18: return "/ITU-T/Recommendation/R";
|
||||
case 19: return "/ITU-T/Recommendation/S";
|
||||
case 20: return "/ITU-T/Recommendation/T";
|
||||
case 21: return "/ITU-T/Recommendation/U";
|
||||
case 22: return "/ITU-T/Recommendation/V";
|
||||
case 24: return "/ITU-T/Recommendation/X";
|
||||
case 25: return "/ITU-T/Recommendation/Y";
|
||||
case 26: return "/ITU-T/Recommendation/Z";
|
||||
default: return $"/ITU-T/Recommendation/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// iso
|
||||
#region 1.*
|
||||
|
||||
oid_1:
|
||||
|
||||
if (index == values.Length) return "/ISO";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: return "/ISO/Standard";
|
||||
case 1: return "/ISO/Registration-Authority";
|
||||
case 2: goto oid_1_2;
|
||||
case 3: return "/ISO/Identified-Organization";
|
||||
default: return $"/ISO/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// member-body
|
||||
#region 1.2.*
|
||||
|
||||
oid_1_2:
|
||||
|
||||
if (index == values.Length) return "/ISO/Member-Body";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 36: return "/ISO/Member-Body/AU";
|
||||
case 40: return "/ISO/Member-Body/AT";
|
||||
case 56: return "/ISO/Member-Body/BE";
|
||||
case 124: return "/ISO/Member-Body/CA";
|
||||
case 156: return "/ISO/Member-Body/CN";
|
||||
case 203: return "/ISO/Member-Body/CZ";
|
||||
case 208: return "/ISO/Member-Body/DK";
|
||||
case 246: return "/ISO/Member-Body/FI";
|
||||
case 250: return "/ISO/Member-Body/FR";
|
||||
case 276: return "/ISO/Member-Body/DE";
|
||||
case 300: return "/ISO/Member-Body/GR";
|
||||
case 344: return "/ISO/Member-Body/HK";
|
||||
case 372: return "/ISO/Member-Body/IE";
|
||||
case 392: return "/ISO/Member-Body/JP";
|
||||
case 398: return "/ISO/Member-Body/KZ";
|
||||
case 410: return "/ISO/Member-Body/KR";
|
||||
case 498: return "/ISO/Member-Body/MD";
|
||||
case 528: return "/ISO/Member-Body/NL";
|
||||
case 566: return "/ISO/Member-Body/NG";
|
||||
case 578: return "/ISO/Member-Body/NO";
|
||||
case 616: return "/ISO/Member-Body/PL";
|
||||
case 643: return "/ISO/Member-Body/RU";
|
||||
case 702: return "/ISO/Member-Body/SG";
|
||||
case 752: return "/ISO/Member-Body/SE";
|
||||
case 804: return "/ISO/Member-Body/UA";
|
||||
case 826: return "/ISO/Member-Body/GB";
|
||||
case 840: return "/ISO/Member-Body/US";
|
||||
default: return $"/ISO/Member-Body/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// joint-iso-itu-t, joint-iso-ccitt
|
||||
#region 2.*
|
||||
|
||||
oid_2:
|
||||
|
||||
if (index == values.Length) return "/Joint-ISO-ITU-T";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/ASN.1";
|
||||
case 16: goto oid_2_16;
|
||||
case 17: return "/Joint-ISO-ITU-T/Registration-Procedures";
|
||||
case 23: return "/Joint-ISO-ITU-T/International-Organizations";
|
||||
case 25: goto oid_2_25;
|
||||
case 27: return "/Tag-Based";
|
||||
case 28: return "/Joint-ISO-ITU-T/ITS";
|
||||
case 41: return "/BIP";
|
||||
case 42: goto oid_2_42;
|
||||
case 48: goto oid_2_48;
|
||||
case 49: goto oid_2_49;
|
||||
case 50: return "/OIDResolutionSystem";
|
||||
case 51: return "/GS1";
|
||||
case 52: return "/Joint-ISO-ITU-T/UAV";
|
||||
case 999: return "/Joint-ISO-ITU-T/Example";
|
||||
default: return $"/Joint-ISO-ITU-T/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// country
|
||||
#region 2.16.*
|
||||
|
||||
oid_2_16:
|
||||
|
||||
if (index == values.Length) return "/Country";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 4: return "/Country/AF";
|
||||
case 8: return "/Country/AL";
|
||||
case 12: return "/Country/DZ";
|
||||
case 20: return "/Country/AD";
|
||||
case 24: return "/Country/AO";
|
||||
case 28: return "/Country/AG";
|
||||
case 31: return "/Country/AZ";
|
||||
case 32: return "/Country/AR";
|
||||
case 36: return "/Country/AU";
|
||||
case 40: return "/Country/AT";
|
||||
case 44: return "/Country/BS";
|
||||
case 48: return "/Country/BH";
|
||||
case 50: return "/Country/BD";
|
||||
case 51: return "/Country/AM";
|
||||
case 52: return "/Country/BB";
|
||||
case 56: return "/Country/BE";
|
||||
case 60: return "/Country/BM";
|
||||
case 64: return "/Country/BT";
|
||||
case 68: return "/Country/BO";
|
||||
case 70: return "/Country/BA";
|
||||
case 72: return "/Country/BW";
|
||||
case 76: return "/Country/BR";
|
||||
case 84: return "/Country/BZ";
|
||||
case 90: return "/Country/SB";
|
||||
case 96: return "/Country/BN";
|
||||
case 100: return "/Country/BG";
|
||||
case 104: return "/Country/MM";
|
||||
case 108: return "/Country/BI";
|
||||
case 112: return "/Country/BY";
|
||||
case 116: return "/Country/KH";
|
||||
case 120: return "/Country/CM";
|
||||
case 124: return "/Country/CA";
|
||||
case 132: return "/Country/CV";
|
||||
case 140: return "/Country/CF";
|
||||
case 144: return "/Country/LK";
|
||||
case 148: return "/Country/TD";
|
||||
case 152: return "/Country/CL";
|
||||
case 156: return "/Country/CN";
|
||||
case 158: return "/Country/TW";
|
||||
case 170: return "/Country/CO";
|
||||
case 174: return "/Country/KM";
|
||||
case 178: return "/Country/CG";
|
||||
case 180: return "/Country/CD";
|
||||
case 188: return "/Country/CR";
|
||||
case 191: return "/Country/HR";
|
||||
case 192: return "/Country/CU";
|
||||
case 196: return "/Country/CY";
|
||||
case 203: return "/Country/CZ";
|
||||
case 204: return "/Country/BJ";
|
||||
case 208: return "/Country/DK";
|
||||
case 212: return "/Country/DM";
|
||||
case 214: return "/Country/DO";
|
||||
case 218: return "/Country/EC";
|
||||
case 222: return "/Country/SV";
|
||||
case 226: return "/Country/GQ";
|
||||
case 231: return "/Country/ET";
|
||||
case 232: return "/Country/ER";
|
||||
case 233: return "/Country/EE";
|
||||
case 242: return "/Country/FJ";
|
||||
case 246: return "/Country/FI";
|
||||
case 250: return "/Country/FR";
|
||||
case 262: return "/Country/DJ";
|
||||
case 266: return "/Country/GA";
|
||||
case 268: return "/Country/GE";
|
||||
case 270: return "/Country/GM";
|
||||
case 275: return "/Country/PS";
|
||||
case 276: return "/Country/DE";
|
||||
case 288: return "/Country/GH";
|
||||
case 296: return "/Country/KI";
|
||||
case 300: return "/Country/GR";
|
||||
case 308: return "/Country/GD";
|
||||
case 320: return "/Country/GT";
|
||||
case 324: return "/Country/GN";
|
||||
case 328: return "/Country/GY";
|
||||
case 332: return "/Country/HT";
|
||||
case 336: return "/Country/VA";
|
||||
case 340: return "/Country/HN";
|
||||
case 344: return "/Country/HK";
|
||||
case 348: return "/Country/HU";
|
||||
case 352: return "/Country/IS";
|
||||
case 356: return "/Country/IN";
|
||||
case 360: return "/Country/ID";
|
||||
case 364: return "/Country/IR";
|
||||
case 368: return "/Country/IQ";
|
||||
case 372: return "/Country/IE";
|
||||
case 376: return "/Country/IL";
|
||||
case 380: return "/Country/IT";
|
||||
case 384: return "/Country/CI";
|
||||
case 388: return "/Country/JM";
|
||||
case 392: return "/Country/JP";
|
||||
case 398: return "/Country/KZ";
|
||||
case 400: return "/Country/JO";
|
||||
case 404: return "/Country/KE";
|
||||
case 408: return "/Country/KP";
|
||||
case 410: return "/Country/KR";
|
||||
case 414: return "/Country/KW";
|
||||
case 417: return "/Country/KG";
|
||||
case 418: return "/Country/LA";
|
||||
case 422: return "/Country/LB";
|
||||
case 426: return "/Country/LS";
|
||||
case 428: return "/Country/LV";
|
||||
case 430: return "/Country/LR";
|
||||
case 434: return "/Country/LY";
|
||||
case 438: return "/Country/LI";
|
||||
case 440: return "/Country/LT";
|
||||
case 442: return "/Country/LU";
|
||||
case 450: return "/Country/MG";
|
||||
case 454: return "/Country/MW";
|
||||
case 458: return "/Country/MY";
|
||||
case 462: return "/Country/MV";
|
||||
case 466: return "/Country/ML";
|
||||
case 470: return "/Country/MT";
|
||||
case 478: return "/Country/MR";
|
||||
case 480: return "/Country/MU";
|
||||
case 484: return "/Country/MX";
|
||||
case 492: return "/Country/MC";
|
||||
case 496: return "/Country/MN";
|
||||
case 498: return "/Country/MD";
|
||||
case 499: return "/Country/ME";
|
||||
case 504: return "/Country/MA";
|
||||
case 508: return "/Country/MZ";
|
||||
case 512: return "/Country/OM";
|
||||
case 516: return "/Country/NA";
|
||||
case 520: return "/Country/NR";
|
||||
case 524: return "/Country/NP";
|
||||
case 528: return "/Country/NL";
|
||||
case 530: return "/Country/AN";
|
||||
case 548: return "/Country/VU";
|
||||
case 554: return "/Country/NZ";
|
||||
case 558: return "/Country/NI";
|
||||
case 562: return "/Country/NE";
|
||||
case 566: return "/Country/NG";
|
||||
case 578: return "/Country/NO";
|
||||
case 583: return "/Country/FM";
|
||||
case 584: return "/Country/MH";
|
||||
case 585: return "/Country/PW";
|
||||
case 586: return "/Country/PK";
|
||||
case 591: return "/Country/PA";
|
||||
case 598: return "/Country/PG";
|
||||
case 600: return "/Country/PY";
|
||||
case 604: return "/Country/PE";
|
||||
case 608: return "/Country/PH";
|
||||
case 616: return "/Country/PL";
|
||||
case 620: return "/Country/PT";
|
||||
case 624: return "/Country/GW";
|
||||
case 626: return "/Country/TL";
|
||||
case 634: return "/Country/QA";
|
||||
case 642: return "/Country/RO";
|
||||
case 643: return "/Country/RU";
|
||||
case 646: return "/Country/RW";
|
||||
case 659: return "/Country/KN";
|
||||
case 662: return "/Country/LC";
|
||||
case 670: return "/Country/VC";
|
||||
case 674: return "/Country/SM";
|
||||
case 678: return "/Country/ST";
|
||||
case 682: return "/Country/SA";
|
||||
case 686: return "/Country/SN";
|
||||
case 688: return "/Country/RS";
|
||||
case 690: return "/Country/SC";
|
||||
case 694: return "/Country/SL";
|
||||
case 702: return "/Country/SG";
|
||||
case 703: return "/Country/SK";
|
||||
case 704: return "/Country/VN";
|
||||
case 705: return "/Country/SI";
|
||||
case 706: return "/Country/SO";
|
||||
case 710: return "/Country/ZA";
|
||||
case 716: return "/Country/ZW";
|
||||
case 724: return "/Country/ES";
|
||||
case 728: return "/Country/SS";
|
||||
case 729: return "/Country/SD";
|
||||
case 740: return "/Country/SR";
|
||||
case 748: return "/Country/SZ";
|
||||
case 752: return "/Country/SE";
|
||||
case 756: return "/Country/CH";
|
||||
case 760: return "/Country/SY";
|
||||
case 762: return "/Country/TJ";
|
||||
case 764: return "/Country/TH";
|
||||
case 768: return "/Country/TG";
|
||||
case 776: return "/Country/TO";
|
||||
case 780: return "/Country/TT";
|
||||
case 784: return "/Country/AE";
|
||||
case 788: return "/Country/TN";
|
||||
case 792: return "/Country/TR";
|
||||
case 795: return "/Country/TM";
|
||||
case 798: return "/Country/TV";
|
||||
case 800: return "/Country/UG";
|
||||
case 804: return "/Country/UA";
|
||||
case 807: return "/Country/MK";
|
||||
case 818: return "/Country/EG";
|
||||
case 826: return "/Country/GB";
|
||||
case 834: return "/Country/TZ";
|
||||
case 840: return "/Country/US";
|
||||
case 854: return "/Country/BF";
|
||||
case 858: return "/Country/UY";
|
||||
case 860: return "/Country/UZ";
|
||||
case 862: return "/Country/VE";
|
||||
case 882: return "/Country/WS";
|
||||
case 887: return "/Country/YE";
|
||||
case 894: return "/Country/ZM";
|
||||
default: return $"/Country/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// uuid [TODO: Requires 128-bit values]
|
||||
#region 2.25.*
|
||||
|
||||
oid_2_25:
|
||||
|
||||
if (index == values.Length) return "/Joint-ISO-ITU-T/UUID";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: return "/Joint-ISO-ITU-T/UUID/00000000-0000-0000-0000-000000000000";
|
||||
//case 288786655511405443130567505384701230: return "/Joint-ISO-ITU-T/UUID/00379e48-0a2b-1085-b288-0002a5d5fd2e";
|
||||
//case 987895962269883002155146617097157934: return "/Joint-ISO-ITU-T/UUID/00be4308-0c89-1085-8ea0-0002a5d5fd2e";
|
||||
//case 1858228783942312576083372383319475483: return "/Joint-ISO-ITU-T/UUID/0165e1c0-a655-11e0-95b8-0002a5d5c51b";
|
||||
//case 2474299330026746002885628159579243803: return "/Joint-ISO-ITU-T/UUID/01dc8860-25fb-11da-82b2-0002a5d5c51b";
|
||||
//case 3263645701162998421821186056373271854: return "/Joint-ISO-ITU-T/UUID/02748e28-08c4-1085-b21d-0002a5d5fd2e";
|
||||
//case 3325839809379844461264382260940242222: return "/Joint-ISO-ITU-T/UUID/02808890-0ad8-1085-9bdf-0002a5d5fd2e";
|
||||
// TODO: Left off at http://www.oid-info.com/get/2.25.3664154270495270126161055518190585115
|
||||
default: return $"/Joint-ISO-ITU-T/UUID/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// telebiometrics
|
||||
#region 2.42.*
|
||||
|
||||
oid_2_42:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_2_42_0;
|
||||
case 1: goto oid_2_42_1;
|
||||
case 2: goto oid_2_42_2;
|
||||
case 3: goto oid_2_42_3;
|
||||
default: return $"/Telebiometrics/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// modules
|
||||
#region 2.42.0.*
|
||||
|
||||
oid_2_42_0:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/Modules";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_2_42_0_0;
|
||||
default: return $"/Telebiometrics/Modules/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// main
|
||||
#region 2.42.0.0.*
|
||||
|
||||
oid_2_42_0_0:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/Modules/Main_Module";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/Modules/Main_Module/Version1";
|
||||
default: return $"/Telebiometrics/Modules/Main_Module/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// tmm
|
||||
#region 2.42.1.*
|
||||
|
||||
oid_2_42_1:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/TMM";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_2_42_1_0;
|
||||
case 1: goto oid_2_42_1_1;
|
||||
case 2: goto oid_2_42_1_2;
|
||||
case 3: goto oid_2_42_1_3;
|
||||
case 4: return "/Telebiometrics/TMM/Practitioners";
|
||||
default: return $"/Telebiometrics/TMM/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// modules
|
||||
#region 2.42.1.0.*
|
||||
|
||||
oid_2_42_1_0:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/TMM/Modules";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_2_42_1_0_0;
|
||||
default: return $"/Telebiometrics/TMM/Modules/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// main
|
||||
#region 2.42.1.0.0.*
|
||||
|
||||
oid_2_42_1_0_0:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/TMM/Modules/Main";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: return "/Telebiometrics/TMM/Modules/Main/First_Version";
|
||||
default: return $"/Telebiometrics/TMM/Modules/Main/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// measures, metric
|
||||
#region 2.42.1.1.*
|
||||
|
||||
oid_2_42_1_1:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/TMM/Measures";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: goto oid_2_42_1_1_1;
|
||||
case 2: return "/Telebiometrics/TMM/Measures/Units";
|
||||
case 3: return "/Telebiometrics/TMM/Measures/Symbols";
|
||||
case 4: return "/Telebiometrics/TMM/Measures/Conditions";
|
||||
case 5: goto oid_2_42_1_1_5;
|
||||
default: return $"/Telebiometrics/TMM/Measures/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// quantities
|
||||
#region 2.42.1.1.1.*
|
||||
|
||||
oid_2_42_1_1_1:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/TMM/Measures/Quantities";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/TMM/Measures/Quantities/Physics";
|
||||
case 2: return "/Telebiometrics/TMM/Measures/Quantities/Chemistry";
|
||||
case 3: return "/Telebiometrics/TMM/Measures/Quantities/Biology";
|
||||
case 4: return "/Telebiometrics/TMM/Measures/Quantities/Culturology";
|
||||
case 5: return "/Telebiometrics/TMM/Measures/Quantities/Psychology";
|
||||
default: return $"/Telebiometrics/TMM/Measures/Quantities/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// methods
|
||||
#region 2.42.1.1.5.*
|
||||
|
||||
oid_2_42_1_1_5:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/TMM/Measures/Methods";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/TMM/Measures/Methods/Physics";
|
||||
case 2: return "/Telebiometrics/TMM/Measures/Methods/Chemistry";
|
||||
case 3: return "/Telebiometrics/TMM/Measures/Methods/Biology";
|
||||
case 4: return "/Telebiometrics/TMM/Measures/Methods/Culturology";
|
||||
case 5: return "/Telebiometrics/TMM/Measures/Methods/Psychology";
|
||||
default: return $"/Telebiometrics/TMM/Measures/Methods/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// fields-of-study, scientific
|
||||
#region 2.42.1.2.*
|
||||
|
||||
oid_2_42_1_2:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/TMM/Fields_of_Study";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/TMM/Fields_of_Study/Physics";
|
||||
case 2: return "/Telebiometrics/TMM/Fields_of_Study/Chemistry";
|
||||
case 3: return "/Telebiometrics/TMM/Fields_of_Study/Biology";
|
||||
case 4: return "/Telebiometrics/TMM/Fields_of_Study/Culturology";
|
||||
case 5: return "/Telebiometrics/TMM/Fields_of_Study/Psychology";
|
||||
default: return $"/Telebiometrics/TMM/Fields_of_Study/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// modalities, sensory
|
||||
#region 2.42.1.3.*
|
||||
|
||||
oid_2_42_1_3:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/TMM/Modalities";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/TMM/Modalities/Tango";
|
||||
case 2: return "/Telebiometrics/TMM/Modalities/Video";
|
||||
case 3: return "/Telebiometrics/TMM/Modalities/Audio";
|
||||
case 4: return "/Telebiometrics/TMM/Modalities/Chemo";
|
||||
case 5: return "/Telebiometrics/TMM/Modalities/Radio";
|
||||
case 6: return "/Telebiometrics/TMM/Modalities/Calor";
|
||||
case 7: return "/Telebiometrics/TMM/Modalities/Electro";
|
||||
default: return $"/Telebiometrics/TMM/Modalities/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// human-physiology
|
||||
#region 2.42.2.*
|
||||
|
||||
oid_2_42_2:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/Human_Physiology";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_2_42_2_0;
|
||||
case 1: goto oid_2_42_2_1;
|
||||
case 2: return "/Telebiometrics/Human_Physiology/Symbol_Combinations";
|
||||
default: return $"/Telebiometrics/Human_Physiology/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// modules
|
||||
#region 2.42.2.0.*
|
||||
|
||||
oid_2_42_2_0:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/Human_Physiology/Modules";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_2_42_2_0_0;
|
||||
default: return $"/Telebiometrics/Human_Physiology/Modules/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// main
|
||||
#region 2.42.2.0.0.*
|
||||
|
||||
oid_2_42_2_0_0:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/Human_Physiology/Modules/Main_Module";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: return "/Telebiometrics/Human_Physiology/Modules/Main_Module/First_Version";
|
||||
default: return $"/Telebiometrics/Human_Physiology/Modules/Main_Module/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// symbols
|
||||
#region 2.42.2.1.*
|
||||
|
||||
oid_2_42_2_1:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/Human_Physiology/Symbols";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/Human_Physiology/Symbols/Tango_in";
|
||||
case 2: return "/Telebiometrics/Human_Physiology/Symbols/Video_in";
|
||||
case 3: return "/Telebiometrics/Human_Physiology/Symbols/Audio_in";
|
||||
case 4: return "/Telebiometrics/Human_Physiology/Symbols/Chemo_in";
|
||||
case 5: return "/Telebiometrics/Human_Physiology/Symbols/Radio_in";
|
||||
case 6: return "/Telebiometrics/Human_Physiology/Symbols/Calor_in";
|
||||
case 7: return "/Telebiometrics/Human_Physiology/Symbols/Tango_out";
|
||||
case 8: return "/Telebiometrics/Human_Physiology/Symbols/Video_out";
|
||||
case 9: return "/Telebiometrics/Human_Physiology/Symbols/Audio_out";
|
||||
case 10: return "/Telebiometrics/Human_Physiology/Symbols/Chemo_out";
|
||||
case 11: return "/Telebiometrics/Human_Physiology/Symbols/Radio_out";
|
||||
case 12: return "/Telebiometrics/Human_Physiology/Symbols/Calor_out";
|
||||
case 13: return "/Telebiometrics/Human_Physiology/Symbols/Safe";
|
||||
case 14: return "/Telebiometrics/Human_Physiology/Symbols/Threshold";
|
||||
default: return $"/Telebiometrics/Human_Physiology/Symbols/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// obj-cat, telehealth, e-health-protocol, th
|
||||
#region 2.42.3.*
|
||||
|
||||
oid_2_42_3:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/E_Health_Protocol";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_2_42_3_0;
|
||||
case 1: return "/Telebiometrics/E_Health_Protocol/[Patient schemes]";
|
||||
case 2: return "/Telebiometrics/E_Health_Protocol/[Medical staff schemes]";
|
||||
case 3: return "/Telebiometrics/E_Health_Protocol/[Observer schemes]";
|
||||
case 4: return "/Telebiometrics/E_Health_Protocol/[Pharmaceutical schemes]";
|
||||
case 5: return "/Telebiometrics/E_Health_Protocol/[Laboratory schemes]";
|
||||
case 6: return "/Telebiometrics/E_Health_Protocol/[Drug manufacturer schemes]";
|
||||
case 7: return "/Telebiometrics/E_Health_Protocol/[Medical device schemes]";
|
||||
case 8: return "/Telebiometrics/E_Health_Protocol/[Medical software schemes]";
|
||||
case 9: return "/Telebiometrics/E_Health_Protocol/[Medical insurance schemes]";
|
||||
case 10: return "/Telebiometrics/E_Health_Protocol/[Medical record schemes]";
|
||||
default: return $"/Telebiometrics/E_Health_Protocol/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// obj-cat, telehealth, e-health-protocol, th
|
||||
#region 2.42.3.0.*
|
||||
|
||||
oid_2_42_3_0:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/E_Health_Protocol/Modules";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: goto oid_2_42_3_0_0;
|
||||
case 1: goto oid_2_42_3_0_1;
|
||||
case 2: goto oid_2_42_3_0_2;
|
||||
case 3: goto oid_2_42_3_0_3;
|
||||
case 4: goto oid_2_42_3_0_4;
|
||||
case 5: goto oid_2_42_3_0_5;
|
||||
default: return $"/Telebiometrics/E_Health_Protocol/Modules/{values[index - 1]}";
|
||||
}
|
||||
|
||||
// identification
|
||||
#region 2.42.3.0.0.*
|
||||
|
||||
oid_2_42_3_0_0:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/E_Health_Protocol/Modules/Identification";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/E_Health_Protocol/Modules/Identification/Version1";
|
||||
default: return $"/Telebiometrics/E_Health_Protocol/Modules/Identification/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// set-up
|
||||
#region 2.42.3.0.1.*
|
||||
|
||||
oid_2_42_3_0_1:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/E_Health_Protocol/Modules/Setup";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/E_Health_Protocol/Modules/Setup/Version1";
|
||||
default: return $"/Telebiometrics/E_Health_Protocol/Modules/Setup/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// send-and-ack
|
||||
#region 2.42.3.0.2.*
|
||||
|
||||
oid_2_42_3_0_2:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/E_Health_Protocol/Modules/Send-and-ack";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/E_Health_Protocol/Modules/Send-and-ack/Version1";
|
||||
default: return $"/Telebiometrics/E_Health_Protocol/Modules/Send-and-ack/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// command-response
|
||||
#region 2.42.3.0.3.*
|
||||
|
||||
oid_2_42_3_0_3:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/E_Health_Protocol/Modules/Command-response";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/E_Health_Protocol/Modules/Command-response/Version1";
|
||||
default: return $"/Telebiometrics/E_Health_Protocol/Modules/Command-response/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// quantity-and-units
|
||||
#region 2.42.3.0.4.*
|
||||
|
||||
oid_2_42_3_0_4:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/E_Health_Protocol/Modules/Quantities_And_Units";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Telebiometrics/E_Health_Protocol/Modules/Quantities_And_Units/Version1";
|
||||
default: return $"/Telebiometrics/E_Health_Protocol/Modules/Quantities_And_Units/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// examples
|
||||
#region 2.42.3.0.5.*
|
||||
|
||||
oid_2_42_3_0_5:
|
||||
|
||||
if (index == values.Length) return "/Telebiometrics/E_Health_Protocol/Modules/Examples";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: return "/Telebiometrics/E_Health_Protocol/Modules/Examples/Command_Response";
|
||||
case 1: return "/Telebiometrics/E_Health_Protocol/Modules/Examples/Data_Message";
|
||||
default: return $"/Telebiometrics/E_Health_Protocol/Modules/Examples/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// cybersecurity
|
||||
#region 2.48.*
|
||||
|
||||
oid_2_48:
|
||||
|
||||
if (index == values.Length) return "/Cybersecurity";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 1: return "/Cybersecurity/Country";
|
||||
case 2: return "/Cybersecurity/International-Org";
|
||||
default: return $"/Cybersecurity/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// alerting
|
||||
#region 2.49.*
|
||||
|
||||
oid_2_49:
|
||||
|
||||
if (index == values.Length) return "/Alerting";
|
||||
switch (values[index++])
|
||||
{
|
||||
case 0: return "/Alerting/WMO";
|
||||
default: return $"/Alerting/{values[index - 1]}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore IDE0011
|
||||
}
|
||||
71
BurnOutSharp.Builder/ObjectIdentifier.cs
Normal file
71
BurnOutSharp.Builder/ObjectIdentifier.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BurnOutSharp.Builder
|
||||
{
|
||||
/// <summary>
|
||||
/// Methods related to Object Identifiers (OID)
|
||||
/// </summary>
|
||||
public static partial class ObjectIdentifier
|
||||
{
|
||||
// TODO: ulong[] isn't going to work. If we can use .NET 7, we can use UInt128
|
||||
// We might want to look into storing all values as GUID? I don't remember if
|
||||
// you can do value comparisions between an integral value and a GUID, though.
|
||||
|
||||
/// <summary>
|
||||
/// Parse an OID in DER-encoded byte notation into a list of values
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array representing the data to read</param>
|
||||
/// <param name="length">Total length of the data according to the DER TLV</param>
|
||||
/// <returns>Array of values representing the OID</returns>
|
||||
public static ulong[] ParseDERIntoArray(byte[] data, ulong length)
|
||||
{
|
||||
// The first byte contains nodes 1 and 2
|
||||
int firstNode = Math.DivRem(data[0], 40, out int secondNode);
|
||||
|
||||
// Create a list for all nodes
|
||||
List<ulong> nodes = new List<ulong> { (ulong)firstNode, (ulong)secondNode };
|
||||
|
||||
// All other nodes are encoded uniquely
|
||||
int offset = 1;
|
||||
while (offset < (long)length)
|
||||
{
|
||||
// If bit 7 is not set
|
||||
if ((data[offset] & 0x80) == 0)
|
||||
{
|
||||
nodes.Add(data[offset]);
|
||||
offset++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, read the encoded value in a loop
|
||||
ulong dotValue = 0;
|
||||
bool doneProcessing = false;
|
||||
|
||||
do
|
||||
{
|
||||
// Shift the current encoded value
|
||||
dotValue <<= 7;
|
||||
|
||||
// If we have a leading zero byte, we're at the end
|
||||
if ((data[offset] & 0x80) == 0)
|
||||
doneProcessing = true;
|
||||
|
||||
// Clear the top byte
|
||||
unchecked { data[offset] &= (byte)~0x80; }
|
||||
|
||||
// Add the new value to the result
|
||||
dotValue |= data[offset];
|
||||
|
||||
// Increment the offset
|
||||
offset++;
|
||||
} while (offset < data.Length && !doneProcessing);
|
||||
|
||||
// Add the parsed value to the output
|
||||
nodes.Add(dotValue);
|
||||
}
|
||||
|
||||
return nodes.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
26
BurnOutSharp.Builder/ObjectIdentifier.dot.cs
Normal file
26
BurnOutSharp.Builder/ObjectIdentifier.dot.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace BurnOutSharp.Builder
|
||||
{
|
||||
#pragma warning disable IDE0011
|
||||
|
||||
/// <summary>
|
||||
/// Methods related to Object Identifiers (OID) and dot notation
|
||||
/// </summary>
|
||||
public static partial class ObjectIdentifier
|
||||
{
|
||||
/// <summary>
|
||||
/// Parse an OID in separated-value notation into dot notation
|
||||
/// </summary>
|
||||
/// <param name="values">List of values to check against</param>
|
||||
/// <returns>List of values representing the dot notation</returns>
|
||||
public static string ParseOIDToDotNotation(ulong[] values)
|
||||
{
|
||||
// If we have an invalid set of values, we can't do anything
|
||||
if (values == null || values.Length == 0)
|
||||
return null;
|
||||
|
||||
return string.Join(".", values);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore IDE0011
|
||||
}
|
||||
2515
BurnOutSharp.Builder/PortableExecutable.cs
Normal file
2515
BurnOutSharp.Builder/PortableExecutable.cs
Normal file
File diff suppressed because it is too large
Load Diff
22
BurnOutSharp.Matching/BurnOutSharp.Matching.csproj
Normal file
22
BurnOutSharp.Matching/BurnOutSharp.Matching.csproj
Normal file
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
|
||||
<Title>BurnOutSharp.Matching</Title>
|
||||
<AssemblyName>BurnOutSharp.Matching</AssemblyName>
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
<Product>BurnOutSharp</Product>
|
||||
<Copyright>Copyright (c)2018-2022 Matt Nadareski</Copyright>
|
||||
<RepositoryUrl>https://github.com/mnadareski/BurnOutSharp</RepositoryUrl>
|
||||
<Version>2.5</Version>
|
||||
<AssemblyVersion>2.5</AssemblyVersion>
|
||||
<FileVersion>2.5</FileVersion>
|
||||
<IncludeSource>true</IncludeSource>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,3 +1,5 @@
|
||||
using System.IO;
|
||||
|
||||
namespace BurnOutSharp.Matching
|
||||
{
|
||||
/// <summary>
|
||||
@@ -33,7 +35,7 @@ namespace BurnOutSharp.Matching
|
||||
End = end;
|
||||
}
|
||||
|
||||
#region Matching
|
||||
#region Array Matching
|
||||
|
||||
/// <summary>
|
||||
/// Get if this match can be found in a stack
|
||||
@@ -91,6 +93,7 @@ namespace BurnOutSharp.Matching
|
||||
if (Needle.Length > stack.Length - index)
|
||||
return false;
|
||||
|
||||
// Loop through and check the value
|
||||
for (int i = 0; i < Needle.Length; i++)
|
||||
{
|
||||
// A null value is a wildcard
|
||||
@@ -102,7 +105,96 @@ namespace BurnOutSharp.Matching
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Stream Matching
|
||||
|
||||
/// <summary>
|
||||
/// Get if this match can be found in a stack
|
||||
/// </summary>
|
||||
/// <param name="stack">Stream to search for the given content</param>
|
||||
/// <param name="reverse">True to search from the end of the array, false from the start</param>
|
||||
/// <returns>Tuple of success and found position</returns>
|
||||
public (bool success, int position) Match(Stream stack, bool reverse = false)
|
||||
{
|
||||
// If either array is null or empty, we can't do anything
|
||||
if (stack == null || stack.Length == 0 || Needle == null || Needle.Length == 0)
|
||||
return (false, -1);
|
||||
|
||||
// If the needle array is larger than the stack array, it can't be contained within
|
||||
if (Needle.Length > stack.Length)
|
||||
return (false, -1);
|
||||
|
||||
// Set the default start and end values
|
||||
int start = Start;
|
||||
int end = End;
|
||||
|
||||
// If start or end are not set properly, set them to defaults
|
||||
if (start < 0)
|
||||
start = 0;
|
||||
if (end < 0)
|
||||
end = (int)(stack.Length - Needle.Length);
|
||||
|
||||
for (int i = reverse ? end : start; reverse ? i > start : i < end; i += reverse ? -1 : 1)
|
||||
{
|
||||
// If we somehow have an invalid end and we haven't matched, return
|
||||
if (i > stack.Length)
|
||||
return (false, -1);
|
||||
|
||||
// Check to see if the values are equal
|
||||
if (EqualAt(stack, i))
|
||||
return (true, i);
|
||||
}
|
||||
|
||||
return (false, -1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get if a stack at a certain index is equal to a needle
|
||||
/// </summary>
|
||||
/// <param name="stack">Stream to search for the given content</param>
|
||||
/// <param name="index">Starting index to check equality</param>
|
||||
/// <returns>True if the needle matches the stack at a given index</returns>
|
||||
private bool EqualAt(Stream stack, int index)
|
||||
{
|
||||
// If the index is invalid, we can't do anything
|
||||
if (index < 0)
|
||||
return false;
|
||||
|
||||
// If we're too close to the end of the stack, return false
|
||||
if (Needle.Length > stack.Length - index)
|
||||
return false;
|
||||
|
||||
// Save the current position and move to the index
|
||||
long currentPosition = stack.Position;
|
||||
stack.Seek(index, SeekOrigin.Begin);
|
||||
|
||||
// Set the return value
|
||||
bool matched = true;
|
||||
|
||||
// Loop through and check the value
|
||||
for (int i = 0; i < Needle.Length; i++)
|
||||
{
|
||||
byte stackValue = (byte)stack.ReadByte();
|
||||
|
||||
// A null value is a wildcard
|
||||
if (Needle[i] == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (stackValue != Needle[i])
|
||||
{
|
||||
matched = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the position and return the value
|
||||
stack.Seek(currentPosition, SeekOrigin.Begin);
|
||||
return matched;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
199
BurnOutSharp.Matching/ContentMatchSet.cs
Normal file
199
BurnOutSharp.Matching/ContentMatchSet.cs
Normal file
@@ -0,0 +1,199 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace BurnOutSharp.Matching
|
||||
{
|
||||
/// <summary>
|
||||
/// A set of content matches that work together
|
||||
/// </summary>
|
||||
public class ContentMatchSet : MatchSet<ContentMatch, byte?[]>
|
||||
{
|
||||
/// <summary>
|
||||
/// Function to get a content version
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A content version method takes the file path, the file contents,
|
||||
/// and a list of found positions and returns a single string. That
|
||||
/// string is either a version string, in which case it will be appended
|
||||
/// to the protection name, or `null`, in which case it will cause
|
||||
/// the protection to be omitted.
|
||||
/// </remarks>
|
||||
public Func<string, byte[], List<int>, string> GetArrayVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Function to get a content version
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A content version method takes the file path, the file contents,
|
||||
/// and a list of found positions and returns a single string. That
|
||||
/// string is either a version string, in which case it will be appended
|
||||
/// to the protection name, or `null`, in which case it will cause
|
||||
/// the protection to be omitted.
|
||||
/// </remarks>
|
||||
public Func<string, Stream, List<int>, string> GetStreamVersion { get; set; }
|
||||
|
||||
#region Generic Constructors
|
||||
|
||||
public ContentMatchSet(byte?[] needle, string protectionName)
|
||||
: this(new List<byte?[]> { needle }, getArrayVersion: null, protectionName) { }
|
||||
|
||||
public ContentMatchSet(List<byte?[]> needles, string protectionName)
|
||||
: this(needles, getArrayVersion: null, protectionName) { }
|
||||
|
||||
public ContentMatchSet(ContentMatch needle, string protectionName)
|
||||
: this(new List<ContentMatch>() { needle }, getArrayVersion: null, protectionName) { }
|
||||
|
||||
public ContentMatchSet(List<ContentMatch> needles, string protectionName)
|
||||
: this(needles, getArrayVersion: null, protectionName) { }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Array Constructors
|
||||
|
||||
public ContentMatchSet(byte?[] needle, Func<string, byte[], List<int>, string> getArrayVersion, string protectionName)
|
||||
: this(new List<byte?[]> { needle }, getArrayVersion, protectionName) { }
|
||||
|
||||
public ContentMatchSet(List<byte?[]> needles, Func<string, byte[], List<int>, string> getArrayVersion, string protectionName)
|
||||
: this(needles.Select(n => new ContentMatch(n)).ToList(), getArrayVersion, protectionName) { }
|
||||
|
||||
public ContentMatchSet(ContentMatch needle, Func<string, byte[], List<int>, string> getArrayVersion, string protectionName)
|
||||
: this(new List<ContentMatch>() { needle }, getArrayVersion, protectionName) { }
|
||||
|
||||
public ContentMatchSet(List<ContentMatch> needles, Func<string, byte[], List<int>, string> getArrayVersion, string protectionName)
|
||||
{
|
||||
Matchers = needles;
|
||||
GetArrayVersion = getArrayVersion;
|
||||
ProtectionName = protectionName;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Stream Constructors
|
||||
|
||||
public ContentMatchSet(byte?[] needle, Func<string, Stream, List<int>, string> getStreamVersion, string protectionName)
|
||||
: this(new List<byte?[]> { needle }, getStreamVersion, protectionName) { }
|
||||
|
||||
public ContentMatchSet(List<byte?[]> needles, Func<string, Stream, List<int>, string> getStreamVersion, string protectionName)
|
||||
: this(needles.Select(n => new ContentMatch(n)).ToList(), getStreamVersion, protectionName) { }
|
||||
|
||||
public ContentMatchSet(ContentMatch needle, Func<string, Stream, List<int>, string> getStreamVersion, string protectionName)
|
||||
: this(new List<ContentMatch>() { needle }, getStreamVersion, protectionName) { }
|
||||
|
||||
public ContentMatchSet(List<ContentMatch> needles, Func<string, Stream, List<int>, string> getStreamVersion, string protectionName)
|
||||
{
|
||||
Matchers = needles;
|
||||
GetStreamVersion = getStreamVersion;
|
||||
ProtectionName = protectionName;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Array Matching
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether all content matches pass
|
||||
/// </summary>
|
||||
/// <param name="stack">Array to search</param>
|
||||
/// <returns>Tuple of passing status and matching positions</returns>
|
||||
public (bool, List<int>) MatchesAll(byte[] stack)
|
||||
{
|
||||
// If no content matches are defined, we fail out
|
||||
if (Matchers == null || !Matchers.Any())
|
||||
return (false, new List<int>());
|
||||
|
||||
// Initialize the position list
|
||||
List<int> positions = new List<int>();
|
||||
|
||||
// Loop through all content matches and make sure all pass
|
||||
foreach (var contentMatch in Matchers)
|
||||
{
|
||||
(bool match, int position) = contentMatch.Match(stack);
|
||||
if (!match)
|
||||
return (false, new List<int>());
|
||||
else
|
||||
positions.Add(position);
|
||||
}
|
||||
|
||||
return (true, positions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether any content matches pass
|
||||
/// </summary>
|
||||
/// <param name="stack">Array to search</param>
|
||||
/// <returns>Tuple of passing status and first matching position</returns>
|
||||
public (bool, int) MatchesAny(byte[] stack)
|
||||
{
|
||||
// If no content matches are defined, we fail out
|
||||
if (Matchers == null || !Matchers.Any())
|
||||
return (false, -1);
|
||||
|
||||
// Loop through all content matches and make sure all pass
|
||||
foreach (var contentMatch in Matchers)
|
||||
{
|
||||
(bool match, int position) = contentMatch.Match(stack);
|
||||
if (match)
|
||||
return (true, position);
|
||||
}
|
||||
|
||||
return (false, -1);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Stream Matching
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether all content matches pass
|
||||
/// </summary>
|
||||
/// <param name="stack">Stream to search</param>
|
||||
/// <returns>Tuple of passing status and matching positions</returns>
|
||||
public (bool, List<int>) MatchesAll(Stream stack)
|
||||
{
|
||||
// If no content matches are defined, we fail out
|
||||
if (Matchers == null || !Matchers.Any())
|
||||
return (false, new List<int>());
|
||||
|
||||
// Initialize the position list
|
||||
List<int> positions = new List<int>();
|
||||
|
||||
// Loop through all content matches and make sure all pass
|
||||
foreach (var contentMatch in Matchers)
|
||||
{
|
||||
(bool match, int position) = contentMatch.Match(stack);
|
||||
if (!match)
|
||||
return (false, new List<int>());
|
||||
else
|
||||
positions.Add(position);
|
||||
}
|
||||
|
||||
return (true, positions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether any content matches pass
|
||||
/// </summary>
|
||||
/// <param name="stack">Stream to search</param>
|
||||
/// <returns>Tuple of passing status and first matching position</returns>
|
||||
public (bool, int) MatchesAny(Stream stack)
|
||||
{
|
||||
// If no content matches are defined, we fail out
|
||||
if (Matchers == null || !Matchers.Any())
|
||||
return (false, -1);
|
||||
|
||||
// Loop through all content matches and make sure all pass
|
||||
foreach (var contentMatch in Matchers)
|
||||
{
|
||||
(bool match, int position) = contentMatch.Match(stack);
|
||||
if (match)
|
||||
return (true, position);
|
||||
}
|
||||
|
||||
return (false, -1);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace BurnOutSharp.Matching
|
||||
@@ -7,42 +8,42 @@ namespace BurnOutSharp.Matching
|
||||
/// <summary>
|
||||
/// Helper class for matching
|
||||
/// </summary>
|
||||
internal static class MatchUtil
|
||||
public static class MatchUtil
|
||||
{
|
||||
#region Content Matching
|
||||
#region Array Content Matching
|
||||
|
||||
/// <summary>
|
||||
/// Get all content matches for a given list of matchers
|
||||
/// </summary>
|
||||
/// <param name="file">File to check for matches</param>
|
||||
/// <param name="fileContent">Byte array representing the file contents</param>
|
||||
/// <param name="stack">Array to search</param>
|
||||
/// <param name="matchers">Enumerable of ContentMatchSets to be run on the file</param>
|
||||
/// <param name="includeDebug">True to include positional data, false otherwise</param>
|
||||
/// <returns>List of strings representing the matched protections, null or empty otherwise</returns>
|
||||
public static ConcurrentQueue<string> GetAllMatches(
|
||||
string file,
|
||||
byte[] fileContent,
|
||||
byte[] stack,
|
||||
IEnumerable<ContentMatchSet> matchers,
|
||||
bool includeDebug = false)
|
||||
{
|
||||
return FindAllMatches(file, fileContent, matchers, includeDebug, false);
|
||||
return FindAllMatches(file, stack, matchers, includeDebug, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get first content match for a given list of matchers
|
||||
/// </summary>
|
||||
/// <param name="file">File to check for matches</param>
|
||||
/// <param name="fileContent">Byte array representing the file contents</param>
|
||||
/// <param name="stack">Array to search</param>
|
||||
/// <param name="matchers">Enumerable of ContentMatchSets to be run on the file</param>
|
||||
/// <param name="includeDebug">True to include positional data, false otherwise</param>
|
||||
/// <returns>String representing the matched protection, null otherwise</returns>
|
||||
public static string GetFirstMatch(
|
||||
string file,
|
||||
byte[] fileContent,
|
||||
byte[] stack,
|
||||
IEnumerable<ContentMatchSet> matchers,
|
||||
bool includeDebug = false)
|
||||
{
|
||||
var contentMatches = FindAllMatches(file, fileContent, matchers, includeDebug, true);
|
||||
var contentMatches = FindAllMatches(file, stack, matchers, includeDebug, true);
|
||||
if (contentMatches == null || !contentMatches.Any())
|
||||
return null;
|
||||
|
||||
@@ -53,14 +54,14 @@ namespace BurnOutSharp.Matching
|
||||
/// Get the required set of content matches on a per Matcher basis
|
||||
/// </summary>
|
||||
/// <param name="file">File to check for matches</param>
|
||||
/// <param name="fileContent">Byte array representing the file contents</param>
|
||||
/// <param name="stack">Array to search</param>
|
||||
/// <param name="matchers">Enumerable of ContentMatchSets to be run on the file</param>
|
||||
/// <param name="includeDebug">True to include positional data, false otherwise</param>
|
||||
/// <param name="stopAfterFirst">True to stop after the first match, false otherwise</param>
|
||||
/// <returns>List of strings representing the matched protections, null or empty otherwise</returns>
|
||||
private static ConcurrentQueue<string> FindAllMatches(
|
||||
string file,
|
||||
byte[] fileContent,
|
||||
byte[] stack,
|
||||
IEnumerable<ContentMatchSet> matchers,
|
||||
bool includeDebug,
|
||||
bool stopAfterFirst)
|
||||
@@ -76,7 +77,7 @@ namespace BurnOutSharp.Matching
|
||||
foreach (var matcher in matchers)
|
||||
{
|
||||
// Determine if the matcher passes
|
||||
(bool passes, List<int> positions) = matcher.MatchesAll(fileContent);
|
||||
(bool passes, List<int> positions) = matcher.MatchesAll(stack);
|
||||
if (!passes)
|
||||
continue;
|
||||
|
||||
@@ -84,7 +85,7 @@ namespace BurnOutSharp.Matching
|
||||
string positionsString = string.Join(", ", positions);
|
||||
|
||||
// If we there is no version method, just return the protection name
|
||||
if (matcher.GetVersion == null)
|
||||
if (matcher.GetArrayVersion == null)
|
||||
{
|
||||
matchedProtections.Enqueue((matcher.ProtectionName ?? "Unknown Protection") + (includeDebug ? $" (Index {positionsString})" : string.Empty));
|
||||
}
|
||||
@@ -93,7 +94,108 @@ namespace BurnOutSharp.Matching
|
||||
else
|
||||
{
|
||||
// A null version returned means the check didn't pass at the version step
|
||||
string version = matcher.GetVersion(file, fileContent, positions);
|
||||
string version = matcher.GetArrayVersion(file, stack, positions);
|
||||
if (version == null)
|
||||
continue;
|
||||
|
||||
matchedProtections.Enqueue($"{matcher.ProtectionName ?? "Unknown Protection"} {version}".TrimEnd() + (includeDebug ? $" (Index {positionsString})" : string.Empty));
|
||||
}
|
||||
|
||||
// If we're stopping after the first protection, bail out here
|
||||
if (stopAfterFirst)
|
||||
return matchedProtections;
|
||||
}
|
||||
|
||||
return matchedProtections;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Stream Content Matching
|
||||
|
||||
/// <summary>
|
||||
/// Get all content matches for a given list of matchers
|
||||
/// </summary>
|
||||
/// <param name="file">File to check for matches</param>
|
||||
/// <param name="stack">Stream to search</param>
|
||||
/// <param name="matchers">Enumerable of ContentMatchSets to be run on the file</param>
|
||||
/// <param name="includeDebug">True to include positional data, false otherwise</param>
|
||||
/// <returns>List of strings representing the matched protections, null or empty otherwise</returns>
|
||||
public static ConcurrentQueue<string> GetAllMatches(
|
||||
string file,
|
||||
Stream stack,
|
||||
IEnumerable<ContentMatchSet> matchers,
|
||||
bool includeDebug = false)
|
||||
{
|
||||
return FindAllMatches(file, stack, matchers, includeDebug, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get first content match for a given list of matchers
|
||||
/// </summary>
|
||||
/// <param name="file">File to check for matches</param>
|
||||
/// <param name="stack">Stream to search</param>
|
||||
/// <param name="matchers">Enumerable of ContentMatchSets to be run on the file</param>
|
||||
/// <param name="includeDebug">True to include positional data, false otherwise</param>
|
||||
/// <returns>String representing the matched protection, null otherwise</returns>
|
||||
public static string GetFirstMatch(
|
||||
string file,
|
||||
Stream stack,
|
||||
IEnumerable<ContentMatchSet> matchers,
|
||||
bool includeDebug = false)
|
||||
{
|
||||
var contentMatches = FindAllMatches(file, stack, matchers, includeDebug, true);
|
||||
if (contentMatches == null || !contentMatches.Any())
|
||||
return null;
|
||||
|
||||
return contentMatches.First();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the required set of content matches on a per Matcher basis
|
||||
/// </summary>
|
||||
/// <param name="file">File to check for matches</param>
|
||||
/// <param name="stack">Stream to search</param>
|
||||
/// <param name="matchers">Enumerable of ContentMatchSets to be run on the file</param>
|
||||
/// <param name="includeDebug">True to include positional data, false otherwise</param>
|
||||
/// <param name="stopAfterFirst">True to stop after the first match, false otherwise</param>
|
||||
/// <returns>List of strings representing the matched protections, null or empty otherwise</returns>
|
||||
private static ConcurrentQueue<string> FindAllMatches(
|
||||
string file,
|
||||
Stream stack,
|
||||
IEnumerable<ContentMatchSet> matchers,
|
||||
bool includeDebug,
|
||||
bool stopAfterFirst)
|
||||
{
|
||||
// If there's no mappings, we can't match
|
||||
if (matchers == null || !matchers.Any())
|
||||
return null;
|
||||
|
||||
// Initialize the queue of matched protections
|
||||
var matchedProtections = new ConcurrentQueue<string>();
|
||||
|
||||
// Loop through and try everything otherwise
|
||||
foreach (var matcher in matchers)
|
||||
{
|
||||
// Determine if the matcher passes
|
||||
(bool passes, List<int> positions) = matcher.MatchesAll(stack);
|
||||
if (!passes)
|
||||
continue;
|
||||
|
||||
// Format the list of all positions found
|
||||
string positionsString = string.Join(", ", positions);
|
||||
|
||||
// If we there is no version method, just return the protection name
|
||||
if (matcher.GetStreamVersion == null)
|
||||
{
|
||||
matchedProtections.Enqueue((matcher.ProtectionName ?? "Unknown Protection") + (includeDebug ? $" (Index {positionsString})" : string.Empty));
|
||||
}
|
||||
|
||||
// Otherwise, invoke the version method
|
||||
else
|
||||
{
|
||||
// A null version returned means the check didn't pass at the version step
|
||||
string version = matcher.GetStreamVersion(file, stack, positions);
|
||||
if (version == null)
|
||||
continue;
|
||||
|
||||
22
BurnOutSharp.Models/BurnOutSharp.Models.csproj
Normal file
22
BurnOutSharp.Models/BurnOutSharp.Models.csproj
Normal file
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
|
||||
<Title>BurnOutSharp.Models</Title>
|
||||
<AssemblyName>BurnOutSharp.Models</AssemblyName>
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
<Product>BurnOutSharp</Product>
|
||||
<Copyright>Copyright (c)2022 Matt Nadareski</Copyright>
|
||||
<RepositoryUrl>https://github.com/mnadareski/BurnOutSharp</RepositoryUrl>
|
||||
<Version>2.5</Version>
|
||||
<AssemblyVersion>2.5</AssemblyVersion>
|
||||
<FileVersion>2.5</FileVersion>
|
||||
<IncludeSource>true</IncludeSource>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
36
BurnOutSharp.Models/LinearExecutable/DebugInformation.cs
Normal file
36
BurnOutSharp.Models/LinearExecutable/DebugInformation.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The debug information is defined by the debugger and is not controlled by
|
||||
/// the linear EXE format or linker. The only data defined by the linear EXE
|
||||
/// format relative to the debug information is it's offset in the EXE file and
|
||||
/// length in bytes as defined in the linear EXE header.
|
||||
///
|
||||
/// To support multiple debuggers the first word of the debug information is a
|
||||
/// type field which determines the format of the debug information.
|
||||
/// </summary>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class DebugInformation
|
||||
{
|
||||
/// <summary>
|
||||
/// The signature consists of a string of three (3) ASCII characters: "NB0"
|
||||
/// </summary>
|
||||
public byte[] Signature;
|
||||
|
||||
/// <summary>
|
||||
/// This defines the type of debugger data that exists in the remainder of the
|
||||
/// debug information.
|
||||
/// </summary>
|
||||
public DebugFormatType FormatType;
|
||||
|
||||
// DEBUGGER DATA = Debugger specific data.
|
||||
// The format of the debugger data is defined by the debugger that is being used.
|
||||
// The values defined for the type field are not enforced by the system. It is
|
||||
// the responsibility of the linker or debugging tools to follow the convention
|
||||
// for the type field that is defined here.
|
||||
}
|
||||
}
|
||||
234
BurnOutSharp.Models/LinearExecutable/EntryTableEntry.cs
Normal file
234
BurnOutSharp.Models/LinearExecutable/EntryTableEntry.cs
Normal file
@@ -0,0 +1,234 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The entry table contains object and offset information that is used to resolve
|
||||
/// fixup references to the entry points within this module. Not all entry points
|
||||
/// in the entry table will be exported, some entry points will only be used
|
||||
/// within the module. An ordinal number is used to index into the entry table.
|
||||
/// The entry table entries are numbered starting from one.
|
||||
///
|
||||
/// The list of entries are compressed into 'bundles', where possible. The entries
|
||||
/// within each bundle are all the same size. A bundle starts with a count field
|
||||
/// which indicates the number of entries in the bundle. The count is followed by
|
||||
/// a type field which identifies the bundle format. This provides both a means
|
||||
/// for saving space as well as a mechanism for extending the bundle types.
|
||||
/// </summary>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public class EntryTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of entries.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the number of entries in this bundle.
|
||||
///
|
||||
/// A zero value for the number of entries identifies the end of the
|
||||
/// entry table. There is no further bundle information when the number
|
||||
/// of entries is zero. In other words the entry table is terminated by
|
||||
/// a single zero byte.
|
||||
///
|
||||
/// For <see cref="BundleType.UnusedEntry"/>, this is the number of unused
|
||||
/// entries to skip.
|
||||
/// For <see cref="BundleType.SixteenBitEntry"/>, this is the number of 16-bit
|
||||
/// entries in this bundle. The flags and offset value are repeated this
|
||||
/// number of times.
|
||||
/// For <see cref="BundleType.TwoEightySixCallGateEntry"/>, this is the number
|
||||
/// of 286 call gate entries in this bundle. The flags, callgate, and offset
|
||||
/// value are repeated this number of times.
|
||||
/// For <see cref="BundleType.ThirtyTwoBitEntry"/>, this is the number
|
||||
/// of 32-bit entries in this bundle. The flags and offset value are repeated
|
||||
/// this number of times.
|
||||
/// For <see cref="BundleType.ForwarderEntry"/>, this field is reserved for future use.
|
||||
/// </remarks>
|
||||
[FieldOffset(0)] public byte Entries;
|
||||
|
||||
/// <summary>
|
||||
/// This defines the bundle type which determines the contents of the BUNDLE INFO.
|
||||
/// </summary>
|
||||
[FieldOffset(1)] public BundleType BundleType;
|
||||
|
||||
#region 16-bit Entry
|
||||
|
||||
/// <summary>
|
||||
/// Object number.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the object number for the entries in this bundle.
|
||||
/// </remarks>
|
||||
[FieldOffset(2)] public ushort SixteenBitObjectNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Entry flags.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These are the flags for this entry point.
|
||||
/// </remarks>
|
||||
[FieldOffset(4)] public EntryFlags SixteenBitEntryFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Offset in object.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the offset in the object for the entry point defined at this ordinal number.
|
||||
/// </remarks>
|
||||
[FieldOffset(5)] public ushort SixteenBitOffset;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 286 Call Gate Entry
|
||||
|
||||
/// <summary>
|
||||
/// Object number.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the object number for the entries in this bundle.
|
||||
/// </remarks>
|
||||
[FieldOffset(2)] public ushort TwoEightySixObjectNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Entry flags.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These are the flags for this entry point.
|
||||
/// </remarks>
|
||||
[FieldOffset(4)] public EntryFlags TwoEightySixEntryFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Offset in object.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the offset in the object for the entry point defined at this ordinal number.
|
||||
/// </remarks>
|
||||
[FieldOffset(5)] public ushort TwoEightySixOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Callgate selector.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The callgate selector is a reserved field used by the loader to store a call
|
||||
/// gate selector value for references to ring 2 entry points. When a ring 3
|
||||
/// reference to a ring 2 entry point is made, the callgate selector with a zero
|
||||
/// offset is place in the relocation fixup address. The segment number and offset
|
||||
/// in segment is placed in the LDT callgate.
|
||||
/// </remarks>
|
||||
[FieldOffset(7)] public ushort TwoEightySixCallgate;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 32-bit Entry
|
||||
|
||||
/// <summary>
|
||||
/// Object number.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the object number for the entries in this bundle.
|
||||
/// </remarks>
|
||||
[FieldOffset(2)] public ushort ThirtyTwoBitObjectNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Entry flags.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These are the flags for this entry point.
|
||||
/// </remarks>
|
||||
[FieldOffset(4)] public EntryFlags ThirtyTwoBitEntryFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Offset in object.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the offset in the object for the entry point defined at this ordinal number.
|
||||
/// </remarks>
|
||||
[FieldOffset(5)] public uint ThirtyTwoBitOffset;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Forwarder Entry
|
||||
|
||||
/// <summary>
|
||||
/// 0
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field is reserved for future use.
|
||||
/// </remarks>
|
||||
[FieldOffset(2)] public ushort ForwarderReserved;
|
||||
|
||||
/// <summary>
|
||||
/// Forwarder flags.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These are the flags for this entry point.
|
||||
/// </remarks>
|
||||
[FieldOffset(4)] public ForwarderFlags ForwarderFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Module Ordinal Number
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the index into the Import Module Name Table for this forwarder.
|
||||
/// </remarks>
|
||||
[FieldOffset(5)] public ushort ForwarderModuleOrdinalNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Procedure Name Offset
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the FLAGS field indicates import by ordinal, then this field is the
|
||||
/// ordinal number into the Entry Table of the target module, otherwise this
|
||||
/// field is the offset into the Procedure Names Table of the target module.
|
||||
///
|
||||
/// A Forwarder entry (type = 4) is an entry point whose value is an imported
|
||||
/// reference. When a load time fixup occurs whose target is a forwarder, the
|
||||
/// loader obtains the address imported by the forwarder and uses that imported
|
||||
/// address to resolve the fixup.
|
||||
///
|
||||
/// A forwarder may refer to an entry point in another module which is itself a
|
||||
/// forwarder, so there can be a chain of forwarders. The loader will traverse
|
||||
/// the chain until it finds a non-forwarded entry point which terminates the
|
||||
/// chain, and use this to resolve the original fixup. Circular chains are
|
||||
/// detected by the loader and result in a load time error. A maximum of 1024
|
||||
/// forwarders is allowed in a chain; more than this results in a load time error.
|
||||
///
|
||||
/// Forwarders are useful for merging and recombining API calls into different
|
||||
/// sets of libraries, while maintaining compatibility with applications. For
|
||||
/// example, if one wanted to combine MONCALLS, MOUCALLS, and VIOCALLS into a
|
||||
/// single libraries, one could provide entry points for the three libraries
|
||||
/// that are forwarders pointing to the common implementation.
|
||||
/// </remarks>
|
||||
[FieldOffset(7)] public uint ProcedureNameOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Import Ordinal Number
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the FLAGS field indicates import by ordinal, then this field is the
|
||||
/// ordinal number into the Entry Table of the target module, otherwise this
|
||||
/// field is the offset into the Procedure Names Table of the target module.
|
||||
///
|
||||
/// A Forwarder entry (type = 4) is an entry point whose value is an imported
|
||||
/// reference. When a load time fixup occurs whose target is a forwarder, the
|
||||
/// loader obtains the address imported by the forwarder and uses that imported
|
||||
/// address to resolve the fixup.
|
||||
///
|
||||
/// A forwarder may refer to an entry point in another module which is itself a
|
||||
/// forwarder, so there can be a chain of forwarders. The loader will traverse
|
||||
/// the chain until it finds a non-forwarded entry point which terminates the
|
||||
/// chain, and use this to resolve the original fixup. Circular chains are
|
||||
/// detected by the loader and result in a load time error. A maximum of 1024
|
||||
/// forwarders is allowed in a chain; more than this results in a load time error.
|
||||
///
|
||||
/// Forwarders are useful for merging and recombining API calls into different
|
||||
/// sets of libraries, while maintaining compatibility with applications. For
|
||||
/// example, if one wanted to combine MONCALLS, MOUCALLS, and VIOCALLS into a
|
||||
/// single libraries, one could provide entry points for the three libraries
|
||||
/// that are forwarders pointing to the common implementation.
|
||||
/// </remarks>
|
||||
[FieldOffset(7)] public uint ImportOrdinalNumber;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
662
BurnOutSharp.Models/LinearExecutable/Enums.cs
Normal file
662
BurnOutSharp.Models/LinearExecutable/Enums.cs
Normal file
@@ -0,0 +1,662 @@
|
||||
using System;
|
||||
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
[Flags]
|
||||
public enum BundleType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Unused Entry.
|
||||
/// </summary>
|
||||
UnusedEntry = 0x00,
|
||||
|
||||
/// <summary>
|
||||
/// 16-bit Entry.
|
||||
/// </summary>
|
||||
SixteenBitEntry = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// 286 Call Gate Entry.
|
||||
/// </summary>
|
||||
TwoEightySixCallGateEntry = 0x02,
|
||||
|
||||
/// <summary>
|
||||
/// 32-bit Entry.
|
||||
/// </summary>
|
||||
ThirtyTwoBitEntry = 0x03,
|
||||
|
||||
/// <summary>
|
||||
/// Forwarder Entry.
|
||||
/// </summary>
|
||||
ForwarderEntry = 0x04,
|
||||
|
||||
/// <summary>
|
||||
/// Parameter Typing Information Present.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This bit signifies that additional information is contained in the
|
||||
/// linear EXE module and will be used in the future for parameter type checking.
|
||||
/// </remarks>
|
||||
ParameterTypingInformationPresent = 0x80,
|
||||
}
|
||||
|
||||
public enum ByteOrder : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// little-endian
|
||||
/// </summary>
|
||||
LE = 0x00,
|
||||
|
||||
/// <summary>
|
||||
/// big-endian
|
||||
/// </summary>
|
||||
/// <remarks>non-zero</remarks>
|
||||
BE = 0x01,
|
||||
}
|
||||
|
||||
public enum CPUType : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// Intel 80286 or upwardly compatible
|
||||
/// </summary>
|
||||
Intel80286 = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// Intel 80386 or upwardly compatible
|
||||
/// </summary>
|
||||
Intel80386 = 0x02,
|
||||
|
||||
/// <summary>
|
||||
/// Intel 80486 or upwardly compatible
|
||||
/// </summary>
|
||||
Intel80486 = 0x03,
|
||||
|
||||
/// <summary>
|
||||
/// Intel 80586 or upwardly compatible
|
||||
/// </summary>
|
||||
Intel80586 = 0x04,
|
||||
|
||||
/// <summary>
|
||||
/// Intel i860 (N10) or compatible
|
||||
/// </summary>
|
||||
Inteli860 = 0x20,
|
||||
|
||||
/// <summary>
|
||||
/// Intel "N11" or compatible
|
||||
/// </summary>
|
||||
IntelN11 = 0x21,
|
||||
|
||||
/// <summary>
|
||||
/// MIPS Mark I (R2000, R3000) or compatible
|
||||
/// </summary>
|
||||
MIPSMarkI = 0x40,
|
||||
|
||||
/// <summary>
|
||||
/// MIPS Mark II ( R6000 ) or compatible
|
||||
/// </summary>
|
||||
MIPSMarkII = 0x41,
|
||||
|
||||
/// <summary>
|
||||
/// MIPS Mark III ( R4000 ) or compatible
|
||||
/// </summary>
|
||||
MIPSMarkIII = 0x42,
|
||||
}
|
||||
|
||||
public enum DebugFormatType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// 32-bit CodeView debugger format.
|
||||
/// </summary>
|
||||
CodeView32Bit = 0x00,
|
||||
|
||||
/// <summary>
|
||||
/// AIX debugger format.
|
||||
/// </summary>
|
||||
AIXDebugger = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// 16-bit CodeView debugger format.
|
||||
/// </summary>
|
||||
CodeView16Bit = 0x02,
|
||||
|
||||
/// <summary>
|
||||
/// 32-bit OS/2 PM debugger (IBM) format.
|
||||
/// </summary>
|
||||
OS2PM32Bit = 0x04,
|
||||
}
|
||||
|
||||
public enum DirectiveNumber : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// Resident Flag Mask.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Directive numbers with this bit set indicate that the directive data
|
||||
/// is in the resident area and will be kept resident in memory when the
|
||||
/// module is loaded.
|
||||
/// </remarks>
|
||||
ResidentFlagMask = 0x8000,
|
||||
|
||||
/// <summary>
|
||||
/// Verify Record Directive. (Verify record is a resident table.)
|
||||
/// </summary>
|
||||
VerifyRecordDirective = 0x8001,
|
||||
|
||||
/// <summary>
|
||||
/// Language Information Directive. (This is a non-resident table.)
|
||||
/// </summary>
|
||||
LanguageInformationDirective = 0x0002,
|
||||
|
||||
/// <summary>
|
||||
/// Co-Processor Required Support Table.
|
||||
/// </summary>
|
||||
CoProcessorRequiredSupportTable = 0x0003,
|
||||
|
||||
/// <summary>
|
||||
/// Thread State Initialization Directive.
|
||||
/// </summary>
|
||||
ThreadStateInitializationDirective = 0x0004,
|
||||
|
||||
// Additional directives can be added as needed in the future, as long as
|
||||
// they do not overlap previously defined directive numbers.
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum EntryFlags : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Exported entry flag.
|
||||
/// </summary>
|
||||
ExportedEntry = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// Parameter word count mask.
|
||||
/// </summary>
|
||||
ParameterWordCountMask = 0xF8,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum FixupRecordSourceType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Source mask.
|
||||
/// </summary>
|
||||
SourceMask = 0x0F,
|
||||
|
||||
/// <summary>
|
||||
/// Byte fixup (8-bits).
|
||||
/// </summary>
|
||||
ByteFixup = 0x00,
|
||||
|
||||
/// <summary>
|
||||
/// (undefined).
|
||||
/// </summary>
|
||||
Undefined1 = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// 16-bit Selector fixup (16-bits).
|
||||
/// </summary>
|
||||
SixteenBitSelectorFixup = 0x02,
|
||||
|
||||
/// <summary>
|
||||
/// 16:16 Pointer fixup (32-bits).
|
||||
/// </summary>
|
||||
SixteenSixteenPointerFixup = 0x03,
|
||||
|
||||
/// <summary>
|
||||
/// (undefined).
|
||||
/// </summary>
|
||||
Undefined4 = 0x04,
|
||||
|
||||
/// <summary>
|
||||
/// 16-bit Offset fixup (16-bits).
|
||||
/// </summary>
|
||||
SixteenBitOffsetFixup = 0x05,
|
||||
|
||||
/// <summary>
|
||||
/// 16:32 Pointer fixup (48-bits).
|
||||
/// </summary>
|
||||
SixteenThirtyTwoPointerFixup = 0x06,
|
||||
|
||||
/// <summary>
|
||||
/// 32-bit Offset fixup (32-bits).
|
||||
/// </summary>
|
||||
ThirtyTwoBitOffsetFixup = 0x07,
|
||||
|
||||
/// <summary>
|
||||
/// 32-bit Self-relative offset fixup (32-bits).
|
||||
/// </summary>
|
||||
ThirtyTwoBitSelfRelativeOffsetFixup = 0x08,
|
||||
|
||||
/// <summary>
|
||||
/// Fixup to Alias Flag.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When the 'Fixup to Alias' Flag is set, the source fixup refers to
|
||||
/// the 16:16 alias for the object. This is only valid for source types
|
||||
/// of 2, 3, and 6. For fixups such as this, the linker and loader will
|
||||
/// be required to perform additional checks such as ensuring that the
|
||||
/// target offset for this fixup is less than 64K.
|
||||
/// </remarks>
|
||||
FixupToAliasFlag = 0x10,
|
||||
|
||||
/// <summary>
|
||||
/// Source List Flag.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When the 'Source List' Flag is set, the SRCOFF field is compressed
|
||||
/// to a byte and contains the number of source offsets, and a list of source
|
||||
/// offsets follows the end of fixup record (after the optional additive value).
|
||||
/// </remarks>
|
||||
SourceListFlag = 0x20,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum FixupRecordTargetFlags : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Fixup target type mask.
|
||||
/// </summary>
|
||||
FixupTargetTypeMask = 0x03,
|
||||
|
||||
/// <summary>
|
||||
/// Internal reference.
|
||||
/// </summary>
|
||||
InternalReference = 0x00,
|
||||
|
||||
/// <summary>
|
||||
/// Imported reference by ordinal.
|
||||
/// </summary>
|
||||
ImportedReferenceByOrdinal = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// Imported reference by name.
|
||||
/// </summary>
|
||||
ImportedReferenceByName = 0x02,
|
||||
|
||||
/// <summary>
|
||||
/// Internal reference via entry table.
|
||||
/// </summary>
|
||||
InternalReferenceViaEntryTable = 0x03,
|
||||
|
||||
/// <summary>
|
||||
/// Additive Fixup Flag.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When set, an additive value trails the fixup record (before the optional
|
||||
/// source offset list).
|
||||
/// </remarks>
|
||||
AdditiveFixupFlag = 0x04,
|
||||
|
||||
/// <summary>
|
||||
/// Reserved. Must be zero.
|
||||
/// </summary>
|
||||
Reserved = 0x08,
|
||||
|
||||
/// <summary>
|
||||
/// 32-bit Target Offset Flag.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When set, the target offset is 32-bits, otherwise it is 16-bits.
|
||||
/// </remarks>
|
||||
ThirtyTwoBitTargetOffsetFlag = 0x10,
|
||||
|
||||
/// <summary>
|
||||
/// 32-bit Additive Fixup Flag.
|
||||
/// </summary>
|
||||
/// When set, the additive value is 32-bits, otherwise it is 16-bits.
|
||||
/// </remarks>
|
||||
ThirtyTwoBitAdditiveFixupFlag = 0x20,
|
||||
|
||||
/// <summary>
|
||||
/// 16-bit Object Number/Module Ordinal Flag.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When set, the object number or module ordinal number is 16-bits,
|
||||
/// otherwise it is 8-bits.
|
||||
/// </remarks>
|
||||
SixteenBitObjectNumberModuleOrdinalFlag = 0x40,
|
||||
|
||||
/// <summary>
|
||||
/// 8-bit Ordinal Flag.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When set, the ordinal number is 8-bits, otherwise it is 16-bits.
|
||||
/// </remarks>
|
||||
EightBitOrdinalFlag = 0x80,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ForwarderFlags : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Import by ordinal.
|
||||
/// </summary>
|
||||
ImportByOrdinal = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// Reserved for future use; should be zero.
|
||||
/// </summary>
|
||||
Reserved = 0xF7,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ModuleFlags : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// Reserved for system use.
|
||||
/// </summary>
|
||||
Reserved0 = 0x00000001,
|
||||
|
||||
/// <summary>
|
||||
/// Reserved for system use.
|
||||
/// </summary>
|
||||
Reserved1 = 0x00000002,
|
||||
|
||||
/// <summary>
|
||||
/// Per-Process Library Initialization.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The setting of this bit requires the EIP Object # and EIP fields
|
||||
/// to have valid values. If the EIP Object # and EIP fields are
|
||||
/// valid and this bit is NOT set, then Global Library Initialization
|
||||
/// is assumed. Setting this bit for an EXE file is invalid.
|
||||
/// </remarks>
|
||||
Initialization = 0x00000004,
|
||||
|
||||
/// <summary>
|
||||
/// Reserved for system use.
|
||||
/// </summary>
|
||||
Reserved3 = 0x00000008,
|
||||
|
||||
/// <summary>
|
||||
/// Internal fixups for the module have been applied.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The setting of this bit in a Linear Executable Module indicates that
|
||||
/// each object of the module has a preferred load address specified in
|
||||
/// the Object Table Reloc Base Addr. If the module's objects can not be
|
||||
/// loaded at these preferred addresses, then the relocation records that
|
||||
/// have been retained in the file data will be applied.
|
||||
/// </remarks>
|
||||
InternalFixupsApplied = 0x00000010,
|
||||
|
||||
/// <summary>
|
||||
/// External fixups for the module have been applied.
|
||||
/// </summary>
|
||||
ExternalFixupsApplied = 0x00000020,
|
||||
|
||||
/// <summary>
|
||||
/// Reserved for system use.
|
||||
/// </summary>
|
||||
Reserved6 = 0x00000040,
|
||||
|
||||
/// <summary>
|
||||
/// Reserved for system use.
|
||||
/// </summary>
|
||||
Reserved7 = 0x00000080,
|
||||
|
||||
/// <summary>
|
||||
/// Incompatible with PM windowing.
|
||||
/// </summary>
|
||||
IncompatibleWithPMWindowing = 0x00000100,
|
||||
|
||||
/// <summary>
|
||||
/// Incompatible with PM windowing.
|
||||
/// </summary>
|
||||
CompatibleWithPMWindowing = 0x00000200,
|
||||
|
||||
/// <summary>
|
||||
/// Uses PM windowing API.
|
||||
/// </summary>
|
||||
UsesPMWindowing = 0x00000300,
|
||||
|
||||
/// <summary>
|
||||
/// Reserved for system use.
|
||||
/// </summary>
|
||||
Reserved10 = 0x00000400,
|
||||
|
||||
/// <summary>
|
||||
/// Reserved for system use.
|
||||
/// </summary>
|
||||
Reserved11 = 0x00000800,
|
||||
|
||||
/// <summary>
|
||||
/// Reserved for system use.
|
||||
/// </summary>
|
||||
Reserved12 = 0x00001000,
|
||||
|
||||
/// <summary>
|
||||
/// Module is not loadable.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When the 'Module is not loadable' flag is set, it indicates that
|
||||
/// either errors were detected at link time or that the module is
|
||||
/// being incrementally linked and therefore can't be loaded.
|
||||
/// </remarks>
|
||||
ModuleNotLoadable = 0x00002000,
|
||||
|
||||
/// <summary>
|
||||
/// Reserved for system use.
|
||||
/// </summary>
|
||||
Reserved14 = 0x00004000,
|
||||
|
||||
/// <summary>
|
||||
/// Module type mask.
|
||||
/// </summary>
|
||||
ModuleTypeMask = 0x00038000,
|
||||
|
||||
/// <summary>
|
||||
/// Program module.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A module can not contain dynamic links to other modules that have
|
||||
/// the 'program module' type.
|
||||
/// </remarks>
|
||||
ProgramModule = 0x00000000,
|
||||
|
||||
/// <summary>
|
||||
/// Library module.
|
||||
/// </summary>
|
||||
LibraryModule = 0x00008000,
|
||||
|
||||
/// <summary>
|
||||
/// Protected Memory Library module.
|
||||
/// </summary>
|
||||
ProtectedMemoryLibraryModule = 0x00018000,
|
||||
|
||||
/// <summary>
|
||||
/// Physical Device Driver module.
|
||||
/// </summary>
|
||||
PhysicalDeviceDriverModule = 0x00020000,
|
||||
|
||||
/// <summary>
|
||||
/// Virtual Device Driver module.
|
||||
/// </summary>
|
||||
VirtualDeviceDriverModule = 0x00028000,
|
||||
|
||||
/// <summary>
|
||||
/// Per-process Library Termination.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The setting of this bit requires the EIP Object # and EIP fields
|
||||
/// to have valid values. If the EIP Object # and EIP fields are
|
||||
/// valid and this bit is NOT set, then Global Library Termination
|
||||
/// is assumed. Setting this bit for an EXE file is invalid.
|
||||
/// </remarks>
|
||||
PerProcessLibraryTermination = 0x40000000,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ObjectFlags : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// Readable Object.
|
||||
/// </summary>
|
||||
ReadableObject = 0x0001,
|
||||
|
||||
/// <summary>
|
||||
/// Writable Object.
|
||||
/// </summary>
|
||||
WritableObject = 0x0002,
|
||||
|
||||
/// <summary>
|
||||
/// Executable Object.
|
||||
/// </summary>
|
||||
ExecutableObject = 0x0004,
|
||||
|
||||
// The readable, writable and executable flags provide support for all possible
|
||||
// protections. In systems where all of these protections are not supported,
|
||||
// the loader will be responsible for making the appropriate protection match
|
||||
// for the system.
|
||||
|
||||
/// <summary>
|
||||
/// Resource Object.
|
||||
/// </summary>
|
||||
ResourceObject = 0x0008,
|
||||
|
||||
/// <summary>
|
||||
/// Discardable Object.
|
||||
/// </summary>
|
||||
DiscardableObject = 0x0010,
|
||||
|
||||
/// <summary>
|
||||
/// Object is Shared.
|
||||
/// </summary>
|
||||
Shared = 0x0020,
|
||||
|
||||
/// <summary>
|
||||
/// Object has Preload Pages.
|
||||
/// </summary>
|
||||
HasPreloadPages = 0x0040,
|
||||
|
||||
/// <summary>
|
||||
/// Object has Invalid Pages.
|
||||
/// </summary>
|
||||
HasInvalidPages = 0x0080,
|
||||
|
||||
/// <summary>
|
||||
/// Object has Zero Filled Pages.
|
||||
/// </summary>
|
||||
HasZeroFilledPages = 0x0100,
|
||||
|
||||
/// <summary>
|
||||
/// Object is Resident (valid for VDDs, PDDs only).
|
||||
/// </summary>
|
||||
Resident = 0x0200,
|
||||
|
||||
/// <summary>
|
||||
/// Object is Resident & Contiguous (VDDs, PDDs only).
|
||||
/// </summary>
|
||||
ResidentAndContiguous = 0x0300,
|
||||
|
||||
/// <summary>
|
||||
/// Object is Resident & 'long-lockable' (VDDs, PDDs only).
|
||||
/// </summary>
|
||||
ResidentAndLongLockable = 0x0400,
|
||||
|
||||
/// <summary>
|
||||
/// Reserved for system use.
|
||||
/// </summary>
|
||||
Reserved = 0x0800,
|
||||
|
||||
/// <summary>
|
||||
/// 16:16 Alias Required (80x86 Specific).
|
||||
/// </summary>
|
||||
AliasRequired = 0x1000,
|
||||
|
||||
/// <summary>
|
||||
/// Big/Default Bit Setting (80x86 Specific).
|
||||
/// </summary>
|
||||
BitSetting = 0x2000,
|
||||
|
||||
// The 'big/default' bit, for data segments, controls the setting of the
|
||||
// Big bit in the segment descriptor. (The Big bit, or B-bit, determines
|
||||
// whether ESP or SP is used as the stack pointer.) For code segments,
|
||||
// this bit controls the setting of the Default bit in the segment
|
||||
// descriptor. (The Default bit, or D-bit, determines whether the default
|
||||
// word size is 32-bits or 16-bits. It also affects the interpretation of
|
||||
// the instruction stream.)
|
||||
|
||||
/// <summary>
|
||||
/// Object is conforming for code (80x86 Specific).
|
||||
/// </summary>
|
||||
Conforming = 0x4000,
|
||||
|
||||
/// <summary>
|
||||
/// Object I/O privilege level (80x86 Specific). Only used for 16:16 Alias Objects.
|
||||
/// </summary>
|
||||
PrivilegeLevel = 0x8000,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ObjectPageFlags : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// Legal Physical Page in the module (Offset from Preload Page Section).
|
||||
/// </summary>
|
||||
LegalPhysicalPage = 0x0000,
|
||||
|
||||
/// <summary>
|
||||
/// Iterated Data Page (Offset from Iterated Data Pages Section).
|
||||
/// </summary>
|
||||
IteratedDataPage = 0x0001,
|
||||
|
||||
/// <summary>
|
||||
/// Invalid Page (zero).
|
||||
/// </summary>
|
||||
InvalidPage = 0x0002,
|
||||
|
||||
/// <summary>
|
||||
/// Zero Filled Page (zero).
|
||||
/// </summary>
|
||||
ZeroFilledPage = 0x0003,
|
||||
|
||||
/// <summary>
|
||||
/// Range of Pages.
|
||||
/// </summary>
|
||||
RangeOfPages = 0x0004,
|
||||
}
|
||||
|
||||
public enum OperatingSystem : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// Unknown (any "new-format" OS)
|
||||
/// </summary>
|
||||
Unknown = 0x00,
|
||||
|
||||
/// <summary>
|
||||
/// OS/2 (default)
|
||||
/// </summary>
|
||||
OS2 = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// Windows
|
||||
/// </summary>
|
||||
Windows = 0x02,
|
||||
|
||||
/// <summary>
|
||||
/// DOS 4.x
|
||||
/// </summary>
|
||||
DOS4x = 0x03,
|
||||
|
||||
/// <summary>
|
||||
/// Windows 386
|
||||
/// </summary>
|
||||
Windows386 = 0x04,
|
||||
}
|
||||
|
||||
public enum WordOrder : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// little-endian
|
||||
/// </summary>
|
||||
LE = 0x00,
|
||||
|
||||
/// <summary>
|
||||
/// big-endian
|
||||
/// </summary>
|
||||
/// <remarks>non-zero</remarks>
|
||||
BE = 0x01,
|
||||
}
|
||||
}
|
||||
101
BurnOutSharp.Models/LinearExecutable/Executable.cs
Normal file
101
BurnOutSharp.Models/LinearExecutable/Executable.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The `LINEAR` executable-file header contains information that the loader requires for
|
||||
/// segmented executable files. This information includes the linker version number, data
|
||||
/// specified by linker, data specified by resource compiler, tables of segment data, tables
|
||||
/// of resource data, and so on. The following illustrations shows the LE file header:
|
||||
/// </summary>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
public class Executable
|
||||
{
|
||||
/// <summary>
|
||||
/// MS-DOS executable stub
|
||||
/// </summary>
|
||||
public MSDOS.Executable Stub { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Information block
|
||||
/// </summary>
|
||||
public InformationBlock InformationBlock { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Object table
|
||||
/// </summary>
|
||||
public ObjectTableEntry[] ObjectTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Object page table
|
||||
/// </summary>
|
||||
public ObjectPageTableEntry[] ObjectPageTable { get; set; }
|
||||
|
||||
// TODO: Object iterate data map table [Does this exist?]
|
||||
|
||||
/// <summary>
|
||||
/// Resource table
|
||||
/// </summary>
|
||||
public ResourceTableEntry[] ResourceTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Resident Name table
|
||||
/// </summary>
|
||||
public ResidentNameTableEntry[] ResidentNameTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Entry table
|
||||
/// </summary>
|
||||
public EntryTableEntry[] EntryTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Module format directives table (optional)
|
||||
/// </summary>
|
||||
public ModuleFormatDirectivesTableEntry[] ModuleFormatDirectivesTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Verify record directive table (optional)
|
||||
/// </summary>
|
||||
public VerifyRecordDirectiveTableEntry[] VerifyRecordDirectiveTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Per-Page checksum table
|
||||
/// </summary>
|
||||
public PerPageChecksumTableEntry[] PerPageChecksumTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Fix-up page table
|
||||
/// </summary>
|
||||
public FixupPageTableEntry[] FixupPageTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Fix-up record table
|
||||
/// </summary>
|
||||
public FixupRecordTableEntry[] FixupRecordTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Import module name table
|
||||
/// </summary>
|
||||
public ImportModuleNameTableEntry[] ImportModuleNameTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Import procedure name table
|
||||
/// </summary>
|
||||
public ImportModuleProcedureNameTableEntry[] ImportModuleProcedureNameTable { get; set; }
|
||||
|
||||
// TODO: Preload Pages
|
||||
// TODO: Demand Load Pages
|
||||
// TODO: Iterated Pages
|
||||
|
||||
/// <summary>
|
||||
/// Non-Resident Name table
|
||||
/// </summary>
|
||||
public NonResidentNameTableEntry[] NonResidentNameTable { get; set; }
|
||||
|
||||
// TODO: Non-resident directives data (Undefined)
|
||||
|
||||
/// <summary>
|
||||
/// Debug information
|
||||
/// </summary>
|
||||
public DebugInformation DebugInformation { get; set; }
|
||||
}
|
||||
}
|
||||
36
BurnOutSharp.Models/LinearExecutable/FixupPageTableEntry.cs
Normal file
36
BurnOutSharp.Models/LinearExecutable/FixupPageTableEntry.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The Fixup Page Table provides a simple mapping of a logical page number
|
||||
/// to an offset into the Fixup Record Table for that page.
|
||||
///
|
||||
/// This table is parallel to the Object Page Table, except that there is
|
||||
/// one additional entry in this table to indicate the end of the Fixup
|
||||
/// Record Table.
|
||||
///
|
||||
/// The fixup records are kept in order by logical page in the fixup record
|
||||
/// table. This allows the end of each page's fixup records is defined by the
|
||||
/// offset for the next logical page's fixup records. This last entry provides
|
||||
/// support of this mechanism for the last page in the fixup page table.
|
||||
/// </summary>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class FixupPageTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Offset for fixup record for this page. (1 to n)
|
||||
/// Offset to the end of the fixup records. (n + 1)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field specifies the offset, from the beginning of the fixup record
|
||||
/// table, to the first fixup record for this page. (1 to n)
|
||||
///
|
||||
/// This field specifies the offset following the last fixup record in the
|
||||
/// fixup record table. This is the last entry in the fixup page table. (n + 1)
|
||||
/// </remarks>
|
||||
public uint Offset;
|
||||
}
|
||||
}
|
||||
363
BurnOutSharp.Models/LinearExecutable/FixupRecordTableEntry.cs
Normal file
363
BurnOutSharp.Models/LinearExecutable/FixupRecordTableEntry.cs
Normal file
@@ -0,0 +1,363 @@
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The Fixup Record Table contains entries for all fixups in the linear EXE module.
|
||||
/// The fixup records for a logical page are grouped together and kept in sorted
|
||||
/// order by logical page number. The fixups for each page are further sorted such
|
||||
/// that all external fixups and internal selector/pointer fixups come before
|
||||
/// internal non-selector/non-pointer fixups. This allows the loader to ignore
|
||||
/// internal fixups if the loader is able to load all objects at the addresses
|
||||
/// specified in the object table.
|
||||
/// </summary>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
public class FixupRecordTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Source type.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The source type specifies the size and type of the fixup to be performed
|
||||
/// on the fixup source.
|
||||
/// </remarks>
|
||||
public FixupRecordSourceType SourceType;
|
||||
|
||||
/// <summary>
|
||||
/// Target Flags.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The target flags specify how the target information is interpreted.
|
||||
/// </remarks>
|
||||
public FixupRecordTargetFlags TargetFlags;
|
||||
|
||||
#region Source List Flag
|
||||
|
||||
#region Set
|
||||
|
||||
/// <summary>
|
||||
/// Source offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field contains either an offset or a count depending on the Source
|
||||
/// List Flag. If the Source List Flag is set, a list of source offsets
|
||||
/// follows the additive field and this field contains the count of the
|
||||
/// entries in the source offset list. Otherwise, this is the single source
|
||||
/// offset for the fixup. Source offsets are relative to the beginning of
|
||||
/// the page where the fixup is to be made.
|
||||
///
|
||||
/// Note that for fixups that cross page boundaries, a separate fixup record
|
||||
/// is specified for each page. An offset is still used for the 2nd page but
|
||||
/// it now becomes a negative offset since the fixup originated on the
|
||||
/// preceding page. (For example, if only the last one byte of a 32-bit
|
||||
/// address is on the page to be fixed up, then the offset would have a value
|
||||
/// of -3.)
|
||||
/// </remarks>
|
||||
public ushort SourceOffset;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unset
|
||||
|
||||
/// <summary>
|
||||
/// Source offset list count.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field contains either an offset or a count depending on the Source
|
||||
/// List Flag. If the Source List Flag is set, a list of source offsets
|
||||
/// follows the additive field and this field contains the count of the
|
||||
/// entries in the source offset list. Otherwise, this is the single source
|
||||
/// offset for the fixup. Source offsets are relative to the beginning of
|
||||
/// the page where the fixup is to be made.
|
||||
///
|
||||
/// Note that for fixups that cross page boundaries, a separate fixup record
|
||||
/// is specified for each page. An offset is still used for the 2nd page but
|
||||
/// it now becomes a negative offset since the fixup originated on the
|
||||
/// preceding page. (For example, if only the last one byte of a 32-bit
|
||||
/// address is on the page to be fixed up, then the offset would have a value
|
||||
/// of -3.)
|
||||
/// </remarks>
|
||||
public byte SourceOffsetListCount;
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region OBJECT / TRGOFF
|
||||
|
||||
#region 16-bit Object Number/Module Ordinal Flag
|
||||
|
||||
#region Set
|
||||
|
||||
/// <summary>
|
||||
/// Target object number.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field is an index into the current module's Object Table to specify
|
||||
/// the target Object. It is a Byte value when the '16-bit Object Number/Module
|
||||
/// Ordinal Flag' bit in the target flags field is clear and a Word value when
|
||||
/// the bit is set.
|
||||
/// </remarks>
|
||||
public ushort TargetObjectNumberWORD;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unset
|
||||
|
||||
/// <summary>
|
||||
/// Target object number.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field is an index into the current module's Object Table to specify
|
||||
/// the target Object. It is a Byte value when the '16-bit Object Number/Module
|
||||
/// Ordinal Flag' bit in the target flags field is clear and a Word value when
|
||||
/// the bit is set.
|
||||
/// </remarks>
|
||||
public byte TargetObjectNumberByte;
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region 32-bit Target Offset Flag
|
||||
|
||||
#region Set
|
||||
|
||||
/// <summary>
|
||||
/// Target offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field is an offset into the specified target Object. It is not
|
||||
/// present when the Source Type specifies a 16-bit Selector fixup. It
|
||||
/// is a Word value when the '32-bit Target Offset Flag' bit in the target
|
||||
/// flags field is clear and a Dword value when the bit is set.
|
||||
/// </remarks>
|
||||
public uint TargetOffsetDWORD;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unset
|
||||
|
||||
/// <summary>
|
||||
/// Target offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field is an offset into the specified target Object. It is not
|
||||
/// present when the Source Type specifies a 16-bit Selector fixup. It
|
||||
/// is a Word value when the '32-bit Target Offset Flag' bit in the target
|
||||
/// flags field is clear and a Dword value when the bit is set.
|
||||
/// </remarks>
|
||||
public ushort TargetOffsetWORD;
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region 16-bit Object Number/Module Ordinal Flag [Incompatible with OBJECT / TRGOFF]
|
||||
|
||||
#region Set
|
||||
|
||||
/// <summary>
|
||||
/// Ordinal index into the Import Module Name Table.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is an ordered index in to the Import Module Name Table for
|
||||
/// the module containing the procedure entry point. It is a Byte value
|
||||
/// when the '16-bit Object Number/Module Ordinal' Flag bit in the target
|
||||
/// flags field is clear and a Word value when the bit is set. The loader
|
||||
/// creates a table of pointers with each pointer in the table corresponds
|
||||
/// to the modules named in the Import Module Name Table. This value is used
|
||||
/// by the loader to index into this table created by the loader to locate
|
||||
/// the referenced module.
|
||||
/// </remarks>
|
||||
public ushort OrdinalIndexImportModuleNameTableWORD;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unset
|
||||
|
||||
/// <summary>
|
||||
/// Ordinal index into the Import Module Name Table.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is an ordered index in to the Import Module Name Table for
|
||||
/// the module containing the procedure entry point. It is a Byte value
|
||||
/// when the '16-bit Object Number/Module Ordinal' Flag bit in the target
|
||||
/// flags field is clear and a Word value when the bit is set. The loader
|
||||
/// creates a table of pointers with each pointer in the table corresponds
|
||||
/// to the modules named in the Import Module Name Table. This value is used
|
||||
/// by the loader to index into this table created by the loader to locate
|
||||
/// the referenced module.
|
||||
/// </remarks>
|
||||
public byte OrdinalIndexImportModuleNameTableByte;
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region MOD ORD# / PROCEDURE NAME OFFSET / ADDITIVE
|
||||
|
||||
#region 32-bit Target Offset Flag
|
||||
|
||||
#region Set
|
||||
|
||||
/// <summary>
|
||||
/// Offset into the Import Procedure Name Table.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field is an offset into the Import Procedure Name Table. It is
|
||||
/// a Word value when the '32-bit Target Offset Flag' bit in the target
|
||||
/// flags field is clear and a Dword value when the bit is set.
|
||||
/// </remarks>
|
||||
public uint OffsetImportProcedureNameTableDWORD;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unset
|
||||
|
||||
/// <summary>
|
||||
/// Offset into the Import Procedure Name Table.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field is an offset into the Import Procedure Name Table. It is
|
||||
/// a Word value when the '32-bit Target Offset Flag' bit in the target
|
||||
/// flags field is clear and a Dword value when the bit is set.
|
||||
/// </remarks>
|
||||
public ushort OffsetImportProcedureNameTableWORD;
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region MOD ORD# / IMPORT ORD / ADDITIVE
|
||||
|
||||
#region 8-bit Ordinal Flag
|
||||
|
||||
#region Set
|
||||
|
||||
/// <summary>
|
||||
/// Imported ordinal number.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the imported procedure's ordinal number. It is a Byte value when the
|
||||
/// '8-bit Ordinal' bit in the target flags field is set. Otherwise it is a Word value
|
||||
/// when the '32-bit Target Offset Flag' bit in the target flags field is clear and a
|
||||
/// Dword value when the bit is set.
|
||||
/// </remarks>
|
||||
public byte ImportedOrdinalNumberByte;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unset
|
||||
|
||||
#region 32-bit Target Offset Flag
|
||||
|
||||
#region Set
|
||||
|
||||
/// <summary>
|
||||
/// Imported ordinal number.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the imported procedure's ordinal number. It is a Byte value when the
|
||||
/// '8-bit Ordinal' bit in the target flags field is set. Otherwise it is a Word value
|
||||
/// when the '32-bit Target Offset Flag' bit in the target flags field is clear and a
|
||||
/// Dword value when the bit is set.
|
||||
/// </remarks>
|
||||
public uint ImportedOrdinalNumberDWORD;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unset
|
||||
|
||||
/// <summary>
|
||||
/// Imported ordinal number.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the imported procedure's ordinal number. It is a Byte value when the
|
||||
/// '8-bit Ordinal' bit in the target flags field is set. Otherwise it is a Word value
|
||||
/// when the '32-bit Target Offset Flag' bit in the target flags field is clear and a
|
||||
/// Dword value when the bit is set.
|
||||
/// </remarks>
|
||||
public uint ImportedOrdinalNumberWORD;
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Additive Fixup Flag [Incompatible with OBJECT / TRGOFF]
|
||||
|
||||
#region Set
|
||||
|
||||
#region 32-bit Additive Fixup Flag
|
||||
|
||||
#region Set
|
||||
|
||||
/// <summary>
|
||||
/// Additive fixup value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field exists in the fixup record only when the 'Additive Fixup Flag'
|
||||
/// bit in the target flags field is set. When the 'Additive Fixup Flag' is
|
||||
/// clear the fixup record does not contain this field and is immediately
|
||||
/// followed by the next fixup record (or by the source offset list for this
|
||||
/// fixup record).
|
||||
///
|
||||
/// This value is added to the address derived from the target entry point.
|
||||
/// This field is a Word value when the '32-bit Additive Flag' bit in the
|
||||
/// target flags field is clear and a Dword value when the bit is set.
|
||||
/// </remarks>
|
||||
public uint AdditiveFixupValueDWORD;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unset
|
||||
|
||||
/// <summary>
|
||||
/// Additive fixup value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field exists in the fixup record only when the 'Additive Fixup Flag'
|
||||
/// bit in the target flags field is set. When the 'Additive Fixup Flag' is
|
||||
/// clear the fixup record does not contain this field and is immediately
|
||||
/// followed by the next fixup record (or by the source offset list for this
|
||||
/// fixup record).
|
||||
///
|
||||
/// This value is added to the address derived from the target entry point.
|
||||
/// This field is a Word value when the '32-bit Additive Flag' bit in the
|
||||
/// target flags field is clear and a Dword value when the bit is set.
|
||||
/// </remarks>
|
||||
public ushort AdditiveFixupValueWORD;
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region SCROFFn
|
||||
|
||||
/// <summary>
|
||||
/// Source offset list.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This list is present if the Source List Flag is set in the Target Flags field.
|
||||
/// The number of entries in the source offset list is defined in the SRCOFF/CNT
|
||||
/// field. The source offsets are relative to the beginning of the page where the
|
||||
/// fixups are to be made.
|
||||
/// </remarks>
|
||||
public ushort[] SourceOffsetList;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The import module name table defines the module name strings imported through
|
||||
/// dynamic link references. These strings are referenced through the imported
|
||||
/// relocation fixups.
|
||||
///
|
||||
/// To determine the length of the import module name table subtract the import
|
||||
/// module name table offset from the import procedure name table offset. These
|
||||
/// values are located in the linear EXE header. The end of the import module
|
||||
/// name table is not terminated by a special character, it is followed directly
|
||||
/// by the import procedure name table.
|
||||
///
|
||||
/// The strings are CASE SENSITIVE and NOT NULL TERMINATED.
|
||||
/// </summary>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ImportModuleNameTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// String Length.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This defines the length of the string in bytes. The length of each
|
||||
/// ascii name string is limited to 127 characters.
|
||||
/// </remarks>
|
||||
public byte Length;
|
||||
|
||||
/// <summary>
|
||||
/// ASCII String.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a variable length string with it's length defined in bytes by
|
||||
/// the LEN field. The string is case sensitive and is not null terminated.
|
||||
/// </remarks>
|
||||
public byte[] Name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The import procedure name table defines the procedure name strings imported
|
||||
/// by this module through dynamic link references. These strings are referenced
|
||||
/// through the imported relocation fixups.
|
||||
///
|
||||
/// To determine the length of the import procedure name table add the fixup
|
||||
/// section size to the fixup page table offset, this computes the offset to
|
||||
/// the end of the fixup section, then subtract the import procedure name table
|
||||
/// offset. These values are located in the linear EXE header. The import
|
||||
/// procedure name table is followed by the data pages section. Since the data
|
||||
/// pages section is aligned on a 'page size' boundary, padded space may exist
|
||||
/// between the last import name string and the first page in the data pages
|
||||
/// section. If this padded space exists it will be zero filled.
|
||||
///
|
||||
/// The strings are CASE SENSITIVE and NOT NULL TERMINATED.
|
||||
/// </summary>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ImportModuleProcedureNameTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// String Length.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This defines the length of the string in bytes. The length of each
|
||||
/// ascii name string is limited to 127 characters.
|
||||
///
|
||||
/// The high bit in the LEN field (bit 7) is defined as an Overload bit.
|
||||
/// This bit signifies that additional information is contained in the
|
||||
/// linear EXE module and will be used in the future for parameter type
|
||||
/// checking.
|
||||
/// </remarks>
|
||||
public byte Length;
|
||||
|
||||
/// <summary>
|
||||
/// ASCII String.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a variable length string with it's length defined in bytes by
|
||||
/// the LEN field. The string is case sensitive and is not null terminated.
|
||||
/// </remarks>
|
||||
public byte[] Name;
|
||||
}
|
||||
}
|
||||
426
BurnOutSharp.Models/LinearExecutable/InformationBlock.cs
Normal file
426
BurnOutSharp.Models/LinearExecutable/InformationBlock.cs
Normal file
@@ -0,0 +1,426 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The `information block` in the LE header contains the linker version number,
|
||||
/// length of various tables that further describe the executable file, the
|
||||
/// offsets from the beginning of the header to the beginning of these tables,
|
||||
/// the heap and stack sizes, and so on. The following list summarizes the
|
||||
/// contents of the header `information block` (the locations are relative to
|
||||
/// the beginning of the block):
|
||||
/// </summary>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class InformationBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the signature word
|
||||
/// 'LE' (4Ch 45H)
|
||||
/// 'LX' (4Ch 58H)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The signature word is used by the loader to identify the EXE
|
||||
/// file as a valid 32-bit Linear Executable Module Format.
|
||||
/// </remarks>
|
||||
public char[] Signature;
|
||||
|
||||
/// <summary>
|
||||
/// Byte Ordering.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This byte specifies the byte ordering for the linear EXE format.
|
||||
/// </remarks>
|
||||
public ByteOrder ByteOrder;
|
||||
|
||||
/// <summary>
|
||||
/// Word Ordering.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This byte specifies the Word ordering for the linear EXE format.
|
||||
/// </remarks>
|
||||
public WordOrder WordOrder;
|
||||
|
||||
/// <summary>
|
||||
/// Linear EXE Format Level.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Linear EXE Format Level is set to 0 for the initial version of the
|
||||
/// 32-bit linear EXE format. Each incompatible change to the linear EXE
|
||||
/// format must increment this value. This allows the system to recognized
|
||||
/// future EXE file versions so that an appropriate error message may be
|
||||
/// displayed if an attempt is made to load them.
|
||||
/// </remarks>
|
||||
public uint ExecutableFormatLevel;
|
||||
|
||||
/// <summary>
|
||||
/// Module CPU Type.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field specifies the type of CPU required by this module to run.
|
||||
/// </remarks>
|
||||
public CPUType CPUType;
|
||||
|
||||
/// <summary>
|
||||
/// Module OS Type.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field specifies the type of Operating system required to run this module.
|
||||
/// </remarks>
|
||||
public OperatingSystem ModuleOS;
|
||||
|
||||
/// <summary>
|
||||
/// Module version
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is useful for differentiating between revisions of dynamic linked modules.
|
||||
/// This value is specified at link time by the user.
|
||||
/// </remarks>
|
||||
public uint ModuleVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Module type flags
|
||||
/// </summary>
|
||||
public ModuleFlags ModuleTypeFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Number of pages in module.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field specifies the number of pages physically contained in this module.
|
||||
/// In other words, pages containing either enumerated or iterated data, or
|
||||
/// zero-fill pages that have relocations, not invalid or zero-fill pages implied
|
||||
/// by the Virtual Size in the Object Table being larger than the number of pages
|
||||
/// actually in the linear EXE file. These pages are contained in the 'preload
|
||||
/// pages', 'demand load pages' and 'iterated data pages' sections of the linear
|
||||
/// EXE module. This is used to determine the size of the page information tables
|
||||
/// in the linear EXE module.
|
||||
/// </remarks>
|
||||
public uint ModuleNumberPages;
|
||||
|
||||
/// <summary>
|
||||
/// The Object number to which the Entry Address is relative.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This specifies the object to which the Entry Address is relative. This must be
|
||||
/// a nonzero value for a program module to be correctly loaded. A zero value for
|
||||
/// a library module indicates that no library entry routine exists. If this value
|
||||
/// is zero, then both the Per-process Library Initialization bit and the Per-process
|
||||
/// Library Termination bit must be clear in the module flags, or else the loader
|
||||
/// will fail to load the module. Further, if the Per-process Library Termination bit
|
||||
/// is set, then the object to which this field refers must be a 32-bit object (i.e.,
|
||||
/// the Big/Default bit must be set in the object flags; see below).
|
||||
/// </remarks>
|
||||
public uint InitialObjectCS;
|
||||
|
||||
/// <summary>
|
||||
/// Entry Address of module.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Entry Address is the starting address for program modules and the library
|
||||
/// initialization and Library termination address for library modules.
|
||||
/// </remarks>
|
||||
public uint InitialEIP;
|
||||
|
||||
/// <summary>
|
||||
/// The Object number to which the ESP is relative.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This specifies the object to which the starting ESP is relative. This must be a
|
||||
/// nonzero value for a program module to be correctly loaded. This field is ignored
|
||||
/// for a library module.
|
||||
/// </remarks>
|
||||
public uint InitialObjectSS;
|
||||
|
||||
/// <summary>
|
||||
/// Starting stack address of module.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The ESP defines the starting stack pointer address for program modules. A zero
|
||||
/// value in this field indicates that the stack pointer is to be initialized to the
|
||||
/// highest address/offset in the object. This field is ignored for a library module.
|
||||
/// </remarks>
|
||||
public uint InitialESP;
|
||||
|
||||
/// <summary>
|
||||
/// The size of one page for this system.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field specifies the page size used by the linear EXE format and the system.
|
||||
/// For the initial version of this linear EXE format the page size is 4Kbytes.
|
||||
/// (The 4K page size is specified by a value of 4096 in this field.)
|
||||
/// </remarks>
|
||||
public uint MemoryPageSize;
|
||||
|
||||
/// <summary>
|
||||
/// The shift left bits for page offsets.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field gives the number of bit positions to shift left when interpreting
|
||||
/// the Object Page Table entries' page offset field. This determines the alignment
|
||||
/// of the page information in the file. For example, a value of 4 in this field
|
||||
/// would align all pages in the Data Pages and Iterated Pages sections on 16 byte
|
||||
/// (paragraph) boundaries. A Page Offset Shift of 9 would align all pages on a
|
||||
/// 512 byte (disk sector) basis. The default value for this field is 12 (decimal),
|
||||
/// which give a 4096 byte alignment. All other offsets are byte aligned.
|
||||
/// </remarks>
|
||||
public uint BytesOnLastPage;
|
||||
|
||||
/// <summary>
|
||||
/// Total size of the fixup information in bytes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This includes the following 4 tables:
|
||||
/// - Fixup Page Table
|
||||
/// - Fixup Record Table
|
||||
/// - Import Module name Table
|
||||
/// - Import Procedure Name Table
|
||||
/// </remarks>
|
||||
public uint FixupSectionSize;
|
||||
|
||||
/// <summary>
|
||||
/// Checksum for fixup information.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a cryptographic checksum covering all of the fixup information. The
|
||||
/// checksum for the fixup information is kept separate because the fixup data is
|
||||
/// not always loaded into main memory with the 'loader section'. If the checksum
|
||||
/// feature is not implemented, then the linker will set these fields to zero.
|
||||
/// </remarks>
|
||||
public uint FixupSectionChecksum;
|
||||
|
||||
/// <summary>
|
||||
/// Size of memory resident tables.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the total size in bytes of the tables required to be memory resident
|
||||
/// for the module, while the module is in use. This total size includes all
|
||||
/// tables from the Object Table down to and including the Per-Page Checksum Table.
|
||||
/// </remarks>
|
||||
public uint LoaderSectionSize;
|
||||
|
||||
/// <summary>
|
||||
/// Checksum for loader section.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a cryptographic checksum covering all of the loader section information.
|
||||
/// If the checksum feature is not implemented, then the linker will set these fields
|
||||
/// to zero.
|
||||
/// </remarks>
|
||||
public uint LoaderSectionChecksum;
|
||||
|
||||
/// <summary>
|
||||
/// Object Table offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This offset is relative to the beginning of the linear EXE header.
|
||||
/// </remarks>
|
||||
public uint ObjectTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Object Table Count.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This defines the number of entries in Object Table.
|
||||
/// </remarks>
|
||||
public uint ObjectTableCount;
|
||||
|
||||
/// <summary>
|
||||
/// Object Page Table offset
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This offset is relative to the beginning of the linear EXE header.
|
||||
/// </remarks>
|
||||
public uint ObjectPageMapOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Object Iterated Pages offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This offset is relative to the beginning of the linear EXE header.
|
||||
/// </remarks>
|
||||
public uint ObjectIterateDataMapOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Resource Table offset
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This offset is relative to the beginning of the linear EXE header.
|
||||
/// </remarks>
|
||||
public uint ResourceTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Number of entries in Resource Table.
|
||||
/// </summary>
|
||||
public uint ResourceTableCount;
|
||||
|
||||
/// <summary>
|
||||
/// Resident Name Table offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This offset is relative to the beginning of the linear EXE header.
|
||||
/// </remarks>
|
||||
public uint ResidentNamesTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Entry Table offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This offset is relative to the beginning of the linear EXE header.
|
||||
/// </remarks>
|
||||
public uint EntryTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Module Format Directives Table offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This offset is relative to the beginning of the linear EXE header.
|
||||
/// </remarks>
|
||||
public uint ModuleDirectivesTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Number of Module Format Directives in the Table.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field specifies the number of entries in the
|
||||
/// Module Format Directives Table.
|
||||
/// </remarks>
|
||||
public uint ModuleDirectivesCount;
|
||||
|
||||
/// <summary>
|
||||
/// Fixup Page Table offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This offset is relative to the beginning of the linear EXE header.
|
||||
/// </remarks>
|
||||
public uint FixupPageTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Fixup Record Table offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This offset is relative to the beginning of the linear EXE header.
|
||||
/// </remarks>
|
||||
public uint FixupRecordTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Import Module Name Table offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This offset is relative to the beginning of the linear EXE header.
|
||||
/// </remarks>
|
||||
public uint ImportedModulesNameTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// The number of entries in the Import Module Name Table.
|
||||
/// </summary>
|
||||
public uint ImportedModulesCount;
|
||||
|
||||
/// <summary>
|
||||
/// Import Procedure Name Table offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This offset is relative to the beginning of the linear EXE header.
|
||||
/// </remarks>
|
||||
public uint ImportProcedureNameTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Per-page Checksum Table offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This offset is relative to the beginning of the linear EXE header.
|
||||
/// </remarks>
|
||||
public uint PerPageChecksumTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Data Pages Offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This offset is relative to the beginning of the EXE file.
|
||||
/// </remarks>
|
||||
public uint DataPagesOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Number of Preload pages for this module.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that OS/2 2.0 does not respect the preload of pages as specified
|
||||
/// in the executable file for performance reasons.
|
||||
/// </remarks>
|
||||
public uint PreloadPageCount;
|
||||
|
||||
/// <summary>
|
||||
/// Non-Resident Name Table offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This offset is relative to the beginning of the EXE file.
|
||||
/// </remarks>
|
||||
public uint NonResidentNamesTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Number of bytes in the Non-resident name table.
|
||||
/// </summary>
|
||||
public uint NonResidentNamesTableLength;
|
||||
|
||||
/// <summary>
|
||||
/// Non-Resident Name Table Checksum.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a cryptographic checksum of the Non-Resident Name Table.
|
||||
/// </remarks>
|
||||
public uint NonResidentNamesTableChecksum;
|
||||
|
||||
/// <summary>
|
||||
/// The Auto Data Segment Object number.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the object number for the Auto Data Segment used by 16-bit modules.
|
||||
/// This field is supported for 16-bit compatibility only and is not used by
|
||||
/// 32-bit modules.
|
||||
/// </remarks>
|
||||
public uint AutomaticDataObject;
|
||||
|
||||
/// <summary>
|
||||
/// Debug Information offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This offset is relative to the beginning of the linear EXE header.
|
||||
/// </remarks>
|
||||
public uint DebugInformationOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Debug Information length.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The length of the debug information in bytes.
|
||||
/// </remarks>
|
||||
public uint DebugInformationLength;
|
||||
|
||||
/// <summary>
|
||||
/// Instance pages in preload section.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The number of instance data pages found in the preload section.
|
||||
/// </remarks>
|
||||
public uint PreloadInstancePagesNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Instance pages in demand section.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The number of instance data pages found in the demand section.
|
||||
/// </remarks>
|
||||
public uint DemandInstancePagesNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Heap size added to the Auto DS Object.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The heap size is the number of bytes added to the Auto Data Segment
|
||||
/// by the loader. This field is supported for 16-bit compatibility only and
|
||||
/// is not used by 32-bit modules.
|
||||
/// </remarks>
|
||||
public uint ExtraHeapAllocation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The Module Format Directives Table is an optional table that allows additional
|
||||
/// options to be specified. It also allows for the extension of the linear EXE
|
||||
/// format by allowing additional tables of information to be added to the linear
|
||||
/// EXE module without affecting the format of the linear EXE header. Likewise,
|
||||
/// module format directives provide a place in the linear EXE module for
|
||||
/// 'temporary tables' of information, such as incremental linking information
|
||||
/// and statistic information gathered on the module. When there are no module
|
||||
/// format directives for a linear EXE module, the fields in the linear EXE header
|
||||
/// referencing the module format directives table are zero.
|
||||
/// </summary>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ModuleFormatDirectivesTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Directive number.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The directive number specifies the type of directive defined. This can be
|
||||
/// used to determine the format of the information in the directive data.
|
||||
/// </remarks>
|
||||
public DirectiveNumber DirectiveNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Directive data length.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This specifies the length in byte of the directive data for this directive number.
|
||||
/// </remarks>
|
||||
public ushort DirectiveDataLength;
|
||||
|
||||
/// <summary>
|
||||
/// Directive data offset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the offset to the directive data for this directive number. It is relative
|
||||
/// to beginning of linear EXE header for a resident table, and relative to the
|
||||
/// beginning of the EXE file for non-resident tables.
|
||||
/// </remarks>
|
||||
public uint DirectiveDataOffset;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The resident and non-resident name tables define the ASCII names and ordinal
|
||||
/// numbers for exported entries in the module. In addition the first entry in
|
||||
/// the resident name table contains the module name. These tables are used to
|
||||
/// translate a procedure name string into an ordinal number by searching for a
|
||||
/// matching name string. The ordinal number is used to locate the entry point
|
||||
/// information in the entry table.
|
||||
///
|
||||
/// The resident name table is kept resident in system memory while the module is
|
||||
/// loaded.It is intended to contain the exported entry point names that are
|
||||
/// frequently dynamically linked to by name.Non-resident names are not kept in
|
||||
/// memory and are read from the EXE file when a dynamic link reference is made.
|
||||
/// Exported entry point names that are infrequently dynamically linked to by name
|
||||
/// or are commonly referenced by ordinal number should be placed in the
|
||||
/// non-resident name table.The trade off made for references by name is performance
|
||||
/// vs memory usage.
|
||||
///
|
||||
/// Import references by name require these tables to be searched to obtain the entry
|
||||
/// point ordinal number.Import references by ordinal number provide the fastest
|
||||
/// lookup since the search of these tables is not required.
|
||||
///
|
||||
/// The strings are CASE SENSITIVE and are NOT NULL TERMINATED.
|
||||
/// </summary>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class NonResidentNameTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// String Length.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This defines the length of the string in bytes. A zero length indicates there are
|
||||
/// no more entries in table. The length of each ascii name string is limited to 127
|
||||
/// characters.
|
||||
///
|
||||
/// The high bit in the LEN field (bit 7) is defined as an Overload bit. This bit
|
||||
/// signifies that additional information is contained in the linear EXE module and
|
||||
/// will be used in the future for parameter type checking.
|
||||
/// </remarks>
|
||||
public byte Length;
|
||||
|
||||
/// <summary>
|
||||
/// ASCII String.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a variable length string with it's length defined in bytes by the LEN field.
|
||||
/// The string is case case sensitive and is not null terminated.
|
||||
/// </remarks>
|
||||
public byte[] Name;
|
||||
|
||||
/// <summary>
|
||||
/// Ordinal number.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The ordinal number in an ordered index into the entry table for this entry point.
|
||||
/// </remarks>
|
||||
public ushort OrdinalNumber;
|
||||
}
|
||||
}
|
||||
60
BurnOutSharp.Models/LinearExecutable/ObjectPageTableEntry.cs
Normal file
60
BurnOutSharp.Models/LinearExecutable/ObjectPageTableEntry.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The Object page table provides information about a logical page in an object.
|
||||
/// A logical page may be an enumerated page, a pseudo page or an iterated page.
|
||||
/// The structure of the object page table in conjunction with the structure of
|
||||
/// the object table allows for efficient access of a page when a page fault occurs,
|
||||
/// while still allowing the physical page data to be located in the preload page,
|
||||
/// demand load page or iterated data page sections in the linear EXE module. The
|
||||
/// logical page entries in the Object Page Table are numbered starting from one.
|
||||
/// The Object Page Table is parallel to the Fixup Page Table as they are both
|
||||
/// indexed by the logical page number.
|
||||
/// </summary>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ObjectPageTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Offset to the page data in the EXE file.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field, when bit shifted left by the PAGE OFFSET SHIFT from the module
|
||||
/// header, specifies the offset from the beginning of the Preload Page section
|
||||
/// of the physical page data in the EXE file that corresponds to this logical
|
||||
/// page entry. The page data may reside in the Preload Pages, Demand Load Pages
|
||||
/// or the Iterated Data Pages sections.
|
||||
///
|
||||
/// If the FLAGS field specifies that this is a zero-Filled page then the PAGE
|
||||
/// DATA OFFSET field will contain a 0.
|
||||
///
|
||||
/// If the logical page is specified as an iterated data page, as indicated by
|
||||
/// the FLAGS field, then this field specifies the offset into the Iterated Data
|
||||
/// Pages section.
|
||||
///
|
||||
/// The logical page number (Object Page Table index), is used to index the Fixup
|
||||
/// Page Table to find any fixups associated with the logical page.
|
||||
/// </remarks>
|
||||
public uint PageDataOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Number of bytes of data for this page.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field specifies the actual number of bytes that represent the page in the
|
||||
/// file. If the PAGE SIZE field from the module header is greater than the value
|
||||
/// of this field and the FLAGS field indicates a Legal Physical Page, the remaining
|
||||
/// bytes are to be filled with zeros. If the FLAGS field indicates an Iterated Data
|
||||
/// Page, the iterated data records will completely fill out the remainder.
|
||||
/// </remarks>
|
||||
public ushort DataSize;
|
||||
|
||||
/// <summary>
|
||||
/// Attributes specifying characteristics of this logical page.
|
||||
/// </summary>
|
||||
public ObjectPageFlags Flags;
|
||||
}
|
||||
}
|
||||
82
BurnOutSharp.Models/LinearExecutable/ObjectTableEntry.cs
Normal file
82
BurnOutSharp.Models/LinearExecutable/ObjectTableEntry.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The object table contains information that describes each segment in
|
||||
/// an executable file. This information includes segment length, segment
|
||||
/// type, and segment-relocation data. The following list summarizes the
|
||||
/// values found in in the segment table (the locations are relative to
|
||||
/// the beginning of each entry):
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Entries in the Object Table are numbered starting from one.
|
||||
/// </remarks>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ObjectTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Virtual memory size.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the size of the object that will be allocated when the object
|
||||
/// is loaded. The object's virtual size (rounded up to the page size value)
|
||||
/// must be greater than or equal to the total size of the pages in the EXE
|
||||
/// file for the object. This memory size must also be large enough to
|
||||
/// contain all of the iterated data and uninitialized data in the EXE file.
|
||||
/// </remarks>
|
||||
public uint VirtualSegmentSize;
|
||||
|
||||
/// <summary>
|
||||
/// Relocation Base Address.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The relocation base address the object is currently relocated to. If the
|
||||
/// internal relocation fixups for the module have been removed, this is the
|
||||
/// address the object will be allocated at by the loader.
|
||||
/// </remarks>
|
||||
public uint RelocationBaseAddress;
|
||||
|
||||
/// <summary>
|
||||
/// Flag bits for the object.
|
||||
/// </summary>
|
||||
public ObjectFlags ObjectFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Object Page Table Index.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This specifies the number of the first object page table entry for this object.
|
||||
/// The object page table specifies where in the EXE file a page can be found for
|
||||
/// a given object and specifies per-page attributes.
|
||||
///
|
||||
/// The object table entries are ordered by logical page in the object table. In
|
||||
/// other words the object table entries are sorted based on the object page table
|
||||
/// index value.
|
||||
/// </remarks>
|
||||
public uint PageTableIndex;
|
||||
|
||||
/// <summary>
|
||||
/// # of object page table entries for this object.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Any logical pages at the end of an object that do not have an entry in the object
|
||||
/// page table associated with them are handled as zero filled or invalid pages by
|
||||
/// the loader.
|
||||
///
|
||||
/// When the last logical pages of an object are not specified with an object page
|
||||
/// table entry, they are treated as either zero filled pages or invalid pages based
|
||||
/// on the last entry in the object page table for that object. If the last entry
|
||||
/// was neither a zero filled or invalid page, then the additional pages are treated
|
||||
/// as zero filled pages.
|
||||
/// </remarks>
|
||||
public uint PageTableEntries;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved for future use. Must be set to zero.
|
||||
/// </summary>
|
||||
public uint Reserved;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The Per-Page Checksum table provides space for a cryptographic checksum for
|
||||
/// each physical page in the EXE file.
|
||||
///
|
||||
/// The checksum table is arranged such that the first entry in the table corresponds
|
||||
/// to the first logical page of code/data in the EXE file (usually a preload page)
|
||||
/// and the last entry corresponds to the last logical page in the EXE file (usually
|
||||
/// a iterated data page).
|
||||
/// </summary>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class PerPageChecksumTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Cryptographic checksum.
|
||||
/// </summary>
|
||||
public uint Checksum;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The resident and non-resident name tables define the ASCII names and ordinal
|
||||
/// numbers for exported entries in the module. In addition the first entry in
|
||||
/// the resident name table contains the module name. These tables are used to
|
||||
/// translate a procedure name string into an ordinal number by searching for a
|
||||
/// matching name string. The ordinal number is used to locate the entry point
|
||||
/// information in the entry table.
|
||||
///
|
||||
/// The resident name table is kept resident in system memory while the module is
|
||||
/// loaded.It is intended to contain the exported entry point names that are
|
||||
/// frequently dynamically linked to by name.Non-resident names are not kept in
|
||||
/// memory and are read from the EXE file when a dynamic link reference is made.
|
||||
/// Exported entry point names that are infrequently dynamically linked to by name
|
||||
/// or are commonly referenced by ordinal number should be placed in the
|
||||
/// non-resident name table.The trade off made for references by name is performance
|
||||
/// vs memory usage.
|
||||
///
|
||||
/// Import references by name require these tables to be searched to obtain the entry
|
||||
/// point ordinal number.Import references by ordinal number provide the fastest
|
||||
/// lookup since the search of these tables is not required.
|
||||
///
|
||||
/// The strings are CASE SENSITIVE and are NOT NULL TERMINATED.
|
||||
/// </summary>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ResidentNameTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// String Length.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This defines the length of the string in bytes. A zero length indicates there are
|
||||
/// no more entries in table. The length of each ascii name string is limited to 127
|
||||
/// characters.
|
||||
///
|
||||
/// The high bit in the LEN field (bit 7) is defined as an Overload bit. This bit
|
||||
/// signifies that additional information is contained in the linear EXE module and
|
||||
/// will be used in the future for parameter type checking.
|
||||
/// </remarks>
|
||||
public byte Length;
|
||||
|
||||
/// <summary>
|
||||
/// ASCII String.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a variable length string with it's length defined in bytes by the LEN field.
|
||||
/// The string is case case sensitive and is not null terminated.
|
||||
/// </remarks>
|
||||
public byte[] Name;
|
||||
|
||||
/// <summary>
|
||||
/// Ordinal number.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The ordinal number in an ordered index into the entry table for this entry point.
|
||||
/// </remarks>
|
||||
public ushort OrdinalNumber;
|
||||
}
|
||||
}
|
||||
52
BurnOutSharp.Models/LinearExecutable/ResourceTableEntry.cs
Normal file
52
BurnOutSharp.Models/LinearExecutable/ResourceTableEntry.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The resource table is an array of resource table entries. Each resource table
|
||||
/// entry contains a type ID and name ID. These entries are used to locate resource
|
||||
/// objects contained in the Object table. The number of entries in the resource
|
||||
/// table is defined by the Resource Table Count located in the linear EXE header.
|
||||
/// More than one resource may be contained within a single object. Resource table
|
||||
/// entries are in a sorted order, (ascending, by Resource Name ID within the
|
||||
/// Resource Type ID). This allows the DosGetResource API function to use a binary
|
||||
/// search when looking up a resource in a 32-bit module instead of the linear search
|
||||
/// being used in the current 16-bit module.
|
||||
/// </summary>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ResourceTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Resource type ID.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The type of resources are:
|
||||
/// - BTMP = Bitmap
|
||||
/// - EMSG = Error message string
|
||||
/// - FONT = Fonts
|
||||
/// </remarks>
|
||||
public ushort TypeID;
|
||||
|
||||
/// <summary>
|
||||
/// An ID used as a name for the resource when referred to.
|
||||
/// </summary>
|
||||
public ushort NameID;
|
||||
|
||||
/// <summary>
|
||||
/// The number of bytes the resource consists of.
|
||||
/// </summary>
|
||||
public uint ResourceSize;
|
||||
|
||||
/// <summary>
|
||||
/// The number of the object which contains the resource.
|
||||
/// </summary>
|
||||
public ushort ObjectNumber;
|
||||
|
||||
/// <summary>
|
||||
/// The offset within the specified object where the resource begins.
|
||||
/// </summary>
|
||||
public uint Offset;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.LinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The Verify Record Directive Table is an optional table. It maintains a record
|
||||
/// of the pages in the EXE file that have been fixed up and written back to the
|
||||
/// original linear EXE module, along with the module dependencies used to perform
|
||||
/// these fixups. This table provides an efficient means for verifying the virtual
|
||||
/// addresses required for the fixed up pages when the module is loaded.
|
||||
/// </summary>
|
||||
/// <see href="https://faydoc.tripod.com/formats/exe-LE.htm"/>
|
||||
/// <see href="http://www.edm2.com/index.php/LX_-_Linear_eXecutable_Module_Format_Description"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class VerifyRecordDirectiveTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of module dependencies.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field specifies how many entries there are in the verify record
|
||||
/// directive table. This is equal to the number of modules referenced by
|
||||
/// this module.
|
||||
/// </remarks>
|
||||
public ushort EntryCount;
|
||||
|
||||
/// <summary>
|
||||
/// Ordinal index into the Import Module Name Table.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is an ordered index in to the Import Module Name Table for
|
||||
/// the referenced module.
|
||||
/// </remarks>
|
||||
public ushort OrdinalIndex;
|
||||
|
||||
/// <summary>
|
||||
/// Module Version.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the version of the referenced module that the fixups were
|
||||
/// originally performed.This is used to insure the same version of the
|
||||
/// referenced module is loaded that was fixed up in this module and
|
||||
/// therefore the fixups are still correct. This requires the version
|
||||
/// number in a module to be incremented anytime the entry point offsets
|
||||
/// change.
|
||||
/// </remarks>
|
||||
public ushort Version;
|
||||
|
||||
/// <summary>
|
||||
/// Module # of Object Entries.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field is used to identify the number of object verify entries
|
||||
/// that follow for the referenced module.
|
||||
/// </remarks>
|
||||
public ushort ObjectEntriesCount;
|
||||
|
||||
/// <summary>
|
||||
/// Object # in Module.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field specifies the object number in the referenced module that
|
||||
/// is being verified.
|
||||
/// </remarks>
|
||||
public ushort ObjectNumberInModule;
|
||||
|
||||
/// <summary>
|
||||
/// Object load base address.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the address that the object was loaded at when the fixups were
|
||||
/// performed.
|
||||
/// </remarks>
|
||||
public ushort ObjectLoadBaseAddress;
|
||||
|
||||
/// <summary>
|
||||
/// Object virtual address size.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field specifies the total amount of virtual memory required for
|
||||
/// this object.
|
||||
/// </remarks>
|
||||
public ushort ObjectVirtualAddressSize;
|
||||
}
|
||||
}
|
||||
29
BurnOutSharp.Models/MSDOS/Executable.cs
Normal file
29
BurnOutSharp.Models/MSDOS/Executable.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
namespace BurnOutSharp.Models.MSDOS
|
||||
{
|
||||
/// <summary>
|
||||
/// The MS-DOS EXE format, also known as MZ after its signature (the initials of Microsoft engineer Mark Zbykowski),
|
||||
/// was introduced with MS-DOS 2.0 (version 1.0 only sported the simple COM format). It is designed as a relocatable
|
||||
/// executable running under real mode. As such, only DOS and Windows 9x can use this format natively, but there are
|
||||
/// several free DOS emulators (e.g., DOSBox) that support it and that run under various operating systems (e.g.,
|
||||
/// Linux, Amiga, Windows NT, etc.). Although they can exist on their own, MZ executables are embedded in all NE, LE,
|
||||
/// and PE executables, usually as stubs so that when they are ran under DOS, they display a warning.
|
||||
/// </summary>
|
||||
/// <see href="https://wiki.osdev.org/MZ"/>
|
||||
public class Executable
|
||||
{
|
||||
/// <summary>
|
||||
/// MS-DOS executable header
|
||||
/// </summary>
|
||||
public ExecutableHeader Header { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// After loading the executable into memory, the program loader goes through
|
||||
/// every entry in relocation table. For each relocation entry, the loader
|
||||
/// adds the start segment address into word value pointed to by the
|
||||
/// segment:offset pair. So, for example, a relocation entry 0001:001A will
|
||||
/// make the loader add start segment address to the value at offset
|
||||
/// 1*0x10+0x1A=0x2A within the program data.
|
||||
/// </summary>
|
||||
public RelocationEntry[] RelocationTable { get; set; }
|
||||
}
|
||||
}
|
||||
130
BurnOutSharp.Models/MSDOS/ExecutableHeader.cs
Normal file
130
BurnOutSharp.Models/MSDOS/ExecutableHeader.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.MSDOS
|
||||
{
|
||||
/// <summary>
|
||||
/// MZ executables only consists of 2 structures: the header and the relocation table.
|
||||
/// The header, which is followed by the program image, looks like this.
|
||||
/// </summary>
|
||||
/// <see href="https://wiki.osdev.org/MZ"/>
|
||||
/// <see href="http://www.pinvoke.net/default.aspx/Structures.IMAGE_DOS_HEADER"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ExecutableHeader
|
||||
{
|
||||
#region Standard Fields
|
||||
|
||||
/// <summary>
|
||||
/// 0x5A4D (ASCII for 'M' and 'Z')
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] Magic;
|
||||
|
||||
/// <summary>
|
||||
/// Number of bytes in the last page.
|
||||
/// </summary>
|
||||
public ushort LastPageBytes;
|
||||
|
||||
/// <summary>
|
||||
/// Number of whole/partial pages.
|
||||
/// </summary>
|
||||
/// <remarks>A page (or block) is 512 bytes long.</remarks>
|
||||
public ushort Pages;
|
||||
|
||||
/// <summary>
|
||||
/// Number of entries in the relocation table.
|
||||
/// </summary>
|
||||
public ushort RelocationItems;
|
||||
|
||||
/// <summary>
|
||||
/// The number of paragraphs taken up by the header. It can be any value, as the loader
|
||||
/// just uses it to find where the actual executable data starts. It may be larger than
|
||||
/// what the "standard" fields take up, and you may use it if you want to include your
|
||||
/// own header metadata, or put the relocation table there, or use it for any other purpose. [08]
|
||||
/// </summary>
|
||||
/// <remarks>A paragraph is 16 bytes in size</remarks>
|
||||
public ushort HeaderParagraphSize;
|
||||
|
||||
/// <summary>
|
||||
/// The number of paragraphs required by the program, excluding the PSP and program image.
|
||||
/// If no free block is big enough, the loading stops.
|
||||
/// </summary>
|
||||
/// <remarks>A paragraph is 16 bytes in size</remarks>
|
||||
public ushort MinimumExtraParagraphs;
|
||||
|
||||
/// <summary>
|
||||
/// The number of paragraphs requested by the program.
|
||||
/// If no free block is big enough, the biggest one possible is allocated.
|
||||
/// </summary>
|
||||
/// <remarks>A paragraph is 16 bytes in size</remarks>
|
||||
public ushort MaximumExtraParagraphs;
|
||||
|
||||
/// <summary>
|
||||
/// Relocatable segment address for SS.
|
||||
/// </summary>
|
||||
public ushort InitialSSValue;
|
||||
|
||||
/// <summary>
|
||||
/// Initial value for SP.
|
||||
/// </summary>
|
||||
public ushort InitialSPValue;
|
||||
|
||||
/// <summary>
|
||||
/// When added to the sum of all other words in the file, the result should be zero.
|
||||
/// </summary>
|
||||
public ushort Checksum;
|
||||
|
||||
/// <summary>
|
||||
/// Initial value for IP. [14]
|
||||
/// </summary>
|
||||
public ushort InitialIPValue;
|
||||
|
||||
/// <summary>
|
||||
/// Relocatable segment address for CS.
|
||||
/// </summary>
|
||||
public ushort InitialCSValue;
|
||||
|
||||
/// <summary>
|
||||
/// The (absolute) offset to the relocation table.
|
||||
/// </summary>
|
||||
public ushort RelocationTableAddr;
|
||||
|
||||
/// <summary>
|
||||
/// Value used for overlay management.
|
||||
/// If zero, this is the main executable.
|
||||
/// </summary>
|
||||
public ushort OverlayNumber;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PE Extensions
|
||||
|
||||
/// <summary>
|
||||
/// Reserved words
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public ushort[] Reserved1;
|
||||
|
||||
/// <summary>
|
||||
/// Defined by name but no other information is given; typically zeroes
|
||||
/// </summary>
|
||||
public ushort OEMIdentifier;
|
||||
|
||||
/// <summary>
|
||||
/// Defined by name but no other information is given; typically zeroes
|
||||
/// </summary>
|
||||
public ushort OEMInformation;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved words
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
|
||||
public ushort[] Reserved2;
|
||||
|
||||
/// <summary>
|
||||
/// Starting address of the PE header
|
||||
/// </summary>
|
||||
public uint NewExeHeaderAddr;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
22
BurnOutSharp.Models/MSDOS/RelocationEntry.cs
Normal file
22
BurnOutSharp.Models/MSDOS/RelocationEntry.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.MSDOS
|
||||
{
|
||||
/// <summary>
|
||||
/// Each pointer in the relocation table looks as such
|
||||
/// </summary>
|
||||
/// <see href="https://wiki.osdev.org/MZ"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class RelocationEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Offset of the relocation within provided segment.
|
||||
/// </summary>
|
||||
public ushort Offset;
|
||||
|
||||
/// <summary>
|
||||
/// Segment of the relocation, relative to the load segment address.
|
||||
/// </summary>
|
||||
public ushort Segment;
|
||||
}
|
||||
}
|
||||
84
BurnOutSharp.Models/NewExecutable/EntryTableBundle.cs
Normal file
84
BurnOutSharp.Models/NewExecutable/EntryTableBundle.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The entry table follows the imported-name table. This table contains
|
||||
/// bundles of entry-point definitions. Bundling is done to save space in
|
||||
/// the entry table. The entry table is accessed by an ordinal value.
|
||||
/// Ordinal number one is defined to index the first entry in the entry
|
||||
/// table. To find an entry point, the bundles are scanned searching for a
|
||||
/// specific entry point using an ordinal number. The ordinal number is
|
||||
/// adjusted as each bundle is checked. When the bundle that contains the
|
||||
/// entry point is found, the ordinal number is multiplied by the size of
|
||||
/// the bundle's entries to index the proper entry.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The linker forms bundles in the most dense manner it can, under the
|
||||
/// restriction that it cannot reorder entry points to improve bundling.
|
||||
/// The reason for this restriction is that other .EXE files may refer to
|
||||
/// entry points within this bundle by their ordinal number. The following
|
||||
/// describes the format of the entry table bundles.
|
||||
/// </remarks>
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
public class EntryTableBundle
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of entries in this bundle. All records in one bundle
|
||||
/// are either moveable or refer to the same fixed segment. A zero
|
||||
/// value in this field indicates the end of the entry table.
|
||||
/// </summary>
|
||||
public byte EntryCount;
|
||||
|
||||
/// <summary>
|
||||
/// Segment indicator for this bundle. This defines the type of
|
||||
/// entry table entry data within the bundle. There are three
|
||||
/// types of entries that are defined.
|
||||
/// - 000h = Unused entries. There is no entry data in an unused
|
||||
/// bundle. The next bundle follows this field. This is
|
||||
/// used by the linker to skip ordinal numbers.
|
||||
/// - 001h-0FEh = Segment number for fixed segment entries. A fixed
|
||||
/// segment entry is 3 bytes long.
|
||||
/// - 0FFH = Moveable segment entries. The entry data contains the
|
||||
/// segment number for the entry points. A moveable segment
|
||||
/// entry is 6 bytes long.
|
||||
/// </summary>
|
||||
public byte SegmentIndicator;
|
||||
|
||||
#region Fixed Segment Entry
|
||||
|
||||
/// <summary>
|
||||
/// Flag word.
|
||||
/// </summary>
|
||||
public FixedSegmentEntryFlag FixedFlagWord;
|
||||
|
||||
/// <summary>
|
||||
/// Offset within segment to entry point.
|
||||
/// </summary>
|
||||
public ushort FixedOffset;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Moveable Segment Entry
|
||||
|
||||
/// <summary>
|
||||
/// Flag word.
|
||||
/// </summary>
|
||||
public MoveableSegmentEntryFlag MoveableFlagWord;
|
||||
|
||||
/// <summary>
|
||||
/// INT 3FH.
|
||||
/// </summary>
|
||||
public ushort MoveableReserved;
|
||||
|
||||
/// <summary>
|
||||
/// Segment number.
|
||||
/// </summary>
|
||||
public byte MoveableSegmentNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Offset within segment to entry point.
|
||||
/// </summary>
|
||||
public ushort MoveableOffset;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
324
BurnOutSharp.Models/NewExecutable/Enums.cs
Normal file
324
BurnOutSharp.Models/NewExecutable/Enums.cs
Normal file
@@ -0,0 +1,324 @@
|
||||
using System;
|
||||
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
[Flags]
|
||||
public enum FixedSegmentEntryFlag : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Set if the entry is exported.
|
||||
/// </summary>
|
||||
Exported = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// Set if the entry uses a global (shared) data segments.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The first assembly-language instruction in the
|
||||
/// entry point prologue must be "MOV AX,data
|
||||
/// segment number". This may be set only for
|
||||
/// SINGLEDATA library modules.
|
||||
/// </remarks>
|
||||
Global = 0x02,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum HeaderFlag : ushort
|
||||
{
|
||||
#region Program Flags
|
||||
|
||||
NOAUTODATA = 0x0000,
|
||||
|
||||
/// <summary>
|
||||
/// Shared automatic data segment
|
||||
/// </summary>
|
||||
SINGLEDATA = 0x0001,
|
||||
|
||||
/// <summary>
|
||||
/// Instanced automatic data segment
|
||||
/// </summary>
|
||||
MULTIPLEDATA = 0x0002,
|
||||
|
||||
/// <summary>
|
||||
/// Global initialization
|
||||
/// </summary>
|
||||
GlobalInitialization = 0x0004,
|
||||
|
||||
/// <summary>
|
||||
/// Protected mode only
|
||||
/// </summary>
|
||||
ProtectedModeOnly = 0x0008,
|
||||
|
||||
/// <summary>
|
||||
/// 8086 instructions
|
||||
/// </summary>
|
||||
Instructions8086 = 0x0010,
|
||||
|
||||
/// <summary>
|
||||
/// 80286 instructions
|
||||
/// </summary>
|
||||
Instructions80286 = 0x0020,
|
||||
|
||||
/// <summary>
|
||||
/// 80386 instructions
|
||||
/// </summary>
|
||||
Instructions80386 = 0x0040,
|
||||
|
||||
/// <summary>
|
||||
/// 80x87 instructions
|
||||
/// </summary>
|
||||
Instructions80x87 = 0x0080,
|
||||
|
||||
#endregion
|
||||
|
||||
#region Application Flags
|
||||
|
||||
/// <summary>
|
||||
/// Full screen (not aware of Windows/P.M. API)
|
||||
/// </summary>
|
||||
FullScreen = 0x0100,
|
||||
|
||||
/// <summary>
|
||||
/// Compatible with Windows/P.M. API
|
||||
/// </summary>
|
||||
WindowsPMCompatible = 0x0200,
|
||||
|
||||
/// <summary>
|
||||
/// Uses Windows/P.M. API
|
||||
/// </summary>
|
||||
WindowsPM = 0x0400,
|
||||
|
||||
/// <summary>
|
||||
/// OS/2 family application
|
||||
/// </summary>
|
||||
OS2FamilyApplication = 0x0800,
|
||||
|
||||
/// <summary>
|
||||
/// Unknown (Reserved?)
|
||||
/// </summary>
|
||||
UnknownReserved = 0x1000,
|
||||
|
||||
/// <summary>
|
||||
/// Errors detected at link time, module will not load
|
||||
/// </summary>
|
||||
ErrorsDetectedAtLinkTime = 0x2000,
|
||||
|
||||
/// <summary>
|
||||
/// Unknown (non-conforming program)
|
||||
/// </summary>
|
||||
UnknownNonConforming = 0x4000,
|
||||
|
||||
/// <summary>
|
||||
/// Library module.
|
||||
/// The SS:SP information is invalid, CS:IP points
|
||||
/// to an initialization procedure that is called
|
||||
/// with AX equal to the module handle. This
|
||||
/// initialization procedure must perform a far
|
||||
/// return to the caller, with AX not equal to
|
||||
/// zero to indicate success, or AX equal to zero
|
||||
/// to indicate failure to initialize. DS is set
|
||||
/// to the library's data segment if the
|
||||
/// SINGLEDATA flag is set. Otherwise, DS is set
|
||||
/// to the caller's data segment.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A program or DLL can only contain dynamic
|
||||
/// links to executable files that have this
|
||||
/// library module flag set. One program cannot
|
||||
/// dynamic-link to another program.
|
||||
/// </remarks>
|
||||
LibraryModule = 0x8000,
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum MoveableSegmentEntryFlag : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Set if the entry is exported.
|
||||
/// </summary>
|
||||
Exported = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// Set if the entry uses a global (shared) data segments.
|
||||
/// </summary>
|
||||
Global = 0x02,
|
||||
}
|
||||
|
||||
public enum OperatingSystem : byte
|
||||
{
|
||||
OS2 = 0x01,
|
||||
WINDOWS = 0x02,
|
||||
EU_MSDOS4 = 0x03,
|
||||
WINDOWS_386 = 0x04,
|
||||
BOSS = 0x05,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum OS2Flag : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Long filename support
|
||||
/// </summary>
|
||||
LongFilenameSupport = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// 2.x protected mode
|
||||
/// </summary>
|
||||
ProtectedMode = 0x02,
|
||||
|
||||
/// <summary>
|
||||
/// 2.x proportional fonts
|
||||
/// </summary>
|
||||
ProportionalFonts = 0x04,
|
||||
|
||||
/// <summary>
|
||||
/// Executable has gangload area
|
||||
/// </summary>
|
||||
HasGangload = 0x08,
|
||||
|
||||
/// <summary>
|
||||
/// Unknown
|
||||
/// </summary>
|
||||
Unknown = 0xF0,
|
||||
}
|
||||
|
||||
public enum OSFixupType : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// FIARQQ, FJARQQ
|
||||
/// </summary>
|
||||
FIARQQ = 0x0001,
|
||||
|
||||
/// <summary>
|
||||
/// FISRQQ, FJSRQQ
|
||||
/// </summary>
|
||||
FISRQQ = 0x0002,
|
||||
|
||||
/// <summary>
|
||||
/// FICRQQ, FJCRQQ
|
||||
/// </summary>
|
||||
FICRQQ = 0x0003,
|
||||
|
||||
FIERQQ = 0x0004,
|
||||
|
||||
FIDRQQ = 0x0005,
|
||||
|
||||
FIWRQQ = 0x0006,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum RelocationRecordFlag : byte
|
||||
{
|
||||
TARGET_MASK = 0x03,
|
||||
|
||||
INTERNALREF = 0x00,
|
||||
|
||||
IMPORTORDINAL = 0x01,
|
||||
|
||||
IMPORTNAME = 0x02,
|
||||
|
||||
OSFIXUP = 0x03,
|
||||
|
||||
ADDITIVE = 0x04,
|
||||
}
|
||||
|
||||
public enum RelocationRecordSourceType : byte
|
||||
{
|
||||
SOURCE_MASK = 0x0F,
|
||||
|
||||
LOBYTE = 0x00,
|
||||
|
||||
SEGMENT = 0x02,
|
||||
|
||||
/// <summary>
|
||||
/// 32-bit pointer
|
||||
/// </summary>
|
||||
FAR_ADDR = 0x03,
|
||||
|
||||
/// <summary>
|
||||
/// 16-bit offset
|
||||
/// </summary>
|
||||
OFFSET = 0x05,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ResourceTypeResourceFlag : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// Resource is not fixed.
|
||||
/// </summary>
|
||||
MOVEABLE = 0x0010,
|
||||
|
||||
/// <summary>
|
||||
/// Resource can be shared.
|
||||
/// </summary>
|
||||
PURE = 0x0020,
|
||||
|
||||
/// <summary>
|
||||
/// Resource is preloaded.
|
||||
/// </summary>
|
||||
PRELOAD = 0x0040,
|
||||
}
|
||||
|
||||
public enum SegmentEntryType
|
||||
{
|
||||
/// <summary>
|
||||
/// 000h - There is no entry data in an unused bundle. The next bundle
|
||||
/// follows this field. This is used by the linker to skip ordinal numbers.
|
||||
/// </summary>
|
||||
Unused,
|
||||
|
||||
/// <summary>
|
||||
/// 001h-0FEh - Segment number for fixed segment entries. A fixed segment
|
||||
/// entry is 3 bytes long.
|
||||
/// </summary>
|
||||
FixedSegment,
|
||||
|
||||
/// <summary>
|
||||
/// 0FFH - Moveable segment entries. The entry data contains the segment
|
||||
/// number for the entry points. A moveable segment entry is 6 bytes long.
|
||||
/// </summary>
|
||||
MoveableSegment,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum SegmentTableEntryFlag : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// Segment-type field.
|
||||
/// </summary>
|
||||
TYPE_MASK = 0x0007,
|
||||
|
||||
/// <summary>
|
||||
/// Code-segment type.
|
||||
/// </summary>
|
||||
CODE = 0x0000,
|
||||
|
||||
/// <summary>
|
||||
/// Data-segment type.
|
||||
/// </summary>
|
||||
DATA = 0x0001,
|
||||
|
||||
/// <summary>
|
||||
/// Segment is not fixed.
|
||||
/// </summary>
|
||||
MOVEABLE = 0x0010,
|
||||
|
||||
/// <summary>
|
||||
/// Segment will be preloaded; read-only if this is a data segment.
|
||||
/// </summary>
|
||||
PRELOAD = 0x0040,
|
||||
|
||||
/// <summary>
|
||||
/// Set if segment has relocation records.
|
||||
/// </summary>
|
||||
RELOCINFO = 0x0100,
|
||||
|
||||
/// <summary>
|
||||
/// Discard priority.
|
||||
/// </summary>
|
||||
DISCARD = 0xF000,
|
||||
}
|
||||
}
|
||||
61
BurnOutSharp.Models/NewExecutable/Executable.cs
Normal file
61
BurnOutSharp.Models/NewExecutable/Executable.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The segmented EXE header contains general information about the EXE
|
||||
/// file and contains information on the location and size of the other
|
||||
/// sections. The Windows loader copies this section, along with other
|
||||
/// data, into the module table in the system data. The module table is
|
||||
/// internal data used by the loader to manage the loaded executable
|
||||
/// modules in the system and to support dynamic linking.
|
||||
/// </summary>
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
public class Executable
|
||||
{
|
||||
/// <summary>
|
||||
/// MS-DOS executable stub
|
||||
/// </summary>
|
||||
public MSDOS.Executable Stub { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// New Executable header
|
||||
/// </summary>
|
||||
public ExecutableHeader Header { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Segment table
|
||||
/// </summary>
|
||||
public SegmentTableEntry[] SegmentTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Resource table
|
||||
/// </summary>
|
||||
public ResourceTable ResourceTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Resident-Name table
|
||||
/// </summary>
|
||||
public ResidentNameTableEntry[] ResidentNameTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Module-Reference table
|
||||
/// </summary>
|
||||
public ModuleReferenceTableEntry[] ModuleReferenceTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Imported-Name table
|
||||
/// </summary>
|
||||
public Dictionary<ushort, ImportedNameTableEntry> ImportedNameTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Entry table
|
||||
/// </summary>
|
||||
public EntryTableBundle[] EntryTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Nonresident-Name table
|
||||
/// </summary>
|
||||
public NonResidentNameTableEntry[] NonResidentNameTable { get; set; }
|
||||
}
|
||||
}
|
||||
198
BurnOutSharp.Models/NewExecutable/ExecutableHeader.cs
Normal file
198
BurnOutSharp.Models/NewExecutable/ExecutableHeader.cs
Normal file
@@ -0,0 +1,198 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The NE header is a relatively large structure with multiple characteristics.
|
||||
/// Because of the age of the format some items are unclear in meaning.
|
||||
/// </summary>
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
/// <see href="https://github.com/libyal/libexe/blob/main/documentation/Executable%20(EXE)%20file%20format.asciidoc#24-ne-extended-header"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ExecutableHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// Signature word.
|
||||
/// "N" is low-order byte.
|
||||
/// "E" is high-order byte.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] Magic;
|
||||
|
||||
/// <summary>
|
||||
/// Version number of the linker.
|
||||
/// </summary>
|
||||
public byte LinkerVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Revision number of the linker.
|
||||
/// </summary>
|
||||
public byte LinkerRevision;
|
||||
|
||||
/// <summary>
|
||||
/// Entry Table file offset, relative to the beginning of the segmented EXE header.
|
||||
/// </summary>
|
||||
public ushort EntryTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Number of bytes in the entry table.
|
||||
/// </summary>
|
||||
public ushort EntryTableSize;
|
||||
|
||||
/// <summary>
|
||||
/// 32-bit CRC of entire contents of file.
|
||||
/// </summary>
|
||||
/// <remarks>These words are taken as 00 during the calculation.</remarks>
|
||||
public uint CrcChecksum;
|
||||
|
||||
/// <summary>
|
||||
/// Flag word
|
||||
/// </summary>
|
||||
public HeaderFlag FlagWord;
|
||||
|
||||
/// <summary>
|
||||
/// Segment number of automatic data segment.
|
||||
/// This value is set to zero if SINGLEDATA and
|
||||
/// MULTIPLEDATA flag bits are clear, NOAUTODATA is
|
||||
/// indicated in the flags word.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A Segment number is an index into the module's segment
|
||||
/// table. The first entry in the segment table is segment
|
||||
/// number 1.
|
||||
/// </remarks>
|
||||
public ushort AutomaticDataSegmentNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Initial size, in bytes, of dynamic heap added to the
|
||||
/// data segment. This value is zero if no initial local
|
||||
/// heap is allocated.
|
||||
/// </summary>
|
||||
public ushort InitialHeapAlloc;
|
||||
|
||||
/// <summary>
|
||||
/// Initial size, in bytes, of stack added to the data
|
||||
/// segment. This value is zero to indicate no initial
|
||||
/// stack allocation, or when SS is not equal to DS.
|
||||
/// </summary>
|
||||
public ushort InitialStackAlloc;
|
||||
|
||||
/// <summary>
|
||||
/// Segment number:offset of CS:IP.
|
||||
/// </summary>
|
||||
public uint InitialCSIPSetting;
|
||||
|
||||
/// <summary>
|
||||
/// Segment number:offset of SS:SP.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If SS equals the automatic data segment and SP equals
|
||||
/// zero, the stack pointer is set to the top of the
|
||||
/// automatic data segment just below the additional heap
|
||||
/// area.
|
||||
/// </remarks>
|
||||
public uint InitialSSSPSetting;
|
||||
|
||||
/// <summary>
|
||||
/// Number of entries in the Segment Table.
|
||||
/// </summary>
|
||||
public ushort FileSegmentCount;
|
||||
|
||||
/// <summary>
|
||||
/// Number of entries in the Module Reference Table.
|
||||
/// </summary>
|
||||
public ushort ModuleReferenceTableSize;
|
||||
|
||||
/// <summary>
|
||||
/// Number of bytes in the Non-Resident Name Table.
|
||||
/// </summary>
|
||||
public ushort NonResidentNameTableSize;
|
||||
|
||||
/// <summary>
|
||||
/// Segment Table file offset, relative to the beginning
|
||||
/// of the segmented EXE header.
|
||||
/// </summary>
|
||||
public ushort SegmentTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Resource Table file offset, relative to the beginning
|
||||
/// of the segmented EXE header.
|
||||
/// </summary>
|
||||
public ushort ResourceTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Resident Name Table file offset, relative to the
|
||||
/// beginning of the segmented EXE header.
|
||||
/// </summary>
|
||||
public ushort ResidentNameTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Module Reference Table file offset, relative to the
|
||||
/// beginning of the segmented EXE header.
|
||||
/// </summary>
|
||||
public ushort ModuleReferenceTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Imported Names Table file offset, relative to the
|
||||
/// beginning of the segmented EXE header.
|
||||
/// </summary>
|
||||
public ushort ImportedNamesTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Non-Resident Name Table offset, relative to the
|
||||
/// beginning of the file.
|
||||
/// </summary>
|
||||
public uint NonResidentNamesTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Number of movable entries in the Entry Table.
|
||||
/// </summary>
|
||||
public ushort MovableEntriesCount;
|
||||
|
||||
/// <summary>
|
||||
/// Logical sector alignment shift count, log(base 2) of
|
||||
/// the segment sector size (default 9).
|
||||
/// </summary>
|
||||
public ushort SegmentAlignmentShiftCount;
|
||||
|
||||
/// <summary>
|
||||
/// Number of resource entries.
|
||||
/// </summary>
|
||||
public ushort ResourceEntriesCount;
|
||||
|
||||
/// <summary>
|
||||
/// Executable type, used by loader.
|
||||
/// </summary>
|
||||
public OperatingSystem TargetOperatingSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Other OS/2 flags
|
||||
/// </summary>
|
||||
public OS2Flag AdditionalFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Offset to return thunks or start of gangload area
|
||||
/// </summary>
|
||||
public ushort ReturnThunkOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Offset to segment reference thunks or size of gangload area
|
||||
/// </summary>
|
||||
public ushort SegmentReferenceThunkOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum code swap area size
|
||||
/// </summary>
|
||||
public ushort MinCodeSwapAreaSize;
|
||||
|
||||
/// <summary>
|
||||
/// Windows SDK revison number
|
||||
/// </summary>
|
||||
public byte WindowsSDKRevision;
|
||||
|
||||
/// <summary>
|
||||
/// Windows SDK version number
|
||||
/// </summary>
|
||||
public byte WindowsSDKVersion;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ImportNameRelocationRecord
|
||||
{
|
||||
/// <summary>
|
||||
/// Index into module reference table for the imported module.
|
||||
/// </summary>
|
||||
public ushort Index;
|
||||
|
||||
/// <summary>
|
||||
/// Offset within Imported Names Table to procedure name string.
|
||||
/// </summary>
|
||||
public ushort Offset;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ImportOrdinalRelocationRecord
|
||||
{
|
||||
/// <summary>
|
||||
/// Index into module reference table for the imported module.
|
||||
/// </summary>
|
||||
public ushort Index;
|
||||
|
||||
/// <summary>
|
||||
/// Procedure ordinal number.
|
||||
/// </summary>
|
||||
public ushort Ordinal;
|
||||
}
|
||||
}
|
||||
28
BurnOutSharp.Models/NewExecutable/ImportedNameTableEntry.cs
Normal file
28
BurnOutSharp.Models/NewExecutable/ImportedNameTableEntry.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The imported-name table follows the module-reference table. This table
|
||||
/// contains the names of modules and procedures that are imported by the
|
||||
/// executable file. Each entry is composed of a 1-byte field that
|
||||
/// contains the length of the string, followed by any number of
|
||||
/// characters. The strings are not null-terminated and are case
|
||||
/// sensitive.
|
||||
/// </summary>
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ImportedNameTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Length of the name string that follows. A zero value indicates
|
||||
/// the end of the name table.
|
||||
/// </summary>
|
||||
public byte Length;
|
||||
|
||||
/// <summary>
|
||||
/// ASCII text of the name string.
|
||||
/// </summary>
|
||||
public byte[] NameString;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class InternalRefRelocationRecord
|
||||
{
|
||||
/// <summary>
|
||||
/// Segment number for a fixed segment, or 0FFh for a
|
||||
/// movable segment.
|
||||
/// </summary>
|
||||
public byte SegmentNumber;
|
||||
|
||||
/// <summary>
|
||||
/// 0
|
||||
/// </summary>
|
||||
public byte Reserved;
|
||||
|
||||
/// <summary>
|
||||
/// Offset into segment if fixed segment, or ordinal
|
||||
/// number index into Entry Table if movable segment.
|
||||
/// </summary>
|
||||
public ushort Offset;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The module-reference table follows the resident-name table. Each entry
|
||||
/// contains an offset for the module-name string within the imported-
|
||||
/// names table; each entry is 2 bytes long.
|
||||
/// </summary>
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ModuleReferenceTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Offset within Imported Names Table to referenced module name string.
|
||||
/// </summary>
|
||||
public ushort Offset;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The nonresident-name table follows the entry table, and contains a
|
||||
/// module description and nonresident exported procedure name strings.
|
||||
/// The first string in this table is a module description. These name
|
||||
/// strings are case-sensitive and are not null-terminated. The name
|
||||
/// strings follow the same format as those defined in the resident name
|
||||
/// table.
|
||||
/// </summary>
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class NonResidentNameTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Length of the name string that follows. A zero value indicates
|
||||
/// the end of the name table.
|
||||
/// </summary>
|
||||
public byte Length;
|
||||
|
||||
/// <summary>
|
||||
/// ASCII text of the name string.
|
||||
/// </summary>
|
||||
public byte[] NameString;
|
||||
|
||||
/// <summary>
|
||||
/// Ordinal number (index into entry table). This value is ignored
|
||||
/// for the module name.
|
||||
/// </summary>
|
||||
public ushort OrdinalNumber;
|
||||
}
|
||||
}
|
||||
20
BurnOutSharp.Models/NewExecutable/OSFixupRelocationRecord.cs
Normal file
20
BurnOutSharp.Models/NewExecutable/OSFixupRelocationRecord.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class OSFixupRelocationRecord
|
||||
{
|
||||
/// <summary>
|
||||
/// Operating system fixup type.
|
||||
/// Floating-point fixups.
|
||||
/// </summary>
|
||||
public OSFixupType FixupType;
|
||||
|
||||
/// <summary>
|
||||
/// 0
|
||||
/// </summary>
|
||||
public ushort Reserved;
|
||||
}
|
||||
}
|
||||
23
BurnOutSharp.Models/NewExecutable/PerSegmentData.cs
Normal file
23
BurnOutSharp.Models/NewExecutable/PerSegmentData.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The location and size of the per-segment data is defined in the
|
||||
/// segment table entry for the segment. If the segment has relocation
|
||||
/// fixups, as defined in the segment table entry flags, they directly
|
||||
/// follow the segment data in the file. The relocation fixup information
|
||||
/// is defined as follows:
|
||||
/// </summary>
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
public class PerSegmentData
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of relocation records that follow.
|
||||
/// </summary>
|
||||
public ushort RelocationRecordCount;
|
||||
|
||||
/// <summary>
|
||||
/// A table of relocation records follows.
|
||||
/// </summary>
|
||||
public RelocationRecord[] RelocationRecords;
|
||||
}
|
||||
}
|
||||
60
BurnOutSharp.Models/NewExecutable/RelocationRecord.cs
Normal file
60
BurnOutSharp.Models/NewExecutable/RelocationRecord.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// A table of relocation records follows. The following is the format
|
||||
/// of each relocation record.
|
||||
/// </summary>
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class RelocationRecord
|
||||
{
|
||||
/// <summary>
|
||||
/// Source type.
|
||||
/// </summary>
|
||||
public RelocationRecordSourceType SourceType;
|
||||
|
||||
/// <summary>
|
||||
/// Flags byte.
|
||||
///
|
||||
/// The target value has four types that are defined in the flag
|
||||
/// byte field.
|
||||
/// </summary>
|
||||
public RelocationRecordFlag Flags;
|
||||
|
||||
/// <summary>
|
||||
/// Offset within this segment of the source chain.
|
||||
/// If the ADDITIVE flag is set, then target value is added to
|
||||
/// the source contents, instead of replacing the source and
|
||||
/// following the chain. The source chain is an 0FFFFh
|
||||
/// terminated linked list within this segment of all
|
||||
/// references to the target.
|
||||
/// </summary>
|
||||
public ushort Offset;
|
||||
|
||||
/// <summary>
|
||||
/// INTERNALREF
|
||||
/// </summary>
|
||||
/// <remarks>Must be <c>NULL</c> if <see cref="Flags"/> is not set to <see cref="RelocationRecordFlag.INTERNALREF"/></remarks>
|
||||
public InternalRefRelocationRecord InternalRefRelocationRecord;
|
||||
|
||||
/// <summary>
|
||||
/// IMPORTNAME
|
||||
/// </summary>
|
||||
/// <remarks>Must be <c>NULL</c> if <see cref="Flags"/> is not set to <see cref="RelocationRecordFlag.IMPORTNAME"/></remarks>
|
||||
public ImportNameRelocationRecord ImportNameRelocationRecord;
|
||||
|
||||
/// <summary>
|
||||
/// IMPORTORDINAL
|
||||
/// </summary>
|
||||
/// <remarks>Must be <c>NULL</c> if <see cref="Flags"/> is not set to <see cref="RelocationRecordFlag.IMPORTORDINAL"/></remarks>
|
||||
public ImportOrdinalRelocationRecord ImportOrdinalRelocationRecord;
|
||||
|
||||
/// <summary>
|
||||
/// IMPORTORDINAL
|
||||
/// </summary>
|
||||
/// <remarks>Must be <c>NULL</c> if <see cref="Flags"/> is not set to <see cref="RelocationRecordFlag.OSFIXUP"/></remarks>
|
||||
public OSFixupRelocationRecord OSFixupRelocationRecord;
|
||||
}
|
||||
}
|
||||
33
BurnOutSharp.Models/NewExecutable/ResidentNameTableEntry.cs
Normal file
33
BurnOutSharp.Models/NewExecutable/ResidentNameTableEntry.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The resident-name table follows the resource table, and contains this
|
||||
/// module's name string and resident exported procedure name strings. The
|
||||
/// first string in this table is this module's name. These name strings
|
||||
/// are case-sensitive and are not null-terminated. The following
|
||||
/// describes the format of the name strings:
|
||||
/// </summary>
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ResidentNameTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Length of the name string that follows. A zero value indicates
|
||||
/// the end of the name table.
|
||||
/// </summary>
|
||||
public byte Length;
|
||||
|
||||
/// <summary>
|
||||
/// ASCII text of the name string.
|
||||
/// </summary>
|
||||
public byte[] NameString;
|
||||
|
||||
/// <summary>
|
||||
/// Ordinal number (index into entry table). This value is ignored
|
||||
/// for the module name.
|
||||
/// </summary>
|
||||
public ushort OrdinalNumber;
|
||||
}
|
||||
}
|
||||
36
BurnOutSharp.Models/NewExecutable/ResourceTable.cs
Normal file
36
BurnOutSharp.Models/NewExecutable/ResourceTable.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The resource table follows the segment table and contains entries for
|
||||
/// each resource in the executable file. The resource table consists of
|
||||
/// an alignment shift count, followed by a table of resource records. The
|
||||
/// resource records define the type ID for a set of resources. Each
|
||||
/// resource record contains a table of resource entries of the defined
|
||||
/// type. The resource entry defines the resource ID or name ID for the
|
||||
/// resource. It also defines the location and size of the resource. The
|
||||
/// following describes the contents of each of these structures:
|
||||
/// </summary>
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ResourceTable
|
||||
{
|
||||
/// <summary>
|
||||
/// Alignment shift count for resource data.
|
||||
/// </summary>
|
||||
public ushort AlignmentShiftCount;
|
||||
|
||||
/// <summary>
|
||||
/// A table of resource type information blocks follows.
|
||||
/// </summary>
|
||||
public ResourceTypeInformationEntry[] ResourceTypes;
|
||||
|
||||
/// <summary>
|
||||
/// Resource type and name strings are stored at the end of the
|
||||
/// resource table.
|
||||
/// </summary>
|
||||
public Dictionary<ushort, ResourceTypeAndNameString> TypeAndNameStrings;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Resource type and name strings are stored at the end of the
|
||||
/// resource table. Note that these strings are NOT null terminated and
|
||||
/// are case sensitive.
|
||||
/// </summary>
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ResourceTypeAndNameString
|
||||
{
|
||||
/// <summary>
|
||||
/// Length of the type or name string that follows. A zero value
|
||||
/// indicates the end of the resource type and name string, also
|
||||
/// the end of the resource table.
|
||||
/// </summary>
|
||||
public byte Length;
|
||||
|
||||
/// <summary>
|
||||
/// ASCII text of the type or name string.
|
||||
/// </summary>
|
||||
public byte[] Text;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// A table of resource type information blocks follows. The following
|
||||
/// is the format of each type information block:
|
||||
/// </summary>
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ResourceTypeInformationEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Type ID. This is an integer type if the high-order bit is
|
||||
/// set (8000h); otherwise, it is an offset to the type string,
|
||||
/// the offset is relative to the beginning of the resource
|
||||
/// table. A zero type ID marks the end of the resource type
|
||||
/// information blocks.
|
||||
/// </summary>
|
||||
public ushort TypeID;
|
||||
|
||||
/// <summary>
|
||||
/// Number of resources for this type.
|
||||
/// </summary>
|
||||
public ushort ResourceCount;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved.
|
||||
/// </summary>
|
||||
public uint Reserved;
|
||||
|
||||
/// <summary>
|
||||
/// A table of resources for this type follows.
|
||||
/// </summary>
|
||||
public ResourceTypeResourceEntry[] Resources;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// A table of resources for this type follows. The following is
|
||||
/// the format of each resource (8 bytes each):
|
||||
/// </summary>
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ResourceTypeResourceEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// File offset to the contents of the resource data,
|
||||
/// relative to beginning of file. The offset is in terms
|
||||
/// of the alignment shift count value specified at
|
||||
/// beginning of the resource table.
|
||||
/// </summary>
|
||||
public ushort Offset;
|
||||
|
||||
/// <summary>
|
||||
/// Length of the resource in the file (in bytes).
|
||||
/// </summary>
|
||||
public ushort Length;
|
||||
|
||||
/// <summary>
|
||||
/// Flag word.
|
||||
/// </summary>
|
||||
public ResourceTypeResourceFlag FlagWord;
|
||||
|
||||
/// <summary>
|
||||
/// Resource ID. This is an integer type if the high-order
|
||||
/// bit is set (8000h), otherwise it is the offset to the
|
||||
/// resource string, the offset is relative to the
|
||||
/// beginning of the resource table.
|
||||
/// </summary>
|
||||
public ushort ResourceID;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved.
|
||||
/// </summary>
|
||||
public uint Reserved;
|
||||
}
|
||||
}
|
||||
38
BurnOutSharp.Models/NewExecutable/SegmentTableEntry.cs
Normal file
38
BurnOutSharp.Models/NewExecutable/SegmentTableEntry.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.NewExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The segment table contains an entry for each segment in the executable
|
||||
/// file. The number of segment table entries are defined in the segmented
|
||||
/// EXE header. The first entry in the segment table is segment number 1.
|
||||
/// The following is the structure of a segment table entry.
|
||||
/// </summary>
|
||||
/// <see href="http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class SegmentTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Logical-sector offset (n byte) to the contents of the segment
|
||||
/// data, relative to the beginning of the file. Zero means no
|
||||
/// file data.
|
||||
/// </summary>
|
||||
public ushort Offset;
|
||||
|
||||
/// <summary>
|
||||
/// Length of the segment in the file, in bytes. Zero means 64K.
|
||||
/// </summary>
|
||||
public ushort Length;
|
||||
|
||||
/// <summary>
|
||||
/// Flag word.
|
||||
/// </summary>
|
||||
public SegmentTableEntryFlag FlagWord;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum allocation size of the segment, in bytes. Total size
|
||||
/// of the segment. Zero means 64K.
|
||||
/// </summary>
|
||||
public ushort MinimumAllocationSize;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes the data in an individual accelerator table resource. The structure definition
|
||||
/// provided here is for explanation only; it is not present in any standard header file.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/acceltableentry"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class AcceleratorTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes keyboard accelerator characteristics.
|
||||
/// </summary>
|
||||
public AcceleratorTableFlags Flags;
|
||||
|
||||
/// <summary>
|
||||
/// An ANSI character value or a virtual-key code that identifies the accelerator key.
|
||||
/// </summary>
|
||||
public ushort Ansi;
|
||||
|
||||
/// <summary>
|
||||
/// An identifier for the keyboard accelerator. This is the value passed to the window
|
||||
/// procedure when the user presses the specified key.
|
||||
/// </summary>
|
||||
public ushort Id;
|
||||
|
||||
/// <summary>
|
||||
/// The number of bytes inserted to ensure that the structure is aligned on a DWORD boundary.
|
||||
/// </summary>
|
||||
public ushort Padding;
|
||||
}
|
||||
}
|
||||
390
BurnOutSharp.Models/PortableExecutable/AssemblyManifest.cs
Normal file
390
BurnOutSharp.Models/PortableExecutable/AssemblyManifest.cs
Normal file
@@ -0,0 +1,390 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
[XmlRoot(ElementName = "assembly", Namespace = "urn:schemas-microsoft-com:asm.v1")]
|
||||
public class AssemblyManifest
|
||||
{
|
||||
[XmlAttribute("manifestVersion")]
|
||||
public string ManifestVersion;
|
||||
|
||||
#region Group
|
||||
|
||||
[XmlElement("assemblyIdentity")]
|
||||
public AssemblyIdentity[] AssemblyIdentities;
|
||||
|
||||
[XmlElement("noInheritable")]
|
||||
public AssemblyNoInheritable[] NoInheritables;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Group
|
||||
|
||||
[XmlElement("description")]
|
||||
public AssemblyDescription Description;
|
||||
|
||||
[XmlElement("noInherit")]
|
||||
public AssemblyNoInherit NoInherit;
|
||||
|
||||
//[XmlElement("noInheritable")]
|
||||
//public AssemblyNoInheritable NoInheritable;
|
||||
|
||||
[XmlElement("comInterfaceExternalProxyStub")]
|
||||
public AssemblyCOMInterfaceExternalProxyStub[] COMInterfaceExternalProxyStub;
|
||||
|
||||
[XmlElement("dependency")]
|
||||
public AssemblyDependency[] Dependency;
|
||||
|
||||
[XmlElement("file")]
|
||||
public AssemblyFile[] File;
|
||||
|
||||
[XmlElement("clrClass")]
|
||||
public AssemblyCommonLanguageRuntimeClass[] CLRClass;
|
||||
|
||||
[XmlElement("clrSurrogate")]
|
||||
public AssemblyCommonLanguageSurrogateClass[] CLRSurrogate;
|
||||
|
||||
#endregion
|
||||
|
||||
[XmlAnyElement]
|
||||
public object[] EverythingElse;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyActiveCodePage
|
||||
{
|
||||
[XmlText]
|
||||
public string Value;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyAutoElevate
|
||||
{
|
||||
[XmlText]
|
||||
public string Value;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyBindingRedirect
|
||||
{
|
||||
[XmlAttribute("oldVersion")]
|
||||
public string OldVersion;
|
||||
|
||||
[XmlAttribute("newVersion")]
|
||||
public string NewVersion;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyCOMClass
|
||||
{
|
||||
[XmlAttribute("clsid")]
|
||||
public string CLSID;
|
||||
|
||||
[XmlAttribute("threadingModel")]
|
||||
public string ThreadingModel;
|
||||
|
||||
[XmlAttribute("progid")]
|
||||
public string ProgID;
|
||||
|
||||
[XmlAttribute("tlbid")]
|
||||
public string TLBID;
|
||||
|
||||
[XmlAttribute("description")]
|
||||
public string Description;
|
||||
|
||||
[XmlElement("progid")]
|
||||
public AssemblyProgID[] ProgIDs;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyCOMInterfaceExternalProxyStub
|
||||
{
|
||||
[XmlAttribute("iid")]
|
||||
public string IID;
|
||||
|
||||
[XmlAttribute("name")]
|
||||
public string Name;
|
||||
|
||||
[XmlAttribute("tlbid")]
|
||||
public string TLBID;
|
||||
|
||||
[XmlAttribute("numMethods")]
|
||||
public string NumMethods;
|
||||
|
||||
[XmlAttribute("proxyStubClsid32")]
|
||||
public string ProxyStubClsid32;
|
||||
|
||||
[XmlAttribute("baseInterface")]
|
||||
public string BaseInterface;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyCOMInterfaceProxyStub
|
||||
{
|
||||
[XmlAttribute("iid")]
|
||||
public string IID;
|
||||
|
||||
[XmlAttribute("name")]
|
||||
public string Name;
|
||||
|
||||
[XmlAttribute("tlbid")]
|
||||
public string TLBID;
|
||||
|
||||
[XmlAttribute("numMethods")]
|
||||
public string NumMethods;
|
||||
|
||||
[XmlAttribute("proxyStubClsid32")]
|
||||
public string ProxyStubClsid32;
|
||||
|
||||
[XmlAttribute("baseInterface")]
|
||||
public string BaseInterface;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyCommonLanguageRuntimeClass
|
||||
{
|
||||
[XmlAttribute("name")]
|
||||
public string Name;
|
||||
|
||||
[XmlAttribute("clsid")]
|
||||
public string CLSID;
|
||||
|
||||
[XmlAttribute("progid")]
|
||||
public string ProgID;
|
||||
|
||||
[XmlAttribute("tlbid")]
|
||||
public string TLBID;
|
||||
|
||||
[XmlAttribute("description")]
|
||||
public string Description;
|
||||
|
||||
[XmlAttribute("runtimeVersion")]
|
||||
public string RuntimeVersion;
|
||||
|
||||
[XmlAttribute("threadingModel")]
|
||||
public string ThreadingModel;
|
||||
|
||||
[XmlElement("progid")]
|
||||
public AssemblyProgID[] ProgIDs;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyCommonLanguageSurrogateClass
|
||||
{
|
||||
[XmlAttribute("clsid")]
|
||||
public string CLSID;
|
||||
|
||||
[XmlAttribute("name")]
|
||||
public string Name;
|
||||
|
||||
[XmlAttribute("runtimeVersion")]
|
||||
public string RuntimeVersion;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyDependency
|
||||
{
|
||||
[XmlElement("dependentAssembly")]
|
||||
public AssemblyDependentAssembly DependentAssembly;
|
||||
|
||||
[XmlAttribute("optional")]
|
||||
public string Optional;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyDependentAssembly
|
||||
{
|
||||
[XmlElement("assemblyIdentity")]
|
||||
public AssemblyIdentity AssemblyIdentity;
|
||||
|
||||
[XmlElement("bindingRedirect")]
|
||||
public AssemblyBindingRedirect[] BindingRedirect;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyDescription
|
||||
{
|
||||
[XmlText]
|
||||
public string Value;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyDisableTheming
|
||||
{
|
||||
[XmlText]
|
||||
public string Value;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyDisableWindowFiltering
|
||||
{
|
||||
[XmlText]
|
||||
public string Value;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyDPIAware
|
||||
{
|
||||
[XmlText]
|
||||
public string Value;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyDPIAwareness
|
||||
{
|
||||
[XmlText]
|
||||
public string Value;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyFile
|
||||
{
|
||||
[XmlAttribute("name")]
|
||||
public string Name;
|
||||
|
||||
[XmlAttribute("hash")]
|
||||
public string Hash;
|
||||
|
||||
[XmlAttribute("hashalg")]
|
||||
public string HashAlgorithm;
|
||||
|
||||
[XmlAttribute("size")]
|
||||
public string Size;
|
||||
|
||||
#region Group
|
||||
|
||||
[XmlElement("comClass")]
|
||||
public AssemblyCOMClass[] COMClass;
|
||||
|
||||
[XmlElement("comInterfaceProxyStub")]
|
||||
public AssemblyCOMInterfaceProxyStub[] COMInterfaceProxyStub;
|
||||
|
||||
[XmlElement("typelib")]
|
||||
public AssemblyTypeLib[] Typelib;
|
||||
|
||||
[XmlElement("windowClass")]
|
||||
public AssemblyWindowClass[] WindowClass;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyGDIScaling
|
||||
{
|
||||
[XmlText]
|
||||
public string Value;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyHeapType
|
||||
{
|
||||
[XmlText]
|
||||
public string Value;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyHighResolutionScrollingAware
|
||||
{
|
||||
[XmlText]
|
||||
public string Value;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyIdentity
|
||||
{
|
||||
[XmlAttribute("name")]
|
||||
public string Name;
|
||||
|
||||
[XmlAttribute("version")]
|
||||
public string Version;
|
||||
|
||||
[XmlAttribute("type")]
|
||||
public string Type;
|
||||
|
||||
[XmlAttribute("processorArchitecture")]
|
||||
public string ProcessorArchitecture;
|
||||
|
||||
[XmlAttribute("publicKeyToken")]
|
||||
public string PublicKeyToken;
|
||||
|
||||
[XmlAttribute("language")]
|
||||
public string Language;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyLongPathAware
|
||||
{
|
||||
[XmlText]
|
||||
public string Value;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyNoInherit
|
||||
{
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyNoInheritable
|
||||
{
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyPrinterDriverIsolation
|
||||
{
|
||||
[XmlText]
|
||||
public string Value;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyProgID
|
||||
{
|
||||
[XmlText]
|
||||
public string Value;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblySupportedOS
|
||||
{
|
||||
[XmlAttribute("Id")]
|
||||
public string Id;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyTypeLib
|
||||
{
|
||||
[XmlElement("tlbid")]
|
||||
public string TLBID;
|
||||
|
||||
[XmlElement("version")]
|
||||
public string Version;
|
||||
|
||||
[XmlElement("helpdir")]
|
||||
public string HelpDir;
|
||||
|
||||
[XmlElement("resourceid")]
|
||||
public string ResourceID;
|
||||
|
||||
[XmlElement("flags")]
|
||||
public string Flags;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyUltraHighResolutionScrollingAware
|
||||
{
|
||||
[XmlText]
|
||||
public string Value;
|
||||
}
|
||||
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema"/>
|
||||
public class AssemblyWindowClass
|
||||
{
|
||||
[XmlAttribute("versioned")]
|
||||
public string Versioned;
|
||||
|
||||
[XmlText]
|
||||
public string Value;
|
||||
}
|
||||
|
||||
// TODO: Left off at <ElementType name="progid" />
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Attribute certificates can be associated with an image by adding an attribute
|
||||
/// certificate table. The attribute certificate table is composed of a set of
|
||||
/// contiguous, quadword-aligned attribute certificate entries. Zero padding is
|
||||
/// inserted between the original end of the file and the beginning of the attribute
|
||||
/// certificate table to achieve this alignment.
|
||||
///
|
||||
/// The virtual address value from the Certificate Table entry in the Optional
|
||||
/// Header Data Directory is a file offset to the first attribute certificate
|
||||
/// entry. Subsequent entries are accessed by advancing that entry's dwLength
|
||||
/// bytes, rounded up to an 8-byte multiple, from the start of the current
|
||||
/// attribute certificate entry. This continues until the sum of the rounded dwLength
|
||||
/// values equals the Size value from the Certificates Table entry in the Optional
|
||||
/// Header Data Directory. If the sum of the rounded dwLength values does not equal
|
||||
/// the Size value, then either the attribute certificate table or the Size field
|
||||
/// is corrupted.
|
||||
///
|
||||
/// The first certificate starts at offset 0x5000 from the start of the file on disk.
|
||||
/// To advance through all the attribute certificate entries:
|
||||
///
|
||||
/// 1. Add the first attribute certificate's dwLength value to the starting offset.
|
||||
/// 2. Round the value from step 1 up to the nearest 8-byte multiple to find the offset
|
||||
/// of the second attribute certificate entry.
|
||||
/// 3. Add the offset value from step 2 to the second attribute certificate entry's
|
||||
/// dwLength value and round up to the nearest 8-byte multiple to determine the offset
|
||||
/// of the third attribute certificate entry.
|
||||
/// 4. Repeat step 3 for each successive certificate until the calculated offset equals
|
||||
/// 0x6000 (0x5000 start + 0x1000 total size), which indicates that you've walked
|
||||
/// the entire table.
|
||||
///
|
||||
/// Attribute certificate table entries can contain any certificate type, as long as
|
||||
/// the entry has the correct dwLength value, a unique wRevision value, and a unique
|
||||
/// wCertificateType value. The most common type of certificate table entry is a
|
||||
/// WIN_CERTIFICATE structure, which is documented in Wintrust.h and discussed in
|
||||
/// the remainder of this section.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
public class AttributeCertificateTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the length of the attribute certificate entry.
|
||||
/// </summary>
|
||||
public uint Length;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the certificate version number.
|
||||
/// </summary>
|
||||
public WindowsCertificateRevision Revision;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the type of content in Certificate.
|
||||
/// </summary>
|
||||
public WindowsCertificateType CertificateType;
|
||||
|
||||
/// <summary>
|
||||
/// Contains a certificate, such as an Authenticode signature.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#certificate-data"/>
|
||||
public byte[] Certificate;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The base relocation table contains entries for all base relocations in
|
||||
/// the image. The Base Relocation Table field in the optional header data
|
||||
/// directories gives the number of bytes in the base relocation table. For
|
||||
/// more information, see Optional Header Data Directories (Image Only).
|
||||
/// The base relocation table is divided into blocks. Each block represents
|
||||
/// the base relocations for a 4K page. Each block must start on a 32-bit boundary.
|
||||
///
|
||||
/// The loader is not required to process base relocations that are resolved by
|
||||
/// the linker, unless the load image cannot be loaded at the image base that is
|
||||
/// specified in the PE header.
|
||||
///
|
||||
/// To apply a base relocation, the difference is calculated between the preferred
|
||||
/// base address and the base where the image is actually loaded. If the image is
|
||||
/// loaded at its preferred base, the difference is zero and thus the base
|
||||
/// relocations do not have to be applied.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
public class BaseRelocationBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// The image base plus the page RVA is added to each offset to create
|
||||
/// the VA where the base relocation must be applied.
|
||||
/// </summary>
|
||||
public uint PageRVA;
|
||||
|
||||
/// <summary>
|
||||
/// The total number of bytes in the base relocation block, including
|
||||
/// the Page RVA and Block Size fields and the Type/Offset fields that
|
||||
/// follow.
|
||||
/// </summary>
|
||||
public uint BlockSize;
|
||||
|
||||
/// <summary>
|
||||
/// The Block Size field is then followed by any number of Type or Offset
|
||||
/// field entries. Each entry is a WORD (2 bytes) and has the following
|
||||
/// structure:
|
||||
///
|
||||
/// 4 bits - Type - Stored in the high 4 bits of the WORD, a value
|
||||
/// that indicates the type of base relocation to be
|
||||
/// applied. For more information, see <see cref="BaseRelocationTypes"/>
|
||||
/// 12 bits - Offset - Stored in the remaining 12 bits of the WORD, an
|
||||
/// offset from the starting address that was specified
|
||||
/// in the Page RVA field for the block. This offset
|
||||
/// specifies where the base relocation is to be applied.
|
||||
/// </summary>
|
||||
public BaseRelocationTypeOffsetFieldEntry[] TypeOffsetFieldEntries;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Type or Offset field entry is a WORD (2 bytes).
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
public class BaseRelocationTypeOffsetFieldEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Stored in the high 4 bits of the WORD, a value that indicates the type
|
||||
/// of base relocation to be applied. For more information, see <see cref="BaseRelocationTypes"/>
|
||||
/// </summary>
|
||||
public BaseRelocationTypes BaseRelocationType;
|
||||
|
||||
/// <summary>
|
||||
/// Stored in the remaining 12 bits of the WORD, an offset from the starting
|
||||
/// address that was specified in the Page RVA field for the block. This
|
||||
/// offset specifies where the base relocation is to be applied.
|
||||
/// </summary>
|
||||
public ushort Offset;
|
||||
}
|
||||
}
|
||||
56
BurnOutSharp.Models/PortableExecutable/COFFFileHeader.cs
Normal file
56
BurnOutSharp.Models/PortableExecutable/COFFFileHeader.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// At the beginning of an object file, or immediately after the signature
|
||||
/// of an image file, is a standard COFF file header in the following format.
|
||||
/// Note that the Windows loader limits the number of sections to 96.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class COFFFileHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// The number that identifies the type of target machine.
|
||||
/// </summary>
|
||||
public MachineType Machine;
|
||||
|
||||
/// <summary>
|
||||
/// The number of sections. This indicates the size of the section table,
|
||||
/// which immediately follows the headers.
|
||||
/// </summary>
|
||||
public ushort NumberOfSections;
|
||||
|
||||
/// <summary>
|
||||
/// The low 32 bits of the number of seconds since 00:00 January 1, 1970
|
||||
/// (a C run-time time_t value), which indicates when the file was created.
|
||||
/// </summary>
|
||||
public uint TimeDateStamp;
|
||||
|
||||
/// <summary>
|
||||
/// The file offset of the COFF symbol table, or zero if no COFF symbol table
|
||||
/// is present. This value should be zero for an image because COFF debugging
|
||||
/// information is deprecated.
|
||||
/// </summary>
|
||||
public uint PointerToSymbolTable;
|
||||
|
||||
/// <summary>
|
||||
/// The number of entries in the symbol table. This data can be used to locate
|
||||
/// the string table, which immediately follows the symbol table. This value
|
||||
/// should be zero for an image because COFF debugging information is deprecated.
|
||||
/// </summary>
|
||||
public uint NumberOfSymbols;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the optional header, which is required for executable files but
|
||||
/// not for object files. This value should be zero for an object file.
|
||||
/// </summary>
|
||||
public ushort SizeOfOptionalHeader;
|
||||
|
||||
/// <summary>
|
||||
/// The flags that indicate the attributes of the file.
|
||||
/// </summary>
|
||||
public Characteristics Characteristics;
|
||||
}
|
||||
}
|
||||
42
BurnOutSharp.Models/PortableExecutable/COFFLineNumber.cs
Normal file
42
BurnOutSharp.Models/PortableExecutable/COFFLineNumber.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// COFF line numbers are no longer produced and, in the future, will
|
||||
/// not be consumed.
|
||||
///
|
||||
/// COFF line numbers indicate the relationship between code and line
|
||||
/// numbers in source files. The Microsoft format for COFF line numbers
|
||||
/// is similar to standard COFF, but it has been extended to allow a
|
||||
/// single section to relate to line numbers in multiple source files.
|
||||
///
|
||||
/// COFF line numbers consist of an array of fixed-length records.
|
||||
/// The location (file offset) and size of the array are specified in
|
||||
/// the section header.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public class COFFLineNumber
|
||||
{
|
||||
/// <summary>
|
||||
/// Used when Linenumber is zero: index to symbol table entry for a function.
|
||||
/// This format is used to indicate the function to which a group of
|
||||
/// line-number records refers.
|
||||
/// </summary>
|
||||
[FieldOffset(0)] public uint SymbolTableIndex;
|
||||
|
||||
/// <summary>
|
||||
/// Used when Linenumber is non-zero: the RVA of the executable code that
|
||||
/// corresponds to the source line indicated. In an object file, this
|
||||
/// contains the VA within the section.
|
||||
/// </summary>
|
||||
[FieldOffset(0)] public uint VirtualAddress;
|
||||
|
||||
/// <summary>
|
||||
/// When nonzero, this field specifies a one-based line number. When zero,
|
||||
/// the Type field is interpreted as a symbol table index for a function.
|
||||
/// </summary>
|
||||
[FieldOffset(4)] public ushort Linenumber;
|
||||
}
|
||||
}
|
||||
46
BurnOutSharp.Models/PortableExecutable/COFFRelocation.cs
Normal file
46
BurnOutSharp.Models/PortableExecutable/COFFRelocation.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Object files contain COFF relocations, which specify how the section data
|
||||
/// should be modified when placed in the image file and subsequently loaded
|
||||
/// into memory.
|
||||
///
|
||||
/// Image files do not contain COFF relocations, because all referenced symbols
|
||||
/// have already been assigned addresses in a flat address space. An image
|
||||
/// contains relocation information in the form of base relocations in the
|
||||
/// .reloc section (unless the image has the IMAGE_FILE_RELOCS_STRIPPED attribute).
|
||||
///
|
||||
/// For each section in an object file, an array of fixed-length records holds
|
||||
/// the section's COFF relocations. The position and length of the array are
|
||||
/// specified in the section header.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class COFFRelocation
|
||||
{
|
||||
/// <summary>
|
||||
/// The address of the item to which relocation is applied. This is the
|
||||
/// offset from the beginning of the section, plus the value of the
|
||||
/// section's RVA/Offset field. See Section Table (Section Headers).
|
||||
/// For example, if the first byte of the section has an address of 0x10,
|
||||
/// the third byte has an address of 0x12.
|
||||
/// </summary>
|
||||
public uint VirtualAddress;
|
||||
|
||||
/// <summary>
|
||||
/// A zero-based index into the symbol table. This symbol gives the address
|
||||
/// that is to be used for the relocation. If the specified symbol has section
|
||||
/// storage class, then the symbol's address is the address with the first
|
||||
/// section of the same name.
|
||||
/// </summary>
|
||||
public uint SymbolTableIndex;
|
||||
|
||||
/// <summary>
|
||||
/// A value that indicates the kind of relocation that should be performed.
|
||||
/// Valid relocation types depend on machine type.
|
||||
/// </summary>
|
||||
public RelocationType TypeIndicator;
|
||||
}
|
||||
}
|
||||
25
BurnOutSharp.Models/PortableExecutable/COFFStringTable.cs
Normal file
25
BurnOutSharp.Models/PortableExecutable/COFFStringTable.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Immediately following the COFF symbol table is the COFF string table. The
|
||||
/// position of this table is found by taking the symbol table address in the
|
||||
/// COFF header and adding the number of symbols multiplied by the size of a symbol.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
public class COFFStringTable
|
||||
{
|
||||
/// <summary>
|
||||
/// At the beginning of the COFF string table are 4 bytes that contain the
|
||||
/// total size (in bytes) of the rest of the string table. This size includes
|
||||
/// the size field itself, so that the value in this location would be 4 if no
|
||||
/// strings were present.
|
||||
/// </summary>
|
||||
public uint TotalSize;
|
||||
|
||||
/// <summary>
|
||||
/// Following the size are null-terminated strings that are pointed to by symbols
|
||||
/// in the COFF symbol table.
|
||||
/// </summary>
|
||||
public string[] Strings;
|
||||
}
|
||||
}
|
||||
315
BurnOutSharp.Models/PortableExecutable/COFFSymbolTableEntry.cs
Normal file
315
BurnOutSharp.Models/PortableExecutable/COFFSymbolTableEntry.cs
Normal file
@@ -0,0 +1,315 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol table in this section is inherited from the traditional
|
||||
/// COFF format. It is distinct from Microsoft Visual C++ debug information.
|
||||
/// A file can contain both a COFF symbol table and Visual C++ debug
|
||||
/// information, and the two are kept separate. Some Microsoft tools use
|
||||
/// the symbol table for limited but important purposes, such as
|
||||
/// communicating COMDAT information to the linker. Section names and file
|
||||
/// names, as well as code and data symbols, are listed in the symbol table.
|
||||
///
|
||||
/// The location of the symbol table is indicated in the COFF header.
|
||||
///
|
||||
/// The symbol table is an array of records, each 18 bytes long. Each record
|
||||
/// is either a standard or auxiliary symbol-table record. A standard record
|
||||
/// defines a symbol or name.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
public class COFFSymbolTableEntry
|
||||
{
|
||||
#region Standard COFF Symbol Table Entry
|
||||
|
||||
#region Symbol Name
|
||||
|
||||
/// <summary>
|
||||
/// An array of 8 bytes. This array is padded with nulls on the right if
|
||||
/// the name is less than 8 bytes long.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||||
public byte[] ShortName;
|
||||
|
||||
/// <summary>
|
||||
/// A field that is set to all zeros if the name is longer than 8 bytes.
|
||||
/// </summary>
|
||||
public uint Zeroes;
|
||||
|
||||
/// <summary>
|
||||
/// An offset into the string table.
|
||||
/// </summary>
|
||||
public uint Offset;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The value that is associated with the symbol. The interpretation of this
|
||||
/// field depends on SectionNumber and StorageClass. A typical meaning is the
|
||||
/// relocatable address.
|
||||
/// </summary>
|
||||
public uint Value;
|
||||
|
||||
/// <summary>
|
||||
/// The signed integer that identifies the section, using a one-based index
|
||||
/// into the section table. Some values have special meaning.
|
||||
/// </summary>
|
||||
public ushort SectionNumber;
|
||||
|
||||
/// <summary>
|
||||
/// A number that represents type. Microsoft tools set this field to 0x20
|
||||
/// (function) or 0x0 (not a function).
|
||||
/// </summary>
|
||||
public SymbolType SymbolType;
|
||||
|
||||
/// <summary>
|
||||
/// An enumerated value that represents storage class.
|
||||
/// </summary>
|
||||
public StorageClass StorageClass;
|
||||
|
||||
/// <summary>
|
||||
/// The number of auxiliary symbol table entries that follow this record.
|
||||
/// </summary>
|
||||
public byte NumberOfAuxSymbols;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Auxiliary Symbol Records
|
||||
|
||||
// Auxiliary symbol table records always follow, and apply to, some standard
|
||||
// symbol table record. An auxiliary record can have any format that the tools
|
||||
// can recognize, but 18 bytes must be allocated for them so that symbol table
|
||||
// is maintained as an array of regular size. Currently, Microsoft tools
|
||||
// recognize auxiliary formats for the following kinds of records: function
|
||||
// definitions, function begin and end symbols (.bf and .ef), weak externals,
|
||||
// file names, and section definitions.
|
||||
//
|
||||
// The traditional COFF design also includes auxiliary-record formats for arrays
|
||||
// and structures.Microsoft tools do not use these, but instead place that
|
||||
// symbolic information in Visual C++ debug format in the debug sections.
|
||||
|
||||
#region Auxiliary Format 1: Function Definitions
|
||||
|
||||
// A symbol table record marks the beginning of a function definition if it
|
||||
// has all of the following: a storage class of EXTERNAL (2), a Type value
|
||||
// that indicates it is a function (0x20), and a section number that is
|
||||
// greater than zero. Note that a symbol table record that has a section
|
||||
// number of UNDEFINED (0) does not define the function and does not have
|
||||
// an auxiliary record. Function-definition symbol records are followed by
|
||||
// an auxiliary record in the format described below:
|
||||
|
||||
/// <summary>
|
||||
/// The symbol-table index of the corresponding .bf (begin function)
|
||||
/// symbol record.
|
||||
/// </summary>
|
||||
public uint AuxFormat1TagIndex;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the executable code for the function itself. If the function
|
||||
/// is in its own section, the SizeOfRawData in the section header is greater
|
||||
/// or equal to this field, depending on alignment considerations.
|
||||
/// </summary>
|
||||
public uint AuxFormat1TotalSize;
|
||||
|
||||
/// <summary>
|
||||
/// The file offset of the first COFF line-number entry for the function, or
|
||||
/// zero if none exists.
|
||||
/// </summary>
|
||||
public uint AuxFormat1PointerToLinenumber;
|
||||
|
||||
/// <summary>
|
||||
/// The symbol-table index of the record for the next function. If the function
|
||||
/// is the last in the symbol table, this field is set to zero.
|
||||
/// </summary>
|
||||
public uint AuxFormat1PointerToNextFunction;
|
||||
|
||||
/// <summary>
|
||||
/// Unused
|
||||
/// </summary>
|
||||
public ushort AuxFormat1Unused;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Auxiliary Format 2: .bf and .ef Symbols
|
||||
|
||||
// For each function definition in the symbol table, three items describe
|
||||
// the beginning, ending, and number of lines. Each of these symbols has
|
||||
// storage class FUNCTION (101):
|
||||
//
|
||||
// A symbol record named .bf (begin function). The Value field is unused.
|
||||
//
|
||||
// A symbol record named .lf (lines in function). The Value field gives the
|
||||
// number of lines in the function.
|
||||
//
|
||||
// A symbol record named .ef (end of function). The Value field has the same
|
||||
// number as the Total Size field in the function-definition symbol record.
|
||||
//
|
||||
// The .bf and .ef symbol records (but not .lf records) are followed by an
|
||||
// auxiliary record with the following format:
|
||||
|
||||
/// <summary>
|
||||
/// Unused
|
||||
/// </summary>
|
||||
public uint AuxFormat2Unused1;
|
||||
|
||||
/// <summary>
|
||||
/// The actual ordinal line number (1, 2, 3, and so on) within the source file,
|
||||
/// corresponding to the .bf or .ef record.
|
||||
/// </summary>
|
||||
public ushort AuxFormat2Linenumber;
|
||||
|
||||
/// <summary>
|
||||
/// Unused
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
|
||||
public byte[] AuxFormat2Unused2;
|
||||
|
||||
/// <summary>
|
||||
/// The symbol-table index of the next .bf symbol record. If the function is the
|
||||
/// last in the symbol table, this field is set to zero. It is not used for
|
||||
/// .ef records.
|
||||
/// </summary>
|
||||
public uint AuxFormat2PointerToNextFunction;
|
||||
|
||||
/// <summary>
|
||||
/// Unused
|
||||
/// </summary>
|
||||
public ushort AuxFormat2Unused3;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Auxiliary Format 3: Weak Externals
|
||||
|
||||
// "Weak externals" are a mechanism for object files that allows flexibility at
|
||||
// link time. A module can contain an unresolved external symbol (sym1), but it
|
||||
// can also include an auxiliary record that indicates that if sym1 is not
|
||||
// present at link time, another external symbol (sym2) is used to resolve
|
||||
// references instead.
|
||||
//
|
||||
// If a definition of sym1 is linked, then an external reference to the symbol
|
||||
// is resolved normally. If a definition of sym1 is not linked, then all references
|
||||
// to the weak external for sym1 refer to sym2 instead. The external symbol, sym2,
|
||||
// must always be linked; typically, it is defined in the module that contains
|
||||
// the weak reference to sym1.
|
||||
//
|
||||
// Weak externals are represented by a symbol table record with EXTERNAL storage
|
||||
// class, UNDEF section number, and a value of zero. The weak-external symbol
|
||||
// record is followed by an auxiliary record with the following format:
|
||||
|
||||
/// <summary>
|
||||
/// The symbol-table index of sym2, the symbol to be linked if sym1 is not found.
|
||||
/// </summary>
|
||||
public uint AuxFormat3TagIndex;
|
||||
|
||||
/// <summary>
|
||||
/// A value of IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY indicates that no library search
|
||||
/// for sym1 should be performed.
|
||||
/// A value of IMAGE_WEAK_EXTERN_SEARCH_LIBRARY indicates that a library search for
|
||||
/// sym1 should be performed.
|
||||
/// A value of IMAGE_WEAK_EXTERN_SEARCH_ALIAS indicates that sym1 is an alias for sym2.
|
||||
/// </summary>
|
||||
public uint AuxFormat3Characteristics;
|
||||
|
||||
/// <summary>
|
||||
/// Unused
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
|
||||
public byte[] AuxFormat3Unused;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Auxiliary Format 4: Files
|
||||
|
||||
// This format follows a symbol-table record with storage class FILE (103).
|
||||
// The symbol name itself should be .file, and the auxiliary record that
|
||||
// follows it gives the name of a source-code file.
|
||||
|
||||
/// <summary>
|
||||
/// An ANSI string that gives the name of the source file. This is padded
|
||||
/// with nulls if it is less than the maximum length.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 18)]
|
||||
public byte[] AuxFormat4FileName;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Auxiliary Format 5: Section Definitions
|
||||
|
||||
// This format follows a symbol-table record that defines a section. Such a
|
||||
// record has a symbol name that is the name of a section (such as .text or
|
||||
// .drectve) and has storage class STATIC (3). The auxiliary record provides
|
||||
// information about the section to which it refers. Thus, it duplicates some
|
||||
// of the information in the section header.
|
||||
|
||||
/// <summary>
|
||||
/// The size of section data; the same as SizeOfRawData in the section header.
|
||||
/// </summary>
|
||||
public uint AuxFormat5Length;
|
||||
|
||||
/// <summary>
|
||||
/// The number of relocation entries for the section.
|
||||
/// </summary>
|
||||
public ushort AuxFormat5NumberOfRelocations;
|
||||
|
||||
/// <summary>
|
||||
/// The number of line-number entries for the section.
|
||||
/// </summary>
|
||||
public ushort AuxFormat5NumberOfLinenumbers;
|
||||
|
||||
/// <summary>
|
||||
/// The checksum for communal data. It is applicable if the IMAGE_SCN_LNK_COMDAT
|
||||
/// flag is set in the section header.
|
||||
/// </summary>
|
||||
public uint AuxFormat5CheckSum;
|
||||
|
||||
/// <summary>
|
||||
/// One-based index into the section table for the associated section. This is
|
||||
/// used when the COMDAT selection setting is 5.
|
||||
/// </summary>
|
||||
public ushort AuxFormat5Number;
|
||||
|
||||
/// <summary>
|
||||
/// The COMDAT selection number. This is applicable if the section is a
|
||||
/// COMDAT section.
|
||||
/// </summary>
|
||||
public byte AuxFormat5Selection;
|
||||
|
||||
/// <summary>
|
||||
/// Unused
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] AuxFormat5Unused;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Auxiliary Format 6: CLR Token Definition (Object Only)
|
||||
|
||||
// This auxiliary symbol generally follows the IMAGE_SYM_CLASS_CLR_TOKEN. It is
|
||||
// used to associate a token with the COFF symbol table's namespace.
|
||||
|
||||
/// <summary>
|
||||
/// Must be IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF (1).
|
||||
/// </summary>
|
||||
public byte AuxFormat6AuxType;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved, must be zero.
|
||||
/// </summary>
|
||||
public byte AuxFormat6Reserved1;
|
||||
|
||||
/// <summary>
|
||||
/// The symbol index of the COFF symbol to which this CLR token definition refers.
|
||||
/// </summary>
|
||||
public uint AuxFormat6SymbolTableIndex;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved, must be zero.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||||
public byte[] AuxFormat6Reserved2;
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The system handles each icon and cursor as a single file. However, these are stored in
|
||||
/// .res files and in executable files as a group of icon resources or a group of cursor
|
||||
/// resources. The file formats of icon and cursor resources are similar. In the .res file
|
||||
/// a resource group header follows all of the individual icon or cursor group components.
|
||||
///
|
||||
/// The format of each icon component closely resembles the format of the .ico file. Each
|
||||
/// icon image is stored in a BITMAPINFO structure followed by the color device-independent
|
||||
/// bitmap (DIB) bits of the icon's XOR mask. The monochrome DIB bits of the icon's AND
|
||||
/// mask follow the color DIB bits.
|
||||
///
|
||||
/// The format of each cursor component resembles the format of the .cur file. Each cursor
|
||||
/// image is stored in a BITMAPINFO structure followed by the monochrome DIB bits of the
|
||||
/// cursor's XOR mask, and then by the monochrome DIB bits of the cursor's AND mask. Note
|
||||
/// that there is a difference in the bitmaps of the two resources: Unlike icons, cursor
|
||||
/// XOR masks do not have color DIB bits. Although the bitmaps of the cursor masks are
|
||||
/// monochrome and do not have DIB headers or color tables, the bits are still in DIB
|
||||
/// format with respect to alignment and direction. Another significant difference
|
||||
/// between cursors and icons is that cursors have a hotspot and icons do not.
|
||||
///
|
||||
/// The group header for both icon and cursor resources consists of a NEWHEADER structure
|
||||
/// plus one or more RESDIR structures. There is one RESDIR structure for each icon or
|
||||
/// cursor. The group header contains the information an application needs to select the
|
||||
/// correct icon or cursor to display. Both the group header and the data that repeats for
|
||||
/// each icon or cursor in the group have a fixed length. This allows the application to
|
||||
/// randomly access the information.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/resource-file-formats"/>
|
||||
public class CursorAndIconResource
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes keyboard accelerator characteristics.
|
||||
/// </summary>
|
||||
public NewHeader NEWHEADER;
|
||||
|
||||
// TODO: Add array of entries in the resource
|
||||
}
|
||||
}
|
||||
29
BurnOutSharp.Models/PortableExecutable/DataDirectory.cs
Normal file
29
BurnOutSharp.Models/PortableExecutable/DataDirectory.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Each data directory gives the address and size of a table or string that Windows uses.
|
||||
/// These data directory entries are all loaded into memory so that the system can use them
|
||||
/// at run time.
|
||||
///
|
||||
/// Also, do not assume that the RVAs in this table point to the beginning of a section or
|
||||
/// that the sections that contain specific tables have specific names.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class DataDirectory
|
||||
{
|
||||
/// <summary>
|
||||
/// The first field, VirtualAddress, is actually the RVA of the table. The RVA
|
||||
/// is the address of the table relative to the base address of the image when
|
||||
/// the table is loaded.
|
||||
/// </summary>
|
||||
public uint VirtualAddress;
|
||||
|
||||
/// <summary>
|
||||
/// The second field gives the size in bytes.
|
||||
/// </summary>
|
||||
public uint Size;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Image files contain an optional debug directory that indicates what form
|
||||
/// of debug information is present and where it is. This directory consists
|
||||
/// of an array of debug directory entries whose location and size are indicated
|
||||
/// in the image optional header.
|
||||
///
|
||||
/// The debug directory can be in a discardable .debug section (if one exists),
|
||||
/// or it can be included in any other section in the image file, or not be in
|
||||
/// a section at all.
|
||||
///
|
||||
/// Each debug directory entry identifies the location and size of a block of
|
||||
/// debug information. The specified RVA can be zero if the debug information
|
||||
/// is not covered by a section header (that is, it resides in the image file
|
||||
/// and is not mapped into the run-time address space). If it is mapped, the
|
||||
/// RVA is its address.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class DebugDirectoryEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Reserved, must be zero.
|
||||
/// </summary>
|
||||
public uint Characteristics;
|
||||
|
||||
/// <summary>
|
||||
/// The time and date that the debug data was created.
|
||||
/// </summary>
|
||||
public uint TimeDateStamp;
|
||||
|
||||
/// <summary>
|
||||
/// The major version number of the debug data format.
|
||||
/// </summary>
|
||||
public ushort MajorVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The minor version number of the debug data format.
|
||||
/// </summary>
|
||||
public ushort MinorVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The format of debugging information. This field enables support
|
||||
/// of multiple debuggers.
|
||||
/// </summary>
|
||||
public DebugType DebugType;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the debug data (not including the debug directory itself).
|
||||
/// </summary>
|
||||
public uint SizeOfData;
|
||||
|
||||
/// <summary>
|
||||
/// The address of the debug data when loaded, relative to the image base.
|
||||
/// </summary>
|
||||
public uint AddressOfRawData;
|
||||
|
||||
/// <summary>
|
||||
/// The file pointer to the debug data.
|
||||
/// </summary>
|
||||
public uint PointerToRawData;
|
||||
}
|
||||
}
|
||||
38
BurnOutSharp.Models/PortableExecutable/DebugTable.cs
Normal file
38
BurnOutSharp.Models/PortableExecutable/DebugTable.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The .debug section is used in object files to contain compiler-generated debug
|
||||
/// information and in image files to contain all of the debug information that is
|
||||
/// generated. This section describes the packaging of debug information in object
|
||||
/// and image files.
|
||||
///
|
||||
/// The next section describes the format of the debug directory, which can be
|
||||
/// anywhere in the image. Subsequent sections describe the "groups" in object
|
||||
/// files that contain debug information.
|
||||
///
|
||||
/// The default for the linker is that debug information is not mapped into the
|
||||
/// address space of the image. A .debug section exists only when debug information
|
||||
/// is mapped in the address space.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
public class DebugTable
|
||||
{
|
||||
/// <summary>
|
||||
/// Image files contain an optional debug directory that indicates what form
|
||||
/// of debug information is present and where it is. This directory consists
|
||||
/// of an array of debug directory entries whose location and size are
|
||||
/// indicated in the image optional header.
|
||||
///
|
||||
/// The debug directory can be in a discardable .debug section (if one exists),
|
||||
/// or it can be included in any other section in the image file, or not be
|
||||
/// in a section at all.
|
||||
///
|
||||
/// Each debug directory entry identifies the location and size of a block of
|
||||
/// debug information. The specified RVA can be zero if the debug information
|
||||
/// is not covered by a section header (that is, it resides in the image
|
||||
/// file and is not mapped into the run-time address space). If it is mapped,
|
||||
/// the RVA is its address.
|
||||
/// </summary>
|
||||
public DebugDirectoryEntry[] DebugDirectoryTable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The delay-load directory table is the counterpart to the import directory
|
||||
/// table. It can be retrieved through the Delay Import Descriptor entry in
|
||||
/// the optional header data directories list (offset 200).
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class DelayLoadDirectoryTable
|
||||
{
|
||||
/// <summary>
|
||||
/// Must be zero.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// As yet, no attribute flags are defined. The linker sets this field to
|
||||
/// zero in the image. This field can be used to extend the record by
|
||||
/// indicating the presence of new fields, or it can be used to indicate
|
||||
/// behaviors to the delay or unload helper functions.
|
||||
/// </remarks>
|
||||
public uint Attributes;
|
||||
|
||||
/// <summary>
|
||||
/// The RVA of the name of the DLL to be loaded. The name resides in the
|
||||
/// read-only data section of the image.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The name of the DLL to be delay-loaded resides in the read-only data
|
||||
/// section of the image. It is referenced through the szName field.
|
||||
/// </remarks>
|
||||
public uint Name;
|
||||
|
||||
/// <summary>
|
||||
/// The RVA of the module handle (in the data section of the image) of the DLL
|
||||
/// to be delay-loaded. It is used for storage by the routine that is supplied
|
||||
/// to manage delay-loading.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The handle of the DLL to be delay-loaded is in the data section of the image.
|
||||
/// The phmod field points to the handle. The supplied delay-load helper uses
|
||||
/// this location to store the handle to the loaded DLL.
|
||||
/// </remarks>
|
||||
public uint ModuleHandle;
|
||||
|
||||
/// <summary>
|
||||
/// The RVA of the delay-load import address table.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The delay import address table (IAT) is referenced by the delay import
|
||||
/// descriptor through the pIAT field. The delay-load helper updates these
|
||||
/// pointers with the real entry points so that the thunks are no longer in
|
||||
/// the calling loop. The function pointers are accessed by using the expression
|
||||
/// pINT->u1.Function.
|
||||
/// </remarks>
|
||||
public uint DelayImportAddressTable;
|
||||
|
||||
/// <summary>
|
||||
/// The RVA of the delay-load name table, which contains the names of the imports
|
||||
/// that might need to be loaded. This matches the layout of the import name table.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The delay import name table (INT) contains the names of the imports that might
|
||||
/// require loading. They are ordered in the same fashion as the function pointers
|
||||
/// in the IAT. They consist of the same structures as the standard INT and are
|
||||
/// accessed by using the expression pINT->u1.AddressOfData->Name[0].
|
||||
/// </remarks>
|
||||
public uint DelayImportNameTable;
|
||||
|
||||
/// <summary>
|
||||
/// The RVA of the bound delay-load address table, if it exists.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The delay bound import address table (BIAT) is an optional table of
|
||||
/// IMAGE_THUNK_DATA items that is used along with the timestamp field of the
|
||||
/// delay-load directory table by a post-process binding phase.
|
||||
/// </remarks>
|
||||
public uint BoundDelayImportTable;
|
||||
|
||||
/// <summary>
|
||||
/// The RVA of the unload delay-load address table, if it exists. This is an exact
|
||||
/// copy of the delay import address table. If the caller unloads the DLL, this
|
||||
/// table should be copied back over the delay import address table so that
|
||||
/// subsequent calls to the DLL continue to use the thunking mechanism correctly.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The delay unload import address table (UIAT) is an optional table of
|
||||
/// IMAGE_THUNK_DATA items that the unload code uses to handle an explicit unload
|
||||
/// request. It consists of initialized data in the read-only section that is an
|
||||
/// exact copy of the original IAT that referred the code to the delay-load thunks.
|
||||
/// On the unload request, the library can be freed, the *phmod cleared, and the
|
||||
/// UIAT written over the IAT to restore everything to its preload state.
|
||||
/// </remarks>
|
||||
public uint UnloadDelayImportTable;
|
||||
|
||||
/// <summary>
|
||||
/// The timestamp of the DLL to which this image has been bound.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The delay bound import address table (BIAT) is an optional table of
|
||||
/// IMAGE_THUNK_DATA items that is used along with the timestamp field of the
|
||||
/// delay-load directory table by a post-process binding phase.
|
||||
/// </remarks>
|
||||
public uint TimeStamp;
|
||||
}
|
||||
}
|
||||
46
BurnOutSharp.Models/PortableExecutable/DialogBoxResource.cs
Normal file
46
BurnOutSharp.Models/PortableExecutable/DialogBoxResource.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// A dialog box is also one resource entry in the resource file. It consists of one
|
||||
/// DLGTEMPLATE dialog box header structure plus one DLGITEMTEMPLATE structure for each
|
||||
/// control in the dialog box. The DLGTEMPLATEEX and the DLGITEMTEMPLATEEX structures
|
||||
/// describe the format of extended dialog box resources.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/resource-file-formats"/>
|
||||
public class DialogBoxResource
|
||||
{
|
||||
#region Dialog template
|
||||
|
||||
/// <summary>
|
||||
/// Dialog box header structure
|
||||
/// </summary>
|
||||
public DialogTemplate DialogTemplate;
|
||||
|
||||
/// <summary>
|
||||
/// Dialog box extended header structure
|
||||
/// </summary>
|
||||
public DialogTemplateExtended ExtendedDialogTemplate;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dialog item templates
|
||||
|
||||
/// <summary>
|
||||
/// Following the DLGTEMPLATE header in a standard dialog box template are one or more
|
||||
/// DLGITEMTEMPLATE structures that define the dimensions and style of the controls in the dialog
|
||||
/// box. The cdit member specifies the number of DLGITEMTEMPLATE structures in the template.
|
||||
/// These DLGITEMTEMPLATE structures must be aligned on DWORD boundaries.
|
||||
/// </summary>
|
||||
public DialogItemTemplate[] DialogItemTemplates;
|
||||
|
||||
/// <summary>
|
||||
/// Following the DLGTEMPLATEEX header in an extended dialog box template is one or more
|
||||
/// DLGITEMTEMPLATEEX structures that describe the controls of the dialog box. The cDlgItems
|
||||
/// member of the DLGITEMTEMPLATEEX structure specifies the number of DLGITEMTEMPLATEEX
|
||||
/// structures that follow in the template.
|
||||
/// </summary>
|
||||
public DialogItemTemplateExtended[] ExtendedDialogItemTemplates;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
133
BurnOutSharp.Models/PortableExecutable/DialogItemTemplate.cs
Normal file
133
BurnOutSharp.Models/PortableExecutable/DialogItemTemplate.cs
Normal file
@@ -0,0 +1,133 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the dimensions and style of a control in a dialog box. One or more of these
|
||||
/// structures are combined with a DLGTEMPLATE structure to form a standard template
|
||||
/// for a dialog box.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-dlgitemtemplate"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class DialogItemTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// The style of the control. This member can be a combination of window style values
|
||||
/// (such as WS_BORDER) and one or more of the control style values (such as
|
||||
/// BS_PUSHBUTTON and ES_LEFT).
|
||||
/// </summary>
|
||||
public WindowStyles Style;
|
||||
|
||||
/// <summary>
|
||||
/// The extended styles for a window. This member is not used to create dialog boxes,
|
||||
/// but applications that use dialog box templates can use it to create other types
|
||||
/// of windows.
|
||||
/// </summary>
|
||||
public ExtendedWindowStyles ExtendedStyle;
|
||||
|
||||
/// <summary>
|
||||
/// The x-coordinate, in dialog box units, of the upper-left corner of the control.
|
||||
/// This coordinate is always relative to the upper-left corner of the dialog box's
|
||||
/// client area.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen
|
||||
/// units (pixels) by using the MapDialogRect function.
|
||||
/// </remarks>
|
||||
public short PositionX;
|
||||
|
||||
/// <summary>
|
||||
/// The y-coordinate, in dialog box units, of the upper-left corner of the control.
|
||||
/// This coordinate is always relative to the upper-left corner of the dialog box's
|
||||
/// client area.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen
|
||||
/// units (pixels) by using the MapDialogRect function.
|
||||
/// </remarks>
|
||||
public short PositionY;
|
||||
|
||||
/// <summary>
|
||||
/// The width, in dialog box units, of the control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen
|
||||
/// units (pixels) by using the MapDialogRect function.
|
||||
/// </remarks>
|
||||
public short WidthX;
|
||||
|
||||
/// <summary>
|
||||
/// The height, in dialog box units, of the control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen
|
||||
/// units (pixels) by using the MapDialogRect function.
|
||||
/// </remarks>
|
||||
public short HeightY;
|
||||
|
||||
/// <summary>
|
||||
/// The control identifier.
|
||||
/// </summary>
|
||||
public ushort ID;
|
||||
|
||||
// In a standard template for a dialog box, the DLGITEMTEMPLATE structure is always immediately
|
||||
// followed by three variable-length arrays specifying the class, title, and creation data for
|
||||
// the control. Each array consists of one or more 16-bit elements.
|
||||
//
|
||||
// Each DLGITEMTEMPLATE structure in the template must be aligned on a DWORD boundary. The class
|
||||
// and title arrays must be aligned on WORD boundaries. The creation data array must be aligned
|
||||
// on a WORD boundary.
|
||||
|
||||
/// <summary>
|
||||
/// Immediately following each DLGITEMTEMPLATE structure is a class array that specifies the window
|
||||
/// class of the control. If the first element of this array is any value other than 0xFFFF, the
|
||||
/// system treats the array as a null-terminated Unicode string that specifies the name of a
|
||||
/// registered window class. If the first element is 0xFFFF, the array has one additional element
|
||||
/// that specifies the ordinal value of a predefined system class.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the
|
||||
/// MultiByteToWideChar function to generate Unicode strings from ANSI strings.
|
||||
/// </remarks>
|
||||
public string ClassResource;
|
||||
|
||||
/// <summary>
|
||||
/// The ordinal value of a predefined system class.
|
||||
/// </summary>
|
||||
public DialogItemTemplateOrdinal ClassResourceOrdinal;
|
||||
|
||||
/// <summary>
|
||||
/// Following the class array is a title array that contains the initial text or resource identifier
|
||||
/// of the control. If the first element of this array is 0xFFFF, the array has one additional element
|
||||
/// that specifies an ordinal value of a resource, such as an icon, in an executable file. You can use
|
||||
/// a resource identifier for controls, such as static icon controls, that load and display an icon
|
||||
/// or other resource rather than text. If the first element is any value other than 0xFFFF, the system
|
||||
/// treats the array as a null-terminated Unicode string that specifies the initial text.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the
|
||||
/// MultiByteToWideChar function to generate Unicode strings from ANSI strings.
|
||||
/// </remarks>
|
||||
public string TitleResource;
|
||||
|
||||
/// <summary>
|
||||
/// An ordinal value of a resource, such as an icon, in an executable file
|
||||
/// </summary>
|
||||
public ushort TitleResourceOrdinal;
|
||||
|
||||
/// <summary>
|
||||
/// The creation data array begins at the next WORD boundary after the title array. This creation data
|
||||
/// can be of any size and format. If the first word of the creation data array is nonzero, it indicates
|
||||
/// the size, in bytes, of the creation data (including the size word).
|
||||
/// </summary>
|
||||
public ushort CreationDataSize;
|
||||
|
||||
/// <summary>
|
||||
/// The creation data array begins at the next WORD boundary after the title array. This creation data
|
||||
/// can be of any size and format. The control's window procedure must be able to interpret the data.
|
||||
/// When the system creates the control, it passes a pointer to this data in the lParam parameter of the
|
||||
/// WM_CREATE message that it sends to the control.
|
||||
/// </summary>
|
||||
public byte[] CreationData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// A block of text used by an extended dialog box template to describe the extended dialog box.
|
||||
/// For a description of the format of an extended dialog box template, see DLGTEMPLATEEX.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/dlgbox/dlgitemtemplateex"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class DialogItemTemplateExtended
|
||||
{
|
||||
/// <summary>
|
||||
/// The help context identifier for the control. When the system sends a WM_HELP message,
|
||||
/// it passes the helpID value in the dwContextId member of the HELPINFO structure.
|
||||
/// </summary>
|
||||
public uint HelpID;
|
||||
|
||||
/// <summary>
|
||||
/// The extended styles for a window. This member is not used to create controls in dialog
|
||||
/// boxes, but applications that use dialog box templates can use it to create other types
|
||||
/// of windows.
|
||||
/// </summary>
|
||||
public ExtendedWindowStyles ExtendedStyle;
|
||||
|
||||
/// <summary>
|
||||
/// The style of the control. This member can be a combination of window style values
|
||||
/// (such as WS_BORDER) and one or more of the control style values (such as
|
||||
/// BS_PUSHBUTTON and ES_LEFT).
|
||||
/// </summary>
|
||||
public WindowStyles Style;
|
||||
|
||||
/// <summary>
|
||||
/// The x-coordinate, in dialog box units, of the upper-left corner of the control.
|
||||
/// This coordinate is always relative to the upper-left corner of the dialog box's
|
||||
/// client area.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen
|
||||
/// units (pixels) by using the MapDialogRect function.
|
||||
/// </remarks>
|
||||
public short PositionX;
|
||||
|
||||
/// <summary>
|
||||
/// The y-coordinate, in dialog box units, of the upper-left corner of the control.
|
||||
/// This coordinate is always relative to the upper-left corner of the dialog box's
|
||||
/// client area.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen
|
||||
/// units (pixels) by using the MapDialogRect function.
|
||||
/// </remarks>
|
||||
public short PositionY;
|
||||
|
||||
/// <summary>
|
||||
/// The width, in dialog box units, of the control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen
|
||||
/// units (pixels) by using the MapDialogRect function.
|
||||
/// </remarks>
|
||||
public short WidthX;
|
||||
|
||||
/// <summary>
|
||||
/// The height, in dialog box units, of the control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen
|
||||
/// units (pixels) by using the MapDialogRect function.
|
||||
/// </remarks>
|
||||
public short HeightY;
|
||||
|
||||
/// <summary>
|
||||
/// The control identifier.
|
||||
/// </summary>
|
||||
public uint ID;
|
||||
|
||||
/// <summary>
|
||||
/// A variable-length array of 16-bit elements that specifies the window class of the control. If
|
||||
/// the first element of this array is any value other than 0xFFFF, the system treats the array as
|
||||
/// a null-terminated Unicode string that specifies the name of a registered window class.
|
||||
///
|
||||
/// If the first element is 0xFFFF, the array has one additional element that specifies the ordinal
|
||||
/// value of a predefined system class.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the
|
||||
/// MultiByteToWideChar function to generate Unicode strings from ANSI strings.
|
||||
/// </remarks>
|
||||
public string ClassResource;
|
||||
|
||||
/// <summary>
|
||||
/// The ordinal value of a predefined system class.
|
||||
/// </summary>
|
||||
public DialogItemTemplateOrdinal ClassResourceOrdinal;
|
||||
|
||||
/// <summary>
|
||||
/// A variable-length array of 16-bit elements that contains the initial text or resource identifier of the
|
||||
/// control. If the first element of this array is 0xFFFF, the array has one additional element that
|
||||
/// specifies the ordinal value of a resource, such as an icon, in an executable file. You can use a
|
||||
/// resource identifier for controls, such as static icon controls, that load and display an icon or other
|
||||
/// resource rather than text. If the first element is any value other than 0xFFFF, the system treats the
|
||||
/// array as a null-terminated Unicode string that specifies the initial text.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the
|
||||
/// MultiByteToWideChar function to generate Unicode strings from ANSI strings.
|
||||
/// </remarks>
|
||||
public string TitleResource;
|
||||
|
||||
/// <summary>
|
||||
/// An ordinal value of a resource, such as an icon, in an executable file
|
||||
/// </summary>
|
||||
public ushort TitleResourceOrdinal;
|
||||
|
||||
/// <summary>
|
||||
/// The creation data array begins at the next WORD boundary after the title array. This creation data
|
||||
/// can be of any size and format. If the first word of the creation data array is nonzero, it indicates
|
||||
/// the size, in bytes, of the creation data (including the size word).
|
||||
/// </summary>
|
||||
public ushort CreationDataSize;
|
||||
|
||||
/// <summary>
|
||||
/// The creation data array begins at the next WORD boundary after the title array. This creation data
|
||||
/// can be of any size and format. The control's window procedure must be able to interpret the data.
|
||||
/// When the system creates the control, it passes a pointer to this data in the lParam parameter of the
|
||||
/// WM_CREATE message that it sends to the control.
|
||||
/// </summary>
|
||||
public byte[] CreationData;
|
||||
}
|
||||
}
|
||||
163
BurnOutSharp.Models/PortableExecutable/DialogTemplate.cs
Normal file
163
BurnOutSharp.Models/PortableExecutable/DialogTemplate.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the dimensions and style of a dialog box. This structure, always the first
|
||||
/// in a standard template for a dialog box, also specifies the number of controls in
|
||||
/// the dialog box and therefore specifies the number of subsequent DLGITEMTEMPLATE
|
||||
/// structures in the template.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-dlgtemplate"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class DialogTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// The style of the dialog box. This member can be a combination of window style
|
||||
/// values (such as WS_CAPTION and WS_SYSMENU) and dialog box style values (such
|
||||
/// as DS_CENTER).
|
||||
///
|
||||
/// If the style member includes the DS_SETFONT style, the header of the dialog box
|
||||
/// template contains additional data specifying the font to use for text in the
|
||||
/// client area and controls of the dialog box. The font data begins on the WORD
|
||||
/// boundary that follows the title array. The font data specifies a 16-bit point
|
||||
/// size value and a Unicode font name string. If possible, the system creates a
|
||||
/// font according to the specified values. Then the system sends a WM_SETFONT
|
||||
/// message to the dialog box and to each control to provide a handle to the font.
|
||||
/// If DS_SETFONT is not specified, the dialog box template does not include the
|
||||
/// font data.
|
||||
///
|
||||
/// The DS_SHELLFONT style is not supported in the DLGTEMPLATE header.
|
||||
/// </summary>
|
||||
public WindowStyles Style;
|
||||
|
||||
/// <summary>
|
||||
/// The extended styles for a window. This member is not used to create dialog boxes,
|
||||
/// but applications that use dialog box templates can use it to create other types
|
||||
/// of windows.
|
||||
/// </summary>
|
||||
public ExtendedWindowStyles ExtendedStyle;
|
||||
|
||||
/// <summary>
|
||||
/// The number of items in the dialog box.
|
||||
/// </summary>
|
||||
public ushort ItemCount;
|
||||
|
||||
/// <summary>
|
||||
/// The x-coordinate, in dialog box units, of the upper-left corner of the dialog box.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values
|
||||
/// to screen units (pixels) by using the MapDialogRect function.
|
||||
/// </remarks>
|
||||
public short PositionX;
|
||||
|
||||
/// <summary>
|
||||
/// The y-coordinate, in dialog box units, of the upper-left corner of the dialog box.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values
|
||||
/// to screen units (pixels) by using the MapDialogRect function.
|
||||
/// </remarks>
|
||||
public short PositionY;
|
||||
|
||||
/// <summary>
|
||||
/// The width, in dialog box units, of the dialog box.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values
|
||||
/// to screen units (pixels) by using the MapDialogRect function.
|
||||
/// </remarks>
|
||||
public short WidthX;
|
||||
|
||||
/// <summary>
|
||||
/// The height, in dialog box units, of the dialog box.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values
|
||||
/// to screen units (pixels) by using the MapDialogRect function.
|
||||
/// </remarks>
|
||||
public short HeightY;
|
||||
|
||||
// In a standard template for a dialog box, the DLGTEMPLATE structure is always immediately
|
||||
// followed by three variable-length arrays that specify the menu, class, and title for the
|
||||
// dialog box. When the DS_SETFONT style is specified, these arrays are also followed by a
|
||||
// 16-bit value specifying point size and another variable-length array specifying a
|
||||
// typeface name. Each array consists of one or more 16-bit elements. The menu, class, title,
|
||||
// and font arrays must be aligned on WORD boundaries.
|
||||
|
||||
/// <summary>
|
||||
/// Immediately following the DLGTEMPLATE structure is a menu array that identifies a menu
|
||||
/// resource for the dialog box. If the first element of this array is 0x0000, the dialog box
|
||||
/// has no menu and the array has no other elements. If the first element is 0xFFFF, the array
|
||||
/// has one additional element that specifies the ordinal value of a menu resource in an
|
||||
/// executable file. If the first element has any other value, the system treats the array as
|
||||
/// a null-terminated Unicode string that specifies the name of a menu resource in an executable
|
||||
/// file.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you specify character strings in the menu, class, title, or typeface arrays, you must use
|
||||
/// Unicode strings.
|
||||
/// </remarks>
|
||||
public string MenuResource;
|
||||
|
||||
/// <summary>
|
||||
/// The ordinal value of a menu resource in an executable file.
|
||||
/// </summary>
|
||||
public ushort MenuResourceOrdinal;
|
||||
|
||||
/// <summary>
|
||||
/// Following the menu array is a class array that identifies the window class of the dialog box.
|
||||
/// If the first element of the array is 0x0000, the system uses the predefined dialog box class
|
||||
/// for the dialog box and the array has no other elements. If the first element is 0xFFFF,
|
||||
/// the array has one additional element that specifies the ordinal value of a predefined system
|
||||
/// window class. If the first element has any other value, the system treats the array as a
|
||||
/// null-terminated Unicode string that specifies the name of a registered window class.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you specify character strings in the menu, class, title, or typeface arrays, you must use
|
||||
/// Unicode strings.
|
||||
/// </remarks>
|
||||
public string ClassResource;
|
||||
|
||||
/// <summary>
|
||||
/// The ordinal value of a predefined system class.
|
||||
/// </summary>
|
||||
public ushort ClassResourceOrdinal;
|
||||
|
||||
/// <summary>
|
||||
/// Following the class array is a title array that specifies a null-terminated Unicode string
|
||||
/// that contains the title of the dialog box. If the first element of this array is 0x0000,
|
||||
/// the dialog box has no title and the array has no other elements.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you specify character strings in the menu, class, title, or typeface arrays, you must use
|
||||
/// Unicode strings.
|
||||
/// </remarks>
|
||||
public string TitleResource;
|
||||
|
||||
/// <summary>
|
||||
/// The 16-bit point size value and the typeface array follow the title array, but only if the
|
||||
/// style member specifies the DS_SETFONT style. The point size value specifies the point size
|
||||
/// of the font to use for the text in the dialog box and its controls. When these values are
|
||||
/// specified, the system creates a font having the specified size and typeface (if possible)
|
||||
/// and sends a WM_SETFONT message to the dialog box procedure and the control window
|
||||
/// procedures as it creates the dialog box and controls.
|
||||
/// </summary>
|
||||
public ushort PointSizeValue;
|
||||
|
||||
/// <summary>
|
||||
/// The 16-bit point size value and the typeface array follow the title array, but only if the
|
||||
/// style member specifies the DS_SETFONT style. The typeface array is a null-terminated Unicode
|
||||
/// string specifying the name of the typeface for the font. When these values are specified,
|
||||
/// the system creates a font having the specified size and typeface (if possible) and sends a
|
||||
/// WM_SETFONT message to the dialog box procedure and the control window procedures as it
|
||||
/// creates the dialog box and controls.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you specify character strings in the menu, class, title, or typeface arrays, you must use
|
||||
/// Unicode strings.
|
||||
/// </remarks>
|
||||
public string Typeface;
|
||||
}
|
||||
}
|
||||
188
BurnOutSharp.Models/PortableExecutable/DialogTemplateExtended.cs
Normal file
188
BurnOutSharp.Models/PortableExecutable/DialogTemplateExtended.cs
Normal file
@@ -0,0 +1,188 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// An extended dialog box template begins with a DLGTEMPLATEEX header that describes
|
||||
/// the dialog box and specifies the number of controls in the dialog box. For each
|
||||
/// control in a dialog box, an extended dialog box template has a block of data that
|
||||
/// uses the DLGITEMTEMPLATEEX format to describe the control.
|
||||
///
|
||||
/// The DLGTEMPLATEEX structure is not defined in any standard header file. The
|
||||
/// structure definition is provided here to explain the format of an extended template
|
||||
/// for a dialog box.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/dlgbox/dlgtemplateex"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class DialogTemplateExtended
|
||||
{
|
||||
/// <summary>
|
||||
/// The version number of the extended dialog box template. This member must be
|
||||
/// set to 1.
|
||||
/// </summary>
|
||||
public ushort Version;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether a template is an extended dialog box template. If signature
|
||||
/// is 0xFFFF, this is an extended dialog box template. In this case, the dlgVer
|
||||
/// member specifies the template version number. If signature is any value other
|
||||
/// than 0xFFFF, this is a standard dialog box template that uses the DLGTEMPLATE
|
||||
/// and DLGITEMTEMPLATE structures.
|
||||
/// </summary>
|
||||
public ushort Signature;
|
||||
|
||||
/// <summary>
|
||||
/// The help context identifier for the dialog box window. When the system sends a
|
||||
/// WM_HELP message, it passes this value in the wContextId member of the HELPINFO
|
||||
/// structure.
|
||||
/// </summary>
|
||||
public uint HelpID;
|
||||
|
||||
/// <summary>
|
||||
/// The extended windows styles. This member is not used when creating dialog boxes,
|
||||
/// but applications that use dialog box templates can use it to create other types
|
||||
/// of windows.
|
||||
/// </summary>
|
||||
public ExtendedWindowStyles ExtendedStyle;
|
||||
|
||||
/// <summary>
|
||||
/// The style of the dialog box.
|
||||
///
|
||||
/// If style includes the DS_SETFONT or DS_SHELLFONT dialog box style, the DLGTEMPLATEEX
|
||||
/// header of the extended dialog box template contains four additional members (pointsize,
|
||||
/// weight, italic, and typeface) that describe the font to use for the text in the client
|
||||
/// area and controls of the dialog box. If possible, the system creates a font according
|
||||
/// to the values specified in these members. Then the system sends a WM_SETFONT message
|
||||
/// to the dialog box and to each control to provide a handle to the font.
|
||||
/// </summary>
|
||||
public WindowStyles Style;
|
||||
|
||||
/// <summary>
|
||||
/// The number of controls in the dialog box.
|
||||
/// </summary>
|
||||
public ushort DialogItems;
|
||||
|
||||
/// <summary>
|
||||
/// The x-coordinate, in dialog box units, of the upper-left corner of the dialog box.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values
|
||||
/// to screen units (pixels) by using the MapDialogRect function.
|
||||
/// </remarks>
|
||||
public short PositionX;
|
||||
|
||||
/// <summary>
|
||||
/// The y-coordinate, in dialog box units, of the upper-left corner of the dialog box.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values
|
||||
/// to screen units (pixels) by using the MapDialogRect function.
|
||||
/// </remarks>
|
||||
public short PositionY;
|
||||
|
||||
/// <summary>
|
||||
/// The width, in dialog box units, of the dialog box.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values
|
||||
/// to screen units (pixels) by using the MapDialogRect function.
|
||||
/// </remarks>
|
||||
public short WidthX;
|
||||
|
||||
/// <summary>
|
||||
/// The height, in dialog box units, of the dialog box.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The x, y, cx, and cy members specify values in dialog box units. You can convert these values
|
||||
/// to screen units (pixels) by using the MapDialogRect function.
|
||||
/// </remarks>
|
||||
public short HeightY;
|
||||
|
||||
/// <summary>
|
||||
/// A variable-length array of 16-bit elements that identifies a menu resource for the dialog box.
|
||||
/// If the first element of this array is 0x0000, the dialog box has no menu and the array has no
|
||||
/// other elements. If the first element is 0xFFFF, the array has one additional element that
|
||||
/// specifies the ordinal value of a menu resource in an executable file. If the first element has
|
||||
/// any other value, the system treats the array as a null-terminated Unicode string that specifies
|
||||
/// the name of a menu resource in an executable file.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the
|
||||
/// MultiByteToWideChar function to generate Unicode strings from ANSI strings.
|
||||
/// </remarks>
|
||||
public string MenuResource;
|
||||
|
||||
/// <summary>
|
||||
/// The ordinal value of a menu resource in an executable file.
|
||||
/// </summary>
|
||||
public ushort MenuResourceOrdinal;
|
||||
|
||||
/// <summary>A variable-length array of 16-bit elements that identifies the window class of the
|
||||
/// dialog box. If the first element of the array is 0x0000, the system uses the predefined dialog
|
||||
/// box class for the dialog box and the array has no other elements. If the first element is 0xFFFF,
|
||||
/// the array has one additional element that specifies the ordinal value of a predefined system
|
||||
/// window class. If the first element has any other value, the system treats the array as a
|
||||
/// null-terminated Unicode string that specifies the name of a registered window class.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the
|
||||
/// MultiByteToWideChar function to generate Unicode strings from ANSI strings.
|
||||
/// </remarks>
|
||||
public string ClassResource;
|
||||
|
||||
/// <summary>
|
||||
/// The ordinal value of a predefined system window class.
|
||||
/// </summary>
|
||||
public ushort ClassResourceOrdinal;
|
||||
|
||||
/// <summary>
|
||||
/// The title of the dialog box. If the first element of this array is 0x0000, the dialog box has no
|
||||
/// title and the array has no other elements.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the
|
||||
/// MultiByteToWideChar function to generate Unicode strings from ANSI strings.
|
||||
/// </remarks>
|
||||
public string TitleResource;
|
||||
|
||||
/// <summary>
|
||||
/// The point size of the font to use for the text in the dialog box and its controls.
|
||||
///
|
||||
/// This member is present only if the style member specifies DS_SETFONT or DS_SHELLFONT.
|
||||
/// </summary>
|
||||
public ushort PointSize;
|
||||
|
||||
/// <summary>
|
||||
/// The weight of the font. Note that, although this can be any of the values listed for the lfWeight
|
||||
/// member of the LOGFONT structure, any value that is used will be automatically changed to FW_NORMAL.
|
||||
///
|
||||
/// This member is present only if the style member specifies DS_SETFONT or DS_SHELLFONT.
|
||||
/// </summary>
|
||||
public ushort Weight;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the font is italic. If this value is TRUE, the font is italic.
|
||||
///
|
||||
/// This member is present only if the style member specifies DS_SETFONT or DS_SHELLFONT.
|
||||
/// </summary>
|
||||
public byte Italic;
|
||||
|
||||
/// <summary>
|
||||
/// The character set to be used. For more information, see the lfcharset member of LOGFONT.
|
||||
///
|
||||
/// This member is present only if the style member specifies DS_SETFONT or DS_SHELLFONT.
|
||||
/// </summary>
|
||||
public byte CharSet;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the typeface for the font.
|
||||
///
|
||||
/// This member is present only if the style member specifies DS_SETFONT or DS_SHELLFONT.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the
|
||||
/// MultiByteToWideChar function to generate Unicode strings from ANSI strings.
|
||||
/// </remarks>
|
||||
public string Typeface;
|
||||
}
|
||||
}
|
||||
21
BurnOutSharp.Models/PortableExecutable/DirEntry.cs
Normal file
21
BurnOutSharp.Models/PortableExecutable/DirEntry.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the information necessary for an application to access a specific font. The structure
|
||||
/// definition provided here is for explanation only; it is not present in any standard header file.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/direntry"/>
|
||||
public class DirEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// A unique ordinal identifier for an individual font in a font resource group.
|
||||
/// </summary>
|
||||
public ushort FontOrdinal;
|
||||
|
||||
/// <summary>
|
||||
/// The FONTDIRENTRY structure for the specified font directly follows the DIRENTRY structure
|
||||
/// for that font.
|
||||
/// </summary>
|
||||
public FontDirEntry Entry;
|
||||
}
|
||||
}
|
||||
3373
BurnOutSharp.Models/PortableExecutable/Enums.cs
Normal file
3373
BurnOutSharp.Models/PortableExecutable/Enums.cs
Normal file
File diff suppressed because it is too large
Load Diff
139
BurnOutSharp.Models/PortableExecutable/Executable.cs
Normal file
139
BurnOutSharp.Models/PortableExecutable/Executable.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The following list describes the Microsoft PE executable format, with the
|
||||
/// base of the image header at the top. The section from the MS-DOS 2.0
|
||||
/// Compatible EXE Header through to the unused section just before the PE header
|
||||
/// is the MS-DOS 2.0 Section, and is used for MS-DOS compatibility only.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
public class Executable
|
||||
{
|
||||
/// <summary>
|
||||
/// MS-DOS executable stub
|
||||
/// </summary>
|
||||
public MSDOS.Executable Stub { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// After the MS-DOS stub, at the file offset specified at offset 0x3c, is a 4-byte
|
||||
/// signature that identifies the file as a PE format image file. This signature is "PE\0\0"
|
||||
/// (the letters "P" and "E" followed by two null bytes).
|
||||
/// </summary>
|
||||
public byte[] Signature { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// COFF file header
|
||||
/// </summary>
|
||||
public COFFFileHeader COFFFileHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional header
|
||||
/// </summary>
|
||||
public OptionalHeader OptionalHeader { get; set; }
|
||||
|
||||
// TODO: Support grouped sections in section reading and parsing
|
||||
// https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#grouped-sections-object-only
|
||||
// Grouped sections are ordered and mean that the data in the sections contributes
|
||||
// to the "base" section (the one without the "$X" suffix). This may negatively impact
|
||||
// the use of some of the different types of executables.
|
||||
|
||||
/// <summary>
|
||||
/// Section table
|
||||
/// </summary>
|
||||
public SectionHeader[] SectionTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// COFF symbol table
|
||||
/// </summary>
|
||||
public COFFSymbolTableEntry[] COFFSymbolTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// COFF string table
|
||||
/// </summary>
|
||||
public COFFStringTable COFFStringTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Attribute certificate table
|
||||
/// </summary>
|
||||
public AttributeCertificateTableEntry[] AttributeCertificateTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Delay-load directory table
|
||||
/// </summary>
|
||||
public DelayLoadDirectoryTable DelayLoadDirectoryTable { get; set; }
|
||||
|
||||
#region Named Sections
|
||||
|
||||
// .cormeta - CLR metadata is stored in this section. It is used to indicate that
|
||||
// the object file contains managed code. The format of the metadata is not
|
||||
// documented, but can be handed to the CLR interfaces for handling metadata.
|
||||
|
||||
/// <summary>
|
||||
/// Base relocation table (.reloc)
|
||||
/// </summary>
|
||||
public BaseRelocationBlock[] BaseRelocationTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Debug table (.debug*)
|
||||
/// </summary>
|
||||
public DebugTable DebugTable { get; set; }
|
||||
|
||||
// .drectve - A section is a directive section if it has the IMAGE_SCN_LNK_INFO
|
||||
// flag set in the section header and has the .drectve section name. The linker
|
||||
// removes a .drectve section after processing the information, so the section
|
||||
// does not appear in the image file that is being linked.
|
||||
//
|
||||
// A .drectve section consists of a string of text that can be encoded as ANSI
|
||||
// or UTF-8. If the UTF-8 byte order marker (BOM, a three-byte prefix that
|
||||
// consists of 0xEF, 0xBB, and 0xBF) is not present, the directive string is
|
||||
// interpreted as ANSI. The directive string is a series of linker options that
|
||||
// are separated by spaces. Each option contains a hyphen, the option name, and
|
||||
// any appropriate attribute. If an option contains spaces, the option must be
|
||||
// enclosed in quotes. The .drectve section must not have relocations or line
|
||||
// numbers.
|
||||
//
|
||||
// TODO: Can we implement reading/parsing the .drectve section?
|
||||
|
||||
/// <summary>
|
||||
/// Export table (.edata)
|
||||
/// </summary>
|
||||
public ExportTable ExportTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Import table (.idata)
|
||||
/// </summary>
|
||||
public ImportTable ImportTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Resource directory table (.rsrc)
|
||||
/// </summary>
|
||||
public ResourceDirectoryTable ResourceDirectoryTable { get; set; }
|
||||
|
||||
// .sxdata - The valid exception handlers of an object are listed in the .sxdata
|
||||
// section of that object. The section is marked IMAGE_SCN_LNK_INFO. It contains
|
||||
// the COFF symbol index of each valid handler, using 4 bytes per index.
|
||||
//
|
||||
// Additionally, the compiler marks a COFF object as registered SEH by emitting
|
||||
// the absolute symbol "@feat.00" with the LSB of the value field set to 1. A
|
||||
// COFF object with no registered SEH handlers would have the "@feat.00" symbol,
|
||||
// but no .sxdata section.
|
||||
//
|
||||
// TODO: Can we implement reading/parsing the .sxdata section?
|
||||
|
||||
#endregion
|
||||
|
||||
// TODO: Implement and/or document the following non-modeled parts:
|
||||
// - Delay-Load Import Tables
|
||||
// - [The Delay-Load Directory Table]
|
||||
// - Delay Import Address Table
|
||||
// - Delay Import Name Table
|
||||
// - Delay Bound Import Address Table
|
||||
// - Delay Unload Import Address Table
|
||||
// - The .pdata Section [Multiple formats per entry]
|
||||
// - The .tls Section
|
||||
// - TLS Callback Functions
|
||||
// - [The Load Configuration Structure (Image Only)]
|
||||
|
||||
// TODO: Determine if "Archive (Library) File Format" is worth modelling
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The export address table contains the address of exported entry points
|
||||
/// and exported data and absolutes. An ordinal number is used as an index
|
||||
/// into the export address table.
|
||||
///
|
||||
/// Each entry in the export address table is a field that uses one of two
|
||||
/// formats in the following table. If the address specified is not within
|
||||
/// the export section (as defined by the address and length that are
|
||||
/// indicated in the optional header), the field is an export RVA, which is
|
||||
/// an actual address in code or data. Otherwise, the field is a forwarder RVA,
|
||||
/// which names a symbol in another DLL.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public class ExportAddressTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// The address of the exported symbol when loaded into memory, relative to
|
||||
/// the image base. For example, the address of an exported function.
|
||||
/// </summary>
|
||||
[FieldOffset(0)] public uint ExportRVA;
|
||||
|
||||
/// <summary>
|
||||
/// The pointer to a null-terminated ASCII string in the export section. This
|
||||
/// string must be within the range that is given by the export table data
|
||||
/// directory entry. See Optional Header Data Directories (Image Only). This
|
||||
/// string gives the DLL name and the name of the export (for example,
|
||||
/// "MYDLL.expfunc") or the DLL name and the ordinal number of the export
|
||||
/// (for example, "MYDLL.#27").
|
||||
/// </summary>
|
||||
[FieldOffset(0)] public uint ForwarderRVA;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The export symbol information begins with the export directory table,
|
||||
/// which describes the remainder of the export symbol information. The
|
||||
/// export directory table contains address information that is used to resolve
|
||||
/// imports to the entry points within this image.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ExportDirectoryTable
|
||||
{
|
||||
/// <summary>
|
||||
/// Reserved, must be 0.
|
||||
/// </summary>
|
||||
public uint ExportFlags;
|
||||
|
||||
/// <summary>
|
||||
/// The time and date that the export data was created.
|
||||
/// </summary>
|
||||
public uint TimeDateStamp;
|
||||
|
||||
/// <summary>
|
||||
/// The major version number. The major and minor version numbers can be set
|
||||
/// by the user.
|
||||
/// </summary>
|
||||
public ushort MajorVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The minor version number.
|
||||
/// </summary>
|
||||
public ushort MinorVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The address of the ASCII string that contains the name of the DLL. This
|
||||
/// address is relative to the image base.
|
||||
/// </summary>
|
||||
public uint NameRVA;
|
||||
|
||||
/// <summary>
|
||||
/// ASCII string that contains the name of the DLL.
|
||||
/// </summary>
|
||||
public string Name;
|
||||
|
||||
/// <summary>
|
||||
/// The starting ordinal number for exports in this image. This field specifies
|
||||
/// the starting ordinal number for the export address table. It is usually set
|
||||
/// to 1.
|
||||
/// </summary>
|
||||
public uint OrdinalBase;
|
||||
|
||||
/// <summary>
|
||||
/// The number of entries in the export address table.
|
||||
/// </summary>
|
||||
public uint AddressTableEntries;
|
||||
|
||||
/// <summary>
|
||||
/// The number of entries in the name pointer table. This is also the number of
|
||||
/// entries in the ordinal table.
|
||||
/// </summary>
|
||||
public uint NumberOfNamePointers;
|
||||
|
||||
/// <summary>
|
||||
/// The address of the export address table, relative to the image base.
|
||||
/// </summary>
|
||||
public uint ExportAddressTableRVA;
|
||||
|
||||
/// <summary>
|
||||
/// The address of the export name pointer table, relative to the image base.
|
||||
/// The table size is given by the Number of Name Pointers field.
|
||||
/// </summary>
|
||||
public uint NamePointerRVA;
|
||||
|
||||
/// <summary>
|
||||
/// The address of the ordinal table, relative to the image base.
|
||||
/// </summary>
|
||||
public uint OrdinalTableRVA;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The export name pointer table is an array of addresses (RVAs) into the export name table.
|
||||
/// The pointers are 32 bits each and are relative to the image base. The pointers are ordered
|
||||
/// lexically to allow binary searches.
|
||||
///
|
||||
/// An export name is defined only if the export name pointer table contains a pointer to it.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
public class ExportNamePointerTable
|
||||
{
|
||||
/// <summary>
|
||||
/// The pointers are 32 bits each and are relative to the image base.
|
||||
/// </summary>
|
||||
public uint[] Pointers;
|
||||
}
|
||||
}
|
||||
27
BurnOutSharp.Models/PortableExecutable/ExportNameTable.cs
Normal file
27
BurnOutSharp.Models/PortableExecutable/ExportNameTable.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The export name table contains the actual string data that was pointed to by the export
|
||||
/// name pointer table. The strings in this table are public names that other images can use
|
||||
/// to import the symbols. These public export names are not necessarily the same as the
|
||||
/// private symbol names that the symbols have in their own image file and source code,
|
||||
/// although they can be.
|
||||
///
|
||||
/// Every exported symbol has an ordinal value, which is just the index into the export
|
||||
/// address table. Use of export names, however, is optional. Some, all, or none of the
|
||||
/// exported symbols can have export names. For exported symbols that do have export names,
|
||||
/// corresponding entries in the export name pointer table and export ordinal table work
|
||||
/// together to associate each name with an ordinal.
|
||||
///
|
||||
/// The structure of the export name table is a series of null-terminated ASCII strings
|
||||
/// of variable length.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
public class ExportNameTable
|
||||
{
|
||||
/// <summary>
|
||||
/// A series of null-terminated ASCII strings of variable length.
|
||||
/// </summary>
|
||||
public string[] Strings;
|
||||
}
|
||||
}
|
||||
42
BurnOutSharp.Models/PortableExecutable/ExportOrdinalTable.cs
Normal file
42
BurnOutSharp.Models/PortableExecutable/ExportOrdinalTable.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The export ordinal table is an array of 16-bit unbiased indexes into the export address table.
|
||||
/// Ordinals are biased by the Ordinal Base field of the export directory table. In other words,
|
||||
/// the ordinal base must be subtracted from the ordinals to obtain true indexes into the export
|
||||
/// address table.
|
||||
///
|
||||
/// The export name pointer table and the export ordinal table form two parallel arrays that are
|
||||
/// separated to allow natural field alignment. These two tables, in effect, operate as one table,
|
||||
/// in which the Export Name Pointer column points to a public (exported) name and the Export
|
||||
/// Ordinal column gives the corresponding ordinal for that public name. A member of the export
|
||||
/// name pointer table and a member of the export ordinal table are associated by having the same
|
||||
/// position (index) in their respective arrays.
|
||||
///
|
||||
/// Thus, when the export name pointer table is searched and a matching string is found at position
|
||||
/// i, the algorithm for finding the symbol's RVA and biased ordinal is:
|
||||
///
|
||||
/// i = Search_ExportNamePointerTable(name);
|
||||
/// ordinal = ExportOrdinalTable[i];
|
||||
///
|
||||
/// rva = ExportAddressTable[ordinal];
|
||||
/// biased_ordinal = ordinal + OrdinalBase;
|
||||
///
|
||||
/// When searching for a symbol by(biased) ordinal, the algorithm for finding the symbol's RVA
|
||||
/// and name is:
|
||||
///
|
||||
/// ordinal = biased_ordinal - OrdinalBase;
|
||||
/// i = Search_ExportOrdinalTable(ordinal);
|
||||
///
|
||||
/// rva = ExportAddressTable[ordinal];
|
||||
/// name = ExportNameTable[i];
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
public class ExportOrdinalTable
|
||||
{
|
||||
/// <summary>
|
||||
/// An array of 16-bit unbiased indexes into the export address table
|
||||
/// </summary>
|
||||
public ushort[] Indexes;
|
||||
}
|
||||
}
|
||||
53
BurnOutSharp.Models/PortableExecutable/ExportTable.cs
Normal file
53
BurnOutSharp.Models/PortableExecutable/ExportTable.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The export data section, named .edata, contains information about symbols that other images
|
||||
/// can access through dynamic linking. Exported symbols are generally found in DLLs, but DLLs
|
||||
/// can also import symbols.
|
||||
///
|
||||
/// An overview of the general structure of the export section is described below. The tables
|
||||
/// described are usually contiguous in the file in the order shown (though this is not
|
||||
/// required). Only the export directory table and export address table are required to export
|
||||
/// symbols as ordinals. (An ordinal is an export that is accessed directly by its export
|
||||
/// address table index.) The name pointer table, ordinal table, and export name table all
|
||||
/// exist to support use of export names.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
public class ExportTable
|
||||
{
|
||||
/// <summary>
|
||||
/// A table with just one row (unlike the debug directory). This table indicates the
|
||||
/// locations and sizes of the other export tables.
|
||||
/// </summary>
|
||||
public ExportDirectoryTable ExportDirectoryTable;
|
||||
|
||||
/// <summary>
|
||||
/// An array of RVAs of exported symbols. These are the actual addresses of the exported
|
||||
/// functions and data within the executable code and data sections. Other image files
|
||||
/// can import a symbol by using an index to this table (an ordinal) or, optionally, by
|
||||
/// using the public name that corresponds to the ordinal if a public name is defined.
|
||||
/// </summary>
|
||||
public ExportAddressTableEntry[] ExportAddressTable;
|
||||
|
||||
/// <summary>
|
||||
/// An array of pointers to the public export names, sorted in ascending order.
|
||||
/// </summary>
|
||||
public ExportNamePointerTable NamePointerTable;
|
||||
|
||||
/// <summary>
|
||||
/// An array of the ordinals that correspond to members of the name pointer table. The
|
||||
/// correspondence is by position; therefore, the name pointer table and the ordinal table
|
||||
/// must have the same number of members. Each ordinal is an index into the export address
|
||||
/// table.
|
||||
/// </summary>
|
||||
public ExportOrdinalTable OrdinalTable;
|
||||
|
||||
/// <summary>
|
||||
/// A series of null-terminated ASCII strings. Members of the name pointer table point into
|
||||
/// this area. These names are the public names through which the symbols are imported and
|
||||
/// exported; they are not necessarily the same as the private names that are used within
|
||||
/// the image file.
|
||||
/// </summary>
|
||||
public ExportNameTable ExportNameTable;
|
||||
}
|
||||
}
|
||||
88
BurnOutSharp.Models/PortableExecutable/FixedFileInfo.cs
Normal file
88
BurnOutSharp.Models/PortableExecutable/FixedFileInfo.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains version information for a file. This information is language and
|
||||
/// code page independent.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/api/verrsrc/ns-verrsrc-vs_fixedfileinfo"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class FixedFileInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the value 0xFEEF04BD. This is used with the szKey member of the VS_VERSIONINFO
|
||||
/// structure when searching a file for the FixedFileInfo structure.
|
||||
/// </summary>
|
||||
public uint Signature;
|
||||
|
||||
/// <summary>
|
||||
/// The binary version number of this structure. The high-order word of this member contains
|
||||
/// the major version number, and the low-order word contains the minor version number.
|
||||
/// </summary>
|
||||
public uint StrucVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The most significant 32 bits of the file's binary version number. This member is used with
|
||||
/// FileVersionLS to form a 64-bit value used for numeric comparisons.
|
||||
/// </summary>
|
||||
public uint FileVersionMS;
|
||||
|
||||
/// <summary>
|
||||
/// The least significant 32 bits of the file's binary version number. This member is used with
|
||||
/// FileVersionMS to form a 64-bit value used for numeric comparisons.
|
||||
/// </summary>
|
||||
public uint FileVersionLS;
|
||||
|
||||
/// <summary>
|
||||
/// The most significant 32 bits of the binary version number of the product with which this file
|
||||
/// was distributed. This member is used with ProductVersionLS to form a 64-bit value used for
|
||||
/// numeric comparisons.
|
||||
/// </summary>
|
||||
public uint ProductVersionMS;
|
||||
|
||||
/// <summary>
|
||||
/// The least significant 32 bits of the binary version number of the product with which this file
|
||||
/// was distributed. This member is used with ProductVersionMS to form a 64-bit value used for
|
||||
/// numeric comparisons.
|
||||
/// </summary>
|
||||
public uint ProductVersionLS;
|
||||
|
||||
/// <summary>
|
||||
/// Contains a bitmask that specifies the valid bits in FileFlags. A bit is valid only if it was
|
||||
/// defined when the file was created.
|
||||
/// </summary>
|
||||
public uint FileFlagsMask;
|
||||
|
||||
/// <summary>
|
||||
/// Contains a bitmask that specifies the Boolean attributes of the file.
|
||||
/// </summary>
|
||||
public FixedFileInfoFlags FileFlags;
|
||||
|
||||
/// <summary>
|
||||
/// The operating system for which this file was designed.
|
||||
/// </summary>
|
||||
public FixedFileInfoOS FileOS;
|
||||
|
||||
/// <summary>
|
||||
/// The general type of file.
|
||||
/// </summary>
|
||||
public FixedFileInfoFileType FileType;
|
||||
|
||||
/// <summary>
|
||||
/// The function of the file. The possible values depend on the value of FileType. For all values
|
||||
/// of FileType not described in the following list, FileSubtype is zero.
|
||||
/// </summary>
|
||||
public FixedFileInfoFileSubtype FileSubtype;
|
||||
|
||||
/// <summary>
|
||||
/// The most significant 32 bits of the file's 64-bit binary creation date and time stamp.
|
||||
/// </summary>
|
||||
public uint FileDateMS;
|
||||
|
||||
/// <summary>
|
||||
/// The least significant 32 bits of the file's 64-bit binary creation date and time stamp.
|
||||
/// </summary>
|
||||
public uint FileDateLS;
|
||||
}
|
||||
}
|
||||
174
BurnOutSharp.Models/PortableExecutable/FontDirEntry.cs
Normal file
174
BurnOutSharp.Models/PortableExecutable/FontDirEntry.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains information about an individual font in a font resource group. The structure definition
|
||||
/// provided here is for explanation only; it is not present in any standard header file.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/fontdirentry"/>
|
||||
public class FontDirEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// A user-defined version number for the resource data that tools can use to read and write
|
||||
/// resource files.
|
||||
/// </summary>
|
||||
public ushort Version;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the file, in bytes.
|
||||
/// </summary>
|
||||
public uint Size;
|
||||
|
||||
/// <summary>
|
||||
/// The font supplier's copyright information.
|
||||
/// </summary>
|
||||
/// <remarks>60 characters</remarks>
|
||||
public byte[] Copyright;
|
||||
|
||||
/// <summary>
|
||||
/// The type of font file.
|
||||
/// </summary>
|
||||
public ushort Type;
|
||||
|
||||
/// <summary>
|
||||
/// The point size at which this character set looks best.
|
||||
/// </summary>
|
||||
public ushort Points;
|
||||
|
||||
/// <summary>
|
||||
/// The vertical resolution, in dots per inch, at which this character set was digitized.
|
||||
/// </summary>
|
||||
public ushort VertRes;
|
||||
|
||||
/// <summary>
|
||||
/// The horizontal resolution, in dots per inch, at which this character set was digitized.
|
||||
/// </summary>
|
||||
public ushort HorizRes;
|
||||
|
||||
/// <summary>
|
||||
/// The distance from the top of a character definition cell to the baseline of the typographical
|
||||
/// font.
|
||||
/// </summary>
|
||||
public ushort Ascent;
|
||||
|
||||
/// <summary>
|
||||
/// The amount of leading inside the bounds set by the PixHeight member. Accent marks and other
|
||||
/// diacritical characters can occur in this area.
|
||||
/// </summary>
|
||||
public ushort InternalLeading;
|
||||
|
||||
/// <summary>
|
||||
/// The amount of extra leading that the application adds between rows.
|
||||
/// </summary>
|
||||
public ushort ExternalLeading;
|
||||
|
||||
/// <summary>
|
||||
/// An italic font if not equal to zero.
|
||||
/// </summary>
|
||||
public byte Italic;
|
||||
|
||||
/// <summary>
|
||||
/// An underlined font if not equal to zero.
|
||||
/// </summary>
|
||||
public byte Underline;
|
||||
|
||||
/// <summary>
|
||||
/// A strikeout font if not equal to zero.
|
||||
/// </summary>
|
||||
public byte StrikeOut;
|
||||
|
||||
/// <summary>
|
||||
/// The weight of the font in the range 0 through 1000. For example, 400 is roman and 700 is bold.
|
||||
/// If this value is zero, a default weight is used. For additional defined values, see the
|
||||
/// description of the LOGFONT structure.
|
||||
/// </summary>
|
||||
public ushort Weight;
|
||||
|
||||
/// <summary>
|
||||
/// The character set of the font. For predefined values, see the description of the LOGFONT
|
||||
/// structure.
|
||||
/// </summary>
|
||||
public byte CharSet;
|
||||
|
||||
/// <summary>
|
||||
/// The width of the grid on which a vector font was digitized. For raster fonts, if the member
|
||||
/// is not equal to zero, it represents the width for all the characters in the bitmap. If the
|
||||
/// member is equal to zero, the font has variable-width characters.
|
||||
/// </summary>
|
||||
public ushort PixWidth;
|
||||
|
||||
/// <summary>
|
||||
/// The height of the character bitmap for raster fonts or the height of the grid on which a
|
||||
/// vector font was digitized.
|
||||
/// </summary>
|
||||
public ushort PixHeight;
|
||||
|
||||
/// <summary>
|
||||
/// The pitch and the family of the font. For additional information, see the description of
|
||||
/// the LOGFONT structure.
|
||||
/// </summary>
|
||||
public byte PitchAndFamily;
|
||||
|
||||
/// <summary>
|
||||
/// The average width of characters in the font (generally defined as the width of the letter x).
|
||||
/// This value does not include the overhang required for bold or italic characters.
|
||||
/// </summary>
|
||||
public ushort AvgWidth;
|
||||
|
||||
/// <summary>
|
||||
/// The width of the widest character in the font.
|
||||
/// </summary>
|
||||
public ushort MaxWidth;
|
||||
|
||||
/// <summary>
|
||||
/// The first character code defined in the font.
|
||||
/// </summary>
|
||||
public byte FirstChar;
|
||||
|
||||
/// <summary>
|
||||
/// The last character code defined in the font.
|
||||
/// </summary>
|
||||
public byte LastChar;
|
||||
|
||||
/// <summary>
|
||||
/// The character to substitute for characters not in the font.
|
||||
/// </summary>
|
||||
public byte DefaultChar;
|
||||
|
||||
/// <summary>
|
||||
/// The character that will be used to define word breaks for text justification.
|
||||
/// </summary>
|
||||
public byte BreakChar;
|
||||
|
||||
/// <summary>
|
||||
/// The number of bytes in each row of the bitmap. This value is always even so that the rows
|
||||
/// start on word boundaries. For vector fonts, this member has no meaning.
|
||||
/// </summary>
|
||||
public ushort WidthBytes;
|
||||
|
||||
/// <summary>
|
||||
/// The offset in the file to a null-terminated string that specifies a device name. For a
|
||||
/// generic font, this value is zero.
|
||||
/// </summary>
|
||||
public uint Device;
|
||||
|
||||
/// <summary>
|
||||
/// The offset in the file to a null-terminated string that names the typeface.
|
||||
/// </summary>
|
||||
public uint Face;
|
||||
|
||||
/// <summary>
|
||||
/// This member is reserved.
|
||||
/// </summary>
|
||||
public uint Reserved;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the device if this font file is designated for a specific device.
|
||||
/// </summary>
|
||||
public string DeviceName;
|
||||
|
||||
/// <summary>
|
||||
/// The typeface name of the font.
|
||||
/// </summary>
|
||||
public string FaceName;
|
||||
}
|
||||
}
|
||||
21
BurnOutSharp.Models/PortableExecutable/FontGroupHeader.cs
Normal file
21
BurnOutSharp.Models/PortableExecutable/FontGroupHeader.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the information necessary for an application to access a specific font. The structure
|
||||
/// definition provided here is for explanation only; it is not present in any standard header file.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/menurc/fontgrouphdr"/>
|
||||
public class FontGroupHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of individual fonts associated with this resource.
|
||||
/// </summary>
|
||||
public ushort NumberOfFonts;
|
||||
|
||||
/// <summary>
|
||||
/// A structure that contains a unique ordinal identifier for each font in the resource. The DE
|
||||
/// member is a placeholder for the variable-length array of DIRENTRY structures.
|
||||
/// </summary>
|
||||
public DirEntry[] DE;
|
||||
}
|
||||
}
|
||||
23
BurnOutSharp.Models/PortableExecutable/HintNameTableEntry.cs
Normal file
23
BurnOutSharp.Models/PortableExecutable/HintNameTableEntry.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// One hint/name table suffices for the entire import section.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
public class HintNameTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// An index into the export name pointer table. A match is attempted first
|
||||
/// with this value. If it fails, a binary search is performed on the DLL's
|
||||
/// export name pointer table.
|
||||
/// </summary>
|
||||
public ushort Hint;
|
||||
|
||||
/// <summary>
|
||||
/// An ASCII string that contains the name to import. This is the string that
|
||||
/// must be matched to the public name in the DLL. This string is case sensitive
|
||||
/// and terminated by a null byte.
|
||||
/// </summary>
|
||||
public string Name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The structure and content of the import address table are identical to those of
|
||||
/// the import lookup table, until the file is bound. During binding, the entries in
|
||||
/// the import address table are overwritten with the 32-bit (for PE32) or 64-bit
|
||||
/// (for PE32+) addresses of the symbols that are being imported. These addresses are
|
||||
/// the actual memory addresses of the symbols, although technically they are still
|
||||
/// called "virtual addresses." The loader typically processes the binding.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
public class ImportAddressTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// If this bit is set, import by ordinal. Otherwise, import by name. Bit is
|
||||
/// masked as 0x80000000 for PE32, 0x8000000000000000 for PE32+.
|
||||
/// </summary>
|
||||
/// <remarks>Bit 31/63</remarks>
|
||||
public bool OrdinalNameFlag;
|
||||
|
||||
/// <summary>
|
||||
/// A 16-bit ordinal number. This field is used only if the Ordinal/Name Flag
|
||||
/// bit field is 1 (import by ordinal). Bits 30-15 or 62-15 must be 0.
|
||||
/// </summary>
|
||||
/// <remarks>Bits 15-0</remarks>
|
||||
public ushort OrdinalNumber;
|
||||
|
||||
/// <summary>
|
||||
/// A 31-bit RVA of a hint/name table entry. This field is used only if the
|
||||
/// Ordinal/Name Flag bit field is 0 (import by name). For PE32+ bits 62-31
|
||||
/// must be zero.
|
||||
/// </summary>
|
||||
/// <remarks>Bits 30-0</remarks>
|
||||
public uint HintNameTableRVA;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The import information begins with the import directory table, which
|
||||
/// describes the remainder of the import information. The import directory
|
||||
/// table contains address information that is used to resolve fixup references
|
||||
/// to the entry points within a DLL image. The import directory table consists
|
||||
/// of an array of import directory entries, one entry for each DLL to which
|
||||
/// the image refers. The last directory entry is empty (filled with null values),
|
||||
/// which indicates the end of the directory table.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ImportDirectoryTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// The RVA of the import lookup table. This table contains a name or ordinal
|
||||
/// for each import. (The name "Characteristics" is used in Winnt.h, but no
|
||||
/// longer describes this field.)
|
||||
/// </summary>
|
||||
public uint ImportLookupTableRVA;
|
||||
|
||||
/// <summary>
|
||||
/// The stamp that is set to zero until the image is bound. After the image is
|
||||
/// bound, this field is set to the time/data stamp of the DLL.
|
||||
/// </summary>
|
||||
public uint TimeDateStamp;
|
||||
|
||||
/// <summary>
|
||||
/// The index of the first forwarder reference.
|
||||
/// </summary>
|
||||
public uint ForwarderChain;
|
||||
|
||||
/// <summary>
|
||||
/// The address of an ASCII string that contains the name of the DLL. This address
|
||||
/// is relative to the image base.
|
||||
/// </summary>
|
||||
public uint NameRVA;
|
||||
|
||||
/// <summary>
|
||||
/// ASCII string that contains the name of the DLL.
|
||||
/// </summary>
|
||||
public string Name;
|
||||
|
||||
/// <summary>
|
||||
/// The RVA of the import address table. The contents of this table are identical
|
||||
/// to the contents of the import lookup table until the image is bound.
|
||||
/// </summary>
|
||||
public uint ImportAddressTableRVA;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// An import lookup table is an array of 32-bit numbers for PE32 or an array of
|
||||
/// 64-bit numbers for PE32+. Each entry uses the bit-field format that is described
|
||||
/// in the following table. In this format, bit 31 is the most significant bit for
|
||||
/// PE32 and bit 63 is the most significant bit for PE32+. The collection of these
|
||||
/// entries describes all imports from a given DLL. The last entry is set to zero
|
||||
/// (NULL) to indicate the end of the table.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
public class ImportLookupTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// If this bit is set, import by ordinal. Otherwise, import by name. Bit is
|
||||
/// masked as 0x80000000 for PE32, 0x8000000000000000 for PE32+.
|
||||
/// </summary>
|
||||
/// <remarks>Bit 31/63</remarks>
|
||||
public bool OrdinalNameFlag;
|
||||
|
||||
/// <summary>
|
||||
/// A 16-bit ordinal number. This field is used only if the Ordinal/Name Flag
|
||||
/// bit field is 1 (import by ordinal). Bits 30-15 or 62-15 must be 0.
|
||||
/// </summary>
|
||||
/// <remarks>Bits 15-0</remarks>
|
||||
public ushort OrdinalNumber;
|
||||
|
||||
/// <summary>
|
||||
/// A 31-bit RVA of a hint/name table entry. This field is used only if the
|
||||
/// Ordinal/Name Flag bit field is 0 (import by name). For PE32+ bits 62-31
|
||||
/// must be zero.
|
||||
/// </summary>
|
||||
/// <remarks>Bits 30-0</remarks>
|
||||
public uint HintNameTableRVA;
|
||||
}
|
||||
}
|
||||
45
BurnOutSharp.Models/PortableExecutable/ImportTable.cs
Normal file
45
BurnOutSharp.Models/PortableExecutable/ImportTable.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// All image files that import symbols, including virtually all executable (EXE) files,
|
||||
/// have an .idata section. A typical file layout for the import information follows:
|
||||
///
|
||||
/// - Directory Table
|
||||
/// Null Directory Entry
|
||||
/// - DLL1 Import Lookup Table
|
||||
/// Null
|
||||
/// - DLL2 Import Lookup Table
|
||||
/// Null
|
||||
/// - DLL3 Import Lookup Table
|
||||
/// Null
|
||||
/// - Hint-Name Table
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
public class ImportTable
|
||||
{
|
||||
/// <summary>
|
||||
/// The import information begins with the import directory table, which describes the
|
||||
/// remainder of the import information.
|
||||
/// </summary>
|
||||
public ImportDirectoryTableEntry[] ImportDirectoryTable;
|
||||
|
||||
/// <summary>
|
||||
/// An import lookup table is an array of 32-bit numbers for PE32 or an array of 64-bit
|
||||
/// numbers for PE32+.
|
||||
/// </summary>
|
||||
public Dictionary<int, ImportLookupTableEntry[]> ImportLookupTables;
|
||||
|
||||
/// <summary>
|
||||
/// These addresses are the actual memory addresses of the symbols, although technically
|
||||
/// they are still called "virtual addresses".
|
||||
/// </summary>
|
||||
public Dictionary<int, ImportAddressTableEntry[]> ImportAddressTables;
|
||||
|
||||
/// <summary>
|
||||
/// One hint/name table suffices for the entire import section.
|
||||
/// </summary>
|
||||
public HintNameTableEntry[] HintNameTable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
namespace BurnOutSharp.Models.PortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// The data directory entry for a pre-reserved SEH load configuration
|
||||
/// structure must specify a particular size of the load configuration
|
||||
/// structure because the operating system loader always expects it to
|
||||
/// be a certain value. In that regard, the size is really only a
|
||||
/// version check. For compatibility with Windows XP and earlier versions
|
||||
/// of Windows, the size must be 64 for x86 images.
|
||||
/// </summary>
|
||||
/// <see href="https://learn.microsoft.com/en-us/windows/win32/debug/pe-format"/>
|
||||
public class LoadConfigurationDirectory
|
||||
{
|
||||
/// <summary>
|
||||
/// Flags that indicate attributes of the file, currently unused.
|
||||
/// </summary>
|
||||
public uint Characteristics;
|
||||
|
||||
/// <summary>
|
||||
/// Date and time stamp value. The value is represented in the number of
|
||||
/// seconds that have elapsed since midnight (00:00:00), January 1, 1970,
|
||||
/// Universal Coordinated Time, according to the system clock. The time
|
||||
/// stamp can be printed by using the C runtime (CRT) time function.
|
||||
/// </summary>
|
||||
public uint TimeDateStamp;
|
||||
|
||||
/// <summary>
|
||||
/// Major version number.
|
||||
/// </summary>
|
||||
public ushort MajorVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Minor version number.
|
||||
/// </summary>
|
||||
public ushort MinorVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The global loader flags to clear for this process as the loader starts
|
||||
/// the process.
|
||||
/// </summary>
|
||||
public uint GlobalFlagsClear;
|
||||
|
||||
/// <summary>
|
||||
/// The global loader flags to set for this process as the loader starts
|
||||
/// the process.
|
||||
/// </summary>
|
||||
public uint GlobalFlagsSet;
|
||||
|
||||
/// <summary>
|
||||
/// The default timeout value to use for this process's critical sections
|
||||
/// that are abandoned.
|
||||
/// </summary>
|
||||
public uint CriticalSectionDefaultTimeout;
|
||||
|
||||
#region DeCommitFreeBlockThreshold
|
||||
|
||||
/// <summary>
|
||||
/// Memory that must be freed before it is returned to the system, in bytes.
|
||||
/// </summary>
|
||||
public uint DeCommitFreeBlockThreshold_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// Memory that must be freed before it is returned to the system, in bytes.
|
||||
/// </summary>
|
||||
public ulong DeCommitFreeBlockThreshold_PE32Plus;
|
||||
|
||||
#endregion
|
||||
|
||||
#region DeCommitTotalFreeThreshold
|
||||
|
||||
/// <summary>
|
||||
/// Total amount of free memory, in bytes.
|
||||
/// </summary>
|
||||
public uint DeCommitTotalFreeThreshold_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// Total amount of free memory, in bytes.
|
||||
/// </summary>
|
||||
public ulong DeCommitTotalFreeThreshold_PE32Plus;
|
||||
|
||||
#endregion
|
||||
|
||||
#region LockPrefixTable
|
||||
|
||||
/// <summary>
|
||||
/// [x86 only] The VA of a list of addresses where the LOCK prefix is used so
|
||||
/// that they can be replaced with NOP on single processor machines.
|
||||
/// </summary>
|
||||
public uint LockPrefixTable_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// [x86 only] The VA of a list of addresses where the LOCK prefix is used so
|
||||
/// that they can be replaced with NOP on single processor machines.
|
||||
/// </summary>
|
||||
public ulong LockPrefixTable_PE32Plus;
|
||||
|
||||
#endregion
|
||||
|
||||
#region MaximumAllocationSize
|
||||
|
||||
/// <summary>
|
||||
/// Maximum allocation size, in bytes.
|
||||
/// </summary>
|
||||
public uint MaximumAllocationSize_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum allocation size, in bytes.
|
||||
/// </summary>
|
||||
public ulong MaximumAllocationSize_PE32Plus;
|
||||
|
||||
#endregion
|
||||
|
||||
#region VirtualMemoryThreshold
|
||||
|
||||
/// <summary>
|
||||
/// Maximum virtual memory size, in bytes.
|
||||
/// </summary>
|
||||
public uint VirtualMemoryThreshold_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum virtual memory size, in bytes.
|
||||
/// </summary>
|
||||
public ulong VirtualMemoryThreshold_PE32Plus;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ProcessAffinityMask
|
||||
|
||||
/// <summary>
|
||||
/// Setting this field to a non-zero value is equivalent to calling
|
||||
/// SetProcessAffinityMask with this value during process startup (.exe only)
|
||||
/// </summary>
|
||||
public uint ProcessAffinityMask_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// Setting this field to a non-zero value is equivalent to calling
|
||||
/// SetProcessAffinityMask with this value during process startup (.exe only)
|
||||
/// </summary>
|
||||
public ulong ProcessAffinityMask_PE32Plus;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Process heap flags that correspond to the first argument of the
|
||||
/// HeapCreate function. These flags apply to the process heap that
|
||||
/// is created during process startup.
|
||||
/// </summary>
|
||||
public uint ProcessHeapFlags;
|
||||
|
||||
/// <summary>
|
||||
/// The service pack version identifier.
|
||||
/// </summary>
|
||||
public ushort CSDVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Must be zero.
|
||||
/// </summary>
|
||||
public ushort Reserved;
|
||||
|
||||
#region EditList
|
||||
|
||||
/// <summary>
|
||||
/// Reserved for use by the system.
|
||||
/// </summary>
|
||||
public uint EditList_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved for use by the system.
|
||||
/// </summary>
|
||||
public ulong EditList_PE32Plus;
|
||||
|
||||
#endregion
|
||||
|
||||
#region SecurityCookie
|
||||
|
||||
/// <summary>
|
||||
/// A pointer to a cookie that is used by Visual C++ or GS implementation.
|
||||
/// </summary>
|
||||
public uint SecurityCookie_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// A pointer to a cookie that is used by Visual C++ or GS implementation.
|
||||
/// </summary>
|
||||
public ulong SecurityCookie_PE32Plus;
|
||||
|
||||
#endregion
|
||||
|
||||
#region SEHandlerTable
|
||||
|
||||
/// <summary>
|
||||
/// [x86 only] The VA of the sorted table of RVAs of each valid, unique
|
||||
/// SE handler in the image.
|
||||
/// </summary>
|
||||
public uint SEHandlerTable_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// [x86 only] The VA of the sorted table of RVAs of each valid, unique
|
||||
/// SE handler in the image.
|
||||
/// </summary>
|
||||
public ulong SEHandlerTable_PE32Plus;
|
||||
|
||||
#endregion
|
||||
|
||||
#region SEHandlerCount
|
||||
|
||||
/// <summary>
|
||||
/// [x86 only] The count of unique handlers in the table.
|
||||
/// </summary>
|
||||
public uint SEHandlerCount_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// [x86 only] The count of unique handlers in the table.
|
||||
/// </summary>
|
||||
public ulong SEHandlerCount_PE32Plus;
|
||||
|
||||
#endregion
|
||||
|
||||
#region GuardCFCheckFunctionPointer
|
||||
|
||||
/// <summary>
|
||||
/// The VA where Control Flow Guard check-function pointer is stored.
|
||||
/// </summary>
|
||||
public uint GuardCFCheckFunctionPointer_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// The VA where Control Flow Guard check-function pointer is stored.
|
||||
/// </summary>
|
||||
public ulong GuardCFCheckFunctionPointer_PE32Plus;
|
||||
|
||||
#endregion
|
||||
|
||||
#region GuardCFDispatchFunctionPointer
|
||||
|
||||
/// <summary>
|
||||
/// The VA where Control Flow Guard dispatch-function pointer is stored.
|
||||
/// </summary>
|
||||
public uint GuardCFDispatchFunctionPointer_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// The VA where Control Flow Guard dispatch-function pointer is stored.
|
||||
/// </summary>
|
||||
public ulong GuardCFDispatchFunctionPointer_PE32Plus;
|
||||
|
||||
#endregion
|
||||
|
||||
#region GuardCFFunctionTable
|
||||
|
||||
/// <summary>
|
||||
/// The VA of the sorted table of RVAs of each Control Flow Guard
|
||||
/// function in the image.
|
||||
/// </summary>
|
||||
public uint GuardCFFunctionTable_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// The VA of the sorted table of RVAs of each Control Flow Guard
|
||||
/// function in the image.
|
||||
/// </summary>
|
||||
public ulong GuardCFFunctionTable_PE32Plus;
|
||||
|
||||
#endregion
|
||||
|
||||
#region GuardCFFunctionCount
|
||||
|
||||
/// <summary>
|
||||
/// The count of unique RVAs in the above table.
|
||||
/// </summary>
|
||||
public uint GuardCFFunctionCount_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// The count of unique RVAs in the above table.
|
||||
/// </summary>
|
||||
public ulong GuardCFFunctionCount_PE32Plus;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Control Flow Guard related flags.
|
||||
/// </summary>
|
||||
public GuardFlags GuardFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Code integrity information.
|
||||
/// </summary>
|
||||
/// <remarks>12 bytes</remarks>
|
||||
public byte[] CodeIntegrity;
|
||||
|
||||
#region GuardAddressTakenIatEntryTable
|
||||
|
||||
/// <summary>
|
||||
/// The VA where Control Flow Guard address taken IAT table is stored.
|
||||
/// </summary>
|
||||
public uint GuardAddressTakenIatEntryTable_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// The VA where Control Flow Guard address taken IAT table is stored.
|
||||
/// </summary>
|
||||
public ulong GuardAddressTakenIatEntryTable_PE32Plus;
|
||||
|
||||
#endregion
|
||||
|
||||
#region GuardAddressTakenIatEntryCount
|
||||
|
||||
/// <summary>
|
||||
/// The count of unique RVAs in the above table.
|
||||
/// </summary>
|
||||
public uint GuardAddressTakenIatEntryCount_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// The count of unique RVAs in the above table.
|
||||
/// </summary>
|
||||
public ulong GuardAddressTakenIatEntryCount_PE32Plus;
|
||||
|
||||
#endregion
|
||||
|
||||
#region GuardLongJumpTargetTable
|
||||
|
||||
/// <summary>
|
||||
/// The VA where Control Flow Guard long jump target table is stored.
|
||||
/// </summary>
|
||||
public uint GuardLongJumpTargetTable_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// The VA where Control Flow Guard long jump target table is stored.
|
||||
/// </summary>
|
||||
public ulong GuardLongJumpTargetTable_PE32Plus;
|
||||
|
||||
#endregion
|
||||
|
||||
#region GuardLongJumpTargetCount
|
||||
|
||||
/// <summary>
|
||||
/// The count of unique RVAs in the above table.
|
||||
/// </summary>
|
||||
public uint GuardLongJumpTargetCount_PE32;
|
||||
|
||||
/// <summary>
|
||||
/// The count of unique RVAs in the above table.
|
||||
/// </summary>
|
||||
public ulong GuardLongJumpTargetCount_PE32Plus;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user