diff --git a/docs/source/addRules.rst b/docs/source/addRules.rst deleted file mode 100644 index c658444d2..000000000 --- a/docs/source/addRules.rst +++ /dev/null @@ -1,129 +0,0 @@ -+++++++++ -Add Rules -+++++++++ - -Android malware analysis engine is not a new story. Every antivirus company has -their own secrets to build it. With curiosity, we develop a malware scoring -system from the perspective of Taiwan Criminal Law in an easy but solid way. - -We have an order theory of criminal which explains stages of committing a crime. -For example, crime of murder consists of five stages, they are determined, -conspiracy, preparation, start and practice. The latter the stage the more -we’re sure that the crime is practiced. - -According to the above principle, we developed our order theory of android -malware. We develop five stages to see if the malicious activity is being -practiced. They are - - 1. Permission requested. - 2. Native API call. - 3. Certain combination of native API. - 4. Calling sequence of native API. - 5. APIs that handle the same register. - -We not only define malicious activities and their stages but also develop -weights and thresholds for calculating the threat level of a malware. - -But before we explain how to set weights and thresholds, we need to define -crimes and corresponding five stages. - -An example of defining crime "Send Location via SMS" is shown below. We use -json format to construct the rule of the crime. - -.. code-block:: python - :linenos: - - { - "crime": "Send Location via SMS", - - "permission": [ - "android.permission.SEND_SMS", - "android.permission.ACCESS_COARSE_LOCATION", - "android.permission.ACCESS_FINE_LOCATION" - ], - - "api": [ - { - "class": "Landroid/telephony/TelephonyManager", - "method": "getCellLocation", - "descriptor": "()Landroid/telephony/CellLocation;" - }, - { - "class": "Landroid/telephony/SmsManager", - "method": "sendTextMessage", - "descriptor": "(Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Landroid/app/PendingIntent; Landroid/app/PendingIntent;)V" - } - ], - - "score": 4 - } - - -So let me walk you through the json file. - -.. code-block:: python - - "crime": "Send Location via SMS" - -First, we define the crime. Our principle of constructing a crime is -``Action + Target``. In this example, the action is "Send SMS" and the target -is Location info. Therefore, the crime of our first rule is defined as: -"Send Location via SMS". - - -.. code-block:: python - - "permission": [ - "android.permission.SEND_SMS", - "android.permission.ACCESS_COARSE_LOCATION", - "android.permission.ACCESS_FINE_LOCATION" - ] - -``permission`` is where we fill in permission requested by the apk to -practice the crime. For instance, we need permission -``android.permission.SEND_SMS`` to send information through SMS. We also need -permission ``android.permission.ACCESS_COARSE_LOCATION`` and -``android.permission.ACCESS_FINE_LOCATION`` to practice the crime. - -.. code-block:: python - - "api": [ - { - "class": "Landroid/telephony/TelephonyManager", - "method": "getCellLocation", - "descriptor": "()Landroid/telephony/CellLocation;" - }, - { - "class": "Landroid/telephony/SmsManager", - "method": "sendTextMessage", - "descriptor": "(Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Landroid/app/PendingIntent; Landroid/app/PendingIntent;)V" - } - ] - -``api`` means this field can be used to practice analysis from -stage 2 to stage 4. - -In stage 2, we need to find key native APIs that do -the ``Action`` and ``Target``. And since the API method name can be used by -self-defined class. We need to fill in information of both the native -API class name and method name. - -.. note:: We like to keep our crime/rule simple. So do not fill in more than 2 native APIs. - -In stage 3, we will find the combination of the native APIs we define -in stage 2. Further, we will check whether they're called in the same method. -If so, we will say that the combination of crime is caught! -And we don't need to do anything to adjust the ``api`` field. - -.. note:: We know that the native API might be wrapped in other methods. We use XREF to solve this problem. - -In stage 4, we will find whether the native APIs are called in a right sequence. -If so, we have more confidence that the crime is practiced. - -.. note:: Please place the APIs in the order as the crime is being committed. - -In stage 5, we will check whether the native APIs are operating the same parameter. -If so, we are 100% sure that the crime is practiced. - -As for the field ``score``, we will be updating our principles of weight defining. -please check that part later. diff --git a/docs/source/coding_style.rst b/docs/source/coding_style.rst deleted file mode 100644 index c1b0ac05c..000000000 --- a/docs/source/coding_style.rst +++ /dev/null @@ -1,165 +0,0 @@ -============ -Coding Style -============ - -Having a clean and structured code is very important for the sustainable -development of this project. -`Cuckoo Sandbox `_ is a good example. -So we follow most of their style for maintaining the code base. - -We do help out with code refactoring where required, but please try to do -as much as possible on your own. - -Essentially Quark's code style is based on `PEP 8 - Style Guide for Python Code -`_ and `PEP 257 -- Docstring -Conventions `_. - -Formatting -========== - -File and folder naming ----------------------- - -All characters in the filenames or folder names should be lowercase letters. - -Copyright header ----------------- - -All existing source code files start with the following copyright header:: - - # This file is part of Quark Engine - https://quark-engine.rtfd.io - # See GPLv3 for copying permission. - -Indentation ------------ - -The code must have a 4-spaces-tabs indentation. Since Python enforce the -indentation, make sure to configure your editor properly or your code might -cause malfunctioning. - -Maximum Line Length -------------------- - -Limit all lines to a maximum of 79 characters. - -Blank Lines ------------ - -Separate the class definition and the top level function with one blank line. -Methods definitions inside a class are separated by a single blank line:: - - class MyClass: - """Doing something.""" - - def __init__(self): - """Initialize""" - pass - - def do_it(self, what): - """Do it. - @param what: do what. - """ - pass - -Use blank lines in functions, sparingly, to isolate logic sections. -Import blocks are separated by a single blank line, import blocks are separated -from classes by one blank line. - -Imports -------- - -Imports must be on separate lines. If you're importing multiple objects from a -package, use a single line:: - - from lib import a, b, c - -**NOT**:: - - from lib import a - from lib import b - from lib import c - -Always specify explicitly the objects to import:: - - from lib import a, b, c - -**NOT**:: - - from lib import * - -Strings -------- - -Strings must be delimited by double quotes ("). - -Printing and Logging --------------------- - -We discourage the use of ``print()``: if you need to log an event please use -Python's ``logging`` which is already initialized by Quark. - -In your module add:: - - import logging - log = logging.getLogger(__name__) - -And use the ``log`` handle. More details can be found in the Python -documentation, but as follows is an example:: - - log.info("Log message") - -Exceptions -========== - -Custom exceptions will be defined in the ``quark/utils/exceptions.py`` file. - -Naming ------- - -Custom exception names must start with "Quark" and end with "Error" if it -represents an unexpected malfunction. - -Exception handling ------------------- - -When catching an exception and accessing its handle, use ``as e``:: - - try: - foo() - except Exception as e: - bar() - -**NOT**:: - - try: - foo() - except Exception, something: - bar() - -It's a good practice use "e" instead of "e.message". - -Documentation -============= - -All code must be documented in docstring format, see `PEP 257 -- Docstring -Conventions `_. -Additional comments may be added in logical blocks to make the code easier to understand. - -As for the contribution to `quark rtdf `_. Please use -``make html`` to build the html files. And commit with rst files altogether. -So that users can read docs when offline. - -Automated testing -================= - -We believe in automated testing to provide high quality code and avoid easily -overlooked mistakes. - -When possible, all code must be committed with proper unit tests. Particular -attention must be placed when fixing bugs: it's good practice to write unit -tests to reproduce the bug. -All unit tests and fixtures are placed in the tests folder in the -quark-engine/tests. - -We have adopted `Pytest `_ as unit testing framework. -Also we adopted `travis ci `_ for the continuous integration. diff --git a/docs/source/contribution.rst b/docs/source/contribution.rst deleted file mode 100644 index 116ae49be..000000000 --- a/docs/source/contribution.rst +++ /dev/null @@ -1,80 +0,0 @@ -++++++++++++ -Contribution -++++++++++++ - -Different stages of core members -================================ - -* ``Contributor``: - As soon as you post a comment, fix a typo, ask a question or report a bug etc. - , you become an active contributor. - - - -* ``Contributor followed by a mentor``: - Spotted active contributors can be asked to get a mentor to speedup their - learning of this project. - - -* ``Core member``: - Once other core members consider that a contributor is ready to be promoted, - a core member opens a private vote for the candidate. - - -Core members -============ - -+---------------+-------------------------------------------------------------------------------------------+ -| Name | Contribution | -+===============+===========================================================================================+ -| KunYu Chen | ``BDFL, Project Founder, The man who runs the show`` | -+---------------+-------------------------------------------------------------------------------------------+ -| YuShiang Dang | ``UI/UX Team Lead, Core Developer, Rule generation system, Malware Analyst`` | -+---------------+-------------------------------------------------------------------------------------------+ -| ShengFone Lu | ``Core Developer, Triage Team Lead, Rizin Engine Implementation`` | -+---------------+-------------------------------------------------------------------------------------------+ -| AnWei Kung | ``Core Developer, Triage Team Member, Backend (database, downloader, API), Testing`` | -+---------------+-------------------------------------------------------------------------------------------+ -| Zin Wong | ``Triage Team Member`` | -+---------------+-------------------------------------------------------------------------------------------+ -| Zee | ``UI/UX Team Member`` | -+---------------+-------------------------------------------------------------------------------------------+ - - -Alumni -====== -+---------------+-------------------------------------------------------------------------------------------+ -| Name | Contribution | -+===============+===========================================================================================+ -| JunWei Song | ``Project Co-Founder, Engine Implementation (Malware Scoring System), Frontend, Testing`` | -+---------------+-------------------------------------------------------------------------------------------+ -| ShunTe Lin | ``Core Developer, Triage Team Member`` | -+---------------+-------------------------------------------------------------------------------------------+ -| ChaoWen Li | ``Quark Community Development`` | -+---------------+-------------------------------------------------------------------------------------------+ -| Sin | ``Malware Analyst, Detection Rules, Engine Implementation (Malware Anti-Detection)`` | -+---------------+-------------------------------------------------------------------------------------------+ -| IokJin Sih | ``Malware Analyst`` | -+---------------+-------------------------------------------------------------------------------------------+ -| YunChen Liu | ``Artwork Design, Frontend`` | -+---------------+-------------------------------------------------------------------------------------------+ - -Consultants -=========== - -Consultant is the one who is important to this project and -shows great support to our engine. - -+-----------------+ -| Consultant | -+=================+ -| Chun-I Fan | -+-----------------+ -| HY Lin | -+-----------------+ -| Jheng-Jia Huang | -+-----------------+ -| Lin Gao-Yu | -+-----------------+ -| Pippen Wang | -+-----------------+ diff --git a/docs/source/dev.rst b/docs/source/dev.rst deleted file mode 100644 index f4ee4132d..000000000 --- a/docs/source/dev.rst +++ /dev/null @@ -1,161 +0,0 @@ -================= -Development Notes -================= - -Git Branching Model -=================== - -Quark-engine source code is available in our `official Git repository`_. - -.. _`official Git repository`: https://github.com/quark-engine/quark-engine - -We have 6 branches. - - * **master**: - - - This is the stable and releasing branch. - - * **dev**: - - - This is where we commit our beta version. - - When all the features are fully tested, it will be merged to ``master`` branch. - - * **feature**: - - - This is where we develop new features for the project. - - Once it's done, it will be merged to ``dev`` branch. - - - * **testing**: - - - This is where we write tests for the codebase and new feature. - - When it's done, it will be merged to ``dev`` branch. - - * **hotfix**: - - - This branch is used to fix bugs. - - Will be merged to ``dev`` and ``master`` - - * **doc**: - - - This is where we update our documentation. - - Just like hotfix branch, will be merged to ``dev`` and ``master``. - -Release Versioning -================== - -Our versioning logic is quite simple. We use the year and month of the release -as a version number. ``v19.10`` means we release this version in Oct. 2019. - -Ticketing System -================ - -To submit reports or feature requests, please use GitHub's `Issue`_ tracking system. - -.. _`Issue`: https://github.com/quark-engine/quark-engine/issues - -Contribute -========== - -To submit your patch, just create a Pull Request from your GitHub fork. -If you don't know how to create a Pull Request take a look to `GitHub help`_. - -.. _`GitHub help`: https://help.github.com/articles/using-pull-requests/ - -Packaging -========== - -Kali Linux ------------ - -Steps For Packaging -""""""""""""""""""""" - -Quark is available in the Kali Linux repository. So you can install Quark with ``apt install quark-engine`` in Kali Linux. However, you can also create your own Kali package with the steps below. - -**Step 1: Setup environment for packaging** - - -Install the necessary packages in the latest version of `Kali Linux `_. - -.. code-block:: bash - - sudo apt update && apt-get install git python3 python3-pip \ - build-essential debhelper devscripts equivs - -**Step 2: Download the source code of Quark** - -Download the source code of Quark to the ``quark-engine`` directory. - -.. code-block:: bash - - git clone https://github.com/quark-engine/quark-engine.git - -Enter the ``quark-engine`` directory. - -.. code-block:: bash - - cd quark-engine - -**Step 3: Update the version information (optional)** - -You can update the version number and changelog of the package. If you want to update the version number, change ``Standards-Version`` in the ``debian/control`` file. If you want to update the changelog, add the descriptions of new changes at the beginning of the ``debian/changelog`` file following the `Debian changelog format `_. - - -**Step 4: Create the package** - -Create a package for Kali Linux. - -.. code-block:: bash - - dpkg-buildpackage -us -uc -b - -Go to the previous directory. - -.. code-block:: bash - - cd .. - -Then, you can see the package named ``quark-engine_<>.deb``, where ``<>`` is the version number defined in the ``debian/control`` file. - - -**Step 5: Install Quark** - -Install Quark using the created package. - -.. code-block:: bash - - sudo apt install ./quark-engine_<>.deb - - -Get The Automatically Created Package -"""""""""""""""""""""""""""""""""""""" - -We have automated the above steps with a GitHub CI for convenience. Whenever receiving a pull request or commit, the GitHub CI will create a package automatically. Then, you can get the package with the steps below. - -**Step 1: Navigate to the result page of the GitHub CI** - -Click the ``Actions`` tab on the GitHub page of Quark. - -.. image:: https://i.imgur.com/tpBB18r.png - - -Click the ``Kali Package CI`` workflow in the left sidebar. - -.. image:: https://i.imgur.com/kAYOHdO.png - - -**Step 2: Download the Kali package of the specific PR or commit** - -Click the pull request or commit you want. - -.. image:: https://i.imgur.com/8bJkcAa.png - - -Download the ``kali-package`` artifact in the Artifacts area. - -.. image:: https://i.imgur.com/rlfiBI4.png - - -Decompress the downloaded Zip file to get the package. - diff --git a/docs/source/dev_index.rst b/docs/source/dev_index.rst deleted file mode 100644 index b477ede66..000000000 --- a/docs/source/dev_index.rst +++ /dev/null @@ -1,11 +0,0 @@ -.. Development chapter frontpage - -Development -=========== - -This chapter explains how to write Quark's code and how to contribute. - -.. toctree:: - - dev - coding_style diff --git a/docs/source/doc.rst b/docs/source/doc.rst deleted file mode 100644 index 2d007c91c..000000000 --- a/docs/source/doc.rst +++ /dev/null @@ -1,25 +0,0 @@ -====================== -Updating Documentation -====================== - -If you want to help update Quark documentation, you can refer to the following command to update. To make documentation -can be read offline, we will reserve the HTML files for users. - -After editing the docs you would like to modify, you can type the following commands to make quark generate -documentation automatically. - -Inside the directory of ``quark-engine/docs/``: - - -Clean the source:: - - $ make clean - -Auto gen the doc:: - - $ sphinx-apidoc -o source ../quark -f - -Build the HTML:: - - $ make html - diff --git a/docs/source/faq.rst b/docs/source/faq.rst deleted file mode 100644 index eafdf815d..000000000 --- a/docs/source/faq.rst +++ /dev/null @@ -1,46 +0,0 @@ - -FAQ -================ - -I have some questions. Where can I ask? ---------------------------------------- - -We welcome you to post your questions on our GitHub repository or our Telegram. We'll try our best to answer your questions as soon as possible, but not be instant since we're focusing on adding new features into Quark-Engine! -Also, please understand that we may not answer questions about personal information since we want to keep them as our privacy. - -I got an error while using Quark-Engine. What can I do? -------------------------------------------------------- - -Please use ``pip3 install quark-engine --upgrade`` to update your Quark-Engine and use ``freshquark`` to update rules first, then inspect if there are misspellings in the command. -Here are two common errors that will occur. If those errors happened to you too, please check out the following information. - - -#. Errors on arguments (Reference to issue `#239 `_\ ): This type of error is usually caused by an outdated version of packages. Please update Quark Engine and the related python package first, then check if the problem still exists. -#. Errors on rules not found (Reference to `issue #237 `_\ ): Please update Quark-Rule with ``freshquark`` first. Since the way to specify rules is by adding ```` as an argument, you need to input ```` if the rule file is not in the current folder. If you want to select one of the rules of Quark-Rule, the default path to Quark-Rule is ``$HOME/.quark-engine/quark-rules/``. - - -How do threshold, score, and weight work in Quark Engine? ------------------------------------------------------------- - -About those details, we have a video to explain how it works. You can check out the video on YouTube: -https://www.youtube.com/watch?v=SOH4eqrv9_g - -Why do scores remain the same in all the analyses? ---------------------------------------------------- - -The default value is one since we would like users to define these numbers themselves, and we are still doing experiments to adjust the numbers. - -How can I write a rule? ------------------------ - -We have a detailed introduction to add rules. You can check it out `here `_. - -How can I contribute my rules? ------------------------------- - -Feel free to make a pull request on the `Quark-Rule repository `_. We appreciate your contribution to Quark-Engine! - -Can I take part and contribute to Quark? ----------------------------------------- - -That's a big YES! We welcome anyone interested of Quark-Engine. Please check out our `development document `_ and join our Telegram. diff --git a/docs/source/index.rst b/docs/source/index.rst index e98102f89..9db6de007 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -18,28 +18,6 @@ This guide will explain how to set up Quark, use it, and customize it. :maxdepth: 2 :caption: Contents: + malware_report install_index - quark_script - quark_script_visualization - quark_mit_program - quark_agent - quark_reports - quark_rules - addRules - rule_generation integration - dev_index - contribution - organization - doc - quark_method_reference - quark_inside_index - modules - faq - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/docs/source/quark_rules.rst b/docs/source/malware_report.rst similarity index 99% rename from docs/source/quark_rules.rst rename to docs/source/malware_report.rst index 942a88111..4633a2e99 100644 --- a/docs/source/quark_rules.rst +++ b/docs/source/malware_report.rst @@ -1,6 +1,6 @@ -########### -Quark Rules -########### +##################################### +Quark Android Malware Analysis Report +##################################### New Quark Rules For DroidKungFu =============================== diff --git a/docs/source/modules.rst b/docs/source/modules.rst deleted file mode 100644 index 8a06a7dc3..000000000 --- a/docs/source/modules.rst +++ /dev/null @@ -1,7 +0,0 @@ -quark -===== - -.. toctree:: - :maxdepth: 4 - - quark diff --git a/docs/source/organization.rst b/docs/source/organization.rst deleted file mode 100644 index f70855673..000000000 --- a/docs/source/organization.rst +++ /dev/null @@ -1,302 +0,0 @@ -++++++++++++ -Organization -++++++++++++ - -Quark Core Library Team -======================= - -The Quark Core Library Team is responsible for developing and maintaining the core library of Quark, including developing and maintaining the Rizin-based and Radare2-based core library and defining processes for resolving core library issues. The goal is to build accurate and stable core libraries and to ensure the core libraries are continually updated. By leveraging the core libraries, Quark delivers reliable intelligence. - -Core Library Team Operation Mechanism --------------------------------------- - -.. image:: https://i.imgur.com/DAUlAAW.png - -The team focuses on developing, maintaining, and enhancing the core libraries, with efforts in three dimensions: **issue resolution**, **steady updates**, and **new feature development**. - -For **issue resolution**, they first evaluate the issue of the core library. Next, they report it to the relevant projects (Rizin, Radare2, or Quark) and push for fixes. Then, they ensure that the new core library meets the release criteria. Finally, they publish it in the next Quark release. If the community reports a new issue, they start the process again. - -For **steady updates**, they first develop a new version of the core library for the Rizin or Radare2 release. Then, they ensure that the new core library meets the release criteria. Finally, they publish it in the next Quark release. If Rizin or Radare2 publish a new release, they start the process again. - -For **new feature development**, they first discuss whether to accept the new feature. Next, they develop a new version of the core library to support the feature. Then, they ensure that the new core library meets the release criteria. Finally, they publish it in the next Quark release. If the community proposes a new feature, they start the process again. - -The core library team will follow these processes to ensure the constant renovation and strengthening of the core library. Consequently, the core library achieves the goals of accuracy, stability, and continuous updating. - -2024 Core Library Team Plan ---------------------------- - -* **The 1st Quarter** - We will develop the core library release criteria, define the process of resolving core library issues, and publish a beta release of the Rizin/Radare2 core library. - -* **The 2nd Quarter** - We will develop an automated evaluation process for core library releases using GitHub CI and publish a pre-release of the Rizin/Radare2 core library. - -* **The 3rd Quarter** - We will develop the selection criteria of Quark's main core library and publish a formal release of the Rizin/Radare2 core library. - -* **The 4th Quarter** - We will replace the main core library and resolve the issues on tools integrating Quark because of the replacement. - -Process for Resolving Core Library Issues ------------------------------------------ - -When the team receives a core library issue, they resolve it as below. - -.. image:: https://i.imgur.com/5nPnQwJ.png - -Quark Script Team -================== - -The Quark Script Team is dedicated to the continual improvement of the Quark Script API. Our mission encompasses the development, maintenance, and enhancement of the API, documentation, and Quark Script Repo. We focus on developing methodologies for effective auditing and optimization, aiming to make the Quark Script API user-friendly, practical, and easily comprehensible for developers, contributors, and users. - -Quark Script Team Operation Mechanism --------------------------------------- - -.. image:: https://i.imgur.com/vHcYmPZ.png - - -Our approach integrates development, maintenance, and optimization of the Quark Script API. This comprehensive strategy covers both coding and documentation aspects. - -* Code Aspect: - - Development & Maintenance: We start by focusing on the development and regular upkeep of the Quark Script API. - - Audit & Optimize: Following development, we conduct thorough audits and apply optimization techniques to enhance quality. - - Practical Application: We identify areas for further refinement in real-world applications and circle back to development for continuous improvement. - -* Documentation Aspect: - - Authoring: Initial efforts involve creating clear and detailed API documentation. - - Audit & Optimize: Similar to code, we audit and optimize the documentation to ensure its quality and readability. - - Practical Application: Feedback from practical application helps us pinpoint areas for improvement in documentation, leading to subsequent revisions and enhancements. - -2024 Quark Script Team Plan ---------------------------- - -* Q1: Audit and Optimization - Focus on developing and refining audit and optimization methodologies for both the Quark Script API code and its documentation. - Implement a complete cycle of these methodologies to ensure the highest standards. - -* Q2: Development, Maintenance, and Documentation Enhancement - Post-audit, emphasize further development and maintenance of the Quark Script API. - Apply lessons from the audit phase to refine our development and documentation practices. - -* Q3: Practical Application and Feedback Integration - Engage in real-world application scenarios to identify unseen challenges. - Utilize these insights for targeted development and documentation enhancements. - -* Q4: Comprehensive Review and Strategy Refinement - Review the year's methodologies and outcomes, focusing on development, maintenance, practical application, and auditing processes. - Use these insights to refine our overall approach, ensuring continuous improvement and alignment with user needs. - This revised version aims to eliminate redundancy, clarify processes, and provide a more structured approach to the Quark Script Team's operations and plans. - -Quark triage team -================= - -The Quark triage team handles more than just triage. They are the managers of the Quark organization. They define processes for handling issues/PRs, manage Quark releases. And the most important of all, they communicate with community members. - -Responsibilities ----------------- -``Version: v1.0`` - -* Management of issues within the Quark Github organization, including: - - Review, close issues and apply appropriate labels for issues. - - Resolve minor issues (typo, usage problem, ask about the Quark’s techniques). - - Initiate a discussion with other members if the issues are major changes. - - Define and revise the process for handling issues. - -* Management of PRs within the Quark Github organization, including: - - Review, merging PRs and applying appropriate labels for PRs. - - Initiate a discussion with other members if the PRs are major changes. - - Define and revise the process for handling PRs. - -* Management of Quark releases on Kali/PyPi/Github, including: - - Generate and create releases. - - Test releases. - - Define and revise the process and determine the content for releases. - -Triage process ---------------- -``Version: v1.1`` - -When Quark received an issue, the triage process is as below: - -.. image:: https://i.imgur.com/iFFqcYx.png - -.. note:: - **If the issue is unable to reproduce, and the issue raiser hasn't responded.** - - - **Over one month**, the assignee should apply the label ``more-info-require`` to the issue and ask for more information. - - **Over two months**, the assignee should apply the label ``invalid`` to the issue and close it. - -When Quark received a PR, the triage process is as below: - -.. image:: https://i.imgur.com/jEkZSV8.png - - -Release process ----------------- - -``Version: v2.0`` - -Quark releases a new version every month. To streamline this process, we run a GitHub Actions workflow augmented by LLM, which handles the following tasks automatically: - - -#. Open an issue listing all changes merged since the last release. -#. Create a PR to update the version number and compose the changelog. -#. Generate a release draft. - -The workflow is scheduled to start on the Monday preceding the first Wednesday of each month. On that day, we follow the process below to complete the release. - - -.. image:: https://i.postimg.cc/gYVXBDMp/github-release-drawio-14.png - :target: https://i.postimg.cc/gYVXBDMp/github-release-drawio-14.png - :alt: - - -.. note:: - The release process starts on the Monday preceding the first Wednesday of each month. For example, the process for the **v25.10.1** release starts on **Monday, September 29, 2025**\ , since the following **Wednesday, October 1, 2025**\ , is the first Wednesday of October. - -There are 6 steps in the process: - -**Step 1. (Optional) Manually initiate the workflow for the GitHub release.** - -.. note:: - Normally, this step is unnecessary because the workflow will start automatically. If it fails to start, you can initiate it manually using the method below. - - -Click the ``Actions`` tab on Quark's GitHub page. - -.. image:: https://i.postimg.cc/MHW9J1nc/tpBB18r.png - :target: https://i.postimg.cc/MHW9J1nc/tpBB18r.png - :alt: - - -Click the ``Generate GitHub Release Issue/PR`` workflow in the left sidebar. - - -.. image:: https://i.postimg.cc/7YDJ7Hpn/Screenshot-2025-08-17-11-55-37.png - :target: https://i.postimg.cc/7YDJ7Hpn/Screenshot-2025-08-17-11-55-37.png - :alt: - - -Click the gray ``Run workflow`` button and then the green ``Run workflow`` button. The workflow will create an issue and a PR approximately 5 minutes later. - -.. image:: https://i.postimg.cc/63hhcTMB/Screenshot-2025-08-11-16-07-17.png - :target: https://i.postimg.cc/63hhcTMB/Screenshot-2025-08-11-16-07-17.png - :alt: - - -The issue lists all PRs merged since the last release. - -.. image:: https://i.postimg.cc/MGcGcstT/issue.jpg - :target: https://i.postimg.cc/MGcGcstT/issue.jpg - :alt: - - -And the PR updates the version number and changelog. - -.. image:: https://i.postimg.cc/MKc3FVsB/pr.jpg - :target: https://i.postimg.cc/MKc3FVsB/pr.jpg - :alt: - - -**Step 2. Ensure the issue lists all changes since the last release.** - -If the auto-generated issue omits any changes since the last release, edit the issue manually to include them. To edit the issue, click the ``...`` menu on the right and select ``Edit``. - -.. image:: https://i.postimg.cc/hPM6kKgF/Screenshot-2025-08-12-07-35-15.png - :target: https://i.postimg.cc/hPM6kKgF/Screenshot-2025-08-12-07-35-15.png - :alt: - - -**Step 3. Test whether the new changes work correctly and do not break any features or downstream projects.** - -First, verify that all change listed in the issue works as intended. - -.. image:: https://i.postimg.cc/MGcGcstT/issue.jpg - :target: https://i.postimg.cc/MGcGcstT/issue.jpg - :alt: - -Next, verify that all CI checks for the PR have passed. - -.. image:: https://i.postimg.cc/2CqZ5xDv/cicheck.jpg - :target: https://i.postimg.cc/2CqZ5xDv/cicheck.jpg - :alt: - - -Then, verify that Quark runs correctly in downstream projects such as Jadx and APKLab, and attach the result screenshots to the issue. - -.. image:: https://i.postimg.cc/G2LdFqxG/jadx.jpg - :target: https://i.postimg.cc/G2LdFqxG/jadx.jpg - :alt: - - -**Step 4. Fix the problems caused by the changes.** - -If the changes do not work correctly or break any features or downstream projects, fix the problem. - -**Step 5. Ensure the PR is correct and merge it.** - -The PR should update the version number in: - - -* ``debian/control`` -* ``docs/source/conf.py`` -* ``quark/__init__.py`` - -The PR should update the changelog in: - - -* ``debian/changelog`` - -If the auto-generated PR does not correctly update the version number and changelog, edit them manually by pushing your changes to the branch ``update_version_info_{VERSION_NUMBER}``. For example, if you want to edit the PR for the **v25.8.1** release, push your changes to the branch ``update_version_info_v25.8.1``. - - -.. image:: https://i.postimg.cc/zJtDRMGd/pr-e.jpg - :target: https://i.postimg.cc/zJtDRMGd/pr-e.jpg - :alt: - - -To merge the PR, first click the dropdown button 🔽 and select ``Squash and merge``. - -.. image:: https://i.postimg.cc/4x2SLwGp/merge-pr-1.jpg - :target: https://i.postimg.cc/4x2SLwGp/merge-pr-1.jpg - :alt: - - -Next, click the ``Squash and merge`` button. - -.. image:: https://i.postimg.cc/T3Bc5sGN/merge-pr-2.jpg - :target: https://i.postimg.cc/T3Bc5sGN/merge-pr-2.jpg - :alt: - - -Verify the commit message. Then, click the ``Confirm squash and merge`` button to complete the merge. - -.. image:: https://i.postimg.cc/hPyscjYB/merge-pr-3.jpg - :target: https://i.postimg.cc/hPyscjYB/merge-pr-3.jpg - :alt: - - -**Step 6. Ensure the release draft is accurate and publish it.** - -Click the ``Releases`` link on Quark’s GitHub page, and you can see the auto-generated release draft. - -.. image:: https://i.postimg.cc/SN6XftWt/release-01.jpg - :target: https://i.postimg.cc/SN6XftWt/release-01.jpg - :alt: - - -Click the pencil button. - -.. image:: https://i.postimg.cc/X7GmnSx4/Screenshot-2025-08-12-07-47-19-1.png - :target: https://i.postimg.cc/X7GmnSx4/Screenshot-2025-08-12-07-47-19-1.png - :alt: - - -If the auto-generated release draft cannot accurately describe the changes, edit it manually to provide a precise description. You can edit the release draft in the ``Write`` tab. - -.. image:: https://i.postimg.cc/pTrkkz6R/Screenshot-2025-08-12-07-48-19.png - :target: https://i.postimg.cc/pTrkkz6R/Screenshot-2025-08-12-07-48-19.png - :alt: - - -To publish the release, click the ``Publish release`` button. - -.. image:: https://i.postimg.cc/c1gGLn4p/Screenshot-2025-08-12-07-48-56.png - :target: https://postimg.cc/c6SbD63h - :alt: Screenshot-2025-08-12-07-48-56.png diff --git a/docs/source/quark.agent.rst b/docs/source/quark.agent.rst deleted file mode 100644 index 09056dfd2..000000000 --- a/docs/source/quark.agent.rst +++ /dev/null @@ -1,45 +0,0 @@ -quark.agent package -=================== - -Submodules ----------- - -quark.agent.agentTools module ------------------------------ - -.. automodule:: quark.agent.agentTools - :members: - :undoc-members: - :show-inheritance: - -quark.agent.prompts module --------------------------- - -.. automodule:: quark.agent.prompts - :members: - :undoc-members: - :show-inheritance: - -quark.agent.quarkAgent module ------------------------------ - -.. automodule:: quark.agent.quarkAgent - :members: - :undoc-members: - :show-inheritance: - -quark.agent.quarkAgentWeb module --------------------------------- - -.. automodule:: quark.agent.quarkAgentWeb - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: quark.agent - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/quark.core.axmlreader.rst b/docs/source/quark.core.axmlreader.rst deleted file mode 100644 index 5973c3ec8..000000000 --- a/docs/source/quark.core.axmlreader.rst +++ /dev/null @@ -1,10 +0,0 @@ -quark.core.axmlreader package -============================= - -Module contents ---------------- - -.. automodule:: quark.core.axmlreader - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/quark.core.interface.rst b/docs/source/quark.core.interface.rst deleted file mode 100644 index b71db648a..000000000 --- a/docs/source/quark.core.interface.rst +++ /dev/null @@ -1,21 +0,0 @@ -quark.core.interface package -============================ - -Submodules ----------- - -quark.core.interface.baseapkinfo module ---------------------------------------- - -.. automodule:: quark.core.interface.baseapkinfo - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: quark.core.interface - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/quark.core.rst b/docs/source/quark.core.rst deleted file mode 100644 index c467185c7..000000000 --- a/docs/source/quark.core.rst +++ /dev/null @@ -1,71 +0,0 @@ -quark.core package -================== - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - quark.core.axmlreader - quark.core.interface - quark.core.struct - -Submodules ----------- - -quark.core.analysis module --------------------------- - -.. automodule:: quark.core.analysis - :members: - :undoc-members: - :show-inheritance: - -quark.core.apkinfo module -------------------------- - -.. automodule:: quark.core.apkinfo - :members: - :undoc-members: - :show-inheritance: - -quark.core.parallelquark module -------------------------------- - -.. automodule:: quark.core.parallelquark - :members: - :undoc-members: - :show-inheritance: - -quark.core.quark module ------------------------ - -.. automodule:: quark.core.quark - :members: - :undoc-members: - :show-inheritance: - -quark.core.rzapkinfo module ---------------------------- - -.. automodule:: quark.core.rzapkinfo - :members: - :undoc-members: - :show-inheritance: - -quark.core.r2apkinfo module ---------------------------- - -.. automodule:: quark.core.r2apkinfo - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: quark.core - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/quark.core.struct.rst b/docs/source/quark.core.struct.rst deleted file mode 100644 index d1e20e14e..000000000 --- a/docs/source/quark.core.struct.rst +++ /dev/null @@ -1,53 +0,0 @@ -quark.core.struct package -========================= - -Submodules ----------- - -quark.core.struct.bytecodeobject module ---------------------------------------- - -.. automodule:: quark.core.struct.bytecodeobject - :members: - :undoc-members: - :show-inheritance: - -quark.core.struct.methodobject module -------------------------------------- - -.. automodule:: quark.core.struct.methodobject - :members: - :undoc-members: - :show-inheritance: - -quark.core.struct.registerobject module ---------------------------------------- - -.. automodule:: quark.core.struct.registerobject - :members: - :undoc-members: - :show-inheritance: - -quark.core.struct.ruleobject module ------------------------------------ - -.. automodule:: quark.core.struct.ruleobject - :members: - :undoc-members: - :show-inheritance: - -quark.core.struct.tableobject module ------------------------------------- - -.. automodule:: quark.core.struct.tableobject - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: quark.core.struct - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/quark.evaluator.rst b/docs/source/quark.evaluator.rst deleted file mode 100644 index 73d90932c..000000000 --- a/docs/source/quark.evaluator.rst +++ /dev/null @@ -1,21 +0,0 @@ -quark.evaluator package -======================= - -Submodules ----------- - -quark.evaluator.pyeval module ------------------------------ - -.. automodule:: quark.evaluator.pyeval - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: quark.evaluator - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/quark.forensic.rst b/docs/source/quark.forensic.rst deleted file mode 100644 index 66f007636..000000000 --- a/docs/source/quark.forensic.rst +++ /dev/null @@ -1,29 +0,0 @@ -quark.forensic package -====================== - -Submodules ----------- - -quark.forensic.forensic module ------------------------------- - -.. automodule:: quark.forensic.forensic - :members: - :undoc-members: - :show-inheritance: - -quark.forensic.vt\_analysis module ----------------------------------- - -.. automodule:: quark.forensic.vt_analysis - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: quark.forensic - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/quark.rst b/docs/source/quark.rst deleted file mode 100644 index 7875fbea5..000000000 --- a/docs/source/quark.rst +++ /dev/null @@ -1,83 +0,0 @@ -quark package -============= - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - quark.agent - quark.core - quark.evaluator - quark.forensic - quark.script - quark.utils - quark.webreport - -Submodules ----------- - -quark.cli module ----------------- - -.. automodule:: quark.cli - :members: - :undoc-members: - :show-inheritance: - -quark.config module -------------------- - -.. automodule:: quark.config - :members: - :undoc-members: - :show-inheritance: - -quark.freshquark module ------------------------ - -.. automodule:: quark.freshquark - :members: - :undoc-members: - :show-inheritance: - -quark.logo module ------------------ - -.. automodule:: quark.logo - :members: - :undoc-members: - :show-inheritance: - -quark.radiocontrast module --------------------------- - -.. automodule:: quark.radiocontrast - :members: - :undoc-members: - :show-inheritance: - -quark.report module -------------------- - -.. automodule:: quark.report - :members: - :undoc-members: - :show-inheritance: - -quark.rulegeneration module ---------------------------- - -.. automodule:: quark.rulegeneration - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: quark - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/quark.script.frida.rst b/docs/source/quark.script.frida.rst deleted file mode 100644 index d117e16ad..000000000 --- a/docs/source/quark.script.frida.rst +++ /dev/null @@ -1,10 +0,0 @@ -quark.script.frida package -========================== - -Module contents ---------------- - -.. automodule:: quark.script.frida - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/quark.script.rst b/docs/source/quark.script.rst deleted file mode 100644 index 268d4b36a..000000000 --- a/docs/source/quark.script.rst +++ /dev/null @@ -1,45 +0,0 @@ -quark.script package -==================== - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - quark.script.frida - -Submodules ----------- - -quark.script.ares module --------------------------- - -.. automodule:: quark.script.ares - :members: - :undoc-members: - :show-inheritance: - -quark.script.objection module ------------------------------ - -.. automodule:: quark.script.objection - :members: - :undoc-members: - :show-inheritance: - -quark.script.utils module -------------------------- - -.. automodule:: quark.script.utils - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: quark.script - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/quark.utils.rst b/docs/source/quark.utils.rst deleted file mode 100644 index be064f7b0..000000000 --- a/docs/source/quark.utils.rst +++ /dev/null @@ -1,69 +0,0 @@ -quark.utils package -=================== - -Submodules ----------- - -quark.utils.colors module -------------------------- - -.. automodule:: quark.utils.colors - :members: - :undoc-members: - :show-inheritance: - -quark.utils.graph module ------------------------- - -.. automodule:: quark.utils.graph - :members: - :undoc-members: - :show-inheritance: - -quark.utils.output module -------------------------- - -.. automodule:: quark.utils.output - :members: - :undoc-members: - :show-inheritance: - -quark.utils.pprint module -------------------------- - -.. automodule:: quark.utils.pprint - :members: - :undoc-members: - :show-inheritance: - -quark.utils.regex module ------------------------- - -.. automodule:: quark.utils.regex - :members: - :undoc-members: - :show-inheritance: - -quark.utils.tools module ------------------------- - -.. automodule:: quark.utils.tools - :members: - :undoc-members: - :show-inheritance: - -quark.utils.weight module -------------------------- - -.. automodule:: quark.utils.weight - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: quark.utils - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/quark.webreport.rst b/docs/source/quark.webreport.rst deleted file mode 100644 index 65ee48a79..000000000 --- a/docs/source/quark.webreport.rst +++ /dev/null @@ -1,21 +0,0 @@ -quark.webreport package -======================= - -Submodules ----------- - -quark.webreport.generate module -------------------------------- - -.. automodule:: quark.webreport.generate - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: quark.webreport - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/quark_agent.rst b/docs/source/quark_agent.rst deleted file mode 100644 index f51b3c6e8..000000000 --- a/docs/source/quark_agent.rst +++ /dev/null @@ -1,633 +0,0 @@ -########### -Quark Agent -########### - -Introducing Quark's new member, Quark Agent, the AI assistant in the Quark team. This agent lets users perform Quark analysis using natural language, eliminating the need for scripting expertise or terminal commands, which makes the analysis simple and user-friendly. - -Quark Agent integrates with LangChain, using OpenAI's large language model to act as a bridge between the natural language and the Quark/Quark Script APIs. LangChain defines these APIs as tools that large language models can understand and use. This means users can run Quark analysis using natural language by simply adding new tools as needed. - -Below are showcases of using Quark Agent for vulnerability and malware analysis. - -********************** -Vulnerability Analysis -********************** - -Showcase: Detecting CWE-798 with Quark Agent ---------------------------------------------------- - -This example uses Quark Agent to detect `CWE-798 `__ vulnerability in `ovaa.apk `__. See the details below. - -Quick Start -~~~~~~~~~~~ - -1. Clone the repository: - - .. code-block:: - - git clone https://github.com/quark-engine/quark-script.git - -2. Install the required packages: - - .. code-block:: - - pip install -r requirements.txt - -3. Add your OpenAI API key in quarkScriptAgent.py. - - .. code-block:: python - - os.environ["OPENAI_API_KEY"] = {your API Key} - -4. Run the script: - - .. code-block:: - - python quarkScriptAgent.py - -5. Result: - -.. image:: https://github.com/user-attachments/assets/9c8ba9d3-c8b5-4583-8cb8-750f8c3bf2a7 - - -Decode the Prompts -~~~~~~~~~~~~~~~~~~ - -Here are two prompts, each for executing different analysis processes. - -.. code:: TEXT - - 1st Prompt: Initialize the rule instance with the rule path set to "constructCryptoGraphicKey.json" - -Used Quark Script APIs/Tools that LLM used: ``loadRule`` - -.. code:: TEXT - - 2nd Prompt: Run Quark Analysis using the rule instance on the apk sample "ovaa.apk", - and Check if the parameters are hard-coded. If yes, display the hard-coded values. - -Used Quark Script APIs/Tools that LLM used: ``runQuarkAnalysis``, -``getBehaviorOccurList``, ``getParameterValues`` and ``isHardCoded`` - -The ``loadRule``, ``runQuarkAnalysis``, ``getBehaviorOccurList``, -``getParameterValues``, and ``isHardCoded`` functions are treated as -**tools** within LangChain, enabling them to be invoked through the -``gpt-4o`` model to analyze and identify -`CWE-798 `__ vulnerabilities in the `ovaa.apk `__ sample. - -.. image:: https://hackmd.io/_uploads/BkplMjvYR.png - - -Showcase: Generating Quark Script with Quark Agent ---------------------------------------------------------- - -Quark Agent allows you to automate the creation of Quark Script code. This lets users concentrate on designing the detection process, while the LLM and Quark Script API handle the coding. This approach greatly enhances efficiency and streamlines the workflow. - -Here's an example for generating a Quark Script to detect CWE-798. - -Demo Video -~~~~~~~~~~ - -.. raw:: html - - - - - -Decode the Prompts -~~~~~~~~~~~~~~~~~~ - -Now, let's instruct Quark Agent to detect CWE-798 and write the Quark Script for the detection process using the following prompt. - -**Assign a role to the Agent** - -To make Quark Agent's responses more precise and relevant to vulnerability detection, we assign it the role of an Android APK vulnerability analyst. - -.. code-block:: TEXT - - User: - Now you are an Android APK vulnerability analyst. Please follow the steps below to analyze a sample. - -.. code-block:: TEXT - - Agent: - Sure, I'd be happy to help with that. Please provide the sample APK file and the detection rule file that you would like to use for the analysis. - - -**Instruct the detection process** - -Instruct Quark Agent to detect CWE-798 using the following detection process. - -.. code-block:: TEXT - - Detection Process: - 1. Define the behavior "Construct Cryptographic Key" in the rule instance. - 2. Run Quark Analysis using the rule instance on the APK sample. - 3. Obtain all instances of detected behaviors from the Quark Analysis results. - 4. Retrieve the parameter values for each occurred behavior. - 5. Check if any parameters are hard-coded. If found, print the hard-coded parameters. - -.. - -.. note:: - - The prompt will include details like the sample or rule path. - - - -1. Define the behavior "Construct Cryptographic Key" in the rule instance. - -.. code-block:: TEXT - - User: - 1. Define the behavior "Construct Cryptographic Key" in the rule instance, with the rule path set to "constructCryptoGraphicKey.json". - - -.. code-block:: TEXT - - Agent: - The behavior "Construct Cryptographic Key" has been successfully defined in the rule instance with the rule path set to "constructCryptoGraphicKey.json". How would you like to proceed? - - -2. Run Quark Analysis using the rule instance on the APK sample. - -.. code-block:: TEXT - - User: - 2. Run Quark Analysis using the rule instance on the APK sample "ovaa.apk". - - -.. code-block:: TEXT - - Agent: - The Quark analysis on the APK sample "ovaa.apk" has been completed successfully. What would you like to do next? - - -3. Obtain all instances of detected behaviors from the Quark Analysis results. - -.. code-block:: TEXT - - User: - 3. Obtain all instances of detected behaviors from the Quark Analysis results in the sample "ovaa.apk". - - -.. code-block:: TEXT - - Agent - I have obtained all instances of detected behaviors from the Quark Analysis results in the sample "ovaa.apk". If you need further details or specific information about these behaviors, please let me know! - - -4. Retrieve the parameter values for each occurred behavior. - -.. code-block:: TEXT - - User: - 4. Retrieve the parameter values for each occurred behavior. - - -.. code-block:: TEXT - - Agent: - The parameter values for the occurred behavior are: - 1. "49u5gh249gh24985ghf429gh4ch8f23f" - 2. "AES" - - Would you like to check if any of these values are hard-coded? - - -5. Check if any parameters are hard-coded. If found, print the hard-coded parameters. - -.. code-block:: TEXT - - User: - 5. Check if any parameter values are hard-coded. If yes, display the hard-coded values. - - -.. code-block:: TEXT - - Agent: - The following parameter values are hard-coded: - - 1. `49u5gh249gh24985ghf429gh4ch8f23f` - 2. `AES` - - -**Generate Quark Script** - -Finally, ask Quark Agent to write and execute the Python code based on the detection process outlined above. - -.. code-block:: TEXT - - User: - Using the Quark Script API, implement the above logic in Python and save it to 'detectCWE798.py', with the rule path set to 'constructCryptoGraphicKey.json' and the sample path to 'ovaa.apk'. - - -.. code-block:: TEXT - - Agent: - The code has been written to `detectCWE798.py`. You can now execute this script to perform the analysis. - - -Here is the generated code: - -.. code-block:: python - - from quark.script import Rule, runQuarkAnalysis - - # Load the rule - rule_path = 'constructCryptoGraphicKey.json' - rule_instance = Rule(rule_path) - - # Define the sample path - sample_path = 'ovaa.apk' - - # Run the Quark analysis - quark_result = runQuarkAnalysis(sample_path, rule_instance) - - # Extract the behavior occurrence list - behavior_occur_list = quark_result.behaviorOccurList - - # Iterate through each behavior and get parameter values - for behavior in behavior_occur_list: - param_values = behavior.getParamValues() - for param in param_values: - # Check if the parameter value is hardcoded - is_hardcoded = quark_result.isHardcoded(param) - if is_hardcoded: - print(f'Hardcoded value found: {param}') - - -.. code-block:: TEXT - - User: - Execute detectCWE798.py - - -Here is the result. - -.. code-block:: shell - - Hardcoded value found: 49u5gh249gh24985ghf429gh4ch8f23f - Hardcoded value found: AES - - -We added 2 tools, ``writeCodeInFile`` and ``executeCode`` , to enable Quark Agent to generate and execute Quark Script code. - -.. image:: https://github.com/user-attachments/assets/d8fd805a-86c9-4eff-b120-d340fc43d792 - - -.. note:: - 1. The code is generated by OpenAI's GPT model, and the output may not always match the documentation exactly. - 2. Since LangChain currently does not support passing Python - instances between tools, we are temporarily using global variables - to pass parameters between tools in ``quarkScriptAgent.py``. - 3. Place the rules, samples, and ``quarkScriptAgent.py`` in the same - folder; the LLM will automatically find files with matching names. - 4. A web GUI is under construction, please stay tuned! - -**************** -Malware Analysis -**************** - -Showcase: Generate Summary Report with Quark Agent --------------------------------------------------- - -This example uses Quark Agent to analyze `ovaa.apk `__ and generate a :ref:`summary report `. See the details below. - -Quick Start -~~~~~~~~~~~ - -1. Install Quark Agent: - - .. code-block:: shell - - git clone https://github.com/quark-engine/quark-engine.git & cd quark-engine - pip install .[QuarkAgent] - -2. Prepare the rule and the sample: - - .. code-block:: shell - - git clone https://github.com/quark-engine/quark-script - cd quark-script - -3. Add your OpenAI API key to the environment: - - .. code-block:: python - - export OPENAI_API_KEY='your-api-key-here' - -4. Run Quark Agent: - - .. code-block:: shell - - quark-agent - -5. Result: - -.. image:: https://github.com/user-attachments/assets/46407664-de0d-4849-8995-642ff636d71e - - -Decode the Prompts -~~~~~~~~~~~~~~~~~~ - -Here, we explain what happens after running Quark Agent. - -**Preset Prompt** - -To ensure the ``gpt-4o-mini`` model follows the correct format of a summary report, we designed the following preset prompt and hard-coded it into Quark Agent. - -When Quark Agent starts, it will automatically pass the preset prompt to the ``gpt-4o-mini`` model. Hence, we don't need to pass this prompt manually. - -.. code:: TEXT - - Preset Prompt: - - When prompted to provide a summary report, follow these rules and the summary report example: - - 1. Print a newline character first to prevent formatting issues. - 2. Change "" in "WARNING: " to the risk level with the first letter of each word capitalized. - 3. Change "" in "Total Score: " to the total score, expressed as a decimal numeral. - 4. Without using a code block, place the output of the tool, getSummaryReportTable, in the line directly after "Total Score: ". - - The Summary Report Example: - - [!] WARNING: - [*] Total Score: - +--------------------------------+-----------------------------+------------+-------+--------+ - | Filename | Rule | Confidence | Score | Weight | - +--------------------------------+-----------------------------+------------+-------+--------+ - | constructCryptoGraphicKey.json | Construct cryptographic key | 100% | 1 | 1.0 | - +--------------------------------+-----------------------------+------------+-------+--------+ - - Ensure you adhere to these rules and the example when providing a summary report. - -**User Prompts** - -Then, by passing the following prompt manually, we ask Quark Agent to analyze the `ovaa.apk `__ sample and generate a summary report. - -.. code:: TEXT - - 1st Prompt: Analyze the sample “ovaa.apk” using Quark and the rule “constructCryptoGraphicKey.json.” - After the analysis, print the summary report. - -Used Quark APIs/Tools that LLM used: ``initRuleObject``, ``initQuarkObject``, ``runQuarkAnalysisForSummaryReport``, ``getSummaryReportTable``, ``getAnalysisResultRisk``, and ``getAnalysisResultScore`` - -To highlight the analysis result, we ask Quark Agent to colorize the summary report. - -.. code:: TEXT - - 2nd Prompt: Colorize "[!]" in yellow, "[*]" in cyan, the "Rule" column and its data in green, - the "Confidence" column and its data in yellow, and the "Weight" column and its data in red. - -Used Quark APIs/Tools that LLM used: ``colorizeInYellow``, ``colorizeInCyan``, ``colorizeInGreen``, and ``colorizeInRed`` - - - -All APIs above are treated as tools within LangChain, enabling them to be invoked through the ``gpt-4o-min`` model to analyze the `ovaa.apk `__ sample and generate a colorized summary report. - -.. image:: https://github.com/user-attachments/assets/656e8dcb-b0b6-4b02-bc06-58b2b01d054b - -Showcase: Enhance Summary Report with Quark Agent ----------------------------------------------------- - -Quark Agent can enhance the summary report by refining Quark's risk assessment mechanism. With user instructions, it can adjust the scores, weights, and risk of the sample based on its understanding of Quark analysis and rules, enabling users to identify high-risk samples and locate critical behaviors accurately. - -Here's an example that enhances the summary report of `Ahmyth.apk `__ . - -Demo Video -~~~~~~~~~~ - -.. raw:: html - - - - - -Decode the Prompts -~~~~~~~~~~~~~~~~~~ - -Now, let's explain what happens after running Quark Agent. - -**Generate a summary report** - -We ask Quark Agent to generate a summary report for `Ahmyth.apk `__. - -.. code-block:: TEXT - - User: - Analyze the sample “Ahmyth.apk” using Quark and the rules in the directory “rules.” After the analysis, print the summary report. - -.. code-block:: TEXT - - Agent: - [!] WARNING: High Risk - [*] Total Score: 10 - +------------+---------------------------------------------------------------------------+------------+-------+--------+ - | Filename | Rule | Confidence | Score | Weight | - +------------+---------------------------------------------------------------------------+------------+-------+--------+ - | 00001.json | Initialize bitmap object and compress data (e.g. JPEG) into bitmap object | 100% | 1 | 1.0 | - | 00002.json | Open the camera and take picture | 100% | 1 | 1.0 | - | 00003.json | Put the compressed bitmap data into JSON object | 80% | 1 | 0.5 | - | 00004.json | Get filename and put it to JSON object | 100% | 1 | 1.0 | - | 00005.json | Get absolute path of file and put it to JSON object | 100% | 1 | 1.0 | - | 00006.json | Scheduling recording task | 80% | 1 | 0.5 | - | 00007.json | Use absolute path of directory for the output media file path | 100% | 1 | 1.0 | - | 00008.json | Check if successfully sending out SMS | 100% | 1 | 1.0 | - | 00009.json | Put data in cursor to JSON object | 100% | 1 | 1.0 | - | 00010.json | Read sensitive data(SMS, CALLLOG) and put it into JSON object | 100% | 1 | 1.0 | - +------------+---------------------------------------------------------------------------+------------+-------+--------+ - - -**Assign a role to the agent** - -To make Quark Agent's responses more precise and relevant to malware analysis, we assign it the role of an Android malware analysis expert. - -.. code-block:: TEXT - - User: - As an expert in Android malware analysis, please adjust the values of each rule in the summary report based on my instructions. After each adjustment, update the report and summarize the reason behind the changes as concisely as possible. - -.. code-block:: TEXT - - Agent: - Certainly! Please provide your instructions for adjusting the values of each rule in the summary report. - - -**Enhance the summary report** - -Then, the agent is ready to enhance the summary report. We then ask it to adjust the scores, weights, and the risk of the sample. - -1. Adjust the scores based on the rule descriptions and their combined effects. - -.. code-block:: TEXT - - User: - Evaluate each rule's threat to sensitive data based on their descriptions and combined effects. Then, adjust each rule's score accordingly. Scores range from 0 to 1, with higher values indicating higher threat. - -.. code-block:: TEXT - - Agent: - Based on the evaluation of each rule's threat to sensitive data and their combined effects, here are the adjusted scores: - - 1. **Initialize bitmap object and compress data (e.g. JPEG) into bitmap object** - Score: 0.6 (Moderate threat; potential for data leakage through images) - 2. **Open the camera and take picture** - Score: 0.9 (High threat; direct access to sensitive data through photos) - 3. **Put the compressed bitmap data into JSON object** - Score: 0.7 (Moderate to high threat; data in JSON can be exploited) - 4. **Get filename and put it to JSON object** - Score: 0.5 (Moderate threat; filenames could lead to sensitive data exposure) - 5. **Get absolute path of file and put it to JSON object** - Score: 0.7 (Moderate to high threat; paths may reveal sensitive data locations) - 6. **Scheduling recording task** - Score: 0.9 (High threat; potential for unauthorized audio recording) - 7. **Use absolute path of directory for the output media file path** - Score: 0.6 (Moderate threat; directory paths could expose sensitive file locations) - 8. **Check if successfully sending out SMS** - Score: 0.8 (High threat; sensitive data can be leaked via SMS) - 9. **Put data in cursor to JSON object** - Score: 0.7 (Moderate to high threat; potentially sensitive data could be exposed) - 10. **Read sensitive data(SMS, CALLLOG) and put it into JSON object** - Score: 1.0 (Critical threat; direct access to sensitive data) - - Now let's update the summary report based on these adjusted scores. - - - [!] WARNING: High Risk - [*] Total Score: 8.6 - +------------+---------------------------------------------------------------------------+------------+-------+--------+ - | Filename | Rule | Confidence | Score | Weight | - +------------+---------------------------------------------------------------------------+------------+-------+--------+ - | 00001.json | Initialize bitmap object and compress data (e.g. JPEG) into bitmap object | 100% | 0.6 | 1.0 | - | 00002.json | Open the camera and take picture | 100% | 0.9 | 1.0 | - | 00003.json | Put the compressed bitmap data into JSON object | 80% | 0.7 | 0.5 | - | 00004.json | Get filename and put it to JSON object | 100% | 0.5 | 1.0 | - | 00005.json | Get absolute path of file and put it to JSON object | 100% | 0.7 | 1.0 | - | 00006.json | Scheduling recording task | 80% | 0.9 | 0.5 | - | 00007.json | Use absolute path of directory for the output media file path | 100% | 0.6 | 1.0 | - | 00008.json | Check if successfully sending out SMS | 100% | 0.8 | 1.0 | - | 00009.json | Put data in cursor to JSON object | 100% | 0.7 | 1.0 | - | 00010.json | Read sensitive data(SMS, CALLLOG) and put it into JSON object | 100% | 1.0 | 1.0 | - +------------+---------------------------------------------------------------------------+------------+-------+--------+ - - - **Summary of Changes:** - - Adjusted scores reflect the potential threat to sensitive data based on the rule descriptions and their implications. - - High-risk actions such as accessing the camera and reading sensitive data were assigned higher scores, while actions with a lesser impact, such as initializing bitmap objects, were reduced accordingly. - - The total score is now more representative of the overall risk posed by the application's behavior. - - -2. Adjust the weights based on the confidence values and their definitions. - -.. code-block:: TEXT - - User: - Adjust each rule's weight based on the confidence values and the definitions below. Weights range from 0 to 1. - - The definitions of the confidence values: - - 100%: The sample used all necessary APIs for this behavior, and a related data flow was detected. - - 80%: The sample used all necessary APIs for this behavior but found no related data flow. - - 60%: The sample used all necessary APIs for this behavior but in the wrong order. - - 40%: The sample used only some necessary APIs for this behavior. - - 20%: The sample did not use the necessary APIs but requested relevant permissions. - - -.. code-block:: TEXT - - Agent: - Based on the provided confidence definitions, here are the adjusted weights for each rule: - - 1. **Initialize bitmap object and compress data (e.g. JPEG) into bitmap object** - Weight: 1.0 (100% confidence) - 2. **Open the camera and take picture** - Weight: 1.0 (100% confidence) - 3. **Put the compressed bitmap data into JSON object** - Weight: 0.5 (80% confidence) - 4. **Get filename and put it to JSON object** - Weight: 1.0 (100% confidence) - 5. **Get absolute path of file and put it to JSON object** - Weight: 1.0 (100% confidence) - 6. **Scheduling recording task** - Weight: 0.5 (80% confidence) - 7. **Use absolute path of directory for the output media file path** - Weight: 1.0 (100% confidence) - 8. **Check if successfully sending out SMS** - Weight: 1.0 (100% confidence) - 9. **Put data in cursor to JSON object** - Weight: 1.0 (100% confidence) - 10. **Read sensitive data(SMS, CALLLOG) and put it into JSON object** - Weight: 1.0 (100% confidence) - - Now let's update the summary report based on these adjusted weights. - - - [!] WARNING: High Risk - [*] Total Score: 8.6 - +------------+---------------------------------------------------------------------------+------------+-------+--------+ - | Filename | Rule | Confidence | Score | Weight | - +------------+---------------------------------------------------------------------------+------------+-------+--------+ - | 00001.json | Initialize bitmap object and compress data (e.g. JPEG) into bitmap object | 100% | 0.6 | 1.0 | - | 00002.json | Open the camera and take picture | 100% | 0.9 | 1.0 | - | 00003.json | Put the compressed bitmap data into JSON object | 80% | 0.7 | 0.5 | - | 00004.json | Get filename and put it to JSON object | 100% | 0.5 | 1.0 | - | 00005.json | Get absolute path of file and put it to JSON object | 100% | 0.7 | 1.0 | - | 00006.json | Scheduling recording task | 80% | 0.9 | 0.5 | - | 00007.json | Use absolute path of directory for the output media file path | 100% | 0.6 | 1.0 | - | 00008.json | Check if successfully sending out SMS | 100% | 0.8 | 1.0 | - | 00009.json | Put data in cursor to JSON object | 100% | 0.7 | 1.0 | - | 00010.json | Read sensitive data(SMS, CALLLOG) and put it into JSON object | 100% | 1.0 | 1.0 | - +------------+---------------------------------------------------------------------------+------------+-------+--------+ - - **Summary of Changes:** - - Adjusted weights reflect the confidence values as per the definitions provided. - - Rules with 100% confidence retained the highest weight of 1.0, while those with 80% confidence received a weight of 0.5. - - The total score remains the same, but the weights provide a clearer indication of the reliability of each rule's detection capabilities. - - -3. Reassess the risk of the sample based on the adjusted scores and weights. - -.. code-block:: TEXT - - User: - Recalculate the total score, reassess the risk of the sample, and explain the reason. Finally, update the report. - - -.. code-block:: TEXT - - Agent: - Based on the recalculated total score of **6.6**, the risk assessment remains categorized as **High Risk**. - - **Reasoning:** - - The total score reflects the aggregated threat level based on the adjusted scores and weights. A score of 6.6 indicates a significant potential for sensitive data exposure, especially with key behaviors such as accessing the camera, reading sensitive data, and sending SMS. - - Despite the adjustments, the presence of high-threat actions maintains the sample's classification as high risk. The analysis indicates that the application has behaviors that could lead to serious privacy violations. - - Let's update the summary report accordingly. - - - [!] WARNING: High Risk - [*] Total Score: 6.6 - +------------+---------------------------------------------------------------------------+------------+-------+--------+ - | Filename | Rule | Confidence | Score | Weight | - +------------+---------------------------------------------------------------------------+------------+-------+--------+ - | 00001.json | Initialize bitmap object and compress data (e.g. JPEG) into bitmap object | 100% | 0.6 | 1.0 | - | 00002.json | Open the camera and take picture | 100% | 0.9 | 1.0 | - | 00003.json | Put the compressed bitmap data into JSON object | 80% | 0.7 | 0.5 | - | 00004.json | Get filename and put it to JSON object | 100% | 0.5 | 1.0 | - | 00005.json | Get absolute path of file and put it to JSON object | 100% | 0.7 | 1.0 | - | 00006.json | Scheduling recording task | 80% | 0.9 | 0.5 | - | 00007.json | Use absolute path of directory for the output media file path | 100% | 0.6 | 1.0 | - | 00008.json | Check if successfully sending out SMS | 100% | 0.8 | 1.0 | - | 00009.json | Put data in cursor to JSON object | 100% | 0.7 | 1.0 | - | 00010.json | Read sensitive data(SMS, CALLLOG) and put it into JSON object | 100% | 1.0 | 1.0 | - +------------+---------------------------------------------------------------------------+------------+-------+--------+ - - -Here is the summary report enhanced by Quark Agent. - -.. code-block:: TEXT - - [!] WARNING: High Risk - [*] Total Score: 6.6 - +------------+---------------------------------------------------------------------------+------------+-------+--------+ - | Filename | Rule | Confidence | Score | Weight | - +------------+---------------------------------------------------------------------------+------------+-------+--------+ - | 00001.json | Initialize bitmap object and compress data (e.g. JPEG) into bitmap object | 100% | 0.6 | 1.0 | - | 00002.json | Open the camera and take picture | 100% | 0.9 | 1.0 | - | 00003.json | Put the compressed bitmap data into JSON object | 80% | 0.7 | 0.5 | - | 00004.json | Get filename and put it to JSON object | 100% | 0.5 | 1.0 | - | 00005.json | Get absolute path of file and put it to JSON object | 100% | 0.7 | 1.0 | - | 00006.json | Scheduling recording task | 80% | 0.9 | 0.5 | - | 00007.json | Use absolute path of directory for the output media file path | 100% | 0.6 | 1.0 | - | 00008.json | Check if successfully sending out SMS | 100% | 0.8 | 1.0 | - | 00009.json | Put data in cursor to JSON object | 100% | 0.7 | 1.0 | - | 00010.json | Read sensitive data(SMS, CALLLOG) and put it into JSON object | 100% | 1.0 | 1.0 | - +------------+---------------------------------------------------------------------------+------------+-------+--------+ - -We added the tool ``listDirectory`` to enable Quark Agent access rules in a directory and the tool ``calculateTotalScore`` to recalculate the total score. The entire enhancement of the summary report relies on Quark Agent's understanding of Quark analysis and rules. - -.. image:: https://github.com/user-attachments/assets/3e0dd6a3-b31c-4d85-8f92-3f0a2bc9918b - -.. note:: - 1. The summary report is generated by OpenAI's GPT model and is not always correct. - 2. Since LangChain currently does not support passing Python instances between tools, we temporarily use global variables to pass parameters between tools. - 3. Place the rules and samples in the working directory; the LLM will automatically find the files with matching names. diff --git a/docs/source/quark_inside_index.rst b/docs/source/quark_inside_index.rst deleted file mode 100644 index 90ef33009..000000000 --- a/docs/source/quark_inside_index.rst +++ /dev/null @@ -1,9 +0,0 @@ -Quark-Engine Inside -=================== -This chapter explains how Quark works inside. - -.. toctree:: - - quark_inside_workflow - quark_inside_overview - quark_inside_objects diff --git a/docs/source/quark_inside_objects.rst b/docs/source/quark_inside_objects.rst deleted file mode 100644 index 259a64803..000000000 --- a/docs/source/quark_inside_objects.rst +++ /dev/null @@ -1,270 +0,0 @@ -================================= -Quark-Engine Objects Introduction -================================= - -Dalvik Bytecode Loader(quark.Evaluator.pyeval) -============================================== - -.. image:: https://i.imgur.com/DvVTUok.png - -PyEval, inspired by the ``ceval.c`` design principle in CPython's Interpreter. It -takes python bytecode instructions into an infinite loop and interacts with the -CPU using C language. Thus, we apply this principle to our Dalvik Bytecode -Loader, takes Dalvik's Bytecode instructions, and apply our custom instructions -events to implement tracking whether two function calls operating the same -variable in the fifth crime stage. Of course, we haven't implemented all the -bytecode instructions, and we haven't considered the conditional jump now. - -.. image:: https://i.imgur.com/WNA6ws7.png - -Take Android's bytecode instruction ``invoke-direct`` as an example. When an -instruction ``invoke-direct`` is passed to our Dalvik bytecode loader, it -will enter the PyEval main switch, execute the corresponding ``INVOKE_DIRECT`` -function, and call ``self._invoke()``, here another ``_invoke`` is written for -reuse, because there are many instructions related to ``invoke`` family, such as -``invoke-direct``, ``invoke-virtual``, but the invoke family is the same for -our program implementation. - -.. image:: https://i.imgur.com/hcU6AX0.png - - - - -XRule(quark.Objects.XRule) -========================== - -XRule as an object in the quark-engine responsible for the five-stage -inspection, each APK will initialize an XRule object respectively. - -.. image:: https://i.imgur.com/8Z0ldvq.png - -Explanation of each function ----------------------------- - - * **run**: - - - This function responsible for starting the five-stage inspection. - - * **show_summary_report**: - - - Show the summary report. - - * **show_detail_report**: - - - Show detailed report. - - * **find_previous_method**: - - - Track the previous function of a specific function. - - * **find_intersection**: - - - Find if there is a function of intersection in a given two functions. - - * **check_sequence**: - - - Check if the two function is in order or not. - - * **check_parameter**: - - - Check if the two functions operate on the same variable or not. - -Five-stage inspection ---------------------- - -Each function in this XRul object is used to correspond to the five-stage -inspection, which will be described in order according to the five-stage -inspection. - -Level 1 -^^^^^^^ - -Check whether all permission requirements match the given rules. - -Level 2 -^^^^^^^ - -Check whether all native API functions match the given rules (as long as one of -them is met). - -Level 3 -^^^^^^^ - -Check if the native API functions all match to the given rules (both appear). - -Level 4 -^^^^^^^ - -Check if the native API functions all match to the given rules (both appear in -the order). - -Level 5 -^^^^^^^ - -Check whether the native API functions all match to the given rules (both -appear in the order, and operate on the same variable). - - - - -Apkinfo(quark.Objects.Apkinfo) -============================== - -Apkinfo is an object in Quark-Engine used to store APK information which is -based on ``androguard`` module. - -.. image:: https://i.imgur.com/FlNVZgU.png - -Explanation of each function ----------------------------- - - * **permissions**: - - - Get all permissions required by the APK. - - * **find_method**: - - - Query function name in APK. - - * **upperfunc**: - - - Query the upper-level function call for a given function name in the APK. - - * **get_method_bytecode**: - - - Returns the Android bytecode corresponding to the given function name. - - - - -BytecodeObject(quark.Objects.bytecodeObject) -============================================ - -Bytecodeobject is an object in Quark-Engine that stores information about a -single bytecode command. - -.. image:: https://i.imgur.com/ZIc3A4W.png - -After bytecode generated by ``androguard``, it will look like below. - -============== ========== ================================================ -mnemonic registers parameter -============== ========== ================================================ -invoke-virtual v3 Lcom/google/progress/APNOperator;->deleteAPN()Z -============== ========== ================================================ - -**mnemonic**: mnemonic is a human-readable instruction form compared to the machine -code. - -**registers**: registers used by each line of instructions in the smali -bytecode instruction. They usually express in the form of "v3", "v4". - -**parameter**: is the function or parameter used in the smali bytecode -instruction. - - - - -RuleObject(quark.Objects.ruleobject) -==================================== - -The ruleobject in Quark-Engine will read a ``JSON`` format rule from a given JSON -file, for example, `sendLocation_SMS `_. - -.. image:: https://i.imgur.com/U0Yi0LJ.png - -Explanation of each function ----------------------------- - - * **get_score**: - - - Returns the weight score based on the five stages of malicious behavior. - -TableObject(quark.Objects.tableobject) -====================================== - -The tableobject is used to track the usage of variables in the register. We want -to know whether the same variable is used by the two APIs we have defined in our rule. - -.. image:: https://i.imgur.com/NZAOX6n.png - -In the output of the bytecode instruction generated by ``androguard``, it is -difficult to use a single register to track the usage of the same parameter -being APIs call since the register is often reused by the Dalvik machine. -Therefore, we creat the TableObject to store each RegisterObject in each row. - -Tableobject is composed of multiple registerobjects as below: - -[[registerobject,registerobject,registerobject],[registerobject,registerobject],[registerobject],[],[]] - -Take this bytecode instruction as an example: - -.. code-block:: - - invoke-virtual v2 Landroid/app/PendingIntent;->send()V - -We can know what the v2 register stores, which is used by the send function. - -.. code-block:: - - const-string v2 'gps' - -However, the "v2" register may be overwritten by other values ​​in the future. -As above instruction, the content in v2 becomes "gps" after executing ``const-string v2 'gps'``. - -Therefore, the method we want to track must be reversed. We use the function -call name as the tracker, and record the contents of the current register in -the table. - -Once we encounter a function call, we will check the parameters used by it, -such as the above command invoke-virtual, then find out the current value of -the v2 register, together with the function recorded in the table, assuming v2 -finds the value "hello", the function name and parameter, "hello", will be -recorded in called_by_func column. - -You can take a look to this `Bytecode example `_. With -this table record, we can track all parameter content by each function call. - -Explanation of each function ----------------------------- - - * **insert**: - - - Insert RegisterObject into the nested list in the hashtable. - - * **get_obj_list**: - - - Return the list which contains the RegisterObject. - - * **get_table**: - - - Get the entire hash table. - - * **pop**: - - - Override the built-in pop function, to get the top element, which - is RegisterObject on the stack while not delete it. - - - - -RegisterObject(quark.Objects.registerobject) -============================================ - -RegisterObject is used to record the state of each register. Each initialized -registerobject will have value and called_by_func in a single instance. - -.. image:: https://i.imgur.com/k5nHprC.png - - -========== ================================================= - value called_by_func -========== ================================================= - "GPS" Lcom/google/progress/APNOperator;->deleteAPN()Z -========== ================================================= - -**value**: the value stored in the register. - -**called_by_func**: what functions are called with this register as a parameter. diff --git a/docs/source/quark_inside_overview.rst b/docs/source/quark_inside_overview.rst deleted file mode 100644 index eedfcdb22..000000000 --- a/docs/source/quark_inside_overview.rst +++ /dev/null @@ -1,53 +0,0 @@ -============================= -Quark-Engine Project Overview -============================= - -Quark-Engine Map -================ - -.. image:: https://i.imgur.com/FEZh3SB.png - - -The entire Quark-Engine project can be composed of four major parts, namely - -* Five-stage rule -* Dalvik Bytecode Loader -* Scoring System -* Self-define objects data structure - - -Quark module architecture diagram -================================= - -.. image:: https://i.imgur.com/8B2oV7c.png - -The project is divided into three main folders. - -Objects -------- - -.. image:: https://i.imgur.com/sw5q0Qn.png - -The Objects directory is used to store all the main self define objects, -including APK information object, Bytecode object, rule object, variable -tracking table object, variable object, and five-stage rule object. - -Evaluator ---------- - -.. image:: https://i.imgur.com/yinL9P3.png - -The Evaluator directory is used to store the Dalvik Bytecode Loader. The name -comes from the CPython virtual machine used to execute the python bytecode. The -Bytecode Loader itself is a huge switch. When the corresponding Bytecode -instruction is given, our customized function event will be executed. However, -the bytecode instruction does not interact with the CPU, so it is faster than -executing Android DEX files dynamically. - -utils ------ - -.. image:: https://i.imgur.com/O6w93vs.png - -The utils directory is used to store repetitive tool code, print output -control, and weighted score calculations. diff --git a/docs/source/quark_inside_workflow.rst b/docs/source/quark_inside_workflow.rst deleted file mode 100644 index 25f72e719..000000000 --- a/docs/source/quark_inside_workflow.rst +++ /dev/null @@ -1,190 +0,0 @@ -===================== -Quark-Engine Workflow -===================== - -.. image:: https://i.imgur.com/xN4js5P.png - - - -Quark-Engine Step 1(Command Line) -================================= - -``quark.cli`` is the entry point of the program, and it will initialize the ``XRule`` -object and the ``RuleObject`` object according to the given APK file -and JSON rules, and create ``quark.utils.weight`` object at the end to -calculate the weighted score, finally, display the report according to ``-s`` -or ``-d``. No matter whether you choose the detail report or the summary -report, a full analysis will be run. The difference is that the report display -is different. - -.. image:: https://i.imgur.com/QZOMJSY.png - -Quark-Engine through the command interface to execute malware analysis like below: - -Summary Report:: - - $ quark -a malware.apk -s - -Detail Report:: - - $ quark -a malware.apk -d - -The Quark-Engine will start from the ``quark.cli`` module, which is our first step in the above image.:: - - -a specifies an apk file - -r will specify a rule directory - -s for summary report - -d for detail report - - - - -Quark-Engine Step 2 (APK Information Extract) -============================================= - -In step 2, we will extract the information we want from the given APK file, -such as the permission request list, what native APIs are called, and with the -help of androguard, we can find the cross-reference method from the given -function name, and also get the Dalvik bytecode instruction. - - - - -Quark-Engine Step 3 (Load JSON Rule) -==================================== - -In step 3, we will traverse each JSON file from the rules folder given by ``-r`` -in the command-line interface, and each JSON file will be considered a five-stage -rule of malicious behavior. - - - - -Quark-Engine Step 4 (Level 1-5 Check) -===================================== - -In step 4, We will follow our custom five-stage crime rules, which are as follows: - -1. Permission requested. -2. Native API call. -3. Certain combination of native API. -4. Calling sequence of native API. -5. APIs that handle the same register. - -Detailed implementation principle, please refer to the ``quark.Objects.xrule``. - - - - -Quark-Engine Step 5 (Weighted Score Calculation) -================================================ - -In step 5, We will calculate the weighted score of each five-stage crime rule -based on the stages we found by each rule, and sum up each score. Further, we -will have a set of formulas to evaluate which risk range this weighted score -is, such as ``low risk``, ``medium risk``, and ``high risk``. - -First of all, in each of the five-stage crime rules, there is a field called -score. This score is based on the severity of the crime. - -Take this rule for example: - -.. code-block:: python - :linenos: - - { - "crime": "Send Location via SMS", - - "permission": [ - "android.permission.SEND_SMS", - "android.permission.ACCESS_COARSE_LOCATION", - "android.permission.ACCESS_FINE_LOCATION" - ], - - "api": [ - { - "class": "Landroid/telephony/TelephonyManager", - "method": "getCellLocation" - }, - { - "class": "Landroid/telephony/SmsManager", - "method": "sendTextMessage" - } - ], - - "score": 4 - } - -As you can see, this rule has a field called ``score``, which is ``4``. -Then, after the ``RuleObject`` initialize this rule, you can get this score by -using ``RuleObject.yscore``. - -After that, while the five-stage analysis check is completed, we can know which -crime stages have been reached. We will use ``get_score`` to get the weighted score -of this five-stage crime rule. - -.. code-block:: python - :linenos: - - def get_score(self, confidence): - """ - According to the state of the five stages, we calculate the weighted score based on exponential growth. - For example, we captured the third stage in five stages, then the weighted score would be (2^3-1) / 2^4. - - 2^(confidence - 1) - - :param confidence: - :return: floating point - """ - if confidence == 0: - return 0 - return (2 ** (confidence - 1) * self._score) / 2 ** 4 - -So assuming this rule, we captured the ``fourth stage``, that is, we can confirm -that the two native APIs appear in order. Then the calculation of this score -is (2 ** (``4`` - 1) * self._score) / 2 ** 4, which is ``2``. - -As for our risk range is defined in function ``calculate`` of ``qaurk.utils.weight``. - -There are five level threshold, the range are defined as below: - -.. code-block:: python - :linenos: - - # Level 1 threshold - level_one_threshold = self.score_sum / 2 ** 4 - - # Level 2 threshold - level_two_threshold = self.score_sum / 2 ** 3 - - # Level 3 threshold - level_three_threshold = self.score_sum / 2 ** 2 - - # Level 4 threshold - level_four_threshold = self.score_sum / 2 ** 1 - - # Level 5 threshold - level_five_threshold = self.score_sum / 2 ** 0 - -If the final total risk score falls in the ``first and second`` stages, it is **low -risk**; if it is in the ``third and fourth`` stages, it is **medium risk**. If it is in -the ``fifth`` stage, it is **high risk**. - - - - -Quark-Engine Step 6 (Report) -============================ - -As a final step, we present our analysis report in two forms, a summary report -and a detailed report. - -Summary Report --------------- - -.. image:: https://i.imgur.com/Ib01V6k.png - -Detail Report ---------------- - -.. image:: https://i.imgur.com/kh1jpsQ.png diff --git a/docs/source/quark_method_reference.rst b/docs/source/quark_method_reference.rst deleted file mode 100644 index cc566e799..000000000 --- a/docs/source/quark_method_reference.rst +++ /dev/null @@ -1,1965 +0,0 @@ -+++++++++++++++++++++++ -Quark Method Reference -+++++++++++++++++++++++ - -quark.core.quark.py --------------------- - -The module provides methods to perform the five-stage checking and Quark report generating. - -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| Method | Function | -+====================================================================================================================================================+=========================================================================================================+ -| `find_previous_method `_ | Find children under a specified parent of a method. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| `find_intersection `_ | Find the intersection between two sets of methods. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| `method_recursive_search `_ | Find the intersection between the parents of two sets of methods. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| `find_api_usage `_ | Find methods in the specified class or its subclasses that match the method name and descriptor. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| `_evaluate_method `_ | Evaluate the executions of opcodes in the target method and return the usage of registers. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| `check_parameter_on_single_method `_ | Check if the two methods use the same parameter. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| `check_parameter `_ | Check for the usage of the same parameter between two lists of methods. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| `check_parameter_values `_ | Check if the parameter values match the specified patterns and keywords. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| `check_sequence `_ | Check if the mutual parent of the two methods calls any first method before any second method. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| `run `_ | Check the APK at five levels to analyze if it meets the rules. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| `get_json_report `_ | Get a report of the analysis of the APK in JSON format. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| `generate_json_report `_ | Generate details of the analysis of the APK according to a rule. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| `add_table_row `_ | Add the analysis of the APK according to a rule to the summary report. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| `show_summary_report `_ | Show the summary report of the APK. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| `show_label_report `_ | Show the tabular report summarizing the statistical information of the APK. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| `show_detail_report `_ | Show the report summarizing the result of the five-level check and the confidence of the APK. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| `show_call_graph `_ | Show all call graphs of the APK. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ -| `show_rule_classification `_ | Show rule classification data in a table, a graphic, or JSON format. | -+----------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+ - - -find_previous_method -===================== - -**The algorithm of find_previous_method** - -The find_previous_method method uses a DFS algorithm to collect all MethodObjects called by the parent_method and add them to the specified wrapper. The search starts from the base_method and goes on recursively until there are no more levels or all candidates have been processed. - -.. code-block:: TEXT - - 1. Initialize an empty set "visited_methods" if it is not provided. - 2. Get a set "method_set" using "self.apkinfo.upperfunc(base_method)". - 3. Add "base_method" to the "visited_methods" set. - 4. If "method_set" is not None then check if "parent_function" is in "method_set". - - If yes, append "base_method" to "wrapper". - - If no, then iterate through each item in "method_set". - - If the item is in "visited_methods", skip it and continue to the next item. - - If not, call "find_previous_method" again with the current item, "parent_function", "wrapper", and "visited_methods". - -**The code of find_previous_method** - -.. code-block:: python - - def find_previous_method( - self, base_method, parent_function, wrapper, visited_methods=None - ): - """ - Find the method under the parent function, based on base_method before to parent_function. - This will append the method into wrapper. - - :param base_method: the base function which needs to be searched. - :param parent_function: the top-level function which calls the basic function. - :param wrapper: list is used to track each function. - :param visited_methods: set with tested method. - :return: None - """ - if visited_methods is None: - visited_methods = set() - - method_set = self.apkinfo.upperfunc(base_method) - visited_methods.add(base_method) - - if method_set is not None: - - if parent_function in method_set: - wrapper.append(base_method) - else: - for item in method_set: - # prevent to test the tested methods. - if item in visited_methods: - continue - self.find_previous_method( - item, parent_function, wrapper, visited_methods - ) - -find_intersection -===================== - -**The algorithm of find_intersection** - -The ``find_intersection`` method takes in two sets, ``first_method_set`` and ``second_method_set``, and finds their intersection using a recursive search algorithm. - -Here is the process of ``find_intersection``。 - -.. code-block:: TEXT - - 1. Check that the input sets are not empty. - If one of the sets is empty, raise a ValueError. - - 2. Use the & operator to find the intersection of the two sets. - If the intersection is not empty, return the resulting set. - - 3. If the intersection is empty, call the method_recursive_search - function with the input sets and a specified maximum depth. - - 4. The method_recursive_search function recursively searches for - the intersection of the two input sets up to the specified depth - by splitting the sets into subsets and comparing each subset's elements. - - If the intersection is found, return the resulting set. - - Otherwise, return None. - -**The code of find_intersection** - -.. code-block:: python - - def find_intersection(self, first_method_set, second_method_set, depth=1): - """ - Find the first_method_list ∩ second_method_list. - [MethodAnalysis, MethodAnalysis,...] - :param first_method_set: first list that contains each MethodAnalysis. - :param second_method_set: second list that contains each MethodAnalysis. - :param depth: maximum number of recursive search functions. - :return: a set of first_method_list ∩ second_method_list or None. - """ - # Check both lists are not null - if not first_method_set or not second_method_set: - raise ValueError("Set is Null") - # find ∩ - result = first_method_set & second_method_set - if result: - return result - else: - return self.method_recursive_search( - depth, first_method_set, second_method_set - ) - -method_recursive_search -======================= - -**The algorithm of method_recursive_search** - -The ``method_recursive_search`` algorithm finds the intersection between -two sets of methods. Specifically, the algorithm expands each set by -recursively adding their respective upper-level method objects until it -finds an intersection or the depth reaches ``MAX_SEARCH_LAYER``. - -Here is the process of ``method_recursive_search``. - -.. code:: text - - 1. The method_recursive_search function takes three arguments: - - depth, first_method_set, and second_method_set - 2. If the depth+1 > MAX_SEARCH_LAYER, return None. - 3. Create next_level_set_1 and next_level_set_2 that are the copies of first_method_set and second_method_set, respectively. - 4. Expand next_level_set_1 and next_level_set_2 by adding their respective upper-level methods. - 5. Calls find_intersection with the next_level_set_1, next_level_set_2 and depth+1 as arguments recursively. - - If an intersection is found, return the result. - - If no intersection is found, continue searching until depth > MAX_SEARCH_LAYER. - -**The code of method_recursive_search** - -.. code:: python - - def method_recursive_search( - self, depth, first_method_set, second_method_set - ): - # Not found same method usage, try to find the next layer. - depth += 1 - if depth > MAX_SEARCH_LAYER: - return None - - # Append first layer into next layer. - next_level_set_1 = first_method_set.copy() - next_level_set_2 = second_method_set.copy() - - # Extend the xref from function into next layer. - for method in first_method_set: - if self.apkinfo.upperfunc(method): - next_level_set_1 = ( - self.apkinfo.upperfunc(method) | next_level_set_1 - ) - for method in second_method_set: - if self.apkinfo.upperfunc(method): - next_level_set_2 = ( - self.apkinfo.upperfunc(method) | next_level_set_2 - ) - - return self.find_intersection( - next_level_set_1, next_level_set_2, depth - ) - -find_api_usage -============== - -**The algorithm of find_api_usage** - -``find_api_usage`` searches for methods with ``method_name`` and ``descriptor_name``, that belong to either the ``class_name`` or its subclass. It returns a list that contains matching methods. - -Here is the process of ``find_api_usage``. - -.. code-block:: TEXT - - 1. Initialize an empty "method_list". - 2. Search for an exact match of the method by its "class_name", "method_name", and "descriptor_name". - - If found, return a list with the matching methods. - 3. Create a list of potential methods with matching "method_name" and "descriptor_name". - 4. Filter the list of potential methods to include only those with bytecodes. - 5. Check if the class of each potential method is a subclass of the given "class_name". - - If yes, add the method to "method_list". - 6. Return "method_list". - -Here is the flowchart of ``find_api_usage``. - -.. image:: https://i.imgur.com/FZKRMgX.png - -**The code of find_api_usage** - -.. code-block:: python - - def find_api_usage(self, class_name, method_name, descriptor_name): - method_list = [] - - # Source method - source_method = self.apkinfo.find_method( - class_name, method_name, descriptor_name - ) - if source_method: - return [source_method] - - # Potential Method - potential_method_list = [ - method - for method in self.apkinfo.all_methods - if method.name == method_name - and method.descriptor == descriptor_name - ] - - potential_method_list = [ - method - for method in potential_method_list - if not next(self.apkinfo.get_method_bytecode(method), None) - ] - - # Check if each method's class is a subclass of the given class - for method in potential_method_list: - current_class_set = {method.class_name} - - while current_class_set and not current_class_set.intersection( - {class_name, "Ljava/lang/Object;"} - ): - next_class_set = set() - for clazz in current_class_set: - next_class_set.update( - self.apkinfo.superclass_relationships[clazz] - ) - - current_class_set = next_class_set - - current_class_set.discard("Ljava/lang/Object;") - if current_class_set: - method_list.append(method) - - return method_list - -_evaluate_method -===================== - -**The algorithm of _evaluate_method** - -The ``_evaluate_method`` method evaluates the execution of opcodes in the target method and returns a matrix representing the usage of each involved register. The method takes one parameter, method, which is the method to be evaluated. - -Here is the process of ``_evaluate_method``. - -.. code-block:: TEXT - - 1. Create a PyEval object with the apkinfo attribute of the instance. PyEval is presumably - a class that handles the evaluation of opcodes. - - 2. Loop through the bytecode objects in the target method by calling the get_method_bytecode - method of the apkinfo attribute. - - 3. Extract the mnemonic (opcode), registers, and parameter from the bytecode_obj and create - an instruction list containing these elements. - - 4. Convert all elements of the instruction list to strings (in case there are MUTF8String objects). - - 5. Check if the opcode (the first element of instruction) is in the eval dictionary of the pyeval object. - - If it is, call the corresponding function with the instruction as its argument. - - 6. Once the loop is finished, call the show_table method of the pyeval object to return the - matrix representing the usage of each involved register. - -Here is the flowchart of ``_evaluate_method``. - -.. image:: https://i.imgur.com/XCKrjjR.jpg - -**The code of _evaluate_method** - -.. code-block:: python - - def _evaluate_method(self, method) -> List[List[str]]: - """ - Evaluate the execution of the opcodes in the target method and return - the usage of each involved register. - :param method: Method to be evaluated - :return: Matrix that holds the usage of the registers - """ - pyeval = PyEval(self.apkinfo) - - for bytecode_obj in self.apkinfo.get_method_bytecode(method): - # ['new-instance', 'v4', Lcom/google/progress/SMSHelper;] - instruction = [bytecode_obj.mnemonic] - if bytecode_obj.registers is not None: - instruction.extend(bytecode_obj.registers) - if bytecode_obj.parameter is not None: - instruction.append(bytecode_obj.parameter) - - # for the case of MUTF8String - instruction = [str(x) for x in instruction] - - if instruction[0] in pyeval.eval.keys(): - pyeval.eval[instruction[0]](instruction) - - return pyeval.show_table() - -check_parameter_on_single_method -======================================= - -**The algorithm of check_parameter_on_single_method** - -The ``check_parameter_on_single_method`` function checks whether two methods use the same parameter. - -Here is the process of ``check_parameter_on_single_method``. - -.. code-block:: TEXT - - 1. Define a method named check_parameter_on_single_method, which takes 5 parameters: - * self: a reference to the current object, indicating that this method is defined in a class - * usage_table: a table for storing the usage of called functions - * first_method: the first API or the method calling the first API - * second_method: the second API or the method calling the second API - * keyword_item_list: a list of keywords used to determine if the parameter meets specific conditions - - 2. Define a Boolean variable regex, which is set to False by default. - - 3. Obtain the patterns of first_method and second_method based on the given input, and store them in - first_method_pattern and second_method_pattern, respectively. - - 4. Define a generator matched_records. Use the filter function to filter register_usage_records to - include only those matched records used by both first_method and second_method. - - 5. Use a for loop to process the matched records one by one. - - 6. Call method check_parameter_values to check if the matched records contain keywords in keyword_item_list. - - If True, add matched keywords to matched_keyword_list. - - If False, leave matched_keyword_list empty. - - 7. Use yield to return the matched record and matched_keyword_list. This method is a generator that processes - data and returns results at the same time. - -Here is the flowchart of ``check_parameter_on_single_method``. - -.. image:: https://i.imgur.com/BJf7oSg.png - -**The code of check_parameter_on_single_method** - -.. code:: python - - def check_parameter_on_single_method( - self, - usage_table, - first_method, - second_method, - keyword_item_list=None, - regex=False, - ) -> Generator[Tuple[str, List[str]], None, None]: - """Check the usage of the same parameter between two method. - - :param usage_table: the usage of the involved registers - :param first_method: the first API or the method calling the first APIs - :param second_method: the second API or the method calling the second - APIs - :param keyword_item_list: keywords required to be present in the usage - , defaults to None - :param regex: treat the keywords as regular expressions, defaults to - False - :yield: _description_ - """ - first_method_pattern = PyEval.get_method_pattern( - first_method.class_name, first_method.name, first_method.descriptor - ) - - second_method_pattern = PyEval.get_method_pattern( - second_method.class_name, - second_method.name, - second_method.descriptor, - ) - - register_usage_records = ( - c_func - for table in usage_table - for val_obj in table - for c_func in val_obj.called_by_func - ) - - matched_records = filter( - lambda r: first_method_pattern in r and second_method_pattern in r, - register_usage_records, - ) - - for record in matched_records: - if keyword_item_list and list(keyword_item_list): - matched_keyword_list = self.check_parameter_values( - record, - (first_method_pattern, second_method_pattern), - keyword_item_list, - regex, - ) - - if matched_keyword_list: - yield (record, matched_keyword_list) - - else: - yield (record, None) - -check_parameter -================== - -**The algorithm of check_parameter** - -The function ``check_parameter`` is designed to check for the usage of the same parameter between two methods. - -Here is the process of ``check_parameter``. - -.. code-block:: TEXT - - 1. Check if parent_function, first_method_list or second_method_list is None. - - If True, raise a TypeError exception. - - 2. Check if the keyword_item_list parameter exists and has elements. - - If False, set keyword_item_list to None. - - 3. Initialize the state variable to False. - - 4. Evaluate the opcode of the parent_function by calling self._evaluate_method and store the result to usage_table. - - 5. Iterate through the combinations of methods from the first_method_list and second_method_list. - - 6. Call self.check_parameter_on_single_method with usage_table to check if the two methods use the same parameters. - - If True, - - Record the corresponding call graph analysis. - - Record the mapping between the parent function and the wrapper method. - - Set the state variable to True. - - 7. Once the iteration finishes, return the state variable. - -Here is the flowchart of ``check_parameter``. - -.. image:: https://i.imgur.com/Og1mXss.png - -**The code of check_parameter** - -.. code:: python - - def check_parameter( - self, - parent_function, - first_method_list, - second_method_list, - keyword_item_list=None, - regex=False, - ): - """ - Check the usage of the same parameter between two method. - - :param parent_function: function that call the first function and - second functions at the same time. - :param first_method_list: function which calls before the second - method. - :param second_method_list: function which calls after the first method. - :return: True or False - """ - if parent_function is None: - raise TypeError("Parent function is None.") - - if first_method_list is None or second_method_list is None: - raise TypeError("First or second method list is None.") - - if keyword_item_list: - keyword_item_list = list(keyword_item_list) - if not any(keyword_item_list): - keyword_item_list = None - - state = False - - # Evaluate the opcode in the parent function - usage_table = self._evaluate_method(parent_function) - - # Check if any of the target methods (the first and second methods) - # used the same registers. - state = False - for first_call_method in first_method_list: - for second_call_method in second_method_list: - - result_generator = self.check_parameter_on_single_method( - usage_table, - first_call_method, - second_call_method, - keyword_item_list, - regex, - ) - - found = next(result_generator, None) is not None - - # Build for the call graph - if found: - call_graph_analysis = { - "parent": parent_function, - "first_call": first_call_method, - "second_call": second_call_method, - "apkinfo": self.apkinfo, - "first_api": self.quark_analysis.first_api, - "second_api": self.quark_analysis.second_api, - "crime": self.quark_analysis.crime_description, - } - self.quark_analysis.call_graph_analysis_list.append( - call_graph_analysis - ) - - # Record the mapping between the parent function and the - # wrapper method - self.quark_analysis.parent_wrapper_mapping[ - parent_function.full_name - ] = self.apkinfo.get_wrapper_smali( - parent_function, - first_call_method, - second_call_method, - ) - - state = True - - return state - -check_parameter_values -========================== - -**The algorithm of check_parameter_values** - -The function ``check_parameter_values`` is designed to check if the parameter values in the source string match the specified patterns and keywords. Then, it collects the matched strings into a set and returns it. - -Here is the process of ``check_parameter_values``. - -.. code-block:: TEXT - - 1. Create an empty set matched_string_set. - - 2. Use tools.get_parenthetic_contents to extract the content that matches each pattern in the pattern_list from the source_str. Store the results in the parameter_strs list. - - 3. Use zip to pair up the parameter_strs and keyword_item_list and iterate over them. - - 4. For each pairing of parameter_str and keyword_item, perform the following operations: - - Check if keyword_item is not None. - - For each keyword in keyword_item, perform the following operations: - - Check If regex is True, - - If True, - - Use re.findall to search for matching strings and store them in matched_strings. - - Check if matched_strings has any matching strings. - - If True, Add all nonempty strings from matched_strings to the matched_string_set. - - If False, add all keywords in parameter_str to the matched_string_set. - - 5. Once the iteration finishes, return a list of strings from the matched_string_set, which represents all the matched results. - - -Here is the flowchart of ``check_parameter_values``. - -.. image:: https://i.imgur.com/SiMGE2w.png - -**The code of check_parameter_values** - -.. code:: python - - @staticmethod - def check_parameter_values( - source_str, pattern_list, keyword_item_list, regex=False - ) -> List[str]: - matched_string_set = set() - - parameter_strs = [ - tools.get_parenthetic_contents( - source_str, source_str.index(pattern) + len(pattern) - ) - for pattern in pattern_list - ] - - for parameter_str, keyword_item in zip( - parameter_strs, keyword_item_list - ): - if keyword_item is None: - continue - - for keyword in keyword_item: - if regex: - matched_strings = re.findall(keyword, parameter_str) - if any(matched_strings): - matched_strings = filter(bool, matched_strings) - matched_strings = list(matched_strings) - - element = matched_strings[0] - if isinstance( - element, collections.abc.Sequence - ) and not isinstance(element, str): - for str_list in matched_strings: - matched_string_set.update(str_list) - - else: - matched_string_set.update(matched_strings) - - else: - if str(keyword) in parameter_str: - matched_string_set.add(keyword) - - return [e for e in list(matched_string_set) if bool(e)] - - - -check_sequence -=============== - -**The algorithm of check_sequence** - -The function ``check_sequence`` checks if ``mutual_parent`` calls any first method before any second method. If Yes, ``check_sequence`` records the mapping between ``mutual_parent`` and the matched methods and returns True. - -Here is the process of ``check_sequence``. - - -.. code-block:: TEXT - - 1. Initialize the variable state as False. - - 2. Iterate the method pairs formed by first_method_list and second_method_list. - - 3. From mutual_parent, find method calls that call any method in the pair. Then collect them into the list seq_table. - - 4. Check if the length of seq_table is less than 2. - - If True, continue to the next iteration. - - 5. Sort seq_table according to the offsets of the method calls. Then name the sorted list as method_list_need_check. - - 6. Check if the method pair is a sublist of method_list_need_check. - - If True, - - Set state to True. - - Record the mapping between mutual_parent and the method pair in quark_analysis. - - 7. Return state. - -Here is the flowchart of ``check_sequence``. - -.. image:: https://i.imgur.com/8wmEre6.png - -**The code of check_sequence** - - -.. code:: python - - def check_sequence( - self, mutual_parent, first_method_list, second_method_list - ): - """ - Check if the first function appeared before the second function. - - :param mutual_parent: function that call the first function and second functions at the same time. - :param first_method_list: the first show up function, which is a MethodAnalysis - :param second_method_list: the second show up function, which is a MethodAnalysis - :return: True or False - """ - state = False - - for first_call_method in first_method_list: - for second_call_method in second_method_list: - - seq_table = [ - (call, number) - for call, number in self.apkinfo.lowerfunc(mutual_parent) - if call in (first_call_method, second_call_method) - ] - - # sorting based on the value of the number - if len(seq_table) < 2: - # Not Found sequence in same_method - continue - seq_table.sort(key=operator.itemgetter(1)) - # seq_table would look like: [(getLocation, 1256), (sendSms, 1566), (sendSms, 2398)] - - method_list_need_check = [x[0] for x in seq_table] - sequence_pattern_method = [ - first_call_method, - second_call_method, - ] - - if tools.contains( - sequence_pattern_method, method_list_need_check - ): - state = True - - # Record the mapping between the parent function and the wrapper method - self.quark_analysis.parent_wrapper_mapping[ - mutual_parent.full_name - ] = self.apkinfo.get_wrapper_smali( - mutual_parent, first_call_method, second_call_method - ) - - return state - - - -run -=============== - -**The algorithm of run** - -The function ``run`` checks the APK file at five levels to analyze whether it meets the rules. - -Here is the process of ``run``. - -.. code-block:: TEXT - - 1. Clean the results of the previous analysis. - - 2. Store the 'crime' description in the analysis result - - 3. Level 1 Check: Permission requested - - Check if the input file is a DEX file. - - If Yes, set the first item of check_item in rule_obj to True. - - If No, check if the permissions of the APK include the permissions in the rule. - - If Yes, set the first item of check_item to True. - - If No, the function exits. - - 4. Level 2 Check: Native API call - - Check if the APK uses any of the two native APIs in the rule. - - If Yes, set the second item of check_item to True and store information about the calls of the two native APIs in the analysis result. - - If No, the function exits. - - 5. Level 3 Check: Certain combination of native API - - Check if the APK uses both native APIs in the rule. - - If Yes, set the third item of check_item to True and store the calls of the two native APIs in the analysis result. - - If No, the function exits. - - 6. Level 4 Check: Calling sequence of native API - - Check if there are any mutual parent functions between each combined API call of the two native APIs - - If Yes, check if any mutual parent function calls the first method before the second method. - - If Yes, set the fourth item of check_item to True and store information about the parent functions in the analysis result. - - If No, the function exits. - - 7. Level 5 Check: APIs that handle the same register - - Check if the native APIs in the rule handle the same registers. - - If Yes, set the fifth item of check_item to True and store the parent functions in the analysis result. - - If No, the function exits. - - - -Here is the flowchart of ``run``. - -.. image:: https://i.imgur.com/v152g3L.png - -**The code of run** - - -.. code:: python - - def run(self, rule_obj): - """ - Run the five levels check to get the y_score. - - :param rule_obj: the instance of the RuleObject. - :return: None - """ - self.quark_analysis.clean_result() - self.quark_analysis.crime_description = rule_obj.crime - - # Level 1: Permission Check - if self.apkinfo.ret_type == "DEX": - rule_obj.check_item[0] = True - elif set(rule_obj.permission).issubset(set(self.apkinfo.permissions)): - rule_obj.check_item[0] = True - else: - # Exit if the level 1 stage check fails. - return - - # Level 2: Single Native API Check - api_1_method_name = rule_obj.api[0]["method"] - api_1_class_name = rule_obj.api[0]["class"] - api_1_descriptor = rule_obj.api[0]["descriptor"] - - api_2_method_name = rule_obj.api[1]["method"] - api_2_class_name = rule_obj.api[1]["class"] - api_2_descriptor = rule_obj.api[1]["descriptor"] - - first_api_list = self.find_api_usage( - api_1_class_name, api_1_method_name, api_1_descriptor - ) - second_api_list = self.find_api_usage( - api_2_class_name, api_2_method_name, api_2_descriptor - ) - - if not first_api_list and not second_api_list: - # Exit if the level 2 stage check fails. - return - - else: - rule_obj.check_item[1] = True - - if first_api_list: - self.quark_analysis.level_2_result.append(first_api_list[0]) - if second_api_list: - self.quark_analysis.level_2_result.append(second_api_list[0]) - - # Level 3: Both Native API Check - if not (first_api_list and second_api_list): - # Exit if the level 3 stage check fails. - return - - self.quark_analysis.first_api = first_api_list[0] - self.quark_analysis.second_api = second_api_list[0] - rule_obj.check_item[2] = True - - self.quark_analysis.level_3_result = [set(), set()] - - # Level 4: Sequence Check - for first_api in first_api_list: - for second_api in second_api_list: - # Looking for the first layer of the upper function - first_api_xref_from = self.apkinfo.upperfunc(first_api) - second_api_xref_from = self.apkinfo.upperfunc(second_api) - - self.quark_analysis.level_3_result[0].update( - first_api_xref_from - ) - self.quark_analysis.level_3_result[1].update( - second_api_xref_from - ) - - if not first_api_xref_from: - print_warning( - f"Unable to find the upperfunc of {first_api}" - ) - continue - if not second_api_xref_from: - print_warning( - f"Unable to find the upperfunc of{second_api}" - ) - continue - - mutual_parent_function_list = self.find_intersection( - first_api_xref_from, second_api_xref_from - ) - - if mutual_parent_function_list is None: - # Exit if the level 4 stage check fails. - return - for parent_function in mutual_parent_function_list: - first_wrapper = [] - second_wrapper = [] - - self.find_previous_method( - first_api, parent_function, first_wrapper - ) - self.find_previous_method( - second_api, parent_function, second_wrapper - ) - - if self.check_sequence( - parent_function, first_wrapper, second_wrapper - ): - rule_obj.check_item[3] = True - self.quark_analysis.level_4_result.append( - parent_function - ) - - keyword_item_list = ( - rule_obj.api[i].get("keyword", None) - for i in range(2) - ) - - # Level 5: Handling The Same Register Check - if self.check_parameter( - parent_function, - first_wrapper, - second_wrapper, - keyword_item_list=keyword_item_list, - ): - rule_obj.check_item[4] = True - self.quark_analysis.level_5_result.append( - parent_function - ) - - -get_json_report -=============== - -**The algorithm of get_json_report** - -The function ``get_json_report`` generates a report of the analysis performed on the APK file, in JSON format. - -Here is the process of ``get_json_report``. - - -.. code-block:: TEXT - - 1. Create a Weight object with the total score and weight from the analysis result. - - 2. Calculate the threat level with the Weight object and store the result in the variable warning. - - 3. Loop through a list of threat levels and check if the variable warning contains any of the threat levels. - - If Yes, sets the variable warning to the threat level. - - 4. Return a report with various pieces of information: - - The MD5 hash of the APK - - The filename of the APK - - The file size of the APK - - The threat level of the APK - - The total score of the analysis result - - The JSON report of the analysis result - - -Here is the flowchart of ``get_json_report``. - -.. image:: https://i.imgur.com/i2JZJQ0.png - - -**The code of get_json_report** - - -.. code:: python - - def get_json_report(self): - """ - Get quark report including summary and detail with json format. - - :return: json report - """ - - w = Weight( - self.quark_analysis.score_sum, self.quark_analysis.weight_sum - ) - warning = w.calculate() - - # Filter out color code in threat level - for level in ["Low Risk", "Moderate Risk", "High Risk"]: - if level in warning: - warning = level - - return { - "md5": self.apkinfo.md5, - "apk_filename": self.apkinfo.filename, - "size_bytes": self.apkinfo.filesize, - "threat_level": warning, - "total_score": self.quark_analysis.score_sum, - "crimes": self.quark_analysis.json_report, - } - - -generate_json_report -=============== - -**The algorithm of generate_json_report** - -The function ``‎generate_json_report`` generates a JSON report based on the information extracted from the ruleobject instance . - -Here is the process of ``generate_json_report``. - - -.. code-block:: TEXT - - 1. Calculate confidence percentage by counting the number of True values in check_item and multiplying by 20. Store the confidence value. - - 2. Count the True values in check_item and store the count as conf. Use conf to calculate the weight of the rule using the get_score method. - - 3. Assign the score attribute's value to the score variable. - - 4. Check the first item in check_item. - -If True, assign the permission attribute to permissions. - -Otherwise, assign an empty list. - - 5. Check the second item in check_item. - -If True, populate the API list with dictionaries from quark_analysis.level_2_result. - - 6. Check the third item in check_item. - -If True, assign the API attribute's value to the combination variable. - - 7. Define two empty lists: - -sequnce_show_up - -same_operation_show_up - - 8. Check if the fourth item in the check_item is True and the quark_analysis.level_4_result list is not empty. - -If True, - -populate the sequnce_show_up list with dictionaries containing full_name attributes and their corresponding values from quark_analysis.parent_wrapper_mapping. - -Check if the fifth item in the check_item is True and the quark_analysis.level_5_result list is not empty. - -If True, populate the same_operation_show_up list with dictionaries containing full_name attributes and their corresponding values from quark_analysis.parent_wrapper_mapping. - - 9. Create a dictionary called crime, containing the following attributes: - -rule:filename of rule in rule_obj - -crime:description of quark_analysis's crime in rule_obj - -label:the label in rule_obj - -score:the score in rule_obj - -weight:the weight in rule_obj - -confidence:the number of True values in check_item and multiplying by 20 - -permissions:the permission in rule_obj - -native_api:list with dictionaries from quark_analysis.level_2_result - -combination:the value of the api attribute of rule_obj - -sequence:sequnce_show_up, information about the items in quark_analysis.level_4_result - -register:same_operation_show_up, information about the items in the quark_analysis.level_5_result - - 10. Append the crime dictionary to the json_report attribute of quark_analysis. - - 11. Add the weight to the weight_sum attribute of quark_analysis. - - 12. Add the score to the score_sum attribute of quark_analysis. - - - -Here is the flowchart of ``generate_json_report``. - -.. image:: https://i.imgur.com/gROkCdB.png - - -**The code of generate_json_report** - - -.. code:: python - - def generate_json_report(self, rule_obj): - """ - Show the json report. - - :param rule_obj: the instance of the RuleObject - :return: None - """ - # Count the confidence - confidence = str(rule_obj.check_item.count(True) * 20) + "%" - conf = rule_obj.check_item.count(True) - weight = rule_obj.get_score(conf) - score = rule_obj.score - - # Assign level 1 examine result - permissions = rule_obj.permission if rule_obj.check_item[0] else [] - - # Assign level 2 examine result - api = [] - if rule_obj.check_item[1]: - for item2 in self.quark_analysis.level_2_result: - api.append( - { - "class": str(item2.class_name), - "method": str(item2.name), - "descriptor": str(item2.descriptor), - } - ) - - # Assign level 3 examine result - combination = [] - if rule_obj.check_item[2]: - combination = rule_obj.api - - # Assign level 4 - 5 examine result if exist - sequnce_show_up = [] - same_operation_show_up = [] - - # Check examination has passed level 4 - if self.quark_analysis.level_4_result and rule_obj.check_item[3]: - for item4 in self.quark_analysis.level_4_result: - sequnce_show_up.append( - { - item4.full_name: self.quark_analysis.parent_wrapper_mapping[ - item4.full_name - ] - } - ) - - # Check examination has passed level 5 - if self.quark_analysis.level_5_result and rule_obj.check_item[4]: - for item5 in self.quark_analysis.level_5_result: - same_operation_show_up.append( - { - item5.full_name: self.quark_analysis.parent_wrapper_mapping[ - item5.full_name - ] - } - ) - - crime = { - "rule": rule_obj.rule_filename, - "crime": rule_obj.crime, - "label": rule_obj.label, - "score": score, - "weight": weight, - "confidence": confidence, - "permissions": permissions, - "native_api": api, - "combination": combination, - "sequence": sequnce_show_up, - "register": same_operation_show_up, - } - self.quark_analysis.json_report.append(crime) - - # add the weight - self.quark_analysis.weight_sum += weight - # add the score - self.quark_analysis.score_sum += score - - -add_table_row -=============== - -**The algorithm of add_table_row** - -The function ``add_table_row`` adds a list to the table. - -Here is the process of ``add_table_row``. - - -.. code-block:: TEXT - - 1. The method add_row is then called with a list of parameters. This list includes: - name: filename of rule in rule_obj - rule_obj.crime: description of quark_analysis's crime in rule_obj - confidence: the number of True values in check_item and multiplying by 20 - score: the score in rule_obj - weight: the weight in rule_obj - - 2. The add_row method takes these parameters and adds them as a new row in the summary_report_table. - -Here is the flowchart of ``add_table_row``. - -.. image:: https://i.imgur.com/5YEubbB.png - - -**The code of add_table_row** - - -.. code:: python - - def add_table_row(self, name, rule_obj, confidence, score, weight): - - self.quark_analysis.summary_report_table.add_row( - [ - name, - green(rule_obj.crime), - yellow(confidence), - score, - red(weight), - ] - ) - -show_summary_report -=============== - -**The algorithm of show_summary_report** - -The function ``show_summary_report`` generates a summary report. - -Here is the process of ``show_summary_report``. - - -.. code-block:: TEXT - - 1. Calculate confidence by counting occurrences of True in rule_obj.check_item and multiplying it by 20 to get a percentage. - - 2. Calculate the weight using the confidence value through rule_obj.get_score, and retrieves score and rule_filename from rule_obj. - - 3. Check if a threshold is provided. - -If true, check if the confidence percentage is greater than or equal to the threshold. - -If true, calls add_table_row with relevant arguments. - -If false, calls add_table_row with relevant arguments. - - 4. Update the quark_analysis instance by adding the calculated weight and score to weight_sum and score_sum. - -Here is the flowchart of ``show_summary_report``. - -.. image:: https://i.imgur.com/0B3nYsa.png - - -**The code of show_summary_report** - - -.. code:: python - - def show_summary_report(self, rule_obj, threshold=None): - """ - Show the summary report. - - :param rule_obj: the instance of the RuleObject. - :return: None - """ - # Count the confidence - confidence = f"{rule_obj.check_item.count(True) * 20}%" - conf = rule_obj.check_item.count(True) - weight = rule_obj.get_score(conf) - score = rule_obj.score - name = rule_obj.rule_filename - - if threshold: - - if rule_obj.check_item.count(True) * 20 >= int(threshold): - self.add_table_row(name, rule_obj, confidence, score, weight) - - else: - self.add_table_row(name, rule_obj, confidence, score, weight) - - # add the weight - self.quark_analysis.weight_sum += weight - # add the score - self.quark_analysis.score_sum += score - -show_label_report -================== - -**The algorithm of show_label_report** - -The function ``show_label_report`` generates a tabular report that summarizes statistical information. - -Here is the process of ``show_label_report``. - -.. code-block:: TEXT - - 1. Clear label_report_table and initializes label_desc. - - 2. Iterate through the all_labels dictionary. - - 3. Calculate the maximum, average, and standard deviation of the confidence values for each label. - - 4. Check if table_version is max. - - If true, set table header for table_version is max. - - If false, set table header for table_version is not max. - -Here is the flowchart of ``show_label_report``. - -.. image:: https://i.imgur.com/uT0RuB8.png - - -**The code of show_label_report** - - -.. code:: python - - def show_label_report(self, rule_path, all_labels, table_version): - """ - Show the report based on label, last column represents max confidence for that label - :param rule_path: the path where may be present the file label_desc.csv. - :param all_labels: dictionary containing label: - :return: None - """ - label_desc = {} - # clear table to manage max/detail version - self.quark_analysis.label_report_table.clear() - if os.path.isfile(os.path.join(rule_path, "label_desc.csv")): - # associate to each label a description - col_list = ["label", "description"] - # csv file on form - # put this file in the folder of rules (it must not be a json file since it could create conflict with management of rules) - # remove temporarily - #df = pd.read_csv( - # os.path.join(rule_path, "label_desc.csv"), usecols=col_list - #) - # - #label_desc = dict(zip(df["label"], df["description"])) - - for label_name in all_labels: - confidences = np.array(all_labels[label_name]) - - if table_version == "max": - self.quark_analysis.label_report_table.field_names = [ - "Label", - "Description", - "Number of rules", - "MAX Confidence %", - ] - self.quark_analysis.label_report_table.add_row( - [ - green(label_name), - yellow(label_desc.get(label_name, "-")), - (len(confidences)), - red(np.max(confidences)), - ] - ) - else: - self.quark_analysis.label_report_table.field_names = [ - "Label", - "Description", - "Number of rules", - "MAX Confidence %", - "AVG Confidence", - "Std Deviation", - "# of Rules with Confidence >= 80%", - ] - self.quark_analysis.label_report_table.add_row( - [ - green(label_name), - yellow(label_desc.get(label_name, "-")), - (len(confidences)), - red(np.max(confidences)), - magenta(round(np.mean(confidences), 2)), - lightblue(round(np.std(confidences), 2)), - lightyellow(np.count_nonzero(confidences >= 80)), - ] - ) - - -show_detail_report -================== - -**The algorithm of show_detail_report** - -The function ``show_detail_report`` prints a report summarizing the result of the five-level check and the confidence of the APK. - -Here is the process of ``show_detail_report``. - -.. code-block:: TEXT - - 1. Calculate the confidence of the APK by multiplying the number of passed levels by 20. - - 2. Check if the APK passed level 1. - - If passed, show the match permissions. - - 3. Check if the APK passed level 2. - - If passed, show the matched APIs. - - 4. Check if the APK passed level 3. - - If passed, show the matched API combinations. - - 5. Check if the APK passed level 4. - - If passed, show the matched API sequences. - - 6. Check if the APK passed level 5. - - If passed, show the matched API sequences that use the same register. - -Here is the flowchart of ``show_detail_report``. - -.. image:: https://i.imgur.com/s1DZVHs.png - - -**The code of show_detail_report** - - -.. code:: python - - def show_detail_report(self, rule_obj): - """ - Show the detail report. - - :param rule_obj: the instance of the RuleObject. - :return: None - """ - - # Count the confidence - print("") - print(f"Confidence: {rule_obj.check_item.count(True) * 20}%") - print("") - - if rule_obj.check_item[0]: - - colorful_report("1.Permission Request") - for permission in rule_obj.permission: - print(f"\t\t {permission}") - if rule_obj.check_item[1]: - colorful_report("2.Native API Usage") - for api in self.quark_analysis.level_2_result: - print(f"\t\t {api.full_name}") - if rule_obj.check_item[2]: - colorful_report("3.Native API Combination") - for numbered_api, method_list in zip( - ("First API", "Second API"), self.quark_analysis.level_3_result - ): - print(f"\t\t {numbered_api} show up in:") - if method_list: - for comb_method in method_list: - print(f"\t\t {comb_method.full_name}") - else: - print("\t\t None") - - if rule_obj.check_item[3]: - - colorful_report("4.Native API Sequence") - print("\t\t Sequence show up in:") - for seq_method in self.quark_analysis.level_4_result: - print(f"\t\t {seq_method.full_name}") - if rule_obj.check_item[4]: - - colorful_report("5.Native API Use Same Parameter") - for seq_operation in self.quark_analysis.level_5_result: - print(f"\t\t {seq_operation.full_name}") - -show_call_graph -================== - -**The algorithm of show_call_graph** - -The function ``show_call_graph`` creates a call graph for each element in call_graph_analysis_list and displays messages to indicate progress. - -Here is the process of ``show_call_graph``. - -.. code-block:: TEXT - - 1. Display the message "Creating Call Graph..." in cyan color. - - 2. Create a call graph for each element in call_graph_analysis_list. - - 3. Display the message "Call Graph Completed" in green color. - - - -Here is the flowchart of ``show_call_graph``. - -.. image:: https://i.imgur.com/18pGB7w.png - - - -**The code of show_call_graph** - - -.. code-block:: python - - def show_call_graph(self, output_format=None): - print_info("Creating Call Graph...") - for ( - call_graph_analysis - ) in self.quark_analysis.call_graph_analysis_list: - call_graph(call_graph_analysis, output_format) - print_success("Call Graph Completed") - - -show_rule_classification -=============================== - -**The algorithm of show_rule_classification** - -The function ``show_rule_classification`` extracts rule classification data, highlighting the links between parent functions and associated crimes. It then displays this data in table, JSON, and graphical formats. - -Here is the process of ``show_rule_classification``. - -.. code-block:: TEXT - - 1. Call the print_info function to display "Rules Classification". - - 2. Invoke the get_rule_classification_data function - - Use self.quark_analysis.call_graph_analysis_list and MAX_SEARCH_LAYER as parameters. - - Store the returned rule classification data in the data_bundle variable. - - 3. Call the output_parent_function_table function to display tables on the console. - - The first column of the table is "Parent Function", and the second column displays the name of that parent function. - - Subsequent rows list the "Crime Description" associated with that parent function. - - 4. Call the output_parent_function_json function to output a JSON file named "rules_classification.json". - - The structure of the file is a list containing multiple dictionaries. Each dictionary has two keys: parent and crime. - - 5. Call the output_parent_function_graph function to create a PNG format graphic file. - - This graphic displays the reference relationships between parent functions and the crime descriptions associated with each parent function. - - -Here is the flowchart of ``show_rule_classification``. - -.. image:: https://i.imgur.com/im3ER02.png - -**The code of show_rule_classification** - -.. code-block:: python - - def show_rule_classification(self): - print_info("Rules Classification") - - data_bundle = get_rule_classification_data( - self.quark_analysis.call_graph_analysis_list, MAX_SEARCH_LAYER - ) - - output_parent_function_table(data_bundle) - output_parent_function_json(data_bundle) - output_parent_function_graph(data_bundle) - - -quark.utils.graph.py ------------------------ - -wrapper_lookup -======================= - - -**The algorithm of wrapper_lookup** - -The ``wrapper_lookup`` method finds the method that calls the specified native API under the specified method. - -.. code-block :: TEXT - - 1. Create a stack that stores the specified method. - - 2. While the stack has elements, keep doing steps 3, 4, and 5, otherwise return an empty list. - - 3. Check if the top element of the stack is visited. - - If YES, pop the top element and continue to the next loop. - - If NO, record the top element as visited. - - 4. Find methods that the top element calls, and we refer to them as submethods. - - 5. Check if the specified native API is one of the submethods. - - If YES, return a list containing the top element. - - If NO, push the submethods to the stack except Android APIs. - - -Here is the flowchart of ``wrapper_lookup``. - -.. image:: https://i.imgur.com/nNvUWVI.png - - -**The code of wrapper_lookup** - -.. code-block:: python - - def wrapper_lookup(apkinfo, method, native_api): - visited_method_list = set() - stack = [method] - - while stack: - parent = stack[-1] - if parent not in visited_method_list: - visited_method_list.add(parent) - - submethods = {reference[0] for reference in apkinfo.lowerfunc(parent)} - if native_api in submethods: - return [parent] - - next_level = filter(lambda m: not m.is_android_api(), submethods) - stack.extend(next_level) - else: - stack.pop() - - return [] - - - - -show_comparison_graph -======================= - - -**The algorithm of show_comparison_graph** - -The ``show_comparison_graph`` generates and displays a radar chart based on the maximum label confidence of rule labels which compares the behaviors between the designated APK samples. - -.. code-block :: TEXT - - 1. The function "show_comparison_graph" takes four parameters: - - title: Text to be displayed as the chart's title. - - labels: Categories to be represented on the radar chart. - - malware_confidences: A mapping of malware identifiers to their respective lists of confidence scores. - - font_size: The textual size for the chart, defaulting to 22 if not specified. - - 2. Initialize the figure - - Create a blank figure object "fig" using "go.Figure()". - - 3. Set the layout of the figure using "fig.update_layout" - - Define the polar coordinate system with the radial axis visible, ranging from 0 to 100, and having a tick every 20 units. - - Enable the legend display. - - Set the chart title with bold text. - - Set the font size. - - Center the title horizontally. - - Configure the position and order of the legend. - - 4. Add data to the figure - - For each "malware_name" in the "malware_confidences" dictionary, create a radar chart data trace. - - Use "go.Scatterpolar", specifying the radius as the array of confidence values and the angle as the labels. - - Set the fill mode to "toself" to create a closed radar area. - - Name each trace as "malware_name" and customize the line width. - - 5. Display the figure - - Display the figure using the "fig.show()" method. - - 6. Check and create a storage directory - - Check if the directory "behaviors_comparison_radar_chart exists", and create it if it does not. - - If YES, proceed to the next step. - - If NOT, create the "behaviors_comparison_radar_chart" directory. - - 7. Save the figure as an image - - Save the figure as a JPEG image in the "behaviors_comparison_radar_chart" directory. - -Here is the flowchart of ``show_comparison_graph``. - -.. image:: https://i.imgur.com/TxMHA7J.png - - -**The code of show_comparison_graph** - -.. code-block:: python - - def show_comparison_graph(title, labels, malware_confidences, font_size=22): - """ - show radar chart based on max label confidence of several malwares - :param title: title of the graph to be displayed - :param labels: labels to be shown on the radar chart - :param malware_confidences: dictionary with structure, malware_name=[ - array of confidences to be shown on radar chart] - :return: None - """ - fig = go.Figure() - # plot the graph with specific layout - fig.update_layout( - polar=dict(radialaxis=dict(visible=True, range=[0, 100], dtick=20)), - showlegend=True, - title={ - "text": f"{title}", - }, - font=dict(size=font_size), - title_x=0.5, - legend=dict( - y=0.5, - x=0.8, - traceorder="normal", - ), - ) - for malware_name in malware_confidences: - fig.add_trace( - go.Scatterpolar( - r=malware_confidences[malware_name], - theta=labels, - fill="toself", - name=malware_name, - line=dict( - width=4, - ), - ) - ) - fig.show() - if not os.path.exists("behaviors_comparison_radar_chart"): - os.mkdir("behaviors_comparison_radar_chart") - fig.write_image("behaviors_comparison_radar_chart/compariso_image.jpeg") - - -call_graph -======================= - - -**The algorithm of call_graph** - -The ``call_graph`` method generates a call graph based on the two native APIs. - -.. code-block :: TEXT - - 1. Check if the two methods in the call graph analysis are the native APIs. - - If NO, find the methods that call the native APIs under the two methods. - And we refer to them as wrappers. - - If YES, continue to the following steps. - - 2. Initialize the call graph and draw it in the following steps. - - 3. Draw the node representing the mutual parent function of the two native APIs. - - 4. Draw the nodes representing the wrappers. - - 5. Draw the edges representing the method calls between the wrappers. - - 6. Draw the nodes representing the two native APIs. - - 7. Draw the edges representing the method calls from the mutual parent function to the native APIs. - - -Here is the flowchart of ``call_graph``. - -.. image:: https://i.imgur.com/sEZ91k9.png - - -**The code of call_graph** - -.. code-block:: python - - def call_graph(call_graph_analysis, output_format="png"): - """ - Generating a call graph based on two native Android APIs. - """ - - parent_function = call_graph_analysis["parent"] - apkinfo = call_graph_analysis["apkinfo"] - first_call = call_graph_analysis["first_call"] - second_call = call_graph_analysis["second_call"] - first_api = call_graph_analysis["first_api"] - second_api = call_graph_analysis["second_api"] - crime = call_graph_analysis["crime"] - - if first_call != first_api: - first_wrapper = wrapper_lookup(apkinfo, first_call, first_api) - if second_call != second_api: - second_wrapper = wrapper_lookup(apkinfo, second_call, second_api) - - # Initialize the Digraph object - dot = Digraph( - filename=f"{parent_function.name}_{first_call.name}_{second_call.name}", - node_attr={"fontname": "Courier New Bold"}, - comment="Quark-Engine Call Graph Result", - format=output_format, - graph_attr={ - "label": f"Potential Malicious Activity: {crime}", - "labelloc": "top", - "center": "true", - }, - ) - dot.attr(compound="true") - - with dot.subgraph(name="cluster_mutual") as mutual_parent_function_description: - mutual_parent_function_description.attr( - style="rounded", - penwidth="1", - fillcolor="white", - fontname="Courier New", - shape="box", - ) - mutual_parent_function_description.attr( - label="Mutual Parent Function", fontname="Courier New Bold" - ) - - # mutual parent function node - p, r = str(parent_function.descriptor).split(")") - mutual_parent_function_description.node( - f"{parent_function.full_name}", - label=f"Access: {parent_function.access_flags}\nClass: {parent_function.class_name}\nMethod: {parent_function.name}\n Parameter: {p})\n Return: {r}", - shape="none", - fontcolor="blue", - fontname="Courier New", - ) - - with dot.subgraph(name="cluster_0") as wrapper: - wrapper.attr(label="Wrapped Functions", fontname="Courier New Bold") - wrapper.attr(style="rounded", penwidth="1", fillcolor="red", shape="box") - # Build the first call nodes - - if first_call != first_api: - - for wp_func in first_wrapper: - p, r = str(wp_func.descriptor).split(")") - - wrapper.node( - f"{wp_func.full_name}", - label=f"Access: {wp_func.access_flags}\nClass: {wp_func.class_name}\nMethod: {wp_func.name}\n Parameter: {p})\n Return: {r}", - style="rounded", - fontcolor="blue", - penwidth="1", - fillcolor="white", - fontname="Courier New", - shape="none", - ) - - # wrapper -> wrapper - for i in range(len(first_wrapper) - 1, 0, -1): - wrapper.edge( - f"{first_wrapper[i].full_name}", - f"{first_wrapper[i - 1].full_name}", - "calls", - fontname="Courier New", - ) - - if second_call != second_api: - - for wp_func in second_wrapper: - p, r = str(wp_func.descriptor).split(")") - wrapper.node( - f"{wp_func.full_name}", - label=f"Access: {wp_func.access_flags}\nClass: {wp_func.class_name}\nMethod: {wp_func.name}\n Parameter: {p})\n Return: {r}", - style="rounded", - fontcolor="blue", - penwidth="1", - fillcolor="white", - fontname="Courier New", - shape="none", - ) - - # wrapper -> wrapper - for i in range(len(second_wrapper) - 1, 0, -1): - wrapper.edge( - f"{second_wrapper[i].full_name}", - f"{second_wrapper[i - 1].full_name}", - "calls", - fontname="Courier New", - ) - - with dot.subgraph(name="cluster_1") as native_call_subgraph: - native_call_subgraph.attr( - style="rounded", - penwidth="1", - fillcolor="white", - fontname="Courier New", - shape="box", - ) - native_call_subgraph.attr(label="Native API Calls", fontname="Courier New Bold") - # Native API Calls - - native_call_subgraph.node( - f"{first_api.full_name}", - label=f"Class: {first_api.class_name}\nMethod: {first_api.name}", - fontcolor="blue", - shape="none", - fontname="Courier New", - ) - native_call_subgraph.node( - f"{second_api.full_name}", - label=f"Class: {second_api.class_name}\nMethod: {second_api.name}", - fontcolor="blue", - shape="none", - fontname="Courier New", - ) - - # mutual parent function -> the first node of each node - - if first_call != first_api: - - dot.edge( - f"{parent_function.full_name}", - f"{first_wrapper[-1].full_name}", - "First Call", - fontname="Courier New", - ) - - dot.edge( - f"{first_wrapper[0].full_name}", - f"{first_api.full_name}", - "calls", - fontname="Courier New", - ) - else: - dot.edge( - f"{parent_function.full_name}", - f"{first_api.full_name}", - "First Call", - fontname="Courier New", - ) - - if second_call != second_api: - dot.edge( - f"{parent_function.full_name}", - f"{second_wrapper[-1].full_name}", - "Second Call", - fontname="Courier New", - ) - - dot.edge( - f"{second_wrapper[0].full_name}", - f"{second_api.full_name}", - "calls", - fontname="Courier New", - ) - else: - dot.edge( - f"{parent_function.full_name}", - f"{second_api.full_name}", - "Second Call", - fontname="Courier New", - ) - - dot.render( - f"call_graph_image/{parent_function.name}_{first_call.name}_{second_call.name}" - ) - - - -select_label_menu -======================= - -**The algorithm of select_label_menu** - -The ``select_label_menu`` method allows users to select labels shown in the radar chart. - -.. code-block :: TEXT - - 1. Show a checkbox dialog for label selection. - - 2. Check if the user cancels the selection. - - If YES, print "Canceled!" and exit. - - If No, continue with the following steps. - - 3. Check the number of labels the user selects is within the specified range. - - If YES, return the labels. - - If No, go back to the first step. - -Here is the flowchart of ``select_label_menu``. - -.. image:: https://i.imgur.com/ww5drta.png - - -**The code of select_label_menu** - -.. code-block:: python - - def select_label_menu(all_labels, min_labels=5, max_labels=10): - """ - allows user to select label to be shown in radar chart - :param all_labels: all label found on the rules - :param min_labels: min label to be shown on radar chart (default 5) - :param max_labels: max label to be shown on radar chart (default 10) - :return: label selected - """ - - value_pair = [(label, label) for label in all_labels] - - while True: - results_array = checkboxlist_dialog( - title="Label-base Report", - text=f"Select number of labels between {min_labels} and {max_labels}", - values=value_pair, - ).run() - - if results_array: - - if min_labels <= len(results_array) <= max_labels: - break - else: - # user selects "Cancel" to leave the program. - print("Canceled!") - sys.exit() - - return results_array - - -quark.utils.output.py -------------------------------------- - -get_rule_classification_data -============================== - -**The algorithm of get_rule_classification_data** - -The ``get_rule_classification_data`` method returns the crimes in the call graph analysis list and the cross-references of their parent functions. - -.. code-block :: TEXT - - 1. Collect the crimes in the call graph analysis list. - 2. Search for cross-references of their parent functions within the specified depth. - 3. Return the results of the two steps above. - -Here is the flowchart of ``get_rule_classification_data``. - -.. image:: https://i.imgur.com/tbrvat6.png - - -**The code of get_rule_classification_data** - -.. code-block:: python - - def get_rule_classification_data(call_graph_analysis_list, search_depth): - return _collect_crime_description( - call_graph_analysis_list - ), _search_cross_references(call_graph_analysis_list, search_depth) - diff --git a/docs/source/quark_mit_program.rst b/docs/source/quark_mit_program.rst deleted file mode 100644 index ff5bc7abe..000000000 --- a/docs/source/quark_mit_program.rst +++ /dev/null @@ -1,50 +0,0 @@ -+++++++++++++++++ -Quark MIT Program -+++++++++++++++++ - -Quark MIT aims to create a **WIN-WIN** for both new comers and the community. - -For new comers, the community helps you to build a stronger resume -by creating specific works that fit the job description of your **DREAM JOB**. - -| For the community, Quark-Engine gets new energy by the work the new comers contribute. -| And the most important of all, the Quark community gets to **GROW**. - -- **Find more details below:** - -.. image:: https://i.imgur.com/XNwGYEN.png - -Quark to You -------------- - -We help our MIT program members to build stronger resumes upon Quark-Engine in just **5** specific steps. - -.. image:: https://i.imgur.com/1Qlf03U.png - -You to Quark -------------- - -Alunies are expected to positive feedbacks and continously participation of the Quark Community (not mandatory). - -.. image:: https://i.imgur.com/xknY1Jc.png - -Better Community ------------------ - -We believe helping people is the key to build a better community. - -.. image:: https://i.imgur.com/kIJBqOn.png - -Minimum Requirements ---------------------- - -Members need to complete at least **1** goal every **6** months. - -.. image:: https://i.imgur.com/LxAVUcE.png - -Contact us ----------- - -Send a direct message to our Twitter @quarkengine to join this program! - -.. image:: https://i.imgur.com/762fgld.png \ No newline at end of file diff --git a/docs/source/quark_reports.rst b/docs/source/quark_reports.rst deleted file mode 100644 index 3f7c83436..000000000 --- a/docs/source/quark_reports.rst +++ /dev/null @@ -1,133 +0,0 @@ -++++++++++++++++++++++++++++++++++++++++ -Quark Report -++++++++++++++++++++++++++++++++++++++++ - -Easy to Use and Intuitive Report ---------------------------------------- - -Quark provides **7 flexible report formats** to boost your analysis. - -* `Summary Report`_ -* `Detail Report`_ -* `Web Report`_ -* `Label-based Report`_ -* `Behaviors Comparison Radar Chart`_ -* `Call Graph`_ -* `Rule Classification`_ - -Please see below for more details. - - .. _summary-report: - -Summary Report --------------- - -Examine with rules. - -.. code-block:: bash - - quark -a 14d9f1a92dd984d6040cc41ed06e273e.apk -s - -There is the possibility to select only one label to filter the rules: - -.. code-block:: bash - - quark -a 14d9f1a92dd984d6040cc41ed06e273e.apk -s network - - -There is also the possibility to select only one rule: - -.. code-block:: bash - - quark -a 14d9f1a92dd984d6040cc41ed06e273e.apk -s - - -.. image:: https://i.imgur.com/v7ehRW0.png - -Note that if you want to select the default rules of Quark, the path to the ruleset is ``$HOME/.quark-engine/quark-rules/rules/``. - -Detail Report -------------- - -This is how we examine a real android malware (candy corn) with one single rule (crime). - -.. code-block:: bash - - quark -a 14d9f1a92dd984d6040cc41ed06e273e.apk -d - - -There is the possibility to select only one label to filter the rules: - -.. code-block:: bash - - quark -a 14d9f1a92dd984d6040cc41ed06e273e.apk -d network - - -There is also the possibility to select only one rule: - -.. code-block:: bash - - quark -a 14d9f1a92dd984d6040cc41ed06e273e.apk -d - -.. image:: https://i.imgur.com/LFLFpvc.png - -Note that if you want to select the default rules of Quark, the path to the ruleset is ``$HOME/.quark-engine/quark-rules/rules/``. - -Web Report ----------------- - -With the following command, you can easily analyze the Android sample and output the web report. See our demo `here `_. - -.. code-block:: python - - quark -a sample.apk -s -w quark_report.html - - -.. image:: https://i.imgur.com/fNc3mC0.jpg - -Label-based Report ------------------- - -Check which topic (indicated by `labels `_) of the malware is more aggressive. - -.. code-block:: bash - - quark -a Ahmyth.apk -l detailed - -.. image:: https://i.imgur.com/0GbBDfn.png - -Behaviors Comparison Radar Chart --------------------------------- - -With the following command, you can compare different APK actions based on the max confidence of rule labels and generate a radar chart. - -.. code-block:: bash - - quark -a first.apk -a second.apk -C - -.. image:: https://i.imgur.com/ClRWOei.png - -Call Graph ----------- - -You can add the ``-g`` option to the quark command, and you can get the call graph (only those rules match with 100% confidence). - -.. code-block:: bash - - quark -a Ahmyth.apk -s -g - -.. image:: https://i.imgur.com/5xcrcdN.png - -.. _rule-classification: - -Rule Classification --------------------- - -You can add the ``-c`` option to the quark command, and you can output the rules classification with the mutual parent function (only those rules match with 100% confidence). - -.. code-block:: bash - - quark -a Ahmyth.apk -s -c - -.. image:: https://i.imgur.com/YTK8V1x.png - diff --git a/docs/source/quark_script.rst b/docs/source/quark_script.rst deleted file mode 100644 index f904724f7..000000000 --- a/docs/source/quark_script.rst +++ /dev/null @@ -1,3751 +0,0 @@ -++++++++++++++++++++++++++++++++++++++++++++++++++ -Quark Script -++++++++++++++++++++++++++++++++++++++++++++++++++ - -Ecosystem for Mobile Security Tools ------------------------------------- - -Innovative & Interactive -========================= - -The goal of Quark Script aims to provide an innovative way for mobile security researchers to analyze or **pentest** the targets. - -Based on Quark, we integrate decent tools as Quark Script APIs and make them exchange valuable intelligence to each other. This enables security researchers to **interact** with staged results and perform **creative** analysis with Quark Script. - -Dynamic & Static Analysis -========================== - -In Quark script, we integrate not only static analysis tools (e.g. Quark itself) but also dynamic analysis tools (e.g. `objection `_). - -Re-Usable & Sharable -==================== - -Once the user creates a Quark script for specific analysis scenario. The script can be used in another targets. Also, the script can be shared to other security researchers. This enables the exchange of knowledges. - -More APIs to come -================== -Quark Script is now in a beta version. We'll keep releasing practical APIs and analysis scenarios. - - -Quickstart ------------ - -| In this tutorial, we will learn how to install and run Quark Script with a very easy example. -| We show how to detect CWE-798 in ovaa.apk. - -Step 1: Environments Requirements -================================== -- Quark Script requires Python 3.10 or above. - -Step 2: Install Quark Engine -============================= - -You can install Quark Engine by running: - -:: - - $ pip3 install quark-engine - - -Step 3: Prepare Quark Script, Detection Rule and the Sample File -================================================================ - -1. Get the CWE-798 Quark Script and the detection rule `here `_. -2. Get the sampe file (ovaa.apk) `here `_. -3. Put the script, detection rule, and sample file in the same directory. -4. Edit accordingly to the file names: - -.. code-block:: python - - SAMPLE_PATH = "ovaa.apk" - RULE_PATH = "findSecretKeySpec.json" - - -Now you are ready to run the script! - -Step 4: Run the script -====================== - -:: - - $ python3 CWE-798.py - - -You should now see the detection result in the terminal. - -:: - - Found hard-coded AES key 49u5gh249gh24985ghf429gh4ch8f23f - - -Introduce of Quark Script APIs ------------------------------- - -findMethodInAPK(samplePath, targetMethod) -========================================= - -- **Description**: Find the target method in APK -- **params**: - 1. samplePath: Target file - 2. targetMethod: A python list contains class name, method name, and descriptor of target method -- **return**: Python list contains caller method instance of target method - -checkMethodCalls(samplePath, targetMethod, checkMethods) -========================================================= - -- **Description**: Check any of the specific methods shown in the target method. -- **params**: - 1. samplePath: target file - 2. targetMethod: python list contains the class name, method name, and descriptor of the target method or a Method Object - 3. checkMethods: python list contains the class name, method name, and descriptor of the target method -- **return**: bool that indicates if the specific methods are called or defined within a target method or not - -findMethodImpls(samplePath, targetMethod) -========================================================= - -- **Description**: Find all implementations of a specified method in the APK. -- **params**: - 1. samplePath: target file - 2. targetMethod: python list contains the class name, method name, and descriptor of the target method -- **return**: python list contains the method implementations of the target method - -isMethodReturnAlwaysTrue(samplePath, targetMethod) -========================================================= - -- **Description**: Check if a method always returns True. -- **params**: - 1. samplePath: target file - 2. targetMethod: python list contains the class name, method name, and descriptor of the target method -- **return**: True/False - -Rule(rule.json) -=============== - -- **Description**: Making detection rule a rule instance -- **params**: Path of a single Quark rule -- **return**: Quark rule instance - -runQuarkAnalysis(SAMPLE_PATH, ruleInstance) -=========================================== - -- **Description**: Given detection rule and target sample, this instance runs the basic Quark analysis. -- **params**: - 1. SAMPLE_PATH: Target file - 2. ruleInstance: Quark rule object -- **return**: quarkResult instance - -quarkResultInstance.behaviorOccurList -===================================== - -- **Description**: List that stores instances of detected behavior in different part of the target file. -- **params**: none -- **return**: detected behavior instance - -quarkResultInstance.getAllStrings(none) -======================================= - -- **Description**: Get all strings inside the target APK file. -- **params**: none -- **return**: python list containing all strings inside the target APK file. - -quarkResultInstance.isHardcoded(argument) -========================================== - -- **Description**: Check if the argument is hardcoded into the APK. -- **params**: - 1. argument: string value that is passed in when a method is invoked -- **return**: True/False - -quarkResultInstance.findMethodInCaller(callerMethod, targetMethod) -================================================================== -- **Description**: Find target method in caller method. -- **params**: - 1. callerMethod: python list contains class name, method name and descriptor of caller method. - 2. targetMethod: python list contains class name, method name and descriptor of target method. -- **return**: python list contains target method instances. - -behaviorInstance.firstAPI.fullName -================================== - -- **Description**: Show the name of the first key API called in this behavior. -- **params**: none -- **return**: API name - -behaviorInstance.secondAPI.fullName -=================================== - -- **Description**: Show the name of the second key API called in this behavior. -- **params**: none -- **return**: API name - -behaviorInstance.hasString(pattern, isRegex) -============================================ - -- **Description**: Check if the arguments of the two APIs contain the string. -- **params**: - 1. pattern: string that may appear in the arguments - 2. isRegex: consider the string as a regular expression if True, defaults to False -- **return**: the matched string - -behaviorInstance.hasUrl(none) -============================= - -- **Description**: Check if the behavior contains urls. -- **params**: none -- **return**: python list containing all detected urls. - -behaviorInstance.methodCaller -============================= - -- **Description**: Find method who calls this behavior (API1 & API2). -- **params**: none -- **return**: method instance - -behaviorInstance.getParamValues(none) -===================================== - -- **Description**: Get parameter values that API1 sends to API2 in the behavior. -- **params**: none -- **return**: python list containing parameter values. - -behaviorInstance.isArgFromMethod(targetMethod) -============================================== - -- **Description**: Check if there are any arguments from the target method. -- **params**: - 1. targetMethod: python list contains class name, method name, and descriptor of target method -- **return**: True/False - -behaviorInstance.getMethodsInArgs(none) -============================================== - -- **Description**: Get the methods which the arguments in API2 has passed through. -- **params**: none -- **return**: python list containing method instances - -methodInstance.getXrefFrom(none) -================================ - -- **Description**: Find out who call this method. -- **params**: none -- **return**: python list containing caller methods. - -methodInstance.getXrefTo(none) -============================== - -- **Description**: Find out who this method called. -- **params**: none -- **return**: python list containing tuples (callee methods, index). - -methodInstance.getArguments(none) -================================== - -- **Description**: Get arguments from method. -- **params**: none -- **return**: python list containing arguments. - -methodInstance.findSuperclassHierarchy(none) -============================================= - -- **Description**: Find all superclasses of this method object. -- **params**: none -- **return**: Python list contains all superclass names of this method. - -Objection(host) -=============== - -- **Description**: Create an instance for Objection (dynamic analysis tool). -- **params**: Monitoring IP:port -- **return**: objection instance - -objInstance.hookMethod(method, watchArgs, watchBacktrace, watchRet) -===================================================================== - -- **Description**: Hook the target method with Objection. -- **params**: - 1. method: the target API. (type: str or method instance) - 2. watchArgs: Return Args information if True. (type: boolean) - 3. watchBacktrace: Return backtrace information if True. (type: boolean) - 4. watchRet: Return the return information of the target API if True. (type: boolean) -- **return**: none - -runFridaHook(apkPackageName, targetMethod, methodParamTypes, secondToWait) -============================================================================ - -- **Description**: Track calls to the specified method for given seconds. -- **params**: - 1. apkPackageName: the package name of the target APP - 2. targetMethod: the target API - 3. methodParamTypes: string that holds the parameters used by the target API - 4. secondToWait: seconds to wait for method calls, defaults to 10 -- **return**: FridaResult instance - -checkClearText(inputString) -============================ - -- **Description**: Check the decrypted value of the input string. -- **params**: - 1. inputString: string to be checked -- **return**: the decrypted value - -getActivities(samplePath) -========================== -- **Description**: Get activities from the manifest of target sample. -- **params**: - 1. samplePath: the file path of target sample -- **return**: python list containing activities - -activityInstance.hasIntentFilter(none) -====================================== -- **Description**: Check if the activity has an intent-filter. -- **params**: none -- **return**: True/False - -activityInstance.isExported(none) -================================== -- **Description**: Check if the activity set ``android:exported=true``. -- **params**: none -- **return**: True/False - -getReceivers(samplePath) -========================== -- **Description**: Get receivers from a target sample. -- **params**: - 1. samplePath: target sample -- **return**: python list containing receivers - -receiverInstance.hasIntentFilter(none) -====================================== -- **Description**: Check if the receiver has an intent-filter. -- **params**: none -- **return**: True/False - -receiverInstance.isExported(none) -================================== -- **Description**: Check if the receiver is exported. -- **params**: none -- **return**: True/False - -getApplication(samplePath) -========================== -- **Description**: Get the application element from the manifest file of the target sample. -- **params**: - 1. samplePath: the file path of the target sample -- **return**: the application element of the target sample - -applicationInstance.isDebuggable(none) -====================================== -- **Description**: Check if the application element sets ``android:debuggable=true``. -- **params**: none -- **return**: True/False - -getProviders(samplePath) -========================== -- **Description**: Get provider elements from the manifest file of the target sample. -- **params**: - 1. samplePath: the file path of target sample -- **return**: python list containing provider elements - -providerInstance.isExported(none) -================================== -- **Description**: Check if the provider element set ``android:exported=true``. -- **params**: none -- **return**: True/False - -Analyzing real case (InstaStealer) using Quark Script ------------------------------------------------------- - -Quark Script that dynamic hooks the method containing urls -=========================================================== - -The scenario is simple! We'd like to dynamic hooking the methods in the malware that contains urls. We can use APIs above to write Quark Script. - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - from quark.script.objection import Objection - - SAMPLE_PATH = "6f032.apk" - RULE_PATH = "00211.json" - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for behaviorInstance in quarkResult.behaviorOccurList: - detectedUrl = behaviorInstance.hasUrl() - - if detectedUrl: - print(f"\nDetected Behavior -> {ruleInstance.crime}") - print(f"\nDetected Url -> {detectedUrl}") - - method = behaviorInstance.methodCaller - print(f"\nThe detected behavior was called by -> {method.fullName}") - - print("\nAttempt to hook the method:") - obj = Objection("127.0.0.1:8888") - - obj.hookMethod(method, - watchArgs=True, - watchBacktrace=True, - watchRet=True) - print(f"\tHook -> {method.fullName}") - - for methodCaller in method.getXrefFrom(): - obj.hookMethod(methodCaller, - watchArgs=True, - watchBacktrace=True, - watchRet=True) - print(f"\tHook -> {methodCaller.fullName}") - - for methodCallee, _ in method.getXrefTo(): - obj.hookMethod(methodCallee, - watchArgs=True, - watchBacktrace=True, - watchRet=True) - print(f"\tHook -> {methodCallee.fullName}") - - print("\nSee the hook results in Objection's terminal.") - -.. note:: - Please make sure you have the dynamic analysis environment ready before executing the script. - - 1. Objection installed and running. Check the guideline `here `_. - 2. Android Virtual Machine with frida installed. Check the guideline `here `_. - 3. Or a rooted Android Device (Google Pixel 6) with frida installed. Check the root guideline `here `_, frida install guideline is the `same `_ with Android Virtual Machine. - -Quark Script Result -=================== - -.. image:: https://i.imgur.com/elztZdC.png - -Logs on the Objection terminal (hooking) -======================================== - -.. image:: https://i.imgur.com/XrtfgjY.jpg - -Method (callComponentMethod) with urls is detected triggered! -============================================================= - -.. image:: https://i.imgur.com/ryV3f57.jpg - - -Detect CWE-798 in Android Application -------------------------------------------------- - -This scenario seeks to find **hard-coded credentials** in the APK file. - -CWE-798: Use of Hard-coded Credentials -====================================== - -We analyze the definition of CWE-798 and identify its characteristics. - -See `CWE-798 `_ for more details. - -.. image:: https://imgur.com/rF8J8hE.png - -Code of CWE-798 in ovaa.apk -============================ - -We use the `ovaa.apk `_ sample to explain the vulnerability code of CWE-798. - -.. image:: https://imgur.com/Cg7DacP.png - -CWE-798 Detection Process Using Quark Script API -================================================= - -.. image:: https://imgur.com/R8CfDqD.png - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -First, we design a detection rule ``findSecretKeySpec.json`` to spot on behavior using the constructor ``SecretKeySpec``. Second, we get all the parameter values from this constructor. Then, we parse the AES key from the parameter values. Finally, we check if the AES key is hardcoded in the APK file. If the answer is **YES**, BINGO!!! We find hard-coded credentials in the APK file. - -Quark Script: CWE-798.py -======================== - -.. image:: https://imgur.com/IOyrqDc.png - -.. code-block:: python - - import re - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "ovaa.apk" - RULE_PATH = "findSecretKeySpec.json" - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for secretKeySpec in quarkResult.behaviorOccurList: - - firstParam = secretKeySpec.secondAPI.getArguments()[1] - secondParam = secretKeySpec.secondAPI.getArguments()[2] - - if secondParam == "AES": - AESKey = re.findall(r"\((.*?)\)", firstParam)[1] - - if quarkResult.isHardcoded(AESKey): - print(f"Found hard-coded {secondParam} key {AESKey}") - -Quark Rule: findSecretKeySpec.json -=================================== - -.. image:: https://imgur.com/2BYOE70.png - -.. code-block:: json - - { - "crime": "Detect APK using SecretKeySpec.", - "permission": [], - "api": [ - { - "descriptor": "()[B", - "class": "Ljava/lang/String;", - "method": "getBytes" - }, - { - "descriptor": "([BLjava/lang/String;)V", - "class": "Ljavax/crypto/spec/SecretKeySpec;", - "method": "" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-798.py - Found hard-coded AES key 49u5gh249gh24985ghf429gh4ch8f23f - - - -Detect CWE-94 in Android Application -------------------------------------- - -This scenario seeks to find **code injection** in the APK file. - -CWE-94: Improper Control of Generation of Code -=============================================== - -We analyze the definition of CWE-94 and identify its characteristics. - -See `CWE-94 `_ for more details. - -.. image:: https://imgur.com/M9Jlgrn.png - -Code of CWE-94 in ovaa.apk -=========================== - -We use the `ovaa.apk `_ sample to explain the vulnerability code of CWE-94. - -.. image:: https://imgur.com/MdlAnvu.png - -CWE-94 Detection Process Using Quark Script API -================================================ - -Let's use the above APIs to show how the Quark script finds this vulnerability. - -First, we design a detection rule ``loadExternalCode.json`` to spot on behavior using the method ``createPackageContext``. Then, we find the caller method that calls the ``createPackageContext``. Finally, we check if the method ``checkSignatures`` is called in the caller method for verification. - -.. image:: https://imgur.com/6cPBMWP.jpg - -Quark Script: CWE-94.py -======================== - -.. image:: https://imgur.com/Aw26Lv2.jpg - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "ovaa.apk" - RULE_PATH = "loadExternalCode.json" - - targetMethod = [ - "Landroid/content/pm/PackageManager;", - "checkSignatures", - "(Ljava/lang/String;Ljava/lang/String;)I" - ] - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for ldExternalCode in quarkResult.behaviorOccurList: - - callerMethod = [ - ldExternalCode.methodCaller.className, - ldExternalCode.methodCaller.methodName, - ldExternalCode.methodCaller.descriptor - ] - - if not quarkResult.findMethodInCaller(callerMethod, targetMethod): - print(f"Method: {targetMethod[1]} not found!") - print(f"CWE-94 is detected in {SAMPLE_PATH}") - -Quark Rule: loadExternalCode.json -================================== - -.. image:: https://imgur.com/IHENeJx.jpg - -.. code-block:: json - - { - "crime": "Load external code from other APK.", - "permission": [], - "api": [ - { - "descriptor": "(Ljava/lang/String;I)Landroid/content/Context;", - "class": "", - "method": "createPackageContext" - }, - { - "descriptor": "(Ljava/lang/String;)Ljava/lang/Class;", - "class": "Ljava/lang/ClassLoader;", - "method": "loadClass" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-94.py - Method: checkSignatures not found! - CWE-94 is detected in ovaa.apk - - - - -Detect CWE-921 in Android Application --------------------------------------- - -This scenario seeks to find the **unsecured storage mechanism of sensitive data** in the APK file. - -CWE-921: Storage of Sensitive Data in a Mechanism without Access Control -======================================================================== - -We analyze the definition of CWE-921 and identify its characteristics. - -See `CWE-921 `_ for more details. - -.. image:: https://imgur.com/2zlPLHe.jpg - - -Code of CWE-921 in ovaa.apk -============================ - -We use the `ovaa.apk `_ sample to explain the vulnerability code of CWE-921. - -.. image:: https://imgur.com/2u5iL1K.jpg - -CWE-921 Detection Process Using Quark Script API -================================================= - -.. image:: https://imgur.com/qHOMqKy.jpg - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -First, we design a detection rule ``checkFileExistence.json`` to spot on behavior that checks if a file exists on a given storage mechanism. Then, we use API ``methodInstance.getArguments()`` to get the file path. Finally, CWE-921 is found if the file path contains the keyword ``sdcard``. - -Quark Script: CWE-921.py -======================== - -.. image:: https://imgur.com/HULgyIy.jpg - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "ovaa.apk" - RULE_PATH = "checkFileExistence.json" - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for existingFile in quarkResult.behaviorOccurList: - filePath = existingFile.secondAPI.getArguments()[0] - if "sdcard" in filePath: - print(f"This file is stored inside the SDcard\n") - print(f"CWE-921 is detected in {SAMPLE_PATH}.") - -Quark Rule: checkFileExistence.json -==================================== - -.. image:: https://imgur.com/zRiYLtS.jpg - -.. code-block:: json - - { - "crime": "Check file existence", - "permission": [], - "api": [ - { - "descriptor": "(Ljava/lang/String;)V", - "class": "Ljava/io/File;", - "method": "" - }, - { - "descriptor": "()Z", - "class": "Ljava/io/File;", - "method": "exists" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-921.py - This file is stored inside the SDcard - - CWE-921 is detected in ovaa.apk. - - - - -Detect CWE-312 in Android Application --------------------------------------- - -This scenario seeks to find **cleartext storage of sensitive data** in the APK file. - -CWE-312: Cleartext Storage of Sensitive Information -==================================================== - -We analyze the definition of CWE-312 and identify its characteristics. - -See `CWE-312 `_ for more details. - -.. image:: https://imgur.com/mD2uXUy.jpg - -Code of CWE-312 in ovaa.apk -============================ - -We use the `ovaa.apk `_ sample to explain the vulnerability code of CWE-312. - -.. image:: https://imgur.com/MfnYIYy.jpg - -CWE-312 Detection Process Using Quark Script API -================================================= - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -We have designed a `Frida `_ script ``agent.js`` to hook a specified method and get the arguments when the method is called. It can be found in `quark-engine/quark/script/frida `_. - -To begin with, we hook the method ``putString`` to catch its arguments. Then, we check if sensitive information like email or password is passed. Finally, we use ``checkClearText`` imported from `Ares `_ to check if the arguments are cleartext. If both **YES**, CWE-312 vulnerability might be caused. - -.. image:: https://imgur.com/eNjm3ES.jpg - -Quark Script: CWE-312.py -======================== - -.. image:: https://imgur.com/rxMPZX8.jpg - -.. code-block:: python - - from quark.script.frida import runFridaHook - from quark.script.ares import checkClearText - - APP_PACKAGE_NAME = "oversecured.ovaa" - - TARGET_METHOD = "android.app." "SharedPreferencesImpl$EditorImpl." "putString" - - METHOD_PARAM_TYPE = "java.lang.String," "java.lang.String" - - fridaResult = runFridaHook( - APP_PACKAGE_NAME, TARGET_METHOD, METHOD_PARAM_TYPE, secondToWait=10 - ) - - for putString in fridaResult.behaviorOccurList: - - firstParam = putString.firstAPI.getArguments() - secondParam = putString.secondAPI.getArguments() - - if firstParam in ["email", "password"] and secondParam == checkClearText( - secondParam - ): - - print( - "The CWE-312 vulnerability is found. " - f'The cleartext is "{secondParam}"' - ) - - -Frida Script: agent.js -======================= - - -.. code-block:: javascript - - // -*- coding: utf-8 -*- - // This file is part of Quark-Engine - https://github.com/quark-engine/quark-engine - // See the file 'LICENSE' for copying permission. - - /*global Java, send, rpc*/ - function replaceMethodImplementation(targetMethod, classAndMethodName, methodParamTypes, returnType) { - targetMethod.implementation = function () { - let callEvent = { - "type": "CallCaptured", - "identifier": [classAndMethodName, methodParamTypes, returnType], - "paramValues": [] - }; - - for (const arg of arguments) { - callEvent["paramValues"].push((arg || "(none)").toString()); - } - - send(JSON.stringify(callEvent)); - return targetMethod.apply(this, arguments); - }; - } - - function watchMethodCall(classAndMethodName, methodParamTypes) { - if (classAndMethodName == null || methodParamTypes == null) { - return; - } - - const indexOfLastSeparator = classAndMethodName.lastIndexOf("."); - const classNamePattern = classAndMethodName.substring(0, indexOfLastSeparator); - const methodNamePattern = classAndMethodName.substring(indexOfLastSeparator + 1); - - Java.perform(() => { - const classOfTargetMethod = Java.use(classNamePattern); - const possibleMethods = classOfTargetMethod[`${methodNamePattern}`]; - - if (typeof possibleMethods === "undefined") { - const failedToWatchEvent = { - "type": "FailedToWatch", - "identifier": [classAndMethodName, methodParamTypes] - }; - - send(JSON.stringify(failedToWatchEvent)); - return; - } - - possibleMethods.overloads.filter((possibleMethod) => { - const paramTypesOfPossibleMethod = possibleMethod.argumentTypes.map((argument) => argument.className); - return paramTypesOfPossibleMethod.join(",") === methodParamTypes; - }).forEach((matchedMethod) => { - const retType = matchedMethod.returnType.name; - replaceMethodImplementation(matchedMethod, classAndMethodName, methodParamTypes, retType); - } - ); - - }); - } - - rpc.exports["watchMethodCall"] = (classAndMethodName, methodParamTypes) => watchMethodCall(classAndMethodName, methodParamTypes); - - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-312.py - The CWE-312 vulnerability is found. The cleartext is "test@email.com" - The CWE-312 vulnerability is found. The cleartext is "password" - - -Detect CWE-89 in Android Application -------------------------------------- - -This scenario seeks to find **SQL injection** in the APK file. - -CWE-89 Improper Neutralization of Special Elements used in an SQL Command -========================================================================== - -We analyze the definition of CWE-89 and identify its characteristics. - -See `CWE-89 `_ for more details. - -.. image:: https://imgur.com/Yx9vIS2.jpg - -Code of CWE-89 in AndroGoat.apk -================================ - -We use the `AndroGoat.apk `_ sample to explain the vulnerability code of CWE-89. - -.. image:: https://imgur.com/QWvu8te.jpg - -CWE-89 Detection Process Using Quark Script API -================================================ - -.. image:: https://imgur.com/gvPBB3v.jpg - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -First, we design a detection rule ``executeSQLCommand.json`` to spot on behavior using SQL command Execution. Then, we use API ``behaviorInstance.isArgFromMethod(targetMethod)`` to check if ``append`` uses the value of ``getText`` as the argument. If yes, we confirmed that the SQL command string is built from user input, which will cause CWE-89 vulnerability. - -Quark Script: CWE-89.py -======================== - -.. image:: https://imgur.com/B6Mfp2L.jpg - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "AndroGoat.apk" - RULE_PATH = "executeSQLCommand.json" - - targetMethod = [ - "Landroid/widget/EditText;", # class name - "getText", # method name - "()Landroid/text/Editable;", # descriptor - ] - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for sqlCommandExecution in quarkResult.behaviorOccurList: - if sqlCommandExecution.isArgFromMethod( - targetMethod - ): - print(f"CWE-89 is detected in {SAMPLE_PATH}") - -Quark Rule: executeSQLCommand.json -=================================== - -.. image:: https://imgur.com/aYnt5oq.jpg - -.. code-block:: json - - { - "crime": "Execute SQL Command", - "permission": [], - "api": [ - { - "class": "Ljava/lang/StringBuilder;", - "method": "append", - "descriptor": "(Ljava/lang/String;)Ljava/lang/StringBuilder;" - }, - { - "class": "Landroid/database/sqlite/SQLiteDatabase;", - "method": "rawQuery", - "descriptor": "(Ljava/lang/String; [Ljava/lang/String;)Landroid/database/Cursor;" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-89.py - - CWE-89 is detected in AndroGoat.apk - - -Detect CWE-926 in Android Application ----------------------------------------- - -This scenario seeks to find **Improper Export of Android Application Components** in the APK file. - -CWE-926 Improper Export of Android Application Components -============================================================ - -We analyze the definition of CWE-926 and identify its characteristics. - -See `CWE-926 `_ for more details. - -.. image:: https://imgur.com/Km8wtGs.jpg - -Code of CWE-926 in dvba.apk -========================================= - -We use the `dvba.apk `_ sample to explain the vulnerability code of CWE-926. - -.. image:: https://imgur.com/KoOt5ii.jpg - -CWE-926 Detection Process Using Quark Script API -================================================ - -.. image:: https://i.postimg.cc/Qtg97yD0/jie-tu-2025-10-30-wan-shang7-30-04.png - -Let's use the above APIs to show how the Quark script finds this vulnerability. - -First, we use Quark API ``getActivities(samplePath)`` to get all activity data in the manifest. Then, we use ``activityInstance.hasIntentFilter()`` to check if the activities have ``intent-filter``. Also, we use ``activityInstance.isExported()`` to check if the activities set the attribute ``android:exported=true``. If both are **true**, then the APK exports the component for use by other applications. That may cause CWE-926 vulnerabilities. - -Quark Script: CWE-926.py -======================== - -.. image:: https://i.postimg.cc/KcwSLv9L/jie-tu-2025-10-30-wan-shang7-32-01.png - -.. code-block:: python - - from quark.script import * - - SAMPLE_PATH = "dvba.apk" - - for activityInstance in getActivities(SAMPLE_PATH): - - if activityInstance.hasIntentFilter() and activityInstance.isExported(): - print(f"CWE-926 is detected in the activity, {activityInstance}") - -Quark Script Result -===================== - -.. code-block:: TEXT - - $ python3 CWE-926.py - CWE-926 is detected in the activity, com.app.damnvulnerablebank.CurrencyRates - CWE-926 is detected in the activity, com.app.damnvulnerablebank.SplashScreen - - -Detect CWE-749 in Android Application ----------------------------------------------- - -This scenario seeks to find **exposed methods or functions** in the APK file. - -CWE-749 Exposed Dangerous Method or Function -================================================= - -We analyze the definition of CWE-749 and identify its characteristics. - -See `CWE-749 `_ for more details. - -.. image:: https://imgur.com/hmihGze.png - -Code of CWE-749 in MSTG-Android-Java.apk -============================================= - -We use the `MSTG-Android-Java.apk `_ sample to explain the vulnerability code of CWE-749. - -.. image:: https://imgur.com/KiA0vRD.png - -CWE-749 Detection Process Using Quark Script API -================================================ - -.. image:: https://i.postimg.cc/xjWjXH3P/jie-tu-2025-12-12-wan-shang11-01-40.png - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -First, we design a detection rule ``configureJsExecution.json`` to spot on behavior using the method ``setJavascriptEnabled``. Then, we use the API ``methodInstance.getArguments()`` to check if it enables JavaScript execution on websites. Finally, we look for calls to the method ``addJavaScriptInterface`` in the caller method. If yes, the APK exposes dangerous methods or functions to websites. That causes CWE-749 vulnerability. - -Quark Script: CWE-749.py -======================== - -.. image:: https://i.postimg.cc/TwKGwYyH/jie-tu-2025-12-12-wan-shang11-02-28.png - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "MSTG-Android-Java.apk" - RULE_PATH = "configureJsExecution.json" - - targetMethod = [ - "Landroid/webkit/WebView;", - "addJavascriptInterface", - "(Ljava/lang/Object; Ljava/lang/String;)V" - ] - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for configureJsExecution in quarkResult.behaviorOccurList: - - caller = configureJsExecution.methodCaller - secondAPI = configureJsExecution.secondAPI - - enableJS = secondAPI.getArguments()[1] - exposeAPI = quarkResult.findMethodInCaller(caller, targetMethod) - - if enableJS and exposeAPI: - print(f"CWE-749 is detected in method, {caller.fullName}") - -Quark Rule: configureJsExecution.json -===================================== - -.. code-block:: json - - { - "crime": "Configure JavaScript execution on websites", - "permission": [], - "api": [ - { - "class": "Landroid/webkit/WebView;", - "method": "getSettings", - "descriptor": "()Landroid/webkit/WebSettings;" - }, - { - "class": "Landroid/webkit/WebSettings;", - "method": "setJavaScriptEnabled", - "descriptor": "(Z)V" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-749.py - - CWE-749 is detected in method, Lsg/vp/owasp_mobile/OMTG_Android/OMTG_ENV_005_WebView_Remote; onCreate (Landroid/os/Bundle;)V - CWE-749 is detected in method, Lsg/vp/owasp_mobile/OMTG_Android/OMTG_ENV_005_WebView_Local; onCreate (Landroid/os/Bundle;)V - - -Detect CWE-532 in Android Application --------------------------------------- - -This scenario seeks to find **insertion of sensitive information into Log file** in the APK file. - -CWE-532: Insertion of Sensitive Information into Log File -========================================================== - -We analyze the definition of CWE-532 and identify its characteristics. - -See `CWE-532 `_ for more details. - -.. image:: https://imgur.com/6WzpyId.jpg - -Code of CWE-532 in dvba.apk -============================ - -We use the `dvba.apk `_ sample to explain the vulnerability code of CWE-532. - -.. image:: https://imgur.com/cLzBvh2.jpg - -CWE-532 Detection Process Using Quark Script API -================================================= - -.. image:: https://imgur.com/KLbnflF.jpg - -Let's use the above APIs to show how the Quark script finds this vulnerability. - -First, we use the API ``findMethodInAPK(samplePath, targetMethod)`` to locate ``log.d`` method. Then we use API ``methodInstance.getArguments()`` to get the argument that input to ``log.d``. Finally, we use some keywords such as "token", "password", and "decrypt" to check if arguments include sensitive data. If the answer is **YES**, that may cause sensitive data leakage into log file. - -You can use your own keywords in the keywords list to detect sensitive data. - -Quark Script: CWE-532.py -========================= - -.. image:: https://imgur.com/L9Ciqlp.jpg - -.. code-block:: python - - from quark.script import findMethodInAPK - - SAMPLE_PATH = "dvba.apk" - TARGET_METHOD = [ - "Landroid/util/Log;", # class name - "d", # method name - "(Ljava/lang/String; Ljava/lang/String;)I" # descriptor - ] - CREDENTIAL_KEYWORDS = [ - "token", - "decrypt", - "password" - ] - - methodsFound = findMethodInAPK(SAMPLE_PATH, TARGET_METHOD) - - for debugLogger in methodsFound: - arguments = debugLogger.getArguments() - - for keyword in CREDENTIAL_KEYWORDS: - if keyword in arguments[1]: - print(f"CWE-532 is detected in method, {debugLogger.fullName}") - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python CWE-532.py - CWE-532 is detected in method, Lcom/google/firebase/auth/FirebaseAuth; d (Lc/c/b/h/o;)V - - - -Detect CWE-780 in Android Application ------------------------------------------ - -This scenario seeks to find **the use of the RSA algorithm without Optimal Asymmetric Encryption Padding (OAEP)** in the APK file. - -CWE-780 Use of RSA Algorithm without OAEP -============================================ - -We analyze the definition of CWE-780 and identify its characteristics. - -See `CWE-780 `_ for more details. - -.. image:: https://imgur.com/veZNZcg.png - -Code of CWE-780 in dvba.apk -========================================= - -We use the `MSTG-Android-Java.apk `_ sample to explain the vulnerability code of CWE-780. - -.. image:: https://imgur.com/c03senv.png - -CWE-780 Detection Process Using Quark Script API -================================================= - -.. image:: https://i.postimg.cc/x8zTSxpq/jie-tu-2025-11-14-shang-wu10-30-26.png - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -We first design a detection rule ``useOfCryptographicAlgo.json`` to spot on behavior using the cryptographic algorithm. Then, we use API ``behaviorInstance.hasString(pattern, isRegex)`` to filter behaviors using the RSA algorithm. Finally, we use the same API to check if the algorithm runs without the OAEP scheme. If the answer is YES, the plaintext is predictable. - -Quark Script: CWE-780.py -========================= - -.. image:: https://i.postimg.cc/fTYxNZP6/jie-tu-2025-11-14-shang-wu10-31-55.png - -.. code-block:: python - - from quark.script import Rule, runQuarkAnalysis - - SAMPLE_PATH = "MSTG-Android-Java.apk" - RULE_PATH = "useOfCryptographicAlgo.json" - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for useCryptographicAlgo in quarkResult.behaviorOccurList: - methodCaller = useCryptographicAlgo.methodCaller - - if useCryptographicAlgo.hasString( - "RSA" - ) and not useCryptographicAlgo.hasString("OAEP"): - print(f"CWE-780 is detected in method, {methodCaller.fullName}") - - -Quark Rule: useOfCryptographicAlgo.json -======================================= - -.. code-block:: json - - { - "crime": "Use of cryptographic algorithm", - "permission": [], - "api": [ - { - "class": "Ljavax/crypto/Cipher;", - "method": "getInstance", - "descriptor": "(Ljava/lang/String; Ljava/lang/String;)Ljavax/crypto/Cipher" - }, - { - "class": "Ljavax/crypto/Cipher;", - "method": "init", - "descriptor": "(I Ljava/security/Key;)V" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-780.py - CWE-780 is detected in method, Lsg/vp/owasp_mobile/OMTG_Android/OMTG_DATAST_001_KeyStore; encryptString (Ljava/lang/String;)V - - - - -Detect CWE-319 in Android Application --------------------------------------- - -This scenario seeks to find **Cleartext Transmission of Sensitive Information** in the APK file. - -CWE-319 Cleartext Transmission of Sensitive Information -======================================================== - -We analyze the definition of CWE-319 and identify its characteristics. - -See `CWE-319 `_ for more details. - -.. image:: https://imgur.com/hjEYP5b.jpg - -Code of CWE-319 in ovaa.apk -============================ - -We use the `ovaa.apk `_ sample to explain the vulnerability code of CWE-319. - -.. image:: https://imgur.com/wCYfTNx.jpg - -CWE-319 Detection Process Using Quark Script API -================================================= - -.. image:: https://imgur.com/H1FgUtE.jpg - -Let’s use the above APIs to show how the Quark script finds this vulnerability. This sample uses the package ``Retrofit`` to request Web APIs, but the APIs use cleartext protocols. - -We first design a detection rule ``setRetrofitBaseUrl.json`` to spot on behavior that sets the base URL of the Retrofit instance. Then, we loop through a custom list of cleartext protocol schemes and use API ``behaviorInstance.hasString(pattern, isRegex)`` to filter if there are arguments that are URL strings with cleartext protocol. - -If the answer is **YES**, CWE-319 vulnerability is caused. - -Quark Script: CWE-319.py -========================= - -.. image:: https://imgur.com/CktArDJ.jpg - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "./ovaa.apk" - RULE_PATH = "setRetrofitBaseUrl.json" - - PROTOCOL_KEYWORDS = [ - "http", - "smtp", - "ftp" - ] - - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for setRetrofitBaseUrl in quarkResult.behaviorOccurList: - for protocol in PROTOCOL_KEYWORDS: - - regexRule = f"{protocol}://[0-9A-Za-z./-]+" - cleartextProtocolUrl = setRetrofitBaseUrl.hasString(regexRule, True) - - if cleartextProtocolUrl: - print(f"CWE-319 detected!") - print(f"Here are the found URLs with cleartext protocol:") - print("\n".join(cleartextProtocolUrl)) - -Quark Rule: setRetrofitBaseUrl.json -==================================== - -.. image:: https://imgur.com/751Dhce.jpg - -.. code-block:: json - - { - "crime": "Set Retrofit Base Url", - "permission": [], - "api": - [ - { - "descriptor": "()V", - "class": "Lretrofit2/Retrofit$Builder;", - "method": "" - }, - { - "descriptor": "(Ljava/lang/String;)Lretrofit2/Retrofit$Builder;", - "class": "Lretrofit2/Retrofit$Builder;", - "method": "baseUrl" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-319.py - CWE-319 detected! - Here are the found URLs with cleartext protocol: - http://example.com./api/v1/ - - - - -Detect CWE-327 in Android Application --------------------------------------- - -This scenario seeks to find **Use of a Broken or Risky Cryptographic Algorithm** in the APK file. - -CWE-327 Use of a Broken or Risky Cryptographic Algorithm -========================================================= - -We analyze the definition of CWE-327 and identify its characteristics. - -See `CWE-327 `_ for more details. - -.. image:: https://imgur.com/Xfm5C9K.jpg - -Code of CWE-327 in InjuredAndroid.apk -====================================== - -We use the `InjuredAndroid.apk `_ sample to explain the vulnerability code of CWE-327. - -.. image:: https://imgur.com/R5zkGt2.jpg - -CWE-327 Detection Process Using Quark Script API -================================================= - -.. image:: https://imgur.com/2owB5Z7.jpg - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -We first design a detection rule ``useOfCryptographicAlgo.json`` to spot on behavior using cryptographic algorithms. Then, we use API ``behaviorInstance.hasString(pattern, isRegex)`` with a list to check if the algorithm is risky. If **YES**, that may cause the exposure of sensitive data. - -Quark Script CWE-327.py -======================== - -.. image:: https://imgur.com/4fa3yS0.jpg - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "InjuredAndroid.apk" - RULE_PATH = "useOfCryptographicAlgo.json" - - WEAK_ALGORITHMS = ["DES", "ARC4", "BLOWFISH"] - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for useCryptoAlgo in quarkResult.behaviorOccurList: - - caller = useCryptoAlgo.methodCaller - - for algo in WEAK_ALGORITHMS: - if useCryptoAlgo.hasString(algo): - print(f"CWE-327 is detected in method, {caller.fullName}") - -Quark Rule: useOfCryptographicAlgo.json -======================================== - -.. image:: https://imgur.com/rjRykWM.jpg - -.. code-block:: json - - { - "crime": "Use of cryptographic algorithm", - "permission": [], - "api": [ - { - "class": "Ljavax/crypto/Cipher;", - "method": "getInstance", - "descriptor": "(Ljava/lang/String;)Ljavax/crypto/Cipher" - }, - { - "class": "Ljavax/crypto/Cipher;", - "method": "init", - "descriptor": "(I Ljava/security/Key;)V" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-327.py - CWE-327 is detected in method, Lb3nac/injuredandroid/k; b (Ljava/lang/String;)Ljava/lang/String; - CWE-327 is detected in method, Lb3nac/injuredandroid/k; a (Ljava/lang/String;)Ljava/lang/String; - - - -Detect CWE-20 in Android Application -------------------------------------- - -This scenario seeks to find **Improper Input Validation** in the APK file. - -CWE-20: Improper Input Validation -================================== - -We analyze the definition of CWE-20 and identify its characteristics. - -See `CWE-20 `_ for more details. - -.. image:: https://imgur.com/eO8fepu.jpg - -Code of CWE-20 in diva.apk -=========================== - -We use the `diva.apk `_ sample to explain the vulnerability code of CWE-20. - -.. image:: https://imgur.com/nsuXYGU.jpg - -CWE-20 Detection Process Using Quark Script API -================================================ - -.. image:: https://imgur.com/C7zmwLm.jpg - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -First, we design a detection rule ``openUrlThatUserInput.json``, to spot the behavior of opening the URL that the user inputs. Then, we use API ``behaviorInstance.getMethodsInArgs()`` to get a list of methods that the URL in ``loadUrl`` passes through. Finally, we check if any validation method is in the list. If No, the APK does not validate user input. That causes CWE-20 vulnerability. - -Quark Script CWE-20.py -======================= - -.. image:: https://imgur.com/bwPqc4K.jpg - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "diva.apk" - RULE_PATH = "openUrlThatUserInput.json" - - rule = Rule(RULE_PATH) - result = runQuarkAnalysis(SAMPLE_PATH, rule) - - VALIDATE_METHODS = ["contains", "indexOf", "matches", "replaceAll"] - - for openUrl in result.behaviorOccurList: - calledMethods = openUrl.getMethodsInArgs() - - if not any( - method.methodName in VALIDATE_METHODS for method in calledMethods - ): - print(f"CWE-20 is detected in method, {openUrl.methodCaller.fullName}") - -Quark Rule: openUrlThatUserInput.json -====================================== - -.. image:: https://imgur.com/k4WT8Fb.jpg - -.. code-block:: json - - { - "crime": "Open the Url that user input", - "permission": [], - "api": [ - { - "class": "Landroid/widget/EditText;", - "method": "getText", - "descriptor": "()Landroid/text/Editable;" - }, - { - "class": "Landroid/webkit/WebView;", - "method": "loadUrl", - "descriptor": "(Ljava/lang/String;)V" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python CWE-20.py - CWE-20 is detected in method, Ljakhar/aseem/diva/InputValidation2URISchemeActivity; get (Landroid/view/View;)V - - - -Detect CWE-79 in Android Application -------------------------------------- - -This scenario seeks to find **Improper Neutralization of Input During Web Page Generation (‘Cross-site Scripting’)** in the APK file. - -CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') -============================================================================================= - -We analyze the definition of CWE-79 and identify its characteristics. - -See `CWE-79 `_ for more details. - -.. image:: https://imgur.com/3W1QpU1.png - -Code of CWE-79 in Vuldroid.apk -=============================== - -We use the `Vuldroid.apk `_ sample to explain the vulnerability code of CWE-79. - -.. image:: https://imgur.com/iv3Guwi.png - -CWE-79 Detection Process Using Quark Script API -================================================ - -.. image:: https://imgur.com/MpUjFP0.png - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -First, we design a detection rule ``loadUrlFromIntent.json`` to spot the behavior loading URL from intent data to the WebView instance. - -Next, we use API ``quarkResultInstance.findMethodInCaller(callerMethod, targetMethod)`` and ``methodInstance.getArguments()`` to check if the Javascript execution is enabled in the WebView. Finally, we check if there are any famous XSS filters. If **NO**, that may cause CWE-79 vulnerability. - -Quark Script CWE-79.py -======================= - -.. image:: https://imgur.com/NyMpLZW.png - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "Vuldroid.apk" - RULE_PATH = "loadUrlFromIntent.json" - - XSS_FILTERS = [ - [ - "Lorg/owasp/esapi/Validator;", - "getValidSafeHTML", - "(Ljava/lang/String; Ljava/lang/String; I Z)Ljava/lang/String;", - ], - [ - "Lorg/owasp/esapi/Encoder;", - "encodeForHTML", - "(Ljava/lang/String;)Ljava/lang/String;", - ], - [ - "Lorg/owasp/esapi/Encoder;", - "encodeForJavaScript", - "(Ljava/lang/String;)Ljava/lang/String;", - ], - [ - "Lorg/owasp/html/PolicyFactory;", - "sanitize", - "(Ljava/lang/String;)Ljava/lang/String;", - ], - ] - - targetMethod = ["Landroid/webkit/WebSettings;", "setJavaScriptEnabled", "(Z)V"] - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for loadUrl in quarkResult.behaviorOccurList: - caller = loadUrl.methodCaller - setJS = quarkResult.findMethodInCaller(caller, targetMethod) - enableJS = [] - - if setJS: - enableJS = setJS[0].getArguments()[1] - - if enableJS: - XSSFiltersInCaller = [ - filterAPI - for filterAPI in XSS_FILTERS - if quarkResult.findMethodInCaller(caller, filterAPI) - ] - - if not XSSFiltersInCaller: - print(f"CWE-79 is detected in method, {caller.fullName}") - -Quark Rule: loadUrlFromIntent.json -=================================== - -.. image:: https://imgur.com/m4aa4Jk.png - -.. code-block:: json - - { - "crime": "Load URL from intent to WebView", - "permission": [], - "api": [ - { - "descriptor": "()Landroid/net/Uri;", - "class": "Landroid/content/Intent;", - "method": "getData" - }, - { - "descriptor": "(Ljava/lang/String;)V", - "class": "Landroid/webkit/WebView;", - "method": "loadUrl" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python CWE-79.py - CWE-79 is detected in method, Lcom/vuldroid/application/ForgetPassword; onCreate (Landroid/os/Bundle;)V - - - -Detect CWE-328 in Android Application --------------------------------------- - -This scenario seeks to find the **Use of Weak Hash**. - -CWE-328 Use of Weak Hash -========================= - -We analyze the definition of CWE-328 and identify its characteristics. - -See `CWE-328 `_ for more details. - -.. image:: https://imgur.com/DUaOaKi.jpg - -Code of CWE-328 in allsafe.apk -=============================== - -We use the `allsafe.apk `_ sample to explain the vulnerability code of CWE-328. - -.. image:: https://imgur.com/nyreKX2.jpg - -CWE-328 Detection Process Using Quark Script API -================================================= - -.. image:: https://imgur.com/bM7WJKo.jpg - -Let's use the above APIs to show how the Quark script finds this vulnerability. - -First, we use API ``findMethodInAPK(samplePath, targetMethod)`` to find the method ``MessageDigest.getInstance()`` or ``SecretKeyFactory.getInstance()``. Next, we use API ``methodInstance.getArguments()`` with a list to check if the method uses weak hashing algorithms. If **YES**, that causes CWE-328 vulnerability. - -Quark Script: CWE-328.py -========================= - -.. image:: https://imgur.com/wb9Baa3.jpg - -.. code-block:: python - - from quark.script import findMethodInAPK - - SAMPLE_PATH = "./allsafe.apk" - - TARGET_METHODS = [ - [ - "Ljava/security/MessageDigest;", - "getInstance", - "(Ljava/lang/String;)Ljava/security/MessageDigest;", - ], - [ - "Ljavax/crypto/SecretKeyFactory;", - "getInstance", - "(Ljava/lang/String;)Ljavax/crypto/SecretKeyFactory;", - ], - ] - - HASH_KEYWORDS = [ - "MD2", - "MD4", - "MD5", - "PANAMA", - "SHA0", - "SHA1", - "HAVAL128", - "RIPEMD128", - ] - - methodsFound = [] - for target in TARGET_METHODS: - methodsFound += findMethodInAPK(SAMPLE_PATH, target) - - for setHashAlgo in methodsFound: - algoName = setHashAlgo.getArguments()[0].replace("-", "") - - if any(keyword in algoName for keyword in HASH_KEYWORDS): - print( - f"CWE-328 is detected in {SAMPLE_PATH},\n\t" - f"and it occurs in method, {setHashAlgo.fullName}" - ) - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-328.py - CWE-328 is detected in ./allsafe.apk, - and it occurs in method, Linfosecadventures/allsafe/challenges/SQLInjection; md5 (Ljava/lang/String;)Ljava/lang/String; - CWE-328 is detected in ./allsafe.apk, - and it occurs in method, Linfosecadventures/allsafe/challenges/WeakCryptography; md5Hash (Ljava/lang/String;)Ljava/lang/String; - CWE-328 is detected in ./allsafe.apk, - and it occurs in method, Lcom/google/firebase/database/core/utilities/Utilities; sha1HexDigest (Ljava/lang/String;)Ljava/lang/String; - - - -Detect CWE-295 in Android Application --------------------------------------- - -This scenario seeks to find **Improper Certificate Validation**. - -CWE-295: Improper Certificate Validation -========================================= - -We analyze the definition of CWE-295 and identify its characteristics. - -See `CWE-295 `_ for more details. - -.. image:: https://imgur.com/w6yx17J.jpg - -Code of CWE-295 in InsecureShop.apk -==================================== - -We use the `InsecureShop.apk `_ sample to explain the vulnerability code of CWE-295. - -.. image:: https://imgur.com/iBt3mzh.jpg - -CWE-295 Detection Process Using Quark Script API -================================================= - -.. image:: https://imgur.com/HBBurwx.jpg - -To begin with, we use the API ``findMethodInAPK(samplePath, targetMethod)`` to locate all callers of method ``SslErrorHandler.proceed``. - -Next, we must verify whether the caller overrides the method ``WebViewClient.onReceivedSslError``. - -Therefore, we check if the caller has the same method name and descriptor as ``WebViewClient.onReceivedSslError``, then use ``findSuperclassHierarchy()`` to see if its class extends ``Landroid/webkit/WebViewClient``. - -If both are **YES**, the APK will proceed with HTTPS connections without certificate validation when an SSL error occurs, which may cause CWE-295 vulnerability. - -Quark Script CWE-295.py -======================== - -.. image:: https://imgur.com/h9ydW0Y.jpg - -.. code-block:: python - - from quark.script import findMethodInAPK - - SAMPLE_PATH = "insecureShop.apk" - TARGET_METHOD = [ - "Landroid/webkit/SslErrorHandler;", # class name - "proceed", # method name - "()V", # descriptor - ] - OVERRIDDEN_METHOD = [ - "Landroid/webkit/WebViewClient;", # class name - "onReceivedSslError", # method name - "(Landroid/webkit/WebView;" - + " Landroid/webkit/SslErrorHandler;" - + " Landroid/net/http/SslError;)V", # descriptor - ] - - for sslProceedCaller in findMethodInAPK(SAMPLE_PATH, TARGET_METHOD): - if ( - sslProceedCaller.name == OVERRIDDEN_METHOD[1] - and sslProceedCaller.descriptor == OVERRIDDEN_METHOD[2] - and OVERRIDDEN_METHOD[0] in sslProceedCaller.findSuperclassHierarchy() - ): - print(f"CWE-295 is detected in method, {sslProceedCaller.fullName}") - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-295.py - CWE-295 is detected in method, Lcom/insecureshop/util/CustomWebViewClient; onReceivedSslError (Landroid/webkit/WebView; Landroid/webkit/SslErrorHandler; Landroid/net/http/SslError;)V - - - -Detect CWE-489 in Android Application --------------------------------------- - -This scenario seeks to find **active debug code**. - -CWE-489: Active Debug Code -=========================== - -We analyze the definition of CWE-489 and identify its characteristics. - -See `CWE-489 `_ for more details. - -.. image:: https://imgur.com/UuDNFXW.jpg - -Code of CWE-489 in allsafe.apk -=============================== - -We use the `allsafe.apk `_ sample to explain the vulnerability code of CWE-489. - -.. image:: https://imgur.com/QSrATmt.jpg - -CWE-489 Detection Process Using Quark Script API -================================================= - -.. image:: https://imgur.com/ydGfkV4.jpg - -First, we use Quark API ``getApplication(samplePath)`` to get the application element in the manifest file. Then we use ``applicationInstance.isDebuggable()`` to check if the application element sets the attribute ``android:debuggable`` to true. If **Yes**, that causes CWE-489 vulnerabilities. - -Quark Script CWE-489.py -======================== - -.. image:: https://imgur.com/ToCAmD3.jpg - -.. code-block:: python - - from quark.script import getApplication - - SAMPLE_PATH = "allsafe.apk" - - if getApplication(SAMPLE_PATH).isDebuggable(): - print(f"CWE-489 is detected in {SAMPLE_PATH}.") - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-489.py - CWE-489 is detected in allsafe.apk. - - - -Detect CWE-22 in Android Application -------------------------------------- - -This scenario seeks to find **the improper limitation of a pathname to a restricted directory (‘Path Traversal’)**. - -CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') -======================================================================================= - -We analyze the definition of CWE-22 and identify its characteristics. - -See `CWE-22 `_ for more details. - -.. image:: https://imgur.com/XnOUZsV.png - -Code of CWE-22 in ovaa.apk -=========================== - -We use the `ovaa.apk `_ sample to explain the vulnerability code of CWE-22. - -.. image:: https://imgur.com/bgWgeT7.png - -CWE-22 Detection Process Using Quark Script API -================================================ - -.. image:: https://imgur.com/N69bQK2.png - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -First, we design a detection rule ``accessFileInExternalDir.json`` to spot behavior accessing a file in an external directory. - -Next, we use API ``methodInstance.getArguments()`` to get the argument for the file path and use ``quarkResultInstance.isHardcoded(argument)`` to check if the argument is hardcoded into the APK. If **No**, the argument is from external input. - -Finally, we use Quark API ``quarkResultInstance.findMethodInCaller(callerMethod, targetMethod)`` to check if there are any APIs in the caller method for string matching. If **NO**, the APK does not neutralize special elements within the argument, which may cause CWE-22 vulnerability. - -Quark Scipt: CWE-22.py -======================= - -.. image:: https://imgur.com/4b2e4tN.png - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "ovaa.apk" - RULE_PATH = "accessFileInExternalDir.json" - - - STRING_MATCHING_API = [ - ["Ljava/lang/String;", "contains", "(Ljava/lang/CharSequence)Z"], - ["Ljava/lang/String;", "indexOf", "(I)I"], - ["Ljava/lang/String;", "indexOf", "(Ljava/lang/String;)I"], - ["Ljava/lang/String;", "matches", "(Ljava/lang/String;)Z"], - ] - - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for accessExternalDir in quarkResult.behaviorOccurList: - - filePath = accessExternalDir.secondAPI.getArguments()[2] - - if quarkResult.isHardcoded(filePath): - continue - - caller = accessExternalDir.methodCaller - strMatchingAPIs = [ - api for api in STRING_MATCHING_API if quarkResult.findMethodInCaller( - caller, api) - ] - - if not strMatchingAPIs: - print(f"CWE-22 is detected in method, {caller.fullName}") - -Quark Rule: accessFileInExternalDir.json -========================================= - -.. image:: https://imgur.com/N2uKsZj.png - -.. code-block:: json - - { - "crime": "Access a file in an external directory", - "permission": [], - "api": [ - { - "class": "Landroid/os/Environment;", - "method": "getExternalStorageDirectory", - "descriptor": "()Ljava/io/File;" - }, - { - "class": "Ljava/io/File;", - "method": "", - "descriptor": "(Ljava/io/File;Ljava/lang/String;)V" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-22.py - CWE-22 is detected in method, Loversecured/ovaa/providers/TheftOverwriteProvider; openFile (Landroid/net/Uri; Ljava/lang/String;)Landroid/os/ParcelFileDescriptor; - - - - -Detect CWE-23 in Android Application -------------------------------------- - -This scenario aims to demonstrate the detection of the **Relative Path Traversal** vulnerability. - -CWE-23: Relative Path Traversal -================================ - -We analyze the definition of CWE-23 and identify its characteristics. - -See `CWE-23 `_ for more details. - -.. image:: https://imgur.com/k4UPsKO.png - -Code of CWE-23 in ovaa.apk -=========================== - -We use the `ovaa.apk `_ sample to explain the vulnerability code of CWE-23. - -.. image:: https://imgur.com/KT277GG.png - -CWE-23 Detection Process Using Quark Script API -================================================ - -.. image:: https://imgur.com/D852ZLV.png - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -To begin with, we create a detection rule named ``accessFileInExternalDir.json`` to identify behavior that accesses a file in an external directory. - -Next, we use ``methodInstance.getArguments()`` to retrieve the file path argument and check whether it belongs to the APK. If it does not belong to the APK, the argument is likely from external input. - -Then, we use the Quark Script API ``quarkResultInstance.findMethodInCaller(callerMethod, targetMethod)`` to search for any APIs in the caller method that are used to match strings. If no API is found, that implies the APK does not neutralize special elements within the argument, possibly resulting in CWE-23 vulnerability. - -Quark Script: CWE-23.py -======================== - -.. image:: https://imgur.com/lk1C4CX.jpg - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "ovaa.apk" - RULE_PATH = "accessFileInExternalDir.json" - - - STRING_MATCHING_API = [ - ["Ljava/lang/String;", "contains", "(Ljava/lang/CharSequence)Z"], - ["Ljava/lang/String;", "indexOf", "(I)I"], - ["Ljava/lang/String;", "indexOf", "(Ljava/lang/String;)I"], - ["Ljava/lang/String;", "matches", "(Ljava/lang/String;)Z"], - [ - "Ljava/lang/String;", - "replaceAll", - "(Ljava/lang/String; Ljava/lang/String;)Ljava/lang/String;", - ], - ] - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for accessExternalDir in quarkResult.behaviorOccurList: - - filePath = accessExternalDir.secondAPI.getArguments()[2] - - if quarkResult.isHardcoded(filePath): - continue - - caller = accessExternalDir.methodCaller - strMatchingAPIs = [ - api - for api in STRING_MATCHING_API - if quarkResult.findMethodInCaller(caller, api) - ] - - if not strMatchingAPIs: - print(f"CWE-23 is detected in method, {caller.fullName}") - -Quark Rule: accessFileInExternalDir.json -========================================= - -.. image:: https://imgur.com/N2uKsZj.png - -.. code-block:: json - - { - "crime": "Access a file in an external directory", - "permission": [], - "api": [ - { - "class": "Landroid/os/Environment;", - "method": "getExternalStorageDirectory", - "descriptor": "()Ljava/io/File;" - }, - { - "class": "Ljava/io/File;", - "method": "", - "descriptor": "(Ljava/io/File;Ljava/lang/String;)V" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-23.py - CWE-23 is detected in method, Loversecured/ovaa/providers/TheftOverwriteProvider; openFile (Landroid/net/Uri; Ljava/lang/String;)Landroid/os/ParcelFileDescriptor; - - - - - -Detect CWE-338 in Android Application --------------------------------------- - -This scenario seeks to find **Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)**. - -CWE-338: Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG) -============================================================================= - -We analyze the definition of CWE-338 and identify its characteristics. - -See `CWE-338 `_ for more details. - -.. image:: https://imgur.com/aLybax5.jpg - -Code of CWE-338 in pivaa.apk -============================= - -We use the `pivaa.apk `_ sample to explain the vulnerability code of CWE-338. - -.. image:: https://i.postimg.cc/mr5rpTDz/image.png - -CWE-338 Detection Process Using Quark Script API -================================================= - -.. image:: https://imgur.com/yWLNwZV.jpg - -First, we design a detection rule ``useMethodOfPRNG.json`` to spot on behavior that uses Pseudo Random Number Generator (PRNG). Then, we use API ``methodInstance.getXrefFrom()`` to get the caller method of PRNG. Finally, we use some keywords such as "token", "password", and "encrypt" to check if the PRNG is for credential usage. - -Quark Script CWE-338.py -======================== - -.. image:: https://i.postimg.cc/xdt54Lft/image.png - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "pivaa.apk" - RULE_PATH = "useMethodOfPRNG.json" - - CREDENTIAL_KEYWORDS = [ - "token", "password", "account", "encrypt", - "authentication", "authorization", "id", "key" - ] - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for usePRNGMethod in quarkResult.behaviorOccurList: - for prngCaller in usePRNGMethod.methodCaller.getXrefFrom(): - if any( - keyword in prngCaller.fullName for keyword in CREDENTIAL_KEYWORDS - ): - print("CWE-338 is detected in %s" % prngCaller.fullName) - -Quark Rule: useMethodOfPRNG.json -================================= - -.. image:: https://i.postimg.cc/jS6x74Kg/image.png - -.. code-block:: json - - { - "crime": "Use method of PRNG", - "permission": [], - "api": [ - { - "class": "Ljava/util/Random;", - "method": "", - "descriptor": "()V" - }, - { - "class": "Ljava/util/Random;", - "method": "nextInt", - "descriptor": "(I)I" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python CWE-338.py - CWE-338 is detected in Lcom/htbridge/pivaa/EncryptionActivity$2; onClick (Landroid/view/View;)V - - - - -Detect CWE-88 in Android Application --------------------------------------- - -This scenario seeks to find **Argument Injection** in the APK file. - -CWE-88 Improper Neutralization of Argument Delimiters in a Command -=================================================================== - -We analyze the definition of CWE-88 and identify its characteristics. - -See `CWE-88 `_ for more details. - -.. image:: https://imgur.com/5vfXkIE.png - -Code of CWE-88 in vuldroid.apk -=============================== - -We use the `vuldroid.apk `_ sample to explain the vulnerability code of CWE-88. - -.. image:: https://imgur.com/recX0t5.png - -CWE-88 Detection Process Using Quark Script API -================================================ - -.. image:: https://imgur.com/s7Ajr6M.png - -Let‘s use the above APIs to show how the Quark script finds this vulnerability. - -First, we design a detection rule ``ExternalStringsCommands.json`` to spot on behavior using external strings as commands. - -Next, we use Quark API ``behaviorInstance.getMethodsInArgs()`` to get the methods that passed the external command. - -Then we check if the method neutralizes any special elements in the argument. - -If the neutralization is not complete, then it may cause CWE-88 vulnerability. - -Quark Script: CWE-88.py -======================== - -.. image:: https://imgur.com/f8Yee3P.png - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule, findMethodInAPK - - SAMPLE_PATH = "Vuldroid.apk" - RULE_PATH = "ExternalStringCommand.json" - - - STRING_MATCHING_API = set([ - ("Ljava/lang/String;", "contains", "(Ljava/lang/CharSequence)Z"), - ("Ljava/lang/String;", "indexOf", "(I)I"), - ("Ljava/lang/String;", "indexOf", "(Ljava/lang/String;)I"), - ("Ljava/lang/String;", "matches", "(Ljava/lang/String;)Z"), - ("Ljava/lang/String;", "replaceAll", "(Ljava/lang/String; Ljava/lang/String;)Ljava/lang/String;") - ]) - - delimeter = "-" - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for ExternalStringCommand in quarkResult.behaviorOccurList: - - methodCalled = set() - caller = ExternalStringCommand.methodCaller - - for method in ExternalStringCommand.getMethodsInArgs(): - methodCalled.add(method.fullName) - - if methodCalled.intersection(STRING_MATCHING_API) and not ExternalStringCommand.hasString(delimeter): - continue - else: - print(f"CWE-88 is detected in method, {caller.fullName}") - - -Quark Rule: ExternalStringCommand.json -======================================= - -.. image:: https://imgur.com/s9QNF19.png - -.. code-block:: json - - { - "crime": "Using external strings as commands", - "permission": [], - "api": [ - { - "class": "Landroid/content/Intent;", - "method": "getStringExtra", - "descriptor": "(Ljava/lang/String;)Ljava/lang/String" - }, - { - "class": "Ljava/lang/Runtime;", - "method": "exec", - "descriptor": "(Ljava/lang/String;)Ljava/lang/Process" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-88.py - CWE-88 is detected in method, Lcom/vuldroid/application/RootDetection; onCreate (Landroid/os/Bundle;)V - - - -Detect CWE-925 in Android Application --------------------------------------- - -This scenario seeks to find **Improper Verification of Intent by Broadcast Receiver** in the APK file. - -CWE-925 Improper Verification of Intent by Broadcast Receiver -============================================================== - -We analyze the definition of CWE-925 and identify its characteristics. - -See `CWE-925 `_ for more details. - -.. image:: https://imgur.com/fMZ2bMN.jpg - -Code of CWE-925 in InsecureBankv2.apk -====================================== - -We use the `InsecureBankv2.apk `_ sample to explain the vulnerability code of CWE-925. - -.. image:: https://imgur.com/V7VtL3x.jpg - - -CWE-925 Detection Process Using Quark Script API -================================================= - -.. image:: https://i.postimg.cc/Ls0Kw749/2025-09-17-4-19-22.png - -First, we use API ``getReceivers(samplePath)`` and ``receiverInstance.isExported()`` to find all the exported receivers defined in the APK. - -Second, we use API ``checkMethodCalls(samplePath, targetMethod, checkMethods)`` to check if the ``onReceive`` method of every exported receiver obtains an intent action. - -If **No**, it could imply that the APK does not verify intent properly, potentially leading to a CWE-925 vulnerability. - - -Quark Script CWE-925.py -======================== - -.. image:: https://i.postimg.cc/dQhts2gN/2025-09-17-4-17-51.png - -.. code-block:: python - - from quark.script import checkMethodCalls, getReceivers - - sample_path = "InsecureBankv2.apk" - - TARGET_METHOD = [ - '', - 'onReceive', - '(Landroid/content/Context; Landroid/content/Intent;)V' - ] - - CHECK_METHODS = [ - ['Landroid/content/Intent;', 'getAction', '()Ljava/lang/String;'] - ] - - receivers = getReceivers(sample_path) - for receiver in receivers: - if receiver.isExported(): - className = "L"+str(receiver).replace('.', '/')+';' - TARGET_METHOD[0] = className - if not checkMethodCalls(sample_path, TARGET_METHOD, CHECK_METHODS): - print(f"CWE-925 is detected in method, {className}") - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python CWE-925.py - CWE-925 is detected in method, Lcom/android/insecurebankv2/MyBroadCastReceiver; - - - -Detect CWE-73 in Android Application --------------------------------------- - -This scenario seeks to find **External Control of File Name or Path** in the APK file. - -CWE-73 External Control of File Name or Path -============================================= - -We analyze the definition of CWE-73 and identify its characteristics. - -See `CWE-73 `_ for more details. - -.. image:: https://imgur.com/I1C5yku.png - -Code of CWE-73 in ovaa.apk -=========================== - -We use the `ovaa.apk `_ sample to explain the vulnerability code of CWE-73. - -.. image:: https://imgur.com/gLJ6zWr.png - -CWE-73 Detection Process Using Quark Script API -================================================ - -.. image:: https://imgur.com/zGjZHA1.png - -Let’s use the above APIs to show how Quark script finds this vulnerability. - -First, we design a detection rule ``useLastPathSegmentAsFileName.json`` to spot behavior that uses the last path segment as the file name. - -Second, we use the API ``methodInstance.getArguments()`` to get the argument for the file path and use ``quarkResultInstance.isHardcoded(argument)`` to check if the argument is hardcoded into the APK. If **No**, the argument is from external input. - -Finally, we use Quark API ``quarkResultInstance.findMethodInCaller(callerMethod, targetMethod)`` to check if there are any APIs in the caller method for opening files. If **YES**, the APK performs file operations using external input as a path, which may cause CWE-73 vulnerability. - -Quark Script: CWE-73.py -======================== - -.. image:: https://imgur.com/EHrcCPg.png - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "ovaa.apk" - RULE_PATH = "useLastPathSegmentAsFileName.json" - - OPEN_FILE_API = [ - "Landroid/os/ParcelFileDescriptor;", # Class name - "open", # Method name - "(Ljava/io/File; I)Landroid/os/ParcelFileDescriptor;" # Descriptor - ] - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for accessExternalDir in quarkResult.behaviorOccurList: - filePath = accessExternalDir.secondAPI.getArguments()[2] - - if quarkResult.isHardcoded(filePath): - continue - - caller = accessExternalDir.methodCaller - result = quarkResult.findMethodInCaller(caller, OPEN_FILE_API) - - if result: - print("CWE-73 is detected in method, ", caller.fullName) - -Quark Rule: useLastPathSegmentAsFileName.json -============================================== - -.. image:: https://imgur.com/JxBdde0.png - -.. code-block:: json - - { - "crime": "Use the last path segment as the file name", - "permission": [], - "api": [ - { - "class": "Landroid/net/Uri;", - "method": "getLastPathSegment", - "descriptor": "()Ljava/lang/String;" - }, - { - "class": "Ljava/io/File;", - "method": "", - "descriptor": "(Ljava/io/File;Ljava/lang/String;)V" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python CWE-73.py - CWE-73 is detected in method, Loversecured/ovaa/providers/TheftOverwriteProvider; openFile (Landroid/net/Uri; Ljava/lang/String;)Landroid/os/ParcelFileDescriptor; - - - -Detect CWE-78 in Android Application -------------------------------------- - -This scenario seeks to find **Improper Neutralization of Special Elements used in an OS Command** in the APK file. - -CWE-78 Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') -================================================================================================== - -We analyze the definition of CWE-78 and identify its characteristics. - -See `CWE-78 `_ for more details. - -.. image:: https://imgur.com/HpMGGsO.png - -Code of CWE-78 in Vuldroid.apk -=============================== - -We use the `Vuldroid.apk `_ sample to explain the vulnerability code of CWE-78. - -.. image:: https://imgur.com/7Tu0Y3H.png - -CWE-78 Detection Process Using Quark Script API -================================================ - -.. image:: https://imgur.com/Hi7qGjw.png - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -First, we design a detection rule ``ExternalStringsCommands.json`` to spot on behavior using external strings as commands. - -Next, we use Quark API ``behaviorInstance.getMethodsInArgs()`` to get the methods that passed the external command. - -Then we check if the method neutralizes any special elements in the argument. - -If the neutralization is not complete, then it may cause CWE-78 vulnerability. - -Quark Script: CWE-78.py -======================== - -.. image:: https://imgur.com/UpRWgGe.png - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule, findMethodInAPK - - SAMPLE_PATH = "Vuldroid.apk" - RULE_PATH = "ExternalStringCommand.json" - - - STRING_MATCHING_API = set([ - ("Ljava/lang/String;", "contains", "(Ljava/lang/CharSequence)Z"), - ("Ljava/lang/String;", "indexOf", "(I)I"), - ("Ljava/lang/String;", "indexOf", "(Ljava/lang/String;)I"), - ("Ljava/lang/String;", "matches", "(Ljava/lang/String;)Z"), - ( - "Ljava/lang/String;", - "replaceAll", - "(Ljava/lang/String; Ljava/lang/String;)Ljava/lang/String;", - ), - ]) - - specialElementsPattern = r"[ ;|,>`]+" - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for ExternalStringCommand in quarkResult.behaviorOccurList: - - methodCalled = set() - caller = ExternalStringCommand.methodCaller - - for method in ExternalStringCommand.getMethodsInArgs(): - methodCalled.add(method.fullName) - - if methodCalled.intersection(STRING_MATCHING_API) and not ExternalStringCommand.hasString(specialElementsPattern): - continue - else: - print(f"CWE-78 is detected in method, {caller.fullName}") - -Quark Rule: ExternalStringCommand.json -======================================= - -.. image:: https://imgur.com/eoV8hnZ.png - -.. code-block:: json - - { - "crime": "Using external strings as commands", - "permission": [], - "api": [ - { - "class": "Landroid/content/Intent;", - "method": "getStringExtra", - "descriptor": "(Ljava/lang/String;)Ljava/lang/String" - }, - { - "class": "Ljava/lang/Runtime;", - "method": "exec", - "descriptor": "(Ljava/lang/String;)Ljava/lang/Process" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-78.py - CWE-78 is detected in method, Lcom/vuldroid/application/RootDetection; onCreate (Landroid/os/Bundle;)V - - - - -Detect CWE-117 in Android Application --------------------------------------- - -This scenario seeks to find **Improper Output Neutralization for Logs**. - -CWE-117: Improper Output Neutralization for Logs -================================================= - -We analyze the definition of CWE-117 and identify its characteristics. - -See `CWE-117 `_ for more details. - -.. image:: https://imgur.com/JEAyEsU.jpg - -Code of CWE-117 in allsafe.apk -=============================== - -We use the `allsafe.apk `_ sample to explain the vulnerability code of CWE-117. - -.. image:: https://imgur.com/ueePFNu.jpg - -CWE-117 Detection Process Using Quark Script API -================================================= - -.. image:: https://imgur.com/Y5hd4Uc.jpg - -First, we design a detection rule ``writeContentToLog.json`` to spot on behavior using the method that writes contents to the log file. - -Then, we use ``methodInstance.getArguments()`` to get all parameter values of this method. And we check if these parameters contain keywords of APIs for neutralization, such as ``escape``, ``replace``, ``format``, and ``setFilter``. - -If the answer is **YES**, that may result in secret context leakage into the log file, or the attacker may perform log forging attacks. - -Quark Script CWE-117.py -======================== - -.. image:: https://imgur.com/F1X3qg3.jpg - -.. code-block:: python - - from quark.script import Rule, runQuarkAnalysis - - SAMPLE_PATH = "allsafe.apk" - RULE_PATH = "writeContentToLog.json" - KEYWORDS_FOR_NEUTRALIZATION = ["escape", "replace", "format", "setFilter"] - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for logOutputBehavior in quarkResult.behaviorOccurList: - - secondAPIParam = logOutputBehavior.secondAPI.getArguments() - - isKeywordFound = False - for keyword in KEYWORDS_FOR_NEUTRALIZATION: - if keyword in secondAPIParam: - isKeywordFound = True - break - - if not isKeywordFound: - caller = logOutputBehavior.methodCaller.fullName - print(f"CWE-117 is detected in method, {caller}") - -Quark Rule: writeContentToLog.json -=================================== - -.. image:: https://imgur.com/hC4zGgT.jpg - -.. code-block:: json - - { - "crime": "Write contents to the log", - "permission": [], - "api": [ - { - "descriptor": "()Landroid/text/Editable;", - "class": "Lcom/google/android/material/textfield/TextInputEditText;", - "method": "getText" - }, - { - "descriptor": "(Ljava/lang/String;Ljava/lang/String;)I", - "class": "Landroid/util/Log;", - "method": "d" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python CWE-117.py - CWE-117 is detected in method, Linfosecadventures/allsafe/challenges/InsecureLogging; lambda$onCreateView$0 (Lcom/google/android/material/textfield/TextInputEditText; Landroid/widget/TextView; I Landroid/view/KeyEvent;)Z - - - -Detect CWE-940 in Android Application --------------------------------------- - -This scenario seeks to find the **Improper Verification of Source of a Communication Channel** in the APK file. - -CWE-940: Improper Verification of Source of a Communication Channel -==================================================================== - -We analyze the definition of CWE-940 and identify its characteristics. - -See `CWE-940 `_ for more details. - -.. image:: https://imgur.com/wia3OKo.png - -Code of CWE-940 in ovaa.apk -============================ - -We use the `ovaa.apk `_ sample to explain the vulnerability code of CWE-940. - -.. image:: https://imgur.com/1zP5xkN.png - -CWE-940 Detection Process Using Quark Script API -================================================= - -.. image:: https://i.postimg.cc/1XGWt89Q/jie-tu-2025-11-21-xia-wu4-46-36.png - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -To begin with, we create a detection rule named ``LoadUrlFromIntent.json`` to identify behavior that loads URLs from intent data to the ``WebView``. - -Next, we retrieve the methods that pass the URL. Then, we check if these methods are only for getting the URL, such as ``findViewById``, ``getStringExtra``, or ``getIntent``. - -If **YES**, it could imply that the APK uses communication channels without proper verification, which may cause CWE-940 vulnerability. - -Quark Script: CWE-940.py -========================= - -.. image:: https://i.postimg.cc/pLTZNG5J/jie-tu-2025-11-21-xia-wu4-47-11.png - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "ovaa.apk" - RULE_PATH = "LoadUrlFromIntent.json" - - URL_GETTING_METHODS = [ - "findViewById", - "getStringExtra", - "getIntent", - ] - - ruleInstance = Rule(RULE_PATH) - - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for behaviorInstance in quarkResult.behaviorOccurList: - methodsInArgs = behaviorInstance.getMethodsInArgs() - - verifiedMethodCandidates = [] - - for method in methodsInArgs: - if method.methodName not in URL_GETTING_METHODS: - verifiedMethodCandidates.append(method) - - if verifiedMethodCandidates == []: - caller = behaviorInstance.methodCaller.fullName - print(f"CWE-940 is detected in method, {caller}") - -Quark Rule: LoadUrlFromIntent.json -=================================== - -.. code-block:: json - - { - "crime": "Load Url from Intent", - "permission": [], - "api": [ - { - "class": "Landroid/content/Intent;", - "method": "getStringExtra", - "descriptor": "(Ljava/lang/String;)Ljava/lang/String" - }, - { - "class": "Landroid/webkit/WebView;", - "method": "loadUrl", - "descriptor": "(Ljava/lang/String;)V" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python CWE-940.py - CWE-940 is detected in method, Loversecured/ovaa/activities/WebViewActivity; onCreate (Landroid/os/Bundle;)V - - -Detect CWE-502 in Android Application --------------------------------------- - -This scenario seeks to find **Deserialization of Untrusted Data** in the APK file. - -CWE-502: Deserialization of Untrusted Data -=========================================== - -We analyze the definition of CWE-502 and identify its characteristics. - -See `CWE-502 `_ for more details. - -.. image:: https://i.postimg.cc/YSyQsgGf/image.png - -Code of CWE-502 in pivaa.apk -============================= - -We use the `pivaa.apk `_ sample to explain the vulnerability code of CWE-502. - -.. image:: https://i.postimg.cc/XJdXkywv/image.png - -CWE-502 Detection Process Using Quark Script API -================================================= - -.. image:: https://i.postimg.cc/mkV97HsH/image.png - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -To begin with, we created a detection rule named ``deserializeData.json`` to identify behaviors that deserialize data. - -Next, we retrieve the methods that interact with the deserialization API. Following this, we check if the methods match any APIs for verifying data. - -If **NO**, it could imply that the APK deserializes the untrusted data, potentially leading to a CWE-502 vulnerability. - -Quark Script CWE-502.py -======================== - -.. image:: https://i.postimg.cc/vTmXSj7g/image.png - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "pivaa.apk" - RULE_PATH = "deserializeData.json" - - ruleInstance = Rule(RULE_PATH) - - result = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - verificationApis = [ - ["Ljava/io/File;", "exists", "()Z"], - ["Landroid/content/Context;", "getFilesDir", "()Ljava/io/File;"], - ["Landroid/content/Context;", "getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;"], - ["Landroid/os/Environment;", "getExternalStorageDirectory", "()Ljava/io/File;"], - ] - - for dataDeserialization in result.behaviorOccurList: - apis = dataDeserialization.getMethodsInArgs() - caller = dataDeserialization.methodCaller - if not any(api in apis for api in verificationApis): - print(f"CWE-502 is detected in method, {caller.fullName}") - -Quark Rule: deserializeData.json -================================= - -.. image:: https://i.postimg.cc/FsdDQm7r/image.png - -.. code-block:: json - - { - "crime": "Deserialize Data", - "permission": [], - "api": [ - - { - "class": "Ljava/io/ObjectInputStream;", - "method": "", - "descriptor": "(Ljava/io/InputStream;)V" - }, - { - "class": "Ljava/io/ObjectInputStream;", - "method": "readObject", - "descriptor": "()Ljava/lang/Object;" - } - - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python CWE-502.py - CWE-502 is detected in method, Lcom/htbridge/pivaa/handlers/ObjectSerialization; loadObject ()V - - - -Detect CWE-601 in Android Application --------------------------------------- - -This scenario seeks to find **URL Redirection to Untrusted Site** in the APK file. - -CWE-601: URL Redirection to Untrusted Site ('Open Redirect') -============================================================= - -We analyze the definition of CWE-601 and identify its characteristics. - -See `CWE-601 `_ for more details. - -.. image:: https://imgur.com/sgRhcel.png - -Code of CWE-601 in ovaa.apk -========================================= - -We use the `ovaa.apk `_ sample to explain the vulnerability code of CWE-601. - -.. image:: https://i.postimg.cc/hjqKnKLN/2025-10-08-1-12-43.png - - -CWE-601 Detection Process Using Quark Script API -================================================= - -.. image:: https://i.postimg.cc/q75yxptk/2025-10-09-9-14-34.png - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -To detect the vulnerability, we use the API ``findMethodInAPK(samplePath, targetMethod)`` to find all the caller methods of ``startActivity``. Next, we examine the arguments of each method to discover the methods receiving external input. If a method receives external input but lacks proper input validation, the CWE-601 vulnerability is identified. - - -Quark Script: CWE-601.py -======================== - -.. image:: https://i.postimg.cc/wTwvm0Rm/2025-10-09-9-18-38.png - -.. code-block:: python - - from quark.script import findMethodInAPK - - SAMPLE_PATH = 'ovaa.apk' - - # This is the input for findMethodInAPK, formatted as class name, method name, descriptor - TARGET_METHOD = ["", "startActivity", "(Landroid/content/Intent;)V"] - - """ - Due to varying descriptors and classes in smali code from different APIs, - our search relies solely on the consistent method names. - """ - - EXTERNAL_INPUT_METHODS = ["getIntent", "getQueryParameter"] - - INPUT_FILTER_METHODS = [ - "parse", - "isValidUrl", - "Pattern", - "Matcher", - "encode", - "decode", - "escapeHtml", - "HttpURLConnection", - ] - - redirectMethods = findMethodInAPK(SAMPLE_PATH, TARGET_METHOD) - - for redirectMethod in redirectMethods: - arguments = redirectMethod.getArguments() - for argument in arguments: - if any( - externalInput in argument - for externalInput in EXTERNAL_INPUT_METHODS - ): - if not any( - filterMethod in argument - for filterMethod in INPUT_FILTER_METHODS - ): - print(f"CWE-601 is detected in {redirectMethod.fullName}") - -Quark Script Result -====================== - -.. code-block:: TEXT - - $ python CWE-601.py - CWE-601 is detected in Loversecured/ovaa/activities/DeeplinkActivity; processDeeplink (Landroid/net/Uri;)V - CWE-601 is detected in Loversecured/ovaa/activities/LoginActivity; onLoginFinished ()V - - - -Detect CWE-329 in Android Application -------------------------------------- - -This scenario seeks to find **Generation of Predictable IV with CBC Mode** in the APK file. - -CWE-329: Generation of Predictable IV with CBC Mode -=================================================== - -We analyze the definition of CWE-329 and identify its characteristics. - -See `CWE-329 `_ for more details. - - -.. image:: https://i.postimg.cc/ZY6WjB5z/Screenshot-2025-07-11-17-13-40.png - :target: https://i.postimg.cc/ZY6WjB5z/Screenshot-2025-07-11-17-13-40.png - :alt: - - -Code of CWE-329 in InsecureBankv2.apk -======================================== - -We use the `InsecureBankv2.apk `_ sample to explain the vulnerability code of CWE-329. - - -.. image:: https://i.postimg.cc/LXgBX9SB/Screenshot-2025-07-11-17-46-25.png - :target: https://i.postimg.cc/LXgBX9SB/Screenshot-2025-07-11-17-46-25.png - :alt: - - -CWE-329 Detection Process Using Quark Script API -================================================ - - -.. image:: https://i.postimg.cc/50cscyh2/Screenshot-2025-07-12-10-02-34.png - :target: https://i.postimg.cc/50cscyh2/Screenshot-2025-07-12-10-02-34.png - :alt: - - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -To begin with, we created a detection rule named ``initializeCipherWithIV.json`` to identify behaviors that initialize a cipher object with IV. Then, we use API ``behaviorInstance.getParamValues()`` to check if the cipher object uses CBC mode. - -Finally, we use API ``behaviorInstance.isArgFromMethod(targetMethod)`` to check if any random API is applied on the IV used in the cipher object. If **NO**\ , it could imply that the APK uses a predictable IV in CBC mode cipher, potentially leading to a CWE-329 vulnerability. - -Quark Script CWE-329.py -======================= - - -.. image:: https://i.postimg.cc/prCCnZpm/Screenshot-2025-07-12-10-02-58.png - :target: https://i.postimg.cc/prCCnZpm/Screenshot-2025-07-12-10-02-58.png - :alt: - - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "InsecureBankv2.apk" - RULE_PATH = "initializeCipherWithIV.json" - - randomAPIs = [ - ["Ljava/security/SecureRandom", "next", "(I)I"], - ["Ljava/security/SecureRandom", "nextBytes", "([B)V"], - ] - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for initCipherWithIV in quarkResult.behaviorOccurList: - methodcaller = initCipherWithIV.methodCaller - cipherName = initCipherWithIV.getParamValues()[0] - - if "CBC" not in cipherName: - break - - if not any( - initCipherWithIV.isArgFromMethod(api) for api in randomAPIs - ): - print(f"CWE-329 is detected in method, {methodcaller.fullName}") - -Quark Rule: initializeCipherWithIV.json -======================================= - - -.. image:: https://i.postimg.cc/Y9tM29YT/Screenshot-2025-07-11-17-49-41.png - :target: https://i.postimg.cc/Y9tM29YT/Screenshot-2025-07-11-17-49-41.png - :alt: - - -.. code-block:: json - - { - "crime": "Initialize a cipher object with IV", - "permission": [], - "api": [ - { - "class": "Ljavax/crypto/spec/IvParameterSpec;", - "method": "", - "descriptor": "([B)V" - }, - { - "class": "Ljavax/crypto/Cipher;", - "method": "init", - "descriptor": "(ILjava/security/Key;Ljava/security/spec/AlgorithmParameterSpec;)V" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -=================== - -.. code-block:: text - - $ python CWE-329.py - CWE-329 is detected in method, Lcom/google/android/gms/internal/zzar; zzc ([B Ljava/lang/String;)[B - CWE-329 is detected in method, Lcom/android/insecurebankv2/CryptoClass; aes256encrypt ([B [B [B)[B - CWE-329 is detected in method, Lcom/android/insecurebankv2/CryptoClass; aes256decrypt ([B [B [B)[B - - - - -Detect CWE-297 in Android Application --------------------------------------- - -This scenario seeks to find **Improper Validation of Certificate with Host Mismatch**. - -CWE-297: Improper Validation of Certificate with Host Mismatch -=============================================================== - -We analyze the definition of CWE-297 and identify its characteristics. - -See `CWE-297 `_ for more details. - -.. image:: https://i.postimg.cc/PrpC3vgy/image.png - -Code of CWE-297 in pivaa.apk -============================= - -We use the `pivaa.apk `_ sample to explain the vulnerability code of CWE-297. - -.. image:: https://i.postimg.cc/wT29kqv2/image.png - -CWE-297 Detection Process Using Quark Script API -================================================= - -.. image:: https://i.postimg.cc/ryYJRWGN/image.png - -First, we use API ``findMethodImpls(samplePath, targetMethod)`` to locate the method that implements the hostname verification, which verifies the hostname of a certificate. - -Next, we use API ``isMethodReturnAlwaysTrue(samplePath, targetMethod)`` to check if the method always returns true. - -If the answer is **YES**, the method does not check the certificate of the host properly, which may cause CWE-297 vulnerability. - -Quark Script CWE-297.py -======================== - -.. image:: https://i.postimg.cc/Dw311cSL/image.png - -.. code-block:: python - - from quark.script import findMethodImpls, isMethodReturnAlwaysTrue - - SAMPLE_PATH = "pivaa.apk" - - ABSTRACT_METHOD = [ - "Ljavax/net/ssl/HostnameVerifier;", - "verify", - "(Ljava/lang/String; Ljavax/net/ssl/SSLSession;)Z" - ] - - for hostVerification in findMethodImpls(SAMPLE_PATH, ABSTRACT_METHOD): - methodImpls = [ - hostVerification.className, - hostVerification.methodName, - hostVerification.descriptor - ] - if isMethodReturnAlwaysTrue(SAMPLE_PATH, methodImpls): - print(f"CWE-297 is detected in method, {hostVerification.fullName}") - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python CWE-297.py - CWE-297 is detected in method, Lcom/htbridge/pivaa/handlers/API$1; verify (Ljava/lang/String; Ljavax/net/ssl/SSLSession;)Z - - - -Detect CWE-1204 in Android Application ---------------------------------------- - -This scenario seeks to find **Generation of Weak Initialization Vector (IV)**. - -CWE-1204: Generation of Weak Initialization Vector (IV) -======================================================== - -We analyze the definition of CWE-1204 and identify its characteristics. - -See `CWE-1204 `_ for more details. - -.. image:: https://i.postimg.cc/3NNmYz6J/image.png - -Code of CWE-1204 in InsecureBankv2.apk -======================================= - -We use the `InsecureBankv2.apk `_ sample to explain the vulnerability code of CWE-1204. - -.. image:: https://i.postimg.cc/rsHWmQXG/image.png - - -CWE-1204 Detection Process Using Quark Script API -================================================== - -.. image:: https://i.postimg.cc/jq3yZdwW/image.png - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -First, we created a detection rule named ``initializeCipherWithIV.json`` to identify behaviors that initialize a cipher object with IV. - -Then, we use API ``behaviorInstance.isArgFromMethod(targetMethod)`` to check if any random API is applied on the IV used in the cipher object. If **NO**, it could imply that the APK uses a weak IV, potentially leading to a CWE-1204 vulnerability. - -Quark Scipt: CWE-1204.py -========================= - -.. image:: https://i.postimg.cc/Hxs79fT4/image.png - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "InsecureBankv2.apk" - RULE_PATH = "initializeCipherWithIV.json" - - randomAPIs = [ - ["Ljava/security/SecureRandom", "next", "(I)I"], - ["Ljava/security/SecureRandom", "nextBytes", "([B)V"], - ] - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for initCipherWithIV in quarkResult.behaviorOccurList: - methodcaller = initCipherWithIV.methodCaller - - if not any( - initCipherWithIV.isArgFromMethod(api) for api in randomAPIs - ): - print(f"CWE-1204 is detected in method, {methodcaller.fullName}") - -Quark Rule: initializeCipherWithIV.json -======================================== - -.. image:: https://i.postimg.cc/kGL69GKf/image.png - -.. code-block:: json - - { - "crime": "Initialize a cipher object with IV", - "permission": [], - "api": [ - { - "class": "Ljavax/crypto/spec/IvParameterSpec;", - "method": "", - "descriptor": "([B)V" - }, - { - "class": "Ljavax/crypto/Cipher;", - "method": "init", - "descriptor": "(ILjava/security/Key;Ljava/security/spec/AlgorithmParameterSpec;)V" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python CWE-1204.py - CWE-1204 is detected in method, Lcom/android/insecurebankv2/CryptoClass; aes256encrypt ([B [B [B)[B - CWE-1204 is detected in method, Lcom/android/insecurebankv2/CryptoClass; aes256decrypt ([B [B [B)[B - CWE-1204 is detected in method, Lcom/google/android/gms/internal/zzar; zzc ([B Ljava/lang/String;)[B - - - - -Detect CWE-24 in Android Application -------------------------------------- - -This scenario aims to demonstrate the detection of the **Relative Path Traversal** vulnerability. - -CWE-24: Path Traversal: '../filedir' -===================================== - -We analyze the definition of CWE-24 and identify its characteristics. - -See `CWE-24 `_ for more details. - -.. image:: https://i.postimg.cc/xdQjd3M2/image.png - -Code of CWE-24 in ovaa.apk -=========================== - -We use the `ovaa.apk `_ sample to explain the vulnerability code of CWE-24. - -.. image:: https://imgur.com/KT277GG.png - -CWE-24 Detection Process Using Quark Script API -================================================ - -.. image:: https://i.postimg.cc/YCz0YPp9/image.png - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -To begin with, we create a detection rule named ``accessFileInExternalDir.json`` to identify behavior that accesses a file in an external directory. - -Next, we use ``methodInstance.getArguments()`` to retrieve the file path argument and check whether it belongs to the APK. If it does not belong to the APK, the argument is likely from external input. - -Finally, we use the Quark Script API ``quarkResultInstance.findMethodInCaller(callerMethod, targetMethod)`` to search for any APIs in the caller method that are used to match strings, and ``getParamValues(none)`` to retrieve the parameters. - -If no API is found or ``"../"`` is not in parameters, that implies the APK does not neutralize the special element ``../`` within the argument, possibly resulting in CWE-24 vulnerability. - -Quark Script: CWE-24.py -======================== - -.. image:: https://i.postimg.cc/rwfc82VS/image.png - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "ovaa.apk" - RULE_PATH = "accessFileInExternalDir.json" - - - STRING_MATCHING_API = [ - ["Ljava/lang/String;", "contains", "(Ljava/lang/CharSequence)Z"], - ["Ljava/lang/String;", "indexOf", "(I)I"], - ["Ljava/lang/String;", "indexOf", "(Ljava/lang/String;)I"], - ["Ljava/lang/String;", "matches", "(Ljava/lang/String;)Z"], - [ - "Ljava/lang/String;", - "replaceAll", - "(Ljava/lang/String; Ljava/lang/String;)Ljava/lang/String;", - ], - ] - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for accessExternalDir in quarkResult.behaviorOccurList: - - filePath = accessExternalDir.secondAPI.getArguments()[2] - - if quarkResult.isHardcoded(filePath): - continue - - caller = accessExternalDir.methodCaller - strMatchingAPIs = [ - api - for api in STRING_MATCHING_API - if quarkResult.findMethodInCaller(caller, api) - ] - - if not strMatchingAPIs or "../" not in accessExternalDir.getParamValues(): - print(f"CWE-24 is detected in method, {caller.fullName}") - -Quark Rule: accessFileInExternalDir.json -========================================= - -.. image:: https://i.postimg.cc/1RDQ8qRR/image.png - -.. code-block:: json - - { - "crime": "Access a file in an external directory", - "permission": [], - "api": [ - { - "class": "Landroid/os/Environment;", - "method": "getExternalStorageDirectory", - "descriptor": "()Ljava/io/File;" - }, - { - "class": "Ljava/io/File;", - "method": "", - "descriptor": "(Ljava/io/File;Ljava/lang/String;)V" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-24.py - CWE-24 is detected in method, Loversecured/ovaa/providers/TheftOverwriteProvider; openFile (Landroid/net/Uri; Ljava/lang/String;)Landroid/os/ParcelFileDescriptor; - - - - - - -Detect CWE-359 in Android Application --------------------------------------- - -This scenario aims to demonstrate the detection of the **Exposure of Private Personal Information to an Unauthorized Actor** vulnerability. - -CWE-359: Exposure of Private Personal Information to an Unauthorized Actor -=========================================================================== - -We analyze the definition of CWE-359 and identify its characteristics. - -See `CWE-359 `_ for more details. - -.. image:: https://i.postimg.cc/QxZcD3gb/image.png - -Code of CWE-359 in ovaa.apk -============================ - -We use the `ovaa.apk `_ sample to explain the vulnerability code of CWE-359. - -.. image:: https://i.postimg.cc/LhKL2vvC/image.png - -CWE-359 Detection Process Using Quark Script API -================================================= - -.. image:: https://i.postimg.cc/8CB6ywzN/image.png - -Let’s use the above APIs to show how the Quark script finds this vulnerability. - -To begin with, we create a detection rule named ``accessFileWithUnsafeUriPath.json`` to identify behavior that accesses a file with an unsafe path from ``Uri``. - -Next, we use API ``methodInstance.methodCaller`` to retrieve the name of the caller that has this behavior. - -Then, we use API ``quarkResultInstance.isHardcoded(argument)`` to check if the file path is hardcoded into the APK. If not, the file path is likely from external input. - -After that, we use API ``getProviders(samplePath)`` and ``providerInstance.isExported()`` to check if there is any exported provider that matches the caller class name. If yes, any external application can access the behavior. - -Finally, we use API ``quarkResultInstance.findMethodInCaller(callerMethod, targetMethod)`` to search for any APIs in the caller method that are used to match strings. - -If **NO** API is found, that implies the APK does not neutralize special elements within the argument, possibly resulting in a CWE-359 vulnerability. - -Quark Script: CWE-359.py -========================= - -.. image:: https://i.postimg.cc/76KT46zR/image.png - -.. code-block:: python - - from quark.script import Rule, runQuarkAnalysis, getProviders - - SAMPLE_PATH = "ovaa.apk" - RULE_PATH = "accessFileWithUnsafeUriPath.json" - - STRING_MATCHING_API = [ - ["Ljava/lang/String;", "contains", "(Ljava/lang/CharSequence)Z"], - ["Ljava/lang/String;", "indexOf", "(I)I"], - ["Ljava/lang/String;", "indexOf", "(Ljava/lang/String;)I"], - ["Ljava/lang/String;", "matches", "(Ljava/lang/String;)Z"], - [ - "Ljava/lang/String;", - "replaceAll", - "(Ljava/lang/String; Ljava/lang/String;)Ljava/lang/String;", - ], - ] - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - exportedProviders = [ - str(provider) - for provider in getProviders(SAMPLE_PATH) - if provider.isExported() - ] - - for behavior in quarkResult.behaviorOccurList: - caller = behavior.methodCaller - classNameInJavaFormat = caller.className.replace("/", ".")[1:-1] - filePath = behavior.secondAPI.getArguments()[2] - - if quarkResult.isHardcoded(filePath): - continue - - if classNameInJavaFormat not in exportedProviders: - continue - - if not any( - quarkResult.findMethodInCaller(caller, api) - for api in STRING_MATCHING_API - ): - print(f"CWE-359 is detected in method, {caller.fullName}") - -Quark Rule: accessFileWithUnsafeUriPath.json -============================================= - -.. image:: https://i.postimg.cc/kGDRgmFg/image.png - -.. code-block:: json - - { - "crime": "Access a File with an unsafe path from Uri", - "permission": [], - "api": [ - { - "class": "Landroid/net/Uri;", - "method": "getLastPathSegment", - "descriptor": "()Ljava/lang/String;" - }, - { - "class": "Ljava/io/File;", - "method": "", - "descriptor": "(Ljava/io/File;Ljava/lang/String;)V" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-359.py - CWE-359 is detected in method, Loversecured/ovaa/providers/TheftOverwriteProvider; openFile (Landroid/net/Uri; Ljava/lang/String;)Landroid/os/ParcelFileDescriptor; - - - - -Detect CWE-256 in Android Application --------------------------------------- - -This scenario seeks to find **Plaintext Storage of a Password**. - -CWE-256: Plaintext Storage of a Password -========================================= - -We analyze the definition of CWE-256 and identify its characteristics. - -See `CWE-256 `_ for more details. - -.. image:: https://i.postimg.cc/rpydts5T/image.png - -Code of CWE-256 in ovaa.apk -============================ - -We use the `ovaa.apk `_ sample to explain the vulnerability code of CWE-256. - -.. image:: https://i.postimg.cc/RhtqzHx7/image.png - -CWE-256 Detection Process Using Quark Script API -================================================= - -.. image:: https://i.postimg.cc/X7PzpBFM/image.png - -First, we define a detection rule ``putStrAndCommit.json`` to identify behaviors that store information using ``SharedPreferences.Editor``. - -Next, we call ``behaviorInstance.getParamValues()`` to retrieve all parameter values associated with this behavior. We then check whether any parameter contains keywords that suggest it is being used as a password (e.g., ``password``, ``pswd``, or ``passwd``). - -Finally, we use ``behaviorInstance.isArgFromMethod(targetMethod)`` to verify whether the ``doFinal`` method for encryption is applied on the second argument ``value``. (Note: this Quark Script API checks all arguments, not just a specific one. Therefore, the API returns ``True`` even if the ``doFinal`` method is applied on the ``key`` argument rather than the ``value`` argument of ``putString`` . But the situation is so rare that we can neglect it.) - -If the answer is **NO**, it indicates that the value may be stored in plaintext, which could lead to a CWE-256 vulnerability. - -Quark Script CWE-256.py -======================== - -.. image:: https://i.postimg.cc/brxQ0JNR/image.png - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "ovaa.apk" - RULE_PATH = "putStrAndCommit.json" - - encryptAPI = ["Ljavax/crypto/Cipher;", "doFinal", ""] - - passwordPatterns = ["password", "pswd", "passwd"] - - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - for putStrAndCommit in quarkResult.behaviorOccurList: - paramValues = [ - paramValue.lower() for paramValue in putStrAndCommit.getParamValues() - ] - if not any( - passwordPattern in paramValues for passwordPattern in passwordPatterns - ): - continue - - if not putStrAndCommit.isArgFromMethod(encryptAPI): - print( - f"CWE-256 is detected in method", - putStrAndCommit.methodCaller.fullName - ) - -Quark Rule: putStrAndCommit.json -================================= - -.. image:: https://i.postimg.cc/h4sFPGpg/image.png - -.. code-block:: json - - { - "crime": "Use editor to store information", - "permission": [], - "api": [ - { - "class": "Landroid/content/SharedPreferences$Editor;", - "method": "putString", - "descriptor": "(Ljava/lang/String;Ljava/lang/String;)Landroid/content/SharedPreferences$Editor;" - }, - { - "class": "Landroid/content/SharedPreferences$Editor;", - "method": "commit", - "descriptor": "()Z" - } - ], - "score": 1, - "label": [] - } - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-256.py - CWE-256 is detected in method, Loversecured/ovaa/utils/LoginUtils; saveCredentials (Loversecured/ovaa/objects/LoginData;)V - - - - -Detect CWE-927 in Android Application --------------------------------------- - -This scenario seeks to find **Use of Implicit Intent for Sensitive Communication**. - -CWE-927: Use of Implicit Intent for Sensitive Communication -=========================================================== - -We analyze the definition of CWE-927 and identify its characteristics. - -See `CWE-927 `_ for more details. - -.. image:: https://hackmd.io/_uploads/H1UYN6pqxe.png - -Code of CWE-927 in ovaa.apk -============================ - -We use the `ovaa.apk `_ sample to explain the vulnerability code of CWE-927. - -.. image:: https://hackmd.io/_uploads/SJCe0Z1sll.png - -CWE-927 Detection Process Using Quark Script API -================================================= - -.. image:: https://hackmd.io/_uploads/ByAqo4ksxg.png - -First, we design a detection rule ``startActivityWithIntent.json`` to identify the behavior of using an intent to start an activity. - -Then, we use the API ``behaviorInstance.getMethodsInArgs()`` to retrieve a list of methods that prepare an intent. - -Finally, we check whether any component setting method is present in the list. If **none** is found, it indicates that the APK is using an implicit intent, which may lead to a CWE-927 vulnerability. - -Quark Script CWE-927.py -======================== - -.. image:: https://hackmd.io/_uploads/rkl2ii4ysex.png - -.. code-block:: python - - from quark.script import runQuarkAnalysis, Rule - - SAMPLE_PATH = "ovaa.apk" - RULE_PATH = "startActivityWithIntent.json" - - ruleInstance = Rule(RULE_PATH) - quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance) - - COMPONENT_SETTING_METHODS = ["setComponent", "setClass", "setClassName"] - - for intentUsage in quarkResult.behaviorOccurList: - calledMethods = intentUsage.getMethodsInArgs() - - if not any( - method.methodName in COMPONENT_SETTING_METHODS for method in calledMethods - ): - print(f"CWE-927 is detected in method, {intentUsage.methodCaller.fullName}") - - -Quark Rule: startActivityWithIntent.json -======================================== - -.. image:: https://i.postimg.cc/YSPCzMmQ/jie-tu-2025-12-20-shang-wu10-29-09.png - -.. code-block:: json - - { - "crime": "Start Activity With Intent.", - "permission": [], - "api": [ - { - "descriptor": "(Landroid/content/Context;Ljava/lang/Class;)V", - "class": "Landroid/content/Intent;", - "method": "" - }, - { - "descriptor": "(Landroid/content/Intent;)V", - "class": "", - "method": "startActivity" - } - ], - "score": 1, - "label": [] - } - - -Quark Script Result -==================== - -.. code-block:: TEXT - - $ python3 CWE-927.py - CWE-927 is detected in method, Loversecured/ovaa/activities/DeeplinkActivity; processDeeplink (Landroid/net/Uri;)V diff --git a/docs/source/quark_script_visualization.rst b/docs/source/quark_script_visualization.rst deleted file mode 100644 index 2178e3006..000000000 --- a/docs/source/quark_script_visualization.rst +++ /dev/null @@ -1,34 +0,0 @@ -++++++++++++++++++++++++++++ -Quark Script Visualization -++++++++++++++++++++++++++++ - -Introduction of the Program ----------------------------- - -Quark Script is a powerful tool for detecting and analyzing mobile security. However, it can be complex and challenging for user who are not familiar with programming. To overcome this challenge, we are pleased to announce our plan to develop a visual programming tool that simplifies the Quark Script organization process, making it easy for anyone to organize Quark Script using a simple UI interface. - -Goal of the Program --------------------- - -We aim to make Quark Script programming accessible to everyone and remove the barriers that often come with traditional programming languages. So we design a new visual tool for Quark Script organization. It would be more intuitive, time-saving, and effort-saving for users, even if they are not familiar with programming. - -Web Design Layout ------------------- - -The initial draft of the web design is as below. - -Design by: `@Commuter95 `_ - -.. image:: https://github.com/quark-engine/quark-engine/assets/16009212/053d62e2-181a-4fb1-96d7-95fe59809dc3 - -The website's initial design concept -------------------------------------- - -We structure the website into five distinct sections, which are as follows: - -1. At the top area, the navigation bar displays links to documents and social media accounts. -2. On the top right, you can fine-tune the parameters of the APIs. -3. In the bottom right, you can copy the resulting program and run it on your computer. -4. In the center, you can seamlessly drag and assemble Quark Script APIs from the left. -5. On the left area, you can select a CWE example as a template and choose Quark Script APIs to add. - diff --git a/docs/source/rule_generation.rst b/docs/source/rule_generation.rst deleted file mode 100644 index 9eceeb41b..000000000 --- a/docs/source/rule_generation.rst +++ /dev/null @@ -1,103 +0,0 @@ -++++++++++++++++++++++++++++++++++++++++ -Rule Generation -++++++++++++++++++++++++++++++++++++++++ - -The Rule generation technique is based on the idea below: - -1. Sort all APIs used in an APK by their usage counts. -2. Separate all APIs into two groups, P(20% least usage count) and S(other 80% APIs), by the Pareto principle (20-80 rule). -3. Combine $P$ and $S$ into four different phases: - - PxP - - PxS - - SxP - - SxS -4. Execute the rule generation with each phase in this order: PxP -> PxS -> SxP -> SxS - -The earlier the phase, the higher the value of the rule but less time spent. -We can generate rules in a phased manner according to different situations. -For example, under a time constraint, we can take PxP phase rules as an overview for the target APK. - -CLI Usage ------------------------- -Generate rules for APK with the following command:: - - $ quark -a --generate-rule - -Generate rules and web editor with the following command:: - - $ quark -a --generate-rule -w - - -API Usage ------------------------------------ - -And here is the simplest way for API usage: - -.. code-block:: python - - from quark.rulegeneration import RuleGeneration - - # The target APK. - APK_PATH = "Ahmyth.apk" - - # The output directory for generated rules. - GENERATED_RULE_DIR = "generated_rules" - - generator = RuleGeneration(APK_PATH, GENERATED_RULE_DIR) - generator.generate_rule(web_editor="report.html") - - -Web Editor Tutorial ------------------------------------ - -Here is the demo for the rule generation web editor. -You can easily review and edit generated rules with 5 steps: - -1. Input keywords to search rules. -2. Select the generated rules you want to save. -3. Edit rule information. - -.. image:: https://i.imgur.com/0FLlGq0.png - -4. Edit crime, score, and labels with the editor. -5. Save the edited rule. - -.. image:: https://i.imgur.com/kIVIeCk.png - - -Radiocontrast ------------------------------------ -Radiocontrast is a Quark API that quickly generates Quark rules from a specified method. It builds up 100% matched rules by using native APIs in that method. The feature lets you easily expose the behavior of a method, just like radiocontrast. - -For example, we want to know the behavior of a method called ``Lahmyth/mine/king/ahmyth/CameraManager;->startUp(I)V,`` in Ahmyth.apk. -Here is the simplest way for Radiocontrast usage: - -.. code-block:: python - - from quark.radiocontrast import RadioContrast - - # The target APK. - APK_PATH = "Ahmyth.apk" - - # The method that you want to generate rules. - TARGET_METHOD = "Lahmyth/mine/king/ahmyth/CameraManager;->startUp(I)V" - - # The output directory for generated rules. - GENERATED_RULE_DIR = "~/generated_rules" - - radiocontrast = RadioContrast( - APK_PATH, - TARGET_METHOD, - GENERATED_RULE_DIR - ) - - radiocontrast.generate_rule() - -Use web editor to manage generated rules, you can define the parameter ``web_editor`` in ``generate_rule()`` as the path of output html file:: - - radiocontrast.generate_rule(web_editor="ahmyth.html") - -The parameter ``percentile_rank`` in ``generate_rule()`` as the percentile number of API filter rank. -For example, if you want to keep the 20% least usage count APIs, set the percentile_rank as 0.2:: - - radiocontrast.generate_rule(percentile_rank=0.2) diff --git a/docs/source/testing.rst b/docs/source/testing.rst deleted file mode 100644 index 80edc9d05..000000000 --- a/docs/source/testing.rst +++ /dev/null @@ -1,38 +0,0 @@ -++++++++++++++++++++ -Testing Quark-Engine -++++++++++++++++++++ - -Firstly let's fetch some apk examples. - -.. code-block:: bash - - $ git clone https://github.com/quark-engine/apk-samples.git - - -Then we could test one of the apk in `apk-samples/malware-samples` by the rules `quark-rules`. For example: - -.. code-block:: bash - - $ quark -a Ahmyth.apk -s - - -Running in Docker -================= - -We could build the corresponding docker image by this command: - -.. code-block:: bash - - docker build . -t quark - - -When the image is ready, let's run an example to test the image: - -You may also interactively use quark in the docker container. For example: - -.. code-block:: bash - - $ docker run -v $(pwd):/tmp -it quark bash - (in-docker): /app/quark# cd /tmp - (in-docker)::/tmp# quark -a Ahmyth.apk -s -