1. 引入
有些APK运行后,会收集你的手机号。有收集手机号这种行为的APP,就有可能把你的手机号泄露出去。
那么,如何用一段python代码,来检测APK是否有这种收集手机号的行为呢?
2. 原理
从参考1中,我们可以知道,只要你写APP时,满足如下两个条件,就会让你的APP有收集本机手机号的行为。
- 在manifest中添加如下权限
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
- 在java中通过
TelephonyManager
调用了getLine1Number()
这个API
TelephonyManager tMgr = (TelephonyManager)mAppContext.getSystemService(Context.TELEPHONY_SERVICE);
String mPhoneNumber = tMgr.getLine1Number();
所以,给你一个APK,我们只要将APK逆向后,找到上面两个条件,就说明APK中有这样的行为。
3. 实现
- 用Androguard来对APK进行逆向
import os,sys,time,datetime,traceback
from androguard.core.bytecodes import apk
from androguard.core.bytecodes import dvm
from androguard.core.analysis import analysis
class StaticAnalysis(object):
def __init__(self, apkfile):
self.apkfile = apkfile
self.a = None#apk obj
self.d = None#dex obj
self.x = None#analysis result obj
def get_androguard_obj(self):
try:
self.a = apk.APK(self.apkfile, False, "r", None, 2)# get apk obj
self.d = dvm.DalvikVMFormat(self.a.get_dex())# get dex obj
self.x = analysis.Analysis(self.d)# get analysis result obj
except Exception as e:
msg = traceback.format_exc()
print(msg)
导入所需的Androguar的库,然后获取APK的三个对象:apk, dex, analysis result.
详细用法请查看参考中的2。
- 查找APK中是否使用了名字为
getLine1Number
的method
这个method的smali写法为Landroid/telephony/TelephonyManager;->getLine1Number()Ljava/lang/String;
从smali代码上,可以看出
(1)这个method所属的class为Landroid/telephony/TelephonyManager
(2)这个method没有输入参数
(3)这个method的返回值类型为String
所以,我们需要遍历APK中各个class中的method,并匹配method的名字是否为上述给定的内容。具体代码如下
sa = StaticAnalysis('app-debug.apk')
sa.get_androguard_obj()
class_list = sa.d.get_classes()# get all classes
print('class num:{0}'.format(len(class_list)))
for class_item in class_list:
class_name = class_item.name
methods = class_item.get_methods()# get all methods
for m in methods:
raw_code_list = [x for x in m.code.code.get_instructions()]
for line in raw_code_list:# loop all method
if 'getLine1Number' in line.get_output():# match method name
print(line.get_output())# get method head of smali code
print('class-name={0}'.format(class_name))
print('method-name={0} {1}'.format(m.name,m.get_descriptor()))
- 查找APK中是否使用了
android.permission.READ_PHONE_STATE
权限
通过APK对象,获取所有权限列表,然后依次匹配,具体代码如下:
sa = StaticAnalysis('app-debug.apk')
sa.get_androguard_obj()# get 3 objects
permission_list = sa.a.get_permissions() # get all permission list
for p in permission_list:
if 'android.permission.READ_PHONE_STATE' in p:# match
print(p)
4. 总结
本文使用Androguard来检测API与权限,从而检测APK是否有具有“收集手机号”的行为,并给出二零核心代码。完整的代码请看参考3。这种方法可以对很多APK进行批量检测。
参考
-
- https://stackoverflow.com/questions/2480288/programmatically-obtain-the-phone-number-of-the-android-phone
-
- https://blog.csdn.net/ybdesire/article/details/52629142
-
- https://github.com/ybdesire/apk_static_behavior_detector