-
-
[原创]解密教学第6章序列号方式之习题八分析
-
发表于: 2008-10-27 22:11 3728
-
分析程序是本站解密教学第6章(软件保护技术)第一节(常见保护技巧)中的第1小节(序列号方式)第八题。
步骤一、运行程序查看提示信息
运行crackme3.exe,输入用户名yzlyzl,序列号123456,点击[check]按钮,跳出对话框提示“One of the Details you entered was wrong”。
步骤二、运行PEiD.exe查看该程序的实现语言
运行PEiD.exe,将crackme3.exe拉进来,可以看到提示“Microsoft Visual C++ 6.0”
步骤三、用IDA加载crackme3.exe
因为这是VC的程序,所以设置IDA的FLIRT(File->Load file->FLIRT signature file)为vc32mfc。
步骤四、查找[check]按钮的点击事件的代码位置
查找相关提示信息,在IDA的代码视图中,选择View->Open subviews->Strings,跳出字符串引用窗口,查找“One of the Details you entered was wrong”双击它,定位到:
.data:00403040 aOneOfTheDetail db 'One of the Details you entered was wrong',0
.data:00403040 ; DATA XREF: .text:004015CAo
再双击上面绿色的部分(004015CA)来到:
... ...
... ...
.text:004015C3 push 0
.text:004015C5 push offset aError ; "ERROR"
.text:004015CA push offset aOneOfTheDetail ; "One of the Details you entered was wron"...
.text:004015CF mov ecx, [ebp-20h]
.text:004015D2 call ?MessageBoxA@CWnd@@QAEHPBD0I@Z ; CWnd::MessageBoxA(char const *,char const *,uint)
.text:004015D7 jmp short loc_4015ED
... ...
... ...
我们向上移动到:
.text:004014B0 push ebp
.text:004014B1 mov ebp, esp
.text:004014B3 push 0FFFFFFFFh
... ...
以下开始分析:
.text:004014B0 push ebp
.text:004014B1 mov ebp, esp
.text:004014B3 push 0FFFFFFFFh
.text:004014B5 push offset loc_401BC2
.text:004014BA mov eax, large fs:0
.text:004014C0 push eax
.text:004014C1 mov large fs:0, esp
.text:004014C8 sub esp, 14h
.text:004014CB push ebx
.text:004014CC push esi
.text:004014CD push edi
.text:004014CE mov [ebp-20h], ecx
.text:004014D1 lea ecx, [ebp-1Ch]
.text:004014D4 call ??0CString@@QAE@XZ ; CString::CString(void)
.text:004014D9 mov dword ptr [ebp-4], 0
.text:004014E0 lea ecx, [ebp-10h]
.text:004014E3 call ??0CString@@QAE@XZ ; CString::CString(void)
.text:004014E8 mov byte ptr [ebp-4], 1
.text:004014EC mov ecx, [ebp-20h]
.text:004014EF add ecx, 0A0h ; name控件
.text:004014F5 call ?GetWindowTextLengthA@CWnd@@QBEHXZ ; CWnd::GetWindowTextLengthA(void)
.text:004014FA mov [ebp-14h], eax ; [ebp-14h]=name的长度
.text:004014FD cmp dword ptr [ebp-14h], 5
.text:00401501 jg short loc_401508
.text:00401503 jmp loc_4015C3 ; name的长度小于5出错
.text:00401508 ; ---------------------------------------------------------------------------
.text:00401508
.text:00401508 loc_401508: ; CODE XREF: .text:00401501j
.text:00401508 mov ecx, [ebp-20h]
.text:0040150B add ecx, 60h ; serial控件
.text:0040150E call ?GetWindowTextLengthA@CWnd@@QBEHXZ ; CWnd::GetWindowTextLengthA(void)
.text:00401513 mov [ebp-18h], eax ; [ebp-18h]=serial的长度
.text:00401516 cmp dword ptr [ebp-18h], 5
.text:0040151A jg short loc_401521
.text:0040151C jmp loc_4015C3 ; serial的长度小于5出错
.text:00401521 ; ---------------------------------------------------------------------------
.text:00401521
.text:00401521 loc_401521: ; CODE XREF: .text:0040151Aj
.text:00401521 mov eax, [ebp-20h]
.text:00401524 add eax, 0E0h ; 0E0h - 存放name的CString
.text:00401529 push eax
.text:0040152A mov ecx, [ebp-20h]
.text:0040152D add ecx, 0A0h ; name控件
.text:00401533 call ?GetWindowTextA@CWnd@@QBEXAAVCString@@@Z ; CWnd::GetWindowTextA(CString &)
.text:00401538 mov ecx, [ebp-20h]
.text:0040153B add ecx, 0E4h ; 0E4h - 存放serial的CString
.text:00401541 push ecx
.text:00401542 mov ecx, [ebp-20h]
.text:00401545 add ecx, 60h ; serial控件
.text:00401548 call ?GetWindowTextA@CWnd@@QBEXAAVCString@@@Z ; CWnd::GetWindowTextA(CString &)
.text:0040154D mov edx, [ebp-20h]
.text:00401550 add edx, 0E0h
.text:00401556 push edx
.text:00401557 lea ecx, [ebp-1Ch] ; [ebp-1Ch] - 存放name的Copy值
.text:0040155A call ??4CString@@QAEABV0@ABV0@@Z ; CString::operator=(CString const &)
.text:0040155F mov eax, [ebp-20h]
.text:00401562 add eax, 0E4h
.text:00401567 push eax
.text:00401568 lea ecx, [ebp-10h] ; [ebp-10h] - 存放serial的Copy值
.text:0040156B call ??4CString@@QAEABV0@ABV0@@Z ; CString::operator=(CString const &)
.text:00401570 xor eax, eax ; eax = 0
.text:00401572 xor ebx, ebx ; ebx = 0
.text:00401574 xor ecx, ecx
.text:00401576 mov ecx, 1 ; ecx = 1
.text:0040157B xor edx, edx ; edx = 0
.text:0040157D mov eax, [ebp-1Ch] ; [ebp-1Ch] - 存放name的Copy值
.text:00401580
.text:00401580 loc_401580: ; CODE XREF: .text:0040158Bj
.text:00401580 mov bl, [eax]
.text:00401582 xor bl, cl
.text:00401584 mov [eax], bl ; 处理name中的各个字符
.text:00401584 ; name[i] = name[i]^(i + 1)
.text:00401586 inc ecx
.text:00401587 inc eax
.text:00401588 cmp byte ptr [eax], 0
.text:0040158B jnz short loc_401580
.text:0040158D xor eax, eax ; eax = 0
.text:0040158F xor ebx, ebx ; ebx = 0
.text:00401591 xor ecx, ecx
.text:00401593 mov ecx, 0Ah ; ecx = 0Ah
.text:00401598 xor edx, edx ; edx = 0
.text:0040159A mov eax, [ebp-10h] ; [ebp-10h] - 存放serial的Copy值
.text:0040159D
.text:0040159D loc_40159D: ; CODE XREF: .text:004015A8j
.text:0040159D mov bl, [eax]
.text:0040159F xor bl, cl
.text:004015A1 mov [eax], bl ; 处理serial中的各个字符
.text:004015A1 ; serial[i] = serial[i]^(i + 0Ah)
.text:004015A3 inc ecx
.text:004015A4 inc eax
.text:004015A5 cmp byte ptr [eax], 0
.text:004015A8 jnz short loc_40159D
.text:004015AA mov eax, [ebp-1Ch] ; [ebp-1Ch] - 存放name的处理后的值
.text:004015AD mov edx, [ebp-10h] ; [ebp-10h] - 存放serial的处理后的值
.text:004015B0
.text:004015B0 loc_4015B0: ; CODE XREF: .text:004015BFj
.text:004015B0 xor ecx, ecx
.text:004015B2 mov bl, [eax]
.text:004015B4 mov cl, [edx]
.text:004015B6 cmp bl, cl ; 逐个比较是否相等,不等则出错
.text:004015B8 jnz short loc_4015C3
.text:004015BA inc eax
.text:004015BB inc edx
.text:004015BC cmp byte ptr [eax], 0
.text:004015BF jnz short loc_4015B0
.text:004015C1 jmp short loc_4015D9
.text:004015C3 ; ---------------------------------------------------------------------------
.text:004015C3
.text:004015C3 loc_4015C3: ; CODE XREF: .text:00401503j
.text:004015C3 ; .text:0040151Cj ...
.text:004015C3 push 0
.text:004015C5 push offset aError ; "ERROR"
.text:004015CA push offset aOneOfTheDetail ; "One of the Details you entered was wron"...
.text:004015CF mov ecx, [ebp-20h]
.text:004015D2 call ?MessageBoxA@CWnd@@QAEHPBD0I@Z ; CWnd::MessageBoxA(char const *,char const *,uint)
.text:004015D7 jmp short loc_4015ED
.text:004015D9 ; ---------------------------------------------------------------------------
.text:004015D9
.text:004015D9 loc_4015D9: ; CODE XREF: .text:004015C1j
.text:004015D9 push 0
.text:004015DB push offset aYouDidIt ; "YOU DID IT"
.text:004015E0 push offset aWellDoneCracke ; "Well done,Cracker"
.text:004015E5 mov ecx, [ebp-20h]
.text:004015E8 call ?MessageBoxA@CWnd@@QAEHPBD0I@Z ; CWnd::MessageBoxA(char const *,char const *,uint)
.text:004015ED
.text:004015ED loc_4015ED: ; CODE XREF: .text:004015D7j
.text:004015ED push 64h
.text:004015EF call ds:Sleep
.text:004015F5 mov byte ptr [ebp-4], 0
.text:004015F9 lea ecx, [ebp-10h]
.text:004015FC call ??1CString@@QAE@XZ ; CString::~CString(void)
.text:00401601 mov dword ptr [ebp-4], 0FFFFFFFFh
.text:00401608 lea ecx, [ebp-1Ch]
.text:0040160B call ??1CString@@QAE@XZ ; CString::~CString(void)
.text:00401610 mov ecx, [ebp-0Ch]
.text:00401613 mov large fs:0, ecx
.text:0040161A pop edi
.text:0040161B pop esi
.text:0040161C pop ebx
.text:0040161D mov esp, ebp
.text:0040161F pop ebp
.text:00401620 retn
步骤五、编写注册机
#include <stdio.h>
void KeyGen(char *name, int len)
{
int i = 0;
char *serial = (char *)malloc(len + 1);
for(; i < len; i ++)
{
serial[i] = name[i]^(i + 1)^(i + 0xA);
}
serial[i] = '\0';
printf("name=%s,serial=%s",name,serial);
free(serial);
}
int main(int argc,char **argv)
{
if(argc != 2)
{
printf("Usage: KeyGen [username]");
return 1;
}
if(strlen(argv[1]) <= 5)
{
printf("Username'Length must be greater than 5");
return 1;
}
KeyGen(argv[1],strlen(argv[1]));
return 0;
}
编译:
cl KeyGen.c
运行
KeyGen yzlyzl
得到
name=yzlyzl,serial=rscpqe
我的分析参杂了些猜测,但是我觉得这并不是最终的解决办法 ,所以想请教一下大家。
疑惑地方:
1、如果我不用OD来配合我怎么知道下面的代码是指向name文本框?
.text:004014EC mov ecx, [ebp-20h]
.text:004014EF add ecx, 0A0h ; name文本框控件
2、如果不通过查找引用字符串,我如何找到这个Check按钮事件代码的位置呢?
.text:004014B0 push ebp
.text:004014B1 mov ebp, esp
... ...
... ...
步骤一、运行程序查看提示信息
运行crackme3.exe,输入用户名yzlyzl,序列号123456,点击[check]按钮,跳出对话框提示“One of the Details you entered was wrong”。
步骤二、运行PEiD.exe查看该程序的实现语言
运行PEiD.exe,将crackme3.exe拉进来,可以看到提示“Microsoft Visual C++ 6.0”
步骤三、用IDA加载crackme3.exe
因为这是VC的程序,所以设置IDA的FLIRT(File->Load file->FLIRT signature file)为vc32mfc。
步骤四、查找[check]按钮的点击事件的代码位置
查找相关提示信息,在IDA的代码视图中,选择View->Open subviews->Strings,跳出字符串引用窗口,查找“One of the Details you entered was wrong”双击它,定位到:
.data:00403040 aOneOfTheDetail db 'One of the Details you entered was wrong',0
.data:00403040 ; DATA XREF: .text:004015CAo
再双击上面绿色的部分(004015CA)来到:
... ...
... ...
.text:004015C3 push 0
.text:004015C5 push offset aError ; "ERROR"
.text:004015CA push offset aOneOfTheDetail ; "One of the Details you entered was wron"...
.text:004015CF mov ecx, [ebp-20h]
.text:004015D2 call ?MessageBoxA@CWnd@@QAEHPBD0I@Z ; CWnd::MessageBoxA(char const *,char const *,uint)
.text:004015D7 jmp short loc_4015ED
... ...
... ...
我们向上移动到:
.text:004014B0 push ebp
.text:004014B1 mov ebp, esp
.text:004014B3 push 0FFFFFFFFh
... ...
以下开始分析:
.text:004014B0 push ebp
.text:004014B1 mov ebp, esp
.text:004014B3 push 0FFFFFFFFh
.text:004014B5 push offset loc_401BC2
.text:004014BA mov eax, large fs:0
.text:004014C0 push eax
.text:004014C1 mov large fs:0, esp
.text:004014C8 sub esp, 14h
.text:004014CB push ebx
.text:004014CC push esi
.text:004014CD push edi
.text:004014CE mov [ebp-20h], ecx
.text:004014D1 lea ecx, [ebp-1Ch]
.text:004014D4 call ??0CString@@QAE@XZ ; CString::CString(void)
.text:004014D9 mov dword ptr [ebp-4], 0
.text:004014E0 lea ecx, [ebp-10h]
.text:004014E3 call ??0CString@@QAE@XZ ; CString::CString(void)
.text:004014E8 mov byte ptr [ebp-4], 1
.text:004014EC mov ecx, [ebp-20h]
.text:004014EF add ecx, 0A0h ; name控件
.text:004014F5 call ?GetWindowTextLengthA@CWnd@@QBEHXZ ; CWnd::GetWindowTextLengthA(void)
.text:004014FA mov [ebp-14h], eax ; [ebp-14h]=name的长度
.text:004014FD cmp dword ptr [ebp-14h], 5
.text:00401501 jg short loc_401508
.text:00401503 jmp loc_4015C3 ; name的长度小于5出错
.text:00401508 ; ---------------------------------------------------------------------------
.text:00401508
.text:00401508 loc_401508: ; CODE XREF: .text:00401501j
.text:00401508 mov ecx, [ebp-20h]
.text:0040150B add ecx, 60h ; serial控件
.text:0040150E call ?GetWindowTextLengthA@CWnd@@QBEHXZ ; CWnd::GetWindowTextLengthA(void)
.text:00401513 mov [ebp-18h], eax ; [ebp-18h]=serial的长度
.text:00401516 cmp dword ptr [ebp-18h], 5
.text:0040151A jg short loc_401521
.text:0040151C jmp loc_4015C3 ; serial的长度小于5出错
.text:00401521 ; ---------------------------------------------------------------------------
.text:00401521
.text:00401521 loc_401521: ; CODE XREF: .text:0040151Aj
.text:00401521 mov eax, [ebp-20h]
.text:00401524 add eax, 0E0h ; 0E0h - 存放name的CString
.text:00401529 push eax
.text:0040152A mov ecx, [ebp-20h]
.text:0040152D add ecx, 0A0h ; name控件
.text:00401533 call ?GetWindowTextA@CWnd@@QBEXAAVCString@@@Z ; CWnd::GetWindowTextA(CString &)
.text:00401538 mov ecx, [ebp-20h]
.text:0040153B add ecx, 0E4h ; 0E4h - 存放serial的CString
.text:00401541 push ecx
.text:00401542 mov ecx, [ebp-20h]
.text:00401545 add ecx, 60h ; serial控件
.text:00401548 call ?GetWindowTextA@CWnd@@QBEXAAVCString@@@Z ; CWnd::GetWindowTextA(CString &)
.text:0040154D mov edx, [ebp-20h]
.text:00401550 add edx, 0E0h
.text:00401556 push edx
.text:00401557 lea ecx, [ebp-1Ch] ; [ebp-1Ch] - 存放name的Copy值
.text:0040155A call ??4CString@@QAEABV0@ABV0@@Z ; CString::operator=(CString const &)
.text:0040155F mov eax, [ebp-20h]
.text:00401562 add eax, 0E4h
.text:00401567 push eax
.text:00401568 lea ecx, [ebp-10h] ; [ebp-10h] - 存放serial的Copy值
.text:0040156B call ??4CString@@QAEABV0@ABV0@@Z ; CString::operator=(CString const &)
.text:00401570 xor eax, eax ; eax = 0
.text:00401572 xor ebx, ebx ; ebx = 0
.text:00401574 xor ecx, ecx
.text:00401576 mov ecx, 1 ; ecx = 1
.text:0040157B xor edx, edx ; edx = 0
.text:0040157D mov eax, [ebp-1Ch] ; [ebp-1Ch] - 存放name的Copy值
.text:00401580
.text:00401580 loc_401580: ; CODE XREF: .text:0040158Bj
.text:00401580 mov bl, [eax]
.text:00401582 xor bl, cl
.text:00401584 mov [eax], bl ; 处理name中的各个字符
.text:00401584 ; name[i] = name[i]^(i + 1)
.text:00401586 inc ecx
.text:00401587 inc eax
.text:00401588 cmp byte ptr [eax], 0
.text:0040158B jnz short loc_401580
.text:0040158D xor eax, eax ; eax = 0
.text:0040158F xor ebx, ebx ; ebx = 0
.text:00401591 xor ecx, ecx
.text:00401593 mov ecx, 0Ah ; ecx = 0Ah
.text:00401598 xor edx, edx ; edx = 0
.text:0040159A mov eax, [ebp-10h] ; [ebp-10h] - 存放serial的Copy值
.text:0040159D
.text:0040159D loc_40159D: ; CODE XREF: .text:004015A8j
.text:0040159D mov bl, [eax]
.text:0040159F xor bl, cl
.text:004015A1 mov [eax], bl ; 处理serial中的各个字符
.text:004015A1 ; serial[i] = serial[i]^(i + 0Ah)
.text:004015A3 inc ecx
.text:004015A4 inc eax
.text:004015A5 cmp byte ptr [eax], 0
.text:004015A8 jnz short loc_40159D
.text:004015AA mov eax, [ebp-1Ch] ; [ebp-1Ch] - 存放name的处理后的值
.text:004015AD mov edx, [ebp-10h] ; [ebp-10h] - 存放serial的处理后的值
.text:004015B0
.text:004015B0 loc_4015B0: ; CODE XREF: .text:004015BFj
.text:004015B0 xor ecx, ecx
.text:004015B2 mov bl, [eax]
.text:004015B4 mov cl, [edx]
.text:004015B6 cmp bl, cl ; 逐个比较是否相等,不等则出错
.text:004015B8 jnz short loc_4015C3
.text:004015BA inc eax
.text:004015BB inc edx
.text:004015BC cmp byte ptr [eax], 0
.text:004015BF jnz short loc_4015B0
.text:004015C1 jmp short loc_4015D9
.text:004015C3 ; ---------------------------------------------------------------------------
.text:004015C3
.text:004015C3 loc_4015C3: ; CODE XREF: .text:00401503j
.text:004015C3 ; .text:0040151Cj ...
.text:004015C3 push 0
.text:004015C5 push offset aError ; "ERROR"
.text:004015CA push offset aOneOfTheDetail ; "One of the Details you entered was wron"...
.text:004015CF mov ecx, [ebp-20h]
.text:004015D2 call ?MessageBoxA@CWnd@@QAEHPBD0I@Z ; CWnd::MessageBoxA(char const *,char const *,uint)
.text:004015D7 jmp short loc_4015ED
.text:004015D9 ; ---------------------------------------------------------------------------
.text:004015D9
.text:004015D9 loc_4015D9: ; CODE XREF: .text:004015C1j
.text:004015D9 push 0
.text:004015DB push offset aYouDidIt ; "YOU DID IT"
.text:004015E0 push offset aWellDoneCracke ; "Well done,Cracker"
.text:004015E5 mov ecx, [ebp-20h]
.text:004015E8 call ?MessageBoxA@CWnd@@QAEHPBD0I@Z ; CWnd::MessageBoxA(char const *,char const *,uint)
.text:004015ED
.text:004015ED loc_4015ED: ; CODE XREF: .text:004015D7j
.text:004015ED push 64h
.text:004015EF call ds:Sleep
.text:004015F5 mov byte ptr [ebp-4], 0
.text:004015F9 lea ecx, [ebp-10h]
.text:004015FC call ??1CString@@QAE@XZ ; CString::~CString(void)
.text:00401601 mov dword ptr [ebp-4], 0FFFFFFFFh
.text:00401608 lea ecx, [ebp-1Ch]
.text:0040160B call ??1CString@@QAE@XZ ; CString::~CString(void)
.text:00401610 mov ecx, [ebp-0Ch]
.text:00401613 mov large fs:0, ecx
.text:0040161A pop edi
.text:0040161B pop esi
.text:0040161C pop ebx
.text:0040161D mov esp, ebp
.text:0040161F pop ebp
.text:00401620 retn
步骤五、编写注册机
#include <stdio.h>
void KeyGen(char *name, int len)
{
int i = 0;
char *serial = (char *)malloc(len + 1);
for(; i < len; i ++)
{
serial[i] = name[i]^(i + 1)^(i + 0xA);
}
serial[i] = '\0';
printf("name=%s,serial=%s",name,serial);
free(serial);
}
int main(int argc,char **argv)
{
if(argc != 2)
{
printf("Usage: KeyGen [username]");
return 1;
}
if(strlen(argv[1]) <= 5)
{
printf("Username'Length must be greater than 5");
return 1;
}
KeyGen(argv[1],strlen(argv[1]));
return 0;
}
编译:
cl KeyGen.c
运行
KeyGen yzlyzl
得到
name=yzlyzl,serial=rscpqe
我的分析参杂了些猜测,但是我觉得这并不是最终的解决办法 ,所以想请教一下大家。
疑惑地方:
1、如果我不用OD来配合我怎么知道下面的代码是指向name文本框?
.text:004014EC mov ecx, [ebp-20h]
.text:004014EF add ecx, 0A0h ; name文本框控件
2、如果不通过查找引用字符串,我如何找到这个Check按钮事件代码的位置呢?
.text:004014B0 push ebp
.text:004014B1 mov ebp, esp
... ...
... ...
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
看原图
赞赏
雪币:
留言: