(Gast)
n/a Beiträge
|
Re: Von PChar nach UINT
26. Mai 2004, 15:37
btw: Hier der Hintergrund der ganzen Geschichte. Auf www.licenturion.com/xp/ gibt es den Quellcode eines Tools, mit dem man u.a. aus dem Produktschlüssel von Windows XP die Produkt-ID (die in der Registry gespeichert ist) berechnen kann. Das heißt, das Programm zeigt den relevanten Teil dieser ID an, so dass man vergleichen kann. So sieht man auch sehr schön, wo dieser Schlüssel eigentlich steckt.
Der Nutzwert hält sich damit zwar in Grenzen, aber man könnte ja mal versuchen, das Verfahren umzukehren. Sprich: aus der ID wieder den Schlüssel generieren. Das würde mich noch interessieren. Evtl. gibt es aber auch eine einfachere Möglichkeit, den Schlüssel zu ermitteln.
Wie dem auch sei, hier wäre also das Ergebnis in Delphi, wobei ich gleich noch die Produkt-ID aus der Registry auslese und ebenfalls anzeige.
Delphi-Quellcode:
procedure ShowProdKey( const ProdKey: pchar);
function CheckDigit( const uVal: UINT): UINT;
var
uSum,
uCopy : UINT;
begin
uSum := 0;
uCopy := uVal;
while(uCopy <> 0) do
begin
uSum := uSum + (uCopy mod 10);
uCopy := uCopy div 10;
end;
Result := uVal * 10 + 7 - (uSum mod 7);
end;
var
s : string;
reg : TRegistry;
uVal1,
uVal2 : UINT;
begin
// die Produkt-ID aus der Registry ermitteln
s := ' ';
reg := TRegistry.Create(KEY_READ);
if(reg <> nil) then
try
reg.RootKey := HKEY_LOCAL_MACHINE;
if(reg.OpenKey(' SOFTWARE\Microsoft\Windows NT\CurrentVersion',
false)) then
try
s := reg.ReadString(' ProductId');
finally
reg.CloseKey;
end;
finally
reg.Free;
end;
// den berechneten Wert holen, ...
uVal1 := PUINT(ProdKey)^;
// ... & umrechnen
uVal1 := uVal1 and $7fffffff;
uVal1 := uVal1 shr 1;
uVal2 := CheckDigit(uVal1 mod 1000000);
uVal1 := uVal1 div 1000000;
// die tatsächlich gespeicherte und die errechnete
// Produkt-ID anzeigen
MessageBox(0,pchar(Format(
' Your product ID should be XXXXX-%.3u-%.7u-XXXXX.' + #13#10 +
' Your reported product ID is %s',
[uVal1,uVal2,s])),' ShowProdKey',MB_OK or MB_ICONINFORMATION);
end;
function DecodeProdKey(ProdKey: string; var pResult: string;
iResLen: integer): integer;
const
ValidDigits = ' BCDFGHJKMPQRTVWXY2346789';
var
k,
m,
Aux,
NumDigits : integer;
begin
Result := -1;
if(length(ProdKey) <> 29) then
begin
Writeln(' Warning: Product key has non-standard length.');
exit;
end;
if(length(ProdKey) mod 6 < 1) then
begin
Writeln(' Product key has invalid length.');
exit;
end;
SetLength(pResult,iResLen);
ZeroMemory(@pResult[1],length(pResult));
NumDigits := length(ValidDigits);
// Bindestriche entfernen, & in Großbuchstaben konvertieren
ProdKey := StringReplace(ProdKey,' -',' ',[rfReplaceAll]);
ProdKey := UpperCase(ProdKey);
for k := 1 to length(ProdKey) do
if(ProdKey[k] <> ' ') then
begin
// Position des aktuellen Zeichens ermitteln, ...
Aux := pos(ProdKey[k],ValidDigits);
if(Aux = 0) then
begin
Writeln(' Invalid character in group');
exit;
end;
// ... aber um Eins verringern, weil sonst die
// Berechnung nicht stimmt (das liegt daran,
// dass das Zeichen-Array "ValidDigits" im
// C-Programm ja auch ein PChar ist und daher
// bei Null beginnt)
dec(Aux);
// und das ist die Berechnung ... furchtbar! ;o)
for m := 1 to length(pResult) do
begin
Aux := Aux + BYTE(pResult[m]) * NumDigits;
pResult[m] := CHR(Aux and 255);
Aux := Aux shr 8;
end;
end;
Result := 0;
end;
Aufzurufen:
Delphi-Quellcode:
var
output : string;
begin
DecodeProdKey(Edit1.Text { <-- WinXP-Schlüssel eingeben },output,15);
ShowProdKey(pchar(output));
end;
Und hier zum Vergleich mal der Original-C-Code:
Code:
unsigned int CheckDigit(unsigned int Val)
{
unsigned int Sum, Copy;
Sum = 0;
Copy = Val;
while (Copy != 0)
{
Sum += Copy % 10;
Copy /= 10;
}
return Val * 10 + 7 - (Sum % 7);
}
void ShowProdKey(unsigned char *ProdKey)
{
unsigned int Val1, Val2;
Val1 = *(unsigned int *)ProdKey;
Val1 &= 0x7fffffff;
Val1 >>= 1;
Val2 = CheckDigit(Val1 % 1000000);
Val1 /= 1000000;
printf("Your product ID should be XXXXX-%.3u-%.7u-XXXXX.\n", Val1, Val2);
}
int DecodeProdKey(char *ProdKey, unsigned char *Result, int ResLen)
{
static char *ValidDigits = "BCDFGHJKMPQRTVWXY2346789";
int i, k, m, Groups;
int Aux, NumDigits;
if (strlen(ProdKey) != 29)
fprintf(stderr, "Warning: Product key has non-standard length.\n");
if (strlen(ProdKey) % 6 < 1)
{
fprintf(stderr, "Product key has invalid length.\n");
return -1;
}
memset(Result, 0, ResLen);
NumDigits = strlen(ValidDigits);
Groups = (strlen(ProdKey) + 5) / 6;
for (i = 0; i < Groups * 6; i += 6)
{
for (k = 0; k < 5 && ProdKey[i + k] != 0; k++)
{
if (ProdKey[i + k] >= 'a' && ProdKey[i + k] <= 'z')
ProdKey[i + k] -= 32;
for (m = 0; ValidDigits[m] != 0; m++)
if (ProdKey[i + k] == ValidDigits[m])
break;
if (ValidDigits[m] == 0)
{
fprintf(stderr, "Invalid character in group '");
for (k = 0; k < 5 && ProdKey[i + k] != 0; k++)
fprintf(stderr, "%c", ProdKey[i + k]);
fprintf(stderr, "'.\n");
return -1;
}
Aux = m;
m = 0;
do
{
Aux += Result[m] * NumDigits;
Result[m++] = (unsigned char)(Aux & 255);
Aux >>= 8;
}
while (m < ResLen);
}
if (ProdKey[i + k] != '-' && ProdKey[i + k] != 0)
{
fprintf(stderr, "Expected '-' character after group '");
for (k = 0; k < 5 && ProdKey[i + k] != 0; k++)
fprintf(stderr, "%c", ProdKey[i + k]);
fprintf(stderr, "'.\n");
return -1;
}
}
return 0;
}
|