├── LICENSE
├── PermissionInfo_Pixel3.txt
├── README.md
├── lib
├── soot-4.2.1-jar-with-dependencies.jar
├── soot-infoflow-2.9.0.jar
├── soot-infoflow-android-2.10.0.jar
└── trove4j-3.0.1.jar
├── pom.xml
├── sinks
├── CF_SINK_INFO.txt
├── DF_SINK_INFO.txt
└── sink.txt
└── src
├── .DS_Store
├── .gitignore
└── main
└── java
├── analyze
├── AnalyzeDatabase.java
├── AnalyzeNIO.java
├── AnalyzeService.java
├── FileUseAnalyze.java
├── Main.java
└── MainAnalyze.java
├── cfg
├── CfgFactory.java
└── Path.java
├── cg
└── CallGraphUtils.java
├── component
├── EntryPointAnalyze.java
├── FragementCreater.java
└── ResolveManifest.java
├── constant
├── ApkAndJavaConstants.java
├── CollectionsUsageDefinition.java
├── EntryPointsDefinition.java
├── FileUsageDefinition.java
├── IPCPointDefinition.java
└── StrawPointsDefinition.java
├── dataflow
├── AbstractDataFlow.java
├── AccessPathTag.java
├── Analyze.java
├── BackwardDataFlow.java
├── CallSite.java
├── DBInfo.java
├── DataFlowEngine.java
├── DatabaseUseDetector.java
├── Event.java
├── EventQueue.java
├── ExportedConfigFileDetector.java
├── ExportedFileChecker.java
├── FileInfo.java
├── FileLoaderDetector.java
├── FileNameConstructor.java
├── FileType.java
├── FileUseDetector.java
├── ForwardDataFlow.java
├── Icc.java
├── Point.java
├── RuleChecker.java
├── SensitiveActionChecker.java
├── SpInfo.java
├── StrawDetector.java
└── TaintWrapper.java
├── timeout
└── TimeOutTask.java
└── util
├── DirTraversal.java
├── Log.java
├── SootInit.java
├── StringConvertUtil.java
└── StringUtil.java
/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 [yyyy] [name of copyright owner]
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CLDroid
2 |
3 | CLDroid provides an end-to-end solution to statically detect cross-layer threats in Android apps (implemented based on Soot framework).
4 |
5 | Given an Android app, CLDroid first identifies the data pools (e.g., shared preference files and databases) that may be injected by external apps through exported components. Second, CLDroid employs data identifier-based analysis to track the data flow of data items that traverse through the target data pool. Third, CLDroid learns app-specific data use semantics and universally assesses their security risks from the perspectives of two attack vectors (i.e., data loading and data consuming).
6 |
7 | For more details, welcome to follow our paper:
8 |
9 | ```
10 | Keke Lian, Lei Zhang, Guangliang Yang, Shuo Mao, Xinjie Wang, Yuan Zhang, and Min Yang. 2024. Component
11 | Security Ten Years Later: An Empirical Study of Cross-Layer Threats in Real-World Mobile Applications. Proc.
12 | ACM Softw. Eng. 1, FSE, Article 4 (July 2024)
13 | ```
--------------------------------------------------------------------------------
/lib/soot-4.2.1-jar-with-dependencies.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LianKee/CLDroid/3f37222c4dfc248b8992e06bbf9f1ecb6a653cd7/lib/soot-4.2.1-jar-with-dependencies.jar
--------------------------------------------------------------------------------
/lib/soot-infoflow-2.9.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LianKee/CLDroid/3f37222c4dfc248b8992e06bbf9f1ecb6a653cd7/lib/soot-infoflow-2.9.0.jar
--------------------------------------------------------------------------------
/lib/soot-infoflow-android-2.10.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LianKee/CLDroid/3f37222c4dfc248b8992e06bbf9f1ecb6a653cd7/lib/soot-infoflow-android-2.10.0.jar
--------------------------------------------------------------------------------
/lib/trove4j-3.0.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LianKee/CLDroid/3f37222c4dfc248b8992e06bbf9f1ecb6a653cd7/lib/trove4j-3.0.1.jar
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.example
8 | CLDroid
9 | 1.0-SNAPSHOT
10 |
11 |
12 |
13 | org.apache.maven.plugins
14 | maven-jar-plugin
15 | 2.4
16 |
17 |
18 |
19 | true
20 | analyze.Main
21 |
22 |
23 |
24 |
25 |
26 | org.apache.maven.plugins
27 | maven-compiler-plugin
28 |
29 | 1.8
30 | 1.8
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | junit
41 | junit
42 | 4.13.2
43 |
44 |
45 | com.alibaba
46 | fastjson
47 | 1.2.28
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LianKee/CLDroid/3f37222c4dfc248b8992e06bbf9f1ecb6a653cd7/src/.DS_Store
--------------------------------------------------------------------------------
/src/.gitignore:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/main/java/analyze/AnalyzeDatabase.java:
--------------------------------------------------------------------------------
1 | package analyze;
2 |
3 | import cg.CallGraphUtils;
4 | import component.EntryPointAnalyze;
5 | import component.ResolveManifest;
6 | import constant.ApkAndJavaConstants;
7 | import constant.FileUsageDefinition;
8 | import dataflow.Analyze;
9 | import dataflow.CallSite;
10 | import dataflow.DatabaseUseDetector;
11 | import dataflow.Point;
12 | import org.slf4j.Logger;
13 | import org.slf4j.LoggerFactory;
14 | import soot.*;
15 | import soot.jimple.*;
16 | import soot.jimple.infoflow.InfoflowConfiguration;
17 | import soot.jimple.infoflow.android.manifest.binary.AbstractBinaryAndroidComponent;
18 | import soot.jimple.toolkits.callgraph.CallGraph;
19 | import soot.jimple.toolkits.callgraph.Edge;
20 | import soot.jimple.toolkits.callgraph.ReachableMethods;
21 | import soot.jimple.toolkits.callgraph.TransitiveTargets;
22 | import soot.util.queue.QueueReader;
23 | import util.DirTraversal;
24 | import util.Log;
25 | import util.SootInit;
26 |
27 | import java.io.File;
28 | import java.io.IOException;
29 | import java.util.*;
30 |
31 |
32 | public class AnalyzeDatabase {
33 |
34 | public static final Logger logger = LoggerFactory.getLogger(AnalyzeDatabase.class);
35 |
36 |
37 | //直接使用数据库提供的API进行查询的
38 | public static final String DATA_BASE_QUERY_0 = "android.database.Cursor query(java.lang.String,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String,java.lang.String,java.lang.String)";
39 | public static final String DATA_BASE_QUERY_1 = "android.database.Cursor query(java.lang.String,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String,java.lang.String,java.lang.String,java.lang.String)";
40 | public static final String DATA_BASE_QUERY_2 = "android.database.Cursor query(boolean,java.lang.String,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String,java.lang.String,java.lang.String,java.lang.String)";
41 | public static final String DATA_BASE_QUERY_3 = "android.database.Cursor query(boolean,java.lang.String,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String,java.lang.String,java.lang.String,java.lang.String,android.os.CancellationSignal)";
42 | public static final String DATA_BASE_QUERY_4 = "android.database.Cursor rawQuery(java.lang.String,java.lang.String[])";
43 | public static final String DATA_BASE_QUERY_5 = "android.database.Cursor rawQuery(java.lang.String,java.lang.String[],android.os.CancellationSignal)";
44 | public static final String DATA_BASE_QUERY_6 = "android.database.Cursor rawQueryWithFactory(android.database.sqlite.SQLiteDatabase$CursorFactory,java.lang.String,java.lang.String[],java.lang.String)";
45 | public static final String DATA_BASE_QUERY_7 = "android.database.Cursor rawQueryWithFactory(android.database.sqlite.SQLiteDatabase$CursorFactory,java.lang.String,java.lang.String[],java.lang.String,android.os.CancellationSignal)";
46 | public static final String DATA_BASE_QUERY_8 = "android.database.Cursor queryWithFactory(android.database.sqlite.SQLiteDatabase$CursorFactory,boolean,java.lang.String,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String,java.lang.String,java.lang.String,java.lang.String)";
47 | public static final String DATA_BASE_QUERY_9 = "android.database.Cursor queryWithFactory(android.database.sqlite.SQLiteDatabase$CursorFactory,boolean,java.lang.String,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String,java.lang.String,java.lang.String,java.lang.String,android.os.CancellationSignal)";
48 | public static final String DATA_BASE_QUERY_10 = "void execSQL(java.lang.String)";
49 | public static final String DATA_BASE_QUERY_11 = "void execSQL(java.lang.String,java.lang.Object[])";
50 |
51 | //使用ContentResolver提供的API进行查询的
52 | public static final String CONTENT_RESOLVER_QUERY_0 = "android.database.Cursor query(android.net.Uri,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String)";
53 | public static final String CONTENT_RESOLVER_QUERY_1 = "android.database.Cursor query(android.net.Uri,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String,android.os.CancellationSignal)";
54 | public static final String CONTENT_RESOLVER_QUERY_2 = "android.database.Cursor query(android.net.Uri,java.lang.String[],android.os.Bundle,android.os.CancellationSignal)";
55 |
56 | public static final HashSet QUERY_API_SET = new HashSet<>();
57 |
58 | static {
59 | QUERY_API_SET.add(DATA_BASE_QUERY_0);
60 | QUERY_API_SET.add(DATA_BASE_QUERY_1);
61 | QUERY_API_SET.add(DATA_BASE_QUERY_2);
62 | QUERY_API_SET.add(DATA_BASE_QUERY_3);
63 | QUERY_API_SET.add(DATA_BASE_QUERY_4);
64 | QUERY_API_SET.add(DATA_BASE_QUERY_5);
65 | QUERY_API_SET.add(DATA_BASE_QUERY_6);
66 | QUERY_API_SET.add(DATA_BASE_QUERY_7);
67 | QUERY_API_SET.add(DATA_BASE_QUERY_8);
68 | QUERY_API_SET.add(DATA_BASE_QUERY_9);
69 | QUERY_API_SET.add(DATA_BASE_QUERY_10);
70 | QUERY_API_SET.add(DATA_BASE_QUERY_11);
71 |
72 | QUERY_API_SET.add(CONTENT_RESOLVER_QUERY_0);
73 | QUERY_API_SET.add(CONTENT_RESOLVER_QUERY_1);
74 | QUERY_API_SET.add(CONTENT_RESOLVER_QUERY_2);
75 | }
76 |
77 | public static final DatabaseUseDetector detector = new DatabaseUseDetector();
78 |
79 |
80 |
81 |
82 | public static void main(String[] args) throws IOException {
83 | String androidJar = "/home/ms/appAnalysis/AndroidHome";
84 | // String androidJar = "/home/ms/appAnalysis/AndroidHome";
85 | // String androidJar = ApkAndJavaConstants.androidJarPath;
86 | String apkDir = "/home/ms/targetApp";
87 | // String apkDir = System.getProperty("user.dir") + File.separator + "App_test";
88 | // String apkDir = "D:\\App\\AppIO\\app\\build\\intermediates\\apk\\debug";
89 | String logName="./log/targetApp.txt";
90 | // String logName="./social_data_use.txt";
91 | Log.openLog(logName, false);
92 |
93 | new DirTraversal() {
94 | @Override
95 | public void work(File apkFile) throws Exception {
96 | if (!apkFile.getName().endsWith(".apk"))
97 | return;
98 | AnalyzeDatabase.logger.info("begin detect App:{}", apkFile);
99 | Log.write(Log.Mode.APP, apkFile.getName());
100 | SootInit.initSootForAndroid(apkFile.getPath(), androidJar);
101 |
102 | HashSet components = ResolveManifest.getAllComponents(apkFile.getPath());
103 | HashMap> component2MapEntryPoint =
104 | EntryPointAnalyze.getComponent2MapEntryPoint(components);
105 |
106 | List entry=new ArrayList<>();
107 | for (String component : component2MapEntryPoint.keySet()) {
108 | HashSet entrypoints = component2MapEntryPoint.get(component);
109 | for(SootMethod method:entrypoints) {
110 | if(method==null)
111 | continue;
112 | entry.add(method);
113 | }
114 | }
115 | AnalyzeDatabase.logger.info("add all clinit method as entrypoint ");
116 | entry.addAll(EntryPointAnalyze.getClinitMethod());
117 | AnalyzeDatabase.logger.info("entry point size: {}",entry.size());
118 | AnalyzeDatabase.logger.info("build cg ...");
119 | long start = System.nanoTime();
120 | CallGraphUtils.buildCGbyCHA(entry);
121 | CallGraph callGraph = Scene.v().getCallGraph();
122 | ReachableMethods reachableMethods = Scene.v().getReachableMethods();
123 | long stop = System.nanoTime();
124 | AnalyzeDatabase.logger.info("build cg coasts :{} seconds",(stop-start)/1E9);
125 | QueueReader listener = reachableMethods.listener();
126 | HashSet riskyMethod=new HashSet<>();
127 | while (listener.hasNext()){
128 | SootMethod method = listener.next().method();
129 | if(QUERY_API_SET.contains(method.getSubSignature())|| FileUsageDefinition.getSharedPreferencesWriteAPIList().contains(method.getSubSignature())||
130 | FileUsageDefinition.getSharedPreferencesReadAPIList().contains(method.getSignature())){
131 | //筛选出可能导致数据库泄漏的方法
132 | Iterator edgeIterator = callGraph.edgesInto(method);
133 | while (edgeIterator.hasNext()){
134 | Edge next = edgeIterator.next();
135 | riskyMethod.add(next.src());
136 | }
137 | }
138 | }
139 | AnalyzeDatabase.logger.info("detect {} methods directly call the risky method in call graph",riskyMethod.size());
140 | HashSet entrySubSignature=new HashSet<>();
141 | for(SootMethod method:entry){
142 | entrySubSignature.add(method.getSubSignature());
143 | }
144 | HashMap> result=new HashMap<>();
145 | detector.setMAX_DEPTH(2);
146 | int count=0;
147 | for(SootMethod method:riskyMethod){
148 | HashSet> paths=new HashSet<>();
149 | CallGraphUtils.findEntryMethod(method,entrySubSignature,"SubSignature",new ArrayList<>(),1,0,paths,false);
150 | for(List path:paths){
151 | AnalyzeDatabase.logger.info("call stack depth: {}",path.size());
152 | Collections.reverse(path);
153 | HashSet points = doAnalyze(method, path);
154 | if(points!=null){
155 | if(!result.containsKey(method.getSignature()))
156 | result.put(method.getSignature(),new HashSet<>());
157 | result.get(method.getSignature()).addAll(points);
158 | }
159 | count++;
160 | }
161 | }
162 | for(String entrypoint:result.keySet()){
163 | writeAnalyzeResult(result.get(entrypoint),entrypoint);
164 | }
165 | AnalyzeDatabase.logger.info("total {} called!",count);
166 | }
167 | }.traverse(new File(apkDir));
168 | Log.closeLog();
169 | }
170 |
171 | public static HashSet doAnalyze(SootMethod method, List callStack) {
172 | if (method == null)
173 | return null;
174 | AnalyzeDatabase.logger.info("detect entrypoint {}", method.getSignature());
175 | detector.setEntryPoint(method.getSignature());
176 | detector.inter_forward(method, 0, callStack);
177 | return detector.getAnalysisResultOfEntry(method.getSignature());
178 | }
179 |
180 | public static void writeAnalyzeResult(HashSet analysisResult, String entryPoint) {
181 | if (analysisResult == null)
182 | return;
183 | for (Point p : analysisResult)
184 | Log.write(Log.Mode.DATA_BASE_SINK, entryPoint, p.unit, p.method, p.type, p.otherMsg);
185 | }
186 |
187 |
188 | public static boolean isSystemClass(String clsName) {
189 | if (clsName.startsWith("java.") || clsName.startsWith("javax."))
190 | return true;
191 | if (clsName.startsWith("android.") || clsName.startsWith("androidx.") || clsName.startsWith("com.google.") || clsName.startsWith("com.android."))
192 | return true;
193 | if (clsName.startsWith("jdk"))
194 | return true;
195 | if (clsName.startsWith("sun."))
196 | return true;
197 | if (clsName.startsWith("org.omg") || clsName.startsWith("org.w3c.dom"))
198 | return true;
199 | return false;
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/src/main/java/analyze/AnalyzeNIO.java:
--------------------------------------------------------------------------------
1 | package analyze;
2 |
3 | import component.EntryPointAnalyze;
4 | import component.ResolveManifest;
5 | import constant.ApkAndJavaConstants;
6 | import dataflow.Point;
7 | import dataflow.StrawDetector;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 | import soot.*;
11 | import soot.jimple.AssignStmt;
12 | import soot.jimple.DefinitionStmt;
13 | import soot.jimple.InvokeExpr;
14 | import soot.jimple.InvokeStmt;
15 | import soot.jimple.infoflow.InfoflowConfiguration;
16 | import soot.jimple.infoflow.android.InfoflowAndroidConfiguration;
17 | import soot.jimple.infoflow.android.SetupApplication;
18 | import soot.jimple.infoflow.android.manifest.binary.AbstractBinaryAndroidComponent;
19 | import soot.jimple.toolkits.callgraph.CallGraph;
20 | import soot.jimple.toolkits.callgraph.Edge;
21 | import soot.jimple.toolkits.callgraph.ReachableMethods;
22 | import soot.util.queue.QueueReader;
23 | import util.DirTraversal;
24 | import util.Log;
25 | import util.SootInit;
26 |
27 | import java.io.*;
28 | import java.util.ArrayList;
29 | import java.util.HashMap;
30 | import java.util.HashSet;
31 | import java.util.Iterator;
32 |
33 |
34 | public class AnalyzeNIO {
35 |
36 | public static final Logger logger = LoggerFactory.getLogger(AnalyzeNIO.class);
37 |
38 |
39 | public static final String SERVER_SOCKET_API = "";
40 | public static final String SERVER_SOCKET_CHANNEL_API_0 = "";
41 | public static final String SERVER_SOCKET_CHANNEL_API_1 = "";
42 | public static final String SERVER_SOCKET_CHANNEL_API_2 = "";
43 |
44 |
45 |
46 | public static final String UDS_API="";
47 | public static final String SERVER_API="";
48 | public static final HashSet NIO_API_List = new HashSet<>();
49 |
50 |
51 | public static final String DATA_READ_IN_PARAM_0="";
52 | public static final String DATA_READ_IN_PARAM_1="";
53 | public static final String DATA_READ_IN_PARAM_2="";
54 | public static final String DATA_READ_IN_PARAM_3="";
55 | public static final String DATA_READ_IN_PARAM_4="";
56 | public static final String DATA_READ_IN_PARAM_5="";
57 | public static final String DATA_READ_IN_PARAM_6="";
58 | public static final String DATA_READ_IN_PARAM_7="";
59 | public static final String DATA_READ_IN_PARAM_8="";
60 | public static final String DATA_READ_IN_PARAM_9="";
61 | public static final String DATA_READ_IN_PARAM_10="";
62 | public static final String DATA_READ_IN_PARAM_11="";
63 | public static final String DATA_READ_IN_PARAM_12="";
64 | public static final String DATA_READ_IN_PARAM_13="";
65 | public static final String DATA_READ_IN_PARAM_14="";
66 | public static final String DATA_READ_IN_PARAM_15="";
67 | public static final String DATA_READ_IN_PARAM_16="";
68 |
69 | public static final HashSet DATA_READ_API=new HashSet<>();
70 |
71 | static {
72 | NIO_API_List.add(UDS_API);
73 | NIO_API_List.add(SERVER_API);
74 |
75 | DATA_READ_API.add(DATA_READ_IN_PARAM_0);
76 | DATA_READ_API.add(DATA_READ_IN_PARAM_1);
77 | DATA_READ_API.add(DATA_READ_IN_PARAM_2);
78 | DATA_READ_API.add(DATA_READ_IN_PARAM_3);
79 | DATA_READ_API.add(DATA_READ_IN_PARAM_4);
80 | DATA_READ_API.add(DATA_READ_IN_PARAM_5);
81 | DATA_READ_API.add(DATA_READ_IN_PARAM_6);
82 | DATA_READ_API.add(DATA_READ_IN_PARAM_7);
83 | DATA_READ_API.add(DATA_READ_IN_PARAM_8);
84 | DATA_READ_API.add(DATA_READ_IN_PARAM_9);
85 | DATA_READ_API.add(DATA_READ_IN_PARAM_10);
86 | DATA_READ_API.add(DATA_READ_IN_PARAM_11);
87 | DATA_READ_API.add(DATA_READ_IN_PARAM_12);
88 | DATA_READ_API.add(DATA_READ_IN_PARAM_13);
89 | DATA_READ_API.add(DATA_READ_IN_PARAM_14);
90 | DATA_READ_API.add(DATA_READ_IN_PARAM_15);
91 | DATA_READ_API.add(DATA_READ_IN_PARAM_16);
92 |
93 | }
94 |
95 | public static final StrawDetector detector=new StrawDetector();
96 |
97 | public static void main(String[] args) throws IOException {
98 | String androidJar = "/home/ms/appAnalysis/AndroidHome";
99 | // String androidJar = ApkAndJavaConstants.androidJarPath;
100 | String apkDir = "/home/shared/download_apks/social";
101 | // String apkDir = System.getProperty("user.dir")+File.separator+"detectedApp";
102 | // String apkDir = "D:\\App\\AppIO\\app\\build\\intermediates\\apk\\debug";
103 |
104 | //
105 | Log.openLog("/home/ms/appAnalysis/log/NIO.txt", false);
106 | // Log.openLog("./NIO.txt", false);
107 |
108 | detector.setTaintWrapper(DATA_READ_API);
109 | new DirTraversal() {
110 | @Override
111 | public void work(File apkFile) throws Exception {
112 | if (!apkFile.getName().endsWith(".apk"))
113 | return;
114 | AnalyzeNIO.logger.info("begin detect App:{}", apkFile);
115 | Log.write(Log.Mode.APP, apkFile.getName());
116 |
117 | SootInit.initSootForAndroid(apkFile.getPath(), androidJar);
118 | boolean flag = false;
119 | for (String apiSignature : NIO_API_List) {
120 | try {
121 | SootMethod method = Scene.v().getMethod(apiSignature);
122 | flag=true;
123 | } catch (Exception e) {
124 | }
125 | }
126 | if (!flag)
127 | return;
128 | for (SootClass cls : Scene.v().getApplicationClasses()) {
129 | if(isSystemClass(cls.getName()))
130 | continue;
131 | for (SootMethod m : cls.getMethods()) {
132 | try {
133 | if (m.isJavaLibraryMethod())
134 | continue;
135 | if (m.isAbstract())
136 | continue;
137 | if (m.isPhantom())
138 | continue;
139 | if (m.isNative())
140 | continue;
141 | for (Unit u : m.retrieveActiveBody().getUnits()) {
142 | if (!(u instanceof AssignStmt))
143 | continue;
144 | AssignStmt assignStmt = (AssignStmt) u;
145 | if (!(assignStmt.containsInvokeExpr()))
146 | continue;
147 | String signature = assignStmt.getInvokeExpr().getMethod().getSignature();
148 | if (!NIO_API_List.contains(signature))
149 | continue;
150 | doAnalysis(m, u);
151 | }
152 | } catch (Exception e) {
153 | }
154 | }
155 | }
156 | }
157 | }.traverse(new File(apkDir));
158 | Log.closeLog();
159 | }
160 |
161 | public static void doAnalysis(SootMethod caller,Unit callSite){
162 | if(!(callSite instanceof DefinitionStmt))
163 | return;
164 | DefinitionStmt definitionStmt = (DefinitionStmt) callSite;
165 | ValueBox valueBox = definitionStmt.getDefBoxes().get(0);
166 | //寻找数据流中的是数据流动
167 | detector.setEntryPoint(caller.getSignature());
168 | AnalyzeNIO.logger.info("detect NIO in {}",caller.getSignature());
169 | detector.run(caller,callSite,valueBox,0,0,new ArrayList<>());
170 | HashSet result = detector.getAnalysisResultOfEntry(caller.getSignature());
171 | if(result!=null)
172 | writeAnalyzeResult(result,caller.getSignature());
173 | }
174 |
175 | public static void writeAnalyzeResult(HashSet analysisResult, String entryPoint) {
176 | if (analysisResult == null)
177 | return;
178 | for (Point p : analysisResult)
179 | Log.write(Log.Mode.SINK, entryPoint, p.unit, p.method, p.type);
180 | }
181 |
182 | public static boolean isSystemClass(String clsName){
183 | if(clsName.startsWith("java.")||clsName.startsWith("javax."))
184 | return true;
185 | if(clsName.startsWith("android.")||clsName.startsWith("androidx.")||clsName.startsWith("com.google.")||clsName.startsWith("com.android."))
186 | return true;
187 | if(clsName.startsWith("jdk"))
188 | return true;
189 | if(clsName.startsWith("sun."))
190 | return true;
191 | if(clsName.startsWith("org.omg")||clsName.startsWith("org.w3c.dom"))
192 | return true;
193 | return false;
194 | }
195 |
196 |
197 |
198 | }
199 |
--------------------------------------------------------------------------------
/src/main/java/analyze/AnalyzeService.java:
--------------------------------------------------------------------------------
1 | package analyze;
2 |
3 | import dataflow.Point;
4 | import dataflow.StrawDetector;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import soot.*;
8 | import soot.options.Options;
9 | import util.Log;
10 |
11 | import java.io.BufferedReader;
12 | import java.io.FileReader;
13 | import java.util.ArrayList;
14 | import java.util.Collections;
15 | import java.util.HashMap;
16 | import java.util.HashSet;
17 |
18 |
19 | public class AnalyzeService {
20 |
21 | public static final Logger logger = LoggerFactory.getLogger(AnalyzeService.class);
22 |
23 | public static final String service_path = "/home/lkk/AndroidStudy_StaticAnalysis/DeviceData/Android11_Pixel3XL/InputData/Jimple";
24 | public static final String entry_point_path = "/home/ms/appAnalysis/entrypoint.txt";
25 |
26 | private static final StrawDetector detector = new StrawDetector();
27 |
28 | private static String logFileName = "serviceLog.txt";
29 |
30 | public static void initSoot() {
31 |
32 | G.reset();
33 |
34 |
35 |
36 | Options.v().set_allow_phantom_refs(true);
37 | Options.v().set_whole_program(true);
38 | Options.v().set_src_prec(Options.src_prec_jimple);
39 | Options.v().set_process_dir(Collections.singletonList(service_path));
40 | Options.v().set_output_format(Options.output_format_none);
41 | ArrayList excludeList = new ArrayList<>();
42 | excludeList.add("java.*");
43 | excludeList.add("sun.*");
44 | Options.v().set_exclude(excludeList);
45 | Options.v().set_drop_bodies_after_load(false);
46 | Options.v().set_no_bodies_for_excluded(true);
47 | Scene.v().loadNecessaryClasses();
48 | }
49 |
50 | public static void main(String[] args) {
51 | initSoot();
52 | logger.info("detector begin running ...");
53 | HashMap> entryFromText = getEntryFromText();//获取所有的系统服务
54 | Log.openLog(logFileName, true);
55 | ArrayList entrypointList = new ArrayList<>();
56 |
57 | for (String service : entryFromText.keySet()) {
58 | for (String interfaceName : entryFromText.get(service)) {
59 | try {
60 | SootMethod method = Scene.v().getMethod(interfaceName);
61 | entrypointList.add(method);
62 | } catch (Exception e) {
63 | logger.info("the method don't exist");
64 | }
65 | }
66 | }
67 |
68 | logger.info("begin building call graph ...");
69 | Scene.v().setEntryPoints(entrypointList);
70 | long start = System.nanoTime();
71 | PackManager.v().getPack("cg").apply();
72 | long end = System.nanoTime();
73 | logger.info("building call graph for {} entry points costs {} seconds", entrypointList.size(), (end - start) / 1e9);
74 |
75 |
76 | for (String service : entryFromText.keySet()) {
77 |
78 | logger.info("detect service {}", service);
79 | Log.write(Log.Mode.SERVICE, service);
80 | for (String interfaceName : entryFromText.get(service)) {
81 | SootMethod method = null;
82 | try {
83 | method = Scene.v().getMethod(interfaceName);
84 | Log.write(Log.Mode.INTERFACE, interfaceName);
85 | for (int i = 0; i < method.getParameterCount(); i++) {
86 | Type type = method.getParameterTypes().get(i);
87 | if(!isPrimativeType(type.toString())) {
88 | logger.info("detect interface {}", interfaceName);
89 | detector.setEntryPoint(interfaceName);
90 | detector.run(method, null, null, i, 0, new ArrayList<>());
91 | }
92 | }
93 | HashSet analysisResultOfEntry = detector.getAnalysisResultOfEntry(interfaceName);
94 | writeAnalyzeResult(analysisResultOfEntry,interfaceName);
95 | } catch (Exception e) {
96 | logger.info("the method don't exist");
97 | }
98 | }
99 | }
100 | Log.closeLog();
101 | }
102 |
103 | public static HashMap> getEntryFromText() {
104 | HashMap> res = new HashMap<>();
105 |
106 | try {
107 | FileReader fileReader = new FileReader(entry_point_path);
108 | BufferedReader reader = new BufferedReader(fileReader);
109 | String line = null;
110 | String service = null;
111 | HashSet serviceInterface = new HashSet<>();
112 | while ((line = reader.readLine()) != null) {
113 | if (line.contains("系统服务")) {
114 | if (service != null) {
115 | res.put(service, (HashSet) serviceInterface.clone());
116 | serviceInterface.clear();
117 | }
118 | service = line.substring(6);
119 | } else {
120 | serviceInterface.add(line.substring(6));
121 | }
122 | }
123 | } catch (Exception e) {
124 | e.printStackTrace();
125 | }
126 | return res;
127 | }
128 |
129 | public static void writeAnalyzeResult(HashSet analysisResult, String entryPoint) {
130 | if (analysisResult == null)
131 | return;
132 | for (Point p : analysisResult)
133 | Log.write(Log.Mode.SINK, entryPoint, p.unit, p.method, p.type);
134 | }
135 |
136 | public static boolean isPrimativeType(String type){
137 | if(type.equals("int")||type.equals("long")||type.equals("float")||type.equals("double")||type.equals("boolean"))
138 | return true;
139 | return false;
140 | }
141 |
142 |
143 |
144 |
145 |
146 | }
147 |
--------------------------------------------------------------------------------
/src/main/java/analyze/FileUseAnalyze.java:
--------------------------------------------------------------------------------
1 | package analyze;
2 |
3 | import component.EntryPointAnalyze;
4 | import component.ResolveManifest;
5 | import constant.ApkAndJavaConstants;
6 | import dataflow.FileUseDetector;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 | import soot.Scene;
10 | import soot.SootMethod;
11 | import soot.Unit;
12 | import soot.jimple.infoflow.android.manifest.ProcessManifest;
13 | import soot.jimple.infoflow.android.manifest.binary.AbstractBinaryAndroidComponent;
14 | import util.DirTraversal;
15 | import util.Log;
16 | import util.SootInit;
17 |
18 | import java.io.File;
19 | import java.util.ArrayList;
20 | import java.util.HashMap;
21 | import java.util.HashSet;
22 |
23 |
24 | public class FileUseAnalyze {
25 |
26 | // private static String apkPath = ApkAndJavaConstants.apkDir;
27 | private static String apkPath = System.getProperty("user.dir")+File.separator+"targetApp";
28 | // private static String apkPath ="/home/shared/download_apks";
29 | // private static String androidJar = ApkAndJavaConstants.androidJarPath;
30 | private static String androidJar = "/home/ms/appAnalysis/AndroidHome";
31 |
32 | public static final Logger logger= LoggerFactory.getLogger(FileUseAnalyze.class);
33 |
34 | public static final FileUseDetector detector=new FileUseDetector();
35 |
36 | public static final String logRootPath="/home/ms/appAnalysis/log/appUseFileInfo";
37 |
38 |
39 | public static void main(String[] args) {
40 | // apkPath=args[0];
41 | // androidJar=args[1];
42 | File apkDir=new File(apkPath);
43 | Log.openLog("fileNameRebuild.txt",false);
44 | new DirTraversal(){
45 | @Override
46 | public void work(File apkFile) throws Exception {
47 | if(!apkFile.getName().endsWith(".apk"))
48 | return;
49 | FileUseAnalyze.logger.info("开始检测App:{}",apkFile);
50 | Log.write(Log.Mode.APP,apkFile.getName());
51 | HashSet components = ResolveManifest.getAllComponents(apkFile.getPath());
52 | SootInit.initSootForAndroid(apkFile.getPath(), androidJar);
53 | HashMap> component2MapEntryPoint =
54 | EntryPointAnalyze.getComponent2MapEntryPoint(components);
55 | Scene.v().getOrMakeFastHierarchy();
56 | String packageName = ResolveManifest.getPackageName(apkFile);
57 | detector.setPackageName(packageName);
58 | for (String component : component2MapEntryPoint.keySet()) {
59 | FileUseAnalyze.logger.info("开始检测Component:{}",component);
60 | HashSet entrypoints = component2MapEntryPoint.get(component);
61 | for(SootMethod method:entrypoints) {
62 | if(method==null)
63 | continue;
64 | FileUseAnalyze.logger.info("开始检测入entry point:{}",method.getSignature());
65 | doAnalyze(method);
66 | }
67 |
68 | }
69 | FileUseAnalyze.logger.info("结束了");
70 | detector.writeLog();
71 | Scene.v().releaseFastHierarchy();
72 | }
73 | }.traverse(apkDir);
74 | Log.closeLog();
75 | }
76 |
77 | public void analyze(String apkPath){
78 | if(!apkPath.endsWith(".apk"))
79 | return;
80 | File apkFile = new File(apkPath);
81 | FileUseAnalyze.logger.info("开始检测App:{}",apkFile);
82 | HashSet components = ResolveManifest.getAllComponents(apkPath);
83 | SootInit.initSootForAndroid(apkFile.getPath(), androidJar);
84 | HashMap> component2MapEntryPoint =
85 | EntryPointAnalyze.getComponent2MapEntryPoint(components);
86 | Scene.v().getOrMakeFastHierarchy();
87 | String packageName = ResolveManifest.getPackageName(apkFile);
88 | detector.setPackageName(packageName);
89 | Log.openLog(String.format("%s/%s.txt",logRootPath,packageName),false);
90 | Log.write(Log.Mode.APP,apkFile.getName());
91 | for (String component : component2MapEntryPoint.keySet()) {
92 | // FileUseAnalyze.logger.info("开始检测Component:{}",component);
93 | HashSet entrypoints = component2MapEntryPoint.get(component);
94 | for(SootMethod method:entrypoints) {
95 | if(method==null)
96 | continue;
97 | // FileUseAnalyze.logger.info("开始检测入entry point:{}",method.getSignature());
98 | doAnalyze(method);
99 | }
100 |
101 |
102 |
103 | }
104 | // FileUseAnalyze.logger.info("结束了");
105 | detector.writeLog();
106 | Scene.v().releaseFastHierarchy();
107 | Log.closeLog();
108 | }
109 |
110 | public static void doAnalyze(SootMethod method){
111 | if(method==null)
112 | return;
113 | detector.inter_forward(method,0,new ArrayList<>());
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/main/java/analyze/Main.java:
--------------------------------------------------------------------------------
1 | package analyze;
2 |
3 | import cg.CallGraphUtils;
4 | import component.EntryPointAnalyze;
5 | import component.ResolveManifest;
6 | import constant.ApkAndJavaConstants;
7 | import constant.EntryPointsDefinition;
8 | import constant.StrawPointsDefinition;
9 | import dataflow.Point;
10 | import dataflow.StrawDetector;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 | import org.xmlpull.v1.XmlPullParserException;
14 | import soot.*;
15 | import soot.jimple.AssignStmt;
16 | import soot.jimple.infoflow.android.manifest.binary.AbstractBinaryAndroidComponent;
17 | import util.DirTraversal;
18 | import util.Log;
19 | import util.SootInit;
20 |
21 | import java.io.*;
22 | import java.util.*;
23 |
24 |
25 | public class Main {
26 |
27 | private static String apkDir = ApkAndJavaConstants.apkDir;
28 | private static String androidJar = ApkAndJavaConstants.androidJarPath;
29 | private static final Logger logger = LoggerFactory.getLogger(Main.class);
30 |
31 | private static final List lifeCycleMethodList = EntryPointsDefinition.getAllLifeCycleMethodList();
32 |
33 | private static final String GET_INTENT = "android.content.Intent getIntent()";
34 |
35 | private static final StrawDetector analyzer=new StrawDetector();
36 |
37 | private static String logFileName = "Log.txt";
38 |
39 | private static String permissionInfoPath="./PermissionInfo.txt";
40 |
41 | private static int max = 100000;
42 |
43 | private static HashSet filterAppSet=new HashSet<>();
44 |
45 | private static String appFilterFile="/home/ms/appAnalysis/filterApp.txt";
46 |
47 |
48 | public static void main(String[] args) throws IOException, XmlPullParserException {
49 |
50 | // apkDir = args[0];
51 | apkDir = System.getProperty("user.dir")+File.separator+"App_test";
52 | // androidJar = args[1];
53 | androidJar = ApkAndJavaConstants.androidJarPath;
54 | // logFileName = args[2];
55 | logFileName = "./detectData";
56 | // max = Integer.parseInt(args[3]);
57 | max = 100;
58 | // permissionInfoPath=args[4];
59 | permissionInfoPath=System.getProperty("user.dir")+File.separator+"PermissionInfo.txt";
60 |
61 | logger.info("the straw detector begin running ...");
62 |
63 | // appFilterFile=args[5];
64 | appFilterFile="./filterApp.txt";
65 |
66 |
67 | Log.openLog(logFileName, false);
68 | File apkDir = new File(Main.apkDir);
69 |
70 | HashSet detectedAppInfo = getDetectedAppInfo(logFileName);
71 | logger.info("retrieve permission info ... ");
72 | HashMap permissionInfo = getDevicePermissionInfo(new File(permissionInfoPath));
73 | logger.info("init filter app set ...");
74 | initFilterApp();
75 |
76 | final int[] counter = {0};
77 |
78 | new DirTraversal(){
79 | @Override
80 | public void work(File apkFile) throws Exception {
81 |
82 | if (counter[0] > max)
83 | return;
84 | if(detectedAppInfo.contains(apkFile.getName()))
85 | return;
86 | if(!apkFile.getName().endsWith(".apk"))
87 | return;
88 | if(!filterAppSet.isEmpty()&&!filterAppSet.contains(apkFile.getName().split(".apk")[0].trim()))
89 | return;
90 |
91 | counter[0]++;
92 |
93 | Log.write(Log.Mode.APP, apkFile.getName());
94 | String versionName = ResolveManifest.getVersionName(apkFile);
95 | Log.write(Log.Mode.VERSION,versionName);
96 | Log.write(Log.Mode.PATH,apkFile.getPath());
97 |
98 | Main.logger.info("straw detector begin detect {}", apkFile.getName());
99 |
100 | Main.logger.info("straw detector begin detecting all exported components ");
101 | HashSet components = ResolveManifest.getReachableComponents(apkFile.getPath(),permissionInfo,new HashSet<>());
102 | SootInit.initSootForAndroid(apkFile.getPath(), androidJar);
103 | Main.logger.info("begin detecting app: {} ,there are {} exported components in it", apkFile.getName(), components.size());
104 | HashMap> component2MapEntryPoint =
105 | EntryPointAnalyze.getComponent2MapEntryPoint(components);
106 | // List entryPoints=new ArrayList<>();
107 | // for (String component : component2MapEntryPoint.keySet()) {
108 | // HashSet entrypoints = component2MapEntryPoint.get(component);
109 | // for(SootMethod m:entrypoints){
110 | // if(m==null)
111 | // continue;
112 | // entryPoints.add(m);
113 | // }
114 | // }
115 | // Scene.v().setEntryPoints(entryPoints);
116 | // try {
117 | // Main.logger.info("begin build cg ...");
118 | // PackManager.v().getPack("cg").apply();
119 | // }catch (Exception e){
120 | // return;
121 | // }
122 | Main.logger.info("begin data flow analyze");
123 | for (String component : component2MapEntryPoint.keySet()) {
124 | HashSet entrypoints = component2MapEntryPoint.get(component);
125 | Main.logger.info("begin detect component: {} there are {} entry points that may be exploited", component, entrypoints.size());
126 | doAnalyze(entrypoints, component);
127 | }
128 | }
129 | }.traverse(apkDir);
130 | Log.closeLog();
131 |
132 | }
133 |
134 | private static void doAnalyze(HashSet entrypoints, String component) {
135 |
136 | boolean flag = false;
137 |
138 | for (SootMethod entryPoint : entrypoints) {
139 | if (entryPoint == null)
140 | continue;
141 | analyzer.setEntryPoint(entryPoint.getSignature());
142 | logger.info("begin detecting {}", entryPoint.getSignature());
143 | if (lifeCycleMethodList.contains(entryPoint.getSubSignature())) {
144 | int index = 0;
145 | List parameterTypes = entryPoint.getParameterTypes();
146 | for (; index < parameterTypes.size(); index++) {
147 | if (parameterTypes.get(index).toString().equals("android.content.Intent") || parameterTypes.get(index).toString().equals("android.content.ContentValues"))
148 | break;
149 | }
150 | if (index != parameterTypes.size()) {
151 | logger.info("run data flow analyze ....");
152 | analyzer.run(entryPoint,null,null,index,0,new ArrayList<>());
153 | }
154 | // 分析代码中是否包含getIntent调用
155 | HashSet invokeUnits = getGetIntentInvokeUnit(entryPoint);
156 | for (Unit invokeUnit : invokeUnits) {
157 | logger.info("run data flow analyze ...");
158 | analyzer.run(entryPoint,invokeUnit,invokeUnit.getDefBoxes().get(0),0,0,new ArrayList<>() );
159 | }
160 |
161 | } else {
162 | logger.info("this is an onBind service {}", entryPoint.getSignature());
163 | int parameterCount = entryPoint.getParameterCount();
164 | for (int index = 0; index < parameterCount; index++) {
165 | logger.info("run data flow analyze ....");
166 | analyzer.run(entryPoint,null,null,index,0,new ArrayList<>());
167 | }
168 | }
169 | HashSet analysisResultOfEntry = analyzer.getAnalysisResultOfEntry(entryPoint.getSignature());
170 | if(analysisResultOfEntry!=null){
171 | writeAnalyzeResult(analysisResultOfEntry,entryPoint.getSignature());
172 | flag=true;
173 | }
174 | }
175 | if (flag) {
176 | Log.write(Log.Mode.COMPONENT, component);
177 | }
178 |
179 | }
180 |
181 | public static void writeAnalyzeResult(HashSet analysisResult, String entryPoint) {
182 | if (analysisResult == null)
183 | return;
184 | for (Point p : analysisResult)
185 | Log.write(Log.Mode.SINK, entryPoint, p.unit, p.method, p.type,p.otherMsg);
186 | }
187 |
188 | private static boolean reachableAnalyze(SootMethod method) {
189 |
190 | boolean entry_usable = false;
191 | if (!lifeCycleMethodList.contains(method.getSubSignature())) {
192 | //如果是bounded Service
193 | entry_usable = true;
194 | } else {
195 | for (Type paramType : method.getParameterTypes()) {
196 | if (paramType.toString().equals("android.content.Intent") || paramType.toString().equals("android.content.ContentValues")) {
197 | entry_usable = true;
198 | break;
199 | }
200 | }
201 | if (!entry_usable) {
202 | if (CallGraphUtils.isMethodReachable2Target(method, "android.content.Intent getIntent()"))
203 | entry_usable = true;
204 | }
205 |
206 | }
207 | if (entry_usable) {
208 | if (CallGraphUtils.isMethodReachable2Target(method, StrawPointsDefinition.getAllInsertMethodList()))//这个方法并不通用
209 | return true;
210 | logger.info("no straw point is found in the call chain");
211 | return false;
212 |
213 | } else {
214 | logger.info("no getIntent is called and no parameter is usable");
215 | return false;
216 | }
217 | }
218 |
219 | public static HashSet getGetIntentInvokeUnit(SootMethod method) {
220 | HashSet res = new HashSet<>();
221 | for (Unit unit : method.retrieveActiveBody().getUnits()) {
222 | if (unit instanceof AssignStmt) {
223 | AssignStmt assignStmt = (AssignStmt) unit;
224 | if (assignStmt.containsInvokeExpr()) {
225 | String subSignature = assignStmt.getInvokeExpr().getMethod().getSubSignature();
226 | if (subSignature.equals(GET_INTENT)) {
227 | res.add(unit);
228 | }
229 | }
230 | }
231 | }
232 | return res;
233 | }
234 |
235 | public static HashSet getDetectedAppInfo(String fileName){
236 | HashSet res=new HashSet<>();
237 | try {
238 | FileReader fileReader = new FileReader(fileName);
239 | BufferedReader reader = new BufferedReader(fileReader);
240 | String line=null;
241 | while ((line=reader.readLine())!=null){
242 | if(line.contains("APP:")){
243 | String[] split = line.split(":");
244 | res.add(split[1].substring(1));
245 | }
246 | }
247 | }catch (Exception e){
248 | e.printStackTrace();
249 | }
250 | return res;
251 | }
252 |
253 | public static HashMap getDevicePermissionInfo(File permissionFile){
254 | HashMap res=new HashMap<>();
255 | try {
256 | FileInputStream in = new FileInputStream(permissionFile);
257 | BufferedReader reader = new BufferedReader(new InputStreamReader(in));
258 | String line=null;
259 | String permission=null;
260 | String protectLevel=null;
261 | while ((line=reader.readLine())!=null){
262 | if(line.contains("permission:")){
263 | permission=line.split(":")[1];
264 | }
265 | if(line.contains("protectionLevel:")){
266 | protectLevel=line.split(":")[1];
267 | if(protectLevel.contains("normal")) {
268 | res.put(permission, 0);
269 | }else if(protectLevel.contains("dangerous")){
270 | res.put(permission,1);
271 | }else if(protectLevel.contains("signature")) {
272 | res.put(permission, 2);
273 | }else {
274 | res.put(permission,3);
275 | }
276 | }
277 | }
278 | return res;
279 | }catch (Exception e){
280 | return res;
281 | }
282 | }
283 |
284 | public static void initFilterApp(){
285 | try {
286 | File file = new File(appFilterFile);
287 | FileReader reader = new FileReader(file);
288 | BufferedReader bufferedReader = new BufferedReader(reader);
289 | String line=null;
290 | while ((line=bufferedReader.readLine())!=null){
291 | filterAppSet.add(line.trim());
292 | }
293 | }catch (Exception e){
294 | e.printStackTrace();
295 | }
296 | }
297 |
298 |
299 | }
300 |
--------------------------------------------------------------------------------
/src/main/java/analyze/MainAnalyze.java:
--------------------------------------------------------------------------------
1 | package analyze;
2 |
3 | import constant.ApkAndJavaConstants;
4 | import dataflow.ExportedConfigFileDetector;
5 | import org.xmlpull.v1.XmlPullParserException;
6 | import soot.Scene;
7 | import soot.SootClass;
8 | import soot.jimple.infoflow.android.axml.AXmlNode;
9 | import soot.jimple.infoflow.android.manifest.IAndroidComponent;
10 | import soot.jimple.infoflow.android.manifest.ProcessManifest;
11 | import soot.jimple.infoflow.android.manifest.binary.BinaryManifestActivity;
12 | import soot.jimple.infoflow.android.manifest.binary.BinaryManifestBroadcastReceiver;
13 | import soot.jimple.infoflow.android.manifest.binary.BinaryManifestContentProvider;
14 | import soot.jimple.infoflow.android.manifest.binary.BinaryManifestService;
15 | import util.SootInit;
16 |
17 | import java.io.*;
18 | import java.util.HashMap;
19 | import java.util.HashSet;
20 | import java.util.List;
21 | import java.util.Set;
22 |
23 |
24 | public class MainAnalyze {
25 |
26 |
27 | public static String apkDir="";
28 |
29 | public static String androidJar="";
30 |
31 | public static String logFileName="";
32 |
33 | public static String permissionInfoFile="";
34 |
35 | public static String filterAppInfo="";
36 |
37 | public static String sinkInfo="";
38 |
39 | public static String dataSavedDir="";
40 |
41 | public static String systemActionFile="";
42 |
43 | public static void main(String[] args) throws Exception {
44 |
45 | // apkDir=System.getProperty("user.dir")+ File.separator+"app";
46 | apkDir="/home/shared/download_apks";
47 |
48 | // androidJar= ApkAndJavaConstants.androidJarPath;
49 | androidJar= "/home/ms/appAnalysis/AndroidHome";
50 | // logFileName="Log.txt";
51 | logFileName="log7.txt";
52 |
53 | // logFileName="myLog.txt";
54 | //
55 | // permissionInfoFile=System.getProperty("user.dir")+ File.separator+"PermissionInfo.txt";
56 | permissionInfoFile="/home/ms/ICFinder/PermissionInfo_Pixel3.txt";
57 |
58 | // filterAppInfo="./filterApp.txt";
59 | // sinkInfo=System.getProperty("user.dir")+File.separator+"sinks"+File.separator+"sink.txt";
60 | sinkInfo="/home/ms/ICFinder/sinks/sink.txt";
61 |
62 | dataSavedDir=System.getProperty("user.dir")+File.separator+"analyze_result";
63 |
64 | // systemActionFile=System.getProperty("user.dir")+File.separator+"SystemProtectedBroadcast_Pixel3.txt";
65 | systemActionFile="/home/ms/ICFinder/SystemProtectedBroadcast_Pixel3.txt";
66 |
67 | //
68 |
69 | ExportedConfigFileDetector detector = new ExportedConfigFileDetector(apkDir, androidJar, logFileName, permissionInfoFile,systemActionFile,sinkInfo,dataSavedDir);
70 | detector.cal_exportComponentNumber();
71 | // detector.analyze();
72 | // detector.setTimeout(10000);
73 | // detector.start();
74 |
75 | }
76 |
77 |
78 | public static void runAnalyze(String apkPath){
79 |
80 | // apkDir="/home/shared/download_apks";
81 | apkDir="/home/ms/target";
82 | androidJar= "/home/ms/appAnalysis/AndroidHome";
83 | logFileName="log7.txt";
84 | permissionInfoFile="/home/ms/ICFinder/PermissionInfo_Pixel3.txt";
85 | filterAppInfo="./filterApp.txt";
86 | sinkInfo="/home/ms/ICFinder/sinks/sink.txt";
87 | dataSavedDir="/home/ms/ICFinder/analyze_result/data7";
88 | systemActionFile="/home/ms/ICFinder/SystemProtectedBroadcast_Pixel3XL.txt";
89 |
90 | ExportedConfigFileDetector detector = new ExportedConfigFileDetector(apkDir, androidJar, logFileName, permissionInfoFile, systemActionFile,sinkInfo,dataSavedDir);
91 | detector.run(apkPath);
92 | }
93 |
94 | public static void analyze(String apkPath){
95 | androidJar= "/home/ms/appAnalysis/AndroidHome";
96 | SootInit.initSootForAndroid(apkPath,androidJar);
97 | System.out.println("开始分析:"+apkPath);
98 |
99 | boolean flag=false;
100 | for(SootClass cls:Scene.v().getClasses())
101 | if(cls.getName().contains("com.alibaba.fastjson")){
102 | flag=true;
103 | break;
104 | }
105 | if(flag){
106 | try {
107 | FileWriter fileWriter = new FileWriter("/home/ms/ICFinder/fastJosn.txt",true);
108 | BufferedWriter writer = new BufferedWriter(fileWriter);
109 | writer.write(apkPath+'\n');
110 | writer.close();
111 | }catch (Exception e){
112 | e.printStackTrace();
113 | }
114 |
115 | }
116 | }
117 |
118 | //获取设备中的权限信息
119 | public static HashMap getDevicePermissionInfo(File permissionFile) {
120 | HashMap res = new HashMap<>();
121 | try {
122 | FileInputStream in = new FileInputStream(permissionFile);
123 | BufferedReader reader = new BufferedReader(new InputStreamReader(in));
124 | String line = null;
125 | String permission = null;
126 | String protectLevel = null;
127 | while ((line = reader.readLine()) != null) {
128 | if (line.contains("permission:")) {
129 | permission = line.split(":")[1];
130 | }
131 | if (line.contains("protectionLevel:")) {
132 | protectLevel = line.split(":")[1];
133 | if (protectLevel.contains("normal")) {
134 | res.put(permission, 0);
135 | } else if (protectLevel.contains("dangerous")) {
136 | res.put(permission, 1);
137 | } else if (protectLevel.contains("signature")) {
138 | res.put(permission, 2);
139 | } else {
140 | res.put(permission, 3);
141 | }
142 | }
143 | }
144 | return res;
145 | } catch (Exception e) {
146 | return res;
147 | }
148 | }
149 |
150 |
151 | // 对于给定应用的指定组件统计他们是不是存在权限申明了permission但是permission是normal的级别
152 |
153 |
154 | public static void analyze(String apkPath, HashSet components) throws XmlPullParserException, IOException {
155 | //我们需要获得设备的权限列表
156 | permissionInfoFile="/home/ms/ICFinder/PermissionInfo_Pixel3.txt";
157 | System.out.println("开始分析应用:"+apkPath);
158 | HashMap devicePermissionInfo = getDevicePermissionInfo(new File(permissionInfoFile));
159 |
160 | ProcessManifest manifest = new ProcessManifest(apkPath);
161 | HashSet res=new HashSet<>();
162 |
163 | //获取应用种自定义权限和他保护等级的映射
164 | for(AXmlNode permission:manifest.getManifest().getChildrenWithTag("permission")) {
165 | if(permission.getAttribute("protectionLevel") == null) devicePermissionInfo.put(permission.getAttribute("name").getValue().toString(), 0);
166 | else {
167 | devicePermissionInfo.put(permission.getAttribute("name").getValue().toString(),(Integer) permission.getAttribute("protectionLevel").getValue());
168 | }
169 | }
170 |
171 | //开始遍历组件
172 | //判断这个组件是不是我们要找的组件,如果是我们看是否申明了权限,如果申明了,看他的权限是不不是normal级别的
173 | for(BinaryManifestService service: manifest.getServices()){
174 | AXmlNode aXmlNode=service.getAXmlNode();
175 | String componentName = aXmlNode.getAttribute("name").getValue().toString();
176 | if(!components.contains(componentName))
177 | continue;
178 | System.out.println("检测到组件");
179 | if(!aXmlNode.hasAttribute("permission"))
180 | continue;
181 | String permission = aXmlNode.getAttribute("permission").getValue().toString();
182 | System.out.println("权限是:"+permission);
183 | if(devicePermissionInfo.get(permission)==0){
184 | //如果应用中的权限未定义或者该权限的级别只为normal,那么记录下该应用以及组件
185 | res.add(componentName);
186 | }
187 | }
188 | for(BinaryManifestActivity activity: manifest.getActivities()){
189 | AXmlNode aXmlNode=activity.getAXmlNode();
190 | String componentName = aXmlNode.getAttribute("name").getValue().toString();
191 | if(!components.contains(componentName))
192 | continue;
193 | System.out.println("检测到组件");
194 | if(!aXmlNode.hasAttribute("permission"))
195 | continue;
196 | String permission = aXmlNode.getAttribute("permission").getValue().toString();
197 | System.out.println("权限是:"+permission);
198 | if(devicePermissionInfo.get(permission)==0){
199 | //如果应用中的权限未定义或者该权限的级别只为normal,那么记录下该应用以及组件
200 | res.add(componentName);
201 | }
202 | }
203 | for(BinaryManifestBroadcastReceiver receiver: manifest.getBroadcastReceivers()){
204 | AXmlNode aXmlNode=receiver.getAXmlNode();
205 | String componentName = aXmlNode.getAttribute("name").getValue().toString();
206 | if(!components.contains(componentName))
207 | continue;
208 | System.out.println("检测到组件");
209 | if(!aXmlNode.hasAttribute("permission"))
210 | continue;
211 | String permission = aXmlNode.getAttribute("permission").getValue().toString();
212 | System.out.println("权限是:"+permission);
213 |
214 | if(devicePermissionInfo.get(permission)==0){
215 | //如果应用中的权限未定义或者该权限的级别只为normal,那么记录下该应用以及组件
216 | res.add(componentName);
217 | }
218 | }
219 | for(BinaryManifestContentProvider provider: manifest.getContentProviders()){
220 | AXmlNode aXmlNode=provider.getAXmlNode();
221 | //provider这里我们只关心它的write permission
222 | String componentName = aXmlNode.getAttribute("name").getValue().toString();
223 | if(!components.contains(componentName))
224 | continue;
225 | System.out.println("检测到组件");
226 |
227 | if(!aXmlNode.hasAttribute("writePermission"))
228 | continue;
229 | String permission = aXmlNode.getAttribute("writePermission").getValue().toString();
230 | System.out.println("权限是:"+permission);
231 |
232 | if(devicePermissionInfo.get(permission)==0){
233 | //如果应用中的权限未定义或者该权限的级别只为normal,那么记录下该应用以及组件
234 | res.add(componentName);
235 | }
236 | }
237 |
238 | //我们根据分析结果进行统计
239 | if(res.isEmpty())
240 | return;
241 | System.out.println("检测到使用权限过低的组件");
242 | try{
243 | BufferedWriter writer = new BufferedWriter(new FileWriter("/home/ms/ICFinder/weakPermissionAppAndConponents", true));
244 | writer.write("App:"+apkPath+'\n');
245 | for(String component : res){
246 | writer.write("COMPONENT:"+component+'\n');
247 | }
248 | writer.close();
249 |
250 | }catch (Exception e){
251 | e.printStackTrace();
252 | }
253 |
254 | }
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 | }
263 |
--------------------------------------------------------------------------------
/src/main/java/cfg/CfgFactory.java:
--------------------------------------------------------------------------------
1 | package cfg;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import soot.Body;
6 | import soot.SootMethod;
7 | import soot.Unit;
8 | import soot.toolkits.graph.BriefUnitGraph;
9 |
10 | import java.util.ArrayList;
11 | import java.util.HashMap;
12 | import java.util.HashSet;
13 | import java.util.List;
14 |
15 |
16 | public class CfgFactory {
17 |
18 | private static final Logger logger = LoggerFactory.getLogger(CfgFactory.class);
19 |
20 | private static CfgFactory cfgFactory = null;
21 | private HashMap methodMapCfg = new HashMap<>();
22 |
23 | private HashMap> methodMapPath=new HashMap<>();
24 |
25 | private CfgFactory() {
26 | }
27 |
28 | public static CfgFactory getInstance() {
29 | if (cfgFactory == null)
30 | cfgFactory = new CfgFactory();
31 | return cfgFactory;
32 | }
33 |
34 |
35 | public BriefUnitGraph getCFG(SootMethod sootMethod) {
36 | if(methodMapCfg.keySet().contains(sootMethod))
37 | return methodMapCfg.get(sootMethod);
38 | if(!sootMethod.isConcrete())
39 | return null;
40 | Body body = sootMethod.retrieveActiveBody();
41 | if(body==null){
42 | logger.warn("can't get the body of {}",sootMethod.getSignature());
43 | return null;
44 | }
45 | BriefUnitGraph graph = new BriefUnitGraph(body);
46 | methodMapCfg.put(sootMethod,graph);
47 | return graph;
48 | }
49 |
50 |
51 |
52 | public void buildPaths(SootMethod method,Unit unit,BriefUnitGraph graph,HashSet visit,Path path){
53 |
54 | Path newPath = new Path();
55 | newPath.addAll(path);
56 | newPath.add(unit);
57 |
58 | HashSet newVisit=new HashSet<>();
59 | newVisit.addAll(visit);
60 | newVisit.add(unit);
61 |
62 | boolean f=true;
63 | for(Unit succor:graph.getSuccsOf(unit)){
64 | if(!newVisit.contains(succor)){
65 | f=false;
66 | buildPaths(method,succor,graph,newVisit,newPath);
67 | }
68 | }
69 |
70 | if(f){
71 | if(!methodMapPath.containsKey(method))
72 | methodMapPath.put(method,new HashSet<>());
73 | methodMapPath.get(method).add(newPath);
74 | }
75 |
76 | }
77 |
78 | public HashSet getPaths(SootMethod method){
79 | if(!methodMapPath.containsKey(method)){
80 | BriefUnitGraph cfg = getCFG(method);
81 | if(cfg==null)
82 | return null;
83 | for(Unit head:cfg.getHeads()){
84 | buildPaths(method,head,cfg,new HashSet<>(),new Path());
85 | }
86 | }
87 | return methodMapPath.get(method);
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/cfg/Path.java:
--------------------------------------------------------------------------------
1 | package cfg;
2 |
3 | import soot.Unit;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 |
9 | public class Path {
10 |
11 | public List list=new ArrayList<>();
12 |
13 | public void add(Unit unit){
14 | list.add(unit);
15 | }
16 |
17 | public void addAll(Path path){
18 | list.addAll(path.list);
19 | }
20 |
21 | public boolean contains(Unit unit){
22 | return list.contains(unit);
23 | }
24 |
25 | public Unit get(int index){
26 | return list.get(index);
27 | }
28 |
29 |
30 |
31 | public int indexOf(Unit unit){
32 | return list.indexOf(unit);
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/component/FragementCreater.java:
--------------------------------------------------------------------------------
1 | package component;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import soot.Scene;
6 | import soot.SootClass;
7 | import soot.SootMethod;
8 |
9 | import java.util.Arrays;
10 | import java.util.HashSet;
11 | import java.util.List;
12 |
13 |
14 | public class FragementCreater {
15 | public static final Logger logger= LoggerFactory.getLogger(FragementCreater.class);
16 |
17 | public static final String FRAGMENT="androidx.fragment.app.Fragment";
18 | public static final String FRAGMENT_1="android.support.v4.app.Fragment";
19 | public static final String DIALOG_FRAGMENT="androidx.fragment.app.DialogFragment";
20 | public static final String LIST_FRAGMENT="androidx.fragment.app.ListFragment";
21 |
22 |
23 | public static final String FRAGMENT_ONCREATE = "void onCreate(android.os.Bundle)";
24 | public static final String FRAGMENT_ONATTACH = "void onAttach(android.app.Activity)";
25 | public static final String FRAGMENT_ONCREATEVIEW = "android.view.View onCreateView(android.view.LayoutInflater,android.view.ViewGroup,android.os.Bundle)";
26 | public static final String FRAGMENT_ONVIEWCREATED = "void onViewCreated(android.view.View,android.os.Bundle)";
27 | public static final String FRAGMENT_ONSTART = "void onStart()";
28 | public static final String FRAGMENT_ONACTIVITYCREATED = "void onActivityCreated(android.os.Bundle)";
29 | public static final String FRAGMENT_ONVIEWSTATERESTORED = "void onViewStateRestored(android.app.Activity)";
30 | public static final String FRAGMENT_ONRESUME = "void onResume()";
31 | public static final String FRAGMENT_ONPAUSE = "void onPause()";
32 | public static final String FRAGMENT_ONSTOP = "void onStop()";
33 | public static final String FRAGMENT_ONDESTROYVIEW = "void onDestroyView()";
34 | public static final String FRAGMENT_ONDESTROY = "void onDestroy()";
35 | public static final String FRAGMENT_ONDETACH = "void onDetach()";
36 | public static final String FRAGMENT_ONSAVEINSTANCESTATE = "void onSaveInstanceState(android.os.Bundle)";
37 |
38 | public static final String[] fragmentLifeCycleMethod={FRAGMENT_ONCREATE,FRAGMENT_ONATTACH,FRAGMENT_ONCREATEVIEW,FRAGMENT_ONVIEWCREATED,FRAGMENT_ONSTART,
39 | FRAGMENT_ONACTIVITYCREATED,FRAGMENT_ONSAVEINSTANCESTATE,FRAGMENT_ONVIEWSTATERESTORED,FRAGMENT_ONRESUME,FRAGMENT_ONPAUSE,FRAGMENT_ONSTOP,FRAGMENT_ONDESTROYVIEW,
40 | FRAGMENT_ONDESTROY,FRAGMENT_ONDETACH};
41 |
42 | public static final List fragmentLifeCycleMethodList= Arrays.asList(fragmentLifeCycleMethod);
43 |
44 | public static final String[] fragmentClasses={FRAGMENT,FRAGMENT_1,DIALOG_FRAGMENT,LIST_FRAGMENT};
45 |
46 | public static HashSet getAllFragmentInApp(){
47 | HashSet res=new HashSet<>();
48 | //我们遍历应用中的类,看这些类是不是
49 | for(SootClass cls:Scene.v().getClasses()){
50 | if(cls.isAbstract()||cls.isInterface())
51 | continue;
52 | if(!cls.isApplicationClass())
53 | continue;
54 | if(cls.isEnum())
55 | continue;
56 | if(cls.isLibraryClass())
57 | continue;
58 | for(String fragmentClas:fragmentClasses) {
59 | //判断是不是Fragment几个类的子类,如果是子类我们应该寻找它的生命周期函数
60 | if (isSubClass(cls, fragmentClas)){
61 | logger.info("[Fragment Class]: {}",cls.getName());
62 | for(String subSignature:fragmentLifeCycleMethodList){
63 | SootMethod method = findMethodBySubSignature(cls, subSignature);
64 | if(method==null)
65 | continue;
66 | res.add(method);
67 | }
68 | }
69 | }
70 | }
71 | return res;
72 | }
73 |
74 | public static SootMethod findMethodBySubSignature(SootClass currentClass, String subsignature) {
75 | if (currentClass.getName().startsWith("android.") || currentClass.getName().startsWith("androidx"))
76 | return null;
77 |
78 | SootMethod m = currentClass.getMethodUnsafe(subsignature);
79 |
80 | if (m != null) {
81 | return m;
82 | }
83 | if (currentClass.hasSuperclass()) {
84 | return findMethodBySubSignature(currentClass.getSuperclass(), subsignature);
85 | }
86 | return null;
87 | }
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | public static boolean isSubClass(SootClass currentCls,String cls){
100 | if(!currentCls.hasSuperclass())
101 | return false;
102 | SootClass superclass = currentCls.getSuperclass();
103 | if(superclass.getName().equals(cls))
104 | return true;
105 | return isSubClass(superclass,cls);
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/main/java/constant/ApkAndJavaConstants.java:
--------------------------------------------------------------------------------
1 | package constant;
2 |
3 | import java.io.File;
4 |
5 |
6 | public class ApkAndJavaConstants {
7 |
8 | public static final String apkDir = System.getProperty("user.dir") + File.separator + "app";
9 | public static final String androidJarPath = System.getenv("ANDROID_HOME") + File.separator + "platforms";
10 |
11 |
12 | public static final String programPath = System.getProperty("user.dir") + File.separator + "program";
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/constant/CollectionsUsageDefinition.java:
--------------------------------------------------------------------------------
1 | package constant;
2 |
3 | import java.util.Arrays;
4 | import java.util.List;
5 |
6 |
7 | public class CollectionsUsageDefinition {
8 |
9 | //和集合相关的api
10 |
11 | //方法特别多,这里只关注他们的subSignature
12 |
13 | public static final String ADD_0="boolean add(java.lang.Object)";
14 | public static final String ADD_1="void add(int,java.lang.Object)";
15 | public static final String ADD_ALL="boolean addAll(java.util.Collection)";
16 | public static final String REMOVE_0="java.lang.Object remove(int)";
17 | public static final String REMOVE_1="boolean remove(java.lang.Object)";
18 | public static final String REMOVE_2="void remove()";
19 | public static final String REMOVE_ALL="boolean removeAll(java.util.Collection)";
20 | public static final String CLEAR="void clear()";
21 | public static final String PUT="java.lang.Object put(java.lang.Object,java.lang.Object)";
22 | public static final String PUT_ALL="java.lang.Object remove(java.lang.Object)";
23 |
24 | public static final String[] collectionApi={
25 | ADD_0,ADD_1,ADD_ALL,REMOVE_0,REMOVE_1,REMOVE_2,REMOVE_ALL,CLEAR,PUT,PUT_ALL
26 | };
27 |
28 | public static final List collectionApiList= Arrays.asList(collectionApi);
29 |
30 | public static List getCollectionApiList(){
31 | return collectionApiList;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/constant/EntryPointsDefinition.java:
--------------------------------------------------------------------------------
1 | package constant;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.List;
6 |
7 |
8 | public class EntryPointsDefinition {
9 |
10 |
11 | public static final String ACTIVITY_ONCREATE = "void onCreate(android.os.Bundle)";
12 | public static final String ACTIVITY_ONSTART = "void onStart()";
13 | public static final String ACTIVITY_ONRESTOREINSTANCESTATE = "void onRestoreInstanceState(android.os.Bundle)";
14 | public static final String ACTIVITY_ONPOSTCREATE = "void onPostCreate(android.os.Bundle)";
15 | public static final String ACTIVITY_ONRESUME = "void onResume()";
16 | public static final String ACTIVITY_ONPOSTRESUME = "void onPostResume()";
17 | public static final String ACTIVITY_ONCREATEDESCRIPTION = "java.lang.CharSequence onCreateDescription()";
18 | public static final String ACTIVITY_ONSAVEINSTANCESTATE = "void onSaveInstanceState(android.os.Bundle)";
19 | public static final String ACTIVITY_ONPAUSE = "void onPause()";
20 | public static final String ACTIVITY_ONSTOP = "void onStop()";
21 | public static final String ACTIVITY_ONRESTART = "void onRestart()";
22 | public static final String ACTIVITY_ONDESTROY = "void onDestroy()";
23 | public static final String ACTIVITY_ONATTACHFRAGMENT = "void onAttachFragment(android.app.Fragment)";
24 |
25 |
26 | public static final String SERVICE_ONCREATE = "void onCreate()";
27 | public static final String SERVICE_ONSTART1 = "void onStart(android.content.Intent,int)";
28 | public static final String SERVICE_ONSTART2 = "int onStartCommand(android.content.Intent,int,int)";
29 | public static final String SERVICE_ONBIND = "android.os.IBinder onBind(android.content.Intent)";
30 | public static final String SERVICE_ONREBIND = "void onRebind(android.content.Intent)";
31 | public static final String SERVICE_ONUNBIND = "boolean onUnbind(android.content.Intent)";
32 | public static final String SERVICE_ONDESTROY = "void onDestroy()";
33 | public static final String SERVICE_ONHANDLEINTENT="void onHandleIntent(android.content.Intent)";
34 |
35 | public static final String BROADCAST_ONRECEIVE = "void onReceive(android.content.Context,android.content.Intent)";
36 |
37 | public static final String CONTENTPROVIDER_ONCREATE = "boolean onCreate()";
38 | public static final String CONTENTPROVIDER_INSERT = "android.net.Uri insert(android.net.Uri,android.content.ContentValues)";
39 | public static final String CONTENTPROVIDER_QUERY =
40 | "android.database.Cursor query(android.net.Uri,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String)";
41 | public static final String CONTENTPROVIDER_UPDATE = "int update(android.net.Uri,android.content.ContentValues,java.lang.String,java.lang.String[])";
42 | public static final String CONTENTPROVIDER_DELETE = "int delete(android.net.Uri,java.lang.String,java.lang.String[])";
43 | public static final String CONTENTPROVIDER_GETTYPE = "java.lang.String getType(android.net.Uri)";
44 |
45 |
46 | public static final String APPLICATION_ONCREATE = "void onCreate()";
47 | public static final String APPLICATION_ONTERMINATE = "void onTerminate()";
48 |
49 | public static List allLifeCycleMethodList = null;
50 |
51 | private static final String[] activityMethods = {ACTIVITY_ONCREATE, ACTIVITY_ONDESTROY, ACTIVITY_ONPAUSE,
52 | ACTIVITY_ONRESTART, ACTIVITY_ONRESUME, ACTIVITY_ONSTART, ACTIVITY_ONSTOP, ACTIVITY_ONSAVEINSTANCESTATE,
53 | ACTIVITY_ONRESTOREINSTANCESTATE, ACTIVITY_ONCREATEDESCRIPTION, ACTIVITY_ONPOSTCREATE, ACTIVITY_ONPOSTRESUME,
54 | ACTIVITY_ONATTACHFRAGMENT};
55 | private static final List activityMethodList = Arrays.asList(activityMethods);
56 |
57 | private static final String[] serviceMethods = {SERVICE_ONCREATE, SERVICE_ONDESTROY, SERVICE_ONSTART1,
58 | SERVICE_ONSTART2, SERVICE_ONBIND, SERVICE_ONREBIND, SERVICE_ONUNBIND,SERVICE_ONHANDLEINTENT};
59 | private static final List serviceMethodList = Arrays.asList(serviceMethods);
60 |
61 | private static final String[] broadcastMethods = {BROADCAST_ONRECEIVE};
62 | private static final List broadcastMethodList = Arrays.asList(broadcastMethods);
63 |
64 | private static final String[] contentproviderMethods = {CONTENTPROVIDER_ONCREATE, CONTENTPROVIDER_DELETE,
65 | CONTENTPROVIDER_GETTYPE, CONTENTPROVIDER_INSERT, CONTENTPROVIDER_QUERY, CONTENTPROVIDER_UPDATE};
66 | private static final List contentProviderMethodList = Arrays.asList(contentproviderMethods);
67 |
68 | private static final String[] applicationMethods={APPLICATION_ONCREATE,APPLICATION_ONTERMINATE};
69 |
70 | private static final List applicationMethodList =Arrays.asList(applicationMethods);
71 |
72 | public static List getActivityLifecycleMethods() {
73 | return activityMethodList;
74 | }
75 |
76 | public static List getServiceLifecycleMethods() {
77 | return serviceMethodList;
78 | }
79 |
80 | public static List getBroadcastLifecycleMethods() {
81 | return broadcastMethodList;
82 | }
83 |
84 | public static List getContentproviderLifecycleMethods() {
85 | return contentProviderMethodList;
86 | }
87 |
88 | public static List getAppliactionMethods(){
89 | return applicationMethodList;
90 | }
91 |
92 | public static List getAllLifeCycleMethodList() {
93 |
94 | if (allLifeCycleMethodList == null) {
95 | allLifeCycleMethodList = new ArrayList<>();
96 | allLifeCycleMethodList.addAll(activityMethodList);
97 | allLifeCycleMethodList.addAll(serviceMethodList);
98 | allLifeCycleMethodList.addAll(broadcastMethodList);
99 | allLifeCycleMethodList.addAll(contentProviderMethodList);
100 | }
101 |
102 | return allLifeCycleMethodList;
103 | }
104 |
105 |
106 |
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/src/main/java/constant/FileUsageDefinition.java:
--------------------------------------------------------------------------------
1 | package constant;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.HashSet;
6 | import java.util.List;
7 |
8 |
9 | public class FileUsageDefinition {
10 |
11 |
12 | //SharedPreferences的载入操作
13 | public static final String SHARED_PREFERENCES_0 = "android.content.SharedPreferences getSharedPreferences(java.lang.String,int)";
14 | public static final String SHARED_PREFERENCES_1 = "android.content.SharedPreferences getPreferences(int)";
15 | public static final String SHARED_PREFERENCES_2 = "android.content.SharedPreferences getDefaultSharedPreferences(android.content.Context)";
16 |
17 | //SharedPreferences的读
18 | public static final String SHARED_PREFERENCE_REDA_0 = "";
19 | public static final String SHARED_PREFERENCE_REDA_1 = "";
20 | public static final String SHARED_PREFERENCE_REDA_2 = "";
21 | public static final String SHARED_PREFERENCE_REDA_3 = "";
22 | public static final String SHARED_PREFERENCE_REDA_4 = "";
23 | public static final String SHARED_PREFERENCE_REDA_5 = "";
24 | public static final String SHARED_PREFERENCE_REDA_6 = "";
25 | //SharedPreference的写
26 | public static final String SHARED_PREFERENCE_WRITE_0 = "android.content.SharedPreferences$Editor putInt(java.lang.String,int)";
27 | public static final String SHARED_PREFERENCE_WRITE_1 = "android.content.SharedPreferences$Editor putBoolean(java.lang.String,boolean)";
28 | public static final String SHARED_PREFERENCE_WRITE_2 = "android.content.SharedPreferences$Editor putLong(java.lang.String,long)";
29 | public static final String SHARED_PREFERENCE_WRITE_3 = "android.content.SharedPreferences$Editor putFloat(java.lang.String,float)";
30 | public static final String SHARED_PREFERENCE_WRITE_4 = "android.content.SharedPreferences$Editor putString(java.lang.String,java.lang.String)";
31 | public static final String SHARED_PREFERENCE_WRITE_5 = "android.content.SharedPreferences$Editor putStringSet(java.lang.String,java.util.Set)";
32 |
33 | //数据库对象的创建方式
34 | public static final String DATA_BASE_0 = "android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String,int,android.database.sqlite.SQLiteDatabase$CursorFactory,android.database.DatabaseErrorHandler)";
35 | public static final String DATA_BASE_1 = "android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String,int,android.database.sqlite.SQLiteDatabase$CursorFactory)";
36 | public static final String DATA_BASE_2 = "android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.io.File,android.database.sqlite.SQLiteDatabase$CursorFactory)";
37 | public static final String DATA_BASE_3 = "android.database.sqlite.SQLiteDatabase getReadableDatabase()";
38 | public static final String DATA_BASE_4 = "android.database.sqlite.SQLiteDatabase getWritableDatabase()";
39 | public static final String DATA_BASE_5 = "android.database.sqlite.SQLiteDatabase openDatabase(java.io.File,android.database.sqlite.SQLiteDatabase$OpenParams)";
40 | public static final String DATA_BASE_6 = "android.database.sqlite.SQLiteDatabase openDatabase(java.lang.String,android.database.sqlite.SQLiteDatabase$CursorFactory,int)";
41 | public static final String DATA_BASE_7 = "android.database.sqlite.SQLiteDatabase openDatabase(java.lang.String,android.database.sqlite.SQLiteDatabase$CursorFactory,int,android.database.DatabaseErrorHandler)";
42 |
43 | //数据库的查询
44 | public static final String DATA_BASE_QUERY_0 = "android.database.Cursor query(java.lang.String,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String,java.lang.String,java.lang.String)";
45 | public static final String DATA_BASE_QUERY_1 = "android.database.Cursor query(java.lang.String,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String,java.lang.String,java.lang.String,java.lang.String)";
46 | public static final String DATA_BASE_QUERY_2 = "android.database.Cursor query(boolean,java.lang.String,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String,java.lang.String,java.lang.String,java.lang.String)";
47 | public static final String DATA_BASE_QUERY_3 = "android.database.Cursor query(boolean,java.lang.String,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String,java.lang.String,java.lang.String,java.lang.String,android.os.CancellationSignal)";
48 | public static final String DATA_BASE_QUERY_4 = "android.database.Cursor rawQuery(java.lang.String,java.lang.String[])";
49 | public static final String DATA_BASE_QUERY_5 = "android.database.Cursor rawQuery(java.lang.String,java.lang.String[],android.os.CancellationSignal)";
50 | public static final String DATA_BASE_QUERY_6 = "android.database.Cursor rawQueryWithFactory(android.database.sqlite.SQLiteDatabase$CursorFactory,java.lang.String,java.lang.String[],java.lang.String)";
51 | public static final String DATA_BASE_QUERY_7 = "android.database.Cursor rawQueryWithFactory(android.database.sqlite.SQLiteDatabase$CursorFactory,java.lang.String,java.lang.String[],java.lang.String,android.os.CancellationSignal)";
52 | public static final String DATA_BASE_QUERY_8 = "android.database.Cursor queryWithFactory(android.database.sqlite.SQLiteDatabase$CursorFactory,boolean,java.lang.String,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String,java.lang.String,java.lang.String,java.lang.String)";
53 | public static final String DATA_BASE_QUERY_9 = "android.database.Cursor queryWithFactory(android.database.sqlite.SQLiteDatabase$CursorFactory,boolean,java.lang.String,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String,java.lang.String,java.lang.String,java.lang.String,android.os.CancellationSignal)";
54 | public static final String DATA_BASE_QUERY_10 = "void execSQL(java.lang.String)";
55 | public static final String DATA_BASE_QUERY_11 = "void execSQL(java.lang.String,java.lang.Object[])";
56 |
57 | //ContentResolver查询
58 | public static final String CONTENT_RESOLVER_QUERY_0 = "android.database.Cursor query(android.net.Uri,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String)";
59 | public static final String CONTENT_RESOLVER_QUERY_1 = "android.database.Cursor query(android.net.Uri,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String,android.os.CancellationSignal)";
60 | // public static final String CONTENT_RESOLVER_LOAD_THUMBNAIL = "android.graphics.Bitmap loadThumbnail(android.net.Uri,android.util.Size,android.os.CancellationSignal)";
61 | // public static final String CONTENT_RESOLVER_OPEN_ASSET_FILE = "android.content.res.AssetFileDescriptor openAssetFile(android.net.Uri,java.lang.String,android.os.CancellationSignal)";
62 | // public static final String CONTENT_RESOLVER_OPEN_FILE = "android.os.ParcelFileDescriptor openFile(android.net.Uri,java.lang.String,android.os.CancellationSignal)";
63 | // public static final String CONTENT_RESOLVER_OPEN_INPUT_STREAM = "java.io.InputStream openInputStream(android.net.Uri)";
64 |
65 | //文件加载构造方法,文件创建
66 | public static final String FILE_LOAD_0 = "(java.lang.String)>";
67 | public static final String FILE_LOAD_1 = "(java.lang.String,java.lang.String)>";
68 | public static final String FILE_LOAD_2 = "(java.io.File,java.lang.String)>";
69 | public static final String FILE_LOAD_3 = "(java.net.URI)>";
70 | //输入流构造方法,这些输入流的参数为file或者file_name,这些API可以直接判定文件名称
71 | public static final String FILE_INPUT_STREAM_0 = "(java.io.File)>";
72 | public static final String FILE_INPUT_STREAM_1 = "(java.lang.String)>";
73 | public static final String FILE_INPUT_STREAM_2 = "(java.lang.String)>";
74 | public static final String FILE_INPUT_STREAM_3 = "(java.io.File)>";
75 | //输出流构造方法,这些输出流的参数为file或者file_name,这些API可以直接判定文件名称
76 | public static final String FILE_OUTPUT_STREAM_0 = "(java.lang.String)>";
77 | public static final String FILE_OUTPUT_STREAM_1 = "(java.lang.String,boolean)>";
78 | public static final String FILE_OUTPUT_STREAM_2 = "(java.io.File)>";
79 | public static final String FILE_OUTPUT_STREAM_3 = "(java.io.File,boolean)>";
80 | public static final String FILE_OUTPUT_STREAM_4 = "(java.lang.String)>";
81 | public static final String FILE_OUTPUT_STREAM_5 = "(java.lang.String,boolean)>";
82 | public static final String FILE_OUTPUT_STREAM_6 = "(java.io.File)>";
83 | public static final String FILE_OUTPUT_STREAM_7 = "(java.io.File,boolean)>";
84 | public static final String FILE_OUTPUT_STREAM_8 = "(java.io.OutputStream)>";
85 | public static final String FILE_OUTPUT_STREAM_9 = "(java.io.OutputStream,java.lang.String)>";
86 | public static final String FILE_OUTPUT_STREAM_10 = "(java.io.Writer)>";
87 | public static final String FILE_OUTPUT_STREAM_11 = "(java.io.Writer,int)>";
88 | public static final String FILE_OUTPUT_STREAM_12 = "(java.io.OutputStream)>";
89 | public static final String FILE_OUTPUT_STREAM_13 = "(java.io.OutputStream)>";
90 | public static final String FILE_OUTPUT_STREAM_14 = "(java.io.OutputStream,int)>";
91 | public static final String FILE_OUTPUT_STREAM_15 = "(java.io.OutputStream)>";
92 |
93 | //Uri创建API
94 | public static final String URI_CREATE_0 = "";
95 | public static final String URI_CREATE_1 = "";
96 | public static final String URI_CREATE_2 = "";
97 | public static final String URI_CREATE_3 = "";
98 |
99 | public static final String[] sharedPreferencesLoadAPI = {SHARED_PREFERENCES_0, SHARED_PREFERENCES_1, SHARED_PREFERENCES_2};
100 |
101 | public static final List sharedPreferencesLoadAPIList = Arrays.asList(sharedPreferencesLoadAPI);
102 |
103 | public static final String[] sharedPreferencesReadAPI = {SHARED_PREFERENCE_REDA_0, SHARED_PREFERENCE_REDA_1, SHARED_PREFERENCE_REDA_2, SHARED_PREFERENCE_REDA_3,
104 | SHARED_PREFERENCE_REDA_4, SHARED_PREFERENCE_REDA_5, SHARED_PREFERENCE_REDA_6};
105 |
106 | public static final List sharedPreferencesReadAPIList = Arrays.asList(sharedPreferencesReadAPI);
107 |
108 | public static final String[] sharedPreferencesWriteAPI = {SHARED_PREFERENCE_WRITE_0, SHARED_PREFERENCE_WRITE_1, SHARED_PREFERENCE_WRITE_2, SHARED_PREFERENCE_WRITE_3,
109 | SHARED_PREFERENCE_WRITE_3, SHARED_PREFERENCE_WRITE_4, SHARED_PREFERENCE_WRITE_5};
110 |
111 | public static final List sharedPreferencesWriteAPIList = Arrays.asList(sharedPreferencesWriteAPI);
112 |
113 | public static final String[] dataBaseOpenOrCreateAPI = {DATA_BASE_0, DATA_BASE_1, DATA_BASE_2, DATA_BASE_3, DATA_BASE_4, DATA_BASE_5, DATA_BASE_6, DATA_BASE_7};
114 |
115 | public static final List dataBaseOpenOrCreateAPIList = Arrays.asList(dataBaseOpenOrCreateAPI);
116 |
117 | public static final String[] dataBaseQueryAPI = {DATA_BASE_QUERY_0, DATA_BASE_QUERY_1, DATA_BASE_QUERY_2, DATA_BASE_QUERY_3, DATA_BASE_QUERY_4, DATA_BASE_QUERY_5,
118 | DATA_BASE_QUERY_6, DATA_BASE_QUERY_7, DATA_BASE_QUERY_8, DATA_BASE_QUERY_9};
119 |
120 | public static final List dataBaseQueryAPIList = Arrays.asList(dataBaseQueryAPI);
121 |
122 | public static final String[] contentResolverQueryAPI = {CONTENT_RESOLVER_QUERY_0, CONTENT_RESOLVER_QUERY_1,
123 | // CONTENT_RESOLVER_LOAD_THUMBNAIL, CONTENT_RESOLVER_OPEN_ASSET_FILE,
124 | // CONTENT_RESOLVER_OPEN_FILE, CONTENT_RESOLVER_OPEN_INPUT_STREAM
125 | };
126 |
127 | public static final List contentResolverQueryAPIList = Arrays.asList(contentResolverQueryAPI);
128 |
129 | public static final String[] inputStreamConstructor = {FILE_INPUT_STREAM_0, FILE_INPUT_STREAM_1, FILE_INPUT_STREAM_2, FILE_INPUT_STREAM_3};
130 |
131 | public static final List inputStreamConstructorList = Arrays.asList(inputStreamConstructor);
132 |
133 | public static final String[] outputStreamConstructor = {FILE_OUTPUT_STREAM_0, FILE_OUTPUT_STREAM_1, FILE_OUTPUT_STREAM_2, FILE_OUTPUT_STREAM_3, FILE_OUTPUT_STREAM_4, FILE_OUTPUT_STREAM_5,
134 | FILE_OUTPUT_STREAM_5, FILE_OUTPUT_STREAM_6, FILE_OUTPUT_STREAM_7, FILE_OUTPUT_STREAM_8, FILE_OUTPUT_STREAM_9, FILE_OUTPUT_STREAM_10,
135 | FILE_OUTPUT_STREAM_11, FILE_OUTPUT_STREAM_12, FILE_OUTPUT_STREAM_12, FILE_OUTPUT_STREAM_13, FILE_OUTPUT_STREAM_14, FILE_OUTPUT_STREAM_15};
136 |
137 | public static final List outputStreamConstructorList = Arrays.asList(outputStreamConstructor);
138 |
139 | public static final String[] uriCreateAPI = {URI_CREATE_0, URI_CREATE_1, URI_CREATE_2, URI_CREATE_3};
140 |
141 | public static final List uriCreateAPIList = Arrays.asList(uriCreateAPI);
142 |
143 | public static final String[] javaIOAPI = {
144 | FILE_LOAD_0,
145 | FILE_LOAD_1,
146 | FILE_LOAD_2,
147 | FILE_LOAD_3,
148 | FILE_INPUT_STREAM_0,
149 | FILE_INPUT_STREAM_1,
150 | FILE_INPUT_STREAM_2,
151 | FILE_INPUT_STREAM_3,
152 | FILE_OUTPUT_STREAM_0,
153 | FILE_OUTPUT_STREAM_1,
154 | FILE_OUTPUT_STREAM_2,
155 | FILE_OUTPUT_STREAM_3,
156 | FILE_OUTPUT_STREAM_4,
157 | FILE_OUTPUT_STREAM_5,
158 | FILE_OUTPUT_STREAM_6,
159 | FILE_OUTPUT_STREAM_7,
160 | FILE_OUTPUT_STREAM_8,
161 | FILE_OUTPUT_STREAM_9,
162 | FILE_OUTPUT_STREAM_10,
163 | FILE_OUTPUT_STREAM_11,
164 | FILE_OUTPUT_STREAM_12,
165 | FILE_OUTPUT_STREAM_13,
166 | FILE_OUTPUT_STREAM_14,
167 | FILE_OUTPUT_STREAM_15
168 | };
169 |
170 |
171 |
172 | private static List javaIOAPIList = Arrays.asList(javaIOAPI);
173 |
174 | public static final String[] fileLoadApis={FILE_LOAD_0,FILE_LOAD_1,FILE_LOAD_2,FILE_LOAD_3};
175 |
176 | private static List fileLoadAPIList=Arrays.asList(fileLoadApis);
177 |
178 |
179 |
180 |
181 | public static List getSharedPreferencesLoadAPIList() {
182 | return sharedPreferencesLoadAPIList;
183 | }
184 |
185 | public static List getSharedPreferencesReadAPIList() {
186 | return sharedPreferencesReadAPIList;
187 | }
188 |
189 | public static List getSharedPreferencesWriteAPIList() {
190 | return sharedPreferencesWriteAPIList;
191 | }
192 |
193 | public static List getDataBaseOpenOrCreateAPIList() {
194 | return dataBaseOpenOrCreateAPIList;
195 | }
196 |
197 | public static List getDataBaseQueryAPIList() {
198 | return dataBaseQueryAPIList;
199 | }
200 |
201 | public static List getContentResolverQueryAPIList() {
202 | return contentResolverQueryAPIList;
203 | }
204 |
205 | public static List getInputStreamConstructorList() {
206 | return inputStreamConstructorList;
207 | }
208 |
209 | public static List getOutputStreamConstructorList() {
210 | return outputStreamConstructorList;
211 | }
212 |
213 | public static List getUriCreateAPIList() {
214 | return uriCreateAPIList;
215 | }
216 |
217 | public static List getJavaIOAPIList(){
218 | return javaIOAPIList;
219 | }
220 |
221 | public static List getFileLoadAPIList(){ return fileLoadAPIList;}
222 |
223 |
224 |
225 |
226 | }
--------------------------------------------------------------------------------
/src/main/java/constant/IPCPointDefinition.java:
--------------------------------------------------------------------------------
1 | package constant;
2 |
3 | import java.util.Arrays;
4 | import java.util.List;
5 |
6 |
7 | public class IPCPointDefinition {
8 |
9 |
10 | //通过以下方法调用第三方应用或者自身应用的组件
11 | public static final String IPC_SERVICE="android.content.ComponentName startService(android.content.Intent)";
12 | public static final String IPC_FOREGROUND_SERVICE="android.content.ComponentName startForegroundService(android.content.Intent)";
13 |
14 | public static final String IPC_RECEIVER="void sendBroadcast(android.content.Intent)";
15 | public static final String IPC_ORDER_RECEIVER="void sendBroadcast(android.content.Intent,java.lang.String)";
16 |
17 | public static final String IPC_PROVIDER_BULK_INSERT="int bulkInsert(android.net.Uri,android.content.ContentValues[])";
18 | public static final String IPC_PROVIDER_INSERT_0="android.net.Uri insert(android.net.Uri,android.content.ContentValues)";
19 | public static final String IPC_PROVIDER_INSERT_1="android.net.Uri insert(android.net.Uri,android.content.ContentValues,android.os.Bundle)";
20 | public static final String IPC_PROVIDER_UPDATE_0="int update(android.net.Uri,android.content.ContentValues[],java.lang.String,java.lang.String[])";
21 | public static final String IPC_PROVIDER_UPDATA_1="int update(android.net.Uri,android.content.ContentValues[],android.os.Bundle)";
22 |
23 |
24 | public static final String[] ipc_method={IPC_SERVICE,IPC_FOREGROUND_SERVICE,IPC_RECEIVER,IPC_ORDER_RECEIVER,IPC_PROVIDER_BULK_INSERT,IPC_PROVIDER_INSERT_0,IPC_PROVIDER_INSERT_1,IPC_PROVIDER_UPDATE_0,
25 | IPC_PROVIDER_UPDATA_1
26 | };
27 |
28 | public static final List ipcMethodList= Arrays.asList(ipc_method);
29 |
30 | public static List getIpcMethodList(){
31 | return ipcMethodList;
32 | }
33 |
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/constant/StrawPointsDefinition.java:
--------------------------------------------------------------------------------
1 | package constant;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.List;
6 |
7 |
8 | public class StrawPointsDefinition {
9 |
10 | public static final String COLLECTIONS_STRAWPOINT_REGEX = "(<(java|android)\\.util\\..*(boolean|void) add.*>)|(<(java|android)\\.util\\..*(java.lang.Object|void) put.*>)|()";
11 |
12 | public static final String FILE_WRITE_0="";
13 | public static final String FILE_WRITE_1="";
14 | public static final String FILE_WRITE_2="";
15 | public static final String FILE_WRITE_3="";
16 | public static final String FILE_WRITE_4="";
17 | public static final String FILE_WRITE_5="";
18 | public static final String FILE_WRITE_6="";
19 | public static final String FILE_WRITE_7="";
20 | public static final String FILE_WRITE_8="";
21 | public static final String FILE_WRITE_9="";
22 | public static final String FILE_WRITE_10="";
23 | public static final String FILE_WRITE_11="";
24 | public static final String FILE_WRITE_12="";
25 | public static final String FILE_WRITE_13="";
26 | public static final String FILE_WRITE_14="";
27 | public static final String FILE_WRITE_15="";
28 | public static final String FILE_WRITE_16="";
29 | public static final String FILE_WRITE_17="";
30 | public static final String FILE_WRITE_18="";
31 | public static final String FILE_WRITE_19="";
32 | public static final String FILE_WRITE_20="";
33 | public static final String FILE_WRITE_21="";
34 | public static final String FILE_WRITE_22="";
35 | public static final String FILE_WRITE_23="";
36 | public static final String FILE_WRITE_24="";
37 | public static final String FILE_WRITE_25="";
38 | public static final String FILE_WRITE_26="";
39 | public static final String FILE_WRITE_27="";
40 | public static final String FILE_WRITE_28="";
41 |
42 | public static final String SHAREDPREFERENCES_PUT_STRING="";
43 | public static final String SHAREDPREFERENCES_PUT_BOOLEAN="";
44 | public static final String SHAREDPREFERENCES_PUT_STRINGSET="";
45 | public static final String SHAREDPREFERENCES_PUT_FLOAT="";
46 | public static final String SHAREDPREFERENCES_PUT_LONG="";
47 | public static final String SHARED_PREFERENCE_PUT_INT = "";
48 |
49 |
50 | public static final String DATABASE_INSERT="";
51 | public static final String DATABASE_INSERTORTHROW="";
52 | public static final String DATABASE_INSERTWITHONCONFLICT="";
53 | public static final String DATABASE_EXECSQL="";
54 | public static final String DATABASE_UPDATE_0="";
55 | public static final String DATABASE_UPDATE_1="";
56 | // public static final String DATABASE_DELETE="";
57 |
58 | public static final String MEDIA_BULK_INSERT="";
59 | public static final String MEDIA_INSERT_0="";
60 | public static final String MEDIA_INSERT_1="";
61 |
62 | public static final String IPC_SERVICE="";
63 | public static final String IPC_FOREGROUND_SERVICE="";
64 | public static final String IPC_RECEIVER="";
65 | public static final String IPC_ORDER_RECEIVER="";
66 | public static final String IPC_PROVIDER_BULK_INSERT="";
67 | public static final String IPC_PROVIDER_INSERT_0="";
68 | public static final String IPC_PROVIDER_INSERT_1="";
69 | public static final String IPC_PROVIDER_UPDATE_0="";
70 | public static final String IPC_PROVIDER_UPDATA_1="";
71 |
72 | private static final String[] fileWriteMethod={FILE_WRITE_0,FILE_WRITE_1,FILE_WRITE_2,FILE_WRITE_3,FILE_WRITE_4,FILE_WRITE_5,
73 | FILE_WRITE_6,FILE_WRITE_7,FILE_WRITE_8,FILE_WRITE_9,FILE_WRITE_10,FILE_WRITE_11,FILE_WRITE_12,FILE_WRITE_13,FILE_WRITE_14,FILE_WRITE_15,
74 | FILE_WRITE_16,FILE_WRITE_17,FILE_WRITE_18,FILE_WRITE_19,FILE_WRITE_20,FILE_WRITE_21,FILE_WRITE_22,FILE_WRITE_23,FILE_WRITE_24,FILE_WRITE_25,
75 | FILE_WRITE_26,FILE_WRITE_27,FILE_WRITE_28};
76 | private static final List fileWriteMethodList=Arrays.asList(fileWriteMethod);
77 |
78 | private static final String[] sharedPreferencesWriteMethod={SHAREDPREFERENCES_PUT_STRING,SHAREDPREFERENCES_PUT_STRINGSET,SHAREDPREFERENCES_PUT_BOOLEAN,SHAREDPREFERENCES_PUT_FLOAT,
79 | SHAREDPREFERENCES_PUT_LONG,SHARED_PREFERENCE_PUT_INT};
80 | private static final List sharedPreferencesWriteMethodList=Arrays.asList(sharedPreferencesWriteMethod);
81 |
82 | private static final String[] databaseInsertMethod={DATABASE_INSERT,DATABASE_INSERTORTHROW,DATABASE_INSERTWITHONCONFLICT,DATABASE_EXECSQL,DATABASE_UPDATE_0,DATABASE_UPDATE_1
83 | ,IPC_PROVIDER_BULK_INSERT,IPC_PROVIDER_INSERT_0,IPC_PROVIDER_UPDATA_1,IPC_PROVIDER_UPDATE_0,IPC_PROVIDER_INSERT_1};
84 | private static final List databaseInsertMethodList=Arrays.asList(databaseInsertMethod);
85 |
86 | private static final String[] mediaInsertMethod={MEDIA_BULK_INSERT,MEDIA_INSERT_0,MEDIA_INSERT_1};
87 | private static final List mediaInsertMethodList=Arrays.asList(mediaInsertMethod);
88 |
89 | private static final String[] databaseModifiedMethods={DATABASE_INSERT,DATABASE_UPDATE_1,DATABASE_UPDATE_0,DATABASE_INSERTORTHROW,DATABASE_INSERTWITHONCONFLICT};
90 | private static final List databaseModifiedMethodsList=Arrays.asList(databaseModifiedMethods);
91 |
92 | public static List allInsertMethodList=null;
93 |
94 | /*
95 | =======================================================================================================
96 | */
97 | public static List getFileWriteMethodList(){
98 | return fileWriteMethodList;
99 | }
100 |
101 | public static List getSharedPreferencesWriteMethodList(){
102 | return sharedPreferencesWriteMethodList;
103 | }
104 |
105 | public static List getDatabaseInsertMethodList(){
106 | return databaseInsertMethodList;
107 | }
108 |
109 | public static List getMediaInsertMethodList(){
110 | return mediaInsertMethodList;
111 | }
112 |
113 | public static List getAllInsertMethodList(){
114 | if(allInsertMethodList==null){
115 | allInsertMethodList=new ArrayList<>();
116 | allInsertMethodList.addAll(fileWriteMethodList);
117 | allInsertMethodList.addAll(sharedPreferencesWriteMethodList);
118 | allInsertMethodList.addAll(databaseInsertMethodList);
119 | allInsertMethodList.addAll(mediaInsertMethodList);
120 | }
121 | return allInsertMethodList;
122 | }
123 |
124 | public static List getDatabaseModifeiedMethods(){
125 | return databaseModifiedMethodsList;
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/src/main/java/dataflow/AbstractDataFlow.java:
--------------------------------------------------------------------------------
1 | package dataflow;
2 |
3 | import cg.CallGraphUtils;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 | import soot.*;
7 | import soot.jimple.*;
8 | import soot.jimple.toolkits.callgraph.Edge;
9 | import soot.toolkits.graph.BriefUnitGraph;
10 |
11 | import java.util.*;
12 |
13 |
14 | public abstract class AbstractDataFlow implements Analyze {
15 |
16 | public static final Logger logger = LoggerFactory.getLogger(AbstractDataFlow.class);
17 |
18 | protected int MAX_DEPTH = 15;
19 |
20 | protected Analyze analyze = null;
21 |
22 | public void run() {
23 |
24 | }
25 |
26 | public void setMAX_DEPTH(int depth){
27 | this.MAX_DEPTH=depth;
28 | }
29 |
30 | public static boolean isValueUsedInUnit(Unit unit, Value value) {
31 | List usedValue = new ArrayList<>();
32 | for (ValueBox useBox : unit.getUseBoxes()) {
33 | usedValue.add(useBox.getValue().toString());
34 | }
35 | return usedValue.contains(value.toString());
36 | }
37 |
38 | public static boolean isValueDefinedInUnit(Unit unit, Value value) {
39 | List definedValue = new ArrayList<>();
40 | for (ValueBox defBox : unit.getDefBoxes()) {
41 | definedValue.add(defBox.getValue().toString());
42 | }
43 | return definedValue.contains(value.toString());
44 | }
45 |
46 |
47 | public static Unit getParmaAssignUnit(BriefUnitGraph graph, int paramIndex) {
48 | Queue queue = new LinkedList<>(graph.getHeads());
49 | HashSet visit = new HashSet<>();
50 | while (!queue.isEmpty()) {
51 | Unit poll = queue.poll();
52 | visit.add(poll);
53 | if (poll.toString().contains("@parameter" + paramIndex)) {
54 | return poll;
55 | }
56 | for (Unit succor : graph.getSuccsOf(poll)) {
57 | if (!visit.contains(succor))
58 | queue.add(succor);
59 | }
60 | }
61 | return null;
62 | }
63 |
64 | public static boolean isSystemClass(SootClass sootClass) {
65 | String name = sootClass.getName();
66 | //如果不是分析android系统,注意要让android的库设置为系统类
67 | if (name.startsWith("java") || name.startsWith("javax")||name.startsWith("android.")||name.startsWith("androidx.")||name.startsWith("com.android")||name.startsWith("sun.")) {
68 | return true;
69 | }
70 | //
71 | // if(name.startsWith("java.")||name.startsWith("javax."))
72 | // return true;
73 | return false;
74 |
75 | }
76 |
77 |
78 | public static boolean isMethodCalled(List callStack, SootMethod method) {
79 | for (CallSite callSite : callStack) {
80 | if (callSite.caller.getSignature().equals(method.getSignature()))
81 | return true;
82 | }
83 | return false;
84 | }
85 |
86 |
87 | //寻找变量的直接赋值语句
88 | public Unit findDirectDefUnit(ValueBox valueBox, Unit u, SootMethod m) {
89 | if (!m.isConcrete())
90 | return null;
91 | BriefUnitGraph cfg = new BriefUnitGraph(m.retrieveActiveBody());
92 | Queue queue = new LinkedList<>();
93 | queue.addAll(cfg.getPredsOf(u));
94 | HashSet visit = new HashSet<>();
95 | while (!queue.isEmpty()) {
96 | Unit poll = queue.poll();
97 | visit.add(poll);
98 | if (isValueDefinedInUnit(poll, valueBox.getValue())) {
99 | return poll;
100 | }
101 | for (Unit pre : cfg.getPredsOf(poll)) {
102 | if (!visit.contains(pre))
103 | queue.add(pre);
104 | }
105 | }
106 | return null;
107 | }
108 |
109 | public static InvokeExpr getInvokeExpr(Unit u){
110 |
111 | if(u instanceof InvokeStmt){
112 | return ((InvokeStmt)u).getInvokeExpr();
113 | }
114 |
115 | if(u instanceof AssignStmt){
116 | AssignStmt assignStmt = (AssignStmt) u;
117 | if(assignStmt.containsInvokeExpr())
118 | return assignStmt.getInvokeExpr();
119 | }
120 | return null;
121 | }
122 |
123 | public static HashSet getMethodFromCG(Unit u) {
124 |
125 |
126 | // HashSet res = new HashSet<>();
127 | //
128 | // InvokeExpr m = getInvokeExpr(u);
129 | // if(m==null)
130 | // return res;
131 | // if(!Scene.v().hasCallGraph())
132 | // throw new RuntimeException("No CallGraph in Scence");
133 | // Iterator edgeIterator = Scene.v().getCallGraph().edgesOutOf(u);
134 | // while (edgeIterator.hasNext()){
135 | // Edge next = edgeIterator.next();
136 | // if(next.tgt().getSubSignature().equals(m.getMethod().getSubSignature()))
137 | // res.add(next.tgt());
138 | // }
139 | return CallGraphUtils.getMethod(u);
140 | }
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 | }
149 |
--------------------------------------------------------------------------------
/src/main/java/dataflow/AccessPathTag.java:
--------------------------------------------------------------------------------
1 | package dataflow;
2 |
3 | import soot.tagkit.AttributeValueException;
4 | import soot.tagkit.Tag;
5 |
6 |
7 | //access path长度为0,表示当前变量就是污染,当前变量可以是局部变量,this,实例字段或者是静态字段
8 | //一个taint,如果它的access path为0,表示该引用所指的对象是污染的
9 | //如果access path不为0,表示这个引用所指的对象是污染的,比如引用是taint,access path是.x.y.z,那么taint.x.y.z是污染的
10 | public class AccessPathTag implements Tag {
11 |
12 | // private byte[] accessPath = new byte[100];//表示当前的域名,规定最大长度为5,如果有本tag并且它特curIndex为0,表示就是本变量被污染了
13 | //规定任何污染的变量都需要带本属性
14 |
15 | private int fieldLength = 0;
16 |
17 | private String fieldChain = "";
18 | int accessPathIndex=0;
19 |
20 | @Override
21 | public String getName() {
22 | return "AccessPath";
23 | }
24 |
25 | public AccessPathTag(Tag tag) {
26 | // accessPath = tag.getValue().clone();
27 | AccessPathTag accessPathTag = (AccessPathTag) tag;
28 | fieldChain = accessPathTag.fieldChain;
29 | fieldLength=accessPathTag.fieldLength;
30 | }
31 |
32 | public AccessPathTag() {
33 |
34 | }
35 |
36 | // public AccessPathTag(String acc)
37 |
38 | @Override
39 | public byte[] getValue() throws AttributeValueException {
40 | return null;
41 | }
42 |
43 | public boolean appendAccessPath(String fieldName) {
44 | if (fieldLength == 5) {//如果当前的access path超过规定的最大长度,我们认为这个比如r.a.b.c.d.f,此时我们认为r是没有被污染的
45 | return false;
46 | } else {
47 | fieldChain = fieldName + "." + fieldChain;
48 | // System.out.println("升");
49 | // System.out.println(fieldChain);
50 | // int cur = 0;
51 | // for (byte c : fieldChain.getBytes()) {
52 | // accessPath[cur] = c;
53 | // cur++;
54 | // }
55 | fieldLength += 1;
56 | return true;
57 | }
58 | }
59 |
60 | public boolean removeAccessPath() {
61 | if (fieldLength == 0)
62 | return true;
63 | // System.out.println("降");
64 | byte[] bytes = fieldChain.getBytes();
65 | for (int i = 0; i < fieldChain.length(); i++) {
66 | if ((char) bytes[i] == '.') {
67 | fieldChain = fieldChain.substring(i+1);
68 | // accessPath = fieldChain.getBytes();
69 | return true;
70 | }
71 | }
72 | return false;
73 |
74 | }
75 |
76 | public void setValue(byte[] value) {
77 | // accessPath = value.clone();
78 | }
79 |
80 | public boolean match(String fieldName) {
81 | if (fieldChain.isEmpty())
82 | return true;
83 | //查看filed是否匹配
84 | // System.out.println(fieldChain);
85 | String[] split = fieldChain.split("/.");
86 | // System.out.println("匹配字段");
87 | // System.out.println(split[0]);
88 | // System.out.println(fieldName);
89 | return split[0].replace(".","").equals(fieldName);
90 | }
91 |
92 | public int getFieldLength() {
93 | return fieldLength;
94 | }
95 |
96 | public String getFieldChain(){
97 | return fieldChain;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/dataflow/Analyze.java:
--------------------------------------------------------------------------------
1 | package dataflow;
2 |
3 |
4 | import soot.SootMethod;
5 | import soot.Unit;
6 | import soot.ValueBox;
7 |
8 | import java.util.HashSet;
9 | import java.util.List;
10 |
11 |
12 | public interface Analyze {
13 | boolean caseAnalyze(Unit unit, SootMethod method, List callStack, HashSet res, ValueBox taintValueBox);
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/dataflow/BackwardDataFlow.java:
--------------------------------------------------------------------------------
1 | package dataflow;
2 |
3 | import cfg.CfgFactory;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 | import soot.*;
7 | import soot.jimple.*;
8 | import soot.toolkits.graph.BriefUnitGraph;
9 | import util.StringUtil;
10 |
11 | import java.util.ArrayList;
12 | import java.util.HashSet;
13 | import java.util.List;
14 |
15 |
16 | public class BackwardDataFlow extends AbstractDataFlow {
17 |
18 | private static final Logger logger= LoggerFactory.getLogger(BackwardDataFlow.class);
19 |
20 | private boolean flag=true;
21 |
22 | public boolean getFlag(){
23 | return flag;
24 | }
25 |
26 | public void startBackward(){
27 | this.flag=true;
28 | }
29 |
30 |
31 | public BackwardDataFlow(Analyze analyze){
32 | this.analyze=analyze;
33 | }
34 |
35 | @Override
36 | public boolean caseAnalyze(Unit unit, SootMethod method, List callStack,HashSet res,ValueBox taintValueBox) {
37 | return analyze.caseAnalyze(unit,method,callStack,res,null);
38 | }
39 |
40 | public void run(SootMethod method,Unit endUnit,ValueBox valueBox,int depth,List callStack){
41 | inter_backward_dataflow(method,endUnit,valueBox,depth,callStack);
42 | }
43 |
44 |
45 | public void inter_backward_dataflow(SootMethod method, Unit endUnit, ValueBox endValueBox, int depth, List callStack){
46 |
47 | if(depth>MAX_DEPTH)
48 | return;
49 | if(isMethodCalled(callStack,method))
50 | return;
51 |
52 | CfgFactory cfgFactory = CfgFactory.getInstance();
53 | BriefUnitGraph cfg = cfgFactory.getCFG(method);
54 | if (cfg == null) {
55 | logger.warn("the cfg is null");
56 | return;
57 | }
58 |
59 | EventQueue waitForProcessEvent=new EventQueue();
60 | if(endUnit!=null&&endValueBox!=null) {
61 | Event event = new Event(endUnit, endValueBox);
62 | waitForProcessEvent.add(event);
63 | }else {
64 | for (Unit tailUnit : cfg.getTails()) {
65 | if (tailUnit instanceof ReturnStmt) {
66 | ReturnStmt returnStmt = (ReturnStmt) tailUnit;
67 | if (!returnStmt.getOp().toString().equals("null")) {
68 | Event event = new Event(tailUnit, returnStmt.getOpBox());
69 | waitForProcessEvent.add(event);
70 | }
71 | }
72 | }
73 | }
74 |
75 | HashSet processedEvent=new HashSet<>();
76 | while (!waitForProcessEvent.isEmpty()&&flag){
77 | Event event = waitForProcessEvent.poll();
78 | processedEvent.add(event);
79 | Unit unit = event.unit;
80 | ValueBox valueBox = event.valueBox;
81 | for(Unit pred:cfg.getPredsOf(unit)){
82 | if(isValueDefinedInUnit(pred,valueBox.getValue())){
83 | //todo:对于字段的,对于new不做处理,交给使用者
84 | if (caseAnalyze(pred,method,callStack,null,null)) {
85 | //如果符合条件,将标志位设为false,同时关闭查找
86 | flag = false;
87 | }
88 | if(pred instanceof AssignStmt){
89 | AssignStmt assignStmt = (AssignStmt) pred;
90 | if(assignStmt.containsInvokeExpr()){
91 | SootClass declaringClass = assignStmt.getInvokeExpr().getMethod().getDeclaringClass();
92 | if(!isSystemClass(declaringClass)){
93 | List new_callStack = new ArrayList<>(callStack);
94 | new_callStack.add(new CallSite(method,pred,-1));
95 | for(SootMethod calleeMethod:getMethodFromCG(pred)) {
96 | inter_backward_dataflow(calleeMethod, null, null, depth + 1, new_callStack);
97 | }
98 | }
99 | }
100 | else if(!assignStmt.containsFieldRef()&&!assignStmt.containsArrayRef()){
101 | if(!(assignStmt.getLeftOp() instanceof NewExpr)){
102 | //如果只是简单的赋值
103 | Event new_event = new Event(pred, assignStmt.getUseBoxes().get(0));
104 | if(processedEvent.contains(new_event))
105 | processedEvent.add(new_event);
106 | }
107 | }
108 | }else if((pred instanceof IdentityStmt)&&pred.toString().contains("@param")) {
109 | //todo:如果是参数,我们应该去上一层中进行后向的数据流分析
110 | int parameterOrder = StringUtil.getParameterOrder(pred.toString());
111 | //找寻本方法的调用语句
112 | CallSite preCallSite = getPreCallSite(callStack);
113 | if (preCallSite != null) {
114 | Unit invokeUnit = preCallSite.invokeUnit;
115 | ValueBox arg = null;
116 | if (invokeUnit instanceof AssignStmt) {
117 | arg = ((AssignStmt) invokeUnit).getInvokeExpr().getArgBox(parameterOrder);
118 | } else {
119 | arg = ((InvokeStmt) invokeUnit).getInvokeExpr().getArgBox(parameterOrder);
120 | }
121 | if (arg != null)
122 | inter_backward_dataflow(preCallSite.caller, preCallSite.invokeUnit, arg, depth--, copyAndRemoveLast(callStack));
123 | }else {
124 | logger.info("the object from the param of the first method called");
125 | }
126 | }
127 | }else {
128 | Event old_event = new Event(pred, valueBox);
129 | if(!processedEvent.contains(old_event)){
130 | waitForProcessEvent.add(old_event);
131 | }
132 | }
133 | }
134 | }
135 |
136 |
137 | }
138 | public CallSite getPreCallSite(List callStack) {
139 | if(callStack.size()==0)
140 | return null;
141 | return callStack.get(callStack.size() - 1);
142 |
143 | }
144 |
145 | public List copyAndRemoveLast(List callStack){
146 | List new_callStack=new ArrayList<>(callStack);
147 | new_callStack.remove(callStack.size()-1);
148 | return new_callStack;
149 | }
150 |
151 | }
152 |
--------------------------------------------------------------------------------
/src/main/java/dataflow/CallSite.java:
--------------------------------------------------------------------------------
1 | package dataflow;
2 |
3 | import soot.SootMethod;
4 | import soot.Unit;
5 |
6 | import java.util.Objects;
7 |
8 |
9 | public class CallSite {
10 | public SootMethod caller;
11 | public Unit invokeUnit;
12 | public int paramIndex=-1;
13 |
14 | public CallSite(SootMethod caller, Unit invokeUnit, int paramIndex) {
15 | this.caller = caller;
16 | this.invokeUnit = invokeUnit;
17 | this.paramIndex=paramIndex;
18 | }
19 |
20 | @Override
21 | public boolean equals(Object obj) {
22 | CallSite callSite = (CallSite) obj;
23 | return this.invokeUnit.toString().equals(callSite.invokeUnit.toString()) && this.caller.getSignature().equals(callSite.caller.getSignature());
24 | }
25 |
26 |
27 | @Override
28 | public int hashCode() {
29 | return Objects.hash(caller, invokeUnit);
30 | }
31 |
32 | @Override
33 | public String toString() {
34 | return "CallSite{" +
35 | "caller=" + caller +
36 | ", invokeUnit=" + invokeUnit +
37 | '}';
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/dataflow/DBInfo.java:
--------------------------------------------------------------------------------
1 | package dataflow;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import util.StringUtil;
6 |
7 | import java.awt.*;
8 | import java.util.HashSet;
9 | import java.util.Objects;
10 |
11 |
12 | public class DBInfo {
13 | //数据库信息描述
14 |
15 | public static final Logger logger= LoggerFactory.getLogger(DBInfo.class);
16 |
17 |
18 | public String dbName;
19 | public String tableName;
20 | public String tableInfo;
21 | public String uri;
22 | public boolean insert;
23 |
24 | public DBInfo(String dbName,String tableName,String tableInfo,String uri,boolean insert){
25 | this.dbName=dbName;
26 | this.tableName=tableName;
27 | //需要对table info进行处理
28 | this.tableInfo=getStandardTableInfo(tableInfo,tableName);
29 |
30 | this.uri=uri;
31 | this.insert=insert;
32 | }
33 |
34 | private String getStandardTableInfo(String tableInfo,String tableName){
35 | //我们需要对tableinfo的信息进行处理
36 | if(tableInfo=="")
37 | return "";
38 | String reg="\\{.*\\}";
39 | String string = StringUtil.findString(tableInfo, reg);
40 | if(string==null)
41 | return "";
42 |
43 | String replace = string.replace("{", "");
44 | String s = replace.replace("}", "");
45 | String[] split = s.split("MS");
46 | HashSet