From 6162581d23f67a4edde39be7436afae406b0818c Mon Sep 17 00:00:00 2001
From: Oleksii Shevchuk
Date: Wed, 5 Jul 2017 11:49:35 +0300
Subject: [PATCH] Add codepage support to smb
---
pupy/modules/smb.py | 80 +++++++++++++++++++--------
pupy/packages/all/pupyutils/psexec.py | 5 ++
2 files changed, 63 insertions(+), 22 deletions(-)
diff --git a/pupy/modules/smb.py b/pupy/modules/smb.py
index 090d6d5b..ac496499 100644
--- a/pupy/modules/smb.py
+++ b/pupy/modules/smb.py
@@ -9,7 +9,7 @@ __class_name__="SMB"
@config(cat="admin")
class SMB(PupyModule):
''' Copy files via SMB protocol '''
-
+
max_clients = 1
dependencies = [ 'impacket', 'pupyutils.psexec' ]
@@ -21,7 +21,8 @@ class SMB(PupyModule):
self.arg_parser.add_argument('-d', '--domain', default='', help='Domain')
self.arg_parser.add_argument('-H', '--hash', default='', help='NTLM hash')
self.arg_parser.add_argument('-T', '--timeout', default=30, type=int, help='Timeout')
-
+ self.arg_parser.add_argument('-c', '--codepage', default=None, help='Codepage')
+
commands = self.arg_parser.add_subparsers(dest="command")
cp = commands.add_parser('cp')
cp.add_argument('src', help='Source')
@@ -75,27 +76,61 @@ class SMB(PupyModule):
if not ft.ok:
self.error(ft.error)
- def parse_netloc(self, line):
+ def parse_netloc(self, line, partial=False, codepage=None):
line = line.replace('\\', '/')
-
if not line.startswith('//'):
raise ValueError('Invalid network format')
-
- remote = line[2:].split('/')
- if len(remote) < 3 or not all(remote[:2]):
- raise ValueError('Invalid network format')
- return remote[0], remote[1], ntpath.normpath('\\'.join(remote[2:]))
+ if not type(line) == unicode:
+ line = line.decode('utf-8')
+
+ if codepage:
+ line = line.encode(codepage, errors='replace')
+
+ remote = line[2:].split('/')
+
+ if partial:
+ if len(remote) == 0:
+ raise ValueError('Empty network specification')
+
+ if not (remote[0]):
+ raise ValueError('Host is empty')
+
+ host = remote[0]
+ if len(remote) > 1:
+ share = remote[1]
+ else:
+ share = ''
+
+ if len(remote) > 2:
+ path = ntpath.normpath('\\'.join(remote[2:]))
+ if remote[-1] == '':
+ path += '\\'
+ else:
+ path = ''
+
+ return host, share, path
+
+ else:
+ if len(remote) < 3 or not all(remote[:2]):
+ raise ValueError('Invalid network format')
+
+ return remote[0], remote[1], ntpath.normpath('\\'.join(remote[2:]))
def ls(self, args):
try:
- host, share, path = self.parse_netloc(args.dst)
+ host, share, path = self.parse_netloc(args.dst, partial=True, codepage=args.codepage)
except Exception, e:
self.error(str(e))
return
- if not path or path == '.':
- path = '\\*'
+ if not share:
+ args.host = host
+ self.shares(args)
+ return
+
+ if not path or path == '.' or path.endswith('\\'):
+ path += '*'
ft = self.get_ft(args, host)
if not ft.ok:
@@ -103,16 +138,17 @@ class SMB(PupyModule):
return
for name, directory, size, ctime in obtain(ft.ls(share, path)):
- self.log('%crw-rw-rw- %10d %s %s' % (
- 'd' if directory > 0 else '-', size, ctime, name
- ))
+ if args.codepage:
+ name = name.encode('utf-16le').decode(args.codepage, errors='replace')
+
+ self.log(u'%crw-rw-rw- %10d %s %s' % ('d' if directory > 0 else '-', size, ctime, name))
if not ft.ok:
self.error(ft.error)
def rm(self, args):
try:
- host, share, path = self.parse_netloc(args.dst)
+ host, share, path = self.parse_netloc(args.dst, codepage=args.codepage)
except Exception, e:
self.error(str(e))
return
@@ -128,7 +164,7 @@ class SMB(PupyModule):
def mkdir(self, args):
try:
- host, share, path = self.parse_netloc(args.dst)
+ host, share, path = self.parse_netloc(args.dst, codepage=args.codepage)
except Exception, e:
self.error(str(e))
return
@@ -144,7 +180,7 @@ class SMB(PupyModule):
def rmdir(self, args):
try:
- host, share, path = self.parse_netloc(args.dst)
+ host, share, path = self.parse_netloc(args.dst, codepage=args.codepage)
except Exception, e:
self.error(str(e))
return
@@ -174,11 +210,11 @@ class SMB(PupyModule):
return
try:
- host, share, path = self.parse_netloc(remote)
+ host, share, path = self.parse_netloc(remote, codepage=args.codepage)
except Exception, e:
self.error(e)
return
-
+
local = os.path.expandvars(local)
local = os.path.expanduser(local)
@@ -187,11 +223,11 @@ class SMB(PupyModule):
return
ft = self.get_ft(args, host)
-
+
if not ft.ok:
self.error(ft.error)
return
-
+
interval, timeout = self.client.conn._conn.root.getconn().get_pings()
self.client.conn._conn.root.getconn().set_pings(0, 0)
diff --git a/pupy/packages/all/pupyutils/psexec.py b/pupy/packages/all/pupyutils/psexec.py
index 1d1a7e52..9f8b6ce5 100644
--- a/pupy/packages/all/pupyutils/psexec.py
+++ b/pupy/packages/all/pupyutils/psexec.py
@@ -13,12 +13,17 @@ import random
import sys
import os
import string
+import encodings
PERM_DIR = ''.join(random.sample(string.ascii_letters, 10))
BATCH_FILENAME = ''.join(random.sample(string.ascii_letters, 10)) + '.bat'
SMBSERVER_DIR = ''.join(random.sample(string.ascii_letters, 10))
DUMMY_SHARE = 'TMP'
+if not encodings._cache['idna']:
+ import encodings.idna
+ encodings._cache['idna'] = encodings.idna.getregentry()
+
class FileTransfer(object):
def __init__(self, host, port=445, hash='', username='', password='', domain='', timeout=30):
self.__host = host