寻求有关“ in_FS_OFFSET ”和“ __stack_chk_fail() ”的解释

逆向工程 反编译
2021-06-19 21:58:15

这是picoCTF 2019问题“Investigative Reversing 0”的一部分。我在使用 Ghidra 时遇到了以下代码:

  if (lVar1 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }

虽然我已经使用它作为指南完成了挑战:https : //github.com/Dvd848/CTFs/blob/master/2019_picoCTF/Investigative_Reversing_0.md

我仍然不明白这部分代码以及它的作用。经过一些更详细的搜索后,我发现分配给代码的两种数据类型:

long in_FS_OFFSET;
long lVar1;

我做了研究,将代码与 'in_FS_OFFSET' 和 '__stack_chk_fail()' 结合起来,其中大部分都作为各种 CTF 问题的解决方案文章出现。只有少数是别的东西。例如:https ://hackaday.io /project/164346-andxor-dc27-badge/log/164366-reverse-engineering-with-ghidra-simtaco-floppy-challenge

该站点有非常相似的反编译结果,所以我认为这部分代码在保护程序免受堆栈溢出方面有一定作用。我查看了站点底部的程序源代码并进行了搜索包括所有的 c 库,但我没有发现有用的提示。我回到 Ghidra,发现了这个未定义的函数:

void UndefinedFunction_00101036(void)

{
                    /* WARNING: Treating indirect jump as call */
  (*(code *)(undefined *)0x0)();
  return;
}

这个未定义的函数与我的问题有什么关系吗?如果是这样,原始代码可能是什么?提前感谢您的任何答案。

编辑:反汇编部分代码

00101380  64 48 33        XOR        sVar2,qword ptr FS:[0x28]
          04 25 28 
          00 00 00
00101389  74 05           JZ         LAB_00101390
0010138b  e8 d0 fc        CALL       __stack_chk_fail       undefined __stack_chk_fail()
          ff ff
                             -- Flow Override: CALL_RETURN (CALL_TERMINATOR)

和功能:

                        //
                        // .plt 
                        // SHT_PROGBITS  [0x1020 - 0x109f]
                        // ram: 00101020-0010109f
                        //
                        LAB_00101020            XREF[9]:     0010103b(j), 0010104b(j), 
                                                0010105b(j), 0010106b(j), 
                                                0010107b(j), 0010108b(j), 
                                                0010109b(j), 001020b4, 
                                                _elfSectionHeaders::00000310(*)  
        00101020 ff 35 6a        PUSH       qword ptr [PTR_00103f90]            = 00000000
                 2f 00 00
        00101026 ff 25 6c        JMP        qword ptr [PTR_00103f98]
                 2f 00 00

1个回答

fs:0x28 是 stack_cookie 或 stack_canary

_stk_check_fail() 是中止执行的函数

编译器在堆栈中放置一个 cookie,并在从操作堆栈的函数返回后进行检查和比较。

如果 cookie 已损坏,则不再继续执行,而是简单地终止执行

这是一种针对缓冲区溢出的强化技术,尤其是堆栈粉碎

转到编译器资源管理器

将此代码选择语言粘贴为 c
将编译器版本保留为最新
将 -fstack-protector 添加到编译器选项
并查看生成的反汇编以了解如何使用 stack_canary @ fs:0x28

#include <stdio.h>
#include <string.h>
void foo (char *str) {
    char buff[16];
    strcpy(buff,str);
}
int main(void){
    printf("test for __stack_chk_fail\n");
    foo("small str");
    printf("success\n");
    foo("A Big String is Copied to a Small Buffer");
    printf("i wont reach here if stack_chk_fail worked ");
}

上面代码的反汇编

foo:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 48
        mov     QWORD PTR [rbp-40], rdi
        mov     rax, QWORD PTR fs:40
        mov     QWORD PTR [rbp-8], rax
        xor     eax, eax
        mov     rdx, QWORD PTR [rbp-40]
        lea     rax, [rbp-32]
        mov     rsi, rdx
        mov     rdi, rax
        call    strcpy
        nop
        mov     rax, QWORD PTR [rbp-8]
        xor     rax, QWORD PTR fs:40   <<<<(40=0x28)
        je      .L2
        call    __stack_chk_fail
.L2:
        leave
        ret

显示上述评论内容的屏幕截图

在此处输入图片说明