MD5
MD5属于单向散列算法,加密原理和过程网上都有,再次不再赘述。
但就从逆向工程的角度来看, MD5最显著的特征莫过于他有4个常数用来初始化。因此,在判断加密算法时需要注意是否具有64个常量元素的表(而不是通过四个常数)来判断,MD5常见的变种有3种
1.改变初始话的4个常数
2.改变填充的方法
3.改变Hash变化的处理过程
对是否使用MD5加密需要依靠以上三个方法进一步判断
一段反汇编代码实列
首先,我设置的断点是在调用了GetDlgItemTextA处,也就是输入了用户名和注册码后。在图中明显可以看出0040118B处程序已经获得了用户输入的注册码,下一步自然是对输入的注册码进行进一步的判断。此时可以注意到下面多处调用了jnz判断语句,进一步跟踪,得到
也就是说明前面三个是注册码的基本判断条件,见下图
此时可以得出注册码的格式为xxxx-xxxx-xxxx-xxxx
然后,在下面的004011E0处又有一个调用函数,跟进,如下图
很明显这可能是进行MD5初始化。当然,为了进一步继续验证向下跟进
可以发现,在下面00401203处进行了字符填充
在跟进下面所调用的call函数后,在下面又发现了正弦函数表此时可以断定就是MD5算法了
这是接下来的图在00401236处,这里开始对输入进行了一次处理,然后和MD5计算出来的序列进行比较,再进行strcmp比较两个注册码,这个分析就结束了。
可以干的事情
1.暴力跳转,直接跳过注册
2.分析反汇编,知道了加密算法也知道处理步骤就可以写注册机了
附上程序源码
程序的加密函数:
/*-------------------------------------------------------------*/
/* MD5Hash - MD5计算主函数 */
/*-------------------------------------------------------------*/
BOOL CheckSerial(HWND hWnd)
{
MD5_CTX context;
long dtLength,lsLength;
int i;
TCHAR szName[MAXINPUTLEN]={0};
TCHAR szHash[MAXINPUTLEN]={0};
TCHAR szBuffer[MAXINPUTLEN]={0};
TCHAR szSerial[MAXINPUTLEN]={0};
TCHAR szTeam[]="www.pediy.com";
TCHAR szSNtemp[20]={0};
TCHAR szBase32[]="23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
unsigned int tcTemp=0;
dtLength=GetDlgItemText(hWnd, IDC_Name, szName, sizeof(szName)/sizeof(TCHAR)+1);
if (dtLength==0)
{
SetDlgItemText(hWnd, IDC_Serial, "Wrong Serial!");
return FALSE;
}
lsLength=GetDlgItemText(hWnd,IDC_Serial,szSerial,sizeof(szSerial)/sizeof(TCHAR)+1);
if (lsLength!=19)
{
SetDlgItemText(hWnd,IDC_Serial,"Wrong Serial!");
return FALSE;
}
if ((szSerial[4]!='-')||(szSerial[9]!='-')||(szSerial[14]!='-'))
{
SetDlgItemText(hWnd,IDC_Serial,"Wrong Serial!");
return FALSE;
}
memcpy(szSNtemp,szSerial,4);
memcpy((szSNtemp+4),(szSerial+5),4);
memcpy((szSNtemp+8),(szSerial+10),4);
memcpy((szSNtemp+12),(szSerial+15),4);
MD5Init(&context);
MD5Update(&context,szName,dtLength);
MD5Update(&context,szTeam,lstrlen(szTeam));
MD5Final(szHash, &context);
for(i=0;i<16;i++)
{
tcTemp=(unsigned int)szHash[i]%32;
szBuffer[i]=szBase32[tcTemp];
}
if (lstrcmp(szSNtemp,szBuffer)==0)
{
SetDlgItemText(hWnd,IDC_Serial,"Success!");
return TRUE;
}
else
{
SetDlgItemText(hWnd,IDC_Serial,"Wrong Serial!");
return FALSE;
}
return TRUE;
}
注册机解密函数:
/*-------------------------------------------------------------*/
/* MD5Hash - MD5计算主函数 */
/*-------------------------------------------------------------*/
BOOL GenerateSerial(HWND hWnd)
{
MD5_CTX context;
long dtLength;
int i;
TCHAR szName[MAXINPUTLEN]={0};
TCHAR szHash[MAXINPUTLEN]={0};
TCHAR szBuffer[MAXINPUTLEN]={0};
TCHAR szTeam[]="www.pediy.com";
TCHAR szBase32[]="23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
TCHAR szSerial[20]={0};
unsigned int tcTemp=0;
dtLength=GetDlgItemText(hWnd, IDC_Name, szName, sizeof(szName)/sizeof(TCHAR)+1);
if (dtLength==0)
{
SetDlgItemText(hWnd, IDC_Serial, "please input name");
return FALSE;
}
MD5Init(&context);
MD5Update(&context, szName, dtLength);
MD5Update(&context,szTeam,lstrlen(szTeam));
MD5Final(szHash, &context);
for(i=0;i<16;i++)
{
tcTemp=(unsigned int)szHash[i]%32;
szBuffer[i]=szBase32[tcTemp];
}
memcpy(szSerial,szBuffer,4);
szSerial[4]='-';
memcpy((szSerial+5),(szBuffer+4),4);
szSerial[9]='-';
memcpy((szSerial+10),(szBuffer+8),4);
szSerial[14]='-';
memcpy((szSerial+15),(szBuffer+12),4);
SetDlgItemText(hWnd, IDC_Serial,szSerial);
return TRUE;
}
小结
1.楼主笔记而已,不严谨之处可以指出。
2.大概这个寒假还会慢慢写233,可以一起学习。
3.都看到这里了,不点个赞再走?0.0