IME as a possible keylogger

2005-11-01

Masaki Suenaga

Symantec Security Response, Japan
Editor: Helen Martin

Abstract

Using components of Windows multilingual support, it is possible to create a file that will capture keystrokes on a target system while using the OS to protect that file from removal or deletion. Masaki Suenaga explains how an IME could be used as a keylogger.


Introduction

The aim of this article is to outline two potential methods for using an IME as a keylogger: by hacking a genuine IME for the Far East versions of Windows and by creating a fake IME for other versions of Windows. Using components of Windows multilingual support, it is possible to create a file that will capture keystrokes on a target system while using the OS to protect that file from removal or deletion.

To begin, I'll explain what an IME, or input method editor is. The Chinese, Japanese and Korean writing systems use thousands of characters: Hanzi (Chinese characters) in Chinese; Kanji (Chinese characters), Hiragana and Katakana in Japanese; Hangeul and Hanja (Chinese characters) in Korean. To represent these characters, each of these languages has its own multi-byte character code sets. On ASCII code-based Windows such as Windows 95, the double byte character set or DBCS is used, where each two-byte sequence represents one character. While DBCS is no longer commonly used, it is still used on Windows XP if a program does not call Unicode APIs. Starting with Windows 2000, Microsoft's desktop operating systems have primarily used Unicode for cross-compatibility and ease of use.

If a keyboard had thousands of keys, as was once the case with mechanical typewriters, there would be no need to convert multiple keystrokes to a single character. However, most modern keyboards have only around 100 keys. Therefore, we need something to convert keystrokes to characters before being used in an application. This kind of software is called a front-end processor or FEP, and IME is the standard name for FEPs used in Windows environments.

keylogger1.jpg
 

The image above shows some common IME options when the keyboard icon is clicked. The pop-up list shows all the available IMEs or keyboard layouts for a given language.

The following pictures illustrate how a user inputs Chinese characters in Notepad. The IME status bar is shown in the bottom right-hand corner of the Notepad window here, but it can be placed anywhere, and generally is shown either in the bottom right-hand corner of the screen or as part of the Taskbar. In the first screenshot the user has typed 'ni' while IME is ON. The string 'ni' here is called the 'composition string' in the interface.

keylogger2.gif

Next, the user has typed 'nichi'. You can see that 'ni' has disappeared from the little grey box, and the character which is most likely to represent 'ni' is underlined with dashes. Both of these strings are called composition strings because they may not match the final text used in the application.

keylogger3.gif

The third image shows the screen when the user has finished typing the phrase 'nichifanleme' and has pressed the Enter key. There is no little grey box, but the five Chinese characters are underlined with dashes. These characters, 10 bytes in DBCS and five words in Unicode, have not been passed to the application yet. At this stage it is still considered a composition string.

keylogger4.gif

Finally, the user has pressed Enter a second time to confirm the characters in the previous string. This string is called the 'result string', since the user has chosen not to alter any of the IME-selected characters for the keystrokes they typed. Each character is sent to the application window with the WM_IME_CHAR window message. If the window procedure does not process this message, it will receive a WM_CHAR message. So most applications don't need to be aware of IME. (Some applications, such as Microsoft Word and Excel are fully aware of IME and display composition strings by themselves.) These complicated tasks are performed by the IME and IMM (input method manager), and an IMM is included in every language version of Windows with multilingual support (2000 and later).

keylogger5.gif

The process diagram below illustrates how the text input process occurs.

keylogger-process.gif
  1. When IMM receives a key stroke from the keyboard driver, it sends the key stroke to the IME through the ImeProcessKey entry to ask the IME if the key stroke should be processed by the IME. If the IME returns zero, the key stroke will be processed by the OS and passed to the application as WM_KEYDOWN and WM_KEYUP, then further processed to WM_CHAR or WM_COMMAND, and so on. The IME will not receive the key through ImeToAsciiEx.

  2. If the IME returns a non-zero value in ImeProcessKey, the IMM sends the character to the IME again.

  3. The IME receives the lpdwTransBuf parameter, which will be set by the IME when the process returns from the IME to the IMM. The lpdwTransBuf parameter contains information about window messages to be sent to the application. The IME also receives the hIMC parameter, which contains composition strings, such as the composition string itself, the result string, and any reading information or clause information, depending on the language. The IME modifies the content of hIMC as it processes characters.

  4. Any time the IMM receives lpdwTransBuf back from the IME, the IMM checks the buffer to see if it contains a message list. Typically it contains the WM_IME_COMPOSITION message, which should be sent whenever the composition string changes. The IMM sends these messages in the buffer to the application window.

  5. If the application is not IME-aware, it will not process the WM_IME_COMPOSITION message and thus the user will not see the text within the application. In this case, the message is relayed to the corresponding IME UI window, which is always created if an IME is activated. An IME UI window will show the composition string as it is typed.

  6. If the application is IME-aware, it will process the WM_IME_COMPOSITION message. If there is a need to get the contents of composition strings, it calls the ImmGetCompositionString API in IMM32.DLL. The WM_IME_COMPOSITION message can also notify that the string is determined and the result string has been generated. If the application gets the determined string directly from IMM and pastes the string into its document, it should not call DefWindowProc on the WM_IME_CHAR message, because further processing will generate the same character twice.

  7. If the application is not IME-aware, it will receive the WM_IME_CHAR message. If the application uses the GetMessageW API (along with DispatchMessageW), it will get one Unicode character in a WM_IME_CHAR. If the GetMessageA API (along with DispatchMessageA) is used, the application receives one DBCS character in the message. If the application does not call DefWindowProc on WM_IME_CHAR, it will not receive the WM_CHAR message later.

  8. If the application is not designed to use IME at all, it will get a WM_CHAR message as the result string is generated. If GetMessageW/DispatchMessageW are used, it receives a Unicode character, which is exactly the same as when getting WM_IME_CHAR. If GetMessageA/ DispatchMessageA are used, it receives two WM_CHAR messages for each DBCS character; the higher byte on the first message, the lower on the second

An IME is a DLL file, typically with the file extension '.IME', and is usually placed in the Windows system directory. IMEs are registered as keyboard layouts in the registry at the following location: HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Keyboard Layouts (see below). The IME has an 'IME file' value ('winpy.ime'). When these registry values are set, a user can choose to enable this IME through the Control Panel. Once it has been enabled, the IME will be shown in the list of keyboard layouts that we saw earlier.

keylogger6.gif

The registry key HKEY_CURRENT_USER\KeyboardLayout\Preload contains the list of keyboard layouts to be selected by the user. The value '1' is the default layout, which is loaded automatically in every process during the user's session. In Japanese and Korean versions of Windows, Microsoft's IME is the default.

An IME is loaded in every process

Any keyboard layout, including an IME, is loaded in every process. KBDUS.DLL, the US keyboard layout DLL, contains only data and has no room to place any extra code. But an IME is a program that has several predetermined entries. No application can reject an IME; an IME acts like a system DLL. Before the instruction enters the entry point of an application, the IME file is loaded, thus DllEntry has been called.

Think of Japanese and Korean OSs. If the genuine Microsoft IME file is replaced with a hacked version using MoveFileEx or another method, the hacked IME will be loaded, even in the System process. This means the hacked IME can run even in the user sessions where the hacked IME is not the default keyboard layout.

A removal tool cannot repair or replace the IME files because the correct files differ depending on the OS and the Service Pack installed. If the hacked IME hinders the replacement of the files, it becomes even more difficult to fix the problem.

Is non-Far East Windows safe?

For those who don't use an IME, a simple IME that does not convert characters can be installed and become the default keyboard layout. There is a slight difference in UI, especially in the language bar, but most users will not understand why it happened unless they have experience using IMEs.

The average user would have no idea that the IME was running in his/her English OS. They might even search some commonly known registry load points for the culprit, but would likely find nothing.

It is far easier to develop a fake IME, which does not convert characters and does not display a window, than it is to infect or hack a genuine IME, or than to develop a whole new fully functional IME for Chinese, Japanese and Korean users.

An IME can be added

In Korea, there seems to be no need to develop IMEs other than Microsoft's. But in Japan, because many users have become accustomed to their favourite input methods, multiple third-party IMEs are sold.

The image below shows the default display of the IME status bar on Japanese Windows XP.

keylogger-start1.jpg

When the icon of keyboard is clicked, the list of available IMEs in the current language is shown. If no IME is added, only one IME is displayed (MS-IME2002 here).

keylogger-start2.jpg

If two IME products are installed on the machine, the list will display three IMEs and their names. The IME currently in use is marked with a tick. (ATOK 2005 and Japanist 2003 are third-party Japanese IME products.)

keylogger-start3.jpg

The screenshot shown below is the dialog of the 'Regional and Language Options' Control Panel. The standard language or default language can be selected here. The standard language will be loaded automatically in every process in the session of the user who has selected the language.

keylogger-dialog.gif

The user also can remove an IME from the list.

IMEs capture every key stroke without hooking

As already discussed, the OS (IMM) always sends any keystrokes to the currently selected IME through ImeProcessKey and ImeToAsciiEx entry points in the IME file, which is just a DLL with the file extension 'IME'. It generally exports some mandatory entry points that should be called from the IMM.

The simplest way to log keystrokes is to log them in ImeProcessKey and return zero. ImeProcessKey receives virtual keys. If zero is returned, the IMM will no longer interact with IME for that keystroke. IME runs in every process and can act as if it is a part of any program.

If the IME sends out packets in the Internet Explorer process to the system or to monitoring tools, it appears as though Internet Explorer has sent them out, just like injecting such a routine into Internet Explorer.

Unlike the injection technique, however, an IME does not have to hook keyboard-related APIs or messages. Existing security tools would not detect such suspicious behaviour performed by the IME.

If ImeProcessKey returns a non-zero value, a virtual key is eventually passed to TranslateMessage by the application window procedure, then it is passed to the ImeToAsciiEx entry point to be converted to a character.

IMEs are loaded in safe mode

It is not surprising that IME is always loaded, even in Safe Mode. This means that the standard (default) IME cannot be deleted from the system, unless a user with a different default IME logs on.

The MoveFileEx API can be used to rename the IME in use. At the next login, the user will see the second IME in the list become his/her default IME.

More harmful actions

Genuine non-infected IME files can be removed from the computer easily. However, if an IME is designed maliciously, code could be added, making the following possible:

  • It may be able to change the default IME of all the users.

  • Even if the user changes his/her default IME, IMEs that have already been selected cannot be changed. The user must re-login or reboot the computer. A program that forcefully changes the IME in use can be developed, but on NT-based Windows the IME module would remain in memory. If the IME runs a thread, it can keep running. And what if the thread checks the standard IME periodically and changes it back again?

  • MoveFileEx sets some registry values. If a malicious code deletes the values, it will be difficult to delete the IME file.

  • An IME is loaded even in 16-bit applications and the command prompt.

  • An IME can load WinSock, enabling it to access the Internet.

Details of the IME interface

The following are some important entry points, or exported functions, that IMEs should have.

DllMain

This is the start address of the IME DLL file. This is called when an IME file is loaded by the IMM during the initialization of an application if the IME is the default, or if it is loaded when the user selected the IME manually.

ImeInquire (LPIMEINFO lpInfo, LPTSTR lpszUIClass, DWORD dwSystemInfoFlags)

The IMM would call this entry at least once to retrieve the IME's properties. On NT-based Windows, this is called only once and the properties are stored in the global system memory.

An IME can set the member of lpInfo, among which fdwProperty has IME_PROP_UNICODE bit (0x00080000). If this bit is on, all the IME interfaces will become Unicode-based. If it is off, they become ANSI-based. All the interfaces are called from IMM, which would convert between Unicode and ANSI if the application does not match the code system.

An IME should set a string in lpszUIClass, such as 'MY_IME_UI_MAIN'. The IMM would automatically create the window of class 'MY_IME_UI_MAIN' at the time the application creates the first window. IME-related window messages are passed to this IME UI window. This window becomes one of the child windows of the application window. RegisterWindow should be called by the IME.

ImeSelect (HIMC hIMC, BOOL bSelected)

This is called when the IME is selected and unselected. If it is a standard IME, this is called after DllMain and before the entry point of the application is called.

hIMC is a handle to Input Context, in which an IME should store data.

ImeSetActiveContext (HIMC hIMC,BOOL fFlag)

This is called when the application is activated and deactivated.

ImeProcessKey (HIMC hIMC,UINT vKey, LPARAM lKeyData, CONST LPBYTE lpbKeyState)

The IMM calls this first to ask the IME whether this key stroke should be processed by the IME. If the IME returns false (zero), the IMM does not send this key to the ImeToAsciiEx.

If the MSB of lKeyData is on, the key is released, otherwise the key is pressed. lpbKeyState is a 256-byte matrix indicating whether each VKEY is down or up (including CAPS LOCK state, etc.). vKey is just a virtual key and needs the states of lpbKeyState to see what character is input.

ImeToAsciiEx (UINT uVKey, UINT uScanCode, CONST LPBYTE lpbKeyState, LPTRANSMSGLIST lpTransBuf, UINT fuState, HIMC hIMC)

If IME returns true (non-zero) in ImeProcessKey, the virtual key is passed to ImeToAsciiEx. This entry is the most important for the genuine IME; in this routine the IME converts alphabet, Katakana or Hangeul jamo (parts) to Chinese character, Hiragana, Kanji, Hangeul or Hanja. This routine determines the usability and performance of the IME.

IME should set the contents of lpTransBuf in order for a generated character to be input into the application window, otherwise the key stroke will be lost here. A genuine IME would send WM_IME_STARTCOMPOSITION, WM_IME_COMPOSITION and WM_IME_ENDCOMPOSITION sequentially.

A member hCompStr in hIMC has the composition string. hCompStr is a handle to the COMPOSITIONSTRING structure. A genuine IME should set members of dwCompStrLen, dwCompStrOffset, dwResultStrLen and dwResultStrOffset in COMPOSITIONSTRING and (especially dwCompStrLen and dwResultStrLen) may change at every key stroke.

If dwCompStrLen and dwCompStrOffset remain unchanged, the application is highly suspicious as an IME. dwCompStrLen is the length of the characters which are being converted and shown in a special IME UI window. dwResultStrLen is the length of the character string which is determined and input into the application window. Again, if dwCompStrLen is never greater than zero, but dwResultStrLen is greater than zero, the IME is highly suspect.

Web-aware

An IME that consults the web as to some information related to the input character strings could be developed as a product. But this action should only be initiated when the user performs a specific operation. There would be no legitimate purpose or value for sending all the keystrokes to the web. Similarly, there would be no legitimate reason for sending keystrokes input into a specific window.

If an IME always loads a socket library, there may be conflicts with the application. If the user runs a 16-bit version of an email client, the application would not run properly. Therefore (even though the number of users running a 16-bit Internet application is very low), any quality commercial product should avoid this.

Listening on a port should be avoided too, since it is hard to tell what port will be opened by the application. So, if you come across an IME that does this, beware, it could be a rogue one.

Conclusions

In the Far East versions of Windows used in China, Japan and Korea, genuine IMEs can be hacked and altered to log keystrokes or carry out malicious actions. The installer of the keylogger will replace an IME file and might set some IME-related registry values. Virus analysts must look out for either ImeProcessKey or ImeToAsciiEx entries that log keystrokes in a file or registry, send keystrokes through a socket, or do anything that is unnecessary as an IME functionality. A hacked IME would not behave any differently from the user's perspective.

In the other language versions of Windows, the keyboard layout can be changed to a fake IME which does nothing but log keystrokes, send the keystrokes or some other malicious behaviour. In this case users would notice the change in behaviour of the IME, but they are still able to input keys without problems. The installer will drop an IME file, add some IME-related registry values and change the registry of default keyboard layout. In this case, virus analysts should watch out for an ImeToAsciiEx entry that does almost nothing compared to what would be expected in a genuine IME.

twitter.png
fb.png
linkedin.png
hackernews.png
reddit.png

 

Latest articles:

Nexus Android banking botnet – compromising C&C panels and dissecting mobile AppInjects

Aditya Sood & Rohit Bansal provide details of a security vulnerability in the Nexus Android botnet C&C panel that was exploited to compromise the C&C panel in order to gather threat intelligence, and present a model of mobile AppInjects.

Cryptojacking on the fly: TeamTNT using NVIDIA drivers to mine cryptocurrency

TeamTNT is known for attacking insecure and vulnerable Kubernetes deployments in order to infiltrate organizations’ dedicated environments and transform them into attack launchpads. In this article Aditya Sood presents a new module introduced by…

Collector-stealer: a Russian origin credential and information extractor

Collector-stealer, a piece of malware of Russian origin, is heavily used on the Internet to exfiltrate sensitive data from end-user systems and store it in its C&C panels. In this article, researchers Aditya K Sood and Rohit Chaturvedi present a 360…

Fighting Fire with Fire

In 1989, Joe Wells encountered his first virus: Jerusalem. He disassembled the virus, and from that moment onward, was intrigued by the properties of these small pieces of self-replicating code. Joe Wells was an expert on computer viruses, was partly…

Run your malicious VBA macros anywhere!

Kurt Natvig wanted to understand whether it’s possible to recompile VBA macros to another language, which could then easily be ‘run’ on any gateway, thus revealing a sample’s true nature in a safe manner. In this article he explains how he recompiled…


Bulletin Archive

We have placed cookies on your device in order to improve the functionality of this site, as outlined in our cookies policy. However, you may delete and block all cookies from this site and your use of the site will be unaffected. By continuing to browse this site, you are agreeing to Virus Bulletin's use of data as outlined in our privacy policy.