Skip to content

output.py — 经典输出格式化 ​

经典 CLIOutputFormatter

apkid/output.py 是 经典 CLI(apkid 命令)的输出层。与 ai_output.py 平行,但风格不同:彩色终端表格或紧凑 JSON,且支持写多文件目录。

📋 文件内容 ​

符号类型说明
prt_* 系列lambdaANSI 颜色辅助函数
is_windows_cmd()func检测 Windows cmd(不支持 ANSI)
colorize_tag(tag)func按 tag 上色
OutputFormatterclass格式化器

🎨 彩色系统 ​

python
prt_red    = lambda s: f"\033[91m{s}\033[00m"
prt_green  = lambda s: f"\033[92m{s}\033[00m"
# ... 共 11 种颜色

colorize_tag 按 tag 类别选色:

tag颜色含义
compilercyan编译器
manipulatorlight cyan篡改器
abnormallight gray异常
anti_vm/anti_debug/anti_disassembly/anti_rootpurple反分析
packer/protector/anticheatred加固/保护
obfuscatoryellow混淆
droppergreen释放器
embeddedlight purple内嵌
file_typeorange文件类型
internalpink内部

is_windows_cmd() 在 Windows 且无 SESSIONNAME 时返回 True,此时禁用颜色(cmd.exe 不认 ANSI)。

🧱 OutputFormatter ​

构造 ​

python
def __init__(self, json_output, output_dir, rules_manager, include_types):
    self.output_dir = output_dir
    self.json = json_output or output_dir   # output_dir 隐含 JSON
    self.version = __version__
    self.rules_hash = rules_manager.hash
    self.include_types = include_types

关键:output_dir 不为 None 时,self.json 强制为 True——写目录必须用 JSON(每文件一个 json)。

write(results) ​

python
def write(self, results):
    if self.output_dir:
        # 取最短 key 作为基准文件名(嵌套时外层最短)
        base_file = sorted(results.keys(), key=lambda k: len(k))[0]
        out_file = os.path.join(self.output_dir, *base_file.split(os.path.sep))
        # 建目录、写 json
    else:
        if self.json:
            self._print_json(results)
        else:
            self._print_console(results)

--output-dir 模式:把每个扫描结果写成 <output_dir>/<文件路径>.json,保留目录结构。适合批量特征提取。

[*] app.apk!classes.dex
 |-> compiler : dx
[*] app.apk!lib/arm64/libfoo.so
 |-> obfuscator : ollvm_v9

TTY 且非 Windows cmd 时给 tag 上色。非 TTY(管道/重定向)输出纯文本,方便脚本处理。

build_json_output ​

python
{
  "apkid_version": "3.1.0",
  "rules_sha256": "...",
  "files": [
    { "filename": "app.apk!classes.dex", "matches": { "compiler": ["dx"] } },
    ...
  ]
}

注意这与 AI 输出格式 不同 schema——经典 JSON 是 {files: [{filename, matches}]},AI JSON 是 {findings: [], summary: {}}。AI 输出更适合程序解析,经典 JSON 是历史格式。

_build_match_results ​

把 List[Match] 转成 Dict[tags_string, List[description]]:

python
{
  "compiler": ["dx"],
  "obfuscator": ["OLLVM v9", "string encryption"]
}

file_type tag 在 include_types=False 时被过滤。

🆚 与 AIOutputFormatter 的区别 ​

维度OutputFormatter(经典)AIOutputFormatter(AI)
用在哪apkid 命令apkid-ai-cli、apkid-mcp
终端输出彩色表格文本(可选)
JSON schema{files:[{filename,matches}]}{findings:[...], summary:{}}
finding 粒度按 tags 分组每条规则每 tag 一条
置信度无high/medium/low
schema_version无1.0.0
写多文件支持(--output-dir)不支持

两者共享同一个 Scanner 输出(Dict[str, List[Match]]),只是格式化方向不同。

📍 相关 ​

基于 GPL & Commercial 双重许可发布