能力值:
( LV3,RANK:20 )
|
-
-
2 楼
注册码特意写成一次算出来,没有分段比较。
明码的key我也找不到。。。
PS:正在学算法分析,有分析过程最好。。。
|
能力值:
( LV6,RANK:80 )
|
-
-
3 楼
abcdefghij
abcdefghij58603ddsoft
明码比较,00401560 . 6A FF push -1
这里是关键点
|
能力值:
( LV3,RANK:20 )
|
-
-
4 楼
你是怎么下断到这里的?
在你的提示下,跟了下算法。
几行源码的分析也这么麻烦。。。。
还好是自己写的,容易看懂。
|
能力值:
( LV5,RANK:60 )
|
-
-
5 楼
呃,在getWindowTestW下断的。。。。。一路跟踪,忽然发现楼主用lstrcmpW比较,不如当初就在这下断了。。。。
连爆破带注册。。。。。。。。分析不了算法。。
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
感谢大家分享,正在学习中
|
能力值:
( LV3,RANK:20 )
|
-
-
7 楼
可以结帖了。我还是感觉有点奇怪。我在OD中下断bp GetWindowTextW 总是断到很奇怪的位置,
让我没法分析。后来在输入表中下断,就找到关键点了。。。
不让明码比较很简单。关键我是分析算法,所以就没处理。呵呵。
|
能力值:
( LV3,RANK:20 )
|
-
-
8 楼
|
能力值:
( LV3,RANK:20 )
|
-
-
9 楼
你的爆破根本不需要,因为那个jz 是判断 if ((user.GetLength()<5 )| (user.GetLength()>10 )| (key.GetLength()<8))
这句的。。。。爆破可以在 0040161D 下的任何一行 jmp 到这
00401728 . 50 push eax
00401729 . 68 AC8F4300 push 00438FAC
0040172E . 68 B88F4300 push 00438FB8
00401733 . E8 BD610000 call CWnd::MessageBoxW ; 注册成功的对话框
|
能力值:
( LV5,RANK:60 )
|
-
-
10 楼
对啊。程序不执行那个。。。我起先是 注册N多用户名。。
|
能力值:
( LV2,RANK:10 )
|
-
-
11 楼
mfc,我喜欢。。
|
能力值:
( LV2,RANK:10 )
|
-
-
12 楼
deppcyan
deppcyan62937ddsoft
|
能力值:
( LV13,RANK:260 )
|
-
-
13 楼
ycming
ycming63647ddsoft
就直接用 bp GetWindowTextW 只不过 是按照 消息流程 来跟 更明确。。
ddsoft 来看看你 ,捧你的场。。。呵呵
|
能力值:
( LV10,RANK:160 )
|
-
-
14 楼
因为还是临时会员,没有办法在他所在的板块回复,只有在这里发帖了。帖子的地址:http://bbs.pediy.com/showthread.php?p=895093#post895093
希望版主能把这个帖回复到ddsoft发的帖子上
自己算出的一组用户名和注册码:
UserName:zouzhiyong
RegCode :zouzhiyong66590ddsoft
怎么说呢,ddsoft写的CM总体上并没有多大的难度,不管是算法上还是anti-debug上,我只是用几分钟进行了一个粗略分析,可能其中在某个CALL里做了一个内存代码校验的,我是在跟踪内存数据下软件断点的时候运行就自动推出,但是奇怪的是,做校验的并不是算法CALL,由于是做算法分析,这里对他的内存校验就不做详细分析
很多朋友都找不到追踪的切入点,其实对于MFC的程序,如果是关联成员变量的话,多数是使用GetWindowTextW来获取的,但是下这个断点是有问题的,因为每个控件的内容都是通过这个函数来获取内容的,会导致,切换到软件的界面就会拦截下来,其实可以通过设置条件进行拦截的,或者是下消息断点~~~
但是我是通过跟踪内存数据来找切入点的,对于MFC的编辑框,当你输入字符串的时候在内存里已经存在这你输入的数据的了,但是不能直接使用。当你点注册的时候就肯定要获取这些内容到设定的一个buffer里,也就是说,获取后,对于你输入的字符串,在内存数据里肯定会多出一处以上,通过对这些地方下访问断点即可。
以下是过程:
输入了信息,还没有点击注册。
点击注册后,注册前和注册后的内存数据变化:
偏移量957DE0就是获取之后的存放位置,到OD中的数据窗口跳到这个位置,下硬件访问断点
这里断下:
一直单步可以来到这个位置
这里很明显是获取输入款的内容
返回之后所在的函数就是这个加密算法的函数过程
代码分析如下:
00401560 . 6A FF PUSH -1
00401562 . 68 631F4300 PUSH CrackMe.00431F63
00401567 . 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
0040156D . 50 PUSH EAX
0040156E . 83EC 78 SUB ESP,78
00401571 . A1 B0274400 MOV EAX,DWORD PTR DS:[4427B0]
00401576 . 33C4 XOR EAX,ESP
00401578 . 894424 74 MOV DWORD PTR SS:[ESP+74],EAX
0040157C . 53 PUSH EBX
0040157D . 55 PUSH EBP
0040157E . 56 PUSH ESI
0040157F . 57 PUSH EDI
00401580 . A1 B0274400 MOV EAX,DWORD PTR DS:[4427B0]
00401585 . 33C4 XOR EAX,ESP
00401587 . 50 PUSH EAX
00401588 . 8D8424 8C000000 LEA EAX,DWORD PTR SS:[ESP+8C]
0040158F . 64:A3 00000000 MOV DWORD PTR FS:[0],EAX
00401595 . 8BF1 MOV ESI,ECX
00401597 . 897424 20 MOV DWORD PTR SS:[ESP+20],ESI
0040159B . E8 70BC0000 CALL CrackMe.0040D210
004015A0 . 33C9 XOR ECX,ECX
004015A2 . 33DB XOR EBX,EBX
004015A4 . 3BC3 CMP EAX,EBX
004015A6 . 0F95C1 SETNE CL
004015A9 . 3BCB CMP ECX,EBX
004015AB . 75 0A JNZ SHORT CrackMe.004015B7
004015AD . 68 05400080 PUSH 80004005
004015B2 . E8 59060000 CALL CrackMe.00401C10
004015B7 > 8B10 MOV EDX,DWORD PTR DS:[EAX]
004015B9 . 8BC8 MOV ECX,EAX
004015BB . 8B42 0C MOV EAX,DWORD PTR DS:[EDX+C]
004015BE . FFD0 CALL EAX
004015C0 . 83C0 10 ADD EAX,10
004015C3 . 894424 14 MOV DWORD PTR SS:[ESP+14],EAX
004015C7 . 899C24 94000000 MOV DWORD PTR SS:[ESP+94],EBX
004015CE . E8 3DBC0000 CALL CrackMe.0040D210
004015D3 . 33C9 XOR ECX,ECX
004015D5 . 3BC3 CMP EAX,EBX
004015D7 . 0F95C1 SETNE CL
004015DA . 3BCB CMP ECX,EBX
004015DC . 75 0A JNZ SHORT CrackMe.004015E8
004015DE . 68 05400080 PUSH 80004005
004015E3 . E8 28060000 CALL CrackMe.00401C10
004015E8 > 8B10 MOV EDX,DWORD PTR DS:[EAX]
004015EA . 8BC8 MOV ECX,EAX
004015EC . 8B42 0C MOV EAX,DWORD PTR DS:[EDX+C]
004015EF . FFD0 CALL EAX
004015F1 . 83C0 10 ADD EAX,10
004015F4 . 894424 18 MOV DWORD PTR SS:[ESP+18],EAX
004015F8 . 8D4C24 14 LEA ECX,DWORD PTR SS:[ESP+14]
004015FC . 51 PUSH ECX ; /Arg1
004015FD . 8D4E 78 LEA ECX,DWORD PTR DS:[ESI+78] ; |
00401600 . C68424 98000000 01 MOV BYTE PTR SS:[ESP+98],1 ; |
00401608 . E8 8B860000 CALL CrackMe.00409C98 ; \//这里读取用户名
0040160D . 8D5424 18 LEA EDX,DWORD PTR SS:[ESP+18]
00401611 . 52 PUSH EDX ; /Arg1
00401612 . 8D8E CC000000 LEA ECX,DWORD PTR DS:[ESI+CC] ; |
00401618 . E8 7B860000 CALL CrackMe.00409C98 ; \//这里读取了注册码
0040161D . 8B7424 18 MOV ESI,DWORD PTR SS:[ESP+18]
00401621 . 8B4E F4 MOV ECX,DWORD PTR DS:[ESI-C] ; //读取注册码长度
00401624 . 8B7C24 14 MOV EDI,DWORD PTR SS:[ESP+14]
00401628 . 8B47 F4 MOV EAX,DWORD PTR DS:[EDI-C] ; //读取用户名产度
0040162B . 33D2 XOR EDX,EDX
0040162D . 83F9 08 CMP ECX,8 ; //注册码长度要大于8
00401630 . 0F9CC2 SETL DL
00401633 . 33C9 XOR ECX,ECX
00401635 . 83F8 0A CMP EAX,0A ; //用户名不能大于10
00401638 . 0F9FC1 SETG CL
0040163B . 0BD1 OR EDX,ECX
0040163D . 33C9 XOR ECX,ECX
0040163F . 83F8 05 CMP EAX,5 ; //用户名不能少于5
00401642 . 0F9CC1 SETL CL
00401645 . 0BD1 OR EDX,ECX
00401647 . 74 14 JE SHORT CrackMe.0040165D ; //都符合条件的话就跳
00401649 . 889C24 94000000 MOV BYTE PTR SS:[ESP+94],BL
00401650 . 8D46 F0 LEA EAX,DWORD PTR DS:[ESI-10]
00401653 . B9 FFFFFFFF MOV ECX,-1
00401658 . E9 ED000000 JMP CrackMe.0040174A
0040165D > 8B15 848F4300 MOV EDX,DWORD PTR DS:[438F84]
00401663 . A1 888F4300 MOV EAX,DWORD PTR DS:[438F88]
00401668 . 8B0D 808F4300 MOV ECX,DWORD PTR DS:[438F80]
0040166E . 6A 52 PUSH 52
00401670 . 894424 30 MOV DWORD PTR SS:[ESP+30],EAX
00401674 . 894C24 28 MOV DWORD PTR SS:[ESP+28],ECX
00401678 . 8B0D 8C8F4300 MOV ECX,DWORD PTR DS:[438F8C]
0040167E . 895424 2C MOV DWORD PTR SS:[ESP+2C],EDX
00401682 . 66:8B15 908F4300 MOV DX,WORD PTR DS:[438F90]
00401689 . 8D4424 3A LEA EAX,DWORD PTR SS:[ESP+3A]
0040168D . 53 PUSH EBX
0040168E . 50 PUSH EAX
0040168F . 894C24 3C MOV DWORD PTR SS:[ESP+3C],ECX
00401693 . 66:895424 40 MOV WORD PTR SS:[ESP+40],DX
00401698 . E8 23E00100 CALL CrackMe.0041F6C0
0040169D . 8D6C24 34 LEA EBP,DWORD PTR SS:[ESP+34]
004016A1 . 83C4 0C ADD ESP,0C
004016A4 . 33F6 XOR ESI,ESI
004016A6 . 33C0 XOR EAX,EAX
004016A8 . 895C24 1C MOV DWORD PTR SS:[ESP+1C],EBX
004016AC . 8BCF MOV ECX,EDI
004016AE . 2BEF SUB EBP,EDI
004016B0 . EB 04 JMP SHORT CrackMe.004016B6
004016B2 > 8B7C24 14 MOV EDI,DWORD PTR SS:[ESP+14]
004016B6 > 85C0 TEST EAX,EAX
004016B8 . 0F8C F2000000 JL CrackMe.004017B0
004016BE . 8B5F F4 MOV EBX,DWORD PTR DS:[EDI-C]
004016C1 . 3BF3 CMP ESI,EBX ; (Initial CPU selection)
004016C3 . 0F8F E7000000 JG CrackMe.004017B0
004016C9 . 0FB711 MOVZX EDX,WORD PTR DS:[ECX] ; //取UserName[i]
004016CC . 0FB71C29 MOVZX EBX,WORD PTR DS:[ECX+EBP] ; //取FlagString[i]
004016D0 . 0FB7FA MOVZX EDI,DX
004016D3 . 0FB7FF MOVZX EDI,DI
004016D6 . 0FAFDF IMUL EBX,EDI ; //mul=UserName[i] * FlagString[i]
004016D9 . 0FB7D2 MOVZX EDX,DX
004016DC . 0FB7D2 MOVZX EDX,DX
004016DF . 03D8 ADD EBX,EAX ; //mul += Temp
004016E1 . 03D3 ADD EDX,EBX ; //result = mul + UserName[i]
004016E3 . 015424 1C ADD DWORD PTR SS:[ESP+1C],EDX
004016E7 . 83C0 05 ADD EAX,5 ; //Temp += 5
004016EA . 46 INC ESI
004016EB . 83C1 02 ADD ECX,2 ; //i++
004016EE . 83F8 1E CMP EAX,1E ; //Temp是否大于30,实际上只对用户名的前6个字符进行运算
004016F1 .^ 7C BF JL SHORT CrackMe.004016B2
004016F3 . 8B4424 1C MOV EAX,DWORD PTR SS:[ESP+1C]
004016F7 . 8B4C24 14 MOV ECX,DWORD PTR SS:[ESP+14]
004016FB . 50 PUSH EAX ; /<%d>
004016FC . 51 PUSH ECX ; |<%s>
004016FD . 8D5424 2C LEA EDX,DWORD PTR SS:[ESP+2C] ; |
00401701 . 68 948F4300 PUSH CrackMe.00438F94 ; |%s%dddsoft,这是字符串的格式
00401706 . 52 PUSH EDX ; |s
00401707 . FF15 84344300 CALL DWORD PTR DS:[<&USER32.wsprintfW>] ; \//这里生成注册码
0040170D . 8B4424 28 MOV EAX,DWORD PTR SS:[ESP+28]
00401711 . 83C4 10 ADD ESP,10
00401714 . 50 PUSH EAX ; /String2
00401715 . 8D4C24 28 LEA ECX,DWORD PTR SS:[ESP+28] ; |
00401719 . 51 PUSH ECX ; |String1
0040171A . FF15 A8324300 CALL DWORD PTR DS:[<&KERNEL32.lstrcmpW>] ; \//注册码比较
00401720 . 85C0 TEST EAX,EAX
00401722 . 75 14 JNZ SHORT CrackMe.00401738 ; //爆破点
加密算法是简单了点,小弟菜鸟一个,用了2分钟就跟出来了~~
希望版主能把这个帖子回复到ddsoft发的帖子上
|
能力值:
( LV2,RANK:10 )
|
-
-
15 楼
学习下思路,有时候确实不懂从哪下手
|
能力值:
( LV2,RANK:10 )
|
-
-
16 楼
这么多的代码和图片
真的是辛苦了
研究下啦
|
能力值:
( LV3,RANK:20 )
|
-
-
17 楼
那是我写的第一个crackme,对我这种汇编菜鸟也是简单得很。
你喜欢复杂点的,下次来个多线程加MD5和RSA的Crackme。。。
|
能力值:
( LV4,RANK:50 )
|
-
-
18 楼
|
能力值:
( LV10,RANK:160 )
|
-
-
19 楼
要进步需要来个复杂点的,哈哈~~~
|
能力值:
( LV2,RANK:10 )
|
-
-
20 楼
// 12.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <string>
#include<iostream>
using namespace std;
int main(int argc, char* argv[])
{
int a=0;
string s1;
string s2="vc.com";
cin >> s1;
int n=s1.length();
if(n<5||n>10)
cout <<"请输入5到10位的用户名"<<endl;
for(int i=0;i<6;i++)
{
a+=s1[i]*s2[i]+5*i+s1[i];
}
cout <<"注册码是:"<<s1<<a<<"ddsoft"<<endl;
return 0;
}
|
能力值:
( LV11,RANK:188 )
|
-
-
21 楼
搞晕了。一直对MFC都是半通水,虽然现在也没好上多少,不过比之前清晰多了。
VS9.0的SEH和ASSERT真多,看流程时比花指令还严重
crackme.udd,放在od的UDD目录,我把主要的消息流程做了标记了。小菜鸟做的笔记就不献丑了,配合这篇文章的看会非常清晰的找到注册按钮的流程:
http://bbs.pediy.com/showthread.php?t=9805
忘了在哪儿抄的了,不管真是很管用,感谢原作者:
一个对话框中按钮点击事件的过程如下:
CWinThread::PumpMessage -> CWnd::PretranslateMessage -> CWnd::WWalkPreTranslateMessate -> CD1Dlg::PreTranslateMessage -> CDialog::PreTranslateMessage -> CWnd::PreTranslateInput -> CWnd::IsDialogMessageA -> USER32内核 -> AfxWndProcBase -> AfxWndProc -> AfxCallWndProc -> CWnd::WindowProc -> CWnd::OnWndMsg -> CWnd::OnCommand -> CDialog::OnCmdMsg -> CCmdTarget::OnCmdMsg -> _AfxDispatchCmdMsg -> CD1Dlg::OnButton1()
由于CWinThread::PumpMessage()函数负责从消息队列中获取消息、翻译消息以及分发消息等,因此习惯将此函数称之为“消息泵”
对于MFC窗口程序,所有窗口都使用同一窗口过程 : AfxWndProcBase(第9个站点)或AfxWndProc(第10个站点)。如果程序是动态链接到MFC DLL(定义了_AFXDLL)则AfxWndProcBase被用作窗口过程,否则AfxWndProc被用作窗口过程.在AfxWndProcBase中,最终也是调用AfxWndProc函数
这个因为是静态 link了,afxWndProc被在CBT windowsHook的 code==3 HCBT_CREATEWND中setwindowlong成窗口的实际消息流程了。 忘了主题了,编辑下。头晕,内存中明码的一个可以用的:
123125612
12312561229633ddsoft
|
能力值:
( LV2,RANK:10 )
|
-
-
22 楼
本人菜鸟,居然没断下来,谁知道怎么断告诉一下,我是靠一个messgebox函数追溯上来的,才发现关键代码,注册机载14楼
012615F4 . 894424 18 mov dword ptr [esp+18], eax
012615F8 . 8D4C24 14 lea ecx, dword ptr [esp+14]
012615FC . 51 push ecx
012615FD . 8D4E 78 lea ecx, dword ptr [esi+78]
01261600 . C68424 980000>mov byte ptr [esp+98], 1
01261608 . E8 8B860000 call 01269C98 ; 用户名ecx,位数放在eax
0126160D . 8D5424 18 lea edx, dword ptr [esp+18]
01261611 . 52 push edx
01261612 . 8D8E CC000000 lea ecx, dword ptr [esi+CC]
01261618 . E8 7B860000 call 01269C98 ; 注册码放在ecx,位数放在eax
0126161D . 8B7424 18 mov esi, dword ptr [esp+18]
01261621 . 8B4E F4 mov ecx, dword ptr [esi-C]
01261624 . 8B7C24 14 mov edi, dword ptr [esp+14]
01261628 . 8B47 F4 mov eax, dword ptr [edi-C]
0126162B . 33D2 xor edx, edx
0126162D . 83F9 08 cmp ecx, 8
01261630 . 0F9CC2 setl dl
01261633 . 33C9 xor ecx, ecx
01261635 . 83F8 0A cmp eax, 0A
01261638 . 0F9FC1 setg cl
0126163B . 0BD1 or edx, ecx
0126163D . 33C9 xor ecx, ecx
0126163F . 83F8 05 cmp eax, 5
01261642 . 0F9CC1 setl cl
01261645 . 0BD1 or edx, ecx ;,上面的一段比较用户名位数5-10之间,注册码位数8位数以上,这儿的setl/g把我弄混了半天,后来才弄明白cx和dx都为零时才成功
01261647 . 74 14 je short 0126165D ; 位数不对则死
01261649 . 889C24 940000>mov byte ptr [esp+94], bl
01261650 . 8D46 F0 lea eax, dword ptr [esi-10]
01261653 . B9 FFFFFFFF mov ecx, -1
01261658 . E9 ED000000 jmp 0126174A
0126165D > 8B15 848F2901 mov edx, dword ptr [1298F84]
01261663 . A1 888F2901 mov eax, dword ptr [1298F88]
01261668 . 8B0D 808F2901 mov ecx, dword ptr [1298F80]
0126166E . 6A 52 push 52
01261670 . 894424 30 mov dword ptr [esp+30], eax
01261674 . 894C24 28 mov dword ptr [esp+28], ecx
01261678 . 8B0D 8C8F2901 mov ecx, dword ptr [1298F8C]
0126167E . 895424 2C mov dword ptr [esp+2C], edx
01261682 . 66:8B15 908F2>mov dx, word ptr [1298F90]
01261689 . 8D4424 3A lea eax, dword ptr [esp+3A]
0126168D . 53 push ebx
0126168E . 50 push eax
0126168F . 894C24 3C mov dword ptr [esp+3C], ecx
01261693 . 66:895424 40 mov word ptr [esp+40], dx
01261698 . E8 23E00100 call 0127F6C0 ; 弄出一个vc.com,后面才知道干啥
0126169D . 8D6C24 34 lea ebp, dword ptr [esp+34]
012616A1 . 83C4 0C add esp, 0C
012616A4 . 33F6 xor esi, esi
012616A6 . 33C0 xor eax, eax
012616A8 . 895C24 1C mov dword ptr [esp+1C], ebx
012616AC . 8BCF mov ecx, edi
012616AE . 2BEF sub ebp, edi
012616B0 . EB 04 jmp short 012616B6
012616B2 > 8B7C24 14 mov edi, dword ptr [esp+14]
012616B6 > 85C0 test eax, eax
012616B8 . 0F8C F2000000 jl 012617B0
012616BE . 8B5F F4 mov ebx, dword ptr [edi-C]
012616C1 . 3BF3 cmp esi, ebx
012616C3 . 0F8F E7000000 jg 012617B0
012616C9 . 0FB711 movzx edx, word ptr [ecx]
012616CC . 0FB71C29 movzx ebx, word ptr [ecx+ebp]
012616D0 . 0FB7FA movzx edi, dx
012616D3 . 0FB7FF movzx edi, di
012616D6 . 0FAFDF imul ebx, edi
012616D9 . 0FB7D2 movzx edx, dx
012616DC . 0FB7D2 movzx edx, dx
012616DF . 03D8 add ebx, eax
012616E1 . 03D3 add edx, ebx
012616E3 . 015424 1C add dword ptr [esp+1C], edx
012616E7 . 83C0 05 add eax, 5
012616EA . 46 inc esi
012616EB . 83C1 02 add ecx, 2
012616EE . 83F8 1E cmp eax, 1E
012616F1 .^ 7C BF jl short 012616B2 ;这里的具体算法看上楼的注册机代码
012616F3 . 8B4424 1C mov eax, dword ptr [esp+1C]
012616F7 . 8B4C24 14 mov ecx, dword ptr [esp+14]
012616FB . 50 push eax ; /<%d> = 13867D8 (20473816.)
012616FC . 51 push ecx ; |<%s> = "hpp1239415ddsoft"
012616FD . 8D5424 2C lea edx, dword ptr [esp+2C] ; |
01261701 . 68 948F2901 push 01298F94 ; |%
01261706 . 52 push edx ; |s = 00000031
01261707 . FF15 84342901 call dword ptr [<&USER32.wsprintfW>] ; \wsprintfW 这里应该是组合注册码
0126170D . 8B4424 28 mov eax, dword ptr [esp+28]
01261711 . 83C4 10 add esp, 10
01261714 . 50 push eax ; /String2 = "123456789"
01261715 . 8D4C24 28 lea ecx, dword ptr [esp+28] ; |
01261719 . 51 push ecx ; |String1 = "hpp1239415ddsoft" ;走到这里才看见真码,下面比较
0126171A . FF15 A8322901 call dword ptr [<&KERNEL32.lstrcmpW>] ; \lstrcmpW
01261720 . 85C0 test eax, eax
01261722 . 75 14 jnz short 01261738 ;不相等则死
01261724 . 8B4C24 20 mov ecx, dword ptr [esp+20]
01261728 . 50 push eax
01261729 . 68 AC8F2901 push 01298FAC
0126172E . 68 B88F2901 push 01298FB8
01261733 . E8 BD610000 call 012678F5 成功了
01261738 > C68424 940000>mov byte ptr [esp+94], 0
01261740 . 8B4424 18 mov eax, dword ptr [esp+18]
01261744 . 83C0 F0 add eax, -10
|
|
|