0x01 OD
实验环境
推荐使用的环境 | 备注 | |
---|---|---|
操作系统 | Windows 10 | |
编译器 | ||
编译选项 | ||
build版本 | ||
调试器 | OD 1.10 |
实验前准备
- 去下载书籍配套资料。
- 用OD打开。
实验过程
由于要取文本框内的字符串,需要调用API函数GetDlgItemTextA,可以在左下方bp GetDlgItemTextA下断点,或者ctrl+g跳转到这个函数处下断点。
UINT GetDlgItemText(
HWND hDlg, //对话框的句柄,即对话框的窗口句柄
int nIDDlgItem, //要获取文本的控件标识符(ID)
LPTSTR lpString, //指向接收文本字符串的缓冲区指针
int nMaxCount //接收文本字符串缓冲区的大小,以字符为单位
);
下图的call 00401340是验证函数。
对应的代码为GenRegCode。
如果eax返回值为1,test eax, eax不会是的ZF=0,从而je不会跳转。这里不跳转的话会弹出成功的结果,所以直接将这里的跳转指令nop掉就crack成功了。
下面是对计算序列号的算法的分析,详细见注释。
看了看我发现,如果输入的用户小于4,也就是算上%00的用户名小于5,最后根本不会进入到计算序列号的函数,序列号直接为0。所以如果更改了判断用户长度的指令,那么同样可以crack成功了。如下图
这里建议自己根据汇编翻译成伪代码,以下是原版代码
/*-------------------------------------------------------------*/
/* GenRegCode - 注册算法主函数 */
/*-------------------------------------------------------------*/
BOOL GenRegCode( TCHAR *rCode, TCHAR *name ,int len)
{
int i,j;
unsigned long code=0;
for(i=3,j=0;i<len;i++,j++)
{if(j>7) j=0;
code+=((BYTE)name[i])*Table[j];
}
wsprintf(name,TEXT("%ld"),code);
if(lstrcmp(rCode, name)==0) //比较真假序列号,这里为了省事,直接比较了
return TRUE;
else
return FALSE;
}
0x02 x64dbg
实验环境
推荐使用的环境 | 备注 | |
---|---|---|
操作系统 | Windows 10 | |
编译器 | ||
编译选项 | ||
build版本 | ||
调试器 | X64DBG |
实验前准备
- 去下载书籍配套资料。
- 用X64DBG打开。
实验过程
实验和之前差不多,就随便写写了。
这里直接将两个字符串的地址,输入的code,计算好的code分别用lea指令取地址到了rdx,rcx参数中。rdx存放的是计算的也就是name,rcx是rcode输入的。应该是__fastcall调用约定。
0x03 Windbg
实验环境
推荐使用的环境 | 备注 | |
---|---|---|
操作系统 | Windows 10 | |
编译器 | ||
编译选项 | ||
build版本 | ||
调试器 | WinDBG |
实验前准备
- 去下载书籍配套资料。
- 用WinDBG打开。
实验过程
暂时留空
文章评论