如何从 .gcc_except_table 和 .eh_handle 部分恢复异常信息?

逆向工程 拆卸 部件 x86 C++ 例外
2021-07-09 07:03:13

对于已定义的C++程序try catch,当用于g++将其编译为汇编代码时(测试在 x86 32bit Linux, g++4.6.3 上)

g++ -S cppexcept.cc

一个指定的部分被称为.gcc_except_table如下产生:

        .section        .gcc_except_table
        .align 4
.LLSDA980:
        .byte   0xff
        .byte   0
        .uleb128 .LLSDATT980-.LLSDATTD980
.LLSDATTD980:
        .byte   0x1
        .uleb128 .LLSDACSE980-.LLSDACSB980
.LLSDACSB980:
        .uleb128 .LEHB3-.LFB980
        .uleb128 .LEHE3-.LEHB3
        .uleb128 0
        .uleb128 0
        .uleb128 .LEHB4-.LFB980
        .uleb128 .LEHE4-.LEHB4
        .uleb128 .L19-.LFB980
        .uleb128 0x3
        .uleb128 .LEHB5-.LFB980
        .uleb128 .LEHE5-.LEHB5
        .uleb128 0
        .uleb128 0
        .uleb128 .LEHB6-.LFB980
        .uleb128 .LEHE6-.LEHB6
        .uleb128 .L20-.LFB980
        .uleb128 0
        .uleb128 .LEHB7-.LFB980
        .uleb128 .LEHE7-.LEHB7
        .uleb128 .L21-.LFB980
        .uleb128 0

编译成exe filewithELF格式后,好像有两个部分是.gcc_except_table异常处理相关的,分别是.eh_frame

但是,我使用以下命令转储了这两部分的内容,将标签的内存地址与中定义的内容进行了比较.gcc_except_table,但对我来说似乎太模糊了......

objdump -s -j .gcc_except_table cppexcept
objdump -s -j .eh_frame cppexcept

所以我的问题是:

有没有办法.gcc_except_tableELF文件.gcc_except_tableeh_frame表格中恢复(如上所示)中定义的信息

1个回答

(我想如果你使用 ,你可能会得到一些额外的评论-fverbose-asm。)

从这些表中恢复信息绝对是可能的,尽管文档很少并且通常只出现在解析它们的代码中。

.eh_frame布局中简要介绍了LSB文件Ian Lance Taylor(黄金链接器的作者)也发表了一些关于.eh_frame.gcc_except_table布局的博文

如需更多类似参考的描述,请查看我的Recon 2012 幻灯片(从 37 左右开始)。

我做了一个IDA的脚本gcc_extab.py),它解析.eh_frame,并.gcc_except_table和格式他们很好。

采取一个示例程序:

void f()
{
    throw 1;
}

int main()
{
    int j;
    try {
        f();
    } catch (int i) {
        j = i;
    }   
    return 0;
}

我将展示 GCC 生成的注释结构。

首先,.eh_table(为清楚起见省略了某些部分):

.Lframe1:                     # start of CFI 1
    .long   .LECIE1-.LSCIE1   # length of CIE 1 data
.LSCIE1:                      # start of CIE 1 data
    .long   0                 # CIE id
    .byte   0x1               # Version
    .string "zPL"             # augmentation string:
                              # z: has augmentation data
                              # P: has personality routine pointer
                              # L: has LSDA pointer
    .uleb128 0x1              # code alignment factor
    .sleb128 -4               # data alignment factor
    .byte   0x8               # return address register no.
    .uleb128 0x6              # augmentation data length (z)
    .byte   0                 # personality routine pointer encoding (P): DW_EH_PE_ptr|DW_EH_PE_absptr
    .long   __gxx_personality_v0 # personality routine pointer (P)
    .byte   0                 # LSDA pointer encoding: DW_EH_PE_ptr|DW_EH_PE_absptr
    .byte   0xc               # Initial CFI Instructions
    [...]
    .align 4
.LECIE1:                      # end of CIE 1
    [...]

.LSFDE3:                      # start of FDE 3
    .long   .LEFDE3-.LASFDE3  # length of FDE 3
.LASFDE3:                     # start of FDE 3 data
    .long   .LASFDE3-.Lframe1 # Distance to parent CIE from here
    .long   .LFB1             # initial location                
    .long   .LFE1-.LFB1       # range length                    
    .uleb128 0x4              # Augmentation data length (z)    
    .long   .LLSDA1           # LSDA pointer (L)                
    .byte   0x4               # CFI instructions                
    .long   .LCFI2-.LFB1
    [...]
    .align 4
.LEFDE3:                      # end of FDE 3

接下来,.gcc_except_tableFDE 3 中引用的 LSDA(特定于语言的数据区)

.LLSDA1:                           # LSDA 1
    .byte   0xff                   # LPStart encoding: DW_EH_PE_omit
    .byte   0                      # TType encoding: DW_EH_PE_ptr|DW_EH_PE_absptr
    .uleb128 .LLSDATT1-.LLSDATTD1  # TType offset
.LLSDATTD1:                        # LSDA 1 action table
    .byte   0x1                    # call site encoding: DW_EH_PE_uleb128|DW_EH_PE_absptr
    .uleb128 .LLSDACSE1-.LLSDACSB1 # call site table length
.LLSDACSB1:                        # LSDA 1 call site entries
    .uleb128 .LEHB0-.LFB1          # call site 0 start
    .uleb128 .LEHE0-.LEHB0         # call site 0 length
    .uleb128 .L8-.LFB1             # call site 0 landing pad
    .uleb128 0x1                   # call site 0 action (1=action 1)
    .uleb128 .LEHB1-.LFB1          # call site 1 start
    .uleb128 .LEHE1-.LEHB1         # call site 1 length
    .uleb128 0                     # call site 1 landing pad
    .uleb128 0                     # call site 1 action (0=no action)
.LLSDACSE1:                        # LSDA 1 action table entries
    .byte   0x1                    # action 1 filter (1=T1 typeinfo)
    .byte   0                      # displacement to next action (0=end of chain)
    .align 4
    .long   _ZTIi                  # T1 typeinfo ("typeinfo for int")
.LLSDATT1:                         # LSDA 1 TTBase