Skip to content

Commit

Permalink
upgrade pyro due to bug#80 @pyrolite
Browse files Browse the repository at this point in the history
  • Loading branch information
mr-m0nst3r committed Aug 29, 2021
1 parent 3ec94bd commit ddd3b4d
Show file tree
Hide file tree
Showing 12 changed files with 236 additions and 472 deletions.
19 changes: 6 additions & 13 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>me.m0nst3r</groupId>
<artifactId>burpy</artifactId>
<version>2.4.4-SNAPSHOT</version>
<version>3.0-SNAPSHOT</version>
<name>burpy</name>
<description>burp plugin to run custom python</description>
<properties>
Expand Down Expand Up @@ -87,27 +87,20 @@
<version>3.8.1</version>
<scope>test</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/net.razorvine/pyrolite -->
<dependency>
<groupId>net.razorvine</groupId>
<artifactId>pyrolite</artifactId>
<version>4.20</version>
<version>5.1</version>
</dependency>

<!-- https://mvnrepository.com/artifact/net.razorvine/serpent -->
<dependency>
<groupId>net.razorvine</groupId>
<artifactId>serpent</artifactId>
<version>1.23</version>
</dependency>

<!-- Local dependency that must be installed locally with Maven -->
<!-- <dependency>-->
<!-- <groupId>com.fifesoft</groupId>-->
<!-- <artifactId>rsyntaxtextarea</artifactId>-->
<!-- <version>2.6.1.edited</version>-->
<!-- </dependency>-->
<version>1.40</version>
</dependency>

</dependencies>
</project>
3 changes: 3 additions & 0 deletions res/.idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions res/.idea/inspectionProfiles/profiles_settings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions res/.idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions res/.idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions res/.idea/res.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions res/.idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

239 changes: 126 additions & 113 deletions res/burpyServicePyro.py
Original file line number Diff line number Diff line change
@@ -1,133 +1,146 @@
#coding:utf-8
import codecs
import Pyro4
# coding:utf-8
# import Pyro4
# from Pyro5.compatibility import Pyro4
import Pyro5.api
import sys
m_module = sys.argv[-1]
import imp
try:
imp.load_source("f",m_module) #imp.load_source("test","/tmp/test.py")
except Exception:
print("Failed to get python file, pls recheck")
from f import Burpy # which loads the destination file
from importlib import reload
import importlib.util
from base64 import b64decode as b64d

reload(sys)
m_module = sys.argv[-1]

@Pyro4.expose
class BridaServicePyro:
module_name = m_module.split("/")[-1][:-2]
spec = importlib.util.spec_from_file_location('{}.Burpy'.format(module_name), m_module)
b = importlib.util.module_from_spec(spec)
spec.loader.exec_module(b)

class http:
'''
accept data string
'''

def __init__(self, data):
self.data = data
self.first_line, self.headers, self.body = self.parse_headers_and_body(data)

def parse_headers(self, s):
headers = s.split("\r\n")
headers_found = {}
for header_line in headers:
try:
key, value = header_line.split(':', 1)
except:
continue
headers_found[key] = value.strip()
return headers_found

def parse_headers_and_body(self, s):
try:
crlfcrlf = "\r\n\r\n".encode('utf-8')
crlfcrlfIndex = s.find(crlfcrlf)
headers = s[:crlfcrlfIndex + len(crlfcrlf)].decode("utf-8")
body = s[crlfcrlfIndex + len(crlfcrlf):]
except:
headers = s
body = ''
first_line, headers = headers.split("\r\n", 1)
return first_line.strip(), self.parse_headers(headers), str(body, encoding="utf-8")

# def build(self, isRequest):
def build(self):
'''
convert self to strings
'''
# if(isRequest):
# get headers as dict
newhttp = list()
first_line = self.headers.pop("first_line")
newhttp.append(first_line)
for k in self.headers.keys():
newhttp.append("{}: {}".format(k, self.headers[k]))

newhttp.append("")
newhttp.append(self.body)
newhttp = map(lambda l: l if isinstance(l, bytes) else l.encode('utf-8'), newhttp)

http_str = b'\r\n'.join(newhttp)
return str(http_str, encoding="utf-8")

# else:
# return "response"
# return p


class Unbuffered(object):
def __init__(self, stream):
self.stream = stream

def write(self, data):
self.stream.write(data)
self.stream.flush()

def writelines(self, datas):
self.stream.writelines(datas)
self.stream.flush()

def __getattr__(self, attr):
return getattr(self.stream, attr)


@Pyro5.api.expose
class BurpyServicePyro:
def __init__(self, daemon):
self.daemon = daemon
self.burpy = Burpy()

def disconnect_application(self):

self.device.kill(self.pid)
return

def hello_spawn(self):
data = "it's working"
return data

def hello(self, header, body):
data = body[0].decode("hex")
if data is None:
return "No data selected"
try:
# header is a list, but body is string
# so we append body to header list
nheader, nbody = self.burpy.main(header, data)
nheader = nheader or list()
nheader.append("")
nheader.append(nbody)
http_str = "\x0d\x0a".join(nheader)
ret_val = http_str

except Exception as e:
print( e )
ret_val = "helo(main) BurpyService failed"
return ret_val

def encrypt(self, header, body):
data = body[0].decode("hex")
if data is None:
return "No data selected"
try:
# header is a list, but body is string
# so we append body to header list
nheader, nbody = self.burpy.encrypt(header, data)
nheader = nheader or list()
header.append("")
nheader.append(nbody)
http_str = "\x0d\x0a".join(nheader)
ret_val = http_str

except Exception as e:
print( e )
ret_val = "Encrypt in BurpyService failed"
return ret_val

def decrypt(self, header, body):
data = body[0].decode("hex")
if data is None:
return "No data selected"
try:
# header is a list, but body is string
# so we append body to header list
nheader, nbody = self.burpy.decrypt(header, data)
nheader = nheader or list()
nheader.append("")
nheader.append(nbody)
http_str = "\x0d\x0a".join(nheader)
ret_val = http_str
self.burpy = b.Burpy()
self.method_list = [func for func in dir(b.Burpy) if
callable(getattr(b.Burpy, func)) and not func.startswith("__") and not func.startswith(
"_") and not func == "processor"]

except Exception as e:
print( e )
ret_val = "Decrypt in BurpyService Failed"
return ret_val
def get_methods(self):
return self.method_list

def sign(self, header, body):
data = body[0].decode("hex")
def invoke_method(self, method_name, data):
func = getattr(self.burpy, method_name)
if data is None:
return "No data selected"
return "Parse HTTP data failed"
try:
# header is a list, but body is string
# so we append body to header list
nheader, nbody = self.burpy.sign(header, data)
nheader.append("")
nheader.append(nbody)
http_str = "\x0d\x0a".join(nheader)
ret_val = http_str

# headers is dict, body is str
if func.__name__ != "processor":
# fix processor bug
data = http(b64d(data))
data.headers.update({"first_line": data.first_line})
data.headers, data.body = func(data.headers, data.body)
ret_val = data.build()
else:
ret_val = func(data)
except Exception as e:
print( e )
ret_val = "Can't find method name burpy or script file not found"
print(e)
ret_val = "{} in BurpyService failed".format(method_name)
return ret_val

def processor(self, data):
try:
ret_val = self.burpy.processor(data)
return ret_val
except Exception as e:
print( e )
return "Can't process payload"

# @Pyro5.api.oneway
# def shutdown(self):
# print('shutting down...')
# try:
# # self.burpy.down()
# del self.burpy
# except Exception:
# print("burpy.down() method not found, skipped.")
# self.daemon.close()

@Pyro4.oneway
def shutdown(self):
print('shutting down...')
try:
# self.burpy.down()
del self.burpy
except Exception:
print("burpy.down() method not found, skipped.")
self.daemon.shutdown()

# Disable python buffering (cause issues when communicating with Java...)
sys.stdout = Unbuffered(sys.stdout)
sys.stderr = Unbuffered(sys.stderr)

host = sys.argv[1]
port = int(sys.argv[2])
daemon = Pyro4.Daemon(host=host,port=port)
daemon = Pyro5.api.Daemon(host=host, port=port)

#daemon = Pyro4.Daemon(host='127.0.0.1',port=9999)
bs = BridaServicePyro(daemon)
uri = daemon.register(bs,objectId='BurpyServicePyro')
# daemon = Pyro4.Daemon(host='127.0.0.1',port=9999)
bs = BurpyServicePyro(daemon)
uri = daemon.register(bs, objectId='BurpyServicePyro')

print("Ready.")
print("Ready. Object uri =", uri)
daemon.requestLoop()
Loading

0 comments on commit ddd3b4d

Please sign in to comment.