Skip to content

Commit

Permalink
Merged from trunk
Browse files Browse the repository at this point in the history
  • Loading branch information
lskladnik committed Apr 29, 2009
1 parent ff234d2 commit 7d919bd
Show file tree
Hide file tree
Showing 6 changed files with 293 additions and 80 deletions.
14 changes: 7 additions & 7 deletions impacket/dcerpc/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,6 @@ def __init__(self, dstip, dstport = 135):

def connect(self):
self.__socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
self.__socket.settimeout(300)
self.__socket.connect((self.get_dip(), self.get_dport()))
Expand Down Expand Up @@ -275,7 +274,7 @@ def connect(self):
class SMBTransport(DCERPCTransport):
"Implementation of ncacn_np protocol sequence"

def __init__(self, dstip, dstport = 445, filename = '', username='', password='', lm_hash='', nt_hash=''):
def __init__(self, dstip, dstport = 445, filename = '', username='', password='', lm_hash='', nt_hash='', remote_name=''):
DCERPCTransport.__init__(self, dstip, dstport)
self.__socket = None
self.__smb_server = 0
Expand All @@ -284,11 +283,14 @@ def __init__(self, dstip, dstport = 445, filename = '', username='', password=''
self.__handle = 0
self.__pending_recv = 0
self.set_credentials(username, password, lm_hash, nt_hash)

self.__remote_name = remote_name

def setup_smb_server(self):
if not self.__smb_server:
self.__smb_server = smb.SMB('*SMBSERVER',self.get_dip(), sess_port = self.get_dport())
if self.__remote_name == '':
self.__smb_server = smb.SMB('*SMBSERVER', self.get_dip(), sess_port = self.get_dport())
else:
self.__smb_server = smb.SMB(self.__remote_name, self.get_dip(), sess_port = self.get_dport())

def connect(self):
self.setup_smb_server()
Expand All @@ -297,10 +299,8 @@ def connect(self):
self.__smb_server.login(self._username, self._password)
elif self._nt_hash != '' or self._lm_hash != '':
self.__smb_server.login(self._username, '', '', self._lm_hash, self._nt_hash)
self.__tid = self.__smb_server.tree_connect_andx('\\\\*SMBSERVER\\IPC$')
self.__tid = self.__smb_server.tree_connect_andx('\\\\%s\\IPC$' % self.__smb_server.get_remote_name())
self.__handle = self.__smb_server.nt_create_andx(self.__tid, self.__filename)
# self.__handle = self.__smb_server.open_file_andx(self.__tid, r"\\PIPE\%s" % self.__filename, smb.SMB_O_CREAT, smb.SMB_ACCESS_READ)[0]
# self.__handle = self.__smb_server.open_file(self.__tid, r"\\PIPE\%s" % self.__filename, smb.SMB_O_CREAT, smb.SMB_ACCESS_READ)[0]
self.__socket = self.__smb_server.get_socket()
return 1

Expand Down
5 changes: 3 additions & 2 deletions impacket/dhcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class BootpPacket(structure.Structure):
commonHdr = (
('op','b'),
('htype','b=1'), # 1 = Ether
('hlen','b-chaddr'),
('hlen','b=len(chaddr)'),
('hops','b=0'),
('xid','!L=0'),
('secs','!H=0'),
Expand All @@ -13,7 +13,8 @@ class BootpPacket(structure.Structure):
('yiaddr','!L=0'),
('siaddr','!L=0'),
('giaddr','!L=0'),
('chaddr','16s'),
('_chaddr','16s=chaddr'),
('chaddr','_','_chaddr[:hlen]'),
('sname','64s=""'),
('file','128s=""'))

Expand Down
158 changes: 126 additions & 32 deletions impacket/nmb.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,16 @@
#
# Altered source done by Alberto Solino

import os, sys, socket, string, re, select, errno
import socket, string, re, select, errno
from structure import Structure
from random import randint
from struct import *


CVS_REVISION = '$Revision$'

# Taken from socket module reference
INADDR_ANY = ''
INADDR_ANY = '0.0.0.0'
BROADCAST_ADDR = '<broadcast>'

# Default port for NetBIOS name service
Expand All @@ -66,9 +67,11 @@
TYPE_CLIENT = 0x03
TYPE_SERVER = 0x20
TYPE_DOMAIN_MASTER = 0x1B
TYPE_DOMAIN_CONTROLLER = 0x1C
TYPE_MASTER_BROWSER = 0x1D
TYPE_BROWSER = 0x1E
TYPE_NETDDE = 0x1F
TYPE_STATUS = 0x21

# Opcodes values
OPCODE_QUERY = 0
Expand Down Expand Up @@ -133,7 +136,7 @@

def strerror(errclass, errcode):
if errclass == ERRCLASS_OS:
return 'OS Error', os.strerror(errcode)
return 'OS Error', str(errcode)
elif errclass == ERRCLASS_QUERY:
return 'Query Error', QUERY_ERRORS.get(errcode, 'Unknown error')
elif errclass == ERRCLASS_SESSION:
Expand Down Expand Up @@ -542,14 +545,14 @@ def __querynodestatus(self, nbname, destaddr, type, scope, timeout):
else:
try:
data, _ = self.__sock.recvfrom(65536, 0)
except:
# t_log(1,"No status response")
return
except Exception, e:
raise NetBIOSError, "recvfrom error: %s" % str(e)
res = NetBIOSPacket(data)
if res.get_trn_id() == p.get_trn_id():
if res.get_rcode():
if res.get_rcode() == 0x03:
return None
# I'm just guessing here
raise NetBIOSError, "Cannot get data from server"
else:
raise NetBIOSError, ( 'Negative name query response', ERRCLASS_QUERY, res.get_rcode() )
answ = NBNodeStatusResponse(res.get_answers())
Expand All @@ -559,9 +562,7 @@ def __querynodestatus(self, nbname, destaddr, type, scope, timeout):
if ex[0] != errno.EINTR and ex[0] != errno.EAGAIN:
raise NetBIOSError, ( 'Error occurs while waiting for response', ERRCLASS_OS, ex[0] )
except socket.error, ex:
pass


raise NetBIOSError, 'Connection error: %s' % str(ex)

# Perform first and second level encoding of name as specified in RFC 1001 (Section 4)
def encode_name(name, type, scope):
Expand Down Expand Up @@ -642,58 +643,155 @@ def get_trailer(self):
return self._trailer

class NetBIOSSession:

def __init__(self, myname, remote_name, remote_host, remote_type = TYPE_SERVER, sess_port = NETBIOS_SESSION_PORT, timeout = None, local_type = TYPE_WORKSTATION):
if len(myname) > 15:
self.__myname = string.upper(myname[:15])
else:
self.__myname = string.upper(myname)
self.__local_type = local_type

assert remote_name
if len(remote_name) > 15:
self.__remote_name = string.upper(remote_name[:15])
else:
self.__remote_name = string.upper(remote_name)
self.__remote_type = remote_type

self.__remote_host = remote_host
self.__sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
self.__sock.connect(( remote_host, sess_port ))
except socket.error, ex:
raise ex

self._sock = self._setup_connection((remote_host, sess_port))

if sess_port == NETBIOS_SESSION_PORT:
self.__request_session(remote_type, local_type, timeout)
self._request_session(remote_type, local_type, timeout)

def get_myname(self):
return self.__myname

def get_mytype(self):
return self.__local_type

def get_remote_host(self):
return self.__remote_host

def get_remote_name(self):
return self.__remote_name

def get_remote_type(self):
return self.__remote_type

def close(self):
self.__sock.close()
self._sock.close()

def get_socket(self):
return self._sock

class NetBIOSUDPSessionPacket(Structure):
TYPE_DIRECT_UNIQUE = 16
TYPE_DIRECT_GROUP = 17

FLAGS_MORE_FRAGMENTS = 1
FLAGS_FIRST_FRAGMENT = 2
FLAGS_B_NODE = 0

structure = (
('Type','B=16'), # Direct Unique Datagram
('Flags','B=2'), # FLAGS_FIRST_FRAGMENT
('ID','<H'),
('_SourceIP','>L'),
('SourceIP','"'),
('SourcePort','>H=138'),
('DataLegth','>H-Data'),
('Offset','>H=0'),
('SourceName','z'),
('DestinationName','z'),
('Data',':'),
)

def getData(self):
addr = self['SourceIP'].split('.')
addr = [int(x) for x in addr]
addr = (((addr[0] << 8) + addr[1] << 8) + addr[2] << 8) + addr[3]
self['_SourceIP'] = addr
return Structure.getData(self)

def get_trailer(self):
return self['Data']

class NetBIOSUDPSession(NetBIOSSession):
def _setup_connection(self, peer):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((INADDR_ANY, 138))
self.peer = peer
return sock

def _request_session(self, remote_type, local_type, timeout = None):
pass

def next_id(self):
if hasattr(self, '__dgram_id'):
answer = self.__dgram_id
else:
self.__dgram_id = randint(1,65535)
answer = self.__dgram_id
self.__dgram_id += 1
return answer

def send_packet(self, data):
# Yes... I know...
self._sock.connect(self.peer)

p = NetBIOSUDPSessionPacket()
p['ID'] = self.next_id()
p['SourceIP'] = self._sock.getsockname()[0]
p['SourceName'] = encode_name(self.get_myname(), self.get_mytype(), '')[:-1]
p['DestinationName'] = encode_name(self.get_remote_name(), self.get_remote_type(), '')[:-1]
p['Data'] = data

self._sock.sendto(str(p), self.peer)
self._sock.close()

self._sock = self._setup_connection(self.peer)

def recv_packet(self, timeout = None):
# The next loop is a workaround for a bigger problem:
# When data reaches higher layers, the lower headers are lost,
# and with them, for example, the source IP. Hence, SMB users
# can't know where packets are comming from... we need a better
# solution, right now, we will filter everything except packets
# coming from the remote_host specified in __init__()

while 1:
data, peer = self._sock.recvfrom(8192)
# print "peer: %r self.peer: %r" % (peer, self.peer)
if peer == self.peer: break

return NetBIOSUDPSessionPacket(data)

class NetBIOSTCPSession(NetBIOSSession):
def _setup_connection(self, peer):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(peer)
return sock

def send_packet(self, data):
p = NetBIOSSessionPacket()
p.set_type(NETBIOS_SESSION_MESSAGE)
p.set_trailer(data)
self.__sock.send(p.rawData())
self._sock.send(p.rawData())

def recv_packet(self, timeout = None):
data = self.__read(timeout)
return NetBIOSSessionPacket(data)

def __request_session(self, remote_type, local_type, timeout = None):
def _request_session(self, remote_type, local_type, timeout = None):
p = NetBIOSSessionPacket()
remote_name = encode_name(self.__remote_name, remote_type, '')
myname = encode_name(self.__myname, local_type, '')
remote_name = encode_name(self.get_remote_name(), remote_type, '')
myname = encode_name(self.get_myname(), local_type, '')
p.set_type(NETBIOS_SESSION_REQUEST)
p.set_trailer(remote_name + myname)
self.__sock.send(p.rawData())

self._sock.send(p.rawData())
while 1:
p = self.recv_packet(timeout)
if p.get_type() == NETBIOS_SESSION_NEGATIVE_RESPONSE:
Expand All @@ -709,11 +807,11 @@ def __read(self, timeout = None):
data = ''
while read_len > 0:
try:
ready, _, _ = select.select([self.__sock.fileno() ], [ ], [ ], timeout)
ready, _, _ = select.select([self._sock.fileno() ], [ ], [ ], timeout)
if not ready:
raise NetBIOSTimeout

received = self.__sock.recv(read_len)
received = self._sock.recv(read_len)
if len(received)==0:
raise NetBIOSError, ( 'Error while reading from remote', ERRCLASS_OS, None)

Expand All @@ -731,11 +829,11 @@ def __read(self, timeout = None):
data2=''
while read_len > 0:
try:
ready, _, _ = select.select([ self.__sock.fileno() ], [ ], [ ], timeout)
ready, _, _ = select.select([ self._sock.fileno() ], [ ], [ ], timeout)
if not ready:
raise NetBIOSTimeout

received = self.__sock.recv(read_len)
received = self._sock.recv(read_len)
if len(received)==0:
raise NetBIOSError, ( 'Error while reading from remote', ERRCLASS_OS, None)

Expand All @@ -747,10 +845,6 @@ def __read(self, timeout = None):

return data + data2

def get_socket(self):
return self.__sock


ERRCLASS_QUERY = 0x00
ERRCLASS_SESSION = 0xf0
ERRCLASS_OS = 0xff
Expand Down
Loading

0 comments on commit 7d919bd

Please sign in to comment.