头图

Teach you how to efficiently check where sensitive permissions are used in the APK and where a system method is called

i校长
中文

Preface

I believe that the students who have recently put on the App in the App Store have felt that the domestic attaches more and more attention to user privacy, such as MAC address, device ID, IMEI information, etc., either simply don’t use it, or you must clearly tell users that they want to get For this information, related laws and regulations, please refer to the "Cyber Security Law" and "Notice on Carrying out Special Rectification Work for APP Infringement of User Rights and Interests"

Straight to the point

Not much nonsense, I found a few decompilation tools, and briefly looked at the usage method, and finally locked androguard, the official explanation: reverse engineering, malware and malware analysis of Android applications, it provides a series of Apk As well as the analysis and processing functions of dex, odex, arsc and other files, it can easily help us find the place to call system permissions. And the execution of the python script is simply not usable anymore

surroundings

  • python

    https://www.python.org
  • pycharm

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

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

    installation

    pip install -U androguard

    If you want to operate directly on the command line, please perform the following after installation:

    androguard analyze

    As shown in the figure after execution:
    CleanShot 2021-07-15 at 17.20.24@2x.png
    Then load the apk. After executing the above, enter the following:

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

    After the apk is loaded, you can call the relevant api to get the information

    Get permission

    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']

    Get 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']

    other

    # 包名
    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>

    Wait a minute, there are too many Apis, let's pay attention to the official documents, only you can't think of it, without it, the following link:

    https://androguard.readthedocs.io/en/latest/intro/gettingstarted.html#using-the-analysis-object

    More demo

https://github.com/androguard/androguard/tree/master/examples

Let's start the practice directly.

Retrieve places where sensitive permissions are used and output files

The following is the implementation of checking the use of sensitive permissions in the APK, please see:

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()

Output result

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']

The output system class, calling method, and required permissions.

Retrieve where a system method is called and print

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()

Output result

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;' Need to detect the class
  • meth.get_xref_from() where the function in this class is referenced
  • You can also make an array yourself, configure the related functions to be checked, and then add if filtering in the above code.
    If you want to find the Android system to locate and which methods are called by the application, you can do this:

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

    Run the script again to see the results.

    the end

    The main purpose of writing this blog is to let more people know about this. When I searched the article myself, I found that there was not much to refer to, which caused many people to be unable to start, but in fact, the official document is also very detailed, but it is in English. , It seems inconvenient, and I hope this short article will help you, if you have any questions, please contact me or leave a comment

    Welcome to follow the new website

  • http://jetpack.net.cn
阅读 2k

抽象化是一种非常的不同于模糊化的东西,抽象的目的并不是为了模糊,而是为了创造出一种能让我们做到百...

65 声望
296 粉丝
0 条评论

抽象化是一种非常的不同于模糊化的东西,抽象的目的并不是为了模糊,而是为了创造出一种能让我们做到百...

65 声望
296 粉丝
文章目录
宣传栏