Skip to main content

插件编写指南:插件交互式输出

当我们可以创建一个插件,并执行代码之后,面对一个很现实的问题是

我们如何为用户输出好看的,利于理解,利于后续操作的插件执行结果?本文我们就来讲解如何实现插件的输出

Yak 原生模块输出#

了解 Yakit 插件技术背景的同学可能非常清楚,Yak 原生插件依赖 webhook 与服务器进行通信。

为此我们在 yak 语言内部内置了一个 yakit 的库,在这个库中,我们可以便捷操作与用户的操作界面通信。

准备工作 yakit.AutoInitYakit()#

如果用户需要启用与 yakit 通信的模块,则需要在脚本开头或者输出之前执行

yakit.AutoInitYakit()

这行代码会从环境变量中提取 Webhook 的实际端口,并且针对实际端口进行通信。在进行初始化之后,我们使用 yakit 中的一些接口,就可以实现把插件的执行结果返回到 yakit 中从而实现与用户的交互了!

输出日志 Info/Warn/Error/Output#

最基础的输出,也就是我们最一开始实现 Hello World 插件的输出,就是使用这种形式。

yakit.AutoInitYakit()yakit.Info("Hello This is a info message")yakit.Warn("Warning!!! Warning: %v", now())yakit.Error("Error!? Impossible")

当我们把这段代码在插件中执行时,得到如下内容

Preview#

输出状态与统计数据#

我们在使用的过程中,经常需要告诉用户 "输出结果" 的状态或者某个指标的数据,例如:

  1. 我们发现了多少漏洞
  2. 我们发出了多少请求
  3. 关键步骤运行了多长时间
  4. ...

这些状态其实往往应该被单独展示,而不应该放在日志中,为了支持这种常见的情况,我们可以使用 yakit.StatusCard(title: string, value: any) 支持。

函数的详情介绍可以看这里

Preview#

输出进度条#

同上,我们在调用 yakit.AutoInitYakit() 之后,将可以使用进度条功能,为你的插件增加一个 "进度"。

单进度条#

作为最简单的情况,进度条的输入只应该是一个 "百分比",为了支持这种情况,我们实现了一个

yakit.SetProgress(percent: float) 函数

yakit.AutoInitYakit()
yakit.SetProgress(0.1)sleep(1)yakit.SetProgress(0.4)sleep(1)yakit.SetProgress(0.8)

将会在界面生成一个进度条,实现进度条的展示!

Preview#

多进度条#

当然如果上述的内容中,单个进度条无法满足用户需求,你希望我们可以展示多个进度条,进度条之间可以互相关联。

那么我们可以使用 yakit.SetProgressEx(id: string, percent: float)

来按照 ID 创建多个进度条

我们使用如下案例来展示

yakit.AutoInitYakit()
go func{    percent = 0.1    for {        yakit.SetProgressEx("test1", percent)        time.sleep(0.3)        percent+=0.1    }
}
yakit.SetProgress(0.1)sleep(1)yakit.SetProgress(0.4)sleep(1)yakit.SetProgress(0.8)sleep(1)yakit.SetProgress(0.9)

我们在原来代码的基础上,增加了 goroutine,来创建另一个进度条,给新的进度条命名为 test1

观察代码,我们预期两个进度条可以同步进行

Preview#

输出表格#

虽然上面输出了一些内容,但是实际上并不够,如果我们需要不断输出一些结果

例如批量扫描的结果,或者猜测某一个 KEY 的结果,我们经常需要一个表格作为输出。

这个时候,我们应该如何编写几个表格呢?

yakit.AutoInitYakit()
yakit.EnableTable("tablename", ["key", "key2"])
data = make(map[string]var)data["key"] = 123data["key2"] = 2222yakit.Output(yakit.TableData("tablename", data))
data = make(map[string]var)data["key"] = "测试KEY1"data["key2"] = "测试KEY2"yakit.Output(yakit.TableData("tablename", data))

同样的,我们通过 AutoInitYakit() 来初始化,成功之后我们启用 yakit.EnableTable(tableName: string, fields: string[]) 在界面上创建一个新的表格。

创建了表格则可以通过 yakit.Output(yakit.TableData(tableName: string, data: map[string]var)) 来输出表格具体内容了。

我们可以通过 make(map[string]var) 来创建一个表格需要输出的数据。更简单的,我们可以通过一些小重构,让这个 API 变得更好用!

yakit.EnableTable("tablename", ["key", "key2"])
outputData = def(key, key2){    data = make(map[string]var)    data["key"] = key    data["key2"] = key2    yakit.Output(yakit.TableData("tablename", data))}
outputData("测试数据1", "jkoasdkoasdf")outputData("测试数据2", "jkoasdkoasasdfaadf")outputData("测试数据3", "jkrewgiogq423421oasdkoasdf")outputData("测试数据4", "jkoasdfasdgaasdkoasdf")outputData("测试数据5", "jkoasdkoasdasdfhadfhsdrff")outputData("测试数据1", "j132562345235dcf*&TY^koasdkoasdf")

Preview#

输出图#

详情可参考 Yakit API

MITM 插件的输出#

MITM 插件的输出接口其实并不多,同时接口相对更容易一些

输出到 MITM 插件操作台#

  1. yakit_output(data: any):仅输出到操作台
  2. yakit_save(data: any):输出到操作台,同时保存一份到插件输入,可以在数据库中找保存的数据

以上接口非常容易理解,我们可以创建一个插件,分别输出两个内容试试看~

Preview#

输出状态卡片#

在原生 yak 模块中,状态卡片是一个非常受欢迎的小组件;

我们同样的也在 MITM 中实现了该组件的功能。

yakit_status(title: string, value: any)

直接调用这个函数,将会自动生成一个状态卡片,用于展示各种动态的指标。

Preview:编写一个建议的流量记述插件!#

我们使用一个更贴近场景的案例来告诉大家这个功能的用法:流量统计。

我们可以做一个简单的计数器,在 MITM 的 Hook 函数内实现统计方法,每一个数据包都会被记数,从而实现一个指标来记录流经我们劫持平台的数据包到底有多少。

实际生效的代码仅仅三行,我们为插件创建一个计数器,具体如何使用呢?我们可以查看如下内容