Androguard交叉引用Crossreferences(XREFs)
Crossreferences(XREFs)交叉引用,是由 androguard.core.analysis.analysis.Analysis
类提供的,用于处理 Classes,Methods,Fields 和 Strings
查看类和方法的具体调用情况
准备工作,通过 androguard analyze
命令开启 ipython shell,以腾讯会议的 APK 为例
ubuntu@ubuntu:~$ androguard analyze /home/ubuntu/Desktop/meeting.apk
Please be patient, this might take a while.
Found the provided file is of type 'APK'
[INFO ] androguard.apk: Starting analysis on AndroidManifest.xml
[INFO ] androguard.apk: APK file was successfully validated!
[INFO ] androguard.analysis: Adding DEX file version 35
[INFO ] androguard.analysis: Reading bytecode took : 0min 00s
[INFO ] androguard.analysis: Adding DEX file version 35
[INFO ] androguard.analysis: Reading bytecode took : 0min 00s
[INFO ] androguard.analysis: End of creating cross references (XREF) run time: 0min 00s
Added file to session: SHA256::689673bed0f4d6121a63f3c9fd88efb538ec316561d426120c440d8be89f6256
Loaded APK file...
>>> a
<androguard.core.bytecodes.apk.APK object at 0x7f029d0329b0>
>>> d
[<androguard.core.bytecodes.dvm.DalvikVMFormat object at 0x7f029083f978>, <androguard.core.bytecodes.dvm.DalvikVMFormat object at 0x7f02907d9b00>]
>>> dx
<analysis.Analysis VMs: 2, Classes: 85, Methods: 340, Strings: 122>
Androguard version 3.4.0a1 started
获取方法调用的 XREFs
接下来从 java/io/FileNotFoundException;
类查询调用的类(如果使用其他 APK 进行分析,在进行到这步时最好先使用 dx.get_classes()
查询该 APK 包含的类),注意在写类名时不能再用 “.” 分割,而是应该用正斜杠 “/”
In [9]: dx.classes['Ljava/io/FileNotFoundException;']
Out[9]: <analysis.ClassAnalysis Ljava/io/FileNotFoundException; EXTERNAL>
接下来遍历该类内部的所有方法并输出 XREFs
In [7]: for meth in dx.classes['Lcom/wrapper/proxyapplication/WrapperProxyApplication;'].get_meth
...: ods():
...: print("inside method {}".format(meth.name))
...: for _, call,_ in meth.get_xref_to():
...: print(" calling -> {} -- {}".format(call.class_name, call.name))
...:
inside method <clinit>
inside method <init>
calling -> Landroid/app/Application; -- <init>
inside method Fixappname
calling -> Ljava/lang/StringBuilder; -- <init>
calling -> Ljava/lang/StringBuilder; -- toString
calling -> Ljava/lang/StringBuilder; -- <init>
calling -> Ljava/lang/String; -- indexOf
calling -> Landroid/app/Application; -- getPackageName
calling -> Ljava/lang/String; -- valueOf
calling -> Ljava/lang/StringBuilder; -- toString
calling -> Ljava/lang/StringBuilder; -- append
calling -> Ljava/lang/String; -- startsWith
calling -> Ljava/lang/String; -- valueOf
calling -> Ljava/lang/StringBuilder; -- append
calling -> Landroid/app/Application; -- getPackageName
calling -> Ljava/lang/StringBuilder; -- append
inside method fixAndroid
calling -> Lcom/wrapper/proxyapplication/ShareReflectUtil; -- getField
calling -> Lcom/wrapper/proxyapplication/AndroidNClassLoader; -- inject
calling -> Ljava/lang/Class; -- forName
calling -> Ljava/lang/StringBuilder; -- append
calling -> Ljava/lang/Throwable; -- printStackTrace
calling -> Ljava/lang/StringBuilder; -- toString
calling -> Landroid/util/Log; -- e
calling -> Lcom/wrapper/proxyapplication/ShareReflectUtil; -- getField
calling -> Ljava/lang/Class; -- forName
calling -> Ljava/lang/StringBuilder; -- append
calling -> Ljava/lang/StringBuilder; -- toString
calling -> Landroid/content/Context; -- getClassLoader
calling -> Landroid/util/Log; -- e
calling -> Ljava/lang/StringBuilder; -- <init>
calling -> Ljava/lang/StringBuilder; -- <init>
inside method getVersionCode
calling -> Landroid/content/pm/PackageManager; -- getPackageInfo
calling -> Landroid/content/pm/PackageManager$NameNotFoundException; -- printStackTrace
calling -> Landroid/content/Context; -- getPackageName
calling -> Landroid/content/Context; -- getPackageManager
inside method getWrapperProxyAppBaseContext
inside method Ooo0ooO0oO
inside method attachBaseContext
calling -> Lcom/wrapper/proxyapplication/WrapperProxyApplication; -- getBaseContext
calling -> Lcom/wrapper/proxyapplication/WrapperProxyApplication; -- Fixappname
calling -> Landroid/app/Application; -- attachBaseContext
calling -> Lcom/wrapper/proxyapplication/WrapperProxyApplication; -- initProxyApplication
inside method initProxyApplication
inside method onCreate
calling -> Lcom/wrapper/proxyapplication/WrapperProxyApplication; -- Ooo0ooO0oO
calling -> Landroid/app/Application; -- onCreate
inside method getBaseContext
注意,若方法为外部方法(外部类或方法是在已加载的 dex 文件中找不到的类或方法),将不会输出 XREFs_to,但可以查看 XREFs_from。
查看字符串的具体调用情况
如果想查看字符串的具体使用情况,可以通过 androguard.core.analysis.analysis.Analysis.strings
或者 androguard.core.analysis.analysis.Analysis.find_strings
来得到具体对象的 XREFs
In [9]: dx.strings['Unknown']
Out[9]: <analysis.StringAnalysis 'Unknown'>
由于字符串仅能被使用,而不能执行调用动作,所以对于字符串只存在 xref_from
In [11]: for _,meth in dx.strings['Unknown'].get_xref_from():
...: print("Used in: {} -- {}".format(meth.class_name, meth.name))
...:
Used in: Lcom/wrapper/proxyapplication/CustomerClassLoader; -- getPackage
查看字段的具体调用情况
字段的情况相较于前面三者不同,它没有 xref_from
和 xref_to
,而是使用 androguard.core.analysis.analysis.FieldAnalysis.xref_read
方法和 androguard.core.analysis.analysis.FieldAnalysis.xref_write
方法,通过 androguard.core.analysis.analysis.Analysis.find_methods
查找字段。
通常不会跟踪对静态字段的调用,因为编译器将其优化为 const 调用
In [25]: for field in dx.find_fields(classname='Ltests/androguard/TestActivity;', fieldname='^value$'):
...: print("Field: {}".format(field.name))
...: for _, meth in field.get_xref_read():
...: print(" read in {} -- {}".format(meth.class_name, meth.name))
...: for _, meth in field.get_xref_write():
...: print(" write in {} -- {}".format(meth.class_name, meth.name))
...:
Field: value
read in Ltests/androguard/TestActivity; -- pouet
read in Ltests/androguard/TestActivity; -- test1
read in Ltests/androguard/TestActivity; -- test_base
read in Ltests/androguard/TestActivity; -- testVars
write in Ltests/androguard/TestActivity; -- <init>
write in Ltests/androguard/TestActivity; -- pouet2
write in Ltests/androguard/TestActivity; -- <init>
write in Ltests/androguard/TestActivity; -- <init>