news 2026/10/23 13:34:15

Kong 类型恢复详解:LLM 如何从字段访问中合成完整结构体

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Kong 类型恢复详解:LLM 如何从字段访问中合成完整结构体

【免费下载链接】kong

The world's first agentic reverse engineer.

项目地址:https://gitcode.com/gh_mirrors/kong6/kong
点击查看免费下载

Kong 是一款基于 LLM 的 Agentic 逆向工程框架,自动驱动 Ghidra 分析 stripped 二进制。它的**类型恢复(Type Recovery)**能力尤为出色:LLM 从反编译代码的字段访问模式中"拼出"完整的 struct 结构体定义,并写回 Ghidra,让param_1变成真正可读的结构体指针。

🧩 为什么需要类型恢复?

stripped 二进制丢失了所有类型信息。反编译后的代码里,一个 32 字节的连接对象可能只长这样:

void FUN_00401a30(undefined4 *param_1) { local = *(undefined4 *)(param_1 + 4); // 这是 socket 描述符? ... }

参数类型是undefined4 *,每个字段都藏在魔法偏移量里。类型恢复的目标,就是把这些散落的偏移访问还原成一个有名字、有类型的 struct。

LLM 恰好擅长这种模式匹配——这正是 Kong 让它介入的原因。

🔍 LLM 如何发现结构体线索

固定偏移访问是关键证据

Kong 在系统提示中写明了结构体提案规则(见 kong/agent/prompts.py):

当参数是指针、且函数在多个固定偏移处访问它(如*(param + 0x10)、param->field_0x8)时,应提出结构体布局;至少要看到 2 个不同偏移的字段访问才提案,单个或含糊的访问不算数。

这条规则很关键——它避免了 LLM 对一次性读写的参数"过度发挥"。

结构体提案的输出格式

LLM 被要求只输出一个 JSON 对象,其中的struct_proposals字段承载类型信息(输出格式定义在 kong/agent/prompts.py):

{ "name": "conn_t", "total_size": 32, "fields": [ {"name": "socket_fd", "data_type": "int", "offset": 0, "size": 4}, {"name": "port", "data_type": "uint16_t", "offset": 8, "size": 2} ], "used_by_param": "param_1" }

每个提案都会带上"来源函数"和"被哪个参数使用"的元数据,解析逻辑在 kong/agent/analyzer.py。

🧱 多个提案合并成一个类型

一个 struct 往往被多个函数使用,而每个函数只能看到自己碰过的那几个字段。比如函数 A 只读了type和valueint,函数 B 读到了child、next等 6 个字段——两份提案怎么变成一份完整定义?

这就是 kong/agent/type_recovery.py 中StructAccumulator的工作:

  • 收集阶段:每个函数分析完,其struct_proposals被add_proposals()收集进累加器,并打上来源函数地址标签。
  • 合并阶段:unify()按结构体名称分组,同组内按偏移量(offset)对齐字段逐个合并,总大小取各提案的最大值与"最后一个字段结尾"的较大者(type_recovery.py#L68-L138)。

同偏移冲突时选"最佳字段"

同一偏移可能出现多个候选(名字或类型不一致),_pick_best_field()用打分规则裁决(type_recovery.py#L141-L155):

  1. 类型更具体者优先:int胜过undefined4;
  2. 名字更有描述性者优先:socket_fd胜过field_0x0(field、unk、pad等泛型名扣分)。

真实案例:cJSON 场景

测试用例完美演示了这个流程(tests/test_type_recovery.py):函数 A 只"看见" 24 字节、2 个字段的cJSON;函数 B "看见" 64 字节、6 个字段的cJSON。合并后得到一个64 字节的完整结构体,6 个字段全部保留——这正是"部分视图拼出完整类型"的效果。

✍️ 把类型写回 Ghidra

合并完成只是第一步。apply_unified_structs()(type_recovery.py#L158-L197)负责落地:

  1. 创建 struct:在 Ghidra 的DataTypeManager中创建/kong分类下的结构体,字段按显式偏移放置,空隙自动留为未定义字节(kong/ghidra/client.py);
  2. 应用到参数:把该结构体(默认作为指针类型)应用到提案记录的函数参数上,并记录受影响函数的地址(kong/ghidra/client.py);
  3. 签名重试:分析阶段如果 LLM 给出的函数签名引用了当时还不存在的类型(如cJSON *item),写入会失败并被标记为 pending;Cleanup 阶段创建好类型后,会自动重试这些签名(kong/agent/supervisor.py)。

这个"先提案、后落地、再补偿"的设计,保证了即使类型和签名在时间上错开,最终状态也是一致的。

🌐 全局合成:第二轮结构体恢复

单函数视角之外,Kong 还有 kong/synthesis/semantic.py 中的SemanticSynthesizer:在所有函数分析完成后,发起一次全局 LLM 调用,回顾连接数最多的 50 个函数,执行三项任务——

  • 为被多个函数引用的全局变量(DAT_XXXXXXXX)起有意义的名字;
  • 当多个函数从同一基址以一致偏移访问字段时,合成新的结构体定义;
  • 在全局视野下修正不协调的函数命名。

这一轮能捕获那些单个函数内看不到 2 个偏移访问、但跨函数汇总后才显现的结构体模式。

🗺️ 类型恢复在流水线中的位置

Kong 的完整流水线是:Triage → Analysis → Cleanup → Synthesis → Export(kong/agent/supervisor.py)。类型恢复横跨其中三个阶段:

阶段类型恢复动作
AnalysisLLM 分析每个函数,产出struct_proposals,累加器边跑边收集
Cleanup统一提案、在 Ghidra 建类型、应用到参数、重试失败签名
Synthesis全局视角再合成一轮结构体与全局变量命名

过程事件(如CLEANUP_TYPES_UNIFIED:"Unified N struct proposals into M types")会实时推送到 TUI 界面,方便观察:

📂 相关源码速查

  • 累加器与合并算法:kong/agent/type_recovery.py
  • 提案数据模型与解析:kong/agent/analyzer.py
  • 提示词与输出 Schema:kong/agent/prompts.py
  • Ghidra 建类型/应用类型:kong/ghidra/client.py
  • 流水线编排:kong/agent/supervisor.py
  • 全局合成:kong/synthesis/semantic.py
  • 单元测试(含 cJSON 合并用例):tests/test_type_recovery.py

小结

Kong 的类型恢复把"从用法推断类型"这件传统上最耗人力的逆向工作拆成了四步:固定偏移证据 → JSON 结构体提案 → 按偏移合并 + 最佳字段裁决 → Ghidra 建类型并补偿签名,再用一次全局合成扫尾。对新手来说,理解"部分视图如何拼出完整结构体"(按名称分组、按偏移合并、取最大大小)是掌握这套机制的核心钥匙。

【免费下载链接】kong

The world's first agentic reverse engineer.

项目地址:https://gitcode.com/gh_mirrors/kong6/kong
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 16:17:42

这几天都在聊换季的傍晚,我更想推荐《失真少年》

当睡前还不愿关灯的人走到夜里耳机刚戴上的那几秒,《失真少年》往往会比空泛安慰更先开口——不是要你热闹起来,而是把说不清的那截情绪,轻轻按进旋律里。凌晨三点屏幕像一面霜。添火乐队《失真少年》「凌晨三点的屏幕像一面霜/弹…

作者头像 李华
网站建设 2026/10/22 22:49:10

WSL2部署Cadence Virtuoso IC25.1:Ubuntu 26.04排障实录

干IC设计的朋友应该都有过这种经历:手头这套Cadence Virtuoso IC25.1的设计环境,平时在实验室的Linux工作站上跑得好好的,哪天临时想在Windows笔记本上把版图、电路仿真顺手看一下,却发现一套环境两天装不好。尤其是版本越新的套件…

作者头像 李华
网站建设 2026/10/22 15:10:20

从SD卡驱动入门Linux驱动开发:协议、框架与调试实战

1. 为什么从 SD 卡驱动入手想要理解 Linux 驱动开发,很多人第一反应是去啃字符设备、平台总线、设备树这些概念。但我个人的建议是:直接从 SD 卡/SDIO 驱动入手。理由很简单,SD 卡驱动几乎涵盖了 Linux 驱动开发的全部核心要素:总…

作者头像 李华
网站建设 2026/10/17 16:19:20

TCSP练习题:时间约束调度建模与CP-SAT求解实战

简介:本资源为TCSP(网络安全专业)核心知识点配套练习题集,面向高校信息安全、网络工程专业学生及备考网络安全认证的学习者,聚焦网络攻击类型辨析、防火墙技术对比、入侵检测原理、加密与数字证书机制等关键考点&#…

作者头像 李华
网站建设 2026/10/22 15:41:02

如何将OpenTag部署到Railway:双服务生产架构完整教程

【免费下载链接】OpenTag OpenTag: The Channels SDK starter application, a self-hosted AI on-call triage bot for Slack and Microsoft Teams, built with AG-UI and LangGraph. Fork it and ship your own. 项目地址: https://gitcode.com/gh_mirrors/open/Op…

作者头像 李华