general question…anyone know of good references/techniques to overcoming ASLR with a buffer overflow where the NX bit is not set?
Even if the NX bit is not set it’s probably easier to use ret2libc in these cases.
If it’s 32 bit, then you can bruteforce the libc address as it will only be at 1 of 256 positions Bypassing ASLR – Part II – sploitF-U-N
If it’s 64 bit then it becomes a bit more complicated, and you need either an information leak, or you need to utilise functions already loaded by the binary.
I don’t know if you could just place shellcode as normal and bruteforce the address but I’ve never tried that so I can’t say if it works well or not
Some of the techniques to bypass aslr
WITH executable stack are:
-
ret2libc + Bruteforcing
(x86 arch): as Booj already mentioned the easiest method is bruteforcing libc. This method is easy but has some disadvantages. It can’t be performed on x64-bit architectures and assumes that crashing the binary doesn’t have any other negative effects on the system. -
Return-Oriented-Programming
(x86 & x64 arch): this is a great method but heavily depends on the avalaibility of rop-gadgets. Sometimes is possible to find gadgets (e.g. gadgets that are located in the .text section of an ELF binary) that are not affected by aslr - so your rop chain will work either way. ROP also bypasses nx by default. -
return to PLT (ret2plt)
(x86 & x64 arch): this is the same asret2libc
but instead of invoking a function you invoke function@PLT. This method does not always work - you have to check first if function@PLT is present. Also nx doesn’t affect a ret2plt exploit. -
information leak
(x86 & x64 arch): in certain cases (use of string writing functions, format string attacks etc…) you can leak libc in runtime, so you can construct a multi-stage exploit that bypasses aslr. -
Another method that I haven’t personally tried but I suppose could work (since your stack is executable), is that you can use a very big nop-sled so that you have chances to return to your buffer=payload.
You can also find a great tutorial that demonstrates most of the above here:
I am not a pro on buffer overflows so any feedback to correct something in my answer is welcome
@game0ver that’s great and long answer, good job
@buckko thanks
Another way to use ret2libc with aslr without having to bruteforce is to learn the offset for each function we need in libc and then we find the current address for libc in our binary and then add the offset to the functions we want to use, and that will be the correct address for each function. It’s a couple extra steps but it takes the guesswork out of it and eliminates the need to bruteforce it. Very good post with great information though.
@likwidsec when aslr is enabled, libc will be different every time you execute the binary (try to enable aslr and do: ldd ./your_binary | grep libc
multiple times). So the problem with aslr is that we can’t find the current address for libc in our binary despite that the offsets remain stable.
So how are we going to know the current address of libc prior to execution ? To do that we need an information leak to leak libc in runtime and construct a multi-stage exploit.
Other techniques we can also perform are GOT overwrite and GOT dereference, as they are greatly described here: Bypassing ASLR – Part III – sploitF-U-N.
@game0ver it is different until functions which are called from it are assigned to GOT from their PLT stub. So if the binary calls a function more than once, the second time it calls it, it will make a call to the “actual” - permanent address of that function. Then from there, simple math will allow you to discover the offsets for other, more useful functions.
@likwidsec if I understand correctly the method you’re describing is like this @ippsec video of the camp-ctf-2015-bitterman challenge.
But in this way to get the actual address of the function you indeed need a leak (in ippsec’s video you leak puts function actual address), otherwise you won’t be able to compute the libc base address. Then after you compute libc it’s trivial I agree, you just have to do simple math with the offsets that are stable. But as you can see we need an information leak (in this case the puts function’s actual address).
If this method is not what you mean could you please post a reference of the method
@game0ver said:
@likwidsec if I understand correctly the method you’re describing is like this @ippsec video of the camp-ctf-2015-bitterman challenge.But in this way to get the actual address of the function you indeed need a leak (in ippsec’s video you leak puts function actual address), otherwise you won’t be able to compute the libc base address. Then after you compute libc it’s trivial I agree, you just have to do simple math with the offsets that are stable. But as you can see we need an information leak (in this case the puts function’s actual address).
If this method is not what you mean could you please post a reference of the method
I haven’t seen that particular video, but that’s the technique I’m talking about. Guess I misunderstood what you meant in the way you described “information leak” in the original post. My mistake.
Some of the techniques to bypass aslr WITH executable stack are
@game0ver thanks! great answer:)
@r2d2 thanks!
Does anyone have a link to a good video for ROP chains?
Also an excellent video for learning how to bypass ASLR using ret2libc + bruteforcing is ippsecs video walkthrough for October.
You should look into ropemporium.com, these CTFs will teach you the basics.
semi related but not…i’m trying to BOF the overflw binary in October (using ippsec’s method) but keep getting a “*** buffer overflow detected ***: /home/… terminated” As the file is already compiled i’m assuming its not -fno-stack-protector is not the solution. Any thoughts?? …thanks
Hey guys,
I am working on some buffer overflow challenge.
I build a binary it uses puts function.
ASLR is active, NX is enabled.
So how can I leak the libc base addr?
32-bit binary btw.
My payload looks like: padding + puts@plt + puts@got
But not working.
First of all, sorry for my bad english.
@fasetto im not an expert, just dealing with this stuff for first time now and i’ve only practiced with 64 bits binaries, and from my experience i think there are two problems with your payload (from my 64’s perspective).
I build the first part of my payload like this: padding + pop_rdi + got_puts + plt_puts
There are differences in call conventions between 32 and 64 bit, that’s the reason of the pop_rdi gadget in my payload.
The idea is calling plt_puts()
using the got_puts address as argument, something like that: puts([got_puts])
because [got_puts]
contains the right address of puts()
function, that allow us to calculate the offset, and with it calculate system()
address to, at end, spawn a shell.
In my study of the subject, i dealt with a binary which i tried to leak the puts()
address, and i can’t get it. Then after reading a lot of papers, i found the problem.
The [got_puts]
only contains the address i needed AFTER calling puts()
at least one time. In my case, there wasn’t any puts()
call BEFORE i try to leak the effective address, so i only was able to get a weird ‘0x0’ as the effective address.
So ¿there are any puts()
call BEFORE you inject your payload? in the legit code i mean.
To fix it, instead focus my efforts to leak puts()
address i tried to leak printf() address. Because there were calls to printf()
prior to my injection, so [got_printf]
had the right effective address when i manage to leak it.
Then my payload turned in sumthing like that: padding + pop_rdi + got_printf + plt_puts
Not sure, but this may give you a clue to solve your problem.
2 - To exploit this kind of stuff we need to craft a 2 stages exploit, because the function address we leak it’s only valid for this concrete execution, so, in the same execution we need to do two things (get the libc offset and use it to get a shell).
With your payload the execution ends with it, to illustrate what i want to explain i’ll use again my payload.
To archieve the second ‘step’ of the exploit i add to my payload an extra address that points to the vulnerable function to execute it again:
padding + pop_rdi + got_printf + plt_puts + vuln_addr
In some point of vuln() function you inject your payload, that leaks printf address
With this you calculate the libc offset, and with it, calculate system()
address
You need to locate /bin/sh
string too, to craft the system()
call that spawns shell
With this you’ll craft a second payload in the stage 2
But don’t forget you need to do all this stuff in the SAME BINARY EXECUTION, so you need a way to keep the program running and a way to inject and execute your second payload.
i’ll try to represent it with a diagram to explain what you can do.
1st stage:
vuln() {
.
. <-----------------------------( jump to vuln() again ) --------- +
. |
. <= [inject 1st payload] - (leak printf addr) - (calc offset) - - +
.
}
So execution will arrive again to the vuln point where we inject the 1st payload, and this time do the same but using 2nd payload
2nd stage:
vuln() {
.
.
.
. <= [inject 2nd payload at same point] - - - > spawn a shell
.
}
Not sure if this is 100% true or correct, but it’s the way i understand how it’s going there.
I hope you found it usefull and help you to adapt it to 32bits case and finally reach your objective.
If some expert read this, and found it useless, wrong or directly offensive xD just let me now and i will be happy to correct it or just throw it to garbage.
@rulzgz That was a few months ago, I solved my problem.
I don’t remember it now. I am pretty good at binary exploitation now.
Read your comment, it will help a lot of people I guess…
Thanks.
@fasetto said:
@rulzgz That was a few months ago, I solved my problem. > I don’t remember it now. I am pretty good at binary exploitation now.
I don’t remember it now. I am pretty good at binary exploitation now.
Oops, sorry, my fault… i didn’t notice the post’s date
Btw is good to hear that you found a solution and have improved your skills
Read your comment, it will help a lot of people I guess…
Thanks.