前言
相信最近在App上架應用商店的同學都感受到了惹盼,國內(nèi)對用戶的隱私越來越重視春瞬,如MAC地址,設備ID鸭津,IMEI信息等彤侍,要么就干脆不用,要么就必須很明顯的告訴用戶想要獲取這些信息逆趋,相關法律及規(guī)定盏阶,參考《網(wǎng)絡安全法》及《關于開展APP侵害用戶權益專項整治工作的通知》
開門見山
廢話不多說,找了幾個反編譯工具父泳,并簡單看了下使用方法般哼,最終鎖定androguard,官方解釋:對Android應用程序的逆向工程惠窄、惡意軟件和惡意軟件分析蒸眠,它提供了一系列的Apk以及dex、odex杆融、arsc等文件的分析處理功能楞卡,可以輕松的幫助我們找到調(diào)用系統(tǒng)權限的地方。且python腳本執(zhí)行脾歇,簡直不能再好用了
環(huán)境
- python
https://www.python.org
- pycharm
https://www.jetbrains.com/pycharm/download/
- androguard
https://androguard.readthedocs.io/en/latest/
安裝
pip install -U androguard
如果想在命令行直接操作蒋腮,請在安裝完后執(zhí)行如下:
androguard analyze
執(zhí)行后如圖:
然后再加載apk,在上面執(zhí)行后藕各,輸入如下:
a, d, dx = AnalyzeAPK("examples/android/abcore/app-prod-debug.apk")
apk加載完成后就可以調(diào)用相關api來獲取信息
獲取權限
In [2]: a.get_permissions()
Out[2]:
['android.permission.INTERNET',
'android.permission.WRITE_EXTERNAL_STORAGE',
'android.permission.ACCESS_WIFI_STATE',
'android.permission.ACCESS_NETWORK_STATE']
獲取Activity
In [3]: a.get_activities()
Out[3]:
['com.greenaddress.abcore.MainActivity',
'com.greenaddress.abcore.BitcoinConfEditActivity',
'com.greenaddress.abcore.AboutActivity',
'com.greenaddress.abcore.SettingsActivity',
'com.greenaddress.abcore.DownloadSettingsActivity',
'com.greenaddress.abcore.PeerActivity',
'com.greenaddress.abcore.ProgressActivity',
'com.greenaddress.abcore.LogActivity',
'com.greenaddress.abcore.ConsoleActivity',
'com.greenaddress.abcore.DownloadActivity']
其他
# 包名
In [4]: a.get_package()
Out[4]: 'com.greenaddress.abcore'
# app名字
In [5]: a.get_app_name()
Out[5]: u'ABCore'
# logo
In [6]: a.get_app_icon()
Out[6]: u'res/mipmap-xxxhdpi-v4/ic_launcher.png'
# 版本號
In [7]: a.get_androidversion_code()
Out[7]: '2162'
# 版本名
In [8]: a.get_androidversion_name()
Out[8]: '0.62'
# 最低sdk支持
In [9]: a.get_min_sdk_version()
Out[9]: '21'
# 最高
In [10]: a.get_max_sdk_version()
# 目標版本
In [11]: a.get_target_sdk_version()
Out[11]: '27'
# 獲取有效目標版本
In [12]: a.get_effective_target_sdk_version()
Out[12]: 27
# manifest文件
In [13]: a.get_android_manifest_xml()
Out[13]: <Element manifest at 0x7f9d01587b00>
等等吧池摧,Api實在是太多了,還是關注官方文檔吧激况,只有你想不到作彤,沒有它沒有的膘魄,如下鏈接:
https://androguard.readthedocs.io/en/latest/intro/gettingstarted.html#using-the-analysis-object
更多demo
https://github.com/androguard/androguard/tree/master/examples
下面直接開始實踐。
檢索使用敏感權限的地方并輸出文件
下面就是檢查APK中使用敏感權限的實現(xiàn)竭讳,請看:
import os
import sys
# 引入androguard的路徑创葡,根據(jù)個人存放的位置而定
androguard_module_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'androguard')
if not androguard_module_path in sys.path:
sys.path.append(androguard_module_path)
from androguard.misc import AnalyzeAPK
from androguard.core.androconf import load_api_specific_resource_module
path = r"/apk"
out_path = r"/out"
files = []
path_list = os.listdir(path)
path_list.sort()
for name in path_list:
if os.path.isfile(os.path.join(path, name)):
files.append(name)
def main():
for apkFile in files:
file_name = os.path.splitext(apkFile)[0]
print(apkFile)
out = AnalyzeAPK(path + '/' + apkFile)
# apk object 抽象apk對象,可以獲取apk的一些信息绢慢,如版本號灿渴、包名、Activity等
a = out[0]
# DalvikVMFormat 數(shù)組胰舆,一個元素其實對應的是class.dex骚露,可以從DEX文件中獲取類、方法或字符串思瘟。
d = out[1]
# Analysis 分析對象荸百,因為它包含特殊的類,這些類鏈接有關classes.dex的信息滨攻,甚至可以一次處理許多dex文件够话,所以下面我們從這里面來分析整個apk
dx = out[2]
# api和權限映射
# 輸出文件路徑
api_perm_filename = os.path.join(out_path, file_name + "_api-perm.txt")
api_perm_file = open(api_perm_filename, 'w', encoding='utf-8')
# 權限映射map
permissionMap = load_api_specific_resource_module('api_permission_mappings')
# 遍歷apk所有方法
for meth_analysis in dx.get_methods():
meth = meth_analysis.get_method()
# 獲取類名、方法名
name = meth.get_class_name() + "-" + meth.get_name() + "-" + str(
meth.get_descriptor())
for k, v in permissionMap.items():
# 匹配系統(tǒng)權限方法光绕,匹配上就輸出到文件中
if name == k:
result = str(meth) + ' : ' + str(v)
api_perm_file.write(result + '\n')
api_perm_file.close()
if __name__ == '__main__':
main()
輸出結果
Landroid/app/Activity;->navigateUpTo(Landroid/content/Intent;)Z : ['android.permission.BROADCAST_STICKY']
Landroid/app/Activity;->onMenuItemSelected(I Landroid/view/MenuItem;)Z : ['android.permission.BROADCAST_STICKY']
Landroid/app/Activity;->setRequestedOrientation(I)V : ['android.permission.BROADCAST_STICKY']
Landroid/app/Activity;->unregisterReceiver(Landroid/content/BroadcastReceiver;)V : ['android.permission.BROADCAST_STICKY']
Landroid/os/PowerManager$WakeLock;->acquire(J)V : ['android.permission.WAKE_LOCK']
Landroid/os/PowerManager$WakeLock;->release()V : ['android.permission.WAKE_LOCK']
Landroid/location/LocationManager;->isProviderEnabled(Ljava/lang/String;)Z : ['android.permission.ACCESS_COARSE_LOCATION', 'android.permission.ACCESS_FINE_LOCATION']
Landroid/location/LocationManager;->getLastKnownLocation(Ljava/lang/String;)Landroid/location/Location; : ['android.permission.ACCESS_COARSE_LOCATION', 'android.permission.ACCESS_FINE_LOCATION']
Landroid/app/ActivityManager;->getRunningTasks(I)Ljava/util/List; : ['android.permission.GET_TASKS']
Landroid/accounts/AccountManager;->invalidateAuthToken(Ljava/lang/String; Ljava/lang/String;)V : ['android.permission.MANAGE_ACCOUNTS', 'android.permission.USE_CREDENTIALS']
Landroid/net/ConnectivityManager;->getNetworkInfo(I)Landroid/net/NetworkInfo; : ['android.permission.ACCESS_NETWORK_STATE']
Landroid/net/ConnectivityManager;->isActiveNetworkMetered()Z : ['android.permission.ACCESS_NETWORK_STATE']
Landroid/net/ConnectivityManager;->getActiveNetworkInfo()Landroid/net/NetworkInfo; : ['android.permission.ACCESS_NETWORK_STATE']
Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String; : ['android.permission.READ_PHONE_STATE']
Landroid/telephony/TelephonyManager;->getSubscriberId()Ljava/lang/String; : ['android.permission.READ_PHONE_STATE']
Landroid/telephony/TelephonyManager;->getSimSerialNumber()Ljava/lang/String; : ['android.permission.READ_PHONE_STATE']
輸出的系統(tǒng)類女嘲、調(diào)用方法、需要的權限诞帐。
檢索某系統(tǒng)方法被調(diào)用的地方并打印
import os
import sys
# 引入androguard的路徑欣尼,根據(jù)個人存放的位置而定
androguard_module_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'androguard')
if not androguard_module_path in sys.path:
sys.path.append(androguard_module_path)
from androguard.misc import AnalyzeAPK
from androguard.core.androconf import load_api_specific_resource_module
path = r"/apk"
out_path = r"/out"
files = []
path_list = os.listdir(path)
path_list.sort()
for name in path_list:
if os.path.isfile(os.path.join(path, name)):
files.append(name)
def main():
for apkFile in files:
file_name = os.path.splitext(apkFile)[0]
print(apkFile)
out = AnalyzeAPK(path + '/' + apkFile)
a = out[0]
d = out[1]
dx = out[2]
for meth in dx.classes['Ljava/io/File;'].get_methods():
print("usage of method {}".format(meth.name))
# 拿到改函數(shù)的引用函數(shù)
for _, call, _ in meth.get_xref_from():
print(" called by -> {} -- {}".format(call.class_name, call.name))
if __name__ == '__main__':
main()
輸出結果
usage of method getPath
called by -> Landroid/support/v4/util/AtomicFile; -- <init>
usage of method <init>
called by -> Landroid/support/v4/util/AtomicFile; -- <init>
usage of method delete
called by -> Landroid/support/v4/util/AtomicFile; -- failWrite
called by -> Landroid/support/v4/util/AtomicFile; -- delete
called by -> Landroid/support/v4/util/AtomicFile; -- delete
called by -> Landroid/support/v4/util/AtomicFile; -- startWrite
called by -> Landroid/support/v4/util/AtomicFile; -- openRead
called by -> Landroid/support/v4/util/AtomicFile; -- finishWrite
usage of method renameTo
called by -> Landroid/support/v4/util/AtomicFile; -- openRead
called by -> Landroid/support/v4/util/AtomicFile; -- failWrite
called by -> Landroid/support/v4/util/AtomicFile; -- startWrite
usage of method exists
called by -> Landroid/support/v4/util/AtomicFile; -- startWrite
called by -> Landroid/support/v4/util/AtomicFile; -- openRead
called by -> Landroid/support/v4/util/AtomicFile; -- startWrite
usage of method getParentFile
called by -> Landroid/support/v4/util/AtomicFile; -- startWrite
usage of method mkdir
called by -> Landroid/support/v4/util/AtomicFile; -- startWrite
- ‘Ljava/io/File;’ 需要檢測的類
- meth.get_xref_from() 那該類中函數(shù)被引用的地方
- 你也可以自己搞個數(shù)組,配置好要檢查的相關函數(shù)停蕉,然后在上面代碼中加入if過濾即可
如果你想找Android系統(tǒng)定位愕鼓,被應用哪些方法調(diào)用,你就可以這樣做:
dx.classes['Landroid/location/LocationManager;']
再運行一遍腳本就可以看到結果了慧起。
結束
寫這篇博客菇晃,主要目的是為了讓更多人知道這個東西吧,我自己去搜索文章的時候發(fā)現(xiàn)并沒有多少可以參考的蚓挤,導致很多人無從下手磺送,但其實官方文檔也很詳細,但是英文的灿意,看起來也不方便估灿,也希望這篇簡短的文章給你提供幫助,如果有問題請再聯(lián)系我或留言評論