加密数据还原

SkillCommerce & finance

加密数据还原:定位解密函数、写解密脚本。 触发词:解密、decrypt、还原数据、解密流量

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the 加密数据还原 skill

What this skill tells your AI

The instructions your AI receives, as published by dslsdzc/rev-skills in .claude/skills/re-crypto-decrypt/SKILL.md and read by ahel’s review.

何时使用 / 何时不用

  • 用:需要把密文(数据 blob / 流量 / 配置段)还原成明文
  • 用:算法与密钥已知(或已由 [[re-crypto-id]] / [[re-crypto-keys]] 得出),需要批量解密
  • 用:从样本里还原解密逻辑并重写为独立可复用的脚本
  • 不用:算法/密钥都未知(先 [[re-crypto-id]] → [[re-crypto-keys]])
  • 不用:静态可读的明文([[re-triage]] 熵低直接读)
  • 不用:想跑原样本看输出(那是 [[re-behavior]] / [[re-sandbox]] 的活——解密脚本是为了脱离样本复现)

工具准备

所有工具先验证再使用。本技能处理的是转储/反编译产物与密文数据,运行样本环节在 [[re-sandbox]] 内([[re-analyze/platform-tips]] 最高原则)。

python3 + pycryptodome —— 解密脚本主力

  • Linux: apt install python3 python3-pip / dnf install python3 python3-pip / pacman -S python python-pip
  • macOS: brew install python
  • Windows: python.org 安装包(勾选 Add to PATH);WSL 内 Linux 版
  • 加密库: pip install pycryptodome(AES/DES/RSA/ChaCha 等标准算法)
  • 验证: python3 -c "from Crypto.Cipher import AES; print('ok')"python3 --version

目标程序转储/反编译产物 —— 还原算法的依据

  • 转储: [[re-memdump]] 默认转储(gcore)——定位密文输入点与解密调用现场
  • 反编译: [[re-ghidra]] / [[re-ida]] / [[re-radare2]] 的产物(函数反编译视图)
  • 验证: file out 是 ELF core;反编译器里能找到目标函数(ghidra / rizin 可启动)

angr(可选)—— 符号执行补足难还原的逻辑

  • 全平台: pip install angr(Python 3.8+,依赖多,建议 venv: python3 -m venv venv && venv/bin/pip install angr
  • 验证: venv/bin/python -c "import angr; print(angr.__version__)"
  • 用途: 反编译分支爆炸/混淆严重时,用符号执行求解密函数输出(加载目标二进制 → 设密文输入为符号 → 约束求解)

操作步骤

按顺序执行,每步记下结果。前提:算法([[re-crypto-id]])与密钥([[re-crypto-keys]])已确认或至少有一方候选;脚本与验证结果(明文样本 + sha256)存档供报告引用。

  1. 证伪"密文":先定位真实密文边界(跳过此步是加密分析最常见的失败方式):

    • 高熵段可能是"伪密文"——容器/压缩数据流被误当加密层(如 zip 数据本体、附加在图片后的压缩流)。压缩数据熵同样是 8.0,与加密不可区分
    • 先做整体结构观察:文件头/尾魔数、格式 marker 分布(JPEG 逐段统计大小)、尾部已知结构当锚点(zip EOCD 的 cd_offset/cd_size 反推数据起点,EOCD 签名是已知明文)
    • 找格式结束标记用第一个(JPEG EOI FFD9、PNG IEND),不是最后一个——数据流里碰巧出现的标记字节对会把分析带偏(曾把 zip 数据中的 FFD9 误当图片结尾,把数据流当密文穷举)
    • 同尺寸文件先比尾部 16 字节/整体哈希——"换头副本"(同一 payload 的第二种封装,仅头部不同)直接省掉一整条支线
    • 压缩率是信号:解压后明显变大的层说明内容有结构(可压=编码/明文),接近 1:1 说明内层已压缩或加密
    • 确认是孤立高熵 blob 后再进入步骤 1 的密文定位
  2. 定位解密函数(交叉引用密文输入点)

    • 从密文偏移出发:[[re-crypto-id]] 步骤 2 的高熵区偏移 → 反编译器里找读取该偏移/该全局变量的函数 → 沿调用链看谁写入了它(写入方常是解密函数)
    • 从 API 出发:[[re-crypto-keys]] 步骤 4 找到的 Crypt*/EVP_* 调用点就是候选;观察入参的密文指针是否指向步骤 2 的偏移
    • 动态辅助: [[re-gdb]] / [[re-x64dbg]] 在候选函数下断点(沙箱内),打印入参/返回值,确认它输出可读明文
    • 找不到明确函数 → 密文可能由内联展开的算法处理(无调用边界),回 [[re-crypto-id]] 用数据特征定位(常量表引用处)
  3. 反编译还原算法

    • 把反编译视图逐段抄译成伪代码,明确:算法(AES-CBC/自定义 XOR…)、密钥与 IV 来源(固定值/派生/上下文)、模式与填充(CBC 的 IV 在哪、PKCS7 还是零填充)
    • 自定义算法: 逐条翻译位运算(XOR/移位/查表),注意字节序([[re-proto-rev]] 坑 1 同理——长度/密钥字段先试大小端)
    • 还原标准算法时留意细节:AES 用 CBC 还是 ECB、key 长度 16/24/32、IV 是否复用密钥(常见错误实现,见坑 1)
    • 反编译看不清的循环/查表逻辑 → angr 符号执行兜底(构造求解脚本,把函数当黑盒求输出)
  4. 重写为独立脚本(python)

    # decrypt.py —— 按反编译还原的算法重写
    from Crypto.Cipher import AES
    import sys
    key = bytes.fromhex("...")          # 来自 [[re-crypto-keys]] 步骤 1/2/5
    iv  = key[:16]                       # 样本实现: IV = key 前 16 字节
    data = open(sys.argv[1], 'rb').read()
    pt = AES.new(key, AES.MODE_CBC, iv).decrypt(data)
    print(pt)                            # 或写文件 + 后续校验
    
    • 脚本参数化(密钥/IV/输入文件走参数或配置),一次写对、反复复用——批量解流量用
    • 关键:脚本逻辑必须与样本一致(填充处理、尾部截断),不一致时回查边界条件(见坑 1)
  5. 用已知明文验证

    • 已知明文来源:协议头 magic(如 \xAA\x55)、文件头(PK zip / \x89PNG)、报文字段([[re-proto-rev]] 步骤 2 的固定头)、或 [[re-behavior]] 行为里观察到的明文串
    • 验证方式:解密输出里能找到已知明文片段 → 成功;找不到 → 依次检查:密钥/IV 是否对([[re-crypto-keys]] 候选逐个试)、字节序、填充处理、是否还有外层加密(见坑 3)
    • 无已知明文时用"可读性"验证:输出可打印率 >70% 或通过 file - 识别出格式(PDF/zip/文本)→ 视为成功候选
  6. 流量场景:解出明文流量流

    • 已按 [[re-crypto-id]] / [[re-crypto-keys]] 确认流量加密算法与密钥后,从 pcap 提取密文载荷([[re-netcap]] 步骤 3 tshark 导出):
      tshark -r c2.pcap -Y 'tcp.payload' -T fields -e data.data | sed 's/://g' | xxd -r -p > payloads.bin
      
    • 写批量脚本:按流切分(每 TCP 流一段)、逐段调用解密逻辑(同步骤 3 的脚本),输出明文流文件
    • 验证: 明文流里能看到协议结构(会话序号/命令字),再转 [[re-proto-rev]] 做状态机重建
    • 注意会话密钥变化(每次握手重新派生)→ 脚本里为每个会话取对应密钥([[re-crypto-keys]] 步骤 5 的派生还原)

跨域联合

  • [[re-protocol]]:本网关工作流第 4 步(解密)——加密通信链路的落地点(crypto-id → crypto-keys → crypto-decrypt → proto-rev)
  • [[re-malware]]:C2 流量解密——re-malware 第 4 步;解出的明文(指令/配置)进行为判断与 IOC([[re-ioc]])
  • [[re-firmware]]:固件加密层/加密通信解密——配合 [[re-fw-extract]] 解包失败时的加密层处理
  • [[re-crypto-id]] / [[re-crypto-keys]]:上游——算法与密钥的输入来源
  • [[re-memdump]]:密文输入点定位与解密调用现场(转储产物)
  • [[re-anti-analysis]]:解密在壳内时先脱壳(见坑 2);[[re-gdb]] / [[re-x64dbg]] 动态辅助确认函数行为
  • 解出的明文转 [[re-proto-rev]] 重建状态机,或按 [[re-firmware]] / [[re-malware]] 流程继续

常见坑与陷阱

  • 还原脚本与样本行为不一致 → 回查边界条件(长度/填充):现象——脚本解出的明文与样本自身输出不一样(多/少字节、尾部乱码);原因——边界条件没对齐:填充方式(PKCS7/zero)、长度字段是否含填充、IV 是否每包变、密文尾部是否截断;对策——反编译里逐条核对填充与长度处理代码,脚本里显式实现,再回步骤 4 用已知明文验证
  • 解密在壳内 → 先脱壳:现象——在加壳样本里找不到解密函数,或找到的函数只是壳的解压;原因——密文数据/解密逻辑被壳包着,静态看是壳的初始状态([[re-memdump]] 坑 2 同理);对策——先 [[re-anti-analysis]] 脱壳(OEP 后再转储/反编译),脱壳产物重新做定位
  • 多轮解密链:现象——解出第一层后仍是乱码/高熵(熵 7.0+);原因——多层加密(先 XOR 再 AES,或嵌套压缩+加密,见 [[re-crypto-id]] 坑 3);对策——每层单独验证(解一层测一次熵与可读性),分层还原;可用"熵下降即前进一层"作为停止条件
  • 密钥/IV 顺序用错解出乱码:现象——已知明文验证失败,但算法确定是 AES;原因——key/iv 参数顺序(样本是 key||iv 拼接还是分开传)、密钥字节序、或 IV 复用/固定 IV;对策——把 [[re-crypto-keys]] 的候选(含大小端变体、IV=key 前缀等常见错误实现变体)做成参数组合循环试解,命中即可读性/已知明文判定
  • 受限符号集 = 编码不是加密(伪加密):现象——熵 7.9+ 但字节值域明显受限(如只有 66 个符号、分布均匀、无周期),xortool/IC 对所有密钥长度全平;原因——这是"编码 + 单字节 XOR":单字节 XOR 不改变频率分布与符号集(只平移值),多字节 XOR 才会把符号打散成 256 值;对策——收集全部符号值集合,与已知字符集做 XOR 匹配(对 256 个 key 做集合比较,毫秒级,别用穷举):Base64 64 字符 + \n + = = 66 符号、Ascii85 85、hex 16 等;命中后 XOR 还原 → 解码;交叉验证:填充符(如 = 加密后仅出现 1 次在文件尾)、换行符频率、解码后魔数
  • xortool/IC 结果全平 = 换思路的信号:现象——密钥长度候选全部 ~10-20% 且无突出峰值;结论——统计上不存在周期结构,多字节重复密钥 XOR 基本排除,别换参数继续跑;对策——退回观察数据本身(值域/符号集/熵),通常是编码层或一次性密钥流(流密码)
  • 伪密文已确认但层数不止一层 → 分层剥离纪律:每层剥完用魔数/可读性验证产物完整性再进下一层;中间产物全部保留命名(可回滚);熵不降 / 解出仍高熵 = 还有外层(如 XOR 外再 Base64、再压缩)
  • 像素级 XOR(视觉密码学/图像隐写):现象——两张"随机噪点"图,题目提示叠加;原因——视觉密码学把信息分成两张 share,XOR(或 ADD)像素后可见;对策——ImageChops.logical_xor 或 numpy a^b 逐像素 XOR 两图(RGB 三通道);结果常是"99.5% 纯白背景 + 极浅灰文字"(文字 254 vs 背景 255)——直接看/反色都不可见,用阈值增强==255 → 黑、其余 → 白,文字立现;位图小字再按字符网格(5x7)切分逐字读,重复字符用两两位图相似度矩阵验证(如 d562333d 的重复模式)
  • ADD 饱和加法是 XOR 的近亲:现象——XOR 结果无内容时;原因——share 可能由加法式秘密共享生成(XOR 得到噪声,ADD/SUB 才出图);对策——同样试 clip(a+b) 饱和加法与 a-b 减法,多运算组合对比
  • 新版混淆重 → 老版本回溯定位:现象——最新版核心函数混淆后体积异常庞大,IDA 分析卡顿,硬啃不现实;原因——同一 SDK 早期版本未上重混淆,核心逻辑更清晰;对策——按行为特征(如"同意隐私协议即触发采集")装历史版本包(豌豆荚等渠道)→ 点同意 → 抓包确认最早出现该参数的版本;选行为规范的版本做分析起点(调试方便:spawn/attach 都能复现);老版本还原出的逻辑反过来指导确认新版采集了哪些参数
  • 分段/分层加密上报(每段算法不同):现象——抓到的上报请求字段单看都像密文,但统一按一种算法解全是乱码;原因——客户端加密流程分多段:单字段加密 → 分段加密 → 整体加密,每段的算法/密钥不同(如第一层随机数做 key 逐字节加密、第二层固定 key、第三层拼接组合字段后再加密);且字段本身可能是设备采集的风险特征(svc 指令采集、r_1_0 类字段);对策——按"每层单独验证"纪律分层剥(熵降/可读即前进一层,见多轮解密链坑);注意同源 SDK 的"整体加密"可能再套 VM 化算法(约 70 个 handle 模拟基本指令、handle 未混淆时可逐个识别指令语义);key 来源分随机(抓包不可复现)与固定(可静态找)两类,先固定后随机
  • 双重 AES + 加密字符串(key/iv 也加密存):现象——确认 AES 后直接解仍失败,或 key/iv 每次会话都变;原因——实现常见套路:第一层 key/iv 固定(以加密字符串形式硬编码在 so,运行时经解密函数解出),第二层 key/iv 每次变化;两次加密间拼接固定前缀(如 03000001)再进同一函数;且加解密可能是同一函数(标志位控制方向);对策——hook 解密函数返回点批量导出全部解密字符串(JNI_OnLoad 前 memcpy 的加密串 → 全局变量 → 解密函数),key/iv 直接在其中搜索;找加密点用 findcrypt 扫特征常量(AES S-box 等)→ xref 定位校验 key/iv 长度(16)的函数;动态 hook 打印两次调用前后数据对照验证

Signals

GitHub stars
57
Forks
8
Last commit
Sep 2026

ahel review

  • K1binfo
    installs-packages

Automated review, not a security audit. Ruleset v1+k2.

Advanced
Catalog kind
skill
Gateway key
re-crypto-decrypt
Source
github.com/dslsdzc/rev-skills