androguard是一款非常棒的开源Android APK静态分析工具;使用Python开发;androguard只能在Linux环境运行,因为它使用的几个python库仅支持Linux平台。并且由于复杂的库依赖,在Linux环境的安装也较困难;好消息是santoku已经集成了它,不用我们再折腾,androguard安装在santoku的/usr/share/androguard目录;下面分析其主要功能,并开发一些额外的实用功能;
相关链接:
https://github.com/androguard/androguard/
https://santoku-linux.com/
1.androapkinfo.py
用来查看apk文件信息,该工具输出apk文件的包、资源、权限、组件、方法等信息。使用方法:
./androapkinfo.py -i ./demo.apk
2.androxml.py
用来解密apk包中的AndroidManifest.xml文件。使用方法:
./androxml.py -i ./demo.apk
3.androcsign.py
用于添加apk文件的签名信息到一个数据库文件,其所有目录为signatures/dbandroguard。使用前首先要为apk编写一个sign文件,这个文件使用json格式保存。、
[
{
"SAMPLE":"apks/demo.apk"
},
{
"BASE":"AndroidOS",
"NAME":"DroidDeram",
"SIGNATURE":[
{
"TYPE":"METHSIM",
"CN":"Lcom/droider/demo/MainActivity$SNChecker;",
"MN":"isRegistered",
"D":"()Z"
}
],
"BF":"0"
}
]使用方法:
./androcsign.py -i signatures/demo.sign -o signatures/dbandroguard
4.androdd.py
用于生成apk文件中,每个类的方法的调用流程图。使用方法:
./androdd.py -i ./demo.apk -o ./out -d -d PNG
5.androdiff.py
比较两个apk文件的差异。使用方法:
./androdiff.py -i ./demo.apk ./demo2.apk
6.androdump.py
用于dump一个linux进程的信息。使用方法:
./androdump.py -i pid
7.androgexf.py
用于生成apk的gexf格式的图形文件,该文件可以使用Gephi软件查看。使用方法:
./androgexf.py -i ./demo.apk -o ./demo.gexf
8.androlyze.py
交互式的Android静态分析程序,功能特别多。具体可以参考coreanalysis和corebytecodes下的代码。以及Xbalien的相关使用介绍。
9.andromercury.py
andromercury.py是Mercury工具的框架。功能上是对Mercury的包装。内网实验室的社区网站上有8篇2013年发的Mercury的使用介绍,已经使用,功能比较丰富。
10.androrisk.py
用于评估apk的潜在风险,最后会得出一个分。ICSL_androguard中使用了这个模块的分析结果。
11.androsign.py
用于检测apk的签名信息是否在数据库里,与androcsign.py功能恰好相反。
12.androsim.py
用于计算两个apk文件的相似度。是个开源的库。网上相关资料比较少,在androguard老的google source code网站wiki里面有介绍。
13.androxgmml.py
用于生成apk/jar/class/dex等文件的控制流程及功能调用图,生成格式为xgmml。使用方法:
./androxgmml.py -i ./demo.apk -o ./demo.xgmml
14.apkviewer.py
为apk文件中每个类生成一个独立的graphhml文件,可以使用Gephi查看。使用方法:
./apkviewer.py -i ./demo.apk -o ./output
我们接下来将开发或适配下列功能:
组件Activities,Services,Content Providers、Broadcast Receivers
Permissions 及对应使用代码
敏感 APIs 监控
URL、IP、口令、加解密算法等信息监控
检查动态注册的 Receivers
检测 AllowBackup、Debuggable、ShareUserId、用户自定义权限
risk 评分
下面记录一些关键代码实现:
一、敏感 API 调用
def show_Sensitive_APIs(dx): for i in Sensitive_APIs: print " ",i,Sensitive_APIs[i][0],Sensitive_APIs[i][1] paths = dx.get_tainted_packages().search_methods( Sensitive_APIs[i][0],Sensitive_APIs[i][1],".") show_Paths(dx.get_vm(), paths ) Sensitive_APIs = { #log #0 : [ "Landroid/util/Log;","d"], #send sms 1: ["Landroid/telephony/SmsManager;","sendTextMessage"], #read sms 2: [".","getDisplayMessageBody"], 3: [".","getMessageBody"], #IMEI 4: ["Landroid/telephony/TelephonyManager;","getDecicedID"], #phone number 5: ["Landroid/telephony/TelephonyManager;","getLine1Number"], #get Sim serial 6: ["Landroid/telephony/TelephonyManager;","getSimSerialNumber"], #Location 7: ["Landroid/telephony/TelephonyManager;","getCellLocation"], #GPS 8: [".","getLastKnownLocation"], 9: [".","requestLocationUpdates"], #Recorder 10: ["Landroid/media/MediaRecorder;","prepare"], #native_code 11: ["Ljava/lang/Runtime;","exec"], 12: ["Ljava/lang/Runtime;","load"], 13: ["Ljava/lang/System;","load"], #file io 14: ["Llibcore/io/IoBridge;", "open"], 15: ["Llibcore/io/IoBridge;", "read"], 16: ["Llibcore/io/IoBridge;", "write"], 17: ["Ljava/io/File;", "create"], 18: ["Ljava/io/File;", "delete"], 19: ["Ljava/io/File;", "get"], 20: ["Ljava/io/File;", "mk"], 21: ["Ljava/io/File;", "set"], #get resource 22: [".","openRawResource"], 23: [".","getAssets"], #http 24: ["Lorg/apache/http/impl/client/AbstractHttpClient;", "execute"], 25: ["Ljava/net/HttpURLConnection;","connect"], 26: ["Ljava/net/URL;","openConnection"], 27: ["Ljava/net/URLConnection;","connect"], 28: ["Ljava/net/Socket;","."], #ssl 29: ["Ljavax/net/ssl;","."], #WebView 30: ["Landroid/webkit/WebView;","addJavascriptInterface"], 31: ["Landroid/webkit/WebView;","searchBoxJavaBridge_"], #load jar 32: ["Ldalvik/system/DexClassLoader;","."], 33: ["Ljava/net/URLClassLoader;","."], 34: ["Ldalvik/system/PathClassLoader;","."], #ReflectionCode 35: ["Ljava/lang/reflect/Method;", "."], #encrypt or SHA 36: [".", "doFinal"], 37: [".","digest"], #use camera 38: ["Landroid/hardware/Camera;","open"], #query SQL(read contact\SMS) 39: ["Landroid/content/ContentResolver;","query"], #SharedPreferences 40: ["Landroid/content/SharedPreferences;","edit" ], #sendBroadcast 41: [".","sendBroadcast"], 42: [".","sendOrderedBroadcast"], 43: [".","sendStickyBroadcast"], 44: [".","sendStickyOrderedBroadcast"], #start activity 45: [".","startActivity"], 46: [".","startActivityForResult"], #Service 47: [".","startService"], 48: [".","bindService"], #write to SD card 49: [".","getExternalStorageDirectory"], #input check 50: [".","readLine"] }
二、关键字匹配
vm = dvm.DalvikVMFormat(apk.get_dex()) #dex转DalvikVMFormat vmx = analysis.uVMAnalysis(vm) vm.get_regex_strings("(?i)password") #Key Words vm.get_regex_strings("AES") vm.get_regex_strings("^((https?|ftp)://[^\s/$.?#].[^\s]*)$") #urls vm.get_regex_strings("[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+") #ip
三、动态加载的Receivers
#Dynamically Registered Receiver def show_Register_receiver(dx): paths = dx.get_tainted_packages().search_methods(".","registerReceiver",".") show_Paths(dx.get_vm(), paths )
四、SharedUserId、AllowBackup、Debuggable等
self.sharedUserId = self.xml[i].documentElement.getAttribute("android:sharedUserId") for item in self.xml[i].getElementsByTagName('application'): self.allowbackup.append(str(item.getAttributeNS(NS_ANDROID_URI, "allowBackup")))
五、计算风险评分
ri = risk.RiskIndicator() ri.add_risk_analysis( risk.RedFlags() ) ri.add_risk_analysis( risk.FuzzyRisk() ) analyze_app( options.input, ri, a ) def display_result(res) : for i in res : print "\t", i for j in res[i] : print "\t\t", j, res[i][j] def analyze_app(filename, ri, a) : display_result( ri.with_apk( a ) )
六、扫描结果示例
[Activities]
com.achievo.vipshop.activity.LodingActivity
com.tencent.tauth.AuthActivity
[Services]
com.achievo.vipshop.manage.service.SplashAlarmService
com.vipshop.sdk.push.MqttService
[Content Providers][Broadcast Receivers]
com.vipshop.sdk.viplog.batch.VipLogReceiver
com.vipshop.sdk.push.VipsPushReceiver
[Permissions]
USE_CREDENTIALS :
1 Lcom/androidquery/auth/GoogleHandle;->reauth(Lcom/androidquery/callback/AbstractAjaxCallback;)Z (0x12) ---> Landroid/accounts/AccountManager;->invalidateAuthToken(Ljava/lang/String; Ljava/lang/String;)V
READ_PHONE_STATE :
[Sensitive APIs]
30 Landroid/webkit/WebView; addJavascriptInterface
1 Lbolts/WebViewAppLinkResolver$2;->then(Lbolts/Task;)Lbolts/Task; (0x56) ---> Landroid/webkit/WebView;->addJavascriptInterface(Ljava/lang/Object; Ljava/lang/String;)V
[Dynamically registered receivers]
1 Lcom/achievo/vipshop/newactivity/CartFloatView;->registerFavoriteRecever()V (0x3e) ---> Landroid/content/Context;->registerReceiver(Landroid/content/BroadcastReceiver; Landroid/content/IntentFilter;)Landroid/content/Intent;
[SharedUserId|AllowBackup|Debuggable]
SharedUserId:[]
AllowBackup:[false]
Debuggable[false]
[key words]['PWDCHARS_ARRAY', 'PWDCHARS_STRING', 'pwd', 'pwdWatcher']
['UserName', 'userName', 'username', 'username=', 'username_del']
['secretKey']
['ENCRYPTION', 'ENCRYPTION_AES', 'ENCRYPT_ACTION', 'encrypt', 'encryption error. ']
['imei', 'imei=']
['imsi']
['AES', 'AES/CBC/PKCS5Padding', 'AES/ECB/PKCS7Padding', 'AESUtils', 'AESUtils.java']
['SHA-1']
[]
[]
['MD5', 'MD5.java', 'MD5PatchVerifier.java', 'MD5Util.java', 'MD5_INSTANCE', 'MD5_SALT']
['RSA', 'RSA/ECB/PKCS1Padding', 'RSA_PKCS_V15', 'RSA_PKCS_V21', 'RSA_PRIVATE', 'RSA_PUBLIC'][urls]
ftp://anonymous:anonymous@
http://%1$s/diagnoses/v1/report
http://%1$s/gslb/gslb/getbucket.asp?ver=3.0
http://10.237.12.17:9085/pass/register
http://400.vip.com/WebChat/chat/wapchat.jsp?
http://800.vip.com/live800/chatClient/chatbox.jsp?companyID=8900&configID=17&enterurl=APP&pagereferrer=APP&syslanguage=0
http://a.appsimg.com
http://a.appsimg.com/upload/brand/
http://a.appsimg.com/upload/merchandise/
http://ap.vip.com/coupons_rules
http://ap.vip.com/fwxy1015
http://ap.vip.com/index.php?m=activity&code=coupon_help2&wapid=ap_2342
http://ap.vip.com/index.php?m=activity&code=global_rule&wapid=ap_1881
[ip]
1.1.3.61
1.2.2.56
1.3.4.60
10.0.0.172
10.0.0.200
10.237.12.17
10.237.12.2
2.3.3.61
2.4.0.61
223.202.68.46
42.62.48.181
58.68.235.106
58.68.235.232[risk score]
RedFlags
DEX {'NATIVE': 1, 'DYNAMIC': 1, 'CRYPTO': 1, 'REFLECTION': 1}
APK {'DEX': 0, 'EXECUTABLE': 0, 'ZIP': 0, 'SHELL_SCRIPT': 0, 'APK': 0, 'SHARED LIBRARIES': 87}
PERM {'PRIVACY': 6, 'NORMAL': 9, 'MONEY': 0, 'INTERNET': 1, 'SMS': 2, 'DANGEROUS': 13, 'SIGNATUREORSYSTEM': 1, 'CALL': 0, 'SIGNATURE': 0, 'GPS': 2}
FuzzyRisk
VALUE 80.0
定制androguard可用于大批量APK分析工作;通过迅速给出攻击面信息,辅助人工分析;但在进行加固APK分析时先天不足,需使用DroidBox、Xposed、adbi、Dozer等动态分析工具或手段来补齐短板;