SEH用于反调试或者用于注册码的隐藏时。在没有异常时永远都是错误的注册码,只有当触发异常时,程序才走到注册成功的地方……
代码如下:
void CSehDlg::RegSuc()
{
HWND hWnd = ::GetDlgItem(NULL, IDC_STC_TIP);
::SetWindowText(hWnd, "Success!!");
}
void CSehDlg::RegFail()
{
HWND hDlgWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
HWND hWnd = ::GetDlgItem(hDlgWnd, IDC_STC_TIP);
::SetWindowText(hWnd, "Failed!!");
}
void FirstLevelSeh(char chFlag)
{
__try
{
INT a = chFlag;
int b = a/0;
}
//定义异常处理模块
__except(EXCEPTION_EXECUTE_HANDLER)
{
HWND hDlgWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
HWND hWnd = ::GetDlgItem(hDlgWnd, IDC_STC_TIP);
::SetWindowText(hWnd, "Success!!");
}
}
void CSehDlg::OnReg()
{
// TODO: Add your control notification handler code here
CString strName;
CString strCode;
GetDlgItemText(IDC_EDT_USERNAME, strName);
GetDlgItemText(IDC_EDT_USERCODE, strCode);
TCHAR chFlag = strName.GetAt(strName.GetLength()-1);
if (chFlag == '0')
{
FirstLevelSeh(chFlag);
}
else
{
RegFail();
}
}
在这种情况下,在IDA中,如果姓名最后一位是0的话,程序会是个怎样的图形呢?
如上图所示的,在处理函数中IDA中的显示会有三个不同的函数头……而最右边成功时,是独立出来的。看起来好像在任何情况下都无法到达成功…………
在OD中程序又会是这个样子的……
进入这个有异常处理的函数401542后,是这个样子的……
上面代码中的
xor ecx, ecx
idiv ecx
会触发异常,程序就会跳到函数头时注册的异常处理函数中执行(就是在0040154C处注册的地方)……。
如果我们在调试到这个处理函数时,没有在异常处理函数中下断,在F7走到idiv ecx时,程序就会运行到系统领空,也就是程序跑飞了…………
解决方法:
所以如果要想走到正常的流程中,在这个函数头运行到0040154C的下一行代码是,在它的处理函数(00401c70处)上下断,就能把程序断下……
编译好的程序下载