Compare commits

...

1825 Commits
1.6.0 ... 3.2.1

Author SHA1 Message Date
Matt Nadareski
6acf5ccc09 Bump version 2024-11-15 23:11:00 -05:00
Matt Nadareski
a5f9006ef1 One last Linq place (not all of them) 2024-11-15 23:09:58 -05:00
Matt Nadareski
ae7111e201 Update package versions 2024-11-15 23:06:47 -05:00
Matt Nadareski
5a94cd3b66 Framework only matters for executable 2024-11-15 23:00:37 -05:00
Matt Nadareski
3de58ff05e Fix linux publish script 2024-11-13 13:03:13 -05:00
Matt Nadareski
6e409988a5 Bump version 2024-11-13 13:01:48 -05:00
Matt Nadareski
864fa8d3f8 Add .NET 9 to target frameworks 2024-11-13 04:26:26 -05:00
Matt Nadareski
622f36b056 Add .NET 9 to target frameworks 2024-11-13 04:26:24 -05:00
Matt Nadareski
efe144313b Fix build 2024-11-12 23:29:53 -05:00
Matt Nadareski
1e3aac6748 Linq is friend, not food 2024-11-12 23:17:48 -05:00
Matt Nadareski
984ad1f642 Remove minimally-used System.Memory package 2024-11-05 16:58:13 -05:00
Matt Nadareski
b379e1781b Remove unused MinThreadingBridge library 2024-11-05 16:53:52 -05:00
Matt Nadareski
e244d6939c Attempt to reduce nesting in GHA builds 2024-11-05 13:50:04 -05:00
Matt Nadareski
b4a781acc7 Bump version 2024-11-05 13:10:09 -05:00
Matt Nadareski
eb7bbdde52 Remove now-incorrect remark 2024-11-05 11:06:30 -05:00
Matt Nadareski
f470263196 Func not obj 2024-11-05 01:45:35 -05:00
Matt Nadareski
3822cc41f2 Extract loop into new method; fix build 2024-11-05 01:24:14 -05:00
Matt Nadareski
f04cf25fa9 Move all executable handling to Executable 2024-11-05 01:12:18 -05:00
Matt Nadareski
eb8b9daea8 Reduce unncessary nulls 2024-11-05 00:42:45 -05:00
Matt Nadareski
33ecc246dc Reorganize yet again around check sets 2024-11-05 00:32:42 -05:00
Matt Nadareski
7d55c8224a Move Factory to Data namespace 2024-11-05 00:28:39 -05:00
Matt Nadareski
0ccae4e4b7 Move static check collections to separate class 2024-11-05 00:25:22 -05:00
Matt Nadareski
1798371513 Add better info to coding and dev guides 2024-11-05 00:10:40 -05:00
Matt Nadareski
0858437196 Undo launch changes 2024-11-04 23:59:46 -05:00
Matt Nadareski
ece758bf03 IExtractableExecutable extends IExecutableCheck 2024-11-04 23:59:10 -05:00
Matt Nadareski
d9661cd03d Fix access level 2024-11-04 23:52:40 -05:00
Matt Nadareski
682529d7ba Consolidate more typed methods 2024-11-04 23:49:13 -05:00
Matt Nadareski
27ef24636c Use typed check methods as well 2024-11-04 23:37:23 -05:00
Matt Nadareski
f5f3d3d29a Fun with typed interfaces 2024-11-04 23:21:12 -05:00
Matt Nadareski
550fb70952 Use typed interface for extractable executables 2024-11-04 22:02:10 -05:00
Matt Nadareski
7d6248a3bf Re-merge some code from Handler to Scanner 2024-11-04 21:53:59 -05:00
Matt Nadareski
4575da77bd Use private field when possible 2024-11-04 21:40:56 -05:00
Matt Nadareski
a85aa08117 Reduce publicly visible fields in Scanner 2024-11-04 21:37:03 -05:00
Matt Nadareski
667207761c Reduce SFX code duplication 2024-11-04 21:25:30 -05:00
Matt Nadareski
92097222b0 Sync IExtractable*Executable implementations 2024-11-04 21:14:06 -05:00
Matt Nadareski
5ec90b290a Steam any false 2024-11-04 20:06:47 -05:00
Matt Nadareski
5de78ef552 Make GitHub action Debug-only 2024-11-04 15:02:11 -05:00
Matt Nadareski
57a5531fbd Remove old Test executable; update docs 2024-11-04 14:58:21 -05:00
Matt Nadareski
f7a4b6b43c Add separate ExtractionTool executable 2024-11-04 14:48:29 -05:00
Matt Nadareski
3de56083d8 Add separate ProtectionScan executable 2024-11-04 14:38:23 -05:00
Matt Nadareski
f998a578cc Make Extractor static like Protector 2024-11-04 14:14:50 -05:00
Matt Nadareski
0fc7ce2e07 Simplify code in Extractor 2024-11-04 14:10:16 -05:00
Matt Nadareski
156df10e37 Remove Printer 2024-11-04 14:05:20 -05:00
Matt Nadareski
9490d06509 Remove Utilities namespace references 2024-11-04 11:54:41 -05:00
Matt Nadareski
b8b70a3848 Ensure all files matched in RainbowSentinel (fixes #336) 2024-11-04 11:42:24 -05:00
Matt Nadareski
42df482ffa Fix MPQ compilation 2024-11-04 11:29:36 -05:00
Matt Nadareski
058dfaeb37 Fix missed outDir location 2024-11-04 11:25:42 -05:00
Matt Nadareski
1622bcbe60 Replace now-duplicate code 2024-11-04 11:17:09 -05:00
Matt Nadareski
72629ea3a4 Update IExtractable interface 2024-11-04 11:00:59 -05:00
Matt Nadareski
4ba3c3e3ad Normalize extraction 2024-11-04 10:20:46 -05:00
Matt Nadareski
56c1fd31d4 Add Steam extension matching (fixes #234) 2024-11-04 09:51:20 -05:00
Matt Nadareski
9c27da72bb Add VOB-PCD.KEY detection 2024-11-04 09:38:25 -05:00
Matt Nadareski
e5dc66b140 Bump version 2024-11-03 20:01:41 -05:00
HeroponRikiBestest
41e10a4150 Add aditional light directory checks (#335)
Compensate for some additional variance in directory names found from new samples, in lieu of a more "advanced" check
2024-11-02 19:42:00 -04:00
Matt Nadareski
3c4381049b Minor leftover cleanup 2024-10-31 23:11:11 -04:00
Matt Nadareski
3188c6e922 Further reduce awkward framework gating 2024-10-31 23:08:05 -04:00
Matt Nadareski
1bfb6cda08 Use CheckDictionary helper type 2024-10-31 22:52:20 -04:00
Matt Nadareski
86feb930a8 Add CheckDictionary (unused) 2024-10-31 22:49:57 -04:00
Matt Nadareski
5587c79ac5 Reduce use of generic PathMatch 2024-10-31 22:42:20 -04:00
Matt Nadareski
dc2a2e10de Add summary to ProtectionDictionary 2024-10-31 22:25:11 -04:00
Matt Nadareski
a2fdcb4f6f Remove remaining unncessary Concurrent usings 2024-10-31 22:22:52 -04:00
Matt Nadareski
a355670af9 Use semantic versioning for var names 2024-10-31 22:16:51 -04:00
Matt Nadareski
3489c67e2b Make CheckDirectoryPath signature easier 2024-10-31 22:15:30 -04:00
Matt Nadareski
99a64942ea Reduce per-framework complexity 2024-10-31 21:46:40 -04:00
Matt Nadareski
5eab12946f Fix accidental change 2024-10-31 21:13:09 -04:00
Matt Nadareski
683cfb6306 Start using ProtectionDictionary 2024-10-31 21:10:06 -04:00
Matt Nadareski
9a3fde0518 Add ProtectionDictionary type (unused) 2024-10-31 20:54:36 -04:00
Matt Nadareski
26d19aab37 Fix very strange formatting 2024-10-31 20:38:15 -04:00
Matt Nadareski
08564ed607 Remove end-of-program pauses 2024-10-31 20:36:40 -04:00
Matt Nadareski
0f6378cd2c Update packages 2024-10-31 16:05:11 -04:00
TheRogueArchivist
34a78fc4b9 Minor SafeCast additions (#333)
Adds a text check for SafeCast, along with adding a new confirmed version. Also add notes for a few known programs that used SafeCast, a few TODOs, and a semi-related note about stxt sections.
2024-10-30 07:28:21 -04:00
Matt Nadareski
c9ee45c1d2 Count not Count() 2024-10-27 20:24:24 -04:00
HeroponRikiBestest
13f5b4f79b Improve Copy-X Light detection with additional folder check. (#332)
* Improve Copy-X Light detection with additional folder check.

* Add requested changes to additional copy-X light folder check.

* Cleaned up changes.

* One final comment cleanup.
2024-10-27 20:20:19 -04:00
HeroponRikiBestest
e5d0c5bdc4 Replace tivola with copy-x. (#331) 2024-10-27 00:19:41 -04:00
Matt Nadareski
6220382531 Clarify switch expression use 2024-10-27 00:12:21 -04:00
Matt Nadareski
165896e335 Add note about first-person comments 2024-10-27 00:04:11 -04:00
Matt Nadareski
284d0ea108 Clear out old info from the coding guide 2024-10-27 00:01:22 -04:00
Matt Nadareski
b04feab5da Minor cleanup 2024-10-26 23:54:54 -04:00
HeroponRikiBestest
4e0442d526 Add preliminary copy-X protection checking (#328)
* Add preliminary copy-X protection checking

* Fixed formatting.

* Removed some unecessary lines of code.

* Added debatably sufficient documentation.

* Fixed formatting, hopefully

* Finalize formatting and PR.

* Fleshes out checks after more samples. Fixes some but not all of the change requests.

* Fix ordering.

* Fixes pex check, fixes redump id formatting.

* Added copy-X info to readme.

* Revert "Added copy-X info to readme."

This reverts commit 77349aa8de.

* Add copy-X info to readme, for real this time.

* Replaced some code in byte check with BoS helper function.

* Remove first person.

* Source is no longer just trust me (to some degree)

* Fix typo

* WIP figuring out enumerable (fails to build)

* WIP 2 figuring out getfirstmatch (compiles, but breaks detection)

* Pass 1 of suggested changes.

* Removed debug match.

* Pass 2 of suggested changes.

* Added line.

* Added line for real.

* Added todo

* Improved comments.

* Finished todo.

* Redid change.

* Fixes more comments.

* double double and make it trouble
2024-10-26 23:53:17 -04:00
TheRogueArchivist
d8aa4d230d Fix WTM false positive (#327)
"imp.dat" isn't exactly a very distinctive file name.
2024-10-26 20:31:25 -04:00
TheRogueArchivist
07a7fd05d2 Add new SafeCast version (#329) 2024-10-26 20:30:07 -04:00
Matt Nadareski
671e1ee2b6 Update Matching to 1.3.3 2024-10-26 19:46:34 -04:00
Matt Nadareski
d627e8a4c9 Be consistent with naming 2024-10-25 12:01:08 -04:00
Matt Nadareski
6ee90b28cd Be consistent with naming 2024-10-25 11:57:51 -04:00
Matt Nadareski
8dc2b019b6 Update packages 2024-10-24 17:32:26 -04:00
TheRogueArchivist
f151563e28 Move Armadillo to Protection and add notes (#326)
Armadillo has packer and protection features, meaning it should be move to be a protection. Also add additional notes, including about an alternate later name, "SoftwarePassport".
2024-10-23 00:38:53 -04:00
Matt Nadareski
edbbbb011d Renmae MediaMax CD-3 to be more accurate 2024-10-21 21:59:15 -04:00
TheRogueArchivist
e3fd44134b Add initial .NET Reactor support (#325)
* Add initial .NET Reactor support

It's minimal, but is much better than nothing. A few notes on how it can be realistically improved have been added as well.

* Fix missing using

* 7-zip SFX is extractable now
2024-10-04 23:56:52 -04:00
Matt Nadareski
71fb7318e3 Better handling of Windows libraries 2024-10-03 14:57:14 -04:00
Matt Nadareski
aba4395139 Enable Windows libraries on .NET Framework 4.0 2024-10-03 14:46:35 -04:00
Matt Nadareski
1fd69f101f Remove last two this qualifiers 2024-10-03 13:02:23 -04:00
Matt Nadareski
aa4c72fb90 Old .NET really doesn't like readonly 2024-10-03 12:55:38 -04:00
Matt Nadareski
150b9a0d67 Remove more this qualifiers 2024-10-03 12:53:43 -04:00
Matt Nadareski
b08921a94a Use readonly instead of private set 2024-10-03 12:52:27 -04:00
Matt Nadareski
3406f3c4b3 Remove this qualifiers 2024-10-03 12:51:49 -04:00
Matt Nadareski
ffca156209 Remove init variants :( 2024-10-03 12:51:30 -04:00
Matt Nadareski
b842599006 Update packages 2024-10-03 12:01:08 -04:00
TheRogueArchivist
86b639b04f Add Kalypso Launcher support (#324)
* Add Kalypso Launcher support

* Small changes to Kalypso Launcher

* More minor Kalypso Launcher changes
2024-10-03 10:42:39 -04:00
Matt Nadareski
570602aac6 Remove unused package 2024-10-01 10:45:12 -04:00
Matt Nadareski
4989956a91 Bump version 2024-09-28 13:13:06 -04:00
Matt Nadareski
14849f45da Remove redundant reports in Macrovision code 2024-09-27 13:24:19 -04:00
TheRogueArchivist
28ebc14fe1 Fix various archive formats not extracting folders (#323)
Fixes folder extraction for 7z, RAR, and WinRAR SFX. Applied same fix to tar, but more is needed for it to work properly.
2024-09-26 01:15:38 -04:00
TheRogueArchivist
54cb996fce [WIP] Add 7-Zip SFX extraction (#321)
* Add 7-Zip SFX extraction

Newest SharpCompress added support for extracting 7-Zip SFX files, so we can add support for them here too.

* Clean up 7z SFX extraction method

* Remove unneeded import

* Use file instead of stream for 7z SFX

* Update 7z SFX to be more consistent with other packers
2024-09-26 00:30:25 -04:00
Matt Nadareski
8df58fa4d4 This doesn't inherit from anything 2024-09-25 11:25:52 -04:00
TheRogueArchivist
422add9827 Update SharpCompress to 0.38.0 (#320) 2024-09-25 11:01:16 -04:00
TheRogueArchivist
59435903eb Small update to nProtect comments (#319)
Add new confirmed game to use GameGuard, and start a known version list.
2024-09-12 02:33:17 -04:00
TheRogueArchivist
95ee417e00 Small update to SafeWrap comments (#318)
* Small update to SafeWrap comments

* Further additions to SafeWrap comments
2024-09-05 01:22:11 -04:00
Matt Nadareski
df913372bf Add more SecuROM PA checks (fixes #313) 2024-08-08 08:55:46 -04:00
TheRogueArchivist
2f1c76b7f9 Add EA Anti Cheat detection (#314)
* Add EA Anti Cheat detection

* Make a check more exact
2024-08-02 12:34:43 -04:00
Matt Nadareski
18e57c8182 Fix minor formatting issue 2024-08-02 12:23:05 -04:00
TheRogueArchivist
b4e2117c4b Confirm one SafeCast version (#309) 2024-08-02 00:07:12 -04:00
Matt Nadareski
1bb5ff9e18 Fix README a bit 2024-07-20 21:54:55 -04:00
TheRogueArchivist
a46cae469d Fix scans that use directory name in Windows (#312)
Removes ``.Replace("\\", "/")``, as it was messing with folder paths on Windows.
2024-07-13 01:29:45 -04:00
TheRogueArchivist
b564ff214d Add initial Channelware detection (#311) 2024-07-12 12:35:26 -04:00
TheRogueArchivist
0744a10de0 Improve phenoProtect detection (#307) 2024-07-04 22:16:11 -04:00
HeroponRikiBestest
343ca9497e Fix #.##.xx version number writing second x digit to first digit (#310) 2024-07-04 22:13:49 -04:00
Matt Nadareski
861958527d Fix under-matched runtimes 2024-06-26 12:44:32 -04:00
Matt Nadareski
a6b9dca291 Only copy DLLs for win-x86 2024-06-26 11:53:10 -04:00
Matt Nadareski
18c05cb49d Update workflow runtimes 2024-06-26 11:34:31 -04:00
Matt Nadareski
ed3e58af6c Update publishing to cooler version 2024-06-26 11:32:20 -04:00
Matt Nadareski
e3eed76826 Make debug table reading safer, kinda 2024-06-20 11:26:20 -04:00
Matt Nadareski
7eb86b223f Fix build script 2024-06-17 16:16:11 -04:00
Matt Nadareski
a4ee4529ca Bump version 2024-06-17 16:15:04 -04:00
Matt Nadareski
abc68d8503 Update Serialization to 1.6.7 2024-06-13 11:20:33 -04:00
TheRogueArchivist
aaff4bad1b Add new Alpha-ROM checks (#306) 2024-06-07 13:11:24 -04:00
TheRogueArchivist
d5c81857c3 Update Roxxe detections (#305) 2024-06-05 09:37:37 -04:00
TheRogueArchivist
c2594cdd2d Add checks for Macrovision SecDrv Update Installer (#304) 2024-06-02 19:43:15 -04:00
Matt Nadareski
2412042cef Update Serialization to 1.6.6 2024-06-02 19:42:49 -04:00
Matt Nadareski
1f5c1a8100 Bump version 2024-05-18 22:12:35 -04:00
Matt Nadareski
78cc67f30e Update UnshieldSharp 2024-05-18 22:05:32 -04:00
Matt Nadareski
5b78ba5621 Bump version 2024-05-15 20:30:43 -04:00
Matt Nadareski
c4734cfc3d Update packages 2024-05-15 15:16:41 -04:00
Matt Nadareski
dd45384226 Add secondary check for WinZipSFX NE 2024-05-15 15:15:09 -04:00
Matt Nadareski
3e75d9fa3b Add safety around executable wrapper creation 2024-05-15 13:09:40 -04:00
Matt Nadareski
aa690ab602 Update packages 2024-05-15 12:24:40 -04:00
Matt Nadareski
7432100139 Bump version 2024-05-07 08:57:17 -04:00
Matt Nadareski
29fabb44eb Update IO and Serialization 2024-05-07 05:31:42 -04:00
Matt Nadareski
ad776d4189 Add explicit compatibility notes section 2024-05-06 22:40:39 -04:00
Matt Nadareski
4cf12c76a8 Update IO and Serialization 2024-05-06 22:30:58 -04:00
Matt Nadareski
39185f5ddd Remove now-irrelevant note 2024-05-06 21:59:37 -04:00
Matt Nadareski
03477327c4 Clearer in another place 2024-05-06 21:59:10 -04:00
Matt Nadareski
29fa0d1ac7 Clarify support 2024-05-06 21:54:45 -04:00
Matt Nadareski
7eca23a7f3 Bump version 2024-04-28 19:51:22 -04:00
Matt Nadareski
f0c90bb332 Update packages for critical issues 2024-04-28 19:50:53 -04:00
Matt Nadareski
0af67e5802 Fix build 2024-04-26 22:13:27 -04:00
Matt Nadareski
6ab9f730f9 Bump version 2024-04-26 22:10:27 -04:00
Matt Nadareski
258238bcc0 Update packages 2024-04-26 22:09:05 -04:00
Matt Nadareski
3936a15ef7 Bump version 2024-04-24 17:08:16 -04:00
Matt Nadareski
f6dbb349c4 Update packages 2024-04-24 17:06:51 -04:00
Matt Nadareski
3c69e02cfc Update SabreTools.Serialization 2024-04-24 16:29:58 -04:00
Matt Nadareski
531e634e62 Version-gate a using statement 2024-04-24 14:43:28 -04:00
Matt Nadareski
f9c0c42b26 One Nuget packing error 2024-04-24 12:13:56 -04:00
Matt Nadareski
83aebbbfbd Maybe the last one? 2024-04-24 12:11:05 -04:00
Matt Nadareski
3847e5e9dc Even more warnings 2024-04-24 11:55:27 -04:00
Matt Nadareski
a72bb7e332 Yet more, plus an XML comment 2024-04-24 11:45:20 -04:00
Matt Nadareski
839791f467 Add a couple more for external 2024-04-24 11:43:09 -04:00
Matt Nadareski
469356e8c1 Suppress some "necessary" warnings 2024-04-24 11:35:09 -04:00
Matt Nadareski
66e8eb985c Bump version 2024-04-24 11:23:33 -04:00
Matt Nadareski
90223e6c94 Handle some warnings and messages 2024-04-24 11:16:03 -04:00
Matt Nadareski
2f2cf76d7b Update SabreTools.Printing 2024-04-24 11:15:51 -04:00
Matt Nadareski
558fee2200 Clean up using statements 2024-04-24 11:03:09 -04:00
Matt Nadareski
a82abc05ec Update packages 2024-04-24 11:01:10 -04:00
Matt Nadareski
74df37597a Slight cleanup to Scanner 2024-04-22 11:34:04 -04:00
Matt Nadareski
1581023c01 Update WiseUnpacker 2024-04-18 13:04:49 -04:00
Matt Nadareski
c0d1260656 Update UnshieldSharp 2024-04-18 12:58:32 -04:00
Matt Nadareski
969d103c2c Update packages 2024-04-18 12:48:44 -04:00
TheRogueArchivist
e5e3f3e3ef Add check for StarForce driver removal tool (#301) 2024-04-17 19:30:57 -04:00
Matt Nadareski
c1ee399262 Usings cleanup 2024-04-17 13:46:38 -04:00
Matt Nadareski
74ee9932a7 Update WrapperFactory a bit 2024-04-17 13:44:33 -04:00
Matt Nadareski
e70f8d7220 Reduce unncessary printing code 2024-04-17 13:41:00 -04:00
Matt Nadareski
ceba351372 Update packages 2024-04-17 13:38:14 -04:00
Matt Nadareski
ad4082c531 Forgot the name for playlist 2024-04-17 12:16:57 -04:00
Matt Nadareski
115ea02822 Update libraries 2024-04-17 12:12:01 -04:00
TheRogueArchivist
f876a4e4a6 Add RealArcade detection (#300) 2024-04-16 19:30:48 -04:00
TheRogueArchivist
be114f60d3 Fix WinZip SFX folders not being scanned (#299)
* Fix WinZip SFX folders not being scanned

Use PKZIP extraction to fix WinZip SFX extraction not extracting folders.

* Remove unneeded null check

* Add checks for incomplete zip entries
2024-04-15 00:18:00 -04:00
Matt Nadareski
b2594f8148 Update WiseUnpacker 2024-04-11 12:33:00 -04:00
TheRogueArchivist
f58ada3dde Fix Steam overmatch (#298) 2024-04-11 12:23:46 -04:00
TheRogueArchivist
bc4f07970d Minor Rainbow Sentinel improvements (#295) 2024-04-07 19:15:30 -04:00
Matt Nadareski
25d6822283 Bump version 2024-04-05 15:42:43 -04:00
Silent
3b22262c21 Update SecuROM v7 detection to correctly handle a partly stripped header (#297) 2024-04-04 15:00:09 -04:00
Matt Nadareski
314fc1e3fc Update SabreTools.Printing 2024-04-04 13:48:00 -04:00
Matt Nadareski
5742749dec Update packages 2024-04-04 12:12:52 -04:00
Silent
c55fffeb7b Fix a crash when a sharing violation occurs during --info (#296)
Prints an exception the same way GetInternalProtections
does.
2024-04-03 12:52:12 -07:00
TheRogueArchivist
e469dc38bf Fix Roxxe false positive (#294) 2024-04-02 21:57:23 -07:00
Matt Nadareski
553703c30e Bump version 2024-04-02 17:03:49 -04:00
Matt Nadareski
3fd093f9b4 Update packages 2024-04-02 16:37:02 -04:00
TheRogueArchivist
4946d4e7ff Add Roxxe detection (#293)
* Add Roxxe detection

* Fix Roxxe PR review comments
2024-04-01 09:14:13 -07:00
Matt Nadareski
491fc0f71c Bump version 2024-03-27 12:01:40 -04:00
Matt Nadareski
fe6627f1ba Update to WiseUnpacker 1.3.1 2024-03-25 22:43:34 -04:00
Matt Nadareski
edffa3c7cc Default to using net8.0 target for launch 2024-03-25 22:32:29 -04:00
Matt Nadareski
a66d62bfbc Remove version gate from UnshieldSharp in Test 2024-03-25 21:56:08 -04:00
Matt Nadareski
9321b8f221 Update to UnshieldSharp 1.7.3 2024-03-25 21:53:33 -04:00
Matt Nadareski
cd0863ac56 Ensure zlib inflateEnd is called 2024-03-25 21:34:38 -04:00
Matt Nadareski
24a73e8bfd Update README 2024-03-25 20:08:51 -04:00
Matt Nadareski
46eaa7db1e Fix errant formatting issues 2024-03-25 19:58:37 -04:00
TheRogueArchivist
0eab7fd555 Significantly update Rainbow Sentinel detections and notes (#290) 2024-03-25 16:57:29 -07:00
Matt Nadareski
dba476d8bb Create new extractable interfaces for each executable type 2024-03-25 19:55:16 -04:00
Matt Nadareski
b10b4d6658 Seek to beginning for Embedded Executable 2024-03-25 17:14:10 -04:00
Matt Nadareski
2959fdbe9a Fix zlib with init 2024-03-25 17:10:24 -04:00
Matt Nadareski
9c0d100c2a Set zlib totals (nw) 2024-03-25 17:06:17 -04:00
Matt Nadareski
03ca0faf2e Start fixing zlib implementation 2024-03-25 16:58:11 -04:00
Matt Nadareski
cbaf004e25 Seek to beginning of stream for CExe 2024-03-25 16:37:53 -04:00
Matt Nadareski
bbe4fb610c Correct assumption about directory separators 2024-03-25 16:16:55 -04:00
Matt Nadareski
650115f722 Replace SharpZipLib with ST.Compression 2024-03-25 15:00:42 -04:00
Matt Nadareski
1afcbe3182 Update packages 2024-03-25 14:41:20 -04:00
TheRogueArchivist
8aa90dbc49 Add FlexLM detection (#289) 2024-03-24 19:08:09 -07:00
Matt Nadareski
0781524669 Bump version 2024-03-16 11:16:00 -04:00
Matt Nadareski
3b3cb7a862 Case-insensitive hash comparisons 2024-03-15 21:22:48 -04:00
Matt Nadareski
810d20d95c Bump version 2024-03-14 13:20:30 -04:00
Matt Nadareski
de578511bf Fix type retrieval for all build types 2024-03-13 23:26:16 -04:00
Matt Nadareski
f1ec025950 Fix nulability warning 2024-03-12 16:54:49 -04:00
Matt Nadareski
0c58ecc548 Update packages 2024-03-12 16:53:12 -04:00
Matt Nadareski
d2a73a153b Unroll Linq statements to fix exceptions (fixes #287) 2024-03-10 22:27:18 -04:00
TheRogueArchivist
eae2e3366b Remove DBB Skeleton (#286)
DBB is now documented in DRML.
2024-03-06 08:15:06 -08:00
Matt Nadareski
afb04c99c0 Update packages 2024-03-06 11:08:22 -05:00
Matt Nadareski
1d3bd2f8b1 Use SabreTools.Hashing 2024-03-04 21:27:36 -05:00
TheRogueArchivist
3f52c24713 Move CopyKiller comments to DRML (#285) 2024-02-28 07:36:23 -08:00
Matt Nadareski
ae1417a343 Remove unnecessary commit setting 2024-02-27 17:17:04 -05:00
Matt Nadareski
871a3e6366 Add PR check workflow 2024-02-27 11:21:01 -05:00
Matt Nadareski
3457b807cb Remove GHA on pull request builds 2024-02-27 11:17:41 -05:00
Matt Nadareski
027f295d21 Remove unnecessary newline 2024-02-26 12:46:26 -05:00
Matt Nadareski
63e6d1e285 Add badges to README 2024-02-26 12:43:49 -05:00
Matt Nadareski
2193095f70 Change nupkg location 2024-02-26 12:42:55 -05:00
Matt Nadareski
074694298f Typo typo 2024-02-26 12:37:43 -05:00
Matt Nadareski
ce4d32b053 Forgot to add recursive here 2024-02-26 12:37:11 -05:00
Matt Nadareski
a25af3940c Add recursive checkout 2024-02-26 12:36:47 -05:00
Matt Nadareski
9d1a2db45a Migrate to GitHub Actions 2024-02-26 12:29:12 -05:00
Matt Nadareski
5cdf269a3e Bump version 2024-02-26 12:14:30 -05:00
TheRogueArchivist
b9d90ec35d Remove GetVersionFromSHA1Hash from SafeDisc (#284)
* Remove GetVersionFromSHA1Hash from SafeDisc.
* Minor SafeDisc comment cleanup.
2024-02-23 10:58:58 -08:00
Matt Nadareski
5fc1d3254d Remove outdated comments in build scripts 2024-02-21 19:24:33 -05:00
Matt Nadareski
d61bae8e61 Don't use the auto git hash 2024-02-21 00:04:16 -05:00
Matt Nadareski
f8f53869ae Fix build scripts, again 2024-02-20 23:22:10 -05:00
Matt Nadareski
f5146a6e35 osx-arm64 is such a pain 2024-02-20 22:48:12 -05:00
Matt Nadareski
faf96b9375 Wrong array 2024-02-20 22:10:51 -05:00
Matt Nadareski
2228e344f6 Or, not And 2024-02-20 21:53:52 -05:00
Matt Nadareski
9955bdcab1 Not all DLLs, oops 2024-02-20 21:47:59 -05:00
Matt Nadareski
4586d49a3f Use DLL filtering in publish scripts 2024-02-20 21:45:18 -05:00
Matt Nadareski
1f4e24452a Add non-DLL lists, not hooked up 2024-02-20 21:33:14 -05:00
Matt Nadareski
090bac4d59 Remove unbuildable runtime 2024-02-20 21:12:21 -05:00
Matt Nadareski
59bedf5fce Fix DLL bundling 2024-02-20 21:07:29 -05:00
Matt Nadareski
1bbc541957 Limit packing to just BOS library 2024-02-20 21:04:39 -05:00
Matt Nadareski
1bb0107ceb Remove net6.0 from AppVeyor, add win-x86 2024-02-20 21:03:28 -05:00
Matt Nadareski
10dad356cd Expand default and extended publish targets 2024-02-20 20:59:28 -05:00
Matt Nadareski
22b6971e51 Tabs lose this battle 2024-02-20 20:54:28 -05:00
Matt Nadareski
3203b56ef6 Update publish scripts 2024-02-20 20:51:59 -05:00
Matt Nadareski
d6db84152f Limit to MS-CAB to x86 until IntPtr issue resolved 2024-02-20 20:14:38 -05:00
Matt Nadareski
b7afad5a4a Enable MS-CAB extraction on at least x86 2024-02-20 19:59:43 -05:00
Matt Nadareski
9d6c53f631 Update build after submodule update 2024-02-20 18:45:37 -05:00
Matt Nadareski
aa7b02dfc3 Add libmspack4n and LessIO as submodlues 2024-02-20 18:44:51 -05:00
TheRogueArchivist
379ffaf61a Add more empty file checks for SafeDisc (#283) 2024-02-20 06:47:20 -08:00
TheRogueArchivist
1bdfccddbc Fix Hexalock false positive (#281) 2024-02-08 10:09:11 -08:00
Matt Nadareski
c83cdd590c Update libraries 2024-02-06 10:48:59 -05:00
Matt Nadareski
f4770374a7 Update copyright date 2024-02-06 10:44:36 -05:00
TheRogueArchivist
72880e93bc Add new Denuvo Anti-Cheat detections (#279) 2024-02-01 20:27:49 -08:00
TheRogueArchivist
6c9cd72948 Add CD-X notes (#278)
* Add CD-X notes

* Add additional note
2024-01-26 06:40:09 -08:00
TheRogueArchivist
2e71ef4635 Update CopyKiller detection and notes (WIP) (#277)
* Update CopyKiller detection and notes

* Cleanup Copykiller
2024-01-25 21:19:16 -08:00
TheRogueArchivist
04cd1098ea Improve CrypKey detection (#275)
* Improve CrypKey detection

* Add CrypKey file detections.
* Add new CrypKey executable detections.

* Fix CrypKey version parsing

* Address PR reviews

* Check for both "code" and "CODE" sections
2023-12-28 20:35:57 -08:00
TheRogueArchivist
e76ce64568 Update known versions for the first SafeDisc splash-screen (#274) 2023-12-25 17:31:09 -08:00
Matt Nadareski
8fe84abef3 Use more lenient file reading 2023-12-13 15:52:03 -05:00
TheRogueArchivist
1b1fa53547 Add small note about ProtectDISC using CSS (#272) 2023-12-01 21:28:21 -08:00
TheRogueArchivist
5019407f35 Add additional SafeDisc for Mac detections and notes (#271)
* Add additional SafeDisc for Mac detections and notes

* Slightly update notes

* Minor additions

* Update earliest known SafeDisc splash-screen version
2023-12-01 17:42:03 -08:00
Matt Nadareski
83ba19eccb Fix ancient .NET dictionary extensions 2023-11-29 13:13:27 -05:00
Matt Nadareski
936bf38521 Slight cleanup 2023-11-25 22:25:44 -05:00
TheRogueArchivist
f54b0d2bbb Add SafeDisc Splash-Screen detection and notes (#269)
* Add initial SafeDisc splash-screen scanning and notes

So far only SafeDisc 1 has been added.

* Further update SafeDisc splash screen notes

This gets part of the way through SafeDisc 2 at least

* Update SafeDisc splash-screen notes and detection up through SafeDisc 2

* Update splash-screen notes through SafeDisc 3

* Starting adding SafeDisc 4 splash-screen notes

* Finish adding SafeDisc 4 splash-screen support

* Update SafeDisc splash-screen notes

* oops

* oops again
2023-11-25 19:21:59 -08:00
Matt Nadareski
0e32abc76c Bump version 2023-11-22 13:28:56 -05:00
Matt Nadareski
94cb06a3bd Handle some messages 2023-11-22 13:28:13 -05:00
Matt Nadareski
907aea443e Support .NET Framework 2.0 2023-11-22 12:22:01 -05:00
Matt Nadareski
385922723c Upate packages 2023-11-22 10:48:08 -05:00
Matt Nadareski
3061c2f009 Reenable .NET Framework 4.0 2023-11-21 10:59:29 -05:00
Matt Nadareski
5c0ccbde35 Temporarily remove .NET Framework 4.0 2023-11-21 10:19:15 -05:00
Matt Nadareski
7b998de2ca Handle more C# 12 syntax 2023-11-21 10:17:25 -05:00
Matt Nadareski
b0d49f52a5 Bump version 2023-11-20 12:16:53 -05:00
Matt Nadareski
6f9bcc2111 Fix multiple invocation bug
This bug arose when all of the libraries were consoliated into the same library for better packaging. Each set of classes was being instantiated 3 times as a result.
2023-11-18 20:55:32 -05:00
Matt Nadareski
0fb0ecd28a Update ST libraries for bugfixes 2023-11-15 12:54:32 -05:00
Matt Nadareski
6194d88aec Correct the excludes 2023-11-15 11:26:00 -05:00
Matt Nadareski
b02c3121fe Use official package for IProgress 2023-11-15 00:24:47 -05:00
Matt Nadareski
580db0cb65 Minor tweaks to reduce warnings 2023-11-14 23:48:35 -05:00
Matt Nadareski
6bcdc0e3c6 Bump version 2023-11-14 16:16:08 -05:00
Matt Nadareski
9b4fd91717 Update build scripts 2023-11-14 16:13:49 -05:00
Matt Nadareski
9421249b8e Support ancient .NET 2023-11-14 16:10:10 -05:00
Matt Nadareski
e823cbaee5 Expand supported RIDs 2023-11-08 22:51:47 -05:00
Matt Nadareski
c34618554b Update project comment 2023-11-08 12:08:22 -05:00
Matt Nadareski
6ab7b4a004 Enable latest language version 2023-11-08 11:59:50 -05:00
Matt Nadareski
5b6bf3b73e Rename to BinaryObjectScanner 2023-11-08 11:37:27 -05:00
Matt Nadareski
2a30a13f5f Omit submodule code for modern .NET 2023-10-27 00:58:03 -04:00
Matt Nadareski
3c05a112ca Remove DLLs from modern .NET builds 2023-10-27 00:55:31 -04:00
Matt Nadareski
66af2d83b8 Bump version 2023-10-26 00:35:18 -04:00
Matt Nadareski
fc3be76657 Figure out last couple of nullability issues 2023-10-26 00:27:38 -04:00
Matt Nadareski
259a91dd77 Ensure that the nupkg has the right name 2023-10-26 00:18:48 -04:00
Matt Nadareski
e957b29bae Remove unncessary/broken appveyor zips 2023-10-26 00:10:18 -04:00
Matt Nadareski
33060d9787 Sync appveyor script further to build release 2023-10-26 00:08:22 -04:00
Matt Nadareski
71ca79a456 Update SharpCompress and SharpZipLib 2023-10-26 00:00:34 -04:00
Matt Nadareski
fc744d241a Normalize archive naming with MPF 2023-10-25 23:56:20 -04:00
Matt Nadareski
78b5b3dbc1 Add publish scripts for easier distribution 2023-10-25 23:51:07 -04:00
Matt Nadareski
cb3846261a Fix more nullability locations 2023-10-25 23:33:51 -04:00
Matt Nadareski
9a3dcf70de Slight reordering of XMID/XeMID 2023-10-25 23:16:51 -04:00
Matt Nadareski
670c78302f Add printing for IRD, XMID, XeMID 2023-10-25 23:03:40 -04:00
Matt Nadareski
f4cb97b3bf Bump all ST library versions 2023-10-25 23:03:20 -04:00
TheRogueArchivist
be6d44ed04 Add WEB-Cops detection to CD/DVD-Cops (#268) 2023-10-04 17:55:10 -07:00
TheRogueArchivist
cfc9092479 Add DigiGuard detection (#267)
* Add DigiGuard detection

* Use FilePathMatch instead of PathMatch
2023-10-01 19:05:04 -07:00
TheRogueArchivist
d674ae5b1f Add new CD/DVD-Cops detections (#266) 2023-10-01 11:59:20 -07:00
Matt Nadareski
864972e575 Update packages to fix printing issues 2023-09-29 11:48:42 -04:00
Matt Nadareski
7d97850cb0 Fix some more nullability warnings 2023-09-26 15:31:43 -04:00
Matt Nadareski
3e33f098a6 Fix solution file 2023-09-26 15:25:30 -04:00
Matt Nadareski
adf9ce5e2a Matching to 1.1.1, OpenMcdf to 2.3.0 2023-09-18 15:53:24 -04:00
Matt Nadareski
0c5dff71e9 More nullability fixes 2023-09-18 14:58:33 -04:00
Matt Nadareski
715f773672 Fix DLL inclusion issues 2023-09-18 14:15:51 -04:00
Matt Nadareski
a54b89d380 Make the leap to BinaryObjectScanner 2023-09-18 13:56:07 -04:00
Matt Nadareski
2085c306ab Move stormlibsharp to main library 2023-09-18 12:52:42 -04:00
Matt Nadareski
98b99da0bc Remove stormlibsharp from Compression 2023-09-18 12:15:24 -04:00
Matt Nadareski
e00238b24e Migrate to compression library, mostly 2023-09-18 12:09:54 -04:00
Matt Nadareski
aef2b756c9 Add warning in Extractor 2023-09-18 11:35:52 -04:00
Matt Nadareski
f1f1e20a3e Remove reference to incomplete compressions 2023-09-18 11:33:25 -04:00
Matt Nadareski
62a2fdeaa6 Remove incomplete compressions 2023-09-18 11:24:12 -04:00
Matt Nadareski
37c1852058 Remove unnecessary package references 2023-09-18 01:24:44 -04:00
Matt Nadareski
99c4a08d83 Remove two incomplete compressions 2023-09-18 01:14:01 -04:00
Matt Nadareski
9d4bc6bfab Move psxt001z to its own library 2023-09-18 00:59:37 -04:00
Matt Nadareski
71fd5af48e Move some classes to new library 2023-09-18 00:33:24 -04:00
Matt Nadareski
995521b789 Move Utilities to new library 2023-09-18 00:13:23 -04:00
Matt Nadareski
5031985883 Shift references around to be more accurate 2023-09-18 00:06:07 -04:00
Matt Nadareski
5759090291 Move FileType to new library 2023-09-17 23:58:42 -04:00
Matt Nadareski
008c1c89fb Move Protection to new library 2023-09-17 23:53:14 -04:00
Matt Nadareski
624eb40315 Move Packer to new library 2023-09-17 23:40:29 -04:00
Matt Nadareski
aaa12ae817 Move GameEngine to new library 2023-09-17 23:35:59 -04:00
Matt Nadareski
d37c90878c Move Interfaces to new library 2023-09-17 23:32:29 -04:00
Matt Nadareski
668a631c11 Create new base library 2023-09-17 23:28:27 -04:00
Matt Nadareski
f06c0f4553 Simplify some directives 2023-09-17 23:11:32 -04:00
Matt Nadareski
a0b13a6e6f Fix templated nullability issues 2023-09-17 22:37:01 -04:00
Matt Nadareski
1bd9f3fd88 Open the nullability floodgates 2023-09-17 00:20:33 -04:00
Matt Nadareski
93ba88a35f Enable nullable context and move WrapperFactory 2023-09-17 00:18:04 -04:00
Matt Nadareski
c86b1251a3 Extraction can go in FileType 2023-09-16 23:09:07 -04:00
Matt Nadareski
6f6954b270 Printing is only used by Test 2023-09-16 22:33:43 -04:00
Matt Nadareski
1d4ed425f1 Remove unnecessary dependency 2023-09-16 22:24:00 -04:00
Matt Nadareski
ba657e28ad Migrate to matching library 2023-09-16 22:08:18 -04:00
Matt Nadareski
7575353597 Add nullability to matching library, fix warnings 2023-09-16 21:25:50 -04:00
Matt Nadareski
10d3c09cfa Migrate to printing library 2023-09-16 16:28:41 -04:00
Matt Nadareski
5001c4a881 Fix build from previous updates 2023-09-16 02:04:47 -04:00
Matt Nadareski
7ecd0d1893 Fix using statements in interfaces 2023-09-16 01:00:47 -04:00
Matt Nadareski
ae802d5d75 Update serialization library 2023-09-16 00:58:24 -04:00
Matt Nadareski
3b4266246d Update serialization library 2023-09-16 00:50:48 -04:00
Matt Nadareski
a801e720b2 Use wrappers from Serialization (nw) 2023-09-16 00:44:22 -04:00
Matt Nadareski
a52d45f7c2 Use exposed model directly in more places 2023-09-15 22:21:05 -04:00
Matt Nadareski
57eaa1f04c Make wrapper model visible 2023-09-15 14:15:28 -04:00
Matt Nadareski
6cc2cc5be2 Port XZP to new printing 2023-09-15 13:55:56 -04:00
Matt Nadareski
ebcdc08a77 Port WAD to new printing 2023-09-15 12:01:56 -04:00
Matt Nadareski
7aebdf56fc Port VPK to new printing 2023-09-15 11:50:40 -04:00
Matt Nadareski
6de36eb71c Port VBSP to new printing 2023-09-15 11:37:04 -04:00
Matt Nadareski
5ebd392c5b Port SGA to new printing 2023-09-15 11:25:21 -04:00
Matt Nadareski
5fc2029725 Port Quantum to new printing 2023-09-15 02:48:19 -04:00
Matt Nadareski
45e4a01fc1 Port PE to new printing 2023-09-15 02:37:45 -04:00
Matt Nadareski
c4ea7891ea Port PlayJ to new printing 2023-09-15 01:29:29 -04:00
Matt Nadareski
de871fb8c1 Port PFF to new printing 2023-09-15 01:03:48 -04:00
Matt Nadareski
c322eebb98 Port PAK to new printing 2023-09-15 00:54:40 -04:00
Matt Nadareski
ea6b0f1ca3 Port Nitro to new printing 2023-09-15 00:47:44 -04:00
Matt Nadareski
a35a9a4ab6 Add byte array to encoding extension 2023-09-15 00:23:03 -04:00
Matt Nadareski
9a93c7b15d Port NE to new printing 2023-09-15 00:21:12 -04:00
Matt Nadareski
43eed75635 Port NCF to new printing 2023-09-14 23:52:06 -04:00
Matt Nadareski
74ea6e6002 Port N3DS to new printing 2023-09-14 23:36:29 -04:00
Matt Nadareski
91e2157622 Retrofit existing printers to use extensions 2023-09-14 23:25:39 -04:00
Matt Nadareski
87961e5451 Add StringBuilder extensions to be more consistent 2023-09-14 21:21:08 -04:00
Matt Nadareski
4ff203f393 Port MZ to new printing 2023-09-13 22:46:46 -04:00
Matt Nadareski
410b2bef2b Fix one nullability issue 2023-09-13 22:40:00 -04:00
Matt Nadareski
a9792fdff1 Port MS-CAB to new printing 2023-09-13 22:38:01 -04:00
Matt Nadareski
92e36527fd Port LE/LX to new printing 2023-09-13 22:03:11 -04:00
Matt Nadareski
aa1d7d475c Fix build from oversight 2023-09-13 21:28:09 -04:00
Matt Nadareski
91185c4fe1 Port IS-CAB to new printing 2023-09-13 21:21:19 -04:00
Matt Nadareski
c527b1911f Port GCF to new printing 2023-09-13 13:52:54 -04:00
Matt Nadareski
d1501b2e3e Remove .NET 8 entirely (thanks AppVeyor) 2023-09-13 13:17:08 -04:00
Matt Nadareski
03ac117844 Disable .NET 8 for Test 2023-09-13 13:14:11 -04:00
Matt Nadareski
515be8b025 Port CIA to new printing 2023-09-13 13:12:31 -04:00
Matt Nadareski
c3479450f5 Disable AppVeyor restore until .NET 8 support 2023-09-13 12:52:57 -04:00
Matt Nadareski
611aa3229c Port CFB to new printing 2023-09-13 12:49:46 -04:00
Matt Nadareski
5a865f3d08 Fix one nullability issue 2023-09-13 12:35:08 -04:00
Matt Nadareski
9d8d5c23c8 Clean up project files a little 2023-09-13 11:21:06 -04:00
Matt Nadareski
3fed1a3282 Allow building with .NET 8 2023-09-13 10:48:21 -04:00
Matt Nadareski
f47387c3a4 Port BSP to new printing 2023-09-13 10:41:24 -04:00
Matt Nadareski
133272acb7 Flatten some of the printing code 2023-09-13 10:32:02 -04:00
Matt Nadareski
c49ae98df5 Port BFPK to new printing 2023-09-13 01:37:13 -04:00
Matt Nadareski
a1672a9bc0 Port BD+ to new printing 2023-09-13 01:29:50 -04:00
Matt Nadareski
ffc2e23b2f Let's try a new library for this instead 2023-09-13 01:24:42 -04:00
Matt Nadareski
c481e73418 Take it one step further (test) 2023-09-13 01:15:57 -04:00
Matt Nadareski
06b3124b62 Attempt to make most printing static (test) 2023-09-13 01:14:25 -04:00
Matt Nadareski
d7d81665a0 Fix miscellaneous nullability warnings 2023-09-13 00:29:21 -04:00
Matt Nadareski
24c542c22f Fix "converting null literal" warnings 2023-09-13 00:16:27 -04:00
Matt Nadareski
ec616fcdac Fix "dereference" warnings 2023-09-13 00:08:11 -04:00
Matt Nadareski
24e9455733 Fix "possible null reference" warnings 2023-09-12 17:12:23 -04:00
Matt Nadareski
58aaf46a0e Merge branch 'master' of https://github.com/mnadareski/BurnOutSharp 2023-09-12 12:35:41 -04:00
Matt Nadareski
54e92fe9c8 Fix "nullability of reference types" warnings 2023-09-12 12:35:19 -04:00
Matt Nadareski
4bb83c5d86 Don't allow model to be nullable 2023-09-11 23:38:51 -04:00
Matt Nadareski
2f9280460e Make wrappers more type-defined 2023-09-11 23:25:09 -04:00
Matt Nadareski
30e8e79cf7 Fix PE references 2023-09-11 21:08:08 -04:00
Matt Nadareski
7bb0d4f39a Migrate to ASN1 package 2023-09-11 20:59:11 -04:00
TheRogueArchivist
046814b7c4 Add new EasyAntiCheat file detections (#265)
* Add new EasyAntiCheat file detections

* Add additional EasyAntiCheat file detections
2023-09-11 07:42:54 -07:00
Matt Nadareski
cf00348d46 Update Serialization to 1.1.1 2023-09-11 01:21:38 -04:00
Matt Nadareski
8466edf80f Migrate to Serialization package 2023-09-10 23:51:38 -04:00
Matt Nadareski
ccdf539ed4 Merge branch 'master' of https://github.com/mnadareski/BurnOutSharp 2023-09-10 23:26:54 -04:00
Matt Nadareski
aeee6e9cda Fix build from package update 2023-09-10 23:26:32 -04:00
TheRogueArchivist
2af21cb245 Add DRML link to engine32 (#264) 2023-09-10 20:21:27 -07:00
Matt Nadareski
96fb5a2f93 Update Models to 1.1.1 2023-09-10 21:56:14 -04:00
Matt Nadareski
1eaefb16ba Use IO package for array and stream extensions 2023-09-08 16:33:06 -04:00
Matt Nadareski
1c972a29a7 Migrate INI reading to Nuget 2023-09-08 12:19:31 -04:00
Matt Nadareski
aa33c083fe Fix package reference for Models 2023-09-08 10:36:45 -04:00
Matt Nadareski
a9454e96ed Migrate to Nuget package for Models 2023-09-04 23:44:45 -04:00
Matt Nadareski
fb6fa85cd3 Merge branch 'master' of https://github.com/mnadareski/BurnOutSharp 2023-09-04 22:58:25 -04:00
TheRogueArchivist
3c12bdc212 Add Engine32 detection (#263)
* Add Engine32 detection

* Address PR comment
2023-08-28 12:09:25 -07:00
Matt Nadareski
5eeee760f7 Remove unnecessary param summaries 2023-08-26 22:53:35 -04:00
Matt Nadareski
cfe889d5b3 Add and use FilePathMatch (fixes #262) 2023-08-26 22:51:55 -04:00
TheRogueArchivist
3045c41eda Fix Uplay false positive (#261)
Fix a false positive that resulted in "yuPlay.exe" being detected as Uplay.
2023-08-26 19:02:26 -07:00
TheRogueArchivist
d194ef9dd8 Add new SafeCast version (#260) 2023-07-19 10:30:48 -07:00
Matt Nadareski
aeb379f307 Bump version to 2.8 2023-07-14 11:37:17 -04:00
TheRogueArchivist
cae0edfb49 Add DRML links to Denuvo AC and PlayJ (#259) 2023-07-14 08:35:09 -07:00
TheRogueArchivist
e97558db1f Add new HexaLock check (#254) 2023-05-30 17:56:19 -07:00
Matt Nadareski
06ecc1a571 Temporarily disable MS-CAB extraction
This only affects the code for normal protection scans. This does not affect trying to run extract separately, mainly for the purposes of testing.
2023-05-30 13:43:35 -04:00
TheRogueArchivist
adcf9ee27e Add hash check for RipGuard (#252)
* Add hash check for RipGuard

* Make sure the file exists before trying to hash it

* It's the safety dance
2023-05-14 12:45:30 -07:00
TheRogueArchivist
a8c759be55 Add basic RipGuard detection (#251)
* Add basic RipGuard detection and notes.
2023-05-04 05:24:33 -07:00
Matt Nadareski
ecf97de439 Use larger output buffer for MSZIP 2023-04-28 15:14:28 -04:00
TheRogueArchivist
f134de6609 Minor SecDrv cleanup (#249)
Update comments and improve output.
2023-04-22 18:18:09 -07:00
TheRogueArchivist
d91ce3100b Overhaul Macrovision and related protections (#248)
* Improve several SafeCast checks

* Add new SafeCast versions.

* Add SafeCast NE checks.

* Move stxt* checks to Macrovision, and add SafeCast specific check.

* Confirm SafeCast file and add relevant executable checks.

* Add empty file detection for some SafeDisc drivers.

* Various Macrovision improvements

* Move and improve stxt* section checks.

* Add proper Redump entry number for Puyo Puyo Fever.

* Add directory separator to some SafeDisc checks to avoid false positives.

* Add SafeWrap skeleton with notes.

* Minor Macrovision fixes

* Fix stxt* section checks.

* Add product identification for one CDS-300 version.

* Further Macrovision improvements

* Add product detection via version for SafeDisc Lite and SafeCast ESD.

* Add improved SafeDisc LT/Lite checks.

* Add various notes about SafeCast/SafeDisc.

* Add new secdrv version detection.

* Herald the upcoming secdrv cataclysm.

* Move SecDrv checks into Macrovision

* Move SecDrv checks into Macrovision, as it's known to be present on multiple Macrovision products.

* Improve SafeCast checks

* Add new SafeCast executable and path checks.

* Change a C-Dilla output.

* ah sweet, man-made horrors beyond my comprehension

* Split new and old "BoG" string checks to make finding an expunged version easier.

* Confirm unconfirmed SafeCast version, add new unconfirmed version.

* Remove now unneeded result list cleaning.

* Improve SafeCast notes.

* Add new SafeCast file description and file name checks.

* Remove "GetSafeDisc320to4xVersion" and improve CLCD16 version report.

* Address PR comments

* Address further PR comments
2023-04-21 19:38:18 -07:00
Matt Nadareski
20de40014d Fix version info reading 2023-03-27 10:46:05 -04:00
TheRogueArchivist
a7f9a99d10 Overhaul SVKP (#246)
* Begin SVKP Overhaul

* Add several entry point checks for SVKP, as well as a section check.

* Add SVKP notes.

* Add unconfirmed message in various ActiveMARK checks.

* Add file detections for SVKP

* Add file detections for SVKP.
* Cleanup notes.
* Update README.
2023-03-24 07:35:37 -07:00
TheRogueArchivist
4bdfbabaab Add new SafeDisc DrvMgt detection (#247)
* Add new SafeDisc DrvMgt detection.
2023-03-24 06:03:56 -07:00
TheRogueArchivist
5465c57d96 Add NeoLite detection (#245)
* Add NeoLite detection.
* Update README.
2023-03-22 11:26:25 -07:00
TheRogueArchivist
5082c8f705 Add RenderWare detection (#244)
* Add RenderWare detection.
* Remove unneeded note from SafeDisc.
* Update README.
2023-03-22 10:20:22 -07:00
Matt Nadareski
509fff4684 Reset state.ll for dynamic 2023-03-21 14:14:17 -04:00
Matt Nadareski
9d2c14f809 Fix MSZIP signature check (nw) 2023-03-21 13:39:25 -04:00
Matt Nadareski
b023549b87 Add note for IExtractable 2023-03-21 13:14:42 -04:00
Matt Nadareski
0983073538 Add game engine detection skeleton 2023-03-21 10:42:14 -04:00
TheRogueArchivist
815acf2ce0 Add NEAC Protect detection (#241)
* Add NEAC Protect detection

* Add NEAC Protect detection.
* Update README.

* Address PR comments
2023-03-16 12:38:30 -07:00
Matt Nadareski
6b8596466b Add unused MS-DOS executable check interface 2023-03-15 16:12:12 -04:00
Matt Nadareski
1e5bb7df64 Simplify packer handling code 2023-03-15 15:58:19 -04:00
Matt Nadareski
e920bfc69c Executable is not inherently extractable 2023-03-15 15:53:24 -04:00
Matt Nadareski
a85c6f4028 Rearrange Executable-related things 2023-03-15 15:51:38 -04:00
Matt Nadareski
a75bc15f29 Update IPathCheck helper a bit 2023-03-15 14:21:02 -04:00
Matt Nadareski
659aa30fb3 Update names, access permissions 2023-03-15 14:16:20 -04:00
Matt Nadareski
54a11916d2 Cleanup namespaces 2023-03-15 13:16:21 -04:00
Matt Nadareski
47f423d092 Implement IPathCheck helper 2023-03-15 12:55:08 -04:00
Matt Nadareski
5c5e68e31d Gut Executable for now 2023-03-15 11:37:20 -04:00
Matt Nadareski
9e917e2bb9 Create new Scanner helper classes 2023-03-15 11:06:29 -04:00
Matt Nadareski
4bd4d2f395 Remove errant using statement 2023-03-13 22:58:37 -04:00
Matt Nadareski
6406248840 Make extractable packers safer 2023-03-13 22:53:57 -04:00
Matt Nadareski
3d8134bbd3 Map out Executable extraction skeleton 2023-03-13 22:36:28 -04:00
Matt Nadareski
15310a6c47 Change namespaces but don't move yet 2023-03-13 22:22:52 -04:00
Matt Nadareski
450a8cd5bd Migrate wrapper methods to proper factory 2023-03-13 22:07:28 -04:00
Matt Nadareski
088f99942f Move file type helpers to Utilities 2023-03-13 22:03:10 -04:00
Matt Nadareski
3e97bd8d2d Move SupportedFileType to correct namespace 2023-03-13 21:54:40 -04:00
Matt Nadareski
866051c975 Fix MPQ namespace 2023-03-13 21:49:25 -04:00
Matt Nadareski
0be437f3cf Add skeleton to Scanner helpers 2023-03-13 21:47:40 -04:00
Matt Nadareski
11f3dec65d Add more notes about extraction 2023-03-13 21:45:17 -04:00
Matt Nadareski
912d151164 Add skeleton implementions in Executable 2023-03-13 21:12:11 -04:00
Matt Nadareski
863678f850 Add extractable protections to caches 2023-03-13 21:05:18 -04:00
Matt Nadareski
b82a6a8c5d Simplify some Executable code
Hopefully, simplifying this code will open the door to getting rid of `IScannable` in some way
2023-03-13 20:49:59 -04:00
Matt Nadareski
ab2daf2a80 Fix helper in Executable 2023-03-13 20:39:50 -04:00
Matt Nadareski
f734e3a58a Move MPQ to proper library, fix stormlibsharp 2023-03-13 16:41:53 -04:00
Matt Nadareski
212981fda9 Move stormlibsharp to Compression 2023-03-13 16:31:34 -04:00
Matt Nadareski
c64e138ba7 Figure out how to convert Textfile 2023-03-13 16:17:21 -04:00
Matt Nadareski
c43353d126 Move most detectables to new interface 2023-03-13 16:06:45 -04:00
Matt Nadareski
d439ba9592 Add unused IDetectable interface 2023-03-13 15:34:26 -04:00
Matt Nadareski
b7f06f0b59 Move extractable file types to new library 2023-03-10 13:48:24 -05:00
Matt Nadareski
60d666f8be Add skeleton file type library 2023-03-10 11:55:19 -05:00
Matt Nadareski
4ff4c2afef Move helper methods used in a single place 2023-03-10 11:41:08 -05:00
Matt Nadareski
655b8385f9 Rename tool class 2023-03-10 11:20:35 -05:00
Matt Nadareski
439c141c2c Move packer scans to their own library 2023-03-09 23:52:58 -05:00
Matt Nadareski
95755b930d Add packer library skeleton 2023-03-09 23:31:45 -05:00
Matt Nadareski
9cf54c1f2d Create dummy class for protection library 2023-03-09 23:26:18 -05:00
Matt Nadareski
e118418a23 Move protection scans to their own library
This change also removes a couple of things from `BurnOutSharp.Tools.Utilities` that are no longer needed there. Linear executables are included in the scanning classes. Update the guides accordingly.
2023-03-09 23:19:27 -05:00
Matt Nadareski
a3567d6eb2 Add protection library skeleton 2023-03-09 20:50:59 -05:00
Matt Nadareski
a359143bc7 Include debug in IExtractable 2023-03-09 17:16:39 -05:00
Matt Nadareski
77b7a24d85 Add TODO in Executable 2023-03-09 16:12:21 -05:00
Matt Nadareski
338b2593d5 Update guides 2023-03-09 16:08:56 -05:00
Matt Nadareski
ded5e27355 Migrate packers to extractable only 2023-03-09 16:02:51 -05:00
Matt Nadareski
ee1b005d96 Add call to packer extraction 2023-03-09 15:50:14 -05:00
Matt Nadareski
cd2673d1ba Implement unused packer extractions 2023-03-09 15:46:48 -05:00
Matt Nadareski
41d77085ae Add IExtractable skeletons to packers 2023-03-09 15:33:21 -05:00
Matt Nadareski
67059b2e43 Update guides 2023-03-09 15:17:35 -05:00
Matt Nadareski
f6157ef79b Implementations act the same 2023-03-09 15:07:35 -05:00
Matt Nadareski
6e5d517e82 Replace parts of Scan with Extract 2023-03-09 14:50:24 -05:00
Matt Nadareski
1dca51988a Implement unused extractions 2023-03-09 14:39:26 -05:00
Matt Nadareski
3c064bad55 Add skeleton IExtractable implementations 2023-03-09 14:04:31 -05:00
Matt Nadareski
d60a3ce05a Add extractable interface (unused) 2023-03-09 13:48:51 -05:00
Matt Nadareski
f68438ff8c Remove some errant temp directories 2023-03-09 13:45:42 -05:00
Matt Nadareski
d351f1d08e Create separate Options object 2023-03-09 13:26:20 -05:00
Matt Nadareski
70bdb8f37d Move most interfaces to separate library 2023-03-09 11:52:28 -05:00
TheRogueArchivist
3cd713e078 Add SafeDisc entry point check (#240)
* Add SafeDisc entry point check

* Add SafeDisc entry point check

* Address PR comments
2023-03-08 18:46:14 -08:00
Matt Nadareski
454655de5a Missed a couple in Wrappers 2023-03-08 17:53:26 -05:00
Matt Nadareski
268ed1a6a6 Clean up namespaces in Builders 2023-03-08 17:51:17 -05:00
Matt Nadareski
a42ce601b8 Simplify namespaces in Wrappers 2023-03-08 17:49:14 -05:00
Matt Nadareski
756b37ef6c Minor update for clarity 2023-03-08 17:16:29 -05:00
TheRogueArchivist
ab7e708e02 fuck macrovision (#239)
* Make SafeDisc stxt* section checks more accurate.
* Add unknown SafeDisc section notes.
2023-03-08 14:08:36 -08:00
TheRogueArchivist
326d916c0b Separate unconfirmed Macrovision checks (#238)
* Separate unconfirmed Macrovision checks

* Separate unconfirmed Macrovision checks.

* Separate unconfirmed SafeDisc version

* Separate unconfirmed SafeDisc version.
2023-03-08 13:21:34 -08:00
Matt Nadareski
db09bd931b Macrovision-adjacent additions (TheRogueArchivist) 2023-03-08 15:21:21 -05:00
TheRogueArchivist
d1e9eb90f1 Add DRML link to phenoProtect (#235)
* Add DRML link to phenoProtect.
* Fix case of the "phenoProtect" class name.
2023-03-08 11:59:57 -08:00
Matt Nadareski
20a5c4c78d Use new Macrovision helper method 2023-03-08 09:50:34 -05:00
Matt Nadareski
499f9888b1 Create helper for Macrovision version mapping 2023-03-08 09:40:19 -05:00
Matt Nadareski
7bb3364b43 Trim not TrimEnd 2023-03-08 08:47:46 -05:00
Matt Nadareski
473cbc5694 BOS.* -> BOS.* 2023-03-07 16:59:14 -05:00
Matt Nadareski
e32b24c9f6 BOS.ASN1 -> BOS.ASN1 2023-03-07 12:42:39 -05:00
Matt Nadareski
777fdc14c8 BOS.Utilities -> BOS.Utilities 2023-03-07 12:04:48 -05:00
Matt Nadareski
ffbb01c25c Migrate CDS path checks 2023-03-07 11:31:55 -05:00
Matt Nadareski
47380c2c1c Start migrating CDS, fix Macrovision directory check 2023-03-07 11:28:02 -05:00
Matt Nadareski
51e9121a6b Update generic Macrovision check 2023-03-07 11:22:45 -05:00
Matt Nadareski
94f51d518d Move SafeDisc-specific checks 2023-03-07 11:19:18 -05:00
Matt Nadareski
8fdc17b239 Missed an access modifier 2023-03-07 11:12:31 -05:00
Matt Nadareski
42bb29185f Macrovision cleanup 2023-03-07 11:10:56 -05:00
Matt Nadareski
05ae0f4e80 Add .NET 7 support 2023-03-06 09:34:51 -05:00
Matt Nadareski
092374a143 Bump version to 2.7 2023-03-06 08:57:43 -05:00
TheRogueArchivist
3cfb60430a Split SafeDisc and CDS-300 checks (#236)
* Split SafeDisc/CDS-300 checks.
* Add new DrvMgt.dll hash check.
2023-03-05 14:33:39 -08:00
TheRogueArchivist
370cc68fa4 Move Freelock notes to DRML (#233)
* Move Freelock notes to DRML.
* Add new Freelock checks.
* Tweak some Freelock output.,
* Fix existing DRML links from other protections.
2023-02-09 06:05:13 -08:00
TheRogueArchivist
8fe5046c19 Add new MGI Registration check (#232)
* Add new MGI Registration check

* Add new MGI Registration check

* Address PR comment

* Address PR comment
2023-02-08 13:04:47 -08:00
TheRogueArchivist
37e7604441 Add MGI Registration detection (#231)
* Add MGI Registration detection.
* Update README.
2023-02-08 11:43:15 -08:00
TheRogueArchivist
7651b34855 Add new CD-Key/Serial check (#230)
* Add new CD-Key/Serial check.
2023-02-07 07:00:04 -08:00
TheRogueArchivist
4bf89b1d5f Add new known C-Dilla versions (#229)
* Add two new known C-Dilla versions.

* Make IA samples more consistent.

* Remove TODO.
2023-02-07 06:59:49 -08:00
TheRogueArchivist
0287284909 Add more CD-Cops notes (#228)
* Add more CD-Cops notes and samples.
2023-02-07 06:59:31 -08:00
Matt Nadareski
a8453b3f21 Descriptions for all! 2023-01-18 11:18:53 -08:00
Matt Nadareski
2552564953 Create wrapper creation method 2023-01-18 10:56:19 -08:00
Matt Nadareski
0d4d19559a else if and a note 2023-01-18 08:39:27 -08:00
Matt Nadareski
52f4132ccb Be smarter about EXE checks 2023-01-18 08:36:16 -08:00
Matt Nadareski
cb6440662b Create LE during scan as well 2023-01-17 20:22:25 -08:00
Matt Nadareski
6293895611 Make it so debug doesn't return early 2023-01-17 20:21:25 -08:00
Matt Nadareski
f564fb6e9e Make JSON handling internally a bit easier 2023-01-16 22:15:45 -08:00
Matt Nadareski
3f2adfcf62 Add explicit note about JSON output 2023-01-16 22:12:54 -08:00
Matt Nadareski
2c979f291e Add Options class, allow multiple features 2023-01-16 21:52:32 -08:00
Matt Nadareski
7e7b2ee64a Support PFF version 0 (nw) 2023-01-16 14:34:28 -08:00
Matt Nadareski
87108405a8 Add PFF support (full) 2023-01-15 23:33:09 -08:00
Matt Nadareski
9fb055cbff Move file name into try/catch 2023-01-15 17:45:11 -08:00
Matt Nadareski
e690f0137e Don't try to unpack invalid IS-CAB files 2023-01-15 17:44:25 -08:00
Matt Nadareski
87c08d6fbd Replace EntryHeader with AudioHeader 2023-01-15 16:26:05 -08:00
Matt Nadareski
8c164d776e Start adding separate header information 2023-01-15 12:30:22 -08:00
Matt Nadareski
964271b4e1 Remove now-redundant note 2023-01-15 11:57:41 -08:00
Matt Nadareski
e99ba48f07 Determine PLJv2 Block 3 format, add notes 2023-01-15 02:07:56 -08:00
Matt Nadareski
62b1627b04 More PLJv2 notes/support 2023-01-15 00:19:16 -08:00
Matt Nadareski
3a54997d42 Fix corner case in rapid scans 2023-01-14 23:31:31 -08:00
Matt Nadareski
7d95a43b4b Fix RCDATA issue 2023-01-14 23:26:52 -08:00
Matt Nadareski
23ea8710c0 Read PLJv2 track ID and year 2023-01-14 23:14:50 -08:00
Matt Nadareski
0b62a52991 PLJv2 doesn't seem to have offsets 2023-01-14 23:06:50 -08:00
Matt Nadareski
1143c8a8b7 Add notes, fix v2 skipping 2023-01-14 22:52:22 -08:00
Matt Nadareski
a5b66caae6 "Support" PlayJ v2 by skipping fields 2023-01-14 22:36:57 -08:00
Matt Nadareski
b0b87d05fd Add PLJ builders/wrappers/printing 2023-01-14 22:24:25 -08:00
Matt Nadareski
cb3c666f64 Add PlayJ models 2023-01-14 21:43:59 -08:00
Matt Nadareski
12fdae7944 Fill in more notes before modelling 2023-01-14 21:20:45 -08:00
Matt Nadareski
e76bc70ec6 Fill out more PLJ notes before modelling 2023-01-14 19:47:24 -08:00
Matt Nadareski
e78bb8cb41 Add PLJ header format notes 2023-01-14 14:19:38 -08:00
Matt Nadareski
5153e73f42 Update README 2023-01-14 01:40:57 -08:00
Matt Nadareski
7f36ff8a2b More fixes to IS-CAB 2023-01-14 01:39:15 -08:00
TheRogueArchivist
99a8a39dda Move MediaCloQ notes to DRML (#227)
* Move MediaCloQ notes to DRML.
* Add TODO and fix typo.
2023-01-14 00:44:10 -08:00
Matt Nadareski
adbf983e65 Hook up IS-CAB printing 2023-01-14 00:42:03 -08:00
Matt Nadareski
d7639495ac Fill in some missing IS-CAB parts 2023-01-14 00:41:13 -08:00
Matt Nadareski
fbe09d9082 Add IS-CAB wrapper 2023-01-13 22:24:25 -08:00
Matt Nadareski
70468b72c3 Fix up IS-CAB a little 2023-01-13 21:40:01 -08:00
TheRogueArchivist
90f4af1121 Add version finding to DiscGuard (#226)
* Add version finding to DiscGuard

* Add version finding to DiscGuard.

* Update notes.

* Address PR comments
2023-01-13 20:30:42 -08:00
Matt Nadareski
aa37449bbf Update developer guide 2023-01-13 15:34:10 -08:00
Matt Nadareski
c835e04722 Update coding guide 2023-01-13 15:29:56 -08:00
Matt Nadareski
29b999b8ed Info should act like scan 2023-01-13 15:15:30 -08:00
Matt Nadareski
9ddd6cc317 Write info outputs to file for easier use 2023-01-13 14:20:41 -08:00
Matt Nadareski
3a694f0e31 Pretty print uses StringBuildernow 2023-01-13 14:04:21 -08:00
Matt Nadareski
080cbda588 Rename Print to PrettyPrint 2023-01-13 12:02:42 -08:00
Matt Nadareski
fd066e8aae Simplify printer code, don't duplicate print 2023-01-13 11:14:34 -08:00
Matt Nadareski
0fd0cf689a Add JSON serialization to wrappers (.NET 6) 2023-01-13 10:41:50 -08:00
Matt Nadareski
f85adda24c Add some DVD models 2023-01-12 23:38:09 -08:00
Matt Nadareski
2d1e8e02aa Overhaul BD+ to model/builder/wrapper 2023-01-12 14:45:04 -08:00
Matt Nadareski
371fbee7a4 Replace current AACS checks 2023-01-12 13:57:10 -08:00
Matt Nadareski
a5bb95e7c1 Hook up AACS media block printing 2023-01-12 13:29:02 -08:00
Matt Nadareski
53b5a443fe Add AACS wrapper and printing 2023-01-12 13:28:12 -08:00
Matt Nadareski
a230871f75 Add AACS media block builder 2023-01-12 12:28:31 -08:00
Matt Nadareski
f560ce17e8 Add AACS media key block to file types 2023-01-12 09:44:31 -08:00
Matt Nadareski
b96329bd33 Add AACS media key block models 2023-01-12 09:40:02 -08:00
Matt Nadareski
913f7802de Fix LE/LX debug parsing 2023-01-11 13:55:00 -08:00
Matt Nadareski
a9f61ed51e Hook up LE/LX printing 2023-01-11 13:39:49 -08:00
Matt Nadareski
04c0835228 Add LE/LX printing to wrapper 2023-01-11 13:39:23 -08:00
Matt Nadareski
af7ff05ecf Fill out LE/LX builder 2023-01-11 11:44:13 -08:00
Matt Nadareski
4ccf80189e Start filling out LE/LX builder 2023-01-10 23:41:15 -08:00
Matt Nadareski
b417229ee6 Add print debug, fix NE printing 2023-01-10 23:15:59 -08:00
Matt Nadareski
61457582b3 More summary info fleshing out 2023-01-10 12:23:48 -08:00
Matt Nadareski
ecc1613f49 Start adding some MSI-specific things 2023-01-10 11:59:33 -08:00
Matt Nadareski
5ea89eefe8 MSI was really CFB all along 2023-01-10 10:51:36 -08:00
Matt Nadareski
661808826a Add hex to outputs for debugging 2023-01-10 09:50:49 -08:00
Matt Nadareski
342f78ffd0 Add extension properties for sector sizes 2023-01-09 22:23:12 -08:00
Matt Nadareski
cc6a65d5e4 Slight reorganization 2023-01-09 22:17:58 -08:00
Matt Nadareski
068ee76983 Add generic data reading 2023-01-09 22:15:37 -08:00
Matt Nadareski
b980b33019 Add sector chain helpers 2023-01-09 22:04:29 -08:00
Matt Nadareski
4327ce7848 Fix typo in directory entry output 2023-01-09 21:40:56 -08:00
Matt Nadareski
2c813e7b3d Add CFB to the readme 2023-01-09 21:27:00 -08:00
Matt Nadareski
d69746f7ef Fix printing, hook up to printer 2023-01-09 21:18:45 -08:00
Matt Nadareski
ce8f73d30d Add CFB wrapper and printing 2023-01-09 21:14:21 -08:00
Matt Nadareski
d6602ac8a8 Make UPX a little safer 2023-01-09 16:34:45 -08:00
Matt Nadareski
6478af03e7 Add class IDs we care about 2023-01-09 16:34:22 -08:00
Matt Nadareski
f086e63914 Omit top 32-bits for version 3 2023-01-09 16:33:56 -08:00
Matt Nadareski
6fbb6bd8dc Implement directory section parsing 2023-01-09 15:58:10 -08:00
Matt Nadareski
008629b61f Add all but directory sectors 2023-01-09 14:32:40 -08:00
Matt Nadareski
b7704dbe57 Add skeleton builder for CFB 2023-01-09 13:24:11 -08:00
Matt Nadareski
5aff2d0b1b Add CFB models 2023-01-09 13:11:06 -08:00
Matt Nadareski
771bbeed6a Add DS/3DS to readme 2023-01-09 11:43:07 -08:00
Matt Nadareski
53dd1e9aa5 Add alignment, partition parsing, fix BE 2023-01-09 11:33:54 -08:00
Matt Nadareski
6b7ed456ac Hook up CIA to printer 2023-01-09 11:31:17 -08:00
Matt Nadareski
5e2185dffd Add CIA printing 2023-01-09 10:53:15 -08:00
Matt Nadareski
b5d318013b Add CIA builder 2023-01-09 09:53:57 -08:00
Matt Nadareski
07a926e50c Forgot references 2023-01-08 21:39:48 -08:00
Matt Nadareski
78bbb63c11 Fix formatting issue; clarification 2023-01-08 21:34:52 -08:00
Matt Nadareski
1fd613c2b2 "Library" not "utility"; clarification 2023-01-08 21:31:41 -08:00
Matt Nadareski
792833ebc8 Update readme and description 2023-01-08 21:27:23 -08:00
Matt Nadareski
7392fce770 Add NDS name table/FAT printing 2023-01-08 10:24:27 -08:00
Matt Nadareski
6c621c743d Add NDS FAT parsing 2023-01-08 00:20:57 -08:00
Matt Nadareski
50a7883958 Add NDS name table parsing 2023-01-08 00:16:01 -08:00
Matt Nadareski
3882db6fc6 Add RomFS header parsing/printing 2023-01-07 23:09:26 -08:00
Matt Nadareski
c91691f79b Remove duplicate TODO 2023-01-07 22:57:46 -08:00
Matt Nadareski
17fbf1163d Add ExeFS printing 2023-01-07 22:50:31 -08:00
Matt Nadareski
9a1bbd7e0d Add ExeFS header parsing 2023-01-07 22:44:31 -08:00
Matt Nadareski
bf6f3bad46 Print extended headers 2023-01-07 22:33:55 -08:00
Matt Nadareski
b99b2a53cf Add extended header parsing for N3DS 2023-01-07 22:12:58 -08:00
Matt Nadareski
1fec5c15d4 Fix N3DS parsing and printing 2023-01-07 21:42:13 -08:00
Matt Nadareski
a8b13e60b6 Fix printing if-statements 2023-01-07 20:55:17 -08:00
Matt Nadareski
4c0c44de6b Add DS/3DS to Test printer 2023-01-07 14:50:21 -08:00
Matt Nadareski
af0623beea Add DS/3DS to supported file types 2023-01-07 14:47:36 -08:00
Matt Nadareski
761b418d21 Fix DS/3DS sttuff, add 3DS wrapper/printing 2023-01-07 12:33:15 -08:00
Matt Nadareski
0316edb8cb Split header into 2 files 2023-01-06 23:48:26 -08:00
Matt Nadareski
48cf417d60 Add wrapper and printing for NDS 2023-01-06 23:39:32 -08:00
Matt Nadareski
83af2926aa Add N3DS builder 2023-01-06 16:14:00 -08:00
Matt Nadareski
ddfa820004 Add NDS builder 2023-01-06 15:34:04 -08:00
Matt Nadareski
80986978cb Add N3DS to models 2023-01-06 15:20:10 -08:00
Matt Nadareski
68283554e9 Add NDS to models 2023-01-06 14:37:40 -08:00
Matt Nadareski
0fcedfafbe Bump version to 2.6 2023-01-06 13:04:52 -08:00
Matt Nadareski
d075ce4ebd Relicense to MIT
I am relicensing this code with the permission of all code contributors to this port of the code. All code that this is based on is unaffected by this.
2023-01-06 11:43:50 -08:00
Matt Nadareski
3c6fcb4e4d Update to UnshieldSharp 1.6.9 2023-01-06 11:23:29 -08:00
Matt Nadareski
5d37b7947e Use license expression 2023-01-06 10:57:55 -08:00
Matt Nadareski
537b5c83f2 Add commit hash to artifacts 2023-01-06 10:56:49 -08:00
Matt Nadareski
44d2c90aea Update to WiseUnpacker 1.0.4 2023-01-05 23:19:44 -08:00
Matt Nadareski
af0c984b08 Skip trying to parse null debug data 2023-01-05 22:42:54 -08:00
Matt Nadareski
e9f01c7a10 Make ImpulseReactor check safer for null values 2023-01-05 22:30:56 -08:00
TheRogueArchivist
0c468e3489 Fix typo in SafeDisc detection (#224)
* Fix typo in SafeDisc detection.
2023-01-05 20:34:05 -08:00
TheRogueArchivist
aff43b7625 Add encrypted Link Data Security file detection (#223)
* Add encrypted Link Data Security file (LDSCRYPT) detection.

* Update CD-Cops notes.
2023-01-05 14:55:21 -08:00
Matt Nadareski
dc53ebd378 Try outputting directly to the correct folder 2023-01-05 13:15:06 -08:00
Matt Nadareski
7a7518d92a Buillders not Builder 2023-01-05 13:13:22 -08:00
Matt Nadareski
ee182b8ea7 Remove old Nuget remnants, fix relative path 2023-01-05 13:07:45 -08:00
Matt Nadareski
c1bf48480c Avoid moves, reference directly 2023-01-05 13:02:25 -08:00
Matt Nadareski
b5bb88553c Try quotes again, just differently 2023-01-05 12:57:12 -08:00
Matt Nadareski
9b9fc09bdf Add trailing slash for mv 2023-01-05 12:00:46 -08:00
Matt Nadareski
5709c88232 Disable Nuget, rely on dotnet instead 2023-01-05 12:00:13 -08:00
Matt Nadareski
522c9fba08 Try using different mv command 2023-01-05 11:55:14 -08:00
Matt Nadareski
3a7b15f231 Add Nuget packages to auto-build 2023-01-05 11:43:18 -08:00
TheRogueArchivist
cb2c96ef7d Add basic HyperTech CrackProof detection (#222)
* Add basic HyperTech CrackProof detection

* Add super basic, incomplete HyperTech CrackProof detection.

* Address PR comments
2023-01-05 11:24:40 -08:00
Matt Nadareski
f89f691ee3 Archive scanning is not content scanning 2023-01-05 11:00:29 -08:00
Matt Nadareski
a0f59b774a Enable content scanning flag in Test 2023-01-05 10:54:34 -08:00
Matt Nadareski
65adf2109d Add content scanning flag in Scanner/Test 2023-01-05 10:53:06 -08:00
Matt Nadareski
92da1695bf Add path scanning flag to Test 2023-01-05 10:49:01 -08:00
Matt Nadareski
e46011beff Add path scanning flag in Scanner 2023-01-05 10:46:13 -08:00
Matt Nadareski
e733dea80e CD-Cops path checks are case-sensitive 2023-01-05 10:38:11 -08:00
Matt Nadareski
6a27161322 Add WiseInst for old NE Wise 2023-01-04 23:53:46 -08:00
Matt Nadareski
6bb4193167 Hook up NE Wise extraction thru WiseUnpacker again 2023-01-04 23:31:52 -08:00
Matt Nadareski
52c34250ff Add NE Wise note for later 2023-01-04 23:13:45 -08:00
Matt Nadareski
cd72cccbaa Fix incorrect printer output 2023-01-04 23:00:00 -08:00
Matt Nadareski
ad9689440a Use NE format property too (nw) 2023-01-04 22:53:52 -08:00
Matt Nadareski
dd193352e2 Remove unused directory creation 2023-01-04 22:44:14 -08:00
Matt Nadareski
a376041be4 Separate out Wise PE extraction 2023-01-04 22:43:11 -08:00
Matt Nadareski
7d14eb35ba Support PKZIP-compressed Wise installer data 2023-01-04 22:37:44 -08:00
Matt Nadareski
fdad3b0c87 Print first 16 bytes of unknown resources 2023-01-04 20:29:41 -08:00
Matt Nadareski
8ebaa59b5f Add precursor position check for segment validity 2023-01-04 20:24:31 -08:00
Matt Nadareski
6037be404c Fix bad LaserLok check 2023-01-04 20:22:20 -08:00
Matt Nadareski
1ead65126f WIP bzip2 code 2023-01-04 20:19:15 -08:00
Matt Nadareski
cfa1bc8875 Port ADPCM compression from stormlib 2023-01-04 11:03:03 -08:00
Matt Nadareski
cfbac7a9ab Ensure required field marked as such 2023-01-04 10:27:37 -08:00
Matt Nadareski
6f62777033 Split files for clarity 2023-01-04 10:23:03 -08:00
Matt Nadareski
0a523d74d5 x, not e 2023-01-04 10:13:36 -08:00
Matt Nadareski
907d0eb724 Enable experimental extraction feature 2023-01-04 10:10:42 -08:00
Matt Nadareski
edcf20885c Extraction is possible 2023-01-04 10:05:21 -08:00
Matt Nadareski
bb838c5b1f Fix error for small executables 2023-01-03 23:43:34 -08:00
Matt Nadareski
fa90618200 Remove one more note in README 2023-01-03 23:14:24 -08:00
Matt Nadareski
b421d8f818 Order of operations is important 2023-01-03 23:01:43 -08:00
Matt Nadareski
c1151b7e93 Minor cleanup and bugfixing 2023-01-03 22:32:22 -08:00
Matt Nadareski
b1d6b1be9c Fix errantly deleted line in csproj 2023-01-03 22:24:41 -08:00
Matt Nadareski
cb45405e09 Remove remnants of Dtf and LibMSPackSharp 2023-01-03 22:21:29 -08:00
Matt Nadareski
6ef9f2856a Remove Dtf and LibMSPackSharp 2023-01-03 22:15:53 -08:00
Matt Nadareski
c14300ffbb Port MS-ZIP for MS-CAB 2023-01-03 22:11:57 -08:00
Matt Nadareski
42b4c40d87 Port LZX init and decompression 2023-01-03 19:00:21 -08:00
Matt Nadareski
1c78dac79f Port LZX read lengths 2023-01-03 16:11:30 -08:00
Matt Nadareski
bb6a045dd3 Port LZX macros 2023-01-03 16:08:50 -08:00
Matt Nadareski
b273d8314a Migrate some easy LZX stuff 2023-01-03 14:46:30 -08:00
Matt Nadareski
015b895177 Start trying to get Quantum archives to extract 2023-01-03 13:53:44 -08:00
Matt Nadareski
fce9ce4eb4 Handle unknown data better 2023-01-03 10:59:41 -08:00
Matt Nadareski
e6463adb65 Add Quantum to README 2023-01-03 10:46:09 -08:00
Matt Nadareski
b07fd29753 Minor tweaks from issues found during extraction 2023-01-03 10:42:57 -08:00
Matt Nadareski
2416a035c7 Add Quantum archive models/builder/wrapper 2023-01-03 09:28:16 -08:00
Matt Nadareski
c2c125fd29 Add extract all to BFPK 2023-01-03 09:19:35 -08:00
Matt Nadareski
580bf0494d Fix writing cabinet file data 2023-01-03 00:19:03 -08:00
Matt Nadareski
eefc52d1dd Be safer with uneven lengths 2023-01-03 00:14:42 -08:00
Matt Nadareski
c28de855e2 Take sligthly more academic approach 2023-01-03 00:12:31 -08:00
Matt Nadareski
5e2d7505da Consistency tweaks (nw) 2023-01-02 23:54:40 -08:00
Matt Nadareski
f550c96541 Take some cues from libmspack 2023-01-02 23:35:09 -08:00
Matt Nadareski
d222eec1b1 I want to get off the Quantum ride 2023-01-02 22:03:36 -08:00
Matt Nadareski
be129262da Next level is a set of values, not a single one 2023-01-02 15:04:00 -08:00
Matt Nadareski
87080c906d Port more of the easy stuff over 2023-01-02 15:01:24 -08:00
Matt Nadareski
cdeaf09ed6 Start doing a better job with MSZIP 2023-01-02 11:19:06 -08:00
Matt Nadareski
b17f8dac7a Start fixing Quantum with safeguards, hook up 2023-01-02 10:17:27 -08:00
Matt Nadareski
ec758e5c18 Finalize Quantum port to C# (pass 1) 2023-01-02 00:03:03 -08:00
Matt Nadareski
350f9630df Convert macros to methods, mostly 2023-01-01 23:45:13 -08:00
Matt Nadareski
557c760197 Move Quantum macro notes to Compression 2023-01-01 22:06:09 -08:00
Matt Nadareski
895f40414d Some Quantum things to models / compression 2023-01-01 22:02:54 -08:00
Matt Nadareski
96fbb38b1c Bring in the rest of CAB code commented 2023-01-01 21:34:56 -08:00
Matt Nadareski
650d01d7be Update README with SharpZipLib 2022-12-31 11:44:49 -08:00
Matt Nadareski
3977342a67 Fix empty-not-null data 2022-12-31 11:39:35 -08:00
Matt Nadareski
8a61f01e1b Handle last blocks more efficiently 2022-12-31 11:35:22 -08:00
Matt Nadareski
75a4371f36 Handle MS-CAB compression type masking better 2022-12-31 11:21:29 -08:00
Matt Nadareski
86ee4786a0 Add mostly-working MS-ZIP based on zlib 2022-12-31 10:57:49 -08:00
Matt Nadareski
ef710463ae Port more CAB code (nw, commented out) 2022-12-30 23:07:41 -08:00
Matt Nadareski
e6b153bcbd Add last models from headers 2022-12-30 21:25:46 -08:00
Matt Nadareski
9c9eb8ca7b Align to correct boundary, look for executables 2022-12-30 14:00:10 -08:00
Matt Nadareski
295f438ff1 Forgot the after_build tag 2022-12-30 11:15:06 -08:00
TheRogueArchivist
cc1ad3e690 Update Cenega ProtectDVD (#221)
* Add new export check for Cenega ProtectDVD.

* Update notes and add link to DRML.
2022-12-30 09:54:44 -08:00
Matt Nadareski
3ebb3822dd Revert changes to launch.json 2022-12-30 09:38:11 -08:00
Matt Nadareski
6e22bd4c8d Fix hidden resource parsing 2022-12-30 09:35:35 -08:00
Matt Nadareski
1027956892 Lock section names, scan for hidden resources 2022-12-30 09:09:42 -08:00
Matt Nadareski
a46d52ddbb Shout out DRML in README 2022-12-29 23:34:00 -08:00
Matt Nadareski
fd5e78eb8a Open the path to future .NET versions 2022-12-29 23:01:28 -08:00
Matt Nadareski
8a326cbb91 Fix build zipfile names 2022-12-29 22:15:55 -08:00
Matt Nadareski
09a7893021 Try to get better at artifacts 2022-12-29 22:01:07 -08:00
Matt Nadareski
9c10af58d8 Remove AnyCPU from configuration 2022-12-29 21:27:45 -08:00
Matt Nadareski
81fbe251ba Specify all files in publish directories 2022-12-29 21:22:08 -08:00
Matt Nadareski
5203f0ea57 Attempt to fix AppVeyor build issues 2022-12-29 21:13:42 -08:00
Matt Nadareski
51644c2178 Update to latest LibMSPackSharp 2022-12-29 21:11:12 -08:00
Matt Nadareski
f326a20019 Runtime identifiers, explicit .NET Framework 4.8 2022-12-29 21:06:14 -08:00
Matt Nadareski
daea4ea460 Add CrypKey PE content checks 2022-12-28 23:28:38 -08:00
Matt Nadareski
c9c14bcebf Add note of where to find implementation 2022-12-28 23:07:23 -08:00
Matt Nadareski
9dc21c01f1 Add Microsoft LZ-compressed files support 2022-12-28 22:54:56 -08:00
Matt Nadareski
555dbd592c Re-disable MS-CAB extraction on .NET 6.0 2022-12-28 22:31:46 -08:00
Matt Nadareski
5e027b75b2 Update README with CExe extraction support 2022-12-28 22:21:18 -08:00
Matt Nadareski
01a504dab7 Remove unused using 2022-12-28 22:20:32 -08:00
Matt Nadareski
70eeaaac28 Replace direct LZ ports with cleaned versions 2022-12-28 22:18:23 -08:00
Matt Nadareski
0397d529bb Add LZ decompression to CExe 2022-12-28 17:24:55 -08:00
Matt Nadareski
25bed747f2 First ported implementation of LZ 2022-12-28 17:24:30 -08:00
Matt Nadareski
d17b90e782 Fix constant strings 2022-12-28 17:15:42 -08:00
Matt Nadareski
7868e22a95 Fix constant strings 2022-12-28 17:10:42 -08:00
Matt Nadareski
81f6e2057e Add note for future work 2022-12-28 15:37:09 -08:00
Matt Nadareski
1c3e37ee2b Add and use XZP constants 2022-12-28 15:35:54 -08:00
Matt Nadareski
27756db621 Add and use WAD constants 2022-12-28 15:30:22 -08:00
Matt Nadareski
7f71b04ef7 Add and use VPK constants 2022-12-28 15:27:10 -08:00
Matt Nadareski
c48522e6c0 Add and use VBSP constants 2022-12-28 15:22:16 -08:00
Matt Nadareski
fbf629dd8b Add and use SGA constants 2022-12-28 15:17:34 -08:00
Matt Nadareski
404b2889ff Add SFFS constants 2022-12-28 15:13:38 -08:00
Matt Nadareski
5ccb9d16a8 Add and use PE constants 2022-12-28 15:09:31 -08:00
Matt Nadareski
66b562f24b Add and use PAK constants 2022-12-28 15:03:41 -08:00
Matt Nadareski
ef25b88717 Get CExe prepped for LZ 2022-12-28 15:01:59 -08:00
Matt Nadareski
f22f7273a9 Add and use MZ constants 2022-12-28 14:50:48 -08:00
Matt Nadareski
ea9902c946 Add and use MS-CAB constants 2022-12-28 14:40:40 -08:00
Matt Nadareski
051c38c6df Add and use MoPaQ constants 2022-12-28 14:39:22 -08:00
Matt Nadareski
6b832026b4 Add and use NE constants 2022-12-28 14:26:12 -08:00
Matt Nadareski
81d7151f8f Create new Compression library (nw) 2022-12-28 14:18:50 -08:00
Matt Nadareski
283672e909 Add and use NCF constants 2022-12-28 14:02:09 -08:00
Matt Nadareski
94dfba4b4f Add LZ models 2022-12-28 10:46:33 -08:00
Matt Nadareski
2b66efd11b Add LE/LX constants 2022-12-28 10:31:28 -08:00
Matt Nadareski
14fb3f5758 Add and use IS-CAB constants 2022-12-28 10:21:19 -08:00
Matt Nadareski
9354f0f092 Add and use GCF constants 2022-12-28 10:14:00 -08:00
Matt Nadareski
c3636a0743 Add and use BSP constants 2022-12-28 10:04:10 -08:00
Matt Nadareski
e07b66812c Add and use BFPK constants 2022-12-28 09:57:22 -08:00
Matt Nadareski
c1d231db60 Create Compression models subfolder 2022-12-28 09:47:25 -08:00
TheRogueArchivist
757ab1f228 Fix FreeLock False Positive (#219)
* Fix FreeLock False Positive
2022-12-27 23:30:46 -08:00
TheRogueArchivist
6e42e7fb6b Remove dummy Roxxe file (#217)
* Remove dummy Roxxe file. The notes have been moved to DRML.
2022-12-27 23:13:53 -08:00
TheRogueArchivist
92f88efd4e Fix false positives in Bitpool and LaserLok (#218)
* Fix false positives in Bitpool and LaserLok.
2022-12-27 23:13:47 -08:00
Matt Nadareski
7ba2194d97 Add CExe extraction (partial) 2022-12-27 23:12:52 -08:00
Matt Nadareski
a5f2e2f5c8 Use slightly different zlib port 2022-12-27 22:25:49 -08:00
Matt Nadareski
8658c24ef0 Be more overzealous when locking 2022-12-27 22:25:16 -08:00
Matt Nadareski
0cded076e4 Fix invocation of scannable classes 2022-12-27 22:11:01 -08:00
Matt Nadareski
135c0b6d38 Use slightly different zlib port 2022-12-27 21:47:56 -08:00
Matt Nadareski
769fe42a7a Add TAR skeleton models, for kicks 2022-12-27 21:46:42 -08:00
Matt Nadareski
ab6fcd73e0 Seal as many of the models as possible 2022-12-27 17:12:55 -08:00
Matt Nadareski
3278420d72 Create placeholder for IS-CAB info printing 2022-12-27 16:56:00 -08:00
Matt Nadareski
98395387a7 Add IS-CAB models and builder 2022-12-27 16:54:06 -08:00
TheRogueArchivist
180a097213 Remove dummy Alcatraz file (#215)
* Remove dummy Alcatraz file. The notes have been moved to DRML.
2022-12-27 11:00:17 -08:00
TheRogueArchivist
18ac00080a Move Bitpool comments into DRML (#213)
* Move Bitpool comments into DRML, tidying up BOS,
2022-12-27 11:00:00 -08:00
Matt Nadareski
4da713702a Add header matchers for Wise 2022-12-27 10:53:28 -08:00
Matt Nadareski
68be17de66 Fix SGA builder and wrapper 2022-12-27 10:19:11 -08:00
Matt Nadareski
18cdf9d7ed Use new SGA extraction 2022-12-27 01:07:46 -08:00
Matt Nadareski
c389ea1e49 Add SGA extraction 2022-12-27 00:55:24 -08:00
Matt Nadareski
1f65b0352d Add SGA wrapper 2022-12-26 23:22:03 -08:00
Matt Nadareski
0e63b6638c Do some more work on MSZIP (nw) 2022-12-26 21:39:52 -08:00
Matt Nadareski
fcda1f119b Split MS-CAB wrapper 2022-12-26 15:04:17 -08:00
Matt Nadareski
bb130849ee Fix build with missed changes 2022-12-26 14:52:12 -08:00
Matt Nadareski
7b209eec6c Update to latest LibMSPackSharp 2022-12-26 14:46:17 -08:00
Matt Nadareski
9e7a84d2d6 Remove generic "Valve" 2022-12-26 14:45:49 -08:00
Matt Nadareski
baf43ea307 Remove remnants of HLLibSharp 2022-12-26 14:42:41 -08:00
Matt Nadareski
f524f0da3e Remove HLLibSharp as submodule 2022-12-26 14:37:59 -08:00
Matt Nadareski
49781c47a9 Add executables to support table 2022-12-26 13:01:37 -08:00
Matt Nadareski
aa11ce807a Better container support matrix 2022-12-26 12:58:03 -08:00
Matt Nadareski
702115c55a Make interfaces public 2022-12-26 12:36:09 -08:00
Matt Nadareski
17cb1bf9b0 Add XZP wrapper, extraction, and use it 2022-12-26 12:33:58 -08:00
Matt Nadareski
590c4e0a23 Make extension checks better 2022-12-26 11:43:04 -08:00
Matt Nadareski
fd6196a880 Add WAD wrapper, extraction, and use it 2022-12-26 11:34:17 -08:00
Matt Nadareski
2875f7ff7a Add VBSP wrapper, extraction, and use it 2022-12-26 10:58:16 -08:00
Matt Nadareski
50fe127a8d Add PAK wrapper, extraction, and use it 2022-12-26 10:26:26 -08:00
Matt Nadareski
94ebe5b707 Add NCF wrapper 2022-12-25 23:33:52 -08:00
Matt Nadareski
dc3914e976 Use new GCF extraction code 2022-12-25 22:55:48 -08:00
Matt Nadareski
ef2f037909 Add GCF extraction 2022-12-25 22:53:01 -08:00
Matt Nadareski
374f286585 Add GCF wrapper 2022-12-25 21:27:06 -08:00
Matt Nadareski
34cd933f78 Reset launch.json 2022-12-24 22:31:21 -08:00
Matt Nadareski
f8d533e592 Use new BSP extarction code 2022-12-24 22:30:29 -08:00
Matt Nadareski
21263cf0fd Add BSP extraction 2022-12-24 22:02:30 -08:00
Matt Nadareski
1a62ac2006 Add BSP wrapper 2022-12-24 20:15:58 -08:00
Matt Nadareski
8f3d4d5fb2 Use new VPK extraction code 2022-12-24 15:31:38 -08:00
Matt Nadareski
81902455ff Fix VPK extraction 2022-12-24 15:25:56 -08:00
Matt Nadareski
fbb33d9ef8 Add VPK to info 2022-12-24 14:24:34 -08:00
Matt Nadareski
b025c7a7fa Add VPK wrapper (nw) 2022-12-24 13:49:03 -08:00
Matt Nadareski
d8aec5aa97 Migrate recent HLLib work to BOS
It's better suited for the model of BOS and not an update to HLLibSharp
2022-12-24 12:57:10 -08:00
Matt Nadareski
3a862f343c Add headers and extensions for Valve 2022-12-23 23:27:14 -08:00
Matt Nadareski
69724cfb1c Sync to newest HLLibSharp 2022-12-23 23:13:45 -08:00
Matt Nadareski
f75cdea678 Sync to newest HLLibSharp 2022-12-23 23:04:40 -08:00
Matt Nadareski
32e650eff5 Update README comment 2022-12-23 15:46:42 -08:00
Matt Nadareski
ab022f9049 Sync to newest HLLibSharp 2022-12-23 15:26:48 -08:00
Matt Nadareski
7962e148fa Sync to newest HLLibSharp 2022-12-23 14:29:34 -08:00
Matt Nadareski
efdf3a0691 Sync to newest HLLibSharp 2022-12-23 13:13:57 -08:00
Matt Nadareski
000ab5e856 Sync to newest HLLibSharp 2022-12-23 12:36:48 -08:00
Matt Nadareski
4873133c92 Sync to newest HLLibSharp 2022-12-23 11:10:55 -08:00
Matt Nadareski
360bbef43a Remove redundant note in README 2022-12-22 22:31:45 -08:00
Matt Nadareski
9a21f4987d Sync to newest HLLibSharp 2022-12-22 22:24:13 -08:00
Matt Nadareski
63948767ef Use more granular file opening 2022-12-22 22:03:32 -08:00
Matt Nadareski
e2098f6f71 Disable StormLibSharp for .NET 6.0 2022-12-22 21:58:26 -08:00
Matt Nadareski
609c30da38 Sync to newest HLLibSharp 2022-12-22 21:51:33 -08:00
Matt Nadareski
0896842268 Builder -> Builders 2022-12-22 16:02:10 -08:00
Matt Nadareski
ec9506b9eb Sync to newest HLLibSharp 2022-12-22 15:53:50 -08:00
Matt Nadareski
526526975c Sync to newest HLLibSharp 2022-12-22 15:18:51 -08:00
Matt Nadareski
098734c471 Remove outdated note 2022-12-22 13:06:18 -08:00
Matt Nadareski
47df62534e Add back ActiveMARK entry point checks 2022-12-20 14:40:43 -08:00
Matt Nadareski
7295001892 Read entry point data in safe way 2022-12-20 14:19:48 -08:00
Matt Nadareski
7c820b7fd2 Start re-adding entry point 2022-12-20 13:03:25 -08:00
Matt Nadareski
36429cc1e9 Fix build 2022-12-20 12:21:34 -08:00
Matt Nadareski
a1c22ca9da Make a couple things consistent 2022-12-20 11:52:50 -08:00
Matt Nadareski
0c37932631 Cleanup and notes for 3P-Lock 2022-12-20 11:26:22 -08:00
Matt Nadareski
dbf1f6dcca Integrate changes from TheRogueArchivist 2022-12-19 23:53:52 -08:00
Matt Nadareski
7bb26c0faf Add PE checks to ByteShield 2022-12-19 23:49:34 -08:00
Matt Nadareski
31a0b55556 Add new info to developer guide 2022-12-19 23:28:12 -08:00
Matt Nadareski
64cc4785ca Add PE checks to SoftLock 2022-12-19 21:39:24 -08:00
Matt Nadareski
28391de50c Confirm SoftLock path checks 2022-12-19 20:49:10 -08:00
Matt Nadareski
b2ed69ab78 Add 7-zip SFX detection 2022-12-18 14:18:35 -08:00
Matt Nadareski
2f08940927 Simplify Gefest checks 2022-12-17 22:52:35 -08:00
Matt Nadareski
70928227e4 Fix launch.json 2022-12-17 22:02:12 -08:00
Matt Nadareski
546bd70418 Start fixing MSZIP decoding (nw) 2022-12-17 22:01:00 -08:00
Matt Nadareski
f2521a0110 Write MS-CAB file extraction (nw) 2022-12-16 23:11:06 -08:00
Matt Nadareski
02b83513a1 Hook up MSZIP decompression (nw) 2022-12-16 22:58:07 -08:00
Matt Nadareski
f26b2ff61b Migrate MSZIP to wrapper, where possible 2022-12-16 22:41:36 -08:00
Matt Nadareski
4d26535d07 Add BitStream type and add BitArray extensions 2022-12-16 21:59:46 -08:00
Matt Nadareski
01a365033e MIgrate some Quantum stuff to models 2022-12-16 10:19:32 -08:00
Matt Nadareski
318a89a4bc Move some LZX things to models 2022-12-16 09:48:52 -08:00
Matt Nadareski
b20f22fb92 Subfolder it 2022-12-16 00:19:18 -08:00
Matt Nadareski
fedf76e534 Migrate some MSZIP pieces to Models 2022-12-15 23:51:12 -08:00
Matt Nadareski
e0e16292eb ASN.1 and OID to its own library 2022-12-15 22:07:12 -08:00
Matt Nadareski
b3c0e48bdd Address some MPQ issues 2022-12-15 16:50:24 -08:00
Matt Nadareski
aded5ee03a Stream safety and better streams 2022-12-15 14:20:27 -08:00
Matt Nadareski
16e71c910e Use MemoryStream in builders 2022-12-15 13:37:34 -08:00
Matt Nadareski
bbe234b459 Use MemoryStream in wrappers 2022-12-15 12:41:08 -08:00
Matt Nadareski
715b9eb156 Fix MS-CAB info 2022-12-15 12:20:06 -08:00
Matt Nadareski
4cc441afcf Get rid of code duplication 2022-12-15 00:13:24 -08:00
Matt Nadareski
f79cd759bd Add SFFS models, no encryption 2022-12-14 23:16:37 -08:00
Matt Nadareski
1b232e4405 Fix wrapper printing, add to info 2022-12-14 23:06:09 -08:00
Matt Nadareski
6d43afb258 Use wrapper in BFPK scans 2022-12-14 23:01:06 -08:00
Matt Nadareski
a47c778b0e Add BFPK wrapper 2022-12-14 22:58:18 -08:00
Matt Nadareski
ddb82842bc Add BFPK builder 2022-12-14 22:41:17 -08:00
Matt Nadareski
199914b19f Remove BinaryReader from BFPK 2022-12-14 22:28:35 -08:00
Matt Nadareski
9fadd84597 Add unused BFPK models 2022-12-14 22:25:35 -08:00
Matt Nadareski
95dd670c7c Add format note to SFFS, fix magic 2022-12-14 22:15:43 -08:00
Matt Nadareski
adc9def0c9 Slight MoPaQ builder cleanup 2022-12-14 22:07:11 -08:00
Matt Nadareski
8dcc9d9b0e Add BET/HET parsign to MoPaQ (nw) 2022-12-14 22:06:31 -08:00
Matt Nadareski
b5177b16ea Add hi-block table parsing to MoPaQ (nw) 2022-12-14 21:59:48 -08:00
Matt Nadareski
f9b4693aae Add block table parsing to MoPaQ (nw) 2022-12-14 21:48:22 -08:00
Matt Nadareski
f2a479e35c Update SafeDisc with better finding 2022-12-14 21:31:51 -08:00
Matt Nadareski
1f40c2e052 Fix locking exception 2022-12-14 21:30:53 -08:00
Matt Nadareski
b5c8d05814 Add CodeView debug parsing/finding 2022-12-14 21:07:02 -08:00
Matt Nadareski
f99634bc08 Add generic debug check to SafeDisc 2022-12-14 20:57:26 -08:00
Matt Nadareski
ab88e2f553 Add NB10 debug data type 2022-12-14 20:56:13 -08:00
Matt Nadareski
5465abe1ac Add RSDS debug data type 2022-12-14 20:47:18 -08:00
Matt Nadareski
b0df7a8f3b Add debug data to PE wrapper 2022-12-14 20:46:24 -08:00
Matt Nadareski
0d4fab100d Add PE table data/string caching 2022-12-14 17:24:14 -08:00
Matt Nadareski
8c5e10fd88 First attempt at MoPaQ hash table parsing 2022-12-14 17:03:34 -08:00
Matt Nadareski
e8aef1596b Merge branch 'master' of https://github.com/mnadareski/BurnOutSharp 2022-12-14 16:48:52 -08:00
Matt Nadareski
386c86f04f Add placeholders for parsing in MoPaQ 2022-12-14 16:47:45 -08:00
TheRogueArchivist
3f5a66f170 Add support for Gefest Protection System (#185)
* Add detection and notes for Gefest Protection System.

* Add Gefest Protection System to README.
2022-12-14 16:37:06 -08:00
TheRogueArchivist
a961d9534c Add SafeDisc "SD0XXX.dll" checks (#184)
* Add detection and notes for SafeDisc "SD0XXX.dll" files.
2022-12-14 16:35:54 -08:00
TheRogueArchivist
d1919c18f5 Add nProtect DRM (#183)
* Add nProtect DRM

* Add detection and notes for nProtect GameGuard and nProtect KeyCrypt.

* Add nProtect DRM to README.

* Fix missing "|" character

* Fix missing "|" character.
2022-12-14 16:35:01 -08:00
Matt Nadareski
afa8b24ba9 Add MoPaQ printing skeleton 2022-12-14 16:33:26 -08:00
Matt Nadareski
b793b74b32 Add MoPaQ builder (nw) 2022-12-14 16:29:07 -08:00
Matt Nadareski
65499d1f46 Add MoPaQ models 2022-12-14 15:43:13 -08:00
Matt Nadareski
5f387cdb74 Migrate WIP MS-CAB to model/builder/wrapper 2022-12-14 15:23:54 -08:00
Matt Nadareski
ed2e88c781 Start filling out LZX 2022-12-14 13:57:54 -08:00
Matt Nadareski
1cb3157110 Add more notes, including Quantum 2022-12-14 13:17:29 -08:00
TheRogueArchivist
a480b53787 CD-Cops is a mess why don't we have more samples (#182)
* Confirm CD-Cops check.

* Add a few notes for CD-Cops.
2022-12-14 12:12:12 -08:00
TheRogueArchivist
405c895352 Add support for CD-Guard (#181)
* why is there so much DRM I am going to cry

* Add support for detecting CD-Guard, as well as notes.

* Add CD-Guard to README.

* Address PR comments

* Ignore case in import/export checks.
2022-12-14 12:11:23 -08:00
Matt Nadareski
53dc251a0c Continue with deflate 2022-12-14 12:10:59 -08:00
Matt Nadareski
d715072cbc Start writing Inflate implementation 2022-12-14 10:55:56 -08:00
Matt Nadareski
aaee56f44e Start adding MSZIP notes 2022-12-14 00:05:49 -08:00
Matt Nadareski
27ceb4ed48 Streamline MS-CAB reading, add to info printing 2022-12-13 23:06:49 -08:00
Matt Nadareski
2d51bd8f37 Implement MS-CAB checksum routine 2022-12-13 22:11:19 -08:00
Matt Nadareski
645a366dc5 Split MS-CAB into subfiles, LibMSPackSharp for .NET 6 2022-12-13 21:51:24 -08:00
Matt Nadareski
756a74eda6 Disable printing by default again 2022-12-13 21:13:20 -08:00
Matt Nadareski
8052ee2afb Some PE resource handling cleanup 2022-12-13 21:05:52 -08:00
Matt Nadareski
6171c0defd Fix SFFS not being scanned 2022-12-13 11:55:12 -08:00
TheRogueArchivist
56c27d0b8f Why is there so much StarForce, geez (#180)
* Begin work on overhauling StarForce detection, and to add notes.

* Attempt to add SFFS file detection.

* Fix minor TAGES issue.
2022-12-13 11:42:55 -08:00
Matt Nadareski
9c173fd3a1 Update extension method for AddD section 2022-12-12 21:40:29 -08:00
Matt Nadareski
fa3ccf9953 Add more SecuROM AddD section notes 2022-12-12 21:25:00 -08:00
Matt Nadareski
229e645c8e Bump version 2022-12-12 13:35:36 -08:00
Matt Nadareski
b4606a8b84 Merge pull request #179 from TheRogueArchivist/TTR-Subchannel-Notes
Add notes about various TTR protections
2022-12-12 00:11:20 -08:00
SilasLaspada
d11782a87b Add notes about various TTR protections
* Add notes about DiscGuard's use of subchannels.

* Add reference to DiscAudit and MusicGuard.
2022-12-12 00:13:22 -07:00
Matt Nadareski
4faaf3d251 Add notes to README 2022-12-11 15:42:39 -08:00
Matt Nadareski
89dea30211 Update everything to support .NET 6.0 correctly 2022-12-11 15:32:09 -08:00
Matt Nadareski
7563634f53 Add coding guide 2022-12-11 14:55:29 -08:00
Matt Nadareski
d74dcc1d26 Proofreading 2022-12-11 01:28:17 -08:00
Matt Nadareski
cd75fd0329 Add developer guide 2022-12-11 01:09:49 -08:00
Matt Nadareski
0390ee3363 Don't print section table on debug now 2022-12-10 22:42:03 -08:00
Matt Nadareski
64f52698c3 Add extension to convert byte array 2022-12-10 22:36:02 -08:00
Matt Nadareski
8bd4a87f0b Add SecuROM AddD overlay data models 2022-12-10 22:26:42 -08:00
Matt Nadareski
4ad7c60443 Add overlay string finding 2022-12-10 20:10:25 -08:00
Matt Nadareski
d1a6c9be00 Add header padding strings 2022-12-10 17:31:41 -08:00
Matt Nadareski
3c3fd1be50 Add more guards to PE builder 2022-12-10 14:21:37 -08:00
Matt Nadareski
92c5745ac8 Remove obsolete PE helper method 2022-12-10 14:11:25 -08:00
Matt Nadareski
792de5cda2 Fix Macrovision and SafeCast checks 2022-12-10 14:11:10 -08:00
Matt Nadareski
bfe2381896 Slight tweaks and addtions to AegiSoft 2022-12-09 22:48:23 -08:00
Matt Nadareski
ded5ecb3ed Fix broken COFF string table reading 2022-12-09 22:37:35 -08:00
Matt Nadareski
7895b40a77 Convert LabelGate to string finding 2022-12-09 22:36:21 -08:00
Matt Nadareski
3f2319093f Partially convert SolidShield to string finding 2022-12-09 21:54:21 -08:00
Matt Nadareski
3806b383c9 Convert SmartE to string finding 2022-12-09 21:40:25 -08:00
Matt Nadareski
84a65e998f Partially convert ActiveMARK to string finding 2022-12-09 21:37:33 -08:00
Matt Nadareski
88049affb5 Add note to Macrovision 2022-12-09 21:36:12 -08:00
Matt Nadareski
5fd59b9eac Convert WTM to string finding 2022-12-09 21:34:00 -08:00
Matt Nadareski
8288cc7f96 Convert Wise Installer to string finding 2022-12-09 21:30:37 -08:00
Matt Nadareski
063b643597 Convert Themida to string finding 2022-12-09 21:28:21 -08:00
Matt Nadareski
ff4214877e Convert Sysiphus to string finding 2022-12-09 21:25:19 -08:00
Matt Nadareski
847fa7d2ad Partially convert SecuROM to string finding 2022-12-09 21:22:55 -08:00
Matt Nadareski
886284b42f Convert Rainbow Sentinel to string finding 2022-12-09 20:56:27 -08:00
Matt Nadareski
46776b461b Partially convert ProtectDISC to string finding 2022-12-09 20:53:25 -08:00
Matt Nadareski
e0150d7bb5 Convert NSIS to string finding 2022-12-09 15:18:17 -08:00
Matt Nadareski
ad16260c53 Convert Microsoft CAB SFX to string finding 2022-12-09 15:13:46 -08:00
Matt Nadareski
3cfe9138a5 Convert MediaMax CD-3 to string finding 2022-12-09 15:10:23 -08:00
Matt Nadareski
9e43babe0c Convert SafeCast to string finding 2022-12-09 15:06:17 -08:00
Matt Nadareski
4efbf54edf Convert C-Dilla to string finding 2022-12-09 15:04:14 -08:00
Matt Nadareski
37121a1fd2 Convert Installer VISE to string finding 2022-12-09 15:01:23 -08:00
Matt Nadareski
8a77a8a009 Simplify PE section helper methods 2022-12-09 14:59:31 -08:00
Matt Nadareski
1aef137cb2 Convert Inno Setup to string finding 2022-12-09 14:58:12 -08:00
Matt Nadareski
86707b28c0 Convert Impulse Reactor to string finding 2022-12-09 14:36:43 -08:00
Matt Nadareski
5e42bae77f Convert Gentee Installer to string finding 2022-12-09 14:22:59 -08:00
Matt Nadareski
9396804379 Convert EA to string finding 2022-12-09 14:21:18 -08:00
Matt Nadareski
5613cf9aae Convert dotFuscator to string finding 2022-12-09 14:17:01 -08:00
Matt Nadareski
ff44c717a2 Convert Code-Lock to string finding 2022-12-09 13:55:28 -08:00
Matt Nadareski
42faeb1402 Convert CDSHiELD SE to string finding 2022-12-09 13:41:09 -08:00
Matt Nadareski
7c243ac6ff Convert CDS to string finding 2022-12-09 13:09:27 -08:00
Matt Nadareski
85c6353cba Convert Armadillo to string finding 2022-12-09 12:53:19 -08:00
Matt Nadareski
c7d049efe2 Convert Alpha-ROM to string finding 2022-12-09 12:49:22 -08:00
Matt Nadareski
97aabdca33 Convert Advanced Installer to string finding 2022-12-09 12:35:58 -08:00
Matt Nadareski
9562a0eaf7 Convert XCP to string finding 2022-12-09 12:33:12 -08:00
Matt Nadareski
04bffd4889 Add string finding to wrapper base 2022-12-09 12:32:44 -08:00
Matt Nadareski
a9c71ced47 Add skelton for section string finding 2022-12-09 11:53:58 -08:00
Matt Nadareski
a03bf60ca5 Tweak LaserLok check to pre-screen 2022-12-09 11:21:27 -08:00
Matt Nadareski
02ee94f732 Reduce WMDS checks 2022-12-09 11:18:07 -08:00
Matt Nadareski
0a5ffd247c Slightly update JoWooD 2022-12-09 11:11:18 -08:00
Matt Nadareski
3f4f6a2d07 Update C-Dilla checks 2022-12-09 10:37:09 -08:00
Matt Nadareski
0d22f78b10 Remove standalone ExecutableTest 2022-12-08 23:40:39 -08:00
Matt Nadareski
ca1e3e8e63 Port ExecutableTest to Test 2022-12-08 23:38:28 -08:00
Matt Nadareski
debb7cde2d Start preparing ExecutableTest 2022-12-08 23:31:48 -08:00
Matt Nadareski
40c35a5d50 Update Nuget packages 2022-12-08 23:01:28 -08:00
Matt Nadareski
971f769031 Update project files 2022-12-08 22:53:07 -08:00
Matt Nadareski
a1a3adfafa Move psxt001z to own library 2022-12-08 22:50:42 -08:00
Matt Nadareski
912b49ecc4 Cleanup ProtectionProgress 2022-12-08 22:37:57 -08:00
Matt Nadareski
dcccd6e313 Remove System.Diagnostics dependency 2022-12-08 22:33:02 -08:00
Matt Nadareski
005529f959 Add stream support to Matching 2022-12-08 22:27:17 -08:00
Matt Nadareski
3d5904c997 Move Matching to own library 2022-12-08 22:07:14 -08:00
Matt Nadareski
dcc8915dd2 FileTypes -> SupportedFileType 2022-12-08 21:46:22 -08:00
Matt Nadareski
4a589603e4 Clarify the IScannable description 2022-12-08 21:43:39 -08:00
Matt Nadareski
4f16b9d9e8 Fix misnamed paramter in IScannable 2022-12-08 21:42:24 -08:00
Matt Nadareski
ce7ecc78cc Remove now-useless ShouldScan, part 2 2022-12-08 21:41:33 -08:00
Matt Nadareski
9c8a677f13 Remove now-useless ShouldScan 2022-12-08 21:37:11 -08:00
Matt Nadareski
39f2dd88aa Make it easier to support new file types 2022-12-08 21:32:52 -08:00
Matt Nadareski
3b4929a368 Invert if in ProtectDisc check for clarity 2022-12-08 17:19:42 -08:00
Matt Nadareski
f290b8462d Fix getting last section for SmartE 2022-12-08 17:18:09 -08:00
Matt Nadareski
5ce4f3be56 Clean up awkard SolidShield check 2022-12-08 17:16:47 -08:00
Matt Nadareski
a5158f04db Add ActiveMARK resource check 2022-12-08 17:16:12 -08:00
Matt Nadareski
2aa9f088a4 Add WTM legal trademarks check 2022-12-08 17:06:36 -08:00
Matt Nadareski
bb37c3f94c Add missing commented out print 2022-12-08 17:06:05 -08:00
Matt Nadareski
92b3f14d7b Add SolidShield import directory table checks 2022-12-08 16:53:43 -08:00
Matt Nadareski
2dcd30e346 Make unknown resource printing better 2022-12-08 16:40:04 -08:00
Matt Nadareski
c4ed59dc46 Replace 2 SecuROM PA checks 2022-12-08 16:38:56 -08:00
Matt Nadareski
81141fb2fa Fix Impulse Reactor 2022-12-08 16:08:58 -08:00
Matt Nadareski
58c6f00a6c Add another embedded resource check 2022-12-08 16:01:53 -08:00
Matt Nadareski
c1f4e42219 Convert one MediaMax CD-3 check 2022-12-08 16:01:30 -08:00
Matt Nadareski
02b16843e5 Add note to LaserLok 2022-12-08 15:46:01 -08:00
Matt Nadareski
86bfcc15f9 Add note to JoWooD 2022-12-08 15:37:11 -08:00
Matt Nadareski
4fab4e71f7 Convert one Impulse Reactor check 2022-12-08 15:24:53 -08:00
Matt Nadareski
b230462860 Update GFWL with new framework 2022-12-08 15:16:43 -08:00
Matt Nadareski
5f49b56c3d Add a couple more named version fields 2022-12-08 14:59:15 -08:00
Matt Nadareski
51482dd225 Rename Code-Lock file 2022-12-08 14:55:07 -08:00
Matt Nadareski
c1cb1a41a9 Add note to CDSHiELD SE 2022-12-08 14:53:59 -08:00
Matt Nadareski
b496c79b34 Remove previously added note 2022-12-08 14:49:39 -08:00
Matt Nadareski
fcad7db5ab Add note to CD-Lock 2022-12-08 14:44:15 -08:00
Matt Nadareski
e1bd26f712 Add undocumented version info keys 2022-12-08 14:40:30 -08:00
Matt Nadareski
0518184786 Make CD-Check simpler 2022-12-08 14:36:43 -08:00
Matt Nadareski
576e234216 Remove last explicit .rsrc section read 2022-12-08 14:22:32 -08:00
Matt Nadareski
3c750dac86 Clean up most of the StarForce rsrc checks 2022-12-08 14:01:12 -08:00
Matt Nadareski
714cee586d Make printing methods for all PE resources 2022-12-08 14:00:29 -08:00
Matt Nadareski
cf9cc30d5e Handle casting exceptions 2022-12-08 13:13:16 -08:00
Matt Nadareski
713b1c83e1 Fix yet more string data reading 2022-12-08 10:38:46 -08:00
Matt Nadareski
ddf289d747 Force reading name table as ASCII 2022-12-08 10:17:26 -08:00
Matt Nadareski
ae1edf0f21 Sync resource building in byte and stream paths 2022-12-08 10:13:22 -08:00
Matt Nadareski
38665ddbf3 Add note to Wise installer 2022-12-08 00:07:11 -08:00
Matt Nadareski
2af0f166eb Update WinRAR SFX with new framework 2022-12-07 23:56:38 -08:00
Matt Nadareski
aeaeff28d3 Better alignment in PE resources 2022-12-07 23:56:08 -08:00
Matt Nadareski
28948a0511 Add back truncation 2022-12-07 23:09:18 -08:00
Matt Nadareski
52d190e339 Rewrite WinZip SFX PE checks 2022-12-07 22:52:49 -08:00
Matt Nadareski
d47707c433 Add some CD-Cops notes 2022-12-06 22:31:46 -08:00
Matt Nadareski
11bc46ae86 Update WZ-SFX NE checks a little 2022-12-06 21:04:52 -08:00
Matt Nadareski
d229b23ea6 Fix CD-Cops table checks 2022-12-06 21:04:08 -08:00
Matt Nadareski
41dc7f7b14 Add notes for NE Inno detection 2022-12-05 20:44:34 -08:00
Matt Nadareski
dbd8b14cd2 Convert arbitray data read for NE WZ-SFX 2022-12-05 19:57:57 -08:00
Matt Nadareski
3af8adb067 Add unversioned CD-Cops NE checks 2022-12-05 17:05:41 -08:00
Matt Nadareski
5baa470d54 Use header padding data for UPX 2022-12-05 16:50:18 -08:00
Matt Nadareski
1f5d5215f7 Clean up SafeDisc checks, add header padding check 2022-12-05 15:58:44 -08:00
Matt Nadareski
24c77ecd07 Add header padding data for searching 2022-12-05 15:56:37 -08:00
Matt Nadareski
2264fc0172 Fix IIF product name check 2022-12-05 15:46:56 -08:00
Matt Nadareski
00028ac59b Add notes to EXE Stealth 2022-12-05 14:11:52 -08:00
Matt Nadareski
ad5735a559 Update printing for import tables 2022-12-05 13:57:07 -08:00
Matt Nadareski
9411f5044a Fix import table parsing 2022-12-05 13:52:15 -08:00
Matt Nadareski
7293d55239 Fix PlayJ description check 2022-12-05 12:57:54 -08:00
Matt Nadareski
31dc347df4 Merge pull request #178 from mnadareski/new-exe-framework
Use new executable framework for protection checks
2022-12-05 11:30:54 -08:00
Matt Nadareski
d72d0d4dc2 Clean up printing methods 2022-12-05 11:01:22 -08:00
Matt Nadareski
7181dc9d5b Fix formatting/tagging 2022-12-05 10:47:17 -08:00
Matt Nadareski
95fa8681fe Make SmartE checks even simpler 2022-12-05 10:21:15 -08:00
Matt Nadareski
3a63755d96 Simplify section printing 2022-12-05 10:06:37 -08:00
Matt Nadareski
5390970054 Fix segment validity checks 2022-12-05 10:04:37 -08:00
Matt Nadareski
2b43f2b261 Add notes to SmartE 2022-12-04 23:21:18 -08:00
Matt Nadareski
4330cd1aac Fix WTM code/CODE section 2022-12-04 23:20:22 -08:00
Matt Nadareski
fc9dd8a34d Add base relocation table to passthrough 2022-12-04 23:17:34 -08:00
Matt Nadareski
c64abc15c9 Move .rsrc StarForce checks to new file 2022-12-04 23:00:30 -08:00
Matt Nadareski
fca12c639c Update CDS PlayJ check 2022-12-04 22:44:59 -08:00
Matt Nadareski
a1522aabd6 Add relocation real address 2022-12-04 22:37:59 -08:00
Matt Nadareski
9be4b339f8 Add PE base relocation table parsing and printing 2022-12-04 22:32:41 -08:00
Matt Nadareski
ce1c74aec3 Update DiscGuard 2022-12-04 21:11:55 -08:00
Matt Nadareski
e824428e0f String tables are always Unicode 2022-12-04 13:38:04 -08:00
Matt Nadareski
2fd4a8a9b1 Fix launch.json 2022-12-04 00:41:56 -08:00
Matt Nadareski
82de7e8b8e Off by one 2022-12-03 23:58:20 -08:00
Matt Nadareski
26831b4732 Both, both is good 2022-12-03 23:48:48 -08:00
Matt Nadareski
a6862925ca Use endOffset instead of EOF 2022-12-03 23:46:19 -08:00
Matt Nadareski
1e2ce169af Fix unaligned end-of-file certificates 2022-12-03 23:41:42 -08:00
Matt Nadareski
dda9b3551a Cast certificate length more safely 2022-12-03 23:32:11 -08:00
Matt Nadareski
b1760d3541 Fix version printing 2022-12-03 23:30:32 -08:00
Matt Nadareski
2c1e087bc6 Include negative numbers 2022-12-03 23:23:55 -08:00
Matt Nadareski
90d5bd52a2 Check more EA resources 2022-12-03 23:17:29 -08:00
Matt Nadareski
26db75853b Fix malformed PE certificates 2022-12-03 23:09:45 -08:00
Matt Nadareski
fe5a674518 Add more safety around resource finding 2022-12-03 22:55:03 -08:00
Matt Nadareski
2fe56cd6af Register encoding provider in scanner 2022-12-03 22:47:57 -08:00
Matt Nadareski
f26e82d2bc Fix some PE resource caching issues 2022-12-03 22:47:32 -08:00
Matt Nadareski
65892f067a Merge remote-tracking branch 'origin' into new-exe-framework 2022-12-03 22:29:12 -08:00
Matt Nadareski
768717d7b3 Remove old executable framework 2022-12-03 22:28:03 -08:00
Matt Nadareski
f78b3daf8b Attempt to use new executable framework 2022-12-03 22:17:48 -08:00
Matt Nadareski
8a6f481118 Fix indexed section data read 2022-12-03 22:13:17 -08:00
Matt Nadareski
f420434fd3 Handle overlay data better 2022-12-03 21:59:21 -08:00
Matt Nadareski
8e73d7970f Fix PE data locking, add offset read helper 2022-12-03 21:37:32 -08:00
Matt Nadareski
9699af93bc Add temporary helper method for NE 2022-12-03 21:37:05 -08:00
Matt Nadareski
44ca0a94b7 Better PE wrapper section handling 2022-12-03 20:56:06 -08:00
Matt Nadareski
b3bf008e31 Fix NE table printing 2022-12-03 14:44:18 -08:00
Matt Nadareski
ce5e2982d2 Fix resource entry handling 2022-12-03 14:22:54 -08:00
Matt Nadareski
7d2edd315c Add stub data to cache, resource/section finding 2022-12-03 13:17:29 -08:00
Matt Nadareski
8ae0452873 Fix reading 0-length string data 2022-12-03 13:08:10 -08:00
Matt Nadareski
e0efc0d9ab Cache PE overlay data 2022-12-02 22:44:55 -08:00
Matt Nadareski
3ce3b7ca2b Cache PE resource, version, manifest 2022-12-02 22:24:22 -08:00
Matt Nadareski
6997608b63 Split printing into methods, add notes 2022-12-02 21:20:52 -08:00
Matt Nadareski
cee7f12974 Add printing regions 2022-12-02 20:09:55 -08:00
Matt Nadareski
5b4a8d5775 Ceeate wrapper base class, PE raw reads 2022-12-02 20:05:20 -08:00
Matt Nadareski
a59bedec5d Add data source to all wrappers, add note 2022-12-02 17:19:59 -08:00
Matt Nadareski
3c5d670924 Add printing to wrappers, remove from test exe 2022-12-02 16:39:49 -08:00
Matt Nadareski
7bab251915 Add PE passthrough properties 2022-12-02 16:16:12 -08:00
Matt Nadareski
57e47eee5d Add LE passthrough properties 2022-12-02 15:58:06 -08:00
Matt Nadareski
4f09c57755 Add NE passthrough properties 2022-12-02 15:44:33 -08:00
Matt Nadareski
7c1edab6ca Add DOS stub passthrough for LE/NE/PE 2022-12-02 15:35:10 -08:00
Matt Nadareski
f24004c949 Add proof-of-concept MS-DOS wrapper 2022-12-02 15:29:10 -08:00
Matt Nadareski
c4bf3931e2 Add skeletons for all wrappers 2022-12-02 15:20:44 -08:00
Matt Nadareski
fe13562f3e Add notes about ByteShield (TheRogueArchivist) 2022-12-02 15:06:31 -08:00
Matt Nadareski
64334d72ea Improve SolidShield detection
- Add new SolidShield executable and file checks.
- Fix false positives in file name checks due to not using a directory separator in the check.
- Add a few notes and reorganize slightly.
2022-12-02 15:02:45 -08:00
Matt Nadareski
a915980187 Improve SafeDisc detection
- Add support for detecting 4.60.000's drvmgt.
- Add version checks for Diag.exe to remove one case of "SafeCast/SafeDisc" ambiguity.
2022-12-02 14:59:26 -08:00
Matt Nadareski
af882fa588 Properly differentiate between Code-Lock and CopyLok (TheRogueArchivist) 2022-12-02 14:56:08 -08:00
Matt Nadareski
7fcaa16835 Add first Themida check (TheRogueArchivist) 2022-12-02 14:52:28 -08:00
Matt Nadareski
4d640f3cf2 Add Wrapper skeleton project 2022-12-02 14:44:06 -08:00
Matt Nadareski
25d495b1d0 ASN.1 OID parsing (nw) 2022-12-02 14:18:15 -08:00
Matt Nadareski
7fd936c4a8 Handle empty resource name strings 2022-12-02 14:15:50 -08:00
Matt Nadareski
fe753fc4fd Try to fix null resource types issue 2022-12-02 14:15:44 -08:00
Matt Nadareski
0a4763fcc1 Fix PE dialog item printing 2022-12-02 14:15:37 -08:00
Matt Nadareski
e281faf664 Add first attempt at PE certificate parsing 2022-11-12 21:56:24 -08:00
Matt Nadareski
dcb291c1c6 Disable printing raw PE cert data 2022-11-11 16:23:25 -08:00
Matt Nadareski
ecd1c93bb9 Add PE message resource printing, fix parsing 2022-11-11 16:20:17 -08:00
Matt Nadareski
eeb555a6ce Add PE message resource data to parser 2022-11-11 15:52:05 -08:00
Matt Nadareski
27d53abd10 Add PE message resource models 2022-11-11 15:41:37 -08:00
Matt Nadareski
91eef55173 Fix tiny formatting issue 2022-11-11 15:33:41 -08:00
Matt Nadareski
f9e1518da6 Add PE menu resource reading and writing 2022-11-11 15:31:00 -08:00
Matt Nadareski
5b974260cc Add PE extended dialog templates 2022-11-11 14:22:53 -08:00
Matt Nadareski
554374b710 Add PE dialog template extended 2022-11-11 14:12:03 -08:00
Matt Nadareski
475669ac1b Add PE standard dialog parsing and writing 2022-11-11 13:56:23 -08:00
Matt Nadareski
623d1e6a40 Invert PE "if" logic where possible 2022-11-11 10:08:15 -08:00
Matt Nadareski
08fa4a997f Fix PE resource data entry printing 2022-11-11 09:58:50 -08:00
Matt Nadareski
4e21cf8494 Make PE RVA checks simpler 2022-11-11 09:58:19 -08:00
Matt Nadareski
2ebbda6852 Don't trust PE sections 2022-11-10 23:38:59 -08:00
Matt Nadareski
010a6d6e42 Safeguard all PE virtual address uses 2022-11-10 23:06:21 -08:00
Matt Nadareski
3b1481879a Fix PE debug table parsing 2022-11-10 22:39:10 -08:00
Matt Nadareski
3ddcc3884b Fix PE printing typo 2022-11-10 22:23:36 -08:00
Matt Nadareski
260ab1ec89 Safeguard PE invalid virtual addresses 2022-11-10 22:19:58 -08:00
Matt Nadareski
69803a999f Fix PE virtual address for section-aligned RVAs 2022-11-10 22:09:58 -08:00
Matt Nadareski
d4a75ed871 Reorganize PE notes for delay-load 2022-11-10 21:41:42 -08:00
Matt Nadareski
7394f14218 Add missing PE notes for sections 2022-11-10 21:38:52 -08:00
Matt Nadareski
23cd7b9ebd Add note for PE .drectve section 2022-11-10 21:32:01 -08:00
Matt Nadareski
477cfee78e Add PE debug section printing 2022-11-10 21:29:17 -08:00
Matt Nadareski
750cecfdaf Add PE partial debug table parsing 2022-11-10 21:24:28 -08:00
TheRogueArchivist
32a28fba32 Add more checks for Rainbow Sentinel (#171)
* Add more checks for Rainbow Sentinel.

* Make comments more consistent.

* Add more notes on versions/
2022-11-10 16:23:10 -08:00
Matt Nadareski
fe926cbf9a Rewrite PE accelerator table extension 2022-11-10 13:09:23 -08:00
Matt Nadareski
d18e65ca6c Add PE debug directory skeleton, notes 2022-11-10 12:57:41 -08:00
Matt Nadareski
ec67ca605c Fix PE virtual directory size issues 2022-11-10 12:57:19 -08:00
Matt Nadareski
9cb3c963a1 Add PE .sxdata section notes 2022-11-10 12:42:34 -08:00
Matt Nadareski
8a4caf82bb Add PE .coremeta section note 2022-11-10 12:40:18 -08:00
Matt Nadareski
7a5941cfa9 Add PE import table printing 2022-11-10 12:16:48 -08:00
Matt Nadareski
690c49ae1f Fix PE import table parsing 2022-11-10 11:58:46 -08:00
Matt Nadareski
c77c095893 Add initial PE import table parsing 2022-11-10 11:31:06 -08:00
Matt Nadareski
98ddc65fa2 Add PE import table to model 2022-11-10 10:10:12 -08:00
Matt Nadareski
41a7c71b7d Fix PE bitmasks 2022-11-10 00:06:29 -08:00
Matt Nadareski
cb1d3d1db4 Add PE export table to printing 2022-11-09 23:27:06 -08:00
Matt Nadareski
5ba2a31d7d Add PE export table to builder 2022-11-09 23:06:52 -08:00
Matt Nadareski
0768a93bcb Fix Stream ReadString extension 2022-11-09 23:04:07 -08:00
Matt Nadareski
e690c6d0ff Add PE .edata components (not hooked up)
This also does a pretty major cleanup of TODOs
2022-11-09 22:23:40 -08:00
Matt Nadareski
0c6bf406c1 Fix PE delay-load directory 2022-11-09 22:02:38 -08:00
Matt Nadareski
95b5f12226 Add PE grouped sections note 2022-11-09 21:55:15 -08:00
Matt Nadareski
5b4b622834 Add PE delay-load directory to printing 2022-11-09 21:50:36 -08:00
Matt Nadareski
b908b77a34 Add PE delay-load directory table to builder 2022-11-09 21:47:39 -08:00
Matt Nadareski
dbba310385 Add console print to PE string table parsing 2022-11-09 21:32:36 -08:00
Matt Nadareski
0a0ca9ba93 Be slightly safer on PE string table parsing 2022-11-09 21:31:40 -08:00
Matt Nadareski
8aa574a7c4 Add PE COFF string table printing 2022-11-09 21:28:00 -08:00
Matt Nadareski
37ac8c038f Add PE COFF string table to builder 2022-11-09 21:22:29 -08:00
Matt Nadareski
9b6456a80f Register encoding provider for ExecutableTest 2022-11-09 21:09:37 -08:00
Matt Nadareski
f6ffd314b1 Add PE attribute certificate table printing 2022-11-09 21:08:33 -08:00
Matt Nadareski
b569c6a6dd Add PE certificate attribute table to builder 2022-11-09 21:02:02 -08:00
Matt Nadareski
c84f416973 Add better TODO 2022-11-09 20:44:14 -08:00
Matt Nadareski
6ebc476d2b Remove partially completed TODO 2022-11-09 20:43:47 -08:00
Matt Nadareski
98c340d94d Add unused PE font group parser 2022-11-09 20:39:20 -08:00
Matt Nadareski
78d80918aa Remove incorrect console statement 2022-11-09 20:38:37 -08:00
Matt Nadareski
e8d7d6b4e7 Print nonstandard PE manifest items 2022-11-09 20:07:03 -08:00
Matt Nadareski
53341b0dc0 Add remaining unused PE manifest types 2022-11-09 20:04:06 -08:00
Matt Nadareski
f64c7d81ad Add full PE assembly manifest printing 2022-11-09 19:59:39 -08:00
Matt Nadareski
197de59089 Add PE assembly manifest deserialization 2022-11-09 19:09:30 -08:00
Matt Nadareski
13eb37cc46 Add full PE file info printing 2022-11-09 16:17:40 -08:00
Matt Nadareski
c21c0ff411 Add PE version info parsing 2022-11-09 15:53:40 -08:00
Matt Nadareski
72f6af7019 Add PE version resource models 2022-11-09 15:17:53 -08:00
Matt Nadareski
6b14321505 Clean up PE string table parsing 2022-11-09 14:27:32 -08:00
Matt Nadareski
4fcb719613 Start adding PE cursor and icon resources 2022-11-09 14:19:23 -08:00
Matt Nadareski
50915d9100 Clean up PE accelerator table 2022-11-09 14:19:14 -08:00
Matt Nadareski
834792bc2d Print NE string table resources 2022-11-09 14:18:59 -08:00
Matt Nadareski
04b225711f Better add TODOs to PE resource printing 2022-11-09 13:29:30 -08:00
Matt Nadareski
eee4a75353 Remove PE resource header writing
This was incorrectly assuming all resources had this header. This is not correct, only a few do. Another debug statement to print out as Unicode characters helped solve this.
2022-11-09 13:22:07 -08:00
Matt Nadareski
15d0df1a12 Add PE resource tree printing (incomplete) 2022-11-09 13:17:14 -08:00
Matt Nadareski
5c3e8c35c4 Add PE accelerator table 2022-11-09 12:05:30 -08:00
Matt Nadareski
ac514fce30 Add PE resource header 2022-11-09 11:58:35 -08:00
Matt Nadareski
f7343ea305 Update PE resource type enum 2022-11-09 11:35:31 -08:00
Matt Nadareski
1435421c3c Add PE accelerator table resource 2022-11-09 11:26:21 -08:00
Matt Nadareski
735c0fe367 Add PE resource table parsing (incomplete) 2022-11-09 11:11:30 -08:00
Matt Nadareski
af99cfa6f9 Add PE virtual address extension 2022-11-08 22:05:30 -08:00
Matt Nadareski
525ff009b6 Fix COFF symbol table entries 2022-11-08 21:43:20 -08:00
Matt Nadareski
ee46167320 Add PE COFF symbol table parsing, printing 2022-11-08 21:36:46 -08:00
Matt Nadareski
6fc03403b4 Add PE section table parsing, writing 2022-11-08 16:31:30 -08:00
Matt Nadareski
760c481d39 Fix PE section header 2022-11-08 16:31:15 -08:00
Matt Nadareski
2c4906534b Enable PE headers writing 2022-11-08 15:11:18 -08:00
Matt Nadareski
2ed79f3f9c Safer PE optional header builder; start printing PE 2022-11-08 15:02:31 -08:00
Matt Nadareski
7e9be878c4 Add PE optional header parsing to builder 2022-11-08 14:27:41 -08:00
Matt Nadareski
0a5ae3b090 Add PE COFF file header parsing to builder 2022-11-08 14:12:05 -08:00
Matt Nadareski
70b8c1f9b7 NE nonresident table absolute, not relative 2022-11-08 14:07:02 -08:00
Matt Nadareski
b067b671db Add PE signature parsing to builder 2022-11-08 14:04:02 -08:00
Matt Nadareski
268ccac7e1 Add NE nonresident name table printing 2022-11-08 13:41:51 -08:00
Matt Nadareski
5e487bc4ba Add NE entry table printing 2022-11-08 13:41:37 -08:00
Matt Nadareski
ffeda7d60b Print NE imported-name table 2022-11-08 13:35:21 -08:00
Matt Nadareski
2779d1a489 Add NE module reference table printing 2022-11-08 13:30:12 -08:00
Matt Nadareski
1752815654 Print NE resident name table 2022-11-08 13:27:12 -08:00
Matt Nadareski
429ca400e5 Fix all NE table bounded offsets 2022-11-08 13:25:31 -08:00
Matt Nadareski
984853bd66 Add NE resource name/type string output 2022-11-08 13:16:24 -08:00
Matt Nadareski
ff2549d4b7 Fix NE resource table parsing 2022-11-08 13:16:00 -08:00
Matt Nadareski
d33bb6b4bb Add first part of NE printing 2022-11-08 13:07:48 -08:00
Matt Nadareski
a3c0eca063 Address some NE parsing issues 2022-11-08 11:52:24 -08:00
Matt Nadareski
10de4ac78e Create executable info test program 2022-11-08 11:35:39 -08:00
Matt Nadareski
895394ebb9 Fix MS-DOS header parsing 2022-11-08 11:30:23 -08:00
Matt Nadareski
349f8d936a Add NE nonresident table to builder 2022-11-08 10:36:16 -08:00
Matt Nadareski
bbc65391a1 Add NE entry table to builder 2022-11-08 10:09:23 -08:00
Matt Nadareski
751c248657 Update NE entry table bundle 2022-11-08 09:59:15 -08:00
Matt Nadareski
9052cd3cdd Add NE imported-name table to builder 2022-11-07 14:13:23 -08:00
Matt Nadareski
2736527fc1 NE imported name table needs indexes 2022-11-07 13:22:59 -08:00
Matt Nadareski
0c7001acf6 Add NE module-reference table parsing
This also fixes a critical flaw in the resident-name table parsing since there is no defined size, just the point where the next table begins.
2022-11-07 10:42:48 -08:00
Matt Nadareski
9e9be5bf09 Add NE resident-name table parsing to builder 2022-11-07 10:13:10 -08:00
Matt Nadareski
008e1ad27b Finalize NE resource table building 2022-11-07 09:38:34 -08:00
Matt Nadareski
3e5ae14a54 Implment first half of NE resource table builder 2022-11-07 09:18:20 -08:00
Matt Nadareski
0c28833b14 Fix offsets for NE tables in builder 2022-11-06 23:58:53 -08:00
Matt Nadareski
75ef95c6bf Fix missing LE/LX/PE stub setting in builders 2022-11-06 23:52:52 -08:00
Matt Nadareski
b906f3c654 Add NE resource table skeleton to builder 2022-11-06 23:49:46 -08:00
Matt Nadareski
4b274a454b Add extensions for NE resource entries 2022-11-06 23:47:54 -08:00
Matt Nadareski
6554005742 Return incomplete NE from builder 2022-11-06 21:48:53 -08:00
Matt Nadareski
9f04022afc Add regions for easier code navigation 2022-11-06 21:48:19 -08:00
Matt Nadareski
fbab512975 Add NE segment table parsing to builder 2022-11-06 21:45:37 -08:00
Matt Nadareski
c9b3a67c8b Merge branch 'master' of https://github.com/mnadareski/BurnOutSharp 2022-11-06 21:39:02 -08:00
Matt Nadareski
3169cd6591 Let private methods be simpler 2022-11-06 21:38:42 -08:00
TheRogueArchivist
b116e487d3 Overhaul Freelock (#170)
* Overhaul Freelock

* Overhaul Freelock, including notes and new checks, along with confirming the existing checks.

* Add text-based checks for Freelock.

* Update README.

* Fix whitespace and re-add return

* Fix whitespace and re-add return
2022-11-06 21:30:59 -08:00
Matt Nadareski
aa57044bb8 Add skeleton for NE segment table parsing 2022-11-06 21:30:19 -08:00
TheRogueArchivist
fdd578dad9 Confirm existing WinLock checks (#169)
* Confirm existing WinLock checks

* Confirm existing WinLock checks.

* Add WinLock notes.

* Update README.

* Rename Winlock.cs to WinLock.cs
2022-11-06 21:22:58 -08:00
Matt Nadareski
2801520546 Add NE header parsing tp builder 2022-11-06 21:19:48 -08:00
TheRogueArchivist
caaf983b3d Overhaul TZCopyProtection (#168)
* Add notes and research relating to TZCopyProtection.

* Fix name (was previously "TZCopyProtector").

* Add new file check for "ZakMcCrack.Ghost".

* Update README.
2022-11-06 21:05:58 -08:00
TheRogueArchivist
aaba13530c Confirm existing CD-Protector checks (#167)
* Confirm existing CD-Protector checks, and add one new one.

* Add CD-Protector notes.

* Update README.
2022-11-06 21:04:03 -08:00
TheRogueArchivist
e05ec3bcee Initial addition of Rainbow Sentinel (#166)
* Initial addition of Rainbow Sentinel

* Basic detection based off of one sample, no specific research/notes.

* Update README.

* Add additional sample sources for Rainbow Sentinel

* Add additional sample sources for Rainbow Sentinel, with no new functionality.

* Add Rainbow Sentinel text checks

* Add Rainbow Sentinel text checks.
2022-11-06 21:03:23 -08:00
Matt Nadareski
703a132a61 Add missing MS-DOS stub to builders 2022-11-06 00:01:24 -07:00
Matt Nadareski
e55226e685 Add header skeletons for NE/LE/LX/PE builders 2022-11-05 23:59:38 -07:00
Matt Nadareski
9a4e6de5f9 Add MS-DOS stub to NE/LE/LX/PE builders 2022-11-05 23:52:16 -07:00
Matt Nadareski
a4e55a328c Add boilerplate for NE, LE, PE builders 2022-11-05 23:47:50 -07:00
Matt Nadareski
2705685f07 Add placeholder LE interface (fixes #165) 2022-11-05 23:42:55 -07:00
Matt Nadareski
b7fb17a79f Add skeletons for other executable types 2022-11-05 23:36:15 -07:00
Matt Nadareski
ffeb73ab7c Add proof-of-concept MS-DOS builder 2022-11-05 23:29:04 -07:00
Matt Nadareski
427dec56e4 Add COFF archive note 2022-11-05 22:46:50 -07:00
Matt Nadareski
94ce87d953 Add PE resource classes 2022-11-05 22:45:18 -07:00
Matt Nadareski
0dc4f0f11a Add PE load configuration directory; fix naming 2022-11-05 22:34:33 -07:00
Matt Nadareski
a1d7e65ffb Add PE TLS directory 2022-11-05 22:11:41 -07:00
Matt Nadareski
61702d9c2a Add PE base relocation blocks 2022-11-05 22:03:17 -07:00
Matt Nadareski
5b08bef53f Add "missing" pieces list, so far 2022-11-05 21:54:36 -07:00
Matt Nadareski
53a6588054 Add PE hint name table entries 2022-11-05 21:49:34 -07:00
Matt Nadareski
9855c0c13e Add PE import directory table entries 2022-11-05 21:41:33 -07:00
Matt Nadareski
c5d005bdeb Add PE export address table entries 2022-11-05 21:37:54 -07:00
Matt Nadareski
1eb844c75b Add PE export directory table 2022-11-05 21:34:30 -07:00
Matt Nadareski
7e177f3cbf Add PE debug directory 2022-11-05 21:29:36 -07:00
Matt Nadareski
eb91cfbda1 Add PE delay load directory 2022-11-05 21:12:41 -07:00
Matt Nadareski
54082c1fce Add PE attribute certificate table 2022-11-05 21:02:30 -07:00
Matt Nadareski
b5caf6dacf Add PE COFF string table 2022-11-05 15:40:48 -07:00
Matt Nadareski
f4d1ce5388 Add PE CLR token definition symbol 2022-11-05 15:37:25 -07:00
Matt Nadareski
7d7ec69dc1 Add PE auxiliary symbol record formats 2022-11-05 15:34:14 -07:00
Matt Nadareski
7208288c00 Add PE section numbers 2022-11-05 15:16:38 -07:00
Matt Nadareski
aff3745859 Add PE COFF symbol table 2022-11-05 00:17:26 -07:00
Matt Nadareski
e103ddd216 Add PE COFF line numbers to section headers 2022-11-05 00:08:00 -07:00
Matt Nadareski
41a4965775 Add PE COFF relocations to section headers 2022-11-05 00:04:17 -07:00
Matt Nadareski
49a06f513b Add PE section table 2022-11-04 23:56:56 -07:00
Matt Nadareski
1308f3684b Add PE data directories 2022-11-04 23:50:54 -07:00
Matt Nadareski
c51eccac38 Add PE optional header 2022-11-04 23:41:31 -07:00
Matt Nadareski
09157767bf Add PE COFF file header 2022-11-04 23:25:02 -07:00
Matt Nadareski
32cc2c708a Add PE enums 2022-11-04 23:19:28 -07:00
Matt Nadareski
7f2de233fc Add PE skeleton, change MZ stubs 2022-11-04 21:05:03 -07:00
Matt Nadareski
7cb150606c Add LE/LX fix-up record table 2022-11-04 21:00:02 -07:00
Matt Nadareski
87cac010eb Fill out most of FixupRecordTableEntry 2022-11-04 17:23:21 -07:00
Matt Nadareski
03926754e7 Add LE/LX FRT source offset/count 2022-11-04 16:59:29 -07:00
Matt Nadareski
65efda1a7a Add LE/LX entry table 2022-11-04 16:51:04 -07:00
Matt Nadareski
5941d4ca16 Add skeleton for FixupRecordTableEntry 2022-11-04 16:27:01 -07:00
Matt Nadareski
e77101af89 Add LE/LX fixup record enums 2022-11-04 16:19:42 -07:00
Matt Nadareski
e766be6af9 Add LE/LX Fix-up page table 2022-11-04 16:09:20 -07:00
Matt Nadareski
95d1658324 Add LE/LX debug information 2022-11-04 16:04:01 -07:00
Matt Nadareski
9b24550738 Add LE/LX verify record directive table 2022-11-04 15:56:08 -07:00
Matt Nadareski
7947568019 Add LE/LX entry table bundle type enum 2022-11-04 15:46:24 -07:00
Matt Nadareski
399ee98923 Add LE/LX import procedure name table 2022-11-04 15:36:38 -07:00
Matt Nadareski
7b3b4a2ec5 Add LE/LX imported module name table 2022-11-04 15:31:59 -07:00
Matt Nadareski
09177da620 Add LE/LX per-page checksum table 2022-11-04 15:29:04 -07:00
Matt Nadareski
8392cfb2fa Add LE/LX module format directives table 2022-11-04 15:24:15 -07:00
Matt Nadareski
01face7315 Add LE/LX resident name tables 2022-11-04 15:00:11 -07:00
Matt Nadareski
5b6f4d65bf Add LE/LX resource table 2022-11-04 14:51:57 -07:00
Matt Nadareski
cd6f8f3db3 Add LE/LX object page table 2022-11-04 13:48:30 -07:00
Matt Nadareski
a9b07ddf1d Add more thorough LE/LX notes 2022-11-04 13:42:58 -07:00
Matt Nadareski
f3710c575b Add LE object table 2022-11-04 12:59:50 -07:00
Matt Nadareski
1f5ab45a1e Add LE information block 2022-11-04 12:55:43 -07:00
Matt Nadareski
58d453db11 Update csproj 2022-11-04 10:35:26 -07:00
Matt Nadareski
bd426b763c Add skeleton for LE work 2022-11-04 10:34:49 -07:00
Matt Nadareski
2e42efa71f Add NE per segment data 2022-11-04 10:25:48 -07:00
Matt Nadareski
58181bd723 Add NE entry table 2022-11-04 10:09:09 -07:00
Matt Nadareski
dcef3115b8 Add NE resource table 2022-11-04 09:56:06 -07:00
Matt Nadareski
4bdc5dc90f Add simple NE tables 2022-11-04 09:40:29 -07:00
TheRogueArchivist
e33d6b3a0a Add support for C-Dilla protections (#164)
* Fuck C-Dilla

* Add initial detection of C-Dilla LMS/CD-Secure.

* Add a few code comments for Macrovision.

* Update README.

* Reorganize C-Dilla NE Checks

* Reorganize C-Dilla NE Checks.
* Add NE skeleton for C-Dilla and other Macrovision protections.
* Add more detections for CD-Secure 1.

* Let Macrovision return multiple protections

* Let Macrovision return multiple protections.
* Add new C-Dilla and SafeCast checks.

* why is C-Dilla so confusing

* Add additional checks for C-Dilla and SafeCast.

* Add skeleton for NE checks for SafeCast.

* Address PR comments
2022-11-04 09:31:20 -07:00
Matt Nadareski
d8ddaccf07 Add OS/2 flags 2022-11-03 23:51:04 -07:00
Matt Nadareski
ca55ea16f0 Fill in missing NE header flags 2022-11-03 23:49:05 -07:00
Matt Nadareski
cb42330e22 Add missing operating systems to enum 2022-11-03 23:42:19 -07:00
Matt Nadareski
4e55cf0baa Add NE segment table 2022-11-03 23:38:51 -07:00
Matt Nadareski
abec45c492 Add skeleton of NE to Models project 2022-11-03 23:32:35 -07:00
Matt Nadareski
610e25b98a Add empty folders for future executable formats 2022-11-03 23:11:26 -07:00
Matt Nadareski
ad11e63338 Add template BurnOutSharp.Models project 2022-11-03 22:57:51 -07:00
TheRogueArchivist
440eb72ae4 The End Is Never The End Is Never The End Is (#163)
* Add notes about C-Dilla.
* Add related notes for other Macrovision/C-Dilla products.
2022-11-02 11:41:34 -07:00
TheRogueArchivist
c4553de302 Add Denuvo Anti-Cheat detection (#162)
* Add support for detecting Denuvo Anti-Cheat

* Update README
2022-10-28 23:10:08 -07:00
TheRogueArchivist
32904b75e4 Begin porting protections made by Macrovision to Macrovision sub-protections (#161)
* Fuck Macrovision

* Port SafeCast/SafeDisc checks to Macrovision sub-protections.

* Move generic checks into the main Macrovision checks.

* Add basic detection for FLEXnet.

* Add C-Dilla notes.

* Add TODO's for porting CactusDataShield.

* Address PR comments
2022-10-27 16:40:16 -07:00
Matt Nadareski
35a4771f89 Split out obvious SafeCast from SafeDisc (nw) 2022-10-26 21:10:33 -07:00
Matt Nadareski
bbb2e9391e Add SafeDisc as Macrovision example (nw) 2022-10-26 21:03:33 -07:00
Matt Nadareski
9dc186f455 Merge branch 'master' of https://github.com/mnadareski/BurnOutSharp 2022-10-26 20:38:39 -07:00
Matt Nadareski
82b9c03a7e Add skeleton for Macrovision sub-protections 2022-10-26 20:38:12 -07:00
TheRogueArchivist
f4f9ba9efa Add "SafeDisc.exe" checks (#160)
* Add checks for "SafeDisc.exe".
* Add note about previously unknown SafeDisc version.
* Add note about Drvmgt file with known sample but no known version.
* Add various SafeDisc/SafeCast resources.
* Add resource for CDS.
2022-10-25 10:31:17 -07:00
TheRogueArchivist
495864e8e0 Add summary for Denuvo (#159)
Add summary and various notes for Denuvo.
2022-10-23 20:46:58 -07:00
Matt Nadareski
ac917df519 Bump version to 2.3.4 2022-10-17 13:18:55 -07:00
Matt Nadareski
3b12fef948 Fix build, fix Nuget 2022-10-17 12:26:57 -07:00
Matt Nadareski
a74b769aef Bump version to 2.3.3 2022-10-17 10:26:21 -07:00
Matt Nadareski
ea17ad1eae Bump version to 2.3.2 2022-10-17 10:10:01 -07:00
Matt Nadareski
6087e6e0c6 Update Nuget packages 2022-10-14 09:28:27 -07:00
TheRogueArchivist
535f14bc54 Cleanup CDS detections (#158)
* Specify CDS-200 for more detections

* Fix the use of GetVersion
2022-10-13 22:14:50 -07:00
Matt Nadareski
6b3d42b81f Include exception in dictionary during debug 2022-10-13 21:52:16 -07:00
TheRogueArchivist
e645b8e1c0 Add notes to unconfirmed detections (#157)
* Add notes to unconfirmed detections

* Add notes to unconfirmed detections to let users know what detections we need samples of.

* Add sources for some protections to confirm them.

* Confirm some RingPROTECH checks

* Confirm some RingPROTECH checks.

* Add notes for IndyVCD.
2022-10-13 20:58:49 -07:00
TheRogueArchivist
955c8685b6 Overhaul CD-Lock (#156)
* Confirm CD-Lock's current detections

* Reduce possibility for CD-Lock false positives

* Add notes about CD-Lock
2022-10-13 11:50:43 -07:00
Matt Nadareski
6184ae22aa Fix StartsWith equal length issue 2022-10-11 21:14:58 -07:00
TheRogueArchivist
4e2c5313f3 Add support for PlayJ (#155)
* Add support for PlayJ

* Add support for detecting PlayJ format audio files and PlayJ Music Player related files.
* Add an incomplete summary for Cactus Data Shield.
* Improve Cactus Data Shield Detection for CDS-200 (PlayJ).

* Address PlayJ PR comments

Fix whitespace and improve safety of PlayJ header check.

* Address further PlayJ PR comments

Reduce redundancy and further improve safety.
2022-10-11 21:00:30 -07:00
TheRogueArchivist
137f7fcc01 Add Doc.loc as an undetected protection and add notes (#153)
* Add Doc.loc as an undetected copy protection, along with basic notes.
* Fix link in "Special Thanks" in README.md
2022-09-26 09:35:04 -07:00
TheRogueArchivist
d771c4931c Add grouped name check for mcp.dll (#149) 2022-08-30 21:32:21 -07:00
TheRogueArchivist
61a2181924 Improve Alpha-ROM detection (#152)
Check for an existing string in the overlay as well as the .data section.
2022-08-30 20:10:56 -07:00
Matt Nadareski
baad181e5f Bump version to 2.3.1 2022-08-25 10:03:48 -07:00
Matt Nadareski
1b0fcdcf32 Bump version to 2.3.0 2022-08-22 09:30:49 -07:00
Matt Nadareski
9fa1ef1d2e Slight cleanup of CDS 2022-08-21 20:36:37 -07:00
Matt Nadareski
e2492c9e5b Consolidate field string checks (fixes #141) 2022-08-21 20:34:59 -07:00
TheRogueArchivist
297514ef17 Overhaul SafeDisc detection (#133)
* Begin overhauling SafeDisc detection

* A new utility method for obtaining the SHA1 hash of a file.
* SHA1-based detection for drvmgt.dll, which is vastly more accurate than the existing size checks.
* (Currently nonfunctional) PEX based checks for newer secdrv.sys versions.
* General clean-up and minor additions.

* Address PR review comments

* Address further PR comments and remove some file size checks

Remove file size checks that are now redundant.

* Add CLCD16 hash based version detection

Add support for detecting a rough version range from the hash of CLCD16.dll, as well as general cleanup.

* Add CLCD32 hash based version detection

Add hash based version checks for CLCD32.dll, which provides reliable detection for 1.X, much more than CLCD16.dll.

* Add CLOKSPL hash based version detection

Add CLOKSPL hash based version detection, which is an excellent indicator of version within 1.X.

* Add detailed SafeDisc version notes, address PR reviews

* Add a note that includes every known SafeDisc and SafeCast version.

* General cleanup and minor detection additions.

* Address PR reviews.

* Various SafeDisc detection improvements

* Add broad version checks for 00000001.TMP.

* Add a few SafeDisc Lite specific CLCD32.DLL checks.

* Remove unneeded dplayerx.dll size checks that were already covered by executable string checks.

* Improve DPlayerX version size checks

Improve DPlayerX existing version size checks and add new ones.

Add new hash checks for previously undetected files.

* Improve secdrv.sys version detection

Improve secdrv.sys version detection using both file size checks and product version checks.

* Fix various false positives

Fix various false positives, as well as incomplete detections.

* Address PR comments

* Properly set check for File Description
2022-08-21 20:20:28 -07:00
SilasLaspada
2acb0a037c Add initial support for detecting Easy Anti-Cheat (#148)
Add initial support for detecting Easy Anti-Cheat. This is presumed to only detect later versions, though it's possible that older versions may be detected as well.
2022-08-13 20:09:46 -07:00
SilasLaspada
c38eb0cc71 Various note additions and minor fixes (#147)
- Add notes for Alpha-ROM, Hexalock, SVKP, and Zzxzz.

- Fix typos for Intenium.
2022-08-13 20:04:26 -07:00
SilasLaspada
258369bb9e Add support for detecting "AegiSoft License Manager" (#144)
Add support for "AegiSoft License Manager", as well as notes about what's known about the protection so far.
2022-08-13 20:03:27 -07:00
SilasLaspada
8cba9529d7 Overhaul DiscGuard detection (#140)
* Overhaul DiscGuard detection

* Verify some existing checks for DiscGuard.
* Add several new executable and path checks.
* Add note for remaining unconfirmed check.
* Add notes and research in comments.
* Add related protection "DiscAudit" to list of protections that needs to be added.

* Address DiscGuard PR review comments
2022-07-28 23:31:04 -07:00
SilasLaspada
10296f40b4 Improve Alpha-ROM detection for Siglus and RealLive games (#139)
* Improve Alpha-ROM detection for Siglus and RealLive games

Improve Alpha-ROM detection for games that use the Siglus and RealLive VN game engines.

* Address PR comments for Alpha-ROM

* Add comment and address PR review
2022-07-28 21:03:35 -07:00
Matt Nadareski
73d085deac Update stream path for VersionInfo 2022-07-27 22:31:15 -07:00
SilasLaspada
c7261c342a Vastly improve MediaCloQ checks (#138)
* Vastly improve MediaCloQ checks

Vastly improve MediaCloQ checks, including adding content and text file checks. Also, add notes relating to it in comments.

* Add comment to MediaCloQ

Add mention of "sunncomm.ico" being used as a previous check.
2022-07-27 13:06:52 -07:00
Matt Nadareski
14d905fba3 Handle alternatively named version resources 2022-07-27 11:28:24 -07:00
Matt Nadareski
1f66edc201 Fix some resource finding 2022-07-27 11:10:46 -07:00
SilasLaspada
ade95c3210 Improve Hexalock AutoLock detection (#136)
* Improve Hexalock AutoLock detection

Verify the last remaining unverified checks, and add more checks and notes.

* Add special thanks for Hexalock
2022-07-26 20:17:28 -07:00
SilasLaspada
8a419f50db Fix MediaMax CD-3 false positive (#135)
The LaunchCD files checked for were completely unrelated to the copy protection.
2022-07-23 23:55:04 -07:00
Matt Nadareski
52efca767e Make sure start/end not reset 2022-07-17 21:14:20 -07:00
Matt Nadareski
421dfa2591 Add LibMSPackSharp note in readme 2022-07-13 14:02:52 -07:00
Matt Nadareski
76183c529c Remove explicit .NET Core 3.1 and .NET 5.0 builds 2022-07-13 13:46:30 -07:00
Matt Nadareski
463506d1e8 Add note to Wise Installer 2022-07-13 12:54:42 -07:00
Matt Nadareski
1f2a187f55 Add note to UPX 2022-07-13 12:54:08 -07:00
Matt Nadareski
40de5c4d0a Add note to Shrinker 2022-07-13 12:53:28 -07:00
Matt Nadareski
5e72acb44c Add note to Setup Factory 2022-07-13 12:53:08 -07:00
Matt Nadareski
fab3c935f8 Add note to PEtite 2022-07-13 12:52:41 -07:00
Matt Nadareski
a498513662 Add note to PECompact 2022-07-13 12:52:20 -07:00
Matt Nadareski
3eaebffff1 Add note to MS-CAB SFX 2022-07-13 12:51:54 -07:00
Matt Nadareski
280ae5babe Add note to Installer VISE 2022-07-13 12:51:21 -07:00
Matt Nadareski
5bf64d46bd Add note to InstallAnywhere 2022-07-13 12:51:00 -07:00
Matt Nadareski
6fb510c852 Add note to Inno Setup 2022-07-13 12:50:36 -07:00
Matt Nadareski
20223eea87 Add note to Gentee Installer 2022-07-13 12:50:06 -07:00
Matt Nadareski
3f796e4e0e Add note to EXEStealth 2022-07-13 12:49:34 -07:00
Matt Nadareski
74732a1b50 Add note to CExe 2022-07-13 12:48:49 -07:00
Matt Nadareski
f252681364 Add note to Armadillo 2022-07-13 12:48:16 -07:00
Matt Nadareski
82cb0f934d Add note to Themida 2022-07-13 12:47:06 -07:00
Matt Nadareski
7dc5644d21 Add note to SVKP 2022-07-13 12:46:17 -07:00
Matt Nadareski
313cc2bfb8 Add another source for CrypKey 2022-07-13 12:18:39 -07:00
Matt Nadareski
f24a8763fd Add missing ActiveMark entry point checks 2022-07-13 12:14:39 -07:00
Matt Nadareski
47845a2409 Split Cucko into separate file 2022-07-13 11:52:49 -07:00
SilasLaspada
42da9f4a82 Add support for detecting Cucko (#132)
* Add support for detecting Cucko

Add support for detecting Cucko.

* Remove debug line
2022-07-12 22:57:22 -07:00
Matt Nadareski
e9fa86343a Add special thanks 2022-07-11 22:45:12 -07:00
Matt Nadareski
8ccf2272d6 Add proper SecuROM White Label detection 2022-07-11 22:38:02 -07:00
Matt Nadareski
8fb42bc12d Add ASPack 2022-07-11 21:23:44 -07:00
Matt Nadareski
6202ee5d5c Print sections during debug 2022-07-11 16:10:52 -07:00
Matt Nadareski
655a8adb1c Disable .shr section for SecuROM for now 2022-07-11 10:08:08 -07:00
Matt Nadareski
d7fcc99fc2 Add volitile by default 2022-07-08 14:50:03 -07:00
Matt Nadareski
8601f373bd More work on MS-CAB and MSZIP 2022-07-08 13:07:03 -07:00
Matt Nadareski
3c783fdc68 Re-format some info data 2022-07-07 17:02:43 -07:00
Matt Nadareski
a75388cf17 Merge branch 'master' of https://github.com/mnadareski/BurnOutSharp 2022-07-07 16:34:52 -07:00
Matt Nadareski
7968a79fe6 Add start of decompression 2022-07-07 16:33:15 -07:00
SilasLaspada
8502924083 Overhaul existing and add new audio CD protections (#131)
* Overhaul existing and add new audio CD protections

Overhaul many audio CD protections, on top of adding a few more. Unfortunately, disable key2Audio detection as well, as the existing checks were simply detecting OpenMG components and not key2Audio itself.

* Fix issues from PR review
2022-07-07 15:24:41 -07:00
Matt Nadareski
af95ca08c3 Add dec/hex outputs 2022-07-07 15:24:24 -07:00
Matt Nadareski
06995b75d6 Move printing to classes 2022-07-07 15:16:34 -07:00
Matt Nadareski
1a2be26c72 Finalize intial info output 2022-07-07 15:10:31 -07:00
Matt Nadareski
a2a583e317 Add GetInfo, fix MSCABCabinet deserialize 2022-07-07 14:55:29 -07:00
Matt Nadareski
289a55ca21 Seek to file header location instead 2022-07-07 14:20:31 -07:00
Matt Nadareski
598f625ed1 Add some deserialization for MPQ 2022-07-07 14:15:44 -07:00
Matt Nadareski
d604a6d784 Fix endregion tags 2022-07-07 13:27:31 -07:00
Matt Nadareski
cf34a0adee Add Quantum framework 2022-07-07 13:27:13 -07:00
Matt Nadareski
083ded8a7e Add framework for extract all files 2022-07-07 12:43:35 -07:00
Matt Nadareski
1517a66724 Add cabinet finding 2022-07-07 12:11:23 -07:00
Matt Nadareski
5385de0f0a Add MS-ZIP deserialize and deflate 2022-07-07 12:02:25 -07:00
Matt Nadareski
43729b53f0 Add multi-cabinet note 2022-07-07 11:51:27 -07:00
Matt Nadareski
e4aa618f0b Add automatic date-time translation 2022-07-07 11:49:57 -07:00
Matt Nadareski
4953673caf Start writing CAB extraction 2022-07-07 11:37:53 -07:00
Matt Nadareski
35c6d4f36c Add unused cabinet-level deserialization 2022-07-07 11:24:21 -07:00
Matt Nadareski
9108fa5a11 Add unused MS-CAB deserialization 2022-07-07 11:15:35 -07:00
Matt Nadareski
dc97feae39 Add unused structures for MS-CAB 2022-07-07 10:39:41 -07:00
Matt Nadareski
beac29c650 Re-add Wix for MS-CAB
Added until LibMSPackSharp can be fixed
2022-07-06 15:33:10 -07:00
Matt Nadareski
21a041dad6 Update MS-CAB 2022-07-06 15:17:02 -07:00
Matt Nadareski
26eee23511 Update LibMSPackSharp to newest Git version 2022-07-06 15:16:41 -07:00
Matt Nadareski
0915c7eccd Add a few more things for MPQ 2022-07-06 13:39:54 -07:00
Matt Nadareski
e2e65bfbdf Add some unused structures for MPQ 2022-07-05 22:35:58 -07:00
SilasLaspada
033f2e0a4e Improve Cenega ProtectDVD detection (#129)
Improve detection of Cenega ProtectDVD and add notes.
2022-07-05 21:03:27 -07:00
SilasLaspada
71ee0863eb Add shell for Themida (#128)
Add shell and a few notes for Themida/WinLicense/Code Virtualize.
2022-07-04 21:15:18 -07:00
SilasLaspada
3203c3ac83 Improve Steam detection (#127)
Improve Steam detection. Fixes #114
2022-06-30 16:18:12 -07:00
SilasLaspada
1733f60a0f Improve HexaLock AutoLock detection (#126)
Vastly improve HexaLock AutoLock detection, and add notes.
2022-06-30 16:17:18 -07:00
SilasLaspada
b01abdcce3 Improve Bitpool detection (#125)
Improve Bitpool detection on top of adding many more notes.
2022-06-30 16:14:09 -07:00
SilasLaspada
53c90533e3 Improve ProtectDISC checks (#124)
This check is known to be used in at ProtectDISC 6.8.
2022-06-29 14:30:13 -07:00
SilasLaspada
03bd7bd1f5 Add initial detection of WMDS, and improve detection of MediaMax CD-3 (#122)
* Add initial detection of WMDS, and improve detection of MediaMax CD-3

Add initial detection of Windows Media Data Session, and improve detection of MediaMax CD-3.

* Fix whitespace

Fix whitespace as requested in PR review.

* Add comment to WMDS

* Further improve MediaMax CD-3 checks
2022-06-29 14:28:46 -07:00
Matt Nadareski
637579b0fc Remove Wix 2022-06-23 14:02:18 -07:00
Matt Nadareski
bd40ca6d9d Use OpenMcdf for MSI 2022-06-23 13:58:48 -07:00
Matt Nadareski
3c1623cb22 Remove libgsf/libmsi/ComHandler 2022-06-23 13:57:41 -07:00
SilasLaspada
66da32b5c1 Initial Detection of "Dinamic Multimedia Protection"/LockBlocks (#121)
Add initial detection of and notes about "Dinamic Multimedia Protection"/LockBlocks.

Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2022-06-22 13:52:58 -07:00
Matt Nadareski
c21b64b5bd Add initial Denuvo checks (fixes #75) 2022-06-22 13:40:28 -07:00
Matt Nadareski
e968eeea96 Add entry point note to Tages 2022-06-22 10:17:56 -07:00
Matt Nadareski
c14005dcc4 Add entry point note to Steam 2022-06-22 10:03:14 -07:00
Matt Nadareski
84c6c257df Add missing protection note for StarForce 2022-06-22 10:00:35 -07:00
Matt Nadareski
e28b930f85 Add entry point note to SafeDisc 2022-06-22 09:57:12 -07:00
Matt Nadareski
9dac2eb91b Add entry point note to LaserLok 2022-06-22 09:54:38 -07:00
Matt Nadareski
2209f362fa Add notes for CrypKey 2022-06-22 09:50:16 -07:00
Matt Nadareski
614413ab76 Add missing checks for ActiveMARK 2022-06-22 09:42:52 -07:00
Matt Nadareski
35c15d0ff8 Add missing SecuROM 8 check 2022-06-22 09:35:41 -07:00
Matt Nadareski
b521df2ad4 Fix finding, update SecuROM 2022-06-22 09:29:29 -07:00
Matt Nadareski
778fe106f9 Read overlay data (unused) 2022-06-22 09:13:01 -07:00
Matt Nadareski
9171014dcd Add missing PKZIP signature 2022-06-21 23:39:19 -07:00
Matt Nadareski
7ee74d9b81 Port remaining psxt001z code 2022-06-21 23:38:30 -07:00
Matt Nadareski
826011f532 More small cleanup (nw) 2022-06-20 22:37:46 -07:00
Matt Nadareski
adb349932f Start overlay framework 2022-06-20 21:39:19 -07:00
Matt Nadareski
f4f13c03fe Update SharpCompress 2022-06-20 21:38:01 -07:00
Matt Nadareski
e29e87444e ComHandler 2022-06-20 21:36:53 -07:00
Matt Nadareski
b233b3c17b Add data at PE entry point 2022-06-19 22:40:07 -07:00
Matt Nadareski
a8fca77331 Minor cleanup attempt 2022-06-18 23:19:57 -07:00
Matt Nadareski
5e4ee07646 Partially fix caching 2022-06-18 21:59:13 -07:00
Matt Nadareski
52b2a9bef8 Fix name decode 2022-06-18 21:49:06 -07:00
Matt Nadareski
dc7f8da52f Simplify and fix MS-OLE 2022-06-18 21:16:11 -07:00
Matt Nadareski
d46b0768a0 LibMSI cleanup and notes (nw) 2022-06-17 23:12:21 -07:00
Matt Nadareski
f136af3457 Cleanup and minor MS-OLE fixes 2022-06-17 23:11:12 -07:00
Matt Nadareski
2e2b6068c5 Fix SQL parsing 2022-06-17 21:22:06 -07:00
Matt Nadareski
7a29d8a8f9 Fix StringTable read/build 2022-06-17 14:53:18 -07:00
Matt Nadareski
ae0c47066e Safety and trimming 2022-06-17 14:47:32 -07:00
Matt Nadareski
11188c9488 Buffer pointer 2022-06-17 14:46:59 -07:00
Matt Nadareski
4d5d2d8690 Seek -> SeekImpl 2022-06-17 13:41:51 -07:00
SilasLaspada
1860a863b8 Add initial detection of phenoProtect (#120)
Add initial detection of phenoProtect, which is currently text file based only.
2022-06-16 22:13:02 -07:00
Matt Nadareski
8dbf6d9362 GsfInfileZip second pass 2022-06-16 22:11:09 -07:00
Matt Nadareski
e3e8a1170f GsfInfileTar second pass 2022-06-16 16:43:07 -07:00
Matt Nadareski
b22641b7ab GsfInfileStdio second pass 2022-06-16 15:43:10 -07:00
Matt Nadareski
d3d75b9e58 GsfInfileMSVBA second pass 2022-06-16 15:35:58 -07:00
Matt Nadareski
6083c64b87 GsfInfileMSOle second pass 2022-06-16 15:17:38 -07:00
Matt Nadareski
4185367a49 GsfBlob, GsfClipData, and GsfDocMetaData second pass 2022-06-16 13:54:35 -07:00
Matt Nadareski
c027b1798a Ensure consistent reads and writes 2022-06-16 13:07:41 -07:00
Matt Nadareski
76e52292a8 Fix GsfInputMemory.ReadImpl 2022-06-15 23:43:59 -07:00
Matt Nadareski
dd5f7c4e0b Fix GsfInputStdio.MakeLocalCopy 2022-06-15 23:35:06 -07:00
Matt Nadareski
6e70991e86 Fix build, add export all (nw) 2022-06-15 23:31:08 -07:00
Matt Nadareski
f1803b9f3a Organize files, clean up formatting, add TODOs 2022-06-15 22:53:41 -07:00
Matt Nadareski
9e0abe7c5d Merge branch 'master' of https://github.com/mnadareski/BurnOutSharp 2022-06-15 17:19:59 -07:00
Matt Nadareski
1a01102252 LibMSI (nw) 2022-06-15 17:19:44 -07:00
Matt Nadareski
ce849d312f Fix naming in GSF 2022-06-15 17:19:25 -07:00
SilasLaspada
71da8a53c0 Add detection for new TAGES variant and add references to Redump entries (#119)
Add detection for new TAGES variant found in Robocop, and add the Redump entries for every listed file.
2022-06-13 00:12:34 -07:00
Matt Nadareski
b8f7d00dc9 Fix LibGSF build 2022-06-10 20:59:36 -07:00
Matt Nadareski
7e69a56892 LibGSF (nw) 2022-06-10 15:29:58 -07:00
Matt Nadareski
8cedd3e469 Handle malformed IS-CAB filenames 2022-06-04 22:02:13 -07:00
Matt Nadareski
d5e60439fb Remove now-unused Wix references 2022-06-04 22:01:02 -07:00
Matt Nadareski
1a0e16a05b Use new debug flag 2022-06-01 12:01:14 -07:00
Matt Nadareski
bee6d2b885 Update LibMSPackSharp 2022-06-01 11:50:49 -07:00
Matt Nadareski
5d515c7ddd Update LibMSPackSharp 2022-06-01 11:34:50 -07:00
Matt Nadareski
013301fa99 Update LibMSPackSharp 2022-05-31 16:40:12 -07:00
Matt Nadareski
152ae8bf6c Update LibMSPackSharp 2022-05-31 16:38:21 -07:00
Matt Nadareski
439f71ef5c Migrate to external libmspack 2022-05-31 16:34:40 -07:00
Matt Nadareski
66c7afe20b Use placeholder cabinet to start at first file 2022-05-31 16:06:29 -07:00
Matt Nadareski
6a609ea3f5 Break and set fixing flags if there's an appending error 2022-05-31 16:04:20 -07:00
Matt Nadareski
6752d0cfa3 Append cabinets where needed 2022-05-31 15:54:53 -07:00
Matt Nadareski
1d26b06592 Fix 0 checks, fix aligned table creation 2022-05-31 15:44:22 -07:00
Matt Nadareski
9ca24a3053 LZX and MSCAB format cleanup 2022-05-26 23:12:53 -07:00
Matt Nadareski
76ca87f7a9 Fully fix LZX 2022-05-25 23:52:26 -07:00
Matt Nadareski
c913b10286 Partially fix CAB decompression 2022-05-25 23:46:45 -07:00
Matt Nadareski
768c77a6bc Attempts at changes 2022-05-25 21:55:36 -07:00
Matt Nadareski
20d90d6a60 More reorganization 2022-05-24 21:39:33 -07:00
Matt Nadareski
54a48e0729 Less static methods 2022-05-24 17:05:34 -07:00
Matt Nadareski
15c05c65e7 Partial classes 2022-05-24 16:52:41 -07:00
Matt Nadareski
4dbaa415c5 Constants 2022-05-24 15:52:05 -07:00
Matt Nadareski
1a0b83a9f1 Split last MSB/LSB 2022-05-24 09:35:11 -07:00
Matt Nadareski
4316427980 Nearly finish demacroificiation 2022-05-24 00:47:09 -07:00
Matt Nadareski
21ecaca761 Properly implement methods from macros 2022-05-23 23:31:55 -07:00
Matt Nadareski
7022a957d6 Start making common read methods again 2022-05-23 22:36:24 -07:00
Matt Nadareski
32cfcbff0a Rename a couple things 2022-05-23 21:21:13 -07:00
Matt Nadareski
283fa425d4 Partial OAB cleanup 2022-05-23 21:16:42 -07:00
Matt Nadareski
d37eac02d5 KWAJ objectification and cleanup 2022-05-23 21:13:55 -07:00
Matt Nadareski
c3e0b99002 CHM decompressor cleanup 2022-05-23 20:48:34 -07:00
Matt Nadareski
9e49703bc5 Clean up some CAB decompressor code 2022-05-23 15:05:03 -07:00
Matt Nadareski
98a7149cc9 CHM objectification cleanup 2022-05-23 14:25:22 -07:00
Matt Nadareski
394b4e70fb libmspack cleanup 2022-05-23 13:36:19 -07:00
Matt Nadareski
b29198b3d4 CHM objectification 2022-05-22 23:46:29 -07:00
Matt Nadareski
044c398fa7 Minor LZX cleanup (nw) 2022-05-22 20:41:41 -07:00
Matt Nadareski
ae7087e8d0 Attempts at LZX fixes 2022-05-22 13:57:33 -07:00
Matt Nadareski
90bc78982c Safer opening of CABs 2022-05-22 13:13:42 -07:00
Matt Nadareski
2ce8bda394 Skip other null writes for other packages 2022-05-22 10:21:54 -07:00
Matt Nadareski
ac0ed050dc Partially fix MSZIP decompression 2022-05-22 10:17:41 -07:00
Matt Nadareski
e4aadb3794 Minor tweaks that might help 2022-05-22 00:19:04 -07:00
Matt Nadareski
80626f3b9e Cleanup to get some things working 2022-05-21 23:44:03 -07:00
Matt Nadareski
93263dfeb9 Finish KWAJ LZH and get building 2022-05-21 22:38:28 -07:00
Matt Nadareski
51e5f82cc2 Complete LZX implementation 2022-05-21 22:18:25 -07:00
Matt Nadareski
b69c5cf928 Huffman tree implement MSZIP (nw) 2022-05-21 21:47:54 -07:00
Matt Nadareski
e45b593c7b LZH KWAJ demacroificiation (nw) 2022-05-21 21:26:42 -07:00
Matt Nadareski
c245ebb80a Focus on QTM for demacroification 2022-05-21 21:00:26 -07:00
Matt Nadareski
cd38407e4e Continue demacroization (nw) 2022-05-20 23:33:57 -07:00
Matt Nadareski
f34b1ba5cf Continue demacroification (nw) 2022-05-20 22:29:43 -07:00
Matt Nadareski
08c97d291e Start of de-macro-ification 2022-05-19 23:52:08 -07:00
Matt Nadareski
3ea294f4d9 DefaultFileImpl -> FileStream 2022-05-19 22:32:58 -07:00
Matt Nadareski
ddb2be278a More CAB-specific cleanup 2022-05-19 22:19:06 -07:00
Matt Nadareski
b6b5dc4efa Make more objects for CAB 2022-05-19 20:46:58 -07:00
Matt Nadareski
218fecb273 Start cleanup on libmspack 2022-05-19 17:07:08 -07:00
Matt Nadareski
b23a504c7b Missed a few cast->as 2022-05-19 12:11:23 -07:00
Matt Nadareski
c54181e9ac "as" not "cast" 2022-05-19 11:56:38 -07:00
Matt Nadareski
7e100a261c Make Library static 2022-05-19 11:24:34 -07:00
Matt Nadareski
38e1154bad Add initial port of libmspack (nw) 2022-05-19 11:20:44 -07:00
Matt Nadareski
901804e9e4 Add OS limitation note to readme 2022-05-15 21:09:03 -07:00
Matt Nadareski
dfee4a8d76 Use debug flag for exception printing 2022-05-15 20:58:27 -07:00
Matt Nadareski
295b86fbd0 Replace HLExtract with HLLibSharp 2022-05-15 14:18:45 -07:00
Matt Nadareski
177543a51c Use WixToolset for MS-CAB 2022-05-14 21:25:41 -07:00
Matt Nadareski
dfff702e5d Remove x86 build limitation on test program 2022-05-14 14:37:52 -07:00
Matt Nadareski
c0ad427b5e Remove x86 build limitation on library 2022-05-14 14:33:15 -07:00
Matt Nadareski
2f68f95d80 Path.DirectorySeparatorChar 2022-05-13 21:03:13 -07:00
Matt Nadareski
a8ba104d0f Better interface comments 2022-05-01 21:06:52 -07:00
Matt Nadareski
6f9e92d222 Clean up interface comments 2022-05-01 21:03:48 -07:00
Matt Nadareski
1e20c1b147 Ensure packer consistency 2022-05-01 21:02:59 -07:00
Matt Nadareski
c16946ace7 Add IScannable to GenteeInstaller 2022-05-01 20:44:45 -07:00
Matt Nadareski
9d7cc4012c Move interfaces to own namespace 2022-05-01 17:41:50 -07:00
Matt Nadareski
a44bdf9013 Reorder inherited interfaces 2022-05-01 17:23:00 -07:00
Matt Nadareski
f9f2e0d932 Better naming 2022-05-01 17:17:15 -07:00
Matt Nadareski
2dd3e21ea6 Separate stream helper 2022-05-01 17:06:46 -07:00
Matt Nadareski
81bb47b634 Progress tracker doesn't need to be public 2022-05-01 16:59:03 -07:00
Matt Nadareski
c8efc1430a Get fancy 2022-05-01 14:46:01 -07:00
Matt Nadareski
7883638f0a Make helper method easier to read 2022-05-01 14:28:28 -07:00
Matt Nadareski
e930be12c8 Reduce parameters for helper 2022-05-01 14:27:04 -07:00
Matt Nadareski
c45ae4b693 Consolidate ShouldAddProtection checks 2022-05-01 14:24:46 -07:00
Matt Nadareski
478f28b513 Create Initializer class 2022-05-01 14:16:53 -07:00
Matt Nadareski
aac3c391db Simplify construction and access in Scanner 2022-05-01 14:11:09 -07:00
Matt Nadareski
802734b515 Remove another implicit assignment 2022-05-01 14:04:21 -07:00
Matt Nadareski
ef212fc8d9 Remove library-level assignments in Scanner 2022-05-01 14:00:20 -07:00
Matt Nadareski
ee85f2f6f0 Remove useless all files flag 2022-05-01 13:58:43 -07:00
Matt Nadareski
9a160b3127 Split Directory/File checks for SafeDisc 2022-04-25 12:34:39 -07:00
Matt Nadareski
4486c5ed62 ICD overmatches for SafeDisc, somehow 2022-04-25 12:27:07 -07:00
Matt Nadareski
d6feab3958 Bump version to 2.1.0 2022-04-17 22:02:43 -07:00
Matt Nadareski
2d2207a1ee Update UnshieldSharp to 1.6.8 2022-04-17 13:35:14 -07:00
Matt Nadareski
89b86630d8 Update WiseUnpacker to 1.0.3 2022-04-17 13:33:59 -07:00
Matt Nadareski
bcb1571a23 Use .NET Standard 2.0, add .NET 6.0 2022-04-16 21:58:54 -07:00
Matt Nadareski
5d658ebe4a Upgrade to VS2022 for AppVeyor 2022-04-16 21:56:45 -07:00
Matt Nadareski
7d2de80e77 Fix over-matching SafeLock 2022-04-02 21:36:29 -07:00
Matt Nadareski
b933249ff7 Add resource finding on creation 2022-04-02 16:12:23 -07:00
Matt Nadareski
61c09e3c97 Move resource helpers to PortableExecutable 2022-04-02 15:54:51 -07:00
SilasLaspada
32695ee6dd Add support for detecting AutoPlay Media Studio (#116)
* Add support for detecting AutoPlay Media Studio

* Comment out too vague AutoPlay Media Studio check

* Tweak comment
2022-04-01 23:23:32 -07:00
Matt Nadareski
4b66cd8cd2 Update file version resource handling 2022-04-01 10:16:31 -07:00
SilasLaspada
edc4cc1706 Refactor Setup Factory detection (#115)
* Refactor Setup Factory detection

* Address Setup Factory PR comments

* Fix whitespace
2022-04-01 09:58:02 -07:00
Matt Nadareski
35acb77bf7 Bump version to 2.0.0 2022-03-27 20:43:49 -07:00
Matt Nadareski
e970a7b4d9 Clean up SafeDisc a little more 2022-03-18 21:05:09 -07:00
Matt Nadareski
f155291139 Update comments after confirmation of existence 2022-03-17 12:18:08 -07:00
Matt Nadareski
b0293419e1 Add note to Tages for future research 2022-03-17 12:16:41 -07:00
Matt Nadareski
09db225929 Simplify TAGES version checking 2022-03-17 12:13:11 -07:00
Matt Nadareski
0c52b4e236 Update to UnshieldSharp 1.6.7 2022-03-17 10:03:39 -07:00
Matt Nadareski
5dc30942ff Add missing TAGES version byte 2022-03-15 23:04:10 -07:00
Matt Nadareski
cab200e893 Add Shrinker PE detection 2022-03-15 22:44:10 -07:00
Matt Nadareski
c349f3a3c4 Add Gentee Installer detection (fixes #93) 2022-03-15 22:35:44 -07:00
Matt Nadareski
0acb29f2e9 Add Steam Client Engine check 2022-03-15 22:23:23 -07:00
Matt Nadareski
b66e01f7b4 Fix SLL comment 2022-03-15 22:11:37 -07:00
Matt Nadareski
8d6d215e57 Remove commented debug code 2022-03-15 22:10:13 -07:00
Matt Nadareski
d54a90a034 Add some missing SecuROM checks 2022-03-15 22:09:28 -07:00
Matt Nadareski
e1e7172561 Make ReadArbitraryRange safer 2022-03-15 21:30:46 -07:00
Matt Nadareski
6606b388f6 Remove duplicate comment 2022-03-15 15:48:05 -07:00
Matt Nadareski
b6c6c01358 Slightly rearrange generic content check invocation 2022-03-15 15:47:37 -07:00
Matt Nadareski
6886c5a4a2 Convert SVKP to PE content check 2022-03-15 15:39:35 -07:00
Matt Nadareski
87546a3dc8 Remove lingering unconfirmed TAGES check 2022-03-15 15:37:13 -07:00
Matt Nadareski
6e3028639a Fix one TAGES PE check 2022-03-15 15:05:08 -07:00
Matt Nadareski
386da02e27 Convert CExe to PE content check 2022-03-15 13:19:06 -07:00
Matt Nadareski
ec8c395ffa Streams 2022-03-15 12:39:22 -07:00
Matt Nadareski
9b98215fc9 Make SourceArray private in NE 2022-03-15 11:18:53 -07:00
Matt Nadareski
40e037fb2a Make SourceStream private 2022-03-15 11:11:54 -07:00
Matt Nadareski
17f8569a7e Only read resource in WinZipSFX 2022-03-15 11:11:44 -07:00
Matt Nadareski
1105f36cee Add hacky thing for Inno for now 2022-03-15 11:11:22 -07:00
Matt Nadareski
f9fcd8749b Add arbitrary reads to NE 2022-03-15 10:50:40 -07:00
Matt Nadareski
eef76d362a Fix arbitrary reads, update SecuROM check 2022-03-15 10:39:06 -07:00
Matt Nadareski
3b0e3693eb Add arbitrary range reading 2022-03-15 10:26:29 -07:00
Matt Nadareski
ba4c56997a Add Relocation section skeleton 2022-03-15 10:15:05 -07:00
Matt Nadareski
ca4d08567d Fix resetting position for DebugSection 2022-03-15 10:02:10 -07:00
Matt Nadareski
3211149996 Remove NE Inno check from PE path 2022-03-15 09:01:54 -07:00
Matt Nadareski
5a7e60cabb Use backward read for UPX 2022-03-15 00:30:33 -07:00
Matt Nadareski
46ff4b6ef9 Remove one use of SourceArray in SecuROM 2022-03-14 23:44:17 -07:00
Matt Nadareski
dc252e8d86 Add comments around remaining SourceArray usages 2022-03-14 23:32:19 -07:00
Matt Nadareski
133e29dc2e Add NameString to SectionHeader 2022-03-14 23:28:31 -07:00
Matt Nadareski
368cec4fc6 Remove more explicit content array usages 2022-03-14 23:17:45 -07:00
Matt Nadareski
65eea4301d Hide section complexity from content checks 2022-03-14 23:01:06 -07:00
Matt Nadareski
ceae505f4d Switch order of interface parameters 2022-03-14 22:51:17 -07:00
Matt Nadareski
a7e9164f4f Use SourceArray for PE checks 2022-03-14 22:49:35 -07:00
Matt Nadareski
3820546c07 Use SourceArray for NE checks 2022-03-14 22:43:26 -07:00
Matt Nadareski
0fa6673d21 Add debug section (nw) 2022-03-14 15:27:42 -07:00
Matt Nadareski
0a486c2195 Add another Uplay check, note 2022-03-14 15:08:27 -07:00
Matt Nadareski
a723fbefc3 Add some resource checks for WTM 2022-03-14 15:00:20 -07:00
Matt Nadareski
70e64e57dd Add PE content checks for Uplay 2022-03-14 14:56:41 -07:00
Matt Nadareski
edfc3c6c5d Add PE checks for Steam 2022-03-14 12:16:38 -07:00
Matt Nadareski
c4447fc505 Modernize path check for SolidShield a little 2022-03-14 12:09:03 -07:00
Matt Nadareski
a1d2292381 Add content checks for key2AudioXS 2022-03-14 12:08:35 -07:00
Matt Nadareski
033fb0c1ac Add utility checks to ImpulseReactor 2022-03-14 11:56:18 -07:00
Matt Nadareski
e80034abf1 Simplify CDS code a bit 2022-03-14 11:52:49 -07:00
Matt Nadareski
27e4a6c452 Add comment to old interface 2022-03-14 11:31:57 -07:00
Matt Nadareski
914497b76f Slightly safer checks before invoking 2022-03-14 11:26:10 -07:00
Matt Nadareski
513e799aa3 Migrate protections to new interfaces 2022-03-14 11:20:11 -07:00
Matt Nadareski
fcbf006e4e Migrate packers to new interfaces 2022-03-14 11:00:17 -07:00
Matt Nadareski
bef26e0fd7 Add more helpers for NE/PE 2022-03-14 10:49:02 -07:00
Matt Nadareski
3dde84f683 Add new helpers for NE/PE specific 2022-03-14 10:45:01 -07:00
Matt Nadareski
74c6aa06e0 Add new interfaces 2022-03-14 10:43:08 -07:00
Matt Nadareski
ffb529edb3 Granularly separate out executable types 2022-03-14 10:40:44 -07:00
Matt Nadareski
d1279a471c Add NE Resident Name table structures 2022-03-14 10:01:01 -07:00
Matt Nadareski
a7f406537e Add more SecuROM checks (fixes #70) 2022-03-14 09:03:43 -07:00
Matt Nadareski
df7d5150c1 Add yet another Steam exe (fixes #92) 2022-03-14 08:54:58 -07:00
Matt Nadareski
73e4569b3b Clean up recent TAGES change 2022-03-09 14:35:38 -08:00
SilasLaspada
30c249ce74 Massively overhaul TAGES detection (#87)
* Massively overhaul TAGES detection

* Address TAGES PR comments

* Address further PR comments
2022-03-09 14:00:33 -08:00
Matt Nadareski
ec83669d7d Create Executable constructors 2022-03-08 23:03:26 -08:00
Matt Nadareski
e765fb6c0b Simplify PSX Anti-Modchip a little 2022-03-08 22:33:39 -08:00
Matt Nadareski
76465d30ec Change fileContent to sectionContent in SmartE 2022-03-08 22:30:12 -08:00
Matt Nadareski
71d3771c1d Add "check disc" to LaserLok 2022-03-07 13:44:10 -08:00
Matt Nadareski
bfd9c12163 Update nuget packages 2022-03-07 13:39:04 -08:00
Matt Nadareski
eb57065562 Aggregate paths instead of relying on breaking 2022-03-03 16:36:32 -08:00
Matt Nadareski
3875f3b8fb Fix potential off-by-one error 2022-03-02 14:58:29 -08:00
Matt Nadareski
8c2bedd21e Add test program parameters 2022-03-02 10:17:50 -08:00
Matt Nadareski
b199a6aa54 Update README 2022-03-02 09:12:59 -08:00
Matt Nadareski
1b1f64c2de Lock unknown checks behind debug flag
This also re-enables some previously commented out checks that could not be verified.
2022-03-02 08:56:26 -08:00
Matt Nadareski
7b73cc9d9b Add alternate checks for StarForce (fixes #79) 2022-02-10 11:06:35 -08:00
Matt Nadareski
d9d84a01e5 Fix crash in SolidShield scanning (fixes #76) 2022-02-10 10:37:57 -08:00
Matt Nadareski
56f009ac56 Fail slower on resource parsing (fixes #81) 2022-02-10 10:28:59 -08:00
Matt Nadareski
96daf90ae8 Update protection notes in README 2022-02-04 15:24:41 -08:00
Matt Nadareski
b581cb3124 Disable content checks for RPT/ProRing 2022-02-04 15:24:05 -08:00
Matt Nadareski
4b0e39b950 Add Steam API DLLs to detection 2022-02-04 15:19:24 -08:00
Matt Nadareski
3a1c476edc Remove StarForce directory checks for now (fixes #77) 2022-01-30 21:07:35 -08:00
Matt Nadareski
0d62d5336c Add older Uplay installer to file list 2022-01-15 11:46:38 -08:00
Matt Nadareski
cf87279dfc Add content notes to SafeLock 2021-11-24 21:59:54 -08:00
Matt Nadareski
0006f7932a Remove overly-broad CDS checks 2021-11-22 20:30:58 -08:00
Matt Nadareski
841a39c6c7 Overhaul SafeLock checks 2021-11-21 21:18:56 -08:00
Matt Nadareski
60b12f25a6 Disable SafeLock content check for now 2021-11-21 14:04:16 -08:00
SilasLaspada
f2b96b6c50 Fix InstallAnywhere reporting (#71)
* Fix InstallAnywhere reporting

* Fix formatting

* Fix formatting again
2021-11-20 23:22:10 -08:00
Matt Nadareski
d2fad1ab29 Fix Alpha-ROM... again (fixes #69) 2021-10-29 15:19:50 -07:00
Matt Nadareski
6f6755b218 Remove over-matching TAGES check 2021-10-27 23:08:16 -07:00
SilasLaspada
9a2f2e6f17 Add initial detection for InstallAnywhere (#67) 2021-10-26 10:23:08 -07:00
Matt Nadareski
d9ca550e3b Add ProRing path checks; add note (fixes #68) 2021-10-26 10:12:21 -07:00
Matt Nadareski
ec66e87ee6 Remove one note from Alpha-ROM 2021-10-21 21:33:50 -07:00
Matt Nadareski
53ce3aee74 Refine Alpha-ROM checks; add notes 2021-10-20 21:06:43 -07:00
Matt Nadareski
1ecb06f020 Bump AppVeyor version 2021-09-24 10:44:55 -07:00
Matt Nadareski
3ce4ac785e Comment out probable NE-only check 2021-09-23 15:13:57 -07:00
Matt Nadareski
1df157434d Remove debug print 2021-09-23 15:05:46 -07:00
Matt Nadareski
594f001dda Add NE check for CD-Cops; add notes 2021-09-23 15:05:30 -07:00
Matt Nadareski
c2c6bc268e Update README 2021-09-23 13:51:28 -07:00
Matt Nadareski
7aa2207edd Add PEtite detection; add notes 2021-09-23 13:43:57 -07:00
Matt Nadareski
22aa1642a6 Partial cleanup of CD/DVD-Cops; add notes 2021-09-23 13:33:48 -07:00
Matt Nadareski
844a9686af Bump version to 1.8.0 2021-09-22 11:06:34 -07:00
Matt Nadareski
8f929366b3 Merge branch 'master' of https://github.com/mnadareski/BurnOutSharp 2021-09-20 21:02:40 -07:00
Matt Nadareski
dfa0fab979 Update README 2021-09-20 21:02:14 -07:00
dependabot[bot]
415d6c587f Bump SharpCompress from 0.28.3 to 0.29.0 in /BurnOutSharp (#65)
Bumps [SharpCompress](https://github.com/adamhathcock/sharpcompress) from 0.28.3 to 0.29.0.
- [Release notes](https://github.com/adamhathcock/sharpcompress/releases)
- [Commits](https://github.com/adamhathcock/sharpcompress/compare/0.28.3...0.29)

---
updated-dependencies:
- dependency-name: SharpCompress
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-20 12:59:41 -07:00
Matt Nadareski
b1034b964e Update success/failure tracking in AppVeyor 2021-09-16 14:40:49 -07:00
Matt Nadareski
85d2382680 Only use extra checks for NE executables in Wise 2021-09-15 15:44:26 -07:00
Matt Nadareski
a6e694fe5d Convert EXE Stealth to section based; add notes 2021-09-15 14:52:11 -07:00
Matt Nadareski
a579bfea1f Fix reading generic sections 2021-09-15 11:47:12 -07:00
Matt Nadareski
ba97abed44 Convert dotFuscator to section based 2021-09-15 11:45:35 -07:00
Matt Nadareski
9fe6b101bd Convert CDSHiELD SE to section-based 2021-09-15 11:01:51 -07:00
Matt Nadareski
1345182eea Update small things about Ring PROTECH 2021-09-14 23:01:44 -07:00
Matt Nadareski
a84ac8d3cc Update CodeLock with a few things; notes 2021-09-14 22:57:17 -07:00
Matt Nadareski
1eb07c52e5 Address comments in SolidShield 2021-09-14 14:31:03 -07:00
Matt Nadareski
0d75ee135c Combine SafeCast into SafeDisc; improvements 2021-09-14 13:56:43 -07:00
Matt Nadareski
c915f29c05 Minor formatting changes 2021-09-14 13:53:30 -07:00
Matt Nadareski
38d35d1991 Convert remaining XCP full content check 2021-09-14 11:51:01 -07:00
Matt Nadareski
dbc841cb7f Clean up formatting of remaining full content checks 2021-09-14 11:33:53 -07:00
Matt Nadareski
46f53221c9 Clean up ActiveMARK 2021-09-14 00:51:44 -07:00
Matt Nadareski
708fd01d1e Clean up CD Check 2021-09-13 23:46:59 -07:00
Matt Nadareski
4aa3ba0545 Disable possibly overly-broad CD Check check 2021-09-13 23:43:24 -07:00
Matt Nadareski
57499002d2 Use beginning seek 2021-09-13 23:16:57 -07:00
Matt Nadareski
630f628598 Update UnshieldSharp to 1.6.6 2021-09-13 11:19:55 -07:00
Matt Nadareski
d66c890b71 Combine SafeDisc and Lite 2021-09-12 16:03:58 -07:00
Matt Nadareski
2b5649588a Remove errant content checks from Bitpool 2021-09-12 13:43:08 -07:00
Matt Nadareski
5425578f78 Clean up Origin 2021-09-12 13:40:29 -07:00
Matt Nadareski
8c39adcc04 Simplify EA checks, add note to Registration 2021-09-11 23:03:56 -07:00
Matt Nadareski
7773b32847 Update comment in Inno 2021-09-11 22:48:05 -07:00
Matt Nadareski
143b261a67 Fix NE reading for Inno 2021-09-11 22:40:01 -07:00
Matt Nadareski
25fc2b9b04 Last easilly-removed fileContent reliance removal 2021-09-11 22:31:06 -07:00
Matt Nadareski
d6fd0c4d2c Reduce reliance on fileContent; add notes 2021-09-11 22:27:52 -07:00
Matt Nadareski
44c44be412 Read MS-DOS stub data directly; use with CExe 2021-09-11 21:54:38 -07:00
Matt Nadareski
7b71d7b4bf Fix resource parsing, fix MS-CAB SFX 2021-09-11 21:41:17 -07:00
Matt Nadareski
2c2aee6797 Add a couple of sections to raw read with notes 2021-09-11 21:10:29 -07:00
Matt Nadareski
afdd032f73 Start using more methods to make life easier 2021-09-11 21:03:36 -07:00
Matt Nadareski
9d52ca4b4c Fix invalid reads 2021-09-11 20:58:44 -07:00
Matt Nadareski
1bc8fe7ff6 Fix version finding for MS-CAB SFX 2021-09-11 16:58:05 -07:00
Matt Nadareski
6ab7a06dd5 Lock stream when reading raw section 2021-09-11 16:54:00 -07:00
Matt Nadareski
7195ed3587 Combine CD-Cops and DVD-Cops 2021-09-11 16:49:54 -07:00
Matt Nadareski
214e8d41c7 Pre-read 3 most commonly-used section data
This also adds comprehensive notes around the sections used in various protections, how they're used, and what we can do with them. It also adds a couple of various notes based on the findings from the protection audit
2021-09-11 16:47:25 -07:00
Matt Nadareski
bd9f583659 Add sections note to PE 2021-09-11 15:22:17 -07:00
Matt Nadareski
abbf0b7ff5 Work on PE export data section 2021-09-11 15:08:58 -07:00
Matt Nadareski
f2b9e3a31b Clean up a significant number of TODOs 2021-09-11 00:32:48 -07:00
Matt Nadareski
73dd669c20 Add and use byte array extension methods 2021-09-10 22:35:32 -07:00
Matt Nadareski
32390149f3 Identify and use .rsrc item for 321 Studios 2021-09-10 22:19:24 -07:00
Matt Nadareski
9e73d8762e Clean up StarForce; add notes 2021-09-10 22:15:49 -07:00
Matt Nadareski
09854b469e Remove redundant .rsrc check in SolidShield 2021-09-10 22:09:03 -07:00
Matt Nadareski
e817063e53 Remove debug write from NSIS 2021-09-10 22:05:43 -07:00
Matt Nadareski
7cdf6a8c79 Identify and use .rsrc item for MediaMax 2021-09-10 22:02:57 -07:00
Matt Nadareski
d87087dcfb Add note to Itenium 2021-09-10 21:58:27 -07:00
Matt Nadareski
7c27fcd8a4 Identify and use .rsrc item for EA 2021-09-10 21:52:31 -07:00
Matt Nadareski
56408ed9f4 Add note and future code in Executable 2021-09-10 21:45:34 -07:00
Matt Nadareski
bf385f0bbf Identify and use .rsrc item for NSIS 2021-09-10 21:45:14 -07:00
Matt Nadareski
2a6a2930c1 Handle some TODOs 2021-09-10 21:42:42 -07:00
Matt Nadareski
9f676732a4 A little extra safety 2021-09-10 20:59:39 -07:00
Matt Nadareski
44fac8cc92 Fix reading resource table from stream 2021-09-10 16:21:55 -07:00
Matt Nadareski
e510915098 Add note about streams 2021-09-10 16:15:20 -07:00
Matt Nadareski
b779f2f546 Only deserialze a file once per round of checks 2021-09-10 16:10:15 -07:00
Matt Nadareski
5344de96b2 Cleanup and bugfixes; additional notes 2021-09-10 15:32:37 -07:00
Matt Nadareski
1e70d960ba Remove unnecessary trims 2021-09-10 13:59:35 -07:00
Matt Nadareski
e03808fbc5 Fix trailing whitespace in resource strings 2021-09-10 13:54:12 -07:00
Matt Nadareski
373268a6a8 Convert resource checks to header checks 2021-09-10 13:51:32 -07:00
Matt Nadareski
905d440367 Process file info resources; cleanup; refactors 2021-09-10 02:58:59 -07:00
Matt Nadareski
5628cf8d73 Add Wix to the solution 2021-09-09 18:51:04 -07:00
Matt Nadareski
4aaea417f0 Make generic resource finding methods 2021-09-09 18:45:50 -07:00
Matt Nadareski
892886b730 Ensure CodePage package is installed 2021-09-09 16:32:24 -07:00
Matt Nadareski
1028050464 Use resource section to find assembly manifest 2021-09-09 16:29:17 -07:00
Matt Nadareski
af79b00bd6 Finalize resource reading 2021-09-09 16:05:17 -07:00
Matt Nadareski
dc9a581e1c Fix resource entry checking 2021-09-09 15:10:22 -07:00
Matt Nadareski
4d800fd644 Fix ResourceDirectoryString reading 2021-09-09 11:25:02 -07:00
Matt Nadareski
126e8827de Move WixToolset to separate folder now that it supports .NET Standard 2021-09-09 10:51:18 -07:00
Matt Nadareski
23c79d4452 Update WixToolset version 2021-09-09 10:44:05 -07:00
Matt Nadareski
173fc69a08 Update UnshieldSharp to 1.6.5 2021-09-09 10:37:51 -07:00
Matt Nadareski
0411278f1d Remove unused and outdated classes 2021-09-08 10:33:28 -07:00
Matt Nadareski
bb1f9bdcdc Remove search result 2021-09-08 10:28:50 -07:00
Matt Nadareski
9d5ab935de Add .txt2 check to SafeDisc 2021-09-08 10:28:35 -07:00
Matt Nadareski
1df9d145e4 Add another note to IContentCheck 2021-09-08 10:22:28 -07:00
Matt Nadareski
fba30949bd Fix one ActiveMARK check; add note 2021-09-08 10:14:02 -07:00
Matt Nadareski
198c320ad8 Convert XCP to section based; add note 2021-09-08 09:58:11 -07:00
Matt Nadareski
e798ba1104 Convert WTM to section based 2021-09-08 00:51:25 -07:00
Matt Nadareski
f8f02a54f6 Combine VOB into ProtectDISC; add notes
This also means that EVORE is no longer relevant to the code and has been fully removed.
2021-09-07 23:53:05 -07:00
Matt Nadareski
da01668cbe Convert 321Studios Activation to section based 2021-09-07 21:08:25 -07:00
Matt Nadareski
95770c63af Convert 3PLock to section based 2021-09-07 21:02:52 -07:00
Matt Nadareski
af6e5d7441 Partially convert TAGES to section based; add notes 2021-09-07 21:02:19 -07:00
Matt Nadareski
ae5bdcc97a Convert Sisiphus to section based 2021-09-06 13:58:16 -07:00
Matt Nadareski
0fc415fb34 Convert SVKP to header based; add note 2021-09-05 23:31:10 -07:00
Matt Nadareski
0fe30392d8 Add note to Steam 2021-09-05 23:29:48 -07:00
Matt Nadareski
77fc11289c Convert StarForce to section-based; add notes 2021-09-05 23:22:48 -07:00
Matt Nadareski
9d3969d4ce Remove debug output 2021-09-05 23:08:41 -07:00
Matt Nadareski
2ba2756a8f Partially convert SolidShield to section based; add notes 2021-09-05 23:02:55 -07:00
Matt Nadareski
53088b4e60 Convert SmartE to section based 2021-09-03 13:26:52 -07:00
Matt Nadareski
0dc83739e7 Add v8 white label notes to SecuROM 2021-09-03 11:16:15 -07:00
Matt Nadareski
e8a205b221 Convert SecuROM to section based; add notes 2021-09-02 22:32:06 -07:00
Matt Nadareski
02c3d3fb4a Add note to SafeLock 2021-09-02 16:09:29 -07:00
Matt Nadareski
2d3d66f077 Convert SafeDisc to section based; add notes 2021-09-02 15:22:33 -07:00
Matt Nadareski
a5f21adeee Add content matches to SafeCast; add notes 2021-09-02 09:30:37 -07:00
Matt Nadareski
cbb4cdddfa Add note to Ring PROTECH 2021-09-02 00:54:36 -07:00
Matt Nadareski
e6b898882d Add notes to PSX Anti-modchip 2021-09-01 23:12:16 -07:00
Matt Nadareski
3bd7f5c890 Convert ProtectDisc to section based 2021-09-01 23:09:01 -07:00
Matt Nadareski
39c20fd0cd Wrap file scanning in try/catch for more safety 2021-09-01 22:22:14 -07:00
Matt Nadareski
21117e81a3 Fix EVORE IsPEExecutable check 2021-09-01 16:10:06 -07:00
Matt Nadareski
df172b49db Add note to Origin 2021-09-01 14:15:38 -07:00
Matt Nadareski
1ae0f694de Convert EReg to fvinfo and section based; add note 2021-09-01 14:10:12 -07:00
Matt Nadareski
040aa8daf6 Convert MediaMax CD-3 to section based 2021-09-01 14:06:19 -07:00
Matt Nadareski
3b9aa2d45c Convert LaserLok to section based; add notes 2021-09-01 13:46:08 -07:00
Matt Nadareski
8705cac648 Convert ImpulseReactor to section based; add notes 2021-09-01 10:27:16 -07:00
Matt Nadareski
5a4e3caea8 Add note to Key-Lock 2021-08-31 22:57:28 -07:00
Matt Nadareski
593d4a35b7 Convert JoWood to section based; add notes 2021-08-31 22:56:57 -07:00
SilasLaspada
801eef5f37 Improve Steam detection (#62) 2021-08-31 22:22:47 -07:00
Matt Nadareski
a0ac0ea189 Convert Itenium to section based 2021-08-31 21:15:56 -07:00
Matt Nadareski
f249455b00 Convert GFWL to fvinfo and section based; add note 2021-08-31 20:53:17 -07:00
Matt Nadareski
8dbb8d9fe1 Disable Valve scanning until further notice 2021-08-31 20:33:32 -07:00
Matt Nadareski
ed698e05d8 Partially convert EA to section based; add notes 2021-08-30 15:08:14 -07:00
Matt Nadareski
47b189bf87 Improve CD-Key matching 2021-08-30 14:24:16 -07:00
Matt Nadareski
460eb78ecd Improve Setup Factory matching 2021-08-30 14:18:15 -07:00
Matt Nadareski
ffcaf4d16b Improve MS-CAB SFX matching 2021-08-30 12:08:17 -07:00
Matt Nadareski
64de357257 Remove debug from IIF again 2021-08-30 12:06:29 -07:00
Matt Nadareski
cc3f6622b4 Improve IIF matching 2021-08-30 11:47:49 -07:00
Matt Nadareski
f0b66d4bfb Improve NSIS matching 2021-08-30 11:40:14 -07:00
Matt Nadareski
9c32f663b0 Add notes to DVD-Cops 2021-08-30 10:02:40 -07:00
Matt Nadareski
e0e22d91e1 Add notes to CopyKiller 2021-08-30 10:00:18 -07:00
Matt Nadareski
dbc72cb4c2 Fix typo in Wise Installer 2021-08-29 22:39:34 -07:00
Matt Nadareski
17d6c6aa6b Have exception dump all info 2021-08-29 22:39:04 -07:00
Matt Nadareski
7be5916041 Partially convert CodeLock to section based; add note 2021-08-29 22:26:58 -07:00
Matt Nadareski
2d8a25178e Fix Cenega naming 2021-08-29 22:20:25 -07:00
Matt Nadareski
5195025849 Remove leftover debug in CD Check 2021-08-29 22:14:46 -07:00
Matt Nadareski
c3c2fc6171 Convert Cenga to section based; add note 2021-08-29 21:51:43 -07:00
Matt Nadareski
6fa5e9a67f Add note to CDSHiELDSE 2021-08-29 21:49:56 -07:00
Matt Nadareski
834018b325 Convert CD-Lock to section based 2021-08-29 21:49:14 -07:00
Matt Nadareski
027388f587 Add fvinfo to CDKey; add note 2021-08-29 21:40:25 -07:00
Matt Nadareski
6452d39de1 Partially convert CD-Cops to section based; add note 2021-08-29 21:38:19 -07:00
Matt Nadareski
6d78e2fff7 Partially convert CD Check to section based; add notes 2021-08-29 21:13:50 -07:00
Matt Nadareski
56ae245305 Partially convert CDS to section based; add note 2021-08-29 21:07:26 -07:00
Matt Nadareski
76b16ca6d4 Add note to Bitpool 2021-08-29 20:58:10 -07:00
Matt Nadareski
d0a174d71c Add note to AlphaROM 2021-08-29 20:56:48 -07:00
Matt Nadareski
8e62f12f61 Add note to ActiveMARK 2021-08-29 20:55:36 -07:00
Matt Nadareski
621bcdf380 Convert Wise to section based; add note 2021-08-29 20:52:00 -07:00
Matt Nadareski
1b54dd92ab Convert WZ-SFX to section and header based 2021-08-29 11:43:43 -07:00
Matt Nadareski
2b0a43ca3e Disable possibility of ReadLine in Valve check 2021-08-29 11:31:17 -07:00
Matt Nadareski
81ce49c219 Fix manifest description finding 2021-08-29 11:15:37 -07:00
Matt Nadareski
b287c7236b Fix NE header deserialization 2021-08-28 15:55:08 -07:00
Matt Nadareski
b63d4a3da0 Update EVORE 2021-08-28 00:13:19 -07:00
Matt Nadareski
e652e43cba Add more NE structures 2021-08-27 23:29:34 -07:00
Matt Nadareski
e6b2be1738 Formalize New Executable classes; renames 2021-08-27 22:34:57 -07:00
Matt Nadareski
d2606e21fe Convert WinRAR SFX to section based 2021-08-27 21:58:05 -07:00
Matt Nadareski
22235cbe84 Add Setup Factory version info checks; add notes 2021-08-27 21:49:14 -07:00
Matt Nadareski
6bd5fae1cd Add TODO on IContentCheck 2021-08-27 21:42:05 -07:00
Matt Nadareski
ebb20bbe5e Fix overmatching on JoWooDX; add note 2021-08-27 21:37:46 -07:00
Matt Nadareski
82d7395b79 Make PE parsing attempts safer 2021-08-27 21:32:12 -07:00
Matt Nadareski
451cb04714 Reduce StarForce over-matching check 2021-08-27 21:12:09 -07:00
Matt Nadareski
15e5feafef Add helper methods to PE class for later 2021-08-27 14:30:03 -07:00
Matt Nadareski
4d19bd27f0 Make MachineType enum values consistent 2021-08-27 14:29:38 -07:00
Matt Nadareski
2400f2d0ad Convert PEC to section based; add notes 2021-08-27 14:28:17 -07:00
Matt Nadareski
ee0193eb71 Clean up some usings, add note to NSIS 2021-08-27 13:30:24 -07:00
Matt Nadareski
eb76acb767 Add note to MS-CAB SFX 2021-08-27 13:13:41 -07:00
Matt Nadareski
6c77cccf53 Clarify and comment out in IIF 2021-08-27 12:03:00 -07:00
Matt Nadareski
b4ab969f88 Reorganize and create Resource-related things 2021-08-27 10:38:42 -07:00
Matt Nadareski
2de4f3f808 Continue exe organization, start IIF migration 2021-08-27 09:42:05 -07:00
Matt Nadareski
4b5d0980f7 Convert Installer VISE to section based 2021-08-26 23:18:55 -07:00
Matt Nadareski
2bdbad1ba6 Convert Inno Setup to section based 2021-08-26 23:07:04 -07:00
Matt Nadareski
3b634877d0 Add note to EXE Stealth 2021-08-26 22:22:15 -07:00
Matt Nadareski
2996bbb18f Add note to dotFuscator 2021-08-26 22:13:14 -07:00
Matt Nadareski
c4ca27608b Convert Advanced Installer to section based 2021-08-26 21:57:56 -07:00
Matt Nadareski
5a85ff2ad3 Clean up Armadillo, fix edge case 2021-08-26 21:47:44 -07:00
Matt Nadareski
a27b3cc43f Add old version UPX detection 2021-08-26 20:43:58 -07:00
Matt Nadareski
ea8f557097 Start converting Armadillo checks 2021-08-26 20:38:01 -07:00
Matt Nadareski
7bbed5985b A little EVORE cleanup 2021-08-26 16:05:38 -07:00
Matt Nadareski
0ec6dfb287 Use UPX as a guinea pig for new exe handling 2021-08-26 15:50:38 -07:00
Matt Nadareski
3b753c137b Fill out and fix way more executable stuff 2021-08-26 15:48:56 -07:00
Matt Nadareski
6cde7b8bef Reduce redundant code in content matchers now 2021-08-25 20:26:43 -07:00
Matt Nadareski
d26a89b8ab Add time elapsed to debug output 2021-08-25 20:25:45 -07:00
Matt Nadareski
3ab0bcc0ae ContentMatchSets are now expected in IContentCheck 2021-08-25 19:37:32 -07:00
Matt Nadareski
7548646ba2 Create and use the Tools namespace 2021-08-25 15:09:42 -07:00
Matt Nadareski
0b75c6f046 What I like about EVORE... 2021-08-25 14:23:11 -07:00
SilasLaspada
958d306f42 Fix NullReferenceExceptions (#59) 2021-08-24 23:13:27 -07:00
Matt Nadareski
742b25e4dd Split manifest reading into helper methods 2021-08-24 15:28:23 -07:00
Matt Nadareski
43845cf722 Rename position flag -> debug flag 2021-08-24 15:19:23 -07:00
Matt Nadareski
a2a0e5c2ee Clean up TODOs in IContentCheck 2021-08-24 15:19:10 -07:00
Matt Nadareski
93e8322ba5 Add skeleton code to MS-CAB SFX 2021-08-24 14:29:30 -07:00
Matt Nadareski
8a07c9cf4e Add byte array checks for IIF 2021-08-24 09:26:27 -07:00
Matt Nadareski
6049eda580 Add byte array checks for MS-CAB SFX 2021-08-24 09:13:58 -07:00
Matt Nadareski
177641894e Clean up MS-CAB SFX a little 2021-08-23 23:09:05 -07:00
Matt Nadareski
dc49335ace Add notes for later 2021-08-23 23:04:01 -07:00
SilasLaspada
3dcce8a8ac Add support for Intel Installation Framework detection (#57)
* Add support for Intel Installation Framework detection

* Address reviews
2021-08-23 22:56:31 -07:00
Matt Nadareski
04651d46d8 Clean up usings 2021-08-23 22:07:24 -07:00
Matt Nadareski
56aeded8eb String and EVORE cleanups 2021-08-23 22:05:18 -07:00
SilasLaspada
97c9c7e5ed Add support for Microsoft SFX CAB detection (#56)
* Add support for Microsoft SFX CAB detection

* Address reviews

* Simplify GetVersion

* Fix GetVersion
2021-08-23 22:03:28 -07:00
Matt Nadareski
a891391879 Merge branch 'master' of https://github.com/mnadareski/BurnOutSharp 2021-08-23 20:58:24 -07:00
Matt Nadareski
5aae9b01d4 Make file version finding safer 2021-08-23 20:45:13 -07:00
SilasLaspada
b74a370b11 Fix WTM false positive (#55) 2021-08-16 21:58:36 -07:00
Matt Nadareski
5e560661d4 Add extra try/catch around Valve archives 2021-07-31 21:41:06 -07:00
Matt Nadareski
93e450c2bf Update README for IS-Z 2021-07-21 14:21:39 -07:00
Matt Nadareski
cc762754c5 Add support of IS-Z archives 2021-07-21 13:40:32 -07:00
Matt Nadareski
7065436033 Update nuget packages 2021-07-21 13:33:52 -07:00
Matt Nadareski
debe091502 Update protection list 2021-07-19 23:02:04 -07:00
Matt Nadareski
80905b56cd Better attempt at narrowing down 2021-07-19 21:56:31 -07:00
Matt Nadareski
0a7cd8a69e Comment out broader UPX (NOS) check 2021-07-19 21:38:19 -07:00
Matt Nadareski
c3957977a2 Reorder StarForce 3-5 checks for accuracy 2021-07-18 21:56:15 -07:00
Matt Nadareski
ff602c77ed Improve GFWL support
Adds support for the previously-undetected Games for Windows LIVE - Zero Day Piracy Protection Module as well as adding a generic check for any other modules
2021-07-18 21:50:58 -07:00
Matt Nadareski
3667a5b57a Concurrent protection scans per file (#52)
* Move to ConcurrentDictionary

* Convert to ConcurrentQueue
2021-07-18 09:44:23 -07:00
Matt Nadareski
3ac57b1c0c Fix static matcher issues (fixes #51)
Note: This may result in slower, but more accurate, scans
2021-07-17 23:40:16 -07:00
Matt Nadareski
957d82b2f7 Add new SecuROM PA detection 2021-07-17 23:06:11 -07:00
Matt Nadareski
6d0817ad15 Path protections separator-agnostic (fixes #47) 2021-07-17 22:31:29 -07:00
Matt Nadareski
5b10e6d614 Add check note for Tivola 2021-07-17 21:54:47 -07:00
Matt Nadareski
2d39b8c532 Add more GFWL checks 2021-07-17 21:45:37 -07:00
Matt Nadareski
2ae860e8ca Add Tivola Ring Protection detection (fixes #45) 2021-07-17 21:17:45 -07:00
Matt Nadareski
9e21c28e52 Temporary fix for StarForce directory scan 2021-07-17 21:11:38 -07:00
Matt Nadareski
2f5053b49f Make StarForce checks AND not OR (fixes #46) 2021-07-17 17:08:15 -07:00
Matt Nadareski
7024136919 Make large file parsing safer (fixes #44) 2021-07-15 09:57:06 -07:00
SilasLaspada
c74b5b3d29 Improve Bitpool detection (#43)
* Improve Bitpool detection

* Address comments
2021-07-02 10:16:06 -07:00
SilasLaspada
9c3201aa4b Improve XCP detection to prevent false positives (#42)
* Improve XCP detection to prevent false positives

* Address comments
2021-07-01 20:51:40 -07:00
SilasLaspada
dfd1141635 Vastly improve WTM detection (#41)
* Fix false positive in WTM detection

* Forgot to improve part of the detection

* Vastly improve detection
2021-06-30 09:36:02 -07:00
SilasLaspada
1188cad5e6 Slightly improve PE Compact version detection (#40)
* Slightly improve PE Compact version detection

* Address comments

* Address comments
2021-06-24 11:58:38 -07:00
SilasLaspada
65fa2f8481 Greatly improve WinZip SFX version detection (#39) 2021-06-21 21:48:25 -07:00
SilasLaspada
475e0b9d91 Add support for detecting Installer VISE (#38)
* Add support for detecting Installer VISE

* Add comment about extraction
2021-06-05 15:08:10 -07:00
SilasLaspada
b76d09aa20 Improve Inno Setup detection (#37)
* Improve Inno Setup detection

* Split "GetVersion"

* Remove unneeded check

* Make version detection more robust

* Add Unicode version detection

* Address review comments
2021-06-05 11:46:04 -07:00
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
355 changed files with 21094 additions and 13167 deletions

43
.github/workflows/build_nupkg.yml vendored Normal file
View File

@@ -0,0 +1,43 @@
name: Nuget Pack
on:
push:
branches: [ "master" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Restore dependencies
run: dotnet restore
- name: Pack
run: dotnet pack
- name: Upload build
uses: actions/upload-artifact@v4
with:
name: 'Nuget Package'
path: 'BinaryObjectScanner/bin/Release/*.nupkg'
- name: Upload to rolling
uses: ncipollo/release-action@v1.14.0
with:
allowUpdates: True
artifacts: 'BinaryObjectScanner/bin/Release/*.nupkg'
body: 'Last built commit: ${{ github.sha }}'
name: 'Rolling Release'
prerelease: True
replacesArtifacts: True
tag: "rolling"
updateOnlyUnreleased: True

55
.github/workflows/build_programs.yml vendored Normal file
View File

@@ -0,0 +1,55 @@
name: Build Programs
on:
push:
branches: [ "master" ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
project: [ExtractionTool, ProtectionScan]
runtime: [win-x86, win-x64, win-arm64, linux-x64, linux-arm64, osx-x64]
framework: [net9.0] #[net20, net35, net40, net452, net472, net48, netcoreapp3.1, net5.0, net6.0, net7.0, net8.0, net9.0]
conf: [Debug] #[Release, Debug]
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet publish ${{ matrix.project }}/${{ matrix.project }}.csproj -f ${{ matrix.framework }} -r ${{ matrix.runtime }} -c ${{ matrix.conf == 'Release' && 'Release -p:DebugType=None -p:DebugSymbols=false' || 'Debug'}} --self-contained true --version-suffix ${{ github.sha }} ${{ (startsWith(matrix.framework, 'net5') || startsWith(matrix.framework, 'net6') || startsWith(matrix.framework, 'net7') || startsWith(matrix.framework, 'net8') || startsWith(matrix.framework, 'net9')) && '-p:PublishSingleFile=true' || ''}}
- name: Archive build
run: |
cd ${{ matrix.project }}/bin/Debug/${{ matrix.framework }}/${{ matrix.runtime }}/publish/
zip -r ${{ github.workspace }}/${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_${{ matrix.conf }}.zip ./
- name: Upload build
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_${{ matrix.conf }}
path: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_${{ matrix.conf }}.zip
- name: Upload to rolling
uses: ncipollo/release-action@v1.14.0
with:
allowUpdates: True
artifacts: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_${{ matrix.conf }}.zip
body: 'Last built commit: ${{ github.sha }}'
name: 'Rolling Release'
prerelease: True
replacesArtifacts: True
tag: "rolling"
updateOnlyUnreleased: True

17
.github/workflows/check_pr.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
name: Build PR
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Build
run: dotnet build

22
.gitmodules vendored
View File

@@ -1,15 +1,9 @@
[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
[submodule "BinaryObjectScanner/_EXTERNAL/stormlibsharp"]
path = BinaryObjectScanner/_EXTERNAL/stormlibsharp
url = https://github.com/robpaveza/stormlibsharp.git
[submodule "BurnOutSharp/External/WixToolset"]
path = BurnOutSharp/External/WixToolset
url = https://github.com/wixtoolset/Dtf.git
[submodule "BinaryObjectScanner/_EXTERNAL/libmspack4n"]
path = BinaryObjectScanner/_EXTERNAL/libmspack4n
url = https://github.com/activescott/libmspack4n.git
[submodule "BinaryObjectScanner/_EXTERNAL/LessIO"]
path = BinaryObjectScanner/_EXTERNAL/LessIO
url = https://github.com/activescott/LessIO.git

19
.vscode/launch.json vendored
View File

@@ -5,14 +5,27 @@
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"name": ".NET Core Launch (ProtectionScan)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/Test/bin/Debug/netcoreapp3.1/Test.dll",
"program": "${workspaceFolder}/ProtectionScan/bin/Debug/net9.0/ProtectionScan.dll",
"args": [],
"cwd": "${workspaceFolder}/Test",
"cwd": "${workspaceFolder}/ProtectionScan",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": ".NET Core Launch (ExtractionTool)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/ExtractionTool/bin/Debug/net9.0/ExtractionTool.dll",
"args": [],
"cwd": "${workspaceFolder}/ExtractionTool",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"dotnet.defaultSolution": "BinaryObjectScanner.sln"
}

6
.vscode/tasks.json vendored
View File

@@ -7,7 +7,7 @@
"type": "process",
"args": [
"build",
"${workspaceFolder}/Test/Test.csproj",
"${workspaceFolder}/BinaryObjectScanner.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
@@ -19,7 +19,7 @@
"type": "process",
"args": [
"publish",
"${workspaceFolder}/Test/Test.csproj",
"${workspaceFolder}/BinaryObjectScanner.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
@@ -32,7 +32,7 @@
"args": [
"watch",
"run",
"${workspaceFolder}/Test/Test.csproj",
"${workspaceFolder}/BinaryObjectScanner.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],

48
BinaryObjectScanner.sln Normal file
View File

@@ -0,0 +1,48 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32407.343
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{68D10531-99CB-40B1-8912-73FA286C9433}"
ProjectSection(SolutionItems) = preProject
appveyor.yml = appveyor.yml
Coding Guide.md = Coding Guide.md
Developer Guide.md = Developer Guide.md
LICENSE = LICENSE
publish-nix.sh = publish-nix.sh
publish-win.ps1 = publish-win.ps1
README.md = README.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BinaryObjectScanner", "BinaryObjectScanner\BinaryObjectScanner.csproj", "{341EA3F5-847C-4739-B86F-2B051FFE4EF2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtectionScan", "ProtectionScan\ProtectionScan.csproj", "{14CC56E0-7D56-497C-BF3D-4C06FA169831}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtractionTool", "ExtractionTool\ExtractionTool.csproj", "{89767A19-043F-4251-805B-B2CBC48E2B79}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{341EA3F5-847C-4739-B86F-2B051FFE4EF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{341EA3F5-847C-4739-B86F-2B051FFE4EF2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{341EA3F5-847C-4739-B86F-2B051FFE4EF2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{341EA3F5-847C-4739-B86F-2B051FFE4EF2}.Release|Any CPU.Build.0 = Release|Any CPU
{14CC56E0-7D56-497C-BF3D-4C06FA169831}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{14CC56E0-7D56-497C-BF3D-4C06FA169831}.Debug|Any CPU.Build.0 = Debug|Any CPU
{14CC56E0-7D56-497C-BF3D-4C06FA169831}.Release|Any CPU.ActiveCfg = Release|Any CPU
{14CC56E0-7D56-497C-BF3D-4C06FA169831}.Release|Any CPU.Build.0 = Release|Any CPU
{89767A19-043F-4251-805B-B2CBC48E2B79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{89767A19-043F-4251-805B-B2CBC48E2B79}.Debug|Any CPU.Build.0 = Debug|Any CPU
{89767A19-043F-4251-805B-B2CBC48E2B79}.Release|Any CPU.ActiveCfg = Release|Any CPU
{89767A19-043F-4251-805B-B2CBC48E2B79}.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,101 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Assembly Properties -->
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<LangVersion>latest</LangVersion>
<NoWarn>CS0162;CS0612</NoWarn>
<Nullable>enable</Nullable>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>3.2.1</Version>
<!-- Mostly added due to external libraries -->
<WarningsNotAsErrors>CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8618;CS8625;CS8634;CS8765;IL3000;NU5100</WarningsNotAsErrors>
<!-- Package Properties -->
<Authors>Matt Nadareski</Authors>
<Description>Protection scanning library</Description>
<Copyright>Copyright (c)2018-2024 Matt Nadareski</Copyright>
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
<RepositoryUrl>https://github.com/SabreTools/BinaryObjectScanner</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>protection copy-protection scanning packer</PackageTags>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>
<!-- Set a build flag for Windows specifically -->
<PropertyGroup Condition="'$(RuntimeIdentifier)'=='win-x86'">
<DefineConstants>$(DefineConstants);WIN</DefineConstants>
</PropertyGroup>
<!-- Exclude certain parts of external modules for by default -->
<PropertyGroup>
<DefaultItemExcludes>
$(DefaultItemExcludes);
**\AssemblyInfo.cs;
_EXTERNAL\LessIO\src\LessIO.Tests\**;
_EXTERNAL\libmspack4n\lib\**;
_EXTERNAL\libmspack4n\libmspack4ntest\**;
_EXTERNAL\stormlibsharp\lib\**;
_EXTERNAL\stormlibsharp\src\TestConsole\**
</DefaultItemExcludes>
</PropertyGroup>
<!-- Exclude all StormLibSharp for .NET Framework 4.0 -->
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net40`))">
<DefaultItemExcludes>
$(DefaultItemExcludes);
_EXTERNAL\stormlibsharp\src\**
</DefaultItemExcludes>
</PropertyGroup>
<!-- Exclude all external modules for .NET Framework 2.0, .NET Framework 3.5, or non-Windows
builds -->
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR !$(RuntimeIdentifier.StartsWith(`win-x86`))">
<DefaultItemExcludes>
$(DefaultItemExcludes);
_EXTERNAL\**
</DefaultItemExcludes>
</PropertyGroup>
<!-- These are needed for dealing with native Windows DLLs -->
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND $(RuntimeIdentifier.StartsWith(`win-x86`))">
<Content Include="*.dll">
<Pack>true</Pack>
<PackagePath>contentFiles;content</PackagePath>
<IncludeInPackage>true</IncludeInPackage>
<CopyToOutput>true</CopyToOutput>
<BuildAction>Content</BuildAction>
<copyToOutput>true</copyToOutput>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
</Content>
</ItemGroup>
<!-- Support for old .NET versions -->
<ItemGroup Condition="$(TargetFramework.StartsWith(`net2`))">
<PackageReference Include="Net30.LinqBridge" Version="1.3.0" />
</ItemGroup>
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`))">
<PackageReference Include="OpenMcdf" Version="2.3.1" />
</ItemGroup>
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))">
<PackageReference Include="SharpCompress" Version="0.38.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SabreTools.Compression" Version="0.6.1" />
<PackageReference Include="SabreTools.Hashing" Version="1.4.0" />
<PackageReference Include="SabreTools.IO" Version="1.5.1" />
<PackageReference Include="SabreTools.Matching" Version="1.4.1" />
<PackageReference Include="SabreTools.Models" Version="1.5.1" />
<PackageReference Include="SabreTools.Serialization" Version="1.7.5" />
<PackageReference Include="UnshieldSharp" Version="1.9.1" />
<PackageReference Include="WiseUnpacker" Version="1.5.1" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,26 @@
namespace BinaryObjectScanner
{
/// <summary>
/// Represents a mapping from checker to detected protection
/// </summary>
#if NET20 || NET35
public class CheckDictionary<T> : System.Collections.Generic.Dictionary<T, string> where T : notnull
#else
public class CheckDictionary<T> : System.Collections.Concurrent.ConcurrentDictionary<T, string> where T : notnull
#endif
{
/// <inheritdoc cref="System.Collections.Generic.Dictionary{TKey, TValue}.Add(TKey, TValue)"/>
/// <remarks>Handles the proper Add implementation</remarks>
public void Append(T key, string? value)
{
if (value == null)
return;
#if NET20 || NET35
this[key] = value;
#else
TryAdd(key, value);
#endif
}
}
}

View File

@@ -0,0 +1,181 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Data
{
internal static class StaticChecks
{
#region Public Collections
/// <summary>
/// Cache for all IContentCheck types
/// </summary>
public static List<IContentCheck> ContentCheckClasses
{
get
{
contentCheckClasses ??= InitCheckClasses<IContentCheck>();
return contentCheckClasses ?? [];
}
}
/// <summary>
/// Cache for all IExecutableCheck<LinearExecutable> types
/// </summary>
public static List<IExecutableCheck<LinearExecutable>> LinearExecutableCheckClasses
{
get
{
linearExecutableCheckClasses ??= InitCheckClasses<IExecutableCheck<LinearExecutable>>();
return linearExecutableCheckClasses ?? [];
}
}
/// <summary>
/// Cache for all IExecutableCheck<MSDOS> types
/// </summary>
public static List<IExecutableCheck<MSDOS>> MSDOSExecutableCheckClasses
{
get
{
msdosExecutableCheckClasses ??= InitCheckClasses<IExecutableCheck<MSDOS>>();
return msdosExecutableCheckClasses ?? [];
}
}
/// <summary>
/// Cache for all IExecutableCheck<NewExecutable> types
/// </summary>
public static List<IExecutableCheck<NewExecutable>> NewExecutableCheckClasses
{
get
{
newExecutableCheckClasses ??= InitCheckClasses<IExecutableCheck<NewExecutable>>();
return newExecutableCheckClasses ?? [];
}
}
/// <summary>
/// Cache for all IPathCheck types
/// </summary>
public static List<IPathCheck> PathCheckClasses
{
get
{
pathCheckClasses ??= InitCheckClasses<IPathCheck>();
return pathCheckClasses ?? [];
}
}
/// <summary>
/// Cache for all IExecutableCheck<PortableExecutable> types
/// </summary>
public static List<IExecutableCheck<PortableExecutable>> PortableExecutableCheckClasses
{
get
{
portableExecutableCheckClasses ??= InitCheckClasses<IExecutableCheck<PortableExecutable>>();
return portableExecutableCheckClasses ?? [];
}
}
#endregion
#region Internal Instances
/// <summary>
/// Cache for all IContentCheck types
/// </summary>
private static List<IContentCheck>? contentCheckClasses;
/// <summary>
/// Cache for all IExecutableCheck<LinearExecutable> types
/// </summary>
private static List<IExecutableCheck<LinearExecutable>>? linearExecutableCheckClasses;
/// <summary>
/// Cache for all IExecutableCheck<MSDOS> types
/// </summary>
private static List<IExecutableCheck<MSDOS>>? msdosExecutableCheckClasses;
/// <summary>
/// Cache for all IExecutableCheck<NewExecutable> types
/// </summary>
private static List<IExecutableCheck<NewExecutable>>? newExecutableCheckClasses;
/// <summary>
/// Cache for all IPathCheck types
/// </summary>
private static List<IPathCheck>? pathCheckClasses;
/// <summary>
/// Cache for all IExecutableCheck<PortableExecutable> types
/// </summary>
private static List<IExecutableCheck<PortableExecutable>>? portableExecutableCheckClasses;
#endregion
/// <summary>
/// Initialize all implementations of a type
/// </summary>
private static List<T>? InitCheckClasses<T>() =>
InitCheckClasses<T>(Assembly.GetExecutingAssembly()) ?? [];
/// <summary>
/// Initialize all implementations of a type
/// </summary>
private static List<T>? InitCheckClasses<T>(Assembly assembly)
{
List<T> classTypes = [];
// If not all types can be loaded, use the ones that could be
Type?[] assemblyTypes = [];
try
{
assemblyTypes = assembly.GetTypes();
}
catch (ReflectionTypeLoadException rtle)
{
assemblyTypes = [.. rtle.Types];
}
// Get information from the type param
string interfaceName = typeof(T)!.FullName!;
// Loop through all types
foreach (Type? type in assemblyTypes)
{
// Skip invalid types
if (type == null)
continue;
// If the type isn't a class
if (!type.IsClass)
continue;
// If the type isn't a class or doesn't implement the interface
bool interfaceFound = false;
foreach (var ii in type.GetInterfaces())
{
if (ii.FullName != interfaceName)
continue;
interfaceFound = true;
break;
}
if (!interfaceFound)
continue;
// Try to create a concrete instance of the type
var instance = (T?)Activator.CreateInstance(type);
if (instance != null)
classTypes.Add(instance);
}
return classTypes;
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
namespace BinaryObjectScanner
{
internal static class EnumerableExtensions
{
/// <summary>
/// Wrap iterating through an enumerable with an action
/// </summary>
/// <remarks>
/// .NET Frameworks 2.0 and 3.5 process in series.
/// .NET Frameworks 4.0 onward process in parallel.
/// </remarks>
public static void IterateWithAction<T>(this IEnumerable<T> source, Action<T> action)
{
#if NET20 || NET35
foreach (var item in source)
{
action(item);
}
#else
System.Threading.Tasks.Parallel.ForEach(source, action);
#endif
}
}
}

View File

@@ -0,0 +1,72 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner
{
public static class Factory
{
/// <summary>
/// Create an instance of a detectable based on file type
/// </summary>
public static IDetectable? CreateDetectable(WrapperType fileType)
{
return fileType switch
{
WrapperType.AACSMediaKeyBlock => new FileType.AACSMediaKeyBlock(),
WrapperType.BDPlusSVM => new FileType.BDPlusSVM(),
//WrapperType.CIA => new FileType.CIA(),
WrapperType.Executable => new FileType.Executable(),
WrapperType.LDSCRYPT => new FileType.LDSCRYPT(),
//WrapperType.N3DS => new FileType.N3DS(),
//WrapperType.Nitro => new FileType.Nitro(),
WrapperType.PlayJAudioFile => new FileType.PLJ(),
WrapperType.RealArcadeInstaller => new FileType.RealArcadeInstaller(),
WrapperType.RealArcadeMezzanine => new FileType.RealArcadeMezzanine(),
WrapperType.SFFS => new FileType.SFFS(),
WrapperType.Textfile => new FileType.Textfile(),
_ => null,
};
}
/// <summary>
/// Create an instance of an extractable based on file type
/// </summary>
public static IExtractable? CreateExtractable(WrapperType fileType)
{
return fileType switch
{
WrapperType.BFPK => new FileType.BFPK(),
WrapperType.BSP => new FileType.BSP(),
WrapperType.BZip2 => new FileType.BZip2(),
WrapperType.CFB => new FileType.CFB(),
//WrapperType.CIA => new FileType.CIA(),
WrapperType.GCF => new FileType.GCF(),
WrapperType.GZIP => new FileType.GZIP(),
WrapperType.InstallShieldArchiveV3 => new FileType.InstallShieldArchiveV3(),
WrapperType.InstallShieldCAB => new FileType.InstallShieldCAB(),
WrapperType.MicrosoftCAB => new FileType.MicrosoftCAB(),
WrapperType.MicrosoftLZ => new FileType.MicrosoftLZ(),
WrapperType.MoPaQ => new FileType.MPQ(),
//WrapperType.N3DS => new FileType.N3DS(),
//WrapperType.NCF => new FileType.NCF(),
//WrapperType.Nitro => new FileType.Nitro(),
WrapperType.PAK => new FileType.PAK(),
WrapperType.PFF => new FileType.PFF(),
WrapperType.PKZIP => new FileType.PKZIP(),
//WrapperType.PlayJAudioFile => new FileType.PLJ(),
//WrapperType.Quantum => new FileType.Quantum(),
WrapperType.RAR => new FileType.RAR(),
WrapperType.SevenZip => new FileType.SevenZip(),
WrapperType.SFFS => new FileType.SFFS(),
WrapperType.SGA => new FileType.SGA(),
WrapperType.TapeArchive => new FileType.TapeArchive(),
WrapperType.VBSP => new FileType.VBSP(),
WrapperType.VPK => new FileType.VPK(),
WrapperType.WAD => new FileType.WAD(),
WrapperType.XZ => new FileType.XZ(),
WrapperType.XZP => new FileType.XZP(),
_ => null,
};
}
}
}

View File

@@ -0,0 +1,48 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// AACS media key block
/// </summary>
public class AACSMediaKeyBlock : IDetectable
{
/// <inheritdoc/>
public string? Detect(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Detect(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Detect(Stream stream, string file, bool includeDebug)
{
// If the MKB file itself fails
try
{
// Create the wrapper
var mkb = SabreTools.Serialization.Wrappers.AACSMediaKeyBlock.Create(stream);
if (mkb == null)
return null;
// Derive the version, if possible
var typeAndVersion = Array.Find(mkb.Model.Records ?? [], r => r?.RecordType == SabreTools.Models.AACS.RecordType.TypeAndVersion);
if (typeAndVersion == null)
return "AACS (Unknown Version)";
else
return $"AACS {(typeAndVersion as SabreTools.Models.AACS.TypeAndVersionRecord)?.VersionNumber}";
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return null;
}
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// BD+ SVM
/// </summary>
public class BDPlusSVM : IDetectable
{
/// <inheritdoc/>
public string? Detect(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Detect(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Detect(Stream stream, string file, bool includeDebug)
{
// If the BD+ file itself fails
try
{
// Create the wrapper
var svm = SabreTools.Serialization.Wrappers.BDPlusSVM.Create(stream);
if (svm == null)
return null;
// Format the date
string date = $"{svm.Model.Year:0000}/{svm.Model.Month:00}/{svm.Model.Day:00}";
// Return the formatted value
return $"BD+ {date}";
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return null;
}
}
}

View File

@@ -0,0 +1,138 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
#if NET462_OR_GREATER || NETCOREAPP
using SharpCompress.Compressors;
using SharpCompress.Compressors.Deflate;
#endif
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// BFPK custom archive format
/// </summary>
public class BFPK : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
try
{
// Create the wrapper
var bfpk = SabreTools.Serialization.Wrappers.BFPK.Create(stream);
if (bfpk == null)
return false;
// Extract all files
Directory.CreateDirectory(outDir);
ExtractAll(bfpk, outDir);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
/// <summary>
/// Extract all files from the BFPK to an output directory
/// </summary>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if all files extracted, false otherwise</returns>
public static bool ExtractAll(SabreTools.Serialization.Wrappers.BFPK item, string outputDirectory)
{
// If we have no files
if (item.Model.Files == null || item.Model.Files.Length == 0)
return false;
// Loop through and extract all files to the output
bool allExtracted = true;
for (int i = 0; i < item.Model.Files.Length; i++)
{
allExtracted &= ExtractFile(item, i, outputDirectory);
}
return allExtracted;
}
/// <summary>
/// Extract a file from the BFPK to an output directory by index
/// </summary>
/// <param name="index">File index to extract</param>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if the file extracted, false otherwise</returns>
public static bool ExtractFile(SabreTools.Serialization.Wrappers.BFPK item, int index, string outputDirectory)
{
// If we have no files
if (item.Model.Files == null || item.Model.Files.Length == 0)
return false;
// If we have an invalid index
if (index < 0 || index >= item.Model.Files.Length)
return false;
// Get the file information
var file = item.Model.Files[index];
if (file == null)
return false;
// Get the read index and length
int offset = file.Offset + 4;
int compressedSize = file.CompressedSize;
// Some files can lack the length prefix
if (compressedSize > item.GetEndOfFile())
{
offset -= 4;
compressedSize = file.UncompressedSize;
}
try
{
// Ensure the output directory exists
Directory.CreateDirectory(outputDirectory);
// Create the output path
string filePath = Path.Combine(outputDirectory, file.Name ?? $"file{index}");
using FileStream fs = File.OpenWrite(filePath);
// Read the data block
var data = item.ReadFromDataSource(offset, compressedSize);
if (data == null)
return false;
// If we have uncompressed data
if (compressedSize == file.UncompressedSize)
{
fs.Write(data, 0, compressedSize);
}
#if NET462_OR_GREATER || NETCOREAPP
else
{
MemoryStream ms = new MemoryStream(data);
ZlibStream zs = new ZlibStream(ms, CompressionMode.Decompress);
zs.CopyTo(fs);
}
#endif
return true;
}
catch
{
return false;
}
}
}
}

View File

@@ -0,0 +1,302 @@
using System;
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Half-Life Level
/// </summary>
public class BSP : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
try
{
// Create the wrapper
var bsp = SabreTools.Serialization.Wrappers.BSP.Create(stream);
if (bsp == null)
return false;
// Loop through and extract all files
Directory.CreateDirectory(outDir);
ExtractAllLumps(bsp, outDir);
ExtractAllTextures(bsp, outDir);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
/// <summary>
/// Extract all lumps from the BSP to an output directory
/// </summary>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if all lumps extracted, false otherwise</returns>
public static bool ExtractAllLumps(SabreTools.Serialization.Wrappers.BSP item, string outputDirectory)
{
// If we have no lumps
if (item.Model.Lumps == null || item.Model.Lumps.Length == 0)
return false;
// Loop through and extract all lumps to the output
bool allExtracted = true;
for (int i = 0; i < item.Model.Lumps.Length; i++)
{
allExtracted &= ExtractLump(item, i, outputDirectory);
}
return allExtracted;
}
/// <summary>
/// Extract a lump from the BSP to an output directory by index
/// </summary>
/// <param name="index">Lump index to extract</param>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if the lump extracted, false otherwise</returns>
public static bool ExtractLump(SabreTools.Serialization.Wrappers.BSP item, int index, string outputDirectory)
{
// If we have no lumps
if (item.Model.Lumps == null || item.Model.Lumps.Length == 0)
return false;
// If the lumps index is invalid
if (index < 0 || index >= item.Model.Lumps.Length)
return false;
// Get the lump
var lump = item.Model.Lumps[index];
if (lump == null)
return false;
// Read the data
var data = item.ReadFromDataSource((int)lump.Offset, (int)lump.Length);
if (data == null)
return false;
// Create the filename
string filename = $"lump_{index}.bin";
switch (index)
{
case SabreTools.Models.BSP.Constants.HL_BSP_LUMP_ENTITIES:
filename = "entities.ent";
break;
case SabreTools.Models.BSP.Constants.HL_BSP_LUMP_TEXTUREDATA:
filename = "texture_data.bin";
break;
}
// If we have an invalid output directory
if (string.IsNullOrEmpty(outputDirectory))
return false;
// Create the full output path
filename = Path.Combine(outputDirectory, filename);
// Ensure the output directory is created
var directoryName = Path.GetDirectoryName(filename);
if (directoryName != null)
Directory.CreateDirectory(directoryName);
// Try to write the data
try
{
// Open the output file for writing
using (Stream fs = File.OpenWrite(filename))
{
fs.Write(data, 0, data.Length);
}
}
catch
{
return false;
}
return true;
}
/// <summary>
/// Extract all textures from the BSP to an output directory
/// </summary>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if all textures extracted, false otherwise</returns>
public static bool ExtractAllTextures(SabreTools.Serialization.Wrappers.BSP item, string outputDirectory)
{
// If we have no textures
if (item.Model.TextureHeader?.Offsets == null || item.Model.TextureHeader.Offsets.Length == 0)
return false;
// Loop through and extract all lumps to the output
bool allExtracted = true;
for (int i = 0; i < item.Model.TextureHeader.Offsets.Length; i++)
{
allExtracted &= ExtractTexture(item, i, outputDirectory);
}
return allExtracted;
}
/// <summary>
/// Extract a texture from the BSP to an output directory by index
/// </summary>
/// <param name="index">Lump index to extract</param>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if the texture extracted, false otherwise</returns>
public static bool ExtractTexture(SabreTools.Serialization.Wrappers.BSP item, int index, string outputDirectory)
{
// If we have no textures
if (item.Model.Textures == null || item.Model.Textures.Length == 0)
return false;
// If the texture index is invalid
if (index < 0 || index >= item.Model.Textures.Length)
return false;
// Get the texture
var texture = item.Model.Textures[index];
if (texture == null)
return false;
// Read the data
var data = CreateTextureData(texture);
if (data == null)
return false;
// Create the filename
string filename = $"{texture.Name}.bmp";
// If we have an invalid output directory
if (string.IsNullOrEmpty(outputDirectory))
return false;
// Create the full output path
filename = Path.Combine(outputDirectory, filename);
// Ensure the output directory is created
var directoryName = Path.GetDirectoryName(filename);
if (directoryName != null)
Directory.CreateDirectory(directoryName);
// Try to write the data
try
{
// Open the output file for writing
using (Stream fs = File.OpenWrite(filename))
{
fs.Write(data, 0, data.Length);
}
}
catch
{
return false;
}
return true;
}
/// <summary>
/// Create a bitmap from the texture and palette data
/// </summary>
/// <param name="texture">Texture object to format</param>
/// <returns>Byte array representing the texture as a bitmap</returns>
private static byte[]? CreateTextureData(SabreTools.Models.BSP.Texture texture)
{
// If there's no palette data
if (texture.PaletteData == null || texture.PaletteData.Length == 0)
return null;
// If there's no texture data
if (texture.TextureData == null || texture.TextureData.Length == 0)
return null;
// Create the bitmap file header
var fileHeader = new SabreTools.Models.BMP.BITMAPFILEHEADER()
{
Type = ('M' << 8) | 'B',
Size = 14 + 40 + (texture.PaletteSize * 4) + (texture.Width * texture.Height),
OffBits = 14 + 40 + (texture.PaletteSize * 4),
};
// Create the bitmap info header
var infoHeader = new SabreTools.Models.BMP.BITMAPINFOHEADER
{
Size = 40,
Width = (int)texture.Width,
Height = (int)texture.Height,
Planes = 1,
BitCount = 8,
SizeImage = 0,
ClrUsed = texture.PaletteSize,
ClrImportant = texture.PaletteSize,
};
// Reformat the palette data
byte[] paletteData = new byte[texture.PaletteSize * 4];
for (uint i = 0; i < texture.PaletteSize; i++)
{
paletteData[i * 4 + 0] = texture.PaletteData[i * 3 + 2];
paletteData[i * 4 + 1] = texture.PaletteData[i * 3 + 1];
paletteData[i * 4 + 2] = texture.PaletteData[i * 3 + 0];
paletteData[i * 4 + 3] = 0;
}
// Reformat the pixel data
byte[] pixelData = new byte[texture.Width * texture.Height];
for (uint i = 0; i < texture.Width; i++)
{
for (uint j = 0; j < texture.Height; j++)
{
pixelData[i + ((texture.Height - 1 - j) * texture.Width)] = texture.TextureData[i + j * texture.Width];
}
}
// Build the file data
List<byte> buffer = new List<byte>();
// Bitmap file header
buffer.AddRange(BitConverter.GetBytes(fileHeader.Type));
buffer.AddRange(BitConverter.GetBytes(fileHeader.Size));
buffer.AddRange(BitConverter.GetBytes(fileHeader.Reserved1));
buffer.AddRange(BitConverter.GetBytes(fileHeader.Reserved2));
buffer.AddRange(BitConverter.GetBytes(fileHeader.OffBits));
// Bitmap info header
buffer.AddRange(BitConverter.GetBytes(infoHeader.Size));
buffer.AddRange(BitConverter.GetBytes(infoHeader.Width));
buffer.AddRange(BitConverter.GetBytes(infoHeader.Height));
buffer.AddRange(BitConverter.GetBytes(infoHeader.Planes));
buffer.AddRange(BitConverter.GetBytes(infoHeader.BitCount));
buffer.AddRange(BitConverter.GetBytes(infoHeader.Compression));
buffer.AddRange(BitConverter.GetBytes(infoHeader.SizeImage));
buffer.AddRange(BitConverter.GetBytes(infoHeader.XPelsPerMeter));
buffer.AddRange(BitConverter.GetBytes(infoHeader.YPelsPerMeter));
buffer.AddRange(BitConverter.GetBytes(infoHeader.ClrUsed));
buffer.AddRange(BitConverter.GetBytes(infoHeader.ClrImportant));
// Palette data
buffer.AddRange(paletteData);
// Pixel data
buffer.AddRange(pixelData);
return buffer.ToArray();
}
}
}

View File

@@ -0,0 +1,58 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
#if NET462_OR_GREATER || NETCOREAPP
using SharpCompress.Compressors;
using SharpCompress.Compressors.BZip2;
#endif
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// bzip2 archive
/// </summary>
public class BZip2 : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
if (stream == null || !stream.CanRead)
return false;
#if NET462_OR_GREATER || NETCOREAPP
try
{
// Try opening the stream
using var bz2File = new BZip2Stream(stream, CompressionMode.Decompress, true);
// Create the output file path
Directory.CreateDirectory(outDir);
string tempFile = Path.Combine(outDir, Guid.NewGuid().ToString());
// Extract the file
using FileStream fs = File.OpenWrite(tempFile);
bz2File.CopyTo(fs);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
#else
return false;
#endif
}
}
}

View File

@@ -0,0 +1,153 @@
using System;
using System.IO;
using System.Text;
using BinaryObjectScanner.Interfaces;
#if NET40_OR_GREATER || NETCOREAPP
using OpenMcdf;
#endif
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Compound File Binary
/// </summary>
public class CFB : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
#if NET20 || NET35
// Not supported for .NET Framework 2.0 or .NET Framework 3.5 due to library support
return false;
#else
try
{
using var msi = new CompoundFile(stream, CFSUpdateMode.ReadOnly, CFSConfiguration.Default);
msi.RootStorage.VisitEntries((e) =>
{
try
{
if (!e.IsStream)
return;
var str = msi.RootStorage.GetStream(e.Name);
if (str == null)
return;
byte[] strData = str.GetData();
if (strData == null)
return;
var decoded = DecodeStreamName(e.Name)?.TrimEnd('\0');
if (decoded == null)
return;
byte[] nameBytes = Encoding.UTF8.GetBytes(e.Name);
// UTF-8 encoding of 0x4840.
if (nameBytes[0] == 0xe4 && nameBytes[1] == 0xa1 && nameBytes[2] == 0x80)
decoded = decoded.Substring(3);
foreach (char c in Path.GetInvalidFileNameChars())
{
decoded = decoded.Replace(c, '_');
}
string tempFile = Path.Combine(outDir, decoded);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
using Stream fs = File.OpenWrite(tempFile);
fs.Write(strData, 0, strData.Length);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}, recursive: true);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
#endif
}
/// <remarks>Adapted from LibMSI</remarks>
public static string? DecodeStreamName(string input)
{
if (input == null)
return null;
int count = 0;
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
int p = 0; // inputBytes[0]
byte[] output = new byte[inputBytes.Length + 1];
int q = 0; // output[0]
while (p < inputBytes.Length && inputBytes[p] != 0)
{
int ch = inputBytes[p];
if ((ch == 0xe3 && inputBytes[p + 1] >= 0xa0) || (ch == 0xe4 && inputBytes[p + 1] < 0xa0))
{
// UTF-8 encoding of 0x3800..0x47ff.
output[q++] = (byte)Mime2Utf(inputBytes[p + 2] & 0x7f);
output[q++] = (byte)Mime2Utf(inputBytes[p + 1] ^ 0xa0);
p += 3;
count += 2;
continue;
}
if (ch == 0xe4 && inputBytes[p + 1] == 0xa0)
{
// UTF-8 encoding of 0x4800..0x483f.
output[q++] = (byte)Mime2Utf(inputBytes[p + 2] & 0x7f);
p += 3;
count++;
continue;
}
output[q++] = inputBytes[p++];
if (ch >= 0xc1)
output[q++] = inputBytes[p++];
if (ch >= 0xe0)
output[q++] = inputBytes[p++];
if (ch >= 0xf0)
output[q++] = inputBytes[p++];
count++;
}
output[q] = 0;
return Encoding.ASCII.GetString(output);
}
/// <remarks>Adapted from LibMSI</remarks>
private static int Mime2Utf(int x)
{
if (x < 10)
return x + '0';
if (x < (10 + 26))
return x - 10 + 'A';
if (x < (10 + 26 + 26))
return x - 10 - 26 + 'a';
if (x == (10 + 26 + 26))
return '.';
return '_';
}
}
}

View File

@@ -0,0 +1,348 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Data;
using BinaryObjectScanner.Interfaces;
using SabreTools.IO.Extensions;
using SabreTools.Serialization.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Executable or library
/// </summary>
public class Executable : IDetectable
{
#region Properties
/// <summary>
/// Determines if game engines are counted as detected protections or not
/// </summary>
public bool IncludeGameEngines { get; set; }
/// <summary>
/// Determines if packers are counted as detected protections or not
/// </summary>
public bool IncludePackers { get; set; }
#endregion
/// <inheritdoc/>
public string? Detect(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Detect(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Detect(Stream stream, string file, bool includeDebug)
{
// Get all non-nested protections
var protections = DetectDict(stream, file, getProtections: null, includeDebug);
if (protections.Count == 0)
return null;
// Create the internal list
var protectionList = new List<string>();
foreach (string key in protections.Keys)
{
protectionList.AddRange(protections[key]);
}
return string.Join(";", [.. protectionList]);
}
/// <inheritdoc cref="IDetectable.Detect(Stream, string, bool)"/>
/// <remarks>
/// Ideally, we wouldn't need to circumvent the proper handling of file types just for Executable,
/// but due to the complexity of scanning, this is not currently possible.
/// </remarks>
public ProtectionDictionary DetectDict(Stream stream,
string file,
Func<string, ProtectionDictionary>? getProtections,
bool includeDebug)
{
// Create the output dictionary
var protections = new ProtectionDictionary();
// Try to create a wrapper for the proper executable type
IWrapper? wrapper;
try
{
wrapper = WrapperFactory.CreateExecutableWrapper(stream);
if (wrapper == null)
return protections;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return protections;
}
// Only use generic content checks if we're in debug mode
if (includeDebug)
{
var subProtections = RunContentChecks(file, stream, includeDebug);
protections.Append(file, subProtections.Values);
}
if (wrapper is MSDOS mz)
{
// Standard checks
var subProtections = RunExecutableChecks(file, mz, StaticChecks.MSDOSExecutableCheckClasses, includeDebug);
protections.Append(file, subProtections.Values);
// Extractable checks
var extractedProtections = HandleExtractableProtections(file, mz, subProtections.Keys, getProtections, includeDebug);
protections.Append(extractedProtections);
}
else if (wrapper is LinearExecutable lex)
{
// Standard checks
var subProtections = RunExecutableChecks(file, lex, StaticChecks.LinearExecutableCheckClasses, includeDebug);
protections.Append(file, subProtections.Values);
// Extractable checks
var extractedProtections = HandleExtractableProtections(file, lex, subProtections.Keys, getProtections, includeDebug);
protections.Append(extractedProtections);
}
else if (wrapper is NewExecutable nex)
{
// Standard checks
var subProtections = RunExecutableChecks(file, nex, StaticChecks.NewExecutableCheckClasses, includeDebug);
protections.Append(file, subProtections.Values);
// Extractable checks
var extractedProtections = HandleExtractableProtections(file, nex, subProtections.Keys, getProtections, includeDebug);
protections.Append(extractedProtections);
}
else if (wrapper is PortableExecutable pex)
{
// Standard checks
var subProtections = RunExecutableChecks(file, pex, StaticChecks.PortableExecutableCheckClasses, includeDebug);
protections.Append(file, subProtections.Values);
// Extractable checks
var extractedProtections = HandleExtractableProtections(file, pex, subProtections.Keys, getProtections, includeDebug);
protections.Append(extractedProtections);
}
return protections;
}
#region Check Runners
/// <summary>
/// Handle a single file based on all content check implementations
/// </summary>
/// <param name="file">Name of the source file of the stream, for tracking</param>
/// <param name="stream">Stream to scan the contents of</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Set of protections in file, empty on error</returns>
public IDictionary<IContentCheck, string> RunContentChecks(string? file, Stream stream, bool includeDebug)
{
// Create the output dictionary
var protections = new CheckDictionary<IContentCheck>();
// If we have an invalid file
if (string.IsNullOrEmpty(file))
return protections;
else if (!File.Exists(file))
return protections;
// Read the file contents
byte[] fileContent = [];
try
{
fileContent = stream.ReadBytes((int)stream.Length);
if (fileContent == null)
return protections;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return protections;
}
// Iterate through all checks
StaticChecks.ContentCheckClasses.IterateWithAction(checkClass =>
{
// Get the protection for the class, if possible
var protection = checkClass.CheckContents(file!, fileContent, includeDebug);
if (string.IsNullOrEmpty(protection))
return;
// If we are filtering on game engines
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
return;
// If we are filtering on packers
if (CheckIfPacker(checkClass) && !IncludePackers)
return;
protections.Append(checkClass, protection);
});
return protections;
}
/// <summary>
/// Handle a single file based on all executable check implementations
/// </summary>
/// <param name="file">Name of the source file of the executable, for tracking</param>
/// <param name="exe">Executable to scan</param>
/// <param name="checks">Set of checks to use</param>
/// <param name="scanner">Scanner for handling recursive protections</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Set of protections in file, empty on error</returns>
public IDictionary<U, string> RunExecutableChecks<T, U>(string file, T exe, List<U> checks, bool includeDebug)
where T : WrapperBase
where U : IExecutableCheck<T>
{
// Create the output dictionary
var protections = new CheckDictionary<U>();
// Iterate through all checks
checks.IterateWithAction(checkClass =>
{
// Get the protection for the class, if possible
var protection = checkClass.CheckExecutable(file, exe, includeDebug);
if (string.IsNullOrEmpty(protection))
return;
// If we are filtering on game engines
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
return;
// If we are filtering on packers
if (CheckIfPacker(checkClass) && !IncludePackers)
return;
protections.Append(checkClass, protection);
});
return protections;
}
/// <summary>
/// Handle extractable protections, such as executable packers
/// </summary>
/// <param name="file">Name of the source file of the stream, for tracking</param>
/// <param name="exe">Executable to scan the contents of</param>
/// <param name="checks">Set of classes returned from Exectuable scans</param>
/// <param name="getProtections">Optional function for handling recursive protections</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Set of protections found from extraction, empty on error</returns>
private static ProtectionDictionary HandleExtractableProtections<T, U>(string file,
T exe,
IEnumerable<U> checks,
Func<string, ProtectionDictionary>? getProtections,
bool includeDebug)
where T : WrapperBase
where U : IExecutableCheck<T>
{
// Create the output dictionary
var protections = new ProtectionDictionary();
// If we have an invalid set of classes
if (checks == null)
return protections;
// If we have any extractable packers
var extractables = checks
.Where(c => c is IExtractableExecutable<T>)
.Select(c => c as IExtractableExecutable<T>);
extractables.IterateWithAction(extractable =>
{
var subProtections = PerformExtractableCheck(extractable!, file, exe, getProtections, includeDebug);
protections.Append(subProtections);
});
return protections;
}
/// <summary>
/// Handle files based on an IExtractableExecutable implementation
/// </summary>
/// <param name="file">Name of the source file of the stream, for tracking</param>
/// <param name="exe">Executable to scan the contents of</param>
/// <param name="impl">IExtractableExecutable class representing the file type</param>
/// <param name="getProtections">Optional function for handling recursive protections</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Set of protections in path, empty on error</returns>
private static ProtectionDictionary PerformExtractableCheck<T>(IExtractableExecutable<T> impl,
string file,
T exe,
Func<string, ProtectionDictionary>? getProtections,
bool includeDebug)
where T : WrapperBase
{
// If we have an invalid extractable somehow
if (impl == null)
return [];
// If the extractable file itself fails
try
{
// Extract and get the output path
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
bool extracted = impl.Extract(file, exe, tempPath, includeDebug);
// Collect and format all found protections
ProtectionDictionary? subProtections = null;
if (extracted && getProtections != null)
subProtections = getProtections(tempPath);
// If temp directory cleanup fails
try
{
if (Directory.Exists(tempPath))
Directory.Delete(tempPath, true);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
// Prepare the returned protections
subProtections?.StripFromKeys(tempPath);
subProtections?.PrependToKeys(file);
return subProtections ?? [];
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return [];
}
}
#endregion
#region Helpers
/// <summary>
/// Check to see if an implementation is a game engine using reflection
/// </summary>
/// <param name="impl">Implementation that was last used to check</param>
private static bool CheckIfGameEngine(object impl)
{
return impl.GetType().Namespace?.ToLowerInvariant()?.Contains("gameengine") ?? false;
}
/// <summary>
/// Check to see if an implementation is a packer using reflection
/// </summary>
/// <param name="impl">Implementation that was last used to check</param>
private static bool CheckIfPacker(object impl)
{
return impl.GetType().Namespace?.ToLowerInvariant()?.Contains("packer") ?? false;
}
#endregion
}
}

View File

@@ -0,0 +1,152 @@
using System;
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Half-Life Game Cache File
/// </summary>
public class GCF : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
try
{
// Create the wrapper
var gcf = SabreTools.Serialization.Wrappers.GCF.Create(stream);
if (gcf == null)
return false;
// Loop through and extract all files
Directory.CreateDirectory(outDir);
ExtractAll(gcf, outDir);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
/// <summary>
/// Extract all files from the GCF to an output directory
/// </summary>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if all files extracted, false otherwise</returns>
public static bool ExtractAll(SabreTools.Serialization.Wrappers.GCF item, string outputDirectory)
{
// If we have no files
if (item.Files == null || item.Files.Length == 0)
return false;
// Loop through and extract all files to the output
bool allExtracted = true;
for (int i = 0; i < item.Files.Length; i++)
{
allExtracted &= ExtractFile(item, i, outputDirectory);
}
return allExtracted;
}
/// <summary>
/// Extract a file from the GCF to an output directory by index
/// </summary>
/// <param name="index">File index to extract</param>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if the file extracted, false otherwise</returns>
public static bool ExtractFile(SabreTools.Serialization.Wrappers.GCF item, int index, string outputDirectory)
{
// If we have no files
if (item.Files == null || item.Files.Length == 0 || item.DataBlockOffsets == null)
return false;
// If the files index is invalid
if (index < 0 || index >= item.Files.Length)
return false;
// Get the file
var file = item.Files[index];
if (file?.BlockEntries == null || file.Size == 0)
return false;
// If the file is encrypted -- TODO: Revisit later
if (file.Encrypted)
return false;
// Get all data block offsets needed for extraction
var dataBlockOffsets = new List<long>();
for (int i = 0; i < file.BlockEntries.Length; i++)
{
var blockEntry = file.BlockEntries[i];
if (blockEntry == null)
continue;
uint dataBlockIndex = blockEntry.FirstDataBlockIndex;
long blockEntrySize = blockEntry.FileDataSize;
while (blockEntrySize > 0)
{
long dataBlockOffset = item.DataBlockOffsets[dataBlockIndex++];
dataBlockOffsets.Add(dataBlockOffset);
blockEntrySize -= item.Model.DataBlockHeader?.BlockSize ?? 0;
}
}
// Create the filename
var filename = file.Path;
// If we have an invalid output directory
if (string.IsNullOrEmpty(outputDirectory))
return false;
// Create the full output path
filename = Path.Combine(outputDirectory, filename ?? $"file{index}");
// Ensure the output directory is created
var directoryName = Path.GetDirectoryName(filename);
if (directoryName != null)
Directory.CreateDirectory(directoryName);
// Try to write the data
try
{
// Open the output file for writing
using (Stream fs = File.OpenWrite(filename))
{
// Now read the data sequentially and write out while we have data left
long fileSize = file.Size;
for (int i = 0; i < dataBlockOffsets.Count; i++)
{
int readSize = (int)Math.Min(item.Model.DataBlockHeader?.BlockSize ?? 0, fileSize);
var data = item.ReadFromDataSource((int)dataBlockOffsets[i], readSize);
if (data == null)
return false;
fs.Write(data, 0, data.Length);
}
}
}
catch
{
return false;
}
return true;
}
}
}

View File

@@ -0,0 +1,73 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
#if NET462_OR_GREATER || NETCOREAPP
using SharpCompress.Archives;
using SharpCompress.Archives.GZip;
#endif
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// gzip archive
/// </summary>
public class GZIP : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
if (stream == null || !stream.CanRead)
return false;
#if NET462_OR_GREATER || NETCOREAPP
try
{
using var zipFile = GZipArchive.Open(stream);
foreach (var entry in zipFile.Entries)
{
try
{
// If the entry is a directory
if (entry.IsDirectory)
continue;
// If the entry has an invalid key
if (entry.Key == null)
continue;
string tempFile = Path.Combine(outDir, entry.Key);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
entry.WriteToFile(tempFile);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
#else
return false;
#endif
}
}
}

View File

@@ -0,0 +1,62 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
using ISv3 = UnshieldSharp.Archive.InstallShieldArchiveV3;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// InstallShield archive v3
/// </summary>
public class InstallShieldArchiveV3 : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
try
{
var archive = new ISv3(file);
foreach (var cfile in archive.Files)
{
try
{
string tempFile = Path.Combine(outDir, cfile.Key);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
byte[]? fileContents = archive.Extract(cfile.Key, out string? error);
if (fileContents == null || !string.IsNullOrEmpty(error))
continue;
using (FileStream fs = File.OpenWrite(tempFile))
{
fs.Write(fileContents, 0, fileContents.Length);
}
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
}
}

View File

@@ -0,0 +1,97 @@
using System;
using System.IO;
using System.Text.RegularExpressions;
using BinaryObjectScanner.Interfaces;
using UnshieldSharp.Cabinet;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// InstallShield cabinet file
/// </summary>
public class InstallShieldCAB : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
// Get the name of the first cabinet file or header
var directory = Path.GetDirectoryName(file);
string noExtension = Path.GetFileNameWithoutExtension(file);
bool shouldScanCabinet;
if (directory == null)
{
string filenamePattern = noExtension;
filenamePattern = new Regex(@"\d+$").Replace(filenamePattern, string.Empty);
bool cabinetHeaderExists = File.Exists(filenamePattern + "1.hdr");
shouldScanCabinet = cabinetHeaderExists
? file.Equals(filenamePattern + "1.hdr", StringComparison.OrdinalIgnoreCase)
: file.Equals(filenamePattern + "1.cab", StringComparison.OrdinalIgnoreCase);
}
else
{
string filenamePattern = Path.Combine(directory, noExtension);
filenamePattern = new Regex(@"\d+$").Replace(filenamePattern, string.Empty);
bool cabinetHeaderExists = File.Exists(Path.Combine(directory, filenamePattern + "1.hdr"));
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 anything but the first file
if (!shouldScanCabinet)
return false;
try
{
var cabfile = InstallShieldCabinet.Open(file);
if (cabfile?.HeaderList == null)
return false;
for (int i = 0; i < cabfile.HeaderList.FileCount; i++)
{
try
{
// Check if the file is valid first
if (!cabfile.HeaderList.FileIsValid(i))
continue;
string tempFile;
try
{
string? filename = cabfile.HeaderList.GetFileName(i);
tempFile = Path.Combine(outDir, filename ?? string.Empty);
}
catch
{
tempFile = Path.Combine(outDir, $"BAD_FILENAME{i}");
}
cabfile.FileSave(i, tempFile);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
}
}

View File

@@ -0,0 +1,46 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Link Data Security encrypted file
/// </summary>
public class LDSCRYPT : IDetectable
{
/// <inheritdoc/>
public string? Detect(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Detect(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Detect(Stream stream, string file, bool includeDebug)
{
try
{
byte[] magic = new byte[16];
int read = stream.Read(magic, 0, 16);
#if NET20
if (Extensions.StartsWith(magic, new byte?[] { 0x4C, 0x44, 0x53, 0x43, 0x52, 0x59, 0x50, 0x54 }))
#else
if (magic.StartsWith(new byte?[] { 0x4C, 0x44, 0x53, 0x43, 0x52, 0x59, 0x50, 0x54 }))
#endif
return "Link Data Security encrypted file";
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return null;
}
}
}

View File

@@ -0,0 +1,81 @@
using System.IO;
using BinaryObjectScanner.Interfaces;
#if (NET452_OR_GREATER || NETCOREAPP) && WIN
using StormLibSharp;
#endif
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// MoPaQ game data archive
/// </summary>
public class MPQ : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
// TODO: Add stream opening support
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
#if NET20 || NET35 || NET40 || !WIN
// Not supported for old .NET due to feature requirements
// Not supported in non-Windows builds due to DLL requirements
return false;
#else
try
{
// Try to open the archive and listfile
var mpqArchive = new MpqArchive(file, FileAccess.Read);
string? listfile = null;
MpqFileStream listStream = mpqArchive.OpenFile("(listfile)");
// If we can't read the listfile, we just return
if (!listStream.CanRead)
return false;
// Read the listfile in for processing
using (var 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)
{
try
{
string tempFile = Path.Combine(outDir, sub);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
mpqArchive.ExtractFile(sub, tempFile);
}
catch (System.Exception ex)
{
if (includeDebug) System.Console.WriteLine(ex);
}
}
return true;
}
catch (System.Exception ex)
{
if (includeDebug) System.Console.WriteLine(ex);
return false;
}
#endif
}
}
}

View File

@@ -0,0 +1,65 @@
using System.IO;
using BinaryObjectScanner.Interfaces;
#if (NET40_OR_GREATER || NETCOREAPP) && WIN
using LibMSPackN;
#endif
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Microsoft cabinet file
/// </summary>
/// <remarks>Specification available at <see href="http://download.microsoft.com/download/5/0/1/501ED102-E53F-4CE0-AA6B-B0F93629DDC6/Exchange/%5BMS-CAB%5D.pdf"/></remarks>
/// <see href="https://github.com/wine-mirror/wine/tree/master/dlls/cabinet"/>
public class MicrosoftCAB : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
#if NET20 || NET35 || !WIN
// Not supported for old .NET due to feature requirements
// Not supported in non-Windows builds due to DLL requirements
return false;
#else
try
{
// Loop over each entry
var cabArchive = new MSCabinet(file);
foreach (var compressedFile in cabArchive.GetFiles())
{
try
{
string tempFile = Path.Combine(outDir, compressedFile.Filename);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
compressedFile.ExtractTo(tempFile);
}
catch (System.Exception ex)
{
if (includeDebug) System.Console.WriteLine(ex);
}
}
return true;
}
catch (System.Exception ex)
{
if (includeDebug) System.Console.WriteLine(ex);
return false;
}
#endif
}
}
}

View File

@@ -0,0 +1,63 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.Compression.LZ;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Microsoft LZ-compressed Files (LZ32)
/// </summary>
/// <remarks>This is treated like an archive type due to the packing style</remarks>
public class MicrosoftLZ : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
try
{
var data = Decompressor.Decompress(stream);
if (data == null)
return false;
// Create the temp filename
string tempFile = "temp.bin";
if (!string.IsNullOrEmpty(file))
{
var expandedFilePath = Decompressor.GetExpandedName(file, out _);
if (expandedFilePath != null)
tempFile = Path.GetFileName(expandedFilePath).TrimEnd('\0');
if (tempFile.EndsWith(".ex"))
tempFile += "e";
else if (tempFile.EndsWith(".dl"))
tempFile += "l";
}
tempFile = Path.Combine(outDir, tempFile);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
using Stream tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
tempStream.Write(data, 0, data.Length);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
}
}

View File

@@ -0,0 +1,124 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Half-Life Package File
/// </summary>
public class PAK : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
try
{
// Create the wrapper
var pak = SabreTools.Serialization.Wrappers.PAK.Create(stream);
if (pak == null)
return false;
// Loop through and extract all files
Directory.CreateDirectory(outDir);
ExtractAll(pak, outDir);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
/// <summary>
/// Extract all files from the PAK to an output directory
/// </summary>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if all files extracted, false otherwise</returns>
public static bool ExtractAll(SabreTools.Serialization.Wrappers.PAK item, string outputDirectory)
{
// If we have no directory items
if (item.Model.DirectoryItems == null || item.Model.DirectoryItems.Length == 0)
return false;
// Loop through and extract all files to the output
bool allExtracted = true;
for (int i = 0; i < item.Model.DirectoryItems.Length; i++)
{
allExtracted &= ExtractFile(item, i, outputDirectory);
}
return allExtracted;
}
/// <summary>
/// Extract a file from the PAK to an output directory by index
/// </summary>
/// <param name="index">File index to extract</param>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if the file extracted, false otherwise</returns>
public static bool ExtractFile(SabreTools.Serialization.Wrappers.PAK item, int index, string outputDirectory)
{
// If we have no directory items
if (item.Model.DirectoryItems == null || item.Model.DirectoryItems.Length == 0)
return false;
// If the directory item index is invalid
if (index < 0 || index >= item.Model.DirectoryItems.Length)
return false;
// Get the directory item
var directoryItem = item.Model.DirectoryItems[index];
if (directoryItem == null)
return false;
// Read the item data
var data = item.ReadFromDataSource((int)directoryItem.ItemOffset, (int)directoryItem.ItemLength);
if (data == null)
return false;
// Create the filename
var filename = directoryItem.ItemName;
// If we have an invalid output directory
if (string.IsNullOrEmpty(outputDirectory))
return false;
// Create the full output path
filename = Path.Combine(outputDirectory, filename ?? $"file{index}");
// Ensure the output directory is created
var directoryName = Path.GetDirectoryName(filename);
if (directoryName != null)
Directory.CreateDirectory(directoryName);
// Try to write the data
try
{
// Open the output file for writing
using (Stream fs = File.OpenWrite(filename))
{
fs.Write(data, 0, data.Length);
}
}
catch
{
return false;
}
return true;
}
}
}

View File

@@ -0,0 +1,117 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// NovaLogic Game Archive Format
/// </summary>
public class PFF : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
try
{
// Create the wrapper
var pff = SabreTools.Serialization.Wrappers.PFF.Create(stream);
if (pff == null)
return false;
// Extract all files
Directory.CreateDirectory(outDir);
ExtractAll(pff, outDir);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex.Message);
return false;
}
}
/// <summary>
/// Extract all segments from the PFF to an output directory
/// </summary>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if all segments extracted, false otherwise</returns>
public static bool ExtractAll(SabreTools.Serialization.Wrappers.PFF item, string outputDirectory)
{
// If we have no segments
if (item.Model.Segments == null || item.Model.Segments.Length == 0)
return false;
// Loop through and extract all files to the output
bool allExtracted = true;
for (int i = 0; i < item.Model.Segments.Length; i++)
{
allExtracted &= ExtractSegment(item, i, outputDirectory);
}
return allExtracted;
}
/// <summary>
/// Extract a segment from the PFF to an output directory by index
/// </summary>
/// <param name="index">Segment index to extract</param>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if the segment extracted, false otherwise</returns>
public static bool ExtractSegment(SabreTools.Serialization.Wrappers.PFF item, int index, string outputDirectory)
{
// If we have no segments
if (item.Model.Header?.NumberOfFiles == null || item.Model.Header.NumberOfFiles == 0 || item.Model.Segments == null || item.Model.Segments.Length == 0)
return false;
// If we have an invalid index
if (index < 0 || index >= item.Model.Segments.Length)
return false;
// Get the segment information
var file = item.Model.Segments[index];
if (file == null)
return false;
// Get the read index and length
int offset = (int)file.FileLocation;
int size = (int)file.FileSize;
try
{
// Ensure the output directory exists
Directory.CreateDirectory(outputDirectory);
// Create the output path
string filePath = Path.Combine(outputDirectory, file.FileName ?? $"file{index}");
using (FileStream fs = File.OpenWrite(filePath))
{
// Read the data block
var data = item.ReadFromDataSource(offset, size);
if (data == null)
return false;
// Write the data -- TODO: Compressed data?
fs.Write(data, 0, size);
}
return true;
}
catch
{
return false;
}
}
}
}

View File

@@ -0,0 +1,87 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
#if NET462_OR_GREATER || NETCOREAPP
using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
using SharpCompress.Readers;
#endif
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// PKWARE ZIP archive and derivatives
/// </summary>
public class PKZIP : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
=> Extract(file, outDir, lookForHeader: false, includeDebug);
/// <inheritdoc cref="IExtractable.Extract(string, string, bool)"/>
public bool Extract(string file, string outDir, bool lookForHeader, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, lookForHeader, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
=> Extract(stream, file, outDir, lookForHeader: false, includeDebug);
/// <inheritdoc cref="IExtractable.Extract(Stream?, string, string, bool)"/>
public bool Extract(Stream? stream, string file, string outDir, bool lookForHeader, bool includeDebug)
{
if (stream == null || !stream.CanRead)
return false;
#if NET462_OR_GREATER || NETCOREAPP
try
{
var readerOptions = new ReaderOptions() { LookForHeader = lookForHeader };
using var zipFile = ZipArchive.Open(stream, readerOptions);
foreach (var entry in zipFile.Entries)
{
try
{
// If the entry is a directory
if (entry.IsDirectory)
continue;
// If the entry has an invalid key
if (entry.Key == null)
continue;
// If the entry is partial due to an incomplete multi-part archive, skip it
if (!entry.IsComplete)
continue;
string tempFile = Path.Combine(outDir, entry.Key);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
entry.WriteToFile(tempFile);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
#else
return false;
#endif
}
}
}

View File

@@ -0,0 +1,46 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// PlayJ audio file
/// </summary>
public class PLJ : IDetectable
{
/// <inheritdoc/>
public string? Detect(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Detect(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Detect(Stream stream, string file, bool includeDebug)
{
try
{
byte[] magic = new byte[16];
int read = stream.Read(magic, 0, 16);
#if NET20
if (Extensions.StartsWith(magic, new byte?[] { 0xFF, 0x9D, 0x53, 0x4B }))
#else
if (magic.StartsWith(new byte?[] { 0xFF, 0x9D, 0x53, 0x4B }))
#endif
return "PlayJ Audio File";
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return null;
}
}
}

View File

@@ -0,0 +1,153 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Quantum Archive
/// </summary>
public class Quantum : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
try
{
// Create the wrapper
var quantum = SabreTools.Serialization.Wrappers.Quantum.Create(stream);
if (quantum == null)
return false;
// Extract all files
Directory.CreateDirectory(outDir);
ExtractAll(quantum, outDir);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex.Message);
return false;
}
}
/// <summary>
/// Extract all files from the Quantum archive to an output directory
/// </summary>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if all files extracted, false otherwise</returns>
public static bool ExtractAll(SabreTools.Serialization.Wrappers.Quantum item, string outputDirectory)
{
// If we have no files
if (item.Model.FileList == null || item.Model.FileList.Length == 0)
return false;
// Loop through and extract all files to the output
bool allExtracted = true;
for (int i = 0; i < item.Model.FileList.Length; i++)
{
allExtracted &= ExtractFile(item, i, outputDirectory);
}
return allExtracted;
}
/// <summary>
/// Extract a file from the Quantum archive to an output directory by index
/// </summary>
/// <param name="index">File index to extract</param>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if the file extracted, false otherwise</returns>
public static bool ExtractFile(SabreTools.Serialization.Wrappers.Quantum item, int index, string outputDirectory)
{
// If we have no files
if (item.Model.Header == null || item.Model.Header.FileCount == 0 || item.Model.FileList == null || item.Model.FileList.Length == 0)
return false;
// If we have an invalid index
if (index < 0 || index >= item.Model.FileList.Length)
return false;
// Get the file information
var fileDescriptor = item.Model.FileList[index];
// Read the entire compressed data
int compressedDataOffset = (int)item.Model.CompressedDataOffset;
int compressedDataLength = item.GetEndOfFile() - compressedDataOffset;
var compressedData = item.ReadFromDataSource(compressedDataOffset, compressedDataLength);
// TODO: Figure out decompression
// - Single-file archives seem to work
// - Single-file archives with files that span a window boundary seem to work
// - The first files in each archive seem to work
return false;
// // Setup the decompression state
// State state = new State();
// Decompressor.InitState(state, TableSize, CompressionFlags);
// // Decompress the entire array
// int decompressedDataLength = (int)FileList.Sum(fd => fd.ExpandedFileSize);
// byte[] decompressedData = new byte[decompressedDataLength];
// Decompressor.Decompress(state, compressedData.Length, compressedData, decompressedData.Length, decompressedData);
// // Read the data
// int offset = (int)FileList.Take(index).Sum(fd => fd.ExpandedFileSize);
// byte[] data = new byte[fileDescriptor.ExpandedFileSize];
// Array.Copy(decompressedData, offset, data, 0, data.Length);
// // Loop through all files before the current
// for (int i = 0; i < index; i++)
// {
// // Decompress the next block of data
// byte[] tempData = new byte[FileList[i].ExpandedFileSize];
// int lastRead = Decompressor.Decompress(state, compressedData.Length, compressedData, tempData.Length, tempData);
// compressedData = new ReadOnlySpan<byte>(compressedData, (lastRead), compressedData.Length - (lastRead)).ToArray();
// }
// // Read the data
// byte[] data = new byte[fileDescriptor.ExpandedFileSize];
// _ = Decompressor.Decompress(state, compressedData.Length, compressedData, data.Length, data);
// // Create the filename
// string filename = fileDescriptor.FileName;
// // If we have an invalid output directory
// if (string.IsNullOrEmpty(outputDirectory))
// return false;
// // Create the full output path
// filename = Path.Combine(outputDirectory, filename);
// // Ensure the output directory is created
// Directory.CreateDirectory(Path.GetDirectoryName(filename));
// // Try to write the data
// try
// {
// // Open the output file for writing
// using (Stream fs = File.OpenWrite(filename))
// {
// fs.Write(data, 0, data.Length);
// }
// }
// catch
// {
// return false;
// }
return true;
}
}
}

View File

@@ -0,0 +1,90 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
#if NET462_OR_GREATER || NETCOREAPP
using SharpCompress.Archives;
using SharpCompress.Archives.Rar;
using SharpCompress.Readers;
#endif
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// RAR archive
/// </summary>
public class RAR : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
=> Extract(file, outDir, lookForHeader: false, includeDebug);
/// <inheritdoc cref="IExtractable.Extract(string, string, bool)"/>
public bool Extract(string file, string outDir, bool lookForHeader, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, lookForHeader, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
=> Extract(stream, file, outDir, lookForHeader: false, includeDebug);
/// <inheritdoc cref="IExtractable.Extract(Stream?, string, string, bool)"/>
public bool Extract(Stream? stream, string file, string outDir, bool lookForHeader, bool includeDebug)
{
if (stream == null || !stream.CanRead)
return false;
#if NET462_OR_GREATER || NETCOREAPP
try
{
var readerOptions = new ReaderOptions() { LookForHeader = lookForHeader };
using RarArchive rarFile = RarArchive.Open(stream, readerOptions);
if (!rarFile.IsComplete)
return false;
foreach (var entry in rarFile.Entries)
{
try
{
// If the entry is a directory
if (entry.IsDirectory)
continue;
// If the entry has an invalid key
if (entry.Key == null)
continue;
// If we have a partial entry due to an incomplete multi-part archive, skip it
if (!entry.IsComplete)
continue;
string tempFile = Path.Combine(outDir, entry.Key);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
entry.WriteToFile(tempFile);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
#else
return false;
#endif
}
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// RealArcade Installer. Known to use the ".rgs" file extension.
///
/// TODO: Add further parsing, game ID and name should be possible to parse.
/// </summary>
public class RealArcadeInstaller : IDetectable
{
/// <inheritdoc/>
public string? Detect(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Detect(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Detect(Stream stream, string file, bool includeDebug)
{
try
{
byte[] magic = new byte[16];
int read = stream.Read(magic, 0, 16);
// RASGI2.0
// Found in the ".rgs" files in IA item "Nova_RealArcadeCD_USA".
#if NET20
if (Extensions.StartsWith(magic, new byte?[] { 0x52, 0x41, 0x53, 0x47, 0x49, 0x32, 0x2E, 0x30 }))
#else
if (magic.StartsWith(new byte?[] { 0x52, 0x41, 0x53, 0x47, 0x49, 0x32, 0x2E, 0x30 }))
#endif
return "RealArcade Installer";
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return null;
}
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// RealArcade Mezzanine files, which contain metadata. Known to use the ".mez" file extension.
///
/// TODO: Add further parsing, game ID should be possible to parse.
/// </summary>
public class RealArcadeMezzanine : IDetectable
{
/// <inheritdoc/>
public string? Detect(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Detect(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Detect(Stream stream, string file, bool includeDebug)
{
try
{
byte[] magic = new byte[16];
int read = stream.Read(magic, 0, 16);
// XZip2.0
// Found in the ".mez" files in IA item "Nova_RealArcadeCD_USA".
#if NET20
if (Extensions.StartsWith(magic, new byte?[] { 0x58, 0x5A, 0x69, 0x70, 0x32, 0x2E, 0x30 }))
#else
if (magic.StartsWith(new byte?[] { 0x58, 0x5A, 0x69, 0x70, 0x32, 0x2E, 0x30 }))
#endif
return "RealArcade Mezzanine";
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return null;
}
}
}

View File

@@ -0,0 +1,63 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// StarForce Filesystem file
/// </summary>
/// <see href="https://forum.xentax.com/viewtopic.php?f=21&t=2084"/>
public class SFFS : IExtractable, IDetectable
{
/// <inheritdoc/>
public string? Detect(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Detect(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Detect(Stream stream, string file, bool includeDebug)
{
try
{
byte[] magic = new byte[16];
int read = stream.Read(magic, 0, 16);
#if NET20
if (Extensions.StartsWith(magic, new byte?[] { 0x53, 0x46, 0x46, 0x53 }))
#else
if (magic.StartsWith(new byte?[] { 0x53, 0x46, 0x46, 0x53 }))
#endif
return "StarForce Filesystem Container";
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
return false;
}
}
}

View File

@@ -0,0 +1,262 @@
using System;
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.Compression.zlib;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// SGA game archive
/// </summary>
public class SGA : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
try
{
// Create the wrapper
var sga = SabreTools.Serialization.Wrappers.SGA.Create(stream);
if (sga == null)
return false;
// Loop through and extract all files
Directory.CreateDirectory(outDir);
ExtractAll(sga, outDir);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
/// <summary>
/// Extract all files from the SGA to an output directory
/// </summary>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if all files extracted, false otherwise</returns>
public static bool ExtractAll(SabreTools.Serialization.Wrappers.SGA item, string outputDirectory)
{
// Get the file count
int filesLength = item.Model.Directory switch
{
SabreTools.Models.SGA.Directory4 d4 => filesLength = d4.Files?.Length ?? 0,
SabreTools.Models.SGA.Directory5 d5 => filesLength = d5.Files?.Length ?? 0,
SabreTools.Models.SGA.Directory6 d6 => filesLength = d6.Files?.Length ?? 0,
SabreTools.Models.SGA.Directory7 d7 => filesLength = d7.Files?.Length ?? 0,
_ => 0,
};
// If we have no files
if (filesLength == 0)
return false;
// Loop through and extract all files to the output
bool allExtracted = true;
for (int i = 0; i < filesLength; i++)
{
allExtracted &= ExtractFile(item, i, outputDirectory);
}
return allExtracted;
}
/// <summary>
/// Extract a file from the SGA to an output directory by index
/// </summary>
/// <param name="index">File index to extract</param>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if the file extracted, false otherwise</returns>
public static bool ExtractFile(SabreTools.Serialization.Wrappers.SGA item, int index, string outputDirectory)
{
// Get the file count
int filesLength = item.Model.Directory switch
{
SabreTools.Models.SGA.Directory4 d4 => filesLength = d4.Files?.Length ?? 0,
SabreTools.Models.SGA.Directory5 d5 => filesLength = d5.Files?.Length ?? 0,
SabreTools.Models.SGA.Directory6 d6 => filesLength = d6.Files?.Length ?? 0,
SabreTools.Models.SGA.Directory7 d7 => filesLength = d7.Files?.Length ?? 0,
_ => 0,
};
// If we have no files
if (filesLength == 0)
return false;
// If the files index is invalid
if (index < 0 || index >= filesLength)
return false;
// Get the files
object? file = item.Model.Directory switch
{
SabreTools.Models.SGA.Directory4 d4 => d4.Files![index],
SabreTools.Models.SGA.Directory5 d5 => d5.Files![index],
SabreTools.Models.SGA.Directory6 d6 => d6.Files![index],
SabreTools.Models.SGA.Directory7 d7 => d7.Files![index],
_ => null,
};
// If the file is invalid
if (file == null)
return false;
// Create the filename
var filename = file switch
{
SabreTools.Models.SGA.File4 f4 => f4.Name,
_ => null,
};
// If the filename is invalid
if (filename == null)
return false;
// Loop through and get all parent directories
var parentNames = new List<string> { filename };
// Get the parent directory
var folder = item.Model.Directory switch
{
SabreTools.Models.SGA.Directory4 d4 => Array.Find(d4.Folders ?? [], f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex),
SabreTools.Models.SGA.Directory5 d5 => Array.Find(d5.Folders ?? [], f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex),
SabreTools.Models.SGA.Directory6 d6 => Array.Find(d6.Folders ?? [], f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex),
SabreTools.Models.SGA.Directory7 d7 => Array.Find(d7.Folders ?? [], f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex),
_ => default(object),
};
// If we have a parent folder
if (folder != null)
{
string folderName = folder switch
{
SabreTools.Models.SGA.Folder4 f4 => f4.Name ?? string.Empty,
SabreTools.Models.SGA.Folder5 f5 => f5.Name ?? string.Empty,
_ => string.Empty,
};
parentNames.Add(folderName);
}
// TODO: Should the section name/alias be used in the path as well?
// Reverse and assemble the filename
parentNames.Reverse();
#if NET20 || NET35
filename = parentNames[0];
for (int i = 1; i < parentNames.Count; i++)
{
filename = Path.Combine(filename, parentNames[i]);
}
#else
filename = Path.Combine([.. parentNames]);
#endif
// Get the file offset
long fileOffset = file switch
{
SabreTools.Models.SGA.File4 f4 => f4.Offset,
_ => -1,
};
// Adjust the file offset
fileOffset += item.Model.Header switch
{
SabreTools.Models.SGA.Header4 h4 => h4.FileDataOffset,
SabreTools.Models.SGA.Header6 h6 => h6.FileDataOffset,
_ => -1,
};
// If the offset is invalid
if (fileOffset < 0)
return false;
// Get the file sizes
long fileSize, outputFileSize;
switch (file)
{
case SabreTools.Models.SGA.File4 f4:
fileSize = f4.SizeOnDisk;
outputFileSize = f4.Size;
break;
default:
return false;
}
// Read the compressed data directly
var compressedData = item.ReadFromDataSource((int)fileOffset, (int)fileSize);
if (compressedData == null)
return false;
// If the compressed and uncompressed sizes match
byte[] data;
if (fileSize == outputFileSize)
{
data = compressedData;
}
else
{
// Inflate the data into the buffer
var zstream = new ZLib.z_stream_s();
data = new byte[outputFileSize];
unsafe
{
fixed (byte* payloadPtr = compressedData)
fixed (byte* dataPtr = data)
{
zstream.next_in = payloadPtr;
zstream.avail_in = (uint)compressedData.Length;
zstream.total_in = (uint)compressedData.Length;
zstream.next_out = dataPtr;
zstream.avail_out = (uint)data.Length;
zstream.total_out = 0;
ZLib.inflateInit_(zstream, ZLib.zlibVersion(), compressedData.Length);
int zret = ZLib.inflate(zstream, 1);
ZLib.inflateEnd(zstream);
}
}
}
// If we have an invalid output directory
if (string.IsNullOrEmpty(outputDirectory))
return false;
// Create the full output path
filename = Path.Combine(outputDirectory, filename);
// Ensure the output directory is created
var directoryName = Path.GetDirectoryName(filename);
if (directoryName != null)
Directory.CreateDirectory(directoryName);
// Try to write the data
try
{
// Open the output file for writing
using Stream fs = File.OpenWrite(filename);
fs.Write(data, 0, data.Length);
}
catch
{
return false;
}
return false;
}
}
}

View File

@@ -0,0 +1,87 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
#if NET462_OR_GREATER || NETCOREAPP
using SharpCompress.Archives;
using SharpCompress.Archives.SevenZip;
using SharpCompress.Readers;
#endif
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// 7-zip archive
/// </summary>
public class SevenZip : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
=> Extract(file, outDir, lookForHeader: false, includeDebug);
/// <inheritdoc cref="IExtractable.Extract(string, string, bool)"/>
public bool Extract(string file, string outDir, bool lookForHeader, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, lookForHeader, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
=> Extract(stream, file, outDir, lookForHeader: false, includeDebug);
/// <inheritdoc cref="IExtractable.Extract(Stream?, string, string, bool)"/>
public bool Extract(Stream? stream, string file, string outDir, bool lookForHeader, bool includeDebug)
{
if (stream == null || !stream.CanRead)
return false;
#if NET462_OR_GREATER || NETCOREAPP
try
{
var readerOptions = new ReaderOptions() { LookForHeader = lookForHeader };
using var sevenZip = SevenZipArchive.Open(stream, readerOptions);
foreach (var entry in sevenZip.Entries)
{
try
{
// If the entry is a directory
if (entry.IsDirectory)
continue;
// If the entry has an invalid key
if (entry.Key == null)
continue;
// If we have a partial entry due to an incomplete multi-part archive, skip it
if (!entry.IsComplete)
continue;
string tempFile = Path.Combine(outDir, entry.Key);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
entry.WriteToFile(tempFile);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
#else
return false;
#endif
}
}
}

View File

@@ -0,0 +1,77 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
#if NET462_OR_GREATER || NETCOREAPP
using SharpCompress.Archives;
using SharpCompress.Archives.Tar;
#endif
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Tape archive
/// </summary>
public class TapeArchive : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
if (stream == null || !stream.CanRead)
return false;
#if NET462_OR_GREATER || NETCOREAPP
try
{
using var tarFile = TarArchive.Open(stream);
foreach (var entry in tarFile.Entries)
{
try
{
// If the entry is a directory
if (entry.IsDirectory)
continue;
// If the entry has an invalid key
if (entry.Key == null)
continue;
// If we have a partial entry due to an incomplete multi-part archive, skip it
if (!entry.IsComplete)
continue;
string tempFile = Path.Combine(outDir, entry.Key);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
entry.WriteToFile(tempFile);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
#else
return false;
#endif
}
}
}

View File

@@ -0,0 +1,187 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Various generic textfile formats
/// </summary>
public class Textfile : IDetectable
{
/// <inheritdoc/>
public string? Detect(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Detect(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Detect(Stream stream, string file, bool includeDebug)
{
// Files can be protected in multiple ways
var protections = new List<string>();
try
{
// Load the current file content
var fileContent = string.Empty;
#if NET20 || NET35 || NET40
using (var sr = new StreamReader(stream, Encoding.Default, true, 1024 * 1024))
#else
using (var sr = new StreamReader(stream, Encoding.Default, true, 1024 * 1024, true))
#endif
{
fileContent = sr.ReadToEnd();
}
// AegiSoft License Manager
// Found in "setup.ins" (Redump entry 73521/IA item "Nova_HoyleCasino99USA").
if (fileContent.Contains("Failed to load the AegiSoft License Manager install program."))
protections.Add("AegiSoft License Manager");
// CD-Key
if (fileContent.Contains("a valid serial number is required"))
protections.Add("CD-Key / Serial");
else if (fileContent.Contains("serial number is located"))
protections.Add("CD-Key / Serial");
// Found in "Setup.Ins" ("Word Point 2002" in IA item "advantage-language-french-beginner-langmaster-2005").
else if (fileContent.Contains("Please enter a valid registration number"))
protections.Add("CD-Key / Serial");
// Channelware
// Found in "README.TXT" in Redump entry 116358.
if (fileContent.Contains("This application is a Channelware-activated product."))
protections.Add("Channelware");
// Found in "Swr.dat" in the "TOYSTORY" installation folder from Redump entry 12354.
if (fileContent.Contains("cwsw.com/authts"))
protections.Add("Channelware");
// CopyKiller
// Found in "autorun.dat" in CopyKiller versions 3.62 and 3.64.
if (fileContent.Contains("CopyKiller CD-Protection V3.6x"))
protections.Add("CopyKiller V3.62-V3.64");
// Found in "autorun.dat" in CopyKiller versions 3.99 and 3.99a.
else if (fileContent.Contains("CopyKiller V4 CD / DVD-Protection"))
protections.Add("CopyKiller V3.99+");
// Found in "engine.wzc" in CopyKiller versions 3.62 and 3.64.
else if (fileContent.Contains("CopyKiller V3.6x Protection Engine"))
protections.Add("CopyKiller V3.62-V3.64");
// Found in "engine.wzc" in CopyKiller versions 3.99 and 3.99a.
else if (fileContent.Contains("CopyKiller V3.99x Protection Engine"))
protections.Add("CopyKiller V3.99+");
// Freelock
// Found in "FILE_ID.DIZ" distributed with Freelock.
if (fileContent.Contains("FREELOCK 1.0"))
protections.Add("Freelock 1.0");
else if (fileContent.Contains("FREELOCK 1.2"))
protections.Add("Freelock 1.2");
else if (fileContent.Contains("FREELOCK 1.2a"))
protections.Add("Freelock 1.2a");
else if (fileContent.Contains("FREELOCK 1.3"))
protections.Add("Freelock 1.3");
else if (fileContent.Contains("FREELOCK"))
protections.Add("Freelock");
// MediaCloQ
if (fileContent.Contains("SunnComm MediaCloQ"))
protections.Add("MediaCloQ");
else if (fileContent.Contains("http://download.mediacloq.com/"))
protections.Add("MediaCloQ");
else if (fileContent.Contains("http://www.sunncomm.com/mediacloq/"))
protections.Add("MediaCloQ");
// MediaMax
if (fileContent.Contains("MediaMax technology"))
protections.Add("MediaMax CD-3");
else if (fileContent.Contains("exclusive Cd3 technology"))
protections.Add("MediaMax CD-3");
else if (fileContent.Contains("<PROTECTION-VENDOR>MediaMAX</PROTECTION-VENDOR>"))
protections.Add("MediaMax CD-3");
else if (fileContent.Contains("MediaMax(tm)"))
protections.Add("MediaMax CD-3");
// phenoProtect
// Found in Redump entry 84082.
if (fileContent.Contains("phenoProtect"))
protections.Add("phenoProtect");
// Additional check to minimize overmatching.
if (fileContent.Contains("InstallSHIELD Software Coporation"))
// Found in Redump entry 102493.
if (fileContent.Contains("COPYPROTECTION_FAILEDR"))
protections.Add("phenoProtect");
// Rainbow Sentinel
// Found in "SENTW95.HLP" and "SENTINEL.HLP" in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]".
if (fileContent.Contains("Rainbow Sentinel Driver Help"))
protections.Add("Rainbow Sentinel");
// Found in "\disc4\cad\sdcc_200.zip\DISK1\_USER1.HDR\Language_Independent_Intel_32_Files\SNTNLUSB.INF" in "CICA 32 For Windows CD-ROM (Walnut Creek) (October 1999) (Disc 4).iso" in IA item "CICA_32_For_Windows_CD-ROM_Walnut_Creek_October_1999".
if (fileContent.Contains("SNTNLUSB.SvcDesc=\"Rainbow Security Device\""))
protections.Add("Rainbow Sentinel USB Driver");
if (fileContent.Contains("SntUsb95.SvcDesc=\"Rainbow Security Device\""))
protections.Add("Rainbow Sentinel USB Driver");
// Found in "OEMSETUP.INF" in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]".
if (fileContent.Contains("Sentinel Driver Disk"))
protections.Add("Rainbow Sentinel");
// SafeCast
// Found in "AdlmLog.xml" in IA item game-programming-in-c-start-to-finish-2006 after installing "3dsMax8_Demo.zip".
if (fileContent.Contains("<NAME>SAFECAST</NAME>"))
protections.Add("SafeCast");
// SafeDisc
// TODO: Add better version parsing.
// Found in "Info.plist" in Redump entries 23983, 42762, 72713, 73070, and 89603.
if (fileContent.Contains("<string>com.europevisionmacro.SafeDiscDVD</string>"))
{
if (fileContent.Contains("<string>2.90.032</string>"))
protections.Add("SafeDiscDVD for Macintosh 2.90.032");
else
protections.Add("SafeDiscDVD for Macintosh (Unknown Version - Please report to us on GitHub)");
}
// Found in "Info.plist" in Redump entry 89649.
if (fileContent.Contains("<string>com.macrovisioneurope.SafeDiscLT</string>"))
{
// TODO: Investigate why "CFBundleGetInfoString" and "CFBundleShortVersionString" say version 2.70.020, but "CFBundleVersion" says version 2.70.010.
if (fileContent.Contains("<string>2.70.020</string"))
protections.Add("SafeDiscLT for Macintosh 2.70.020");
else
protections.Add("SafeDiscLT for Macintosh (Unknown Version - Please report to us on GitHub)");
}
// The full line from a sample is as follows:
//
// The files securom_v7_01.dat and securom_v7_01.bak have been created during the installation of a SecuROM protected application.
//
// TODO: Use the filenames in this line to get the version out of it
// SecuROM
if (fileContent.Contains("SecuROM protected application"))
protections.Add("SecuROM");
// Steam
if (fileContent.Contains("All use of the Program is governed by the terms of the Steam Agreement as described below."))
protections.Add("Steam");
// XCP
if (fileContent.Contains("http://cp.sonybmg.com/xcp/"))
protections.Add("XCP");
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return string.Join(";", [.. protections]);
}
}
}

View File

@@ -0,0 +1,133 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Half-Life 2 Level
/// </summary>
public class VBSP : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
try
{
// Create the wrapper
var vbsp = SabreTools.Serialization.Wrappers.VBSP.Create(stream);
if (vbsp == null)
return false;
// Loop through and extract all files
Directory.CreateDirectory(outDir);
ExtractAllLumps(vbsp, outDir);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex.ToString());
return false;
}
}
/// <summary>
/// Extract all lumps from the VBSP to an output directory
/// </summary>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if all lumps extracted, false otherwise</returns>
public static bool ExtractAllLumps(SabreTools.Serialization.Wrappers.VBSP item, string outputDirectory)
{
// If we have no lumps
if (item.Model.Header?.Lumps == null || item.Model.Header.Lumps.Length == 0)
return false;
// Loop through and extract all lumps to the output
bool allExtracted = true;
for (int i = 0; i < item.Model.Header.Lumps.Length; i++)
{
allExtracted &= ExtractLump(item, i, outputDirectory);
}
return allExtracted;
}
/// <summary>
/// Extract a lump from the VBSP to an output directory by index
/// </summary>
/// <param name="index">Lump index to extract</param>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if the lump extracted, false otherwise</returns>
public static bool ExtractLump(SabreTools.Serialization.Wrappers.VBSP item, int index, string outputDirectory)
{
// If we have no lumps
if (item.Model.Header?.Lumps == null || item.Model.Header.Lumps.Length == 0)
return false;
// If the lumps index is invalid
if (index < 0 || index >= item.Model.Header.Lumps.Length)
return false;
// Get the lump
var lump = item.Model.Header.Lumps[index];
if (lump == null)
return false;
// Read the data
var data = item.ReadFromDataSource((int)lump.Offset, (int)lump.Length);
if (data == null)
return false;
// Create the filename
string filename = $"lump_{index}.bin";
switch (index)
{
case SabreTools.Models.VBSP.Constants.HL_VBSP_LUMP_ENTITIES:
filename = "entities.ent";
break;
case SabreTools.Models.VBSP.Constants.HL_VBSP_LUMP_PAKFILE:
filename = "pakfile.zip";
break;
}
// If we have an invalid output directory
if (string.IsNullOrEmpty(outputDirectory))
return false;
// Create the full output path
filename = Path.Combine(outputDirectory, filename);
// Ensure the output directory is created
var directoryName = Path.GetDirectoryName(filename);
if (directoryName != null)
Directory.CreateDirectory(directoryName);
// Try to write the data
try
{
// Open the output file for writing
using (Stream fs = File.OpenWrite(filename))
{
fs.Write(data, 0, data.Length);
}
}
catch
{
return false;
}
return true;
}
}
}

View File

@@ -0,0 +1,181 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.IO.Extensions;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Valve Package File
/// </summary>
public class VPK : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
try
{
// Create the wrapper
var vpk = SabreTools.Serialization.Wrappers.VPK.Create(stream);
if (vpk == null)
return false;
// Loop through and extract all files
Directory.CreateDirectory(outDir);
ExtractAll(vpk, outDir);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
/// <summary>
/// Extract all files from the VPK to an output directory
/// </summary>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if all files extracted, false otherwise</returns>
public static bool ExtractAll(SabreTools.Serialization.Wrappers.VPK item, string outputDirectory)
{
// If we have no directory items
if (item.Model.DirectoryItems == null || item.Model.DirectoryItems.Length == 0)
return false;
// Loop through and extract all files to the output
bool allExtracted = true;
for (int i = 0; i < item.Model.DirectoryItems.Length; i++)
{
allExtracted &= ExtractFile(item, i, outputDirectory);
}
return allExtracted;
}
/// <summary>
/// Extract a file from the VPK to an output directory by index
/// </summary>
/// <param name="index">File index to extract</param>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if the file extracted, false otherwise</returns>
public static bool ExtractFile(SabreTools.Serialization.Wrappers.VPK item, int index, string outputDirectory)
{
// If we have no directory items
if (item.Model.DirectoryItems == null || item.Model.DirectoryItems.Length == 0)
return false;
// If the directory item index is invalid
if (index < 0 || index >= item.Model.DirectoryItems.Length)
return false;
// Get the directory item
var directoryItem = item.Model.DirectoryItems[index];
if (directoryItem?.DirectoryEntry == null)
return false;
// If we have an item with no archive
var data = new byte[0];
if (directoryItem.DirectoryEntry.ArchiveIndex == SabreTools.Models.VPK.Constants.HL_VPK_NO_ARCHIVE)
{
if (directoryItem.PreloadData == null)
return false;
data = directoryItem.PreloadData;
}
else
{
// If we have invalid archives
if (item.ArchiveFilenames == null || item.ArchiveFilenames.Length == 0)
return false;
// If we have an invalid index
if (directoryItem.DirectoryEntry.ArchiveIndex < 0 || directoryItem.DirectoryEntry.ArchiveIndex >= item.ArchiveFilenames.Length)
return false;
// Get the archive filename
string archiveFileName = item.ArchiveFilenames[directoryItem.DirectoryEntry.ArchiveIndex];
if (string.IsNullOrEmpty(archiveFileName))
return false;
// If the archive doesn't exist
if (!File.Exists(archiveFileName))
return false;
// Try to open the archive
var archiveStream = default(Stream);
try
{
// Open the archive
archiveStream = File.Open(archiveFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// Seek to the data
archiveStream.Seek(directoryItem.DirectoryEntry.EntryOffset, SeekOrigin.Begin);
// Read the directory item bytes
data = archiveStream.ReadBytes((int)directoryItem.DirectoryEntry.EntryLength);
}
catch
{
return false;
}
finally
{
archiveStream?.Close();
}
// If we have preload data, prepend it
if (data != null && directoryItem.PreloadData != null)
data = [.. directoryItem.PreloadData, .. data];
}
// If there is nothing to write out
if (data == null)
return false;
// Create the filename
string filename = $"{directoryItem.Name}.{directoryItem.Extension}";
if (!string.IsNullOrEmpty(directoryItem.Path))
filename = Path.Combine(directoryItem.Path, filename);
// If we have an invalid output directory
if (string.IsNullOrEmpty(outputDirectory))
return false;
// Create the full output path
filename = Path.Combine(outputDirectory, filename);
// Ensure the output directory is created
var directoryName = Path.GetDirectoryName(filename);
if (directoryName != null)
Directory.CreateDirectory(directoryName);
// Try to write the data
try
{
// Open the output file for writing
using (Stream fs = File.OpenWrite(filename))
{
fs.Write(data, 0, data.Length);
}
}
catch
{
return false;
}
return true;
}
}
}

View File

@@ -0,0 +1,124 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Half-Life Texture Package File
/// </summary>
public class WAD : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
try
{
// Create the wrapper
var wad = SabreTools.Serialization.Wrappers.WAD.Create(stream);
if (wad == null)
return false;
// Loop through and extract all files
Directory.CreateDirectory(outDir);
ExtractAllLumps(wad, outDir);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
/// <summary>
/// Extract all lumps from the WAD to an output directory
/// </summary>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if all lumps extracted, false otherwise</returns>
public static bool ExtractAllLumps(SabreTools.Serialization.Wrappers.WAD item, string outputDirectory)
{
// If we have no lumps
if (item.Model.Lumps == null || item.Model.Lumps.Length == 0)
return false;
// Loop through and extract all lumps to the output
bool allExtracted = true;
for (int i = 0; i < item.Model.Lumps.Length; i++)
{
allExtracted &= ExtractLump(item, i, outputDirectory);
}
return allExtracted;
}
/// <summary>
/// Extract a lump from the WAD to an output directory by index
/// </summary>
/// <param name="index">Lump index to extract</param>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if the lump extracted, false otherwise</returns>
public static bool ExtractLump(SabreTools.Serialization.Wrappers.WAD item, int index, string outputDirectory)
{
// If we have no lumps
if (item.Model.Lumps == null || item.Model.Lumps.Length == 0)
return false;
// If the lumps index is invalid
if (index < 0 || index >= item.Model.Lumps.Length)
return false;
// Get the lump
var lump = item.Model.Lumps[index];
if (lump == null)
return false;
// Read the data -- TODO: Handle uncompressed lumps (see BSP.ExtractTexture)
var data = item.ReadFromDataSource((int)lump.Offset, (int)lump.Length);
if (data == null)
return false;
// Create the filename
string filename = $"{lump.Name}.lmp";
// If we have an invalid output directory
if (string.IsNullOrEmpty(outputDirectory))
return false;
// Create the full output path
filename = Path.Combine(outputDirectory, filename);
// Ensure the output directory is created
var directoryName = Path.GetDirectoryName(filename);
if (directoryName != null)
Directory.CreateDirectory(directoryName);
// Try to write the data
try
{
// Open the output file for writing
using (Stream fs = File.OpenWrite(filename))
{
fs.Write(data, 0, data.Length);
}
}
catch
{
return false;
}
return true;
}
}
}

View File

@@ -0,0 +1,54 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
#if NET462_OR_GREATER || NETCOREAPP
using SharpCompress.Compressors.Xz;
#endif
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// xz archive
/// </summary>
public class XZ : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
#if NET462_OR_GREATER || NETCOREAPP
try
{
// Try opening the stream
using var xzFile = new XZStream(stream);
// Create the output file path
Directory.CreateDirectory(outDir);
string tempFile = Path.Combine(outDir, Guid.NewGuid().ToString());
// Extract the file
using FileStream fs = File.OpenWrite(tempFile);
xzFile.CopyTo(fs);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
#else
return false;
#endif
}
}
}

View File

@@ -0,0 +1,133 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// XBox Package File
/// </summary>
public class XZP : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
{
if (!File.Exists(file))
return false;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, outDir, includeDebug);
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
try
{
// Create the wrapper
var xzp = SabreTools.Serialization.Wrappers.XZP.Create(stream);
if (xzp == null)
return false;
// Loop through and extract all files
Directory.CreateDirectory(outDir);
ExtractAll(xzp, outDir);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
/// <summary>
/// Extract all files from the XZP to an output directory
/// </summary>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if all files extracted, false otherwise</returns>
public static bool ExtractAll(SabreTools.Serialization.Wrappers.XZP item, string outputDirectory)
{
// If we have no directory entries
if (item.Model.DirectoryEntries == null || item.Model.DirectoryEntries.Length == 0)
return false;
// Loop through and extract all files to the output
bool allExtracted = true;
for (int i = 0; i < item.Model.DirectoryEntries.Length; i++)
{
allExtracted &= ExtractFile(item, i, outputDirectory);
}
return allExtracted;
}
/// <summary>
/// Extract a file from the XZP to an output directory by index
/// </summary>
/// <param name="index">File index to extract</param>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if the file extracted, false otherwise</returns>
public static bool ExtractFile(SabreTools.Serialization.Wrappers.XZP item, int index, string outputDirectory)
{
// If we have no directory entries
if (item.Model.DirectoryEntries == null || item.Model.DirectoryEntries.Length == 0)
return false;
// If we have no directory items
if (item.Model.DirectoryItems == null || item.Model.DirectoryItems.Length == 0)
return false;
// If the directory entry index is invalid
if (index < 0 || index >= item.Model.DirectoryEntries.Length)
return false;
// Get the directory entry
var directoryEntry = item.Model.DirectoryEntries[index];
if (directoryEntry == null)
return false;
// Get the associated directory item
var directoryItem = Array.Find(item.Model.DirectoryItems, di => di?.FileNameCRC == directoryEntry.FileNameCRC);
if (directoryItem == null)
return false;
// Load the item data
var data = item.ReadFromDataSource((int)directoryEntry.EntryOffset, (int)directoryEntry.EntryLength);
if (data == null)
return false;
// Create the filename
var filename = directoryItem.Name;
// If we have an invalid output directory
if (string.IsNullOrEmpty(outputDirectory))
return false;
// Create the full output path
filename = Path.Combine(outputDirectory, filename ?? $"file{index}");
// Ensure the output directory is created
var directoryName = Path.GetDirectoryName(filename);
if (directoryName != null)
Directory.CreateDirectory(directoryName);
// Try to write the data
try
{
// Open the output file for writing
using (Stream fs = File.OpenWrite(filename))
{
fs.Write(data, 0, data.Length);
}
}
catch
{
return false;
}
return true;
}
}
}

View File

@@ -0,0 +1,40 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.GameEngine
{
/// <summary>
/// RenderWare (https://web.archive.org/web/20070214132346/http://www.renderware.com/) is an API and graphics engine created by Criterion in 1993.
/// It appears that version 4.X was exclusively used by EA internally, with version 3.X being the final public version (https://sigmaco.org/3782-renderware/).
/// It was available to use on many different platforms, with it being particularly useful for the PS2 (https://en.wikipedia.org/wiki/RenderWare).
///
/// Additional resources and documentation:
/// RenderWare interview: https://web.archive.org/web/20031208124348/http://www.homelanfed.com/index.php?id=9856
/// RenderWare V2.1 API reference: http://www.tnlc.com/rw/api/rwdoc.htm
/// RenderWare 2 official docs: https://github.com/electronicarts/RenderWare3Docs
/// RenderWare 3.7 SDK: https://github.com/sigmaco/rwsdk-v37-pc
/// Wikipedia list of RenderWare games: https://en.wikipedia.org/wiki/Category:RenderWare_games
/// </summary>
public class RenderWare : IExecutableCheck<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Found in Redump entries 20138, 55823, and 102493.
bool rwcsegSection = pex.ContainsSection("_rwcseg", exact: true);
// Found in Redump entry 20138.
bool rwdsegSection = pex.ContainsSection("_rwdseg", exact: true);
// TODO: Check if this indicates a specific version, or if these sections are present in multiple.
if (rwcsegSection || rwdsegSection)
return "RenderWare";
return null;
}
}
}

View File

@@ -1,15 +1,17 @@
namespace BurnOutSharp
namespace BinaryObjectScanner.Interfaces
{
internal interface IContentCheck
/// <summary>
/// Check a generic file for protection
/// </summary>
public 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>
/// <param name="includeDebug">True to include debug 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);
string? CheckContents(string file, byte[] fileContent, bool includeDebug);
}
}

View File

@@ -0,0 +1,28 @@
using System.IO;
namespace BinaryObjectScanner.Interfaces
{
/// <summary>
/// Mark a file type as being able to be detected
/// </summary>
public interface IDetectable
{
/// <summary>
/// Check if a file is detected as this file type
/// </summary>
/// <param name="file">Path to the input file</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Detected file or protection type, null on error</returns>
/// <remarks>Ideally, this should just point to the other detect implementation.</remarks>
string? Detect(string file, bool includeDebug);
/// <summary>
/// Check if a stream is detected as this file type
/// </summary>
/// <param name="stream">Stream representing the input file</param>
/// <param name="file">Path to the input file</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Detected file or protection type, null on error</returns>
string? Detect(Stream stream, string file, bool includeDebug);
}
}

View File

@@ -0,0 +1,19 @@
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Interfaces
{
/// <summary>
/// Check an executable for protection
/// </summary>
public interface IExecutableCheck<T> where T : WrapperBase
{
/// <summary>
/// Check a path for protections based on file contents
/// </summary>
/// <param name="file">File to check for protection indicators</param>
/// <param name="exe">Executable representing the read-in file</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>String containing any protections found in the file</returns>
string? CheckExecutable(string file, T exe, bool includeDebug);
}
}

View File

@@ -0,0 +1,30 @@
using System.IO;
namespace BinaryObjectScanner.Interfaces
{
/// <summary>
/// Mark a file type as being able to be extracted
/// </summary>
public interface IExtractable
{
/// <summary>
/// Extract a file to a temporary path, if possible
/// </summary>
/// <param name="file">Path to the input file</param>
/// <param name="outDir">Path to the output directory</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Indicates if the extractable was successfully extracted</returns>
/// <remarks>Ideally, this should just point to the other extract implementation.</remarks>
bool Extract(string file, string outDir, bool includeDebug);
/// <summary>
/// Extract a stream to a temporary path, if possible
/// </summary>
/// <param name="stream">Stream representing the input file</param>
/// <param name="file">Path to the input file</param>
/// <param name="outDir">Path to the output directory</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Indicates if the extractable was successfully extracted</returns>
bool Extract(Stream? stream, string file, string outDir, bool includeDebug);
}
}

View File

@@ -0,0 +1,20 @@
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Interfaces
{
/// <summary>
/// Mark an executable type as being able to be extracted
/// </summary>
public interface IExtractableExecutable<T> : IExecutableCheck<T> where T : WrapperBase
{
/// <summary>
/// Extract an Executable to a path, if possible
/// </summary>
/// <param name="file">Path to the input file</param>
/// <param name="exe">Executable representing the read-in file</param>
/// <param name="outDir">Path to the output directory</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Path to extracted files, null on error</returns>
bool Extract(string file, T exe, string outDir, bool includeDebug);
}
}

View File

@@ -1,22 +1,28 @@
using System.Collections.Generic;
namespace BurnOutSharp
namespace BinaryObjectScanner.Interfaces
{
internal interface IPathCheck
/// <summary>
/// Check a file or directory path for protection
/// </summary>
/// <remarks>
/// These checks rely primarily on filenames and paths, not file contents
/// </remarks>
public 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);
/// <remarks>This can do some limited content checking as well, but it's suggested to use a content check instead, if possible</remarks>
IEnumerable<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);
/// <remarks>This can do some limited content checking as well, but it's suggested to use a content check instead, if possible</remarks>
string? CheckFilePath(string path);
}
}

View File

@@ -0,0 +1,38 @@
namespace BinaryObjectScanner
{
/// <summary>
/// Scanning options
/// </summary>
public class Options
{
/// <summary>
/// Determines whether archives are decompressed and scanned
/// </summary>
public bool ScanArchives { get; set; }
/// <summary>
/// Determines if content matches are used or not
/// </summary>
public bool ScanContents { get; set; }
/// <summary>
/// Determines if game engines are counted as detected protections or not
/// </summary>
public bool ScanGameEngines { get; set; }
/// <summary>
/// Determines if packers are counted as detected protections or not
/// </summary>
public bool ScanPackers { get; set; }
/// <summary>
/// Determines if path matches are used or not
/// </summary>
public bool ScanPaths { get; set; }
/// <summary>
/// Determines if debug information is output or not
/// </summary>
public bool IncludeDebug { get; set; }
}
}

View File

@@ -0,0 +1,647 @@
using System.Collections.Generic;
using System.Text;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
public class ASPack : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the .aspack section, if it exists
bool aspackSection = pex.ContainsSection(".aspack", exact: true);
if (aspackSection)
return "ASPack 2.29";
// TODO: Re-enable all Entry Point checks after implementing
// Use the entry point data, if it exists
// if (pex.EntryPointRaw != null)
// {
// var matchers = GenerateMatchers();
// var match = MatchUtil.GetFirstMatch(file, pex.EntryPointRaw, matchers, includeDebug);
// if (!string.IsNullOrEmpty(match))
// return match;
// }
// Get the .adata* section, if it exists
var adataSection = pex.GetFirstSection(".adata", exact: false);
if (adataSection?.Name != null)
{
var adataSectionRaw = pex.GetFirstSectionData(Encoding.UTF8.GetString(adataSection.Name));
if (adataSectionRaw != null)
{
var matchers = GenerateMatchers();
var match = MatchUtil.GetFirstMatch(file, adataSectionRaw, matchers, includeDebug);
if (!string.IsNullOrEmpty(match))
return match;
}
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
/// <summary>
/// Generate the set of matchers used for each section
/// </summary>
/// <returns></returns>
private List<ContentMatchSet> GenerateMatchers()
{
return new List<ContentMatchSet>
{
#region No Wildcards (Long)
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x92, 0x1A, 0x44, 0x00, 0xB8, 0x8C, 0x1A,
0x44, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0xCD, 0x1D,
0x44, 0x00, 0x89, 0x85, 0xD9, 0x1D, 0x44, 0x00,
0x80, 0xBD, 0xC4, 0x1D, 0x44,
}, "ASPack 1.00b -> Solodovnikov Alexey"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0xD2, 0x2A, 0x44, 0x00, 0xB8, 0xCC, 0x2A,
0x44, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0xA5, 0x2E,
0x44, 0x00, 0x89, 0x85, 0xB1, 0x2E, 0x44, 0x00,
0x80, 0xBD, 0x9C, 0x2E, 0x44, 0x00, 0x00, 0x75,
0x15, 0xFE, 0x85, 0x9C, 0x2E, 0x44, 0x00, 0xE8,
0x1D, 0x00, 0x00, 0x00, 0xE8, 0xE4, 0x01, 0x00,
0x00, 0xE8, 0x7A, 0x02, 0x00, 0x00, 0x8B, 0x85,
0x9D, 0x2E, 0x44, 0x00, 0x03, 0x85, 0xB1, 0x2E,
0x44, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
}, "ASPack 1.01b"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0xD2, 0x2A, 0x44, 0x00, 0xB8, 0xCC, 0x2A,
0x44, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0xA5, 0x2E,
0x44, 0x00, 0x89, 0x85, 0xB1, 0x2E, 0x44, 0x00,
0x80, 0xBD, 0x9C, 0x2E, 0x44
}, "ASPack 1.01b -> Solodovnikov Alexey"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x96, 0x78, 0x43, 0x00, 0xB8, 0x90, 0x78,
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x7D, 0x7C,
0x43, 0x00, 0x89, 0x85, 0x89, 0x7C, 0x43, 0x00,
0x80, 0xBD, 0x74, 0x7C, 0x43, 0x00, 0x00, 0x75,
0x15, 0xFE, 0x85, 0x74, 0x7C, 0x43, 0x00, 0xE8,
0x1D, 0x00, 0x00, 0x00, 0xE8, 0xF7, 0x01, 0x00,
0x00, 0xE8, 0x8E, 0x02, 0x00, 0x00, 0x8B, 0x85,
0x75, 0x7C, 0x43, 0x00, 0x03, 0x85, 0x89, 0x7C,
0x43, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
}, "ASPack 1.02b"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x96, 0x78, 0x43, 0x00, 0xB8, 0x90, 0x78,
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x7D, 0x7C,
0x43, 0x00, 0x89, 0x85, 0x89, 0x7C, 0x43, 0x00,
0x80, 0xBD, 0x74, 0x7C, 0x43, 0x00, 0x00, 0x75,
0x15, 0xFE, 0x85, 0x74, 0x7C, 0x43
}, "ASPack 1.02b -> Solodovnikov Alexey"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x8A, 0x1C, 0x40, 0x00, 0xB9, 0x9E, 0x00,
0x00, 0x00, 0x8D, 0xBD, 0x4C, 0x23, 0x40, 0x00,
0x8B, 0xF7, 0x33
}, "ASPack 1.02b"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x96, 0x78, 0x43, 0x00, 0xB8, 0x90, 0x78,
0x43, 0x00, 0x03, 0xC5
}, "ASPack 1.02b"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0xAE, 0x98, 0x43, 0x00, 0xB8, 0xA8, 0x98,
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x18, 0x9D,
0x43, 0x00, 0x89, 0x85, 0x24, 0x9D, 0x43, 0x00,
0x80, 0xBD, 0x0E, 0x9D, 0x43
}, "ASPack 1.03b -> Solodovnikov Alexey"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0xCE, 0x3A, 0x44, 0x00, 0xB8, 0xC8, 0x3A,
0x44, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0xB5, 0x3E,
0x44, 0x00, 0x89, 0x85, 0xC1, 0x3E, 0x44, 0x00,
0x80, 0xBD, 0xAC, 0x3E, 0x44
}, "ASPack 1.05b -> Solodovnikov Alexey"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0xEA, 0xA8, 0x43, 0x00, 0xB8, 0xE4, 0xA8,
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x78, 0xAD,
0x43, 0x00, 0x89, 0x85, 0x84, 0xAD, 0x43, 0x00,
0x80, 0xBD, 0x6E, 0xAD, 0x43, 0x00, 0x00, 0x75,
0x15, 0xFE, 0x85, 0x6E, 0xAD, 0x43, 0x00, 0xE8,
0x1D, 0x00, 0x00, 0x00, 0xE8, 0x73, 0x02, 0x00,
0x00, 0xE8, 0x0A, 0x03, 0x00, 0x00, 0x8B, 0x85,
0x70, 0xAD, 0x43, 0x00, 0x03, 0x85, 0x84, 0xAD,
0x43, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
}, "ASPack 1.06.01b (DLL)"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0xEA, 0xA8, 0x43, 0x00, 0xB8, 0xE4, 0xA8,
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x78, 0xAD,
0x43, 0x00, 0x89, 0x85, 0x84, 0xAD, 0x43, 0x00,
0x80, 0xBD, 0x6E, 0xAD, 0x43, 0x00, 0x00, 0x75,
0x15, 0xFE, 0x85, 0x6E, 0xAD, 0x43
}, "ASPack 1.06.01b -> Solodovnikov Alexey"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x3E, 0xD9, 0x43, 0x00, 0xB8, 0x38, 0xD9,
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x0B, 0xDE,
0x43, 0x00, 0x89, 0x85, 0x17, 0xDE, 0x43, 0x00,
0x80, 0xBD, 0x01, 0xDE, 0x43, 0x00, 0x00, 0x75,
0x15, 0xFE, 0x85, 0x01, 0xDE, 0x43, 0x00, 0xE8,
0x1D, 0x00, 0x00, 0x00, 0xE8, 0x79, 0x02, 0x00,
0x00, 0xE8, 0x12, 0x03, 0x00, 0x00, 0x8B, 0x85,
0x03, 0xDE, 0x43, 0x00, 0x03, 0x85, 0x17, 0xDE,
0x43, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
}, "ASPack 1.07b (DLL)"),
new(new byte?[]
{
0x60, 0xEB, 0x03, 0x5D, 0xFF, 0xE5, 0xE8, 0xF8,
0xFF, 0xFF, 0xFF, 0x81, 0xED, 0x1B, 0x6A, 0x44,
0x00, 0xBB, 0x10, 0x6A, 0x44, 0x00, 0x03, 0xDD,
0x2B, 0x9D, 0x2A
}, "ASPack 1.08"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x0A, 0x4A, 0x44, 0x00, 0xBB, 0x04, 0x4A,
0x44, 0x00, 0x03, 0xDD, 0x2B, 0x9D, 0xB1, 0x50,
0x44, 0x00, 0x83, 0xBD, 0xAC, 0x50, 0x44, 0x00,
0x00, 0x89, 0x9D, 0xBB, 0x4E, 0x44, 0x00, 0x0F,
0x85, 0x17, 0x05, 0x00, 0x00, 0x8D, 0x85, 0xD1,
0x50, 0x44, 0x00, 0x50, 0xFF, 0x95, 0x94, 0x51,
0x44, 0x00, 0x89, 0x85, 0xCD, 0x50, 0x44, 0x00,
0x8B, 0xF8, 0x8D, 0x9D, 0xDE, 0x50, 0x44, 0x00,
0x53, 0x50, 0xFF, 0x95, 0x90, 0x51, 0x44, 0x00
}, "ASPack 1.08.03"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x0A, 0x4A, 0x44, 0x00, 0xBB, 0x04, 0x4A,
0x44, 0x00, 0x03, 0xDD, 0x2B, 0x9D, 0xB1, 0x50,
0x44, 0x00, 0x83, 0xBD, 0xAC, 0x50, 0x44, 0x00,
0x00, 0x89, 0x9D, 0xBB, 0x4E
}, "ASPack 1.08.03"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x0A, 0x4A, 0x44, 0x00, 0xBB, 0x04, 0x4A,
0x44, 0x00, 0x03, 0xDD
}, "ASPack 1.08.03"),
new(new byte?[]
{
0x60, 0xE8, 0x72, 0x05, 0x00, 0x00, 0xEB, 0x33,
0x87, 0xDB, 0x90, 0x00
}, "ASPack 2.00.01"),
new(new byte?[]
{
0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9, 0xEB,
0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01, 0x00,
0x00, 0x00, 0xEB, 0x5D, 0xBB, 0xED, 0xFF, 0xFF,
0xFF, 0x03, 0xDD, 0x81, 0xEB
}, "ASPack 2.1"),
new(new byte?[]
{
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xEB, 0x09,
0x5D, 0x55, 0x81, 0xED, 0x39, 0x39, 0x44, 0x00,
0xC3, 0xE9, 0x3D, 0x04, 0x00, 0x00
}, "ASPack 2.11b"),
new(new byte?[]
{
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xEB, 0x09,
0x5D, 0x55
}, "ASPack 2.11b"),
new(new byte?[]
{
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xEB, 0x09,
0x5D, 0x55, 0x81, 0xED, 0x39, 0x39, 0x44, 0x00,
0xC3, 0xE9, 0x59, 0x04, 0x00, 0x00
}, "ASPack 2.11c"),
new(new byte?[]
{
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xCD, 0x20,
0xE8, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x2B, 0xC9,
0x58, 0x74, 0x02
}, "ASPack 2.11d"),
new(new byte?[]
{
0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9, 0xEB,
0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01
}, "ASPack 2.12"),
#endregion
#region Wildcards (Long)
new(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, 0x3E, 0xD9, 0x43, null, 0xB8, 0x38, null,
null, null, 0x03, 0xC5, 0x2B, 0x85, 0x0B, 0xDE,
0x43, null, 0x89, 0x85, 0x17, 0xDE, 0x43, null,
0x80, 0xBD, 0x01, 0xDE, 0x43, null, null, 0x75,
0x15, 0xFE, 0x85, 0x01, 0xDE, 0x43, null, 0xE8,
0x1D, null, null, null, 0xE8, 0x79, 0x02, null,
null, 0xE8, 0x12, 0x03, null, null, 0x8B, 0x85,
0x03, 0xDE, 0x43, null, 0x03, 0x85, 0x17, 0xDE,
0x43, null, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
}, "ASPack 1.00b"),
new(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, 0xD2, 0x2A, 0x44, null, 0xB8, 0xCC, 0x2A,
0x44, null, 0x03, 0xC5, 0x2B, 0x85, 0xA5, 0x2E,
0x44, null, 0x89, 0x85, 0xB1, 0x2E, 0x44, null,
0x80, 0xBD, 0x9C, 0x2E, 0x44
}, "ASPack 1.01b"),
new(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, 0xCE, 0x3A, 0x44, null, 0xB8, 0xC8, 0x3A,
0x44, null, 0x03, 0xC5, 0x2B, 0x85, 0xB5, 0x3E,
0x44, null, 0x89, 0x85, 0xC1, 0x3E, 0x44, null,
0x80, 0xBD, 0xAC, 0x3E, 0x44
}, "ASPack 1.01b"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x3E, 0xD9, 0x43, 0x00, 0xB8, 0x38, null,
null, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x0B, 0xDE,
0x43, 0x00, 0x89, 0x85, 0x17, 0xDE, 0x43, 0x00,
0x80, 0xBD, 0x01, 0xDE, 0x43, 0x00, 0x00, 0x75,
0x15, 0xFE, 0x85, 0x01, 0xDE, 0x43, 0x00, 0xE8,
0x1D, 0x00, 0x00, 0x00, 0xE8, 0x79, 0x02, 0x00,
0x00, 0xE8, 0x12, 0x03, 0x00, 0x00, 0x8B, 0x85,
0x03, 0xDE, 0x43, 0x00, 0x03, 0x85, 0x17, 0xDE,
0x43, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
}, "ASPack 1.02a -> Solodovnikov Alexey"),
new(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, 0x06, null, null, null, 0x64, 0xA0, 0x23
}, "ASPack 1.02a"),
new(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, 0x96, 0x78, 0x43, null, 0xB8, 0x90, 0x78,
0x43, null, 0x03, 0xC5, 0x2B, 0x85, 0x7D, 0x7C,
0x43, null, 0x89, 0x85, 0x89, 0x7C, 0x43, null,
0x80, 0xBD, 0x74, 0x7C, 0x43
}, "ASPack 1.02b"),
new(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, 0xAE, 0x98, 0x43, null, 0xB8, 0xA8, 0x98,
0x43, null, 0x03, 0xC5, 0x2B, 0x85, 0x18, 0x9D,
0x43, null, 0x89, 0x85, 0x24, 0x9D, 0x43, null,
0x80, 0xBD, 0x0E, 0x9D, 0x43
}, "ASPack 1.03b"),
new(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, null, null, null, null, 0xE8, 0x0D, null,
null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, 0x58
}, "ASPack 1.03b"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, null, null, null, 0x00, 0xB8, null, null,
null, 0x00, 0x03, 0xC5, 0x2B, 0x85, null, 0x12,
0x9D, null, 0x89, 0x85, 0x1E, 0x9D, null, 0x00,
0x80, 0xBD, 0x08, 0x9D, null, 0x00, 0x00
}, "ASPack 1.04b -> Solodovnikov Alexey"),
new(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, null, null, null, null, 0xB8, null, null,
null, null, 0x03, 0xC5, 0x2B, 0x85, null, 0x12,
0x9D, null, 0x89, 0x85, 0x1E, 0x9D, null, null,
0x80, 0xBD, 0x08, 0x9D
}, "ASPack 1.04b"),
new(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, null, null, null, null, 0xB8, null, null,
null, null, 0x03, 0xC5, 0x2B, 0x85, null, 0x0B,
0xDE, null, 0x89, 0x85, 0x17, 0xDE, null, null,
0x80, 0xBD, 0x01, 0xDE
}, "ASPack 1.04b"),
new(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, 0xEA, 0xA8, 0x43, null, 0xB8, 0xE4, 0xA8,
0x43, null, 0x03, 0xC5, 0x2B, 0x85, 0x78, 0xAD,
0x43, null, 0x89, 0x85, 0x84, 0xAD, 0x43, null,
0x80, 0xBD, 0x6E, 0xAD, 0x43
}, "ASPack 1.06.1b"),
new(new byte?[]
{
0x90, 0x61, 0xBE, null, null, null, null, 0x8D,
0xBE, null, null, null, null, 0x57, 0x83, 0xCD,
0xFF
}, "ASPack 1.06.1b"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, null,
null, null, null, null, null, 0xB8, null, null,
null, null, 0x03, 0xC5
}, "ASPack 1.07b"),
new(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, null, null, null, null, 0x60, 0xE8, 0x2B,
0x03, 0x00, 0x00
}, "ASPack 1.07b"),
new(new byte?[]
{
0x60, 0xEB, 0x0A, 0x5D, 0xEB, 0x02, 0xFF, 0x25,
0x45, 0xFF, 0xE5, 0xE8, 0xE9, 0xE8, 0xF1, 0xFF,
0xFF, 0xFF, 0xE9, 0x81, null, null, null, 0x44,
0x00, 0xBB, 0x10, null, 0x44, 0x00, 0x03, 0xDD,
0x2B, 0x9D
}, "ASPack 1.08.01"),
new(new byte?[]
{
0x60, 0xEB, 0x0A, 0x5D, 0xEB, 0x02, 0xFF, 0x25,
0x45, 0xFF, 0xE5, 0xE8, 0xE9, 0xE8, 0xF1, 0xFF,
0xFF, 0xFF, 0xE9, 0x81, null, null, null, 0x44,
null, 0xBB, 0x10, null, 0x44, null, 0x03, 0xDD,
0x2B, 0x9D
}, "ASPack 1.08.01"),
new(new byte?[]
{
0x60, 0xEB, 0x0A, 0x5D, 0xEB, 0x02, 0xFF, 0x25,
0x45, 0xFF, 0xE5, 0xE8, 0xE9, 0xE8, 0xF1, 0xFF,
0xFF, 0xFF, 0xE9, 0x81, 0xED, 0x23, 0x6A, 0x44,
0x00, 0xBB, 0x10, null, 0x44, 0x00, 0x03, 0xDD,
0x2B, 0x9D, 0x72
}, "ASPack 1.08.02"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, null,
null, null, null, null, null, 0xBB, null, null,
null, null, 0x03, 0xDD, 0x2B, 0x9D, 0xB1, 0x50,
0x44, 0x00, 0x83, 0xBD, 0xAC, 0x50, 0x44, 0x00,
0x00, 0x89, 0x9D, 0xBB, 0x4E
}, "ASPack 1.08.03"),
new(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, null,
null, null, null, null, null, 0xBB, null, null,
null, null, 0x03, 0xDD
}, "ASPack 1.08.03"),
new(new byte?[]
{
0x55, 0x57, 0x51, 0x53, 0xE8, null, null, null,
null, 0x5D, 0x8B, 0xC5, 0x81, 0xED, null, null,
null, null, 0x2B, 0x85, null, null, null, null,
0x83, 0xE8, 0x09, 0x89, 0x85, null, null, null,
null, 0x0F, 0xB6
}, "ASPack 1.08.03"),
new(new byte?[]
{
0x60, 0xE9, null, null, null, null, 0xEF, 0x40,
0x03, 0xA7, 0x07, 0x8F, 0x07, 0x1C, 0x37, 0x5D,
0x43, 0xA7, 0x04, 0xB9, 0x2C, 0x3A
}, "ASPack 1.08.x"),
new(new byte?[]
{
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xEB, 0x09,
0x5D, 0x55, 0x81, 0xED, 0x39, 0x39, 0x44, 0x00,
0xC3, 0xE9, null, 0x04, 0x00, 0x00
}, "ASPack 2.11.x -> Alexey Solodovnikov"),
new(new byte?[]
{
null, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9, 0xEB,
0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01
}, "ASPack 2.12 (without Poly) -> Solodovnikov Alexey"),
new(new byte?[]
{
null, 0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9,
0xEB, 0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01,
0x00, 0x00, 0x00, 0xEB, 0x5D, 0xBB, 0xEC, 0xFF,
0xFF, 0xFF, 0x03, 0xDD, 0x81, 0xEB, 0x00, null,
null, 0x00, 0x83, 0xBD, 0x22, 0x04, 0x00, 0x00,
0x00, 0x89, 0x9D, 0x22, 0x04, 0x00, 0x00, 0x0F,
0x85, 0x65, 0x03, 0x00, 0x00, 0x8D, 0x85, 0x2E,
0x04, 0x00, 0x00, 0x50, 0xFF, 0x95, 0x4C, 0x0F,
0x00, 0x00, 0x89, 0x85, 0x26, 0x04, 0x00, 0x00,
0x8B, 0xF8, 0x8D, 0x5D, 0x5E, 0x53, 0x50, 0xFF,
0x95, 0x48, 0x0F, 0x00, 0x00, 0x89, 0x85, 0x4C,
0x05, 0x00, 0x00, 0x8D, 0x5D, 0x6B, 0x53, 0x57,
0xFF, 0x95, 0x48, 0x0F
}, "ASPack 2.12b -> Solodovnikov Alexey"),
new(new byte?[]
{
0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9, 0xEB,
0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01, 0x00,
0x00, 0x00, 0xEB, 0x5D, 0xBB, 0xED, 0xFF, 0xFF,
0xFF, 0x03, 0xDD, null, null, null, null, null,
null, 0x83, 0xBD, 0x7D, 0x04, 0x00, 0x00, 0x00,
0x89, 0x9D, 0x7D, 0x04, 0x00, 0x00, 0x0F, 0x85,
0xC0, 0x03, 0x00, 0x00, 0x8D, 0x85, 0x89, 0x04,
0x00, 0x00, 0x50, 0xFF, 0x95, 0x09, 0x0F, 0x00,
0x00, 0x89, 0x85, 0x81, 0x04, 0x00, 0x00, 0x8B,
0xF0, 0x8D, 0x7D, 0x51, 0x57, 0x56, 0xFF, 0x95,
0x05, 0x0F, 0x00, 0x00, 0xAB, 0xB0, 0x00, 0xAE,
0x75, 0xFD, 0x38, 0x07, 0x75, 0xEE, 0x8D, 0x45,
0x7A, 0xFF, 0xE0, 0x56, 0x69, 0x72, 0x74, 0x75,
0x61, 0x6C, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x00,
0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6C, 0x46,
0x72, 0x65, 0x65, 0x00, 0x56, 0x69, 0x72, 0x74,
0x75, 0x61, 0x6C, 0x50, 0x72, 0x6F, 0x74, 0x65,
0x63, 0x74, 0x00, 0x00, 0x8B, 0x9D, 0x8D, 0x05,
0x00, 0x00, 0x0B, 0xDB, 0x74, 0x0A, 0x8B, 0x03,
0x87, 0x85, 0x91, 0x05, 0x00, 0x00, 0x89, 0x03,
0x8D, 0xB5, 0xBD, 0x05, 0x00, 0x00, 0x83, 0x3E,
0x00, 0x0F, 0x84, 0x15, 0x01, 0x00, 0x00, 0x6A,
0x04, 0x68, 0x00, 0x10, 0x00, 0x00, 0x68, 0x00,
0x18, 0x00, 0x00, 0x6A, 0x00, 0xFF, 0x55, 0x51,
0x89, 0x85, 0x53, 0x01, 0x00, 0x00, 0x8B, 0x46,
0x04, 0x05, 0x0E, 0x01, 0x00, 0x00, 0x6A, 0x04,
0x68, 0x00, 0x10, 0x00, 0x00, 0x50, 0x6A, 0x00,
0xFF, 0x55, 0x51, 0x89, 0x85, 0x4F, 0x01, 0x00,
0x00, 0x56, 0x8B, 0x1E, 0x03, 0x9D, 0x7D, 0x04,
0x00, 0x00, 0xFF, 0xB5, 0x53, 0x01, 0x00, 0x00,
0xFF, 0x76, 0x04, 0x50, 0x53, 0xE8, 0x2D, 0x05,
0x00, 0x00, 0xB3, 0x00, 0x80, 0xFB, 0x00, 0x75,
0x5E, 0xFE, 0x85, 0xE9, 0x00, 0x00, 0x00, 0x8B,
0x3E, 0x03, 0xBD, 0x7D, 0x04, 0x00, 0x00, 0xFF,
0x37, 0xC6, 0x07, 0xC3, 0xFF, 0xD7, 0x8F, 0x07,
0x50, 0x51, 0x56, 0x53, 0x8B, 0xC8, 0x83, 0xE9,
0x06, 0x8B, 0xB5, 0x4F, 0x01, 0x00, 0x00, 0x33,
0xDB, 0x0B, 0xC9, 0x74, 0x2E, 0x78, 0x2C, 0xAC,
0x3C, 0xE8, 0x74, 0x0A, 0xEB, 0x00, 0x3C, 0xE9,
0x74, 0x04, 0x43, 0x49, 0xEB, 0xEB, 0x8B, 0x06,
0xEB, 0x00, null, null, null, 0x75, 0xF3, 0x24,
0x00, 0xC1, 0xC0, 0x18, 0x2B, 0xC3, 0x89, 0x06,
0x83, 0xC3, 0x05, 0x83, 0xC6, 0x04, 0x83, 0xE9,
0x05, 0xEB, 0xCE, 0x5B, 0x5E, 0x59, 0x58, 0xEB,
0x08
}, "ASPack 2.2 -> Alexey Solodovnikov & StarForce * 2009408"),
new(new byte?[]
{
null, 0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9,
0xEB, 0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01,
0x00, 0x00, 0x00, 0xEB, 0x5D, 0xBB, 0xEC, 0xFF,
0xFF, 0xFF, 0x03, 0xDD, 0x81, 0xEB, 0x00, 0x40,
0x1C, 0x00
}, "ASPack 2.x (without Poly) -> Solodovnikov Alexey"),
#endregion
#region 2.xx (Long)
new(new byte?[]
{
0xA8, 0x03, 0x00, 0x00, 0x61, 0x75, 0x08, 0xB8,
0x01, 0x00, 0x00, 0x00, 0xC2, 0x0C, 0x00, 0x68,
0x00, 0x00, 0x00, 0x00, 0xC3, 0x8B, 0x85, 0x26,
0x04, 0x00, 0x00, 0x8D, 0x8D, 0x3B, 0x04, 0x00,
0x00, 0x51, 0x50, 0xFF, 0x95
}, "ASPack 2.xx"),
new(new byte?[]
{
0xA8, 0x03, null, null, 0x61, 0x75, 0x08, 0xB8,
0x01, null, null, null, 0xC2, 0x0C, null, 0x68,
null, null, null, null, 0xC3, 0x8B, 0x85, 0x26,
0x04, null, null, 0x8D, 0x8D, 0x3B, 0x04, null,
null, 0x51, 0x50, 0xFF, 0x95
}, "ASPack 2.xx"),
#endregion
#region Short
new(new byte?[] { 0x75, 0x00, 0xE9 }, "ASPack 1.05b"),
new(new byte?[] { 0x90, 0x90, 0x90, 0x75, 0x00, 0xE9 }, "ASPack 1.06.1b"),
new(new byte?[] { 0x90, 0x90, 0x75, 0x00, 0xE9 }, "ASPack 1.06.1b"),
new(new byte?[] { 0x90, 0x75, 0x00, 0xE9 }, "ASPack 1.06.1b"),
new(new byte?[] { 0x90, 0x90, 0x90, 0x75, null, 0xE9 }, "ASPack 1.07b"),
new(new byte?[] { 0x90, 0x90, 0x75, null, 0xE9 }, "ASPack 1.07b"),
new(new byte?[] { 0x90, 0x75, null, 0xE9 }, "ASPack 1.07b"),
new(new byte?[] { 0x90, 0x90, 0x90, 0x75, 0x01, 0x90, 0xE9 }, "ASPack 1.08"),
new(new byte?[] { 0x90, 0x90, 0x90, 0x75, 0x01, 0xFF, 0xE9 }, "ASPack 1.08"),
new(new byte?[] { 0x90, 0x90, 0x75, 0x01, 0xFF, 0xE9 }, "ASPack 1.08"),
new(new byte?[] { 0x90, 0x75, 0x01, 0xFF, 0xE9 }, "ASPack 1.08"),
new(new byte?[] { 0x90, 0x90, 0x90, 0x75, null, 0x90, 0xE9 }, "ASPack 1.08.01"),
new(new byte?[] { 0x90, 0x90, 0x75, null, 0x90, 0xE9 }, "ASPack 1.08.01"),
new(new byte?[] { 0x90, 0x75, null, 0x90, 0xE9 }, "ASPack 1.08.01"),
new(new byte?[] { 0x90, 0x90, 0x75, 0x01, 0x90, 0xE9 }, "ASPack 1.08.02"),
new(new byte?[] { 0x90, 0x75, 0x01, 0x90, 0xE9 }, "ASPack 1.08.02"),
new(new byte?[] { 0x60, 0xE8, 0x41, 0x06, 0x00, 0x00, 0xEB, 0x41 }, "ASPack 1.08.04"),
new(new byte?[] { 0x60, 0xE8, null, null, null, null, 0xEB }, "ASPack 1.08.04"),
new(new byte?[] { 0x60, 0xE8, 0x70, 0x05, 0x00, 0x00, 0xEB, 0x4C }, "ASPack 2.00.00"),
new(new byte?[] { 0x60, 0xE8, 0x48, 0x11, 0x00, 0x00, 0xC3, 0x83 }, "ASPack 2.00.00"),
new(new byte?[] { 0x60, 0xE8, 0x72, 0x05, 0x00, 0x00, 0xEB, 0x4C }, "ASPack 2.00.01"),
new(new byte?[] { 0x60, 0xE8, null, 0x05, 0x00, 0x00, 0xEB, 0x4C }, "ASPack 2.00.x -> Alexey Solodovnikov"),
new(new byte?[] { 0x60, 0xE9, 0x3D, 0x04, 0x00, 0x00 }, "ASPack 2.11"),
new(new byte?[] { 0x60, 0xE8, 0xF9, 0x11, 0x00, 0x00, 0xC3, 0x83 }, "ASPack 2.11"),
new(new byte?[] { 0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81, 0xED }, "ASPack 1.02b/1.08.03"),
#endregion
};
}
}
}

View File

@@ -0,0 +1,35 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
// TODO: Verify that all versions are detected
public class AdvancedInstaller : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the .rdata section strings, if they exist
var strs = pex.GetFirstSectionStrings(".rdata");
if (strs != null)
{
if (strs.Exists(s => s.Contains("Software\\Caphyon\\Advanced Installer")))
return "Caphyon Advanced Installer";
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
}
}

View File

@@ -0,0 +1,56 @@
using System;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// Created by IndigoRose (creators of Setup Factory), primarily to be used to create autorun menus for various media.
// Official website: https://www.autoplay.org/
// TODO: Add extraction
public class AutoPlayMediaStudio : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Known to detect versions 5.0.0.3 - 8.1.0.0
var name = pex.ProductName;
if (name?.StartsWith("AutoPlay Media Studio", StringComparison.OrdinalIgnoreCase) == true)
return $"AutoPlay Media Studio {GetVersion(pex)}";
// Currently too vague, may be re-enabled in the future
/*
name = Utilities.GetLegalCopyright(pex);
if (name?.StartsWith("Runtime Engine", StringComparison.OrdinalIgnoreCase) == true)
return $"AutoPlay Media Studio {GetVersion(pex)}";
*/
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
private string GetVersion(PortableExecutable pex)
{
// Check the product version explicitly
var version = pex.ProductVersion;
if (!string.IsNullOrEmpty(version))
return version!;
// Check the internal versions
version = pex.GetInternalVersion();
if (!string.IsNullOrEmpty(version))
return version!;
return "(Unknown Version)";
}
}
}

View File

@@ -0,0 +1,150 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Compression.zlib;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// 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
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class CExe : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// If there are exactly 2 resources with type 99
if (pex.FindResourceByNamedType("99, ").Count() == 2)
return "CExe";
if (pex.StubExecutableData != null)
{
var matchers = new List<ContentMatchSet>
{
new(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
}, "CExe")
};
var match = MatchUtil.GetFirstMatch(file, pex.StubExecutableData, matchers, includeDebug);
if (!string.IsNullOrEmpty(match))
return match;
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
try
{
// Get the first resource of type 99 with index 2
var payload = pex.FindResourceByNamedType("99, 2").FirstOrDefault();
if (payload == null || payload.Length == 0)
return false;
// Determine which compression was used
bool zlib = pex.FindResourceByNamedType("99, 1").Any();
// Create the output data buffer
var data = new byte[0];
// If we had the decompression DLL included, it's zlib
if (zlib)
{
try
{
// Inflate the data into the buffer
var zstream = new ZLib.z_stream_s();
data = new byte[payload.Length * 4];
unsafe
{
fixed (byte* payloadPtr = payload)
fixed (byte* dataPtr = data)
{
zstream.next_in = payloadPtr;
zstream.avail_in = (uint)payload.Length;
zstream.total_in = (uint)payload.Length;
zstream.next_out = dataPtr;
zstream.avail_out = (uint)data.Length;
zstream.total_out = 0;
ZLib.inflateInit_(zstream, ZLib.zlibVersion(), payload.Length);
int zret = ZLib.inflate(zstream, 1);
ZLib.inflateEnd(zstream);
}
}
// Trim the buffer to the proper size
uint read = zstream.total_out;
#if NETFRAMEWORK
var temp = new byte[read];
Array.Copy(data, 0, temp, 0, read);
data = temp;
#else
data = new ReadOnlySpan<byte>(data, 0, (int)read).ToArray();
#endif
}
catch
{
// Reset the data
data = null;
}
}
// Otherwise, LZ is used
else
{
try
{
data = SabreTools.Compression.LZ.Decompressor.Decompress(payload);
}
catch
{
// Reset the data
data = null;
}
}
// If we have no data
if (data == null)
return false;
// Create the temp filename
string tempFile = string.IsNullOrEmpty(file) ? "temp.sxe" : $"{Path.GetFileNameWithoutExtension(file)}.sxe";
tempFile = Path.Combine(outDir, tempFile);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
// Write the file data to a temp file
var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
tempStream.Write(data, 0, data.Length);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
}
}

View File

@@ -0,0 +1,34 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
public class DotFuscator : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the .text section strings, if they exist
var strs = pex.GetFirstSectionStrings(".text");
if (strs != null)
{
if (strs.Exists(s => s.Contains("DotfuscatorAttribute")))
return "dotFuscator";
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
}
}

View File

@@ -0,0 +1,106 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
using System.Collections.Generic;
using SabreTools.Matching;
using SabreTools.Matching.Content;
namespace BinaryObjectScanner.Packer
{
/// <summary>
/// .NET Reactor is a .NET obfuscator that was original released in 2004. https://web.archive.org/web/20040828162124/http://eziriz.com:80/
/// It is currently still being updated and supported. https://www.eziriz.com/dotnet_reactor.htm
/// While ProtectionID does detect .NET Reactor, it's currently unknown exactly how.
/// It seems to simply check for the string "<PrivateImplementationDetails>" in specific, and currently unknown, conditions but appears to be prone to false positives.
/// A "Demo/Nag Screen" version is available for free, and may be able to be used to make samples to improve detections. https://www.eziriz.com/reactor_download.htm
///
/// Resource that could be useful for extraction: https://github.com/SychicBoy/NETReactorSlayer
/// </summary>
public class DotNetReactor : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// TODO: Detect version
// TODO: Further refine checks using https://github.com/horsicq/Detect-It-Easy/blob/075a70b1484d1d84d1dc37c86aac16188d5a84e7/db/PE/NetReactor.2.sg and https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the .text section, if it exists
if (pex.ContainsSection(".text"))
{
var textData = pex.GetFirstSectionData(".text");
if (textData != null)
{
var matchers = new List<ContentMatchSet>
{
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
// <PrivateImplementationDetails>{[8]-[4]-[4]-[4]-[12]}
new(new byte?[]
{
0x3C, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65,
0x49, 0x6D, 0x70, 0x6C, 0x65, 0x6D, 0x65, 0x6E,
0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x65,
0x74, 0x61, 0x69, 0x6C, 0x73, 0x3E, 0x7B, null,
null, null, null, null, null, null, null, 0x2D,
null, null, null, null, 0x2D, null, null, null,
null, 0x2D, null, null, null, null, 0x2D, null,
null, null, null, null, null, null, null, null,
null, null, null, 0x7D
}, ".NET Reactor"),
// Modified from the previous detection to detect a presumably newer version of .NET Reactor found in "KalypsoLauncher.dll" version 2.0.4.2.
// TODO: Check if this can/should be made more specific.
// <PrivateImplementationDetails>.RSA
new(new byte?[]
{
0x3C, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65,
0x49, 0x6D, 0x70, 0x6C, 0x65, 0x6D, 0x65, 0x6E,
0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x65,
0x74, 0x61, 0x69, 0x6C, 0x73, 0x3E, 0x00, 0x52,
0x53, 0x41
}, ".NET Reactor"),
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
// 3{.[9].-.[9].-.[9].}
new(new byte?[]
{
0x33, 0x7B, 0x00, null, null, null, null, null,
null, null, null, null, 0x00, 0x2D, 0x00, null,
null, null, null, null, null, null, null, null,
0x00, 0x2D, 0x00, null, null, null, null, null,
null, null, null, null, 0x00, 0x2D, 0x00, null,
null, null, null, null, null, null, null, null,
0x00, 0x7D, 0x00
}, ".NET Reactor (Unconfirmed - Please report to us on GitHub)"),
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
// <Module>{[8]-[4]-[4]-[4]-[12]}
new(new byte?[]
{
0x3C, 0x4D, 0x6F, 0x64, 0x75, 0x6C, 0x65, 0x3E,
0x7B, null, null, null, null, null, null, null,
null, 0x2D, null, null, null, null, 0x2D, null,
null, null, null, 0x2D, null, null, null, null,
0x2D, null, null, null, null, null, null, null,
null, null, null, null, null, 0x7D
}, ".NET Reactor (Unconfirmed - Please report to us on GitHub)")
};
return MatchUtil.GetFirstMatch(file, textData, matchers, includeDebug);
}
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
// TODO: Add extraction
return false;
}
}
}

View File

@@ -0,0 +1,83 @@
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Figure out how to more granularly determine versions like PiD
// TODO: Detect 3.15 and up (maybe looking for `Metamorphism`)
// TODO: Add extraction
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class EXEStealth : IContentCheck, IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckContents(string file, byte[] fileContent, bool includeDebug)
{
// TODO: Obtain a sample to find where this string is in a typical executable
if (includeDebug)
{
var contentMatchSets = new List<ContentMatchSet>
{
// ??[[__[[_ + (char)0x00 + {{ + (char)0x0 + (char)0x00 + {{ + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x0 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + ?;??;??
new(new byte?[]
{
0x3F, 0x3F, 0x5B, 0x5B, 0x5F, 0x5F, 0x5B, 0x5B,
0x5F, 0x00, 0x7B, 0x7B, 0x00, 0x00, 0x7B, 0x7B,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x20, 0x3F, 0x3B, 0x3F, 0x3F, 0x3B, 0x3F,
0x3F
}, "EXE Stealth"),
};
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
}
return null;
}
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// The ExeS/EXES/*mtw sections seem to map to the Import Table
// 2.6/2.51
// `ExeStealth - www.webtoolmaster.com`
// 2.72/2.73
// `Shareware - ExeStealth`
// `www.webtoolmaster.com`
// 2.74
// `Shareware - ExeStealth`
// 2.76
// `ExeStealth V2 Shareware not for public - This text not in registered version - www.webtoolmaster.com`
// Get the ExeS/EXES section, if it exists
bool exesSection = pex.ContainsSection("ExeS", exact: true) || pex.ContainsSection("EXES", exact: true);
if (exesSection)
return "EXE Stealth 2.41-2.75";
// Get the mtw section, if it exists
bool mtwSection = pex.ContainsSection("mtw", exact: true);
if (mtwSection)
return "EXE Stealth 1.1";
// Get the rsrr section, if it exists
bool rsrrSection = pex.ContainsSection("rsrr", exact: true);
if (rsrrSection)
return "EXE Stealth 2.76";
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
}
}

View File

@@ -0,0 +1,93 @@
using System;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
/// <summary>
/// Though not technically a packer, this detection is for any executables that include
/// others in their resources in some uncompressed manner to be used at runtime.
/// </summary>
public class EmbeddedExecutable : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the resources that have an executable signature
if (pex.ResourceData?.Any(kvp => kvp.Value is byte[] ba
#if NET20
&& Extensions.StartsWith(ba, SabreTools.Models.MSDOS.Constants.SignatureBytes)) == true)
#else
&& ba.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes)) == true)
#endif
{
return "Embedded Executable";
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
try
{
// If there are no resources
if (pex.ResourceData == null)
return false;
// Get the resources that have an executable signature
var resources = pex.ResourceData
.Where(kvp => kvp.Value != null && kvp.Value is byte[])
.Select(kvp => kvp.Value as byte[])
#if NET20
.Where(b => b != null && Extensions.StartsWith(b, SabreTools.Models.MSDOS.Constants.SignatureBytes))
#else
.Where(b => b != null && b.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes))
#endif
.ToList();
for (int i = 0; i < resources.Count; i++)
{
try
{
// Get the resource data
var data = resources[i];
if (data == null)
continue;
// Create the temp filename
string tempFile = $"embedded_resource_{i}.bin";
tempFile = Path.Combine(outDir, tempFile);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
// Write the resource data to a temp file
using var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
tempStream?.Write(data, 0, data.Length);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
}
}

View File

@@ -0,0 +1,38 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class GenteeInstaller : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the .data/DATA section strings, if they exist
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
if (strs != null)
{
if (strs.Exists(s => s.Contains("Gentee installer")))
return "Gentee Installer";
if (strs.Exists(s => s.Contains("ginstall.dll")))
return "Gentee Installer";
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// CrackProof is a packer/obfuscator created by Japanese company HyperTech (https://www.hypertech.co.jp/products/windows/).
// It is known to be used along with other DRM, such as Shury2 (Redump entry 97135) and BDL.
// https://www.reddit.com/r/riseofincarnates/comments/m3vbnm/subreddit_revival_does_anyone_still_have_rise_of/
// https://steamcommunity.com/app/310950/discussions/0/4224890554455490819/
// https://github.com/horsicq/Detect-It-Easy/blob/63a1aa8bb23ca02d8a7fd5936db8dbc5c5d52dea/db/PE/HyperTech%20Crackproof.2.sg
public class HyperTechCrackProof : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// This check may be overly limiting, as it excludes the sample provided to DiE (https://github.com/horsicq/Detect-It-Easy/issues/102).
// TODO: Find further samples and invesitgate if the "peC" section is only present on specific versions.
bool peCSection = pex.ContainsSection("peC", exact: true);
bool importTableMatch = Array.Exists(pex.Model.ImportTable?.ImportDirectoryTable ?? [],
idte => idte?.Name == "KeRnEl32.dLl");
if (peCSection && importTableMatch)
return "HyperTech CrackProof";
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
}
}

View File

@@ -0,0 +1,85 @@
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction - https://github.com/dscharrer/InnoExtract
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class InnoSetup : IExecutableCheck<NewExecutable>,
IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, NewExecutable nex, bool includeDebug)
{
// Check for "Inno" in the reserved words
if (nex.Model.Stub?.Header?.Reserved2?[4] == 0x6E49 && nex.Model.Stub?.Header?.Reserved2?[5] == 0x6F6E)
{
string version = GetOldVersion(file, nex);
if (!string.IsNullOrEmpty(version))
return $"Inno Setup {version}";
return "Inno Setup (Unknown Version)";
}
return null;
}
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the .data/DATA section strings, if they exist
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
if (strs != null)
{
var str = strs.Find(s => s.StartsWith("Inno Setup Setup Data"));
if (str != null)
{
return str.Replace("Inno Setup Setup Data", "Inno Setup")
.Replace("(u)", "[Unicode]")
.Replace("(", string.Empty)
.Replace(")", string.Empty)
.Replace("[Unicode]", "(Unicode)");
}
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
private static string GetOldVersion(string file, NewExecutable nex)
{
// Notes:
// Look into `SETUPLDR` in the resident-name table
// Look into `SETUPLDR.EXE` in the nonresident-name table
// TODO: Don't read entire file
// TODO: Only 64 bytes at the end of the file is needed
var data = nex.ReadArbitraryRange();
if (data != null)
{
var matchers = new List<ContentMatchSet>
{
// "rDlPtS02" + (char)0x87 + "eVx"
new(new byte?[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x32, 0x87, 0x65, 0x56, 0x78 }, "1.2.16 or earlier"),
};
return MatchUtil.GetFirstMatch(file, data, matchers, false) ?? "Unknown 1.X";
}
return "Unknown 1.X";
}
}
}

View File

@@ -0,0 +1,46 @@
using System;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction, which may be possible with the current libraries but needs to be investigated further.
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class InstallAnywhere : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
var name= pex.FileDescription;
if (name?.StartsWith("InstallAnywhere Self Extractor", StringComparison.OrdinalIgnoreCase) == true)
return $"InstallAnywhere {GetVersion(pex)}";
name = pex.ProductName;
if (name?.StartsWith("InstallAnywhere", StringComparison.OrdinalIgnoreCase) == true)
return $"InstallAnywhere {GetVersion(pex)}";
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
private string GetVersion(PortableExecutable pex)
{
// Check the internal versions
var version = pex.GetInternalVersion();
if (!string.IsNullOrEmpty(version))
return version!;
return "(Unknown Version)";
}
}
}

View File

@@ -0,0 +1,36 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction - https://github.com/Bioruebe/UniExtract2
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class InstallerVISE : IExtractableExecutable<PortableExecutable>
{
//TODO: Add exact version detection for Windows builds, make sure versions before 3.X are detected as well, and detect the Mac builds.
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the .data/DATA section strings, if they exist
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
if (strs != null)
{
if (strs.Exists(s => s.Contains("ViseMain")))
return "Installer VISE";
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction, seems to primarily use MSZip compression.
public class IntelInstallationFramework : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
var name= pex.FileDescription;
if (name?.Equals("Intel(R) Installation Framework", StringComparison.OrdinalIgnoreCase) == true
|| name?.Equals("Intel Installation Framework", StringComparison.OrdinalIgnoreCase) == true)
{
return $"Intel Installation Framework {pex.GetInternalVersion()}";
}
name = pex.ProductName;
if (name?.Equals("Intel(R) Installation Framework", StringComparison.OrdinalIgnoreCase) == true
|| name?.Equals("Intel Installation Framework", StringComparison.OrdinalIgnoreCase) == true)
{
return $"Intel Installation Framework {pex.GetInternalVersion()}";
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
}
}

View File

@@ -0,0 +1,64 @@
using System;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction, which should be possible with LibMSPackN, but it refuses to extract due to SFX files lacking the typical CAB identifiers.
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class MicrosoftCABSFX : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
var name= pex.InternalName;
if (name?.Equals("Wextract", StringComparison.OrdinalIgnoreCase) == true)
return $"Microsoft CAB SFX {GetVersion(pex)}";
name = pex.OriginalFilename;
if (name?.Equals("WEXTRACT.EXE", StringComparison.OrdinalIgnoreCase) == true)
return $"Microsoft CAB SFX {GetVersion(pex)}";
// Get the .data/DATA section strings, if they exist
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
if (strs != null)
{
if (strs.Exists(s => s.Contains("wextract_cleanup")))
return $"Microsoft CAB SFX {GetVersion(pex)}";
}
// Get the .text section strings, if they exist
strs = pex.GetFirstSectionStrings(".text");
if (strs != null)
{
// This detects a different but similar type of SFX that uses Microsoft CAB files.
// Further research is needed to see if it's just a different version or entirely separate.
if (strs.Exists(s => s.Contains("MSCFu")))
return $"Microsoft CAB SFX {GetVersion(pex)}";
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
private string GetVersion(PortableExecutable pex)
{
// Check the internal versions
var version = pex.GetInternalVersion();
if (!string.IsNullOrEmpty(version))
return $"v{version}";
return string.Empty;
}
}
}

View File

@@ -0,0 +1,38 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
public class NSIS : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
var description = pex.AssemblyDescription;
if (!string.IsNullOrEmpty(description) && description!.StartsWith("Nullsoft Install System"))
return $"NSIS {description.Substring("Nullsoft Install System".Length).Trim()}";
// Get the .data/DATA section strings, if they exist
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
if (strs != null)
{
if (strs.Exists(s => s.Contains("NullsoftInst")))
return "NSIS";
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
}
}

View File

@@ -0,0 +1,44 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
/// <summary>
/// NeoLite (https://web.archive.org/web/20000815214147/http://www.neoworx.com/products/neolite/default.asp) was a packer created by NeoWorx.
/// The most common version appears to be 2.0, with earlier versions existing but with no archived copies available.
/// NeoWorx was acquired by McAfee in October 2001, who seemingly dropped support for NeoLite (https://web.archive.org/web/20020603224725/http://www.mcafee.com/myapps/neoworx/default.asp).
///
/// Additional references and documentation:
/// NeoLite 2.0 evaluation installer: https://web.archive.org/web/20001012061916/http://www.neoworx.com/download/neolte20.exe
/// PEiD scanning definitions that include NeoLite: https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
/// Website listing various packers, including NeoLite: http://protools.narod.ru/packers.htm
/// </summary>
public class NeoLite : IExtractableExecutable<PortableExecutable>
{
// TODO: Find samples of NeoLite 1.X.
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the .neolit section, if it exists.
// TODO: Check if this section is also present in NeoLite 1.X.
bool neolitSection = pex.ContainsSection(".neolit", exact: true);
if (neolitSection)
return "NeoLite";
// If more specific or additional checks are needed, "NeoLite Executable File Compressor" should be present
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
}
}

View File

@@ -0,0 +1,49 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Better version detection - https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
// TODO: Add extraction
public class PECompact : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// 0x4F434550 is "PECO"
if (pex.Model.COFFFileHeader?.PointerToSymbolTable == 0x4F434550)
return "PE Compact v1.x";
// TODO: Get more granular version detection. PiD is somehow able to detect version ranges based
// on the data in the file. This may be related to information in other fields
// Get the pec1 section, if it exists
bool pec1Section = pex.ContainsSection("pec1", exact: true);
if (pec1Section)
return "PE Compact v1.x";
// Get the PEC2 section, if it exists -- TODO: Verify this comment since it's pulling the .text section
var textSection = pex.GetFirstSection(".text", exact: true);
if (textSection != null && textSection.PointerToRelocations == 0x32434550)
{
if (textSection.PointerToLinenumbers != 0)
return $"PE Compact v{textSection.PointerToLinenumbers} (internal version)";
return "PE Compact v2.x (or newer)";
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
}
}

View File

@@ -0,0 +1,32 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class PEtite : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the .petite section, if it exists -- TODO: Is there a version number that can be found?
bool petiteSection = pex.ContainsSection(".petite", exact: true);
if (petiteSection)
return "PEtite";
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
}
}

View File

@@ -0,0 +1,61 @@
using System;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// 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)
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class SetupFactory : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Known to detect versions 7.0.5.1 - 9.1.0.0
var name = pex.LegalCopyright;
if (name?.StartsWith("Setup Engine", StringComparison.OrdinalIgnoreCase) == true)
return $"Setup Factory {GetVersion(pex)}";
name = pex.ProductName;
if (name?.StartsWith("Setup Factory", StringComparison.OrdinalIgnoreCase) == true)
return $"Setup Factory {GetVersion(pex)}";
// Known to detect version 5.0.1 - 6.0.1.3
name = pex.FileDescription;
if (name?.StartsWith("Setup Factory", StringComparison.OrdinalIgnoreCase) == true)
return $"Setup Factory {GetVersion(pex)}";
// Longer version of the check that can be used if false positves become an issue:
// "Setup Factory is a trademark of Indigo Rose Corporation"
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
private string GetVersion(PortableExecutable pex)
{
// Check the product version explicitly
var version = pex.ProductVersion;
if (!string.IsNullOrEmpty(version))
return version!;
// Check the internal versions
version = pex.GetInternalVersion();
if (!string.IsNullOrEmpty(version))
return version!;
return "(Unknown Version)";
}
}
}

View File

@@ -0,0 +1,53 @@
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
public class SevenZipSFX : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the assembly description, if possible
if (pex.AssemblyDescription?.StartsWith("7-Zip Self-extracting Archive") == true)
return $"7-Zip SFX {pex.AssemblyDescription.Substring("7-Zip Self-extracting Archive ".Length)}";
// Get the file description, if it exists
if (pex.FileDescription?.Equals("7z SFX") == true)
return "7-Zip SFX";
if (pex.FileDescription?.Equals("7z Self-Extract Setup") == true)
return "7-Zip SFX";
// Get the original filename, if it exists
if (pex.OriginalFilename?.Equals("7z.sfx.exe") == true)
return "7-Zip SFX";
else if (pex.OriginalFilename?.Equals("7zS.sfx") == true)
return "7-Zip SFX";
// Get the internal name, if it exists
if (pex.InternalName?.Equals("7z.sfx") == true)
return "7-Zip SFX";
else if (pex.InternalName?.Equals("7zS.sfx") == true)
return "7-Zip SFX";
// If any dialog boxes match
if (pex.FindDialogByTitle("7-Zip self-extracting archive").Any())
return "7-Zip SFX";
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
var sevenZip = new FileType.SevenZip();
return sevenZip.Extract(file, outDir, lookForHeader: true, includeDebug);
}
}
}

View File

@@ -0,0 +1,33 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class Shrinker : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the .shrink0 and .shrink2 sections, if they exist -- TODO: Confirm if both are needed or either/or is fine
bool shrink0Section = pex.ContainsSection(".shrink0", true);
bool shrink2Section = pex.ContainsSection(".shrink2", true);
if (shrink0Section || shrink2Section)
return "Shrinker";
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
}
}

View File

@@ -0,0 +1,99 @@
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class UPX : IExtractableExecutable<PortableExecutable>
{
private static readonly Regex _oldUpxVersionMatch = new Regex(@"\$Id: UPX (.*?) Copyright \(C\)", RegexOptions.Compiled);
private static readonly Regex _upxVersionMatch = new Regex(@"^([0-9]\.[0-9]{2})$", RegexOptions.Compiled);
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Check header padding strings
if (pex.HeaderPaddingStrings != null && pex.HeaderPaddingStrings.Count > 0)
{
var match = pex.HeaderPaddingStrings.Find(s => s.Contains("UPX!"));
//if (match != null)
// return "UPX";
match = pex.HeaderPaddingStrings.Find(s => s.StartsWith("$Id: UPX"));
if (match != null)
{
var regexMatch = _oldUpxVersionMatch.Match(match);
if (regexMatch.Success)
return $"UPX {regexMatch.Groups[1].Value}";
else
return "UPX (Unknown Version)";
}
match = pex.HeaderPaddingStrings.Find(s => _upxVersionMatch.IsMatch(s));
if (match != null && pex.HeaderPaddingStrings.Exists(s => s == "UPX!"))
{
var regexMatch = _upxVersionMatch.Match(match);
if (regexMatch.Success)
return $"UPX {regexMatch.Groups[1].Value}";
else
return "UPX (Unknown Version)";
}
else if (match != null && pex.HeaderPaddingStrings.Exists(s => s == "NOS "))
{
var regexMatch = _upxVersionMatch.Match(match);
if (regexMatch.Success)
return $"UPX (NOS Variant) {regexMatch.Groups[1].Value}";
else
return "UPX (NOS Variant) (Unknown Version)";
}
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
public static string GetVersion(string file, byte[] fileContent, List<int> positions)
{
try
{
// Check the normal version location first
int index = positions[0] - 5;
string versionString = Encoding.ASCII.GetString(fileContent, index, 4);
if (char.IsNumber(versionString[0]))
return versionString;
// Check for the old-style string
//
// Example:
// $Info: This file is packed with the UPX executable packer http://upx.tsx.org $
// $Id: UPX 1.02 Copyright (C) 1996-2000 the UPX Team. All Rights Reserved. $
// UPX!
index = positions[0] - 67;
versionString = Encoding.ASCII.GetString(fileContent, index, 4);
if (char.IsNumber(versionString[0]))
return versionString;
return "(Unknown Version)";
}
catch
{
return "(Unknown Version)";
}
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
public class WinRARSFX : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
var name = pex.AssemblyDescription;
if (name?.Contains("WinRAR archiver") == true)
return "WinRAR SFX";
var resources = pex.FindDialogByTitle("WinRAR self-extracting archive");
if (resources.Any())
return "WinRAR SFX";
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
var rar = new FileType.RAR();
return rar.Extract(file, outDir, lookForHeader: true, includeDebug);
}
}
}

View File

@@ -0,0 +1,763 @@
using System.Linq;
using System.Text;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
public class WinZipSFX : IExtractableExecutable<NewExecutable>, IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, NewExecutable nex, bool includeDebug)
{
// If the resident-name table doesnt exist
if (nex.Model.ResidentNameTable == null)
return null;
// Check for the WinZip name strings
bool winZipNameFound = nex.Model.ResidentNameTable
.Select(rnte => rnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(rnte.NameString))
.Any(s => s.Contains("WZ-SE-01"));
winZipNameFound |= nex.Model.NonResidentNameTable?
.Select(nrnte => nrnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(nrnte.NameString))
.Any(s => s.Contains("WinZip(R) Self-Extractor")) ?? false;
// If we didn't find it
if (!winZipNameFound)
return null;
// Try to get a known version
var version = GetNEHeaderVersion(nex);
if (!string.IsNullOrEmpty(version))
return $"WinZip SFX {version}";
return $"WinZip SFX Unknown Version (16-bit)";
}
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Check the export directory table, if it exists
if (pex.Model.ExportTable?.ExportDirectoryTable != null)
{
var version = GetPEExportDirectoryVersion(pex);
if (!string.IsNullOrEmpty(version))
return $"WinZip SFX {version}";
}
// Get the _winzip_ section, if it exists
if (pex.ContainsSection("_winzip_", exact: true))
return "WinZip SFX Unknown Version (32-bit)";
return null;
}
// TODO: Find a way to generically detect 2.X versions and improve exact version detection for SFX PE versions bundled with WinZip 11+
/// <inheritdoc/>
public bool Extract(string file, NewExecutable nex, string outDir, bool includeDebug)
=> Extract(file, outDir, includeDebug);
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
=> Extract(file, outDir, includeDebug);
/// <summary>
/// Handle common extraction between executable types
/// </summary>
public static bool Extract(string file, string outDir, bool includeDebug)
{
var pkzip = new FileType.PKZIP();
return pkzip.Extract(file, outDir, lookForHeader: true, includeDebug);
}
/// <summary>
/// Get the version from the NE header value combinations
/// </summary>
/// TODO: Reduce the checks to only the ones that differ between versions
/// TODO: Research to see if the versions are embedded elsewhere in these files
private static string? GetNEHeaderVersion(NewExecutable nex)
{
#region 2.0 Variants
// 2.0 (MS-DOS/16-bit)
if (nex.Model.Header?.LinkerVersion == 0x11
&& nex.Model.Header?.LinkerRevision == 0x20
&& nex.Model.Header?.EntryTableOffset == 0x0086
&& nex.Model.Header?.EntryTableSize == 0x0002
&& nex.Model.Header?.CrcChecksum == 0x00000000
&& nex.Model.Header?.FlagWord == (SabreTools.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| SabreTools.Models.NewExecutable.HeaderFlag.ProtectedModeOnly
| SabreTools.Models.NewExecutable.HeaderFlag.FullScreen
| SabreTools.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.Model.Header?.AutomaticDataSegmentNumber == 0x0003
&& nex.Model.Header?.InitialHeapAlloc == 0x2000
&& nex.Model.Header?.InitialStackAlloc == 0x4000
&& nex.Model.Header?.InitialCSIPSetting == 0x00012BE6
&& nex.Model.Header?.InitialSSSPSetting == 0x00030000
&& nex.Model.Header?.FileSegmentCount == 0x0003
&& nex.Model.Header?.ModuleReferenceTableSize == 0x0004
&& nex.Model.Header?.NonResidentNameTableSize == 0x004B
&& nex.Model.Header?.SegmentTableOffset == 0x0040
&& nex.Model.Header?.ResourceTableOffset == 0x0058
&& nex.Model.Header?.ResidentNameTableOffset == 0x0058
&& nex.Model.Header?.ModuleReferenceTableOffset == 0x0064
&& nex.Model.Header?.ImportedNamesTableOffset == 0x006C
&& nex.Model.Header?.NonResidentNamesTableOffset == 0x000044B8
&& nex.Model.Header?.MovableEntriesCount == 0x0000
&& nex.Model.Header?.SegmentAlignmentShiftCount == 0x0001
&& nex.Model.Header?.ResourceEntriesCount == 0x0000
&& nex.Model.Header?.TargetOperatingSystem == SabreTools.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.Model.Header?.AdditionalFlags == 0x00
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.MinCodeSwapAreaSize == 0x0000
&& nex.Model.Header?.WindowsSDKRevision == 0x00
&& nex.Model.Header?.WindowsSDKVersion == 0x03)
return "2.0 (MS-DOS/16-bit)";
// 2.0 (16-bit)
if (nex.Model.Header?.LinkerVersion == 0x11
&& nex.Model.Header?.LinkerRevision == 0x20
&& nex.Model.Header?.EntryTableOffset == 0x0086
&& nex.Model.Header?.EntryTableSize == 0x0002
&& nex.Model.Header?.CrcChecksum == 0x00000000
&& nex.Model.Header?.FlagWord == (SabreTools.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| SabreTools.Models.NewExecutable.HeaderFlag.ProtectedModeOnly
| SabreTools.Models.NewExecutable.HeaderFlag.FullScreen
| SabreTools.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.Model.Header?.AutomaticDataSegmentNumber == 0x0003
&& nex.Model.Header?.InitialHeapAlloc == 0x2000
&& nex.Model.Header?.InitialStackAlloc == 0x4000
&& nex.Model.Header?.InitialCSIPSetting == 0x00013174
&& nex.Model.Header?.InitialSSSPSetting == 0x00030000
&& nex.Model.Header?.FileSegmentCount == 0x0003
&& nex.Model.Header?.ModuleReferenceTableSize == 0x0004
&& nex.Model.Header?.NonResidentNameTableSize == 0x004B
&& nex.Model.Header?.SegmentTableOffset == 0x0040
&& nex.Model.Header?.ResourceTableOffset == 0x0058
&& nex.Model.Header?.ResidentNameTableOffset == 0x0058
&& nex.Model.Header?.ModuleReferenceTableOffset == 0x0064
&& nex.Model.Header?.ImportedNamesTableOffset == 0x006C
&& nex.Model.Header?.NonResidentNamesTableOffset == 0x00000198
&& nex.Model.Header?.MovableEntriesCount == 0x0000
&& nex.Model.Header?.SegmentAlignmentShiftCount == 0x0001
&& nex.Model.Header?.ResourceEntriesCount == 0x0000
&& nex.Model.Header?.TargetOperatingSystem == SabreTools.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.Model.Header?.AdditionalFlags == 0x00
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.MinCodeSwapAreaSize == 0x0000
&& nex.Model.Header?.WindowsSDKRevision == 0x00
&& nex.Model.Header?.WindowsSDKVersion == 0x03)
return "2.0 (16-bit)";
// Compact 2.0 (16-bit)
if (nex.Model.Header?.LinkerVersion == 0x11
&& nex.Model.Header?.LinkerRevision == 0x20
&& nex.Model.Header?.EntryTableOffset == 0x0080
&& nex.Model.Header?.EntryTableSize == 0x0002
&& nex.Model.Header?.CrcChecksum == 0x00000000
&& nex.Model.Header?.FlagWord == (SabreTools.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| SabreTools.Models.NewExecutable.HeaderFlag.ProtectedModeOnly
| SabreTools.Models.NewExecutable.HeaderFlag.FullScreen
| SabreTools.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.Model.Header?.AutomaticDataSegmentNumber == 0x0003
&& nex.Model.Header?.InitialHeapAlloc == 0x2000
&& nex.Model.Header?.InitialStackAlloc == 0x4000
&& nex.Model.Header?.InitialCSIPSetting == 0x000124A0
&& nex.Model.Header?.InitialSSSPSetting == 0x00030000
&& nex.Model.Header?.FileSegmentCount == 0x0003
&& nex.Model.Header?.ModuleReferenceTableSize == 0x0003
&& nex.Model.Header?.NonResidentNameTableSize == 0x004B
&& nex.Model.Header?.SegmentTableOffset == 0x0040
&& nex.Model.Header?.ResourceTableOffset == 0x0058
&& nex.Model.Header?.ResidentNameTableOffset == 0x0058
&& nex.Model.Header?.ModuleReferenceTableOffset == 0x0064
&& nex.Model.Header?.ImportedNamesTableOffset == 0x006A
&& nex.Model.Header?.NonResidentNamesTableOffset == 0x00000192
&& nex.Model.Header?.MovableEntriesCount == 0x0000
&& nex.Model.Header?.SegmentAlignmentShiftCount == 0x0001
&& nex.Model.Header?.ResourceEntriesCount == 0x0000
&& nex.Model.Header?.TargetOperatingSystem == SabreTools.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.Model.Header?.AdditionalFlags == 0x00
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.MinCodeSwapAreaSize == 0x0000
&& nex.Model.Header?.WindowsSDKRevision == 0x00
&& nex.Model.Header?.WindowsSDKVersion == 0x03)
return "Compact 2.0 (16-bit)";
// Software Installation 2.0 (16-bit)
if (nex.Model.Header?.LinkerVersion == 0x11
&& nex.Model.Header?.LinkerRevision == 0x20
&& nex.Model.Header?.EntryTableOffset == 0x00CD
&& nex.Model.Header?.EntryTableSize == 0x0002
&& nex.Model.Header?.CrcChecksum == 0x00000000
&& nex.Model.Header?.FlagWord == (SabreTools.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| SabreTools.Models.NewExecutable.HeaderFlag.FullScreen
| SabreTools.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.Model.Header?.AutomaticDataSegmentNumber == 0x0003
&& nex.Model.Header?.InitialHeapAlloc == 0x2000
&& nex.Model.Header?.InitialStackAlloc == 0x4000
&& nex.Model.Header?.InitialCSIPSetting == 0x000136FA
&& nex.Model.Header?.InitialSSSPSetting == 0x00030000
&& nex.Model.Header?.FileSegmentCount == 0x0003
&& nex.Model.Header?.ModuleReferenceTableSize == 0x0005
&& nex.Model.Header?.NonResidentNameTableSize == 0x004B
&& nex.Model.Header?.SegmentTableOffset == 0x0040
&& nex.Model.Header?.ResourceTableOffset == 0x0058
&& nex.Model.Header?.ResidentNameTableOffset == 0x0097
&& nex.Model.Header?.ModuleReferenceTableOffset == 0x00A3
&& nex.Model.Header?.ImportedNamesTableOffset == 0x00AD
&& nex.Model.Header?.NonResidentNamesTableOffset == 0x000001DF
&& nex.Model.Header?.MovableEntriesCount == 0x0000
&& nex.Model.Header?.SegmentAlignmentShiftCount == 0x0001
&& nex.Model.Header?.ResourceEntriesCount == 0x0000
&& nex.Model.Header?.TargetOperatingSystem == SabreTools.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.Model.Header?.AdditionalFlags == 0x00
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.MinCodeSwapAreaSize == 0x0000
&& nex.Model.Header?.WindowsSDKRevision == 0x00
&& nex.Model.Header?.WindowsSDKVersion == 0x03)
return "Software Installation 2.0 (16-bit)";
#endregion
#region 2.1 RC2 Variants
// 2.1 RC2 (MS-DOS/16-bit)
if (nex.Model.Header?.LinkerVersion == 0x11
&& nex.Model.Header?.LinkerRevision == 0x20
&& nex.Model.Header?.EntryTableOffset == 0x0086
&& nex.Model.Header?.EntryTableSize == 0x0002
&& nex.Model.Header?.CrcChecksum == 0x00000000
&& nex.Model.Header?.FlagWord == (SabreTools.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| SabreTools.Models.NewExecutable.HeaderFlag.ProtectedModeOnly
| SabreTools.Models.NewExecutable.HeaderFlag.FullScreen
| SabreTools.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.Model.Header?.AutomaticDataSegmentNumber == 0x0003
&& nex.Model.Header?.InitialHeapAlloc == 0x2000
&& nex.Model.Header?.InitialStackAlloc == 0x4000
&& nex.Model.Header?.InitialCSIPSetting == 0x00013386
&& nex.Model.Header?.InitialSSSPSetting == 0x00030000
&& nex.Model.Header?.FileSegmentCount == 0x0003
&& nex.Model.Header?.ModuleReferenceTableSize == 0x0004
&& nex.Model.Header?.NonResidentNameTableSize == 0x004B
&& nex.Model.Header?.SegmentTableOffset == 0x0040
&& nex.Model.Header?.ResourceTableOffset == 0x0058
&& nex.Model.Header?.ResidentNameTableOffset == 0x0058
&& nex.Model.Header?.ModuleReferenceTableOffset == 0x0064
&& nex.Model.Header?.ImportedNamesTableOffset == 0x006C
&& nex.Model.Header?.NonResidentNamesTableOffset == 0x000043C8
&& nex.Model.Header?.MovableEntriesCount == 0x0000
&& nex.Model.Header?.SegmentAlignmentShiftCount == 0x0001
&& nex.Model.Header?.ResourceEntriesCount == 0x0000
&& nex.Model.Header?.TargetOperatingSystem == SabreTools.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.Model.Header?.AdditionalFlags == 0x00
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.MinCodeSwapAreaSize == 0x0000
&& nex.Model.Header?.WindowsSDKRevision == 0x00
&& nex.Model.Header?.WindowsSDKVersion == 0x03)
return "2.1 RC2 (MS-DOS/16-bit)";
// 2.1 RC2 (16-bit)
if (nex.Model.Header?.LinkerVersion == 0x11
&& nex.Model.Header?.LinkerRevision == 0x20
&& nex.Model.Header?.EntryTableOffset == 0x00BE
&& nex.Model.Header?.EntryTableSize == 0x0002
&& nex.Model.Header?.CrcChecksum == 0x00000000
&& nex.Model.Header?.FlagWord == (SabreTools.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| SabreTools.Models.NewExecutable.HeaderFlag.FullScreen
| SabreTools.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.Model.Header?.AutomaticDataSegmentNumber == 0x0003
&& nex.Model.Header?.InitialHeapAlloc == 0x2000
&& nex.Model.Header?.InitialStackAlloc == 0x4000
&& nex.Model.Header?.InitialCSIPSetting == 0x00013E56
&& nex.Model.Header?.InitialSSSPSetting == 0x00030000
&& nex.Model.Header?.FileSegmentCount == 0x0003
&& nex.Model.Header?.ModuleReferenceTableSize == 0x0004
&& nex.Model.Header?.NonResidentNameTableSize == 0x004B
&& nex.Model.Header?.SegmentTableOffset == 0x0040
&& nex.Model.Header?.ResourceTableOffset == 0x0058
&& nex.Model.Header?.ResidentNameTableOffset == 0x0090
&& nex.Model.Header?.ModuleReferenceTableOffset == 0x009C
&& nex.Model.Header?.ImportedNamesTableOffset == 0x00A4
&& nex.Model.Header?.NonResidentNamesTableOffset == 0x000001D0
&& nex.Model.Header?.MovableEntriesCount == 0x0000
&& nex.Model.Header?.SegmentAlignmentShiftCount == 0x0001
&& nex.Model.Header?.ResourceEntriesCount == 0x0000
&& nex.Model.Header?.TargetOperatingSystem == SabreTools.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.Model.Header?.AdditionalFlags == 0x00
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.MinCodeSwapAreaSize == 0x0000
&& nex.Model.Header?.WindowsSDKRevision == 0x00
&& nex.Model.Header?.WindowsSDKVersion == 0x03)
return "2.1 RC2 (16-bit)";
// Compact 2.1 RC2 (16-bit)
if (nex.Model.Header?.LinkerVersion == 0x11
&& nex.Model.Header?.LinkerRevision == 0x20
&& nex.Model.Header?.EntryTableOffset == 0x0080
&& nex.Model.Header?.EntryTableSize == 0x0002
&& nex.Model.Header?.CrcChecksum == 0x00000000
&& nex.Model.Header?.FlagWord == (SabreTools.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| SabreTools.Models.NewExecutable.HeaderFlag.ProtectedModeOnly
| SabreTools.Models.NewExecutable.HeaderFlag.FullScreen
| SabreTools.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.Model.Header?.AutomaticDataSegmentNumber == 0x0003
&& nex.Model.Header?.InitialHeapAlloc == 0x2000
&& nex.Model.Header?.InitialStackAlloc == 0x4000
&& nex.Model.Header?.InitialCSIPSetting == 0x00012B84
&& nex.Model.Header?.InitialSSSPSetting == 0x00030000
&& nex.Model.Header?.FileSegmentCount == 0x0003
&& nex.Model.Header?.ModuleReferenceTableSize == 0x0003
&& nex.Model.Header?.NonResidentNameTableSize == 0x004B
&& nex.Model.Header?.SegmentTableOffset == 0x0040
&& nex.Model.Header?.ResourceTableOffset == 0x0058
&& nex.Model.Header?.ResidentNameTableOffset == 0x0058
&& nex.Model.Header?.ModuleReferenceTableOffset == 0x0064
&& nex.Model.Header?.ImportedNamesTableOffset == 0x006A
&& nex.Model.Header?.NonResidentNamesTableOffset == 0x00000192
&& nex.Model.Header?.MovableEntriesCount == 0x0000
&& nex.Model.Header?.SegmentAlignmentShiftCount == 0x0001
&& nex.Model.Header?.ResourceEntriesCount == 0x0000
&& nex.Model.Header?.TargetOperatingSystem == SabreTools.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.Model.Header?.AdditionalFlags == 0x00
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.MinCodeSwapAreaSize == 0x0000
&& nex.Model.Header?.WindowsSDKRevision == 0x00
&& nex.Model.Header?.WindowsSDKVersion == 0x03)
return "Compact 2.1 RC2 (16-bit)";
// Software Installation 2.1 RC2 (16-bit)
if (nex.Model.Header?.LinkerVersion == 0x11
&& nex.Model.Header?.LinkerRevision == 0x20
&& nex.Model.Header?.EntryTableOffset == 0x00BE
&& nex.Model.Header?.EntryTableSize == 0x0002
&& nex.Model.Header?.CrcChecksum == 0x00000000
&& nex.Model.Header?.FlagWord == (SabreTools.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| SabreTools.Models.NewExecutable.HeaderFlag.FullScreen
| SabreTools.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.Model.Header?.AutomaticDataSegmentNumber == 0x0003
&& nex.Model.Header?.InitialHeapAlloc == 0x2000
&& nex.Model.Header?.InitialStackAlloc == 0x4000
&& nex.Model.Header?.InitialCSIPSetting == 0x000143AC
&& nex.Model.Header?.InitialSSSPSetting == 0x00030000
&& nex.Model.Header?.FileSegmentCount == 0x0003
&& nex.Model.Header?.ModuleReferenceTableSize == 0x0004
&& nex.Model.Header?.NonResidentNameTableSize == 0x004B
&& nex.Model.Header?.SegmentTableOffset == 0x0040
&& nex.Model.Header?.ResourceTableOffset == 0x0058
&& nex.Model.Header?.ResidentNameTableOffset == 0x0090
&& nex.Model.Header?.ModuleReferenceTableOffset == 0x009C
&& nex.Model.Header?.ImportedNamesTableOffset == 0x00A4
&& nex.Model.Header?.NonResidentNamesTableOffset == 0x000001D0
&& nex.Model.Header?.MovableEntriesCount == 0x0000
&& nex.Model.Header?.SegmentAlignmentShiftCount == 0x0001
&& nex.Model.Header?.ResourceEntriesCount == 0x0000
&& nex.Model.Header?.TargetOperatingSystem == SabreTools.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.Model.Header?.AdditionalFlags == 0x00
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.MinCodeSwapAreaSize == 0x0000
&& nex.Model.Header?.WindowsSDKRevision == 0x00
&& nex.Model.Header?.WindowsSDKVersion == 0x03)
return "Software Installation 2.1 RC2 (16-bit)";
#endregion
#region 2.1 Variants
// 2.1 (MS-DOS/16-bit)
if (nex.Model.Header?.LinkerVersion == 0x11
&& nex.Model.Header?.LinkerRevision == 0x20
&& nex.Model.Header?.EntryTableOffset == 0x0086
&& nex.Model.Header?.EntryTableSize == 0x0002
&& nex.Model.Header?.CrcChecksum == 0x00000000
&& nex.Model.Header?.FlagWord == (SabreTools.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| SabreTools.Models.NewExecutable.HeaderFlag.ProtectedModeOnly
| SabreTools.Models.NewExecutable.HeaderFlag.FullScreen
| SabreTools.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.Model.Header?.AutomaticDataSegmentNumber == 0x0003
&& nex.Model.Header?.InitialHeapAlloc == 0x2000
&& nex.Model.Header?.InitialStackAlloc == 0x3A00
&& nex.Model.Header?.InitialCSIPSetting == 0x00013396
&& nex.Model.Header?.InitialSSSPSetting == 0x00030000
&& nex.Model.Header?.FileSegmentCount == 0x0003
&& nex.Model.Header?.ModuleReferenceTableSize == 0x0004
&& nex.Model.Header?.NonResidentNameTableSize == 0x004B
&& nex.Model.Header?.SegmentTableOffset == 0x0040
&& nex.Model.Header?.ResourceTableOffset == 0x0058
&& nex.Model.Header?.ResidentNameTableOffset == 0x0058
&& nex.Model.Header?.ModuleReferenceTableOffset == 0x0064
&& nex.Model.Header?.ImportedNamesTableOffset == 0x006C
&& nex.Model.Header?.NonResidentNamesTableOffset == 0x000043C8
&& nex.Model.Header?.MovableEntriesCount == 0x0000
&& nex.Model.Header?.SegmentAlignmentShiftCount == 0x0001
&& nex.Model.Header?.ResourceEntriesCount == 0x0000
&& nex.Model.Header?.TargetOperatingSystem == SabreTools.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.Model.Header?.AdditionalFlags == 0x00
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.MinCodeSwapAreaSize == 0x0000
&& nex.Model.Header?.WindowsSDKRevision == 0x00
&& nex.Model.Header?.WindowsSDKVersion == 0x03)
return "2.1 (MS-DOS/16-bit)";
// 2.1 (16-bit)
if (nex.Model.Header?.LinkerVersion == 0x11
&& nex.Model.Header?.LinkerRevision == 0x20
&& nex.Model.Header?.EntryTableOffset == 0x00BE
&& nex.Model.Header?.EntryTableSize == 0x0002
&& nex.Model.Header?.CrcChecksum == 0x00000000
&& nex.Model.Header?.FlagWord == (SabreTools.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| SabreTools.Models.NewExecutable.HeaderFlag.FullScreen
| SabreTools.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.Model.Header?.AutomaticDataSegmentNumber == 0x0003
&& nex.Model.Header?.InitialHeapAlloc == 0x2000
&& nex.Model.Header?.InitialStackAlloc == 0x3A00
&& nex.Model.Header?.InitialCSIPSetting == 0x00013E7E
&& nex.Model.Header?.InitialSSSPSetting == 0x00030000
&& nex.Model.Header?.FileSegmentCount == 0x0003
&& nex.Model.Header?.ModuleReferenceTableSize == 0x0004
&& nex.Model.Header?.NonResidentNameTableSize == 0x004B
&& nex.Model.Header?.SegmentTableOffset == 0x0040
&& nex.Model.Header?.ResourceTableOffset == 0x0058
&& nex.Model.Header?.ResidentNameTableOffset == 0x0090
&& nex.Model.Header?.ModuleReferenceTableOffset == 0x009C
&& nex.Model.Header?.ImportedNamesTableOffset == 0x00A4
&& nex.Model.Header?.NonResidentNamesTableOffset == 0x000001D0
&& nex.Model.Header?.MovableEntriesCount == 0x0000
&& nex.Model.Header?.SegmentAlignmentShiftCount == 0x0001
&& nex.Model.Header?.ResourceEntriesCount == 0x0000
&& nex.Model.Header?.TargetOperatingSystem == SabreTools.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.Model.Header?.AdditionalFlags == 0x00
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.MinCodeSwapAreaSize == 0x0000
&& nex.Model.Header?.WindowsSDKRevision == 0x00
&& nex.Model.Header?.WindowsSDKVersion == 0x03)
return "2.1 (16-bit)";
// Compact 2.1 (16-bit)
if (nex.Model.Header?.LinkerVersion == 0x11
&& nex.Model.Header?.LinkerRevision == 0x20
&& nex.Model.Header?.EntryTableOffset == 0x0080
&& nex.Model.Header?.EntryTableSize == 0x0002
&& nex.Model.Header?.CrcChecksum == 0x00000000
&& nex.Model.Header?.FlagWord == (SabreTools.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| SabreTools.Models.NewExecutable.HeaderFlag.ProtectedModeOnly
| SabreTools.Models.NewExecutable.HeaderFlag.FullScreen
| SabreTools.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.Model.Header?.AutomaticDataSegmentNumber == 0x0003
&& nex.Model.Header?.InitialHeapAlloc == 0x2000
&& nex.Model.Header?.InitialStackAlloc == 0x3A00
&& nex.Model.Header?.InitialCSIPSetting == 0x00012B90
&& nex.Model.Header?.InitialSSSPSetting == 0x00030000
&& nex.Model.Header?.FileSegmentCount == 0x0003
&& nex.Model.Header?.ModuleReferenceTableSize == 0x0003
&& nex.Model.Header?.NonResidentNameTableSize == 0x004B
&& nex.Model.Header?.SegmentTableOffset == 0x0040
&& nex.Model.Header?.ResourceTableOffset == 0x0058
&& nex.Model.Header?.ResidentNameTableOffset == 0x0058
&& nex.Model.Header?.ModuleReferenceTableOffset == 0x0064
&& nex.Model.Header?.ImportedNamesTableOffset == 0x006A
&& nex.Model.Header?.NonResidentNamesTableOffset == 0x00000192
&& nex.Model.Header?.MovableEntriesCount == 0x0000
&& nex.Model.Header?.SegmentAlignmentShiftCount == 0x0001
&& nex.Model.Header?.ResourceEntriesCount == 0x0000
&& nex.Model.Header?.TargetOperatingSystem == SabreTools.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.Model.Header?.AdditionalFlags == 0x00
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.MinCodeSwapAreaSize == 0x0000
&& nex.Model.Header?.WindowsSDKRevision == 0x00
&& nex.Model.Header?.WindowsSDKVersion == 0x03)
return "Compact 2.1 (16-bit)";
// Software Installation 2.1 (16-bit)
if (nex.Model.Header?.LinkerVersion == 0x11
&& nex.Model.Header?.LinkerRevision == 0x20
&& nex.Model.Header?.EntryTableOffset == 0x00BE
&& nex.Model.Header?.EntryTableSize == 0x0002
&& nex.Model.Header?.CrcChecksum == 0x00000000
&& nex.Model.Header?.FlagWord == (SabreTools.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| SabreTools.Models.NewExecutable.HeaderFlag.FullScreen
| SabreTools.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.Model.Header?.AutomaticDataSegmentNumber == 0x0003
&& nex.Model.Header?.InitialHeapAlloc == 0x2000
&& nex.Model.Header?.InitialStackAlloc == 0x3A00
&& nex.Model.Header?.InitialCSIPSetting == 0x00014408
&& nex.Model.Header?.InitialSSSPSetting == 0x00030000
&& nex.Model.Header?.FileSegmentCount == 0x0003
&& nex.Model.Header?.ModuleReferenceTableSize == 0x0004
&& nex.Model.Header?.NonResidentNameTableSize == 0x004B
&& nex.Model.Header?.SegmentTableOffset == 0x0040
&& nex.Model.Header?.ResourceTableOffset == 0x0058
&& nex.Model.Header?.ResidentNameTableOffset == 0x0090
&& nex.Model.Header?.ModuleReferenceTableOffset == 0x009C
&& nex.Model.Header?.ImportedNamesTableOffset == 0x00A4
&& nex.Model.Header?.NonResidentNamesTableOffset == 0x000001D0
&& nex.Model.Header?.MovableEntriesCount == 0x0000
&& nex.Model.Header?.SegmentAlignmentShiftCount == 0x0001
&& nex.Model.Header?.ResourceEntriesCount == 0x0000
&& nex.Model.Header?.TargetOperatingSystem == SabreTools.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.Model.Header?.AdditionalFlags == 0x00
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.MinCodeSwapAreaSize == 0x0000
&& nex.Model.Header?.WindowsSDKRevision == 0x00
&& nex.Model.Header?.WindowsSDKVersion == 0x03)
return "Software Installation 2.1 (16-bit)";
#endregion
#region Misc. Variants
// Personal Edition (16-bit)
if (nex.Model.Header?.LinkerVersion == 0x11
&& nex.Model.Header?.LinkerRevision == 0x20
&& nex.Model.Header?.EntryTableOffset == 0x0086
&& nex.Model.Header?.EntryTableSize == 0x0002
&& nex.Model.Header?.CrcChecksum == 0x00000000
&& nex.Model.Header?.FlagWord == (SabreTools.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| SabreTools.Models.NewExecutable.HeaderFlag.ProtectedModeOnly
| SabreTools.Models.NewExecutable.HeaderFlag.FullScreen
| SabreTools.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.Model.Header?.AutomaticDataSegmentNumber == 0x0003
&& nex.Model.Header?.InitialHeapAlloc == 0x2000
&& nex.Model.Header?.InitialStackAlloc == 0x4000
&& nex.Model.Header?.InitialCSIPSetting == 0x0001317C
&& nex.Model.Header?.InitialSSSPSetting == 0x00030000
&& nex.Model.Header?.FileSegmentCount == 0x0003
&& nex.Model.Header?.ModuleReferenceTableSize == 0x0004
&& nex.Model.Header?.NonResidentNameTableSize == 0x004B
&& nex.Model.Header?.SegmentTableOffset == 0x0040
&& nex.Model.Header?.ResourceTableOffset == 0x0058
&& nex.Model.Header?.ResidentNameTableOffset == 0x0058
&& nex.Model.Header?.ModuleReferenceTableOffset == 0x0064
&& nex.Model.Header?.ImportedNamesTableOffset == 0x006C
&& nex.Model.Header?.NonResidentNamesTableOffset == 0x00000198
&& nex.Model.Header?.MovableEntriesCount == 0x0000
&& nex.Model.Header?.SegmentAlignmentShiftCount == 0x0001
&& nex.Model.Header?.ResourceEntriesCount == 0x0000
&& nex.Model.Header?.TargetOperatingSystem == SabreTools.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.Model.Header?.AdditionalFlags == 0x00
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.MinCodeSwapAreaSize == 0x0000
&& nex.Model.Header?.WindowsSDKRevision == 0x00
&& nex.Model.Header?.WindowsSDKVersion == 0x03)
return "Personal Edition (16-bit)";
// Personal Edition 32-bit (16-bit)
if (nex.Model.Header?.LinkerVersion == 0x11
&& nex.Model.Header?.LinkerRevision == 0x20
&& nex.Model.Header?.EntryTableOffset == 0x00BE
&& nex.Model.Header?.EntryTableSize == 0x0002
&& nex.Model.Header?.CrcChecksum == 0x00000000
&& nex.Model.Header?.FlagWord == (SabreTools.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| SabreTools.Models.NewExecutable.HeaderFlag.FullScreen
| SabreTools.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.Model.Header?.AutomaticDataSegmentNumber == 0x0003
&& nex.Model.Header?.InitialHeapAlloc == 0x2000
&& nex.Model.Header?.InitialStackAlloc == 0x3C00
&& nex.Model.Header?.InitialCSIPSetting == 0x00013E7C
&& nex.Model.Header?.InitialSSSPSetting == 0x00030000
&& nex.Model.Header?.FileSegmentCount == 0x0003
&& nex.Model.Header?.ModuleReferenceTableSize == 0x0004
&& nex.Model.Header?.NonResidentNameTableSize == 0x004B
&& nex.Model.Header?.SegmentTableOffset == 0x0040
&& nex.Model.Header?.ResourceTableOffset == 0x0058
&& nex.Model.Header?.ResidentNameTableOffset == 0x0090
&& nex.Model.Header?.ModuleReferenceTableOffset == 0x009C
&& nex.Model.Header?.ImportedNamesTableOffset == 0x00A4
&& nex.Model.Header?.NonResidentNamesTableOffset == 0x000001D0
&& nex.Model.Header?.MovableEntriesCount == 0x0000
&& nex.Model.Header?.SegmentAlignmentShiftCount == 0x0001
&& nex.Model.Header?.ResourceEntriesCount == 0x0000
&& nex.Model.Header?.TargetOperatingSystem == SabreTools.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.Model.Header?.AdditionalFlags == 0x00
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.MinCodeSwapAreaSize == 0x0000
&& nex.Model.Header?.WindowsSDKRevision == 0x00
&& nex.Model.Header?.WindowsSDKVersion == 0x03)
return "Personal Edition 32-bit (16-bit)";
// Personal Edition 32-bit Build 1260/1285 (16-bit)
if (nex.Model.Header?.LinkerVersion == 0x11
&& nex.Model.Header?.LinkerRevision == 0x20
&& nex.Model.Header?.EntryTableOffset == 0x00C6
&& nex.Model.Header?.EntryTableSize == 0x0002
&& nex.Model.Header?.CrcChecksum == 0x00000000
&& nex.Model.Header?.FlagWord == (SabreTools.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| SabreTools.Models.NewExecutable.HeaderFlag.FullScreen
| SabreTools.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.Model.Header?.AutomaticDataSegmentNumber == 0x0003
&& nex.Model.Header?.InitialHeapAlloc == 0x43DC
&& nex.Model.Header?.InitialStackAlloc == 0x2708
&& nex.Model.Header?.InitialCSIPSetting == 0x00014ADC
&& nex.Model.Header?.InitialSSSPSetting == 0x00030000
&& nex.Model.Header?.FileSegmentCount == 0x0003
&& nex.Model.Header?.ModuleReferenceTableSize == 0x0005
&& nex.Model.Header?.NonResidentNameTableSize == 0x004B
&& nex.Model.Header?.SegmentTableOffset == 0x0040
&& nex.Model.Header?.ResourceTableOffset == 0x0058
&& nex.Model.Header?.ResidentNameTableOffset == 0x0090
&& nex.Model.Header?.ModuleReferenceTableOffset == 0x009C
&& nex.Model.Header?.ImportedNamesTableOffset == 0x00A6
&& nex.Model.Header?.NonResidentNamesTableOffset == 0x000001D8
&& nex.Model.Header?.MovableEntriesCount == 0x0000
&& nex.Model.Header?.SegmentAlignmentShiftCount == 0x0001
&& nex.Model.Header?.ResourceEntriesCount == 0x0000
&& nex.Model.Header?.TargetOperatingSystem == SabreTools.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.Model.Header?.AdditionalFlags == 0x00
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.ReturnThunkOffset == 0x0000
&& nex.Model.Header?.MinCodeSwapAreaSize == 0x0000
&& nex.Model.Header?.WindowsSDKRevision == 0x00
&& nex.Model.Header?.WindowsSDKVersion == 0x03)
return "Personal Edition 32-bit Build 1260/1285 (16-bit)";
#endregion
return null;
}
/// <summary>
/// Get the version from the PE export directory table value combinations
/// </summary>
/// TODO: Research to see if the versions are embedded elsewhere in these files
private static string? GetPEExportDirectoryVersion(PortableExecutable pex)
{
string sfxFileName = pex.Model.ExportTable?.ExportDirectoryTable?.Name ?? string.Empty;
uint sfxTimeDateStamp = pex.Model.ExportTable?.ExportDirectoryTable?.TimeDateStamp ?? uint.MaxValue;
string assemblyVersion = pex.AssemblyVersion ?? "Unknown Version";
// Standard
if (sfxFileName == "VW95SE.SFX" || sfxFileName == "ST32E.SFX"
|| sfxFileName == "WZIPSE32.exe" || sfxFileName == "SI32LPG.SFX"
|| sfxFileName == "ST32E.WZE")
{
return sfxTimeDateStamp switch
{
842636344 => "2.0 (32-bit)",
865370756 => "2.1 RC2 (32-bit)",
869059925 => "2.1 (32-bit)",
979049321 => "2.2.4003",
1149714685 => "3.0.7158",
1185211734 => "3.1.7556",
1185211920 => "3.1.7556",
1235490556 => "4.0.8421",
1235490757 => "4.0.8421",
1235490687 => "4.0.8421",// 3.1.8421.0, SI32LPG?
1257193383 => "4.0.8672",// 3.1.8672.0
1257193543 => "4.0.8672",
1470410848 => "4.0.12218",// 4.0.1221.0
_ => $"{assemblyVersion} (32-bit)",
};
}
// Personal Edition
if (sfxFileName == "VW95LE.SFX" || sfxFileName == "PE32E.SFX"
|| sfxFileName == "wzsepe32.exe" || sfxFileName == "SI32PE.SFX"
|| sfxFileName == "SI32LPE.SFX")
{
return sfxTimeDateStamp switch
{
845061601 => "Personal Edition (32-bit)",// TODO: Find version
868303343 => "Personal Edition (32-bit)",// TODO: Find version
868304170 => "Personal Edition (32-bit)",// TODO: Find version
906039079 => "Personal Edition 2.2.1260 (32-bit)",
906040543 => "Personal Edition 2.2.1260 (32-bit)",
908628435 => "Personal Edition 2.2.1285 (32-bit)",
908628785 => "Personal Edition 2.2.1285 (32-bit)",
956165981 => "Personal Edition 2.2.3063",
956166038 => "Personal Edition 2.2.3063",
1006353695 => "Personal Edition 2.2.4325",
1006353714 => "Personal Edition 2.2.4325",// 8.1.0.0
1076515698 => "Personal Edition 2.2.6028",
1076515784 => "Personal Edition 2.2.6028",// 9.0.6028.0
1092688561 => "Personal Edition 2.2.6224",
1092688645 => "Personal Edition 2.2.6224",// 9.0.6224.0
1125074095 => "Personal Edition 2.2.6604",
1125074162 => "Personal Edition 2.2.6604",// 10.0.6604.0
1130153399 => "Personal Edition 2.2.6663",
1130153428 => "Personal Edition 2.2.6663",// 10.0.6663.0
1149714176 => "Personal Edition 3.0.7158",
1163137967 => "Personal Edition 3.0.7305",
1163137994 => "Personal Edition 3.0.7313",// 11.0.7313.0
1176345383 => "Personal Edition 3.0.7452",
1176345423 => "Personal Edition 3.1.7466",// 11.1.7466.0
1184106698 => "Personal Edition 3.1.7556",
1207280880 => "Personal Edition 4.0.8060",// 2.3.7382.0
1207280892 => "Personal Edition 4.0.8094",// 11.2.8094.0
1220904506 => "Personal Edition 4.0.8213",// 2.3.7382.0
1220904518 => "Personal Edition 4.0.8252",// 12.0.8252.0
1235490648 => "Personal Edition 4.0.8421",// 3.1.8421.0
1242049399 => "Personal Edition 4.0.8497",// 12.1.8497.0
1257193469 => "Personal Edition 4.0.8672",// 3.1.8672.0, SI32LPE?
_ => $"Personal Edition {assemblyVersion} (32-bit)",
};
}
// Software Installation
else if (sfxFileName == "VW95SRE.SFX" || sfxFileName == "SI32E.SFX"
|| sfxFileName == "SI32E.WZE")
{
return sfxTimeDateStamp switch
{
842636381 => "Software Installation 2.0 (32-bit)",
865370800 => "Software Installation 2.1 RC2 (32-bit)",
869059963 => "Software Installation 2.1 (32-bit)",
893107697 => "Software Installation 2.2.1110 (32-bit)",
952007369 => "Software Installation 2.2.3063",
1006352634 => "Software Installation 2.2.4325",// +Personal Edition?
979049345 => "Software Installation 2.2.4403",
1026227373 => "Software Installation 2.2.5196",// +Personal Edition?
1090582390 => "Software Installation 2.2.6202",// +Personal Edition?
1149714757 => "Software Installation 3.0.7158",
1154357628 => "Software Installation 3.0.7212",
1175234637 => "Software Installation 3.0.7454",
1185211802 => "Software Installation 3.1.7556",
1470410906 => "Software Installation 4.0.12218",// 4.0.1221.0
_ => $"Software Installation {assemblyVersion} (32-bit)",
};
}
return sfxFileName switch
{
// Standard
"VW95SE.SFX" => "Unknown Version (32-bit)",// TODO: Find starting version
"ST32E.SFX" => "Unknown Version (32-bit)",// TODO: Find starting version
"WZIPSE32.exe" => "Unknown Version (32-bit)",// TODO: Find starting version
"SI32LPG.SFX" => "Unknown Version (32-bit)",// TODO: Find starting version
"ST32E.WZE" => "Unknown Version (32-bit)",// TODO: Find starting version
// Personal Edition
"VW95LE.SFX" => "Unknown Version before Personal Edition Build 1285 (32-bit)",
"PE32E.SFX" => "Unknown Version after Personal Edition Build 1285 (32-bit)",
"wzsepe32.exe" => "Unknown Version Personal Edition (32-bit)",// TODO: Find starting version
"SI32PE.SFX" => "Unknown Version Personal Edition (32-bit)",// TODO: Find starting version
"SI32LPE.SFX" => "Unknown Version Personal Edition (32-bit)",// TODO: Find starting version
// Software Installation
"VW95SRE.SFX" => "Unknown Version before Software Installation 2.1 (32-bit)",
"SI32E.SFX" => "Unknown Version after Software Installation 2.1 (32-bit)",
"SI32E.WZE" => "Unknown Version Software Installation (32-bit)",// TODO: Find starting version
_ => null,
};
}
}
}

View File

@@ -0,0 +1,292 @@
using System;
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.IO.Extensions;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Serialization.Wrappers;
using WiseUnpacker;
using WiseUnpacker.EWISE;
namespace BinaryObjectScanner.Packer
{
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class WiseInstaller : IExtractableExecutable<NewExecutable>, IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, NewExecutable nex, bool includeDebug)
{
// If we match a known header
if (MatchesNEVersion(nex) != null)
return "Wise Installation Wizard Module";
// TODO: Investigate STUB.EXE in nonresident-name table
// TODO: Don't read entire file
var data = nex.ReadArbitraryRange();
if (data == null)
return null;
var neMatchSets = new List<ContentMatchSet>
{
// WiseInst
new(new byte?[] { 0x57, 0x69, 0x73, 0x65, 0x49, 0x6E, 0x73, 0x74 }, "Wise Installation Wizard Module"),
// WiseMain
new(new byte?[] { 0x57, 0x69, 0x73, 0x65, 0x4D, 0x61, 0x69, 0x6E }, "Wise Installation Wizard Module"),
};
return MatchUtil.GetFirstMatch(file, data, neMatchSets, includeDebug);
}
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// If we match a known header
if (GetPEFormat(pex) != null)
return "Wise Installation Wizard Module";
// TODO: Investigate STUB32.EXE in export directory table
// Get the .data/DATA section strings, if they exist
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
if (strs != null)
{
if (strs.Exists(s => s.Contains("WiseMain")))
return "Wise Installation Wizard Module";
}
// Get the .rdata section strings, if they exist
strs = pex.GetFirstSectionStrings(".rdata");
if (strs != null)
{
if (strs.Exists(s => s.Contains("WiseMain")))
return "Wise Installation Wizard Module";
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, NewExecutable nex, string outDir, bool includeDebug)
{
Directory.CreateDirectory(outDir);
try
{
return Extractor.ExtractTo(file, outDir);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
try
{
// Get the matching PE format
var format = GetPEFormat(pex);
if (format == null)
return false;
// Get the overlay data for easier reading
int overlayOffset = 0, dataStart = 0;
var overlayData = pex.OverlayData;
if (overlayData == null)
return false;
// Skip over the additional DLL name, if we expect it
if (format.Dll)
{
// Read the name length
byte dllNameLength = overlayData.ReadByte(ref overlayOffset);
dataStart++;
// Read the name, if it exists
if (dllNameLength != 0)
{
// Ignore the name for now
_ = overlayData.ReadBytes(ref overlayOffset, dllNameLength);
dataStart += dllNameLength;
// Named DLLs also have a DLL length that we ignore
_ = overlayData.ReadUInt32(ref overlayOffset);
dataStart += 4;
}
}
// Check if flags are consistent
if (!format.NoCrc)
{
// Unlike WiseUnpacker, we ignore the flag value here
_ = overlayData.ReadUInt32(ref overlayOffset);
}
// Ensure that we have an archive end
if (format.ArchiveEnd > 0)
{
overlayOffset = (int)(dataStart + format.ArchiveEnd);
int archiveEndLoaded = overlayData.ReadInt32(ref overlayOffset);
if (archiveEndLoaded != 0)
format.ArchiveEnd = archiveEndLoaded;
}
// Skip to the start of the archive
overlayOffset = (int)(dataStart + format.ArchiveStart);
// Skip over the initialization text, if we expect it
if (format.InitText)
{
int initTextLength = overlayData.ReadByte(ref overlayOffset);
_ = overlayData.ReadBytes(ref overlayOffset, initTextLength);
}
// Cache the current offset in the overlay as the "start of data"
int offsetReal = overlayOffset;
// If the first entry is PKZIP, we assume it's an embedded zipfile
var magic = overlayData.ReadBytes(ref overlayOffset, 4); overlayOffset -= 4;
#if NET20
bool pkzip = Extensions.StartsWith(magic, new byte?[] { (byte)'P', (byte)'K' });
#else
bool pkzip = magic?.StartsWith(new byte?[] { (byte)'P', (byte)'K' }) ?? false;
#endif
// Create the output directory
Directory.CreateDirectory(outDir);
// If we have PKZIP
if (pkzip)
{
string tempFile = Path.Combine(outDir, "WISEDATA.zip");
using Stream tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
tempStream.Write(overlayData, overlayOffset, overlayData.Length - overlayOffset);
return true;
}
// If we have DEFLATE -- TODO: Port implementation here or use DeflateStream
else
{
return Extractor.ExtractTo(file, outDir);
}
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
/// <summary>
/// Checks an NE header to see if it matches a known signature
/// </summary>
/// <param name="nex">New executable to check</param>
/// <returns>True if it matches a known version, false otherwise</returns>
private FormatProperty? MatchesNEVersion(NewExecutable nex)
{
// TODO: Offset is _not_ the EXE header address, rather where the data starts. Fix this.
switch (nex.Model.Stub?.Header?.NewExeHeaderAddr)
{
case 0x84b0:
return new FormatProperty { Dll = false, ArchiveStart = 0x11, ArchiveEnd = -1, InitText = false, FilenamePosition = 0x04, NoCrc = true };
case 0x3e10:
return new FormatProperty { Dll = false, ArchiveStart = 0x1e, ArchiveEnd = -1, InitText = false, FilenamePosition = 0x04, NoCrc = false };
case 0x3e50:
return new FormatProperty { Dll = false, ArchiveStart = 0x1e, ArchiveEnd = -1, InitText = false, FilenamePosition = 0x04, NoCrc = false };
case 0x3c20:
return new FormatProperty { Dll = false, ArchiveStart = 0x1e, ArchiveEnd = -1, InitText = false, FilenamePosition = 0x04, NoCrc = false };
case 0x3c30:
return new FormatProperty { Dll = false, ArchiveStart = 0x22, ArchiveEnd = -1, InitText = false, FilenamePosition = 0x04, NoCrc = false };
case 0x3660:
return new FormatProperty { Dll = false, ArchiveStart = 0x40, ArchiveEnd = 0x3c, InitText = false, FilenamePosition = 0x04, NoCrc = false };
case 0x36f0:
return new FormatProperty { Dll = false, ArchiveStart = 0x48, ArchiveEnd = 0x44, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
case 0x3770:
return new FormatProperty { Dll = false, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
case 0x3780:
return new FormatProperty { Dll = true, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
case 0x37b0:
return new FormatProperty { Dll = true, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
case 0x37d0:
return new FormatProperty { Dll = true, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
case 0x3c80:
return new FormatProperty { Dll = true, ArchiveStart = 0x5a, ArchiveEnd = 0x4c, InitText = true, FilenamePosition = 0x1c, NoCrc = false };
case 0x3bd0:
return new FormatProperty { Dll = true, ArchiveStart = 0x5a, ArchiveEnd = 0x4c, InitText = true, FilenamePosition = 0x1c, NoCrc = false };
case 0x3c10:
return new FormatProperty { Dll = true, ArchiveStart = 0x5a, ArchiveEnd = 0x4c, InitText = true, FilenamePosition = 0x1c, NoCrc = false };
default:
return null;
}
}
/// <summary>
/// Checks a PE header to see if it matches a known signature
/// </summary>
/// <param name="pex">Portable executable to check</param>
/// <returns>True if it matches a known version, false otherwise</returns>
private FormatProperty? GetPEFormat(PortableExecutable pex)
{
if (pex.OverlayAddress == 0x6e00
&& pex.GetFirstSection(".text")?.VirtualSize == 0x3cf4
&& pex.GetFirstSection(".data")?.VirtualSize == 0x1528)
return new FormatProperty { Dll = false, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
else if (pex.OverlayAddress == 0x6e00
&& pex.GetFirstSection(".text")?.VirtualSize == 0x3cf4
&& pex.GetFirstSection(".data")?.VirtualSize == 0x1568)
return new FormatProperty { Dll = false, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
else if (pex.OverlayAddress == 0x6e00
&& pex.GetFirstSection(".text")?.VirtualSize == 0x3d54)
return new FormatProperty { Dll = false, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
else if (pex.OverlayAddress == 0x6e00
&& pex.GetFirstSection(".text")?.VirtualSize == 0x3d44)
return new FormatProperty { Dll = false, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
else if (pex.OverlayAddress == 0x6e00
&& pex.GetFirstSection(".text")?.VirtualSize == 0x3d04)
return new FormatProperty { Dll = false, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
// Found in Binary.WiseCustomCalla
else if (pex.OverlayAddress == 0x6200)
return new FormatProperty { Dll = true, ArchiveStart = 0x62, ArchiveEnd = 0x4c, InitText = true, FilenamePosition = 0x1c, NoCrc = false };
else if (pex.OverlayAddress == 0x3000)
return new FormatProperty { Dll = false, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
else if (pex.OverlayAddress == 0x3800)
return new FormatProperty { Dll = true, ArchiveStart = 0x5a, ArchiveEnd = 0x4c, InitText = true, FilenamePosition = 0x1c, NoCrc = false };
else if (pex.OverlayAddress == 0x3a00)
return new FormatProperty { Dll = true, ArchiveStart = 0x5a, ArchiveEnd = 0x4c, InitText = true, FilenamePosition = 0x1c, NoCrc = false };
return null;
}
}
}

View File

@@ -0,0 +1,117 @@
#if NET20 || NET35 || NET40
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Threading;
using System.Diagnostics;
namespace System
{
/// <summary>Defines a provider for progress updates.</summary>
/// <typeparam name="T">The type of progress update value.</typeparam>
/// <see href="https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/IProgress.cs"/>
public interface IProgress<in T>
{
/// <summary>Reports a progress update.</summary>
/// <param name="value">The value of the updated progress.</param>
void Report(T value);
}
/// <summary>
/// Provides an IProgress{T} that invokes callbacks for each reported progress value.
/// </summary>
/// <typeparam name="T">Specifies the type of the progress report value.</typeparam>
/// <remarks>
/// Any handler provided to the constructor or event handlers registered with
/// the <see cref="ProgressChanged"/> event are invoked through a
/// <see cref="SynchronizationContext"/> instance captured
/// when the instance is constructed. If there is no current SynchronizationContext
/// at the time of construction, the callbacks will be invoked on the ThreadPool.
/// </remarks>
/// <see href="https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Progress.cs"/>
public class Progress<T> : IProgress<T> where T : EventArgs
{
/// <summary>The synchronization context captured upon construction. This will never be null.</summary>
private readonly SynchronizationContext? _synchronizationContext;
/// <summary>The handler specified to the constructor. This may be null.</summary>
private readonly Action<T>? _handler;
/// <summary>A cached delegate used to post invocation to the synchronization context.</summary>
private readonly SendOrPostCallback _invokeHandlers;
/// <summary>Initializes the <see cref="Progress{T}"/>.</summary>
public Progress()
{
// Capture the current synchronization context.
// If there is no current context, we use a default instance targeting the ThreadPool.
_synchronizationContext = SynchronizationContext.Current ?? ProgressStatics.DefaultContext;
Debug.Assert(_synchronizationContext != null);
_invokeHandlers = new SendOrPostCallback(InvokeHandlers);
}
/// <summary>Initializes the <see cref="Progress{T}"/> with the specified callback.</summary>
/// <param name="handler">
/// A handler to invoke for each reported progress value. This handler will be invoked
/// in addition to any delegates registered with the <see cref="ProgressChanged"/> event.
/// Depending on the <see cref="SynchronizationContext"/> instance captured by
/// the <see cref="Progress{T}"/> at construction, it's possible that this handler instance
/// could be invoked concurrently with itself.
/// </param>
/// <exception cref="ArgumentNullException">The <paramref name="handler"/> is null (<see langword="Nothing" /> in Visual Basic).</exception>
public Progress(Action<T> handler) : this()
{
_handler = handler ?? throw new ArgumentNullException(nameof(handler));
}
/// <summary>Raised for each reported progress value.</summary>
/// <remarks>
/// Handlers registered with this event will be invoked on the
/// <see cref="SynchronizationContext"/> captured when the instance was constructed.
/// </remarks>
public event EventHandler<T>? ProgressChanged;
/// <summary>Reports a progress change.</summary>
/// <param name="value">The value of the updated progress.</param>
protected virtual void OnReport(T value)
{
// If there's no handler, don't bother going through the sync context.
// Inside the callback, we'll need to check again, in case
// an event handler is removed between now and then.
Action<T>? handler = _handler;
EventHandler<T>? changedEvent = ProgressChanged;
if (handler != null || changedEvent != null)
{
// Post the processing to the sync context.
// (If T is a value type, it will get boxed here.)
_synchronizationContext?.Post(_invokeHandlers, value);
}
}
/// <summary>Reports a progress change.</summary>
/// <param name="value">The value of the updated progress.</param>
void IProgress<T>.Report(T value) { OnReport(value); }
/// <summary>Invokes the action and event callbacks.</summary>
/// <param name="state">The progress value.</param>
private void InvokeHandlers(object? state)
{
T value = (T)state!;
Action<T>? handler = _handler;
EventHandler<T>? changedEvent = ProgressChanged;
handler?.Invoke(value);
changedEvent?.Invoke(this, value);
}
}
/// <summary>Holds static values for <see cref="Progress{T}"/>.</summary>
/// <remarks>This avoids one static instance per type T.</remarks>
internal static class ProgressStatics
{
/// <summary>A default synchronization context that targets the ThreadPool.</summary>
internal static readonly SynchronizationContext DefaultContext = new();
}
}
#endif

View File

@@ -0,0 +1,131 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
// TODO: Figure out how to get version numbers
public class ActiveMARK : IContentCheck, IExecutableCheck<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckContents(string file, byte[] fileContent, bool includeDebug)
{
// TODO: Obtain a sample to find where this string is in a typical executable
if (includeDebug)
{
var contentMatchSets = new List<ContentMatchSet>
{
// " " + (char)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(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 (Unconfirmed - Please report to us on Github)"),
};
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
}
return null;
}
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the entry point data, if it exists
if (pex.EntryPointData != null)
{
#if NET20
// Found in "Zuma.exe"
if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, 0x04, 0xF0, 0x86, 0x00, 0x68, 0x30 }))
return "ActiveMark v5.3.1078 (Packer Version)";
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, null, null, null, null, 0xEB }))
return "ActiveMark -> Trymedia Systems Inc. (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, null, null, null, null, 0x33, 0xED, 0x55, 0x8B, 0xEC, 0xE8, null, null, null, null, 0x8B, 0xD0, 0x81, 0xE2, 0xFF, 0x00, 0x00, 0x00, 0x89, 0x15, null, null, null, null, 0x8B, 0xD0, 0xC1, 0xEA, 0x08, 0x81, 0xE2, 0xFF, 0x00, 0x00, 0x00, 0xA3, null, null, null, null, 0xD1, 0xE0, 0x0F, 0x93, 0xC3, 0x33, 0xC0, 0x8A, 0xC3, 0xA3, null, null, null, null, 0x68, 0xFF, 0x00, 0x00, 0x00, 0xE8, null, null, null, null, 0x6A, 0x00, 0xE8, null, null, null, null, 0xA3, null, null, null, null, 0xBB, null, null, null, null, 0xC7, 0x03, 0x44, 0x00, 0x00, 0x00 }))
return "ActiveMark -> Trymedia Systems Inc. (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x20, 0x2D, 0x2D, 0x4D, 0x50, 0x52, 0x4D, 0x4D, 0x47, 0x56, 0x41, 0x2D, 0x2D, 0x00, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6F, 0x78, 0x41, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67 }))
return "ActiveMARK 5.x -> Trymedia Systems Inc. (h) (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x20, 0x2D, 0x2D, 0x4D, 0x50, 0x52, 0x4D, 0x4D, 0x47, 0x56, 0x41, 0x2D, 0x2D, 0x00, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6F, 0x78, 0x41, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x2E, 0x0D, 0x0A, 0x50, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x20, 0x75, 0x6E, 0x6C, 0x6F, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x00, 0x57, 0x61, 0x72, 0x6E, 0x69, 0x6E, 0x67 }))
return "ActiveMARK 5.x -> Trymedia Systems,Inc. (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x79, 0x11, 0x7F, 0xAB, 0x9A, 0x4A, 0x83, 0xB5, 0xC9, 0x6B, 0x1A, 0x48, 0xF9, 0x27, 0xB4, 0x25 }))
return "ActiveMARK[TM] (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x79, 0x07, 0x0F, 0xB7, 0x07, 0x47, 0x50, 0x47, 0xB9, 0x57, 0x48, 0xF2, 0xAE, 0x55, 0xFF, 0x96, 0x84, null, 0x00, 0x00, 0x09, 0xC0, 0x74, 0x07, 0x89, 0x03, 0x83, 0xC3, 0x04, 0xEB, 0xD8, 0xFF, 0x96, 0x88, null, 0x00, 0x00, 0x61, 0xE9, null, null, null, 0xFF }))
return "ActiveMARK[TM] R5.31.1140 -> Trymedia (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0xBE, 0x48, 0x01, 0x40, 0x00, 0xAD, 0x8B, 0xF8, 0x95, 0xA5, 0x33, 0xC0, 0x33, 0xC9, 0xAB, 0x48, 0xAB, 0xF7, 0xD8, 0xB1, 0x04, 0xF3, 0xAB, 0xC1, 0xE0, 0x0A, 0xB5, 0x1C, 0xF3, 0xAB, 0xAD, 0x50, 0x97, 0x51, 0xAD, 0x87, 0xF5, 0x58, 0x8D, 0x54, 0x86, 0x5C, 0xFF, 0xD5, 0x72, 0x5A, 0x2C, 0x03, 0x73, 0x02, 0xB0, 0x00, 0x3C, 0x07, 0x72, 0x02, 0x2C, 0x03, 0x50, 0x0F, 0xB6, 0x5F, 0xFF, 0xC1, 0xE3, 0x03, 0xB3, 0x00, 0x8D, 0x1C, 0x5B, 0x8D, 0x9C, 0x9E, 0x0C, 0x10, 0x00, 0x00, 0xB0, 0x01, 0x67, 0xE3, 0x29, 0x8B, 0xD7, 0x2B, 0x56, 0x0C, 0x8A, 0x2A, 0x33, 0xD2, 0x84, 0xE9, 0x0F, 0x95, 0xC6, 0x52, 0xFE, 0xC6, 0x8A, 0xD0, 0x8D, 0x14, 0x93, 0xFF, 0xD5, 0x5A, 0x9F, 0x12, 0xC0, 0xD0, 0xE9, 0x74, 0x0E, 0x9E, 0x1A, 0xF2, 0x74, 0xE4, 0xB4, 0x00, 0x33, 0xC9, 0xB5, 0x01, 0xFF, 0x55, 0xCC, 0x33, 0xC9, 0xE9, 0xDF, 0x00, 0x00, 0x00, 0x8B, 0x5E, 0x0C, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x73, 0x50, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x72, 0x1B, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x72, 0x2B, 0x3C, 0x07, 0xB0, 0x09, 0x72, 0x02, 0xB0, 0x0B, 0x50, 0x8B, 0xC7, 0x2B, 0x46, 0x0C, 0xB1, 0x80, 0x8A, 0x00, 0xEB, 0xCF, 0x83, 0xC2, 0x60, 0xFF, 0xD5, 0x87, 0x5E, 0x10, 0x73, 0x0D, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x87, 0x5E, 0x14, 0x73, 0x03, 0x87, 0x5E, 0x18, 0x3C, 0x07, 0xB0, 0x08, 0x72, 0x02, 0xB0, 0x0B, 0x50, 0x53, 0x8D, 0x96, 0x7C, 0x07, 0x00, 0x00, 0xFF, 0x55, 0xD0, 0x5B, 0x91, 0xEB, 0x77, 0x3C, 0x07, 0xB0, 0x07, 0x72, 0x02, 0xB0, 0x0A, 0x50, 0x87, 0x5E, 0x10, 0x87, 0x5E, 0x14, 0x89, 0x5E, 0x18, 0x8D, 0x96, 0xC4, 0x0B, 0x00, 0x00, 0xFF, 0x55, 0xD0, 0x50, 0x48 }))
return "ActiveMARK 5.x -> Trymedia Systems,Inc. (h) (Unconfirmed - Please report to us on Github)";
#else
// Found in "Zuma.exe"
if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, 0x04, 0xF0, 0x86, 0x00, 0x68, 0x30 }))
return "ActiveMark v5.3.1078 (Packer Version)";
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, null, null, null, null, 0xEB }))
return "ActiveMark -> Trymedia Systems Inc. (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, null, null, null, null, 0x33, 0xED, 0x55, 0x8B, 0xEC, 0xE8, null, null, null, null, 0x8B, 0xD0, 0x81, 0xE2, 0xFF, 0x00, 0x00, 0x00, 0x89, 0x15, null, null, null, null, 0x8B, 0xD0, 0xC1, 0xEA, 0x08, 0x81, 0xE2, 0xFF, 0x00, 0x00, 0x00, 0xA3, null, null, null, null, 0xD1, 0xE0, 0x0F, 0x93, 0xC3, 0x33, 0xC0, 0x8A, 0xC3, 0xA3, null, null, null, null, 0x68, 0xFF, 0x00, 0x00, 0x00, 0xE8, null, null, null, null, 0x6A, 0x00, 0xE8, null, null, null, null, 0xA3, null, null, null, null, 0xBB, null, null, null, null, 0xC7, 0x03, 0x44, 0x00, 0x00, 0x00 }))
return "ActiveMark -> Trymedia Systems Inc. (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x20, 0x2D, 0x2D, 0x4D, 0x50, 0x52, 0x4D, 0x4D, 0x47, 0x56, 0x41, 0x2D, 0x2D, 0x00, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6F, 0x78, 0x41, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67 }))
return "ActiveMARK 5.x -> Trymedia Systems Inc. (h) (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x20, 0x2D, 0x2D, 0x4D, 0x50, 0x52, 0x4D, 0x4D, 0x47, 0x56, 0x41, 0x2D, 0x2D, 0x00, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6F, 0x78, 0x41, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x2E, 0x0D, 0x0A, 0x50, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x20, 0x75, 0x6E, 0x6C, 0x6F, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x00, 0x57, 0x61, 0x72, 0x6E, 0x69, 0x6E, 0x67 }))
return "ActiveMARK 5.x -> Trymedia Systems,Inc. (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x79, 0x11, 0x7F, 0xAB, 0x9A, 0x4A, 0x83, 0xB5, 0xC9, 0x6B, 0x1A, 0x48, 0xF9, 0x27, 0xB4, 0x25 }))
return "ActiveMARK[TM] (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x79, 0x07, 0x0F, 0xB7, 0x07, 0x47, 0x50, 0x47, 0xB9, 0x57, 0x48, 0xF2, 0xAE, 0x55, 0xFF, 0x96, 0x84, null, 0x00, 0x00, 0x09, 0xC0, 0x74, 0x07, 0x89, 0x03, 0x83, 0xC3, 0x04, 0xEB, 0xD8, 0xFF, 0x96, 0x88, null, 0x00, 0x00, 0x61, 0xE9, null, null, null, 0xFF }))
return "ActiveMARK[TM] R5.31.1140 -> Trymedia (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0xBE, 0x48, 0x01, 0x40, 0x00, 0xAD, 0x8B, 0xF8, 0x95, 0xA5, 0x33, 0xC0, 0x33, 0xC9, 0xAB, 0x48, 0xAB, 0xF7, 0xD8, 0xB1, 0x04, 0xF3, 0xAB, 0xC1, 0xE0, 0x0A, 0xB5, 0x1C, 0xF3, 0xAB, 0xAD, 0x50, 0x97, 0x51, 0xAD, 0x87, 0xF5, 0x58, 0x8D, 0x54, 0x86, 0x5C, 0xFF, 0xD5, 0x72, 0x5A, 0x2C, 0x03, 0x73, 0x02, 0xB0, 0x00, 0x3C, 0x07, 0x72, 0x02, 0x2C, 0x03, 0x50, 0x0F, 0xB6, 0x5F, 0xFF, 0xC1, 0xE3, 0x03, 0xB3, 0x00, 0x8D, 0x1C, 0x5B, 0x8D, 0x9C, 0x9E, 0x0C, 0x10, 0x00, 0x00, 0xB0, 0x01, 0x67, 0xE3, 0x29, 0x8B, 0xD7, 0x2B, 0x56, 0x0C, 0x8A, 0x2A, 0x33, 0xD2, 0x84, 0xE9, 0x0F, 0x95, 0xC6, 0x52, 0xFE, 0xC6, 0x8A, 0xD0, 0x8D, 0x14, 0x93, 0xFF, 0xD5, 0x5A, 0x9F, 0x12, 0xC0, 0xD0, 0xE9, 0x74, 0x0E, 0x9E, 0x1A, 0xF2, 0x74, 0xE4, 0xB4, 0x00, 0x33, 0xC9, 0xB5, 0x01, 0xFF, 0x55, 0xCC, 0x33, 0xC9, 0xE9, 0xDF, 0x00, 0x00, 0x00, 0x8B, 0x5E, 0x0C, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x73, 0x50, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x72, 0x1B, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x72, 0x2B, 0x3C, 0x07, 0xB0, 0x09, 0x72, 0x02, 0xB0, 0x0B, 0x50, 0x8B, 0xC7, 0x2B, 0x46, 0x0C, 0xB1, 0x80, 0x8A, 0x00, 0xEB, 0xCF, 0x83, 0xC2, 0x60, 0xFF, 0xD5, 0x87, 0x5E, 0x10, 0x73, 0x0D, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x87, 0x5E, 0x14, 0x73, 0x03, 0x87, 0x5E, 0x18, 0x3C, 0x07, 0xB0, 0x08, 0x72, 0x02, 0xB0, 0x0B, 0x50, 0x53, 0x8D, 0x96, 0x7C, 0x07, 0x00, 0x00, 0xFF, 0x55, 0xD0, 0x5B, 0x91, 0xEB, 0x77, 0x3C, 0x07, 0xB0, 0x07, 0x72, 0x02, 0xB0, 0x0A, 0x50, 0x87, 0x5E, 0x10, 0x87, 0x5E, 0x14, 0x89, 0x5E, 0x18, 0x8D, 0x96, 0xC4, 0x0B, 0x00, 0x00, 0xFF, 0x55, 0xD0, 0x50, 0x48 }))
return "ActiveMARK 5.x -> Trymedia Systems,Inc. (h) (Unconfirmed - Please report to us on Github)";
#endif
}
// Get the .data section strings, if they exist
var strs = pex.GetLastSectionStrings(".data");
if (strs != null)
{
if (strs.Exists(s => s.Contains("MPRMMGVA"))
&& strs.Exists(s => s.Contains("This application cannot run with an active debugger in memory.")))
{
return "ActiveMARK 6.x";
}
}
// Get "REGISTRY, AMINTERNETPROTOCOL" resource items
var resources = pex.FindResourceByNamedType("REGISTRY, AMINTERNETPROTOCOL");
if (resources.Any())
{
bool match = resources
.Select(r => r == null ? string.Empty : Encoding.ASCII.GetString(r))
.Any(r => r.Contains("ActiveMARK"));
if (match)
return "ActiveMARK";
}
// Get the overlay data, if it exists
if (pex.OverlayStrings != null)
{
if (pex.OverlayStrings.Exists(s => s.Contains("TMSAMVOH")))
return "ActiveMARK";
}
// Get the last .bss section strings, if they exist
strs = pex.GetLastSectionStrings(".bss");
if (strs != null)
{
if (strs.Exists(s => s.Contains("TMSAMVOF")))
return "ActiveMARK";
}
return null;
}
}
}

View File

@@ -0,0 +1,109 @@
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
/// <summary>
/// AegiSoft License Manager was made AegiSoft, which was later bought by Real Networks, the makes of RealArcade (https://www.crunchbase.com/organization/aegisoft).
/// It allowed publishers to give users a time-based free trial of software.
/// Based on "Asc005.dll" and "Asc006.exe", AegiSoft License Manager may also have been referred to as "Software-On-Demand License Manager", or it may just be a distinct component of the larger product.
/// The single sample investigated was only able to run on Windows 9x (Redump entry 73521/IA item "Nova_HoyleCasino99USA").
/// Based on the packaging from IA item "Nova_HoyleCasino99USA", it seems that additional software from "www.1-800-software.com" is likely to be protected with AegiSoft License Manager or other DRM.
/// References and further information:
/// https://pitchbook.com/profiles/company/118805-59
/// https://web.archive.org/web/19990417191351/http://www.aegisoft.com:80/
/// </summary>
public class AegiSoft : IExecutableCheck<PortableExecutable>, IPathCheck
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// There are possibly identifying Product Names for some files used in AegiSoft License Manager, but they were deemed too overmatching to use for the time being (Found in Redump entry 73521/IA item "Nova_HoyleCasino99USA")..
// "Asc001.dll" has the Product Name "Install Dynamic Link Library".
// "Asc002.dll" has the Product Name "Transact Dynamic Link Library".
// "Asc003.dll" has the Product Name "Uninstall Dynamic Link Library".
// "Asc005.dll" has the Product Name "OrderWizard Dynamic Link Library".
// "Asc006.exe" has the Product Name "AGENT Application".
// These are possibly identifying export name table strings
// "Asc001.dll" has the strings "AscCheck" and "AscInstall"
// "Asc002.dll" has the string "AscActivate"
// Get string table resources
var resource = pex.FindStringTableByEntry("AegiSoft License Manager");
if (resource.Any())
return "AegiSoft License Manager";
// Get the .data/DATA section, if it exists
var dataSectionRaw = pex.GetFirstSectionData(".data") ?? pex.GetFirstSectionData("DATA");
if (dataSectionRaw != null)
{
var matchers = new List<ContentMatchSet>
{
// Found in "Asc001.dll", "Asc002.dll", "Asc003.dll", "Asc005.dll", "Asc006.exe", and "AscLM.cpl" (Redump entry 73521/IA item "Nova_HoyleCasino99USA").
// ÿÿÿÿ\\.\ASCLM
new(new byte?[]
{
0xFF, 0xFF, 0xFF, 0xFF, 0x5C, 0x5C, 0x2E, 0x5C,
0x41, 0x53, 0x43, 0x4C, 0x4D
}, "AegiSoft License Manager"),
};
var match = MatchUtil.GetFirstMatch(file, dataSectionRaw, matchers, includeDebug);
if (!string.IsNullOrEmpty(match))
return match;
}
return null;
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// Found in Redump entry 73521/IA item "Nova_HoyleCasino99USA".
new(new FilePathMatch("AscLM.cpl"), "AegiSoft License Manager"),
new(new FilePathMatch("AscLM.vxd"), "AegiSoft License Manager"),
new(new FilePathMatch("AscLMd.vxd"), "AegiSoft License Manager"),
// There are a few other files present, but the file names on their own may be too overmatching. Due to the small sample size, it's not sure if these files are always present together.
// These files are "Asc001.dll", "Asc002.dll", "Asc003.dll", "Asc005.dll", and "Asc006.exe" (Found in Redump entry 73521/IA item "Nova_HoyleCasino99USA").
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string? CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
// Found in Redump entry 73521/IA item "Nova_HoyleCasino99USA".
new(new FilePathMatch("AscLM.cpl"), "AegiSoft License Manager"),
new(new FilePathMatch("AscLM.vxd"), "AegiSoft License Manager"),
new(new FilePathMatch("AscLMd.vxd"), "AegiSoft License Manager"),
// There are a few other files present, but the file names on their own may be too overmatching. Due to the small sample size, it's not sure if these files are always present together.
// These files are "Asc001.dll", "Asc002.dll", "Asc003.dll", "Asc005.dll", and "Asc006.exe" (Found in Redump entry 73521/IA item "Nova_HoyleCasino99USA").
// The "DATA.TAG" file in the "AgeiSoft" folder is an INI that includes:
// Company=AegiSoft Corporation
// Application=AegiSoft License Manager
// Version=2.1
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

@@ -0,0 +1,9 @@
namespace BinaryObjectScanner.Protection
{
public class AlphaAudio
{
// TODO: Implement - http://settec.net/eng/pro_cd.html
// References and further information:
// https://www.cdmediaworld.com/hardware/cdrom/cd_protections_alpha.shtml
}
}

View File

@@ -0,0 +1,40 @@
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
namespace BinaryObjectScanner.Protection
{
/// <summary>
/// Alpha-DVD is a DVD-Video copy protection created by SETTEC.
/// References and further information:
/// http://www.gonsuke.co.jp/protect.html
/// http://copy2.info/copy_protect.html
/// http://s2000.yokinihakarae.com/sub03-10-2(DVD).html
/// https://www.cdmediaworld.com/hardware/cdrom/cd_protections_alpha.shtml
/// </summary>
public class AlphaDVD : IPathCheck
{
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
new(new FilePathMatch("PlayDVD.exe"), "Alpha-DVD (Unconfirmed - Please report to us on Github)"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string? CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
new(new FilePathMatch("PlayDVD.exe"), "Alpha-DVD (Unconfirmed - Please report to us on Github"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

@@ -0,0 +1,91 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
/// <summary>
/// Alpha-ROM is a form of copy protection created by SETTEC. It is known to make use of twin sectors as well as region locking.
/// Later forms of Alpha-ROM appear to be digital only, and it's currently unsure what forms of protection the digital only version includes, except that it does make use of region locking.
/// It seems that Alpha-ROM was used in Visual Novels using certain game engines, most notably RealLive and Siglus (https://forums.fuwanovel.net/topic/20927-cannot-crack-siglus-engine-with-alpharom/).
/// Not every Siglus engine game uses Alpha-ROM (Source: https://sample9.dmm.co.jp/digital/pcgame/vsat_0263/vsat_0263t.zip {Official trial mirror}).
/// Not every RealLive engine game uses Alpha-ROM (Source: IA item "Kanon_Standard_Edition_Japan").
/// Alpha-ROM also seems to have made use of something called "Alpha-DPS" for non-executable data files (http://www.gonsuke.co.jp/protect.html).
/// Example of Alpha-ROM (official trial download mirrors):
/// (Siglus Engine)
/// http://suezou.dyndns.org/dl2018/key/summer_pokets/Summer_Pockets_trial.zip
/// http://mirror.studio-ramble.com/upload/300/201103/RewriteTE_Ver200.zip
/// http://suezou.dyndns.org/dl2012/tone-works/hatsukoi1-1/hatsukoi_tr_web.zip
/// (RealLive Engine)
/// http://suezou.dyndns.org/dl2020/hadashi/princess_heart_link/phl_trial.exe
/// https://archive.org/details/little-busters-regular-edition-iso-only-2007
/// Games that may have Alpha-ROM:
/// http://cpdb.kemuri-net.com/ (Protection database that includes many different protections, including Alpha-ROM).
/// https://w.atwiki.jp/tirasinoura/pages/3.html (List of games with Alpha-ROM, and explains some version differences).
/// https://vndb.org/r?f=fwSiglusEngine- (VNs made with an engine known to use Alpha-ROM).
/// https://vndb.org/r?f=fwRealLive- (VNs made with an engine known to use Alpha-ROM).
/// References and further information:
/// http://hhg.sakura.ne.jp/cd-dvd/dust/alpha/alpha_index.htm
/// https://www.weblio.jp/content/Alpha-ROM
/// https://ameblo.jp/michael-j-fox/entry-10046574609.html
/// http://s2000.yokinihakarae.com/sub03-10-2(DVD).html
/// https://www.cdmediaworld.com/hardware/cdrom/cd_protections_alpha.shtml
/// Special thanks to Bestest for researching this protection and helping make further improvements possible!
/// </summary>
// TODO: Alternative string possibilities:
// - \AlphaDiscLog.txt
// - \SETTEC
// - AlphaROM
// - SETTEC0000SETTEC1111
// - SOFTWARE\SETTEC
// TODO: Are there version numbers?
public class AlphaROM : IExecutableCheck<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// TODO: Add support for detecting Alpha-ROM found in older games made with the RealLive engine.
// TODO: Add version detection for Alpha-ROM.
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the .data/DATA section strings, if they exist
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
if (strs != null)
{
if (strs.Exists(s => s.Contains("\\SETTEC")))
return "Alpha-ROM";
if (strs.Exists(s => s.Contains("SETTEC0000")))
return "Alpha-ROM";
}
// Get the .rdata section strings, if they exist
strs = pex.GetFirstSectionStrings(".rdata");
if (strs != null)
{
if (strs.Exists(s => s.Contains("This Game is Japan Only")))
return "Alpha-ROM";
// Found in "Filechk.exe" in Redump entry 115358.
if (strs.Exists(s => s.Contains("AlphaCheck.exe")))
return "Alpha-ROM";
// Found in "Uninstall.exe" in Redump entry 115358.
if (strs.Exists(s => s.Contains("AlphaCheck.dat")))
return "Alpha-ROM";
}
// Get the overlay data, if it exists
if (pex.OverlayStrings != null)
{
// Found in Redump entry 84122.
if (pex.OverlayStrings.Exists(s => s.Contains("SETTEC0000")))
return "Alpha-ROM";
}
return null;
}
}
}

View File

@@ -0,0 +1,60 @@
using System;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
/// <summary>
/// Armadillo was a license manager, packer, and DRM by "The Silicon Realm Toolworks": https://web.archive.org/web/20030203101931/http://www.siliconrealms.com/armadillo.shtml
/// They were later bought by Digital River, and updated their website: https://web.archive.org/web/20031203021152/http://www.siliconrealms.com/armadillo.shtml
/// A new updated version named "SoftwarePassport" was released: https://web.archive.org/web/20040423044529/http://siliconrealms.com/softwarepassport/popup.shtml
/// Later copy of the website, with SoftwarePassport being named instead of Armadillo: https://web.archive.org/web/20040804032608/http://www.siliconrealms.com/armadillo.shtml
/// It appears as though both Armadillo and SoftwarePassport were being released at the same time, possibly with Armadillo acting as the core component and SoftwarePassport being supplementary: https://web.archive.org/web/20050619013312/http://siliconrealms.com/srt-news.shtml
/// Digital River itself also advertised Armadillo at first: https://web.archive.org/web/20040116043029/http://www.digitalriver.com:80/corporate/solutions06.shtml
/// But then only advertised SoftwarePassport once it was released: https://web.archive.org/web/20040604065907/http://www.digitalriver.com/corporate/solutions06.shtml
/// </summary>
// TODO: Add extraction
// TODO: Add version checking, if possible
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class Armadillo : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the .nicode section, if it exists
bool nicodeSection = pex.ContainsSection(".nicode", exact: true);
if (nicodeSection)
return "Armadillo";
// Loop through all "extension" sections -- usually .data1 or .text1
if (pex.SectionNames != null)
{
foreach (var sectionName in Array.FindAll(pex.SectionNames, s => s != null && s.EndsWith("1")))
{
// Get the section strings, if they exist
var strs = pex.GetFirstSectionStrings(sectionName);
if (strs != null)
{
if (strs.Exists(s => s.Contains("ARMDEBUG")))
return "Armadillo";
}
}
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
return false;
}
}
}

View File

@@ -0,0 +1,55 @@
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
namespace BinaryObjectScanner.Protection
{
/// <summary>
/// Bitpool is a copy protection found most commonly in German releases.
/// It always has errors present on the disc (either between 1-4, or between 1,000-10,000+ depending on generation), and makes use of padded dummy files to prevent copying.
/// <see href="https://github.com/TheRogueArchivist/DRML/blob/main/entries/Bitpool/Bitpool.md"/>
/// </summary>
public class Bitpool : IPathCheck
{
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
new(new FilePathMatch("bitpool.rsc"), "Bitpool"),
new(new FilePathMatch("CD.IDX"), "Bitpool"),
// Completely empty file present on multiple discs with Bitpool (Redump entries 52626 and 50229).
new(new FilePathMatch("LEADOUT.OFS"), "Bitpool"),
// A set of 4 identically sized (within the same game, not between games), corrupted/padded files present in several games (Redump entries 31782 and 35476).
// Both examples with only having the first letter uppercase and as the whole file name being uppercase have been seen.
new(
[
new FilePathMatch("Crc_a"),
new FilePathMatch("Crc_b"),
new FilePathMatch("Crc_c"),
new FilePathMatch("Crc_d"),
], "Bitpool"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string? CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
new(new FilePathMatch("bitpool.rsc"), "Bitpool"),
new(new FilePathMatch("CD.IDX"), "Bitpool"),
// Completely empty file present on multiple discs with Bitpool (Redump entries 52626 and 50229).
new(new FilePathMatch("LEADOUT.OFS"), "Bitpool"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

@@ -0,0 +1,160 @@
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
/// <summary>
/// ByteShield, Inc. (https://web.archive.org/web/20070216191623/http://www.byteshield.net/) was founded in 2004 (https://www.apollo.io/companies/ByteShield--Inc-/54a1357069702d4494ab9b00).
/// There is a website seemingly belonging to them that's been archived as early as 2004, but there doesn't appear to be anything useful on it (https://web.archive.org/web/20040615001350/http://byteshield.com/).
/// The ByteShield DRM itself is online activation based, using randomly generated activation codes it refers to as DACs (https://web.archive.org/web/20080921231346/http://www.byteshield.net/byteshield_whitepaper_0005.pdf).
/// It appears that ByteShield advertised itself around online web forums (https://gamedev.net/forums/topic/508082-net-copy-protection-c/508082/ and https://cboard.cprogramming.com/tech-board/106642-how-add-copy-protection-software.html).
/// Patent relating to ByteShield: https://patentimages.storage.googleapis.com/ed/76/c7/d98a56aeeca2e9/US7716474.pdf and https://patents.google.com/patent/US20100212028.
///
/// Games known to use it:
/// Line Rider 2: Unbound (https://fileforums.com/showthread.php?t=86909).
/// Football Manager 2011 (https://community.sigames.com/forums/topic/189163-for-those-of-you-struggling-with-byteshield-activation-issues/).
///
/// Publishers known to use it:
/// PAN Vision (http://web.archive.org/web/20120413160122/http://www.byteshield.net/ -> Company -> Milestones).
/// JIAN (http://web.archive.org/web/20120413160122/http://www.byteshield.net/ -> Company -> Milestones).
/// GamersGate (http://web.archive.org/web/20120413160122/http://www.byteshield.net/ -> Company -> Milestones).
/// Akella (http://web.archive.org/web/20120413160122/http://www.byteshield.net/ -> Customers).
/// All Interactive Distributuion (http://web.archive.org/web/20120413160122/http://www.byteshield.net/ -> Customers).
/// Beowulf (http://web.archive.org/web/20120413160122/http://www.byteshield.net/ -> Customers).
/// CroVortex (http://web.archive.org/web/20120413160122/http://www.byteshield.net/ -> Customers).
/// N3V Games (http://web.archive.org/web/20120413160122/http://www.byteshield.net/ -> Customers).
/// OnePlayS (http://web.archive.org/web/20120413160122/http://www.byteshield.net/ -> Customers).
/// YAWMA (http://web.archive.org/web/20120413160122/http://www.byteshield.net/ -> Customers).
///
/// Further links and resources:
/// https://www.cdmediaworld.com/hardware/cdrom/cd_protections_byteshield.shtml
/// https://www.bcs.org/articles-opinion-and-research/is-there-anything-like-acceptable-drm/
/// https://forums.auran.com/trainz/showthread.php?106673-Trainz-and-DRM/page22
/// https://www.auran.com/planetauran/byteshield_drm.php
/// https://www.ftc.gov/sites/default/files/documents/public_comments/ftc-town-hall-address-digital-rights-management-technologies-event-takes-place-wednesday-march-25/539814-00707.pdf
/// https://www.gamesindustry.biz/byteshield-drm-system-now-protecting-over-200-games
/// </summary>
public class ByteShield : IExecutableCheck<PortableExecutable>, IPathCheck
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Found in "LineRider2.exe" in Redump entry 6236
var name = pex.FileDescription;
if (name?.Equals("ByteShield Client") == true)
return $"ByteShield Activation Client {pex.GetInternalVersion()}";
// Found in "LineRider2.exe" in Redump entry 6236
name = pex.InternalName;
if (name?.Equals("ByteShield") == true)
return $"ByteShield Activation Client {pex.GetInternalVersion()}";
// Found in "LineRider2.exe" in Redump entry 6236
name = pex.OriginalFilename;
if (name?.Equals("ByteShield.EXE") == true)
return $"ByteShield Activation Client {pex.GetInternalVersion()}";
// Found in "LineRider2.exe" in Redump entry 6236
name = pex.ProductName;
if (name?.Equals("ByteShield Client") == true)
return $"ByteShield Activation Client {pex.GetInternalVersion()}";
// Found in "ByteShield.dll" in Redump entry 6236
name = pex.Model.ExportTable?.ExportDirectoryTable?.Name;
if (name?.Equals("ByteShield Client") == true)
return "ByteShield Component Module";
// Found in "LineRider2.exe" in Redump entry 6236
var stMatch = pex.FindStringTableByEntry("ByteShield");
if (stMatch.Any())
return $"ByteShield Activation Client {pex.GetInternalVersion()}";
// Found in "LineRider2.exe" in Redump entry 6236
var dbMatch = pex.FindDialogByTitle("About ByteShield");
if (dbMatch.Any())
return "ByteShield";
// TODO: See if the version number is anywhere else
// TODO: Parse the version number out of the dialog box item
// Found in "LineRider2.exe" in Redump entry 6236
dbMatch = pex.FindDialogBoxByItemTitle("ByteShield Version 1.0");
if (dbMatch.Any())
return "ByteShield";
// Get the .data/DATA section strings, if they exist
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
if (strs != null)
{
// Found in "LineRider2.exe" in Redump entry 6236
if (strs.Exists(s => s?.Contains("ByteShield") == true))
return "ByteShield";
}
// Get the .rdata section strings, if they exist
strs = pex.GetFirstSectionStrings(".rdata");
if (strs != null)
{
// Found in "ByteShield.dll" in Redump entry 6236
if (strs.Exists(s => s?.Contains("Byte|Shield") == true))
return "ByteShield Component Module";
// Found in "ByteShield.dll" in Redump entry 6236
else if (strs.Exists(s => s?.Contains("Byteshield0") == true))
return "ByteShield Component Module";
// Found in "ByteShield.dll" in Redump entry 6236
else if (strs.Exists(s => s?.Contains("ByteShieldLoader") == true))
return "ByteShield Component Module";
}
// Get the .ret section strings, if they exist
strs = pex.GetFirstSectionStrings(".ret");
if (strs != null)
{
// TODO: Figure out if this specifically indicates if the file is encrypted
// Found in "LineRider2.bbz" in Redump entry 6236
if (strs.Exists(s => s?.Contains("ByteShield") == true))
return "ByteShield";
}
return null;
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
// TODO: Investigate reference to "bbz650.tmp" in "Byteshield.dll" (Redump entry 6236)
// Files with the ".bbz" extension are associated with ByteShield, but the extenstion is known to be used in other places as well.
var matchers = new List<PathMatchSet>
{
new(new FilePathMatch("Byteshield.dll"), "ByteShield Component Module"),
new(new FilePathMatch("Byteshield.ini"), "ByteShield"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string? CheckFilePath(string path)
{
// TODO: Investigate reference to "bbz650.tmp" in "Byteshield.dll" (Redump entry 6236)
// Files with the ".bbz" extension are associated with ByteShield, but the extenstion is known to be used in other places as well.
var matchers = new List<PathMatchSet>
{
new(new FilePathMatch("Byteshield.dll"), "ByteShield Component Module"),
new(new FilePathMatch("Byteshield.ini"), "ByteShield"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

@@ -0,0 +1,33 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
public class CDCheck : IExecutableCheck<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
var name = pex.Comments;
if (name?.Contains("CDCheck utlity for Microsoft Game Studios") == true)
return "Microsoft Game Studios CD Check";
// To broad to be of use
//name = pex.InternalName;
//if (name?.Contains("CDCheck") == true)
// return "Microsoft Game Studios CD Check";
// To broad to be of use
//name = pex.OriginalFilename;
//if (name?.Contains("CDCheck.exe") == true)
// return "Microsoft Game Studios CD Check";
return null;
}
}
}

View File

@@ -0,0 +1,241 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
/// <summary>
/// TODO: Investigate "Cops Copylock II" (https://www.cbmstuff.com/forum/showthread.php?tid=488).
/// TODO: Investigate additional products mentioned on the Link Data Security website (https://www.linkdatasecurity.com/index.htm#/protection-products/overview).
/// `AgentHugo.exe`
/// Embedded PE executable in one of the NE sections
/// `AgentHugo.exe` / `NE.EXE` (1.46) / `NETINST.EXE` (1.48) / `NETINST.QZ_`
/// Embedded PKZIP archive that may contain the CD-Cops files
/// `CDCOPS.DLL` (1.46) / `CDCOPS.DLL` (1.48)
/// `WINCOPS.INI`
///
/// TODO: Investigate if "DVD-Cops" is a separate product, or simply what CD-Cops is referred to when used on a DVD.
///
/// Known versions of CD-Cops:
/// * 1.08 (Unconfirmed) (Redump entry 84517).
/// * 1,13[sic] (Confirmed) ("FGP.exe" in IA item "flaklypa-grand-prix-gullutgave-2cd"/Redump entries 108167-108168 patched with https://web.archive.org/web/20040307124358/http://www.caprino.no:80/download/fgpgold_upd4.exe).
/// * 1.21 (Unconfirmed) (Redump entry 91713).
/// * 1,22[sic] (Confirmed) ("FGP.exe" in IA item "flaklypa-grand-prix-gullutgave-2cd"/Redump entries 108167-108168 patched with https://web.archive.org/web/20030430194917/http://www.caprino.no:80/download/fgpgold_upd2.exe).
/// * 1,28[sic] (Confirmed) ("RunMenu.exe" in IA item "Faculty_Edition_People_Problems_and_Power_by_Joseph_Unekis_Textbytes").
/// * 1,31[sic] (Confirmed) ("FGP.exe" in IA item "flaklypa-grand-prix-gullutgave-2cd"/Redump entries 108167-108168).
/// * 1.31 (Confirmed) ("FGP.exe" in IA item "flaklypa-grand-prix-gullutgave-2cd"/Redump entries 108167-108168 patched with Patch 11).
/// * 1.46 (Confirmed) ("FGP.exe" in IA item "flaklypa-grand-prix-gullutgave-2cd"/Redump entries 108167-108168 patched with https://web.archive.org/web/20210103064517/http://www.caprino.no/download/FGPGOLD_UPD12.exe)
/// * 1,63[sic] (Confirmed) ("FGP.exe" in IA item "flaklypa-grand-prix-gullutgave-2cd"/Redump entries 108167-108168 patched with https://web.archive.org/web/20060926082522/http://www.caprino.no:80/download/fgpgold_upd7.exe).
/// * 1.72 (Confirmed) ("h3blade.exe" in Redump entry 85077).
/// * 1.73 (Confirmed) ("WETFLIPPER.EXE" in IA item "LULA_Erotic_Pinball_-_Windows95_Eng).
/// * 1,81[sic] (Confirmed) ("FGP.exe" in IA item "flaklypa-grand-prix-gullutgave-2cd"/Redump entries 108167-108168 patched with https://web.archive.org/web/20030308040529/http://www.caprino.no:80/download/fgpgold_upd1.exe).
/// * 2.03 (Confirmed) ("HyperBowl.exe" in IA item "hyperbowl_20190626").
///
/// Known versions of DVD-Cops:
/// * 1.69 (Confirmed) ("FGP.exe" in IA item "flaklypa-grand-prix-dvd"/Redump entry 108169).
///
/// Known samples of CD-Cops include:
/// * IA item "der-brockhaus-multimedial-2002-premium".
/// * IA item "der-brockhaus-multimedial-2003-premium".
/// * IA item "SCIENCESENCYCLOPEDIAV2.0ARISSCD1".
/// * IA item "SCIENCESENCYCLOPEDIAV2.0ARISSCD2".
/// * IA item "Triada_Russian_DVD_Complete_Collection_of_Erotic_Games".
/// * IA item "LULA_Erotic_Pinball_-_Windows95_Eng".
/// * IA item "flaklypa-grand-prix-gullutgave-2cd"/Redump entries 108167-108168.
/// * Patches for "flaklypa-grand-prix-gullutgave-2cd"/Redump entries 108167-108168, found at https://web.archive.org/web/*/http://www.caprino.no/download/* (FGPGOLD_UPD files).
/// * IA item "hyperbowl_20190626"/"hyperbowl-arcade-edition".
/// * Redump entries 51403(?), 84517, and 85077.
///
/// Known samples of DVD-Cops include:
/// * IA item "flaklypa-grand-prix-dvd"/Redump entry 108169.
///
/// Known samples of WEB-Cops include:
/// * https://web.archive.org/web/20120616074941/http://icm.games.tucows.com/files2/HyperDemo-109a.exe
///
/// A sample of CD-Cops that makes use of encrypted PDFs (LDSCRYPT) can be found in IA item "Faculty_Edition_People_Problems_and_Power_by_Joseph_Unekis_Textbytes".
///
/// List of applications that have CD/DVD/WEB-Cops relating to a Windows update: https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/924867
/// </summary>
public class CDDVDCops : IContentCheck, IExecutableCheck<NewExecutable>, IExecutableCheck<PortableExecutable>, IPathCheck
{
// TODO: Investigate reference to "CD32COPS.DLL" in "WETFLIPP.QZ_" in IA item "Triada_Russian_DVD_Complete_Collection_of_Erotic_Games".
/// <inheritdoc/>
public string? CheckContents(string file, byte[] fileContent, bool includeDebug)
{
// TODO: Obtain a sample to find where this string is in a typical executable
if (includeDebug)
{
var contentMatchSets = new List<ContentMatchSet>
{
// TODO: Remove from here once it's confirmed that no PE executables contain this string
// CD-Cops, ver.
new(new byte?[]
{
0x43, 0x44, 0x2D, 0x43, 0x6F, 0x70, 0x73, 0x2C,
0x20, 0x20, 0x76, 0x65, 0x72, 0x2E, 0x20
}, GetVersion, "CD-Cops (Unconfirmed - Please report to us on Github)"),
// // DVD-Cops, ver.
new(new byte?[]
{
0x44, 0x56, 0x44, 0x2D, 0x43, 0x6F, 0x70, 0x73,
0x2C, 0x20, 0x20, 0x76, 0x65, 0x72, 0x2E, 0x20
}, GetVersion, "DVD-Cops (Unconfirmed - Please report to us on Github)"),
};
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
}
return null;
}
/// <inheritdoc/>
public string? CheckExecutable(string file, NewExecutable nex, bool includeDebug)
{
// TODO: Don't read entire file
var data = nex.ReadArbitraryRange();
if (data == null)
return null;
// TODO: Figure out what NE section this lives in
var neMatchSets = new List<ContentMatchSet>
{
// CD-Cops, ver.
// Found in "h3blade.exe" in Redump entry 85077.
new(new byte?[]
{
0x43, 0x44, 0x2D, 0x43, 0x6F, 0x70, 0x73, 0x2C,
0x20, 0x20, 0x76, 0x65, 0x72, 0x2E, 0x20
}, GetVersion, "CD-Cops"),
};
var match = MatchUtil.GetFirstMatch(file, data, neMatchSets, includeDebug);
if (!string.IsNullOrEmpty(match))
return match;
// Check the imported-name table
// Found in "h3blade.exe" in Redump entry 85077.
bool importedNameTableEntries = nex.Model.ImportedNameTable?
.Select(kvp => kvp.Value)
.Select(inte => inte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(inte.NameString))
.Any(s => s.Contains("CDCOPS")) ?? false;
if (importedNameTableEntries)
return "CD-Cops";
// Check the nonresident-name table
// Found in "CDCOPS.DLL" in Redump entry 85077.
bool nonresidentNameTableEntries = nex.Model.NonResidentNameTable?
.Select(nrnte => nrnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(nrnte.NameString))
.Any(s => s.Contains("CDcops assembly-language DLL")) ?? false;
if (nonresidentNameTableEntries)
return "CD-Cops";
return null;
}
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the stub executable data, if it exists
if (pex.StubExecutableData != null)
{
var matchers = new List<ContentMatchSet>
{
// WEBCOPS
// Found in "HyperBowl.C_S" in https://web.archive.org/web/20120616074941/http://icm.games.tucows.com/files2/HyperDemo-109a.exe.
new(new byte?[]
{
0x57, 0x45, 0x42, 0x43, 0x4F, 0x50, 0x53
}, "WEB-Cops")
};
var match = MatchUtil.GetFirstMatch(file, pex.StubExecutableData, matchers, includeDebug);
if (!string.IsNullOrEmpty(match))
return match;
}
// Get the .grand section, if it exists
// Found in "AGENTHUG.QZ_" in Redump entry 84517 and "h3blade.QZ_" in Redump entry 85077.
bool grandSection = pex.ContainsSection(".grand", exact: true);
if (grandSection)
return "CD/DVD/WEB-Cops";
// Get the UNICops section, if it exists
// Found in "FGP.exe" in IA item "flaklypa-grand-prix-dvd"/Redump entry 108169.
bool UNICopsSection = pex.ContainsSection("UNICops", exact: true);
if (UNICopsSection)
return "UNI-Cops";
return null;
}
/// <inheritdoc/>
public IEnumerable<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>
{
// A 400+ MB file called "WASTE.DAT" that is fully 00 padded can be found in IA item "Faculty_Edition_People_Problems_and_Power_by_Joseph_Unekis_Textbytes".
// Presumably used to increase the amount of data written to the disc to allow DPM checking to be used for the protection. It's unknown if this file is used on any other protected discs.
// Found in Redump entry 84517.
new(new FilePathMatch("CDCOPS.DLL"), "CD-Cops"),
new(new PathMatch(".W_X", matchExact: true, useEndsWith: true), "CD/DVD-Cops"),
new(new PathMatch(".QZ_", matchExact: true, useEndsWith: true), "CD/DVD-Cops"),
new(new PathMatch(".GZ_", matchExact: true, useEndsWith: true), "CD-Cops (Unconfirmed - Please report to us on Github)"),
new(new PathMatch(".Qz", matchExact: true, useEndsWith: true), "CD-Cops (Unconfirmed - Please report to us on Github)"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string? CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
// A 400+ MB file called "WASTE.DAT" that is fully 00 padded can be found in IA item "Faculty_Edition_People_Problems_and_Power_by_Joseph_Unekis_Textbytes".
// Presumably used to increase the amount of data written to the disc to allow DPM checking to be used for the protection. It's unknown if this file is used on any other protected discs.
// Found in Redump entry 84517.
new(new FilePathMatch("CDCOPS.DLL"), "CD-Cops"),
new(new PathMatch(".W_X", matchExact: true, useEndsWith: true), "CD/DVD-Cops"),
new(new PathMatch(".QZ_", matchExact: true, useEndsWith: true), "CD/DVD-Cops"),
new(new PathMatch(".GZ_", matchExact: true, useEndsWith: true), "CD-Cops (Unconfirmed - Please report to us on Github)"),
new(new PathMatch(".Qz", matchExact: true, useEndsWith: true), "CD-Cops (Unconfirmed - Please report to us on Github)"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
public static string? GetVersion(string file, byte[]? fileContent, List<int> positions)
{
// If we have no content
if (fileContent == null)
return null;
byte[] versionBytes = new byte[4];
Array.Copy(fileContent, positions[0] + 15, versionBytes, 0, 4);
char[] version = Array.ConvertAll(versionBytes, b => (char)b);
if (version[0] == 0x00)
return string.Empty;
return new string(version);
}
}
}

View File

@@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
/// <summary>
/// CD-Guard is a DRM from Russia that's similar to CD-Cops and may be related to StarForce, meaning it likely needs DPM.
/// It may have been developed by Russobit-M, though the same source also says that StarForce was created by the same company as well, which seems unlikely (https://m.linkdatasecurity.com/pnews6.htm).
/// Others online have been confused by this as well (https://forum.ixbt.com/topic.cgi?id=31:009712).
/// A game referred to as having CD-Guard by http://lastboss.ru/games/RUS/randevu-s-neznakomkoi-2 that was published by Russobit-M is known to have an early version of StarForce (Redump entry 97088).
/// The FAQ on the game's official website indicates that StarForce specifically is present (https://web.archive.org/web/20011220224222/http://www.aha.ru/~exe_soft/russian/exesoft.htm).
/// It's unknown for sure if there were two separate versions of this game that contained separate protections, or if the game never actually contained CD-Guard, or if CD-Guard was an early name for the StarForce line of products.
/// There is a re-release of an earlier game by the same developer that seems to include both CD-Guard and StarForce drivers, with the CD-Guard driver seemingly not used during installation, nor installed onto the system (IA item "pahgeby-he3hakomkou").
///
/// Additional resources and references:
/// https://gamecopyworld.com/games/pc_omikron.shtml
/// https://forum.ixbt.com/topic.cgi?id=31:3985
/// </summary>
public class CDGuard : IExecutableCheck<PortableExecutable>, IPathCheck
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// TODO: Investigate the numerous ".guard" sections present in "Randevu.exe" in Redump entry 97142.
// Get the export directory table
if (pex.Model.ExportTable?.ExportDirectoryTable != null)
{
// Found in "cdguard.dll" in Redump entry 97142 and IA item "pahgeby-he3hakomkou".
bool match = pex.Model.ExportTable.ExportDirectoryTable.Name?.Equals("cdguard.dll", StringComparison.OrdinalIgnoreCase) == true;
if (match)
return "CD-Guard Copy Protection System";
}
// Get the import directory table
if (pex.Model.ImportTable?.ImportDirectoryTable != null)
{
// Found in "Randevu.exe" in Redump entry 97142.
bool match = Array.Exists(pex.Model.ImportTable.ImportDirectoryTable, idte => idte?.Name != null && idte.Name.Equals("cdguard.dll", StringComparison.OrdinalIgnoreCase));
if (match)
return "CD-Guard Copy Protection System";
}
return null;
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// Found in Redump entry 97142.
new(new FilePathMatch("cdguard.dll"), "CD-Guard Copy Protection System"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string? CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
// Found in Redump entry 97142.
new(new FilePathMatch("cdguard.dll"), "CD-Guard Copy Protection System"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

@@ -0,0 +1,24 @@
using System;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
public class CDKey : IExecutableCheck<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
var name = pex.InternalName;
if (name?.Equals("CDKey", StringComparison.OrdinalIgnoreCase) == true)
return "CD-Key / Serial";
return null;
}
}
}

View File

@@ -0,0 +1,96 @@
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
/// <summary>
/// CD-Lock (https://www.cdmediaworld.com/hardware/cdrom/cd_protections_dummy_files.shtml) is a copy protection most commonly used in Europe and active from 1998-2001 that seems to have a resemblance to Bitpool in a few ways.
/// It makes use of padded dummy files with an AFP extension, with there being 4 such files on a disc.
/// These files typically have a filename consistening of seemingly random 4 characters with an AFP extension, though there are known exceptions.
/// These exceptions have "afp" files with the names "Gang1.afp", "Gang2.afp", "Gang3.afp", and "Gang4.afp" (Redump entries 37788 and 43221).
/// There also always seems to be a "CONFIG.AFP" file present, which in most cases contains a marker relating to the other AFP files present on the disc.
/// At least one game breaks this mould, having a "CONFIG.AFP" file present but is filled with 0x20 bytes instead of the expected data (Redump entries 37788 and 43221).
/// Games protected with CD-Lock also appear to consistently have 3 additional tracks relating to the protection appended. These are 2 audio tracks, followed by a data track.
/// Unlike Bitpool, it seems that these additional tracks are appended whether or not there are intentional audio tracks present on the disc as well. Compare Redump entries 37788 and 66321.
/// It appears that this latter data track points to the data of the first data track, giving the appearance to some software that the disc contains 2 equally sized data tracks.
/// It seems to me that this is intended to confuse dumping software, possibly attempting to lead it to believe that the disc has a larger capacity than it physically could have.
/// https://inxs8.tripod.com/illegal_toc.htm seems to confirm that the software of the time especially seems to have had issues with this, though none of the technical information on the page seems to be particularly correct.
/// Based off of Redump entries 31615 and 37700, it seems that there are cases where the main data track on two separate discs is identical, but the protection tracks differ. The reason for this is unknown.
/// There are a few discs where one of the protection audio tracks is quite large, sometimes even larger than the main data track. The reason for this is also unknown (Redump entries 43221 and 66749).
/// https://www.softpedia.com/get/Security/Encrypting/CD-Lock.shtml seems to be an unrelated program that protects CDs via encryption.
/// Possible false positives include Redump entries 51241, 51373, 54397, 76437.
/// Confirmed to be present on Redump entries 24287, 31615, 34448, 35967, 36627, 37700, 37788, 43221, 55788, and 66749.
/// </summary>
public class CDLock : IExecutableCheck<PortableExecutable>, IPathCheck
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the .data/DATA section, if it exists
var dataSectionRaw = pex.GetFirstSectionData(".data") ?? pex.GetFirstSectionData("DATA");
if (dataSectionRaw != null)
{
var matchers = new List<ContentMatchSet>
{
// Found in game executables protected with CD-Lock (Redump entries 24287 and 31615).
// TODO: Check for possible false postives (Redump entry 97942).
// 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(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"),
};
var match = MatchUtil.GetFirstMatch(file, dataSectionRaw, matchers, includeDebug);
if (!string.IsNullOrEmpty(match))
return match;
}
return null;
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// TODO: Determine if there's any consistency in the naming of the additional AFP files.
// Found in every confirmed sample of CD-Lock, generally (but not always) appears to include markers relating to the additional AFP files present (Redump entries 24287 and 31615).
new(new FilePathMatch("CONFIG.AFP"), "CD-Lock"),
// There is also a "$$$$$$$$.$$$" file present on some discs, but it isn't known if this is directly related to CD-Lock (Redump entries 37788 and 43221).
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string? CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
// TODO: Determine if there's any consistency in the naming of the additional AFP files.
// Found in every confirmed sample of CD-Lock, generally (but not always) appears to include markers relating to the additional AFP files present (Redump entries 24287 and 31615).
new(new FilePathMatch("CONFIG.AFP"), "CD-Lock"),
// There is also a "$$$$$$$$.$$$" file present on some discs, but it isn't known if this is directly related to CD-Lock (Redump entries 37788 and 43221).
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

@@ -0,0 +1,63 @@
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
namespace BinaryObjectScanner.Protection
{
/// <summary>
/// CD-Protector is a form of DRM that allows users to create their own copy protected discs.
/// It prevents copying via "Phantom Trax", intended to confuse dumping software, and by obfuscating a specified EXE.
/// The official website seems to be https://web.archive.org/web/20000302173822/http://surf.to/nrgcrew.
/// The author's site should be https://members.xoom.it/_XOOM/Dudez/index.htm, but no captures of this site appear to be functional.
/// Instructions on how this software can be used: https://3dnews.ru/166065
/// Download: https://www.cdmediaworld.com/hardware/cdrom/cd_utils_3.shtml#CD-Protector
/// TODO: See if any of the older versions of CD-Protector are archived, and check if they need to be detected differently.
/// </summary>
public class CDProtector : IPathCheck
{
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// These are the main files used by CD-Protector, which should all be present in every protected disc.
// "_cdp16.dll" and "_cdp32.dll" are actually renamed WAV files.
// "_cdp32.dat" is actually an archive that contains the original executable.
// Another EXE is created, with the name of the original executable. I'm not sure what this executable does, but it appears to be compressed with NeoLite.
// TODO: Invesitage if this EXE itself can be detected in any way.
new(new FilePathMatch("_cdp16.dat"), "CD-Protector"),
new(new FilePathMatch("_cdp16.dll"), "CD-Protector"),
new(new FilePathMatch("_cdp32.dat"), "CD-Protector"),
new(new FilePathMatch("_cdp32.dll"), "CD-Protector"),
// This is the "Phantom Trax" file generated by CD-Protector, intended to be burned to a protected CD as an audio track.
new(new FilePathMatch("Track#1 - Track#2 Cd-Protector.wav"), "CD-Protector"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string? CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
// These are the main files used by CD-Protector, which should all be present in every protected disc.
// "_cdp16.dll" and "_cdp32.dll" are actually renamed WAV files.
// "_cdp32.dat" is actually an archive that contains the original executable.
// Another EXE is created, with the name of the original executable. I'm not sure what this executable does, but it appears to be compressed with NeoLite.
// TODO: Invesitage if this EXE itself can be detected in any way.
new(new FilePathMatch("_cdp16.dat"), "CD-Protector"),
new(new FilePathMatch("_cdp16.dll"), "CD-Protector"),
new(new FilePathMatch("_cdp32.dat"), "CD-Protector"),
new(new FilePathMatch("_cdp32.dll"), "CD-Protector"),
// This is the "Phantom Trax" file generated by CD-Protector, intended to be burned to a protected CD as an audio track.
new(new FilePathMatch("Track#1 - Track#2 Cd-Protector.wav"), "CD-Protector"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

@@ -0,0 +1,36 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
public class CDSHiELDSE : IExecutableCheck<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// TODO: Indicates Hypertech Crack Proof as well?
//// Get the import directory table
//if (pex.Model.ImportTable?.ImportDirectoryTable != null)
//{
// bool match = pex.Model.ImportTable.ImportDirectoryTable.Any(idte => idte.Name == "KeRnEl32.dLl");
// if (match)
// return "CDSHiELD SE";
//}
// Get the code/CODE section strings, if they exist
var strs = pex.GetFirstSectionStrings("code") ?? pex.GetFirstSectionStrings("CODE");
if (strs != null)
{
if (strs.Exists(s => s.Contains("~0017.tmp")))
return "CDSHiELD SE";
}
return null;
}
}
}

View File

@@ -0,0 +1,41 @@
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
namespace BinaryObjectScanner.Protection
{
// Nothing is currently known about this DRM. One program may possibly have included it, as it has been listed as including these files in the installion directory (https://www.advanceduninstaller.com/Visit-Gallery-2-90896afd3151ed9660dddc23b892863f-application.htm).
// Unfortunately, this program and developer are so obscure, I'm not able to find any relevant further information on them whatsoever.
// The only source of valuable information currently known is a forum post about a user attempting to crack this DRM (https://forum.p30world.com/showthread.php?t=413264).
// Every attachment, upload, or photo from the forum thread are offline and unarchived.
public class CDX : IPathCheck
{
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
// TODO: Verify if these are OR or AND
var matchers = new List<PathMatchSet>
{
new(new FilePathMatch("CHKCDX16.DLL"), "CD-X (Unconfirmed - Please report to us on Github)"),
new(new FilePathMatch("CHKCDX32.DLL"), "CD-X (Unconfirmed - Please report to us on Github)"),
new(new FilePathMatch("CHKCDXNT.DLL"), "CD-X (Unconfirmed - Please report to us on Github)"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string? CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
new(new FilePathMatch("CHKCDX16.DLL"), "CD-X (Unconfirmed - Please report to us on Github)"),
new(new FilePathMatch("CHKCDX32.DLL"), "CD-X (Unconfirmed - Please report to us on Github)"),
new(new FilePathMatch("CHKCDXNT.DLL"), "CD-X (Unconfirmed - Please report to us on Github)"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

@@ -0,0 +1,32 @@
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
namespace BinaryObjectScanner.Protection
{
public class CactusDataShield : IContentCheck
{
/// <inheritdoc/>
public string? CheckContents(string file, byte[] fileContent, bool includeDebug)
{
// TODO: Limit these checks to Mac binaries
// TODO: Obtain a sample to find where this string is in a typical executable
if (includeDebug)
{
var contentMatchSets = new List<ContentMatchSet>
{
// CDSPlayer
new([0x43, 0x44, 0x53, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72], "Cactus Data Shield 200"),
// yucca.cds
new([0x79, 0x75, 0x63, 0x63, 0x61, 0x2E, 0x63, 0x64, 0x73], "Cactus Data Shield 200"),
};
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
}
return null;
}
}
}

View File

@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
/// <summary>
/// Cenega ProtectDVD is a protection seemingly created by the publisher Cenega for use with their games.
/// Games using this protection aren't able to be run from an ISO file, and presumably use DPM as a protection feature.
/// <see href="https://github.com/TheRogueArchivist/DRML/blob/main/entries/Cenega_ProtectDVD/Cenega_ProtectDVD.md"/>
/// </summary>
public class CengaProtectDVD : IExecutableCheck<PortableExecutable>, IPathCheck
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the export directory table
if (pex.Model.ExportTable?.ExportDirectoryTable != null)
{
// Found in "cenega.dll" in IA item "speed-pack".
bool match = pex.Model.ExportTable.ExportDirectoryTable.Name?.Equals("ProtectDVD.dll", StringComparison.OrdinalIgnoreCase) == true;
if (match)
return "Cenega ProtectDVD";
}
// Get the .cenega section, if it exists. Seems to be found in the protected game executable ("game.exe" in Redump entry 31422 and "Classic Car Racing.exe" in IA item "speed-pack").
bool cenegaSection = pex.ContainsSection(".cenega", exact: true);
if (cenegaSection)
return "Cenega ProtectDVD";
// Get the .cenega0 through .cenega2 sections, if they exists. Found in "cenega.dll" in Redump entry 31422 and IA item "speed-pack".
cenegaSection = pex.ContainsSection(".cenega0", exact: true);
if (cenegaSection)
return "Cenega ProtectDVD";
cenegaSection = pex.ContainsSection(".cenega1", exact: true);
if (cenegaSection)
return "Cenega ProtectDVD";
cenegaSection = pex.ContainsSection(".cenega2", exact: true);
if (cenegaSection)
return "Cenega ProtectDVD";
return null;
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// Seems likely to be present in most, if not all discs protected with Cenega ProtectDVD, but unable to confirm due to only having a small sample size.
// Found in Redump entry 31422 and IA item "speed-pack".
new(new FilePathMatch("cenega.dll"), "Cenega ProtectDVD"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string? CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
// Seems likely to be present in most, if not all discs protected with Cenega ProtectDVD, but unable to confirm due to only having a small sample size.
// Found in Redump entry 31422 and IA item "speed-pack".
new(new FilePathMatch("cenega.dll"), "Cenega ProtectDVD"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

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