长夜漫漫,无心睡眠。14天的居家隔离简直度日如年,为了打发时间我又重新将卸载数月之久的DouYu直播下载到手机上,从关注列表中找到一个之前挺喜欢的英雄联盟游戏主播,其主播风格基本没有改变还是之前喜欢的样子。与记忆中不同的一点,现在主播通过弹幕进行投票来决定当局游戏选择哪个英雄,但是由于在APP端限制一秒只能发送一条弹幕,外加本人手速着实的慢,十有八九都会错过自己想看的英雄。还有一周多的隔离时间,好不容易找到一个可以打发时间的事情,如果经常不能看到自己想看的内容,大概率用不了多久就会失去兴趣,万一再引发心理问题就严重咯!作为技术人员,何不搞它一波?
从主播口中了解到,现在的投票规则是主播提供几个英雄选项,粉丝弹幕输入对应的序号,且不会进行重复过滤。根据现在的规则,如果我们可以自动发送指定内容的弹幕,就可以实现我们想要的效果。想要实现自动投票,我们需要解决两个问题:其一是APP端限制的一秒只可发送一条弹幕,如何突破这一限制?其二是如何实现弹幕的自动发送?带着这两个问题,我们进行一些逆向分析:1、首先,我们需要定位到当前Activity。手机启动APP并打开直播界面,命令行执行“adb shell dumpsys activity top”查看当前Activity,结果如下图所示,2、然后,借助逆向工具jadx对DouYu的安装包进行反编译,并分析PlayerActivity的逻辑实现,虽然作了大量的混淆,还是可以找到如下图所示部分代码,从图中所示的代码,我们可以看到DouYu是通过控制焦点来限制一秒钟只能发送一条弹幕,了解了限制的方式我们可以有多种手段突破该限制,例如直接调用setText来设置弹幕内容。3、定位弹幕发送的位置,如果能够找到弹幕发送的函数实现,我们可以主动调用来实现弹幕的自动发送,但是事与愿违,受混淆的限制不能轻易的定位弹幕发送的位置,就我个人而言也不希望花费太多的时间。冷静思考一番,何不换一种思路,以开发的角度来定位弹幕发送的位置?俗话说,细节决定成败。我们发送一条弹幕,并仔细观察这一个过程,其实不难发现在我们点击弹幕输入框的时候会蹦出软键盘,当我们输入弹幕内容后,需要点击“发送”按钮才会真正的发送弹幕。如果作为开发人员,我们该如何实现这一需求呢?其实实现该需求是比较简单的,无非就是软键盘的按键。在安卓开发的领域内提供了三种监听方法:1、重写Activity的dispatchKeyEvent(KeyEvent event)方法2、使用OnKeyListener方法监听软键盘按键3、使用setOnEditorActionListener方法来监听上面三种方法,setOnEditorActionListener可以更精准的判断右下角按键情况,并且可对“Go”、“Done”、“search”键的情况做出更细分的操作。我们可以针对三种方法依次借助jadx的文本搜索功能进行搜索,最终基本确定采用了第三种方法。如果只看文本搜索的结果,可以看到有多处都使用了这一方法,但是我们可以重点关注图中显示的最后一项,再回顾下第一步定位Activity输出的内容。结合两张图片基本可以确定DouYu弹幕发送是如何监听软键盘的。4、思考如何实现自动弹幕,我们可以跟踪一下setOnEditorActionListener的使用,如下图所示,我们可以看到函数传递的参数是一个OnEditorActionListener对象,可以理解成一个回调,当用户点击软键盘的“发送”按钮后,最终会触发OnEditorActionListener对象所定义的onEditorAction函数,那么我们是否可以伪造参数来主动调用onEditorAction函数,实现弹幕的自动发送呢?
在前面的分析过程,我们提出一种方案,伪造参数主动调用onEditorAction函数,这种方案究竟是否可行,我们编写一个demo来做一下简单的验证。1、界面布局的编写,布局中包括一个文本输入框EditText和一个用于主动发送弹幕的Button,图中红框属性即说明弹出带“发送”键的软键盘。2、使用setOnEditorActionListener给EditText添加软键盘的监听事件,并如红框所示存储EditText对象和OnEditorActionListener对象。根据代码内容,当用户点击发送后Logcat日志会输出EditText的输入内容及当前时间戳,3、Button点击事件实现,每点击一次就相当于主动发送一次弹幕4、运行demo,我们先正常操作输入一个Douyu,之后点击三次按钮,日志输出内容如下所示:从结果看,伪造参数主动调用onEditorAction函数来实现弹幕的自动发送是可行的,但是也出现了一个更为棘手的问题,如何注入到Douyu应用中?
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)