参考帖子:http://bbs.pediy.com/showthread.php?threadid=30694
本来以为这次又要管理员帮忙转移帖子了,试了一下,我也能在这个版块发帖了!哈哈!
这次我练习的仍然是PEDIY CrackMe 2007里面一个极其简单的crackme,请大佬路过
这个crackme带壳,因为我暂时还未学到脱壳,所以就按照醉天使的方法脱了壳,首先感谢醉天使大佬。
注意:以下的步骤是在脱完壳的基础上进行的!
程序有错误提示,我们可以查找字符串来到关键地址处:
如果是爆破的话,在je跳转那里进行修改就可以了。
往上翻,可以看到一些运算指令,如果不出错的话,应该是算法的核心部分。但是翻的过程中,却始终看不见我熟悉的GetWindowText,GetDlgItemText之类的函数?好吧,查找一下:
右键->查找->当前模块中的名称(标签),或者直接快捷键Ctrl+N
什么?就这么几个函数,怎么可能?
幸亏前几天学习反调试的时候,我接触到了一个函数,否则,今天我真的就折这了。
这个函数就是GetProcAddress,看一下MSDN:
该函数接受两个参数,第一个是DLL模块的句柄,第二个就是我们需要调用的函数名称。返回值是:要调用的函数的地址。
接下来,我们给GetProcAddress下断,F9运行:
通过堆栈,我们可以看到GetProcAddress具体的执行情况,继续F9执行,直到看见我们想要看到的函数,如下:
出现了GetDlgItemTextA,好,Ctrl+F9,执行到返回,然后bp eax,因为eax存放的就是GetDlgItemTextA函数的地址!如果你不放心的话,也可以继续F9执行下去,但是这个程序调用的确实就GetProcAddress一个函数。删除GetProcAddress断点,重新加载程序,输入用户名和注册码后,我们直接断到了GetDlgItemText函数处。
通过提示,猜到这两个函数在这的作用就是检验我们是否输入了用户名和注册码。
上次看OLLYICE帮助文档的时候,学到了一个小技巧,新手朋友们可以试一下:
比如上面那个图片,光标所在处,call 00401339,我们已经知道了此处call 的是 GetDlgItemText,为了观看的比较直观,一我们可以在旁边加上注释,但要是有很多处都调用了此函数,那岂不是要了命了!所以,二,在光标处 回车 ,进入函数内部,然后输入冒号:,填入你需要的函数名。
所有的00401339地址的调用,都有了一个直观的名字了
下面就是具体的算法分析了:
00401154 6A 64 push 64
00401156 68 A0334000 push 004033A0 ; ASCII "^YIW^Y\"
0040115B 6A 64 push 64
0040115D FF75 08 push dword ptr [ebp+8]
00401160 E8 D1000000 call <GetDigItemText>
00401165 8BD0 mov edx, eax ; edx = len(name)
00401167 33DB xor ebx, ebx ; i = 0
00401169 33C9 xor ecx, ecx ; j = 0
0040116B BE A0334000 mov esi, 004033A0 ; ASCII "^YIW^Y\"
00401170 8D7C32 FF lea edi, dword ptr [edx+esi-1] ; name的最后一位
00401174 3BF7 cmp esi, edi
00401176 73 0C jnb short 00401184 ; 如果name的第一位大于最后一位,跳转
00401178 8A26 mov ah, byte ptr [esi]
0040117A 8A07 mov al, byte ptr [edi]
0040117C 8806 mov byte ptr [esi], al
0040117E 8827 mov byte ptr [edi], ah
00401180 46 inc esi
00401181 4F dec edi
00401182 ^ EB F0 jmp short 00401174
00401184 BE A0334000 mov esi, 004033A0 ; esi指向变换后的name[niygnil]
00401189 8A1C31 mov bl, byte ptr [ecx+esi] ; bl = name[j]
0040118C 80F3 30 xor bl, 30 ; bl = bl ^ 0x30
0040118F 881C31 mov byte ptr [ecx+esi], bl ; name[j] = name[j] ^ 0x30
00401192 41 inc ecx ; j++
00401193 3BCA cmp ecx, edx ; 判断是否遍历完毕
00401195 ^ 75 F2 jnz short 00401189
00401197 6A 64 push 64
00401199 68 AD334000 push 004033AD
0040119E 68 C8000000 push 0C8
004011A3 FF75 08 push dword ptr [ebp+8]
004011A6 E8 8B000000 call <GetDigItemText>
004011AB 8BD0 mov edx, eax ; edx = len(serial);
004011AD 33C9 xor ecx, ecx ; i = 0;
004011AF 33DB xor ebx, ebx ; j = 0;
004011B1 BF AD334000 mov edi, 004033AD
004011B6 8A1C39 mov bl, byte ptr [ecx+edi] ; bl = serial[i]
004011B9 80F3 20 xor bl, 20 ; bl = bl ^ 0x20
004011BC 881C39 mov byte ptr [ecx+edi], bl ; serial[i] = searil[i] ^ 0x20
004011BF 41 inc ecx ; i++
004011C0 3BCA cmp ecx, edx ; 判断是否遍历完毕
004011C2 ^ 75 F2 jnz short 004011B6
004011C4 8A06 mov al, byte ptr [esi]
004011C6 8A1F mov bl, byte ptr [edi]
004011C8 46 inc esi
004011C9 47 inc edi
004011CA 3C 00 cmp al, 0 ; 比较完毕!
004011CC 74 19 je short 004011E7
004011CE 38D8 cmp al, bl
004011D0 ^ 74 F2 je short 004011C4
004011D2 6A 00 push 0
004011D4 68 6B304000 push 0040306B ; You must die baby !!!
004011D9 68 81304000 push 00403081 ; You should Kill your self if you can't keygen me :p !!
004011DE 6A 00 push 0
004011E0 E8 5D000000 call 00401242
004011E5 EB 13 jmp short 004011FA
004011E7 6A 00 push 0
004011E9 68 00304000 push 00403000 ; Congratulation !!!
004011EE 68 13304000 push 00403013 ; Good serial, Now send me Tut & KeyGen to\n devilzcrack@yahoo.fr
004011F3 6A 00 push 0
004011F5 E8 48000000 call 00401242
lingyin是作为上面的name
简单的注册机:
#include<stdio.h>
#include<string.h>
char name[30];
char serial[30];
void F_key()
{
int i;
int j;
char tmp;
int len = strlen(name);
for(i = 0;i < len / 2;i++)
{
if(name[i] < name[len - i - 1])
{
tmp = name[i];
name[i] = name[len - i - 1];
name[len - i - 1] = tmp;
}
}
for(j = 0;j < len;j++)
{
name[j] ^= 0x30;
serial[j] = name[j] ^ 0x20;
printf("%c",serial[j]);
}
printf("\n");
}
int main()
{
printf("请输入用户名:\n");
scanf("%s",name);
F_key();
return 0;
}
注册成功!
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)