教你如何高效的檢查APK中使用敏感權限的地方以及檢查某系統(tǒng)方法被調(diào)用的地方

前言

相信最近在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í)行后如圖:


CleanShot 2021-07-15 at 17.20.24@2x.png

然后再加載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)系我或留言評論

歡迎關注新網(wǎng)站

http://jetpack.net.cn

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末缤剧,一起剝皮案震驚了整個濱河市馅袁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌荒辕,老刑警劉巖司顿,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件芒粹,死亡現(xiàn)場離奇詭異,居然都是意外死亡大溜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門估脆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钦奋,“玉大人,你說我怎么就攤上這事疙赠「恫模” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵圃阳,是天一觀的道長厌衔。 經(jīng)常有香客問我,道長捍岳,這世上最難降的妖魔是什么富寿? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮锣夹,結果婚禮上页徐,老公的妹妹穿的比我還像新娘。我一直安慰自己银萍,他們只是感情好变勇,可當我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著贴唇,像睡著了一般搀绣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上戳气,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天巾遭,我揣著相機與錄音,去河邊找鬼锰蓬。 笑死旬昭,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的览闰。 我是一名探鬼主播芯肤,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼压鉴!你這毒婦竟也來了崖咨?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤油吭,失蹤者是張志新(化名)和其女友劉穎击蹲,沒想到半個月后署拟,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡歌豺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年推穷,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片类咧。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡馒铃,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出痕惋,到底是詐尸還是另有隱情区宇,我是刑警寧澤,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布值戳,位于F島的核電站议谷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏堕虹。R本人自食惡果不足惜卧晓,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鲫凶。 院中可真熱鬧禀崖,春花似錦、人聲如沸螟炫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽昼钻。三九已至掸屡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間然评,已是汗流浹背仅财。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留碗淌,地道東北人盏求。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像亿眠,于是被迫代替她去往敵國和親碎罚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容