diff options
-rw-r--r-- | python-plugins/zipbomb/__init__.py | 2 | ||||
-rw-r--r-- | python-plugins/zipbomb/plugin.py | 71 | ||||
-rw-r--r-- | python/extract.py | 71 | ||||
-rw-r--r-- | python/googleplay.py | 86 |
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() |