Compare commits

...

268 Commits

Author SHA1 Message Date
Matt Nadareski
9a931eae67 Bump version 2021-04-14 09:09:48 -07:00
Matt Nadareski
47caa714c4 Remove pause from Valve entirely 2021-04-14 09:08:36 -07:00
Matt Nadareski
6740011c11 Bump version to 1.6.0 2021-04-09 09:32:12 -07:00
SilasLaspada
732078f24d Improve Steam detection (#35)
* Improve Steam detection

* Alphabetize the order of detections
2021-04-03 21:25:22 -07:00
Matt Nadareski
5218aaaeb1 Remove all uses of Pause in Valve 2021-04-03 20:49:53 -07:00
Matt Nadareski
6b9df94613 Remove unused library from README 2021-04-02 16:02:39 -07:00
Matt Nadareski
b1ac88fc20 Use submodule for WixToolset.Dtf 2021-04-02 16:01:23 -07:00
Matt Nadareski
ca83019a58 Move wix mirror to backup 2021-04-02 15:51:46 -07:00
Matt Nadareski
d68272a5bb Use submodule for stormlibsharp
This also gets CascLibSharp for free. Maybe keep that in mind
2021-04-02 15:48:57 -07:00
Matt Nadareski
6ab0fd5e3b Move StormLibSharp mirror to backup 2021-04-02 15:38:59 -07:00
Matt Nadareski
a0034b8fa8 Use submodule for hllib 2021-04-02 15:34:47 -07:00
Matt Nadareski
a884737242 Move HLLib mirror to backup 2021-04-02 15:19:00 -07:00
Matt Nadareski
c7b3776386 Use submodule for libmspack4n 2021-04-02 15:17:26 -07:00
Matt Nadareski
b387c77179 Move libmspack4n mirror to backup 2021-04-02 15:09:56 -07:00
Matt Nadareski
f6b58223de Replace LessIO code mirror with submodule 2021-04-02 15:08:05 -07:00
Matt Nadareski
8960ad3b16 Backup current LessIO code mirror 2021-04-02 14:54:46 -07:00
Matt Nadareski
28e95f9eb7 Slight SolidShield cleanup 2021-04-01 15:00:22 -07:00
Matt Nadareski
0bf5065cbc Add future work note 2021-04-01 14:53:25 -07:00
Matt Nadareski
579c9c0f84 Fix missing SafeDisc version 2021-04-01 11:38:32 -07:00
Matt Nadareski
b2e8b66eae Fix SmartE overmatching 2021-04-01 11:20:13 -07:00
Matt Nadareski
80e71f43de Try to make structs more marshalable 2021-04-01 11:09:20 -07:00
Matt Nadareski
e0497e6fee Migrate SafeDisc to modern path checking 2021-04-01 10:38:50 -07:00
Matt Nadareski
18a78f44c0 Make EVORE a bit safer 2021-04-01 10:36:03 -07:00
Matt Nadareski
f9e7fd5725 Fix marshalling issue 2021-04-01 10:34:53 -07:00
Matt Nadareski
e9c1a170ad Move generic CD key to own file 2021-03-31 19:07:00 -07:00
SilasLaspada
9ce84c75dd Comment out an overmatching definition (#34) 2021-03-31 18:58:34 -07:00
Matt Nadareski
0bd5339b78 Update to UnshieldSharp 1.5.0 2021-03-29 14:35:06 -07:00
Matt Nadareski
e06b1987b9 Update to WiseUnpacker 1.0.2 2021-03-29 14:17:42 -07:00
Matt Nadareski
c8b271ac76 Port over executable header code from Wise 2021-03-25 15:53:45 -07:00
Matt Nadareski
1672c73a57 Fix PECompact scanning
Thanks Silas for noticing the regression
2021-03-25 15:25:15 -07:00
Matt Nadareski
32f6e0e8fc Further making test executable a bit nicer 2021-03-24 20:50:58 -07:00
Matt Nadareski
5c21de5a0f Make the test executable a bit nicer 2021-03-23 16:55:19 -07:00
Matt Nadareski
9f40a8c4c0 Perform some post-removal cleanup 2021-03-23 16:43:23 -07:00
Matt Nadareski
c179f29e2e Remove .NET Framework 4.7.2, update SharpCompress 2021-03-23 16:37:21 -07:00
Matt Nadareski
f9d6fce3bd Reduce boilerplate for directory checks 2021-03-23 13:35:12 -07:00
Matt Nadareski
aa83896963 Final batch of first pass for path check conversions 2021-03-23 10:36:14 -07:00
Matt Nadareski
7d13b8c9db Optimize checking with better caching 2021-03-23 10:04:09 -07:00
Matt Nadareski
921292e077 Static list of content matchers
This also includes some more path matcher conversions that I couldn't reasonably split out
2021-03-23 09:52:09 -07:00
Matt Nadareski
c3e7f0b99f Return empty not null 2021-03-23 08:47:36 -07:00
Matt Nadareski
b9cc5e9ada Second batch of path check conversions 2021-03-22 23:02:01 -07:00
Matt Nadareski
76d76b2bf2 Convert a few more path checks 2021-03-22 22:23:55 -07:00
Matt Nadareski
532e912a2d Accidental comment issue 2021-03-22 22:12:25 -07:00
Matt Nadareski
8ada667dfe Be consistent with var naming 2021-03-22 22:11:01 -07:00
Matt Nadareski
28a4f7ce82 File path should only get first match 2021-03-22 22:09:35 -07:00
Matt Nadareski
3a66183d0e Convert AACS to use new matching 2021-03-22 22:07:14 -07:00
Matt Nadareski
7f91346878 Fix assumptions for path matching 2021-03-22 22:06:55 -07:00
Matt Nadareski
2af0dc4a8c Don't include PDBs 2021-03-22 21:38:49 -07:00
Matt Nadareski
5240f2eb70 Simplify util method naming 2021-03-22 21:32:58 -07:00
Matt Nadareski
f25800510b MatchSet is abstract 2021-03-22 21:30:30 -07:00
Matt Nadareski
6400c954ef Split matchers more cleanly, comment better 2021-03-22 21:25:14 -07:00
Matt Nadareski
e43423d2c9 Fix misleading version results 2021-03-22 16:25:40 -07:00
Matt Nadareski
bc613a0413 Fix build 2021-03-22 11:44:16 -07:00
Matt Nadareski
e47a52dbe0 Use framework in even more content protections 2021-03-22 11:43:51 -07:00
Matt Nadareski
da165345b6 Use framework for more content protections 2021-03-22 11:13:14 -07:00
Matt Nadareski
8ea54328ef Use framework for WZ-SFX v2 checks 2021-03-22 10:22:56 -07:00
Matt Nadareski
a4aeebee68 Split content and path version checks 2021-03-22 10:04:33 -07:00
Matt Nadareski
95a61c3b28 Add path matching to util 2021-03-22 09:55:29 -07:00
Matt Nadareski
9aadf5e948 Add invariance 2021-03-22 01:26:33 -07:00
Matt Nadareski
129ac1bb78 More granular on path search 2021-03-22 01:18:49 -07:00
Matt Nadareski
e4278c55b7 Add path matching matcher 2021-03-22 01:11:59 -07:00
Matt Nadareski
7aca58a6c9 Better split matching code, fix UPX name 2021-03-22 00:41:18 -07:00
Matt Nadareski
ea022de022 Fix a couple things:
- Fix PECompact 2 version string
- Fix UPX (NOS Variant) over-matching
2021-03-21 23:14:37 -07:00
Matt Nadareski
bb4f16d91f Use content matching helper, part 6 2021-03-21 22:45:06 -07:00
Matt Nadareski
f1c165845f Merge branch 'master' of https://github.com/mnadareski/BurnOutSharp 2021-03-21 22:37:25 -07:00
Matt Nadareski
15ae2441c3 Use content matching helper, part 5 2021-03-21 22:37:16 -07:00
SilasLaspada
6b8f8957de Add Advanced Installer Detection (#32)
* Add Advanced Installer Detection

* Updated README

* Address comments
2021-03-21 22:36:01 -07:00
Matt Nadareski
cf9bd99f3d Use content matching helper, part 4 2021-03-21 22:19:38 -07:00
SilasLaspada
557114d92d Add CExe detection (#30)
* Add CExe detection

* Optimize check
2021-03-21 21:39:01 -07:00
Matt Nadareski
d01826ffa4 Use content matching helper, part 3 2021-03-21 15:34:19 -07:00
Matt Nadareski
7e3ef544f0 Use content matching helper, part 2 2021-03-21 15:24:23 -07:00
Matt Nadareski
ab07eb96ce Use content matching helper, part 1 2021-03-21 14:30:37 -07:00
Matt Nadareski
7c53eaab13 Merge branch 'master' of https://github.com/mnadareski/BurnOutSharp 2021-03-21 14:04:19 -07:00
SilasLaspada
fad7d87282 Add WinRAR SFX detection and extraction (#31) 2021-03-21 14:03:47 -07:00
Matt Nadareski
578519169a Add helper method for simple content matches 2021-03-20 22:37:56 -07:00
Matt Nadareski
fe106d23ec Fix BD+ in reverse 2021-03-20 22:28:57 -07:00
Matt Nadareski
e1669f031f BD+ using BitConverter 2021-03-20 22:00:38 -07:00
SilasLaspada
9bff6d5fe1 Improve version detection (#29)
* Improve version detection

* Address comments

* Address comments

Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2021-03-20 21:29:19 -07:00
Matt Nadareski
544aaed9da Modify array finding, part 2 2021-03-20 20:47:56 -07:00
Matt Nadareski
b6b7a5e7aa Clean up terminology 2021-03-20 19:23:59 -07:00
Matt Nadareski
cdc4d509ee Modify array finding, part 1 2021-03-20 19:00:22 -07:00
Matt Nadareski
07882f7632 Create and use manifesr version utility 2021-03-20 17:34:31 -07:00
Matt Nadareski
deb3c01362 Merge branch 'master' of https://github.com/mnadareski/BurnOutSharp 2021-03-20 16:26:19 -07:00
SilasLaspada
a51b16aed2 Add Setup Factory detection (#28)
* Add Setup Factory detection

* Improve version detection

* Address comments
2021-03-20 16:18:17 -07:00
Matt Nadareski
0e7d98158e Split out generic online registration 2021-03-20 13:29:46 -07:00
Matt Nadareski
56d8518ee4 Comment out over-matching EA check 2021-03-19 17:31:53 -07:00
Matt Nadareski
8897fd8650 Make SafeDisc more like Tages path check 2021-03-19 15:56:07 -07:00
Matt Nadareski
6f811e43d0 Split method in Scanner too 2021-03-19 15:48:53 -07:00
Matt Nadareski
a2888e3371 Split IPathCheck method 2021-03-19 15:41:49 -07:00
SilasLaspada
30d3312d87 Added BD+ version detection (#26)
* Added BD+ version detection

* Address Comments

* Address comment

* Remove unnecessary assignment
2021-03-18 10:50:45 -07:00
SilasLaspada
854a257fd6 Implement AACS version detection (#25)
* Implement AACS version detection

* Address comments

* Address more comments

* Address comment
2021-03-17 22:27:37 -07:00
Matt Nadareski
28344c6e3f Add WinZip SFX to readme 2021-03-14 14:39:31 -07:00
SilasLaspada
11a82addd8 Implement BD+ detection (#24) 2021-03-14 14:23:24 -07:00
Matt Nadareski
152f6c7051 Reduce size of 32-bit checks 2021-03-14 14:16:54 -07:00
Matt Nadareski
bedbceafa7 Use NE headers for all 16-bit versions 2021-03-14 13:55:26 -07:00
Matt Nadareski
2f19bf7ceb SFX cleanup and add missing check 2021-03-14 00:19:10 -08:00
SilasLaspada
a39ae9facf Add support for WinZip SFX archives (#23)
* Add inital check for WinZip SFX archives

Every version of WinZip SFX has the string "WinZip Self-Extractor" in it,

* Add basic version detection

Versions 3+ and 2.x are identified radically differently, so make separate methods for them.

* Implement version 3+ detection

Should be very thorough detection, detects every 3+ file I have accurately.

* Cleanup code

General clanup

* Improve version 3+ detection

Use an XML string to determine the version.

* Harden against false positives

* Implement basic extraction

* Partial 2.X version detection

Very crude but effective 2.X detection for 2.0 versions

* Add version detection for 2.1 RC2 variants

* Add 2.1 version detection

* Add 2.2 version detection

Aside from clean-ups, this is the final functional addition

* Address comments
2021-03-13 20:18:03 -08:00
Matt Nadareski
56b234bc96 A little cleanup 2021-03-02 15:21:14 -08:00
Matt Nadareski
633fe23b80 Reflection
This change eliminates the need to explicitly list out every single protection in the same way now that we have interfaces that we can rely on.
2021-03-02 15:10:52 -08:00
Matt Nadareski
2867ce2e9a Add more EA CDKey checks (fixes #21) 2021-03-02 13:48:10 -08:00
Matt Nadareski
ac0e5e95a9 Add note to RPT scan 2021-03-02 13:34:15 -08:00
Matt Nadareski
e3bed19e79 Import WixToolset code as external 2021-03-02 13:09:15 -08:00
Matt Nadareski
73aae8118f Wrap in libmspack4n and LessIO as external code 2021-03-02 12:14:14 -08:00
Matt Nadareski
b3671a430e Swap order of params for IPathCheck 2021-02-26 11:02:10 -08:00
Matt Nadareski
54465ff4e7 Move both installers to packers 2021-02-26 09:34:07 -08:00
Matt Nadareski
52eef84374 Make InnoSetup like WiseInstaller 2021-02-26 09:32:41 -08:00
Matt Nadareski
f4310206e9 Add IScannable interface 2021-02-26 09:26:23 -08:00
Matt Nadareski
7cfa9649e4 Add IContentCheck interface 2021-02-26 01:26:49 -08:00
Matt Nadareski
c6eaafebbe Add IPathCheck interface 2021-02-26 00:32:09 -08:00
Matt Nadareski
df1e14b6c9 Rename NOS variant of UPX 2021-02-25 13:38:13 -08:00
Matt Nadareski
ad2d854969 Add versioned NOS check, fix naming 2021-02-25 11:27:08 -08:00
Matt Nadareski
61202a87fb Add UPX detection for odd cases 2021-02-25 11:13:57 -08:00
Matt Nadareski
9ebbeaed0f Make EA CDKey checks more robust 2021-02-23 13:16:25 -08:00
Matt Nadareski
aebc139d52 I lied, keep it separate 2021-02-20 22:13:48 -08:00
Matt Nadareski
0e82eea891 Origin is an EA protection 2021-02-20 22:06:18 -08:00
Matt Nadareski
7ec76acf2f Remove Cucko until more investigation 2021-02-20 13:16:52 -08:00
Matt Nadareski
21f17791ff No... that's not right 2021-02-19 21:26:49 -08:00
Matt Nadareski
fff5f2610a Add Cucko notes 2021-02-19 10:14:02 -08:00
Matt Nadareski
d574fb5e44 Fix link to MPF in README 2021-01-25 09:53:18 -08:00
Matt Nadareski
d8aacbcc5d Treat Wise internally a bit strangely 2021-01-25 09:51:16 -08:00
Matt Nadareski
6467ef97d5 Only scan Wise internals if scanning archives 2021-01-24 21:23:05 -08:00
Matt Nadareski
5ec4872b36 Fix framework string 2021-01-22 11:25:24 -08:00
Matt Nadareski
30bfff833f Bump version to 1.5.1 2021-01-22 11:10:19 -08:00
Matt Nadareski
e37d5a80ab Add .NET 5.0 target framework 2021-01-21 13:17:59 -08:00
Matt Nadareski
df1081507d Thrown exceptions get logged to file in Test 2021-01-21 13:17:34 -08:00
Matt Nadareski
a140e1c444 Fix MPQ extraction (fixes #16) 2021-01-21 11:54:05 -08:00
Matt Nadareski
f9a990b27b Rename this to be more accurate 2020-11-12 22:47:33 -08:00
Matt Nadareski
b841c7aa94 More comments in EVORE for later 2020-11-12 22:40:50 -08:00
Matt Nadareski
554520ae1f Less EVORE code to fail 2020-11-12 22:33:18 -08:00
Matt Nadareski
3155b3fe41 Move EVORE things around 2020-11-12 22:10:45 -08:00
Matt Nadareski
e52cfd244a Little more reorganization 2020-11-12 22:00:50 -08:00
Matt Nadareski
c52b22fb4e Split things out for executables 2020-11-12 21:58:06 -08:00
Matt Nadareski
b3f72bbbe1 Add EVORE note, VSCode stuff 2020-11-12 21:35:43 -08:00
Matt Nadareski
9ebcfdba53 Bump version to 1.5.0 2020-11-03 21:15:36 -08:00
Matt Nadareski
15f020cb06 Fix textfile content scan 2020-11-03 14:57:23 -08:00
Matt Nadareski
4b387f86c1 Hook up MediaMax to scan 2020-11-03 14:47:15 -08:00
Matt Nadareski
1a3a73a86d Add MediaMax CD-3 content detections 2020-11-03 14:41:05 -08:00
Matt Nadareski
31eff196e6 Forgot to fix path in Wise 2020-11-02 15:18:03 -08:00
Matt Nadareski
828d3403f1 Upgrade UnshieldSharp, re-enable ISCab for Core 2020-11-01 23:13:35 -08:00
Matt Nadareski
28d6d06033 Unshield uses zlib.net which isn't .NET Core... 2020-11-01 22:13:46 -08:00
Matt Nadareski
0a2477e1b3 Remove console writes, make LibCrypt read better 2020-11-01 21:53:42 -08:00
Matt Nadareski
01451d7009 A bit of cleanup 2020-11-01 16:01:45 -08:00
Matt Nadareski
cff9582bf5 Comment out one of the 3PLock checks 2020-11-01 14:30:32 -08:00
Matt Nadareski
428d839700 Remove outdated TODOs 2020-11-01 14:18:01 -08:00
Matt Nadareski
50db0044b0 Fix MSCab corner case of trailing periods 2020-11-01 14:06:46 -08:00
SilasLaspada
68b1ec7b3f Fix name of INTENIUM protection (#15)
Change ITENIUM to INTENIUM
2020-11-01 10:45:30 -08:00
Matt Nadareski
fd524e1d5c List archive formats in README 2020-10-31 23:57:02 -07:00
Matt Nadareski
ef581c3f36 Add note for MS-CAB 2020-10-31 23:29:27 -07:00
Matt Nadareski
64e67b8daa Gate non-core compatible includes 2020-10-31 23:17:03 -07:00
Matt Nadareski
8624350b82 Why am I doing this? 2020-10-31 22:44:26 -07:00
Matt Nadareski
e3b32fd974 Clear empty keys as you go 2020-10-31 21:20:16 -07:00
Matt Nadareski
6f789d2454 Fix output of in-archive files 2020-10-31 14:57:47 -07:00
Matt Nadareski
d365dd1164 More consistent naming 2020-10-31 14:48:25 -07:00
Matt Nadareski
aa3afd676b Add option for including packers in scan 2020-10-31 14:46:08 -07:00
Matt Nadareski
69a04ff825 Hook up ITENIUM 2020-10-31 14:43:27 -07:00
Matt Nadareski
938e1f94bb Fix CDCheck message (non-false-positive in XCP) 2020-10-31 14:19:41 -07:00
Matt Nadareski
3eda785a5a Skip files with no protection on output 2020-10-31 14:16:51 -07:00
Matt Nadareski
6b895fa7c8 Fix invalid UPX packing versions 2020-10-31 14:15:33 -07:00
Matt Nadareski
45e10a84ae Strip temp paths, add archive name as prefix 2020-10-31 14:14:35 -07:00
Matt Nadareski
81f0400790 Pass-thru scanner, better return types 2020-10-31 14:00:31 -07:00
Matt Nadareski
df90583f73 Scanner shouldn't include path intrinsically 2020-10-31 13:20:54 -07:00
Matt Nadareski
5b980e138a Add scanner to all archive signatures (nw) 2020-10-31 00:06:41 -07:00
Matt Nadareski
0dd71d72ca Add new, but unused, Scanner class 2020-10-30 23:56:27 -07:00
Matt Nadareski
a7364eab67 Comments and a better guard 2020-10-30 21:43:40 -07:00
Matt Nadareski
99013e3448 Separate out archive and non-archive in code 2020-10-30 21:14:07 -07:00
Matt Nadareski
7f5e93db95 Fix 3PLock scanning finally 2020-10-30 17:02:58 -07:00
Matt Nadareski
4aa9662ebe Update README 2020-10-30 09:16:16 -07:00
Matt Nadareski
68dc6c3139 Region-ize the executable scans 2020-10-30 09:11:17 -07:00
Matt Nadareski
8b99577c66 New namespace for packers 2020-10-30 09:09:16 -07:00
Matt Nadareski
20ea1b4427 Fix formatting 2020-10-30 09:02:48 -07:00
SilasLaspada
cf0c6126b9 Add support for detecting NSIS (#14) 2020-10-30 08:56:34 -07:00
Matt Nadareski
49eef3f45a Update README with changes 2020-10-29 11:07:00 -07:00
Matt Nadareski
23e852bbdb Add first ITENIUM check, not hooked up 2020-10-29 11:01:52 -07:00
Matt Nadareski
f182dccbf2 21 -> 321, add a couple protection notes 2020-10-29 10:05:56 -07:00
Matt Nadareski
2d2cff4d0e Add MSI extraction and scanning 2020-10-28 22:51:33 -07:00
Matt Nadareski
c0621a83cb Enable 21Studios scan 2020-10-28 22:51:14 -07:00
Matt Nadareski
3c5da9f7ec Add 21Studios activator detection 2020-10-28 22:49:55 -07:00
Matt Nadareski
a7b5288277 One more EA CDKey detection 2020-10-28 21:03:45 -07:00
Matt Nadareski
fee980e048 CD Check has a valid case again 2020-10-28 16:33:20 -07:00
Matt Nadareski
21eac43e9f Remove unused vars 2020-10-28 13:31:15 -07:00
Matt Nadareski
b55698004c Make it blindingly obvious the files are from an archive 2020-10-28 13:25:58 -07:00
Matt Nadareski
40bdb9b2d9 Use 'i+1' during progress 2020-10-28 13:21:42 -07:00
Matt Nadareski
dfabb1a244 Strip out temp paths from results and progress 2020-10-28 13:17:26 -07:00
Matt Nadareski
cd5f9561bf Pre-scan progress indicator 2020-10-28 13:06:45 -07:00
Matt Nadareski
d8d6fac67e Fix issue with libmspack4n, again 2020-10-28 12:34:33 -07:00
Matt Nadareski
965c32482d Remove note 2020-10-28 12:24:04 -07:00
Matt Nadareski
c8c9d4ac64 Scan whole path for Wise 2020-10-28 12:23:25 -07:00
Matt Nadareski
5f5abf8a14 Scan whole path for Valve 2020-10-28 12:22:29 -07:00
Matt Nadareski
406791b938 Scan whole path for TAP 2020-10-28 12:21:59 -07:00
Matt Nadareski
eb2e6e7029 Scan whole path for 7zip 2020-10-28 12:21:44 -07:00
Matt Nadareski
9f0b41c6aa Scan whole path for RAR 2020-10-28 12:21:26 -07:00
Matt Nadareski
e2b72d8a5b Scan whole folder for PKZIP 2020-10-28 12:20:55 -07:00
Matt Nadareski
9802840309 Scan whole folder for MPQ 2020-10-28 12:20:36 -07:00
Matt Nadareski
4a6e2fd62d Scan whole folder for MSCab 2020-10-28 12:20:07 -07:00
Matt Nadareski
79c706e35a Scan whole folder for ISCab 2020-10-28 12:19:10 -07:00
Matt Nadareski
9be19d6925 Scan whole folder for BFPK 2020-10-28 12:17:10 -07:00
Matt Nadareski
0cfb9907d0 Make archives use full scan, not just content 2020-10-28 12:05:48 -07:00
Matt Nadareski
c18e9b3538 Combine EA protection checks, add/fix reg checks 2020-10-28 11:13:26 -07:00
Matt Nadareski
3754c3a65b Ensure mspack.dll exists for libmspack4n 2020-10-28 10:49:24 -07:00
Matt Nadareski
513a64df4c Rename Cucko and cleanup misc 2020-10-28 10:42:54 -07:00
Matt Nadareski
d18a51c7fa Add SolidShield wrapper check 2020-10-28 10:23:57 -07:00
Matt Nadareski
b43433b9ed Add more EA protection checks 2020-10-28 10:10:43 -07:00
Matt Nadareski
d553395f3f Reorder CDS path checks, change one to fit code 2020-10-27 17:13:35 -07:00
Matt Nadareski
28dbe8542b Add CDS content checks, fix XCP over-detection 2020-10-27 17:01:33 -07:00
Matt Nadareski
912e605dc8 Clarify SafeDisc version identifiers 2020-10-27 14:47:02 -07:00
Matt Nadareski
039982d02d Cleanup on Cactus for future dev work 2020-10-27 14:37:14 -07:00
Matt Nadareski
1a40c6cbb2 SafeDisc... one OR greater 2020-10-27 13:35:57 -07:00
Matt Nadareski
35921e3cac Be smarter about SecuROM strings 2020-10-26 23:30:35 -07:00
Matt Nadareski
a42040d644 Add UPX checking 2020-10-26 23:30:06 -07:00
Matt Nadareski
e1fb1c7bcf Minor renaming 2020-10-26 22:22:46 -07:00
Matt Nadareski
095de1441d Add XCP content checks (thanks to Silas) 2020-10-26 21:08:39 -07:00
Matt Nadareski
43cbafc0f5 Add better detection for XCP2 2020-10-26 20:34:47 -07:00
Matt Nadareski
9143e4c02c Disable CD Check in source due to false positives 2020-10-09 23:12:11 -07:00
Matt Nadareski
2af0692ab4 Update libraries, fix deps, bump to 1.04.1 2020-09-30 23:19:50 -07:00
Matt Nadareski
e00c8786b9 Update version to 1.4.0 2020-09-10 22:32:00 -07:00
Matt Nadareski
ab6298ac67 Include all builds for Test 2020-09-10 21:59:50 -07:00
Matt Nadareski
aaad56794b Fix odd case for secdrv.sys (fixes #8) 2020-09-10 21:50:59 -07:00
Matt Nadareski
77d99460ab Fix exception in EVORE (fixes #9) 2020-09-10 21:49:46 -07:00
Matt Nadareski
4b222003d2 Minor cleanup 2020-09-10 21:47:14 -07:00
Matt Nadareski
517d5528c9 Remove .NET Framework 4.6.2 2020-09-10 21:44:42 -07:00
Matt Nadareski
0c137e97f0 Make protection location optional (default off) 2020-09-10 21:43:18 -07:00
Matt Nadareski
c4f8fa4b0d Location, Location, Location (#11)
* Add index to all content checks

* Get mostly onto byte arrays

* Migrate as much as possible to byte array

* Minor cleanup

* Cleanup comments, fix search

* Safer CABs and auto-log on test

* Comments and better SecuROM

* Cleanup, Wise Detection, archives

* Minor fixes

* Add externals, cleanup README

* Add WiseUnpacker

* Add Wise extraction

* Better separation of special file format handling

* Consistent licencing

* Add to README

* Fix StartsWith

* Fix Valve scanning

* Fix build

* Remove old TODO

* Fix BFPK extraction

* More free decompression formats

* Fix EVORE

* Fix LibCrypt detection

* Fix EVORE deletion
2020-09-10 21:10:32 -07:00
Matt Nadareski
0bc1d1efa6 CheckPath should not call CheckContents 2020-02-20 14:28:26 -08:00
Matt Nadareski
c78229c3cd Use Any() instead of Count() > 0 2020-02-20 14:23:39 -08:00
Matt Nadareski
aa41cb9edf Clean up some of the psxt001z code (fixes #6) 2020-02-18 13:54:39 -08:00
Matt Nadareski
11f1fec53c Update copyright 2020-01-29 11:32:05 -08:00
Matt Nadareski
249064580a Sync nuspec and assembly info 2020-01-29 11:31:44 -08:00
Matt Nadareski
72d29aabd2 Update version and add to README 2020-01-29 11:30:22 -08:00
Matt Nadareski
18a17d2579 Port LibCrypt sub detection from psxt001z 2020-01-29 11:28:03 -08:00
Matt Nadareski
4e664cbe0f Add *nix and Mac executable headers to checking 2019-10-30 12:06:40 -07:00
Matt Nadareski
99f4909e9b Missing or moved files shouldn't cause an issue (#5) 2019-10-25 23:25:30 -04:00
Matt Nadareski
482644af85 Fix Memory Issues (#4)
* Fix a couple of protection scans (possible mem issues)

* Don't open the file contents on path scan for antimodchip

* IS-CAB intermediate filtering to reduce scan times

* Update NuGet version
2019-10-24 16:09:43 -04:00
Matt Nadareski
45661f3ccd Merge pull request #2 from mnadareski/reorg
Reorganization and Update
2019-09-30 20:39:49 -07:00
Matt Nadareski
c7a9485bf3 Update all 2019-09-30 20:08:12 -07:00
Matt Nadareski
9422ba01e7 Remove backups 2019-09-30 12:17:15 -07:00
Matt Nadareski
b8bbc0b333 Update packages 2019-09-30 12:10:32 -07:00
Matt Nadareski
44922a1f6b Fix encoding issue, add note 2019-09-30 12:09:03 -07:00
Matt Nadareski
cfcb608990 Update all to 4.7.2 2019-09-30 11:46:53 -07:00
Matt Nadareski
392f9dae0c Fix build 2019-09-30 11:29:38 -07:00
Matt Nadareski
4b1cae2ba2 Filename is no longer expected 2019-09-30 11:08:44 -07:00
Matt Nadareski
fd866465b4 Fix test program output 2019-09-29 12:08:31 -07:00
Matt Nadareski
5ffaedc024 Keep path scanning on individual files, for now 2019-09-29 11:57:46 -07:00
Matt Nadareski
ca0d695470 Else-If causes some issues 2019-09-28 01:51:06 -07:00
Matt Nadareski
c109aceb24 Update nuspec 2019-09-28 00:05:44 -07:00
Matt Nadareski
2938033fa6 Remove unused class 2019-09-28 00:01:22 -07:00
Matt Nadareski
5a2755d7c7 Consistent comments 2019-09-27 23:57:32 -07:00
Matt Nadareski
550086791b Separate protections into their own classes 2019-09-27 23:52:24 -07:00
Matt Nadareski
9e4836826d Fix "FileProtection" callback, add InnoSetup
The InnoSetup placeholder here will eventually be a way to call to an external library to extract the contents of the installer, similar to how CAB files are handled right now. The code to o so need sto be converted before that can happen, so in the meantime, this adds Inno Steup itself as a "protection" since other protections could be hidden within.
2018-07-22 23:48:44 -07:00
Matt Nadareski
e0d0722e2b Update csproj 2018-07-22 23:47:08 -07:00
Matt Nadareski
b4c5b220ef Progress => FileProtection
This also implements a sample usage in the Test program
2018-07-22 23:46:49 -07:00
Matt Nadareski
413652f92a Add AppVeyor badge 2018-07-19 14:42:18 -07:00
Matt Nadareski
0cf2b0f6d2 Better cabinet handling, update version 2018-07-19 10:12:38 -07:00
Matt Nadareski
a3094ef471 Add antimod detection (2/3) 2018-07-18 12:06:25 -07:00
Matt Nadareski
055fcbbde7 Update to 1.3.8 2018-07-18 10:57:33 -07:00
Matt Nadareski
a2e00e3945 Better progress indicator 2018-07-18 10:38:41 -07:00
Matt Nadareski
7338640635 Add optional progress indicator callback 2018-07-18 10:11:49 -07:00
Matt Nadareski
99d4adee75 Update version 2018-07-17 10:25:41 -07:00
Matt Nadareski
3356854215 Public documentation 2018-07-16 17:28:47 -07:00
Matt Nadareski
0d04a1b20e Files are valid too 2018-07-16 17:25:36 -07:00
Matt Nadareski
8723639ebc Add simple program for functionality testing 2018-07-16 17:10:45 -07:00
Matt Nadareski
e4df323266 EVORE should not be public 2018-07-16 17:06:16 -07:00
Matt Nadareski
43990dfddb Update README.md 2018-07-16 16:47:52 -07:00
Matt Nadareski
dad04915d4 Fixes for SolidShield and TAGES 2018-07-16 16:27:21 -07:00
Matt Nadareski
959a8d4dc2 CopyKiller check is in error 2018-07-16 14:44:35 -07:00
Matt Nadareski
d6d223946f Add list of known-missing protections 2018-07-16 14:38:17 -07:00
Matt Nadareski
426bc94725 Add nuspec 2018-07-16 02:27:52 -07:00
Matt Nadareski
9728bff8c8 Use the NuGet package 2018-07-16 02:16:55 -07:00
Matt Nadareski
afe72d4083 Add UnshieldSharp as a submodule 2018-07-16 00:58:28 -07:00
Matt Nadareski
d266c7dd20 Initial commit forked from DICUI
This will rely on UnshieldSharp, so it is not currently buildable
2018-07-16 00:45:29 -07:00
171 changed files with 12856 additions and 69 deletions

63
.gitattributes vendored Normal file
View File

@@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

15
.gitmodules vendored Normal file
View File

@@ -0,0 +1,15 @@
[submodule "BurnOutSharp/External/LessIO"]
path = BurnOutSharp/External/LessIO
url = https://github.com/activescott/LessIO.git
[submodule "BurnOutSharp/External/libmspack4n"]
path = BurnOutSharp/External/libmspack4n
url = https://github.com/activescott/libmspack4n.git
[submodule "BurnOutSharp/External/hllib"]
path = BurnOutSharp/External/hllib
url = https://github.com/RavuAlHemio/hllib.git
[submodule "BurnOutSharp/External/stormlibsharp"]
path = BurnOutSharp/External/stormlibsharp
url = https://github.com/robpaveza/stormlibsharp.git
[submodule "BurnOutSharp/External/WixToolset"]
path = BurnOutSharp/External/WixToolset
url = https://github.com/wixtoolset/Dtf.git

27
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,27 @@
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/Test/bin/Debug/netcoreapp3.1/Test.dll",
"args": [],
"cwd": "${workspaceFolder}/Test",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}"
}
]
}

42
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,42 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/Test/Test.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/Test/Test.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"${workspaceFolder}/Test/Test.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}

37
BurnOutSharp.sln Normal file
View File

@@ -0,0 +1,37 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29306.81
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}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{68D10531-99CB-40B1-8912-73FA286C9433}"
ProjectSection(SolutionItems) = preProject
LICENSE = LICENSE
README.md = README.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1DA4212E-6071-4951-B45D-BB74A7838246}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1DA4212E-6071-4951-B45D-BB74A7838246}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1DA4212E-6071-4951-B45D-BB74A7838246}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1DA4212E-6071-4951-B45D-BB74A7838246}.Release|Any CPU.Build.0 = Release|Any CPU
{88735BA2-778D-4192-8EB2-FFF6843719E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0B343DD2-8852-47B0-9647-DFCFBEDF933C}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,64 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net48;netcoreapp3.1;net5.0</TargetFrameworks>
<PlatformTarget>x86</PlatformTarget>
<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>
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
<RepositoryUrl>https://github.com/mnadareski/BurnOutSharp</RepositoryUrl>
<Version>1.6.1</Version>
<AssemblyVersion>1.6.1</AssemblyVersion>
<FileVersion>1.6.1</FileVersion>
<IncludeSource>true</IncludeSource>
<IncludeSymbols>true</IncludeSymbols>
</PropertyGroup>
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SharpCompress" Version="0.28.1" />
<PackageReference Include="UnshieldSharp" Version="1.5.0" />
<PackageReference Include="WiseUnpacker" Version="1.0.2" />
</ItemGroup>
<!-- These are needed for dealing with submodules -->
<PropertyGroup>
<DefaultItemExcludes>
$(DefaultItemExcludes);
**\AssemblyInfo.cs;
External\hllib\HLExtract\**\*;
External\hllib\HLExtract.Net\Program.cs;
External\hllib\HLLib\**\*;
External\LessIO\src\LessIO.Tests\**\*;
External\libmspack4n\lib\**\*;
External\libmspack4n\libmspack4ntest\**\*;
External\stormlibsharp\lib\**;
External\stormlibsharp\TestConsole\**;
External\WixToolset\src\Samples\**;
External\WixToolset\src\Tools\**;
External\WixToolset\src\WixToolset.Dtf.MSBuild\**;
External\WixToolset\src\WixToolset.Dtf.Resources\**;
External\WixToolset\src\WixToolsetTests.*\**
</DefaultItemExcludes>
</PropertyGroup>
<ItemGroup>
<None Include="LICENSE.txt" Pack="true" PackagePath="$(PackageLicenseFile)" />
</ItemGroup>
<ItemGroup>
<None Include="*.dll" Pack="true">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
<PackageCopyToOutput>true</PackageCopyToOutput>
</None>
</ItemGroup>
</Project>

BIN
BurnOutSharp/CascLib.dll Normal file

Binary file not shown.

245
BurnOutSharp/EVORE.cs Normal file
View File

@@ -0,0 +1,245 @@
//this file is part of BurnOut
//Copyright (C)2005-2010 Gernot Knippen
//Ported code with augments Copyright (C)2018 Matt Nadareski
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You can get a copy of the GNU General Public License
//by writing to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using BurnOutSharp.ExecutableType.Microsoft;
namespace BurnOutSharp
{
internal static class EVORE
{
/// <summary>
/// Checks if the file contents that represent a PE is a DLL or an EXE
/// </summary>
/// <param name="fileContent">File contents to check</param>
/// <returns>True if the file is an EXE, false if it's a DLL</returns>
internal static bool IsEXE(byte[] fileContent)
{
int PEHeaderOffset = BitConverter.ToInt32(fileContent, 60);
short Characteristics = BitConverter.ToInt16(fileContent, PEHeaderOffset + 22);
// Check if file is dll
return (Characteristics & 0x2000) != 0x2000;
}
/// <summary>
/// Writes the file contents to a temporary file, if possible
/// </summary>
/// <param name="fileContent">File contents to write</param>
/// <param name="sExtension">Optional extension for the temproary file, defaults to ".exe"</param>
/// <returns>Name of the new temporary file, null on error</returns>
internal static string MakeTempFile(byte[] fileContent, string sExtension = ".exe")
{
string filei = Guid.NewGuid().ToString();
string tempPath = Path.Combine(Path.GetTempPath(), "tmp", $"{filei}{sExtension}");
try
{
File.Delete(tempPath);
}
catch { }
try
{
Directory.CreateDirectory(Path.GetDirectoryName(tempPath));
using (BinaryWriter bw = new BinaryWriter(File.OpenWrite(tempPath)))
{
bw.Write(fileContent);
}
return Path.GetFullPath(tempPath);
}
catch { }
return null;
}
/// <summary>
/// Copies all required DLLs for a given executable
/// </summary>
/// <param name="file">Temporary file path</param>
/// <param name="fileContent">File contents to read</param>
/// <returns>Paths for all of the copied DLLs, null on error</returns>
internal static string[] CopyDependentDlls(string file, byte[] fileContent)
{
var sections = ReadSections(fileContent);
long lastPosition;
string[] saDependentDLLs = null;
int index = 60;
int PEHeaderOffset = BitConverter.ToInt32(fileContent, index);
index = PEHeaderOffset + 120 + 8; //120 Bytes till IMAGE_DATA_DIRECTORY array,8 Bytes=size of IMAGE_DATA_DIRECTORY
uint ImportTableRVA = BitConverter.ToUInt32(fileContent, index);
index += 4;
uint ImportTableSize = BitConverter.ToUInt32(fileContent, index);
index = (int)RVA2Offset(ImportTableRVA, sections);
index += 12;
uint DllNameRVA = BitConverter.ToUInt32(fileContent, index);
index += 4;
while (DllNameRVA != 0)
{
string sDllName = "";
byte bChar;
lastPosition = index;
uint DLLNameOffset = RVA2Offset(DllNameRVA, sections);
if (DLLNameOffset > 0)
{
index = (int)DLLNameOffset;
if ((char)fileContent[index] > -1)
{
do
{
bChar = fileContent[index];
index++;
sDllName += (char)bChar;
} while (bChar != 0 && (char)fileContent[index] > -1);
sDllName = sDllName.Remove(sDllName.Length - 1, 1);
if (File.Exists(Path.Combine(Path.GetDirectoryName(file), sDllName)))
{
if (saDependentDLLs == null)
saDependentDLLs = new string[0];
else
saDependentDLLs = new string[saDependentDLLs.Length];
FileInfo fiDLL = new FileInfo(Path.Combine(Path.GetDirectoryName(file), sDllName));
saDependentDLLs[saDependentDLLs.Length - 1] = fiDLL.CopyTo(Path.GetTempPath() + sDllName, true).FullName;
}
}
index = (int)lastPosition;
}
index += 4 + 12;
DllNameRVA = BitConverter.ToUInt32(fileContent, index);
index += 4;
}
return saDependentDLLs;
}
/// <summary>
/// Attempt to run an executable
/// </summary>
/// <param name="file">Executable to attempt to run</param>
/// <returns>Process representing the running executable, null on error</returns>
internal static Process StartSafe(string file)
{
if (file == null || !File.Exists(file))
return null;
Process startingprocess = new Process();
startingprocess.StartInfo.FileName = file;
startingprocess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
startingprocess.StartInfo.CreateNoWindow = true;
startingprocess.StartInfo.ErrorDialog = false;
try
{
startingprocess.Start();
}
catch
{
return null;
}
return startingprocess;
}
private static IMAGE_SECTION_HEADER[] ReadSections(byte[] fileContent)
{
if (fileContent == null)
return null;
uint PEHeaderOffset = BitConverter.ToUInt32(fileContent, 60);
ushort NumberOfSections = BitConverter.ToUInt16(fileContent, (int)PEHeaderOffset + 6);
var sections = new IMAGE_SECTION_HEADER[NumberOfSections];
int index = (int)PEHeaderOffset + 120 + 16 * 8;
for (int i = 0; i < NumberOfSections; i++)
{
sections[i] = ReadSection(fileContent, index);
}
return sections;
}
private static IMAGE_SECTION_HEADER ReadSection(byte[] fileContent, int ptr)
{
try
{
// Get the size of a section header for later
int sectionSize = Marshal.SizeOf<IMAGE_SECTION_HEADER>();
// If the contents are null or the wrong size, we can't read a section
if (fileContent == null || fileContent.Length < sectionSize)
return null;
// Create a new section and try our best to read one
IMAGE_SECTION_HEADER section = null;
IntPtr tempPtr = IntPtr.Zero;
try
{
// Get the pointer to where the section will go
tempPtr = Marshal.AllocHGlobal(sectionSize);
// If we couldn't get the space, just return null
if (tempPtr == IntPtr.Zero)
return null;
// Copy from the array to the new space
Marshal.Copy(fileContent, ptr, tempPtr, sectionSize);
// Get the new section and return
section = Marshal.PtrToStructure<IMAGE_SECTION_HEADER>(tempPtr);
}
catch
{
// We don't care what the error was
return null;
}
finally
{
if (tempPtr != IntPtr.Zero)
Marshal.FreeHGlobal(tempPtr);
}
return section;
}
catch
{
return null;
}
}
private static uint RVA2Offset(uint RVA, IMAGE_SECTION_HEADER[] sections)
{
for (int i = 0; i < sections.Length; i++)
{
if (sections[i] == null)
continue;
var section = sections[i];
if (section.VirtualAddress <= RVA && section.VirtualAddress + section.PhysicalAddress > RVA)
return RVA - section.VirtualAddress + section.PointerToRawData;
}
return 0;
}
}
}

View File

@@ -0,0 +1,99 @@
namespace BurnOutSharp.ExecutableType.Microsoft
{
/// <summary>
/// All constant values needed for file header reading
/// </summary>
internal static class Constants
{
public const ushort IMAGE_DOS_SIGNATURE = 0x5A4D; // MZ
public const ushort IMAGE_OS2_SIGNATURE = 0x454E; // NE
public const ushort IMAGE_OS2_SIGNATURE_LE = 0x454C; // LE
public const uint IMAGE_NT_SIGNATURE = 0x00004550; // PE00
#region IMAGE_DOS_HEADER
public const ushort ENEWEXE = 0x40; // Value of E_LFARLC for new .EXEs
public const ushort ENEWHDR = 0x003C; // Offset in old hdr. of ptr. to new
public const ushort ERESWDS = 0x0010; // No. of reserved words (OLD)
public const ushort ERES1WDS = 0x0004; // No. of reserved words in e_res
public const ushort ERES2WDS = 0x000A; // No. of reserved words in e_res2
public const ushort ECP = 0x0004; // Offset in struct of E_CP
public const ushort ECBLP = 0x0002; // Offset in struct of E_CBLP
public const ushort EMINALLOC = 0x000A; // Offset in struct of E_MINALLOC
#endregion
#region IMAGE_OS2_HEADER
public const ushort NERESWORDS = 3; // 6 bytes reserved
public const ushort NECRC = 8; //Offset into new header of NE_CRC
#endregion
#region NewSeg
public const ushort NSALIGN = 9; // Segment data aligned on 512 byte boundaries
public const ushort NSLOADED = 0x0004; // ns_sector field contains memory addr
#endregion
#region RsrcNameInfo
public const ushort RSORDID = 0x8000; /* if high bit of ID set then integer id */
/* otherwise ID is offset of string from
the beginning of the resource table */
/* Ideally these are the same as the */
/* corresponding segment flags */
public const ushort RNMOVE = 0x0010; /* Moveable resource */
public const ushort RNPURE = 0x0020; /* Pure (read-only) resource */
public const ushort RNPRELOAD = 0x0040; /* Preloaded resource */
public const ushort RNDISCARD = 0xF000; /* Discard priority level for resource */
#endregion
#region IMAGE_OPTIONAL_HEADER
public const ushort IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
/* Directory Entries */
/* Export Directory */
public const byte IMAGE_DIRECTORY_ENTRY_EXPORT = 0;
/* Import Directory */
public const byte IMAGE_DIRECTORY_ENTRY_IMPORT = 1;
/* Resource Directory */
public const byte IMAGE_DIRECTORY_ENTRY_RESOURCE = 2;
/* Exception Directory */
public const byte IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3;
/* Security Directory */
public const byte IMAGE_DIRECTORY_ENTRY_SECURITY = 4;
/* Base Relocation Table */
public const byte IMAGE_DIRECTORY_ENTRY_BASERELOC = 5;
/* Debug Directory */
public const byte IMAGE_DIRECTORY_ENTRY_DEBUG = 6;
/* Description String */
public const byte IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7;
/* Machine Value (MIPS GP) */
public const byte IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8;
/* TLS Directory */
public const byte IMAGE_DIRECTORY_ENTRY_TLS = 9;
/* Load Configuration Directory */
public const byte IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10;
#endregion
#region IMAGE_SECTION_HEADER
public const int IMAGE_SIZEOF_SHORT_NAME = 8;
#endregion
#region IMAGE_RESOURCE_DATA_ENTRY
public const uint IMAGE_RESOURCE_DATA_IS_DIRECTORY = 0x80000000;
public const uint IMAGE_RESOURCE_NAME_IS_STRING = 0x80000000;
#endregion
}
}

View File

@@ -0,0 +1,384 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System;
namespace BurnOutSharp.ExecutableType.Microsoft
{
internal enum ExecutableType
{
Unknown,
NE,
PE,
}
/// <summary>
/// Format of NE_FLAGS(x):
///
/// p Not-a-process
/// x Unused
/// e Errors in image
/// x Unused
/// b Bound as family app
/// ttt Application type
/// f Floating-point instructions
/// 3 386 instructions
/// 2 286 instructions
/// 0 8086 instructions
/// P Protected mode only
/// p Per-process library initialization
/// i Instance data
/// s Solo data
/// </summary>
[Flags]
internal enum NeFlags : ushort
{
/// <summary>
/// Not a process
/// </summary>
NENOTP = 0x8000,
/// <summary>
/// Errors in image
/// </summary>
NEIERR = 0x2000,
/// <summary>
/// Bound as family app
/// </summary>
NEBOUND = 0x0800,
/// <summary>
/// Application type mask
/// </summary>
NEAPPTYP = 0x0700,
/// <summary>
/// Not compatible with P.M. Windowing
/// </summary>
NENOTWINCOMPAT = 0x0100,
/// <summary>
/// Compatible with P.M. Windowing
/// </summary>
NEWINCOMPAT = 0x0200,
/// <summary>
/// Uses P.M. Windowing API
/// </summary>
NEWINAPI = 0x0300,
/// <summary>
/// Floating-point instructions
/// </summary>
NEFLTP = 0x0080,
/// <summary>
/// 386 instructions
/// </summary>
NEI386 = 0x0040,
/// <summary>
/// 286 instructions
/// </summary>
NEI286 = 0x0020,
/// <summary>
/// 8086 instructions
/// </summary>
NEI086 = 0x0010,
/// <summary>
/// Runs in protected mode only
/// </summary>
NEPROT = 0x0008,
/// <summary>
/// Per-Process Library Initialization
/// </summary>
NEPPLI = 0x0004,
/// <summary>
/// Instance data
/// </summary>
NEINST = 0x0002,
/// <summary>
/// Solo data
/// </summary>
NESOLO = 0x0001,
}
/// <summary>
/// Format of NR_FLAGS(x):
///
/// xxxxx Unused
/// a Additive fixup
/// rr Reference type
/// </summary>
[Flags]
internal enum NrFlags : byte
{
/// <summary>
/// Additive fixup
/// </summary>
NRADD = 0x04,
/// <summary>
/// Reference type mask
/// </summary>
NRRTYP = 0x03,
/// <summary>
/// Internal reference
/// </summary>
NRRINT = 0x00,
/// <summary>
/// Import by ordinal
/// </summary>
NRRORD = 0x01,
/// <summary>
/// Import by name
/// </summary>
NRRNAM = 0x02,
/// <summary>
/// Operating system fixup
/// </summary>
NRROSF = 0x03,
}
/// <summary>
/// Format of NR_STYPE(x):
///
/// xxxxx Unused
/// sss Source type
////
/// </summary>
[Flags]
internal enum NrStype : byte
{
/// <summary>
/// Source type mask
/// </summary>
NRSTYP = 0x0f,
/// <summary>
/// lo byte
/// </summary>
NRSBYT = 0x00,
/// <summary>
/// 16-bit segment
/// </summary>
NRSSEG = 0x02,
/// <summary>
/// 32-bit pointer
/// </summary>
NRSPTR = 0x03,
/// <summary>
/// 16-bit offset
/// </summary>
NRSOFF = 0x05,
/// <summary>
/// 48-bit pointer
/// </summary>
NRSPTR48 = 0x0B,
/// <summary>
/// 32-bit offset
/// </summary>
NRSOFF32 = 0x0D,
}
/// <summary>
/// Format of NS_FLAGS(x)
///
/// x Unused
/// h Huge segment
/// c 32-bit code segment
/// d Discardable segment
/// DD I/O privilege level (286 DPL bits)
/// c Conforming segment
/// r Segment has relocations
/// e Execute/read only
/// p Preload segment
/// P Pure segment
/// m Movable segment
/// i Iterated segment
/// ttt Segment type
/// </summary>
[Flags]
internal enum NsFlags : ushort
{
/// <summary>
/// Segment type mask
/// </summary>
NSTYPE = 0x0007,
/// <summary>
/// Code segment
/// </summary>
NSCODE = 0x0000,
/// <summary>
/// Data segment
/// </summary>
NSDATA = 0x0001,
/// <summary>
/// Iterated segment flag
/// </summary>
NSITER = 0x0008,
/// <summary>
/// Movable segment flag
/// </summary>
NSMOVE = 0x0010,
/// <summary>
/// Shared segment flag
/// </summary>
NSSHARED = 0x0020,
/// <summary>
/// For compatibility
/// </summary>
NSPURE = 0x0020,
/// <summary>
/// Preload segment flag
/// </summary>
NSPRELOAD = 0x0040,
/// <summary>
/// Execute-only (code segment), or read-only (data segment)
/// </summary>
NSEXRD = 0x0080,
/// <summary>
/// Segment has relocations
/// </summary>
NSRELOC = 0x0100,
/// <summary>
/// Conforming segment
/// </summary>
NSCONFORM = 0x0200,
/// <summary>
/// I/O privilege level (286 DPL bits)
/// </summary>
NSDPL = 0x0C00,
/// <summary>
/// Left shift count for SEGDPL field
/// </summary>
SHIFTDPL = 10,
/// <summary>
/// Segment is discardable
/// </summary>
NSDISCARD = 0x1000,
/// <summary>
/// 32-bit code segment
/// </summary>
NS32BIT = 0x2000,
/// <summary>
/// Huge memory segment, length of segment and minimum allocation size are in segment sector units
/// </summary>
NSHUGE = 0x4000,
}
/// <summary>
/// Predefined Resource Types
/// </summary>
internal enum ResourceTypes : ushort
{
RT_CURSOR = 1,
RT_BITMAP = 2,
RT_ICON = 3,
RT_MENU = 4,
RT_DIALOG = 5,
RT_STRING = 6,
RT_FONTDIR = 7,
RT_FONT = 8,
RT_ACCELERATOR = 9,
RT_RCDATA = 10,
RT_MESSAGELIST = 11, // RT_MESSAGETABLE
RT_GROUP_CURSOR = 12,
RT_RESERVED_1 = 13, // Undefined
RT_GROUP_ICON = 14,
RT_RESERVED_2 = 15, // Undefined
RT_VERSION = 16,
RT_DLGINCLUDE = 17,
RT_PLUGPLAY = 19,
RT_VXD = 20,
RT_ANICURSOR = 21,
RT_NEWRESOURCE = 0x2000,
RT_NEWBITMAP = (RT_BITMAP |RT_NEWRESOURCE),
RT_NEWMENU = (RT_MENU |RT_NEWRESOURCE),
RT_NEWDIALOG = (RT_DIALOG |RT_NEWRESOURCE),
RT_ERROR = 0x7fff,
}
[Flags]
internal enum SectionCharacteristics : uint
{
CodeSection = 0x00000020,
InitializedDataSection = 0x00000040,
UninitializedDataSection = 0x00000080,
SectionCannotBeCached = 0x04000000,
SectionIsNotPageable = 0x08000000,
SectionIsShared = 0x10000000,
ExecutableSection = 0x20000000,
ReadableSection = 0x40000000,
WritableSection = 0x80000000,
}
[Flags]
internal enum TargetOperatingSystems : byte
{
/// <summary>
/// Unknown (any "new-format" OS)
/// </summary>
NE_UNKNOWN = 0x0,
/// <summary>
/// Microsoft/IBM OS/2 (default)
/// </summary>
NE_OS2 = 0x1,
/// <summary>
/// Microsoft Windows
/// </summary>
NE_WINDOWS = 0x2,
/// <summary>
/// Microsoft MS-DOS 4.x
/// </summary>
NE_DOS4 = 0x3,
/// <summary>
/// Windows 386
/// </summary>
NE_WIN386 = 0x4,
}
}

View File

@@ -0,0 +1,34 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
[StructLayout(LayoutKind.Sequential)]
internal class IMAGE_DATA_DIRECTORY
{
public uint VirtualAddress;
public uint Size;
public static IMAGE_DATA_DIRECTORY Deserialize(Stream stream)
{
var idd = new IMAGE_DATA_DIRECTORY();
idd.VirtualAddress = stream.ReadUInt32();
idd.Size = stream.ReadUInt32();
return idd;
}
}
}

View File

@@ -0,0 +1,81 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
/// <summary>
/// DOS 1, 2, 3 .EXE header
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal class IMAGE_DOS_HEADER
{
public ushort Magic; // 00 Magic number
public ushort LastPageBytes; // 02 Bytes on last page of file
public ushort Pages; // 04 Pages in file
public ushort Relocations; // 06 Relocations
public ushort HeaderParagraphSize; // 08 Size of header in paragraphs
public ushort MinimumExtraParagraphs; // 0A Minimum extra paragraphs needed
public ushort MaximumExtraParagraphs; // 0C Maximum extra paragraphs needed
public ushort InitialSSValue; // 0E Initial (relative) SS value
public ushort InitialSPValue; // 10 Initial SP value
public ushort Checksum; // 12 Checksum
public ushort InitialIPValue; // 14 Initial IP value
public ushort InitialCSValue; // 16 Initial (relative) CS value
public ushort RelocationTableAddr; // 18 File address of relocation table
public ushort OverlayNumber; // 1A Overlay number
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.ERES1WDS)]
public ushort[] Reserved1; // 1C Reserved words
public ushort OEMIdentifier; // 24 OEM identifier (for e_oeminfo)
public ushort OEMInformation; // 26 OEM information; e_oemid specific
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.ERES2WDS)]
public ushort[] Reserved2; // 28 Reserved words
public int NewExeHeaderAddr; // 3C File address of new exe header
public static IMAGE_DOS_HEADER Deserialize(Stream stream)
{
IMAGE_DOS_HEADER idh = new IMAGE_DOS_HEADER();
idh.Magic = stream.ReadUInt16();
idh.LastPageBytes = stream.ReadUInt16();
idh.Pages = stream.ReadUInt16();
idh.Relocations = stream.ReadUInt16();
idh.HeaderParagraphSize = stream.ReadUInt16();
idh.MinimumExtraParagraphs = stream.ReadUInt16();
idh.MaximumExtraParagraphs = stream.ReadUInt16();
idh.InitialSSValue = stream.ReadUInt16();
idh.InitialSPValue = stream.ReadUInt16();
idh.Checksum = stream.ReadUInt16();
idh.InitialIPValue = stream.ReadUInt16();
idh.InitialCSValue = stream.ReadUInt16();
idh.RelocationTableAddr = stream.ReadUInt16();
idh.OverlayNumber = stream.ReadUInt16();
idh.Reserved1 = new ushort[Constants.ERES1WDS];
for (int i = 0; i < Constants.ERES1WDS; i++)
{
idh.Reserved1[i] = stream.ReadUInt16();
}
idh.OEMIdentifier = stream.ReadUInt16();
idh.OEMInformation = stream.ReadUInt16();
idh.Reserved2 = new ushort[Constants.ERES2WDS];
for (int i = 0; i < Constants.ERES2WDS; i++)
{
idh.Reserved2[i] = stream.ReadUInt16();
}
idh.NewExeHeaderAddr = stream.ReadInt32();
return idh;
}
}
}

View File

@@ -0,0 +1,44 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
[StructLayout(LayoutKind.Sequential)]
internal class IMAGE_FILE_HEADER
{
public ushort Machine;
public ushort NumberOfSections;
public uint TimeDateStamp;
public uint PointerToSymbolTable;
public uint NumberOfSymbols;
public ushort SizeOfOptionalHeader;
public ushort Characteristics;
public static IMAGE_FILE_HEADER Deserialize(Stream stream)
{
var ifh = new IMAGE_FILE_HEADER();
ifh.Machine = stream.ReadUInt16();
ifh.NumberOfSections = stream.ReadUInt16();
ifh.TimeDateStamp = stream.ReadUInt32();
ifh.PointerToSymbolTable = stream.ReadUInt32();
ifh.NumberOfSymbols = stream.ReadUInt32();
ifh.SizeOfOptionalHeader = stream.ReadUInt16();
ifh.Characteristics = stream.ReadUInt16();
return ifh;
}
}
}

View File

@@ -0,0 +1,103 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
[StructLayout(LayoutKind.Sequential)]
internal class IMAGE_OPTIONAL_HEADER
{
// Standard fields
public ushort Magic;
public byte MajorLinkerVersion;
public byte MinorLinkerVersion;
public uint SizeOfCode;
public uint SizeOfInitializedData;
public uint SizeOfUninitializedData;
public uint AddressOfEntryPoint;
public uint BaseOfCode;
public uint BaseOfData;
// NT additional fields.
public uint ImageBase;
public uint SectionAlignment;
public uint FileAlignment;
public ushort MajorOperatingSystemVersion;
public ushort MinorOperatingSystemVersion;
public ushort MajorImageVersion;
public ushort MinorImageVersion;
public ushort MajorSubsystemVersion;
public ushort MinorSubsystemVersion;
public uint Reserved1;
public uint SizeOfImage;
public uint SizeOfHeaders;
public uint CheckSum;
public ushort Subsystem;
public ushort DllCharacteristics;
public uint SizeOfStackReserve;
public uint SizeOfStackCommit;
public uint SizeOfHeapReserve;
public uint SizeOfHeapCommit;
public uint LoaderFlags;
public uint NumberOfRvaAndSizes;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES)]
public IMAGE_DATA_DIRECTORY[] DataDirectory;
public static IMAGE_OPTIONAL_HEADER Deserialize(Stream stream)
{
var ioh = new IMAGE_OPTIONAL_HEADER();
ioh.Magic = stream.ReadUInt16();
ioh.MajorLinkerVersion = stream.ReadByteValue();
ioh.MinorLinkerVersion = stream.ReadByteValue();
ioh.SizeOfCode = stream.ReadUInt32();
ioh.SizeOfInitializedData = stream.ReadUInt32();
ioh.SizeOfUninitializedData = stream.ReadUInt32();
ioh.AddressOfEntryPoint = stream.ReadUInt32();
ioh.BaseOfCode = stream.ReadUInt32();
ioh.BaseOfData = stream.ReadUInt32();
ioh.ImageBase = stream.ReadUInt32();
ioh.SectionAlignment = stream.ReadUInt32();
ioh.FileAlignment = stream.ReadUInt32();
ioh.MajorOperatingSystemVersion = stream.ReadUInt16();
ioh.MinorOperatingSystemVersion = stream.ReadUInt16();
ioh.MajorImageVersion = stream.ReadUInt16();
ioh.MinorImageVersion = stream.ReadUInt16();
ioh.MajorSubsystemVersion = stream.ReadUInt16();
ioh.MinorSubsystemVersion = stream.ReadUInt16();
ioh.Reserved1 = stream.ReadUInt32();
ioh.SizeOfImage = stream.ReadUInt32();
ioh.SizeOfHeaders = stream.ReadUInt32();
ioh.CheckSum = stream.ReadUInt32();
ioh.Subsystem = stream.ReadUInt16();
ioh.DllCharacteristics = stream.ReadUInt16();
ioh.SizeOfStackReserve = stream.ReadUInt32();
ioh.SizeOfStackCommit = stream.ReadUInt32();
ioh.SizeOfHeapReserve = stream.ReadUInt32();
ioh.SizeOfHeapCommit = stream.ReadUInt32();
ioh.LoaderFlags = stream.ReadUInt32();
ioh.NumberOfRvaAndSizes = stream.ReadUInt32();
ioh.DataDirectory = new IMAGE_DATA_DIRECTORY[Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
for (int i = 0; i < Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
{
ioh.DataDirectory[i] = IMAGE_DATA_DIRECTORY.Deserialize(stream);
}
return ioh;
}
}
}

View File

@@ -0,0 +1,96 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
/// <summary>
/// New .EXE header
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal class IMAGE_OS2_HEADER
{
public ushort Magic; // 00 Magic number NE_MAGIC
public byte LinkerVersion; // 02 Linker Version number
public byte LinkerRevision; // 03 Linker Revision number
public ushort EntryTableOffset; // 04 Offset of Entry Table
public ushort EntryTableSize; // 06 Number of bytes in Entry Table
public uint CrcChecksum; // 08 Checksum of whole file
public ushort Flags; // 0C Flag word
public ushort Autodata; // 0E Automatic data segment number
public ushort InitialHeapAlloc; // 10 Initial heap allocation
public ushort InitialStackAlloc; // 12 Initial stack allocation
public uint InitialCSIPSetting; // 14 Initial CS:IP setting
public uint InitialSSSPSetting; // 18 Initial SS:SP setting
public ushort FileSegmentCount; // 1C Count of file segments
public ushort ModuleReferenceTableSize; // 1E Entries in Module Reference Table
public ushort NonResidentNameTableSize; // 20 Size of non-resident name table
public ushort SegmentTableOffset; // 22 Offset of Segment Table
public ushort ResourceTableOffset; // 24 Offset of Resource Table
public ushort ResidentNameTableOffset; // 26 Offset of resident name table
public ushort ModuleReferenceTableOffset; // 28 Offset of Module Reference Table
public ushort ImportedNamesTableOffset; // 2A Offset of Imported Names Table
public uint NonResidentNamesTableOffset; // 2C Offset of Non-resident Names Table
public ushort MovableEntriesCount; // 30 Count of movable entries
public ushort SegmentAlignmentShiftCount; // 32 Segment alignment shift count
public ushort ResourceEntriesCount; // 34 Count of resource entries
public byte TargetOperatingSystem; // 36 Target operating system
public byte AdditionalFlags; // 37 Additional flags
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.NERESWORDS)]
public ushort[] Reserved; // 38 3 reserved words
public byte WindowsSDKRevision; // 3E Windows SDK revison number
public byte WindowsSDKVersion; // 3F Windows SDK version number
public static IMAGE_OS2_HEADER Deserialize(Stream stream)
{
var ioh = new IMAGE_OS2_HEADER();
ioh.Magic = stream.ReadUInt16();
ioh.LinkerVersion = stream.ReadByteValue();
ioh.LinkerRevision = stream.ReadByteValue();
ioh.EntryTableOffset = stream.ReadUInt16();
ioh.EntryTableSize = stream.ReadUInt16();
ioh.CrcChecksum = stream.ReadUInt32();
ioh.Flags = stream.ReadUInt16();
ioh.Autodata = stream.ReadUInt16();
ioh.InitialHeapAlloc = stream.ReadUInt16();
ioh.InitialStackAlloc = stream.ReadUInt16();
ioh.InitialCSIPSetting = stream.ReadUInt32();
ioh.InitialSSSPSetting = stream.ReadUInt32();
ioh.FileSegmentCount = stream.ReadUInt16();
ioh.ModuleReferenceTableSize = stream.ReadUInt16();
ioh.NonResidentNameTableSize = stream.ReadUInt16();
ioh.SegmentTableOffset = stream.ReadUInt16();
ioh.ResourceTableOffset = stream.ReadUInt16();
ioh.ResidentNameTableOffset = stream.ReadUInt16();
ioh.ModuleReferenceTableOffset = stream.ReadUInt16();
ioh.ImportedNamesTableOffset = stream.ReadUInt16();
ioh.NonResidentNamesTableOffset = stream.ReadUInt32();
ioh.MovableEntriesCount = stream.ReadUInt16();
ioh.SegmentAlignmentShiftCount = stream.ReadUInt16();
ioh.ResourceEntriesCount = stream.ReadUInt16();
ioh.TargetOperatingSystem = stream.ReadByteValue();
ioh.AdditionalFlags = stream.ReadByteValue();
ioh.Reserved = new ushort[Constants.NERESWORDS];
for (int i = 0; i < Constants.NERESWORDS; i++)
{
ioh.Reserved[i] = stream.ReadUInt16();
}
ioh.WindowsSDKRevision = stream.ReadByteValue();
ioh.WindowsSDKVersion = stream.ReadByteValue();
return ioh;
}
}
}

View File

@@ -0,0 +1,38 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
[StructLayout(LayoutKind.Sequential)]
internal class IMAGE_RESOURCE_DATA_ENTRY
{
public uint OffsetToData;
public uint Size;
public uint CodePage;
public uint Reserved;
public static IMAGE_RESOURCE_DATA_ENTRY Deserialize(Stream stream)
{
var irde = new IMAGE_RESOURCE_DATA_ENTRY();
irde.OffsetToData = stream.ReadUInt32();
irde.Size = stream.ReadUInt32();
irde.CodePage = stream.ReadUInt32();
irde.Reserved = stream.ReadUInt32();
return irde;
}
}
}

View File

@@ -0,0 +1,42 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
[StructLayout(LayoutKind.Sequential)]
internal class IMAGE_RESOURCE_DIRECTORY
{
public uint Characteristics;
public uint TimeDateStamp;
public ushort MajorVersion;
public ushort MinorVersion;
public ushort NumberOfNamedEntries;
public ushort NumberOfIdEntries;
public static IMAGE_RESOURCE_DIRECTORY Deserialize(Stream stream)
{
var ird = new IMAGE_RESOURCE_DIRECTORY();
ird.Characteristics = stream.ReadUInt32();
ird.TimeDateStamp = stream.ReadUInt32();
ird.MajorVersion = stream.ReadUInt16();
ird.MinorVersion = stream.ReadUInt16();
ird.NumberOfNamedEntries = stream.ReadUInt16();
ird.NumberOfIdEntries = stream.ReadUInt16();
return ird;
}
}
}

View File

@@ -0,0 +1,34 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
[StructLayout(LayoutKind.Sequential)]
internal class IMAGE_RESOURCE_DIRECTORY_ENTRY
{
public uint Name;
public uint OffsetToData;
public static IMAGE_RESOURCE_DIRECTORY_ENTRY Deserialize(Stream stream)
{
var irde = new IMAGE_RESOURCE_DIRECTORY_ENTRY();
irde.Name = stream.ReadUInt32();
irde.OffsetToData = stream.ReadUInt32();
return irde;
}
}
}

View File

@@ -0,0 +1,34 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
[StructLayout(LayoutKind.Sequential)]
internal class IMAGE_RESOURCE_DIR_STRING_U
{
public ushort Length;
public char[] NameString;
public static IMAGE_RESOURCE_DIR_STRING_U Deserialize(Stream stream)
{
var irdsu = new IMAGE_RESOURCE_DIR_STRING_U();
irdsu.Length = stream.ReadUInt16();
irdsu.NameString = stream.ReadChars(irdsu.Length);
return irdsu;
}
}
}

View File

@@ -0,0 +1,59 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
[StructLayout(LayoutKind.Sequential)]
internal class IMAGE_SECTION_HEADER
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.IMAGE_SIZEOF_SHORT_NAME)]
public byte[] Name;
// Misc
public uint PhysicalAddress;
public uint VirtualSize;
public uint VirtualAddress;
public uint SizeOfRawData;
public uint PointerToRawData;
public uint PointerToRelocations;
public uint PointerToLinenumbers;
public ushort NumberOfRelocations;
public ushort NumberOfLinenumbers;
public SectionCharacteristics Characteristics;
public static IMAGE_SECTION_HEADER Deserialize(Stream stream)
{
var ish = new IMAGE_SECTION_HEADER();
ish.Name = stream.ReadBytes(Constants.IMAGE_SIZEOF_SHORT_NAME);
// Misc
ish.PhysicalAddress = stream.ReadUInt32();
ish.VirtualSize = ish.PhysicalAddress;
ish.VirtualAddress = stream.ReadUInt32();
ish.SizeOfRawData = stream.ReadUInt32();
ish.PointerToRawData = stream.ReadUInt32();
ish.PointerToRelocations = stream.ReadUInt32();
ish.PointerToLinenumbers = stream.ReadUInt32();
ish.NumberOfRelocations = stream.ReadUInt16();
ish.NumberOfLinenumbers = stream.ReadUInt16();
ish.Characteristics = (SectionCharacteristics)stream.ReadUInt32();
return ish;
}
}
}

View File

@@ -0,0 +1,42 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
[StructLayout(LayoutKind.Sequential)]
internal class NAMEINFO
{
public ushort Offset;
public ushort Length;
public ushort Flags;
public ushort ID;
public ushort Handle;
public ushort Usage;
public static NAMEINFO Deserialize(Stream stream)
{
var ni = new NAMEINFO();
ni.Offset = stream.ReadUInt16();
ni.Length = stream.ReadUInt16();
ni.Flags = stream.ReadUInt16();
ni.ID = stream.ReadUInt16();
ni.Handle = stream.ReadUInt16();
ni.Usage = stream.ReadUInt16();
return ni;
}
}
}

View File

@@ -0,0 +1,67 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
/// <summary>
/// Relocation item
/// </summary>
/// TODO: Fix this because Marshal will not work since it's not a direct read
[StructLayout(LayoutKind.Sequential)]
internal class NewRlc
{
public char SourceType; // Source type
public char Flags; // Flag byte
public ushort SourceOffset; // Source offset
// nr_intref - Internal Reference
public char TargetSegmentNumber; // Target segment number
public char Reserved1; // Reserved
public ushort TargetEntryTableOffset; // Target Entry Table offset
// nr_import - Import
public ushort ModuleReferenceTableIndex; // Index into Module Reference Table
public ushort ProcedureOffset; // Procedure ordinal or name offset
// nr_osfix - Operating system fixup
public ushort OperatingSystemFixupType; // OSFIXUP type
public ushort Reserved2; // Reserved
public static NewRlc Deserialize(Stream stream)
{
var nr = new NewRlc();
nr.SourceType = stream.ReadChar();
nr.Flags = stream.ReadChar();
nr.SourceOffset = stream.ReadUInt16();
// nr_intref
nr.TargetSegmentNumber = stream.ReadChar();
nr.Reserved1 = stream.ReadChar();
nr.TargetEntryTableOffset = stream.ReadUInt16();
// nr_import
nr.ModuleReferenceTableIndex = BitConverter.ToUInt16(new byte[] { (byte)nr.SourceType, (byte)nr.Flags }, 0);
nr.ProcedureOffset = nr.TargetEntryTableOffset;
// nr_osfix
nr.OperatingSystemFixupType = nr.ModuleReferenceTableIndex;
nr.Reserved2 = nr.ProcedureOffset;
return nr;
}
}
}

View File

@@ -0,0 +1,38 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
/// <summary>
/// Relocation info
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal class NewRlcInfo
{
/// <summary>
/// Number of relocation items that follow
/// </summary>
public ushort RelocationItemCount;
public static NewRlcInfo Deserialize(Stream stream)
{
var nri = new NewRlcInfo();
nri.RelocationItemCount = stream.ReadUInt16();
return nri;
}
}
}

View File

@@ -0,0 +1,40 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
/// <summary>
/// Resource table
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal class NewRsrc
{
/// <summary>
/// Alignment shift count for resources
/// </summary>
public ushort AlignmentShiftCount;
public RsrcTypeInfo TypeInfo;
public static NewRsrc Deserialize(Stream stream)
{
var nr = new NewRsrc();
nr.AlignmentShiftCount = stream.ReadUInt16();
nr.TypeInfo = RsrcTypeInfo.Deserialize(stream);
return nr;
}
}
}

View File

@@ -0,0 +1,56 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
/// <summary>
/// New .EXE segment table entry
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal class NewSeg
{
/// <summary>
/// File sector of start of segment
/// </summary>
public ushort StartFileSector;
/// <summary>
/// Number of bytes in file
/// </summary>
public ushort BytesInFile;
/// <summary>
/// Attribute flags
/// </summary>
public ushort Flags;
/// <summary>
/// Minimum allocation in bytes
/// </summary>
public ushort MinimumAllocation;
public static NewSeg Deserialize(Stream stream)
{
var ns = new NewSeg();
ns.StartFileSector = stream.ReadUInt16();
ns.BytesInFile = stream.ReadUInt16();
ns.Flags = stream.ReadUInt16();
ns.MinimumAllocation = stream.ReadUInt16();
return ns;
}
}
}

View File

@@ -0,0 +1,66 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
/// <summary>
/// Segment data
/// </summary>
/// TODO: Fix this because Marshal will not work since it's not a direct read
[StructLayout(LayoutKind.Sequential)]
internal class NewSegdata
{
#region ns_iter
/// <summary>
/// Number of iterations
/// </summary>
public ushort Iterations;
/// <summary>
/// Number of bytes
/// </summary>
public ushort TotalBytes;
/// <summary>
/// Iterated data bytes
/// </summary>
public char IteratedDataBytes;
#endregion
#region ns_noiter
/// <summary>
/// Data bytes
/// </summary>
public char DataBytes;
#endregion
public static NewSegdata Deserialize(Stream stream)
{
var nsd = new NewSegdata();
nsd.Iterations = stream.ReadUInt16();
nsd.TotalBytes = stream.ReadUInt16();
nsd.IteratedDataBytes = stream.ReadChar();
nsd.DataBytes = (char)BitConverter.GetBytes(nsd.Iterations)[0];
return nsd;
}
}
}

View File

@@ -0,0 +1,41 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
[StructLayout(LayoutKind.Sequential)]
internal class ResourceTable
{
public ushort rscAlignShift;
public TYPEINFO TypeInfo;
public ushort rscEndTypes;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
public sbyte[][] rscResourceNames;
public byte rscEndNames;
public static ResourceTable Deserialize(Stream stream)
{
var rt = new ResourceTable();
rt.rscAlignShift = stream.ReadUInt16();
rt.TypeInfo = TYPEINFO.Deserialize(stream);
rt.rscEndTypes = stream.ReadUInt16();
rt.rscResourceNames = null; // TODO: Figure out size
rt.rscEndNames = stream.ReadByteValue();
return rt;
}
}
}

View File

@@ -0,0 +1,75 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
/// <summary>
/// Resource name information block
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal class RsrcNameInfo
{
/*
* The following two fields must be shifted left by the value of
* the rs_align field to compute their actual value. This allows
* resources to be larger than 64k, but they do not need to be
* aligned on 512 byte boundaries, the way segments are.
*/
/// <summary>
/// File offset to resource data
/// </summary>
public ushort Offset;
/// <summary>
/// Length of resource data
/// </summary>
public ushort Length;
/// <summary>
/// Resource flags
/// </summary>
public ushort Flags;
/// <summary>
/// Resource name id
/// </summary>
public ushort NameID;
/// <summary>
/// If loaded, then global handle
/// </summary>
public ushort Handle;
/// <summary>
/// Initially zero. Number of times the handle for this resource has been given out
/// </summary>
public ushort UsageCount;
public static RsrcNameInfo Deserialize(Stream stream)
{
var rni = new RsrcNameInfo();
rni.Offset = stream.ReadUInt16();
rni.Length = stream.ReadUInt16();
rni.Flags = stream.ReadUInt16();
rni.NameID = stream.ReadUInt16();
rni.Handle = stream.ReadUInt16();
rni.UsageCount = stream.ReadUInt16();
return rni;
}
}
}

View File

@@ -0,0 +1,46 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
/// <summary>
/// Resource type or name string
/// </summary>
/// TODO: Fix this because SizeConst = 0 is not valid
[StructLayout(LayoutKind.Sequential)]
internal class RsrcString
{
/// <summary>
/// Number of bytes in string
/// </summary>
public byte Length;
/// <summary>
/// Next of string
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
public char[] Text;
public static RsrcString Deserialize(Stream stream)
{
var rs = new RsrcString();
rs.Length = stream.ReadByteValue();
rs.Text = stream.ReadChars(rs.Length);
return rs;
}
}
}

View File

@@ -0,0 +1,39 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
/// <summary>
/// Resource type information block
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal class RsrcTypeInfo
{
public ushort ID;
public ushort rt_nres;
public uint rt_proc;
public static RsrcTypeInfo Deserialize(Stream stream)
{
var rti = new RsrcTypeInfo();
rti.ID = stream.ReadUInt16();
rti.rt_nres = stream.ReadUInt16();
rti.rt_proc = stream.ReadUInt32();
return rti;
}
}
}

View File

@@ -0,0 +1,38 @@
/*
* NEWEXE.H (C) Copyright Microsoft Corp 1984-1987
*
* Data structure definitions for the OS/2 & Windows
* executable file format.
*
* Modified by IVS on 24-Jan-1991 for Resource DeCompiler
* (C) Copyright IVS 1991
*
* http://csn.ul.ie/~caolan/pub/winresdump/winresdump/newexe.h
*/
using System.IO;
using System.Runtime.InteropServices;
namespace BurnOutSharp.ExecutableType.Microsoft
{
[StructLayout(LayoutKind.Sequential)]
internal class TYPEINFO
{
public ushort TypeID;
public ushort ResourceCount;
public uint Reserved;
public NAMEINFO NameInfo;
public static TYPEINFO Deserialize(Stream stream)
{
var ti = new TYPEINFO();
ti.TypeID = stream.ReadUInt16();
ti.ResourceCount = stream.ReadUInt16();
ti.Reserved = stream.ReadUInt32();
ti.NameInfo = NAMEINFO.Deserialize(stream);
return ti;
}
}
}

109
BurnOutSharp/Extensions.cs Normal file
View File

@@ -0,0 +1,109 @@
using System;
using System.IO;
using System.Text;
namespace BurnOutSharp
{
internal static class Ebuffertensions
{
/// <summary>
/// Read a byte from the stream
/// </summary>
public static byte ReadByteValue(this Stream stream)
{
byte[] buffer = new byte[1];
stream.Read(buffer, 0, 1);
return buffer[0];
}
/// <summary>
/// Read a byte array from the stream
/// </summary>
public static byte[] ReadBytes(this Stream stream, int count)
{
byte[] buffer = new byte[count];
stream.Read(buffer, 0, count);
return buffer;
}
/// <summary>
/// Read a character from the stream
/// </summary>
public static char ReadChar(this Stream stream)
{
byte[] buffer = new byte[1];
stream.Read(buffer, 0, 1);
return (char)buffer[0];
}
/// <summary>
/// Read a character array from the stream
/// </summary>
public static char[] ReadChars(this Stream stream, int count)
{
byte[] buffer = new byte[count];
stream.Read(buffer, 0, count);
return Encoding.Default.GetString(buffer).ToCharArray();
}
/// <summary>
/// Read a short from the stream
/// </summary>
public static short ReadInt16(this Stream stream)
{
byte[] buffer = new byte[2];
stream.Read(buffer, 0, 2);
return BitConverter.ToInt16(buffer, 0);
}
/// <summary>
/// Read a ushort from the stream
/// </summary>
public static ushort ReadUInt16(this Stream stream)
{
byte[] buffer = new byte[2];
stream.Read(buffer, 0, 2);
return BitConverter.ToUInt16(buffer, 0);
}
/// <summary>
/// Read an int from the stream
/// </summary>
public static int ReadInt32(this Stream stream)
{
byte[] buffer = new byte[4];
stream.Read(buffer, 0, 4);
return BitConverter.ToInt32(buffer, 0);
}
/// <summary>
/// Read a uint from the stream
/// </summary>
public static uint ReadUInt32(this Stream stream)
{
byte[] buffer = new byte[4];
stream.Read(buffer, 0, 4);
return BitConverter.ToUInt32(buffer, 0);
}
/// <summary>
/// Read a long from the stream
/// </summary>
public static long ReadInt64(this Stream stream)
{
byte[] buffer = new byte[8];
stream.Read(buffer, 0, 8);
return BitConverter.ToInt64(buffer, 0);
}
/// <summary>
/// Read a ulong from the stream
/// </summary>
public static ulong ReadUInt64(this Stream stream)
{
byte[] buffer = new byte[8];
stream.Read(buffer, 0, 8);
return BitConverter.ToUInt64(buffer, 0);
}
}
}

1
BurnOutSharp/External/LessIO vendored Submodule

1
BurnOutSharp/External/hllib vendored Submodule

53
BurnOutSharp/External/psxt001z/CRC16.cs vendored Normal file
View File

@@ -0,0 +1,53 @@
namespace BurnOutSharp.External.psxt001z
{
public class CRC16
{
// Table of CRC constants - implements x^16+x^12+x^5+1
private static ushort[] crc16_tab = new ushort[]
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
};
public static ushort Calculate(byte[] buf, int bufPtr, int len)
{
ushort cksum = 0;
for (int i = 0; i < len; i++)
{
cksum = (ushort)(crc16_tab[((cksum >> 8) ^ buf[bufPtr++]) & 0xFF] ^ (cksum << 8));
}
return (ushort)(~cksum);
}
}
}

View File

@@ -0,0 +1,128 @@
using System;
using System.IO;
using System.Linq;
namespace BurnOutSharp.External.psxt001z
{
/// <summary>
/// LibCrypt detection code
/// Originally written by Dremora: https://github.com/Dremora/psxt001z
/// Ported and changed by darksabre76
/// </summary>
public class LibCrypt
{
public static bool CheckSubfile(string subFilePath)
{
// Check the file exists first
if (!File.Exists(subFilePath))
return false;
// Check the extension is a subfile
string ext = Path.GetExtension(subFilePath).TrimStart('.').ToLowerInvariant();
if (ext != "sub")
return false;
// Open and check the subfile for LibCrypt
try
{
using (FileStream subfile = File.OpenRead(subFilePath))
{
return CheckSubfile(subfile);
}
}
catch
{
return false;
}
}
public static bool CheckSubfile(Stream subfile)
{
// Check the length is valid for subfiles
long size = subfile.Length;
if (size % 96 != 0)
return false;
// Persistent values
byte[] buffer = new byte[16];
byte[] sub = new byte[16];
int tpos = 0;
int modifiedSectors = 0;
// Check each sector for modifications
for (uint sector = 150; sector < ((size / 96) + 150); sector++)
{
subfile.Seek(12, SeekOrigin.Current);
if (subfile.Read(buffer, 0, 12) == 0)
return modifiedSectors != 0;
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 = ((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 = ((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);
byte[] crcBytes = BitConverter.GetBytes(crc);
sub[10] = crcBytes[0];
sub[11] = crcBytes[1];
// If any byte (except position 6) is different, it's a modified sector
for (int i = 0; i < 12; i++)
{
if (i == 6)
continue;
if (buffer[i] != sub[i])
{
modifiedSectors++;
break;
}
}
}
return modifiedSectors != 0;
}
private static byte btoi(byte b)
{
/* BCD to u_char */
return (byte)((b) / 16 * 10 + (b) % 16);
}
private static byte itob(byte i)
{
/* u_char to BCD */
return (byte)((i) / 10 * 16 + (i) % 10);
}
}
}

View File

@@ -0,0 +1,129 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using SharpCompress.Compressors;
using SharpCompress.Compressors.Deflate;
namespace BurnOutSharp.FileType
{
internal class BFPK : IScannable
{
/// <inheritdoc/>
public bool ShouldScan(byte[] magic)
{
if (magic.StartsWith(new byte?[] { 0x42, 0x46, 0x50, 0x4b }))
return true;
return false;
}
/// <inheritdoc/>
public Dictionary<string, List<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 Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
// If the BFPK file itself fails
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
{
br.ReadBytes(4); // Skip magic number
int version = br.ReadInt32();
int files = br.ReadInt32();
long current = br.BaseStream.Position;
for (int i = 0; i < files; i++)
{
br.BaseStream.Seek(current, SeekOrigin.Begin);
int nameSize = br.ReadInt32();
string name = new string(br.ReadChars(nameSize));
uint uncompressedSize = br.ReadUInt32();
int offset = br.ReadInt32();
current = br.BaseStream.Position;
br.BaseStream.Seek(offset, SeekOrigin.Begin);
uint compressedSize = br.ReadUInt32();
// Some files can lack the length prefix
if (compressedSize > br.BaseStream.Length)
{
br.BaseStream.Seek(-4, SeekOrigin.Current);
compressedSize = uncompressedSize;
}
// If an individual entry fails
try
{
string tempFile = Path.Combine(tempPath, name);
if (!Directory.Exists(Path.GetDirectoryName(tempFile)))
Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
if (compressedSize == uncompressedSize)
{
using (FileStream fs = File.OpenWrite(tempFile))
{
fs.Write(br.ReadBytes((int)uncompressedSize), 0, (int)uncompressedSize);
}
}
else
{
using (FileStream fs = File.OpenWrite(tempFile))
{
try
{
ZlibStream zs = new ZlibStream(br.BaseStream, CompressionMode.Decompress);
zs.CopyTo(fs);
}
catch (ZlibException)
{
br.BaseStream.Seek(offset + 4, SeekOrigin.Begin);
fs.Write(br.ReadBytes((int)compressedSize), 0, (int)compressedSize);
}
}
}
}
catch { }
br.BaseStream.Seek(current, SeekOrigin.Begin);
}
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return null;
}
}
}

View File

@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.IO;
using SharpCompress.Compressors;
using SharpCompress.Compressors.BZip2;
namespace BurnOutSharp.FileType
{
internal class BZip2 : IScannable
{
/// <inheritdoc/>
public bool ShouldScan(byte[] magic)
{
if (magic.StartsWith(new byte?[] { 0x42, 0x52, 0x68 }))
return true;
return false;
}
/// <inheritdoc/>
public Dictionary<string, List<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 Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
// If the BZip2 file itself fails
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (BZip2Stream bz2File = new BZip2Stream(stream, CompressionMode.Decompress, true))
{
// If an individual entry fails
try
{
string tempFile = Path.Combine(tempPath, Guid.NewGuid().ToString());
using (FileStream fs = File.OpenWrite(tempFile))
{
bz2File.CopyTo(fs);
}
}
catch { }
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return null;
}
}
}

View File

@@ -0,0 +1,118 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
namespace BurnOutSharp.FileType
{
internal class Executable : IScannable
{
/// <summary>
/// Cache for all IContentCheck types
/// </summary>
private static readonly IEnumerable<IContentCheck> contentCheckClasses = InitContentCheckClasses();
/// <inheritdoc/>
public bool ShouldScan(byte[] magic)
{
// DOS MZ executable file format (and descendants)
if (magic.StartsWith(new byte?[] { 0x4d, 0x5a }))
return true;
// Executable and Linkable Format
if (magic.StartsWith(new byte?[] { 0x7f, 0x45, 0x4c, 0x46 }))
return true;
// Mach-O binary (32-bit)
if (magic.StartsWith(new byte?[] { 0xfe, 0xed, 0xfa, 0xce }))
return true;
// Mach-O binary (32-bit, reverse byte ordering scheme)
if (magic.StartsWith(new byte?[] { 0xce, 0xfa, 0xed, 0xfe }))
return true;
// Mach-O binary (64-bit)
if (magic.StartsWith(new byte?[] { 0xfe, 0xed, 0xfa, 0xcf }))
return true;
// Mach-O binary (64-bit, reverse byte ordering scheme)
if (magic.StartsWith(new byte?[] { 0xcf, 0xfa, 0xed, 0xfe }))
return true;
// Prefrred Executable File Format
if (magic.StartsWith(new byte?[] { 0x4a, 0x6f, 0x79, 0x21, 0x70, 0x65, 0x66, 0x66 }))
return true;
return false;
}
/// <inheritdoc/>
public Dictionary<string, List<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 Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
// Load the current file content
byte[] fileContent = null;
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
{
fileContent = br.ReadBytes((int)stream.Length);
}
// If we can, seek to the beginning of the stream
if (stream.CanSeek)
stream.Seek(0, SeekOrigin.Begin);
// Files can be protected in multiple ways
var protections = new Dictionary<string, List<string>>();
// Iterate through all content checks
foreach (var contentCheckClass in contentCheckClasses)
{
string protection = contentCheckClass.CheckContents(file, fileContent, scanner.IncludePosition);
// If we have a valid content check based on settings
if (!contentCheckClass.GetType().Namespace.ToLowerInvariant().Contains("packertype") || scanner.ScanPackers)
{
if (!string.IsNullOrWhiteSpace(protection))
Utilities.AppendToDictionary(protections, file, protection);
}
// If we have an IScannable implementation
if (contentCheckClass is IScannable)
{
IScannable scannable = contentCheckClass as IScannable;
if (file != null && !string.IsNullOrEmpty(protection))
{
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);
}
}
}

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.IO;
using SharpCompress.Archives;
using SharpCompress.Archives.GZip;
namespace BurnOutSharp.FileType
{
internal class GZIP : IScannable
{
/// <inheritdoc/>
public bool ShouldScan(byte[] magic)
{
if (magic.StartsWith(new byte?[] { 0x1f, 0x8b }))
return true;
return false;
}
/// <inheritdoc/>
public Dictionary<string, List<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 Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
// If the gzip file itself fails
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (GZipArchive zipFile = GZipArchive.Open(stream))
{
foreach (var entry in zipFile.Entries)
{
// If an individual entry fails
try
{
// If we have a directory, skip it
if (entry.IsDirectory)
continue;
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch { }
}
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return null;
}
}
}

View File

@@ -0,0 +1,296 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace BurnOutSharp.FileType
{
public class IniFile : IDictionary<string, string>
{
private Dictionary<string, string> _keyValuePairs = new Dictionary<string, string>();
public string this[string key]
{
get
{
if (_keyValuePairs == null)
_keyValuePairs = new Dictionary<string, string>();
key = key.ToLowerInvariant();
if (_keyValuePairs.ContainsKey(key))
return _keyValuePairs[key];
return null;
}
set
{
if (_keyValuePairs == null)
_keyValuePairs = new Dictionary<string, string>();
key = key.ToLowerInvariant();
_keyValuePairs[key] = value;
}
}
/// <summary>
/// Create an empty INI file
/// </summary>
public IniFile()
{
}
/// <summary>
/// Populate an INI file from path
/// </summary>
public IniFile(string path)
{
this.Parse(path);
}
/// <summary>
/// Populate an INI file from stream
/// </summary>
public IniFile(Stream stream)
{
this.Parse(stream);
}
/// <summary>
/// Add or update a key and value to the INI file
/// </summary>
public void AddOrUpdate(string key, string value)
{
_keyValuePairs[key.ToLowerInvariant()] = value;
}
/// <summary>
/// Remove a key from the INI file
/// </summary>
public void Remove(string key)
{
_keyValuePairs.Remove(key.ToLowerInvariant());
}
/// <summary>
/// Read an INI file based on the path
/// </summary>
public bool Parse(string path)
{
// If we don't have a file, we can't read it
if (!File.Exists(path))
return false;
using (var fileStream = File.OpenRead(path))
{
return Parse(fileStream);
}
}
/// <summary>
/// Read an INI file from a stream
/// </summary>
public bool Parse(Stream stream)
{
// If the stream is invalid or unreadable, we can't process it
if (stream == null || !stream.CanRead || stream.Position >= stream.Length - 1)
return false;
// Keys are case-insensitive by default
try
{
using (StreamReader sr = new StreamReader(stream))
{
string section = string.Empty;
while (!sr.EndOfStream)
{
string line = sr.ReadLine().Trim();
// Comments start with ';'
if (line.StartsWith(";"))
{
// No-op, we don't process comments
}
// Section titles are surrounded by square brackets
else if (line.StartsWith("["))
{
section = line.TrimStart('[').TrimEnd(']');
}
// Valid INI lines are in the format key=value
else if (line.Contains("="))
{
// Split the line by '=' for key-value pairs
string[] data = line.Split('=');
// If the value field contains an '=', we need to put them back in
string key = data[0].Trim();
string value = string.Join("=", data.Skip(1)).Trim();
// Section names are prepended to the key with a '.' separating
if (!string.IsNullOrEmpty(section))
key = $"{section}.{key}";
// Set or overwrite keys in the returned dictionary
_keyValuePairs[key.ToLowerInvariant()] = value;
}
// All other lines are ignored
}
}
}
catch
{
// We don't care what the error was, just catch and return
return false;
}
return true;
}
/// <summary>
/// Write an INI file to a path
/// </summary>
public bool Write(string path)
{
// If we don't have a valid dictionary with values, we can't write out
if (_keyValuePairs == null || _keyValuePairs.Count == 0)
return false;
using (var fileStream = File.OpenWrite(path))
{
return Write(fileStream);
}
}
/// <summary>
/// Write an INI file to a stream
/// </summary>
public bool Write(Stream stream)
{
// If we don't have a valid dictionary with values, we can't write out
if (_keyValuePairs == null || _keyValuePairs.Count == 0)
return false;
// If the stream is invalid or unwritable, we can't output to it
if (stream == null || !stream.CanWrite || stream.Position >= stream.Length - 1)
return false;
try
{
using (StreamWriter sw = new StreamWriter(stream))
{
// Order the dictionary by keys to link sections together
var orderedKeyValuePairs = _keyValuePairs.OrderBy(kvp => kvp.Key);
string section = string.Empty;
foreach (var keyValuePair in orderedKeyValuePairs)
{
// Extract the key and value
string key = keyValuePair.Key;
string value = keyValuePair.Value;
// We assume '.' is a section name separator
if (key.Contains('.'))
{
// Split the key by '.'
string[] data = keyValuePair.Key.Split('.');
// If the key contains an '.', we need to put them back in
string newSection = data[0].Trim();
key = string.Join(".", data.Skip(1)).Trim();
// If we have a new section, write it out
if (!string.Equals(newSection, section, StringComparison.OrdinalIgnoreCase))
{
sw.WriteLine($"[{newSection}]");
section = newSection;
}
}
// Now write out the key and value in a standardized way
sw.WriteLine($"{key}={value}");
}
}
}
catch
{
// We don't care what the error was, just catch and return
return false;
}
return true;
}
#region IDictionary Impelementations
public ICollection<string> Keys => ((IDictionary<string, string>)_keyValuePairs).Keys;
public ICollection<string> Values => ((IDictionary<string, string>)_keyValuePairs).Values;
public int Count => ((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Count;
public bool IsReadOnly => ((ICollection<KeyValuePair<string, string>>)_keyValuePairs).IsReadOnly;
public void Add(string key, string value)
{
((IDictionary<string, string>)_keyValuePairs).Add(key.ToLowerInvariant(), value);
}
bool IDictionary<string, string>.Remove(string key)
{
return ((IDictionary<string, string>)_keyValuePairs).Remove(key.ToLowerInvariant());
}
public bool TryGetValue(string key, out string value)
{
return ((IDictionary<string, string>)_keyValuePairs).TryGetValue(key.ToLowerInvariant(), out value);
}
public void Add(KeyValuePair<string, string> item)
{
var newItem = new KeyValuePair<string, string>(item.Key.ToLowerInvariant(), item.Value);
((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Add(newItem);
}
public void Clear()
{
((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Clear();
}
public bool Contains(KeyValuePair<string, string> item)
{
var newItem = new KeyValuePair<string, string>(item.Key.ToLowerInvariant(), item.Value);
return ((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Contains(newItem);
}
public bool ContainsKey(string key)
{
return _keyValuePairs.ContainsKey(key.ToLowerInvariant());
}
public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex)
{
((ICollection<KeyValuePair<string, string>>)_keyValuePairs).CopyTo(array, arrayIndex);
}
public bool Remove(KeyValuePair<string, string> item)
{
var newItem = new KeyValuePair<string, string>(item.Key.ToLowerInvariant(), item.Value);
return ((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Remove(newItem);
}
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{
return ((IEnumerable<KeyValuePair<string, string>>)_keyValuePairs).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)_keyValuePairs).GetEnumerator();
}
#endregion
}
}

View File

@@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using UnshieldSharp;
namespace BurnOutSharp.FileType
{
internal class InstallShieldCAB : IScannable
{
/// <inheritdoc/>
public bool ShouldScan(byte[] magic)
{
if (magic.StartsWith(new byte?[] { 0x49, 0x53, 0x63 }))
return true;
return false;
}
/// <inheritdoc/>
public Dictionary<string, List<string>> Scan(Scanner scanner, string file)
{
if (!File.Exists(file))
return null;
using (var fs = File.OpenRead(file))
{
return Scan(scanner, fs, file);
}
}
// TODO: Add stream opening support
/// <inheritdoc/>
public Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
// Get the name of the first cabinet file or header
string directory = Path.GetDirectoryName(file);
string noExtension = Path.GetFileNameWithoutExtension(file);
string filenamePattern = Path.Combine(directory, noExtension);
filenamePattern = new Regex(@"\d+$").Replace(filenamePattern, string.Empty);
bool cabinetHeaderExists = File.Exists(Path.Combine(directory, filenamePattern + "1.hdr"));
bool shouldScanCabinet = cabinetHeaderExists
? file.Equals(Path.Combine(directory, filenamePattern + "1.hdr"), StringComparison.OrdinalIgnoreCase)
: file.Equals(Path.Combine(directory, filenamePattern + "1.cab"), StringComparison.OrdinalIgnoreCase);
// If we have the first file
if (shouldScanCabinet)
{
// If the cab file itself fails
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
UnshieldCabinet cabfile = UnshieldCabinet.Open(file);
for (int i = 0; i < cabfile.FileCount; i++)
{
// If an individual entry fails
try
{
string tempFile = Path.Combine(tempPath, cabfile.FileName(i));
cabfile.FileSave(i, tempFile);
}
catch { }
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
}
return null;
}
}
}

View File

@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.IO;
using StormLibSharp;
namespace BurnOutSharp.FileType
{
internal class MPQ : IScannable
{
/// <inheritdoc/>
public bool ShouldScan(byte[] magic)
{
if (magic.StartsWith(new byte?[] { 0x4d, 0x50, 0x51, 0x1a }))
return true;
return false;
}
/// <inheritdoc/>
public Dictionary<string, List<string>> Scan(Scanner scanner, string file)
{
if (!File.Exists(file))
return null;
using (var fs = File.OpenRead(file))
{
return Scan(scanner, fs, file);
}
}
// TODO: Add stream opening support
/// <inheritdoc/>
public Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
// If the mpq file itself fails
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (MpqArchive mpqArchive = new MpqArchive(file, FileAccess.Read))
{
// Try to open the listfile
string listfile = null;
MpqFileStream listStream = mpqArchive.OpenFile("(listfile)");
// If we can't read the listfile, we just return
if (!listStream.CanRead)
return null;
// Read the listfile in for processing
using (StreamReader sr = new StreamReader(listStream))
{
listfile = sr.ReadToEnd();
}
// Split the listfile by newlines
string[] listfileLines = listfile.Replace("\r\n", "\n").Split('\n');
// Loop over each entry
foreach (string sub in listfileLines)
{
// If an individual entry fails
try
{
string tempFile = Path.Combine(tempPath, sub);
Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
mpqArchive.ExtractFile(sub, tempFile);
}
catch { }
}
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return null;
}
}
}

View File

@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.IO;
using WixToolset.Dtf.WindowsInstaller;
namespace BurnOutSharp.FileType
{
internal class MSI : IScannable
{
/// <inheritdoc/>
public bool ShouldScan(byte[] magic)
{
if (magic.StartsWith(new byte?[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }))
return true;
return false;
}
/// <inheritdoc/>
public Dictionary<string, List<string>> Scan(Scanner scanner, string file)
{
if (!File.Exists(file))
return null;
using (var fs = File.OpenRead(file))
{
return Scan(scanner, fs, file);
}
}
// TODO: Add stream opening support
/// <inheritdoc/>
public Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
// If the MSI file itself fails
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (Database msidb = new Database(file, DatabaseOpenMode.ReadOnly))
{
msidb.ExportAll(tempPath);
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return null;
}
}
}

View File

@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.IO;
using LibMSPackN;
namespace BurnOutSharp.FileType
{
// Specification available at http://download.microsoft.com/download/5/0/1/501ED102-E53F-4CE0-AA6B-B0F93629DDC6/Exchange/%5BMS-CAB%5D.pdf
internal class MicrosoftCAB : IScannable
{
/// <inheritdoc/>
public bool ShouldScan(byte[] magic)
{
if (magic.StartsWith(new byte?[] { 0x4d, 0x53, 0x43, 0x46 }))
return true;
return false;
}
/// <inheritdoc/>
public Dictionary<string, List<string>> Scan(Scanner scanner, string file)
{
if (!File.Exists(file))
return null;
using (var fs = File.OpenRead(file))
{
return Scan(scanner, fs, file);
}
}
// TODO: Add stream opening support
/// <inheritdoc/>
public Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
// If the cab file itself fails
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (MSCabinet cabfile = new MSCabinet(file))
{
foreach (var sub in cabfile.GetFiles())
{
// If an individual entry fails
try
{
// The trim here is for some very odd and stubborn files
string tempFile = Path.Combine(tempPath, sub.Filename.TrimEnd('.'));
sub.ExtractTo(tempFile);
}
catch { }
}
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return null;
}
}
}

View File

@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.IO;
using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
namespace BurnOutSharp.FileType
{
internal class PKZIP : IScannable
{
/// <inheritdoc/>
public bool ShouldScan(byte[] magic)
{
// PKZIP
if (magic.StartsWith(new byte?[] { 0x50, 0x4b, 0x03, 0x04 }))
return true;
// PKZIP (Empty Archive)
if (magic.StartsWith(new byte?[] { 0x50, 0x4b, 0x05, 0x06 }))
return true;
// PKZIP (Spanned Archive)
if (magic.StartsWith(new byte?[] { 0x50, 0x4b, 0x07, 0x08 }))
return true;
return false;
}
/// <inheritdoc/>
public Dictionary<string, List<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 Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
// If the zip file itself fails
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (ZipArchive zipFile = ZipArchive.Open(stream))
{
foreach (var entry in zipFile.Entries)
{
// If an individual entry fails
try
{
// If we have a directory, skip it
if (entry.IsDirectory)
continue;
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch { }
}
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return null;
}
}
}

View File

@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.IO;
using SharpCompress.Archives;
using SharpCompress.Archives.Rar;
namespace BurnOutSharp.FileType
{
internal class RAR : IScannable
{
/// <inheritdoc/>
public bool ShouldScan(byte[] magic)
{
// RAR archive version 1.50 onwards
if (magic.StartsWith(new byte?[] { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 }))
return true;
// RAR archive version 5.0 onwards
if (magic.StartsWith(new byte?[] { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0x00 }))
return true;
return false;
}
/// <inheritdoc/>
public Dictionary<string, List<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 Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
// If the rar file itself fails
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (RarArchive zipFile = RarArchive.Open(stream))
{
foreach (var entry in zipFile.Entries)
{
// If an individual entry fails
try
{
// If we have a directory, skip it
if (entry.IsDirectory)
continue;
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch { }
}
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return null;
}
}
}

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.IO;
using SharpCompress.Archives;
using SharpCompress.Archives.SevenZip;
namespace BurnOutSharp.FileType
{
internal class SevenZip : IScannable
{
/// <inheritdoc/>
public bool ShouldScan(byte[] magic)
{
if (magic.StartsWith(new byte?[] { 0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c }))
return true;
return false;
}
/// <inheritdoc/>
public Dictionary<string, List<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 Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
// If the 7-zip file itself fails
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (SevenZipArchive sevenZipFile = SevenZipArchive.Open(stream))
{
foreach (var entry in sevenZipFile.Entries)
{
// If an individual entry fails
try
{
// If we have a directory, skip it
if (entry.IsDirectory)
continue;
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch { }
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
}
catch { }
return null;
}
}
}

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.IO;
using SharpCompress.Archives;
using SharpCompress.Archives.Tar;
namespace BurnOutSharp.FileType
{
internal class TapeArchive : IScannable
{
/// <inheritdoc/>
public bool ShouldScan(byte[] magic)
{
if (magic.StartsWith(new byte?[] { 0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30 }))
return true;
if (magic.StartsWith(new byte?[] { 0x75, 0x73, 0x74, 0x61, 0x72, 0x20, 0x20, 0x00 }))
return true;
return false;
}
/// <inheritdoc/>
public Dictionary<string, List<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 Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
// If the tar file itself fails
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (TarArchive tarFile = TarArchive.Open(stream))
{
foreach (var entry in tarFile.Entries)
{
// If an individual entry fails
try
{
// If we have a directory, skip it
if (entry.IsDirectory)
continue;
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch { }
}
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return null;
}
}
}

View File

@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace BurnOutSharp.FileType
{
internal class Textfile : IScannable
{
/// <inheritdoc/>
public bool ShouldScan(byte[] magic)
{
return ShouldScan(magic, null);
}
/// <summary>
/// Determine if a file signature or extension matches one of the expected values
/// </summary>
/// <param name="magic">Byte array representing the file header</param>
/// <param name="extension">Extension for the file being checked</param>
/// <returns>True if the signature is valid, false otherwise</returns>
public bool ShouldScan(byte[] magic, string extension)
{
// Rich Text File
if (magic.StartsWith(new byte?[] { 0x7b, 0x5c, 0x72, 0x74, 0x66, 0x31 }))
return true;
// HTML
if (magic.StartsWith(new byte?[] { 0x3c, 0x68, 0x74, 0x6d, 0x6c }))
return true;
// HTML and XML
if (magic.StartsWith(new byte?[] { 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45 }))
return true;
// Microsoft Office File (old)
if (magic.StartsWith(new byte?[] { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 }))
return true;
// Generic textfile (no header)
if (string.Equals(extension?.TrimStart('.'), "txt", StringComparison.OrdinalIgnoreCase))
return true;
return false;
}
/// <inheritdoc/>
public Dictionary<string, List<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 Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
// Files can be protected in multiple ways
var protections = new Dictionary<string, List<string>>();
try
{
// Load the current file content
string fileContent = null;
using (var sr = new StreamReader(stream, Encoding.Default, true, 1024 * 1024, true))
{
fileContent = sr.ReadToEnd();
}
// 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");
// MediaMax
if (fileContent.Contains("MediaMax technology"))
Utilities.AppendToDictionary(protections, file, "MediaMax CD-3");
}
catch
{
// We don't care what the error was
}
return protections;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.IO;
using SharpCompress.Compressors.Xz;
namespace BurnOutSharp.FileType
{
internal class XZ : IScannable
{
/// <inheritdoc/>
public bool ShouldScan(byte[] magic)
{
if (magic.StartsWith(new byte?[] { 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00 }))
return true;
return false;
}
/// <inheritdoc/>
public Dictionary<string, List<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 Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
// If the xz file itself fails
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (XZStream xzFile = new XZStream(stream))
{
// If an individual entry fails
try
{
string tempFile = Path.Combine(tempPath, Guid.NewGuid().ToString());
using (FileStream fs = File.OpenWrite(tempFile))
{
xzFile.CopyTo(fs);
}
}
catch { }
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return null;
}
}
}

BIN
BurnOutSharp/HLLib.x64.dll Normal file

Binary file not shown.

BIN
BurnOutSharp/HLLib.x86.dll Normal file

Binary file not shown.

View File

@@ -0,0 +1,15 @@
namespace BurnOutSharp
{
internal interface IContentCheck
{
/// <summary>
/// Check a path for protections based on file contents
/// </summary>
/// <param name="file">File to check for protection indicators</param>
/// <param name="fileContent">Byte array representing the file contents</param>
/// <param name="includePosition">True to include positional data, false otherwise</param>
/// <returns>String containing any protections found in the file</returns>
/// TODO: This should be replaced with a "GenerateMatchers" that produces a list of matchers to be run instead
string CheckContents(string file, byte[] fileContent, bool includePosition);
}
}

View File

@@ -0,0 +1,22 @@
using System.Collections.Generic;
namespace BurnOutSharp
{
internal interface IPathCheck
{
/// <summary>
/// Check a file path for protections based on path name
/// </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>
List<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>
string CheckFilePath(string path);
}
}

View File

@@ -0,0 +1,33 @@
using System.Collections.Generic;
using System.IO;
namespace BurnOutSharp
{
internal interface IScannable
{
/// <summary>
/// Determine if a file signature matches one of the expected values
/// </summary>
/// <param name="magic">Byte array representing the file header</param>
/// <returns>True if the signature is valid, false otherwise</returns>
bool ShouldScan(byte[] magic);
/// <summary>
/// Scan a file for all internal protections
/// </summary>
/// <param name="scanner">Scanner object for state tracking</param>
/// <param name="file">Path to the input file</param>
/// <returns>Dictionary mapping paths to protection lists</returns>
/// <remarks>Ideally, this should just point to the other scan implementation</remarks>
Dictionary<string, List<string>> Scan(Scanner scanner, string file);
/// <summary>
/// Scan a stream for all internal protections
/// </summary>
/// <param name="scanner">Scanner object for state tracking</param>
/// <param name="stream">Stream representing the input file</param>
/// <param name="file">Path to the input file</param>
/// <returns>Dictionary mapping paths to protection lists</returns>
Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string filename);
}
}

674
BurnOutSharp/LICENSE.txt Normal file
View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@@ -0,0 +1,99 @@
namespace BurnOutSharp.Matching
{
/// <summary>
/// Content matching criteria
/// </summary>
internal class ContentMatch : IMatch<byte?[]>
{
/// <summary>
/// Content to match
/// </summary>
public byte?[] Needle { get; set; }
/// <summary>
/// Starting index for matching
/// </summary>
public int Start { get; set; }
/// <summary>
/// Ending index for matching
/// </summary>
public int End { get; set; }
/// <summary>
/// Constructor
/// </summary>
/// <param name="needle">Byte array representing the search</param>
/// <param name="start">Optional starting index</param>
/// <param name="end">Optional ending index</param>
public ContentMatch(byte?[] needle, int start = -1, int end = -1)
{
Needle = needle;
Start = start;
End = end;
}
#region Matching
/// <summary>
/// Get if this match can be found in a stack
/// </summary>
/// <param name="stack">Array to search for the given content</param>
/// <param name="reverse">True to search from the end of the array, false from the start</param>
/// <returns>Tuple of success and found position</returns>
public (bool success, int position) Match(byte[] stack, bool reverse = false)
{
// If either array is null or empty, we can't do anything
if (stack == null || stack.Length == 0 || Needle == null || Needle.Length == 0)
return (false, -1);
// If the needle array is larger than the stack array, it can't be contained within
if (Needle.Length > stack.Length)
return (false, -1);
// 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 (EqualAt(stack, i))
return (true, i);
}
return (false, -1);
}
/// <summary>
/// Get if a stack at a certain index is equal to a needle
/// </summary>
/// <param name="stack">Array to search for the given content</param>
/// <param name="index">Starting index to check equality</param>
/// <returns>True if the needle matches the stack at a given index</returns>
private bool EqualAt(byte[] stack, int index)
{
// If the index is invalid, we can't do anything
if (index < 0)
return false;
// If we're too close to the end of the stack, return false
if (Needle.Length >= stack.Length - index)
return false;
for (int i = 0; i < Needle.Length; i++)
{
// A null value is a wildcard
if (Needle[i] == null)
continue;
else if (stack[i + index] != Needle[i])
return false;
}
return true;
}
#endregion
}
}

View File

@@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace BurnOutSharp.Matching
{
/// <summary>
/// A set of content matches that work together
/// </summary>
internal class ContentMatchSet : MatchSet<ContentMatch, byte?[]>
{
/// <summary>
/// Function to get a content version
/// </summary>
/// <remarks>
/// A content version method takes the file path, the file contents,
/// and a list of found positions and returns a single string. That
/// string is either a version string, in which case it will be appended
/// to the protection name, or `null`, in which case it will cause
/// the protection to be omitted.
/// </remarks>
public Func<string, byte[], List<int>, string> GetVersion { get; set; }
#region Constructors
public ContentMatchSet(byte?[] needle, string protectionName)
: this(new List<byte?[]> { needle }, null, protectionName) { }
public ContentMatchSet(List<byte?[]> needles, string protectionName)
: this(needles, null, protectionName) { }
public ContentMatchSet(byte?[] needle, Func<string, byte[], List<int>, string> getVersion, string protectionName)
: this(new List<byte?[]> { needle }, getVersion, protectionName) { }
public ContentMatchSet(List<byte?[]> needles, Func<string, byte[], List<int>, string> getVersion, string protectionName)
: this(needles.Select(n => new ContentMatch(n)).ToList(), getVersion, protectionName) { }
public ContentMatchSet(ContentMatch needle, string protectionName)
: this(new List<ContentMatch>() { needle }, null, protectionName) { }
public ContentMatchSet(List<ContentMatch> needles, string protectionName)
: this(needles, null, protectionName) { }
public ContentMatchSet(ContentMatch needle, Func<string, byte[], List<int>, string> getVersion, string protectionName)
: this(new List<ContentMatch>() { needle }, getVersion, protectionName) { }
public ContentMatchSet(List<ContentMatch> needles, Func<string, byte[], List<int>, string> getVersion, string protectionName)
{
Matchers = needles;
GetVersion = getVersion;
ProtectionName = protectionName;
}
#endregion
#region Matching
/// <summary>
/// Determine whether all content matches pass
/// </summary>
/// <param name="fileContent">Byte array representing the file contents</param>
/// <returns>Tuple of passing status and matching positions</returns>
public (bool, List<int>) MatchesAll(byte[] fileContent)
{
// If no content matches are defined, we fail out
if (Matchers == null || !Matchers.Any())
return (false, new List<int>());
// Initialize the position list
List<int> positions = new List<int>();
// Loop through all content matches and make sure all pass
foreach (var contentMatch in Matchers)
{
(bool match, int position) = contentMatch.Match(fileContent);
if (!match)
return (false, new List<int>());
else
positions.Add(position);
}
return (true, positions);
}
/// <summary>
/// Determine whether any content matches pass
/// </summary>
/// <param name="fileContent">Byte array representing the file contents</param>
/// <returns>Tuple of passing status and first matching position</returns>
public (bool, int) MatchesAny(byte[] fileContent)
{
// If no content matches are defined, we fail out
if (Matchers == null || !Matchers.Any())
return (false, -1);
// Loop through all content matches and make sure all pass
foreach (var contentMatch in Matchers)
{
(bool match, int position) = contentMatch.Match(fileContent);
if (match)
return (true, position);
}
return (false, -1);
}
#endregion
}
}

View File

@@ -0,0 +1,7 @@
namespace BurnOutSharp.Matching
{
internal interface IMatch<T>
{
T Needle { get; set; }
}
}

View File

@@ -0,0 +1,20 @@
using System.Collections.Generic;
namespace BurnOutSharp.Matching
{
/// <summary>
/// Wrapper for a single set of matching criteria
/// </summary>
internal abstract class MatchSet<T, U> where T : IMatch<U>
{
/// <summary>
/// Set of all matchers
/// </summary>
public IEnumerable<T> Matchers { get; set; }
/// <summary>
/// Name of the protection to show
/// </summary>
public string ProtectionName { get; set; }
}
}

View File

@@ -0,0 +1,237 @@
using System.Collections.Generic;
using System.Linq;
namespace BurnOutSharp.Matching
{
/// <summary>
/// Helper class for matching
/// </summary>
internal static class MatchUtil
{
#region Content Matching
/// <summary>
/// Get all content matches for a given list of matchers
/// </summary>
/// <param name="file">File to check for matches</param>
/// <param name="fileContent">Byte array representing the file contents</param>
/// <param name="matchers">Enumerable of ContentMatchSets to be run on the file</param>
/// <param name="includePosition">True to include positional data, false otherwise</param>
/// <returns>List of strings representing the matched protections, null or empty otherwise</returns>
public static List<string> GetAllMatches(
string file,
byte[] fileContent,
IEnumerable<ContentMatchSet> matchers,
bool includePosition = false)
{
return FindAllMatches(file, fileContent, matchers, includePosition, false);
}
/// <summary>
/// Get first content match for a given list of matchers
/// </summary>
/// <param name="file">File to check for matches</param>
/// <param name="fileContent">Byte array representing the file contents</param>
/// <param name="matchers">Enumerable of ContentMatchSets to be run on the file</param>
/// <param name="includePosition">True to include positional data, false otherwise</param>
/// <returns>String representing the matched protection, null otherwise</returns>
public static string GetFirstMatch(
string file,
byte[] fileContent,
IEnumerable<ContentMatchSet> matchers,
bool includePosition = false)
{
var contentMatches = FindAllMatches(file, fileContent, matchers, includePosition, true);
if (contentMatches == null || !contentMatches.Any())
return null;
return contentMatches.First();
}
/// <summary>
/// Get the required set of content matches on a per Matcher basis
/// </summary>
/// <param name="file">File to check for matches</param>
/// <param name="fileContent">Byte array representing the file contents</param>
/// <param name="matchers">Enumerable of ContentMatchSets to be run on the file</param>
/// <param name="includePosition">True to include positional data, false otherwise</param>
/// <param name="stopAfterFirst">True to stop after the first match, false otherwise</param>
/// <returns>List of strings representing the matched protections, null or empty otherwise</returns>
private static List<string> FindAllMatches(
string file,
byte[] fileContent,
IEnumerable<ContentMatchSet> matchers,
bool includePosition,
bool stopAfterFirst)
{
// If there's no mappings, we can't match
if (matchers == null || !matchers.Any())
return null;
// Initialize the list of matched protections
List<string> matchedProtections = new List<string>();
// Loop through and try everything otherwise
foreach (var matcher in matchers)
{
// Determine if the matcher passes
(bool passes, List<int> positions) = matcher.MatchesAll(fileContent);
if (!passes)
continue;
// Format the list of all positions found
string positionsString = string.Join(", ", positions);
// If we there is no version method, just return the protection name
if (matcher.GetVersion == null)
{
matchedProtections.Add((matcher.ProtectionName ?? "Unknown Protection") + (includePosition ? $" (Index {positionsString})" : string.Empty));
}
// Otherwise, invoke the version method
else
{
// A null version returned means the check didn't pass at the version step
string version = matcher.GetVersion(file, fileContent, positions);
if (version == null)
continue;
matchedProtections.Add($"{matcher.ProtectionName ?? "Unknown Protection"} {version}".TrimEnd() + (includePosition ? $" (Index {positionsString})" : string.Empty));
}
// If we're stopping after the first protection, bail out here
if (stopAfterFirst)
return matchedProtections;
}
return matchedProtections;
}
#endregion
#region Path Matching
/// <summary>
/// Get all path matches for a given list of matchers
/// </summary>
/// <param name="file">File path to check for matches</param>
/// <param name="matchers">Enumerable of PathMatchSets to be run on the file</param>
/// <param name="any">True if any path match is a success, false if all have to match</param>
/// <returns>List of strings representing the matched protections, null or empty otherwise</returns>
public static List<string> GetAllMatches(string file, IEnumerable<PathMatchSet> matchers, bool any = false)
{
return FindAllMatches(new List<string> { file }, matchers, any, false);
}
// <summary>
/// Get all path matches for a given list of matchers
/// </summary>
/// <param name="files">File paths to check for matches</param>
/// <param name="matchers">Enumerable of PathMatchSets to be run on the file</param>
/// <param name="any">True if any path match is a success, false if all have to match</param>
/// <returns>List of strings representing the matched protections, null or empty otherwise</returns>
public static List<string> GetAllMatches(IEnumerable<string> files, IEnumerable<PathMatchSet> matchers, bool any = false)
{
return FindAllMatches(files, matchers, any, false);
}
/// <summary>
/// Get first path match for a given list of matchers
/// </summary>
/// <param name="file">File path to check for matches</param>
/// <param name="matchers">Enumerable of PathMatchSets to be run on the file</param>
/// <param name="any">True if any path match is a success, false if all have to match</param>
/// <returns>String representing the matched protection, null otherwise</returns>
public static string GetFirstMatch(string file, IEnumerable<PathMatchSet> matchers, bool any = false)
{
var contentMatches = FindAllMatches(new List<string> { file }, matchers, any, true);
if (contentMatches == null || !contentMatches.Any())
return null;
return contentMatches.First();
}
/// <summary>
/// Get first path match for a given list of matchers
/// </summary>
/// <param name="files">File paths to check for matches</param>
/// <param name="matchers">Enumerable of PathMatchSets to be run on the file</param>
/// <param name="any">True if any path match is a success, false if all have to match</param>
/// <returns>String representing the matched protection, null otherwise</returns>
public static string GetFirstMatch(IEnumerable<string> files, IEnumerable<PathMatchSet> matchers, bool any = false)
{
var contentMatches = FindAllMatches(files, matchers, any, true);
if (contentMatches == null || !contentMatches.Any())
return null;
return contentMatches.First();
}
/// <summary>
/// Get the required set of path matches on a per Matcher basis
/// </summary>
/// <param name="files">File paths to check for matches</param>
/// <param name="matchers">Enumerable of PathMatchSets to be run on the file</param>
/// <param name="any">True if any path match is a success, false if all have to match</param>
/// <param name="stopAfterFirst">True to stop after the first match, false otherwise</param>
/// <returns>List of strings representing the matched protections, null or empty otherwise</returns>
private static List<string> FindAllMatches(IEnumerable<string> files, IEnumerable<PathMatchSet> matchers, bool any, bool stopAfterFirst)
{
// If there's no mappings, we can't match
if (matchers == null || !matchers.Any())
return new List<string>();
// Initialize the list of matched protections
List<string> matchedProtections = new List<string>();
// Loop through and try everything otherwise
foreach (var matcher in matchers)
{
// Determine if the matcher passes
bool passes;
string firstMatchedString;
if (any)
{
(bool anyPasses, string matchedString) = matcher.MatchesAny(files);
passes = anyPasses;
firstMatchedString = matchedString;
}
else
{
(bool allPasses, List<string> matchedStrings) = matcher.MatchesAll(files);
passes = allPasses;
firstMatchedString = matchedStrings.FirstOrDefault();
}
// If we don't have a pass, just continue
if (!passes)
continue;
// If we there is no version method, just return the protection name
if (matcher.GetVersion == null)
{
matchedProtections.Add(matcher.ProtectionName ?? "Unknown Protection");
}
// Otherwise, invoke the version method
else
{
// A null version returned means the check didn't pass at the version step
string version = matcher.GetVersion(firstMatchedString, files);
if (version == null)
continue;
matchedProtections.Add($"{matcher.ProtectionName ?? "Unknown Protection"} {version}".TrimEnd());
}
// If we're stopping after the first protection, bail out here
if (stopAfterFirst)
return matchedProtections;
}
return matchedProtections;
}
#endregion
}
}

View File

@@ -0,0 +1,71 @@
using System.Collections.Generic;
using System.Linq;
namespace BurnOutSharp.Matching
{
/// <summary>
/// Path matching criteria
/// </summary>
internal class PathMatch : IMatch<string>
{
/// <summary>
/// String to match
/// </summary>
public string Needle { get; set; }
/// <summary>
/// Match exact casing instead of invariant
/// </summary>
public bool MatchExact { get; set; }
/// <summary>
/// Match that values end with the needle and not just contains
/// </summary>
public bool UseEndsWith { get; set; }
/// <summary>
/// Constructor
/// </summary>
/// <param name="needle">String representing the search</param>
/// <param name="matchExact">True to match exact casing, false otherwise</param>
/// <param name="useEndsWith">True to match the end only, false for all contents</param>
public PathMatch(string needle, bool matchExact = false, bool useEndsWith = false)
{
Needle = needle;
MatchExact = matchExact;
UseEndsWith = useEndsWith;
}
#region Matching
/// <summary>
/// Get if this match can be found in a stack
/// </summary>
/// <param name="stack">List of strings to search for the given content</param>
/// <returns>Tuple of success and matched item</returns>
public (bool, string) Match(IEnumerable<string> stack)
{
// If either array is null or empty, we can't do anything
if (stack == null || !stack.Any() || Needle == null || Needle.Length == 0)
return (false, null);
// Preprocess the needle, if necessary
string procNeedle = MatchExact ? Needle : Needle.ToLowerInvariant();
foreach (string stackItem in stack)
{
// Preprocess the stack item, if necessary
string procStackItem = MatchExact ? stackItem : stackItem.ToLowerInvariant();
if (UseEndsWith && procStackItem.EndsWith(procNeedle))
return (true, stackItem);
else if (!UseEndsWith && procStackItem.Contains(procNeedle))
return (true, stackItem);
}
return (false, null);
}
#endregion
}
}

View File

@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace BurnOutSharp.Matching
{
/// <summary>
/// A set of path matches that work together
/// </summary>
internal class PathMatchSet : MatchSet<PathMatch, string>
{
/// <summary>
/// Function to get a path version for this Matcher
/// </summary>
/// <remarks>
/// A path version method takes the matched path and an enumerable of files
/// and returns a single string. That string is either a version string,
/// in which case it will be appended to the protection name, or `null`,
/// in which case it will cause the protection to be omitted.
/// </remarks>
public Func<string, IEnumerable<string>, string> GetVersion { get; set; }
#region Constructors
public PathMatchSet(string needle, string protectionName)
: this(new List<string> { needle }, null, protectionName) { }
public PathMatchSet(List<string> needles, string protectionName)
: this(needles, null, protectionName) { }
public PathMatchSet(string needle, Func<string, IEnumerable<string>, string> getVersion, string protectionName)
: this(new List<string> { needle }, getVersion, protectionName) { }
public PathMatchSet(List<string> needles, Func<string, IEnumerable<string>, string> getVersion, string protectionName)
: this(needles.Select(n => new PathMatch(n)).ToList(), getVersion, protectionName) { }
public PathMatchSet(PathMatch needle, string protectionName)
: this(new List<PathMatch>() { needle }, null, protectionName) { }
public PathMatchSet(List<PathMatch> needles, string protectionName)
: this(needles, null, protectionName) { }
public PathMatchSet(PathMatch needle, Func<string, IEnumerable<string>, string> getVersion, string protectionName)
: this(new List<PathMatch>() { needle }, getVersion, protectionName) { }
public PathMatchSet(List<PathMatch> needles, Func<string, IEnumerable<string>, string> getVersion, string protectionName)
{
Matchers = needles;
GetVersion = getVersion;
ProtectionName = protectionName;
}
#endregion
#region Matching
/// <summary>
/// Determine whether all path matches pass
/// </summary>
/// <param name="stack">List of strings to try to match</param>
/// <returns>Tuple of passing status and matching values</returns>
public (bool, List<string>) MatchesAll(IEnumerable<string> stack)
{
// If no path matches are defined, we fail out
if (Matchers == null || !Matchers.Any())
return (false, new List<string>());
// Initialize the value list
List<string> values = new List<string>();
// Loop through all path matches and make sure all pass
foreach (var pathMatch in Matchers)
{
(bool match, string value) = pathMatch.Match(stack);
if (!match)
return (false, new List<string>());
else
values.Add(value);
}
return (true, values);
}
/// <summary>
/// Determine whether any path matches pass
/// </summary>
/// <param name="stack">List of strings to try to match</param>
/// <returns>Tuple of passing status and first matching value</returns>
public (bool, string) MatchesAny(IEnumerable<string> stack)
{
// If no path matches are defined, we fail out
if (Matchers == null || !Matchers.Any())
return (false, null);
// Loop through all path matches and make sure all pass
foreach (var pathMatch in Matchers)
{
(bool match, string value) = pathMatch.Match(stack);
if (match)
return (true, value);
}
return (false, null);
}
#endregion
}
}

View File

@@ -0,0 +1,31 @@
using System.Collections.Generic;
using BurnOutSharp.Matching;
namespace BurnOutSharp.PackerType
{
// TODO: Add extraction and verify that all versions are detected
public class AdvancedInstaller : IContentCheck
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = new List<ContentMatchSet>
{
// Software\Caphyon\Advanced Installer
new ContentMatchSet(new byte?[]
{
0x53, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
0x5C, 0x43, 0x61, 0x70, 0x68, 0x79, 0x6F, 0x6E,
0x5C, 0x41, 0x64, 0x76, 0x61, 0x6E, 0x63, 0x65,
0x64, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6C,
0x6C, 0x65, 0x72
}, "Caphyon Advanced Installer"),
};
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
}
}

View File

@@ -0,0 +1,26 @@
using System.Collections.Generic;
using BurnOutSharp.Matching;
namespace BurnOutSharp.PackerType
{
public class Armadillo : IContentCheck
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = new List<ContentMatchSet>
{
// .nicode + (char)0x00
new ContentMatchSet(new byte?[] { 0x2E, 0x6E, 0x69, 0x63, 0x6F, 0x64, 0x65, 0x00 }, "Armadillo"),
// ARMDEBUG
new ContentMatchSet(new byte?[] { 0x41, 0x52, 0x4D, 0x44, 0x45, 0x42, 0x55, 0x47 }, "Armadillo"),
};
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
}
}

View File

@@ -0,0 +1,57 @@
using System.Collections.Generic;
using System.IO;
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
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = 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 ContentMatch(new byte?[]
{
0x25, 0x57, 0x6F, 0xC1, 0x61, 0x36, 0x01, 0x92,
0x61, 0x36, 0x01, 0x92, 0x61, 0x36, 0x01, 0x92,
0x61, 0x36, 0x00, 0x92, 0x7B, 0x36, 0x01, 0x92,
0x03, 0x29, 0x12, 0x92, 0x66, 0x36, 0x01, 0x92,
0x89, 0x29, 0x0A, 0x92, 0x60, 0x36, 0x01, 0x92,
0xD9, 0x30, 0x07, 0x92, 0x60, 0x36, 0x01, 0x92
}, end: 200), "CExe"),
};
/// <inheritdoc/>
public bool ShouldScan(byte[] magic) => true;
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
/// <inheritdoc/>
public Dictionary<string, List<string>> Scan(Scanner scanner, string file)
{
if (!File.Exists(file))
return null;
using (var fs = File.OpenRead(file))
{
return Scan(scanner, fs, file);
}
}
/// <inheritdoc/>
// TODO: Add extraction if viable
public Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
return null;
}
}
}

View File

@@ -0,0 +1,30 @@
using System.Collections.Generic;
using BurnOutSharp.Matching;
namespace BurnOutSharp.PackerType
{
public class EXEStealth : IContentCheck
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = 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"),
};
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
}
}

View File

@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BurnOutSharp.Matching;
namespace BurnOutSharp.PackerType
{
public class InnoSetup : IContentCheck, IScannable
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = new List<ContentMatchSet>
{
// Inno
new ContentMatchSet(
new ContentMatch(new byte?[] { 0x49, 0x6E, 0x6E, 0x6F }, start: 0x30, end: 0x31),
GetVersion,
"Inno Setup"),
};
/// <inheritdoc/>
public bool ShouldScan(byte[] magic) => true;
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
/// <inheritdoc/>
public Dictionary<string, List<string>> Scan(Scanner scanner, string file)
{
if (!File.Exists(file))
return null;
using (var fs = File.OpenRead(file))
{
return Scan(scanner, fs, file);
}
}
// TOOO: Add Inno Setup extraction
// https://github.com/dscharrer/InnoExtract
/// <inheritdoc/>
public Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
return null;
}
public static string GetVersion(string file, byte[] fileContent, List<int> positions)
{
byte[] signature = new ArraySegment<byte>(fileContent, 0x30, 12).ToArray();
// "rDlPtS02" + (char)0x87 + "eVx"
if (signature.SequenceEqual( new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x32, 0x87, 0x65, 0x56, 0x78 }))
return "1.2.10";
// "rDlPtS04" + (char)0x87 + "eVx"
else if (signature.SequenceEqual(new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x34, 0x87, 0x65, 0x56, 0x78 }))
return "4.0.0";
// "rDlPtS05" + (char)0x87 + "eVx"
else if (signature.SequenceEqual(new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x35, 0x87, 0x65, 0x56, 0x78 }))
return "4.0.3";
// "rDlPtS06" + (char)0x87 + "eVx"
else if (signature.SequenceEqual(new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x36, 0x87, 0x65, 0x56, 0x78 }))
return "4.0.10";
// "rDlPtS07" + (char)0x87 + "eVx"
else if (signature.SequenceEqual(new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x37, 0x87, 0x65, 0x56, 0x78 }))
return "4.1.6";
// "rDlPtS" + (char)0xcd + (char)0xe6 + (char)0xd7 + "{" + (char)0x0b + "*"
else if (signature.SequenceEqual(new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0xCD, 0xE6, 0xD7, 0x7B, 0x0b, 0x2A }))
return "5.1.5";
// "nS5W7dT" + (char)0x83 + (char)0xaa + (char)0x1b + (char)0x0f + "j"
else if (signature.SequenceEqual(new byte[] { 0x6E, 0x53, 0x35, 0x57, 0x37, 0x64, 0x54, 0x83, 0xAA, 0x1B, 0x0F, 0x6A }))
return "5.1.5";
return string.Empty;
}
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BurnOutSharp.Matching;
namespace BurnOutSharp.PackerType
{
public class NSIS : IContentCheck
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = new List<ContentMatchSet>
{
// Nullsoft Install System
new ContentMatchSet(new byte?[]
{
0x4e, 0x75, 0x6c, 0x6c, 0x73, 0x6f, 0x66, 0x74,
0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d
}, GetVersion, "NSIS"),
// NullsoftInst
new ContentMatchSet(new byte?[]
{
0x4e, 0x75, 0x6c, 0x6c, 0x73, 0x6f, 0x66, 0x74,
0x49, 0x6e, 0x73, 0x74
}, "NSIS"),
};
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
public static string GetVersion(string file, byte[] fileContent, List<int> positions)
{
try
{
int index = positions[0];
index += 24;
if (fileContent[index] != 'v')
return "(Unknown Version)";
var versionBytes = new ReadOnlySpan<byte>(fileContent, index, 16).ToArray();
var onlyVersion = versionBytes.TakeWhile(b => b != '<').ToArray();
return Encoding.ASCII.GetString(onlyVersion);
}
catch
{
return "(Unknown Version)";
}
}
}
}

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using BurnOutSharp.Matching;
namespace BurnOutSharp.PackerType
{
// TODO: Add extraction and better version detection
public class PECompact : IContentCheck
{
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
// Another possible version string for version 1 is "PECO" (50 45 43 4F)
var matchers = new List<ContentMatchSet>
{
// pec1
new ContentMatchSet(new ContentMatch(new byte?[] { 0x70, 0x65, 0x63, 0x31 }, end: 2048), "PE Compact 1"),
// PEC2
new ContentMatchSet(new ContentMatch(new byte?[] { 0x50, 0x45, 0x43, 0x32 }, end: 2048), GetVersion, "PE Compact 2"),
// PECompact2
new ContentMatchSet(new byte?[]
{
0x50, 0x45, 0x43, 0x6F, 0x6D, 0x70, 0x61, 0x63,
0x74, 0x32
}, "PE Compact 2"),
};
return MatchUtil.GetFirstMatch(file, fileContent, matchers, includePosition);
}
public static string GetVersion(string file, byte[] fileContent, List<int> positions)
{
return $"v{BitConverter.ToInt16(fileContent, positions[0] + 4)}";
}
}
}

View File

@@ -0,0 +1,10 @@
namespace BurnOutSharp.PackerType
{
public class Petite
{
/*
* Possible strings for PEtite Win32 Executable Compressor (Unknown how to get version)
* - petite - 40 70 65 74 69 74 65 (Made with Version 2.4, Compression Level 1-9)
*/
}
}

View File

@@ -0,0 +1,88 @@
using System.Collections.Generic;
using System.IO;
using BurnOutSharp.Matching;
namespace BurnOutSharp.PackerType
{
public class SetupFactory : IContentCheck, IScannable
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = new List<ContentMatchSet>
{
// S.e.t.u.p. .F.a.c.t.o.r.y.
new ContentMatchSet(new byte?[]
{
0x53, 0x00, 0x65, 0x00, 0x74, 0x00, 0x75, 0x00,
0x70, 0x00, 0x20, 0x00, 0x46, 0x00, 0x61, 0x00,
0x63, 0x00, 0x74, 0x00, 0x6F, 0x00, 0x72, 0x00,
0x79, 0x00
}, GetVersion, "Setup Factory"),
// Longer version of the check that can be used if false positves become an issue:
// S.e.t.u.p. .F.a.c.t.o.r.y. .i.s. .a. .t.r.a.d.e.m.a.r.k. .o.f. .I.n.d.i.g.o. .R.o.s.e. .C.o.r.p.o.r.a.t.i.o.n.
// new ContentMatchSet(new byte?[]
// {
// 0x53, 0x00, 0x65, 0x00, 0x74, 0x00, 0x75, 0x00,
// 0x70, 0x00, 0x20, 0x00, 0x46, 0x00, 0x61, 0x00,
// 0x63, 0x00, 0x74, 0x00, 0x6F, 0x00, 0x72, 0x00,
// 0x79, 0x00, 0x20, 0x00, 0x69, 0x00, 0x73, 0x00,
// 0x20, 0x00, 0x61, 0x00, 0x20, 0x00, 0x74, 0x00,
// 0x72, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00,
// 0x6D, 0x00, 0x61, 0x00, 0x72, 0x00, 0x6B, 0x00,
// 0x20, 0x00, 0x6F, 0x00, 0x66, 0x00, 0x20, 0x00,
// 0x49, 0x00, 0x6E, 0x00, 0x64, 0x00, 0x69, 0x00,
// 0x67, 0x00, 0x6F, 0x00, 0x20, 0x00, 0x52, 0x00,
// 0x6F, 0x00, 0x73, 0x00, 0x65, 0x00, 0x20, 0x00,
// 0x43, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x70, 0x00,
// 0x6F, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00,
// 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00
// }, GetVersion, "Setup Factory"),
};
/// <inheritdoc/>
public bool ShouldScan(byte[] magic) => true;
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
/// <inheritdoc/>
public Dictionary<string, List<string>> Scan(Scanner scanner, string file)
{
if (!File.Exists(file))
return null;
using (var fs = File.OpenRead(file))
{
return Scan(scanner, fs, file);
}
}
/// <inheritdoc/>
// TODO: Add extraction, which is possible but the only tools available that can
// do this seem to be Universal Extractor 2 and InstallExplorer (https://totalcmd.net/plugring/InstallExplorer.html)
public Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
return null;
}
public static string GetVersion(string file, byte[] fileContent, List<int> positions)
{
// Check the manifest version first
string version = Utilities.GetManifestVersion(fileContent);
if (!string.IsNullOrEmpty(version))
return version;
// Then check the file version
version = Utilities.GetFileVersion(file);
if (!string.IsNullOrEmpty(version))
return version;
return "(Unknown Version)";
}
}
}

View File

@@ -0,0 +1,69 @@
using System.Collections.Generic;
using System.Text;
using BurnOutSharp.Matching;
namespace BurnOutSharp.PackerType
{
public class UPX : IContentCheck
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = new List<ContentMatchSet>
{
// UPX!
new ContentMatchSet(new byte?[] { 0x55, 0x50, 0x58, 0x21 }, GetVersion, "UPX"),
// NOS
new ContentMatchSet(new byte?[] { 0x4E, 0x4F, 0x53, 0x20 }, GetVersion, "UPX (NOS Variant)"),
new ContentMatchSet(
new List<byte?[]>
{
// UPX0
new byte?[] { 0x55, 0x50, 0x58, 0x30 },
// UPX1
new byte?[] { 0x55, 0x50, 0x58, 0x31 },
},
"UPX (Unknown Version)"
),
new ContentMatchSet(
new List<byte?[]>
{
// NOS0
new byte?[] { 0x4E, 0x4F, 0x53, 0x30 },
// NOS1
new byte?[] { 0x4E, 0x4F, 0x53, 0x31 },
},
"UPX (NOS Variant) (Unknown Version)"
),
};
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
public static string GetVersion(string file, byte[] fileContent, List<int> positions)
{
try
{
int index = positions[0];
index -= 5;
string versionString = Encoding.ASCII.GetString(fileContent, index, 4);
if (!char.IsNumber(versionString[0]))
return "(Unknown Version)";
return versionString;
}
catch
{
return "(Unknown Version)";
}
}
}
}

View File

@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.IO;
using BurnOutSharp.Matching;
using SharpCompress.Archives;
using SharpCompress.Archives.Rar;
namespace BurnOutSharp.PackerType
{
public class WinRARSFX : IContentCheck, IScannable
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = new List<ContentMatchSet>
{
// Software\WinRAR SFX
new ContentMatchSet(new byte?[]
{
0x53, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
0x5C, 0x57, 0x69, 0x6E, 0x52, 0x41, 0x52, 0x20,
0x53, 0x46, 0x58
}, "WinRAR SFX"),
};
/// <inheritdoc/>
public bool ShouldScan(byte[] magic) => true;
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
public Dictionary<string, List<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 Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
// If the rar file itself fails
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// Should be using stream instead of file, but stream fails to extract anything. My guess is that the executable portion of the archive is causing stream to fail, but not file.
using (RarArchive zipFile = RarArchive.Open(file, new SharpCompress.Readers.ReaderOptions() {LookForHeader = true}))
{
foreach (var entry in zipFile.Entries)
{
// If an individual entry fails
try
{
// If we have a directory, skip it
if (entry.IsDirectory)
continue;
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch { }
}
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return null;
}
}
}

View File

@@ -0,0 +1,391 @@
using System;
using System.Collections.Generic;
using System.IO;
using BurnOutSharp.Matching;
using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
namespace BurnOutSharp.PackerType
{
public class WinZipSFX : IContentCheck, IScannable
{
/// <inheritdoc/>
public bool ShouldScan(byte[] magic) => true;
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
var matchers = new List<ContentMatchSet>
{
// WinZip Self-Extractor
new ContentMatchSet(new byte?[]
{
0x57, 0x69, 0x6E, 0x5A, 0x69, 0x70, 0x20, 0x53,
0x65, 0x6C, 0x66, 0x2D, 0x45, 0x78, 0x74, 0x72,
0x61, 0x63, 0x74, 0x6F, 0x72
}, GetVersion, "WinZip SFX"),
// _winzip_
new ContentMatchSet(new byte?[] { 0x5F, 0x77, 0x69, 0x6E, 0x7A, 0x69, 0x70, 0x5F }, GetVersion, "WinZip SFX"),
};
return MatchUtil.GetFirstMatch(file, fileContent, matchers, includePosition);
}
/// <inheritdoc/>
public Dictionary<string, List<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 Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
// If the zip file itself fails
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// Should be using stream instead of file, but stream fails to extract anything. My guess is that the executable portion of the archive is causing stream to fail, but not file.
using (ZipArchive zipFile = ZipArchive.Open(file))
{
foreach (var entry in zipFile.Entries)
{
// If an individual entry fails
try
{
// If we have a directory, skip it
if (entry.IsDirectory)
continue;
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch { }
}
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return null;
}
public static string GetVersion(string file, byte[] fileContent, List<int> positions)
{
// Check the manifest version first
string version = Utilities.GetManifestVersion(fileContent);
if (!string.IsNullOrEmpty(version))
return GetV3PlusVersion(version);
// Assume an earlier version
return GetV2Version(file, fileContent);
}
private static string GetV2Version(string file, byte[] fileContent)
{
var matchers = new List<ContentMatchSet>
{
#region 16-bit NE Header Checks
new ContentMatchSet(new byte?[]
{
0x4E, 0x45, 0x11, 0x20, 0x86, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x03, 0x03, 0x00,
0x00, 0x20, 0x00, 0x40, 0xE6, 0x2B, 0x01, 0x00,
0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00,
0x4B, 0x00, 0x40, 0x00, 0x58, 0x00, 0x58, 0x00,
0x64, 0x00, 0x6C, 0x00, 0xB8, 0x44, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
}, "2.0 (MS-DOS/16-bit)"),
new ContentMatchSet(new byte?[]
{
0x4E, 0x45, 0x11, 0x20, 0x86, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x03, 0x03, 0x00,
0x00, 0x20, 0x00, 0x40, 0x74, 0x31, 0x01, 0x00,
0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00,
0x4B, 0x00, 0x40, 0x00, 0x58, 0x00, 0x58, 0x00,
0x64, 0x00, 0x6C, 0x00, 0x98, 0x01, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
}, "2.0 (16-bit)"),
new ContentMatchSet(new byte?[]
{
0x4E, 0x45, 0x11, 0x20, 0x80, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x03, 0x03, 0x00,
0x00, 0x20, 0x00, 0x40, 0xA0, 0x24, 0x01, 0x00,
0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
0x4B, 0x00, 0x40, 0x00, 0x58, 0x00, 0x58, 0x00,
0x64, 0x00, 0x6A, 0x00, 0x92, 0x01, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
}, "Compact 2.0 (16-bit)"),
new ContentMatchSet(new byte?[]
{
0x4E, 0x45, 0x11, 0x20, 0xCD, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x03, 0x00,
0x00, 0x20, 0x00, 0x40, 0xFA, 0x36, 0x01, 0x00,
0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x05, 0x00,
0x4B, 0x00, 0x40, 0x00, 0x58, 0x00, 0x97, 0x00,
0xA3, 0x00, 0xAD, 0x00, 0xDF, 0x01, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
}, "Software Installation 2.0 (16-bit)"),
new ContentMatchSet(new byte?[]
{
0x4E, 0x45, 0x11, 0x20, 0x86, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x03, 0x03, 0x00,
0x00, 0x20, 0x00, 0x40, 0x86, 0x33, 0x01, 0x00,
0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00,
0x4B, 0x00, 0x40, 0x00, 0x58, 0x00, 0x58, 0x00,
0x64, 0x00, 0x6C, 0x00, 0xC8, 0x43, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
}, "2.1 RC2 (MS-DOS/16-bit)"),
new ContentMatchSet(new byte?[]
{
0x4E, 0x45, 0x11, 0x20, 0xBE, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x03, 0x00,
0x00, 0x20, 0x00, 0x40, 0x56, 0x3E, 0x01, 0x00,
0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00,
0x4B, 0x00, 0x40, 0x00, 0x58, 0x00, 0x90, 0x00,
0x9C, 0x00, 0xA4, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
}, "2.1 RC2 (16-bit)"),
new ContentMatchSet(new byte?[]
{
0x4E, 0x45, 0x11, 0x20, 0x80, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x03, 0x03, 0x00,
0x00, 0x20, 0x00, 0x40, 0x84, 0x2B, 0x01, 0x00,
0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
0x4B, 0x00, 0x40, 0x00, 0x58, 0x00, 0x58, 0x00,
0x64, 0x00, 0x6A, 0x00, 0x92, 0x01, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
}, "Compact 2.1 RC2 (16-bit)"),
new ContentMatchSet(new byte?[]
{
0x4E, 0x45, 0x11, 0x20, 0xBE, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x03, 0x00,
0x00, 0x20, 0x00, 0x40, 0xAC, 0x43, 0x01, 0x00,
0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00,
0x4B, 0x00, 0x40, 0x00, 0x58, 0x00, 0x90, 0x00,
0x9C, 0x00, 0xA4, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
}, "Software Installation 2.1 RC2 (16-bit)"),
new ContentMatchSet(new byte?[]
{
0x4E, 0x45, 0x11, 0x20, 0x86, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x03, 0x03, 0x00,
0x00, 0x20, 0x00, 0x3A, 0x96, 0x33, 0x01, 0x00,
0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00,
0x4B, 0x00, 0x40, 0x00, 0x58, 0x00, 0x58, 0x00,
0x64, 0x00, 0x6C, 0x00, 0xC8, 0x43, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
}, "2.1 (MS-DOS/16-bit)"),
new ContentMatchSet(new byte?[]
{
0x4E, 0x45, 0x11, 0x20, 0xBE, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x03, 0x00,
0x00, 0x20, 0x00, 0x3A, 0x7E, 0x3E, 0x01, 0x00,
0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00,
0x4B, 0x00, 0x40, 0x00, 0x58, 0x00, 0x90, 0x00,
0x9C, 0x00, 0xA4, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
}, "2.1 (16-bit)"),
new ContentMatchSet(new byte?[]
{
0x4E, 0x45, 0x11, 0x20, 0x80, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x03, 0x03, 0x00,
0x00, 0x20, 0x00, 0x3A, 0x90, 0x2B, 0x01, 0x00,
0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
0x4B, 0x00, 0x40, 0x00, 0x58, 0x00, 0x58, 0x00,
0x64, 0x00, 0x6A, 0x00, 0x92, 0x01, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
}, "Compact 2.1 (16-bit)"),
new ContentMatchSet(new byte?[]
{
0x4E, 0x45, 0x11, 0x20, 0xBE, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x03, 0x00,
0x00, 0x20, 0x00, 0x3A, 0x08, 0x44, 0x01, 0x00,
0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00,
0x4B, 0x00, 0x40, 0x00, 0x58, 0x00, 0x90, 0x00,
0x9C, 0x00, 0xA4, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
}, "Software Installation 2.1 (16-bit)"),
#endregion
#region 32-bit SFX Header Checks
// .............8<EFBFBD>92....<2E>P..............<2E>P..<2E>P..<2E>P..VW95SE.SFX
new ContentMatchSet(new byte?[]
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x9C, 0x39,
0x32, 0x00, 0x00, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x88, 0x50, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x56, 0x57, 0x39, 0x35, 0x53, 0x45, 0x2E,
0x53, 0x46, 0x58,
}, "2.0 (32-bit)"),
// .............]<5D>92....<2E>P..............<2E>P..<2E>P..<2E>P..VW95SRE.SFX
new ContentMatchSet(new byte?[]
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x9C, 0x39,
0x32, 0x00, 0x00, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x88, 0x50, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x56, 0x57, 0x39, 0x35, 0x53, 0x52, 0x45,
0x2E, 0x53, 0x46, 0x58,
}, "Software Installation 2.0 (32-bit)"),
// .............<2E><><EFBFBD>3....<2E>P..............<2E>P..<2E>P..<2E>P..VW95SE.SFX
new ContentMatchSet(new byte?[]
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x82, 0x94,
0x33, 0x00, 0x00, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x88, 0x50, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x56, 0x57, 0x39, 0x35, 0x53, 0x45, 0x2E,
0x53, 0x46, 0x58,
}, "2.1 RC2 (32-bit)"),
// .............<2E><><EFBFBD>3....<2E>P..............<2E>P..<2E>P..<2E>P..VW95SRE.SFX
new ContentMatchSet(new byte?[]
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x82, 0x94,
0x33, 0x00, 0x00, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x88, 0x50, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x56, 0x57, 0x39, 0x35, 0x53, 0x52, 0x45,
0x2E, 0x53, 0x46, 0x58,
}, "Software Installation 2.1 RC2 (32-bit)"),
// .............U<><55>3....<2E>P..............<2E>P..<2E>P..<2E>P..VW95SE.SFX
new ContentMatchSet(new byte?[]
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xCD, 0xCC,
0x33, 0x00, 0x00, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x88, 0x50, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x56, 0x57, 0x39, 0x35, 0x53, 0x45, 0x2E,
0x53, 0x46, 0x58,
}, "2.1 (32-bit)"),
// .............{<7B><>3....<2E>P..............<2E>P..<2E>P..<2E>P..VW95SRE.SFX
new ContentMatchSet(new byte?[]
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7B, 0xCD, 0xCC,
0x33, 0x00, 0x00, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x88, 0x50, 0x00, 0x00, 0x88, 0x50, 0x00,
0x00, 0x56, 0x57, 0x39, 0x35, 0x53, 0x52, 0x45,
0x2E, 0x53, 0x46, 0x58,
}, "Software Installation 2.1 (32-bit)"),
#endregion
#region 32-bit PE Header Checks
new ContentMatchSet(new byte?[]
{
0x50, 0x45, 0x00, 0x00, 0x4C, 0x01, 0x05, 0x00,
0x69, 0x1B, 0x5B, 0x3A, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x0F, 0x01,
0x0B, 0x01, 0x05, 0x0A, 0x00, 0x4A, 0x00, 0x00,
0x00, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xD8, 0x39, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
}, "2.2.4003"),
new ContentMatchSet(new byte?[]
{
0x50, 0x45, 0x00, 0x00, 0x4C, 0x01, 0x05, 0x00,
0x81, 0x1B, 0x5B, 0x3A, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x0F, 0x01,
0x0B, 0x01, 0x05, 0x0A, 0x00, 0x56, 0x00, 0x00,
0x00, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x8F, 0x3F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
}, "Software Installation 2.2.4003"),
#endregion
};
string match = MatchUtil.GetFirstMatch(file, fileContent, matchers, false);
return match ?? "Unknown 2.x";
}
private static string GetV3PlusVersion(string version)
{
// Some version strings don't exactly match the public version number
switch (version)
{
case "3.0.7158.0":
return "3.0.7158";
case "3.1.7556.0":
return "3.1.7556";
case "3.1.8421.0":
return "4.0.8421";
case "3.1.8672.0":
return "4.0.8672";
case "4.0.1221.0":
return "4.0.12218";
default:
return $"(Unknown - {version})";
}
}
}
}

View File

@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.IO;
using BurnOutSharp.Matching;
using Wise = WiseUnpacker.WiseUnpacker;
namespace BurnOutSharp.PackerType
{
public class WiseInstaller : IContentCheck, IScannable
{
/// <inheritdoc/>
public bool ShouldScan(byte[] magic) => true;
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
var matchers = new List<ContentMatchSet>
{
// WiseMain
new ContentMatchSet(new byte?[] { 0x57, 0x69, 0x73, 0x65, 0x4D, 0x61, 0x69, 0x6E }, "Wise Installation Wizard Module"),
};
return MatchUtil.GetFirstMatch(file, fileContent, matchers, includePosition);
}
/// <inheritdoc/>
public Dictionary<string, List<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 Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file)
{
// If the installer file itself fails
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
Wise unpacker = new Wise();
unpacker.ExtractTo(file, tempPath);
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return null;
}
}
}

View File

@@ -0,0 +1,28 @@
using System.Collections.Generic;
using BurnOutSharp.Matching;
namespace BurnOutSharp.PackerType
{
public class dotFuscator : IContentCheck
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = new List<ContentMatchSet>
{
// DotfuscatorAttribute
new ContentMatchSet(new byte?[]
{
0x44, 0x6F, 0x74, 0x66, 0x75, 0x73, 0x63, 0x61,
0x74, 0x6F, 0x72, 0x41, 0x74, 0x74, 0x72, 0x69,
0x62, 0x75, 0x74, 0x65
}, "dotFuscator"),
};
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
}
}

View File

@@ -0,0 +1,16 @@
namespace BurnOutSharp
{
public class ProtectionProgress
{
public string Filename { get; private set; }
public float Percentage { get; private set; }
public string Protection { get; private set; }
public ProtectionProgress(string filename, float percentage, string protection)
{
this.Filename = filename;
this.Percentage = percentage;
this.Protection = protection;
}
}
}

View File

@@ -0,0 +1,58 @@
using System.Collections.Generic;
using System.IO;
using BurnOutSharp.Matching;
namespace BurnOutSharp.ProtectionType
{
public class AACS : IPathCheck
{
/// <inheritdoc/>
public List<string> CheckDirectoryPath(string path, IEnumerable<string> files)
{
var matchers = new List<PathMatchSet>
{
// BD-ROM
new PathMatchSet(Path.Combine("AACS", "MKB_RO.inf"), GetVersion, "AACS"),
// HD-DVD
new PathMatchSet(Path.Combine("AACS", "MKBROM.AACS"), GetVersion, "AACS"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
// BD-ROM
new PathMatchSet(new PathMatch("MKB_RO.inf", useEndsWith: true), GetVersion, "AACS"),
// HD-DVD
new PathMatchSet(new PathMatch("MKBROM.AACS", useEndsWith: true), GetVersion, "AACS"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
public static string GetVersion(string firstMatchedString, IEnumerable<string> files)
{
if (!File.Exists(firstMatchedString))
return "(Unknown Version)";
try
{
using (var fs = File.OpenRead(firstMatchedString))
{
fs.Seek(0xB, SeekOrigin.Begin);
return fs.ReadByte().ToString();
}
}
catch
{
return "(Unknown Version)";
}
}
}
}

View File

@@ -0,0 +1,31 @@
using System.Collections.Generic;
using BurnOutSharp.Matching;
namespace BurnOutSharp.ProtectionType
{
public class ActiveMARK : IContentCheck
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = new List<ContentMatchSet>
{
// TMSAMVOF
new ContentMatchSet(new byte?[] { 0x54, 0x4D, 0x53, 0x41, 0x4D, 0x56, 0x4F, 0x46 }, "ActiveMARK"),
// " " + (char)0xC2 + (char)0x16 + (char)0x00 + (char)0xA8 + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0xB8 + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0x86 + (char)0xC8 + (char)0x16 + (char)0x00 + (char)0x9A + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0x10 + (char)0xC2 + (char)0x16 + (char)0x00
new ContentMatchSet(new byte?[]
{
0x20, 0xC2, 0x16, 0x00, 0xA8, 0xC1, 0x16, 0x00,
0xB8, 0xC1, 0x16, 0x00, 0x86, 0xC8, 0x16, 0x00,
0x9A, 0xC1, 0x16, 0x00, 0x10, 0xC2, 0x16, 0x00
}, "ActiveMARK 5"),
};
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
}
}

View File

@@ -0,0 +1,7 @@
namespace BurnOutSharp.ProtectionType
{
public class Alcatraz
{
// TODO: Implement - http://www.kdg-mt.com/1/product_d_6.html
}
}

View File

@@ -0,0 +1,7 @@
namespace BurnOutSharp.ProtectionType
{
public class AlphaAudio
{
// TODO: Implement - http://settec.net/eng/pro_cd.html
}
}

View File

@@ -0,0 +1,30 @@
using System.Collections.Generic;
using BurnOutSharp.Matching;
namespace BurnOutSharp.ProtectionType
{
public class AlphaDVD : IPathCheck
{
/// <inheritdoc/>
public List<string> CheckDirectoryPath(string path, IEnumerable<string> files)
{
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("PlayDVD.exe", useEndsWith: true), "Alpha-DVD"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("PlayDVD.exe", useEndsWith: true), "Alpha-DVD"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

@@ -0,0 +1,23 @@
using System.Collections.Generic;
using BurnOutSharp.Matching;
namespace BurnOutSharp.ProtectionType
{
public class AlphaROM : IContentCheck
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = new List<ContentMatchSet>
{
// SETTEC
new ContentMatchSet(new byte?[] { 0x53, 0x45, 0x54, 0x54, 0x45, 0x43 }, "Alpha-ROM"),
};
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
}
}

View File

@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BurnOutSharp.Matching;
namespace BurnOutSharp.ProtectionType
{
public class BDPlus : IPathCheck
{
/// <inheritdoc/>
public List<string> CheckDirectoryPath(string path, IEnumerable<string> files)
{
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new List<string>
{
Path.Combine("BDSVM", "00000.svm"),
Path.Combine("BDSVM", "BACKUP", "00000.svm"),
}, GetVersion, "BD+"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("00000.svm", useEndsWith: true), GetVersion, "BD+"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
/// <remarks>
/// Version detection logic from libbdplus was used to implement this
/// </remarks>
public static string GetVersion(string firstMatchedString, IEnumerable<string> files)
{
if (!File.Exists(firstMatchedString))
return "(Unknown Version)";
try
{
using (var fs = File.OpenRead(firstMatchedString))
{
fs.Seek(0x0D, SeekOrigin.Begin);
byte[] date = new byte[4];
fs.Read(date, 0, 4); //yymd
short year = BitConverter.ToInt16(date.Reverse().ToArray(), 2);
// Do some rudimentary date checking
if (year < 2006 || year > 2100 || date[2] < 1 || date[2] > 12 || date[3] < 1 || date[3] > 31)
return "(Invalid Version)";
return $"{year:0000}/{date[2]:00}/{date[3]:00}";
}
}
catch
{
return "(Unknown Version)";
}
}
}
}

View File

@@ -0,0 +1,30 @@
using System.Collections.Generic;
using BurnOutSharp.Matching;
namespace BurnOutSharp.ProtectionType
{
public class Bitpool : IPathCheck
{
/// <inheritdoc/>
public List<string> CheckDirectoryPath(string path, IEnumerable<string> files)
{
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("bitpool.rsc", useEndsWith: true), "Bitpool"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("bitpool.rsc", useEndsWith: true), "Bitpool"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

@@ -0,0 +1,32 @@
using System.Collections.Generic;
using BurnOutSharp.Matching;
namespace BurnOutSharp.ProtectionType
{
public class ByteShield : IPathCheck
{
/// <inheritdoc/>
public List<string> CheckDirectoryPath(string path, IEnumerable<string> files)
{
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("Byteshield.dll", useEndsWith: true), "ByteShield"),
new PathMatchSet(new PathMatch(".bbz", useEndsWith: true), "ByteShield"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("Byteshield.dll", useEndsWith: true), "ByteShield"),
new PathMatchSet(new PathMatch(".bbz", useEndsWith: true), "ByteShield"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

@@ -0,0 +1,54 @@
using System.Collections.Generic;
using BurnOutSharp.Matching;
namespace BurnOutSharp.ProtectionType
{
public class CDCheck : IContentCheck
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = new List<ContentMatchSet>
{
// MGS CDCheck
new ContentMatchSet(new byte?[]
{
0x4D, 0x47, 0x53, 0x20, 0x43, 0x44, 0x43, 0x68,
0x65, 0x63, 0x6B
}, "Microsoft Game Studios CD Check"),
// CDCheck
new ContentMatchSet(new byte?[] { 0x43, 0x44, 0x43, 0x68, 0x65, 0x63, 0x6B }, "Executable-Based CD Check"),
};
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
// These content checks are too broad to be useful
private static string CheckContentsBroad(string file, byte[] fileContent, bool includePosition = false)
{
var matchers = new List<ContentMatchSet>
{
// GetDriveType
new ContentMatchSet(new byte?[]
{
0x47, 0x65, 0x74, 0x44, 0x72, 0x69, 0x76, 0x65,
0x54, 0x79, 0x70, 0x65
}, "Executable-Based CD Check"),
// GetVolumeInformation
new ContentMatchSet(new byte?[]
{
0x47, 0x65, 0x74, 0x56, 0x6F, 0x6C, 0x75, 0x6D,
0x65, 0x49, 0x6E, 0x66, 0x6F, 0x72, 0x6D, 0x61,
0x74, 0x69, 0x6F, 0x6E
}, "Executable-Based CD Check"),
};
return MatchUtil.GetFirstMatch(file, fileContent, matchers, includePosition);
}
}
}

View File

@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using BurnOutSharp.Matching;
namespace BurnOutSharp.ProtectionType
{
public class CDCops : IContentCheck, IPathCheck
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = new List<ContentMatchSet>
{
// CD-Cops, ver.
new ContentMatchSet(new byte?[]
{
0x43, 0x44, 0x2D, 0x43, 0x6F, 0x70, 0x73, 0x2C,
0x20, 0x20, 0x76, 0x65, 0x72, 0x2E, 0x20
}, GetVersion, "CD-Cops"),
// .grand + (char)0x00
new ContentMatchSet(new byte?[] { 0x2E, 0x67, 0x72, 0x61, 0x6E, 0x64, 0x00 }, "CD-Cops"),
};
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
/// <inheritdoc/>
public List<string> CheckDirectoryPath(string path, IEnumerable<string> files)
{
// TODO: Original had "CDCOPS.DLL" required and all the rest in a combined OR
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("CDCOPS.DLL", useEndsWith: true), "CD-Cops"),
new PathMatchSet(new PathMatch(".GZ_", useEndsWith: true), "CD-Cops"),
new PathMatchSet(new PathMatch(".W_X", useEndsWith: true), "CD-Cops"),
new PathMatchSet(new PathMatch(".Qz", useEndsWith: true), "CD-Cops"),
new PathMatchSet(new PathMatch(".QZ_", useEndsWith: true), "CD-Cops"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("CDCOPS.DLL", useEndsWith: true), "CD-Cops"),
new PathMatchSet(new PathMatch(".GZ_", useEndsWith: true), "CD-Cops"),
new PathMatchSet(new PathMatch(".W_X", useEndsWith: true), "CD-Cops"),
new PathMatchSet(new PathMatch(".Qz", useEndsWith: true), "CD-Cops"),
new PathMatchSet(new PathMatch(".QZ_", useEndsWith: true), "CD-Cops"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
public static string GetVersion(string file, byte[] fileContent, List<int> positions)
{
char[] version = new ArraySegment<byte>(fileContent, positions[0] + 15, 4).Select(b => (char)b).ToArray();
if (version[0] == 0x00)
return string.Empty;
return new string(version);
}
}
}

View File

@@ -0,0 +1,30 @@
using System.Collections.Generic;
using BurnOutSharp.Matching;
namespace BurnOutSharp.ProtectionType
{
public class CDKey : IContentCheck
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = new List<ContentMatchSet>
{
// I + (char)0x00 + n + (char)0x00 + t + (char)0x00 + e + (char)0x00 + r + (char)0x00 + n + (char)0x00 + a + (char)0x00 + l + (char)0x00 + N + (char)0x00 + a + (char)0x00 + m + (char)0x00 + e + (char)0x00 + + (char)0x00 + + (char)0x00 + C + (char)0x00 + D + (char)0x00 + K + (char)0x00 + e + (char)0x00 + y + (char)0x00
new ContentMatchSet(new byte?[]
{
0x49, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x65, 0x00,
0x72, 0x00, 0x6E, 0x00, 0x61, 0x00, 0x6C, 0x00,
0x4E, 0x00, 0x61, 0x00, 0x6D, 0x00, 0x65, 0x00,
0x00, 0x00, 0x43, 0x00, 0x44, 0x00, 0x4B, 0x00,
0x65, 0x00, 0x79, 0x00
}, Utilities.GetFileVersion, "CD-Key / Serial"),
};
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
}
}

View File

@@ -0,0 +1,51 @@
using System.Collections.Generic;
using BurnOutSharp.Matching;
namespace BurnOutSharp.ProtectionType
{
public class CDLock : IContentCheck, IPathCheck
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = new List<ContentMatchSet>
{
// 2 + (char)0xF2 + (char)0x02 + (char)0x82 + (char)0xC3 + (char)0xBC + (char)0x0B + $ + (char)0x99 + (char)0xAD + 'C + (char)0xE4 + (char)0x9D + st + (char)0x99 + (char)0xFA + 2$ + (char)0x9D + )4 + (char)0xFF + t
new ContentMatchSet(new byte?[]
{
0x32, 0xF2, 0x02, 0x82, 0xC3, 0xBC, 0x0B, 0x24,
0x99, 0xAD, 0x27, 0x43, 0xE4, 0x9D, 0x73, 0x74,
0x99, 0xFA, 0x32, 0x24, 0x9D, 0x29, 0x34, 0xFF,
0x74
}, "CD-Lock"),
};
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
/// <inheritdoc/>
public List<string> CheckDirectoryPath(string path, IEnumerable<string> files)
{
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch(".AFP", useEndsWith: true), "CD-Lock"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch(".AFP", useEndsWith: true), "CD-Lock"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

@@ -0,0 +1,37 @@
using System.Collections.Generic;
using BurnOutSharp.Matching;
namespace BurnOutSharp.ProtectionType
{
public class CDProtector : IPathCheck
{
/// <inheritdoc/>
public List<string> CheckDirectoryPath(string path, IEnumerable<string> files)
{
// TODO: Verify if these are OR or AND
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("_cdp16.dat", useEndsWith: true), "CD-Protector"),
new PathMatchSet(new PathMatch("_cdp16.dll", useEndsWith: true), "CD-Protector"),
new PathMatchSet(new PathMatch("_cdp32.dat", useEndsWith: true), "CD-Protector"),
new PathMatchSet(new PathMatch("_cdp32.dll", useEndsWith: true), "CD-Protector"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("_cdp16.dat", useEndsWith: true), "CD-Protector"),
new PathMatchSet(new PathMatch("_cdp16.dll", useEndsWith: true), "CD-Protector"),
new PathMatchSet(new PathMatch("_cdp32.dat", useEndsWith: true), "CD-Protector"),
new PathMatchSet(new PathMatch("_cdp32.dll", useEndsWith: true), "CD-Protector"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

@@ -0,0 +1,23 @@
using System.Collections.Generic;
using BurnOutSharp.Matching;
namespace BurnOutSharp.ProtectionType
{
public class CDSHiELDSE : IContentCheck
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = new List<ContentMatchSet>
{
// ~0017.tmp
new ContentMatchSet(new byte?[] { 0x7E, 0x30, 0x30, 0x31, 0x37, 0x2E, 0x74, 0x6D, 0x70 }, "CDSHiELD SE"),
};
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Collections.Generic;
using BurnOutSharp.Matching;
namespace BurnOutSharp.ProtectionType
{
public class CDX : IPathCheck
{
/// <inheritdoc/>
public List<string> CheckDirectoryPath(string path, IEnumerable<string> files)
{
// TODO: Verify if these are OR or AND
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("CHKCDX16.DLL", useEndsWith: true), "CD-X"),
new PathMatchSet(new PathMatch("CHKCDX32.DLL", useEndsWith: true), "CD-X"),
new PathMatchSet(new PathMatch("CHKCDXNT.DLL", useEndsWith: true), "CD-X"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("CHKCDX16.DLL", useEndsWith: true), "CD-X"),
new PathMatchSet(new PathMatch("CHKCDX32.DLL", useEndsWith: true), "CD-X"),
new PathMatchSet(new PathMatch("CHKCDXNT.DLL", useEndsWith: true), "CD-X"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

@@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using BurnOutSharp.Matching;
namespace BurnOutSharp.ProtectionType
{
public class CactusDataShield : IContentCheck, IPathCheck
{
/// <summary>
/// Set of all ContentMatchSets for this protection
/// </summary>
private static readonly List<ContentMatchSet> contentMatchers = new List<ContentMatchSet>
{
// DATA.CDS
new ContentMatchSet(new byte?[] { 0x44, 0x41, 0x54, 0x41, 0x2E, 0x43, 0x44, 0x53 }, "Cactus Data Shield 200"),
// \*.CDS
new ContentMatchSet(new byte?[] { 0x5C, 0x2A, 0x2E, 0x43, 0x44, 0x53 }, "Cactus Data Shield 200"),
// CDSPlayer
new ContentMatchSet(new byte?[] { 0x43, 0x44, 0x53, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72 }, "Cactus Data Shield 200"),
};
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchers, includePosition);
}
/// <inheritdoc/>
public List<string> CheckDirectoryPath(string path, IEnumerable<string> files)
{
// TODO: Verify if these are OR or AND
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("CACTUSPJ.exe", useEndsWith: true), GetVersion, "Cactus Data Shield"),
new PathMatchSet(new PathMatch("CDSPlayer.app", useEndsWith: true), GetVersion, "Cactus Data Shield"),
new PathMatchSet(new PathMatch("PJSTREAM.DLL", useEndsWith: true), GetVersion, "Cactus Data Shield"),
new PathMatchSet(new PathMatch("wmmp.exe", useEndsWith: true), GetVersion, "Cactus Data Shield"),
new PathMatchSet(new PathMatch(".cds", useEndsWith: true), GetVersion, "Cactus Data Shield"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("CACTUSPJ.exe", useEndsWith: true), "Cactus Data Shield 200"),
new PathMatchSet(new PathMatch("CDSPlayer.app", useEndsWith: true), "Cactus Data Shield 200"),
new PathMatchSet(new PathMatch("PJSTREAM.DLL", useEndsWith: true), "Cactus Data Shield 200"),
new PathMatchSet(new PathMatch("wmmp.exe", useEndsWith: true), "Cactus Data Shield 200"),
new PathMatchSet(new PathMatch(".cds", useEndsWith: true), "Cactus Data Shield 200"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
public static string GetVersion(string firstMatchedString, IEnumerable<string> files)
{
// Find the version.txt file first
string versionPath = files.FirstOrDefault(f => Path.GetFileName(f).Equals("version.txt", StringComparison.OrdinalIgnoreCase));
if (!string.IsNullOrWhiteSpace(versionPath))
{
string version = GetInternalVersion(versionPath);
if (!string.IsNullOrWhiteSpace(version))
return version;
}
return "200";
}
private static string GetInternalVersion(string path)
{
if (!File.Exists(path))
return null;
try
{
using (var sr = new StreamReader(path, Encoding.Default))
{
return $"{sr.ReadLine().Substring(3)} ({sr.ReadLine()})";
}
}
catch
{
return null;
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More