日历
网志分类
· 所有网志 (107)
· 傻伦 (54)
· 心情 (6)
· 任务 (2)
· 希望 (2)
· friends (0)
· 日记 (20)
· 技术类 (16)
· (2)
· 镜头下的缤纷世界 (2)
· 未分类 (3)
站内搜索
友情链接
· 我的歪酷
· xuan&connie's msn spaces
· connie
· rrrickey
· zorzor
· catherine 佟儿
· 风轻君 木棉林中的面包树
· suesu-阿苏
· 妹头
· 伟荣师弟
· 面包
· 桃桃

订阅 RSS

0023471

歪酷博客

猪之栏,清荷,轩


« 上一篇: hide func 下一篇: simple asm »
Eric @ 2007-03-25 21:10

;文件:attach.asm.
;宏定义.
_call MACRO procedure, parameters:VARARG
    LOCAL param, reversed
    reversed TEXTEQU <>
%    for    param, <parameters>
        reversed CATSTR <param>, <!,>, reversed
    endm
%    for    param, <reversed>
        push    param
    endm
    call    procedure
ENDM

;常量定义.
.const

;代码段开始.
.code

;以“_”开头,并以 API 函数名相接的,是用来贮存通过 GetProcAddress 得到的 API 线形地址.
    attach_start            equ        $
        OEP                             dd                0
    hLibUser32            dd        ?
    _GetProcAddress            dd        0
    _LoadLibrary            dd        0
    _FreeLibrary            dd        0
    _ExitProcess            dd        0
    _MessageBox            dd        0
    szLibUser32            db        "user32", 0
    szProcLoadLibrary        db        "LoadLibraryA", 0
    szProcFreeLibrary        db        "FreeLibrary", 0
    szProcExitProcess        db        "ExitProcess", 0
    szProcMessageBox        db        "MessageBoxA", 0
     _szAppTitle            db        "Shellcode Test", 0
        _szShowText                     db           "Shellcode Done!",0
    ;真正的代码开始.
     attach_code_start        equ        $
        call Attachment
;-----------------------------------------------------------------------------
;附加段的子程序处理模块.
Attachment proc
    ;以下是经典的查找 kernel32.dll 的基地址的代码.
        pop ebp
        sub ebp, offset Attachment
     mov    eax, [esp]
    and    eax, 0FFFF0000h
@@chk:
    cmp    dword ptr [eax], 00905A4Dh   
    je    @@fnd               
    sub    eax, 1000h           
    jmp    @@chk               
@@fnd:
    ;以下的涉及到 PE 格式的操作.
    push     ebp
    push     ebx
    push     esi
    push     edi
    mov    ebp, eax
    add    eax, [eax][IMAGE_DOS_HEADER.e_lfanew]
    mov    edi, [eax][IMAGE_NT_HEADERS.OptionalHeader.DataDirectory]
    add    edi, ebp
    mov    esi, [edi][IMAGE_EXPORT_DIRECTORY.AddressOfNames]
    add    esi, ebp
    ;在 kernel32.dll 里面查找 GetProcAddress 的API 的线形地址.
    xor    edx, edx
@@name:
    mov    eax, [esi]
    add    eax, ebp
@@chgp:    ; GetProcAddress()
    cmp    dword ptr [eax+00h], "PteG"    ; GetP
    jne    @@next
    cmp    dword ptr [eax+04h], "Acor"    ; rocA
    jne    @@next
    cmp    dword ptr [eax+08h], "erdd"    ; ddre
    jne    @@next
    cmp    word ptr [eax+0Ch], "ss"    ; ss
    jne    @@next
    mov    eax, [edi][IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals]
    add    eax, ebp
    movzx ebx, word ptr [edx*2+eax]
    mov    eax, [edi][IMAGE_EXPORT_DIRECTORY.AddressOfFunctions]
    add    eax, ebp
    mov    eax, [ebx*4+eax]
    add    eax, ebp
    ; 找到GetProcAddress 的线形地址并保存.
    mov    [_GetProcAddress], eax
@@next:
    add    esi, 4
    inc    edx
    cmp    edx, [edi][IMAGE_EXPORT_DIRECTORY.NumberOfNames]
    jne    @@name
    ;下面的是通过 GetProcAddress 获得一些API 的线形地址,并储存起来,供后面使用.
    _call    [_GetProcAddress], ebp, offset szProcFreeLibrary
    mov    [_FreeLibrary], eax
    _call    [_GetProcAddress], ebp, offset szProcExitProcess
    mov    [_ExitProcess], eax
    _call    [_GetProcAddress], ebp, offset szProcLoadLibrary
    mov    [_LoadLibrary], eax
    ;载入 user32.dll ,并储存它的句柄.
    _call    eax, offset szLibUser32
    mov    [hLibUser32], eax
    _call    [_GetProcAddress], [hLibUser32], offset szProcMessageBox
     mov    [_MessageBox], eax
        ;调用加壳函数   
    _call ShellFunc
    ;返回原程序入口点
     mov eax, dword ptr [OEP]
    jmp eax
    _call    [_FreeLibrary], [hLibUser32]
    _call    [_ExitProcess], 0
Attachment endp
;-----------------------------------------------------------------------------
;用于加壳的函数
ShellFunc proc
    ;显示对话框
        _call [_MessageBox], 0, offset _szShowText, offset _szAppTitle,\
          MB_OK or MB_ICONASTERISK or MB_APPLMODAL
        ret
ShellFunc endp
;-----------------------------------------------------------------------------
;计算加壳代码的长度.
attach_size    equ    $ - offset attach_start



;文件:Shellcode.asm.
.386
.model flat, stdcall
option casemap:none
include     c:\masm32\include\windows.inc
include     c:\masm32\include\kernel32.inc
include     c:\masm32\include\user32.inc
include     c:\masm32\include\shell32.inc
include     c:\masm32\include\comdlg32.inc
includelib     c:\masm32\lib\kernel32.lib
includelib     c:\masm32\lib\user32.lib
includelib     c:\masm32\lib\shell32.lib
includelib     c:\masm32\lib\comdlg32.lib
include     c:\masm32\include\dialogs.inc

;文本宏定义.
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

;子程序定义.
DlgProc            proto    :DWORD, :DWORD, :DWORD, :DWORD
ModifyFile        proto
ShellProc          proto

;常量定义.
.const
IDI_SHELL             equ    1000
IDC_FILENAME          equ    1001
IDC_FILEOPEN          equ    1002
IDC_OK                equ    1004
IDC_CANCEL            equ    1005

;变量定义.
.data
szFileFilter        db    "Executables (*.exe)", 0, "*.exe", 0, 0
;插入宿主的代码.
include attach.asm

;未初始化的变量定义.
.data?
mbp            MSGBOXPARAMS        <>
ofn            OPENFILENAME        <>
hInstance            dd    ?
hFile            dd    ?
szFileName        db    MAX_PATH dup (?)
szFileNameSave    db    MAX_PATH dup (?)
szFileNameBak        db    MAX_PATH dup (?)
img_dos_hdr        IMAGE_DOS_HEADER    <>
img_nt_hdrs        IMAGE_NT_HEADERS    <>
img_sect_hdr        IMAGE_SECTION_HEADER    <>

;代码段开始.
.code
main:
    invoke    GetModuleHandle, eax
    mov        hInstance, eax
    mov        mbp.hInstance, eax
    mov        ofn.hInstance, eax
    Dialog "Shellcode", \    
           "MS Sans Serif",10, \                                ; 字体和字体大小.
            WS_OVERLAPPED or WS_SYSMENU or DS_CENTER, \         ; 对话框窗口.
            5, \                                          ; 控件数目.
            50,50,160,75,\                                  ; x和y坐标.
            1024                                                ; 内存缓冲区大小.
      DlgButton "Quit",WS_TABSTOP,110,40,38,12,IDC_CANCEL
       DlgButton "OK",  WS_TABSTOP,10,40,35,12,IDC_OK
    DlgButton "Open",WS_TABSTOP,110,6,38,12,IDC_FILEOPEN
     DlgEdit WS_TABSTOP or WS_BORDER or BS_CENTER,10,20,138,12,IDC_FILENAME
        DlgStatic "File Name",SS_LEFT,10,8,70,9,100
       
        CallModalDialog hInstance,0,DlgProc,NULL
        invoke ExitProcess,NULL
;-----------------------------------------------------------------------------
;主程序消息循环.
DlgProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
    .if uMsg == WM_CLOSE
        invoke    EndDialog, hWnd, 0
                invoke ExitProcess, 0
    .elseif uMsg == WM_INITDIALOG
        ;设置图标.
        invoke    LoadIcon, hInstance, IDI_SHELL
        invoke    SendMessage, hWnd, WM_SETICON, NULL, eax
        ;储存hWnd,后面会用到.
        mov eax, hWnd
        mov    mbp.hwndOwner, eax
        mov    ofn.hwndOwner, eax
        ;设置每个 Edit 框的最大文本输入字数.
        invoke    SendDlgItemMessage, hWnd, IDC_FILENAME, \
                    EM_SETLIMITTEXT, sizeof szFileName, 0
    .elseif uMsg == WM_COMMAND
        mov    eax, wParam
        .if ax == IDC_FILEOPEN
            ;"打开文件"对话框.
            mov    ofn.lStructSize, sizeof ofn
            mov    ofn.lpstrFilter, offset szFileFilter
            mov    ofn.lpstrFile,   offset szFileName
            mov    ofn.nMaxFile,    sizeof szFileName
            invoke    GetOpenFileName, addr ofn
            ;如果选择了一个文件,就把它的文件名输出到"文件名"这个 Edit 中.
            test    eax, eax
            .if !zero?
                invoke    SetDlgItemText, hWnd, IDC_FILENAME, addr szFileName
            .endif
        .elseif ax == IDC_OK
            ;进入加壳模块.
            invoke    ShellProc
            ;把加壳后的程序变成"test.exe".
            invoke CopyFile,  addr szFileName, CTEXT("test.exe"),FALSE
            ;把备份文件还原还原成加壳前的状态.
            invoke CopyFile,  addr szFileNameBak, addr szFileNameSave,FALSE
            ;删除备份文件.
            invoke DeleteFile,addr szFileNameBak
        .elseif ax == IDC_CANCEL
            ;关闭窗口.
            invoke    SendMessage, hWnd, WM_CLOSE, 0, 0
            invoke  ExitProcess, 0
        .endif
    .else
        mov eax, FALSE
        ret
    .endif
    xor    eax, eax
    ret
DlgProc endp
;-----------------------------------------------------------------------------
;写入加壳节的模块.
ShellProc proc uses ebx ecx edx esi edi
    LOCAL bOK: BOOL
    invoke    GetDlgItemText, [mbp.hwndOwner], IDC_FILENAME, \
                     addr szFileName, sizeof szFileName
    ;备份文件.
    invoke lstrcpy, addr szFileNameSave, addr szFileName
    invoke lstrcpy, addr szFileNameBak,  addr szFileName
    ;把 szFileName字符串变成 szFileNameBak(szFileName.bak).
    invoke lstrcat, addr szFileNameBak, CTEXT(".bak")
    ;把szFileName文件复制为    szFileNamebak文件以作备份.
    invoke CopyFile, addr szFileName, addr szFileNameBak, FALSE
    invoke ModifyFile
    invoke    MessageBox, [mbp.hwndOwner], CTEXT("加壳成功!"), \
             addr szFileName, MB_OK or MB_ICONINFORMATION
    ret
ShellProc endp
;-----------------------------------------------------------------------------
;加壳函数.
ModifyFile proc uses ebx ecx edx esi edi
    LOCAL bOK: BOOL
    LOCAL pMem:DWORD
    ;打开文件.
    invoke CreateFile, addr szFileName, \
               GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, NULL,\
               OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
    ;如果打开文件失败,进行处理.
    .if eax == INVALID_HANDLE_VALUE
        ;打开文件失败.
        jmp @@safe
    .endif
    ;复制文件句柄.
    mov hFile, eax
    ;定位到文件头.
    invoke SetFilePointer,hFile,0,0,FILE_BEGIN
    ;读入 PE 文件的 IMAGE_DOS_HEADER.
    invoke    ReadFile, hFile, addr img_dos_hdr, sizeof img_dos_hdr, esp, 0
    ;判断是否为一个有效的 PE 文件.
    cmp    [img_dos_hdr.e_magic], "ZM"
    .if !zero?
    ;这不是一个有效的 PE 文件!
        jmp @@safe
    .endif
    ;把文件指针指向 IMAGE_NT_HEADERS,并读入该部分内容.
    invoke    SetFilePointer, hFile, img_dos_hdr.e_lfanew, 0, FILE_BEGIN
    invoke    ReadFile, hFile, addr img_nt_hdrs, sizeof img_nt_hdrs, esp, 0
    ;判断是否为一个有效的 PE 文件.
    cmp    [img_nt_hdrs.Signature], "EP"
    .if !zero?
        ;这不是一个有效的 PE 文件.
        jmp @@safe
    .endif
    ;储存一些数据,后面会用到.
    xor    eax, eax
    xor    edx, edx
    movzx    ecx, [img_nt_hdrs.FileHeader.NumberOfSections]
@@s000:
    push    ecx
    push    eax
    push    edx
    ;读入 IMAGE_SECTION_HEADER 内容.
    invoke    ReadFile, hFile, addr img_sect_hdr, sizeof img_sect_hdr, esp, 0
    ;判断是否已被加壳过:
    cmp  dword ptr[img_sect_hdr.Name1], "SA."
    .if eax == 0
        ;文件已被加壳.
        jmp @@safe
    .endif
    ;查找可以插入新节的位置.
    pop    edx
    mov    eax, img_sect_hdr.PointerToRawData
    add    eax, img_sect_hdr.SizeOfRawData
    cmp    eax, edx
    jbe    @@s001
    mov    edx, eax
@@s001:
    pop    eax
    mov    ecx, [img_sect_hdr.VirtualAddress]
    add    ecx, [img_sect_hdr.Misc.VirtualSize]
    cmp    eax, ecx
    jae    @@s002
    mov    eax, ecx
@@s002:
    pop    ecx
    loopd    @@s000
    ;新节的名称为".AS".
    mov    dword ptr [img_sect_hdr.Name1+00h], "SA."
    ;填充剩下的字段:
    mov    [img_sect_hdr.Misc.VirtualSize],     attach_size
    mov    [img_sect_hdr.VirtualAddress],       eax
    mov    [img_sect_hdr.SizeOfRawData],        attach_size
    mov    [img_sect_hdr.PointerToRawData],     edx
    mov    [img_sect_hdr.PointerToRelocations], ecx
    mov    [img_sect_hdr.PointerToLinenumbers], ecx
    mov    dword ptr [img_sect_hdr.NumberOfRelocations], ecx
    ;计算新节的加载RVA.
    mov    edx, 00000FFFh
    test [img_sect_hdr.VirtualAddress], edx
    .if !zero?
        and    edx, [img_sect_hdr.VirtualAddress]
        sub    edx, 1000h
        neg    edx
        add    [img_sect_hdr.VirtualAddress], edx
    .endif
    ;计算新节的 PointerToRawData 的偏移值.在 Win2k/XP 中,200h是比较保险的值.
    xor    edx, edx
    mov    eax, [img_sect_hdr.PointerToRawData]
    mov    ecx, 200h
    div    ecx
    test     edx, edx
    .if !zero?
        sub    edx, 200h
        neg    edx
        add    [img_sect_hdr.PointerToRawData], edx
    .endif
    ;设置新节的属性.
    ;code/data/execute/read/write/inited data/un-inited data.
    mov    [img_sect_hdr.Characteristics], 0E00000E0h
    ;把新节信息(IMAGE_SECTION_HEADER)写入文件.
    invoke    WriteFile, [hFile], addr img_sect_hdr, sizeof img_sect_hdr, esp, 0
    ;把一些有用的信息压栈,后面会用到.
    push     esi
    push     edi
    push eax   
    ;分配内存.
    invoke GlobalAlloc,GMEM_FIXED,attach_size
    mov pMem,eax
    mov    esi, attach_start
    mov    edi, pMem
    mov    ecx, attach_size
    rep    movsb
    mov    esi,  pMem
    mov    ecx, attach_size
;改写原程序的代码段的第一条指令的入口地址.
@@copy:
    mov    eax, [esi]
    and    eax, NOT 00000FFFh
    cmp    eax, attach_start
    .if zero?
        mov    eax, [esi]
        sub    eax, attach_start
        add    eax, [img_nt_hdrs.OptionalHeader.ImageBase]
        add    eax, [img_sect_hdr.VirtualAddress]
        mov    [esi], eax
    .endif
    inc    esi
    loopd @@copy
    mov    eax, [img_nt_hdrs.OptionalHeader.AddressOfEntryPoint]
    add    eax, [img_nt_hdrs.OptionalHeader.ImageBase]
    mov ebx, pMem
    add ebx, OEP-attach_start
    mov dword ptr[ebx],eax
    ;定位到新节的起始偏移地址.
    invoke    SetFilePointer, [hFile], [img_sect_hdr.PointerToRawData], 0, FILE_BEGIN
    ;真正把整个新节的内容写入原程序.
    invoke    WriteFile, [hFile], pMem, [img_sect_hdr.Misc.VirtualSize], esp, 0
     push pMem
    ;释放内存.
    call GlobalFree    
    mov    eax, [img_sect_hdr.VirtualAddress]
    add    eax, attach_code_start - attach_start
    inc    [img_nt_hdrs.FileHeader.NumberOfSections]
    mov    [img_nt_hdrs.OptionalHeader.AddressOfEntryPoint], eax
    add    [img_nt_hdrs.OptionalHeader.SizeOfImage], attach_size
    ;下面两句非常重要,否则加壳后的程序在 Win2k 以上的系统中运行会有错误.
    push 0
    pop [img_nt_hdrs.OptionalHeader.DataDirectory(88).VirtualAddress]
      invoke    SetFilePointer, [hFile], [img_dos_hdr.e_lfanew], 0, FILE_BEGIN
    invoke    WriteFile, [hFile], addr img_nt_hdrs, sizeof img_nt_hdrs, esp, 0
;安全的文件关闭点.
@@safe:
    invoke CloseHandle, [hFile]
    ret
ModifyFile endp
end main


评论 / 个人网页 / 扔小纸条
*昵称

已经注册过? 请登录

Email
网址
*评论