网络安全【免费下载链接】HavocThe Havoc Framework项目地址https://gitcode.com/gh_mirrors/ha/Havoc点击查看免费下载HCLHashiCorp Configuration Language工具包是 Havoc Teamserver 的 profile 配置文件.yaotl背后的解析引擎。本文以仓库中内嵌的 HCL 官方指南guide 索引为核心骨架结合 profile 解析入口、配置结构体定义 和真实的 profile 示例讲清 Havoc 是如何把 HCL 改造成一套名为yaotl的应用级配置语言并用 struct tag 声明 schema、一键解码到 Go 结构体的完整链路。读完后你将能够独立编写 Teamserver profile并理解其从源文件到内存对象的底层解析流程。一、HCL 配置语言工具包是什么HCL 是一个用于创建结构化配置语言的工具包目标是让人和机器都能友好地读写配置适用于命令行工具、服务器等场景见 guide/index.rst。它提供两种语法原生语法native syntax面向人类追求可读性风格受 libucl、nginx 配置等启发JSON 变体语法面向机器便于程序生成与解析。它自带一套表达式语法支持基础的行内计算在调用方应用的配合下还可以使用变量variables和函数functions构造更动态的配置语言。从源码结构看HCL 的定位是提供构造配置语言的构件调用方应用自己声明期望的参数名和嵌套块类型HCL 负责解析配置文件、校验其是否符合预期结构并返回应用可继续使用的高层对象。HCL 本身是用 Go 编写的主要作为 Go 程序中的库来使用——这正是 Havoc Teamserver 采用它的方式。二、核心概念参数、块、标签与 body以下面这个假设应用的配置为例出自 guide/intro.rstio_mode async service http web_proxy { listen_addr 127.0.0.1:8080 process main { command [/usr/local/bin/awesome-app, server] } process mgmt { command [/usr/local/bin/awesome-app, mgmt] } }其中io_mode是一个顶层参数argument/attributeservice引入了一个块block块体内允许继续出现参数和嵌套块http与web_proxy是块的标签labels即跟在块类型关键字之后的引号字符串。io_mode、service、process这些关键字都是应用自定义的HCL 只提供通用的块结构语法并根据应用提供的 schema 完成校验与解码。几个关键术语需要区分body体某一嵌套层级上的参数与块的集合。文件永远有一个根 body 包含顶层元素每个块也有自己的 body。argument vs attribute指南指出attribute一词既可以指 body 中的参数也指对象值object value里的字段因此 argument 专指直接出现在 body 里的那类 attribute。HCL 是结构化配置语言不是数据结构序列化语言与 JSON、YAML、TOML 不同HCL 始终基于应用定义的 schema进行解码。同样的结构也可以用 JSON 变体写出{ io_mode: async, service: { http: { web_proxy: { listen_addr: 127.0.0.1:8080, process: { main: { command: [/usr/local/bin/awesome-app, server] }, mgmt: { command: [/usr/local/bin/awesome-app, mgmt] } } } } } }调用方应用可以选择支持哪些语法。JSON 语法在某些场景下并非必需但存在价值JSON 本身是含糊的例如一个 JSON 对象到底代表嵌套块还是对象表达式应用提供的 schema 让 JSON 输入也能被正确解码。参数表达式参数的值除了字面量之外还可以是表达式支持算术、从一个值派生另一个值等listen_addr env.LISTEN_ADDR所有 HCL 系配置语言自动内置算术与比较运算符调用方应用还可以可选地提供变量如env和自定义函数以应用特定的方式变换值。由于 JSON 没有表达式语法JSON 变体配置中的表达式以嵌入 JSON 字符串中的原生表达式形式出现。三、在 Go 应用中分层使用 HCLguide/go.rst 说明对简单场景HCL 可以像encoding/json、encoding/xml那样直接把配置解码进 Go struct对于更复杂、或结构只能在运行时才能确定的语言HCL 的 Go API 也提供了流水线式的低层接口。指南的完整 API 文档包括 go_parsing.rst、go_diagnostics.rst、go_decoding_gohcl.rst、go_expression_eval.rst、go_decoding_lowlevel.rst 与 go_patterns.rst。Havoc 的调用链恰好体现了这套分层设计。Teamserver 的 profile 加载入口在 profile.gofunc (p *Profile) SetProfile(path string, def bool) error { err : yaotl.DecodeFile(path, nil, p.Config) if err ! nil { return err } ... }这里yaotl实际是仓库内 vendored 的 HCL 包路径前缀为Havoc/pkg/profile/yaotlDecodeFile对应 vendored 包 hclsimple 中的一键入口它把主 API 中的四个步骤压缩为一次调用func Decode(filename string, src []byte, ctx *hcl.EvalContext, target interface{}) error { file, diags hclsyntax.ParseConfig(src, filename, hcl.Pos{Line: 1, Column: 1}) if diags.HasErrors() { return diags } diags gohcl.DecodeBody(file.Body, ctx, target) if diags.HasErrors() { return diags } return nil }即hclsyntax.ParseConfig解析源码为抽象语法 →gohcl.DecodeBody按 schema 提取结构并求值表达式。注意SetProfile传入的ctx为nil——按 hclsimple 的文档nil上下文意味着Havoc 的 profile 语言不支持变量与函数只接受常量值这正是指南中简单应用可以不做表达式求值的落地案例。错误处理同样遵循指南的约定DecodeFile在文件不存在或不可读时返回结构化的hcl.Diagnostics源码非 nil 错误均可类型断言为hcl.Diagnostics以获取完整诊断细节。四、Havoc 的 schema用 struct tag 声明 yaotl 配置调用方应用定义语言的主要方式就是声明结构体并标注 tag。Havoc 的完整 schema 在 config.go 中type HavocConfig struct { Server *ServerProfile yaotl:Teamserver,block Operators *OperatorsBlock yaotl:Operators,block Listener *Listeners yaotl:Listeners,block Demon *Demon yaotl:Demon,block Service *ServiceConfig yaotl:Service,block WebHook *WebHookConfig yaotl:WebHook,block }tag 格式为yaotl:名称[,block|label|optional]tag 片段含义示例Name普通参数attribute解码时必填Port int \yaotl:PortName,optional可选参数KillDate string \yaotl:KillDate,optionalName,block子块block单个字段表示最多一个slice 字段表示可重复Build *BuildConfig \yaotl:Build,blockName,label块的标签label只能赋给字符串字段Name string \yaotl:Name,label顶层六大块各自的字段要点均取自 config.goTeamserver 块ServerProfileHost、Port以及可选子块BuildCompiler64、Compiler86、Nasm三个编译器路径均为 optionalOperators 块OperatorsBlock内含可重复的user子块Users []UsersBlock每个 user 有一个 label用户名和Password参数Listeners 块Listeners支持Http、Smb、External三类可重复子块。其中 HTTP 监听器字段最丰富必填Name、Hosts、HostBind、HostRotation、PortBind可选KillDate格式2006-01-02 15:04:05、WorkingHours格式8:00-17:00、PortConn、Method、UserAgent、Headers、Uris、Secure以及可选子块Cert证书/密钥路径、Response响应头、Proxy正向代理Demon 块Demon内嵌于生成 payload 的运行时行为参数如Sleep、Jitter、IndirectSyscall、SleepTechnique、AmsiEtwPatching等均 optional以及可选子块InjectionSpawn64/Spawn32注入目标进程与BinaryHeader的 MZ 头魔数覆盖、按架构的ReplaceStrings-x64/x86字符串替换 mapService 块ServiceConfigEndpoint、PasswordWebHook 块WebHookConfig嵌套Discord子块含Url、可选AvatarUrl与User。一个值得注意的实现细节Listeners中三种监听器字段都是[]*ListenerXxx的slice 指针组合。对照 gohcl/decode.go 的块解码逻辑可以推断slice 字段支持同类型块重复出现指针元素则在块缺失时保持 nil与optional 子块的语义配合。五、一份真实的 Havoc profile 配置仓库提供的默认 profile 在 profiles/havoc.yaotl另见 data/havoc.yaotl 与 profiles/webhook_example.yaotlTeamserver { Host 0.0.0.0 Port 40056 Build { Compiler64 data/x86_64-w64-mingw32-cross/bin/x86_64-w64-mingw32-gcc Compiler86 data/i686-w64-mingw32-cross/bin/i686-w64-mingw32-gcc Nasm /usr/bin/nasm } } Operators { user 5pider { Password password1234 } user Neo { Password password1234 } } # this is optional. if you dont use it you can remove it. Service { Endpoint service-endpoint Password service-password } Demon { Sleep 2 Jitter 15 TrustXForwardedFor false Injection { Spawn64 C:\\Windows\\System32\\notepad.exe Spawn32 C:\\Windows\\SysWOW64\\notepad.exe } }这份示例把指南中的三个概念都体现出来了Teamserver/Operators等是应用自定义的块类型关键字user 5pider中的5pider是块的 labelHost 0.0.0.0是参数赋值。由于Listeners在 schema 中不是必填块HavocConfig.Listener为指针类型默认 profile 中省略它是合法的监听器也可以通过 Teamserver 的 HTTP 接口动态创建而不写入 profile。六、解码管线源码剖析把上面的 profile 加载进内存实际经历以下管线对应指南中解析 → 结构分析 → 表达式求值 → 提取结果的流水线见 guide/go.rst读取文件DecodeFile用ioutil.ReadFile读入字节失败时返回带Severity: hcl.DiagError的诊断hclsimple.go。解析语法hclsyntax.ParseConfig(src, filename, ...)把源码解析为带完整位置信息的 AST文件名会被用于在报错时附加源位置上下文。按 schema 提取结构gohcl.DecodeBody 要求 target 是指向 struct 或 map 的非 nil 指针通过ImpliedBodySchema(val)从 struct tag 反推出期望的 body schema再调用body.Content(schema)校验并提取参数与块。对 struct 字段的解码区分三种形态decode.go字段可接收hcl.Attribute保存原始属性字段可接收hcl.Expression保存原始表达式用于延迟求值其余情况调用DecodeExpression立即求值并转换。表达式求值与类型转换DecodeExpression先用expr.Value(ctx)求值再用gocty.ImpliedType推断目标类型、convert.Convert做类型转换最后gocty.FromCtyValue写入 Go 值任何一步失败都会生成带expr.StartRange()位置的诊断decode.go。块数量约束也在这一层强制decode.go非 slice 字段出现重复块会报Duplicate ... block非指针、非 slice 字段缺失块会报Missing ... block。这解释了为什么 config.go 把Teamserver、Operators等顶层块都声明为指针类型——缺失时不报错、得到 nil而Profile.ServerPort()之类访问器再对 nil 做防御profile.go。七、HCL 系配置语言的设计约定guide/language_design.rst 沉淀了一批让不同 HCL 系语言手感一致的约定值得在做 Havoc 扩展或阅读其他 HCL 项目时对照命名HCL 标识符的标准是全小写下划线风格service、io_mode大写字母和连字符虽然合法但主要用于对接外部系统。块类型名通常用单数每个块定义一个对象参数名在期望集合值时才用复数name foovssubnet_ids [abc, 123]。函数名一般不用下划线而是直接连写如substr与 C 标准库函数命名习惯一致。块 vs 对象值两者在原生语法里外观相似、在 JSON 里完全相同但语义不同——子块内可以嵌套块而对象构造表达式只能定义属性。经验法则是块表达语言里更刚性的领域对象schema 由应用明确定义对象构造留给键由用户自由挑选的场景如 Terraform 的tags。特殊情况下自由键的块语法也可以用来批量声明一等对象如locals。标准函数HCL 本身不强制一套通用函数但指南建议各语言尽量提供名称与行为兼容的标准函数集包括abs、coalesce、concat、format、jsondecode/jsonencode、length、lower/upper、substr、timeadd、setunion/setintersection等底层依托cty类型与函数体系。块结果作为表达式变量若顶层块的结果要参与表达式约定以块类型.标签1.标签2的路径暴露如service.http.web_proxy.listen_addr无序的同类块用 map 表示更直观有序则用 list 配合 splat 运算符。文件扩展名非平凡的 HCL 系语言应使用约定俗成的专属扩展名而非.hcl便于编辑器识别并启用针对性集成。Havoc 正是这条约定的实践者它没有沿用.hcl而是给 profile 语言起了yaotl的名字——struct tag 前缀是yaotl:文件后缀是.yaotl与指南每个非平凡 HCL 系语言应有专属扩展名的建议完全吻合。八、小结与实操要点Havoc 的 Teamserver profile 语言 HCL 原生语法 应用自定义 schemaschema 完全由 config.go 的 struct tag 声明入口为 profile.go 的SetProfile→yaotl.DecodeFile编写 profile 时块名必须与 tag 中声明的一致大小写敏感optional标记的字段可省略label字段对应块后引号内的名字可重复块slice 字段可写多个默认行为值可参考 profiles/havoc.yaotl由于SetProfile传入 nil 求值上下文profile 中只能写常量不能引用变量或调用函数配置写错时错误以hcl.Diagnostics形式返回并携带源位置信息可据此定位到具体行完整的 API 用法可继续阅读 vendored 指南的 go_parsing.rst、go_expression_eval.rst、go_patterns.rst 等页面以及解析器 hclsyntax 包 与解码器 gohcl 包 的源码。赞分享网络安全【免费下载链接】HavocThe Havoc Framework项目地址https://gitcode.com/gh_mirrors/ha/Havoc点击查看免费下载相关推荐Havoc Teamserver yaotl userfunc用 HCL 用户自定义函数扩展 .yaotl 配置语言Havoc Teamserver yaotl userfunc用 HCL 用户自定义函数扩展 .yaotl 配置语言 在 Havoc 的 Teamserver网络安全Havoc TeamServer 配置子系统实践在 Go 应用中使用 yaotlHCL库解析与解码配置文件Havoc TeamServer 配置子系统实践在 Go 应用中使用 yaotlHCL库解析与解码配置文件 本篇技术文章围绕 Havoc 仓库中内置的配置网络安全Havoc Teamserver 配置解析管线hclparse 入口与 YaotlHCL解析机制详解Havoc Teamserver 配置解析管线hclparse 入口与 YaotlHCL解析机制详解 本篇以 Havoc 团队服务器Teamserver网络安全上一篇logseq-plugin-gpt3-openai核心功能全解析从文本生成到DALL-E图像创作下一篇7步实现ng-zorro-antd与NativeScript集成构建高性能原生移动应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?