Source code for androlyze.model.script.util.AnaUtil


# encoding: utf-8

__author__ = "Nils Tobias Schmidt"
__email__ = "schmidt89 at informatik.uni-marburg.de"

from androguard.decompiler.dad import decompile
import re

from androlyze.log.Log import log


############################################################
#---Checks
############################################################

[docs]def check_own_method_implementation(apk, encoded_method): ''' Check if the `encoded_method` is implemented in an own package (no third party) ''' # package name separated with "." apk_pn = apk.package_name.lower() method_pn = convert_dalvik_pn_to_java_pn(encoded_method.get_class_name().lower()) # package names equal ?? if method_pn.find(apk_pn) != -1: return True
[docs]def check_method_contains_string(enoded_method, regexp, lowercase = True, all_findings = False): ''' Check if the `encoded_method` contains the `string` in the instruction output. Parameters ---------- enoded_method: androguard.core.bytecodes.dvm.EncodedMethod regexp: str lowercase: boolean, optional (default is True) Convert the string on which shall be matched beforehand to lowercase all_findings : bool, optional (default is False) If true, return a list of all match objects Returns ------- re match object If not `all_findings`. list<re match object> Else ''' res = [] for instr in enoded_method.get_instructions(): match_on = instr.get_output() if lowercase: match_on = match_on.lower() match_object = re.search(regexp, match_on) if match_object: if not all_findings: return match_object else: res.append(match_object) return res
[docs]def check_instructions_one(instructions, func): ''' Check if at least one instruction matches with `func`. Parameters ---------- instructions: iterable<androguard.core.bytecodes.dvm.Instruction> func: Instruction -> Bool Returns ------- bool ''' for instruction in instructions: if func(instruction): return True
############################################################ #---Decompilation ############################################################
[docs]def decompile_pathp(pathp, dalvik_vm_format, vm_analysis, caller = True, show_class = True): ''' Decompile either the caller or callee Parameters ---------- pathp: androguard.androguard.core.analysis.analysis.PathP Edge in method call graph. dalvik_vm_format: DalvikVMFormat Parsed .dex file. vm_analysis: uVMAnalysis Dex analyzer. caller: bool, optional (default is True) Use the src of the `pathp`, hence decompile the caller. Otherwise the dst is used. show_class : bool, optional (default is True) Include the package name in the decompilation. Returns ------- str The decompiled method None N/A Example ------- >>> decompile_pathp(...) protected varargs String doInBackground(Void[] p14) { org.apache.http.client.methods.HttpGet v6_1 = new org.apache.http.client.methods.HttpGet("http://10.10.0.134:8080/index.html"); v6_1.addHeader("Authorization", new StringBuilder().append("Basic ").append(android.util.Base64.encodeToString(this.CREDENTIALS.getBytes(), 2)).toString()); try { java.io.InputStream v9 = new org.apache.http.impl.client.DefaultHttpClient().execute(v6_1).getEntity().getContent(); int v7 = de.uni_marburg.ipcinetcallee.InetActivity.inputStream2String(v9); v9.close(); } catch (org.apache.http.client.ClientProtocolException v2) { android.util.Log.e("HTTPGetTask", "msg", v2); v7 = 0; } catch (java.io.IOException v5) { android.util.Log.e("HTTPGetTask", "msg", v5); } return v7; } ''' idx = pathp.src_idx if caller else pathp.dst_idx encoded_method = dalvik_vm_format.get_method_by_idx(idx) if encoded_method is not None: method_analysis = vm_analysis.get_method(encoded_method) res = "" if show_class: res += "class %s\n" % encoded_method.get_class_name() res += decompile_method_analysis(method_analysis) return res
# TODO: ADD MORE DECOMPILERS!
[docs]def decompile_method_analysis(method_analysis): ''' Decompile the `method_analysis` object Parameters ---------- method_analysis: androguard.androguard.core.analysis.analysis.MethodAnalysis Returns ------- str The decompiled method Example ------- >>> decompile_method_analysis(...) protected varargs String doInBackground(Void[] p14) { org.apache.http.client.methods.HttpGet v6_1 = new org.apache.http.client.methods.HttpGet("http://10.10.0.134:8080/index.html"); v6_1.addHeader("Authorization", new StringBuilder().append("Basic ").append(android.util.Base64.encodeToString(this.CREDENTIALS.getBytes(), 2)).toString()); try { java.io.InputStream v9 = new org.apache.http.impl.client.DefaultHttpClient().execute(v6_1).getEntity().getContent(); int v7 = de.uni_marburg.ipcinetcallee.InetActivity.inputStream2String(v9); v9.close(); } catch (org.apache.http.client.ClientProtocolException v2) { android.util.Log.e("HTTPGetTask", "msg", v2); v7 = 0; } catch (java.io.IOException v5) { android.util.Log.e("HTTPGetTask", "msg", v5); } return v7; } ''' dv_method = decompile.DvMethod(method_analysis) dv_method.process() return dv_method.get_source()
############################################################ #---Disassembly ############################################################
[docs]def disassemble_encoded_method(encoded_method): ''' Create the disassemble of the `encoded_method` Parameters ---------- encoded_method : androguard.androguard.core.bytecodes.dvm.EncodedMethod Returns ------- str The disassembled method Example ------- >>> disassemble_encoded_method(...) Lde/uni_marburg/ipcinetcallee/InetActivity$HTTPGetTask; doInBackground ([Ljava/lang/Void;)Ljava/lang/String; 0 new-instance v6, Lorg/apache/http/client/methods/HttpGet; 4 const-string v10, 'http://10.10.0.134:8080/index.html' 8 invoke-direct v6, v10, Lorg/apache/http/client/methods/HttpGet;-><init>(Ljava/lang/String;)V e iget-object v10, v13, Lde/uni_marburg/ipcinetcallee/InetActivity$HTTPGetTask;->CREDENTIALS Ljava/lang/String; 12 invoke-virtual v10, Ljava/lang/String;->getBytes()[B 18 move-result-object v10 1a const/4 v11, 2 1c invoke-static v10, v11, Landroid/util/Base64;->encodeToString([B I)Ljava/lang/String; 22 move-result-object v0 24 const-string v10, 'Authorization' 28 new-instance v11, Ljava/lang/StringBuilder; 2c invoke-direct v11, Ljava/lang/StringBuilder;-><init>()V 32 const-string v12, 'Basic ' 36 invoke-virtual v11, v12, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; 3c move-result-object v11 3e invoke-virtual v11, v0, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; 44 move-result-object v11 46 invoke-virtual v11, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; 4c move-result-object v11 4e invoke-interface v6, v10, v11, Lorg/apache/http/client/methods/HttpUriRequest;->addHeader(Ljava/lang/String; Ljava/lang/String;)V 54 new-instance v4, Lorg/apache/http/impl/client/DefaultHttpClient; 58 invoke-direct v4, Lorg/apache/http/impl/client/DefaultHttpClient;-><init>()V 5e const-string v3, '' 62 const/16 v10, 8192 66 new-array v1, v10, [B 6a invoke-interface v4, v6, Lorg/apache/http/client/HttpClient;->execute(Lorg/apache/http/client/methods/HttpUriRequest;)Lorg/apache/http/HttpResponse; 70 move-result-object v8 72 invoke-interface v8, Lorg/apache/http/HttpResponse;->getEntity()Lorg/apache/http/HttpEntity; 78 move-result-object v10 7a invoke-interface v10, Lorg/apache/http/HttpEntity;->getContent()Ljava/io/InputStream; 80 move-result-object v9 82 invoke-static v9, Lde/uni_marburg/ipcinetcallee/InetActivity;->inputStream2String(Ljava/io/InputStream;)Ljava/lang/String; 88 move-result-object v7 8a invoke-virtual v9, Ljava/io/InputStream;->close()V 90 return-object v7 92 move-exception v2 94 const-string v10, 'HTTPGetTask' 98 const-string v11, 'msg' 9c invoke-static v10, v11, v2, Landroid/util/Log;->e(Ljava/lang/String; Ljava/lang/String; Ljava/lang/Throwable;)I a2 const/4 v7, 0 a4 goto -a a6 move-exception v5 a8 const-string v10, 'HTTPGetTask' ac const-string v11, 'msg' b0 invoke-static v10, v11, v5, Landroid/util/Log;->e(Ljava/lang/String; Ljava/lang/String; Ljava/lang/Throwable;)I b6 goto -a ''' # add method signature disassembly = fmt_encoded_method(encoded_method) + "\n" idx = 0 for i in encoded_method.get_instructions(): disassembly += "%x %s %s\n" % (idx, i.get_name(), i.get_output()) idx += i.get_length() return disassembly
[docs]def disassemble_pathp(pathp, dalvik_vm_format, caller = True): ''' Disassemble either the caller or callee. Parameters ---------- pathp: androguard.androguard.core.analysis.analysis.PathP Edge in method call graph. dalvik_vm_format: DalvikVMFormat Parsed .dex file. caller: bool, optional (default is True) Use the src of the `pathp`, hence disassemble the caller. Otherwise the dst is used. Returns ------- str The disassembled method. None N/A See :py:method:`.disassemble_encoded_method` ''' idx = pathp.src_idx if caller else pathp.dst_idx encoded_method = dalvik_vm_format.get_method_by_idx(idx) if encoded_method is not None: return disassemble_encoded_method(encoded_method)
############################################################ #---Filtering ############################################################
[docs]def filter_own_implementations(apk, dalvik_vm_format, pathp_list): ''' Filter the `PathP` objects which are inside the apk package Parameters ---------- apk: Apk The apk representation dalvik_vm_format: DalvikVMFormat Parsed .dex file. pathp_list: list<androguard.androguard.core.analysis.analysis.PathP> Returns ------- list<androguard.androguard.core.analysis.analysis.PathP> ''' pathp_list_check = [] for pathp in pathp_list: encoded_method = dalvik_vm_format.get_method_by_idx(pathp.src_idx) # package name separated with "." apk_pn = apk.package_name.lower() method_pn = convert_dalvik_pn_to_java_pn(encoded_method.get_class_name().lower()) # package names equal ?? if method_pn.find(apk_pn) != -1: pathp_list_check.append(pathp) return pathp_list_check
############################################################ #---Abstract Syntax Tree (AST) ############################################################
[docs]def ast_for_pathp(pathp, dalvik_vm_format, vm_analysis, caller = True): ''' Disassemble either the caller or callee. Parameters ---------- pathp: androguard.androguard.core.analysis.analysis.PathP Edge in method call graph. dalvik_vm_format: DalvikVMFormat Parsed .dex file. vm_analysis: VMAnalysis Dex analyzer. caller: bool, optional (default is True) Use the src of the `pathp`, hence disassemble the caller. Otherwise the dst is used. Returns ------- str The disassembled method. None N/A ''' idx = pathp.src_idx if caller else pathp.dst_idx encoded_method = dalvik_vm_format.get_method_by_idx(idx) if encoded_method is not None: return ast_for_method_analysis(vm_analysis.get_method(encoded_method))
[docs]def ast_for_method_analysis(method_analysis): ''' Create the abstract syntax tree. Parameters ---------- method_analysis: androguard.androguard.core.analysis.analysis.MethodAnalysis Returns ------- dict The abstract syntax tree of the `method_analysis`. ''' dv_method = decompile.DvMethod(method_analysis) dv_method.process(doAST = True) return dv_method.ast
[docs]def ast_get_containing_collection(iterable, pattern): ''' Check the structure recursive for matches with the regex `pattern` and return the collection that contains the match. Parameters ---------- iterable: iterable pattern: str Regex Returns ------- iterable ''' def ast_get_containing_collection_inner(iterable, pattern, containing_collection, findings): def do_check(on, containing_collection): if isinstance(on, (str, unicode)): mo = re.search(pattern, on) if mo: findings.append(containing_collection) return mo # dict if isinstance(iterable, dict): # recursively check all keys and values for k, v in iterable.items(): # do check (method has side-effect!) do_check(k, iterable) # recursively check value too ast_get_containing_collection_inner(v, pattern, iterable, findings) # lists, sets elif isinstance(iterable, (tuple, list, set)): for it in iterable: ast_get_containing_collection_inner(it, pattern, iterable, findings) # do_check on value else: do_check(iterable, containing_collection) return findings return ast_get_containing_collection_inner(iterable, pattern, iterable, [])
############################################################ #---Formatting ############################################################
[docs]def fmt_encoded_method(encoded_method): ''' Return a string represenation of `encoded_method`. Parameters ---------- encoded_method : androguard.androguard.core.bytecodes.dvm.EncodedMethod Returns ------- str Example ------- >>> fmt_encoded_method(...) Lde/uni_marburg/ipcinetcallee/InetActivity$HTTPGetTask; doInBackground ([Ljava/lang/Void;)Ljava/lang/String; ''' return "%s %s %s" % (encoded_method.get_class_name(), encoded_method.get_name(), encoded_method.get_descriptor())
############################################################ #---Converting ############################################################
[docs]def convert_dalvik_pn_to_java_pn(dalvik_pn, ignore_inner_class = True): ''' Convert e.g. "Lde/uni_marburg/ipcinetcallee/InetActivity$HTTPGetTask;" to "de.uni_marburg.ipcinetcall.InetActivity" Parameters ---------- ignore_inner_class : bool, optional (default is True) Strip inner class names like $HTTPGetTask Returns ------- str Example ------- >>> print convert_dalvik_pn_to_java_pn('Lde/uni_marburg/ipcinetcallee/InetActivity$HTTPGetTask;', True) "de.uni_marburg.ipcinetcallee.InetActivity" >>> print convert_dalvik_pn_to_java_pn('Lde/uni_marburg/ipcinetcallee/InetActivity$HTTPGetTask;', False) "de.uni_marburg.ipcinetcallee.InetActivity.HTTPGetTask" ''' package_name = dalvik_pn[1:] package_name = package_name.replace("/", ".") package_name = package_name[:-1] if not ignore_inner_class: package_name = re.sub("\$d*", ".", package_name) else: dollar_idx = package_name.find("$") if dollar_idx != -1: package_name = package_name[:dollar_idx] return package_name
[docs]def convert_java_pn_to_dalvik(java_pn): ''' Convert e.g. "de.uni_marburg.ipcinetcall.InetActivity" to "Lde/uni_marburg/ipcinetcallee/InetActivity;" Parameters ---------- java_pn: str Package name separated with "." Returns ------- str ''' java_pn = java_pn.replace(".", "/") return 'L%s;' % java_pn
if __name__ == '__main__': print convert_dalvik_pn_to_java_pn('Lde/uni_marburg/ipcinetcallee/InetActivity$HTTPGetTask;', True) print convert_dalvik_pn_to_java_pn('Lde/uni_marburg/ipcinetcallee/InetActivity$HTTPGetTask;', False) print convert_java_pn_to_dalvik('de.uni_marburg.ipcinetcallee.InetActivity')