• 标 题:【标题:Tag&Rename 1.7 文章一 :跟踪,并且制作Loader。(适合初学者)】
  • 作 者:mcny@work
  • 时 间:2000-11-11 15:39:06
  • 链 接:http://bbs.pediy.com

【标题: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
          才是破解本软件最佳方法。
========================================================================================
本文作者:McNy@Work
日期     :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
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

---------------------------------第三部分完-----------------------------------------------

==========================================================================================
全文结束(这是我的处女作,有不对的地方,还望大家多多指正与包涵!)

  • 标 题:【文章一的小小补充(仅供初学者)】
  • 作 者:mcny@work
  • 时 间:2000-12-1 16:49:32

【文章一的小小补充(仅供初学者)】
========================================================================================
软件      :Tag&Rename 1.7

软件简介  :一个可以修改MP3 和 VQF 音乐文件中的TAG说明的程序。最新的1.8beta3版开始支持MP3
            最新的ID3v2,是一个很好用的编辑工具。

下载处    :软件主页: http://www.softpointer.com/tr.htm
          :由于该主页更新很快,1.7 与 1.7(buid3)版本请在我这里下载:
            http://www.freedrive.com/ASP/PostFolderShortcut.asp?fsc=15913190
            (找share\TagRename ,需有freedrive的免费帐号)
----------------------------------------------------------------------------------------
Tag&Rename v.1.7 build 3 (11/22/00):
  * fixed  sharing violation error under Win 2000 with 'Rename folder'
    function
  * added Portuguese translation
 
Tag&Rename v.1.7 build 2 (11/04/00):
  * minor bug in 'Rename files test' window fixed
  * added Slovene and Swiss-German translations

Tag&Rename v.1.7 (11/02/00):
  * improved scroll mouse support
  * supported languages: Brazilian Portuguese, Bulgarian, Czech, Dutch
    French, German, Greek, Hungarian, Italian, Russian
  * minor bugs fixed

========================================================================================
  【正文】
========================================================================================
由于在贴文章一的时候,TagRename1.7已经悄悄的发布了1.7(build2)。所以大家从该主页下载
的版本与我的不同。故,造成与该文章有所出入的地方。


这里以1.7(build3)为例子作一个小小的修正。其实,除了使用各个版本的Aspack、Asprotect加壳之外。
自1.4版以来它在保护上并没什么长进(虽然注册码是无望了)! 用十几个 F12 即可搞定,找到如下代码.
( 而版本1.7(11/02/00)是一个例外,一路F10 即可。) 所以TagRename是一个很好的入门级程序。


A)1.7(build3)中 添入注册码,按OK后。被TRW2000中断,按下14个F12 ,再F10就可见到如下特征代码:
    ... 
    MOV EAX,[EBP-08]    //某一个ret会返回到此。
    LEA EDX,[EBP-04]
    MOV EAX,[EBP-04]
    CALL XXXXXXXX      //处理、计算、比较注册码!!!注册码正确时,返回AL=1。 【<==我们进入此!!!】
    CMP AL,01        
    JZ ZZZZZZZZ        //若AL=1,则可以避开error对话框!
           


B)按F8进入 CALL XXXXXXXX 后的下面四十行以内,即可看到如下特征代码:
  ...
  ...
  ...
  CALL NEAR [ECX+50]  //比较"注册码生成串'和两百余个"正确的串"。若全部不匹配返回EAX=FFFFFFFF
                        //(内部会调用 Kernel32!CompareStringA + 0D)
  INC EAX            
  JZ 0456598          //EAX=0 时跳转。                                  【 <==我们改这里!!!】
  MOV BL,01            //若上一行不跳转,则注册码正确。
  CALL YYYYYYYY
  ..
  ..
  ..
  RET                  //去下面两个jmp的下一行
  ..
  ..
  RET                  // 真正的返回。返回 A) CALL XXXXXXXX 处的下一行



C)所以Loader要做以下调整
    目标程序名:TAGRENAME.EXE
    修改的地址:004556a4h         (h 代表十六进制数)
    所作修改  :7402 ==> 9090        (nop的代码是90)
    修改字节数:2             
    从004556a4h起的10个字节为:74,02,B3,01,8B,45,F8,E8,3C,D8

        [Loader.asm]
        CSiR_AppName  db 'TAGRENAME.EXE',0
        mcny          dd 004556a4h      ; 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,03ch,0d8h  ; if there not there, we have the wrong version??

        patch_data_1  db 90h,90h
        patch_size_1  dd 2
        patch_addr_1  dd 004556a4h
       

附:很有趣的是,TagRename 多个Asprotect的壳,皆无法用目前流行的CASPR0.952 与 RAD0.6 完全脱壳。
    有些版本脱壳后手工修正即可。另一些则只能手工脱壳了 8(
    真是怪哉!怪哉!

~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
笔者      :McNy@Work
网址      :http://mcny.yeah.net  或  http://mcny.iscool.net  (施工缓慢,请见谅。。。)
日期      :2000年12月01日
Email      :mcny_work@yahoo.com
            (邮件主题请以"WANTED:McNycn"开始,注意英文字母大小写,否则我将收不到喔!)
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
全文结束(若有疏漏,还望大家多多包涵与指正!)