szUser32 db 'user32',0
szMessageBox db 'MessageBoxA',0
;定义指向对话框函数的指针变量及常量的定义
_GetModuleHandle _ApiGetModuleHandle ?
_GlobalAlloc _ApiGlobalAlloc ?
_MultiByteToWideChar _ApiMultiByteToWideChar ?
_DialogBoxIndirectParam _ApiDialogBoxIndirectParam ?
_GlobalFree _ApiGlobalFree ?
_EndDialog _ApiEndDialog ?
_GetDlgItemText _ApiGetDlgItemText ?
_SetWindowText _ApiSetWindowText ?
_SendDlgItemMessage _ApiSendDlgItemMessage ?
szGetModuleHandle db 'GetModuleHandleA',0
szGlobalAlloc db 'GlobalAlloc',0
szMultiByteToWideChar db 'MultiByteToWideChar',0
szDialogBoxIndirectParam db 'DialogBoxIndirectParamA',0
szGlobalFree db 'GlobalFree',0
szEndDialog db 'EndDialog',0
szGetDlgItemText db 'GetDlgItemTextA',0
szSetWindowText db 'SetWindowTextA',0
szSendDlgItemMessage db 'SendDlgItemMessageA',0
APPEND_PASSWD_CODE equ this byte
OldPswdText db 30 dup(0) ;加密后留存的口令
PswdText db 30 dup(0) ;对话框输入的验证口令
TitleName db 'Enter PassWord',0
ButtonName db '确定',0
FontName db 'Times New Roman',0
ID_PSWD equ 101
ID_EXIT equ 202
ID_CAPTION equ 11011
szCaption db "问题提示:",0
TitleText db "请输入口令:",0
ErrPasswd db "口令错误!",0
hInstance1 dd ?
@strlen11 dd ?
@strlen22 dd ?
;取字符串长度过程
strlen proc _dwarg
local @count
mov @count,0
pushad
cld
mov esi,_dwarg
@@: lodsb
inc @count
cmp al,0
jz exit
jmp @b
exit:
popad
mov eax,@count
ret
strlen endp
;口令核对过程
ChkEnterpswd proc
pushad
call @f
@@:
pop ebx
sub ebx,offset @b
lea eax,[ebx+PswdText]
invoke strlen,eax
mov [ebx+@strlen11],eax
lea eax,[ebx+OldPswdText]
invoke strlen,eax
mov [ebx+@strlen22],eax
mov ecx,[ebx+@strlen11]
mov eax,[ebx+@strlen22]
.if ecx < eax
xchg eax,ecx
.endif
lea esi,[ebx+OldPswdText]
lea edi,[ebx+PswdText]
cld
repe cmpsb
.if ZERO?
popad
mov eax,TRUE
ret
.else
popad
mov eax,FALSE
ret
.endif
ChkEnterpswd endp
;对话框过程
DlgProc proc hWnd:dword,uMsg:dword,wParam:dword,lParam:dword
call @f
@@:
pop ebx
sub ebx,offset @b
.if uMsg==WM_COMMAND
mov eax,wParam
.if ax==ID_PSWD
lea edx,[ebx+PswdText]
invoke [ebx+_GetDlgItemText],hWnd,ID_PSWD,edx,30
.elseif ax==ID_EXIT
invoke [ebx+_EndDialog],hWnd,NULL
.endif
.elseif uMsg==WM_INITDIALOG
lea ecx,[ebx+TitleText]
invoke [ebx+_SetWindowText],hWnd,ecx
invoke [ebx+_SendDlgItemMessage],hWnd,ID_PSWD,EM_LIMITTEXT,18,NULL
invoke [ebx+_SendDlgItemMessage],hWnd,ID_PSWD,EM_SETPASSWORDCHAR,42,NULL
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DlgProc endp
;口令加密代码的入口
_NewEntry:
;重定位
call @F
@@:
pop ebx
sub ebx,offset @B
invoke _GetKernelBase,[esp] ;获取Kernel32.dll基地址
mov [ebx+hDllKernel32],eax
lea eax,[ebx+szGetProcAddress] ;获取GetProcAddress入口地址
invoke _GetApi,[ebx+hDllKernel32],eax
mov [ebx+_GetProcAddress],eax
lea eax,[ebx+szLoadLibrary] ;获取LoadLibrary入口地址
invoke [ebx+_GetProcAddress],[ebx+hDllKernel32],eax
mov [ebx+_LoadLibrary],eax
lea eax,[ebx+szUser32] ;获取User32.dll基地址
invoke [ebx+_LoadLibrary],eax
mov [ebx+hDllUser32],eax
lea eax,[ebx+szGlobalAlloc] ;获取GlobalAlloc入口地址
invoke [ebx+_GetProcAddress],[ebx+hDllKernel32],eax
mov [ebx+_GlobalAlloc],eax
lea eax,[ebx+szGetModuleHandle] ;获取GetModuleHandle入口地址
invoke [ebx+_GetProcAddress],[ebx+hDllKernel32],eax
mov [ebx+_GetModuleHandle],eax
;获取MultiByteToWideChar入口地
lea eax,[ebx+szMultiByteToWideChar]
invoke [ebx+_GetProcAddress],[ebx+hDllKernel32],eax
mov [ebx+_MultiByteToWideChar],eax
lea eax,[ebx+szGlobalFree] ;获取GlobalFree入口地址
invoke [ebx+_GetProcAddress],[ebx+hDllKernel32],eax
mov [ebx+_GlobalFree],eax
;获取DialogBoxIndirectParam入口地址
lea eax,[ebx+szDialogBoxIndirectParam]
invoke [ebx+_GetProcAddress],[ebx+hDllUser32],eax
mov [ebx+_DialogBoxIndirectParam],eax
lea eax,[ebx+szEndDialog] ;获取EndDialog入口地址
invoke [ebx+_GetProcAddress],[ebx+hDllUser32],eax
mov [ebx+_EndDialog],eax
lea eax,[ebx+szGetDlgItemText] ;获取GetDlgItemText入口地址
invoke [ebx+_GetProcAddress],[ebx+hDllUser32],eax
mov [ebx+_GetDlgItemText],eax
lea eax,[ebx+szSetWindowText] ;获取SetWindowText入口地址
invoke [ebx+_GetProcAddress],[ebx+hDllUser32],eax
mov [ebx+_SetWindowText],eax
lea eax,[ebx+szSendDlgItemMessage] ;获取SendDlgItemMessage入口地址
invoke [ebx+_GetProcAddress],[ebx+hDllUser32],eax
mov [ebx+_SendDlgItemMessage],eax
lea eax,[ebx+szMessageBox] ;获取MessageBox入口地址
invoke [ebx+_GetProcAddress],[ebx+hDllUser32],eax
mov [ebx+_MessageBox],eax
pushad
invoke [ebx+_GetModuleHandle],NULL ;获取本模块的句柄
mov [ebx+hInstance1],eax
;对话框模板
;申请长度为4K,用0初始化,地址固定的内存块,用于建立对话框模板。
invoke [ebx+_GlobalAlloc],GMEM_FIXED or GMEM_ZEROINIT,1024*4
mov esi,eax
mov edi,eax
mov dword ptr [edi],DS_SETFONT or WS_SYSMENU or WS_OVERLAPPED ;对话框样式
mov word ptr [edi+8],2 ;控件数目
mov word ptr [edi+10],200
mov word ptr [edi+12],180 ;对话框的屏幕坐标(200,180)
mov word ptr [edi+14],110
mov word ptr [edi+16],60 ;对话框的大小110×60
add edi,22 ;菜单2字节、CLASS 2字节,共22字节
lea edx,[ebx+TitleName]
invoke strlen,edx
mov ecx,eax
push ecx
invoke [ebx+_MultiByteToWideChar],CP_ACP,MB_PRECOMPOSED,edx,ID_CAPTION,edi,eax
pop ecx
mov eax,ecx
shl eax,1
add edi,eax
mov word ptr [edi],9 ;字体点阵大小
add edi,2
lea edx,[ebx+FontName]
invoke strlen,edx
mov ecx,eax
push ecx
invoke [ebx+_MultiByteToWideChar],CP_ACP,MB_PRECOMPOSED,edx,-1,edi,eax
pop ecx
mov eax,ecx
shl eax,1
add edi,eax
add edi,3
shr edi,2
shl edi,2 ;起始地址双字对齐
;按钮控件
mov dword ptr [edi],WS_VISIBLE or WS_CHILD ;按钮样式
mov word ptr [edi+8],30
mov word ptr [edi+10],27 ;按钮在对话框中的坐标(30,27)
mov word ptr [edi+12],40
mov word ptr [edi+14],12 ;按钮的大小40×12
mov word ptr [edi+16],ID_EXIT ;按钮标识
mov word ptr [edi+18],0ffffh
mov word ptr [edi+20],0080h ;序数值0080h代表Button类
add edi,22
lea edx,[ebx+ButtonName]
invoke strlen,edx
mov ecx,eax
push ecx
invoke [ebx+_MultiByteToWideChar],CP_ACP,MB_PRECOMPOSED,edx,-1,edi,eax
pop ecx
mov eax,ecx
shl eax,1
add edi,eax
add edi,3
shr edi,2
shl edi,2 ;起始地址双字对齐
;编辑控件
mov dword ptr [edi],WS_VISIBLE or WS_CHILD or WS_TABSTOP or WS_BORDER ;编辑框样式
mov word ptr [edi+8],13
mov word ptr [edi+10],10 ;编辑框在对话框中的坐标(13×10)
mov word ptr [edi+12],80
mov word ptr [edi+14],12 ;编辑框的大小80×12
mov word ptr [edi+16],ID_PSWD ;编辑框标识
mov word ptr [edi+18],0ffffh
mov word ptr [edi+20],0081h ;序数值0081h代表Edit类
add edi,22
lea edx,[ebx+PswdText]
invoke strlen,edx
mov ecx,eax
push ecx
invoke [ebx+_MultiByteToWideChar],CP_ACP,MB_PRECOMPOSED,edx,-1,edi,eax
pop ecx
mov eax,ecx
shl eax,1
add edi,eax
add edi,3
shr edi,2
shl edi,2
lea ecx,[ebx + DlgProc]
;创建模态对话框
invoke [ebx + _DialogBoxIndirectParam],[ebx+hInstance1],esi,NULL,ecx,NULL
;对话框关闭后释放申请的内存块
invoke [ebx + _GlobalFree],esi
popad
invoke ChkEnterpswd ;校对用户输入的口令的正确性
.if !eax ;口令错误,则退出。
lea ecx,[ebx+ErrPasswd]
lea eax,[ebx+szCaption]
invoke [ebx+_MessageBox],NULL,ecx,eax,MB_OK
ret
.endif
;口令正确,执行原来的目标PE文件
db 0e9h ;0e9h是jmp xxxxxxxx的机器码
RetOldEntry:
dd ? ;用来填写返回到目标PE文件的入口地址
APPEND_CODE_END equ this byte
三、结语
本文在Windows XP中文版下对多个PE文件进行测试,效果良好。还有可以改进的地方,如对输入的口令进行加密,增加防静态分析和反动态跟踪的功能,使加密软件更加安全可靠。另外,有兴趣的读者可以在此加密原理的基础上,开发出对应的解密程序(或防病毒免疫程序),以更加方便实用。
|