A patch is a piece of software designed to fix problems.
Hot patching is a mechanism of applying the patch to an application without requiring to shutdown or restart the system or the program concerned. This addresses the problems related to unavailability of service provided by the system or the program.
We came across a situation where a DLL is loaded by one of the critical processes in a system and that process demands high availability. The DLL has exported functions that are supposed to perform the core operations within the process. We identified a critical flaw in one of the exported functions from the DLL. One constraint we had while trying to fix the problem was to avoid any down time of this critical process.
We solved this problem by using the hot patch mechanism. We used an external process to inject a DLL [Hot patch]. This DLL has the corrected version of the defective function and also a hook to
GetProcAddress function. As we know, calling
GetProcAddress returns the address of the exported function from the specified DLL. By hooking into the
GetProcAddress API, we monitored the requests to the exported function. When we find that the request was made for the flawed function, we just returned the address of the updated function which was part of the injected DLL.
By intercepting the calls of
GetProcAddress API, we redirected the requests from the flawed function to the corrected function.
We could resolve this problem by using the concepts like DLL injection and API hooking.
Hot Patch Structure
This hot patching structure has the following binaries:
- Hot Patch DLL: This DLL has only exported functions that are updated and will be used as replacement for the flawed functions. This also has the hooking logic to hook to
GetProcAddress API exported by Kernel32.DLL.
- Updater.exe: This process injects the hot patched DLL into the target process.
How to Inject DLL into a Remote Process
One method of injecting a DLL into a remote process requires a thread in the remote process to call
LoadLibray of the desired DLL. Since we can't control the threads in a process other that our own, the solution would be to create a new thread in the target process. This enables us to have full control over the code that this thread is going to execute.
We can create a thread in a remote process using the following Windows API:
HANDLE hProcess, </span /> PSECURITY_ATTRIBUTES psa,
PDWORD pdwThreadId );
After creating a new thread in the target process, we need to make sure that there is a call to
LoadLibrary API that will load the DLL into the target process.
Following is the complete set of steps for injecting a DLL into the target process:
VirtualAllocEx API to allocate memory equal to the size of DLL full file path in the remote process:
VirtualAllocEx(hProcess, NULL, dwSizeOfFilePath, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory to copy the DLL's full file path in the allocated space [Step 1]:
(void</span />*)szDLLFilePath, dwSizeOfFilePath,NULL);
CreateRemoteThread API to create thread in the remote process passing in the address of
LoadLibary API and also the memory location of the DLL's full file path.
hProcess, </span /> NULL,
(LPTHREAD_START_ROUTINE) ::GetProcAddress(hKernel32,"</span />LoadLibraryA"</span />),
pDLLFilePath, </span /> 0</span />,
VirtualFreeEx function to free the memory allocated in step 1:
::VirtualFreeEx( hProcess, pDLLFilePath, dwSize, MEM_RELEASE );
How to Perform API Hooking using Import Section
Using module’s import section to perform hooking is quiet robust and easy to implement. To hook to a particular function, all we need to do is change the address of the flawed function in the module's import section.
We are trying to Hook to the
GetProcAddress API exported by Kernel32.dll.
Following is the complete set of steps for API hooking:
- Locate the Module’s import section by calling
- Loop through import section for the DLL which contains API that we want to hook. In this case, we would be searching for Kernel32.dll.
- Once the DLL module is located, get the address to the array of
IMAGE_THUNK_DATA structure that contains the information about the imported symbols:
pThunk = (PIMAGE_THUNK_DATA)((PBYTE)hModule + pImportDesc-></span />FirstThunk);
- Once the address of the exported is located, use the following APIs to update the address to the new function that needs to be hooked:
WriteProcessMemory(GetCurrentProcess(), ppfn, &pNewFunction,
sizeof</span />(pNewFunction), NULL);
VirtualProtect(ppfn, sizeof</span />(pNewFunction), dwOldProtect,&dwOldProtect);
When Are We Going to Perform this Hooking
Immediately after injecting the DLL into the remote process,
LoadLibary calls the
DLLMain of the injected DLL with
DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
switch</span />( ul_reason_for_call )
case</span /> DLL_PROCESS_ATTACH:
HookTheAPI(); </span /> break</span />;
Implementing Our Own GetProcAddress
MyGetProcAddress will intercept all the calls made to
GetProcAddress APIs to monitor if there is any request for the faulting function and if so, return the address of the corrected function.
FARPROC WINAPI MyGetProcAddress(HMODULE hmod, PCSTR pszProcName)
pOldFunAdd = GetProcAddress(GetModuleHandle("</span />MySubsystem.dll"</span />), "</span />Foo"</span />);
pNewFunAdd = GetProcAddress(GetModuleHandle("</span />MySubsystem.HP.dll"</span />), "</span />"</span />Foo"</span />);
pRetFunAdd = GetProcAddress(hmod, pszProcName);
if((NULL != pOldFunAdd) && (NULL != pNewFunAdd))
// if the request is of that Faulting Function
if(pOldFunAdd == pRetFunAdd )
pRetFunAdd = pNewFunAdd; // Return address of
// corrected function
return pRetFunAdd ;
The attached binaries demo the hot patching implemented using the DLL Injection and Function Hooking. To keep the thing simple and for easy understanding, I am demonstrating with a very basic functionality. Please ignore the code optimizations for now:
- MySubsystem.DLL: This DLL exports following functions
RandomNumber: Returns a random number
SleepTime: Specifies the time to sleep before making the other call to
- MyProcess.exe: This process loads the MySubsystem.DLL and displays the
RandomNumbers in console after sleeping for the specified amount of time as returned by MySubsystem.DLL.
- Change Request: Displays the random numbers which are even. Odd number should not be displayed on the console. This has to be accomplished without restarting the process MyProcess.exe.
- MySubsystem.HP.DLL: This is a HOT Patch DLL that contains the corrected
MyRandomNumber as per the request. This also has the implementation for Hooking and Hooked function
- Updater.exe: This process injects the MySubsystem.HP.DLL into MyProcess.exe
Run MyProcess.exe to see that
RandomNumbers which are both even and odd are getting displayed. Run the updater.exe and you will see only even numbers getting displayed. All the odd numbers are skipped.
One limitation for this approach is that the functions that are exported can be hot patched.
- 6th October, 2010: Initial version