Acme_Sun - virtuoso
type: channel
link: https://acmesun.cn/tag/virtuoso/
items: cxt 上下文算法介绍
items: ile混淆算法介绍

cxt 上下文算法介绍
type: item
date: 2026-07-12T23:28:00+08:00
description: Virtuoso CXT 文件结构、生成原理与三种恢复方案1. 文档范围本文介绍以下内容：CXT 文件是什么，以及它与普通 SKILL 源文件有什么区别。CXT 是怎样从 SKILL/SKILL++ 代码生成的。CXT 文件在磁盘上的整体组织结构。procedure、普通变量、defclass、defgeneric 和 defmethod 在 CXT 中如何表示。CXT 加载时，保存地址如何被重定位成当前进程中的有效地址。为什么受保护的 VCODE 仍然可以被恢复。三种恢复方案：传统方案：修改 Virtuoso 的 *.so，让 pp 忽略保护判断。创新方案一：使用 GDB 修改正在运行的 Virtuoso 内存，再使用 pp。创新方案二：用 C 程序直接加载 *.so，脱离 Virtuoso 和 pp。本文不展开 CXT 外层的简单 XOR 处理。这里关注的是完成外层处理之后，CXT 内部真正有用的对象图、VCODE、类和方法数据。1.1 版本边界文中的精确偏移来自Virtuoso 618版本运行库不同 Cadence/Virtuoso 版本可能改变结构大小、字段含义或内部函数地址。因此应把本文理解为：对当前分析版本已经验证的结构说明；分析其他版本时的可靠方法；不是对所有历史版本都保证不变的公开 ABI 文档。例如，version 602 的 FunObj 是 40 字节，而 version 601 的旧 FunObj 路径使用 32 字节布局。2. 先建立一个正确直觉：CXT 不是源代码压缩包初学者最容易产生的误解是：“CXT 可能只是把 .il 源文件压缩或加密后放进去，解开以后就能拿回原文。”实际情况不是这样。CXT 更接近一份“SKILL 运行时对象图快照”。源代码被读取、求值或编译以后，运行时会形成很多对象：Symbol，也就是变量名和函数名；普通变量的最终值；List/Cons；String；Array；FunObj；VCODE；class metadata；generic method table；method 安装记录；TopForm；namespace 和导出信息。CXT 保存的是这些运行时对象及其相互引用，而不是原始文本。可以把两者类比为：SKILL 源文件 类似“建造说明书” CXT 类似“建造完成后的零件、连接关系和部分可执行程序”因此，恢复出来的代码通常可以在语义上接近原始代码，但以下内容往往已经不可逆地丢失：注释；空格和换行风格；原始括号排版；局部变量原始命名的一部分；某些宏展开前的写法；被优化掉的中间表达式；普通变量赋值时原始 RHS 的计算过程。例如，普通快照路径下：foo = 1 + 2和：foo = 3最终都可能只留下“Symbol foo 的值为整数 3”。仅根据最终 binding 无法判断原来是哪一种写法。3. 阅读本文前需要认识的几个术语3.1 SymbolSymbol 是 SKILL 运行时里的“名字对象”。同一个 Symbol 可以同时关联：普通变量值；函数定义；property list；namespace；保护标志。因此，变量名和函数名不是两种完全不同的对象。它们都可以从 Symbol 开始，只是使用的 binding 槽不同。3.2 BindingBinding 可以理解为“某个名字当前绑定到什么对象”。在当前 64 位版本中：Symbol +0x18 是普通变量值 binding；Symbol +0x20 是函数定义 binding。这也是下面两个函数的区别：ilGetSym(symbol) -> 读取 symbol + 0x18，普通变量值 ilGetd(symbol) -> 读取 symbol + 0x20，函数定义3.3 ILValueILValue 是 SKILL 运行时中常见的 64 位值表示。它既可能直接保存一个小整数，也可能保存指向对象的指针。常见低位标记如下：形式含义0nilvalue & 1 != 0立即数整数，通常为 `(n << 2)value & 2 != 0List/Cons 引用低两位为00对齐后的堆对象指针例如：整数 1 -> (1 << 2) | 1 = 0x5 整数 123 -> (123 << 2) | 1 = 0x1ED因此，小整数不一定需要单独的 integer object。3.4 FunObjFunObj 是 SKILL 可执行函数对象。对于编译后的 SKILL 函数，它会关联：参数数量和参数描述；VCODE 向量；指令入口；函数子类型；保护标志。3.5 VCODEVCODE 是 SKILL 运行时使用的 64 位 qword 混合指令流。它不是字符串，也不是原始源码。VCODE 中可以混合出现：指令 word；立即数；Sym…

ile混淆算法介绍
type: item
date: 2026-07-11T23:59:00+08:00
description: *.ile 文件混淆算法详解1. 文档目标与范围本文独立说明 Encrypt 生成混淆文件的完整过程，包括：文件由哪些区域组成；38 字节元数据区如何构造；64 字节混淆头如何生成；设置密码与不设置密码时，混淆头有什么区别；官方读取逻辑如何恢复元数据、判断密码并读取正文；正文如何经过固定密钥表和前一密文字节进行链式 XOR；如何用一段清晰的 C 代码恢复元数据和正文。本文把该方案称为“混淆”，因为它使用固定密钥和可逆 XOR，不具备现代密码学加密算法应有的安全性。2. 基础概念2.1 bit、byte 和十六进制计算机中的最小信息单位是 bit（位），一个 bit 只能取 0 或 1。在当前 x86-64 平台上：1 byte = 8 bit一个字节可以表示 0~255。使用十六进制表示时，范围是：0x00 ~ 0xFF一个字节本身只是数字。只有按照某种字符编码解释时，它才可能表示字符。例如 ASCII/UTF-8 中：内容字节数十六进制字节A141a1610130空格120换行\n10A字符串结束符\0100中3E4 B8 AD常见 emoji通常 4取决于具体字符C 字符串以 \0 结束。因此字符串 "ABC" 在内存中占 4 字节：41 42 43 00 A B C \0本文中的“密码最多 15 字节”是字节限制，不是字符数量限制。15 个 ASCII 字符正好是 15 字节；常见中文字符在 UTF-8 中通常每个占 3 字节，因此 15 字节通常只能完整容纳 5 个中文字符。2.2 文件偏移文件偏移表示一个字节距离文件开头有多远，从 0 开始计数：文件顺序：第1字节 第2字节 第3字节 ... 第65字节 第66字节 文件偏移： 0 1 2 ... 64 65因此：偏移 0 是文件第 1 字节；偏移 64 是文件第 65 字节；偏移 65 是文件第 66 字节。C 数组下标采用相同规则：data[0] /* 文件第 1 字节 */ data[64] /* 文件第 65 字节 */ data[65] /* 文件第 66 字节 */十六进制 0x40 等于十进制 64，0x41 等于十进制 65。2.3 XOR 异或C 语言中的 ^ 是按位 XOR（异或）：0 ^ 0 = 0 0 ^ 1 = 1 1 ^ 0 = 1 1 ^ 1 = 0XOR 有三个重要性质：A ^ A = 0 A ^ 0 = A A ^ B ^ B = A因此，如果：cipher = plain ^ mask;再次 XOR 相同的 mask 就能恢复：plain = cipher ^ mask;3. 文件整体结构生成的文件分为三个区域：文件偏移长度内容作用01 字节0x02加密/混淆文件标志1~6464 字节混淆头隐藏密码和可选参数，并提供正文初始状态65~EOF可变正文密文规范化源码及包装文本的链式 XOR 结果图示如下：+-----------+--------------------------------------+-------------------------+ | 偏移 0 | 偏移 1~64 | 偏移 65~文件结束 | +-----------+--------------------------------------+-------------------------+ | 标志 0x02 | 64 字节混淆头 | 正文密文 | | | 38 个元数据槽 + 26 个随机干扰槽 | 从 key[126] 开始循环 | +-----------+--------------------------------------+-------------------------+偏移 64 是混淆头最后一个字节。它不是正文的明文，但会直接作为正文混淆的初始“前一个密文字节”。4. 总体生成流程flowchart TD A["接收源文件、目标文件、可选密码和可选整数参数"] --> B{"源文件名和目标文件名相同?"} B -- "是" --> Z["报错并停止"] B -- "否" --> C["调用 ilCompress 解析并规范化源文件"] C --> D["目标文件写入标志 0x02"] D --> E["使用当前时间初始化随机数"] E --> F["构造 38 字节 metadata"] F --> G["将 metadata 分散到 64 字节混淆头"] G --> H["保存偏移 64 作为正文 previous_cipher"] H --> I["生成开头时间包装文本"] I --> J["链式 XOR 写入规范化源码"] J --> K["生成并链式 XOR 写入结尾时间包装文本"] K --> L["关闭文件并删除临…