【破解作者】 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
总结一下,这个注册码算法比较简单,这里献丑了!时间仓凑,不管了,过年去了先!大家新年快乐!万事如意!!!!!!!
--------------------------------------------------------------------------------
【版权声明】 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢