mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-02-05 13:49:37 +00:00
Compare commits
335 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac917df519 | ||
|
|
3b12fef948 | ||
|
|
a74b769aef | ||
|
|
ea17ad1eae | ||
|
|
6087e6e0c6 | ||
|
|
535f14bc54 | ||
|
|
6b3d42b81f | ||
|
|
e645b8e1c0 | ||
|
|
955c8685b6 | ||
|
|
6184ae22aa | ||
|
|
4e2c5313f3 | ||
|
|
137f7fcc01 | ||
|
|
d771c4931c | ||
|
|
61a2181924 | ||
|
|
baad181e5f | ||
|
|
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 |
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 = 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,23 +1,26 @@
|
||||
|
||||
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("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WixToolset", "WixToolset", "{09D405CA-CF15-4929-8408-C970F0656C62}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HLLibSharp", "HLLibSharp\HLLibSharp\HLLibSharp.csproj", "{14E9764A-A8BF-44C0-A1A8-2C95EA307040}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{182E02A8-5E8E-4140-9C9B-61049C33E921}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibMSPackSharp", "LibMSPackSharp\LibMSPackSharp\LibMSPackSharp.csproj", "{BD8144B8-4857-47E6-9717-E9F2DB374A89}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WixToolset.Dtf.WindowsInstaller", "WixToolset\src\WixToolset.Dtf.WindowsInstaller\WixToolset.Dtf.WindowsInstaller.csproj", "{B3537EB7-CEF6-4D90-A041-47626442A656}"
|
||||
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
|
||||
@@ -33,10 +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
|
||||
{B3537EB7-CEF6-4D90-A041-47626442A656}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B3537EB7-CEF6-4D90-A041-47626442A656}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B3537EB7-CEF6-4D90-A041-47626442A656}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B3537EB7-CEF6-4D90-A041-47626442A656}.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
|
||||
@@ -44,8 +59,4 @@ Global
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {0B343DD2-8852-47B0-9647-DFCFBEDF933C}
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{182E02A8-5E8E-4140-9C9B-61049C33E921} = {09D405CA-CF15-4929-8408-C970F0656C62}
|
||||
{B3537EB7-CEF6-4D90-A041-47626442A656} = {182E02A8-5E8E-4140-9C9B-61049C33E921}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -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.8.0</Version>
|
||||
<AssemblyVersion>1.8.0</AssemblyVersion>
|
||||
<FileVersion>1.8.0</FileVersion>
|
||||
<Version>2.3.4</Version>
|
||||
<AssemblyVersion>2.3.4</AssemblyVersion>
|
||||
<FileVersion>2.3.4</FileVersion>
|
||||
<IncludeSource>true</IncludeSource>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
</PropertyGroup>
|
||||
@@ -23,14 +22,16 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SharpCompress" Version="0.29.0" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" />
|
||||
<PackageReference Include="Teronis.MSBuild.Packaging.ProjectBuildInPackage" Version="0.1.7">
|
||||
<PackageReference Include="OpenMcdf" Version="2.2.1.12" />
|
||||
<PackageReference Include="SharpCompress" Version="0.32.2" />
|
||||
<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.6" />
|
||||
<PackageReference Include="WiseUnpacker" Version="1.0.2" />
|
||||
<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 -->
|
||||
@@ -38,12 +39,6 @@
|
||||
<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\**
|
||||
</DefaultItemExcludes>
|
||||
@@ -62,7 +57,20 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WixToolset\src\WixToolset.Dtf.WindowsInstaller\WixToolset.Dtf.WindowsInstaller.csproj">
|
||||
<ProjectReference Include="..\Dtf\src\WixToolset.Dtf.Compression\WixToolset.Dtf.Compression.csproj">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Dtf\src\WixToolset.Dtf.Compression.Cab\WixToolset.Dtf.Compression.Cab.csproj">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\HLLibSharp\HLLibSharp\HLLibSharp.csproj">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\LibMSPackSharp\LibMSPackSharp\LibMSPackSharp.csproj">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Resource type and name strings
|
||||
/// </summary>
|
||||
public class NEResourceNameString
|
||||
{
|
||||
/// <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 NEResourceNameString Deserialize(Stream stream)
|
||||
{
|
||||
var rds = new NEResourceNameString();
|
||||
|
||||
rds.Length = stream.ReadByteValue();
|
||||
rds.Value = stream.ReadChars(rds.Length, Encoding.ASCII);
|
||||
|
||||
return rds;
|
||||
}
|
||||
|
||||
public static NEResourceNameString Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var rds = new NEResourceNameString();
|
||||
|
||||
rds.Length = content.ReadByte(ref offset);
|
||||
rds.Value = Encoding.ASCII.GetChars(content, offset, rds.Length); offset += rds.Length;
|
||||
|
||||
return rds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,83 @@ using System;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#debug-type
|
||||
public enum DebugType : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// An unknown value that is ignored by all tools.
|
||||
/// </summary>
|
||||
IMAGE_DEBUG_TYPE_UNKNOWN = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The COFF debug information (line numbers, symbol table, and string table).
|
||||
/// This type of debug information is also pointed to by fields in the file headers.
|
||||
/// </summary>
|
||||
IMAGE_DEBUG_TYPE_COFF = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The Visual C++ debug information.
|
||||
/// </summary>
|
||||
IMAGE_DEBUG_TYPE_CODEVIEW = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The frame pointer omission (FPO) information.
|
||||
/// This information tells the debugger how to interpret nonstandard stack frames,
|
||||
/// which use the EBP register for a purpose other than as a frame pointer.
|
||||
/// </summary>
|
||||
IMAGE_DEBUG_TYPE_FPO = 3,
|
||||
|
||||
/// <summary>
|
||||
/// The location of DBG file.
|
||||
/// </summary>
|
||||
IMAGE_DEBUG_TYPE_MISC = 4,
|
||||
|
||||
/// <summary>
|
||||
/// A copy of .pdata section.
|
||||
/// </summary>
|
||||
IMAGE_DEBUG_TYPE_EXCEPTION = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Reserved.
|
||||
/// </summary>
|
||||
IMAGE_DEBUG_TYPE_FIXUP = 6,
|
||||
|
||||
/// <summary>
|
||||
/// The mapping from an RVA in image to an RVA in source image.
|
||||
/// </summary>
|
||||
IMAGE_DEBUG_TYPE_OMAP_TO_SRC = 7,
|
||||
|
||||
/// <summary>
|
||||
/// The mapping from an RVA in source image to an RVA in image.
|
||||
/// </summary>
|
||||
IMAGE_DEBUG_TYPE_OMAP_FROM_SRC = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Reserved for Borland.
|
||||
/// </summary>
|
||||
IMAGE_DEBUG_TYPE_BORLAND = 9,
|
||||
|
||||
/// <summary>
|
||||
/// Reserved.
|
||||
/// </summary>
|
||||
IMAGE_DEBUG_TYPE_RESERVED10 = 10,
|
||||
|
||||
/// <summary>
|
||||
/// Reserved.
|
||||
/// </summary>
|
||||
IMAGE_DEBUG_TYPE_CLSID = 11,
|
||||
|
||||
/// <summary>
|
||||
/// PE determinism or reproducibility.
|
||||
/// </summary>
|
||||
IMAGE_DEBUG_TYPE_REPRO = 16,
|
||||
|
||||
/// <summary>
|
||||
/// Extended DLL characteristics bits.
|
||||
/// </summary>
|
||||
IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS = 20,
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#dll-characteristics
|
||||
[Flags]
|
||||
public enum DllCharacteristics : ushort
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
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),
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.NE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// A table of resources for this type
|
||||
/// </summary>
|
||||
public class NEResourceTableEntry
|
||||
public class ResourceTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// File offset to the contents of the resource data,
|
||||
@@ -45,9 +44,9 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
/// </summary>
|
||||
public ushort Usage;
|
||||
|
||||
public static NEResourceTableEntry Deserialize(Stream stream)
|
||||
public static ResourceTableEntry Deserialize(Stream stream)
|
||||
{
|
||||
var ni = new NEResourceTableEntry();
|
||||
var ni = new ResourceTableEntry();
|
||||
|
||||
ni.Offset = stream.ReadUInt16();
|
||||
ni.Length = stream.ReadUInt16();
|
||||
@@ -59,9 +58,9 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
return ni;
|
||||
}
|
||||
|
||||
public static NEResourceTableEntry Deserialize(byte[] content, ref int offset)
|
||||
public static ResourceTableEntry Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var ni = new NEResourceTableEntry();
|
||||
var ni = new ResourceTableEntry();
|
||||
|
||||
ni.Offset = content.ReadUInt16(ref offset);
|
||||
ni.Length = content.ReadUInt16(ref offset);
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.NE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Resource type information block
|
||||
@@ -31,7 +30,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
/// <summary>
|
||||
/// Reserved.
|
||||
/// </summary>
|
||||
public NEResourceTableEntry[] ResourceTable;
|
||||
public ResourceTableEntry[] ResourceTable;
|
||||
|
||||
public static ResourceTypeInformationBlock Deserialize(Stream stream)
|
||||
{
|
||||
@@ -41,10 +40,10 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
rtib.ResourceCount = stream.ReadUInt16();
|
||||
rtib.Reserved = stream.ReadUInt32();
|
||||
|
||||
rtib.ResourceTable = new NEResourceTableEntry[rtib.ResourceCount];
|
||||
rtib.ResourceTable = new ResourceTableEntry[rtib.ResourceCount];
|
||||
for (int i = 0; i < rtib.ResourceCount; i++)
|
||||
{
|
||||
rtib.ResourceTable[i] = NEResourceTableEntry.Deserialize(stream);
|
||||
rtib.ResourceTable[i] = ResourceTableEntry.Deserialize(stream);
|
||||
}
|
||||
|
||||
return rtib;
|
||||
@@ -58,10 +57,10 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
rtib.ResourceCount = content.ReadUInt16(ref offset);
|
||||
rtib.Reserved = content.ReadUInt32(ref offset);
|
||||
|
||||
rtib.ResourceTable = new NEResourceTableEntry[rtib.ResourceCount];
|
||||
rtib.ResourceTable = new ResourceTableEntry[rtib.ResourceCount];
|
||||
for (int i = 0; i < rtib.ResourceCount; i++)
|
||||
{
|
||||
rtib.ResourceTable[i] = NEResourceTableEntry.Deserialize(content, ref offset);
|
||||
rtib.ResourceTable[i] = ResourceTableEntry.Deserialize(content, ref offset);
|
||||
}
|
||||
|
||||
return rtib;
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.NE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// The segment table contains an entry for each segment in the executable
|
||||
@@ -10,7 +9,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
/// 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 NESegmentTableEntry
|
||||
public class SegmentTableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Logical-sector offset (n byte) to the contents of the segment
|
||||
@@ -35,9 +34,9 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
/// </summary>
|
||||
public ushort MinimumAllocation;
|
||||
|
||||
public static NESegmentTableEntry Deserialize(Stream stream)
|
||||
public static SegmentTableEntry Deserialize(Stream stream)
|
||||
{
|
||||
var nste = new NESegmentTableEntry();
|
||||
var nste = new SegmentTableEntry();
|
||||
|
||||
nste.StartFileSector = stream.ReadUInt16();
|
||||
nste.BytesInFile = stream.ReadUInt16();
|
||||
@@ -47,9 +46,9 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
return nste;
|
||||
}
|
||||
|
||||
public static NESegmentTableEntry Deserialize(byte[] content, ref int offset)
|
||||
public static SegmentTableEntry Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var nste = new NESegmentTableEntry();
|
||||
var nste = new SegmentTableEntry();
|
||||
|
||||
nste.StartFileSector = content.ReadUInt16(ref offset);
|
||||
nste.BytesInFile = content.ReadUInt16(ref offset);
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.NE.Headers
|
||||
{
|
||||
/// <summary>
|
||||
/// The NE header is a relatively large structure with multiple characteristics.
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Entries;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.NE.Entries;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.NE.Tables
|
||||
{
|
||||
/// <summary>
|
||||
/// The resource table follows the segment table and contains entries for
|
||||
@@ -16,7 +15,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
/// 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 NEResourceTable
|
||||
public class ResourceTable
|
||||
{
|
||||
/// <summary>
|
||||
/// Alignment shift count for resource data.
|
||||
@@ -33,13 +32,13 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
/// resource table. Note that these strings are NOT null terminated and
|
||||
/// are case sensitive.
|
||||
/// </summary>
|
||||
public NEResourceNameString[] TypeAndNameStrings;
|
||||
public ResourceNameString[] TypeAndNameStrings;
|
||||
|
||||
public static NEResourceTable Deserialize(Stream stream)
|
||||
public static ResourceTable Deserialize(Stream stream)
|
||||
{
|
||||
var nrt = new NEResourceTable();
|
||||
var rt = new ResourceTable();
|
||||
|
||||
nrt.AlignmentShiftCount = stream.ReadUInt16();
|
||||
rt.AlignmentShiftCount = stream.ReadUInt16();
|
||||
var typeInformationBlocks = new List<ResourceTypeInformationBlock>();
|
||||
while (true)
|
||||
{
|
||||
@@ -50,28 +49,28 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
typeInformationBlocks.Add(block);
|
||||
}
|
||||
|
||||
nrt.TypeInformationBlocks = typeInformationBlocks.ToArray();
|
||||
rt.TypeInformationBlocks = typeInformationBlocks.ToArray();
|
||||
|
||||
var typeAndNameStrings = new List<NEResourceNameString>();
|
||||
var typeAndNameStrings = new List<ResourceNameString>();
|
||||
while (true)
|
||||
{
|
||||
var str = NEResourceNameString.Deserialize(stream);
|
||||
var str = ResourceNameString.Deserialize(stream);
|
||||
if (str.Length == 0)
|
||||
break;
|
||||
|
||||
typeAndNameStrings.Add(str);
|
||||
}
|
||||
|
||||
nrt.TypeAndNameStrings = typeAndNameStrings.ToArray();
|
||||
rt.TypeAndNameStrings = typeAndNameStrings.ToArray();
|
||||
|
||||
return nrt;
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static NEResourceTable Deserialize(byte[] content, ref int offset)
|
||||
public static ResourceTable Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
var nrt = new NEResourceTable();
|
||||
var rt = new ResourceTable();
|
||||
|
||||
nrt.AlignmentShiftCount = content.ReadUInt16(ref offset);
|
||||
rt.AlignmentShiftCount = content.ReadUInt16(ref offset);
|
||||
var typeInformationBlocks = new List<ResourceTypeInformationBlock>();
|
||||
while (true)
|
||||
{
|
||||
@@ -82,21 +81,21 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
typeInformationBlocks.Add(block);
|
||||
}
|
||||
|
||||
nrt.TypeInformationBlocks = typeInformationBlocks.ToArray();
|
||||
rt.TypeInformationBlocks = typeInformationBlocks.ToArray();
|
||||
|
||||
var typeAndNameStrings = new List<NEResourceNameString>();
|
||||
var typeAndNameStrings = new List<ResourceNameString>();
|
||||
while (true)
|
||||
{
|
||||
var str = NEResourceNameString.Deserialize(content, ref offset);
|
||||
var str = ResourceNameString.Deserialize(content, ref offset);
|
||||
if (str.Length == 0)
|
||||
break;
|
||||
|
||||
typeAndNameStrings.Add(str);
|
||||
}
|
||||
|
||||
nrt.TypeAndNameStrings = typeAndNameStrings.ToArray();
|
||||
rt.TypeAndNameStrings = typeAndNameStrings.ToArray();
|
||||
|
||||
return nrt;
|
||||
return rt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Headers;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
/// <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
|
||||
{
|
||||
#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
|
||||
|
||||
// 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)
|
||||
|
||||
public static NewExecutable Deserialize(Stream stream)
|
||||
{
|
||||
NewExecutable nex = new NewExecutable();
|
||||
|
||||
try
|
||||
{
|
||||
// Attempt to read the DOS header first
|
||||
nex.DOSStubHeader = MSDOSExecutableHeader.Deserialize(stream);
|
||||
stream.Seek(nex.DOSStubHeader.NewExeHeaderAddr, SeekOrigin.Begin);
|
||||
if (nex.DOSStubHeader.Magic != Constants.IMAGE_DOS_SIGNATURE)
|
||||
return null;
|
||||
|
||||
// If the new header address is invalid for the file, it's not a NE
|
||||
if (nex.DOSStubHeader.NewExeHeaderAddr >= stream.Length)
|
||||
return null;
|
||||
|
||||
// Then attempt to read the NE header
|
||||
nex.NewExecutableHeader = NewExecutableHeader.Deserialize(stream);
|
||||
if (nex.NewExecutableHeader.Magic != Constants.IMAGE_OS2_SIGNATURE)
|
||||
return null;
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Console.WriteLine($"Errored out on a file: {ex}");
|
||||
return null;
|
||||
}
|
||||
|
||||
return nex;
|
||||
}
|
||||
|
||||
public static NewExecutable Deserialize(byte[] content, int offset)
|
||||
{
|
||||
NewExecutable nex = new NewExecutable();
|
||||
|
||||
try
|
||||
{
|
||||
// Attempt to read the DOS header first
|
||||
nex.DOSStubHeader = MSDOSExecutableHeader.Deserialize(content, ref offset);
|
||||
offset = nex.DOSStubHeader.NewExeHeaderAddr;
|
||||
if (nex.DOSStubHeader.Magic != Constants.IMAGE_DOS_SIGNATURE)
|
||||
return null;
|
||||
|
||||
// If the new header address is invalid for the file, it's not a PE
|
||||
if (nex.DOSStubHeader.NewExeHeaderAddr >= content.Length)
|
||||
return null;
|
||||
|
||||
// Then attempt to read the NE header
|
||||
nex.NewExecutableHeader = NewExecutableHeader.Deserialize(content, ref offset);
|
||||
if (nex.NewExecutableHeader.Magic != Constants.IMAGE_OS2_SIGNATURE)
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Console.WriteLine($"Errored out on a file: {ex}");
|
||||
return null;
|
||||
}
|
||||
|
||||
return nex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Tools;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Headers;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Headers;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
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.
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
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.
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Each entry in the hint/name table has the following format
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Each import address entry has the following format
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Each import directory entry has the following format
|
||||
@@ -2,10 +2,10 @@ using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Headers;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Headers;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Each Resource Data entry describes an actual unit of raw data in the Resource Data area.
|
||||
@@ -33,6 +33,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
if (Data == null || codePage < 0)
|
||||
return string.Empty;
|
||||
|
||||
// Try to convert to UTF-8 first
|
||||
try
|
||||
{
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
@@ -40,11 +41,17 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
byte[] convertedData = Encoding.Convert(originalEncoding, Encoding.UTF8, Data);
|
||||
return Encoding.UTF8.GetString(convertedData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// The resource directory string area consists of Unicode strings, which are word-aligned.
|
||||
@@ -1,10 +1,9 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Headers;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Tables;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Headers;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Tables;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Entries
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// The directory entries make up the rows of a table.
|
||||
@@ -2,7 +2,7 @@ using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Headers
|
||||
{
|
||||
public class CommonObjectFileFormatHeader
|
||||
{
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Headers
|
||||
{
|
||||
public class DataDirectoryHeader
|
||||
{
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Headers
|
||||
{
|
||||
/// <summary>
|
||||
/// Every image file has an optional header that provides information to the loader.
|
||||
@@ -58,7 +57,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
/// 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.
|
||||
/// An entry point is optional for DLLs.
|
||||
/// When no entry point is present, this field must be zero.
|
||||
/// </summary>
|
||||
public uint AddressOfEntryPoint;
|
||||
@@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Headers
|
||||
{
|
||||
/// <summary>
|
||||
/// Each row of the section table is, in effect, a section header.
|
||||
@@ -22,6 +23,35 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Headers
|
||||
/// 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.
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Tables;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Tables;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Sections
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Sections
|
||||
{
|
||||
/// <summary>
|
||||
/// The .pdata section contains an array of function table entries that are used for exception handling.
|
||||
@@ -1,10 +1,10 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Entries;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Headers;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Tables;
|
||||
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.Sections
|
||||
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.
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Tables;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Tables;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Sections
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Sections
|
||||
{
|
||||
/// <summary>
|
||||
/// All image files that import symbols, including virtually all executable (EXE) files, have an .idata section.
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Headers;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Tables;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Headers;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Tables;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Sections
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Sections
|
||||
{
|
||||
/// <summary>
|
||||
/// A series of resource directory tables relates all of the levels in the following way:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
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.
|
||||
@@ -2,7 +2,7 @@ using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Tables
|
||||
{
|
||||
/// <summary>
|
||||
/// The export ordinal table is an array of 16-bit unbiased indexes into the export address table.
|
||||
@@ -1,6 +1,6 @@
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Entries;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Entries;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Tables
|
||||
{
|
||||
/// <summary>
|
||||
/// The .pdata section contains an array of function table entries that are used for exception handling.
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Entries;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Entries;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Tables
|
||||
{
|
||||
/// <summary>
|
||||
/// One hint/name table suffices for the entire import section.
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Entries;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Entries;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
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.
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Entries;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Entries;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Tables
|
||||
{
|
||||
/// <summary>
|
||||
/// The import information begins with the import directory table, which describes the remainder of the import information.
|
||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
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+.
|
||||
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Entries;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Headers;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Entries;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE.Headers;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.Tables
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft.PE.Tables
|
||||
{
|
||||
/// <summary>
|
||||
/// Each resource directory table has the following format.
|
||||
@@ -1,526 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Headers;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.Sections;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ExecutableType.Microsoft
|
||||
{
|
||||
/// <summary>
|
||||
/// The PE file header consists of a Microsoft MS-DOS stub, the PE signature, the COFF file header, and an optional header.
|
||||
/// A COFF object file header consists of a COFF file header and an optional header.
|
||||
/// In both cases, the file headers are followed immediately by section headers.
|
||||
/// </summary>
|
||||
public class PortableExecutable
|
||||
{
|
||||
#region Headers
|
||||
|
||||
/// <summary>
|
||||
/// The MS-DOS stub is a valid application that runs under MS-DOS.
|
||||
/// It is placed at the front of the EXE image.
|
||||
/// The linker places a default stub here, which prints out the message "This program cannot be run in DOS mode" when the image is run in MS-DOS.
|
||||
/// The user can specify a different stub by using the /STUB linker option.
|
||||
/// At location 0x3c, the stub has the file offset to the PE signature.
|
||||
/// This information enables Windows to properly execute the image file, even though it has an MS-DOS stub.
|
||||
/// This file offset is placed at location 0x3c during linking.
|
||||
// </summary>
|
||||
public MSDOSExecutableHeader DOSStubHeader;
|
||||
|
||||
/// <summary>
|
||||
/// At the beginning of an object file, or immediately after the signature of an image file, is a standard COFF file header in the following format.
|
||||
/// Note that the Windows loader limits the number of sections to 96.
|
||||
/// </summary>
|
||||
public CommonObjectFileFormatHeader ImageFileHeader;
|
||||
|
||||
/// <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.
|
||||
/// </summary>
|
||||
public OptionalHeader OptionalHeader;
|
||||
|
||||
/// <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 SectionHeader[] SectionTable;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Tables
|
||||
|
||||
/// <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>
|
||||
public ExportDataSection ExportTable;
|
||||
|
||||
/// <summary>
|
||||
/// All image files that import symbols, including virtually all executable (EXE) files, have an .idata section.
|
||||
/// </summary>
|
||||
public ImportDataSection ImportTable;
|
||||
|
||||
/// <summary>
|
||||
/// Resources are indexed by a multiple-level binary-sorted tree structure.
|
||||
/// The general design can incorporate 2**31 levels.
|
||||
/// By convention, however, Windows uses three levels
|
||||
/// </summary>
|
||||
public ResourceSection ResourceSection;
|
||||
|
||||
// TODO: Add more and more parts of a standard PE executable, not just the header
|
||||
// TODO: Add data directory table information here instead of in IMAGE_OPTIONAL_HEADER
|
||||
|
||||
#endregion
|
||||
|
||||
#region Raw Section Data
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#special-sections
|
||||
// Here is a list of standard sections that are used in various protections:
|
||||
// Y - .bss *1 protection Uninitialized data (free format)
|
||||
// X - .data 14 protections Initialized data (free format)
|
||||
// X - .edata *1 protection Export tables
|
||||
// X - .idata *1 protection Import tables
|
||||
// X - .rdata 11 protections Read-only initialized data
|
||||
// - .rsrc *1 protection Resource directory [Mostly taken care of, last protection needs research]
|
||||
// X - .text 6 protections Executable code (free format)
|
||||
// Y - .tls *1 protection Thread-local storage (object only)
|
||||
//
|
||||
// Here is a list of non-standard sections whose contents are read by various protections:
|
||||
// X - CODE 2 protections SafeDisc, WTM CD Protect
|
||||
// X - .dcrtext *1 protection JoWood
|
||||
// X - .grand *1 protection CD-Cops / DVD-Cops
|
||||
// X - .init *1 protection SolidShield
|
||||
// - .pec2 *1 protection PE Compact [Unconfirmed]
|
||||
// X - .txt2 *1 protection SafeDisc
|
||||
//
|
||||
// Here is a list of non-standard sections whose data is not read by various protections:
|
||||
// - .brick 1 protection StarForce
|
||||
// - .cenega 1 protection Cenega ProtectDVD
|
||||
// - .ext 1 protection JoWood
|
||||
// - HC09 1 protection JoWood
|
||||
// - .icd* 1 protection CodeLock
|
||||
// - .ldr 1 protection 3PLock
|
||||
// - .ldt 1 protection 3PLock
|
||||
// - .nicode 1 protection Armadillo
|
||||
// - .NOS0 1 protection UPX (NOS Variant) [Used as endpoint]
|
||||
// - .NOS1 1 protection UPX (NOS Variant) [Used as endpoint]
|
||||
// - .pec1 1 protection PE Compact
|
||||
// - .securom 1 protection SecuROM
|
||||
// - .sforce 1 protection StarForce
|
||||
// - stxt371 1 protection SafeDisc
|
||||
// - stxt774 1 protection SafeDisc
|
||||
// - .UPX0 1 protection UPX [Used as endpoint]
|
||||
// - .UPX1 1 protection UPX [Used as endpoint]
|
||||
// - .vob.pcd 1 protection VOB ProtectCD
|
||||
// - _winzip_ 1 protection WinZip SFX
|
||||
// - XPROT 1 protection JoWood
|
||||
//
|
||||
// * => Only used by 1 protection so it may be read in by that protection specifically
|
||||
|
||||
/// <summary>
|
||||
/// .data/DATA - Initialized data (free format)
|
||||
/// </summary>
|
||||
public byte[] DataSectionRaw;
|
||||
|
||||
/// <summary>
|
||||
/// .edata - Export tables
|
||||
/// </summary>
|
||||
/// <remarks>Replace with ExportDataSection</remarks>
|
||||
public byte[] ExportDataSectionRaw;
|
||||
|
||||
/// <summary>
|
||||
/// .idata - Import tables
|
||||
/// </summary>
|
||||
/// <remarks>Replace with ImportDataSection</remarks>
|
||||
public byte[] ImportDataSectionRaw;
|
||||
|
||||
/// <summary>
|
||||
/// .rdata - Read-only initialized data
|
||||
/// </summary>
|
||||
public byte[] ResourceDataSectionRaw;
|
||||
|
||||
/// <summary>
|
||||
/// .text - Executable code (free format)
|
||||
/// </summary>
|
||||
public byte[] TextSectionRaw;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Determine if a section is contained within the section table
|
||||
/// </summary>
|
||||
/// <param name="sectionName">Name of the section to check for</param>
|
||||
/// <param name="exact">True to enable exact matching of names, false for starts-with</param>
|
||||
/// <returns>True if the section is in the executable, false otherwise</returns>
|
||||
public bool ContainsSection(string sectionName, bool exact = false)
|
||||
{
|
||||
// Get all section names first
|
||||
string[] sectionNames = GetSectionNames();
|
||||
if (sectionNames == null)
|
||||
return false;
|
||||
|
||||
// If we're checking exactly, return only exact matches (with nulls trimmed)
|
||||
if (exact)
|
||||
return sectionNames.Any(n => n.Trim('\0').Equals(sectionName));
|
||||
|
||||
// Otherwise, check if section name starts with the value
|
||||
else
|
||||
return sectionNames.Any(n => n.Trim('\0').StartsWith(sectionName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a virtual address to a physical one
|
||||
/// </summary>
|
||||
/// <param name="virtualAddress">Virtual address to convert</param>
|
||||
/// <param name="sections">Array of sections to check against</param>
|
||||
/// <returns>Physical address, 0 on error</returns>
|
||||
public static uint ConvertVirtualAddress(uint virtualAddress, SectionHeader[] sections)
|
||||
{
|
||||
// Loop through all of the sections
|
||||
for (int i = 0; i < sections.Length; i++)
|
||||
{
|
||||
// If the section is invalid, just skip it
|
||||
if (sections[i] == null)
|
||||
continue;
|
||||
|
||||
// If the section "starts" at 0, just skip it
|
||||
if (sections[i].PointerToRawData == 0)
|
||||
continue;
|
||||
|
||||
// Attempt to derive the physical address from the current section
|
||||
var section = sections[i];
|
||||
if (virtualAddress >= section.VirtualAddress && virtualAddress <= section.VirtualAddress + section.VirtualSize)
|
||||
return section.PointerToRawData + virtualAddress - section.VirtualAddress;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the first section based on name, if possible
|
||||
/// </summary>
|
||||
/// <param name="sectionName">Name of the section to check for</param>
|
||||
/// <param name="exact">True to enable exact matching of names, false for starts-with</param>
|
||||
/// <returns>Section data on success, null on error</returns>
|
||||
public SectionHeader GetFirstSection(string sectionName, bool exact = false)
|
||||
{
|
||||
// If we have no sections, we can't do anything
|
||||
if (SectionTable == null || !SectionTable.Any())
|
||||
return null;
|
||||
|
||||
// If we're checking exactly, return only exact matches (with nulls trimmed)
|
||||
if (exact)
|
||||
return SectionTable.FirstOrDefault(s => Encoding.ASCII.GetString(s.Name).Trim('\0').Equals(sectionName));
|
||||
|
||||
// Otherwise, check if section name starts with the value
|
||||
else
|
||||
return SectionTable.FirstOrDefault(s => Encoding.ASCII.GetString(s.Name).Trim('\0').StartsWith(sectionName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the last section based on name, if possible
|
||||
/// </summary>
|
||||
/// <param name="sectionName">Name of the section to check for</param>
|
||||
/// <param name="exact">True to enable exact matching of names, false for starts-with</param>
|
||||
/// <returns>Section data on success, null on error</returns>
|
||||
public SectionHeader GetLastSection(string sectionName, bool exact = false)
|
||||
{
|
||||
// If we have no sections, we can't do anything
|
||||
if (SectionTable == null || !SectionTable.Any())
|
||||
return null;
|
||||
|
||||
// If we're checking exactly, return only exact matches (with nulls trimmed)
|
||||
if (exact)
|
||||
return SectionTable.LastOrDefault(s => Encoding.ASCII.GetString(s.Name).Trim('\0').Equals(sectionName));
|
||||
|
||||
// Otherwise, check if section name starts with the value
|
||||
else
|
||||
return SectionTable.LastOrDefault(s => Encoding.ASCII.GetString(s.Name).Trim('\0').StartsWith(sectionName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the list of section names
|
||||
/// </summary>
|
||||
public string[] GetSectionNames()
|
||||
{
|
||||
// Invalid table means no names are accessible
|
||||
if (SectionTable == null || SectionTable.Length == 0)
|
||||
return null;
|
||||
|
||||
return SectionTable.Select(s => Encoding.ASCII.GetString(s.Name)).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Print all sections, including their start and end addresses
|
||||
/// </summary>
|
||||
public void PrintAllSections()
|
||||
{
|
||||
foreach (var section in SectionTable)
|
||||
{
|
||||
string sectionName = Encoding.ASCII.GetString(section.Name).Trim('\0');
|
||||
int sectionAddr = (int)section.PointerToRawData;
|
||||
int sectionEnd = sectionAddr + (int)section.VirtualSize;
|
||||
Console.WriteLine($"{sectionName}: {sectionAddr} -> {sectionEnd}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the raw bytes from a section, if possible
|
||||
/// </summary>
|
||||
public byte[] ReadRawSection(Stream stream, string sectionName, bool force = false, bool first = true, int offset = 0)
|
||||
{
|
||||
// Special cases for non-forced, non-offset data
|
||||
if (!force && offset == 0)
|
||||
{
|
||||
switch (sectionName)
|
||||
{
|
||||
case ".data":
|
||||
return DataSectionRaw;
|
||||
case ".edata":
|
||||
return ExportDataSectionRaw;
|
||||
case ".idata":
|
||||
return ImportDataSectionRaw;
|
||||
case ".rdata":
|
||||
return ResourceDataSectionRaw;
|
||||
case ".text":
|
||||
return TextSectionRaw;
|
||||
}
|
||||
}
|
||||
|
||||
var section = first ? GetFirstSection(sectionName, true) : GetLastSection(sectionName, true);
|
||||
if (section == null)
|
||||
return null;
|
||||
|
||||
lock (stream)
|
||||
{
|
||||
int startingIndex = (int)Math.Max(section.PointerToRawData + offset, 0);
|
||||
int readLength = (int)Math.Min(section.VirtualSize - offset, stream.Length);
|
||||
|
||||
long originalPosition = stream.Position;
|
||||
stream.Seek(startingIndex, SeekOrigin.Begin);
|
||||
byte[] sectionData = stream.ReadBytes(readLength);
|
||||
stream.Seek(originalPosition, SeekOrigin.Begin);
|
||||
return sectionData;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the raw bytes from a section, if possible
|
||||
/// </summary>
|
||||
public byte[] ReadRawSection(byte[] content, string sectionName, bool force = false, bool first = true, int offset = 0)
|
||||
{
|
||||
// Special cases for non-forced, non-offset data
|
||||
if (!force && offset == 0)
|
||||
{
|
||||
switch (sectionName)
|
||||
{
|
||||
case ".data":
|
||||
return DataSectionRaw;
|
||||
case ".edata":
|
||||
return ExportDataSectionRaw;
|
||||
case ".idata":
|
||||
return ImportDataSectionRaw;
|
||||
case ".rdata":
|
||||
return ResourceDataSectionRaw;
|
||||
case ".text":
|
||||
return TextSectionRaw;
|
||||
}
|
||||
}
|
||||
|
||||
var section = first ? GetFirstSection(sectionName, true) : GetLastSection(sectionName, true);
|
||||
if (section == null)
|
||||
return null;
|
||||
|
||||
int startingIndex = (int)Math.Max(section.PointerToRawData + offset, 0);
|
||||
int readLength = (int)Math.Min(section.VirtualSize - offset, content.Length);
|
||||
|
||||
return content.ReadBytes(ref startingIndex, readLength);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static PortableExecutable Deserialize(Stream stream)
|
||||
{
|
||||
PortableExecutable pex = new PortableExecutable();
|
||||
|
||||
try
|
||||
{
|
||||
// Attempt to read the DOS header first
|
||||
pex.DOSStubHeader = MSDOSExecutableHeader.Deserialize(stream); stream.Seek(pex.DOSStubHeader.NewExeHeaderAddr, SeekOrigin.Begin);
|
||||
if (pex.DOSStubHeader.Magic != Constants.IMAGE_DOS_SIGNATURE)
|
||||
return null;
|
||||
|
||||
// If the new header address is invalid for the file, it's not a PE
|
||||
if (pex.DOSStubHeader.NewExeHeaderAddr >= stream.Length)
|
||||
return null;
|
||||
|
||||
// Then attempt to read the PE header
|
||||
pex.ImageFileHeader = CommonObjectFileFormatHeader.Deserialize(stream);
|
||||
if (pex.ImageFileHeader.Signature != Constants.IMAGE_NT_SIGNATURE)
|
||||
return null;
|
||||
|
||||
// If the optional header is supposed to exist, read that as well
|
||||
if (pex.ImageFileHeader.SizeOfOptionalHeader > 0)
|
||||
pex.OptionalHeader = OptionalHeader.Deserialize(stream);
|
||||
|
||||
// Then read in the section table
|
||||
pex.SectionTable = new SectionHeader[pex.ImageFileHeader.NumberOfSections];
|
||||
for (int i = 0; i < pex.ImageFileHeader.NumberOfSections; i++)
|
||||
{
|
||||
pex.SectionTable[i] = SectionHeader.Deserialize(stream);
|
||||
}
|
||||
|
||||
#region Structured Tables
|
||||
|
||||
// // Export Table
|
||||
// var table = pex.GetLastSection(".edata", true);
|
||||
// if (table != null && table.VirtualSize > 0)
|
||||
// {
|
||||
// stream.Seek((int)table.PointerToRawData, SeekOrigin.Begin);
|
||||
// pex.ExportTable = ExportDataSection.Deserialize(stream, pex.SectionTable);
|
||||
// }
|
||||
|
||||
// // Import Table
|
||||
// table = pex.GetSection(".idata", true);
|
||||
// if (table != null && table.VirtualSize > 0)
|
||||
// {
|
||||
// stream.Seek((int)table.PointerToRawData, SeekOrigin.Begin);
|
||||
// pex.ImportTable = ImportDataSection.Deserialize(stream, pex.OptionalHeader.Magic == OptionalHeaderType.PE32Plus, hintCount: 0);
|
||||
// }
|
||||
|
||||
// Resource Table
|
||||
var table = pex.GetLastSection(".rsrc", true);
|
||||
if (table != null && table.VirtualSize > 0)
|
||||
{
|
||||
stream.Seek((int)table.PointerToRawData, SeekOrigin.Begin);
|
||||
pex.ResourceSection = ResourceSection.Deserialize(stream, pex.SectionTable);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Freeform Sections
|
||||
|
||||
// Data Section
|
||||
pex.DataSectionRaw = pex.ReadRawSection(stream, ".data", force: true, first: false) ?? pex.ReadRawSection(stream, "DATA", force: true, first: false);
|
||||
|
||||
// Export Table
|
||||
pex.ExportDataSectionRaw = pex.ReadRawSection(stream, ".edata", force: true, first: false);
|
||||
|
||||
// Import Table
|
||||
pex.ImportDataSectionRaw = pex.ReadRawSection(stream, ".idata", force: true, first: false);
|
||||
|
||||
// Resource Data Section
|
||||
pex.ResourceDataSectionRaw = pex.ReadRawSection(stream, ".rdata", force: true, first: false);
|
||||
|
||||
// Text Section
|
||||
pex.TextSectionRaw = pex.ReadRawSection(stream, ".text", force: true, first: false);
|
||||
|
||||
#endregion
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Console.WriteLine($"Errored out on a file: {ex}");
|
||||
return null;
|
||||
}
|
||||
|
||||
return pex;
|
||||
}
|
||||
|
||||
public static PortableExecutable Deserialize(byte[] content, int offset)
|
||||
{
|
||||
PortableExecutable pex = new PortableExecutable();
|
||||
|
||||
try
|
||||
{
|
||||
// Attempt to read the DOS header first
|
||||
pex.DOSStubHeader = MSDOSExecutableHeader.Deserialize(content, ref offset);
|
||||
offset = pex.DOSStubHeader.NewExeHeaderAddr;
|
||||
if (pex.DOSStubHeader.Magic != Constants.IMAGE_DOS_SIGNATURE)
|
||||
return null;
|
||||
|
||||
// If the new header address is invalid for the file, it's not a PE
|
||||
if (pex.DOSStubHeader.NewExeHeaderAddr >= content.Length)
|
||||
return null;
|
||||
|
||||
// Then attempt to read the PE header
|
||||
pex.ImageFileHeader = CommonObjectFileFormatHeader.Deserialize(content, ref offset);
|
||||
if (pex.ImageFileHeader.Signature != Constants.IMAGE_NT_SIGNATURE)
|
||||
return null;
|
||||
|
||||
// If the optional header is supposed to exist, read that as well
|
||||
if (pex.ImageFileHeader.SizeOfOptionalHeader > 0)
|
||||
pex.OptionalHeader = OptionalHeader.Deserialize(content, ref offset);
|
||||
|
||||
// Then read in the section table
|
||||
pex.SectionTable = new SectionHeader[pex.ImageFileHeader.NumberOfSections];
|
||||
for (int i = 0; i < pex.ImageFileHeader.NumberOfSections; i++)
|
||||
{
|
||||
pex.SectionTable[i] = SectionHeader.Deserialize(content, ref offset);
|
||||
}
|
||||
|
||||
#region Structured Tables
|
||||
|
||||
// // Export Table
|
||||
// var table = pex.GetLastSection(".edata", true);
|
||||
// if (table != null && table.VirtualSize > 0)
|
||||
// {
|
||||
// int tableAddress = (int)table.PointerToRawData;
|
||||
// pex.ExportTable = ExportDataSection.Deserialize(content, ref tableAddress, pex.SectionTable);
|
||||
// }
|
||||
|
||||
// // Import Table
|
||||
// table = pex.GetSection(".idata", true);
|
||||
// if (table != null && table.VirtualSize > 0)
|
||||
// {
|
||||
// int tableAddress = (int)table.PointerToRawData;
|
||||
// pex.ImportTable = ImportDataSection.Deserialize(content, tableAddress, pex.OptionalHeader.Magic == OptionalHeaderType.PE32Plus, hintCount: 0);
|
||||
// }
|
||||
|
||||
// Resource Table
|
||||
var table = pex.GetLastSection(".rsrc", true);
|
||||
if (table != null && table.VirtualSize > 0)
|
||||
{
|
||||
int tableAddress = (int)table.PointerToRawData;
|
||||
pex.ResourceSection = ResourceSection.Deserialize(content, ref tableAddress, pex.SectionTable);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Freeform Sections
|
||||
|
||||
// Data Section
|
||||
pex.DataSectionRaw = pex.ReadRawSection(content, ".data", force: true, first: false) ?? pex.ReadRawSection(content, "DATA", force: true, first: false);
|
||||
|
||||
// Export Table
|
||||
pex.ExportDataSectionRaw = pex.ReadRawSection(content, ".edata", force: true, first: false);
|
||||
|
||||
// Import Table
|
||||
pex.ImportDataSectionRaw = pex.ReadRawSection(content, ".idata", force: true, first: false);
|
||||
|
||||
// Resource Data Section
|
||||
pex.ResourceDataSectionRaw = pex.ReadRawSection(content, ".rdata", force: true, first: false);
|
||||
|
||||
// Text Section
|
||||
pex.TextSectionRaw = pex.ReadRawSection(content, ".text", force: true, first: false);
|
||||
|
||||
#endregion
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Console.WriteLine($"Errored out on a file: {ex}");
|
||||
return null;
|
||||
}
|
||||
|
||||
return pex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
|
||||
@@ -15,13 +15,13 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
this.Length = resource?.Length ?? default;
|
||||
this.ValueLength = resource?.ValueLength ?? default;
|
||||
this.Type = resource?.Type ?? default;
|
||||
this.Key = resource?.Key ?? default;
|
||||
this.Key = resource?.Key?.TrimStart('\u0001') ?? default;
|
||||
}
|
||||
|
||||
public static new StringFileInfo Deserialize(Stream stream)
|
||||
{
|
||||
Resource resource = Resource.Deserialize(stream);
|
||||
if (resource.Key != "StringFileInfo")
|
||||
if (resource.Key != "StringFileInfo" && resource.Key != "\u0001StringFileInfo")
|
||||
return null;
|
||||
|
||||
StringFileInfo sfi = new StringFileInfo(resource);
|
||||
@@ -33,7 +33,7 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
public static new StringFileInfo Deserialize(byte[] content, ref int offset)
|
||||
{
|
||||
Resource resource = Resource.Deserialize(content, ref offset);
|
||||
if (resource.Key != "StringFileInfo")
|
||||
if (resource.Key != "StringFileInfo" && resource.Key != "\u0001StringFileInfo")
|
||||
return null;
|
||||
|
||||
StringFileInfo sfi = new StringFileInfo(resource);
|
||||
|
||||
@@ -48,12 +48,12 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
|
||||
long preChildOffset = stream.Position;
|
||||
Resource firstChild = Resource.Deserialize(stream);
|
||||
if (firstChild.Key == "StringFileInfo")
|
||||
if (firstChild.Key == "StringFileInfo" || firstChild.Key == "\u0001StringFileInfo")
|
||||
{
|
||||
stream.Seek(preChildOffset, SeekOrigin.Begin);
|
||||
vi.ChildrenStringFileInfo = StringFileInfo.Deserialize(stream);
|
||||
}
|
||||
else if (firstChild.Key == "VarFileInfo")
|
||||
else if (firstChild.Key == "VarFileInfo" || firstChild.Key == "\u0001VarFileInfo")
|
||||
{
|
||||
stream.Seek(preChildOffset, SeekOrigin.Begin);
|
||||
vi.ChildrenVarFileInfo = VarFileInfo.Deserialize(stream);
|
||||
@@ -64,12 +64,12 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
|
||||
preChildOffset = stream.Position;
|
||||
Resource secondChild = Resource.Deserialize(stream);
|
||||
if (secondChild.Key == "StringFileInfo")
|
||||
if (secondChild.Key == "StringFileInfo" || secondChild.Key == "\u0001StringFileInfo")
|
||||
{
|
||||
stream.Seek(preChildOffset, SeekOrigin.Begin);
|
||||
vi.ChildrenStringFileInfo = StringFileInfo.Deserialize(stream);
|
||||
}
|
||||
else if (secondChild.Key == "VarFileInfo")
|
||||
else if (secondChild.Key == "VarFileInfo" || secondChild.Key == "\u0001VarFileInfo")
|
||||
{
|
||||
stream.Seek(preChildOffset, SeekOrigin.Begin);
|
||||
vi.ChildrenVarFileInfo = VarFileInfo.Deserialize(stream);
|
||||
@@ -95,12 +95,12 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
|
||||
int preChildOffset = offset;
|
||||
Resource firstChild = Resource.Deserialize(content, ref offset);
|
||||
if (firstChild.Key == "StringFileInfo")
|
||||
if (firstChild.Key == "StringFileInfo" || firstChild.Key == "\u0001StringFileInfo")
|
||||
{
|
||||
offset = preChildOffset;
|
||||
vi.ChildrenStringFileInfo = StringFileInfo.Deserialize(content, ref offset);
|
||||
}
|
||||
else if (firstChild.Key == "VarFileInfo")
|
||||
else if (firstChild.Key == "VarFileInfo" || firstChild.Key == "\u0001VarFileInfo")
|
||||
{
|
||||
offset = preChildOffset;
|
||||
vi.ChildrenVarFileInfo = VarFileInfo.Deserialize(content, ref offset);
|
||||
@@ -112,12 +112,12 @@ namespace BurnOutSharp.ExecutableType.Microsoft.Resources
|
||||
|
||||
preChildOffset = offset;
|
||||
Resource secondChild = Resource.Deserialize(content, ref offset);
|
||||
if (secondChild.Key == "StringFileInfo")
|
||||
if (secondChild.Key == "StringFileInfo" || secondChild.Key == "\u0001StringFileInfo")
|
||||
{
|
||||
offset = preChildOffset;
|
||||
vi.ChildrenStringFileInfo = StringFileInfo.Deserialize(content, ref offset);
|
||||
}
|
||||
else if (secondChild.Key == "VarFileInfo")
|
||||
else if (secondChild.Key == "VarFileInfo" || secondChild.Key == "\u0001VarFileInfo")
|
||||
{
|
||||
offset = preChildOffset;
|
||||
vi.ChildrenVarFileInfo = VarFileInfo.Deserialize(content, ref offset);
|
||||
|
||||
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/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
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.Deflate;
|
||||
@@ -62,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)
|
||||
{
|
||||
@@ -101,8 +102,11 @@ namespace BurnOutSharp.FileType
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
br.BaseStream.Seek(current, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
@@ -115,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,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.BZip2;
|
||||
@@ -50,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
|
||||
@@ -61,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,23 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BurnOutSharp.ExecutableType.Microsoft;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.NE;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
public class Executable : IScannable
|
||||
{
|
||||
/// <summary>
|
||||
/// Cache for all IContentCheck types
|
||||
/// </summary>
|
||||
private static readonly IEnumerable<IContentCheck> contentCheckClasses = InitContentCheckClasses();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic)
|
||||
{
|
||||
@@ -70,91 +64,130 @@ namespace BurnOutSharp.FileType
|
||||
// Files can be protected in multiple ways
|
||||
var protections = new ConcurrentDictionary<string, ConcurrentQueue<string>>();
|
||||
|
||||
// Load the current file content
|
||||
// Load the current file content for debug only
|
||||
byte[] fileContent = null;
|
||||
try
|
||||
if (scanner.IncludeDebug)
|
||||
{
|
||||
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
|
||||
try
|
||||
{
|
||||
fileContent = br.ReadBytes((int)stream.Length);
|
||||
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Utilities.AppendToDictionary(protections, file, "[Out of memory attempting to open]");
|
||||
return protections;
|
||||
}
|
||||
|
||||
// TODO: Start moving toward reading from the stream directly. In theory,
|
||||
// deserialization can be done at this point, and if all of the sections are populated
|
||||
// properly, nearly all of the content checks can be dealt with without having
|
||||
// to take up as much memory as it does right now reading into the fileContent
|
||||
// byte array
|
||||
|
||||
// Create PortableExecutable and NewExecutable objects for use in the checks
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0);
|
||||
NewExecutable nex = NewExecutable.Deserialize(fileContent, 0);
|
||||
PortableExecutable pex = new PortableExecutable(stream);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
NewExecutable nex = new NewExecutable(stream);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
// Create PortableExecutable and NewExecutable objects for use in the checks
|
||||
// PortableExecutable pex = PortableExecutable.Deserialize(stream);
|
||||
// stream.Seek(0, SeekOrigin.Begin);
|
||||
// NewExecutable nex = NewExecutable.Deserialize(stream);
|
||||
// stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
// Iterate through all content checks
|
||||
Parallel.ForEach(contentCheckClasses, contentCheckClass =>
|
||||
// Iterate through all generic content checks
|
||||
if (fileContent != null)
|
||||
{
|
||||
// Track if any protection is found
|
||||
bool foundProtection = false;
|
||||
|
||||
// Check using custom content checks first
|
||||
string protection = contentCheckClass.CheckContents(file, fileContent, scanner.IncludeDebug, pex, nex);
|
||||
foundProtection |= !string.IsNullOrWhiteSpace(protection);
|
||||
if (ShouldAddProtection(contentCheckClass, scanner, protection))
|
||||
Utilities.AppendToDictionary(protections, file, protection);
|
||||
|
||||
// If we have an IScannable implementation
|
||||
if (contentCheckClass is IScannable scannable)
|
||||
Parallel.ForEach(ScanningClasses.ContentCheckClasses, contentCheckClass =>
|
||||
{
|
||||
if (file != null && !string.IsNullOrEmpty(protection))
|
||||
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)
|
||||
{
|
||||
var subProtections = scannable.Scan(scanner, null, file);
|
||||
Utilities.PrependToKeys(subProtections, file);
|
||||
Utilities.AppendToDictionary(protections, subProtections);
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize all IContentCheck implementations
|
||||
/// </summary>
|
||||
private static IEnumerable<IContentCheck> InitContentCheckClasses()
|
||||
{
|
||||
return Assembly.GetExecutingAssembly().GetTypes()
|
||||
.Where(t => t.IsClass && t.GetInterface(nameof(IContentCheck)) != null)
|
||||
.Select(t => Activator.CreateInstance(t) as IContentCheck);
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Check to see if a protection should be added or not
|
||||
/// </summary>
|
||||
/// <param name="contentCheckClass">Class that was last used to check</param>
|
||||
/// <param name="scanner">Scanner object for state tracking</param>
|
||||
/// <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(IContentCheck contentCheckClass, Scanner scanner, string protection)
|
||||
private bool ShouldAddProtection(object checkClass, bool scanPackers, string protection)
|
||||
{
|
||||
// If we have a valid content check based on settings
|
||||
if (!contentCheckClass.GetType().Namespace.ToLowerInvariant().Contains("packertype") || scanner.ScanPackers)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
return true;
|
||||
}
|
||||
// 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,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.GZip;
|
||||
@@ -53,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,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;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
using UnshieldSharp.Archive;
|
||||
|
||||
@@ -74,7 +75,10 @@ namespace BurnOutSharp.FileType
|
||||
fs.Write(fileContents, 0, fileContents.Length);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
@@ -85,14 +89,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;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
using UnshieldSharp.Cabinet;
|
||||
|
||||
@@ -60,10 +61,23 @@ namespace BurnOutSharp.FileType
|
||||
// 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
|
||||
@@ -74,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,8 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
using WixToolset.Dtf.WindowsInstaller;
|
||||
using OpenMcdf;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
@@ -39,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
|
||||
@@ -52,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
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Zip;
|
||||
@@ -12,6 +13,10 @@ namespace BurnOutSharp.FileType
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic)
|
||||
{
|
||||
// PKZIP (Unknown)
|
||||
if (magic.StartsWith(new byte?[] { 0x50, 0x4b, 0x00, 0x00 }))
|
||||
return true;
|
||||
|
||||
// PKZIP
|
||||
if (magic.StartsWith(new byte?[] { 0x50, 0x4b, 0x03, 0x04 }))
|
||||
return true;
|
||||
@@ -60,9 +65,13 @@ namespace BurnOutSharp.FileType
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,14 +83,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;
|
||||
}
|
||||
|
||||
57
BurnOutSharp/FileType/PLJ.cs
Normal file
57
BurnOutSharp/FileType/PLJ.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
public class PLJ : IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic)
|
||||
{
|
||||
// https://www.iana.org/assignments/media-types/audio/vnd.everad.plj
|
||||
if (magic.StartsWith(new byte?[] { 0xFF, 0x9D, 0x53, 0x4B }))
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
var protections = new ConcurrentDictionary<string, ConcurrentQueue<string>>();
|
||||
try
|
||||
{
|
||||
byte[] magic = new byte[16];
|
||||
stream.Read(magic, 0, 16);
|
||||
|
||||
if (ShouldScan(magic))
|
||||
{
|
||||
Utilities.AppendToDictionary(protections, file, "PlayJ Audio File");
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Rar;
|
||||
@@ -58,7 +59,10 @@ namespace BurnOutSharp.FileType
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,14 +74,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,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.SevenZip;
|
||||
@@ -53,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);
|
||||
}
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
@@ -64,7 +68,10 @@ 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);
|
||||
@@ -72,7 +79,10 @@ namespace BurnOutSharp.FileType
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Tar;
|
||||
@@ -56,7 +57,10 @@ namespace BurnOutSharp.FileType
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,14 +72,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;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
@@ -38,10 +39,22 @@ namespace BurnOutSharp.FileType
|
||||
if (magic.StartsWith(new byte?[] { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 }))
|
||||
return true;
|
||||
|
||||
// InstallShield Compiled Rules
|
||||
if (magic.StartsWith(new byte?[] { 0x61, 0x4C, 0x75, 0x5A }))
|
||||
return true;
|
||||
|
||||
// InstallShield Script
|
||||
if (string.Equals(extension?.TrimStart('.'), "ins", StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
|
||||
// Generic textfile (no header)
|
||||
if (string.Equals(extension?.TrimStart('.'), "txt", StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
|
||||
// XML (multiple headers possible)
|
||||
if (string.Equals(extension?.TrimStart('.'), "xml", StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -72,23 +85,60 @@ namespace BurnOutSharp.FileType
|
||||
fileContent = sr.ReadToEnd();
|
||||
}
|
||||
|
||||
// AegiSoft License Manager
|
||||
// Found in "setup.ins" (Redump entry 73521/IA item "Nova_HoyleCasino99USA").
|
||||
if (fileContent.Contains("Failed to load the AegiSoft License Manager install program."))
|
||||
Utilities.AppendToDictionary(protections, file, "AegiSoft License Manager");
|
||||
|
||||
// CD-Key
|
||||
if (fileContent.Contains("a valid serial number is required"))
|
||||
Utilities.AppendToDictionary(protections, file, "CD-Key / Serial");
|
||||
else if (fileContent.Contains("serial number is located"))
|
||||
Utilities.AppendToDictionary(protections, file, "CD-Key / Serial");
|
||||
|
||||
// MediaCloQ
|
||||
if (fileContent.Contains("SunnComm MediaCloQ"))
|
||||
Utilities.AppendToDictionary(protections, file, "MediaCloQ");
|
||||
else if (fileContent.Contains("http://download.mediacloq.com/"))
|
||||
Utilities.AppendToDictionary(protections, file, "MediaCloQ");
|
||||
else if (fileContent.Contains("http://www.sunncomm.com/mediacloq/"))
|
||||
Utilities.AppendToDictionary(protections, file, "MediaCloQ");
|
||||
|
||||
// MediaMax
|
||||
if (fileContent.Contains("MediaMax technology"))
|
||||
Utilities.AppendToDictionary(protections, file, "MediaMax CD-3");
|
||||
else if (fileContent.Contains("exclusive Cd3 technology"))
|
||||
Utilities.AppendToDictionary(protections, file, "MediaMax CD-3");
|
||||
else if (fileContent.Contains("<PROTECTION-VENDOR>MediaMAX</PROTECTION-VENDOR>"))
|
||||
Utilities.AppendToDictionary(protections, file, "MediaMax CD-3");
|
||||
else if (fileContent.Contains("MediaMax(tm)"))
|
||||
Utilities.AppendToDictionary(protections, file, "MediaMax CD-3");
|
||||
|
||||
// phenoProtect
|
||||
if (fileContent.Contains("phenoProtect"))
|
||||
Utilities.AppendToDictionary(protections, file, "phenoProtect");
|
||||
|
||||
// The full line from a sample is as follows:
|
||||
//
|
||||
// The files securom_v7_01.dat and securom_v7_01.bak have been created during the installation of a SecuROM protected application.
|
||||
//
|
||||
// TODO: Use the filenames in this line to get the version out of it
|
||||
|
||||
// SecuROM
|
||||
if (fileContent.Contains("SecuROM protected application"))
|
||||
Utilities.AppendToDictionary(protections, file, "SecuROM");
|
||||
|
||||
// Steam
|
||||
if (fileContent.Contains("All use of the Program is governed by the terms of the Steam Agreement as described below."))
|
||||
Utilities.AppendToDictionary(protections, file, "Steam");
|
||||
|
||||
// XCP
|
||||
if (fileContent.Contains("http://cp.sonybmg.com/xcp/"))
|
||||
Utilities.AppendToDictionary(protections, file, "XCP");
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
// We don't care what the error was
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return protections;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
using SharpCompress.Compressors.Xz;
|
||||
|
||||
@@ -49,7 +50,10 @@ namespace BurnOutSharp.FileType
|
||||
xzFile.CopyTo(fs);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Collect and format all found protections
|
||||
@@ -60,14 +64,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;
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,19 +1,17 @@
|
||||
using BurnOutSharp.ExecutableType.Microsoft;
|
||||
|
||||
namespace BurnOutSharp
|
||||
namespace BurnOutSharp.Interfaces
|
||||
{
|
||||
// TODO: This should either include an override that takes a Stream instead of the byte[]
|
||||
// OR have a completely separate check for when it's an executable specifically
|
||||
/// <summary>
|
||||
/// Check a generic file for protection
|
||||
/// </summary>
|
||||
internal interface IContentCheck
|
||||
{
|
||||
/// <summary>
|
||||
/// Check a path for protections based on file contents
|
||||
/// </summary>
|
||||
/// <param name="pex">PortableExecutable representing the read-in file</param>
|
||||
/// <param name="file">File to check for protection indicators</param>
|
||||
/// <param name="fileContent">Byte array representing the file contents</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>String containing any protections found in the file</returns>
|
||||
string CheckContents(string file, byte[] fileContent, bool includeDebug, PortableExecutable pex, NewExecutable nex);
|
||||
string CheckContents(string file, byte[] fileContent, bool includeDebug);
|
||||
}
|
||||
}
|
||||
19
BurnOutSharp/Interfaces/INewExecutableCheck.cs
Normal file
19
BurnOutSharp/Interfaces/INewExecutableCheck.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using BurnOutSharp.ExecutableType.Microsoft.NE;
|
||||
|
||||
namespace BurnOutSharp.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Check a New Executable (NE) for protection
|
||||
/// </summary>
|
||||
internal interface INewExecutableCheck
|
||||
{
|
||||
/// <summary>
|
||||
/// Check a path for protections based on file contents
|
||||
/// </summary>
|
||||
/// <param name="file">File to check for protection indicators</param>
|
||||
/// <param name="nex">NewExecutable representing the read-in file</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>String containing any protections found in the file</returns>
|
||||
string CheckNewExecutable(string file, NewExecutable nex, bool includeDebug);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,14 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BurnOutSharp
|
||||
namespace BurnOutSharp.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Check a file or directory path for protection
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These checks rely primarily on filenames and paths, not file contents
|
||||
/// </remarks>
|
||||
internal interface IPathCheck
|
||||
{
|
||||
/// <summary>
|
||||
@@ -10,14 +16,14 @@ namespace BurnOutSharp
|
||||
/// </summary>
|
||||
/// <param name="path">Path to check for protection indicators</param>
|
||||
/// <param name="files">Enumerable of strings representing files in a directory</param>
|
||||
/// <remarks>This can do some limited content checking as well, but it's suggested to use IContentCheck instead, if possible</remarks>
|
||||
/// <remarks>This can do some limited content checking as well, but it's suggested to use a content check instead, if possible</remarks>
|
||||
ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string> files);
|
||||
|
||||
/// <summary>
|
||||
/// Check a file path for protections based on path name
|
||||
/// </summary>
|
||||
/// <param name="path">Path to check for protection indicators</param>
|
||||
/// <remarks>This can do some limited content checking as well, but it's suggested to use IContentCheck instead, if possible</remarks>
|
||||
/// <remarks>This can do some limited content checking as well, but it's suggested to use a content check instead, if possible</remarks>
|
||||
string CheckFilePath(string path);
|
||||
}
|
||||
}
|
||||
19
BurnOutSharp/Interfaces/IPortableExecutableCheck.cs
Normal file
19
BurnOutSharp/Interfaces/IPortableExecutableCheck.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE;
|
||||
|
||||
namespace BurnOutSharp.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Check a Portable Executable (PE) for protection
|
||||
/// </summary>
|
||||
internal interface IPortableExecutableCheck
|
||||
{
|
||||
/// <summary>
|
||||
/// Check a path for protections based on file contents
|
||||
/// </summary>
|
||||
/// <param name="file">File to check for protection indicators</param>
|
||||
/// <param name="pex">PortableExecutable representing the read-in file</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>String containing any protections found in the file</returns>
|
||||
string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
|
||||
namespace BurnOutSharp
|
||||
namespace BurnOutSharp.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Mark a file type as extractable
|
||||
/// </summary>
|
||||
internal interface IScannable
|
||||
{
|
||||
/// <summary>
|
||||
@@ -51,13 +51,17 @@ namespace BurnOutSharp.Matching
|
||||
if (Needle.Length > stack.Length)
|
||||
return (false, -1);
|
||||
|
||||
// If start or end are not set properly, set them to defaults
|
||||
if (Start < 0)
|
||||
Start = 0;
|
||||
if (End < 0)
|
||||
End = stack.Length - Needle.Length;
|
||||
// Set the default start and end values
|
||||
int start = Start;
|
||||
int end = End;
|
||||
|
||||
for (int i = reverse ? End : Start; reverse ? i > Start : i < End; i += reverse ? -1 : 1)
|
||||
// If start or end are not set properly, set them to defaults
|
||||
if (start < 0)
|
||||
start = 0;
|
||||
if (end < 0)
|
||||
end = stack.Length - Needle.Length;
|
||||
|
||||
for (int i = reverse ? end : start; reverse ? i > start : i < end; i += reverse ? -1 : 1)
|
||||
{
|
||||
// If we somehow have an invalid end and we haven't matched, return
|
||||
if (i > stack.Length)
|
||||
@@ -84,7 +88,7 @@ namespace BurnOutSharp.Matching
|
||||
return false;
|
||||
|
||||
// If we're too close to the end of the stack, return false
|
||||
if (Needle.Length >= stack.Length - index)
|
||||
if (Needle.Length > stack.Length - index)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < Needle.Length; i++)
|
||||
|
||||
661
BurnOutSharp/PackerType/ASPack.cs
Normal file
661
BurnOutSharp/PackerType/ASPack.cs
Normal file
@@ -0,0 +1,661 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
// TODO: Add extraction
|
||||
public class ASPack : IPortableExecutableCheck, IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic) => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex?.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
// Get the .aspack section, if it exists
|
||||
bool aspackSection = pex.ContainsSection(".aspack", exact: true);
|
||||
if (aspackSection)
|
||||
return "ASPack 2.29";
|
||||
|
||||
// Use the entry point data, if it exists
|
||||
if (pex.EntryPointRaw != null)
|
||||
{
|
||||
var matchers = GenerateMatchers();
|
||||
string match = MatchUtil.GetFirstMatch(file, pex.EntryPointRaw, matchers, includeDebug);
|
||||
if (!string.IsNullOrWhiteSpace(match))
|
||||
return match;
|
||||
}
|
||||
|
||||
// Get the .adata* section, if it exists
|
||||
var adataSection = pex.GetFirstSection(".adata", exact: false);
|
||||
if (adataSection != null)
|
||||
{
|
||||
var adataSectionRaw = pex.ReadRawSection(adataSection.NameString);
|
||||
if (adataSectionRaw != null)
|
||||
{
|
||||
var matchers = GenerateMatchers();
|
||||
string match = MatchUtil.GetFirstMatch(file, adataSectionRaw, matchers, includeDebug);
|
||||
if (!string.IsNullOrWhiteSpace(match))
|
||||
return match;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate the set of matchers used for each section
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private List<ContentMatchSet> GenerateMatchers()
|
||||
{
|
||||
return new List<ContentMatchSet>
|
||||
{
|
||||
#region No Wildcards (Long)
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x92, 0x1A, 0x44, 0x00, 0xB8, 0x8C, 0x1A,
|
||||
0x44, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0xCD, 0x1D,
|
||||
0x44, 0x00, 0x89, 0x85, 0xD9, 0x1D, 0x44, 0x00,
|
||||
0x80, 0xBD, 0xC4, 0x1D, 0x44,
|
||||
}, "ASPack 1.00b -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0xD2, 0x2A, 0x44, 0x00, 0xB8, 0xCC, 0x2A,
|
||||
0x44, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0xA5, 0x2E,
|
||||
0x44, 0x00, 0x89, 0x85, 0xB1, 0x2E, 0x44, 0x00,
|
||||
0x80, 0xBD, 0x9C, 0x2E, 0x44, 0x00, 0x00, 0x75,
|
||||
0x15, 0xFE, 0x85, 0x9C, 0x2E, 0x44, 0x00, 0xE8,
|
||||
0x1D, 0x00, 0x00, 0x00, 0xE8, 0xE4, 0x01, 0x00,
|
||||
0x00, 0xE8, 0x7A, 0x02, 0x00, 0x00, 0x8B, 0x85,
|
||||
0x9D, 0x2E, 0x44, 0x00, 0x03, 0x85, 0xB1, 0x2E,
|
||||
0x44, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
|
||||
}, "ASPack 1.01b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0xD2, 0x2A, 0x44, 0x00, 0xB8, 0xCC, 0x2A,
|
||||
0x44, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0xA5, 0x2E,
|
||||
0x44, 0x00, 0x89, 0x85, 0xB1, 0x2E, 0x44, 0x00,
|
||||
0x80, 0xBD, 0x9C, 0x2E, 0x44
|
||||
}, "ASPack 1.01b -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x96, 0x78, 0x43, 0x00, 0xB8, 0x90, 0x78,
|
||||
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x7D, 0x7C,
|
||||
0x43, 0x00, 0x89, 0x85, 0x89, 0x7C, 0x43, 0x00,
|
||||
0x80, 0xBD, 0x74, 0x7C, 0x43, 0x00, 0x00, 0x75,
|
||||
0x15, 0xFE, 0x85, 0x74, 0x7C, 0x43, 0x00, 0xE8,
|
||||
0x1D, 0x00, 0x00, 0x00, 0xE8, 0xF7, 0x01, 0x00,
|
||||
0x00, 0xE8, 0x8E, 0x02, 0x00, 0x00, 0x8B, 0x85,
|
||||
0x75, 0x7C, 0x43, 0x00, 0x03, 0x85, 0x89, 0x7C,
|
||||
0x43, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
|
||||
}, "ASPack 1.02b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x96, 0x78, 0x43, 0x00, 0xB8, 0x90, 0x78,
|
||||
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x7D, 0x7C,
|
||||
0x43, 0x00, 0x89, 0x85, 0x89, 0x7C, 0x43, 0x00,
|
||||
0x80, 0xBD, 0x74, 0x7C, 0x43, 0x00, 0x00, 0x75,
|
||||
0x15, 0xFE, 0x85, 0x74, 0x7C, 0x43
|
||||
}, "ASPack 1.02b -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x8A, 0x1C, 0x40, 0x00, 0xB9, 0x9E, 0x00,
|
||||
0x00, 0x00, 0x8D, 0xBD, 0x4C, 0x23, 0x40, 0x00,
|
||||
0x8B, 0xF7, 0x33
|
||||
}, "ASPack 1.02b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x96, 0x78, 0x43, 0x00, 0xB8, 0x90, 0x78,
|
||||
0x43, 0x00, 0x03, 0xC5
|
||||
}, "ASPack 1.02b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0xAE, 0x98, 0x43, 0x00, 0xB8, 0xA8, 0x98,
|
||||
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x18, 0x9D,
|
||||
0x43, 0x00, 0x89, 0x85, 0x24, 0x9D, 0x43, 0x00,
|
||||
0x80, 0xBD, 0x0E, 0x9D, 0x43
|
||||
}, "ASPack 1.03b -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0xCE, 0x3A, 0x44, 0x00, 0xB8, 0xC8, 0x3A,
|
||||
0x44, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0xB5, 0x3E,
|
||||
0x44, 0x00, 0x89, 0x85, 0xC1, 0x3E, 0x44, 0x00,
|
||||
0x80, 0xBD, 0xAC, 0x3E, 0x44
|
||||
}, "ASPack 1.05b -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0xEA, 0xA8, 0x43, 0x00, 0xB8, 0xE4, 0xA8,
|
||||
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x78, 0xAD,
|
||||
0x43, 0x00, 0x89, 0x85, 0x84, 0xAD, 0x43, 0x00,
|
||||
0x80, 0xBD, 0x6E, 0xAD, 0x43, 0x00, 0x00, 0x75,
|
||||
0x15, 0xFE, 0x85, 0x6E, 0xAD, 0x43, 0x00, 0xE8,
|
||||
0x1D, 0x00, 0x00, 0x00, 0xE8, 0x73, 0x02, 0x00,
|
||||
0x00, 0xE8, 0x0A, 0x03, 0x00, 0x00, 0x8B, 0x85,
|
||||
0x70, 0xAD, 0x43, 0x00, 0x03, 0x85, 0x84, 0xAD,
|
||||
0x43, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
|
||||
}, "ASPack 1.06.01b (DLL)"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0xEA, 0xA8, 0x43, 0x00, 0xB8, 0xE4, 0xA8,
|
||||
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x78, 0xAD,
|
||||
0x43, 0x00, 0x89, 0x85, 0x84, 0xAD, 0x43, 0x00,
|
||||
0x80, 0xBD, 0x6E, 0xAD, 0x43, 0x00, 0x00, 0x75,
|
||||
0x15, 0xFE, 0x85, 0x6E, 0xAD, 0x43
|
||||
}, "ASPack 1.06.01b -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x3E, 0xD9, 0x43, 0x00, 0xB8, 0x38, 0xD9,
|
||||
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x0B, 0xDE,
|
||||
0x43, 0x00, 0x89, 0x85, 0x17, 0xDE, 0x43, 0x00,
|
||||
0x80, 0xBD, 0x01, 0xDE, 0x43, 0x00, 0x00, 0x75,
|
||||
0x15, 0xFE, 0x85, 0x01, 0xDE, 0x43, 0x00, 0xE8,
|
||||
0x1D, 0x00, 0x00, 0x00, 0xE8, 0x79, 0x02, 0x00,
|
||||
0x00, 0xE8, 0x12, 0x03, 0x00, 0x00, 0x8B, 0x85,
|
||||
0x03, 0xDE, 0x43, 0x00, 0x03, 0x85, 0x17, 0xDE,
|
||||
0x43, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
|
||||
}, "ASPack 1.07b (DLL)"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xEB, 0x03, 0x5D, 0xFF, 0xE5, 0xE8, 0xF8,
|
||||
0xFF, 0xFF, 0xFF, 0x81, 0xED, 0x1B, 0x6A, 0x44,
|
||||
0x00, 0xBB, 0x10, 0x6A, 0x44, 0x00, 0x03, 0xDD,
|
||||
0x2B, 0x9D, 0x2A
|
||||
}, "ASPack 1.08"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x0A, 0x4A, 0x44, 0x00, 0xBB, 0x04, 0x4A,
|
||||
0x44, 0x00, 0x03, 0xDD, 0x2B, 0x9D, 0xB1, 0x50,
|
||||
0x44, 0x00, 0x83, 0xBD, 0xAC, 0x50, 0x44, 0x00,
|
||||
0x00, 0x89, 0x9D, 0xBB, 0x4E, 0x44, 0x00, 0x0F,
|
||||
0x85, 0x17, 0x05, 0x00, 0x00, 0x8D, 0x85, 0xD1,
|
||||
0x50, 0x44, 0x00, 0x50, 0xFF, 0x95, 0x94, 0x51,
|
||||
0x44, 0x00, 0x89, 0x85, 0xCD, 0x50, 0x44, 0x00,
|
||||
0x8B, 0xF8, 0x8D, 0x9D, 0xDE, 0x50, 0x44, 0x00,
|
||||
0x53, 0x50, 0xFF, 0x95, 0x90, 0x51, 0x44, 0x00
|
||||
}, "ASPack 1.08.03"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x0A, 0x4A, 0x44, 0x00, 0xBB, 0x04, 0x4A,
|
||||
0x44, 0x00, 0x03, 0xDD, 0x2B, 0x9D, 0xB1, 0x50,
|
||||
0x44, 0x00, 0x83, 0xBD, 0xAC, 0x50, 0x44, 0x00,
|
||||
0x00, 0x89, 0x9D, 0xBB, 0x4E
|
||||
}, "ASPack 1.08.03"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x0A, 0x4A, 0x44, 0x00, 0xBB, 0x04, 0x4A,
|
||||
0x44, 0x00, 0x03, 0xDD
|
||||
}, "ASPack 1.08.03"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x72, 0x05, 0x00, 0x00, 0xEB, 0x33,
|
||||
0x87, 0xDB, 0x90, 0x00
|
||||
}, "ASPack 2.00.01"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9, 0xEB,
|
||||
0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01, 0x00,
|
||||
0x00, 0x00, 0xEB, 0x5D, 0xBB, 0xED, 0xFF, 0xFF,
|
||||
0xFF, 0x03, 0xDD, 0x81, 0xEB
|
||||
}, "ASPack 2.1"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xEB, 0x09,
|
||||
0x5D, 0x55, 0x81, 0xED, 0x39, 0x39, 0x44, 0x00,
|
||||
0xC3, 0xE9, 0x3D, 0x04, 0x00, 0x00
|
||||
}, "ASPack 2.11b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xEB, 0x09,
|
||||
0x5D, 0x55
|
||||
}, "ASPack 2.11b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xEB, 0x09,
|
||||
0x5D, 0x55, 0x81, 0xED, 0x39, 0x39, 0x44, 0x00,
|
||||
0xC3, 0xE9, 0x59, 0x04, 0x00, 0x00
|
||||
}, "ASPack 2.11c"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xCD, 0x20,
|
||||
0xE8, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x2B, 0xC9,
|
||||
0x58, 0x74, 0x02
|
||||
}, "ASPack 2.11d"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9, 0xEB,
|
||||
0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01
|
||||
}, "ASPack 2.12"),
|
||||
|
||||
#endregion
|
||||
|
||||
#region Wildcards (Long)
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, 0x3E, 0xD9, 0x43, null, 0xB8, 0x38, null,
|
||||
null, null, 0x03, 0xC5, 0x2B, 0x85, 0x0B, 0xDE,
|
||||
0x43, null, 0x89, 0x85, 0x17, 0xDE, 0x43, null,
|
||||
0x80, 0xBD, 0x01, 0xDE, 0x43, null, null, 0x75,
|
||||
0x15, 0xFE, 0x85, 0x01, 0xDE, 0x43, null, 0xE8,
|
||||
0x1D, null, null, null, 0xE8, 0x79, 0x02, null,
|
||||
null, 0xE8, 0x12, 0x03, null, null, 0x8B, 0x85,
|
||||
0x03, 0xDE, 0x43, null, 0x03, 0x85, 0x17, 0xDE,
|
||||
0x43, null, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
|
||||
}, "ASPack 1.00b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, 0xD2, 0x2A, 0x44, null, 0xB8, 0xCC, 0x2A,
|
||||
0x44, null, 0x03, 0xC5, 0x2B, 0x85, 0xA5, 0x2E,
|
||||
0x44, null, 0x89, 0x85, 0xB1, 0x2E, 0x44, null,
|
||||
0x80, 0xBD, 0x9C, 0x2E, 0x44
|
||||
}, "ASPack 1.01b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, 0xCE, 0x3A, 0x44, null, 0xB8, 0xC8, 0x3A,
|
||||
0x44, null, 0x03, 0xC5, 0x2B, 0x85, 0xB5, 0x3E,
|
||||
0x44, null, 0x89, 0x85, 0xC1, 0x3E, 0x44, null,
|
||||
0x80, 0xBD, 0xAC, 0x3E, 0x44
|
||||
}, "ASPack 1.01b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x3E, 0xD9, 0x43, 0x00, 0xB8, 0x38, null,
|
||||
null, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x0B, 0xDE,
|
||||
0x43, 0x00, 0x89, 0x85, 0x17, 0xDE, 0x43, 0x00,
|
||||
0x80, 0xBD, 0x01, 0xDE, 0x43, 0x00, 0x00, 0x75,
|
||||
0x15, 0xFE, 0x85, 0x01, 0xDE, 0x43, 0x00, 0xE8,
|
||||
0x1D, 0x00, 0x00, 0x00, 0xE8, 0x79, 0x02, 0x00,
|
||||
0x00, 0xE8, 0x12, 0x03, 0x00, 0x00, 0x8B, 0x85,
|
||||
0x03, 0xDE, 0x43, 0x00, 0x03, 0x85, 0x17, 0xDE,
|
||||
0x43, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
|
||||
}, "ASPack 1.02a -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, 0x06, null, null, null, 0x64, 0xA0, 0x23
|
||||
}, "ASPack 1.02a"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, 0x96, 0x78, 0x43, null, 0xB8, 0x90, 0x78,
|
||||
0x43, null, 0x03, 0xC5, 0x2B, 0x85, 0x7D, 0x7C,
|
||||
0x43, null, 0x89, 0x85, 0x89, 0x7C, 0x43, null,
|
||||
0x80, 0xBD, 0x74, 0x7C, 0x43
|
||||
}, "ASPack 1.02b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, 0xAE, 0x98, 0x43, null, 0xB8, 0xA8, 0x98,
|
||||
0x43, null, 0x03, 0xC5, 0x2B, 0x85, 0x18, 0x9D,
|
||||
0x43, null, 0x89, 0x85, 0x24, 0x9D, 0x43, null,
|
||||
0x80, 0xBD, 0x0E, 0x9D, 0x43
|
||||
}, "ASPack 1.03b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, null, null, null, null, 0xE8, 0x0D, null,
|
||||
null, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, null, null, 0x58
|
||||
}, "ASPack 1.03b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, null, null, null, 0x00, 0xB8, null, null,
|
||||
null, 0x00, 0x03, 0xC5, 0x2B, 0x85, null, 0x12,
|
||||
0x9D, null, 0x89, 0x85, 0x1E, 0x9D, null, 0x00,
|
||||
0x80, 0xBD, 0x08, 0x9D, null, 0x00, 0x00
|
||||
}, "ASPack 1.04b -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, null, null, null, null, 0xB8, null, null,
|
||||
null, null, 0x03, 0xC5, 0x2B, 0x85, null, 0x12,
|
||||
0x9D, null, 0x89, 0x85, 0x1E, 0x9D, null, null,
|
||||
0x80, 0xBD, 0x08, 0x9D
|
||||
}, "ASPack 1.04b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, null, null, null, null, 0xB8, null, null,
|
||||
null, null, 0x03, 0xC5, 0x2B, 0x85, null, 0x0B,
|
||||
0xDE, null, 0x89, 0x85, 0x17, 0xDE, null, null,
|
||||
0x80, 0xBD, 0x01, 0xDE
|
||||
}, "ASPack 1.04b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, 0xEA, 0xA8, 0x43, null, 0xB8, 0xE4, 0xA8,
|
||||
0x43, null, 0x03, 0xC5, 0x2B, 0x85, 0x78, 0xAD,
|
||||
0x43, null, 0x89, 0x85, 0x84, 0xAD, 0x43, null,
|
||||
0x80, 0xBD, 0x6E, 0xAD, 0x43
|
||||
}, "ASPack 1.06.1b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x90, 0x61, 0xBE, null, null, null, null, 0x8D,
|
||||
0xBE, null, null, null, null, 0x57, 0x83, 0xCD,
|
||||
0xFF
|
||||
}, "ASPack 1.06.1b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, null,
|
||||
null, null, null, null, null, 0xB8, null, null,
|
||||
null, null, 0x03, 0xC5
|
||||
}, "ASPack 1.07b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, null, null, null, null, 0x60, 0xE8, 0x2B,
|
||||
0x03, 0x00, 0x00
|
||||
}, "ASPack 1.07b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xEB, 0x0A, 0x5D, 0xEB, 0x02, 0xFF, 0x25,
|
||||
0x45, 0xFF, 0xE5, 0xE8, 0xE9, 0xE8, 0xF1, 0xFF,
|
||||
0xFF, 0xFF, 0xE9, 0x81, null, null, null, 0x44,
|
||||
0x00, 0xBB, 0x10, null, 0x44, 0x00, 0x03, 0xDD,
|
||||
0x2B, 0x9D
|
||||
}, "ASPack 1.08.01"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xEB, 0x0A, 0x5D, 0xEB, 0x02, 0xFF, 0x25,
|
||||
0x45, 0xFF, 0xE5, 0xE8, 0xE9, 0xE8, 0xF1, 0xFF,
|
||||
0xFF, 0xFF, 0xE9, 0x81, null, null, null, 0x44,
|
||||
null, 0xBB, 0x10, null, 0x44, null, 0x03, 0xDD,
|
||||
0x2B, 0x9D
|
||||
}, "ASPack 1.08.01"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xEB, 0x0A, 0x5D, 0xEB, 0x02, 0xFF, 0x25,
|
||||
0x45, 0xFF, 0xE5, 0xE8, 0xE9, 0xE8, 0xF1, 0xFF,
|
||||
0xFF, 0xFF, 0xE9, 0x81, 0xED, 0x23, 0x6A, 0x44,
|
||||
0x00, 0xBB, 0x10, null, 0x44, 0x00, 0x03, 0xDD,
|
||||
0x2B, 0x9D, 0x72
|
||||
}, "ASPack 1.08.02"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, null,
|
||||
null, null, null, null, null, 0xBB, null, null,
|
||||
null, null, 0x03, 0xDD, 0x2B, 0x9D, 0xB1, 0x50,
|
||||
0x44, 0x00, 0x83, 0xBD, 0xAC, 0x50, 0x44, 0x00,
|
||||
0x00, 0x89, 0x9D, 0xBB, 0x4E
|
||||
}, "ASPack 1.08.03"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, null,
|
||||
null, null, null, null, null, 0xBB, null, null,
|
||||
null, null, 0x03, 0xDD
|
||||
}, "ASPack 1.08.03"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x55, 0x57, 0x51, 0x53, 0xE8, null, null, null,
|
||||
null, 0x5D, 0x8B, 0xC5, 0x81, 0xED, null, null,
|
||||
null, null, 0x2B, 0x85, null, null, null, null,
|
||||
0x83, 0xE8, 0x09, 0x89, 0x85, null, null, null,
|
||||
null, 0x0F, 0xB6
|
||||
}, "ASPack 1.08.03"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE9, null, null, null, null, 0xEF, 0x40,
|
||||
0x03, 0xA7, 0x07, 0x8F, 0x07, 0x1C, 0x37, 0x5D,
|
||||
0x43, 0xA7, 0x04, 0xB9, 0x2C, 0x3A
|
||||
}, "ASPack 1.08.x"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xEB, 0x09,
|
||||
0x5D, 0x55, 0x81, 0xED, 0x39, 0x39, 0x44, 0x00,
|
||||
0xC3, 0xE9, null, 0x04, 0x00, 0x00
|
||||
}, "ASPack 2.11.x -> Alexey Solodovnikov"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
null, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9, 0xEB,
|
||||
0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01
|
||||
}, "ASPack 2.12 (without Poly) -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
null, 0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9,
|
||||
0xEB, 0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01,
|
||||
0x00, 0x00, 0x00, 0xEB, 0x5D, 0xBB, 0xEC, 0xFF,
|
||||
0xFF, 0xFF, 0x03, 0xDD, 0x81, 0xEB, 0x00, null,
|
||||
null, 0x00, 0x83, 0xBD, 0x22, 0x04, 0x00, 0x00,
|
||||
0x00, 0x89, 0x9D, 0x22, 0x04, 0x00, 0x00, 0x0F,
|
||||
0x85, 0x65, 0x03, 0x00, 0x00, 0x8D, 0x85, 0x2E,
|
||||
0x04, 0x00, 0x00, 0x50, 0xFF, 0x95, 0x4C, 0x0F,
|
||||
0x00, 0x00, 0x89, 0x85, 0x26, 0x04, 0x00, 0x00,
|
||||
0x8B, 0xF8, 0x8D, 0x5D, 0x5E, 0x53, 0x50, 0xFF,
|
||||
0x95, 0x48, 0x0F, 0x00, 0x00, 0x89, 0x85, 0x4C,
|
||||
0x05, 0x00, 0x00, 0x8D, 0x5D, 0x6B, 0x53, 0x57,
|
||||
0xFF, 0x95, 0x48, 0x0F
|
||||
}, "ASPack 2.12b -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9, 0xEB,
|
||||
0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01, 0x00,
|
||||
0x00, 0x00, 0xEB, 0x5D, 0xBB, 0xED, 0xFF, 0xFF,
|
||||
0xFF, 0x03, 0xDD, null, null, null, null, null,
|
||||
null, 0x83, 0xBD, 0x7D, 0x04, 0x00, 0x00, 0x00,
|
||||
0x89, 0x9D, 0x7D, 0x04, 0x00, 0x00, 0x0F, 0x85,
|
||||
0xC0, 0x03, 0x00, 0x00, 0x8D, 0x85, 0x89, 0x04,
|
||||
0x00, 0x00, 0x50, 0xFF, 0x95, 0x09, 0x0F, 0x00,
|
||||
0x00, 0x89, 0x85, 0x81, 0x04, 0x00, 0x00, 0x8B,
|
||||
0xF0, 0x8D, 0x7D, 0x51, 0x57, 0x56, 0xFF, 0x95,
|
||||
0x05, 0x0F, 0x00, 0x00, 0xAB, 0xB0, 0x00, 0xAE,
|
||||
0x75, 0xFD, 0x38, 0x07, 0x75, 0xEE, 0x8D, 0x45,
|
||||
0x7A, 0xFF, 0xE0, 0x56, 0x69, 0x72, 0x74, 0x75,
|
||||
0x61, 0x6C, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x00,
|
||||
0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6C, 0x46,
|
||||
0x72, 0x65, 0x65, 0x00, 0x56, 0x69, 0x72, 0x74,
|
||||
0x75, 0x61, 0x6C, 0x50, 0x72, 0x6F, 0x74, 0x65,
|
||||
0x63, 0x74, 0x00, 0x00, 0x8B, 0x9D, 0x8D, 0x05,
|
||||
0x00, 0x00, 0x0B, 0xDB, 0x74, 0x0A, 0x8B, 0x03,
|
||||
0x87, 0x85, 0x91, 0x05, 0x00, 0x00, 0x89, 0x03,
|
||||
0x8D, 0xB5, 0xBD, 0x05, 0x00, 0x00, 0x83, 0x3E,
|
||||
0x00, 0x0F, 0x84, 0x15, 0x01, 0x00, 0x00, 0x6A,
|
||||
0x04, 0x68, 0x00, 0x10, 0x00, 0x00, 0x68, 0x00,
|
||||
0x18, 0x00, 0x00, 0x6A, 0x00, 0xFF, 0x55, 0x51,
|
||||
0x89, 0x85, 0x53, 0x01, 0x00, 0x00, 0x8B, 0x46,
|
||||
0x04, 0x05, 0x0E, 0x01, 0x00, 0x00, 0x6A, 0x04,
|
||||
0x68, 0x00, 0x10, 0x00, 0x00, 0x50, 0x6A, 0x00,
|
||||
0xFF, 0x55, 0x51, 0x89, 0x85, 0x4F, 0x01, 0x00,
|
||||
0x00, 0x56, 0x8B, 0x1E, 0x03, 0x9D, 0x7D, 0x04,
|
||||
0x00, 0x00, 0xFF, 0xB5, 0x53, 0x01, 0x00, 0x00,
|
||||
0xFF, 0x76, 0x04, 0x50, 0x53, 0xE8, 0x2D, 0x05,
|
||||
0x00, 0x00, 0xB3, 0x00, 0x80, 0xFB, 0x00, 0x75,
|
||||
0x5E, 0xFE, 0x85, 0xE9, 0x00, 0x00, 0x00, 0x8B,
|
||||
0x3E, 0x03, 0xBD, 0x7D, 0x04, 0x00, 0x00, 0xFF,
|
||||
0x37, 0xC6, 0x07, 0xC3, 0xFF, 0xD7, 0x8F, 0x07,
|
||||
0x50, 0x51, 0x56, 0x53, 0x8B, 0xC8, 0x83, 0xE9,
|
||||
0x06, 0x8B, 0xB5, 0x4F, 0x01, 0x00, 0x00, 0x33,
|
||||
0xDB, 0x0B, 0xC9, 0x74, 0x2E, 0x78, 0x2C, 0xAC,
|
||||
0x3C, 0xE8, 0x74, 0x0A, 0xEB, 0x00, 0x3C, 0xE9,
|
||||
0x74, 0x04, 0x43, 0x49, 0xEB, 0xEB, 0x8B, 0x06,
|
||||
0xEB, 0x00, null, null, null, 0x75, 0xF3, 0x24,
|
||||
0x00, 0xC1, 0xC0, 0x18, 0x2B, 0xC3, 0x89, 0x06,
|
||||
0x83, 0xC3, 0x05, 0x83, 0xC6, 0x04, 0x83, 0xE9,
|
||||
0x05, 0xEB, 0xCE, 0x5B, 0x5E, 0x59, 0x58, 0xEB,
|
||||
0x08
|
||||
}, "ASPack 2.2 -> Alexey Solodovnikov & StarForce * 2009408"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
null, 0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9,
|
||||
0xEB, 0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01,
|
||||
0x00, 0x00, 0x00, 0xEB, 0x5D, 0xBB, 0xEC, 0xFF,
|
||||
0xFF, 0xFF, 0x03, 0xDD, 0x81, 0xEB, 0x00, 0x40,
|
||||
0x1C, 0x00
|
||||
}, "ASPack 2.x (without Poly) -> Solodovnikov Alexey"),
|
||||
|
||||
#endregion
|
||||
|
||||
#region 2.xx (Long)
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0xA8, 0x03, 0x00, 0x00, 0x61, 0x75, 0x08, 0xB8,
|
||||
0x01, 0x00, 0x00, 0x00, 0xC2, 0x0C, 0x00, 0x68,
|
||||
0x00, 0x00, 0x00, 0x00, 0xC3, 0x8B, 0x85, 0x26,
|
||||
0x04, 0x00, 0x00, 0x8D, 0x8D, 0x3B, 0x04, 0x00,
|
||||
0x00, 0x51, 0x50, 0xFF, 0x95
|
||||
}, "ASPack 2.xx"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0xA8, 0x03, null, null, 0x61, 0x75, 0x08, 0xB8,
|
||||
0x01, null, null, null, 0xC2, 0x0C, null, 0x68,
|
||||
null, null, null, null, 0xC3, 0x8B, 0x85, 0x26,
|
||||
0x04, null, null, 0x8D, 0x8D, 0x3B, 0x04, null,
|
||||
null, 0x51, 0x50, 0xFF, 0x95
|
||||
}, "ASPack 2.xx"),
|
||||
|
||||
#endregion
|
||||
|
||||
#region Short
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x75, 0x00, 0xE9 }, "ASPack 1.05b"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x90, 0x75, 0x00, 0xE9 }, "ASPack 1.06.1b"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x75, 0x00, 0xE9 }, "ASPack 1.06.1b"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x75, 0x00, 0xE9 }, "ASPack 1.06.1b"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x90, 0x75, null, 0xE9 }, "ASPack 1.07b"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x75, null, 0xE9 }, "ASPack 1.07b"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x75, null, 0xE9 }, "ASPack 1.07b"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x90, 0x75, 0x01, 0x90, 0xE9 }, "ASPack 1.08"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x90, 0x75, 0x01, 0xFF, 0xE9 }, "ASPack 1.08"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x75, 0x01, 0xFF, 0xE9 }, "ASPack 1.08"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x75, 0x01, 0xFF, 0xE9 }, "ASPack 1.08"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x90, 0x75, null, 0x90, 0xE9 }, "ASPack 1.08.01"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x75, null, 0x90, 0xE9 }, "ASPack 1.08.01"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x75, null, 0x90, 0xE9 }, "ASPack 1.08.01"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x75, 0x01, 0x90, 0xE9 }, "ASPack 1.08.02"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x75, 0x01, 0x90, 0xE9 }, "ASPack 1.08.02"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0x41, 0x06, 0x00, 0x00, 0xEB, 0x41 }, "ASPack 1.08.04"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE8, null, null, null, null, 0xEB }, "ASPack 1.08.04"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0x70, 0x05, 0x00, 0x00, 0xEB, 0x4C }, "ASPack 2.00.00"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0x48, 0x11, 0x00, 0x00, 0xC3, 0x83 }, "ASPack 2.00.00"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0x72, 0x05, 0x00, 0x00, 0xEB, 0x4C }, "ASPack 2.00.01"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE8, null, 0x05, 0x00, 0x00, 0xEB, 0x4C }, "ASPack 2.00.x -> Alexey Solodovnikov"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE9, 0x3D, 0x04, 0x00, 0x00 }, "ASPack 2.11"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0xF9, 0x11, 0x00, 0x00, 0xC3, 0x83 }, "ASPack 2.11"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81, 0xED }, "ASPack 1.02b/1.08.03"),
|
||||
|
||||
#endregion
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,21 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using BurnOutSharp.ExecutableType.Microsoft;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
// TODO: Add extraction and verify that all versions are detected
|
||||
public class AdvancedInstaller : IContentCheck
|
||||
// TODO: Add extraction
|
||||
// TODO: Verify that all versions are detected
|
||||
public class AdvancedInstaller : IPortableExecutableCheck, IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug, PortableExecutable pex, NewExecutable nex)
|
||||
public bool ShouldScan(byte[] magic) => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex?.SectionTable;
|
||||
@@ -36,5 +43,23 @@ namespace BurnOutSharp.PackerType
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BurnOutSharp.ExecutableType.Microsoft;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
// TODO: Add extraction
|
||||
// TODO: Add version checking, if possible
|
||||
public class Armadillo : IContentCheck
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class Armadillo : IPortableExecutableCheck, IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug, PortableExecutable pex, NewExecutable nex)
|
||||
public bool ShouldScan(byte[] magic) => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex?.SectionTable;
|
||||
@@ -23,22 +30,42 @@ namespace BurnOutSharp.PackerType
|
||||
return "Armadillo";
|
||||
|
||||
// Loop through all "extension" sections -- usually .data1 or .text1
|
||||
foreach (var section in sections.Where(s => s != null && Encoding.ASCII.GetString(s.Name).Trim('\0').EndsWith("1")))
|
||||
foreach (var section in sections.Where(s => s != null && s.NameString.EndsWith("1")))
|
||||
{
|
||||
string sectionName = Encoding.ASCII.GetString(section.Name).Trim('\0');
|
||||
var sectionRaw = pex.ReadRawSection(fileContent, sectionName);
|
||||
var matchers = new List<ContentMatchSet>
|
||||
var sectionRaw = pex.ReadRawSection(section.NameString);
|
||||
if (sectionRaw != null)
|
||||
{
|
||||
// ARMDEBUG
|
||||
new ContentMatchSet(new byte?[] { 0x41, 0x52, 0x4D, 0x44, 0x45, 0x42, 0x55, 0x47 }, $"Armadillo"),
|
||||
};
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
// ARMDEBUG
|
||||
new ContentMatchSet(new byte?[] { 0x41, 0x52, 0x4D, 0x44, 0x45, 0x42, 0x55, 0x47 }, $"Armadillo"),
|
||||
};
|
||||
|
||||
string match = MatchUtil.GetFirstMatch(file, sectionRaw, matchers, includeDebug);
|
||||
if (!string.IsNullOrWhiteSpace(match))
|
||||
return match;
|
||||
string match = MatchUtil.GetFirstMatch(file, sectionRaw, matchers, includeDebug);
|
||||
if (!string.IsNullOrWhiteSpace(match))
|
||||
return match;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
74
BurnOutSharp/PackerType/AutoPlayMediaStudio.cs
Normal file
74
BurnOutSharp/PackerType/AutoPlayMediaStudio.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
// Created by IndigoRose (creators of Setup Factory), primarily to be used to create autorun menus for various media.
|
||||
// Official website: https://www.autoplay.org/
|
||||
// TODO: Add extraction
|
||||
public class AutoPlayMediaStudio : IPortableExecutableCheck, IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic) => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex?.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
// Known to detect versions 5.0.0.3 - 8.1.0.0
|
||||
string name = pex.ProductName;
|
||||
if (name?.StartsWith("AutoPlay Media Studio", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"AutoPlay Media Studio {GetVersion(pex)}";
|
||||
|
||||
// Currently too vague, may be re-enabled in the future
|
||||
/*
|
||||
name = Utilities.GetLegalCopyright(pex);
|
||||
if (name?.StartsWith("Runtime Engine", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"AutoPlay Media Studio {GetVersion(pex)}";
|
||||
*/
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
private string GetVersion(PortableExecutable pex)
|
||||
{
|
||||
// Check the product version explicitly
|
||||
string version = pex.ProductVersion;
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return version;
|
||||
|
||||
// Check the internal versions
|
||||
version = Utilities.GetInternalVersion(pex);
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return version;
|
||||
|
||||
return "(Unknown Version)";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,23 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
// The official website for CExe also includes the source code (which does have to be retrieved by the Wayback Machine)
|
||||
// http://www.scottlu.com/Content/CExe.html
|
||||
public class CExe : IContentCheck, IScannable
|
||||
// TODO: Add extraction
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class CExe : IPortableExecutableCheck, IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic) => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug, PortableExecutable pex, NewExecutable nex)
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var stub = pex?.DOSStubHeader;
|
||||
@@ -23,7 +26,6 @@ namespace BurnOutSharp.PackerType
|
||||
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
// %Wo<57>a6.<2E>a6.<2E>a6.<2E>a6.<2E>{6.<2E>.).<2E>f6.<2E><>).<2E>`6.<2E><>0.<2E>`6.<2E>
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x25, 0x57, 0x6F, 0xC1, 0x61, 0x36, 0x01, 0x92,
|
||||
@@ -55,7 +57,6 @@ namespace BurnOutSharp.PackerType
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
// TODO: Add extraction if viable
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
return null;
|
||||
|
||||
@@ -1,14 +1,49 @@
|
||||
using BurnOutSharp.ExecutableType.Microsoft;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
// TODO: Figure out how to more granularly determine versions like PiD,
|
||||
// at least for the 2.41 -> 2.75 range
|
||||
// TODO: Detect 3.15 and up (maybe looking for `Metamorphism`)
|
||||
public class EXEStealth : IContentCheck
|
||||
// TODO: Add extraction
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class EXEStealth : IContentCheck, IPortableExecutableCheck, IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug, PortableExecutable pex, NewExecutable nex)
|
||||
public bool ShouldScan(byte[] magic) => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug)
|
||||
{
|
||||
// TODO: Obtain a sample to find where this string is in a typical executable
|
||||
if (includeDebug)
|
||||
{
|
||||
var contentMatchSets = new List<ContentMatchSet>
|
||||
{
|
||||
// ??[[__[[_ + (char)0x00 + {{ + (char)0x0 + (char)0x00 + {{ + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x0 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + ?;??;??
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x3F, 0x3F, 0x5B, 0x5B, 0x5F, 0x5F, 0x5B, 0x5B,
|
||||
0x5F, 0x00, 0x7B, 0x7B, 0x00, 0x00, 0x7B, 0x7B,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x20, 0x3F, 0x3B, 0x3F, 0x3F, 0x3B, 0x3F,
|
||||
0x3F
|
||||
}, "EXE Stealth"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex?.SectionTable;
|
||||
@@ -31,22 +66,24 @@ namespace BurnOutSharp.PackerType
|
||||
return "EXE Stealth 2.76";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: Could not be confirmed with any sample, so disabling for now
|
||||
// var contentMatchSets = new List<ContentMatchSet>
|
||||
// {
|
||||
// // ??[[__[[_ + (char)0x00 + {{ + (char)0x0 + (char)0x00 + {{ + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x0 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + ?;??;??
|
||||
// new ContentMatchSet(new byte?[]
|
||||
// {
|
||||
// 0x3F, 0x3F, 0x5B, 0x5B, 0x5F, 0x5F, 0x5B, 0x5B,
|
||||
// 0x5F, 0x00, 0x7B, 0x7B, 0x00, 0x00, 0x7B, 0x7B,
|
||||
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// 0x00, 0x20, 0x3F, 0x3B, 0x3F, 0x3F, 0x3B, 0x3F,
|
||||
// 0x3F
|
||||
// }, "EXE Stealth"),
|
||||
// };
|
||||
|
||||
// return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
69
BurnOutSharp/PackerType/GenteeInstaller.cs
Normal file
69
BurnOutSharp/PackerType/GenteeInstaller.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
// TODO: Add extraction
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class GenteeInstaller : IPortableExecutableCheck, IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic) => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex?.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
// Get the .data section, if it exists
|
||||
if (pex.DataSectionRaw != null)
|
||||
{
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
// Gentee installer
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x47, 0x65, 0x6E, 0x74, 0x65, 0x65, 0x20, 0x69,
|
||||
0x6E, 0x73, 0x74, 0x61, 0x6C, 0x6C, 0x65, 0x72,
|
||||
}, "Gentee Installer"),
|
||||
|
||||
// ginstall.dll
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x67, 0x69, 0x6E, 0x73, 0x74, 0x61, 0x6C, 0x6C,
|
||||
0x2E, 0x64, 0x6C, 0x6C,
|
||||
}, "Gentee Installer"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(file, pex.DataSectionRaw, matchers, includeDebug);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,78 +4,66 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BurnOutSharp.ExecutableType.Microsoft;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.NE;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
public class InnoSetup : IContentCheck, IScannable
|
||||
// TODO: Add extraction - https://github.com/dscharrer/InnoExtract
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class InnoSetup : INewExecutableCheck, IPortableExecutableCheck, IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic) => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug, PortableExecutable pex, NewExecutable nex)
|
||||
public string CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
{
|
||||
// Try to read the contents as a PE executable
|
||||
if (pex != null)
|
||||
// Get the DOS stub from the executable, if possible
|
||||
var stub = nex?.DOSStubHeader;
|
||||
if (stub == null)
|
||||
return null;
|
||||
|
||||
// Check for "Inno" in the reserved words
|
||||
if (stub.Reserved2[4] == 0x6E49 && stub.Reserved2[5] == 0x6F6E)
|
||||
{
|
||||
var sections = pex?.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
string version = GetOldVersion(file, nex);
|
||||
if (!string.IsNullOrWhiteSpace(version))
|
||||
return $"Inno Setup {version}";
|
||||
|
||||
// Get the DATA/.data section, if it exists
|
||||
if (pex.DataSectionRaw != null)
|
||||
{
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
// Inno Setup Setup Data (
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x49, 0x6E, 0x6E, 0x6F, 0x20, 0x53, 0x65, 0x74,
|
||||
0x75, 0x70, 0x20, 0x53, 0x65, 0x74, 0x75, 0x70,
|
||||
0x20, 0x44, 0x61, 0x74, 0x61, 0x20, 0x28
|
||||
}, GetVersion, "Inno Setup"),
|
||||
};
|
||||
|
||||
string match = MatchUtil.GetFirstMatch(file, pex.DataSectionRaw, matchers, includeDebug);
|
||||
if (!string.IsNullOrWhiteSpace(match))
|
||||
return match;
|
||||
}
|
||||
|
||||
// Get the DOS stub from the executable, if possible
|
||||
var stub = pex?.DOSStubHeader;
|
||||
if (stub == null)
|
||||
return null;
|
||||
|
||||
// Check for "Inno" in the reserved words
|
||||
if (stub.Reserved2[4] == 0x6E49 && stub.Reserved2[5] == 0x6F6E)
|
||||
{
|
||||
string version = GetOldVersion(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(version))
|
||||
return $"Inno Setup {version}";
|
||||
|
||||
return "Inno Setup (Unknown Version)";
|
||||
}
|
||||
return "Inno Setup (Unknown Version)";
|
||||
}
|
||||
|
||||
// Try to read the contents as an NE executable
|
||||
if (nex != null)
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex?.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
// Get the DATA/.data section, if it exists
|
||||
if (pex.DataSectionRaw != null)
|
||||
{
|
||||
// Get the DOS stub from the executable, if possible
|
||||
var stub = nex?.DOSStubHeader;
|
||||
if (stub == null)
|
||||
return null;
|
||||
|
||||
// Check for "Inno" in the reserved words
|
||||
if (stub.Reserved2[4] == 0x6E49 && stub.Reserved2[5] == 0x6F6E)
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
string version = GetOldVersion(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(version))
|
||||
return $"Inno Setup {version}";
|
||||
|
||||
return "Inno Setup (Unknown Version)";
|
||||
}
|
||||
// Inno Setup Setup Data (
|
||||
new ContentMatchSet(new byte?[]
|
||||
{
|
||||
0x49, 0x6E, 0x6E, 0x6F, 0x20, 0x53, 0x65, 0x74,
|
||||
0x75, 0x70, 0x20, 0x53, 0x65, 0x74, 0x75, 0x70,
|
||||
0x20, 0x44, 0x61, 0x74, 0x61, 0x20, 0x28
|
||||
}, GetVersion, "Inno Setup"),
|
||||
};
|
||||
|
||||
string match = MatchUtil.GetFirstMatch(file, pex.DataSectionRaw, matchers, includeDebug);
|
||||
if (!string.IsNullOrWhiteSpace(match))
|
||||
return match;
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -93,8 +81,6 @@ namespace BurnOutSharp.PackerType
|
||||
}
|
||||
}
|
||||
|
||||
// TOOO: Add Inno Setup extraction
|
||||
// https://github.com/dscharrer/InnoExtract
|
||||
/// <inheritdoc/>
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
@@ -126,17 +112,23 @@ namespace BurnOutSharp.PackerType
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetOldVersion(string file, byte[] fileContent)
|
||||
private static string GetOldVersion(string file, NewExecutable nex)
|
||||
{
|
||||
// TODO: Only sample is an NE executable - verify if this is in PE as well or where in the NE this lives
|
||||
var matchers = new List<ContentMatchSet>
|
||||
// TODO: Don't read entire file
|
||||
// TODO: Only 64 bytes at the end of the file is needed
|
||||
var data = nex.ReadArbitraryRange();
|
||||
if (data != null)
|
||||
{
|
||||
// "rDlPtS02" + (char)0x87 + "eVx"
|
||||
new ContentMatchSet(new byte?[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x32, 0x87, 0x65, 0x56, 0x78 }, "1.2.16 or earlier"),
|
||||
};
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
// "rDlPtS02" + (char)0x87 + "eVx"
|
||||
new ContentMatchSet(new byte?[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x32, 0x87, 0x65, 0x56, 0x78 }, "1.2.16 or earlier"),
|
||||
};
|
||||
|
||||
string match = MatchUtil.GetFirstMatch(file, fileContent, matchers, false);
|
||||
return match ?? "Unknown 1.X";
|
||||
return MatchUtil.GetFirstMatch(file, data, matchers, false) ?? "Unknown 1.X";
|
||||
}
|
||||
|
||||
return "Unknown 1.X";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
64
BurnOutSharp/PackerType/InstallAnywhere.cs
Normal file
64
BurnOutSharp/PackerType/InstallAnywhere.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
// TODO: Add extraction, which may be possible with the current libraries but needs to be investigated further.
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class InstallAnywhere : IPortableExecutableCheck, IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic) => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex?.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
string name = pex.FileDescription;
|
||||
if (name?.StartsWith("InstallAnywhere Self Extractor", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"InstallAnywhere {GetVersion(pex)}";
|
||||
|
||||
name = pex.ProductName;
|
||||
if (name?.StartsWith("InstallAnywhere", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"InstallAnywhere {GetVersion(pex)}";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
private string GetVersion(PortableExecutable pex)
|
||||
{
|
||||
// Check the internal versions
|
||||
string version = Utilities.GetInternalVersion(pex);
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return version;
|
||||
|
||||
return "(Unknown Version)";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,22 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
public class InstallerVISE : IContentCheck, IScannable
|
||||
// TODO: Add extraction - https://github.com/Bioruebe/UniExtract2
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class InstallerVISE : IPortableExecutableCheck, IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic) => true;
|
||||
|
||||
//TODO: Add exact version detection for Windows builds, make sure versions before 3.X are detected as well, and detect the Mac builds.
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug, PortableExecutable pex, NewExecutable nex)
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex?.SectionTable;
|
||||
@@ -35,8 +38,6 @@ namespace BurnOutSharp.PackerType
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: Add Installer VISE extraction
|
||||
// https://github.com/Bioruebe/UniExtract2
|
||||
/// <inheritdoc/>
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, string file)
|
||||
{
|
||||
|
||||
@@ -1,37 +1,61 @@
|
||||
using System;
|
||||
using BurnOutSharp.ExecutableType.Microsoft;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
// TODO: Add extraction, seems to primarily use MSZip compression.
|
||||
public class IntelInstallationFramework : IContentCheck
|
||||
public class IntelInstallationFramework : IPortableExecutableCheck, IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug, PortableExecutable pex, NewExecutable nex)
|
||||
public bool ShouldScan(byte[] magic) => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex?.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
string name = Utilities.GetFileDescription(pex);
|
||||
string name = pex.FileDescription;
|
||||
if (!string.IsNullOrWhiteSpace(name)
|
||||
&& (name.Equals("Intel(R) Installation Framework", StringComparison.OrdinalIgnoreCase)
|
||||
|| name.Equals("Intel Installation Framework", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return $"Intel Installation Framework {Utilities.GetFileVersion(pex)}";
|
||||
return $"Intel Installation Framework {Utilities.GetInternalVersion(pex)}";
|
||||
}
|
||||
|
||||
name = Utilities.GetProductName(pex);
|
||||
name = pex.ProductName;
|
||||
if (!string.IsNullOrWhiteSpace(name)
|
||||
&& (name.Equals("Intel(R) Installation Framework", StringComparison.OrdinalIgnoreCase)
|
||||
|| name.Equals("Intel Installation Framework", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return $"Intel Installation Framework {Utilities.GetFileVersion(pex)}";
|
||||
return $"Intel Installation Framework {Utilities.GetInternalVersion(pex)}";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,32 +2,34 @@ using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.ExecutableType.Microsoft;
|
||||
using BurnOutSharp.ExecutableType.Microsoft.PE;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Matching;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
// TODO: Add extraction, which should be possible with LibMSPackN, but it refuses to extract due to SFX files lacking the typical CAB identifiers.
|
||||
public class MicrosoftCABSFX : IContentCheck, IScannable
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class MicrosoftCABSFX : IPortableExecutableCheck, IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic) => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug, PortableExecutable pex, NewExecutable nex)
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex?.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
string name = Utilities.GetInternalName(pex);
|
||||
if (!string.IsNullOrWhiteSpace(name) && name.Equals("Wextract", StringComparison.OrdinalIgnoreCase))
|
||||
string name = pex.InternalName;
|
||||
if (name?.Equals("Wextract", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"Microsoft CAB SFX {GetVersion(pex)}";
|
||||
|
||||
name = Utilities.GetOriginalFileName(pex);
|
||||
if (!string.IsNullOrWhiteSpace(name) && name.Equals("WEXTRACT.EXE", StringComparison.OrdinalIgnoreCase))
|
||||
name = pex.OriginalFileName;
|
||||
if (name?.Equals("WEXTRACT.EXE", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"Microsoft CAB SFX {GetVersion(pex)}";
|
||||
|
||||
// Get the .data section, if it exists
|
||||
@@ -87,11 +89,8 @@ namespace BurnOutSharp.PackerType
|
||||
|
||||
private string GetVersion(PortableExecutable pex)
|
||||
{
|
||||
string version = Utilities.GetFileVersion(pex);
|
||||
if (!string.IsNullOrWhiteSpace(version))
|
||||
return $"v{version}";
|
||||
|
||||
version = Utilities.GetManifestVersion(pex);
|
||||
// Check the internal versions
|
||||
string version = Utilities.GetInternalVersion(pex);
|
||||
if (!string.IsNullOrWhiteSpace(version))
|
||||
return $"v{version}";
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user