| 
				 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文件进行测试,效果良好。还有可以改进的地方,如对输入的口令进行加密,增加防静态分析和反动态跟踪的功能,使加密软件更加安全可靠。另外,有兴趣的读者可以在此加密原理的基础上,开发出对应的解密程序(或防病毒免疫程序),以更加方便实用。 
  			
				 |