你的打印机安全吗?在别人发现之前检查一下……
PRET 是一款用于打印机安全测试的新工具,基于鲁尔大学波鸿分校的一篇硕士论文开发。它通过网络或 USB 连接到设备,并利用指定打印机语言的功能。目前支持 PostScript、PJL 和 PCL,大多数激光打印机都支持这些语言。这可以实现诸如捕获或操纵打印作业、访问打印机文件系统和内存,甚至对设备造成物理损坏等酷炫功能。所有攻击方法均在 Hacking Printers Wiki 中有详细记录。
PRET 的主要理念是简化最终用户与打印机之间的通信。因此,在输入类 UNIX 命令后,PRET 会将其转换为 PostScript、PJL 或 PCL,发送到打印机,评估结果,再转换回用户友好的格式。PRET 提供了大量用于打印机攻击和模糊测试的命令。

PRET 仅需要 Python2 解释器。不过,要获得彩色输出和 SNMP 支持,需要安装第三方模块:
# pip install colorama pysnmp
如果在 Windows 控制台上运行且 Unicode 字符显示不正确,请安装 win_unicode_console 模块:
# pip install win_unicode_console
对于实验性的‘免驱动’打印(参见 print 命令),需要安装 ImageMagick 和 GhostScript:
# apt-get install imagemagick ghostscript
usage: pret.py [-h] [-s] [-q] [-d] [-i file] [-o file] target {ps,pjl,pcl}
positional arguments:
target 打印机设备或主机名
{ps,pjl,pcl} 要滥用的打印语言
optional arguments:
-h, --help 显示此帮助消息并退出
-s, --safe 验证语言是否受支持
-q, --quiet 抑制警告和闲聊
-d, --debug 进入调试模式(显示流量)
-i file, --load file 从文件加载并运行命令
-o file, --log file 将发送到目标的原始数据记录到文件
$ ./pret.py laserjet.lan ps
$ ./pret.py /dev/usb/lp0 pjl
PRET 需要有效的目标和打印机语言作为参数。目标可以是网络打印机的 IP 地址/主机名(端口 9100/tcp 打开),也可以是本地 USB 打印机的设备(如 /dev/usb/lp0)。要使用 SNMP 广播快速发现子网中的所有网络打印机,只需不带参数运行 PRET:
./pret.py
未提供目标,正在发现本地打印机
地址 设备 运行时间 状态
───────────────────────────────────────────────────────────────────────────────
192.168.1.5 hp LaserJet 4250 10:21:49 就绪
192.168.1.11 HP LaserJet M3027 MFP 13 天 卡纸
192.168.1.27 Lexmark X792 153 天 就绪
192.168.1.28 Brother MFC-7860DW 16:31:17 睡眠模式
要滥用的打印机语言必须是 ps、pjl 或 pcl 之一。并非每台打印机都支持所有语言,因此如果收不到任何反馈,您可能需要切换语言。每种打印机语言对应不同的 PRET 命令集,并具有不同的可利用能力。
--safe 尝试通过 IPP、HTTP 和 SNMP 检查选定的打印语言(PS/PJL/PCL)在连接前是否实际受设备支持。对于非网络打印机(USB、并口电缆),此测试将失败。
--quiet 抑制打印机型号确定、介绍消息和其他一些闲聊。
--debug 显示实际发送到设备的数据流和收到的反馈。请注意,会过滤掉头部数据和其他开销。要查看全部流量,请使用 wireshark。也可以在 PRET 会话中使用 debug 命令打开/关闭调试。
--load 文件名 从文本文件读取并执行 PRET 命令。这对自动化很有用。稍后也可以在 PRET 会话中使用 load 命令调用命令文件。
--log 文件名 将发送到打印机的原始数据流副本写入文件。这对于构建恶意打印作业文件很有用,这些文件可以部署在无法直接访问的另一台打印机上,例如通过 USB 驱动器打印。
连接到打印机设备后,您将看到 PRET shell 并可以执行各种命令:
$ ./pret.py laserjet.lan pjl
________________
_/_______________/|
/___________/___//|| PRET | 打印机利用工具包 v0.25
|=== |----| || 作者:Jens Mueller <[email protected]>
| | ô| ||
|___________| ô| ||
| ||/.´---.|| | || 「 让你的设备比卡纸更有趣 」
|-||/_____\||-. | |´
|_||=L==H==||_|__|/
(ASCII 艺术 by
Jan Foerster)
已连接到 laserjet.lan
设备: hp LaserJet 4250
欢迎来到 pret shell。输入 help 或 ? 列出命令。
laserjet.lan:/> help
可用命令(输入 help <主题>):
=======================================
append debug edit free id ls open restart timeout
cat delete env fuzz info mirror printenv selftest touch
cd df exit get load mkdir put set traversal
chvol disable find help lock nvram pwd site unlock
close display format hold loop offline reset status version
laserjet.lan:/> ls ../../
- 834 .profile
d - bin
d - dev
d - etc
d - hp
d - hpmnt
- 1276 init
d - lib
d - pipe
d - tmp
laserjet.lan:/> exit
以下是通用 PRET 命令列表:
help 列出可用命令或使用 'help cmd' 获取详细帮助。
debug 进入调试模式。使用 'hex' 进行十六进制转储: debug [hex]
load 从文件运行命令: load cmd.txt
loop 为多个参数运行命令: loop <cmd> <arg1> <arg2> …
open 连接到远程设备: open <target>
close 断开与设备的连接。
timeout 设置连接超时时间: timeout <seconds>
discover 通过 SNMP 发现本地打印机设备。
print 打印图像文件或原始文本: print <file>|"text"
site 在打印机上执行自定义命令: site <command>
exit 退出解释器。
基于 PS/PJL/PCL 特定实现的通用文件系统操作:
┌───────────┬─────┬─────┬─────┬────────────────────────────────────────┐
│ 命令 │ PS │ PJL │ PCL │ 描述 │
├───────────┼─────┼─────┼─────┼────────────────────────────────────────┤
│ ls │ ✓ │ ✓ │ ✓ │ 列出远程目录内容。 │
│ get │ ✓ │ ✓ │ ✓ │ 接收文件:get <file> │
│ put │ ✓ │ ✓ │ ✓ │ 发送文件:put <local file> │
│ append │ ✓ │ ✓ │ │ 追加到文件:append <file> <str> │
│ delete │ ✓ │ ✓ │ ✓ │ 删除远程文件:delete <file> │
│ rename │ ✓ │ │ │ 重命名远程文件:rename <old> <new> │
│ find │ ✓ │ ✓ │ │ 递归列出目录内容。 │
│ mirror │ ✓ │ ✓ │ │ 将远程文件系统镜像到本地目录。 │
│ cat │ ✓ │ ✓ │ ✓ │ 将远程文件输出到标准输出。 │
│ edit │ ✓ │ ✓ │ ✓ │ 使用 vim 编辑远程文件。 │
│ touch │ ✓ │ ✓ │ │ 更新文件时间戳:touch <file> │
│ mkdir │ ✓ │ ✓ │ │ 创建远程目录:mkdir <path> │
├───────────┼─────┼─────┼─────┼────────────────────────────────────────┤
│ cd │ ✓ │ ✓ │ │ 更改远程工作目录。 │
│ pwd │ ✓ │ ✓ │ │ 显示设备上的工作目录。 │
│ chvol │ ✓ │ ✓ │ │ 更改远程卷:chvol <volume> │
│ traversal │ ✓ │ ✓ │ │ 设置路径遍历:traversal <path> │
├───────────┼─────┼─────┼─────┼────────────────────────────────────────┤
│ format │ ✓ │ ✓ │ │ 初始化打印机的文件系统。 │
│ fuzz │ ✓ │ ✓ │ │ 文件系统模糊测试:fuzz <category> │
├─ ─ ─ ─ ─ ─┴─ ─ ─┴─ ─ ─┴─ ─ ─┴─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤
│ path - 使用路径遍历策略探索文件系统结构。 │
│ write - 先 put/append 文件,然后检查其是否存在。 │
│ blind - 只读测试现有文件,如 /etc/passwd。 │
├───────────┬─────┬─────┬─────┬────────────────────────────────────────┤
│ df │ ✓ │ ✓ │ │ 显示卷信息。 │
│ free │ ✓ │ ✓ │ ✓ │ 显示可用内存。 │
└───────────┴─────┴─────┴─────┴────────────────────────────────────────┘
id 显示设备信息。
version 显示 PostScript 解释器版本。
devices 显示可用的 I/O 设备。
uptime 显示系统运行时间(可能是随机的)。
date 显示打印机的系统日期和时间。
pagecount 显示打印机的页计数器。
lock 设置 startjob 和系统参数密码。
unlock 取消设置 startjob 和系统参数密码。
restart 重启 PostScript 解释器。
reset 将 PostScript 设置重置为出厂默认值。
disable 禁用打印功能。
destroy 对打印机的 NVRAM 造成物理损坏。
hang 执行 PostScript 无限循环。
overlay 将所有硬拷贝叠加 eps 文件:overlay <file.eps>
cross 在所有硬拷贝上添加打印机涂鸦:cross <font> <text>
replace 替换要打印文档中的字符串:replace <old> <new>
capture 捕获后续要打印在此设备上的作业。
hold 启用作业保留。
set 将键设置为最顶层字典中的值:set <key=value>
known 列出支持的 PostScript 运算符:known <operator>
search 按键搜索所有字典:search <key>
dicts 返回字典列表及其权限。
resource 列出或转储 PostScript 资源:resource <category> [dump]
dump 转储字典:dump <dict>
字典:- systemdict - statusdict - userdict
- globaldict - serverdict - errordict
- internaldict - currentsystemparams
- currentuserparams - currentpagedevice
config 更改打印机设置:config <setting>
duplex - 设置双面打印。
copies # - 设置副本数。
economode - 设置经济模式。
negative - 设置负片打印。
mirror - 设置镜像反转。
并非每台打印机都支持所有命令。特别是 Brother 和 Kyocera 设备使用自己的 PostScript 克隆版本——Br-Script 和 KPDL——而不是授权原始的“Adobe PostScript”。这些 PostScript 语言的变体可能不是 100% 兼容的,尤其是在安全敏感功能(如捕获打印作业)方面。大多数打印机支持访问文件系统,但通常仅限于某个隔离的目录。
id 显示设备信息。
status 启用状态消息。
version 显示固件版本或序列号(来自 'info config')。
pagecount 操作打印机的页计数器:pagecount <number>
printenv 显示打印机环境变量:printenv <VAR>
env 显示环境变量('info variables' 的别名)。
set 设置打印机环境变量:set <VAR=VALUE>
display 设置打印机的显示屏消息:display <message>
offline 使打印机离线并显示消息:offline <message>
restart 重启打印机。
reset 重置为出厂默认值。
selftest 执行各种打印机自检。
disable 禁用打印功能。
destroy 对打印机的 NVRAM 造成物理损坏。
flood 淹没用户输入,可能揭示缓冲区溢出。
lock 锁定控制面板设置和磁盘写入访问。
unlock 解锁控制面板设置和磁盘写入访问。
hold 启用作业保留。
nvram NVRAM 操作:nvram <operation>
nvram dump [all] - 转储(全部)NVRAM 到本地文件。
nvram read addr - 从地址读取单个字节。
nvram write addr value - 向地址写入单个字节。
info 显示信息:info <category>
info config - 提供配置信息。
info filesys - 返回 PJL 文件系统信息。
info id - 提供打印机型号。
info memory - 标识可用内存量。
info pagecount - 返回已打印页数。
info status - 提供当前打印机状态。
info ustatus - 列出非请求状态变量。
info variables - 列出打印机的环境变量。
某些命令仅 HP 打印机支持,因为其他供应商只实现了 PJL 标准的子集。这对于基于 PML 的命令(如 restart 或 reset)尤其如此。通过 hold 命令启用长期作业保留似乎仅在某些 Epson 设备上可行。通过 nvram 命令访问 NVRAM 是 Brother 打印机的专有功能。有限的文件系统访问支持各种 HP、OKI、Konica、Xerox、Epson 和 Ricoh 设备。
selftest 执行打印机自检。
info 显示信息:info <category>
info fonts - 显示已安装字体。
info macros - 显示已安装宏。
info patterns - 显示用户定义的模式。
info symbols - 显示符号集。
info extended - 显示扩展字体。
PCL 是一种非常有限制的页面描述语言,无法访问文件系统。因此,get/put/ls 命令使用基于 PCL 宏的虚拟文件系统,主要出于黑客乐趣而实现。这一概念验证表明,即使仅支持像 PCL 这样最小化语言的设备,也可以用于存储任意文件(如版权侵权材料)。尽管此类文件共享服务本身并非安全漏洞,但根据公司政策,它可能被视为“服务滥用”。
pret.py - 可执行主程序capabilities.py - 检查打印机语言支持的例程discovery.py - 使用 SNMP 广播列出打印机的例程printer.py - 描述打印设备的通用代码postscript.py - PS 特定代码(继承自 printer 类)pjl.py - PJL 特定代码(继承自 printer 类)pcl.py - PCL 特定代码(继承自 printer 类)helper.py - 输出、日志、套接字等辅助函数codebook.py - PJL 状态/错误代码的静态表fuzzer.py - 文件系统模糊测试的常量mibs/* - 打印机特定的 SNMP MIBdb/* - 支持型号的数据库lpd/* - LPD 模糊测试脚本鉴于打印语言(如 PostScript 和 PJL)的功能和各种专有扩展,对打印机进行渗透测试并非易事。PRET 可以帮助验证语言中的已知问题。一旦您熟悉了该工具,您可能希望执行系统的打印机安全分析。一个很好的起点是 打印机安全测试速查表。
祝黑客愉快!