summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--python-plugins/zipbomb/__init__.py2
-rw-r--r--python-plugins/zipbomb/plugin.py71
-rw-r--r--python/extract.py71
-rw-r--r--python/googleplay.py86
4 files changed, 230 insertions, 0 deletions
diff --git a/python-plugins/zipbomb/__init__.py b/python-plugins/zipbomb/__init__.py
new file mode 100644
index 0000000..a9d4527
--- /dev/null
+++ b/python-plugins/zipbomb/__init__.py
@@ -0,0 +1,2 @@
+
+from zipbomb.plugin import ZipBombChecker as AutoLoad
diff --git a/python-plugins/zipbomb/plugin.py b/python-plugins/zipbomb/plugin.py
new file mode 100644
index 0000000..be8c12f
--- /dev/null
+++ b/python-plugins/zipbomb/plugin.py
@@ -0,0 +1,71 @@
+
+import io
+import zipfile
+
+from pychrysalide.analysis.scan import ScanRegisteredItem
+from pychrysalide.analysis.scan.exprs import ScanLiteralExpression
+from pychrysalide.core import get_rost_root_namespace
+from pychrysalide.plugins import PluginModule
+
+
+class ZipBombKeyword(ScanRegisteredItem):
+ """Introduce a new keyword in the ROST grammar."""
+
+ _name = 'is_zip_bomb'
+
+
+ def _reduce(self, ctx, scope):
+
+ expr = None
+
+ try:
+
+ has_bomb = False
+
+ # compress < 10% plain => bomb
+ ZIP_BOMB_RATIO = 0.01
+
+ data = io.BytesIO(ctx.content.data)
+
+ zf = zipfile.ZipFile(data)
+
+ info = zf.infolist()
+
+ for i in info:
+
+ ratio = i.compress_size / i.file_size
+
+ has_bomb = ratio < ZIP_BOMB_RATIO
+
+ if has_bomb:
+ break
+
+ expr = ScanLiteralExpression(has_bomb)
+
+ except:
+ pass
+
+ return expr
+
+
+class ZipBombChecker(PluginModule):
+ """Check for ZIP bombs."""
+
+ _name = 'ZipBombChecker'
+ _desc = 'Check if a ZIP archive may contain heavy files on extraction'
+ _version = '0.1'
+ _url = 'https://www.chrysalide.re/'
+
+ _actions = ( )
+
+
+ def __init__(self):
+ """Create a ZipBombChecker plugin instance."""
+
+ super().__init__()
+
+ ns = get_rost_root_namespace()
+
+ kw = ZipBombKeyword()
+
+ ns.register_item(kw)
diff --git a/python/extract.py b/python/extract.py
new file mode 100644
index 0000000..e04ba7e
--- /dev/null
+++ b/python/extract.py
@@ -0,0 +1,71 @@
+
+import gi
+import os
+import sys
+from gi.repository import Gio
+
+
+if len(sys.argv) != 2:
+ print('Usage: %s <theme file>' % sys.argv[0])
+ sys.exit(1)
+
+res = Gio.Resource.load(sys.argv[1])
+
+
+# Get the name of the theme
+
+children = res.enumerate_children('/org/chrysalide/gui/themes', Gio.ResourceLookupFlags.NONE)
+
+name = children[0][:-1]
+
+
+# Prepare the output directory
+
+if not(os.path.isdir(name)):
+ os.mkdir(name)
+
+
+# Dump resource files
+
+files = ''
+
+children = res.enumerate_children('/org/chrysalide/gui/themes/' + name, Gio.ResourceLookupFlags.NONE)
+
+for child in children:
+
+ raw = res.lookup_data('/org/chrysalide/gui/themes/' + name + '/' + child, Gio.ResourceLookupFlags.NONE)
+
+ with open(name + os.sep + child, 'wb') as out:
+ out.write(raw.get_data())
+
+ files += '\n <file compressed="true">%s</file>' % child
+
+
+# Create the gresource.xml file
+
+xml = '''<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/chrysalide/gui/themes/%s">%s
+ </gresource>
+</gresources>
+''' % (name, files)
+
+with open(name + os.sep + 'gresource.xml', 'w') as out:
+ out.write(xml)
+
+
+# Create a Makefile
+
+rules = '''
+GTK3_CSS = %s
+
+%s.ctm: gresource.xml $(GTK3_CSS)
+ glib-compile-resources --target=$@ --sourcedir=. gresource.xml
+
+clean:
+ rm -f %s
+
+''' % (' '.join(children), name.lower(), name.lower())
+
+with open(name + os.sep + 'Makefile', 'w') as out:
+ out.write(rules)
diff --git a/python/googleplay.py b/python/googleplay.py
new file mode 100644
index 0000000..d580ce2
--- /dev/null
+++ b/python/googleplay.py
@@ -0,0 +1,86 @@
+
+import json
+import os
+import threading
+
+from pychrysalide import core
+from pychrysalide.analysis.contents import MemoryContent
+from pychrysalide.plugins.gplay import PlayStore, AndroidDevice
+
+
+if __name__ == "__main__":
+
+ core.set_verbosity(0)
+
+
+ assert('bacon' in AndroidDevice.list_available_models())
+
+ dev = AndroidDevice('bacon')
+
+
+ MyPlayStore = PlayStore
+
+ if not(os.path.isfile('playstore.cfg')):
+
+ user = os.getenv('USER')
+ password = os.getenv('PASSWORD')
+
+ store = PlayStore(dev, user, password)
+
+ cfg = {
+ 'dev_id': store.device_id,
+ 'auth_token': store.auth_token,
+ 'dev_token': store.device_token,
+ }
+
+ with open('playstore.cfg', 'w') as fd:
+ json.dump(cfg, fd, indent=' ')
+
+ else:
+
+ with open('playstore.cfg', 'r') as fd:
+ cfg = json.load(fd)
+
+ store = PlayStore(dev, dev_id=cfg['dev_id'], auth_token=cfg['auth_token'], dev_token=cfg['dev_token'])
+
+
+ _take_ownership = None
+
+
+ ret = store.login()
+
+ if ret:
+
+ pkg_name = 'org.mozilla.firefox'
+
+ details = store.get_package_details(pkg_name)
+
+ pkg_version = details.version_code
+
+
+ def _on_downloaded(_store, _content, _event):
+
+ if not(_content is None):
+
+ # As the content is allocated from another thread,
+ # transfer ownership to the main thread in order
+ # to avoid deadlock when Python tries to free this content
+ global _take_ownership
+ _take_ownership = _content
+
+ with open('%s-%u.apk' % (pkg_name, pkg_version), 'wb') as fd:
+ fd.write(_content.data)
+
+ else:
+ core.log_message(core.LogMessageType.EXT_ERROR, 'Error while downloading the APK file')
+
+ _event.set()
+
+
+ event = threading.Event()
+
+ store.connect('downloaded', _on_downloaded, event)
+
+ store.download_package(pkg_name, pkg_version)
+
+ event.wait()