Hur man knäcker Atrise HTMLock

(2002-09-15)

Programmets funktioner

"True protection algorithm, based on true encryption: XOR operation of source page with a password. The password is not stored in the locked page so hackers cannot get it;"

Till skillnad från HTML Guardian som primärt inriktar sig på att skydda html-kod inriktar sig Atrise program på att lösenordsskydda sidor. Lösenordsskyddet är därför bättre här. Man skulle faktiskt kunna sträcka sig så långt som att säga att funktionen lösenordsskydd faktiskt finns i HTMLock. Sidan kodas olika beroende på vad man skriver för lösenord och för den ska bli riktigt avkodad krävs det att man matar in rätt lösenord. Därför blir tillvägagångssättet här ett annat. Vi måste försöka hitta lösenordet i den krypterade texten.

Hur det gick till

Till att börja med ska vi därför studera krypteringsalgoritmen. Tacksamt nog följer den med varje skyddad sida i javaskriptkod. Och det måste den. Annars skulle inte datorn veta hur den skulle bära sig åt för att avkryptera texten. Det är heller normalt sett inte dumt att göra algoritmen tillgänglig, för all säkerhet ska finnas i nyckeln, dvs i lösenordet. Att bygga kryptering på att hålla algoritmen hemlig är inte så smart, för om någon då tar reda på hemligheten är allt som krypterats med den algoritmen avslöjat, medan om man lyckas knäcka ett lösenord så får man ju bara reda på det som krypterats med just det lösenordet. Trots det förekommer det att företag skapar krypteringar där hela säkerheten bygger på några få hemligheter (dvd-filmer exempelvis).

Koden finns i slutet av sidan och ser ut så här:

Första funktionen: HTMLock(pw, er)

// Samtliga kommentarer av Thomas Tydal.

var emsg='Invalid password';

var h = // En array med själva sidinnehållet. De första fem elementen
        // innehåller copyrightinformation från Atrise och det sjätte

        // en kort lösenordshash på 8 bitar. Övriga element innehåller
        // vart och ett hundra bytes sidinnehåll. Dock förekommer en kodning
        // som tas upp längre ner som gör att längderna kan variera.

var t = // En array med samtliga tecken ur asciitabellen, från 0 till 255.

var x = '0123456789ABCDEF'; // Används för att skapa strängar av hexadecimala tal.

var i, j, xs;
var c = 0;
if (pw.length == 0)
  return false;
for (i = 0; i < pw.length; i++)
  c = c ^ t.indexOf(pw.charAt(i));  // ^ betyder XOR och det kommer vi
                                    // att få se mer av här.

if (c != parseInt(h[5].charAt(0) + h[5].charAt(1), 16))
{
  if (er == 1)    // Detta är bara en liten snabbkoll för att
    alert(emsg);  // besökaren inte ska råka stava fel till
  return false;   // lösenordet och se en massa skräptecken.

}
for (i = 0; i < 5; i++)
  document.writeln(h[i]);  // Skriver ut copyrightinformationen.
for (i = 0; i < 40; i++)
  document.writeln();      // Skriver ut 40 tomrader innan html-koden.
                           // Prydnadssak?
var n = pw.length;
var m = 0;
var s='';
for (j = 6; j < h.length; j++)  // Här kommer själva sidinnehållet.
{
  for (i = 0; i < h[j].length; i++)
  {
    xs = h[j].charAt(i)  // xs går igenom sidinnehållet, tecken för tecken.

    if (x.indexOf(xs) >= 0)  // Här är kodningen jag pratade om längre upp. x
    {                        // innehåller ju de hexadecimala siffrorna, så om
                             // tecknet är mellan 0 och F är det kodat och repre-
                             // senterar då alltså ascii-värdet.
      i++;
      xs = xs + h[j].charAt(i);
      c = parseInt(xs, 16);
    }
    else
      c = t.indexOf(xs);
    c = c ^ 44 ^ t.indexOf(pw.charAt(m));  // Själva krypteringsalgoritmen. Först

                                           // XOR med 44 och sedan XOR med aktuellt
                                           // tecken ur lösenordet.
    m++;
    if (m == n)
      m = 0;
    if (c == 13)
    {
      document.writeln(s);
      s = '';
    }
    else if (c == 10)
    {
      ;
    }
    else
      s = s + t.charAt(c);
  }
}
document.writeln(s);
document.close();
return true;

Andra funktionen: OnLoadCheck()

// Kallar på HTMLock() om lösenordet har angetts på adressraden.

var e = '&';
var q = unescape(window.location.search).toLowerCase() + e;
i = q.indexOf('pwd=');
var p='';
if (i != -1)
{
  var a = q.substring(i + 4, q.indexOf(e, i + 4));
  if (a != '')
    p = a;
}
HTMLock(p,0);

Tredje funktionen: HTMLockCall(pwd)

// Kallar på HTMLock() när man trycker på knappen efter att ha angett lösen.

HTMLock(document.forms[0].pwd.value, 1);

När vi nu har studerat koden är det dags att kolla in den krypterade texten och krypteringsalgoritmen för att se hur vi kan få fram sidan utan att i förväg veta lösenordet. Så här ser sidan ut när den är krypterad:

@my`xt00070ATJ39$3Dw1438(3727i("+$3D:tzm31%31/!3Eplsx;;)p{393
9 &%633E)3Eji?3E3C0D3938ti TJ/!-3E%64vkpwv0F0B~U42u1E0C1B0C1D
h+%?3D%*uyj.3C,3418(.)30.?uzj.3C,341B39+.30.?uyj:30$,|yi~U42i
jq0D02170C10t@S`xt1D18sTJxhijq0D04x)%#*37}35!-.!3C`/!-3E%64rh
}wv0CTJxhijmy(*-/wo3134,38s6562.37/6630+%36/v+&276231/35-3D65
r313438s65623835;3C%#*n!)!%"w#37%ktq1B~01)!%"xMRhijmy`193D*3E
$36.+t6608s65o19vu081Fg|0B05080601g|194543jmy`xh!38(?}z 3D3E3
D63ow?3E3D63!3027&64.36-w&27(-og3D3E3D63ow$3939w!-+3D#"3733v3
1(""36n;27$657Fitnx64),-%?27;3363313435$kt.36)36;u650CglU42ij

Imponerande, va? Det går ju inte att förstå vad som står där. Men låt oss då dra oss till minnes krypteringsalgorimen från koden ovan. Först XOR med 44 och sedan XOR med lösenordet. Vi kan ju börja med att ta den krypterade texten XOR 44 först och se vad som händer:

§?[ ?§??§?      ?V[Z#K*?!?!??´???K'X]Z*??*?!]Z??? Y???§'Ry??E
????????§??G????%?§?    ?X??'_??.&ZÊF]?¶a~DEFAULTDEFAULTDEFAU
?????K$X]Z????%)*_??C  [kkULTDEFAULTDEFAULTDEFAUP  E?ý´??
?"??Ð"????FV@D_??????%)*_-L??%??lAULTDEFAULTDEFAULTDEFAUL?, \
!/???K$X]?Ø???ËEZ xfTDEFAULTDEFAULTDEFAULTDE?? ??F?¤§?[K?¤![?
kkULTDEFAULTDEFAULTDEFAULT?&??¶? ???? KP?ì&ÐA??-y??EFAULTDEFA
¤§?´?VZ/??A??By??EFAULTDEFAULTDEFAULTDEFA'?????C?§ZY$?#¦TX$kk
!?Z???¶R??&?'ÍUP?§????FAULTDEFAULTDEFAULTDEFAU??[C???? ¶_????
?QV/ ¤·?C[??¤·???.?
????????"R'??? ,?X??'_YL??%??lAULTDEFAULTD?¶?QV/ ¤·?C[??¤·???

Hmm... Det här ser ju intressant ut. Vad kan det där "default" vara som återkommer hela tiden? Kan det vara lösenordet? *testar*... Bingo! Det var det visst.

Hur blev det så enkelt? Jo, krypteringsalgoritmen består ju som sagt av xor, och xor har den lilla "egenheten" (eller vad man nu ska kalla det) att om man tar en bokstav xor mellanslag så får man samma bokstav tillbaka (men stor om den var liten och tvärtom).
Alltså: "a" xor " " => "A".
Det som HTMLock gör är ju att ta hemsidan som ska skyddas xor lösenordet, tecken för tecken. Så vad händer om det skulle råka komma, säg tio, mellanslag i rad? Jo, då "skiner" ju lösenordet igenom. Och eftersom det är ganska vanligt att ha många mellanslag i rad när man skriver html-kod, så ja, du såg ju själv resultatet ovan.

Skulle man dock inte ha sådan tur att det finns en massa mellanslag så får man använda en annan metod som är nästan lika enkel. Den kallas "Known-plaintext attack" och bygger på att vi faktiskt har en ganska god uppfattning om vad den krypterade texten egentligen innehåller. Exempelvis börjar den säkert med &lt;HTML&gt;&lt;HEAD&gt; och har säkert ord som </HEAD><BODY> och <TABLE> i sig.

Vi tar ett exempel här så får den som inte räknat binärt med xor tidigare se hur det går till.

Vi börjar med att hämta de första tio tecknen ur den krypterade filen. Observera den enkla lilla kodningen som nämnts tidigare. Om det finns en hexadecimal siffra i texten, alltså 0-F, så utgör den tillsammans med efterföljande ett tecken. De tio första tecknena blir alltså:
t 01 1E 00 15 ~ 64 00 0C 0B 09 g.
Vi gör först om tecknena till hexkoder enligt ascii-tabellen:
74 01 1E 00 15 7E 64 00 0C 0B 09 67
Sedan måste vi börja att ta xor 44, eller 2C som det blir i hex, eftersom det stod så i krypteringsalgoritmen. Xor är ett binärt räknesätt som fungerar så här: ("^" = xor)

0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0

Först ska vi räkna 74 ^ 2C, så vi gör om dessa tal till binära. För att göra det kan du antingen titta i ascii-tabellen, eller nästan lättare är att använda nedanstående tabell (som man bör kunna utantill):

0 = 00004 = 01008 = 1000C = 1100
1 = 00015 = 01019 = 1001D = 1101
2 = 00106 = 0110A = 1010E = 1110
3 = 00117 = 0111B = 1011F = 1111

För att göra om 74 till binärt tar vi alltså 7 (0111) och 4 (0100) och slår ihop dem och får 01110100 vilket motsvarar 74. Observera att detta bara gäller när man har hexadecimala tal. Ska man göra om ett vanligt tal till binärt så måste det räknas om. Detta är en av fördelarna med att använda hexadecimala tal.

Vi ska alltså räkna 74 ^ 2C. 74 är 01110100 binärt och 2C är 00101100:

 01110100
^00101100
=========
 01011000

Sedan fortsätter vi med 01 ^ 2C, 1E ^ 2C osv. När vi gjort det får vi fram de binära talen: 01011000, 00101101, 00110010, 00101100, 00111001, 01010010, 01001000, 00101100, 00100000, 00100111, 00100101 och 01001011. Dessa ska nu i sin tur xor:as med de binära talen som representer de tecken vi vill testa med, i det här fallet &lt;HTML&gt;&lt;HEAD&gt;. Dessa binära tal slås upp i ascii-tabellen och är: 00111100, 01001000, 01010100, 01001101, 01001100, 00111110, 00111100, 01001000, 01001010, 01000001, 01000100 och 00111110.

 01011000    00101101    00110010
^00111100   ^01001000   ^01010100
==========  ==========  ==========
 01100100    01100101    01100110

Svaren vi får slås även dessa upp i ascii-tabellen och vi ser att 01100100 motsvaras av "d", 01100101 av "e" och 01100110 av "f". Fortsätter vi så kommer vi att få "defaultdefau". Surprise, surprise. Den här hemsidan började visst med <HTML><HEAD> och vi fick på så vis fram lösenordet eftersom den här krypteringen är ruskigt svag.

Länkar

Atrise HTMLock - Se själv tillverkarens information om programmet.
Ascii-tabell - Tabell över tecken samt deras hexadecimala och binära tal.