Yak语言基础
Yakit使用的是Yak语言,所以在写插件之前需要学习一下Yak语言(感觉比较像Python和JavaScript)
变量与数据类型
变量
Yak中赋值符为:=
定义变量
使用var
作为关键词,var
后使用空格作为分隔符即可定义变量
1 | var a // 声明变量a |
在没有var
修饰的时候,赋值符“=”会为左边的“标识符”自动创建一个变量
基础数据类型
int
:表示可以带正负号的整数数据类型(在Yak语言中占用的大小为64位);string
:用于表示一系列字符数据的,字符串中可以使用转义字符,例如\n
等;float
:用于表示浮点数;byte
:等同于“无符号8位整数”,通常用来表示一个“字节”,类似C语言中的Char类型;nil
与undefined
一般用于表示一个未定义的变量或者空值;bool
:表示“布尔值”,其值只有两种情况,true
或false
;
Tips:
声明一个非十进制的整数
1 | // 二进制声明 |
多行文本
可以使用``
(反引号)来定义多行文本,此时会忽略文本中的转义符号
1 | abc = `Hello World\n |
格式化字符串
Yak语言使用%
进行基本的字符串格式化。格式化字符串的两种用法和操作基本语法:
printf
函数:第一个参数为需要格式化的字符串模版,其余参数为为格式化字符串中的参数;%
格式化操作符:%
左边为需要格式化的模版,右边为一个格式化字符串的参数,例如"Hello %v" % "World"
;如果有多个需要格式化的点,那么需要使用
[]
来包裹,并用逗号分隔元素,例如:"My name is %v, I am %d years old" % ["John", 18]
。
示例:
1 | printf("Hello I am %d years old\n", 18) |
格式化字符串中的占位符
字符串中的占位符 | 解释 |
---|---|
%v | 根据变量的类型自动选择格式。 |
%T | 输出变量的类型。 |
%d | 十进制整数。 |
%b | 二进制整数。 |
%o | 八进制整数。 |
%x | 十六进制整数,使用小写字母。 |
%X | 十六进制整数,使用大写字母。 |
%f | 浮点数,不带指数部分。 |
%c | ASCII码对应的字符。 |
%q | 带引号的字符或字符串。 |
%s | 字符串。 |
%p | 输出十六进制表示的内存地址或引用。 |
字符串模版字面量
类似于Python,在字符串的前面加上一个小写的 f
,然后在字符串内部用 ${}
包裹需要插入的表达式。
示例:字符串中插入变量 a
和 name
的值。
1 | println(f`Hello ${a}, Hello ${name}`) |
其他数据类型
列表类型:List
在 Yak 语言中,List 是一种动态数组,它可以存储和管理相同类型的元素。Yak 语言支持字面量声明和 make
语法来创建 List
字面量创建列表:使用 [var1, var2, var3...]
形式快速声明一个 List。Yak 语言会根据列表内的元素类型自动推断合适的 List 类型。
**字典类型:**map
字典用于存储键值对
字面量创建字典示例:
1 | m = {"a": 1, "b": 2} |
**通道类型:**channel
通道类型用于多线程之间的数据共享
创建与声明:使用make函数来创建一个新的channel。这就像是开设一个新的邮局,用于发送和接收包裹。
1 | ch := make(chan int) // 创建一个没有存储空间的int类型的channel |
数据写入
1 | ch <- 1 // 将一个整数1寄出到ch,但是因为 ch 在上文创建时没有声明存储空间,这里会阻塞 |
读取数据
1 | v := <-ch // 从ch取走一个包裹 |
Tips:判断数据是否取走
1 | v, ok := <-ch |
Channel的属性
Yak提供了一些内置的函数来检查channel的当前状态。
1 | len(ch2) // 查看ch2中还有多少个包裹 |
关闭Channel
关闭后的channel不能再寄出数据,但仍然可以从中取走数据。
1 | close(ch2) |
运算符
数学运算
数学运算包括加、减、乘、除和取余等操作:
1 | println(2 + 2) // 输出: 4 |
逻辑运算符
逻辑运算符在Yak语言中用于进行逻辑操作,包括逻辑与(&&
)和逻辑或(||
)
这两个运算符都具有短路特性,即如果左侧的操作数已经能确定整个表达式的值,那么就不会再计算右侧的操作数
1 | a = true |
三元逻辑运算符
形式为condition ? value1 : value2
如果condition为真,则表达式的结果为value1,否则为value2。这个运算符也具有短路特性,即如果条件已经能确定整个表达式的值,那么就不会再计算其他的值。以下是一些使用示例:
1 | a = 5b = 3 |
控制与循环
这部分比较像Python,直接写示例就好了
条件判断
示例:
1 | x = 88; // 学生的成绩 |
SWITCH 语句
示例:
1 | grade = 'B' |
此外,switch
允许一个case
分支匹配多个值
For循环
定义:
1 | for 表达式1 ; 表达式2 ; 表达式3 { |
首先运行表达式1 -> 判断表达式2,如果成立则运行循环体中的代码 -> 每一次循环后执行表达式3 -> 进行表达式2的判断并循环执行,直到表达式2判断为假,则结束整个函数。
TIPS:
简化的For循环
对于无初始化表达式和每次循环后的迭代表达式的for循环,可以写为:
1 | for 布尔表达式 { |
遍历列表
使用for-range
与使用for-in
效果相同
1 | for i, v = range a { |
i, v
是我们在每次迭代中定义的两个变量,其中i
将存储当前的索引,而v
将存储与该索引对应的值(若只迭代一个变量,迭代的值将会是索引)。range a
是一个表达式,它创建了一个从集合a
中提取索引和值的范围。
遍历字典
使用for-range
/for-in
遍历字典,这样可以同时获取键和值:
1 | for k, v = range b { |
在这个循环中,k
和v
分别在每次迭代时被赋予字典中的键和对应的值
遍历通道
遍历通道中的数据可以使用for-range
/for-in
语句来实现这一点:
1 | for result = range ch { // 遍历通道内的数据 |
直接指定循环次数
1 | for in n { |
如需当前的索引:
1 | for i in n { |
或使用range
关键字:
1 | for range n { |
如果需要索引,可以将i
和range
一起使用(注意:range 前有一个 =
):
1 | for i = range n { |
插件
Yakit的插件基本可以分成三种类型:交互式插件(Yak原生插件)、MITM 插件、Codec插件
交互式插件类似于单开一个功能页面
MITM 插件用于被动扫描时对漏洞进行检测
Codec插件用于对数据包进行操作,可以设置右键调用,对HTTP数据进行变形
API
Yakit插件编写提供的API
几个比较经常用到的API
https://yaklang.com/api-manual/api/cli (用于输入插件所需的数据)
https://yaklang.com/api-manual/api/codec (Crypto等操作)
https://yaklang.com/api-manual/api/poc (获得、修改数据包等操作)