mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-23 00:01:36 +00:00
Substantially rewrite AMF decoding.
This is tricky, but we should now handle a lot more corner-cases.
This commit is contained in:
parent
64bf97bfb0
commit
8c976ac7f0
@ -15,11 +15,10 @@ from ..contrib import jsbeautifier, html2text
|
||||
|
||||
try:
|
||||
import pyamf
|
||||
from pyamf import remoting
|
||||
from pyamf import remoting, flex
|
||||
except ImportError: # pragma nocover
|
||||
pyamf = None
|
||||
|
||||
|
||||
VIEW_CUTOFF = 1024*50
|
||||
|
||||
|
||||
@ -236,30 +235,75 @@ class ViewMultipart:
|
||||
return "Multipart form", r
|
||||
|
||||
|
||||
class ViewAMF:
|
||||
name = "AMF"
|
||||
prompt = ("amf", "f")
|
||||
content_types = ["application/x-amf"]
|
||||
def __call__(self, hdrs, content, limit):
|
||||
envelope = remoting.decode(content)
|
||||
if not envelope:
|
||||
return None
|
||||
if pyamf:
|
||||
class DummyObject(dict):
|
||||
def __init__(self, alias):
|
||||
dict.__init__(self)
|
||||
|
||||
data = {}
|
||||
data['amfVersion'] = envelope.amfVersion
|
||||
for target, message in iter(envelope):
|
||||
one_message = {}
|
||||
def __readamf__(self, input):
|
||||
data = input.readObject()
|
||||
self["data"] = data
|
||||
|
||||
if hasattr(message, 'status'):
|
||||
one_message['status'] = message.status
|
||||
def pyamf_class_loader(s):
|
||||
for i in pyamf.CLASS_LOADERS:
|
||||
if i != pyamf_class_loader:
|
||||
v = i(s)
|
||||
if v:
|
||||
return v
|
||||
return DummyObject
|
||||
|
||||
if hasattr(message, 'target'):
|
||||
one_message['target'] = message.target
|
||||
pyamf.register_class_loader(pyamf_class_loader)
|
||||
|
||||
one_message['body'] = message.body
|
||||
data[target] = one_message
|
||||
s = json.dumps(data, indent=4)
|
||||
return "AMF", _view_text(s[:limit], len(s), limit)
|
||||
class ViewAMF:
|
||||
name = "AMF"
|
||||
prompt = ("amf", "f")
|
||||
content_types = ["application/x-amf"]
|
||||
|
||||
def unpack(self, b, seen=set([])):
|
||||
if hasattr(b, "body"):
|
||||
return self.unpack(b.body, seen)
|
||||
if isinstance(b, DummyObject):
|
||||
if id(b) in seen:
|
||||
return "<recursion>"
|
||||
else:
|
||||
seen.add(id(b))
|
||||
for k, v in b.items():
|
||||
b[k] = self.unpack(v, seen)
|
||||
return b
|
||||
elif isinstance(b, dict):
|
||||
for k, v in b.items():
|
||||
b[k] = self.unpack(v, seen)
|
||||
return b
|
||||
elif isinstance(b, list):
|
||||
return [self.unpack(i) for i in b]
|
||||
elif isinstance(b, flex.ArrayCollection):
|
||||
return [self.unpack(i, seen) for i in b]
|
||||
else:
|
||||
return b
|
||||
|
||||
def __call__(self, hdrs, content, limit):
|
||||
envelope = remoting.decode(content, strict=False)
|
||||
if not envelope:
|
||||
return None
|
||||
|
||||
|
||||
txt = []
|
||||
for target, message in iter(envelope):
|
||||
if isinstance(message, pyamf.remoting.Request):
|
||||
txt.append(urwid.Text([
|
||||
("header", "Request: "),
|
||||
("text", str(target)),
|
||||
]))
|
||||
else:
|
||||
txt.append(urwid.Text([
|
||||
("header", "Response: "),
|
||||
("text", "%s, code %s"%(target, message.status)),
|
||||
]))
|
||||
|
||||
s = json.dumps(self.unpack(message), indent=4)
|
||||
txt.extend(_view_text(s[:limit], len(s), limit))
|
||||
|
||||
return "AMF v%s"%envelope.amfVersion, txt
|
||||
|
||||
|
||||
class ViewJavaScript:
|
||||
|
BIN
test/data/amf02
Normal file
BIN
test/data/amf02
Normal file
Binary file not shown.
BIN
test/data/amf03
Normal file
BIN
test/data/amf03
Normal file
Binary file not shown.
@ -3,6 +3,12 @@ import libmproxy.console.contentview as cv
|
||||
from libmproxy import utils, flow, encoding
|
||||
import tutils
|
||||
|
||||
try:
|
||||
import pyamf
|
||||
except ImportError:
|
||||
pyamf = None
|
||||
|
||||
|
||||
class TestContentView:
|
||||
def test_trailer(self):
|
||||
txt = []
|
||||
@ -119,15 +125,6 @@ class TestContentView:
|
||||
|
||||
assert not v([], "flibble", sys.maxint)
|
||||
|
||||
def test_view_amf(self):
|
||||
try:
|
||||
import pyamf
|
||||
v = cv.ViewAMF()
|
||||
p = tutils.test_data.path("data/test.amf")
|
||||
assert v([], file(p).read(), sys.maxint)
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
def test_view_multipart(self):
|
||||
view = cv.ViewMultipart()
|
||||
v = """
|
||||
@ -220,5 +217,21 @@ Larry
|
||||
assert "Raw" in r[0]
|
||||
|
||||
|
||||
if pyamf:
|
||||
def test_view_amf_request():
|
||||
v = cv.ViewAMF()
|
||||
|
||||
p = tutils.test_data.path("data/amf01")
|
||||
assert v([], file(p).read(), sys.maxint)
|
||||
|
||||
p = tutils.test_data.path("data/amf02")
|
||||
assert v([], file(p).read(), sys.maxint)
|
||||
|
||||
def test_view_amf_response():
|
||||
v = cv.ViewAMF()
|
||||
p = tutils.test_data.path("data/amf03")
|
||||
assert v([], file(p).read(), sys.maxint)
|
||||
|
||||
|
||||
def test_get_by_shortcut():
|
||||
assert cv.get_by_shortcut("h")
|
||||
|
Loading…
Reference in New Issue
Block a user