Improve starforce keyless detection (#396)

This commit is contained in:
HeroponRikiBestest
2025-11-17 22:00:44 -05:00
committed by GitHub
parent cc7592e07a
commit 805beb3418

View File

@@ -29,16 +29,51 @@ namespace BinaryObjectScanner.Protection
if (diskImage.VolumeDescriptorSet[0] is not PrimaryVolumeDescriptor pvd)
return null;
// Starforce Keyless check #1: the reserved 653 bytes start with a 32-bit LE number that's slightly less
int offset = 0;
// StarForce Keyless check: the key is stored in the Data Preparer identifier.
string? dataPreparerIdentiferString = pvd.DataPreparerIdentifier.ReadNullTerminatedAnsiString(ref offset)?.Trim();
if (dataPreparerIdentiferString != null
&& dataPreparerIdentiferString.Length != 0
&& Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9-]*$"))
{
// It is returning the key, as it tells you what set of DPM your disc corresponds to, and it would also
// help show why a disc might be an alt of another disc (there are at least a decent amount of StarForce
// Keyless alts that would amtch otherwise). Unclear if this is desired by the users of BOS or those
// affected by it.
// Thus far, the StarForce Keyless key is always made up of a number of characters, all either capital letters or
// numbers, sometimes with dashes in between. Thus far, 4 formats have been observed:
// XXXXXXXXXXXXXXXXXXXXXXXXX (25 characters)
// XXXXX-XXXXX-XXXXX-XXXXX-XXXXX (25 characters, plus 4 dashes seperating 5 groups of 5)
// XXXXXXXXXXXXXXXXXXXXXXXXXXXX (28 characters)
// XXXX-XXXXXX-XXXXXX-XXXXXX-XXXXXX (28 characters, with 4 dashes)
if (Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{25}$")
|| Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}$")
|| Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{28}$")
|| Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{4}-[A-Z0-9]{6}-[A-Z0-9]{6}-[A-Z0-9]{6}-[A-Z0-9]{6}$"))
{
return $"StarForce Keyless - {dataPreparerIdentiferString}";
}
// Redump ID 60270 is a unique case, there could possibly be more.
if (UnusualStarforceKeylessKeys.ContainsKey(dataPreparerIdentiferString))
return $"StarForce Keyless - {dataPreparerIdentiferString}";
}
// Starforce general check: the reserved 653 bytes start with a 32-bit LE number that's slightly less
// than the length of the volume size space. The difference varies, it's usually around 10. Check 500 to be
// safe. The rest of the data is all 0x00.
// safe. The rest of the data is all 0x00. Not many starforce discs have this, but some do, and it's
// currently the only known non-keyless check. Redump ID 60266, 72531, 87181, 91734, 106732, 105356, 74578,
// 78200 are some examples.
if (FileType.ISO9660.NoteworthyApplicationUse(pvd))
return null;
if (!FileType.ISO9660.NoteworthyReserved653Bytes(pvd))
return null;
int offset = 0;
offset = 0;
var reserved653Bytes = pvd.Reserved653Bytes;
uint initialValue = reserved653Bytes.ReadUInt32LittleEndian(ref offset);
@@ -48,48 +83,7 @@ namespace BinaryObjectScanner.Protection
// through here.
if (initialValue > pvd.VolumeSpaceSize || initialValue + 500 < pvd.VolumeSpaceSize || !Array.TrueForAll(zeroBytes, b => b == 0x00))
return null;
offset = 0;
// StarForce Keyless check #2: the key is stored in the Data Preparer identifier.
// It turns out that some (i.e. Redump ID 60266, 72531, 87181, 91734, 106732, 105356, 74578, 78200)
// non-keyless StarForce discs still have this value here? This check may need to be disabled, but it
// seems to avoid any false positives in practice so far.
var dataPreparerIdentiferString = pvd.DataPreparerIdentifier.ReadNullTerminatedAnsiString(ref offset)?.Trim();
if (dataPreparerIdentiferString == null || dataPreparerIdentiferString.Length == 0)
return "StarForce";
// It is returning the key, as it tells you what set of DPM your disc corresponds to, and it would also
// help show why a disc might be an alt of another disc (there are at least a decent amount of StarForce
// Keyless alts that would amtch otherwise). Unclear if this is desired by the users of BOS or those
// affected by it.
// Thus far, the StarForce Keyless key is always made up of a number of characters, all either capital letters or
// numbers, sometimes with dashes in between. Thus far, 4 formats have been observed:
// XXXXXXXXXXXXXXXXXXXXXXXXX (25 characters)
// XXXXX-XXXXX-XXXXX-XXXXX-XXXXX (25 characters, plus 4 dashes seperating 5 groups of 5)
// XXXXXXXXXXXXXXXXXXXXXXXXXXXX (28 characters)
// XXXX-XXXXXX-XXXXXX-XXXXXX-XXXXXX (28 characters, with 4 dashes)
if (Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{25}$")
|| Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}$")
|| Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{28}$")
|| Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{4}-[A-Z0-9]{6}-[A-Z0-9]{6}-[A-Z0-9]{6}-[A-Z0-9]{6}$"))
{
return $"StarForce Keyless - {dataPreparerIdentiferString}";
}
// Redump ID 60270 is a unique case, there could possibly be more.
if (UnusualStarforceKeylessKeys.ContainsKey(dataPreparerIdentiferString))
return $"StarForce Keyless - {dataPreparerIdentiferString}";
// In case any variants were missed.
if (Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9-]*$"))
return $"StarForce Keyless - {dataPreparerIdentiferString} - Unknown variant, please report to us on GitHub!";
// 34206 reaches this because it's not keyless, and has "WinISO software" as the DPI string. However, since
// it has lowercase letters and spaces, it's caught here. It is genuinely StarForce, so it's not a false
// positive.
return "StarForce";
}