-
Notifications
You must be signed in to change notification settings - Fork 0
/
resident.asm
349 lines (292 loc) · 7.32 KB
/
resident.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
%if 0
Resident code of TSR example
2020 by C. Masloch
Usage of the works is permitted provided that this
instrument is retained with the works, so that any entity
that uses the works is notified of this instrument.
DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
%endif
%if 0
Supported Int2D functions:
AMIS - Installation check
INP: al = 00h
OUT: al = 0FFh
cx = Private version number (currently 0100h)
dx:di-> signature: "ecm ","TSR "
AMIS - Get private entry point - NOP: no private entry point
INP: al = 01h
OUT: al = 00h
AMIS - Uninstall - NOP: no resident uninstaller or NOP: can't uninstall
INP: al = 02h
OUT: If installed from command line,
al = 03h
bx = memory block of resident TSR (cs)
(If internal (pre-installed),
al = 01h
If with resident uninstaller,
al = 01h if unsuccessful
al = 0FFh if successful)
AMIS - Request pop-up - NOP: no pop-up
INP: al = 03h
OUT: al = 00h
AMIS - Determine chained interrupts
INP: al = 04h
OUT: al = 04h
dx:bx-> interrupt hook list (Int2D always.)
AMIS - Get hotkeys - NOP: no hotkeys
INP: al = 05h
OUT: al = 00h
AMIS - Get device driver information - NOP: no device
INP: al = 06h
OUT: al = 00h
AMIS - Reserved for AMIS
INP: al = 07h..0Fh
OUT: al = 00h
TSR - Get compatible version
INP: al = 10h
OUT: al = 0FFh
cx = compatible version number (currently 0100h)
TSR - Get ctrl0
INP: al = 20h
OUT: al = size of returned control data (not 0)
dx:bx-> control data
Unsupported bits switched off
TSR - Reserved for TSR
INP: al = 11h..1Fh, 21h..FFh
OUT: al = 00h
%endif
%if 0
%if TSR_VERP != ver(0,1) ; if defined one doesn't match current
%error "TSR version doesn't match"
%endif
%endif
handler:
; AMIS stuff
amissig:
.ven: fill 8,32,db "ecm" ; vendor
.prod: fill 8,32,db "TSR" ; product
%if 0
.desc: asciz ;"Example TSR" ; save memory by omitting the description
%else
.desc: asciz "Example TSR" ; description
%endif
%if $ - .desc > 64
%error AMIS description too long
%endif
amisintr:
.i21: db 21h
dw i21
.i9: db 9h
dw i9
.i70: db 70h
dw i70
.i2D: db 2Dh
dw i2D
; TSR data
ctrl0: db 1100_0000b ; control byte
; bit 6: state 1
; 7: state 2
i2D.uninstall:
inc ax ; (= 03h) safe to remove but no resident uninstaller
mov bx, cs ; = segment
i2D.hwreset equ $-1 ; (second byte of mov bx, cs is same as the retf opcode)
iret
iispentry i2D, 0, i2D
cmp ah, 0
amisnum equ $-1 ; AMIS multiplex number (data for cmp opcode)
je .handle ; our multiplex number -->
jmp far [cs:.next] ; else go to next handler -->
.handle:
test al, al
jz .installationcheck ; installation check -->
cmp al, 02h
je .uninstall ; uninstallation -->
cmp al, 04h
je .determineinterrupts ; determine hooked interrupts -->
cmp al, 10h
je .getver ; get compatible version -->
cmp al, 20h
je .getctrl0 ; get ctrl0 -->
; all other functions are reserved or not supported by TSR
.nop:
mov al, 0 ; show not implemented
iret
.installationcheck:
dec al ; (= FFh) show we're here
mov cx, TSR_VERP ; = version
xor di, di ; dx:di -> AMIS signature strings of this program
.iret_dx_cs:
mov dx, cs
.iret:
iret
.determineinterrupts: ; al = 04h, always returns list
mov bx, amisintr ; dx:bx -> hooked interrupts list
jmp short .iret_dx_cs
.getver:
mov al, 0FFh ; show call supported
mov cx, TSR_VERC ; = compatible version
iret
.getctrl0:
mov bx, ctrl0 ; dx:bx -> ctrl0
mov al, 1 ; size of ctrl0: 1 byte
jmp short .iret_dx_cs
iispentry i21, 0, i2D
jmp far [cs:.next]
%idefine KEY_MAKE_B 30h
%idefine KEY_MAKE_N 31h
%idefine KEY_MAKE_1 02h
%idefine KEY_BREAK_1 82h
%idefine KEY_BREAK_B 0B0h
%idefine KEY_BREAK_N 0B1h
iispentry i9, 0
push ax
push bx
push dx
push cx
push es
mov ah, 35h ;chained to with out original offset
mov al, 9h ;either we installed ourselves, or another ISR has
int 21h ;gracefully added us as next in the chain
;and is ceeding control, let's see...
mov ax, es
mov dx, cs
cmp ax, dx
jnz .skippush ;definitely not us, so proceed as normal
cmp bx, i9.override ;us but via the force override entry point (below)
jz .force_chain ;not safe to continue
cmp bx, i9
jnz .skippush ;not us, proceed as normal
xor bx, bx ;otherwise clean up avoid going to a non-address
mov word [cs:i9.hijacker], bx
mov word [cs:i9.hijacker + 2], bx
jmp .skippush
.override: ;called with the forced override entry point
push ax ;always act normally, as override is only applied once
push bx
push dx
push cx
push es
.skippush:
mov bl, [cs:.ctr]
in al, 60h
mov dx, ax
mov dh, KEY_MAKE_1
.check_b:
cmp dl, KEY_MAKE_B
jnz .check_n
test bl, bl
jnz .ctr_dec
mov bl, [cs:.lim]
.ctr_dec:
dec bl
jmp .meddle
.check_n:
cmp dl, KEY_MAKE_N
jnz .check_b_br
inc bl
cmp bl, [cs:.lim]
jl .meddle
xor bx, bx
jmp .meddle
.check_b_br:
mov dh, KEY_BREAK_1
cmp dl, KEY_BREAK_B
jz .meddle
.check_n_br:
cmp dl, KEY_BREAK_N
jz .meddle
.chain:
mov ax, word [cs:.hijacker]
or ax, word [cs:.hijacker + 2]
.force_chain:
pop es
pop cx
pop dx
pop bx
pop ax
jnz .to_hijacker
jmp far [cs:.next]
.to_hijacker:
jmp far [cs:.hijacker]
.meddle:
mov [cs:.ctr], bl
mov al, 0ADh
call .8024_write
jnz .panic
mov al, 0D2h
call .8024_write
jnz .panic
mov al, dh
add al, bl
out 60h, al
.panic:
mov al, 0AEh
call .8024_write
mov al, 20h
out 20h, al
pop es
pop cx
pop dx
pop bx
pop ax
iret
.8024_write:
push ax
mov cx, 0fffh
.8024_full:
in al, 64h
test al, 2
loopnz .8024_full
pop ax
jnz .8024_fail
out 64h, al
.8024_fail:
retn
.ctr:
db 0
.lim:
db 7
.hijacker:
dd 0
iispentry i70, 0
push ax
push bx
push cx
push dx
push es
push ds
mov ah, 35h
mov al, 9h
int 21h
mov ax, es
mov dx, cs
cmp ax, dx
jnz .fixup
cmp bx, i9.override
jz .done
cmp bx, i9
jnz .fixup
jmp .done
.fixup:
mov ax, word [cs:i9.hijacker] ;but don't fixup if have fixed up already once
or ax, word [cs:i9.hijacker + 2] ;so as to avoid circular loops, since this TSR
jnz .done ;does not maintain a stack of overrides
mov word [cs:i9.hijacker], bx
mov word [cs:i9.hijacker + 2], es
mov byte [cs:i9.ctr], 0
xor dx, dx
mov ds, dx
mov dx, i9.override
mov word [ds:(9 * 4)], dx
mov cx, cs
mov word [ds:(9 * 4) + 2], cx
.done:
pop ds
pop es
pop dx
pop cx
pop bx
pop ax
jmp far [cs:.next]
align 16
endarea handler