Yak:专注安全能力融合的编程语言快速入门

Yak:专注安全能力融合的编程语言快速入门

大家好,今天给大家分享一门专为安全领域设计、致力于解决安全能力融合问题的编程语言------Yak。在安全研发领域,我们常面临这样的困境:不同安全能力模块因适配不同语言而分散,导致平台与能力割裂,规模化研发和效率提升受阻。而Yak语言的核心目标,就是打造"一站式"安全能力基座,打破这种壁垒。接下来,我将结合官方文档的核心内容,带大家全面认识Yak,快速掌握其基础用法与核心特性。

一、Yak要解决的核心问题

提到黑客编程,Python凭借简洁语法和丰富安全工具生态,成为安全从业者的必备技能。但随着技术深入,规模化工具/平台/安全产品的研发需求凸显,Golang因更高效率、更适配产品分发和工程研发的特性,逐渐成为安全研发的重要选择。

在这一阶段,"安全研发不仅包含安全平台研发,也包含安全能力研发"的理念逐渐普及。我们通常会用合适的语言编写平台处理业务需求,但安全能力研发更为复杂,不同安全工具往往采用"最合适"的语言实现------这就造成了安全平台与安全能力模块的割裂。

这里的"最合适",很大程度上源于历史原因:缺乏专人进行新场景适配,导致"老代码"不断积累,最终形成能力分散的局面。为解决这一问题,Yak应运而生,其核心职责就是安全能力融合------无论是PoC、扫描器、扫描模块还是漏洞扫描算法,都能通过Yak实现,最终打造"一站式"安全能力基座。

二、核心理念:安全基础能力融合

Yak的核心理念围绕"安全基础能力融合"展开,具体具备以下优势:

  • 完善的内容生态,提供入门/保姆级安全研发教程;
  • 长期支持,具备成功的企业实践经验;
  • 高级功能自由度极高,提供独一无二的Fuzz体验;
  • 底层融合多种安全能力/工具,打破工具和安全小领域间的壁垒;
  • 集成MIT协议的高质量工具;
  • 最终目标是提升行业整体安全水平。

三、速览:极速编写安全工具

Yak的一大优势是极简的安全工具编写体验,我们以服务扫描工具为例,快速感受其便捷性。

创建文件 service_scan.yak,内容如下:

yak 复制代码
// 极简获取参数,--target xxxx  --port 80
scanTarget, scanPorts = cli.String("target"), cli.String("port")

// 默认批量进行服务扫描
results, err = servicescan.Scan(scanTarget, scanPorts)
die(err)

// 取出扫描结果(异步扫描结果)
for result = range results {
    println(result.String())
}

执行命令:

bash 复制代码
yak service_scan.yak --target 192.168.1.1/24 --port 22,80

即可得到扫描输出(部分结果):

复制代码
tcp://192.168.1.32:22    open   openssh[6.6.1]
tcp://192.168.1.21:22    open   openssh[7.4]
tcp://192.168.1.40:22    open   openssh[6.6.1]
tcp://192.168.1.43:22    open   openssh[5.3]
tcp://192.168.1.83:80    open   apache_tomcat[1.1]/coyote[1.1]/coyote_http_connector[1.1]/java[*]/jquery[*]/jquery[1.3.2]
tcp://192.168.1.99:80    open
tcp://192.168.1.122:80   open   nginx[*]
tcp://192.168.1.125:80   open   linux_kernel[*]/nginx[1.10.3]/ubuntu[*]/ubuntu_linux[*]
tcp://192.168.1.126:80   open   nginx[*]/php[5.4.45]

仅需几行代码,就能实现批量服务扫描,足见Yak在安全工具开发中的高效性。

四、Yak基础语法快速入门

在正式学习前,先明确几个约定:后续文中"Yak"和"Yaklang"均指代Yak语言;完全大写的"YAK"表示Yak生态,包含Yaklang编程语言和Yakit安全平台。

4.1 第一个Yak程序:Hello World

和多数编程语言一样,Yak的第一个程序可实现"Hello World"打印,仅需一行代码:

yak 复制代码
print("Hello World")
// 输出:Hello World

Yak设计遵循"符合逻辑"的原则:无需引入额外库,无需封装成类,无需在代码末尾加分号,极简的语法降低了入门门槛。

4.2 变量创建

Yak支持多种变量创建方式,核心逻辑简洁直观:

yak 复制代码
var myVariable = 1  // 声明并初始化变量
myVariable = 2      // 赋值(变量已存在则更新值,不存在则创建)
myVariable := 3     // 强制创建新变量(与var myVariable = 3等价)
var myAnotherVariable  // 声明空变量,值为nil

注意:Yak是动态类型语言,无需指定变量类型,会自动根据赋值内容推断类型,因此创建变量时不能指定类型。

4.3 基本数据类型(字面量)

Yak中的"值(字面量)"是基本数据类型,变量是值的容器。常见基本类型及创建方式如下:

yak 复制代码
myIntVariable = 1          // 整数
myFloatVariable = 3.14     // 浮点数
myStringVariable = "Hello World"  // 字符串
myBoolVariable = true      // 布尔值
myArrayVariable = [1, 2, 3]  // 数组
myDictVariable = {"key": "value"}  // 字典
myFunctionVariable = func() {  // 函数
    print("Hello World")
}

Yak的设计贴合"符合直觉"的哲学,上述代码无需额外解释即可轻松理解。

4.4 重要类型:string(字符串)

字符串在安全研发中应用广泛,数据传输和存储多以字符串形式进行。以下是Yak中字符串的核心操作。

4.4.1 字符串创建

支持三种创建方式,适配不同场景需求:

yak 复制代码
// 1. 双引号(支持转义,如\"、\n)
myString1 := "Hello \"Yak\""
// 2. 反引号(支持多行,不转义,不能包含反引号)
myString2 := `Hello Yak
This is a multi-line string`
// 3. Heredoc语法(支持多行,可包含反引号)
myString3 := <<<EOF
Hello Yak
This is Heredoc string
EOF
4.4.2 字符串格式化与插值

Yak提供多种字符串格式化方式,适配不同变量数量和使用习惯:

yak 复制代码
// 1. % 语法(单变量)
name := "John"
println("Hello %v" % name)  // 输出:Hello John

// 2. % 语法(多变量,需用[]包裹)
name, age := "John", 20
println("Hello %v, you are %v years old" % [name, age])  // 输出:Hello John, you are 20 years old

// 3. sprintf函数(多变量直接传入参数)
println(sprintf("Hello %v, you are %v years old", name, age))  // 输出同上

// 4. f-string插值(简洁直观,常用)
println(f"Hello ${name}, you are ${age} years old")  // 输出同上

说明%v是通用占位符,可适配任意类型变量;也可使用%d(整数)、%f(浮点数)、%s(字符串)等指定类型占位符。

4.5 复合类型:列表与字典

列表(数组)和字典是Yak中常用的复合类型,支持"增删改查"等核心操作,语法简洁。

4.5.1 列表操作
yak 复制代码
myList = [1,2,3]

// 增:Append方法
myList.Append(4)
println(myList)  // 输出:[1 2 3 4]

// 删:Remove方法(删除指定元素)
myList.Remove(2)
println(myList)  // 输出:[1 3 4]

// 改:通过索引赋值
myList[1] = 999
println(myList)  // 输出:[1 999 4]

// 查:索引访问与切片
println(myList[2])   // 输出:4(访问索引2的元素)
println(myList[:2])  // 输出:[1 999](从开头到索引2前)
println(myList[1:])  // 输出:[999 4](从索引1到末尾)
println(myList[1:3]) // 输出:[999 4](从索引1到索引3前)

// 内置append函数(批量添加元素)
newList = append(myList, 5, 6, 7)
println(newList)  // 输出:[1 999 4 5 6 7]
4.5.2 字典操作
yak 复制代码
myDict = {}

// 增:键值对赋值
myDict["name"] = "John"
myDict["age"] = 12
println(myDict)  // 输出:map[age:12 name:John]

// 删:Delete方法
myDict.Delete("age")
println(myDict)  // 输出:map[name:John]

// 改:覆盖键值对
myDict["name"] = "Tom"
myDict["age"] = 22
println(myDict)  // 输出:map[age:22 name:Tom]

// 查:键访问与字符串插值
println(f`Hello ${myDict["name"]}, your age is ${myDict["age"]}`)  // 输出:Hello Tom, your age is 22

4.6 控制流

Yak通过IF、Switch实现条件控制,通过For实现循环控制,语法贴近主流编程语言,学习成本低。

4.6.1 条件控制(IF/ELSE)

支持elifelse if表示"否则如果",两种写法等价,可按需选择:

yak 复制代码
// 示例1:elif用法
scores = [10, 20, 30, 40, 50, 60, 70, 80, 99, 100]
teamScore = 0
for score in scores {
    if score > 90 {
        teamScore += 3
    } elif score > 80 {
        teamScore += 2
    } elif score > 70 {
        teamScore += 1
    } else {
        teamScore += 0
    }
}
println(teamScore)  // 输出:7

// 示例2:else if用法(与elif等价)
result = ""
age = 18
if age > 80 {
    result = "old man"
} else if age > 10 {
    result = "teenager"
} else {
    result = "child"
}
println(result)  // 输出:teenager
4.6.2 循环控制(For)

Yak的For循环支持多种写法,适配不同循环场景:

yak 复制代码
scores = [10, 20, 30, 40, 50, 60, 70, 80, 99, 100]

// 1. foreach循环(Python风格)
for score in scores {
    println(score)  // 依次输出列表中所有元素
}

// 2. for range循环(Golang风格,获取索引和值)
for index, score = range scores {
    println(index, score)  // 输出:索引 对应值(如0 10、1 20...)
}

// 3. while循环(通过for condition实现)
i := 0
for i < 10 {
    println(i)  // 输出0-9
    i += 1
}

// 4. 三段式For循环(贴近Golang/C风格)
for i := 0; i < 10; i++ {
    println(i)  // 输出0-9
}

4.7 函数与函数调用

Yak中函数创建灵活,支持多种关键字和简写形式,适配不同编程习惯。

4.7.1 基础函数创建与调用

支持funcfndef三种关键字创建函数,功能完全等价:

yak 复制代码
// 1. func关键字
func myFunction() {
    println("Hello World")
}
myFunction()  // 输出:Hello World

// 2. fn关键字
fn helloName(name) {
    return sprintf("Hello %v", name)
}
println(helloName("John"))  // 输出:Hello John

// 3. def关键字
def helloNameAndAge(name, age) {
    return sprintf("Hello %v, you are %v years old", name, age)
}
println(helloNameAndAge("John", 20))  // 输出:Hello John, you are 20 years old
4.7.2 箭头函数(简写形式)

通过=>创建箭头函数,语法更简洁,支持自动返回表达式结果:

yak 复制代码
// 基础箭头函数
myFunction = () => {
    println("Hello World")
}
myFunction()  // 输出:Hello World

// 单参数可省略括号,表达式自动返回
helloName = name => sprintf("Hello %v", name)
println(helloName("John"))  // 输出:Hello John

// 多参数箭头函数
helloNameAndAge = (name, age) => {
    return sprintf("Hello %v, you are %v years old", name, age)
}
println(helloNameAndAge("John", 20))  // 输出:Hello John, you are 20 years old

说明:箭头右侧若为单个表达式,会自动返回表达式结果;若为代码块,会自动返回最后一个表达式的值。

4.7.3 函数与闭包

Yak函数支持自动捕获和访问外部变量,这一特性称为"闭包",极大提升了函数式编程的表现力:

yak 复制代码
// 捕获外部变量
name := "John"
helloWithOutterName = () => sprintf("Hello %v", name)
println(helloWithOutterName())  // 输出:Hello John

// 修改外部变量
name := "John"
helloModifiedWithOutterName = () => {
    name = "Jane"
    return sprintf("Hello %v", name)
}
println(helloModifiedWithOutterName())  // 输出:Hello Jane

4.8 库函数的使用

Yak作为安全领域DSL(领域特定语言),内置了大量安全相关库函数,无需安装依赖、无需导入,可直接使用。以服务扫描函数servicescan.Scan为例:

yak 复制代码
results, err = servicescan.Scan(scanTarget, scanPorts)
die(err)  // 错误处理

for result in results {
    println(result.String())  // 打印扫描结果
}

类似的内置安全库函数还有很多,例如:

  • synscan.Scan:启动SYN端口开放扫描;
  • mitm.Start:启动MITM劫持服务器。

提示 :这些库函数多基于Golang实现,返回值常包含error类型,因此调用时需进行错误处理(下文将详细讲解)。

4.9 错误处理

Yak提供多种错误处理方式,适配不同场景需求,确保程序健壮性。

4.9.1 手动处理错误(die(err))

通过手动接收函数返回的error,再用die(err)处理:若存在错误,程序中断并抛出错误;无错误则正常执行。

yak 复制代码
results, err = servicescan.Scan(scanTarget, scanPorts)
die(err)  // 有错误则中断,无错误则继续
4.9.2 自动处理错误(~语法,WavyCall)

使用~语法可自动处理错误,效果与die(err)一致,语法更简洁:

yak 复制代码
// 自动处理错误,有错误则中断执行
results = servicescan.Scan(scanTarget, scanPorts)~

说明 :无论函数返回值最后一个是否为error类型,均可使用~语法;若函数报错,~会抛出错误并中断当前函数执行。

4.9.3 Try-Catch捕获错误

支持try-catch-finally语法,可主动捕获错误并自定义处理逻辑:

yak 复制代码
try {
    results = servicescan.Scan(scanTarget, scanPorts)~
    for result in results {
        println(result.String())
    }
} catch err {  // 捕获错误,err为错误变量(不可加括号)
    println(err)  // 自定义错误处理
} finally {
    println("finally")  // 无论是否出错,均会执行
}
4.9.4 defer recover()捕获错误

通过defer+recover()捕获错误,适用于自定义函数或需要保证执行完整性的场景:

yak 复制代码
myFunc = () => {
    // 延迟执行错误捕获逻辑
    defer func {
        err = recover()
        if err != nil {
            println(err)  // 打印错误
        }
    }
    println("Before Error")
    1/0  // 触发错误(除零错误)
    println("After Error")  // 不会执行
}
myFunc()
// 输出:
// Before Error
// runtime error: integer divide by zero

提示~语法抛出的错误,也可被defer recover()try-catch捕获,实际开发中可组合使用。

4.10 并发编程

Yak支持并发编程,语法与Golang类似,通过go关键字创建并发任务,高效利用系统资源。

4.10.1 基础并发任务(go关键字)
yak 复制代码
go func() {
    println("Hello World in Goroutine")
}()
sleep(1)  // 等待并发任务执行完成
println("Hello World in Main")
// 输出:
// Hello World in Goroutine
// Hello World in Main
4.10.2 WaitGroup:等待并发任务完成

当需要等待所有并发任务执行完毕后再继续主程序时,可使用WaitGroup

yak 复制代码
wg = sync.NewWaitGroup()
for element in [1,2,3] {
    element := element  // 捕获循环变量
    wg.Add(1)  // 计数器+1,标记一个并发任务启动
    go func() {
        defer wg.Done()  // 任务完成,计数器-1
        println(element)
    } ()
}
wg.Wait()  // 等待所有任务完成(计数器归0)
println("All Goroutine is done")
// 输出:1、2、3(顺序不固定)、All Goroutine is done
4.10.3 SizedWaitGroup:限制并发资源

WaitGroup计数器无上限,可能导致资源耗尽。SizedWaitGroup可指定最大并发数,限制资源使用:

yak 复制代码
// 指定最大并发数为2
wg = sync.NewSizedWaitGroup(2)
for element in [1,2,3] {
    element := element
    wg.Add(1)  // 若计数器已达上限,会阻塞至有任务完成
    go func() {
        defer wg.Done()
        println(element)
        sleep(1)  // 模拟任务耗时
    } ()
}
wg.Wait()
println("All Goroutine is done")

说明 :当SizedWaitGroup计数器达到指定上限时,新的wg.Add(1)会阻塞,直到有任务完成(计数器减少)后才会继续执行。

五、总结

通过本文的分享,相信大家对Yak语言有了全面的认识。Yak作为专注于安全能力融合的编程语言,核心价值在于打破安全平台与安全能力模块的割裂,提供"一站式"安全能力基座,极大提升安全研发的效率和规模化水平。

其核心优势可总结为三点:一是语法简洁直观,兼容多语言编程习惯,入门门槛低;二是内置丰富安全库函数,无需额外依赖,可快速开发安全工具;三是支持灵活的错误处理和并发编程,适配复杂安全研发场景。

对于安全从业者而言,Yak不仅是一门新的编程语言,更是提升安全研发效率、整合安全能力的有力工具。后续我会继续分享Yak的高级特性(如Fuzz功能)和实战案例,感兴趣的朋友可以持续关注。如果在学习过程中有疑问,欢迎在评论区交流讨论!

相关推荐
dingchengyu18 小时前
web应用安全与加速
安全
橘颂TA18 小时前
线程池与线程安全:后端开发的 “性能 + 安全” 双维实践
java·开发语言·安全
bruce_哈哈哈18 小时前
go语言初认识
开发语言·后端·golang
梁辰兴19 小时前
中国信通院发布《人工智能安全治理研究报告(2025年)》,AI安全攻防为何“易攻难守“?
人工智能·安全·ai·ai安全·梁辰兴·人工智能安全治理·中国信通院
飞飞传输19 小时前
适配信创环境的传输系统推荐:助力企业数据安全合规传输!
大数据·运维·安全
moxiaoran575319 小时前
Go语言的接口
开发语言·后端·golang
浮尘笔记19 小时前
Go语言中的同步等待组和单例模式:sync.WaitGroup和sync.Once
开发语言·后端·单例模式·golang
●VON19 小时前
智能暗战:AI 安全攻防实战全景解析
人工智能·学习·安全·von
廋到被风吹走19 小时前
【Spring】Spring Boot Actuator 深度解析:健康检查、指标暴露与端点安全
spring boot·安全·spring