Živě.cz o počítačích a internetu

Tipy a triky v Delphi, díl 183. – licenční klíč Windows

Jan Šindelář 4.5.2005

Trik, který si dnes ukážeme, byl do značné míry motivován mou vlastní nedávnou zkušeností s instalací Windows a souvisí s licenčním klíčem, který je nutné při instalaci zadat. Naučíme se totiž, jak jej získat. Ale nebudeme nic crackovat ani nic podobného, vše bude zcela legální.

Legálně? Legálně!

Nejdřív nastíním pozadí dnešního příkladu. Troufám si tvrdit, že většina z vás již někdy instalovala systém Windows a tak víte, že během instalace je nutné zadat klíč, který je součástí legální kopie. Vzhledem k tomu, že se systém instaluje jen jednou za čas, nebývá toto CD právě při ruce, často bývá někde hluboko ve skříni.

Oblíbené je dnes rovněž to, že si zkušenější uživatelé a administrátoři předělávají originální instalační média tím, že do nich například integrují service pack, ovladače, vytváří bezobslužnou instalaci a podobně. Často se pak stává, že neinstalujeme z originálních médií, která máme někde založena, ale z upravené kopie, ke které si zapomeneme poznamenat licenční klíč.

Sedíte tedy u počítače, všechno máte zálohováno a chystáte se přeinstalovat kompletně systém, ale bez licenčního čísla to nejde a hledat se vám originální médium nechce. Co teď? Ano, jako bych viděl vaše úsměvy, jedna z cest je pochopitelně ne zcela legální a sice najít si vše potřebné rychle na internetu. Proč to ale dělat, když přece náš licenční klíč máme a to v našem právě spuštěném systému, u kterého sedíme a který se chystáme přeinstalovat. Než ho tedy pošleme definitivně do pekel a přeinstalujeme, může nám prokázat poslední službu a prozradit nám licenční klíč.

Kde jinde by mohl být klíč uložen než v registrech. Pokud jej ovšem budete hledat, tak zjistíte, že sice cosi jako klíč najdete, avšak ne v té podobě, ve které se zadává při instalaci. Je totiž "zakódován" do číselné podoby a je nutné ho nejprve upravit. Přesně v této situaci jsem se nacházel nedávno a věc jsem nakonec vyřešil tím, že jsem si z internetu stáhl jednoduchou utilitku, která právě toto dekódování uměla. Nedalo mi to však a později jsem našel zajímavý zdrojový kód, ve kterém je vidět, jak se toto dekódování provádí. A právě ten jsem pro vás dnes upravil.

Začínáme programovat

Nejprve omezující podmínka. Tento kód bude fungovat pouze pro novější Windows, tedy 2000/XP, takže pod dnes již "odepsanou" generací 9x jej ani nezkoušejte. Nejsem si jistý, ale v této staré generaci je licenční klíč tuším uložen v registrech dokonce v té podobě, jak se zadává při instalaci, takže žádné dekódování ani není nutné. Stačí vědět, kde klíč najít.

Uživatelské rozhraní bude tentokrát velmi jednoduché a nebude obsahovat nic jiného než Edit, do kterého bude vypsáno licenční číslo hned po spuštění programu v události OnCreate formuláře. O zbytek se postarají dvě jednoduché funkce. V první bude jednoduché čtení registrů, čímž získáme původní nedekódované číslo. To pak pošleme druhé funkci, která nám vrátí textový řetězec s hledaným výsledným klíčem.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Registry, StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function DecodeProductKey(const HexSrc: array of Byte): string;
const
  StartOffset: Integer = $34;
  EndOffset: Integer  = $34 + 15;
  Digits: array[0..23] of Char = (`B`, `C`, `D`, `F`, `G`, `H`, `J`, `K`, `M`, `P`, `Q`, `R`, `T`, `V`, `W`, `X`, `Y`, `2`, `3`, `4`, `6`, `7`, `8`, `9`);
  dLen: Integer = 29;
  sLen: Integer = 15;
var
  HexDigitalPID: array of Cardinal;
  Des: array of Char;
  i, n: Integer;
  hn, Value: Cardinal;
begin
  SetLength(HexDigitalPID, dLen);
  for i := StartOffset to EndOffset do HexDigitalPID[i - StartOffSet] := HexSrc[i];
  SetLength(Des, dLen + 1);
  for i := dLen - 1 downto 0 do
  begin
    if (((i + 1) mod 6) = 0) then Des[i] := `-`
                            else
                              begin
                                hn := 0;
                                for n := sLen - 1 downto 0 do
                                  begin
                                    Value := (hn shl 8) or HexDigitalPID[n];
                                    HexDigitalPID[n] := Value div 24;
                                    hn := Value mod 24;
                                  end;
                                Des[i] := Digits[hn];
                              end;
  end;
  Des[dLen] := Chr(0);
  for I := 0 to Length(Des) do Result := Result + Des[I];
end;

function View_Win_Key: string;
var
  Reg: TRegistry;
  binarySize: integer;
  HexBuf: array of byte;
begin
  Reg := TRegistry.Create;
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    if Reg.OpenKeyReadOnly(`\SOFTWARE\Microsoft\Windows NT\CurrentVersion`) then
    begin
      if Reg.GetDataType(`DigitalProductId`) = rdBinary then
      begin
        binarySize := Reg.GetDataSize(`DigitalProductId`);
        SetLength(HexBuf, binarySize);
        if binarySize > 0 then Reg.ReadBinaryData(`DigitalProductId`, HexBuf[0], binarySize);
      end;
    end;
  finally
    FreeAndNil(Reg);
  end;
  Result := DecodeProductKey(HexBuf);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Edit1.Text := View_Win_Key;
end;

end.

Na čtení údajů z registru není zajímavého celkem nic, dělali jsme to již mnohokrát. Mnohem zajímavější je funkce na dekódování. Výsledný klíč se skládá z omezené množiny možných znaků, několik písmen a číslic chybí. Alespoň mně to přišlo zajímavé. Samotný algoritmus dekódování pak nemá celkem cenu příliš rozebírat, všechno je vidět ve zdrojovém kódu.

A to je pro dnešek vše. Chápu, že tato funkce má velmi specifické použití, ale občas neškodí si ukázat nějakou zajímavost. Jako obvykle, i tentokrát si můžete ukázkovou aplikaci stáhnout zde.