首页
社区
课程
招聘
[原创]Textobot-史上最另类的文本型GUI事件模型
发表于: 2020-1-5 10:21 9709

[原创]Textobot-史上最另类的文本型GUI事件模型

2020-1-5 10:21
9709

​导读

0x00.交个朋友

0x01.常规的GUI事件模型

0x02.TB插件的GUI事件模型

0x03.配置文件中的target

0x04.TB_on_event事件回调

0x05.TB_gui显示与解析

0x06.下篇再见


0x00.交个朋友

手游从业者模拟器玩家请关注云游模拟器PantaWin;

Android开发者请关注云游模拟器PantaWin/PantaMac/PantaLinux;

iOS越狱开发者请关注晓文框架Textobot;

Android插件开发者请关注飞度框架Fridobot;

移动调试器重度用户请关注利达调试器LidaDbg;

我们的产品推荐使用git下载和更新,在码云搜索geekneo即可。


0x01.常规的GUI事件模型

在有GUI的操作系统上面,系统都定义了一组非常细致的GUI事件交给应用程序处理。如果是非常高层的SDK封装,使用更是方便,通过重载函数就可以处理GUI事件了。比如iOS的UIEvent、Qt的QEvent、Windows的PeekMessage等相关接口或者虚函数就可以实时处理GUI事件。下图是iOS的部分事件接口:


这类操作系统级GUI事件模型几乎都是针对编译型开发语言设计的,功能非常完备但是使用复杂。尤其是我们用动态语言封装出来的运行时,要全部处理这些事件非常费劲同时也是没有必要的。


0x02.TB插件的GUI事件模型

TB插件事务型流程推荐使用Python编写,功能型流程推荐使用JavaScript编写。这就要求我们封装的GUI事件模型是平台无关的,并且简单易懂,即便是没有iOS SDK开发经验的人也可以使用。如果用Python处理起来异常困难的话就失去了我们标榜的高效率开发iOS越狱插件的意义了。编译型语言比如C/C++/Objective-C擅长处理二进制数据结构,解释型语言比如Python非常擅长处理文本型数据结构。从这个角度出发,我们就分配了一个关键任务给注入库textobot.dylib-记录界面文本以及坐标,然后生成GUI文本事件汇报给调度器。
这样一来,TB插件就能感知当前界面显示的文本内容,那么结合文本分析,我们就可以编写事务处理逻辑了。看到这里,我想读者也能明白Textobot名字的由来了-Text Robot。此处Text即指界面文本,也指TB插件形态,用文本代码感知动态的界面内容。我们把收到的文本事件打印出来,如下:

只要触发了GUI事件,textobot.dylib就会把当前最新的文本状态汇报给调度器,从而交给TB插件处理。然后再加上一些点击、滑动操作,那么就源源不断的形成了事件流。这就是Textobot插件体系的文本型GUI事件模型。职业测试专家不知道用不用得上,用Python这种全民编程语言写带复杂逻辑的自动化测试用例,如果还有更高级的方式请不要笑话我,毕竟我并不懂专业测试的玩法。然后在Frida的加持下,TB插件是如此的强大以至于还有很多其他高级的玩法,但是切记:


0x03.配置文件中的target

打开TBROOT/Template/textobot.json模版项目配置文件,有一个关键字段target如下:

打开TBROOT/Sample/TextCapture/textobot.json例子项目配置文件,同样注意关键字段target如下:

如前文所述,textobot.dylib会源源不断的把文本型GUI事件汇报给调度器,进而交给TB插件处理。由于当前的界面可能来自不同的App,所以我们需要指明希望处理哪些App的文本型GUI事件,这就是target字段的作用,它是一个BundleID数组,字符*代表处理所有的文本型GUI事件。


0x04.TB_on_event事件回调

插件脚本选择性提供的事件回调函数,没有则不会收到文本型GUI事件。dictarg是框架提供的Key-Value字符串参数,当插件处于运行状态,则会在如下情况被调用:

def TB_on_event(dictarg)

弹出了对话框,对应的event为dlgtexts;

每隔10s或者UI事件被触发了,对应的event为texts;

dictarg中还包含target,值为发送UI事件的App标志符,剩下的就是文本控件坐标和文本内容,类似于:

'89,98' : 'UILabel.iCloud'

前者是文本控件‘中心坐标’,后者是控件‘类名.文本’,中心坐标可以通过TB_touch_pair进行点击操作。

模版代码如下:

def TB_on_event(dictarg):
    target = dictarg['target']
    event = dictarg['event']
    if event == 'texts':
        pass
    elif event == 'dlgtexts':
        pass
    return {}

0x05.TB_gui显示与解析

上一篇《用交互式TB插件在iPhone上砸壳更美滋滋》当中我们贴出了它GUI处理的部分,在这里我们详细解释它的原理。先看TB_gui的说明。
def TB_gui(controls)

controls:GUI控件描述文本;

通用格式为:控件类型---提示标题[---初始参数]

当前支持的控件如下:

label :文本字符串,控件类型---提示标题---对齐方式包括空、center、right;

edit :多行编辑框,控件类型---提示标题---初始文本;

combo :单选列表框,控件类型---提示标题---初始列表,以逗号分隔;

spin :数据调节器,控件类型---提示标题---初始参数,格式为“起始值,步长,终止值”;

padding :多加一些空白

 TBMachoDumper选择目标App的GUI显示代码:

def dump_selector():
    TB_gui(
'''
label---MachO Dumper---center
label---GeekNeo/AloneMonkey---center
label---%s---center
padding
combo---%s---%s
''' % (pkg_version, flag_apps, running_apps(idev)))

这样调用就会借助Textobot管理器显示描述的GUI界面,然后用户选择完了点击OK的话,Textobot管理器就会将结果格式化为一个方便解析的文本并弹出Textobot Submitting对话框,这样再通过文本型GUI事件发送给TBMachoDumper插件的处理逻辑,我们就可以解析用户到底选择了哪一个App。
flag_tbsubmit = 'Textobot Submitting'
flag_sep = '---'
flag_apps = 'Applications'
#...
# parse result from TB commit dialog
def proc_event_texts(pts, txts):
    # 查找 Textobot Submitting 结果对话框标志
    if contain_text(pts, txts, flag_tbsubmit):
        # 自动点击OK关闭对话框
        TB_touch_pair(contain_text(pts, txts, '.OK'))
        time.sleep(1)
        for i in range(0, len(txts)):
            # 查找我们显示GUI时设置的App列表标准 Applications
            if txts[i].find(flag_apps) > 0:
                # 将结果拆分成一行一行的结构
                lines = txts[i].split('\n')
                result = ''
                for l in lines:
                    # 将一行拆分成单一元素 --- 是Textobot定义的行分隔符
                    items = l.split(flag_sep)
                    if len(items) != 3:
                        continue
                    # 此处是 Applications
                    key = items[1]
                    # 此处是 pid-bid 键值对
                    value = items[2]
                    print('Dumping %s ...' % (value))
                    appinfo = value.split('\t')
                    # kill it before dump
                    if appinfo[0] != '-':
                        run_cmd('kill -9 ' + appinfo[0])
                        time.sleep(1)
                    dump_main(appinfo[1])
                break
​
# handler for event
def TB_on_event(dictarg):
    event = dictarg['event']
    if event == 'dlgtexts':
        proc_event_texts(dictarg.keys(), dictarg.values())
    return {}

0x06.下篇再见

到此,我们详细解释了Textobot定义的文本型GUI事件模型、TB_on_event事件处理回调、TB_gui的显示与解析。可以看出,我们不需要iOS SDK的任何帮助就可以实现一个可交互式的TB插件,但是如果要写出有意义的TB插件,iOS相关的知识还是必不可少的。下一篇文章,我们详细介绍TB插件项目的其他内容,比如TB_main插件事件、当前导出的系统级API。



[课程]Linux pwn 探索篇!

收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//