<?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>WinHTTP - RiskInsight</title>
	<atom:link href="https://www.riskinsight-wavestone.com/en/tag/winhttp/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.riskinsight-wavestone.com/en/tag/winhttp/</link>
	<description>The cybersecurity &#38; digital trust blog by Wavestone&#039;s consultants</description>
	<lastBuildDate>Wed, 30 Oct 2024 15:55:09 +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>WinHTTP - RiskInsight</title>
	<link>https://www.riskinsight-wavestone.com/en/tag/winhttp/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>LoadLibrary madness: dynamically load WinHTTP.dll</title>
		<link>https://www.riskinsight-wavestone.com/en/2024/10/loadlibrary-madness-dynamically-load-winhttp-dll/</link>
					<comments>https://www.riskinsight-wavestone.com/en/2024/10/loadlibrary-madness-dynamically-load-winhttp-dll/#respond</comments>
		
		<dc:creator><![CDATA[Yoann DEQUEKER]]></dc:creator>
		<pubDate>Wed, 30 Oct 2024 15:52:37 +0000</pubDate>
				<category><![CDATA[Deep-dive]]></category>
		<category><![CDATA[Ethical Hacking & Incident Response]]></category>
		<category><![CDATA[C2]]></category>
		<category><![CDATA[Command and Control]]></category>
		<category><![CDATA[Dll]]></category>
		<category><![CDATA[Ethical Hacking]]></category>
		<category><![CDATA[WinHTTP]]></category>
		<guid isPermaLink="false">https://www.riskinsight-wavestone.com/?p=24427</guid>

					<description><![CDATA[<p>For the last few weeks, I have been developing a full custom Command and Control (C2). This C2 uses several Windows DLL for network communication and specially the WINHTTP.DLL one to handle HTTP requests used for the HTTP and HTTPS...</p>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/en/2024/10/loadlibrary-madness-dynamically-load-winhttp-dll/">LoadLibrary madness: dynamically load WinHTTP.dll</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com/en/">RiskInsight</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>For the last few weeks, I have been developing a full custom <span style="color: #451dc7;"><em>Command and Control</em></span> (<em><span style="color: #451dc7;">C2</span></em>). This <em><span style="color: #451dc7;">C2</span> </em>uses several <span style="color: #451dc7;"><em>Windows DLL</em></span> for network communication and specially the <span style="color: #451dc7;"><em>WINHTTP.DLL</em></span> one to handle <span style="color: #451dc7;"><em>HTTP</em> </span>requests used for the <em><span style="color: #451dc7;">HTTP</span> </em>and <em><span style="color: #451dc7;">HTTPS</span> </em>listener.</p>
<p>As everyone knows, when developing a <em><span style="color: #451dc7;">C2</span> </em>and the corresponding agent, <span style="color: #451dc7;"><em>OPSEC</em></span> must be the priority, so the agent code must rise as few events (<span style="color: #451dc7;"><em>ETW</em></span>) as possible.</p>
<p>The most common way to increase <span style="color: #451dc7;"><em>OPSEC</em> </span>when using external <span style="color: #451dc7;"><em>DLL</em> </span>is to perform dynamic loading to avoid getting the loaded <span style="color: #451dc7;"><em>DLL</em> </span>name in the source code. This can be done using the <span style="color: #451dc7;"><em>LoadLibrary Win32 API</em></span>.</p>
<p>This <span style="color: #451dc7;"><em>API</em> </span>allows a program to load a specific <span style="color: #451dc7;"><em>DLL</em></span> from the disk. However, the drawback is that <em><span style="color: #451dc7;">LoadLibrary</span> </em>raises several events and telemetry an <span style="color: #451dc7;"><em>EDR</em> </span>can analyze to detect the malicious <span style="color: #451dc7;"><em>C2</em> </span>agent.</p>
<p>In order to avoid this kind of event, I chose to implement a custom <span style="color: #451dc7;"><em>LoadLibrary</em> </span>that will not raise such events.</p>
<p style="text-align: justify;"> </p>
<h2 style="text-align: justify;"><span style="color: #451dc7;">State of the art &#8211; LoadLibrary</span></h2>
<p>I will not go too much deeper in the implementation details, as this has already been documented several times in <em>blogposts</em><a href="#_ftn1" name="_ftnref1">[1]</a> or <em>books</em> (<em><span style="color: #451dc7;">Windows Internals Part 1</span></em>).</p>
<p>The goal here is to create a function that takes as an input a <span style="color: #451dc7;"><em>DLL</em> </span>path and loads the <em><span style="color: #451dc7;">DLL</span> </em>in memory. Doing it manually has a lot of advantages:</p>
<ul>
<li>Limits <span style="color: #451dc7;"><em>ETW</em> </span>and <span style="color: #451dc7;"><em>Microsoft</em> </span>telemetry</li>
<li>More choices in the way sections are allocated and written.</li>
<li>Possibility to hide malicious loaded <em><span style="color: #451dc7;">DLL</span> </em>when not used.</li>
</ul>
<p>However, there are a lot of edge cases that could make the custom loader unreliable as it was mentioned in the <span style="color: #451dc7;"><em>SpecterOps</em> </span>blogpost <em>PerfectLoader<span style="color: #250f6b;"><a href="#_ftn2" name="_ftnref2">[2]</a></span></em>:</p>
<p><code>The quality of these reimplementations may be judged by comparing the feature set of these custom loaders against what the OS’s native loader supports. As such, the native OS loader may be considered a “perfect loader,” but it should not be considered the only perfect loader.</code><br /><br /></p>
<h3 style="text-align: justify;"><span style="color: #451dc7;">Basic implementation</span></h3>
<p style="text-align: justify;">The basic implementation consists in just copying the <em><span style="color: #451dc7;">DLL</span> </em>image in memory, performing relocation, importing imported modules and resolving the <em><span style="color: #451dc7;">IAT</span> </em>entries.<br />The different steps can be found in the <em><span style="color: #451dc7;">Windows Internal Part 1</span></em> book (<em><span style="color: #451dc7;">page 178</span></em>) and a more described implementation can be found here<a href="#_ftn3" name="_ftnref3">[3]</a>.<br />This is the most common way to load a <em><span style="color: #451dc7;">DLL</span></em>. Once the <em><span style="color: #451dc7;">DLL</span> </em>is loaded as-is in memory, it can be used for basic usages. However, any use of standard <em><span style="color: #451dc7;">Win32API</span></em> against this <em><span style="color: #451dc7;">DLL</span> </em>such as <em><span style="color: #451dc7;">GetModuleHandle</span> </em>or <span style="color: #451dc7;"><em>GetProcAddress</em> </span>will fail.<br />This implementation does not implement any additional feature provided by the <em><span style="color: #451dc7;">Windows DLL</span></em> loader: it just performs a textbook <em><span style="color: #451dc7;">DLL</span> </em>loading.</p>
<p> </p>
<h3 style="text-align: justify;"><span style="color: #451dc7;">Fixing compatibility with Microsoft WIN32API</span></h3>
<p>The previous implementation has the merit of working and it helped me out more times I can count. However, it is not reliable; the most important edge case being the <em><span style="color: #451dc7;">DLL</span> </em>cannot be searched using <span style="color: #451dc7;"><em>GetModuleHandle</em> </span>or <span style="color: #451dc7;"><em>LoadLibrary</em></span>.</p>
<p>Therefore, if the others <span style="color: #451dc7;"><em>DLL</em> </span>need access to the loaded <span style="color: #451dc7;"><em>DLL</em></span>, they will not find it with the standard <span style="color: #451dc7;"><em>Win32API</em> </span>and will load it again using <span style="color: #451dc7;"><em>LoadLibrary</em> </span>leading to a nice <span style="color: #451dc7;"><em>ETW</em> </span>event: all we wanted to avoid in the first place.</p>
<p><em>Batsec</em><span style="color: #250f6b;"><a href="#_ftn4" name="_ftnref4">[4]</a></span> wrote an <em>article</em><a href="#_ftn5" name="_ftnref5">[5]</a> on how the <span style="color: #451dc7;"><em>DLL</em></span> can be loaded in memory and still be compatible with the <span style="color: #451dc7;"><em>Microsoft</em> <em>Win32 API</em></span> (at least <span style="color: #451dc7;"><em>GetProcAddress</em></span>, <span style="color: #451dc7;"><em>LoadLibrary</em> </span>and <span style="color: #451dc7;"><em>GetModuleHandle</em></span>) without raising a bunch of events.</p>
<p>His research shows that when a <span style="color: #451dc7;"><em>DLL</em> </span>is loaded by the standard <span style="color: #451dc7;"><em>Windows DLL</em></span> loader, it does not just load the image in memory and the loader will perform at least two additional actions:</p>
<ul>
<li>Add the <span style="color: #451dc7;"><em>DLL</em> </span>in the <span style="color: #451dc7;"><em>PEB</em> </span>linked list that contains all the <span style="color: #451dc7;"><em>DLL</em> </span>loaded by a process.</li>
<li>Create a hash identifying the <span style="color: #451dc7;"><em>DLL</em> </span>and adding it to another structure called <em><span style="color: #451dc7;">LdrpHashTable</span></em></li>
</ul>
<p>During the loading process, the <span style="color: #451dc7;"><em>DLL</em> </span>loader, calls the <span style="color: #451dc7;"><em>LdrpInsertDataTableEntry</em> </span>function. This function creates a hash identifying the <span style="color: #451dc7;"><em>DLL</em> </span>and adds it to the <span style="color: #451dc7;"><em>LdrpHashTable</em> </span>structure as shown in the following figure:</p>
<p style="text-align: center;"><img fetchpriority="high" decoding="async" class="aligncenter size-full wp-image-24350" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/01-Use-of-LdrpHashTable.png" alt="" width="471" height="292" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/01-Use-of-LdrpHashTable.png 471w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/01-Use-of-LdrpHashTable-308x191.png 308w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/01-Use-of-LdrpHashTable-63x39.png 63w" sizes="(max-width: 471px) 100vw, 471px" /></p>
<p style="text-align: center;"><em>Figure 1: use of LdrpHashTable during DLL loading</em></p>
<p>This mechanism has been implemented by <span style="color: #451dc7;"><em>Microsoft</em> </span>to ease and speedup <span style="color: #451dc7;"><em>DLL</em> </span>search through a read and black binary tree. This structure allows the search of a <span style="color: #451dc7;"><em>DLL</em> </span>in <span style="color: #451dc7;"><em>O(log(n))</em></span> instead of <span style="color: #451dc7;"><em>O(n)</em></span> with the previous linked list. This mechanism will not be explained here but can be seen in the <span style="color: #451dc7;"><em>DarkLoadLibrary</em> </span>project in the <span style="color: #451dc7;"><em>FindModuleBaseAddressIndex</em> </span>function.</p>
<p>Adding the <span style="color: #451dc7;"><em>DLL</em> </span>in the <span style="color: #451dc7;"><em>PEB</em> </span>linked list <strong>AND</strong> in the <span style="color: #451dc7;"><em>LdrpHashTable</em> </span>can be seen as fully registering the <span style="color: #451dc7;"><em>DLL</em> </span>and makes it known to the process.</p>
<p>Once this link has been established, the <span style="color: #451dc7;"><em>DLL</em> </span>can be searched, freed, or copied through the <span style="color: #451dc7;"><em>Win32API</em></span>.</p>
<p> </p>
<h3 style="text-align: justify;"><span style="color: #451dc7;">Problems with this implementation</span></h3>
<p>When I saw this implementation, I thought that all my problems were solved and started reimplementing it on my side to understand and customize the process.</p>
<p>For a moment it worked well. All the <em><span style="color: #451dc7;">DLL</span> </em>I loaded with worked out of the box and no specific event regarding the loading of an additional <em><span style="color: #451dc7;">DLL</span> </em>were raised by the agent.</p>
<p>The troubles begin when I tried to dynamically load a specific <em><span style="color: #451dc7;">DLL</span></em>: <span style="color: #451dc7;"><em>WinHTTP.dll.</em></span></p>
<p>The <span style="color: #451dc7;"><em>DLL</em> </span>is successfully loaded, and the majority of functions worked well, but one function did not want to work: <span style="color: #451dc7;"><em>WinHTTPOpen</em></span>.</p>
<p>This function is used to initialize the environment and prepare the structures that will be used by the other network <span style="color: #451dc7;"><em>API</em> </span>used to perform an <span style="color: #451dc7;"><em>HTTP</em> </span>connection. So, without this function, it was not possible to perform any <span style="color: #451dc7;"><em>HTTP</em> </span>communication through the <span style="color: #451dc7;"><em>WinHTTP API</em></span>.</p>
<p>When I called the <span style="color: #451dc7;"><em>WinHTTPOpen</em></span> function, the call failed with the error code <span style="color: #451dc7;"><em>126</em></span>. This error code is related to a missing <span style="color: #451dc7;"><em>DLL</em> </span>which does not make any sense as all the <span style="color: #451dc7;"><em>DLL</em> </span>were successfully loaded.</p>
<p> </p>
<h2 style="text-align: justify;"><span style="color: #451dc7;">Dive into WinHTTP.DLL madness</span></h2>
<h3 style="text-align: justify;"><span style="color: #451dc7;">Macroscopic investigation</span></h3>
<p>The error code hinted a problem with a <span style="color: #451dc7;"><em>DLL</em> </span>that has not been loaded, so my first reflex was to monitor the process using <span style="color: #451dc7;"><em>Procmon</em></span>, looking for an imported <span style="color: #451dc7;"><em>DLL</em> </span>that could have failed to be loaded.</p>
<p>However, even when comparing the <em><span style="color: #451dc7;">DLL</span> </em>loaded with the standard <span style="color: #451dc7;"><em>LoadLibrary</em> </span>and the ones loaded through the custom loader, no differences could explain the error code <span style="color: #451dc7;"><em>126</em></span>.</p>
<p> </p>
<h3 style="text-align: justify;"><span style="color: #451dc7;">Microscopic investigation</span></h3>
<p>For a moment I let this problem aside and continue the development of the agent, but it still bothered me, and I had no idea how I could debug it. Until one day, I took my sanity away, and decided to just decompile the <em><span style="color: #451dc7;">WinHTTP.DLL</span></em> and debug it step by step until I saw the error code <em><span style="color: #451dc7;">126</span> </em>popping in one of the registers.</p>
<p> </p>
<h4 style="text-align: justify;"><span style="color: #451dc7;">Finding the initial problem</span></h4>
<p>With the step by step debug, I quickly found that the problem occurred in the <em><span style="color: #451dc7;">INTERNET_SESSION_HANDLE_OBJECT::SetProxySettings</span></em> function in the <em><span style="color: #451dc7;">WINHTTP.DLL</span></em> file.</p>
<p>Following the call stack leads me to the following functions:</p>
<ul>
<li><em><span style="color: #451dc7;">INTERNET_HANDLE_BASE::SetProxySettingsWithInterfaceIndex</span></em></li>
<li><em><span style="color: #451dc7;">WxReferenceDll</span></em></li>
<li><em><span style="color: #451dc7;">TakeSingleDllRef</span></em></li>
</ul>
<p>In the <span style="color: #451dc7;"><em>TakeSingleDllRef</em> </span>I found the following piece of code:</p>
<p><img decoding="async" class="aligncenter size-full wp-image-24352" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/02-Code-TakeSingleDllRef.png" alt="" width="433" height="233" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/02-Code-TakeSingleDllRef.png 433w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/02-Code-TakeSingleDllRef-355x191.png 355w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/02-Code-TakeSingleDllRef-71x39.png 71w" sizes="(max-width: 433px) 100vw, 433px" /></p>
<p style="text-align: center;"><em>Figure 2: TakeSingleDllRef code</em></p>
<p>The <span style="color: #451dc7;"><em>126</em> </span>error code I got when running the <span style="color: #451dc7;"><em>WinHTTPOpen</em> </span>function is generated by the <span style="color: #451dc7;"><em>GetModuleHandleExA</em> </span>function.</p>
<p>This function is usually used to retrieve the base address of an already loaded <span style="color: #451dc7;"><em>DLL</em> </span>by its <span style="color: #451dc7;"><em>DLL</em> </span>name. However, here, two unusual parameters are given to this API:</p>
<ul>
<li><span style="color: #451dc7;"><em>dwFlags</em></span>: <span style="color: #451dc7;"><em>4</em> </span>instead of <span style="color: #451dc7;"><em>2</em></span></li>
<li><span style="color: #451dc7;"><em>dllName</em></span>: the address of the current function instead of the name of the <span style="color: #451dc7;"><em>DLL</em> </span>to search for.</li>
</ul>
<p>Looking at the <span style="color: #451dc7;"><em>Microsoft</em> </span>documentation shows that <em><span style="color: #451dc7;">dwFlags 4</span></em> is named <span style="color: #451dc7;"><em>GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS</em> </span>and thus explains why an address is given instead of a <span style="color: #451dc7;"><em>DLL</em> </span>name.</p>
<p>Indeed, when this flag is passed to the <span style="color: #451dc7;"><em>GetModuleHandleExA</em></span>, the function will not search for the <span style="color: #451dc7;"><em>DLL</em> </span>base address by its name but will find the <span style="color: #451dc7;"><em>DLL</em> </span>that contains the given function.</p>
<p> </p>
<h4 style="text-align: justify;"><span style="color: #451dc7;">Narrow down the problem</span></h4>
<p>The problem comes from the <span style="color: #451dc7;"><em>GetModuleHandleExA</em> </span>function. This is interesting because during my tests the custom loader worked fine with <span style="color: #451dc7;"><em>GetModuleHandle</em> </span>(that call <span style="color: #451dc7;"><em>GetModuleHandleEx</em> </span>under the hood with <em><span style="color: #451dc7;">dwFlags 2</span></em> instead of <span style="color: #451dc7;"><em>4</em></span>).</p>
<p>So, I decompiled the <span style="color: #451dc7;"><em>KERNELBASE.DLL</em></span> to find the difference of implementation when <span style="color: #451dc7;"><em>dwFlags 4</em></span> is passed to <span style="color: #451dc7;"><em>GetModuleHandleEx</em></span>.</p>
<p>The callstack shows that <span style="color: #451dc7;"><em>GetModuleHandleEx</em> </span>called the <span style="color: #451dc7;"><em>BasepGetModuleHandleExW</em> </span>function.</p>
<p><img decoding="async" class="aligncenter size-full wp-image-24354" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/03-BasepGetModuleHandleExW.png" alt="" width="354" height="257" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/03-BasepGetModuleHandleExW.png 354w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/03-BasepGetModuleHandleExW-263x191.png 263w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/03-BasepGetModuleHandleExW-54x39.png 54w" sizes="(max-width: 354px) 100vw, 354px" /></p>
<p style="text-align: center;"><em>Figure 3: BasepGetModuleHandleExW code</em></p>
<p>The first part of the <span style="color: #451dc7;"><em>BasepGetModuleHandleExW</em> </span>function explains the difference of behavior between <span style="color: #451dc7;"><em>GetModuleHandle</em> </span>and <span style="color: #451dc7;"><em>GetModuleHandleEx</em> </span>with <span style="color: #451dc7;"><em>dwFlags</em></span> set to <span style="color: #451dc7;"><em>4</em></span>.</p>
<p>When the <span style="color: #451dc7;"><em>dwFlags</em></span> is set to <span style="color: #451dc7;"><em>4</em></span>, the function uses the <span style="color: #451dc7;"><em>RtlPcToFileHeader</em> </span>to find the base address of the module related to the function passed as parameters.</p>
<p>A step-by-step debug shows that this function returns the right value for a <span style="color: #451dc7;"><em>DLL</em> </span>loaded with <span style="color: #451dc7;"><em>LoadLibrary</em> </span>but always return <span style="color: #451dc7;"><em>0</em> </span>for a <span style="color: #451dc7;"><em>DLL</em> </span>loaded with the custom <span style="color: #451dc7;"><em>DLL Loader</em></span>.</p>
<p> </p>
<h4 style="text-align: justify;"><span style="color: #451dc7;">Analysis of RtlPcToFileHeader</span></h4>
<p>If I had to implement a function that, given a specific address, returns the base address of the image containing the function, I would naturally use the <span style="color: #451dc7;"><em>Win32Api VirtualQuery</em></span>. So, I did not see why this function could fail.</p>
<p>The <span style="color: #451dc7;"><em>RtlPcToFileHeader</em> </span>indeed use <span style="color: #451dc7;"><em>VirtualQuery</em> </span>to get the base address:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-24356" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/04-VirtualQuery-in-RtlPcToFileHeader.png" alt="" width="469" height="204" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/04-VirtualQuery-in-RtlPcToFileHeader.png 469w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/04-VirtualQuery-in-RtlPcToFileHeader-437x191.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/04-VirtualQuery-in-RtlPcToFileHeader-71x31.png 71w" sizes="auto, (max-width: 469px) 100vw, 469px" /></p>
<p style="text-align: center;"><em>Figure 4: use of VirtualQuery inRtlPcToFileHeader</em></p>
<p style="text-align: justify;">However, before getting in this execution branch it performs some additional tests :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-24358" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/05-Tests-in-RtlPcToFileHeader.png" alt="" width="517" height="299" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/05-Tests-in-RtlPcToFileHeader.png 517w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/05-Tests-in-RtlPcToFileHeader-330x191.png 330w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/05-Tests-in-RtlPcToFileHeader-67x39.png 67w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/05-Tests-in-RtlPcToFileHeader-120x70.png 120w" sizes="auto, (max-width: 517px) 100vw, 517px" /></p>
<p style="text-align: center;"><em>Figure 5: Tests performed in RtlPcToFileHeader</em></p>
<p>If the execution flow goes into the <em><span style="color: #451dc7;">if(!v10)</span></em>, the function will return <span style="color: #451dc7;"><em>0</em></span>, otherwise, it has a chance to go through the <span style="color: #451dc7;"><em>VirtualQuery</em> </span>and returns the right base address.</p>
<p>When this function is used on a <span style="color: #451dc7;"><em>DLL</em> </span>loaded by the custom loader, it always falls in the wrong code path returning <span style="color: #451dc7;"><em>0</em></span>.</p>
<p> </p>
<h4 style="text-align: justify;"><span style="color: #451dc7;">LdrpInvertedFunctionTable</span></h4>
<p>The test performed by the <span style="color: #451dc7;"><em>RtlPcToFileHeader</em> </span>function is based on an analysis of the <span style="color: #451dc7;"><em>LdrpInvertedFunctionTable</em></span>.</p>
<p>This table that can be parsed using the two following structures,</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-24360" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/06-Parse-inverted-table.png" alt="" width="509" height="265" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/06-Parse-inverted-table.png 509w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/06-Parse-inverted-table-367x191.png 367w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/06-Parse-inverted-table-71x37.png 71w" sizes="auto, (max-width: 509px) 100vw, 509px" /></p>
<p style="text-align: center;"><em>Figure 6: Structure used to parse the inverted table</em></p>
<p>seems to be used to handle <span style="color: #451dc7;"><em>SEH</em> </span>exceptions.</p>
<p>So, it seems that the custom loader fails to register these exceptions. Indeed, using <span style="color: #451dc7;"><em>WinDBG</em> </span>with the <em><span style="color: #451dc7;">DLL</span> </em>loaded through <span style="color: #451dc7;"><em>LoadLibrary</em></span>, it is possible to see that an entry corresponding to the<em><span style="color: #451dc7;"> WINHTTP.DLL</span> </em>file has been registered:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-24362" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/07-WinDBG-analysis.png" alt="" width="599" height="108" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/07-WinDBG-analysis.png 599w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/07-WinDBG-analysis-437x79.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/07-WinDBG-analysis-71x13.png 71w" sizes="auto, (max-width: 599px) 100vw, 599px" /></p>
<p style="text-align: center;"><em>Figure 7: Analysis of the inverted table with WinDBG</em></p>
<p>The same test with the custom loaded <span style="color: #451dc7;"><em>DLL</em> </span>shows that no new entry were added to the <span style="color: #451dc7;"><em>LdrpInvertedFunctionTable</em></span>.</p>
<p> </p>
<h2 style="text-align: justify;"><span style="color: #451dc7;">Solutions</span></h2>
<h3 style="text-align: justify;"><span style="color: #451dc7;">The messy one</span></h3>
<p>The root cause of the problem is that when loading the <span style="color: #451dc7;"><em>DLL</em></span>, no additional entries are added to the <span style="color: #451dc7;"><em>LdrpInvertedFunctionTable</em> </span>leading to a hard failure on the <span style="color: #451dc7;"><em>RtlPcToFileHeader</em> </span>function.</p>
<p>However, the main cause of the problem is that <span style="color: #451dc7;"><em>GetModuleHandleEx</em> </span>uses <span style="color: #451dc7;"><em>RtlPcToFileHeader</em></span>.</p>
<p>While adding a new entry to the <span style="color: #451dc7;"><em>LdrpInvertedFunctionTable</em> </span>can be a hard problem, hijacking the <span style="color: #451dc7;"><em>GetModuleHandleEx</em> </span>function when loading the <span style="color: #451dc7;"><em>DLL</em> </span>is an easy one.</p>
<p>Indeed, during the <span style="color: #451dc7;"><em>DLL</em> </span>loading process, we have to manually resolve the exported function address, so it is possible to hijack the entry related to <span style="color: #451dc7;"><em>GetModuleHandleExA</em></span>.</p>
<p>The following code can be used instead of <span style="color: #451dc7;"><em>GetModuleHandleExA</em></span>:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-24364" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/08-Custom-GetModuleHandleExA.png" alt="" width="605" height="358" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/08-Custom-GetModuleHandleExA.png 605w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/08-Custom-GetModuleHandleExA-323x191.png 323w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/08-Custom-GetModuleHandleExA-66x39.png 66w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/08-Custom-GetModuleHandleExA-120x70.png 120w" sizes="auto, (max-width: 605px) 100vw, 605px" /></p>
<p style="text-align: center;"><em>Figure 8: custom GetModuleHandleExA code</em></p>
<p>This code iterates over the <span style="color: #451dc7;"><em>DLL</em> </span>registered in the <span style="color: #451dc7;"><em>PEB</em> </span>linked list, check if the given function is located in the <span style="color: #451dc7;"><em>DLL</em> </span>and returns the base address of the related <span style="color: #451dc7;"><em>DLL</em></span>.</p>
<p>This solution worked for the <span style="color: #451dc7;"><em>WinHTTP.DLL</em></span> but what about other use cases or other functions based on <span style="color: #451dc7;"><em>RtlPcToFileHeader</em></span>? We would have to remap them explicitly every time which is not the best way to operate.</p>
<p> </p>
<h3 style="text-align: justify;"><span style="color: #451dc7;">The elegant one</span></h3>
<p>When two things have to work well together, we have to comply with the rules of the part we are integrating to. In this case, the custom loader should implement the feature that adds the different entries in the <span style="color: #451dc7;"><em>LdrpInvertedFunctionTable</em></span>.</p>
<p> </p>
<h4 style="text-align: justify;"><span style="color: #451dc7;">Locate the use of RtlInsertInvertedFunctionTable</span></h4>
<p>The function <span style="color: #451dc7;"><em>RtlInsertInvertedFunctionTable</em> </span>can be used to add an entry in the <span style="color: #451dc7;"><em>LdrpInvertedFunctionTable</em></span>. So, if this is performed by the <span style="color: #451dc7;"><em>Windows DLL</em></span> loader, it should be possible to find a reference of this function in the <span style="color: #451dc7;"><em>LoadLibrary</em></span> callstack.</p>
<p>Indeed, the call to the <span style="color: #451dc7;"><em>RtlInsertInvertedFunctionTable</em> </span>is found in the <span style="color: #451dc7;"><em>LdrpProcessMappedModule</em> </span>function:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-24366" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/09-RtlInsertInvertedFunctionTable.png" alt="" width="609" height="127" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/09-RtlInsertInvertedFunctionTable.png 609w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/09-RtlInsertInvertedFunctionTable-437x91.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/09-RtlInsertInvertedFunctionTable-71x15.png 71w" sizes="auto, (max-width: 609px) 100vw, 609px" /></p>
<p style="text-align: center;"><em>Figure 9: use of RtlInsertInvertedFunctionTable during DLL loading</em></p>
<p style="text-align: justify;">This function is called with a security cookie generated using the <span style="color: #451dc7;"><em>LdrInitSecurityCookie</em> </span>function:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-24368" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/10-LdrInitSecurityCookie.png" alt="" width="442" height="124" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/10-LdrInitSecurityCookie.png 442w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/10-LdrInitSecurityCookie-437x123.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/10-LdrInitSecurityCookie-71x20.png 71w" sizes="auto, (max-width: 442px) 100vw, 442px" /></p>
<p style="text-align: center;"><em>Figure 10: Use of LdrInitSecurityCookie</em></p>
<p>While the <span style="color: #451dc7;"><em>LdrInitSecurityCookie</em> </span>is an exported function, the <em><span style="color: #451dc7;">RtlInsertInvertedFunctionTable</span> </em>is not. So, if we want to use this function, there are two choices:</p>
<ul>
<li>Using a pattern recognition algorithm to find the function in the NTDLL knowing that the pattern can change between each Windows build version (this technique has been implemented <em>here</em><a href="#_ftn6" name="_ftnref6">[6]</a>)</li>
<li>Redeveloping the function</li>
</ul>
<p>I’m not a fan of pattern recognition because it is an unreliable technique that must be maintained over each Windows build version.</p>
<p style="text-align: justify;"> </p>
<h4 style="text-align: justify;"><span style="color: #451dc7;">Analysis of the RtlInsertInvertedFunctionTable function</span></h4>
<p style="text-align: justify;">Decompiling the <em><span style="color: #451dc7;">RtlInsertInvertedFunctionTable</span> </em>shows the following code :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-24370" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/11-RtlInsertInvertedFunctionTable.png" alt="" width="471" height="204" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/11-RtlInsertInvertedFunctionTable.png 471w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/11-RtlInsertInvertedFunctionTable-437x189.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/11-RtlInsertInvertedFunctionTable-71x31.png 71w" sizes="auto, (max-width: 471px) 100vw, 471px" /></p>
<p style="text-align: center;"><em>Figure 11: RtlInsertInvertedFunctionTable function</em></p>
<p>Among these functions, the only ones exported are the <span style="color: #451dc7;"><em>RtlAcquireSRWLockExclusive</em> </span>and <span style="color: #451dc7;"><em>RtlReleaseSrwLockExclusive</em></span>. However, the other ones are quite simple to implement:</p>
<ul>
<li><span style="color: #451dc7;"><em>RtlCaptureImageExceptionValues</em> </span>retrieves the image <span style="color: #451dc7;"><em>ExportDirectory</em></span></li>
<li><span style="color: #451dc7;"><em>LdrProtectMrData</em> </span>performs a <span style="color: #451dc7;"><em>VirtualProtect</em></span> on the <span style="color: #451dc7;"><em>.mrdata</em></span> section</li>
<li><span style="color: #451dc7;"><em>RtlpInsertInvertedFunctionTableEntry</em> </span>populates the <span style="color: #451dc7;"><em>RTL_INVERTED_FUNCTION_TABLE_ENTRY</em></span> and adds the new element to the <span style="color: #451dc7;"><em>RTL_INVERTED_FUNCTION_TABLE LdrpInvertedFunctionTable</em></span>.</li>
</ul>
<p>The only problem now is there is not any exported function that allows the retrieval of the <span style="color: #451dc7;"><em>LdrpInvertedFunctionTable</em> </span>object.</p>
<p> </p>
<h4 style="text-align: justify;"><span style="color: #451dc7;">Locate the RtlInsertInvertedFunctionTable</span></h4>
<p>So, against all my principle, some pattern recognition algorithms need to be coded in order to locate the <span style="color: #451dc7;"><em>LdrpInvertedFunctionTable</em> </span>structure. However, finding this structure will be easier and more reliable than finding some instructions sequences in the whole <span style="color: #451dc7;"><em>NTDLL .text</em></span> section.</p>
<p>Indeed, there are some inputs that can be used to narrow down the lookup and avoid false positive:</p>
<ul>
<li>The structure is located in the <span style="color: #451dc7;"><em>.mrdata</em></span></li>
<li>The <span style="color: #451dc7;"><em>MaxCount</em> </span>field must be less than <span style="color: #451dc7;"><em>512</em></span></li>
<li>The <span style="color: #451dc7;"><em>Count</em> </span>field must be less than max count and more than <span style="color: #451dc7;"><em>0</em></span></li>
</ul>
<p><code>The <span style="color: #451dc7;"><em>LdrpInvertedFunctionTable</em> </span>is located in the <span style="color: #451dc7;"><em>NTDLL .mrdata</em></span>. This section is a specific section that is configured with <span style="color: #451dc7;"><em>ReadOnly</em> </span>protection as the <span style="color: #451dc7;"><em>.rdata</em></span>. However, this section protection is often changed from <span style="color: #451dc7;"><em>ReadOnly</em> </span>to <span style="color: #451dc7;"><em>ReadWrite</em></span>.</code></p>
<p><code>This section is used to store sensitive structure that can be modified by the <span style="color: #451dc7;"><em>OS</em> </span>under specific circumstances (enhance the <span style="color: #451dc7;"><em>ReadWrite</em> </span>protection) but must be protected against programmatic error that could write arbitrary data in it (enhance the <span style="color: #451dc7;"><em>ReadOnly</em> </span>protection at runtime).</code></p>
<p>Then, some conditions on the different entries can be verified to ensure that the address tested represents the <span style="color: #451dc7;"><em>LdrpInvertedFunctionTable</em> </span>and is not a false positive. For each entry:</p>
<ul>
<li>The exception directory address must be contained in the <span style="color: #451dc7;"><em>DLL</em> </span>image</li>
<li>The exception directory address must match with the one computed from the <span style="color: #451dc7;"><em>DLL</em> </span>base image</li>
<li>The exception directory size must match with the one computed from the <span style="color: #451dc7;"><em>DLL</em> </span>base image</li>
</ul>
<p>These conditions do not ensure the unicity of the solution, but I don’t think random garbage in memory could verify all these conditions, especially the last three.</p>
<p style="text-align: justify;">The following function can be used to locate the <span style="color: #451dc7;"><em>LdrpInvertedFunctionTable</em></span>:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-24372" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/12-LdrpInvertedFunctionTable-Search.png" alt="" width="605" height="700" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/12-LdrpInvertedFunctionTable-Search.png 605w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/12-LdrpInvertedFunctionTable-Search-165x191.png 165w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/12-LdrpInvertedFunctionTable-Search-34x39.png 34w" sizes="auto, (max-width: 605px) 100vw, 605px" /></p>
<p style="text-align: center;"><em>Figure 12: Code looking for LdrpInvertedFunctionTable</em></p>
<p style="text-align: justify;">We now have everything we need to implement the <em><span style="color: #451dc7;">RtlInsertInvertedFunctionTable</span></em>.</p>
<p> </p>
<h4 style="text-align: justify;"><span style="color: #451dc7;">Implement the RtlInsertInvertedFunctionTable</span></h4>
<p>The <span style="color: #451dc7;"><em>RtlInsertInvertedFunctionTable</em> </span>can be implemented as the following:</p>
<ul>
<li>Locate the <span style="color: #451dc7;"><em>LdrpInvertedFunctionTable</em> </span>as explained before</li>
<li>Unprotect the <span style="color: #451dc7;"><em>.mrdata</em></span> section from <span style="color: #451dc7;"><em>ReadOnly</em> </span>to <span style="color: #451dc7;"><em>ReadWrite</em> </span>using <span style="color: #451dc7;"><em>VirtualProtect</em></span></li>
<li>Locate the index where the new <span style="color: #451dc7;"><em>DLL</em> </span>entry must be stored (these entries are sorted by image base address)</li>
<li>Write the <span style="color: #451dc7;"><em>RTL_INVERTED_FUNCTION_TABLE_ENTRY</em> </span>element in the <span style="color: #451dc7;"><em>LdrpInvertedFunctionTable</em></span></li>
</ul>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-24374" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/13-RtlpInsertInvertedFunctionTableEntry-Implementation.png" alt="" width="605" height="659" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/13-RtlpInsertInvertedFunctionTableEntry-Implementation.png 605w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/13-RtlpInsertInvertedFunctionTableEntry-Implementation-175x191.png 175w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/10/13-RtlpInsertInvertedFunctionTableEntry-Implementation-36x39.png 36w" sizes="auto, (max-width: 605px) 100vw, 605px" /></p>
<p style="text-align: center;"><em>Figure 13:  RtlpInsertInvertedFunctionTableEntry implementation</em></p>
<p>This code can be added to the <em>DarkLoadLibrary</em><a href="#_ftn7" name="_ftnref7">[7]</a> project to get a fully functional <em><span style="color: #451dc7;">DLL</span> </em>Loader.</p>
<p style="text-align: justify;"> </p>
<h2 style="text-align: justify;"><span style="color: #451dc7;">Conclusion</span></h2>
<p>When developing a custom <span style="color: #451dc7;"><em>C2</em></span>, the most difficult part is not getting something functional. This is mainly basic development. The most difficult and interesting part is to get something <em><span style="color: #451dc7;">OPSEC</span></em>.</p>
<p>This part implies a deep understanding of Windows internals in order to understand what <em><span style="color: #451dc7;">IOC</span> </em>will be raised, how it can be bypassed and how this custom part can be adapted to be fully integrated with the native <span style="color: #451dc7;"><em>Windows</em> </span>ecosystem.</p>
<p>This blogpost does not only show how a specific part of the <em><span style="color: #451dc7;">Windows DLL</span></em> loader can be reimplemented, but how <span style="color: #451dc7;"><em>IOC</em> </span>can be hunted, and how the <span style="color: #451dc7;"><em>Windows</em> </span>internals can be reversed to adapt our work to the ecosystem.</p>
<p> </p>
<p><a href="#_ftnref1" name="_ftn1">[1]</a> <a href="https://otterhacker.github.io/Malware/Reflective DLL injection.html" data-wplink-url-error="true">https://otterhacker.github.io/Malware/Reflective DLL injection.html</a></p>
<p><a href="#_ftnref2" name="_ftn2">[2]</a> <a href="https://posts.specterops.io/perfect-loader-implementations-7d785f4e1fa">https://posts.specterops.io/perfect-loader-implementations-7d785f4e1fa</a></p>
<p><a href="#_ftnref3" name="_ftn3">[3]</a> <a href="https://otterhacker.github.io/Malware/Reflective DLL injection.html" data-wplink-url-error="true">https://otterhacker.github.io/Malware/Reflective DLL injection.html</a></p>
<p><a href="#_ftnref4" name="_ftn4">[4]</a> <a href="https://twitter.com/_batsec_">https://twitter.com/_batsec_</a></p>
<p><a href="#_ftnref5" name="_ftn5">[5]</a> <a href="https://www.mdsec.co.uk/2021/06/bypassing-image-load-kernel-callbacks/">https://www.mdsec.co.uk/2021/06/bypassing-image-load-kernel-callbacks/</a></p>
<p><a href="#_ftnref6" name="_ftn6">[6]</a> <a href="https://github.com/strivexjun/MemoryModulePP/blob/master/MemoryModulePP.c">https://github.com/strivexjun/MemoryModulePP/blob/master/MemoryModulePP.c</a></p>
<p><a href="#_ftnref7" name="_ftn7">[7]</a> <a href="https://github.com/bats3c/DarkLoadLibrary">https://github.com/bats3c/DarkLoadLibrary</a></p>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/en/2024/10/loadlibrary-madness-dynamically-load-winhttp-dll/">LoadLibrary madness: dynamically load WinHTTP.dll</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/2024/10/loadlibrary-madness-dynamically-load-winhttp-dll/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
