定位异常处理函数
示例代码
#include <iostream>
#define INTTYPE 0
#define FLOATTYPE 1
#define DOUBLETYPE 2
#define CHARPTRTYPE 3
#define CHARTYPE 4
#define INTPTRTYPE 5
using namespace std;
int main(int argc)
{
try
{
switch (argc)
{
case INTTYPE:
{
throw (int)argc;
break;
}
case FLOATTYPE:
{
throw (float)argc;
break;
}
case DOUBLETYPE:
{
throw 5.8;
break;
}
case CHARPTRTYPE:
{
throw (char*)&argc;
break;
}
case CHARTYPE:
{
throw (char)&argc;
break;
}
case INTPTRTYPE:
{
throw &argc;
break;
}
default:
char* ptr = NULL;
throw ptr;
break;
}
}
catch (int nNumber)
{
std::cout << "错误" << nNumber << std::endl;
}
catch (char* szBuff)
{
std::cout << "错误" << szBuff << std::endl;
}
catch (float fNumber)
{
std::cout << "错误" << fNumber << std::endl;
}
catch (double dblNumber)
{
std::cout << "错误" << dblNumber << std::endl;
}
catch (char cTemp)
{
std::cout << "错误" << cTemp << std::endl;
}
catch (...)
{
std::cout << "错误" << "Unknown" << std::endl;
}
}
定位异常处理函数
1.找到SEH异常处理回调
- 一般在函数起始的位置
2.找到异常处理函数查表的位置,下断点,断点来的时候单步步入
3.接着根据以下定则下断点跟踪(中间需要跟进7层)
- 找参数最多的call下断点
- 参数一样则选第二个
- 最后一层是call 寄存器(eax)
IDA静态分析SEH链
异常数据关系表
还原异常处理结构(上半部分表)
1函数开头进入SEH链
2.找到异常函数信息结构体
3.分析数据关系
- 第一个表记录了该函数有几个try,以及对应的catch块信息表指针数组
- 第二个表记录了该函数有try对应的catch表,以及对应的catch函数指针数组
- 第三个表为每个catch函数的地址
还原具体的异常处理代码(下半部分表)
1.找到函数内抛异常的函数,参数内找异常信息表
2.找到catch表 image
3.表内记录了该异常类型匹配的catch个数和catch信息表 image
4.catch信息表内找到对应的catch类型表 image
5.找到类型表,对类型表做一个交叉引用,根据引用类类型表,则能找到catch的函数地址 image
补充
1.如果是抛出的异常是类对象的话
2.编译器会根据抛出异常的子父类关系生成catch函数指针数组
子类优先,父类次之