Koodous is a service that provides metadata about a rich collection of Android apps. Apart from that it also stores a public set of YARA rules that are being used by different 3rd parties as indicators for malware detection.
While quality of available YARA rules in the public collection differ and their blind usage may be disputable, YARA syntax extension invented by Koodous is definitely useful for two reasons:
- It allows to match public YARA rules against own Android app samples
- It allows to create new YARA rules taking advantage of Koodous YARA syntax extension – new syntax is documented here.
The tricky part is to get Koodous YARA extension really working in practice. In order do avoid platform-dependent complications I have decided to build a docker image wrapping YARA tool into an isolated environment. I got inspired with a GIST from here, but it needed modifications to make it really work in my Docker container:
FROM python:3.8-slim RUN mkdir -p /usr/src/app RUN mkdir -p /mnt/apk RUN apt-get update RUN apt-get --assume-yes install musl gcc g++ \ libjansson-dev file flex bison make libssl-dev \ libmagic-dev libtool automake autoconf git binutils curl \ libfuzzy-dev RUN pip install --upgrade pip WORKDIR /usr/src # YARA library and tool compilation RUN git clone --branch v3.11.0 https://github.com/VirusTotal/yara.git WORKDIR /usr/src/yara/libyara/modules # download the Androguard module from Koodous (implementing YARA syntax extension) RUN curl -O https://raw.githubusercontent.com/Koodous/androguard-yara/master/androguard.c # misuse --enable-cockoo argument for compilation of the Androguard module RUN sed -i -e 's/MODULE(cuckoo)/MODULE(androguard)/g' module_list WORKDIR /usr/src/yara/libyara RUN sed -i -e 's/MODULES += modules\/cuckoo.c/MODULES += modules\/androguard.c/g' Makefile.am # build and install YARA WORKDIR /usr/src/yara RUN ./bootstrap.sh RUN ./configure --enable-dotnet --enable-magic --enable-dex --enable-cuckoo && make && make install WORKDIR /usr/src # Download and build yara-python package for usage of YARA from Python - it must be linked with the previously compiled YARA lib RUN git clone --branch v3.11.0 https://github.com/VirusTotal/yara-python WORKDIR /usr/src/yara-python RUN python setup.py build --dynamic-linking RUN python setup.py install WORKDIR /usr/src/app ADD ./requirements.txt /usr/src/app/requirements.txt #we need to extend LD_LIBRARY_PATH and C_INCLUDE_PATH before installing requirements because of the ssdeep package RUN export LD_LIBRARY_PATH=/usr/local/lib/ && export C_INCLUDE_PATH=/usr/local/include && pip install -r requirements.txt ADD . /usr/src/app
Having a Docker image built, we can take a look on a practical use of the extended Yara from Python. Here I provide a simple demo Python script that uses the Androguard extension to check if the app requires any of RECEIVE_SMS
or READ_SMS
permissions.
from androguard.core.bytecodes.apk import APK from androguard.misc import AnalyzeAPK from androguard.session import Session import yara import json APK_PATH = 'target.apk' RULE_SOURCE_CODE = '''import "androguard" rule SmsInteraction { condition: androguard.permission(/android.permission.RECEIVE_SMS/) or androguard.permission(/android.permission.READ_SMS/) }''' def main(): compiled_rule = yara.compile(source=RULE_SOURCE_CODE) androguard_report = prepare_report() matching_rules = compiled_rule.match(APK_PATH, modules_data={'androguard': androguard_report}) if matching_rules: print('It matches!') else: print('It does not match!') def prepare_report() -> bytes: androguard_session = Session() apk_file: APK apk_file, _, _ = AnalyzeAPK(APK_PATH, androguard_session) apk_sha256 = list(androguard_session.get_all_apks())[0][0] return json.dumps({ 'app_name': apk_file.get_app_name(), 'package_name': apk_file.get_package(), 'certificate': {}, #TODO 'services': apk_file.get_services(), 'permissions': apk_file.get_permissions(), 'new_permissions': [], # we have no older version of app to compare with 'filters': [], #TODO 'min_sdk_version': apk_file.get_min_sdk_version(), 'max_sdk_version': apk_file.get_max_sdk_version(), 'target_sdk_version': apk_file.get_target_sdk_version(), 'version_code': apk_file.get_androidversion_code(), 'displayed_version': apk_file.get_androidversion_name(), 'libraries': apk_file.get_libraries(), 'activities': apk_file.get_activities(), 'main_activity': apk_file.get_main_activity(), 'providers': apk_file.get_providers(), 'receivers': apk_file.get_receivers(), 'signature_name': apk_file.get_signature_name(), 'wearable': apk_file.is_wearable(), 'androidtv': apk_file.is_androidtv(), 'sha256': apk_sha256, 'dexes': [], #TODO 'urls': [] #TODO }, indent=2).encode('utf-8') if __name__ == '__main__': main()
Note that prepare_report()
does not generate a complete Androguard report and there are some TODOs to make the report complete. All of those can be completed with more in-depth app analysis with Androguard.