这个CrackMe的整体思路是想通过异常来打断程序的正常流程,以达到迷惑的目的!
代码是用VC8来完成的!
首先是按钮事件的触发:
case IDC_REGISTER:
{
TCHAR szContent[1024];
memset(szContent,0,1024);
for(int i=0;info1[i];i++)
szContent[i]=info1[i]^0x78;
TCHAR szT[128];
memset(szT,0,128);
for(int i=0;szTitle[i];i++)
szT[i]=szTitle[i]^0x78;
int nRet=GetDlgItemText(hDlg,IDC_USERNAME,strName,STR_LEN);
if(nRet<5){
MessageBox(NULL,szContent,szT,MB_OK);
return TRUE;
}
memset(szContent,0,1024);
for(int i=0;info2[i];i++)
szContent[i]=info2[i]^0x78;
nRet=GetDlgItemText(hDlg,IDC_PWD,strCode,STR_LEN);
if(nRet!=16){
MessageBox(NULL,szContent,szT,MB_OK);
return TRUE;
}
__try{
_asm int 3
}
__except(EXCEPTION_BREAKPOINT==GetExceptionCode()){
SendMessage(hDlg,IAWEN_VERIFY,0,0);
}
}
return TRUE;
在这个事件中,我只是做一个简单的判断与验证是否符合要求!
其关键的地方是这里:
__try{
_asm int 3
}
__except(EXCEPTION_BREAKPOINT==GetExceptionCode()){
SendMessage(hDlg,IAWEN_VERIFY,0,0);
}
通过人为的int3异常,跳转到了一个自定义的消息里,然后再转向真实的验证地址,当然我们还可以在这里玩更多的花样,呵呵!
case IAWEN_VERIFY:
RegistMyCrackMe(hDlg);
return TRUE;
2、在真实的验证函数里,同样也利用到了异常来强行改变程序的流程:
__try{
_asm int 3
_asm int 3
}
__except(GetExceptionCode() == EXCEPTION_BREAKPOINT)
{
if((dwCode1==dwHash2-0x1234567) &&(dwCode2==dwHash1+0x0123456)){
memset(szContent,0,1024);
for(int i=0;info4[i];i++)
szContent[i]=info4[i]^0x78;
SendMessage(GetDlgItem(hDlg,IDC_USERNAME),EM_SETREADONLY,(WPARAM)TRUE,0);
SendMessage(GetDlgItem(hDlg,IDC_PWD),EM_SETREADONLY,(WPARAM)TRUE,0);
SetWindowText(hDlg,szContent);
}
}
这里将最后的判断再次强行转换了个位置!
3、同时,为了增加一些难度,增加了一个线程来反对在关键的函数(验证函数RegistMyCrackMe(hDlg)):
[codes]
BOOL WINAPI VerifyPro(LPVOID lParam){
const BYTE *dwAddr=(BYTE*)RegistMyCrackMe;
while(1){
for(int i=0;;i++){
if(*(dwAddr+i) == 0xCC)
{
if( *(dwAddr+i+1)!=0xCC)
ExitProcess(0);
else
break;
}
}
Sleep(50);
}
return TRUE;
}
首先获取验证函数的首地址,然后逐位判断是否等于0xCC,即int3中断,在OD等调试器里,也就是一般的F2断点。所以如果在跟踪程序时,如果在该函数里下F2断点的话,运行的话的,都将自动退出!
下载源码:
CrackMe.8.rar