破解某CM
破解某CM作者:riusksk
主页:http://riusksk.blogbus.com
中午在CCG论坛上看到某兄弟发了个CM,只暴破了,于是就操起家伙,磨刀霍霍向CM,因此就有了本文。那兄弟发的帖子在:
http://www.ccgcn.com/bbs/viewthread.php?tid=1114&extra=page%3D1 ,如果有错误之处,欢迎指正.说实话,有些地方,我也是很模糊的,
首先打开文件,随便输入用户名“riusksk”和注册“78787878“,查看错误提示,发现提示为 “fail”,然后用OD载入,查找所有字符串,具体内容如下:
文本字串参考位于 Crack_Me:.text
地址 反汇编 文本字串
004015C1 PUSH Crack_Me.00403038 ASCII "User Name is empty!"
0040160C PUSH Crack_Me.00403028 ASCII "Great! pf! pf!"
0040161A PUSH Crack_Me.00403020 ASCII "fail!"
004016A7 PUSH Crack_Me.00403050 ASCII "C:\"
004016C4 MOV EDX,DWORD PTR SS: (初始 CPU 选择)
00401899 PUSH Crack_Me.0040304C ASCII "%s"
此时鼠标双击ASCII "fail!",窗口自动跳至下面:
00401590 .6A FF PUSH -1
00401592 .68 381E4000 PUSH Crack_Me.00401E38 ;SE 处理程序安装
00401597 .64:A1 0000000>MOV EAX,DWORD PTR FS:
0040159D .50 PUSH EAX
0040159E .64:8925 00000>MOV DWORD PTR FS:,ESP
004015A5 .51 PUSH ECX
004015A6 .56 PUSH ESI
004015A7 .8BF1 MOV ESI,ECX
004015A9 .6A 01 PUSH 1
004015AB .E8 6A050000 CALL <JMP.&MFC42.#6334_?UpdateData@CWnd@@QAEHH@Z>
004015B0 .8B4E 60 MOV ECX,DWORD PTR DS: ;将用户名存入ECX
004015B3 .8D46 60 LEA EAX,DWORD PTR DS: ;用户名指针
004015B6 .8B51 F8 MOV EDX,DWORD PTR DS: ;用户名长度
004015B9 .85D2 TEST EDX,EDX
004015BB .75 20 JNZ SHORT Crack_Me.004015DD ;用户名不为空则跳,否则提示"User Name is empty"
004015BD .6A 00 PUSH 0
004015BF .6A 00 PUSH 0
004015C1 .68 38304000 PUSH Crack_Me.00403038 ;ASCII "User Name is empty!"
004015C6 .8BCE MOV ECX,ESI
004015C8 .E8 47050000 CALL <JMP.&MFC42.#4224_?MessageBoxA@CWnd@@QAEHPBD0I@Z>
004015CD .5E POP ESI
004015CE .8B4C24 04 MOV ECX,DWORD PTR SS:
004015D2 .64:890D 00000>MOV DWORD PTR FS:,ECX
004015D9 .83C4 10 ADD ESP,10
004015DC .C3 RETN
004015DD >8D5424 04 LEA EDX,DWORD PTR SS:
004015E1 .50 PUSH EAX ; /Arg2
004015E2 .52 PUSH EDX ; |Arg1
004015E3 .8BCE MOV ECX,ESI ; |
004015E5 .E8 66000000 CALL Crack_Me.00401650 ; \对用户名riusksk进行计算,得出注册码
我们跟进此CALL看看:
{
0040164F .C3 RETN
00401650/$6A FF PUSH -1
00401652|.68 6F1E4000 PUSH Crack_Me.00401E6F ;SE 处理程序安装
00401657|.64:A1 0000000>MOV EAX,DWORD PTR FS:
0040165D|.50 PUSH EAX
0040165E|.64:8925 00000>MOV DWORD PTR FS:,ESP
00401665|.83EC 34 SUB ESP,34
00401668|.33C0 XOR EAX,EAX
0040166A|.53 PUSH EBX
0040166B|.894424 21 MOV DWORD PTR SS:,EAX
0040166F|.55 PUSH EBP
00401670|.894424 29 MOV DWORD PTR SS:,EAX
00401674|.56 PUSH ESI
00401675|.894424 31 MOV DWORD PTR SS:,EAX
00401679|.33DB XOR EBX,EBX
0040167B|.894424 35 MOV DWORD PTR SS:,EAX
0040167F|.57 PUSH EDI
00401680|.8D4C24 18 LEA ECX,DWORD PTR SS:
00401684|.895C24 20 MOV DWORD PTR SS:,EBX
00401688|.885C24 2C MOV BYTE PTR SS:,BL
0040168C|.894424 3D MOV DWORD PTR SS:,EAX
00401690|.E8 55040000 CALL <JMP.&MFC42.#540_??0CString@@QAE@XZ>
00401695|.6A 0A PUSH 0A ; /pFileSystemNameSize = 0000000A
00401697|.53 PUSH EBX ; |pFileSystemNameBuffer
00401698|.53 PUSH EBX ; |pFileSystemFlags
00401699|.8D4C24 1C LEA ECX,DWORD PTR SS: ; |
0040169D|.53 PUSH EBX ; |pMaxFilenameLength
0040169E|.51 PUSH ECX ; |pVolumeSerialNumber
0040169F|.6A 0C PUSH 0C ; |MaxVolumeNameSize = C (12.)
004016A1|.BE 01000000 MOV ESI,1 ; |
004016A6|.53 PUSH EBX ; |VolumeNameBuffer
004016A7|.68 50304000 PUSH Crack_Me.00403050 ; |RootPathName = "C:\"
004016AC|.897424 6C MOV DWORD PTR SS:,ESI ; |
004016B0|.895C24 34 MOV DWORD PTR SS:,EBX ; |
004016B4|.33ED XOR EBP,EBP ; |
004016B6|.895C24 30 MOV DWORD PTR SS:,EBX ; |
004016BA|.FF15 00204000 CALL DWORD PTR DS:[<&KERNEL32.GetVolumeInformationA>] ; \GetVolumeInformationA
004016C0|.8B4424 10 MOV EAX,DWORD PTR SS: ;C盘序列号48468be9入EAX
004016C4|.8B5424 58 MOV EDX,DWORD PTR SS:
004016C8|.35 26038319 XOR EAX,19830326 ;C盘序列号48468be9与19830326异或,长得有点像生日日期,呵呵
004016CD|.83C9 FF OR ECX,FFFFFFFF ;令ECX=-1
004016D0|.8B12 MOV EDX,DWORD PTR DS: ;用户名riusksk入EDX
004016D2|.894424 10 MOV DWORD PTR SS:,EAX
004016D6|.8BFA MOV EDI,EDX ;将用户名存入EDI
004016D8|.33C0 XOR EAX,EAX
004016DA|.F2:AE REPNE SCAS BYTE PTR ES:
004016DC|.F7D1 NOT ECX
004016DE|.49 DEC ECX ;获取用户名长度
004016DF|.895424 1C MOV DWORD PTR SS:,EDX ;EDX指向用户名
004016E3|.8BF9 MOV EDI,ECX ;将用户名长度存入EDI
004016E5|.0F84 BC010000 JE Crack_Me.004018A7
004016EB|.3BFE CMP EDI,ESI
004016ED|.897424 58 MOV DWORD PTR SS:,ESI
004016F1|.0F8C AF000000 JL Crack_Me.004017A6 ;用户名长度小于1则跳
004016F7|.DD05 30254000 FLD QWORD PTR DS: ;ST0=0.0
004016FD|.EB 04 JMP SHORT Crack_Me.00401703
004016FF|>8B5424 1C /MOV EDX,DWORD PTR SS: ;用户名入EDX
00401703|>8A5C32 FF MOV BL,BYTE PTR DS: ;循环处理用户名每一字符
00401707|.DB4424 58 |FILD DWORD PTR SS: ;用户名位数存入ST0
0040170B|.0FBEC3 |MOVSX EAX,BL ;BL为用户名中的一个字符,此处先取'r',下面就以它为例进行分析
0040170E|.DD5C24 24 |FSTP QWORD PTR SS: ;用户名位数存入ST7
00401712|.894424 58 |MOV DWORD PTR SS:,EAX ;eax=72("r"),即用户名字符的ASCII值
00401716|.DB4424 58 |FILD DWORD PTR SS: ;ST0=114(十进制)
0040171A|.0FBECB |MOVSX ECX,BL ;BL=72 ('r'),即用户名ASCII值
0040171D|.D9FA |FSQRT ;开平方根,值保存在ST0
0040171F|.0FAFCE |IMUL ECX,ESI ;ecx=0x72*1,即用户名字符乘以其所在位数
00401722|.DC4C24 24 |FMUL QWORD PTR SS: ;ST0=平方根值乘以位数
00401726|.DC05 28254000 |FADD QWORD PTR DS: ;ST0=ST0+1
0040172C|.0FAFCE |IMUL ECX,ESI ;用户名字符ASCII乘以位数的值再乘以位数
0040172F|.894C24 58 |MOV DWORD PTR SS:,ECX
00401733|.DB4424 58 |FILD DWORD PTR SS: ;将上面的积存入ST0
00401737|.DEC9 |FMULP ST(1),ST ;ST0=ST1*ST0
00401739|.D8C1 |FADD ST,ST(1) ;ST0=ST0+ST1
0040173B|.E8 36040000 |CALL <JMP.&MSVCRT._ftol> ;进入浮点数运算
00401740|.99 |CDQ
00401741|.DDD8 |FSTP ST ;ST7=ST0
00401743|.B9 A0860100 |MOV ECX,186A0
00401748|.F7F9 |IDIV ECX ;用64位的EDX:EAX除以ECX
0040174A|.895424 14 |MOV DWORD PTR SS:,EDX ;保存余数,记为数据1
0040174E|.0FBED3 |MOVSX EDX,BL ;BL=72 ('r'),即依次取用户名ASCII码
00401751|.895424 58 |MOV DWORD PTR SS:,EDX
00401755|.DB4424 58 |FILD DWORD PTR SS: ;ST0=114(十进制),相当于0x72,即将用户名ASCII入ST0
00401759|.DD05 20254000 |FLD QWORD PTR DS: ;将位数入ST0
0040175F|.E8 0C040000 |CALL <JMP.&MSVCRT._CIpow> ;运算后ST0=用户名ASCII码平方
00401764|.DC4C24 24 |FMUL QWORD PTR SS: ;ST0*1,即用户名平方后的值乘以其位数
00401768|.E8 09040000 |CALL <JMP.&MSVCRT._ftol>
0040176D|.DB4424 14 |FILD DWORD PTR SS: ;ST0等于上面的余数
00401771|.8BCE |MOV ECX,ESI ;用户名位数
00401773|.0FAFCD |IMUL ECX,EBP ;用户名位数乘以用户名前一位在本循环算出的值(最初为0)
00401776|.D9C0 |FLD ST ;ST1=ST0,ST0=ST0
00401778|.D9FA |FSQRT ;开平方,值保存在ST0
0040177A|.03C1 |ADD EAX,ECX
0040177C|.B9 A0860100 |MOV ECX,186A0
00401781|.99 |CDQ
00401782|.F7F9 |IDIV ECX
00401784|.8BEA |MOV EBP,EDX ;保存余数,记为数据2
00401786|.E8 EB030000 |CALL <JMP.&MSVCRT._ftol>
0040178B|.03C5 |ADD EAX,EBP
0040178D|.B9 A0860100 |MOV ECX,186A0
00401792|.99 |CDQ
00401793|.F7F9 |IDIV ECX ;除以ECX,余数保存在EDX
00401795|.46 |INC ESI ;esi为计数器
00401796|.3BF7 |CMP ESI,EDI ;将ESI与用户名长度比较
00401798|.897424 58 |MOV DWORD PTR SS:,ESI
0040179C|.8BDA |MOV EBX,EDX ;保存余数,记为数据3
0040179E|.^ 0F8E 5BFFFFFF \JLE Crack_Me.004016FF ;循环依次对各用户名字符进行以上计算
004017A4|.DDD8 FSTP ST
004017A6|>33C0 XOR EAX,EAX ;EAX清零
004017A8|>8BD0 /MOV EDX,EAX
004017AA|.8B4C24 14 |MOV ECX,DWORD PTR SS: ;ECX=数据1(参见0040174A)
004017AE|.0FAFD0 |IMUL EDX,EAX
004017B1|.0FAFD0 |IMUL EDX,EAX ;EDX=EAX^3
004017B4|.8D540A 1F |LEA EDX,DWORD PTR DS: ;EDX=EAX^3+数据1+1F
004017B8|.81E2 7F000080 |AND EDX,8000007F ;将EDX与8000007F与运算
004017BE|.79 05 |JNS SHORT Crack_Me.004017C5
004017C0|.4A |DEC EDX
004017C1|.83CA 80 |OR EDX,FFFFFF80
004017C4|.42 |INC EDX
004017C5|>885404 2C |MOV BYTE PTR SS:,DL ;保存DL到ESP+EAX+2C
004017C9|.40 |INC EAX ;EAX为计数器
004017CA|.83F8 05 |CMP EAX,5 ;循环操作5次
004017CD|.^ 7C D9 \JL SHORT Crack_Me.004017A8
004017CF|.B8 05000000 MOV EAX,5
004017D4|>8BC8 /MOV ECX,EAX
004017D6|.0FAFC8 |IMUL ECX,EAX
004017D9|.0FAFC8 |IMUL ECX,EAX
004017DC|.8D5429 1F |LEA EDX,DWORD PTR DS: ;EDX=EAX^3+数据2+1F(参见00401784)
004017E0|.81E2 7F000080 |AND EDX,8000007F ;将EDX与8000007F与运算
004017E6|.79 05 |JNS SHORT Crack_Me.004017ED
004017E8|.4A |DEC EDX
004017E9|.83CA 80 |OR EDX,FFFFFF80
004017EC|.42 |INC EDX
004017ED|>885404 2C |MOV BYTE PTR SS:,DL ;保存DL到ESP+EAX+2C
004017F1|.40 |INC EAX ;EAX为计数器
004017F2|.83F8 0A |CMP EAX,0A ;循环操作5次
004017F5|.^ 7C DD \JL SHORT Crack_Me.004017D4
004017F7|.B8 0A000000 MOV EAX,0A
004017FC|>8BC8 /MOV ECX,EAX
004017FE|.0FAFC8 |IMUL ECX,EAX
00401801|.0FAFC8 |IMUL ECX,EAX
00401804|.8D5419 1F |LEA EDX,DWORD PTR DS: ;EDX=EAX^3+数据3+1F(参见0040179C)
00401808|.81E2 7F000080 |AND EDX,8000007F ;将EDX与8000007F与运算
0040180E|.79 05 |JNS SHORT Crack_Me.00401815
00401810|.4A |DEC EDX
00401811|.83CA 80 |OR EDX,FFFFFF80
00401814|.42 |INC EDX
00401815|>885404 2C |MOV BYTE PTR SS:,DL ;保存DL到ESP+EAX+2C
00401819|.40 |INC EAX ;EAX为计数器
0040181A|.83F8 0F |CMP EAX,0F ;循环以上操作5次
0040181D|.^ 7C DD \JL SHORT Crack_Me.004017FC
0040181F|.B8 0F000000 MOV EAX,0F
00401824|>8BC8 /MOV ECX,EAX
00401826|.8B5424 10 |MOV EDX,DWORD PTR SS: ;C盘序列号(参见004016C0),现在才发现记忆力在逆向过程中的用处了
0040182A|.0FAFC8 |IMUL ECX,EAX
0040182D|.0FAFC8 |IMUL ECX,EAX
00401830|.8D4C11 1F |LEA ECX,DWORD PTR DS: ;ECX=EAX^3+C盘序列号+1F
00401834|.81E1 7F000080 |AND ECX,8000007F ;将ECX与8000007F与运算
0040183A|.79 05 |JNS SHORT Crack_Me.00401841
0040183C|.49 |DEC ECX
0040183D|.83C9 80 |OR ECX,FFFFFF80
00401840|.41 |INC ECX
00401841|>884C04 2C |MOV BYTE PTR SS:,CL ;保存CL到ESP+EAX+2C
00401845|.40 |INC EAX
00401846|.83F8 14 |CMP EAX,14 ;循环操作5次
00401849|.^ 7C D9 \JL SHORT Crack_Me.00401824
0040184B|.33D2 XOR EDX,EDX
0040184D|.33C9 XOR ECX,ECX ;下面这段循环计算就是注册算法的关键所在
0040184F|>8A4414 2C /MOV AL,BYTE PTR SS:
00401853|.3C 30 |CMP AL,30 ;小于数值“0”则跳转
00401855|.7C 04 |JL SHORT Crack_Me.0040185B
00401857|.3C 39 |CMP AL,39 ;小于等于数值“9”则跳转
00401859|.7E 29 |JLE SHORT Crack_Me.00401884
0040185B|>3C 41 |CMP AL,41 ;小于“A”跳转
0040185D|.7C 04 |JL SHORT Crack_Me.00401863
0040185F|.3C 5A |CMP AL,5A ;小于等于“Z”则跳转
00401861|.7E 21 |JLE SHORT Crack_Me.00401884
00401863|>3C 61 |CMP AL,61 ;小于“a”则跳转
00401865|.7C 04 |JL SHORT Crack_Me.0040186B
00401867|.3C 7A |CMP AL,7A ;小于等于“z”则跳转
00401869|.7E 19 |JLE SHORT Crack_Me.00401884 ;非0-9,A-Z,a-z之间的值需进行以下操作转换为以上范围的值
0040186B|>0FBEC0 |MOVSX EAX,AL
0040186E|.8D4408 1F |LEA EAX,DWORD PTR DS:
00401872|.25 7F000080 |AND EAX,8000007F
00401877|.79 05 |JNS SHORT Crack_Me.0040187E
00401879|.48 |DEC EAX
0040187A|.83C8 80 |OR EAX,FFFFFF80
0040187D|.40 |INC EAX
0040187E|>884414 2C |MOV BYTE PTR SS:,AL
00401882|.^ EB CB |JMP SHORT Crack_Me.0040184F
00401884|>83C1 07 |ADD ECX,7 ;ECX为计数器
00401887|.42 |INC EDX
00401888|.81F9 8C000000 |CMP ECX,8C ;循环计算20次,也就是注册码的位数
0040188E|.^ 7C BF \JL SHORT Crack_Me.0040184F
00401890|.8D4C24 2C LEA ECX,DWORD PTR SS: ;真注册码存入ECX
00401894|.8D5424 18 LEA EDX,DWORD PTR SS:
00401898|.51 PUSH ECX ; 真注册码ASCII "4bJ0UYrqqsbcpEh5n569"
00401899|.68 4C304000 PUSH Crack_Me.0040304C ;ASCII "%s"
0040189E|.52 PUSH EDX
0040189F|.E8 82020000 CALL <JMP.&MFC42.#2818_?Format@CString@@QAAXPBDZZ>
004018A4|.83C4 0C ADD ESP,0C
004018A7|>8B7424 54 MOV ESI,DWORD PTR SS:
004018AB|.8D4424 18 LEA EAX,DWORD PTR SS:
004018AF|.50 PUSH EAX
004018B0|.8BCE MOV ECX,ESI
004018B2|.E8 69020000 CALL <JMP.&MFC42.#535_??0CString@@QAE@ABV0@@Z>
004018B7|.C74424 20 010>MOV DWORD PTR SS:,1
004018BF|.8D4C24 18 LEA ECX,DWORD PTR SS:
004018C3|.C64424 4C 00MOV BYTE PTR SS:,0
004018C8|.E8 33010000 CALL <JMP.&MFC42.#800_??1CString@@QAE@XZ>
004018CD|.8B4C24 44 MOV ECX,DWORD PTR SS:
004018D1|.8BC6 MOV EAX,ESI
004018D3|.5F POP EDI
004018D4|.5E POP ESI
004018D5|.5D POP EBP
004018D6|.5B POP EBX
004018D7|.64:890D 00000>MOV DWORD PTR FS:,ECX
004018DE|.83C4 40 ADD ESP,40
004018E1\.C2 0800 RETN 8
}
004015EA .8B46 64 MOV EAX,DWORD PTR DS: ;假注册码78787878
004015ED .C74424 10 000>MOV DWORD PTR SS:,0
004015F5 .50 PUSH EAX ; /参数2=假注册码
004015F6 .8B4424 08 MOV EAX,DWORD PTR SS: ; |
004015FA .50 PUSH EAX ; |参数1=真注册码
004015FB .FF15 C8214000 CALL DWORD PTR DS:[<&MSVCRT._mbscmp>] ; \进行注册码比较
00401601 .83C4 08 ADD ESP,8
00401604 .85C0 TEST EAX,EAX ;eax必须为0,也就是上面比较的注册码必须相等
00401606 .6A 00 PUSH 0
00401608 .6A 00 PUSH 0
0040160A .75 0E JNZ SHORT Crack_Me.0040161A ;此句可NOP掉,进行暴破
0040160C .68 28304000 PUSH Crack_Me.00403028 ;ASCII "Great! pf! pf!"
00401611 .8BCE MOV ECX,ESI
00401613 .E8 FC040000 CALL <JMP.&MFC42.#4224_?MessageBoxA@CWnd@@QAEHPBD0I@Z>
00401618 .EB 15 JMP SHORT Crack_Me.0040162F
0040161A >68 20304000 PUSH Crack_Me.00403020 ;ASCII "fail!",正是跳转到此处
0040161F .8BCE MOV ECX,ESI
00401621 .E8 EE040000 CALL <JMP.&MFC42.#4224_?MessageBoxA@CWnd@@QAEHPBD0I@Z>
00401626 .6A 00 PUSH 0
00401628 .8BCE MOV ECX,ESI
0040162A .E8 EB040000 CALL <JMP.&MFC42.#6334_?UpdateData@CWnd@@QAEHH@Z>
0040162F >8D4C24 04 LEA ECX,DWORD PTR SS:
00401633 .C74424 10 FFF>MOV DWORD PTR SS:,-1
0040163B .E8 C0030000 CALL <JMP.&MFC42.#800_??1CString@@QAE@XZ>
00401640 .8B4C24 08 MOV ECX,DWORD PTR SS:
00401644 .5E POP ESI
00401645 .64:890D 00000>MOV DWORD PTR FS:,ECX
0040164C .83C4 10 ADD ESP,10
0040164F .C3 RETN
算法总结:
1.取C盘序列号与19830326做异或运算
2.利用用户名字符u的ASCII值进行计算
数据1=%186A0
数据2=[(ascii(u)^2 *i+数据2*i]%186A0
数据3=[数据2+sqrt(数据1)]%186A0
3.edx=eax^3+数据(包括C盘序列号)+1F(共四组,每组循环计算5次)
4.用上面计算出来的20组数据算出20位注册码
[ 本帖最后由 riusksk 于 2009-8-23 10:08 编辑 ] 写得很详细。 强烈学习了 感谢分享~ 非常详细的分析/:014 感谢版主的支持,继续努力,哈哈…… 写得很详细,学习了。 支持一个! 我也来学习下,多谢了~/:014
页:
[1]