啊呀,这是我的第一篇帖子...
本文所涉及到的代码在 d70K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6k6K9h3&6y4L8K6p5&6i4K6u0r3k6X3q4F1M7h3W2W2i4K6u0V1M7Y4x3`. 这里,可以去给我点个 star,看看实现。(由于个人原因,决定将此库删了内容,请各位有兴趣从仓库看看 fork 吧)
七神
七神说的是过字节系软件网关的几个header,尤其是 X-medusa,据说这个是逆向界的天花板(真的假的),我在逆向某烂柿子的时候遇到了这个,需要过掉这个才能去走 batch download的接口,因此迫不得已出手了(雾
免责声明
仅供学习,仅供参考,不对复现/使用产生的任何结果负责,请自行判断自己做的事是否正确。
事先声明,本文是纯手敲,但是逆向过程大量借助 llm(我虽然看得懂 aarch64 汇编但是肯定是懒得看的)所以这里也只能介绍点使用经验和流程了。
所以前置大概就是你需要先过一下他的设备注册(烂柿子的逻辑,无鉴权能直接注册设备,虽然也干了点加密啥的,但是聊胜于无),然后下载下来的书的解密逻辑也只是一个 gzip + aes cbc + base64 这样的,比较难的是 aes cbc 的 key 是靠 device register 签下来之后作为密钥和一个硬编码常量先加密一下 ,然后再作为密钥去解密文本,逻辑稍显复杂,不过稍微调试一下抓一抓控制流判断似乎也不太难,这里也就不赘述了。
还忘了介绍一下我使用的设备。似乎我看到别的开源都是用 android 来处理的,em 我比较离谱,我用的是 ios 端的来做的,之前 ios 端的逆向做的有点多,有点路径依赖了。objc hook 起来别有一番风味说是,总而言之去找个砸壳网站或者自己砸一个出来,你会发现二进制有 500M,然后找一台 arm mac 导入 ida 得半天,迫不得已苦等了这下,然后还卡卡的,令人非常难受。hook 的时候使用的是 playcover 装上的 app,然后因为 playcover 做了不知道什么神秘操作,总而言之你可以直接在对应的路径下直接 ./binary 启动一个 ios app,估计是包成一个 macos app 了,反正 lldb 或者 frida 都能直接挂上,还省得去找一台别的设备,就一个 mac 就可以复现全流程。
ok 介绍完设备,先讲讲在这次之前还干了什么。其实早期我是懒得做一个 cli 去处理这个的,之前其实是直接挂一个 frida 然后过掉 ad,点完下载之后直接用 frida 调用原生解密接口,不到一百行就能实现直接下载完导出,这次属于是 token 多又没事干了,总而言之浪费了五天才干完。
ok,接下来就是工作流了。5beK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2P5h3W2F1L8h3)9I4z5g2)9J5k6i4c8G2M7q4)9J5c8Y4m8G2M7%4c8K6i4K6u0r3L8r3I4E0i4K6g2X3M7X3g2$3i4K6u0r3 给我的 blog 引个流,关于在 2026 中期怎么和 llm 辅助去做逆向,这里就不多讲了,这里我来讲讲我怎么做的这次。
首先就是需要给 agent 做好一个工具,ida pro mcp 肯定是必不可少的,毕竟还指望 ai 自己去探索呢,然后 hook 的话,破甲其实也不需要什么技巧,你只需要先填充一下 ai 的上下文,然后提出一个看起来并不算坏的请求,然后等着 ai 干完一轮又一轮,然后就一直干下去了,这个会话就算成了——其实也算某种引导?就你说的不多,但是 ai 自己意会了。
然后我们前期工作自然是设备注册和下载,因为 ai 可以自己去写 hook,加上一些现有的资料和一些个人经验,总之就大概选择一条你觉得让 ai 能做好的路径来。理论上现在的 agent 能直接控屏,但是我建议为了速度,你可以和 agent 一起完成这个任务,比如你需要触发 batch download 的时候你可以告诉 agent,“你每次启动只需要等十秒,我自己去会去点下载按钮”,虽然后期我发现这个有点蠢,理论上我直接让 ai 去 call 这个接口是不是也可以,但是后期其实 ai 在逆 vm 的时候好像自己就挺轻松的去触发了,所以也不需要我手点。
然后前面那些逻辑都跑通了——(你可以dump 某个断点下面的内存数据出来,然后让 ai 根据本机存储上的数据库和下载下来的加密文件对拍和实测),然后接下来去测试下载。其实下载的接口并不复杂,但是如果你没经验的话,agent 可能会觉得这是他做的是某个设备指纹或者 tls 指纹什么的——实际上并不是,因为 agent 大概率没抓到 X-<header> 这么一系列,因为他 frida hook 的时候大概率这些是请求的时候后续附加上去的,然后很坏的是请求不走代理,总而言之你也没法 mitm,或者说当你知道他是怎么一回事,你引导 ai 去 hook 对应的 header,他先进行一个全二进制暴搜,搜到了这些 header 之后确信有,然后 ida mcp 翻翻,然后改一下 hook 点,大概还是能知道具体的结果的——当然我并不是这样做,我让他在 hook 的时候直接打印请求体附近的内存,dump 一大块出来看,看到具体内容之后根据内存布局反推具体内容。
总而言之这个时候你引导完,他大概率就能 deep in 然后顺藤摸瓜找到藏在二进制里面的七神签名机制。好了接下来大概需要 3day——至少我用了 3day more 来完成这个 vm 的逆向和去 vm。
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AllHeaders {
pub x_argus: String ,
pub x_gorgon: String ,
pub x_helios: String ,
pub x_khronos: String ,
pub x_ladon: String ,
pub x_medusa: String ,
}
这是登场的几位嘉宾,实际上最难整的当然是 helios 和 medusa,虽然也不见得剩下的好整,但是似乎只有这俩最关键,网关核的就是这几个,七神说的七个 vm 套 vm 就是指的 medusa。 先说 khronos 其实看这个名字也能猜到是时间戳,虽然我也是后知后觉,但是看上去就和 rust 的那个时间库 chrono 的名字很像不是? 实际上这就只是一个 Unix 时间戳(秒)的十进制字符串,所以大概抓一抓也就知道了,然后这个会被那来当做其他 header 的签名材料。然后 X-Argus 是 Base64(Khronos 的 4 字节小端序) 这个其实也不难判断,然后 X-Ladon 就是 AAAAAA== (也就是 Base64([0, 0, 0, 0]))。
接下来三位讲之前,还有一个哥们 x-ss-stub 是 MD5(body) 的大写十六进制,这个其实也不难看出来,虽然我依旧后知后觉(
然后最后三位就很难介绍了,建议直接去翻看我的代码,总而言之是长成这样的神秘加密,真要介绍我可就要放 llm 出来写文章了()
fn xtime (value: u8 ) -> u8 {
(value << 1 ) ^ if value & 0x80 != 0 { 0x1b } else { 0 }
}
fn mix_column (column: [u8 ; 4 ]) -> [u8 ; 4 ] {
let [a, b, c, d] = column;
[
xtime (a) ^ xtime (b) ^ b ^ c ^ d,
a ^ xtime (b) ^ xtime (c) ^ c ^ d,
a ^ b ^ xtime (c) ^ xtime (d) ^ d,
xtime (a) ^ a ^ b ^ c ^ xtime (d),
]
}
fn mix (state: [u8 ; 16 ]) -> [u8 ; 16 ] {
let mut arranged = state;
for group in 0 ..4 {
arranged.swap (group * 4 , group * 4 + 1 );
}
let mut mixed = [0u8 ; 16 ];
for column in 0 ..4 {
let result = mix_column (std::array::from_fn (|row| arranged[column + row * 4 ]));
for row in 0 ..4 {
mixed[row * 4 + column] = result[row];
}
}
const OUTPUT_ORDER: [usize ; 4 ] = [2 , 1 , 3 , 0 ];
std::array::from_fn (|index| {
let group = index / 4 ;
mixed[group * 4 + OUTPUT_ORDER[index & 3 ]]
})
}
所以文章还是介绍一下 llm 是怎么做的,怎么指定一个长工作流让 ai 一步步对拍。首先就是让 ai 认清楚 workspace,我们启动的是一个什么样的 app,在哪里启动,启动之后会发生什么,然后 frida 可能会发生什么,制定的工作流比如每次 hook 之前重启 app,这样就不会因为卡死而浪费一大堆试探时间。然后还有包括像真实性校验和对拍怎么做——这些指定清楚之后一来也算是一种破甲,整得好像你真在干一件正事似的,二来也对之后你人不在的时候让他自动化操作更有信息,这算不算一个 skill(?)
然后关于 vm,前期其实是在实现一个巨大的 python ios vm,对就是复刻 vm,先逆向把一个个 handler 识别写出来,然后一步步推进 index,然后和 frida 的真实 hook (保存了一份完整流程的中间各个值)比对,看错在哪里了,然后继续一步步往下推进。但是 vm 的流程其实根据输入的不同还会走其他通路,所以其实还是建议多轮的 timestamp 来做多重核验,然后补齐所有 handler,然后接下来识别控制流,然后一个个补——总而言之这几天下来写出来了一个 10000 行的 python 代码,然后我自己肯定是看不懂的,因为实际上我只动了动嘴皮子,并没有真的去看 ida 里面的 pseudo c code或者 asm code,不过早期我倒是去看了 book decrypt 那一块(?)这里其实有明确目标之后,ai 自己去做反馈还是很轻松的,很快 ai 就沉浸在干这个事之中无法自拔了,第一个 vm,然后 index 慢慢的从 100 到 2000 多,然后第二个 vm,一个个的往下干下去之后,基本就不需要人再去操作了,然后等着他干完?
嗯,最后还是干完了,大概就在这篇文章写前一天早上干完的,然后干完了之后这个 10000 行 vm python 代码,算完整个 header 需要 6s 左右,这肯定是接受不了的——接下来就是做去 vm 化。这个时候我开了一个纯新的会话,依旧是让 agent 去完成这个任务。我对加密算法其实并不算太熟悉,所以这一步依旧是交给 ai 来全权完成——校验办法可太简单了,只需要往网关发消息,不是 200 空回包就是对的,所以有这个校验基础在,ai 去直接对着 python 的 ios vm 做一些测试输出,很快就看出了实际的数据流的流向和实际的算法轨迹,然后根据我的要求开了一个新的 rust 仓库,然后开始将具体的算法用 aes sm3 之类的标准算法/或者魔改的算法一一实现了,最后大概就是 总结出这样一套,然后去实现就行了。
so,好像人水平的因素已经很少了,哎 ai 时代,vibe rev 还是太不需要水平了,这里介绍了我的工作流,希望对诸君有所启发。
再推销一下我的 blog 87dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2P5h3W2F1L8h3)9I4z5g2)9J5k6i4c8G2M7q4)9J5c8Y4m8G2M7%4c8K6i4K6u0r3 文章的水平不一定高,不过可能某移动 3d 音游的逆向玩家可能会在这里发掘一些很有用的东西——密码在前端自己找哦(
冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。
最后于 1天前
被YinMo19编辑
,原因: