• 标 题:使用loader方式破解 arm 1.01 (6千字)
  • 作 者:Fpc
  • 时 间:2001-4-16 19:26:08
  • 链 接:http://bbs.pediy.com

使用loader方式破解 arm 1.01
作者:Fpc
  arm1.01是近期程序保护方式的一个典型例子 (详情请见不久前的贴子):
  1、使用Aspack(或Asprotect)以及其它压缩软件为文件加壳;
  2、加密算法不可逆(昨天看了MD5的算法,应该就是这个),只有暴破一条路。只是现在我还不知道有没有可能通过逐渐逼近的方式得到注册码;
  3、脱壳比较困难,对我即如此(虽然Arm可以被Carspr脱壳)。
  这样我们就面对比较困难的选择:要么手动,要么等待解压软件。但这两者都是解决问题的正确途径。那么对菜鸟级选手来说,采用Loader方式就是另一种选择。
 
  以Arm为例,它的注册码计算过程至少被调用三次:启动时的检查、启动时对输入注册码的检查、启动后在‘关于’中输入注册码时的检查。显然在正常情况下,这些检查都是对同一个CALL的调用。因此要做的就是在外壳程序完成解压后、第一次对注册码的检查之前在内存中对这个CALL打补丁。这就是Loader的原理。
  本例的Loader 的原型在tKC Tutor #25,可能是由 R!SC首先公布出来的,我只做了微小的改动:
 
;-=-Larm101.asm-=-=-cut & paste me :)=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; based on original loader.exe by Hayras [tNO '98] used in
; Hayras's Neolite v1.22 memory patcher.
; (Loader is also a real mother!!!)
; This is slightly modifide by Fpc @2001.
;
; Special thanks to TNO for graciously allowing me to use this
; source on behalf of Hayras, who has now retired from the scene.
; Yes, Hayras's loader reversed by R!SC, then totally re-written
; & released to the public, so everyone can learn this shit :)
;
; Requires Tasm 5.0 & import32.lib to compile
; make a BatFile as following:
; mk.bat
; <your path>\tasm32 /ml %1.asm
; <your path>\tlink32 /Tpe /aa /c %1,%1,, <your path>\Lib\import32.lib
; [Eof]
; replace <your path> with whatever...
; (c)1999 R!SC (see what i do instead of cracking...duh) yey Prophecy!

.386P
Locals
jumps
.Model Flat ,StdCall
;Define the needed external functions and constants here.
Extrn      MessageBoxA:PROC
Extrn      WaitForInputIdle:PROC
Extrn      WriteProcessMemory:PROC
Extrn      ReadProcessMemory:PROC
Extrn      CreateProcessA:PROC
Extrn      CloseHandle:PROC
Extrn      ExitProcess:PROC
;-=-Normal data-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
.Data
CSiR_Tag            db ' PE LOADER & CRACKER---R!SC 1999 ',0
CSiR_Error          db 'Error!!!',0
CSiR_Error1        db 'Something fucked up...',0
OpenERR_txt        db 'CreateProcess Error :(',0
ReadERR_txt        db 'ReadProcessMemory Error :(',0
WriteERR_txt        db 'WriteProcessMemory Error :P',0
VersionERR_txt      db 'Incorrect Version of application :(',0
CSiR_ProcessInfo    dd 4 dup (0)        ;process handles
CSiR_StartupInfo    db 48h dup (0)      ;startup info for the process were opening
CSiR_RPBuffer      db 10h dup (0)      ;read buffer, for checking data
;-=-Patch datas-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
CSiR_AppName  db 'arm.exe',0
fuck          dd 495825h        ; address to read data from for version checking
sizeof        dd 10            ; in the new process
checkbytes    db 089h,045h,0f0h,0c7h,045h  ; the bytes to check for
              db 0f4h,01h,0h,0h,00h  ; if there not there, we have the wrong version??
patch_data_1  db 0c7h,045h,0f4h,01h,0h,0h,0h,08bh
          db 045h,0f4h,08bh,014h,085h,044h,060h,04bh,0h
          db 08bh,0c2h,089h,045h,0f0h,090h
patch_size_1  dd 23
patch_addr_1  dd 495825h
.Code
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Main:
    push    offset CSiR_Tag
    mov    dword ptr [CSiR_StartupInfo],44h ; (the size in bytes of the structure)
    push    offset CSiR_ProcessInfo          ; Typedef struct _PROCESS_INFORMATION
    push    offset CSiR_StartupInfo          ; Pointer to STARTUPINFO structure
    push    0
    push    0
    push    20h                              ; Creation flags
    push    0
    push    0
    push    0
    push    0
    push    offset CSiR_AppName              ; Pointer to name of executable mod
    call    CreateProcessA
    test    eax,eax
    jz      OpenERR
Wait4Depack:
    push    800                            ; Timeout (in milliseconds, -1 = infinate)
    push    dword ptr [CSiR_ProcessInfo]    ; Here we take 0.8s
    call    WaitForInputIdle
Check_Data:
    push    0                              ; BytesRead
    push    dword ptr [sizeof]              ; Length
    push    offset CSiR_RPBuffer            ; Destination (to read them to)
    push    dword ptr [fuck]                ; Source
    push    dword ptr [CSiR_ProcessInfo]    ; Process whose memory we are to read
    call    ReadProcessMemory
    test    eax,eax
    jz      ReadERR
    ;...
    ;int 03 ;-)
    cld
    lea    esi, CSiR_RPBuffer
    lea    edi, checkbytes
    mov    ecx, 10
    rep    cmpsb
;    nop
    jnz    VersionERR
    ;...
Patch_the_mother:
    push    0                              ; Pointer to byteswritten (i like null though)
    push    dword ptr [patch_size_1]        ; Length
    push    offset patch_data_1            ; Source
    push    dword ptr [patch_addr_1]        ; Destination
    push    dword ptr [CSiR_ProcessInfo]    ; Process whose memory we are to patch
    call    WriteProcessMemory              ; Call Kernel32!WriteProcessMenory
    test    eax,eax
    jz      WriteERR
Close_This_app:
    push    dword ptr [CSiR_ProcessInfo]
    call    CloseHandle
    push    dword ptr [CSiR_ProcessInfo+4]
    call    CloseHandle
Exit_Proc:
    Push LARGE-1
    Call ExitProcess
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
VersionERR:
    lea    eax, VersionERR_txt
    jmp    abort
ReadERR:
    lea    eax, ReadERR_txt
    jmp    abort
OpenERR:
    lea    eax, OpenERR_txt
    jmp    abort
WriteERR:
    lea    eax, WriteERR_txt
abort:
    push 0
    push offset CSiR_Error                  ; Title
    push eax                                ; Message
    push 0
    call MessageBoxA
    jmp Close_This_app
End Main
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  这个程序是有缺点的,即机器的速度如果过快或过慢,运行可能就要出错。自己的学艺实在不精。肯请哪位虾虾出手,在其中加入判断机器速度、根据这个速度来确定打补丁的时间。我这里用的800毫秒(0.8秒),在PII 300的条件下正常运行。
  最后大家要注意一点,Loader方式回避了对解压这一问题的处理,有点消极,算是没有办法的办法。软件的脱壳技术还是需要掌握的。