grgalex/pyxray

GitHub: grgalex/pyxray

PyXray 通过混合静态与动态分析为含原生扩展的 Python 包构建跨语言调用图,支持漏洞可达性分析和依赖膨胀量化。

Stars: 5 | Forks: 0

[![DOI](https://img.shields.io/badge/DOI-10.1145%2F3744916.3764555-blue)](https://doi.org/10.1145/3744916.3764555) [![Zenodo](https://img.shields.io/badge/Zenodo-10.5281%2Fzenodo.18009456-blue)](https://doi.org/10.5281/zenodo.18009456) [![License: AGPL v3](https://img.shields.io/badge/License-AGPLv3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0) [![Docker Image](https://img.shields.io/badge/Docker-grgalex%2Fpyxray-blue)](https://hub.docker.com/r/grgalex/pyxray) # PyXray:实用的 Python 跨语言调用图 PyXray 是一款混合(静态/动态)分析工具,用于构建带有原生扩展的 Python 包的跨语言调用图 (XLCG)。 它随 ICSE'26 论文[*PyXray: Practical Cross-Language Call Graph Construction through Object Layout Analysis*](https://doi.org/10.1145/3744916.3764555)([PDF](https://grgalex.gr/assets/pdf/pyxray_icse26.pdf))一同发布。

PyXray cross-language call graph architecture diagram

### 用例 - 分析跨 Python 和原生代码的供应链 CVE 可达性 - 审计带有原生扩展的 Python 包 - 量化特定客户端包的依赖膨胀 ### 工作原理 PyXray: 1. 解析目标包的依赖关系 2. 通过分析可调用 Python 对象的活动对象布局,检测 Python 到原生的调用桥接 3. 生成静态 Python 调用图(通过 PyCG)和原生二进制调用图(通过 Ghidra) 4. 使用识别出的桥接将 Python 和二进制图缝合在一起 5. 为目标包及其所有依赖项生成统一的跨语言调用图 (XLCG) 桥接和调用图按包版本进行缓存,并在多次分析中重复使用,因此随着缓存的增长,计算 XLCG 的成本会降低。 请注意,XLCG 继承了底层调用图生成器(用于 Python 代码的 PyCG,用于二进制文件的 Ghidra)潜在的不精确性和不完整性,因此它可能包含误报和漏报。 ## 快速开始 **1. 使用 submodules 克隆** ``` git clone --recurse-submodules https://github.com/grgalex/pyxray.git ``` ``` cd pyxray ``` **2. 拉取预构建的镜像**(或在本地构建,参见 [docs/installation.md](docs/installation.md)) ``` docker pull docker.io/grgalex/pyxray:latest ``` 为了最大化桥接检测的准确性,PyXray 会从源代码构建正在分析的应用包(及其依赖项)并带有 debug symbols。默认镜像捆绑了所需的编译器、系统头文件和 Python 构建后端。如果您偏好较小的镜像,仅用于仅 wheel (`-W`) 分析的话,`grgalex/pyxray:slim` 就足够了。 **3. 启动一个容器** ``` docker run --rm -it --name pyxray \ -e GHIDRA_INSTALL_DIR=/ghidra --cap-add=SYS_PTRACE \ --security-opt seccomp=unconfined \ -v ${PWD}:/pyxray -w /pyxray \ grgalex/pyxray:latest ``` 以下所有命令都在容器内运行。结果将存放在 `data/` 目录下,该目录是从您的主机绑定挂载的。容器以名为 `pyxray` 的非 root 用户身份运行(UID 为 1000,并带有免密 sudo),因此结果的所有者为您的主机用户。 ## 使用说明 ### 1. 查找 Python 到原生的桥接 桥接是指由原生库内的 C 函数实际实现、但对 Python 可见的 callable。PyXray 通过对象布局分析发现桥接,而无需对包有任何先验知识: ``` pyxray bridges markupsafe:3.0.2 ``` 结果将写入 `data/star_bridges/m/markupsafe/3.0.2/starbridges.json`。每个桥接都会记录 Python 名称、C 函数以及包含该函数的原生库: ``` { "pyname": "markupsafe._speedups._escape_inner", "cfunc": "escape_unicode", "library": "markupsafe___3.0.2/markupsafe/_speedups.cpython-312-x86_64-linux-gnu.so" } ``` ### 2. 构建跨语言调用图 ``` pyxray xlcg markupsafe:3.0.2 ``` 这将运行完整的流水线:依赖解析、Python 调用图构建、桥接检测、使用 Ghidra 提取二进制调用图以及缝合。输出: - `data/unified_cg/pypi/m/markupsafe/3.0.2/unified.json`,完整的 XLCG - `data/reached_cg/pypi/m/markupsafe/3.0.2/reached.json`,从包入口点可达的子图 XLCG 是一个包含 Python 函数和原生函数的单一图。每个节点都带有其所属的包,原生节点还带有其所在的库,边是简单的从调用者到被调用者的配对,它们在桥接处跨越语言边界: ``` { "nodes": { "31": {"name": "markupsafe._speedups._escape_inner", "package": "markupsafe:3.0.2"}, "43": {"name": "escape_unicode", "library": "markupsafe/_speedups.cpython-312-x86_64-linux-gnu.so", "package": "markupsafe:3.0.2"} }, "edges": [[31, 43]] } ``` 在这个片段中,Python callable `markupsafe._speedups._escape_inner` 调用了包的原生扩展内部的 C 函数 `escape_unicode`。 ### 3. 量化依赖膨胀 在运行 `xlcg` 之后,`bloat` 会报告从客户端包实际可达的每个依赖项的比例: ``` pyxray xlcg thumbor:7.7.4 ``` ``` pyxray bloat thumbor:7.7.4 -T ``` `-T` 标志会打印汇总表。对于 thumbor,三个直接依赖项被发现完全未被使用: ``` Unreachable (3 packages): pytz:2023.4 (6 py files, 107 py funcs, 0 bin files, 0 bin funcs, 69.9K) webcolors:1.13 (6 py files, 31 py funcs, 0 bin files, 0 bin funcs, 39.4K) thumbor-plugins-gifv:0.1.5 (2 py files, 7 py funcs, 0 bin files, 0 bin funcs, 3.5K) ``` 每个包的完整度量指标将写入 `data/bloat/t/thumbor/7.7.4/bloat.json`。 我们向 thumbor 维护者报告了未使用的 `webcolors` 依赖,该问题已得到修复 ([thumbor#1808](https://github.com/thumbor/thumbor/issues/1808))。 ### 4. 检查 CVE 可达性 CVE-2024-28219 影响 10.3.0 之前版本 Pillow 中的原生函数 `buildTransform`。 在运行任何可达性分析之前,首先确定 PyXray 是否能完全看到漏洞符号。`bridge-reach` 会计算从包的任何 Python 到原生桥接可达的每个原生函数,因此请在其输出中搜索该符号: ``` pyxray bridge-reach pillow:10.0.1 ``` ``` grep buildTransform data/bridge_reach/p/pillow/10.0.1/bridge_reach.json ``` 如果没有匹配项,则 PyXray 无法观察到漏洞符号(例如,该符号可能已被内联或剥离),此时对其进行可达性分析将毫无意义。如果存在匹配项,则检查客户端可达性是有意义的:要确定特定应用是否间接受到影响,请搜索其已到达的 XLCG(thumbor 7.7.4 依赖于存在漏洞的 Pillow,我们在上一步中已经构建了它的 XLCG): ``` grep buildTransform data/reached_cg/pypi/t/thumbor/7.7.4/reached.json ``` 然后,PyXray 可以从客户端提取到漏洞函数的具体跨语言调用链: ``` python3 -m pyxray.call_chain -i data/reached_cg/pypi/t/thumbor/7.7.4/reached.json -s buildTransform ``` ``` [ "thumbor.engines.pil.Engine.read", "thumbor.utils.ensure_srgb", "PIL.ImageCms.ImageCmsTransform.__init__", "PIL._imagingcms.buildTransform", "buildTransform" ] ``` 该链条从 thumbor 的一个 Python 函数开始,跨越到 Pillow 的 Python 层,并最终结束于存在漏洞的原生代码内部。 ## CLI 概览 ``` pyxray [PACKAGE...] [options] Commands: bridges Find Python-to-native bridges of the package itself (deps excluded) bridge-reach Compute native reachability from ANY bridge (baseline for CVE reachability) xlcg Compute cross-language call graph (XLCG) bloat Calculate dependency bloat (requires prior xlcg) Package sources: PACKAGE One or more packages as name:version (e.g. numpy:1.26.4) or just name (e.g. pillow) to use the latest PyPI version -i, --input-file CSV file with name:version entries (one per line) --source-dir DIR Source project directory (auto-detect & install) --install-dir DIR Pre-installed site-packages directory --requirements FILE Requirements file (name:version per line) for --source-dir deps Options: --version Show version and exit -j, --jobs N Number of parallel workers (default: 1) -A, --always Force regeneration of all artifacts -B, --binary-always Force binary CG regeneration via Ghidra (xlcg/bridge-reach) -W, --wheel-only Use pre-built wheels instead of source builds -T, --table Print ASCII summary table (bloat only) -v, --verbose Stream subprocess output in real time --log LEVEL Logging level (debug, info, warning, error) ``` ## 文档 - **[docs/installation.md](docs/installation.md)**:通过 Docker 安装(拉取或在本地构建)或不使用 Docker 的手动设置。 - **[docs/advanced-usage.md](docs/advanced-usage.md)**:完整的 CLI 参考、所有子命令、批处理、并行机制、仅 wheel 模式、source-dir 与 install-dir 分析、架构、数据布局、开发与测试。 ## 许可证 Copyright (C) 2026 Georgios Alexopoulos 该项目基于 GNU Affero General Public License v3.0 (AGPLv3) 授权。 详情请参阅 [LICENSE](LICENSE) 文件。 ## 相关出版物 * Georgios Alexopoulos, Thodoris Sotiropoulos, Georgios Gousios, Zhendong Su, and Dimitris Mitropoulos. [PyXray: Practical Cross-Language Call Graph Construction through Object Layout Analysis](https://grgalex.gr/assets/pdf/pyxray_icse26.pdf). In Proceedings of the 48th International Conference on Software Engineering (ICSE '26), April 2026.
标签:Python, UML, WebSocket, 云安全监控, 依赖分析, 无后门, 漏洞可达性分析, 请求拦截, 调用图, 逆向工具, 静态分析