欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

【标题:Tag&Rename 1.7 文章一 :跟踪,并且制作Loader。(适合初学者)】

【标题:Tag&Rename 1.7 文章一 :跟踪,并且制作Loader。(适合初学者)】

【标题:Tag&Rename 1.7 文章一 :跟踪,并且制作Loader。(适合初学者)】
========================================================================================
软件      :Tag&Rename 1.7
软件简介  :一个可以修改MP3 和 VQF 音乐文件中的TAG说明的程序。目前尚未支持MP3最新的ID3v2
            但是,仍然是一个很好用的编辑工具。
下载处    :软件主页: http://www.softpointer.com/tr.htm
          :版本1.7(若找不到)可以在我这里
            http://www.geocities.com/mcny_work/orgfile/2000/TagRename17.zip
            (888k bytes  不支持断点续传 )
注册方法  :注册码(与名字无关,而且是不可逆算法,无法计算出注册码)
反跟踪保护 :Asprotect 1.0 加壳
========================================================================================
破解难度        :易 (这里是指:找出关键跳转,改变它)
去反跟踪保护难度:易 (这里是指:使用Loader,有现成的代码嘛,不用自己写!
                      若要自动脱壳的话,有现成的脱壳机(SAC的,我还没用过,不知效果如何)。
                      若要手工脱壳的话,可以参考http://toye.yeah.net
                      '破解教学'上的相关文章,难度:中)
使用工具        :1) Trw2000 v1.22
                  2) TASM32 5.0(需要3个文件:import32.lib ,tasm32.exe, tlink32.exe)
目标文件        :TagRename.exe
关键            :找出关键跳转点,制作一个Loader来改变该跳转(原因:因为软件经过加壳,无
                  法直接修改目标文件)
----------------------------------------------------------------------------------------
【注1】 :看雪论坛中,有人曾告诉我:破解是破解,脱壳是脱壳,不能混为一谈。 觉得很有
          道理,所以这里就分成两个难度度量:破解、去反跟踪。
【注2】 :编译连接Loader时,本文没有使用'资源文件',所以制作出来Loader不会包含图标。有
          兴趣,你可以自己补上。
【注3】 :本文意在给予不曾制作Loader的朋友一个Loader的制作经验。并不是说,制作Loader
          才是破解本软件最佳方法。
========================================================================================
本文
日期     :2000年11月09日
Email    :mcny_work@yahoo.com
        (邮件主题请以"WANTED:McNycn"开始,注意英文字母大小写,否则我会收不到喔!)

                【目录】
§====================§
§第一部分:初步追踪                    §
§第二部分:进一步追踪,找到关键比较点    §
§第三部分:制作Loader,附:程序源代码    §
§====================§

-------------------------------【第一部分:初步追踪】-----------------------------------
    首先运行 Trw2000 ,用它载入TagRename.exe 。按下'Load'健后,我们来到trw2000的调试框中,
按F5,程序继续运行。然后,TagRename 会出现一个提示框告述你已经使用了几天,还叫你注册。选择
'Unlock',在Yourname中添入姓名,在Code中添入任意文本。(eg, Name: McNy@Work    Code:a )
暂时不要按下OK按钮。
    然后,按Ctrl+N, 来到trw2000调试框中。设置断点,键入:bpx hmemcpy  ,回车。(<--这可是
经典动作喔!)按F5,让程序继续运行。我们会回到windows 中,按下刚才没按下的OK键。
    程序又被中断,我们又来到trw2000调试框中。现在,我们不断的按F10 ,一直到Error对话框出
现(F10 是逐步跟踪)。其中一个ret处按下F10后会来到地址 00508B49。继续跟踪,当用F10越过
00508B76  call 004646EC 后,Error 框出现,告诉你注册码不对! 按OK ,会回到Trw2000调试框。
    很明显,00508B76 处的call 会显示error对话框。要如何避开它呢?我们向上找,发现00508B80
处的JZ有机会避开Error框,条件是AL=1。(当然,我们到这里时的AL<>1,因为注册码不对嘛!)
        
            ...
        ==>    017F:00508B49    MOV EAX,[EBP-08]        //某一个ret会返回到此。
        017F:00508B4C    LEA EDX,[EBP-04]
                017F:00508B4F    CALL 0408EBC
                017F:00508B54    MOV EAX,[EBP-04]
      **(A1)**  017F:00508B57    CALL 00456510          //处理、计算、比较注册码!!!
                                                        //注册码正确时,返回AL=1。
      **(A2)**  017F:00508B5C    CMP AL,01        
    ==>    017F:00508B5E    JZ 0508B80        //若AL=1,则可以避开error对话框!
                017F:00508B60    LEA ECX,[EBP-0C]
                017F:00508B63    MOV EAX,[00541A98]
                017F:00508B68    MOV EAX,[EAX]
                017F:00508B6A    MOV DX,01D9
                017F:00508B6E    CALL 0046DE40
                017F:00508B73    MOV EAX,[EBP-0C]
        ==>    017F:00508B76    CALL 004646EC          //会出现error对话框
                017F:00508B7B    JMP 00508C56
            ...

    聪明的你,一定会想到改变 00508B5C 的比较指令 或者 改变 00508B5E 的条转指令来达到
避开error对话框的目的。但是,这样做的话只对了一半!因为程序不止在一地方调用 call 00456510 。
(我当然是试过才知道嘛!)所以使 call 00456510 的返回结果必定 AL=01才是一劳永逸的方法。
    所以,我们也可以修改 00465610 处的代码,使之变成 mov al,01 。 ret。(置AL=1,并马上返回)
但我们不这样做,因为这样做已改变了整个Call的作用,可能会带来潜在的程序错误。我想对原始程
序用最少、最安全的修改来达到我们的目的。
    于是,我们本着这样的思路来进行追踪:是什么造成AL=1?原来是地址xxxxxxxx 处的 EBX=1 时。
哪又是什么造成 xxxxxxxx 时的EBX=1?原来是地址yyyyyyyy处的 EAX<>0 ,... 就这样,一直到比较
注册码的地点。
---------------------------------第一部分完-----------------------------------------------

-------------------------------【第二部分:进一步追踪,找到关键比较点】-------------------
    我们重新设置所有断点,而新断点设置在上述代码中有注明**(A1)**处,所call的地址。
即 bc * , 回车。bpx 00456510 ,回车 。 按下F5 。TagRename程序继续运行。
    按'Unlock'键,'OK'键。程序又被中断,我们来到调试框中,地址是我们刚才设置的断点处,即
00456510 。不断按F10一直到过了第一个RET (下面代码的 **(A4)** 处)。由于第二个RET 才是真
正的RET,所以我们知道地址004565BD处的EBX 决定了即将返回的EAX值(我们要使EAX=1)!
    
    于是我们把注意力转移到EBX。再往上面几行看看,发现00456598 处将1 赋值给BL。但是为什么
我们的是EBX=0 ? 这是因为 00456594 处的JZ 跳转成功!(下面代码的**(A3)** )
    很明显00456594就是我们要改的地方了。只要将 JZ 00456598 去掉即可(即,不管真正结果如
何,我们都令注册码正确(BL=1) )。键入 code on,回车。先用纸记下00456594处开始的10 Bytes
的代码(制作LOADER时会用到:即74 02 B3 01 8B 45 F8 E8 C8 C9)。
   
    现在,用两个nop取代00456594的JZ 00456598。我们键入a 456594,回车。nop,回车。nop,两
个回车。可以看见,00456594处的代码变成两个nop 了。
    让程序继续运行前,我们应该清除所有断点。故键入bc * ,回车。按下F5。TagRename程序继续
运行。程序出现Error框(我们的修改在下一次才生效)。
    按'Unlock'键,'OK'键。出现一个对话框感谢我们注册 8^)  。我们的追踪也到此结束了。选择
TagRename 程序中的HELP > ABOUT,出现的ABOUT对话框会显示 Register to: McNy@Work 。

            ...
        ==>    017F:00456510    PUSH EBP                //此为断点处,程序在这里暂停。
                017F:00456511    MOV EBP,ESP
            ...
            ...
                017F:0045655F    MOV EAX,ESI
                017F:00456561    CALL 00402F68
                017F:00456566    LEA EDX,[EBP-04]
                017F:00456569    LEA EAX,[EBP-18]
                017F:0045656C    CALL 00456460          //由输入S/N,产生"输入码生成串"的
                                                        //主要调用。
                017F:00456571    MOV DL,01
                017F:00456573    MOV EAX,[00410060]
                017F:0045657D    MOV [EBP-08],EAX
                017F:00456580    LEA EAX,[EBP-08]
                017F:00456583     CALL 00456404
                017F:00456588    MOV EDX,[EBP-04]
                017F:0045658B    MOV EAX,[EBP-08]
                017F:0045658E    MOV ECX,[EAX]
                017F:00456590    CALL NEAR [ECX+50]  //比较"注册码生成串'和两百余个
                                                    //"正确的串"。
                                                    //若全部不匹配返回EAX=FFFFFFFF
                                                    //(内部会调用 Kernel32!CompareStringA)
                017F:00456593    INC EAX            
      **(A3)**  017F:00456594    JZ 0456598              //EAX=0 时跳转。我们改这里!!!
        ==>    017F:00456598    MOV BL,01              //若上一行不跳转,则注册码正确。
                017F:0045659B    CALL 00402F68
                017F:004565A0    XOR EAX,EAX
                017F:004565A2     POP EDX
                017F:004565A3    POP ECX
                017F:004565A4    POP ECX
                017F:004565A5    MOV [FS:EAX],EDX
                017F:004565A8    PUSH DWORD 004565BD
                017F:004565AD    LEA EAX,[EBP-04]
                017F:004565B0    CALL 00403CEC
        ==>    017F:004565B5    RET                    //去017f:004565BD  !!!
                017F:004565B6    JMP 004036C8
                017F:004565BB    JMP SHORT 004565AD
      **(A4)**  017F:004565BD    MOV EAX,EBX            //哈!原来是将EBX赋值给EAX。
                017F:004565BF    POP ESI
                017F:004565C0    POP EBX
                017F:004565C1    POP ESP,EBP
                017F:004565C3    POP EBP
                017F:004565C4    RET                    //返回到**(A2)**处

---------------------------------第二部分完-----------------------------------------------

-------------------------------【第三部分:制作Loader】-----------------------------------
本文采用R!SC 的Loader源代码,并改变相应的地方:
(一)我们先整理由第一、二部分的跟踪所得的一些数据:
    目标程序名:TAGRENAME.EXE
    修改的地址:00456594h         (h 代表十六进制数)
    所作修改  :7402 ==> 9090        (nop的代码是90)
    修改字节数:2             
    从00456594起的10个字节为:74,02,B3,01,8B,45,F8,E8,C8,C9
(二)步骤:
        1)在TASM的目录中,建立一个文件名为loader.asm 的文本文件(.asm是文件扩展名)
        2)将下面两行 ;+++++++++++++ 之间的代码全部拷贝粘贴到loader.asm中,保存文件。
    
        3)将我们(一)中的所有资料填在loader.asm中**(B1)**处的相应位置。
        在**(B2)**处,填入延时,先假定1000 吧。若不能正常使用则在调整。
        (调整原则:Loader 可以载入TagRename,但程序依然没注册。 ==> 减少延时 (eg: 800)
                Loader 不能正常运行,出现ERROR框。          ==> 增加延时 (eg:1200)
         )    
    
        4)在DOS Prompt 中 ,进入TASM的目录中(笔者的目录为:e:\tasm5),依次键入以下
        两行命令。
        tasm32 /ml loader.asm                        (编译)
        tlink32 /Tpe /aa /c loader,loader,,e:\tasm5\import32.lib    (连接)
       
        5)成功的话,会在当前目录产生一个名为loader.exe的文件,将它拷贝到Tag&Rename的
        目录中,即可。运行Loader,看看能不能正常使用,不能则再次调整延时,重新编译。

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Requires Tasm 5.0 & import32.lib to compile
; tasm32 /ml loader.asm
; tlink32 /Tpe /aa /c loader,loader,, <path to> import32.lib
; replace <path to> with whatever...
.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 'Tag&Rename 1.7 (Loader),by McNy@Work ',0
CSiR_Error          db 'Error!!!',0
CSiR_Error1        db 'Something wrong!!...',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 'TAGRENAME.EXE',0          ; **(B1)**
mcny          dd 00456594h                  ; address to read data from for version checking
sizeof        dd 10                        ; in the new process
checkbytes    db 074h,002h,0b3h,001h,08bh  ; the bytes to check for
              db 045h,0f8h,0e8h,0c8h,0c9h  ; if there not there, we have the wrong version??
;-----
patch_data_1  db 90h,90h
patch_size_1  dd 2
patch_addr_1  dd 00456594h
.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    1000                            ; **(B2)**   
                                            ; Timeout (in milliseconds, -1 = infinate)
                                            ; 原作者为 LARGE-1
                                            ; 我的PC上可以用800到1500。你自己设一个数吧!
    push    dword ptr [CSiR_ProcessInfo]
    call    WaitForInputIdle
   
Check_Data:
    push    0                              ; BytesRead
    push    dword ptr [sizeof]              ; Length
    push    offset CSiR_RPBuffer            ; Destination (to read them to)
    push    dword ptr [mcny]                ; 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
    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
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
---------------------------------第三部分完-----------------------------------------------
==========================================================================================
全文结束(这是我的处女作,有不对的地方,还望大家多多指正与包涵!)

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功