Android平台下基于frida对用户输入的hook
一、概念
输入法:
输入法 (IME) 是一种可让用户输入文本的用户控件。Android 提供了一种可扩展的输入法框架。借助该框架,应用可以为用户提供备选输入法,例如屏幕键盘,甚至语音输入。安装所需的 IME 后,用户可以从系统设置中选择要使用的 IME,并在整个系统中使用该 IME;同时只能启用一个 IME。需要使用输入法的应用通常需要输入法管理者 InputMethodManager 来与系统中的输入法服务 InputMethodService 进行交互。
关于焦点:
一个窗口中一个时间内只能有一个具有焦点的控件。
并不是所有视图都可以获取焦点。而在触摸设备上通常默认情况下只有EditText控件才具有焦点,而我们通常会遇到的一个问题就是当进入一个具有EditText的界面时键盘就会自动弹出,而且有时候可能无法消失,但需求可能是进入时不弹出键盘。而这些所有的东西都是和视图的焦点有关。
关于输入法连接:
Android应用中的 InputMethodManager 类通过 EditableInputConnection类来与输入法服务建立连接并进行通信,所有的数据交互都通过 EditableInputConnection类。当用户输入一个字符串时,会调用 EditableInputConnection类中的 commitText 函数提交。当用户点击键盘上某个键时,会调用 EditableInputConnection类中的 sendKeyEvent 函数来发送击键事件,里面会有点击的键位信息。
二、实现
每个可输入控件在用户进行输入前一定会先获取焦点,所以在控件请求焦点时就是其打算输入时,这就把握住用户输入的时机。
每个视图上的控件都是继承自父类"android.view.View",当请求焦点时会调用其中的 requestFocus 函数,对其hook即知道输入的开始。
var view = Java.use("android.view.View"); view.requestFocus.overload().implementation = function() { clz = this.getClass().getName(); viewId = this.getId(); return view.requestFocus.overload().call(this); };
每个普通Android应用都是通过注册一个输入法客户端然后请求系统中注册的输入法服务,而在应用中客户端是通过InputMethodManager这个中间人与输入服务交互的。所以我们也可以通过 InputMethodManager 类里的 startInputInner 函数来感知用户输入的开始。
var InputMethodManager = Java.use("android.view.inputmethod.InputMethodManager"); InputMethodManager.startInputInner.implementation = function(v,e,f,d,a){ var ret = InputMethodManager.startInputInner.call(this,v,e,f,d,a); return ret; };
我们可以通过 EditableInputConnection类中的 commitText 函数获得用户输入的内容,也可以通过键位信息获知用户敲击的键位,比如在删除字符时点击 "KEYCODE_DEL" 键。
var EditableInputConnection = Java.use("com.android.internal.widget.EditableInputConnection"); EditableInputConnection.commitText.implementation = function(text,newCursorPosition){ var ret = EditableInputConnection.commitText.call(this,text,newCursorPosition); return ret; };
hook删除操作代码:
EditableInputConnection.sendKeyEvent.implementation = function(event){ var ret = EditableInputConnection.sendKeyEvent.call(this,event); return ret; };