⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 easyunpack.asm

📁 也算是一个通用脱壳软件吧
💻 ASM
📖 第 1 页 / 共 3 页
字号:
                                
                                mov     g_context.ContextFlags, CONTEXT_FULL
                                invoke  GetThreadContext, ProcInfo2.hThread, addr g_context
                                mov     g_context.iDr0, 0
                                mov     g_context.iDr7, 0
                                invoke  SetThreadContext, ProcInfo2.hThread, addr g_context
                                
                                invoke  _OutputInfo, g_hOutputCtl, CTXT("抓取进程...")
                                invoke  _Dump, ProcInfo2.hProcess, dwImageBase, dwSizeOfImage, lpMem
                                invoke  TerminateProcess, ProcInfo2.hProcess, 0
                                invoke  ContinueDebugEvent, DbgEvent.dwProcessId, DbgEvent.dwThreadId, DBG_CONTINUE
                                .continue
                        .endif
                .endif
                invoke  ContinueDebugEvent, DbgEvent.dwProcessId, DbgEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED
        .endw
        invoke  CloseHandle, ProcInfo2.hThread
        invoke  CloseHandle, ProcInfo2.hProcess
        mov     ProcInfo2.hProcess, 0
        
;--------------------------------------------------------------------------------
        ;修正抓取的映象文件
        invoke  _OutputInfo, g_hOutputCtl, CTXT("修正映象文件...")
        mov     eax, dwOEP
        sub     eax, dwImageBase
        invoke  _DumpFix, lpMem, eax
        
;--------------------------------------------------------------------------------
        ;保存文件
        invoke  _OutputInfo, g_hOutputCtl, CTXT("保存文件...")
        invoke  GetPathOnly, addr szFile, addr g_buffer
        invoke  lstrcat, addr g_buffer, addr g_szDumpedName
        invoke  RtlZeroMemory, addr g_ofn, sizeof g_ofn
        mov     g_ofn.lStructSize, sizeof g_ofn
        m2m     g_ofn.hwndOwner, hWnd
        m2m     g_ofn.hInstance, g_hInst
        lea     eax, g_buffer
        mov     g_ofn.lpstrFile, eax
        mov     g_ofn.nMaxFile, sizeof g_buffer
        mov     g_ofn.Flags, OFN_FILEMUSTEXIST + OFN_PATHMUSTEXIST + OFN_OVERWRITEPROMPT
        mov     g_ofn.lpstrFilter, offset g_szFilter
        mov     g_ofn.lpstrTitle, offset g_szSaveTitle
        invoke  GetSaveFileName, addr g_ofn
        .if eax
                invoke  CreateFile, addr g_buffer, GENERIC_READ + GENERIC_WRITE, 
                        FILE_SHARE_READ + FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, 0
                .if eax==INVALID_HANDLE_VALUE
                        invoke  _OutputInfo, g_hOutputCtl, CTXT("保存文件出错!!!")
                        jmp     l_exit
                .endif
                mov     hFileDumped, eax
                invoke  WriteFile, hFileDumped, lpMem, dwSizeOfImage, addr dwSizeReturn, 0
                invoke  CloseHandle, hFileDumped
                mov     hFileDumped, 0
        .else
                invoke  _OutputInfo, g_hOutputCtl, CTXT("被取消,文件没有保存!!!")
                jmp     l_exit
        .endif
        
;--------------------------------------------------------------------------------
        ;重建输入表
        invoke  SendMessage, g_hRebIAT, BM_GETCHECK, 0, 0
        .if eax
                .if g_lpRebuildImport
                        invoke  CreateProcess, NULL, addr szFile, NULL, NULL, NULL, NORMAL_PRIORITY_CLASS, \
                                               NULL, NULL, addr StartupInfo, addr ProcInfo3
                        invoke  WaitForInputIdle, ProcInfo3.hProcess, -1
                        invoke  _OutputInfo, g_hOutputCtl, CTXT("重建输入表...")
                        mov     ecx, dwOEP
                        sub     ecx, dwImageBase
                        lea     eax, g_buffer
                        
                        push    eax
                        push    5
                        push    0
                        push    ecx
                        push    ProcInfo3.dwProcessId
                        call    g_lpRebuildImport       ;调用 ImpREC.dll 中的 RebuildImport 函数重建输入表
                        
                        .if eax==0
                                invoke  _OutputInfo, g_hOutputCtl, CTXT("重建输入表失败!!!")
                        .else
                                invoke  DeleteFile, addr g_buffer
                                lea     esi, g_buffer
                                invoke  lstrlen, esi
                                add     esi, eax
                                sub     esi, 4
                                invoke  lstrcpy, esi, CTXT("_.exe")
                        .endif
                        invoke  TerminateProcess, ProcInfo3.hProcess, 0
                .endif
        .endif
        
        invoke  SendMessage, g_hOptFile, BM_GETCHECK, 0, 0
        .if eax
                invoke  _OutputInfo, g_hOutputCtl, CTXT("优化文件结构...")
                invoke  _RebuildPE, addr g_buffer
        .endif
        invoke  _OutputInfo, g_hOutputCtl, CTXT("脱壳完成!!! *^_^*")
        
;--------------------------------------------------------------------------------
;清除工作
l_exit:
        .if pMemory
                invoke  UnmapViewOfFile, pMemory
        .endif
        .if hMapFile
                invoke  CloseHandle, hMapFile
                mov     hMapFile, 0
        .endif
        .if hFile
                invoke  CloseHandle, hFile
        .endif
        .if ProcInfo.hProcess
                invoke  CloseHandle, ProcInfo.hThread
                invoke  CloseHandle, ProcInfo.hProcess
        .endif
        .if ProcInfo2.hProcess
                invoke  CloseHandle, ProcInfo2.hThread
                invoke  CloseHandle, ProcInfo2.hProcess
        .endif
        .if ProcInfo3.hProcess
                invoke  CloseHandle, ProcInfo3.hThread
                invoke  CloseHandle, ProcInfo3.hProcess
        .endif
        .if lpMem
                invoke  GlobalFree, lpMem
        .endif
        .if hFileDumped
                invoke  CloseHandle, hFileDumped
        .endif
        ret
_Unpack endp

;优化 PE 文件,分两方面优化文件
;第一: 去掉 Dos Stub 来压缩文件头的大小,第二: 去掉每个节中的无用字节来压缩节的大小
_RebuildPE proc lpszFile:DWORD
        LOCAL   hFile, hMapFile, pMemory
        LOCAL   lpMem, dwFileSize, dwReturn
        LOCAL   lpDosHeader
        LOCAL   lpNewSection
        
        pushad
        
;--------------------------------------------------------------------------------
        ;打开文件,创建内存映射文件
        invoke  CreateFile, lpszFile, GENERIC_READ + GENERIC_WRITE, FILE_SHARE_READ,
                        0, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, 0
        .if eax==INVALID_HANDLE_VALUE
                invoke  _OutputInfo, g_hOutputCtl, CTXT("打开文件出错!!!")
                popad
                ret
        .endif
        mov     hFile, eax
        invoke  CreateFileMapping, hFile, 0, PAGE_READWRITE, 0, 0, 0
        .if !eax
                invoke  _OutputInfo, g_hOutputCtl, CTXT("创建内存映射文件出错!!!")
                invoke  CloseHandle, hFile
                popad
                ret
        .endif
        mov     hMapFile, eax
        invoke  MapViewOfFile, hMapFile, FILE_MAP_WRITE, 0, 0, 0
        .if !eax
                invoke  _OutputInfo, g_hOutputCtl, CTXT("把文件映射进内存时出错!!!")
                invoke  CloseHandle, hMapFile
                invoke  CloseHandle, hFile
                popad
                ret
        .endif
        mov     pMemory, eax
        
        invoke  GetFileSize, hFile, 0
        invoke  GlobalAlloc, GMEM_FIXED + GMEM_ZEROINIT, eax
        .if !eax
                invoke  _OutputInfo, g_hOutputCtl, CTXT("内存分配出错,文件优化不成功!!!")
                invoke  UnmapViewOfFile, pMemory
                invoke  CloseHandle, hMapFile
                invoke  CloseHandle, hFile
                popad
                ret
        .endif
        mov     lpMem, eax
        
;--------------------------------------------------------------------------------
        ;检查 PE 文件是否合法
        mov     eax, pMemory
        mov     lpDosHeader, eax
        assume  eax : ptr IMAGE_DOS_HEADER
        .if [eax].e_magic == IMAGE_DOS_SIGNATURE
                mov     ebx, eax
                add     ebx, [eax].e_lfanew
                assume  ebx : ptr IMAGE_NT_HEADERS
                .if [ebx].Signature == IMAGE_NT_SIGNATURE
                        jmp     @F
                .endif
        .endif
        invoke  _OutputInfo, g_hOutputCtl, CTXT("不是合法的 PE 文件!!!")
        invoke  UnmapViewOfFile, pMemory
        invoke  CloseHandle, hMapFile
        invoke  CloseHandle, hFile
        invoke  GlobalFree, lpMem
        popad
        ret
        @@:
        
;--------------------------------------------------------------------------------
        ;计算第一个节调整后的位置
        movzx   eax, [ebx].FileHeader.NumberOfSections
        inc     eax
        imul    eax, sizeof IMAGE_SECTION_HEADER
        movzx   ecx, [ebx].FileHeader.SizeOfOptionalHeader
        add     ecx, 18h
        add     eax, ecx
        add     eax, sizeof IMAGE_DOS_HEADER    ;eax = DosHeader+NtHeader+SectionHeader 的大小
        
        cdq
        mov     ecx, 200h
        div     ecx
        test    edx, edx
        jz      @F
        inc     eax
        @@:
        mul     ecx                             ;依 200h 对齐
        add     eax, lpMem
        mov     lpNewSection, eax
        
;--------------------------------------------------------------------------------
        ;计算节的位置和大小,构造节
        movzx   edx, [ebx].FileHeader.NumberOfSections
        movzx   ecx, [ebx].FileHeader.SizeOfOptionalHeader
        lea     ebx, [ebx+ecx+18h]
        assume  ebx : ptr IMAGE_SECTION_HEADER
        
        ;edx = 节的个数,ebx 指向节表。然后循环每个节,从节的末尾开始
        ;查找节中的无用字节(00h 就是无用字节)
        .while edx
                push    edx
                
                ;从节的末尾开始倒序查找 00h 字节
                mov     edi, [ebx].PointerToRawData
                add     edi, [ebx].SizeOfRawData
                add     edi, lpDosHeader
                mov     edx, edi
                dec     edi
                xor     eax, eax
                mov     ecx, eax
                dec     ecx
                std
                repz scasb
                
                ;在节的末尾的 4 个 00h 字节有可能是指令的一部分
                add     edi, 6
                .if edi>edx
                        mov     edi, edx
                .endif
                mov     ecx, edi
                
                ;把有用字节保存起来
                mov     esi, [ebx].PointerToRawData
                add     esi, lpDosHeader
                sub     ecx, esi
                mov     eax, ecx
                mov     edi, lpNewSection
                cld
                rep movsb
                
                ;计算下一个节的开始位置
                mov     ecx, lpNewSection
                sub     ecx, lpMem
                mov     [ebx].PointerToRawData, ecx
                mov     [ebx].SizeOfRawData, eax
                cdq
                mov     ecx, 200h
                div     ecx
                test    edx, edx
                jz      @F
                inc     eax
                @@:
                mul     ecx
                add     lpNewSection, eax
                
                add     ebx, sizeof IMAGE_SECTION_HEADER
                pop     edx
                dec     edx
        .endw
        assume  ebx : nothing
        
        ;计算优化后的文件大小
        mov     eax, lpNewSection
        sub     eax, lpMem
        mov     dwFileSize, eax
        

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -