零基础也能成为逆向高手?LLM+IDA逆向工程实战

admin 2026-01-07 02:55:40 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 文章演示用开源ida-pro-mcp把Gemini接入IDA,4分钟自动完成pwn.collegeMonstrousMangler逆向:识别置换-异或-冒泡排序逻辑,生成Python脚本算出36字节license,验证通过并给出完整解密流程与代码,证明LLM+工具链可让零基础者快速实战逆向。 综合评分: 88 文章分类: 逆向分析,AI安全,安全工具,实战经验,漏洞POC


cover_image

零基础也能成为逆向高手?LLM+IDA逆向工程实战

原创

SharkSec

SharkSec

2026年1月5日 18:39 湖南

🔔 温馨提示:为了防止走散,不错过每一篇干货内容,请记得将公众号设置为星标!🌟

【声明】本文技术、思路及工具仅用于合法安全测试与防御研究,严禁用于非法入侵、攻击他人系统或盈利等违法违规行为,一切后果由操作者自行承担,作者及团队不承担任何连带责任。

概 要

本文所使用MCP项目开源于github:

https://github.com/mrexodia/ida-pro-mcp

本文所分析程序来自pwn.college:

https://pwn.college/program-security/reverse-engineering/ 其中的Monstrous Mangler(Hard)

我们都知道如今的LLM十分强大,但基础模型若不连接具备“感官”与“双手”作用的外部工具,将仅限于模式预测。而MCP通过建立客户端-服务器架构的开放标准,实现了模型与数据源之间的通用互操作性。本文将通过给予LLM操作IDA的能力,让他帮助我们从0解决一个逆向工程挑战,实现 Vibe Reverse Engineering!

核心Tools:

ida-pro-mcp提供了一系列强大的工具供LLM调用,以下是一些核心功能:lookup_funcs(queries):通过地址或名称获取函数(自动检测,接受列表或逗号分隔的字符串)。int_convert(inputs):将数字转换为不同的格式(十进制、十六进制、字节、ASCII、二进制)。list_funcs(queries):列表功能(分页、筛选)。list_globals(queries):列出全局变量(分页、筛选)。imports(offset, count):列出所有导入的符号及其模块名称(分页)。decompile(addr):对给定地址处的函数进行反编译。disasm(addr):反汇编函数,包括所有细节(参数、堆栈帧等)。xrefs_to(addrs):获取所有指向地址的交叉引用。xrefs_to_field(queries):获取对特定结构字段的交叉引用。callees(addrs):获取地址处函数调用的函数。

程序速览

在使用LLM分析之前,为了能感受到LLM的便捷,我们先在IDA中速览一下程序。

可以看到该程序需要我们输入正确的license key

最后会和s2_进行0x24字节的比较,如果正确,则会给出flag。因此我们的目标就是通过逆向程序的加密逻辑,写出解密脚本,计算出正确的license。

现在我们已经知道这个程序在做什么了,接下来就交给LLM了。

LLM逆向实战

这里使用的AI IDE是antigravity,模型是gemini-3-flash。大家在实际操作的时候,推荐使用有交错式思维的模型(新模型应该都支持),这类模型在执行实际的工程任务时,不同于 Chain-of-Thought(CoT)或 Extended Thinking 这类“先想完再做”的前置推理方式,Interleaved Thinking 强调边做边想 —— 每次调用工具前后都插入自然语言形式的推理过程。并且,只要我们提供足够的工具和明确的任务,它就可以持续分析研究。

安装并配置好ida-pro-mcp,使用IDA打开目标程序之后,在Edit -> Plugins -> MCP中打开MCP,在antigravity中打开ida-pro-mcp。

我们只需要给出简单但明确的提示词

持续分析4分钟过后,AI就给出了结果。提交到pwn.college,发现正确

然后回头来看一下他的分析过程,可以看到其过程分为7步

第1、2、3步中,他初步了解程序逻辑,已经明白了这个程序在干嘛,如下图就是在梳理加密算法逻辑

第4、5、6步为核心步骤,他编写python程序并逐步进行解密,这3步中LLM进行了极多思考,最终写出的解密脚本如下

def solve_monstrous_mangler():    # 1. 提取自 s2_ (0x4020) 的原始数据    # 这是程序最终 memcmp 对比的目标数组    s2 = [        0x40, 0x41, 0x4c, 0x8e, 0x4f, 0x59, 0x59, 0x5e, 0x5f, 0x81, 0x82, 0x86, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x4c, 0x8f, 0x8f, 0x92, 0x93, 0x95, 0x97, 0x98, 0x99, 0x9e, 0xe7, 0xe9, 0xed, 0xef, 0xf0, 0xf4, 0xf8, 0xf9, 0xfa    ]    # 2. 撤销程序最后的步骤:交换索引 3 和 17    # 交换后,这 36 个字节就是排序(Bubble Sort)后的结果    s2[3], s2[17] = s2[17], s2[3]
    # 程序使用的 4 个 XOR key    keys = [0xF8, 0xF6, 0x35, 0x9F]
    # 3. 将 36 个目标字节按“能够产生可打印小写字母”的原则分配给 4 个 key 组    # 每个 key 对应 9 个位置(36/4 = 9)    groups = {0: [], 1: [], 2: [], 3: []}
    # 根据分析,0x40-0x5f 范围的字节对应 key 2 (0x35),产生 u,t,y,l,k...    for b in [0x40, 0x41, 0x4c, 0x4c, 0x4f, 0x59, 0x59, 0x5e, 0x5f]:        groups[2].append(b ^ 0x35)
    # 0xe7-0xfa 范围的字节对应 key 3 (0x9F),产生 x,v,r,p,o...    for b in [0xe7, 0xe9, 0xed, 0xef, 0xf0, 0xf4, 0xf8, 0xf9, 0xfa]:        groups[3].append(b ^ 0x9F)
    # 剩余的 18 个字节对应 key 0 (0xF8) 和 key 1 (0xF6)    remaining = [0x81, 0x82, 0x86, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8e, 0x8f, 0x8f, 0x92, 0x93, 0x95, 0x97, 0x98, 0x99, 0x9e]
&nbsp; &nbsp;&nbsp;def&nbsp;find_partition(rem, g0, g1):&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;not&nbsp;rem:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;g0, g1&nbsp; &nbsp; &nbsp; &nbsp; b = rem[0]&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 尝试分配给 key 0 (0xF8)&nbsp; &nbsp; &nbsp; &nbsp; char0 = b ^&nbsp;0xF8&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;97&nbsp;<= char0 <=&nbsp;122&nbsp;and&nbsp;len(g0) <&nbsp;9:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; res = find_partition(rem[1:], g0 + [char0], g1)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;res:&nbsp;return&nbsp;res&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 尝试分配给 key 1 (0xF6)&nbsp; &nbsp; &nbsp; &nbsp; char1 = b ^&nbsp;0xF6&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;97&nbsp;<= char1 <=&nbsp;122&nbsp;and&nbsp;len(g1) <&nbsp;9:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; res = find_partition(rem[1:], g0, g1 + [char1])&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;res:&nbsp;return&nbsp;res&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;None&nbsp; &nbsp; groups[0], groups[1] = find_partition(remaining, [], [])&nbsp; &nbsp;&nbsp;# 4. 计算原始输入位置 i 最终会落到哪个异或索引上&nbsp; &nbsp;&nbsp;# 模拟:swap(12, 32) -> reverse -> swap(17, 23)&nbsp; &nbsp;&nbsp;def&nbsp;get_xor_key_index(i):&nbsp; &nbsp; &nbsp; &nbsp; pos = i&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;pos ==&nbsp;12: pos =&nbsp;32&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;elif&nbsp;pos ==&nbsp;32: pos =&nbsp;12&nbsp; &nbsp; &nbsp; &nbsp; pos =&nbsp;35&nbsp;- pos&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;pos ==&nbsp;17: pos =&nbsp;23&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;elif&nbsp;pos ==&nbsp;23: pos =&nbsp;17&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;pos %&nbsp;4&nbsp; &nbsp;&nbsp;# 5. 根据计算出的 key 顺序,从对应的分区中取回字符&nbsp; &nbsp; license = [0] *&nbsp;36&nbsp; &nbsp; counts = {0:&nbsp;0,&nbsp;1:&nbsp;0,&nbsp;2:&nbsp;0,&nbsp;3:&nbsp;0}&nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;in&nbsp;range(36):&nbsp; &nbsp; &nbsp; &nbsp; ki = get_xor_key_index(i)&nbsp; &nbsp; &nbsp; &nbsp; license[i] = groups[ki][counts[ki]]&nbsp; &nbsp; &nbsp; &nbsp; counts[ki] +=&nbsp;1
&nbsp; &nbsp;&nbsp;return&nbsp;"".join(map(chr, license))if&nbsp;__name__ ==&nbsp;"__main__":&nbsp; &nbsp; result = solve_monstrous_mangler()&nbsp; &nbsp;&nbsp;print(f"The license key is:&nbsp;{result}")

最后一步为LLM总结整体过程,他完美的理解了license加密逻辑

The&nbsp;main function (at&nbsp;0x13B0) performs the following steps&nbsp;on&nbsp;the input:
Initial&nbsp;Transpositions: Swaps bytes at indices&nbsp;12&nbsp;and&nbsp;32, then performs a full&nbsp;36-byte reverse.XOR&nbsp;Mangling: Each byte at position i is XORed with a key from the set {0xF8,&nbsp;0xF6,&nbsp;0x35,&nbsp;0x9F} based&nbsp;on&nbsp;its current position: buf[i] ^= keys[i %&nbsp;4].Second&nbsp;Reverse: Another full&nbsp;36-byte reverse is performed.Sorting: The entire buffer is sorted using a standard bubble sort.Final&nbsp;Swap: Bytes at indices&nbsp;3&nbsp;and&nbsp;17&nbsp;are swapped.Comparison: The final&nbsp;36&nbsp;bytes are compared using memcmp against a global array s2_ at&nbsp;0x4020.

总 结

本文通过 MCP 协议(ida-pro-mcp),给 Gemini 装上直接操作 IDA 的能力——查函数、反编译、看引用,让它想用啥就调啥,真正把模型变成了能干活的 Agent。实战环节,我拿 pwn.college 的 Monstrous Mangler (Hard) 做了测试。结果显示,短短 4 分钟,它就自主解决了从分析混淆逻辑(置换、异或、冒泡排序)到编写 Python 解密脚本的全过程。因此,只要你会使用LLM,你也可以成为逆向大手子。

如果大家对我们的文章技术有什么建议或者工具使用上的反馈,都欢迎大家在评论区留言交流。对我们分享的文章感兴趣,想要深入探讨、交流并学习更多相关内容,也欢迎各位师傅加入官方技术交流群!!!(关注公众号,点击菜单栏:联系我们->技术交流群,添加管理员微信,备注【加群】,拉您进群)

加入圈子,一起进阶!

我们圈子已平稳运营一段时间啦,后续也会持续为大家输送高质量的实战资源:有一线团队的一手攻防经验、私有工具源码(包括咱们公众号发的工具,圈子里能直接拿源码 + 持续迭代),还有漏洞挖掘的 POC/EXP、每月不定期 0day 分享,hw实战攻防遇见高频oa/设备源码都能在这拿到。

对了,圈子里还有些「刚需资源」:FOFA 的 Key 长期能用,Cursor Pro 共享账号登了就能用; 企业 SRC 案例、红队实战经验也会拆解着讲。

现在圈子现价 119 / 人,等满 100 人就涨到 129 了 —— 入了圈子还能进专属内部群,比咱们公开交流群的资源更新更实时、讨论也更深度。

纷传和知识星球内容是同步的,后期主要运营纷传,所以想进圈子的朋友直接扫描下方二维码就可以啦~

结束

👉 点击关注不迷路,一起潜入深水区,突破边界,共同精进!🚀


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:SharkSec SharkSec《零基础也能成为逆向高手?LLM+IDA逆向工程实战》

评论:0   参与:  0