【标题: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
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
---------------------------------第三部分完-----------------------------------------------
==========================================================================================
全文结束(这是我的处女作,有不对的地方,还望大家多多指正与包涵!)
- 标 题:【标题:Tag&Rename 1.7 文章一 :跟踪,并且制作Loader。(适合初学者)】
- 作 者:mcny@work
- 时 间:2000-11-11 15:39:06
- 链 接:http://bbs.pediy.com