From Zero To Zero Day
From Zero To Zero Day
From Zero To Zero Day
• @j0nathanj
• My journey, basically
• Demo!
Vuln research – why?
• It’s awesome!
What is a vulnerability?
What is a vulnerability?
What is a vulnerability?
The Journey, part 0x0: Programming
• Being a solid developer is an important part of being a vuln researcher
• The most notable and used programming languages/topics that helped me progress
are mainly C, C++, Assembly, OS internals and Python
• Exploit-exercises
• Try harder things, don’t be afraid to fail - we all learn from our failures!
• I tried to always expose myself to harder challenges, even to ones I was not sure I
could solve.
Part 0x3: Pwn, Repeat
• Practice =)
vulnerability
Part 0x4: Vuln discovery
• I came to the point where I have seen a few different vuln types, and some of them
had some things in common.
- Many more
Part 0x4: Vuln discovery
• CTFs: Usually in CTFs the vuln is a bug that does not require too much to reach it
• JS engines are responsible for actually running the JS code that comes in
• Doing this efficiently is hard, which is the why they are so complex
• Parser
• Interpreter
• Runtime
• JIT compiler <--- the interesting part for our use-case
• Garbage Collector
JavaScript 101 :: Basics
• Fairly readable
• JS objects have “prototypes”, which are used to inherit features from other objects
var parentObj = { x : 1, y : 2 };
var childObj = { z : 3 };
childObj.__proto__ = parentObj;
console.log(childObj.x); // 1
console.log(childObj.y); // 2
console.log(childObj.z); // 3
JavaScript 101 :: Proxy
proxy.x = 0x1337;
console.log(proxy.x); // prints "got_proxied"
ChakraCore 101 :: Arrays
JavascriptNativeIntArray
• Stores integers
JavascriptNativeFloatArray
• Stores floats
JavascriptArray
• Stores objects
… next next …
Element[0] Element[0]
… …
Loosely based on a diagram from “The ECMA and the Chakra: Hunting bugs in the Microsoft Edge Script Engine” by @natashenka. Great talk btw ☺
ChakraCore 101 :: Array layout
• When debugging the following sample code, we can see the state of the fields
we just mentioned.
JavascriptArray properties
Segment properties
• One interesting field for our vuln is the arrayFlags field of JavascriptArray.
• In our example:
• The HasNoMissingValues flag indicates that the array does not have missing
values
As seen, the
HasNoMissingValues flag
is OFF – which indicates that
there are indeed missing
values in the array.
ChakraCore internals :: var arr = new Array(3);
arr[0] = -1.1885959257070704e+148; // == (double)0xdeadbeefdeadbeef
• Let’s have a look at how those so called “missing values” are represented in memory.
• This is the memory dump of the Segment, marked in red are the elements of the array:
• Wait.. What ?
• Mixing data && metadata
• JIT type confusions are vulns that occur due to wrong assumptions by the JIT
• Most common: “Side Effect” that took place, and the JIT was not aware of.
• Example:
• JITed function invokes a function foo() that changes the type of an array
• JITed function doesn’t know the conversion happened, and uses the old type of the array
• Leads to a Type Confusion in the JITed code, could potentially be turned into an RCE
JIT Bugs :: Type Confusions
• Theoretical example:
function jit(arr) {
foo(arr); // Side Effect *may* change arr’s type
• Force jit() to be JITed and optimized
}
• Theoretical example:
• As already mentioned, this weird state was already investigated by Loki and
S0rryMybad
We can get
isFillFromPrototypes to
return false if
HasNoMissingValues is set,
as seen in the next slide
ChakraCore vulns :: weird state --> vuln * “this” is what we referred to as “buggy”
ChakraCore vulns :: weird state --> vuln * aItem is what we referred to as “buggy”
• Quick recap:
• If we create an array with a fake Missing Value, but HasNoMissingValue flag is set, we
reach an interesting code flow from Array.prototype.concat()
• It will loop through the fake array’s prototype chain, and will make sure every prototype in
the prototype-chain is a Non-native array (AKA: JavascriptArray).
• Remember: if some object is the prototype of another object directly, the prototype is
converted to a JavascriptArray.
ChakraCore vulns :: weird state --> vuln
• So, if we could theoretically have a Native array as the prototype, we can cause it to be
converted to a JavascriptArray, without the JIT knowing it..
o Similarly to the “usual” Side-Effect JIT bugs explained earlier
• To exploit this bug we faked a DataView object, which in turn grants us an arbitrary read/write
primitive
• After that we just ROP and restore what we overwrote, allowing valid process continuation
DEMO
Thank you ☺
• @tom41sh && @Arbel2025 – definitely wouldn’t have made it without you guys!
• The whole @BlueHatIL crew for helping me be prepared for all this ☺
• The MSRC Vulnerabilities & Mitigations team for the great feedback
• Pwnable.kr
• Pwnable.tw