Compare commits

...

1312 Commits
2.1.0 ... 3.1.3

Author SHA1 Message Date
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
371 changed files with 22600 additions and 19456 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: 8.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

53
.github/workflows/build_test.yml vendored Normal file
View File

@@ -0,0 +1,53 @@
name: Build Test
on:
push:
branches: [ "master" ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
project: [Test]
runtime: [win-x86, win-x64, linux-x64, osx-x64] #[win-x86, win-x64, win-arm64, linux-x64, linux-arm64, osx-x64]
framework: [net8.0] #[net20, net35, net40, net452, net472, net48, netcoreapp3.1, net5.0, net6.0, net7.0, net8.0]
conf: [Release, Debug]
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.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')) && '-p:PublishSingleFile=true' || ''}}
- name: Archive build
run: zip -r ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_${{ matrix.conf }}.zip ${{ matrix.project }}/bin/${{ matrix.conf }}/${{ matrix.framework }}/${{ matrix.runtime }}/publish/
- 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: 8.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 = 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

4
.vscode/launch.json vendored
View File

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

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"
],

View File

@@ -3,22 +3,20 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32407.343
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BurnOutSharp", "BurnOutSharp\BurnOutSharp.csproj", "{1DA4212E-6071-4951-B45D-BB74A7838246}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{88735BA2-778D-4192-8EB2-FFF6843719E2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{68D10531-99CB-40B1-8912-73FA286C9433}"
ProjectSection(SolutionItems) = preProject
appveyor.yml = appveyor.yml
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("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WixToolset", "WixToolset", "{09D405CA-CF15-4929-8408-C970F0656C62}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{182E02A8-5E8E-4140-9C9B-61049C33E921}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Dtf.WindowsInstaller", "WixToolset\src\WixToolset.Dtf.WindowsInstaller\WixToolset.Dtf.WindowsInstaller.csproj", "{B3537EB7-CEF6-4D90-A041-47626442A656}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BinaryObjectScanner", "BinaryObjectScanner\BinaryObjectScanner.csproj", "{341EA3F5-847C-4739-B86F-2B051FFE4EF2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -26,26 +24,18 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1DA4212E-6071-4951-B45D-BB74A7838246}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1DA4212E-6071-4951-B45D-BB74A7838246}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1DA4212E-6071-4951-B45D-BB74A7838246}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1DA4212E-6071-4951-B45D-BB74A7838246}.Release|Any CPU.Build.0 = Release|Any CPU
{88735BA2-778D-4192-8EB2-FFF6843719E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{88735BA2-778D-4192-8EB2-FFF6843719E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{88735BA2-778D-4192-8EB2-FFF6843719E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{88735BA2-778D-4192-8EB2-FFF6843719E2}.Release|Any CPU.Build.0 = Release|Any CPU
{B3537EB7-CEF6-4D90-A041-47626442A656}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B3537EB7-CEF6-4D90-A041-47626442A656}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B3537EB7-CEF6-4D90-A041-47626442A656}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B3537EB7-CEF6-4D90-A041-47626442A656}.Release|Any CPU.Build.0 = Release|Any CPU
{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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{182E02A8-5E8E-4140-9C9B-61049C33E921} = {09D405CA-CF15-4929-8408-C970F0656C62}
{B3537EB7-CEF6-4D90-A041-47626442A656} = {182E02A8-5E8E-4140-9C9B-61049C33E921}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0B343DD2-8852-47B0-9647-DFCFBEDF933C}
EndGlobalSection

View File

@@ -0,0 +1,94 @@
<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</TargetFrameworks>
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
<!-- <TreatWarningsAsErrors>true</TreatWarningsAsErrors> --> <!-- Can't be enabled because of external code -->
<Version>3.1.3</Version>
<!-- 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 .NET Framework 4.5.2 and above -->
<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 external modules for .NET Framework 2.0, .NET Framework 3.5, .NET Framework 4.0 or non-Windows builds -->
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`)) OR !$(RuntimeIdentifier.StartsWith(`win-`))">
<DefaultItemExcludes>
$(DefaultItemExcludes);
_EXTERNAL\**
</DefaultItemExcludes>
</PropertyGroup>
<!-- These are needed for dealing with native Windows DLLs -->
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`))">
<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`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`))">
<PackageReference Include="MinThreadingBridge" Version="0.11.4" />
<PackageReference Include="MinTasksExtensionsBridge" Version="0.3.4" />
</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.36.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith(`net4`)) AND !$(TargetFramework.StartsWith(`net40`))">
<PackageReference Include="System.Memory" Version="4.5.5" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SabreTools.Compression" Version="0.4.0" />
<PackageReference Include="SabreTools.Hashing" Version="1.2.0" />
<PackageReference Include="SabreTools.IO" Version="1.3.2" />
<PackageReference Include="SabreTools.Matching" Version="1.3.1" />
<PackageReference Include="SabreTools.Models" Version="1.4.0" />
<PackageReference Include="SabreTools.Serialization" Version="1.4.1" />
<PackageReference Include="UnshieldSharp" Version="1.7.3" />
<PackageReference Include="WiseUnpacker" Version="1.3.1" />
</ItemGroup>
</Project>

View File

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

View File

@@ -0,0 +1,51 @@
using System;
using System.IO;
using System.Linq;
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 = mkb.Model.Records?.FirstOrDefault(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,49 @@
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,141 @@
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 string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
try
{
// Create the wrapper
var bfpk = SabreTools.Serialization.Wrappers.BFPK.Create(stream);
if (bfpk == null)
return null;
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// Extract all files
ExtractAll(bfpk, tempPath);
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
/// <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,307 @@
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 string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
try
{
// Create the wrapper
var bsp = SabreTools.Serialization.Wrappers.BSP.Create(stream);
if (bsp == null)
return null;
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// Loop through and extract all files
ExtractAllLumps(bsp, tempPath);
ExtractAllTextures(bsp, tempPath);
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
/// <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,60 @@
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 string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
if (stream == null)
return null;
#if NET462_OR_GREATER || NETCOREAPP
try
{
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (BZip2Stream bz2File = new BZip2Stream(stream, CompressionMode.Decompress, true))
{
string tempFile = Path.Combine(tempPath, Guid.NewGuid().ToString());
using (FileStream fs = File.OpenWrite(tempFile))
{
bz2File.CopyTo(fs);
}
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
#else
return null;
#endif
}
}
}

View File

@@ -0,0 +1,157 @@
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 string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
#if NET20 || NET35
// Not supported for .NET Framework 2.0 or .NET Framework 3.5 due to library support
return null;
#else
try
{
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (CompoundFile 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 filename = Path.Combine(tempPath, decoded);
using (Stream fs = File.OpenWrite(filename))
{
fs.Write(strData, 0, strData.Length);
}
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}, recursive: true);
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
#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,600 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Utilities;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Executable or library
/// </summary>
/// <remarks>
/// Due to the complexity of executables, all extraction handling
/// another class that is used by the scanner
/// </remarks>
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; }
/// <summary>
/// Cache for all IContentCheck types
/// </summary>
public static IEnumerable<IContentCheck> ContentCheckClasses
{
get
{
contentCheckClasses ??= InitCheckClasses<IContentCheck>();
return contentCheckClasses ?? [];
}
}
/// <summary>
/// Cache for all ILinearExecutableCheck types
/// </summary>
public static IEnumerable<ILinearExecutableCheck> LinearExecutableCheckClasses
{
get
{
linearExecutableCheckClasses ??= InitCheckClasses<ILinearExecutableCheck>();
return linearExecutableCheckClasses ?? [];
}
}
/// <summary>
/// Cache for all IMSDOSExecutableCheck types
/// </summary>
public static IEnumerable<IMSDOSExecutableCheck> MSDOSExecutableCheckClasses
{
get
{
msdosExecutableCheckClasses ??= InitCheckClasses<IMSDOSExecutableCheck>();
return msdosExecutableCheckClasses ?? [];
}
}
/// <summary>
/// Cache for all INewExecutableCheck types
/// </summary>
public static IEnumerable<INewExecutableCheck> NewExecutableCheckClasses
{
get
{
newExecutableCheckClasses ??= InitCheckClasses<INewExecutableCheck>();
return newExecutableCheckClasses ?? [];
}
}
/// <summary>
/// Cache for all IPortableExecutableCheck types
/// </summary>
public static IEnumerable<IPortableExecutableCheck> PortableExecutableCheckClasses
{
get
{
portableExecutableCheckClasses ??= InitCheckClasses<IPortableExecutableCheck>();
return portableExecutableCheckClasses ?? [];
}
}
#endregion
#region Internal Instances
/// <summary>
/// Cache for all IContentCheck types
/// </summary>
private static IEnumerable<IContentCheck>? contentCheckClasses;
/// <summary>
/// Cache for all ILinearExecutableCheck types
/// </summary>
private static IEnumerable<ILinearExecutableCheck>? linearExecutableCheckClasses;
/// <summary>
/// Cache for all IMSDOSExecutableCheck types
/// </summary>
private static IEnumerable<IMSDOSExecutableCheck>? msdosExecutableCheckClasses;
/// <summary>
/// Cache for all INewExecutableCheck types
/// </summary>
private static IEnumerable<INewExecutableCheck>? newExecutableCheckClasses;
/// <summary>
/// Cache for all IPortableExecutableCheck types
/// </summary>
private static IEnumerable<IPortableExecutableCheck>? portableExecutableCheckClasses;
#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)
{
// Try to create a wrapper for the proper executable type
var wrapper = WrapperFactory.CreateExecutableWrapper(stream);
if (wrapper == null)
return null;
// Create the internal queue
#if NET20 || NET35
var protections = new Queue<string>();
#else
var protections = new ConcurrentQueue<string>();
#endif
// Only use generic content checks if we're in debug mode
if (includeDebug)
{
var subProtections = RunContentChecks(file, stream, includeDebug);
if (subProtections != null)
protections.AddRange(subProtections.Values.ToArray());
}
if (wrapper is MSDOS mz)
{
var subProtections = RunMSDOSExecutableChecks(file, stream, mz, includeDebug);
if (subProtections != null)
protections.AddRange(subProtections.Values.ToArray());
}
else if (wrapper is LinearExecutable lex)
{
var subProtections = RunLinearExecutableChecks(file, stream, lex, includeDebug);
if (subProtections != null)
protections.AddRange(subProtections.Values.ToArray());
}
else if (wrapper is NewExecutable nex)
{
var subProtections = RunNewExecutableChecks(file, stream, nex, includeDebug);
if (subProtections != null)
protections.AddRange(subProtections.Values.ToArray());
}
else if (wrapper is PortableExecutable pex)
{
var subProtections = RunPortableExecutableChecks(file, stream, pex, includeDebug);
if (subProtections != null)
protections.AddRange(subProtections.Values.ToArray());
}
return string.Join(";", [.. 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, null on error</returns>
#if NET20 || NET35
public Dictionary<IContentCheck, string>? RunContentChecks(string? file, Stream stream, bool includeDebug)
#else
public ConcurrentDictionary<IContentCheck, string>? RunContentChecks(string? file, Stream stream, bool includeDebug)
#endif
{
// If we have an invalid file
if (string.IsNullOrEmpty(file))
return null;
else if (!File.Exists(file))
return null;
// Read the file contents
byte[] fileContent = [];
try
{
#if NET20 || NET35 || NET40
using var br = new BinaryReader(stream, Encoding.Default);
#else
using var br = new BinaryReader(stream, Encoding.Default, true);
#endif
fileContent = br.ReadBytes((int)stream.Length);
if (fileContent == null)
return null;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
// Create the output dictionary
#if NET20 || NET35
var protections = new Dictionary<IContentCheck, string>();
#else
var protections = new ConcurrentDictionary<IContentCheck, string>();
#endif
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in ContentCheckClasses)
#else
Parallel.ForEach(ContentCheckClasses, checkClass =>
#endif
{
// Get the protection for the class, if possible
var protection = checkClass.CheckContents(file!, fileContent, includeDebug);
if (string.IsNullOrEmpty(protection))
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on game engines
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on packers
if (CheckIfPacker(checkClass) && !IncludePackers)
#if NET20 || NET35
continue;
#else
return;
#endif
#if NET20 || NET35
protections[checkClass] = protection!;
}
#else
protections.TryAdd(checkClass, protection!);
});
#endif
return protections;
}
/// <summary>
/// Handle a single file based on all linear executable check implementations
/// </summary>
/// <param name="file">Name of the source file of the executable, for tracking</param>
/// <param name="lex">Executable to scan</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public Dictionary<ILinearExecutableCheck, string> RunLinearExecutableChecks(string file, Stream stream, LinearExecutable lex, bool includeDebug)
#else
public ConcurrentDictionary<ILinearExecutableCheck, string> RunLinearExecutableChecks(string file, Stream stream, LinearExecutable lex, bool includeDebug)
#endif
{
// Create the output dictionary
#if NET20 || NET35
var protections = new Dictionary<ILinearExecutableCheck, string>();
#else
var protections = new ConcurrentDictionary<ILinearExecutableCheck, string>();
#endif
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in LinearExecutableCheckClasses)
#else
Parallel.ForEach(LinearExecutableCheckClasses, checkClass =>
#endif
{
// Get the protection for the class, if possible
var protection = checkClass.CheckLinearExecutable(file, lex, includeDebug);
if (string.IsNullOrEmpty(protection))
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on game engines
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on packers
if (CheckIfPacker(checkClass) && !IncludePackers)
#if NET20 || NET35
continue;
#else
return;
#endif
#if NET20 || NET35
protections[checkClass] = protection!;
}
#else
protections.TryAdd(checkClass, protection!);
});
#endif
return protections;
}
/// <summary>
/// Handle a single file based on all MS-DOS executable check implementations
/// </summary>
/// <param name="file">Name of the source file of the executable, for tracking</param>
/// <param name="mz">Executable to scan</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public Dictionary<IMSDOSExecutableCheck, string> RunMSDOSExecutableChecks(string file, Stream stream, MSDOS mz, bool includeDebug)
#else
public ConcurrentDictionary<IMSDOSExecutableCheck, string> RunMSDOSExecutableChecks(string file, Stream stream, MSDOS mz, bool includeDebug)
#endif
{
// Create the output dictionary
#if NET20 || NET35
var protections = new Dictionary<IMSDOSExecutableCheck, string>();
#else
var protections = new ConcurrentDictionary<IMSDOSExecutableCheck, string>();
#endif
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in MSDOSExecutableCheckClasses)
#else
Parallel.ForEach(MSDOSExecutableCheckClasses, checkClass =>
#endif
{
// Get the protection for the class, if possible
var protection = checkClass.CheckMSDOSExecutable(file, mz, includeDebug);
if (string.IsNullOrEmpty(protection))
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on game engines
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on packers
if (CheckIfPacker(checkClass) && !IncludePackers)
#if NET20 || NET35
continue;
#else
return;
#endif
#if NET20 || NET35
protections[checkClass] = protection!;
}
#else
protections.TryAdd(checkClass, protection!);
});
#endif
return protections;
}
/// <summary>
/// Handle a single file based on all new executable check implementations
/// </summary>
/// <param name="file">Name of the source file of the executable, for tracking</param>
/// <param name="nex">Executable to scan</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public Dictionary<INewExecutableCheck, string> RunNewExecutableChecks(string file, Stream stream, NewExecutable nex, bool includeDebug)
#else
public ConcurrentDictionary<INewExecutableCheck, string> RunNewExecutableChecks(string file, Stream stream, NewExecutable nex, bool includeDebug)
#endif
{
// Create the output dictionary
#if NET20 || NET35
var protections = new Dictionary<INewExecutableCheck, string>();
#else
var protections = new ConcurrentDictionary<INewExecutableCheck, string>();
#endif
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in NewExecutableCheckClasses)
#else
Parallel.ForEach(NewExecutableCheckClasses, checkClass =>
#endif
{
// Get the protection for the class, if possible
var protection = checkClass.CheckNewExecutable(file, nex, includeDebug);
if (string.IsNullOrEmpty(protection))
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on game engines
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on packers
if (CheckIfPacker(checkClass) && !IncludePackers)
#if NET20 || NET35
continue;
#else
return;
#endif
#if NET20 || NET35
protections[checkClass] = protection!;
}
#else
protections.TryAdd(checkClass, protection!);
});
#endif
return protections;
}
/// <summary>
/// Handle a single file based on all portable executable check implementations
/// </summary>
/// <param name="file">Name of the source file of the executable, for tracking</param>
/// <param name="pex">Executable to scan</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public Dictionary<IPortableExecutableCheck, string> RunPortableExecutableChecks(string file, Stream stream, PortableExecutable pex, bool includeDebug)
#else
public ConcurrentDictionary<IPortableExecutableCheck, string> RunPortableExecutableChecks(string file, Stream stream, PortableExecutable pex, bool includeDebug)
#endif
{
// Create the output dictionary
#if NET20 || NET35
var protections = new Dictionary<IPortableExecutableCheck, string>();
#else
var protections = new ConcurrentDictionary<IPortableExecutableCheck, string>();
#endif
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in PortableExecutableCheckClasses)
#else
Parallel.ForEach(PortableExecutableCheckClasses, checkClass =>
#endif
{
// Get the protection for the class, if possible
var protection = checkClass.CheckPortableExecutable(file, pex, includeDebug);
if (string.IsNullOrEmpty(protection))
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on game engines
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on packers
if (CheckIfPacker(checkClass) && !IncludePackers)
#if NET20 || NET35
continue;
#else
return;
#endif
#if NET20 || NET35
protections[checkClass] = protection!;
}
#else
protections.TryAdd(checkClass, protection!);
});
#endif
return protections;
}
#endregion
#region Initializers
/// <summary>
/// Initialize all implementations of a type
/// </summary>
private static IEnumerable<T>? InitCheckClasses<T>() =>
InitCheckClasses<T>(Assembly.GetExecutingAssembly()) ?? [];
/// <summary>
/// Initialize all implementations of a type
/// </summary>
private static IEnumerable<T>? InitCheckClasses<T>(Assembly assembly)
{
List<T> classTypes = [];
// If not all types can be loaded, use the ones that could be
List<Type> assemblyTypes = [];
try
{
assemblyTypes = assembly.GetTypes().ToList<Type>();
}
catch (ReflectionTypeLoadException rtle)
{
assemblyTypes = rtle.Types.Where(t => t != null)!.ToList<Type>();
}
// Loop through all types
foreach (Type type in assemblyTypes)
{
// If the type isn't a class or doesn't implement the interface
if (!type.IsClass || type.GetInterface(typeof(T).Name) == null)
continue;
// Try to create a concrete instance of the type
var instance = (T?)Activator.CreateInstance(type);
if (instance != null)
classTypes.Add(instance);
}
return classTypes;
}
#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,157 @@
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 string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
try
{
// Create the wrapper
var gcf = SabreTools.Serialization.Wrappers.GCF.Create(stream);
if (gcf == null)
return null;
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// Loop through and extract all files
ExtractAll(gcf, tempPath);
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
/// <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,71 @@
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 string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
if (stream == null)
return null;
#if NET462_OR_GREATER || NETCOREAPP
try
{
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (GZipArchive zipFile = GZipArchive.Open(stream))
{
foreach (var entry in zipFile.Entries)
{
try
{
// If we have a directory, skip it
if (entry.IsDirectory)
continue;
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
#else
return null;
#endif
}
}
}

View File

@@ -0,0 +1,67 @@
using System;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using UnshieldSharp.Archive;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// InstallShield archive v3
/// </summary>
public class InstallShieldArchiveV3 : IExtractable
{
/// <inheritdoc/>
public string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
try
{
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
UnshieldSharp.Archive.InstallShieldArchiveV3 archive = new UnshieldSharp.Archive.InstallShieldArchiveV3(file);
foreach (CompressedFile cfile in archive.Files.Select(kvp => kvp.Value))
{
try
{
string tempFile = Path.Combine(tempPath, cfile.FullPath!);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
(byte[]? fileContents, string? error) = archive.Extract(cfile.FullPath!);
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 tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
}
}

View File

@@ -0,0 +1,101 @@
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 string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, 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 null;
try
{
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
var cabfile = InstallShieldCabinet.Open(file);
if (cabfile == null)
return null;
for (int i = 0; i < cabfile.FileCount; i++)
{
try
{
// Check if the file is valid first
if (!cabfile.FileIsValid(i))
continue;
string tempFile;
try
{
string? filename = cabfile.FileName(i);
tempFile = Path.Combine(tempPath, filename ?? string.Empty);
}
catch
{
tempFile = Path.Combine(tempPath, $"BAD_FILENAME{i}");
}
cabfile.FileSave(i, tempFile);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
}
}

View File

@@ -0,0 +1,44 @@
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];
stream.Read(magic, 0, 16);
if (magic.StartsWith(new byte?[] { 0x4C, 0x44, 0x53, 0x43, 0x52, 0x59, 0x50, 0x54 }))
return "Link Data Security encrypted file";
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return null;
}
}
}

View File

@@ -1,56 +1,54 @@
using System;
using System.Collections.Concurrent;
using System.IO;
using BurnOutSharp.Tools;
using BinaryObjectScanner.Interfaces;
#if ((NETFRAMEWORK && !NET20 && !NET35 && !NET40) || NETCOREAPP) && WIN
using StormLibSharp;
#endif
namespace BurnOutSharp.FileType
namespace BinaryObjectScanner.FileType
{
public class MPQ : IScannable
/// <summary>
/// MoPaQ game data archive
/// </summary>
public class MPQ : IExtractable
{
/// <inheritdoc/>
public bool ShouldScan(byte[] magic)
{
if (magic.StartsWith(new byte?[] { 0x4d, 0x50, 0x51, 0x1a }))
return true;
return false;
}
/// <inheritdoc/>
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, string file)
public string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.OpenRead(file))
{
return Scan(scanner, fs, file);
}
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, includeDebug);
}
// TODO: Add stream opening support
/// <inheritdoc/>
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
public string? Extract(Stream? stream, string file, bool includeDebug)
{
// If the mpq file itself fails
#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 null;
#else
try
{
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (MpqArchive mpqArchive = new MpqArchive(file, FileAccess.Read))
using (var mpqArchive = new MpqArchive(file, FileAccess.Read))
{
// Try to open the listfile
string listfile = null;
string? listfile = null;
MpqFileStream listStream = mpqArchive.OpenFile("(listfile)");
// If we can't read the listfile, we just return
if (!listStream.CanRead)
return null;
// Read the listfile in for processing
using (StreamReader sr = new StreamReader(listStream))
using (var sr = new StreamReader(listStream))
{
listfile = sr.ReadToEnd();
}
@@ -61,35 +59,27 @@ namespace BurnOutSharp.FileType
// Loop over each entry
foreach (string sub in listfileLines)
{
// If an individual entry fails
try
{
string tempFile = Path.Combine(tempPath, sub);
Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
mpqArchive.ExtractFile(sub, tempFile);
}
catch { }
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
return tempPath;
}
catch { }
return null;
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
#endif
}
}
}

View File

@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Interfaces;
#if ((NETFRAMEWORK && !NET20 && !NET35 && !NET40) || 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 string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, 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 null;
#else
try
{
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (var cabArchive = new MSCabinet(file))
{
// Loop over each entry
foreach (var compressedFile in cabArchive.GetFiles())
{
try
{
string tempFile = Path.Combine(tempPath, compressedFile.Filename);
Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
compressedFile.ExtractTo(tempFile);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
#endif
}
}
}

View File

@@ -0,0 +1,69 @@
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 string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
try
{
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
var data = Decompressor.Decompress(stream);
if (data == null)
return null;
// 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(tempPath, tempFile);
// Write the file data to a temp file
using (Stream tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
{
tempStream.Write(data, 0, data.Length);
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
}
}

View File

@@ -0,0 +1,129 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Half-Life Package File
/// </summary>
public class PAK : IExtractable
{
/// <inheritdoc/>
public string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
try
{
// Create the wrapper
var pak = SabreTools.Serialization.Wrappers.PAK.Create(stream);
if (pak == null)
return null;
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// Loop through and extract all files
ExtractAll(pak, tempPath);
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
/// <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,122 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// NovaLogic Game Archive Format
/// </summary>
public class PFF : IExtractable
{
/// <inheritdoc/>
public string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
try
{
// Create the wrapper
var pff = SabreTools.Serialization.Wrappers.PFF.Create(stream);
if (pff == null)
return null;
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// Extract all files
ExtractAll(pff, tempPath);
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex.Message);
return null;
}
}
/// <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,74 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
#if NET462_OR_GREATER || NETCOREAPP
using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
#endif
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// PKWARE ZIP archive and derivatives
/// </summary>
public class PKZIP : IExtractable
{
/// <inheritdoc/>
public string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
if (stream == null)
return null;
#if NET462_OR_GREATER || NETCOREAPP
try
{
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (ZipArchive zipFile = ZipArchive.Open(stream))
{
foreach (var entry in zipFile.Entries)
{
try
{
// If we have a directory, skip it
if (entry.IsDirectory)
continue;
string tempFile = Path.Combine(tempPath, 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 tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
#else
return null;
#endif
}
}
}

View File

@@ -0,0 +1,44 @@
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];
stream.Read(magic, 0, 16);
if (magic.StartsWith(new byte?[] { 0xFF, 0x9D, 0x53, 0x4B }))
return "PlayJ Audio File";
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return null;
}
}
}

View File

@@ -0,0 +1,158 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Quantum Archive
/// </summary>
public class Quantum : IExtractable
{
/// <inheritdoc/>
public string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
try
{
// Create the wrapper
var quantum = SabreTools.Serialization.Wrappers.Quantum.Create(stream);
if (quantum == null)
return null;
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// Extract all files
ExtractAll(quantum, tempPath);
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex.Message);
return null;
}
}
/// <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,71 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
#if NET462_OR_GREATER || NETCOREAPP
using SharpCompress.Archives;
using SharpCompress.Archives.Rar;
#endif
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// RAR archive
/// </summary>
public class RAR : IExtractable
{
/// <inheritdoc/>
public string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
if (stream == null)
return null;
#if NET462_OR_GREATER || NETCOREAPP
try
{
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (RarArchive rarFile = RarArchive.Open(stream))
{
foreach (var entry in rarFile.Entries)
{
try
{
// If we have a directory, skip it
if (entry.IsDirectory)
continue;
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
#else
return null;
#endif
}
}
}

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];
stream.Read(magic, 0, 16);
if (magic.StartsWith(new byte?[] { 0x53, 0x46, 0x46, 0x53 }))
return "StarForce Filesystem Container";
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return null;
}
/// <inheritdoc/>
public string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,280 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Compression.zlib;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// SGA game archive
/// </summary>
public class SGA : IExtractable
{
/// <inheritdoc/>
public string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
try
{
// Create the wrapper
var sga = SabreTools.Serialization.Wrappers.SGA.Create(stream);
if (sga == null)
return null;
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// Loop through and extract all files
ExtractAll(sga, tempPath);
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
/// <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 number of files
int filesLength;
switch (item.Model.Header?.MajorVersion)
{
case 4: filesLength = (item.Model.Directory as SabreTools.Models.SGA.Directory4)?.Files?.Length ?? 0; break;
case 5: filesLength = (item.Model.Directory as SabreTools.Models.SGA.Directory5)?.Files?.Length ?? 0; break;
case 6: filesLength = (item.Model.Directory as SabreTools.Models.SGA.Directory6)?.Files?.Length ?? 0; break;
case 7: filesLength = (item.Model.Directory as SabreTools.Models.SGA.Directory7)?.Files?.Length ?? 0; break;
default: return false;
}
// 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 number of files
int filesLength;
switch (item.Model.Header?.MajorVersion)
{
case 4: filesLength = (item.Model.Directory as SabreTools.Models.SGA.Directory4)?.Files?.Length ?? 0; break;
case 5: filesLength = (item.Model.Directory as SabreTools.Models.SGA.Directory5)?.Files?.Length ?? 0; break;
case 6: filesLength = (item.Model.Directory as SabreTools.Models.SGA.Directory6)?.Files?.Length ?? 0; break;
case 7: filesLength = (item.Model.Directory as SabreTools.Models.SGA.Directory7)?.Files?.Length ?? 0; break;
default: return false;
}
// 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;
switch (item.Model.Header?.MajorVersion)
{
case 4: file = (item.Model.Directory as SabreTools.Models.SGA.Directory4)?.Files?[index]; break;
case 5: file = (item.Model.Directory as SabreTools.Models.SGA.Directory5)?.Files?[index]; break;
case 6: file = (item.Model.Directory as SabreTools.Models.SGA.Directory6)?.Files?[index]; break;
case 7: file = (item.Model.Directory as SabreTools.Models.SGA.Directory7)?.Files?[index]; break;
default: return false;
}
if (file == null)
return false;
// Create the filename
var filename = string.Empty;
switch (item.Model.Header?.MajorVersion)
{
case 4:
case 5: filename = (file as SabreTools.Models.SGA.File4)?.Name; break;
case 6: filename = (file as SabreTools.Models.SGA.File6)?.Name; break;
case 7: filename = (file as SabreTools.Models.SGA.File7)?.Name; break;
default: return false;
}
// Loop through and get all parent directories
var parentNames = new List<string?> { filename };
// Get the parent directory
var folder = default(object);
switch (item.Model.Header?.MajorVersion)
{
case 4: folder = (item.Model.Directory as SabreTools.Models.SGA.Directory4)?.Folders?.FirstOrDefault(f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex); break;
case 5: folder = (item.Model.Directory as SabreTools.Models.SGA.Directory5)?.Folders?.FirstOrDefault(f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex); break;
case 6: folder = (item.Model.Directory as SabreTools.Models.SGA.Directory6)?.Folders?.FirstOrDefault(f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex); break;
case 7: folder = (item.Model.Directory as SabreTools.Models.SGA.Directory7)?.Folders?.FirstOrDefault(f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex); break;
default: return false;
}
// If we have a parent folder
if (folder != null)
{
switch (item.Model.Header?.MajorVersion)
{
case 4: parentNames.Add((folder as SabreTools.Models.SGA.Folder4)?.Name); break;
case 5:
case 6:
case 7: parentNames.Add((folder as SabreTools.Models.SGA.Folder5)?.Name); break;
default: return false;
}
}
// TODO: Should the section name/alias be used in the path as well?
// Reverse and assemble the filename
parentNames.Reverse();
#if NET20 || NET35
var parentNamesArray = parentNames.Cast<string>().ToArray();
filename = parentNamesArray[0];
for (int i = 1; i < parentNamesArray.Length; i++)
{
filename = Path.Combine(filename, parentNamesArray[i]);
}
#else
filename = Path.Combine(parentNames.Cast<string>().ToArray());
#endif
// Get the file offset
long fileOffset;
switch (item.Model.Header?.MajorVersion)
{
case 4:
case 5: fileOffset = (file as SabreTools.Models.SGA.File4)?.Offset ?? 0; break;
case 6: fileOffset = (file as SabreTools.Models.SGA.File6)?.Offset ?? 0; break;
case 7: fileOffset = (file as SabreTools.Models.SGA.File7)?.Offset ?? 0; break;
default: return false;
}
// Adjust the file offset
switch (item.Model.Header?.MajorVersion)
{
case 4: fileOffset += (item.Model.Header as SabreTools.Models.SGA.Header4)?.FileDataOffset ?? 0; break;
case 5: fileOffset += (item.Model.Header as SabreTools.Models.SGA.Header4)?.FileDataOffset ?? 0; break;
case 6: fileOffset += (item.Model.Header as SabreTools.Models.SGA.Header6)?.FileDataOffset ?? 0; break;
case 7: fileOffset += (item.Model.Header as SabreTools.Models.SGA.Header6)?.FileDataOffset ?? 0; break;
default: return false;
};
// Get the file sizes
long fileSize, outputFileSize;
switch (item.Model.Header?.MajorVersion)
{
case 4:
case 5:
fileSize = (file as SabreTools.Models.SGA.File4)?.SizeOnDisk ?? 0;
outputFileSize = (file as SabreTools.Models.SGA.File4)?.Size ?? 0;
break;
case 6:
fileSize = (file as SabreTools.Models.SGA.File6)?.SizeOnDisk ?? 0;
outputFileSize = (file as SabreTools.Models.SGA.File6)?.Size ?? 0;
break;
case 7:
fileSize = (file as SabreTools.Models.SGA.File7)?.SizeOnDisk ?? 0;
outputFileSize = (file as SabreTools.Models.SGA.File7)?.Size ?? 0;
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,68 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
#if NET462_OR_GREATER || NETCOREAPP
using SharpCompress.Archives;
using SharpCompress.Archives.SevenZip;
#endif
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// 7-zip archive
/// </summary>
public class SevenZip : IExtractable
{
/// <inheritdoc/>
public string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
#if NET462_OR_GREATER || NETCOREAPP
try
{
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (SevenZipArchive sevenZipFile = SevenZipArchive.Open(stream))
{
foreach (var entry in sevenZipFile.Entries)
{
try
{
// If we have a directory, skip it
if (entry.IsDirectory)
continue;
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
#else
return null;
#endif
}
}
}

View File

@@ -0,0 +1,71 @@
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 string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
if (stream == null)
return null;
#if NET462_OR_GREATER || NETCOREAPP
try
{
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (TarArchive tarFile = TarArchive.Open(stream))
{
foreach (var entry in tarFile.Entries)
{
try
{
// If we have a directory, skip it
if (entry.IsDirectory)
continue;
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
#else
return null;
#endif
}
}
}

View File

@@ -0,0 +1,163 @@
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");
// 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
if (fileContent.Contains("phenoProtect"))
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 "OEMSETUP.INF" in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]".
if (fileContent.Contains("Sentinel Driver Disk"))
protections.Add("Rainbow Sentinel");
// 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,138 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Half-Life 2 Level
/// </summary>
public class VBSP : IExtractable
{
/// <inheritdoc/>
public string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
try
{
// Create the wrapper
var vbsp = SabreTools.Serialization.Wrappers.VBSP.Create(stream);
if (vbsp == null)
return null;
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// Loop through and extract all files
ExtractAllLumps(vbsp, tempPath);
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex.ToString());
return null;
}
}
/// <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,187 @@
using System;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.IO;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Valve Package File
/// </summary>
public class VPK : IExtractable
{
/// <inheritdoc/>
public string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
try
{
// Create the wrapper
var vpk = SabreTools.Serialization.Wrappers.VPK.Create(stream);
if (vpk == null)
return null;
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// Loop through and extract all files
ExtractAll(vpk, tempPath);
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
/// <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.Concat(data).ToArray();
}
// 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,129 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Half-Life Texture Package File
/// </summary>
public class WAD : IExtractable
{
/// <inheritdoc/>
public string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
try
{
// Create the wrapper
var wad = SabreTools.Serialization.Wrappers.WAD.Create(stream);
if (wad == null)
return null;
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// Loop through and extract all files
ExtractAllLumps(wad, tempPath);
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
/// <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,56 @@
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 string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Extract(fs, file, includeDebug);
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
#if NET462_OR_GREATER || NETCOREAPP
try
{
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (XZStream xzFile = new XZStream(stream))
{
string tempFile = Path.Combine(tempPath, Guid.NewGuid().ToString());
using (FileStream fs = File.OpenWrite(tempFile))
{
xzFile.CopyTo(fs);
}
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
#else
return null;
#endif
}
}
}

View File

@@ -0,0 +1,139 @@
using System;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// XBox Package File
/// </summary>
public class XZP : IExtractable
{
/// <inheritdoc/>
public string? Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
try
{
// Create the wrapper
var xzp = SabreTools.Serialization.Wrappers.XZP.Create(stream);
if (xzp == null)
return null;
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// Loop through and extract all files
ExtractAll(xzp, tempPath);
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
/// <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 = item.Model.DirectoryItems.Where(di => di?.FileNameCRC == directoryEntry.FileNameCRC).FirstOrDefault();
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 : IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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

@@ -0,0 +1,478 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Utilities;
using SabreTools.Serialization.Wrappers;
using static BinaryObjectScanner.Utilities.Dictionary;
namespace BinaryObjectScanner
{
internal static class Handler
{
#region Public Collections
/// <summary>
/// Cache for all IPathCheck types
/// </summary>
public static IEnumerable<IPathCheck?> PathCheckClasses
{
get
{
pathCheckClasses ??= InitCheckClasses<IPathCheck>();
return pathCheckClasses;
}
}
#endregion
#region Internal Instances
/// <summary>
/// Cache for all IPathCheck types
/// </summary>
private static IEnumerable<IPathCheck?>? pathCheckClasses;
#endregion
#region Multiple Implementation Wrappers
/// <summary>
/// Handle a single path based on all path check implementations
/// </summary>
/// <param name="path">Path of the file or directory to check</param>
/// <param name="scanner">Scanner object to use for options and scanning</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public static Dictionary<string, Queue<string>> HandlePathChecks(string path, IEnumerable<string>? files)
#else
public static ConcurrentDictionary<string, ConcurrentQueue<string>> HandlePathChecks(string path, IEnumerable<string>? files)
#endif
{
// Create the output dictionary
#if NET20 || NET35
var protections = new Dictionary<string, Queue<string>>();
#else
var protections = new ConcurrentDictionary<string, ConcurrentQueue<string>>();
#endif
// Preprocess the list of files
files = files?.Select(f => f.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar))?.ToList();
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in PathCheckClasses)
#else
Parallel.ForEach(PathCheckClasses, checkClass =>
#endif
{
var subProtections = checkClass?.PerformCheck(path, files);
if (subProtections != null)
AppendToDictionary(protections, path, subProtections);
#if NET20 || NET35
}
#else
});
#endif
return protections;
}
#endregion
#region Single Implementation Handlers
/// <summary>
/// Handle files based on an IDetectable implementation
/// </summary>
/// <param name="impl">IDetectable class representing the file type</param>
/// <param name="fileName">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, null on error</returns>
#if NET20 || NET35
public static Queue<string>? HandleDetectable(IDetectable impl, string fileName, Stream stream, bool includeDebug)
#else
public static ConcurrentQueue<string>? HandleDetectable(IDetectable impl, string fileName, Stream stream, bool includeDebug)
#endif
{
var protection = impl.Detect(stream, fileName, includeDebug);
return ProcessProtectionString(protection);
}
/// <summary>
/// Handle files based on an IExtractable implementation
/// </summary>
/// <param name="impl">IExtractable class representing the file type</param>
/// <param name="fileName">Name of the source file of the stream, for tracking</param>
/// <param name="stream">Stream to scan the contents of</param>
/// <param name="scanner">Scanner object to use on extractable contents</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractable impl, string fileName, Stream? stream, Scanner scanner)
#else
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractable impl, string fileName, Stream? stream, Scanner scanner)
#endif
{
// If the extractable file itself fails
try
{
// Extract and get the output path
var tempPath = impl.Extract(stream, fileName, scanner.IncludeDebug);
if (tempPath == null)
return null;
// Collect and format all found protections
var subProtections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch (Exception ex)
{
if (scanner.IncludeDebug) Console.WriteLine(ex);
}
// Prepare the returned protections
StripFromKeys(subProtections, tempPath);
PrependToKeys(subProtections, fileName);
return subProtections;
}
catch (Exception ex)
{
if (scanner.IncludeDebug) Console.WriteLine(ex);
}
return null;
}
/// <summary>
/// Handle files based on an IExtractableMSDOSExecutable implementation
/// </summary>
/// <param name="impl">IExtractableMSDOSExecutable class representing the file type</param>
/// <param name="fileName">Name of the source file of the stream, for tracking</param>
/// <param name="mz">MSDOS to scan the contents of</param>
/// <param name="scanner">Scanner object to use on extractable contents</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractableMSDOSExecutable impl, string fileName, MSDOS mz, Scanner scanner)
#else
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractableMSDOSExecutable impl, string fileName, MSDOS mz, Scanner scanner)
#endif
{
// If the extractable file itself fails
try
{
// Extract and get the output path
var tempPath = impl.Extract(fileName, mz, scanner.IncludeDebug);
if (tempPath == null)
return null;
// Collect and format all found protections
var subProtections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch (Exception ex)
{
if (scanner.IncludeDebug) Console.WriteLine(ex);
}
// Prepare the returned protections
StripFromKeys(subProtections, tempPath);
PrependToKeys(subProtections, fileName);
return subProtections;
}
catch (Exception ex)
{
if (scanner.IncludeDebug) Console.WriteLine(ex);
}
return null;
}
/// <summary>
/// Handle files based on an IExtractableLinearExecutable implementation
/// </summary>
/// <param name="impl">IExtractableLinearExecutable class representing the file type</param>
/// <param name="fileName">Name of the source file of the stream, for tracking</param>
/// <param name="lex">LinearExecutable to scan the contents of</param>
/// <param name="scanner">Scanner object to use on extractable contents</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractableLinearExecutable impl, string fileName, LinearExecutable lex, Scanner scanner)
#else
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractableLinearExecutable impl, string fileName, LinearExecutable lex, Scanner scanner)
#endif
{
// If the extractable file itself fails
try
{
// Extract and get the output path
var tempPath = impl.Extract(fileName, lex, scanner.IncludeDebug);
if (tempPath == null)
return null;
// Collect and format all found protections
var subProtections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch (Exception ex)
{
if (scanner.IncludeDebug) Console.WriteLine(ex);
}
// Prepare the returned protections
StripFromKeys(subProtections, tempPath);
PrependToKeys(subProtections, fileName);
return subProtections;
}
catch (Exception ex)
{
if (scanner.IncludeDebug) Console.WriteLine(ex);
}
return null;
}
/// <summary>
/// Handle files based on an IExtractableNewExecutable implementation
/// </summary>
/// <param name="impl">IExtractableNewExecutable class representing the file type</param>
/// <param name="fileName">Name of the source file of the stream, for tracking</param>
/// <param name="nex">NewExecutable to scan the contents of</param>
/// <param name="scanner">Scanner object to use on extractable contents</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractableNewExecutable impl, string fileName, NewExecutable nex, Scanner scanner)
#else
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractableNewExecutable impl, string fileName, NewExecutable nex, Scanner scanner)
#endif
{
// If the extractable file itself fails
try
{
// Extract and get the output path
var tempPath = impl.Extract(fileName, nex, scanner.IncludeDebug);
if (tempPath == null)
return null;
// Collect and format all found protections
var subProtections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch (Exception ex)
{
if (scanner.IncludeDebug) Console.WriteLine(ex);
}
// Prepare the returned protections
StripFromKeys(subProtections, tempPath);
PrependToKeys(subProtections, fileName);
return subProtections;
}
catch (Exception ex)
{
if (scanner.IncludeDebug) Console.WriteLine(ex);
}
return null;
}
/// <summary>
/// Handle files based on an IExtractablePortableExecutable implementation
/// </summary>
/// <param name="impl">IExtractablePortableExecutable class representing the file type</param>
/// <param name="fileName">Name of the source file of the stream, for tracking</param>
/// <param name="pex">PortableExecutable to scan the contents of</param>
/// <param name="scanner">Scanner object to use on extractable contents</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractablePortableExecutable impl, string fileName, PortableExecutable pex, Scanner scanner)
#else
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractablePortableExecutable impl, string fileName, PortableExecutable pex, Scanner scanner)
#endif
{
// If the extractable file itself fails
try
{
// Extract and get the output path
var tempPath = impl.Extract(fileName, pex, scanner.IncludeDebug);
if (tempPath == null)
return null;
// Collect and format all found protections
var subProtections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch (Exception ex)
{
if (scanner.IncludeDebug) Console.WriteLine(ex);
}
// Prepare the returned protections
StripFromKeys(subProtections, tempPath);
PrependToKeys(subProtections, fileName);
return subProtections;
}
catch (Exception ex)
{
if (scanner.IncludeDebug) Console.WriteLine(ex);
}
return null;
}
/// <summary>
/// Handle files based on an IPathCheck implementation
/// </summary>
/// <param name="impl">IPathCheck class representing the file type</param>
/// <param name="path">Path of the file or directory to check</param>
/// <returns>Set of protections in path, null on error</returns>
#if NET20 || NET35
private static Queue<string>? PerformCheck(this IPathCheck impl, string? path, IEnumerable<string>? files)
#else
private static ConcurrentQueue<string>? PerformCheck(this IPathCheck impl, string? path, IEnumerable<string>? files)
#endif
{
// If we have an invalid path
if (string.IsNullOrEmpty(path))
return null;
// Setup the output dictionary
#if NET20 || NET35
var protections = new Queue<string>();
#else
var protections = new ConcurrentQueue<string>();
#endif
// If we have a file path
if (File.Exists(path))
{
var protection = impl.CheckFilePath(path!);
var subProtections = ProcessProtectionString(protection);
if (subProtections != null)
protections.AddRange(subProtections);
}
// If we have a directory path
if (Directory.Exists(path) && files?.Any() == true)
{
var subProtections = impl.CheckDirectoryPath(path!, files);
if (subProtections != null)
protections.AddRange(subProtections);
}
return protections;
}
#endregion
#region Initializers
/// <summary>
/// Initialize all implementations of a type
/// </summary>
private static IEnumerable<T?> InitCheckClasses<T>() =>
InitCheckClasses<T>(Assembly.GetExecutingAssembly());
/// <summary>
/// Initialize all implementations of a type
/// </summary>
private static IEnumerable<T?> InitCheckClasses<T>(Assembly assembly)
{
List<T?> classTypes = [];
// If not all types can be loaded, use the ones that could be
List<Type> assemblyTypes = [];
try
{
assemblyTypes = assembly.GetTypes().ToList<Type>();
}
catch (ReflectionTypeLoadException rtle)
{
assemblyTypes = rtle.Types.Where(t => t != null)!.ToList<Type>();
}
// Loop through all types
foreach (Type type in assemblyTypes)
{
// If the type isn't a class or doesn't implement the interface
if (!type.IsClass || type.GetInterface(typeof(T).Name) == null)
continue;
// Try to create a concrete instance of the type
var instance = (T?)Activator.CreateInstance(type);
if (instance != null)
classTypes.Add(instance);
}
return classTypes;
}
#endregion
#region Helpers
/// <summary>
/// Process a protection string if it includes multiple protections
/// </summary>
/// <param name="protection">Protection string to process</param>
/// <returns>Set of protections parsed, null on error</returns>
#if NET20 || NET35
private static Queue<string>? ProcessProtectionString(string? protection)
#else
private static ConcurrentQueue<string>? ProcessProtectionString(string? protection)
#endif
{
// If we have an invalid protection string
if (string.IsNullOrEmpty(protection))
return null;
// Setup the output queue
#if NET20 || NET35
var protections = new Queue<string>();
#else
var protections = new ConcurrentQueue<string>();
#endif
// If we have an indicator of multiple protections
if (protection!.Contains(";"))
{
var splitProtections = protection.Split(';');
protections.AddRange(splitProtections);
}
else
{
protections.Enqueue(protection);
}
return protections;
}
#endregion
}
}

View File

@@ -0,0 +1,17 @@
namespace BinaryObjectScanner.Interfaces
{
/// <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="includeDebug">True to include debug data, false otherwise</param>
/// <returns>String containing any protections found in the file</returns>
string? CheckContents(string file, byte[] fileContent, bool includeDebug);
}
}

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,30 @@
using System.IO;
namespace BinaryObjectScanner.Interfaces
{
/// <summary>
/// Mark a file type as being able to be extracted
/// </summary>
/// TODO: Change to have output directory passed in
/// TODO: Change to return a bool
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="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Path to extracted files, null on error</returns>
/// <remarks>Ideally, this should just point to the other extract implementation.</remarks>
string? Extract(string file, 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="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Path to extracted files, null on error</returns>
string? Extract(Stream? stream, string file, bool includeDebug);
}
}

View File

@@ -0,0 +1,19 @@
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Interfaces
{
/// <summary>
/// Mark a LinearExecutable type as being able to be extracted
/// </summary>
public interface IExtractableLinearExecutable
{
/// <summary>
/// Extract a LinearExecutable to a temporary path, if possible
/// </summary>
/// <param name="file">Path to the input file</param>
/// <param name="lex">LinearExecutable representing the read-in file</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Path to extracted files, null on error</returns>
string? Extract(string file, LinearExecutable lex, bool includeDebug);
}
}

View File

@@ -0,0 +1,19 @@
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Interfaces
{
/// <summary>
/// Mark a MSDOS type as being able to be extracted
/// </summary>
public interface IExtractableMSDOSExecutable
{
/// <summary>
/// Extract a MSDOS to a temporary path, if possible
/// </summary>
/// <param name="file">Path to the input file</param>
/// <param name="mz">MSDOS representing the read-in file</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Path to extracted files, null on error</returns>
string? Extract(string file, MSDOS mz, bool includeDebug);
}
}

View File

@@ -0,0 +1,19 @@
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Interfaces
{
/// <summary>
/// Mark a NewExecutable type as being able to be extracted
/// </summary>
public interface IExtractableNewExecutable
{
/// <summary>
/// Extract a NewExecutable to a temporary path, if possible
/// </summary>
/// <param name="file">Path to the input file</param>
/// <param name="nex">NewExecutable representing the read-in file</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Path to extracted files, null on error</returns>
string? Extract(string file, NewExecutable nex, bool includeDebug);
}
}

View File

@@ -0,0 +1,19 @@
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Interfaces
{
/// <summary>
/// Mark a PortableExecutable type as being able to be extracted
/// </summary>
public interface IExtractablePortableExecutable
{
/// <summary>
/// Extract a PortableExecutable to a temporary path, if possible
/// </summary>
/// <param name="file">Path to the input file</param>
/// <param name="pex">PortableExecutable representing the read-in file</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Path to extracted files, null on error</returns>
string? Extract(string file, PortableExecutable pex, bool includeDebug);
}
}

View File

@@ -0,0 +1,19 @@
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Interfaces
{
/// <summary>
/// Check a Linear Executable (LE) for protection
/// </summary>
public interface ILinearExecutableCheck
{
/// <summary>
/// Check a path for protections based on file contents
/// </summary>
/// <param name="file">File to check for protection indicators</param>
/// <param name="lex">LinearExecutable 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? CheckLinearExecutable(string file, LinearExecutable lex, bool includeDebug);
}
}

View File

@@ -0,0 +1,19 @@
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Interfaces
{
/// <summary>
/// Check a MS-DOS Executable (MZ) for protection
/// </summary>
public interface IMSDOSExecutableCheck
{
/// <summary>
/// Check a path for protections based on file contents
/// </summary>
/// <param name="file">File to check for protection indicators</param>
/// <param name="mz">MSDOS 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? CheckMSDOSExecutable(string file, MSDOS mz, bool includeDebug);
}
}

View File

@@ -1,9 +1,11 @@
using BurnOutSharp.ExecutableType.Microsoft.NE;
using SabreTools.Serialization.Wrappers;
namespace BurnOutSharp
namespace BinaryObjectScanner.Interfaces
{
// TODO: This should either include an override that takes a Stream instead of the byte[]
internal interface INEContentCheck
/// <summary>
/// Check a New Executable (NE) for protection
/// </summary>
public interface INewExecutableCheck
{
/// <summary>
/// Check a path for protections based on file contents
@@ -12,6 +14,6 @@ namespace BurnOutSharp
/// <param name="nex">NewExecutable representing the read-in file</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>String containing any protections found in the file</returns>
string CheckNEContents(string file, NewExecutable nex, bool includeDebug);
string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug);
}
}

View File

@@ -1,23 +1,35 @@
using System.Collections.Concurrent;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
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>
ConcurrentQueue<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>
#if NET20 || NET35
Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files);
#else
ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files);
#endif
/// <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

@@ -1,17 +1,19 @@
using BurnOutSharp.ExecutableType.Microsoft.PE;
using SabreTools.Serialization.Wrappers;
namespace BurnOutSharp
namespace BinaryObjectScanner.Interfaces
{
// TODO: This should either include an override that takes a Stream instead of the byte[]
internal interface IPEContentCheck
/// <summary>
/// Check a Portable Executable (PE) for protection
/// </summary>
public interface IPortableExecutableCheck
{
/// <summary>
/// Check a path for protections based on file contents
/// </summary>
/// <param name="file">File to check for protection indicators</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <param name="pex">PortableExecutable representing the read-in file</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>String containing any protections found in the file</returns>
string CheckPEContents(string file, PortableExecutable pex, bool includeDebug);
string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug);
}
}

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,646 @@
using System.Collections.Generic;
using System.Text;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
public class ASPack : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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 string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
/// <summary>
/// Generate the set of matchers used for each section
/// </summary>
/// <returns></returns>
private List<ContentMatchSet> GenerateMatchers()
{
return new List<ContentMatchSet>
{
#region No Wildcards (Long)
new(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,36 @@
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
// TODO: Verify that all versions are detected
public class AdvancedInstaller : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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.Any(s => s.Contains("Software\\Caphyon\\Advanced Installer")))
return "Caphyon Advanced Installer";
}
return null;
}
/// <inheritdoc/>
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,49 @@
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
// TODO: Add version checking, if possible
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class Armadillo : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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 pex.SectionNames.Where(s => s != null && s.EndsWith("1")))
{
// Get the section strings, if they exist
var strs = pex.GetFirstSectionStrings(sectionName);
if (strs != null)
{
if (strs.Any(s => s.Contains("ARMDEBUG")))
return "Armadillo";
}
}
}
return null;
}
/// <inheritdoc/>
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
}
}

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 : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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 string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
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,151 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Compression.zlib;
using SabreTools.Matching;
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 : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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 string? Extract(string file, PortableExecutable pex, 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 null;
// 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 NET462_OR_GREATER || NETCOREAPP
data = new ReadOnlySpan<byte>(data, 0, (int)read).ToArray();
#else
var temp = new byte[read];
Array.Copy(data, 0, temp, 0, read);
data = temp;
#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 null;
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// Create the temp filename
string tempFile = string.IsNullOrEmpty(file) ? "temp.sxe" : $"{Path.GetFileNameWithoutExtension(file)}.sxe";
tempFile = Path.Combine(tempPath, tempFile);
// Write the file data to a temp file
using (Stream tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
{
tempStream.Write(data, 0, data.Length);
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
}
}

View File

@@ -1,17 +1,18 @@
using System.Collections.Generic;
using BurnOutSharp.ExecutableType.Microsoft.NE;
using BurnOutSharp.ExecutableType.Microsoft.PE;
using BurnOutSharp.Matching;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Serialization.Wrappers;
namespace BurnOutSharp.PackerType
namespace BinaryObjectScanner.Packer
{
// TODO: Figure out how to more granularly determine versions like PiD,
// at least for the 2.41 -> 2.75 range
// TODO: Figure out how to more granularly determine versions like PiD
// TODO: Detect 3.15 and up (maybe looking for `Metamorphism`)
public class EXEStealth : IContentCheck, IPEContentCheck
// TODO: Add extraction
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class EXEStealth : IContentCheck, IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includeDebug, PortableExecutable pex, NewExecutable nex)
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)
@@ -19,7 +20,7 @@ namespace BurnOutSharp.PackerType
var contentMatchSets = new List<ContentMatchSet>
{
// ??[[__[[_ + (char)0x00 + {{ + (char)0x0 + (char)0x00 + {{ + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x0 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + ?;??;??
new ContentMatchSet(new byte?[]
new(new byte?[]
{
0x3F, 0x3F, 0x5B, 0x5B, 0x5F, 0x5F, 0x5B, 0x5B,
0x5F, 0x00, 0x7B, 0x7B, 0x00, 0x00, 0x7B, 0x7B,
@@ -36,13 +37,24 @@ namespace BurnOutSharp.PackerType
}
/// <inheritdoc/>
public string CheckPEContents(string file, PortableExecutable pex, bool includeDebug)
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
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)
@@ -60,5 +72,11 @@ namespace BurnOutSharp.PackerType
return null;
}
/// <inheritdoc/>
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,81 @@
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 : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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 && ba.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes)) == true)
return "Embedded Executable";
return null;
}
/// <inheritdoc/>
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
try
{
// 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[])
.Where(b => b != null && b.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes))
.ToList();
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
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(tempPath, tempFile);
// Write the resource data to a temp file
using (var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
{
if (tempStream != null)
tempStream.Write(data, 0, data.Length);
}
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
}
}

View File

@@ -0,0 +1,39 @@
using System.Linq;
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 : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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.Any(s => s.Contains("Gentee installer")))
return "Gentee Installer";
if (strs.Any(s => s.Contains("ginstall.dll")))
return "Gentee Installer";
}
return null;
}
/// <inheritdoc/>
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,39 @@
using System.Linq;
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 : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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 = (pex.Model.ImportTable?.ImportDirectoryTable?.Any(idte => idte?.Name == "KeRnEl32.dLl") ?? false);
if (peCSection && importTableMatch)
return "HyperTech CrackProof";
return null;
}
/// <inheritdoc/>
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,84 @@
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
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 : IExtractablePortableExecutable, INewExecutableCheck, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckNewExecutable(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? CheckPortableExecutable(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.FirstOrDefault(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 string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
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 : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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 string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
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,37 @@
using System.Linq;
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 : IExtractablePortableExecutable, IPortableExecutableCheck
{
//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? CheckPortableExecutable(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.Any(s => s.Contains("ViseMain")))
return "Installer VISE";
}
return null;
}
/// <inheritdoc/>
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
}
}

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 : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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 string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,65 @@
using System;
using System.Linq;
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 : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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.Any(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.Any(s => s.Contains("MSCFu")))
return $"Microsoft CAB SFX {GetVersion(pex)}";
}
return null;
}
/// <inheritdoc/>
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
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,39 @@
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
public class NSIS : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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.Any(s => s.Contains("NullsoftInst")))
return "NSIS";
}
return null;
}
/// <inheritdoc/>
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,45 @@
using System.IO;
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 : IExtractablePortableExecutable, IPortableExecutableCheck
{
// TODO: Find samples of NeoLite 1.X.
/// <inheritdoc/>
public string? CheckPortableExecutable(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 string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
}
}

View File

@@ -1,20 +1,22 @@
using BurnOutSharp.ExecutableType.Microsoft.PE;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BurnOutSharp.PackerType
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction and better version detection
public class PECompact : IPEContentCheck
// TODO: Better version detection - https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
// TODO: Add extraction
public class PECompact : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPEContents(string file, PortableExecutable pex, bool includeDebug)
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// 0x4F434550 is "PECO"
if (pex.ImageFileHeader.PointerToSymbolTable == 0x4F434550)
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
@@ -37,5 +39,11 @@ namespace BurnOutSharp.PackerType
return null;
}
/// <inheritdoc/>
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
}
}

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 : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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 string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
}
}

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 : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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 string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
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
{
// TODO: Add extraction
public class SevenZipSFX : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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 string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
}
}

View File

@@ -1,17 +1,17 @@
using System.Collections.Generic;
using BurnOutSharp.ExecutableType.Microsoft.PE;
using BurnOutSharp.Matching;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BurnOutSharp.PackerType
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
public class Shrinker : IPEContentCheck
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class Shrinker : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPEContents(string file, PortableExecutable pex, bool includeDebug)
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
@@ -23,5 +23,11 @@ namespace BurnOutSharp.PackerType
return null;
}
/// <inheritdoc/>
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,100 @@
using System.Collections.Generic;
using System.Linq;
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 : IExtractablePortableExecutable, IPortableExecutableCheck
{
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? CheckPortableExecutable(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?.Any() == true)
{
var match = pex.HeaderPaddingStrings.FirstOrDefault(s => s.Contains("UPX!"));
//if (match != null)
// return "UPX";
match = pex.HeaderPaddingStrings.FirstOrDefault(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.FirstOrDefault(s => _upxVersionMatch.IsMatch(s));
if (match != null && pex.HeaderPaddingStrings.Any(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.Any(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 string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
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,80 @@
using System;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
#if NET462_OR_GREATER || NETCOREAPP
using SharpCompress.Archives;
using SharpCompress.Archives.Rar;
using SharpCompress.Readers;
#endif
namespace BinaryObjectScanner.Packer
{
public class WinRARSFX : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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 string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
#if NET462_OR_GREATER || NETCOREAPP
try
{
// Should be using stream instead of file, but stream fails to extract anything. My guess is that the executable portion of the archive is causing stream to fail, but not file.
using (RarArchive zipFile = RarArchive.Open(file, new ReaderOptions() { LookForHeader = true }))
{
if (!zipFile.IsComplete)
return null;
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
foreach (var entry in zipFile.Entries)
{
try
{
// If we have a directory, skip it
if (entry.IsDirectory)
continue;
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
return tempPath;
}
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
#else
return null;
#endif
}
}
}

View File

@@ -0,0 +1,804 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
#if NET462_OR_GREATER || NETCOREAPP
using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
#endif
namespace BinaryObjectScanner.Packer
{
public class WinZipSFX : IExtractableNewExecutable, IExtractablePortableExecutable, INewExecutableCheck, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckNewExecutable(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 string
bool winZipNameFound = nex.Model.ResidentNameTable
.Select(rnte => rnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(rnte.NameString))
.Any(s => s.Contains("WZ-SE-01"));
// 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? CheckPortableExecutable(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 string? Extract(string file, NewExecutable nex, bool includeDebug)
=> Extract(file, includeDebug);
/// <inheritdoc/>
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
=> Extract(file, includeDebug);
/// <summary>
/// Handle common extraction between executable types
/// </summary>
private static string? Extract(string file, bool includeDebug)
{
#if NET462_OR_GREATER || NETCOREAPP
try
{
// Should be using stream instead of file, but stream fails to extract anything. My guess is that the executable portion of the archive is causing stream to fail, but not file.
using (ZipArchive zipFile = ZipArchive.Open(file))
{
if (!zipFile.IsComplete)
return null;
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
foreach (var entry in zipFile.Entries)
{
try
{
// If we have a directory, skip it
if (entry.IsDirectory)
continue;
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
return tempPath;
}
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
#else
return null;
#endif
}
/// <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,362 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.IO;
using SabreTools.Matching;
using SabreTools.Serialization.Wrappers;
using Wise = WiseUnpacker.WiseUnpacker;
namespace BinaryObjectScanner.Packer
{
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class WiseInstaller : IExtractableNewExecutable, IExtractablePortableExecutable, INewExecutableCheck, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckNewExecutable(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? CheckPortableExecutable(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.Any(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.Any(s => s.Contains("WiseMain")))
return "Wise Installation Wizard Module";
}
return null;
}
/// <inheritdoc/>
public string? Extract(string file, NewExecutable nex, bool includeDebug)
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
try
{
// TODO: Try to find where the file data lives and how to get it
var unpacker = new Wise();
if (!unpacker.ExtractTo(file, tempPath))
{
try
{
Directory.Delete(tempPath, true);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return null;
}
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
return tempPath;
}
/// <inheritdoc/>
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
try
{
// Get the matching PE format
var format = GetPEFormat(pex);
if (format == null)
return null;
// Get the overlay data for easier reading
int overlayOffset = 0, dataStart = 0;
var overlayData = pex.OverlayData;
if (overlayData == null)
return null;
// 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 = dataStart + format.ArchiveEnd;
int archiveEndLoaded = overlayData.ReadInt32(ref overlayOffset);
if (archiveEndLoaded != 0)
format.ArchiveEnd = archiveEndLoaded;
}
// Skip to the start of the archive
overlayOffset = 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;
bool pkzip = magic?.StartsWith(new byte?[] { (byte)'P', (byte)'K' }) ?? false;
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// If we have PKZIP
if (pkzip)
{
string tempFile = Path.Combine(tempPath, "WISEDATA.zip");
using (Stream tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
{
tempStream.Write(overlayData, overlayOffset, overlayData.Length - overlayOffset);
}
}
// If we have DEFLATE -- TODO: Port implementation here or use DeflateStream
else
{
Wise unpacker = new Wise();
if (!unpacker.ExtractTo(file, tempPath))
{
try
{
Directory.Delete(tempPath, true);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return null;
}
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
/// <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;
}
/// <summary>
/// Class representing the properties of each recognized Wise installer format
/// </summary>
/// TODO: Requires all fields to be writable in package before replacement
private class FormatProperty
{
/// <summary>
/// Offset to the executable data
/// </summary>
public int ExecutableOffset { get; set; }
/// <summary>
/// Indicates if this format includes a DLL at the start or not
/// </summary>
public bool Dll { get; set; }
/// <summary>
/// Offset within the data where the archive starts
/// </summary>
public int ArchiveStart { get; set; }
/// <summary>
/// Position in the archive head of the archive end
/// </summary>
public int ArchiveEnd { get; set; }
/// <summary>
/// Format includes initialization text
/// </summary>
public bool InitText { get; set; }
/// <summary>
/// Position of the filename within the data
/// </summary>
public int FilenamePosition { get; set; }
/// <summary>
/// Format does not include a CRC
/// </summary>
public bool NoCrc { get; set; }
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
public class dotFuscator : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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.Any(s => s.Contains("DotfuscatorAttribute")))
return "dotFuscator";
}
return null;
}
/// <inheritdoc/>
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,107 @@
#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>
/// 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,120 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
// TODO: Figure out how to get version numbers
public class ActiveMARK : IContentCheck, IPortableExecutableCheck
{
/// <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? CheckPortableExecutable(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)
{
// Found in "Zuma.exe"
if (pex.EntryPointData.StartsWith(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 (pex.EntryPointData.StartsWith(new byte?[] { 0x89, 0x25, null, null, null, null, 0xEB }))
return "ActiveMark -> Trymedia Systems Inc. (Unconfirmed - Please report to us on Github)";
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
else if (pex.EntryPointData.StartsWith(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)";
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
else if (pex.EntryPointData.StartsWith(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)";
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
else if (pex.EntryPointData.StartsWith(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)";
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
else if (pex.EntryPointData.StartsWith(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)";
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
else if (pex.EntryPointData.StartsWith(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)";
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
else if (pex.EntryPointData.StartsWith(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)";
}
// Get the .data section strings, if they exist
var strs = pex.GetLastSectionStrings(".data");
if (strs != null)
{
if (strs.Any(s => s.Contains("MPRMMGVA"))
&& strs.Any(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.Any(s => s.Contains("TMSAMVOH")))
return "ActiveMARK";
}
// Get the last .bss section strings, if they exist
strs = pex.GetLastSectionStrings(".bss");
if (strs != null)
{
if (strs.Any(s => s.Contains("TMSAMVOF")))
return "ActiveMARK";
}
return null;
}
}
}

View File

@@ -0,0 +1,114 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
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 : IPathCheck, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
{
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,46 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
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/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
{
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,87 @@
using System.Collections.Generic;
using System.Linq;
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 : IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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.Any(s => s.Contains("\\SETTEC")))
return "Alpha-ROM";
if (strs.Any(s => s.Contains("SETTEC0000")))
return "Alpha-ROM";
}
// Get the .rdata section strings, if they exist
strs = pex.GetFirstSectionStrings(".rdata");
if (strs != null)
{
if (strs.Any(s => s.Contains("This Game is Japan Only")))
return "Alpha-ROM";
}
// Get the overlay data, if it exists
if (pex.OverlayStrings != null)
{
// Found in Redump entry 84122.
if (pex.OverlayStrings.Any(s => s.Contains("SETTEC0000")))
return "Alpha-ROM";
}
return null;
}
}
}

View File

@@ -0,0 +1,61 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
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/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
{
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 List<PathMatch>
{
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,166 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
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 : IPortableExecutableCheck, IPathCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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.Any(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.Any(s => s?.Contains("Byte|Shield") == true))
return "ByteShield Component Module";
// Found in "ByteShield.dll" in Redump entry 6236
else if (strs.Any(s => s?.Contains("Byteshield0") == true))
return "ByteShield Component Module";
// Found in "ByteShield.dll" in Redump entry 6236
else if (strs.Any(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.Any(s => s?.Contains("ByteShield") == true))
return "ByteShield";
}
return null;
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
{
// 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 : IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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,250 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Models.PortableExecutable;
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, INewExecutableCheck, IPathCheck, IPortableExecutableCheck
{
// 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? CheckNewExecutable(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? CheckPortableExecutable(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/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
{
// 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 PathMatch("CDCOPS.DLL", useEndsWith: true), "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 PathMatch("CDCOPS.DLL", useEndsWith: true), "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;
#if NET20 || NET35 || NET40
byte[] versionBytes = new byte[4];
Array.Copy(fileContent, positions[0] + 15, versionBytes, 0, 4);
char[] version = versionBytes.Select(b => (char)b).ToArray();
#else
char[] version = new ArraySegment<byte>(fileContent, positions[0] + 15, 4).Select(b => (char)b).ToArray();
#endif
if (version[0] == 0x00)
return string.Empty;
return new string(version);
}
}
}

View File

@@ -0,0 +1,87 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
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 : IPathCheck, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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 = pex.Model.ImportTable.ImportDirectoryTable.Any(idte => idte?.Name != null && idte.Name.Equals("cdguard.dll", StringComparison.OrdinalIgnoreCase));
if (match)
return "CD-Guard Copy Protection System";
}
return null;
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
{
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 : IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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,101 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
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 : IPathCheck, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
{
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 PathMatch("CONFIG.AFP", useEndsWith: true), "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 PathMatch("CONFIG.AFP", useEndsWith: true), "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,69 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
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/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
{
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,38 @@
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
public class CDSHiELDSE : IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(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.Any(s => s.Contains("~0017.tmp")))
return "CDSHiELD SE";
}
return null;
}
}
}

View File

@@ -0,0 +1,47 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
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/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
{
// 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,33 @@
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
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(new byte?[] { 0x43, 0x44, 0x53, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72 }, "Cactus Data Shield 200"),
// yucca.cds
new(new byte?[] { 0x79, 0x75, 0x63, 0x63, 0x61, 0x2E, 0x63, 0x64, 0x73 }, "Cactus Data Shield 200"),
};
if (contentMatchSets != null && contentMatchSets.Any())
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
}
return null;
}
}
}

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