loader写法

 先分析这个CRACKME:

//机器码运算
004013B4  |.  E8 01080000    call    <jmp.&user32.GetDlgItemTextA>   
004013B9  |.  8D05 98334000  lea      eaxdword  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.wsprintfA>
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      esieax
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.wsprintfA>          

//对比结果
004010E8  |.  68 48334000    push    00403348                          ;  机器码运算后的字符串
004010ED  |.  68 F8324000    push    004032F8                          ;  注册码运算后的字符串
004010F2  |.  E8 F30A0000    call    <jmp.&kernel32.lstrcmpA>          ;  比较
004010F7  |.  0BC0           or       eaxeax
004010F9  |.  75 19          jnz     short 00401114

这个CRACKME虽然简单了点,但是讲的是一个原理。程序先将注册码运算后得到一个字符串,再将机器码运算后得到一个字符串,对比两个字符串,只要相等就注册成功了。
我们可以看出,004013BF中EAX指向的是机器码,00401B90中的EAX指向的就是暗码,得到暗码后我们只要根据注册码变形的那个逆运算就可以推出真正的注册码。
这次我们改用打开文件的方式,也加入了对话框窗口。详细代码如下:

.586
.model  flatstdcall  
option  casemap : none  
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
include comdlg32.inc
includelib comdlg32.lib 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
IDD_DLG1                 equ 1000
IDC_NAME                 equ 1001
IDC_CODE                 equ 1002
IDC_OK                   equ 1005
IDC_ABOUT                equ 1006
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
BREAK_POINT1    equ 004013BFh  ;第一个断点
BREAK_POINT2    equ 00401B90h  ;第二个断点
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DlgProc  proto :HWND,:UINT,:WPARAM,:LPARAM
GetKey   proto 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    .data 
   MsgboxText     db  '   test',0dh
               db  ' test',0
   MsgboxCaption  db  '关于',0
   MsgBoxText1     db  '请输入远程机器码!并打开crackme.exe程序。',0
   MsgBoxCaption1  db  '提示',0
   AppName  db  "crackme",0 
   int3     db 0cch
   oldcode  db 2  dup(?)
   value    db 8  dup(?)
   BUFFER   db 8  dup(?)
   oldbyte1  db 68h
   oldbyte2  db 50h
   szFormat  db  "%X",0
   ofn OPENFILENAME <> 
   FilterString  db  "Executable Files",0, "*.exe",0 
                 db  "All Files",0, "*.*",0,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 
    .data? 
   buffer  db 512  dup(?) 
   startinfo STARTUPINFO <> 
   pi PROCESS_INFORMATION <> 
   DBEvent DEBUG_EVENT <> 
   context CONTEXT <>
   uExitCode      dd ?
   hInstance     HINSTANCE ?
   hDlg          HINSTANCE ?  
   UserID         db 80  dup (?)
   Serial         db 80  dup (?)

    .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
   .if      eax==WM_CLOSE
        invoke  EndDialog,hWin,0
   .elseif  eax==WM_INITDIALOG
         push hWin
         pop  hDlg       
   .elseif  eax==WM_COMMAND
           mov  eax,wParam
              .if  eax==IDC_OK                
                 invoke  GetDlgItemText,hDlg,IDC_NAME, addr UserID, Sizeof UserID                                           
                    .if  eax==0
                      invoke  MessageBox,hDlg, addr MsgBoxText1, addr MsgBoxCaption1,MB_OK
                    .elseif  
                      invoke GetKey
                      invoke  SetDlgItemText,hDlg,IDC_CODE, addr value
                    .endif
              .elseif  eax==IDC_ABOUT
                 invoke  MessageBox,hDlg, addr MsgboxText, addr MsgboxCaption,MB_OK
              .endif            
   .else
     mov  eax, FALSE
     ret
   .endif
   mov  eax, TRUE
   ret
DlgProc  endp

GetKey  proc  
        pushad
;********************************************************************
; 打开文件
;******************************************************************** 
    mov ofn.lStructSize, sizeof ofn 
    mov ofn.lpstrFilter,  offset FilterString 
    mov ofn.lpstrFile,  offset buffer 
    mov ofn.nMaxFile,512 
    mov ofn.Flags, OFN_FILEMUSTEXIST  or OFN_PATHMUSTEXIST  or OFN_LONGNAMES  or OFN_EXPLORER  or OFN_HIDEREADONLY 
    invoke  GetOpenFileNameADDR ofn   
;********************************************************************
; 创建进程
;******************************************************************** 
    .if  eax== TRUE     
     invoke  GetStartupInfo, addr startinfo 
     invoke  CreateProcessaddr buffer, NULL, NULL, NULL,  FALSE,\
                      DEBUG_PROCESS  or DEBUG_ONLY_THIS_PROCESS, NULL, NULL,\
                       addr startinfo,  addr pi 
;********************************************************************
; 调试进程
;********************************************************************
.while  TRUE 
        invoke  WaitForDebugEventaddr DBEvent, INFINITE 
       .break  .if DBEvent.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT
;********************************************************************
; 如果进程开始,则将两个断点地址的代码改为INT3中断
;********************************************************************
        .if DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT
           invoke   WriteProcessMemory,pi.hProcess,BREAK_POINT1, addr int3,1,NULL        ;插入INT3
           invoke   WriteProcessMemory,pi.hProcess,BREAK_POINT2, addr int3,1,NULL        ;插入INT3
;********************************************************************
; 中断触发的异常事件,并进入安全模式读写状态
;********************************************************************                             
        .elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT
            .if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT 
              mov context.ContextFlags, CONTEXT_FULL 
              invoke  GetThreadContext, pi.hThread,  addr context 
;********************************************************************
; 如果在机器码处中断,则恢复原来的代码,并写入新的机器码
;********************************************************************              
              .if     context.regEip == BREAK_POINT1+1
               dec     context.regEip
               invoke   WriteProcessMemory,pi.hProcess,BREAK_POINT1, addr oldbyte1,1,NULL     ;恢复代码
               mov  eax,context.regEax                                                       ;机器码在EAX中
               invoke   WriteProcessMemory,pi.hProcess, eax, addr UserID,0ch,NULL              ;读入22位机器码
               invoke   SetThreadContext,pi.hThread,  addr context                            ;设置生效
               ;invoke ReadProcessMemory,pi.hProcess,context.regEax,addr BUFFER,0ch,NULL   ;用于检测修改的机器码是否已经生效
               ;invoke  MessageBox,0, addr BUFFER,addr AppName, MB_OK+MB_ICONINFORMATION       
;********************************************************************
; 如果在注册码处中断,则恢复原来的代码,并读出注册码
;********************************************************************                                                     
             .elseif  context.regEip == BREAK_POINT2+1
               dec     context.regEip
               invoke  WriteProcessMemory,pi.hProcess,BREAK_POINT2, addr oldbyte2,1,NULL      ;恢复代码             
;********************************************************************
; 逆推注册码
;********************************************************************   
               MOV  EAX,context.regEax                                                       ;暗码在EAX中
               ADD  EAX,0A98AC7h
               XOR  EAX,4ECAEDDh
               SUB  EAX,0FFF379A6h 
               invoke  wsprintf, addr value, addr szFormat, eax                 
               invoke  SetDlgItemText,hDlg,IDC_CODE, addr value                               ;输出到注册码框
               invoke  SetThreadContext,pi.hThread,  addr context
               invoke  TerminateProcess,pi.hProcess,uExitCode                                ;强行退出 
              .break            
             .endif           
           .endif 
        .endif 
        invoke  ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId,DBG_CONTINUE 
.endw 
;********************************************************************
; 结束线程
;******************************************************************** 
           invoke   CloseHandle,pi.hProcess
           invoke   CloseHandle,pi.hThread
.endif       
     popad
     ret 
GetKey  endp
end start 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值