Thema: Delphi Von PChar nach UINT

Einzelnen Beitrag anzeigen

MathiasSimmack
(Gast)

n/a Beiträge
 
#6

Re: Von PChar nach UINT

  Alt 26. Mai 2004, 14: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;
}
  Mit Zitat antworten Zitat