Android静态权限静态分析工具

前言

相信最近在App上架应用商店的同学都感受到了,国内对用户的隐私越来越重视,如MAC地址,设备ID,IMEI信息等,要么就干脆不用,要么就必须很明显的告诉用户想要获取这些信息,相关法律及规定,参考《网络安全法》及《关于开展APP侵害用户权益专项整治工作的通知》
开门见山

废话不多说,找了几个反编译工具,并简单看了下使用方法,最终锁定androguard,官方解释:对Android应用程序的逆向工程、恶意软件和恶意软件分析,它提供了一系列的Apk以及dex、odex、arsc等文件的分析处理功能,可以轻松的帮助我们找到调用系统权限的地方。且python脚本执行,简直不能再好用了
环境

python

https://www.python.org

pycharm

https://www.jetbrains.com/pycharm/download/

androguard

https://androguard.readthedocs.io/en/latest/

安装

pip install -U androguard

如果想在命令行直接操作,请在安装完后执行如下:

androguard analyze

执行后如图:
CleanShot 2021-07-15 at 17.20.24@2x.png

然后再加载apk,在上面执行后,输入如下:

a, d, dx = AnalyzeAPK("examples/android/abcore/app-prod-debug.apk")

apk加载完成后就可以调用相关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中使用敏感权限的实现,请看:

import os
import sys
 
# 引入androguard的路径,根据个人存放的位置而定
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 数组,一个元素其实对应的是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():
                # 匹配系统权限方法,匹配上就输出到文件中
                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']

输出的系统类、调用方法、需要的权限。
检索某系统方法被调用的地方并打印

import os
import sys
 
# 引入androguard的路径,根据个人存放的位置而定
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))
            # 拿到改函数的引用函数
            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() 那该类中函数被引用的地方
你也可以自己搞个数组,配置好要检查的相关函数,然后在上面代码中加入if过滤即可
如果你想找Android系统定位,被应用哪些方法调用,你就可以这样做:

dx.classes['Landroid/location/LocationManager;']

再运行一遍脚本就可以看到结果了。
————————————————
版权声明:本文为CSDN博主「i校长」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_46622598/article/details/118854019

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容