加壳工具:利用调试积存器为加壳软件Software打补丁

上篇写了通过补丁方式利用软件Software本身算法模块做出注册机例子但是都是针对无壳情况这篇来讲下通过硬件断点利用同样原理对加壳软件Software打补丁
    有关调试寄存器DRx作用可以查Intel手册,加密软件Software技术内幕也有提及到.其中Dr0-Dr3 4个调试寄存器是存放中断地址用于设置硬件断点Dr4、Dr5英特尔保留使用功能至少现在没什么用Dr6、Dr7这两个寄存器作用是用来记录Dr0-Dr3中下断地址属性如下硬件断点读还是写或者是执行;是对字节还是对字或者是双字
    我们还是以上次那个CRACKME作为例子我对它加了个简单ASPACK压缩壳
00405001 >  60              PUSHAD                                   ; 壳入口
00405002    E8 03000000     CALL crackme.0040500A
00405007  - E9 EB045D45     JMP 459D54F7
0040500C    55              PUSH EBP
0040500D    C3              RETN
...
//机器码运算
004013B4  |.  E8 01080000   call    <jmp.&user32.GetDlgItemTextA>   
004013B9  |.  8D05 98334000 lea     eax, dword ptr [403398]          ;  压入机器码
004013BF  |?  68 98334000   push    00403398                         ;  EAX中放着机器码
...
00401B90  |.  50            push    eax                              ;  EAX中就是暗码
00401B91  |?  68 7E324000   push    0040327E                         ;  转串   
00401B96  |?  68 48334000   push    00403348                        
00401B9B  |?  E8 08000000   call    <jmp.&user32.wsprfA>
00401BA0  |.  83C4 0C       add     esp, 0C
...
//注册码变形
0040131E  |.  E8 97080000   call    <jmp.&user32.GetDlgItemTextA>    ;  取注册码
00401323  |.  6A 08         push    8
00401325  |.  68 A8324000   push    004032A8
0040132A  |.  E8 B4FEFFFF   call    004011E3                         ;  转16进制
0040132F  |.  8BF0          mov     esi, eax
00401331  |.  81C6 A679F3FF add     esi, FFF379A6                    ;  加FFF379A6h
00401337  |.  81F6 DDAEEC04 xor     esi, 4ECAEDD                     ;  异或4ECAEDDh
0040133D  |.  81EE C78AA900 sub     esi, 0A98AC7                     ;  减0A98AC7h
00401343  |.  56            push    esi                              ;  结果
00401344  |.  68 7E324000   push    0040327E                         ;  转
00401349  |.  68 F8324000   push    004032F8                         
0040134E  |.  E8 55080000   call    <jmp.&user32.wsprfA>          
...
//对比结果
004010E8  |.  68 48334000   push    00403348                         ;  机器码运算后
004010ED  |.  68 F8324000   push    004032F8                         ;  注册码运算后
004010F2  |.  E8 F30A0000   call    <jmp.&kernel32.lstrcmpA>         ;  比较
004010F7  |.  0BC0          or      eax, eax
004010F9  |.  75 19         jnz      00401114
    假如以上次思路方法对004013BF和00401B90处下INT3断点当外壳把代码解密后所修改0CCh字节就会被解密后代码覆盖将导致3断点不起作用所以我们改下硬件断点
我们先让停在原始入口处再在004013BF和00401B90处下硬件断点断下后就可以为所欲为了...详细代码如下:
.586
.model flat, stdcall  
option map :none  
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 windows.inc
 kernel32.inc
 user32.inc
 Comctl32.inc
 comdlg32.inc
 macros.inc
 masm32.inc

lib kernel32.lib
lib user32.lib
lib Comctl32.lib
lib comdlg32.lib
lib masm32.lib

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
IDD_DLG1                equ 1000
IDC_NAME                equ 1001
IDC_CODE                equ 1002
IDC_OK                  equ 1005
IDC_ABOUT               equ 1006
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
dwOrgOEP       equ 00405001h ;原始入口
BREAK_POINT1   equ 004013BFh ;第个断点
BREAK_POINT2   equ 00401B90h ;第 2个断点
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DlgProc proto :HWND,:UINT,:WPARAM,:LPARAM
GetKey  proto 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.CONST
DR0_ENABLED              EQU 000000001b
LOCAL_EXACT_BPM_ENABLED  EQU 100000000b

.data
MsgboxText    db '    -=Author: langxang=-',0dh
              db ' -=Email:[email protected]=-',0
MsgboxCaption db '有关',0
FileName      db 'crackme.exe',0
3          db 0cch   
value         db 8 dup(?)
buffer        db 8 dup(?)
old       db 8 dup(?)  
szFormat      db "%X",0
dwCountSS     dd 0
dwCountBP     dd 0
ProcessInfo   db "File Handle: %lx ",0dh,0Ah 
              db "Process Handle: %lx",0Dh,0Ah 
              db "Thread  Handle: %lx",0Dh,0Ah 
              db "Image   Base: %lx",0Dh,0Ah 
              db "Start   Address: %lx",0 
Startup       STARTUPINFO <>
processinfo   PROCESS_INFORMATION <>  

.data?
UserID        db 80 dup (?)
Serial        db 80 dup (?)
uExitCode     dd ?
hInstance     HINSTANCE ?
hDlg          HINSTANCE ? 
startinfo     STARTUPINFO <> 
pi            PROCESS_INFORMATION <> 
DBEvent       DEBUG_EVENT <> 
context       CONTEXT <>

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
start:
  invoke GetModuleHandle,NULL
       mov hInstance,eax
  invoke DialogBoxParam,hInstance,IDD_DLG1,NULL,addr DlgProc,NULL
  invoke ExitProcess,0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
        mov eax,uMsg
  .     eaxWM_CLOSE
       invoke EndDialog,hWin,0
  . eaxWM_INITDIALOG
       push hWin
       pop  hDlg     
  . eaxWM_COMMAND
          mov eax,wParam
             . eaxIDC_OK                
                invoke GetDlgItemText,hDlg,IDC_NAME,addr UserID,Sizeof UserID                                                        
                   . eax0
                     invoke MessageBox,hDlg,CTXT("请输入远程机器码"),CTXT("提示!"),MB_OK
                   .  
                     invoke GetKey                     
                   .end
             . eaxIDC_ABOUT
                invoke MessageBox,hDlg,addr MsgboxText,addr MsgboxCaption,MB_OK
             .end            
  .
    mov eax,FALSE
    ret
  .end
  mov eax,TRUE
  ret
DlgProc endp

GetKey proc  
       pushad
;********************************************************************
; 创建进程
;********************************************************************        
       invoke CreateProcess, addr FileName, NULL, NULL, NULL, FALSE, DEBUG_PROCESS or DEBUG_ONLY_THIS_PROCESS, NULL, NULL, addr startinfo, addr pi 
       .    !eax
        invoke MessageBox,hDlg,CTXT("不能创建进程"),CTXT("!"),MB_OK
        invoke ExitProcess,NULL
       .end
        xor  eax,eax
  mov  dwCountBP, eax
  mov  dwCountSS, eax
;********************************************************************
; 调试进程进入循环调试
;********************************************************************
.while TRUE  
         invoke WaitForDebugEvent, addr DBEvent, INFINITE              
. DBEvent.dwDebugEventCodeEXIT_PROCESS_DEBUG_EVENT 
         invoke MessageBox, 0, CTXT("退出进程..."), CTXT("提示!"), MB_OK+MB_ICONINFORMATION 
         . 
;********************************************************************
; 异常中断
;********************************************************************   
. DBEvent.dwDebugEventCodeEXCEPTION_DEBUG_EVENT   
         . DBEvent.u.Exception.pExceptionRecord.ExceptionCodeEXCEPTION_BREAKPOINT                  
;********************************************************************
; 第次中断时在原始入口点处设置断点
;********************************************************************  
              inc     dwCountBP
                  . dwCountBP
                invoke  ReadProcessMemory, pi.hProcess, dwOrgOEP, addr old, 1, 0   ;在dwOrgOEP中读出个字节
                      invoke  WriteProcessMemory, pi.hProcess, dwOrgOEP, addr 3, 1, 0     ;写入INT3断点                 
;********************************************************************
; 第 2次中断中断在起先设置原始入口点恢复代码在机器码处设置硬件断点
;********************************************************************  
                  . dwCountBP2                       
                       mov  context.ContextFlags, CONTEXT_CONTROL
                       invoke  GetThreadContext, pi.hThread, addr context
                       dec  context.regEip
                       invoke  WriteProcessMemory, pi.hProcess, dwOrgOEP, addr old, 1, 0  ;恢复入口代码
                       invoke  SetThreadContext, pi.hThread, addr context
                       mov     context.ContextFlags, CONTEXT_DEBUG_REGISTERS
                       invoke  GetThreadContext, pi.hThread, addr context
                       mov    context.iDr0, BREAK_POINT1                                       ;设置硬件断点      
                       mov    context.iDr7, LOCAL_EXACT_BPM_ENABLED + DR0_ENABLED
                       invoke  SetThreadContext, pi.hThread, addr context                                       
                  .end
                       invoke  ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE
                       .continue               
          . DBEvent.u.Exception.pExceptionRecord.ExceptionCodeEXCEPTION_SINGLE_STEP    ;单步运行模式     
;********************************************************************
; 第 3次中断中断在机器码处清除断点在注册码处设置硬件断点
;******************************************************************** 
             inc    dwCountSS                  
        .IF dwCountSS  1
                       mov     context.ContextFlags, CONTEXT_FULL
                       invoke  GetThreadContext, pi.hThread, addr context
                       mov eax,context.regEax                                                      ;机器码在EAX中
                       invoke  WriteProcessMemory,pi.hProcess,eax,addr UserID, UserID,NULL   ;写入机器码
                       invoke  SetThreadContext, pi.hThread, addr context
                     ; invoke ReadProcessMemory,pi.hProcess,context.regEax,addr buffer,0ch,NULL    ;用于检测修改机器码是否已经生效
                     ; invoke  MessageBox,0, addr buffer,CTXT("输入新机器码为:"), MB_OK+MB_ICONINFORMATION   
                       mov     context.ContextFlags, CONTEXT_DEBUG_REGISTERS
                       invoke  GetThreadContext, pi.hThread, addr context
                       mov     context.iDr0, BREAK_POINT2
                       mov     context.iDr7, LOCAL_EXACT_BPM_ENABLED + DR0_ENABLED
                       invoke  SetThreadContext, pi.hThread, addr context                          
                       invoke  ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE
                      .continue                     
;********************************************************************
; 第 4次中断中断在注册码处读出注册码清除硬件断点恢复线程
;********************************************************************               
                 . dwCountSS  2
                       mov     context.ContextFlags, CONTEXT_FULL
                       invoke  GetThreadContext, pi.hThread, addr context
                       mov context.ContextFlags, CONTEXT_FULL
                       mov EAX,context.regEax                                                    ;暗码在EAX中
                       add EAX,0A98AC7h
                       xor EAX,4ECAEDDh
                       sub EAX,0FFF379A6h 
                      invoke wsprf,addr value,addr szFormat,eax   
                      invoke SetDlgItemText,hDlg,IDC_CODE,addr value                              
                      mov     context.iDr0, 0
                      mov     context.iDr7, 0  
                      invoke  SetThreadContext,pi.hThread, addr context    
                      invoke TerminateProcess,pi.hProcess,uExitCode                               ;强行退出 
                      .                    
                 .end
             invoke  ContinueDebugEvent, DBEvent.dwProcessId,DBEvent.dwThreadId, DBG_CONTINUE
         .end
.end
   invoke  ContinueDebugEvent, DBEvent.dwProcessId,DBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED
.endw
;********************************************************************
; 结束线程
;******************************************************************** 
        invoke  CloseHandle, pi.hThread
        invoke  CloseHandle, pi.hProcess
       
    popad
    ret 
GetKey endp
end start


  • 篇文章: Dll Show 4.7 汉化版注册算法

  • 篇文章: 脚本后门深入--图片中后门
  • Tags:  灰鸽子加壳 加壳免杀 加壳软件 加壳工具

    延伸阅读

    最新评论

    发表评论