微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在不链接 libc.so 的情况下访问段寄存器?

如何解决如何在不链接 libc.so 的情况下访问段寄存器?

我正在尝试在 Ubuntu 20.10 上使用 NASM 2.15.04 版在 64 位程序集中编写一个简单的堆栈金丝雀。使用命令 nasm -felf64 canary.asm && ld canary.o 进行组装和链接时,执行以下代码会导致分段错误

            global  _start

            section .text
_start:     endbr64
            push    rbp                     ; Save base pointer
            mov     rbp,rsp                ; Set the stack pointer
            call    _func                   ; Call _func
            mov     rdi,rax                ; Save return value of _func in RDI
            mov     rax,0x3c               ; Specify exit syscall 
            syscall                         ; Exit

_func:      endbr64
            push    rbp                     ; Save the base pointer
            mov     rbp,rsp                ; Set the stack pointer
            sub     rsp,0x8                ; Adjust the stack pointer
            mov     rax,qword fs:[0x28]   ; Get stack canary
            mov     qword [rbp - 0x8],rax  ; Save stack canary on the stack
            xor     eax,eax                ; Clear RAX
            mov     rax,0x1                ; Specify write syscall
            mov     rdi,0x1                ; Specify stdout
            mov     rsi,msg                ; Char* buffer to print
            mov     rdx,0xd                ; Length of the buffer
            syscall                         ; Write msg
            mov     rax,qword [rbp - 0x8]  ; Retrieve the stack canary
            xor     rax,qword fs:[0x28]    ; Compare to original value    
            je      _return                 ; Jump to _return if canary matched original
            xor     eax,0x1                ; Specify write syscall 
            mov     rdi,stack_fail         ; Char* buffer to print
            mov     rdx,0x18               ; Length of the buffer 
            syscall                         ; Write stack_fail
            mov     rax,0x3c               ; Specify exit syscall
            mov     rax,0x1                ; Specify error code 1    
            syscall                         ; Exit

_return:    xor     eax,eax                ; Set return value to 0
            add     rsp,0x8                ; Reset stack pointer
            pop     rbp                     ; Get original base pointer
            ret                             ; Return 

            section .data
msg:        db      "Hello,World",0xa,0x0
stack_fail  db      "Stack smashing detected",0x0

使用 GDB 调试显示分段错误发生在第 16 行:mov rax,qword fs:[0x28]

─────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
     0x40101b <_func+4>        push   rbp
     0x40101c <_func+5>        mov    rbp,rsp
     0x40101f <_func+8>        sub    rsp,0x8
 →   0x401023 <_func+12>       mov    rax,QWORD PTR fs:0x28
     0x40102c <_func+21>       mov    QWORD PTR [rbp-0x8],rax
     0x401030 <_func+25>       xor    eax,eax
     0x401032 <_func+27>       mov    eax,0x1
     0x401037 <_func+32>       mov    edi,0x1
     0x40103c <_func+37>       movabs rsi,0x402000
─────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1,Name: "a.out",stopped 0x401023 in _func (),reason: SIGSEGV

然而,通过 nasm -felf64 canary.asm && ld canary.o -lc -dynamic-linker /usr/lib64/ld-linux-x86-64.so.2 组装和动态链接 libc 会导致执行成功,不再导致分段错误

使用 Radare2 比较最终的二进制文件表明,两个版本都以相同的方式组装了问题指令:

0x00401023 64488b042528. mov rax,qword fs:[0x28]

这两种情况下的 GDB 也显示该指令执行时 FS 寄存器为 0x0000。

因此,无论二进制文件是否与 libc 链接并且代码没有使用来自 libc 的外部符号,指令字节和 FS 寄存器都是相同的。为什么链接 libc 会导致执行成功,而不链接 libc 会导致分段错误?是否有可能和/或如何在不链接 libc 的情况下实现这一点?

注意:本示例中堆栈金丝雀的相关性或需求不是问题的重点。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。