tag:blogger.com,1999:blog-87700730980845920292024-03-29T02:14:28.405-07:00Dr. Fu's Security BlogUnknownnoreply@blogger.comBlogger34125tag:blogger.com,1999:blog-8770073098084592029.post-43879051978357216052012-10-23T08:35:00.001-07:002012-10-23T08:35:43.223-07:00Malware Analysis Tutorial 34: Evaluation of Automated Malware Analysis Tools CWSandBox, PeID, and Other Unpacking Tools<b>Learning Goals</b>:<br />
<ol>
<li>Understand Design Principles of Automated Malware Analysis Systems</li>
<li>Hands-on Experiences with CWSandBox and Packer Identification Tools</li>
</ol>
<b>Applicable to:</b><br />
<ol>
<li>Operating System Security </li>
</ol>
<u><b>1. CWSandBox</b></u><br />
<br />
We first examine the performance of another automated malware analysis tool CWSandBox (now named GFI Sandbox). The tool is available at <a href="http://www.gfi.com/malware-analysis-tool">http://www.gfi.com/malware-analysis-tool</a>. CWSandBox uses dynamic API hook technique (DLL injection) to monitor system calls. This is similar to the approach taken by the Anubis system. In this article, we will examine the report generated by CWSandBox. We take a similar approach as the previous tutorial, and submit a modified version of Max++. Unfortunately, the server was not able to generate a report for us in 24 hours.<br />
<br />
<u><b>2. VirusTotal</b></u><br />
We then submitted the modified version of Max++ to VirusTotal (<a href="http://www.virustotal.com/">http://www.virustotal.com</a>). This is an integration site that runs multiple virus search/malware detection engines. We explicitly requested for an onsite start-from-scratch analysis of the modified version. Figure 1 shows the result from VirusTotal (many virus detection tools listed).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhh3Tx0AQzSrpvayTgO8m0BSv8o0ZSdDKWtJgmA2NLWCg7NnMhnvgW7a8neI-2MfVv0Xn4v9hKXXPZqgcClEIfslAfCMSnL-K2eV6QEDF7A6kI0iJH1sczl0B2okVbgwKi4t39giZExqac/s1600/aaa.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhh3Tx0AQzSrpvayTgO8m0BSv8o0ZSdDKWtJgmA2NLWCg7NnMhnvgW7a8neI-2MfVv0Xn4v9hKXXPZqgcClEIfslAfCMSnL-K2eV6QEDF7A6kI0iJH1sczl0B2okVbgwKi4t39giZExqac/s1600/aaa.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Results by Virus Total on Modified Max++</td></tr>
</tbody></table>
As shown in Figure 1, most signature based tool (including ClamAV) was not able to discover that the modified version of Max++ is a virus (note that the modified version is<u><b> functionally equivalent </b></u>to the original Max++. We only inserted two NOP instructions after the INT2D trick.). Among all the virus tools, DrWeb identified it in the virus familty of MaxPlus.6 and most others either identified it as <b>Smiscer </b>or <u><b>Sirefef</b></u>.<br />
<br />
Interesting, if we submit the original version of Max++ to virus total, we have the results shown in Figure 1.5. This time ClamAV is able to identify it as "Trojan.Dropper".<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsErk-BUlP4dp7VhVkESpzN4NMouQI9iqw8okjXor70AtFob-Vm4K1jWLoVYa3ynzYFKrMhvopdAY3ms5AnnalwG9x1MlNMcYlQrIBA2puQTHmJ4s713Uu7DyOeB8gHyNW9t2VJIgyjEM/s1600/aaa.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsErk-BUlP4dp7VhVkESpzN4NMouQI9iqw8okjXor70AtFob-Vm4K1jWLoVYa3ynzYFKrMhvopdAY3ms5AnnalwG9x1MlNMcYlQrIBA2puQTHmJ4s713Uu7DyOeB8gHyNW9t2VJIgyjEM/s1600/aaa.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1.5. Results by Virus Total on Original Version of Max++</td></tr>
</tbody></table>
<br />
<br />
<u><b>2. Packer Identification Tools</b></u><br />
As introduced in <a href="http://fumalwareanalysis.blogspot.com/2011/12/malware-analysis-tutorial-6-analyzing.html" target="_blank">Malware Analysis Tutorial 6- Self-Decoding and Self-Extracting Code Segment </a>, Max++ has self-unpacking behaviors. It is interesting to see that if the tool has used any existing packers such as UPX. We used three packer identification tools: <u><b>PeID</b></u>, <u><b>RDGPacker</b></u> <u><b>Detector</b></u>, and <u><b>ExeInfoPE </b></u>to examine the modified version of Max++. All of these tools are freely available on the Internet.<br />
<br />
PeID and RDGPacker did not find any known packers used to pack the Max++ code. Figure 2 and Figure 3 shows the running results of these tools.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0ESzkFeYyfqAkIGfBNh9BckWcQIOe-sm31QLjNMI6G_5SgPDGZGRWv9RlVM6Gi1iecjrA5EXvJwIXrJwPU80_OJomIGfYcElmNnAcl_-yzsicuASd-I-pg4yBAzNRciSx0wM3gXRl02o/s1600/aaa.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0ESzkFeYyfqAkIGfBNh9BckWcQIOe-sm31QLjNMI6G_5SgPDGZGRWv9RlVM6Gi1iecjrA5EXvJwIXrJwPU80_OJomIGfYcElmNnAcl_-yzsicuASd-I-pg4yBAzNRciSx0wM3gXRl02o/s1600/aaa.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. Results by PeID</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyDrVkBROnr-RFt4KiupFz7KohEkKc9x_293t8KTmDpuCqDl4GmtHtxq0AaK5xvoVFrlgqG2MgjHIgNJuM1pvdoM7ywPhjH_CXefxdDesSSGb47jQiHuBwSjMZorXYPt-qN2EjMPSsDNM/s1600/aaa.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyDrVkBROnr-RFt4KiupFz7KohEkKc9x_293t8KTmDpuCqDl4GmtHtxq0AaK5xvoVFrlgqG2MgjHIgNJuM1pvdoM7ywPhjH_CXefxdDesSSGb47jQiHuBwSjMZorXYPt-qN2EjMPSsDNM/s1600/aaa.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. Result by RDGPacker Detector</td></tr>
</tbody></table>
<br />
<br />
Only ExeInfoPE reports that Max++ has 3 sections packed using similar algorithms like UPX (however, it does not precisely identify it's UPX). Figure 4 shows the report by ExeInfoPE.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3JE-BGya95ViDl7NgrZMQnGjH1HmxvMg7uBXqHTg52ZJTvVg0g4Kdd72c3CI583O8EJqxa66KTStnkjxp5L0EurIrDCUSxqNzGGgUWR8D1tcCLByA-SAJlvoRuLvi_LUD8d9NYbwLmZI/s1600/aaa.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3JE-BGya95ViDl7NgrZMQnGjH1HmxvMg7uBXqHTg52ZJTvVg0g4Kdd72c3CI583O8EJqxa66KTStnkjxp5L0EurIrDCUSxqNzGGgUWR8D1tcCLByA-SAJlvoRuLvi_LUD8d9NYbwLmZI/s1600/aaa.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Report by ExeInfoPE</td></tr>
</tbody></table>
<br />
<br />
The conclusion is that Max++ did not use any existing packers to directly pack its code. Its multiple layer packing algorithm is a customized algorithm (although it's not too complex).<br />
<br />
<br />Unknownnoreply@blogger.com549tag:blogger.com,1999:blog-8770073098084592029.post-83098089947047031362012-09-18T17:14:00.001-07:002012-09-18T17:14:53.182-07:00Malware Analysis Tutorial 33: Evaluation of Automated Malware Analysis System I (Anubis)<b>Learning Goals</b>:<br />
<ol>
<li>Practice Binary Patching</li>
<li>Understand Design Principles of Automated Malware Analysis Systems</li>
<li>Hands-on Experiences with Anubis Malware Analysis System</li>
</ol>
<b>Applicable to:</b><br />
<ol>
<li>Operating System Security </li>
</ol>
<u><b>1. Introduction</b></u><br />
<br />
As we have examined the entire Max++/ZeroAccess binary code, it is now a great time to evaluate a number of automated malware analysis systems based on our knowledge. This tutorial reports our experiences with Anubis (formerly known as TTAnalyze), an automated malware analysis system. A webportal is provided by Anubis designers to submit Windows binary executables (<a href="http://anubis.iseclab.org/">http://anubis.iseclab.org/</a>).<br />
<br />
Anubis uses API hook to monitor the system calls placed by a malware (and the processes started by the malware). Equipped with a data structure parser, it is able to extract rich semantic information from the function parameters of system calls (such as registry values and file names). This allows the system to provide a detailed report of malware behaviors.<br />
<br />
<u><b>2. Run Benign Software on Anubis </b></u><br />
To verify the functionality and validity of Anubis, we first submitted int2d.exe (used in our <a href="http://www.blogger.com/Malware%20Analysis%20Tutorial%204:%20Int2dh%20Anti-Debugging%20%28Part%20II%29">malware analysis tutorial 4</a>) to Anubis. int2d.exe is a very simple executable that calls printf() to print two simple strings. As this is the first time that this binary executable is submitted to Anubis, it takes Anubis about 7.5 minutes to generate the report. Figure 1 presents the details of the report.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTrJZ_3QnJYonOtjy-FrWnz0XlEeDRoXAJ-LkOEolPQ4SW4N7pqiiafAS16DkhwxOiSQHoc0XGcEFJcS7gmyI-jmAiGBqf09dZ-W9qQDHgC2F4XLFvLacrEh0qY9qCcaf6FTiLOLQ9-H4/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTrJZ_3QnJYonOtjy-FrWnz0XlEeDRoXAJ-LkOEolPQ4SW4N7pqiiafAS16DkhwxOiSQHoc0XGcEFJcS7gmyI-jmAiGBqf09dZ-W9qQDHgC2F4XLFvLacrEh0qY9qCcaf6FTiLOLQ9-H4/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Anubis Analysis on int2d.exe</td></tr>
</tbody></table>
<br />
<br />
As shown in Figure 1, int2d.exe is identified as a benign file. It does not generate any suspicious file, registry, or network activities.<br />
<br />
<u><b>3. First Submission of Max++.exe</b></u><br />
We then proceed with the submission of Max++.exe. This time, it only takes Anubis 10 seconds to generate the report, because it pulls out the report from its repository based on the <u><b>md5 checksum</b></u> of the binary executable file. (i.e., Even if we change the file name, it's still the same report). As shown in Figure 2, the first time the binary of Max++ submitted to Anubis is <u><b>November 2010</b></u>.<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrLe_ffqmz4m2naHbz2dP0_ExOUgOeTLxVmhKlWhT5oj6nsavr2R3ftw7lZq0msz0HrVlVkza5FaZOPJ6Xmz5cL-RqTfzva737inuL7uGTaVu5R9vz4OUP9tNu_9O3YVXju0X4eptM9KE/s1600/a1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrLe_ffqmz4m2naHbz2dP0_ExOUgOeTLxVmhKlWhT5oj6nsavr2R3ftw7lZq0msz0HrVlVkza5FaZOPJ6Xmz5cL-RqTfzva737inuL7uGTaVu5R9vz4OUP9tNu_9O3YVXju0X4eptM9KE/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. Cached Report of Max++</td></tr>
</tbody></table>
Figure 3 shows the summary of Max++. It is reported
that Max++ has suspicious file, registry, and process creation
activities. Specifically, Max++ spawned two processes: dwwin.exe and
drwtsn32.exe. This is interesting: because we have not observed such
activities during our analysis.It is known that dwwin.exe and
dwtsn32.exe are files related to Dr. Watson (a part of the microsoft
error report/diagnosis/debugging utility). However, it is unknown in
this case if these two files are already there on the Anubis system, or
they are fake files downloaded by Max++. We need to drill down deeper
into the report.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLsg5lFu8umxuFlOgpjXFRvwY5dhByTGehMBQw5dvb8T5nehNGssqK1KmhJUD64AphowpYwCfzFt7lUtBb9U4H4Diy9heEtBxKVqRxYp_20d66vxux-_FiRkkwEsj_5idZPOri9fsMAJc/s1600/a1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLsg5lFu8umxuFlOgpjXFRvwY5dhByTGehMBQw5dvb8T5nehNGssqK1KmhJUD64AphowpYwCfzFt7lUtBb9U4H4Diy9heEtBxKVqRxYp_20d66vxux-_FiRkkwEsj_5idZPOri9fsMAJc/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. Summary of Max++</td></tr>
</tbody></table>
<br />
<br />
<br />
Anubis then reports the detailed activities performed by Max++ and the processes spawned by it. We now briefly examine each:<br />
<br />
<u><b>Runtime DLL Activities:</b></u> As shown in Figure 4, Anubis successfully discovered that lz32.dll is loaded at run time, however, no further information about the hijack and reloading of DLL contents.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMhRqqy2Mn-qxyZ6cvoxOSFae0QVrarN7Q6zvGJspH-NLdFBjCTpVM2ln-7E_i9GRuk4_pUvR5a7b1E1dgb8WWlq7OToKbtzPTBf_uDjoW25j5Zz7tUnSEOADG01IdireDVMTp7T3yutg/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMhRqqy2Mn-qxyZ6cvoxOSFae0QVrarN7Q6zvGJspH-NLdFBjCTpVM2ln-7E_i9GRuk4_pUvR5a7b1E1dgb8WWlq7OToKbtzPTBf_uDjoW25j5Zz7tUnSEOADG01IdireDVMTp7T3yutg/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Run-time DLL Activities</td></tr>
</tbody></table>
<u><b>Registry Activities:</b></u> only read values are reported, no write-values. <br />
<br />
<u><b>File Activities.</b></u> Figure 5 shows the file activities reported by Anubis (note the highlighted area). This is quite different from our own manual analysis. First of all, Anubis did not notice that the file and device drivers are modified by Max++ and thus all operations on the hidden drive (and corresponding file mapping activities) are not discovered by Anubis. Secondly, the reported activities (such as creation of a temporary file and modification of PIPE\lsarpc [used for Local Security Authority]) were not noted in our analysis. We suspect that these activities were made by the drwtsn32.exe.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuBuAG5ujuoes96XeHAqeQph7L-zPjrUl_0nua2EVbTyRAN28x7m84DH53I-Smgnzrp4WgfnreRVukNhQY69VY-Z8YXcFYIVrTHr3Ek-IxFWvy7412lkgYZtiEftFIQdM4wW_Jm3cBcyk/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuBuAG5ujuoes96XeHAqeQph7L-zPjrUl_0nua2EVbTyRAN28x7m84DH53I-Smgnzrp4WgfnreRVukNhQY69VY-Z8YXcFYIVrTHr3Ek-IxFWvy7412lkgYZtiEftFIQdM4wW_Jm3cBcyk/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5. File Activities</td></tr>
</tbody></table>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijNlALTXQlHDHkNKkeFkiymuwNIV1EAoC4EvPlA5BUvnsjRCDsHYKRJFwdtqx5ADU2yEDqtzrbHIoouyJtvw7XSEIfxeukWXQb0ddryyptqmpQl-AEiqupCIf_TYbd_1qG2Tp4ajS_ZDs/s1600/a1.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
<u><b>Process Activities. </b></u>Figure 6 shows the process activities. Again, this is completely different from our manual analysis. Note that Max++ has foreign memory regions written (see highlighted area in Figure 6). Our best guess is that this is similar to the injection of remote thread of an existing process (smss.exe) in our analysis (see <a href="http://fumalwareanalysis.blogspot.com/2012/02/malware-analysis-tutorial-15-injecting.html">Tutorial 15</a>). Because the process is randomly picked, it is possible that the drwtsn.exe is chosen at run time. However, the intended behavior, i.e., to remove the max++_download_2010.exe is not reported by Anubis.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDG2ElocAkdA-bj9Y_XkcKG-9-TDjR2zCrrGdFUDO_TGNYdhIg2W5kG2tAokBJdKAw7j8OsWHHMwy1x9lfxtfEVLhDr3omt3vkyhZIMRmKklLfh3IOmMT3l6iD_3tHeYYVPpkDSXwSAGY/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDG2ElocAkdA-bj9Y_XkcKG-9-TDjR2zCrrGdFUDO_TGNYdhIg2W5kG2tAokBJdKAw7j8OsWHHMwy1x9lfxtfEVLhDr3omt3vkyhZIMRmKklLfh3IOmMT3l6iD_3tHeYYVPpkDSXwSAGY/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6. Process Activities</td></tr>
</tbody></table>
<br />
<u><b>Structured Exceptions. </b></u>Figure 7 shows Anubis report on the SEH activities. Anubis has captured one of many Max++'s SEH activities, however, did not perform in-depth analysis of the exception handler after the exception is triggered. For example, the one in <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-11-starling.html">Tutorial 11</a> is not reported.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbECWPVJn_fRUrkwxlCeLxKE7dCoga9dmBNdw6ZYPJ7qq0Y6Tuyr1J3FsoNoof0vj1F0ncqT9hpko0PkmiP7Mkik95sHK7GNiQ975z6oOxtQ0ZxYiwjMqk46fBZbJXpnRDEPfhKmf70m8/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbECWPVJn_fRUrkwxlCeLxKE7dCoga9dmBNdw6ZYPJ7qq0Y6Tuyr1J3FsoNoof0vj1F0ncqT9hpko0PkmiP7Mkik95sHK7GNiQ975z6oOxtQ0ZxYiwjMqk46fBZbJXpnRDEPfhKmf70m8/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 7. Structured Exceptions.</td></tr>
</tbody></table>
<br />
<u><b>Conclusion:</b></u> it is unclear to us at this moment: if the Dr. Watson service is hijacked by Max++, or it's simply launched because Max++ crashed, as Anubis report also includes a screenshot of the Dr. Watson service screenshot (see Figure 8). To clarify this issue, we have to enforce Anubis to have a new run of Max++ (instead of retrieving the reports based on its MD5 checksum).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeJZHlo6OAlC9NpSN9AO2bjNdugJq3813d9-b3pNv38OJA1-9ttUlXGGaVU2SO1yYdnbwplOf_HqTW8ijIZUCcw36j7qJ7nmmdIGblsrjz6-X0yap6wcr8TNLMGhgK7f_tqnAzX3_96Co/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeJZHlo6OAlC9NpSN9AO2bjNdugJq3813d9-b3pNv38OJA1-9ttUlXGGaVU2SO1yYdnbwplOf_HqTW8ijIZUCcw36j7qJ7nmmdIGblsrjz6-X0yap6wcr8TNLMGhgK7f_tqnAzX3_96Co/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 8. Dr. Watson Screenshot</td></tr>
</tbody></table>
<br />
<br />
<u><b>4. Second Trial. Anubis Report on Modified Max++</b></u><br />
To enforce the execution of Max++ on Anubis, we have to change the binary executable slighly, so that the Max++ executable does not have the same MD5 (which is already stored in Anubis). Follow the instructions below to modify Max++:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM9fMTSciFxrIfxt0E4rV3PXn1l5VOC4wX_M5BbWQ0uVL1OGZomVwsC2MuFlcakHSx24ZOfYrdi0JA5MLwryh4VvlT4O8FetaUNbP_nejPns23le_eutZKNvWibm08thZdi0SA6Q_KTSc/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM9fMTSciFxrIfxt0E4rV3PXn1l5VOC4wX_M5BbWQ0uVL1OGZomVwsC2MuFlcakHSx24ZOfYrdi0JA5MLwryh4VvlT4O8FetaUNbP_nejPns23le_eutZKNvWibm08thZdi0SA6Q_KTSc/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 9. Modify Max++ Binary Executable</td></tr>
</tbody></table>
<br />
(1) Pick one instruction that will never be executed (e.g., the one at 0x00413BD7 in Figure 9).<br />
(2) Right click in code pane -> Assemble -> NOP.<br />
(3) Right click -> Copy to Executable ->All Modified -> Copy All -> click "close" button on the right top of the dialog and then select "save".<br />
<br />
Then upload the modified Max++ to Anubis. It will now take over 8 minutes to generate the report. Interestingly, the report is exactly the same. This seems to confirm that Max++ did not complete in Anubis, and it was stopped early by the drwtson32.exe.<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><br /></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
Unknownnoreply@blogger.com476tag:blogger.com,1999:blog-8770073098084592029.post-18406594573570152862012-08-15T15:37:00.002-07:002012-08-15T15:37:52.376-07:00Malware Analysis Tutorial 32: Exploration of Botnet Client<br />
<b>Learning Goals</b>:<br />
<ol>
<li>Practice WinDbg for Inspecting Kernel Data Structure</li>
<li>Use Packet Sniffer to Monitor Malware Network Activities</li>
<li>Understand Frequently Used Network Activities by Malware</li>
<li>Expose Hidden/Unreachable Control Flow of Malware </li>
</ol>
<b>Applicable to:</b><br />
<ol>
<li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security </li>
</ol>
<u><b>1. Introduction</b></u><br />
<br />
This tutorial explores the botnet client part of Max++. We assume that you have completed <a href="http://fumalwareanalysis.blogspot.com/2012/08/malware-analysis-tutorial-31-exposing.html">tutorial 31</a> where our lab setting directly results from its analysis. You should have the following before the analysis, as shown in Figure 1.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyXLi2d9eRcLA2HW0y7vqb_WTDUGDpq3qAS2kWnO6FZnFxehW_bCCiq_arG_TC6jFxbygad1oaE3ZV4Dd1A7PtF98oC3mVf26M8M7BxrR_ai-GRtHCejLkwbwSrAkw30etSK4FkIW8qxo/s1600/a1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyXLi2d9eRcLA2HW0y7vqb_WTDUGDpq3qAS2kWnO6FZnFxehW_bCCiq_arG_TC6jFxbygad1oaE3ZV4Dd1A7PtF98oC3mVf26M8M7BxrR_ai-GRtHCejLkwbwSrAkw30etSK4FkIW8qxo/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Process Network Message</td></tr>
</tbody></table>
<br />
As shown in Figure 1, there is a big loop of calling <u><b>zwReplyWaitReceivePortEx</b></u>, which tries to wait for a message from the port. EAX represents the return code of the function, e.g., 0x0 represents OK and 0x102 represents time-out. If time-out, it calls function 0x35671D03. Otherwise, it proceeds to process the message. <br />
<br />
Max++ first reads the <u><b>2nd word</b></u> in the message, this is supposed to be an integer between 1 and 3. For case 3, it calls function 0x3567162D. for case 1, it calls function <u><b>0x3567204F</b></u>. Note that all the four parameters of 0x3567204F are from the msg (5th, 7th, 8th and 10th words from the message respectively).<br />
<br />
<u><b>2. Execute Remote Command (#1).</b></u><br />
Now let's delve into function <u><b>0x3567204F</b></u>. Again, notice that this function gets executed ONLY WHEN the second word of the remote network message is 0x1. Figure 2 shows its function body.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjA0k3QAIr5xeN-gwOd53wqSifGHgBGV-6889vWIkFs6ra7lev6maZVNEvZp2y8qNHkVerfBfUBeLhEgyVqpjlf0dX714rNK8blWq4gd9-c-g6VbgTeTjN9NCTHFQA4QDo24B2J41A6ijI/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjA0k3QAIr5xeN-gwOd53wqSifGHgBGV-6889vWIkFs6ra7lev6maZVNEvZp2y8qNHkVerfBfUBeLhEgyVqpjlf0dX714rNK8blWq4gd9-c-g6VbgTeTjN9NCTHFQA4QDo24B2J41A6ijI/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. Mysterious Function 0x3567204F</td></tr>
</tbody></table>
<br />
As shown in Figure 2, one of the input parameters of the function is <u><b>ESI </b></u>register (pointing to 0x00181580). This is a mysterious data structure. We suspect that it is the COM interface of the fake JScript COM object (the remote max++.x86.dll). The COM interface wraps a C++ object so that the program (Max++) can call the functions available in the DLL.<br />
<br />
Next, the function clears memory region 0x009FFEE8, and copies the<u><b> first four parameters</b></u> passed in the stack to this region. Notice that these four parameters are the 5th, 7th, 8th, and 10th words in the remote message. Then it saves 0x009FFFE8 to EBP-10. <br />
<br />
Max++ then proceeds to call <u><b>some function of the remote DLL</b></u> (see the second highlighted area in Figure 2). It seems to be taking out the virtual function table of the object and it invokes the function located at offset 0x18. This function takes at least <u><b>7 parameters,</b></u> and they are <u><b>[ESI+18], [ESI+20], 0x356782A4, 0, 1, [EBP-20], and [EBP-10].</b></u> Here [ESI+18] and [ESI+20] must be some data attributes of the COM interface object, and [EBP-20] is a pointer to collect result. From the VariantClear call (see the last highlighted area of figure 2), we can infer that [EBP-20] is a pointer to VARIANTARG. Lastly notice that [EBP-10] stores <u><b>0x009FFEE8</b></u>, which contains the four words from the remote message.<br />
<br />
Although we have no access of the remote DLL, we can infer that this part of the malware is taking some command/parameters of the remote message, and execute some functions correspondingly. It looks like a bot-net client.<br />
<br />
<u><b>3. Initilization (command #3)</b></u><br />
We now look at case #3 (where the 2nd word of the remote message is 3). In this case, function <u><b>0x3567162D</b></u> is invoked.. To enforce the control flow into this case, we simply change the register values correspondingly. Figure 3 displays the body of function 0x3567162D.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLE9wP0bUrX_IdSi48WQwnp69jebAkbpxNqEUuNjSKNv8-5b0XQTwp0pqT-6erCcZpnpoqfrSwYoMUzVJK8CTmLJTyYldOz88rMGc-cooL8aBv2qZ-12ZhRhMwNRvcVbgmkPoVbzzTlr8/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLE9wP0bUrX_IdSi48WQwnp69jebAkbpxNqEUuNjSKNv8-5b0XQTwp0pqT-6erCcZpnpoqfrSwYoMUzVJK8CTmLJTyYldOz88rMGc-cooL8aBv2qZ-12ZhRhMwNRvcVbgmkPoVbzzTlr8/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><u><b>Figure 3. Function Body of 0x3567162D</b></u></td></tr>
</tbody></table>
<br />
As shown in Figure 3, function 0x3567162D extracts a file from the hidden drive into a newly allocated heap area. The contents of the file seem to be some special javascript tags and HTTP request headers. The file name is read from an absolute location 0x3567806C. Unless the address is being re-written, it's always reading the same file.<br />
<br />
Then Max++ jumps to function 0x356719E4, as shown in Figure 4. Again, it's invoking the COM interface of the remote object which is not available. As shown in Figure 4, it loads the virtual function table of the COM object multiple times and calls several functions of that COM interface. <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFivJWXu0ICe5MLKN1KQQAcRYkyi2sQTBCSWTp-K-AiR7gK6fexRvZTmt3MjziBtRMMkvPDBJImkTKcY1FLzhZ3cH8IxsffbpKbyQ5iQKgGIYbUGnNxDsl9b_UVBuSvsbDLdJJ1aqwAOo/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFivJWXu0ICe5MLKN1KQQAcRYkyi2sQTBCSWTp-K-AiR7gK6fexRvZTmt3MjziBtRMMkvPDBJImkTKcY1FLzhZ3cH8IxsffbpKbyQ5iQKgGIYbUGnNxDsl9b_UVBuSvsbDLdJJ1aqwAOo/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Calling COM Object</td></tr>
</tbody></table>
<br />
<u><b>4. Conclusion</b></u><br />
Since the remote object is not available, we are not able to drill deeper into Max++. The bottomline via the analysis in this tutorial is that the maxware is able to listen to a port and receive commands from a remote server. The remote command has a fairly simple structure, the second word of the remote message decides the action to take at the max++ client side. #3 seems to be initializing service; and #1 seems to be executing some actions, where four words from the remote message serve as the parameters.<br />
<br />
In the next tutorial, we will submit Max++ to various malware analysis engines and match their discovery with our manual analysis. <br />
<u><b> </b></u><br />
<u><b><br /></b></u>
Unknownnoreply@blogger.com191tag:blogger.com,1999:blog-8770073098084592029.post-79109358212388575012012-08-04T10:29:00.002-07:002012-08-04T10:29:17.550-07:00Malware Analysis Tutorial 31: Exposing Hidden Control Flow<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOdLDiHp-yBR2Sajn8fg2g2oeqKd5MzJ-TBBk9dNKTSFiXNp-h6WsHMpCdn1bBxCbTutv3opOziTD09x4nNnuQG521WwkDFxNC7RrYBO_L28qQwgnPF-E4U1Q-PMpZJ5vfncPCeMSU1XU/s1600/a1.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
<b>Learning Goals</b>:<br />
<ol>
<li>Practice WinDbg for Inspecting Kernel Data Structure</li>
<li>Use Packet Sniffer to Monitor Malware Network Activities</li>
<li>Understand Frequently Used Network Activities by Malware</li>
<li>Expose Hidden/Unreachable Control Flow of Malware </li>
</ol>
<b>Applicable to:</b><br />
<ol>
<li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security</li>
</ol>
<u><b>1. Introduction</b></u><br />
<br />
This tutorial
analyzes the network activity performed by max++.00.x86 when its efforts to load 147.47.xx.xx\max++.x86.dll fails. We show the use of network sniffer to assist the analysis. We show the use of debugger to expose and analyze the hidden/unreachable control flow of a malware.<br />
<br />
<u><b>2. Lab Configuration</b></u><br />
<br />
We assume that you have finished <a href="http://fumalwareanalysis.blogspot.com/2012/06/malware-analysis-tutorial-30-loading.html">Tutorial 30</a> and max++.00.x86 is already resident on the system. .Now set a breakpoint at <u><b>0x35671797 </b></u>(this is where the malware tries to modify the kernel data structure about library path of max++. Later it will call Ole32.CoInitialize to load the remote). Now at the Ubuntu server, start the Wireshark packet sniffer and listen on the local area network (use ifconfig to find out which adapter to listen to).<br />
<br />
Now press F9 until you hit 0x35671797. At this moment, in the Wireshark window, no packets should be intercepted yet. Execute the program step by step until we reach 0x35671D8B. This is right before the call of ole32.CoInitialize.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqwHkjQhFfDxEkWAfLHF00C5s0Vf1hDuXkdN3Y5P7kTSSyyUDKTcASwHz-EhPmWsq5c7mzVh2PfmJxteIybYpL8NEFJAm2KDhCsPZUeJG3pW-jBqY0b8q4HxPimB3cJ8_J7FEPCpbc0lM/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqwHkjQhFfDxEkWAfLHF00C5s0Vf1hDuXkdN3Y5P7kTSSyyUDKTcASwHz-EhPmWsq5c7mzVh2PfmJxteIybYpL8NEFJAm2KDhCsPZUeJG3pW-jBqY0b8q4HxPimB3cJ8_J7FEPCpbc0lM/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. The Code Which Tires to Load Remote DLL</td></tr>
</tbody></table>
<br />
<br />
<u><b>3. Wireshark Assisted Analysis</b></u><br />
Now the intersting part, just one more step in the WinDbg instance, the Ole32.CoInitialize is called. Then you can notice that there is a lot of communication between 169.253.236.201 (our WinDbg instance) and 74.117.114.86. From Figure 2, you can tell that it's using a special HTTP method PROPFIND to retrieve max.x86.dll (note that PROPFIND is a method provided by the WebDav protocol which is an extension of HTTP).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9_AKMojyrRwxpo1F-HKx9Aj1qwU4sh4a9RymNq1WpiFsgNvYjYNpcbCNLRvWvyUeGq-UDMTdIjWfuwjtMlnjGVkwkHLjKcD3-ZQrybpfYgXIfdy8BLY-gsWaPXMZYZCmGfiyy659Vut8/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9_AKMojyrRwxpo1F-HKx9Aj1qwU4sh4a9RymNq1WpiFsgNvYjYNpcbCNLRvWvyUeGq-UDMTdIjWfuwjtMlnjGVkwkHLjKcD3-ZQrybpfYgXIfdy8BLY-gsWaPXMZYZCmGfiyy659Vut8/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. Network Trace of Ole32.CoInitialize</td></tr>
</tbody></table>
However, interestingly, if we directly F9 from 0x35671797, we got the following in Figure 3. Notice the difference!<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvLjK-gXXEo2a5FZWXXp4ZdiD48x123q67KaqFpiYUDp5712xUCJcBFuhifhyk2VDcOy-VU3m4ipQKIaYSvLzEegrkZZb7W3EQMjrVBv2xUj4rJxfSzGPyKs7O8JxB6CoPe2NFnmA2gp0/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvLjK-gXXEo2a5FZWXXp4ZdiD48x123q67KaqFpiYUDp5712xUCJcBFuhifhyk2VDcOy-VU3m4ipQKIaYSvLzEegrkZZb7W3EQMjrVBv2xUj4rJxfSzGPyKs7O8JxB6CoPe2NFnmA2gp0/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. A slightly different network trace</td></tr>
</tbody></table>
Clearly, the malware is trying to invoke the /install/setup.ppc.php at 108.61.4.52! Now the question is: who is sending this request and why didn't we capture it when we step by step the execution?<br />
<br />
<u><b>Challenge 1.</b></u> Find a way to trace back to the sender of the packet to 108.61.4.52.<br />
<br />
<u><b> 4. Run Malware without Remote DLL</b></u><br />
We are interested in looking at the rest of the malware logic and would like to have a rough idea of Max++.00.x86's behavior what if 74.117.114.86/max++.x86.dll is loaded. This would need us to tweak the control flow a little bit to observe the behavior. We need to perform the following lab configuration:<br />
<br />
(1) <u><b>set a breakpoint at<span style="background-color: red;"> 0x35671D8D</span> and run to it.</b></u> See Figure 4. This is right before the ole32.CoInitialize() call, which tries to load the remote 74.117.114.86/max++.x86.dll. However, the file is not available any more and the call will fail and terminate the entire process. We need to skip this call so that we could examine the rest of the malware logic.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZW4M7PkYaoeK8YLGl9VBsBFwcCF9MN3RKpSCBOuMYoPoQSvYbOlO4XdZXSPjjBrFWDchhyAkrY9ZVQH52I-k7h8LsbJohjHPP4KiRovx0WsettAMt1bZBvPAnuN03LUAiOhdIpBT66-c/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZW4M7PkYaoeK8YLGl9VBsBFwcCF9MN3RKpSCBOuMYoPoQSvYbOlO4XdZXSPjjBrFWDchhyAkrY9ZVQH52I-k7h8LsbJohjHPP4KiRovx0WsettAMt1bZBvPAnuN03LUAiOhdIpBT66-c/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Breakpoint to Divert Control Flow When Remote DLL Loading Fails</td></tr>
</tbody></table>
<br />
<br />
(2) Click the 2nd button on the toolbar (the Python window) and then type<br />
<u style="font-family: "Courier New",Courier,monospace;"><b> imm.setReg("EIP", <span style="background-color: red; color: orange;">0x35671D93</span><span style="background-color: red;">)</span></b></u><br />
This is to skip the call of ole32.coInitialize and jump to the next instruction<br />
<br />
(3) Now in the register window, <u><b>change the value of EAX to 0</b></u> (to indicate that the call is a success).<br />
<br />
After the control flow diverting is successful, max++.00.x86 jumps to function 0x35674737, whose function body is shown in Figure 5.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgBYo3OKGegcEinPeQ6i-_fxxq4TbFWupoc4TJJWJo0hQcYLdxiXe5oon-PZjpJIW8AuWa-CosxfSNrue03LTjBsvnJp9eceKx1NSpvW91of-ESy1RwjuRgsY-MJ2gKCqgxf2UZ9ulqQM/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgBYo3OKGegcEinPeQ6i-_fxxq4TbFWupoc4TJJWJo0hQcYLdxiXe5oon-PZjpJIW8AuWa-CosxfSNrue03LTjBsvnJp9eceKx1NSpvW91of-ESy1RwjuRgsY-MJ2gKCqgxf2UZ9ulqQM/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5. Function 0x35674737 - Allocate Memory in Heap</td></tr>
</tbody></table>
Then the malware calls function 0x35671E37 [note at this moment <u><b>0x00182130</b></u> is the beginning address of allocated heap memory]. As shown in Figure 6, it is constructing some data structure at 0x00182130 (size: 0x24 bytes).<br />
<br />
<u><b>Challenge 2.</b></u> Use data breakpoints to find out what is the type of the data structure constructed by 0x35671E37.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjj7NPVZNkIV0U4DZz_gATl2AnLZo444FhM1ySqDds8b8vunD-z6IVOFS9D0UTRC7Wl-3Jf1wukGeHjBp6KKXCCxfa0__uWYd5U-lCBJYW4ZGXca4Vo3WgLEK3hpv-4otSquhR-NrfQiR8/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjj7NPVZNkIV0U4DZz_gATl2AnLZo444FhM1ySqDds8b8vunD-z6IVOFS9D0UTRC7Wl-3Jf1wukGeHjBp6KKXCCxfa0__uWYd5U-lCBJYW4ZGXca4Vo3WgLEK3hpv-4otSquhR-NrfQiR8/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6. Function 0x35671E37 constructs some data structure</td></tr>
</tbody></table>
The control soon flows to 0x35671C4A. This function has several interesting calls, as shown in Figure 7. It seems to be creating a port and listens to it. To figure out the logic, we have to carefully handle the execution of function 0x35671E61 (because it is invoking functions in the remote max++.x86.dll, which is not loaded due to network failure).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOdLDiHp-yBR2Sajn8fg2g2oeqKd5MzJ-TBBk9dNKTSFiXNp-h6WsHMpCdn1bBxCbTutv3opOziTD09x4nNnuQG521WwkDFxNC7RrYBO_L28qQwgnPF-E4U1Q-PMpZJ5vfncPCeMSU1XU/s1600/a1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOdLDiHp-yBR2Sajn8fg2g2oeqKd5MzJ-TBBk9dNKTSFiXNp-h6WsHMpCdn1bBxCbTutv3opOziTD09x4nNnuQG521WwkDFxNC7RrYBO_L28qQwgnPF-E4U1Q-PMpZJ5vfncPCeMSU1XU/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 7. Function body of 0x35671C4A</td></tr>
</tbody></table>
Now let's delve into function <u><b>0x35671E61 </b></u>first,Figure 8 shows its first part. It's a call to <b>ole32.CLSIDFromProgID("JavaScript")</b>. The function locates registry entry based on program ID information. But this call triggers the remote DLL. We'll need to look at the details.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjddvP_CS-Jrf5qfaFFK2YyiYMGqwPxTQh4JLIfY_SMt_7-wS-ZYDMZWAQOHRXdxeu5RS4f-uJBHK2kF9GuwvbUX22ZsYqdF6IQmOT0KTXMsoHZp-V4R8VCIQ-jyYrKwBTVvjEq4Y-CL8A/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjddvP_CS-Jrf5qfaFFK2YyiYMGqwPxTQh4JLIfY_SMt_7-wS-ZYDMZWAQOHRXdxeu5RS4f-uJBHK2kF9GuwvbUX22ZsYqdF6IQmOT0KTXMsoHZp-V4R8VCIQ-jyYrKwBTVvjEq4Y-CL8A/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 8. A Call That Triggers remote max++.x86.dll</td></tr>
</tbody></table>
<br />
By tracing into the old32.CLSIDFromProgID("JavaScript") call, we notice that at the<u><b>ole32.CoGetComCatalog</b></u> call, it is stuck on loading the 74.117.114.86/max++.x86.dll. As shown in figure 9. It seems that CoGetComCatalog visits the loaded module again (and reads the manipulated information of the current module and thus trying to load the remote module. This is similar to the CoInitialize call in discussed in <a href="http://fumalwareanalysis.blogspot.com/2012/06/malware-analysis-tutorial-30-loading.html">Tutorial 30</a>).<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7fosQZcKzn_grHAgHKcMkR5EKvkTy24yM9X8SN43wbTWLptUQ5xlCqIkzaz0_V36YQRpmBKvg11834KCzGQYEm-ul1YqYsM_tNB4DqiWViLd9xTftV3ik4T_9n0S-274QJguTZnLirXE/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7fosQZcKzn_grHAgHKcMkR5EKvkTy24yM9X8SN43wbTWLptUQ5xlCqIkzaz0_V36YQRpmBKvg11834KCzGQYEm-ul1YqYsM_tNB4DqiWViLd9xTftV3ik4T_9n0S-274QJguTZnLirXE/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 9. CLSIDFromProgID Stuck on CoGetComCatalog</td></tr>
</tbody></table>
Since the remote module name causes the problem, we could try to reset it back. From Tutorial 30, we know that the module name/path information is located at 0x002529c0. We could change it back to the original name "<b><span style="font-family: "Courier New",Courier,monospace;">\\.\C2CAD972#4079#4fd3#A68D#AD34CC121074\L\max++.00.x86</span></b>". (Right click on address 002529c0 in memory dump, select <i><b>Binary Edit</b></i>, then enter the path string in the <i><b>UNICODE </b></i>box).<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivTLuPvVF9U2YlTsCyIuwV9-7KX6MjAUG81Z_gML_8WN8J7OKTm_IvmxQZiuUWpHuMQDZYT_N88ks_YFzI6fxVrOVzb4AsOIVWZQ-lsFO1k5NlfkCtZU2JtpkeiEAGnU_A1mXKmywsSi8/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivTLuPvVF9U2YlTsCyIuwV9-7KX6MjAUG81Z_gML_8WN8J7OKTm_IvmxQZiuUWpHuMQDZYT_N88ks_YFzI6fxVrOVzb4AsOIVWZQ-lsFO1k5NlfkCtZU2JtpkeiEAGnU_A1mXKmywsSi8/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 10. Modify the Module Name - Convert it Back</td></tr>
</tbody></table>
<br />
Now let's let's observe the second parameter of CLSIDFromProgID in Figure 8. Via a simple analysis we can identify that the second parameter is located at <u><b>0x009FFF48</b></u>, as shown in Figure 11.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKCkpepaieS2cfqKAShAcrB53kjkOdPdq588xVALW3bgTLN54vds31V-Dd27_gM_Uie_srypTgRROwq6BzVywS5SqIOA8oAZRh-JRWhSTVYcRLPW47bJRti8P1up1vyrYwXNNZfO4Z-ec/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKCkpepaieS2cfqKAShAcrB53kjkOdPdq588xVALW3bgTLN54vds31V-Dd27_gM_Uie_srypTgRROwq6BzVywS5SqIOA8oAZRh-JRWhSTVYcRLPW47bJRti8P1up1vyrYwXNNZfO4Z-ec/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 11. Successful Completion of CLSIDFromProgID</td></tr>
</tbody></table>
<br />
As shown in Figure 11, address <u><b>0x009FFF48 </b></u>stores the class ID. Pay attention to the byte order (you should read the first 4 bytes in the reversed order). For example, for the first 4 bytes (60 C2 14 F4), it should read as <u><b>0xf414c260</b></u>. Searching f414c260 in <u style="background-color: yellow; color: red;"><b>regedit</b></u>, we found <u><b>CLSID {f414c260-6ac0-11cf...}</b></u>, as shown in Figure 11. You can verify that it matches the highlighted area in the IMM memory dump pane. Reading more details about <u><b>CLSID {f414c260-6ac0-11cf...}</b></u>, we can find that the CLSID is mapped to jscript.dll in the system directory, this is as expected (i.e., the CLSIDFromProgID works correctly, given that the broken remote library link did not crash the CoGetComCatalog call in figure 10).<br />
<br />
However, notice that, there is a possibility that the remote library when loaded, will re-write the registry entry so that later when JSScript object is used, it is actually referring to the functions of the remote library. As we do not have the 74.117.14.86/max++.x86.dll binary, we have no way to tell.<br />
<br />
<u><b>4.1 Rest of Logic of Function 0x35671E61</b></u><br />
We now continue from the call of CLSIDFromProgID. Again, notice that the CLSID is stored at <b style="background-color: yellow; color: red;">0x009FFF48</b>. <br />
<br />
Figure 12 shows the rest of the logic of the function 0x35671E61. The major part is a call of CoCreateInstance which constructs a unique instance of the JScript COM object. Note that its second last parameter rrid is the id of the interface that is used to communicate with JScript. However, as the co-initialize function fails, the CoCreateInstance() returns an error code 0x800410F0 (means the COM interface not initialized correctly). In such case, we have to modify the EAX register at 0x35671E90 to force the logic through.<br />
<br />
It can be seen that, in Figure 12, three calls related to JScript COM object are placed. However, due to the failed co-initialize, we have no way to know about the details of these three functions. Lastly, function 0x35671E61 returns.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJ4vPs_cj_FRbA4ZXum9_6V8eLYBJSD_fwnLIbxsgI4Oz8D0-QzzALYPggKWt6B_jO6HixG4MpWxqGMqPR65XwXp9m4FO8ohnd0iJQ7M0Ht9LZtTRyeLmcNvZ9fiSCbstlQbtb_Z9JglA/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJ4vPs_cj_FRbA4ZXum9_6V8eLYBJSD_fwnLIbxsgI4Oz8D0-QzzALYPggKWt6B_jO6HixG4MpWxqGMqPR65XwXp9m4FO8ohnd0iJQ7M0Ht9LZtTRyeLmcNvZ9fiSCbstlQbtb_Z9JglA/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 12. Interacting with COM Object</td></tr>
</tbody></table>
<br />
<u><b>4.2 Function 0x3567162D</b></u><br />
Using the similar technique, we can enforce the logic into function 0x3567162D. Figure 13 shows its function body. As shown in Figure 13, Max++ is readling from \??\C2CAD...6cc2 and allocates 0x15b bytes at 0x003E0000 and extracts the contents fro mthe file into 0x003E0000.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_5Jf8OglQ8qa9Jv58_EnaIbX6-B3NaD934d5ZxzLhSGxymfNL-LfqYiXe9mFv1jwzSsT9mT8SJgakgt4vGMU0xoQJaqYFZMPhM_nkrjKD4O25umfDAXd7vvPbHvjuxtOg2rm9b_LczPw/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_5Jf8OglQ8qa9Jv58_EnaIbX6-B3NaD934d5ZxzLhSGxymfNL-LfqYiXe9mFv1jwzSsT9mT8SJgakgt4vGMU0xoQJaqYFZMPhM_nkrjKD4O25umfDAXd7vvPbHvjuxtOg2rm9b_LczPw/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 13. Loading New Malicious Logic</td></tr>
</tbody></table>
<br />
The rest of functio n0x3567162D is shown in Figure 14. It applies 2 layers of decryption to extract the contents at 0x003E0000. As shown in Figure 14, at 0x003E0000 it looks like an XML spec. At this moment, we do not know the meaning of "<jst>" tag. But if you look at the contents, it looks like a URL to download from intensivedive.com and the rest looks like the HTTP request header.<br />
<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRLAQIbQAfSdwSuvqcbpm7YKRe_k5hZZLLJpH4eENKi1ixf57uqg-jTjbSCiXvfTLlrHLmI_7goU0jT-dkfbIrxEQbtNYFOuhwed_lqo4S5WuGa6Nm5MBTA-ZboPikS7x-LZvIpype1YE/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRLAQIbQAfSdwSuvqcbpm7YKRe_k5hZZLLJpH4eENKi1ixf57uqg-jTjbSCiXvfTLlrHLmI_7goU0jT-dkfbIrxEQbtNYFOuhwed_lqo4S5WuGa6Nm5MBTA-ZboPikS7x-LZvIpype1YE/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 14. Extraction of Encrypted Contents</td></tr>
</tbody></table>
<u><b>Challenge 2. </b></u>Analyze the logic of function 0x35671ECF.
Notice that you have to carefully rewire the logic when it tries to
invoke functions in remote DLL.<br />
<br />
<u><b>4.3 Function 0x356713AC. </b></u><br />
At the end of functio n0x3567162D, it calls function 0x356713AC, which is shown below. Its function is pretty similar to 0x3567162D. It reads from another hidden file, resolve the IP of intensivedive.com and constructs request payload.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQaoDOw8i7hyphenhyphenMCfF8dG59xMTS-7tfg0t83HZ0_hPQozsBVccPpHx6JJxTCiN-7rz3mdmTtjlTv6b_hjIsi6Z3ns3bxLBF7M938X8j-aIO6r4B6xWWFocQvK0RhY_CjJpkZzXl-jFtpi2E/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQaoDOw8i7hyphenhyphenMCfF8dG59xMTS-7tfg0t83HZ0_hPQozsBVccPpHx6JJxTCiN-7rz3mdmTtjlTv6b_hjIsi6Z3ns3bxLBF7M938X8j-aIO6r4B6xWWFocQvK0RhY_CjJpkZzXl-jFtpi2E/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 15. Function 0x356713AC</td></tr>
</tbody></table>
At the end of function 0x356713AC, it calls 0x356712D8, whose function body is shown as below. It prepares the necessary resources (UUIDs) for socket communication, in 0x35674237, which calls function 0x3567417c.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS4-w6scM7yAWSgE0dtck2Isb5YRKpDlVJ1TdHOxTR10S_0uHc74-MOgn99qZZoKsxQMWFsL2NJdvWFhRRXH_c2sxaruz7YjldpW5WnP0RSMgqBlG-Ia4hPlVTYSfYDqOUE2m9DXwEes8/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS4-w6scM7yAWSgE0dtck2Isb5YRKpDlVJ1TdHOxTR10S_0uHc74-MOgn99qZZoKsxQMWFsL2NJdvWFhRRXH_c2sxaruz7YjldpW5WnP0RSMgqBlG-Ia4hPlVTYSfYDqOUE2m9DXwEes8/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 16. Function 0x356712D8 First Half</td></tr>
</tbody></table>
<br />
The function body of 0x3567417C is shown in Figure 17. Note that the first call of ws32_socket will fail. The most interesting part (see highlighted) is the call of <u><b>BindIoCompletionCallBack</b></u>. It sets <u><b>0x356740D4</b></u> as the handler on any IoCompletion on handle of the network communication. Let's set a breakpoint and see if it's getting called. This breakpoint, under the current setting will never get hit because the WSASocket call fails. However, the analysis of its binary code is still possible. We leave it as a homework for readers.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIOq6NPnyeUiDDyqS1F_cdqixZYB52ABhF2cS0w3XP9yCUkxXe4Wsm1pvcyEH4z3TBH3Ivx9PLDxfO6B0W2CEjxHJzHDdHEbdUPFP83FQj5F8jkGDmSV9cfoVaRHYyAgKnwO1XezY0VRs/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIOq6NPnyeUiDDyqS1F_cdqixZYB52ABhF2cS0w3XP9yCUkxXe4Wsm1pvcyEH4z3TBH3Ivx9PLDxfO6B0W2CEjxHJzHDdHEbdUPFP83FQj5F8jkGDmSV9cfoVaRHYyAgKnwO1XezY0VRs/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 17. Function Body of 0x3567417C</td></tr>
</tbody></table>
<u><b>Challenge 3.</b></u> Analyze the function of 0x356740D4.<br />
<br />
The rest of of 0x356712D8 deals with sending out packets (mainly to intensivedive.com/install.ppc) and there are too many errors as the network initialization of WSASocketW fails. Let's go back to <u><b>0x35671C6F</b></u> and see what's the logic here.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhExS_Q2snhhxbaOQfCQ0pMJAu69ktTROHLDtPvk8uZpmM9AhGHYfSobTDfxpbIoLW5z_me7fLgaAW__3pY1o-pRXBPTihdZc5jDPpCKa18OWmX-WYKMG5F3HUAHvxzj5YkHfzU1G_IVI8/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhExS_Q2snhhxbaOQfCQ0pMJAu69ktTROHLDtPvk8uZpmM9AhGHYfSobTDfxpbIoLW5z_me7fLgaAW__3pY1o-pRXBPTihdZc5jDPpCKa18OWmX-WYKMG5F3HUAHvxzj5YkHfzU1G_IVI8/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 18. Port Service Open</td></tr>
</tbody></table>
As shown in Figure 18, clearly, Max++ is opening a port (using <u><b>zwCreatePort</b></u>), and then there is a big loop and during each iteration, it is calling <u><b>ZwReplyWaitReceivePortEx </b></u>to try to listen to the port.<br />
<br />
<u><b>Challenge 4.</b></u> Find out the port number that Max++ is using. Notice that since TCP/IP stack service is hijacked by Max++, netstat command won't get you any interesting information!<br />
<br />
In the next tutorial, we will tweak the control flow of Max++ to get into each of the switch case of the <u><b>zwReplyWaitReceivePortEx </b></u>call and check out if Max++ is serving as a bot-client of a bot-net.Unknownnoreply@blogger.com78tag:blogger.com,1999:blog-8770073098084592029.post-7155380268258327422012-06-12T04:39:00.002-07:002012-07-07T06:05:45.953-07:00Malware Analysis Tutorial 30: Self-Overwriting COM Loading for Remote Loading DLL<b>Learning Goals</b>:<br />
<ol>
<li>Practice WinDbg for Inspecting Kernel Data Structure</li>
<li>Trace and Modify Control Flow Using IMM</li>
<li>Understand the techniques employed at Max++ for hiding library loading</li>
<li>Understand image loading notifier, asynchronous procedure call, kernel and normal routines. </li>
</ol>
<b>Applicable to:</b><br />
<ol>
<li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security</li>
</ol>
<u><b>1. Introduction</b></u><br />
<br />
This tutorial
analyzes the malicious DLL file \\.\C2CAD....\max++.00.x86. We will see a lot of interesting techniques for hiding its malicious behaviors.<br />
<br />
<u><b>2. Lab Configuration</b></u><br />
<br />
The first step is to take out max++.00.x86 from the hidden drive. You can follow the similar techniques presented in <a href="http://fumalwareanalysis.blogspot.com/2012/05/malware-analysis-tutorial-28-break-max.html">Tutorial 28</a>, The basic idea is to invoke zwCopyFileA after the file is available in the hidden drive.<br />
<br />
Then, we have to get into the entry of max++.00.x86, which is located at offset <u><b>+2DFF</b></u>. This information is available in IMM, when you load max++.00.x86 as a DLL file in IMM. Then <u><b>View -> Executable Modules</b></u>, you can find out the +2DFF DLL entry and its base is <u><b>35670000</b></u>.<br />
<br />
Notice that, you do can execute max++.00.x86 step by step in IMM, however, it will not exhibit the "correct" malicious behaviors, because it's not running in the environment where Max++ has pre-hooked certain driver entries and exception handlers as needed. We have to, instead, use WinDbg to get to the DLL entry, following the "proper" execution flow of Max++.<br />
<br />
In the following, we show how to step into the entry of max++.00.x86.<br />
<br />
The configuration is similar to the setting of the WinDbg instance of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html"><u><b>Tutorial 20</b></u></a>. In
the win_debug instance, you need to set a breakpoint at <u><b>0x3C230F. This is the place right before the call of CALL WS2_32.WSASocketW, as shown in Figure 1 below.</b></u><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirSt7n4O_hbbGKcLjE9J_PV7nMcIClcR-8dHOpgGCs2V32mUqu5dP6YvoPJmVNoy8RfcWXMiyzes2F8I-k3_JOD9pvAchewK5kUtkKw4gqqBD3lj68m8NHG1ywKofif8wNMs89bbpvO8w/s1600/a1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirSt7n4O_hbbGKcLjE9J_PV7nMcIClcR-8dHOpgGCs2V32mUqu5dP6YvoPJmVNoy8RfcWXMiyzes2F8I-k3_JOD9pvAchewK5kUtkKw4gqqBD3lj68m8NHG1ywKofif8wNMs89bbpvO8w/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Something that we do not know that we do not know</td></tr>
</tbody></table>
<br />
<br />
<br />
This is where Max++ is trying to access <u><b>http://74.117.114.86\max++.x86.dll</b></u>. Now press F8 in the IMM, you will stop in WinDbg twice on loading images. Now type the following to stop at the entry of max++.00.x86:<br />
<br />
> <u><b>bp 35672dff</b></u><br />
<br />
Somehow WinDbg is not able to capture the breakpoint, but instead, the INT 3 is captured by the IMM instance as shown in Figure 2:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbmVfx-pebb_FZd6f6JssYQNw6G7CLQtxp63zHSGWy05RbU7Lvn2j9GtmWcjMJbLmRmPuwzwBfYAOX1EDgaM7LwjqzgyuV02r76_aSgleYD1Hh_EoQuJ_JJNT03pF0g3Vi6gbGyjJ0Ui0/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbmVfx-pebb_FZd6f6JssYQNw6G7CLQtxp63zHSGWy05RbU7Lvn2j9GtmWcjMJbLmRmPuwzwBfYAOX1EDgaM7LwjqzgyuV02r76_aSgleYD1Hh_EoQuJ_JJNT03pF0g3Vi6gbGyjJ0Ui0/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. Entry of max++.00.x86</td></tr>
</tbody></table>
<br />
If you look at the instruction at 35672DFF (in Figure 2), you will notice that there is an '<u><b>INT 3</b></u>' (single-step breakpoint) placed by WinDbg. We have to recover it to the original instruction <u><b>PUSH EBP</b></u> (we can learn about this information in the previous session that loads max++.00.x86 as a DLL in user mode IMM). The resetting of "PUSH EBP" has to be done, otherwise, the instruction at 0x35672E05 (<u><b>MOV EAX, [EBP+C]</b></u>) would not function correctly, because EBP is not set right. Please follow the instructions below in IMM:<br />
<br />
(1) in the code pane, right click on the INT 3 instruction and select <u><b>assemble</b></u>, and then type "<u><b>PUSH EBP</b></u>".<br />
(2) click the 2nd button (Python) on the tool bar to bring up the Python window and and run the following commands in the python window: <u><b>imm.setReg("EIP", 0x35672DFF); This is to reset the EIP register.</b></u> From no on, you can execute max++.00.x86 step by step.<br />
<br />
<u><b>3. Hiding DLL Loading</b></u><br />
We now can explain why the remote DLL loading is not captured by IMM earlier in <a href="http://fumalwareanalysis.blogspot.com/2012/06/malware-analysis-tutorial-29-stealthy.html">Tutorial 29</a>. Look at figure 3 below.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1XHa2EIIn0t1oj43EtKoXs82ouzU84DgocEqlliDqOiirjm8bWJXEFnygXcdjPRjp7LOPLM17ggyWn-aqwm3Qk49QbPyTOL4VwRIdBp5wA0bOa_4-IkaYaVWlyMBnu_XnVBWtSEgr-B4/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1XHa2EIIn0t1oj43EtKoXs82ouzU84DgocEqlliDqOiirjm8bWJXEFnygXcdjPRjp7LOPLM17ggyWn-aqwm3Qk49QbPyTOL4VwRIdBp5wA0bOa_4-IkaYaVWlyMBnu_XnVBWtSEgr-B4/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. Hide DLL Loading</td></tr>
</tbody></table>
<br />
The first call (shown in Figure 3), <u><b>zwTestAlert </b></u>clears the APC queue, and the second call <u><b>DisableThreadLibraryCalls </b></u>detaches DLL_LOAD signal so that the later DLL loading event will not be captured. Then the program plays a trick, it reads out the function addresses stored from <u><b>356761E0 </b></u>to <u><b>35676200 </b></u>one by one, and <u style="background-color: yellow;"><b>call each of them</b></u> (see the high lighted area in the memory dump in Figure 3) one by one. These calls are 3567595c, 35675979, and etc..<br />
<br />
<u><b>Challenge 1. Find out all the functions (and their semantics) being called described in the above.</b></u><br />
<br />
The logic is roughly described below:<br />
(1) max++ first creates an AVL tree.<br />
(2) then it copied the entry address of several ntdll functions such as ntWriteFile into global memory.<br />
It's basically to prepare the data section (hard code it) in global memory. Then it calls 356752D7 (at 0x35672E5E).<br />
(3) then it saves several dll names such as "kernel32.dll", "kernel32base.dll" into its stack.<br />
<br />
<u><b>4. Manipulation of System Kernel DLLs</b></u><br />
Now we start the analysis from 0x356762D7. Figure 4 shows its function body.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYZWz_6TGTzGShjLbLl7_4lVX9LCdVLkWHfmg56SAf7n0M4FRGmvQ3fn3UTTiq8B4C-SkBcDLXZLtVoRUMf9-m-jxnxxkg5RR4nTFL1exTvoxEDEE-1T8dPIqpyhMs_m-k_D_OSyZgk2M/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYZWz_6TGTzGShjLbLl7_4lVX9LCdVLkWHfmg56SAf7n0M4FRGmvQ3fn3UTTiq8B4C-SkBcDLXZLtVoRUMf9-m-jxnxxkg5RR4nTFL1exTvoxEDEE-1T8dPIqpyhMs_m-k_D_OSyZgk2M/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Processing Kernel Modules</td></tr>
</tbody></table>
<br />
<br />
Function 0x356752D7 processes the related kernel DLLs one by one using a loop. The collection of DLL names is preset by Max++ (see the comments after challenge 1). The function tries to get the handle of each DLL, it proceeds to call 0x3567525C to process the header information of each DLL (only when the handle is successfully retrieved, i.e., the DLL is currently already alive in the system space).<br />
<br />
We now look at the details of funciton 0x3657525C, as shown in Figure 5.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPYMyAdOODp3943S2Rm7uZAIlXYHo4gtkkUnQoEfNE02hbOjw1FJ9LJPzdOzGr1S3WnwFrICS3W5U578_U4J5qCPi_7HY9g7h_L6DdIv9CqOPJhqWraSmPLB24Mpxplgb_2DM9GT91YTo/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPYMyAdOODp3943S2Rm7uZAIlXYHo4gtkkUnQoEfNE02hbOjw1FJ9LJPzdOzGr1S3WnwFrICS3W5U578_U4J5qCPi_7HY9g7h_L6DdIv9CqOPJhqWraSmPLB24Mpxplgb_2DM9GT91YTo/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5. Function 0x3567525c</td></tr>
</tbody></table>
<br />
The major part, as shown in Figure 5, is a call of <u><b>RtlImageDirectoryEntryToData</b></u>. The undocumented system call (if you search it on ReactOS, you can find the source code) takes four parameters: (1) the image base of the DLL file, (2) whether it is regarded as an image file, (3) the ID of the entry to retrieve, and (4) the entry size. In this case, our ID is "1", reading the MSDN documentation of <a href="http://msdn.microsoft.com/en-us/magazine/bb985997.aspx">IMAGE_DIRECTORY</a> of PE header, we can find that ID "1" stands for <u><b>import table address</b></u> and size. Now it's your job to find out what is the use of this information, i.e., what does Max++ plan to do with them?<br />
<br />
<u><b>Challenge 2.</b></u> Find out the use of NT header information retrieved by code at 0x35675277 (hint: use data breakpoints to find out when and where the information is used).<br />
<br />
Following function 0x356752D7 there are many technical details related to NT header information retrieval and resetting, whereas the analysis is similar. In the following, we directly jump to the other interesting parts of max++.00.x86.<br />
<br />
<u><b>5. Resetting Exception Handler (SEH)</b></u><br />
We now look at an interesting behavior of max++.00.x86 that resets the SEH handler. Before max++.00.x86 does the trick, the current SEH chain is shown in Figure 6 (click View -> SEH chain in IMM).<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4LMLKruWk4ziYIl7EhG3WeQS8xEMFNVYEnb2DQk2eDFVQFR9ZVs5XEywwESZNy2p8xbvyhyphenhyphenQ0Dvi9q1CeD9a8r8p6hON9-G64FlKu_6xkwgbsyfyLlAfgCfDB_gEvS60Xm8bJOikWXRc/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="260" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4LMLKruWk4ziYIl7EhG3WeQS8xEMFNVYEnb2DQk2eDFVQFR9ZVs5XEywwESZNy2p8xbvyhyphenhyphenQ0Dvi9q1CeD9a8r8p6hON9-G64FlKu_6xkwgbsyfyLlAfgCfDB_gEvS60Xm8bJOikWXRc/s400/a1.JPG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6. SEH Chain before max++.00.x86 does the trick</td></tr>
</tbody></table>
<br />
As shown in Figure 6, when an exception occurs, it is first passed to ntdll.7C90E900 (3 times) and then kernel32.7C839AC0 (if 7C90E900 cannot handle it right). In fact, SEH chain is a very simple singly-listed data structure. Each SEH record has two elements as shown below:<br />
<br />
struct SEH_RECORD{<br />
SEH_RECORD *next;<br />
void* handler_entry<br />
};<br />
<br />
For example, the first SEH record is locatd at 0x0012BF1C (this is usually at the bottom of the current stack frame of the current thread), as shown in Figure 7.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHTQq4F5fs6-Yzvs7tN0FifsI_JoEba8D41O9tIMpL841KXOaxSVS2VxLoPASxGBJpKj4qhiQTW56hNtk-8QYFF8RhKkG13su34STYVItOnIU-8mLggZROZRoOoL8ffKLX-hRA5veQzPE/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="202" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHTQq4F5fs6-Yzvs7tN0FifsI_JoEba8D41O9tIMpL841KXOaxSVS2VxLoPASxGBJpKj4qhiQTW56hNtk-8QYFF8RhKkG13su34STYVItOnIU-8mLggZROZRoOoL8ffKLX-hRA5veQzPE/s640/a1.JPG" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 7. Memory dump of the first SEH record</td></tr>
</tbody></table>
As shown in Figure 7 (highlighted part), the next pointer points to 0x0012C1C8 (compare it with Figure 6), and the handler part has value 0x7C90E900.<br />
<br />
Now, in Figure 8, we present the malicious code in max++.00.x86 which resets SEH. The basic idea is to construct a new SEH record and push it into the stack, and reset the value at FS:[0] (which is part of the kernel data that points to SEH chain). The important instructions are already highlighted.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhU9rGSEm6pETCyWpzexvaDpbDh8_skuBv8kxlzYbb38WKXAyK2SlNm09MGIkgwaQnYU2JmMX8n1y0FTXEJvL7vVpAAJN3S_qX0qO4_l4CXc9Ac7nDpegr1-sdvRzdFxtxduP0PsqGvNNE/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhU9rGSEm6pETCyWpzexvaDpbDh8_skuBv8kxlzYbb38WKXAyK2SlNm09MGIkgwaQnYU2JmMX8n1y0FTXEJvL7vVpAAJN3S_qX0qO4_l4CXc9Ac7nDpegr1-sdvRzdFxtxduP0PsqGvNNE/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 8. Manipulates SEH Chain</td></tr>
</tbody></table>
<br />
<u><b>Challenge 3.</b></u> Explain in details (based on the instructions given in Figure 8, starting from 0x356754BC): why is 35675510 the new exception handler?<br />
<br />
<u><b>Challenge 4.</b></u> Explain the logic of handler at 35675510 and investigate when it is called.<br />
<br />
<u><b>5. Loading Remote DLL</b></u><br />
The next interesting part is located at 0x35672E6D. Figure 9 shows a call of zwCreateThread and its parameters. The thread's start routine (i.e., the function to execute when the thread is born) is 0x356718D2.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDTtvnGYTc_09Ci83WocjdvniAkcXKYIxx2OIngjdX7YMNy2X7Na7IQVio2zKrt1DXmRod58zDIh9L1bafvvQY6iZgTJeEgoqpSN4GCi8W8ltKmMEN2hhDvLnXgf52nh5RC_G11rXWoNU/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDTtvnGYTc_09Ci83WocjdvniAkcXKYIxx2OIngjdX7YMNy2X7Na7IQVio2zKrt1DXmRod58zDIh9L1bafvvQY6iZgTJeEgoqpSN4GCi8W8ltKmMEN2hhDvLnXgf52nh5RC_G11rXWoNU/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 9. Create a new thread which invokes 0x356718D2</td></tr>
</tbody></table>
<br />
Let's set a software breakpoint at 0x356718D2 and trace into it, as shown in Figure 10. There are two major functions: 0x35671797 and ole32.CoInitialize.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghrjwClyl4YV4j326_m53xlcFAS07-_5M0l38zGnmgccW44fjNdeVSGLhVDBmbhl6R82UaMPMrxHVzHvR-SZgOqNTJjBICxBbKM06Ag2QmKpE883ucZysEUrZ_8IGeljuNuxwo8mFytsA/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghrjwClyl4YV4j326_m53xlcFAS07-_5M0l38zGnmgccW44fjNdeVSGLhVDBmbhl6R82UaMPMrxHVzHvR-SZgOqNTJjBICxBbKM06Ag2QmKpE883ucZysEUrZ_8IGeljuNuxwo8mFytsA/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 10. Thread Start Routine</td></tr>
</tbody></table>
Figure 11 displays the first part of the function body of 0x35671797.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2RciPMsZcfaTIzZKVxGgNrbihtDZ2EWPJH99STAQU5aQOHQMGiDg6-u_TbbuJtCTTW6yzSnndSIIXZU489b2CATCdLGmfx0Jdf2GedxX9L34xaTizmWTMkiN8mR3jcqYstXoHfIwNDp4/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2RciPMsZcfaTIzZKVxGgNrbihtDZ2EWPJH99STAQU5aQOHQMGiDg6-u_TbbuJtCTTW6yzSnndSIIXZU489b2CATCdLGmfx0Jdf2GedxX9L34xaTizmWTMkiN8mR3jcqYstXoHfIwNDp4/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 11. First Part of 0x0035671797</td></tr>
</tbody></table>
<br />
<br />
As shown in Figure 11, The first important call in 0x35671797 is <u><b>LdrFindEntryForAddress</b></u>(0x0035670000, 0x009FFFA8). Search the documentation of LdrFindEntryForAddress, we could soon learn that the function finds the module entry (LDR_DATA_TABLE_ENTRY) for address 0x0035670000, and the pointer to LDR_DATA_TABLE_ENTRY is stored in 0x009FFFA8 (which contains value <u><b>0x00252A50 </b></u>after the call. Dump the data structure using WinDbg (start the WinDbg inside the WIN_DEBUG VBox instance and attach the process max++ noninvasively, we have the following. Note that the FullDllName's type is _UNICODE string, while the <u><b>real char array is stored at 0x002529c0.</b></u><br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">:000> dt _LDR_DATA_TABLE_ENTRY 0x00252a50 -r1</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">ntdll!_LDR_DATA_TABLE_ENTRY</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x252b10 - 0x252cd0 ]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Flink : 0x00252b10 _LIST_ENTRY [ 0x252bd8 - 0x252a50 ]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x004 Blink : 0x00252cd0 _LIST_ENTRY [ 0x252a50 - 0x252900 ]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x252b18 - 0x252cd8 ]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Flink : 0x00252b18 _LIST_ENTRY [ 0x252be0 - 0x252a58 ]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x004 Blink : 0x00252cd8 _LIST_ENTRY [ 0x252a58 - 0x252908 ]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x252d48 - 0x252be8 ]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Flink : 0x00252d48 _LIST_ENTRY [ 0x252e08 - 0x252a60 ]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x004 Blink : 0x00252be8 _LIST_ENTRY [ 0x252a60 - 0x252b20 ]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x018 DllBase : 0x35670000 Void</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x01c EntryPoint : 0x35672dff Void</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x020 SizeOfImage : 0xc000</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x024 FullDllName : _UNICODE_STRING "<u><b>\\.\C2CAD972#4079#4fd3#A68D#AD34CC121074\L\max++.00.x86</b></u>"</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Length : 0x6e</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x002 MaximumLength : 0x72</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x004 Buffer : <u><b>0x002529c0 </b></u> "\\.\C2CAD972#4079#4fd3#A68D#AD34CC121074\L\max++.00.x86"</span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"> ...</span><br />
<br />
The next call is <u><b>OLE32.LoadTypeLibrary("\\.\C2CAD...max++.00.x86", REGKIND_NONE, 0x009FFFAC),</b></u> where a pointer to ITypeLib is stored at <u><b>0x009FFFAC</b></u>. By dumping the RAM, we can find that the ITypeLib pointer is <u><b>0x00180F10</b></u>. <br />
<br />
Next comes the interesting part. It reads ECX = [EAX], as shown in Figure 11, then it calls [ECX+18], passing three parameters: 0x00180F10 (the "this" pointer for the ITypeLib interface itself), 0x003567696C, and 0x00356782A0 (and there might be other parameters, i.e., not necessarily 3). None of the 0x003567696c and 0x00356792a0 looks like inside code region. But which function is it calling?<br />
<br />
We need to read the documentation of MSDN about ITypeLib carefully. According to MSDN, ITypeLib supports a number of functions such as FindName, GetDocumentation, etc.If we examine the memory contents of 0x00356782A0, before and after the call of [ECX+18], we might notice that its contents is changed. Thus, checking the list of functions available in ITypeLib, the only function that has the second parameter as output is ITypeLib::getTypeInfoOfGUID(int GUID, ITypeLib **).<br />
<br />
<u><b>Challenge 5.</b></u> Verify if the above conjecture about getTypeInfoOfGUID is correct.<br />
<br />
<br />
Now let us study the last interesting part of function 0x35671797, as shown in Figure 12.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvOG7kYbwhLCycn0nQ2YmmqHBcDN9clBzmZFuUPUpx0LttCP-K0jmm2yQsrvcG2Duni5cwXsJQuixR-hQyCA-1mD1lkPt1sim9nNZ4yHkpHVumo-vt38nEm35VmNZ-KiIkBJvAJIqcxkg/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvOG7kYbwhLCycn0nQ2YmmqHBcDN9clBzmZFuUPUpx0LttCP-K0jmm2yQsrvcG2Duni5cwXsJQuixR-hQyCA-1mD1lkPt1sim9nNZ4yHkpHVumo-vt38nEm35VmNZ-KiIkBJvAJIqcxkg/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 12. Overwrite Module Information</td></tr>
</tbody></table>
As shown in Figure 12, it's a simple <u><b>memcpy </b></u>function that copies string "<i><u><b>\\74.117.114.86\max++.x86.dll</b></u></i>" into address <u><b>0x002529C0</b></u>. Read the discussion after Figure 11 again, address <u><b>0x002529C0 </b></u>stores the <u><b>name of the current module</b></u> in the in-order-load module list!<br />
<br />
Now, when the control flow returns from 0x35671797 (look at Figure 10, it calls <u><b><i>Ole32.CoInitialize. </i></b></u>Because the current module is registered as a type library, and Ole32 modules will try to reload it again somehow, which enforces the system to load the remote DLL \\74.117.114.86\max++.x86.dll.<br />
<br />
The file \\74.117.114.86\max++.x86.dll is not available on the Internet anymore. The call of CoInitialize fails. We have to figure out a way to explore the rest of the logic. We will continue our exploration in our next tutorial.<br />
<br />
<br />
<br />Unknownnoreply@blogger.com69tag:blogger.com,1999:blog-8770073098084592029.post-10348807900580934542012-06-10T19:10:00.002-07:002012-06-10T19:10:56.792-07:00Malware Analysis Tutorial 29: Stealthy Library Loading II (Using Self-Modifying APC)<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimMUexDi6O2MSj2-3LjX-pP77vaNvWHUty1Bc9F7xI6iZLGPfXzwk41w4D66UvWARYijMj11XrNz9_aYmf2k40aeZ_b6ZDRMndHtpJRYf9Jb6jx7VZD8oNkisI8Nlru0VqGcNa4TjJ8lo/s1600/a1.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
<br />
<b>Learning Goals</b>:<br />
<ol>
<li>Practice WinDbg for Intercepting Driver Loading</li>
<li>Trace and Modify Control Flow Using IMM</li>
<li>Understand the techniques employed at Max++ for hiding library loading</li>
<li>Understand image loading notifier, asynchronous procedure call, kernel and normal routines. </li>
</ol>
<b>Applicable to:</b><br />
<ol>
<li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security</li>
</ol>
<u><b>1. Introduction</b></u><br />
<br />
This tutorial analyzes the malicious driver B48DADF8.sys. We assume that you have retrieved the driver from the hidden drive, following the instructions of <a href="http://fumalwareanalysis.blogspot.com/2012/05/malware-analysis-tutorial-28-break-max.html">Tutorial 28</a>.<br />
<br />
<u><b>2. Lab Configuration</b></u><br />
<br />
We need two windows images: one for taking notes and one for actually running the malware. Also a kernel mode WinDbg instance is needed on the host.<br />
<br />
To set up the Notes images, you can follow the instructions of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html">Tutorial 20</a>. The basic idea is to start two instances of IMM, using one to debug the other. Then at 0x004E6095 to set a breakpoint and skip the instruction when there will be an illegal memory write. Once B48DADF8.sys is loaded, in the second IMM (as shown in Figure 1), if we check the executable modules (View -> Executable Modules), we can find out the entry of the driver is +1259. Jumping to that address, we can see the driver entry (which makes a bunch of calls on hooking image loading and creation of driver device).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEin7_a6pmaup8whk5ujkmVjHjqEVnp-EPPyhBUkT1Z3i0EJITkszTS_15CFo9rLg_EdIDPc1GhpRbdaQwwughYFTZ_daMpjqfJnlhlgnB3mkgLzNs9y-NoomKYWgy31qLLGQkeQNRMT8dM/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEin7_a6pmaup8whk5ujkmVjHjqEVnp-EPPyhBUkT1Z3i0EJITkszTS_15CFo9rLg_EdIDPc1GhpRbdaQwwughYFTZ_daMpjqfJnlhlgnB3mkgLzNs9y-NoomKYWgy31qLLGQkeQNRMT8dM/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Identify B48DADF8.sys Entry</td></tr>
</tbody></table>
<br />
The set up of the windows image for debugging and WinDbg should follow the instructions of <a href="http://fumalwareanalysis.blogspot.com/2012/05/malware-analysis-tutorial-28-break-max.html">Tutorial 28</a>. We need to stop at the entry of the driver. This could be achieved by first finding out the starting address of the module in WinDbg, and then plus offset 1259.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
kd> g<br />
nt!DebugService2+0x10:<br />
80506d3e cc int 3<br />
kd> g<br />
nt!DebugService2+0x10:<br />
80506d3e cc int 3<br />
kd> lm<br />
start end module name<br />
804d7000 806ed680 nt (pdb symbols) c:\windows\symbols\ntoskrnl.pdb\47A5AC97343A4A7ABF14EFD9E99337722\ntoskrnl.pdb<br />
<u><b>faf0c000 </b></u>faf11000 B48DADF8 (deferred) <br />
faf54000 faf5c000 _ (deferred) </div>
<br />
First, we learned that the B48DADF8 module starts at faf0c000. Given that the offset of the entry is 1259, we can set a breakpoint at faf0d259, as shown below. <br />
<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">kd> <u><b>bp faf0d259</b></u></span><br />
<span style="font-family: "Courier New",Courier,monospace;">*** ERROR: Module load completed but symbols could not be loaded for B48DADF8.sys</span><br />
<span style="font-family: "Courier New",Courier,monospace;">kd> g</span><br />
<span style="font-family: "Courier New",Courier,monospace;">Wed May 30 09:55:24.281 2012 (UTC - 4:00): Breakpoint 0 hit</span><br />
<span style="font-family: "Courier New",Courier,monospace;">B48DADF8+0x1259:</span><br />
<span style="font-family: "Courier New",Courier,monospace;">faf0d259 55 push ebp</span><br />
<span style="font-family: "Courier New",Courier,monospace;">kd> u</span><br />
<span style="font-family: "Courier New",Courier,monospace;">B48DADF8+0x1259:</span><br />
<span style="font-family: "Courier New",Courier,monospace;">faf0d259 55 push ebp</span><br />
<span style="font-family: "Courier New",Courier,monospace;">faf0d25a 8bec mov ebp,esp</span><br />
<span style="font-family: "Courier New",Courier,monospace;">faf0d25c 56 push esi</span><br />
<span style="font-family: "Courier New",Courier,monospace;">faf0d25d 8b7508 mov esi,dword ptr [ebp+8]</span><br />
<span style="font-family: "Courier New",Courier,monospace;">faf0d260 893518f0f0fa mov dword ptr [B48DADF8+0x3018 (faf0f018)],esi</span><br />
<span style="font-family: "Courier New",Courier,monospace;">faf0d266 33c0 xor eax,eax</span><br />
<span style="font-family: "Courier New",Courier,monospace;">faf0d268 6882d0f0fa push offset B48DADF8+0x1082 (faf0d082)</span><br />
<span style="font-family: "Courier New",Courier,monospace;">faf0d26d c746384cd1f0fa mov dword ptr [esi+38h],offset B48DADF8+0x114c (faf0d14c)</span><br />
<br />
You can verify that the code starts at <u><b>faf0d259</b></u> (shown in the WinDbg dump above) matches the instructions in the IMM window in Figure 1. From now on, we can start the analysis. The basic approach is to execute the driver in the WinDbg instance and annotate the code in the WinNotes image.<br />
<br />
<br />
<br />
<u><b>3.Hook Up Driver with New Device and Set Image Load Notifier</b></u><br />
<br />
We now observe the first section of the code at the beginning of the driver loading. Figure 3 shows the annotated code.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbLkBEA7N7ODpIGBqtnFIZDTt7ufjjGnWz89zI8Vt_YfDjXg1smv7lI97oX8bye8faWlpBSv3yoCT0ohR8pXN18bDZMbykS7J7OJyEQGkgLB0YcKfXfL85ovdnbOBKFkqq3c8fxzfUcic/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbLkBEA7N7ODpIGBqtnFIZDTt7ufjjGnWz89zI8Vt_YfDjXg1smv7lI97oX8bye8faWlpBSv3yoCT0ohR8pXN18bDZMbykS7J7OJyEQGkgLB0YcKfXfL85ovdnbOBKFkqq3c8fxzfUcic/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. First Part of B48DADF8.sys</td></tr>
</tbody></table>
<br />
<br />
The first interesting part is that the driver takes itself (DRIVER_OBJECT) and saves to a global variable. It first reads from EBP+8, i.e., the first parameter to a driver (PDRIVER_OBJECT), as shown in the first highlighted part. We will see that the malware later will need this value.<br />
<br />
We can verify that the value ffb81268 is really a driver object as shown below. It is clear that the driver object is not fully set up yet, e.g., the <u><b>DeviceObject</b></u> is null.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">kd> dd esp</span><br />
<span style="font-family: "Courier New",Courier,monospace;">f7c88920 <u><b>faf4d121</b></u><b> </b><u><b>ffb81268</b></u><b> </b><u><b>00000000 </b></u>02002000</span><br />
<span style="font-family: "Courier New",Courier,monospace;">...</span><br />
<span style="font-family: "Courier New",Courier,monospace;">kd> <u><b>dd _DRIVER_OBJECT ffb81268</b></u></span><br />
<span style="font-family: "Courier New",Courier,monospace;">Couldn't resolve error at '_DRIVER_OBJECT ffb81268'</span><br />
<span style="font-family: "Courier New",Courier,monospace;">kd> dt _DRIVER_OBJECT ffb81268</span><br />
<span style="font-family: "Courier New",Courier,monospace;">nt!_DRIVER_OBJECT</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> +0x000 Type : 0n4</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> +0x002 Size : 0n168</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> +0x004 DeviceObject : (null) </span><br />
<span style="font-family: "Courier New",Courier,monospace;"> +0x008 Flags : 4</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> +0x00c DriverStart : (null) </span><br />
<span style="font-family: "Courier New",Courier,monospace;"> +0x010 DriverSize : 0</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> +0x014 DriverSection : 0xffb8c8f0 Void</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> +0x018 DriverExtension : 0xffb81310 _DRIVER_EXTENSION</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> +0x01c <u><b>DriverName : _UNICODE_STRING "\driver\4157114776"</b></u></span><br />
<span style="font-family: "Courier New",Courier,monospace;"> ...</span><br />
<br />
Next B48DADF8.sys tries to call function <u><b>psSetLoadImageNotifyRoutine at to </b></u>+1082. This is clearly an operation that tries to hide the loading of modules. We are not getting into the details yet, but we can set a breakpoint on it. We can see that the breakpoint will be hit multiple times and DebugService + 2bde is not hit any more.<br />
<br />
Then, B48DADF8.sys tries to create an IO device and hooks itself up as the driver for that device. According to MSDN, <u><b>IoCreateDevice()</b></u> has 6 parameters: PDRIVER_OBJECT, DriverExtension, DeviceName, DeviceType, DeviceCharacteristics, Exclusive, PDEVICE_OBJECT.<br />
<br />
From the WinDbg dump below, we can soon infer that the name of the new device is \??\EBB02C33..\#...0CFE and the device type is FILE_DEVICE_UNKNOWN. This is confirmed by the following WinDbg dump:<br />
<br />
<br />
kd> dd esp<br />
f7c888fc <u><b>ffb81268 </b><b>00000000 </b><b>faed6114 </b></u>00000022<br />
...<br />
kd> dt _UNICODE_STRING faed6114<br />
nt!_UNICODE_STRING<br />
"\??\EBB02C33#910D#415d#BB61#FBD3CC1D0CFE"<br />
+0x000 Length : 0x50<br />
+0x002 MaximumLength : 0x52<br />
+0x004 Buffer : 0xfaed60c0 "\??\EBB02C33#910D#415d#BB61#FBD3CC1D0CFE"<br />
<br />
<u><b>4.Hide Driver Module</b></u><br />
We now discuss the efforts of B48DADF8.sys to hide itself. This part contains no more than 20 instructions, as shown in Figure 4.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigpnUgTuGn_9PX9ZpU50kgdmc8YzZjFeQ2oVZrai1nGQqBa5OvxlYSgH-ngAOlyrK3rFNGnok8gDvX3YGEdMzrfFHAUgFaymwRr_Oe1bXVumvYjNNa6FM-QuiFvqar3STPLJGYQOfliLg/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigpnUgTuGn_9PX9ZpU50kgdmc8YzZjFeQ2oVZrai1nGQqBa5OvxlYSgH-ngAOlyrK3rFNGnok8gDvX3YGEdMzrfFHAUgFaymwRr_Oe1bXVumvYjNNa6FM-QuiFvqar3STPLJGYQOfliLg/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Hide Driver Module B48DADF8.sys</td></tr>
</tbody></table>
<br />
At the beginning of the code, ESI points to the _DRIVER_OBJECT of B48DADF8, and then the code retrieves the word at offset 0x14 of the _DRIVER_OBJECT, and now EDX points to DriverSection (whose data type is _LDR_DATA_TABLE_ENTRY). Using WinDbg, we can easily verify its contents as below. You can see that it's full DLL name is "\??\... C2CAD...B48DADF8.sys".<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;">kd> dt _LDR_DATA_TABLE_ENTRY ffbd61b0 -r1</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">nt!_LDR_DATA_TABLE_ENTRY</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x8055b1c0 - 0xffbacea8 ]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Flink : 0x8055b1c0 _LIST_ENTRY [ 0x8131db20 - 0xffbd61b0 ]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x004 Blink : 0xffbacea8 _LIST_ENTRY [ 0xffbd61b0 - 0x811974c8 ]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Flink : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x004 Blink : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x630069 - 0x0 ]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Flink : 0x00630069 _LIST_ENTRY</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +</span><span style="font-family: "Courier New",Courier,monospace;">0x004 Blink : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x018 DllBase : 0xfaedc000 Void</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x01c EntryPoint : 0xfaedd259 Void</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x020 SizeOfImage : 0x5000</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x024 </span><u style="font-family: "Courier New",Courier,monospace;"><b>FullDllName : _UNICODE_STRING "\??\C2CAD972#4079#4fd3#A68D#AD34CC121074\B48DADF8.sys"</b></u><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Length : 0x6a</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x002 MaximumLength : 0x6a</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x004 Buffer : 0xe1a678c8 "\??\C2CAD972#4079#4fd3#A68D#AD34CC121074\B48DADF8.sys"</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x02c BaseDllName : _UNICODE_STRING "B48DADF8.sys"</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Length : 0x18</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x002 MaximumLength : 0x18</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x004 Buffer : 0xffbd61fc "B48DADF8.sys"</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x034 Flags : 0x1104000</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x038 LoadCount : 1</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x03a TlsIndex : 0x49</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x03c HashLinks : _LIST_ENTRY [ 0xffffffff - 0x4f51 ]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Flink : 0xffffffff _LIST_ENTRY</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x004 Blink : 0x00004f51 _LIST_ENTRY</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x03c SectionPointer : 0xffffffff Void</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x040 CheckSum : 0x4f51</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x044 TimeDateStamp : 0xfffffffe</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x044 LoadedImports : 0xfffffffe Void</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x048 EntryPointActivationContext : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x04c PatchInformation : 0x00340042 Void</span></span><br />
<br />
The next couple of instructions (from 0x100012CE to 0x100012D2 in figure 4) clears the FullDLLName. After 0x100012D2, if you display the same DriverSection again, you would notice that the FullDllName is gone, as shown below. However, the BaseDllName is still there, I guess the malware author forgot to clear it as well.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">kd> dt _LDR_DATA_TABLE_ENTRY ffbd61b0</span><br />
<span style="font-family: "Courier New",Courier,monospace;">nt!_LDR_DATA_TABLE_ENTRY</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> ...</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> +0x024 FullDllName : _UNICODE_STRING ""</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> +0x02c BaseDllName : _UNICODE_STRING "B48DADF8.sys"</span><br />
...<br />
<br />
Next, B48DADF8.sys tries to remove itself from the module list. As shown in Figure 4, at 100012D6, EAX and ECX now have the FLINK and BLINK of the first module of the InLoadOrderModule list. The next four instructions constitute a typical REMOVE_NODE operation on a doubly linked list, which removes B48DADF8 module from the list.<br />
<br />
<u><b>Challenge 2. Explain the logic of code from 100012D6 to 100012E3 in Figure 4.</b></u><br />
<br />
<u><b>4.Hook Up on PCI Device</b></u><br />
The next step (function 0x100011D0) is to hook up on the PCI Device by copying from the original PCI driver. This is shown in Figure 5.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSg_ouyXis0rWF9XOmVpHkL-EF6M8RKSe9dsPPJZXXj4IOTACxPZaK96xEC0787vxDUrsfPc4ddGVI_DZSK5uia2MXhZLhlFoAoqVpCMoWoUL9rgRUbZUCkjSJWqgYHqwDVnm9KxfJorg/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSg_ouyXis0rWF9XOmVpHkL-EF6M8RKSe9dsPPJZXXj4IOTACxPZaK96xEC0787vxDUrsfPc4ddGVI_DZSK5uia2MXhZLhlFoAoqVpCMoWoUL9rgRUbZUCkjSJWqgYHqwDVnm9KxfJorg/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5. Copy from PCI Driver</td></tr>
</tbody></table>
As shown in Figure 5, the first step of function 0x100011D0 is to retrieve the PCI Driver object by name "driver\PCI". Then it copies several attributes of the PCI driver to the current driver, such as driver_start, driver_init, driver size, and driver name. However, the driver major functions <u><b>0xfaed514c </b></u>(an array that contains the IRP handler entry addresses) is not changed. Here all entries are redirected to 0xfaed514, as shown below (which dumps the contents of the B4DADF8.sys driver object, <b>before </b>and <b>after </b>the call of 0x100011D0.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
kd> dt _DRIVER_OBJECT ffb80b90<br />
nt!_DRIVER_OBJECT<br />
+0x000 Type : 0n0<br />
+0x002 Size : 0n168<br />
+0x004 DeviceObject : 0xffbb4af8 _DEVICE_OBJECT<br />
+0x008 Flags : 4<br />
+0x00c DriverStart : <u><b>(null) </b></u><br />
+0x010 DriverSize : <u><b>0</b></u><br />
+0x014 DriverSection : <u><b>0xffb8c8f0</b></u> Void<br />
+0x018 DriverExtension : <span style="background-color: yellow;">0xffb80c38</span> _DRIVER_EXTENSION<br />
+0x01c DriverName : <u><b>_UNICODE_STRING "\driver\4157114776"</b></u><br />
+0x024 HardwareDatabase : (null) <br />
+0x028 FastIoDispatch : (null) <br />
+0x02c DriverInit : <u><b>0xfaf572c5 </b></u> long +0<br />
+0x030 DriverStartIo : (null) <br />
+0x034 DriverUnload : (null) <br />
+0x038 MajorFunction : [28] <span style="background-color: yellow;">0xfaed514c</span> long +0<br />
kd> p<br />
...<br />
kd> dt _DRIVER_OBJECT ffb80b90<br />
nt!_DRIVER_OBJECT<br />
+0x000 Type : 0n0<br />
+0x002 Size : 0n168<br />
+0x004 DeviceObject : 0xffbb4af8 _DEVICE_OBJECT<br />
+0x008 Flags : 4<br />
+0x00c DriverStart : <u><b>0xfaafc000</b></u> Void<br />
+0x010 DriverSize : <u><b>0x10a80</b></u><br />
+0x014 DriverSection : <u><b>0x8131d8a0</b></u> Void<br />
+0x018 DriverExtension : <span style="background-color: yellow;">0xffb80c38</span> _DRIVER_EXTENSION<br />
+0x01c DriverName : <u><b>_UNICODE_STRING "\Driver\PCI"</b></u><br />
+0x024 HardwareDatabase : (null) <br />
+0x028 FastIoDispatch : (null) <br />
+0x02c DriverInit : <u><b>0xfab0a004 </b></u> long +fffffffffab0a004<br />
+0x030 DriverStartIo : (null) <br />
+0x034 DriverUnload : (null) <br />
+0x038 MajorFunction : [28] <span style="background-color: yellow;">0xfaed514c</span> long +0</div>
<br />
<u><b>Challenge 3.</b></u> Note that at this moment, the PCI device has not been completely hooked up to the new driver. Find a way to find out where the new driver is eventually set as the handling driver for the PCI device.<br />
<br />
<u><b>5.Image Loading</b></u><br />
We now go back to study the image loading call at +1082, which is discussed earlier in section 3. Max++ sets +1082 as the call back function whenever NtImageLoad is called. This first, of course, disrupts WinDbg in monitoring image loading. But the code itself is doing a lot of malicious stuff. Let's set a breakpoint at +1082 and watch its behavior. The set up is shown as below:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">kd> lm</span><br />
<span style="font-family: "Courier New",Courier,monospace;">start end module name</span><br />
<span style="font-family: "Courier New",Courier,monospace;">804d7000 806ed680 nt (pdb symbols) c:\windows\symbols\ntoskrnl.pdb\47A5AC97343A4A7ABF14EFD9E99337722\ntoskrnl.pdb</span><br />
<span style="font-family: "Courier New",Courier,monospace;"><u><b>faee4000 </b></u>faee9000 B48DADF8 (deferred) </span><br />
<span style="font-family: "Courier New",Courier,monospace;">faf64000 faf6c000 _ (deferred) </span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">Unloaded modules:</span><br />
<span style="font-family: "Courier New",Courier,monospace;">...</span><br />
<span style="font-family: "Courier New",Courier,monospace;">kd> <u><b>bp faee4000 + 1082</b></u></span><br />
<span style="font-family: "Courier New",Courier,monospace;">*** ERROR: Module load completed but symbols could not be loaded for B48DADF8.sys</span><br />
<span style="font-family: "Courier New",Courier,monospace;">kd> g</span><br />
<span style="font-family: "Courier New",Courier,monospace;">Mon Jun 4 08:34:46.187 2012 (UTC - 4:00): Breakpoint 0 hit</span><br />
<span style="font-family: "Courier New",Courier,monospace;">B48DADF8+0x1082:</span><br />
<span style="font-family: "Courier New",Courier,monospace;">faee5082 55 push ebp</span><br />
<br />
Figure 6 displays the major function of +1082 (also written as 0x10001082).<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyDYRysm7JOAW-0K-IECx87bphGqkVv5a_lazXa9_mtQdqW7x2xdwDsplscPoQU3CT-Ufy7-aSgK0GAOPqmz4J02EwQtYSm1luJDQoee0i1AX4-OdIjJupNso_nKXFGdNkCeN03UGtuTA/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyDYRysm7JOAW-0K-IECx87bphGqkVv5a_lazXa9_mtQdqW7x2xdwDsplscPoQU3CT-Ufy7-aSgK0GAOPqmz4J02EwQtYSm1luJDQoee0i1AX4-OdIjJupNso_nKXFGdNkCeN03UGtuTA/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6. Function Body of 0x10001082</td></tr>
</tbody></table>
<br />
As shown in Figure 6, the majority part of +1082 is to set up and queue an APC object (Asynchronous Procedure Call). APC is frequently used in I/O operation, it stands for an object that will be executed a while later.<br />
<br />
See the highlighted parts in Figure 6, the control flow is very clear: Max++ first tries to call ExAllocatePool to reserve 30 bytes of kernel memory for the APC object, then it calls KeInitializeAPC and KeInsertQueue to queue the APC call. We need to look at the details of KeInitializeAPC. According to <a href="http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CEkQFjAA&url=http%3A%2F%2Fdoxygen.reactos.org%2Fd0%2Fddc%2Fndk_2kefuncs_8h_af384e3c2ab5d909a9e4981b651eda277.html&ei=c7jMT7-FK4PW0QH1rIycAQ&usg=AFQjCNEDd58bnl7EsoD3FBsJlMOSq_COjA">ReactOS</a> documentation, the prototype of KeInitializeAPC is shown below:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
VOID NAPI KeInitializeAPC(</div>
<div style="font-family: "Courier New",Courier,monospace;">
IN PKAPC pApc,</div>
<div style="font-family: "Courier New",Courier,monospace;">
IN PKTHREAD thread, </div>
<div style="font-family: "Courier New",Courier,monospace;">
IN KAPC_ENVIRONMENT env,</div>
<div style="font-family: "Courier New",Courier,monospace;">
IN PKKERNEL_ROUTINE kernelRoutine,</div>
<div style="font-family: "Courier New",Courier,monospace;">
IN PKROUNDOWN_ROUTINE rundownRoutine,</div>
<div style="font-family: "Courier New",Courier,monospace;">
IN PKNORMAL_ROUTINE normalRoutine,</div>
<div style="font-family: "Courier New",Courier,monospace;">
IN KPROCESSOR_MODE mode,</div>
<div style="font-family: "Courier New",Courier,monospace;">
IN VOID context</div>
<div style="font-family: "Courier New",Courier,monospace;">
)</div>
<div style="font-family: "Courier New",Courier,monospace;">
<br /></div>
<br />
<br />
<br />
The dump from WinDbg can be found in the following:<br />
<span style="font-family: "Courier New",Courier,monospace;">kd> dd esp</span><br />
<span style="font-family: "Courier New",Courier,monospace;">f7c88bb4 ffbb2e48 81176320 00000000 <u><b>faee530c</b></u></span><br />
<span style="font-family: "Courier New",Courier,monospace;">f7c88bc4 <u><b>faee52f0 </b><b>71a50000 </b><b>00000001 </b></u>00000000</span><br />
<br />
Here, the kernelRoutine is faee530c (+130c), rundownRoutine is faee52f0 (+12f0), and normalRoutine is 71a50000 (your job: find out which module does it belong to), mode is 1. By MSDN documentation, if mode is 1 and normalRoutine is not 0, this is a <u><b>user mode APC</b></u>, which will call the <u><b>normalRoutine </b></u>later. However, to be safe, we want to <u><b>set up breakpoints on all of the routines +130c, +12f0, 71a50000</b></u>.<br />
Pay special attention, at this moment, the <u><b>normal routine is 71a50000</b></u>!<br />
<br />
Interestingly, it's the kernel routine 130c which is hit first. The following is the call stack:<br />
<span style="font-family: "Courier New",Courier,monospace;">kd> kv</span><br />
<span style="font-family: "Courier New",Courier,monospace;">ChildEBP RetAddr Args to Child </span><br />
<span style="font-family: "Courier New",Courier,monospace;">WARNING: Stack unwind information not available. Following frames may be wrong.</span><br />
<span style="font-family: "Courier New",Courier,monospace;">f7c88d4c 804de855 00000001 00000000 f7c88d64 B48DADF8+0x130c</span><br />
<span style="font-family: "Courier New",Courier,monospace;">f7c88d4c 7c90e4f4 00000001 00000000 f7c88d64 nt!KiServiceExit+0x58 (FPO: [0,0] TrapFrame @ f7c88d64)</span><br />
<span style="font-family: "Courier New",Courier,monospace;">0012c8f8 7c91624a 0017c0e0 0012c984 0012ceac 0x7c90e4f4</span><br />
<span style="font-family: "Courier New",Courier,monospace;">0012cbb8 7c9164b3 00000000 0017c0e0 0012ceac 0x7c91624a</span><br />
<span style="font-family: "Courier New",Courier,monospace;">0012ce60 7c801bbd 0017c0e0 0012ceac 0012ce8c 0x7c9164b3</span><br />
<span style="font-family: "Courier New",Courier,monospace;">0012cec8 7c801d72 7ffdfc00 00000000 00000000 0x7c801bbd</span><br />
<span style="font-family: "Courier New",Courier,monospace;">0012cedc 7c801da8 0012d15c 00000000 00000000 0x7c801d72</span><br />
<span style="font-family: "Courier New",Courier,monospace;">0012cef8 71ab78f1 0012d15c 00155218 0017f410 0x7c801da8</span><br />
<span style="font-family: "Courier New",Courier,monospace;">0012d27c 71ab496d 0017f694 0017f420 00000000 0x71ab78f1</span><br />
<span style="font-family: "Courier New",Courier,monospace;">0012d29c 71ab49cc 0017f410 c000010e 00000000 0x71ab496d</span><br />
<span style="font-family: "Courier New",Courier,monospace;">0012d2b8 71ab40a3 00000002 00000001 00000006 0x71ab49cc</span><br />
<span style="font-family: "Courier New",Courier,monospace;">0012d310 003c2315 00000002 00000001 00000006 0x71ab40a3</span><br />
<span style="font-family: "Courier New",Courier,monospace;">0012d604 003c24ef 0012d634 7c906786 7c903400 0x3c2315</span><br />
<span style="font-family: "Courier New",Courier,monospace;">0012d648 003c2507 00401166 003c0000 fffffffe 0x3c24ef</span><br />
<span style="font-family: "Courier New",Courier,monospace;">0012ffd0 8054b6b8 0012ffc8 81176320 ffffffff 0x3c2507</span><br />
<span style="font-family: "Courier New",Courier,monospace;">00413a40 ec81ec8b 0000030c d98b5653 f4b58d57 nt!ExFreePoolWithTag+0x676 (FPO: [Non-Fpo])</span><br />
<span style="font-family: "Courier New",Courier,monospace;">00413a4c f4b58d57 8bfffffd f45589c3 0000c0e8 0xec81ec8b</span><br />
<span style="font-family: "Courier New",Courier,monospace;">00413a50 8bfffffd f45589c3 0000c0e8 10c38300 0xf4b58d57</span><br />
<span style="font-family: "Courier New",Courier,monospace;">00413a54 f45589c3 0000c0e8 10c38300 0cf85d89 0x8bfffffd</span><br />
<span style="font-family: "Courier New",Courier,monospace;">00413a58 00000000 10c38300 0cf85d89 f3b58dff 0xf45589c3</span><br />
<br />
<u><b>Challenge 4. Analyze who triggers +130c. (hint: 0x71 range is the mwsock.dll, 0x7c range is ntdll.dll).</b></u><br />
<br />
Now let's study what the function +130c (0x1000130c in IMM) is doing. Figure 7 shows its function body.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibsKsd0GuuYKmyNrCDjoyVLJgr9JlRS2AW4tvnAdjz7Jou1qDJo34sgbIpTnNWi_uaidj11s7Su2EPO1kTwIScfhYInG4U7kuQpwOefSoDfDBIyavAe20N6_FNXEKYCws27F72mrPMGSs/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibsKsd0GuuYKmyNrCDjoyVLJgr9JlRS2AW4tvnAdjz7Jou1qDJo34sgbIpTnNWi_uaidj11s7Su2EPO1kTwIScfhYInG4U7kuQpwOefSoDfDBIyavAe20N6_FNXEKYCws27F72mrPMGSs/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 7. Function Body of +1307</td></tr>
</tbody></table>
The first part of +130c is pretty interesting. It's a collection of exchange functions, which essentially rotates 6 words on top of the stack. In the following, we show you the contents of the stack before the rotation.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
kd> <b>dd esp</b><br />
f7c88d00 <u><b>804e60f1</b></u> <u><b>ffb9b638</b></u> <u><b>f7c88d48</b></u> <u><b>f7c88d3c</b></u></div>
<div style="font-family: "Courier New",Courier,monospace;">
f7c88d10 <u><b>f7c88d40</b></u> <u><b>f7c88d44</b></u> f7c88d64 0012c834 <u><b><br /></b></u></div>
<div style="font-family: "Courier New",Courier,monospace;">
...</div>
<br />
The stack contents after the rotation is shown below. You can find that 0x804e60f1 is shifted to the right (now the 6'th word in the stack).<br />
<span style="font-family: "Courier New",Courier,monospace;">kd> <b>dd esp</b></span><br />
<span style="font-family: "Courier New",Courier,monospace;">f7c88d00 <u><b>ffb9b638</b></u> <u><b>f7c88d48</b></u> <u><b>f7c88d3c</b></u> <u><b>f7c88d40</b></u></span><br />
<span style="font-family: "Courier New",Courier,monospace;">f7c88d10 <u><b>f7c88d44</b></u> <u><b>804e60f1</b></u> f7c88d64 0012c834</span><br />
<br />
<br />
<br />
<br />
<br />
Why does Max++ have to do this? The reason is that the function <u><b>copyMaliciousCodeToNewVM </b></u>(the call located at 10001327 in Figure 7) actually consumes 5 additional words in stack. In the following, we display the stack contents after the call of <u><b>copyMaliciousCodeToNewVM </b></u>is completed. <br />
<span style="font-family: "Courier New",Courier,monospace;">kd> dd esp</span><br />
<span style="font-family: "Courier New",Courier,monospace;">f7c88d14 <u><b>804e60f1</b></u> f7c88d64 0012c834 f7c88d64</span><br />
<span style="font-family: "Courier New",Courier,monospace;">f7c88d24 ffffffff 804e2490 804f2001 7c90e4f4</span><br />
<br />
You can notice that 804e60f1 is now at the top of the stack. At this
moment, the control flow (at 0x10001332) is going to jump to
ntoskrnl.ObfDereferenceObject, which when finishes, will jump to
0x804e60f1 (which is originally the return address of +130c). By
manipulating the stack this way, Max++ can successfully confuse the control flow analysis performed by static analysis tools.<br />
<br />
Now let's observe the logic of <u><b>copyMaliciousCodeToNewVM </b></u>, which is located at +100f. Figure 8 shows its function body<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibsKsd0GuuYKmyNrCDjoyVLJgr9JlRS2AW4tvnAdjz7Jou1qDJo34sgbIpTnNWi_uaidj11s7Su2EPO1kTwIScfhYInG4U7kuQpwOefSoDfDBIyavAe20N6_FNXEKYCws27F72mrPMGSs/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibsKsd0GuuYKmyNrCDjoyVLJgr9JlRS2AW4tvnAdjz7Jou1qDJo34sgbIpTnNWi_uaidj11s7Su2EPO1kTwIScfhYInG4U7kuQpwOefSoDfDBIyavAe20N6_FNXEKYCws27F72mrPMGSs/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 8. Function Body of +100f</td></tr>
</tbody></table>
<br />
The logic of <u><b>copyMalicoiusCodeToNewVM </b></u>(+100f) is very simple, it first lowers the IRQ level and then it allocates a small piece from the memory and copies the contents of <u><b>+1338</b></u> to the target address (0x00380000).Recall the "Stealthy 0x00380000 memory segment" in <a href="http://fumalwareanalysis.blogspot.com/2012/05/malware-analysis-tutorial-27-stealthy.html">Tutorial 27</a>,it's now your job to figure out what is copied into the region 0x00380000.<br />
<br />
<u><b>Challenge 5. Figure out what is copied by the copyMaliciousCodeToNewVM.</b></u><br />
<br />
Then the JMP ntoskrnl.obfDerefrenceObject de-references the new driver object and returns to the system call that triggers the kernel function +130c.<br />
<br />
Figure 9 shows the contents of the copyMalicoiusCodeToNewVM (+100f). If you look it its logic, it basically matches the description above. However, there is one thing we'd like you to pay special attention:<br />
<br />
<u><b>Challenge 6. See figure 9, where is the new VM address (allocated by ZwAllocatevirtualMemory, i.e., 0x00380000) stored at?</b></u><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimMUexDi6O2MSj2-3LjX-pP77vaNvWHUty1Bc9F7xI6iZLGPfXzwk41w4D66UvWARYijMj11XrNz9_aYmf2k40aeZ_b6ZDRMndHtpJRYf9Jb6jx7VZD8oNkisI8Nlru0VqGcNa4TjJ8lo/s1600/a1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimMUexDi6O2MSj2-3LjX-pP77vaNvWHUty1Bc9F7xI6iZLGPfXzwk41w4D66UvWARYijMj11XrNz9_aYmf2k40aeZ_b6ZDRMndHtpJRYf9Jb6jx7VZD8oNkisI8Nlru0VqGcNa4TjJ8lo/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 9. Function Body of copyMalicousCodeToNewVM (0x1000100f)</td></tr>
</tbody></table>
<br />
<br />
If you look at the two highlighed instructions in Figure 9, you might notice that the 3rd parameter of 0x1000100F (copyMaliciousCodeToNewVM) is used to store 0x00380000. But why?<br />
<br />
<u><b>Challenge 7. Figure out what is the motivation for storing 0x00380000 in the 3rd parameter of 0x1000100F.</b></u><br />
<br />
To solve the above challenge, we need to go back to Figure 8, and we notice that it's <span style="font-family: "Courier New",Courier,monospace;"><u><b>f7c88d3c</b></u>which is passed to the call of 0x1000100F (copyMaliciousCodeToNewVM). </span><br />
Looking at the <u><b>ReactOS </b></u>information about kernel routine (search for <u><b>PKKERNEL_ROUTINE</b></u> on ReactOS), you will find that kernel routine (130c) accepts 5 parameters: <u><b>APC</b></u>, <u><b>pNormal_Routine</b></u>, <u><b>Normal_Context</b></u>, System_Arg, System_Arg2). So the <u><b>f7c88d3c </b></u>is actually the <u style="background-color: yellow; color: red;"><b>NORMAL_CONTEXT </b></u>parameter of the KERNEL_ROUTINE.! Similarly, you would find that <u><b>f7c88d48 (the second parameter)</b></u> is the <u><b>NORMAL_ROUTINE.</b></u><br />
<br />
Now, look the highlighted part in Figure 9 (two yellow underlines and three thicker ones), you will find that copyMalicoiusCodeToNewVM writes value 0x00380000 into both the place holders for <u><b>NORMAL_CONTEXT</b></u> and <u><b>NORMAL_ROUTINE</b></u>!<br />
<br />
<div style="background-color: yellow; color: red;">
<u><b>Lab Configuration for Analyzing Code 0x00380000: </b></u></div>
Clearly, the next step we would like to pursue is to debug the code located at <u><b>0x00380000</b></u> (originally copied from <u><b>0x10001338</b></u>). Interestingly, if you set a hardware BP in WinDbg, the debugger never stops on 0x00380000. We suspect that somehow hardware BP is cleared at some point. Only the software BP works in this scenario ("bp 0x00380000"), and in some scenarios you might find that your IMM actually gets the INT3 (software BP) interrupt and you have to now debug it in IMM. Figure 10 shows you the screen of IMM when the software BP is intercepted. You can see that the "instruction" at 0x00380000 is "INT3". <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHUiO5yzFk17eCcoY-NAvIUQp1xRVHWpRIJuMEWN8Pc6IbYNxb192mw5vU9AHsZPgeyn0y-hVGUtCQ-Q7udx9szyBUXNRTSXv_7VxGiwjwzsreRf9OtjWGaX0GXdVXqi_JZzkO6-vkmXg/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHUiO5yzFk17eCcoY-NAvIUQp1xRVHWpRIJuMEWN8Pc6IbYNxb192mw5vU9AHsZPgeyn0y-hVGUtCQ-Q7udx9szyBUXNRTSXv_7VxGiwjwzsreRf9OtjWGaX0GXdVXqi_JZzkO6-vkmXg/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 10. Interesting Debugging Behavior of WinDbg/IMM</td></tr>
</tbody></table>
<u><b>Open Challenge:</b></u> Figure out why the software BP set by WinDbg is intercepted by Immunity Debugger. (conjecture: the debug port of the operating system is reset by Max++).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr-A7w3J-1xULVpk8_iWEoInle7MXsKkXxawLLjQxTHWI5jSBgRVpFDWMyB_nHnFX3x6N9HO9E3Y79dMu5FjOs6xDGMfaw6YaZkAfkgk0Jiq34JA6Qmlq02YhLPabt-wXfw6JQGC8YSd0/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr-A7w3J-1xULVpk8_iWEoInle7MXsKkXxawLLjQxTHWI5jSBgRVpFDWMyB_nHnFX3x6N9HO9E3Y79dMu5FjOs6xDGMfaw6YaZkAfkgk0Jiq34JA6Qmlq02YhLPabt-wXfw6JQGC8YSd0/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 11. Code at 0x00380000</td></tr>
</tbody></table>
<br />
Figure 11 displays the logic of code at 0x00380000 (originally copied from 0x10001338). It mainly consists of three steps: (1) it searches for module "kernel32.dll", (2) it searches for funciton LoadLibraryW in the PE header, (3) it invokes function +1404 (we named it <u><b>LoadMax++00x86</b></u>).<br />
<br />
The main part of function LoadMax++00x86 (located at +1404) is shown in Figure 12.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjl4ndajKR8t0wypSieV5iHR1i4t_Zk90ms_Y4FSIt7M1CvQaXh3zqGLLto6aWEh-HCq-oDEqZDobv_O7L29MVlInRynfQUIyMii5FgIMMpl4uE5sjoAUKX4M2UIYeyznrq703SlyFDhY/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjl4ndajKR8t0wypSieV5iHR1i4t_Zk90ms_Y4FSIt7M1CvQaXh3zqGLLto6aWEh-HCq-oDEqZDobv_O7L29MVlInRynfQUIyMii5FgIMMpl4uE5sjoAUKX4M2UIYeyznrq703SlyFDhY/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 12. Load Max++.00.x86</td></tr>
</tbody></table>
<br />
The major bulk of the funciton + 1404 is the call of <u><b>LoadLibraryW("\.\C2CAD...max++.00.x86")</b></u>.<br />
<br />
<u><b>Challenge 8.</b></u> Prove the above statement is true (especially, <u><i><b>why is its parameter "\.\C2CAD...max++.00.x86"</b></i></u>?).<br />
<br />
<u><b>Summary:</b></u><br />
Up to now, combined with Tutorial 27, we have shown you the complete picture of the stealthy remote DLL loading technique. Max++ loads max++.x86.dll via three steps: (1) load B48DADF8.sys; (2) load max++.00.x86; and (3) load max++.x86.dll. During each step, a variety of techniques are employed to hide the trace, e.g., by modifying the kernel data structures of libraries. There are also techniques that we have not completely understand, see the open challenge in this tutorial.<br />
<br />Unknownnoreply@blogger.com59tag:blogger.com,1999:blog-8770073098084592029.post-54287084988374711732012-05-29T11:49:00.001-07:002012-05-29T11:49:04.920-07:00Malware Analysis Tutorial 28: Break Max++ Rootkit Hidden Drive Protection<b>Learning Goals</b>:<br />
<ol>
<li>Practice WinDbg for Intercepting Driver Loading</li>
<li>Practice IMM for Modifying Binary Code</li>
<li>Trace and Modify Control Flow Using IMM</li>
</ol>
<b>Applicable to:</b><br />
<ol>
<li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security</li>
</ol>
<u><b>1. Introduction</b></u><br />
<br />
One typical feature of Max++ is its ability to hide malicious files in a hidden drive. In this tutorial, we show you how to <u><b>modify the malware itself to break its hidden drive protection</b></u>. Our goal is to dig out the B48DADFD.sys from the hidden drive. Recall that B48DADFD.sys is used to load a series of malicious DLL files, introduced in <a href="http://fumalwareanalysis.blogspot.com/2012/05/malware-analysis-tutorial-27-stealthy.html">Tutorial 27</a>, <br />
<br />
<u><b>2. Preliminaries: Who Has Loaded B8DADFD.sys?</b></u><br />
We need to figure out who loads B48DADFD.sys first. Simply follow the instructions (1) to (4) of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-19-anatomy-of.html">Tutorial 19</a> to set up the lab experiment. Once the WinDbg is started, click Debug->Event Filter to enable the "Load Module" event (as shown in Figure 1). Then, after you hit the BP at 0x401417 in IMM, press SHIFT+F9 to let it go. The first module you capture will be "_" (the one which hacks lz32.dll) and the second hit will get you B48DADFD.sys.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuMHZMgbTx00JE8oLlzcCuHIH3fonopNJ8Iq7C_YgZl6TT4X6tHO0s-7U7Fz97eoK0rM_LGPXL9X3F7u8Wa-SUseFfr03EsTxt8bie3gwGAeicl9ad3G8Lksz2YtxvuvHN69oKkMlN1Yw/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuMHZMgbTx00JE8oLlzcCuHIH3fonopNJ8Iq7C_YgZl6TT4X6tHO0s-7U7Fz97eoK0rM_LGPXL9X3F7u8Wa-SUseFfr03EsTxt8bie3gwGAeicl9ad3G8Lksz2YtxvuvHN69oKkMlN1Yw/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Enable Event Filter on Module Loading</td></tr>
</tbody></table>
<br />
As shown in the following, when WinDbg hit DebugService2+0x10, it's the handler for module load event. If you list all current modules using "<u><b>lm</b></u>", you will notice that B48DADF8 is the module being loaded. We can further dump the stack contents to find out the caller.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
kd> g<br />
<u><b>nt!DebugService2+0x10:</b></u><br />
80506d3e cc int 3<br />
kd> <u><b>lm</b></u><br />
start end module name<br />
804d7000 806ed680 nt (pdb symbols) c:\windows\symbols\ntoskrnl.pdb\47A5AC97343A4A7ABF14EFD9E99337722\ntoskrnl.pdb<br />
<u><b>fadfc000 fae01000 B48DADF8 (deferred) </b></u> <br />
faed4000 faedc000 _ (deferred) <br />
<br />
Unloaded modules:<br />
f77c4000 f77ef000 kmixer.sys<br />
f7b6e000 f7b99000 kmixer.sys<br />
fb206000 fb207000 drmkaud.sys<br />
f7b99000 f7bbc000 aec.sys <br />
f7c89000 f7c96000 DMusic.sys<br />
facec000 facfa000 swmidi.sys<br />
fb0f0000 fb0f2000 splitter.sys<br />
fad6c000 fad77000 imapi.sys<br />
fad5c000 fad6b000 redbook.sys<br />
fae6c000 fae71000 Cdaudio.SYS<br />
fb050000 fb053000 Sfloppy.SYS<br />
fae64000 fae69000 Flpydisk.SYS<br />
fae5c000 fae63000 Fdc.SYS <br />
kd> <u><b>kv</b></u><br />
ChildEBP RetAddr Args to Child <br />
f76a251c 80506d80 f76a25b4 f76a2530 00000003 nt!DebugService2+0x10 (FPO: [Non-Fpo])<br />
f76a2540 805a3113 f76a25b4 fadfc000 ffffffff nt!DbgLoadImageSymbols+0x42 (FPO: [Non-Fpo])<br />
f76a26e4 805a7c9d f76a2800 00000000 00000000 nt!MmLoadSystemImage+0xa80 (FPO: [Non-Fpo])<br />
f76a2894 804de7ec 00000036 f76a2974 0000001c nt!NtSetSystemInformation+0x8a9 (FPO: [Non-Fpo])<br />
f76a2894 804dd98d 00000036 f76a2974 0000001c nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ f76a28a8)<br />
*** ERROR: Module load completed but symbols could not be loaded for *<br />
f76a2918 faed50c7 00000036 f76a2974 0000001c nt!ZwSetSystemInformation+0x11 (FPO: [3,0,0])<br />
WARNING: Stack unwind information not available. Following frames may be wrong.<br />
f76a299c faed6b93 ffbd2478 ffb23550 003f005c _+0x10c7<br />
f76a2a34 faed6bf8 ffbd2478 ffb23550 ffb97840 _+0x2b93<br />
f76a2a4c 804e37f7 ffa337b0 ffbd2468 ffbd2468 _+0x2bf8<br />
f76a2a5c 8056c712 ffa33798 ffaad86c f76a2c04 nt!<u><b>IopfCallDriver</b></u>+0x31 (FPO: [0,0,0])<br />
f76a2b3c 80563fec ffa337b0 00000000 ffaad7c8 nt!IopParseDevice+0xa12 (FPO: [Non-Fpo])<br />
f76a2bc4 805684da 00000000 f76a2c04 00000040 nt!ObpLookupObjectName+0x56a (FPO: [Non-Fpo])<br />
f76a2c18 8056cbeb 00000000 00000000 160de801 nt!ObOpenObjectByName+0xeb (FPO: [Non-Fpo])<br />
f76a2c94 8056ccba 0012d624 00100000 003d3150 nt!IopCreateFile+0x407 (FPO: [Non-Fpo])<br />
f76a2cf0 8056cdf0 0012d624 00100000 003d3150 nt!<u><b>IoCreateFile</b></u>+0x8e (FPO: [Non-Fpo])<br />
f76a2d30 804de7ec 0012d624 00100000 003d3150 nt!NtCreateFile+0x30 (FPO: [Non-Fpo])<br />
f76a2d30 7c90e4f4 0012d624 00100000 003d3150 nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ f76a2d64)<br />
0012d648 003c2507 00401166 003c0000 fffffffe 0x7c90e4f4<br />
0012ffd0 8054b6b8 0012ffc8 81148da8 ffffffff <u><b>0x3c2507</b></u><br />
00413a40 ec81ec8b 0000030c d98b5653 f4b58d57 nt!ExFreePoolWithTag+0x676 (FPO: [Non-Fpo])<br />
00413a4c f4b58d57 8bfffffd f45589c3 0000c0e8 0xec81ec8b<br />
00413a50 8bfffffd f45589c3 0000c0e8 10c38300 0xf4b58d57<br />
00413a54 f45589c3 0000c0e8 10c38300 0cf85d89 0x8bfffffd<br />
00413a58 00000000 10c38300 0cf85d89 f3b58dff 0xf45589c3</div>
<br />
<br />
<br />
As shown by the stack dump, it's the <u><b>lz32.dll </b></u>code (one instruction before <u><b>0x3C2507</b></u>) that eventually triggers the load of B48DADFD.sys. The chain of calls are:<br />
<br />
one instruction before 0x3C2507 (lz32.dll) --> ... --> IoCreateFile --> ... --> IopfCallDriver ... ---> load B484DADFD.sys<br />
<br />
<u><b>Challenge 1. Use the analysis techniques presented in <a href="http://fumalwareanalysis.blogspot.com/2012/05/malware-analysis-tutorial-27-stealthy.html">Tutorial 27</a> and analyze how B48DADFD is loaded.</b></u><br />
<br />
<br />
<br />
<u><b>3. Lab Configuration</b></u><br />
Given that B48DADFD is loaded by one instruction before <u><b>3C2507</b></u>, we can start our lab configuration to dig out the malicious driver file. The lab configuration is shown below:<br />
<br />
First, follow the instructions (1) to (4) of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-19-anatomy-of.html">Tutorial 19</a>. When the breakpoint at 0x004017 is hit, jump to <u style="background-color: yellow; color: red;"><b>0X3C2502 </b></u>in the CPU pane and set a software breakpoint on it (by right clicking in CPU pane -> go to expression). You should see the binary code as shown in Figure 2 below.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitH83ZGx9KQLdso0eoEWC5PVO4px606CdJtSl8bVKqoBI2uYQaOu7afcN1poLvQh6wJUnLQanNF0o01aDLDt3B-U6ZaCQn96vlDU36pdoJcN-rVlmpwZEHldcRVg3AFs8PSSU7-NQigOs/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitH83ZGx9KQLdso0eoEWC5PVO4px606CdJtSl8bVKqoBI2uYQaOu7afcN1poLvQh6wJUnLQanNF0o01aDLDt3B-U6ZaCQn96vlDU36pdoJcN-rVlmpwZEHldcRVg3AFs8PSSU7-NQigOs/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. Breakpoint Right Before Loading B48DADFD.sys</td></tr>
</tbody></table>
<br />
<br />
At this moment, we are now ready to take the B48DADFD out.<br />
<br />
<u><b>4. Surgery on Hidden Drive</b></u><br />
As the hidden drive is not visible in Windows explorer, we have to call some functions available in the windows system library to get B48DADFD.sys out of the hidden drive. This is possible because Max++ hooks up the file system driver to handle special requests on the hidden drive. Our plan is to overwrite the instructions right after the instruction of 0x003C2502, and try to copy the file out.<br />
<br />
Browsing the kernel32.dll (View -> Executable Modules -> ViewNames) gives us one good candidate, as shown in Figure 3.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSohMklGbsV2LIlYTJWLr2Gjm0T0BrEe8wboIvypfTJYCnRYgsTa2H05YkJE8J3GhLGiN26Uk28Bqzb80yERY-pu0RMfCI7_UoVbw64LmiD27PVUNfGGjaDo9qF9TxHTtMGYGjsPR5yH8/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSohMklGbsV2LIlYTJWLr2Gjm0T0BrEe8wboIvypfTJYCnRYgsTa2H05YkJE8J3GhLGiN26Uk28Bqzb80yERY-pu0RMfCI7_UoVbw64LmiD27PVUNfGGjaDo9qF9TxHTtMGYGjsPR5yH8/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. kernel32.dll CopyFileA</td></tr>
</tbody></table>
<br />
By <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa363851%28v=vs.85%29.aspx">MSDN</a>,the prototype of CopyFileA is defined as below: (where "A" stands for ASCII, i.e., how file name is encoded. You could see there are several variations in Figure 3, such as copyFileW).<br />
<br />
<pre style="font-family: "Courier New",Courier,monospace;">BOOL WINAPI CopyFile(
_In_ LPCTSTR lpExistingFileName,
_In_ LPCTSTR lpNewFileName,
_In_ BOOL bFailIfExists
);</pre>
<br />
So the following is our plan, starting at 0x003C250C, we can use IMM to modify the binary code and insert a instruction CALL 7C8286D6. Meanwhile, we will modify the stack contents so that the three parameters are arranged properly. We can first modify the instructions, as shown in Figure 4. Simply right click in CPU pane --> assemble (or press space bar), and type "CALL 7C8286D6") to modify the binary code.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9XVzlsdpLzl75PMKJ9cmKfItVR6NkiQafB46zUNYTOwbJanFUrOCVJUIYjayizPevNRT4KWq_U6w3_jIBaojCEGcqjXa5lvnOeDorMDwg8389Gl2WH4LrHghVMD2a4XimmIsd0pgpPsw/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9XVzlsdpLzl75PMKJ9cmKfItVR6NkiQafB46zUNYTOwbJanFUrOCVJUIYjayizPevNRT4KWq_U6w3_jIBaojCEGcqjXa5lvnOeDorMDwg8389Gl2WH4LrHghVMD2a4XimmIsd0pgpPsw/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Modify Binary Code in IMM</td></tr>
</tbody></table>
<br />
We now need to create the parameters for the CopyFileA call. We need to insert two strings in the data dump window, the general approach is shown in Figure 5. Right click -> Binary -> Edit. <u><b>Make sure that only insert data when EIP is 0x003c2507 to avoid destructing the data for previous calls of Max++.</b></u><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2XzrL0ouyI3ZfHXPzN9EC94cvmAoVjp3qPfbiYLVN9_Jtd3Hc107_coeiHb1VefPfEhdPL6pEqPDIj5nT0Wpx1l1izTev7y1k1rJlDqbmEcSpLLhZ_zztS3rfD1zYQpVeFBO3ufb6jA8/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2XzrL0ouyI3ZfHXPzN9EC94cvmAoVjp3qPfbiYLVN9_Jtd3Hc107_coeiHb1VefPfEhdPL6pEqPDIj5nT0Wpx1l1izTev7y1k1rJlDqbmEcSpLLhZ_zztS3rfD1zYQpVeFBO3ufb6jA8/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5. Modify Binary Code</td></tr>
</tbody></table>
<br />
The inserted data is shown in Figure 6. The file string "\\.\C2CAD...\B48DADF8.sys" is retrieved from the earlier analysis of the ntLoadImage in the stack dump in section 2. As shown in Figure 6, we inserted two pieces of strings, one is the "\\.\C2CAD...\B48DADF8.sys" and the other is "c:\bad.sys". Also the parameter setting is shown in the stack once we have entered the data in the memory dump pane. The third parameter (FailfExists) can be set to "false" (0).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJ1w5BElPpxAnfCGilVR39wONeVZf2zugPU4vX4kefuLNdT9F9w7NSIohcbk8KHFVPZsqj5qy9OzZLpbeV_AszMVNjh_up7sT0xSIZZMSDgoItEIc8BTDTVr-lqc8K7nJFXyb5xRy8MoU/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJ1w5BElPpxAnfCGilVR39wONeVZf2zugPU4vX4kefuLNdT9F9w7NSIohcbk8KHFVPZsqj5qy9OzZLpbeV_AszMVNjh_up7sT0xSIZZMSDgoItEIc8BTDTVr-lqc8K7nJFXyb5xRy8MoU/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6. The Input Parameters of CopyFileA</td></tr>
</tbody></table>
<br />
Execute one step in the CPU pane and we have successfully pulled out the malicious driver file out. See Figure 7.<br />
<br />
<u><b>Challenge 2. List all files in the hidden drive and take all of them out. </b></u><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzasd3z0w_ssIt9RKpgU8coUL7OmJgoUB7LKFwkLFXkzBmGqHKYUa3aoDkp4ZZu9U8QwyhVIhqE0cW80Ami98FMfi0cFvI5kdoILIK_HsZ0XCmBd7PfqHVZTY8w9EyQPRqz2YwyxAqf5o/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzasd3z0w_ssIt9RKpgU8coUL7OmJgoUB7LKFwkLFXkzBmGqHKYUa3aoDkp4ZZu9U8QwyhVIhqE0cW80Ami98FMfi0cFvI5kdoILIK_HsZ0XCmBd7PfqHVZTY8w9EyQPRqz2YwyxAqf5o/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 7. Success</td></tr>
</tbody></table>
<br />Unknownnoreply@blogger.com53tag:blogger.com,1999:blog-8770073098084592029.post-78853555518690916862012-05-25T17:32:00.004-07:002012-05-25T17:38:51.195-07:00Malware Analysis Tutorial 27: Stealthy Loading of Malicious DLL<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYx3xl_GX-pyT2ekJnp8IFgZGkyAoC5JD2ziVqJju8wgL0hkJwnTN4RGOIEvH6jxNMoyFTLgEhvfJOcgxqJnshmGqYzdkmVkDzPKxo2yfxVsI1dJUI_gfe_mrXcJVcu9YcXyrZPtiXqv8/s1600/cc1.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
<b>Learning Goals</b>:<br />
<ol>
<li>Practice the use of WinDbg for intercepting DLL loading </li>
<li>Use IMM Python scripts to log DLL loading sequence </li>
<li>Understand the stealthy DLL loading/hickjacking technique by malware </li>
</ol>
<b>Applicable to:</b><br />
<ol>
<li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security</li>
</ol>
<u><b>1. Introduction</b></u><br />
<br />
The following is my favorite from Rumsfield about malware analysis, although he is not a computing professional:<br />
<br />
"<b>There are known knowns; there are things we know we know. We also know there are known unknowns; that is to say we know there are some things we do not know. But there are also unknown unknowns – there are things we do not know we don't know.</b>"<br />
----- Donald Rumsfield<br />
<br />
<br />
This tutorial discusses one stealthy DLL loading behavior of Max++. It is something that we know we don't know. The analysis starts from <u><b>0x3C230F</b></u>.<br />
<br />
<br />
<u><b>2. Lab Configuration</b></u><br />
We could simply reuse the lab configuration of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html"><u><b>Tutorial 20</b></u></a>. In general, you need two windows XP instances, one for taking notes and the other for running the malware. Also you need a WinDbg instance sitting on the host to debug the win_debug instance. Specifically, in the win_debug instance, you need to set a breakpoint at <u><b>0x3C230F. This is the place right before the call of CALL WS2_32.WSASocketW, as shown in Figure 1 below.</b></u><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirSt7n4O_hbbGKcLjE9J_PV7nMcIClcR-8dHOpgGCs2V32mUqu5dP6YvoPJmVNoy8RfcWXMiyzes2F8I-k3_JOD9pvAchewK5kUtkKw4gqqBD3lj68m8NHG1ywKofif8wNMs89bbpvO8w/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirSt7n4O_hbbGKcLjE9J_PV7nMcIClcR-8dHOpgGCs2V32mUqu5dP6YvoPJmVNoy8RfcWXMiyzes2F8I-k3_JOD9pvAchewK5kUtkKw4gqqBD3lj68m8NHG1ywKofif8wNMs89bbpvO8w/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Something that we do not know that we do not know</td></tr>
</tbody></table>
<br />
<br />
<br />
As shown in Figure 1, at 0x3C230F, it is a call to <u><b>WS2_32.WSASocketW</b></u>, which tries to establish a TCP/IP socket. Interestingly, if you try to step it by F8, you might notice that your IMM will freeze for about 10 seconds and on its status bar, it is stating: trying to access <u><b>http://74.117.114.86\max++.x86.dll</b></u>.<br />
<br />
This is clearly not a good sign, why does the standard WSASocketW call need to invoke a remote DLL? There must be something that <u><i><b>we do not know that we do not know</b></i></u>!<br />
<br />
<u><b>3.IMM Debugger Scripts for Logging the Stack Frames When DLL Loading</b></u><br />
Our first attempt will be the immunity debugger itself. If you look at the Pycommands folder in the IMM system directory, you will notice that there are many interesting examples for controlling the Immunity Debugger using Python scripts! We are interested in exploring the following:<br />
(1) When are DLL loaded (specifically, why and when is max++.x86.dll loaded?)<br />
(2) Who issues the call to load DLLs?<br />
<br />
To answer these two questions, we rely on two features of the IMM Python library: (1) functions that allow us to print out stack frames, so that we could trace back to caller; and (2) event hookers that allow us to log the information when a DLL is loaded. Based on this information we could further explore the issue using breakpoints.<br />
<br />
In the following, find the source code of "<u><b>TraceDLLLoad.py</b></u>". You can simply place it in the <u><b>root directory </b></u>of IMM, and start the Python winodw in IMM (second button in the toolbar), and type "<u><b>from TraceDLLLoad import *</b></u>" and then "<u><b>hk = TraceDLLLoad(); </b></u>" and "<u><b>hk.add('abc');</b></u>" to set up the hook.<br />
<br />
<br />
<br />
<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
from immlib import *;</div>
<div style="font-family: "Courier New",Courier,monospace;">
from immutils import *;</div>
<div style="font-family: "Courier New",Courier,monospace;">
<br /></div>
<div style="font-family: "Courier New",Courier,monospace;">
HOOK_NAME = "testbplog"</div>
<div style="font-family: "Courier New",Courier,monospace;">
imm = Debugger();</div>
<div style="font-family: "Courier New",Courier,monospace;">
<br /></div>
<div style="font-family: "Courier New",Courier,monospace;">
class TraceDLLLoad(LoadDLLHook):</div>
<div style="font-family: "Courier New",Courier,monospace;">
</div>
<div style="font-family: "Courier New",Courier,monospace;">
def __init__(self):</div>
<div style="font-family: "Courier New",Courier,monospace;">
</div>
<div style="font-family: "Courier New",Courier,monospace;">
LoadDLLHook.__init__(self)</div>
<br />
<div style="font-family: "Courier New",Courier,monospace;">
def run(self, regs):</div>
<div style="font-family: "Courier New",Courier,monospace;">
</div>
<div style="font-family: "Courier New",Courier,monospace;">
ev = imm.getEvent();</div>
<div style="font-family: "Courier New",Courier,monospace;">
if ev.isLoadDll(): imm.log(" it is LOADDLL!---");</div>
<div style="font-family: "Courier New",Courier,monospace;">
</div>
<div style="font-family: "Courier New",Courier,monospace;">
imm.log("!!!!!!!! DLL Loaded: %x" % ev.lpImageName);</div>
<span style="font-family: "Courier New",Courier,monospace;"> baseaddr = ev.lpBaseOfDll;</span><br />
<div style="font-family: "Courier New",Courier,monospace;">
imm.log("!!!!!!!! DLL image: %x" % ev.lpBaseOfDll);</div>
<div style="font-family: "Courier New",Courier,monospace;">
</div>
<div style="font-family: "Courier New",Courier,monospace;">
regs = imm.getRegs();</div>
<div style="font-family: "Courier New",Courier,monospace;">
call_stack = imm.callStack()</div>
<div style="font-family: "Courier New",Courier,monospace;">
for frame in call_stack:</div>
<div style="font-family: "Courier New",Courier,monospace;">
imm.log("Addr= %08x | Stack = %08x | Procedure %s | Frame %08x | Called from %08x" \</div>
<div style="font-family: "Courier New",Courier,monospace;">
%(frame.address, frame.stack, frame.procedure, frame.frame, frame.calledfrom))</div>
<br />
<br />
The logic of the above script is pretty clear: it overrides the LoadDLLHook class in IMM, and whenenver a DLL is loaded, it prints out the stack contents. <br />
<br />
<br />
The dump of the log window is shown in Figure1, the image base of every DLL file is shown in Figure 2 (by clicking View -> Executable Modules in IMM).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjScqYDWNuPSMikiHeEy7EWZO4JGXV0sPYymOSh1mAJ5yaGSdho-ymEmWU3-_dTP_TYv-n_yjC1nqXxQiheWPTxD2QnW-OJszcsy5nCAAoAWegPJ5gAE73TlPj4AI9bMcClcIwTvQFr6o4/s1600/b1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjScqYDWNuPSMikiHeEy7EWZO4JGXV0sPYymOSh1mAJ5yaGSdho-ymEmWU3-_dTP_TYv-n_yjC1nqXxQiheWPTxD2QnW-OJszcsy5nCAAoAWegPJ5gAE73TlPj4AI9bMcClcIwTvQFr6o4/s1600/b1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. DLL Load Log</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk9cfROt_YkvIMPGxwc3aylbIn64Bsr0BYdUqR31i16yxuJu6W2C0VJAEd1CA6NbUCZxGvnBB-OnYxlUGSKUxqu5w7hnU2Tk-8F8U-0RIfV0KdExeUz_4g4tqgWQWxwBohshTGoQuSdQI/s1600/b2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk9cfROt_YkvIMPGxwc3aylbIn64Bsr0BYdUqR31i16yxuJu6W2C0VJAEd1CA6NbUCZxGvnBB-OnYxlUGSKUxqu5w7hnU2Tk-8F8U-0RIfV0KdExeUz_4g4tqgWQWxwBohshTGoQuSdQI/s1600/b2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. DLL Image Base</td></tr>
</tbody></table>
<br />
Observe Figure 1, you might have some interesting observation. First of all, while loading WSASocket, the system loads many DLLs (most likely by reading the imports of DLLs and load them recursively). The list includes old32.dll, mswsocket.dll etc. What's interesting to us is that <u><b>74.117.114.86\max++.x86.dll</b></u> is loaded at the end (with wshtcpip.dll), while the most astounding discoveries we have so far is: the system actually loads (and then unloads) another module:<u><b> \\.\C2CAD9724#4079...\L\max++.00.x86</b></u>! It is unloaded before max++.x86.dll is loaded! So that we don't have a trace of it in the visible executable module list in Figure 2! (<i>as we will show you later, actually the new max++.x86.dll is loaded by \\.\C2CAD...\max++.00.x86 and the new DLL takes its address space 0x35670000</i>).<br />
<br />
<br />
<br />
<u><b>4. First Attempt: Break on LdrLoadDll</b></u><br />
<br />
We now explore the use of IMM breakpoint to drill into the loading process of DLLs. We use <u><b>\\.\C2CAD9724...\L\max++.00.x86</b></u> as an example.<br />
<br />
Our first attempt would be to simply set a breakpoint at ntdll.LdrLoadDLL. This can be achieved using the following steps. In <u><b>IMM -> View -> Executable Modules</b></u>, find ntdll.dll and right click on it and then select <b>View->Names</b>. All functions exported from ntdll will be displayed in alphabetical order. Find the <b>LdrLoadDll </b>and set a breakpoint on it (F2). Go back to the CPU pane and press F9, we would be able to see that LdrLoadDll has been called multiple times. Figure 3 shows one of the stack frames of the call:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY7-QnxS2gyb4XdlcvzQBfj27GLP-Vt6iZPsrZHJ-EuoZVU3AeYeq5izGug9OuWFjNifNlMvaztlIZj-2FqMGwNSBLmHR7BOstPTA97FCJSelyKpYO9KyR-eaUISZgLG2gtxQPU2KVeIk/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY7-QnxS2gyb4XdlcvzQBfj27GLP-Vt6iZPsrZHJ-EuoZVU3AeYeq5izGug9OuWFjNifNlMvaztlIZj-2FqMGwNSBLmHR7BOstPTA97FCJSelyKpYO9KyR-eaUISZgLG2gtxQPU2KVeIk/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. LdrLoadDll Parameters</td></tr>
</tbody></table>
.Doing a simple Google search, we can easily find out the function definition of ntdll.LdrLoadDll. It has four parameters: (1) PathToFile, (2) Flags, (3) ModuleFileName, (4) handle. We are clearly interested in parameter 3 <u><b>ModuleName</b></u>, whose type is _Unicode_String. Observe the stack contents in Figure 3, we would easily find out that the <u><b>ModuleFileName </b></u>value is <u><b>0x0012CE8C</b></u>. (where the first highlighted area is the folder of max++, which corresponds to the first parameter).<br />
<br />
Right click on <u><b>0x112CE8C</b></u> and select "follow in dump", we have the RAM contents starting from <u><b>0x0012CE8C</b></u>. From the _Unicode_String documentation, we can soon follow that the first word (0x3E0040) indicates the max and the actual length of the unicode string, and the second word <u><b>0x7FFDEC00</b></u> contains the starting address of the actual string (in wide char). Go to 0x7FFDEC00, we have the contents shown in Figure 4: <u><b>c:\windows\system32\mswsock.dll</b></u>.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv0ejS8Ha1q5utP6RnCxhdkFYOqxg0MeQcCv679F34mj93CEQqB-fGQsEkTNP-hv5gNIfEtNCxOVB6QN40hTDIFfxHpVbTPmuQvISySSDQqK6tSojQUzPwn3HtgKDN0hlYamK5a7RMFe8/s1600/a2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv0ejS8Ha1q5utP6RnCxhdkFYOqxg0MeQcCv679F34mj93CEQqB-fGQsEkTNP-hv5gNIfEtNCxOVB6QN40hTDIFfxHpVbTPmuQvISySSDQqK6tSojQUzPwn3HtgKDN0hlYamK5a7RMFe8/s1600/a2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. String Contents of the DLL File Name</td></tr>
</tbody></table>
<br />
Using the similar approach, we find that the following DLLs are loaded in sequence:<br />
<br />
<u><b>mswsock.dll, \\.\C2CAD....\L\max++.00.x86, hnet.cfg.dll, mswsock.dll (again), wshtcpip.dll, SXS.dll </b></u><br />
<br />
Notice that the system might generate some random behavior, e.g., sometimes the SXS.dll in the sequence is replaced by wstheme.dll.This could be caused by random behavior of Max++ (but we have not verified in its code).<br />
<br />
It is also interesting to know <i><b>who calls LdrLoadDLL</b></i>. Figure 5 shows more contents of the stack when the mswsock.dll is first loaded. It is not hard to see the call chain: <u><b>LoadLibraryExA -> LoadLibraryExW->LdrLoadDll, </b>which loads mswsock.dll.</u><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgduTXPGGgHJFMu0hLPn5mme2Ppd_qrdnq3ylyPGGKAE-v1lh1c0JAkd9UiNxdHLUe5GDEA3IxzZ6t9ebICKQJyC4jnPcSUUoNidk2Q4xXMxM2_ejIARfcRHiBzMZ57iId_9UujhOgiLn4/s1600/a3.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgduTXPGGgHJFMu0hLPn5mme2Ppd_qrdnq3ylyPGGKAE-v1lh1c0JAkd9UiNxdHLUe5GDEA3IxzZ6t9ebICKQJyC4jnPcSUUoNidk2Q4xXMxM2_ejIARfcRHiBzMZ57iId_9UujhOgiLn4/s1600/a3.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5. More Stack Contents for Call Chain of LdrLoadDll</td></tr>
</tbody></table>
<br />
<br />
If we compare this sequence with the sequence shown in Figure 2, we might notice that there are two DLLs that are not captured using the brekapoint on LdrLoadDll: (1) the <u><b>old32.dll</b></u>, and (3) the <u><b>max++.x86.dll</b></u>! Clearly, <u><b>this approach does not work for max++.x86.dll</b></u>. But it should allow us to find who loads <u><b>\\?\C2CAD....\L\max++.00.x86</b></u> instead!<br />
<br />
<u><b>Challenge 1.</b></u> use the above technique to find out who loads max++.00.x86.<br />
<br />
<u><b>5. Second Attempt: Break on ntdll.KiFastSyscall</b></u><br />
Our second approach is to break on <u><b>KiFastSyscall</b></u>. This is motivated by the IMM trace log in Figure 2. It seems that IMM is capturing the call of loading DLLs by stopping at KiFastSyscall. In fact, KiFastSyscall is essentially a wrapper of core OS system in Windows. If you look at its implementation, you might notice that it sets up the service code and parameters in registers, and then invokes software interrupt.<br />
<br />
By setting a breakpoint at KiFastSyscall, we hope to get a better idea of how DLLs are loaded. Figure 6 below shows the stack contents of one of the KiFastSyscalls we intercepted. By looking at the stack contents, you might immediately infer that this is to perform <u><b>zwQueryAttributesFile for mswsock.dll</b></u>.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFxn_VyzC5pE7aYbF3zIHJc9EREc0hLcsbEITCundonAa2rU1DjS4-1_-4JWHFrDd7hUIocxV3FMnRIglBXNDC3TDeTf13WPMjXzLR6Vfi2JAPeQMNmOPNKIMFzPKuzMRCSIPnao_vvRs/s1600/a1.bmp" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFxn_VyzC5pE7aYbF3zIHJc9EREc0hLcsbEITCundonAa2rU1DjS4-1_-4JWHFrDd7hUIocxV3FMnRIglBXNDC3TDeTf13WPMjXzLR6Vfi2JAPeQMNmOPNKIMFzPKuzMRCSIPnao_vvRs/s1600/a1.bmp" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6. Syscall for zwQueryAttributeFile</td></tr>
</tbody></table>
<br />
The breakpoint will be hit multiple times for LdrLoadDll. The sequence of the calls are shown below: <u><b>zwFsControlFile, zwQueryAttributesFile, zwOpenFile, zwCreateSection, zwClose, zwMapViewOfSection, zwClose.</b></u><br />
<br />
Now we might have a good picture of the DLL loading: the system needs to read the DLL file, then <u><b>creates a section to map the new DLL into the original address space of the process</b></u>.<br />
<br />
<u><b>6. Who loads max++.00.x86?</b></u><br />
We now use the technique shown in section 4 to check who loads <u><b>max++.00.x86</b></u>. We will show the various delicate attempts that finally accomplish the goal.<br />
<br />
<u><b>6.1 Bottom-up Approach</b></u><br />
One natural thought would be to set a breakpoint at <u><b>LdrLoadDll </b></u>and then trace back along the stack frame. The lab configuration is pretty simple: Once reaching <u><b>0x3C230F</b></u>, set a breakpoint at ntdll.LdrLoadDll press <u><b>F9</b></u>, and when we hit LdrLoadDll twice, we are at the call to load <u><b>\\.\C2CAD..\max++.00.x86</b></u>. By using the technique of Section 4, you can observe the memory dump as shown in Figure 7.<br />
<br />
On the left of Figure 7, it is the string<u><b> \\.\C2CAD..\max++.00.x86</b></u>, and on the right, you can see that the Unicode string starts at <u><b>0x0012C4AC</b></u> (second highlighted area on the right).<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYx3xl_GX-pyT2ekJnp8IFgZGkyAoC5JD2ziVqJju8wgL0hkJwnTN4RGOIEvH6jxNMoyFTLgEhvfJOcgxqJnshmGqYzdkmVkDzPKxo2yfxVsI1dJUI_gfe_mrXcJVcu9YcXyrZPtiXqv8/s1600/cc1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYx3xl_GX-pyT2ekJnp8IFgZGkyAoC5JD2ziVqJju8wgL0hkJwnTN4RGOIEvH6jxNMoyFTLgEhvfJOcgxqJnshmGqYzdkmVkDzPKxo2yfxVsI1dJUI_gfe_mrXcJVcu9YcXyrZPtiXqv8/s1600/cc1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 7. Bottom-up Analysis</td></tr>
</tbody></table>
<br />
<br />
Now if we look at the right side of Figure 7 (stack contents), we see a lot of <u><i><b>candidates</b></i></u> for return address (note that Figure 7 does not show all the addresses, you need to scroll down in your IMM to see all of them). If we chain them up, we have a chain of <u><b>conjecture of return addresses</b></u> shown in Figure 8. Note that we call them "conjecture" because it's just a guess -- there is no reason that the malware will follow the standard C language calling convention, and thus all addresses (in the range of code segments of various modules) are regarded as <u><i><b>candidates </b></i></u>of return addresses. In Figure 8, areas with bold fonts are the ones verified by step-by-step execution in IMM. The ones with <span style="background-color: yellow;">yellow background </span>are actually not return addresses!<br />
<br />
Let us observe figure 8 (from the bottom), the logic is pretty clear: lz32 loads ws_32 module for network socket service, which calls load library to load mwsock32.dll. During the loading process, somehow, it calls zwMapViewOfSection, which loads library \\.\C2CAD...\max++.00.x86.<u><b> There must be some tricks about why zwMapViewOfSection needs to load \\.\C2CAD..\max++.00.x86?</b></u> We need to rely on further debugging to figure it out.<br />
<br />
----------------------------------------------------------------------------------------------------------<br />
----> <u><b>ntdll.7C801BBD </b></u>(stored at 0x0012C484)<br />
---> 0x0038005C (stored at 0x0012C4B0)<br />
---> <u><b>ntdll.7C80AEEC (part of LoadLibraryExW of \\.\C2CAD...\max++.00.x86)</b></u> (stored at 0x0012C4EC)<br />
--><span style="background-color: yellow;"> 0x003800CE (stored at 0x0012C4F0)</span><br />
--> <u><b>0x003800CE </b></u>(stored at 0x0012C500) <br />
<b> </b>--> <span style="background-color: yellow;">0x0038005C (stored at 0x0012C504 )</span><br />
---><u><b> 0x7C90E437</b></u> (<u><b>KiDispatchUserAPC, </b></u>stored at 0x0012C528 )<br />
---> 0x7C90E4F4 (ntdll.KiFastSyscallRet) (stored at 0x0012C5E0 )<br />
---> <u><b>0x7C90E4F4</b></u> (ntdll.KiFastSyscallRet) (stored at 0x0012C5F0 )<br />
---> <u><b>ntdll.0x7C90D50C</b></u> (stored at 0x0012C804 )<br />
---><u><b> ntdll.0x7C91BD03</b></u> (zwMapViewOfSection)(stored at 0x0012C808 )<br />
---> <u><b>ntdll.0x7C91624A</b></u> (stored at 0x0012C8FC )<br />
---><u><b> ntdll.0x7C801BBD</b></u> (part of ntdll.LoadLdrDll of mwsock32.dll) (stored at 0x0012CE64)<br />
---><br />
... a lot of ntdll calls<br />
--> <u><b>ws2_32.71AB78F1</b></u> [this is where ws2_32 calls load library) (stored at 0x0012CEFC)<br />
--> ...<br />
---> <u><b>lz32.0x003C2315</b></u> (this is the instruction right after 0x003C230F) (stored at 0x0012D314).<br />
<br />
<div style="text-align: center;">
Figure 8. Conjecture of Return Addresses in Stack</div>
<div style="text-align: center;">
---------------------------------------------------------------------------------------------------- </div>
<div style="text-align: center;">
<br /></div>
Let us first verify the actual return addresses in stack. This time, we use step by step execution (F8) instead of <i>execute until return</i> Ctrl+F9 (because it is unreliable). The following is the sequence of call chains we verified so far. You can verify that some "guessed" return addresses in Figure 8 are fake. Another interesting observation is that: when we get into KiDispatchUserAPC(7c90E437), we are not able to continue because the next instruction is <u><b>CALL zwContinue</b></u> (see Figure 10), which switches threads.<br />
<br />
----------------------------------------------------------------------------------------------<br />
LdrLoadDrll<br />
----><u><b> </b> ntdll.7C801BBD </u>(stored at 0x0012C484)<br />
----><u> ntdll.7C80AEEC</u> (LoadLibraryExW of max++.00.x86) (stored at 0x0012CE4C)<br />
-----> <u>0x003800CE</u> (stored at 0x0012C500)<br />
-----> ntdll.7C90E437 (<u><b>KiDispatchUserAPC</b></u>) (stored at 0x0012C528)<br />
<br />
<div style="text-align: center;">
Figure 9. Stack Frame Verification by Execution</div>
<div style="text-align: left;">
---------------------------------------------------------------------------------------------------</div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkCH83gU3l6cSB7Y-J4XSm5R5KUbmd3Y4w9b5Fn17_vYKkp65o4P14PBp1iBgGigLpbXyEAbTQdKV8lNrSux9GsSWtPse2GGtsgT47QuQBHI4gKilVku47gp_AKWKJGs8-Rq7TO3GShwI/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkCH83gU3l6cSB7Y-J4XSm5R5KUbmd3Y4w9b5Fn17_vYKkp65o4P14PBp1iBgGigLpbXyEAbTQdKV8lNrSux9GsSWtPse2GGtsgT47QuQBHI4gKilVku47gp_AKWKJGs8-Rq7TO3GShwI/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 10. Code of KiDispatchUserAPC</td></tr>
</tbody></table>
<br />
According to MSDN documentation, <u><b>KiDispatchUserAPC </b></u>is to handle a user APC (asynchronous procedure call), which is usually a queued time consuming I/O request. When it finishes the task, it calls <u><b>zwContinue </b></u>to resume the original thread's execution (i.e., it performs a context switch). Clearly, pressing F8 here will not work, because it's not going to hit the next instruction (in KiDispatchUserAPC) any more. Instead, we have to figure out what is the next instruction that the OS will resume. Looking at the documentation of zwContinue (or NtContinue), we found that it takes two parameters: pContenxt which points to a thread context structure and bRaiseAlert. By looking at the stack contents, we can infer that pContext's value is 0x0012C538, then we can easily display all of its contents using WinDbg (simply start a user level WinDbg and attach it to the Max++ process in <u><b>non-invasive mode</b></u>):<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">0:000> dt _CONTEXT 0x0012C538<br />ntdll!_CONTEXT<br /> +0x000 ContextFlags : 0x10017<br /> +0x004 <u><b>Dr0 : 0x4012dc</b></u><br /> +0x008 Dr1 : 0<br /> +0x00c Dr2 : 0<br /> +0x010 Dr3 : 0<br /> +0x014 Dr6 : 0xffff0ff0<br /> +0x018 Dr7 : 0x401<br /> +0x01c FloatSave : _FLOATING_SAVE_AREA<br /> +0x08c SegGs : 0<br /> +0x090 SegFs : 0x3b<br /> +0x094 SegEs : 0x23<br /> +0x098 SegDs : 0x23<br /> +0x09c Edi : 0<br /> +0x0a0 Esi : 0<br /> +0x0a4 Ebx : 0<br /> +0x0a8 Edx : 0x7c90e4f4<br /> +0x0ac Ecx : 0x900000<br /> +0x0b0 Eax : 0<br /> +0x0b4 Ebp : 0x12c8f8<br /> +0x0b8 <u><b>Eip : 0x7c90e4f4</b></u><br /> +0x0bc SegCs : 0x1b<br /> +0x0c0 EFlags : 0x296<br /> +0x0c4 Esp : 0x12c804<br /> +0x0c8 SegSs : 0x23<br /> +0x0cc ExtendedRegisters : [512] "???"</span><br />
<br />
You can see that the next EIP is <u><b>0x7C90E4F4</b></u>, and (you can also see Dr0: 0x4012DC, which is a hardware breakpoint which we set before). Now we can set up a breakpoint at 0x7C90E4F4 and continue the step-by-step execution analysis. We can verify that the following return addresses from Figure 8 are visited:<br />
<br />
---> <u><b>0x7C90E4F4</b></u> (ntdll.KiFastSyscallRet) (stored at 0x0012C5F0 )<br />
---> <u><b>ntdll.0x7C90D50C</b></u> (stored at 0x0012C804 )<br />
---><u><b> ntdll.0x7C91BD03</b></u> (zwMapViewOfSection)(stored at 0x0012C808 )<br />
---> <u><b>ntdll.0x7C91624A</b></u> (stored at 0x0012C8FC )<br />
---><u><b> ntdll.0x7C801BBD</b></u> (part of <i><b>ntdll.LoadLdrDll of ws2help.dll</b></i>) (stored at 0x0012CE64)<br />
So far we have verified all the return addresses, let's revisit them in Figure 8. Anything suspicious? Look at the following about those in red.<br />
<br />
----------------------------------------------------------------------------------------------------------- <br />
<br />
<div style="background-color: white;">
---> <u><b>ntdll.<span style="background-color: red;">7C80AEEC </span>(part of LoadLibraryExW of \\.\C2CAD...\max++.00.x86)</b></u> (stored at 0x0012C4EC)</div>
<div style="background-color: white;">
--> 0x003800CE (stored at 0x0012C4F0)</div>
<div style="background-color: white;">
--><span style="background-color: red;"> </span><u style="background-color: red;"><b>0x003800CE </b></u>(stored at 0x0012C500) </div>
<div style="background-color: white;">
<b> </b>--> 0x0038005C (stored at 0x0012C504 )</div>
<div style="background-color: white;">
---><u><b> 0x7C90E437</b></u> (<u><b>KiDispatchUserAPC, </b></u>stored at 0x0012C528 )</div>
<div style="background-color: white;">
---> 0x7C90E4F4 (ntdll.KiFastSyscallRet) (stored at 0x0012C5E0 )</div>
<div style="background-color: white;">
---> <u><b>0x7C90E4F4</b></u> (ntdll.KiFastSyscallRet) (stored at 0x0012C5F0 )</div>
<div style="background-color: white;">
---> <u><b>ntdll.0x7C90D50C</b></u> (stored at 0x0012C804 )</div>
<div style="background-color: white;">
---><u><b> ntdll.0x7C91BD03</b></u> (<span style="background-color: red;">zwMapViewOfSection</span>)(stored at 0x0012C808 )</div>
<div style="background-color: white;">
---------------------------------------------------------------------------------------------------------- </div>
<br />
The first question is: <u><b>why does zwMapViewOfSection calls LoadLibraryExW?</b></u><br />
The second question is: <u><b>what is the address range of <span style="background-color: yellow;">0x003800CE</span>? This looks like the addr range of some kernel. Also, if it is a kernel module, how come we could trace into it?</b></u><br />
<br />
The two questions are clearly related. We suspect that 0x003800CE is some malicious kernel modules loaded by Max++. In the following, we have to look into the challenge.<br />
<br />
<u><b>6.2 Stealthy Memory Segment at 0x00380000</b></u><br />
Figure 11 shows the list of memory segments of the system when we are hitting the breakpoint at LdrLoadDll for \\.\C2CAD...\max++.00.x86.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSdANuTfEb9ldSXc4R6XL_KtCnTeGrAih02gGvJffvWiFXaM47PBxuxZSPM2gcDg6-BIsjjpvU3_mTakdLg2kQfySOp6l7z3_YhcGk1xt6WIo853S6Kflz4NR_ymmflipYtf6FodcObPI/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSdANuTfEb9ldSXc4R6XL_KtCnTeGrAih02gGvJffvWiFXaM47PBxuxZSPM2gcDg6-BIsjjpvU3_mTakdLg2kQfySOp6l7z3_YhcGk1xt6WIo853S6Kflz4NR_ymmflipYtf6FodcObPI/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 11. Stealthy Memory Segment at 0x00380000</td></tr>
</tbody></table>
Note that this memory segment is very stealthy! When we hit the LdrLoadDll the first time (for loading mwsock32.dll), it is not there. Later, when we get back to the completion of zwMapViewOfSection (along the call chain in Figure 8), it disappears! From the memory map, we are not able to tell who is the owner of the segment 0x00380000!<br />
<br />
If we start a user level WinDbg and attach it to the max++ process, we could run the following command for finding the information of address 0x00380000, which does not yield more information than IMM.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;">0:000> !address 0x00380000 </span><span style="font-size: small;"><br style="font-family: "Courier New",Courier,monospace;" /></span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;">Failed to map Heaps (error 80004005)</span><span style="font-size: small;"><br style="font-family: "Courier New",Courier,monospace;" /></span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;">Usage: <u><b><unclassified></b></u></span><span style="font-size: small;"><br style="font-family: "Courier New",Courier,monospace;" /></span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;">Allocation Base: 00380000</span><span style="font-size: small;"><br style="font-family: "Courier New",Courier,monospace;" /></span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;">Base Address: 00380000</span><span style="font-size: small;"><br style="font-family: "Courier New",Courier,monospace;" /></span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;">End Address: 00381000</span><span style="font-size: small;"><br style="font-family: "Courier New",Courier,monospace;" /></span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;">Region Size: 00001000</span><span style="font-size: small;"><br style="font-family: "Courier New",Courier,monospace;" /></span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;">Type: 00020000 MEM_PRIVATE</span><span style="font-size: small;"><br style="font-family: "Courier New",Courier,monospace;" /></span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;">State: 00001000 MEM_COMMIT</span><span style="font-size: small;"><br style="font-family: "Courier New",Courier,monospace;" /></span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;">Protect: 00000040 PAGE_EXECUTE_READWRITE</span><br />
<br />
Our last report would be the kernel model WinDbg. The lab configuration is similar to <u><b>Section 2</b></u>, except that the windows image is started in the <u><b>DEBUGGED mode</b></u> and a <u><b>kernel WinDbg</b></u> is attached from the host machine. Then run to <u><b>0x003C203F</b></u>, we can start our analysis in kernel mode WinDbg (in the host system).<br />
<br />
Press <u><b>Ctrl+Break</b></u> in WinDbg to get into the command mode. Our first step is to find out and attack to the process using the kernel mode WinDbg.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">kd> !process 0 0<br />**** NT ACTIVE PROCESS DUMP ****<br />PROCESS 812ed020 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000<br /> DirBase: 00039000 ObjectTable: e1000d10 HandleCount: 239.<br /> Image: System<br /><br />...</span></div>
<div style="font-family: "Courier New",Courier,monospace;">
<br /></div>
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">PROCESS <u><b>ff9d9020 </b></u>SessionId: 0 Cid: 0130 Peb: 7ffde000 ParentCid: 07f8</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> DirBase: 0999d000 ObjectTable: e1aa7bc0 HandleCount: 40.</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> Image: <u><b>Max++ downloader install_2010.exe</b></u></span></span><br />
<br />
<span style="font-size: small;">kd> .process</span><br />
<span style="font-size: small;">80559c20 ...</span><br />
<br />
We find that that the process id of Max++ is ff9d9020. The current process (kernel) is 80559c20. Then we attach to it.<br />
<br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">kd> .process ff9d9020</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">Implicit process is now ff9d9020</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">WARNING: .cache forcedecodeuser is not enabled</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> dd 00380000</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">00380000 ???????? ???????? ???????? ????????</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">00380010 ???????? ???????? ???????? ????????</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">00380020 ???????? ???????? ???????? ????????</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">00380030 ???????? ???????? ???????? ????????</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">00380040 ???????? ???????? ???????? ????????</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">00380050 ???????? ???????? ???????? ????????</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">00380060 ???????? ???????? ???????? ????????</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">00380070 ???????? ???????? ???????? ????????</span></span><br />
<br />
As shown by the above, segment 0x00380000 has not been created yet. But we could set a memory breakpoint on the address, when it is being written, and see what we get.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">kd> ba w1 0x003800CE<br />kd> bl<br /> 0 e 003800ce w 1 0001 (0001) </span></div>
<br />
Note that 0x003800CE is the return address as shown in Figure 8. We are interested in finding out who sets up the code at that address. here "<u><b>ba w1 0x003800CE</b></u>" means to set a memory breakpoint at 0x003800CE whenever that byte is overwritten. Now type "g" (meaning continue) in GDB and F9 in the IMM, we have the breakpoint hit.<br />
<br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"><b>B48DADF8+0x105f:<br />faea505f f3a5 rep movs dword ptr es:[edi],dword ptr [esi]</b></span><b><span style="font-family: "Courier New",Courier,monospace;">kd> r edi</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">edi=003800d0</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> r esi</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">esi=faea5408</span></b></span><br />
<br />
<br />
Clearly, the code is trying to copy from 0xFAF3D408 to 0x003800D0. Now the interesting part: who owns code located at 0xFAF3D05F (the rep moves instruction)? Doing an !address 0x003800CE yields nothing. Looking at the prompt "B48DADF8+0x105f", we know that the code belongs to a module named B48DADF8. This can be confirmed by:<br />
<br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">kd> lm</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">start end module name</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">804d7000 806ed680 nt (pdb symbols) c:\windows\symbols\ntoskrnl.pdb\47A5AC97343A4A7ABF14EFD9E99337722\ntoskrnl.pdb</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">f7612000 f761b000 HIDCLASS (deferred) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">f7682000 f76ac180 kmixer (deferred) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">f76b9000 f76bb880 hidusb (deferred) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">f76bd000 f76bff80 mouhid (deferred) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"><u><b>faea4000 faea9000 B48DADF8 (no symbols) </b></u> </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">faf24000 faf2c000 _ (deferred) </span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">Unloaded modules:</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fad9c000 fada5000 HIDCLASS.SYS</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafec000 fafef000 hidusb.sys</span></span><br />
...<br />
<br />
Clearly B48DADF8 is a kernel module loaded earlier by Max++. But when is it loaded? We leave this as a challenge to you.<br />
<br />
<u><b>Challenge 1.</b></u> Find out when B48DADF8 is loaded (hint: enable the event handler of WinDbg for watching module loads and combine it with the analysis of stack).<br />
<br />
<u><b>6.3 Conclusion about Max++.00.x86</b></u><br />
lz32.dll loads <u><b>B48DADF8 </b></u>as a kernel module and modifies the system service table for handling zwMapViewSection. B4DADF8 then creates the memory segment 0x00380000 in Max++, and resets the kernel handling table for zwMapViewSection. When zwMapViewSection tries to SYSENTER, it jumps to 0x003800CE, which issues a call of LoadLibraryW("max++.00.x86"). This is how max++.00.x86 is loaded. Notice that it is achieved via remote kernel module loading and redirection of system call - this avoids it be discovered by prevalent virus detectors.<br />
<br />
However, this approach does have some vulnerability. Notice that SYSENTER is supposed to enter kernel code. The malware author intends to be lazy here and directly calls the user level ntdll.LoadLibrary and ntdll.LdrLoadDll, which actually allows us to trace to unknown/newly created memory region 0x380000, which eventually leads to the discovery of B48DADF8 module. Had the malware author embed all the load library code in kernel, it would be much more difficulty to find it out.<br />
<br />
<u><b>7. Who Loads the Remote http://74.117.114.86\max++.x86.dll?</b></u> <br />
<br />
We now try to analyze who loads <u><b>http://74.117.114.86/max++.x86.dll</b></u>. As shown in Figure 2, the LoadDllHook is not able to capture the loading of a remote DLL, however IMM does see its loading. We need to find another way out. Again, we will resort to the kernel mode WinDbg.<br />
<br />
Before we proceed, keep in mind that the <u><b>\\.\C2CAD...\max++.00.x86</b></u> is loaded in the<span style="color: red; font-size: large;"> <u style="background-color: yellow;"><b>0x35670000</b></u></span> range. This is easily visible in IMM -> View -> Executable Modules.<br />
<br />
<u><b>7.1 Lab Instructions </b></u><br />
<br />
Now start the lab setting following the instructions in<u><b> Section 6.2</b></u> (kernel mode WinDbg), then run in IMM until you see that IMM shows that it is trying to load http://74.117.114.86/max++.x86.dll in its status bar (as shown in the red boxed area in Figure 12). <u><b>Make sure to cut off the internet of the WinXP image </b></u>(so that the effort to load 74.117.114.86/max++.x86.dll will fail). Now press <u><b>Ctrl + Break</b></u> in the kernel WinDbg to stop the running.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-MjymTcVWNTTdCm0UknqcV-a9IUgIkUkyHgJc7l85KHs6EuP_qZqJ0made_ARqdViu2p1TG5blhvUTl-FXNCg6IdCtVUxDOCPD1MqpjmASMkW4grIoje_4kIfmtaCF-V-CiZofwz7xY8/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-MjymTcVWNTTdCm0UknqcV-a9IUgIkUkyHgJc7l85KHs6EuP_qZqJ0made_ARqdViu2p1TG5blhvUTl-FXNCg6IdCtVUxDOCPD1MqpjmASMkW4grIoje_4kIfmtaCF-V-CiZofwz7xY8/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 12. Intercepting Load of remote DLL</td></tr>
</tbody></table>
<br />
<u><b>7.2 Analysis</b></u><br />
Now we are interested in figuring out the status of all related processes in the system. Type<u><b> !process 0 0 </b></u>will give us the list of all existing processes. We now have the process "address" (regard it process ID) of Max++ is 81180228. We could then display all of its details, as shown in the following. It's long, but easy to interpret. <u><b>Take a moment to read and guess: there are two threads. Which thread loads 74.117.1147.86/max++.x86.dll?</b></u><br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> <u><b>!process 81180228 7</b></u></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">PROCESS 81180228 SessionId: 0 Cid: 0214 Peb: 7ffd4000 ParentCid: 01ac</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> DirBase: 01652000 ObjectTable: e1070918 HandleCount: 51.</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> Image: Max++ downloader install_2010.exe</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> ...</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> <u><b>THREAD 811807f0</b></u> Cid 0214.01e4 Teb: 7ffdf000 Win32Thread: e10c6118 WAIT: (Suspended) KernelMode Non-Alertable</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">SuspendCount 1</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> 8118098c Semaphore Limit 0x2</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> ...</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> Stack Init f7d10000 Current f7d0fb68 Base f7d10000 Limit f7d0c000 Call 0</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> Priority 10 BasePriority 8 PriorityDecrement 0 DecrementCount 16</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> ChildEBP RetAddr Args to Child </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f7d0fb80 804dc0f7 81180860 811807f0 804dc143 nt!KiSwapContext+0x2e (FPO: [Uses EBP] [0,0,4])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f7d0fb8c 804dc143 8118095c 811807f0 81180824 nt!KiSwapThread+0x46 (FPO: [0,0,0])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f7d0fbb4 804f8ca9 00000000 00000005 00000000 nt!KeWaitForSingleObject+0x1c2 (FPO: [Non-Fpo])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f7d0fbcc 804f1718 00000000 00000000 00000000 nt!KiSuspendThread+0x18 (FPO: [3,0,0])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f7d0fc14 804ecae9 00000000 00000000 00000000 nt!KiDeliverApc+0x124 (FPO: [Non-Fpo])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f7d0fc2c 804dc143 00000000 811807f0 e1767f58 nt!KiSwapThread+0x64 (FPO: [0,0,0])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f7d0fc54 8058f9db 00000001 00000000 00000001 nt!KeWaitForSingleObject+0x1c2 (FPO: [Non-Fpo])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f7d0fd10 80587a0f 00185f18 0012c608 0012c610 nt!NtSecureConnectPort+0x662 (FPO: [Non-Fpo])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f7d0fd3c 804de7ec 00185f18 0012c608 0012c610 <u><b>nt!NtConnectPort</b></u>+0x24 (FPO: [Non-Fpo])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f7d0fd3c 7c90e4f4 00185f18 0012c608 0012c610 nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ f7d0fd64)</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">WARNING: Frame IP not in any known module. Following frames may be wrong.</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> 0012c6f8 00000000 00000000 00000000 00000000 0x7c90e4f4</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> <u><b>THREAD 81228da8 </b></u> Cid 0214.07c0 Teb: 7ffde000 Win32Thread: e171a6f0 WAIT: (Suspended) KernelMode Non-Alertable</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">SuspendCount 1</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> ...</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> Win32 Start Address 0x35671d82</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> Start Address 0x7c8106e9</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> Stack Init f76e4640 Current f76e40f0 Base f76e5000 Limit f76e1000 Call f76e464c</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> Priority 10 BasePriority 8 PriorityDecrement 0 DecrementCount 0</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> ChildEBP RetAddr Args to Child </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f76e4108 804dc0f7 81228e18 81228da8 804dc143 nt!KiSwapContext+0x2e (FPO: [Uses EBP] [0,0,4])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f76e4114 804dc143 81228f14 81228da8 81228ddc nt!KiSwapThread+0x46 (FPO: [0,0,0])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f76e413c 804f8ca9 00000000 00000005 00000000 nt!KeWaitForSingleObject+0x1c2 (FPO: [Non-Fpo])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f76e4154 804f1718 00000000 00000000 00000000 nt!KiSuspendThread+0x18 (FPO: [3,0,0])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f76e419c 806f4c0e 00000000 00000000 f76e41b4 nt!KiDeliverApc+0x124 (FPO: [Non-Fpo])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">WARNING: Frame IP not in any known module. Following frames may be wrong.</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f76e41c0 804dcce5 badb0d00 f76e4238 00000000 0x806f4c0e</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f76e4230 8065b4d0 ffffff00 f76e424c 8065b4da nt!ZwFlushInstructionCache+0x11 (FPO: [3,0,0])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f76e423c 8065b4da 00000000 00000000 f76e42fc nt!DbgkpSendApiMessage+0x50 (FPO: [Non-Fpo])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f76e424c 80610d25 f76e4268 00000001 81180228 nt!DbgkpSendApiMessage+0x5a (FPO: [Non-Fpo])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f76e42fc 8057d8f2 e1d43d10 5ad70000 00000000 nt!DbgkMapViewOfSection+0xba (FPO: [Non-Fpo])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f76e4374 804de7ec 000000c8 ffffffff 009ff318 nt!<u><b>NtMapViewOfSection</b></u>+0x31a (FPO: [Non-Fpo])</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> f76e4374 7c90e4f4 000000c8 ffffffff 009ff318 nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ f76e43a4)</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> 009ff334 00000000 00000000 00000000 00000000 0x7c90e4f4</span></span><br />
<br />
<br />
Although the first thread is doing some network connections, the second thread (<u><b>81228da8</b></u>) is actually the one which loads the remote DLL. Let's take a deeper look in WinDbg. We need to first properly set up the context (specify the current process and thread being inspected to be 81180228 and 81228da8, thus, when we speak of a virtual address, it is for the process we want). Then we display the stack contents of thread 81228da8 using command "<u><b>kv</b></u>", as shown in the following.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
kd> <b>.process 81180228</b><br />
Implicit process is now 81180228<br />
WARNING: .cache forcedecodeuser is not enabled<br />
kd> <b>.thread 81228da8</b><br />
Implicit thread is now 81228da8<br />
kd> <u><b>kv</b></u><br />
*** Stack trace for last set context - .thread/.cxr resets it<br />
ChildEBP RetAddr Args to Child <br />
f76e4108 804dc0f7 81228e18 81228da8 804dc143 nt!KiSwapContext+0x2e (FPO: [Uses EBP] [0,0,4])<br />
f76e4114 804dc143 81228f14 81228da8 81228ddc nt!KiSwapThread+0x46 (FPO: [0,0,0])<br />
f76e413c 804f8ca9 00000000 00000005 00000000 nt!KeWaitForSingleObject+0x1c2 (FPO: [Non-Fpo])<br />
f76e4154 804f1718 00000000 00000000 00000000 nt!KiSuspendThread+0x18 (FPO: [3,0,0])<br />
f76e419c 806f4c0e 00000000 00000000 f76e41b4 nt!KiDeliverApc+0x124 (FPO: [Non-Fpo])<br />
WARNING: Frame IP not in any known module. Following frames may be wrong.<br />
f76e41c0 804dcce5 badb0d00 f76e4238 00000000 0x806f4c0e<br />
f76e4230 8065b4d0 ffffff00 f76e424c 8065b4da nt!ZwFlushInstructionCache+0x11 (FPO: [3,0,0])<br />
f76e423c 8065b4da 00000000 00000000 f76e42fc nt!DbgkpSendApiMessage+0x50 (FPO: [Non-Fpo])<br />
f76e424c 80610d25 f76e4268 00000001 81180228 nt!<u><b>DbgkpSendApiMessage</b></u>+0x5a (FPO: [Non-Fpo])<br />
f76e42fc 8057d8f2 e161b338 5ad70000 00000000 nt!<u><b>DbgkMapViewOfSection</b></u>+0xba (FPO: [Non-Fpo])<br />
f76e4374 804de7ec 000000c8 ffffffff 009ff318 nt!<u><b>NtMapViewOfSection</b></u>+0x31a (FPO: [Non-Fpo])<br />
f76e4374 7c90e4f4 000000c8 ffffffff 009ff318 nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ f76e43a4)<br />
009ff334 7c91624a 00189ee0 009ff3c0 009ff8e8 0x7c90e4f4<br />
009ff5f4 7c9164b3 00000000 00189ee0 009ff8e8 0x7c91624a<br />
009ff89c 7c801bbd 00189ee0 009ff8e8 009ff8c8 0x7c9164b3<br />
009ff904 7e428055 009ff968 00000000 00000008 0x7c801bbd<br />
009ff930 7c90e453 009ff940 00000068 00000068 0x7e428055<br />
009ffe48 7e42e442 00000000 0000c038 009ffee0 0x7c90e453<br />
009ffef4 7e42d0d6 00000000 0000c038 009ffee0 0x7e42e442<br />
009fff30 77512f04 00000000 0000c038 774ed2a4 0x7e42d0d6<br />
009fff7c 774ff041 00000000 00000002 7c97b2b0 0x77512f04<br />
009fff9c 77502a62 00181358 00000002 009fffec 0x774ff041<br />
009fffac 35671d93 00000000 7c80b713 00000000 0x77502a62<br />
009fffec 00000000 35671d82 00000000 00000000 0x<span style="background-color: yellow; color: red; font-size: large;"><u><b>35671d93</b></u></span></div>
<br />
<br />
<br />
Now, we could have the flow of funtion calls, first it's<br />
<br />
<div style="background-color: yellow;">
35671D93 --> 77502A62 ---> ... 7C91624A ---> NtMapViewOfSection ---> DbgkMapViewOfSection ---> DbgkpSendApiMessage.</div>
<br />
Note the first <u><b>35671D93</b></u> (this is a part of<u style="background-color: orange;"><b> max++.00.x86</b></u>!). Again, look back at Figure 12, <u><b>35671D8D</b></u> is actually the reall caller and 35671D93 is the return address. At 35671D8D, it is calling <u><b>ole32.CoInitialize</b></u>, which initializes the compartment environment for OLE32 objects (which reorganizes the address space and loads a new DLL named "uwtheme.dll"). However, during the loading process, the remote DLL is loaded. What happened?<br />
<br />
Let's try to delve more into the call sequence above. It is clear that CoInitialize loads DLL (called LdrLoadDll on "uwtheme.dll" and then maps it into the current processes's address space using NtMapViewOfSection). NtMapViewOfSection instead calls DbgkMapViewOfSection, which is the "debugged version" of NtMapViewOfSection, because it finds that there is a debugger attached and actually lets the debugger to load the DLL (so IMM should have the ability to monitor the loading of all DLLs!). The mission is accomplished by sending a debug API command via the debug port, via calling <u><b>DbgkpSendApiMessage</b></u>. Then a software trap is generated, the IMM debugger should be responsible for handling that ApiMessage (i.e., to load the DLL).<br />
<br />
The natural step next is to inspect the status of IMM debugger. Similarly, using "!process 0 0" we can find the process id (address) of IMM and inspect its threads and stack dump as below.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">kd> !<u><b>process 81181da0 7</b></u></span><br />
<span style="font-family: "Courier New",Courier,monospace;">PROCESS 81181da0 SessionId: 0 Cid: 01ac Peb: 7ffdf000 ParentCid: 05f8</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> DirBase: 08b8e000 ObjectTable: e1c38850 HandleCount: 139.</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> Image: ImmunityDebugger.exe</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> ...</span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"> <u><b>THREAD 8117e748 </b></u> Cid 01ac.075c Teb: 7ffde000 Win32Thread: e1023598 WAIT: (UserRequest) KernelMode Non-Alertable</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> 8119f7a4 SynchronizationEvent</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> IRP List:</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> ffbdff68: (0006,0094) Flags: 00000884 Mdl: 00000000</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> Not impersonating</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> ...</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> ChildEBP RetAddr Args to Child </span><br />
<span style="font-family: "Courier New",Courier,monospace;"> f7d5f868 804dc0f7 8117e7b8 8117e748 804dc143 nt!KiSwapContext+0x2e (FPO: [Uses EBP] [0,0,4])</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> f7d5f874 804dc143 00000000 8119f778 8119f7a4 nt!KiSwapThread+0x46 (FPO: [0,0,0])</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> f7d5f89c fa96392e 00000000 00000006 00000000 nt!KeWaitForSingleObject+0x1c2 (FPO: [Non-Fpo])</span><br />
<span style="font-family: "Courier New",Courier,monospace;">WARNING: Frame IP not in any known module. Following frames may be wrong.</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> f7d5f998 80564b0d 00000080 c00000be f7d5fa04 0xfa96392e</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> f7d5fa04 804e37f7 812c4b28 ffbdff68 ffbdff68 nt!SepPrivilegeCheck+0x8d (FPO: [Non-Fpo])</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> f7d5faf4 80563fec 812c4b28 00000000 ffb776a8 <u><b>nt!IopfCallDriver</b></u>+0x31 (FPO: [0,0,0])</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> f7d5fb7c 805684da 00000000 f7d5fbbc 00000040 nt!ObpLookupObjectName+0x56a (FPO: [Non-Fpo])</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> f7d5fbd0 805745a3 00000000 00000000 bf823d01 nt!ObOpenObjectByName+0xeb (FPO: [Non-Fpo])</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> f7d5fd54 804de7ec 0022e278 0022e250 0022e2a4 <u><b>nt!NtQueryAttributesFile</b></u>+0xf1 (FPO: [Non-Fpo])</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> f7d5fd54 7c90e4f4 0022e278 0022e250 0022e2a4 nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ f7d5fd64)</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> 0022e2a4 7c916f13 0022e2b4 00000001 003c003a 0x7c90e4f4</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> 0022e2bc 7c9172f3 7c97bec8 00000001 0022e5cc 0x7c916f13</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> 0022e2dc 7c916023 002d5330 7c97bec8 00000000 0x7c9172f3</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> 0022e5a4 7c916866 002d5330 0022e5cc 0022e600 0x7c916023</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> 0022e620 7c916698 00000001 002d5330 00000000 0x7c916866</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> 0022e63c 7c801d23 002d5330 00000000 0022e668 0x7c916698</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> 0022e6a4 77c013bd 002e4758 00000000 00000002 0x7c801d23</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> 0022e6f4 77c01a28 002e4758 0022e854 015374e0 0x77c013bd</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> 0022e718 0049715a 015374e0 0022e854 01536960 0x77c01a28</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> 0022e878 004977a3 015374e0 01537894 00000014 0x49715a</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> 0022f548 00453e01 0022fe44 00000000 00000000 0x4977a3</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> 0022ffa8 80581c9f 7c90dc9c 7c817064 fffffffe 0x453e01</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> 00230018 00000000 00000014 00000001 00000006 nt!CcPfBeginAppLaunch+0x19f (FPO: [Non-Fpo])</span><br />
<br />
The thread <span style="font-family: "Courier New",Courier,monospace;"><u><b>with id 8117e748</b></u> </span>shown in the above dump is the thread responsible for handling the DbgApiMsg (and thus needs to load the remote DLL). We can verify this by looking at the parameters of the function calls in the call stack. As shown by the <a href="http://msdn.microsoft.com/en-us/library/cc512135%28v=vs.85%29.aspx">MSDN documentatio</a>n, the function prototype of NtQueryAttributesFile is:<br />
<br />
<pre style="font-family: "Courier New",Courier,monospace;">NTSTATUS NtQueryAttributesFile(
__in POBJECT_ATTRIBUTES ObjectAttributes,
__out PFILE_BASIC_INFORMATION FileInformation
); </pre>
<pre> </pre>
<pre> We are interested in figuring out its first parameter, as shown in the following:</pre>
<pre> </pre>
<pre><span style="font-family: "Courier New",Courier,monospace;">kd> dt _OBJECT_ATTRIBUTES 0022e278 </span>
<span style="font-family: "Courier New",Courier,monospace;">nt!_OBJECT_ATTRIBUTES</span>
<span style="font-family: "Courier New",Courier,monospace;"> +0x000 Length : 0x18</span>
<span style="font-family: "Courier New",Courier,monospace;"> +0x004 RootDirectory : (null) </span>
<span style="font-family: "Courier New",Courier,monospace;"> +0x008 ObjectName : 0x0022e29c _UNICODE_STRING "<u><b>\??\UNC\74.117.114.86\max++.x86.dll</b></u>"</span>
<span style="font-family: "Courier New",Courier,monospace;"> +0x00c Attributes : 0x40</span>
<span style="font-family: "Courier New",Courier,monospace;"> +0x010 SecurityDescriptor : (null) </span>
<span style="font-family: "Courier New",Courier,monospace;"> +0x014 SecurityQualityOfService : (null) </span>
</pre>
<pre> </pre>
<pre>Bingo, now the IMM is tricked into loading the remote DLL located at 74.117.114.86. But the question is:</pre>
<pre></pre>
<pre><u><b>Challenge 2. Since ole32.CoInitialize originally intends to load </b><b>wstheme</b></u><u><b>.dll, why is 74.117.114.86\max.x86.dll loaded?</b></u></pre>
<u><b>(hints: search for string "max++.x86.dll" in "\\.\C2CAD...\max++.00.x86" and set data breakpoints for it and find out how it is used)</b></u><br />
<br />
<br />
<br />Unknownnoreply@blogger.com110tag:blogger.com,1999:blog-8770073098084592029.post-57711119473139690992012-04-12T07:37:00.000-07:002012-04-12T07:37:41.562-07:00Malware Analysis Tutorial 26: Rootkit Configuration<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhW_v0ApdJgpw0jovCxUV6PtfV1hPaAeuFfMBU_qo5ws0oy3x_kj80EbcJC1CKnZnY-1F5v7bWuE5ejd4JQg7LeSM666l6DQ69XttdXX3mLhRBQ0zK9Hx57y5SunI5B7KBl-VNOfJf2fqA/s1600/a1.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgenKdOPADJvsboB5lUMeKDWiGmCyQ1EI5dwhJSDzngtEunt9Nf7rmAtiYN4M9PfRk4r9ycxSP44bmebKWNYmBG4MwZ88475JOGzvLd0ml6tAER1qAs6SLAs5SyV97T0i_8geIBogGXbXA/s1600/a1.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><b>Learning Goals</b>:<br />
<ol><li>Practice the use of user mode WinDbg for inspecting process in non-invasive mode</li>
<li>Practice the use of IMM and WinDbg for data analysis</li>
<li>Understand registry operations</li>
<li>Understand file operations at multiple levels</li>
<li>Understand the high level network operations</li>
<li>Practice the general unpacking technique and searching for the decoding key</li>
</ol><b>Applicable to:</b><br />
<ol><li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security</li>
</ol><u><b>1. Introduction</b></u><br />
In this section, we go back to the analysis of lz32.dll and finish the rest of it. We will see a wide variety of malicious operations performed by the malicious lz32.dll injected by Max++, including disk formatting of the hidden drive, generation of network payload and configuration, unpacking of code segment, and infection of other system library files.<br />
<br />
Our analysis will be mostly performed in the address range 0x3Cxxxx, and for some part we will have to dig into the raspppoe.sys again. We start the analysis from the address <u><b>0x3C1B3E</b></u>. Follow the instructions below. <br />
<br />
<u><b>2. Lab Configuration</b></u><br />
We could simply reuse the lab configuration of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html"><u><b>Tutorial 20</b></u></a>. In general, you need two windows XP instances, one for taking notes and the other for running the malware. Also you need a WinDbg instance sitting on the host to debug the win_debug instance. Specifically, in the win_debug instance, you need to set a breakpoint at <u><b>0x3C1B3E. This is the place right before the call of loadDriver("raspppoe.sys"), as shown in Figure 1 below.</b></u><br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgenKdOPADJvsboB5lUMeKDWiGmCyQ1EI5dwhJSDzngtEunt9Nf7rmAtiYN4M9PfRk4r9ycxSP44bmebKWNYmBG4MwZ88475JOGzvLd0ml6tAER1qAs6SLAs5SyV97T0i_8geIBogGXbXA/s1600/a1.JPG" style="margin-left: auto; margin-right: auto;" /></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Code of Lz32.dll after zwLoadDriver</td></tr>
</tbody></table><br />
<b>3. Clean Up Operations</b><br />
Recall that at 0x3C1B3F, max++ (at lz32.dll) calls <u><b>zwLoadDriver </b></u>to load <u><b>rasppoe.sys</b></u>. The behavior of rasppoe.sys is explained in the Tutorials <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html">20</a> to <a href="http://fumalwareanalysis.blogspot.com/2012/04/malware-analysis-tutorial-25-deferred.html">25</a>. Now lz32.dll has to perform some clean up operations to further hide the trail of the malware. At 0x003C1B48 (see the first highlighted area of Figure 1), it closes the file handle of raspppoe.sys, and then from 0x3C1B55 to 0x3C1B3B, there is a loop which resumes a collection of threads one by one. This is actually to re-enable the windows file protection service.<br />
<br />
<u><b>Challenge 1.</b></u> Use data tracing/breakpoint technique to prove that the loop from 0x3C1B55 to 0x3C1B3B is to re-enable the windows file protection service.<br />
<br />
<br />
Note that major responsibility of the infected rasspppoe.sys is to set up the I/O handler for disk operations and also the infection of TDI (TCP/IP) service stack. Many services in raspppoe.sys are delayed for 15 seconds using deferred procedure call or delayed timer on system thread, because they need the further configuration done in lz32.dll. We now present the details.<br />
<br />
<u><b>4. Creation of Virtual Drive</b></u><br />
The first interesting part of the code is the creation of a virtual drive. The code is shown in Figure 2. It consists of four steps: it first loads the "<u><b>fmifs</b></u>" library, and then it gets the procedure address of "<u><b>FormatEx</b></u>", and then it calls the function to format the drive. If you look at the stack content, you will notice the name of the drive is "C2CAD...". Once everything is done, it unloads the library.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5x1B6RtWs2mH5_X_OQKwRbM9NcqUtCdLVyRIa3TkHHHeal88GDyW2hXdGjNuMvoBKsE-uhkU0YxFaW6pJn1qjxvIVoKj66fR6C_89sqEgjZj2lx3t2ERwSpVyyNbSBq_ESErcqRFyHQA/s1600/a2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5x1B6RtWs2mH5_X_OQKwRbM9NcqUtCdLVyRIa3TkHHHeal88GDyW2hXdGjNuMvoBKsE-uhkU0YxFaW6pJn1qjxvIVoKj66fR6C_89sqEgjZj2lx3t2ERwSpVyyNbSBq_ESErcqRFyHQA/s1600/a2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. Create Virtual Drive \??\C2CAD...</td></tr>
</tbody></table><br />
<b>5. Storing Malicious File in Hidden Drive</b><br />
The next action performed by Max++ is to save the infected driver file raspppoe.sys into the newly created hidden drive. The details is shown in Figure 3. <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLQeNQ3isJ8jV-JYl1AozvwvpamV1lh5CoN3NtG2slYyL8N6-Jl83E5nO5ulz8mjDWHherf_06giIcpto12MCtGiv2MbX4RQvkAt0cO4PqJzzCSOUo6MC-4QsxPVnK1LIoEXEmbRdX8rw/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLQeNQ3isJ8jV-JYl1AozvwvpamV1lh5CoN3NtG2slYyL8N6-Jl83E5nO5ulz8mjDWHherf_06giIcpto12MCtGiv2MbX4RQvkAt0cO4PqJzzCSOUo6MC-4QsxPVnK1LIoEXEmbRdX8rw/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. Store Malicious raspppoe.sys file into Hidden Drive. file name: snifer67</td></tr>
</tbody></table>As shown in Figure 3, the first action at <u><b>0x3C2000 </b></u>is a call of <u><b>MapViewOfSection</b></u>. Essentially, it maps a section object to the address space of the current object. The section object, before this call, is set up by Max++ to be the mapping of the <u><b>raspppoe.sys</b></u> driver file (which is infected). After the call is completed, the entire section object will be mapped to somewhere in the current process, in our case, the starting address is <u><b>0x00380000</b></u>. If you look at the memory dump in Figure 3, you can notice the "4D 5A", which is the magic code of a PE file. Then Max++ creates a file named "osseqw" (which is the result of encoding "snifer67" using the current time stamp). It then saves the contents of the rassppoe.sys into the newly created file.<br />
<br />
<u><b>Challenge 1.</b></u> Prove that the section object used in the MapviewOfSection call at 0x3C2000 is the one for raspppoe.sys (infected driver).<br />
<br />
<u><b>Challenge 2. </b></u>Find out when the snifer67 file in the hidden drive is used.<br />
<br />
<b>6.Configuration File</b><br />
The next function to analyze is 0x3C2162. Figure 4 shows its function body. Its main job is to create the configuration file used by the TDI_SEND activities introduced in section 5 of <a href="http://fumalwareanalysis.blogspot.com/2012/04/malware-analysis-tutorial-25-deferred.html">Tutorial 25</a>.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRQOhh80bzsb-QF_x-kah5iNAlT8FMk0JaJjr8LUY_gkjjDBWHnUbKrkps9U3jGuadaGb2qUEu7FKpc3-aTFmXq095m4Q-i09NkEF_PtlmeeCWCz6Knsw6G4rjMCPZw8mVwiPzYsqoAdM/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRQOhh80bzsb-QF_x-kah5iNAlT8FMk0JaJjr8LUY_gkjjDBWHnUbKrkps9U3jGuadaGb2qUEu7FKpc3-aTFmXq095m4Q-i09NkEF_PtlmeeCWCz6Knsw6G4rjMCPZw8mVwiPzYsqoAdM/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Writing IP/domain names of malicious servers</td></tr>
</tbody></table><br />
As shown in Figure 4, Max++ loads and encodes several strings such as<ip>85.17.239.212</ip> and <host>intensivedive.com</host>. It's your job to find out all the malicious servers saved to the configuration file.<br />
<br />
<u><b>Challenge 3.</b></u> Analyze the function at 0x003C20E0. What are its input parameters?<br />
<br />
<u><b>Challenge 4.</b></u> Identify all the IP addresses and domain names saved into the configuration file in hidden drive.<br />
<br />
<u><b>Challenge 5.</b></u> Find the name of the configuration file.<br />
<br />
<b>7. Saving Decoding Key in Registry</b><br />
The next action Max++ performs is to save the "decoding key" which is used for self-packing into registry. Figure 5 shows the code.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqjyUX2jQAizLMTioCq_u_gHYm_vYh5pMnml0KlJ4OhvJqR3LO_1O8RH_GxUGtsl_qVHgYlfP9MRa8krMhAateNUxRO7chw_8FxBHtJPFlQ3-sbDxmetTBcPhyphenhypheniMMmOx6C1NKpx8x0JvQ/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqjyUX2jQAizLMTioCq_u_gHYm_vYh5pMnml0KlJ4OhvJqR3LO_1O8RH_GxUGtsl_qVHgYlfP9MRa8krMhAateNUxRO7chw_8FxBHtJPFlQ3-sbDxmetTBcPhyphenhypheniMMmOx6C1NKpx8x0JvQ/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5. Saving Decoding Key</td></tr>
</tbody></table><br />
As shown in Figure 5, the decoding key is "1100100", which is retrieved from the PE header of Max+++downloader2010.exe and it is used in decoding/unpacking the code. Max++ creates a registry key in IE explorer and saves the value there.<br />
<br />
<u><b>Challenge 6.</b></u> Prove that the key 11001800 is from the PE header of Max++.<br />
<br />
<u><b>Challenge 7.</b></u> Find out where the key is used.<br />
<br />
<b>8. Creating HTTP Request</b><br />
Max++ proceeds to function 3C220A, which creates the HTTP request header for downloading more malicious files. Figure 6 shows its contents. The highlighted area in Figure 6 shows the HTTP request header. It is basically to invoke /install/setup.ppc.php on intensivedive.com.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2afTEoeXC7WWs648JQr-eBK1e0zZ9BGjzvYT9Th1XGzzRT3BNCn1f4LB1CNW5lBU4jw2oJSE3rIemKWW_iBkVopNbgh9pz7s5FT4dhe5bj5d9yqwlOH_TzOv0nAa17LFanZcXOr-bXQk/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2afTEoeXC7WWs648JQr-eBK1e0zZ9BGjzvYT9Th1XGzzRT3BNCn1f4LB1CNW5lBU4jw2oJSE3rIemKWW_iBkVopNbgh9pz7s5FT4dhe5bj5d9yqwlOH_TzOv0nAa17LFanZcXOr-bXQk/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6. Creating HTTP Request Header</td></tr>
</tbody></table><br />
<b>9.Creation of Malicious File max++.00.x86</b><br />
Next we analyze the function located at 0x3C16b8. Figure 7 shows its contents. It first opens the ntdll file and reads its basic file information. Then it creates a file called <u><b>max++.00.x86</b></u> in the hidden drive. The file uses the same configuration (basic file information) of ntdll.<br />
<br />
<u><b>Challenge 8</b></u>. Observe the function call at 0x3C16CD (in Figure 7). It creates a decoding table. Where does the decoding table start and end? <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhW_v0ApdJgpw0jovCxUV6PtfV1hPaAeuFfMBU_qo5ws0oy3x_kj80EbcJC1CKnZnY-1F5v7bWuE5ejd4JQg7LeSM666l6DQ69XttdXX3mLhRBQ0zK9Hx57y5SunI5B7KBl-VNOfJf2fqA/s1600/a1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhW_v0ApdJgpw0jovCxUV6PtfV1hPaAeuFfMBU_qo5ws0oy3x_kj80EbcJC1CKnZnY-1F5v7bWuE5ejd4JQg7LeSM666l6DQ69XttdXX3mLhRBQ0zK9Hx57y5SunI5B7KBl-VNOfJf2fqA/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 7. First Part of 0x3c16b8</td></tr>
</tbody></table><br />
<br />
Figure 8 shows the rest of the function. It establishes the contents of <u><b>max++.00.x86</b></u>. The first action is to allocate a virtual memory of 0x8000 bytes (see the highlighted area in Figure 7). Then it first establishes a decoding table in the stack (in range of 0x12D3XX). Then using this decoding table, Max++ first copies the encrypted code from 0x3C2550 to 0x380000 and deciphers the information via multiple passes of decryption. Finally it writes all the contents into max++.00.x86. The file will be later loaded by another system driver.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhydZNucINf_UInRBi7zutV0jaZrZjOw_fIwVVE1DM5tMVa5WkInvzl2s3XfVgpqC-WTh1RNVAsC0Pwk9kuV3u3A8_F6h9mIjS5T6y3zo0FtFQHlLoyUdJvBXNnGz5iCx-QnefP2W7GzIc/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhydZNucINf_UInRBi7zutV0jaZrZjOw_fIwVVE1DM5tMVa5WkInvzl2s3XfVgpqC-WTh1RNVAsC0Pwk9kuV3u3A8_F6h9mIjS5T6y3zo0FtFQHlLoyUdJvBXNnGz5iCx-QnefP2W7GzIc/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 8. Establish file max++.00.x86</td></tr>
</tbody></table><br />
<b>10. Contact Malicious Server</b><br />
Next Max++ contacts the malicious server, as shown in Figure 9. It constructs a <u><b>winsock </b></u>and connects to 85.17.239.212 and send a HTTP request to it. Notice that the interesting part is the encoding key "<u><b>11001800</b></u>" is embedded in the HTTP request (see the memory dump part of Figure 9). The function <i>does not have a receive operation</i> though. It seems to just inform the malicious server that the infection of Max++ is successful.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8UWifMtCdECDMuI6ZkBj3UkjfsO1qu0Rh48O09nT7FpE9FeseXJ3tyGuRLly2eO71hDoLUxRnjYeDH9VZn-hTil0Cr01nPLRKgfd3uf18rwzA1LHgOmhaM82djhK2zFS0wpw3DZ2AuV8/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8UWifMtCdECDMuI6ZkBj3UkjfsO1qu0Rh48O09nT7FpE9FeseXJ3tyGuRLly2eO71hDoLUxRnjYeDH9VZn-hTil0Cr01nPLRKgfd3uf18rwzA1LHgOmhaM82djhK2zFS0wpw3DZ2AuV8/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 9. Send Traffic to intensivedive</td></tr>
</tbody></table>Unknownnoreply@blogger.com62tag:blogger.com,1999:blog-8770073098084592029.post-30032041868621043802012-04-09T05:18:00.000-07:002012-04-09T05:18:55.453-07:00Malware Analysis Tutorial 25: Deferred Procedure Call (DPC) and TCP Connection<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIn0yDblhZ7i-ivM_0Vk5H2mRcIGRqRrv5w9dvfkUh8q6gCqoWcYpbsb5PA470izaq_xbfyrEtMajAL5Rr0mR-iYTrd29dJiEdnR5xNAihan5BPgrgkgD3aCYJA1YpIzyPYvNn8h47xxM/s1600/a1.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><b>Learning Goals</b>:<br />
<ol><li>Use WinDbg for kernel debugging</li>
<li>Apply <b></b>hardware data breakpoint for analyzing data flow</li>
<li>Understand TDI Network Service</li>
<li>Understand key I/O data structures such as _IRP and _IO_STACK_LOCATION </li>
<li>Understand deferred procedure call</li>
<li>Understand the use of system timer for delayed actions</li>
<li>Understand the use of WorkItem queue and worker routines </li>
</ol><b>Applicable to:</b><br />
<ol><li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security</li>
</ol><u><b>1. Introduction</b></u><br />
We now finish the last part of raspppoe.sys and look at its malicious actions regarding the use of deferred procedure call (DPC) and establishment of a TCP connection to remote server. We show how to use WinDbg to find out an encrypted configuration file that contains the list of malicious servers (IP and domain names) that Max++ tries to contact. In this tutorial, combined with <a href="http://fumalwareanalysis.blogspot.com/2012/04/malware-analysis-tutorial-24-tracing.html">Tutorial 24</a>, we also show the multi-thread tricks played by Max++ to make the analysis harder. The network activity (setting up TCP connection and sending and processing data) is accomplished via multiple threads. This creates trouble in debugging.<br />
<br />
Our analysis starts from <b>_+38A1</b>.<br />
<br />
<br />
<b>2. Lab Configuration</b><br />
We will use the instructions of Section 2 of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html">Tutorial 20</a>. In the following we just remind you of several important steps in the configuration:<br />
(1) You need a separate image named "<b>Win_Notes</b>" to record and comment the code. You don't really need to run the malware on this instance, but just to record all your observations using the .udd file. To do this, you have to modify the control flow of IMM so that it does not crash on .sys files. See <u><b>Section 2</b></u> of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html">Tutorial 20</a> for details. Jump to <u><b>0x100038A1</b></u> to start the analysis.<br />
(2) The second "<b>Win_DEBUG</b>" image has to be run in the <u><b> DEBUG </b></u>mode and there should be a WinDbg hooked from the host system using COM part -- so here, we are doing kernel debugging.<br />
(3) Set a breakpoint "<b>bu _+38A1</b>" in WinDbg to intercept the driver entry function.<br />
<br />
<b>3. Code Starting at _+38A1</b><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwYOLpjLO_B3UhsdNumqOpRF7uKHhFqQsPv3jyzkq-dWCSL4bjwMeRutVqSi0G_psge0JZrrBllhjeYsH3rAzsBDhx2z3AdKLUpcocHryN1Uioup15WERDy-V8g4BwA9pymFZYv8iCZpU/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwYOLpjLO_B3UhsdNumqOpRF7uKHhFqQsPv3jyzkq-dWCSL4bjwMeRutVqSi0G_psge0JZrrBllhjeYsH3rAzsBDhx2z3AdKLUpcocHryN1Uioup15WERDy-V8g4BwA9pymFZYv8iCZpU/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Last Part of rasppoe.sys</td></tr>
</tbody></table><br />
As shown in Figure 1 (first highlighted part), the first call is <b>IoAllocateWorkItem</b>(PDevice_Object). It produces a structure named IO_WorkItem that describes a work item for system threads. Using WinDbg, we can easily identify the device_object passed to the call. <br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> dt _DEVICE_OBJECT ffa50bb8 -r1</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">nt!_DEVICE_OBJECT</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> ...</span><span style="font-family: "Courier New",Courier,monospace;"></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x010 DriverSize : 0x8e00</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x014 DriverSection : 0x8131d310 Void</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x018 DriverExtension : 0x81131888 _DRIVER_EXTENSION</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x01c DriverName : _UNICODE_STRING "<b>\Driver\Disk</b>"</span></span><br />
<br />
Then the created IoWorkItem is saved to a global variable.<br />
<u><b>Challenge 1.</b></u> Find out when the IoWorkItem is used using data breakpoints.<br />
<br />
The next step performed is a call to <u><b>KeInitializeTimer</b></u> and the timer object is also saved in a global variable.<br />
<u><b>Challenge 2. </b></u>Find when and how the timer is used.<br />
<br />
As shown in Figure 1, the subsequent action is a call to <u><b>KeInitializeDPC</b></u>. This is an important call. According to MSDN document [<a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff552130%28v=vs.85%29.aspx">1</a>], the prototype of KeInitializeDPC is shown below. Here <b>DPC </b>means <b>deferred procedure call</b>. It is frequently used to service I/O requests (so that low priority calls will be executed later). The function creates and stores a _DPC structure in its first parameter, and registers a function as a second parameter.<br />
<pre>VOID KeInitializeDpc(
__out PRKDPC Dpc,
__in PKDEFERRED_ROUTINE <b>DeferredRoutine</b>,
__in_opt PVOID DeferredContext
);</pre><pre> </pre><pre>Using WinDbg, we can soon infer that the<b> deferred procedure to call </b>later is located at <b>_+3016</b>.</pre><pre><span style="font-family: "Courier New",Courier,monospace; font-size: x-small;">kd> p
_+0x38c2:
faf4f8c2 6a00 push 0
kd> p
_+0x38c4:
faf4f8c4 6816f0f4fa <b>push offset _+0x3016 (faf4f016)</b>
kd> p
_+0x38c9:
faf4f8c9 be7821f5fa mov esi,offset _+0x6178 (faf52178)
kd> p
_+0x38ce:
faf4f8ce 56 push esi
kd> p
_+0x38cf:
faf4f8cf ff152001f5fa call dword ptr [_+0x4120 (faf50120)]
</span></pre>We can set a breakpoint at <b>_+3016 (bp _+3016)</b> and see what is going on.<br />
<br />
Next, Max++ calls another interesting function <u><b>KeSetTimerEx </b></u>to link all the previous actions together. According to [<a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff553292%28v=vs.85%29.aspx">2</a>], the prototype of <u><b>KeSetTimerEx </b></u>is listed in the following:<br />
<br />
<pre style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;">BOOLEAN KeSetTimerEx(
__inout PKTIMER <b>Timer</b>,
__in LARGE_INTEGER <b>DueTime</b>,
__in LONG Period,
__in_opt PKDPC <b>Dpc</b>
); </span></pre><pre> </pre><pre>The KeSetTimerEx uses a previously constructed timer to set an "alarm" so that after some</pre><pre>timethe DPC procedure that _+3016 is triggered.</pre><br />
<br />
<br />
<b>Challenge 3.</b> Prove that the alarm will trigger _+3016 15 seconds later.<br />
<br />
<u><b>4. IO Worker Routine that Connects to Server</b></u><br />
<br />
Figure 2 shows the function body of <b>_+3016</b>. It's mainly a call to <u><b>IoQueueWorkItem</b></u>.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1IH-EuF5Y5Hb9Xnwr6rv3j7Drok-inDmE496Et_5RjZ3M2ADS6IBVND_Wh3zWtODgJ-jgrTHMTi8W2qQ4sh-gc6hzzBlgctrgrTqgxGyIOmudqu-M4Z7AM0Rh8MPqXpjUnqQEGvRqi98/s1600/a2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1IH-EuF5Y5Hb9Xnwr6rv3j7Drok-inDmE496Et_5RjZ3M2ADS6IBVND_Wh3zWtODgJ-jgrTHMTi8W2qQ4sh-gc6hzzBlgctrgrTqgxGyIOmudqu-M4Z7AM0Rh8MPqXpjUnqQEGvRqi98/s1600/a2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. Function body of _+3016</td></tr>
</tbody></table> The following is IoQueueWorkItem's prototype from [3]. It pushes an work item into the queue and associate a function that processes the work item when it's taken out.<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">VOID IoQueueWorkItem(</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> __in PIO_WORKITEM IoWorkItem,</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> __in PIO_WORKITEM_ROUTINE <u><b>WorkerRoutine</b></u>,</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> __in WORK_QUEUE_TYPE QueueType,</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> __in_opt PVOID Context</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">);</span></span><br />
<br />
Using WinDBG to dump the stack contents, we can easily infer that the <u><b>WorkerRoutine </b></u>is located at <b>_+1a0c</b> (in our fiture: it's named DPCWorkItemFunc_connects_to_server). We now proceed to the analysis of _1a0c. By MSDN [4], WorkerRoutine should have the following prototype: <br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">VOID WorkItem(</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> __in PDEVICE_OBJECT DeviceObject,</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> __in_opt PVOID Context</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">)</span></span><br />
<br />
<br />
We now proceed to analyze the worker routine <b>_+1a0c</b>. At the first instruction of _+1a0c, we dump the stack contents as following:<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> dd esp</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3d64 <b><u>80564610 </u>8114edf0 00000000 </b>805622fc</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3d74 fafb3dac 804e426b 81227cb0 00000000</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3d84 812e9da8 00000000 00000000 00000000</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3d94 00000001 80562334 00000000 812e9da8</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3da4 00000000 805645fd fafb3ddc 8057aeff</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3db4 81227cb0 00000000 00000000 00000000</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3dc4 fafb3db8 00000000 ffffffff 804e2490</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3dd4 804f8ab0 00000000 00000000 804f88ea</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> dt _DEVICE_OBJECT 8114edf0 -r1</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">nt!_DEVICE_OBJECT</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> ...</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> </span><span style="font-family: "Courier New",Courier,monospace;"> +0x01c DriverName : _UNICODE_STRING "\Driver\Disk"</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> <u><b>...</b></u></span></span><u><b></b></u><br />
<br />
Clearly, here 80564610 is the return address, <b>8114edf0 is a device object</b> (see the prototype of WorkItem routine above), and 0x0000 is the context. You can verify that 8114edf0 is a disk device. Figure 3 shows the simple function body of <b>_+1a0c</b>. It consists of only 4 instructions. At <u><b>10001A0E</b></u>, it pushes the offset of an object attributes into the stack and then it calls a function (readConfig_ConnectToServer) located at <b>_+18d6</b>.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwvjDFcO2G_Z4wgUIOfVQcbF0kxX89xr2rBxbKa1UESqMuCnMZj84las2bdQ87IETgwdJIjEP0ni8m_kcXs3xMy08wLUyLZnuIkblG5mIohUhx18_GexGZXZdI7JWyYboH5qmqLC5wUzc/s1600/a2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwvjDFcO2G_Z4wgUIOfVQcbF0kxX89xr2rBxbKa1UESqMuCnMZj84las2bdQ87IETgwdJIjEP0ni8m_kcXs3xMy08wLUyLZnuIkblG5mIohUhx18_GexGZXZdI7JWyYboH5qmqLC5wUzc/s1600/a2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. Worker Item Routine</td></tr>
</tbody></table>Now let's first dump the contents of <u><b>OBJ_ATTR_CONFIG_FILE </b></u>and proceed to <u><b>_+18d6</b></u>. The dump is shown below: that's clearly a file name inside the hidden disk drive!<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> dt _OBJECT_ATTRIBUTES faf4a050</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">nt!_OBJECT_ATTRIBUTES</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Length : 0x18</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x004 RootDirectory : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x008 ObjectName : 0xfaf482e8 _UNICODE_STRING "<u><b>\??\C2CAD972#4079#4fd3#A68D#AD34CC121074\{49B474EB-92D0-464f-B1DD-1F37AABF9D95}</b></u>"</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x00c Attributes : 0x40</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x010 SecurityDescriptor : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x014 SecurityQualityOfService : (null) </span></span><br />
<br />
<b>5. Read Configuration File in Hidden Drive and Connect to Remote Server</b><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIn0yDblhZ7i-ivM_0Vk5H2mRcIGRqRrv5w9dvfkUh8q6gCqoWcYpbsb5PA470izaq_xbfyrEtMajAL5Rr0mR-iYTrd29dJiEdnR5xNAihan5BPgrgkgD3aCYJA1YpIzyPYvNn8h47xxM/s1600/a1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIn0yDblhZ7i-ivM_0Vk5H2mRcIGRqRrv5w9dvfkUh8q6gCqoWcYpbsb5PA470izaq_xbfyrEtMajAL5Rr0mR-iYTrd29dJiEdnR5xNAihan5BPgrgkgD3aCYJA1YpIzyPYvNn8h47xxM/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5. First Part of _+18d6</td></tr>
</tbody></table>Now we proceed to _+18d6. Figure 5 shows its first part of the code. The control flow is very straightforward. Max++ first opens a file (the one in hidden drive, as shown in Section 4). Then it reads about the contents of the file, and then establishes an encoding table, and uses this encoding table to decipher the file contents. Shown in the following is the dump of the file contents, and we can now find out some interesting information: the list of IP addresses and domain names to contact!<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> db fafb3b3c</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3b3c 3c 69 70 3e 38 35 2e 31-37 2e 32 33 39 2e 32 31 <b><ip>85.17.239.21</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3b4c 32 3c 2f 69 70 3e 3c 68-6f 73 74 3e 69 6e 74 65 <b>2</ip><host>inte</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3b5c 6e 73 65 64 69 76 65 2e-63 6f 6d 3c 2f 68 6f 73 <b>nsedive.com</hos</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3b6c 74 3e 4e 80 98 3b fb fa-12 cc 51 80 08 00 00 00 <b>t></b>N..;....Q.....</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3b7c 00 00 00 00 98 3b fb fa-2e cc 51 80 01 20 f1 df .....;....Q.. ..</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3b8c 02 02 00 00 5d 34 4e 80-4a 61 00 00 f6 32 4e 80 ....]4N.Ja...2N.</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3b9c fd 32 4e 80 12 c6 05 fb-30 00 00 00 38 3c fb fa .2N.....0...8<..</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3bac 08 56 6f 80 00 0d db ba-08 40 00 00 00 00 00 00 .Vo......@......</span></span><br />
<br />
<u><b>Challenge 1:</b></u> replicate the success to find out the contents of the configuration file of Max++.<br />
<br />
Figure 6 shows the rest of function <b>_+18d6</b>. The logic is very clear. At 0x10001983, it calls a self-defined function <b>getTagContent (located at _+1486) </b>to look for a tag <ip> in the configuration file. It soon finds out the ip string <b>85.17.239.212</b>. Then it calls system function <b>RtlIpv4StringToAddressExA </b>to generate the 32-bit representation of the IP address.<br />
<br />
<u><b>Challenge 2. </b></u>Analyze function _+1486 (getTagContent). What are its parameters and output?<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicUazWzX8YVgq51TSXf-bgvx1MQ9jaJWc79SxeWIAaz2jx4CKolPdVQOYBqwpl_Y2xi080xglS7k8D4HhNWASJO3RWxHc12lsxBspSITrL2NsUprtkw5S9u2WudylXIvev2ExUsvxmWy8/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicUazWzX8YVgq51TSXf-bgvx1MQ9jaJWc79SxeWIAaz2jx4CKolPdVQOYBqwpl_Y2xi080xglS7k8D4HhNWASJO3RWxHc12lsxBspSITrL2NsUprtkw5S9u2WudylXIvev2ExUsvxmWy8/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6. Rest of Function _+18d6</td></tr>
</tbody></table> Then at 0x100019F8 (see the last highlighted area of Figure 6), it calls a self-defined function <b>openConnectTo85.17.xx </b>(located at <b>_+1832</b>). The following lists the dump of the stack contents before the call. Observe its first parameter: d4ef1155. Can you guess its meaning?<br />
<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> dd esp</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3a28 </span><u style="font-family: "Courier New",Courier,monospace;"><b>d4ef1155 </b></u><span style="font-family: "Courier New",Courier,monospace;">00005000 00000001 ffb4b850</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3a38 812e9da8 652e7ecd a4362152 3c135905</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb3a48 ee8d12d7 d1b04962 0150df55 0fd8ad5f</span></span><br />
<br />
It is not hard to see that <u><b>d4ef1155 </b></u>is the integer representation of IP address <u><b>85.17.239.212</b></u> (note the byte sequence and the HEX translation, e.g., 0x55 is decimal number 85).<br />
<br />
<br />
<b>6. Establish the TCP Connection</b><br />
Function _+1832 establishes a TCP connection to the 85.17.239.212/5000, however, it does not send anything. The TDI_SEND operation is actually issued by the system thread discussed in <a href="http://fumalwareanalysis.blogspot.com/2012/04/malware-analysis-tutorial-24-tracing.html">Tutorial 24</a>. Why doesn't Max++ try to accomplish in one thread? It's creating trouble for analysts.<br />
<br />
Figure 7 presents the function body of <b>_+1832</b> here. We omit most of the analysis and leave the details to you.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgstDAiew3KwKPsfoLsHBivBpbyOOMGw1-U4CUuA2LR-U54aBEmtclNVbmsFLSOIZ8cojp9zoJouC118jmdnWsQxWWkKryODOJUSoa5Ghp6ac9227W50fYPHtG3P16gd5I6b8hIi3GsvBM/s1600/a2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgstDAiew3KwKPsfoLsHBivBpbyOOMGw1-U4CUuA2LR-U54aBEmtclNVbmsFLSOIZ8cojp9zoJouC118jmdnWsQxWWkKryODOJUSoa5Ghp6ac9227W50fYPHtG3P16gd5I6b8hIi3GsvBM/s1600/a2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 7. Establish the TCP Connection</td></tr>
</tbody></table><br />
As shown in Figure 7, Max++ follows the general procedure of establishing a TCP connection -- it first binds the address and then requests the connection.<br />
<br />
<u><b>Challenge 4.</b></u> Completely analyze all the details of function _+1832<br />
<br />
<br />
<u><b>References</b></u><br />
1. MSDN, "KeInitializeDPC routine", available at http://msdn.microsoft.com/en-us/library/windows/hardware/ff552130(v=vs.85).aspx.<br />
2. MSDN, "KeSetTimerEx routine", available at http://msdn.microsoft.com/en-us/library/windows/hardware/ff553292(v=vs.85).aspx<br />
3. MSDN, "IoQueueWorkItem", available at http://msdn.microsoft.com/en-us/library/windows/hardware/ff549466%28v=vs.85%29.aspx <br />
4. MSDN, "Work Item Routine", available at http://msdn.microsoft.com/en-us/library/windows/hardware/ff566380%28v=vs.85%29.aspxUnknownnoreply@blogger.com91tag:blogger.com,1999:blog-8770073098084592029.post-1739272813275109422012-04-03T17:57:00.000-07:002012-04-03T17:57:56.994-07:00Malware Analysis Tutorial 24: Tracing Malicious TDI Network Behaviors of Max++<b>Learning Goals</b>:<br />
<ol><li>Use WinDbg for kernel debugging</li>
<li>Apply the <b>data tracing </b>and hardware data breakpoint points for analyzing data flow</li>
<li>Understand TDI Network Service</li>
<li>Understand key I/O data structures such as _IRP and _IO_STACK_LOCATION </li>
</ol><b>Applicable to:</b><br />
<ol><li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security</li>
</ol><u><b>1. Introduction</b></u><br />
This tutorial continues the analysis of the infected raspppoe driver and presents Max++'s malicious network activities and the low level I/O operations that create a lot of trouble in debugging. We show how Max++ directly constructs TDI low level I/O requests for sending out network data. TDI is the windows low level I/O interface for TCP/IP devices.<br />
<br />
Our analysis starts from <b>_+1BF2</b>.<br />
<br />
<br />
<b>2. Lab Configuration</b><br />
We will use the instructions of Section 2 of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html">Tutorial 20</a>. In the following we just remind you of several important steps in the configuration:<br />
(1) You need a separate image named "<b>Win_Notes</b>" to record and comment the code. You don't really need to run the malware on this instance, but just to record all your observations using the .udd file. To do this, you have to modify the control flow of IMM so that it does not crash on .sys files. See <u><b>Section 2</b></u> of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html">Tutorial 20</a> for details. Jump to <u><b>0x10001BF2</b></u> to start the analysis.<br />
(2) The second "<b>Win_DEBUG</b>" image has to be run in the <u><b> DEBUG </b></u>mode and there should be a WinDbg hooked from the host system using COM part -- so here, we are doing kernel debugging.<br />
(3) Set a breakpoint "<b>bu _+1bF2</b>" in WinDbg to intercept the driver entry function.<br />
<br />
<b>3. Function _+1BF2 (Network Activities)</b><br />
Function body of <b>_+1BF2</b> is shown in Figure 1. This is a relatively simple function. The first action (see highlighted area in Figure 1) is a call to <u><b>KeInitializeQueue</b></u>. This is to create a queue for processing I/O request. Interestingly, this queue is NOT used in function _+1BF2. You can follow the same technique as shown in <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-tutorial-analysis-23-tracing.html">Tutorial 23</a> to find out how the queue is used.<br />
<br />
<b>Challenge 1. </b>Use hardware data breakpoints to find out how the I/O queue created at _+1C07 is used. For example, you have to figure out who is inserting new items into the queue?<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEga31jsh06KZeWDAut4gVUpW3jViio2e2vFlHJzyAxLWnLMkCZFl46ZTcy-E3Uyulm0VFAx_UMOB-1d75SN9rg7tNeOGcoCyRyTJAwCW7PZ9sDhlt5_52OKNFzQ275vAwOlbkE11aYNbJI/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEga31jsh06KZeWDAut4gVUpW3jViio2e2vFlHJzyAxLWnLMkCZFl46ZTcy-E3Uyulm0VFAx_UMOB-1d75SN9rg7tNeOGcoCyRyTJAwCW7PZ9sDhlt5_52OKNFzQ275vAwOlbkE11aYNbJI/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Start a System Thread</td></tr>
</tbody></table><br />
Next the function creates a system thread (at _+1C1F in Figure 1). The start routine of the system thread is <b>_+393A</b> and the disk driver object will be passed as the parameter to the start routine. Notice that it is already infected (its Major Function is set to _+2BDE)<br />
<br />
<b>Challenge 2.</b> Prove that the INFECTED disk driver object is passed as the parameter to the start routine.<br />
<br />
Now if we set a breakpoint "<b>bp _+393A</b>" at the start routine, we get into its function body. The function immediately calls <b>_+1b88</b>. The function body of _+1b88 is shown below:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhPLvvZNqKp6davskeSkJopqrdNcEiwWxqsXLBRyHSfirBS5riuCMiRjfLdxIoSjH1CZqhq5zrVKEVjtFo4595F7rGhT7CJ5xyR-aty4nZ1do0q8LQEBmY7s3o6bAiaAZF9dC7cjiLucs/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhPLvvZNqKp6davskeSkJopqrdNcEiwWxqsXLBRyHSfirBS5riuCMiRjfLdxIoSjH1CZqhq5zrVKEVjtFo4595F7rGhT7CJ5xyR-aty4nZ1do0q8LQEBmY7s3o6bAiaAZF9dC7cjiLucs/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. Process IRP Request WorkItem</td></tr>
</tbody></table><br />
Function <b>_+1b88</b> deserves some special attention and requires skillful analysis. The first portion of the function (0x10001B95 to 0x10001BB5, in Figure 2) is easy to understand. Based on the error code returned by KeRemoveQueue, the function will take proper processing actions. Then if <u><b>KeRemoveQueue </b></u>is returning correctly, which is a <b>_LIST_ENTRY</b> instance, we have to understand the actions performed by Max++ from <u><b>0x10001BB7 </b></u>(see Figure 2).<br />
<br />
There are four instructions, from 0x10001BB7, seem to reference some data attributes related to EAX. The question is what is the data type of EAX. If we look at instruction at 0x10001BC3 (see the highlighted box in Figure 2), and then the call of IoFreeIrp at 0x1BC7, we can immediately infer that <u><b>EAX-58</b></u> is the entry address of an <b>_IRP</b>. Then based on this fact, we could easily infer the meaning of the rest of the code.<br />
<br />
Finally, at 0x10001BDD (see the last highlighted area in Figure 2), Max++ jumps to <b>_+21A1</b>. This address must be set up by Max++ when it sets up the IRP work item.<br />
<br />
We now look at function _+21A1. Like any other driver processing logic, it consists of a lot of switch cases. Tracing through the calls using WinDbg, we soon reach function <b>_+1660</b> (as shown in the following).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-vYTSNiBVK37IeYbGujMIasyxbrDwIj4zKPW56IUZD2zYk_To7ydgR9VRmMSV0-BKp2Q_AIWor9UFyMGjU7hQot4P3QiecNBZ_ItIjVq9YYN1BbfuZq9mIe5YLXDPCe4bkNt-SsDke9s/s1600/a2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-vYTSNiBVK37IeYbGujMIasyxbrDwIj4zKPW56IUZD2zYk_To7ydgR9VRmMSV0-BKp2Q_AIWor9UFyMGjU7hQot4P3QiecNBZ_ItIjVq9YYN1BbfuZq9mIe5YLXDPCe4bkNt-SsDke9s/s1600/a2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. Function Body of _+1660</td></tr>
</tbody></table><br />
<br />
As shown in Figure 3, function <b>_+1660</b> first reads the current IO status code passed as the parameter, stored in [EBP+8]. If everything ok (network device ok), it proceeds to generate a GUID (unique identifier), uses sprintf to generate the HTTP header request "/install/setup.php" and calls a function "<b>sendsHTTPReq_Get_InstallPHP</b>" (label we attached to function <b>_+2090</b>). <br />
<br />
(<b>[LAB NOTE: Because Max++ tried to access x86.00.dll located at 74.117.xx.xx and it failed. The device status is C00000B5. To present that it is successful, we can use the "ed 0xaaaabbbb 0" command to reset the error code, where "aaaabbbb" is the EBP+8].</b>).<br />
<br />
<u><b>Challenge 3:</b></u> Trace who is writing to [EBP+8]. <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR1mR5I23JhthL4m1c6hl4tqCxT3r_EFrvNcy7nwdlEuugevZqt5fz_GXyILQofBkRBu-qVsPkwZiQ8y4Up7n3Wg1fiy5CK2gOExDzRV0G-GRNpviosPUnjUpJ-yxqfxcYZep-8TSz_AM/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR1mR5I23JhthL4m1c6hl4tqCxT3r_EFrvNcy7nwdlEuugevZqt5fz_GXyILQofBkRBu-qVsPkwZiQ8y4Up7n3Wg1fiy5CK2gOExDzRV0G-GRNpviosPUnjUpJ-yxqfxcYZep-8TSz_AM/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Function Body of _+2090: Send out TCP Packet</td></tr>
</tbody></table><br />
<b>[Lab Notice: to cheat the malware again and make it believe that the TDI service is there. Set a BP at _+20D4 and then change the value of eax to 1, e.g., using WinDbg command "r eax=1"]</b><br />
<br />
As shown in Figure 4, the job of function <b>_+2090</b> is to send out network packets. Its main function is to build up IRP requests and invoke the network driver to send out the request. We now expose some of its major operations here.<br />
<br />
At <b>_+2102</b> (see the highlighted area in Figure 4), we encounter the first interesting call: <u><b>IoBuildDeviceIoControlRequest</b></u>. By the MSDN document [<a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff548318%28v=vs.85%29.aspx">1</a>], the prototype of the function is listed below. Clearly it returns an instance of <b>IRP </b>object. The interesting parameters are: <b>IoControlCode</b>, <b>DeviceObject</b>, <b>Input/Output Buffer</b>, <b>PKEvent</b>. We now check the parameters of these parameters one by one.<u><b></b></u><br />
<pre>PIRP IoBuildDeviceIoControlRequest(
__in ULONG IoControlCode,
__in PDEVICE_OBJECT DeviceObject,
__in_opt PVOID InputBuffer,
__in ULONG InputBufferLength,
__out_opt PVOID OutputBuffer,
__in ULONG OutputBufferLength,
__in BOOLEAN InternalDeviceIoControl,
__in_opt PKEVENT Event,
__out PIO_STATUS_BLOCK IoStatusBlock
);
</pre><br />
Doing a dump of the stack using WinDbg right before the call of IoBuildDeviceIoControlRequest, we have the following:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;">kd> dd esp<br />
f7df4d04 <b>00000002 ffb24530 </b>00000000 00000000<br />
f7df4d14 <b>e11c600c </b>0000008c 00000001 00000000<br />
f7df4d24 f7df4d34 00000000 e10e26c8 00000000<br />
f7df4d34 faf36091 00000008 ffb24530 f7df4d6c<br />
f7df4d44 faf356e2 00000000 e10e26c8 00000000<br />
f7df4d54 00000000 c66258dd 11e17d8d 00089c9e<br />
f7df4d64 02b75027 00000382 f7df4d84 faf3628c<br />
f7df4d74 00000000 e10e26c8 00000000 c00000b5<br />
</span></div>Clearly, the <b>IoControlCode </b>is <b>0x2</b>, the <b>DeviceObject </b>is <b>ffb24530</b>, and the <b>output buffer</b> is <b>0xe11c600c</b>. If you later dump the contents of DeviceObject using "<b>dt _DEVICE_OBJECT ffb24530 -r2</b>" you will find that its driver object is "<b>Driver/TCP</b>". To find out the meaning of <u><b>IoControlCode</b></u>, 0x2, simply search for "#define IRP_MJ_CREATE" on Google, you will soon learn that 0x2 means <b>IRP_MJ_CLOSE</b>. Note that interestingly, the output buffer, which is supposed to be overwritten has the following (which is the HTTP request header for intensedive.com/install/setup.php):<br />
<br />
<span style="font-family: "Courier New",Courier,monospace; font-size: x-small;">kd> db 0xe11c600c<br />
e11c600c 47 45 54 20 2f 69 6e 73-74 61 6c 6c 2f 73 65 74 GET <b>/install/set</b><br />
e11c601c 75 70 2e 70 68 70 3f 6d-3d 30 38 30 30 32 37 35 <b>up.php</b>?m=0800275<br />
e11c602c 30 62 37 30 32 20 48 54-54 50 2f 31 2e 31 0d 0a 0b702 HTTP/1.1..<br />
e11c603c 48 6f 73 74 3a 20 69 6e-74 65 6e 73 65 64 69 76 Host: <b>intensediv</b><br />
e11c604c 65 2e 63 6f 6d 0d 0a 55-73 65 72 2d 41 67 65 6e <b>e.com</b>..User-Agen<br />
e11c605c 74 3a 20 4f 70 65 72 61-2f 39 2e 32 39 20 28 57 t: Opera/9.29 (W<br />
e11c606c 69 6e 64 6f 77 73 20 4e-54 20 35 2e 31 3b 20 55 indows NT 5.1; U<br />
e11c607c 3b 20 65 6e 29 0d 0a 43-6f 6e 6e 65 63 74 69 6f ; en)..Connectio</span><br />
<br />
Why use it as output buffer (it should be an input buffer instead!)? Let's first examine the _IRP generated by the call, it is stored in EAX. The following shows the dump. The first interesting data member is the StartVa (virtual address) associated with the _IRP, it is 0xe11c6000 (which is very close to the output buffer above). Then the next interesting part is that: <b>stack count</b> is 1, <b>current location</b> is 2, and <b>currentStackLocation</b> is 0x81158a3c.<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> dt _IRP 811589a8 -r2</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">nt!_IRP</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Type : 0n6</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x002 Size : 0x94</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x004 MdlAddress : 0xffa339e0 _MDL</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Next : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x004 Size : 0n32</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x006 MdlFlags : 0n138</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x008 Process : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x00c MappedSystemVa : 0x81257000 Void</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x010 StartVa : <u><b>0xe11c6000</b></u> Void</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x014 ByteCount : 0x8c</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x018 ByteOffset : 0xc</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x008 Flags : 0</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> </span><span style="font-family: "Courier New",Courier,monospace;">+0x022 <u><b>StackCount </b></u>: <b>1</b> ''</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x023 <u><b>CurrentLocation </b></u>: <b>2</b> ''</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> ...</span><span style="font-family: "Courier New",Courier,monospace;"></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> </span><span style="font-family: "Courier New",Courier,monospace;"> +0x040 Tail : __unnamed</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Overlay : __unnamed</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 DeviceQueueEntry : _KDEVICE_QUEUE_ENTRY</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 DriverContext : [4] (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x010 Thread : 0x8112c200 _ETHREAD</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x014 AuxiliaryBuffer : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x018 ListEntry : _LIST_ENTRY [ 0x0 - 0x0 ]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x020 CurrentStackLocation : <u><b>0x81158a3c </b></u>_IO_STACK_LOCATION</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x020 PacketType : 0x81158a3c</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x024 OriginalFileObject : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> </span></span><br />
<br />
There is no sufficient information of the entire data structure of _IRP, and we again have to rely on google. Searching _IRP and StackCount and CurrentLocation we found the following code from [3]:<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">#define IoSetNextIoStackLocation(_IRP){</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> _IRP->currentLocation--;</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> IRP->Tail.Overlay.currentStackLocation--; </span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">} </span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><br />
</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><br />
</span></span><br />
Note that the type of currentLocation is byte, while the currentStackLocation is _IO_STACK_LOCATION (so the -- operator is actually to reduce by 9x24 bytes, i.e., the size of IO_STACK_LOCATION). You can also notice that the <u><b>stack growth direction is DOWN</b></u>! <b>In another word, notice that IO_STACK_LOCATION is a subtask of the entire _IRP, i.e., an _IRP can consists of multiple IO_STACK_LOCATION located on the IO_stack, consecutively. To move to the next _IO_STACK_LOCATION, reduce the current IO_STACK_LOCATION address by 24.</b><br />
<br />
Let's print the contents of the current <b>_IO_STACK_LOCATION</b> and see what it is:<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> dt _IO_STACK_LOCATION 0x81158a3c </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">nt!_IO_STACK_LOCATION</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 <b>MajorFunction </b>: <b>0x9c</b> ''</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x001 <b>MinorFunction</b> : <b>0x89</b> ''</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x002 Flags : 0x15 ''</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x003 Control : 0x81 ''</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x004 Parameters : __unnamed</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x014 DeviceObject : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x018 FileObject : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x01c CompletionRoutine : 0x81158a58 long +ffffffff81158a58</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x020 Context : 0x81158a58 Void</span></span><br />
<br />
Notice the major function is 0x9c, minor function is 0x89. If you search winnt_types.h you will find that it is MEANINGLESS! Why? Because the _IO_STACK_LOCATION we are displaying is INVALID! Pay attention to the value of stackCount (it's 1), which means that there is ONLY ONE _IO_STACK_LOCATION (subtask) associated with this IRP, and the currentLocation is 2 (<u><b>which means that 0x81158a58) is actually 0x24 bytes after the ACTUAL _IO_STACK_LOCATION associated with the _IRP!</b></u><br />
<br />
Now look at the code located at <u><b>0x1000211b </b></u>and <u><b>0x1000211E</b></u>, its counter part in WinDbg is shown below:<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">_+0x211b:</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">faf3611b 8b4860 mov ecx,dword ptr [eax+60h]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> p</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">_+0x211e:</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">faf3611e 83e924 <b>sub ecx,24h</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> kd> r ecx</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">ecx=<b>81158a18</b></span></span><br />
<br />
The motivation is clear, now ECX has the real address of the _IO_STACK_LOCATION. The next couple of instructions set up the contents of the _IO_STACK_LOCATION, and the real contents of the _IO_STACK_LOCATION are:<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> dt _IO_STACK_LOCATION 81158a18</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">nt!_IO_STACK_LOCATION</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 <u><b>MajorFunction</b></u> : 0xf ''</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x001 <u><b>MinorFunction </b></u>: 0x7 ''</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x002 Flags : 0 ''</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x003 Control : 0 ''</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x004 Parameters : __unnamed</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x014 DeviceObject : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x018 FileObject : 0xffbc7698 _FILE_OBJECT</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x01c CompletionRoutine : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x020 Context : (null) </span></span><br />
<br />
<br />
Now the major function is 0xf (<b>IRP_MJ_INTERNAL_DEVICE_CONTROL</b>) and the MinorFunction code is 0x7 (<b>TDI_SEND</b>). If you read the MSDN documentation about TDI_SEND [<a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff565549%28v=vs.85%29.aspx">4</a>], you might notice that the <u><b>data to send is stored in _IRP->MDL (which contains the HTTP request to intensivedive.com</b></u>, <br />
and the _IO_STACK_LOCATION->FileObject represents the TCP connection socket end-object.<br />
<br />
Up to now, we are clear that function _1660 is trying to send a request "<b>/install/setup.php..</b>." to <b>intensivedive.com</b>. If you open the WireShark on the Linux Gateway, you will be able to capture this packet.<br />
<br />
<u><b>Challenge of the Day:</b></u> Can you find out the code which is responsible for getting the data returned by the "/install/setup.php"? [hint: use data breakpoints and think about how to use TDI service to receive].<br />
<br />
<br />
<u><b>References</b></u><br />
1. MSDN, "IoBuildDeviceControlRequest Routine", available at http://msdn.microsoft.com/en-us/library/windows/hardware/ff548318(v=vs.85).aspx.<br />
2. MSDN, "KeInsertQueue", available at<br />
3. winddk.h, available on linkm.googlecode.com<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">4. MSDN, "TDI_SEND", available at http://msdn.microsoft.com/en-us/library/windows/hardware/ff565549%28v=vs.85%29.aspx </span></span>Unknownnoreply@blogger.com29tag:blogger.com,1999:blog-8770073098084592029.post-8945798265369617892012-03-27T11:40:00.002-07:002012-03-28T19:11:59.824-07:00Malware Tutorial Analysis 23: Tracing Kernel Data Using Data Breakpoints<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaTgAwKC8xu1gb992EpPCpqANiyrpP96OJA1k4bO3ovEPu_nDlkiGxzO5ImuzTd4IfXGANXzZx_cJd8YAHPGHVPcc8aOlAuM9HIfDTp9eVzTY0SSzVtvBZZkU5B1ykxzbbkHNvvgdpnPI/s1600/a1.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><b>Learning Goals</b>:<br />
<ol><li>Use WinDbg for kernel debugging</li>
<li>Apply the <b>data tracing </b>and hardware data breakpoint points for analyzing data flow</li>
<li>Understand how rootkits set up and hide a driver module </li>
</ol><b>Applicable to:</b><br />
<ol><li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security</li>
</ol><u><b>1. Introduction</b></u><br />
This tutorial continues the analysis presented in <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html">Tutorial 20</a>. We reveal how Max++ performs another round of driver infection, and how it sets up and hides an infected driver. We will also study how to use hardware data breakpoint to trace the use of data and kernel data structures. Our analysis starts from <b>_+37AF</b>.<br />
<br />
<br />
<b>2. Lab Configuration</b><br />
In general we will use the instructions of Section 2 of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html">Tutorial 20</a>. In the following we just remind you of several important steps in the configuration:<br />
(1) You need a separate image named "<b>Win_Notes</b>" to record and comment the code. You don't really need to run the malware on this instance, but just to record all your observations using the .udd file. To do this, you have to modify the control flow of IMM so that it does not crash on .sys files. See <u><b>Section 2</b></u> of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html">Tutorial 20</a> for details. Jump to <u><b>0x100037AF</b></u> to start the analysis.<br />
(2) The second "<b>Win_DEBUG</b>" image has to be run in the <u><b> DEBUG </b></u>mode and there should be a WinDbg hooked from the host system using COM part -- so here, we are doing kernel debugging.<br />
(3) Set a breakpoint "<b>bu _+37af</b>" in WinDbg to intercept the driver entry function.<br />
<br />
<b>3. Data Breakpoints and Tracing File Name</b><br />
We now continue the analysis after Tutorial 21. We begin with <b>_+37AF</b>. Figure 1 shows the first couple of instructions. As shown in Figure 1, the first section of the code is to massage a collection of names.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaTgAwKC8xu1gb992EpPCpqANiyrpP96OJA1k4bO3ovEPu_nDlkiGxzO5ImuzTd4IfXGANXzZx_cJd8YAHPGHVPcc8aOlAuM9HIfDTp9eVzTY0SSzVtvBZZkU5B1ykxzbbkHNvvgdpnPI/s1600/a1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaTgAwKC8xu1gb992EpPCpqANiyrpP96OJA1k4bO3ovEPu_nDlkiGxzO5ImuzTd4IfXGANXzZx_cJd8YAHPGHVPcc8aOlAuM9HIfDTp9eVzTY0SSzVtvBZZkU5B1ykxzbbkHNvvgdpnPI/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Copy and Manipulate Strings</td></tr>
</tbody></table><br />
At 0x100037BF, it is copying string "\??\C2CAD...\snifer67" to the area pointed by EDI. Doing a data analysis in WinDbg yields the following. Clearly, EDI value (the starting address) of the string is <u><b>0xFAFAF9F8</b></u> (which is <u><b>ESP+34</b></u> at this moment)<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"></span><span style="font-family: "Courier New",Courier,monospace;">kd> db <u><b>fafaf9f8</b></u></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf9f8 5c 00 3f 00 3f 00 5c 00-43 00 32 00 43 00 41 00 <b>\.?.?.\.C.2.C.A.</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafafa08 44 00 39 00 37 00 32 00-23 00 34 00 30 00 37 00 <b>D.9.7.2.#.4.0.7.</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafafa18 39 00 23 00 34 00 66 00-64 00 33 00 23 00 41 00 <b>9.#.4.f.d.3.#.A.</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafafa28 36 00 38 00 44 00 23 00-41 00 44 00 33 00 34 00 <b>6.8.D.#.A.D.3.4.</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafafa38 43 00 43 00 31 00 32 00-31 00 30 00 37 00 34 00 <b>C.C.1.2.1.0.7.4.</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafafa48 5c 00 4c 00 5c 00 53 00-6e 00 69 00 66 00 65 00 <b>\.L.\.S.n.i.f.e.</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafafa58 72 00 36 00 37 00 00 00-14 fb 57 80 00 f3 c4 e1 <b>r.6.7</b>.....W.....</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafafa68 00 52 2e 81 00 20 2f 81-00 10 00 00 d8 fa 57 80 .R... /.......W.</span></span><br />
<br />
Similarly you can infer the second string generated by the swpringf at 0x100037DB (in Figure 1) is "<b>\systemroot\system32\drivers\rasppoe</b>" (this is the name of the randomly picked driver). The name could change in every run.<br />
<br />
The the challenge to us is that if we look in the notes window, we are not able to infer where these two strings are used! We have to use WinDbg data breakpoints to figure out where these file/service names are used.<br />
<br />
Let's take the second string as an example. By analyzing the input parameter of swprintf (as shown in Figure 1, 2nd highlighted area), we know that the second string "\systemroot\system32\drivers\rasppoe" is located at 0xFAFB7A78, as shown in following. Then we could set a data read breakpoint on it: <b>ba r4 fafb7a78 </b>(this means to watch for any reading on the 4 bytes starting at fafb7a78). <br />
<br />
<div style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;">kd> <b>db fafb7a78 </b></span></div><div style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;">fafb7a78 5c 00 73 00 79 00 73 00-74 00 65 00 6d 00 72 00 <b>\.s.y.s.t.e.m.r</b>.<br />
fafb7a88 6f 00 6f 00 74 00 5c 00-73 00 79 00 73 00 74 00 o.o.t.\.s.y.s.t.<br />
fafb7a98 65 00 6d 00 33 00 32 00-5c 00 64 00 72 00 69 00 e.m.3.2.\.d.r.i.<br />
fafb7aa8 76 00 65 00 72 00 73 00-5c 00 6b 00 62 00 64 00 v.e.r.s.\.k.b.d.<br />
fafb7ab8 63 00 6c 00 61 00 73 00-73 00 2e 00 73 00 79 00 c.l.a.s.s...s.y.<br />
fafb7ac8 73 00 00 00 77 7a 56 80-10 0d 00 e1 c4 06 00 00 s...wzV.........<br />
fafb7ad8 a8 7b fb fa 10 0d 00 e1-01 00 00 00 c4 06 00 00 .{..............<br />
fafb7ae8 00 00 00 00 20 0d 00 e1-88 2d 00 e1 f9 ba 13 81 .... ....-......<br />
kd> <b>ba r4 fafb7a78</b></span></div><br />
Now run the program we hit <b>_+0x1b </b>in <u><b>RtlInitUnicodeString</b></u>, at this time, if you run <u><b>Kp</b></u> (to show the stack contents) you might not be able to get the right sequence of frames in the stack (as shown in the following).<br />
<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> g</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">Sun Mar 25 20:26:39.359 2012 (UTC - 4:00): Breakpoint 1 hit</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">nt!RtlInitUnicodeString+0x1b:</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">804d92c2 66f2af repne scas word ptr es:[edi]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> Kp</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">ChildEBP RetAddr </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb7970 faeaefea nt!RtlInitUnicodeString+0x1b</span><br style="font-family: "Courier New",Courier,monospace;" /><u><b><span style="font-family: "Courier New",Courier,monospace;">WARNING: Stack unwind information not available. Following frames may be wrong.</span></b></u><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb79b4 faeaf808 _+0x2fea</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb7c7c 805a399d _+0x3808</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb7d4c 805a3c73 nt!IopLoadDriver+0x66d</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb7d74 804e426b nt!IopLoadUnloadDriver+0x45</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb7dac 8057aeff nt!ExpWorkerThread+0x100</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb7ddc 804f88ea nt!PspSystemThreadStartup+0x34</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">00000000 00000000 nt!KiThreadStartup+0x16</span></span><br />
<br />
In this case, we want to step out of RtlInitUnicodeString. There is a command<b> Step Out (shift+f11), however, not working here,</b> because Max++ does not follow the conventional C conventions. We have to press F10 very patiently. After around 10 steps over (F10), we reached _+1a32, as shown below!<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> p</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">nt!RtlInitUnicodeString+0x38:</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">804d92df 5f pop edi</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> p</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">nt!RtlInitUnicodeString+0x39:</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">804d92e0 c20800 ret 8</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> p</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">_+0x1a32:</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">faeada32 33c0 xor eax,eax</span></span><br />
<br />
_+1a32 is a part of a function in Max++, which is responsible for constructing an instance of _OBJECT_ATTRIBUTES (where "\systemroot\system32\drivers\rasppoe" is served as the ObjectName).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiElKBwb6uykfCKUnXTyY4NqU58gGq4ihgbNvFcPsvU8nAMTHYWNzt-PaRpLx7E0ZYwMVqSoMhcnSp2ACGQYy79Ov7ofilai55YosFOmQM10EuZLrNKRSnPXv1-q2kcO_GJML0OAph42FA/s1600/a2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiElKBwb6uykfCKUnXTyY4NqU58gGq4ihgbNvFcPsvU8nAMTHYWNzt-PaRpLx7E0ZYwMVqSoMhcnSp2ACGQYy79Ov7ofilai55YosFOmQM10EuZLrNKRSnPXv1-q2kcO_GJML0OAph42FA/s1600/a2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. The Function Which Calls RtlInitUnicodeString</td></tr>
</tbody></table>Tracing again from <u><b>_+1a32</b></u>, we can find that the program flow jumps to <u><b>_+23e9</b></u> (which reads the contents of the driver file and put it in a collection of locked virtual pages).<br />
<br />
<u><b>Challenge 1</b></u>. Finish the above analysis and provide a detailed report on how the "\systemroot\system32\drivers\raspppoe" string is used.<br />
<br />
<b><br />
</b><br />
<b>4. Virtual Pages</b><br />
We continue the analysis. At <b>_+3803</b>, Max++ calls another function located at <b>_+23C8</b> (which reads the contents of a file and puts the contents in virtual pages). There are some interesting technical details here. Figure 3 shows its function body. Note the first highlighted area, <u>it constructs an instance of _OBJECT_ATTRIBUTES that entails the file name "\systemroot\system32\drivers\raspppoe", as discussed in Section 3 (how to trace the use of data).</u> Then Max++ opens the file and queries about the standard file information of the file. When all operations succeed, it proceeds to the creation of virtual pages.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUJGpoUCqnlmeWDERHD3UA39LXzQHdsd7JntwByyJkrgb-bhNKzSMpu3UhfNrWFzw9KjIDvWvEu9FtgiWNoZFy8H89Q7M5sRpcbexRWHsKefyFpxfwoJ24cq-auBiG8EhUDxEFpqC9fYM/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUJGpoUCqnlmeWDERHD3UA39LXzQHdsd7JntwByyJkrgb-bhNKzSMpu3UhfNrWFzw9KjIDvWvEu9FtgiWNoZFy8H89Q7M5sRpcbexRWHsKefyFpxfwoJ24cq-auBiG8EhUDxEFpqC9fYM/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. First Part of _+23C8</td></tr>
</tbody></table><br />
We continue to the second part of Function _+23C8 (as shown in Figure 4). In driver implementation, in many cases you have to lock the physical pages for your virtual addresses (so that your contents in RAM will not be swapped into disk by OS). The intention of this part of code is pretty clear: it first requests virtual pages (see the first highlighted area), the virtual page descriptor is saved in a data structure named <b>_MDL</b> (stored at 8121c970). Once successful, it will ask the system to allocate the physical pages (see MmMapLockedPageSpecifyCache). Then Max++ reads the infected driver file into these pages (starting at address 0xf7649000). If you dump the data starts at 0xf7649000, you would find it's really a binary executable (i.e., see the magic 4D5A header info. for DOS header).<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> dd f7649000</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">f7649000 0090<u><b>5a4d </b></u>00000003 00000004 0000ffff</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">f7649010 000000b8 00000000 00000040 00000000</span></span><br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLV1sddVN49_gGfr9u2AxrpoF_QMYBZ9xuBvw3M8IqBv3nBAuYclZxeudtJYLmirdVn4eAOfE0GE5HwtrXOM7iQN0AVzoyilUUlWSzOmvh4tT0fdpjgIhZ286pzg5g6iDQIVjH2E0Bjbc/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLV1sddVN49_gGfr9u2AxrpoF_QMYBZ9xuBvw3M8IqBv3nBAuYclZxeudtJYLmirdVn4eAOfE0GE5HwtrXOM7iQN0AVzoyilUUlWSzOmvh4tT0fdpjgIhZ286pzg5g6iDQIVjH2E0Bjbc/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Second Part of _+23C8</td></tr>
</tbody></table>Now comes the interesting part (see the last highlighted area of Figure 4). Once the file contents of the infected driver are read, Max++<u><b> immediately released the physical pages</b></u> (for virtual address 0xf7649000) immediately. This is quite counter-intuitive, wouldn't Max++ want to use these data later? It's your job to figure it out.<br />
<br />
<u><b>Challenge 3.</b></u> Use the same trick for tracing the data, set two <u><b>data breakpoints</b></u>. One for the _MDL (e.g., in our case it's 0x8121c970) and one for the starting address of the infected driver executable data (e.g., in our case it's 0xf7649000). Try to figure out if these pages of malicious binary executable are really used or not. In summary, you have to answer the question: <u><b>why does Max++ release the pages in Figure 4</b></u>?<br />
<br />
<u><b>Challenge 4. </b></u>Analyze the function of _+22C3.<br />
<br />
<br />
<b>5. Infection of Driver Again and the Use of Virtual Pages</b><br />
At _+3889 Max++ calls function 2D9F. We now analyze its function (as shown in Figure 5). It is used to infect a driver file (the file name is given as the first parameter in its stack frame). The function first creates a section object on the file, then it performs a memcopy from a MDL descriptor to the file, and flushes the contents back to the file.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV_wm-Nv_nX1Lt8IlX1oK1765AygQNyfeMQRF5ChhY3PjxZ3JW5cs2kcjXauNtCy_HODlqolmIlBSsasrQ16DWrLqhIUXiw0KwNnAzyedB9iOAuwfdRrAHSLRzKwhOWJ132CfunH-0kj4/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV_wm-Nv_nX1Lt8IlX1oK1765AygQNyfeMQRF5ChhY3PjxZ3JW5cs2kcjXauNtCy_HODlqolmIlBSsasrQ16DWrLqhIUXiw0KwNnAzyedB9iOAuwfdRrAHSLRzKwhOWJ132CfunH-0kj4/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5. Infect Driver fips.sys</td></tr>
</tbody></table><u><b>Challenge 5</b></u>. use data tracing technique to analyze where is the malicious file content from?<br />
<br />
<b>6. Final Set Up of Malicious Disk Driver</b><br />
In Tutorial 22, we showed you how a malicious disk driver is used to simulate the file requests on "\??\C2CAD..." using a file called "12345678.sav". In the following, we show how this driver is configured by copying attributes from the real disk driver.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYR8LRJqEt3zNSYMxF1eukW79dIS6Yb0Fc-mlV4rXMrzY9gU5UbywnwZbZoh8Hw4_LV9DxmoCaS9Hghub4TQmubvyWEFnCwZ8CLH9tFHj4D7Yp9ifjw1K9r4Wx2hzzvA2XxFOq47KNhs0/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYR8LRJqEt3zNSYMxF1eukW79dIS6Yb0Fc-mlV4rXMrzY9gU5UbywnwZbZoh8Hw4_LV9DxmoCaS9Hghub4TQmubvyWEFnCwZ8CLH9tFHj4D7Yp9ifjw1K9r4Wx2hzzvA2XxFOq47KNhs0/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6. Wiring and Copying of Driver Object</td></tr>
</tbody></table><br />
The first part (as shown in the first highlighted area in Figure 6), adjusts the <u><b>DriverSection </b></u>field of the infected object. <u><b>It is actually a basic link list operation, which tries to remove the infected driver from the list of modules.</b></u> Notice that the type of the DriverSection field (offset 0x14) is <b>_LDR_DATA_TABLE_ENTRY</b>. You can use WinDbg to verify.<br />
<br />
Next in the second highlighted area of Figure 6, Max++ tries to copy all the attributes from the original \Driver\Disk object to the infected driver (in this case on the comments it's .serial, the name could change during sessions). There is only one attribute of the infected driver remains: the major function _+2bDE! Up to this point, Max++ has successfully set up the infected disk driver and it has hided it from the loaded module list.Unknownnoreply@blogger.com483tag:blogger.com,1999:blog-8770073098084592029.post-56793673779953516822012-03-23T11:37:00.000-07:002012-03-23T11:37:55.883-07:00Malware Analysis Tutorial 22: IRP Handler and Infected Disk Driver<b>Learning Goals</b>:<br />
<ol><li>Use WinDbg for kernel debugging</li>
<li>Understand basic inner working of disk driver</li>
<li>Understand virtual hidden drive creation</li>
<li>Reverse engineering Max++ driver infection technique</li>
</ol><b>Applicable to:</b><br />
<ol><li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security</li>
</ol><u><b>1. Introduction</b></u><br />
This tutorial continues the analysis presented in <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html">Tutorial 20</a>. We reveal how Max++ uses a modified disk driver to handle I/O requests on the disk it created (its name is "\\?\C2CAD..."). Recall that in section 4.2.3 we showed you Max++ creates a new IO device and hooks it to the malicious driver object, so that whenever an IO request is raised on this device the request will be forwarded to driver object <span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">8112d550</span></span>, <i>as shown below. </i>Pay attention to the value of <u><b>MajorFunction</b></u> (<u><b>0xfae36bde</b></u>), this is where IO requests are handled. Obtaining the module base address, we can easily calculate its offset: <b>_+2BDE</b>.<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> dt _DRIVER_OBJECT 8112d550 </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">nt!_DRIVER_OBJECT</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Type : 0n4</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> ...</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x02c DriverInit : <u><b>0xfae4772b </b></u>long +0</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x030 DriverStartIo : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x034 DriverUnload : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x038 MajorFunction : [28] <u><b>0xfae56bde </b></u>long +0</span></span><br />
<br />
<br />
To replicate the experiments of this tutorial, you have to follow the instructions in <u><b>Section 2</b></u> of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html">Tutorial 20</a>. In this tutorial, we perform analysis on the code of raspppoe.sys from <b>_+2BDE</b> (<b>0x10002BDE</b>)<br />
<br />
<b>2. Lab Configuration</b><br />
In general we will use the instructions of Section 2 of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html">Tutorial 20</a>. In the following we just remind you of several important steps in the configuration:<br />
(1) You need a separate image named "<b>Win_Notes</b>" to record and comment the code. You don't really need to run the malware on this instance, but just to record all your observations using the .udd file. To do this, you have to modify the control flow of IMM so that it does not crash on .sys files. See <u><b>Section 2</b></u> of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html">Tutorial 20</a> for details. Jump to <u><b>0x10002BDE</b></u> to start the analysis.<br />
(2) The second "<b>Win_DEBUG</b>" image has to be run in the <u><b> DEBUG </b></u>mode and there should be a WinDbg hooked from the host system using COM part -- so here, we are doing kernel debugging.<br />
(3) Set a breakpoint "<b>bu _+2BDE</b>" in WinDbg to intercept the driver entry function.<br />
<br />
<b>3. Background: Windows Driver Development</b><br />
Opferman provides an excellent introduction and sample code in [1]. In the following, we summarize of the major points here.<br />
<br />
<b>(1) Each driver has a driver entry function, its prototype is shown below:</b><br />
<br />
<div style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;">NTSTATUS DriverEntry(PDRIVER_OBJECT pDrv, PUNICODE_STRING reg)</span></div><br />
Here pDrv is a pointer to _DRIVER_OBJECT, and reg is a string that represents the registry entry where the driver could store information.<br />
<br />
As we shown earlier in Tutorial 20, the DriverEntry function is <b>located at _+372b</b>.<br />
<br />
<u><b>(2) Each driver may have a collection of </b><b>28 functions to handle different types of I/O requests</b></u> (such as close handle, read, write etc.) The IRP Function code can be found at [2] (typical ones are IRP_MR_CREATE and IRP_MR_READ).<br />
<br />
You might wonder, do we have to set breakpoints on all of the 28 functions? The answer is YES and NO. Look at the following dump (combined with the dump in section 1).<br />
<br />
<span style="font-family: "Courier New",Courier,monospace; font-size: x-small;">kd> dd 8112d550 </span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: x-small;">8112d550 00a80004 81210030 00000002 fae54000<br />
8112d560 00008000 ffbd7d80 8112d5f8 001a001a<br />
8112d570 e1389208 8068fa90 00000000 fae5772b<br />
8112d580 00000000 00000000 <u><b>fae56bde fae56bde</b></u><br />
8112d590 fae56bde fae56bde fae56bde fae56bde<br />
8112d5a0 fae56bde fae56bde fae56bde fae56bde<br />
8112d5b0 fae56bde fae56bde fae56bde fae56bde<br />
8112d5c0 fae56bde fae56bde fae56bde fae56bde</span><br />
<br />
At offset 0x38 of the driver object (the starting of the major function array), all IRP handlers are set to one single function _+2BDE! The malware author tries to be lazy here, and it saves us a lot of job too. We can just concentrate on <b>_+2BDE</b> then!<br />
<br />
Now before we move on, we should know that each IRP handler function has the following prototype:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;"><b><span style="font-size: x-small;">NTSTATUS Handler(PDEVICE_OBJECT pDevice, PIRP pIRP)</span></b></div><br />
Here, the first parameter is a <u><b>device object</b></u>, and the second parameter represents the<u><b> IRP request</b></u> to handle.<br />
<br />
When we hit the _+2BDE handler, we could easily find out the contents of the two input parameters (device located at 8112d550 and irp located at 00070000) as below:<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> dd esp</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb73fc 81210030 <b>8112d550 00070000 </b>81210030</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb740c fafb7460 804e37f7 81210030 ffbbe7e8</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb741c 00000000 fb07c7a9 81210030 c000014f</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb742c 00000000 00000000 c3a408e0 00000000</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb743c 00000001 00000000 804e2490 fa047501</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb744c 00000000 fafb7450 fafb7450 804fb1a9</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb745c 00000000 fafb748c fb07ce80 81210030</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafb746c fafb7484 ffb6fe10 81210030 ffb6fe10</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> <b>dt _DEVICE_OBJECT 8112d550 </b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">nt!_DEVICE_OBJECT</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Type : 0n4</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x002 Size : 0xa8</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x004 ReferenceCount : 0n-2128543696</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x008 DriverObject : 0x00000002 _DRIVER_OBJECT</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x00c NextDevice : 0xfae54000 _DEVICE_OBJECT</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> ...</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> <b>dt _IRP 00070000 </b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">nt!_IRP</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Type : 0n193</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x002 Size : 0</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x004 MdlAddress : 0x00000100 _MDL</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> ...</span></span><br />
<br />
<br />
<br />
<b>4. Anatomy of Infected Disk Driver</b><br />
Figure 1 shows you the first part of the IRP handler function at _+2BDE.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKJ1IRq4TXxsbXDxCqb8-o4dH4DL9bc9pUGwCu4cM1EgZwvHcTIeV3Msbnhksi9b2D5jTMgeGh5rjxKaxxbnNOIfzPPz7pUVFaxO1Hckp7ERM1K-An2QB2u8hbdmDnOFWSiANbQ3ZxqGc/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKJ1IRq4TXxsbXDxCqb8-o4dH4DL9bc9pUGwCu4cM1EgZwvHcTIeV3Msbnhksi9b2D5jTMgeGh5rjxKaxxbnNOIfzPPz7pUVFaxO1Hckp7ERM1K-An2QB2u8hbdmDnOFWSiANbQ3ZxqGc/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Infected Disk Driver</td></tr>
</tbody></table><br />
As shown in Figure 1, the control flow is a very simple decision procedure. First it takes out the PDEVICE_OBJECT pointer from <u><b>EBP+8 </b></u>(1st parameter) and compare it with a global variable stored at <u><b>100061B0 </b></u>(see highlighted area). Clearly, the global variables stores the newly created infected device (for \??\C2CAD...). If it is not a request to \??\C2CAD, the flow jumps to <u><b>10002BFD</b></u> (second highlighted area), which calls <u><b>PoCallDriver </b></u>to relay the request to low level (real) drivers to do the work; otherwise it calls a self-defined function <u><b>handleIRPForVirtualVolume </b></u>which performs the real operation to simulate the virtual disk.<br />
<br />
<u><b>Challenge 1.</b></u> Analyze the logic between 10002BFD and 10002C25 (highlighted area in Figure 1). Especially, explain the instructions at 0x10002C16 and 0x10002C19.<br />
<br />
<b>5. Simulating the Virtual Disk Operations</b><br />
Now we will analyze the function <u><b>handleIRPForVirtualVolume</b></u>. It is located at <b>_+292A</b>. In this case, you need to set a breakpoint using "bp _+292A" in WinDbg. Figure 2 shows its major function body. Notice that you can easily infer from the context that EBX is an input parameter of the function, <u><b>EBX points to the IRP request right now</b></u>!<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlBdg_-XIuM_bCNvThdsTa9Wl484ZHKTgukYsNonEvoPp5CfMkJZArCkX5sO7M0QpZdKwJTXDBwU0YiaEVxIb6eus1SdDLyb-5XGpypVZLrIKYH1PY-cPionqbHBXJZSZbrMoVXKPvjPE/s1600/a2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlBdg_-XIuM_bCNvThdsTa9Wl484ZHKTgukYsNonEvoPp5CfMkJZArCkX5sO7M0QpZdKwJTXDBwU0YiaEVxIb6eus1SdDLyb-5XGpypVZLrIKYH1PY-cPionqbHBXJZSZbrMoVXKPvjPE/s1600/a2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. Function body of handleIRPForVirtualVolum</td></tr>
</tbody></table><br />
<br />
Now comes the interesting part. Look at Figure 2, at 0x1000293C EAX now has the "MajorFunction" of _IO_STACK_LOCATION (the value is one of the IRP_MJ_xxx types). Then there is a big switch case statement (see the highlighted area in Figure 2), which redirects the control flow to handle each of the different IRP requests such as READ, WRITE, etc.<br />
<br />
<u><b>Challenge 2. </b></u>Argue that the statement about "0x1000293C EAX now has the "MajorFunction" (the value is one of the IRP_MJ_xxx types" is true. You may need to find out the definition of IRP_MJ_xyz values.<br />
<br />
As an example of how Max++ simulates the disk volume operation, we show how it handles the IRP_MJ_READ request. Figure 3 shows the handler code.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLE4bgL9175nnIJBHCjtMJmYmHvJAx2EUZ8pyCwpVxuqubUNojWzSZ6ozlKtDAuHp9L6YvSbcUYkbSzY1hv6teotErNtmqzsRWUcax0VqzGi71Yr9CQZfeQYvGV2dYo8JAp7f-_1Es2gA/s1600/a2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLE4bgL9175nnIJBHCjtMJmYmHvJAx2EUZ8pyCwpVxuqubUNojWzSZ6ozlKtDAuHp9L6YvSbcUYkbSzY1hv6teotErNtmqzsRWUcax0VqzGi71Yr9CQZfeQYvGV2dYo8JAp7f-_1Es2gA/s1600/a2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. Simulate the Disk Operation on File</td></tr>
</tbody></table> First, let's look at the definition of _IO_STACK_LOCATION which represents an I/O operation task. Note that at this moment, ESI points to the current _IO_STACK_LOCATION, the following is its contents. You can easily infer that it's current Device Object is \??\C2CAD...<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> dt _IO_STACK_LOCATION ff9c7fd8</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">nt!_IO_STACK_LOCATION</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 MajorFunction : 0x3 ''</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x001 MinorFunction : 0 ''</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x002 Flags : 0x2 ''</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x003 Control : 0 ''</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x004 Parameters : __unnamed</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x014 DeviceObject : 0xffb746d8 _DEVICE_OBJECT</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +<u><b>0x018 </b><b>FileObject </b></u>: (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x01c <u><b>CompletionRoutine</b></u> : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x020 Context : (null) </span></span><br />
<br />
Now look at the first instruction <u><b>LEA EAX, [ESI-24]</b></u> in Figure 3. The purpose here is to move 0x24 bytes away (note the direction of stack) and the size of _IO_STACK_LOCATION (0x24). So EAX is now pointing to a new _IO_STACK_LOCATION instance. The next couple of instructions copy the first 9 words of the existing _IO_STACK_LOCATION to the new.<br />
<br />
Then at <u><b>0x10002B10</b></u> (look at the <b>highlighted area of Figure 3</b>), it assigns the value of ECX (from global variable at DS:[1000614C]) to offset 0x18 of the new _IO_STACK_LOCATION. Notice that 0x18 is the <u><b>FileObject </b></u>attribute (see above dump of _IO_STACK_LOCATION!). The following is the dump of the File Object pointed by ECX:<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> dt _FILE_OBJECT 811b25d0</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">nt!_FILE_OBJECT</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Type : 0n5</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x002 Size : 0n112</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> ...</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x02c Flags : 0x40040</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x030 FileName : _UNICODE_STRING "</span><b style="font-family: "Courier New",Courier,monospace;">\WINDOWS\system32\config\yknueenf.sav</b><span style="font-family: "Courier New",Courier,monospace;">"</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x038 CurrentByteOffset : _LARGE_INTEGER 0x0</span></span><br />
...<br />
<br />
<br />
<br />
<br />
<br />
<div style="background-color: yellow; color: red;"><span style="font-size: large;"><u><b>Now it's pretty clear that the READ operation on the disk volume is actually achieved by CONSTRUCTING A NEW _IO_STACK_LOCATION task on the "*.sav" file created by Max++ earlier!</b></u></span></div><br />
The last interesting point is at 0x10002B17: Max++ hooks up a function for the <u><b>CompleteRoutine (offset 0x1c of _IO_STACK_LOCATION)</b></u>, the intention is pretty clear: the data stored on the *.sav file is encrypted, and Max++ now decodes it when reading it out.<br />
<br />
We've finished a very challenging and interesting analysis of a portion of the infected disk driver. Now it's your job to finish the rest:<br />
<br />
<u><b>Challenge 3.</b></u> What happens when FormatEx operation is performed on the virtual disk volume?<br />
<br />
<u><b>Challenge 4.</b></u> Analyze all the other IRP_MJ_ operations supported by the infected disk driver (hint: this could take considerable efforts).<br />
<br />
<br />
<br />
<br />
<b>References</b><br />
[1] T. Opferman, "Driver Development Introduction Part I", available at http://codeproject.com<br />
[2] MSDN, "IRP Function Code", available atUnknownnoreply@blogger.com187tag:blogger.com,1999:blog-8770073098084592029.post-27342250335948223382012-03-17T16:53:00.002-07:002012-03-23T05:10:17.259-07:00Malware Analysis Tutorial 21: Hijack Disk Driver<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlNeNlHc-e3N_-82t-VM_rXCypsIUDhkd3TIHMz3RY0LAL4FEE3CEaQho8utZIGzii69oXFx2Dqwx3tvWV1CpvfznDwGz6ruZLlpwJf4HwXqHNooNcdC4M9dVuEVNPAZ-LydnYq5ZRATo/s1600/g4.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"> </a></div><b>Learning Goals</b>:<br />
<ol><li>Use WinDbg for kernel debugging</li>
<li>Understand basic inner working of disk driver</li>
<li>Understand virtual hidden drive creation</li>
<li>Reverse engineering Max++ driver infection technique</li>
</ol><b>Applicable to:</b><br />
<ol><li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security</li>
</ol><u><b>1. Introduction</b></u><br />
This tutorial shows you how to use WinDbg to analyze the malicious .sys (driver) file (let it be raspppoe.sys which is randomly infected by Max++). We will learn some basic analysis techniques using WinDbg.<br />
<br />
Once the driver file is loaded, Max++ will establish a virtual hidden drive to store the malicious files it unpacked from itself or downloaded from the Internet. To achieve this goal, Max++ has to perform some low level disk operations. First, it will establish a file called "12345678.sav", which actually stores all the information of the hidden disk drive. Then it overwrites the disk/file driver so that all requests (read/write operations) to the hidden disk drive is actually performed on the file "12345678.sav".<br />
<br />
To replicate the experiments of this tutorial, you have to follow the instructions in <u><b>Section 2</b></u> of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html">Tutorial 20</a>.<br />
<br />
<b>2. Lab Configuration</b><br />
In general we will use the instructions of Section 2 of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-20-kernel.html">Tutorial 20</a>. In the following we just remind you of several important steps in the configuration:<br />
(1) You need a separate image named "Win_Notes" to record and comment the code. You don't really need to run the malware on this instance, but just to record all your observations using the .udd file. To do this, you have to modify the control flow of IMM so that it does not crash on .sys files.<br />
(2) The second "Win_DEBUG" image has to be run in the DEBUG mode and there should be a WinDbg hooked from the host system using COM part -- so here, we are doing kernel debugging.<br />
(3) Set a breakpoint "<b>bu _+372b</b>" in WinDbg to intercept the driver entry function.<br />
<br />
Once your Win_Notes environment is set up you should have the following dump at 0x1000372b.<b></b><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI-IgE9N1fxlyP-OQl5M_I0C0oYKt20i58TNXS1wgtGgtgMKQDB-OI9M5It0QIkbK9LGQBeC4Q9fsPgIHFLANj6L-BDCgFz7Gd2flYQ5G1rCn4z7-y_BlTIbPHrDsptmkwXC3BxA6hDhc/s1600/g1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI-IgE9N1fxlyP-OQl5M_I0C0oYKt20i58TNXS1wgtGgtgMKQDB-OI9M5It0QIkbK9LGQBeC4Q9fsPgIHFLANj6L-BDCgFz7Gd2flYQ5G1rCn4z7-y_BlTIbPHrDsptmkwXC3BxA6hDhc/s1600/g1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Win_Notes Dump</td></tr>
</tbody></table><b><br />
</b><br />
Figure 2 shows the initial setting of WinDbg.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh457CGm7nruAfkClSkpiWwDe7v5MM8ro27Krhu5xdHtS6pRK6wj38GBE4ITr3Z9a6XwUJA2fPS6PvWp0A-slzK3oYar-fnPVEf2UafU7k5PNajMIRfrP1Mioi2hcxRkIdxlOBfMzD-cS4/s1600/g2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh457CGm7nruAfkClSkpiWwDe7v5MM8ro27Krhu5xdHtS6pRK6wj38GBE4ITr3Z9a6XwUJA2fPS6PvWp0A-slzK3oYar-fnPVEf2UafU7k5PNajMIRfrP1Mioi2hcxRkIdxlOBfMzD-cS4/s1600/g2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. Win_Debug ScreenShot</td></tr>
</tbody></table><br />
<br />
In the following we use "<b>_</b>" to represent the base address of the driver file. In the Win_Notes, the base address is 0x10000000 and in the WinDbg, it is based on the run-time value, e.g., 0xfafe6400. Whenver we refer to an address we will use the form of <b>_ + offset</b>, e.g., _+372b (which is the entry address of the driver)<br />
<b> </b><br />
<br />
<b>3. Basic WinDbg Skills for Inspecting Function Parameters</b><br />
This section introduces several useful techniques you can use to analyze function calls when using WinDbg. We will take the function call at<b> 0x10003743</b> (in Figure 1) as an example. Our objective is to analyze: what is the function and what are its parameters.<br />
<br />
Since we might have to step into the function in WinDbg, let's first set a breakpoint at the next immediate instruction after 0x10003743, if you look at Figure 1 you will notice that the next address is _ + 3749. <br />
<br />
In WinDbg let's set two breakpoints:<br />
kd> bp _+3743<br />
kd> bp _+3749<br />
kd> g <br />
<br />
You might notice that here we are using "<u><b>bp</b></u>" instead of "<u><b>bu</b></u>", this is because the module name "_" can be resolved by WinDbg now after the module is loaded.<br />
<br />
Now let's examine the data around ESP. Typing "<u><b>dd esp</b></u>", we have the following. Clearly, currently ESP value is 0xfafb39c0 and the first parameter would be located at 0x81184008 and the second parameter would be 0x0000005c and so on.<br />
<span style="font-family: "Courier New",Courier,monospace;">kd> dd esp</span><br />
<span style="font-family: "Courier New",Courier,monospace;"><u><b>fafb39c0 </b><b>81184008 </b><b>0000005c </b></u>81139f38 e1533360</span><br />
<span style="font-family: "Courier New",Courier,monospace;">fafb39d0 00000000 dd841000 fafb3a18 812e6f80</span><br />
<span style="font-family: "Courier New",Courier,monospace;">fafb39e0 8054b6b8 81184076 e14fd07e 81184000</span><br />
<span style="font-family: "Courier New",Courier,monospace;">fafb39f0 805702de e14fd008 e14fd000 e14fd080</span><br />
<span style="font-family: "Courier New",Courier,monospace;">fafb3a00 00000001 00000000 00000080 00000020</span><br />
<span style="font-family: "Courier New",Courier,monospace;">fafb3a10 81184076 80557ee0 81184000 80566ca2</span><br />
<span style="font-family: "Courier New",Courier,monospace;">fafb3a20 e14fd07e 805a65ee 805a669a 81184000</span><br />
<span style="font-family: "Courier New",Courier,monospace;">fafb3a30 e1bc9908 00000000 e14fd008 e14fd010</span><br />
<br />
<br />
Now press F11 in WinDbg into the function _+3743 you will have the following:<br />
<span style="font-family: "Courier New",Courier,monospace;">kd> t</span><br />
<span style="font-family: "Courier New",Courier,monospace;"><b>nt!wcsrchr</b>:</span><br />
<span style="font-family: "Courier New",Courier,monospace;">80506d93 8bff mov edi,edi</span><br />
<br />
Notice that it shows that we are currently located in the function body of nt!wcsrchr. This allows us to identify the function name: <u><b>wcsrchr</b></u>. There could be an easier way to identify it using the "<u><b>ln</b></u>" command in WinDbg. However, interestingly, it does not work in our session and at this moment we do not know the cause.<br />
<br />
Searching the documentation for <u><b>wcsrcchr</b></u>(str, c), we soon find that <u><b>wcsrchr </b></u>is the wide character version of strrchr which searches the last occurrence of a character "c" in a string "str". Here the wide character means that each character actually takes two bytes (for internationalization and localization purpose).<br />
<br />
So far we could infer that 0x81184008 is the starting address of the string, and the character is 0x5c. Doing a data dump of 0x81184008, we have:<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> db 0x81184008</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">81184008 5c 00 52 00 45 00 47 00-49 00 53 00 54 00 52 00 <b>\.R.E.G.I.S.T.R.</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">81184018 59 00 5c 00 4d 00 41 00-43 00 48 00 49 00 4e 00 <b>Y.\.M.A.C.H.I.N.</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">81184028 45 00 5c 00 53 00 59 00-53 00 54 00 45 00 4d 00 <b>E.\.S.Y.S.T.E.M.</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">81184038 5c 00 43 00 6f 00 6e 00-74 00 72 00 6f 00 6c 00 <b>\.C.o.n.t.r.o.l.</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">81184048 53 00 65 00 74 00 30 00-30 00 31 00 5c 00 53 00 <b>S.e.t.0.0.1.\.S.</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">81184058 65 00 72 00 76 00 69 00-63 00 65 00 73 00 <b>5c</b> 00 <b>e.r.v.i.c.e.s.\.</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">81184068 2e 00 6d 00 72 00 78 00-73 00 6d 00 62 00 00 00 <b>..m.r.x.s.m.b</b>...</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">81184078 da 01 0c 00 00 00 00 00-ff ff ff ff 18 00 00 00 ................</span></span><br />
<br />
Look at the above data dump you can immediately infer that the string is "<u><b>\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services\.mrxsmb</b></u>" and 0x5c is the "<b>\</b>" character. <u><b>Clearly, Max++ is trying to get the service name associated with the driver. Keep in mind that the string (service name) is from the Driver_Object (the first parameter of the entire driver entry function)!</b></u><br />
<br />
Now type "g" again in Windbg so that it hits _+3749. Then run the program by F10 (step over) several times, you will soon reach the code at _+375f (the 0x1000375f in Figure 1). You might notice that it is comparing the value located at [ebx] with 0x2E. Look at the dump you might notice that the ASCII value for 0x2E is "."<br />
<br />
So what's the purpose of the code?<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">_+0x375f:</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fae6775f 66833b2e <b>cmp word ptr [ebx],2Eh</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> db ebx</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">81184068 <b>2e</b> 00 6d 00 72 00 78 00-73 00 6d 00 62 00 00 00 <b>.</b>.m.r.x.s.m.b...</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">81184078 da 01 0c 00 00 00 00 00-ff ff ff ff 18 00 00 00 ................</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">81184088 00 10 00 00 01 00 00 00-00 00 00 00 d9 01 00 00 ................</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">81184098 00 00 00 00 58 4d 4c 03-00 00 00 00 d9 01 0c 00 ....XML.........</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">811840a8 00 00 00 00 ff ff ff ff-18 00 00 00 00 10 00 00 ................</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">811840b8 01 00 00 00 00 00 00 00-30 00 00 00 00 00 00 00 ........0.......</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">811840c8 4c 51 4c 03 00 00 00 00-30 00 0c 00 00 00 00 00 LQL.....0.......</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">811840d8 ff ff ff ff 18 00 00 00-00 10 00 00 01 00 00 00 ................</span></span><br />
<br />
The purpose is to examine if the service name starts with "<b>.</b>". Recall that in <a href="http://fumalwareanalysis.blogspot.com/2012/02/malware-analysis-tutorial-18-infecting.html">Tutorial 18</a> (<u><b>section 4</b></u>), when Max++ infects the driver, it also modifies its registry entry (duplicates all the registry contents and creates a new entry name "."). This time, the code is verifying that it is indeed the infected driver!<br />
<br />
If this is indeed the infected driver and now since it's "correctly" running. Max++ now has to hide its trace and properly set up the registry key. The next action it's going to perform is to remove the "." and "LEGACY_" registry entry. It's now your job to analyze the two function calls at _+3797 and _+379d (0x10003797 and 0x1000379d in Figure 1).<br />
<br />
<u><b>Challenge 1.</b></u> Analyze the function call at 0x10003797 in Figure 1 (what is it trying to do and what are its function parameters?)<br />
<u><b>Challenge 2.</b></u> Analyze the function call at 0x1000379d in Figure 1 (what is it trying to do and what are its function parameters?) <br />
<br />
<b>4. Infecting File Driver</b><br />
We now look at Max++'s behavior regarding disk driver. Right after modifying the registry entries, Max++ calls function _+36CA. [For your lab, simply go to <b>0x100036CA</b> in your notes environment and "<b>bp _+36CA</b>" in WinDbg]. As shown in Figure 2, the function consists of two important steps: (1) to create a disk device "\??\C2CAD ..." and set up the 12345678.sav file for simulating all file operations on the disk. This is done by the function call at <b>0x100036DE</b>; and (2) to infect all disk devices by setting up their IRP requests handlers properly; this is done at the JMP of <b>0x100036E4</b> (it jumps to 0x10002C95). We now proceed to these two important calls.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioXYL5qldWMjjGGwYnnjuPszWhqMFJD2vR8WEPGUihXLHgMb3jHSpRPMjq00H3885biGt51plmUM_2PpiFjMHrBk_JuX2UBiRAXOutXMW5cfUUYTIQsvHEuoLri-PZm2UuTi_9qYnIdWY/s1600/g3.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioXYL5qldWMjjGGwYnnjuPszWhqMFJD2vR8WEPGUihXLHgMb3jHSpRPMjq00H3885biGt51plmUM_2PpiFjMHrBk_JuX2UBiRAXOutXMW5cfUUYTIQsvHEuoLri-PZm2UuTi_9qYnIdWY/s1600/g3.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. Infection of Disk Driver</td></tr>
</tbody></table><br />
<b>4.1 Create Device "\??\C2CAD..." (_+3108)</b><br />
At 0x100036DE, Max++ calls function createDeviceC2CAD (_+3108). Figure 3 displays the first part of function _+3108 (createDeviceC2CAD is the name we assigned to the function). It consists of two function calls: (1) at 0x1000312C, Max++ calls<b> ntoskrnl.IoCreateDevice</b> to create a device calls "\??\C2CAD..."; and then (2) at 0x10003140, Max++ calls <b>ntoskrnl.ObMakeTemporaryObject</b> to make the newly created device partially effective.<br />
<br />
<b>4.1.1 Create Disk Volume </b><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlNeNlHc-e3N_-82t-VM_rXCypsIUDhkd3TIHMz3RY0LAL4FEE3CEaQho8utZIGzii69oXFx2Dqwx3tvWV1CpvfznDwGz6ruZLlpwJf4HwXqHNooNcdC4M9dVuEVNPAZ-LydnYq5ZRATo/s1600/g4.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlNeNlHc-e3N_-82t-VM_rXCypsIUDhkd3TIHMz3RY0LAL4FEE3CEaQho8utZIGzii69oXFx2Dqwx3tvWV1CpvfznDwGz6ruZLlpwJf4HwXqHNooNcdC4M9dVuEVNPAZ-LydnYq5ZRATo/s1600/g4.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. Add Disk Device and Update IRP Handler</td></tr>
</tbody></table>The following is the official declaration of<u><b> IoCreateDevice()</b></u> function from MSDN [1]. To analyze the contents, we could use the same technique introduced earlier and stop at _+312C to observe the stack. We listed the values of each of the attributes in the following as well (in the comments area).<br />
<br />
<pre>NTSTATUS IoCreateDevice(
__in PDRIVER_OBJECT DriverObject, //<b>"\Driver\.mrxsmb"</b>
__in ULONG DeviceExtensionSize,
__in_opt PUNICODE_STRING DeviceName, <b>//""\??\C2CAD972#4079#4fd3#A68D#AD34CC121074"
"</b>
__in DEVICE_TYPE DeviceType,
__in ULONG DeviceCharacteristics,
__in BOOLEAN Exclusive,
__out PDEVICE_OBJECT *DeviceObject
);
</pre><br />
In summary: its purpose is to create a new device named "\??\C2CAD972..." whose driver is ".mrxsmb".<br />
<br />
<u><b>Challenge 3:</b></u> where is the resulting DEVICE_OBJECT located? (hint: look at the last parameter of IoCreateDevice). <br />
<br />
The next function is to call <u><b>ObMakeTemporary </b></u>on the newly allocated DEVICE_OBJECT and call <u><b>ObDereferenceObject </b></u>again. These two function are reserved function of the OS and there is no official documentation. The purpose is to <u><b>completely destroy the newly created device object</b></u>! (so that it's not living in kernel any more!) You might wonder why?<br />
<br />
<span style="background-color: yellow;">This is because once the device object is deleted, you will not be able to find the device "\??\C2CAD..."anymore. But, the driver mechanism for handling request to "\??\C2CAD..." has somehow partly survived the deletion of device object. The next step of Max++ is to complete the construction of IO handling for "\??\C2CAD..." and simulate its actions using a single file called 12345678.sav.</span><br />
<br />
<b>4.1.2 Create Simulation File 12345678.sav</b><br />
<br />
We now look at how the file 12345678.sav is created. As shown in Figure 4, it consists of three steps: (1) At 0x10003176 it <u><b>encrypts </b></u><b>12345678.sav</b> using the last AGP write time and <u><b>generates a random file name</b></u> such as <b>yknueenef.sav</b>; (2) it then at 0x100031B4 calls <u><b>zwCreateFile </b></u>to create the file, (3) it calls <u><b>zwSetFileControlInfo </b></u>to make sure that the file is not compressed.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIURUMqJEUc-VbQ3GkAOc5_v8C7iNtV8oqfuZ9_O1-42Hnfznl3jgxocqwNKj02rY8rANGdgwdTlovbCNWdwbQJw43MnKTBFeVmtx7ijuFJ49DqqqVfIut9UFGCjKzsHIAqiChqDSj5eA/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIURUMqJEUc-VbQ3GkAOc5_v8C7iNtV8oqfuZ9_O1-42Hnfznl3jgxocqwNKj02rY8rANGdgwdTlovbCNWdwbQJw43MnKTBFeVmtx7ijuFJ49DqqqVfIut9UFGCjKzsHIAqiChqDSj5eA/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Create File 12345678.sav</td></tr>
</tbody></table>To see the trick of the encoding file name, look at the following WinDbg dump below (before and after the call at 0x10003177).<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> dd esp</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf8f4 <b>fafaf940 </b>81138bb8 812f2000 812f2068</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf904 fafaf927 0073005c 00730079 00650074</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf914 0072006d 006f006f 005c0074 00790073</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf924 00740073 006d0065 00320033 0063005c</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf934 006e006f 00690066 005c0067 00320031</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf944 00340033 00360035 00380037 0073002e</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf954 00760061 00000000 00000000 00000000</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf964 00000000 00000000 00000000 00000000</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> db <b>fafaf940</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf940 31 00 32 00 33 00 34 00-35 00 36 00 37 00 38 00 <b>1.2.3.4.5.6.7.8.</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf950 2e 00 73 00 61 00 76 00-00 00 00 00 00 00 00 00 <b>..s.a.v</b>.........</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf960 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf970 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf980 00 00 00 00 00 00 00 00-23 00 00 00 c1 c8 4d 80 ........#.....M.</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf990 08 00 00 00 10 8b 13 81-10 8b 13 81 cc fd fa fa ................</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf9a0 30 00 00 00 10 8b 13 81-00 20 2f 81 68 20 2f 81 0........ /.h /.</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf9b0 7c fc fa fa 00 00 00 00-7c fc fa fa e3 76 e0 fa |.......|....v..</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> p</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">_+0x317c:</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fae0717c 53 push ebx</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> db fafaf940</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf940 79 00 6b 00 6e 00 75 00-65 00 65 00 6e 00 66 00 <b>y.k.n.u.e.e.n.f.</b></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf950 2e 00 73 00 61 00 76 00-00 00 00 00 00 00 00 00 <b>..s.a.v.</b>........</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf960 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf970 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf980 00 00 00 00 00 00 00 00-23 00 00 00 c1 c8 4d 80 ........#.....M.</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf990 08 00 00 00 10 8b 13 81-10 8b 13 81 cc fd fa fa ................</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf9a0 30 00 00 00 10 8b 13 81-00 20 2f 81 68 20 2f 81 0........ /.h /.</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafaf9b0 7c fc fa fa 00 00 00 00-7c fc fa fa e3 76 e0 fa |.......|....v..</span></span><br />
<br />
<u><b>Challenge 4.</b></u> Analyze the details of the function call at 0x10003177 (encrypt file name).<br />
<u><b>Challenge 5.</b></u> Analyze the details of the function call at 0x100031B4 (create file)<br />
<u><b>Challenge 6. </b></u> Analyze the details of the function call at 0x100031E5 (set file control information)<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8tZVG4p-sTxGmewqtbdWbwGsIOW92nHqDGLCOfDTm6aZOr7Z55eU96ISIm69i5ocnyVgel-SlkskSiF5TfyNJNuN8VQn0migE1ZtrJU5-JrydsPFHD77OYqQBUrMSURHg6D49GOqrLaM/s1600/a2.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8tZVG4p-sTxGmewqtbdWbwGsIOW92nHqDGLCOfDTm6aZOr7Z55eU96ISIm69i5ocnyVgel-SlkskSiF5TfyNJNuN8VQn0migE1ZtrJU5-JrydsPFHD77OYqQBUrMSURHg6D49GOqrLaM/s1600/a2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5. Set up Properties of 12345678.sav and Test Disk Drive</td></tr>
</tbody></table><br />
As shown in Figure 5, the next action Max++ performs is t<b>o set the end of file of 12345678.sav to 0x0100 0000</b> (because this is going to be a big file that holds a lot of stuff). It then gets the device handler of 12345678.sav (note that the current disk driver is "<u><b>FileSystem\sr</b></u>"), however, this handler will be never used (by the IoDeleteDevice at the end). Because at 0x1000329E, it directly jumps and skips the call of IoDeleteDevice call.<br />
<br />
<u><b>Challenge 7</b></u>. Analyze the details of the function call at 0x100031FD (zwSetInformation).<br />
<u><b>Challenge 8</b></u>. Analyze the details of the function call at 0x1000322E (getDevice)<br />
<u><b>Challenge 9</b></u>. Analyze the details of the function call at 0x10003297 (which calls <b>_+302E</b>)<br />
<br />
Note that function <b>_+302E</b> (in challenge 9) just tests the opening of "\??\C2CAD..." and it <u><i><b>fails </b></i></u>(no wonder, because the IRP handling has not been set up for the new disk driver yet).<br />
<br />
<b>4.2 Infect Disk Devices (_+2C95)</b><br />
We now look at the function at <b>0x10002C95</b> (the jump is made from 0x100036E4). Figure 6 shows its function body. This function infects (modifies) all device objects hooked to the Disk driver. We now check the details in depth. As shown in the highlighted areas in Figure 6, the function performs to actions: (1) first it calls IoEnumerateDeviceObjectList to get the list of device objects registered with the "\Driver\Disk" driver - in our system, we get a list of two devices; (2) it then uses a loop to modify the devices related (creating a new device and making some copies as well as modifications). But what's the purpose of all these actions? We need to get more details and trace the execution.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvAnzOsY4mGgXQYyG16PS1oI2HFa1KG2wpWgDTXx4dxitgTPocBY2Sxc-YiIBXqidCUYicmbjIhcCtgpFf_yZndUDfK1O032zPrtJzQBJMOujm_zmcUppQiZHZIVZFo1-f9d_TTTIumls/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvAnzOsY4mGgXQYyG16PS1oI2HFa1KG2wpWgDTXx4dxitgTPocBY2Sxc-YiIBXqidCUYicmbjIhcCtgpFf_yZndUDfK1O032zPrtJzQBJMOujm_zmcUppQiZHZIVZFo1-f9d_TTTIumls/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6. Infect Devices Hooked to Disk Driver</td></tr>
</tbody></table><br />
<b>4.2.1 Device Object List</b><br />
We are interested in figuring out the device list involved. To achieve this goal, we need to first check out the parameters of <b>IoEnumerateDeviceObjectList</b>. According to [<a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff548342%28v=vs.85%29.aspx">2</a>], the function prototype of <b>IoEnumerateDeviceList </b>is listed below:<br />
<br />
<pre><span style="font-family: "Courier New",Courier,monospace; font-size: x-small;">NTSTATUS IoEnumerateDeviceObjectList(
__in PDRIVER_OBJECT <u><b>DriverObject</b></u>,
__out PDEVICE_OBJECT *<u><b>DeviceObjectList</b></u>,
__in ULONG DeviceObjectListSize,
__out PULONG <u><b>ActualNumberDeviceObjects</b></u>
);</span>
</pre><br />
Clearly, the first parameter is the INPUT driver object (related to which we want to enumerate all devices), the second parameter is a pointer points to the place holder for a list of _DEVICE_OBJECTs, and the fourth parameter is another integer point which points to the integer variable that holds the number of device objects.<br />
<br />
To examine the contents of the stack, we display the first four words starting from the ESP value, as shown below. Here, the first param (DriverObject) is <u><b>81299670 </b></u>and the fourth param (ActualNumberDeviceObjects) is <u><b>fafab9bc</b></u>.<br />
<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> bp _+2cd8</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> g</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"></span><span style="font-family: "Courier New",Courier,monospace;">fae36cd8 ff15d480e3fa call dword ptr [_+0x40d4 (fae380d4)]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> dd esp</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafab5a0 <u><b>81299670 </b><b>fafab5b4 </b></u>00000400 <u><b>fafab9bc</b></u></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> <b>dt _DRIVER_OBJECT</b> <u><b>81299670 </b></u></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">nt!_DRIVER_OBJECT</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> ...</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x018 DriverExtension : 0x81299718 _DRIVER_EXTENSION</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x01c DriverName : _UNICODE_STRING "<b>\Driver\Disk</b>"</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> </span></span><br />
By examining the contents of _DRIVER_OBJECT using the WinDbg dt command, we are able to know that the driver is "<u><b>\Driver\Disk</b></u>". After stepping over the function call, we can identify that there are <u><b>two </b></u>Device Objects involved, and they are <u><b>812fb810 </b></u>and <u><b>812fc030</b></u>: . Details are shown below.<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> p</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">_+0x2cde:</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fae36cde 395dfc cmp dword ptr [ebp-4],ebx</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> dd <u><b>fafab9bc</b></u></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafab9bc <u><b>00000002 </b></u>fafabc7c fae377af ffb3a6e8</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> dd <u><b>fafab5b4</b></u></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fafab5b4 <u><b>812fb810 </b><b>812fc030 </b></u>00000000 e1b63f30</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"></span></span><br />
We could display the contents of the two device object at as below. First note their difference <u><b>in Sector size</b></u>. What is your guess? You could infer that <u><b>_DEVICE_OBJECT 812fc030 is not a volume</b></u>! According to "<span style="font-family: "Courier New",Courier,monospace;">If the device object does not represent a volume, this member is set to zero. If the device object represents a volume, this member specifies the volume's sector size, in bytes</span>." in [3].<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;">kd> dt _DEVICE_OBJECT 812fb810<br />
nt!_DEVICE_OBJECT<br />
+0x000 Type : 0n3<br />
+0x002 Size : 0x368<br />
+0x004 ReferenceCount : 0n0<br />
...<br />
<u><b>+0x0ac SectorSize : 0x200</b></u><br />
+0x0ae Spare1 : 0<br />
+0x0b0 DeviceObjectExtension : 0x812fbb78 _DEVOBJ_EXTENSION<br />
+0x0b4 Reserved : (null) <br />
kd> dt _DEVICE_OBJECT 812fc030 <br />
nt!_DEVICE_OBJECT<br />
+0x000 Type : 0n3<br />
+0x002 Size : 0x518<br />
+0x004 ReferenceCount : 0n0<br />
...<br />
<u><b>+0x0ac SectorSize : 0</b></u><br />
+0x0ae Spare1 : 1<br />
+0x0b0 DeviceObjectExtension : 0x812fc548 _DEVOBJ_EXTENSION<br />
+0x0b4 Reserved : (null) <br />
</span></div><b>4.2.2 The Loop That Performs Infection</b><br />
We now look at the very tricky actions of related to infection. The loop picture is shown below.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGBebuK_qD0_qMFM0DH1LWGJx6Fo2Iexfy_j_x0wOfhxtK_C03vxx996qiELG5nPQSUplvplFk77iapl_jRtHdLsmAjKJVZ4AzsCZ74vQN4y5bfhEhEJXfdr3P5p8ASIXmMNeWwlKFU68/s1600/a1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGBebuK_qD0_qMFM0DH1LWGJx6Fo2Iexfy_j_x0wOfhxtK_C03vxx996qiELG5nPQSUplvplFk77iapl_jRtHdLsmAjKJVZ4AzsCZ74vQN4y5bfhEhEJXfdr3P5p8ASIXmMNeWwlKFU68/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 7: Part 1 of the Loop: check If this the module</td></tr>
</tbody></table><br />
<br />
At _+2CF6 (or 0x10002CF6), EDI is now pointing to the current _DEVICE_OBJECT being visited. You can verify the information below (it's now pointing to the second device at <u><b>812FC030</b></u>). Note that the loop starts to process the <b>LAST device</b> in the list! Can you figure out why?<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> bp _+2CF6</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> g</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">Sat Mar 17 10:40:52.406 2012 (UTC - 4:00): Breakpoint 1 hit</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">_+0x2cf6:</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">fae36cf6 8b4728 mov eax,dword ptr [edi+28h]</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">kd> r edi</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">edi=812fc030</span></span><br />
<br />
<u><b>Challenge 10.</b></u> Prove that the loop as shown in Figure 6 is processing the device objects from the end to the beginning.<br />
<br />
Now, as shown in Figure 7, Max++ is performing a lot of checks on the device properties, mostly performed on the DeviceExtension structure. The device extension structure is device specific and we could not get more details here, but the 2nd device module has passed all checks and now Max++ performs the modification of the module.<br />
<br />
<b>4.2.3 Infection</b><br />
The second part of the loop is shown in Figure 8.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwq0I8d0CUa4vWUDjTK6Lu62Ve0VJsMIx1KUXg9QljvqHejywt5-HMQYT3vsnwhi4Od7-y3wprigVTLjSwzlWNWABBdyGdQoliwV2tZsv_qNF1pFTExbZ_iAhK7g325oo80IKYer5P2Fg/s1600/a2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwq0I8d0CUa4vWUDjTK6Lu62Ve0VJsMIx1KUXg9QljvqHejywt5-HMQYT3vsnwhi4Od7-y3wprigVTLjSwzlWNWABBdyGdQoliwV2tZsv_qNF1pFTExbZ_iAhK7g325oo80IKYer5P2Fg/s1600/a2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 8. Create New Device Object to Wrap Old Device Object</td></tr>
</tbody></table><br />
<br />
The first interesting action is the call of IoCreateDevice() at _+2D34. Its first parameter is a DRIVER_OBJECT. When we dump its contents we found something interesting:<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">kd> dt _DRIVER_OBJECT ffb3a6e8</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">nt!_DRIVER_OBJECT</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x000 Type : 0n4</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> ...</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x02c DriverInit : <u><b>0xfae3772b </b></u>long +0</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x030 DriverStartIo : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x034 DriverUnload : (null) </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> +0x038 MajorFunction : [28] <u><b>0xfae36bde </b></u>long +0</span></span><br />
<br />
This is the infected driver (entry address 372b)! So <u><b>Max++ is creating another IO device which is associated with the <span style="background-color: yellow;">infected driver</span>. Note that the DEVICE_OBJECT returned by the function will be stored at [EBP-8]. You can infer this from the IoCreateDevice() specification and the code.</b></u><br />
<br />
Next, Max++ will perform some copy actions. For example, at _+2D3E, it is copying the StackSize attribute (located at offset 0x30) of _DEVICE_OBJECT from the old device object to the new one. Then, at _+2D4D, it is setting the first word (guess: AttachedDevice) of the DeviceExtension to the old device. If you look into details, it seems to be performing some standard linked list operations which modifies the DeviceExtension of the new device object in the following ways:<br />
<div style="background-color: yellow;">At DeviceExtension[0] it stores the OLD device object, at DeviceExtension [4] it stores the real attached low level hardware device (controled by ATAPI)! While the device itself is registered with the INFECTED driver!</div><br />
Thus, it is very clear what Max++ wants to do: it inserts another layer of device into the IRP request handler chain such that any disk IRP request will go through the INFECTED DRIVER (entry function: 372b)!<br />
<br />
<u><b>At this point, we have a big picture: Max++ has completed the first part of wiring of the malicious driver to disk operations (a new wrapper disk device object is created). All IRP requests related to disk will be wired to the malicious driver first! But notice that the "\??\C2CAD..." device has not been completely set up. We'll continue to the second part in the next tutorial.</b></u><br />
<br />
<b><u>References</u></b><br />
1. Microsoft, MSDN, "IoCreateDevice", available at http://msdn.microsoft.com/en-us/library/windows/hardware/ff548397(v=vs.85).aspx<br />
2. Mcrosoft MSDN, "IoEnumerateDeviceObjectList", available at http://msdn.microsoft.com/en-us/library/windows/hardware/ff548342(v=vs.85).aspx<br />
3. Microsoft MSDN, "Device Object", available at http://msdn.microsoft.com/en-us/library/windows/hardware/ff543147(v=vs.85).aspxUnknownnoreply@blogger.com87tag:blogger.com,1999:blog-8770073098084592029.post-78311102839516416032012-03-10T07:51:00.000-08:002012-03-10T07:51:25.052-08:00Malware Analysis Tutorial 20: Kernel Debugging - Intercepting Driver Loading<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvRcvvkP14WY1v2QUF_Wr0OdJtSHpL1UKRnUCYjVmyoF3GLn619f0YQ7FzRahQFtGJZ7CqSJI6MCJf1Q5CqHTFRVYLiRLGjU5S_wniEnxXBwZNlba8RAdTvCEOnwPALH2hQuz5Mz5mGQY/s1600/a4.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><b>Learning Goals</b>:<br />
<ol><li>Use WinDbg for kernel debugging</li>
<li>Patch Debugger to Defend Malicious Actions by Malware</li>
<li>Understand Driver Entry </li>
<li>Interception of Driver Loading</li>
</ol><b>Applicable to:</b><br />
<ol><li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security</li>
</ol><u><b>1. Introduction</b></u><br />
We now explore the more challenging part of a reverse engineering process. In the past, all the malicious actions performed by Max++ have been at the application level (ring-3), which can be effectively traced by Immunity Debugger. After Max++ injects code into a randomly selected driver file, and loads it with <u><b>zwLoadDriver()</b></u>, the analysis becomes more difficult - Immunity Debugger is not able to analyze ring-0 code and we have to use WinDbg as a kernel debugger. Unfortunately, WinDbg does not have a convenient notes-taking support. In this case, we will duplicate the VBox instance to two. One used for taking notes (where we will have Immunity Debugger to take comments on code), and the other used for kernel debugging (and it will be controlled by a WinDbg from the host via COM port).<br />
<br />
In this tutorial, we concentrate on the sophisticated setup of the lab environment and kick start the analysis of the driver entry function. Our job is to <u><b>intercept the loading of the driver</b></u> that Max++ infects.<br />
<br />
In the following, we call the VBox instance with IMM the <u><b>Win_Notes</b></u> instance and the instance to be debugged the <u><b>Win_Debug</b></u> instance. We first begin the introduction of how to set up the lab environment, and then we start the kernel debugging process.<br />
<br />
Let us assume the name of the infected driver is <u><b>rasppoe_2.sys</b></u>.Note that the version of the IMM we used for this tutorial is <u><b>1.8.3.</b></u> The instructions listed in Section 2 is for this version only.<br />
<br />
<u><b>2. Lab Configuration</b></u><br />
The lab configuration of this tutorial is sophisticated. It contains the following four steps:<br />
(1) Take the infected driver.<br />
(2) Make the duplicate copy of VBox instance.<br />
(3) Start the Win_Notes environment.<br />
(4) Start the Win_Debug instance.<br />
<br />
<u><b>2.1 Retrieve the Infected Driver</b></u><br />
The first step is to retrieve the infected driver. You can simply follow the instructions in <u><b>Section 2</b></u> of <a href="http://fumalwareanalysis.blogspot.com/2012/03/malware-analysis-tutorial-19-anatomy-of.html">Tutorial 19 (Anatomy of Infected Driver)</a> and save the drivers. Once the driver is taken, you have to <u><b>email</b></u> these files back to yourself, and<u><b> restore the snapshot</b></u> of the<u><b> clean system</b></u> (because it has been infected and Max++ has removed itself from disk). Then download these files from your email. From this point, we can duplicate the VBox instance. <br />
<br />
<u><b>2.2 Make the Duplicate Copy of VBox instance</b></u><br />
Now in VirtualBox right click on theWinXP instance and select <u><b>CLONE</b></u>, and rename the new instance to <u><b>Win_Notes</b></u> and select the <u><b>full clone</b></u> and <u><b>all snapshots</b></u>. Up to now, you should have <u><b>two VBox instances</b></u> of the WinXP system. We use Win_Notes for taking comments only.<br />
<br />
Hofstra students can pick up both images from my office.<br />
<br />
<u><b>2.3 Start the Win_Notes Environment</b></u><br />
The purpose of the <u><b>Win_Notes</b></u> environment is to take the notes. As the malware will crash IMM for a certain reason, we have to change the control flow of IMM a bit to successfully take our notes. Follow the steps below to set up the environment:<br />
<br />
(1) Start IMM.<br />
(2) In the <u><b>first instance</b></u> of IMM, open the IMM exe file from c:\Program Files\Immunity Debugger\IMM.exe<br />
(3) Set a SOFTWARE breakpoint <u><b>at 0x004E6095 </b></u>. This is some vulnerable part of the IMM debugger. It occasionally crashes given mal-formatted data. We now provide some brief explanation here. By no means, we are trying to reverse engineer the IMM debugger, but just want to correct some bugs and provide a minor fix on the current version of the debugger.<br />
At <u><b>0x004E6095 (as shown in Figure 1)</b></u>, IMM is trying to put a "\0" at the end of a string. Here ESI points to the beginning of a string and EDI contains its length. Now, if ESI and EDI are both set to NULL, what happens is the instruction will trigger a segmentation fault (it's then trying to access address 0xFFFFFFFF which leads to segmentation fault).<br />
To solve the problem, we have to skip this instruction when ESI/EDI value is not right.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk1dUIpp06lVHAGrXSzL6a6SrRNt__Ytr1d7iLRFvWps94Lldl2WpssoRtRF4OuDfW8BGtVm6EKtpsVahfvrBge7xC7xnZN4Nk2tw10wRxbptj7vRu0R5hINiAeJmHO-iQlshyphenhyphenWuXbx2w/s1600/a1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk1dUIpp06lVHAGrXSzL6a6SrRNt__Ytr1d7iLRFvWps94Lldl2WpssoRtRF4OuDfW8BGtVm6EKtpsVahfvrBge7xC7xnZN4Nk2tw10wRxbptj7vRu0R5hINiAeJmHO-iQlshyphenhyphenWuXbx2w/s1600/a1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Reset the EIP to Skip one struction</td></tr>
</tbody></table> Follow the instructions below:<br />
Now <u><b>load the rapppoe_2.sys</b></u> in the second IMM, and let it run. We will hit the breakpoint <u><b>0x004E6095</b></u> several times in the 1st IMM. Whenever you see the<u><b> ESI/EDI pair is 0</b></u>, launch the Python command window (see Figure 1, <u><b>t</b><b>he 2nd button on the toolbar</b></u>), and type the following command to readjust EIP.<br />
<u><b>imm.setReg("EIP", 0x004E609A)</b></u><br />
<br />
<u><b> But if the ESI/EDI is ok, don't do the above, just hit F9 and let it continue.</b></u> You will repeat the above for several times until the .sys file is loaded. Note that, during the process, you will get a couple of warnings like some other modules are out of range, just click ok and let it go.<br />
<br />
(4) Now<u><b> in the second IMM</b></u>, click <u><b>View -> Executable Modules</b></u>, and double click on <u><b>rapppoe_2.sys</b></u>, you will be able to jump to the starting address of the module. The module should start from 0x10001000 (PUSH ESI). <u><b> Figure 2 shows our analysis window</b></u>, loaded with the comments (Hofstra students can get the .udd file from my office). <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2nijrbBvmqsi6ahz077Z7WSpKYg4y8TDtEbKcvtic3hDliNQzWTebO3XZbEX3K4soTIcbvhR1rGVg7hAhhV_chOD612-bXwxy52PFtq-Thor0CiSj3TY_JVQC_edUamQXkPsyrUvs90E/s1600/a2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2nijrbBvmqsi6ahz077Z7WSpKYg4y8TDtEbKcvtic3hDliNQzWTebO3XZbEX3K4soTIcbvhR1rGVg7hAhhV_chOD612-bXwxy52PFtq-Thor0CiSj3TY_JVQC_edUamQXkPsyrUvs90E/s1600/a2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. The Driver File Dump</td></tr>
</tbody></table> (5) We will need an additional step to finish: Click<u><b> View->Modules</b></u> in the 2nd IMM, and record its entry address. No matter which driver file Max++ picks to infect, the entry address (offset) is always <u><b>0x372B</b></u> (as shown in Figure 3).<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmvFH9Lu5nUdIkdHy-51rfR1_P2yNPSDBpqgp7uwDZlXo1QHTBNCQkuHHmNSID12pqkB4NibPntsiCsBRQdG1TTIK77qdL-bdH-1GCfFY6Mog9hRtxuQsSmZp7_STQak8E07PMFDEiNuo/s1600/a3.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmvFH9Lu5nUdIkdHy-51rfR1_P2yNPSDBpqgp7uwDZlXo1QHTBNCQkuHHmNSID12pqkB4NibPntsiCsBRQdG1TTIK77qdL-bdH-1GCfFY6Mog9hRtxuQsSmZp7_STQak8E07PMFDEiNuo/s1600/a3.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. Entry Point of the Module raspppoe_2.ssys</td></tr>
</tbody></table>(6) Now right click in the <u><b>CPU pane -> Go To (0x1000372B)</b></u>, and you should be located at the entry point of the drive module. The <u><b>Win_Notes environment</b></u> is prepared and you can use it to take notes (placing comments on the code). Figure 4 shows you the first part of the malicious infected driver.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV8ULu5oEyaCzSisM3-6Yvh8HyEA-8bRvdORAOSKo7lvJF_AoSZCdbyZqf4wcb13UDc0_-OY1kZBnUfcAkWBmN65hvtENWLBYMFUYS4wI7jpaQYzJiaAL5pAJBNdm0196BLzSX9a8QbbA/s1600/a4.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV8ULu5oEyaCzSisM3-6Yvh8HyEA-8bRvdORAOSKo7lvJF_AoSZCdbyZqf4wcb13UDc0_-OY1kZBnUfcAkWBmN65hvtENWLBYMFUYS4wI7jpaQYzJiaAL5pAJBNdm0196BLzSX9a8QbbA/s1600/a4.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Entry Part of the Infected Driver</td></tr>
</tbody></table><br />
<u><b>2.4 Trace the Win_Debug Instance</b></u><br />
We now describe how to use the <u><b>WinDbg on the host </b></u>to perform the tracing of the driver module. Our purpose is to stop the system on the <u><b>Driver_Entry function </b></u>of raspppoe_2.sys. Note that the function can only be traced by WinDbg because IMM is a ring-3 debugger. Our purpose is to stop at the driver entry function. This is accomplished by the following steps.<br />
<br />
(1) Start <u><b>WinXP_DEBUG </b></u>image in <u><b>DEBUGGED </b></u>mode. Now in your host system, start a windows command window and CD to "<u><b>c:\Program Files\Debugging Tools for Windows (x86)</b></u>" (where WinDBG is installed). Type "<u><b>windbg -b -k com:pipe,port=\\.\pipe\com_12</b></u>" (check the com port number in your VBox instance set up). <br />
<br />
(2) Now in your WinDbg window, type "<b>bu _+372b</b>", this is to set a breakpoint at offset <u><b>0x372b </b></u>for module named "<u><b>_</b></u>". You might wonder where the "_" is coming from. Later, we will show you how we find out that after the zwLoadDriver() is called by Max++, t a module named "_" is added by Max++.<br />
<br />
(3) Now type "g" twice to let the system go. In the following, we will run Max++ in a controlled way, until we load the driver. <br />
<br />
<br />
(4) Now launch IMM in the WinXP instance, clear all breakpoints and hardware breakpoints in IMM (see <u><b>View->Breakpoints</b></u> and <u><b>View->Hardware Breakpoints</b></u>).<br />
<br />
(5) Go to <u><b>0x4012DC </b></u>and set a hardware breakpoint there. (why not software bp? Because that region will be self-extracted and overwritten and the software BP will be lost). Pay special attention that once you go to 0x4012DC, directly right click on the line to set hardware BP (currently it's gibberish code).<br />
<br />
(6) Press<u><b>F9</b></u> several times run to <u><b>0x4012DC</b></u>. You will encounter several breakpoints before 0x4012DC. If you pay attention, they are actually caused by the int 2d tricks (explained in <a href="http://www.blogger.com/cd%20%22c:/Program%20Files/Debugging%20Tools%20for%20Windows%20%28x86%29%22">Tutorial 3</a> and <a href="http://fumalwareanalysis.blogspot.com/2011/10/malware-analysis-tutorial-4-int2dh-anti.html">4</a>, and <a href="http://fumalwareanalysis.blogspot.com/2011/10/malware-analysis-tutorial-5-int2d-anti.html">5</a>). Simply ignore them and continue (using F9) until you hit <u><b>0x4012DC</b></u>.<br />
<br />
Figure 5 shows the code that you should be able to see. As you can see, this is right before the call of RtlAddVectoredException, where hardware BP is set to break the LdrLoadDll call (see <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-11-starling.html">Tutorial 11</a> for details).<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwY824Lshgaeu8tuf06xKBmXnOPpS45_aLSiyOO45sA9pUkglF0nkUNMcKdeRPsWKWehn-aEkpgnh_QlWjxN24f9iwlRq3j49BXfnl1EalZjMddZCgC7CrlmOpeIW3gUaEWXq-lxL5ULk/s1600/c1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwY824Lshgaeu8tuf06xKBmXnOPpS45_aLSiyOO45sA9pUkglF0nkUNMcKdeRPsWKWehn-aEkpgnh_QlWjxN24f9iwlRq3j49BXfnl1EalZjMddZCgC7CrlmOpeIW3gUaEWXq-lxL5ULk/s1600/c1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5: code at 0x4012DC</td></tr>
</tbody></table>(7) Now scroll down about 2 pages and set a <u><b>SOFTWARE BREAKPOINT</b></u> at <u><b>0x401417</b></u>. This is right after the call of LdrLoadDll("lz32.dll"), where Max++ finishes the loading of lz32.dll. Then hit <u><b>SHIFT+F9 </b></u>several times until you reach <u><b>0x401417</b></u> (you will hit 0x7C90D500 twice, this is somwhere inside ntdll.zwMapViewSection which is being called by LdrLoadDll). <br />
<br />
<br />
 <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdtJaTR3WJ33l5wLbd_tnt7knNdgNf2mnPTZkY4JnUjgqmsT5MmCcncck40DPpvSxsTDU1FqKSmI3pKeZpha2zb9nEzPe6EVmFatNSs-b5G6Jz3wS0GslZmw4vscwFZONefJRcfuDAtGc/s1600/c2.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdtJaTR3WJ33l5wLbd_tnt7knNdgNf2mnPTZkY4JnUjgqmsT5MmCcncck40DPpvSxsTDU1FqKSmI3pKeZpha2zb9nEzPe6EVmFatNSs-b5G6Jz3wS0GslZmw4vscwFZONefJRcfuDAtGc/s1600/c2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6: code at 0x401407</td></tr>
</tbody></table> <br />
(8) Now we will set a breakpoint at <u><b>0x3C1B3E </b></u>. As shown in Figure 7, Goto <u><b>0x3C1B3E </b></u>and set a <u><b>SOFTWARE </b><b>BREAKPOINT</b><b>. </b></u>Press <u><b>SHIFT+F9 </b></u>to run to <u><b>0x3C1B3E </b></u>. (You may see a warning that this is out range of the code segment, simply ignore the warning).<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvRcvvkP14WY1v2QUF_Wr0OdJtSHpL1UKRnUCYjVmyoF3GLn619f0YQ7FzRahQFtGJZ7CqSJI6MCJf1Q5CqHTFRVYLiRLGjU5S_wniEnxXBwZNlba8RAdTvCEOnwPALH2hQuz5Mz5mGQY/s1600/a4.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvRcvvkP14WY1v2QUF_Wr0OdJtSHpL1UKRnUCYjVmyoF3GLn619f0YQ7FzRahQFtGJZ7CqSJI6MCJf1Q5CqHTFRVYLiRLGjU5S_wniEnxXBwZNlba8RAdTvCEOnwPALH2hQuz5Mz5mGQY/s1600/a4.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 7: The Code Right Before zwLoadDriver</td></tr>
</tbody></table>Figure 7 shows the code that you should be able to see at <u><b>0x3C1B3E </b></u>. This is right before the call zwLoadDriver.<br />
<br />
<u><b>*** Now we'll capture the driver loading event. in WinDbg, pres "Ctrl+Break" to stop the program. click Debug-> Event Filters, select the <i>LoadModule event</i> and click "Add". Then "g" to continue ***</b></u><br />
<br />
Now go back to the WinXP_Debug, press F8 twice and execute the zwLoadDriver function and you might see that your WinXP_Debug instance is frozen, because now the WinDbg hitsmodule load event first. If you do an "lm" command in WinDbg, you will see that the newly loaded module is "_". Type "g" again in WinDbg, you will now hit the breakpoint<u><b> </b></u><b>bu _ + 372b</b>. <br />
<br />
As shown by Figure 8, the instruction we are stopped at is located at fae3772b (this is offset 372b relative to the base address of module "_"). <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKwS_FcLKphzGyEaCwncAycT9wwaXwJtH9UfQUCqmXC-SgdJjXkh7vCQoHXXoCG-okT6_hDlYunaLdrWNLPg24XiphubqnCjQ8HLd0XTE6yMnigxljuaRUmww3adNd_s5AbkpjXrzD8T8/s1600/a5.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKwS_FcLKphzGyEaCwncAycT9wwaXwJtH9UfQUCqmXC-SgdJjXkh7vCQoHXXoCG-okT6_hDlYunaLdrWNLPg24XiphubqnCjQ8HLd0XTE6yMnigxljuaRUmww3adNd_s5AbkpjXrzD8T8/s1600/a5.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 8: WinDbg DUMP</td></tr>
</tbody></table>Press <u><b>Alt+7 </b></u>(or <u><b>View->Disassembly</b></u>), you can watch the current instructions (as shown in Figure 9). If you compare with Figure 1, you can verify that we are indeed in the Driver Entry function of raspppoe_2.sys.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyDuc8Jm2dkOhp3-sAfpxfKVmrv5ThwZiV4x47fddD6g_taFqp9VzXDjz7cMf_7Wk_ZRrstum8JlmFVcNGhhPuob6VDGgJ5He55eQlxV0c6oNoIjisAuGltqKHdOHvVFZrwH4GE1s4ME4/s1600/a6.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyDuc8Jm2dkOhp3-sAfpxfKVmrv5ThwZiV4x47fddD6g_taFqp9VzXDjz7cMf_7Wk_ZRrstum8JlmFVcNGhhPuob6VDGgJ5He55eQlxV0c6oNoIjisAuGltqKHdOHvVFZrwH4GE1s4ME4/s1600/a6.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 9: Disassembly Dump</td></tr>
</tbody></table><br />
<br />
<br />
<u><b>3. Driver Entry Function</b></u><br />
We now proceed to the analysis of the Driver Entry function using WinDbg. According to [<a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff544113%28v=vs.85%29.aspx">1</a>], a driver entry function on Windows has the following prototype:<br />
<br />
DRIVER_INITIALIZE DriverEntry; NTSTATUS DriverEntry(<br />
__in struct _DRIVER_OBJECT *<u><b>DriverObject</b></u>,<br />
__in PUNICODE_STRING <u><b>RegistryPath </b></u><br />
)<br />
<br />
The first parameter is an object containing the information about the related driver object, and the second parameter is a unicode string containing the path to the corresponding registry key in the registry database. Our first goal of the analysis is to figure out the values of these two input parameters.<br />
<br />
If you look at the first couple of instructions of the function (see Figure 9, from fae3772b to fae37738), they are to set up the stack frame (e.g., to preserve the previous EBP value, to readjust ESP value to create the stack frame and to preserve other relevant registers).<br />
<br />
In WinDbg, Press <u><b>F10</b></u> (single step) to run to <u><b>0xFAE37738 </b></u>(see Figure 9), according to the C function call parameter passing convention, we have the 1st parameter (_DRIVER_OBJECT) located at<u><b> EBP+8</b></u> and the 2nd parameter (PUNICODE_STRING) at <u><b>EBP+C</b></u>. Now that these two values are simply pointers. Let's first get these two pointers by typing "dd EBP", we have the memory dump below: [Note that <u><b>the first colum</b></u>n is the <u><b>address </b></u>for each row and each row has 4 computer words (32-bit each), e.g., fafabc7c (1st word in 1st row) is the address for fafabd4c (first row), and fafabc8c (1st word of second row) is the address for 00000000). Here EBP value is <u><b>fafabc7c</b></u>.<br />
<br />
<br />
<span style="font-family: "Courier New",Courier,monospace; font-size: x-small;">kd> dd EBP<br />
fafabc7c fafabd4c 805a399d <u><b>811254d8 </b><b>81184000</b></u><br />
fafabc8c 00000000 f7a1dcf4 00000000 00000018<br />
fafabc9c 00000000 fafabcc0 00000010 00000000<br />
fafabcac 00000000 811254d8 fafabd70 811462f0<br />
fafabcbc 81184000 00200020 81128f48 e101b000<br />
fafabccc 811254d8 81143280 00000020 8000030c<br />
fafabcdc fae34000 00000308 00120010 e14fe090<br />
fafabcec 0000007a 00060004 e1bcc5f8 00000000</span><br />
<br />
Clearly, the 1st parameter _DRIVER_OBJECT value is 811254d8 (the entry address of the object), and the _UNICODE_STRING (2nd parameter) starts at 81184000.<br />
<br />
We now display their values:<br />
<div style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;">kd> <u><b>dt _DRIVER_OBJECT 811254d8</b></u><br />
nt!_DRIVER_OBJECT<br />
+0x000 Type : 0n4<br />
+0x002 Size : 0n168<br />
+0x004 DeviceObject : (null) <br />
+0x008 Flags : 2<br />
+0x00c DriverStart : 0xfae34000 Void<br />
+0x010 DriverSize : 0x8000<br />
+0x014 DriverSection : 0x81143280 Void<br />
+0x018 DriverExtension : 0x81125580 _DRIVER_EXTENSION<br />
+0x01c DriverName : _UNICODE_STRING "<u><b>\Driver\.NDProxy</b></u>"<br />
+0x024 HardwareDatabase : 0x8068fa90 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"<br />
+0x028 FastIoDispatch : (null) <br />
+0x02c DriverInit : 0xfae3772b long +0<br />
+0x030 DriverStartIo : (null) <br />
+0x034 DriverUnload : (null) <br />
+0x038 MajorFunction : [28] 0x804fa87e long nt!IopInvalidDeviceRequest+0<br />
kd> dt _UNICODE_STRING 81184000<br />
<u><b>nt!_UNICODE_STRING</b></u><br />
"\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services\.NDProxy"<br />
+0x000 Length : 0x70<br />
+0x002 MaximumLength : 0x70<br />
+0x004 Buffer : 0x81184008 "<u><b>\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services\.NDProxy</b></u>"</span></div><br />
<br />
<br />
As you note, this matches the role of raspppoe.sys (which is used for remote internet connectoin).<br />
<br />
<u><b>Challenge of the Day: </b></u>Analyze the call at _+3743, what are its parameters and what is it doing?<br />
<br />
<u><b>References</b></u><br />
[1] Microsoft, "DriverEntry Routine", available at http://msdn.microsoft.com/en-us/library/windows/hardware/ff544113(v=vs.85).aspxUnknownnoreply@blogger.com28tag:blogger.com,1999:blog-8770073098084592029.post-35618453581710667982012-03-02T05:29:00.000-08:002012-03-02T05:29:14.146-08:00Malware Analysis Tutorial 19: Anatomy of Infected Driver<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1R8BY611brAjow1sdRhDBZt-0lqMQoslPvy8m_jooK0R0MKKKJO7rAZHEjJfa1KL4qrcwXNzdI3k2ePUQm_q3UhRrRATC1bFBJcVBGbVUnDu0E-Ly44oyGawAjQ1aquRmkC_6Y9cL6iE/s1600/g1.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><b>Learning Goals</b>:<br />
<ol><li>Perform binary comparison of files</li>
<li>Practice debugging techniques</li>
<li>Understand executable file header format</li>
</ol><b>Applicable to:</b><br />
<ol><li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security</li>
</ol><u><b>1. Introduction</b></u><br />
We now continue our analysis presented in <a href="http://fumalwareanalysis.blogspot.com/2012/02/malware-analysis-tutorial-17-infecting.html"><u><b>Tutorials 17</b></u></a> and <a href="http://fumalwareanalysis.blogspot.com/2012/02/malware-analysis-tutorial-18-infecting.html"><u><b>18</b></u></a>. This time, we are interested in looking at the infected driver and compare it with the clean state of the same driver. For this purpose, we need to perform some "surgery" to the malware and the operating system to retrieve the two versions of the driver. Recall that, the malware infects a driver randomly, and we have to be cautious during the process.<br />
<br />
We will intercept the running of Max++ at two critical points:<br />
(1) right <u><b>after </b></u>Max++ randomly picks up the driver name. At this point, we will copy the clean version of the driver from the system.<br />
(2) right <u><b>before </b></u>Max++ calls zwLoadDriver() to load the infected driver. We will copy the infected version of the driver from the OS.<br />
<br />
Then we could easily do a binary comparison of the two versions of the drivers. We will use a handy tool called <u><b>WinDiff</b></u>. Please follow the lab configuration below to take out the two drivers.<br />
<br />
<u><b>2. Lab Configuration (Retrieve BIN files of Drivers)</b></u><br />
(*) Download <u><b>WinDiff </b></u>and have it installed.<br />
<br />
(0) Start WinXP image in <u><b>DEBUGGED </b></u>mode. Now in your host system, start a windows command window and CD to "<u><b>c:\Program Files\Debugging Tools for Windows (x86)</b></u>" (where WinDBG is installed). Type "<u><b>windbg -b -k com:pipe,port=\\.\pipe\com_12</b></u>" (check the com port number in your VBox instance set up). When WinDbg initiates, types "g" (go) twice to let it continue.<br />
<br />
(1) Now launch IMM in the WinXP instance, clear all breakpoints and hardware breakpoints in IMM (see <u><b>View->Breakpoints</b></u> and <u><b>View->Hardware Breakpoints</b></u>).<br />
<br />
(2) Go to <u><b>0x4012DC </b></u>and set a hardware breakpoint there. (why not software bp? Because that region will be self-extracted and overwritten and the software BP will be lost). Pay special attention that once you go to 0x4012DC, directly right click on the line to set hardware BP (currently it's gibberish code).<br />
<br />
(3) Press<u><b>F9</b></u> several times run to <u><b>0x4012DC</b></u>. You will encounter several breakpoints before 0x4012DC. If you pay attention, they are actually caused by the int 2d tricks (explained in <a href="http://www.blogger.com/cd%20%22c:/Program%20Files/Debugging%20Tools%20for%20Windows%20%28x86%29%22">Tutorial 3</a> and <a href="http://fumalwareanalysis.blogspot.com/2011/10/malware-analysis-tutorial-4-int2dh-anti.html">4</a>, and <a href="http://fumalwareanalysis.blogspot.com/2011/10/malware-analysis-tutorial-5-int2d-anti.html">5</a>). Simply ignore them and continue (using F9) until you hit <u><b>0x4012DC</b></u>.<br />
<br />
Figure 1 shows the code that you should be able to see. As you can see, this is right before the call of RtlAddVectoredException, where hardware BP is set to break the LdrLoadDll call (see <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-11-starling.html">Tutorial 11</a> for details).<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwY824Lshgaeu8tuf06xKBmXnOPpS45_aLSiyOO45sA9pUkglF0nkUNMcKdeRPsWKWehn-aEkpgnh_QlWjxN24f9iwlRq3j49BXfnl1EalZjMddZCgC7CrlmOpeIW3gUaEWXq-lxL5ULk/s1600/c1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwY824Lshgaeu8tuf06xKBmXnOPpS45_aLSiyOO45sA9pUkglF0nkUNMcKdeRPsWKWehn-aEkpgnh_QlWjxN24f9iwlRq3j49BXfnl1EalZjMddZCgC7CrlmOpeIW3gUaEWXq-lxL5ULk/s1600/c1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1: code at 0x4012DC</td></tr>
</tbody></table>(4) Now scroll down about 2 pages and set a <u><b>SOFTWARE BREAKPOINT</b></u> at <u><b>0x401417</b></u>. This is right after the call of LdrLoadDll("lz32.dll"), where Max++ finishes the loading of lz32.dll. Then hit <u><b>SHIFT+F9 </b></u>several times until you reach <u><b>0x401417</b></u> (you will hit 0x7C90D500 twice, this is somwhere inside ntdll.zwMapViewSection which is being called by LdrLoadDll). <br />
<br />
<br />
 <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdtJaTR3WJ33l5wLbd_tnt7knNdgNf2mnPTZkY4JnUjgqmsT5MmCcncck40DPpvSxsTDU1FqKSmI3pKeZpha2zb9nEzPe6EVmFatNSs-b5G6Jz3wS0GslZmw4vscwFZONefJRcfuDAtGc/s1600/c2.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdtJaTR3WJ33l5wLbd_tnt7knNdgNf2mnPTZkY4JnUjgqmsT5MmCcncck40DPpvSxsTDU1FqKSmI3pKeZpha2zb9nEzPe6EVmFatNSs-b5G6Jz3wS0GslZmw4vscwFZONefJRcfuDAtGc/s1600/c2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2: code at 0x401407</td></tr>
</tbody></table> <br />
(6) Now we will set a breakpoint at <u><b>0x3C1E77 </b></u>. Goto <u><b>0x3C1E77 </b></u>and set a <u><b>SOFTWARE </b><b>BREAKPOINT</b><b>. SHIFT+F9</b></u> there. Press <u><b>SHIFT+F9 </b></u>to run to <u><b>0x3C1E77 </b></u>. (You may see a warning that this is out range of the code segment, simply ignore the warning).<br />
<br />
(Figure 3 shows the code that you should be able to see at <u><b>0x3C1E77 </b></u>. This is right after the loop for randomly picking up a system module to infect. As shown in the image, this time, the driver to infect is "<u><b>afd.sys</b></u>".<br />
<br />
<u><b>*** Now copy afd.sys from c:\Windows\System32\Drivers to your desktop and rename it as afd_v1.sys</b></u><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1R8BY611brAjow1sdRhDBZt-0lqMQoslPvy8m_jooK0R0MKKKJO7rAZHEjJfa1KL4qrcwXNzdI3k2ePUQm_q3UhRrRATC1bFBJcVBGbVUnDu0E-Ly44oyGawAjQ1aquRmkC_6Y9cL6iE/s1600/g1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1R8BY611brAjow1sdRhDBZt-0lqMQoslPvy8m_jooK0R0MKKKJO7rAZHEjJfa1KL4qrcwXNzdI3k2ePUQm_q3UhRrRATC1bFBJcVBGbVUnDu0E-Ly44oyGawAjQ1aquRmkC_6Y9cL6iE/s1600/g1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. Randomly Pick File Name</td></tr>
</tbody></table><br />
(7) Now we will set a breakpoint at <u><b>0x3C1B3E</b></u>. (as shown in Figure 4) This is right before the zwLoadDriver is called to cause the harm to the system.<br />
<br />
<u><b>*** Now go to c:\Windows\System32\Drivers again and copy afd.sys out as afd_v2.sys. Up to now, our job of retrieving files is done. We can terminate the IMM debugger.</b></u><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioj2p94Q4X28OmLOEpRjxw3_wVLYRQ53uD_OgLfN1F47UseW6NLUvrTxmwVJbsPTB0rDKWYGq4n5DK7MX5vMNxV1Aik9jTYBW8vIJPQ5TVKOGok-78vboa5MsG3cQQMnLci9Nu2xEFlG8/s1600/g2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioj2p94Q4X28OmLOEpRjxw3_wVLYRQ53uD_OgLfN1F47UseW6NLUvrTxmwVJbsPTB0rDKWYGq4n5DK7MX5vMNxV1Aik9jTYBW8vIJPQ5TVKOGok-78vboa5MsG3cQQMnLci9Nu2xEFlG8/s1600/g2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Take out Infected Driver</td></tr>
</tbody></table><br />
<u><b> 3. Comparison of the Clean and Infected File</b></u><br />
Figure 5 shows the comparison of the clean and infected driver file using WinDiff. Let's take a look. On the left side of the image, you might notice two color bars, one corresponding to afd_v1.sys and the other corresponding to afd_v2.sys. The first fact you might notice is that afd_v2.sys is a bit larger.<br />
<br />
The first difference between the two files is line 1 (this is because the number of bytes and total blocks of the file has to be changed when Max++ injects additional logic), <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuXspiXTgOTU1RCRzljHHYWhazNWMorv-2UMq8V3l4yjw5Z5qGjNXgZUpA2RgheHfKMFXcmPyTkjE7DZFQT1D9_XczM4EHZ6EPyazDjmOm6-rPMuBQHcyX-MY6irdWsSOBd5ONbVtwvN4/s1600/g3.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuXspiXTgOTU1RCRzljHHYWhazNWMorv-2UMq8V3l4yjw5Z5qGjNXgZUpA2RgheHfKMFXcmPyTkjE7DZFQT1D9_XczM4EHZ6EPyazDjmOm6-rPMuBQHcyX-MY6irdWsSOBd5ONbVtwvN4/s1600/g3.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5: WinDiff of Clean and Infected Driver</td></tr>
</tbody></table>The second difference is the part (note region 2) from line 2 to line 28. Max++ injects (actually inserts) a lot of information. The red bar corresponds to the original content and the yellow bar corresponds to the new and inserted code. If you take a look at the highlighted region 4 (on the right of Figure 5) you might find a lot of interesting information:<br />
(1) There is a HTTP request for /install/setup.php<br />
(2) There is a string "C2CAD972#4079..." - this is the name of the hidden disk drive<br />
<br />
The rest of the two files is interesting. If you notice the rest of the two bars, the contents are exactly the same (note the highlighted region #2 on the left). This shows that Max++ did a good job at retaining the original logic of afd.sys. What it does is to insert the additional logic at the beginning and properly rewires the control flow so that after its malicoius actions are performed, the driver will perform its original functionality.<br />
<br />
In Figure 7, we display the disassembly of afd_v2.sys. You can see that it is performing some actions related to HTTP request and hidden disk drive. Notice that if you try to load afd_v2.sys using the Immunity Debugger directly, the IMM would simply crash. You need to actually debug IMM and overwrite some of its machine instructions to make it work when memory segmentation fault occurs.<br />
<br />
In fact, since we are about to get to kernel debugging (for drivers), IMM is not quite appropriate for such cases. In the next tutorial, we will show you how to use WinDbg to perform the analysis. <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhybvetR4fJVav3DeFf4xzpPiBMbDcbuJp7QMFS6fvqq849bpgTDRyljsVdOXNmkf1Kz6O5cqjvR3rkDfvVJtjb5S8jPCulwAvE4jAjHVELphoGJiPXDDR2x2w7-j7vjvVprQzB2IPqjFM/s1600/g6.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhybvetR4fJVav3DeFf4xzpPiBMbDcbuJp7QMFS6fvqq849bpgTDRyljsVdOXNmkf1Kz6O5cqjvR3rkDfvVJtjb5S8jPCulwAvE4jAjHVELphoGJiPXDDR2x2w7-j7vjvVprQzB2IPqjFM/s1600/g6.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 7. Disassembly of afd_v2.sys</td></tr>
</tbody></table><br />
<br />
<u><b>Challenge of the Day: </b></u><br />
(1) what is the size of the injected code?<br />
(2) Can you identify where does starts and where it ends inside Max++, right before it is written to the drier file?Unknownnoreply@blogger.com21tag:blogger.com,1999:blog-8770073098084592029.post-78877251124284847832012-02-25T08:33:00.000-08:002012-02-25T08:33:11.951-08:00Malware Analysis Tutorial 18: Infecting Driver Files (Part II: Simple Infection)<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgw1FiLxj-rrbgAPTDNtbyJr88fu8J2nykhxzbkW2epDwpf5Sg9CZD8yrwXfmS3uXEns7WqFq9CaztuTtZTeU9Y05NdhsCxJH8w1BINgRZH69tnWEgUfCjdQjtcZmXXXLJvhqQMw7ytl5w/s1600/e1.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"> </a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi76tbyElopI6Zufq9_Pn6mGNFu5pdUcJTS8Wg6hdkM1MqvIi4IdPEO0MBfQnBNtbMc_JM__M1ksCmNt7aNshakaq7sQui8hbY3S7B2JgRClLKAo-f3Ty997kjGiHo8-JIJIBxQeOHPxdM/s1600/e1.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><b>Learning Goals</b>:<br />
<ol><li>Understand the frequently used tricks by malware to infect driver files</li>
<li>Understand the role of registry in Windows operating systems</li>
<li>Practice analyzing function calls </li>
<li>Practice reverse engineering sophisticated data structures in memory </li>
</ol><b>Applicable to:</b><br />
<ol><li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security</li>
</ol><u><b>1. Introduction</b></u><br />
This tutorial continues the analysis of <a href="http://fumalwareanalysis.blogspot.com/2012/02/malware-analysis-tutorial-17-infecting.html">Tutorial 17</a>. As shown in <a href="http://fumalwareanalysis.blogspot.com/2012/02/malware-analysis-tutorial-17-infecting.html">Tutorial 17</a>, Max++ randomly picks up a system module which satisfies two criteria: (1) has export table and (2) file size > 0x4c10. This tutorial shows how Max++ infects the randomly picked driver and run it.<br />
<br />
We will analyze the code from <u><b>0x3C1E73 </b></u>in this tutorial. <br />
<br />
<br />
<u><b>2. Lab Configuration</b></u><br />
(0) Start WinXP image in <u><b>DEBUGGED </b></u>mode. Now in your host system, start a windows command window and CD to "<u><b>c:\Program Files\Debugging Tools for Windows (x86)</b></u>" (where WinDBG is installed). Type "<u><b>windbg -b -k com:pipe,port=\\.\pipe\com_12</b></u>" (check the com port number in your VBox instance set up). When WinDbg initiates, types "g" (go) twice to let it continue.<br />
<br />
(1) Now launch IMM in the WinXP instance, clear all breakpoints and hardware breakpoints in IMM (see <u><b>View->Breakpoints</b></u> and <u><b>View->Hardware Breakpoints</b></u>).<br />
<br />
(2) Go to <u><b>0x4012DC </b></u>and set a hardware breakpoint there. (why not software bp? Because that region will be self-extracted and overwritten and the software BP will be lost). Pay special attention that once you go to 0x4012DC, directly right click on the line to set hardware BP (currently it's gibberish code).<br />
<br />
(3) Press<u><b>F9</b></u> several times run to <u><b>0x4012DC</b></u>. You will encounter several breakpoints before 0x4012DC. If you pay attention, they are actually caused by the int 2d tricks (explained in <a href="http://www.blogger.com/cd%20%22c:/Program%20Files/Debugging%20Tools%20for%20Windows%20%28x86%29%22">Tutorial 3</a> and <a href="http://fumalwareanalysis.blogspot.com/2011/10/malware-analysis-tutorial-4-int2dh-anti.html">4</a>, and <a href="http://fumalwareanalysis.blogspot.com/2011/10/malware-analysis-tutorial-5-int2d-anti.html">5</a>). Simply ignore them and continue (using F9) until you hit <u><b>0x4012DC</b></u>.<br />
<br />
Figure 1 shows the code that you should be able to see. As you can see, this is right before the call of RtlAddVectoredException, where hardware BP is set to break the LdrLoadDll call (see <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-11-starling.html">Tutorial 11</a> for details).<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwY824Lshgaeu8tuf06xKBmXnOPpS45_aLSiyOO45sA9pUkglF0nkUNMcKdeRPsWKWehn-aEkpgnh_QlWjxN24f9iwlRq3j49BXfnl1EalZjMddZCgC7CrlmOpeIW3gUaEWXq-lxL5ULk/s1600/c1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwY824Lshgaeu8tuf06xKBmXnOPpS45_aLSiyOO45sA9pUkglF0nkUNMcKdeRPsWKWehn-aEkpgnh_QlWjxN24f9iwlRq3j49BXfnl1EalZjMddZCgC7CrlmOpeIW3gUaEWXq-lxL5ULk/s1600/c1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1: code at 0x4012DC</td></tr>
</tbody></table>(4) Now scroll down about 2 pages and set a <u><b>SOFTWARE BREAKPOINT</b></u> at <u><b>0x401417</b></u>. This is right after the call of LdrLoadDll("lz32.dll"), where Max++ finishes the loading of lz32.dll. Then hit <u><b>SHIFT+F9 </b></u>several times until you reach <u><b>0x401417</b></u> (you will hit 0x7C90D500 twice, this is somwhere inside ntdll.zwMapViewSection which is being called by LdrLoadDll). <br />
<br />
<br />
 <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdtJaTR3WJ33l5wLbd_tnt7knNdgNf2mnPTZkY4JnUjgqmsT5MmCcncck40DPpvSxsTDU1FqKSmI3pKeZpha2zb9nEzPe6EVmFatNSs-b5G6Jz3wS0GslZmw4vscwFZONefJRcfuDAtGc/s1600/c2.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdtJaTR3WJ33l5wLbd_tnt7knNdgNf2mnPTZkY4JnUjgqmsT5MmCcncck40DPpvSxsTDU1FqKSmI3pKeZpha2zb9nEzPe6EVmFatNSs-b5G6Jz3wS0GslZmw4vscwFZONefJRcfuDAtGc/s1600/c2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2: code at 0x401407</td></tr>
</tbody></table> <br />
(6) Now we will set a breakpoint at <u><b>0x3C1E73 </b></u>. Goto <u><b>0x3C1E73 </b></u>and set a <u><b>SOFTWARE </b><b>BREAKPOINT</b><b>. SHIFT+F9</b></u> there. Press <u><b>SHIFT+F9 </b></u>to run to <u><b>0x3C1E73 </b></u>. (You may see a warning that this is out range of the code segment, simply ignore the warning).<br />
<br />
(Figure 3 shows the code that you should be able to see at <u><b>0x3C1E73 </b></u>. This is right after the loop for randomly picking up a system module to infect.<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8UPo5cKlFVJz70bU9_53D0ZQFq0lYF1pPH8y4ldZnqGUxYMEqmDTQje02Auwp3JN9xKp3UcHkzX6GGMdRWO7pOgBTPRGsBk7HTGYXIpXyFpvkkjSKiSC2uiNFklYxgbZQElrxGCZ9EAg/s1600/e1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8UPo5cKlFVJz70bU9_53D0ZQFq0lYF1pPH8y4ldZnqGUxYMEqmDTQje02Auwp3JN9xKp3UcHkzX6GGMdRWO7pOgBTPRGsBk7HTGYXIpXyFpvkkjSKiSC2uiNFklYxgbZQElrxGCZ9EAg/s1600/e1.JPG" yda="true" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. Code Starts at 0x3C1E73 (Double Check of System Functions)</td></tr>
</tbody></table><br />
<u><b>Section 3. Warm-Up before Infection</b></u><br />
As shown in Figure 3, right after the random pick loop (at <u><b>0x3C1E73</b></u>), EDI points to the name of the system module to infect (in our case, it's "<u><b>mouclass</b><b>.sys</b></u>" - the name will be different every time you run Max++). Starting from <u><b>0x3C1E73 </b></u>to <u><b>0x3C1F83</b></u>, Max++ performs some warm-up activities to check of all important system functions are working right. Details are shown in Figure 3. It checks the following functions:<br />
<br />
(1) zwCreateSection - this function allows to create a section (a shared memory object between processes), it can also be used to map between a file and a memory region.<br />
(2) zwMapViewOfSection - map a section object into the address space of a process<br />
(3) zwReadFile - read file contents into a memory region.<br />
<br />
If all checks are good, it will continue to the infection.<br />
<br />
<b>Challenge 1. </b>As shown in Figure 3, analyze the <u><b>sprintf </b></u>call at <u><b>0x3C1E84</b></u>. What are its parameters? What's returned?<br />
<b>Challenge 2. </b>As shown in Figure 3, analyze the <u><b>zwCreateSection </b></u>call at <u><b>0x3C1EEE</b></u>. What are its parameters? What's returned?<br />
<b>Challenge 3. </b>As shown in Figure 3, analyze the <u><b>zwMapViewOfSection </b></u>call at <u><b>0x3C1F20</b></u>. What are its parameters? What's returned? <br />
<b>Challenge 4. </b>As shown in Figure 3, analyze the <u><b>zwReadFile </b></u>call at <u><b>0x3C1F73</b></u>. What are its parameters? What's returned?<br />
<br />
<br />
<u><b>Section 4. Mods on Registry</b></u><br />
At 0x3C1FAD, Max++ calls function 0x3C196A. This is the function that performs the real malicious infection operation.<br />
<br />
The first series of actions Max++ performs is to create a registry entry and set its values, as shown in Figure 4. Assume that the file to infect is mouclass.sys, Max++ creates a registry key named "<b>\registry\MACHINE\SYSTEM\CurrentControlSet\Services\.mouclass</b>". Then it creates several value pair, such as the "start" and the "ImagePath". Note that in the "CurrentControlSet\Services" there is originally a registry named "mouclass" (just without the .dot). The original version of the registry and the new version are displayed in Figure 5(a) and Figure 5(b) respectively, using <u><b>regedit</b></u>.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirIs0QK1g5Bkt6-5EpLoj8vztGNIGZr2c_ULjUWGhBi-jTO4h1zZmMfpGi2Z7STrB2OjNAE7JolS_a1bF7y_16SkDhSa6Ktd6529QGwBmVz_cezzIsplJ7_sky1v1eVCvCK8tiAwugHk8/s1600/e2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirIs0QK1g5Bkt6-5EpLoj8vztGNIGZr2c_ULjUWGhBi-jTO4h1zZmMfpGi2Z7STrB2OjNAE7JolS_a1bF7y_16SkDhSa6Ktd6529QGwBmVz_cezzIsplJ7_sky1v1eVCvCK8tiAwugHk8/s1600/e2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Registry Keys</td></tr>
</tbody></table><br />
<br />
Look at Figure 5 and compare the values for "<b>Start</b>" and "<b>ImagePath</b>". There are some interesting observations: In the old Mouclass entry, the "Start" type is "0" (meaning load at boot time) and the new ".Mouclass" start type is "3" (meaning load on demand). The ImagePath of the old Mouclass entry is the absolute path to the driver, while the <u><b>ImagePath </b></u>of the new Mouclass is "<u><b>\*</b></u>". The meaning of these parameters can be found in MSDN documentation [<a href="http://support.microsoft.com/kb/103000">1</a>]. As far as we know, the "\*" is not a legal value for ImagePath. There must be some special handling for this once Max++ infects the file/disk driver. The meaning of "\*" is currently an open question to us.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2r8XJsZjNsWNajGacWIZS8ieBHttTbYT72Blgra88cN1dm9A5EZ-LhJJsG49Wo83yt2nfGkEOtDMA0r4zcksy8V6McrUPDZ9DUNZgCuZi5lyV4n6KP8LgNfAWiAf6YanwTcFaRYj_qEE/s1600/e1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2r8XJsZjNsWNajGacWIZS8ieBHttTbYT72Blgra88cN1dm9A5EZ-LhJJsG49Wo83yt2nfGkEOtDMA0r4zcksy8V6McrUPDZ9DUNZgCuZi5lyV4n6KP8LgNfAWiAf6YanwTcFaRYj_qEE/s1600/e1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5. Registry "mouclass" (old) and ".mouclass" (new)</td></tr>
</tbody></table><br />
<u><b>Section 5. Disable File Protection Service (Function 0x003C15AB)</b></u><br />
Next, Max++ disables a file protection service called <u><b>sfc_os.dll</b></u>. Here sfc stands for "<u><b>Microsoft Windows File Protection Service</b></u>", it monitors the file operations on system files (including drivers). Max++ needs to disable sfc_os.dll to overwrite the system driver file for infection. To do this, Max++ calls function <u><b>0x003C15AB </b></u>at <u><b>0x003C1A16 </b></u>(shown at the bottom of Figure 3). <u><b>Function 0x003C15AB</b></u> kills the kernel process/thread related to sfc_os.dll one by one to achieve the goal. We now delve into the details of Function <u><b>0x003C15AB</b></u>.<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi76tbyElopI6Zufq9_Pn6mGNFu5pdUcJTS8Wg6hdkM1MqvIi4IdPEO0MBfQnBNtbMc_JM__M1ksCmNt7aNshakaq7sQui8hbY3S7B2JgRClLKAo-f3Ty997kjGiHo8-JIJIBxQeOHPxdM/s1600/e1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi76tbyElopI6Zufq9_Pn6mGNFu5pdUcJTS8Wg6hdkM1MqvIi4IdPEO0MBfQnBNtbMc_JM__M1ksCmNt7aNshakaq7sQui8hbY3S7B2JgRClLKAo-f3Ty997kjGiHo8-JIJIBxQeOHPxdM/s1600/e1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6. Search for "Winlogon.exe"</td></tr>
</tbody></table>Shown in Figure 6 is our old friend <u><b>zwQuerySystemInformation</b></u>. This times, Max++ uses it to retrieve the information of live processes in the system (last time in Tutorial 16 and 17, it retrieves system modules/drivers). It then enumerates the information of each process and compares its name with "Winlogin.exe" until it finds the <u><b>Winlogon.exe</b></u> process.<br />
<br />
<u><b>Challenge 1.</b></u> How do you tell that the function call at 0x3C1612 (<u><b>RtlEqualUnicodeString</b></u>) is to compare with Winlogin.exe? Show the parameters of the RtlEqualUnicodeString call. (hint: use WinDbg to display UNICODE_STRING).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYwYzpfYIcEf4Yyf4mgzz4dXgwsC58aZXrbbHZFkXTI3kDZ3Bxkefeovlg68vVRnOD-SWTygX74kskgUNbS238MCimigSBAebGO52XA_62YmOo_duaRVsY4Xieszrs9mUFi-kY629LPuQ/s1600/e3.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYwYzpfYIcEf4Yyf4mgzz4dXgwsC58aZXrbbHZFkXTI3kDZ3Bxkefeovlg68vVRnOD-SWTygX74kskgUNbS238MCimigSBAebGO52XA_62YmOo_duaRVsY4Xieszrs9mUFi-kY629LPuQ/s1600/e3.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 7. Query Debugging Information</td></tr>
</tbody></table>Max++ then does a query on the debugging information of Winlogon.exe process (as shown in Figure 7). We leave the analysis details to you and you can refer to [<a href="http://evilcodecave.wordpress.com/2009/04/11/rtlqueryprocessdebuginformation-as-anti-dbg-trick/">2</a>] for details of <u><b>RtlqueryProcessDebugInfo</b></u>. Potentially, Max++ could take advantage of the information to tell if the system is being debugged or not, but it didn't perform any detection/anti-debugging actions here and directly jumps to function <u><b>0x003C14D7 </b></u>(at <u><b>0x003c1651</b></u>, see Figure 7). Function <u><b>0x003C14D7 </b></u>disables the file protection service.For now, we just keep in mind that the <u><b>_DEBUG_BUFFER</b></u> is located at <u><b>0x00900000</b></u>, which might be useful later. <u><b>Note that the _DEBUG_BUFFER at 0x00900000 stores the information of Winlogon.exe!</b></u><br />
<br />
<u><b>Challenge 2.</b></u> Trace to the RtlQueryProcessDebugInfo, and show the contents of the _DEBUG_MODULE_INFO.<br />
<br />
<u><b>5.1 Kill the File Protection Service</b></u><br />
We now trace into function <u><b>0x003C14D7</b></u>. Figure 8 shows its function body. As usual, the first thing you should look at is the input parameter of the function. By examining the first copy of instructions you would soon notice that the function is reading from two registers:<br />
(1) EAX - it contains value 0x00900000 (note: this is the <u><b>_DEBUG_BUFFER</b></u> for winlogon.exe)<br />
(2) ECX - it contains the <u><b>_SYSTEM_MODULE_INFORMION</b></u> of winlogon.exe.<br />
<br />
We leave the details of inferring the semantics of EAX, ECX parameters to you:<br />
<u><b>Challenge 2. </b></u>How do you infer the data type of the EAX, ECX (as input parameters) of function 0x003C14D7?<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgM3jZMV4oISzAe6JfyvXybUurXKevPGfxqPWkZxSoVZ9_ZLBuTRJhKNBIaQadPjXWnaC6q5BlLqqK2PxFauTHryfO0-5eSfgHh9HHPt6moRx0zDgHXIchnycf10jgZflKLkKCCFUVNEEU/s1600/e3.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgM3jZMV4oISzAe6JfyvXybUurXKevPGfxqPWkZxSoVZ9_ZLBuTRJhKNBIaQadPjXWnaC6q5BlLqqK2PxFauTHryfO0-5eSfgHh9HHPt6moRx0zDgHXIchnycf10jgZflKLkKCCFUVNEEU/s1600/e3.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 8. Function body (Part I) of Function 0x3C14D7</td></tr>
</tbody></table><br />
The first part of the function is a loop (from 0x3C14EC to 0x3C150E, see Figure 8). Max++ reads the _DEBUG_MODULE_INFORMATION one by one, and compare its name with "sfc_os.dll" (see the function call at <u><b>0x3C14FB, and the stack contents in Figure 8</b></u>). It jumps out of the loop once it finds the _DEBUG_MODULE_INFORMATION for "sfc_os.dll".<br />
<br />
The tricky part of the analysis of this part of the code is the lack of documentation for kernel data structures such as _DEBUG_BUFFER and _DEBUG_MODULE_INFORMATION.<br />
<br />
<u><b>Challenge 3.</b></u> ***** Observe the instruction at 0x003C14E3, how would you infer that EDI now contains the number of modules, assuming that EAX has the PVOID ModuleInformation of _DEBUG_BUFFER? To simply search "typedef _DEBUG_BUFFER" gives you no more information than a PVOID type. You have to read the source code of <u><b>RtlQueryProcessDebugInformation </b></u>(at [<a href="http://doxygen.reactos.org/d8/dd5/ndk_2rtlfuncs_8h_a18ff51253f8e8f51e2018bcf6d1ca533.html">3</a>]) and <u><b>LdrQueryProcessModuleInformationEx </b></u>(at [<a href="http://doxygen.reactos.org/d7/d55/ldrapi_8c_a2925d74ddee77bdef1e1abab8e1ae8d6.html#a2925d74ddee77bdef1e1abab8e1ae8d6">4</a>]) to figure it out.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4XOzbGJlCGc6Po6YhQYvI5gRW64hb0NkJud7oVq36A9OQch_6hJ45xez7MoXq6WAfNP4kUgy7oAdqXYCviqY1c7-Azz0jCQkloMLe_nEEBoZsHyII1c6c0M5-rOZeb3OUxmRwuo5tbus/s1600/e4.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4XOzbGJlCGc6Po6YhQYvI5gRW64hb0NkJud7oVq36A9OQch_6hJ45xez7MoXq6WAfNP4kUgy7oAdqXYCviqY1c7-Azz0jCQkloMLe_nEEBoZsHyII1c6c0M5-rOZeb3OUxmRwuo5tbus/s1600/e4.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 9. Kill Threads Related to sfc_os.dll</td></tr>
</tbody></table><br />
Now, since Max++ identifies the DEBUG_MODULE_INFORMATION of sfc_os.dll, it is able to know the ImageBase address of sfc_os.dll. The next immediate action is a loop which <u><b>searches all threads of winlogon.exe and kill those that are related to sfc_os.dll. </b></u>The details are shown in <u><b>Figure 9</b></u>.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;">The basic control flow is:</span></div><div style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"> for each thread in winlogon.exe</span></div><div style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"> open thread</span></div><div style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"> get the base address of the thread</span></div><div style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"> if <u><b>base address of the thread</b></u> - <u><b>imageAddress of sfc_os</b></u> <= <u><b>imageSize of sfc_os</b></u></span></div><div style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"> suspend the thread</span></div><br />
In summary: if the base address of a thread is inside the image range of sfc_os, it is killed.<br />
<br />
We now list some challenges to help you understand the program logic in Figure 9.<br />
<u><b>Challenge 4.</b></u> Observe the instruction at <u><b>0x3C1519 </b></u>of <u><b>Figure 9</b></u>: <b>MOV EAX, [ESI+8]</b>. How would you infer that EAX will then contain the base of sfc_os.dll?<br />
<br />
<u><b>Challenge 5.</b></u> Observe the instruction at <u><b>0x3C1562 </b></u>of <u><b>Figure 9</b></u>: <b>MOV EAX, [EBP-8]</b>. How would you infer that EAX will then contain the base address of the thread?<br />
<br />
<u><b>Up to now, the sfc_os.dll module should be completely disabled and the OS is not performing security check on the driver files located on disk.</b></u><br />
<br />
<u><b>Section 6. The Infection</b></u><br />
We now discuss the infection. This part of the code starts from <u><b>0x3C1A1B </b></u>(right after it returns from the call of <u><b>0x3C15AB </b></u>- to disable sfc_os.dll).<br />
<br />
Figure 10 shows the first action taken by Max++. It makes sure that the randomly picked driver (e.g., mouclass.sys - note the name is changing everytime you run it) is not compressed. This is achieved by the call of zwFsControlFile.<br />
<br />
<u><b>Challenge 6</b></u>. Observe the instruction at <u><b>0x003C1A63 </b></u>(call of <u><b>zwFsControlFile</b></u>). Analyze the semantics of its function parameters.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkTkQFL9hh-99slQU3h8uV_hrWeIjapyjdRH2YyNcITr8FUzc9fxdxy0eBWR24PlcfSXnWhZ6HPhi3TPVrCvKlN-05kkkW0hV_4sjPUujbrObej1VSYOqvmkac_y4u7KhXGRrUjeNZu1M/s1600/e5.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkTkQFL9hh-99slQU3h8uV_hrWeIjapyjdRH2YyNcITr8FUzc9fxdxy0eBWR24PlcfSXnWhZ6HPhi3TPVrCvKlN-05kkkW0hV_4sjPUujbrObej1VSYOqvmkac_y4u7KhXGRrUjeNZu1M/s1600/e5.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 10. Change File Property</td></tr>
</tbody></table><br />
Figure 11 displays the next actions of Max++: It creates a <u><b>section object</b></u> and then a <u><b>view</b></u>. Section object is used by Windows to share memory between processes. It can also be used to map a file to memory. Max++ uses the second case: it creates a section object that maps the contents of the driver file to infect (let it be mouclass.sys) to memory and then creates a view of the section object. You need to analyze the highlighted function calls to get more information, e.g., what is the starting address of the memory region of the file mapping and what is the size?<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpf0x5-pqVuhlBLvYAsVKq9HwZdfwpm7lhjzeD7cZCRINAyPbWiDBHZ9aLxt8eHxgyaDIbsQRDUaYYhba66y6ouPLI728aL8V0Qs8BdfQlB56qF84u85nXhKtK7RhJyaNiu_DsLfZafZM/s1600/e6.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpf0x5-pqVuhlBLvYAsVKq9HwZdfwpm7lhjzeD7cZCRINAyPbWiDBHZ9aLxt8eHxgyaDIbsQRDUaYYhba66y6ouPLI728aL8V0Qs8BdfQlB56qF84u85nXhKtK7RhJyaNiu_DsLfZafZM/s1600/e6.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 11. Create Memory Mapping of File</td></tr>
</tbody></table><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3qP1I94RlO0hLohT4EIxppZECWBYmy9yF6j-Ffmp5evzCWLb5YCI8BadqG-T4l6ARsOf_ySK9aFidzokGaPtKcu9V4W5hJHBojgcJBpBBi8gTtxo5EjsOQiUdlpTzvHmReWZW4B7rt9E/s1600/e8.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3qP1I94RlO0hLohT4EIxppZECWBYmy9yF6j-Ffmp5evzCWLb5YCI8BadqG-T4l6ARsOf_ySK9aFidzokGaPtKcu9V4W5hJHBojgcJBpBBi8gTtxo5EjsOQiUdlpTzvHmReWZW4B7rt9E/s1600/e8.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 12. New Section Object</td></tr>
</tbody></table><br />
<br />
<u><b>Challenge 7: </b></u>Analyze the highlighted functions in Figure 11 and answer the following questions: (1) where is the<u><b> mapped memory region</b></u> of mouclass.sys (the file to infect), i.e., where it starts and where it ends? (2) how do you tell that the call zwCreateSection is not to create a shared memory region between two processes, but to map a file? (hint: you could click View->View Memory, and you will notice the starting address of the new section object created, see <u><b>Figure 12</b></u>)<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUB447QxpNM46abc_EnC7yw-OJOil47PuSJUHUzsChoDo6zq_g-CgAKcoweAY_aOUHLdUPMdYDz2V3DWgX0cD3dm6n73OEkSAqZ3N8l1dA7qzRaLALC9cwgJuCFK-9hDLD4V0z5kdlN28/s1600/e7.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUB447QxpNM46abc_EnC7yw-OJOil47PuSJUHUzsChoDo6zq_g-CgAKcoweAY_aOUHLdUPMdYDz2V3DWgX0cD3dm6n73OEkSAqZ3N8l1dA7qzRaLALC9cwgJuCFK-9hDLD4V0z5kdlN28/s1600/e7.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 13. Decoding and Copy to Mapped File</td></tr>
</tbody></table><br />
Next Max++ establishes a decoding table (see Figure 13), and copies some contents from its own stack (0x12XXXX range) to 0x00380000 (the mapped region for file mouclass.sys). Notice that the value 0x00380000 could vary in a different section. After a number of decoding rounds, we finally have the contents starting from 0x00380000 (see Figure 13, the memory dump section). You will notice the <u><b>0x4D5A</b></u>, which is the magic word for "DOS header".<br />
<br />
<u><b>Conclusion: Max++ performs a very simple infection approach. It just brutally overwrites the beginning of the driver file to infect and does not do any "weaving" of the LONG JUMP instructions to maintain the original logic of the infected file. Once the infected file is overwritten, it loses its original functions! </b></u><br />
<br />
<br />
<br />
The final action Max++ takes is to set up the checksum of the PE header and then writes the contents of the memory region to the file (by calling <b>zwFlushVirtualMemory</b>, see Figure 14).<br />
<br />
<u><b>Challenge 8. </b></u>Analyze the highlighted area 2 of Figure 14, explain why the instruction is setting the PE checksum?<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQxAJ4XD3gbe5N-s4wKUIsWJ-7R7zmn9t7fw1pk93gJVVYtqTnJYzIElfBL5ONk3tC7auksXRWyqPjbEmhT54lPDujRHEf-5oBDKE1JKLePdnmdfeFlUjR6lmawq6UdM51IOWrAmyxLP8/s1600/e9.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQxAJ4XD3gbe5N-s4wKUIsWJ-7R7zmn9t7fw1pk93gJVVYtqTnJYzIElfBL5ONk3tC7auksXRWyqPjbEmhT54lPDujRHEf-5oBDKE1JKLePdnmdfeFlUjR6lmawq6UdM51IOWrAmyxLP8/s1600/e9.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 14. Set up Checksum and Write Contents Back</td></tr>
</tbody></table><br />
<br />
As shown in Figure 14 (highlighted area 4), Max++ immediately call zwLoadDriver() to load the newly updated file. If we want to delve into the logic of the new driver file, we would not be able to, because the driver will run in privileged mode while IMM is a ring3 debugger. In this case, we need kernel debugger WinDbg. We will move on to the analysis of the infected driver file in the next tutorial.<br />
<br />
<u><b>References</b></u><br />
1. Microsoft, "<b>CurrentControlSet\Services subentry keys</b>", Availabe at <a href="http://support.microsoft.com/kb/103000">http://support.microsoft.com/kb/103000</a><br />
2.Unknown, "RtlQueryProcessDebugInformation as Anti-Dbg Trick", Available at <a href="http://evilcodecave.wordpress.com/2009/04/11/rtlqueryprocessdebuginformation-as-anti-dbg-trick/">http://evilcodecave.wordpress.com/2009/04/11/rtlqueryprocessdebuginformation-as-anti-dbg-trick/</a><br />
3. Unofficial source code of RtlQueryProcessDebugInformation (<a href="http://doxygen.reactos.org/d8/dd5/ndk_2rtlfuncs_8h_a18ff51253f8e8f51e2018bcf6d1ca533.html">http://doxygen.reactos.org/d8/dd5/ndk_2rtlfuncs_8h_a18ff51253f8e8f51e2018bcf6d1ca533.html</a>) <br />
4. Unofficial source code of LdrQueryProcessModuleInformationEx (<a href="http://doxygen.reactos.org/d7/d55/ldrapi_8c_a2925d74ddee77bdef1e1abab8e1ae8d6.html#a2925d74ddee77bdef1e1abab8e1ae8d6">http://doxygen.reactos.org/d7/d55/ldrapi_8c_a2925d74ddee77bdef1e1abab8e1ae8d6.html#a2925d74ddee77bdef1e1abab8e1ae8d6</a>)<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><br />
</td></tr>
<tr><td class="tr-caption" style="text-align: center;"><br />
</td></tr>
</tbody></table>Unknownnoreply@blogger.com23tag:blogger.com,1999:blog-8770073098084592029.post-1022189865603421422012-02-19T09:13:00.000-08:002012-02-19T09:13:20.159-08:00Malware Analysis Tutorial 17: Infecting Driver Files (Part I: Randomly Select a System Module)<b>Learning Goals</b>:<br />
<ol><li>Understand the frequently used tricks by malware to infect driver files</li>
<li>Understand the role of registry in Windows operating systems</li>
<li>Practice analyzing function cals </li>
<li>Practice reverse engineering sophisticated data structures in memory </li>
</ol><b>Applicable to:</b><br />
<ol><li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security</li>
</ol><u><b>1. Introduction</b></u><br />
This tutorial shows some frequently used tricks by malware to infect system drivers. We show how Max++ examines the list of active system modules (drivers) in the system and <u><b>pick up randomly the candidates for infection. </b></u>In this tutorial, we will practice the use of WinDbg for examining sophisticated system data structures and learn some important system calls such zwQuerySystemInformation.<br />
<br />
We will analyze the code from <u><b>0x3C2408 </b></u>in this tutorial. This is to continue the analysis in <a href="http://fumalwareanalysis.blogspot.com/2012/02/malware-analysis-tutorial-16-return.html">Tutorial 16</a>, where we showed that Max++ injects a thread into another running process and the thread will remove the binary executable Max++Loader2010.exe from the disk once the Max++ process terminates. <br />
<br />
<br />
<u><b>2. Lab Configuration</b></u><br />
(0) Start WinXP image in <u><b>DEBUGGED </b></u>mode. Now in your host system, start a windows command window and CD to "<u><b>c:\Program Files\Debugging Tools for Windows (x86)</b></u>" (where WinDBG is installed). Type "<u><b>windbg -b -k com:pipe,port=\\.\pipe\com_12</b></u>" (check the com port number in your VBox instance set up). When WinDbg initiates, types "g" (go) twice to let it continue.<br />
<br />
(1) Now launch IMM in the WinXP instance, clear all breakpoints and hardware breakpoints in IMM (see <u><b>View->Breakpoints</b></u> and <u><b>View->Hardware Breakpoints</b></u>).<br />
<br />
(2) Go to <u><b>0x4012DC </b></u>and set a hardware breakpoint there. (why not software bp? Because that region will be self-extracted and overwritten and the software BP will be lost). Pay special attention that once you go to 0x4012DC, directly right click on the line to set hardware BP (currently it's gibberish code).<br />
<br />
(3) Press<u><b>F9</b></u> several times run to <u><b>0x4012DC</b></u>. You will encounter several breakpoints before 0x4012DC. If you pay attention, they are actually caused by the int 2d tricks (explained in <a href="http://www.blogger.com/cd%20%22c:/Program%20Files/Debugging%20Tools%20for%20Windows%20%28x86%29%22">Tutorial 3</a> and <a href="http://fumalwareanalysis.blogspot.com/2011/10/malware-analysis-tutorial-4-int2dh-anti.html">4</a>, and <a href="http://fumalwareanalysis.blogspot.com/2011/10/malware-analysis-tutorial-5-int2d-anti.html">5</a>). Simply ignore them and continue (using F9) until you hit <u><b>0x4012DC</b></u>.<br />
<br />
Figure 1 shows the code that you should be able to see. As you can see, this is right before the call of RtlAddVectoredException, where hardware BP is set to break the LdrLoadDll call (see <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-11-starling.html">Tutorial 11</a> for details).<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwY824Lshgaeu8tuf06xKBmXnOPpS45_aLSiyOO45sA9pUkglF0nkUNMcKdeRPsWKWehn-aEkpgnh_QlWjxN24f9iwlRq3j49BXfnl1EalZjMddZCgC7CrlmOpeIW3gUaEWXq-lxL5ULk/s1600/c1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwY824Lshgaeu8tuf06xKBmXnOPpS45_aLSiyOO45sA9pUkglF0nkUNMcKdeRPsWKWehn-aEkpgnh_QlWjxN24f9iwlRq3j49BXfnl1EalZjMddZCgC7CrlmOpeIW3gUaEWXq-lxL5ULk/s1600/c1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1: code at 0x4012DC</td></tr>
</tbody></table>(4) Now scroll down about 2 pages and set a <u><b>SOFTWARE BREAKPOINT</b></u> at <u><b>0x401417</b></u>. This is right after the call of LdrLoadDll("lz32.dll"), where Max++ finishes the loading of lz32.dll. Then hit <u><b>SHIFT+F9 </b></u>several times until you reach <u><b>0x401417</b></u> (you will hit 0x7C90D500 twice, this is somwhere inside ntdll.zwMapViewSection which is being called by LdrLoadDll). <br />
<br />
<br />
 <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdtJaTR3WJ33l5wLbd_tnt7knNdgNf2mnPTZkY4JnUjgqmsT5MmCcncck40DPpvSxsTDU1FqKSmI3pKeZpha2zb9nEzPe6EVmFatNSs-b5G6Jz3wS0GslZmw4vscwFZONefJRcfuDAtGc/s1600/c2.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdtJaTR3WJ33l5wLbd_tnt7knNdgNf2mnPTZkY4JnUjgqmsT5MmCcncck40DPpvSxsTDU1FqKSmI3pKeZpha2zb9nEzPe6EVmFatNSs-b5G6Jz3wS0GslZmw4vscwFZONefJRcfuDAtGc/s1600/c2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2: code at 0x401407</td></tr>
</tbody></table> <br />
(6) Now we will set a breakpoint at <u><b>0x3C2408 </b></u>. Goto <u><b>0x3C2408</b></u> and set a <u><b>SOFTWARE </b><b>BREAKPOINT</b><b>. SHIFT+F9</b></u> there. Press <u><b>SHIFT+F9 </b></u>to run to <u><b>0x3C2408 </b></u>. (You may see a warning that this is out range of the code segment, simply ignore the warning).<br />
<br />
(Figure 3 shows the code that you should be able to see at <u><b>0x3C2408 </b></u>. The first instruction should be <u><b>TEST EAX, EAX.</b></u> The value of the EAX register at this moment should be 0x1, and the control flow will continue to 0x3C2410 (PUSH 10000). We will start our analysis from here.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg7JMsYgSkaFKrG3Jn_Le6_57TcIha2S1EaWrtKNYRp4iSDgplYA4Tdmv1RM8EDKHzx64ltYM3OwnHHiLJ5DGbqeYfjBGCLXya4_tEap1oFTZijd_xwOHkUBjPGdpTHK0GLoOoaFC7zYI/s1600/e1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg7JMsYgSkaFKrG3Jn_Le6_57TcIha2S1EaWrtKNYRp4iSDgplYA4Tdmv1RM8EDKHzx64ltYM3OwnHHiLJ5DGbqeYfjBGCLXya4_tEap1oFTZijd_xwOHkUBjPGdpTHK0GLoOoaFC7zYI/s1600/e1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3: Code Starting at 0x3C2408</td></tr>
</tbody></table><br />
<br />
<u><b>Section 3. Check Infection Status</b></u><br />
The first action Max++ takes is to examine if the system has already been affected. It checks the existence of a virtual volume named ""<u><b>\??\C2CAD972#4079#4fd3#A68D#AD34CC121074</b></u>". Notice that this is a very interesting name, if you look at the Mcirosoft UNC file name specification [<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx">1</a>], it's actually not quite a legal name. Usually UNC names with extended length should start with "\\?\" instead of two question marks inside it [as far as I know]. If the system is never infected before, the call <u><b>zwOpenFile </b></u>at <u><b>0x3C242D </b></u>should fail and return an error code. Only when Max++ successfully creates a virtual drive and overwrites the disk operation driver (so that the driver can handle \??\ prefix), the call will report success.<br />
<br />
It is interesting to delve more into the call zwOpenFile and look at its parameters. In the past, we have used IMM debugger to directly watch the parameters. When the data type of a parameter is complex, it's more convenient to use WinDbg. We will in the following show a sample use of WinDbg.<br />
<br />
The formal declaration of zwOpenFile can be easily found out by Google. The first three parameters of zwOpenFile are interesting to us: (1) OUT PHANDLE FileHandle, (2) ACCESS_MASK DesiredAccess, and (3) POBJECT_ATTRIBUTES <u><b>ObjectAttributes</b></u>, according to [<a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff567011%28v=vs.85%29.aspx">2</a>]. <br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8V3TXncQvt2pkbo1n2JRw9CG5SwunuVGNIsKmHB7CDQkr7j08CGiBhV7PvxcKS9604TsAvBeT6gWgQLw3XU3XFqUvDX1kWHHO6JhumWm4g81sWrtlK7b7d7r27z1wMax8SRYMs6N0lZY/s1600/e3.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8V3TXncQvt2pkbo1n2JRw9CG5SwunuVGNIsKmHB7CDQkr7j08CGiBhV7PvxcKS9604TsAvBeT6gWgQLw3XU3XFqUvDX1kWHHO6JhumWm4g81sWrtlK7b7d7r27z1wMax8SRYMs6N0lZY/s1600/e3.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Stack Contents of zwOpenFile Call</td></tr>
</tbody></table><br />
Now if we look at the contents of the stack when the call is made (as shown in Figure 4), we might notice that the value for the third parameter (ObjectAttributes) is <u><b>0x3D3150</b></u>. Notice that its data type is POBJECT_ATTRIBUTES where "P" stands for the pointer. Clearly, it means that starting at 0x3D3150, there is a data structure named OBJECT_ATTRIBUTES. It is possible to get the formal declaration of OBJECT_ATTRIBUTES structure and interpret the bits and bytes by yourself. But a simpler way is to use WinDbg to help with it.<br />
<br />
For this purpose, let's start the <u><b>WinDbg in the VBox Windows image</b><b>. File-> Attack Process -> Max++</b></u> (note: not the external one in the host) and then click and select to run <u><b>Noninvasively</b></u>. (as shown in Figure 6). <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGuWXP0dm_0jk2IwiGuMGTMQarXJpssSqeyvX0bvNH2qQhwMghn8IcLRcc5w4mNkvEnQSMjFliZHCnATsRfgxzv8H8gH5e5FkWvqC_cx47v7wqmiKyWdCtYPAZoSrMwPRI8LdvxxiP59E/s1600/d8.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGuWXP0dm_0jk2IwiGuMGTMQarXJpssSqeyvX0bvNH2qQhwMghn8IcLRcc5w4mNkvEnQSMjFliZHCnATsRfgxzv8H8gH5e5FkWvqC_cx47v7wqmiKyWdCtYPAZoSrMwPRI8LdvxxiP59E/s1600/d8.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6. Run WinDebug in Noninvasive Mode</td></tr>
</tbody></table>Simply type "<b>dt _OBJECT_ATTRIBUTES 0x3D3150 -r2</b>" in the WinDbg command window, we have the dump of the contents as shown below. Here "-r2" means to display 2 layers of details level (recursively). Shown in Figure 7 is the dump of the OBJECT_ATTRIBUTES. You can see that the file it tries to access is "<u><b>\??\C2CAD972#4079#4fd3#A68D#AD34CC121074".</b></u> The call will return an error code in EAX, which drives the execution flow to <u><b>0x3C243B </b></u>(see Figure 3) and then to <u><b>0x3C2461</b></u>.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfXDEJiQ-a8VtdkMPjtDQcuP3MiKEf8ZN4ctfQ6l5DPR6uo4MewZwpHFgnVwSCeN02p07scIExyWInRBxeqBhyphenhyphenfP43UOkKhSC99fXKPTzXz4HlMaXrb0TAEqwULnZXAfErjhVbGAUc2ic/s1600/e2.JPG" style="margin-left: 1em; margin-right: 1em;"></a></div><br />
<br />
<u><b>Section 4. Search for Modules to Infect (Function 0x3C1C2C)</b></u><br />
We now examine the logic of Function 0x3C1C2C (as shown in Figure 7). The first part of the function is to call 0x3D0BC0. This is a function frequently called by the Max++ code. We leave the analysis details to you.<br />
<br />
<br />
<u><b>Challenge 1. </b></u>Analyze the functionality of function 0x003D0BC0 (what are its input? and what are its output? Hint: it adjusts the position of ESP register according to some input and then puts the address of the next immediate instruction into EAX).<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGBZ7ZqsgsZQgKtqjJ8f9yEDtAIgBx2jRSiIw4i3gUqmisG25thGk8E6srGZJ8JrMhAM1G0DuFnPZ7rqS8tW8z_GeRk_Q_Q9N_c4w712RtGqxlYv8diM_sz1PeotYug2EnA-aSV1Kdn78/s1600/e1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGBZ7ZqsgsZQgKtqjJ8f9yEDtAIgBx2jRSiIw4i3gUqmisG25thGk8E6srGZJ8JrMhAM1G0DuFnPZ7rqS8tW8z_GeRk_Q_Q9N_c4w712RtGqxlYv8diM_sz1PeotYug2EnA-aSV1Kdn78/s1600/e1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 7. First part of Function 0x3C1C2C</td></tr>
</tbody></table><br />
<br />
The major bulk of the function is the a loop from <u><b>0x003C1C5B </b></u>to <u><b>0x003C1D04 </b></u>(shown in Figure 8). During the first iteration, the code calls zwQueryInformation to get the list of system modules (all running driver processes in the system) and find out the system module whose name is "<u><b>ndis.sys</b></u>". Note that <u><b>NDIS </b></u>stands for <u><b>Network Driver Interface Specification</b></u>, the ndis.sys is a driver file that controls network adapters. You can roughly infer what the loop is doing, but it's beneficial to repeat the analysis process on your own so that you can sharpen your reverse engineering skills. We now expose some of the technical details here:<br />
<br />
<br />
(1) <u><b>zwQuerySystemInformation</b></u>. This is a very important system call provided by the OS. The function prototype is shown in the following, from <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms725506%28v=vs.85%29.aspx">MSDN</a>.<br />
<pre>NTSTATUS WINAPI ZwQuerySystemInformation(
__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
__inout PVOID SystemInformation,
__in ULONG SystemInformationLength,
__out_opt PULONG ReturnLength
);</pre>The first parameter is an integer that represents the type of information to query. There are many types available, e.g., system performance information, time of the day etc. In our case, the system information class is <u><b>SystemModuleInformation</b></u>, which provides the information of running system modules. Notice that the size of the SystemInformation (second parameter) can vary, you have to pass the BUFFER LENGTH of your preallocated buffer to zwQuerySystemInformation. If zwQuerySystemInformation needs more space, it will inform you that the <u><b>space is not enough</b></u> (using the ReturnLength, the 4th parameter). In that case, the Max++ code will go back to reallocate space.[see the Call of 0x3D0BC0 at 0x3C1C61, see <b>Challenge 1</b>]<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8S8NT9SQjTvwSdc7OUPXgAG9CHr5z-YJQwHwz8Oykcr3yfA53a-a6taMlVvuCY9j4UJNC9fPI0q0qaVsIkQTrn5Crmb68ZkAlx3skiGbtG2huZMG9hWlgbKjXjqqZ1xhCwsqz0VvHvkE/s1600/e2.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8S8NT9SQjTvwSdc7OUPXgAG9CHr5z-YJQwHwz8Oykcr3yfA53a-a6taMlVvuCY9j4UJNC9fPI0q0qaVsIkQTrn5Crmb68ZkAlx3skiGbtG2huZMG9hWlgbKjXjqqZ1xhCwsqz0VvHvkE/s1600/e2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 8. Read System Module Information</td></tr>
</tbody></table><br />
(2) System Module Information. Let's now delve into the data returned by zwQueryInformation. Using a simple google search, we can find the definition of _SYSTEM_MODULE_INFORMATION and _SYSTEM_MODULE. As shown below [the code is from <a href="http://source.winehq.org/source/include/winternl.h">http://source.winehq.org/source/include/winternl.h</a>] .<br />
<br />
<div style="font-family: 'Courier New',Courier,monospace;"><span style="font-size: x-small;">typedef struct _SYSTEM_MODULE_INFORMATION<br />
{</span></div><span style="font-family: "Courier New",Courier,monospace; font-size: x-small;">ULONG ModulesCount;<br />
SYSTEM_MODULE <u><b>Modules[0];</b></u> /* FIXME: should be Modules[0] */<br />
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;<br />
<br />
<br />
typedef struct _SYSTEM_MODULE<br />
{<br />
PVOID Reserved1; /* 00/00 */<br />
PVOID Reserved2; /* 04/08 */<br />
PVOID ImageBaseAddress; /* 08/10 */<br />
ULONG ImageSize; /* 0c/18 */<br />
ULONG Flags; /* 10/1c */<br />
WORD Id; /* 14/20 */<br />
WORD Rank; /* 16/22 */<br />
WORD Unknown; /* 18/24 */<br />
WORD NameOffset; /* 1a/26 */<br />
BYTE Name[MAXIMUM_FILENAME_LENGTH]; /* 1c/28 */<br />
} SYSTEM_MODULE, *PSYSTEM_MODULE;</span><br />
<br />
<br />
<br />
Note that the second parameter <u><b>Modules[0] </b></u>of _SYSTEM_MODULE_INFORMATION is a real array (i.e., not a simple pointer to the entry address of the array). In another word, the size of _SYSTEM_MODULE_INFORMATION can vary, depending on the value of ModulesCount. Similarly, the last attribute <u><b>NAME[MAXIMUM-FILENAME_LENGTH] </b></u>of _SYSTEM_MODULE is a real character array (not a pointer)<br />
<br />
<br />
Figure 9 shows the first 0x90 bytes of the _SYSTEM_MODULE_INFORMATION structure.<br />
<br />
<u><b>Challenge 2.</b></u> Given Figure 9, can you infer how many modules are located in the _SYSTEM_MODULE_INFORMATION? (i.e., how many modules are loaded in the system right now?)<br />
<br />
<u><b>Challenge 3.</b></u> Given Figure 9, can you infer the name of the first module? What is the value of <u><b>NameOffset </b></u>in the first _SYSTEM_MODULE?<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoUpJwTJeBWSb0_mVWSvwZAAzIpZgwP8laUm_qNy381KX2yayQwKKr0YeQXc-95lEiM5aE2f86pSANvGFft2KmWlcF8rdxS9jZ_bu00-NnfIZeyCnchqGwBh5FVmi1elqrjiGugnCyFsY/s1600/e3.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoUpJwTJeBWSb0_mVWSvwZAAzIpZgwP8laUm_qNy381KX2yayQwKKr0YeQXc-95lEiM5aE2f86pSANvGFft2KmWlcF8rdxS9jZ_bu00-NnfIZeyCnchqGwBh5FVmi1elqrjiGugnCyFsY/s1600/e3.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 9. System Module Information</td></tr>
</tbody></table><br />
To help you further understand the logic in <u><b>Figure 8</b></u>, we list more challenges below:<br />
<u><b>Challenge 4.</b></u> Given Figure 8, observe the instructions from 0x3C1C73 and 0x3C1C78, they push the parameters for zwQueryInformation. which of the registers (EAX, ESI etc.) contains the buffer to hold system information?<br />
<br />
<u><b>Challenge 5.</b></u> Given Figure 8, observe the instructions at 0x3C1CDF. The instruction is LEA ESI, DS:[EAX+EDI+1C]. Explain the meaning and purpose of this instruction? Specifically, explain what is contained in EAX, EDI and what's the meaning of offset 0x1c?<br />
<br />
<br />
<br />
<u><b>Challenge 7.</b></u> Find a way to get out of the loop and what is the ImageBaseAddress of "ndis.nys"? (you have to first properly set up a conditional breakpoint).<br />
<br />
<u><b>Challenge 8</b></u>. Explain the logic between <u><b>0x3C1CF3 </b></u>(NEG EAX) to <u><b>0x3C1CFE </b></u>(JE 0x3C1E1E), and explain why would the JE instruction not jump when the module name is "NDIS.sys".<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7Zp-IEzbpKd3vLznSTyGIFdx3TIpsZOU0vPxTc50UVQS_F760-iKHBHPjrMvCI22WzPgovVgXgWj2MTwtSpR1o3AaqOTTO14zK3pjyKNvPWOqE-nCzni7rkgezOJPLq-GsLHjLd2GfPM/s1600/e1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7Zp-IEzbpKd3vLznSTyGIFdx3TIpsZOU0vPxTc50UVQS_F760-iKHBHPjrMvCI22WzPgovVgXgWj2MTwtSpR1o3AaqOTTO14zK3pjyKNvPWOqE-nCzni7rkgezOJPLq-GsLHjLd2GfPM/s1600/e1.JPG" yda="true" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 10. After NDIS.sys is found</td></tr>
</tbody></table><br />
<u><b>Section 5. Test Registry (Function 0x003C18D4)</b></u><br />
When the module of NDIS is found, the control flow continues to 0x003C1D04 (shown in Figure 10). The code first did a name comparison of "ndis.sys" and "win32k.sys", and if not equal, it calls function <u><b>0x003C18D4 </b></u>at <u><b>0x003C1D27</b></u>. We'll provide the analysis of function 0x003C18D4 below.<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheTtZpM-lopm9RR19SEY2ke5GXtmK4y0n20NtEEub_22TETKCGsP4vAcibhMeB_DcO9AMZwaavROLPMS1kCZiigMh4BvBZ6nav3fscWA5CY-dckMMyTJ7bglwCHbzFP5G0xD4fNJ1WvyQ/s1600/e2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheTtZpM-lopm9RR19SEY2ke5GXtmK4y0n20NtEEub_22TETKCGsP4vAcibhMeB_DcO9AMZwaavROLPMS1kCZiigMh4BvBZ6nav3fscWA5CY-dckMMyTJ7bglwCHbzFP5G0xD4fNJ1WvyQ/s1600/e2.JPG" yda="true" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Fogure 11. First Part of Function 0x3C18D4</td></tr>
</tbody></table>Figure 11 shows the first part of Function 0x3C18D4. Most of the functions are very easy to analyze. It first calculates the string length of the ndis.sys file and checks if the file name is not too long. Then it checks if the first letter of the file name is ascii code 2E "." (if not, it continues). Then it searches for the file suffix and verifies if it ends with ".sys". These are fairly routine checks to make sure that the file (ndis.sys) is a normal system driver file. Lastly, it calls <u><b>lz32.003C250C</b></u> at <u><b>0x003c193e</b></u>. We now try to analyze function 0x003c250c.<br />
<br />
<u><b>5.1 Function 0x003C250C (Building Object_Attributes)</b></u><br />
<br />
In general, to analyze a function, we need to figure out three things: (1) what are the input parameters? (2) what are the output parameters? (3) what does the function do?<br />
<br />
Analysis of malware functions can be a challenging job, as malware authors will not necessarily have to follow the typical C language calling conventions (i.e., pushing parameters to stack and use standard registers for return).It creates trouble for us to understand the functionality of a function.<br />
<br />
Figure 12 shows the body of function 0x003C250C.By studying the instructions we know that the input parameter of this function is the ESI register. The function body calls RtlInitUnicodeString and then is saving some values to the RAM (at ESI+4, ESI+8 etc.). It seems that the function is building some data structure however we have no way to know what exactly the type is. In this case, we have to trace how the return data is used (note that the return of this function is saved in EAX, look at the instruction at 0x3C2535).<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMIH3wxUUs-eu-HAhSreYfel0UlJRGexL7R_xHF4UiNU-39mMYcYBSrBKjrqVtO_K3MM2gM0SKdFgUvM_vhzjk2MMircJ6bFXwqUP5vxj6HO2Wdgm9dZJYKezt-waHPYx7Q6vhG3KXZ2g/s1600/e6.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMIH3wxUUs-eu-HAhSreYfel0UlJRGexL7R_xHF4UiNU-39mMYcYBSrBKjrqVtO_K3MM2gM0SKdFgUvM_vhzjk2MMircJ6bFXwqUP5vxj6HO2Wdgm9dZJYKezt-waHPYx7Q6vhG3KXZ2g/s1600/e6.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 12. Function Body 0x3C250C</td></tr>
</tbody></table><br />
Figure 13 shows the caller of 0x3C250C. Notice that at 0x003C1943 (right after the call of function 0x3C250C), the code pushes EAX (the return of function 0x3C250C) into stack, and then it pushed another two words into stack and calls <u><b>zwOpenKey</b></u>. Clearly, the return value of 0x003C250C is used as the 3rd parameter of <u><b>ZwOpenKey</b></u>, which immediately leads us to the conclusion: <u><b>function 0x3C250C is building an object of _OBJECT_ATTRIBUTES.</b></u> Figure 14 shows the details of the object constructed. You can see that the main component is the ObjectName, which contains value "<u><b>\registry\...\NDIS</b></u>".<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBl8hCs7iY9M1N7f9fXN0ST63lumoOBpyfMmzYU1O8SRx3996gK3voTdvS3Poq741U-tj9V-NQW_TLgCxjHMLRQo4yaNvDbY2iE3pcUdniCmmHzJBwcf53Hdc6KvMugv8j3ucozOsuPzY/s1600/e3.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBl8hCs7iY9M1N7f9fXN0ST63lumoOBpyfMmzYU1O8SRx3996gK3voTdvS3Poq741U-tj9V-NQW_TLgCxjHMLRQo4yaNvDbY2iE3pcUdniCmmHzJBwcf53Hdc6KvMugv8j3ucozOsuPzY/s1600/e3.JPG" yda="true" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 13. How the return data of Function 0x3C250C is Used</td></tr>
</tbody></table><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMWmfGQBqXYQTT1DMOWg8NFp4B0H9TuUgsnXlxcIQtgLSkukFP21fgKw4goulf5dyR2gjV-AJjhf-OGHyPCRvtOSStduNfLWzXhdLUpvt5Khpo5XSUCZLP_BTvsz8EaR1Kt1Ttl2XaKj8/s1600/e4.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMWmfGQBqXYQTT1DMOWg8NFp4B0H9TuUgsnXlxcIQtgLSkukFP21fgKw4goulf5dyR2gjV-AJjhf-OGHyPCRvtOSStduNfLWzXhdLUpvt5Khpo5XSUCZLP_BTvsz8EaR1Kt1Ttl2XaKj8/s1600/e4.JPG" yda="true" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 14. Memory Contents of Object Attributes</td></tr>
</tbody></table><br />
<u><b>5.2 Rest of Function </b></u><u><b>0x003C18D4 </b></u><u><b>(check existence of registry file)</b></u><br />
<br />
We now continue to analyze the rest of Function 0x003C18D4 (shown in Figure 15). Interestingly, after calling the ZwOpenKey, the code immediately call ZwClose to close the registry handle immediately. What's its purpose then? If you check the control flow, you would notice that<u><b> depending on the return value of ZwOpenKey, the function returns 1 when the registry key is successfully opened, and returns 0 when the ZwOpenKey fails.</b></u><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSYMp6nE9ZpkpBPS2Rn4StyV1QplnLaBLugtEzmwmuwnEVnIFi5zHRlC2nCywaC0ASbCL5Qh__tr7uz1asynJMPXExc4T3Vk1JVAPrIiE3OBUd2ONTJxz_oW8YCrI5U9-30wmwVTFVtT8/s1600/e1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSYMp6nE9ZpkpBPS2Rn4StyV1QplnLaBLugtEzmwmuwnEVnIFi5zHRlC2nCywaC0ASbCL5Qh__tr7uz1asynJMPXExc4T3Vk1JVAPrIiE3OBUd2ONTJxz_oW8YCrI5U9-30wmwVTFVtT8/s1600/e1.JPG" yda="true" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 15. Rest of Function 0x3C18D4</td></tr>
</tbody></table><br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmDqaUExsAlOOB4GWYmveUlYhyphenhyphenSp8bmtgcYWQNUv_l_wzWBEdI509nOAINICJ04smRZHkW3jS4Pp7PAx0_ixa_KXnPlgdrVG_5k0hXtDvfGxzGOYKR4fTsKhh2-K6H7cw7-g9w6SJjHKU/s1600/E2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmDqaUExsAlOOB4GWYmveUlYhyphenhyphenSp8bmtgcYWQNUv_l_wzWBEdI509nOAINICJ04smRZHkW3jS4Pp7PAx0_ixa_KXnPlgdrVG_5k0hXtDvfGxzGOYKR4fTsKhh2-K6H7cw7-g9w6SJjHKU/s1600/E2.JPG" yda="true" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 16. Reads NDIS.sys</td></tr>
</tbody></table><br />
<u><b>Section 6. Scanning Proper Driver Files (Starting from 0x3C12DC).</b></u><br />
As shown in Figure 16, at <u>0x3C1D27 </u>the code returns from 0x3C18D4 (check the existence of registry for NDIS). Then it performs zwReadFile twice, first to read 0x40 bytes and then to read 0xF8 bytes. The second read loads the<u><b> entire PE header</b></u> (0xF8 bytes) into 0x12D388. <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmJ1HwpIeZjIexHAmshr_J_spucW8RgIy5uOBanfQIEG0r5dhRdmfkV2YkNKAOqxO_nlfX6TXVi3O0gWHPDa8FQLhiQICPyyrle54tKqSg8Ew13PewGLaJhcCGZwibSfzECDuVJY80SK8/s1600/e3.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmJ1HwpIeZjIexHAmshr_J_spucW8RgIy5uOBanfQIEG0r5dhRdmfkV2YkNKAOqxO_nlfX6TXVi3O0gWHPDa8FQLhiQICPyyrle54tKqSg8Ew13PewGLaJhcCGZwibSfzECDuVJY80SK8/s1600/e3.JPG" yda="true" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 17. Check Proper Size</td></tr>
</tbody></table><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><br />
</td></tr>
</tbody></table><i>Now comes the interesting part</i>, see <u><b>Figure 17</b></u>. At <u><b>0x3C1DDF</b></u>, the code checks the EXPORT TABLE SIZE of the PE header and see if it is NOT zero. If it's zero, it will continue the search and check another system module. NDIS.sys fails the check (its export table size is 0). <br />
<br />
Then at <u><b>0x003C1DF3</b></u>, it calls zwQueryInformationFile and reads the FILE_STANDARD_INFORMATION of the module (this time, the mup.sys). It then reads the file size of the module and compare it with value 0x4C10. If the file size is below 0x4C10, it continues the search.<br />
<br />
If everything is fine so far, at <u><b>0x003C1E0E</b></u>, it resets the ID of the _SYSTEM_MODULE to 1 and it writes the actual file size of the system module file back into the _SYSTEM_MODULE (i.e., reset the ImageSize attribute).<br />
<br />
For each system module found (with EXPORT TABLE SIZE>0 and file size>0x4c10), the code increments counter at <u><b>0x12D5D4 </b></u>by 1.<br />
<br />
<br />
<u><b>Challenge 9.</b></u> Explain the logic of the code of Figure 17 in details. For example, for instruction at 0x3C1DDF, how would you know that it is checking EXPORT TABLE SIZE?<br />
<br />
<u><b>Section 7. Random Pick of Drivers(Starting from 0x3C1E30).</b></u><br />
We now examine the next section of the malicious logic (shown in Figure 18). When the code executes to 0x3C1E30 (out of the big loop), at <b>EBP-30</b> (0x12D5D4), it stores the number of system modules that satisfy the criteria: (1) size greater than 0x4C10; and (2) EXPORT TABLE SIZE > 0. On our system, there are <u><b>0x19</b></u> modules that satisfy the condition.<br />
<br />
The next section (from 0x003C1E30 to 0x3C1E6D) randomly picks up a module to infect. First, it calls GetTickCount to get the current time, and then it calls RtlRandom using the current time as seed. Then it does a <u><b>DIV </b></u>operation (at 0x3C1E51) on 0x19 (the number of modules), after which, the remainder is stored in <u><b>EDX</b></u>.<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhafqOEayxwKxXT7piBnXwOw89BIZelvpQo90u0eF4v6FDVnyXY7blKBkB0evCBZdLQ55RIDqUTFcEcwEYbMps_SIV5p9wYJymM5SRhJpABN_wvdPAW-AaGmtNXE3daqcEOsjFLooXC6fI/s1600/e1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhafqOEayxwKxXT7piBnXwOw89BIZelvpQo90u0eF4v6FDVnyXY7blKBkB0evCBZdLQ55RIDqUTFcEcwEYbMps_SIV5p9wYJymM5SRhJpABN_wvdPAW-AaGmtNXE3daqcEOsjFLooXC6fI/s1600/e1.JPG" yda="true" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 18. Randomly Pick a Driver File</td></tr>
</tbody></table><br />
The loop from <u><b>0x3C1E59 </b></u>to <u><b>0x3C1E6D </b></u>is used to get the _SYSTEM_MODULE. Given that the random ID stored in EDX, without the loss of generality, let's assume that it's 5. It tries to get the 5th satisfactory module by visiting every module in the list of _SYSTEM_MODULES retrieved by earlier call of zwQuerySystemInformation. Notice that at 0x003C1E59, <u><b>it compares [ESI+14] with BX (value 1)</b></u>. Here ESI points to the _SYSTEM_MODULE, and the offset 0x14 stores ID. Recall that earlier the code marks each module satisfying the criteria with ID 1, this immediately explains the purpose of the comparison code. <u><b>After the code jumps out of the loop, ESI points to the selected _SYSTEM_MODULE.</b></u> Up to now, the random selection of a system module is completed. We will explain the infection process in the next tutorial.Unknownnoreply@blogger.com32tag:blogger.com,1999:blog-8770073098084592029.post-20065366765092902772012-02-10T08:21:00.000-08:002012-04-23T04:23:13.887-07:00Malware Analysis Tutorial 16: Return Oriented Programming (Return to LIBC) Attack<b>Learning Goals</b>:<br />
<ol>
<li>Understand Return to LibC attacks</li>
<li>Analyze Return to LibC data payloads</li>
<li>Practice analyzing function call parameters and stack</li>
</ol>
<b>Applicable to:</b><br />
<ol>
<li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security</li>
</ol>
<u><b>1. Introduction</b></u><br />
This tutorial shows a very interesting attack called <u><b>Return to LibC</b></u>. The general idea is to form a chain of system calls by setting up stack contents properly so that the target process, when returning from one system call, will continue onto the next system call set up by the attacker. A more general form of the Return to LibC attack is the recently very active<u><b> Return Oriented Programming</b></u> [<a href="http://cseweb.ucsd.edu/~hovav/talks/blackhat08.html">1</a>], where<i><b> any arbitrary</b></i> program can be implemented by setting up the stack contents.<br />
<br />
Usually, Return to LibC attack is applied to buffer overflow attacks so that it can overcome the protections taken by OS to set stack as non-executable (recall that it does not inject a shell code, but a bunch of function parameters and return addresses).<br />
<br />
In this tutorial, we show that the Max++ author takes a very clever application of the Return to LibC attack. Instead of setting up the code section of a thread, the author directly implements the desired program logic as the stack contents, which saves a lot of trouble in injecting a new thread into a running process [see background information in Tutorial <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-14-retrieve.html">14</a> and <a href="http://fumalwareanalysis.blogspot.com/2012/02/malware-analysis-tutorial-15-injecting.html">15</a>].<br />
<br />
We will analyze the code from <u><b>0x3C1390 </b></u>in this tutorial.<br />
<br />
<br />
<u><b>2. Lab Configuration</b></u><br />
(0) Start WinXP image in <u><b>DEBUGGED </b></u>mode. Now in your host system, start a windows command window and CD to "<u><b>c:\Program Files\Debugging Tools for Windows (x86)</b></u>" (where WinDBG is installed). Type "<u><b>windbg -b -k com:pipe,port=\\.\pipe\com_12</b></u>" (check the com port number in your VBox instance set up). When WinDbg initiates, types "g" (go) twice to let it continue.<br />
<br />
(1) Now launch IMM in the WinXP instance, clear all breakpoints and hardware breakpoints in IMM (see <u><b>View->Breakpoints</b></u> and <u><b>View->Hardware Breakpoints</b></u>).<br />
<br />
(2) Go to <u><b>0x4012DC </b></u>and set a hardware breakpoint there. (why not software bp? Because that region will be self-extracted and overwritten and the software BP will be lost). Pay special attention that once you go to 0x4012DC, directly right click on the line to set hardware BP (currently it's gibberish code).<br />
<br />
(3) Press<u><b>F9</b></u> several times run to <u><b>0x4012DC</b></u>. You will encounter several breakpoints before 0x4012DC. If you pay attention, they are actually caused by the int 2d tricks (explained in <a href="http://www.blogger.com/cd%20%22c:/Program%20Files/Debugging%20Tools%20for%20Windows%20%28x86%29%22">Tutorial 3</a> and <a href="http://fumalwareanalysis.blogspot.com/2011/10/malware-analysis-tutorial-4-int2dh-anti.html">4</a>, and <a href="http://fumalwareanalysis.blogspot.com/2011/10/malware-analysis-tutorial-5-int2d-anti.html">5</a>). Simply ignore them and continue (using F9) until you hit <u><b>0x4012DC</b></u>.<br />
<br />
Figure 1 shows the code that you should be able to see. As you can see, this is right before the call of RtlAddVectoredException, where hardware BP is set to break the LdrLoadDll call (see <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-11-starling.html">Tutorial 11</a> for details). <u><i><b>At this point, the code at 0x3C24FB has not been extracted. If you go to 0x3C24FB at this moment, IMM will complain that this address is not accessible.</b></i></u><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwY824Lshgaeu8tuf06xKBmXnOPpS45_aLSiyOO45sA9pUkglF0nkUNMcKdeRPsWKWehn-aEkpgnh_QlWjxN24f9iwlRq3j49BXfnl1EalZjMddZCgC7CrlmOpeIW3gUaEWXq-lxL5ULk/s1600/c1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwY824Lshgaeu8tuf06xKBmXnOPpS45_aLSiyOO45sA9pUkglF0nkUNMcKdeRPsWKWehn-aEkpgnh_QlWjxN24f9iwlRq3j49BXfnl1EalZjMddZCgC7CrlmOpeIW3gUaEWXq-lxL5ULk/s1600/c1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1: code at 0x4012DC</td></tr>
</tbody></table>
(4) Now scroll down about 2 pages and set a <u><b>SOFTWARE BREAKPOINT</b></u> at <u><b>0x401417</b></u>. This is right after the call of LdrLoadDll("lz32.dll"), where Max++ finishes the loading of lz32.dll. Then hit <u><b>SHIFT+F9 </b></u>several times until you reach <u><b>0x401417</b></u> (you will hit 0x7C90D500 twice, this is somwhere inside ntdll.zwMapViewSection which is being called by LdrLoadDll). <br />
<br />
<br />
 <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdtJaTR3WJ33l5wLbd_tnt7knNdgNf2mnPTZkY4JnUjgqmsT5MmCcncck40DPpvSxsTDU1FqKSmI3pKeZpha2zb9nEzPe6EVmFatNSs-b5G6Jz3wS0GslZmw4vscwFZONefJRcfuDAtGc/s1600/c2.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdtJaTR3WJ33l5wLbd_tnt7knNdgNf2mnPTZkY4JnUjgqmsT5MmCcncck40DPpvSxsTDU1FqKSmI3pKeZpha2zb9nEzPe6EVmFatNSs-b5G6Jz3wS0GslZmw4vscwFZONefJRcfuDAtGc/s1600/c2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2: code at 0x401407</td></tr>
</tbody></table>
 <br />
(6) Now we will set a breakpoint at <u><b>0x3C1390</b></u>. Goto <u><b>0x3C1390</b></u>set a <u><b>SOFTWARE </b><b>BREAKPOINT</b><b>. SHIFT+F9</b></u> there. Press to run to <u><b>0x3C1390</b></u>. (You may see a warning that this is out range of the code segment, simply ignore the warning).<br />
<br />
(Figure 3 shows the code that you should be able to see at <u><b>0x3C1390</b></u>. The first instruction should be <u><b>PUSH SS:[EBP-8]</b></u>, and he next is a function call: <u><b>CALL DWORD PTR DS: [3D1128]</b></u> (see Figure 3). This is a function call to <u><b>RtlCreateUserThread</b></u>. <u><i><b>We will start our analysis here!</b></i></u><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiMQzqaZ3dQO5ii4YXBsATDEstUjzsmGyCq1JGj9L778eOaLHs5HGLnqMk6f9SwvSXYh5NOEQl1N-CFtHDheX7HLTzoz5AGshZ6tzjtFVLLEUz2wx57hJLvzeRJtxYQ-VQUg-IQJimf_4/s1600/d5.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" sda="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiMQzqaZ3dQO5ii4YXBsATDEstUjzsmGyCq1JGj9L778eOaLHs5HGLnqMk6f9SwvSXYh5NOEQl1N-CFtHDheX7HLTzoz5AGshZ6tzjtFVLLEUz2wx57hJLvzeRJtxYQ-VQUg-IQJimf_4/s1600/d5.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. Code Starting from 0x003C1390</td></tr>
</tbody></table>
<br />
<u><b>Section 3. Creating Target Thread</b></u><br />
The first function we are analyzing is located at 0x003C1393 (see Figure 3). <u><b>RtlCreateUserThread </b></u>is an undocumented function by MS Windows. But a simple google search can turn out its function declaration as shown following (taken from [<a href="http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Executable%20Images/RtlCreateUserThread.html">2</a>]):<br />
<br />
<div style="font-family: 'Courier New',Courier,monospace;">
<span style="font-size: x-small;">RtlCreateUserThread(<br />
IN HANDLE <u><b>ProcessHandle</b></u>,</span></div>
<div style="font-family: 'Courier New',Courier,monospace;">
<span style="font-size: x-small;"> IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,<br />
IN BOOLEAN CreateSuspended,<br />
IN ULONG StackZeroBits,<br />
IN OUT PULONG StackReserved,<br />
IN OUT PULONG StackCommit,<br />
IN PVOID <u><b>StartAddress</b></u>,<br />
IN PVOID StartParameter OPTIONAL,<br />
OUT PHANDLE ThreadHandle,<br />
OUT PCLIENT_ID ClientID</span></div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">); </span><br />
<br />
<pre class="FnDefinition"><div class="FnDefParams">
There are many parameters, and the following are interesting to us:</div>
<div class="FnDefParams">
(1) <u><b>ProcessHandle </b></u>- the handle of the process to create a user thread in.</div>
<div class="FnDefParams">
(2) <u><b>StartAddress </b></u>- when the thread is created, where to begin its execution</div>
<div class="FnDefParams">
</div>
<div class="FnDefParams">
Figure 4 shows the stack contents when we get to the CALL instruction at <u><b>0x3C1390</b></u>.
</div>
</pre>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGlBABuLUbFc_E_9xHR4mJIH4g9s-VlJeCPadFy80ggRyD3cthCxxa-3zVdwDhw0kRKsNJo0ffGfhjrYT4nIrE8RBKW9fghZphrqheS6og4St4SQaCtHzLKq9kOzsMDO4X7kcWqgW0Tx0/s1600/d6.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" sda="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGlBABuLUbFc_E_9xHR4mJIH4g9s-VlJeCPadFy80ggRyD3cthCxxa-3zVdwDhw0kRKsNJo0ffGfhjrYT4nIrE8RBKW9fghZphrqheS6og4St4SQaCtHzLKq9kOzsMDO4X7kcWqgW0Tx0/s1600/d6.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4: Stack Contents for Call RtlCreateUserThread</td></tr>
</tbody></table>
<br />
<br />
You can immediately infer that the ProcessHandle is 0x44. If you follow Tutorial <a href="http://fumalwareanalysis.blogspot.com/2012/02/malware-analysis-tutorial-15-injecting.html">15</a>, you will notice that it's the handle of the target process (e.g., smss.exe in our VM instance). The startAddress is <u><b>0x7C96149B</b></u> (note! IMM has already found it for you! It's the entry address of <u><b>RtlExitUserThread</b></u>!!!) The situation has got a little bit funny here because the author tries to inject a thread which terminates itself immediately! But he/she has additional tricks. Now let's proceed to the next function call.<br />
<br />
<u><b>Section 4. Get Context Thread</b></u><br />
The next system call we are analyzing is located at 0x3C13B5.It's a call to <u><b>zwGetContext</b></u> (as shown in Figure 5). A simple search of zwGetContext or ntGetContext yields the function prototype of zwGetContext. It takes two parameters (1) HANDLE threadHandle, and (2) PCONTEXT <u><b>pContext</b></u>. Clearly, the first is the handle of the thread to be examined, and the second (i.e., <u><b>pContext</b></u>) is a pointer which holds the entry address of the CONTEXT structure. If you look at Figure 5, you might notice that the pContext value is <u><b>0x0012D288</b></u>.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjThXZ-vBvNZTChE2UCw8obGdiyyY8F7MoeKtKagnsi7bEAr2ytzJj_lv7vlWOrdmcgDqVdDx2algoTAryitZXjkfg0_w3MLXAl3GWUcuFomr_H37BZssFuvVdAlgWJMdwdFV4PEqL0ZuI/s1600/d7.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" sda="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjThXZ-vBvNZTChE2UCw8obGdiyyY8F7MoeKtKagnsi7bEAr2ytzJj_lv7vlWOrdmcgDqVdDx2algoTAryitZXjkfg0_w3MLXAl3GWUcuFomr_H37BZssFuvVdAlgWJMdwdFV4PEqL0ZuI/s1600/d7.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5. call of zwGetContext</td></tr>
</tbody></table>
Now we are interested in looking at the contents of the CONTEXT structure at <u><b>0x0012D288</b></u>. Of course, you can use IMM to examine it in the memory dump directly. There is a better way. Using WinDbg can show kernel data structures nicely. For this purpose, let's start the <u><b>WinDbg in the VBox Windows image</b><b>File-> Attack Process -> Max++</b></u> (note: not the external one in the host) and then click and select to run <u><b>Noninvasively</b></u>. (as shown in Figure 6).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGuWXP0dm_0jk2IwiGuMGTMQarXJpssSqeyvX0bvNH2qQhwMghn8IcLRcc5w4mNkvEnQSMjFliZHCnATsRfgxzv8H8gH5e5FkWvqC_cx47v7wqmiKyWdCtYPAZoSrMwPRI8LdvxxiP59E/s1600/d8.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" sda="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGuWXP0dm_0jk2IwiGuMGTMQarXJpssSqeyvX0bvNH2qQhwMghn8IcLRcc5w4mNkvEnQSMjFliZHCnATsRfgxzv8H8gH5e5FkWvqC_cx47v7wqmiKyWdCtYPAZoSrMwPRI8LdvxxiP59E/s1600/d8.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6. Run WinDebug in Noninvasive Mode</td></tr>
</tbody></table>
<br />
<br />
Now type "<u><b>dt _CONTEXT -r2 0x0012D288</b></u>" we have the complete dump of the _CONTEXT structure. Note that the _CONTEXT is used by OS to keep track of the running context (mainly the value of the registers) of a thread when doing context switch. As shown in <u><b>Figure 7</b></u>, the initial context of the new thread in smss.exe has several interesting registers:<br />
(1) First, we could see all hardware BPs are cleared.<br />
(2) All segment registers GS/FS/ES/DS are not set yet.<br />
(3) EIP is set to 0x7c96149b. (If you find it out in IMM->View->Modules->ntdll->Names. You will find that this is the entry address of <u><b>RtlExitUserThread</b></u>, matching the description before).<br />
(4) The ESP is set to 0x3fff8 (note: this is within the address space of smss.exe, not Max++.exe).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiymyzbdCHUYl9Ht9RVICo5rnfcnilVvyHaQDIS4WNnLOQI1gA_Ib_iapFPqPrjFkYsJ9EsRTDVdE9UgGoBwgbOjifyBgT1ziRn_xMkDFYcdQGau_tE7LVjn-vgGIpLENdhic4QJ5LD41Y/s1600/d9.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" sda="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiymyzbdCHUYl9Ht9RVICo5rnfcnilVvyHaQDIS4WNnLOQI1gA_Ib_iapFPqPrjFkYsJ9EsRTDVdE9UgGoBwgbOjifyBgT1ziRn_xMkDFYcdQGau_tE7LVjn-vgGIpLENdhic4QJ5LD41Y/s1600/d9.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 7. Initial Dump of the _CONTEXT at 0x0012D288</td></tr>
</tbody></table>
<br />
<br />
<u><b>Section 5. Set up smssexe Stack</b></u><br />
Next, Max++ will set up the stack for the new thread properly. Let's look at Figure 8. From 0x003C13C3 to 0x003C1455, Max++ prepares the contents first in its own stack (you could see here there are lots of operations to the EBP based addresses). Then at <u><b>0x3C145F</b></u>, it calls the most important function <u><b>zwWriteVirtualMemory</b></u>!<br />
 <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhuyYGDtwifgd8xDse5_il4IAO4HkuGRyjL3CWsZSmrLeQyPRDABNkyvzhA9GvM1lHBplm1F_uPAJsh28ruYyClyE6FcwPLQZ3m2aS2HKmOiMqmL8jSuh4FSZQ7qdejEmjUyAIyUtB0QY/s1600/d10.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" sda="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhuyYGDtwifgd8xDse5_il4IAO4HkuGRyjL3CWsZSmrLeQyPRDABNkyvzhA9GvM1lHBplm1F_uPAJsh28ruYyClyE6FcwPLQZ3m2aS2HKmOiMqmL8jSuh4FSZQ7qdejEmjUyAIyUtB0QY/s1600/d10.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 8. Set up Target Stack of smss.exe's new Thread</td></tr>
</tbody></table>
 <br />
Google the documentation of <u><b>zwWriteVirtualMemory </b></u>or <u><b>ntWriteVirtualMemory</b></u>, we could find that it takes four parameters: (1) target process handle [we could verify that this is the handle of the smss.exe], (2) target address [in our case, it's <u><b>0x3FF000</b></u>!], (3) source address (in Max++ addr space): <u><b>0x0012D580</b></u>, (4) number of bytes to write 0x<u><b>4c</b></u>!<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj40lZPHYOb7H1VjG4PQBcQ-2wBD2XEOYuPBK0f4rdPZA8AGeohSqmmwF0djvc8Pnkbi5y0-Zxmi44jNjI37CeiElFskZGXufsJLOgpCILtwqQQUQv1n0a-Yo1Q835Q86NAkUO3_Kxxp4s/s1600/d12.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" sda="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj40lZPHYOb7H1VjG4PQBcQ-2wBD2XEOYuPBK0f4rdPZA8AGeohSqmmwF0djvc8Pnkbi5y0-Zxmi44jNjI37CeiElFskZGXufsJLOgpCILtwqQQUQv1n0a-Yo1Q835Q86NAkUO3_Kxxp4s/s1600/d12.JPG" unselectable="on" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 9. Contents to Inject </td></tr>
</tbody></table>
Now let's take a look at the 0x4c bytes to write into the target process smss.exe. It's listed in Figure 9. Notice that the data is starting from <u><b>0x0012D580 </b></u>and ends at <u><b>0x0012D5CC</b></u> i.e., the first word is the <u><b>0x7C90CFD0 </b></u>(i.e., the first word in the first row of <u><b>Hex Dump</b></u> in figure 9, note the byte sequence) in the first row and then the last word is the <u><b>0xFFFFFFFF </b></u>(the first word in the last row). Notice that when copied to the target address space of smss.exe, starting from 0x3FF000 we should have 0x7C90CFD0 and at <u><b>0x3FF048 </b></u>we should have <u><b>FFFFFFFF</b></u>.<br />
<br />
<u><b>Section 6. Set Context of smss.exe thread</b></u><br />
As shown in Figure 8, the last trick to play is to call the <u><b>zwSetContextThread </b></u>call. Using the same trick we used in section 4, we can easily infer the meaning of all parameters of <u><b>zwSetContextThread</b></u>. It changes the value of the <u><b>ESP register to 0x3FF000, EBP is set to 0x0, EIP register is reset to 0x7C90DF30 (using IMM->View->Modules->Names) we can find that it's <span style="font-size: large;">zwWaitForSingleObject</span>!</b></u><br />
<br />
<u><b>Section 7. Analysis of Return To LibC Attack</b></u><br />
Now we are getting to the interesting point. The first instruction to be executed by the new thread is the entry of <u><b>zwWaitForSingleObject</b></u>(handle, alertable, timeout) . But were are the parameters? If you read about the calling conventions of these ntdll functions you will find that when executing to the first (entry) instruction of a NTDLL function, we have<br />
ESP --> the return address<br />
ESP+4: 1st parameter<br />
ESP+8: 2nd parameter<br />
ESP+c: 3rd paramter<br />
<br />
Thus we immediately get: the return address is (see Figure 9) <u><b>0x7C90CFDO </b></u>(<u><b>zwClose</b></u>). The parameters for zwWaitForSingleObject is:<br />
handle: 0x54 (what's the handle for? It's a challenge for you)<br />
alertable: 0<br />
timeOut: 0.<br />
<br />
When zwWaitForSingleObject finishes, it will jump to zwClose. The parameter for zwClose is 0x54 (still the same handle). When zwClose returns, the next function entry is <u><b>0x0x7C90D1F0 </b></u>(<u><b>zwDelayExecution</b></u>)!<br />
<br />
<u><b>Challenge of the Day:</b></u> Finish the above analysis of ReturnToLibC attack employed by Max++ and analyze what it is trying to do? <i>HINT: again if you could find documentation for <b>zwXYZ()</b>, you can try searching ntXYZ().</i><br />
<br />
<br />
<br />
<u><b>References</b></u><br />
1. E. Buchanan, R. Roemer, and S. Savage, "<a href="http://cseweb.ucsd.edu/~hovav/talks/blackhat08.html">Return-Oriented Programming: Exploits Without Code Injection</a>", Blackhat USA 2008.<br />
2. "Undocumented Functions of NTDLL", Available at <a href="http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Executable%20Images/RtlCreateUserThread.html">http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Executable%20Images/RtlCreateUserThread.html</a>.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><br /></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
<img height="40px" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj40lZPHYOb7H1VjG4PQBcQ-2wBD2XEOYuPBK0f4rdPZA8AGeohSqmmwF0djvc8Pnkbi5y0-Zxmi44jNjI37CeiElFskZGXufsJLOgpCILtwqQQUQv1n0a-Yo1Q835Q86NAkUO3_Kxxp4s/s1600/d12.JPG" style="left: 422px; opacity: 0.3; position: absolute; top: 6358px; visibility: hidden;" width="96px" />Unknownnoreply@blogger.com15tag:blogger.com,1999:blog-8770073098084592029.post-62264874240980549742012-02-03T16:56:00.000-08:002012-02-03T16:56:12.260-08:00Malware Analysis Tutorial 15: Injecting Thread into a Running Process<b>Learning Goals</b>:<br />
<ol><li>Understand process/thread privileges</li>
<li>Understand intercommunication and object duplication among processes</li>
<li>Practice analyzing function call parameters and stack</li>
</ol><b>Applicable to:</b><br />
<ol><li>Operating Systems</li>
<li>Assembly Language</li>
<li>Operating System Security</li>
</ol><u><b>1. Introduction</b></u><br />
In this tutorial, we show you another intriguing behavior of Max++: it removes the Max++Loader.exe from disk once it finishes its infection operations, such as modification of registry and infection of driver DLL files. The removal operation is accomplished using a series of interesting techniques: changing of process privileges, adding threads to another running process, hooking up timer events, and return oriented programming (more exactly return to libc attacks).<br />
<br />
We will analyze the code from <u><b>0x3C1193 </b></u>in this tutorial.<br />
<br />
The key to analyzing such malicious activities is to examine the system calls placed by Max++. We have introduced the techniques and skills you need for such analysis in <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-14-retrieve.html">Tutorial 14</a>.<br />
<br />
<u><b>2. Lab Configuration</b></u><br />
(0) Start WinXP image in <u><b>DEBUGGED </b></u>mode. Now in your host system, start a windows command window and CD to "<u><b>c:\Program Files\Debugging Tools for Windows (x86)</b></u>" (where WinDBG is installed). Type "<u><b>windbg -b -k com:pipe,port=\\.\pipe\com_12</b></u>" (check the com port number in your VBox instance set up). When WinDbg initiates, types "g" (go) twice to let it continue.<br />
<br />
(1) Now launch IMM in the WinXP instance, clear all breakpoints and hardware breakpoints in IMM (see <u><b>View->Breakpoints</b></u> and <u><b>View->Hardware Breakpoints</b></u>).<br />
<br />
(2) Go to <u><b>0x4012DC </b></u>and set a hardware breakpoint there. (why not software bp? Because that region will be self-extracted and overwritten and the software BP will be lost). Pay special attention that once you go to 0x4012DC, directly right click on the line to set hardware BP (currently it's gibberish code).<br />
<br />
(3) Press<u><b>F9</b></u> several times run to <u><b>0x4012DC</b></u>. You will encounter several breakpoints before 0x4012DC. If you pay attention, they are actually caused by the int 2d tricks (explained in <a href="http://www.blogger.com/cd%20%22c:/Program%20Files/Debugging%20Tools%20for%20Windows%20%28x86%29%22">Tutorial 3</a> and <a href="http://fumalwareanalysis.blogspot.com/2011/10/malware-analysis-tutorial-4-int2dh-anti.html">4</a>, and <a href="http://fumalwareanalysis.blogspot.com/2011/10/malware-analysis-tutorial-5-int2d-anti.html">5</a>). Simply ignore them and continue (using F9) until you hit <u><b>0x4012DC</b></u>.<br />
<br />
Figure 1 shows the code that should be able to see. As you can see, this is right before the call of RtlAddVectoredException, where hardware BP is set to break the LdrLoadDll call (see <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-11-starling.html">Tutorial 11</a> for details). <u><i><b>At this point, the code at 0x3C24FB has not been extracted. If you go to 0x3C24FB at this moment, IMM will complain that this address is not accessible.</b></i></u><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwY824Lshgaeu8tuf06xKBmXnOPpS45_aLSiyOO45sA9pUkglF0nkUNMcKdeRPsWKWehn-aEkpgnh_QlWjxN24f9iwlRq3j49BXfnl1EalZjMddZCgC7CrlmOpeIW3gUaEWXq-lxL5ULk/s1600/c1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwY824Lshgaeu8tuf06xKBmXnOPpS45_aLSiyOO45sA9pUkglF0nkUNMcKdeRPsWKWehn-aEkpgnh_QlWjxN24f9iwlRq3j49BXfnl1EalZjMddZCgC7CrlmOpeIW3gUaEWXq-lxL5ULk/s1600/c1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1: code at 0x4012DC</td></tr>
</tbody></table>(4) Now scroll down about 2 pages and set a <u><b>SOFTWARE BREAKPOINT</b></u> at <u><b>0x401417</b></u>. This is right after the call of LdrLoadDll("lz32.dll"), where Max++ finishes the loading of lz32.dll. Then hit <u><b>SHIFT+F9 </b></u>several times until you reach <u><b>0x401417</b></u> (you will hit 0x7C90D500 twice, this is somwhere inside ntdll.zwMapViewSection which is being called by LdrLoadDll). <br />
<br />
<br />
 <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdtJaTR3WJ33l5wLbd_tnt7knNdgNf2mnPTZkY4JnUjgqmsT5MmCcncck40DPpvSxsTDU1FqKSmI3pKeZpha2zb9nEzPe6EVmFatNSs-b5G6Jz3wS0GslZmw4vscwFZONefJRcfuDAtGc/s1600/c2.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdtJaTR3WJ33l5wLbd_tnt7knNdgNf2mnPTZkY4JnUjgqmsT5MmCcncck40DPpvSxsTDU1FqKSmI3pKeZpha2zb9nEzPe6EVmFatNSs-b5G6Jz3wS0GslZmw4vscwFZONefJRcfuDAtGc/s1600/c2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2: code at 0x401407</td></tr>
</tbody></table> <br />
(6) Now we will set a breakpoint at <u><b>0x3C1193</b></u>. Goto <u><b>0x3C1193</b></u>and set a <u><b>SOFTWARE </b><b>BREAKPOINT</b></u> there. Press SHIFT+F9 to run to <u><b>0x3C1193</b></u>. (You may see a warning that this is out range of the code segment, simply ignore the warning).<br />
<br />
(Figure 3 shows the code that you should be able to see at <u><b>0x3C1193</b></u>. The first instruction should be <u><b>PUSH EBP</b></u>, and then <u><b>MOV EBP, ESP</b></u>, and then <u><b>SUB EBP, 384</b></u>.).<br />
<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgl0c4W8_lz6BkgLDIp9lD7vjjzZ9E4EbhjLQGETxraBgW0_e4qBQH1oNL_YPO52sHOBLThBVc6-6sTcEZlNilYLOL6ifReP2P3xoIHADCYXzmLudFmnpFeQTHlskzWDOZoep9Ythz9NIY/s1600/e1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgl0c4W8_lz6BkgLDIp9lD7vjjzZ9E4EbhjLQGETxraBgW0_e4qBQH1oNL_YPO52sHOBLThBVc6-6sTcEZlNilYLOL6ifReP2P3xoIHADCYXzmLudFmnpFeQTHlskzWDOZoep9Ythz9NIY/s1600/e1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3: Function 0x3C1193</td></tr>
</tbody></table><u><b>3. Brief Analysis of Function 0x3C1193</b></u><br />
We now briefly describe the functionality of 0x3C1193 and we leave most analysis details to you in Section 4 (challenges).<br />
<br />
The first part of the code is shown in Figure 3. Max++ first calls a function <u><b>getModuleHandleW </b></u>of itself, and then it calls <u><b>LdrFindEntryForAddress </b></u>(its own module). Then there is a big loop from 0x3C11F1 to 0x3c1224, which follows the module list and examine the information of processes. This is done using <u><b>zwQueryProcessInformation </b></u>(there is an internal loop which adjusts the buffer size if the size is not enough). After several iterations, Max++ identifies a process which satisfies some criteria on parent process and children threads. In our case, the process identified is smss.exe. Then it opens a thread (<u><b>think about which thread it is</b></u>), and assign a bunch of privileges to the thread (See Figure 4).<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJTi8eYROBxryiTOQjtloZ4M-eFG1b3DZW9VjLsfViGV9Cd1C5Klto6ah8f0bEW4a7x1EKCm6g3pNbfK84YDjCWyDDlxirU4fidmh5HOsHk9rOjmRYQSNwP4qlbwWdHdIUttxPANXIj5U/s1600/d2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" sda="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJTi8eYROBxryiTOQjtloZ4M-eFG1b3DZW9VjLsfViGV9Cd1C5Klto6ah8f0bEW4a7x1EKCm6g3pNbfK84YDjCWyDDlxirU4fidmh5HOsHk9rOjmRYQSNwP4qlbwWdHdIUttxPANXIj5U/s1600/d2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Adding Privileges to Thread</td></tr>
</tbody></table>Figure 5 shows the next section of the code. This part is quite interesting. Now look at the function call at 0x003C12DA. The DosPathNameToNtPathName call converts string "c:\.. ..\Max++downloader.exe" to the format of NtPath (look at the stack top for the string). Then it opens the file at 0x0003C1331, and then <u><b>duplicates </b></u>the file object at 0x003C1355. Notice where is the duplicate object to be created! It's to be placed in the "smss.exe" process (which is not the Max++ process)!<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWXQFk9vckv7VXDzJBiQm1u6uEDgY7n47EchHMUArkgoi8kdWn1SiLc37RcNGzoD8DRxzo_usQSDU-7GW36-nqAF1_bfNrZPnQLve6LttstHK9YqIF7P9fVhyui7Ebk1HKutiMTtanPHI/s1600/d3.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" sda="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWXQFk9vckv7VXDzJBiQm1u6uEDgY7n47EchHMUArkgoi8kdWn1SiLc37RcNGzoD8DRxzo_usQSDU-7GW36-nqAF1_bfNrZPnQLve6LttstHK9YqIF7P9fVhyui7Ebk1HKutiMTtanPHI/s1600/d3.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5. Duplicate File Object</td></tr>
</tbody></table>The last part of the code is very tricky, and we'll leave the discussion of the return oriented technique to the next tutorial. Here, we'll only give some general idea. Figure 6 shows the last part of the code. At 0x003C1393, Max++ calls <u><b>RtlCreateUserThread </b></u>to create a new thread (question: who's the owner? Max++ or smss.exe?). Then it sets up the context of the newly created thread. From 0x003C13CF to 0x3C14FF, Max++ spent quite some efforts in setting up the contents of a piece of memory and then it copies this piece to a special region in the target process (smss.exe). Then it calls <u><b>zwSetContextThread </b></u>(at 0x003C1481) to set up the EIP register of the new thread. NOTE that here we have not specified the function body for the new thread! <u><b>How does the new thread accomplish the job? We'll elaborate a very interesting technique called return oriented programming in the next tutorial.</b></u><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR3TcWQNGcIfU4lgAOodyDM6wfgXl0ofkM4NgrjJk1vgDtxDHVSAa4Ff6GK5BDDaQu-mm0O2NAH-PeF1jejM9KM-gEVZ7eYRF3KSTqEYnPnBSVj1VrUD-HK2fYI6KOBHxur5mxjaNyGqo/s1600/d4.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" sda="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR3TcWQNGcIfU4lgAOodyDM6wfgXl0ofkM4NgrjJk1vgDtxDHVSAa4Ff6GK5BDDaQu-mm0O2NAH-PeF1jejM9KM-gEVZ7eYRF3KSTqEYnPnBSVj1VrUD-HK2fYI6KOBHxur5mxjaNyGqo/s1600/d4.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6. Create a New Thread in smss.exe Process</td></tr>
</tbody></table><br />
<br />
<br />
<u><b>4. Challenges</b></u><br />
[<i><u><b>Hint</b></u></i>: for system functions started with "zw", the "nt" series documentation can be often found. For example, "zwDuplicateObject" has a corresponding "ntDuplicateObject"]<br />
<br />
<u><b>Challenge 1. </b></u>Analyze the semantics of all function parameters and the return of <u><b>getModuleHandleW </b></u>call at <u><b>0x3C11A6 </b></u>(see Figure 3)<br />
<br />
<u><b>Challenge 2. </b></u>Analyze the semantics of all function parameters and the return of <u><b>LdrFindEntryForAddress</b></u> call at 0x3C11AD (see Figure 3)<br />
<br />
<u><b>Challenge 3. </b></u>Analyze the semantics of all function parameters and the return of <u><b>zwQuerySystemInformation</b></u> call at 0x3C11F3 (see Figure 3) <br />
<br />
<u><b>Challenge 4 </b></u>Summarize the function of the loop starting from 0x3C1209 to 0x3C123F which searches for a a process to inject a thread. There are some properties such a host process must satisfy. Read the code and describe these desired properties (on parent process and children threads).<br />
<br />
<u><b>Challenge 5 </b></u>In Figure 4, Max++ is adding a collection of privileges to a thread? Which thread it is (which process does this thread belong to)? Try to figure it out and prove that your argument is correct.<br />
<br />
<u><b>Challenge 6 </b></u>In Figure 4, Max++ is adding a collection of privileges to a thread? Analyze RtlAdjustPrivilege calls at 0x003C1297, 0x003C12A3, 0x003C12AF, 0x003C12BB, etc. List the privileges added.<br />
<br />
<u><b>Challenge 7 </b></u>Analyze the function call <u><b>DosPathNameToNtPathName </b></u>at 0x003C12DA (in Figure 5).<br />
<br />
<u><b>Challenge 8 </b></u>Analyze the function call <u><b>zwOpenFile </b></u>at 0x003C1331 (in Figure 5).<br />
<br />
<u><b>Challenge 9 </b></u>Analyze the function call <u><b>zwDuplicateObject </b></u>at 0x003C1355 (in Figure 5). Where is the new object (duplicated object) stored?<br />
<br />
<u><b>Challenge 10 </b></u>Analyze the function call <u><b>zwDuplicateObject </b></u>at 0x003C136e (in Figure 5). Which object is duplicated?<br />
<br />
<u><b>Challenge 11 </b></u>Analyze the function call <u><b>RtlCreateUserThread </b></u>at 0x003C1390 (in Figure 6).<br />
<br />
<u><b>Challenge 12 </b></u>Analyze the function call <u><b>zwContextThread </b></u>at 0x003C13B5 (in Figure 6). <br />
<br />
<u><b>Challenge 13 </b></u>Analyze the function call <u><b>zwWriteVirtualMemory </b></u>at 0x003C145F (in Figure 6). <br />
<span class="rwRRO"></span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><br />
</td></tr>
<tr><td class="tr-caption" style="text-align: center;"><br />
</td><td class="tr-caption" style="text-align: center;"></td><td class="tr-caption" style="text-align: center;"></td><td class="tr-caption" style="text-align: center;"><br />
</td><td class="tr-caption" style="text-align: center;"><br />
</td></tr>
</tbody></table>Unknownnoreply@blogger.com37tag:blogger.com,1999:blog-8770073098084592029.post-21027652546046675322012-01-31T08:01:00.000-08:002012-01-31T08:01:36.034-08:00Malware Analysis Tutorial 14: Retrieve Self-Decoding Key<b>Learning Goals</b>:<br />
<ol><li>Understand PE manifest</li>
<li>Practice analyzing function call parameters and stack</li>
</ol><b>Applicable to:</b><br />
<ol><li>Operating Systems</li>
<li>Assembly Language</li>
</ol><u><b>1. Introduction</b></u><br />
In this tutorial, we show you how Max++ retrieves an "instance specific" decoding key from the PE manifest. By planting a decoding key into the PE manifest, the malware can first distinguish a copy from the other so that it can trace which copy sits on which machine (thus tagging an ID to each victim and can even potentially trace back to malware analyst if the copy is being debugged). One more popular use of it would be making each copy of the binary executable significantly different from each other, thus making a much harder job for virus detectors to define virus signatures.<br />
<br />
We will also practice how to analyze the parameters of a function call and the use of MSDN documentation and other relevant online resources to reverse engineer binary code.<br />
<br />
<u><b>2. Lab Configuration</b></u><br />
(0) Start WinXP image in <u><b>DEBUGGED </b></u>mode. Now in your host system, start a windows command window and CD to "c:\Program Files\Debugging Tools for Windows (x86)" (where WinDBG is installed). Type "<u><b>windbg -b -k com:pipe,port=\\.\pipe\com_12</b></u>" (check the com port number in your VBox instance set up). When WinDbg initiates, types "g" (go) twice to let it continue.<br />
<br />
(1) Now launch IMM in the WinXP instance, clear all breakpoints and hardware breakpoints in IMM (see <u><b>View->Breakpoints</b></u> and <u><b>View->Hardware Breakpoints</b></u>).<br />
<br />
(2) Go to <u><b>0x4012DC </b></u>and set a hardware breakpoint there. (why not software bp? Because that region will be self-extracted and overwritten and the software BP will be lost). Pay special attention that once you go to 0x4012DC, directly right click on the line to set hardware BP (currently it's gibberish code).<br />
<br />
(3) Press<u><b>F9</b></u> several times run to <u><b>0x4012DC</b></u>. You will encounter several breakpoints before 0x4012DC. If you pay attention, they are actually caused by the int 2d tricks (explained in <a href="http://www.blogger.com/cd%20%22c:/Program%20Files/Debugging%20Tools%20for%20Windows%20%28x86%29%22">Tutorial 3</a> and <a href="http://fumalwareanalysis.blogspot.com/2011/10/malware-analysis-tutorial-4-int2dh-anti.html">4</a>, and <a href="http://fumalwareanalysis.blogspot.com/2011/10/malware-analysis-tutorial-5-int2d-anti.html">5</a>). Simply ignore then and continue (using F9) until you hit <u><b>0x4012DC</b></u>.<br />
<br />
Figure 1 shows the code that should be able to see. As you can see, this is right before the call of RtlAddVectoredException, where hardware BP is set to break the LdrLoadDll call (see <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-11-starling.html">Tutorial 11</a> for details). <u><i><b>At this point, the code at 0x3C24FB has not been extracted. If you go to 0x3C24FB at this moment, IMM will complain that this address is not accessible.</b></i></u><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwY824Lshgaeu8tuf06xKBmXnOPpS45_aLSiyOO45sA9pUkglF0nkUNMcKdeRPsWKWehn-aEkpgnh_QlWjxN24f9iwlRq3j49BXfnl1EalZjMddZCgC7CrlmOpeIW3gUaEWXq-lxL5ULk/s1600/c1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwY824Lshgaeu8tuf06xKBmXnOPpS45_aLSiyOO45sA9pUkglF0nkUNMcKdeRPsWKWehn-aEkpgnh_QlWjxN24f9iwlRq3j49BXfnl1EalZjMddZCgC7CrlmOpeIW3gUaEWXq-lxL5ULk/s1600/c1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1: code at 0x4012DC</td></tr>
</tbody></table>(4) Now scroll down about 2 pages and set a <u><b>SOFTWARE BREAKPOINT</b></u> at <u><b>0x401417</b></u>. This is right after the call of LdrLoadDll("lz32.dll"), where Max++ finishes the loading of lz32.dll. Then hit <u><b>SHIFT+F9 </b></u>several times until you reach <u><b>0x401417</b></u> (you will hit 0x7C90D500 twice, this is somwhere inside ntdll.zwMapViewSection which is being called by LdrLoadDll). <br />
<br />
<br />
 <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdtJaTR3WJ33l5wLbd_tnt7knNdgNf2mnPTZkY4JnUjgqmsT5MmCcncck40DPpvSxsTDU1FqKSmI3pKeZpha2zb9nEzPe6EVmFatNSs-b5G6Jz3wS0GslZmw4vscwFZONefJRcfuDAtGc/s1600/c2.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdtJaTR3WJ33l5wLbd_tnt7knNdgNf2mnPTZkY4JnUjgqmsT5MmCcncck40DPpvSxsTDU1FqKSmI3pKeZpha2zb9nEzPe6EVmFatNSs-b5G6Jz3wS0GslZmw4vscwFZONefJRcfuDAtGc/s1600/c2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2: code at 0x401407</td></tr>
</tbody></table> <br />
(6) Now we will set a breakpoint at <u><b>0x3C24FB</b></u>. Goto <u><b>0x3C24FB </b></u>and set a <u><b>SOFTWARE </b><b>BREAKPOINT</b></u> there. Press SHIFT+F9 to run to 0x3C24FB.<br />
<br />
(Figure 3 shows the code that you should be able to see. The first instruction at 0x3C24FB should be <u><b>CMP DWORD PTR SS:[ESP+8], -2</b></u>. You will notice that [ESP+8] is currently -2, and the execution will reach the instruction <u><b>CALL 0x003C23DB</b></u>. Press <u><b>F7 </b></u>to step into function <u><b>0x003C23DB</b></u>.<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghs8lA7BBKznVvLECOxlJqvF4OcF_PG_tln545MFBZq4-yQHy7M7bUTNyzm49HI7ZDuWvaw32kgo1axFiWwt45vfzfM4ym6iko_o5bKuCpnsTWea2xistSD3XNx_HPS4xSHJXAAcHuALw/s1600/c3.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghs8lA7BBKznVvLECOxlJqvF4OcF_PG_tln545MFBZq4-yQHy7M7bUTNyzm49HI7ZDuWvaw32kgo1axFiWwt45vfzfM4ym6iko_o5bKuCpnsTWea2xistSD3XNx_HPS4xSHJXAAcHuALw/s1600/c3.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3: code at 0x3C24FB</td></tr>
</tbody></table><br />
<u><b>3. Background Introduction: Function 0x003C23DB</b></u><br />
The function body of 0x003C23DB is shown in Figure 4. If you look at the comments of the code pane, you might notice that this function is doing a lot of malicious actions. It first retrieve a self-decoding key from the PE manifest. Then it injects a thread into a currently running process and sets a timer, which kills the Max++.exe 10 seconds after the process is terminated. It then infects a number of important system libraries such as ntdll.dll and also randomly picks a system driver to infect. It is not possible to cover all the malicious actions of function 0x003C23DB in one tutorial. We concentrate on the function call at 0x3C23FE (reads decoding key)<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEit1ne_UbhTlN9amENMUTYJNsMOiHmkqgJv0VWupRhyphenhypheno9ZIL33yMTVmTfF-Bg0y_MxchIOZPS819Y9snmiOfEVOLT5r7J7-1eLdLC9ceH8N8qee-JydPbOhhoupz5RcL58raImt7xfCgAg/s1600/d1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" sda="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEit1ne_UbhTlN9amENMUTYJNsMOiHmkqgJv0VWupRhyphenhypheno9ZIL33yMTVmTfF-Bg0y_MxchIOZPS819Y9snmiOfEVOLT5r7J7-1eLdLC9ceH8N8qee-JydPbOhhoupz5RcL58raImt7xfCgAg/s1600/d1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4: The Malicious Actions</td></tr>
</tbody></table><br />
<u><b>4. RtlAdjustPrivilege at 0x3C23F3.</b></u><br />
Let's first study the instruction "CALL DS:[3D10E8]" at 0x3C23F3 (as shown in Figure 4 and Figure 5). Note that before the call of the entry function by Max++ itself, it has properly set up the DS register. So when the execution comes to 0x003C23F3, the value of <u><b>DS + 0X3D10E8</b></u> is the entry address of the <u><b>ntdll.RtlAdjustPrivilege</b></u> function. IMM is smart enough to show the hint in the comments area, which is very nice (see Figure 2). Our job is to try to figure out, what is the semantics of all the parameters of this call. Doing a simple Google search of RtlAdjustPrivilege (<u><b>again, please do the search in the VBox instance to avoid potential drive-by-download attack</b></u>) leads us to the documentation such as [<a href="http://forum.sysinternals.com/tip-easy-way-to-enable-privileges_topic15745.html">1</a>] and [<a href="http://doxygen.reactos.org/d9/db7/lib_2rtl_2security_8c_a1cf697d376343212dfa89ac97b0c30d8.html">2</a>]. We soon learn that the RtlAdjustPrivilege function has four parameters:<br />
(1)ULONG Privilege<br />
(2) BOOLEAN Enable<br />
(3) BOOLEAN CurrentThread<br />
(4) OUT Boolean Enabled<br />
<br />
<u><b>Then the question is: what are the corresponding values in the stack?</b></u><br />
<br />
Now look at the stack contents in Figure 5. You can immediately infer that <u><b>0x14 </b></u>is the <u><b>Privilege</b></u>, Enable value is 0x1 (true), CurrentThread is 0x0, and ENABLED value is 0x12D623 (why? because the output value will be stored at that address -- to verify this, read the source code at line 00174 of [<a href="http://doxygen.reactos.org/d9/db7/lib_2rtl_2security_8c_a1cf697d376343212dfa89ac97b0c30d8.html">2</a>] ).<br />
<br />
<u><b>Challenge 1:</b></u> What does the value 0 mean for CurrentThread? [hint: you have to read the source code in [<a href="http://doxygen.reactos.org/d9/db7/lib_2rtl_2security_8c_a1cf697d376343212dfa89ac97b0c30d8.html">2</a>])<br />
<br />
Now the most intriguing part to us is: what is the semantics of 0x14 for Privilege? We have to blame the macro definition of constants of the C language (what if the WINNT designers have used enumerated types, that makes our job much easier!) If you read [<a href="http://forum.sysinternals.com/tip-easy-way-to-enable-privileges_topic15745.html">1</a>] carefully, you will notice that it's the <u><b>SeDebug privilege</b></u>. [note: the decimal value of 0x14 is 20].<br />
<br />
Why does Max++ need the SeDebug privilege? If you read the explanation in [1], you will notice that once a process has SeDebug, it is able to open any other process in the system, which is perfect for accomplishing the jobs like injecting another thread into a currently running process (see Figure 1 in Section 3).<br />
<table class="memname"><tbody>
<tr><td class="paramtype"></td><td class="paramtype"></td><td class="paramtype"></td><td class="paramname"><br />
</td><td class="paramname"></td><td class="paramname"><br />
</td></tr>
<tr><td class="paramkey"></td><td></td><td class="paramtype"></td><td class="paramname"><br />
</td></tr>
<tr><td class="paramkey"></td><td></td><td class="paramtype"></td><td class="paramname"><br />
</td></tr>
<tr><td class="paramkey"></td><td></td><td class="paramtype"></td><td class="paramname"><br />
</td></tr>
</tbody></table><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjpIpZ8N8-IqqVXwnB2OvxyCAM9LnSjDlshARe6pEkhmearbztD6dJYGIwZSNaEFRg4Q5Qu4AFlAKyAH_ZvZitpUTIJcLlsCslnGAtZjyC2q4r-KRzt6gva7kpzqdUVIP6mFMQgSfzPz8/s1600/d2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" sda="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjpIpZ8N8-IqqVXwnB2OvxyCAM9LnSjDlshARe6pEkhmearbztD6dJYGIwZSNaEFRg4Q5Qu4AFlAKyAH_ZvZitpUTIJcLlsCslnGAtZjyC2q4r-KRzt6gva7kpzqdUVIP6mFMQgSfzPz8/s1600/d2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5: RtlAdjustPrivilege</td></tr>
</tbody></table><br />
<u><b>Section 5. Analysis of the Function call at 0x3C23FE (CALL lz32.003C1129)</b></u><br />
Now, let's delve into the function call at 0x3C23FE (see Figure 4). F7 to step into it,<br />
Figure 7 shows the function body of 0x003C1129. It gives you the general idea of what this function is doing.<br />
There are several important calls: at 0x003C1131, it calls <u><b>getModuleHandleW </b></u>to get the handle of the current process, and then at 0x3C1145 it calls <u><b>LdrFindResource</b></u>_U to find some resources related to this process, and then at 0x3C1159, it calls <u><b>LdrAccessResource</b></u>. At 0x003C116B it calls strstr (to search for a string "<description>"). Then it takes out the decode-key "11001800" and saves it to somewhere in the stack at 0x003C1185.<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWVe_3suGI-XbXXyl1sYmIQsdR9T9b1USdcF_0YdaeiQvuHU1TmYX7mq4gJzDj69md-xXgvg4AuBltiodBOTScMBciCYTkWOqZR7IFbwV-ixh754vi-Lzx3xDLwIFrhuju3Y8kolOqedo/s1600/d3.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" sda="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWVe_3suGI-XbXXyl1sYmIQsdR9T9b1USdcF_0YdaeiQvuHU1TmYX7mq4gJzDj69md-xXgvg4AuBltiodBOTScMBciCYTkWOqZR7IFbwV-ixh754vi-Lzx3xDLwIFrhuju3Y8kolOqedo/s1600/d3.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 7: Function body of 0x003C1129</td></tr>
</tbody></table><br />
<u><b>Challenge 2</b></u>.Explain the semantics of the parameters of all system calls in the function body (e.g., getModuleHandleW and LdrAccessResource).<br />
<br />
<u><b>Challenge 3.</b></u> Explain how is the decoding key "11001800" taken out?<br />
<br />
<u><b>Challenge 4***. </b></u>Can you find out how is "11001800" used in the later code of Max++? (hint: use Data breakpoint).<br />
<br />
<br />
<br />
<u><b>References</b></u><br />
1. "<b>Topic: Tip: Easy way to enable privileges", available at </b>http://forum.sysinternals.com/tip-easy-way-to-enable-privileges_topic15745.html<br />
2. ReactOS Doxygen, "RtlAdjustPrivilege source code", available at http://doxygen.reactos.org/d9/db7/lib_2rtl_2security_8c_a1cf697d376343212dfa89ac97b0c30d8.htmlUnknownnoreply@blogger.com16tag:blogger.com,1999:blog-8770073098084592029.post-36698349872115154082012-01-26T13:32:00.000-08:002012-01-26T17:43:04.074-08:00Malware Analysis Tutorial 13: Tracing DLL Entry Point<b>Learning Goals</b>:<br />
<ol><li>Understand C calling convention</li>
<li>Practice reverse engineering</li>
</ol><b>Applicable to:</b><br />
<ol><li>Operating Systems</li>
<li>Assembly Language</li>
</ol><u><b>1. Introduction</b></u><br />
In <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-11-starling.html">Tutorial 11</a>, we have shown you the trick played by Max++ to load its own malicious executable using the "corpse" of another DLL called "lz32.dll".Beginning from this tutorial, we will analyze the functionality of the malicious DLL. In the following, we use "<u><b>lz32.dll</b></u>" to refer to this malicious code starting at <u><b>0x003C24FB</b></u>. (In your VBox instance, this entry address might vary. Check <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-11-starling.html">Tutorial 11</a> for how to find out the correct entry address of lz32.dll).<br />
<br />
Today, we will discuss some basic background information related to DLL entry point and analyze the first part of lz32.dll (it's not the real "lz32.dll", but the malicious code of Max++ planted into it).<br />
<br />
<u><b>2. Lab Configuration</b></u><br />
(1) clear all breakpoints and hardware breakpoints in IMM (see <u><b>View->Breakpoints</b></u> and <u><b>View->Hardware Breakpoints</b></u>).<br />
(2) Go to <u><b>0x4012DC </b></u>and set a hardware breakpoint there. (why not software bp? Because that region will be self-extracted and overwritten and the software BP will be lost). Pay special attention that once you go to 0x4012DC, directly right click on the line to set hardware BP (currently it's gibberish code).<br />
(3) Press <u><b>SHIFT+F9</b></u> to run to <u><b>0x4012DC</b></u>. Figure 1 shows the code that should be able to see. As you can see, this is right before the call of RtlAddVectoredException, where hardware BP is set to break the LdrLoadDll call (see <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-11-starling.html">Tutorial 11</a> for details). <u><i><b>At this point, the code at 0x3C24FB has not been extracted. If you go to 0x3C24FB at this moment, IMM will complain that this address is not accessible.</b></i></u><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwY824Lshgaeu8tuf06xKBmXnOPpS45_aLSiyOO45sA9pUkglF0nkUNMcKdeRPsWKWehn-aEkpgnh_QlWjxN24f9iwlRq3j49BXfnl1EalZjMddZCgC7CrlmOpeIW3gUaEWXq-lxL5ULk/s1600/c1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" gda="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwY824Lshgaeu8tuf06xKBmXnOPpS45_aLSiyOO45sA9pUkglF0nkUNMcKdeRPsWKWehn-aEkpgnh_QlWjxN24f9iwlRq3j49BXfnl1EalZjMddZCgC7CrlmOpeIW3gUaEWXq-lxL5ULk/s1600/c1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1: code at 0x4012DC</td></tr>
</tbody></table>(4) Now scroll down about 2 pages and set a <u><b>SOFTWARE BREAKPOINT</b></u> at <u><b>0x401417</b></u>. This is right after the call of LdrLoadDll("lz32.dll"), where Max++ finishes the loading of lz32.dll.<br />
<br />
<br />
 <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdtJaTR3WJ33l5wLbd_tnt7knNdgNf2mnPTZkY4JnUjgqmsT5MmCcncck40DPpvSxsTDU1FqKSmI3pKeZpha2zb9nEzPe6EVmFatNSs-b5G6Jz3wS0GslZmw4vscwFZONefJRcfuDAtGc/s1600/c2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" gda="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdtJaTR3WJ33l5wLbd_tnt7knNdgNf2mnPTZkY4JnUjgqmsT5MmCcncck40DPpvSxsTDU1FqKSmI3pKeZpha2zb9nEzPe6EVmFatNSs-b5G6Jz3wS0GslZmw4vscwFZONefJRcfuDAtGc/s1600/c2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2: code at 0x401407</td></tr>
</tbody></table> <br />
(6) Now we will set a breakpoint at <u><b>0x3C24FB</b></u>. Follow the instructions below:<br />
Press SHIFT+F9 several times, until you hit 0x7C90D500 (this is somwhere inside ntdll.zwMapViewSection which is being called by LdrLoadDll). Goto <u><b>0x3C24FB </b></u>and set a <u><b>SOFTWARE </b><b>BREAKPOINT</b></u> there. (You will see a warning which says your BP is out of the range. This is because the malware author did not do a good job at resetting the binary PE information (executable code section size messed up - see <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-12-debug.html">Tutorial 12</a> for details). It should be fine, just click ok.<br />
<br />
(7) If you hit SHIFT+F9 (probably twice), you will hit 0x3C24FB. <u><b>If you hit 0x401417 directly, something wrong is with IMM (strangely, I cannot explain). You have to RESTART (Debug->Restart), and repeat steps (1) to (6) [yes, clear all BP and hardBPs). </b></u>The current sequence should be you hit 0x7C90D500 twice, and then hit 0x3C24FB. This is because the LdrLoadDll will try to call the entry point of the DLL.<br />
<br />
(Figure 3 shows the code that you should be able to see. The first instruction at 0x3C24FB should be <u><b>CMP DWORD PTR SS:[ESP+8], -2</b></u>. If you execute several steps, you might notice that it soon returns, because the value at [ESP+8] is 1.<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghs8lA7BBKznVvLECOxlJqvF4OcF_PG_tln545MFBZq4-yQHy7M7bUTNyzm49HI7ZDuWvaw32kgo1axFiWwt45vfzfM4ym6iko_o5bKuCpnsTWea2xistSD3XNx_HPS4xSHJXAAcHuALw/s1600/c3.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" gda="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghs8lA7BBKznVvLECOxlJqvF4OcF_PG_tln545MFBZq4-yQHy7M7bUTNyzm49HI7ZDuWvaw32kgo1axFiWwt45vfzfM4ym6iko_o5bKuCpnsTWea2xistSD3XNx_HPS4xSHJXAAcHuALw/s1600/c3.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3: code at 0x3C24FB</td></tr>
</tbody></table><br />
(9) Shift +F9 again, you will be hitting <u><b>0x401417, </b></u>and then SHIFT+F9 again, you will be hitting 0x3C24FB again! You might notice that now [ESP+8] has value -2 and if you F7, you will trace into a lot of details of the malicious logic.<br />
<br />
Up to this point, you are doing it right. If there is anything messed up, <u><i><b>you have to restore the snapshot because Max++ automatically removes its binary executable from the disk drive </b></i></u>so that you will not be able to find it again.<br />
<br />
<br />
<u><b>2. Background Information of DLL Entry</b></u><br />
<br />
DLLs, like .exe files, can have an entry point. This entry function will be executed when the DLL is loaded by system calls such as LdrLoadDLL(). MSDN has tons of excellent articles on it and you can read [<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682596%28v=vs.85%29.aspx">1</a>] for details. The following sample declaration is from [1], an DLL entry function takes three parameters, see below:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;">BOOL WINAPI DllMain(</span></div><div style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"> HINSTANCE <u><b>hinstDLL</b></u>, // handle to DLL module </span></div><div style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"> DWORD <u><b>fdwReason</b></u>, // reason for calling function </span></div><div style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"> LPVOID <u><b>lpReserved </b></u>) // reserved {...}</span></div><br />
<u><b>Challenge 1:</b></u> Note the code at 0x3C24FB (Figure 3) is checking the value of [ESP+8]. Which parameter is stored at ESP+8?<br />
<br />
We are particularly interested in the fwdReason. Where is it defined? Reading [<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682596%28v=vs.85%29.aspx">1</a>] you can find that there are some macros defined for fwdReason such as DLL_PROCESS_ATTACH (when a process first attaches the DLL), DLL_THREAD_ATTACH (when the thread of a process has it attached) etc. [1] does not provide information on the real integer values of these macros, but a simple google search of "#define DLL_PROCESS_ATTACH" yields the values [<i>again! do the google search in your VM. Many sites hosting MS sources can be harmful!</i>]. These values range from 1 to 8. For example, value 1 denotes DLL_PROCESS_ATTACH. This is the value of [ESP+8] when 0x3C24FB is hit the first time (which is called by LdrLoadDLL).<br />
<br />
<u><b>3. Analysis of Max++ </b></u><br />
<br />
If you pay attention to the first couple of instructions at 0x3C24FB, one natural question is:<br />
<u><b>Challenge 2: </b></u>Why is the malware compare [ESP+8] with -2? What is the motivation for doing this?<br />
<br />
The motivation is that, when it's a legal invocation (e.g., placed by LdrLoadDLL), the code at 0x3C24FB will return immediately (without doing any harm). Why? because, recall in <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-12-debug.html">Tutorial 12</a>, Max++ cut in LoadLdrDll and actually LoadLdrDll did not finish gracefully (some kernel structure information is not set up correctly). These information has be be properly set up, because the code can NOT call external functions (e.g., those provided by ntdll). Max++ does have to set up all these information by itself, and manually call the entry function at 0x3C24FB. Well, before calling it, it sets up the second parameter (fwdReason) to -2 (which is a value that will NEVER be used by a normal call of DLL entry point), so that the code knows that it's the call from Max++.<br />
<br />
<u><b>Last challenge of the day:</b></u><br />
<u><b>Challenge 3: </b></u>Can you find out which instruction calls 0x3C24FB the second time (which provides -2 for fwdReason)? [hint: check out the stack contents] Look at how 0x3C24FB is called. Can a static analysis tool find out that 0x3C24FB is called by the Max++ code?<br />
<br />
<u><b>References</b></u><br />
1. Microsoft, "Dynamic-Link Library Entry-Point Function",<br />
available at <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682596%28v=vs.85%29.aspx">http://msdn.microsoft.com/en-us/library/windows/desktop/ms682596(v=vs.85).aspx</a><br />
2.<br />
<br />
<ol></ol>Unknownnoreply@blogger.com200tag:blogger.com,1999:blog-8770073098084592029.post-50335965828904455342012-01-18T14:12:00.000-08:002012-01-18T14:12:12.020-08:00Malware Analysis Tutorial 12: Debug the Debugger - Fix Module Information and UDD File<b>Learning Goals</b>:<br />
<ol><li>Understand how debugger saves debugger information</li>
<li>Know how to use binary editor to examine file contents</li>
<li>Trouble shooting and fix issues of debuggers when necessary</li>
</ol><b>Applicable to:</b><br />
<ol><li>Assembly Language.</li>
<li>Computer Security.</li>
<li>Programming Language Principles.</li>
<li>Operating Systems.</li>
</ol><br />
<u><b>1. Introduction</b></u><br />
In <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-11-starling.html">Tutorial 11</a>, we have shown you the trick played by Max++ to load its own malicious executable using the "corpse" of another DLL called "lz32.dll". The basic idea is to cut in the <u><b>LdrLoadDll </b></u>call and reset the base address and other relevant information of the module, without loading the executable of lz32.dll from its file (while the malicious PE has been copied into that memory area). This is achieved by setting up a hardware breakpoint inside LdrLoadDll and the "<u><b>surgery</b></u>" is performed by the vectored exception handler configured by Max++ in advance.<br />
<br />
Now, one side-effect of Max++'s "surgery" on Lz32.dll is that, <u><b>we are no longer able to make comments in that particular area of "lz32.dll"</b></u>. When you try to place comments on the code (starting from 0x003C24FB, the starting addr of "lz32.dll"), they will not be properly saved by IMM. The next time you load Max++ in IMM, all comments related to lz32 will be lost! The reason is that Max++'s surgery is incomplete -- it did not fix the entire kernel structure of lz32.dll and the mal-formated data structure fails the internal analysis of IMM. When IMM tries to create a <u><b>UDD </b></u>file (a file records the debugging information for each module in a binary executable), it fails.<br />
<br />
Clearly, there are two ways to fix this:<br />
(1) make sure that all kernel data related to lz32.dll are properly reset [which can be a huge task], and<br />
(2) debug into IMM and tweak its control flow so that it can work correctly given the malformed data.<br />
<br />
We will take approach 2 and show you how to debug the IMM debugger and fix issues on the spot. <br />
<br />
<br />
<br />
<u><b>2. Lab Configuration</b></u><br />
<u><b>2.1 Software You need</b></u><br />
You need the following software tools. They can be easily downloaded from Internet: (1) HxD binary editor and (2) NotePad++.<br />
<br />
<u><b>2.2 Lab Configuration</b></u><br />
You can either continue from <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-10-tricks-for.html">Tutorial 10</a>, or follow the instructions below to set up the lab. Refer to <a href="http://fumalwareanalysis.blogspot.com/2011/08/malware-analysis-tutorial-reverse.html">Tutorial 1</a> and <a href="http://fumalwareanalysis.blogspot.com/2011/10/malware-analysis-tutorial-4-int2dh-anti.html">Tutorial 4</a> for setting up VBOX instances and WinDbg. We now proceed to the steps that we need for this tutorial:<br />
<br />
(0) -- <u><b>IT IS IMPORTANT TO TAKE A SNAPSHOT</b></u> after you've installed HxD and NotePad. At this moment, the system is still clean. <u><b>After step (3)</b></u>, the system will be infected, later, whenever you restart the system, you have to<u><b> restore the snapshot</b></u> to start from a clean system!!!<br />
--------------------------------------------------------------------------------------------------<br />
(0.5) restore the snapshot as discussed in step (0)<br />
<br />
(1) In IMM, clear all hardware breakpoints and software breakpoints.<br />
<br />
(2) Go to <u><b>0x4012DC </b></u>and set a hardware breakpoint there (the instruction at 0x4012DC should be <u><b>CALL 0x413652</b></u>). Press <u><b>F9 </b></u>to run to 0x4012DC.<br />
This is the point right before the tricks introduced in <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-11-starling.html">Tutorial 11</a> (which sets up hardware breakpoint inside zwMapViewSection and then calls LdrLoadDLL).<br />
At this point, you might want to straighten out the display of the assembly code of IMM (if there is a large gibberish section of DB instructions). Highlight and select one or two pages of DB instructions, right click and then select <u><b>Analysis -> During Next Analysis Treat Selection As -> Command,</b></u> and then right click and select <u><b>Analysis -> Code Analysis</b></u>.<br />
<br />
(3) Now at <u><b>0x401419 </b></u>(instruction is <u><b>MOV [ESP-2E8]: ESI</b></u>) set a <u><b>SOFTWARE BREAKPOINT</b></u> (by pressing <u><b>F2</b></u>), and then press <u><b>Shift+F9</b></u> (at least twice) until you hit 0x401419.<br />
Shift+F9 is to RUN (but passing all exceptions to user code). This way we allow the vectored exception handler set by Max++ to be effective. Hence, the malicious code will be layed in the "body" of lz32.dll. Notice that when you hit the 0x401419, the code of the fake lz32.dll has already been executed (which infects a number of driver files and modifies system registry etc.). We will introduce the analysis of this code in future tutorials. At this moment, we are interested in making comments working in IMM.<br />
<br />
(4) At this point, if you click IMM <u><b>View->Executable Modules</b></u> (as shown in Figure 1, the first row), you can find a new module is loaded for "lz32.dll". Its base address is <u><b>0x3C0000 </b></u>(could vary depending on the run-time behavior of the system). Using the trick introduced in Tutorial 9, we can find the entry point of the module to be <u style="color: red;"><b>0x3C24FB</b></u>.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOz5SwKH25yCyR13wxYmd-obOIwY_SSerTz6FqHe3OuLfew4dxBHlkrBwbGPMyEoqr8xRAV0CrVS75kCzQlYdYLkDfwgF4Xr0Cw4ZrCqwDqTiGKRdaOUh8gWlQiEtZz58la43UMQupLDE/s1600/b1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" kba="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOz5SwKH25yCyR13wxYmd-obOIwY_SSerTz6FqHe3OuLfew4dxBHlkrBwbGPMyEoqr8xRAV0CrVS75kCzQlYdYLkDfwgF4Xr0Cw4ZrCqwDqTiGKRdaOUh8gWlQiEtZz58la43UMQupLDE/s1600/b1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. New "lz32.dll" Module</td></tr>
</tbody></table>(5) Now in the code pane you can right click and goto 0x3C24FB. The first instruction should be "<u><b>CMP [ESP+8], -2</b></u>". You can set up some comments on any code below this instruction. To save your comments, goto to "<u><b>View -> Executable Modules</b></u>", right click on lz32.dll and select "<u><b>Actualize</b></u>" and then "<u><b>save UDD files now</b></u>". Stop the process being debugged and exit from IMM. Restart IMM again and repeat steps (1) to (5) again, <u><b>you will notice that all your comments in the previous IMM session are gone!</b></u><br />
<br />
<u><b>3. Introduction of UDD Format</b></u><br />
The missing comments problem is caused by IMM. When the module information structure is mal-formed, IMM will not behave correctly when analyzing its code section, and hence will not create a corresponding UDD file for lz32.dll (that's the reason all your comments are lost). IMM creates UDD files to record the debugging information (e.g., comments created by users). This section introduces some background information about the UDD file format.<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX-cMpA26UcAaWsSPPbfpoP0ScYz6HFkZAqPDKEveUDxAEU5iNLx6Pb-deCe9FRVwA_MdDNJlsEpbbDq_8Gn8gN6UOVdIK_xqWWgchFnh8kVBtLpq_dK7qojoQuWs_kxUXUc1JzFdPMYA/s1600/b2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" kba="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX-cMpA26UcAaWsSPPbfpoP0ScYz6HFkZAqPDKEveUDxAEU5iNLx6Pb-deCe9FRVwA_MdDNJlsEpbbDq_8Gn8gN6UOVdIK_xqWWgchFnh8kVBtLpq_dK7qojoQuWs_kxUXUc1JzFdPMYA/s1600/b2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. UDD Files</td></tr>
</tbody></table><br />
There are several simple fact about UDD files:<br />
(1) All UDD files are located in the Immunity Debugger folder (e.g., c:\Program files\Imm Inc\Immunity Debugger), as shown in Figure 2. <br />
(2) For each module that is analyzed by IMM (i.e., its code is shown at least once in the IMM code pane), IMM will create a corresponding UDD file. For example, look at Figure 2 (to analyze Max++, we once stepped into ntdll, and there is a corresponding ntdll.udd). The ".bak" files are the temporary UDD files.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioja93yj5VSWC9D2XYjAvhMmg_6t3hGoy9JgTzQErpoVYnLLbQrMy_Dd76Cn3Dxp81nRK_N35RYe6cKoiPHiwUSwosHQsLafVLU_mm8Bg3_ORA6-GOjVuMktCGO7-T2heQtwlux_FbULs/s1600/b3.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" kba="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioja93yj5VSWC9D2XYjAvhMmg_6t3hGoy9JgTzQErpoVYnLLbQrMy_Dd76Cn3Dxp81nRK_N35RYe6cKoiPHiwUSwosHQsLafVLU_mm8Bg3_ORA6-GOjVuMktCGO7-T2heQtwlux_FbULs/s1600/b3.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. Snapshot of Max++_Downloader.udd (in Notepad)</td></tr>
</tbody></table><br />
A UDD file is a collection of records while each record occupies a line. Each record begins with some binary data, and then continued with the corresponding comment by the user. For example, in Figure 3, we displays a fragment of the Max++ download.udd. You can see that the file (opened by Notepad++) corresponds to the comments in the IMM debugger window.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRV6vZ9rvJiKfqtwyMWnWF6DO4SUnoVNwAOvO6OK_1BpxKD5z8syV4kxGmqVCILmoySNTjnfKch4FVxrMTft8hP67JbzI-a_Z0s_OfM3IW-UbNB1eSrWf6Y9kV7VBerfJgRriELW1_9Ng/s1600/b4.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRV6vZ9rvJiKfqtwyMWnWF6DO4SUnoVNwAOvO6OK_1BpxKD5z8syV4kxGmqVCILmoySNTjnfKch4FVxrMTft8hP67JbzI-a_Z0s_OfM3IW-UbNB1eSrWf6Y9kV7VBerfJgRriELW1_9Ng/s1600/b4.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Same UDD file in HxD binary editor</td></tr>
</tbody></table><br />
<br />
So far, there is no complete documentation on UDD format, however, it's easy to infer the meaning of the binary data at the beginning of each record. Look at the "ENTRY PC!" comment in Figure 4 and its subsequent comment "Standard stack protection for function call".<br />
<br />
The binary data before "ENTRY PC!" is<br />
0x <u><b>55 73 36</b></u> <u><b>13 00 00 00</b></u> <u><b>C8 3B 01 00</b></u> .... <u><b>00 0A</b></u><br />
Clearly the tag "55 73 36" indicates the type of the record (a user comment) - this is the same for the next comment "Standard stack protection". The next 4 bytes "13 00 00 00" indicates that the record length is 0x13 bytes, and then "<u><b>C8 3B 01 00</b></u>" indicate its relative location (beginning from the module base address) - you can verify this in Figure 3 (the location of the comment is <u><b>0x413BC8</b></u> - note the reversed byte sequence of integers). Clearly "00 0A" is used to end the record.<br />
<br />
It is straightforward to infer how IMM works with a UDD file. For each module, IMM gets its base address and for each user comment, it calculates its offset and place the record in the UDD file. Clearly, if IMM's analysis fails somehow, the UDD file will not be created and thus all user comments will be lost.<br />
<br />
<u><b>4. Debug the Debugger</b></u><br />
Now we show the tricks to debug into the IMM debugger and fix the issues. Our purpose is to redirect the control flow of IMM so that it would work normal. Follow the instructions below:<br />
(1) Start IMM, and then open the executable of IMM (located in c:\Program Files\Imm Inc\Immunity Debugger). Press F9 to run it. In this case, we have two IMM instances, we call the first one IMM1 and the second one IMM2.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9Eb0sXsox9xglJ7O7LMIeSntB0mXENcndRhlWV2p3ZkchYg8nIBympctwMe4uyBfLnCbZkclx9OYdbvasr6dH0F7FAQU88zqltlQYZhxDzL2Fb9GmdEn3GeQdOK_F59v2mk8HMJHc-W8/s1600/c1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" nfa="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9Eb0sXsox9xglJ7O7LMIeSntB0mXENcndRhlWV2p3ZkchYg8nIBympctwMe4uyBfLnCbZkclx9OYdbvasr6dH0F7FAQU88zqltlQYZhxDzL2Fb9GmdEn3GeQdOK_F59v2mk8HMJHc-W8/s1600/c1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5. Set Breakpoint on IMM</td></tr>
</tbody></table>(2) In IMM2, open the Max++ binary executable.<br />
(3) Now in IMM1, <u><b>View -> Executable Modules</b></u> and then right click on IMM (the first one) and then right click and select <u><b>View -> Names.</b></u> Basically, this shows the list of exported functions. You might immediately notice that there is something that we are interested in: the function <u><b>Analyzecode </b></u>at <u><b>0x00411020</b></u>(see Figure 5).<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZCGSTmHeJPi3MgcNJvZuJCSkf7vZbkU7AbOOWyK6QlgotQtHo_tEFIwpmuWtoPZDVBpD7Bzqa_MCVZUrrgfVZ1jaDlacSwMbg2Z5_NLl-U_OYrkceMQEvIMet9PEJf8ofiJWcfhrVcvI/s1600/c2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" nfa="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZCGSTmHeJPi3MgcNJvZuJCSkf7vZbkU7AbOOWyK6QlgotQtHo_tEFIwpmuWtoPZDVBpD7Bzqa_MCVZUrrgfVZ1jaDlacSwMbg2Z5_NLl-U_OYrkceMQEvIMet9PEJf8ofiJWcfhrVcvI/s1600/c2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6. Python Script to Trigger Analyzecode</td></tr>
</tbody></table><br />
(4) We would like to trigger the Analyzecode() of IMM2 and then analyze its logic in IMM1. In IMM2, repeat Steps (1) to (3) in Section 2.2 until you hit 0x401419.<br />
<br />
(5) Now in IMM2, click to open the <u><b>python script window</b></u> (it's the <u><b>second button</b></u> in the toolbar, right after the "open file" button). Type the first two commands:<u><b> mod = getModule('ntdll.dll'); mod.Analyse()</b></u> (see Figure 6). You will then hit the breakpoint in IMM1!<br />
Step through the instructions in IMM1 and make a good memory of it. When the function Analyzecode() returns, press F9 to let it run and you will go back to IMM2.<br />
Now do the same thing for lz32.dll. <u><b>Did you notice there is something different? </b></u><br />
<br />
<br />
<u><b>5. Challenge of the Day</b></u><br />
(1) The control flow of two analyzecode() sessions depart from a <u><b>CMP EDX, 7 </b></u>instruction. Find out where it is.<br />
(2) The value contained in EDX is an important attribute of a DLL module. Can you find out its meaning? [hint: codeSize. Prove it]<br />
(3) Can you modify the control flow so that analyzecode() is successfully completed? After that, you can repeat steps (4) and (5) in section 2.2 and make comments. In the c:\program...\immunity debugger\ folder, you can verify that the lz32.udd file is created and your comments will be recorded.Unknownnoreply@blogger.com30tag:blogger.com,1999:blog-8770073098084592029.post-44930951384632965062012-01-10T16:32:00.000-08:002012-01-16T17:41:20.670-08:00Malware Analysis Tutorial 11: Starling Technique and Hijacking Kernel System Calls using Hardware Breakpoints<b>Learning Goals</b>:<br />
<ol><li>Understand hardware breakpoint</li>
<li>Understand vectored/structured exception handling</li>
<li>Understand the tricks that interrupt module loading</li>
</ol><b>Applicable to:</b><br />
<ol><li>Operating Systems.</li>
<li>Computer Security.</li>
<li>Programming Language Principles.</li>
<li>Assembly Language.</li>
</ol><u><b>1. Introduction</b></u><br />
Starling is a bird that steals nests of other birds. In this tutorial, you will look at a "starling" technique used by Max++ to run its own malicious code using the "body" of another benign module named "lz32.dll". <br />
<br />
<u><b>2. Lab Configuration</b></u><br />
You can either continue from <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-10-tricks-for.html">Tutorial 10</a>, or follow the instructions below to set up the lab. Refer to <a href="http://fumalwareanalysis.blogspot.com/2011/08/malware-analysis-tutorial-reverse.html">Tutorial 1</a> and <a href="http://fumalwareanalysis.blogspot.com/2011/10/malware-analysis-tutorial-4-int2dh-anti.html">Tutorial 4</a> for setting up VBOX instances and WinDbg. <u><b>We will continue to analyze the function starting at 0x4014F9. </b></u><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl75jzGoFFvuOoKPzm7zquUwx9T1lPBcioJ6xih8xu4BXe2cySnbsfcvgwyTPY473O4UkCZbsA55WtmG9toe-HVk-Vv0whmNwqfbBxbG6IV2s0FpX-Un08ic6_KeCKF2mvCl5kBN80yj8/s1600/b1.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl75jzGoFFvuOoKPzm7zquUwx9T1lPBcioJ6xih8xu4BXe2cySnbsfcvgwyTPY473O4UkCZbsA55WtmG9toe-HVk-Vv0whmNwqfbBxbG6IV2s0FpX-Un08ic6_KeCKF2mvCl5kBN80yj8/s1600/b1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Function 0x4014F9 to Analyze</td></tr>
</tbody></table><br />
(1) Clear all hardware breakpoints.<br />
(2) In code pane, right click and go to expression "0x4014F9"<br />
(3) right click and then "breakpoints -> hardware, on execution"<br />
(4) Press F9 to run to 0x4014F9<br />
(4) If you see a lot of DB instructions, select them and right click -> "During next analysis treat them as Command".<br />
(5) Restart Max++ and run to 0x4014F9 again. Select the instructions (about 1 screen) below 0x4014F9, right click -> Analysis-> Analyze Code. You should be able to see all loops now identified by IMM.<br />
<br />
<br />
<u><b>3. Background</b></u><br />
Before we get to the interesting point, we will quickly go through the code before where the Max++ malware sets up a hardware breakpoint. We leave most of the analysis details to you and summarize the functionality of the these code snippets directly.<br />
<br />
<u><b>3.1 Revisit of zwAllocateVirtualMemory </b></u><br />
Recall that in <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-10-tricks-for.html">Tutorial 10</a>, we showed you the trick how Max++ can invoke ntdll system calls without the use of export table. At 0x00401157 it calls 0x004136BF, which does a binary search in the encoded export table and then it jumps to the entry address of <u><b>zwAllocateVirtualMemory</b></u>. Now the interesting point is: what are the parameters of the call? <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZwkKZF16mxCbMGKTLrVIxbsTHIRa86H8-sSdukjA1LlWBIw-3ny_58GHutqnwHNkEyqNghxhuLKpZyjvIRe7x6cSdjoNx5VHj7WSf2yPGfzL6k7iFxJfll4NgEmNGrHn21WpwmCmmE3Y/s1600/d1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" rea="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZwkKZF16mxCbMGKTLrVIxbsTHIRa86H8-sSdukjA1LlWBIw-3ny_58GHutqnwHNkEyqNghxhuLKpZyjvIRe7x6cSdjoNx5VHj7WSf2yPGfzL6k7iFxJfll4NgEmNGrHn21WpwmCmmE3Y/s1600/d1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. Stack Contents</td></tr>
</tbody></table><br />
According to [<a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff566416%28v=vs.85%29.aspx">1</a>], zwAllocateVirtualMemory has 6 parameters, as shown in the following:<br />
<br />
<pre>NTSTATUS ZwAllocateVirtualMemory(
__in HANDLE ProcessHandle,
__inout PVOID *BaseAddress,
__in ULONG_PTR ZeroBits,
__inout PSIZE_T RegionSize,
__in ULONG AllocationType,
__in ULONG Protect
);</pre><br />
The first parameter is the handle to a process within the address space of which a piece of memory will be allocated. Here, its value is 0xFFFF (-1) [see Figure 2], which means the current process. The second parameter (baseAddress) points to the memory word which will hold the base address of the newly allocated memory (note its type is <u><b>inout</b></u>). The last parameter, Protect, its value is 0x0040 [see the 5th word in Figure 2]. From the documentation in [<a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff566416%28v=vs.85%29.aspx">1</a>], we know that the constant values for "Protect" is defined in ntifs.h, or a simple Google search of "#define PAGE_NOACCESS" leads us to the header file directly. [<i><u><b>NOTE: always use virtual machine to perform such Google search. Websites publishing windows source code are often loaded with malicious attack code such as drive-by download!</b></u></i>] We now know that 0x40 is the value of macro "<u><b>PAGE_EXECUTE_READWRITE</b></u>". Did you smell something suspicious? The newly allocated memory will be <u><i><b>executable</b></i></u>!<br />
<br />
So far so good, we know that the beginning address of the new VM (virtual memory) will be stored in 0x0012D648. Right click on 0x0012D648 in the stack and select "Follow in Dump", step over (F8) the call 0x4136BF instruction at 0x00401157, you will notice that the newly allocated memory starts at <u><b>0x00003A00</b></u>. [This value could vary between runs, even if you are using the same VBox instance]<br />
<br />
<br />
<u><b>3.2 Another Layer of Self-Extraction</b></u><br />
Immediately following the zwAllocateVirtualMemory is a big two-layer nested loop (shown in Figure 3), starting from 0x00401567. Its purpose is to extract a section of data from Max++'s address space and copy it into the newly allocated VM starting at 0x00003A00 (the address may vary at run-time). We leave the details of the analysis to you and the following are some questions for you:<br />
<br />
(1) Where is the data from?<br />
(2) What is the size of the code copied into 0x00003A00?<br />
(3) How do you jump out of the two layer nested loop?<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgx5jCV8yVFfIvbCS5aF4sfwSCY8GLahtcy0W4Xr1KJZOmqxyfGJNnkxKI4LQpTMRYv0f3YiurOlbSi3SKNO03-8Cu1S9m7dRNb-bVBacaIipu9GInxrwJ0H8F6eZwBT-2SOOYSrxszueg/s1600/A1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" rea="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgx5jCV8yVFfIvbCS5aF4sfwSCY8GLahtcy0W4Xr1KJZOmqxyfGJNnkxKI4LQpTMRYv0f3YiurOlbSi3SKNO03-8Cu1S9m7dRNb-bVBacaIipu9GInxrwJ0H8F6eZwBT-2SOOYSrxszueg/s1600/A1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. Self-Extraction Again</td></tr>
</tbody></table><br />
<u><b>3.3. First section of 0x4012AB.</b></u><br />
If you successfully get out of the 2-layer loop of section 3.2, you would soon reach function 0x4012AB. This is an important function. Figure 4 shows the first part of this section. Now we get to the first interesting call at 0x4012C9 (see Figure 4). It calls function <u><b>0x004137D1</b></u>. By tracing into the function, you will soon notice that it is actually a call to ntdll function <u><b>RtlNtImageNtHeader</b></u>, which takes a module address as a parameter, and returns a pointer to <u><b>IMAGE_NT_HEADERS</b></u> structure. Read <a href="http://fumalwareanalysis.blogspot.com/2011/12/malware-analysis-tutorial-8-pe-header.html">Tutorial 8 (PE header)</a> for the detailed analysis of the data structure.<br />
<br />
So what is the input parameter of RtlNtImageHeader? It's 0x003A0000 (the newly allocated memory). The return value (pointer to IMAGE_NT_HEADER) is also 0x003A0000. You can verify that it is indeed a pointer to IMAGE_NT_HEADER. <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDur96sis2pAi_3Ad2LzL4EOVRFWcjwUbaQPfqH9i8GyOLaDPRBv3LHwHANgOwvq3GE2mXu245gYgzWSDiXcSaYYkt7BrYTNKSXo7Jsumz0zCUFhiJZrkZId6lFDQQsA2CgTyHaiFmzW4/s1600/b1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" rea="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDur96sis2pAi_3Ad2LzL4EOVRFWcjwUbaQPfqH9i8GyOLaDPRBv3LHwHANgOwvq3GE2mXu245gYgzWSDiXcSaYYkt7BrYTNKSXo7Jsumz0zCUFhiJZrkZId6lFDQQsA2CgTyHaiFmzW4/s1600/b1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. RtlImageNtHeader</td></tr>
</tbody></table>In the memory dump pane, go to 0x003A0000, right click and select <u><b>Special->PE heade</b><b>r</b></u>. (see Figure 5) You will notice that the information is beautifully rendered by the immunity debugger. There are, of course, several interesting points you have to note. For example, the entry point is offset 0x24FB. Also, you can find out the precise entry point of the module (that is 0X003A24FB).<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgA7dnFUlNPzFLu_l41zENpjxfb1hvsQB7op0umFJ0OnMKNOExiMjr6xM3ax22DRVWjsExR_hc9HXMxqJvRt67GGZUf3w81XcaUMn6P-kJonHhhN-8wZXi61b3ag-BUUobIaejQ5alSj1M/s1600/b2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" rea="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgA7dnFUlNPzFLu_l41zENpjxfb1hvsQB7op0umFJ0OnMKNOExiMjr6xM3ax22DRVWjsExR_hc9HXMxqJvRt67GGZUf3w81XcaUMn6P-kJonHhhN-8wZXi61b3ag-BUUobIaejQ5alSj1M/s1600/b2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5. PE Header of the newly extracted binary executable</td></tr>
</tbody></table><u><b>Challenge 1 of the Day: Look at the two instructions starting at 0x4012CE (there is a comparison instruction following them). Explain the logic.</b></u><br />
<br />
<u><b>4. The Starlings Trick: Take the Address Space of Another Module</b></u><br />
Starlings are well known for stealing other birds' nest. In the following, we show a highly skillful technique employed by Max++, which simulates starlings to load the new executable starting from 0x003A0000 using the address space of another module. <u><b>The road map is follows:</b></u><br />
<ol><li>add an exception handler at 0x413657 (all interrupts, including hardware breakpoints, will trigger the code at 0x413657), </li>
<li>set a hardware exception at 0x7C90D500, </li>
<li>load a DLL file named "lz32.dll", </li>
<li>while the OS kernel is loading lz32.dll, the hardware exception triggers the code of 0x413657. It finishes the job of resetting the module address range to 0x003A0000 and avoid the loading of the real code from the "lz32.dll" file into the module's address space. </li>
</ol><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"></td></tr>
<tr><td class="tr-caption" style="text-align: center;"></td></tr>
</tbody></table>Now let us examine each of these steps one by one. <br />
<br />
<u><b>4.1 Add Vectored Exception Handler</b></u><br />
At 0x4012E4 (see Figure 6), the malware calls 0x413776 (again, it's a <a href="http://fumalwareanalysis.blogspot.com/2012/01/malware-analysis-tutorial-10-tricks-for.html">trick </a>to avoid the use of export table to call ntdll functions) to invoke <u><b>RtlAddVectoredExceptionHandler</b></u>. For an introduction of Structured Exception Handlers, see <a href="http://fumalwareanalysis.blogspot.com/2011/09/malware-analysis-3-int2d-anti-debugging.html">Tutorial 3</a>. It installs <u><b>0x00413657</b></u> as the first handler for all exceptions, including hardware breakpoints, any interrupt will trigger the code at <u><b>0x00413657 </b></u>first.<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0c2ZjAipQWf7Fard1JXm1Kuvckz9pKtps4dbBgm54eqesxta-UOfMSI34m9S5c6kHMhP0ZDbi8R4z0bNU7j_zaExvb2AgZnu1dN5EP9TESkrEB5j8IJaoZ6JZuqtoXIFqFHiSOFuF3n0/s1600/a3.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0c2ZjAipQWf7Fard1JXm1Kuvckz9pKtps4dbBgm54eqesxta-UOfMSI34m9S5c6kHMhP0ZDbi8R4z0bNU7j_zaExvb2AgZnu1dN5EP9TESkrEB5j8IJaoZ6JZuqtoXIFqFHiSOFuF3n0/s1600/a3.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6. Set up Vectored Exception Handler</td></tr>
</tbody></table><br />
<br />
<u><b>Challenge 2 of the Day: </b></u>(1) show the parameters of the RtlAddVectoredException; (2) If we run Max++ on a different computer, would the value of exception handler entry take a value other than 0x00413657?<br />
<br />
<u><b>Challenge 3 of the Day: </b></u>(1) at 0x401314, Max++ calls 0x4136E4. Analyze which system function it is actually invoking. (2) At 0x401346 (call 0x413811), it is actually calling RtlPushFrame. Explain its purpose. (3) At 0x00401360 (call 0x413701), it is actually calling zwMapViewOfSection. Explain its purpose. (4) Combining (1), (2), and (3), what do you think the malware is trying to do?<br />
<br />
<u><b>4.2 Set Hardware Breakpoint 0x7C90D500</b></u><br />
We now list some details of the second step. The key is the function 0x413736 as shown in Figure 7. It is essentially a call to <u><b>zwSetContextThread</b></u>. Its information is not officially available from Microsoft, but doing a little web search you will be able to find that it takes two parameters:<br />
<br />
IN HANDLE <u><b>processHandle </b></u>(value is 0xFFFF as shown in the stack pane of Figure 7)<br />
INOUT PCONTEXT <u><b>pContext </b></u>(value is 0x0012D028 as shown in Figure 7)<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVZP0vzL4wATFrAL1usSt1v-LjgyNHG1uH7YnUuW8of7bxbUbofg1GL7A5l9To0qsKnVLOBJab2gN_8VAHkpLMfgO8h8Q_KG2XA9_Cty8OHg4aO-DVfbKCQlpdA9QWvYwsvT08grneJXM/s1600/a4.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" rea="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVZP0vzL4wATFrAL1usSt1v-LjgyNHG1uH7YnUuW8of7bxbUbofg1GL7A5l9To0qsKnVLOBJab2gN_8VAHkpLMfgO8h8Q_KG2XA9_Cty8OHg4aO-DVfbKCQlpdA9QWvYwsvT08grneJXM/s1600/a4.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 7. zwSetContextThread</td></tr>
</tbody></table>0x0012D028 will hold a <u><b>Context </b></u>structure. Its data structure is shown as below (from [<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms679284%28v=vs.85%29.aspx">2</a>]). Starting from the second word in the _CONTEXT structure are the values of hardware breakpoint registers (Dr0 to Dr7). Now if you look at Figure 8 (the current contents at 0x0012D028), you would notice that the value of ContextFlags is <u><b>0x00010010</b></u>, and the value of Dr3 (the fourth hardware breakpoint register) is set to <u><b>0x7C90D500</b></u>!!!<br />
<br />
<br />
<br />
<div class="communityContentAnnotationBody" style="font-family: 'Courier New',Courier,monospace;">//for x86<br />
typedef struct _CONTEXT {<br />
<br />
DWORD ContextFlags;<br />
...<br />
DWORD Dr0;<br />
DWORD Dr1;<br />
DWORD Dr2;<br />
DWORD Dr3;<br />
DWORD Dr6;<br />
DWORD Dr7;<br />
...<br />
FLOATING_SAVE_AREA FloatSave;<br />
/...<br />
} CONTEXT; </div><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO6gW_tjBf1g8l3XoqNaHaLF1iOBA-raaiSyT1lh_NyZTsVMjQ0g7Z38ICSid5iTSOLSFl0Hgf6L-jHuq1OjbByLRXyqZU4ZTAYecX-Q4laqwlBmyvUbovchs7QcuPrO8tt0nfLxHI9tI/s1600/a5.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" rea="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO6gW_tjBf1g8l3XoqNaHaLF1iOBA-raaiSyT1lh_NyZTsVMjQ0g7Z38ICSid5iTSOLSFl0Hgf6L-jHuq1OjbByLRXyqZU4ZTAYecX-Q4laqwlBmyvUbovchs7QcuPrO8tt0nfLxHI9tI/s1600/a5.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 8. CONTEXT structure contents at 0x0012D028</td></tr>
</tbody></table>Now we have almost unveiled all the tricks related to this step. Here are some of the challenges for you:<br />
<br />
<u><b>Challenge 3 of the Day: (1) Explain the value 0x00010010 of the ContextFlags, what does it mean? (2) Find out 0x7C90D500, is it an entry address (or somewhere inside) of a system function?</b></u><br />
<br />
<u><b>4.3 Load lz32.dll</b></u><br />
The next step is to <u><b>load lz32.dll</b></u>. Figure 9 shows the details (look at the comments area). It basically consists of two steps: (1) construct a unicode string "lz32.dll" and then (2) load the "lz32.dll" as a module. Tackle the following questions:<br />
<br />
<u><b>Challenge 4 of the day: (1) Explain the logic of function 0x004137EF, (2) Explain the logic of 0x41385D.</b></u><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR5ajUx067EOkZLJFDaX1kQb0tKb8KncKfcwAAGwm0c7ZfU86CXkyrnmCl2VMDLeTzr-0fdpXvgcjik57fH6HjKgS4k56u5uEkfIVnSkKaFHfk7kEjVDi70n9IuLyd_GiffxPew-GIRpE/s1600/a6.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" rea="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR5ajUx067EOkZLJFDaX1kQb0tKb8KncKfcwAAGwm0c7ZfU86CXkyrnmCl2VMDLeTzr-0fdpXvgcjik57fH6HjKgS4k56u5uEkfIVnSkKaFHfk7kEjVDi70n9IuLyd_GiffxPew-GIRpE/s1600/a6.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 9. Load lz32.dll</td></tr>
</tbody></table><br />
<u><b>4.4 Interrupting the LdrLoadDll procedure</b></u><br />
Note that "lz32.dll" is not malicious, it IS the victim! When the dll file is loaded, the loading procedure will actually be interrupted by Max++. Recall that Max++ has already set the interrupt handler at 0x00413657.<br />
<br />
Now set a software breakpoint at 0x00413657, and also a breakpoint at 0x0040140E (right after the loading of lz32.dll). You going to get the most tricky part of the analysis:<br />
<br />
<u><b>Challenge 5 of the day: Explain why isn't 0x00413657 never hit? Find a way to stop at 0x00413657.</b></u><br />
<br />
<div style="background-color: red;"><u><b>The correct way of hitting the 0x00413657:</b></u></div><div style="background-color: red;">(1)goto 0x00413657 and set a SOFTWARE BREAKPOINT on it (by pressing F2).</div><div style="background-color: red;">(2) Press SHIFT+F9 (think about what is the meaning of SHIFT+F9).</div><div style="background-color: red;">(3) You might be hitting 0x7C90D5000 (think about why you are hitting it in IMM? -- because it's a hardware breakpoint set by Max++. IMM stops at it even though it's not a HW breakpoint set inside IMM).</div><div style="background-color: red;">(4) Simply SHIFT+F9 again and you will hit 0x00413657. Now you can start your analysis of the exception handler.</div><br />
<br />
Then the analysis is going to be quite some work, in the following please find some hints:<br />
<br />
(1) The code at 0x00413657 is essentially an exception handler. Check out [<a href="http://www.microsoft.com/msj/0197/exception/exception.aspxhttp://www.microsoft.com/msj/0197/exception/exception.aspx">3</a>] for the calling convention (h<u><b>ow the parameters are passed</b></u>) for exception handlers. You will notice that the code is reading the exception record and tell if it is of its special interest. If it's not the hardware breakpoint exception (more exactly <u><b>single_step_trap</b></u>), the handler simply passes the exception to the next handler in the chain.<br />
<br />
(2) Once it is identified to be a hardware breakpoint, the handler does some writing into the memory. For example, it is writing value "0x003A0000" to some kernel data structures (related to a module). Think about why?<br />
<br />
(3) The handler sets the thread Context again to set the EIP register so that it does not return the 0x7Cxx (ntdll) function being called. The result? the actual binary code of lz32.dll is not loaded. Thus, the 0x003A0000 code stays there and is executed when the module "lz32.dll" is started.<br />
<br />
<u><b>Challenge 6 of the day: analyze each line starting from 0x00413657 and verify if the above statement is true.</b></u><br />
<br />
<br />
<br />
<br />
<br />
<u><b>References</b></u><br />
1. Microsoft, "zwAllocateVirtualMemory Routine", available at <a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff566416%28v=vs.85%29.aspx">http://msdn.microsoft.com/en-us/library/windows/hardware/ff566416(v=vs.85).aspx</a>.<br />
2. Microsoft, "Context Structure", available at <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms679284%28v=vs.85%29.aspx">http://msdn.microsoft.com/en-us/library/windows/desktop/ms679284(v=vs.85).aspx</a>.<br />
3. M. Pietrek, "A Crash Course on the Depth of Win32Tm Structured Exception Handling," Microsoft System Journal, 1997/01. Available at <a href="http://www.microsoft.com/msj/0197/exception/exception.aspx">http://www.microsoft.com/msj/0197/exception/exception.aspx</a><a href="http://www.microsoft.com/msj/0197/exception/exception.aspx">http://www.microsoft.com/msj/0197/exception/exception.aspx</a>.Unknownnoreply@blogger.com6tag:blogger.com,1999:blog-8770073098084592029.post-58129196246759961152012-01-04T11:14:00.000-08:002012-01-04T11:14:02.029-08:00Malware Analysis Tutorial 10: Tricks for Confusing Static Analysis Tools<b>Learning Goals</b>:<br />
<ol><li>Explore Use of Stack for Supporting Function Calls</li>
<li>Practice Reverse Engineering</li>
</ol><b>Applicable to:</b><br />
<ol><li>Operating Systems.</li>
<li>Computer Security.</li>
<li>Programming Language Principles.</li>
</ol><br />
<u><b>1. Introduction</b></u><br />
This tutorial explores several tricks employed by Max++ for confusing static analysis tools. These tricks effectively prevent static program analysis tools that plot call graph and extract system call invocation information of the malware. By "static" we mean that the tool does not actually execute/run the malware. Most "smart" virus scanners are static analysis tools. Many of them employ heuristics to tell if a binary executable is malicious or not by examining the collection of the system function calls in that binary. For example, if a binary invokes too many operations related to registry, then an alert should be flagged. If such analysis can be blocked, the malware can significantly improve its survival rate. Note that, however, such tricks cannot block "dynamic" tools which actually run the malware (typical examples include <a href="http://www.gfi.com/malware-analysis-tool">CWSandBox </a>and <a href="http://anubis.iseclab.org/">Anubis</a>). <br />
<br />
<b>2. Lab Configuration</b><br />
You can either continue from <a href="http://fumalwareanalysis.blogspot.com/2011/12/malware-analysis-tutorial-9-encoded.html">Tutorial 9</a>, or follow the instructions below to set up the lab. Refer to <a href="http://fumalwareanalysis.blogspot.com/2011/08/malware-analysis-tutorial-reverse.html">Tutorial 1</a> and <a href="http://fumalwareanalysis.blogspot.com/2011/10/malware-analysis-tutorial-4-int2dh-anti.html">Tutorial 4</a> for setting up VBOX instances and WinDbg. <u><b>We will analyze the function starting at 0x4014F9. </b></u><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl75jzGoFFvuOoKPzm7zquUwx9T1lPBcioJ6xih8xu4BXe2cySnbsfcvgwyTPY473O4UkCZbsA55WtmG9toe-HVk-Vv0whmNwqfbBxbG6IV2s0FpX-Un08ic6_KeCKF2mvCl5kBN80yj8/s1600/b1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" rea="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl75jzGoFFvuOoKPzm7zquUwx9T1lPBcioJ6xih8xu4BXe2cySnbsfcvgwyTPY473O4UkCZbsA55WtmG9toe-HVk-Vv0whmNwqfbBxbG6IV2s0FpX-Un08ic6_KeCKF2mvCl5kBN80yj8/s1600/b1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Function 0x4014F9 to Analyze</td></tr>
</tbody></table><br />
<br />
(1) In code pane, right click and go to expression "0x40105c"<br />
(2) right click and then "breakpoints -> hardware, on execution"<br />
(3) Press F9 to run to 0x40105c<br />
(4) If you see a lot of DB instructions, select them and right click -> "During next analysis treat them as Command".<br />
(5) Exit from IMM and restart it again and run to 0x40105c. Select the instructions (about 1 screen) below 0x40105c, right click -> Analysis-> Analyze Code. You should be able to see all loops now identified by IMM.<br />
(6) Now go to 0x401147, you will notice that it's "CALL 0x4014F9". Press F4 to run to the point and then Press F7 to step into the function <u><b>0x4014F9</b></u>. <br />
<br />
<br />
<br />
<u><b>3. Two-Layer Function Return</b></u><br />
We now analyze the first trick of a two-layer function return which disrupts call graph generation. In the following we analyze function <u><b>0x00401838</b></u>. Observe the instructions from 0x401502 to 0x401505 (in Figure 2). Our first impression would be that Function 0x401038 takes three parameters: a pointer to string "ntdll.dll", 0x7C903400, and 0x7C905D40. However, later you will find that it is not the case: function 0x00401838 is simply used to confuse static analysis tools.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDOYB6ML8Q2OvjYJyI2yqvjkJXIvaxtmho1-3MKhlReDoBJb5eUQYkfvRQmGl667qwDzVPjr0wVpI3z-6_SazaelxIXF14L8kO52UF5jS-e4s00Th1v9GJuMML05Mcc_UcCJsc_TVHJLQ/s1600/b2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" rea="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDOYB6ML8Q2OvjYJyI2yqvjkJXIvaxtmho1-3MKhlReDoBJb5eUQYkfvRQmGl667qwDzVPjr0wVpI3z-6_SazaelxIXF14L8kO52UF5jS-e4s00Th1v9GJuMML05Mcc_UcCJsc_TVHJLQ/s1600/b2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. Two Layer Function Call at 0x401505</td></tr>
</tbody></table>Figure 3 displays the function body of 0x401838. It starts with a call of 0x00413650 and then a bunch of other instructions (later, you will notice that these instructions will never be executed).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiQhg5S_BFhzaq1NNbuTGNUMmdMspOQM6fPYtjkWsjQCAS96To-Ej3hVPG9EBkMiZHALZFC2NKzXk7RZOvtl5HtIPqCJp-Tf84KiTySBz0ZXgHI76gyw6QxyfpHF2S09QUW17rnL3gF-Q/s1600/b3.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" rea="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiQhg5S_BFhzaq1NNbuTGNUMmdMspOQM6fPYtjkWsjQCAS96To-Ej3hVPG9EBkMiZHALZFC2NKzXk7RZOvtl5HtIPqCJp-Tf84KiTySBz0ZXgHI76gyw6QxyfpHF2S09QUW17rnL3gF-Q/s1600/b3.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 3. Function body of 0x401838</td></tr>
</tbody></table>Notice that at 0x0040183B, it calls function 0x00413650, whose function body is displayed in Figure 4. There are only two instructions: POP EAX, and RETN.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi544PxTX-DLpsrSduRfO-tkyO6xc5izU6SPRUblzu3hf0fBEWR8bJJ1Rjc3OVlN6cZ0Du_gSzrU7pfa82jqqaqY5Q7a6S7IBLzJ1rvjL7xXsjwgnSIb8csLY5UMz5kg5oIEUMA_gMvunI/s1600/b4.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" rea="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi544PxTX-DLpsrSduRfO-tkyO6xc5izU6SPRUblzu3hf0fBEWR8bJJ1Rjc3OVlN6cZ0Du_gSzrU7pfa82jqqaqY5Q7a6S7IBLzJ1rvjL7xXsjwgnSIb8csLY5UMz5kg5oIEUMA_gMvunI/s1600/b4.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Function Body of 0x413650</td></tr>
</tbody></table>Now we have the interesting part. Look at the stack contents in Figure 5. First of all, starting from the third computer word, we have the three words pushed by the code earlier (they are pointer to "ntdll.dll", 0x7c903400, and 0x7c905d40). Then you might notice that the top two words are the <u><b>RETURN ADDRESSES</b></u> pushed by the CALL instructions.<br />
<br />
Each CALL instruction consists of essentially two steps: push the address of the next instruction to the stack (so that it can return when the function being called is completed) and then jump to the entry address of the function. <u><b>Thus, it is not difficult to infer that </b></u><u><b>0x00401840 </b></u><u><b>is pushed by the CALL 0x00413650 at 0x0040183B (see Figure 3), and </b></u><u><b>0x0040150A </b></u><u><b>is pushed by the CALL 0x00401838 at 0x00401505 (see Figure 2).</b> </u>So the POP EAX will pop off 0x00401840 and save it to EAX. <u><b>When the RETN instruction is executed, it is directly returning to 0x40150A (i.e., it jumps two layers back)!</b></u> Clearly, the instructions starting from 0x00401840 are never executed and the two layer jumping can confuse quite a number of static analysis tools when they try to plot call graphs.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheXbByjx5AS_Bz4mKV3SJr-M1gX3FnQvvF1S-yG248mMwNjawBJ7sSutLUzQsbtoiVMZrflkU2syop4WQ5sIrKQw9rpI6o5jNWOiscE85vwCrYJGK3iIuWjKu5hvNNqxYE8oxOs_UwlUQ/s1600/b5.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" rea="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheXbByjx5AS_Bz4mKV3SJr-M1gX3FnQvvF1S-yG248mMwNjawBJ7sSutLUzQsbtoiVMZrflkU2syop4WQ5sIrKQw9rpI6o5jNWOiscE85vwCrYJGK3iIuWjKu5hvNNqxYE8oxOs_UwlUQ/s1600/b5.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 5. Stack Contents at 0x00413650</td></tr>
</tbody></table><br />
<br />
<u><b>4. Invoking NTDLL System Calls using Encoded Table</b></u><br />
Next we show an interesting technique to invoke ntdll.dll functions without the use of export table. We will analyze the instruction at <u><b>0x401557 </b></u>(as shown in Figure 6), it calls function <u><b>0x4136BF</b></u>. Later, you will find that function 0x4136BF invokes zwAllocateVirtualMemory without exposing the entry address of zwAllocateVirtualMemory explicitly and it does not use export table.<br />
<br />
We leave the analysis of the logic between 0x40150A and 0x401557 (shown in Figure 6) to readers. Basically the code is to establish an encoded translation table in stack from 0x0012D538 to 0x0012D638. <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdYIVJY5fxB-ZjNEkztOmu__-ecLpt9j__Lg5lyKJyuq6q3KBNFUmyxP90FByHFTwaFfu1KOfx3TqwgbvmFLwVe447db9nhNlHZq4wQ6pIPFVnRcabIWLmPedaNAEvWIbUEVeAw314dO0/s1600/c1.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" rea="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdYIVJY5fxB-ZjNEkztOmu__-ecLpt9j__Lg5lyKJyuq6q3KBNFUmyxP90FByHFTwaFfu1KOfx3TqwgbvmFLwVe447db9nhNlHZq4wQ6pIPFVnRcabIWLmPedaNAEvWIbUEVeAw314dO0/s1600/c1.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 6. Code Between 0x40150A and 0x401557</td></tr>
</tbody></table><br />
Now observe the function body of 0x004136BF in Figure 7. The first instruction is <u><b>CALL 0x004136DC</b></u>. You might notice that between 0x004136BF and 0x004136DC, there are some gibberish code. If you read it more carefully, you will find that they are actually the contents of string "zwAllocateVirtualMemory" where the byte at 0x004136C4 is the character "z".<br />
<br />
Think about the <u><b>CALL 0x004136BF</b></u> again. It is essentially two stesp:<br />
<u><b>PUSH 0x004136C4</b></u> # note 0x004136C4 is the beginning of "zwAllocateVirtualMemory" (see Figure 8)<br />
<u><b>JUMP 0X004136DC</b></u><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjayMwPAtFwEyL4SrO4aYefXCMnkfJhjckf26SPBH5mQ_A0gotwYE-i2UL5c5i0O7qsCJ8km0Dm1DDNclESwREiNz2H2sDV59vHiGGwtW-y7EaCJNeE1pbeqAq18caQ25Vb4iyhCTWvryQ/s1600/c2.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" rea="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjayMwPAtFwEyL4SrO4aYefXCMnkfJhjckf26SPBH5mQ_A0gotwYE-i2UL5c5i0O7qsCJ8km0Dm1DDNclESwREiNz2H2sDV59vHiGGwtW-y7EaCJNeE1pbeqAq18caQ25Vb4iyhCTWvryQ/s1600/c2.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 7. Function Body of 0x4136BF.</td></tr>
</tbody></table><br />
Now you can pretty much guess the point of the code: it is trying to invoke zwAllocateVirtualMemory! But how is it accomplished? Let's delve deeper. At 0x004136DC it is calling function <u><b>0x00401172 </b></u>and when it returns, at <u><b>0x004136E1</b></u>, it <u><b>JMP EAX</b></u>. Can you guess the functionality of 0x00401172?<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCzZNUdD7GYfvdGyWPg2ffTJJyuLD8YfWt4KJqxsh_augyW38NlmXQHG8UOAzHkA4oNpuhUCqVc-xtdgVemVTEj-jq9z9CcEFxZ_OQeD29H20z0i2V1uGExa5756Z56MwTsmeyuawj9Q4/s1600/c3.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" rea="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCzZNUdD7GYfvdGyWPg2ffTJJyuLD8YfWt4KJqxsh_augyW38NlmXQHG8UOAzHkA4oNpuhUCqVc-xtdgVemVTEj-jq9z9CcEFxZ_OQeD29H20z0i2V1uGExa5756Z56MwTsmeyuawj9Q4/s1600/c3.JPG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 8. Stack Contents at 0x4136DC before the Call of 0x00401172</td></tr>
</tbody></table>We list some hints below (see Figure 9):<br />
(1) The loop between 0x0040118E and 0x004011A0 is to compute the checksum of the function name<br />
(2) The loop between 0x4011A2 and 0x004011BA is a binary search. The search is performed on the encoded export table (as discussed in <a href="http://fumalwareanalysis.blogspot.com/2011/12/malware-analysis-tutorial-9-encoded.html">Tutorial 9</a>). Each entry has two elements: (1) check sum of the function name, and (2) the entry address of the function.<br />
<br />
You could easily infer that function 0x00401172, given the name of a function, returns its entry address. Once it returns, the return value is saved in EAX. Then JMP EAX at <u><b>0x004136E1 </b></u>will invoke the function.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiT1evY6usVd_-QOWNj-nTo-RWqbkjG6zAoGfGk5OPCRzLQUrWm8VEnA9nC2eftadqzDt21gXPXMm6EJxeM0I_BWBfj6XwstSuKHcYZmYrM-iya0R_0SLdZ5rorJZbXsAkQAGYASrX4HU8/s1600/c4.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" rea="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiT1evY6usVd_-QOWNj-nTo-RWqbkjG6zAoGfGk5OPCRzLQUrWm8VEnA9nC2eftadqzDt21gXPXMm6EJxeM0I_BWBfj6XwstSuKHcYZmYrM-iya0R_0SLdZ5rorJZbXsAkQAGYASrX4HU8/s1600/c4.JPG" /></a></div><br />
<u><b>5. Challenge of the Day</b></u><br />
(1) What is the checksum of zwAllocateVirtualMemory?<br />
(2) What are the parameters of zwAllocateVirtualMemory? Why does Max++ call this function?<br />
(3) Look at 0x40117B, what is stored in the thread local storage (EAX+2C)? How do you make your conclusion?Unknownnoreply@blogger.com21