📄 easyunpack.asm
字号:
;========================
; 一块三毛钱
; 2004.3.16
;========================
.386
.model flat, stdcall ;32 bit memory model
option casemap :none ;case sensitive
include EasyUnpack.inc
.code
start:
invoke GetModuleHandle, NULL
mov g_hInst, eax
invoke InitCommonControls
invoke DialogBoxParam, g_hInst, DLG_MAIN, NULL, addr DlgProc, NULL
invoke ExitProcess, 0
DlgProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
mov eax, uMsg
.if eax==WM_INITDIALOG
invoke _Init, hWnd
.elseif eax==WM_COMMAND
invoke _Command, hWnd, wParam, lParam
.elseif eax==WM_PAINT
invoke _Paint, hWnd
.elseif eax==WM_DROPFILES
invoke DragQueryFile, wParam, 0, addr g_buffer, sizeof g_buffer
invoke GetFileAttributes, addr g_buffer
and eax, FILE_ATTRIBUTE_DIRECTORY
.if !eax ;如果不是文件夹
invoke SetWindowText, g_hFileCtl, addr g_buffer
.endif
invoke DragFinish, wParam
.elseif eax==WM_CLOSE
invoke EndDialog, hWnd, 0
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DlgProc endp
;处理按钮消息
_Command proc hWnd:DWORD, wParam:DWORD, lParam:DWORD
pushad
mov eax, wParam
and eax, 0ffffh
.if eax==IDC_BTN_OPENFILE
invoke RtlZeroMemory, addr g_buffer, sizeof g_buffer
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
mov g_ofn.lpstrFilter, offset g_szFilter
mov g_ofn.lpstrTitle, offset g_szOpenTitle
invoke GetOpenFileName, addr g_ofn
.if eax
invoke SetWindowText, g_hFileCtl, addr g_buffer
.endif
.elseif eax==IDC_CHK_OEP
invoke SendMessage, g_hChkOEP, BM_GETCHECK, 0, 0
.if eax
invoke EnableWindow, g_hOEP, TRUE
.else
invoke EnableWindow, g_hOEP, FALSE
.endif
.elseif eax==IDC_BTN_START
invoke _Unpack, hWnd
.endif
popad
ret
_Command endp
;脱壳过程
_Unpack proc hWnd:DWORD
LOCAL szFile[1024] : BYTE
LOCAL hFile, hMapFile, pMemory
LOCAL dwImageBase, dwSizeOfImage, dwOrgOEP
LOCAL StartupInfo : STARTUPINFO
LOCAL ProcInfo : PROCESS_INFORMATION
LOCAL ProcInfo2: PROCESS_INFORMATION
LOCAL ProcInfo3: PROCESS_INFORMATION
LOCAL buf[256] : BYTE
LOCAL lpMem, dwOEP
LOCAL int3 : BYTE, org_code : BYTE
LOCAL dwCountBP
LOCAL DbgEvent : DEBUG_EVENT
LOCAL hFileDumped, dwSizeReturn
;--------------------------------------------------------------------------------
;初始化局部变量
invoke RtlZeroMemory, addr szFile, sizeof szFile
xor eax, eax
mov hFile, eax
mov hMapFile, eax
mov pMemory, eax
mov lpMem, eax
mov dwOEP, eax
mov int3, al
mov org_code, al
mov dwCountBP, eax
mov hFileDumped, eax
mov dwSizeReturn, eax
invoke RtlZeroMemory, addr StartupInfo, sizeof StartupInfo
invoke RtlZeroMemory, addr ProcInfo, sizeof ProcInfo
invoke RtlZeroMemory, addr ProcInfo2, sizeof ProcInfo2
invoke RtlZeroMemory, addr ProcInfo3, sizeof ProcInfo3
invoke RtlZeroMemory, addr DbgEvent, sizeof DbgEvent
;--------------------------------------------------------------------------------
;取得文件名
invoke SendMessage, g_hOutputCtl, LB_RESETCONTENT, 0, 0
invoke GetWindowText, g_hFileCtl, addr szFile, sizeof szFile
.if eax==0
invoke _OutputInfo, g_hOutputCtl, CTXT("没有指定文件!!!")
jmp l_exit
.endif
;--------------------------------------------------------------------------------
;打开文件,创建内存映射文件,检查文件是不是合法的 PE 文件
invoke CreateFile, addr szFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, 0
.if eax==INVALID_HANDLE_VALUE
invoke _OutputInfo, g_hOutputCtl, CTXT("打开文件出错!!!")
jmp l_exit
.endif
mov hFile, eax
invoke CreateFileMapping, hFile, 0, PAGE_READONLY, 0, 0, 0
.if !eax
invoke _OutputInfo, g_hOutputCtl, CTXT("创建内存映射文件出错!!!")
jmp l_exit
.endif
mov hMapFile, eax
invoke MapViewOfFile, hMapFile, FILE_MAP_READ, 0, 0, 0
.if !eax
invoke _OutputInfo, g_hOutputCtl, CTXT("把文件映射进内存时出错!!!")
jmp l_exit
.endif
mov pMemory, eax
mov esi, eax
assume esi : ptr IMAGE_DOS_HEADER
.if [esi].e_magic == IMAGE_DOS_SIGNATURE
add esi, [esi].e_lfanew
assume esi : ptr IMAGE_NT_HEADERS
.if [esi].Signature == IMAGE_NT_SIGNATURE
jmp @F
.endif
.endif
invoke _OutputInfo, g_hOutputCtl, CTXT("不是合法的 PE 文件!!!")
jmp l_exit
@@:
m2m dwImageBase, [esi].OptionalHeader.ImageBase
m2m dwSizeOfImage, [esi].OptionalHeader.SizeOfImage
m2m dwOrgOEP, [esi].OptionalHeader.AddressOfEntryPoint
mov eax, dwImageBase
add dwOrgOEP, eax
;--------------------------------------------------------------------------------
;关闭内存映射文件,关闭文件
invoke UnmapViewOfFile, pMemory
mov pMemory, 0
invoke CloseHandle, hMapFile
mov hMapFile, 0
invoke CloseHandle, hFile
mov hFile, 0
;--------------------------------------------------------------------------------
invoke wsprintf, addr buf, CTXT("基地址: %08lXh"), dwImageBase
invoke _OutputInfo, g_hOutputCtl, addr buf
invoke wsprintf, addr buf, CTXT("映象大小: %08lXh"), dwSizeOfImage
invoke _OutputInfo, g_hOutputCtl, addr buf
invoke wsprintf, addr buf, CTXT("原始入口点: %08lXh"), dwOrgOEP
invoke _OutputInfo, g_hOutputCtl, addr buf
invoke _OutputInfo, g_hOutputCtl, CTXT("开始脱壳...")
;--------------------------------------------------------------------------------
;创建进程,准备查找入口点
invoke GetStartupInfo, addr StartupInfo
mov StartupInfo.dwFlags, STARTF_USESHOWWINDOW
mov StartupInfo.wShowWindow, SW_HIDE
invoke CreateProcess, NULL, addr szFile, NULL, NULL, NULL, NORMAL_PRIORITY_CLASS, \
NULL, NULL, addr StartupInfo, addr ProcInfo
.if !eax
invoke _OutputInfo, g_hOutputCtl, CTXT("不能创建进程!!!")
jmp l_exit
.endif
invoke WaitForInputIdle, ProcInfo.hProcess, INFINITE
invoke SuspendThread, ProcInfo.hThread
invoke wsprintf, addr buf, CTXT("已创建进程: PID=%08lXh"), ProcInfo.dwProcessId
invoke _OutputInfo, g_hOutputCtl, addr buf
invoke _OutputInfo, g_hOutputCtl, CTXT("查找入口点...")
;--------------------------------------------------------------------------------
;读取进程内存
invoke GlobalAlloc, GMEM_ZEROINIT + GMEM_FIXED, dwSizeOfImage
.if !eax
invoke _OutputInfo, g_hOutputCtl, CTXT("分配内存出错!!!")
jmp l_exit
.endif
mov lpMem, eax
invoke ReadProcessMemory, ProcInfo.hProcess, dwImageBase, lpMem, dwSizeOfImage, 0
.if !eax
invoke wsprintf, addr buf, CTXT("读取进程 (%08lXh) 内存出错!!!"), ProcInfo.dwProcessId
invoke _OutputInfo, g_hOutputCtl, addr buf
jmp l_exit
.endif
invoke TerminateProcess, ProcInfo.hProcess, 0
invoke CloseHandle, ProcInfo.hThread
invoke CloseHandle, ProcInfo.hProcess
mov ProcInfo.hProcess, 0
;--------------------------------------------------------------------------------
;查找入口点
invoke SendMessage, g_hChkOEP, BM_GETCHECK, 0, 0
.if eax
invoke GetWindowText, g_hOEP, addr buf, 9
invoke htodw, addr buf
.else
invoke _GetOEP, lpMem, dwSizeOfImage
add eax, dwImageBase
.endif
.if eax==0
invoke _OutputInfo, g_hOutputCtl, CTXT("找不到入口点")
jmp l_exit
.endif
mov dwOEP, eax
invoke wsprintf, addr buf, CTXT("找到入口点: %08lXh"), eax
invoke _OutputInfo, g_hOutputCtl, addr buf
;--------------------------------------------------------------------------------
;创建调试进程
invoke CreateProcess, 0, addr szFile, 0, 0, 0, DEBUG_PROCESS + DEBUG_ONLY_THIS_PROCESS,
0, 0, addr StartupInfo, addr ProcInfo2
.if !eax
invoke _OutputInfo, g_hOutputCtl, CTXT("不能创建进程!!!")
jmp l_exit
.endif
.while TRUE
invoke WaitForDebugEvent, addr DbgEvent, INFINITE
.if DbgEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT
;下面这一行代码很重要,否则被调试进程不会完全退出
invoke ContinueDebugEvent, DbgEvent.dwProcessId, DbgEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED
.break
.elseif DbgEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT
.if DbgEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT
inc dwCountBP
.if dwCountBP==1 ;第一次中断时在原始入口点处设置断点
invoke _OutputInfo, g_hOutputCtl, CTXT("在原始入口点设置断点...")
mov int3, 0CCh
invoke ReadProcessMemory, ProcInfo2.hProcess, dwOrgOEP, addr org_code, 1, 0
invoke WriteProcessMemory, ProcInfo2.hProcess, dwOrgOEP, addr int3, 1, 0
.elseif dwCountBP==2 ;第二次中断,这次是中断在原始入口点,在 OEP 处设置硬件断点
invoke _OutputInfo, g_hOutputCtl, CTXT("到达原始入口点")
mov g_context.ContextFlags, CONTEXT_CONTROL
invoke GetThreadContext, ProcInfo2.hThread, addr g_context
dec g_context.regEip
invoke WriteProcessMemory, ProcInfo2.hProcess, dwOrgOEP, addr org_code, 1, 0
invoke SetThreadContext, ProcInfo2.hThread, addr g_context
mov g_context.ContextFlags, CONTEXT_DEBUG_REGISTERS
invoke GetThreadContext, ProcInfo2.hThread, addr g_context
m2m g_context.iDr0, dwOEP
mov g_context.iDr7, 1
invoke SetThreadContext, ProcInfo2.hThread, addr g_context
invoke wsprintf, addr buf, CTXT("在 OEP: %08lXh 处设置硬件断点..."), dwOEP
invoke _OutputInfo, g_hOutputCtl, addr buf
.endif
invoke ContinueDebugEvent, DbgEvent.dwProcessId, DbgEvent.dwThreadId, DBG_CONTINUE
.continue
.elseif DbgEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_SINGLE_STEP
;第三次中断,来到真正的入口点,抓取进程,然后终止进程
invoke wsprintf, addr buf, CTXT("中断在 OEP: %08lXh 处"), dwOEP
invoke _OutputInfo, g_hOutputCtl, addr buf
invoke _OutputInfo, g_hOutputCtl, CTXT("清除硬件断点...")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -