=================================
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 register_name, value, called_by_func in a single
instance.
.. image:: https://i.imgur.com/k5nHprC.png
============== ========== =================================================
register_name value called_by_func
============== ========== =================================================
"v3" "GPS" Lcom/google/progress/APNOperator;->deleteAPN()Z
============== ========== =================================================
**register_name**: register name, such as "v3", "v4".
**value**: the value stored in the register.
**called_by_func**: what functions are called with this register as a parameter.
Explanation of each function
----------------------------
* **hash_index**:
- Get the index number from given VarabileObject, given "v34" will return 34.