使用loader方式破解 arm 1.01 (6千字)

看雪資料發表於2001-04-16

使用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方式迴避了對解壓這一問題的處理,有點消極,算是沒有辦法的辦法。軟體的脫殼技術還是需要掌握的。

相關文章