Citrix XenApp/XenDesktop API Hooking Explained

What is API Hooking?

API hooking is all about making others do things they never even knew they could do. More precisely: tricking other processes into doing things differently from what their developers programmed.

API hooking is done in two steps: first, you need access to another process’ memory. Second you manipulate memory addresses so that whenever the other process wants to call certain operating system API functions, your code is called instead. Let’s explain this in more detail.

Getting Access: AppInit_DLLs

Getting access to the memory of another process can be tricky. It is by far easier to use a technique not too dissimilar to a trojan horse and have your code automatically loaded into all processes created in the system. That is exactly what AppInit_DLLs does.

AppInit_DLLs has been part of Windows since the dawn of time. Because tampering with unsuspecting processes can have severe security and stability implications Microsoft disabled the functionality by default starting with Vista, but enabling it is as simple as changing a registry value (LoadAppInit_DLLs).

Technically, AppInit_DLLs is a registry value located in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows. By default it is empty. When User32.dll initializes, it reads the AppInit_DLLs registry value and loads all DLL names it finds in that value into memory. As User32.dll is one of the most common Windows DLLs this basically affects every single process.

Think of AppInit_DLLs as a free delivery mechanism that puts your code right into the heart of all processes running on your Windows machine. But wait: I explained how you can get your DLL loaded into another process’ memory, but how do you make that other process execute your code so that you can install the API hook? Easy: whenever a DLL is loaded, the OS automatically calls the DllMain function of the DLL. That is where you install the hook.

The Hook

When processes need to do basic stuff like reading from a file, sending data across the network or accessing the registry, they call an API function provided by the operating system for that task. This might happen through multiple layers, but eventually there is always an API function that does the job. This is true for every programming language, including runtime environments like .NET and Java.

If you control how a process accesses the operating system APIs, you control the information flowing in and out of the process. You also control what that process is doing.

Here is an example: you want to capture a process’ registry activity? Simple; hook the registry API functions. Whenever the process tries to open a key or change a value, your code is called and you can log the activity. Then you call the original API function – you do not want to intrude, you just want to know what is going on.

But you could just as well change parameters before making the API call. Redirecting from HKLM to HKCU is as simple as changing a single parameter. The hooked process would never know what happened.

So how do we install our hooks? The typical way of calling operating system API functions is through an import address table (IAT). When the compiler generates code it does not know at which memory addresses in the OS DLLs the API functions will be located on the user’s machine, so it uses dummy addresses. These are replaced with the real addresses by the Windows DLL loader. To keep this process simple a lookup table is used, the IAT.

Installing the hook involves locating the entry for the API function to be hooked in the IAT. Then you replace it with the address of a function in your DLL. Done. From now on your code is called instead of, say, RegOpenKeyEx.

Citrix’ Way of Hooking

Remoting applications and desktops is no small feat, and Citrix needs many different hooks in order to pull it off. To simplify management a single hook DLL, Mfaphook.dll is added to the AppInit_DLLs registry value when the XenApp/XenDesktop VDA is installed. Actually, two hook DLLs are added:

  • Mfaphook.dll to the 32-bit registry: HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs
  • Mfaphook64.dll to the 64-bit registry: HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs

These two AppInit_DLLs registry values ensure that Mfaphook[64].dll is loaded into practically all processes created on machines with XenApp/XenDesktop installed. However, depending on the host process entirely different hooks are required. That is why Citrix has implemented a flexible configuration scheme to specify which hook DLLs are loaded into which processes. Mfaphook[64].dll reads that configuration from the registry key HKLM\SOFTWARE\Citrix\CtxHook\AppInit_Dlls:

Citrix XenApp API hook configuration

As you can see above there is one registry key below the AppInit_DLLs key per hook. Each hook’s key has a FilePathName value that contains the path and name of the hook DLL to be loaded. Optional subkeys control which processes the hook DLL is loaded into; no subkey stands for all processes.

Disabling Hooks

API Hooks change the way an application operates. Due to that nature hooks may cause problems. If you experience weird application malfunctions it might be a good idea to test with some or all hooks disabled.

Disabling API Hooking

To disable API hooking altogether set the value LoadAppInit_DLLs to 0 (REG_DWORD).

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\LoadAppInit_DLLs = 0 [REG_DWORD]

Disabling Citrix Hooks

To disable specific Citrix hooks set the Flag value below the hook’s registry key to 0 (REG_DWORD), e.g. to disable the multi monitor hook:

HKLM\SOFTWARE\Citrix\CtxHook\AppInit_Dlls\Multiple Monitor Hook\Flag = 0 [REG_DWORD]

Disabling Citrix Hooks for one Executable

To disable all Citrix hooks for specific executables create a comma-separated list of executable names in the string value ExcludedImageNames, e.g.:

HKLM\SOFTWARE\Citrix\CtxHook\ExcludedImageNames = calc.exe,notepad.exe [REG_SZ]

List of all Citrix Hooks

XenApp 7.6: 64-Bit Hooks

The following table lists all hooks loaded into 64-bit processes.

Hook name Hook DLL Processes to hook Description
CreateProcessHook CreateProcessHook64.dll explorer.exe, tabtip.exe
CtxMFPlugin CtxMFPlugin64.dll * Media player
CtxNotif Launcher ctxnflau64.dll winlogon.exe
Flash Legacy sphook64.dll iexplore.exe
Graphics Helper CtxGraphicsHelper64.dll * GPU sharing
Multiple Monitor Hook mmhook64.dll *
Seamless Explorer explhook64.dll explorer.exe Prevents published Explorer from displaying a full desktop
SfrHook Sfrhook64.dll * Special folder redirection
Shell Hook ShellHook64.dll * Support for FlashWindow() API
Smart Card Hook scardhook64.dll *
UPD Printer hook cpprov.dll spoolsv.exe
UPS win32Spl hook Win32SplHook.dll spoolsv.exe
VIPHook viphook64.dll * Virtual IP address hook (CTX125506)

XenApp 7.6: 32-Bit Hooks

The following table lists all hooks loaded into 32-bit processes.

Hook name Hook DLL Processes to hook Description
ActiveSync asynchook.dll rapimgr.exe, wcescomm.exe, WCESMgr.exe
CreateProcessHook CreateProcessHook.dll explorer.exe, tabtip.exe
CtxMFPlugin CtxMFPlugin.dll * Media player
Flash Legacy sphook.dll iexplore.exe
Graphics Helper CtxGraphicsHelper.dll * GPU sharing
HDXMediaStreamForFlash HdxFlashHook.dll iexplore.exe
Multiple Monitor Hook mmhook.dll *
Seamless Explorer explhook.dll explorer.exe Prevents published Explorer from displaying a full desktop
SfrHook Sfrhook.dll * Special folder redirection
Shell Hook ShellHook.dll * Support for FlashWindow() API
Smart Card Hook scardhook.dll *
Twain Hook twnhook.dll * Communicates with CtxTwnPA.exe on the client through a virtual channel
VIPHook viphook64.dll * Virtual IP address hook (CTX125506)

XenDesktop 7.6: 64-Bit Hooks

The following table lists all hooks loaded into 64-bit processes.

Hook name Hook DLL Processes to hook Description
CreateProcessHook CreateProcessHook64.dll explorer.exe, tabtip.exe
FullScreenHook picaFullScreenHookX64.dll * Citrix HDX 3D for Pro Graphics Full Screen Hook
Multiple Monitor Hook mmhook64.dll control.exe, explorer.exe, logonui.exe, rundll32.exe, SelfService.exe
PicaFusChoiceDialogHook PicaFusChoiceDialogHook64.dll rundll32.exe Citrix PortICA Fast User Switching Choice Dialog Hook DLL
PicaWaveHook PicaWaveHook64.dll * Citrix PortICA Wave Audio Hook DLL
PicaWinlogonHook PicaWinlogonHook64.dll winlogon.exe Citrix PortICA Winlogon Hook DLL
Seamless Explorer explhook64.dll explorer.exe, userinit.exe Prevents published Explorer from displaying a full desktop
Shell Hook ShellHook64.dll * Support for FlashWindow() API
Smart Card Hook SCardHook64.dll *
UI Tweak picaUiTweakHook64.dll explorer.exe, rundll32.exe, SystemPropertiesAdvanced.exe, SystemPropertiesPerformance.exe, winlogon.exe Citrix UI Preferences Hook
Unicode Injection IME Hook cxinjime64.dll *
UPD Printer hook cpprov.dll spoolsv.exe
UPS win32Spl hook Win32SplHook.dll spoolsv.exe
WTS Hook PicaWtsHook64.dll *

XenDesktop 7.6: 32-Bit Hooks

The following table lists all hooks loaded into 32-bit processes.

Hook name Hook DLL Processes to hook Description
CreateProcessHook CreateProcessHook.dll explorer.exe, tabtip.exe
CtxMFPlugin CtxMFPlugin.dll firefox.exe, iexplore.exe, lync.exe, realplay.exe, wmplayer.exe Media player
FullScreenHook picaFullScreenHookX86.dll * Citrix HDX 3D for Pro Graphics Full Screen Hook
HDXMediaStreamForFlash HdxFlashHook.dll iexplore.exe
Multiple Monitor Hook mmhook.dll control.exe, explorer.exe, logonui.exe, rundll32.exe, SelfService.exe
PICA Passthrough picaPassThruHook.dll wfica32.exe
PicaFusChoiceDialogHook PicaFusChoiceDialogHook.dll rundll32.exe Citrix PortICA Fast User Switching Choice Dialog Hook DLL
PicaWaveHook PicaWaveHook.dll * Citrix PortICA Wave Audio Hook DLL
PicaWinlogonHook PicaWinlogonHook.dll winlogon.exe Citrix PortICA Winlogon Hook DLL
Seamless Explorer explhook.dll explorer.exe, userinit.exe Prevents published Explorer from displaying a full desktop
Shell Hook ShellHook.dll * Support for FlashWindow() API
Smart Card Hook SCardHook.dll *
Twain Hook twnhook.dll * Communicates with CtxTwnPA.exe on the client through a virtual channel
UI Tweak picaUiTweakHook.dll explorer.exe, rundll32.exe, SystemPropertiesAdvanced.exe, SystemPropertiesPerformance.exe, winlogon.exe Citrix UI Preferences Hook
Unicode Injection IME Hook cxinjime.dll *
WTS Hook PicaWtsHook.dll *

Fun Fact

Did you notice that Citrix is hooking one of their own processes on XenDesktop? The VDA hooks Receiver (wfica32.exe). It would most likely have been better to talk to the developers on the Receiver team and ask them to change some of their code. Hooking might achieve the same goal, but in a much less friendly way.

, ,

6 Responses to Citrix XenApp/XenDesktop API Hooking Explained

  1. Sandro Christiaan October 2, 2015 at 07:21 #

    Hey Helge,

    Excellent information.

    Thanks,
    S.

  2. Joe Nord October 2, 2015 at 15:23 #

    Nice post Helge. I add that AppInit_Dlls is only processed when the Windows component user32.dll is loaded into the process. An interesting side-effect is that if the process doesn’t link user32.lib, no hooks get installed. In Citrix App Streaming, we took an extra step to force-load user32.dll into executed processes, even if they didn’t link it. With this, our registry and COM filtering would reliably be in place.

    MfAppHook is mostly a “layer above”. Since the technique of hooking has a habit of changing with each release of the operating system, most of the XA/XD system programs hooks using the internal “hook SDK” and MfAppHook. Changes to the operating system or bugs/enhancements in hook implementation can then be implemented in one-spot. None of this is easy. There are smart folks in the halls.

    • Helge Klein October 2, 2015 at 15:43 #

      Thanks for the great additional information!

  3. Martin Latteier October 3, 2015 at 11:28 #

    Very good information, thanks for sharing Helge.

    Another fact: The AppInit_DLL feature is disabled by Windows when UEFI Secure Boot is enabled. That’s why you cannot run XenApp or XenDesktop VDAs on Hyper-V Generation 2 machines with Secure Boot enabled.

    https://msdn.microsoft.com/de-de/library/windows/desktop/dn280412

    • C. L. Jones June 16, 2016 at 11:50 #

      Very, very good information to know! Thank you, Martin!

  4. Sandeep October 6, 2015 at 21:07 #

    Hooks in wfica32 are need for double hop use case!

    Also with 7.6 FP3, hook dll can be disabled per process. To do so, add the process name as a key under the hook key and create a “Flag” value of dword type and give it a value 512 (0x200).

Leave a Reply