Skip to content

Instantly share code, notes, and snippets.

@shibajee
Created June 25, 2023 11:54
Show Gist options
  • Save shibajee/566f981049ec95eb2353736f1ba1cc61 to your computer and use it in GitHub Desktop.
Save shibajee/566f981049ec95eb2353736f1ba1cc61 to your computer and use it in GitHub Desktop.
Creative Sound Blaster Legacy Product Activation Source Code
#include <mbedtls/des.h>
#include <mbedtls/md5.h>
#include <stdio.h>
#include <Windows.h>
#include <IPHlpApi.h>
#include <ShlObj.h>
#include <Shlwapi.h>
#define TRACE 0
/* In place DSA-ECB encryption */
void encryptData(const unsigned char *key, unsigned char *msg, size_t len)
{
mbedtls_des_context ctx;
mbedtls_des_init(&ctx);
while (len >= 8) {
mbedtls_des_setkey_enc(&ctx, key);
mbedtls_des_crypt_ecb(&ctx, msg, msg);
msg += 8;
len -= 8;
}
#if TRACE
if (len)
printf("encryptData: Skipping last %d bytes.\n");
#endif
mbedtls_des_free(&ctx);
}
/* In place DSA-ECB decryption */
void decryptData(const unsigned char *key, unsigned char *msg, size_t len)
{
mbedtls_des_context ctx;
mbedtls_des_init(&ctx);
while (len >= 8) {
mbedtls_des_setkey_enc(&ctx, key);
mbedtls_des_crypt_ecb(&ctx, msg, msg);
msg += 8;
len -= 8;
}
#if TRACE
if (len)
printf("decryptData: Skipping last %d bytes.\n");
#endif
mbedtls_des_free(&ctx);
}
/* MAC address MD5 hash */
void hashMACAddress(const BYTE *msg, size_t len, BYTE *out)
{
unsigned char tmp[16];
char *buf;
if (msg == NULL || !len || out == NULL)
return;
buf = (char *)malloc(3 * len);
sprintf(buf, "%02X", msg[0]);
for (size_t i = 1; i < len; i++)
sprintf(buf + 2 + 3 * (i - 1), "-%02X", msg[i]);
#if TRACE
printf("Hashing interface %s\n", buf);
#endif
mbedtls_md5((unsigned char *)buf, 3 * len - 1, tmp);
for (size_t i = 0; i < 16; i++) {
sprintf(buf, "%02x", tmp[i]);
out[2 * i] = buf[0];
out[2 * i + 1] = buf[1];
}
#if TRACE
printf("MD5 hash %.32s\n", out);
#endif
free(buf);
}
/* Volume serial MD5 hash */
void hashVolumeSerial(DWORD msg, BYTE *out)
{
unsigned char tmp[16];
char buf[9];
int i;
sprintf(buf, "%08X", msg);
#if TRACE
printf("Hashing volume %s\n", buf);
#endif
mbedtls_md5((unsigned char *)buf, 8, tmp);
for (i = 0; i < 16; i++) {
sprintf(buf, "%02x", tmp[i]);
out[2 * i] = buf[0];
out[2 * i + 1] = buf[1];
}
#if TRACE
printf("MD5 hash %.32s\n", out);
#endif
}
/* System time MD5 hash */
void hashSystemTime(SYSTEMTIME *msg, BYTE *out)
{
unsigned char tmp[16];
char buf[9];
int i;
sprintf(buf, "%04d%02d%02d", msg->wYear, msg->wMonth, msg->wDay);
#if TRACE
printf("Hashing time %s\n", buf);
#endif
mbedtls_md5((unsigned char *)buf, 8, tmp);
for (i = 0; i < 16; i++) {
sprintf(buf, "%02x", tmp[i]);
out[2 * i] = buf[0];
out[2 * i + 1] = buf[1];
}
#if TRACE
printf("MD5 hash %.32s\n", out);
#endif
}
const BYTE terminator[] = "\x00\xff\xff\xff\xff\xff\xff\xff";
// unknown purpose, but needs to be unique
const BYTE unknown[] = "deadbeef000000000000000000000000";
struct KeyNamePair
{
const char * key;
const char * name;
};
KeyNamePair knp[] =
{
{ "LA56KHYE", "CTLT99HB0X.kga" },
{ "S3MP42XB", "CTLT46HL1X.kga" },
{ "KYE08ZY3", "CTLT72HL2X.kga" },
{ "A31OKL25", "CTLT11HL3X.kga" },
{ "6K5YEHLA", "CTLT47H9X2.kga" }, //
{ "PX432SBM", "CTLT21H1X2.kga" }, //
{ "ZKY03YE8", "CTLT02H0X2.kga" }, //
{ "OKLA2153", "CTLTD2H3X2.kga" }, //
{ "NH5L2P13", "CTLT9SJDX2.kga" }, //
{ "BDC5687E", "CTLXS2Q3X2.kga" }, //
{ "23A3693F", "CTLO3H65X2.kga" }, //
{ "OAMDWHRH", "CTLMN34SX2.kga" }, //
{ "OTRTTRTR", "CTLNBK2HX2.kga" }, //
{ "OARPTNDH", "CTLLAS4HX2.kga" }, //
{ "OMNPMHHH", "CTLPS4HTX2.kga" }, //!
{ "AKSMRTSD", "CTLI37CVX2.kga" }, //
{ "F1GY89SE", "CTLUE8XYX2.kga" }, //
{ "L3IUZSK3", "CTLS2SR4X2.kga" }, //
{ "JH578SAA", "CTLT53HURX.kga" },
{ "LWR232SZ", "CTD5H2W3DK.kga" },
{ "XR2AG82P", "CTD1JXF23A.kga" }, //*
{ "P23DSU4S", "CTT78HSK12.kga" },
{ "P32LUD17", "CTT92KD23N.kga" },
{ "X34DSL1S", "CTD3SPO23G.kga" },
{ "ZL00SEW3", "CTLE2C3BA1.kga" },
{ "H34T2GW2", "CTH6K23AS7.kga" },
{ "BX32DNEK", "CTA30CF234.kga" }, //
{ "6BDF7E41", "CTA200FF2D.kga" }, //
{ "J8K23NM2", "CTAE90C24A.kga" }, //
{ "IH68ULK0", "CTLD2JX234.kga" }, //
{ "K53SFR23", "CTLD14KLI5.kga" }, //
{ "LQW341ME", "CTL42SW23M.kga" }, //
{ "M21PWSZ0", "CTLP22SV21.kga" }, //
{ "GN3E92V4", "CTLA20RVB5.kga" }, //*
{ "R260D5PX", "CTL34AF61R.kga" }, //
};
void GenKga(const char * key, const char * filename)
{
DWORD ret, adapterCount, hashCount, volumeSerial;
ULONG len;
PIP_ADAPTER_INFO adapters, adap;
PBYTE hashes, hash;
CHAR buf[256];
INT drive;
SYSTEMTIME time;
FILE *file;
printf("Generating %s\n", filename);
adapterCount = 1;
len = adapterCount * sizeof(IP_ADAPTER_INFO);
adapters = (PIP_ADAPTER_INFO)malloc(len);
if ((ret = GetAdaptersInfo(adapters, &len)) == ERROR_BUFFER_OVERFLOW)
adapters = (PIP_ADAPTER_INFO)realloc(adapters, len);
if (GetAdaptersInfo(adapters, &len) != NO_ERROR) {
fprintf(stderr, "GetAdapterInfo failed, aborting.\n");
free(adapters);
exit(1);
}
adapterCount = 0;
adap = adapters;
while (adap) {
if (adap->Type == MIB_IF_TYPE_ETHERNET) {
adapterCount++;
}
adap = adap->Next;
}
#if TRACE
printf("Adapter count: %d\n", adapterCount);
#endif
hashCount = adapterCount + 3;
hash = hashes = (PBYTE)malloc((32 * hashCount) + 8);
adap = adapters;
while (adap) {
if (adap->Type == MIB_IF_TYPE_ETHERNET) {
if (adap->AddressLength) {
hashMACAddress(adap->Address, adap->AddressLength, hash);
hash += 32;
}
else {
hashCount--;
}
}
adap = adap->Next;
}
free(adapters);
GetSystemDirectory(buf, 256);
drive = PathGetDriveNumber(buf);
sprintf(buf, "%C:\\", 'A' + drive);
GetVolumeInformation(buf, NULL, 0, &volumeSerial, NULL, NULL, NULL, 0);
hashVolumeSerial(volumeSerial, hash);
hash += 32;
memcpy(hash, unknown, 32);
hash += 32;
GetSystemTime(&time);
hashSystemTime(&time, hash);
hash += 32;
memcpy(hash, terminator, 8);
encryptData((unsigned char *)key, (unsigned char *)hashes, (32 * hashCount) + 8);
file = fopen(filename, "wb+");
fwrite(hashes, (32 * hashCount) + 8, 1, file);
fclose(file);
free(hashes);
#if TRACE
printf("\n");
#endif
}
int main(int argc, char *argv[])
{
char szPath[MAX_PATH];
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, szPath)))
{
strcat_s(szPath, "\\Creative\\SoftwareLock");
int error = SHCreateDirectoryExA(NULL, szPath, NULL);
if (error == ERROR_SUCCESS || error == ERROR_FILE_EXISTS || error == ERROR_ALREADY_EXISTS)
SetCurrentDirectoryA(szPath);
ZeroMemory(szPath, sizeof(szPath));
}
GetCurrentDirectoryA(MAX_PATH, szPath);
printf("%s\n", szPath);
for (int i = 0; i < sizeof(knp) / sizeof(KeyNamePair); i++)
{
GenKga(knp[i].key, knp[i].name);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment