Open GoogleCodeExporter opened 9 years ago
Hey Arthur:
1) I would do the communication against port 445, not 139. The likelihood of
failing with 139 is higher since you need to establish a NetBIOS connection
first, and for that you need the remote NetBIOS name. '*SMBSERVER' used to work
on older Windows, but that alias doesn't exist anymore in newer versions. The
library itself would try to gather the target NetBIOS name, but that's not
always possible. So.. try 445 (which is the default behaviour).
2) What Impacket version are you using?
3) Did you try doing the same procedure outside your lib, using the
smbclient.py script?
4) A wireshark export would be very useful if the problem persists.
cheers
beto
Original comment by bet...@gmail.com
on 29 Jul 2014 at 6:54
Thanks Beto,
I checked what you suggested with the latest version (0.9.12) of the lib.
The smbclient.py works fine. I also changed the method to use 445:
smbconn = impacket.smbconnection.SMBConnection(remoteName="192...",
remoteHost="192...", sess_port=445)
The issue is still there. But if I add these lines everything works fine
too:
rpctransport = transport.SMBTransport(smbconn.getServerName(),
smbconn.getRemoteHost(), filename = r'\srvsvc', smb_connection = smbconn)
dce = rpctransport.get_dce_rpc()
dce.connect()
Do I really need to keep this connection?
Thanks again,
Arthur
Original comment by aamshu...@rivermeadow.com
on 29 Jul 2014 at 8:17
Hey Arthur:
1) Okey, so smbclient.py is working. That's good to know :)
2) The lines you're adding there are going to use your existing connection to
connect to the '\srvsvc' pipe, which has nothing to do with uploading a file to
a target server.
Don't you wanna share a little bit more of your code?.. 'cause I'm kind of
confused now. If you say it worked with smbclient.py the problem might be in
your code.. I can try to help you
cheers
beto
Original comment by bet...@gmail.com
on 29 Jul 2014 at 8:32
I stripped the code a little bit ...
# built-in imports
import contextlib
import ntpath
import os
import re
import time
import socket
import pipes
# 3rd party
import sh
import impacket.smbconnection
from impacket.smb3 import SessionError
from phore.util import retryable, trace
@register(SourceConnection, 'windows')
class WindowsSourceConnection(SourceConnection):
DEFAULT_SMB_PORT = 445
@contextlib.contextmanager
def smbconnect(self, smbport=445):
"""
@type smbport: int
@return: context manager
"""
smbconn = impacket.smbconnection.SMBConnection(remoteName=self.host,
# attempt to get hostname
remoteHost=self.host,
# ip address
sess_port=smbport)
self.log.debug("SMB connection to {} port {}".format(self.host,
smbport))
smbconn.login(self.creds.username, self.creds.password.plaintext)
# dialect = smbconn.getDialect()
# self.log.debug(dialect)
#
# if smbconn.isGuestSession() > 0:
# self.log.debug("GUEST Session Granted")
# else:
# self.log.debug("USER Session Granted")
# ADDING THESE LINES MAKES THE CODE WORK
from impacket import smb, version, smb3, nt_errors
from impacket.dcerpc.v5 import samr, transport, srvs
from impacket.dcerpc.v5.dtypes import NULL
from impacket.smbconnection import *
rpctransport = transport.SMBTransport(smbconn.getServerName(),
smbconn.getRemoteHost(), filename = r'\srvsvc', smb_connection = smbconn)
dce = rpctransport.get_dce_rpc()
dce.connect()
yield smbconn
smbconn.logoff()
# TODO: there might be some windows machines that have SMB exposed on a
# different port. At the moment, winexe (used elsewhere) is always
# using port 139, so there's not much we can do about this. But here's
# where configuration could be added if they- for whatever reason- have
# SMB working on another port.
@trace
def upload(self, file_names, share="ADMIN$", upload_to=None,
smbport=DEFAULT_SMB_PORT):
"""
Uploads software to ADMIN$ on the remote Windows machine. Copies
software over to the Windows temp collection path.
This strategy is legacy from encloud, but the implementation is pure
python whereas before there was a samba share mounted on the Windows
source machine.
@param file_names: names of files to upload
@type file_names: list[str]
@param share: the share name to upload. defaults to ADMIN$ which
"comes"
with Windows by default.
@type share: str
@param upload_to: directory to upload to, defaults to "None" but is
set to "collection_dir" inside this method
@type upload_to: str
@param smbport: port on which to connect to host via the SMB
protocol.
defaults to DEFAULT_SMB_PORT.
@type smbport: int
"""
if not upload_to:
upload_to = ntpath.normpath(ntpath.join('TEMP',
COLLECTION_DIR_NAME))
with self.smbconnect(smbport) as smbconn:
stime = time.time()
n_files = 0
for n_files, filename in enumerate(file_names, 1):
# get a reference to filename. e.g. cygwin.exe. If the
filename
# referred to is part of WST, select that, if not try to
upload
# filename from phoenix machine.
with open(windows_source_tools.paths.get(filename,
filename)) as file_to_upload:
upload_path = ntpath.join(upload_to,
os.path.basename(filename))
self.log.info('SEND {0} => {1}'.format(filename,
upload_to))
if self._smb_upload(smbconn, upload_path,
file_to_upload, share):
self._smb_uploaded.add(upload_path)
self.log.debug('{} files transferred in {:1.1f}s.'.format(
n_files, time.time() - stime))
@retryable(retries=SMB_RETRIES, no_retry_list=[SessionError],
retry_backoff=SMB_RETRY_BACKOFF,
caller_log=SourceConnection.log)
def _smb_upload(self, smbconn, upload_to_path, file_to_upload, share):
"""Upload a file to the remote machine over SMBConnection
@param smbconn: A connected SMBConnection
@type smbconn: SMBConnection
@param upload_path: the uploaded file's absolute path
@type upload_path: str
@param file_to_upload: the file to stream from
@type file_to_upload: file
@param share: the share name to upload
@type share: str
@raise SMBSessionRetryableError
@raise SessionError
"""
try:
smbconn.putFile(share, upload_to_path, file_to_upload.read)
except SessionError, se:
self.log.debug('Error uploading {}'.format(file_to_upload.name))
self.log.exception(se)
if RETRYABLE_SMB_SESSION_ERRORS.search(str(se)):
raise SMBSessionRetryableError()
else:
raise
return True
Original comment by aamshu...@rivermeadow.com
on 29 Jul 2014 at 8:45
Arthur:
I'll take a look at the code.. Please write me (or chat) @ bethus at gmail dot
com.
No need to continue on this ticket.
Original comment by bet...@gmail.com
on 29 Jul 2014 at 8:56
Looks like it's not an impacket issue.
Original comment by bet...@gmail.com
on 30 Jul 2014 at 4:06
Reopening this issue.
After further research, looks like the problem is the MaxWriteSize change in
Windows 8.1/2012 R2.
From http://msdn.microsoft.com/en-us/library/cc246805.aspx:
<216> Section 3.3.5.3.1: If the underlying transport is NETBIOS over TCP,
Windows servers set MaxWriteSize to 65536. Otherwise, MaxWriteSize is based on
the following table.
Windows version\Connection.Dialect: MaxWriteSize
Windows 7/Windows Server 2008 R2: 1048576
Windows 8/Windows Server 2012: 1048576
All other SMB2 servers: 8388608
Looks like when having such a big MaxWriteSize and uploading a file that is
bigger than that, the connection gets closed by the server.
Temporary fix is to force the MaxWriteSize to be smaller until we figure out
why the server is closing the connection:
===================================================================
--- smb3.py (revision 1251)
+++ smb3.py (working copy)
@@ -360,7 +360,7 @@
negResp = SMB2Negotiate_Response(ans['Data'])
self._Connection['MaxTransactSize'] = negResp['MaxTransactSize']
self._Connection['MaxReadSize'] = negResp['MaxReadSize']
- self._Connection['MaxWriteSize'] = negResp['MaxWriteSize']
+ self._Connection['MaxWriteSize'] =
min(65536,negResp['MaxWriteSize'])
self._Connection['ServerGuid'] = negResp['ServerGuid']
self._Connection['GSSNegotiateToken'] = negResp['Buffer']
self._Connection['Dialect'] = negResp['DialectRevision']
Original comment by bet...@gmail.com
on 31 Jul 2014 at 1:28
Original issue reported on code.google.com by
aamshu...@rivermeadow.com
on 29 Jul 2014 at 6:46