前一段时间肝了挺久的JVM注入,作为Hack Android的一种方法这个显然是最强大而且最行之有效的。但是相对的,其难度也是最高的,先不说so库Hook这个过程对大多数人来说如何理解,单就其操作难度就是对新手十分的不友好。所以我觉得需要有一种简单的Hack方法,然后我发现了Accessibility的强大之处(首先声明 这个方法因为要经过用户授权所以基本不能拿来做什么坏事,不过通过心理学欺骗来达到效果也不是不行 这也就是相对前面比较Weak的地方了)

0x00 基础内容

 

0x000 状态机

百度百科对状态机的释义是:关于状态机的一个极度确切的描述是它是一个有向图形,由一组节点和一组相应的转移函数组成。状态机通过响应一系列事件而“运行”。每个事件都在属于“当前” 节点的转移函数的控制范围内,其中函数的范围是节点的一个子集。函数返回“下一个”(也许是同一个)节点。这些节点中至少有一个必须是终态。当到达终态, 状态机停止。
为什么我们会用到这东西呢,因为我们必须要根据某一时候界面所处的状态来判断下一步做什么(注意 是界面所处的状态,也就是说我们的操作必须在前台完成虽然会很快 但是必须处于对应的界面 这也更是为什么不能拿来做坏事 坏事都干到明面上了)

 

0x001 Accessibility Service

这个东西呢,是安卓提供给方便残疾人使用手机的辅助服务 (这样想是不是不太好)来直接操作界面,可操作内容包括(click, scroll, paste….基本能模拟人的所有操作,除此以外还额外附赠可以说是全Android里最频繁的系统调用(感觉在这里加上个Service唤醒简直死不了/大雾))。所以我们要做的 就是充分了解目标界面,然后模拟人的操作干它。这就是我们的外部Hack法(大雾)

 

0x002 hierarchyviewer

所以这又是个什么东西呢,这个是sdk的tools里带的一个工具,这个工具的作用本来的用来优化UI的,然后我们可以用来做一些坏事。USB调试连接之后打开对应界面,在这个工具的界面里就可以看到这个界面的控件树,而且鼠标移到对应的控件上的时候会显示这部分的截图。而且这些控件还显示出了ID。我们所需要的就是这些ID。

 

0x01 正篇

 

0x010 准备工作

首先我们需要通过刚刚的hierarvhyviewer取得我们所要的控件的ID还有Hack的界面的类名,然后记录下来,之后通过实际使用判断需要的操作流程。ID是为了通过辅助服务获取到对应控件的句柄(或许不该叫这个),Hack界面的类名是为了我们确定在不同的界面执行不同的脚本,而操作流程就是最重要的脚本部分。

 

0x011 Hack it

首先,如何创建一个带有辅助服务的应用以及如何启用辅助服务我就不赘述浪费字数了可以参见这个连接 Android 辅助服务 。我们只讲一讲在 onAccessibilityEvent() 函数,也就是系统给我们的回调中我们要做些什么。

0x0110 过滤事件

因为我们在这个回调中会收到各种各样的事件,所以我们最好只过滤出其中一些(比如界面变化事件),并且通过一个标志位Handling来确保在处理某一个事件流程的时候不会被新来到的事件影响(具体做法就是在操作开始的时候将handling置位并在完成的时候重置false)。

0x0111 过滤界面

我们需要做的是在不同的地方执行不同的脚本,所以我们必须确定我们当前在哪。那如何获取呢,我们参考这个方法

添加权限: <uses-permission android:name="android.permission.GET_TASKS" />
private String getRunningActivityName(){
ActivityManager activityManager = (ActivityManager) getSystemService (Context. ACTIVITY_SERVICE);
String runningActivity = activityManager. getRunningTasks(1). get(0). topActivity. getClassName();
return runningActivity;
}

然后用这个获取到的类名与上面的类名做一个比较就知道当前位于我们需要的哪一个界面了

0x0112 编写脚本

现在我们位于我们判断类名完成的if块中了,换句话说我们已经保证当前的界面是有这个脚本中的控件的以及可以正常执行我们的脚本。那么我们就可以编写脚本了

关键函数
List stop_nodes = event.getSource().findAccessibilityNodeInfosByViewId([应用包名]:id/[控件ID]);

event是回调的传参,这样获取到一个List就是这个ID的所有控件(这里要注意ID的写法,因为要访问到其他包的id,所以必须注明包名,这引用方法和android:id/xxx是一个道理),接下来我们就只要知道我们要取用哪个(一般是第一个),然后获得到一个该控件的封装对象AccessibilityNodeInfo 这个封装对象的方法
AccessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
参数的值就是我们要这个控件执行的操作,可以做的操作包括上面提到的那些,多次使用这个流程,最终得到的就是一个界面操作的脚本,再结合上面的步骤,我们就可以在不同界面相应不同的操作,代码毫不杂糅。


0x012 实践项目

QQ回复框架 仅用100余行代码实现,近期将托管到Git

发表评论

电子邮件地址不会被公开。