/usr/share/doc/python-impacket/examples/spoolss.py is in python-impacket 0.9.10-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | #!/usr/bin/python
# Copyright (c) 2003-2012 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: spoolss.py 600 2012-07-11 19:39:46Z bethus@gmail.com $
#
# SPOOLSS example for some functions implemented
#
# Author:
# Alberto Solino (bethus@gmail.com)
#
# Reference for:
# DCE/RPC for SPOOLSS
import socket
import string
import sys
import types
from impacket import uuid, ntlm, version
from impacket.dcerpc import dcerpc_v4, dcerpc, transport, printer
from struct import unpack
import argparse
class SPOOLSS:
KNOWN_PROTOCOLS = {
'139/SMB': (r'ncacn_np:%s[\pipe\spoolss]', 139),
'445/SMB': (r'ncacn_np:%s[\pipe\spoolss]', 445),
}
def __init__(self, username, password, domain, hashes, protocols):
if not protocols:
protocols = SPOOLSS.KNOWN_PROTOCOLS.keys()
self.__username = username
self.__password = password
self.__protocols = [protocols]
self.__domain = domain
self.__lmhash = ''
self.__nthash = ''
if hashes is not None:
self.__lmhash, self.__nthash = hashes.split(':')
def play(self, addr):
# Try all requested protocols until one works.
entries = []
for protocol in self.__protocols:
protodef = SPOOLSS.KNOWN_PROTOCOLS[protocol]
port = protodef[1]
print "Trying protocol %s..." % protocol
stringbinding = protodef[0] % addr
rpctransport = transport.DCERPCTransportFactory(stringbinding)
rpctransport.set_dport(port)
if hasattr(rpctransport, 'set_credentials'):
# This method exists only for selected protocol sequences.
rpctransport.set_credentials(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash)
try:
entries = self.doStuff(rpctransport)
except Exception, e:
print 'Protocol failed: %s' % e
else:
# Got a response. No need for further iterations.
break
def doStuff(self, rpctransport):
dce = dcerpc.DCERPC_v5(rpctransport)
dce.connect()
dce.set_auth_level(ntlm.NTLM_AUTH_PKT_PRIVACY)
#dce.set_max_fragment_size(16)
dce.bind(printer.MSRPC_UUID_SPOOLSS)
rpcspool = printer.PrintSpooler(dce)
resp = rpcspool.enumPrinters('\x00',0x2, level=1)
data = resp['PrinterEnum']
index = 0
for i in range(resp['cReturned']):
# skip the flags
flags = unpack('<L',data[index:index+4])[0]
index += 4
description = unpack('<L',data[index:index+4])[0]
index += 4
name = unpack('<L',data[index:index+4])[0]
index += 4
comment = unpack('<L',data[index:index+4])[0]
index += 4
# Yes.. still don't know why.. offsets are 0x10*i away from the actual data
description = data[(description+16*i):].split('\x00\x00')[0]
name = data[(name+16*i):].split('\x00\x00')[0]
comment = data[(comment+16*i):].split('\x00\x00')[0]
print "flags: 0x%x\nname:[%s]\ndescription:[%s]\ncomment:[%s]\n" %(flags,name,description,comment)
#resp = rpcspool.enumPorts()
#resp.dump()
dce.disconnect()
# Process command-line arguments.
if __name__ == '__main__':
print version.BANNER
parser = argparse.ArgumentParser()
parser.add_argument('target', action='store', help='[domain/][username[:password]@]<address>')
parser.add_argument('protocol', choices=SPOOLSS.KNOWN_PROTOCOLS.keys(), nargs='?', default='445/SMB', help='transport protocol (default 445/SMB)')
group = parser.add_argument_group('authentication')
group.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH')
if len(sys.argv)==1:
parser.print_help()
sys.exit(1)
options = parser.parse_args()
import re
domain, username, password, address = re.compile('(?:(?:([^/@:]*)/)?([^@:]*)(?::([^@]*))?@)?(.*)').match(options.target).groups('')
if domain is None:
domain = ''
dumper = SPOOLSS(username, password, domain, options.hashes, options.protocol)
dumper.play(address)
|