diff --git a/BurnOutSharp/ProtectionType/CDDVDCops.cs b/BurnOutSharp/ProtectionType/CDDVDCops.cs
index 4e770ab8..9b390d6e 100644
--- a/BurnOutSharp/ProtectionType/CDDVDCops.cs
+++ b/BurnOutSharp/ProtectionType/CDDVDCops.cs
@@ -9,6 +9,7 @@ using BurnOutSharp.Matching;
namespace BurnOutSharp.ProtectionType
{
+ // TODO: Investigate "Cops Copylock II" (https://www.cbmstuff.com/forum/showthread.php?tid=488).
public class CDDVDCops : IContentCheck, INewExecutableCheck, IPathCheck, IPortableExecutableCheck
{
///
diff --git a/BurnOutSharp/ProtectionType/ChosenBytesCode-Lock.cs b/BurnOutSharp/ProtectionType/ChosenBytesCode-Lock.cs
new file mode 100644
index 00000000..aae4bccd
--- /dev/null
+++ b/BurnOutSharp/ProtectionType/ChosenBytesCode-Lock.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using BurnOutSharp.ExecutableType.Microsoft.PE;
+using BurnOutSharp.Interfaces;
+using BurnOutSharp.Matching;
+
+namespace BurnOutSharp.ProtectionType
+{
+ ///
+ /// Code-Lock by ChosenBytes (https://web.archive.org/web/20040225072021/http://chosenbytes.com/) is a form of DRM that protects Visual Basic and .NET programs.
+ /// It requires the use of a registration code that is unique to each individual user (https://web.archive.org/web/20031210093259/http://www.chosenbytes.com/codemain.php).
+ /// As an advertising point, ChosenBytes apparently held a contest with a cash prize to see if a protected file could be cracked (https://web.archive.org/web/20031106163334/http://www.chosenbytes.com/challenge.php).
+ ///
+ /// Previous versions of BurnOutSharp incorrectly reported this DRM as "CodeLock / CodeLok / CopyLok". It was later discovered that due to the similar names, two entirely different DRM were erroneously lumped together.
+ /// Not only is "CodeLok / CopyLok" an entirely separate form of DRM, but "CodeLock" (as opposed to "Code-Lock") appears to refer specifically to another unrelated DRM (https://web.archive.org/web/20031106033758/http://www.codelock.co.nz/).
+ /// Also not to be confused with https://www.youtube.com/watch?v=AHqdgk0uJyc.
+ ///
+ /// Code-Lock FAQ: https://web.archive.org/web/20041205165232/http://www.chosenbytes.com/codefaq.php
+ /// Download (Version 2.35 trial): https://web.archive.org/web/20060220121200/http://www.chosenbytes.com:80/Code-Lock_cnet.zip
+ ///
+ public class ChosenBytesCodeLock : IContentCheck, IPathCheck, IPortableExecutableCheck
+ {
+ ///
+ 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
+ {
+ // CODE-LOCK.OCX
+ new ContentMatchSet(new byte?[]
+ {
+ 0x43, 0x4F, 0x44, 0x45, 0x2D, 0x4C, 0x4F, 0x43,
+ 0x4B, 0x2E, 0x4F, 0x43, 0x58
+ }, "ChosenBytes Code-Lock (Unconfirmed - Please report to us on Github)"),
+ };
+
+ return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
+ }
+
+ return null;
+ }
+
+ ///
+ public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
+ {
+ // Get the sections from the executable, if possible
+ var sections = pex?.SectionTable;
+ if (sections == null)
+ return null;
+
+ // Found in "Code-Lock.ocx" in Code-Lock version 2.35.
+ // Also worth noting is the File Description for this file, which is "A future for you, a challenge for the rest.".
+ // This check is currently broken until executable checks are overhauled.
+ string name = pex.ProductName;
+ if (name?.StartsWith("Code-Lock", StringComparison.OrdinalIgnoreCase) == true)
+ return $"ChosenBytes Code-Lock {pex.ProductVersion}";
+
+ // Get the .text section, if it exists
+ if (pex.TextSectionRaw != null)
+ {
+ var matchers = new List
+ {
+ // Found in compiled code examples created with Code-Lock 2.35.
+ // Code-Lock.ocx
+ new ContentMatchSet(new byte?[]
+ {
+ 0x43, 0x6F, 0x64, 0x65, 0x2D, 0x4C, 0x6F, 0x63,
+ 0x6B, 0x2E, 0x6F, 0x63, 0x78
+ }, "ChosenBytes Code-Lock"),
+ };
+
+ string match = MatchUtil.GetFirstMatch(file, pex.TextSectionRaw, matchers, includeDebug);
+ if (!string.IsNullOrWhiteSpace(match))
+ return match;
+ }
+
+ return null;
+ }
+
+ ///
+ public ConcurrentQueue CheckDirectoryPath(string path, IEnumerable files)
+ {
+ var matchers = new List
+ {
+ // Found in the installation directory of Code-Lock version 2.35.
+ new PathMatchSet(new PathMatch("Code-Lock.chm", useEndsWith: true), "ChosenBytes Code-Lock"),
+ new PathMatchSet(new PathMatch("Code-Lock.DEP", useEndsWith: true), "ChosenBytes Code-Lock"),
+ new PathMatchSet(new PathMatch("Code-Lock.ocx", useEndsWith: true), "ChosenBytes Code-Lock"),
+ new PathMatchSet(new PathMatch("Code-Lock Wizard.exe", useEndsWith: true), "ChosenBytes Code-Lock"),
+ };
+
+ return MatchUtil.GetAllMatches(files, matchers, any: true);
+ }
+
+ ///
+ public string CheckFilePath(string path)
+ {
+ var matchers = new List
+ {
+ // Found in the installation directory of Code-Lock version 2.35.
+ new PathMatchSet(new PathMatch("Code-Lock.chm", useEndsWith: true), "ChosenBytes Code-Lock"),
+ new PathMatchSet(new PathMatch("Code-Lock.DEP", useEndsWith: true), "ChosenBytes Code-Lock"),
+ new PathMatchSet(new PathMatch("Code-Lock.ocx", useEndsWith: true), "ChosenBytes Code-Lock"),
+ new PathMatchSet(new PathMatch("Code-Lock Wizard.exe", useEndsWith: true), "ChosenBytes Code-Lock"),
+ };
+
+ return MatchUtil.GetFirstMatch(path, matchers, any: true);
+ }
+ }
+}
\ No newline at end of file
diff --git a/BurnOutSharp/ProtectionType/CodeLock.cs b/BurnOutSharp/ProtectionType/CodeLock.cs
deleted file mode 100644
index adf255a4..00000000
--- a/BurnOutSharp/ProtectionType/CodeLock.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using BurnOutSharp.ExecutableType.Microsoft.PE;
-using BurnOutSharp.Interfaces;
-using BurnOutSharp.Matching;
-
-namespace BurnOutSharp.ProtectionType
-{
- // CodeLock / CodeLok / CopyLok
- public class CodeLock : IContentCheck, IPortableExecutableCheck
- {
- ///
- 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
- {
- // CODE-LOCK.OCX
- new ContentMatchSet(new byte?[]
- {
- 0x43, 0x4F, 0x44, 0x45, 0x2D, 0x4C, 0x4F, 0x43,
- 0x4B, 0x2E, 0x4F, 0x43, 0x58
- }, "CodeLock / CodeLok / CopyLok (Unconfirmed - Please report to us on Github)"),
- };
-
- return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
- }
-
- return null;
- }
-
- ///
- public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
- {
- // Get the sections from the executable, if possible
- var sections = pex?.SectionTable;
- if (sections == null)
- return null;
-
- // If there are more than 2 icd-prefixed sections, then we have a match
- // Found in Redump entry 31557.
- int icdSectionCount = pex.GetSectionNames().Count(s => s.StartsWith("icd"));
- if (icdSectionCount >= 2)
- return "CodeLock / CodeLok / CopyLok";
-
- return null;
- }
- }
-}
diff --git a/BurnOutSharp/ProtectionType/CopyLok.cs b/BurnOutSharp/ProtectionType/CopyLok.cs
new file mode 100644
index 00000000..3a370a09
--- /dev/null
+++ b/BurnOutSharp/ProtectionType/CopyLok.cs
@@ -0,0 +1,43 @@
+using System.Linq;
+using BurnOutSharp.ExecutableType.Microsoft.PE;
+using BurnOutSharp.Interfaces;
+
+namespace BurnOutSharp.ProtectionType
+{
+ ///
+ /// CopyLok (AKA CodeLok) is a DRM created by PAN Technology (https://web.archive.org/web/19991117100625/http://www.pantechnology.com/).
+ /// More specifically, it may have been created a spin-off division known as "Panlok" (https://cdmediaworld.com/hardware/cdrom/cd_protections_copylok.shtml).
+ /// Though it may also be that "PanLok" was an alternate name for the program itself (https://gamecopyworld.com/games/pc_generic_copylok.shtml).
+ /// There was a PanLok website, but it's unknown what content it had hosted (https://web.archive.org/web/20041215075727/http://www.panlok.com/).
+ ///
+ /// CopyLok made use of bad sectors, using an average of 720-750 per disc, and appears to have been a form of ring protection (http://forum.redump.org/topic/29842/issues-dumping-pc-disc-with-code-lock-copy-protection/).
+ /// At least one disc with CopyLok appears to contain an excerpt of the poem "Jabberwocky" by Lewis Carroll in the raw sector data (http://forum.redump.org/post/54050/#p54050).
+ /// According to the Readme for poxylok (https://gf.wiretarget.com/copylok.htm), some version of Gangsters 2 may have this protection.
+ ///
+ /// Previous versions of BurnOutSharp incorrectly reported this DRM as "CodeLock / CodeLok / CopyLok". It was later discovered that due to the similar names, two entirely different DRM were erroneously lumped together.
+ /// "CodeLock" (in this case actually referring to "Code-Lock") is an entirely separate form of DRM, with the existing check now getting used separately.
+ /// Also not to be confused with https://en.wikipedia.org/wiki/Rob_Northen_copylock.
+ ///
+ /// COPYLOK trademark: https://www.trademarkelite.com/europe/trademark/trademark-detail/000618512/COPYLOK.
+ ///
+ public class CopyLok : IPortableExecutableCheck
+ {
+ ///
+ public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
+ {
+ // Get the sections from the executable, if possible
+ var sections = pex?.SectionTable;
+ if (sections == null)
+ return null;
+
+ // If there are more than 2 icd-prefixed sections, then we have a match
+ // Though this is the same name that SafeDisc uses for protected executables, this seems to be a coincidence.
+ // Found in Redump entries 31557, 31674, 31675, 31708, 38239, 44210, and 53929.
+ int icdSectionCount = pex.GetSectionNames().Count(s => s.StartsWith("icd"));
+ if (icdSectionCount >= 2)
+ return "CopyLok / CodeLok";
+
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index c0d22c98..effd48b2 100644
--- a/README.md
+++ b/README.md
@@ -42,8 +42,9 @@ Below is a list of protections detected by BurnOutSharp. The two columns explain
| CD-X | False | True | Unconfirmed¹ |
| CDSHiELD SE | True | False | |
| Cenga ProtectDVD | True | True | |
-| CodeLock / CodeLok / CopyLok | True | False | Partially unconfirmed² |
+| ChosenBytes CodeLock | True | True | Partially unconfirmed² |
| CopyKiller | True | True | Unconfirmed¹ |
+| CopyLok/CodeLok | True | False | |
| Cucko (EA Custom) | True | False | Does not detect all known cases |
| Denuvo Anti-Cheat/Anti-Tamper| True | True | |
| Dinamic Multimedia Protection/LockBlocks | False | True | LockBlocks needs manual confirmation of the presence of 2 rings |