• 标 题:supercleaner注册算法分析
  • 作 者:mejy
  • 时 间:2004-1-22 周四, 上午8:07
  • 链 接:http://bbs.pediy.com

【破解作者】 mejy【BCG】【DFCG】【FCG】
【作者邮箱】 yjychao@sohu.com
【使用工具】 OD,FI,W32ASM
【破解平台】 Win9x/NT/2000/XP
【软件名称】 supercleaner
【下载地址】 http://www.southbaypc.com/download/CleanSetup.exe
【软件简介】 一款系统清理软件
注册算法较为简单,献丑了!
【软件大小】 386
【加壳方式】 无
【破解声明】 我是一只小菜鸟,偶得一点心得,愿与大家分享:)
--------------------------------------------------------------------------------
【破解内容】


这是一个国外软件,下载安装后用FI检测,是VC作品,没有加壳。我们先运行一下看看注册方式,程序启动进入NAG,30天限制,然后点击ENTER Registration,输入试练码
NAME:mejy
CODE:888888888888888888888888
点确定后提示,"sorry,you have enter an incorrect registration code!"好了,这是线索,我们再用W32ASM反汇编,看看大体的程序流程,查看字符串参考,找到上面的内容,双击来到这里姑且不表,先看利用OD直接找程序注册关键位置,
操作步骤:
用OD载入目标程序;F9运行程序,点击Enter Registration,输入试练信息,先别点击"OK",返回OD,点击鼠标右键,选择"搜索――当前模块中的名称",查找GetDlgItemTextA函数,这个是Windows的常用断点,然后在此函数上右键选择"查找导入参考",可以看见有几个地方对他进行了调用,不管他因为我们尚且不知具体是哪一个与注册码有关,于是用在每个命令中设置断点,好了之后,点击来到目标程序,点击"OK"按钮,程序回到OD,断在下面的地方:
0041912E   . 8B3D CCA34200  MOV EDI,DWORD PTR DS:[<&USER32.GetDlgIte>;  USER32.GetDlgItemTextA
00419134   . 8D8C24 0801000>LEA ECX,DWORD PTR SS:[ESP+108]
0041913B   . 68 00010000    PUSH 100                   ; /Count = 100 (256.)
00419140   . 51             PUSH ECX                         ; |Buffer
00419141   . 68 17040000    PUSH 417                      ; |ControlID = 417 (1047.)
00419146   . 56             PUSH ESI                                 ; |hWnd
00419147   . FFD7           CALL EDI                 ; GetDlgItemTextA
00419149   . 8D5424 08      LEA EDX,DWORD PTR SS:[ESP+8]
0041914D   . 68 00010000    PUSH 100            ; /Count = 100 (256.)
00419152   . 52             PUSH EDX                        ; |Buffer
00419153   . 68 F3030000    PUSH 3F3                   ; |ControlID = 3F3 (1011.)
00419158   . 56             PUSH ESI                         ; |hWnd
00419159   . FFD7           CALL EDI                ; GetDlgItemTextA
0041915B   . E8 A0ECFFFF    CALL SuperCle.00417E00
00419160   . 85C0           TEST EAX,EAX
00419162   . 5F             POP EDI
00419163   . 75 5C          JNZ SHORT SuperCle.004191C1
00419165   . 8D4424 04    LEA EAX,DWORD PTR SS:[ESP+4]  数据传送指令取CODE
00419169   . 8D8C24 0401000>LEA ECX,DWORD PTR SS:[ESP+104] 取用户名NAME
00419170   . 50             PUSH EAX将试练码入栈Code
00419171   . 51             PUSH ECX将用户名入栈Name
00419172   . E8 89050000    CALL SuperCle.00419700 
 这个call应该是对用户名和注册码进行比较或者变形的关键函数,当然或许你第一次并不知道,但是走过一遍之后,你就应该锁定该目标,对于一般的软件我现在认为只要你能找到关键CALL,那么应该成功了一半,那些BT的算法,还是留给高手把,我们跟进这个CALL见后面
00419177   . 83C4 08        ADD ESP,8
0041917A   . 85C0           TEST EAX,EAX  测试是否是正确的注册码
0041917C   . 74 43          JE SHORT SuperCle.004191C1  跳走则失败!交钱!^_^
0041917E   . 8D5424 04      LEA EDX,DWORD PTR SS:[ESP+4]
00419182   . 8D8424 0401000>LEA EAX,DWORD PTR SS:[ESP+104]
00419189   . 52             PUSH EDX
0041918A   . 50             PUSH EAX
0041918B   . 68 78184300    PUSH SuperCle.00431878                   ;  ASCII "SoftwareSuperCleanerRegistration"   将正确地注册信息写入注册表
00419190   . 68 01000080    PUSH 80000001
00419195   . E8 E6050000    CALL SuperCle.00419780
0041919A   . 68 78184300    PUSH SuperCle.00431878                   ;  ASCII "SoftwareSuperCleanerRegistration"
0041919F   . 68 01000080    PUSH 80000001
004191A4   . E8 A7030000    CALL SuperCle.00419550
004191A9   . 83C4 18        ADD ESP,18
004191AC   . 6A 01          PUSH 1                                   ; /Result = 1
004191AE   . 56             PUSH ESI                                 ; |hWnd
004191AF   . FF15 68A34200  CALL DWORD PTR DS:[<&USER32.EndDialog>]  ; EndDialog
004191B5   . 33C0           XOR EAX,EAX
004191B7   . 5E             POP ESI
004191B8   . 81C4 00020000  ADD ESP,200
004191BE   . C2 1000        RETN 10
※  ※※※※※※※※※※※※关键注册码计算函数※※※※※※※※※※※※※※※※
00419700  /$ 81EC 00010000  SUB ESP,100
00419706  |. 53             PUSH EBX
00419707  |. 8B9C24 0801000>MOV EBX,DWORD PTR SS:[ESP+108]
0041970E  |. 53             PUSH EBX
0041970F  |. E8 FCEFFFFF    CALL SuperCle.00418710
00419714  |. 83C4 04        ADD ESP,4
00419717  |. 85C0           TEST EAX,EAX
00419719  |. 74 0A          JE SHORT SuperCle.00419725
0041971B  |. 33C0           XOR EAX,EAX
0041971D  |. 5B             POP EBX
0041971E  |. 81C4 00010000  ADD ESP,100
00419724  |. C3             RETN
00419725  |> A0 18554300    MOV AL,BYTE PTR DS:[435518]
0041972A  |. 56             PUSH ESI
0041972B  |. 57             PUSH EDI
0041972C  |. 884424 0C      MOV BYTE PTR SS:[ESP+C],AL
00419730  |. B9 3F000000    MOV ECX,3F
00419735  |. 33C0           XOR EAX,EAX
00419737  |. 8D7C24 0D      LEA EDI,DWORD PTR SS:[ESP+D]
0041973B  |. 33F6           XOR ESI,ESI
0041973D  |. F3:AB          REP STOS DWORD PTR ES:[EDI]
0041973F  |. 66:AB          STOS WORD PTR ES:[EDI]
00419741  |. 8D4C24 0C      LEA ECX,DWORD PTR SS:[ESP+C]
00419745  |. 51             PUSH ECX
00419746  |. 53             PUSH EBX
00419747  |. AA             STOS BYTE PTR ES:[EDI]
00419748  |. E8 B3000000    CALL SuperCle.00419800  该call是计算注册码的关键
怎么来得,呵呵多跟几次就知道了!看下面※※※※※
0041974D  |. 8B8424 1C01000>MOV EAX,DWORD PTR SS:[ESP+11C]
00419754  |. 8D5424 14      LEA EDX,DWORD PTR SS:[ESP+14]
00419758  |. 52             PUSH EDX 正确地注册码
00419759  |. 50             PUSH EAX 你输入的错误注册码
0041975A  |. E8 51FFFFFF    CALL SuperCle.004196B0  这个call应该就是比较了,可跟进看一下,大体是先比较长度,若试练码长度和正确注册码长度相等再,逐位比较!
0041975F  |. 83C4 10        ADD ESP,10
00419762  |. 85C0           TEST EAX,EAX
00419764  |. 74 05          JE SHORT SuperCle.0041976B
00419766  |. BE 01000000    MOV ESI,1
0041976B  |> 8BC6           MOV EAX,ESI
0041976D  |. 5F             POP EDI
0041976E  |. 5E             POP ESI
0041976F  |. 5B             POP EBX
00419770  |. 81C4 00010000  ADD ESP,100
00419776  . C3             RETN
※  ※※※※※计算注册码的关键call※※※※※※※※※※※※※※※※※※※
00419800  /$ 81EC 00010000  SUB ESP,100
00419806  |. A0 18554300    MOV AL,BYTE PTR DS:[435518]
0041980B  |. 53             PUSH EBX   NAME入栈
0041980C  |. 55             PUSH EBP  
0041980D  |. 56             PUSH ESI
0041980E  |. 57             PUSH EDI
0041980F  |. 884424 10      MOV BYTE PTR SS:[ESP+10],AL
00419813  |. B9 3F000000    MOV ECX,3F
00419818  |. 33C0           XOR EAX,EAX
0041981A  |. 8D7C24 11      LEA EDI,DWORD PTR SS:[ESP+11]
0041981E  |. F3:AB          REP STOS DWORD PTR ES:[EDI]
00419820  |. 66:AB          STOS WORD PTR ES:[EDI]
00419822  |. AA             STOS BYTE PTR ES:[EDI]
00419823  |. 8BBC24 1401000>MOV EDI,DWORD PTR SS:[ESP+114]
0041982A  |. 57             PUSH EDI                                 ; /String
0041982B  |. FF15 CCA24200  CALL DWORD PTR DS:[<&KERNEL32.lstrlenA>] ; lstrlenA
这里是得到注册用户名的长度,作为下面的循环次数;
00419831  |. 8BF0           MOV ESI,EAX
00419833  |. 33C9           XOR ECX,ECX
00419835  |. 33C0           XOR EAX,EAX
00419837  |. 85F6           TEST ESI,ESI
00419839  |. 7E 13          JLE SHORT SuperCle.0041984E
0041983B  |. 8B15 141D4300  MOV EDX,DWORD PTR DS:[431D14]
这里将程序固定的数据0x26入栈,注册码的第一部分利用这个进行变换
00419841  |> 0FBE1C38       /MOVSX EBX,BYTE PTR DS:[EAX+EDI
 取用户名的第I个字符 ,ECX初始值为0;
00419845  |. 03DA           |ADD EBX,EDX 将NAMe每一个字符与EDX=0x26相加
00419847  |. 03CB           |ADD ECX,EBX  ECX中保存计算结果
00419849  |. 40             |INC EAX          ++I;
0041984A  |. 3BC6           |CMP EAX,ESI
0041984C  |.^7C F3          JL SHORT SuperCle.00419841  
上面那个循环是计算注册码的第一部分
上面循环对应的C++语言表达为:
for(i=0;I<strlen(name);I++)//sum=0,temp=0;edx=0x26;*name={输入的用户名}
{
 temp=edx+name[i];
 sum+=temp;
}
0041984E  |> 8B9C24 1801000>MOV EBX,DWORD PTR SS:[ESP+118]
00419855  |. 51             PUSH ECX                                 ; /<%ld>
00419856  |. 68 34224300    PUSH SuperCle.00432234               ; |Format = "%ld-"
格式化字符串将上面的结果转化为十进制并转化为字符串形式,并在其后面加上字符"-"
0041985B  |. 53             PUSH EBX                                 ; |s
0041985C  |. FF15 80A34200  CALL DWORD PTR DS:[<&USER32.wsprintfA>]  ; wsprintfA
00419862  |. 83C4 0C        ADD ESP,0C
00419865  |. 33C9           XOR ECX,ECX  将ECX中清零
00419867  |. 33C0           XOR EAX,EAX
00419869  |. 85F6           TEST ESI,ESI
0041986B  |. 7E 14          JLE SHORT SuperCle.00419881
下面开始计算注册码的第二部分
0041986D  |. 8B15 181D4300  MOV EDX,DWORD PTR DS:[431D18]
431D18中存的是0x34,第二部分注册码变换的基础  
00419873  |> 0FBE2C38       /MOVSX EBP,BYTE PTR DS:[EAX+EDI]依次取每一位注册码
00419877  |. 0FAFEA         |IMUL EBP,EDX  将每一位注册码和EDX=0x34相乘
0041987A  |. 03CD           |ADD ECX,EBP  上面的计算结果累加
0041987C  |. 40             |INC EAX
0041987D  |. 3BC6           |CMP EAX,ESI  看取完没有
0041987F  |.^7C F2          JL SHORT SuperCle.00419873
这一段对应的C++语言代码
for(I=0;I<strlen(name);I++)  注释初始条件//edx=0x34,ECX=0;
{
temp=edx*name[i];
ECX+=temp;
}
00419881  |> 51             PUSH ECX                                 ; /<%ld>
00419882  |. 8D4C24 14      LEA ECX,DWORD PTR SS:[ESP+14]            ; |
00419886  |. 68 34224300    PUSH SuperCle.00432234         ; |Format = "%ld-"
0041988B  |. 51             PUSH ECX                                 ; |s
0041988C  |. FF15 80A34200  CALL DWORD PTR DS:[<&USER32.wsprintfA>]  ; wsprintfA        //同样转化字符串
00419892  |. 83C4 0C        ADD ESP,0C
00419895  |. 8D5424 10      LEA EDX,DWORD PTR SS:[ESP+10]
00419899  |. 52             PUSH EDX                    ; /StringToAdd
0041989A  |. 53             PUSH EBX                  ; |ConcatString
0041989B  |. FF15 B4A24200  CALL DWORD PTR DS:[<&KERNEL32.lstrcatA>] ; lstrcatA
连接上面的三部分字符串
004198A1  |. 33C9           XOR ECX,ECX   清零
004198A3  |. 33C0           XOR EAX,EAX 
004198A5  |. 85F6           TEST ESI,ESI
004198A7  |. 7E 13          JLE SHORT SuperCle.004198BC
下面计算注册码的第三部分
004198A9  |. 8B15 1C1D4300  MOV EDX,DWORD PTR DS:[431D1C]
431D1C中保存的是0xC作为第三部分计算的基础,
004198AF  |> 0FBE2C38   /MOVSX EBP,BYTE PTR DS:[EAX+EDI] 依次取用户名的每位
004198B3  |. 03EA           |ADD EBP,EDX  每一位和0xC相加
004198B5  |. 03CD           |ADD ECX,EBP  保存累加结果
004198B7  |. 40             |INC EAX
004198B8  |. 3BC6           |CMP EAX,ESI
004198BA  |.^7C F3          JL SHORT SuperCle.004198AF
004198BC  |> 51             PUSH ECX                                 ; /<%ld>
004198BD  |. 8D4424 14      LEA EAX,DWORD PTR SS:[ESP+14]            ; |
004198C1  |. 68 34224300    PUSH SuperCle.00432234              ; |Format = "%ld-"
格式化字符串
004198C6  |. 50             PUSH EAX                                 ; |s
004198C7  |. FF15 80A34200  CALL DWORD PTR DS:[<&USER32.wsprintfA>]  ; wsprintfA
004198CD  |. 83C4 0C        ADD ESP,0C
004198D0  |. 8D4C24 10      LEA ECX,DWORD PTR SS:[ESP+10]
004198D4  |. 51             PUSH ECX                   ; /StringToAdd
004198D5  |. 53             PUSH EBX                    ; |ConcatString
004198D6  |. FF15 B4A24200  CALL DWORD PTR DS:[<&KERNEL32.lstrcatA>] ; lstrcatA
将上面三部分连接起来
004198DC  |. 33C9           XOR ECX,ECX    清零
004198DE  |. 33C0           XOR EAX,EAX
004198E0  |. 85F6           TEST ESI,ESI
004198E2  |. 7E 14          JLE SHORT SuperCle.004198F8
004198E4  |. 8B15 201D4300  MOV EDX,DWORD PTR DS:[431D20]
431D20中的数据为0xE,作为注册码第四部分变换的基础
004198EA  |> 0FBE2C38    /MOVSX EBP,BYTE PTR DS:[EAX+EDI]依次取用户名每一位
004198EE  |. 0FAFEA         |IMUL EBP,EDX   ebp=ebp*edx
004198F1  |. 03CD           |ADD ECX,EBP     ecx+=ebp;
004198F3  |. 40             |INC EAX
004198F4  |. 3BC6           |CMP EAX,ESI
004198F6  |.^7C F2          JL SHORT SuperCle.004198EA   循环结束
004198F8  |> 51             PUSH ECX                                 ; /<%ld>
004198F9  |. 8D5424 14      LEA EDX,DWORD PTR SS:[ESP+14]            ; |
004198FD  |. 68 30224300    PUSH SuperCle.00432230                   ; |Format = "%ld"  最后一个后面不加"-"
00419902  |. 52             PUSH EDX                                 ; |s
00419903  |. FF15 80A34200  CALL DWORD PTR DS:[<&USER32.wsprintfA>]  ; wsprintfA            格式化字符串
00419909  |. 83C4 0C        ADD ESP,0C
0041990C  |. 8D4424 10      LEA EAX,DWORD PTR SS:[ESP+10]
00419910  |. 50             PUSH EAX                     ; /StringToAdd
00419911  |. 53             PUSH EBX                      ; |ConcatString
00419912  |. FF15 B4A24200  CALL DWORD PTR DS:[<&KERNEL32.lstrcatA>] ; lstrcatA
连接上面计算的四个部分。形成注册码
00419918  |. 5F             POP EDI
00419919  |. 5E             POP ESI
0041991A  |. 5D             POP EBP
0041991B  |. 5B             POP EBX
0041991C  |. 81C4 00010000  ADD ESP,100
00419922  . C3             RETN    
计算结束注册信息保存在:HKEY_CURRENT_USER softwareSuperCleaner egistration里面。


--------------------------------------------------------------------------------
【破解总结】
NAME: mejy
Code:589-22724-485-6118


总结一下,这个注册码算法比较简单,这里献丑了!时间仓凑,不管了,过年去了先!大家新年快乐!万事如意!!!!!!!

--------------------------------------------------------------------------------
【版权声明】 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢