因为是第一次用od,
写题解也不太会。
可能会有不恰当的地方欢迎指正。
先使用查找文本字符串
发现倒数第二句。双击进入。
向上找到跳转处。发现关键。
00401305 |. 33C0 xor eax,eax ; -------------------------
00401307 |. 33DB xor ebx,ebx
00401309 |. 33C9 xor ecx,ecx ; d2k2_cra.<ModuleEntryPoint>
0040130B |. 33D2 xor edx,edx ; d2k2_cra.<ModuleEntryPoint>
0040130D |. 8D05 B4314000 lea eax,dword ptr ds:[0x4031B4] ; 取偏移地址
00401313 |> 8A1C01 mov bl,byte ptr ds:[ecx+eax] ; 将bl依次赋值为输入的密码
00401316 |. 8A91 3C314000 mov dl,byte ptr ds:[ecx+0x40313C] ; dl依次赋值为用户名产生的密码
0040131C |. 80FB 00 cmp bl,0x0 ; 一直进行到前面都一致,后面bl与0x0比较
继续向上。
004012E5 |> \33C0 xor eax,eax ; -----------------------------
004012E7 |. 6A 28 push 0x28 ; /Count = 28 (40.)
004012E9 |. 68 B4314000 push d2k2_cra.004031B4 ; |Buffer = d2k2_cra.004031B4
004012EE |. 6A 04 push 0x4 ; |ControlID = 0x4
004012F0 |. FF75 08 push [arg.1] ; |hWnd = 00220000
004012F3 |. E8 F0000000 call <jmp.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
004012F8 |. 66:85C0 test ax,ax ; 存放用户密码0x4031B4
004012FB |. 74 55 je short d2k2_cra.00401352 ; NULL跳出
004012FD |. 66:83F8 0A cmp ax,0xA
00401301 |. 7F 4F jg short d2k2_cra.00401352 ; 大于10跳出
00401303 |. 7C 4D jl short d2k2_cra.00401352 ; 小于10跳出
发现密码存储地址,可以继续向上找跳转。
00401248 |. 6A 28 push 0x28 ; /Count = 28 (40.)
0040124A |. 68 8C314000 push d2k2_cra.0040318C ; |Buffer = d2k2_cra.0040318C
0040124F |. 6A 02 push 0x2 ; |ControlID = 0x2
00401251 |. FF75 08 push [arg.1] ; |hWnd = 00220000
00401254 |. E8 8F010000 call <jmp.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
00401259 |. 84C0 test al,al ; 获取用户输入用户名,存放至0040318c
0040125B |. 0F84 06010000 je d2k2_cra.00401367 ; 用户名为NULL不合法跳出
00401261 |. 3C 20 cmp al,0x20
00401263 |. 0F8F 13010000 jg d2k2_cra.0040137C ; 用户名大于32跳出
00401269 |. 3C 05 cmp al,0x5
0040126B |. 0F8C 20010000 jl d2k2_cra.00401391 ; 用户名小于5跳出
00401271 |. 8D1D 8C314000 lea ebx,dword ptr ds:[0x40318C]
00401277 |. 33C9 xor ecx,ecx ; ------------------------------------
00401279 |. B0 05 mov al,0x5 ; al的值为5,目的是为了下面的循环5次
0040127B |. 33D2 xor edx,edx ; d2k2_cra.<ModuleEntryPoint>
0040127D |> 8A0C1A mov cl,byte ptr ds:[edx+ebx] ; CL赋值为用户的前五个字符
00401280 |. 80F1 29 xor cl,0x29
00401283 |. 02C8 add cl,al ; cl与0x29异或后,加al
00401285 |. 80F9 41 cmp cl,0x41
00401288 |. 7C 1C jl short d2k2_cra.004012A6 ; 小于0x41
0040128A |. 80F9 5A cmp cl,0x5A
0040128D |. 7F 17 jg short d2k2_cra.004012A6 ; 大于0x5A
0040128F |> 888A 3C314000 mov byte ptr ds:[edx+0x40313C],cl ; 将处理之后的字符值放入0x40313C首地址中
00401295 |. C682 3D314000>mov byte ptr ds:[edx+0x40313D],0x0 ; 清空下一位
0040129C |. FEC2 inc dl ; dl自增
0040129E |. FEC8 dec al ; 循环al每次-1,0停止
004012A0 |. 3C 00 cmp al,0x0
004012A2 |. 74 08 je short d2k2_cra.004012AC ; 结束后跳转
004012A4 |.^ EB D7 jmp short d2k2_cra.0040127D
004012A6 |> B1 52 mov cl,0x52 ; 赋值 cl=0x52
004012A8 |. 02C8 add cl,al ; cl加上al
004012AA |.^ EB E3 jmp short d2k2_cra.0040128F ; 把5个字符放在地址中
004012AC |> 33D2 xor edx,edx ; -----------------------------------------------
004012AE |. B8 05000000 mov eax,0x5
004012B3 |> 8A0C1A mov cl,byte ptr ds:[edx+ebx]
004012B6 |. 80F1 27 xor cl,0x27 ; 与0x27异或
004012B9 |. 02C8 add cl,al
004012BB |. 80C1 01 add cl,0x1 ; 加上al+1
004012BE |. 80F9 41 cmp cl,0x41
004012C1 |. 7C 1C jl short d2k2_cra.004012DF ; 小于41
004012C3 |. 80F9 5A cmp cl,0x5A
004012C6 |. 7F 17 jg short d2k2_cra.004012DF ; 大于5A
004012C8 |> 888A 41314000 mov byte ptr ds:[edx+0x403141],cl
004012CE |. C682 42314000>mov byte ptr ds:[edx+0x403142],0x0
004012D5 |. FEC2 inc dl
004012D7 |. FEC8 dec al ; 循环al每次-1,0停止
004012D9 |. 3C 00 cmp al,0x0 ; 判断处理完毕与否
004012DB |. 74 08 je short d2k2_cra.004012E5 ; 读取用户名并且生成密码完毕,跳转至输入密码处
004012DD |.^ EB D4 jmp short d2k2_cra.004012B3
004012DF |> B1 4D mov cl,0x4D ; cl赋值0x4D
004012E1 |. 02C8 add cl,al ; cl+al
004012E3 |.^ EB E3 jmp short d2k2_cra.004012C8 ; 接着存放后5个字符
004012E5 |> 33C0 xor eax,eax ; -----------------------------
结合字符串信息和提示可以完成题目了。
尝试写了一下注册机。因为对汇编还是不太熟练,对于cl寄存器这里理解一开始出现了误区。导致一开始怎么都不对。后来知道问题在哪了。和寄存器cl有关系。
#include
#include
int main()
{
char s[100];
int cl[10];
int mima[10];
for(int i=0;i<5;i++)
scanf("%c",&s[i]);
if(strlen(s)>32||strlen(s)<5)
{
printf("用户名格式为5-32个字符!");
return 0;
}//用户格式有误,无法继续
for(int k=0,a=5;k<5;k++,a--)
{
cl[k]=s[k]^0x29+a;
if(cl[k]<0x41||cl[k]>0x5a)
cl[k]=0x52+a;
} //前五位密码生成步骤1
for(int l=0,b=5;l<5;l++,b--)
{
cl[l+5]=s[l]^0x27+b+1;
if(cl[l+5]<0x41||cl[l+5]>0x5a)
cl[l+5]=0x4d+b;
} //后五位密码生成步骤1
for(int w=0;w<10;w++)
{
mima[w]=cl[w]+5;
if(mima[w]>0x5a)
mima[w]-=0xd;
mima[w]^=0xc;
if(mima[w]>0x5a)
mima[w]=0x4b-w;//原错误理解:mima[w]=0x4b-cl[w]
else if(mima[w]<0x41)
mima[w]=0x4b+w;//原错误理解:mima[w]=0x4b+cl[w]
}//密码生成步骤2
printf("生成的密码为:\n");
for(int n=0;n<10;n++)
printf("%c",mima[n]);
}