题目:“摸着石头过河法”轻松获取LeapFtp2.7.2 版本注册码(2006元旦向各位看雪论坛大侠献礼)
软件名称:LeapFTP 2.72
文件大小:1018KB
适用平台:Win9x/Me/NT/2000
软件简介:功能强大,媲美Bullet Proof FTP的FTP软件。跟Netscape相仿的书签形式,连线更加方便。下载与上传文件支持续传。可下载或上传整个目录,亦可直接删除整个目录。可让你编列顺序一次下载或上传同一站台中不同目录下的文件。浏览网页时若在文件连结上按鼠标右键选“复制捷径”便会自动下载该文件。具有不会因闲置过久而被站台踢出的功能。可直接编辑远端Server上的文件。可设定文件传送完毕自动中断Modem连接。
破解时间:2005年12月28日
工具:只用一个法宝TRW足矣!当然也需要FI*_^
破解目的:了解注册码计算方法,找到注册码,可以写出注册机,不赞成暴力。
引子:今天闲来无事,在学习看雪精华III,偶尔瞥到LeapFtp2.7破解教程,我想起在我的《电脑报2001合订本》有这个软件,版本2.7.2,看起来细微的差别,我在没有参考精华III里面的文章的前提下,自己独立完成属于我自己的破解教程。等我写完了自己的教程然后再去看那几篇文章,以便对比各自的优缺点,这也是一种积极的学习方法。看到一些教程不要盲目的去亦步亦趋,完全可以先自己尝试做一下,如果没有搞明白再去参考那些大侠的教程,这样比较有针对性。我现在刚刚入门2个月,已经是10几篇菜鸟教程了,当然都比较浅显,大侠莫要取笑!我觉得如果自己破解了一个小东西,如果不写出来觉得心里不塌实。随着破解的深入,写的文章多了,自然水平就提高了。切听如下分解:
首先用FI查看是否带“甲克”,结果比较幸运,没有带壳。下面就顺利了。首先运行LeapFtp2.7.2,点击Help菜单,单击"Enter Registration Data",在弹出的对话框内输入用户名和注册码,这里注意注册码的格式为: mmmx-nnyn-pqpp-zzzz,其中m,n,p为大写字符,x,y,q为数字。(你也许会问“你咋知道的?”,回答我跟踪了一遍)。我输入的用户名bigpig,注册码AAA8-BB8B-C8CC-DDDD,Ctrl+N唤出TRW,下pbx hmemcpy命令,F5退出,按OK按钮,拦下,按F10数次来到如下代码处。(有人问到底到哪里才合适呢?你看到代码后面不远处不存在RET这样的指令,就说明已经到了程序中心来了。)
0167:0048742A 8B45F8 MOV EAX,[EBP-08]
0167:0048742D 8D55FC LEA EDX,[EBP-04] //在这里d eax 看到输入的假注册码
0167:00487430 E87B16F8FF CALL 00408AB0 //该CALL检查两头是否带有空格,如果有则错误。
0167:00487435 80BBF402000000 CMP BYTE [EBX+02F4],00
0167:0048743C 740E JZ 0048744C //如果注册码两头没有空格,自然不会跳走。
0167:0048743E 8B55FC MOV EDX,[EBP-04]
0167:00487441 8BC3 MOV EAX,EBX
0167:00487443 E888030000 CALL 004877D0 //这个CALL是重点,F8跟入研究,注册算法就在这里啦。见后面代码分析。
0167:00487448 84C0 TEST AL,AL
0167:0048744A 7526 JNZ 00487472 //通往光明之路,必须跳走。
0167:0048744C 8B83F0020000 MOV EAX,[EBX+02F0]
0167:00487452 50 PUSH EAX
0167:00487453 8D55F4 LEA EDX,[EBP-0C]
0167:00487456 8B83D0020000 MOV EAX,[EBX+02D0]
0167:0048745C E867C5FAFF CALL 004339C8
0167:00487461 8B55F4 MOV EDX,[EBP-0C]
0167:00487464 8B4DFC MOV ECX,[EBP-04]
0167:00487467 8BC3 MOV EAX,EBX
0167:00487469 E8BA010000 CALL 00487628
0167:0048746E 84C0 TEST AL,AL
0167:00487470 7462 JZ 004874D4 //如果程序在这里就跳转则OVER,所以不可以跳。
0167:00487472 8D55F0 LEA EDX,[EBP-10] //下面到4874D2都是在注册成功后对注册表进行写入键值的。
0167:00487475 8B83E4020000 MOV EAX,[EBX+02E4]
0167:0048747B E848C5FAFF CALL 004339C8
*
*略去10来行代码
*
0167:004874C4 8B55E8 MOV EDX,[EBP-18]
0167:004874C7 8D83E8020000 LEA EAX,[EBX+02E8]
0167:004874CD E806C8F7FF CALL 00403CD8
0167:004874D2 EB15 JMP SHORT 004874E9 //让程序从这里跳转则活。
0167:004874D4 6A00 PUSH BYTE +00
0167:004874D6 668B0D3C754800 MOV CX,[0048753C]
0167:004874DD B201 MOV DL,01
0167:004874DF B848754800 MOV EAX,00487548
0167:004874E4 E84333FDFF CALL 0045A82C //此CALL出现错误提示窗口
0167:004874E9 33C0 XOR EAX,EAX
0167:004874EB 5A POP EDX
*
*略去10来行代码
*
0167:00487514 8BE5 MOV ESP,EBP
0167:00487516 5D POP EBP
===========================
以下代码片段来自487443的调用,这是最精彩的地方了,慢慢看就明白了,其实很简单的。
0167:004877D0 55 PUSH EBP
0167:004877D1 8BEC MOV EBP,ESP
0167:004877D3 83C4F4 ADD ESP,BYTE -0C
0167:004877D6 53 PUSH EBX
0167:004877D7 56 PUSH ESI
0167:004877D8 57 PUSH EDI
0167:004877D9 8955FC MOV [EBP-04],EDX
0167:004877DC 8B45FC MOV EAX,[EBP-04]
0167:004877DF E8D4C8F7FF CALL 004040B8
0167:004877E4 33C0 XOR EAX,EAX
0167:004877E6 55 PUSH EBP
0167:004877E7 683D794800 PUSH DWORD 0048793D
0167:004877EC 64FF30 PUSH DWORD [FS:EAX]
0167:004877EF 648920 MOV [FS:EAX],ESP
0167:004877F2 C645FB00 MOV BYTE [EBP-05],00
0167:004877F6 8B45FC MOV EAX,[EBP-04]
0167:004877F9 E806C7F7FF CALL 00403F04 //此函数获取注册码长度
0167:004877FE 83F813 CMP EAX,BYTE +13 //判断是否为19位,不是则错。
0167:00487801 0F8520010000 JNZ NEAR 00487927
0167:00487807 8B45FC MOV EAX,[EBP-04]
0167:0048780A 8078042D CMP BYTE [EAX+04],2D //判断第5位是否为短杠 "-" ,不是则错。
0167:0048780E 0F8513010000 JNZ NEAR 00487927
0167:00487814 8B45FC MOV EAX,[EBP-04]
0167:00487817 8078092D CMP BYTE [EAX+09],2D //判断第10位是否为短杠 "-" ,不是则错。
0167:0048781B 0F8506010000 JNZ NEAR 00487927
0167:00487821 8B45FC MOV EAX,[EBP-04]
0167:00487824 80780E2D CMP BYTE [EAX+0E],2D //判断第15位是否为短杠 "-" ,不是则错。
0167:00487828 0F85F9000000 JNZ NEAR 00487927
0167:0048782E 33F6 XOR ESI,ESI
0167:00487830 33FF XOR EDI,EDI
0167:00487832 33C0 XOR EAX,EAX
0167:00487834 8945F4 MOV [EBP-0C],EAX
0167:00487837 BB01000000 MOV EBX,01
----------------循环开始---------------
0167:0048783C 8BC3 MOV EAX,EBX
0167:0048783E 2503000080 AND EAX,80000003 //EAX为注册码串的相对偏移量,跟3进行“逻辑与”运算,如果为结果0,则这个位置需要输入数字,而非字母。可以看出只有第4,8,12个位置是特殊位置。
0167:00487843 7905 JNS 0048784A //不是负数则跳走,一般都是跳走了。
0167:00487845 48 DEC EAX
0167:00487846 83C8FC OR EAX,BYTE -04
0167:00487849 40 INC EAX
0167:0048784A 85C0 TEST EAX,EAX //测试“与”运算后的结果
0167:0048784C 7516 JNZ 00487864 //如果不为0,则跳走。否则对特别位置(第4,8,12个位置)进行特别检验。
0167:0048784E 8B45FC MOV EAX,[EBP-04]
0167:00487851 8A4418FF MOV AL,[EAX+EBX-01]
0167:00487855 E84EFFFFFF CALL 004877A8 //此CALL就是检验“特殊位置”的字符是否是数字的。
0167:0048785A 84C0 TEST AL,AL
0167:0048785C 0F84C5000000 JZ NEAR 00487927 //如果不是数字,则AL=0,那么只有死路一条。
0167:00487862 EB22 JMP SHORT 00487886
0167:00487864 8BC3 MOV EAX,EBX
0167:00487866 B905000000 MOV ECX,05
0167:0048786B 99 CDQ
0167:0048786C F7F9 IDIV ECX
0167:0048786E 85D2 TEST EDX,EDX
0167:00487870 7414 JZ 00487886
0167:00487872 8B45FC MOV EAX,[EBP-04]
0167:00487875 8A4418FF MOV AL,[EAX+EBX-01]
0167:00487879 E83EFFFFFF CALL 004877BC //此函数检测注册码是否为大写字符。如果不是则OVER。
0167:0048787E 84C0 TEST AL,AL
0167:00487880 0F84A1000000 JZ NEAR 00487927
0167:00487886 8B45FC MOV EAX,[EBP-04] //从此处开始对注册码分段求和,第一段的和放在ESI内,第二段的和放在EDI内,第三段的和放在[EBP-0C]的内存。
0167:00487889 8A4418FF MOV AL,[EAX+EBX-01]
0167:0048788D 3C2D CMP AL,2D //比较是否是短杠 "-"
0167:0048788F 742D JZ 004878BE
0167:00487891 83FB05 CMP EBX,BYTE +05 //比较计数器EBX是否超过5,如果未超过,则下面对第一段求和
0167:00487894 7D0C JNL 004878A2
0167:00487896 8B55FC MOV EDX,[EBP-04]
0167:00487899 25FF000000 AND EAX,FF //取出EAX低字节
0167:0048789E 03F0 ADD ESI,EAX //保存到ESI,ESI保存和值,即第一段的和。
0167:004878A0 EB1C JMP SHORT 004878BE
0167:004878A2 83FB0A CMP EBX,BYTE +0A //计数器是否超过10,如果没有超过,计算第二段的和。
0167:004878A5 7D0C JNL 004878B3 //计数器超过10后,跳到4878B3处。
0167:004878A7 8B55FC MOV EDX,[EBP-04]
0167:004878AA 25FF000000 AND EAX,FF //取出EAX低字节
0167:004878AF 03F8 ADD EDI,EAX //保存到EDI,EDI保存和值,即第二段的和。
0167:004878B1 EB0B JMP SHORT 004878BE
0167:004878B3 8B55FC MOV EDX,[EBP-04]
0167:004878B6 25FF000000 AND EAX,FF
0167:004878BB 0145F4 ADD [EBP-0C],EAX //第三段累加和放在 [EBP-0C]内存。
0167:004878BE 43 INC EBX //计数器增1。上面累加完毕都跳到这里。
0167:004878BF 83FB0F CMP EBX,BYTE +0F //计数器是否到达15?
0167:004878C2 0F8574FFFFFF JNZ NEAR 0048783C //如果没有到达15,则循环返回48783C。继续上述工作。
----------------循环结束---------------
下面的代码计算第四段注册码,使用前面得到的3段注册码来得到第四段注册码,非常简单。
0167:004878C8 8D0C37 LEA ECX,[EDI+ESI] // 第一段累加和ESI和第二段累加和EDI相加送ECX保存。
0167:004878CB 034DF4 ADD ECX,[EBP-0C] // ECX和第三段和值相加,结果放在ECX内备用。
1.下面取第一段注册码(在ESI内)计算第16个字符
0167:004878CE 8BC6 MOV EAX,ESI
0167:004878D0 BB1A000000 MOV EBX,1A
0167:004878D5 99 CDQ //双字扩展,把EAX符号位扩展到EDX,形成8个字节的被除数。
0167:004878D6 F7FB IDIV EBX //EAX和EDX组成的被除数除以十进制的26,余数(实际上是26个字母的序号)在EDX。
0167:004878D8 83C241 ADD EDX,BYTE +41 //EDX加上41H形成大写字母
0167:004878DB 8B45FC MOV EAX,[EBP-04] //假注册码起始地址送EAX。
0167:004878DE 3A500F CMP DL,[EAX+0F] //取出第16个字符与DL比较,如果不相同则失败。此时为了能够继续调试,输入e命令,回车,即可修改你想修改的内存单元,把第16个字符改成和DL的值一样即可。
0167:004878E1 7544 JNZ 00487927
2.下面只取第二段注册码(在EDI内)计算第17个字符,方法同上,不要忘记用E命令修改你的内存单元注册码值;
0167:004878E3 8BC7 MOV EAX,EDI
0167:004878E5 BB1A000000 MOV EBX,1A
0167:004878EA 99 CDQ
0167:004878EB F7FB IDIV EBX
0167:004878ED 83C241 ADD EDX,BYTE +41
0167:004878F0 8B45FC MOV EAX,[EBP-04]
0167:004878F3 3A5010 CMP DL,[EAX+10]
0167:004878F6 752F JNZ 00487927
3.下面只取第三段注册码(在[EBP-0C]内)计算第18个字符,方法同上,不要忘记用E命令修改你的内存单元注册码值;
0167:004878F8 8B45F4 MOV EAX,[EBP-0C]
0167:004878FB BB1A000000 MOV EBX,1A
0167:00487900 99 CDQ
0167:00487901 F7FB IDIV EBX
0167:00487903 83C241 ADD EDX,BYTE +41
0167:00487906 8B45FC MOV EAX,[EBP-04]
0167:00487909 3A5011 CMP DL,[EAX+11]
0167:0048790C 7519 JNZ 00487927
4.下面用三段注册码总和(在ECX内)计算第19个字符,方法同上,不要忘记用E命令修改你的内存单元注册码值;
0167:0048790E 8BC1 MOV EAX,ECX
0167:00487910 B91A000000 MOV ECX,1A
0167:00487915 99 CDQ
0167:00487916 F7F9 IDIV ECX
0167:00487918 83C241 ADD EDX,BYTE +41
0167:0048791B 8B45FC MOV EAX,[EBP-04]
0167:0048791E 3A5012 CMP DL,[EAX+12]
0167:00487921 7504 JNZ 00487927
0167:00487923 C645FB01 MOV BYTE [EBP-05],01
*
*略去10来行代码
*
0167:0048794C 5D POP EBP
0167:0048794D C3 RET
===========================
下面是487855的 CALL 004877A8 调用的函数模块。功能:检查是否是数字,不是则错。
:004877A8 8BD0 mov edx, eax
:004877AA 80FA2F cmp dl, 2F
:004877AD 7608 jbe 004877B7 //字符ASCII值小于2Fh则错。
:004877AF 80FA3A cmp dl, 3A
:004877B2 7303 jnb 004877B7 //字符ASCII值大于3Ah则错。
:004877B4 B001 mov al, 01
:004877B6 C3 ret
:004877B7 33C0 xor eax, eax
:004877B9 C3 ret
下面是487879的 CALL 004877BC 调用的函数模块。功能:检查是否是大写字母,不是则错。
0167:004877BC 8BD0 MOV EDX,EAX
0167:004877BE 80FA40 CMP DL,40
0167:004877C1 7608 JNA 004877CB //不大于40H则失败。
0167:004877C3 80FA5B CMP DL,5B
0167:004877C6 7303 JNC 004877CB //不小于5BH则失败。
0167:004877C8 B001 MOV AL,01
0167:004877CA C3 RET
0167:004877CB 33C0 XOR EAX,EAX
0167:004877CD C3 RET
===========================
后记:
通过跟踪这个注册码验证过程,我们就可以轻松得到注册码,比如我原来输入的注册码是AAA8-BB8B-C8CC-DDDD,经过修正变成了 AAA8-BB8B-C8CC-RUXI,只有第四段被修改即可。
第一段:ESI=AAA8 =41h+41h+41h+38h=FBh
第二段:EDI=BB8B =42h+42h+38h+42h=FEh
第三段:[EBP-0C]=C8CC =43h+38h+43h+43h=101h
第四段:ESI/1A..... 余11h,加41h=52h=R
EDI/1A..... 余14h,加41h=55h=U
[EBP-0C]/1A..... 余17h,加41h=58h=X
[ECX]/1A..... 余8h,加41h=49h=I
用了30分钟破解,可是用了1个小时写教程,注册机等有时间再写吧。:)算是在元旦来临之际送给菜鸟们的一份礼物吧!祝元旦快乐!
行文中如有不当之处请指出为盼。Emailto:qduwg@163.com
QduWg
2005/12/28
[课程]FART 脱壳王!加量不加价!FART作者讲授!