《脱壳艺术》学习笔记2--SEH检测调试器

 
《脱壳艺术》学习笔记 2
时间: 2008 2 22 星期五, 10 5 35
 
SEH 检测调试器
 
新建 vc++ Console 项目 , 编写下面代码测试 :
int main()
{
 bool bIsInDebugger = true ;
 
 try{
   // 非法内存访问 , 会引发异常    
   int *p = NULL;
   *p = 0;
 }catch(...)
 {
    // 对异常进行处理
    // 如果应用程序接管异常 , 我们认为当前程序没有被调试
    bIsInDebugger = false ;
 }
 
 if ( bIsInDebugger == true )
 {
    exit();
 }else
 {
    cout<<"Hello World"<<endl;  
 }
 
 return 0;
}
 
检测调试器的原理是 :
当被调试进程出现异常时,该异常通常被调试器接管。这样应用程序自己设置的异常处理函数就得不到执行。我们可以利用这一点在异常处理例程中设置标志变量达到检测的目的。
 
实际调试过程中发现 : try 语句中给 0x00000000 地址赋值的操作导致内存访问违规 , 应用程序弹出下面窗口
《脱壳艺术》学习笔记2--SEH检测调试器_第1张图片

连续试了几次都是这样, 可能没有执行SEH处理? 分析反汇编代码没有发现什么特别的地方.

回想以前用VC 6.0 的时候,异常处理可以捕获这个异常并很好的处理.

思考了一会,我觉得可能和项目属性设置有关,

查看了 [配置属性]-->[C/C++]-->代码生成-->启用C++异常中的设置  这里的设置为"", 更改为",但有SEH异常"

再次调试上面代码运行 OK.

 

实际加壳部分的 SEH 是用汇编写的:

分析 《脱壳艺术》中的代码

//----------设置异常处理----------

// 异常处理函数地址

push     .exeception_handler

// 指向先前SEH结构体的地址, 现在它作为下一个异常处理函数

push     dword [fs:0]                

//使 fs:[0]指向刚添加SEH结构地址,当出现异常时 exeception_handler 首先得到处理

mov           [fs:0],esp

      

;reset flag(EAX) invoke int 3

xor       eax,eax // 设置初始标志

int 3             // 引发异常

 

;restore exception handler

pop       dword [fs:0]

add       esp,4

 

; check if the flag had been set

test     eax,eax

je        .debugger_found

:::

// 异常处理函数

.exeception_handler:

;EAX = ContextRecord

mov       eax,[esp+0xc]

;set flag (ContextRecord.EAX)

mov       dword [eax+0xb0],0xffffffff

;set ContextRecord.EIP

inc       dword [eax+0xb8]

xor       eax,eax

 retn

 

push    .exeception_handler

push    dword [fs:0]

mov         [fs:0],esp

3 条汇编语句可以用下面结构图表示.

《脱壳艺术》学习笔记2--SEH检测调试器_第2张图片

                                             简单的 SEH

 

你可能感兴趣的:(C++,exception,汇编,测试,null,vc++)