├── .gitignore ├── LICENSE ├── LiteRadar ├── Data │ ├── logging.conf │ ├── strict_api.csv │ └── tag_rules.csv ├── __init__.py ├── _settings.py ├── dex_parser.py ├── litedextree.py └── literadar.py ├── README.md └── docs └── QuickStart.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | env/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | wheels/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | .hypothesis/ 50 | 51 | # Translations 52 | *.mo 53 | *.pot 54 | 55 | # Django stuff: 56 | *.log 57 | local_settings.py 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # dotenv 85 | .env 86 | 87 | # virtualenv 88 | .venv 89 | venv/ 90 | ENV/ 91 | 92 | # Spyder project settings 93 | .spyderproject 94 | .spyproject 95 | 96 | # Rope project settings 97 | .ropeproject 98 | 99 | # mkdocs documentation 100 | /site 101 | 102 | # mypy 103 | .mypy_cache/ 104 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {2017} {Ma Ziang} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LiteRadar/Data/logging.conf: -------------------------------------------------------------------------------- 1 | #logger.conf 2 | ######## 3 | [loggers] 4 | keys=root,radar,info 5 | 6 | [logger_root] 7 | level=DEBUG 8 | handlers=hand01,hand02 9 | 10 | [logger_radar] 11 | level=DEBUG 12 | handlers=hand01,hand02 13 | qualname=libradar 14 | propagate=0 15 | 16 | [logger_info] 17 | level=INFO 18 | handlers=hand02 19 | propagate=0 20 | qualname=libradar_info 21 | 22 | ######## 23 | [handlers] 24 | keys=hand01,hand02 25 | [handler_hand01] 26 | class=StreamHandler 27 | level=INFO 28 | formatter=form02 29 | args=(sys.stderr,) 30 | [handler_hand02] 31 | class=FileHandler 32 | level=DEBUG 33 | formatter=form01 34 | args=('log_libradar.txt', 'a') 35 | 36 | ######## 37 | [formatters] 38 | keys=form01,form02 39 | [formatter_form01] 40 | format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s 41 | datefmt=%a, %d %b %Y %H:%M:%S 42 | [formatter_form02] 43 | format=%(asctime)s: %(levelname)-8s %(message)s 44 | datefmt= -------------------------------------------------------------------------------- /LiteRadar/Data/tag_rules.csv: -------------------------------------------------------------------------------- 1 | Package Name,Library Name,Type,Official Website 2 | La,no,, 3 | La/a,no,, 4 | La/a/a,no,, 5 | La/a/a/a,no,, 6 | La/a/a/a/a,no,, 7 | La/a/a/a/a/a,no,, 8 | La/a/a/a/a/b,no,, 9 | Lafzkl,no,, 10 | Lafzkl/development,no,, 11 | Lafzkl/development/mColorPicker,Penroser,Development Aid,https://github.com/JesusFreke/Penroser 12 | Lair,no,, 13 | Lair/com,no,, 14 | Landroid,no,, 15 | Landroid/content,no,, 16 | Landroid/content/pm,Android Package management,Development Aid,https://developer.android.com/reference/android/content/pm/package-summary.html 17 | Landroid/opengl,OpenGL,Development Aid,http://developer.android.com/reference/android/opengl/package-summary.html 18 | Landroid/support,no,, 19 | Landroid/support/a,no,, 20 | Landroid/support/a/a,no,, 21 | Landroid/support/design,Android Support Design,Development Aid,https://developer.android.com/reference/android/support/design/package-summary.html 22 | Landroid/support/multidex,Multidex,Development Aid,https://developer.android.com/studio/build/multidex.html 23 | Landroid/support/v13,Android Support v13,Development Aid,https://developer.android.com/reference/android/support/v13/app/package-summary.html 24 | Landroid/support/v4,Android Support v4,Development Aid,http://developer.android.com/reference/android/support/v4/app/package-summary.html 25 | Landroid/support/v7,Android Support v7,Development Aid,https://developer.android.com/reference/android/support/v7/app/package-summary.html 26 | Landroid/widget,android widget,GUI Component, 27 | Lanet,no,, 28 | Lanet/channel,Umeng push,Development Aid,http://mobile.umeng.com/push 29 | Lanetwork,no,, 30 | Lanetwork/channel,no,, 31 | Lanetwork/channel/aidl,AIDL,Development Aid,https://developer.android.com/guide/components/aidl.html 32 | Lanywheresoftware,anywheresoftware,Development Aid, 33 | Lappinventor,Appinventor,Development Aid,http://appinventor.mit.edu/ 34 | Lappmachine,AppMachine App Generator,Development Aid,http://www.appmachine.com/ 35 | Lau/com/bytecode/opencsv,Opencsv,Development Aid,https://github.com/EmergentOrder/opencsv 36 | Laurelienribon,AurelienRibon Animation Library,Development Aid,http://www.aurelienribon.com 37 | Lb/a,no,, 38 | Lb/a/a,no,, 39 | Lb/a/a/a,no,, 40 | Lb/a/a/a/a,no,, 41 | Lb/a/a/a/a/b,no,, 42 | Lbiz,no,, 43 | Lbiz/neoline,Neoline,Development Aid,http://www.neoline.biz/ 44 | Lbolts,Bolts Base Library,Development Aid,https://github.com/BoltsFramework/Bolts-Android 45 | Lbutterknife,butterknife UI Framework,GUI Component,https://github.com/JakeWharton/butterknife 46 | Lc,no,, 47 | Lc/a,no,, 48 | Lc/a/a,no,, 49 | Lc/a/a/a,no,, 50 | Lc/a/a/a/a,no,, 51 | Lc/a/a/a/a/a,no,, 52 | Lc/a/a/a/a/b,no,, 53 | Lc/a/a/a/a/c,no,, 54 | Lc/a/a/a/a/e,no,, 55 | Lc/a/a/a/a/g,no,, 56 | Lc/b,no,, 57 | Lc/b/a,no,, 58 | Lc/m,no,, 59 | Lc/m/x,no,, 60 | Lc/m/x/a,no,, 61 | Lc/m/x/a/am48,no,, 62 | Lch/boye/httpclientandroidlib,httpclientandroidlib,Development Aid,https://github.com/surespot/httpclientandroidlib 63 | Lch/qos/logback,Logback,Development Aid,http://logback.qos.ch/ 64 | Lcn,no,, 65 | Lcn/domob,domob,Advertisement,http://www.domob.cn/ 66 | Lcn/jiguang,Jiguang,Development Aid,https://www.jiguang.cn/ 67 | Lcn/jiguang/a,no,, 68 | Lcn/jiguang/a/a,no,, 69 | Lcn/jpush,no,, 70 | Lcn/jpush/android,Jpush,Development Aid,https://www.jiguang.cn/ 71 | Lcn/sharesdk,no,, 72 | Lcn/sharesdk/evernote,Mob Share Evernote,Social Network,http://mob.com 73 | Lcn/sharesdk/framework,ShareSDK,Social Network,http://www.mob.com/downloadDetail/ShareSDK/android 74 | Lcn/sharesdk/onekeyshare,Mob one key share,Social Network,http://mob.com/ 75 | Lcn/sharesdk/socialization,mob social,Social Network,mob.com 76 | Lcn/sharesdk/tencent,Mob share to tencent,Social Network,http://wiki.mob.com/%E5%88%86%E4%BA%AB%E5%88%B0%E6%8C%87%E5%AE%9A%E5%B9%B3%E5%8F%B0/ 77 | Lcn/smssdk,Mob SMS SDK,Development Aid,http://wiki.mob.com/android-%E7%9F%AD%E4%BF%A1sdk%E9%9B%86%E6%88%90%E6%96%87%E6%A1%A3/ 78 | Lcn/uc,no,, 79 | Lcn/uc/a,no,, 80 | Lcn/uc/a/a,no,, 81 | Lcn/uc/a/a/a,no,, 82 | Lcn/uc/gamesdk,UC GAME,Game Engine,https://game.open.uc.cn/document/doc/detail/95 83 | Lco,no,, 84 | Lcom,no,, 85 | Lcom/a,no,, 86 | Lcom/a/a,no,, 87 | Lcom/a/a/a,no,, 88 | Lcom/a/c/a,no,, 89 | Lcom/ace,no,, 90 | Lcom/ace/universalimageloader,Universal Image Loader,Development Aid,https://github.com/nostra13/Android-Universal-Image-Loader 91 | Lcom/actionbarsherlock,ActionBarSherlock,Development Aid,http://actionbarsherlock.com/ 92 | Lcom/activeandroid,ActiveAndroid,Development Aid,https://github.com/pardom/ActiveAndroid 93 | Lcom/adfonic,Adfonic Mobile Ads,Advertisement,http://www.adfonic.com 94 | Lcom/adjust,no,, 95 | Lcom/adjust/sdk,adjust,Mobile Analytics,https://www.adjust.com/ 96 | Lcom/admob,Google Admob,Advertisement,https://www.google.com/admob/ 97 | Lcom/adobe,no,, 98 | Lcom/adobe/air,Adobe Air,Development Aid,http://www.adobe.com/cn/devnet/air/air_for_android.html 99 | Lcom/adobe/flashplayer,Adobe FlashPlayer,Development Aid, 100 | Lcom/adobe/flashruntime,Adobe FlashPlayer,Development Aid, 101 | Lcom/adobe/fre,Adobe Air FRE,Development Aid,http://www.adobe.com/cn/devnet/air/air_for_android.html 102 | Lcom/adobe/plugin,Adobe plugin,Development Aid, 103 | Lcom/adobe/xmp,Adobe XMP,Development Aid,http://www.adobe.com/products/xmp.html 104 | Lcom/adsdk,AdSDK,Advertisement, 105 | Lcom/adsmogo,adsmogo,Advertisement,http://www.adsmogo.com/ 106 | Lcom/adtech,Adtech,Advertisement,http://www.adtech.com/ 107 | Lcom/adwhirl,Adwhirl Ads,Advertisement,https://code.google.com/p/adwhirl/ 108 | Lcom/adwo,no,, 109 | Lcom/adwo/adsdk,adwo,Advertisement,http://www.adwo.com/ 110 | Lcom/alibaba,no,, 111 | Lcom/alibaba/fastjson,Fastjson,Development Aid,https://github.com/alibaba/fastjson 112 | Lcom/alibaba/mtl,Alibaba MTL,Development Aid,https://doc.open.alipay.com/doc2/detail.htm?treeId=195&articleId=105220&docType=1 113 | Lcom/alimama,no,, 114 | Lcom/alimama/mobile,Alimama Dev,Social Network,http://dev.alimama.com/ 115 | Lcom/alipay,Alipay,Payment,https://dev.alipay.com/ 116 | Lcom/aliyun,Aliyun,Development Aid, 117 | Lcom/amap,Alibaba Amap,Map/LBS,https://lbs.amap.com/ 118 | Lcom/amazon,no,, 119 | Lcom/amazon/ags,Amazon Game Studios,Game Engine,https://games.amazon.com/ 120 | Lcom/amazon/device,no,, 121 | Lcom/amazon/device/ads,Amazon Advertisement,Advertisement,https://developer.amazon.com/public/apis/earn/mobile-ads/docs/quick-start 122 | Lcom/amazon/device/associates,Amazon Mobile Associates,Advertisement,https://developer.amazon.com/mobile-associates 123 | Lcom/amazon/device/iap,Amazon In-App Purchasing,Payment,https://developer.amazon.com/public/apis/earn/in-app-purchasing 124 | Lcom/amazon/identity,no,, 125 | Lcom/amazon/identity/auth,Amazon Auth SDK,Development Aid,https://developer.amazon.com/public/apis/engage/login-with-amazon/docs/use_sdk_android.html 126 | Lcom/amazon/inapp,Amazon In-App Purchasing,Payment,https://developer.amazon.com/in-app-purchasing 127 | Lcom/amazon/insights,Amazon Analytics,Mobile Analytics,https://developer.amazon.com/public/apis/manage/analytics/docs/analytics-for-android-fire-os 128 | Lcom/amazonaws,Amazon AWS,Development Aid,http://mvnrepository.com/artifact/com.amazonaws 129 | Lcom/android,no,, 130 | Lcom/android/vending,Google Play,App Market,https://play.google.com 131 | Lcom/android/volley,Volley HTTP library,Development Aid,https://developer.android.com/training/volley/index.html 132 | Lcom/androidplot,Androidplot,Development Aid,http://androidplot.com/ 133 | Lcom/androidquery,AndroidQuery,Development Aid,https://github.com/androidquery/androidquery/ 134 | Lcom/ansca/corona,Corona,Development Aid,https://docs.coronalabs.com/native/android/html/com/ansca/corona/package-summary.html 135 | Lcom/anzhi,no,, 136 | Lcom/anzhi/market,Anzhi Market,App Market,http://www.anzhi.com/ 137 | Lcom/appbrain,Appbrain SDK,Development Aid,https://www.appbrain.com/info/help/sdk/index.html 138 | Lcom/appbyme,Appbyme,Development Framework,http://www.appbyme.com/ 139 | Lcom/apperhand,apperhand,Advertisement, 140 | Lcom/appflood,Appflood,Advertisement,http://appflood.com 141 | Lcom/applovin,Applovin,Advertisement,https://www.applovin.com/ 142 | Lcom/appmakr,Appmakr,Development Aid,https://www.appmakr.com/ 143 | Lcom/appodeal,no,, 144 | Lcom/appodeal/ads,Appodeal Ads,Advertisement,https://www.appodeal.com 145 | Lcom/appquanta,Quanta Sky Ino.,Mobile Analytics,http://www.appquanta.com/ 146 | Lcom/appquanta/,Qunta Sky Ino.,Mobile Analytics,http://www.appquanta.com/index.html 147 | Lcom/appsflyer,AppsFlyer,Mobile Analytics,https://www.appsflyer.com/ 148 | Lcom/appyet,Appyet,Development Aid,http://www.appyet.com/ 149 | Lcom/aps,no,, 150 | Lcom/astuetz,Astuetz Pager Sliding Tab Strip,GUI Component,https://github.com/astuetz 151 | Lcom/auth0/android,Auth0 Android SDK,Utility,https://auth0.com/docs/quickstart/native/android/getting-started 152 | Lcom/auth0/jwt,Java implementation of JSON Web Token (JWT),Development Aid,https://github.com/auth0/java-jwt 153 | Lcom/autonavi,no,, 154 | Lcom/autonavi/aps,no,, 155 | Lcom/autonavi/aps/amapapi,AMAP autonavi API,Map/LBS,https://lbs.amap.com/ 156 | Lcom/aviary,Aviary photo editing SDK,Development Aid,https://developers.aviary.com/docs/android 157 | Lcom/avos/avoscloud,,Development Aid, 158 | Lcom/avos/avoscloud/okhttp,Okhttp,Development Aid, 159 | Lcom/b,no,, 160 | Lcom/b/a/a,no,, 161 | Lcom/b/a/a/a,no,, 162 | Lcom/badlogic,badlogic,Game Engine,http://www.badlogicgames.com/ 163 | Lcom/baidu,no,, 164 | Lcom/baidu/android,Baidu APP SDK,Development Aid,https://developer.baidu.com/ 165 | Lcom/baidu/android/pushservice,baidu push service,Development Aid,https://developer.baidu.com/ 166 | Lcom/baidu/appx,Baidu APPX,Advertisement,https://app.baidu.com/ 167 | Lcom/baidu/autoupdatesdk,baidu autoupdate sdk,Development Aid, 168 | Lcom/baidu/bdgame,no,, 169 | Lcom/baidu/bdgame/sdk,baidu game,Social Network,http://mgame.baidu.com/ 170 | Lcom/baidu/cyberplayer,Baiduyun Android Player,Development Aid,https://cloud.baidu.com/doc/MCT/Android-SDK.html 171 | Lcom/baidu/frontia,Baidu Frontia,Development Aid, 172 | Lcom/baidu/location,Baidu Location,Map/LBS,https://developer.baidu.com/ 173 | Lcom/baidu/mapapi,Baidu Map,Map/LBS,http://lbsyun.baidu.com/ 174 | Lcom/baidu/mapapi/,Baidu Map,Map/LBS,http://lbsyun.baidu.com/ 175 | Lcom/baidu/mobads,Baidu Mobile Ads,Advertisement,https://developer.baidu.com/ 176 | Lcom/baidu/mobstat,Baidu Mobile Stat,Mobile Analytics,https://developer.baidu.com/ 177 | Lcom/baidu/mtjstatsdk,baidu Stat Android SDK API.,Development Aid,https://mtj.baidu.com/ 178 | Lcom/baidu/navi,Baidu Navigation,Map/LBS,http://lbsyun.baidu.com/index.php?title=android-navsdk 179 | Lcom/baidu/navisdk,Baidu Navigation SDK,Map/LBS,http://lbsyun.baidu.com/index.php?title=android-navsdk 180 | Lcom/baidu/paysdk,Baidu Wallet,Payment,https://www.baifubao.com/ 181 | Lcom/baidu/platform,Baidu APP SDK,Development Aid,https://developer.baidu.com/ 182 | Lcom/baidu/sapi2,Baidu SAPI2,Development Aid, 183 | Lcom/baidu/searchsdk,Baidu Search SDK,Development Aid,https://developer.baidu.com/ 184 | Lcom/baidu/tiebasdk,Baidu Tieba SDK,Social Network,http://tieba.baidu.com/tb/zt/tiebaapi/index.html 185 | Lcom/baidu/wallet,Baidu Wallet(baifubao),Payment,https://www.baifubao.com/ 186 | Lcom/batch,batch,Mobile Analytics,https://batch.com/doc/ 187 | Lcom/bda,no,, 188 | Lcom/bda/controller,MOGAanywhere,Game Engine,http://www.mogaanywhere.com/ 189 | Lcom/bea/xml/stream,StAX API,Development Aid,https://jcp.org/en/jsr/detail?id=173 190 | Lcom/biznessapps,biznessapps,Development Aid,https://www.biznessapps.com/ 191 | Lcom/bugsense,BugSense,Development Aid,https://github.com/wrapp/bugsense-android 192 | Lcom/bump,Bump pay,Payment, 193 | Lcom/bumptech,no,, 194 | Lcom/bumptech/glide,Glide,Development Aid,https://github.com/bumptech/glide/ 195 | Lcom/c,no,, 196 | Lcom/c/a,no,, 197 | Lcom/c/a/a,no,, 198 | Lcom/c/a/a/a,no,, 199 | Lcom/c/a/a/a/a,no,, 200 | Lcom/c/a/a/a/a/a,no,, 201 | Lcom/c/a/b/a,no,, 202 | Lcom/c/a/b/a/a,no,, 203 | Lcom/c/a/b/d,no,, 204 | Lcom/c/a/c,no,, 205 | Lcom/cOoNkCqXw,no,, 206 | Lcom/cOoNkCqXw/anhYjsorr71313,no,, 207 | Lcom/chartboost,no,, 208 | Lcom/chartboost/sdk,ChartBoost,Advertisement,http://www.chartboost.com/ 209 | Lcom/chineseall/reader,chineseall reader,Development Aid, 210 | Lcom/commonsware/cwac/merge,CommonsWare MergeAdapter,Development Aid,https://github.com/commonsguy/cwac-merge 211 | Lcom/commonsware/cwac/sacklist,CommonsWare SackOfViewsAdapter,Development Aid,https://github.com/commonsguy/cwac-sacklist 212 | Lcom/comscore,comscore,Mobile Analytics,https://www.comscore.com/ 213 | Lcom/conduit/app,Conduit App,Development Aid,http://apps.conduit.com/ 214 | Lcom/coolcloud,no,, 215 | Lcom/coolcloud/uac,no,, 216 | Lcom/coolcloud/uac/android,Coolyun UAC,Development Aid,https://www.coolyun.com/ 217 | Lcom/coremedia/iso,ISO Parser,Development Aid, 218 | Lcom/crashlytics/android,Crashlytics,Mobile Analytics,http://try.crashlytics.com 219 | Lcom/crowdcompass,crowdcompass,Development Aid,https://www.crowdcompass.com/ 220 | Lcom/daggertech,Dagger Tech,Development Aid, 221 | Lcom/daimajia/androidanimations,AndroidAnimations Library,GUI Component,https://github.com/daimajia/AndroidViewAnimations 222 | Lcom/data,no,, 223 | Lcom/db4o,db4o,Development Aid,https://github.com/mohataher/db4o-android 224 | Lcom/deploygate,com/deploygate,Development Aid,https://deploygate.com/ 225 | Lcom/digits/sdk/vcard,Digits,Mobile Analytics,https://fabric.io/kits/android/digits/summary 226 | Lcom/doapps,doapps,Development Aid,http://www.doapps.com/ 227 | Lcom/dobao,com/dobao,Development Aid, 228 | Lcom/dropbox,no,, 229 | Lcom/dropbox/client2,Dropbox Java SDK,Utility,https://github.com/gini/dropbox-java-sdk 230 | Lcom/duoku,no,, 231 | Lcom/duoku/platform,duoku(Baidu Mobile Game Platform),Social Network,http://www.duoku.com.cn/ 232 | Lcom/e,no,, 233 | Lcom/e/a,no,, 234 | Lcom/easemob/,Huanxin,Development Aid,http://www.easemob.com/ 235 | Lcom/esotericsoftware,Esoteric Software 2D,Development Aid,https://github.com/EsotericSoftware 236 | Lcom/espian/showcaseview,Espian ShowcaseView,GUI Component,https://github.com/arianvp/ShowcaseView 237 | Lcom/everyplay,Everyplay,Game Engine,https://everyplay.com/ 238 | Lcom/external,no,, 239 | Lcom/f,no,, 240 | Lcom/f/a,no,, 241 | Lcom/facebook,Facebook,Social Network,https://developers.facebook.com 242 | Lcom/fasterxml,Fasterxml,Utility,http://fasterxml.com/ 243 | Lcom/flurry,no,, 244 | Lcom/flurry/android,Flurry,Mobile Analytics,https://flurry.com 245 | Lcom/flurry/org,Flurry,Mobile Analytics,https://flurry.com 246 | Lcom/flurry/sdk,Flurry SDK,Mobile Analytics,https://developer.yahoo.com 247 | Lcom/fyber,Fyber,Advertisement,https://www.fyber.com/ 248 | Lcom/g6677/spread,no,, 249 | Lcom/github,Github,Development Aid,https://github.com/ 250 | Lcom/goodbarber,goodbarber,Development Framework,http://www.goodbarber.com/ 251 | Lcom/google,no,, 252 | Lcom/google/a,no,, 253 | Lcom/google/a/b,no,, 254 | Lcom/google/a/b/a,no,, 255 | Lcom/google/a/b/a/a,no,, 256 | Lcom/google/ads,Google Ads,Advertisement,https://www.google.com/ads/ 257 | Lcom/google/analytics,Google Analytics,Mobile Analytics,https://www.google.com/analytics/ 258 | Lcom/google/android,no,, 259 | Lcom/google/android/a,no,, 260 | Lcom/google/android/apps/dashclock/api,DashClock API,Development Aid,http://api.dashclock.com/reference/com/google/android/apps/dashclock/api/package-summary.html 261 | Lcom/google/android/exoplayer,ExoPlayer,Development Aid,https://github.com/google/ExoPlayer 262 | Lcom/google/android/gcm,Google GCM,Development Aid,https://developers.google.com/cloud-messaging/ 263 | Lcom/google/android/gms,Google Mobile Services,Development Aid,https://developers.google.com/android/reference/com/google/android/gms/package-summary 264 | Lcom/google/android/net,Google Android Net,Development Aid,http://developer.android.com/reference/android/net/package-summary.html 265 | Lcom/google/android/vending,Google Play,App Market,https://play.google.com 266 | Lcom/google/android/youtube,no,, 267 | Lcom/google/android/youtube/player,YouTube Android Player API,Development Aid,https://developers.google.com/youtube/android/player/ 268 | Lcom/google/api,no,, 269 | Lcom/google/api/client,Google API Client Libraries,Development Framework,https://developers.google.com/api-client-library/java/ 270 | Lcom/google/appinventor,Google Appinventor,Development Aid,https://code.google.com/p/app-inventor-for-android/ 271 | Lcom/google/common,Google Core Libraries for Java 6+,Development Aid,https://github.com/google/guava 272 | Lcom/google/firebase,Firebase,Development Aid,http://firebase.com 273 | Lcom/google/gdata,Google GData,Development Aid,https://developers.google.com/gdata/ 274 | Lcom/google/gson,Google Gson,Development Aid,https://github.com/google/gson 275 | Lcom/google/i18n,Google Internationalization,Development Aid,https://developers.google.com/international/ 276 | Lcom/google/inject,Guice,Development Aid,https://github.com/google/guice 277 | Lcom/google/maps/android,Google Maps Utils,Map/LBS,https://github.com/googlemaps/android-maps-utils 278 | Lcom/google/protobuf,Google Protocol Buffers,Development Aid,https://github.com/google/protobuf 279 | Lcom/google/tagmanager,Google Tag Manager,Mobile Analytics,https://www.google.com/analytics/tag-manager/ 280 | Lcom/google/thirdparty,Google Core Libraries (3rd Party),Development Aid,https://github.com/google/guava 281 | Lcom/google/zxing,ZXing ('Zebra Crossing'),Development Aid,https://github.com/zxing/zxing 282 | Lcom/googlecode/apdfviewer,Google Docs PDF Viewer,Development Aid,https://code.google.com/p/apdfviewer/source/browse/trunk/src/com/googlecode/apdfviewer/?r=3 283 | Lcom/handmark/pulltorefresh,pulltorefresh,GUI Component,https://github.com/chrisbanes/Android-PullToRefresh 284 | Lcom/heyzap,Heyzap,Development Aid,https://www.heyzap.com 285 | Lcom/huawei,no,, 286 | Lcom/huawei/android,Huawei Android SDK,Development Aid,http://developer.huawei.com/ 287 | Lcom/huawei/ecs,Huawei ECS,Utility,https://www.hwclouds.com/en-us/product/ecs.html 288 | Lcom/huntmads,HUNT Mobile Ads,Advertisement,http://www.huntmads.com/ 289 | Lcom/iapppay,Iapppay,Payment,https://www.iapppay.com/ 290 | Lcom/ibm,no,, 291 | Lcom/ibm/icu,International Components for Unicode,Utility,https://www-01.ibm.com/software/globalization/icu/ 292 | Lcom/idddx,no,, 293 | Lcom/idddx/sdk,no,, 294 | Lcom/idddx/sdk/dynamic,no,, 295 | Lcom/idddx/sdk/dynamic/service,no,, 296 | Lcom/idddx/sdk/dynamic/service/thrift,no,, 297 | Lcom/iflytek,xunfei,Development Framework,http://www.xfyun.cn/ 298 | Lcom/iflytek/speech,iflyteck speech,Development Aid, 299 | Lcom/iflytek/speech/aidl,iflytek speech,Development Aid,https://www.xfyun.cn/doccenter/tts 300 | Lcom/iflytek/sunflower,Xunfei(iflytek) Voice,Development Framework, 301 | Lcom/iflytek/thirdparty,Iflytek Thirdparty,Development Aid,https://www.xfyun.cn/sdk/dispatcher 302 | Lcom/igaworks,igaworks,Advertisement,http://www.igaworks.com/en/index.html 303 | Lcom/igexin,getui,Development Aid,http://www.getui.com/cn/index.html 304 | Lcom/immersion,no,, 305 | Lcom/immersion/hapticmediasdk,Immersion TouchSense SDK,Development Aid,https://www.immersion.com/products-services/software-development-kit-for-mobile-games/ 306 | Lcom/inmobi,Inmobi,Advertisement,http://inmobi.com 307 | Lcom/inneractive,Inneractive,Advertisement,http://inner-active.com/ 308 | Lcom/ironsource,IronSource,Development Aid,http://www.ironsrc.com 309 | Lcom/iwanvi,ZhongWenWanwei Reader,Development Aid,http://www1.iwanvi.com/ 310 | Lcom/j256,J256,Development Aid,https://github.com/j256/ormlite-android 311 | Lcom/jakewharton/disklrucache,Disk LRU Cache,Development Aid,https://github.com/JakeWharton/DiskLruCache 312 | Lcom/jakewharton/disklrucache/,Disk LRU Cache,Development Aid,https://github.com/JakeWharton/DiskLruCache 313 | Lcom/jasonkostempski,Jasonkostempski,Development Aid,https://github.com/jasonkostempski/ 314 | Lcom/jayway,no,, 315 | Lcom/jayway/jsonpath,JsonPath,Development Aid,https://github.com/jayway/JsonPath 316 | Lcom/jcodecraeer/xrecyclerview/progressindicator,no,, 317 | Lcom/jcodecraeer/xrecyclerview/progressindicator/indicator,XRecyclerView (pull to refresh),Development Aid,https://github.com/jianghejie/XRecyclerView 318 | Lcom/jcraft/jsch,Java Secure Channel,Development Aid,http://www.jcraft.com/jsch/ 319 | Lcom/jirbo,no,, 320 | Lcom/jirbo/adcolony,Jirbo,Development Aid,http://www.jirbo.com/ 321 | Lcom/jiubang/commerce,no,, 322 | Lcom/jumptap,jumptap,Advertisement,http://jumptap.com/ 323 | Lcom/kakao/talk,Kakao,Social Network,https://developers.kakao.com/ 324 | Lcom/kbeanie,no,, 325 | Lcom/kbeanie/imagechooser,image chooser library,Development Aid,https://github.com/coomar2841/image-chooser-library 326 | Lcom/koushikdutta/async,AndroidAsync,Development Aid,https://github.com/koush/AndroidAsync 327 | Lcom/kuguo/ad,kuguo Advertisement SDK,Advertisement, 328 | Lcom/leadbolt,Leadbolt,Development Aid,https://www.leadbolt.com/ 329 | Lcom/lenovo,no,, 330 | Lcom/lenovo/lps,Lenovo LPS,Development Aid, 331 | Lcom/letv/adlib,Letv Advertisement Library,Advertisement, 332 | Lcom/letv/datastatistics,Letv Data Statistics,Mobile Analytics, 333 | Lcom/letv/lepaysdk,Letv pyment,Payment, 334 | Lcom/letv/sdk,Letv SDK,Utility, 335 | Lcom/letvcloud,Letv Cloud,Utility,http://www.lecloud.com/ 336 | Lcom/lib,no,, 337 | Lcom/lidroid,no,, 338 | Lcom/lidroid/xutils,xUtils,Development Aid,https://github.com/wyouflf/xUtils 339 | Lcom/loc,no,, 340 | Lcom/loopj,Loopj,Development Aid,https://github.com/loopj/android-async-http 341 | Lcom/madhouse/android,no,, 342 | Lcom/madhouse/android/ads,Madhouse Inc Ads,Advertisement,http://www.madhouse.cn/ 343 | Lcom/magook,no,, 344 | Lcom/magtab,Magtab,Development Aid,https://www.magtab.com/ 345 | Lcom/mashape/relocation,Mashape Relocation API,Development Aid, 346 | Lcom/maximono,Maximono,Social Network,http://maximono.com 347 | Lcom/meitu/android/trivialdrivesample,no,, 348 | Lcom/melnykov,no,, 349 | Lcom/melnykov/fab,FloatingActionButton,GUI Component,https://github.com/makovkastar/FloatingActionButton/ 350 | Lcom/milkmangames/extensions/android/coremobile,Milkman plugins,Development Aid,https://www.milkmanplugins.com 351 | Lcom/millennialmedia,millennialmedia,Advertisement,http://www.millennialmedia.com/ 352 | Lcom/mindprod/ledatastream,LEDataStream,Development Aid,http://mindprod.com/products1.html 353 | Lcom/mob,no,, 354 | Lcom/mob/commons,mob share,Social Network,mob.com 355 | Lcom/mob/tools,Mob Tools,Development Aid,http://www.mob.com/ 356 | Lcom/mobcent,MobCent,Social Network,http://www.baike.com/wiki/%E6%91%A9%E8%AE%AF%E7%A7%91%E6%8A%80 357 | Lcom/mobclick,no,, 358 | Lcom/mobclick/android,Umeng Click Analysis,Mobile Analytics,https://www.umeng.com/ 359 | Lcom/mobeta,Mobeta ListView,GUI Component,https://github.com/bauerca/drag-sort-listview 360 | Lcom/mobfox,mobfox,Development Aid,http://www.mobfox.com/ 361 | Lcom/mobisage,no,, 362 | Lcom/mobisage/android,Mobisage(adSage),Advertisement,http://www.adsage.com/ 363 | Lcom/mongodb,mongoDB,Development Aid,http://mongodb.github.io/mongo-java-driver/2.13/getting-started/quick-tour/ 364 | Lcom/mopub,MoPub,Advertisement,http://www.mopub.com 365 | Lcom/my/target/core,no,, 366 | Lcom/my/target/core/ui,no,, 367 | Lcom/my/target/core/ui/views,no,, 368 | Lcom/myappengine,myappengine,Game Engine,https://appengine.google.com/ 369 | Lcom/myshare,no,, 370 | Lcom/myshare/dynamic,Mob Share Dynamic,Social Network,http://mob.com 371 | Lcom/naef,no,, 372 | Lcom/naef,no,, 373 | Lcom/naef/jnlua,jnlua,Development Aid,Java Lua 374 | Lcom/nd,no,, 375 | Lcom/nd/dianjin,Dianjin Advertisement,Advertisement,http://www.devstore.cn/service/serviceDetail/428.html 376 | Lcom/neatplug,no,, 377 | Lcom/neatplug/u3d/plugins,NeatPlug Unity3d Plugins,Development Aid,https://neatplug.com/ 378 | Lcom/nerd/TapdaqUnityPlugin,TapDaq Unity Plugin,Utility,https://github.com/tapdaq/unity-plugin 379 | Lcom/netease,no,, 380 | Lcom/netease/nim,Netease IM SDK,Utility,https://github.com/netease-im/NIM_Android_SDK 381 | Lcom/netease/ntespm,no,, 382 | Lcom/newrelic,newrelic,Development Aid,https://newrelic.com/ 383 | Lcom/ngpinc/,ngpinc:National Guard Products,Mobile Analytics,http://www.ngpinc.com/ 384 | Lcom/nhaarman/listviewanimations,ListViewAnimations,Development Aid,https://github.com/nhaarman/ListViewAnimations 385 | Lcom/nineoldandroids,Nine Old Androids,Development Aid,https://github.com/JakeWharton/NineOldAndroids 386 | Lcom/nokia,no,, 387 | Lcom/nokia/payment,no,, 388 | Lcom/nokia/payment/iap,Nokia In-App Payment,Payment,http://developer.nokia.com/?p=932370&s=e0f3a2d5a412162fe5a577cfb660a309 389 | Lcom/nostra13,Nostra13 Image Loading,Development Aid,https://github.com/nostra13/Android-Universal-Image-Loader 390 | Lcom/nuance,Nuance Speech Kit Library,Development Aid,https://nuance.com/ 391 | Lcom/nv/support/pulltorefresh,pulltorefresh,GUI Component, 392 | Lcom/onbarcode,onbarcode,Development Aid,http://www.onbarcode.com/ 393 | Lcom/openfeint,OpenFeint,Game Engine, 394 | Lcom/outlinegames,Outline Games,Payment,http://www.outlinegames.com 395 | Lcom/papaya,Papaya,Development Aid,http://en.papayamobile.com/ 396 | Lcom/parse,Parse.com,Mobile Analytics,https://parse.com/docs/cn/android/guide 397 | Lcom/path/android/jobqueue,Android Priority Job Queue,Development Aid,https://github.com/path/android-priority-jobqueue 398 | Lcom/paypal,PayPal,Payment,https://developer.paypal.com/docs/integration/mobile/android-integration-guide/ 399 | Lcom/phonegap,PhoneGap,Development Aid,http://phonegap.com/ 400 | Lcom/playhaven,PlayHaven Mobile Ads,Advertisement,http://www.playhaven.com/ 401 | Lcom/pocketchange/,pocketchange,Payment,http://www.pocketchange.com/ 402 | Lcom/polites,GestureImageView polites.com,GUI Component,https://polites.com 403 | Lcom/pollfish,Pollfish,Development Aid,https://www.pollfish.com/ 404 | Lcom/prime31,prime[31],Development Aid,https://prime31.com 405 | Lcom/purplebrain/adbuddiz,AdBuddiz,Advertisement,https://www.adbuddiz.com 406 | Lcom/qihoo,no,, 407 | Lcom/qihoo/gamecenter,no,, 408 | Lcom/qihoo/gamecenter/sdk,Qihoo 360 Gamecenter,Social Network,http://wan.360.cn/ 409 | Lcom/qihoo/psdk,Qihoo push,Development Aid,http://dev.360.cn/ 410 | Lcom/qihoo/stat,Qihoo Stat,Development Aid,http://dev.360.cn/ 411 | Lcom/qihoopp,no,, 412 | Lcom/qihoopp/framework,QihooPP Framework,Development Framework,http://dev.360.cn 413 | Lcom/qihoopp/qcoinpay,Qihoo 360 Qcoinpay,Payment,https://pay.360.cn/index/mobile 414 | Lcom/qmoney,no,, 415 | Lcom/qmoney/ui,Qmoney,Payment, 416 | Lcom/qoppa,Qoppa Software,Development Aid,https://www.qoppa.com/ 417 | Lcom/qwapi,qwapi,Development Aid, 418 | Lcom/radiusnetworks,Radius Networks,Development Aid,http://www.radiusnetworks.com 419 | Lcom/readystatesoftware,no,, 420 | Lcom/readystatesoftware/sqliteasset,Android SQLiteAssetHelper,Utility,https://github.com/jgilfelt/android-sqlite-asset-helper 421 | Lcom/renn,no,, 422 | Lcom/renn/rennsdk,renren sdk,Development Aid,http://open.renren.com/wiki/SDK2/androidsdk 423 | Lcom/revmob,Revmob,Advertisement,https://www.revmobmobileadnetwork.com/ 424 | Lcom/samsung/spen,Samsung Spen,GUI Component,https://developer.samsung.com/galaxy 425 | Lcom/scoreloop,Scoreloop Game,Game Engine, 426 | Lcom/sec,no,, 427 | Lcom/sec/android,no,, 428 | Lcom/sec/android/iap,Samsung In-App Purchase,Payment,http://developer.samsung.com/iap 429 | Lcom/shengliwang,no,, 430 | Lcom/shengliwang/CarLogo,no,, 431 | Lcom/sina,no,, 432 | Lcom/sina/a,no,, 433 | Lcom/sina/sso,Sina SSO,Social Network,http://open.weibo.com/ 434 | Lcom/sina/weibo,Weibo,Social Network,http://weibo.com/ 435 | Lcom/skplanet,skplanet,Development Aid,http://www.skplanet.com 436 | Lcom/slidingmenu,SlidingMenu,GUI Component,https://github.com/jfeinstein10/SlidingMenu 437 | Lcom/smaato,Smaato,Advertisement,https://www.smaato.com/ 438 | Lcom/spoledge,Spoledge AAC Decoder,Development Aid,https://code.google.com/p/aacdecoder-android/ 439 | Lcom/sponsorpay,Fyber(SponsorPay),Advertisement,http://www.sponsorpay.com 440 | Lcom/squareup,no,, 441 | Lcom/squareup/okhttp,OkHttp,Development Aid,https://github.com/square/okhttp 442 | Lcom/squareup/otto,otto,Development Aid,http://square.github.io/otto/ 443 | Lcom/squareup/picasso,picasso,Development Aid,https://github.com/square/picasso 444 | Lcom/squareup/pollexor,pollexor,Development Aid,http://square.github.io/pollexor/ 445 | Lcom/squareup/seismic,Seismic,Utility,https://github.com/square/seismic 446 | Lcom/squareup/tape,Tape by Square,Utility,https://github.com/square/tape 447 | Lcom/squareup/timessquare,timessquare,Development Aid,https://github.com/square/android-times-square 448 | Lcom/startapp,StartApp,Advertisement,http://www.startapp.com/ 449 | Lcom/stericson/RootTools,Stericson RootTools,Development Aid,https://github.com/Stericson/RootTools 450 | Lcom/subsplash,subsplash,Development Aid,http://www.subsplash.com/ 451 | Lcom/sun,no,, 452 | Lcom/sun/activation,JavaBeans(TM) Activation Framework,Development Aid,http://java.sun.com/javase/technologies/desktop/javabeans/jaf/index.jsp 453 | Lcom/sun/mail,Sun Mail.jar,Development Aid, 454 | Lcom/supersonic/adapters/supersonicads,Supersonic Ads,Advertisement,https://www.supersonic.com/ 455 | Lcom/supersonic/mediationsdk,Supersonic MediationSDK(Abandoned),Development Aid,https://github.com/SupersonicAds/android-mediation-sdk 456 | Lcom/supersonicads,no,, 457 | Lcom/supersonicads/sdk,Supersonic: Mobile Advertising,Advertisement,https://www.supersonic.com/ 458 | Lcom/taobao,no,, 459 | Lcom/taobao/accs,Taobao ACCS,Development Aid,https://open.taobao.com/ 460 | Lcom/tapdaq/sdk,TapDaq Android SDK,Development Framework,https://github.com/tapdaq/tapdaq-android-sdk 461 | Lcom/tapdaq/tapdaqunityads,TapDaq Unity Plugin Ads,Advertisement, 462 | Lcom/tapit,Tapit,Development Aid,Tapit NFC 463 | Lcom/tapjoy,Tapjoy,Advertisement,https://home.tapjoy.com/ 464 | Lcom/tencent,no,, 465 | Lcom/tencent/android,no,, 466 | Lcom/tencent/android/tpush,Tencent Tpush (Xinge),Development Aid,http://xg.qq.com/ 467 | Lcom/tencent/bugly,Bugly,Mobile Analytics,https://bugly.qq.com/ 468 | Lcom/tencent/common,Tencent Login,Social Network,http://wiki.open.qq.com/wiki/mobile/Android_SDK 469 | Lcom/tencent/connect,Tencent Login,Social Network,https://connect.qq.com 470 | Lcom/tencent/jsutil,Tencent Login,Social Network,http://wiki.open.qq.com/wiki/mobile/Android_SDK 471 | Lcom/tencent/lbs,Tencent Map LBS,Map/LBS,https://lbs.qq.com/ 472 | Lcom/tencent/map,Tencent Map,Map/LBS,https://lbs.qq.com/ 473 | Lcom/tencent/mm,Tencent Wechat,Social Network,https://open.weixin.qq.com/ 474 | Lcom/tencent/mobwin,Tencent MobWin,Advertisement, 475 | Lcom/tencent/mta,Tencent MTA,Mobile Analytics,https://mta.qq.com/ 476 | Lcom/tencent/open,Tencent Login,Social Network,http://wiki.open.qq.com/wiki/mobile/Android_SDK 477 | Lcom/tencent/plus,Tencent Login,Social Network,http://wiki.open.qq.com/wiki/mobile/Android_SDK 478 | Lcom/tencent/qqconnect,Tencent Login,Social Network,http://wiki.open.qq.com/wiki/mobile/Android_SDK 479 | Lcom/tencent/qzone,Tencent Qzone,Social Network, 480 | Lcom/tencent/record,Tencent Login,Social Network,http://wiki.open.qq.com/wiki/mobile/Android_SDK 481 | Lcom/tencent/sdkutil,Tencent SDK Utilities,Development Aid,http://open.qq.com 482 | Lcom/tencent/smtt,Tencent X5 (SMTT),Social Network,http://x5.tencent.com/tbs/guide/sdkInit.html 483 | Lcom/tencent/stat,Tecent MTA,Mobile Analytics,http://mta.qq.com/ 484 | Lcom/tencent/t,Tencent Login,Social Network,http://t.qq.com 485 | Lcom/tencent/tauth,Tencent Login,Social Network,http://wiki.open.qq.com/wiki/mobile/Android_SDK 486 | Lcom/tencent/utils,Tencent Login,Social Network,http://wiki.open.qq.com/wiki/mobile/Android_SDK 487 | Lcom/tencent/webnet,Tencent WebNet,Development Aid, 488 | Lcom/tencent/weibo,Tencent Weibo,Social Network,http://t.qq.com 489 | Lcom/tencent/weiyun,Tencent Weiyun,Mobile Analytics,https://www.weiyun.com 490 | Lcom/tencent/wpa,Tencent WPA,Development Aid,http://wiki.open.qq.com/wiki/mobile/API 491 | Lcom/tencent/wxop,tencent weixin Open(Share),Social Network,https://open.weixin.qq.com/ 492 | Lcom/tendcloud,no,, 493 | Lcom/tendcloud/tenddata,TendDaTa,Mobile Analytics,https://www.talkingdata.com/products.jsp 494 | Lcom/thirdparty,Thirdparty,Development Aid,http://thirdparty.com/ 495 | Lcom/threatmetrix,ThreatMetrix,Digital Identity,https://www.threatmetrix.com/ 496 | Lcom/turbomanage,no,, 497 | Lcom/turbomanage/httpclient,basic-http-client,Development Aid,https://github.com/turbomanage/basic-http-client 498 | Lcom/umeng,no,, 499 | Lcom/umeng/analytics,Umeng Analytics,Mobile Analytics,https://www.umeng.com/analytics 500 | Lcom/umeng/api,Umeng API,Development Aid,http://dev.umeng.com 501 | Lcom/umeng/common,Umeng Common,Development Aid,http://dev.umeng.com/ 502 | Lcom/umeng/fb,Umeng feedback,Mobile Analytics,http://dev.umeng.com/feedback 503 | Lcom/umeng/message,Umeng Message Push,Development Aid,http://dev.umeng.com/push/android/sdk-download 504 | Lcom/umeng/newxp,Umeng newxp,Development Aid,http://www.umeng.com/ 505 | Lcom/umeng/newxp/view,no,, 506 | Lcom/umeng/socialize,Umeng Socialize,Social Network,http://dev.umeng.com/social/android/operation 507 | Lcom/umeng/socom,Umeng social component,Social Network,http://mobile.umeng.com/social 508 | Lcom/umeng/update,Umeng Update,Development Aid,https://www.umeng.com/component_update 509 | Lcom/umeng/xp,Umeng XP,Development Aid,http://dev.umeng.com/ 510 | Lcom/unionpay,no,, 511 | Lcom/unionpay/mobile,no,, 512 | Lcom/unionpay/mobile/android,Unionpay,Payment,http://mobile.unionpay.com/ 513 | Lcom/unionpay/sdk,no,, 514 | Lcom/unionpay/tsmservice,Unionpay TSM(Trusted Service Management),Payment,https://www.95516.com/static/union/pages/index/index.html 515 | Lcom/unity3d,Unity3D,Game Engine,https://unity3d.com/ 516 | Lcom/unity3d/ads,Unity3d Ads,Advertisement,https://unity3d.com/cn/services/ads 517 | Lcom/urbanairship,urbanairship,Mobile Analytics,https://www.urbanairship.com/ 518 | Lcom/uservoice/uservoicesdk,UserVoice Android SDK,Social Network,https://github.com/uservoice/uservoice-android-sdk 519 | Lcom/ut,no,, 520 | Lcom/ut/mini,ut mini push sdk,Development Aid, 521 | Lcom/uzmap,no,, 522 | Lcom/uzmap/pkg,no,, 523 | Lcom/uzmap/pkg/uzkit,no,, 524 | Lcom/uzmap/pkg/uzkit/fineHttp,fine HTTP,Development Aid,http://docs.apicloud.com/superwebview/Android/com/uzmap/pkg/uzkit/package-summary.html 525 | Lcom/vercoop,Vercoop,Development Aid,http://www.vercoop.com/ 526 | Lcom/verizon,Verizon,Development Aid,https://www.verizon.com/ 527 | Lcom/viewpagerindicator,Android Viewpagerindicator Widget,Development Aid,https://github.com/JakeWharton/ViewPagerIndicator 528 | Lcom/vividsolutions,no,, 529 | Lcom/vividsolutions/jts,JTS Topology Suite,Development Framework,http://sourceforge.net/projects/jts-topo-suite 530 | Lcom/vjianke,no,, 531 | Lcom/vjianke/pulltorefresh,pulltorefresh,GUI Component, 532 | Lcom/vl,no,, 533 | Lcom/vl/pulltorefresh,pulltorefresh,GUI Component, 534 | Lcom/vpon,Vpon,Advertisement,http://www.vpon.com/ 535 | Lcom/vungle,Vungle,Advertisement,https://vungle.com 536 | Lcom/wm/pulltorefresh,pulltorefresh,GUI Component, 537 | Lcom/xiaomi,no,, 538 | Lcom/xiaomi/mipush,no,, 539 | Lcom/xiaomi/mipush/sdk,miaomi mipush,Development Aid,https://dev.mi.com/console/appservice/push.html 540 | Lcom/xiaomi/push,Xiaomi Push,Development Aid,https://dev.mi.com/console/appservice/push.html 541 | Lcom/xiaomi/smack,Xiaomi Smack,Development Aid, 542 | Lcom/xiaomi/xmpush,Xiaomi XMpush,Development Aid,https://dev.mi.com/doc/p=533/index.html 543 | Lcom/xw,no,, 544 | Lcom/yandex,no,, 545 | Lcom/yandex/mobile/ads,Yandex Ad,Advertisement,https://www.yandex.com/ 546 | Lcom/yixia,Yixia,Development Aid,http://www.yixia.com/ 547 | Lcz,no,, 548 | Lcz/msebera,no,, 549 | Lcz/msebera/android,no,, 550 | Lcz/msebera/android/httpclient,HttpClient Android repackage buildscript,Development Aid,https://github.com/smarek/httpclient-android 551 | Ldagger,Dagger,Development Aid,http://square.github.io/dagger/ 552 | Lde,no,, 553 | Lde/greenrobot,no,, 554 | Lde/greenrobot/dao,GreenDao,Development Aid,https://github.com/greenrobot/greenDAO 555 | Lde/greenrobot/event,EventBus,Development Aid,https://github.com/greenrobot/EventBus 556 | Lde/keyboardsurfer,Keyboard Surfer,GUI Component,https://github.com/keyboardsurfer 557 | Lflexjson,FlexJson Library,Development Aid,http://flexjson.sourceforge.net/ 558 | Lfr,no,, 559 | Lfr/castorfle,castorfle Smooth Progress Bar,GUI Component,https://github.com/castorflex/SmoothProgressBar 560 | Lgnu,no,, 561 | Lgnu/commonlisp,GNU Common Lisp,Development Aid,https://www.gnu.org/s/gcl/ 562 | Lgnu/ecmascript,ECMAScript,Development Aid,https://www.gnu.org/s/kawa/api/gnu/ecmascript/package-frame.html 563 | Lgnu/kawa,GNU KAWA,Development Aid,https://www.gnu.org/software/kawa/Building-for-Android.html 564 | Lgnu/mapping,GNU Mapping,Development Aid,https://www.gnu.org/s/kawa/api/gnu/mapping/package-summary.html 565 | Lgnu/xml,GNU XML,Development Aid,https://www.gnu.org/s/kawa/api/gnu/xml/package-summary.html 566 | Lgreendroid,GreenDroid,GUI Component,https://github.com/cyrilmottier/GreenDroid 567 | Lhirondelle,no,, 568 | Lhirondelle/date4j,DATE4J,Development Aid,http://www.date4j.net/ 569 | Lim,no,, 570 | Lim/quar,AutoLayout for Android,Development Aid,https://mvnrepository.com/artifact/im.quar 571 | Linfo,no,, 572 | Linfo/guardianproject/bouncycastle,GuardianProject Bouncy Castle,Development Aid, 573 | Lio,no,, 574 | Lio/dcloud,Dcloud,Development Aid,http://dcloud.io/doc.html 575 | Lio/fabric,no,, 576 | Lio/fabric/sdk,no,, 577 | Lio/fabric/sdk/android,Fabric,Development Aid,https://get.fabric.io/ 578 | Lit,no,, 579 | Lit/gmariotti,no,, 580 | Lit/gmariotti/cardslib,Card Library,Utility,https://github.com/gabrielemariotti/cardslib 581 | Lit/sauronsoftware,no,, 582 | Lit/sauronsoftware/ftp4j,ftp4j,Development Aid,http://www.sauronsoftware.it/projects/ftp4j/ 583 | Ljavax,no,, 584 | Ljavax/activation,JavaBeans Activation Framework (JAF),Utility,http://www.oracle.com/technetwork/java/javase/jaf-135115.html 585 | Ljavax/annotation,JavaX Annotation API,Utility, 586 | Ljavax/jmdns,JavaX jmDNS library,Utility,https://github.com/jmdns/jmdns 587 | Ljavax/mail,JavaMail API,Utility,http://www.oracle.com/technetwork/java/javamail/index.html 588 | Ljavax/servlet,JavaX Servlet API,Utility,https://www.jcp.org/en/jsr/detail?id=369 589 | Ljavax/ws,no,, 590 | Ljavax/ws/rs,JavaX WebServices RESTful Resources,Utility,https://docs.oracle.com/javaee/7/api/javax/ws/rs/package-summary.html 591 | Ljcifs,JCIFS,Development Aid,http://jcifs.samba.org/ 592 | Ljsr166y,JSR-166y Java,Development Aid,http://g.oswego.edu/dl/concurrency-interest/ 593 | Ljunit,Junit,Development Aid,http://junit.org/junit4/ 594 | Ljxl,Java Excel API,Utility,http://jexcelapi.sourceforge.net/ 595 | Lkankan/wheel,Kankan Wheel Android scroller,GUI Component,https://github.com/chemalarrea/Android-wheel/blob/master/wheel-demo/src/kankan/wheel/demo/DateActivity.java 596 | Lkawa,Kawa for Android,Development Aid,https://www.gnu.org/software/kawa/Building-for-Android.html 597 | Ll,no,, 598 | Lm,no,, 599 | Lm/framework,no,, 600 | Lme,no,, 601 | Lme/apla,no,, 602 | Lme/apla/cordova,Application preferences plugin for Cordova 3+,Development Framework,https://github.com/apla/me.apla.cordova.app-preferences 603 | Lme/kiip,KIIP Mobile Ads,Advertisement,https://www.kiip.me/ 604 | Lme/zhanghai,no,, 605 | Lme/zhanghai/android,no,, 606 | Lme/zhanghai/android/materialprogressbar,MaterialProgressBar,Development Aid,https://github.com/DreaminginCodeZH/MaterialProgressBar 607 | Lmicrosoft,no,, 608 | Lmicrosoft/mappoint,Microsoft MapPoint,Map/LBS,https://www.microsoft.com/mappoint/ 609 | Lmm,no,, 610 | Lmm/purchasesdk,China Mobile PurchaseSDK,Payment, 611 | Lmobisocial,no,, 612 | Lmobisocial/omlet,no,, 613 | Lmobisocial/omlib,Omlet SDK,Social Network,https://sdk.omlet.me/en/docs.html 614 | Lmono,,,no 615 | Lmono/android,Mono for Android,Development Aid,http://www.mono-project.com/ 616 | Lmy,no,, 617 | Lname,no,, 618 | Lname/rkmlpv,no,, 619 | Lname/rkmlpv/jjhrjt,no,, 620 | Lname/rkmlpv/jjhrjt/ktphvh,no,, 621 | Lnet,no,, 622 | Lnet/authorize,Authorize.NET,Development Aid,http://www.authorize.net/ 623 | Lnet/hockeyapp/android,HockeyApp,Mobile Analytics,https://www.hockeyapp.net/ 624 | Lnet/lingala/zip4j,Zip4j,Development Aid,http://www.lingala.net/zip4j/ 625 | Lnet/minidev/json,json smart,Development Aid,https://github.com/netplex/json-smart-v2 626 | Lnet/simonvt/menudrawer,MenuDrawer,Development Aid,https://github.com/SimonVT/android-menudrawer 627 | Lnet/sourceforge/pinyin4j,Pinyin4j,Development Aid,http://pinyin4j.sourceforge.net/ 628 | Lnet/sourceforge/zbar,SourceForge ZBar,Development Aid,http://zbar.sourceforge.net/ 629 | Lnet/tsz,no,, 630 | Lnet/tsz/afinal,Afinal,Advertisement,https://github.com/yangfuhai/afinal/tree/master/src/net/tsz/afinal 631 | Lnet/youmi,Youmi Ads,Advertisement,http://www.youmi.net/ 632 | Lnl,no,, 633 | Lnl/siegmann,no,, 634 | Lnl/siegmann/epublib,EPublib,Development Aid,http://www.siegmann.nl/epublib 635 | Loauth,no,, 636 | Loauth/signpost,Signpost Oauth,Development Aid,https://code.google.com/p/oauth-signpost/ 637 | Lokhttp3,OKHttp3.0,Development Aid,https://github.com/square/okhttp 638 | Lokio,OkHttp okio Framework,Development Aid,https://github.com/square/okio 639 | Lopentk,The Open Toolkit Library,Development Aid,http://www.opentk.com/ 640 | Lorg,no,, 641 | Lorg/achartengine,AChartEngine,Development Aid,http://www.achartengine.org/ 642 | Lorg/acra,ACRA (Application Crash Reports for Android),Development Aid,https://github.com/ACRA/acra 643 | Lorg/anddev,no,, 644 | Lorg/anddev/andengine,Andengine Game Engine,Game Engine,http://www.andengine.org/ 645 | Lorg/andengine,Andengine Game Engine,Game Engine,http://www.andengine.org/ 646 | Lorg/android,no,, 647 | Lorg/android/agoo,Umeng U-push (Old version called agoo),Development Aid,http://dev.umeng.com/push/android/integration 648 | Lorg/androidannotations,AndroidAnnotations API,Development Aid,https://github.com/excilys/androidannotations 649 | Lorg/apache,no,, 650 | Lorg/apache/commons,Apache Common,Development Aid,https://commons.apache.org/ 651 | Lorg/apache/cordova,Apache Cordova,Development Aid,https://cordova.apache.org/ 652 | Lorg/apache/harmony,Apache Harmony,Development Aid,https://harmony.apache.org/ 653 | Lorg/apache/http,Apache Http,Development Aid,https://hc.apache.org/ 654 | Lorg/apache/james,Apache James Mail Enterprise Serve,Development Aid,http://james.apache.org 655 | Lorg/apache/log4j,Apache Log4j,Development Aid,http://logging.apache.org/log4j/2.x/ 656 | Lorg/apache/tools/ant,Apache Ant Core,Development Aid,http://ant.apache.org/ 657 | Lorg/appcelerator,Appcelerator,Development Aid,http://www.appcelerator.org/ 658 | Lorg/aspectj,AspectJ,Development Aid,https://eclipse.org/aspectj/ 659 | Lorg/bouncycastle,Bouncy Castle,Development Aid,http://www.bouncycastle.org/java.html 660 | Lorg/ccil,no,, 661 | Lorg/ccil/cowan,no,, 662 | Lorg/ccil/cowan/tagsoup,TagSoup,Utility,https://github.com/orbeon/tagsoup 663 | Lorg/cocos2d,cocos2D,Game Engine,http://www.cocos2d-x.org/ 664 | Lorg/cocos2dx,cocos2DX,Game Engine,http://www.cocos2d-x.org/ 665 | Lorg/codehaus,no,, 666 | Lorg/codehaus/jackson,Jackson Json-processor,Utility,https://github.com/codehaus/jackson 667 | Lorg/dom4j,Dom4j,Development Aid,http://dom4j.sourceforge.net/ 668 | Lorg/ebookdroid,no,, 669 | Lorg/ebookdroid/ui,no,, 670 | Lorg/ebookdroid/ui/library,no,, 671 | Lorg/ebookdroid/ui/library/tasks,EBookDroid,Development Aid,https://github.com/mortenpi/ebookdroid/ 672 | Lorg/fmod,Fmod,Game Engine,https://www.fmod.org/ 673 | Lorg/geometerplus,no,, 674 | Lorg/geometerplus/zlibrary,Zlibrary(FBReader PDF Reader),Development Aid, 675 | Lorg/hamcrest,hamcrest,Development Aid,http://hamcrest.org/ 676 | Lorg/htmlcleaner,htmlCleaner,Development Aid,http://htmlcleaner.sourceforge.net 677 | Lorg/ice4j,A Java implementation of the ICE protocol,Development Aid,https://github.com/jitsi/ice4j 678 | Lorg/ini4j,ini4j,Development Aid,http://ini4j.sourceforge.net 679 | Lorg/jaudiotagger,JAudiotagger,Utility,http://www.jthink.net/jaudiotagger/ 680 | Lorg/java_websocket,Java-WebSocket,Development Aid,https://github.com/TooTallNate/Java-WebSocket 681 | Lorg/jaxen,Jaxen,Development Aid,http://jaxen.org/ 682 | Lorg/jdeferred,Java jdeferred Library,Development Aid,http://jdeferred.org/ 683 | Lorg/jdom,JDOM V1,Development Aid,http://www.jdom.org/ 684 | Lorg/jdom2,JDOM2,Development Aid,https://github.com/hunterhacker/jdom/wiki/JDOM2-A-Primer 685 | Lorg/jivesoftware,no,, 686 | Lorg/jivesoftware/smack,Smack,Payment,https://mvnrepository.com/artifact/jivesoftware/smack 687 | Lorg/jivesoftware/smackx,Smack Extensions,Development Aid,https://mvnrepository.com/artifact/jivesoftware/smackx 688 | Lorg/joda/time,Joda Time,Development Aid,http://www.joda.org/joda-time/ 689 | Lorg/json,Json org,Development Aid,http://www.json.org/ 690 | Lorg/jsoup,Jsoup,Development Aid,http://jsoup.org/ 691 | Lorg/junit,jUnit Java Unit Test,Development Aid,http://junit.org/ 692 | Lorg/kde/necessitas/ministro/,Ministro Qt shared libraries,Development Aid,http://community.kde.org/Necessitas 693 | Lorg/kobjects,KObjects,Development Aid,http://kobjects.org 694 | Lorg/ksoap2,ksoap2,Development Aid,http://ksoap2.sourceforge.net/ 695 | Lorg/kxml2,Kxml2,Development Aid,http://www.kxml.org/ 696 | Lorg/lobobrowser,Lobobrowser,Development Aid,https://github.com/lobobrowser/LoboBrowser 697 | Lorg/mapsforge,Mapsforge API,Map/LBS,https://github.com/DonTomika/mapsforge 698 | Lorg/metalev,no,, 699 | Lorg/metalev/multitouch,Metalev Multi Touch,GUI Component,https://code.google.com/p/android-multitouch-controller/ 700 | Lorg/mozilla/intl/chardet,Mozilla Charset Detector,Utility, 701 | Lorg/mozilla/javascript,Mozilla Rhino,Development Aid,https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino 702 | Lorg/mozilla/universalchardet,Mozilla Universal Detector,Utility,https://github.com/ctt-gob-es/clienteafirma-external 703 | Lorg/msgpack,Messagepack,Utility,http://msgpack.org 704 | Lorg/nexage,Millennial Media,Advertisement,http://www.nexage.com 705 | Lorg/nexage/sourcekit/mraid,Nexage SourceKit-MRAID(part of MillennialMedia),Advertisement,https://github.com/nexage/sourcekit-mraid-android 706 | Lorg/ocpsoft,no,, 707 | Lorg/ocpsoft/prettytime,PrettyTime,Development Aid,https://github.com/ocpsoft/prettytime 708 | Lorg/openudid,OpenUDID Salama Generator,Development Aid,https://github.com/vieux/OpenUDID 709 | Lorg/osmdroid,OpenStreetMap-Tools,Map/LBS,https://github.com/osmdroid/osmdroid 710 | Lorg/scribe,Scribe Java Lib,Development Aid,https://github.com/scribejava/scribejava 711 | Lorg/simpleframework,simple framework,Development Aid,http://www.simpleframework.org/ 712 | Lorg/slf4j,SLF4J,Development Aid,http://www.slf4j.org/ 713 | Lorg/spongycastle,Spongy Castle,Development Aid,http://rtyley.github.io/spongycastle/ 714 | Lorg/springframework,Spring Framework,Development Aid,https://projects.spring.io/spring-framework/ 715 | Lorg/tukaani/xz,XZ For Java,Development Aid,http://tukaani.org/xz/java.html 716 | Lorg/vudroid,Vudroid PDF Reader,Development Aid, 717 | Lorg/xbill,no,, 718 | Lorg/xbill/DNS,Dnsjava,Development Aid,http://www.dnsjava.org/ 719 | Lorg/xinhua/analytics,Xinhua Analytics,Mobile Analytics, 720 | Lorg/xmlpull,XML Pull,Development Aid,http://www.xmlpull.org/ 721 | Lorg/yaml/snakeyaml,SnakeYAML,Development Aid,https://bitbucket.org/asomov/snakeyaml 722 | Lorg/zywx,no,, 723 | Lorg/zywx/wbpalmstar,Zywx Wbpalmstar APP Framework,Development Framework, 724 | Lpagerslidingtabstrip,PagerSlidingTabStrip UI Framework,GUI Component,https://github.com/astuetz/PagerSlidingTabStrip 725 | Lpdftron,Pdftron PDF Widget,Development Aid,https://www.pdftron.com/ 726 | Lpl/polidea,Polidea,Development Aid,https://www.polidea.com/ 727 | Lpts,no,, 728 | Lpts/PhoneGap,PhoneGap,Development Framework,http://phonegap.com/ 729 | Lrajawali,no,, 730 | Lrajawali/wallpaper,rajawali WallPapper,Development Aid,https://github.com/Rajawali/RajawaliWallpaperTemplate 731 | Lretrofit,retrofit RESTful Library,Development Aid,https://square.github.io/retrofit/ 732 | Lroboguice,Roboguice,Development Aid,https://github.com/roboguice/roboguice 733 | Lrx,no,, 734 | Lrx/internal,RxJava Retrofit,Development Aid,https://github.com/square/retrofit 735 | Lsafiap,no,, 736 | Lsafiap/framework,no,, 737 | Lsdk,no,, 738 | Lsdk/download,no,, 739 | Lshared_presage,no,, 740 | Lshared_presage/com,no,, 741 | Lti,no,, 742 | Lti/imagefactory,Titanium Image Factory,Development Aid,https://github.com/appcelerator-modules/ti.imagefactory 743 | Lti/map,Ti Map,Map/LBS,https://github.com/appcelerator-modules/ti.map 744 | Lti/modules,no,, 745 | Lti/modules/titanium,Titanium-Modules,Development Aid, 746 | Ltv,no,, 747 | Ltv/rhmjpj,no,, 748 | Ltv/rhmjpj/jrhrjt,no,, 749 | Ltv/rhmjpj/jrhrjt/ksptvg,no,, 750 | Ltwitter4j,Twitter,Social Network,http://twitter4j.org/ 751 | Lu,no,, 752 | Lu/aly,Umeng Analysis,Mobile Analytics,https://www.umeng.com/ 753 | Luk,no,, 754 | Luk/co,no,, 755 | Luk/co/senab,no,, 756 | Luk/co/senab/actionbarpulltorefresh,actionbarpulltorefresh,GUI Component,https://github.com/chrisbanes/ActionBar-PullToRefresh 757 | Lv2,no,, 758 | Lv2/com,no,, 759 | Lv2/com/playhaven,PlayHaven Mobile Ads,Advertisement,http://www.playhaven.com/ 760 | Lxamarin,Xamarin,Development Aid,https://xamarin.com/ 761 | Lzfee,no,, 762 | Lzfee/sdk,ZFEE SDK,Utility, 763 | -------------------------------------------------------------------------------- /LiteRadar/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Copyright 2017 Zachary Marv (马子昂) 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # LibRadar 18 | # ~~~~~ 19 | # 20 | # An automatically detecting tool for Android third-party libraries. 21 | # Ideas about this tool is written as a publisher, you could view the [PDF] 22 | # (http://dl.acm.org/citation.cfm?id=2889178) here. 23 | 24 | __all__ = ( 25 | "__title__", "__summary__", "__uri__", "__version__", "__author__", 26 | "__email__", "__license__", "__copyright__", 27 | ) 28 | 29 | __title__ = "libradar" 30 | __summary__ = "A tool for Android library detection." 31 | __uri__ = "https://github.com/pkumza/libradar" 32 | 33 | __version__ = "2.2.1" 34 | 35 | __author__ = "Zachary Marv (马子昂)" 36 | __email__ = "ma@zablog.me" 37 | 38 | __license__ = "Apache License, Version 2.0" 39 | __copyright__ = "Copyright 2017 " + __author__ 40 | -------------------------------------------------------------------------------- /LiteRadar/_settings.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Copyright 2017 Zachary Marv (马子昂) 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # LibRadar settings.py 18 | 19 | # Settings about python scripts in LibRadar folder. 20 | # All the scripts in LibRadar need import this file. 21 | 22 | 23 | import logging.config 24 | import os 25 | 26 | """ 27 | whether clean the workspace after work 28 | 0 : Clean nothing 29 | 1 : Clean res files 30 | 2 : Clean smali files 31 | 3 : Clean everything 32 | """ 33 | CLEAN_WORKSPACE = 0 34 | 35 | """ 36 | Database use db 0 as default 37 | """ 38 | 39 | DB_HOST = 'localhost' 40 | DB_PORT = 6379 41 | DB_ID = 2 42 | # if you don't have Password, delete DB_PSWD 43 | DB_PSWD = '' 44 | 45 | DB_FEATURE_CNT = 'feature_cnt' 46 | DB_FEATURE_WEIGHT = 'feature_weight' 47 | DB_UN_OB_PN = 'un_ob_pn' 48 | DB_UN_OB_CNT = 'un_ob_cnt' 49 | 50 | """ 51 | running_processes 52 | 53 | Use multi-processing could fully use the cores of cpu. 54 | Once I set QUEUE_TIME_OUT 5. After about two hours, three processes returns. So it should be little longer. 55 | I set it 30 yesterday and in two hours' processing, every process runs well. 56 | """ 57 | # RUNNING_PROCESS_NUMBER = 8 58 | RUNNING_PROCESS_NUMBER = 1 59 | QUEUE_TIME_OUT = 30 60 | 61 | """ 62 | IGNORE ZERO API FILES 63 | 64 | If there's no API in a class file, just ignore it. 65 | If there's no API in a package, just ignore it. 66 | """ 67 | IGNORE_ZERO_API_FILES = True 68 | 69 | """ 70 | Config Files 71 | """ 72 | 73 | SCRIPT_PATH = os.path.split(os.path.realpath(__file__))[0] 74 | if not os.path.exists(os.path.join(SCRIPT_PATH, 'Data')): 75 | os.mkdir(os.path.join(SCRIPT_PATH, 'Data')) 76 | FILE_LOGGING = os.path.join(SCRIPT_PATH, 'Data', 'logging.conf') 77 | FILE_RULE = os.path.join(SCRIPT_PATH, 'Data', 'tag_rules.csv') 78 | LITE_DATASET_10 = os.path.join(SCRIPT_PATH, 'Data', 'lite_dataset_10.csv') 79 | 80 | """ 81 | Logs 82 | """ 83 | 84 | logging.config.fileConfig(FILE_LOGGING) 85 | # create logger 86 | logger = logging.getLogger('radar') 87 | -------------------------------------------------------------------------------- /LiteRadar/dex_parser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #coding:utf-8 3 | 4 | # BSD 2-Clause License 5 | # 6 | # Copyright (c) [2016], [guanchao wen], shuwoom.wgc@gmail.com 7 | # All rights reserved. 8 | # 9 | # Redistribution and use in source and binary forms, with or without 10 | # modification, are permitted provided that the following conditions are met: 11 | # 12 | # * Redistributions of source code must retain the above copyright notice, this 13 | # list of conditions and the following disclaimer. 14 | # 15 | # * Redistributions in binary form must reproduce the above copyright notice, 16 | # this list of conditions and the following disclaimer in the documentation 17 | # and/or other materials provided with the distribution. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | import sys 31 | import binascii 32 | 33 | def byte_to_buma(val): 34 | binVal = bin(val)[2:].zfill(8) 35 | if binVal[0:1] == '0': 36 | return val 37 | sb = '' 38 | for i in range(7): 39 | if binVal[i+1:i+2] == '0': 40 | sb += '1' 41 | else: 42 | sb += '0' 43 | 44 | return -(int(sb, 2) + 1) 45 | 46 | def word_to_buma(val): 47 | binVal = bin(val)[2:].zfill(16) 48 | if binVal[0:1] == '0': 49 | return val 50 | sb = '' 51 | for i in range(15): 52 | if binVal[i+1:i+2] == '0': 53 | sb += '1' 54 | else: 55 | sb += '0' 56 | 57 | return -(int(sb, 2) + 1) 58 | 59 | def reverse_hex(binary_input): 60 | return binascii.hexlify(binascii.unhexlify(binary_input)[::-1]) 61 | 62 | """ 63 | 64 | # Not Used? zachary 20170105 65 | 66 | def dword_to_buma(val): 67 | binVal = bin(val)[2:].zfill(32) 68 | if binVal[0:1] == '0': 69 | return val 70 | sb = '' 71 | for i in range(31): 72 | if binVal[i+1:i+2] == '0': 73 | sb += '1' 74 | else: 75 | sb += '0' 76 | 77 | return -(int(sb, 2) + 1) 78 | """ 79 | """ 80 | ############### OPCODE ################# 81 | """ 82 | def getOpCode(opcode): 83 | """ 84 | 参考: dalvik-bytecode 85 | """ 86 | if opcode == 0x00 : return '10x', 'nop' 87 | if opcode == 0x01 : return '12x', 'move vA, vB' 88 | if opcode == 0x02 : return '22x', 'move/from16 vAA, vBBBB' 89 | if opcode == 0x03 : return '32x', 'move/16 vAAAA, vBBBB' 90 | if opcode == 0x04 : return '12x', 'move-wide vA, vB' 91 | if opcode == 0x05 : return '22x', 'move-wide/from16 vAA, vBBBB' 92 | if opcode == 0x06 : return '32x', 'move-wide/16 vAAAA, vBBBB' 93 | if opcode == 0x07 : return '12x', 'move-object vA, vB' 94 | if opcode == 0x08 : return '22x', 'move-object/from16 vAA, vBBBB' 95 | if opcode == 0x09 : return '32x', 'move-object/16 vAAAA, vBBBB' 96 | if opcode == 0xa : return '11x', 'move-result vAA' 97 | if opcode == 0xb : return '11x', 'move-result-wide vAA' 98 | if opcode == 0xc : return '11x', 'move-result-object vAA' 99 | if opcode == 0xd : return '11x', 'move-exception vAA' 100 | if opcode == 0xe : return '10x', 'return-void' 101 | if opcode == 0xf : return '11x', 'return vAA' 102 | if opcode == 0x10 : return '11x', 'return-wide' 103 | if opcode == 0x11 : return '11x', 'return-object vAA' 104 | if opcode == 0x12 : return '11n', 'const/4 vA, #+B' 105 | if opcode == 0x13 : return '21s', 'const/16 vAA, #+BBBB' 106 | if opcode == 0x14 : return '31i', 'const vAA, #+BBBBBBBB' 107 | if opcode == 0x15 : return '21h', 'const/high16 vAA, #+BBBB0000' 108 | if opcode == 0x16 : return '21s', 'const-wide/16 vAA, #+BBBB' 109 | if opcode == 0x17 : return '31i', 'const-wide/32 vAA, #+BBBBBBBB' 110 | if opcode == 0x18 : return '51l', 'const-wide vAA, #+BBBBBBBBBBBBBBBB' 111 | if opcode == 0x19 : return '21h', 'const-wide/high16 vAA, #+BBBB000000000000' 112 | if opcode == 0x1a : return '21c', 'const-string vAA, string@BBBB' 113 | if opcode == 0x1b : return '31c', 'const-string/jumbo vAA, string@BBBBBBBB' 114 | if opcode == 0x1c : return '21c', 'const-class vAA, type@BBBB' 115 | if opcode == 0x1d : return '11x', 'monitor-enter vAA' 116 | if opcode == 0x1e : return '11x', 'monitor-exit vAA' 117 | if opcode == 0x1f : return '21c', 'check-cast vAA, type@BBBB' 118 | if opcode == 0x20 : return '22c', 'instance-of vA, vB, type@CCCC' 119 | if opcode == 0x21 : return '12x', 'array-length vA, vB' 120 | if opcode == 0x22 : return '21c', 'new-instance vAA, type@BBBB' 121 | if opcode == 0x23 : return '22c', 'new-array vA, vB, type@CCCC' 122 | if opcode == 0x24 : return '35c', 'filled-new-array {vD, vE, vF, vG, vA}, type@CCCC' 123 | if opcode == 0x25 : return '3rc', 'filled-new-array/range {vCCCC .. vNNNN}, type@BBBB' 124 | if opcode == 0x26 : return '31t', 'fill-array-data vAA, +BBBBBBBB' 125 | if opcode == 0x27 : return '11x', 'throw vAA' 126 | if opcode == 0x28 : return '10t', 'goto +AA' 127 | if opcode == 0x29 : return '20t', 'goto/16 +AAAA' 128 | if opcode == 0x2a : return '30t', 'goto/32 +AAAAAAAA' 129 | if opcode == 0x2b : return '31t', 'packed-switch vAA, +BBBBBBBB' 130 | if opcode == 0x2c : return '31t', 'sparse-switch vAA, +BBBBBBBB' 131 | if opcode >= 0x2d and opcode <= 0x31 : return '23x', 'cmpkind vAA, vBB, vCC' 132 | if opcode >= 0x32 and opcode <= 0x37 : return '22t', 'if-test vA, vB, +CCCC' 133 | if opcode >= 0x38 and opcode <= 0x3d : return '21t', 'if-testz vAA, +BBBB' 134 | if opcode >= 0x3e and opcode <= 0x43 : return '10x', 'unused' 135 | if opcode >= 0x44 and opcode <= 0x51 : return '23x', 'arrayop vAA, vBB, vCC' 136 | if opcode >= 0x52 and opcode <= 0x5f : return '22c', 'iinstanceop vA, vB, field@CCCC' 137 | if opcode >= 0x60 and opcode <= 0x6d: return '21c', 'sstaticop vAA, field@BBBB' 138 | if opcode >= 0x6e and opcode <= 0x72 : return '35c', 'invoke-kind {vD, vE, vF, vG, vA}, meth@CCCC' 139 | if opcode == 0x73 : return '10x', 'unused' 140 | if opcode >= 0x74 and opcode <= 0x78 : return '3rc', 'invoke-kind/range {vCCCC .. vNNNN}, meth@BBBB' 141 | if opcode >= 0x79 and opcode <= 0x7a : return '10x', 'unused' 142 | if opcode >= 0x7b and opcode <= 0x8f : return '12x', 'unop vA, vB' 143 | if opcode >= 0x90 and opcode <= 0xaf : return '23x', 'binop vAA, vBB, vCC' 144 | if opcode >= 0xb0 and opcode <= 0xcf : return '12x', 'binop/2addr vA, vB' 145 | if opcode >= 0xd0 and opcode <= 0xd7 : return '22s', 'binop/lit16 vA, vB, #+CCCC' 146 | if opcode >= 0xd8 and opcode <= 0xe2 : return '22b', 'binop/lit8 vAA, vBB, #+CC' 147 | if opcode >= 0xe3 and opcode <= 0xfe : return '10x', 'unused' 148 | if opcode == 0x00ff : return '41c', 'const-class/jumbo vAAAA, type@BBBBBBBB' 149 | if opcode == 0x01ff : return '41c', 'check-cast/jumbo vAAAA, type@BBBBBBBB' 150 | if opcode == 0x02ff : return '52c', 'instance-of/jumbo vAAAA, vBBBB, type@CCCCCCCC' 151 | if opcode == 0x03ff : return '41c', 'new-instance/jumbo vAAAA, type@BBBBBBBB' 152 | if opcode == 0x04ff : return '52c', 'new-array/jumbo vAAAA, vBBBB, type@CCCCCCCC' 153 | if opcode == 0x05ff : return '52rc', 'filled-new-array/jumbo {vCCCC .. vNNNN}, type@BBBBBBBB' 154 | if opcode >= 0x06ff and opcode <= 0x13ff: return '52c', 'iinstanceop/jumbo vAAAA, vBBBB, field@CCCCCCCC' 155 | if opcode >= 0x14ff and opcode <= 0x21ff: return '41c', 'sstaticop/jumbo vAAAA, field@BBBBBBBB' 156 | if opcode >= 0x22ff and opcode <= 0x26ff: return '5rc', 'invoke-kind/jumbo {vCCCC .. vNNNN}, meth@BBBBBBBB' 157 | 158 | """ 159 | ############### OPCODE END ################# 160 | """ 161 | 162 | """ 163 | ############### InstrUtils ################# 164 | """ 165 | class DecodedInstruction(object): 166 | """docstring for DecodedInstruction""" 167 | def __init__(self): 168 | super(DecodedInstruction, self).__init__() 169 | self.vA = None 170 | self.vB = None 171 | self.vC = None 172 | self.vD = None 173 | self.vE = None 174 | self.vF = None 175 | self.vG = None 176 | self.opcode = None 177 | self.op = None 178 | self.indexType = None 179 | self.smaliCode = None 180 | # DeCode.insns指令集内相对于起始地址的offset 181 | self.offset = None 182 | # 代码片段长度 183 | self.length = None 184 | 185 | def dexDecodeInstruction(dexFile, dexCode, offset): 186 | byteCounts = int(offset / 4) 187 | insns = dexCode.insns 188 | 189 | if insns == '': 190 | return None 191 | 192 | decodedInstruction = DecodedInstruction() 193 | opcode = int(insns[offset:offset+2], 16) 194 | formatIns, syntax = getOpCode(opcode) 195 | 196 | decodedInstruction.opcode = opcode 197 | 198 | if formatIns == '10x': 199 | # Format: 00|op <=> op 200 | # (1) opcode=00 nop 201 | if opcode == 0x00: 202 | decodedInstruction.op = 'nop' 203 | decodedInstruction.smaliCode = 'nop' 204 | decodedInstruction.offset = offset 205 | decodedInstruction.length = 4 206 | 207 | # (2) opcode=0e return-void 208 | if opcode == 0x0e: 209 | decodedInstruction.op = 'return-void' 210 | decodedInstruction.smaliCode = 'return-void' 211 | decodedInstruction.offset = offset 212 | decodedInstruction.length = 4 213 | 214 | # (3) opcode=3e..43 unused 215 | if opcode >= 0x3e and opcode <= 0x43: 216 | decodedInstruction.op = 'unused' 217 | decodedInstruction.smaliCode = 'unused' 218 | decodedInstruction.offset = offset 219 | decodedInstruction.length = 4 220 | 221 | # (4) opcode=73 unused 222 | if opcode == 0x73: 223 | decodedInstruction.op = 'unused' 224 | decodedInstruction.smaliCode = 'unused' 225 | decodedInstruction.offset = offset 226 | decodedInstruction.length = 4 227 | 228 | # (5) opcode=79..7a unused 229 | if opcode >= 0x79 and opcode <= 0x7a: 230 | decodedInstruction.op = 'unused' 231 | decodedInstruction.smaliCode = 'unused' 232 | decodedInstruction.offset = offset 233 | decodedInstruction.length = 4 234 | 235 | # (6) opcode=e3..fe unused 236 | if opcode >= 0xe3 and opcode <= 0xfe: 237 | decodedInstruction.op = 'unused' 238 | decodedInstruction.smaliCode = 'unused' 239 | decodedInstruction.offset = offset 240 | decodedInstruction.length = 4 241 | 242 | elif formatIns == '12x': # op vA, vB 243 | # Format: B|A|op <=> op vA, vB 244 | op = '????' 245 | # (1) opcode=01 move vA, vB 246 | if opcode == 0x01: 247 | op = 'move' 248 | # (2) opcode=04 move-wide vA, vB 249 | if opcode == 0x04: 250 | op = 'move-wide' 251 | # (3) opcode=07 move-object vA, vB 252 | if opcode == 0x07: 253 | op = 'move-object' 254 | # (4) opcode=21 array-length vA, vB 255 | if opcode == 0x21: 256 | op = 'array-length' 257 | # (5) opcode7b..8f unop vA, vB 258 | if opcode >= 0x7b and opcode <= 0x8f: 259 | unop = ['neg-int', 'not-int', 'neg-long', 'not-long', 'neg-float', 'neg-double', 'int-to-long', 'int-to-float', 'int-to-double', 260 | 'long-to-int', 'long-to-float', 'long-to-double', 'float-to-int', 'float-to-long', 'float-to-double', 261 | 'double-to-int', 'double-to-long', 'double-to-float', 'int-to-byte', 'int-to-char', 'int-to-short'] 262 | op = unop[opcode - 0x7b] 263 | # (6) opcode=b0..cf binop/2addr vA, vB 264 | if opcode >= 0xb0 and opcode <= 0xcf: 265 | ops = ['add-int/2addr', 'sub-int/2addr', 'mul-int/2addr', 'div-int/2addr', 'rem-int/2addr', 'and-int/2addr', 'or-int/2addr', 'xor-int/2addr', 'shl-int/2addr', 'shr-int/2addr', 'ushr-int/2addr', 266 | 'add-long/2addr', 'sub-long/2addr', 'mul-long/2addr', 'div-long/2addr', 'rem-long/2addr', 'and-long/2addr', 'or-long/2addr', 'xor-long/2addr', 'shl-long/2addr', 'shr-long/2addr','ushr-long/2addr', 267 | 'add-float/2addr', 'sub-float/2addr', 'mul-float/2addr', 'div-float/2addr', 'rem-float/2addr', 268 | 'add-double/2addr', 'sub-double/2addr', 'mul-double/2addr', 'div-double/2addr', 'rem-double/2addr'] 269 | op = ops[opcode - 0xb0] 270 | 271 | B = int(insns[offset + 2:offset + 3], 16) 272 | A = int(insns[offset + 3:offset + 4], 16) 273 | 274 | decodedInstruction.op = op 275 | decodedInstruction.vA = A 276 | decodedInstruction.vB = B 277 | decodedInstruction.smaliCode = '%s v%d, v%d' % (op, A, B) 278 | decodedInstruction.offset = offset 279 | decodedInstruction.length = 4 280 | 281 | elif formatIns == '11n': 282 | # Format: B|A|op <=> # op vA, #+B 283 | # (1) opcode=12 const/4 vA, #+B 284 | B = int(insns[offset+2:offset+3], 16) 285 | A = int(insns[offset+3:offset+4], 16) 286 | 287 | decodedInstruction.op = 'const/4' 288 | decodedInstruction.vA = A 289 | decodedInstruction.B = B 290 | decodedInstruction.smaliCode = 'const/4 v%d, #+%d' % (A, B) 291 | decodedInstruction.offset = offset 292 | decodedInstruction.length = 4 293 | 294 | elif formatIns == '11x': 295 | # Format: AA|op <=> # op vAA 296 | op = '????' 297 | # (1) opcode=0a move-result vAA 298 | if opcode == 0x0a: 299 | op = 'move-result' 300 | # (2) opcode=0b move-result-wide vAA 301 | if opcode == 0x0b: 302 | op = 'move-result-wide' 303 | # (3) opcode=0c move-result-object vAA 304 | if opcode == 0x0c: 305 | op = 'move-result-object' 306 | # (4) opcode=0d move-exception vAA 307 | if opcode == 0x0d: 308 | op = 'move-exception' 309 | # (5) opcode=0f return vAA 310 | if opcode == 0x0f: 311 | op = 'return' 312 | # (6) opcode=10 return-wide vAA 313 | if opcode == 0x10: 314 | op = 'return-wide' 315 | # (7) opcode=11 return-object vAA 316 | if opcode == 0x11: 317 | op = 'return-object' 318 | # (8) opcode=1d monitor-enter vAA 319 | if opcode == 0x1d: 320 | op = 'monitor-enter' 321 | # (9) opcode=1e monitor-exit vAA 322 | if opcode == 0x1e: 323 | op = 'monitor-exit' 324 | # (10) opcode=27 throw vAA 325 | if opcode == 0x27: 326 | op = 'throw' 327 | 328 | AA = int(insns[offset + 2:offset + 4], 16) 329 | 330 | decodedInstruction.op = op 331 | decodedInstruction.vA = AA 332 | decodedInstruction.smaliCode = '%s v%d' % (op, AA) 333 | decodedInstruction.offset = offset 334 | decodedInstruction.length = 4 335 | 336 | elif formatIns == '10t': 337 | # Format: AA|op <=> # op +AA 338 | # (1) opcode=28 goto +AA 339 | AA = int(insns[offset + 2:offset + 4], 16) 340 | buma = byte_to_buma(AA) 341 | 342 | decodedInstruction.op = 'goto' 343 | decodedInstruction.vA = AA 344 | decodedInstruction.smaliCode = 'goto %s //%s' % (hex(int(offset/4)+buma), hex(buma)) 345 | decodedInstruction.offset = offset 346 | decodedInstruction.length = 4 347 | 348 | elif formatIns == '20t': 349 | # Format: 00|op AAAA <=> # op +vAAAA 350 | # (1) opcode=29 goto/16 +AAAA 351 | if opcode == 0x29: 352 | AAAA = int(insns[offset + 2:offset + 8], 16) 353 | buma = word_to_buma(int(reverse_hex(insns[offset + 4:offset + 8]), 16)) 354 | 355 | decodedInstruction.op = 'goto/16' 356 | decodedInstruction.vA = AAAA 357 | decodedInstruction.smaliCode = 'goto/16 %s //%s' % (hex(int(offset/4)+buma), hex(buma)) 358 | decodedInstruction.offset = offset 359 | decodedInstruction.length = 8 360 | 361 | elif formatIns == '20bc': 362 | # Format: AA|op BBBB <=> op AA, kind@BBBB 363 | # 无opcode 364 | pass 365 | elif formatIns == '22x': 366 | # Format: AA|op BBBB <=> op vAA, vBBBB 367 | op = '????' 368 | # (1) opcode=02 move/from16 vAA, vBBBB 369 | if opcode == 0x02: 370 | op = 'move/from16' 371 | # (2) opcode=05 move-wide/from16 vAA, vBBBB 372 | if opcode == 0x05: 373 | op = 'move-wide/from16' 374 | # (3) opcode=08 move-object/from16 vAA, vBBBB 375 | if opcode == 0x08: 376 | op = 'move-object/from16' 377 | 378 | AA = int(insns[offset + 2:offset + 4], 16) 379 | BBBB = int(reverse_hex(insns[offset + 4:offset + 8]), 16) 380 | 381 | decodedInstruction.op = op 382 | decodedInstruction.vA = AA 383 | decodedInstruction.vB = BBBB 384 | decodedInstruction.smaliCode = '%s v%d, v%s' % (op, AA, BBBB) 385 | decodedInstruction.offset = offset 386 | decodedInstruction.length = 8 387 | 388 | elif formatIns == '21t': 389 | # Format: AA|op BBBB <=> op vAA, +BBBB 390 | op = '????' 391 | # (1) opcode=38..3d if-testz vAA, +BBBB 392 | if opcode >= 0x38 and opcode <= 0x3d: 393 | ops = ['if-eqz', 'if-nez', 'if-ltz', 'if-gez', 'if-gtz', 'if-lez'] 394 | op = ops[opcode - 0x38] 395 | 396 | AA = int(insns[offset + 2:offset + 4], 16) 397 | BBBB = int(reverse_hex(insns[offset + 4:offset + 8]), 16) 398 | 399 | decodedInstruction.op = op 400 | decodedInstruction.vA = AA 401 | decodedInstruction.vB = BBBB 402 | decodedInstruction.smaliCode = '%s v%d, %s //+%s' % (op, AA, hex(BBBB+int(offset/4)), hex(BBBB)) 403 | decodedInstruction.offset = offset 404 | decodedInstruction.length = 8 405 | 406 | elif formatIns == '21s': 407 | # Format: AA|op BBBB <=> op vAA, #+BBBB 408 | op = '????' 409 | # (1) opcode=13 const/16 vAA, #_BBBB 410 | if opcode == 0x13: 411 | op = 'const/16' 412 | # (2) opcode=16 const-wide/16 vAA, #+BBBB 413 | if opcode == 0x16: 414 | op = 'const-wide/16' 415 | 416 | AA = int(insns[offset + 2:offset + 4], 16) 417 | BBBB = int(reverse_hex(insns[offset + 4:offset + 8]), 16) 418 | 419 | decodedInstruction.op = op 420 | decodedInstruction.vA = AA 421 | decodedInstruction.vB = BBBB 422 | decodedInstruction.smaliCode = '%s v%d, #+%s' % (op, AA, BBBB) 423 | decodedInstruction.offset = offset 424 | decodedInstruction.length = 8 425 | 426 | elif formatIns == '21h': 427 | # Format: AA|op BBBB <=> op vAA, #+BBBB0000[00000000] 428 | AA = int(insns[offset + 2:offset + 4], 16) 429 | BBBB = reverse_hex(insns[offset + 4:offset + 8]).decode() 430 | 431 | # (1) opcode=15 const/high16 vAA, #+BBBB0000 432 | if opcode == 0x15: 433 | op = 'const/high16' 434 | 435 | decodedInstruction.op = op 436 | decodedInstruction.vA = AA 437 | decodedInstruction.vB = int(BBBB + '0000', 16) 438 | decodedInstruction.smaliCode = '%s v%d, #+%s' % (op, AA, int(BBBB + '0000', 16)) 439 | decodedInstruction.offset = offset 440 | decodedInstruction.length = 8 441 | 442 | # (2) opcode=19 const-wide/high16 vAA, #+BBBB000000000000 443 | if opcode == 0x19: 444 | op = 'const-wide/high16' 445 | 446 | decodedInstruction.op = op 447 | decodedInstruction.vA = AA 448 | decodedInstruction.vB = int(BBBB + '000000000000', 16) 449 | decodedInstruction.smaliCode = '%s v%d, #+%s' % (op, AA, int(BBBB + '000000000000', 16)) 450 | decodedInstruction.offset = offset 451 | decodedInstruction.length = 8 452 | 453 | elif formatIns == '21c': 454 | # Format: AA|op BBBB <=> op vAA, [type|field|string]@BBBB 455 | indexType = '????' 456 | op = '????' 457 | indexStr = '' 458 | 459 | AA = int(insns[offset + 2:offset + 4], 16) 460 | BBBB = reverse_hex(insns[offset + 4:offset + 8]) 461 | 462 | # (1) opcode=1a const-string vAA, string@BBBB 463 | if opcode == 0x1a: 464 | op = 'const-string' 465 | indexType = 'string' 466 | indexStr = dexFile.getDexStringId(int(BBBB, 16)) 467 | # (2) opcode=1c const-class vAA, type@BBBB 468 | if opcode == 0x1c: 469 | op = 'const-class' 470 | indexType = 'type' 471 | indexStr = dexFile.getDexTypeId(int(BBBB, 16)) 472 | # (3) opcode=1f check-cast vAA, type@BBBB 473 | if opcode == 0x1f: 474 | op = 'check-cast' 475 | indexType = 'type' 476 | indexStr = dexFile.getDexTypeId(int(BBBB, 16)) 477 | # (4) opcode=22 new-instance vAA, type@BBBB 478 | if opcode == 0x22: 479 | op = 'new-instance' 480 | indexType = 'type' 481 | indexStr = dexFile.getDexTypeId(int(BBBB, 16)) 482 | # (5) opcode=60..6d sstaticop vAA, field@BBBB 483 | if opcode >= 0x60 and opcode <=0x6d: 484 | sstaticop = ['sget', 'sget-wide', 'sget-object', 'sget-boolean', 'sget-byte', 'sget-char', 485 | 'sget-char', 'sget-short', 'sput', 'sput-wide', 'sput-object', 'sput-boolean', 486 | 'sput-byte', 'sput-char', 'sput-short'] 487 | op = sstaticop[opcode - 0x60] 488 | indexType = 'field' 489 | dexFieldIdObj = dexFile.DexFieldIdList[int(BBBB, 16)] 490 | indexStr = dexFieldIdObj.toString(dexFile) 491 | 492 | decodedInstruction.op = op 493 | decodedInstruction.vA = AA 494 | decodedInstruction.vB = int(BBBB, 16) 495 | decodedInstruction.indexType = indexType 496 | decodedInstruction.smaliCode = '%s v%d, %s@%s //%s' % (op, AA, indexType, BBBB, indexStr) 497 | decodedInstruction.offset = offset 498 | decodedInstruction.length = 8 499 | 500 | elif formatIns == '23x': 501 | # Format: AA|op CC|BB <=> op vAA, vBB, vCC 502 | op = '????' 503 | # (1) opcode=2d..31 cmpkind vAA, vBB, vCC 504 | if opcode >= 0x2d and opcode <= 0x31: 505 | cmpkind = ['cmpl-float', 'cmpg-float', 'cmpl-double', 'cmpg-double', 'cmp-long'] 506 | op =cmpkind[opcode - 0x2d] 507 | # (2) opcode=44..51 arrayop vAA, vBB, vCC 508 | if opcode >= 0x44 and opcode <= 0x51: 509 | arrayop = ['aget', 'aget-wide', 'aget-object', 'aget-boolean', 'aget-byte', 'aget-char', 'aget-short', 510 | 'aput', 'aput-wide', 'aput-object', 'aput-boolean', 'aput-byte', 'aput-char', 'aput-short'] 511 | op = arrayop[opcode - 0x44] 512 | # (3) opcode=90..af binop vAA, vBB, vCC 513 | if opcode >= 0x90 and opcode <= 0xaf: 514 | binop = ['add-int', 'sub-int', 'mul-int', 'div-int', 'rem-int', 'and-int', 'or-int', 'xor-int', 'shl-int', 'shr-int', 'ushr-int', 515 | 'add-long', 'sub-long', 'mul-long', 'div-long', 'rem-long', 'and-long', 'or-long', 'xor-long', 'shl-long', 'shr-long', 'ushr-long', 516 | 'add-float', 'sub-float', 'mul-float', 'div-float', 'rem-float', 517 | 'add-double', 'sub-double', 'mul-double', 'div-double', 'rem-double'] 518 | op = binop[opcode - 0x90] 519 | 520 | AA = int(insns[offset + 2:offset + 4], 16) 521 | BB = int(insns[offset + 4:offset + 6], 16) 522 | CC = int(insns[offset + 6:offset + 8], 16) 523 | 524 | decodedInstruction.op = op 525 | decodedInstruction.vA = AA 526 | decodedInstruction.vB = BB 527 | decodedInstruction.vC = CC 528 | decodedInstruction.smaliCode = '%s v%d, v%d, v%d' % (op, AA, BB, CC) 529 | decodedInstruction.offset = offset 530 | decodedInstruction.length = 8 531 | 532 | elif formatIns == '22b': 533 | # Format: AA|op CC|BB <=> op vAA, vBB, #+CC 534 | # (1) opcode=d8..e2 binop/lit8 vAA, vBB, #+CC 535 | if opcode >= 0xd8 and opcode <= 0xe2: 536 | ops = ['add-int/lit8', 'rsub-int/lit8', 'mul-int/lit8', 'div-int/lit8', 'rem-int/lit8', 'and-int/lit8', 537 | 'or-int/lit8', 'xor-int/lit8', 'shl-int/lit8', 'shr-int/lit8', 'ushr-int/lit8'] 538 | op = ops[opcode - 0xd8] 539 | 540 | AA = int(insns[offset + 2:offset + 4], 16) 541 | BB = int(insns[offset + 4:offset + 6], 16) 542 | CC = int(insns[offset + 6:offset + 8], 16) 543 | 544 | decodedInstruction.op = op 545 | decodedInstruction.vA = AA 546 | decodedInstruction.vB = BB 547 | decodedInstruction.vC = CC 548 | decodedInstruction.smaliCode = '%s v%d, v%d, #+v%d' % (op, AA, BB, CC) 549 | decodedInstruction.offset = offset 550 | decodedInstruction.length = 8 551 | 552 | elif formatIns == '22t': 553 | # Format: B|A|op CCCC <=> op vA, vB, +CCCC 554 | op = '????' 555 | # (1) opcode=32..37 if-test vA, vB, +CCCC 556 | if opcode >=0x32 and opcode <= 0x37: 557 | ops = ['if-eq', 'if-ne', 'if-lt', 'if-ge', 'if-gt', 'if-le'] 558 | op = ops[opcode - 0x32] 559 | B = int(insns[offset + 2: offset + 3], 16) 560 | A = int(insns[offset + 3: offset + 4], 16) 561 | CCCC = reverse_hex(insns[offset+4:offset+8]) 562 | 563 | decodedInstruction.op = op 564 | decodedInstruction.vA = A 565 | decodedInstruction.vB = B 566 | decodedInstruction.vC = CCCC 567 | decodedInstruction.smaliCode = '%s v%d, v%d, %s // +%s' % (op, A, B, hex(int(offset/4)+int(CCCC, 16)), CCCC) 568 | decodedInstruction.offset = offset 569 | decodedInstruction.length = 8 570 | 571 | elif formatIns == '22s': 572 | # Format: B|A|op CCCC <=> op vA, vB, #+CCCC 573 | op = '????' 574 | # (1) opcode=d0..d7 binop/lit16 vA, vB, #+CCCC 575 | if opcode >= 0xd0 and opcode <= 0xd7: 576 | ops = ['add-int/lit16', 'rsub-int', 'mul-int/lit16', 'div-int/lit16', 'rem-int/lit16', 'and-int/lit16', 'or-int/lit16', 'xor-int/lit16'] 577 | op = ops[opcode - 0xd0] 578 | 579 | B = int(insns[offset + 2: offset + 3], 16) 580 | A = int(insns[offset + 3: offset + 4], 16) 581 | CCCC = reverse_hex(insns[offset + 4:offset + 8]) 582 | 583 | decodedInstruction.op = op 584 | decodedInstruction.vA = A 585 | decodedInstruction.vB = B 586 | decodedInstruction.vC = int(CCCC, 16) 587 | decodedInstruction.smaliCode = '%s v%d, v%d, #+%s' % (op, A, B, CCCC) 588 | decodedInstruction.offset = offset 589 | decodedInstruction.length = 8 590 | 591 | elif formatIns == '22c': 592 | # Format: B|A|op CCCC <=> op vA, vB, [type|field]@CCCC 593 | op = '????' 594 | indexType = '????' 595 | indexStr = '' 596 | 597 | B = int(insns[offset + 2:offset + 3], 16) 598 | A = int(insns[offset + 3:offset + 4], 16) 599 | CCCC = reverse_hex(insns[offset + 4:offset + 8]) 600 | 601 | # (1) opcode=20 instance-of vA, vB, type@CCCC 602 | if opcode == 0x20: 603 | op = 'instance-of' 604 | indexType = 'type' 605 | indexStr = dexFile.DexTypeIdList[int(CCCC, 16)] 606 | # (2) opcode=23 new-array vA, vB, type@CCCC 607 | if opcode == 0x23: 608 | op = 'new-array' 609 | indexType = 'type' 610 | indexStr = dexFile.DexTypeIdList[int(CCCC, 16)] 611 | # (3) opcode=52..5f iinstanceop vA, vB, field@CCCC 612 | if opcode >= 0x52 and opcode <= 0x5f: 613 | iinstanceop = ['iget', 'iget-wide', 'iget-object', 'iget-boolean', 'iget-byte', 'iget-char', 'iget-short', 614 | 'iput', 'iput-wide', 'iput-object', 'iput-boolean', 'iput-byte', 'iput-char', 'put-short'] 615 | op = iinstanceop[opcode - 0x52] 616 | indexType = 'field' 617 | dexFieldIdObj = dexFile.DexFieldIdList[int(CCCC, 16)] 618 | indexStr = dexFieldIdObj.toString(dexFile) 619 | 620 | decodedInstruction.op = op 621 | decodedInstruction.vA = A 622 | decodedInstruction.vB = B 623 | decodedInstruction.vC = int(CCCC, 16) 624 | decodedInstruction.indexType = indexType 625 | decodedInstruction.smaliCode = '%s v%d, v%d %s@%s //%s' % (op, A, B, indexType, CCCC, indexStr) 626 | decodedInstruction.offset = offset 627 | decodedInstruction.length = 8 628 | 629 | elif formatIns == '22cs': 630 | # Format: B|A|op CCCC <=> op vA, vB, fieldoff@CCCC 631 | # 无opcode 632 | pass 633 | elif formatIns == '30t': 634 | # Format: ØØ|op AAAAlo AAAAhi <=> op +AAAAAAAA 635 | # (1) opcode=2a goto/32 +AAAAAAAA 636 | if opcode == 0x2a: 637 | AAAAAAAA = reverse_hex(insns[offset + 2:offset + 12]) 638 | buma = word_to_buma(int(reverse_hex(insns[offset + 4:offset + 12]), 16)) 639 | 640 | decodedInstruction.op = 'goto/32' 641 | decodedInstruction.vA = int(AAAAAAAA, 16) 642 | decodedInstruction.smaliCode = 'goto/32 %s //%s' % (hex(int(offset/4)+buma), hex(buma)) 643 | decodedInstruction.offset = offset 644 | decodedInstruction.length = 12 645 | 646 | elif formatIns == '32x': 647 | # Format: ØØ|op AAAA BBBB <=> op vAAAA, vBBBB 648 | op = '????' 649 | # (1) opcode=03 move/16 vAAAA, vBBBB 650 | # (2) opcode=06 move-wide/16 vAAAA, vBBBB 651 | # (3) opcode=09 move-object/16 vAAAA, vBBBB 652 | if opcode == 0x03: 653 | op = 'move/16' 654 | if opcode == 0x06: 655 | op = 'move-wide/16' 656 | if opcode == 0x09: 657 | op = 'move-object/16' 658 | AAAA = reverse_hex(insns[offset + 2:offset + 6]) 659 | BBBB = reverse_hex(insns[offset + 6:offset + 10]) 660 | 661 | decodedInstruction.op = op 662 | decodedInstruction.vA = int(AAAA, 16) 663 | decodedInstruction.vB = int(BBBB, 16) 664 | decodedInstruction.smaliCode = '%s v%s, v%s' % (op, AAAA, BBBB) 665 | decodedInstruction.offset = offset 666 | decodedInstruction.length = 10 667 | 668 | elif formatIns == '31i': 669 | # Format: AA|op BBBBlo BBBBhi <=> op vAA, #+BBBBBBBB 670 | op = '????' 671 | # (1) opcode=14 const vAA, #+BBBBBBBB 672 | if opcode == 0x14: 673 | op = 'const' 674 | # (2) opcode=17 const-wide/32 vAA, #+BBBBBBBB 675 | if opcode == 0x17: 676 | op = 'const-wide/32' 677 | 678 | AA = int(insns[offset + 2:offset + 4], 16) 679 | BBBBBBBB = reverse_hex(insns[offset + 4:offset + 12]) 680 | 681 | decodedInstruction.op = op 682 | decodedInstruction.vA = AA 683 | decodedInstruction.vB = int(BBBBBBBB, 16) 684 | decodedInstruction.smaliCode = '%s v%d, #+%s' % (op, AA, BBBBBBBB) 685 | decodedInstruction.offset = offset 686 | decodedInstruction.length = 12 687 | 688 | elif formatIns == '31t': 689 | # Format: AA|op BBBBlo BBBBhi <=> op vAA, +BBBBBBBB 690 | op = '????' 691 | # (1) opcode=26 fill-array-data vAA, +BBBBBBBB 692 | # (2) opcode=2b packed-switch vAA, +BBBBBBBB 693 | # (3) opcode=2c sparse-switch vAA, +BBBBBBBB 694 | if opcode == 0x26: 695 | op = 'fill-array-data' 696 | if opcode == 0x2b: 697 | op = 'packed-switch' 698 | if opcode == 0x2c: 699 | op = 'sparse-switch' 700 | 701 | AA = int(insns[offset + 2:offset + 4], 16) 702 | BBBBBBBB = reverse_hex(insns[offset + 4:offset + 12]) 703 | pseudo_instructions_offset = int(int(BBBBBBBB, 16) + byteCounts) 704 | retVal = parsePseudoInstruction(byteCounts, insns, pseudo_instructions_offset * 4) 705 | 706 | decodedInstruction.op = op 707 | decodedInstruction.vA = AA 708 | decodedInstruction.vB = int(BBBBBBBB, 16) 709 | decodedInstruction.smaliCode = '%s v%d, %08x // +%s, %s' % (op, AA, pseudo_instructions_offset, BBBBBBBB, retVal) 710 | decodedInstruction.offset = offset 711 | decodedInstruction.length = 12 712 | 713 | elif formatIns == '31c': 714 | # Format: AA|op BBBBlo BBBBhi <=> op vAA, thing@BBBBBBBB 715 | op = '????' 716 | indexStr = '' 717 | 718 | AA = int(insns[offset + 2:offset + 4], 16) 719 | BBBBBBBB = reverse_hex(insns[offset + 4:offset + 12]) 720 | 721 | # (1) opcode=1b const-string/jumbo vAA, string@BBBBBBBB 722 | if opcode == 0x1b: 723 | op = 'const-string/jumbo' 724 | indexStr = dexFile.DexStringIdList[int(BBBBBBBB, 16)] 725 | 726 | decodedInstruction.op = op 727 | decodedInstruction.vA = AA 728 | decodedInstruction.vB = BBBBBBBB 729 | decodedInstruction.smaliCode = '%s v%d, string@%s //%s' % (op, AA, BBBBBBBB, indexStr) 730 | decodedInstruction.offset = offset 731 | decodedInstruction.length = 12 732 | 733 | elif formatIns == '35c': 734 | # Format: A|G|op BBBB F|E|D|C 735 | indexType = '????' 736 | op = '????' 737 | indexStr = '' 738 | 739 | A = int(insns[offset + 2:offset + 3], 16) 740 | G = int(insns[offset + 3:offset + 4], 16) 741 | BBBB = reverse_hex(insns[offset + 4:offset + 8]) 742 | 743 | registerStr = reverse_hex(insns[offset + 8:offset + 12]) 744 | F = int(registerStr[:1], 16) 745 | E = int(registerStr[1:2], 16) 746 | D = int(registerStr[2:3], 16) 747 | C = int(registerStr[3:4], 16) 748 | 749 | # (1) opcode=24 filled-new-array {vC, vD, vE, vF, vG}, type@BBBB 750 | if opcode == 0x24: 751 | op = 'filled-new-array' 752 | indexType = 'type' 753 | indexStr = dexFile.DexTypeIdList[int(BBBB, 16)] 754 | # (2) opcode=62..72 invoke-kind {vC, vD, vE, vF, vG}, method@BBBB 755 | if opcode >= 0x6e and opcode <= 0x72: 756 | invoke_kind = ['invoke-virtual', 'invoke-super', 'invoke-direct', 'invoke-static', 'invoke-interface'] 757 | op = invoke_kind[opcode-0x6e] 758 | indexType = 'method' 759 | 760 | dexMethodIdObj = dexFile.DexMethodIdList[int(BBBB, 16)] 761 | indexStr = dexMethodIdObj.toString(dexFile) 762 | decodedInstruction.getApi = dexMethodIdObj.toApi(dexFile) 763 | 764 | registers = None 765 | if A == 0: # [A=0] op {}, kind@BBBB 766 | decodedInstruction.op = op 767 | decodedInstruction.vA = A 768 | decodedInstruction.vB = int(BBBB, 16) 769 | decodedInstruction.indexType = indexType 770 | decodedInstruction.smaliCode = '%s {}, %s@%s //%s' % (op, indexType, BBBB, indexStr) 771 | decodedInstruction.offset = offset 772 | decodedInstruction.length = 12 773 | 774 | elif A == 1: # [A=1] op {vC}, kind@BBBB 775 | decodedInstruction.op = op 776 | decodedInstruction.vA = A 777 | decodedInstruction.vB = int(BBBB, 16) 778 | decodedInstruction.vC = C 779 | decodedInstruction.indexType = indexType 780 | decodedInstruction.smaliCode = '%s {v%d}, %s@%s //%s' % (op, C, indexType, BBBB, indexStr) 781 | decodedInstruction.offset = offset 782 | decodedInstruction.length = 12 783 | 784 | elif A == 2: # [A=2] op {vC, vD}, kind@BBBB 785 | decodedInstruction.op = op 786 | decodedInstruction.vA = A 787 | decodedInstruction.vB = int(BBBB, 16) 788 | decodedInstruction.vC = C 789 | decodedInstruction.vD = D 790 | decodedInstruction.indexType = indexType 791 | decodedInstruction.smaliCode = '%s {v%d, v%d}, %s@%s //%s' % (op, C, D, indexType, BBBB, indexStr) 792 | decodedInstruction.offset = offset 793 | decodedInstruction.length = 12 794 | 795 | elif A == 3: # [A=3] op {vC, vD, vE}, kind@BBBB 796 | decodedInstruction.op = op 797 | decodedInstruction.vA = A 798 | decodedInstruction.vB = int(BBBB, 16) 799 | decodedInstruction.vC = C 800 | decodedInstruction.vD = D 801 | decodedInstruction.vE = E 802 | decodedInstruction.indexType = indexType 803 | decodedInstruction.smaliCode = '%s {v%d, v%d, v%d}, %s@%s //%s' % (op, C, D, E, indexType, BBBB, indexStr) 804 | decodedInstruction.offset = offset 805 | decodedInstruction.length = 12 806 | 807 | elif A == 4: # [A=4] op {vC, vD, vE, vF}, kind@BBBB 808 | decodedInstruction.op = op 809 | decodedInstruction.vA = A 810 | decodedInstruction.vB = int(BBBB, 16) 811 | decodedInstruction.vC = C 812 | decodedInstruction.vD = D 813 | decodedInstruction.vE = E 814 | decodedInstruction.vF = F 815 | decodedInstruction.indexType = indexType 816 | decodedInstruction.smaliCode = '%s {v%d, v%d, v%d, v%d}, %s@%s //%s' % (op, C, D, E, F, indexType, BBBB, indexStr) 817 | decodedInstruction.offset = offset 818 | decodedInstruction.length = 12 819 | 820 | elif A == 5: # [A=5] op {vC, vD, vE, vF, vG}, type@BBBB 821 | decodedInstruction.op = op 822 | decodedInstruction.vA = A 823 | decodedInstruction.vB = int(BBBB, 16) 824 | decodedInstruction.vC = C 825 | decodedInstruction.vD = D 826 | decodedInstruction.vE = E 827 | decodedInstruction.vF = F 828 | decodedInstruction.vG = G 829 | decodedInstruction.indexType = indexType 830 | decodedInstruction.smaliCode = '%s {v%d, v%d, v%d, v%d, %d}, %s@%s //%s' % (op, C, D, E, F, G, indexType, BBBB, indexStr) 831 | decodedInstruction.offset = offset 832 | decodedInstruction.length = 12 833 | 834 | elif formatIns == '35ms': 835 | # Format: A|G|op BBBB F|E|D|C 836 | # 无opcode 837 | pass 838 | 839 | elif formatIns == '35mi': 840 | # Format: A|G|op BBBB F|E|D|C 841 | # 无opcode 842 | pass 843 | 844 | elif formatIns == '3rc': 845 | # Format: AA|op BBBB CCCC <=> op {vCCCC .. vNNNN} [method|type]@BBBB 846 | op = '????' 847 | indexType = '????' 848 | indexStr = '' 849 | 850 | AA = int(insns[offset + 2:offset + 4], 16) 851 | BBBB = reverse_hex(insns[offset + 4:offset + 8]) 852 | CCCC = int(reverse_hex(insns[offset + 8:offset + 12]), 16) 853 | N = AA + CCCC - 1 854 | 855 | # (1) opcode=25 filled-new-array/range {vCCCC .. vNNNN}, type@BBBB 856 | if opcode == 0x25: 857 | op = 'fiiled-new-array/range' 858 | indexType = 'type' 859 | indexStr = dexFile.DexTypeIdList[int(BBBB, 16)] 860 | # (2) opcode=74..78 invoke-kind/range {vCCCC .. vNNNN}, method@BBBB 861 | if opcode >= 0x74 and opcode <= 0x78: 862 | ops = ['invoke-virtual/range', 'invoke-super/range', 'invoke-direct/range', 'invoke-static/range', 'invoke-intenrface/range'] 863 | op = ops[opcode - 0x74] 864 | indexType = 'method' 865 | dexMethodIdObj = dexFile.DexMethodIdList[int(BBBB, 16)] 866 | indexStr = dexMethodIdObj.toString(dexFile) 867 | 868 | registers = '' 869 | for i in range(N): 870 | registers += 'v' + str(CCCC + i) + ',' 871 | 872 | decodedInstruction.op = op 873 | decodedInstruction.vA = AA 874 | decodedInstruction.vB = int(BBBB, 16) 875 | decodedInstruction.vC = CCCC 876 | decodedInstruction.indexType = indexType 877 | decodedInstruction.smaliCode = '%s {%s} %s@%s //%s' % (op, registers, indexType, BBBB, indexStr) 878 | decodedInstruction.offset = offset 879 | decodedInstruction.length = 12 880 | 881 | elif formatIns == '3rms': 882 | # Format: AA|op BBBB CCCC <=> op {vCCCC .. vNNNN}, vtaboff@BBBB 883 | # 无opcode 884 | pass 885 | elif formatIns == '3rmi': 886 | # Format: AA|op BBBB CCCC <=> op {vCCCC .. vNNNN}, inline@BBBB 887 | # 无opcode 888 | pass 889 | elif formatIns == '51l': 890 | # Format: AA|op BBBBlo BBBB BBBB BBBBhi <=>op vAA,#+BBBBBBBBBBBBBBBB 891 | # (1) opcode=18 const-wide vAA, #+BBBBBBBBBBBBBBBB 892 | if opcode == 0x18: 893 | AA = int(insns[offset+2:offset+4], 16) 894 | BBBBBBBBBBBBBBBB = reverse_hex(insns[offset+4:offset+20]) 895 | 896 | decodedInstruction.op = 'const-wide' 897 | decodedInstruction.vA = AA 898 | decodedInstruction.vB = int(BBBBBBBBBBBBBBBB, 16) 899 | decodedInstruction.smaliCode = 'const-wide v%d, #+%s' % (AA, BBBBBBBBBBBBBBBB) 900 | decodedInstruction.offset = offset 901 | decodedInstruction.length = 20 902 | 903 | 904 | elif formatIns == '33x': 905 | # Format: exop BB|AA CCCC <=> exop vAA, vBB, vCCCC 906 | # 无opcode 907 | pass 908 | elif formatIns == '32s': 909 | # Format: exop BB|AA CCCC <=> exop vAA, vBB, #+CCCC 910 | # 无opcode 911 | pass 912 | elif formatIns == '40sc': 913 | # Format: exop BBBBlo BBBBhi AAAA <=> exop AAAA, kind@BBBBBBBB 914 | # 无opcode 915 | pass 916 | 917 | ''' 918 | expaneded opcode 919 | opcode为ff,表示后面还有二级opcode 920 | ''' 921 | if opcode == 0xff: 922 | expanded_opcode = int(reverse_hex(insns[offset:offset + 4]), 16) 923 | formatIns, _ = getOpCode(expanded_opcode) 924 | 925 | if formatIns == '41c': 926 | expanded_opcode = int(reverse_hex(insns[offset:offset + 4]), 16) 927 | # Format: exop BBBBlo BBBBhi AAAA <=> exop vAAAA, [field|type]@BBBBBBBB 928 | indexType = '????' 929 | op = '????' 930 | # (1) expanded_opcode=00ff const-class/jumbo vAAAA, type@BBBBBBBB 931 | if expanded_opcode == 0x00ff: 932 | op = 'const-class/jumbo' 933 | indexType = 'type' 934 | # (2) expanded_opcode=01ff check-cast/jumbo vAAAA, type@BBBBBBBB 935 | elif expanded_opcode == 0x01ff: 936 | op = 'check-cast/jumbo' 937 | indexType = 'type' 938 | # (3) expanded_opcode=03ff new-instance/jumbo vAAAA, type@BBBBBBBB 939 | elif expanded_opcode == 0x03ff: 940 | op = 'new-instance/jumbo' 941 | indexType = 'type' 942 | # (4) expanded_opcode=14ff..21ff sstaticop/jumbo vAAAA, field@BBBBBBBB 943 | elif expanded_opcode >= 0x14ff and expanded_opcode <= 0x21ff: 944 | ops = ['sget/jumbo', 'sget-wide/jumbo', 'sget-object/jumbo', 'sget-boolean/jumbo', 'sget-byte/jumbo', 945 | 'sget-char/jumbo', 'sget-short/jumbo', 'sput/jumbo', 'sput-wide/jumbo', 'sput-object/jumbo', 946 | 'sput-boolean/jumbo', 'sput-byte/jumbo', 'sput-char/jumbo', 'sput-short/jumbo'] 947 | op = ops[expanded_opcode - 0x14ff] 948 | indexType = 'field' 949 | 950 | BBBBBBBB = int(reverse_hex(insns[offset + 4:offset + 12]), 16) 951 | AAAA = int(reverse_hex(insns[offset + 12:offset + 16]), 16) 952 | 953 | decodedInstruction.op = op 954 | decodedInstruction.vA = AAAA 955 | decodedInstruction.vB = BBBBBBBB 956 | decodedInstruction.indexType = indexType 957 | decodedInstruction.smaliCode = '%s v%d, %s@%s' % (op, AAAA, indexType, hex(BBBBBBBB)[2:]) 958 | decodedInstruction.offset = offset 959 | decodedInstruction.length = 16 960 | 961 | elif formatIns == '52c': 962 | expanded_opcode = int(reverse_hex(insns[offset:offset + 4]), 16) 963 | indexType = '????' 964 | op = '????' 965 | # Format: exop CCCClo CCCChi AAAA BBBB <=> exop vAAAA, vBBBB, [field|type]@CCCCCCCC 966 | # (1) expanded_opcode=02ff instance-of/jumbo vAAAA, vBBBB, type@CCCCCCCC 967 | if expanded_opcode == 0x02ff: 968 | op = 'instance-of/jumbo' 969 | indexType = 'type' 970 | # (2) expanded_opcode=04ff new-array/jumbo vAAAA, vBBBB, type@CCCCCCCC 971 | if expanded_opcode == 0x02ff: 972 | op = 'new-array/jumbo' 973 | indexType = 'type' 974 | # (3) expanded_opcode=06ff..13ff iinstanceop/jumbo vAAAA, vBBBB, field@CCCCCCCC 975 | if expanded_opcode >= 0x06ff and expanded_opcode <= 0x13ff: 976 | ops = ['iget/jumbo', 'iget-wide/jumbo', 'iget-object/jumbo', 'iget-boolean/jumbo', 'iget-byte/jumbo', 977 | 'iget-char/jumbo', 'iget-short/jumbo', 'iput/jumbo', 'iput-wide/jumbo', 'iput-object/jumbo', 978 | 'iput-boolean/jumbo', 'iput-byte/jumbo', 'iput-char/jumbo', 'iput-short/jumbo'] 979 | op = ops[expanded_opcode - 0x06ff] 980 | indexType = 'field' 981 | CCCCCCCC = int(reverse_hex(insns[offset + 4:offset + 12]), 16) 982 | AAAA = int(reverse_hex(insns[offset + 12:offset + 16]), 16) 983 | BBBB = int(reverse_hex(insns[offset + 16:offset + 20]), 16) 984 | 985 | decodedInstruction.op = op 986 | decodedInstruction.vA = AAAA 987 | decodedInstruction.vB = BBBB 988 | decodedInstruction.vC = CCCCCCCC 989 | decodedInstruction.indexType = indexType 990 | decodedInstruction.smaliCode = '%s v%d, v%d %s@%s' % (op, AAAA, BBBB, indexType, hex(CCCCCCCC)[2:]) 991 | decodedInstruction.offset = offset 992 | decodedInstruction.length = 20 993 | 994 | elif formatIns == '5rc': 995 | expanded_opcode = int(reverse_hex(insns[offset:offset + 4]), 16) 996 | indexType = '????' 997 | op = '????' 998 | # Format: exop BBBBlo BBBBhi AAAA CCCC <=> exop {vCCCC .. vNNNN}, [method|type]@BBBBBBBB 999 | # (1) expanded_opcode=05ff filled-new-array/jumbo {vCCCC .. vNNNN}, type@BBBBBBBB 1000 | if expanded_opcode == 0x05ff: 1001 | op = 'filled-new-array/jumbo' 1002 | indexType = 'type' 1003 | # (2) expanded_opcode=22ff..26ff invoke-kind/jumbo {vCCCC .. vNNNN}, method@BBBBBBBB 1004 | if expanded_opcode >= 0x22ff and expanded_opcode <= 0x26ff: 1005 | ops= ['invoke-virtual/jumbo', 'invoke-super/jumbo', 'invoke-direct/jumbo', 1006 | 'invoke-static/jumbo', 'invoke-interface/jumbo'] 1007 | op = ops[expanded_opcode - 0x22ff] 1008 | indexType = 'method' 1009 | BBBBBBBB = int(reverse_hex(insns[offset + 4:offset + 12]), 16) 1010 | AAAA = int(reverse_hex(insns[offset + 12:offset + 16]), 16) 1011 | CCCC = int(reverse_hex(insns[offset + 16:offset + 20]), 16) 1012 | N = AAAA + CCCC - 1 1013 | 1014 | registers = '' 1015 | for i in range(N): 1016 | registers += 'v' + str(CCCC + i) + ',' 1017 | 1018 | decodedInstruction.op = op 1019 | decodedInstruction.vA = AAAA 1020 | decodedInstruction.vB = BBBBBBBB 1021 | decodedInstruction.vC = CCCC 1022 | decodedInstruction.indexType = indexType 1023 | decodedInstruction.smaliCode = '%s {%s} %s@%s' % (op, registers, indexType, hex(BBBBBBBB)[2:]) 1024 | decodedInstruction.offset = offset 1025 | decodedInstruction.length = 20 1026 | 1027 | return decodedInstruction 1028 | 1029 | def parsePseudoInstruction(opcode_address, insns, offset): 1030 | offset = int(offset) 1031 | ident = reverse_hex(insns[offset:offset+4]) 1032 | # packed-switch-payload Format 1033 | if ident == '0100': 1034 | size = int(reverse_hex(insns[offset + 4:offset + 8]), 16) 1035 | first_key = int(reverse_hex(insns[offset+8:offset+16]), 16) 1036 | targets = [] 1037 | sb = '' 1038 | for i in range(size): 1039 | _v = int(reverse_hex(insns[offset+16+8*i:offset+16+8*(i+1)]), 16) 1040 | targets.append(_v) 1041 | sb += ' \t%-16scase %d: goto %s\n' % ('', first_key+i, hex(_v + opcode_address)) 1042 | return '\n'+sb 1043 | # sparse-switch-payload Format 1044 | if ident == '0200': 1045 | size = int(reverse_hex(insns[offset + 4:offset + 8]), 16) 1046 | keys = [] 1047 | targets = [] 1048 | sb = '' 1049 | for i in range(size): 1050 | keys.append(int(reverse_hex(insns[offset+8+8*i:offset+8+8*(i+1)]), 16)) 1051 | _v = int(reverse_hex(insns[(offset+8+8*i)+size*8:(offset+8+8*(i+1))+size*8]), 16) 1052 | 1053 | hexNum = _v + opcode_address 1054 | if hexNum > (0xffffffff+1): 1055 | hexNum -= 0xffffffff+1 1056 | tmp = hex(hexNum) 1057 | if tmp.endswith('L'): 1058 | tmp = tmp[:-1] 1059 | targets.append(tmp) 1060 | else: 1061 | targets.append(hex(hexNum)) 1062 | sb += ' \t%-16scase %d: goto %s\n' % ('', keys[i], targets[i]) 1063 | return '\n'+sb 1064 | # fill-array-data-payload Format 1065 | if ident == '0300': 1066 | element_width = int(reverse_hex(insns[offset + 4:offset + 8]), 16) 1067 | size = int(reverse_hex(insns[offset + 8:offset + 16]), 16) 1068 | data = [] 1069 | 1070 | dataStr = '[' 1071 | for i in range(size): 1072 | val = insns[offset + 16 + 2*element_width*i:offset + 16 + 2*element_width*(i+1)] 1073 | data.append(val) 1074 | dataStr += val + ',' 1075 | dataStr += ']' 1076 | return dataStr 1077 | 1078 | 1079 | MAP_ITEM_TYPE_CODES = { 1080 | 0x0000 : "kDexTypeHeaderItem", 1081 | 0x0001 : "kDexTypeStringIdItem", 1082 | 0x0002 : "kDexTypeTypeIdItem", 1083 | 0x0003 : "kDexTypeProtoIdItem", 1084 | 0x0004 : "kDexTypeFieldIdItem", 1085 | 0x0005 : "kDexTypeMethodIdItem", 1086 | 0x0006 : "kDexTypeClassDefItem", 1087 | 0x1000 : "kDexTypeMapList", 1088 | 0x1001 : "kDexTypeTypeList", 1089 | 0x1002 : "kDexTypeAnnotationSetRefList", 1090 | 0x1003 : "kDexTypeAnnotationSetItem", 1091 | 0x2000 : "kDexTypeClassDataItem", 1092 | 0x2001 : "kDexTypeCodeItem", 1093 | 0x2002 : "kDexTypeStringDataItem", 1094 | 0x2003 : "kDexTypeDebugInfoItem", 1095 | 0x2004 : "kDexTypeAnnotationItem", 1096 | 0x2005 : "kDexTypeEncodedArrayItem", 1097 | 0x2006 : "kDexTypeAnnotationsDirectoryItem", 1098 | } 1099 | 1100 | 1101 | class DexFile(object): 1102 | """docstring for DexFile""" 1103 | def __init__(self, filepath): 1104 | super(DexFile, self).__init__() 1105 | self.filepath = filepath 1106 | # Dex文件头部 1107 | self.DexHeader = DexHeader() 1108 | # 字符串索引区 1109 | self.DexStringIdList = [] 1110 | # 类型索引区 1111 | self.DexTypeIdList = [] 1112 | # 字段索引区 1113 | self.DexFieldIdList = [] 1114 | # 原型索引区 1115 | self.DexProtoIdList = [] 1116 | # 方法索引区 1117 | self.DexMethodIdList = [] 1118 | # 类定义区 1119 | self.dexClassDefList = [] 1120 | 1121 | self.init_header(self.filepath) # 初始化dex header 1122 | self.init_DexStringId() # 初始化 DexStringId index table 1123 | self.init_DexTypeId() # 初始化DexTypeId index table 1124 | self.init_DexProtoId() # 初始化DexProtoId index table 1125 | self.int_DexFieldId() # 初始化DexFieldId index table 1126 | self.init_DexMethodId() # 初始化DexMethodId index table 1127 | self.init_DexClassDef() # 初始化DexClassDef类定义区 1128 | 1129 | 1130 | def init_header(self, filepath): 1131 | f = open(filepath, "rb") 1132 | 1133 | self.DexHeader.f = f 1134 | 1135 | f.seek(0x0, 0) 1136 | 1137 | self.DexHeader.magic = binascii.b2a_hex(f.read(8)) 1138 | 1139 | f.seek(0x8, 0) 1140 | self.DexHeader.checksum = reverse_hex(binascii.b2a_hex(f.read(4))) 1141 | 1142 | f.seek(0xc, 0) 1143 | self.DexHeader.signature = binascii.b2a_hex(f.read(20)) 1144 | 1145 | f.seek(0x20, 0) 1146 | self.DexHeader.file_size = reverse_hex(binascii.b2a_hex(f.read(4))) 1147 | 1148 | f.seek(0x24, 0) 1149 | self.DexHeader.header_size = reverse_hex(binascii.b2a_hex(f.read(4))) 1150 | 1151 | f.seek(0x28, 0) 1152 | self.DexHeader.endian_tag = reverse_hex(binascii.b2a_hex(f.read(4))) 1153 | 1154 | f.seek(0x2c, 0) 1155 | self.DexHeader.link_size = reverse_hex(binascii.b2a_hex(f.read(4))) 1156 | 1157 | f.seek(0x30, 0) 1158 | self.DexHeader.link_off = reverse_hex(binascii.b2a_hex(f.read(4))) 1159 | 1160 | f.seek(0x34, 0) 1161 | self.DexHeader.map_off = reverse_hex(binascii.b2a_hex(f.read(4))) 1162 | 1163 | f.seek(0x38, 0) 1164 | self.DexHeader.string_ids_size = reverse_hex(binascii.b2a_hex(f.read(4))) 1165 | 1166 | f.seek(0x3c, 0) 1167 | self.DexHeader.string_ids_off = reverse_hex(binascii.b2a_hex(f.read(4))) 1168 | 1169 | f.seek(0x40, 0) 1170 | self.DexHeader.type_ids_size = reverse_hex(binascii.b2a_hex(f.read(4))) 1171 | 1172 | f.seek(0x44, 0) 1173 | self.DexHeader.type_ids_off = reverse_hex(binascii.b2a_hex(f.read(4))) 1174 | 1175 | f.seek(0x48, 0) 1176 | self.DexHeader.proto_ids_size = reverse_hex(binascii.b2a_hex(f.read(4))) 1177 | 1178 | f.seek(0x4c, 0) 1179 | self.DexHeader.proto_ids_off = reverse_hex(binascii.b2a_hex(f.read(4))) 1180 | 1181 | f.seek(0x50, 0) 1182 | self.DexHeader.field_ids_size = reverse_hex(binascii.b2a_hex(f.read(4))) 1183 | 1184 | f.seek(0x54, 0) 1185 | self.DexHeader.field_ids_off = reverse_hex(binascii.b2a_hex(f.read(4))) 1186 | 1187 | f.seek(0x58, 0) 1188 | self.DexHeader.method_ids_size = reverse_hex(binascii.b2a_hex(f.read(4))) 1189 | 1190 | f.seek(0x5c, 0) 1191 | self.DexHeader.method_ids_off = reverse_hex(binascii.b2a_hex(f.read(4))) 1192 | 1193 | f.seek(0x60, 0) 1194 | self.DexHeader.class_defs_size = reverse_hex(binascii.b2a_hex(f.read(4))) 1195 | 1196 | f.seek(0x64, 0) 1197 | self.DexHeader.class_defs_off = reverse_hex(binascii.b2a_hex(f.read(4))) 1198 | 1199 | f.seek(0x68, 0) 1200 | self.DexHeader.data_size = reverse_hex(binascii.b2a_hex(f.read(4))) 1201 | 1202 | f.seek(0x6c, 0) 1203 | self.DexHeader.data_off = reverse_hex(binascii.b2a_hex(f.read(4))) 1204 | 1205 | def print_header(self): 1206 | print('[+] magic:\t0x' + self.DexHeader.magic) 1207 | print('[+] checksum:\t0x' + self.DexHeader.checksum) 1208 | print('[+] signature:\t' + self.DexHeader.signature) 1209 | print('[+] file_size:\t0x' + self.DexHeader.file_size) 1210 | print('[+] header_size:\t0x' + self.DexHeader.header_size) 1211 | print('[+] endian_tag:\t0x' + self.DexHeader.endian_tag) 1212 | print('[+] link_size:\t0x' + self.DexHeader.link_size) 1213 | print('[+] link_off:\t0x' + self.DexHeader.link_off) 1214 | print('[+] map_off:\t0x' + self.DexHeader.map_off) 1215 | print('[+] string_ids_size:\t0x' + self.DexHeader.string_ids_size) 1216 | print('[+] string_ids_off:\t0x' + self.DexHeader.string_ids_off) 1217 | print('[+] type_ids_size:\t0x' + self.DexHeader.type_ids_size) 1218 | print('[+] type_ids_off:\t0x' + self.DexHeader.type_ids_off) 1219 | print('[+] proto_ids_size:\t0x' + self.DexHeader.proto_ids_size) 1220 | print('[+] proto_ids_off:\t0x' + self.DexHeader.proto_ids_off) 1221 | print('[+] field_ids_size:\t0x' + self.DexHeader.field_ids_size) 1222 | print('[+] field_ids_off:\t0x' + self.DexHeader.field_ids_off) 1223 | print('[+] method_ids_size:\t0x' + self.DexHeader.method_ids_size) 1224 | print('[+] method_ids_off:\t0x' + self.DexHeader.method_ids_off) 1225 | print('[+] class_defs_size:\t0x' + self.DexHeader.class_defs_size) 1226 | print('[+] class_defs_off:\t0x' + self.DexHeader.class_defs_off) 1227 | print('[+] data_size:\t0x' + self.DexHeader.data_size) 1228 | print('[+] data_off:\t0x' + self.DexHeader.data_off) 1229 | 1230 | def print_DexMapList(self): 1231 | """ 1232 | typedef struct DexMapList { 1233 | u4 size; /* #of entries in list */ 1234 | DexMapItem list[1]; /* entries */ 1235 | } DexMapList; 1236 | """ 1237 | map_off_int = int(self.DexHeader.map_off, 16) 1238 | 1239 | #u4 size 1240 | self.DexHeader.f.seek(map_off_int, 0) 1241 | size_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1242 | size = int(size_hex, 16) 1243 | 1244 | for index in range(size): 1245 | # DexMapItem list[] 1246 | self.print_DexMapItem(map_off_int+4, index) 1247 | 1248 | def print_DexMapItem(self, map_off, index): 1249 | """ 1250 | typedef struct DexMapItem { 1251 | u2 type; /* type code (see kDexType* above) */ 1252 | u2 unused; 1253 | u4 size; /* count of items of the indicated type */ 1254 | u4 offset; /* file offset to the start of data */ 1255 | } DexMapItem; 1256 | """ 1257 | #u2 type 1258 | self.DexHeader.f.seek(map_off + index*12, 0) 1259 | dexType = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(2))) 1260 | 1261 | #u2 unused 1262 | self.DexHeader.f.seek(map_off + index*12 + 2, 0) 1263 | unused = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(2))) 1264 | 1265 | #u4 size 1266 | self.DexHeader.f.seek(map_off + index*12 + 4, 0) 1267 | size = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1268 | 1269 | #u4 offset 1270 | self.DexHeader.f.seek(map_off + index*12 + 8, 0) 1271 | offset = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1272 | 1273 | print('\n') 1274 | print('[+] #%d DexMapItem:\t' % index) 1275 | print(' u2 dexType\t%s #%s' % (dexType, MAP_ITEM_TYPE_CODES[int(dexType, 16)])) 1276 | print(' u2 unused\t' + unused) 1277 | print(' u4 size\t' + size) 1278 | print(' u4 offset\t' + offset) 1279 | 1280 | def init_DexStringId(self): 1281 | """ 1282 | typedef struct DexStringId { 1283 | u4 stringDataOff; /* file offset to string_data_item */ 1284 | } DexStringId; 1285 | """ 1286 | string_ids_off_int = int(self.DexHeader.string_ids_off, 16) 1287 | string_ids_size_int = int(self.DexHeader.string_ids_size, 16) 1288 | 1289 | for index in range(string_ids_size_int): 1290 | # string offset 1291 | self.DexHeader.f.seek(string_ids_off_int + index*4, 0) 1292 | 1293 | some_data = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1294 | 1295 | try: 1296 | string_data_off = int(some_data, 16) 1297 | except: 1298 | print('Something is wrong with ', some_data) 1299 | self.DexHeader.f.seek(string_data_off, 0) 1300 | 1301 | # length of str 1302 | self.DexHeader.f.read(1) 1303 | 1304 | length = 0 1305 | 1306 | try: 1307 | while True: 1308 | input_data = binascii.b2a_hex(self.DexHeader.f.read(1)) 1309 | some_data = reverse_hex(input_data) 1310 | some_data = int(some_data, 16) 1311 | if some_data == 0: break 1312 | length += 1 1313 | except: 1314 | print('Something went wrong with ', some_data, input_data) 1315 | raise 1316 | 1317 | self.DexHeader.f.seek(string_data_off + 1,0) 1318 | dex_str = self.DexHeader.f.read(length) 1319 | self.DexHeader.f.read(1) # remove \x00 1320 | string_data_off += (length + 2) # + \0 + size bit 1321 | 1322 | # self.DexStringIdList.append(dex_str.decode('utf-8')) 1323 | 1324 | try: 1325 | dex_str_string = dex_str.decode() 1326 | except: 1327 | dex_str_string = '' 1328 | 1329 | self.DexStringIdList.append(dex_str_string) 1330 | 1331 | def print_DexStringId(self): 1332 | 1333 | print('\n') 1334 | print('[+] DexStringId:') 1335 | for index in range(len(self.DexStringIdList)): 1336 | print(' #%s %s' % (hex(index), self.DexStringIdList[index])) 1337 | 1338 | def init_DexTypeId(self): 1339 | type_ids_off_int = int(self.DexHeader.type_ids_off, 16) 1340 | type_ids_size_int = int(self.DexHeader.type_ids_size, 16) 1341 | 1342 | self.DexHeader.f.seek(type_ids_off_int, 0) 1343 | 1344 | for index in range(type_ids_size_int): 1345 | descriptorIdx_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1346 | descriptorIdx_int = int(descriptorIdx_hex, 16) 1347 | 1348 | self.DexTypeIdList.append(descriptorIdx_int) 1349 | 1350 | def print_DexTypeId(self): 1351 | print('\n') 1352 | print('[+] DexTypeId:') 1353 | for index in range(len(self.DexTypeIdList)): 1354 | print(' #%s #%s' % (hex(index), self.getDexTypeId(index))) 1355 | 1356 | def init_DexProtoId(self): 1357 | proto_ids_size_int = int(self.DexHeader.proto_ids_size, 16) 1358 | proto_ids_off_int = int(self.DexHeader.proto_ids_off, 16) 1359 | 1360 | for index in range(proto_ids_size_int): 1361 | self.DexHeader.f.seek(proto_ids_off_int+index*12, 0) 1362 | dexProtoIdObj = DexProtoId() 1363 | # u4 shortyIdx 1364 | shortyIdx_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1365 | shortyIdx = int(shortyIdx_hex, 16) 1366 | # u4 returnTypeIdx 1367 | returnTypeIdx_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1368 | returnTypeIdx = int(returnTypeIdx_hex, 16) 1369 | # u4 parametersOff 1370 | parametersOff_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1371 | parametersOff = int(parametersOff_hex, 16) 1372 | 1373 | dexProtoIdObj.shortyIdx = shortyIdx 1374 | dexProtoIdObj.returnTypeIdx = returnTypeIdx 1375 | dexProtoIdObj.parameterOff = parametersOff 1376 | dexProtoIdObj.offset = proto_ids_off_int + index * 12 1377 | dexProtoIdObj.length = 12 1378 | 1379 | if parametersOff == 0: 1380 | dexProtoIdObj.dexTypeList = None 1381 | self.DexProtoIdList.append(dexProtoIdObj) 1382 | 1383 | continue 1384 | self.DexHeader.f.seek(parametersOff, 0) 1385 | 1386 | parameter_str = "" 1387 | # Struct DexTypeList 1388 | # u4 size 1389 | dexTypeItemSize_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1390 | dexTypeItemSize = int(dexTypeItemSize_hex, 16) 1391 | 1392 | dexTypeListObj = DexTypeList() 1393 | dexTypeListObj.size = dexTypeItemSize 1394 | 1395 | # DexTypeItem list[] 1396 | for i in range(dexTypeItemSize): 1397 | # Struct DexTypeItem 1398 | # u2 typeIdx 1399 | typeIdx_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(2))) 1400 | typeIdx = int(typeIdx_hex, 16) 1401 | dexTypeListObj.list.append(typeIdx) 1402 | 1403 | dexProtoIdObj.dexTypeList = dexTypeListObj 1404 | self.DexProtoIdList.append(dexProtoIdObj) 1405 | 1406 | def getDexStringId(self, shortyIdx): 1407 | return self.DexStringIdList[shortyIdx] 1408 | 1409 | def getDexTypeId(self, returnTypeIdx): 1410 | return self.DexStringIdList[self.DexTypeIdList[returnTypeIdx]] 1411 | 1412 | def print_DexProtoId(self): 1413 | proto_ids_off_int = int(self.DexHeader.proto_ids_off, 16) 1414 | self.DexHeader.f.seek(proto_ids_off_int, 0) 1415 | print('\n') 1416 | print('[+] DexProtoId:') 1417 | for index in range(len(self.DexProtoIdList)): 1418 | dexProtoidObj = self.DexProtoIdList[index] 1419 | 1420 | shortyIdxStr = self.getDexStringId(dexProtoidObj.shortyIdx) 1421 | returnTypeIdxStr = self.getDexStringId(dexProtoidObj.returnTypeIdx) 1422 | 1423 | print(' #%s (%s~%s)' % (hex(index), hex(dexProtoidObj.offset), hex(dexProtoidObj.offset + dexProtoidObj.length))) 1424 | print(' DexProtoId[%d]->shortyIdx= %s\t#%s' % (index,hex(dexProtoidObj.shortyIdx), shortyIdxStr)) 1425 | print(' DexProtoId[%d]->returnTypeIdx= %s\t#%s' % (index, hex(dexProtoidObj.returnTypeIdx), returnTypeIdxStr)) 1426 | print(' DexProtoId[%d]->parametersOff= %s' % (index, hex(dexProtoidObj.parameterOff))) 1427 | if dexProtoidObj.dexTypeList: 1428 | print(' DexTypeList->size= %s' % hex(dexProtoidObj.dexTypeList.size)) 1429 | for k in range(dexProtoidObj.dexTypeList.size): 1430 | print(' DexTypeList->list[%d]= %s\t#%s' % (k, hex(dexProtoidObj.dexTypeList.list[k]), self.getDexTypeId(dexProtoidObj.dexTypeList.list[k]))) 1431 | print('') 1432 | 1433 | def int_DexFieldId(self): 1434 | field_ids_off = int(self.DexHeader.field_ids_off, 16) 1435 | field_ids_size = int(self.DexHeader.field_ids_size, 16) 1436 | 1437 | self.DexHeader.f.seek(field_ids_off, 0) 1438 | 1439 | for index in range(field_ids_size): 1440 | # DexFieldId 1441 | dexFieldIdObj = DexFieldId() 1442 | # u2 classIdx 1443 | classIdx_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(2))) 1444 | classIdx = int(classIdx_hex, 16) 1445 | # u2 typeIdx 1446 | typeIdx_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(2))) 1447 | typeIdx = int(typeIdx_hex, 16) 1448 | # u4 nameIdx 1449 | nameIdx_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1450 | nameIdx = int(nameIdx_hex, 16) 1451 | 1452 | dexFieldIdObj.classIdx = classIdx 1453 | dexFieldIdObj.typeIdx = typeIdx 1454 | dexFieldIdObj.nameIdx = nameIdx 1455 | dexFieldIdObj.offset = field_ids_off + index * 8 1456 | dexFieldIdObj.length = 8 1457 | 1458 | self.DexFieldIdList.append(dexFieldIdObj) 1459 | 1460 | def print_DexFieldId(self): 1461 | print('[+] DexFieldId:') 1462 | for index in range(len(self.DexFieldIdList)): 1463 | self.DexHeader.f.seek(self.DexFieldIdList[index].offset, 0) 1464 | # DexFieldId 1465 | # u2 classIdx 1466 | classIdx = self.DexFieldIdList[index].classIdx 1467 | # u2 typeIdx 1468 | typeIdx = self.DexFieldIdList[index].typeIdx 1469 | # u4 nameIdx 1470 | nameIdx = self.DexFieldIdList[index].nameIdx 1471 | 1472 | print(' #%s (%s~%s)' % (hex(index), hex(self.DexFieldIdList[index].offset), hex(self.DexFieldIdList[index].offset + self.DexFieldIdList[index].length))) 1473 | print(' DexFieldId[%d]->classIdx=%s\t#%s' % (index, hex(classIdx), self.getDexStringId(classIdx))) 1474 | print(' DexFieldId[%d]->typeIdx=%s\t#%s' % (index, hex(typeIdx), self.getDexStringId(typeIdx))) 1475 | print(' DexFieldId[%d]->nameIdx=%s\t#%s' % (index, hex(nameIdx), self.getDexStringId(nameIdx))) 1476 | print('') 1477 | 1478 | def init_DexMethodId(self): 1479 | method_ids_off = int(self.DexHeader.method_ids_off, 16) 1480 | method_ids_size = int(self.DexHeader.method_ids_size, 16) 1481 | 1482 | self.DexHeader.f.seek(method_ids_off, 0) 1483 | 1484 | for index in range(method_ids_size): 1485 | # DexMethodId 1486 | dexMethodIdObj = DexMethodId() 1487 | # u2 classIdx 1488 | classIdx_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(2))) 1489 | classIdx = int(classIdx_hex, 16) 1490 | # u2 protoIdx 1491 | protoIdx_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(2))) 1492 | protoIdx = int(protoIdx_hex, 16) 1493 | # u4 nameIdx 1494 | nameIdx_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1495 | nameIdx = int(nameIdx_hex, 16) 1496 | 1497 | dexMethodIdObj.classIdx = classIdx 1498 | dexMethodIdObj.protoIdx = protoIdx 1499 | dexMethodIdObj.nameIdx = nameIdx 1500 | dexMethodIdObj.offset = method_ids_off + index * 8 1501 | dexMethodIdObj.length = 8 1502 | 1503 | self.DexMethodIdList.append(dexMethodIdObj) 1504 | 1505 | def print_DexMethodId(self): 1506 | print('\n') 1507 | print('[+] DexMethodId:') 1508 | for index in range(len(self.DexMethodIdList)): 1509 | # DexMethodId 1510 | # u2 classIdx 1511 | classIdx = self.DexMethodIdList[index].classIdx 1512 | # u2 protoIdx 1513 | protoIdx = self.DexMethodIdList[index].protoIdx 1514 | # u4 nameIdx 1515 | nameIdx = self.DexMethodIdList[index].nameIdx 1516 | 1517 | print(' #%s (%s~%s)' % (hex(index), hex(self.DexMethodIdList[index].offset), hex(self.DexMethodIdList[index].offset + self.DexMethodIdList[index].length))) 1518 | print(' DexMethodId[%d]->classIdx=%s\t#%s' % (index, hex(classIdx), self.getDexTypeId(classIdx))) 1519 | print(' DexMethodId[%d]->protoIdx=%s\t#%s' % (index, hex(protoIdx), self.DexProtoIdList[protoIdx].toString(self))) 1520 | print(' DexMethodId[%d]->nameIdx =%s\t#%s' % (index, hex(nameIdx), self.DexStringIdList[nameIdx])) 1521 | print('') 1522 | 1523 | def init_DexClassDef(self): 1524 | class_defs_size_int = int(self.DexHeader.class_defs_size, 16) 1525 | class_defs_off_int = int(self.DexHeader.class_defs_off, 16) 1526 | 1527 | for index in range(class_defs_size_int): 1528 | dexClassDefObj = DexClassDef() 1529 | self.dexClassDefList.append(dexClassDefObj) 1530 | 1531 | #u4 classIdx 1532 | self.DexHeader.f.seek(class_defs_off_int + index*32, 0) 1533 | classIdx_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1534 | classIdx = int(classIdx_hex, 16) 1535 | 1536 | #u4 accessFlags 1537 | self.DexHeader.f.seek(class_defs_off_int + index*32 + 4, 0) 1538 | accessFlags_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1539 | accessFlags = int(accessFlags_hex, 16) 1540 | 1541 | #u4 superclassIdx 1542 | self.DexHeader.f.seek(class_defs_off_int + index*32 + 8, 0) 1543 | superclassIdx_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1544 | superclassIdx = int(superclassIdx_hex, 16) 1545 | 1546 | #u4 interfaceOff 1547 | self.DexHeader.f.seek(class_defs_off_int + index*32 + 12, 0) 1548 | interfaceOff_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1549 | interfaceOff = int(interfaceOff_hex, 16) 1550 | 1551 | #u4 sourceFieldIdx 1552 | self.DexHeader.f.seek(class_defs_off_int + index*32 + 16, 0) 1553 | sourceFieldIdx_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1554 | sourceFieldIdx = int(sourceFieldIdx_hex, 16) 1555 | 1556 | #u4 annotationsOff 1557 | self.DexHeader.f.seek(class_defs_off_int + index*32 + 20, 0) 1558 | annotationsOff_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1559 | annotationsOff = int(annotationsOff_hex, 16) 1560 | 1561 | #u4 classDataOff 1562 | self.DexHeader.f.seek(class_defs_off_int + index*32 + 24, 0) 1563 | classDataOff_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1564 | classDataOff = int(classDataOff_hex, 16) 1565 | 1566 | #u4 staticValueOff 1567 | self.DexHeader.f.seek(class_defs_off_int + index * 32 + 28, 0) 1568 | staticValueOff_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1569 | staticValueOff = int(staticValueOff_hex, 16) 1570 | 1571 | dexClassDefObj.classIdx = classIdx 1572 | dexClassDefObj.accessFlags = accessFlags 1573 | dexClassDefObj.superclassIdx = superclassIdx 1574 | dexClassDefObj.interfaceOff = interfaceOff 1575 | dexClassDefObj.sourceFieldIdx = sourceFieldIdx 1576 | dexClassDefObj.annotationsOff = annotationsOff 1577 | dexClassDefObj.classDataOff = classDataOff 1578 | dexClassDefObj.staticValueOff = staticValueOff 1579 | dexClassDefObj.offset = class_defs_off_int + index * 32 1580 | dexClassDefObj.length = 32 1581 | 1582 | if classDataOff == 0: 1583 | continue 1584 | 1585 | # 获取DexClassData结构 1586 | ###################################################### 1587 | dexClassDataHeaderOffset = classDataOff 1588 | dexClassDataHeaderLength = 0 1589 | 1590 | # 解析DexClassData结构体中header成员 1591 | self.DexHeader.f.seek(classDataOff, 0) 1592 | dexClassDataHeader = [] 1593 | for i in range(4): 1594 | cur_bytes_hex = binascii.b2a_hex(self.DexHeader.f.read(1)) 1595 | dexClassDataHeaderLength += 1 1596 | cur_bytes = int(cur_bytes_hex, 16) 1597 | value = cur_bytes_hex 1598 | 1599 | while cur_bytes > 0x7f: 1600 | cur_bytes_hex = binascii.b2a_hex(self.DexHeader.f.read(1)) 1601 | dexClassDataHeaderLength += 1 1602 | value += cur_bytes_hex 1603 | cur_bytes = int(cur_bytes_hex, 16) 1604 | dexClassDataHeader.append(value) 1605 | staticFieldsSize = self.readUnsignedLeb128(dexClassDataHeader[0]) 1606 | instanceFieldsSize = self.readUnsignedLeb128(dexClassDataHeader[1]) 1607 | directMethodsSize = self.readUnsignedLeb128(dexClassDataHeader[2]) 1608 | virtualMethodsSize = self.readUnsignedLeb128(dexClassDataHeader[3]) 1609 | 1610 | dexClassDataHeader = DexClassDataHeader() 1611 | dexClassDataHeader.staticFieldsSize = staticFieldsSize 1612 | dexClassDataHeader.instanceFieldsSize = instanceFieldsSize 1613 | dexClassDataHeader.directMethodsSize = directMethodsSize 1614 | dexClassDataHeader.virtualMethodsSize = virtualMethodsSize 1615 | dexClassDataHeader.offset = classDataOff 1616 | dexClassDataHeader.length = dexClassDataHeaderLength 1617 | 1618 | dexClassDefObj.header = dexClassDataHeader 1619 | 1620 | # 解析DexClassData结构体中staticFields、instanceFields、directMethods和virtualMethods成员 1621 | offset = dexClassDataHeader.offset + dexClassDataHeader.length 1622 | # (1)解析DexField* staticFields成员 1623 | """ 1624 | struct DexField{ 1625 | u4 fieldIdx; 1626 | u4 accessFlags; 1627 | } 1628 | """ 1629 | for i in range(staticFieldsSize): 1630 | array = [] 1631 | length = 0 1632 | for j in range(2): 1633 | cur_bytes_hex = binascii.b2a_hex(self.DexHeader.f.read(1)) 1634 | length += 1 1635 | 1636 | cur_bytes = int(cur_bytes_hex, 16) 1637 | value = cur_bytes_hex 1638 | 1639 | while cur_bytes > 0x7f: 1640 | cur_bytes_hex = binascii.b2a_hex(self.DexHeader.f.read(1)) 1641 | length += 1 1642 | 1643 | cur_bytes = int(cur_bytes_hex, 16) 1644 | value += cur_bytes_hex 1645 | 1646 | array.append(value) 1647 | 1648 | dexField = DexField() 1649 | dexField.fieldIdx = self.readUnsignedLeb128(array[0]) 1650 | dexField.accessFlags = self.readUnsignedLeb128(array[1]) 1651 | dexField.offset = offset 1652 | dexField.length = length 1653 | 1654 | offset += length 1655 | 1656 | dexClassDefObj.staticFields.append(dexField) 1657 | 1658 | # (2)解析DexField* instanceFields成员 1659 | for i in range(instanceFieldsSize): 1660 | array = [] 1661 | length = 0 1662 | for j in range(2): 1663 | cur_bytes_hex = binascii.b2a_hex(self.DexHeader.f.read(1)) 1664 | length += 1 1665 | 1666 | cur_bytes = int(cur_bytes_hex, 16) 1667 | value = cur_bytes_hex 1668 | 1669 | while cur_bytes > 0x7f: 1670 | cur_bytes_hex = binascii.b2a_hex(self.DexHeader.f.read(1)) 1671 | length += 1 1672 | 1673 | cur_bytes = int(cur_bytes_hex, 16) 1674 | value += cur_bytes_hex 1675 | 1676 | array.append(value) 1677 | 1678 | dexField = DexField() 1679 | dexField.fieldIdx = self.readUnsignedLeb128(array[0]) 1680 | dexField.accessFlags = self.readUnsignedLeb128(array[1]) 1681 | dexField.offset = offset 1682 | dexField.length = length 1683 | 1684 | offset += length 1685 | 1686 | dexClassDefObj.instanceFields.append(dexField) 1687 | 1688 | # (3)解析DexMethod* directMethods成员 1689 | for i in range(directMethodsSize): 1690 | array = [] 1691 | length = 0 1692 | for j in range(3): 1693 | cur_bytes_hex = binascii.b2a_hex(self.DexHeader.f.read(1)) 1694 | length += 1 1695 | 1696 | cur_bytes = int(cur_bytes_hex, 16) 1697 | value = cur_bytes_hex 1698 | 1699 | while cur_bytes > 0x7f: 1700 | cur_bytes_hex = binascii.b2a_hex(self.DexHeader.f.read(1)) 1701 | length += 1 1702 | 1703 | cur_bytes = int(cur_bytes_hex, 16) 1704 | value += cur_bytes_hex 1705 | 1706 | array.append(value) 1707 | 1708 | dexMethod = DexMethod() 1709 | dexMethod.methodIdx = self.readUnsignedLeb128(array[0]) 1710 | dexMethod.accessFlags = self.readUnsignedLeb128(array[1]) 1711 | dexMethod.codeOff = self.readUnsignedLeb128(array[2]) 1712 | dexMethod.offset = offset 1713 | dexMethod.length = length 1714 | 1715 | offset += length 1716 | 1717 | dexClassDefObj.directMethods.append(dexMethod) 1718 | 1719 | # (4)解析DexMethod* virtualMethods成员 1720 | for i in range(virtualMethodsSize): 1721 | array = [] 1722 | length = 0 1723 | for j in range(3): 1724 | cur_bytes_hex = binascii.b2a_hex(self.DexHeader.f.read(1)) 1725 | length += 1 1726 | 1727 | cur_bytes = int(cur_bytes_hex, 16) 1728 | value = cur_bytes_hex 1729 | 1730 | while cur_bytes > 0x7f: 1731 | cur_bytes_hex = binascii.b2a_hex(self.DexHeader.f.read(1)) 1732 | length += 1 1733 | 1734 | cur_bytes = int(cur_bytes_hex, 16) 1735 | value += cur_bytes_hex 1736 | 1737 | array.append(value) 1738 | 1739 | dexMethod = DexMethod() 1740 | dexMethod.methodIdx = self.readUnsignedLeb128(array[0]) 1741 | dexMethod.accessFlags = self.readUnsignedLeb128(array[1]) 1742 | dexMethod.codeOff = self.readUnsignedLeb128(array[2]) 1743 | dexMethod.offset = offset 1744 | dexMethod.length = length 1745 | 1746 | offset += length 1747 | 1748 | dexClassDefObj.virtualMethods.append(dexMethod) 1749 | ###################################################### 1750 | 1751 | # 解析DexCode 1752 | for dexMethod in dexClassDefObj.directMethods: 1753 | # 跳转到指向DexCode的偏移处 1754 | if dexMethod.codeOff != 0x0: 1755 | dexCode = self.parseDexCode(dexMethod.codeOff) 1756 | dexMethod.dexCode = dexCode 1757 | else: 1758 | dexMethod.dexCode = None 1759 | 1760 | for dexMethod in dexClassDefObj.virtualMethods: 1761 | # 跳转到指向DexCode的偏移处 1762 | if dexMethod.codeOff != 0x0: 1763 | dexCode = self.parseDexCode(dexMethod.codeOff) 1764 | dexMethod.dexCode = dexCode 1765 | else: 1766 | dexMethod.dexCode = None 1767 | 1768 | def print_DexClassDef(self): 1769 | print('\n') 1770 | print('[+] DexClassDef:') 1771 | 1772 | for index in range(len(self.dexClassDefList)): 1773 | dexClassDefObj = self.dexClassDefList[index] 1774 | print(' #%s~%s' % (hex(dexClassDefObj.offset), hex(dexClassDefObj.offset + dexClassDefObj.length))) 1775 | print(' DexClassDef[%d]:\t' % index) 1776 | print(' DexClassDef[%d]->classIdx\t= %s\t#%s' % (index, hex(dexClassDefObj.classIdx), self.getDexTypeId(dexClassDefObj.classIdx))) 1777 | print(' DexClassDef[%d]->accessFlags\t= %s' % (index, hex(dexClassDefObj.accessFlags) )) 1778 | print(' DexClassDef[%d]->superclassIdx\t= %s\t#%s' % (index, hex(dexClassDefObj.superclassIdx), self.getDexTypeId(dexClassDefObj.superclassIdx))) 1779 | print(' DexClassDef[%d]->interfaceOff\t= %s' % (index, hex(dexClassDefObj.interfaceOff))) 1780 | if dexClassDefObj.sourceFieldIdx == 0xffffffff: 1781 | print(' DexClassDef[%d]->sourceFieldIdx\t= %s\t#UNKNOWN' % (index, hex(dexClassDefObj.sourceFieldIdx))) 1782 | else: 1783 | print(' DexClassDef[%d]->sourceFieldIdx\t= %s\t#%s' % (index, hex(dexClassDefObj.sourceFieldIdx), self.DexStringIdList[dexClassDefObj.sourceFieldIdx])) 1784 | print(' DexClassDef[%d]->annotationsOff\t= %s' % (index, hex(dexClassDefObj.annotationsOff))) 1785 | print(' DexClassDef[%d]->classDataOff\t= %s' % (index, hex(dexClassDefObj.classDataOff))) 1786 | print(' DexClassDef[%d]->staticValueOff\t= %s' % (index, hex(dexClassDefObj.staticValueOff))) 1787 | if dexClassDefObj.classDataOff == 0: 1788 | continue 1789 | print(' ------------------------------------------------------------------------') 1790 | print(' # %s~%s' % (hex(dexClassDefObj.header.offset), hex(dexClassDefObj.header.offset + dexClassDefObj.header.length))) 1791 | print(' DexClassDef[%d]->DexClassData->DexClassDataHeader->staticFieldsSize \t= %s' % (index, hex(dexClassDefObj.header.staticFieldsSize))) 1792 | print(' DexClassDef[%d]->DexClassData->DexClassDataHeader->instanceFieldsSize \t= %s' % (index, hex(dexClassDefObj.header.instanceFieldsSize))) 1793 | print(' DexClassDef[%d]->DexClassData->DexClassDataHeader->directMethodsSize \t= %s' % (index, hex(dexClassDefObj.header.directMethodsSize))) 1794 | print(' DexClassDef[%d]->DexClassData->DexClassDataHeader->virtualMethodsSize \t= %s' % (index, hex(dexClassDefObj.header.virtualMethodsSize))) 1795 | if len(dexClassDefObj.staticFields) > 0: 1796 | print(' ------------------------------------------------------------------------') 1797 | print(' # %s~%s' % (hex(dexClassDefObj.staticFields[0].offset), hex(dexClassDefObj.staticFields[-1].offset + dexClassDefObj.staticFields[-1].length))) 1798 | if len(dexClassDefObj.staticFields) < 0 and len(dexClassDefObj.instanceFields) > 0: 1799 | print(' ------------------------------------------------------------------------') 1800 | print(' # %s~%s' % (hex(dexClassDefObj.instanceFields[0].offset), hex( 1801 | dexClassDefObj.instanceFields[-1].offset + dexClassDefObj.instanceFields[-1].length))) 1802 | lastFieldIdx = 0 1803 | for k in range(len(dexClassDefObj.staticFields)): 1804 | currFieldIdx = lastFieldIdx + dexClassDefObj.staticFields[k].fieldIdx 1805 | fieldName = self.getDexStringId(self.DexFieldIdList[currFieldIdx].nameIdx) 1806 | lastFieldIdx = currFieldIdx 1807 | print(' DexClassDef[%d]->DexClassData->staticFields[%d]\t= %s\t#%s' % (index, k, fieldName, dexClassDefObj.staticFields[k])) 1808 | 1809 | lastFieldIdx = 0 1810 | for k in range(len(dexClassDefObj.instanceFields)): 1811 | currFieldIdx = lastFieldIdx + dexClassDefObj.instanceFields[k].fieldIdx 1812 | fieldName = self.getDexStringId(self.DexFieldIdList[currFieldIdx].nameIdx) 1813 | lastFieldIdx = currFieldIdx 1814 | print(' DexClassDef[%d]->DexClassData->instanceFields[%d]\t= %s\t#%s' % (index, k, fieldName, dexClassDefObj.instanceFields[k])) 1815 | 1816 | if len(dexClassDefObj.staticFields) + len(dexClassDefObj.instanceFields) > 0: 1817 | print(' ------------------------------------------------------------------------') 1818 | 1819 | lastMethodIdx = 0 1820 | for k in range(len(dexClassDefObj.directMethods)): 1821 | currMethodIdx = lastMethodIdx + dexClassDefObj.directMethods[k].methodIdx 1822 | dexMethodIdObj = self.DexMethodIdList[currMethodIdx] 1823 | lastMethodIdx = currMethodIdx 1824 | print(' # %s~%s' % (hex(dexClassDefObj.directMethods[k].offset), hex(dexClassDefObj.directMethods[k].offset + dexClassDefObj.directMethods[k].length))) 1825 | print(' DexClassDef[%d]->DexClassData->directMethods[%d]\t= %s\t#%s' % (index, k, dexMethodIdObj.toString(self), dexClassDefObj.directMethods[k])) 1826 | self.dumpDexCode(dexClassDefObj.directMethods[k]) 1827 | print(' ------------------------------------------------------------------------') 1828 | 1829 | lastMethodIdx = 0 1830 | for k in range(len(dexClassDefObj.virtualMethods)): 1831 | currMethodIdx = lastMethodIdx + dexClassDefObj.virtualMethods[k].methodIdx 1832 | dexMethodIdObj = self.DexMethodIdList[currMethodIdx] 1833 | lastMethodIdx = currMethodIdx 1834 | print(' # %s~%s' % (hex(dexClassDefObj.virtualMethods[k].offset), hex(dexClassDefObj.virtualMethods[k].offset + dexClassDefObj.virtualMethods[k].length))) 1835 | print(' DexClassDef[%d]->DexClassData->virtualMethods[%d]\t= %s\t#%s' % (index, k, dexMethodIdObj.toString(self), dexClassDefObj.virtualMethods[k])) 1836 | self.dumpDexCode(dexClassDefObj.virtualMethods[k]) 1837 | print(' ------------------------------------------------------------------------') 1838 | print('\n') 1839 | 1840 | def dumpDexCode(self, dexMethod): 1841 | if dexMethod.dexCode == None: 1842 | return 1843 | print(' # %s~%s' % (hex(dexMethod.dexCode.offset), hex(dexMethod.dexCode.offset + dexMethod.dexCode.length))) 1844 | print(' DexCode=%s' % dexMethod.dexCode) 1845 | offset = 0 1846 | insnsSize = dexMethod.dexCode.insnsSize * 4 1847 | 1848 | while offset < insnsSize: 1849 | opcode = int(dexMethod.dexCode.insns[offset:offset + 2], 16) 1850 | formatIns, _ = getOpCode(opcode) 1851 | 1852 | decodedInstruction = dexDecodeInstruction(self, dexMethod.dexCode, offset) 1853 | 1854 | smaliCode = decodedInstruction.smaliCode 1855 | if smaliCode == None: 1856 | continue 1857 | 1858 | insns = dexMethod.dexCode.insns[decodedInstruction.offset:decodedInstruction.offset + decodedInstruction.length] 1859 | print(' \t%-16s|%04x: %s' % (insns, int(offset/4), smaliCode)) 1860 | offset += len(insns) 1861 | 1862 | if smaliCode == 'nop': 1863 | break 1864 | 1865 | def parseDexCode(self, codeOff): 1866 | self.DexHeader.f.seek(codeOff, 0) 1867 | 1868 | registersSize_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(2))) 1869 | registersSize = int(registersSize_hex, 16) 1870 | 1871 | insSize_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(2))) 1872 | insSize = int(insSize_hex, 16) 1873 | 1874 | outsSize_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(2))) 1875 | outsSize = int(outsSize_hex, 16) 1876 | 1877 | triesSize_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(2))) 1878 | triesSize = int(triesSize_hex, 16) 1879 | 1880 | debugInfoOff_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1881 | debugInfoOff = int(debugInfoOff_hex, 16) 1882 | 1883 | insnsSize_hex = reverse_hex(binascii.b2a_hex(self.DexHeader.f.read(4))) 1884 | insnsSize = int(insnsSize_hex, 16) 1885 | 1886 | if insnsSize == 0: 1887 | insns = '' 1888 | else: 1889 | if insnsSize*2 > sys.maxsize: 1890 | size = insnsSize*2 1891 | insns = '' 1892 | while size > sys.maxsize: 1893 | insns += binascii.b2a_hex(self.DexHeader.f.read(sys.maxsize)) 1894 | size -= sys.maxsize 1895 | else: 1896 | insns = binascii.b2a_hex(self.DexHeader.f.read(insnsSize*2)) 1897 | 1898 | dexCode = DexCode() 1899 | dexCode.registersSize = registersSize 1900 | dexCode.insSize = insSize 1901 | dexCode.outsSize = outsSize 1902 | dexCode.triesSize = triesSize 1903 | dexCode.debugInfoOff = debugInfoOff 1904 | dexCode.insnsSize = insnsSize 1905 | dexCode.insns = insns 1906 | 1907 | dexCode.offset = codeOff 1908 | dexCode.length = 16 + len(insns)/2 1909 | 1910 | return dexCode 1911 | 1912 | def readUnsignedLeb128(self, hex_value): 1913 | byte_counts = int(len(hex_value)/2) 1914 | 1915 | #找出第一个不是0的byte位置 1916 | index = 0 1917 | for i in range(byte_counts): 1918 | v1 = int(hex_value[i*2:i*2+2], 16) 1919 | if v1 > 0: 1920 | index = i 1921 | break 1922 | 1923 | hex_value = hex_value[index*2:] 1924 | byte_counts = int(len(hex_value)/2) 1925 | 1926 | result = 0 1927 | for i in range(byte_counts): 1928 | cur = int(hex_value[i*2:i*2+2], 16) 1929 | if cur > 0x7f: 1930 | result = result | ((cur & 0x7f) << (7*i)) 1931 | else: 1932 | result = result | ((cur & 0x7f) << (7*i)) 1933 | break 1934 | return result 1935 | 1936 | class DexHeader(object): 1937 | def __init__(self, ): 1938 | super(DexHeader, self).__init__() 1939 | self.f = None 1940 | self.magic = None 1941 | self.checksum = None 1942 | self.signature = None 1943 | self.file_size = None 1944 | self.header_size = None 1945 | self.endian_tag = None 1946 | self.link_size = None 1947 | self.link_off = None 1948 | self.map_off = None 1949 | self.string_ids_size = None 1950 | self.string_ids_off = None 1951 | self.type_ids_size = None 1952 | self.type_ids_off = None 1953 | self.proto_ids_size = None 1954 | self.proto_ids_off = None 1955 | self.field_ids_size = None 1956 | self.field_ids_off = None 1957 | self.method_ids_size = None 1958 | self.method_ids_off = None 1959 | self.class_defs_size = None 1960 | self.class_defs_off = None 1961 | self.data_size = None 1962 | self.data_off = None 1963 | 1964 | 1965 | class DexProtoId(object): 1966 | def __init__(self, ): 1967 | super(DexProtoId, self).__init__() 1968 | self.shortyIdx = None 1969 | self.returnTypeIdx = None 1970 | self.parameterOff = None 1971 | self.dexTypeList = None 1972 | 1973 | # Address index 1974 | self.offset = None 1975 | self.length = 0 1976 | 1977 | def toString(self, dexFile): 1978 | if self.dexTypeList: 1979 | return '%s%s' % (self.dexTypeList.toString(dexFile), dexFile.getDexTypeId(self.returnTypeIdx)) 1980 | else: 1981 | return '()%s' % dexFile.getDexTypeId(self.returnTypeIdx) 1982 | 1983 | class DexTypeList(object): 1984 | def __init__(self, ): 1985 | super(DexTypeList, self).__init__() 1986 | self.size = None 1987 | self.list = [] 1988 | 1989 | def toString(self, dexFile): 1990 | parametersStr = '' 1991 | if self.size: 1992 | for idx in self.list: 1993 | parametersStr += dexFile.getDexTypeId(idx) + ',' 1994 | return '(%s)' % parametersStr 1995 | 1996 | class DexMethodId(object): 1997 | def __init__(self, ): 1998 | super(DexMethodId, self).__init__() 1999 | self.classIdx = None 2000 | self.protoIdx = None 2001 | self.nameIdx = None 2002 | 2003 | # Address index 2004 | self.offset = None 2005 | self.length = 0 2006 | 2007 | def toString(self, dexFile): 2008 | if (self.classIdx != None) and (self.protoIdx != None) and (self.nameIdx != None): 2009 | return '%s.%s:%s' % (dexFile.getDexTypeId(self.classIdx), 2010 | dexFile.getDexStringId(self.nameIdx), 2011 | dexFile.DexProtoIdList[self.protoIdx].toString(dexFile)) 2012 | else: 2013 | return None 2014 | 2015 | def toApi(self, dexFile): 2016 | if (self.classIdx != None) and (self.protoIdx != None) and (self.nameIdx != None): 2017 | return '%s->%s' % (dexFile.getDexTypeId(self.classIdx), 2018 | dexFile.getDexStringId(self.nameIdx)) 2019 | else: 2020 | return None 2021 | 2022 | class DexFieldId(object): 2023 | def __init__(self, ): 2024 | super(DexFieldId, self).__init__() 2025 | self.classIdx = None 2026 | self.typeIdx = None 2027 | self.nameIdx = None 2028 | 2029 | # Address index 2030 | self.offset = None 2031 | self.length = 0 2032 | 2033 | def toString(self, dexFile): 2034 | if (self.classIdx != None) and (self.typeIdx != None) and (self.nameIdx != None): 2035 | return '%s.%s:%s' % (dexFile.getDexTypeId(self.classIdx), 2036 | dexFile.getDexStringId(self.nameIdx), 2037 | dexFile.getDexTypeId(self.typeIdx)) 2038 | else: 2039 | return None 2040 | 2041 | class DexClassDef(object): 2042 | def __init__(self,): 2043 | super(DexClassDef, self).__init__() 2044 | self.classIdx = None 2045 | self.accessFlags = None 2046 | self.superclassIdx = None 2047 | self.interfaceOff = None 2048 | self.sourceFieldIdx = None 2049 | self.annotationsOff = None 2050 | self.classDataOff = None 2051 | self.staticValueOff = None 2052 | 2053 | self.header = None 2054 | self.staticFields = [] 2055 | self.instanceFields = [] 2056 | self.directMethods = [] 2057 | self.virtualMethods = [] 2058 | 2059 | # Address index 2060 | self.offset = None 2061 | self.length = 0 2062 | 2063 | class DexClassDataHeader(object): 2064 | """docstring for ClassName""" 2065 | def __init__(self): 2066 | super(DexClassDataHeader, self).__init__() 2067 | self.staticFieldsSize = None 2068 | self.instanceFieldsSize = None 2069 | self.directMethodsSize = None 2070 | self.virtualMethodsSize = None 2071 | 2072 | # Address index 2073 | self.offset = None 2074 | self.length = 0 2075 | 2076 | class DexField(object): 2077 | """docstring for DexField""" 2078 | def __init__(self): 2079 | super(DexField, self).__init__() 2080 | self.fieldIdx = None 2081 | self.accessFlags = None 2082 | 2083 | # Address index 2084 | self.offset = None 2085 | self.length = 0 2086 | 2087 | def __str__(self): 2088 | return '[fieldIdx = %s, accessFlags = %s]' % (hex(self.fieldIdx), hex(self.accessFlags)) 2089 | 2090 | 2091 | class DexMethod(object): 2092 | """docstring for DexMethod""" 2093 | def __init__(self): 2094 | super(DexMethod, self).__init__() 2095 | self.methodIdx = None 2096 | self.accessFlags = None 2097 | self.codeOff = None 2098 | 2099 | # Address index 2100 | self.offset = None 2101 | self.length = 0 2102 | 2103 | self.dexCode = DexCode() 2104 | 2105 | def __str__(self): 2106 | return '[methodIdx = %s, accessFlags = %s, codeOff = %s]' % (hex(self.methodIdx), hex(self.accessFlags), hex(self.codeOff)) 2107 | 2108 | class DexCode(object): 2109 | """docstring for DexCode""" 2110 | def __init__(self): 2111 | super(DexCode, self).__init__() 2112 | self.registersSize = None 2113 | self.insSize = None 2114 | self.outsSize = None 2115 | self.triesSize = None 2116 | self.debugInfoOff = None 2117 | self.insnsSize = None 2118 | self.insns = None 2119 | 2120 | # Address index 2121 | self.offset = None 2122 | self.length = 0 2123 | 2124 | def __str__(self): 2125 | return '[registersSize = %s, insSize = %s, outsSize = %s, triesSize = %s, debugInfoOff = %s, insnsSize = %s, insns = %s]' % \ 2126 | (self.registersSize, self.insSize, self.outsSize, self.triesSize, hex(self.debugInfoOff), self.insnsSize, self.insns) 2127 | 2128 | 2129 | def main(): 2130 | dex = DexFile(sys.argv[1]) 2131 | dex.print_header() 2132 | dex.print_DexMapList() 2133 | dex.print_DexStringId() 2134 | dex.print_DexTypeId() 2135 | dex.print_DexProtoId() 2136 | dex.print_DexFieldId() 2137 | dex.print_DexMethodId() 2138 | dex.print_DexClassDef() 2139 | 2140 | if __name__ == '__main__': 2141 | main() 2142 | -------------------------------------------------------------------------------- /LiteRadar/litedextree.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Copyright 2017 Zachary Marv (马子昂) 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | 18 | # DEX Tree 19 | # 20 | # This script is used to implement the tree node and tree structure. 21 | 22 | 23 | from _settings import * 24 | import hashlib 25 | import csv 26 | 27 | 28 | # tag_rules 29 | labeled_libs = list() 30 | no_lib = list() 31 | 32 | with open(FILE_RULE, 'r') as file_rules: 33 | csv_rules_reader = csv.reader(file_rules, delimiter=',', quotechar='|') 34 | for row in csv_rules_reader: 35 | if row[1] == "no": 36 | no_lib.append(row) 37 | else: 38 | labeled_libs.append(row) 39 | 40 | 41 | class TreeNode(object): 42 | """ 43 | Tree Node Structure 44 | { 45 | sha256 : 02b018f5b94c5fbc773ab425a15b8bbb // In fact sha256 is the non-hex one 46 | weight : 1023 // How many APIs in this Node 47 | pn : Lcom/facebook/internal // Current package name 48 | parent : // Parent node 49 | children: dict("pn": ) // Children nodes 50 | match : list( tuple(package_name, match_weight) ) // match lib list 51 | } 52 | """ 53 | def __init__(self, n_weight=-1, n_pn="", n_parent=None): 54 | self.sha256 = "" 55 | self.weight = n_weight 56 | self.pn = n_pn 57 | self.parent = n_parent 58 | self.children = dict() 59 | self.match = list() 60 | self.permissions = set() 61 | 62 | def insert(self, package_name, weight, sha256, permission_list): 63 | # no matter how deep the package is, add permissions here. 64 | for permission in permission_list: 65 | self.permissions.add(permission) 66 | current_depth = 0 if self.pn == "" else self.pn.count('/') + 1 67 | target_depth = package_name.count('/') + 1 68 | if current_depth == target_depth: 69 | self.sha256 = sha256 70 | return "F: %s" % package_name 71 | target_package_name = '/'.join(package_name.split('/')[:current_depth + 1]) 72 | if target_package_name in self.children: 73 | self.children[target_package_name].weight += weight 74 | return self.children[target_package_name].insert(package_name, weight, sha256, permission_list) 75 | else: 76 | self.children[target_package_name] = TreeNode(n_weight=weight, n_pn=target_package_name, n_parent=self) 77 | return self.children[target_package_name].insert(package_name, weight, sha256, permission_list) 78 | 79 | 80 | 81 | class Tree(object): 82 | """ 83 | Tree 84 | """ 85 | def __init__(self): 86 | self.root = TreeNode() 87 | self.db = None 88 | self.feature = None 89 | self.feature = dict() 90 | with open(LITE_DATASET_10, 'r') as file_rules: 91 | csv_rules_reader = csv.reader(file_rules, delimiter=',', quotechar='|') 92 | for row in csv_rules_reader: 93 | self.feature[row[0]] = row[1:5] 94 | 95 | def insert(self, package_name, weight, sha256, permission_list): 96 | self.root.insert(package_name, weight, sha256, permission_list) 97 | 98 | def brand(self, package_name, standard_package): 99 | return self.root.brand(package_name, standard_package) 100 | 101 | def pre_order_res(self, visit, res): 102 | self._pre_order_res(node=self.root, visit=visit, res=res) 103 | 104 | def _pre_order_res(self, node, visit, res): 105 | ret = visit(node, res) 106 | 107 | if ret == None or ret < 0: 108 | return 109 | else: 110 | for child_pn in node.children: 111 | self._pre_order_res(node.children[child_pn], visit, res) 112 | 113 | def pre_order(self, visit): 114 | self._pre_order(self.root, visit) 115 | 116 | def _pre_order(self, node, visit): 117 | ret = visit(node) 118 | if ret < 0: 119 | return 120 | else: 121 | for child_pn in node.children: 122 | self._pre_order(node.children[child_pn], visit) 123 | 124 | def post_order(self, visit): 125 | self._post_order(self.root, visit) 126 | 127 | def _post_order(self, node, visit): 128 | for child_pn in node.children: 129 | self._post_order(node.children[child_pn], visit) 130 | visit(node) 131 | 132 | @staticmethod 133 | def _cal_sha256(node): 134 | # Ignore Leaf Node 135 | if len(node.children) == 0 and node.sha256 != "": 136 | return 137 | # Everything seems Okay. 138 | cur_sha256 = hashlib.sha256() 139 | sha256_list = list() 140 | for child in node.children: 141 | sha256_list.append(node.children[child].sha256) 142 | sha256_list.sort() 143 | for sha256_item in sha256_list: 144 | cur_sha256.update(sha256_item.encode()) 145 | node.sha256 = cur_sha256.hexdigest() 146 | 147 | # you could see node.pn here. e.g. Lcom/tencent/mm/sdk/modelpay 148 | 149 | def cal_sha256(self): 150 | """ 151 | Calculate sha256 for every package 152 | :return: 153 | """ 154 | self.post_order(visit=self._cal_sha256) 155 | 156 | def _match(self, node): 157 | a, c, u = None, None, None 158 | 159 | if node.sha256 in self.feature: 160 | acu_cur = self.feature[node.sha256] 161 | a, c, u = acu_cur[3], acu_cur[0], acu_cur[2] 162 | 163 | # if could not find this package in database, search its children. 164 | if a is None: 165 | return 1 166 | # Potential Name is not convincing enough. 167 | if float(u) < 8 or float(u) / float(c) < 0.3: 168 | return 2 169 | flag_not_deeper = False 170 | for lib in labeled_libs: 171 | # if the potential package name is the same as full lib path 172 | # do not search its children 173 | if lib[0] == a: 174 | node.match.append([lib, node.weight, int(c)]) 175 | continue 176 | # If they have the same length but not equal to each other, just continue 177 | if len(lib[0]) == len(a): 178 | continue 179 | # if the potential package name is part of full lib path, search its children 180 | # e.g. a is Lcom/google, we could find it as a part of Lcom/google/android/gms, so search its children for 181 | # more details 182 | if len(a) < len(lib[0]) and a == lib[0][:len(a)] and lib[0][len(a)] == '/': 183 | continue 184 | # If the lib path is part of potential package name, add some count into parent's match list. 185 | if len(a) > len(lib[0]) and lib[0] == a[:len(lib[0])] and a[len(lib[0])] == '/': 186 | depth_diff = a.count('/') - lib[0].count('/') 187 | cursor = node 188 | for i in range(depth_diff): 189 | # cursor should not be the root, so cursor's parent should not be None. 190 | if cursor.parent.parent is not None: 191 | cursor = cursor.parent 192 | else: 193 | # root's parent is None 194 | # This situation exists 195 | # For Example: If it takes Lcom/a/b as Lcom/google/android/gms/ads/mediation/customevent, 196 | # It will find its ancestor until root or None. 197 | return 4 198 | flag = False 199 | for matc in cursor.match: 200 | # if matc[0][0] == lib[0]: 201 | if matc[0] == lib: 202 | flag = True 203 | if matc[1] != cursor.weight: 204 | matc[1] += node.weight 205 | if not flag: 206 | cursor.match.append([lib, node.weight, c]) 207 | flag_not_deeper = True 208 | continue 209 | """ 210 | One degree deeper! 211 | 深入探测一层 212 | 213 | There's a situation that a package is a library and the child of a package is also a library. 214 | 库是存在相互嵌套的。 215 | 216 | As we all know that Lcom/unity3d is definitely a Game Engine library. There could be some sub-package 217 | like Lcom/unity3d/player, Lcom/unity3d/plugin, Lcom/unity3d/sdk, etc. So we take Lcom/unity3d as the 218 | root package of this library. 219 | 比如,Lcom/unity3d 显然是Unity3D这个游戏引擎,在游戏引擎下可能会有player, plugin, sdk等次级包(文件夹),所以我们很 220 | 显然地把Lcom/unity3d作为游戏引擎的根包。 221 | 222 | However, Lcom/unity3d/ads is an Advertisement library. 223 | 但是,Lcom/unity3d/ads是Unity3D公司推出的广告库 224 | 225 | If we do not search one degree deeper, we could only find the game engine other than the ads library. 226 | Likewise, we could not find Landroid/support/v4 anymore if we take Landroid/support as a library. 227 | 如果我们不继续搜索的话,那么对于一个应用,我们只能检测到Unity3D这个引擎,无法检测到Unity3D Ads这个广告库。 228 | 229 | Implementation: 230 | 实现: 231 | if lib[0] == a, we continue search his children. 232 | if lib[0] == a 这个后面从return变成了continue,我们会继续搜索它的子节点 233 | 234 | if we already found his child, we will not search deeper. 235 | 在后面的代码中,如果已经知道的就是子节点,那么就不会继续深层的搜了。 236 | 237 | In my original code, I found a bug that the match degree is larger than the total amount of weight. 238 | This is impossible. After debugging, I found that if I add the match value multiple times, the match 239 | weight could overflow. 240 | 在我原来有bug的代码中,我发现匹配的similarity有大于1的情况,即com/facebook这个库的similarity大于了1。这是因为match 241 | 被我加总了数次 242 | 243 | For example: 244 | There's a library Lcom/google/android/gson, weight is 189 245 | we found Lcom/google/android/gson, so add the weight 189 246 | we found Lcom/google/android/gson/internal, so add the weight 24 247 | we found Lcom/google/android/gson/stream, so add the weight 43 248 | In this case, the weight of package gson overflows. 249 | 举例来看: 250 | 对于Lcom/google/android/gson这个包来说,它的API数量是189 251 | 搜索中找到 Lcom/google/android/gson, weight加上189 252 | 搜索中找到 Lcom/google/android/gson/internal, weight加上24 253 | 搜索中找到 Lcom/google/android/gson/stream, weight加上 43 254 | 这样显然就溢出了。 255 | 256 | Because we only search 1 degree deeper, the match situation of Lcom/google/android/gson is only true or 257 | false. In this case, we just need to check if the weight has overflowed before add weight. as the code: 258 | if matc[1] != cursor.weight: 259 | matc[1] += node.weight 260 | 因为我们可以多搜一层,所以判断是否溢出很简单。因为对于上层的库来说,也就只有两种情况,那就是匹配到和没匹配到。所以只需要 261 | 检测一下是否已经超出就行了。 262 | """ 263 | if flag_not_deeper: 264 | return -1 265 | # Never find a good match, search its children. 266 | return 5 267 | 268 | def match(self): 269 | self.pre_order(visit=self._match) 270 | 271 | def _find_untagged(self, node, res): 272 | # If there's already some matches here, do not search its children. non-sense. 273 | a, c, u = None, None, None 274 | if len(node.match) != 0: 275 | return -1 276 | if node.sha256 in self.feature: 277 | acu_cur = self.feature[node.sha256] 278 | a, c, u = acu_cur[3], acu_cur[0], acu_cur[2] 279 | 280 | if a is None: 281 | return 1 282 | 283 | # If the package name is already in no_lib list, ignore it and search its children. 284 | for non_lib in no_lib: 285 | if non_lib[0] == a: 286 | return 1 287 | # Potential Name is not convincing enough. search its children 288 | if float(u) / float(c) < 0.5 or node.weight < 50 or int(c) < 20: 289 | return 2 290 | 291 | # JSON support 292 | utg_lib_obj = dict() # untagged library object 293 | utg_lib_obj["Package"] = node.pn 294 | utg_lib_obj["Standard Package"] = a 295 | utg_lib_obj["Library"] = "Unknown" 296 | utg_lib_obj["Popularity"] = int(c) 297 | utg_lib_obj["Weight"] = node.weight 298 | 299 | res.append(utg_lib_obj) 300 | 301 | # OLD Print 302 | # print("----") 303 | # print("Package: %s" % node.pn) 304 | # print("Match Package: %s" % u) 305 | # print("Library: Unknown.") 306 | # print("Popularity: %s" % c) 307 | # print("API count: %s" % node.weight) 308 | 309 | def find_untagged(self, res): 310 | self.pre_order_res(visit=self._find_untagged, res=res) 311 | 312 | @staticmethod 313 | def _get_lib(node, res): 314 | for matc in node.match: 315 | if float(matc[1]) / float(node.weight) < 0.1 and matc[0][0] != node.pn: 316 | continue 317 | # JSON 318 | lib_obj = dict() 319 | lib_obj["Package"] = node.pn # cpn 320 | lib_obj["Library"] = matc[0][1] # lib 321 | lib_obj["Standard Package"] = matc[0][0] # pn 322 | lib_obj["Type"] = matc[0][2] # tp 323 | lib_obj["Website"] = matc[0][3] # ch 324 | lib_obj["Match Ratio"] = "%d/%d" % (matc[1], node.weight) # no similarity in V1 325 | lib_obj["Popularity"] = matc[2] # dn 326 | lib_obj["Permission"] = sorted(list(node.permissions)) 327 | res.append(lib_obj) 328 | # Old Print 329 | # print("----") 330 | # print("Package: %s" % node.pn) 331 | # print("Library: %s" % matc[0][1]) 332 | # print("Standard Package: %s" % matc[0][0]) 333 | # print("Type: %s" % matc[0][2]) 334 | # print("Website: %s" % matc[0][3]) 335 | # print("Similarity: %d/%d" % (matc[1], node.weight)) 336 | # print("Popularity: %d" % matc[2]) 337 | # permission_out = "" 338 | # for permission in sorted(list(node.permissions)): 339 | # permission_out += (permission + ",") 340 | # if len(permission_out) > 0: 341 | # permission_out = permission_out[:-1] 342 | # print("Permissions:" + permission_out) 343 | return 0 344 | 345 | def get_lib(self, res): 346 | self.pre_order_res(visit=self._get_lib, res=res) 347 | 348 | -------------------------------------------------------------------------------- /LiteRadar/literadar.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Copyright 2017 Zachary Marv (马子昂) 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | 18 | # LibRadar 19 | # 20 | # main function for instant detection. 21 | 22 | 23 | import sys 24 | from _settings import * 25 | import litedextree 26 | import dex_parser 27 | import hashlib 28 | import zipfile 29 | import json 30 | 31 | 32 | class LibRadarLite(object): 33 | """ 34 | LibRadar 35 | """ 36 | 37 | def __init__(self, apk_path): 38 | """ 39 | Init LibRadar instance with apk_path as a basestring. 40 | Create a Tree for every LibRadar instance. The tree describe 41 | the architecture of the apk. Every package is a node. 42 | :param apk_path: basestring 43 | """ 44 | self.apk_path = apk_path 45 | self.tree = litedextree.Tree() 46 | 47 | # A list with the .dex file names contained in the apk, for multidex support. 48 | self.dex_names = [] 49 | 50 | # Every element in this array is an instance of Dex Object in dex_parser. This 51 | # is an array instead of a single element to enable multidex. 52 | self.dex_objects = [] 53 | 54 | """ 55 | Use redis database to exam whether a call is an Android API consumes 27% running time. 56 | I think it should be replaced by a hash table as the API list could not be modified during the progress. 57 | """ 58 | self.k_api_v_permission = dict() 59 | with open(os.path.join(SCRIPT_PATH, 'Data', 'strict_api.csv'), 'r') as api_and_permission: 60 | for line in api_and_permission: 61 | api, permission_with_colon = line.split(",") 62 | permissions = permission_with_colon[:-2].split(":") 63 | # delete the last empty one 64 | permission_list = list() 65 | for permission in permissions: 66 | if permission != "": 67 | permission_list.append(permission) 68 | self.k_api_v_permission[api] = permission_list 69 | """ 70 | invoke_file = open(SCRIPT_PATH +"/Data/IntermediateData/invokeFormat.txt", 'r') 71 | self.invokes = set() 72 | for line in invoke_file: 73 | self.invokes.add(line[:-1]) 74 | """ 75 | 76 | def __del__(self): 77 | # Delete dex file 78 | if CLEAN_WORKSPACE >= 3: 79 | for dex_name in self.dex_names: 80 | os.remove(dex_name) 81 | os.removedirs(os.path.dirname(dex_name)) 82 | 83 | def unzip(self): 84 | # If it is a valid file 85 | if not os.path.isfile(self.apk_path): 86 | logger.error("%s is not a valid file." % self.apk_path) 87 | raise AssertionError 88 | # If it is a apk file 89 | if len(self.apk_path) <= 4 or self.apk_path[-4:] != ".apk": 90 | logger.error("%s is not a apk file.") 91 | raise AssertionError 92 | # Get SHA256 93 | self.hex_sha256 = self.get_sha256() 94 | # Unzip 95 | zf = zipfile.ZipFile(self.apk_path, mode='r') 96 | 97 | # Save all the .dex files contained in the apk into the Decompiled directory and save 98 | # the .dex file names into the dex_names array. 99 | try: 100 | self.dex_names.append(zf.extract("classes.dex", SCRIPT_PATH + "/Data/Decompiled/%s" % self.hex_sha256)) 101 | 102 | # Enable multidex support. If this apk has only a .dex file, then the dex_names array 103 | # will contain a single element. 104 | basename = "classes%d.dex" 105 | 106 | # Little hack to let Python2 work without much trouble 107 | try: 108 | x_range = xrange(2, sys.maxint) 109 | except Exception: 110 | x_range = range(2, sys.maxsize) 111 | 112 | for i in x_range: 113 | self.dex_names.append(zf.extract(basename % i, SCRIPT_PATH + "/Data/Decompiled/%s" % self.hex_sha256)) 114 | 115 | except KeyError: 116 | pass 117 | 118 | return self.dex_names 119 | 120 | def get_sha256(self): 121 | if not os.path.isfile(self.apk_path): 122 | logger.critical("file path %s is not a file" % self.apk_path) 123 | raise AssertionError 124 | file_sha256 = hashlib.sha256() 125 | f = open(self.apk_path, 'rb') 126 | while True: 127 | block = f.read(4096) 128 | if not block: 129 | break 130 | file_sha256.update(block) 131 | f.close() 132 | file_sha256_value = file_sha256.hexdigest() 133 | logger.debug("APK %s's MD5 is %s" % (self.apk_path, file_sha256_value)) 134 | return file_sha256_value 135 | 136 | def get_api_list(self, dex_obj, dex_method, api_list, permission_list): 137 | if dex_method.dexCode is None: 138 | return 139 | offset = 0 140 | insns_size = dex_method.dexCode.insnsSize * 4 141 | 142 | while offset < insns_size: 143 | op_code = int(dex_method.dexCode.insns[int(offset):int(offset + 2)], 16) 144 | decoded_instruction = dex_parser.dexDecodeInstruction(dex_obj, dex_method.dexCode, offset) 145 | smali_code = decoded_instruction.smaliCode 146 | if smali_code is None: 147 | logger.warning("smali code is None.") 148 | continue 149 | # Next Instruction. 150 | offset += decoded_instruction.length 151 | if smali_code == 'nop': 152 | break 153 | # 4 invokes from 0x6e to 0x72 154 | if 0x6e <= op_code <= 0x72: 155 | if decoded_instruction.getApi in self.k_api_v_permission: 156 | api_list.append(decoded_instruction.getApi) 157 | for permission in self.k_api_v_permission[decoded_instruction.getApi]: 158 | permission_list.add(permission) 159 | return 160 | 161 | def extract_class(self, dex_obj, dex_class_def_obj): 162 | class_sha256 = hashlib.sha256() 163 | # API List 164 | # a list for basestring 165 | api_list = list() 166 | permission_list = set() 167 | # direct methods 168 | last_method_index = 0 169 | 170 | for k in range(len(dex_class_def_obj.directMethods)): 171 | current_method_index = last_method_index + dex_class_def_obj.directMethods[k].methodIdx 172 | last_method_index = current_method_index 173 | self.get_api_list(dex_obj, dex_class_def_obj.directMethods[k], api_list=api_list, permission_list=permission_list) 174 | # virtual methods 175 | last_method_index = 0 176 | for k in range(len(dex_class_def_obj.virtualMethods)): 177 | current_method_index = last_method_index + dex_class_def_obj.virtualMethods[k].methodIdx 178 | last_method_index = current_method_index 179 | self.get_api_list(dex_obj, dex_class_def_obj.virtualMethods[k], api_list=api_list, permission_list=permission_list) 180 | 181 | # Use sort to pass the tree construction stage. 182 | # In this case, we could only use a stack to create the package features. 183 | api_list.sort() 184 | for api in api_list: 185 | class_sha256.update(api.encode()) 186 | if not IGNORE_ZERO_API_FILES or len(api_list) != 0: 187 | pass 188 | return len(api_list), class_sha256.hexdigest(), class_sha256.hexdigest(), sorted(list(permission_list)) 189 | 190 | def extract_dex(self): 191 | for dex_name in self.dex_names: 192 | # Log Start 193 | logger.debug("Extracting %s" % dex_name) 194 | # Validate existing 195 | if not os.path.isfile(dex_name): 196 | logger.error("%s is not a file" % dex_name) 197 | return -1 198 | # Create a Dex object for each dex file contained in the apk. 199 | current_dex = dex_parser.DexFile(dex_name) 200 | self.dex_objects.append(current_dex) 201 | for dex_class_def_obj in current_dex.dexClassDefList: 202 | weight, raw_sha256, hex_sha256, permission_list = self.extract_class(dex_obj=current_dex, dex_class_def_obj=dex_class_def_obj) 203 | class_name = current_dex.getDexTypeId(dex_class_def_obj.classIdx) 204 | """ 205 | I got many \x01 here before the class name. 206 | such as '\x01Lcom/vungle/publisher/inject' 207 | don't know exactly but could use code below to deal with it. 208 | """ 209 | if class_name[0] is not 'L': 210 | l_index = class_name.find('L') 211 | 212 | if l_index == '-1': 213 | continue 214 | 215 | class_name = class_name[l_index:] 216 | 217 | if IGNORE_ZERO_API_FILES and weight == 0: 218 | continue 219 | 220 | self.tree.insert(package_name=class_name, weight=weight, sha256=raw_sha256, permission_list=permission_list) 221 | return 0 222 | 223 | def analyse(self): 224 | """ 225 | Main function for LibRadar Object. 226 | :return: None 227 | """ 228 | # Step 1: Unzip APK file, only extract the dex files. 229 | self.unzip() 230 | # Step 2: Extract Dex and insert package-level info into Tree 231 | self.extract_dex() 232 | # Step 3: post-order traverse the tree, calculate every package's sha256 value. 233 | self.tree.cal_sha256() 234 | 235 | def compare(self): 236 | self.analyse() 237 | # Step 4: pre-order traverse the tree, calculate every node's match degree (similarity). 238 | self.tree.match() 239 | # Init res for step 5 & 6 240 | res = list() 241 | # Step 5: traverse the tree, find out all the libraries. 242 | self.tree.get_lib(res) 243 | # Step 6: traverse the tree, find potential libraries that has not been tagged. 244 | self.tree.find_untagged(res) 245 | return res 246 | 247 | 248 | if __name__ == '__main__': 249 | if len(sys.argv) != 2: 250 | print("LiteRadar only takes 1 argument.") 251 | print("Usage:") 252 | print(" $ python literadar.py example.apk") 253 | exit(1) 254 | iron_apk_path = sys.argv[1] 255 | lrd = LibRadarLite(iron_apk_path) 256 | res = lrd.compare() 257 | print(json.dumps(res, indent=4, sort_keys=True)) 258 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LiteRadar 2 | Lite version of LibRadar 3 | 4 | 5 | ## Usage 6 | 7 | ```bash 8 | $ python literadar.py someapp.apk 9 | ``` 10 | View [docs/QuickStart.md](https://github.com/pkumza/LiteRadar/blob/master/docs/QuickStart.md) for more information. 11 | -------------------------------------------------------------------------------- /docs/QuickStart.md: -------------------------------------------------------------------------------- 1 | # QuickStart 2 | 3 | ## How to use LiteRadar 4 | 5 | Lite Version Online! (The lite version can meet most needs) 6 | 7 | 1. Download Code 8 | - Github 9 | ```bash 10 | $ git clone https://github.com/pkumza/LiteRadar 11 | ``` 12 | 13 | 2. Download Feature File 14 | 15 | Download lite_datasetfile, then move it into LiteRadar/LiteRadar/Data directory. (about 90MB) 16 | 17 | [Mirror 1 Github](https://github.com/pkumza/Data_for_LibRadar/blob/master/lite_dataset_10.csv) 18 | 19 | [Mirror 2 Aliyun](http://lxwiki.oss-cn-beijing.aliyuncs.com/lite_dataset_10.csv) 20 | 21 | 3. Use LiteRadar to detect libraries. 22 | 23 | ```bash 24 | $ python literadar.py someapp.apk 25 | ``` 26 | --------------------------------------------------------------------------------