问题
I'm writing a return to libc attack for my systems security class. First, the vulnerable code:
//vuln.c
#include <stdio.h>
#include <stdlib.h>
int loadconfig(void){
char buf[1024];
sprintf(buf, "%s/.config", getenv("HOME"));
return 0;
}
int main(int argc, char **argv){
loadconfig();
return 0;
}
I want to use a return to libc attack. Compiling and debugging the program:
$ gcc -g -fno-stack-protector -o vuln vuln.c
$ gdb vuln
(gdb) break loadconfig
(gdb) run
Reached breakpoint blah blah blah.
(gdb) p $ebp
$1 = (void *) 0xbfffefb0
(gdb) p system
$2 = {<text variable, no debug info>} 0x0016db20 <system>
(gdb) p exit
$3 = {<text variable, no debug info>} 0x001639e0 <exit>
(gdb) x/2000s $esp
...
0xbffff5af: "SHELL=/bin/bash"
To execute the attack, I want to overflow the buffer into loadconfig
's return address (aka $esp+4
), replacing it with the return address for system
, then the return address for exit
(since system
expects a real return address), then the command name (the address of SHELL=/bin/bash
plus 6, to trim the SHELL=
part). This should be possible by crafting a $HOME
environment variable of 1024 characters of crap, then the little-endian address of system
, exit
, and /bin/bash
.
However, with every computer I've tried, system
gets loaded at an address that starts with 0x00, which will null terminate the string that sprintf
is reading and stop the attack dead. Is there some way to force libc
to load elsewhere in memory, or am I misinterpreting the attack?
For reference, I'm running an Ubuntu Server 11.10 virtual machine in VirtualBox (Windows host), with gcc
version 4.6.1 and gdb
version 7.3-2011.08. edit: ASLR is disabled, and I compiled with -fno-stack-protector
to remove the canary. Since I'm not executing anything from the stack, I don't need to execstack
it.
回答1:
The act of mapping important libc function to addresses which contain a NULL byte is called ASCII armoring. This protection is part of RedHat Exec-shield which is currently enabled on recent ubuntu distros link To disable it you have to run as root:
sysctl -w kernel.exec-shield=0
as explained here
By the way you can find interesting material about how to bypass ASCII armoring here on exploit-db
回答2:
I am fairly certain that this is impossible on 11.10, at least in the ways you mention. Have a look:
https://wiki.ubuntu.com/Security/Features
In detail, and just picking some problems with your ideas:
(1) because of canary values and for other reasons, buffer Overflow into esp+4 will raise a Segmentation fault exception
(2) you probably mean to extract the address of the environmental variable, which traditionally would have been at ESP (main) + a certain number of bytes. However, as even logical memory addresses these days are scrambled/randomized after compile, you will instead get a different mememory address for your $HOME variable for each run, probably somewhere on the other side of the main stack
(3) to the best of my knowledge, there are other ways in which return from library attacks these days are thwarted. I am less familiar with those. This should be why you see x00 for the address
Hacking these days on a ubunti system is hard. If you just need to do this for a class that doesn't insist on current distros, install instead the first ubunti distro in virtualbox. Magically, all you try will work. There is no more "standard overflow attack" that you also reference - even if you cleverly bypass canary valued etc, setting the nx bit makes this impossible. And similarly, while I'm less perfectly certain about how return from libc attacks are addressed, don't rely on believing this will be possible on a current distro. Good luck!
来源:https://stackoverflow.com/questions/7779534/writing-a-return-to-libc-attack-but-libc-is-loaded-at-0x00-in-memory