mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-02-04 13:45:28 +00:00
Compare commits
537 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b0fcdcf32 | ||
|
|
9fa1ef1d2e | ||
|
|
e2492c9e5b | ||
|
|
297514ef17 | ||
|
|
2acb0a037c | ||
|
|
c38eb0cc71 | ||
|
|
258369bb9e | ||
|
|
8cba9529d7 | ||
|
|
10296f40b4 | ||
|
|
73d085deac | ||
|
|
c7261c342a | ||
|
|
14d905fba3 | ||
|
|
1f66edc201 | ||
|
|
ade95c3210 | ||
|
|
8a419f50db | ||
|
|
52efca767e | ||
|
|
421dfa2591 | ||
|
|
76183c529c | ||
|
|
463506d1e8 | ||
|
|
1f2a187f55 | ||
|
|
40de5c4d0a | ||
|
|
5e72acb44c | ||
|
|
fab3c935f8 | ||
|
|
a498513662 | ||
|
|
3eaebffff1 | ||
|
|
280ae5babe | ||
|
|
5bf64d46bd | ||
|
|
6fb510c852 | ||
|
|
20223eea87 | ||
|
|
3f796e4e0e | ||
|
|
74732a1b50 | ||
|
|
f252681364 | ||
|
|
82cb0f934d | ||
|
|
7dc5644d21 | ||
|
|
313cc2bfb8 | ||
|
|
f24a8763fd | ||
|
|
47845a2409 | ||
|
|
42da9f4a82 | ||
|
|
e9fa86343a | ||
|
|
8ccf2272d6 | ||
|
|
8fb42bc12d | ||
|
|
6202ee5d5c | ||
|
|
655a8adb1c | ||
|
|
d7fcc99fc2 | ||
|
|
8601f373bd | ||
|
|
3c783fdc68 | ||
|
|
a75388cf17 | ||
|
|
7968a79fe6 | ||
|
|
8502924083 | ||
|
|
af95ca08c3 | ||
|
|
06995b75d6 | ||
|
|
1a2be26c72 | ||
|
|
a2a583e317 | ||
|
|
289a55ca21 | ||
|
|
598f625ed1 | ||
|
|
d604a6d784 | ||
|
|
cf34a0adee | ||
|
|
083ded8a7e | ||
|
|
1517a66724 | ||
|
|
5385de0f0a | ||
|
|
43729b53f0 | ||
|
|
e4aa618f0b | ||
|
|
4953673caf | ||
|
|
35c6d4f36c | ||
|
|
9108fa5a11 | ||
|
|
dc97feae39 | ||
|
|
beac29c650 | ||
|
|
21a041dad6 | ||
|
|
26eee23511 | ||
|
|
0915c7eccd | ||
|
|
e2e65bfbdf | ||
|
|
033f2e0a4e | ||
|
|
71ee0863eb | ||
|
|
3203c3ac83 | ||
|
|
1733f60a0f | ||
|
|
b01abdcce3 | ||
|
|
53c90533e3 | ||
|
|
03bd7bd1f5 | ||
|
|
637579b0fc | ||
|
|
bd40ca6d9d | ||
|
|
3c1623cb22 | ||
|
|
66da32b5c1 | ||
|
|
c21b64b5bd | ||
|
|
e968eeea96 | ||
|
|
c14005dcc4 | ||
|
|
84c6c257df | ||
|
|
e28b930f85 | ||
|
|
9dac2eb91b | ||
|
|
2209f362fa | ||
|
|
614413ab76 | ||
|
|
35c15d0ff8 | ||
|
|
b521df2ad4 | ||
|
|
778fe106f9 | ||
|
|
9171014dcd | ||
|
|
7ee74d9b81 | ||
|
|
826011f532 | ||
|
|
adb349932f | ||
|
|
f4f13c03fe | ||
|
|
e29e87444e | ||
|
|
b233b3c17b | ||
|
|
a8fca77331 | ||
|
|
5e4ee07646 | ||
|
|
52b2a9bef8 | ||
|
|
dc7f8da52f | ||
|
|
d46b0768a0 | ||
|
|
f136af3457 | ||
|
|
2e2b6068c5 | ||
|
|
7a29d8a8f9 | ||
|
|
ae0c47066e | ||
|
|
11188c9488 | ||
|
|
4d5d2d8690 | ||
|
|
1860a863b8 | ||
|
|
8dbf6d9362 | ||
|
|
e3e8a1170f | ||
|
|
b22641b7ab | ||
|
|
d3d75b9e58 | ||
|
|
6083c64b87 | ||
|
|
4185367a49 | ||
|
|
c027b1798a | ||
|
|
76e52292a8 | ||
|
|
dd5f7c4e0b | ||
|
|
6e70991e86 | ||
|
|
f1803b9f3a | ||
|
|
9e0abe7c5d | ||
|
|
1a01102252 | ||
|
|
ce849d312f | ||
|
|
71da8a53c0 | ||
|
|
b8f7d00dc9 | ||
|
|
7e69a56892 | ||
|
|
8cedd3e469 | ||
|
|
d5e60439fb | ||
|
|
1a0e16a05b | ||
|
|
bee6d2b885 | ||
|
|
5d515c7ddd | ||
|
|
013301fa99 | ||
|
|
152ae8bf6c | ||
|
|
439f71ef5c | ||
|
|
66c7afe20b | ||
|
|
6a609ea3f5 | ||
|
|
6752d0cfa3 | ||
|
|
1d26b06592 | ||
|
|
9ca24a3053 | ||
|
|
76ca87f7a9 | ||
|
|
c913b10286 | ||
|
|
768c77a6bc | ||
|
|
20d90d6a60 | ||
|
|
54a48e0729 | ||
|
|
15c05c65e7 | ||
|
|
4dbaa415c5 | ||
|
|
1a0b83a9f1 | ||
|
|
4316427980 | ||
|
|
21ecaca761 | ||
|
|
7022a957d6 | ||
|
|
32cfcbff0a | ||
|
|
283fa425d4 | ||
|
|
d37eac02d5 | ||
|
|
c3e0b99002 | ||
|
|
9e49703bc5 | ||
|
|
98a7149cc9 | ||
|
|
394b4e70fb | ||
|
|
b29198b3d4 | ||
|
|
044c398fa7 | ||
|
|
ae7087e8d0 | ||
|
|
90bc78982c | ||
|
|
2ce8bda394 | ||
|
|
ac0ed050dc | ||
|
|
e4aadb3794 | ||
|
|
80626f3b9e | ||
|
|
93263dfeb9 | ||
|
|
51e5f82cc2 | ||
|
|
b69c5cf928 | ||
|
|
e45b593c7b | ||
|
|
c245ebb80a | ||
|
|
cd38407e4e | ||
|
|
f34b1ba5cf | ||
|
|
08c97d291e | ||
|
|
3ea294f4d9 | ||
|
|
ddb2be278a | ||
|
|
b6b5dc4efa | ||
|
|
218fecb273 | ||
|
|
b23a504c7b | ||
|
|
c54181e9ac | ||
|
|
7e100a261c | ||
|
|
38e1154bad | ||
|
|
901804e9e4 | ||
|
|
dfee4a8d76 | ||
|
|
295b86fbd0 | ||
|
|
177543a51c | ||
|
|
dfff702e5d | ||
|
|
c0ad427b5e | ||
|
|
2f68f95d80 | ||
|
|
a8ba104d0f | ||
|
|
6f9e92d222 | ||
|
|
1e20c1b147 | ||
|
|
c16946ace7 | ||
|
|
9d7cc4012c | ||
|
|
a44bdf9013 | ||
|
|
f9f2e0d932 | ||
|
|
2dd3e21ea6 | ||
|
|
81bb47b634 | ||
|
|
c8efc1430a | ||
|
|
7883638f0a | ||
|
|
e930be12c8 | ||
|
|
c45ae4b693 | ||
|
|
478f28b513 | ||
|
|
aac3c391db | ||
|
|
802734b515 | ||
|
|
ef212fc8d9 | ||
|
|
ee85f2f6f0 | ||
|
|
9a160b3127 | ||
|
|
4486c5ed62 | ||
|
|
d6feab3958 | ||
|
|
2d2207a1ee | ||
|
|
89b86630d8 | ||
|
|
bcb1571a23 | ||
|
|
5d658ebe4a | ||
|
|
7d2de80e77 | ||
|
|
b933249ff7 | ||
|
|
61c09e3c97 | ||
|
|
32695ee6dd | ||
|
|
4b66cd8cd2 | ||
|
|
edc4cc1706 | ||
|
|
35acb77bf7 | ||
|
|
e970a7b4d9 | ||
|
|
f155291139 | ||
|
|
b0293419e1 | ||
|
|
09db225929 | ||
|
|
0c52b4e236 | ||
|
|
5dc30942ff | ||
|
|
cab200e893 | ||
|
|
c349f3a3c4 | ||
|
|
0acb29f2e9 | ||
|
|
b66e01f7b4 | ||
|
|
8d6d215e57 | ||
|
|
d54a90a034 | ||
|
|
e1e7172561 | ||
|
|
6606b388f6 | ||
|
|
b6c6c01358 | ||
|
|
6886c5a4a2 | ||
|
|
87546a3dc8 | ||
|
|
6e3028639a | ||
|
|
386da02e27 | ||
|
|
ec8c395ffa | ||
|
|
9b98215fc9 | ||
|
|
40e037fb2a | ||
|
|
17f8569a7e | ||
|
|
1105f36cee | ||
|
|
f9fcd8749b | ||
|
|
eef76d362a | ||
|
|
3b0e3693eb | ||
|
|
ba4c56997a | ||
|
|
ca4d08567d | ||
|
|
3211149996 | ||
|
|
5a7e60cabb | ||
|
|
46ff4b6ef9 | ||
|
|
dc252e8d86 | ||
|
|
133e29dc2e | ||
|
|
368cec4fc6 | ||
|
|
65eea4301d | ||
|
|
ceae505f4d | ||
|
|
a7e9164f4f | ||
|
|
3820546c07 | ||
|
|
0fa6673d21 | ||
|
|
0a486c2195 | ||
|
|
a723fbefc3 | ||
|
|
70e64e57dd | ||
|
|
edfc3c6c5d | ||
|
|
c4447fc505 | ||
|
|
a1d2292381 | ||
|
|
033fb0c1ac | ||
|
|
e80034abf1 | ||
|
|
27e4a6c452 | ||
|
|
914497b76f | ||
|
|
513e799aa3 | ||
|
|
fcbf006e4e | ||
|
|
bef26e0fd7 | ||
|
|
3dde84f683 | ||
|
|
74c6aa06e0 | ||
|
|
ffb529edb3 | ||
|
|
d1279a471c | ||
|
|
a7f406537e | ||
|
|
df7d5150c1 | ||
|
|
73e4569b3b | ||
|
|
30c249ce74 | ||
|
|
ec83669d7d | ||
|
|
e765fb6c0b | ||
|
|
76465d30ec | ||
|
|
71d3771c1d | ||
|
|
bfd9c12163 | ||
|
|
eb57065562 | ||
|
|
3875f3b8fb | ||
|
|
8c2bedd21e | ||
|
|
b199a6aa54 | ||
|
|
1b1f64c2de | ||
|
|
7b73cc9d9b | ||
|
|
d9d84a01e5 | ||
|
|
56f009ac56 | ||
|
|
96daf90ae8 | ||
|
|
b581cb3124 | ||
|
|
4b0e39b950 | ||
|
|
3a1c476edc | ||
|
|
0d62d5336c | ||
|
|
cf87279dfc | ||
|
|
0006f7932a | ||
|
|
841a39c6c7 | ||
|
|
60b12f25a6 | ||
|
|
f2b96b6c50 | ||
|
|
d2fad1ab29 | ||
|
|
6f6755b218 | ||
|
|
9a2f2e6f17 | ||
|
|
d9ca550e3b | ||
|
|
ec66e87ee6 | ||
|
|
53ce3aee74 | ||
|
|
1ecb06f020 | ||
|
|
3ce4ac785e | ||
|
|
1df157434d | ||
|
|
594f001dda | ||
|
|
c2c6bc268e | ||
|
|
7aa2207edd | ||
|
|
22aa1642a6 | ||
|
|
844a9686af | ||
|
|
8f929366b3 | ||
|
|
dfa0fab979 | ||
|
|
415d6c587f | ||
|
|
b1034b964e | ||
|
|
85d2382680 | ||
|
|
a6e694fe5d | ||
|
|
a579bfea1f | ||
|
|
ba97abed44 | ||
|
|
9fe6b101bd | ||
|
|
1345182eea | ||
|
|
a84ac8d3cc | ||
|
|
1eb07c52e5 | ||
|
|
0d75ee135c | ||
|
|
c915f29c05 | ||
|
|
38d35d1991 | ||
|
|
dbc841cb7f | ||
|
|
46f53221c9 | ||
|
|
708fd01d1e | ||
|
|
4aa3ba0545 | ||
|
|
57499002d2 | ||
|
|
630f628598 | ||
|
|
d66c890b71 | ||
|
|
2b5649588a | ||
|
|
5425578f78 | ||
|
|
8c39adcc04 | ||
|
|
7773b32847 | ||
|
|
143b261a67 | ||
|
|
25fc2b9b04 | ||
|
|
d6fd0c4d2c | ||
|
|
44c44be412 | ||
|
|
7b71d7b4bf | ||
|
|
2c2aee6797 | ||
|
|
afdd032f73 | ||
|
|
9d52ca4b4c | ||
|
|
1bc8fe7ff6 | ||
|
|
6ab7a06dd5 | ||
|
|
7195ed3587 | ||
|
|
214e8d41c7 | ||
|
|
bd9f583659 | ||
|
|
abbf0b7ff5 | ||
|
|
f2b9e3a31b | ||
|
|
73dd669c20 | ||
|
|
32390149f3 | ||
|
|
9e73d8762e | ||
|
|
09854b469e | ||
|
|
e817063e53 | ||
|
|
7cdf6a8c79 | ||
|
|
d87087dcfb | ||
|
|
7c27fcd8a4 | ||
|
|
56408ed9f4 | ||
|
|
bf385f0bbf | ||
|
|
2a6a2930c1 | ||
|
|
9f676732a4 | ||
|
|
44fac8cc92 | ||
|
|
e510915098 | ||
|
|
b779f2f546 | ||
|
|
5344de96b2 | ||
|
|
1e70d960ba | ||
|
|
e03808fbc5 | ||
|
|
373268a6a8 | ||
|
|
905d440367 | ||
|
|
5628cf8d73 | ||
|
|
4aaea417f0 | ||
|
|
892886b730 | ||
|
|
1028050464 | ||
|
|
af79b00bd6 | ||
|
|
dc9a581e1c | ||
|
|
4d800fd644 | ||
|
|
126e8827de | ||
|
|
23c79d4452 | ||
|
|
173fc69a08 | ||
|
|
0411278f1d | ||
|
|
bb1f9bdcdc | ||
|
|
9d5ab935de | ||
|
|
1df9d145e4 | ||
|
|
fba30949bd | ||
|
|
198c320ad8 | ||
|
|
e798ba1104 | ||
|
|
f8f02a54f6 | ||
|
|
da01668cbe | ||
|
|
95770c63af | ||
|
|
af6e5d7441 | ||
|
|
ae5bdcc97a | ||
|
|
0fc415fb34 | ||
|
|
0fe30392d8 | ||
|
|
77fc11289c | ||
|
|
9d3969d4ce | ||
|
|
2ba2756a8f | ||
|
|
53088b4e60 | ||
|
|
0dc83739e7 | ||
|
|
e8a205b221 | ||
|
|
02c3d3fb4a | ||
|
|
2d3d66f077 | ||
|
|
a5f21adeee | ||
|
|
cbb4cdddfa | ||
|
|
e6b898882d | ||
|
|
3bd7f5c890 | ||
|
|
39c20fd0cd | ||
|
|
21117e81a3 | ||
|
|
df172b49db | ||
|
|
1ae0f694de | ||
|
|
040aa8daf6 | ||
|
|
3b9aa2d45c | ||
|
|
8705cac648 | ||
|
|
5a4e3caea8 | ||
|
|
593d4a35b7 | ||
|
|
801eef5f37 | ||
|
|
a0ac0ea189 | ||
|
|
f249455b00 | ||
|
|
8dbb8d9fe1 | ||
|
|
ed698e05d8 | ||
|
|
47b189bf87 | ||
|
|
460eb78ecd | ||
|
|
ffcaf4d16b | ||
|
|
64de357257 | ||
|
|
cc3f6622b4 | ||
|
|
f0b66d4bfb | ||
|
|
9c32f663b0 | ||
|
|
e0e22d91e1 | ||
|
|
dbc72cb4c2 | ||
|
|
17d6c6aa6b | ||
|
|
7be5916041 | ||
|
|
2d8a25178e | ||
|
|
5195025849 | ||
|
|
c3c2fc6171 | ||
|
|
6fa5e9a67f | ||
|
|
834018b325 | ||
|
|
027388f587 | ||
|
|
6452d39de1 | ||
|
|
6d78e2fff7 | ||
|
|
56ae245305 | ||
|
|
76b16ca6d4 | ||
|
|
d0a174d71c | ||
|
|
8e62f12f61 | ||
|
|
621bcdf380 | ||
|
|
1b54dd92ab | ||
|
|
2b0a43ca3e | ||
|
|
81ce49c219 | ||
|
|
b287c7236b | ||
|
|
b63d4a3da0 | ||
|
|
e652e43cba | ||
|
|
e6b2be1738 | ||
|
|
d2606e21fe | ||
|
|
22235cbe84 | ||
|
|
6bd5fae1cd | ||
|
|
ebb20bbe5e | ||
|
|
82d7395b79 | ||
|
|
451cb04714 | ||
|
|
15e5feafef | ||
|
|
4d19bd27f0 | ||
|
|
2400f2d0ad | ||
|
|
ee0193eb71 | ||
|
|
eb76acb767 | ||
|
|
6c77cccf53 | ||
|
|
b4ab969f88 | ||
|
|
2de4f3f808 | ||
|
|
4b5d0980f7 | ||
|
|
2bdbad1ba6 | ||
|
|
3b634877d0 | ||
|
|
2996bbb18f | ||
|
|
c4ca27608b | ||
|
|
5a85ff2ad3 | ||
|
|
a27b3cc43f | ||
|
|
ea8f557097 | ||
|
|
7bbed5985b | ||
|
|
0ec6dfb287 | ||
|
|
3b753c137b | ||
|
|
6cde7b8bef | ||
|
|
d26a89b8ab | ||
|
|
3ab0bcc0ae | ||
|
|
7548646ba2 | ||
|
|
0b75c6f046 | ||
|
|
958d306f42 | ||
|
|
742b25e4dd | ||
|
|
43845cf722 | ||
|
|
a2a0e5c2ee | ||
|
|
93e8322ba5 | ||
|
|
8a07c9cf4e | ||
|
|
6049eda580 | ||
|
|
177641894e | ||
|
|
dc49335ace | ||
|
|
3dcce8a8ac | ||
|
|
04651d46d8 | ||
|
|
56aeded8eb | ||
|
|
97c9c7e5ed | ||
|
|
a891391879 | ||
|
|
5aae9b01d4 | ||
|
|
b74a370b11 | ||
|
|
5e560661d4 | ||
|
|
93e450c2bf | ||
|
|
cc762754c5 | ||
|
|
7065436033 | ||
|
|
debe091502 | ||
|
|
80905b56cd | ||
|
|
0a7cd8a69e | ||
|
|
c3957977a2 | ||
|
|
ff602c77ed | ||
|
|
3667a5b57a | ||
|
|
3ac57b1c0c | ||
|
|
957d82b2f7 | ||
|
|
6d0817ad15 | ||
|
|
5b10e6d614 | ||
|
|
2d39b8c532 | ||
|
|
2ae860e8ca | ||
|
|
9e21c28e52 | ||
|
|
2f5053b49f | ||
|
|
7024136919 | ||
|
|
c74b5b3d29 | ||
|
|
9c3201aa4b | ||
|
|
dfd1141635 | ||
|
|
1188cad5e6 | ||
|
|
65fa2f8481 | ||
|
|
475e0b9d91 | ||
|
|
b76d09aa20 | ||
|
|
9a931eae67 | ||
|
|
47caa714c4 |
19
.gitmodules
vendored
19
.gitmodules
vendored
@@ -1,15 +1,12 @@
|
||||
[submodule "BurnOutSharp/External/LessIO"]
|
||||
path = BurnOutSharp/External/LessIO
|
||||
url = https://github.com/activescott/LessIO.git
|
||||
[submodule "BurnOutSharp/External/libmspack4n"]
|
||||
path = BurnOutSharp/External/libmspack4n
|
||||
url = https://github.com/activescott/libmspack4n.git
|
||||
[submodule "BurnOutSharp/External/hllib"]
|
||||
path = BurnOutSharp/External/hllib
|
||||
url = https://github.com/RavuAlHemio/hllib.git
|
||||
[submodule "BurnOutSharp/External/stormlibsharp"]
|
||||
path = BurnOutSharp/External/stormlibsharp
|
||||
url = https://github.com/robpaveza/stormlibsharp.git
|
||||
[submodule "BurnOutSharp/External/WixToolset"]
|
||||
path = BurnOutSharp/External/WixToolset
|
||||
[submodule "HLLibSharp"]
|
||||
path = HLLibSharp
|
||||
url = https://github.com/mnadareski/HLLibSharp
|
||||
[submodule "LibMSPackSharp"]
|
||||
path = LibMSPackSharp
|
||||
url = https://github.com/mnadareski/LibMSPackSharp.git
|
||||
[submodule "Dtf"]
|
||||
path = Dtf
|
||||
url = https://github.com/wixtoolset/Dtf.git
|
||||
|
||||
@@ -1,18 +1,27 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29306.81
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.1.32407.343
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BurnOutSharp", "BurnOutSharp\BurnOutSharp.csproj", "{1DA4212E-6071-4951-B45D-BB74A7838246}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{88735BA2-778D-4192-8EB2-FFF6843719E2}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{88735BA2-778D-4192-8EB2-FFF6843719E2}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{68D10531-99CB-40B1-8912-73FA286C9433}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
appveyor.yml = appveyor.yml
|
||||
LICENSE = LICENSE
|
||||
README.md = README.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HLLibSharp", "HLLibSharp\HLLibSharp\HLLibSharp.csproj", "{14E9764A-A8BF-44C0-A1A8-2C95EA307040}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibMSPackSharp", "LibMSPackSharp\LibMSPackSharp\LibMSPackSharp.csproj", "{BD8144B8-4857-47E6-9717-E9F2DB374A89}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Dtf.Compression.Cab", "Dtf\src\WixToolset.Dtf.Compression.Cab\WixToolset.Dtf.Compression.Cab.csproj", "{55B1D2D8-7470-4332-96EE-E18079C8A306}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Dtf.Compression", "Dtf\src\WixToolset.Dtf.Compression\WixToolset.Dtf.Compression.csproj", "{3065BE52-CB56-4557-80CD-E3AC57C242F2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -27,6 +36,22 @@ Global
|
||||
{88735BA2-778D-4192-8EB2-FFF6843719E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{88735BA2-778D-4192-8EB2-FFF6843719E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{88735BA2-778D-4192-8EB2-FFF6843719E2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{14E9764A-A8BF-44C0-A1A8-2C95EA307040}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{14E9764A-A8BF-44C0-A1A8-2C95EA307040}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{14E9764A-A8BF-44C0-A1A8-2C95EA307040}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{14E9764A-A8BF-44C0-A1A8-2C95EA307040}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BD8144B8-4857-47E6-9717-E9F2DB374A89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BD8144B8-4857-47E6-9717-E9F2DB374A89}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BD8144B8-4857-47E6-9717-E9F2DB374A89}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BD8144B8-4857-47E6-9717-E9F2DB374A89}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{55B1D2D8-7470-4332-96EE-E18079C8A306}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{55B1D2D8-7470-4332-96EE-E18079C8A306}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{55B1D2D8-7470-4332-96EE-E18079C8A306}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{55B1D2D8-7470-4332-96EE-E18079C8A306}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3065BE52-CB56-4557-80CD-E3AC57C242F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3065BE52-CB56-4557-80CD-E3AC57C242F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3065BE52-CB56-4557-80CD-E3AC57C242F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3065BE52-CB56-4557-80CD-E3AC57C242F2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net48;netcoreapp3.1;net5.0</TargetFrameworks>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<TargetFrameworks>netstandard2.0</TargetFrameworks>
|
||||
<Title>BurnOutSharp</Title>
|
||||
<AssemblyName>BurnOutSharp</AssemblyName>
|
||||
<Description>Port of BurnOut to C#, with additions</Description>
|
||||
<Authors>Matt Nadareski;Gernot Knippen</Authors>
|
||||
<Product>BurnOutSharp</Product>
|
||||
<Copyright>Copyright (c)2005-2010 Gernot Knippen, Copyright (c)2018-2021 Matt Nadareski</Copyright>
|
||||
<Copyright>Copyright (c)2005-2010 Gernot Knippen, Copyright (c)2018-2022 Matt Nadareski</Copyright>
|
||||
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
|
||||
<RepositoryUrl>https://github.com/mnadareski/BurnOutSharp</RepositoryUrl>
|
||||
<Version>1.6.0</Version>
|
||||
<AssemblyVersion>1.6.0</AssemblyVersion>
|
||||
<FileVersion>1.6.0</FileVersion>
|
||||
<Version>2.3.0</Version>
|
||||
<AssemblyVersion>2.3.0</AssemblyVersion>
|
||||
<FileVersion>2.3.0</FileVersion>
|
||||
<IncludeSource>true</IncludeSource>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
</PropertyGroup>
|
||||
@@ -23,9 +22,16 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SharpCompress" Version="0.28.1" />
|
||||
<PackageReference Include="UnshieldSharp" Version="1.5.0" />
|
||||
<PackageReference Include="WiseUnpacker" Version="1.0.2" />
|
||||
<PackageReference Include="OpenMcdf" Version="2.2.1.9" />
|
||||
<PackageReference Include="SharpCompress" Version="0.32.1" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
|
||||
<PackageReference Include="Teronis.MSBuild.Packaging.ProjectBuildInPackage" Version="1.0.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="UnshieldSharp" Version="1.6.8" />
|
||||
<PackageReference Include="WiseUnpacker" Version="1.0.3" />
|
||||
<PackageReference Include="zlib.net-mutliplatform" Version="1.0.6" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- These are needed for dealing with submodules -->
|
||||
@@ -33,19 +39,8 @@
|
||||
<DefaultItemExcludes>
|
||||
$(DefaultItemExcludes);
|
||||
**\AssemblyInfo.cs;
|
||||
External\hllib\HLExtract\**\*;
|
||||
External\hllib\HLExtract.Net\Program.cs;
|
||||
External\hllib\HLLib\**\*;
|
||||
External\LessIO\src\LessIO.Tests\**\*;
|
||||
External\libmspack4n\lib\**\*;
|
||||
External\libmspack4n\libmspack4ntest\**\*;
|
||||
External\stormlibsharp\lib\**;
|
||||
External\stormlibsharp\TestConsole\**;
|
||||
External\WixToolset\src\Samples\**;
|
||||
External\WixToolset\src\Tools\**;
|
||||
External\WixToolset\src\WixToolset.Dtf.MSBuild\**;
|
||||
External\WixToolset\src\WixToolset.Dtf.Resources\**;
|
||||
External\WixToolset\src\WixToolsetTests.*\**
|
||||
External\stormlibsharp\TestConsole\**
|
||||
</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -61,4 +56,10 @@
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Dtf\src\WixToolset.Dtf.Compression.Cab\WixToolset.Dtf.Compression.Cab.csproj" />
|
||||
<ProjectReference Include="..\HLLibSharp\HLLibSharp\HLLibSharp.csproj" />
|
||||
<ProjectReference Include="..\LibMSPackSharp\LibMSPackSharp\LibMSPackSharp.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,245 +0,0 @@
|
||||
//this file is part of BurnOut
|
||||
//Copyright (C)2005-2010 Gernot Knippen
|
||||
//Ported code with augments Copyright (C)2018 Matt Nadareski
|
||||
//
|
||||
//This program is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU General Public License
|
||||
//as published by the Free Software Foundation; either
|
||||
//version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This program is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
//GNU General Public License for more details.
|
||||
//
|
||||
//You can get a copy of the GNU General Public License
|
||||
//by writing to the Free Software
|
||||
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using BurnOutSharp.ExecutableType.Microsoft;
|
||||
|
||||
namespace BurnOutSharp
|
||||
{
|
||||
internal static class EVORE
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if the file contents that represent a PE is a DLL or an EXE
|
||||
/// </summary>
|
||||
/// <param name="fileContent">File contents to check</param>
|
||||
/// <returns>True if the file is an EXE, false if it's a DLL</returns>
|
||||
internal static bool IsEXE(byte[] fileContent)
|
||||
{
|
||||
int PEHeaderOffset = BitConverter.ToInt32(fileContent, 60);
|
||||
short Characteristics = BitConverter.ToInt16(fileContent, PEHeaderOffset + 22);
|
||||
|
||||
// Check if file is dll
|
||||
return (Characteristics & 0x2000) != 0x2000;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the file contents to a temporary file, if possible
|
||||
/// </summary>
|
||||
/// <param name="fileContent">File contents to write</param>
|
||||
/// <param name="sExtension">Optional extension for the temproary file, defaults to ".exe"</param>
|
||||
/// <returns>Name of the new temporary file, null on error</returns>
|
||||
internal static string MakeTempFile(byte[] fileContent, string sExtension = ".exe")
|
||||
{
|
||||
string filei = Guid.NewGuid().ToString();
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), "tmp", $"{filei}{sExtension}");
|
||||
try
|
||||
{
|
||||
File.Delete(tempPath);
|
||||
}
|
||||
catch { }
|
||||
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(tempPath));
|
||||
using (BinaryWriter bw = new BinaryWriter(File.OpenWrite(tempPath)))
|
||||
{
|
||||
bw.Write(fileContent);
|
||||
}
|
||||
|
||||
return Path.GetFullPath(tempPath);
|
||||
}
|
||||
catch { }
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies all required DLLs for a given executable
|
||||
/// </summary>
|
||||
/// <param name="file">Temporary file path</param>
|
||||
/// <param name="fileContent">File contents to read</param>
|
||||
/// <returns>Paths for all of the copied DLLs, null on error</returns>
|
||||
internal static string[] CopyDependentDlls(string file, byte[] fileContent)
|
||||
{
|
||||
var sections = ReadSections(fileContent);
|
||||
|
||||
long lastPosition;
|
||||
string[] saDependentDLLs = null;
|
||||
int index = 60;
|
||||
int PEHeaderOffset = BitConverter.ToInt32(fileContent, index);
|
||||
index = PEHeaderOffset + 120 + 8; //120 Bytes till IMAGE_DATA_DIRECTORY array,8 Bytes=size of IMAGE_DATA_DIRECTORY
|
||||
uint ImportTableRVA = BitConverter.ToUInt32(fileContent, index);
|
||||
index += 4;
|
||||
uint ImportTableSize = BitConverter.ToUInt32(fileContent, index);
|
||||
index = (int)RVA2Offset(ImportTableRVA, sections);
|
||||
index += 12;
|
||||
uint DllNameRVA = BitConverter.ToUInt32(fileContent, index);
|
||||
index += 4;
|
||||
while (DllNameRVA != 0)
|
||||
{
|
||||
string sDllName = "";
|
||||
byte bChar;
|
||||
lastPosition = index;
|
||||
uint DLLNameOffset = RVA2Offset(DllNameRVA, sections);
|
||||
if (DLLNameOffset > 0)
|
||||
{
|
||||
index = (int)DLLNameOffset;
|
||||
if ((char)fileContent[index] > -1)
|
||||
{
|
||||
do
|
||||
{
|
||||
bChar = fileContent[index];
|
||||
index++;
|
||||
sDllName += (char)bChar;
|
||||
} while (bChar != 0 && (char)fileContent[index] > -1);
|
||||
|
||||
sDllName = sDllName.Remove(sDllName.Length - 1, 1);
|
||||
if (File.Exists(Path.Combine(Path.GetDirectoryName(file), sDllName)))
|
||||
{
|
||||
if (saDependentDLLs == null)
|
||||
saDependentDLLs = new string[0];
|
||||
else
|
||||
saDependentDLLs = new string[saDependentDLLs.Length];
|
||||
|
||||
FileInfo fiDLL = new FileInfo(Path.Combine(Path.GetDirectoryName(file), sDllName));
|
||||
saDependentDLLs[saDependentDLLs.Length - 1] = fiDLL.CopyTo(Path.GetTempPath() + sDllName, true).FullName;
|
||||
}
|
||||
}
|
||||
|
||||
index = (int)lastPosition;
|
||||
}
|
||||
|
||||
index += 4 + 12;
|
||||
DllNameRVA = BitConverter.ToUInt32(fileContent, index);
|
||||
index += 4;
|
||||
}
|
||||
|
||||
return saDependentDLLs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to run an executable
|
||||
/// </summary>
|
||||
/// <param name="file">Executable to attempt to run</param>
|
||||
/// <returns>Process representing the running executable, null on error</returns>
|
||||
internal static Process StartSafe(string file)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return null;
|
||||
|
||||
Process startingprocess = new Process();
|
||||
startingprocess.StartInfo.FileName = file;
|
||||
startingprocess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||
startingprocess.StartInfo.CreateNoWindow = true;
|
||||
startingprocess.StartInfo.ErrorDialog = false;
|
||||
try
|
||||
{
|
||||
startingprocess.Start();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return startingprocess;
|
||||
}
|
||||
|
||||
private static IMAGE_SECTION_HEADER[] ReadSections(byte[] fileContent)
|
||||
{
|
||||
if (fileContent == null)
|
||||
return null;
|
||||
|
||||
uint PEHeaderOffset = BitConverter.ToUInt32(fileContent, 60);
|
||||
ushort NumberOfSections = BitConverter.ToUInt16(fileContent, (int)PEHeaderOffset + 6);
|
||||
var sections = new IMAGE_SECTION_HEADER[NumberOfSections];
|
||||
int index = (int)PEHeaderOffset + 120 + 16 * 8;
|
||||
for (int i = 0; i < NumberOfSections; i++)
|
||||
{
|
||||
sections[i] = ReadSection(fileContent, index);
|
||||
}
|
||||
|
||||
return sections;
|
||||
}
|
||||
|
||||
private static IMAGE_SECTION_HEADER ReadSection(byte[] fileContent, int ptr)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get the size of a section header for later
|
||||
int sectionSize = Marshal.SizeOf<IMAGE_SECTION_HEADER>();
|
||||
|
||||
// If the contents are null or the wrong size, we can't read a section
|
||||
if (fileContent == null || fileContent.Length < sectionSize)
|
||||
return null;
|
||||
|
||||
// Create a new section and try our best to read one
|
||||
IMAGE_SECTION_HEADER section = null;
|
||||
IntPtr tempPtr = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
// Get the pointer to where the section will go
|
||||
tempPtr = Marshal.AllocHGlobal(sectionSize);
|
||||
|
||||
// If we couldn't get the space, just return null
|
||||
if (tempPtr == IntPtr.Zero)
|
||||
return null;
|
||||
|
||||
// Copy from the array to the new space
|
||||
Marshal.Copy(fileContent, ptr, tempPtr, sectionSize);
|
||||
|
||||
// Get the new section and return
|
||||
section = Marshal.PtrToStructure<IMAGE_SECTION_HEADER>(tempPtr);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (tempPtr != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal(tempPtr);
|
||||
}
|
||||
|
||||
return section;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static uint RVA2Offset(uint RVA, IMAGE_SECTION_HEADER[] sections)
|
||||
{
|
||||
for (int i = 0; i < sections.Length; i++)
|
||||
{
|
||||
if (sections[i] == null)
|
||||
continue;
|
||||
|
||||
var section = sections[i];
|
||||
if (section.VirtualAddress <= RVA && section.VirtualAddress + section.PhysicalAddress > RVA)
|
||||
return RVA - section.VirtualAddress + section.PointerToRawData;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,31 +56,6 @@ namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
|
||||
public const ushort IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
|
||||
|
||||
/* Directory Entries */
|
||||
|
||||
/* Export Directory */
|
||||
public const byte IMAGE_DIRECTORY_ENTRY_EXPORT = 0;
|
||||
/* Import Directory */
|
||||
public const byte IMAGE_DIRECTORY_ENTRY_IMPORT = 1;
|
||||
/* Resource Directory */
|
||||
public const byte IMAGE_DIRECTORY_ENTRY_RESOURCE = 2;
|
||||
/* Exception Directory */
|
||||
public const byte IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3;
|
||||
/* Security Directory */
|
||||
public const byte IMAGE_DIRECTORY_ENTRY_SECURITY = 4;
|
||||
/* Base Relocation Table */
|
||||
public const byte IMAGE_DIRECTORY_ENTRY_BASERELOC = 5;
|
||||
/* Debug Directory */
|
||||
public const byte IMAGE_DIRECTORY_ENTRY_DEBUG = 6;
|
||||
/* Description String */
|
||||
public const byte IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7;
|
||||
/* Machine Value (MIPS GP) */
|
||||
public const byte IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8;
|
||||
/* TLS Directory */
|
||||
public const byte IMAGE_DIRECTORY_ENTRY_TLS = 9;
|
||||
/* Load Configuration Directory */
|
||||
public const byte IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10;
|
||||
|
||||
#endregion
|
||||
|
||||
#region IMAGE_SECTION_HEADER
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class IMAGE_DATA_DIRECTORY
|
||||
{
|
||||
public uint VirtualAddress;
|
||||
public uint Size;
|
||||
|
||||
public static IMAGE_DATA_DIRECTORY Deserialize(Stream stream)
|
||||
{
|
||||
var idd = new IMAGE_DATA_DIRECTORY();
|
||||
|
||||
idd.VirtualAddress = stream.ReadUInt32();
|
||||
idd.Size = stream.ReadUInt32();
|
||||
|
||||
return idd;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
/// <summary>
|
||||
/// DOS 1, 2, 3 .EXE header
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class IMAGE_DOS_HEADER
|
||||
{
|
||||
public ushort Magic; // 00 Magic number
|
||||
public ushort LastPageBytes; // 02 Bytes on last page of file
|
||||
public ushort Pages; // 04 Pages in file
|
||||
public ushort Relocations; // 06 Relocations
|
||||
public ushort HeaderParagraphSize; // 08 Size of header in paragraphs
|
||||
public ushort MinimumExtraParagraphs; // 0A Minimum extra paragraphs needed
|
||||
public ushort MaximumExtraParagraphs; // 0C Maximum extra paragraphs needed
|
||||
public ushort InitialSSValue; // 0E Initial (relative) SS value
|
||||
public ushort InitialSPValue; // 10 Initial SP value
|
||||
public ushort Checksum; // 12 Checksum
|
||||
public ushort InitialIPValue; // 14 Initial IP value
|
||||
public ushort InitialCSValue; // 16 Initial (relative) CS value
|
||||
public ushort RelocationTableAddr; // 18 File address of relocation table
|
||||
public ushort OverlayNumber; // 1A Overlay number
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.ERES1WDS)]
|
||||
public ushort[] Reserved1; // 1C Reserved words
|
||||
public ushort OEMIdentifier; // 24 OEM identifier (for e_oeminfo)
|
||||
public ushort OEMInformation; // 26 OEM information; e_oemid specific
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.ERES2WDS)]
|
||||
public ushort[] Reserved2; // 28 Reserved words
|
||||
public int NewExeHeaderAddr; // 3C File address of new exe header
|
||||
|
||||
public static IMAGE_DOS_HEADER Deserialize(Stream stream)
|
||||
{
|
||||
IMAGE_DOS_HEADER idh = new IMAGE_DOS_HEADER();
|
||||
|
||||
idh.Magic = stream.ReadUInt16();
|
||||
idh.LastPageBytes = stream.ReadUInt16();
|
||||
idh.Pages = stream.ReadUInt16();
|
||||
idh.Relocations = stream.ReadUInt16();
|
||||
idh.HeaderParagraphSize = stream.ReadUInt16();
|
||||
idh.MinimumExtraParagraphs = stream.ReadUInt16();
|
||||
idh.MaximumExtraParagraphs = stream.ReadUInt16();
|
||||
idh.InitialSSValue = stream.ReadUInt16();
|
||||
idh.InitialSPValue = stream.ReadUInt16();
|
||||
idh.Checksum = stream.ReadUInt16();
|
||||
idh.InitialIPValue = stream.ReadUInt16();
|
||||
idh.InitialCSValue = stream.ReadUInt16();
|
||||
idh.RelocationTableAddr = stream.ReadUInt16();
|
||||
idh.OverlayNumber = stream.ReadUInt16();
|
||||
idh.Reserved1 = new ushort[Constants.ERES1WDS];
|
||||
for (int i = 0; i < Constants.ERES1WDS; i++)
|
||||
{
|
||||
idh.Reserved1[i] = stream.ReadUInt16();
|
||||
}
|
||||
idh.OEMIdentifier = stream.ReadUInt16();
|
||||
idh.OEMInformation = stream.ReadUInt16();
|
||||
idh.Reserved2 = new ushort[Constants.ERES2WDS];
|
||||
for (int i = 0; i < Constants.ERES2WDS; i++)
|
||||
{
|
||||
idh.Reserved2[i] = stream.ReadUInt16();
|
||||
}
|
||||
idh.NewExeHeaderAddr = stream.ReadInt32();
|
||||
|
||||
return idh;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class IMAGE_FILE_HEADER
|
||||
{
|
||||
public ushort Machine;
|
||||
public ushort NumberOfSections;
|
||||
public uint TimeDateStamp;
|
||||
public uint PointerToSymbolTable;
|
||||
public uint NumberOfSymbols;
|
||||
public ushort SizeOfOptionalHeader;
|
||||
public ushort Characteristics;
|
||||
|
||||
public static IMAGE_FILE_HEADER Deserialize(Stream stream)
|
||||
{
|
||||
var ifh = new IMAGE_FILE_HEADER();
|
||||
|
||||
ifh.Machine = stream.ReadUInt16();
|
||||
ifh.NumberOfSections = stream.ReadUInt16();
|
||||
ifh.TimeDateStamp = stream.ReadUInt32();
|
||||
ifh.PointerToSymbolTable = stream.ReadUInt32();
|
||||
ifh.NumberOfSymbols = stream.ReadUInt32();
|
||||
ifh.SizeOfOptionalHeader = stream.ReadUInt16();
|
||||
ifh.Characteristics = stream.ReadUInt16();
|
||||
|
||||
return ifh;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class IMAGE_OPTIONAL_HEADER
|
||||
{
|
||||
// Standard fields
|
||||
|
||||
public ushort Magic;
|
||||
public byte MajorLinkerVersion;
|
||||
public byte MinorLinkerVersion;
|
||||
public uint SizeOfCode;
|
||||
public uint SizeOfInitializedData;
|
||||
public uint SizeOfUninitializedData;
|
||||
public uint AddressOfEntryPoint;
|
||||
public uint BaseOfCode;
|
||||
public uint BaseOfData;
|
||||
|
||||
// NT additional fields.
|
||||
|
||||
public uint ImageBase;
|
||||
public uint SectionAlignment;
|
||||
public uint FileAlignment;
|
||||
public ushort MajorOperatingSystemVersion;
|
||||
public ushort MinorOperatingSystemVersion;
|
||||
public ushort MajorImageVersion;
|
||||
public ushort MinorImageVersion;
|
||||
public ushort MajorSubsystemVersion;
|
||||
public ushort MinorSubsystemVersion;
|
||||
public uint Reserved1;
|
||||
public uint SizeOfImage;
|
||||
public uint SizeOfHeaders;
|
||||
public uint CheckSum;
|
||||
public ushort Subsystem;
|
||||
public ushort DllCharacteristics;
|
||||
public uint SizeOfStackReserve;
|
||||
public uint SizeOfStackCommit;
|
||||
public uint SizeOfHeapReserve;
|
||||
public uint SizeOfHeapCommit;
|
||||
public uint LoaderFlags;
|
||||
public uint NumberOfRvaAndSizes;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES)]
|
||||
public IMAGE_DATA_DIRECTORY[] DataDirectory;
|
||||
|
||||
public static IMAGE_OPTIONAL_HEADER Deserialize(Stream stream)
|
||||
{
|
||||
var ioh = new IMAGE_OPTIONAL_HEADER();
|
||||
|
||||
ioh.Magic = stream.ReadUInt16();
|
||||
ioh.MajorLinkerVersion = stream.ReadByteValue();
|
||||
ioh.MinorLinkerVersion = stream.ReadByteValue();
|
||||
ioh.SizeOfCode = stream.ReadUInt32();
|
||||
ioh.SizeOfInitializedData = stream.ReadUInt32();
|
||||
ioh.SizeOfUninitializedData = stream.ReadUInt32();
|
||||
ioh.AddressOfEntryPoint = stream.ReadUInt32();
|
||||
ioh.BaseOfCode = stream.ReadUInt32();
|
||||
ioh.BaseOfData = stream.ReadUInt32();
|
||||
|
||||
ioh.ImageBase = stream.ReadUInt32();
|
||||
ioh.SectionAlignment = stream.ReadUInt32();
|
||||
ioh.FileAlignment = stream.ReadUInt32();
|
||||
ioh.MajorOperatingSystemVersion = stream.ReadUInt16();
|
||||
ioh.MinorOperatingSystemVersion = stream.ReadUInt16();
|
||||
ioh.MajorImageVersion = stream.ReadUInt16();
|
||||
ioh.MinorImageVersion = stream.ReadUInt16();
|
||||
ioh.MajorSubsystemVersion = stream.ReadUInt16();
|
||||
ioh.MinorSubsystemVersion = stream.ReadUInt16();
|
||||
ioh.Reserved1 = stream.ReadUInt32();
|
||||
ioh.SizeOfImage = stream.ReadUInt32();
|
||||
ioh.SizeOfHeaders = stream.ReadUInt32();
|
||||
ioh.CheckSum = stream.ReadUInt32();
|
||||
ioh.Subsystem = stream.ReadUInt16();
|
||||
ioh.DllCharacteristics = stream.ReadUInt16();
|
||||
ioh.SizeOfStackReserve = stream.ReadUInt32();
|
||||
ioh.SizeOfStackCommit = stream.ReadUInt32();
|
||||
ioh.SizeOfHeapReserve = stream.ReadUInt32();
|
||||
ioh.SizeOfHeapCommit = stream.ReadUInt32();
|
||||
ioh.LoaderFlags = stream.ReadUInt32();
|
||||
ioh.NumberOfRvaAndSizes = stream.ReadUInt32();
|
||||
ioh.DataDirectory = new IMAGE_DATA_DIRECTORY[Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||
for (int i = 0; i < Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
|
||||
{
|
||||
ioh.DataDirectory[i] = IMAGE_DATA_DIRECTORY.Deserialize(stream);
|
||||
}
|
||||
|
||||
return ioh;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
/// <summary>
|
||||
/// New .EXE header
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class IMAGE_OS2_HEADER
|
||||
{
|
||||
public ushort Magic; // 00 Magic number NE_MAGIC
|
||||
public byte LinkerVersion; // 02 Linker Version number
|
||||
public byte LinkerRevision; // 03 Linker Revision number
|
||||
public ushort EntryTableOffset; // 04 Offset of Entry Table
|
||||
public ushort EntryTableSize; // 06 Number of bytes in Entry Table
|
||||
public uint CrcChecksum; // 08 Checksum of whole file
|
||||
public ushort Flags; // 0C Flag word
|
||||
public ushort Autodata; // 0E Automatic data segment number
|
||||
public ushort InitialHeapAlloc; // 10 Initial heap allocation
|
||||
public ushort InitialStackAlloc; // 12 Initial stack allocation
|
||||
public uint InitialCSIPSetting; // 14 Initial CS:IP setting
|
||||
public uint InitialSSSPSetting; // 18 Initial SS:SP setting
|
||||
public ushort FileSegmentCount; // 1C Count of file segments
|
||||
public ushort ModuleReferenceTableSize; // 1E Entries in Module Reference Table
|
||||
public ushort NonResidentNameTableSize; // 20 Size of non-resident name table
|
||||
public ushort SegmentTableOffset; // 22 Offset of Segment Table
|
||||
public ushort ResourceTableOffset; // 24 Offset of Resource Table
|
||||
public ushort ResidentNameTableOffset; // 26 Offset of resident name table
|
||||
public ushort ModuleReferenceTableOffset; // 28 Offset of Module Reference Table
|
||||
public ushort ImportedNamesTableOffset; // 2A Offset of Imported Names Table
|
||||
public uint NonResidentNamesTableOffset; // 2C Offset of Non-resident Names Table
|
||||
public ushort MovableEntriesCount; // 30 Count of movable entries
|
||||
public ushort SegmentAlignmentShiftCount; // 32 Segment alignment shift count
|
||||
public ushort ResourceEntriesCount; // 34 Count of resource entries
|
||||
public byte TargetOperatingSystem; // 36 Target operating system
|
||||
public byte AdditionalFlags; // 37 Additional flags
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.NERESWORDS)]
|
||||
public ushort[] Reserved; // 38 3 reserved words
|
||||
public byte WindowsSDKRevision; // 3E Windows SDK revison number
|
||||
public byte WindowsSDKVersion; // 3F Windows SDK version number
|
||||
|
||||
public static IMAGE_OS2_HEADER Deserialize(Stream stream)
|
||||
{
|
||||
var ioh = new IMAGE_OS2_HEADER();
|
||||
|
||||
ioh.Magic = stream.ReadUInt16();
|
||||
ioh.LinkerVersion = stream.ReadByteValue();
|
||||
ioh.LinkerRevision = stream.ReadByteValue();
|
||||
ioh.EntryTableOffset = stream.ReadUInt16();
|
||||
ioh.EntryTableSize = stream.ReadUInt16();
|
||||
ioh.CrcChecksum = stream.ReadUInt32();
|
||||
ioh.Flags = stream.ReadUInt16();
|
||||
ioh.Autodata = stream.ReadUInt16();
|
||||
ioh.InitialHeapAlloc = stream.ReadUInt16();
|
||||
ioh.InitialStackAlloc = stream.ReadUInt16();
|
||||
ioh.InitialCSIPSetting = stream.ReadUInt32();
|
||||
ioh.InitialSSSPSetting = stream.ReadUInt32();
|
||||
ioh.FileSegmentCount = stream.ReadUInt16();
|
||||
ioh.ModuleReferenceTableSize = stream.ReadUInt16();
|
||||
ioh.NonResidentNameTableSize = stream.ReadUInt16();
|
||||
ioh.SegmentTableOffset = stream.ReadUInt16();
|
||||
ioh.ResourceTableOffset = stream.ReadUInt16();
|
||||
ioh.ResidentNameTableOffset = stream.ReadUInt16();
|
||||
ioh.ModuleReferenceTableOffset = stream.ReadUInt16();
|
||||
ioh.ImportedNamesTableOffset = stream.ReadUInt16();
|
||||
ioh.NonResidentNamesTableOffset = stream.ReadUInt32();
|
||||
ioh.MovableEntriesCount = stream.ReadUInt16();
|
||||
ioh.SegmentAlignmentShiftCount = stream.ReadUInt16();
|
||||
ioh.ResourceEntriesCount = stream.ReadUInt16();
|
||||
ioh.TargetOperatingSystem = stream.ReadByteValue();
|
||||
ioh.AdditionalFlags = stream.ReadByteValue();
|
||||
ioh.Reserved = new ushort[Constants.NERESWORDS];
|
||||
for (int i = 0; i < Constants.NERESWORDS; i++)
|
||||
{
|
||||
ioh.Reserved[i] = stream.ReadUInt16();
|
||||
}
|
||||
ioh.WindowsSDKRevision = stream.ReadByteValue();
|
||||
ioh.WindowsSDKVersion = stream.ReadByteValue();
|
||||
|
||||
return ioh;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class IMAGE_RESOURCE_DATA_ENTRY
|
||||
{
|
||||
public uint OffsetToData;
|
||||
public uint Size;
|
||||
public uint CodePage;
|
||||
public uint Reserved;
|
||||
|
||||
public static IMAGE_RESOURCE_DATA_ENTRY Deserialize(Stream stream)
|
||||
{
|
||||
var irde = new IMAGE_RESOURCE_DATA_ENTRY();
|
||||
|
||||
irde.OffsetToData = stream.ReadUInt32();
|
||||
irde.Size = stream.ReadUInt32();
|
||||
irde.CodePage = stream.ReadUInt32();
|
||||
irde.Reserved = stream.ReadUInt32();
|
||||
|
||||
return irde;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class IMAGE_RESOURCE_DIRECTORY
|
||||
{
|
||||
public uint Characteristics;
|
||||
public uint TimeDateStamp;
|
||||
public ushort MajorVersion;
|
||||
public ushort MinorVersion;
|
||||
public ushort NumberOfNamedEntries;
|
||||
public ushort NumberOfIdEntries;
|
||||
|
||||
public static IMAGE_RESOURCE_DIRECTORY Deserialize(Stream stream)
|
||||
{
|
||||
var ird = new IMAGE_RESOURCE_DIRECTORY();
|
||||
|
||||
ird.Characteristics = stream.ReadUInt32();
|
||||
ird.TimeDateStamp = stream.ReadUInt32();
|
||||
ird.MajorVersion = stream.ReadUInt16();
|
||||
ird.MinorVersion = stream.ReadUInt16();
|
||||
ird.NumberOfNamedEntries = stream.ReadUInt16();
|
||||
ird.NumberOfIdEntries = stream.ReadUInt16();
|
||||
|
||||
return ird;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class IMAGE_RESOURCE_DIRECTORY_ENTRY
|
||||
{
|
||||
public uint Name;
|
||||
public uint OffsetToData;
|
||||
|
||||
public static IMAGE_RESOURCE_DIRECTORY_ENTRY Deserialize(Stream stream)
|
||||
{
|
||||
var irde = new IMAGE_RESOURCE_DIRECTORY_ENTRY();
|
||||
|
||||
irde.Name = stream.ReadUInt32();
|
||||
irde.OffsetToData = stream.ReadUInt32();
|
||||
|
||||
return irde;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class IMAGE_RESOURCE_DIR_STRING_U
|
||||
{
|
||||
public ushort Length;
|
||||
public char[] NameString;
|
||||
|
||||
public static IMAGE_RESOURCE_DIR_STRING_U Deserialize(Stream stream)
|
||||
{
|
||||
var irdsu = new IMAGE_RESOURCE_DIR_STRING_U();
|
||||
|
||||
irdsu.Length = stream.ReadUInt16();
|
||||
irdsu.NameString = stream.ReadChars(irdsu.Length);
|
||||
|
||||
return irdsu;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class IMAGE_SECTION_HEADER
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.IMAGE_SIZEOF_SHORT_NAME)]
|
||||
public byte[] Name;
|
||||
|
||||
// Misc
|
||||
public uint PhysicalAddress;
|
||||
public uint VirtualSize;
|
||||
|
||||
public uint VirtualAddress;
|
||||
public uint SizeOfRawData;
|
||||
public uint PointerToRawData;
|
||||
public uint PointerToRelocations;
|
||||
public uint PointerToLinenumbers;
|
||||
public ushort NumberOfRelocations;
|
||||
public ushort NumberOfLinenumbers;
|
||||
public SectionCharacteristics Characteristics;
|
||||
|
||||
public static IMAGE_SECTION_HEADER Deserialize(Stream stream)
|
||||
{
|
||||
var ish = new IMAGE_SECTION_HEADER();
|
||||
|
||||
ish.Name = stream.ReadBytes(Constants.IMAGE_SIZEOF_SHORT_NAME);
|
||||
|
||||
// Misc
|
||||
ish.PhysicalAddress = stream.ReadUInt32();
|
||||
ish.VirtualSize = ish.PhysicalAddress;
|
||||
|
||||
ish.VirtualAddress = stream.ReadUInt32();
|
||||
ish.SizeOfRawData = stream.ReadUInt32();
|
||||
ish.PointerToRawData = stream.ReadUInt32();
|
||||
ish.PointerToRelocations = stream.ReadUInt32();
|
||||
ish.PointerToLinenumbers = stream.ReadUInt32();
|
||||
ish.NumberOfRelocations = stream.ReadUInt16();
|
||||
ish.NumberOfLinenumbers = stream.ReadUInt16();
|
||||
ish.Characteristics = (SectionCharacteristics)stream.ReadUInt32();
|
||||
|
||||
return ish;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.MZ.Headers
|
||||
{
|
||||
/// <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>
|
||||
/// <remarks>https://wiki.osdev.org/MZ</remarks>
|
||||
public class MSDOSExecutableHeader
|
||||
{
|
||||
#region Standard Fields
|
||||
|
||||
/// <summary>
|
||||
/// 0x5A4D (ASCII for 'M' and 'Z') [00]
|
||||
/// </summary>
|
||||
public ushort Magic;
|
||||
|
||||
/// <summary>
|
||||
/// Number of bytes in the last page. [02]
|
||||
/// </summary>
|
||||
public ushort LastPageBytes;
|
||||
|
||||
/// <summary>
|
||||
/// Number of whole/partial pages. [04]
|
||||
/// </summary>
|
||||
public ushort Pages;
|
||||
|
||||
/// <summary>
|
||||
/// Number of entries in the relocation table. [06]
|
||||
/// </summary>
|
||||
public ushort Relocations;
|
||||
|
||||
/// <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>
|
||||
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. [0A]
|
||||
/// </summary>
|
||||
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. [0C]
|
||||
/// </summary>
|
||||
public ushort MaximumExtraParagraphs;
|
||||
|
||||
/// <summary>
|
||||
/// Relocatable segment address for SS. [0E]
|
||||
/// </summary>
|
||||
public ushort InitialSSValue;
|
||||
|
||||
/// <summary>
|
||||
/// Initial value for SP. [10]
|
||||
/// </summary>
|
||||
public ushort InitialSPValue;
|
||||
|
||||
/// <summary>
|
||||
/// When added to the sum of all other words in the file, the result should be zero. [12]
|
||||
/// </summary>
|
||||
public ushort Checksum;
|
||||
|
||||
/// <summary>
|
||||
/// Initial value for IP. [14]
|
||||
/// </summary>
|
||||
public ushort InitialIPValue;
|
||||
|
||||
/// <summary>
|
||||
/// Relocatable segment address for CS. [16]
|
||||
/// </summary>
|
||||
public ushort InitialCSValue;
|
||||
|
||||
/// <summary>
|
||||
/// The (absolute) offset to the relocation table. [18]
|
||||
/// </summary>
|
||||
public ushort RelocationTableAddr;
|
||||
|
||||
/// <summary>
|
||||
/// Value used for overlay management.
|
||||
/// If zero, this is the main executable. [1A]
|
||||
/// </summary>
|
||||
public ushort OverlayNumber;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PE Extensions
|
||||
|
||||
/// <summary>
|
||||
/// Reserved words [1C]
|
||||
/// </summary>
|
||||
public ushort[] Reserved1;
|
||||
|
||||
/// <summary>
|
||||
/// Defined by name but no other information is given; typically zeroes [24]
|
||||
/// </summary>
|
||||
public ushort OEMIdentifier;
|
||||
|
||||
/// <summary>
|
||||
/// Defined by name but no other information is given; typically zeroes [26]
|
||||
/// </summary>
|
||||
public ushort OEMInformation;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved words [28]
|
||||
/// </summary>
|
||||
public ushort[] Reserved2;
|
||||
|
||||
/// <summary>
|
||||
/// Starting address of the PE header [3C]
|
||||
/// </summary>
|
||||
public int NewExeHeaderAddr;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// All data after the last item in the header but before the new EXE header address
|
||||
/// </summary>
|
||||
public byte[] ExecutableData;
|
||||
|
||||
public static MSDOSExecutableHeader Deserialize(Stream stream, bool asStub = true)
|
||||
{
|
||||
MSDOSExecutableHeader idh = new MSDOSExecutableHeader();
|
||||
|
||||
idh.Magic = stream.ReadUInt16();
|
||||
idh.LastPageBytes = stream.ReadUInt16();
|
||||
idh.Pages = stream.ReadUInt16();
|
||||
idh.Relocations = stream.ReadUInt16();
|
||||
idh.HeaderParagraphSize = stream.ReadUInt16();
|
||||
idh.MinimumExtraParagraphs = stream.ReadUInt16();
|
||||
idh.MaximumExtraParagraphs = stream.ReadUInt16();
|
||||
idh.InitialSSValue = stream.ReadUInt16();
|
||||
idh.InitialSPValue = stream.ReadUInt16();
|
||||
idh.Checksum = stream.ReadUInt16();
|
||||
idh.InitialIPValue = stream.ReadUInt16();
|
||||
idh.InitialCSValue = stream.ReadUInt16();
|
||||
idh.RelocationTableAddr = stream.ReadUInt16();
|
||||
idh.OverlayNumber = stream.ReadUInt16();
|
||||
|
||||
// If we're not reading as a stub, return now
|
||||
if (!asStub)
|
||||
return idh;
|
||||
|
||||
idh.Reserved1 = new ushort[Constants.ERES1WDS];
|
||||
for (int i = 0; i < Constants.ERES1WDS; i++)
|
||||
{
|
||||
idh.Reserved1[i] = stream.ReadUInt16();
|
||||
}
|
||||
|
||||
idh.OEMIdentifier = stream.ReadUInt16();
|
||||
idh.OEMInformation = stream.ReadUInt16();
|
||||
idh.Reserved2 = new ushort[Constants.ERES2WDS];
|
||||
for (int i = 0; i < Constants.ERES2WDS; i++)
|
||||
{
|
||||
idh.Reserved2[i] = stream.ReadUInt16();
|
||||
}
|
||||
|
||||
idh.NewExeHeaderAddr = stream.ReadInt32();
|
||||
idh.ExecutableData = stream.ReadBytes(idh.NewExeHeaderAddr - (int)stream.Position);
|
||||
|
||||
return idh;
|
||||
}
|
||||
|
||||
public static MSDOSExecutableHeader Deserialize(byte[] content, ref int offset, bool asStub = true)
|
||||
{
|
||||
MSDOSExecutableHeader idh = new MSDOSExecutableHeader();
|
||||
|
||||
idh.Magic = content.ReadUInt16(ref offset);
|
||||
idh.LastPageBytes = content.ReadUInt16(ref offset);
|
||||
idh.Pages = content.ReadUInt16(ref offset);
|
||||
idh.Relocations = content.ReadUInt16(ref offset);
|
||||
idh.HeaderParagraphSize = content.ReadUInt16(ref offset);
|
||||
idh.MinimumExtraParagraphs = content.ReadUInt16(ref offset);
|
||||
idh.MaximumExtraParagraphs = content.ReadUInt16(ref offset);
|
||||
idh.InitialSSValue = content.ReadUInt16(ref offset);
|
||||
idh.InitialSPValue = content.ReadUInt16(ref offset);
|
||||
idh.Checksum = content.ReadUInt16(ref offset);
|
||||
idh.InitialIPValue = content.ReadUInt16(ref offset);
|
||||
idh.InitialCSValue = content.ReadUInt16(ref offset);
|
||||
idh.RelocationTableAddr = content.ReadUInt16(ref offset);
|
||||
idh.OverlayNumber = content.ReadUInt16(ref offset);
|
||||
|
||||
// If we're not reading as a stub, return now
|
||||
if (!asStub)
|
||||
return idh;
|
||||
|
||||
idh.Reserved1 = new ushort[Constants.ERES1WDS];
|
||||
for (int i = 0; i < Constants.ERES1WDS; i++)
|
||||
{
|
||||
idh.Reserved1[i] = content.ReadUInt16(ref offset);
|
||||
}
|
||||
|
||||
idh.OEMIdentifier = content.ReadUInt16(ref offset);
|
||||
idh.OEMInformation = content.ReadUInt16(ref offset);
|
||||
idh.Reserved2 = new ushort[Constants.ERES2WDS];
|
||||
for (int i = 0; i < Constants.ERES2WDS; i++)
|
||||
{
|
||||
idh.Reserved2[i] = content.ReadUInt16(ref offset);
|
||||
}
|
||||
|
||||
idh.NewExeHeaderAddr = content.ReadInt32(ref offset);
|
||||
idh.ExecutableData = content.ReadBytes(ref offset, idh.NewExeHeaderAddr - offset);
|
||||
|
||||
return idh;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class NAMEINFO
|
||||
{
|
||||
public ushort Offset;
|
||||
public ushort Length;
|
||||
public ushort Flags;
|
||||
public ushort ID;
|
||||
public ushort Handle;
|
||||
public ushort Usage;
|
||||
|
||||
public static NAMEINFO Deserialize(Stream stream)
|
||||
{
|
||||
var ni = new NAMEINFO();
|
||||
|
||||
ni.Offset = stream.ReadUInt16();
|
||||
ni.Length = stream.ReadUInt16();
|
||||
ni.Flags = stream.ReadUInt16();
|
||||
ni.ID = stream.ReadUInt16();
|
||||
ni.Handle = stream.ReadUInt16();
|
||||
ni.Usage = stream.ReadUInt16();
|
||||
|
||||
return ni;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.NE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// These name strings are case-sensitive and are not null-terminated
|
||||
/// </summary>
|
||||
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[] Data;
|
||||
|
||||
/// <summary>
|
||||
/// Ordinal number (index into entry table).
|
||||
/// This value is ignored for the module name.
|
||||
/// </summary>
|
||||
public ushort OrdinalNumber;
|
||||
|
||||
/// <summary>
|
||||
/// ASCII text of the name string
|
||||
/// </summary>
|
||||
public string DataAsString
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Data == null)
|
||||
return string.Empty;
|
||||
|
||||
// Try to read direct as ASCII
|
||||
try
|
||||
{
|
||||
return Encoding.ASCII.GetString(Data);
|
||||
}
|
||||
catch { }
|
||||
|
||||
// If ASCII encoding fails, then just return an empty string
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public static ResidentNameTableEntry Deserialize(Stream stream)
|
||||
{
|
||||
var rnte = new ResidentNameTableEntry();
|
||||
|
||||
rnte.Length = stream.ReadByteValue();
|
||||
if (rnte.Length == 0)
|
||||
return rnte;
|
||||
|
||||
rnte.Data = stream.ReadBytes(rnte.Length);
|
||||
rnte.OrdinalNumber = stream.ReadUInt16();
|
||||
|
||||
return rnte;
|
||||
}
|
||||
|
||||
public static ResidentNameTableEntry Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var rnte = new ResidentNameTableEntry();
|
||||
|
||||
rnte.Length = content.ReadByte(ref offset);
|
||||
if (rnte.Length == 0)
|
||||
return rnte;
|
||||
|
||||
rnte.Data = content.ReadBytes(ref offset, rnte.Length);
|
||||
rnte.OrdinalNumber = content.ReadUInt16(ref offset);
|
||||
|
||||
return rnte;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.NE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Resource type and name strings
|
||||
/// </summary>
|
||||
public class ResourceNameString
|
||||
{
|
||||
/// <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 char[] Value;
|
||||
|
||||
public static ResourceNameString Deserialize(Stream stream)
|
||||
{
|
||||
var rns = new ResourceNameString();
|
||||
|
||||
rns.Length = stream.ReadByteValue();
|
||||
rns.Value = stream.ReadChars(rns.Length, Encoding.ASCII);
|
||||
|
||||
return rns;
|
||||
}
|
||||
|
||||
public static ResourceNameString Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var rns = new ResourceNameString();
|
||||
|
||||
rns.Length = content.ReadByte(ref offset);
|
||||
rns.Value = Encoding.ASCII.GetChars(content, offset, rns.Length); offset += rns.Length;
|
||||
|
||||
return rns;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.NE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// A table of resources for this type
|
||||
/// </summary>
|
||||
public class ResourceTableEntry
|
||||
{
|
||||
/// <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>
|
||||
/// Resource flags
|
||||
/// </summary>
|
||||
public ResourceTableEntryFlags Flags;
|
||||
|
||||
/// <summary>
|
||||
/// 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 ushort Handle;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved.
|
||||
/// </summary>
|
||||
public ushort Usage;
|
||||
|
||||
public static ResourceTableEntry Deserialize(Stream stream)
|
||||
{
|
||||
var ni = new ResourceTableEntry();
|
||||
|
||||
ni.Offset = stream.ReadUInt16();
|
||||
ni.Length = stream.ReadUInt16();
|
||||
ni.Flags = (ResourceTableEntryFlags)stream.ReadUInt16();
|
||||
ni.ResourceID = stream.ReadUInt16();
|
||||
ni.Handle = stream.ReadUInt16();
|
||||
ni.Usage = stream.ReadUInt16();
|
||||
|
||||
return ni;
|
||||
}
|
||||
|
||||
public static ResourceTableEntry Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var ni = new ResourceTableEntry();
|
||||
|
||||
ni.Offset = content.ReadUInt16(ref offset);
|
||||
ni.Length = content.ReadUInt16(ref offset);
|
||||
ni.Flags = (ResourceTableEntryFlags)content.ReadUInt16(ref offset);
|
||||
ni.ResourceID = content.ReadUInt16(ref offset);
|
||||
ni.Handle = content.ReadUInt16(ref offset);
|
||||
ni.Usage = content.ReadUInt16(ref offset);
|
||||
|
||||
return ni;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.NE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Resource type information block
|
||||
/// </summary>
|
||||
public class ResourceTypeInformationBlock
|
||||
{
|
||||
/// <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>
|
||||
/// Reserved.
|
||||
/// </summary>
|
||||
public ResourceTableEntry[] ResourceTable;
|
||||
|
||||
public static ResourceTypeInformationBlock Deserialize(Stream stream)
|
||||
{
|
||||
var rtib = new ResourceTypeInformationBlock();
|
||||
|
||||
rtib.TypeID = stream.ReadUInt16();
|
||||
rtib.ResourceCount = stream.ReadUInt16();
|
||||
rtib.Reserved = stream.ReadUInt32();
|
||||
|
||||
rtib.ResourceTable = new ResourceTableEntry[rtib.ResourceCount];
|
||||
for (int i = 0; i < rtib.ResourceCount; i++)
|
||||
{
|
||||
rtib.ResourceTable[i] = ResourceTableEntry.Deserialize(stream);
|
||||
}
|
||||
|
||||
return rtib;
|
||||
}
|
||||
|
||||
public static ResourceTypeInformationBlock Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var rtib = new ResourceTypeInformationBlock();
|
||||
|
||||
rtib.TypeID = content.ReadUInt16(ref offset);
|
||||
rtib.ResourceCount = content.ReadUInt16(ref offset);
|
||||
rtib.Reserved = content.ReadUInt32(ref offset);
|
||||
|
||||
rtib.ResourceTable = new ResourceTableEntry[rtib.ResourceCount];
|
||||
for (int i = 0; i < rtib.ResourceCount; i++)
|
||||
{
|
||||
rtib.ResourceTable[i] = ResourceTableEntry.Deserialize(content, ref offset);
|
||||
}
|
||||
|
||||
return rtib;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.NE.Entries
|
||||
{
|
||||
/// <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>
|
||||
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 StartFileSector;
|
||||
|
||||
/// <summary>
|
||||
/// Length of the segment in the file, in bytes. Zero means 64K.
|
||||
/// </summary>
|
||||
public ushort BytesInFile;
|
||||
|
||||
/// <summary>
|
||||
/// Attribute flags
|
||||
/// </summary>
|
||||
public SegmentTableEntryFlags Flags;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum allocation size of the segment, in bytes.
|
||||
/// Total size of the segment. Zero means 64K
|
||||
/// </summary>
|
||||
public ushort MinimumAllocation;
|
||||
|
||||
public static SegmentTableEntry Deserialize(Stream stream)
|
||||
{
|
||||
var nste = new SegmentTableEntry();
|
||||
|
||||
nste.StartFileSector = stream.ReadUInt16();
|
||||
nste.BytesInFile = stream.ReadUInt16();
|
||||
nste.Flags = (SegmentTableEntryFlags)stream.ReadUInt16();
|
||||
nste.MinimumAllocation = stream.ReadUInt16();
|
||||
|
||||
return nste;
|
||||
}
|
||||
|
||||
public static SegmentTableEntry Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var nste = new SegmentTableEntry();
|
||||
|
||||
nste.StartFileSector = content.ReadUInt16(ref offset);
|
||||
nste.BytesInFile = content.ReadUInt16(ref offset);
|
||||
nste.Flags = (SegmentTableEntryFlags)content.ReadUInt16(ref offset);
|
||||
nste.MinimumAllocation = content.ReadUInt16(ref offset);
|
||||
|
||||
return nste;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.NE.Headers
|
||||
{
|
||||
/// <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>
|
||||
/// <remarks>http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm</remarks>
|
||||
public class NewExecutableHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// Signature word. [00]
|
||||
/// "N" is low-order byte.
|
||||
/// "E" is high-order byte.
|
||||
/// </summary>
|
||||
public ushort Magic;
|
||||
|
||||
/// <summary>
|
||||
/// Version number of the linker. [02]
|
||||
/// </summary>
|
||||
public byte LinkerVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Revision number of the linker. [03]
|
||||
/// </summary>
|
||||
public byte LinkerRevision;
|
||||
|
||||
/// <summary>
|
||||
/// Entry Table file offset, relative to the beginning of the segmented EXE header. [04]
|
||||
/// </summary>
|
||||
public ushort EntryTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Number of bytes in the entry table. [06]
|
||||
/// </summary>
|
||||
public ushort EntryTableSize;
|
||||
|
||||
/// <summary>
|
||||
/// 32-bit CRC of entire contents of file. [08]
|
||||
/// These words are taken as 00 during the calculation.
|
||||
/// </summary>
|
||||
public uint CrcChecksum;
|
||||
|
||||
/// <summary>
|
||||
/// Program flags, bitmapped [0C]
|
||||
/// </summary>
|
||||
public byte ProgramFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Application flags, bitmapped [0D]
|
||||
/// </summary>
|
||||
public byte ApplicationFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Automatic data segment number [0E]
|
||||
/// </summary>
|
||||
public ushort Autodata;
|
||||
|
||||
/// <summary>
|
||||
/// Initial heap allocation [10]
|
||||
/// </summary>
|
||||
public ushort InitialHeapAlloc;
|
||||
|
||||
/// <summary>
|
||||
/// Initial stack allocation [12]
|
||||
/// </summary>
|
||||
public ushort InitialStackAlloc;
|
||||
|
||||
/// <summary>
|
||||
/// CS:IP entry point, CS is index into segment table [14]
|
||||
/// </summary>
|
||||
public uint InitialCSIPSetting;
|
||||
|
||||
/// <summary>
|
||||
/// SS:SP inital stack pointer, SS is index into segment table [18]
|
||||
/// </summary>
|
||||
public uint InitialSSSPSetting;
|
||||
|
||||
/// <summary>
|
||||
/// Number of segments in segment table [1C]
|
||||
/// </summary>
|
||||
public ushort FileSegmentCount;
|
||||
|
||||
/// <summary>
|
||||
/// Entries in Module Reference Table [1E]
|
||||
/// </summary>
|
||||
public ushort ModuleReferenceTableSize;
|
||||
|
||||
/// <summary>
|
||||
/// Size of non-resident name table [20]
|
||||
/// </summary>
|
||||
public ushort NonResidentNameTableSize;
|
||||
|
||||
/// <summary>
|
||||
/// Offset of Segment Table [22]
|
||||
/// </summary>
|
||||
public ushort SegmentTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Offset of Resource Table [24]
|
||||
/// </summary>
|
||||
public ushort ResourceTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Offset of resident name table [26]
|
||||
/// </summary>
|
||||
public ushort ResidentNameTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Offset of Module Reference Table [28]
|
||||
/// </summary>
|
||||
public ushort ModuleReferenceTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Offset of Imported Names Table [2A]
|
||||
/// </summary>
|
||||
public ushort ImportedNamesTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Offset of Non-resident Names Table [2C]
|
||||
/// </summary>
|
||||
public uint NonResidentNamesTableOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Count of moveable entry points listed in entry table [30]
|
||||
/// </summary>
|
||||
public ushort MovableEntriesCount;
|
||||
|
||||
/// <summary>
|
||||
/// File allignment size shift count (0-9 (default 512 byte pages)) [32]
|
||||
/// </summary>
|
||||
public ushort SegmentAlignmentShiftCount;
|
||||
|
||||
/// <summary>
|
||||
/// Count of resource table entries [34]
|
||||
/// </summary>
|
||||
public ushort ResourceEntriesCount;
|
||||
|
||||
/// <summary>
|
||||
/// Target operating system [36]
|
||||
/// </summary>
|
||||
public byte TargetOperatingSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Other OS/2 flags [37]
|
||||
/// </summary>
|
||||
public byte AdditionalFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Offset to return thunks or start of gangload area [38]
|
||||
/// </summary>
|
||||
public ushort ReturnThunkOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Offset to segment reference thunks or size of gangload area [3A]
|
||||
/// </summary>
|
||||
public ushort SegmentReferenceThunkOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum code swap area size [3C]
|
||||
/// </summary>
|
||||
public ushort MinCodeSwapAreaSize;
|
||||
|
||||
/// <summary>
|
||||
/// Windows SDK revison number [3E]
|
||||
/// </summary>
|
||||
public byte WindowsSDKRevision;
|
||||
|
||||
/// <summary>
|
||||
/// Windows SDK version number [3F]
|
||||
/// </summary>
|
||||
public byte WindowsSDKVersion;
|
||||
|
||||
public static NewExecutableHeader Deserialize(Stream stream)
|
||||
{
|
||||
var neh = new NewExecutableHeader();
|
||||
|
||||
neh.Magic = stream.ReadUInt16();
|
||||
neh.LinkerVersion = stream.ReadByteValue();
|
||||
neh.LinkerRevision = stream.ReadByteValue();
|
||||
neh.EntryTableOffset = stream.ReadUInt16();
|
||||
neh.EntryTableSize = stream.ReadUInt16();
|
||||
neh.CrcChecksum = stream.ReadUInt32();
|
||||
neh.ProgramFlags = stream.ReadByteValue();
|
||||
neh.ApplicationFlags = stream.ReadByteValue();
|
||||
neh.Autodata = stream.ReadUInt16();
|
||||
neh.InitialHeapAlloc = stream.ReadUInt16();
|
||||
neh.InitialStackAlloc = stream.ReadUInt16();
|
||||
neh.InitialCSIPSetting = stream.ReadUInt32();
|
||||
neh.InitialSSSPSetting = stream.ReadUInt32();
|
||||
neh.FileSegmentCount = stream.ReadUInt16();
|
||||
neh.ModuleReferenceTableSize = stream.ReadUInt16();
|
||||
neh.NonResidentNameTableSize = stream.ReadUInt16();
|
||||
neh.SegmentTableOffset = stream.ReadUInt16();
|
||||
neh.ResourceTableOffset = stream.ReadUInt16();
|
||||
neh.ResidentNameTableOffset = stream.ReadUInt16();
|
||||
neh.ModuleReferenceTableOffset = stream.ReadUInt16();
|
||||
neh.ImportedNamesTableOffset = stream.ReadUInt16();
|
||||
neh.NonResidentNamesTableOffset = stream.ReadUInt32();
|
||||
neh.MovableEntriesCount = stream.ReadUInt16();
|
||||
neh.SegmentAlignmentShiftCount = stream.ReadUInt16();
|
||||
neh.ResourceEntriesCount = stream.ReadUInt16();
|
||||
neh.TargetOperatingSystem = stream.ReadByteValue();
|
||||
neh.AdditionalFlags = stream.ReadByteValue();
|
||||
neh.ReturnThunkOffset = stream.ReadUInt16();
|
||||
neh.SegmentReferenceThunkOffset = stream.ReadUInt16();
|
||||
neh.MinCodeSwapAreaSize = stream.ReadUInt16();
|
||||
neh.WindowsSDKRevision = stream.ReadByteValue();
|
||||
neh.WindowsSDKVersion = stream.ReadByteValue();
|
||||
|
||||
return neh;
|
||||
}
|
||||
|
||||
public static NewExecutableHeader Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var neh = new NewExecutableHeader();
|
||||
|
||||
neh.Magic = content.ReadUInt16(ref offset);
|
||||
neh.LinkerVersion = content.ReadByte(ref offset);
|
||||
neh.LinkerRevision = content.ReadByte(ref offset);
|
||||
neh.EntryTableOffset = content.ReadUInt16(ref offset);
|
||||
neh.EntryTableSize = content.ReadUInt16(ref offset);
|
||||
neh.CrcChecksum = content.ReadUInt32(ref offset);
|
||||
neh.ProgramFlags = content.ReadByte(ref offset);
|
||||
neh.ApplicationFlags = content.ReadByte(ref offset);
|
||||
neh.Autodata = content.ReadUInt16(ref offset);
|
||||
neh.InitialHeapAlloc = content.ReadUInt16(ref offset);
|
||||
neh.InitialStackAlloc = content.ReadUInt16(ref offset);
|
||||
neh.InitialCSIPSetting = content.ReadUInt32(ref offset);
|
||||
neh.InitialSSSPSetting = content.ReadUInt32(ref offset);
|
||||
neh.FileSegmentCount = content.ReadUInt16(ref offset);
|
||||
neh.ModuleReferenceTableSize = content.ReadUInt16(ref offset);
|
||||
neh.NonResidentNameTableSize = content.ReadUInt16(ref offset);
|
||||
neh.SegmentTableOffset = content.ReadUInt16(ref offset);
|
||||
neh.ResourceTableOffset = content.ReadUInt16(ref offset);
|
||||
neh.ResidentNameTableOffset = content.ReadUInt16(ref offset);
|
||||
neh.ModuleReferenceTableOffset = content.ReadUInt16(ref offset);
|
||||
neh.ImportedNamesTableOffset = content.ReadUInt16(ref offset);
|
||||
neh.NonResidentNamesTableOffset = content.ReadUInt32(ref offset);
|
||||
neh.MovableEntriesCount = content.ReadUInt16(ref offset);
|
||||
neh.SegmentAlignmentShiftCount = content.ReadUInt16(ref offset);
|
||||
neh.ResourceEntriesCount = content.ReadUInt16(ref offset);
|
||||
neh.TargetOperatingSystem = content.ReadByte(ref offset);
|
||||
neh.AdditionalFlags = content.ReadByte(ref offset);
|
||||
neh.ReturnThunkOffset = content.ReadUInt16(ref offset);
|
||||
neh.SegmentReferenceThunkOffset = content.ReadUInt16(ref offset);
|
||||
neh.MinCodeSwapAreaSize = content.ReadUInt16(ref offset);
|
||||
neh.WindowsSDKRevision = content.ReadByte(ref offset);
|
||||
neh.WindowsSDKVersion = content.ReadByte(ref offset);
|
||||
|
||||
return neh;
|
||||
}
|
||||
}
|
||||
}
|
||||
233
BurnOutSharp/ExecutableType/Microsoft/NE/NewExecutable.cs
Normal file
233
BurnOutSharp/ExecutableType/Microsoft/NE/NewExecutable.cs
Normal file
@@ -0,0 +1,233 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.MZ.Headers;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.NE.Headers;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.NE
|
||||
{
|
||||
/// <summary>
|
||||
/// The WIN-NE executable format, designed for Windows 3.x, was the "NE", or "New Executable" format.
|
||||
/// Again, a 16bit format, it alleviated the maximum size restrictions that the MZ format had.
|
||||
/// </summary>
|
||||
public class NewExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Value determining if the executable is initialized or not
|
||||
/// </summary>
|
||||
public bool Initialized { get; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Source array that the executable was parsed from
|
||||
/// </summary>
|
||||
private readonly byte[] _sourceArray = null;
|
||||
|
||||
/// <summary>
|
||||
/// Source stream that the executable was parsed from
|
||||
/// </summary>
|
||||
private readonly Stream _sourceStream = null;
|
||||
|
||||
#region Headers
|
||||
|
||||
/// <summary>
|
||||
/// he DOS stub is a valid MZ exe.
|
||||
/// This enables the develper to package both an MS-DOS and Win16 version of the program,
|
||||
/// but normally just prints "This Program requires Microsoft Windows".
|
||||
/// The e_lfanew field (offset 0x3C) points to the NE header.
|
||||
// </summary>
|
||||
public MSDOSExecutableHeader DOSStubHeader;
|
||||
|
||||
/// <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>
|
||||
public NewExecutableHeader NewExecutableHeader;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Tables
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
// TODO: Add more and more parts of a standard NE executable, not just the header
|
||||
// TODO: Tables? What about the tables?
|
||||
// TODO: Implement the rest of the structures found at http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm
|
||||
// (Left off at RESIDENT-NAME TABLE)
|
||||
|
||||
/// <summary>
|
||||
/// Create a NewExecutable object from a stream
|
||||
/// </summary>
|
||||
/// <param name="stream">Stream representing a file</param>
|
||||
/// <remarks>
|
||||
/// This constructor assumes that the stream is already in the correct position to start parsing
|
||||
/// </remarks>
|
||||
public NewExecutable(Stream stream)
|
||||
{
|
||||
if (stream == null || !stream.CanRead || !stream.CanSeek)
|
||||
return;
|
||||
|
||||
this.Initialized = Deserialize(stream);
|
||||
this._sourceStream = stream;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a NewExecutable object from a byte array
|
||||
/// </summary>
|
||||
/// <param name="fileContent">Byte array representing a file</param>
|
||||
/// <param name="offset">Positive offset representing the current position in the array</param>
|
||||
public NewExecutable(byte[] fileContent, int offset)
|
||||
{
|
||||
if (fileContent == null || fileContent.Length == 0 || offset < 0)
|
||||
return;
|
||||
|
||||
this.Initialized = Deserialize(fileContent, offset);
|
||||
this._sourceArray = fileContent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserialize a NewExecutable object from a stream
|
||||
/// </summary>
|
||||
/// <param name="stream">Stream representing a file</param>
|
||||
private bool Deserialize(Stream stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Attempt to read the DOS header first
|
||||
this.DOSStubHeader = MSDOSExecutableHeader.Deserialize(stream);
|
||||
stream.Seek(this.DOSStubHeader.NewExeHeaderAddr, SeekOrigin.Begin);
|
||||
if (this.DOSStubHeader.Magic != Constants.IMAGE_DOS_SIGNATURE)
|
||||
return false;
|
||||
|
||||
// If the new header address is invalid for the file, it's not a NE
|
||||
if (this.DOSStubHeader.NewExeHeaderAddr >= stream.Length)
|
||||
return false;
|
||||
|
||||
// Then attempt to read the NE header
|
||||
this.NewExecutableHeader = NewExecutableHeader.Deserialize(stream);
|
||||
if (this.NewExecutableHeader.Magic != Constants.IMAGE_OS2_SIGNATURE)
|
||||
return false;
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Console.WriteLine($"Errored out on a file: {ex}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserialize a NewExecutable object from a byte array
|
||||
/// </summary>
|
||||
/// <param name="fileContent">Byte array representing a file</param>
|
||||
/// <param name="offset">Positive offset representing the current position in the array</param>
|
||||
private bool Deserialize(byte[] content, int offset)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Attempt to read the DOS header first
|
||||
this.DOSStubHeader = MSDOSExecutableHeader.Deserialize(content, ref offset);
|
||||
offset = this.DOSStubHeader.NewExeHeaderAddr;
|
||||
if (this.DOSStubHeader.Magic != Constants.IMAGE_DOS_SIGNATURE)
|
||||
return false;
|
||||
|
||||
// If the new header address is invalid for the file, it's not a PE
|
||||
if (this.DOSStubHeader.NewExeHeaderAddr >= content.Length)
|
||||
return false;
|
||||
|
||||
// Then attempt to read the NE header
|
||||
this.NewExecutableHeader = NewExecutableHeader.Deserialize(content, ref offset);
|
||||
if (this.NewExecutableHeader.Magic != Constants.IMAGE_OS2_SIGNATURE)
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Console.WriteLine($"Errored out on a file: {ex}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Read an arbitrary range from the source
|
||||
/// </summary>
|
||||
/// <param name="rangeStart">The start of where to read data from, -1 means start of source</param>
|
||||
/// <param name="length">How many bytes to read, -1 means read until end</param>
|
||||
/// <returns></returns>
|
||||
public byte[] ReadArbitraryRange(int rangeStart = -1, int length = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
// If we have a source stream, use that
|
||||
if (this._sourceStream != null)
|
||||
return ReadArbitraryRangeFromSourceStream(rangeStart, length);
|
||||
|
||||
// If we have a source array, use that
|
||||
if (this._sourceArray != null)
|
||||
return ReadArbitraryRangeFromSourceArray(rangeStart, length);
|
||||
|
||||
// Otherwise, return null
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// TODO: How to handle this differently?
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read an arbitrary range from the stream source, if possible
|
||||
/// </summary>
|
||||
/// <param name="rangeStart">The start of where to read data from, -1 means start of source</param>
|
||||
/// <param name="length">How many bytes to read, -1 means read until end</param>
|
||||
/// <returns></returns>
|
||||
private byte[] ReadArbitraryRangeFromSourceStream(int rangeStart, int length)
|
||||
{
|
||||
lock (this._sourceStream)
|
||||
{
|
||||
int startingIndex = (int)Math.Max(rangeStart, 0);
|
||||
int readLength = (int)Math.Min(length == -1 ? length = Int32.MaxValue : length, this._sourceStream.Length);
|
||||
|
||||
long originalPosition = this._sourceStream.Position;
|
||||
this._sourceStream.Seek(startingIndex, SeekOrigin.Begin);
|
||||
byte[] sectionData = this._sourceStream.ReadBytes(readLength);
|
||||
this._sourceStream.Seek(originalPosition, SeekOrigin.Begin);
|
||||
return sectionData;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read an arbitrary range from the array source, if possible
|
||||
/// </summary>
|
||||
/// <param name="rangeStart">The start of where to read data from, -1 means start of source</param>
|
||||
/// <param name="length">How many bytes to read, -1 means read until end</param>
|
||||
/// <returns></returns>
|
||||
private byte[] ReadArbitraryRangeFromSourceArray(int rangeStart, int length)
|
||||
{
|
||||
int startingIndex = (int)Math.Max(rangeStart, 0);
|
||||
int readLength = (int)Math.Min(length == -1 ? length = Int32.MaxValue : length, this._sourceArray.Length);
|
||||
|
||||
try
|
||||
{
|
||||
return this._sourceArray.ReadBytes(ref startingIndex, readLength);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Just absorb errors for now
|
||||
// TODO: Investigate why and when this would be hit
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.NE.Entries;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.NE.Tables
|
||||
{
|
||||
/// <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.
|
||||
/// </summary>
|
||||
public class ResidentNameTable
|
||||
{
|
||||
/// <summary>
|
||||
/// The first string in this table is this module's name.
|
||||
/// These name strings are case-sensitive and are not null-terminated.
|
||||
/// </summary>
|
||||
public ResidentNameTableEntry[] NameTableEntries;
|
||||
|
||||
public static ResidentNameTable Deserialize(Stream stream)
|
||||
{
|
||||
var rnt = new ResidentNameTable();
|
||||
|
||||
var nameTableEntries = new List<ResidentNameTableEntry>();
|
||||
while (true)
|
||||
{
|
||||
var rnte = ResidentNameTableEntry.Deserialize(stream);
|
||||
if (rnte == null || rnte.Length == 0)
|
||||
break;
|
||||
|
||||
nameTableEntries.Add(rnte);
|
||||
}
|
||||
|
||||
rnt.NameTableEntries = nameTableEntries.ToArray();
|
||||
|
||||
return rnt;
|
||||
}
|
||||
|
||||
public static ResidentNameTable Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var rnt = new ResidentNameTable();
|
||||
|
||||
var nameTableEntries = new List<ResidentNameTableEntry>();
|
||||
while (true)
|
||||
{
|
||||
var rnte = ResidentNameTableEntry.Deserialize(content, ref offset);
|
||||
if (rnte == null || rnte.Length == 0)
|
||||
break;
|
||||
|
||||
nameTableEntries.Add(rnte);
|
||||
}
|
||||
|
||||
rnt.NameTableEntries = nameTableEntries.ToArray();
|
||||
|
||||
return rnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
101
BurnOutSharp/ExecutableType/Microsoft/NE/Tables/ResourceTable.cs
Normal file
101
BurnOutSharp/ExecutableType/Microsoft/NE/Tables/ResourceTable.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.NE.Entries;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.NE.Tables
|
||||
{
|
||||
/// <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.
|
||||
/// </summary>
|
||||
/// <remarks>http://bytepointer.com/resources/win16_ne_exe_format_win3.0.htm</remarks>
|
||||
public class ResourceTable
|
||||
{
|
||||
/// <summary>
|
||||
/// Alignment shift count for resource data.
|
||||
/// </summary>
|
||||
public ushort AlignmentShiftCount;
|
||||
|
||||
/// <summary>
|
||||
/// A table of resource type information blocks.
|
||||
/// </summary>
|
||||
public ResourceTypeInformationBlock[] TypeInformationBlocks;
|
||||
|
||||
/// <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>
|
||||
public ResourceNameString[] TypeAndNameStrings;
|
||||
|
||||
public static ResourceTable Deserialize(Stream stream)
|
||||
{
|
||||
var rt = new ResourceTable();
|
||||
|
||||
rt.AlignmentShiftCount = stream.ReadUInt16();
|
||||
var typeInformationBlocks = new List<ResourceTypeInformationBlock>();
|
||||
while (true)
|
||||
{
|
||||
var block = ResourceTypeInformationBlock.Deserialize(stream);
|
||||
if (block.TypeID == 0)
|
||||
break;
|
||||
|
||||
typeInformationBlocks.Add(block);
|
||||
}
|
||||
|
||||
rt.TypeInformationBlocks = typeInformationBlocks.ToArray();
|
||||
|
||||
var typeAndNameStrings = new List<ResourceNameString>();
|
||||
while (true)
|
||||
{
|
||||
var str = ResourceNameString.Deserialize(stream);
|
||||
if (str.Length == 0)
|
||||
break;
|
||||
|
||||
typeAndNameStrings.Add(str);
|
||||
}
|
||||
|
||||
rt.TypeAndNameStrings = typeAndNameStrings.ToArray();
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static ResourceTable Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var rt = new ResourceTable();
|
||||
|
||||
rt.AlignmentShiftCount = content.ReadUInt16(ref offset);
|
||||
var typeInformationBlocks = new List<ResourceTypeInformationBlock>();
|
||||
while (true)
|
||||
{
|
||||
var block = ResourceTypeInformationBlock.Deserialize(content, ref offset);
|
||||
if (block.TypeID == 0)
|
||||
break;
|
||||
|
||||
typeInformationBlocks.Add(block);
|
||||
}
|
||||
|
||||
rt.TypeInformationBlocks = typeInformationBlocks.ToArray();
|
||||
|
||||
var typeAndNameStrings = new List<ResourceNameString>();
|
||||
while (true)
|
||||
{
|
||||
var str = ResourceNameString.Deserialize(content, ref offset);
|
||||
if (str.Length == 0)
|
||||
break;
|
||||
|
||||
typeAndNameStrings.Add(str);
|
||||
}
|
||||
|
||||
rt.TypeAndNameStrings = typeAndNameStrings.ToArray();
|
||||
|
||||
return rt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
/// <summary>
|
||||
/// Relocation item
|
||||
/// </summary>
|
||||
/// TODO: Fix this because Marshal will not work since it's not a direct read
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class NewRlc
|
||||
{
|
||||
public char SourceType; // Source type
|
||||
public char Flags; // Flag byte
|
||||
public ushort SourceOffset; // Source offset
|
||||
|
||||
// nr_intref - Internal Reference
|
||||
public char TargetSegmentNumber; // Target segment number
|
||||
public char Reserved1; // Reserved
|
||||
public ushort TargetEntryTableOffset; // Target Entry Table offset
|
||||
|
||||
// nr_import - Import
|
||||
public ushort ModuleReferenceTableIndex; // Index into Module Reference Table
|
||||
public ushort ProcedureOffset; // Procedure ordinal or name offset
|
||||
|
||||
// nr_osfix - Operating system fixup
|
||||
public ushort OperatingSystemFixupType; // OSFIXUP type
|
||||
public ushort Reserved2; // Reserved
|
||||
|
||||
public static NewRlc Deserialize(Stream stream)
|
||||
{
|
||||
var nr = new NewRlc();
|
||||
|
||||
nr.SourceType = stream.ReadChar();
|
||||
nr.Flags = stream.ReadChar();
|
||||
nr.SourceOffset = stream.ReadUInt16();
|
||||
|
||||
// nr_intref
|
||||
nr.TargetSegmentNumber = stream.ReadChar();
|
||||
nr.Reserved1 = stream.ReadChar();
|
||||
nr.TargetEntryTableOffset = stream.ReadUInt16();
|
||||
|
||||
// nr_import
|
||||
nr.ModuleReferenceTableIndex = BitConverter.ToUInt16(new byte[] { (byte)nr.SourceType, (byte)nr.Flags }, 0);
|
||||
nr.ProcedureOffset = nr.TargetEntryTableOffset;
|
||||
|
||||
// nr_osfix
|
||||
nr.OperatingSystemFixupType = nr.ModuleReferenceTableIndex;
|
||||
nr.Reserved2 = nr.ProcedureOffset;
|
||||
|
||||
return nr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
/// <summary>
|
||||
/// Relocation info
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class NewRlcInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of relocation items that follow
|
||||
/// </summary>
|
||||
public ushort RelocationItemCount;
|
||||
|
||||
public static NewRlcInfo Deserialize(Stream stream)
|
||||
{
|
||||
var nri = new NewRlcInfo();
|
||||
|
||||
nri.RelocationItemCount = stream.ReadUInt16();
|
||||
|
||||
return nri;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
/// <summary>
|
||||
/// Resource table
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class NewRsrc
|
||||
{
|
||||
/// <summary>
|
||||
/// Alignment shift count for resources
|
||||
/// </summary>
|
||||
public ushort AlignmentShiftCount;
|
||||
public RsrcTypeInfo TypeInfo;
|
||||
|
||||
public static NewRsrc Deserialize(Stream stream)
|
||||
{
|
||||
var nr = new NewRsrc();
|
||||
|
||||
nr.AlignmentShiftCount = stream.ReadUInt16();
|
||||
nr.TypeInfo = RsrcTypeInfo.Deserialize(stream);
|
||||
|
||||
return nr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
/// <summary>
|
||||
/// New .EXE segment table entry
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class NewSeg
|
||||
{
|
||||
/// <summary>
|
||||
/// File sector of start of segment
|
||||
/// </summary>
|
||||
public ushort StartFileSector;
|
||||
|
||||
/// <summary>
|
||||
/// Number of bytes in file
|
||||
/// </summary>
|
||||
public ushort BytesInFile;
|
||||
|
||||
/// <summary>
|
||||
/// Attribute flags
|
||||
/// </summary>
|
||||
public ushort Flags;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum allocation in bytes
|
||||
/// </summary>
|
||||
public ushort MinimumAllocation;
|
||||
|
||||
public static NewSeg Deserialize(Stream stream)
|
||||
{
|
||||
var ns = new NewSeg();
|
||||
|
||||
ns.StartFileSector = stream.ReadUInt16();
|
||||
ns.BytesInFile = stream.ReadUInt16();
|
||||
ns.Flags = stream.ReadUInt16();
|
||||
ns.MinimumAllocation = stream.ReadUInt16();
|
||||
|
||||
return ns;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
/// <summary>
|
||||
/// Segment data
|
||||
/// </summary>
|
||||
/// TODO: Fix this because Marshal will not work since it's not a direct read
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class NewSegdata
|
||||
{
|
||||
#region ns_iter
|
||||
|
||||
/// <summary>
|
||||
/// Number of iterations
|
||||
/// </summary>
|
||||
public ushort Iterations;
|
||||
|
||||
/// <summary>
|
||||
/// Number of bytes
|
||||
/// </summary>
|
||||
public ushort TotalBytes;
|
||||
|
||||
/// <summary>
|
||||
/// Iterated data bytes
|
||||
/// </summary>
|
||||
public char IteratedDataBytes;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ns_noiter
|
||||
|
||||
/// <summary>
|
||||
/// Data bytes
|
||||
/// </summary>
|
||||
public char DataBytes;
|
||||
|
||||
#endregion
|
||||
|
||||
public static NewSegdata Deserialize(Stream stream)
|
||||
{
|
||||
var nsd = new NewSegdata();
|
||||
|
||||
nsd.Iterations = stream.ReadUInt16();
|
||||
nsd.TotalBytes = stream.ReadUInt16();
|
||||
nsd.IteratedDataBytes = stream.ReadChar();
|
||||
nsd.DataBytes = (char)BitConverter.GetBytes(nsd.Iterations)[0];
|
||||
|
||||
return nsd;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#base-relocation-block</remarks>
|
||||
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;
|
||||
|
||||
public static BaseRelocationBlock Deserialize(Stream stream)
|
||||
{
|
||||
var brb = new BaseRelocationBlock();
|
||||
|
||||
brb.PageRVA = stream.ReadUInt32();
|
||||
brb.BlockSize = stream.ReadUInt32();
|
||||
|
||||
// TODO: Read in the type/offset field entries
|
||||
|
||||
return brb;
|
||||
}
|
||||
|
||||
public static BaseRelocationBlock Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var brb = new BaseRelocationBlock();
|
||||
|
||||
brb.PageRVA = content.ReadUInt32(ref offset);
|
||||
brb.BlockSize = content.ReadUInt32(ref offset);
|
||||
|
||||
// TODO: Read in the type/offset field entries
|
||||
|
||||
return brb;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Tools;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Headers;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// 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>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#export-address-table</remarks>
|
||||
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>
|
||||
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.
|
||||
/// 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>
|
||||
public uint ForwarderRVA; // TODO: Read this into a separate field
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// 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>
|
||||
public string Forwarder;
|
||||
|
||||
public static ExportAddressTableEntry Deserialize(Stream stream, SectionHeader[] sections)
|
||||
{
|
||||
var eate = new ExportAddressTableEntry();
|
||||
|
||||
eate.ExportRVA = stream.ReadUInt32();
|
||||
eate.ForwarderRVA = eate.ExportRVA;
|
||||
|
||||
int forwarderAddress = (int)PortableExecutable.ConvertVirtualAddress(eate.ForwarderRVA, sections);
|
||||
if (forwarderAddress > -1 && forwarderAddress < stream.Length)
|
||||
{
|
||||
long originalPosition = stream.Position;
|
||||
stream.Seek(forwarderAddress, SeekOrigin.Begin);
|
||||
eate.Forwarder = stream.ReadString(Encoding.ASCII);
|
||||
stream.Seek(originalPosition, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
return eate;
|
||||
}
|
||||
|
||||
public static ExportAddressTableEntry Deserialize(byte[] content, ref int offset, SectionHeader[] sections)
|
||||
{
|
||||
var eate = new ExportAddressTableEntry();
|
||||
|
||||
eate.ExportRVA = content.ReadUInt32(ref offset);
|
||||
eate.ForwarderRVA = eate.ExportRVA;
|
||||
|
||||
int forwarderAddress = (int)PortableExecutable.ConvertVirtualAddress(eate.ForwarderRVA, sections);
|
||||
if (forwarderAddress > -1 && forwarderAddress < content.Length)
|
||||
eate.Forwarder = content.ReadString(ref forwarderAddress, Encoding.ASCII);
|
||||
|
||||
return eate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// 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>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-pdata-section</remarks>
|
||||
public class FunctionTableEntry
|
||||
{
|
||||
#region 32-bit MIPS
|
||||
|
||||
/// <summary>
|
||||
/// The VA of the corresponding function.
|
||||
/// </summary>
|
||||
public uint MIPSBeginAddress;
|
||||
|
||||
/// <summary>
|
||||
/// The VA of the end of the function.
|
||||
/// </summary>
|
||||
public uint MIPSEndAddress;
|
||||
|
||||
/// <summary>
|
||||
/// The pointer to the exception handler to be executed.
|
||||
/// </summary>
|
||||
public uint MIPSExceptionHandler;
|
||||
|
||||
/// <summary>
|
||||
/// The pointer to additional information to be passed to the handler.
|
||||
/// </summary>
|
||||
public uint MIPSHandlerData;
|
||||
|
||||
/// <summary>
|
||||
/// The VA of the end of the function's prolog.
|
||||
/// </summary>
|
||||
public uint MIPSPrologEndAddress;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ARM, PowerPC, SH3 and SH4 Windows CE
|
||||
|
||||
/// <summary>
|
||||
/// The VA of the corresponding function.
|
||||
/// </summary>
|
||||
public uint ARMBeginAddress;
|
||||
|
||||
/// <summary>
|
||||
/// The VA of the end of the function.
|
||||
///
|
||||
/// 8 bits Prolog Length The number of instructions in the function's prolog.
|
||||
/// 22 bits Function Length The number of instructions in the function.
|
||||
/// 1 bit 32-bit Flag If set, the function consists of 32-bit instructions. If clear, the function consists of 16-bit instructions.
|
||||
/// 1 bit Exception Flag If set, an exception handler exists for the function. Otherwise, no exception handler exists.
|
||||
/// </summary>
|
||||
public uint ARMLengthsAndFlags;
|
||||
|
||||
#endregion
|
||||
|
||||
#region x64 and Itanium
|
||||
|
||||
/// <summary>
|
||||
/// The RVA of the corresponding function.
|
||||
/// </summary>
|
||||
public uint X64BeginAddress;
|
||||
|
||||
/// <summary>
|
||||
/// The RVA of the end of the function.
|
||||
/// </summary>
|
||||
public uint X64EndAddress;
|
||||
|
||||
/// <summary>
|
||||
/// The RVA of the unwind information.
|
||||
/// </summary>
|
||||
public uint X64UnwindInformation;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Each entry in the hint/name table has the following format
|
||||
/// </summary>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#hintname-table</remarks>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// A trailing zero-pad byte that appears after the trailing null byte, if necessary, to align the next entry on an even boundary.
|
||||
/// </summary>
|
||||
public byte Pad;
|
||||
|
||||
public static HintNameTableEntry Deserialize(Stream stream)
|
||||
{
|
||||
var hnte = new HintNameTableEntry();
|
||||
|
||||
hnte.Hint = stream.ReadUInt16();
|
||||
hnte.Name = string.Empty;
|
||||
while (true)
|
||||
{
|
||||
char c = stream.ReadChar();
|
||||
if (c == (char)0x00)
|
||||
break;
|
||||
|
||||
hnte.Name += c;
|
||||
}
|
||||
|
||||
// If the name length is not even, read and pad
|
||||
if (hnte.Name.Length % 2 != 0)
|
||||
{
|
||||
stream.ReadByte();
|
||||
hnte.Pad = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
hnte.Pad = 0;
|
||||
}
|
||||
|
||||
return hnte;
|
||||
}
|
||||
|
||||
public static HintNameTableEntry Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var hnte = new HintNameTableEntry();
|
||||
|
||||
hnte.Hint = content.ReadUInt16(ref offset);
|
||||
hnte.Name = string.Empty;
|
||||
while (true)
|
||||
{
|
||||
char c = (char)content[offset]; offset += 1;
|
||||
if (c == (char)0x00)
|
||||
break;
|
||||
|
||||
hnte.Name += c;
|
||||
}
|
||||
|
||||
// If the name length is not even, read and pad
|
||||
if (hnte.Name.Length % 2 != 0)
|
||||
{
|
||||
offset += 1;
|
||||
hnte.Pad = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
hnte.Pad = 0;
|
||||
}
|
||||
|
||||
return hnte;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Each import address entry has the following format
|
||||
/// </summary>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-address-table</remarks>
|
||||
public class ImportAddressTableEntry
|
||||
{
|
||||
/// <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>
|
||||
/// 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;
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the entry is null or not
|
||||
/// This indicates the last entry in a table
|
||||
/// </summary>
|
||||
public bool IsNull()
|
||||
{
|
||||
return ImportLookupTableRVA == 0
|
||||
&& TimeDateStamp == 0
|
||||
&& ForwarderChain == 0
|
||||
&& NameRVA == 0
|
||||
&& ImportAddressTableRVA == 0;
|
||||
}
|
||||
|
||||
public static ImportAddressTableEntry Deserialize(Stream stream)
|
||||
{
|
||||
var iate = new ImportAddressTableEntry();
|
||||
|
||||
iate.ImportLookupTableRVA = stream.ReadUInt32();
|
||||
iate.TimeDateStamp = stream.ReadUInt32();
|
||||
iate.ForwarderChain = stream.ReadUInt32();
|
||||
iate.NameRVA = stream.ReadUInt32();
|
||||
iate.ImportAddressTableRVA = stream.ReadUInt32();
|
||||
|
||||
return iate;
|
||||
}
|
||||
|
||||
public static ImportAddressTableEntry Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var iate = new ImportAddressTableEntry();
|
||||
|
||||
iate.ImportLookupTableRVA = content.ReadUInt32(ref offset);
|
||||
iate.TimeDateStamp = content.ReadUInt32(ref offset);
|
||||
iate.ForwarderChain = content.ReadUInt32(ref offset);
|
||||
iate.NameRVA = content.ReadUInt32(ref offset);
|
||||
iate.ImportAddressTableRVA = content.ReadUInt32(ref offset);
|
||||
|
||||
return iate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Each import directory entry has the following format
|
||||
/// </summary>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-directory-table</remarks>
|
||||
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>
|
||||
/// 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;
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the entry is null or not
|
||||
/// This indicates the last entry in a table
|
||||
/// </summary>
|
||||
public bool IsNull()
|
||||
{
|
||||
return ImportLookupTableRVA == 0
|
||||
&& TimeDateStamp == 0
|
||||
&& ForwarderChain == 0
|
||||
&& NameRVA == 0
|
||||
&& ImportAddressTableRVA == 0;
|
||||
}
|
||||
|
||||
public static ImportDirectoryTableEntry Deserialize(Stream stream)
|
||||
{
|
||||
var idte = new ImportDirectoryTableEntry();
|
||||
|
||||
idte.ImportLookupTableRVA = stream.ReadUInt32();
|
||||
idte.TimeDateStamp = stream.ReadUInt32();
|
||||
idte.ForwarderChain = stream.ReadUInt32();
|
||||
idte.NameRVA = stream.ReadUInt32();
|
||||
idte.ImportAddressTableRVA = stream.ReadUInt32();
|
||||
|
||||
return idte;
|
||||
}
|
||||
|
||||
public static ImportDirectoryTableEntry Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var idte = new ImportDirectoryTableEntry();
|
||||
|
||||
idte.ImportLookupTableRVA = content.ReadUInt32(ref offset);
|
||||
idte.TimeDateStamp = content.ReadUInt32(ref offset);
|
||||
idte.ForwarderChain = content.ReadUInt32(ref offset);
|
||||
idte.NameRVA = content.ReadUInt32(ref offset);
|
||||
idte.ImportAddressTableRVA = content.ReadUInt32(ref offset);
|
||||
|
||||
return idte;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Headers;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Each Resource Data entry describes an actual unit of raw data in the Resource Data area.
|
||||
/// </summary>
|
||||
public class ResourceDataEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// The address of a unit of resource data in the Resource Data area.
|
||||
/// </summary>
|
||||
public uint OffsetToData;
|
||||
|
||||
/// <summary>
|
||||
/// A unit of resource data in the Resource Data area.
|
||||
/// </summary>
|
||||
public byte[] Data;
|
||||
|
||||
/// <summary>
|
||||
/// A unit of resource data in the Resource Data area.
|
||||
/// </summary>
|
||||
public string DataAsUTF8String
|
||||
{
|
||||
get
|
||||
{
|
||||
int codePage = (int)CodePage;
|
||||
if (Data == null || codePage < 0)
|
||||
return string.Empty;
|
||||
|
||||
// Try to convert to UTF-8 first
|
||||
try
|
||||
{
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
var originalEncoding = Encoding.GetEncoding(codePage);
|
||||
byte[] convertedData = Encoding.Convert(originalEncoding, Encoding.UTF8, Data);
|
||||
return Encoding.UTF8.GetString(convertedData);
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Then try to read direct as ASCII
|
||||
try
|
||||
{
|
||||
return Encoding.ASCII.GetString(Data);
|
||||
}
|
||||
catch { }
|
||||
|
||||
// If both encodings fail, then just return an empty string
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The size, in bytes, of the resource data that is pointed to by the Data RVA field.
|
||||
/// </summary>
|
||||
public uint Size;
|
||||
|
||||
/// <summary>
|
||||
/// The code page that is used to decode code point values within the resource data.
|
||||
/// Typically, the code page would be the Unicode code page.
|
||||
/// </summary>
|
||||
public uint CodePage;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved, must be 0.
|
||||
/// </summary>
|
||||
public uint Reserved;
|
||||
|
||||
public static ResourceDataEntry Deserialize(Stream stream, SectionHeader[] sections)
|
||||
{
|
||||
var rde = new ResourceDataEntry();
|
||||
|
||||
rde.OffsetToData = stream.ReadUInt32();
|
||||
rde.Size = stream.ReadUInt32();
|
||||
rde.CodePage = stream.ReadUInt32();
|
||||
rde.Reserved = stream.ReadUInt32();
|
||||
|
||||
int realOffsetToData = (int)PortableExecutable.ConvertVirtualAddress(rde.OffsetToData, sections);
|
||||
if (realOffsetToData > -1 && realOffsetToData < stream.Length && (int)rde.Size > 0 && realOffsetToData + (int)rde.Size < stream.Length)
|
||||
{
|
||||
long lastPosition = stream.Position;
|
||||
stream.Seek(realOffsetToData, SeekOrigin.Begin);
|
||||
rde.Data = stream.ReadBytes((int)rde.Size);
|
||||
stream.Seek(lastPosition, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
return rde;
|
||||
}
|
||||
|
||||
public static ResourceDataEntry Deserialize(byte[] content, ref int offset, SectionHeader[] sections)
|
||||
{
|
||||
var rde = new ResourceDataEntry();
|
||||
|
||||
rde.OffsetToData = content.ReadUInt32(ref offset);
|
||||
rde.Size = content.ReadUInt32(ref offset);
|
||||
rde.CodePage = content.ReadUInt32(ref offset);
|
||||
rde.Reserved = content.ReadUInt32(ref offset);
|
||||
|
||||
int realOffsetToData = (int)PortableExecutable.ConvertVirtualAddress(rde.OffsetToData, sections);
|
||||
if (realOffsetToData > -1 && realOffsetToData < content.Length && (int)rde.Size > 0 && realOffsetToData + (int)rde.Size < content.Length)
|
||||
rde.Data = new ArraySegment<byte>(content, realOffsetToData, (int)rde.Size).ToArray();
|
||||
|
||||
return rde;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// The resource directory string area consists of Unicode strings, which are word-aligned.
|
||||
/// These strings are stored together after the last Resource Directory entry and before the first Resource Data entry.
|
||||
/// This minimizes the impact of these variable-length strings on the alignment of the fixed-size directory entries.
|
||||
/// </summary>
|
||||
public class ResourceDirectoryString
|
||||
{
|
||||
/// <summary>
|
||||
/// The size of the string, not including length field itself.
|
||||
/// </summary>
|
||||
public ushort Length;
|
||||
|
||||
/// <summary>
|
||||
/// The variable-length Unicode string data, word-aligned.
|
||||
/// </summary>
|
||||
public string UnicodeString;
|
||||
|
||||
public static ResourceDirectoryString Deserialize(Stream stream)
|
||||
{
|
||||
var rds = new ResourceDirectoryString();
|
||||
|
||||
rds.Length = stream.ReadUInt16();
|
||||
if (rds.Length + stream.Position > stream.Length)
|
||||
return null;
|
||||
|
||||
rds.UnicodeString = new string(stream.ReadChars(rds.Length, Encoding.Unicode));
|
||||
|
||||
return rds;
|
||||
}
|
||||
|
||||
public static ResourceDirectoryString Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var rds = new ResourceDirectoryString();
|
||||
|
||||
rds.Length = content.ReadUInt16(ref offset);
|
||||
if (rds.Length + offset > content.Length)
|
||||
return null;
|
||||
|
||||
rds.UnicodeString = Encoding.Unicode.GetString(content, offset, rds.Length); offset += rds.Length;
|
||||
|
||||
return rds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Headers;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Tables;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// The directory entries make up the rows of a table.
|
||||
/// Each resource directory entry has the following format.
|
||||
/// Whether the entry is a Name or ID entry is indicated by the
|
||||
/// resource directory table, which indicates how many Name and
|
||||
/// ID entries follow it (remember that all the Name entries
|
||||
/// precede all the ID entries for the table). All entries for
|
||||
/// the table are sorted in ascending order: the Name entries
|
||||
/// by case-sensitive string and the ID entries by numeric value.
|
||||
/// Offsets are relative to the address in the IMAGE_DIRECTORY_ENTRY_RESOURCE DataDirectory.
|
||||
/// </summary>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#resource-directory-entries</remarks>
|
||||
public class ResourceDirectoryTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// The offset of a string that gives the Type, Name, or Language ID entry, depending on level of table.
|
||||
/// </summary>
|
||||
public uint NameOffset => (uint)(IntegerId ^ (1 << 31));
|
||||
|
||||
/// <summary>
|
||||
/// The string that gives the Type, Name, or Language ID entry, depending on level of table pointed to by NameOffset
|
||||
/// </summary>
|
||||
public ResourceDirectoryString Name;
|
||||
|
||||
/// <summary>
|
||||
/// A 32-bit integer that identifies the Type, Name, or Language ID entry.
|
||||
/// </summary>
|
||||
public uint IntegerId;
|
||||
|
||||
/// <summary>
|
||||
/// High bit 0. Address of a Resource Data entry (a leaf).
|
||||
/// </summary>
|
||||
public uint DataEntryOffset;
|
||||
|
||||
/// <summary>
|
||||
/// High bit 1. The lower 31 bits are the address of another resource directory table (the next level down).
|
||||
/// </summary>
|
||||
public uint SubdirectoryOffset => (uint)(DataEntryOffset ^ (1 << 31));
|
||||
|
||||
/// <summary>
|
||||
/// Resource Data entry (a leaf).
|
||||
/// </summary>
|
||||
public ResourceDataEntry DataEntry;
|
||||
|
||||
/// <summary>
|
||||
/// Another resource directory table (the next level down).
|
||||
/// </summary>
|
||||
public ResourceDirectoryTable Subdirectory;
|
||||
|
||||
/// <summary>
|
||||
/// Determine if an entry has a name or integer identifier
|
||||
/// </summary>
|
||||
public bool IsIntegerIDEntry() => (IntegerId & (1 << 31)) == 0;
|
||||
|
||||
/// <summary>
|
||||
/// Determine if an entry represents a leaf or another directory table
|
||||
/// </summary>
|
||||
public bool IsResourceDataEntry() => (DataEntryOffset & (1 << 31)) == 0;
|
||||
|
||||
public static ResourceDirectoryTableEntry Deserialize(Stream stream, long sectionStart, SectionHeader[] sections)
|
||||
{
|
||||
var rdte = new ResourceDirectoryTableEntry();
|
||||
|
||||
rdte.IntegerId = stream.ReadUInt32();
|
||||
if (!rdte.IsIntegerIDEntry())
|
||||
{
|
||||
int nameAddress = (int)(rdte.NameOffset + sectionStart);
|
||||
if (nameAddress >= 0 && nameAddress < stream.Length)
|
||||
{
|
||||
long lastPosition = stream.Position;
|
||||
stream.Seek(nameAddress, SeekOrigin.Begin);
|
||||
rdte.Name = ResourceDirectoryString.Deserialize(stream);
|
||||
stream.Seek(lastPosition, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
rdte.DataEntryOffset = stream.ReadUInt32();
|
||||
if (rdte.IsResourceDataEntry())
|
||||
{
|
||||
int dataEntryAddress = (int)(rdte.DataEntryOffset + sectionStart);
|
||||
if (dataEntryAddress > 0 && dataEntryAddress < stream.Length)
|
||||
{
|
||||
long lastPosition = stream.Position;
|
||||
stream.Seek(dataEntryAddress, SeekOrigin.Begin);
|
||||
rdte.DataEntry = ResourceDataEntry.Deserialize(stream, sections);
|
||||
stream.Seek(lastPosition, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int subdirectoryAddress = (int)(rdte.SubdirectoryOffset + sectionStart);
|
||||
if (subdirectoryAddress > 0 && subdirectoryAddress < stream.Length)
|
||||
{
|
||||
long lastPosition = stream.Position;
|
||||
stream.Seek(subdirectoryAddress, SeekOrigin.Begin);
|
||||
rdte.Subdirectory = ResourceDirectoryTable.Deserialize(stream, sectionStart, sections);
|
||||
stream.Seek(lastPosition, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
return rdte;
|
||||
}
|
||||
|
||||
public static ResourceDirectoryTableEntry Deserialize(byte[] content, ref int offset, long sectionStart, SectionHeader[] sections)
|
||||
{
|
||||
var rdte = new ResourceDirectoryTableEntry();
|
||||
|
||||
rdte.IntegerId = content.ReadUInt32(ref offset);
|
||||
if (!rdte.IsIntegerIDEntry())
|
||||
{
|
||||
int nameAddress = (int)(rdte.NameOffset + sectionStart);
|
||||
if (nameAddress >= 0 && nameAddress < content.Length)
|
||||
rdte.Name = ResourceDirectoryString.Deserialize(content, ref nameAddress);
|
||||
}
|
||||
|
||||
rdte.DataEntryOffset = content.ReadUInt32(ref offset);
|
||||
if (rdte.IsResourceDataEntry())
|
||||
{
|
||||
int dataEntryAddress = (int)(rdte.DataEntryOffset + sectionStart);
|
||||
if (dataEntryAddress > 0 && dataEntryAddress < content.Length)
|
||||
rdte.DataEntry = ResourceDataEntry.Deserialize(content, ref dataEntryAddress, sections);
|
||||
}
|
||||
else
|
||||
{
|
||||
int subdirectoryAddress = (int)(rdte.SubdirectoryOffset + sectionStart);
|
||||
if (subdirectoryAddress > 0 && subdirectoryAddress < content.Length)
|
||||
rdte.Subdirectory = ResourceDirectoryTable.Deserialize(content, ref subdirectoryAddress, sectionStart, sections);
|
||||
}
|
||||
|
||||
return rdte;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Headers
|
||||
{
|
||||
public class CommonObjectFileFormatHeader
|
||||
{
|
||||
/// <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 uint Signature;
|
||||
|
||||
/// <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>
|
||||
[Obsolete]
|
||||
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>
|
||||
[Obsolete]
|
||||
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 ImageObjectCharacteristics Characteristics;
|
||||
|
||||
public static CommonObjectFileFormatHeader Deserialize(Stream stream)
|
||||
{
|
||||
var ifh = new CommonObjectFileFormatHeader();
|
||||
|
||||
ifh.Signature = stream.ReadUInt32();
|
||||
ifh.Machine = (MachineType)stream.ReadUInt16();
|
||||
ifh.NumberOfSections = stream.ReadUInt16();
|
||||
ifh.TimeDateStamp = stream.ReadUInt32();
|
||||
ifh.PointerToSymbolTable = stream.ReadUInt32();
|
||||
ifh.NumberOfSymbols = stream.ReadUInt32();
|
||||
ifh.SizeOfOptionalHeader = stream.ReadUInt16();
|
||||
ifh.Characteristics = (ImageObjectCharacteristics)stream.ReadUInt16();
|
||||
|
||||
return ifh;
|
||||
}
|
||||
|
||||
public static CommonObjectFileFormatHeader Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var ifh = new CommonObjectFileFormatHeader();
|
||||
|
||||
ifh.Signature = content.ReadUInt32(ref offset);
|
||||
ifh.Machine = (MachineType)content.ReadUInt16(ref offset);
|
||||
ifh.NumberOfSections = content.ReadUInt16(ref offset);
|
||||
ifh.TimeDateStamp = content.ReadUInt32(ref offset);
|
||||
ifh.PointerToSymbolTable = content.ReadUInt32(ref offset);
|
||||
ifh.NumberOfSymbols = content.ReadUInt32(ref offset);
|
||||
ifh.SizeOfOptionalHeader = content.ReadUInt16(ref offset);
|
||||
ifh.Characteristics = (ImageObjectCharacteristics)content.ReadUInt16(ref offset);
|
||||
|
||||
return ifh;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Headers
|
||||
{
|
||||
public class DataDirectoryHeader
|
||||
{
|
||||
/// <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;
|
||||
|
||||
public static DataDirectoryHeader Deserialize(Stream stream)
|
||||
{
|
||||
var ddh = new DataDirectoryHeader();
|
||||
|
||||
ddh.VirtualAddress = stream.ReadUInt32();
|
||||
ddh.Size = stream.ReadUInt32();
|
||||
|
||||
return ddh;
|
||||
}
|
||||
|
||||
public static DataDirectoryHeader Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var ddh = new DataDirectoryHeader();
|
||||
|
||||
ddh.VirtualAddress = content.ReadUInt32(ref offset);
|
||||
ddh.Size = content.ReadUInt32(ref offset);
|
||||
|
||||
return ddh;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Headers
|
||||
{
|
||||
/// <summary>
|
||||
/// Every image file has an optional header that provides information to the loader.
|
||||
/// This header is optional in the sense that some files (specifically, object files) do not have it.
|
||||
/// For image files, this header is required. An object file can have an optional header, but generally
|
||||
/// this header has no function in an object file except to increase its size.
|
||||
///
|
||||
/// Note that the size of the optional header is not fixed.
|
||||
/// The SizeOfOptionalHeader field in the COFF header must be used to validate that a probe into the file
|
||||
/// for a particular data directory does not go beyond SizeOfOptionalHeader.
|
||||
///
|
||||
/// The NumberOfRvaAndSizes field of the optional header should also be used to ensure that no probe for
|
||||
/// a particular data directory entry goes beyond the optional header.
|
||||
/// In addition, it is important to validate the optional header magic number for format compatibility.
|
||||
/// </summary>
|
||||
public class OptionalHeader
|
||||
{
|
||||
#region Standard Fields
|
||||
|
||||
/// <summary>
|
||||
/// The unsigned integer that identifies the state of the image file.
|
||||
/// The most common number is 0x10B, which identifies it as a normal executable file.
|
||||
/// 0x107 identifies it as a ROM image, and 0x20B identifies it as a PE32+ executable.
|
||||
/// </summary>
|
||||
public OptionalHeaderType Magic;
|
||||
|
||||
/// <summary>
|
||||
/// The linker major version number.
|
||||
/// </summary>
|
||||
public byte MajorLinkerVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The linker minor version number.
|
||||
/// </summary>
|
||||
public byte MinorLinkerVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the code (text) section, or the sum of all code sections if there are multiple sections.
|
||||
/// </summary>
|
||||
public uint SizeOfCode;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the initialized data section, or the sum of all such sections if there are multiple data sections.
|
||||
/// </summary>
|
||||
public uint SizeOfInitializedData;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the uninitialized data section (BSS), or the sum of all such sections if there are multiple BSS sections.
|
||||
/// </summary>
|
||||
public uint SizeOfUninitializedData;
|
||||
|
||||
/// <summary>
|
||||
/// The address of the entry point relative to the image base when the executable file is loaded into memory.
|
||||
/// For program images, this is the starting address.
|
||||
/// For device drivers, this is the address of the initialization function.
|
||||
/// An entry point is optional for DLLs.
|
||||
/// When no entry point is present, this field must be zero.
|
||||
/// </summary>
|
||||
public uint AddressOfEntryPoint;
|
||||
|
||||
/// <summary>
|
||||
/// The address that is relative to the image base of the beginning-of-code section when it is loaded into memory.
|
||||
/// </summary>
|
||||
public uint BaseOfCode;
|
||||
|
||||
/// <summary>
|
||||
/// The address that is relative to the image base of the beginning-of-data section when it is loaded into memory.
|
||||
/// </summary>
|
||||
public uint BaseOfData;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Windows-Specific Fields
|
||||
|
||||
/// <summary>
|
||||
/// The preferred address of the first byte of image when loaded into memory; must be a multiple of 64 K.
|
||||
/// The default for DLLs is 0x10000000.
|
||||
/// The default for Windows CE EXEs is 0x00010000.
|
||||
/// The default for Windows NT, Windows 2000, Windows XP, Windows 95, Windows 98, and Windows Me is 0x00400000.
|
||||
/// </summary>
|
||||
public uint ImageBasePE32;
|
||||
|
||||
/// <summary>
|
||||
/// The preferred address of the first byte of image when loaded into memory; must be a multiple of 64 K.
|
||||
/// The default for DLLs is 0x10000000.
|
||||
/// The default for Windows CE EXEs is 0x00010000.
|
||||
/// The default for Windows NT, Windows 2000, Windows XP, Windows 95, Windows 98, and Windows Me is 0x00400000.
|
||||
/// </summary>
|
||||
public ulong ImageBasePE32Plus;
|
||||
|
||||
/// <summary>
|
||||
/// The alignment (in bytes) of sections when they are loaded into memory.
|
||||
/// It must be greater than or equal to FileAlignment.
|
||||
/// The default is the page size for the architecture.
|
||||
/// </summary>
|
||||
public uint SectionAlignment;
|
||||
|
||||
/// <summary>
|
||||
/// The alignment factor (in bytes) that is used to align the raw data of sections in the image file.
|
||||
/// The value should be a power of 2 between 512 and 64 K, inclusive.
|
||||
/// The default is 512.
|
||||
/// If the SectionAlignment is less than the architecture's page size, then FileAlignment must match SectionAlignment.
|
||||
/// </summary>
|
||||
public uint FileAlignment;
|
||||
|
||||
/// <summary>
|
||||
/// The major version number of the required operating system.
|
||||
/// </summary>
|
||||
public ushort MajorOperatingSystemVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The minor version number of the required operating system.
|
||||
/// </summary>
|
||||
public ushort MinorOperatingSystemVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The major version number of the image.
|
||||
/// </summary>
|
||||
public ushort MajorImageVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The minor version number of the image.
|
||||
/// </summary>
|
||||
public ushort MinorImageVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The major version number of the subsystem.
|
||||
/// </summary>
|
||||
public ushort MajorSubsystemVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The minor version number of the subsystem.
|
||||
/// </summary>
|
||||
public ushort MinorSubsystemVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved, must be zero.
|
||||
/// </summary>
|
||||
public uint Reserved1;
|
||||
|
||||
/// <summary>
|
||||
/// The size (in bytes) of the image, including all headers, as the image is loaded in memory.
|
||||
/// It must be a multiple of SectionAlignment.
|
||||
/// </summary>
|
||||
public uint SizeOfImage;
|
||||
|
||||
/// <summary>
|
||||
/// The combined size of an MS-DOS stub, PE header, and section headers rounded up to a multiple of FileAlignment.
|
||||
/// </summary>
|
||||
public uint SizeOfHeaders;
|
||||
|
||||
/// <summary>
|
||||
/// The image file checksum.
|
||||
/// The algorithm for computing the checksum is incorporated into IMAGHELP.DLL.
|
||||
/// The following are checked for validation at load time: all drivers, any DLL loaded at boot time, and any DLL that is loaded into a critical Windows process.
|
||||
/// </summary>
|
||||
public uint CheckSum;
|
||||
|
||||
/// <summary>
|
||||
/// The subsystem that is required to run this image.
|
||||
/// </summary>
|
||||
public WindowsSubsystem Subsystem;
|
||||
|
||||
/// <summary>
|
||||
/// DLL Characteristics
|
||||
/// </summary>
|
||||
public DllCharacteristics DllCharacteristics;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the stack to reserve.
|
||||
/// Only SizeOfStackCommit is committed; the rest is made available one page at a time until the reserve size is reached.
|
||||
/// </summary>
|
||||
public uint SizeOfStackReservePE32;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the stack to reserve.
|
||||
/// Only SizeOfStackCommit is committed; the rest is made available one page at a time until the reserve size is reached.
|
||||
/// </summary>
|
||||
public ulong SizeOfStackReservePE32Plus;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the stack to commit.
|
||||
/// </summary>
|
||||
public uint SizeOfStackCommitPE32;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the stack to commit.
|
||||
/// </summary>
|
||||
public ulong SizeOfStackCommitPE32Plus;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the local heap space to reserve.
|
||||
/// Only SizeOfHeapCommit is committed; the rest is made available one page at a time until the reserve size is reached.
|
||||
/// </summary>
|
||||
public uint SizeOfHeapReservePE32;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the local heap space to reserve.
|
||||
/// Only SizeOfHeapCommit is committed; the rest is made available one page at a time until the reserve size is reached.
|
||||
/// </summary>
|
||||
public ulong SizeOfHeapReservePE32Plus;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the local heap space to commit.
|
||||
/// </summary>
|
||||
public uint SizeOfHeapCommitPE32;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the local heap space to commit.
|
||||
/// </summary>
|
||||
public ulong SizeOfHeapCommitPE32Plus;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved, must be zero.
|
||||
/// </summary>
|
||||
public uint LoaderFlags;
|
||||
|
||||
/// <summary>
|
||||
/// The number of data-directory entries in the remainder of the optional header.
|
||||
/// Each describes a location and size.
|
||||
/// </summary>
|
||||
public uint NumberOfRvaAndSizes;
|
||||
|
||||
/// <summary>
|
||||
/// Data-directory entries following the optional header
|
||||
/// </summary>
|
||||
public DataDirectoryHeader[] DataDirectories;
|
||||
|
||||
#endregion
|
||||
|
||||
public static OptionalHeader Deserialize(Stream stream)
|
||||
{
|
||||
var ioh = new OptionalHeader();
|
||||
|
||||
ioh.Magic = (OptionalHeaderType)stream.ReadUInt16();
|
||||
ioh.MajorLinkerVersion = stream.ReadByteValue();
|
||||
ioh.MinorLinkerVersion = stream.ReadByteValue();
|
||||
ioh.SizeOfCode = stream.ReadUInt32();
|
||||
ioh.SizeOfInitializedData = stream.ReadUInt32();
|
||||
ioh.SizeOfUninitializedData = stream.ReadUInt32();
|
||||
ioh.AddressOfEntryPoint = stream.ReadUInt32();
|
||||
ioh.BaseOfCode = stream.ReadUInt32();
|
||||
|
||||
// Only standard PE32 has this value
|
||||
if (ioh.Magic == OptionalHeaderType.PE32)
|
||||
ioh.BaseOfData = stream.ReadUInt32();
|
||||
|
||||
// PE32+ has an 8-byte value here
|
||||
if (ioh.Magic == OptionalHeaderType.PE32Plus)
|
||||
ioh.ImageBasePE32Plus = stream.ReadUInt64();
|
||||
else
|
||||
ioh.ImageBasePE32 = stream.ReadUInt32();
|
||||
|
||||
ioh.SectionAlignment = stream.ReadUInt32();
|
||||
ioh.FileAlignment = stream.ReadUInt32();
|
||||
ioh.MajorOperatingSystemVersion = stream.ReadUInt16();
|
||||
ioh.MinorOperatingSystemVersion = stream.ReadUInt16();
|
||||
ioh.MajorImageVersion = stream.ReadUInt16();
|
||||
ioh.MinorImageVersion = stream.ReadUInt16();
|
||||
ioh.MajorSubsystemVersion = stream.ReadUInt16();
|
||||
ioh.MinorSubsystemVersion = stream.ReadUInt16();
|
||||
ioh.Reserved1 = stream.ReadUInt32();
|
||||
ioh.SizeOfImage = stream.ReadUInt32();
|
||||
ioh.SizeOfHeaders = stream.ReadUInt32();
|
||||
ioh.CheckSum = stream.ReadUInt32();
|
||||
ioh.Subsystem = (WindowsSubsystem)stream.ReadUInt16();
|
||||
ioh.DllCharacteristics = (DllCharacteristics)stream.ReadUInt16();
|
||||
|
||||
// PE32+ uses 8-byte values
|
||||
if (ioh.Magic == OptionalHeaderType.PE32Plus)
|
||||
{
|
||||
ioh.SizeOfStackReservePE32Plus = stream.ReadUInt64();
|
||||
ioh.SizeOfStackCommitPE32Plus = stream.ReadUInt64();
|
||||
ioh.SizeOfHeapReservePE32Plus = stream.ReadUInt64();
|
||||
ioh.SizeOfHeapCommitPE32Plus = stream.ReadUInt64();
|
||||
}
|
||||
else
|
||||
{
|
||||
ioh.SizeOfStackReservePE32 = stream.ReadUInt32();
|
||||
ioh.SizeOfStackCommitPE32 = stream.ReadUInt32();
|
||||
ioh.SizeOfHeapReservePE32 = stream.ReadUInt32();
|
||||
ioh.SizeOfHeapCommitPE32 = stream.ReadUInt32();
|
||||
}
|
||||
|
||||
ioh.LoaderFlags = stream.ReadUInt32();
|
||||
ioh.NumberOfRvaAndSizes = stream.ReadUInt32();
|
||||
ioh.DataDirectories = new DataDirectoryHeader[Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||
for (int i = 0; i < Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
|
||||
{
|
||||
ioh.DataDirectories[i] = DataDirectoryHeader.Deserialize(stream);
|
||||
}
|
||||
|
||||
return ioh;
|
||||
}
|
||||
|
||||
public static OptionalHeader Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var ioh = new OptionalHeader();
|
||||
|
||||
ioh.Magic = (OptionalHeaderType)content.ReadUInt16(ref offset);
|
||||
ioh.MajorLinkerVersion = content[offset]; offset++;
|
||||
ioh.MinorLinkerVersion = content[offset]; offset++;
|
||||
ioh.SizeOfCode = content.ReadUInt32(ref offset);
|
||||
ioh.SizeOfInitializedData = content.ReadUInt32(ref offset);
|
||||
ioh.SizeOfUninitializedData = content.ReadUInt32(ref offset);
|
||||
ioh.AddressOfEntryPoint = content.ReadUInt32(ref offset);
|
||||
ioh.BaseOfCode = content.ReadUInt32(ref offset);
|
||||
|
||||
// Only standard PE32 has this value
|
||||
if (ioh.Magic == OptionalHeaderType.PE32)
|
||||
ioh.BaseOfData = content.ReadUInt32(ref offset);
|
||||
|
||||
// PE32+ has an 8-bit value here
|
||||
if (ioh.Magic == OptionalHeaderType.PE32Plus)
|
||||
{
|
||||
ioh.ImageBasePE32Plus = content.ReadUInt64(ref offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
ioh.ImageBasePE32 = content.ReadUInt32(ref offset);
|
||||
}
|
||||
|
||||
ioh.SectionAlignment = content.ReadUInt32(ref offset);
|
||||
ioh.FileAlignment = content.ReadUInt32(ref offset);
|
||||
ioh.MajorOperatingSystemVersion = content.ReadUInt16(ref offset);
|
||||
ioh.MinorOperatingSystemVersion = content.ReadUInt16(ref offset);
|
||||
ioh.MajorImageVersion = content.ReadUInt16(ref offset);
|
||||
ioh.MinorImageVersion = content.ReadUInt16(ref offset);
|
||||
ioh.MajorSubsystemVersion = content.ReadUInt16(ref offset);
|
||||
ioh.MinorSubsystemVersion = content.ReadUInt16(ref offset);
|
||||
ioh.Reserved1 = content.ReadUInt32(ref offset);
|
||||
ioh.SizeOfImage = content.ReadUInt32(ref offset);
|
||||
ioh.SizeOfHeaders = content.ReadUInt32(ref offset);
|
||||
ioh.CheckSum = content.ReadUInt32(ref offset);
|
||||
ioh.Subsystem = (WindowsSubsystem)content.ReadUInt16(ref offset);
|
||||
ioh.DllCharacteristics = (DllCharacteristics)content.ReadUInt16(ref offset);
|
||||
|
||||
// PE32+ uses 8-byte values
|
||||
if (ioh.Magic == OptionalHeaderType.PE32Plus)
|
||||
{
|
||||
ioh.SizeOfStackReservePE32Plus = content.ReadUInt64(ref offset);
|
||||
ioh.SizeOfStackCommitPE32Plus = content.ReadUInt64(ref offset);
|
||||
ioh.SizeOfHeapReservePE32Plus = content.ReadUInt64(ref offset);
|
||||
ioh.SizeOfHeapCommitPE32Plus = content.ReadUInt64(ref offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
ioh.SizeOfStackReservePE32 = content.ReadUInt32(ref offset);
|
||||
ioh.SizeOfStackCommitPE32 = content.ReadUInt32(ref offset);
|
||||
ioh.SizeOfHeapReservePE32 = content.ReadUInt32(ref offset);
|
||||
ioh.SizeOfHeapCommitPE32 = content.ReadUInt32(ref offset);
|
||||
}
|
||||
|
||||
ioh.LoaderFlags = content.ReadUInt32(ref offset);
|
||||
ioh.NumberOfRvaAndSizes = content.ReadUInt32(ref offset);
|
||||
ioh.DataDirectories = new DataDirectoryHeader[Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||
for (int i = 0; i < Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
|
||||
{
|
||||
ioh.DataDirectories[i] = DataDirectoryHeader.Deserialize(content, ref offset);
|
||||
}
|
||||
|
||||
return ioh;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Headers
|
||||
{
|
||||
/// <summary>
|
||||
/// Each row of the section table is, in effect, a section header.
|
||||
/// This table immediately follows the optional header, if any.
|
||||
/// This positioning is required because the file header does not contain a direct pointer to the section table.
|
||||
/// Instead, the location of the section table is determined by calculating the location of the first byte after the headers.
|
||||
/// Make sure to use the size of the optional header as specified in the file header.
|
||||
/// </summary>
|
||||
public class SectionHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// An 8-byte, null-padded UTF-8 encoded string.
|
||||
/// If the string is exactly 8 characters long, there is no terminating null.
|
||||
/// For longer names, this field contains a slash (/) that is followed by an ASCII representation of a decimal number
|
||||
/// that is an offset into the string table.
|
||||
/// Executable images do not use a string table and do not support section names longer than 8 characters.
|
||||
/// Long names in object files are truncated if they are emitted to an executable file.
|
||||
/// </summary>
|
||||
public byte[] Name;
|
||||
|
||||
/// <summary>
|
||||
/// Section name as a string, trimming any trailing null bytes
|
||||
/// </summary>
|
||||
public string NameString
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.Name == null || this.Name.Length == 0)
|
||||
return null;
|
||||
|
||||
// First try decoding as UTF-8
|
||||
try
|
||||
{
|
||||
return Encoding.UTF8.GetString(this.Name).TrimEnd('\0');
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Then try decoding as ASCII
|
||||
try
|
||||
{
|
||||
return Encoding.ASCII.GetString(this.Name).TrimEnd('\0');
|
||||
}
|
||||
catch { }
|
||||
|
||||
// If it fails, return null
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The total size of the section when loaded into memory.
|
||||
/// If this value is greater than SizeOfRawData, the section is zero-padded.
|
||||
/// This field is valid only for executable images and should be set to zero for object files.
|
||||
/// </summary>
|
||||
public uint VirtualSize;
|
||||
|
||||
/// <summary>
|
||||
/// For executable images, the address of the first byte of the section relative to the image base when the section
|
||||
/// is loaded into memory.
|
||||
/// For object files, this field is the address of the first byte before relocation is applied; for simplicity,
|
||||
/// compilers should set this to zero.
|
||||
/// Otherwise, it is an arbitrary value that is subtracted from offsets during relocation.
|
||||
/// </summary>
|
||||
public uint VirtualAddress;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the section (for object files) or the size of the initialized data on disk (for image files).
|
||||
/// For executable images, this must be a multiple of FileAlignment from the optional header.
|
||||
/// If this is less than VirtualSize, the remainder of the section is zero-filled.
|
||||
/// Because the SizeOfRawData field is rounded but the VirtualSize field is not, it is possible for SizeOfRawData
|
||||
/// to be greater than VirtualSize as well.
|
||||
/// When a section contains only uninitialized data, this field should be zero.
|
||||
/// </summary>
|
||||
public uint SizeOfRawData;
|
||||
|
||||
/// <summary>
|
||||
/// The file pointer to the first page of the section within the COFF file.
|
||||
/// For executable images, this must be a multiple of FileAlignment from the optional header.
|
||||
/// For object files, the value should be aligned on a 4-byte boundary for best performance.
|
||||
/// When a section contains only uninitialized data, this field should be zero.
|
||||
/// </summary>
|
||||
public uint PointerToRawData;
|
||||
|
||||
/// <summary>
|
||||
/// The file pointer to the beginning of relocation entries for the section.
|
||||
/// This is set to zero for executable images or if there are no relocations.
|
||||
/// </summary>
|
||||
public uint PointerToRelocations;
|
||||
|
||||
/// <summary>
|
||||
/// The file pointer to the beginning of line-number entries for the section.
|
||||
/// This is set to zero if there are no COFF line numbers.
|
||||
/// This value should be zero for an image because COFF debugging information is deprecated.
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
public uint PointerToLinenumbers;
|
||||
|
||||
/// <summary>
|
||||
/// The number of relocation entries for the section.
|
||||
/// This is set to zero for executable images.
|
||||
/// </summary>
|
||||
public ushort NumberOfRelocations;
|
||||
|
||||
/// <summary>
|
||||
/// The number of line-number entries for the section.
|
||||
/// This value should be zero for an image because COFF debugging information is deprecated.
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
public ushort NumberOfLinenumbers;
|
||||
|
||||
/// <summary>
|
||||
/// The flags that describe the characteristics of the section.
|
||||
/// </summary>
|
||||
public SectionCharacteristics Characteristics;
|
||||
|
||||
public static SectionHeader Deserialize(Stream stream)
|
||||
{
|
||||
var ish = new SectionHeader();
|
||||
|
||||
ish.Name = stream.ReadBytes(Constants.IMAGE_SIZEOF_SHORT_NAME);
|
||||
ish.VirtualSize = stream.ReadUInt32();
|
||||
ish.VirtualAddress = stream.ReadUInt32();
|
||||
ish.SizeOfRawData = stream.ReadUInt32();
|
||||
ish.PointerToRawData = stream.ReadUInt32();
|
||||
ish.PointerToRelocations = stream.ReadUInt32();
|
||||
ish.PointerToLinenumbers = stream.ReadUInt32();
|
||||
ish.NumberOfRelocations = stream.ReadUInt16();
|
||||
ish.NumberOfLinenumbers = stream.ReadUInt16();
|
||||
ish.Characteristics = (SectionCharacteristics)stream.ReadUInt32();
|
||||
|
||||
return ish;
|
||||
}
|
||||
|
||||
public static SectionHeader Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var ish = new SectionHeader();
|
||||
|
||||
ish.Name = new byte[Constants.IMAGE_SIZEOF_SHORT_NAME];
|
||||
Array.Copy(content, offset, ish.Name, 0, Constants.IMAGE_SIZEOF_SHORT_NAME); offset += Constants.IMAGE_SIZEOF_SHORT_NAME;
|
||||
ish.VirtualSize = content.ReadUInt32(ref offset);
|
||||
ish.VirtualAddress = content.ReadUInt32(ref offset);
|
||||
ish.SizeOfRawData = content.ReadUInt32(ref offset);
|
||||
ish.PointerToRawData = content.ReadUInt32(ref offset);
|
||||
ish.PointerToRelocations = content.ReadUInt32(ref offset);
|
||||
ish.PointerToLinenumbers = content.ReadUInt32(ref offset);
|
||||
ish.NumberOfRelocations = content.ReadUInt16(ref offset);
|
||||
ish.NumberOfLinenumbers = content.ReadUInt16(ref offset);
|
||||
ish.Characteristics = (SectionCharacteristics)content.ReadUInt32(ref offset);
|
||||
|
||||
return ish;
|
||||
}
|
||||
}
|
||||
}
|
||||
1054
BurnOutSharp/ExecutableType/Microsoft/PE/PortableExecutable.cs
Normal file
1054
BurnOutSharp/ExecutableType/Microsoft/PE/PortableExecutable.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,46 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Tables;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Sections
|
||||
{
|
||||
/// <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.
|
||||
/// </summary>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-debug-section</remarks>
|
||||
public class DebugSection
|
||||
{
|
||||
/// <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.
|
||||
/// </summary>
|
||||
public DebugDirectory DebugDirectory;
|
||||
|
||||
public static DebugSection Deserialize(Stream stream)
|
||||
{
|
||||
long originalPosition = stream.Position;
|
||||
var ds = new DebugSection();
|
||||
|
||||
ds.DebugDirectory = DebugDirectory.Deserialize(stream);
|
||||
|
||||
// TODO: Read in raw debug data
|
||||
|
||||
stream.Seek(originalPosition, SeekOrigin.Begin);
|
||||
return ds;
|
||||
}
|
||||
|
||||
public static DebugSection Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
int originalPosition = offset;
|
||||
var ds = new DebugSection();
|
||||
|
||||
ds.DebugDirectory = DebugDirectory.Deserialize(content, ref offset);
|
||||
|
||||
// TODO: Read in raw debug data
|
||||
|
||||
offset = originalPosition;
|
||||
return ds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Tables;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Sections
|
||||
{
|
||||
/// <summary>
|
||||
/// The .pdata section contains an array of function table entries that are used for exception handling.
|
||||
/// It is pointed to by the exception table entry in the image data directory.
|
||||
/// The entries must be sorted according to the function addresses (the first field in each structure) before being emitted into the final image.
|
||||
/// The target platform determines which of the three function table entry format variations described below is used.
|
||||
/// </summary>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-edata-section-image-only</remarks>
|
||||
public class ExceptionHandlingSection
|
||||
{
|
||||
/// <summary>
|
||||
/// Array of function table entries that are used for exception handling
|
||||
/// </summary>
|
||||
public FunctionTable FunctionTable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Entries;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Headers;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Tables;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Sections
|
||||
{
|
||||
/// <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.
|
||||
/// </summary>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-edata-section-image-only</remarks>
|
||||
public class ExportDataSection
|
||||
{
|
||||
/// <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 uint[] ExportNamePointerTable;
|
||||
|
||||
/// <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;
|
||||
|
||||
public static ExportDataSection Deserialize(Stream stream, SectionHeader[] sections)
|
||||
{
|
||||
long originalPosition = stream.Position;
|
||||
var eds = new ExportDataSection();
|
||||
|
||||
eds.ExportDirectoryTable = ExportDirectoryTable.Deserialize(stream);
|
||||
|
||||
stream.Seek((int)PortableExecutable.ConvertVirtualAddress(eds.ExportDirectoryTable.ExportAddressTableRVA, sections), SeekOrigin.Begin);
|
||||
eds.ExportAddressTable = new ExportAddressTableEntry[(int)eds.ExportDirectoryTable.AddressTableEntries];
|
||||
for (int i = 0; i < eds.ExportAddressTable.Length; i++)
|
||||
{
|
||||
eds.ExportAddressTable[i] = ExportAddressTableEntry.Deserialize(stream, sections);
|
||||
}
|
||||
|
||||
stream.Seek((int)PortableExecutable.ConvertVirtualAddress(eds.ExportDirectoryTable.NamePointerRVA, sections), SeekOrigin.Begin);
|
||||
eds.ExportNamePointerTable = new uint[(int)eds.ExportDirectoryTable.NumberOfNamePointers];
|
||||
for (int i = 0; i < eds.ExportNamePointerTable.Length; i++)
|
||||
{
|
||||
eds.ExportNamePointerTable[i] = stream.ReadUInt32();
|
||||
}
|
||||
|
||||
stream.Seek((int)PortableExecutable.ConvertVirtualAddress(eds.ExportDirectoryTable.OrdinalTableRVA, sections), SeekOrigin.Begin);
|
||||
// eds.OrdinalTable = ExportOrdinalTable.Deserialize(stream, count: 0); // TODO: Figure out where this count comes from
|
||||
|
||||
return eds;
|
||||
}
|
||||
|
||||
public static ExportDataSection Deserialize(byte[] content, ref int offset, SectionHeader[] sections)
|
||||
{
|
||||
int originalPosition = offset;
|
||||
var eds = new ExportDataSection();
|
||||
|
||||
eds.ExportDirectoryTable = ExportDirectoryTable.Deserialize(content, ref offset);
|
||||
|
||||
offset = (int)PortableExecutable.ConvertVirtualAddress(eds.ExportDirectoryTable.ExportAddressTableRVA, sections);
|
||||
eds.ExportAddressTable = new ExportAddressTableEntry[(int)eds.ExportDirectoryTable.AddressTableEntries];
|
||||
for (int i = 0; i < eds.ExportAddressTable.Length; i++)
|
||||
{
|
||||
eds.ExportAddressTable[i] = ExportAddressTableEntry.Deserialize(content, ref offset, sections);
|
||||
}
|
||||
|
||||
offset = (int)PortableExecutable.ConvertVirtualAddress(eds.ExportDirectoryTable.NamePointerRVA, sections);
|
||||
eds.ExportNamePointerTable = new uint[(int)eds.ExportDirectoryTable.NumberOfNamePointers];
|
||||
for (int i = 0; i < eds.ExportNamePointerTable.Length; i++)
|
||||
{
|
||||
eds.ExportNamePointerTable[i] = content.ReadUInt32(ref offset);
|
||||
}
|
||||
|
||||
offset = (int)PortableExecutable.ConvertVirtualAddress(eds.ExportDirectoryTable.OrdinalTableRVA, sections);
|
||||
// eds.OrdinalTable = ExportOrdinalTable.Deserialize(content, ref offset, count: 0); // TODO: Figure out where this count comes from
|
||||
|
||||
return eds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Tables;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Sections
|
||||
{
|
||||
/// <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>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-idata-section</remarks>
|
||||
public class ImportDataSection
|
||||
{
|
||||
/// <summary>
|
||||
/// Import directory table
|
||||
/// </summary>
|
||||
public ImportDirectoryTable ImportDirectoryTable;
|
||||
|
||||
/// <summary>
|
||||
/// Import lookup tables
|
||||
/// </summary>
|
||||
public ImportLookupTable[] ImportLookupTables;
|
||||
|
||||
/// <summary>
|
||||
/// Hint/Name table
|
||||
/// </summary>
|
||||
public HintNameTable HintNameTable;
|
||||
|
||||
public static ImportDataSection Deserialize(Stream stream, bool pe32plus, int hintCount)
|
||||
{
|
||||
var ids = new ImportDataSection();
|
||||
|
||||
ids.ImportDirectoryTable = ImportDirectoryTable.Deserialize(stream);
|
||||
|
||||
List<ImportLookupTable> tempLookupTables = new List<ImportLookupTable>();
|
||||
while (true)
|
||||
{
|
||||
var tempLookupTable = ImportLookupTable.Deserialize(stream, pe32plus);
|
||||
if (tempLookupTable.EntriesPE32 == null && tempLookupTable.EntriesPE32Plus == null)
|
||||
break;
|
||||
|
||||
tempLookupTables.Add(tempLookupTable);
|
||||
}
|
||||
|
||||
ids.HintNameTable = HintNameTable.Deserialize(stream, hintCount);
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
public static ImportDataSection Deserialize(byte[] content, ref int offset, bool pe32plus, int hintCount)
|
||||
{
|
||||
var ids = new ImportDataSection();
|
||||
|
||||
ids.ImportDirectoryTable = ImportDirectoryTable.Deserialize(content, ref offset);
|
||||
|
||||
List<ImportLookupTable> tempLookupTables = new List<ImportLookupTable>();
|
||||
while (true)
|
||||
{
|
||||
var tempLookupTable = ImportLookupTable.Deserialize(content, ref offset, pe32plus);
|
||||
if (tempLookupTable.EntriesPE32 == null && tempLookupTable.EntriesPE32Plus == null)
|
||||
break;
|
||||
|
||||
tempLookupTables.Add(tempLookupTable);
|
||||
}
|
||||
|
||||
ids.HintNameTable = HintNameTable.Deserialize(content, ref offset, hintCount);
|
||||
|
||||
return ids;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Entries;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Sections
|
||||
{
|
||||
/// <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.
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-reloc-section-image-only</remarks>
|
||||
public class RelocationSection
|
||||
{
|
||||
/// <summary>
|
||||
/// The base relocation table is divided into blocks.
|
||||
/// </summary>
|
||||
public BaseRelocationBlock[] BaseRelocationTable;
|
||||
|
||||
public static RelocationSection Deserialize(Stream stream, int blockCount)
|
||||
{
|
||||
long originalPosition = stream.Position;
|
||||
|
||||
var rs = new RelocationSection();
|
||||
rs.BaseRelocationTable = new BaseRelocationBlock[blockCount];
|
||||
for (int i = 0; i < blockCount; i++)
|
||||
{
|
||||
rs.BaseRelocationTable[i] = BaseRelocationBlock.Deserialize(stream);
|
||||
}
|
||||
|
||||
stream.Seek(originalPosition, SeekOrigin.Begin);
|
||||
return rs;
|
||||
}
|
||||
|
||||
public static RelocationSection Deserialize(byte[] content, ref int offset, int blockCount)
|
||||
{
|
||||
int originalPosition = offset;
|
||||
|
||||
var rs = new RelocationSection();
|
||||
rs.BaseRelocationTable = new BaseRelocationBlock[blockCount];
|
||||
for (int i = 0; i < blockCount; i++)
|
||||
{
|
||||
rs.BaseRelocationTable[i] = BaseRelocationBlock.Deserialize(content, ref offset);
|
||||
}
|
||||
|
||||
offset = originalPosition;
|
||||
return rs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Headers;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Tables;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Sections
|
||||
{
|
||||
/// <summary>
|
||||
/// A series of resource directory tables relates all of the levels in the following way:
|
||||
// Each directory table is followed by a series of directory entries that give the name or
|
||||
// identifier (ID) for that level (Type, Name, or Language level) and an address of either
|
||||
// a data description or another directory table. If the address points to a data description,
|
||||
// then the data is a leaf in the tree. If the address points to another directory table,
|
||||
// then that table lists directory entries at the next level down
|
||||
/// </summary>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-rsrc-section</remarks>
|
||||
public class ResourceSection
|
||||
{
|
||||
/// <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 ResourceDirectoryTable ResourceDirectoryTable;
|
||||
|
||||
public static ResourceSection Deserialize(Stream stream, SectionHeader[] sections)
|
||||
{
|
||||
var rs = new ResourceSection();
|
||||
|
||||
long sectionStart = stream.Position;
|
||||
rs.ResourceDirectoryTable = ResourceDirectoryTable.Deserialize(stream, sectionStart, sections);
|
||||
|
||||
return rs;
|
||||
}
|
||||
|
||||
public static ResourceSection Deserialize(byte[] content, ref int offset, SectionHeader[] sections)
|
||||
{
|
||||
var rs = new ResourceSection();
|
||||
|
||||
long sectionStart = offset;
|
||||
rs.ResourceDirectoryTable = ResourceDirectoryTable.Deserialize(content, ref offset, sectionStart, sections);
|
||||
|
||||
return rs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Tables
|
||||
{
|
||||
/// <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.
|
||||
/// </summary>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#debug-directory-image-only</remarks>
|
||||
public class DebugDirectory
|
||||
{
|
||||
/// <summary>
|
||||
/// Reserved, must be 0.
|
||||
/// </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;
|
||||
|
||||
public static DebugDirectory Deserialize(Stream stream)
|
||||
{
|
||||
var dd = new DebugDirectory();
|
||||
|
||||
dd.Characteristics = stream.ReadUInt32();
|
||||
dd.TimeDateStamp = stream.ReadUInt32();
|
||||
dd.MajorVersion = stream.ReadUInt16();
|
||||
dd.MinorVersion = stream.ReadUInt16();
|
||||
dd.DebugType = (DebugType)stream.ReadUInt32();
|
||||
dd.SizeOfData = stream.ReadUInt32();
|
||||
dd.AddressOfRawData = stream.ReadUInt32();
|
||||
dd.PointerToRawData = stream.ReadUInt32();
|
||||
|
||||
return dd;
|
||||
}
|
||||
|
||||
public static DebugDirectory Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var dd = new DebugDirectory();
|
||||
|
||||
dd.Characteristics = content.ReadUInt32(ref offset);
|
||||
dd.TimeDateStamp = content.ReadUInt32(ref offset);
|
||||
dd.MajorVersion = content.ReadUInt16(ref offset);
|
||||
dd.MinorVersion = content.ReadUInt16(ref offset);
|
||||
dd.DebugType = (DebugType)content.ReadUInt32(ref offset);
|
||||
dd.SizeOfData = content.ReadUInt32(ref offset);
|
||||
dd.AddressOfRawData = content.ReadUInt32(ref offset);
|
||||
dd.PointerToRawData = content.ReadUInt32(ref offset);
|
||||
|
||||
return dd;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Tables
|
||||
{
|
||||
/// <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>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#export-directory-table</remarks>
|
||||
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; // TODO: Read this into a separate field
|
||||
|
||||
/// <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;
|
||||
|
||||
public static ExportDirectoryTable Deserialize(Stream stream)
|
||||
{
|
||||
var edt = new ExportDirectoryTable();
|
||||
|
||||
edt.ExportFlags = stream.ReadUInt32();
|
||||
edt.TimeDateStamp = stream.ReadUInt32();
|
||||
edt.MajorVersion = stream.ReadUInt16();
|
||||
edt.MinorVersion = stream.ReadUInt16();
|
||||
edt.NameRVA = stream.ReadUInt32();
|
||||
edt.OrdinalBase = stream.ReadUInt32();
|
||||
edt.AddressTableEntries = stream.ReadUInt32();
|
||||
edt.NumberOfNamePointers = stream.ReadUInt32();
|
||||
edt.ExportAddressTableRVA = stream.ReadUInt32();
|
||||
edt.NamePointerRVA = stream.ReadUInt32();
|
||||
edt.OrdinalTableRVA = stream.ReadUInt32();
|
||||
|
||||
return edt;
|
||||
}
|
||||
|
||||
public static ExportDirectoryTable Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var edt = new ExportDirectoryTable();
|
||||
|
||||
edt.ExportFlags = content.ReadUInt32(ref offset);
|
||||
edt.TimeDateStamp = content.ReadUInt32(ref offset);
|
||||
edt.MajorVersion = content.ReadUInt16(ref offset);
|
||||
edt.MinorVersion = content.ReadUInt16(ref offset);
|
||||
edt.NameRVA = content.ReadUInt32(ref offset);
|
||||
edt.OrdinalBase = content.ReadUInt32(ref offset);
|
||||
edt.AddressTableEntries = content.ReadUInt32(ref offset);
|
||||
edt.NumberOfNamePointers = content.ReadUInt32(ref offset);
|
||||
edt.ExportAddressTableRVA = content.ReadUInt32(ref offset);
|
||||
edt.NamePointerRVA = content.ReadUInt32(ref offset);
|
||||
edt.OrdinalTableRVA = content.ReadUInt32(ref offset);
|
||||
|
||||
return edt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Tables
|
||||
{
|
||||
/// <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.
|
||||
/// </summary>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#export-ordinal-table</remarks>
|
||||
public class ExportOrdinalTable
|
||||
{
|
||||
/// <remarks>Number of entries is defined externally</remarks>
|
||||
public ushort[] Entries;
|
||||
|
||||
public static ExportOrdinalTable Deserialize(Stream stream, int count)
|
||||
{
|
||||
var edt = new ExportOrdinalTable();
|
||||
|
||||
edt.Entries = new ushort[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
edt.Entries[i] = stream.ReadUInt16();
|
||||
}
|
||||
|
||||
return edt;
|
||||
}
|
||||
|
||||
public static ExportOrdinalTable Deserialize(byte[] content, ref int offset, int count)
|
||||
{
|
||||
var edt = new ExportOrdinalTable();
|
||||
|
||||
edt.Entries = new ushort[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
edt.Entries[i] = content.ReadUInt16(ref offset);
|
||||
}
|
||||
|
||||
return edt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Entries;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Tables
|
||||
{
|
||||
/// <summary>
|
||||
/// The .pdata section contains an array of function table entries that are used for exception handling.
|
||||
/// It is pointed to by the exception table entry in the image data directory.
|
||||
/// The entries must be sorted according to the function addresses (the first field in each structure) before being emitted into the final image.
|
||||
/// The target platform determines which of the three function table entry format variations described below is used.
|
||||
/// </summary>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-pdata-section</remarks>
|
||||
public class FunctionTable
|
||||
{
|
||||
/// <remarks>Number of entries is defined externally</remarks>
|
||||
public FunctionTableEntry[] Entries;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Entries;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Tables
|
||||
{
|
||||
/// <summary>
|
||||
/// One hint/name table suffices for the entire import section.
|
||||
/// </summary>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#hintname-table</remarks>
|
||||
public class HintNameTable
|
||||
{
|
||||
/// <remarks>Number of entries is defined externally</remarks>
|
||||
public HintNameTableEntry[] Entries;
|
||||
|
||||
public static HintNameTable Deserialize(Stream stream, int count)
|
||||
{
|
||||
var hnt = new HintNameTable();
|
||||
|
||||
hnt.Entries = new HintNameTableEntry[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
hnt.Entries[i] = HintNameTableEntry.Deserialize(stream);
|
||||
}
|
||||
|
||||
return hnt;
|
||||
}
|
||||
|
||||
public static HintNameTable Deserialize(byte[] content, ref int offset, int count)
|
||||
{
|
||||
var hnt = new HintNameTable();
|
||||
|
||||
hnt.Entries = new HintNameTableEntry[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
hnt.Entries[i] = HintNameTableEntry.Deserialize(content, ref offset);
|
||||
offset += 2 + hnt.Entries[i].Name.Length + hnt.Entries[i].Pad;
|
||||
}
|
||||
|
||||
return hnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Entries;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Tables
|
||||
{
|
||||
/// <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>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-address-table</remarks>
|
||||
public class ImportAddressTable
|
||||
{
|
||||
/// <remarks>Number of entries is known after parsing</remarks>
|
||||
public ImportAddressTableEntry[] Entries;
|
||||
|
||||
public static ImportAddressTable Deserialize(Stream stream)
|
||||
{
|
||||
var iat = new ImportAddressTable();
|
||||
|
||||
List<ImportAddressTableEntry> tempEntries = new List<ImportAddressTableEntry>();
|
||||
while (true)
|
||||
{
|
||||
var entry = ImportAddressTableEntry.Deserialize(stream);
|
||||
tempEntries.Add(entry);
|
||||
if (entry.IsNull())
|
||||
break;
|
||||
}
|
||||
|
||||
iat.Entries = tempEntries.ToArray();
|
||||
return iat;
|
||||
}
|
||||
|
||||
public static ImportAddressTable Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var iat = new ImportAddressTable();
|
||||
|
||||
List<ImportAddressTableEntry> tempEntries = new List<ImportAddressTableEntry>();
|
||||
while (true)
|
||||
{
|
||||
var entry = ImportAddressTableEntry.Deserialize(content, ref offset);
|
||||
tempEntries.Add(entry);
|
||||
if (entry.IsNull())
|
||||
break;
|
||||
}
|
||||
|
||||
iat.Entries = tempEntries.ToArray();
|
||||
return iat;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Entries;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Tables
|
||||
{
|
||||
/// <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>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-directory-table</remarks>
|
||||
public class ImportDirectoryTable
|
||||
{
|
||||
/// <remarks>Number of entries is known after parsing</remarks>
|
||||
public ImportDirectoryTableEntry[] Entries;
|
||||
|
||||
public static ImportDirectoryTable Deserialize(Stream stream)
|
||||
{
|
||||
var idt = new ImportDirectoryTable();
|
||||
|
||||
List<ImportDirectoryTableEntry> tempEntries = new List<ImportDirectoryTableEntry>();
|
||||
while (true)
|
||||
{
|
||||
var entry = ImportDirectoryTableEntry.Deserialize(stream);
|
||||
tempEntries.Add(entry);
|
||||
if (entry.IsNull())
|
||||
break;
|
||||
}
|
||||
|
||||
idt.Entries = tempEntries.ToArray();
|
||||
return idt;
|
||||
}
|
||||
|
||||
public static ImportDirectoryTable Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var idt = new ImportDirectoryTable();
|
||||
|
||||
List<ImportDirectoryTableEntry> tempEntries = new List<ImportDirectoryTableEntry>();
|
||||
while (true)
|
||||
{
|
||||
var entry = ImportDirectoryTableEntry.Deserialize(content, ref offset);
|
||||
tempEntries.Add(entry);
|
||||
if (entry.IsNull())
|
||||
break;
|
||||
}
|
||||
|
||||
idt.Entries = tempEntries.ToArray();
|
||||
return idt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Tables
|
||||
{
|
||||
/// <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>
|
||||
/// <remarks>https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-lookup-table</remarks>
|
||||
public class ImportLookupTable
|
||||
{
|
||||
/// <remarks>Number of entries is known after parsing</remarks>
|
||||
public uint[] EntriesPE32;
|
||||
|
||||
/// <remarks>Number of entries is known after parsing</remarks>
|
||||
public ulong[] EntriesPE32Plus;
|
||||
|
||||
public static ImportLookupTable Deserialize(Stream stream, bool pe32plus)
|
||||
{
|
||||
var ilt = new ImportLookupTable();
|
||||
|
||||
// PE32+ has 8-byte values
|
||||
if (pe32plus)
|
||||
{
|
||||
List<ulong> tempEntries = new List<ulong>();
|
||||
while (true)
|
||||
{
|
||||
ulong bitfield = stream.ReadUInt64();
|
||||
tempEntries.Add(bitfield);
|
||||
if (bitfield == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (tempEntries.Count > 0)
|
||||
ilt.EntriesPE32Plus = tempEntries.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
List<uint> tempEntries = new List<uint>();
|
||||
while (true)
|
||||
{
|
||||
uint bitfield = stream.ReadUInt32();
|
||||
tempEntries.Add(bitfield);
|
||||
if (bitfield == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (tempEntries.Count > 0)
|
||||
ilt.EntriesPE32 = tempEntries.ToArray();
|
||||
}
|
||||
|
||||
return ilt;
|
||||
}
|
||||
|
||||
public static ImportLookupTable Deserialize(byte[] content, ref int offset, bool pe32plus)
|
||||
{
|
||||
var ilt = new ImportLookupTable();
|
||||
|
||||
// PE32+ has 8-byte values
|
||||
if (pe32plus)
|
||||
{
|
||||
List<ulong> tempEntries = new List<ulong>();
|
||||
while (true)
|
||||
{
|
||||
ulong bitfield = content.ReadUInt64(ref offset);
|
||||
tempEntries.Add(bitfield);
|
||||
if (bitfield == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (tempEntries.Count > 0)
|
||||
ilt.EntriesPE32Plus = tempEntries.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
List<uint> tempEntries = new List<uint>();
|
||||
while (true)
|
||||
{
|
||||
uint bitfield = content.ReadUInt32(ref offset);
|
||||
tempEntries.Add(bitfield);
|
||||
if (bitfield == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (tempEntries.Count > 0)
|
||||
ilt.EntriesPE32 = tempEntries.ToArray();
|
||||
}
|
||||
|
||||
return ilt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Entries;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Headers;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Tables
|
||||
{
|
||||
/// <summary>
|
||||
/// Each resource directory table has the following format.
|
||||
/// This data structure should be considered the heading of a table
|
||||
/// because the table actually consists of directory entries and this structure
|
||||
/// </summary>
|
||||
public class ResourceDirectoryTable
|
||||
{
|
||||
/// <summary>
|
||||
/// Resource flags.
|
||||
/// This field is reserved for future use.
|
||||
/// It is currently set to zero.
|
||||
/// </summary>
|
||||
public uint Characteristics;
|
||||
|
||||
/// <summary>
|
||||
/// The time that the resource data was created by the resource compiler.
|
||||
/// </summary>
|
||||
public uint TimeDateStamp;
|
||||
|
||||
/// <summary>
|
||||
/// The major version number, set by the user.
|
||||
/// </summary>
|
||||
public ushort MajorVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The minor version number, set by the user.
|
||||
/// </summary>
|
||||
public ushort MinorVersion;
|
||||
|
||||
/// <summary>
|
||||
/// The number of directory entries immediately following
|
||||
/// the table that use strings to identify Type, Name, or
|
||||
/// Language entries (depending on the level of the table).
|
||||
/// </summary>
|
||||
public ushort NumberOfNamedEntries;
|
||||
|
||||
/// <summary>
|
||||
/// The number of directory entries immediately following
|
||||
/// the Name entries that use numeric IDs for Type, Name,
|
||||
/// or Language entries.
|
||||
/// </summary>
|
||||
public ushort NumberOfIdEntries;
|
||||
|
||||
/// <summary>
|
||||
/// The directory entries immediately following
|
||||
/// the table that use strings to identify Type, Name, or
|
||||
/// Language entries (depending on the level of the table).
|
||||
/// </summary>
|
||||
public ResourceDirectoryTableEntry[] NamedEntries;
|
||||
|
||||
/// <summary>
|
||||
/// The directory entries immediately following
|
||||
/// the Name entries that use numeric IDs for Type, Name,
|
||||
/// or Language entries.
|
||||
/// </summary>
|
||||
public ResourceDirectoryTableEntry[] IdEntries;
|
||||
|
||||
public static ResourceDirectoryTable Deserialize(Stream stream, long sectionStart, SectionHeader[] sections)
|
||||
{
|
||||
var rdt = new ResourceDirectoryTable();
|
||||
|
||||
rdt.Characteristics = stream.ReadUInt32();
|
||||
rdt.TimeDateStamp = stream.ReadUInt32();
|
||||
rdt.MajorVersion = stream.ReadUInt16();
|
||||
rdt.MinorVersion = stream.ReadUInt16();
|
||||
rdt.NumberOfNamedEntries = stream.ReadUInt16();
|
||||
rdt.NumberOfIdEntries = stream.ReadUInt16();
|
||||
|
||||
rdt.NamedEntries = new ResourceDirectoryTableEntry[rdt.NumberOfNamedEntries];
|
||||
for (int i = 0; i < rdt.NumberOfNamedEntries; i++)
|
||||
{
|
||||
rdt.NamedEntries[i] = ResourceDirectoryTableEntry.Deserialize(stream, sectionStart, sections);
|
||||
}
|
||||
|
||||
rdt.IdEntries = new ResourceDirectoryTableEntry[rdt.NumberOfIdEntries];
|
||||
for (int i = 0; i < rdt.NumberOfIdEntries; i++)
|
||||
{
|
||||
rdt.IdEntries[i] = ResourceDirectoryTableEntry.Deserialize(stream, sectionStart, sections);
|
||||
}
|
||||
|
||||
return rdt;
|
||||
}
|
||||
|
||||
public static ResourceDirectoryTable Deserialize(byte[] content, ref int offset, long sectionStart, SectionHeader[] sections)
|
||||
{
|
||||
var rdt = new ResourceDirectoryTable();
|
||||
|
||||
rdt.Characteristics = content.ReadUInt32(ref offset);
|
||||
rdt.TimeDateStamp = content.ReadUInt32(ref offset);
|
||||
rdt.MajorVersion = content.ReadUInt16(ref offset);
|
||||
rdt.MinorVersion = content.ReadUInt16(ref offset);
|
||||
rdt.NumberOfNamedEntries = content.ReadUInt16(ref offset);
|
||||
rdt.NumberOfIdEntries = content.ReadUInt16(ref offset);
|
||||
|
||||
rdt.NamedEntries = new ResourceDirectoryTableEntry[rdt.NumberOfNamedEntries];
|
||||
for (int i = 0; i < rdt.NumberOfNamedEntries; i++)
|
||||
{
|
||||
rdt.NamedEntries[i] = ResourceDirectoryTableEntry.Deserialize(content, ref offset, sectionStart, sections);
|
||||
}
|
||||
|
||||
rdt.IdEntries = new ResourceDirectoryTableEntry[rdt.NumberOfIdEntries];
|
||||
for (int i = 0; i < rdt.NumberOfIdEntries; i++)
|
||||
{
|
||||
rdt.IdEntries[i] = ResourceDirectoryTableEntry.Deserialize(content, ref offset, sectionStart, sections);
|
||||
}
|
||||
|
||||
return rdt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class ResourceTable
|
||||
{
|
||||
public ushort rscAlignShift;
|
||||
public TYPEINFO TypeInfo;
|
||||
public ushort rscEndTypes;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
|
||||
public sbyte[][] rscResourceNames;
|
||||
public byte rscEndNames;
|
||||
|
||||
public static ResourceTable Deserialize(Stream stream)
|
||||
{
|
||||
var rt = new ResourceTable();
|
||||
|
||||
rt.rscAlignShift = stream.ReadUInt16();
|
||||
rt.TypeInfo = TYPEINFO.Deserialize(stream);
|
||||
rt.rscEndTypes = stream.ReadUInt16();
|
||||
rt.rscResourceNames = null; // TODO: Figure out size
|
||||
rt.rscEndNames = stream.ReadByteValue();
|
||||
|
||||
return rt;
|
||||
}
|
||||
}
|
||||
}
|
||||
147
BurnOutSharp/ExecutableType/Microsoft/Resources/FixedFileInfo.cs
Normal file
147
BurnOutSharp/ExecutableType/Microsoft/Resources/FixedFileInfo.cs
Normal file
@@ -0,0 +1,147 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
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 VS_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 dwFileVersionLS 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 dwFileVersionMS 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 dwProductVersionLS 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 dwProductVersionMS to form a 64-bit value used for numeric comparisons.
|
||||
/// </summary>
|
||||
public uint ProductVersionLS;
|
||||
|
||||
/// <summary>
|
||||
/// Contains a bitmask that specifies the valid bits in dwFileFlags.
|
||||
/// 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. This member can include one or more of the following values.
|
||||
/// </summary>
|
||||
public FileInfoFileFlags FileFlags;
|
||||
|
||||
/// <summary>
|
||||
/// The operating system for which this file was designed. This member can be one of the following values.
|
||||
///
|
||||
/// An application can combine these values to indicate that the file was designed for one operating system running on another.
|
||||
/// The following dwFileOS values are examples of this, but are not a complete list.
|
||||
/// </summary>
|
||||
public FileInfoOS FileOS;
|
||||
|
||||
/// <summary>
|
||||
/// The general type of file. This member can be one of the following values. All other values are reserved.
|
||||
/// </summary>
|
||||
public FileInfoFileType FileType;
|
||||
|
||||
/// <summary>
|
||||
/// The function of the file. The possible values depend on the value of dwFileType.
|
||||
/// For all values of dwFileType not described in the following list, dwFileSubtype is zero.
|
||||
///
|
||||
/// If dwFileType is VFT_DRV, dwFileSubtype can be one of the following values.
|
||||
///
|
||||
/// If dwFileType is VFT_FONT, dwFileSubtype can be one of the following values.
|
||||
///
|
||||
/// If dwFileType is VFT_VXD, dwFileSubtype contains the virtual device identifier included in the virtual device control block.
|
||||
/// All dwFileSubtype values not listed here are reserved.
|
||||
/// </summary>
|
||||
public FileInfoFileSubtype 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;
|
||||
|
||||
public static FixedFileInfo Deserialize(Stream stream)
|
||||
{
|
||||
FixedFileInfo ffi = new FixedFileInfo();
|
||||
|
||||
ushort temp;
|
||||
while ((temp = stream.ReadUInt16()) == 0x0000);
|
||||
stream.Seek(-2, SeekOrigin.Current);
|
||||
|
||||
ffi.Signature = stream.ReadUInt32();
|
||||
ffi.StrucVersion = stream.ReadUInt32();
|
||||
ffi.FileVersionMS = stream.ReadUInt32();
|
||||
ffi.FileVersionLS = stream.ReadUInt32();
|
||||
ffi.ProductVersionMS = stream.ReadUInt32();
|
||||
ffi.ProductVersionLS = stream.ReadUInt32();
|
||||
ffi.FileFlagsMask = stream.ReadUInt32();
|
||||
ffi.FileFlags = (FileInfoFileFlags)stream.ReadUInt32();
|
||||
ffi.FileOS = (FileInfoOS)stream.ReadUInt32();
|
||||
ffi.FileType = (FileInfoFileType)stream.ReadUInt32();
|
||||
ffi.FileSubtype = (FileInfoFileSubtype)stream.ReadUInt32();
|
||||
ffi.FileDateMS = stream.ReadUInt32();
|
||||
ffi.FileDateLS = stream.ReadUInt32();
|
||||
|
||||
return ffi;
|
||||
}
|
||||
|
||||
public static FixedFileInfo Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
FixedFileInfo ffi = new FixedFileInfo();
|
||||
|
||||
ushort temp;
|
||||
bool padded = false;
|
||||
while ((temp = content.ReadUInt16(ref offset)) == 0x0000)
|
||||
{
|
||||
padded = true;
|
||||
}
|
||||
|
||||
if (padded)
|
||||
offset -= 2;
|
||||
|
||||
ffi.Signature = content.ReadUInt32(ref offset);
|
||||
ffi.StrucVersion = content.ReadUInt32(ref offset);
|
||||
ffi.FileVersionMS = content.ReadUInt32(ref offset);
|
||||
ffi.FileVersionLS = content.ReadUInt32(ref offset);
|
||||
ffi.ProductVersionMS = content.ReadUInt32(ref offset);
|
||||
ffi.ProductVersionLS = content.ReadUInt32(ref offset);
|
||||
ffi.FileFlagsMask = content.ReadUInt32(ref offset);
|
||||
ffi.FileFlags = (FileInfoFileFlags)content.ReadUInt32(ref offset);
|
||||
ffi.FileOS = (FileInfoOS)content.ReadUInt32(ref offset);
|
||||
ffi.FileType = (FileInfoFileType)content.ReadUInt32(ref offset);
|
||||
ffi.FileSubtype = (FileInfoFileSubtype)content.ReadUInt32(ref offset);
|
||||
ffi.FileDateMS = content.ReadUInt32(ref offset);
|
||||
ffi.FileDateLS = content.ReadUInt32(ref offset);
|
||||
|
||||
return ffi;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
/// <summary>
|
||||
/// If you use the Var structure to list the languages your application or DLL supports instead of using multiple version resources,
|
||||
/// use the Value member to contain an array of DWORD values indicating the language and code page combinations supported by this file.
|
||||
/// The low-order word of each DWORD must contain a Microsoft language identifier, and the high-order word must contain the IBM code page number.
|
||||
/// Either high-order or low-order word can be zero, indicating that the file is language or code page independent.
|
||||
/// If the Var structure is omitted, the file will be interpreted as both language and code page independent.
|
||||
/// </summary>
|
||||
public class LanguageCodePage
|
||||
{
|
||||
/// <summary>
|
||||
/// The low-order word of each DWORD must contain a Microsoft language identifier
|
||||
/// </summary>
|
||||
public ushort MicrosoftLanguageIdentifier;
|
||||
|
||||
/// <summary>
|
||||
/// The high-order word must contain the IBM code page number
|
||||
/// </summary>
|
||||
public ushort IBMCodePageNumber;
|
||||
|
||||
public static LanguageCodePage Deserialize(Stream stream)
|
||||
{
|
||||
LanguageCodePage lcp = new LanguageCodePage();
|
||||
|
||||
lcp.MicrosoftLanguageIdentifier = stream.ReadUInt16();
|
||||
lcp.IBMCodePageNumber = stream.ReadUInt16();
|
||||
|
||||
return lcp;
|
||||
}
|
||||
|
||||
public static LanguageCodePage Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
LanguageCodePage lcp = new LanguageCodePage();
|
||||
|
||||
lcp.MicrosoftLanguageIdentifier = content.ReadUInt16(ref offset);
|
||||
lcp.IBMCodePageNumber = content.ReadUInt16(ref offset);
|
||||
|
||||
return lcp;
|
||||
}
|
||||
}
|
||||
}
|
||||
58
BurnOutSharp/ExecutableType/Microsoft/Resources/Resource.cs
Normal file
58
BurnOutSharp/ExecutableType/Microsoft/Resources/Resource.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
public class Resource
|
||||
{
|
||||
/// <summary>
|
||||
/// The length, in bytes, of the resource structure.
|
||||
/// This length does not include any padding that aligns any subsequent version resource data on a 32-bit boundary.
|
||||
/// </summary>
|
||||
public ushort Length;
|
||||
|
||||
/// <summary>
|
||||
/// The length, in bytes, of the Value member.
|
||||
/// This value is zero if there is no Value member associated with the current version structure.
|
||||
/// </summary>
|
||||
public ushort ValueLength;
|
||||
|
||||
/// <summary>
|
||||
/// The type of data in the version resource.
|
||||
/// This member is 1 if the version resource contains text data and 0 if the version resource contains binary data.
|
||||
/// </summary>
|
||||
public ushort Type;
|
||||
|
||||
/// <summary>
|
||||
/// A Unicode string representing the key
|
||||
/// </summary>
|
||||
public string Key;
|
||||
|
||||
public static Resource Deserialize(Stream stream)
|
||||
{
|
||||
Resource r = new Resource();
|
||||
|
||||
while ((r.Length = stream.ReadUInt16()) == 0x0000);
|
||||
|
||||
r.ValueLength = stream.ReadUInt16();
|
||||
r.Type = stream.ReadUInt16();
|
||||
r.Key = stream.ReadString(Encoding.Unicode);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
public static Resource Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
Resource r = new Resource();
|
||||
|
||||
while ((r.Length = content.ReadUInt16(ref offset)) == 0x0000);
|
||||
|
||||
r.ValueLength = content.ReadUInt16(ref offset);
|
||||
r.Type = content.ReadUInt16(ref offset);
|
||||
r.Key = content.ReadString(ref offset, Encoding.Unicode);
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.IO;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
public class StringFileInfo : Resource
|
||||
{
|
||||
/// <summary>
|
||||
/// An array of one or more StringTable structures.
|
||||
/// Each StringTable structure's szKey member indicates the appropriate language and code page for displaying the text in that StringTable structure.
|
||||
/// </summary>
|
||||
public StringTable Children;
|
||||
|
||||
public StringFileInfo(Resource resource)
|
||||
{
|
||||
this.Length = resource?.Length ?? default;
|
||||
this.ValueLength = resource?.ValueLength ?? default;
|
||||
this.Type = resource?.Type ?? default;
|
||||
this.Key = resource?.Key?.TrimStart('\u0001') ?? default;
|
||||
}
|
||||
|
||||
public static new StringFileInfo Deserialize(Stream stream)
|
||||
{
|
||||
Resource resource = Resource.Deserialize(stream);
|
||||
if (resource.Key != "StringFileInfo" && resource.Key != "\u0001StringFileInfo")
|
||||
return null;
|
||||
|
||||
StringFileInfo sfi = new StringFileInfo(resource);
|
||||
sfi.Children = StringTable.Deserialize(stream);
|
||||
|
||||
return sfi;
|
||||
}
|
||||
|
||||
public static new StringFileInfo Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
Resource resource = Resource.Deserialize(content, ref offset);
|
||||
if (resource.Key != "StringFileInfo" && resource.Key != "\u0001StringFileInfo")
|
||||
return null;
|
||||
|
||||
StringFileInfo sfi = new StringFileInfo(resource);
|
||||
sfi.Children = StringTable.Deserialize(content, ref offset);
|
||||
|
||||
return sfi;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
public class StringStruct : Resource
|
||||
{
|
||||
/// <summary>
|
||||
/// Typically contains a list of languages that the application or DLL supports.
|
||||
/// </summary>
|
||||
public string Value;
|
||||
|
||||
public StringStruct(Resource resource)
|
||||
{
|
||||
this.Length = resource?.Length ?? default;
|
||||
this.ValueLength = resource?.ValueLength ?? default;
|
||||
this.Type = resource?.Type ?? default;
|
||||
this.Key = resource?.Key ?? default;
|
||||
}
|
||||
|
||||
public static new StringStruct Deserialize(Stream stream)
|
||||
{
|
||||
Resource resource = Resource.Deserialize(stream);
|
||||
StringStruct s = new StringStruct(resource);
|
||||
stream.Seek(stream.Position % 4 == 0 ? 0 : 4 - (stream.Position % 4), SeekOrigin.Current);
|
||||
s.Value = new string(stream.ReadChars(s.ValueLength));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
public static new StringStruct Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
Resource resource = Resource.Deserialize(content, ref offset);
|
||||
StringStruct s = new StringStruct(resource);
|
||||
offset += offset % 4 == 0 ? 0 : 4 - (offset % 4);
|
||||
s.Value = Encoding.Unicode.GetString(content, offset, s.ValueLength * 2); offset += s.ValueLength * 2;
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
public class StringTable : Resource
|
||||
{
|
||||
/// <summary>
|
||||
/// An array of one or more String structures.
|
||||
/// </summary>
|
||||
public StringStruct[] Children;
|
||||
|
||||
public StringTable(Resource resource)
|
||||
{
|
||||
this.Length = resource?.Length ?? default;
|
||||
this.ValueLength = resource?.ValueLength ?? default;
|
||||
this.Type = resource?.Type ?? default;
|
||||
this.Key = resource?.Key ?? default;
|
||||
}
|
||||
|
||||
public static new StringTable Deserialize(Stream stream)
|
||||
{
|
||||
long originalPosition = stream.Position;
|
||||
Resource resource = Resource.Deserialize(stream);
|
||||
if (resource.Key.Length != 8)
|
||||
return null;
|
||||
|
||||
StringTable st = new StringTable(resource);
|
||||
|
||||
var tempValue = new List<StringStruct>();
|
||||
while (stream.Position - originalPosition < st.Length)
|
||||
{
|
||||
tempValue.Add(StringStruct.Deserialize(stream));
|
||||
}
|
||||
|
||||
st.Children = tempValue.ToArray();
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
public static new StringTable Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
int originalPosition = offset;
|
||||
Resource resource = Resource.Deserialize(content, ref offset);
|
||||
if (resource.Key.Length != 8)
|
||||
return null;
|
||||
|
||||
StringTable st = new StringTable(resource);
|
||||
|
||||
var tempValue = new List<StringStruct>();
|
||||
while (offset - originalPosition < st.Length)
|
||||
{
|
||||
tempValue.Add(StringStruct.Deserialize(content, ref offset));
|
||||
}
|
||||
|
||||
st.Children = tempValue.ToArray();
|
||||
|
||||
return st;
|
||||
}
|
||||
}
|
||||
}
|
||||
67
BurnOutSharp/ExecutableType/Microsoft/Resources/Var.cs
Normal file
67
BurnOutSharp/ExecutableType/Microsoft/Resources/Var.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
public class Var : Resource
|
||||
{
|
||||
/// <summary>
|
||||
/// An array of one or more values that are language and code page identifier pairs.
|
||||
///
|
||||
/// If you use the Var structure to list the languages your application or DLL supports instead of using multiple version resources,
|
||||
/// use the Value member to contain an array of DWORD values indicating the language and code page combinations supported by this file.
|
||||
/// The low-order word of each DWORD must contain a Microsoft language identifier, and the high-order word must contain the IBM code page number.
|
||||
/// Either high-order or low-order word can be zero, indicating that the file is language or code page independent.
|
||||
/// If the Var structure is omitted, the file will be interpreted as both language and code page independent.
|
||||
/// </summary>
|
||||
public LanguageCodePage[] Value;
|
||||
|
||||
public Var(Resource resource)
|
||||
{
|
||||
this.Length = resource?.Length ?? default;
|
||||
this.ValueLength = resource?.ValueLength ?? default;
|
||||
this.Type = resource?.Type ?? default;
|
||||
this.Key = resource?.Key ?? default;
|
||||
}
|
||||
|
||||
public static new Var Deserialize(Stream stream)
|
||||
{
|
||||
long originalPosition = stream.Position;
|
||||
Resource resource = Resource.Deserialize(stream);
|
||||
if (resource.Key != "Translation")
|
||||
return null;
|
||||
|
||||
Var v = new Var(resource);
|
||||
|
||||
var tempValue = new List<LanguageCodePage>();
|
||||
while (stream.Position - originalPosition < v.Length)
|
||||
{
|
||||
tempValue.Add(LanguageCodePage.Deserialize(stream));
|
||||
}
|
||||
|
||||
v.Value = tempValue.ToArray();
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public static new Var Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
int originalPosition = offset;
|
||||
Resource resource = Resource.Deserialize(content, ref offset);
|
||||
if (resource.Key != "Translation")
|
||||
return null;
|
||||
|
||||
Var v = new Var(resource);
|
||||
|
||||
var tempValue = new List<LanguageCodePage>();
|
||||
while (offset - originalPosition < v.Length)
|
||||
{
|
||||
tempValue.Add(LanguageCodePage.Deserialize(content, ref offset));
|
||||
}
|
||||
|
||||
v.Value = tempValue.ToArray();
|
||||
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System.IO;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
public class VarFileInfo : Resource
|
||||
{
|
||||
/// <summary>
|
||||
/// Typically contains a list of languages that the application or DLL supports.
|
||||
/// </summary>
|
||||
public Var Children;
|
||||
|
||||
public VarFileInfo(Resource resource)
|
||||
{
|
||||
this.Length = resource?.Length ?? default;
|
||||
this.ValueLength = resource?.ValueLength ?? default;
|
||||
this.Type = resource?.Type ?? default;
|
||||
this.Key = resource?.Key ?? default;
|
||||
}
|
||||
|
||||
public static new VarFileInfo Deserialize(Stream stream)
|
||||
{
|
||||
Resource resource = Resource.Deserialize(stream);
|
||||
if (resource.Key != "VarFileInfo")
|
||||
return null;
|
||||
|
||||
VarFileInfo vfi = new VarFileInfo(resource);
|
||||
vfi.Children = Var.Deserialize(stream);
|
||||
|
||||
return vfi;
|
||||
}
|
||||
|
||||
public static new VarFileInfo Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
Resource resource = Resource.Deserialize(content, ref offset);
|
||||
if (resource.Key != "VarFileInfo")
|
||||
return null;
|
||||
|
||||
VarFileInfo vfi = new VarFileInfo(resource);
|
||||
vfi.Children = Var.Deserialize(content, ref offset);
|
||||
|
||||
return vfi;
|
||||
}
|
||||
}
|
||||
}
|
||||
129
BurnOutSharp/ExecutableType/Microsoft/Resources/VersionInfo.cs
Normal file
129
BurnOutSharp/ExecutableType/Microsoft/Resources/VersionInfo.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
using System.IO;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
{
|
||||
public class VersionInfo : Resource
|
||||
{
|
||||
/// <summary>
|
||||
/// Arbitrary data associated with this VS_VERSIONINFO structure.
|
||||
/// The wValueLength member specifies the length of this member;
|
||||
/// if wValueLength is zero, this member does not exist.
|
||||
/// </summary>
|
||||
public FixedFileInfo Value;
|
||||
|
||||
/// <summary>
|
||||
/// An array of zero or one StringFileInfo structures, and zero or one VarFileInfo structures
|
||||
/// that are children of the current VS_VERSIONINFO structure.
|
||||
/// </summary>
|
||||
public StringFileInfo ChildrenStringFileInfo;
|
||||
|
||||
/// <summary>
|
||||
/// An array of zero or one StringFileInfo structures, and zero or one VarFileInfo structures
|
||||
/// that are children of the current VS_VERSIONINFO structure.
|
||||
/// </summary>
|
||||
public VarFileInfo ChildrenVarFileInfo;
|
||||
|
||||
public VersionInfo(Resource resource)
|
||||
{
|
||||
this.Length = resource?.Length ?? default;
|
||||
this.ValueLength = resource?.ValueLength ?? default;
|
||||
this.Type = resource?.Type ?? default;
|
||||
this.Key = resource?.Key ?? default;
|
||||
}
|
||||
|
||||
public static new VersionInfo Deserialize(Stream stream)
|
||||
{
|
||||
long originalPosition = stream.Position;
|
||||
Resource resource = Resource.Deserialize(stream);
|
||||
if (resource.Key != "VS_VERSION_INFO")
|
||||
return null;
|
||||
|
||||
VersionInfo vi = new VersionInfo(resource);
|
||||
|
||||
if (vi.ValueLength > 0)
|
||||
vi.Value = FixedFileInfo.Deserialize(stream);
|
||||
|
||||
if (stream.Position - originalPosition > vi.Length)
|
||||
return vi;
|
||||
|
||||
long preChildOffset = stream.Position;
|
||||
Resource firstChild = Resource.Deserialize(stream);
|
||||
if (firstChild.Key == "StringFileInfo" || firstChild.Key == "\u0001StringFileInfo")
|
||||
{
|
||||
stream.Seek(preChildOffset, SeekOrigin.Begin);
|
||||
vi.ChildrenStringFileInfo = StringFileInfo.Deserialize(stream);
|
||||
}
|
||||
else if (firstChild.Key == "VarFileInfo" || firstChild.Key == "\u0001VarFileInfo")
|
||||
{
|
||||
stream.Seek(preChildOffset, SeekOrigin.Begin);
|
||||
vi.ChildrenVarFileInfo = VarFileInfo.Deserialize(stream);
|
||||
}
|
||||
|
||||
if (stream.Position - originalPosition > vi.Length)
|
||||
return vi;
|
||||
|
||||
preChildOffset = stream.Position;
|
||||
Resource secondChild = Resource.Deserialize(stream);
|
||||
if (secondChild.Key == "StringFileInfo" || secondChild.Key == "\u0001StringFileInfo")
|
||||
{
|
||||
stream.Seek(preChildOffset, SeekOrigin.Begin);
|
||||
vi.ChildrenStringFileInfo = StringFileInfo.Deserialize(stream);
|
||||
}
|
||||
else if (secondChild.Key == "VarFileInfo" || secondChild.Key == "\u0001VarFileInfo")
|
||||
{
|
||||
stream.Seek(preChildOffset, SeekOrigin.Begin);
|
||||
vi.ChildrenVarFileInfo = VarFileInfo.Deserialize(stream);
|
||||
}
|
||||
|
||||
return vi;
|
||||
}
|
||||
|
||||
public static new VersionInfo Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
int originalOffset = offset;
|
||||
Resource resource = Resource.Deserialize(content, ref offset);
|
||||
if (resource.Key != "VS_VERSION_INFO")
|
||||
return null;
|
||||
|
||||
VersionInfo vi = new VersionInfo(resource);
|
||||
|
||||
if (vi.ValueLength > 0)
|
||||
vi.Value = FixedFileInfo.Deserialize(content, ref offset);
|
||||
|
||||
if (offset - originalOffset > vi.Length)
|
||||
return vi;
|
||||
|
||||
int preChildOffset = offset;
|
||||
Resource firstChild = Resource.Deserialize(content, ref offset);
|
||||
if (firstChild.Key == "StringFileInfo" || firstChild.Key == "\u0001StringFileInfo")
|
||||
{
|
||||
offset = preChildOffset;
|
||||
vi.ChildrenStringFileInfo = StringFileInfo.Deserialize(content, ref offset);
|
||||
}
|
||||
else if (firstChild.Key == "VarFileInfo" || firstChild.Key == "\u0001VarFileInfo")
|
||||
{
|
||||
offset = preChildOffset;
|
||||
vi.ChildrenVarFileInfo = VarFileInfo.Deserialize(content, ref offset);
|
||||
}
|
||||
|
||||
if (offset - originalOffset > vi.Length)
|
||||
return vi;
|
||||
|
||||
|
||||
preChildOffset = offset;
|
||||
Resource secondChild = Resource.Deserialize(content, ref offset);
|
||||
if (secondChild.Key == "StringFileInfo" || secondChild.Key == "\u0001StringFileInfo")
|
||||
{
|
||||
offset = preChildOffset;
|
||||
vi.ChildrenStringFileInfo = StringFileInfo.Deserialize(content, ref offset);
|
||||
}
|
||||
else if (secondChild.Key == "VarFileInfo" || secondChild.Key == "\u0001VarFileInfo")
|
||||
{
|
||||
offset = preChildOffset;
|
||||
vi.ChildrenVarFileInfo = VarFileInfo.Deserialize(content, ref offset);
|
||||
}
|
||||
|
||||
return vi;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
/// <summary>
|
||||
/// Resource name information block
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class RsrcNameInfo
|
||||
{
|
||||
/*
|
||||
* The following two fields must be shifted left by the value of
|
||||
* the rs_align field to compute their actual value. This allows
|
||||
* resources to be larger than 64k, but they do not need to be
|
||||
* aligned on 512 byte boundaries, the way segments are.
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// File offset to resource data
|
||||
/// </summary>
|
||||
public ushort Offset;
|
||||
|
||||
/// <summary>
|
||||
/// Length of resource data
|
||||
/// </summary>
|
||||
public ushort Length;
|
||||
|
||||
/// <summary>
|
||||
/// Resource flags
|
||||
/// </summary>
|
||||
public ushort Flags;
|
||||
|
||||
/// <summary>
|
||||
/// Resource name id
|
||||
/// </summary>
|
||||
public ushort NameID;
|
||||
|
||||
/// <summary>
|
||||
/// If loaded, then global handle
|
||||
/// </summary>
|
||||
public ushort Handle;
|
||||
|
||||
/// <summary>
|
||||
/// Initially zero. Number of times the handle for this resource has been given out
|
||||
/// </summary>
|
||||
public ushort UsageCount;
|
||||
|
||||
public static RsrcNameInfo Deserialize(Stream stream)
|
||||
{
|
||||
var rni = new RsrcNameInfo();
|
||||
|
||||
rni.Offset = stream.ReadUInt16();
|
||||
rni.Length = stream.ReadUInt16();
|
||||
rni.Flags = stream.ReadUInt16();
|
||||
rni.NameID = stream.ReadUInt16();
|
||||
rni.Handle = stream.ReadUInt16();
|
||||
rni.UsageCount = stream.ReadUInt16();
|
||||
|
||||
return rni;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
/// <summary>
|
||||
/// Resource type or name string
|
||||
/// </summary>
|
||||
/// TODO: Fix this because SizeConst = 0 is not valid
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class RsrcString
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of bytes in string
|
||||
/// </summary>
|
||||
public byte Length;
|
||||
|
||||
/// <summary>
|
||||
/// Next of string
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
|
||||
public char[] Text;
|
||||
|
||||
public static RsrcString Deserialize(Stream stream)
|
||||
{
|
||||
var rs = new RsrcString();
|
||||
|
||||
rs.Length = stream.ReadByteValue();
|
||||
rs.Text = stream.ReadChars(rs.Length);
|
||||
|
||||
return rs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
/// <summary>
|
||||
/// Resource type information block
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class RsrcTypeInfo
|
||||
{
|
||||
public ushort ID;
|
||||
public ushort rt_nres;
|
||||
public uint rt_proc;
|
||||
|
||||
public static RsrcTypeInfo Deserialize(Stream stream)
|
||||
{
|
||||
var rti = new RsrcTypeInfo();
|
||||
|
||||
rti.ID = stream.ReadUInt16();
|
||||
rti.rt_nres = stream.ReadUInt16();
|
||||
rti.rt_proc = stream.ReadUInt32();
|
||||
|
||||
return rti;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
|
||||
*
|
||||
* Data structure definitions for the OS/2 & Windows
|
||||
* executable file format.
|
||||
*
|
||||
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
|
||||
* (C) Copyright IVS 1991
|
||||
*
|
||||
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal class TYPEINFO
|
||||
{
|
||||
public ushort TypeID;
|
||||
public ushort ResourceCount;
|
||||
public uint Reserved;
|
||||
public NAMEINFO NameInfo;
|
||||
|
||||
public static TYPEINFO Deserialize(Stream stream)
|
||||
{
|
||||
var ti = new TYPEINFO();
|
||||
|
||||
ti.TypeID = stream.ReadUInt16();
|
||||
ti.ResourceCount = stream.ReadUInt16();
|
||||
ti.Reserved = stream.ReadUInt32();
|
||||
ti.NameInfo = NAMEINFO.Deserialize(stream);
|
||||
|
||||
return ti;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace BurnOutSharp
|
||||
{
|
||||
internal static class Ebuffertensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Read a byte from the stream
|
||||
/// </summary>
|
||||
public static byte ReadByteValue(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[1];
|
||||
stream.Read(buffer, 0, 1);
|
||||
return buffer[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a byte array from the stream
|
||||
/// </summary>
|
||||
public static byte[] ReadBytes(this Stream stream, int count)
|
||||
{
|
||||
byte[] buffer = new byte[count];
|
||||
stream.Read(buffer, 0, count);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a character from the stream
|
||||
/// </summary>
|
||||
public static char ReadChar(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[1];
|
||||
stream.Read(buffer, 0, 1);
|
||||
return (char)buffer[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a character array from the stream
|
||||
/// </summary>
|
||||
public static char[] ReadChars(this Stream stream, int count)
|
||||
{
|
||||
byte[] buffer = new byte[count];
|
||||
stream.Read(buffer, 0, count);
|
||||
return Encoding.Default.GetString(buffer).ToCharArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a short from the stream
|
||||
/// </summary>
|
||||
public static short ReadInt16(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[2];
|
||||
stream.Read(buffer, 0, 2);
|
||||
return BitConverter.ToInt16(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a ushort from the stream
|
||||
/// </summary>
|
||||
public static ushort ReadUInt16(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[2];
|
||||
stream.Read(buffer, 0, 2);
|
||||
return BitConverter.ToUInt16(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read an int from the stream
|
||||
/// </summary>
|
||||
public static int ReadInt32(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[4];
|
||||
stream.Read(buffer, 0, 4);
|
||||
return BitConverter.ToInt32(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a uint from the stream
|
||||
/// </summary>
|
||||
public static uint ReadUInt32(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[4];
|
||||
stream.Read(buffer, 0, 4);
|
||||
return BitConverter.ToUInt32(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a long from the stream
|
||||
/// </summary>
|
||||
public static long ReadInt64(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[8];
|
||||
stream.Read(buffer, 0, 8);
|
||||
return BitConverter.ToInt64(buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a ulong from the stream
|
||||
/// </summary>
|
||||
public static ulong ReadUInt64(this Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[8];
|
||||
stream.Read(buffer, 0, 8);
|
||||
return BitConverter.ToUInt64(buffer, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
1
BurnOutSharp/External/LessIO
vendored
1
BurnOutSharp/External/LessIO
vendored
Submodule BurnOutSharp/External/LessIO deleted from 1def7d19cc
8
BurnOutSharp/External/README.MD
vendored
Normal file
8
BurnOutSharp/External/README.MD
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# External Library Notes
|
||||
|
||||
This directory contains multiple external libraries. Here is the status of each:
|
||||
|
||||
| Directory | Library | Status |
|
||||
| --------- | ------- | ------ |
|
||||
| psxt001z | [psxt001z](https://github.com/Dremora/psxt001z) | 90% ported to C#, device reading disabled |
|
||||
| stormlibsharp | [stormlibsharp](https://github.com/robpaveza/stormlibsharp) | External submodule |
|
||||
1
BurnOutSharp/External/WixToolset
vendored
1
BurnOutSharp/External/WixToolset
vendored
Submodule BurnOutSharp/External/WixToolset deleted from 43e22fe96a
1
BurnOutSharp/External/hllib
vendored
1
BurnOutSharp/External/hllib
vendored
Submodule BurnOutSharp/External/hllib deleted from 2063e3e0cd
1
BurnOutSharp/External/libmspack4n
vendored
1
BurnOutSharp/External/libmspack4n
vendored
Submodule BurnOutSharp/External/libmspack4n deleted from 7213a361f8
6
BurnOutSharp/External/psxt001z/CRC16.cs
vendored
6
BurnOutSharp/External/psxt001z/CRC16.cs
vendored
@@ -1,9 +1,9 @@
|
||||
namespace BurnOutSharp.External.psxt001z
|
||||
namespace psxt001z
|
||||
{
|
||||
public class CRC16
|
||||
{
|
||||
// Table of CRC constants - implements x^16+x^12+x^5+1
|
||||
private static ushort[] crc16_tab = new ushort[]
|
||||
private static ushort[] CRC16Table = new ushort[]
|
||||
{
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
|
||||
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
|
||||
@@ -44,7 +44,7 @@
|
||||
ushort cksum = 0;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
cksum = (ushort)(crc16_tab[((cksum >> 8) ^ buf[bufPtr++]) & 0xFF] ^ (cksum << 8));
|
||||
cksum = (ushort)(CRC16Table[((cksum >> 8) ^ buf[bufPtr++]) & 0xFF] ^ (cksum << 8));
|
||||
}
|
||||
|
||||
return (ushort)(~cksum);
|
||||
|
||||
57
BurnOutSharp/External/psxt001z/CRC32.cs
vendored
Normal file
57
BurnOutSharp/External/psxt001z/CRC32.cs
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
namespace psxt001z
|
||||
{
|
||||
internal class CRC32
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const uint CRC_POLY = 0xEDB88320;
|
||||
|
||||
private const uint CRC_MASK = 0xD202EF8D;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
protected uint[] Table { get; private set; } = new uint[256];
|
||||
|
||||
public uint m_crc32 { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public CRC32()
|
||||
{
|
||||
for (uint i = 0; i < 256; i++)
|
||||
{
|
||||
uint r, j;
|
||||
for (r = i, j = 8; j != 0; j--)
|
||||
{
|
||||
r = ((r & 1) != 0) ? (r >> 1) ^ CRC_POLY : r >> 1;
|
||||
}
|
||||
|
||||
Table[i] = r;
|
||||
}
|
||||
|
||||
m_crc32 = 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functions
|
||||
|
||||
public void ProcessCRC(byte[] pData, int pDataPtr, int nLen)
|
||||
{
|
||||
uint crc = m_crc32;
|
||||
while (nLen-- != 0)
|
||||
{
|
||||
crc = Table[(byte)(crc ^ pData[pDataPtr++])] ^ crc >> 8;
|
||||
crc ^= CRC_MASK;
|
||||
}
|
||||
|
||||
m_crc32 = crc;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
19
BurnOutSharp/External/psxt001z/Common.cs
vendored
Normal file
19
BurnOutSharp/External/psxt001z/Common.cs
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace psxt001z
|
||||
{
|
||||
public static class Common
|
||||
{
|
||||
public const int ZERO = 0;
|
||||
|
||||
public const string VERSION = "v0.21 beta 1";
|
||||
|
||||
/// <summary>
|
||||
/// BCD to u_char
|
||||
/// </summary>
|
||||
public static byte btoi(byte b) => (byte)(((b) / 16 * 10 + (b) % 16));
|
||||
|
||||
/// <summary>
|
||||
/// u_char to BCD
|
||||
/// </summary>
|
||||
public static byte itob(byte i) => (byte)(((i) / 10 * 16 + (i) % 10));
|
||||
}
|
||||
}
|
||||
178
BurnOutSharp/External/psxt001z/FileTools.cs
vendored
Normal file
178
BurnOutSharp/External/psxt001z/FileTools.cs
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace psxt001z
|
||||
{
|
||||
internal class FileTools
|
||||
{
|
||||
#region Properties
|
||||
|
||||
private Stream InputStream { get; set; }
|
||||
|
||||
private byte[] ExeName { get; set; } = new byte[20];
|
||||
|
||||
private byte[] DateValue { get; set; } = new byte[11];
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public FileTools(Stream file)
|
||||
{
|
||||
InputStream = file;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functions
|
||||
|
||||
/// <summary>
|
||||
/// Get file size
|
||||
/// </summary>
|
||||
public long size() => InputStream.Length;
|
||||
|
||||
/// <summary>
|
||||
/// Get executable name
|
||||
/// </summary>
|
||||
public string exe()
|
||||
{
|
||||
InputStream.Seek(51744, SeekOrigin.Begin);
|
||||
|
||||
string filename = string.Empty;
|
||||
while (filename != "SYSTEM.CNF")
|
||||
{
|
||||
byte[] buf = new byte[10];
|
||||
InputStream.Read(buf, 0, 10);
|
||||
filename = Encoding.ASCII.GetString(buf);
|
||||
InputStream.Seek(-9, SeekOrigin.Current);
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[20];
|
||||
|
||||
InputStream.Seek(-32, SeekOrigin.Current);
|
||||
InputStream.Read(buffer, 0, 4);
|
||||
uint lba = BitConverter.ToUInt32(buffer, 0);
|
||||
|
||||
InputStream.Seek((2352 * lba) + 29, SeekOrigin.Begin);
|
||||
InputStream.Read(buffer, 0, 6);
|
||||
|
||||
string iniLine = Encoding.ASCII.GetString(buffer);
|
||||
while (iniLine != "cdrom:")
|
||||
{
|
||||
InputStream.Seek(-5, SeekOrigin.Current);
|
||||
InputStream.Read(buffer, 0, 6);
|
||||
iniLine = Encoding.ASCII.GetString(buffer);
|
||||
}
|
||||
|
||||
InputStream.Read(buffer, 0, 1);
|
||||
if (buffer[0] != '\\')
|
||||
InputStream.Seek(-1, SeekOrigin.Current);
|
||||
|
||||
int i = -1;
|
||||
do
|
||||
{
|
||||
InputStream.Read(buffer, ++i, 1);
|
||||
} while (buffer[i] != ';');
|
||||
|
||||
for (long a = 0; a < i; a++)
|
||||
{
|
||||
ExeName[a] = (byte)char.ToUpper((char)buffer[a]);
|
||||
}
|
||||
|
||||
return Encoding.ASCII.GetString(ExeName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get human-readable date
|
||||
/// </summary>
|
||||
public string date()
|
||||
{
|
||||
byte[] buffer = new byte[12], datenofrmt = new byte[3];
|
||||
|
||||
InputStream.Seek(51744, SeekOrigin.Begin);
|
||||
|
||||
do
|
||||
{
|
||||
InputStream.Read(buffer, 0, 11);
|
||||
buffer[11] = 0;
|
||||
InputStream.Seek(-10, SeekOrigin.Current);
|
||||
} while (Encoding.ASCII.GetString(ExeName) != Encoding.ASCII.GetString(buffer));
|
||||
|
||||
InputStream.Seek(-16, SeekOrigin.Current);
|
||||
InputStream.Read(datenofrmt, 0, 3);
|
||||
|
||||
if (datenofrmt[0] < 50)
|
||||
{
|
||||
byte[] year = Encoding.ASCII.GetBytes($"{2000 + datenofrmt[0]}");
|
||||
Array.Copy(year, 0, buffer, 0, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] year = Encoding.ASCII.GetBytes($"{1900 + datenofrmt[0]}");
|
||||
Array.Copy(year, 0, buffer, 0, 4);
|
||||
}
|
||||
|
||||
DateValue[4] = (byte)'-';
|
||||
if (datenofrmt[1] < 10)
|
||||
{
|
||||
byte[] month = Encoding.ASCII.GetBytes($"0{datenofrmt[1]}");
|
||||
Array.Copy(month, 0, buffer, 5, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] month = Encoding.ASCII.GetBytes($"{datenofrmt[1]}");
|
||||
Array.Copy(month, 0, buffer, 5, 2);
|
||||
}
|
||||
|
||||
DateValue[7] = (byte)'-';
|
||||
if (datenofrmt[2] < 10)
|
||||
{
|
||||
byte[] day = Encoding.ASCII.GetBytes($"0{datenofrmt[2]}");
|
||||
Array.Copy(day, 0, buffer, 8, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] day = Encoding.ASCII.GetBytes($"{datenofrmt[2]}");
|
||||
Array.Copy(day, 0, buffer, 8, 2);
|
||||
}
|
||||
|
||||
return Encoding.ASCII.GetString(DateValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resize the image
|
||||
/// </summary>
|
||||
public int resize(long newsize)
|
||||
{
|
||||
long oldsize = size();
|
||||
if (oldsize < newsize)
|
||||
{
|
||||
InputStream.SetLength(newsize);
|
||||
return 1;
|
||||
}
|
||||
else if (oldsize > newsize)
|
||||
{
|
||||
InputStream.SetLength(newsize);
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the reported sector count from the image
|
||||
/// </summary>
|
||||
public int imagesize()
|
||||
{
|
||||
InputStream.Seek(0x9368, SeekOrigin.Begin);
|
||||
byte[] sizebuf = new byte[4];
|
||||
InputStream.Read(sizebuf, 0, 4);
|
||||
return BitConverter.ToInt32(sizebuf, 0);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
108
BurnOutSharp/External/psxt001z/Functions.cs
vendored
Normal file
108
BurnOutSharp/External/psxt001z/Functions.cs
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using static psxt001z.Common;
|
||||
|
||||
namespace psxt001z
|
||||
{
|
||||
internal static class Functions
|
||||
{
|
||||
public static int CalculateEDC(in byte[] src, int srcPtr, int size, int[] edc_lut)
|
||||
{
|
||||
int edc = 0;
|
||||
while (size-- != 0)
|
||||
{
|
||||
edc = (edc >> 8) ^ edc_lut[(edc ^ src[srcPtr++]) & 0xFF];
|
||||
}
|
||||
|
||||
return edc;
|
||||
}
|
||||
|
||||
public static bool ZeroCompare(byte[] buffer, int bufferPtr, int bsize)
|
||||
{
|
||||
for (int i = 0; i < bsize; i++)
|
||||
{
|
||||
if (buffer[bufferPtr + i] != 0x00)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void MSF(long lba, byte[] buffer, int bufferOffset)
|
||||
{
|
||||
lba += 150;
|
||||
|
||||
double mindbl = lba / 60 / 75;
|
||||
byte min = (byte)Math.Floor(mindbl);
|
||||
double secdbl = (lba - (min * 60 * 75)) / 75;
|
||||
byte sec = (byte)Math.Floor(secdbl);
|
||||
byte frame = (byte)(lba - (min * 60 * 75) - (sec * 75));
|
||||
|
||||
buffer[bufferOffset] = itob(min);
|
||||
buffer[bufferOffset + 1] = itob(sec);
|
||||
buffer[bufferOffset + 2] = itob(frame);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public static bool GetEDCStatus(Stream file)
|
||||
{
|
||||
long currentposition = file.Position;
|
||||
|
||||
file.Seek(30572, SeekOrigin.Begin);
|
||||
|
||||
byte[] buffer = new byte[4];
|
||||
file.Read(buffer, 0, 4);
|
||||
|
||||
file.Seek(currentposition, SeekOrigin.Begin);
|
||||
|
||||
return BitConverter.ToInt32(buffer, 0) == 0;
|
||||
}
|
||||
|
||||
public static byte[] ExecutableName(Stream file)
|
||||
{
|
||||
byte[] buffer = new byte[20];
|
||||
byte[] exename = new byte[20];
|
||||
|
||||
//Searching for SYSTEM.CNF
|
||||
file.Seek(51744, SeekOrigin.Begin);
|
||||
while (Encoding.ASCII.GetString(buffer) != "SYSTEM.CNF")
|
||||
{
|
||||
file.Read(buffer, 0, 10);
|
||||
buffer[10] = 0;
|
||||
file.Seek(-9, SeekOrigin.Current);
|
||||
}
|
||||
|
||||
file.Seek(-32, SeekOrigin.Current);
|
||||
byte[] lba = new byte[4];
|
||||
file.Read(lba, 0, 4);
|
||||
file.Seek((2352 * BitConverter.ToInt32(lba, 0)) + 29, SeekOrigin.Begin);
|
||||
file.Read(buffer, 0, 6);
|
||||
buffer[6] = 0;
|
||||
while (Encoding.ASCII.GetString(buffer) != "cdrom:")
|
||||
{
|
||||
file.Seek(-5, SeekOrigin.Current);
|
||||
file.Read(buffer, 0, 6);
|
||||
}
|
||||
|
||||
file.Read(buffer, 0, 1);
|
||||
if (buffer[0] != '\\')
|
||||
file.Seek(-1, SeekOrigin.Current);
|
||||
|
||||
int i = -1;
|
||||
do
|
||||
{
|
||||
file.Read(buffer, ++i, 1);
|
||||
} while (buffer[i] != ';');
|
||||
|
||||
for (int a = 0; a < i; a++)
|
||||
{
|
||||
exename[a] = (byte)char.ToUpper((char)buffer[a]);
|
||||
}
|
||||
|
||||
exename[i] = 0;
|
||||
return exename;
|
||||
}
|
||||
}
|
||||
}
|
||||
293
BurnOutSharp/External/psxt001z/Info.cs
vendored
Normal file
293
BurnOutSharp/External/psxt001z/Info.cs
vendored
Normal file
@@ -0,0 +1,293 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using static psxt001z.Functions;
|
||||
|
||||
namespace psxt001z
|
||||
{
|
||||
public class Info
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private static readonly byte[] edc_form_2 = { 0x3F, 0x13, 0xB0, 0xBE };
|
||||
|
||||
private static readonly byte[] syncheader = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
private static readonly byte[] subheader = { 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00 };
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functions
|
||||
|
||||
public static int GetInfo(string filename, bool fix)
|
||||
{
|
||||
// Variables
|
||||
bool errors = false;
|
||||
byte[] buffer = new byte[2352], buffer2 = new byte[2352];
|
||||
int mode = 15; // synñheader[15];
|
||||
|
||||
#region Opening image
|
||||
|
||||
Stream image;
|
||||
try
|
||||
{
|
||||
FileAccess open_mode = fix ? FileAccess.ReadWrite : FileAccess.Read;
|
||||
image = File.Open(filename, FileMode.Open, open_mode);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.Error.WriteLine(ex);
|
||||
return 1;
|
||||
}
|
||||
|
||||
long size = image.Length;
|
||||
Console.WriteLine($"File: {filename}");
|
||||
|
||||
#endregion
|
||||
|
||||
#region Type
|
||||
|
||||
image.Read(buffer, 0, 12);
|
||||
|
||||
int sectorsize;
|
||||
if (buffer.Take(12).SequenceEqual(syncheader.Take(12)))
|
||||
{
|
||||
sectorsize = 2352;
|
||||
}
|
||||
else
|
||||
{
|
||||
sectorsize = 2048;
|
||||
}
|
||||
if (size % sectorsize != 0)
|
||||
{
|
||||
Console.WriteLine($"{filename}: not ModeX/{sectorsize} image!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
long sectors = size / sectorsize;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mode
|
||||
|
||||
if (sectorsize == 2352)
|
||||
{
|
||||
image.Seek(0xF, SeekOrigin.Begin);
|
||||
mode = image.ReadByte();
|
||||
if (mode != 1 && mode != 2)
|
||||
{
|
||||
Console.WriteLine($"{filename}: unknown mode!");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mode = -1;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Size
|
||||
|
||||
image.Seek(sectorsize * 16 + ((mode == 2) ? 24 : ((mode == 1) ? 16 : 0)) + 0x50, SeekOrigin.Begin);
|
||||
|
||||
// ISO size
|
||||
byte[] buf = new byte[4];
|
||||
image.Read(buf, 0, 4);
|
||||
int realsectors = BitConverter.ToInt32(buf, 0);
|
||||
|
||||
image.Seek(0, SeekOrigin.Begin);
|
||||
int realsize = realsectors * sectorsize;
|
||||
if (sectors == realsectors)
|
||||
{
|
||||
Console.WriteLine($"Size (bytes): {size} (OK)");
|
||||
Console.WriteLine($"Size (sectors): {sectors} (OK)");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Size (bytes): {size}");
|
||||
Console.WriteLine($"From image: {realsize}");
|
||||
Console.WriteLine($"Size (sectors): {sectors}");
|
||||
Console.WriteLine($"From image: {realsectors}");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mode
|
||||
|
||||
if (mode > 0)
|
||||
Console.WriteLine($"Mode: {mode}");
|
||||
|
||||
if (mode == 2)
|
||||
{
|
||||
#region EDC in Form 2
|
||||
|
||||
bool imageedc = GetEDCStatus(image);
|
||||
Console.WriteLine($"EDC in Form 2 sectors: {(imageedc ? "YES" : "NO")}");
|
||||
|
||||
#endregion
|
||||
|
||||
#region Sysarea
|
||||
|
||||
string systemArea = "System area: ";
|
||||
image.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
CRC32 crc = new CRC32();
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
image.Read(buffer, 0, 2352);
|
||||
crc.ProcessCRC(buffer, 0, 2352);
|
||||
}
|
||||
|
||||
uint imagecrc = crc.m_crc32;
|
||||
systemArea += GetEdcType(imagecrc);
|
||||
|
||||
Console.WriteLine(systemArea);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Postgap
|
||||
|
||||
image.Seek((sectors - 150) * sectorsize + 16, SeekOrigin.Begin);
|
||||
image.Read(buffer, 0, 2336);
|
||||
|
||||
string postgap = "Postgap type: Form ";
|
||||
if ((buffer[2] >> 5 & 0x1) != 0)
|
||||
{
|
||||
postgap += "2";
|
||||
if (buffer.Take(8).SequenceEqual(subheader))
|
||||
postgap += ", zero subheader";
|
||||
else
|
||||
postgap += ", non-zero subheader";
|
||||
|
||||
if (ZeroCompare(buffer, 8, 2324))
|
||||
postgap += ", zero data";
|
||||
else
|
||||
postgap += ", non-zero data";
|
||||
|
||||
if (ZeroCompare(buffer, 2332, 4))
|
||||
postgap += ", no EDC";
|
||||
else
|
||||
postgap += ", EDC";
|
||||
}
|
||||
else
|
||||
{
|
||||
postgap += "1";
|
||||
if (ZeroCompare(buffer, 0, 8))
|
||||
postgap += ", zero subheader";
|
||||
else
|
||||
postgap += ", non-zero subheader";
|
||||
|
||||
if (ZeroCompare(buffer, 8, 2328))
|
||||
postgap += ", zero data";
|
||||
else
|
||||
postgap += ", non-zero data";
|
||||
}
|
||||
|
||||
Console.WriteLine(postgap);
|
||||
Array.Copy(buffer, buffer2, 2336);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
if (mode < 0)
|
||||
return 0;
|
||||
|
||||
for (long sector = sectors - 150; sector < sectors; sector++)
|
||||
{
|
||||
bool bad = false;
|
||||
image.Seek(sector * sectorsize, SeekOrigin.Begin);
|
||||
image.Read(buffer, 0, sectorsize);
|
||||
|
||||
// Sync
|
||||
string sectorInfo = string.Empty;
|
||||
|
||||
MSF(sector, syncheader, 12);
|
||||
if (!syncheader.SequenceEqual(buffer.Take(16)))
|
||||
{
|
||||
sectorInfo += $"Sector {sector}: Sync/Header";
|
||||
bad = true;
|
||||
if (fix)
|
||||
{
|
||||
image.Seek(sector * sectorsize, SeekOrigin.Begin);
|
||||
image.Write(syncheader, 0, 16);
|
||||
sectorInfo += (" (fixed)");
|
||||
}
|
||||
}
|
||||
|
||||
// Mode 2
|
||||
if (mode == 2 && buffer.Skip(16).Take(2336).SequenceEqual(buffer2))
|
||||
{
|
||||
if (bad)
|
||||
{
|
||||
sectorInfo += ", Subheader/Data/EDC/ECC";
|
||||
}
|
||||
else
|
||||
{
|
||||
sectorInfo = $"Sector {sector}: Subheader/Data/EDC/ECC";
|
||||
bad = true;
|
||||
}
|
||||
|
||||
if (fix)
|
||||
{
|
||||
image.Seek(sector * sectorsize + 16, SeekOrigin.Begin);
|
||||
image.Write(buffer2, 0, 2336);
|
||||
sectorInfo += " (fixed)";
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine(sectorInfo);
|
||||
|
||||
if (bad && (sector + 1 != sectors))
|
||||
errors = true;
|
||||
}
|
||||
|
||||
if (errors)
|
||||
{
|
||||
Console.WriteLine("NOTICE: One or more errors were found not in the last sector.");
|
||||
Console.WriteLine("Please mention this when submitting dump info.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Done.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Utilities
|
||||
|
||||
internal static string GetEdcType(uint imageCrc)
|
||||
{
|
||||
switch (imageCrc)
|
||||
{
|
||||
case 0x11e3052d:
|
||||
return "Eu EDC";
|
||||
case 0x808c19f6:
|
||||
return "Eu NoEDC";
|
||||
case 0x70ffa73e:
|
||||
return "Eu Alt NoEDC";
|
||||
case 0x7f9a25b1:
|
||||
return "Eu Alt 2 EDC";
|
||||
case 0x783aca30:
|
||||
return "Jap EDC";
|
||||
case 0xe955d6eb:
|
||||
return "Jap NoEDC";
|
||||
case 0x9b519a2e:
|
||||
return "US EDC";
|
||||
case 0x0a3e86f5:
|
||||
return "US NoEDC";
|
||||
case 0x6773d4db:
|
||||
return "US Alt NoEDC";
|
||||
default:
|
||||
return $"Unknown, crc {imageCrc:8x}";
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
721
BurnOutSharp/External/psxt001z/LibCrypt.cs
vendored
721
BurnOutSharp/External/psxt001z/LibCrypt.cs
vendored
@@ -1,16 +1,44 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using static psxt001z.Common;
|
||||
|
||||
namespace BurnOutSharp.External.psxt001z
|
||||
namespace psxt001z
|
||||
{
|
||||
/// <summary>
|
||||
/// LibCrypt detection code
|
||||
/// Originally written by Dremora: https://github.com/Dremora/psxt001z
|
||||
/// Ported and changed by darksabre76
|
||||
/// </summary>
|
||||
internal class ScsiPassThroughDirect
|
||||
{
|
||||
public ushort Length { get; set; }
|
||||
|
||||
public byte ScsiStatus { get; set; }
|
||||
|
||||
public byte PathId { get; set; }
|
||||
|
||||
public byte TargetId { get; set; }
|
||||
|
||||
public byte Lun { get; set; }
|
||||
|
||||
public byte CDBLength { get; set; }
|
||||
|
||||
public byte SenseInfoLength { get; set; }
|
||||
|
||||
public byte DataIn { get; set; }
|
||||
|
||||
public uint DataTransferLength { get; set; }
|
||||
|
||||
public uint TimeOutValue { get; set; }
|
||||
|
||||
public byte[] DataBuffer { get; set; }
|
||||
|
||||
public uint SenseInfoOffset { get; set; }
|
||||
|
||||
public byte[] CDB { get; set; } = new byte[16];
|
||||
}
|
||||
|
||||
public class LibCrypt
|
||||
{
|
||||
#region OLD
|
||||
|
||||
public static bool CheckSubfile(string subFilePath)
|
||||
{
|
||||
// Check the file exists first
|
||||
@@ -113,16 +141,685 @@ namespace BurnOutSharp.External.psxt001z
|
||||
return modifiedSectors != 0;
|
||||
}
|
||||
|
||||
private static byte btoi(byte b)
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
|
||||
private const uint IOCTL_SCSI_PASS_THROUGH_DIRECT = 0x4D014;
|
||||
private const byte SCSI_IOCTL_DATA_IN = 0x1;
|
||||
private const byte RAW_READ_CMD = 0xBE;
|
||||
private const int BUFFER_LEN = 96;
|
||||
private const int SENSE_SIZE = 0; //14
|
||||
private const string F_NAME = "sectors.log";
|
||||
private const int CYCLES = 5;
|
||||
private const int LIBCRYPT_NUM_SECTORS = 64;
|
||||
private const int READ_TIMES = 5;
|
||||
|
||||
private static readonly uint[] lc_addresses = new uint[LIBCRYPT_NUM_SECTORS]
|
||||
{
|
||||
13955, 13960, 14081, 14086, 14335, 14340, 14429, 14434,
|
||||
14499, 14504, 14749, 14754, 14906, 14911, 14980, 14985,
|
||||
15092, 15097, 15162, 15167, 15228, 15233, 15478, 15483,
|
||||
15769, 15774, 15881, 15886, 15951, 15956, 16017, 16022,
|
||||
41895, 41900, 42016, 42021, 42282, 42287, 42430, 42435,
|
||||
42521, 42526, 42663, 42668, 42862, 42867, 43027, 43032,
|
||||
43139, 43144, 43204, 43209, 43258, 43263, 43484, 43489,
|
||||
43813, 43818, 43904, 43909, 44009, 44014, 44162, 44167
|
||||
};
|
||||
|
||||
private static readonly byte[] lc1_sectors_contents = new byte[768]
|
||||
{
|
||||
/* BCD to u_char */
|
||||
return (byte)((b) / 16 * 10 + (b) % 16);
|
||||
0x41, 0x01, 0x01, 0x07, 0x06, 0x05, 0x00, 0x23, 0x08, 0x05, 0x38, 0x39,
|
||||
0x41, 0x01, 0x01, 0x03, 0x06, 0x11, 0x00, 0x03, 0x08, 0x90, 0x5d, 0xa0,
|
||||
0x41, 0x01, 0x01, 0x07, 0x07, 0x56, 0x00, 0x23, 0x09, 0x56, 0xdf, 0xde,
|
||||
0x41, 0x01, 0x01, 0x03, 0x07, 0x60, 0x00, 0x03, 0x09, 0xe1, 0xf2, 0x50,
|
||||
0x41, 0x01, 0x01, 0x03, 0x13, 0x10, 0x00, 0x03, 0x53, 0x10, 0x50, 0xec,
|
||||
0x41, 0x01, 0x01, 0x43, 0x11, 0x15, 0x00, 0x01, 0x13, 0x15, 0x23, 0x1e,
|
||||
0x41, 0x01, 0x01, 0x03, 0x12, 0x09, 0x00, 0x03, 0x14, 0x2d, 0x04, 0x73,
|
||||
0x41, 0x01, 0x01, 0x03, 0x1a, 0x34, 0x00, 0x03, 0x04, 0x34, 0xe2, 0xcf,
|
||||
0x41, 0x01, 0x01, 0x03, 0x13, 0x20, 0x00, 0x03, 0x15, 0x04, 0x82, 0x35,
|
||||
0x41, 0x01, 0x01, 0x01, 0x13, 0x29, 0x00, 0x43, 0x15, 0x29, 0x72, 0xe2,
|
||||
0x41, 0x01, 0x01, 0x03, 0x1e, 0x49, 0x00, 0x03, 0x08, 0x49, 0x32, 0xc5,
|
||||
0x41, 0x01, 0x01, 0x01, 0x16, 0x54, 0x00, 0x43, 0x18, 0x54, 0xd4, 0x79,
|
||||
0x41, 0x01, 0x01, 0x03, 0x18, 0x57, 0x00, 0x03, 0x20, 0xd6, 0xbc, 0x27,
|
||||
0x41, 0x01, 0x01, 0x03, 0x38, 0x61, 0x00, 0x03, 0x24, 0x61, 0x91, 0xa9,
|
||||
0x41, 0x01, 0x01, 0x0b, 0x19, 0x55, 0x00, 0x13, 0x21, 0x55, 0x14, 0x07,
|
||||
0x41, 0x01, 0x01, 0x03, 0x19, 0x62, 0x00, 0x03, 0x21, 0x20, 0x5d, 0x48,
|
||||
0x41, 0x01, 0x01, 0x03, 0x23, 0x17, 0x00, 0x03, 0x63, 0x17, 0x6d, 0xc6,
|
||||
0x41, 0x01, 0x01, 0x43, 0x21, 0x22, 0x00, 0x01, 0x23, 0x22, 0x24, 0x89,
|
||||
0x41, 0x01, 0x01, 0x03, 0x02, 0x12, 0x00, 0x03, 0x20, 0x12, 0x49, 0x43,
|
||||
0x41, 0x01, 0x01, 0x03, 0x22, 0x07, 0x00, 0x03, 0x24, 0x1f, 0x3a, 0xb1,
|
||||
0x41, 0x01, 0x01, 0x03, 0x23, 0x13, 0x00, 0x03, 0x25, 0x0b, 0x93, 0xc9,
|
||||
0x41, 0x01, 0x01, 0x0b, 0x23, 0x08, 0x00, 0x13, 0x25, 0x08, 0xce, 0x5d,
|
||||
0x41, 0x01, 0x01, 0x03, 0x06, 0x28, 0x00, 0x03, 0x2c, 0x28, 0xd7, 0xd6,
|
||||
0x41, 0x01, 0x01, 0x0b, 0x26, 0x33, 0x00, 0x13, 0x28, 0x33, 0x9c, 0x29,
|
||||
0x41, 0x01, 0x01, 0x03, 0x30, 0x59, 0x00, 0x03, 0x32, 0x1b, 0x2c, 0xc6,
|
||||
0x41, 0x01, 0x01, 0x03, 0x20, 0x24, 0x00, 0x03, 0x3a, 0x24, 0xe6, 0xac,
|
||||
0x41, 0x01, 0x01, 0x13, 0x31, 0x56, 0x00, 0x0b, 0x33, 0x56, 0x97, 0xed,
|
||||
0x41, 0x01, 0x01, 0x03, 0x31, 0x65, 0x00, 0x03, 0x33, 0x41, 0xba, 0x63,
|
||||
0x41, 0x01, 0x01, 0x01, 0x32, 0x51, 0x00, 0x43, 0x34, 0x51, 0xd7, 0xa9,
|
||||
0x41, 0x01, 0x01, 0x03, 0x33, 0x56, 0x00, 0x03, 0xb4, 0x56, 0xc0, 0x9a,
|
||||
0x41, 0x01, 0x01, 0x03, 0x32, 0x42, 0x00, 0x03, 0xb5, 0x42, 0x69, 0xe2,
|
||||
0x41, 0x01, 0x01, 0x03, 0x33, 0x07, 0x00, 0x03, 0x35, 0x45, 0x1a, 0x10,
|
||||
0x41, 0x01, 0x01, 0x09, 0x18, 0x65, 0x00, 0x09, 0x20, 0x41, 0x40, 0x72,
|
||||
0x41, 0x01, 0x01, 0x19, 0x18, 0x50, 0x00, 0x01, 0x20, 0x50, 0x25, 0xeb,
|
||||
0x41, 0x01, 0x01, 0x08, 0x20, 0x16, 0x00, 0x89, 0x22, 0x16, 0x95, 0xa8,
|
||||
0x41, 0x01, 0x01, 0x09, 0x20, 0x01, 0x00, 0x09, 0x22, 0x25, 0xb8, 0x26,
|
||||
0x41, 0x01, 0x01, 0x09, 0x23, 0x53, 0x00, 0x09, 0x25, 0x77, 0x21, 0x03,
|
||||
0x41, 0x01, 0x01, 0x0b, 0x23, 0x62, 0x00, 0x49, 0x25, 0x62, 0x68, 0x4c,
|
||||
0x41, 0x01, 0x01, 0x0d, 0x25, 0x55, 0x00, 0x29, 0x27, 0x55, 0xae, 0x41,
|
||||
0x41, 0x01, 0x01, 0x09, 0x25, 0x61, 0x00, 0x09, 0x27, 0xe0, 0xe7, 0x0e,
|
||||
0x41, 0x01, 0x01, 0x08, 0x26, 0x71, 0x00, 0x89, 0x28, 0x71, 0x95, 0xcb,
|
||||
0x41, 0x01, 0x01, 0x09, 0x27, 0x21, 0x00, 0x09, 0x29, 0x05, 0x80, 0x4b,
|
||||
0x41, 0x01, 0x01, 0x0b, 0x28, 0x63, 0x00, 0x49, 0x30, 0x63, 0xed, 0x18,
|
||||
0x41, 0x01, 0x01, 0x09, 0x29, 0x68, 0x00, 0x09, 0xb0, 0x68, 0xb0, 0x8c,
|
||||
0x41, 0x01, 0x01, 0x29, 0x31, 0x37, 0x00, 0x0d, 0x33, 0x37, 0x6c, 0x68,
|
||||
0x41, 0x01, 0x01, 0x09, 0x31, 0x4a, 0x00, 0x09, 0x33, 0x52, 0x7c, 0x8b,
|
||||
0x41, 0x01, 0x01, 0x09, 0x73, 0x52, 0x00, 0x09, 0x37, 0x52, 0x4b, 0x06,
|
||||
0x41, 0x01, 0x01, 0x19, 0x33, 0x57, 0x00, 0x01, 0x35, 0x57, 0x38, 0xf4,
|
||||
0x41, 0x01, 0x01, 0x09, 0x35, 0x04, 0x00, 0x09, 0x37, 0x1c, 0x54, 0x6a,
|
||||
0x41, 0x01, 0x01, 0x09, 0x31, 0x19, 0x00, 0x09, 0x17, 0x19, 0xa4, 0xbd,
|
||||
0x41, 0x01, 0x01, 0x01, 0x36, 0x04, 0x00, 0x19, 0x38, 0x04, 0x9c, 0xdf,
|
||||
0x41, 0x01, 0x01, 0x09, 0x36, 0x0b, 0x00, 0x09, 0x38, 0x49, 0x6c, 0x08,
|
||||
0x41, 0x01, 0x01, 0x49, 0x36, 0x58, 0x00, 0x0b, 0x38, 0x58, 0x99, 0xbf,
|
||||
0x41, 0x01, 0x01, 0x09, 0x36, 0x73, 0x00, 0x09, 0x38, 0x6b, 0xfe, 0x96,
|
||||
0x41, 0x01, 0x01, 0x0b, 0x39, 0x59, 0x00, 0x49, 0x41, 0x59, 0x54, 0x0d,
|
||||
0x41, 0x01, 0x01, 0x09, 0x39, 0x24, 0x00, 0x09, 0x41, 0x66, 0x9e, 0x67,
|
||||
0x41, 0x01, 0x01, 0x09, 0x44, 0x1b, 0x00, 0x09, 0x46, 0x03, 0x78, 0x0d,
|
||||
0x41, 0x01, 0x01, 0x09, 0x46, 0x18, 0x00, 0x09, 0x06, 0x18, 0x25, 0x99,
|
||||
0x41, 0x01, 0x01, 0x09, 0x45, 0x2b, 0x00, 0x09, 0x47, 0x69, 0xd3, 0xc5,
|
||||
0x41, 0x01, 0x01, 0x09, 0x05, 0x34, 0x00, 0x09, 0x45, 0x34, 0x35, 0x79,
|
||||
0x41, 0x01, 0x01, 0x09, 0x44, 0x59, 0x00, 0x09, 0x08, 0x59, 0x6e, 0x0a,
|
||||
0x41, 0x01, 0x01, 0x49, 0x46, 0x64, 0x00, 0x0b, 0x48, 0x64, 0xa4, 0x60,
|
||||
0x41, 0x01, 0x01, 0x09, 0x08, 0x62, 0x00, 0x09, 0x52, 0x62, 0x03, 0x5a,
|
||||
0x41, 0x01, 0x01, 0x19, 0x48, 0x67, 0x00, 0x01, 0x50, 0x67, 0x70, 0xa8
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
// TODO: Enable the following only if reading from a drive directly
|
||||
|
||||
/*
|
||||
internal static byte LibCryptDrive(string[] args)
|
||||
{
|
||||
byte offset = 0;
|
||||
string path = $"\\\\.\\{args[0][0]}:";
|
||||
byte i;
|
||||
byte[] sub = new byte[12], buffer = new byte[BUFFER_LEN], buffer2352 = new byte[23520], buffer2 = new byte[BUFFER_LEN], buffer3 = new byte[BUFFER_LEN], buffer4 = new byte[BUFFER_LEN];
|
||||
byte[] status;
|
||||
ushort crc;
|
||||
uint sector, sector_start, sector_end, a, lcsectors = 0, todo = 9300, done = 0;
|
||||
|
||||
if (args.Length != 1 || (args.Length == 1 && (args[0][1] != 0 && (args[0][1] != ':' || args[0][2] != 0))))
|
||||
{
|
||||
Console.WriteLine("LibCrypt drive detector");
|
||||
Console.WriteLine("nUsage: psxt001z.exe --libcryptdrv <drive letter>");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Stream hDevice;
|
||||
try
|
||||
{
|
||||
hDevice = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Can't open device!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Stream f;
|
||||
try
|
||||
{
|
||||
f = File.Open(F_NAME, FileMode.Open, FileAccess.Write);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Can't open file {F_NAME}!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
byte[] status1 = new byte[4650];
|
||||
byte[] status2 = new byte[4650];
|
||||
|
||||
// Offset detection
|
||||
Console.WriteLine("Determining offset...\r");
|
||||
ScsiPassThroughDirect SRB = new ScsiPassThroughDirect();
|
||||
ReadSub(buffer, 0, f, offset, hDevice, SRB);
|
||||
|
||||
switch (buffer[8])
|
||||
{
|
||||
case 0x01:
|
||||
offset = (byte)(75 - btoi(buffer[9]));
|
||||
break;
|
||||
case 0x02:
|
||||
offset = (byte)(-btoi(buffer[9]));
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine("Can't determine offset!");
|
||||
Console.WriteLine(BitConverter.ToString(buffer).Replace('-', ' '));
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub[0] = buffer[0];
|
||||
sub[1] = 0x01;
|
||||
sub[2] = 0x01;
|
||||
sub[6] = 0x00;
|
||||
|
||||
Console.WriteLine($"Subchannels offset correction: {offset}");
|
||||
|
||||
// Section 1) 02:58:00 - 03:69:74 -- status1
|
||||
// Section 2) 08:58:00 - 09:69:74 -- status2
|
||||
|
||||
// Step 1
|
||||
|
||||
for (i = 0; i < CYCLES * 3; i++)
|
||||
{
|
||||
|
||||
if (todo == 0)
|
||||
goto end;
|
||||
|
||||
if (i % 3 == 0)
|
||||
{
|
||||
sector_start = 13350;
|
||||
sector_end = 18000;
|
||||
status = status1;
|
||||
}
|
||||
else if (i % 3 == 1)
|
||||
{
|
||||
sector_start = 40350;
|
||||
sector_end = 45000;
|
||||
status = status2;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Left: {todo:4} / Flushing cache... \r");
|
||||
ClearCache(buffer2352, f, offset, hDevice, SRB);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (sector = sector_start; sector < sector_end; sector++)
|
||||
{
|
||||
if (status[sector - sector_start] != 0)
|
||||
continue;
|
||||
|
||||
ReadSub(buffer, sector, f, offset, hDevice, SRB);
|
||||
Console.WriteLine("Left: %4u / Sector %u... \r", todo, sector);
|
||||
// generating q-channel
|
||||
sub[3] = itob((byte)(sector / 60 / 75));
|
||||
sub[4] = itob((byte)((sector / 75) % 60));
|
||||
sub[5] = itob((byte)(sector % 75));
|
||||
sub[7] = itob((byte)((sector + 150) / 60 / 75));
|
||||
sub[8] = itob((byte)(((sector + 150) / 75) % 60));
|
||||
sub[9] = itob((byte)((sector + 150) % 75));
|
||||
crc = CRC16.Calculate(sub, 0, 10);
|
||||
sub[10] = (byte)(crc >> 8);
|
||||
sub[11] = (byte)(crc & 0xFF);
|
||||
if (sub.SequenceEqual(buffer.Take(12)))
|
||||
{
|
||||
status[sector - sector_start] = 1;
|
||||
todo--;
|
||||
done++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
sector_start = 13350;
|
||||
sector_end = 18000;
|
||||
status = status1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sector_start = 40350;
|
||||
sector_end = 45000;
|
||||
status = status2;
|
||||
}
|
||||
|
||||
for (sector = sector_start; sector < sector_end; sector++)
|
||||
{
|
||||
if (status[sector - sector_start] != 0)
|
||||
continue;
|
||||
ReadSub(buffer, sector, f, offset, hDevice, SRB);
|
||||
Console.WriteLine($"Left: {todo:4} / Sector {sector}... \r");
|
||||
|
||||
// generating q-channel
|
||||
sub[3] = itob((byte)(sector / 60 / 75));
|
||||
sub[4] = itob((byte)((sector / 75) % 60));
|
||||
sub[5] = itob((byte)(sector % 75));
|
||||
sub[7] = itob((byte)((sector + 150) / 60 / 75));
|
||||
sub[8] = itob((byte)(((sector + 150) / 75) % 60));
|
||||
sub[9] = itob((byte)((sector + 150) % 75));
|
||||
crc = CRC16.Calculate(sub, 0, 10);
|
||||
sub[10] = (byte)(crc >> 8);
|
||||
sub[11] = (byte)(crc ^ 0xFF);
|
||||
if (sub.SequenceEqual(buffer.Take(12)))
|
||||
{
|
||||
Console.WriteLine($"Left: {todo:4} / Sector {sector}: flushing cache... \r");
|
||||
do
|
||||
{
|
||||
ReadSub(buffer, sector, f, offset, hDevice, SRB);
|
||||
ClearCache(buffer2352, f, offset, hDevice, SRB);
|
||||
ReadSub(buffer2, sector, f, offset, hDevice, SRB);
|
||||
ClearCache(buffer2352, f, offset, hDevice, SRB);
|
||||
ReadSub(buffer3, sector, f, offset, hDevice, SRB);
|
||||
ClearCache(buffer2352, f, offset, hDevice, SRB);
|
||||
} while (!buffer.SequenceEqual(buffer2) || !buffer.SequenceEqual(buffer3));
|
||||
//} while (!matrix(buffer, buffer2, buffer3, buffer4, BUFFER_LEN));
|
||||
|
||||
if (buffer.SequenceEqual(sub))
|
||||
{
|
||||
byte[] buf = Encoding.ASCII.GetBytes($"MSF: {sub[7]:2x}:{sub[8]:2x}:{sub[9]:2x} Q-Data: {BitConverter.ToString(buffer.Take(12).ToArray()).Replace('-', ' ')}");
|
||||
f.Write(buf, 0, buf.Length);
|
||||
lcsectors++;
|
||||
//fwrite(SRB.SRB_BufPointer, 1, SRB.SRB_BufLen - 4, f);
|
||||
f.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
todo--;
|
||||
done++;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
Console.WriteLine($"Done! \nProtected sectors: {(lcsectors == 0 ? "None" : lcsectors.ToString())}");
|
||||
|
||||
f.Close();
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static byte itob(byte i)
|
||||
internal static int LibCryptDriveFast(string[] args)
|
||||
{
|
||||
/* u_char to BCD */
|
||||
return (byte)((i) / 10 * 16 + (i) % 10);
|
||||
Stream f;
|
||||
Stream hDevice;
|
||||
ScsiPassThroughDirect SRB;
|
||||
s8 offset = 0, path[] = "\\\\.\\X:";
|
||||
u8 buffer[BUFFER_LEN], buffer2352[23520], sub[12], lc1sectors = 0, lc2sectors = 0, othersectors = 0;
|
||||
u16 crc;
|
||||
|
||||
if (argc != 1 || (argc == 1 && (args[0][1] != 0 && (args[0][1] != ':' || args[0][2] != 0))))
|
||||
{
|
||||
Console.WriteLine("LibCrypt drive detector (fast)\nUsage: psxt001z.exe --libcryptdrvfast <drive letter>\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
path[4] = args[0][0];
|
||||
|
||||
if ((hDevice = CreateFile(path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
Console.WriteLine("Can't open device!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fopen_s(&f, F_NAME, "wb") != 0)
|
||||
{
|
||||
Console.WriteLine("Can\'t open file %s!\n", F_NAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Offset detection
|
||||
ReadSub(buffer, 0, f, offset, hDevice, SRB);
|
||||
//if (buffer[5] != buffer[9]) {
|
||||
// Console.WriteLine("Error determining offset!\nSector 0: %02x%02x%02x %02x:%02x:%02x %02x %02x:%02x:%02x %02x%02x\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9], buffer[10], buffer[11]);
|
||||
//}
|
||||
switch (buffer[8])
|
||||
{
|
||||
case 0x01:
|
||||
offset = 75 - btoi(buffer[9]);
|
||||
break;
|
||||
case 0x02:
|
||||
offset = -btoi(buffer[9]);
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine("Can't determine offset!\nSector 0: %02x%02x%02x %02x:%02x:%02x %02x %02x:%02x:%02x %02x%02x\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9], buffer[10], buffer[11]);
|
||||
return 0;
|
||||
}
|
||||
Console.WriteLine("Subchannels offset correction: %d\n", offset);
|
||||
sub[0] = buffer[0];
|
||||
sub[1] = 0x01;
|
||||
sub[2] = 0x01;
|
||||
sub[6] = 0x00;
|
||||
|
||||
for (int i = 0; i < LIBCRYPT_NUM_SECTORS; i++)
|
||||
{
|
||||
Console.WriteLine("\nReading sector %u... ", lc_addresses[i]);
|
||||
ReadSub(buffer, lc_addresses[i], f, offset, hDevice, SRB);
|
||||
// generating q-channel
|
||||
sub[3] = itob(lc_addresses[i] / 60 / 75);
|
||||
sub[4] = itob((lc_addresses[i] / 75) % 60);
|
||||
sub[5] = itob(lc_addresses[i] % 75);
|
||||
sub[7] = itob((lc_addresses[i] + 150) / 60 / 75);
|
||||
sub[8] = itob(((lc_addresses[i] + 150) / 75) % 60);
|
||||
sub[9] = itob((lc_addresses[i] + 150) % 75);
|
||||
crc = crc16(sub, 10);
|
||||
sub[10] = HIbyte(crc);
|
||||
sub[11] = LObyte(crc);
|
||||
for (int a = 1; a <= READ_TIMES; a++)
|
||||
{
|
||||
if (!memcmp(sub, buffer, 12))
|
||||
{
|
||||
Console.WriteLine("original sector");
|
||||
break;
|
||||
}
|
||||
else if (!memcmp(lc1_sectors_contents + (12 * i), buffer, 12))
|
||||
{
|
||||
Console.WriteLine("LibCrypt, LC1 sector");
|
||||
fConsole.WriteLine(f, "MSF: %02x:%02x:%02x Q-Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", sub[7], sub[8], sub[9], buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9], buffer[10], buffer[11]);
|
||||
lc1sectors++;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (a < READ_TIMES)
|
||||
{
|
||||
ClearCache(buffer2352, 0, offset, hDevice, SRB);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("unknown");
|
||||
fConsole.WriteLine(f, "MSF: %02x:%02x:%02x Q-Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", sub[7], sub[8], sub[9], buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9], buffer[10], buffer[11]);
|
||||
othersectors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Console.WriteLine("\n\nOriginal sectors: %u", LIBCRYPT_NUM_SECTORS - lc1sectors - lc2sectors - othersectors);
|
||||
Console.WriteLine("\nLC1 sectors: %u", lc1sectors);
|
||||
Console.WriteLine("\nLC2 sectors: %u", lc2sectors);
|
||||
Console.WriteLine("\nOther sectors: %u", othersectors);
|
||||
|
||||
fConsole.WriteLine(f, "\nOriginal sectors: %u", LIBCRYPT_NUM_SECTORS - lc1sectors - lc2sectors - othersectors);
|
||||
fConsole.WriteLine(f, "\nLC1 sectors: %u", lc1sectors);
|
||||
fConsole.WriteLine(f, "\nLC2 sectors: %u", lc2sectors);
|
||||
fConsole.WriteLine(f, "\nOther sectors: %u", othersectors);
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
internal static void ReadSub(byte[] buffer, uint sector, Stream f, byte offset, Stream hDevice, ScsiPassThroughDirect SRB)
|
||||
{
|
||||
uint returned;
|
||||
ZeroMemory(&SRB, sizeof(ScsiPassThroughDirect));
|
||||
SRB.Length = sizeof(ScsiPassThroughDirect);
|
||||
SRB.CDBLength = 12;
|
||||
SRB.DataIn = SCSI_IOCTL_DATA_IN;
|
||||
SRB.DataTransferLength = BUFFER_LEN;
|
||||
SRB.TimeOutValue = 30;
|
||||
SRB.DataBuffer = buffer;
|
||||
SRB.CDB[0] = RAW_READ_CMD;
|
||||
SRB.CDB[2] = HIbyte(HIWORD(sector + offset));
|
||||
SRB.CDB[3] = LObyte(HIWORD(sector + offset));
|
||||
SRB.CDB[4] = HIbyte(LOWORD(sector + offset));
|
||||
SRB.CDB[5] = LObyte(LOWORD(sector + offset));
|
||||
SRB.CDB[8] = 1;
|
||||
SRB.CDB[10] = 1;
|
||||
|
||||
if (!DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, &SRB, sizeof(ScsiPassThroughDirect), &SRB, SENSE_SIZE, &returned, 0))
|
||||
{
|
||||
Console.WriteLine("\nError reading subchannel data!\n");
|
||||
if (f != 0)
|
||||
fConsole.WriteLine(f, "Error reading subchannel data!");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Deinterleave(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
internal static void ClearCache(byte[] buffer, Stream f, byte offset, Stream hDevice, ScsiPassThroughDirect SRB)
|
||||
{
|
||||
static uint returned;
|
||||
for (uint sector = 0; sector < 1000; sector += 10)
|
||||
{
|
||||
ZeroMemory(&SRB, sizeof(ScsiPassThroughDirect));
|
||||
SRB.Length = sizeof(ScsiPassThroughDirect);
|
||||
SRB.CDBLength = 12;
|
||||
SRB.DataIn = SCSI_IOCTL_DATA_IN;
|
||||
SRB.DataTransferLength = 23520;
|
||||
SRB.TimeOutValue = 30;
|
||||
SRB.DataBuffer = buffer;
|
||||
SRB.CDB[0] = RAW_READ_CMD;
|
||||
SRB.CDB[2] = HIbyte(HIWORD(sector + offset));
|
||||
SRB.CDB[3] = LObyte(HIWORD(sector + offset));
|
||||
SRB.CDB[4] = HIbyte(LOWORD(sector + offset));
|
||||
SRB.CDB[5] = LObyte(LOWORD(sector + offset));
|
||||
SRB.CDB[8] = 10;
|
||||
SRB.CDB[9] = 0xF8;
|
||||
|
||||
DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, &SRB, sizeof(ScsiPassThroughDirect), &SRB, SENSE_SIZE, &returned, 0);
|
||||
|
||||
if (!DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, &SRB, sizeof(ScsiPassThroughDirect), &SRB, SENSE_SIZE, &returned, 0))
|
||||
{
|
||||
Console.WriteLine("\nError clearing cache!\n");
|
||||
if (f != 0)
|
||||
fConsole.WriteLine(f, "Error clearing cache!");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
internal static bool Matrix(byte[] buffer, byte[] buffer2, byte[] buffer3, byte[] buffer4, uint length)
|
||||
{
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
if (buffer[i] == buffer2[i])
|
||||
{
|
||||
if (buffer[i] == buffer3[i])
|
||||
continue;
|
||||
if (buffer[i] == buffer4[i])
|
||||
continue;
|
||||
}
|
||||
else if (buffer[i] == buffer3[i] && buffer[i] == buffer4[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (buffer2[i] == buffer3[i] && buffer2[i] == buffer4[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static void Deinterleave(byte[] buffer)
|
||||
{
|
||||
byte[] buffertmp = new byte[12];
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
buffertmp[i] |= (byte)((buffer[i * 8] & 0x40) << 1);
|
||||
buffertmp[i] |= (byte)((buffer[i * 8 + 1] & 0x40));
|
||||
buffertmp[i] |= (byte)((buffer[i * 8 + 2] & 0x40) >> 1);
|
||||
buffertmp[i] |= (byte)((buffer[i * 8 + 3] & 0x40) >> 2);
|
||||
buffertmp[i] |= (byte)((buffer[i * 8 + 4] & 0x40) >> 3);
|
||||
buffertmp[i] |= (byte)((buffer[i * 8 + 5] & 0x40) >> 4);
|
||||
buffertmp[i] |= (byte)((buffer[i * 8 + 6] & 0x40) >> 5);
|
||||
buffertmp[i] |= (byte)((buffer[i * 8 + 7] & 0x40) >> 6);
|
||||
}
|
||||
|
||||
Array.Copy(buffertmp, buffer, 12);
|
||||
return;
|
||||
}
|
||||
|
||||
internal static bool LibCryptDetect(string subPath, string sbiPath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(subPath) || !File.Exists(subPath))
|
||||
return false;
|
||||
|
||||
// Variables
|
||||
byte[] buffer = new byte[16], sub = new byte[16];//, pregap = 0;
|
||||
uint sector, psectors = 0, tpos = 0;
|
||||
|
||||
// Opening .sub
|
||||
Stream subfile = File.OpenRead(subPath);
|
||||
|
||||
// checking extension
|
||||
if (Path.GetExtension(subPath).TrimStart('.').ToLowerInvariant() != "sub")
|
||||
{
|
||||
Console.WriteLine($"{subPath}: unknown file extension");
|
||||
return false;
|
||||
}
|
||||
|
||||
// filesize
|
||||
long size = subfile.Length;
|
||||
if (size % 96 != 0)
|
||||
{
|
||||
Console.WriteLine($"{subfile}: wrong size");
|
||||
return false;
|
||||
}
|
||||
|
||||
// sbi
|
||||
Stream sbi = null;
|
||||
if (sbiPath != null)
|
||||
{
|
||||
sbi = File.OpenWrite(sbiPath);
|
||||
sbi.Write(Encoding.ASCII.GetBytes("SBI\0"), 0, 4);
|
||||
}
|
||||
|
||||
for (sector = 150; sector < ((size / 96) + 150); sector++)
|
||||
{
|
||||
subfile.Seek(12, SeekOrigin.Current);
|
||||
if (subfile.Read(buffer, 0, 12) != 12)
|
||||
return true;
|
||||
|
||||
subfile.Seek(72, SeekOrigin.Current);
|
||||
|
||||
// New track
|
||||
if ((btoi(buffer[1]) == (btoi(sub[1]) + 1)) && (buffer[2] == 0 || buffer[2] == 1))
|
||||
{
|
||||
Array.Copy(buffer, sub, 6);
|
||||
tpos = (uint)((btoi((byte)(buffer[3] * 60)) + btoi(buffer[4])) * 75) + btoi(buffer[5]);
|
||||
}
|
||||
|
||||
// New index
|
||||
else if (btoi(buffer[2]) == (btoi(sub[2]) + 1) && buffer[1] == sub[1])
|
||||
{
|
||||
Array.Copy(buffer, 2, sub, 2, 4);
|
||||
tpos = (uint)((btoi((byte)(buffer[3] * 60)) + btoi(buffer[4])) * 75) + btoi(buffer[5]);
|
||||
}
|
||||
|
||||
// MSF1 [3-5]
|
||||
else
|
||||
{
|
||||
if (sub[2] == 0)
|
||||
tpos--;
|
||||
else
|
||||
tpos++;
|
||||
|
||||
sub[3] = itob((byte)(tpos / 60 / 75));
|
||||
sub[4] = itob((byte)((tpos / 75) % 60));
|
||||
sub[5] = itob((byte)(tpos % 75));
|
||||
}
|
||||
|
||||
//MSF2 [7-9]
|
||||
sub[7] = itob((byte)(sector / 60 / 75));
|
||||
sub[8] = itob((byte)((sector / 75) % 60));
|
||||
sub[9] = itob((byte)(sector % 75));
|
||||
|
||||
// CRC-16 [10-11]
|
||||
ushort crc = CRC16.Calculate(sub, 0, 10);
|
||||
sub[10] = (byte)(crc >> 8);
|
||||
sub[11] = (byte)(crc & 0xFF);
|
||||
|
||||
//if (buffer[10] != sub[10] && buffer[11] != sub[11] && (buffer[3] != sub[3] || buffer[7] != sub[7] || buffer[4] != sub[4] || buffer[8] != sub[8] || buffer[5] != sub[5] || buffer[9] != sub[9])) {
|
||||
//if (buffer[10] != sub[10] || buffer[11] != sub[11] || buffer[3] != sub[3] || buffer[7] != sub[7] || buffer[4] != sub[4] || buffer[8] != sub[8] || buffer[5] != sub[5] || buffer[9] != sub[9]) {
|
||||
if (!buffer.Take(6).SequenceEqual(sub.Take(6)) || !buffer.Skip(7).Take(5).SequenceEqual(sub.Skip(7).Take(5)))
|
||||
{
|
||||
Console.WriteLine($"MSF: {sub[7]:2x}:{sub[8]:2x}:{sub[9]:2x} Q-Data: {buffer[0]:2x}{buffer[1]:2x}{buffer[2]:2x} {buffer[3]:2x}:{buffer[4]:2x}:{buffer[5]:2x} {buffer[6]:2x} {buffer[7]:2x}:{buffer[8]:2x}:{buffer[9]:2x} {buffer[10]:2x}{buffer[11]:2x} xor {crc ^ ((buffer[10] << 8) + buffer[11]):4x} {CRC16.Calculate(buffer, 0, 10) ^ ((buffer[10] << 8) + buffer[11]):4x}");
|
||||
//Console.WriteLine("\nMSF: %02x:%02x:%02x Q-Data: %02x%02x%02x %02x:%02x:%02x %02x %02x:%02x:%02x %02x%02x", sub[7], sub[8], sub[9], sub[0], sub[1], sub[2], sub[3], sub[4], sub[5], sub[6], sub[7], sub[8], sub[9], sub[10], sub[11]);
|
||||
|
||||
if (buffer[3] != sub[3] && buffer[7] != sub[7] && buffer[4] == sub[4] && buffer[8] == sub[8] && buffer[5] == sub[5] && buffer[9] == sub[9])
|
||||
Console.WriteLine($" P1 xor {buffer[3] ^ sub[3]:2x} {buffer[7] ^ sub[7]:2x}");
|
||||
else if (buffer[3] == sub[3] && buffer[7] == sub[7] && buffer[4] != sub[4] && buffer[8] != sub[8] && buffer[5] == sub[5] && buffer[9] == sub[9])
|
||||
Console.WriteLine($" P2 xor {buffer[4] ^ sub[4]:2x} {buffer[8] ^ sub[8]:2x}");
|
||||
else if (buffer[3] == sub[3] && buffer[7] == sub[7] && buffer[4] == sub[4] && buffer[8] == sub[8] && buffer[5] != sub[5] && buffer[9] != sub[9])
|
||||
Console.WriteLine($" P3 xor {buffer[5] ^ sub[5]:2x} {buffer[9] ^ sub[9]:2x}");
|
||||
else
|
||||
Console.WriteLine(" ?");
|
||||
|
||||
Console.WriteLine("\n");
|
||||
psectors++;
|
||||
if (sbi != null)
|
||||
{
|
||||
sbi.Write(sub, 7, 3);
|
||||
sbi.Write(new byte[] { 0x01 }, 0, 1);
|
||||
sbi.Write(buffer, 0, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
Console.WriteLine($"Number of modified sectors: {psectors}");
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static int XorLibCrypt()
|
||||
{
|
||||
sbyte b;
|
||||
byte d;
|
||||
byte i, a, x;
|
||||
byte[] sub = new byte[12]
|
||||
{
|
||||
0x41, 0x01, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
ushort crc;
|
||||
for (i = 0; i < LIBCRYPT_NUM_SECTORS; i++)
|
||||
{
|
||||
sub[3] = itob((byte)(lc_addresses[i] / 60 / 75));
|
||||
sub[4] = itob((byte)((lc_addresses[i] / 75) % 60));
|
||||
sub[5] = itob((byte)(lc_addresses[i] % 75));
|
||||
sub[7] = itob((byte)((lc_addresses[i] + 150) / 60 / 75));
|
||||
sub[8] = itob((byte)(((lc_addresses[i] + 150) / 75) % 60));
|
||||
sub[9] = itob((byte)((lc_addresses[i] + 150) % 75));
|
||||
crc = CRC16.Calculate(sub, 0, 10);
|
||||
sub[10] = (byte)(crc >> 8);
|
||||
sub[11] = (byte)(crc & 0xFF);
|
||||
|
||||
Console.WriteLine($"%u %02x:%02x:%02x", lc_addresses[i], sub[7], sub[8], sub[9]);
|
||||
Console.WriteLine($" %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %02x%02x", sub[0], sub[1], sub[2], sub[3], sub[4], sub[5], sub[6], sub[7], sub[8], sub[9], sub[10], sub[11]);
|
||||
Console.WriteLine($" %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %02x%02x", lc1_sectors_contents[i * 12], lc1_sectors_contents[(i * 12) + 1], lc1_sectors_contents[(i * 12) + 2], lc1_sectors_contents[(i * 12) + 3], lc1_sectors_contents[(i * 12) + 4], lc1_sectors_contents[(i * 12) + 5], lc1_sectors_contents[(i * 12) + 6], lc1_sectors_contents[(i * 12) + 7], lc1_sectors_contents[(i * 12) + 8], lc1_sectors_contents[(i * 12) + 9], lc1_sectors_contents[(i * 12) + 10], lc1_sectors_contents[(i * 12) + 11]);
|
||||
|
||||
d = 0;
|
||||
|
||||
for (a = 3; a < 12; a++)
|
||||
{
|
||||
x = (byte)(lc1_sectors_contents[(i * 12) + a] ^ sub[a]);
|
||||
Console.WriteLine($" %x%x%x%x%x%x%x%x", (x >> 7) & 0x1, (x >> 6) & 0x1, (x >> 5) & 0x1, (x >> 4) & 0x1, (x >> 3) & 0x1, (x >> 2) & 0x1, (x >> 1) & 0x1, x & 0x1);
|
||||
if (x == 0)
|
||||
continue;
|
||||
for (b = 7; b >= 0; b--)
|
||||
{
|
||||
if (((x >> b) & 0x1) != 0)
|
||||
{
|
||||
d = (byte)(d << 1);
|
||||
d |= (byte)((sub[a] >> b) & 0x1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine($" {(d >> 3) & 0x1:x}{(d >> 2) & 0x1:x}{(d >> 1) & 0x1:x}{d & 0x1}");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1004
BurnOutSharp/External/psxt001z/Main.cs
vendored
Normal file
1004
BurnOutSharp/External/psxt001z/Main.cs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
110
BurnOutSharp/External/psxt001z/Scramble.cs
vendored
Normal file
110
BurnOutSharp/External/psxt001z/Scramble.cs
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using static psxt001z.Common;
|
||||
|
||||
namespace psxt001z
|
||||
{
|
||||
public class Scramble
|
||||
{
|
||||
private static readonly byte[] sync = new byte[12] { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 };
|
||||
|
||||
public int __main(string[] args)
|
||||
{
|
||||
if (args.Length < 2 || args.Length > 3)
|
||||
{
|
||||
Console.WriteLine("Syntax: px_p8 [-t] filename");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sectors;
|
||||
if (args.Length == 2 && args[0] == "-t")
|
||||
{
|
||||
args[0] = args[1];
|
||||
sectors = 2352;
|
||||
}
|
||||
else
|
||||
{
|
||||
sectors = 4704;
|
||||
}
|
||||
|
||||
Stream sector_file;
|
||||
try
|
||||
{
|
||||
sector_file = File.OpenRead(args[1]);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.Error.WriteLine(ex);
|
||||
return 1;
|
||||
}
|
||||
|
||||
byte[] sector = new byte[sectors];
|
||||
if (args.Length == 2)
|
||||
{
|
||||
uint hex;
|
||||
for (int i = 0; sector_file.Position < sector_file.Length && i < 3252; i++)
|
||||
{
|
||||
byte[] buf = new byte[2];
|
||||
hex = uint.Parse(Encoding.ASCII.GetString(buf), NumberStyles.HexNumber);
|
||||
sector[i] = (byte)hex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sector_file.Read(sector, 0, sectors);
|
||||
}
|
||||
|
||||
int offset = MemSearch(sector, sync, sectors, 12);
|
||||
if (offset == -1)
|
||||
{
|
||||
Console.WriteLine("Error searching for sync!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Console.WriteLine($"MSF: {sector[offset + 12]:2x}:{sector[offset + 12 + 1]:2x}:{sector[offset + 12 + 2]:2x}");
|
||||
|
||||
int shiftRegister = 0x1;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
sector[offset + 12 + i] ^= (byte)(shiftRegister & 0xFF);
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int hibit = ((shiftRegister & 1) ^ ((shiftRegister & 2) >> 1)) << 15;
|
||||
shiftRegister = (hibit | shiftRegister) >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
int start_sector = (btoi(sector[offset + 12]) * 60 + btoi(sector[offset + 13])) * 75 + btoi(sector[offset + 14]) - 150;
|
||||
|
||||
Console.WriteLine($"MSF: {sector[offset + 12]:2x}:{sector[offset + 12 + 1]:2x}:{sector[offset + 12 + 2]:2x}");
|
||||
|
||||
offset -= start_sector * 2352;
|
||||
|
||||
Console.WriteLine($"Combined offset: {offset} bytes / {offset / 4} samples");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search for a byte array in another
|
||||
/// </summary>
|
||||
private int MemSearch(in byte[] buf_where, in byte[] buf_search, int buf_where_len, int buf_search_len)
|
||||
{
|
||||
for (int i = 0; i <= buf_where_len - buf_search_len; i++)
|
||||
{
|
||||
for (int j = 0; j < buf_search_len; j++)
|
||||
{
|
||||
if (buf_where[i + j] != buf_search[j])
|
||||
break;
|
||||
|
||||
if (j + 1 == buf_search_len)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
310
BurnOutSharp/External/psxt001z/Track.cs
vendored
Normal file
310
BurnOutSharp/External/psxt001z/Track.cs
vendored
Normal file
@@ -0,0 +1,310 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace psxt001z
|
||||
{
|
||||
internal class Track
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Original input path for the track
|
||||
/// </summary>
|
||||
private string InputPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Stream representing the track data
|
||||
/// </summary>
|
||||
private Stream InputStream { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Output for saving the track data
|
||||
/// </summary>
|
||||
private string OutputPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Starting offset within the file
|
||||
/// </summary>
|
||||
private int Start { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Size of the input file
|
||||
/// </summary>
|
||||
private int Size { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// CRC-32 of the track data to compare against
|
||||
/// </summary>
|
||||
private uint CRC32 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Audio data header
|
||||
/// </summary>
|
||||
private byte[] RiffData { get; set; } = new byte[44];
|
||||
|
||||
/// <summary>
|
||||
/// True if the track is audio data
|
||||
/// </summary>
|
||||
private bool IsRiff { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the file is under ~100MB
|
||||
/// </summary>
|
||||
private bool SmallFile { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// True to write out the track data
|
||||
/// </summary>
|
||||
private bool SaveTrack { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True means '+' or 'p'
|
||||
/// False means '-' or 'n'
|
||||
/// Null means neither
|
||||
/// </summary>
|
||||
private bool? Mode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cache for small file data
|
||||
/// </summary>
|
||||
private byte[] FileContents { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cached file offset
|
||||
/// </summary>
|
||||
private int Offset { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Current file offset
|
||||
/// </summary>
|
||||
private int Current { get; set; } = 0;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public Track(string filename, int start, int size, uint crc, bool isRiff = false, bool? mode = null, string output = null)
|
||||
{
|
||||
InputPath = filename;
|
||||
InputStream = File.OpenRead(filename);
|
||||
OutputPath = output;
|
||||
|
||||
Start = start;
|
||||
Size = size;
|
||||
CRC32 = crc;
|
||||
Mode = mode;
|
||||
|
||||
IsRiff = isRiff;
|
||||
SmallFile = Size <= 100_000_000;
|
||||
SaveTrack = output != null;
|
||||
|
||||
Console.WriteLine($"File: {InputPath}\nStart: {Start}\nSize: {Size}\nCRC-32: {CRC32:8x}");
|
||||
Console.WriteLine();
|
||||
|
||||
if (IsRiff)
|
||||
PopulateRiffData();
|
||||
|
||||
if (SmallFile)
|
||||
CacheFileData();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functions
|
||||
|
||||
public bool FindTrack()
|
||||
{
|
||||
// Positive mode
|
||||
if (Mode == true)
|
||||
{
|
||||
if (Current > 20000)
|
||||
{
|
||||
Mode = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
Offset = Current;
|
||||
Current += 4;
|
||||
return MatchesCRC();
|
||||
}
|
||||
|
||||
// Negative mode
|
||||
else if (Mode == false)
|
||||
{
|
||||
if (Current > 20000)
|
||||
{
|
||||
Mode = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
Offset = -Current;
|
||||
Current += 4;
|
||||
return MatchesCRC();
|
||||
}
|
||||
|
||||
// Neutral mode
|
||||
else
|
||||
{
|
||||
if (Current > 20000)
|
||||
{
|
||||
Mode = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
Offset = Current;
|
||||
if (MatchesCRC())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Offset = -Current;
|
||||
Current += 4;
|
||||
return MatchesCRC();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool MatchesCRC()
|
||||
{
|
||||
CRC32 calc = new CRC32();
|
||||
if (SmallFile)
|
||||
{
|
||||
if (IsRiff)
|
||||
calc.ProcessCRC(RiffData, 0, 44);
|
||||
|
||||
calc.ProcessCRC(FileContents, (int)(20000 + Offset), (int)Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
InputStream.Seek(Start + Offset, SeekOrigin.Begin);
|
||||
if (IsRiff)
|
||||
calc.ProcessCRC(RiffData, 0, 44);
|
||||
|
||||
for (long i = 0; i < Size; i++)
|
||||
{
|
||||
byte[] buffer = new byte[1];
|
||||
if (InputStream.Read(buffer, 0, 1) != 1)
|
||||
{
|
||||
buffer[0] = 0x00;
|
||||
InputStream.Seek(Start + Offset + i + 1, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
calc.ProcessCRC(buffer, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
Console.Write($"Offset correction {Offset} bytes, {Offset / 4} samples, CRC-32 {calc.m_crc32:8x}");
|
||||
return (calc.m_crc32 == CRC32);
|
||||
}
|
||||
|
||||
public void Done()
|
||||
{
|
||||
if (SmallFile)
|
||||
FileContents = null;
|
||||
|
||||
if (Mode == null)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Can't find offset!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (SaveTrack)
|
||||
{
|
||||
byte[] buffer = new byte[1];
|
||||
Stream f2 = File.Open(OutputPath, FileMode.Create, FileAccess.ReadWrite);
|
||||
if (IsRiff)
|
||||
f2.Write(RiffData, 0, 44);
|
||||
|
||||
InputStream.Seek(Start + Offset, SeekOrigin.Begin);
|
||||
for (long i = 0; i < Size; i++)
|
||||
{
|
||||
if (InputStream.Read(buffer, 0, 1) != 1)
|
||||
{
|
||||
buffer[0] = 0x00;
|
||||
InputStream.Seek(Start + Offset + i + 1, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
f2.Write(buffer, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
Console.Write("DONE!");
|
||||
Console.WriteLine();
|
||||
Console.Write($"Offset correction: {Offset} bytes / {Offset / 4} samples");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Utilities
|
||||
|
||||
// TODO: Figure out what this actually does
|
||||
private void CacheFileData()
|
||||
{
|
||||
FileContents = new byte[Size + 40000];
|
||||
InputStream.Seek(Start - 20000, SeekOrigin.Begin);
|
||||
|
||||
for (int i = 0; i < Size + 40000; i++)
|
||||
{
|
||||
if (Start + i <= 20000)
|
||||
InputStream.Seek(Start + i - 20000, SeekOrigin.Begin);
|
||||
|
||||
if (InputStream.Read(new byte[1], 0, 1) != 1)
|
||||
FileContents[i] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
private void PopulateRiffData()
|
||||
{
|
||||
RiffData[0] = 0x52;
|
||||
RiffData[1] = 0x49;
|
||||
RiffData[2] = 0x46;
|
||||
RiffData[3] = 0x46;
|
||||
|
||||
byte[] temp = BitConverter.GetBytes(Size - 8);
|
||||
Array.Copy(temp, 0, RiffData, 4, 4);
|
||||
|
||||
RiffData[8] = 0x57;
|
||||
RiffData[9] = 0x41;
|
||||
RiffData[10] = 0x56;
|
||||
RiffData[11] = 0x45;
|
||||
RiffData[12] = 0x66;
|
||||
RiffData[13] = 0x6D;
|
||||
RiffData[14] = 0x74;
|
||||
RiffData[15] = 0x20;
|
||||
RiffData[16] = 0x10;
|
||||
RiffData[17] = 0x00;
|
||||
RiffData[18] = 0x00;
|
||||
RiffData[19] = 0x00;
|
||||
RiffData[20] = 0x01;
|
||||
RiffData[21] = 0x00;
|
||||
RiffData[22] = 0x02;
|
||||
RiffData[23] = 0x00;
|
||||
RiffData[24] = 0x44;
|
||||
RiffData[25] = 0xAC;
|
||||
RiffData[26] = 0x00;
|
||||
RiffData[27] = 0x00;
|
||||
RiffData[28] = 0x10;
|
||||
RiffData[29] = 0xB1;
|
||||
RiffData[30] = 0x02;
|
||||
RiffData[31] = 0x00;
|
||||
RiffData[32] = 0x04;
|
||||
RiffData[33] = 0x00;
|
||||
RiffData[34] = 0x10;
|
||||
RiffData[35] = 0x00;
|
||||
RiffData[36] = 0x64;
|
||||
RiffData[37] = 0x61;
|
||||
RiffData[38] = 0x74;
|
||||
RiffData[39] = 0x61;
|
||||
|
||||
temp = BitConverter.GetBytes(Size - 44);
|
||||
Array.Copy(temp, 0, RiffData, 40, 4);
|
||||
|
||||
Size -= 44;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.Deflate;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class BFPK : IScannable
|
||||
public class BFPK : IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic)
|
||||
@@ -19,7 +21,7 @@ namespace BurnOutSharp.FileType
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<string, List<string>> Scan(Scanner scanner, string file)
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, string file)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
@@ -31,7 +33,7 @@ namespace BurnOutSharp.FileType
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
// If the BFPK file itself fails
|
||||
try
|
||||
@@ -61,7 +63,7 @@ namespace BurnOutSharp.FileType
|
||||
|
||||
br.BaseStream.Seek(offset, SeekOrigin.Begin);
|
||||
uint compressedSize = br.ReadUInt32();
|
||||
|
||||
|
||||
// Some files can lack the length prefix
|
||||
if (compressedSize > br.BaseStream.Length)
|
||||
{
|
||||
@@ -100,8 +102,11 @@ namespace BurnOutSharp.FileType
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
br.BaseStream.Seek(current, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
@@ -114,14 +119,20 @@ namespace BurnOutSharp.FileType
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.BZip2;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class BZip2 : IScannable
|
||||
public class BZip2 : IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic)
|
||||
@@ -18,7 +20,7 @@ namespace BurnOutSharp.FileType
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<string, List<string>> Scan(Scanner scanner, string file)
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, string file)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
@@ -30,7 +32,7 @@ namespace BurnOutSharp.FileType
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
// If the BZip2 file itself fails
|
||||
try
|
||||
@@ -49,7 +51,10 @@ namespace BurnOutSharp.FileType
|
||||
bz2File.CopyTo(fs);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
@@ -60,14 +65,20 @@ namespace BurnOutSharp.FileType
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.NE;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class Executable : IScannable
|
||||
public class Executable : IScannable
|
||||
{
|
||||
/// <summary>
|
||||
/// Cache for all IContentCheck types
|
||||
/// </summary>
|
||||
private static readonly IEnumerable<IContentCheck> contentCheckClasses = InitContentCheckClasses();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic)
|
||||
{
|
||||
@@ -49,7 +47,7 @@ namespace BurnOutSharp.FileType
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<string, List<string>> Scan(Scanner scanner, string file)
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, string file)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
@@ -61,58 +59,135 @@ namespace BurnOutSharp.FileType
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
// Load the current file content
|
||||
byte[] fileContent = null;
|
||||
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
|
||||
{
|
||||
fileContent = br.ReadBytes((int)stream.Length);
|
||||
}
|
||||
|
||||
// If we can, seek to the beginning of the stream
|
||||
if (stream.CanSeek)
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
// Files can be protected in multiple ways
|
||||
var protections = new Dictionary<string, List<string>>();
|
||||
var protections = new ConcurrentDictionary<string, ConcurrentQueue<string>>();
|
||||
|
||||
// Iterate through all content checks
|
||||
foreach (var contentCheckClass in contentCheckClasses)
|
||||
// Load the current file content for debug only
|
||||
byte[] fileContent = null;
|
||||
if (scanner.IncludeDebug)
|
||||
{
|
||||
string protection = contentCheckClass.CheckContents(file, fileContent, scanner.IncludePosition);
|
||||
|
||||
// If we have a valid content check based on settings
|
||||
if (!contentCheckClass.GetType().Namespace.ToLowerInvariant().Contains("packertype") || scanner.ScanPackers)
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
}
|
||||
|
||||
// If we have an IScannable implementation
|
||||
if (contentCheckClass is IScannable)
|
||||
{
|
||||
IScannable scannable = contentCheckClass as IScannable;
|
||||
if (file != null && !string.IsNullOrEmpty(protection))
|
||||
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
|
||||
{
|
||||
var subProtections = scannable.Scan(scanner, null, file);
|
||||
Utilities.PrependToKeys(subProtections, file);
|
||||
Utilities.AppendToDictionary(protections, subProtections);
|
||||
fileContent = br.ReadBytes((int)stream.Length);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
|
||||
Utilities.AppendToDictionary(protections, file, "[Out of memory attempting to open]");
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
|
||||
// Create PortableExecutable and NewExecutable objects for use in the checks
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
PortableExecutable pex = new PortableExecutable(stream);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
NewExecutable nex = new NewExecutable(stream);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
// Iterate through all generic content checks
|
||||
if (fileContent != null)
|
||||
{
|
||||
Parallel.ForEach(ScanningClasses.ContentCheckClasses, contentCheckClass =>
|
||||
{
|
||||
string protection = contentCheckClass.CheckContents(file, fileContent, scanner.IncludeDebug);
|
||||
if (ShouldAddProtection(contentCheckClass, scanner.ScanPackers, protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// If we have an IScannable implementation
|
||||
if (contentCheckClass is IScannable scannable)
|
||||
{
|
||||
if (file != null && !string.IsNullOrEmpty(protection))
|
||||
{
|
||||
var subProtections = scannable.Scan(scanner, null, file);
|
||||
Utilities.PrependToKeys(subProtections, file);
|
||||
Utilities.AppendToDictionary(protections, subProtections);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// If we have a NE executable, iterate through all NE content checks
|
||||
if (nex?.Initialized == true)
|
||||
{
|
||||
Parallel.ForEach(ScanningClasses.NewExecutableCheckClasses, contentCheckClass =>
|
||||
{
|
||||
// Check using custom content checks first
|
||||
string protection = contentCheckClass.CheckNewExecutable(file, nex, scanner.IncludeDebug);
|
||||
if (ShouldAddProtection(contentCheckClass, scanner.ScanPackers, protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// If we have an IScannable implementation
|
||||
if (contentCheckClass is IScannable scannable)
|
||||
{
|
||||
if (file != null && !string.IsNullOrEmpty(protection))
|
||||
{
|
||||
var subProtections = scannable.Scan(scanner, null, file);
|
||||
Utilities.PrependToKeys(subProtections, file);
|
||||
Utilities.AppendToDictionary(protections, subProtections);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// If we have a PE executable, iterate through all PE content checks
|
||||
if (pex?.Initialized == true)
|
||||
{
|
||||
// Print the section table for debug
|
||||
if (scanner.IncludeDebug && pex.SectionTable != null)
|
||||
pex.PrintAllSections();
|
||||
|
||||
Parallel.ForEach(ScanningClasses.PortableExecutableCheckClasses, contentCheckClass =>
|
||||
{
|
||||
// Check using custom content checks first
|
||||
string protection = contentCheckClass.CheckPortableExecutable(file, pex, scanner.IncludeDebug);
|
||||
if (ShouldAddProtection(contentCheckClass, scanner.ScanPackers, protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// If we have an IScannable implementation
|
||||
if (contentCheckClass is IScannable scannable)
|
||||
{
|
||||
if (file != null && !string.IsNullOrEmpty(protection))
|
||||
{
|
||||
var subProtections = scannable.Scan(scanner, null, file);
|
||||
Utilities.PrependToKeys(subProtections, file);
|
||||
Utilities.AppendToDictionary(protections, subProtections);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Initialize all IContentCheck implementations
|
||||
/// Check to see if a protection should be added or not
|
||||
/// </summary>
|
||||
private static IEnumerable<IContentCheck> InitContentCheckClasses()
|
||||
/// <param name="checkClass">Class that was last used to check</param>
|
||||
/// <param name="scanPackers">Determines if packers should be included in the output</param>
|
||||
/// <param name="protection">The protection result to be checked</param>
|
||||
private bool ShouldAddProtection(object checkClass, bool scanPackers, string protection)
|
||||
{
|
||||
return Assembly.GetExecutingAssembly().GetTypes()
|
||||
.Where(t => t.IsClass && t.GetInterface(nameof(IContentCheck)) != null)
|
||||
.Select(t => Activator.CreateInstance(t) as IContentCheck);
|
||||
// If we have an invalid protection
|
||||
if (string.IsNullOrWhiteSpace(protection))
|
||||
return false;
|
||||
|
||||
// If we have a valid content check based on settings
|
||||
if (scanPackers || !checkClass.GetType().Namespace.ToLowerInvariant().Contains("packertype"))
|
||||
return true;
|
||||
|
||||
// Everything else fails
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.GZip;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class GZIP : IScannable
|
||||
public class GZIP : IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic)
|
||||
@@ -18,7 +20,7 @@ namespace BurnOutSharp.FileType
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<string, List<string>> Scan(Scanner scanner, string file)
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, string file)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
@@ -30,7 +32,7 @@ namespace BurnOutSharp.FileType
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
// If the gzip file itself fails
|
||||
try
|
||||
@@ -52,7 +54,10 @@ namespace BurnOutSharp.FileType
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,14 +69,20 @@ namespace BurnOutSharp.FileType
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
111
BurnOutSharp/FileType/InstallShieldArchiveV3.cs
Normal file
111
BurnOutSharp/FileType/InstallShieldArchiveV3.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
using UnshieldSharp.Archive;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
public class InstallShieldArchiveV3 : IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte?[] { 0x13, 0x5D, 0x65, 0x8C }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, string file)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.OpenRead(file))
|
||||
{
|
||||
return Scan(scanner, fs, file);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add stream opening support
|
||||
/// <inheritdoc/>
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
// Get the name of the first cabinet file or header
|
||||
string directory = Path.GetDirectoryName(file);
|
||||
string noExtension = Path.GetFileNameWithoutExtension(file);
|
||||
string filenamePattern = Path.Combine(directory, noExtension);
|
||||
filenamePattern = new Regex(@"\d+$").Replace(filenamePattern, string.Empty);
|
||||
|
||||
bool cabinetHeaderExists = File.Exists(Path.Combine(directory, filenamePattern + "1.hdr"));
|
||||
bool shouldScanCabinet = cabinetHeaderExists
|
||||
? file.Equals(Path.Combine(directory, filenamePattern + "1.hdr"), StringComparison.OrdinalIgnoreCase)
|
||||
: file.Equals(Path.Combine(directory, filenamePattern + "1.cab"), StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
// If we have the first file
|
||||
if (shouldScanCabinet)
|
||||
{
|
||||
// If the cab file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
UnshieldSharp.Archive.InstallShieldArchiveV3 archive = new UnshieldSharp.Archive.InstallShieldArchiveV3(file);
|
||||
foreach (CompressedFile cfile in archive.Files.Select(kvp => kvp.Value))
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, cfile.FullPath);
|
||||
if (!Directory.Exists(Path.GetDirectoryName(tempFile)))
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
|
||||
|
||||
(byte[] fileContents, string error) = archive.Extract(cfile.FullPath);
|
||||
if (!string.IsNullOrWhiteSpace(error))
|
||||
continue;
|
||||
|
||||
using (FileStream fs = File.OpenWrite(tempFile))
|
||||
{
|
||||
fs.Write(fileContents, 0, fileContents.Length);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
var protections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnshieldSharp;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
using UnshieldSharp.Cabinet;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class InstallShieldCAB : IScannable
|
||||
public class InstallShieldCAB : IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic)
|
||||
@@ -18,7 +20,7 @@ namespace BurnOutSharp.FileType
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<string, List<string>> Scan(Scanner scanner, string file)
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, string file)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
@@ -31,7 +33,7 @@ namespace BurnOutSharp.FileType
|
||||
|
||||
// TODO: Add stream opening support
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
// Get the name of the first cabinet file or header
|
||||
string directory = Path.GetDirectoryName(file);
|
||||
@@ -53,16 +55,29 @@ namespace BurnOutSharp.FileType
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
UnshieldCabinet cabfile = UnshieldCabinet.Open(file);
|
||||
InstallShieldCabinet cabfile = InstallShieldCabinet.Open(file);
|
||||
for (int i = 0; i < cabfile.FileCount; i++)
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, cabfile.FileName(i));
|
||||
string filename = cabfile.FileName(i);
|
||||
string tempFile;
|
||||
try
|
||||
{
|
||||
tempFile = Path.Combine(tempPath, filename);
|
||||
}
|
||||
catch
|
||||
{
|
||||
tempFile = Path.Combine(tempPath, $"BAD_FILENAME{i}");
|
||||
}
|
||||
|
||||
cabfile.FileSave(i, tempFile);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
@@ -73,14 +88,20 @@ namespace BurnOutSharp.FileType
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using WixToolset.Dtf.WindowsInstaller;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
using OpenMcdf;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class MSI : IScannable
|
||||
public class MSI : IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic)
|
||||
@@ -17,7 +20,7 @@ namespace BurnOutSharp.FileType
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<string, List<string>> Scan(Scanner scanner, string file)
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, string file)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
@@ -30,7 +33,7 @@ namespace BurnOutSharp.FileType
|
||||
|
||||
// TODO: Add stream opening support
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
// If the MSI file itself fails
|
||||
try
|
||||
@@ -38,9 +41,39 @@ namespace BurnOutSharp.FileType
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (Database msidb = new Database(file, DatabaseOpenMode.ReadOnly))
|
||||
using (CompoundFile msi = new CompoundFile(stream, CFSUpdateMode.ReadOnly, CFSConfiguration.Default))
|
||||
{
|
||||
msidb.ExportAll(tempPath);
|
||||
msi.RootStorage.VisitEntries((e) =>
|
||||
{
|
||||
if (!e.IsStream)
|
||||
return;
|
||||
|
||||
var str = msi.RootStorage.GetStream(e.Name);
|
||||
if (str == null)
|
||||
return;
|
||||
|
||||
byte[] strData = str.GetData();
|
||||
if (strData == null)
|
||||
return;
|
||||
|
||||
string decoded = DecodeStreamName(e.Name).TrimEnd('\0');
|
||||
byte[] nameBytes = Encoding.UTF8.GetBytes(e.Name);
|
||||
|
||||
// UTF-8 encoding of 0x4840.
|
||||
if (nameBytes[0] == 0xe4 && nameBytes[1] == 0xa1 && nameBytes[2] == 0x80)
|
||||
decoded = decoded.Substring(3);
|
||||
|
||||
foreach (char c in Path.GetInvalidFileNameChars())
|
||||
{
|
||||
decoded = decoded.Replace(c, '_');
|
||||
}
|
||||
|
||||
string filename = Path.Combine(tempPath, decoded);
|
||||
using (Stream fs = File.OpenWrite(filename))
|
||||
{
|
||||
fs.Write(strData, 0, strData.Length);
|
||||
}
|
||||
}, recursive: true);
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
@@ -51,16 +84,85 @@ namespace BurnOutSharp.FileType
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
// Remove temporary path references
|
||||
Utilities.StripFromKeys(protections, tempPath);
|
||||
|
||||
return protections;
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <remarks>Adapted from LibMSI</remarks>
|
||||
private static string DecodeStreamName(string input)
|
||||
{
|
||||
if (input == null)
|
||||
return null;
|
||||
|
||||
int count = 0;
|
||||
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
|
||||
int p = 0; // inputBytes[0]
|
||||
|
||||
byte[] output = new byte[inputBytes.Length + 1];
|
||||
int q = 0; // output[0]
|
||||
while (p < inputBytes.Length && inputBytes[p] != 0)
|
||||
{
|
||||
int ch = inputBytes[p];
|
||||
if ((ch == 0xe3 && inputBytes[p + 1] >= 0xa0) || (ch == 0xe4 && inputBytes[p + 1] < 0xa0))
|
||||
{
|
||||
// UTF-8 encoding of 0x3800..0x47ff.
|
||||
output[q++] = (byte)Mime2Utf(inputBytes[p + 2] & 0x7f);
|
||||
output[q++] = (byte)Mime2Utf(inputBytes[p + 1] ^ 0xa0);
|
||||
p += 3;
|
||||
count += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == 0xe4 && inputBytes[p + 1] == 0xa0)
|
||||
{
|
||||
// UTF-8 encoding of 0x4800..0x483f.
|
||||
output[q++] = (byte)Mime2Utf(inputBytes[p + 2] & 0x7f);
|
||||
p += 3;
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
output[q++] = inputBytes[p++];
|
||||
if (ch >= 0xc1)
|
||||
output[q++] = inputBytes[p++];
|
||||
if (ch >= 0xe0)
|
||||
output[q++] = inputBytes[p++];
|
||||
if (ch >= 0xf0)
|
||||
output[q++] = inputBytes[p++];
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
output[q] = 0;
|
||||
return Encoding.ASCII.GetString(output);
|
||||
}
|
||||
|
||||
/// <remarks>Adapted from LibMSI</remarks>
|
||||
private static int Mime2Utf(int x)
|
||||
{
|
||||
if (x < 10)
|
||||
return x + '0';
|
||||
if (x < (10 + 26))
|
||||
return x - 10 + 'A';
|
||||
if (x < (10 + 26 + 26))
|
||||
return x - 10 - 26 + 'a';
|
||||
if (x == (10 + 26 + 26))
|
||||
return '.';
|
||||
return '_';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user