# Copyright (c) 2003-2006 CORE Security Technologies
#
# This software is provided under under a slightly modified version
# of the Apache Software License. See the accompanying LICENSE file
# for more information.
#
# $Id: printer.py,v 1.2 2006/05/23 21:19:26 gera Exp $
#
from impacket.structure import Structure
def zeroize(s):
return '\x00'.join(str(s)) + '\x00'
class SpoolSS_DevModeContainer(Structure):
alignment = 4
structure = (
('cbBuf','<L-DevMode'),
('pDevMode','<L&DevMode'),
('DevMode',':'),
)
class SpoolSS_OpenPrinter(Structure):
alignment = 4
opnum = 1
structure = (
('pPrinterName','<L&PrinterName'),
('PrinterName','w'),
# ('pDataType','<L&DataType'),
('pDevMode','<L&DevMode'),
('DevMode',':',SpoolSS_DevModeContainer),
('AccessRequired','<L'),
('DataType','w'),
)
class SpoolSS_PrinterInfo1(Structure):
alignment = 4
structure = (
('level','<L=1'),
('_level','<L=1'),
('pPrinterInfo1','<L=0x08081200'),
('flags','<L'),
('pDescription','<L&Description'),
('pName','<L&Name'),
('pComment','<L&Comment'),
('Description','w'),
('Name','w'),
('Comment','w'),
)
class SpoolSS_PrinterInfo2(Structure):
alignment = 4
structure = (
('level','<L=2'),
('_level','<L=2'),
('pPrinterInfo2','<L=0x08081200'),
('pServerName', '<L&ServerName'),
('pPrinterName', '<L&PrinterName'),
('pShareName', '<L&ShareName'),
('pPortName', '<L&PortName'),
('pDriverName', '<L&DriverName'),
('pComment', '<L&Comment'),
('pLocation', '<L&Location'),
('pDevMode', '<L&DevMode'),
('pSepFile', '<L&SepFile'),
('pPrintProcessor', '<L&PrintProcessor'),
('pDatatype', '<L&Datatype'),
('pParameters', '<L&Parameters'),
('pSecurityDescriptor', '<L&SecurityDescriptor'),
('Attributes', '<L=0'),
('Priority', '<L=0'),
('DefaultPriority', '<L=0'),
('StartTime', '<L=0'),
('UntilTime', '<L=0'),
('Status', '<L=0'),
('cjobs', '<L=0'),
('AveragePPM', '<L=0'),
('ServerName', 'w'),
('PrinterName', 'w'),
('ShareName', 'w'),
('PortName', 'w'),
('DriverName', 'w'),
('Comment', 'w'),
('Location', 'w'),
('DevMode', ':'),
('SepFile', 'w'),
('PrintProcessor', 'w'),
('Datatype', 'w'),
('Parameters', 'w'),
('SecurityDescriptor', ':'),
)
class SpoolSS_AddPrinter(Structure):
# opnum from http://bob.marlboro.edu/~msie/2003/it1/tools/ethereal/ethereal-0.9.7/packet-dcerpc-spoolss.h
opnum = 5
alignment = 4
structure = (
('pName','<L&Name'),
('Name','w'),
('info',':',SpoolSS_PrinterInfo2),
('blob',':'),
)
class SpoolSS_DeletePrinter(Structure):
opnum = 6
alignment = 4
structure = (
('handle','<L'),
)
class SpoolSS_AddPrinterEx(Structure):
opnum = 0x46
alignment = 4
structure = (
('pName','<L=0x12345678'),
('Name','w'),
('info',':',SpoolSS_PrinterInfo2),
('blob',':'),
)
class SpoolSS_EnumPrinters(Structure):
opnum = 0
alignment = 4
structure = (
('flags','<L'),
('pName','<L&Name'),
('Name','w'),
('level','<L'),
('pPrinterEnum','<L&PrinterEnum'),
('_cbBuf','<L-PrinterEnum'),
('PrinterEnum',':'),
('cbBuf','<L-PrinterEnum'),
)
class SpoolSS_EnumPrinters_answer(Structure):
alignment = 4
structure = (
('pPrinterEnum','<L&PrinterEnum'),
('cbPrinterEnum','<L-PrinterEnum'),
('PrinterEnum',':'),
('cbNeeded','<L'),
('cReturned','<L'),
)
class SpoolSS_EnumPorts(Structure):
# fields order (in the wire) from:
# http://samba.vernstok.nl/docs/htmldocs/manpages-4/pidl.1.html
opnum = 0x23
alignment = 4
structure = (
('pName','<L&Name'),
('Name','w'),
('level','<L'),
('pPort','<L&Port'),
('_cbBuf','<L-Port'),
('Port',':'),
('cbBuf','<L-Port'),
)
class SpoolSS_EnumPorts_answer(Structure):
alignment = 4
structure = (
('pPort','<L&Port'),
('cbPort','<L-Port'),
('Port',':'),
('cbNeeded','<L'),
('cReturned','<L'),
)
class SpoolSS_AddPort(Structure):
opnum = 37
alignment = 4
structure = (
('pName','<L&Name'),
('Name','w'),
('hWnd','<L'),
('pMonitorName','<L&MonitorName'),
('MonitorName','w'),
)
class SpoolSS_PortInfo1(Structure):
alignment = 4
structure = (
('level','<L=1'),
('_level','<L=1'),
('pPortInfo1','<L=0x08081200'),
('pName','<L&Name'),
('Name','w'),
)
class SpoolSS_AddPortEx(Structure):
opnum = 61
alignment = 4
structure = (
('pName','<L&Name'),
('Name','w'),
('Port',':',SpoolSS_PortInfo1),
('cbMonitorData','<L-MonitorData'),
('MonitorData',':'),
# ('pMonitorName','<L&MonitorName'),
('MonitorName','w'),
)
class SpoolSS_AddPrintProcessor(Structure):
opnum = 14
alignment = 4
structure = (
('pName','<L&Name'),
('Name','w'),
('pEnvironment','<L&Environment'),
('pPathName','<L&PathName'),
('pPrintProcessorName','<L&PrintProcessorName'),
('Environment','w'),
('PathName','w'),
('PrintProcessorName','w'),
)
class SpoolSS_EnumMonitors(Structure):
# fields order (in the wire) from:
# http://samba.vernstok.nl/docs/htmldocs/manpages-4/pidl.1.html
opnum = 0x24
alignment = 4
structure = (
('pName','<L&Name'),
('Name','w'),
('level','<L'),
('pMonitor','<L&Monitor'),
('_cbBuf','<L-Monitor'),
('Monitor',':'),
('cbBuf','<L-Monitor'),
)
class SpoolSS_AddMonitor(Structure):
# fields order (in the wire) from:
# http://samba.vernstok.nl/docs/htmldocs/manpages-4/pidl.1.html
opnum = 0x2e
alignment = 4
structure = (
('pHostName','<L&HostName'),
('HostName','w'),
('level','<L'),
('level','<L'),
('pLevel','<L&level'),
('pName','<L&Name'),
('pEnvironment','<L&Environment'),
('pDLLName','<L&DLLName'),
('Name','w'),
('Environment','w'),
('DLLName','w'),
)
class SpoolSS_EnumMonitors_answer(Structure):
alignment = 4
structure = (
('pMonitor','<L&Monitor'),
('cbMonitor','<L-Monitor'),
('Monitor',':'),
('cbNeeded','<L'),
('cReturned','<L'),
)
PRINTER_ENUM_DEFAULT = 0x00000001
PRINTER_ENUM_LOCAL = 0x00000002
PRINTER_ENUM_CONNECTIONS = 0x00000004
PRINTER_ENUM_FAVORITE = 0x00000004
PRINTER_ENUM_NAME = 0x00000008
PRINTER_ENUM_REMOTE = 0x00000010
PRINTER_ENUM_SHARED = 0x00000020
PRINTER_ENUM_NETWORK = 0x00000040
class PrintSpooler:
def __init__(self, dce):
self.dce = dce
def doRequest(self, request, noAnswer = 0, checkReturn = 1):
self.dce.call(request.opnum, request)
if noAnswer:
return
else:
answer = self.dce.recv()
if checkReturn and answer[-4:] != '\x00\x00\x00\x00':
raise Exception, 'DCE-RPC call returned an error.'
return answer
def enumPrinters(self, name, flags = 0, level = 1):
# first get the number of bytes needed
enumPrinters = SpoolSS_EnumPrinters()
enumPrinters['level'] = level
enumPrinters['flags'] = flags
enumPrinters['Name'] = name
enumPrinters['PrinterEnum'] = ''
ans = SpoolSS_EnumPrinters_answer(self.doRequest(enumPrinters, checkReturn = 0))
self.logDebug("enumPrinters() needing %d bytes" % ans['cbNeeded'])
if ans['cbNeeded'] > 4096:
raise Exception, "Buffer is too big."
# do the real request
enumPrinters = SpoolSS_EnumPrinters()
enumPrinters['level'] = level
enumPrinters['flags'] = flags
enumPrinters['Name'] = name
enumPrinters['PrinterEnum'] = '\x00' * ans['cbNeeded']
ans = SpoolSS_EnumPrinters_answer(self.doRequest(enumPrinters, checkReturn = 0))
# ans.dump('answer')
def openPrinter(self, printerName, dataType, devMode, accessRequired):
openPrinter = SpoolSS_OpenPrinter()
if printerName: openPrinter['PrinterName'] = zeroize(printerName+'\x00')
if dataType: openPrinter['DataType'] = zeroize(dataType+'\x00')
if devMode:
devModeC = SpoolSS_DevModeContainer()
# devModeC['DevMode'] = devModeC
devModeC['cbBuf'] = 0
devModeC['pDevMode'] = 0
devModeC['DevMode'] = ''
openPrinter['DevMode'] = '\x00\x00\x00\x00'
openPrinter['pDevMode'] = 0
openPrinter['AccessRequired'] = accessRequired
return self.doRequest(openPrinter, checkReturn = 0)
def enumPorts(self, level = 1, noAnswer = 0):
# this one calls ntdll_RtlAcquirePebLock and ntdll_RtlReleasePebLock
# first get the number of bytes needed
enumPorts = SpoolSS_EnumPorts()
enumPorts['level'] = level
enumPorts['Port'] = ''
if noAnswer:
self.doRequest(enumPorts, noAnswer = 1)
else:
ans = SpoolSS_EnumPorts_answer(self.doRequest(enumPorts, checkReturn = 0))
# do the real request
enumPorts = SpoolSS_EnumPorts()
# enumPorts['Name'] = '\\\x00\\\x00hola\x00\x00'
enumPorts['level'] = level
enumPorts['Port'] = '\x00'*ans['cbNeeded']
ans = SpoolSS_EnumPorts_answer(self.doRequest(enumPorts, checkReturn = 0))
# ans.dump('answer')
def enumMonitors(self, level = 1):
# first get the number of bytes needed
enumMonitors = SpoolSS_EnumMonitors()
enumMonitors['level'] = level
enumMonitors['Monitor'] = ''
ans = SpoolSS_EnumMonitors_answer(self.doRequest(enumMonitors, checkReturn = 0))
# do the real request
enumMonitors = SpoolSS_EnumMonitors()
# enumMonitors['Name'] = '\\\x00\\\x00hola\x00\x00'
enumMonitors['level'] = level
enumMonitors['Monitor'] = '\x00'*ans['cbNeeded']
ans = SpoolSS_EnumMonitors_answer(self.doRequest(enumMonitors, checkReturn = 0))
# ans.dump('answer')
def addMonitor(self, name, monitorName, environment, dllName):
addMonitor = SpoolSS_AddMonitor()
addMonitor['level'] = 2
addMonitor['HostName'] = zeroize(name)
addMonitor['Name'] = zeroize(monitorName)
addMonitor['Environment'] = zeroize(environment)
addMonitor['DLLName'] = zeroize(dllName)
ans = self.doRequest(addMonitor, checkReturn = 0)
print "%r" % ans
def addPort(self):
addPort = SpoolSS_AddPort()
addPort['Name'] = zeroize('\\192.168.22.90\x00')
addPort['hWnd'] = 0
addPort['MonitorName'] = zeroize('LanMan Print Services Port\x00')
return self.doRequest(addPort)
def addPortEx(self):
port = SpoolSS_PortInfo1()
port['Name'] = zeroize('Port Name\x00')
addPortEx = SpoolSS_AddPortEx()
addPortEx['Name'] = zeroize('\\\\192.168.22.90\x00')
addPortEx['Port'] = port
addPortEx['cbMonitorData'] = 0
addPortEx['MonitorData'] = '\x00'*4
addPortEx['MonitorName'] = zeroize('Monitor Name\x00')
return self.doRequest(addPortEx)
def addPrintProcessor(self):
addPrintProcessor = SpoolSS_AddPrintProcessor()
# addPrintProcessor['Name'] = zeroize('\\\\192.168.22.90\x00')
addPrintProcessor['Environment'] = zeroize('Windows NT x86\x00')
addPrintProcessor['PathName'] = zeroize('C:\\hola\\manola\x00')
addPrintProcessor['PrintProcessorName'] = zeroize('chaucha\x00')
return self.doRequest(addPrintProcessor)
def deletePrinter(self, handle):
deletePrinter = SpoolSS_DeletePrinter()
deletePrinter['handle'] = handle
self.doRequest(deletePrinter)
def addPrinter(self, serverName, name, level = 1, flags = 0, comment = None, description = None):
addPrinter = SpoolSS_AddPrinter()
# length(Name)+length(PrinterName)+2+2 must be the size of the chunk following the overflown
if serverName is not None:
addPrinter['Name'] = serverName
if level == 1:
addPrinter['info'] = SpoolSS_PrinterInfo1()
addPrinter['info']['Name'] = name
addPrinter['info']['Description'] = description
addPrinter['info']['flags'] = flags
elif level == 2:
addPrinter['info'] = SpoolSS_PrinterInfo2()
addPrinter['info']['PrinterName'] = name
else:
raise Exception, "Unknown PRINTER_INFO level"
addPrinter['info']['Comment'] = comment
addPrinter['blob'] = ( # to be improved
"\x00\x00\x00\x00"*4
)
# addPrinter.dump('addPrinter')
# addPrinter['info'].dump('info')
return self.doRequest(addPrinter, checkReturn = 0)
def addPrinterEx(self, serverName, name, comment = None):
addPrinterEx = SpoolSS_AddPrinterEx()
# length(Name)+length(PrinterName)+2+2 must be the size of the chunk following the overflow in mem
addPrinterEx['Name'] = serverName
addPrinterEx['info'] = SpoolSS_PrinterInfo2()
addPrinterEx['info']['PrinterName'] = name
addPrinterEx['info']['Comment'] = comment
addPrinterEx['blob'] = ( # to be improved
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x01\x00\x00\x00\x01\x00\x00\x00"
"\xf8\xf3\x30\x00"
"\x1c\x00\x00\x00"
"\xf0\x62\xc9\x00"
"\xe0\xf1\x30\x00"
"\x93\x08\x00\x00"
"\x03\x00\x00\x00"
"\x00\x00\x00\x00"
"\x00\x00\x00\x00"
"\x08\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00"
# \\ERATO
"\x5c\x00\x5c\x00\x45\x00\x52\x00\x41\x00\x54\x00\x4f\x00\x00\x00"
"\x0e\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00"
# Administrator
"\x41\x00\x64\x00\x6d\x00\x69\x00\x6e\x00\x69\x00\x73\x00\x74\x00"
"\x72\x00\x61\x00\x74\x00\x6f\x00\x72\x00\x00\x00"
)
return self.doRequest(addPrinterEx)
syntax highlighted by Code2HTML, v. 0.9.1