Disabling Buffer overflow protections
When it is time to scan a program for vulnerabilities or just exploit them under GNU / Linux, there are two simple protections that you should keep in mind when it comes to systems with Kernels version 2.6 and higher , and over all if compiled with GCC. There are more protections such as the patch grsecurity or exec-shield (of which I may speak later), even there is protection from hardware called StackGuard .
Virtual Address Space Randomization
The first protection is the creation of random virtual address space in the process , which change with each invocation of the process. By changing this, exploits created for absolute addresses (bone, constants) would be obsolete since they change the addresses with each execution of the program and its libraries in a range of 8MB. This applies only to ELF (Executable and Linkable Format) binaries .
The method to enable and disable it is simple, I will demonstrate the change of addresses in memory with the following code:
Code: C ++
#include <stdio.h>
unsigned long esp ( void ) {
_asm_ ( "movl% esp,% eax" ) ;
}
int main ( int argc, char * argv ) {
printf ( "0x% 08x \ n " , esp ( ) ) ;
return 0 ;
}
--------------------------------------------------------------------
This code would give me the exact address of ESP at the time of execution. Now with this code we are going to test the protection in itself of the kernel in question. The system file that controls this option is located in / proc / sys / kernel / randomizevaspace (only manipulated by a superuser or root ) and we could say that it is controlled by a TRUE (1) or FALSE (0). Then, let's try:
Code: Text
mohamed @ mohamed -desktop: ~ / Desktop $ cat / proc / sys / kernel / randomizevaspace
1
mohamed @ mohamed -desktop: ~ / Desktop $ cat> esp.c << END
> #include <stdio.h>
>
> unsigned long esp (void) {
> _asm _ ("movl% esp,% eax");
>}
>
> int main (int argc, char * argv ) {
> printf ("0x% 08x \ n", esp ());
> return 0;
>}
>
> END
mohamed @ mohamed -desktop: ~ / Desktop $ gcc esp.c -o esp
mohamed @ mohamed -desktop: ~ / Desktop $ ./esp
0xbfef2448
--------------------------------------------------------------------------------------------------------------
By enabling this "patch" we can see that the addresses are changing and making it almost impossible to know the virtual address of ESP (in this case ..) until the moment of execution. Now let's disable this function and let's see what happens:
Code: Text
root @ mohamed -desktop: ~ # echo 0> / proc / sys / kernel / randomizevaspace
...
mohamed @ mohamed -desktop: ~ / Desktop $ cat / proc / sys / kernel / randomizevaspace
0
mohamed @ mohamed -desktop: ~ / Desktop $ ./esp
0xbffff558
mohamed @ mohamed -desktop: ~ / Desktop $ ./esp
0xbffff558
mohamed @ mohamed -desktop: ~ / Desktop $ ./esp
0xbffff558
mohamed @ mohamed -desktop: ~ / Desktop $
------------------------------------------------------------------------------------------------------------------
After disabling the patch we can see that the address of ESP is constant in the executable, without even recompiling it!
But do not be frightened, as history has taught us! Behind every security system is someone trying to break it .. 1
GCC StackGuard (ProPolice) Protection
Well, this is a security protection implemented in the ultra renoted compiler and found in every GNU / Linux distribution, I speak of GCC (GNU Compiler Collection) . This compiler comes with a protection system called "StackGuard" developed by Immunix and now called ProPolice 2. This protection detects a buffer overflow attack (always on the stack) by creating a value called "Canary" between the created buffers and the frame pointer (EBP) & "return address" (EIP), then when a buffer attempts overwriting these values ??must in one way or another overwrite the value "Canary" and this serves as a trigger for protection that gives an alert and takes action against it, for example, stopping the process.
Well, let's see how it reacts to a simple overflow like this:
Code: C ++
#include <stdio.h>
#include <string.h>
void overflow ( char * badbeef ) {
char buffer 32 ;
strcpy ( buffer, badbeef ) ;
}
int main ( int argc, char * argv ) {
overflow ( argv 1 ) ;
return 0 ;
}
--------------------------------------------------------------------------------------
As we see, there is a 32-byte buffer and not a single check when doing the string copy to the buffer. We already know that we have 32 bytes of buffer + EBP + EIP, but if the protection is enabled we would not allow or pass the frame pointer:
Code: Text
mohamed @ mohamed-desktop: ~ / Desktop $ cat> vulnerable.c << END
> #include <stdio.h>
> #include <string.h>
>
> void overflow (char * badbeef) {
> char buffer 32;
> strcpy (buffer, badbeef);
>}
>
> int main (int argc, char * argv ) {
> overflow (argv 1);
> return 0;
>}
>
> END
mohamed @ mohamed-desktop: ~ / Desktop $ gcc vulnerable.c -o vulnerable
mohamed@ mohamed-desktop: ~ / Desktop $ ./vulnerable $ (perl -e 'print "A" x32')
mohamed @ mohamed-desktop: ~ / Desktop $ ./vulnerable $ (perl -e 'print' A "x36 # EBP ')
* stack smashing detected *: ./vulnerable terminated
========= Backtrace =========
/lib/tls/i686/cmov/libc.so.6(_fortify_fail+0x48)0xb7f69138
/lib/tls/i686/cmov/libc.so.6(_fortify_fail+0x0)0xb7f690f0
./vulnerable0x80483fe
./vulnerable0x8048421
0x41414141
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:02 534536 / home /mohamed/ Desktop / vulnerable
08049000-0804a000 rw-p 00000000 08:02 534536 / home / mohamed / Desktop / vulnerable
0804a000-0806b000 rw-p 0804a000 00:00 0 heap
b7e70000-b7e7a000 r-xp 00000000 08:02 197220 /lib/libgcc_s.so.1
b7e7a000-b7e7b000 rw-p 0000a000 08:02 197220 /lib/libgcc_s.so.1
b7e7b000-b7e7c000 rw-p b7e7b000 00:00 0
b7e7c000-b7fc5000 r-xp 00000000 08:02 1425929 /lib/tls/i686/cmov/libc-2.7.so
b7fc5000-b7fc6000 r-p 00149000 08:02 1425929 /lib/tls/i686/cmov/libc-2.7.so
b7fc6000-b7fc8000 rw-p 0014a000 08:02 1425929 /lib/tls/i686/cmov/libc-2.7.so
b7fc8000-b7fcb000 rw-p b7fc8000 00:00 0
b7fe1000-b7fe3000 rw-p b7fe1000 00:00 0
b7fe3000-b7fe4000 r-xp b7fe3000 00:00 0 vdso
b7fe4000-b7ffe000 r-xp 00000000 08:02 196676 /lib/ld-2.7.so
b7ffe000-b8000000 rw-p 00019000 08:02 196676 /lib/ld-2.7.so
bffeb000-c0000000 rw-p bffeb000 00:00 0 stack
Cancelled
mohamed @ mohamed-desktop: ~ / Desktop $ ./vulnerable $ (perl -e 'print' A 'x44 # EIP')
* stack smashing detected *: ./vulnerable terminated
========= Backtrace =========
/lib/tls/i686/cmov/libc.so.6(_fortify_fail+0x48)0xb7f69138
/lib/tls/i686/cmov/libc.so.6(_fortify_fail+0x0)0xb7f690f0
./vulnerable0x80483fe
0x41414141
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:02 534536 / home / mohamed / Desktop / vulnerable
08049000-0804a000 rw-p 00000000 08:02 534536 / home / mohamed / Desktop / vulnerable
0804a000-0806b000 rw-p 0804a000 00:00 0 heap
b7e70000-b7e7a000 r-xp 00000000 08:02 197220 /lib/libgcc_s.so.1
b7e7a000-b7e7b000 rw-p 0000a000 08:02 197220 /lib/libgcc_s.so.1
b7e7b000-b7e7c000 rw-p b7e7b000 00:00 0
b7e7c000-b7fc5000 r-xp 00000000 08:02 1425929 /lib/tls/i686/cmov/libc-2.7.so
b7fc5000-b7fc6000 r-p 00149000 08:02 1425929 /lib/tls/i686/cmov/libc-2.7.so
b7fc6000-b7fc8000 rw-p 0014a000 08:02 1425929 /lib/tls/i686/cmov/libc-2.7.so
b7fc8000-b7fcb000 rw-p b7fc8000 00:00 0
b7fe1000-b7fe3000 rw-p b7fe1000 00:00 0
b7fe3000-b7fe4000 r-xp b7fe3000 00:00 0 vdso
b7fe4000-b7ffe000 r-xp 00000000 08:02 196676 /lib/ld-2.7.so
b7ffe000-b8000000 rw-p 00019000 08:02 196676 /lib/ld-2.7.so
bffeb000-c0000000 rw-p bffeb000 00:00 0 stack
Cancelled
-------------------------------------------------------------------------------------------------------------------------------------
DETECTED! If we analyze more closely this ./vulnerable0x80483ef , that address tells us at what time the program executes the buffer overflow:
Code: Text
mohamed@ mohamed-desktop: ~ / Desktop $ gdb -q vulnerable
(gdb) disas 0x80483ef
Dump of assembler code for function overflow:
0x080483c4 <overflow + 0>: push% ebp
0x080483c5 <overflow + 1>: mov% esp,% ebp
0x080483c7 <overflow + 3>: sub $ 0x48,% esp
0x080483ca <overflow + 6>: mov 0x8 (% ebp),% eax
0x080483cd <overflow + 9>: mov% eax, -0x34 (% ebp)
0x080483d0 <overflow + 12>: mov% gs: 0x14,% eax
0x080483d6 <overflow + 18>: mov% eax, -0x4 (% ebp)
0x080483d9 <overflow + 21>: xor% eax,% eax
0x080483db <overflow + 23>: mov -0x34 (% ebp),% eax
0x080483from <overflow + 26>: mov% eax, 0x4 (% esp)
0x080483e2 <overflow + 30>: read -0x24 (% ebp),% eax
0x080483e5 <overflow + 33>: mov% eax, (% esp)
b 0x080483e8 <overflow + 36>: call 0x8048320 <strcpy @ plt> / b
0x080483ed <overflow + 41>: mov -0x4 (% ebp),% eax
0x080483f0 <overflow + 44>: xor% gs: 0x14,% eax
0x080483f7 <overflow + 51>: je 0x80483fe <overflow + 58>
0x080483f9 <overflow + 53>: call 0x8048330 <_ stackchkfail @ plt>
0x080483fe <overflow + 58>: leave
0x080483ff <overflow + 59>: ret
End of assembler dump.
--------------------------------------------------------------------------------------------------------------------------------------------
As shown stops the program in - instructional leave that (so I understand) is responsible for moving ( mov ) to% ebp to% esp and remove ( pop ) to% ebp stack, that would mean intends to return to ESP and with the copied buffer ( call 0x8048320 <strcpy @ plt> ). It is there where the canary is overwritten and the entire procedure is stopped after the check. The check is done using the _stackchkfail () function .
Now let's try the program sin this protection. For that we are going to compile the program with the flag --no-stack-protector :
Code: Text
mohamed @ mohamed-desktop: ~ / Desktop $ gcc --no-stack-protector vulnerable.c -o vulnerable
mohamed @ mohamed-desktop: ~ / Desktop $ ./vulnerable $ (perl -e 'print' A 'x44 # EIP')
Targeting failure
mohamed @ mohamed-desktop: ~ / Desktop $ gdb -q vulnerable
(gdb) r $ (perl -e 'print "A" x36, "B" x4')
The program being debugged has already started.
Start it from the beginning? (and or n) and
Starting program: / home /mohamed/ Desktop / vulnerable $ (perl -e 'print "A" x36, "B" x4)
Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb) ir eip ebp
eip 0x42424242 0x42424242
ebp 0x41414141 0x41414141
(gdb)
--------------------------------------------------------------------------------------------------------------------------
And without this protection we were able to overwrite EBP and EIP without any difficulty, which would be easy to exploit even more if the protection of which you speak before is disabled to be able to get the constant address of ESP and overwrite the process flow. In itself, I only talk about a single method of protection of this extension, which for what I know are 5.
Be the First to Respond
Share Your Thoughts