能力值:
( LV4,RANK:50 )
|
-
-
2 楼
先用PEID 查得Microsoft Visual C++ 6.0 用OD加载 断点bp GetWindowTextA 77D3216B 再F9运行输入用户名注册码确定停在77D3216B 现在是在USER32下面的 两次ctrl+f9跳到用户代码004015E1 再想想得到文本框个信息应该在点了确定以后吧 所以这里估计是确定按钮对应的事件代码 一直往上看在00401560断点 点击确定后 的确断在这里了 说明断点正确 分析如下:
00401560 . 83EC 5C sub esp, 5C
00401563 . 53 push ebx
00401564 . 56 push esi
00401565 . 8BF1 mov esi, ecx
00401567 . 897424 14 mov dword ptr ss:[esp+14], esi
0040156B . 8D9E 98000000 lea ebx, dword ptr ds:[esi+98]
00401571 . 8BCB mov ecx, ebx
00401573 . E8 838C0100 call 仿射密码.0041A1FB ; length(name)
00401578 . 83F8 05 cmp eax, 5
0040157B . 0F8C 46010000 jl 仿射密码.004016C7 ; length(name)<5 game over
00401581 . 8D4E 5C lea ecx, dword ptr ds:[esi+5C]
00401584 . E8 728C0100 call 仿射密码.0041A1FB ; length(pwd)
00401589 . 85C0 test eax, eax ; length(pwd)==0 game over
0040158B . 0F84 36010000 je 仿射密码.004016C7
00401591 . 55 push ebp
00401592 . 57 push edi
00401593 . B9 0F000000 mov ecx, 0F
00401598 . BE C4B04200 mov esi, 仿射密码.0042B0C4 ; ASCII "0123456789abcdefghjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
0040159D . 8D7C24 2C lea edi, dword ptr ss:[esp+2C]
004015A1 . F3:A5 rep movs dword ptr es:[edi], dword ptr ds:[esi] ; str=0123456789abcdefghjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
004015A3 . 8BCB mov ecx, ebx
004015A5 . 66:A5 movs word ptr es:[edi], word ptr ds:[esi]
004015A7 . E8 4F8C0100 call 仿射密码.0041A1FB ; length(name)
004015AC . 8BF0 mov esi, eax
004015AE . 8D7E 01 lea edi, dword ptr ds:[esi+1]
004015B1 . 57 push edi
004015B2 . E8 3D570100 call 仿射密码.00416CF4 ; 分配内存空间
004015B7 . 57 push edi
004015B8 . 894424 18 mov dword ptr ss:[esp+18], eax
004015BC . E8 33570100 call 仿射密码.00416CF4 ; 分配内存空间
004015C1 . 8BE8 mov ebp, eax
004015C3 . 57 push edi
004015C4 . 896C24 24 mov dword ptr ss:[esp+24], ebp
004015C8 . E8 27570100 call 仿射密码.00416CF4 ; 分配内存空间
004015CD . 83C4 0C add esp, 0C
004015D0 . 894424 14 mov dword ptr ss:[esp+14], eax
004015D4 . 8B4424 10 mov eax, dword ptr ss:[esp+10]
004015D8 . 8BCB mov ecx, ebx
004015DA . 57 push edi
004015DB . 50 push eax
004015DC . E8 EB8B0100 call 仿射密码.0041A1CC ; length(name)
004015E1 . 8BC6 mov eax, esi
004015E3 . B9 3E000000 mov ecx, 3E
004015E8 . 99 cdq
004015E9 . F7F9 idiv ecx ; length(name)/3E
004015EB . 8BC1 mov eax, ecx
004015ED . 2BC6 sub eax, esi
004015EF . 8A5C14 2C mov bl, byte ptr ss:[esp+edx+2C] ; num1=str[length(name)%3E]
004015F3 . 99 cdq
004015F4 . F7F9 idiv ecx ; (3E-length(name))%3E
004015F6 . 33C9 xor ecx, ecx
004015F8 . 85F6 test esi, esi
004015FA . 8A5414 2C mov dl, byte ptr ss:[esp+edx+2C] ; num2=str[(3E-length(name))%3E]
004015FE . 7E 4E jle short 仿射密码.0040164E ; num2<=0 game over
00401600 . 0FBEC3 movsx eax, bl
00401603 . 894424 24 mov dword ptr ss:[esp+24], eax ; num1
00401607 . 8B4424 10 mov eax, dword ptr ss:[esp+10] ; name
0040160B . 0FBED2 movsx edx, dl ; num2
0040160E . 2BC5 sub eax, ebp
00401610 . 895424 28 mov dword ptr ss:[esp+28], edx ; num1
00401614 . 894424 20 mov dword ptr ss:[esp+20], eax
00401618 . EB 04 jmp short 仿射密码.0040161E
0040161A > 8B4424 20 mov eax, dword ptr ss:[esp+20]
0040161E > 8D1C29 lea ebx, dword ptr ds:[ecx+ebp] ; ecx=n
00401621 . 8B5424 28 mov edx, dword ptr ss:[esp+28] ; num1
00401625 . BD 3E000000 mov ebp, 3E
0040162A . 0FBE0418 movsx eax, byte ptr ds:[eax+ebx] ; name[n]
0040162E . 0FAF4424 24 imul eax, dword ptr ss:[esp+24] ; name[n]*num1
00401633 . 03C2 add eax, edx ; name[n]*num1+num2
00401635 . 99 cdq
00401636 . F7FD idiv ebp
00401638 . 8BC2 mov eax, edx ; sum3=(name[n]*num1+num2)%3E
0040163A . 03C1 add eax, ecx ; sum3+n
0040163C . 99 cdq
0040163D . F7FD idiv ebp ; (sum3+n)%3E
0040163F . 8B6C24 18 mov ebp, dword ptr ss:[esp+18]
00401643 . 41 inc ecx
00401644 . 3BCE cmp ecx, esi ; for(n=0; n<length(name); n++)
00401646 . 8A4414 2C mov al, byte ptr ss:[esp+edx+2C] ; pwd[n]=str[(sum3+n)%3E]
0040164A . 8803 mov byte ptr ds:[ebx], al
0040164C .^ 7C CC jl short 仿射密码.0040161A
0040164E > 8B5424 1C mov edx, dword ptr ss:[esp+1C]
00401652 . C60429 00 mov byte ptr ds:[ecx+ebp], 0
00401656 . 8B4C24 14 mov ecx, dword ptr ss:[esp+14]
0040165A . 57 push edi ; 以上循环生成字符串code
0040165B . 51 push ecx
0040165C . 8D4A 5C lea ecx, dword ptr ds:[edx+5C]
0040165F . E8 688B0100 call 仿射密码.0041A1CC ; 得到输入注册码的前面length(name)个字符
00401664 . 33C0 xor eax, eax
00401666 . 33DB xor ebx, ebx
00401668 . 85F6 test esi, esi ; length(name)<0 game over
0040166A . 7E 3C jle short 仿射密码.004016A8
0040166C . 8B4C24 14 mov ecx, dword ptr ss:[esp+14] ; pwd
00401670 . 8BFD mov edi, ebp ; code
00401672 . 2BCD sub ecx, ebp
00401674 . 894C24 28 mov dword ptr ss:[esp+28], ecx
00401678 > 8A1439 mov dl, byte ptr ds:[ecx+edi] ; pwd[0]
0040167B . 3A17 cmp dl, byte ptr ds:[edi] ; 比较 pwd[0]和code[0] 是否相等 看到这里没有继续看了 看看下面的OK 可以猜想是不是生成的字符串就是注册码呢
0040167D . 75 29 jnz short 仿射密码.004016A8
0040167F . 40 inc eax
00401680 . 3BF0 cmp esi, eax
00401682 . 894424 24 mov dword ptr ss:[esp+24], eax
00401686 . 75 1A jnz short 仿射密码.004016A2
00401688 . 8B4C24 1C mov ecx, dword ptr ss:[esp+1C]
0040168C . 6A 00 push 0
0040168E . 6A 00 push 0
00401690 . 68 C0B04200 push 仿射密码.0042B0C0 ; ASCII "OK!"
00401695 . E8 88790100 call 仿射密码.00419022
0040169A . 8B4C24 28 mov ecx, dword ptr ss:[esp+28]
0040169E . 8B4424 24 mov eax, dword ptr ss:[esp+24]
004016A2 > 43 inc ebx
004016A3 . 47 inc edi
004016A4 . 3BDE cmp ebx, esi
004016A6 .^ 7C D0 jl short 仿射密码.00401678
004016A8 > 8B4424 10 mov eax, dword ptr ss:[esp+10]
004016AC . 50 push eax
004016AD . E8 6B560100 call 仿射密码.00416D1D
004016B2 . 55 push ebp
004016B3 . E8 65560100 call 仿射密码.00416D1D
004016B8 . 8B4C24 1C mov ecx, dword ptr ss:[esp+1C]
004016BC . 51 push ecx
004016BD . E8 5B560100 call 仿射密码.00416D1D
004016C2 . 83C4 0C add esp, 0C
004016C5 . 5F pop edi
004016C6 . 5D pop ebp
004016C7 > 5E pop esi
004016C8 . 5B pop ebx
004016C9 . 83C4 5C add esp, 5C
004016CC . C3 retn
大致分析就是这样了 在OD中第一次写的注释很详细但是不见了 比较郁闷 这次就简约写了。。
以下是算法:
在XP环境VC6下编译通过
#include<stdio.h>
#include<string.h>
int main(){
char *str="0123456789abcdefghjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
char name[20];
char pwd[20];
char code[20];
int len, n;
memset(name, 0, sizeof(name));
memset(pwd, 0, sizeof(pwd));
memset(code, 0, sizeof(code));
printf("请输入用户名:");
scanf("%s", name);
printf("请输入注册码:");
scanf("%s", pwd);
len=strlen(name);
if(len<5)
return 0;
if(strcmp(pwd, "")==0)
return 0;
/*
pwd[n]=str[(sum3+n)%3E]
sum3=(name[n]*num1+num2)%3E
num2=str[(3E-length(name))%3E]
num1=str[length(name)%3E]
*/
for(n=0; n<len; n++){
code[n]=str[(((name[n]*(str[len%0x3E])+(str[(0x3E-len)%0x3E]))%0x3E)+n)%0x3E];
if(pwd[n]!=code[n])
return 0;
}
printf("ok!");
getch();
return 0;
}
以下是注册代码:
在XP环境VC6下编译通过
#include<stdio.h>
#include<string.h>
int main(){
char *str="0123456789abcdefghjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
char name[20];
char pwd[20];
int len, n;
printf("请输入用户名(长度大于等于五位):");
scanf("%s", name);
len=strlen(name);
/*
pwd[n]=str[(sum3+n)%3E]
sum3=(name[n]*num1+num2)%3E
num2=str[(3E-length(name))%3E]
num1=str[length(name)%3E]
*/
for(n=0; n<len; n++)
pwd[n]=str[(((name[n]*(str[len%0x3E])+(str[(0x3E-len)%0x3E]))%0x3E)+n)%0x3E];
pwd[n]='\0';
printf("注册码:%s", pwd);
getch();
return 0;
}
|
能力值:
( LV7,RANK:110 )
|
-
-
3 楼
厉害!厉害!能这么详细相信也不是菜鸟了.
以下是仿射密码的原理:
E(a,b,x)=(a*x1+b)%26,(a*x2+b)%26,(a*x3+b)%26,......,(a*x(n-1)+b)%26,(a*xn+b)%26
但希望,没有搞懂的,先搞懂再看
|