Properly differentiate between Code-Lock and CopyLok (TheRogueArchivist)

This commit is contained in:
Matt Nadareski
2022-12-02 14:56:08 -08:00
parent 7fcaa16835
commit af882fa588
5 changed files with 159 additions and 52 deletions

View File

@@ -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
{
/// <inheritdoc/>

View File

@@ -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
{
/// <summary>
/// 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
/// </summary>
public class ChosenBytesCodeLock : IContentCheck, IPathCheck, 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>
{
// 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;
}
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// 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<ContentMatchSet>
{
// 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;
}
/// <inheritdoc/>
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string> files)
{
var matchers = new List<PathMatchSet>
{
// 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);
}
/// <inheritdoc/>
public string CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
// 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);
}
}
}

View File

@@ -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
{
/// <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>
{
// 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;
}
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// 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;
}
}
}

View File

@@ -0,0 +1,43 @@
using System.Linq;
using BurnOutSharp.ExecutableType.Microsoft.PE;
using BurnOutSharp.Interfaces;
namespace BurnOutSharp.ProtectionType
{
/// <summary>
/// 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.
/// </summary>
public class CopyLok : IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// 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;
}
}
}

View File

@@ -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 |