<?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>OpenSSL &#8211; Eamon Woortman</title>
	<atom:link href="https://eamonwoortman.github.io/tag/openssl/feed/" rel="self" type="application/rss+xml" />
	<link>https://eamonwoortman.github.io/</link>
	<description></description>
	<lastBuildDate>Sun, 21 May 2023 07:47:38 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.4.2</generator>
	<item>
		<title>OpenSSL binary patching</title>
		<link>https://eamonwoortman.github.io/openssl-binary-patching/</link>
					<comments>https://eamonwoortman.github.io/openssl-binary-patching/#respond</comments>
		
		<dc:creator><![CDATA[eamon]]></dc:creator>
		<pubDate>Sat, 20 May 2023 20:46:52 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[assembly]]></category>
		<category><![CDATA[Ida]]></category>
		<category><![CDATA[OpenSSL]]></category>
		<category><![CDATA[Unity]]></category>
		<guid isPermaLink="false">https://eamonwoortman.github.io/openssl-binary-patching/</guid>

					<description><![CDATA[This document describes steps taken to binary patch a crash that was occurring in Besiege (Microsoft Store, 64-bit) and the 64-bit Unity Editor. 💡 Source code is available on GitHub: https://github.com/eamonwoortman/openssl-universal-patcher/ Introduction 📖 At the time of writing, we are trying to deploy a new update for Besiege on the Xbox PC/Microsoft Store platform. However, [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="has-text-color" style="color:rgb(0, 0, 0)">This document describes steps taken to binary patch a crash that was occurring in Besiege (Microsoft Store, 64-bit) and the 64-bit Unity Editor.</p>



<p class="has-background" style="background-color:rgb(241, 241, 239)"><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Source code is available on GitHub: <a href="https://github.com/eamonwoortman/openssl-universal-patcher/" target="_blank" rel="noreferrer noopener">https://github.com/eamonwoortman/openssl-universal-patcher/</a></p>



<h1 class="wp-block-heading">Introduction <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f4d6.png" alt="📖" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h1>



<p class="has-text-color" style="color:rgb(0, 0, 0)">At the time of writing, we are trying to deploy a new update for Besiege on the Xbox PC/Microsoft Store platform.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">However, a couple of users have reported that the game doesn&#8217;t open or crashes immediately. The crash logs that we received all contained the last stack trace line: <code>invalid_pointer_read_c0000005_besiege.exe!sha1_block_data_order</code>.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">After troubleshooting, we narrowed the problem down to our workshop integration (<a href="http://mod.io/" target="_blank" rel="noreferrer noopener">Mod.io</a>). It was trying to establish an HTTPS connection through the <a href="https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequest.html" target="_blank" rel="noreferrer noopener">UnityWebRequest</a>.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">Besiege was built with the older <em>64-bit 5.4.0f3 Unity</em> version, which used the <code>1.1.0-dev</code> OpenSSL library. It appears that in the Unity 5.4.0f3 Editor, and builds made with it, there&#8217;s a bug where apps that use OpenSSL (i.e., secure web request) crash for users with specific hardware specifications, specifically 10th Gen and 11th Gen Intel CPUs.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">One of our team members actually had one of these Intel models, and not only did the game build crash, but the <em>64-bit 5.4.0f3 Unity Editor</em> also crashed upon launching.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">A Reddit user called ‘shishire’ and commenters have already described the problem in <a href="https://www.reddit.com/r/Smite/comments/pl35y6/comment/he16988/?utm_source=share&amp;utm_medium=web2x&amp;context=3" target="_blank" rel="noreferrer noopener">this topic</a>; </p>



<blockquote class="wp-block-quote has-text-color" style="color:rgb(0, 0, 0)">
<p><em>The actual failure going on here on 64-bit is happening in a dll called MctsInterface.dll, and it&#8217;s occurring during a pointer dereference to a floating point number that tries to access memory that&#8217;s outside the bounds of what&#8217;s actually available to the application. That being said, one of the things I noticed is that the function this is a part of does a whole bunch of sha1sum operations in cpu-space.</em></p>
</blockquote>



<p class="has-text-color" style="color:rgb(0, 0, 0)">Additionally, Intel has released a short article about the issue. You can read <a rel="noreferrer noopener" href="https://www.intel.com/content/www/us/en/developer/articles/troubleshooting/openssl-sha-crash-bug-requires-application-update.html" target="_blank">their article</a> for more information and additional workarounds.</p>



<h2 class="wp-block-heading"><strong>Existing Workaround</strong></h2>



<p class="has-text-color" style="color:rgb(0, 0, 0)">There&#8217;s a workaround to the crash that involves setting an environment variable on the system. This variable instructs OpenSSL to use software-based hashing instead of hardware-based hashing. This solution doesn&#8217;t require patching the OpenSSL binary and may be simpler for some users.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">To set the environment variable, follow these steps:</p>



<ol>
<li>Open the Control Panel and navigate to System and Security &gt; System &gt; Advanced system settings.</li>



<li>Click on the Environment Variables button.</li>



<li>Under System Variables, click on New and enter the following information:</li>



<li>Click OK to save the changes.</li>
</ol>



<p class="has-text-color" style="color:rgb(0, 0, 0)">After setting the environment variable, restart the affected application, and it should now be able to use OpenSSL without crashing.</p>



<h2 class="wp-block-heading"><strong>Patching motivation</strong></h2>



<p class="has-text-color" style="color:rgb(0, 0, 0)">Although this workaround might work for some users, it is not a permanent fix. In fact, without the workaround, users would experience a crash immediately after downloading the game.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">If users are eager to play the game, they might search the internet for a solution. However, even if they find it, it requires changing the system environment variables, which can be daunting for regular users.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">This does not provide a great user experience, so we sought a way to patch our game.</p>



<h1 class="wp-block-heading">My patching journey <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1fa79.png" alt="🩹" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h1>



<h3 class="wp-block-heading">Attempt #1: Calling ‘SetEnvironmentVariable’ <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h3>



<p class="has-text-color" style="color:rgb(0, 0, 0)">I first set out to try to replicate the environment variable workaround through code.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">My thoughts were that if the user can fix it by setting a specific environment variable before launching it, perhaps we could set the variable ourselves from within the game.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">C# has a way of setting application-specific environment variables through <a rel="noreferrer noopener" href="https://learn.microsoft.com/en-us/dotnet/api/system.environment.setenvironmentvariable?view=netframework-4.0" target="_blank">Environment.SetEnvironmentVariable()</a>. So I used it to set the <code>OPENSSL_ia32cap</code> variable to <code>~0x20000000</code>.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">However, after trying it, we found that the game was still crashing, even though the process&#8217;s environment variable has changed.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">After thinking about it some more, this is probably because the OpenSSL initialization is part of the native Unity player and is already initialized before the mono domain is created. One way of how I could see this type of fix working is to wrap your game executable with another app (C# in this case) that would use <code>SetEnvironmentVariable()</code> before launching the inner app.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">Unfortunately, we don&#8217;t have any wrapper application around our game, so we can&#8217;t set the environment variable like this.</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide"/>



<p class="has-text-color" style="color:rgb(0, 0, 0)"><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f6a7.png" alt="🚧" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Roadblock 1</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide"/>



<h2 class="wp-block-heading">Attempt #2: Binary patching <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h2>



<p class="has-text-color" style="color:rgb(0, 0, 0)">My next attempt would be to either patch the game executable to always set the <code>OPENSSL_ia32cap</code> to <code>~0x20000000</code> or somehow patch the function that would use the flag&#8217;s value.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">I looked up the OpenSSL repository and found a function called <code>OPENSSL_cpuid_setup</code> in <a href="https://github.com/openssl/openssl/blob/c8093347f736c7991350d26048b680d0e64974a0/crypto/cpuid.c#L106" target="_blank" rel="noreferrer noopener">cpuid.c</a>.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">The <code>OPENSSL_cpuid_setup</code> function is responsible for initializing the OpenSSL library. It checks the processor vendor ID and feature flags to determine which cryptographic algorithms are available and whether hardware acceleration is supported. The function sets the <code>OPENSSL_ia32cap</code> environment variable based on the processor&#8217;s capabilities.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">I opened the game binary in <a href="https://hex-rays.com/ida-free/" target="_blank" rel="noreferrer noopener">IDA</a> and looked up the same function. At the very end, I found the instruction that would set the <code>OPENSSL_ia32cap</code> variable;</p>



<figure class="wp-block-image size-large"><img decoding="async" src="https://eamonwoortman.github.io/wp-content/uploads/2023/05/image.png" alt=""/></figure>



<p class="has-text-color" style="color:rgb(0, 0, 0)">My options here were either to patch that part of the method so it would always unset the <code>0x20000000</code> value from the <code>OPENSSL_ia32cap</code> flag or to somehow force the environment variable setting to be a constant string of <code>"~0x20000000"</code>.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">I was in the middle of trying the first option, but I then realized I would need more instructions (more bytes) than were present. I couldn&#8217;t simply replace an existing instruction without altering the functionality.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">After reading up on it, I learned that inserting instructions means looking up some kind of NOP/empty part of the binary and jumping to there from the original code.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">Because I have limited assembly/cracking experience, I wasn&#8217;t comfortable with doing this. So I decided to stop this experiment and look for alternatives.</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide"/>



<p class="has-text-color" style="color:rgb(0, 0, 0)"><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f6a7.png" alt="🚧" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Roadblock 2</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide"/>



<h2 class="wp-block-heading">Attempt #3: Binary patching (2) <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h2>



<p class="has-text-color" style="color:rgb(0, 0, 0)">While looking into setting the environment variable, I stumbled upon one of my many open browser tabs that actually contained the fix that <a href="https://github.com/openssl/openssl/commit/7123aa81e9fb19afb11fdf3850662c5f7ff1f19c#diff-fd85954e17364d4495e1e077a5768e4e" target="_blank" rel="noreferrer noopener">OpenSSL did in their 1.0.2L patch</a>.</p>



<figure class="wp-block-image size-large"><img decoding="async" src="https://eamonwoortman.github.io/wp-content/uploads/2023/05/image-1-1024x278.png" alt=""/></figure>



<p class="has-text-color" style="color:rgb(0, 0, 0)">This patched a function called <code>sha1_block_data_order_shaext</code>, which was the Intel-specific implementation of the SHA1 <code>sha1_block_data_order</code> function.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">It’s not a coincidence that the crashes that users reported were all caused in a function called <code>sha1_block_data_order</code>.</p>



<h3 class="wp-block-heading">Finding the instructions to patch</h3>



<p class="has-text-color" style="color:rgb(0, 0, 0)">Next up was to use IDA and find the corresponding instruction in the game executable. I actually built the patched OpenSSL earlier, so I opened the <code>openssl</code> lib in there and looked up the original <code>sha1_block_data_order_shaext</code> function.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">Looking up the function name was enough to take me to the corresponding function block.</p>



<figure class="wp-block-image size-large"><img decoding="async" src="https://eamonwoortman.github.io/wp-content/uploads/2023/05/image-2-1024x615.png" alt=""/></figure>



<p class="has-text-color" style="color:rgb(0, 0, 0)">And we actually found the <em><strong>patched</strong></em> instructions we needed;</p>



<div class="wp-block-kevinbatdorf-code-block-pro" style="font-size:.875rem;line-height:1.25rem"><span role="button" tabindex="0" data-code="lea     r8, [rsi+40h]
...
cmovnz  rsi, r8" style="color:#adbac7;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark-dimmed" style="background-color: #22272e" tabindex="0"><code><span class="line"><span style="color: #F47067">lea</span><span style="color: #ADBAC7">     </span><span style="color: #6CB6FF">r8</span><span style="color: #ADBAC7">, [</span><span style="color: #6CB6FF">rsi</span><span style="color: #ADBAC7">+</span><span style="color: #6CB6FF">40h</span><span style="color: #ADBAC7">]</span></span>
<span class="line"><span style="color: #ADBAC7">...</span></span>
<span class="line"><span style="color: #F47067">cmovnz</span><span style="color: #ADBAC7">  </span><span style="color: #6CB6FF">rsi</span><span style="color: #ADBAC7">, </span><span style="color: #6CB6FF">r8</span></span></code></pre></div>



<p class="has-text-color" style="color:rgb(0, 0, 0)">From the earlier patch commit on <a href="https://github.com/openssl/openssl/commit/7123aa81e9fb19afb11fdf3850662c5f7ff1f19c#diff-fd85954e17364d4495e1e077a5768e4e" target="_blank" rel="noreferrer noopener">OpenSSL&#8217;s GitHub Repo</a>, we already know they changed the <code>RAX</code> register to <code>R8</code>.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">So to look up the instruction we needed in our game binary, we simply need to reverse the patch;</p>



<div class="wp-block-kevinbatdorf-code-block-pro" style="font-size:.875rem;line-height:1.25rem"><span role="button" tabindex="0" data-code="lea     rax, [rsi+40h]
...
cmovnz  rsi, rax" style="color:#adbac7;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark-dimmed" style="background-color: #22272e" tabindex="0"><code><span class="line"><span style="color: #F47067">lea</span><span style="color: #ADBAC7">     </span><span style="color: #6CB6FF">rax</span><span style="color: #ADBAC7">, [</span><span style="color: #6CB6FF">rsi</span><span style="color: #ADBAC7">+</span><span style="color: #6CB6FF">40h</span><span style="color: #ADBAC7">]</span></span>
<span class="line"><span style="color: #ADBAC7">...</span></span>
<span class="line"><span style="color: #F47067">cmovnz</span><span style="color: #ADBAC7">  </span><span style="color: #6CB6FF">rsi</span><span style="color: #ADBAC7">, </span><span style="color: #6CB6FF">rax</span></span></code></pre></div>



<h3 class="wp-block-heading">Matching the patch instructions in our game</h3>



<p class="has-text-color" style="color:rgb(0, 0, 0)">With the new information on what instructions we needed to look out for, we can start matching them in our game binary.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">In IDA, opened up our game binary, and jumped to the <code>sha1_block_data_order</code> function and found the corresponding instructions (<code>lea rax…, cmovnz rsi …</code>) in a block after a couple of jumps.</p>



<figure class="wp-block-image size-large"><img decoding="async" src="https://eamonwoortman.github.io/wp-content/uploads/2023/05/image-3-1024x590.png" alt=""/></figure>



<p class="has-text-color" style="color:rgb(0, 0, 0)">To-be-patched instructions, 4 bytes apart</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">If we observe the Hex View on the right, you’ll notice that I’ve also marked the corresponding bytes of the two to-be-patched instructions. Observant developers will notice there are 4 bytes between the two instructions; this will be important later.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">I wanted to verify what I was seeing is correct. Since I’m not fluent in assembly and bytecode, instead of Googling and reading up on assembly instructions, I asked ChatGPT what the corresponding bytes are for each instruction.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">At the time of writing, the AI chatbot was still benevolent and obedient, so it told me the answer;</p>



<div class="wp-block-kevinbatdorf-code-block-pro" style="font-size:.875rem;line-height:1.25rem"><span role="button" tabindex="0" data-code="# lea     rax, [rsi+40h]
48 8D 46 40

# cmovnz  rsi, rax
48 0F 45 F0" style="color:#adbac7;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark-dimmed" style="background-color: #22272e" tabindex="0"><code><span class="line"><span style="color: #ADBAC7"># lea     rax, [rsi+40h]</span></span>
<span class="line"><span style="color: #6CB6FF">48</span><span style="color: #ADBAC7"> 8D </span><span style="color: #6CB6FF">46</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">40</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ADBAC7"># cmovnz  rsi, rax</span></span>
<span class="line"><span style="color: #6CB6FF">48</span><span style="color: #ADBAC7"> 0F </span><span style="color: #6CB6FF">45</span><span style="color: #ADBAC7"> F0</span></span></code></pre></div>



<p class="has-text-color" style="color:rgb(0, 0, 0)">This matches what we’ve seen in the Hex View! <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f918.png" alt="🤘" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">I also asked GPT (we go on first-name basis now) to tell me what byte to change if I wanted to change the address from <code>rax</code> to <code>r8</code>, and it basically gave me a patchable diff;</p>



<div class="wp-block-kevinbatdorf-code-block-pro" style="font-size:.875rem;--cbp-line-highlight-color:rgba(139, 186, 234, 0.2);line-height:1.25rem"><span role="button" tabindex="0" data-code="-- First sequence --
# lea     rax, [rsi+40h]
original: 48 8D 46 40
# lea     r8, [rsi+40h]
patched: 4C 8D 46 40

...

-- Second sequence --
# cmovnz  rsi, rax
original: 48 0F 45 F0
# cmovnz  rsi, r8
patched: 49 0F 45 F0" style="color:#adbac7;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark-dimmed" style="background-color: #22272e" tabindex="0"><code><span class="line"><span style="color: #F69D50">--</span><span style="color: #ADBAC7"> </span><span style="color: #96D0FF">First</span><span style="color: #ADBAC7"> </span><span style="color: #96D0FF">sequence</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">--</span></span>
<span class="line"><span style="color: #768390"># lea     rax, [rsi+40h]</span></span>
<span class="line"><span style="color: #F69D50">original:</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">48</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">8</span><span style="color: #96D0FF">D</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">46</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">40</span></span>
<span class="line"><span style="color: #768390"># lea     r8, [rsi+40h]</span></span>
<span class="line cbp-line-highlight"><span style="color: #F69D50">patched:</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">4</span><span style="color: #96D0FF">C</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">8</span><span style="color: #96D0FF">D</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">46</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">40</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6CB6FF">...</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F69D50">--</span><span style="color: #ADBAC7"> </span><span style="color: #96D0FF">Second</span><span style="color: #ADBAC7"> </span><span style="color: #96D0FF">sequence</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">--</span></span>
<span class="line"><span style="color: #768390"># cmovnz  rsi, rax</span></span>
<span class="line"><span style="color: #F69D50">original:</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">48</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">0</span><span style="color: #96D0FF">F</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">45</span><span style="color: #ADBAC7"> </span><span style="color: #96D0FF">F0</span></span>
<span class="line"><span style="color: #768390"># cmovnz  rsi, r8</span></span>
<span class="line cbp-line-highlight"><span style="color: #F69D50">patched:</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">49</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">0</span><span style="color: #96D0FF">F</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">45</span><span style="color: #ADBAC7"> </span><span style="color: #96D0FF">F0</span></span></code></pre></div>



<p class="has-background" style="background-color:rgb(241, 241, 239)"><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Note: I’m aware you can change instructions in IDA by using Edit → Patch Program → Assemble. But when I tried changing <code>rax</code> to <code>r8</code>, IDA refused with an “Invalid Operand” error. According to this Stack Overflow reply, it’s because the Assemble patcher only supports a limited amount of operations; <a href="https://stackoverflow.com/a/38529308" target="_blank" rel="noreferrer noopener">https://stackoverflow.com/a/38529308</a>.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">With the diff file generated, I can use it to apply the patch to the game binary file programmatically. This will allow for easier and faster patching of the game binary file for each new build.</p>



<h1 class="wp-block-heading">Next step; Write a patcher program <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/270d.png" alt="✍" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h1>



<p class="has-text-color" style="color:rgb(0, 0, 0)">
Now we only need to write a simple program that patches the game binary file. </p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">Once we have a patcher, we can include it in our build pipeline before packaging the game.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">IDA does provide a diff/patching method, but it uses a fixed memory offset. This doesn’t work if we’re going to update the game after the initial patch as the memory offsets change due to changes in code. So we need something that’s a bit more clever than a simple offset byte patcher. </p>



<h2 class="wp-block-heading">BSDiff / BSPatch</h2>



<p class="has-text-color" style="color:rgb(0, 0, 0)">Before writing my own diffing and patching tool, I searched for an existing one and found , or more specifically, its .NET port: .</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">To create a diff, I first needed to patch our game binary (<code>Besiege.exe</code>). I used the byte code provided by GPT and applied the patch in IDA (Edit → Patch Program → Change Byte), saving a new patched game binary (<code>Besiege.patched.exe</code>).</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">Next, I used <strong>bsdiff </strong>to create a diff between the old, unpatched game binary and the freshly patched one.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">Using this diff/patch file, I was able to patch a fresh new game build, even with code changes, and verified that the patch was working. I implemented the patcher in our build pipeline by calling <strong>bspatch</strong> after every successful build, just before packaging it.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)"><strong>Success, right?</strong></p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">Not quite&#8230;</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">While this method would work for our own game, unfortunately, on this particular platform, this patch wouldn&#8217;t work on <em>any</em> application that was built on this old OpenSSL library.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">Although my goal isn&#8217;t to make a universal patcher, I&#8217;m not sure how well this BSDiff patch holds up against massive code changes.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">And to be completely honest, I wanted to see if it was possible to create a more universal patcher so we could fix the <em>Unity 5.4.0f3 64-bit</em> <em>Editor</em> from crashing, for example.</p>



<h2 class="wp-block-heading">Writing our own patcher </h2>



<h3 class="wp-block-heading">The patch</h3>



<p class="has-text-color" style="color:rgb(0, 0, 0)">So we know we only have to patch <em>2 bytes, </em>one for the <code>lea</code> instruction and one for the <code>cmovnz</code> instruction. We also know the sequence they’re in and even the relative offset relative to each other, which is <em>4 bytes</em>.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">Now we can hardcode this into our patcher, but for the sake of readability and transparency, I decided to put all the patching information in a <a href="https://github.com/eamonwoortman/openssl-universal-patcher/blob/master/src/OpenSSLUniversalPatcher/Resources/openssl.universal.patch" target="_blank" rel="noreferrer noopener">single text file</a>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" style="font-size:.875rem;line-height:1.25rem"><span role="button" tabindex="0" data-code="# lea     rax, [rsi+40h]
original: 48 8D 46 40
# lea     r8, [rsi+40h]
patched: 4C 8D 46 40
# 4 bytes from the previous instruction
offset: 4
# cmovnz  rsi, rax
original: 48 0F 45 F0
# cmovnz  rsi, r8
patched: 49 0F 45 F0" style="color:#adbac7;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark-dimmed" style="background-color: #22272e" tabindex="0"><code><span class="line"><span style="color: #768390"># lea     rax, [rsi+40h]</span></span>
<span class="line"><span style="color: #F69D50">original:</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">48</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">8</span><span style="color: #96D0FF">D</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">46</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">40</span></span>
<span class="line"><span style="color: #768390"># lea     r8, [rsi+40h]</span></span>
<span class="line"><span style="color: #F69D50">patched:</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">4</span><span style="color: #96D0FF">C</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">8</span><span style="color: #96D0FF">D</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">46</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">40</span></span>
<span class="line"><span style="color: #768390"># 4 bytes from the previous instruction</span></span>
<span class="line"><span style="color: #F69D50">offset:</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">4</span></span>
<span class="line"><span style="color: #768390"># cmovnz  rsi, rax</span></span>
<span class="line"><span style="color: #F69D50">original:</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">48</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">0</span><span style="color: #96D0FF">F</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">45</span><span style="color: #ADBAC7"> </span><span style="color: #96D0FF">F0</span></span>
<span class="line"><span style="color: #768390"># cmovnz  rsi, r8</span></span>
<span class="line"><span style="color: #F69D50">patched:</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">49</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">0</span><span style="color: #96D0FF">F</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">45</span><span style="color: #ADBAC7"> </span><span style="color: #96D0FF">F0</span></span></code></pre></div>



<p>openssl.universal.patch</p>



<h3 class="wp-block-heading">The patching application</h3>



<p class="has-text-color" style="color:rgb(0, 0, 0)">Once again, I asked ChatGPT to help me get started, and it did an okay job of outlining the patcher application. Although it was broken at first, it provided enough groundwork to get me started.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">The C# console application will perform the following steps:</p>



<ul>
<li>Load the <strong>target binary</strong> as a <code>byte</code> array</li>



<li>Parse the <strong>patch file</strong> into a <code>Patch</code> class</li>



<li>Find any number of occurrences of the byte sequences that need to be patched</li>



<li>Replace these byte sequences in the original <code>byte</code> array with our patched bytes, but only if exactly one occurrence is found</li>



<li>Write the patched bytes to a new binary file</li>
</ul>



<p class="has-text-color" style="color:rgb(0, 0, 0)">The main patching method ended up looking like this; </p>



<div class="wp-block-kevinbatdorf-code-block-pro" style="font-size:.875rem;line-height:1.25rem"><span role="button" tabindex="0" data-code="public static bool Apply(string inputPath, string outputPath, string patchFileText) {
	byte[] originalBytes = File.ReadAllBytes(inputPath);
	Patch patch = ParsePatchFile(patchFileText);

	List&lt;PatternOffsets&gt; offsets = FindSequencePattern(originalBytes, patch.FirstSequence, patch.SecondSequence, patch.RelativeOffset);
	if (offsets.Count == 0) {
		Console.Error.WriteLine(&quot;Error, pattern not found in target.&quot;);
		return false;
	}
	if (offsets.Count &gt; 1) {
		Console.Error.WriteLine(&quot;Error, pattern found multiple times in target.&quot;);
		return false;
	}

	Console.WriteLine(&quot;Sequence pattern found in target, patching...&quot;);

	var patternOffsets = offsets[0];
	var firstOffset = patternOffsets.FirstOffset;
	var secondOffset = patternOffsets.SecondOffset;

	// Apply the first sequence patch
	var patchedBytes = patch.FirstSequence.Patched;
	Array.Copy(patchedBytes, 0, originalBytes, firstOffset, patchedBytes.Length);

	// Apply the second sequence patch
	patchedBytes = patch.SecondSequence.Patched;
	Array.Copy(patch.SecondSequence.Patched, 0, originalBytes, secondOffset, patchedBytes.Length);

	// Write the patched bytes to the output file
	File.WriteAllBytes(outputPath, originalBytes);

	Console.WriteLine(&quot;Patched file written to &quot; + outputPath);
	return true;
}" style="color:#adbac7;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark-dimmed" style="background-color: #22272e" tabindex="0"><code><span class="line"><span style="color: #F47067">public</span><span style="color: #ADBAC7"> </span><span style="color: #F47067">static</span><span style="color: #ADBAC7"> </span><span style="color: #F47067">bool</span><span style="color: #ADBAC7"> </span><span style="color: #DCBDFB">Apply</span><span style="color: #ADBAC7">(</span><span style="color: #F47067">string</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">inputPath</span><span style="color: #ADBAC7">, </span><span style="color: #F47067">string</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">outputPath</span><span style="color: #ADBAC7">, </span><span style="color: #F47067">string</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">patchFileText</span><span style="color: #ADBAC7">) {</span></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #F47067">byte</span><span style="color: #ADBAC7">[] </span><span style="color: #F69D50">originalBytes</span><span style="color: #ADBAC7"> </span><span style="color: #F47067">=</span><span style="color: #ADBAC7"> File.</span><span style="color: #DCBDFB">ReadAllBytes</span><span style="color: #ADBAC7">(inputPath);</span></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #F69D50">Patch</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">patch</span><span style="color: #ADBAC7"> </span><span style="color: #F47067">=</span><span style="color: #ADBAC7"> </span><span style="color: #DCBDFB">ParsePatchFile</span><span style="color: #ADBAC7">(patchFileText);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #F69D50">List</span><span style="color: #ADBAC7">&lt;</span><span style="color: #F69D50">PatternOffsets</span><span style="color: #ADBAC7">&gt; </span><span style="color: #F69D50">offsets</span><span style="color: #ADBAC7"> </span><span style="color: #F47067">=</span><span style="color: #ADBAC7"> </span><span style="color: #DCBDFB">FindSequencePattern</span><span style="color: #ADBAC7">(originalBytes, patch.FirstSequence, patch.SecondSequence, patch.RelativeOffset);</span></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #F47067">if</span><span style="color: #ADBAC7"> (offsets.Count </span><span style="color: #F47067">==</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">0</span><span style="color: #ADBAC7">) {</span></span>
<span class="line"><span style="color: #ADBAC7">		Console.Error.</span><span style="color: #DCBDFB">WriteLine</span><span style="color: #ADBAC7">(</span><span style="color: #96D0FF">&quot;Error, pattern not found in target.&quot;</span><span style="color: #ADBAC7">);</span></span>
<span class="line"><span style="color: #ADBAC7">		</span><span style="color: #F47067">return</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">false</span><span style="color: #ADBAC7">;</span></span>
<span class="line"><span style="color: #ADBAC7">	}</span></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #F47067">if</span><span style="color: #ADBAC7"> (offsets.Count </span><span style="color: #F47067">&gt;</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">1</span><span style="color: #ADBAC7">) {</span></span>
<span class="line"><span style="color: #ADBAC7">		Console.Error.</span><span style="color: #DCBDFB">WriteLine</span><span style="color: #ADBAC7">(</span><span style="color: #96D0FF">&quot;Error, pattern found multiple times in target.&quot;</span><span style="color: #ADBAC7">);</span></span>
<span class="line"><span style="color: #ADBAC7">		</span><span style="color: #F47067">return</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">false</span><span style="color: #ADBAC7">;</span></span>
<span class="line"><span style="color: #ADBAC7">	}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ADBAC7">	Console.</span><span style="color: #DCBDFB">WriteLine</span><span style="color: #ADBAC7">(</span><span style="color: #96D0FF">&quot;Sequence pattern found in target, patching...&quot;</span><span style="color: #ADBAC7">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #F47067">var</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">patternOffsets</span><span style="color: #ADBAC7"> </span><span style="color: #F47067">=</span><span style="color: #ADBAC7"> offsets[</span><span style="color: #6CB6FF">0</span><span style="color: #ADBAC7">];</span></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #F47067">var</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">firstOffset</span><span style="color: #ADBAC7"> </span><span style="color: #F47067">=</span><span style="color: #ADBAC7"> patternOffsets.FirstOffset;</span></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #F47067">var</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">secondOffset</span><span style="color: #ADBAC7"> </span><span style="color: #F47067">=</span><span style="color: #ADBAC7"> patternOffsets.SecondOffset;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #768390">// Apply the first sequence patch</span></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #F47067">var</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">patchedBytes</span><span style="color: #ADBAC7"> </span><span style="color: #F47067">=</span><span style="color: #ADBAC7"> patch.FirstSequence.Patched;</span></span>
<span class="line"><span style="color: #ADBAC7">	Array.</span><span style="color: #DCBDFB">Copy</span><span style="color: #ADBAC7">(patchedBytes, </span><span style="color: #6CB6FF">0</span><span style="color: #ADBAC7">, originalBytes, firstOffset, patchedBytes.Length);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #768390">// Apply the second sequence patch</span></span>
<span class="line"><span style="color: #ADBAC7">	patchedBytes </span><span style="color: #F47067">=</span><span style="color: #ADBAC7"> patch.SecondSequence.Patched;</span></span>
<span class="line"><span style="color: #ADBAC7">	Array.</span><span style="color: #DCBDFB">Copy</span><span style="color: #ADBAC7">(patch.SecondSequence.Patched, </span><span style="color: #6CB6FF">0</span><span style="color: #ADBAC7">, originalBytes, secondOffset, patchedBytes.Length);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #768390">// Write the patched bytes to the output file</span></span>
<span class="line"><span style="color: #ADBAC7">	File.</span><span style="color: #DCBDFB">WriteAllBytes</span><span style="color: #ADBAC7">(outputPath, originalBytes);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ADBAC7">	Console.</span><span style="color: #DCBDFB">WriteLine</span><span style="color: #ADBAC7">(</span><span style="color: #96D0FF">&quot;Patched file written to &quot;</span><span style="color: #ADBAC7"> </span><span style="color: #F47067">+</span><span style="color: #ADBAC7"> outputPath);</span></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #F47067">return</span><span style="color: #ADBAC7"> </span><span style="color: #6CB6FF">true</span><span style="color: #ADBAC7">;</span></span>
<span class="line"><span style="color: #ADBAC7">}</span></span></code></pre></div>



<p>main patching method</p>



<div class="wp-block-kevinbatdorf-code-block-pro" style="font-size:.875rem;line-height:1.25rem"><span role="button" tabindex="0" data-code="struct PatternOffsets {
	public int FirstOffset;
	public int SecondOffset;
}

struct SequencePair {
	public byte[] Original;
	public byte[] Patched;
}

class Patch {
	public SequencePair FirstSequence;
	public SequencePair SecondSequence;
	public int RelativeOffset;
}" style="color:#adbac7;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark-dimmed" style="background-color: #22272e" tabindex="0"><code><span class="line"><span style="color: #F47067">struct</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">PatternOffsets</span><span style="color: #ADBAC7"> {</span></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #F47067">public</span><span style="color: #ADBAC7"> </span><span style="color: #F47067">int</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">FirstOffset</span><span style="color: #ADBAC7">;</span></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #F47067">public</span><span style="color: #ADBAC7"> </span><span style="color: #F47067">int</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">SecondOffset</span><span style="color: #ADBAC7">;</span></span>
<span class="line"><span style="color: #ADBAC7">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F47067">struct</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">SequencePair</span><span style="color: #ADBAC7"> {</span></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #F47067">public</span><span style="color: #ADBAC7"> </span><span style="color: #F47067">byte</span><span style="color: #ADBAC7">[] </span><span style="color: #F69D50">Original</span><span style="color: #ADBAC7">;</span></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #F47067">public</span><span style="color: #ADBAC7"> </span><span style="color: #F47067">byte</span><span style="color: #ADBAC7">[] </span><span style="color: #F69D50">Patched</span><span style="color: #ADBAC7">;</span></span>
<span class="line"><span style="color: #ADBAC7">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F47067">class</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">Patch</span><span style="color: #ADBAC7"> {</span></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #F47067">public</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">SequencePair</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">FirstSequence</span><span style="color: #ADBAC7">;</span></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #F47067">public</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">SequencePair</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">SecondSequence</span><span style="color: #ADBAC7">;</span></span>
<span class="line"><span style="color: #ADBAC7">	</span><span style="color: #F47067">public</span><span style="color: #ADBAC7"> </span><span style="color: #F47067">int</span><span style="color: #ADBAC7"> </span><span style="color: #F69D50">RelativeOffset</span><span style="color: #ADBAC7">;</span></span>
<span class="line"><span style="color: #ADBAC7">}</span></span></code></pre></div>



<p>data objects</p>



<h3 class="wp-block-heading">A Couple of Gotchas</h3>



<p class="has-text-color" style="color:rgb(0, 0, 0)">When writing this patcher, there were a couple of things to watch out for. Firstly, it was important to ensure that the two-byte sequences were found <em>in pairs</em>, with the relative offset between them. Otherwise, we might end up patching two entirely unrelated sequences that just happened to look similar.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">Secondly, even though the sequence pair is unlikely to occur more than once, I wanted to make sure that the patcher would stop patching if it did.</p>



<h1 class="wp-block-heading">Testing it <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f4af.png" alt="💯" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h1>



<p class="has-text-color" style="color:rgb(0, 0, 0)">While developing the patcher, I tested whether the assembly instructions were changed in the patched executable. Additionally, I confirmed with my colleague the specific compromised Intel hardware.</p>



<figure class="wp-block-table"><table><thead><tr><th>App</th><th>Engine</th><th>Patch compatible</th><th>Confirmed IDA</th><th>Confirmed on Hardware</th></tr></thead><tbody><tr><td>Besiege</td><td>Unity v5.4.0f3</td><td><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td></tr><tr><td>Unity Editor</td><td>Unity v5.4.0f3</td><td><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td></tr><tr><td>Test Game</td><td>Unreal 4.21.2</td><td><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td><td><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td></tr></tbody></table></figure>



<p class="has-text-color" style="color:rgb(0, 0, 0)">
The only app which I haven’t verified whether it would fix the crash on the specific Intel hardware is the Unreal Test Game. The test game itself is a boilerplate FPS Game template that comes with Unreal 4.21.2. I did verify the before and after in IDA and could confirm that it was compromised with the same faulty OpenSSL code and that the patch would fix it.</p>



<h1 class="wp-block-heading">Conclusion <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f3c1.png" alt="🏁" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h1>



<p class="has-text-color" style="color:rgb(0, 0, 0)">With a little bit of effort, we were able to repurpose the existing, <a href="https://github.com/openssl/openssl/commit/7123aa81e9fb19afb11fdf3850662c5f7ff1f19c#diff-fd85954e17364d4495e1e077a5768e4e" target="_blank" rel="noreferrer noopener">internal OpenSSL library patch</a> into an all-purpose, universal binary patch.  Although, disclaimer: &#8220;universal&#8221; might be a stretch. This may work for these particular apps and engine versions, but it may not work for your particular situation.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">As a reminder, all code is available for free on GitHub: <a href="https://github.com/eamonwoortman/openssl-universal-patcher/">https://github.com/eamonwoortman/openssl-universal-patcher/</a>.</p>



<p class="has-text-color" style="color:rgb(0, 0, 0)">If you found this even slightly useful or an interesting read, please consider buying me a coffee! <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f64f.png" alt="🙏" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<script type="text/javascript" src="https://cdnjs.buymeacoffee.com/1.0.0/button.prod.min.js" data-name="bmc-button" data-slug="eamonw" data-color="#FFDD00" data-emoji=""  data-font="Cookie" data-text="Buy me a coffee" data-outline-color="#000000" data-font-color="#000000" data-coffee-color="#ffffff" ></script>



<h1 class="wp-block-heading">Resources</h1>



<p class="has-text-color" style="color:rgb(0, 0, 0)">These links provide additional information and context for the topics discussed in the article:</p>



<h3 class="wp-block-heading">OpenSSL</h3>



<ul>
<li><a href="https://github.com/openssl/openssl/blob/c8093347f736c7991350d26048b680d0e64974a0/crypto/cpuid.c#L106" target="_blank" rel="noreferrer noopener">cpuid.c</a>: The <code>OPENSSL_cpuid_setup</code> function in the OpenSSL repository on GitHub that initializes the library by checking the processor vendor ID and feature flags.</li>



<li><a href="https://github.com/openssl/openssl/commit/7123aa81e9fb19afb11fdf3850662c5f7ff1f19c#diff-fd85954e17364d4495e1e077a5768e4e" target="_blank" rel="noreferrer noopener">OpenSSL 1.0.2L patch</a>: A commit in the OpenSSL repository that contains a patch for the library&#8217;s Intel-specific implementation of the SHA1 function.</li>



<li><a href="https://github.com/openssl/openssl" target="_blank" rel="noreferrer noopener">OpenSSL repository</a>: The GitHub repository for the OpenSSL library.</li>
</ul>



<h3 class="wp-block-heading">Tools</h3>



<ul>
<li><a href="https://github.com/mendsley/bsdiff" target="_blank" rel="noreferrer noopener">bsdiff.net</a>: A website that provides a binary diffing tool called BSDiff.</li>



<li><a href="https://github.com/LogosBible/bsdiff.net" target="_blank" rel="noreferrer noopener">bsdiff.net .NET port</a>: The .NET port of BSDiff available on GitHub.</li>



<li><a href="https://hex-rays.com/ida-free/" target="_blank" rel="noreferrer noopener">IDA</a>: A disassembler and debugger software that allows users to analyze binary code.</li>
</ul>



<h3 class="wp-block-heading">Other</h3>



<ul>
<li>Reddit post: <a href="https://www.reddit.com/r/gamedev/comments/49d0f3/openssl_binary_patching/" target="_blank" rel="noreferrer noopener">https://www.reddit.com/r/gamedev/comments/49d0f3/openssl_binary_patching/</a></li>



<li>Intel article: <a href="https://www.intel.com/content/www/us/en/developer/articles/troubleshooting/openssl-sha-crash-bug-requires-application-update.html" target="_blank" rel="noreferrer noopener">https://software.intel.com/content/www/us/en/develop/articles/openssl-ia32-capabilities-change-with-newer-generation-intel-processors.html</a></li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://eamonwoortman.github.io/openssl-binary-patching/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
