老文章档案 · 2003 年

FolderView 1.7 注册算法分析 (14千字)

赢政天下 [WINZHENG.COM] · 网络学院 · 2003-07-31 · 作者:炎之川 人气: · 出处:赢政天下整理收藏)

FolderView 1.7 注册算法分析

破解目标:FolderView 1.7

官方主页:http://www.southbaypc.com/

软件简介:这是一个简单易用的小工具,可以将文件夹当中的每个文件,依照大小(byte)、日期、名称作详细列表,并导出成TXT纯文字文件或者将文件资料打列出来。

下载地址:http://hn-down.skycn.net/down/fvsetup.exe

使用工具:W32Dasm、Ollydbg、Windows 自带的计算器

作者:炎之川

时间:2003.3.3

主页:http://skipli.yeah.net/

声明: 此文仅用于学习及交流,若要转载请保持文章完整。

我的第三篇算法分析,前两篇都是crackme,而这篇文章的分析目标是共享软件,不过算法不算难。分析没有花太多时间,而写文章却花费了很长的时间...

用 PEiD 0.8 检查可知文件未加壳。用 W32Dasm 反汇编并初步分析,先在串式参考中找到注册码错误的提示:“Sorry, you have entered an incorrect registration code.”,双击来到下面的代码段:

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00407424(C) //调用之处,右键双击之...

|

:00407469 6A00 push 00000000

* Possible StringData Ref from Data Obj ->"FolderView"

|

:0040746B 6874354100 push 00413574

* Possible StringData Ref from Data Obj ->"Sorry, you have entered an incorrect "

->"registration code."

|

:00407470 68083A4100 push 00413A08

:00407475 56 push esi

来到这里:

* Reference To: USER32.GetDlgItemTextA, Ord:0113h

|

:004073EC 8B3D1C124100 mov edi, dword ptr [0041121C]

:004073F2 68EF030000 push 000003EF

:004073F7 56 push esi

:004073F8 FFD7 call edi

:004073FA 8D542408 lea edx, dword ptr [esp+08]

:004073FE 6800010000 push 00000100

:00407403 52 push edx

:00407404 68ED030000 push 000003ED

:00407409 56 push esi

:0040740A FFD7 call edi

:0040740C 8D442408 lea eax, dword ptr [esp+08]

:00407410 8D8C2408010000 lea ecx, dword ptr [esp+00000108]

:00407417 50 push eax

:00407418 51 push ecx

:00407419 E882030000 call 004077A0 //我们在这里下断点

:0040741E 83C408 add esp, 00000008

:00407421 85C0 test eax, eax

:00407423 5F pop edi

:00407424 7443 je 00407469 //光棒停在这里

:00407426 8D542404 lea edx, dword ptr [esp+04]

:0040742A 8D842404010000 lea eax, dword ptr [esp+00000104]

:00407431 52 push edx

:00407432 50 push eax

可知程序使用 GetDlgItemTextA 来取输入的字符,且我们可以在 407419 处下断点。

Ollydbg 载入文件,在 407419 处按 F2 下断点,然后 ctrl+F2 重新开始,F9 运行程序,填入注册名和假注册码,我填入:

Name: lovefire

S/N: 78787878

按 Check,被 Ollydbg 断下,

(; 后是 Ollydbg 所分析的内容,// 后是我加的注释)

004073FE . 68 00010000 PUSH 100 ; /Count = 100 (256.)

00407403 . 52 PUSH EDX ; |Buffer

00407404 . 68 ED030000 PUSH 3ED ; |ControlID = 3ED (1005.)

00407409 . 56 PUSH ESI ; |hWnd

0040740A . FFD7 CALL EDI ; \GetDlgItemTextA

0040740C . 8D4424 08 LEA EAX, DWORD PTR SS:[ESP+8] //取假码到 EAX

00407410 . 8D8C24 080100>LEA ECX, DWORD PTR SS:[ESP+108] //取注册名到 ECX

00407417 . 50 PUSH EAX //假码入栈,保留到最后比较

00407418 . 51 PUSH ECX //注册名入栈

00407419 . E8 82030000 CALL FolderVi.004077A0 //F7 跟进

0040741E . 83C4 08 ADD ESP, 8

00407421 . 85C0 TEST EAX, EAX

00407423 . 5F POP EDI

00407424 . 74 43 JE SHORT FolderVi.00407469

----------------------------------------------------------------

进入 407419 的call

004077A0 /$ 8B4C24 04 MOV ECX, DWORD PTR SS:[ESP+4]

004077A4 |. 81EC 00010000 SUB ESP, 100

004077AA |. 8D4424 00 LEA EAX, DWORD PTR SS:[ESP]

004077AE |. 50 PUSH EAX

004077AF |. 51 PUSH ECX

004077B0 |. E8 AB000000 CALL FolderVi.00407860

004077B5 |. 8B8424 100100>MOV EAX, DWORD PTR SS:[ESP+110]

004077BC |. 8D5424 08 LEA EDX, DWORD PTR SS:[ESP+8]

004077C0 |. 52 PUSH EDX

004077C1 |. 50 PUSH EAX

004077C2 |. E8 89FFFFFF CALL FolderVi.00407750 //关键call,F7 跟进

004077C7 |. F7D8 NEG EAX

004077C9 |. 1BC0 SBB EAX, EAX

004077CB |. F7D8 NEG EAX

004077CD |. 81C4 10010000 ADD ESP, 110

004077D3 \. C3 RETN

----------------------------------------------------------------

进入 4077C2 的call,算法开始

00407860 /$ 81EC 00010000 SUB ESP, 100

00407866 |. A0 7C684100 MOV AL, BYTE PTR DS:[41687C]

0040786B |. 53 PUSH EBX

0040786C |. 55 PUSH EBP

0040786D |. 56 PUSH ESI

0040786E |. 57 PUSH EDI

0040786F |. 884424 10 MOV BYTE PTR SS:[ESP+10], AL

00407873 |. B9 3F000000 MOV ECX, 3F

00407878 |. 33C0 XOR EAX, EAX

0040787A |. 8D7C24 11 LEA EDI, DWORD PTR SS:[ESP+11]

0040787E |. F3:AB REP STOS DWORD PTR ES:[EDI]

00407880 |. 66:AB STOS WORD PTR ES:[EDI]

00407882 |. AA STOS BYTE PTR ES:[EDI]

00407883 |. 8BBC24 140100>MOV EDI, DWORD PTR SS:[ESP+114] //取输入的注册用户名,放到 edi

0040788A |. 57 PUSH EDI ; /String //edi 入栈

0040788B |. FF15 68114100 CALL DWORD PTR DS:[<&KERNEL32.lstrlen>; \lstrlenA //取输入的注册名长度,然后放到eax(可以通过经过此call后,eax值的变化看出)

00407891 |. 8BF0 MOV ESI, EAX //注册名长度送到 esi

00407893 |. 33C9 XOR ECX, ECX //清零

00407895 |. 33C0 XOR EAX, EAX //清零,做计数器

00407897 |. 85F6 TEST ESI, ESI //比较esi是否为0,即是否已输入注册名

00407899 |. 76 13 JBE SHORT FolderVi.004078AE //如果没有输入,后果很明显...;)

//下面开始的第一个循环

0040789B |. 8B15 F8394100 MOV EDX, DWORD PTR DS:[4139F8] //给edx赋值,发现这里固定是赋值32

004078A1 |> 0FBE1C38 /MOVSX EBX, BYTE PTR DS:[EAX+EDI] //逐位取注册名的字符,第一次取“l”,即6C

004078A5 |. 03DA |ADD EBX, EDX //ebx = ebx+edx = 6C+32 = 9E

004078A7 |. 03CB |ADD ECX, EBX //ecx = ecx+ebx = 0+9E = 9E

004078A9 |. 40 |INC EAX //eax+1,计数器+1

004078AA |. 3BC6 |CMP EAX, ESI //比较eax与esi,esi 中是整个注册名长度值,所以这里比较是否已取完注册名

004078AC |.^ 72 F3 \JB SHORT FolderVi.004078A1 //没有取完就继续循环

//第一个循环结束

第一次循环完成后得到的ebx的值,放入第二次循环继续计算,每次循环最终值放入ecx中。

这个部分的注册算法为:

设 ecx 的值从初始到所有循环完成,分别为N(0),N(1),N(2),N(3),N(4)...则:

ecx = ((注册名字符的ASCII值)+32)+N(n-1)

以我填入的注册名“lovefire”为例:

N(0) = 0 (初始的 ecx=0)

N(1) = 6C+32+0 = 9E //第一次循环,所以N(1-1)=N(0)=0

N(2) = 6F+32+9E = 13F //第二次循环,所以 N(2-1)=N(1)=9E

N(3) = 76+32+13F = 1E7 //以下类推

N(4) = 65+32+1E7 = 27E

N(5) = 66+32+27E = 316

N(6) = 69+32+316 = 3B1

N(7) = 72+32+3B1 = 455

N(8) = 65+32+455 = 4EC = 1260(十进制)

接下来一段是对这个算出来的数做一些处理:

004078AE |> 8B9C24 180100>MOV EBX, DWORD PTR SS:[ESP+118]

004078B5 |. 51 PUSH ECX ; /<%u> //ecx 入栈

004078B6 |. 68 503A4100 PUSH FolderVi.00413A50 ; |Format = "%u-" //格式

004078BB |. 53 PUSH EBX ; |s

004078BC |. FF15 0C124100 CALL DWORD PTR DS:[<&USER32.wsprintfA>; \wsprintfA //给ecx的数值后加上“-”符号

到此处得到一个值“1260-”。

然后开始进行第二个循环,先是一些准备事项:

004078C2 |. 83C4 0C ADD ESP, 0C

004078C5 |. 33C9 XOR ECX, ECX //清零

004078C7 |. 33C0 XOR EAX, EAX //清零

004078C9 |. 85F6 TEST ESI, ESI //比较esi是否为0,即是否已输入注册名

004078CB |. 76 14 JBE SHORT FolderVi.004078E1 //如果没有输入,后果很明显...;)

//下面开始第二个循环

004078CD |. 8B15 FC394100 MOV EDX, DWORD PTR DS:[4139FC] //给 edx 赋值,这个值是固定的,为 28

004078D3 |> 0FBE2C38 /MOVSX EBP, BYTE PTR DS:[EAX+EDI] //逐位取注册名的字符,第一次取“l”,即6C,放到 ebp

004078D7 |. 0FAFEA |IMUL EBP, EDX //ebp = ebp*edx

004078DA |. 03CD |ADD ECX, EBP //ecx = ecx+ebp

004078DC |. 40 |INC EAX //eax+1,计数器+1

004078DD |. 3BC6 |CMP EAX, ESI //是否已取完注册名?

004078DF |.^ 72 F2 \JB SHORT FolderVi.004078D3 //没有取完就继续循环

//循环完成

这个部分的注册算法为:

设 ecx 的值从初始到所有循环完成,分别为N(0),N(1),N(2),N(3),N(4)...则:

ecx=(注册名字符的ASCII值)*28+N(n-1)

以我填入的注册名“lovefire”为例:

N(0) = 0 (初始的 ecx=0)

N(1) = 6C*28+0 = 10E0 //第一次循环,所以N(1-1)=N(0)=0

N(2) = 6F*28+ 10E0 = 2238 //第二次循环,所以 N(2-1)=N(1)=10E0

N(3) = 76*28+ 2238 = 34A8 //以下类推

N(4) = 65*28+ 34A8 = 4470

N(5)= 66*28+ 4470 = 5460

N(6) = 69*28+ 5460 = 64C8

N(7) = 72*28+ 64C8 = 7698

N(8) = 65*28+ 7698 = 8660 = 34400(十进制)

接下来继续对得到的数进行一些处理:

004078E1 |> 51 PUSH ECX ; /<%u> = 8660 (34400.)

004078E2 |. 8D4C24 14 LEA ECX, DWORD PTR SS:[ESP+14] ; |

004078E6 |. 68 503A4100 PUSH FolderVi.00413A50 ; |Format = "%u-"

004078EB |. 51 PUSH ECX ; |s

004078EC |. FF15 0C124100 CALL DWORD PTR DS:[<&USER32.wsprintfA>; \wsprintfA

//将得到的 34400 加上“-”,得到注册码的第二部分 34400-,并放入ecx

004078F2 |. 83C4 0C ADD ESP, 0C

004078F5 |. 8D5424 10 LEA EDX, DWORD PTR SS:[ESP+10]

004078F9 |. 52 PUSH EDX ; /StringToAdd

004078FA |. 53 PUSH EBX ; |ConcatString

004078FB |. FF15 94114100 CALL DWORD PTR DS:[<&KERNEL32.lstrcat>; \lstrcatA //和第一次算出的码合并为“1260-34400-”

至此得到一个新的字串“1260-34400-”。

第三次循环:

00407901 |. 33C9 XOR ECX, ECX

00407903 |. 33C0 XOR EAX, EAX

00407905 |. 85F6 TEST ESI, ESI

00407907 |. 76 13 JBE SHORT FolderVi.0040791C

//对循环3进行一些初始设置,与循环1、2类似,不再多做解释

00407909 |. 8B15 003A4100 MOV EDX, DWORD PTR DS:[413A00] //给edx赋初始值 1E(固定值)

//下面开始的三次循环

0040790F |> 0FBE2C38 /MOVSX EBP, BYTE PTR DS:[EAX+EDI] //逐位取注册名的字符的ASCII值,放到 ebp

00407913 |. 03EA |ADD EBP, EDX //ebp = ebp+edx

00407915 |. 03CD |ADD ECX, EBP //ecx = ecx+ebp

00407917 |. 40 |INC EAX //计数器+1

00407918 |. 3BC6 |CMP EAX, ESI //比较是否已取完注册名

0040791A |.^ 72 F3 \JB SHORT FolderVi.0040790F //没有则继续循环

//循环结束

这个部分的注册算法为:

设 ecx 的值从初始到所有循环完成,分别为N(0),N(1),N(2),N(3),N(4)...则:

ecx=(注册名字符的ASCII值)+1E+N(n-1)

可知,输入的注册名“lovefire”,经过循环计算后得到一个数“44C”,转换为十进制则为“1100”

接下来……

0040791C |> 51 PUSH ECX ; /<%u> = 44C (1100.)

0040791D |. 8D4424 14 LEA EAX, DWORD PTR SS:[ESP+14] ; |

00407921 |. 68 503A4100 PUSH FolderVi.00413A50 ; |Format = "%u-"

00407926 |. 50 PUSH EAX ; |s

00407927 |. FF15 0C124100 CALL DWORD PTR DS:[<&USER32.wsprintfA>; \wsprintfA

0040792D |. 83C4 0C ADD ESP, 0C

00407930 |. 8D4C24 10 LEA ECX, DWORD PTR SS:[ESP+10]

00407934 |. 51 PUSH ECX ; /StringToAdd

00407935 |. 53 PUSH EBX ; |ConcatString

00407936 |. FF15 94114100 CALL DWORD PTR DS:[<&KERNEL32.lstrcat>; \lstrcatA

以上分别代码先给算出的“1100”加上“-”,得到“1100-”,在和前面的字串合并,得到“1260-34400-1100”

第四次循环:

0040793C |. 33C9 XOR ECX, ECX

0040793E |. 33C0 XOR EAX, EAX

00407940 |. 85F6 TEST ESI, ESI

00407942 |. 76 14 JBE SHORT FolderVi.00407958

00407944 |. 8B15 043A4100 MOV EDX, DWORD PTR DS:[413A04] //给edx赋初始值 0B(固定值)

//循环开始

0040794A |> 0FBE2C38 /MOVSX EBP, BYTE PTR DS:[EAX+EDI] //逐位取注册名的字符的ASCII值,放到 ebp

0040794E |. 0FAFEA |IMUL EBP, EDX //ebp = ebp*edx

00407951 |. 03CD |ADD ECX, EBP //ecx = ecx+ebp

00407953 |. 40 |INC EAX //计数器+1

00407954 |. 3BC6 |CMP EAX, ESI //比较是否已取完注册名?

00407956 |.^ 72 F2 \JB SHORT FolderVi.0040794A //没有则继续循环

//循环结束

这个部分的注册算法为:

设 ecx 的值从初始到所有循环完成,分别为N(0),N(1),N(2),N(3),N(4)...则:

ecx=(注册名字符的ASCII值)*0B+N(n-1)

可知,输入的注册名“lovefire”,经过循环计算后得到一个数“24F4”,转换为十进制则为“9460”。

00407958 |> 51 PUSH ECX ; /<%u>

00407959 |. 8D5424 14 LEA EDX, DWORD PTR SS:[ESP+14] ; |

0040795D |. 68 6C384100 PUSH FolderVi.0041386C ; |Format = "%u"

00407962 |. 52 PUSH EDX ; |s

00407963 |. FF15 0C124100 CALL DWORD PTR DS:[<&USER32.wsprintfA>; \wsprintfA

00407969 |. 83C4 0C ADD ESP, 0C

0040796C |. 8D4424 10 LEA EAX, DWORD PTR SS:[ESP+10]

00407970 |. 50 PUSH EAX ; /StringToAdd

00407971 |. 53 PUSH EBX ; |ConcatString

00407972 |. FF15 94114100 CALL DWORD PTR DS:[<&KERNEL32.lstrcat>; \lstrcatA

以上代码将前后算出的数值合并为“1260-34400-1100-9460”,这就是真正的注册码。

再继续往下走,是对比假码与真码,先对比真假注册码长度,如果相等,则逐位比较,如果输入的注册名与计算出的注册码相同,则注册成功,将注册信息写入“HKEY_CURRENT_USER\Software\FolderView\Registration”,分别是"Name"和"Code"两个子键。因为与算法关系不大,且很容易看懂,所以比较注册码这部分的代码就不复制出来了;)

至此,FolderView 1.7 注册算法分析完成。

一组可用的注册码:Name: lovefire S/N: 1260-34400-1100-9460

;by 炎之川 2003.3.3

标 题:大哥写的文章实在是好,条理清晰,一定没少下工夫,感谢ing!附TC注册机 (376字)

发信人:pow

时 间:2003-3-5 17:45:10

详细信息:

#include<stdio.h>

main()

{

char name[80];

int i,name_len;

unsigned long sn1=0,sn2=0,sn3=0,sn4=0;

clrscr();

gets(name);

name_len=strlen(name);

for (i=0;i<name_len;i++)

{

sn1=sn1+(name[i]+0x32);

sn2=sn2+(name[i]*0x28);

sn3=sn3+(name[i]+0x1E);

sn4=sn4+(name[i]*0xB);

}

printf("%ld-%ld-%ld-%ld\n",sn1,sn2,sn3,sn4);

printf("Power By POW ^_^\n");

getch();

}

(出处:赢政天下整理收藏)

相关文章:

·语音界面2.0算法分析及注册机源码!

·侠客系统修改器1.21破解手记--算法分析

·中文拨号上网计时计费器 V4.12注册算法分析

·ClockWise 3.22e注册码算法分析

·CoolClock V1.02注册算法分析

·Directory Scanner v1.5 注册算法分析

·Disk Chief 1.2 简单注册算法分析

·EffeTech HTTP Sniffer 3.2注册算法分析

·eLib2.01算法分析

·EZ MP3 Recorder 1.15 注册算法分析

相关软件:

→ 特别推荐

→ 热点TOP10

关于我们 |

帮助(?)

| 广告服务 |

版权声明 |

商业合作 |

发展历程 |

加盟我们 |

联系我们

Copyright © 1999-2003

winzheng.com All Rights Reserved.

繁体版:由华琦数码技术提供

Powered

by:MeSky.Net

2003-2004 年,宽带刚刚普及,下载站的文章区是许多人学电脑的第一课堂。
🕰 → 🤖 从那时到现在

当年一篇教程能让一台电脑焕然一新;今天的效率工具换成了 AI。 想知道当下最可靠的 AI 模型怎么选?看 赢政指数——我们用了 28 年的选软件严谨,现在用来评测大模型。

档案性质声明:本页为赢政天下(1998-2011)老文章的历史档案复原, 内容反映当年发表时的原貌——包括当年的技术表述、软件版本与观点,部分方法在今天已不适用或不合规,仅作互联网历史记录与研究用途, 不提供任何形式的下载。原始数据经由公共网络存档(Internet Archive)复原。发现问题请联系我们
← 返回老文章档案 · 软件史档案馆 · 赢政天下站史