106 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import socket
 | 
						|
import sys
 | 
						|
import errno
 | 
						|
from code import InteractiveConsole
 | 
						|
 | 
						|
from eventlet import api
 | 
						|
from eventlet.support import greenlets
 | 
						|
 | 
						|
try:
 | 
						|
    sys.ps1
 | 
						|
except AttributeError:
 | 
						|
    sys.ps1 = '>>> '
 | 
						|
try:
 | 
						|
    sys.ps2
 | 
						|
except AttributeError:
 | 
						|
    sys.ps2 = '... '
 | 
						|
 | 
						|
 | 
						|
class SocketConsole(greenlets.greenlet):
 | 
						|
    def __init__(self, desc, hostport, locals):
 | 
						|
        self.hostport = hostport
 | 
						|
        self.locals = locals
 | 
						|
        # mangle the socket
 | 
						|
        self.desc = desc
 | 
						|
        readline = desc.readline
 | 
						|
        self.old = {}
 | 
						|
        self.fixups = {
 | 
						|
            'softspace': 0,
 | 
						|
            'isatty': lambda: True,
 | 
						|
            'flush': lambda: None,
 | 
						|
            'readline': lambda *a: readline(*a).replace('\r\n', '\n'),
 | 
						|
        }
 | 
						|
        for key, value in self.fixups.iteritems():
 | 
						|
            if hasattr(desc, key):
 | 
						|
                self.old[key] = getattr(desc, key)
 | 
						|
            setattr(desc, key, value)
 | 
						|
 | 
						|
        greenlets.greenlet.__init__(self)
 | 
						|
 | 
						|
    def run(self):
 | 
						|
        try:
 | 
						|
            console = InteractiveConsole(self.locals)
 | 
						|
            console.interact()
 | 
						|
        finally:
 | 
						|
            self.switch_out()
 | 
						|
            self.finalize()
 | 
						|
 | 
						|
    def switch(self, *args, **kw):
 | 
						|
        self.saved = sys.stdin, sys.stderr, sys.stdout
 | 
						|
        sys.stdin = sys.stdout = sys.stderr = self.desc
 | 
						|
        greenlets.greenlet.switch(self, *args, **kw)
 | 
						|
 | 
						|
    def switch_out(self):
 | 
						|
        sys.stdin, sys.stderr, sys.stdout = self.saved
 | 
						|
 | 
						|
    def finalize(self):
 | 
						|
        # restore the state of the socket
 | 
						|
        for key in self.fixups:
 | 
						|
            try:
 | 
						|
                value = self.old[key]
 | 
						|
            except KeyError:
 | 
						|
                delattr(self.desc, key)
 | 
						|
            else:
 | 
						|
                setattr(self.desc, key, value)
 | 
						|
        self.fixups.clear()
 | 
						|
        self.old.clear()
 | 
						|
        self.desc = None
 | 
						|
        print "backdoor closed to %s:%s" % self.hostport
 | 
						|
 | 
						|
 | 
						|
def backdoor_server(server, locals=None):
 | 
						|
    """ Runs a backdoor server on the socket, accepting connections and 
 | 
						|
    running backdoor consoles for each client that connects.
 | 
						|
    """
 | 
						|
    print "backdoor server listening on %s:%s" % server.getsockname()
 | 
						|
    try:
 | 
						|
        try:
 | 
						|
            while True:
 | 
						|
                socketpair = server.accept()
 | 
						|
                backdoor(socketpair, locals)
 | 
						|
        except socket.error, e:
 | 
						|
            # Broken pipe means it was shutdown
 | 
						|
            if e[0] != errno.EPIPE:
 | 
						|
                raise
 | 
						|
    finally:
 | 
						|
        server.close()
 | 
						|
 | 
						|
 | 
						|
def backdoor((conn, addr), locals=None):
 | 
						|
    """Sets up an interactive console on a socket with a connected client.  
 | 
						|
    This does not block the caller, as it spawns a new greenlet to handle 
 | 
						|
    the console.
 | 
						|
    """
 | 
						|
    host, port = addr
 | 
						|
    print "backdoor to %s:%s" % (host, port)
 | 
						|
    fl = conn.makeGreenFile("rw")
 | 
						|
    fl.newlines = '\n'
 | 
						|
    greenlet = SocketConsole(fl, (host, port), locals)
 | 
						|
    hub = hubs.get_hub()
 | 
						|
    hub.schedule_call_global(0, greenlet.switch)
 | 
						|
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    backdoor_server(api.tcp_listener(('127.0.0.1', 9000)), {})
 | 
						|
 |