---
# System prepended metadata

title: Windows SEH 機制探索
tags: [security]

---

---
title: Windows SEH 機制探索
tags: security
lang: zh_tw
---

# Windows SEH 機制探索
[TOC]


# Source Code
```cpp
#include <Windows.h>
#include <stdio.h>

// 异常处理器: 由关键字 __try 和 __except 构成
// 如果 __try 中产生了异常，会执行过滤表达式中的内容
// 应该在过滤表达式提供的过滤函数中处理想要处理的异常

// 异常过滤表达式中最常见的情况就是编写一个异常过滤函数，对异常进行处理
DWORD ExceptionFilter(DWORD ExceptionCode, PEXCEPTION_POINTERS ExceptionInfo)
{
    printf("ExceptionCode: %X\n", ExceptionCode);

    // 如果当前产生的异常是除零异常，那么就通过修改寄存器处理异常
    if (ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO)
    {
        // 在这里对寄存器执行的所有修改都会直接被应用到程序中
        ExceptionInfo->ContextRecord->Eax = 1;
        ExceptionInfo->ContextRecord->Ecx = 1;

        // 如果异常被处理了，那么就返回重新执行当前的代码
        return EXCEPTION_CONTINUE_EXECUTION;
    }

    // 如果不是自己能够处理的异常，就不处理只报告
    return EXCEPTION_EXECUTE_HANDLER;
}

int main()
{
    int number = 0;

    __try
    {
        // __try 中的是可能产生异常的代码
        // idiv eax, ecx
        number /= 0;
    }

    // 通常会为异常过滤表达式提供一个异常处理函数用于处理异常，并返回处理结果
    // GetExceptionCode: 用于获取异常的类型，能在过滤表达式和异常处理器中使用
    // GetExceptionInformation: 用于获取异常的信息，只能写在过滤表达式中

    // 异常过滤表达式
    __except (ExceptionFilter(GetExceptionCode(), GetExceptionInformation()))
    {
        // 异常处理器，只有 __except 返回 EXCEPTION_EXECUTE_HANDLER 才会执行
        printf("__try 中产生了异常，但是并没有处理异常 %X\n", GetExceptionCode());
    }

    printf("numebr = %d\n", number);

    return 0;
}
```
* 來自 https://zhuanlan.zhihu.com/p/103258431

# Dynamic Analyze (32-bit)
![](https://i.imgur.com/Rzx5VVX.png)

```
; 取得當前 Thread TIB (Thread Information Block)
mov eax, dword ptr fs:[0]
```

* TEB 的開頭存著 TIB 位址
* fs:\[0\] 也存著 TIB 位址
* TIB 結構如下

```c
typedef struct _NT_TIB {
     struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;

     PVOID StackBase;
     PVOID StackLimit;
     PVOID SubSystemTib;

     union {
         PVOID FiberData;
         DWORD Version;
     };
 
     PVOID ArbitraryUserPointer;
     struct _NT_TIB *Self;
} NT_TIB;
```

```
lea eax, dword ptr ss:[ebp-10]
mov dword ptr fs:[0], eax
```

* 從 function 的開頭來看, stack 長相如下

| Register | Address | Value |
| -------- | -------- | -------- |
|          | ... | ... |
|          | ebp - 10 | TIB address |
|          | ebp - c | seh_test.391133 |
|          | ebp - 8 | seh_test.392548 |
|          | ebp - 4 | 0xFFFFFFFE |
| ebp ->   | ebp - 0 | old ebp value |

* 將新的 \_EXCEPTION_REGISTRATION_RECORD  填入 TIB, 位址是 ebp - 10
* \_EXCEPTION_REGISTRATION_RECORD  結構如下

```c
typedef struct _EXCEPTION_REGISTRATION_RECORD {
     struct _EXCEPTION_REGISTRATION_RECORD *Prev;
     PEXCEPTION_ROUTINE Handler;
} EXCEPTION_REGISTRATION_RECORD;
```

* VC 將其擴展成以下

```c
struct VC_EXCEPTION_REGISTRATION
{
     VC_EXCEPTION_REGISTRATION* prev;
     FARPROC                    handler;
     scopetable_entry*          scopetable;
     int                        _index;
     DWORD                      _ebp;
}
```

* 對應一下
    * Prev: TIB address
    * Handler: seh_test.391133
    * scopetable: seh_test.392548
    * \_index: 0xFFFFFFFE
    * \_ebp: old ebp value
* 現在來看一下 Handler 程式碼

![](https://i.imgur.com/0GxnG6S.png)

* 最終是呼叫到 vcruntime140.dll!_except_handler4_common
* 看一下 scopetable

![](https://i.imgur.com/c12pJ6F.png)

* 其結構如下

```c
struct _EH4_SCOPETABLE {
DWORD GSCookieOffset;
DWORD GSCookieXOROffset;
DWORD EHCookieOffset;
DWORD EHCookieXOROffset;
_EH4_SCOPETABLE_RECORD ScopeRecord[];
};
```

* 推估是以 ScopeRecord.EnclosingLevel 和 \_index 去比對說是否為對應的 except 區塊, HandlerFunc 回傳值決定了是否會再繼續往下個 \_EH4_SCOPETABLE (scopetable_entry) 尋找
* 4种返回值及含义
    1. ExceptionContinueExecution(0)：回调函数处理了异常，可以从异常发生的指令处重新执行。
    2. ExceptionContinueSearch(1)：回调函数不能处理该异常，需要要SEH链中的其他回调函数处理。
    3. ExceptionNestedException(2)：回调函数在执行中又发生了新的异常，即发生了嵌套异常
    4. ExceptionCollidedUnwind(3)：发生了嵌套的展开操作
* 可以看到第一個 scopetable_entry 的 FilterFunc 和 HandlerFunc 對應原始碼的程式

![](https://i.imgur.com/kpfV3Ch.png)

![](https://i.imgur.com/kkKp7Ms.png)


# Reference
* https://www.hexblog.com/wp-content/uploads/2012/06/Recon-2012-Skochinsky-Compiler-Internals.pdf
* https://www.cnblogs.com/yilang/p/11233935.html
* https://zh.wikipedia.org/wiki/%E7%BB%93%E6%9E%84%E5%8C%96%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86