Android IME / InputMethodService Abuse (Malicious Keyboards)

Tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

Overview

Android allows third-party keyboards via an InputMethodService (IME). Once a user enables a keyboard and selects it as the current input method, the IME can observe (and influence) essentially all text input produced on the device across apps.

This is why several Android banking trojans bundle a “secure keyboard” feature: the malicious IME receives keystrokes even from apps that never embed a WebView (banking apps, chat apps, crypto wallets, etc.).

Note

android.permission.BIND_INPUT_METHOD is typically declared on the IME service so only the system can bind to it. Declaring it doesn’t grant special privileges by itself; the key step is getting the victim to enable/select the keyboard in Settings.

Manifest declaration

A keyboard is exposed via a service with the android.view.InputMethod intent action and an IME configuration XML:

<!-- AndroidManifest.xml -->
<service
    android:name=".SpyKeyboard"
    android:permission="android.permission.BIND_INPUT_METHOD"
    android:exported="false">

    <intent-filter>
        <action android:name="android.view.InputMethod" />
    </intent-filter>

    <meta-data
        android:name="android.view.im"
        android:resource="@xml/spy_ime" />
</service>

Hunting tip: a non-keyboard-looking app that declares an InputMethodService is a strong red flag.

Where the data comes from

At runtime an IME learns:

  • The target app being typed into (via EditorInfo, e.g. attribute.packageName in onStartInput).
  • The text being entered (through the IME’s interaction with the current InputConnection and/or key events depending on the implementation).

Minimal (non-functional) sketch of the high-signal hook point:

public class SpyKeyboard extends InputMethodService {
  @Override public void onStartInput(EditorInfo attribute, boolean restarting) {
    // attribute.packageName identifies the foreground app receiving input
  }
}

Common enablement & collection workflow (observed in the wild)

  • The APK is marketed as a “secure keyboard” or the keyboard is embedded inside a broader trojan.
  • The malware drives the victim into the system keyboard settings (e.g. by launching Settings.ACTION_INPUT_METHOD_SETTINGS and/or using UI automation) until the IME is enabled and set as default.
  • Keystrokes are buffered per-app and exfiltrated via the malware’s existing C2 channel, often combined with other data sources (e.g., WebView man-in-the-browser telemetry).

How to detect / triage

On-device checks

  • Settings: Installed keyboards / default keyboard (look for unknown IMEs).
  • ADB:
adb shell dumpsys input_method
adb shell ime list -a
adb shell ime help

Static triage of an APK

  • Look for InputMethodService classes and the android.view.InputMethod intent filter.
  • Inspect @xml/* IME config referenced by android.view.im.
  • Check whether the app’s stated functionality matches shipping a full keyboard UI/resources.

Mitigations

  • User/MDM: allowlist trusted keyboards; block unknown IMEs in managed profiles/devices.
  • App-side (high risk apps): prefer phishing-resistant auth (passkeys/biometrics) and avoid relying on “secret text entry” as a security boundary (a malicious IME sits below the app UI).

Tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks