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>