Skip to content

Commit 8a50134

Browse files
committed
Adds convert rule file. #15
1 parent 50c8d67 commit 8a50134

File tree

8 files changed

+519
-109
lines changed

8 files changed

+519
-109
lines changed

nmm-protect/apkprotect/src/main/java/com/nmmedit/apkprotect/dex2c/filters/KeepConfig.java

-28
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,252 @@
11
package com.nmmedit.apkprotect.dex2c.filters;
22

3+
import com.google.common.collect.HashMultimap;
4+
import com.google.common.collect.Maps;
5+
import com.google.common.collect.Sets;
36
import com.nmmedit.apkprotect.deobfus.MappingProcessor;
47
import com.nmmedit.apkprotect.deobfus.MappingReader;
58
import org.jf.dexlib2.iface.ClassDef;
69
import org.jf.dexlib2.iface.Method;
10+
import org.jf.dexlib2.iface.reference.MethodReference;
11+
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference;
712

13+
import javax.annotation.Nonnull;
814
import java.io.IOException;
9-
import java.util.HashMap;
15+
import java.util.ArrayList;
16+
import java.util.List;
1017
import java.util.Map;
18+
import java.util.Set;
1119

1220
/**
1321
* 读取proguard的mapping.txt文件,根据它得到class和方法名混淆前后映射关系,然后再执行过滤规则
1422
*/
1523

16-
public abstract class ProguardMappingConfig implements ClassAndMethodFilter, MappingProcessor {
24+
public class ProguardMappingConfig implements ClassAndMethodFilter, MappingProcessor {
1725
private final ClassAndMethodFilter filter;
18-
private final Map<String, String> newTypeOldTypeMap = new HashMap<>();
19-
20-
public ProguardMappingConfig(ClassAndMethodFilter filter, MappingReader mappingReader) throws IOException {
26+
private final Map<String, String> newTypeOldTypeMap = Maps.newHashMap();
27+
private final Map<String, String> oldTypeNewTypeMap = Maps.newHashMap();
28+
private final Set<MethodMapping> methodSet = Sets.newHashSet();
29+
private final HashMultimap<MethodReference, MethodReference> newMethodRefMap = HashMultimap.create();
30+
private final SimpleRule simpleRule;
31+
32+
public ProguardMappingConfig(ClassAndMethodFilter filter,
33+
MappingReader mappingReader,
34+
SimpleRule simpleRule) throws IOException {
2135
this.filter = filter;
36+
this.simpleRule = simpleRule;
2237
mappingReader.parse(this);
38+
39+
for (MethodMapping methodMapping : methodSet) {
40+
final List<String> args = parseArgs(methodMapping.args);
41+
final ImmutableMethodReference oldMethodRef = new ImmutableMethodReference(
42+
javaType2jvm(methodMapping.className),
43+
methodMapping.methodName, args,
44+
javaType2jvm(methodMapping.returnType));
45+
46+
final List<String> newArgs = getNewArgs(args);
47+
String newRetType = oldTypeNewTypeMap.get(methodMapping.returnType);
48+
if (newRetType == null) {
49+
newRetType = methodMapping.returnType;
50+
}
51+
final ImmutableMethodReference newMethodRef = new ImmutableMethodReference(javaType2jvm(
52+
methodMapping.newClassName),
53+
methodMapping.newMethodName, newArgs,
54+
javaType2jvm(newRetType));
55+
newMethodRefMap.put(newMethodRef, oldMethodRef);
56+
}
2357
}
2458

59+
private List<String> getNewArgs(List<String> args) {
60+
final ArrayList<String> newArgs = new ArrayList<>();
61+
for (String arg : args) {
62+
final String newType = oldTypeNewTypeMap.get(arg);
63+
newArgs.add(newType == null ? arg : newType);
64+
}
65+
return newArgs;
66+
}
67+
68+
2569
@Override
2670
public final boolean acceptClass(ClassDef classDef) {
2771
//先处理上游的过滤规则,如果上游不通过则直接返回不再处理,如果上游通过再处理当前的过滤规则
2872
if (filter != null && !filter.acceptClass(classDef)) {
2973
return false;
3074
}
3175
//得到混淆之前的className
32-
final String oldName = getOriginClassName(classDef.getType());
33-
if (oldName == null) {
76+
final String oldType = getOriginClassType(classDef.getType());
77+
if (oldType == null) {
3478
return false;
3579
}
36-
//需要保留的class返回false,
37-
return !keepClass(classDef);
80+
final ArrayList<String> ifacs = new ArrayList<>();
81+
for (String ifac : classDef.getInterfaces()) {
82+
ifacs.add(getOriginClassType(ifac));
83+
}
84+
85+
return simpleRule != null && simpleRule.matchClass(
86+
oldType,
87+
getOriginClassType(classDef.getSuperclass()),
88+
ifacs);
3889
}
3990

40-
protected abstract boolean keepClass(ClassDef classDef);
4191

42-
protected String getOriginClassName(String type) {
43-
return newTypeOldTypeMap.get(type);
92+
private String getOriginClassType(String type) {
93+
final String oldType = newTypeOldTypeMap.get(type);
94+
if (oldType == null) {
95+
return type;
96+
}
97+
return oldType;
4498
}
4599

46100
@Override
47101
public final boolean acceptMethod(Method method) {
48102
if (filter != null && !filter.acceptMethod(method)) {
49103
return false;
50104
}
51-
return !keepMethod(method);
52-
}
105+
final String oldType = getOriginClassType(method.getDefiningClass());
106+
if (oldType == null) {
107+
return false;
108+
}
109+
final Set<MethodReference> oldMethodRefSet = newMethodRefMap.get(method);
110+
53111

54-
protected abstract boolean keepMethod(Method method);
112+
if (oldMethodRefSet != null) {
113+
114+
for (MethodReference reference : oldMethodRefSet) {
115+
if (oldType.equals(reference.getDefiningClass())) {
116+
if (simpleRule != null && simpleRule.matchMethod(reference.getName())) {
117+
return true;
118+
}
119+
}
120+
}
121+
122+
}
123+
124+
return simpleRule != null && simpleRule.matchMethod(method.getName());
125+
}
55126

56127
private static String classNameToType(String className) {
57128
return "L" + className.replace('.', '/') + ";";
58129
}
59130

60131
@Override
61132
public final void processClassMapping(String className, String newClassName) {
62-
newTypeOldTypeMap.put(classNameToType(newClassName), className);
133+
newTypeOldTypeMap.put(classNameToType(newClassName), classNameToType(className));
134+
oldTypeNewTypeMap.put(classNameToType(className), classNameToType(newClassName));
63135
}
64136

65137
@Override
66138
public final void processFieldMapping(String className, String fieldType, String fieldName, String newClassName, String newFieldName) {
67139

68140
}
69141

142+
@Nonnull
143+
private static String javaType2jvm(@Nonnull String type) {
144+
switch (type.trim()) {
145+
case "boolean":
146+
return "Z";
147+
case "byte":
148+
return "B";
149+
case "char":
150+
return "C";
151+
case "short":
152+
return "S";
153+
case "int":
154+
return "I";
155+
case "float":
156+
return "F";
157+
case "long":
158+
return "J";
159+
case "double":
160+
return "D";
161+
case "void":
162+
return "V";
163+
default:
164+
int i = type.indexOf('[');
165+
if (i != -1) {
166+
String t = type.substring(0, i);
167+
StringBuilder arr = new StringBuilder("[");
168+
while ((i = type.indexOf('[', i + 1)) != -1) {
169+
arr.append('[');
170+
}
171+
arr.append(javaType2jvm(t));
172+
return arr.toString();
173+
} else {
174+
return classNameToType(type);
175+
}
176+
177+
}
178+
}
179+
180+
@Nonnull
181+
private List<String> parseArgs(String methodArgs) {
182+
final ArrayList<String> args = new ArrayList<>();
183+
if ("".equals(methodArgs)) {
184+
return args;
185+
}
186+
final String[] split = methodArgs.split(",");
187+
for (String type : split) {
188+
args.add(javaType2jvm(type));
189+
}
190+
return args;
191+
}
192+
70193
@Override
71-
public final void processMethodMapping(String className, int firstLineNumber, int lastLineNumber, String methodReturnType, String methodName, String methodArguments, String newClassName, int newFirstLineNumber, int newLastLineNumber, String newMethodName) {
194+
public final void processMethodMapping(String className,
195+
int firstLineNumber, int lastLineNumber,
196+
String methodReturnType,
197+
String methodName,
198+
String methodArguments,
199+
String newClassName,
200+
int newFirstLineNumber, int newLastLineNumber,
201+
String newMethodName) {
202+
final MethodMapping mapping = new MethodMapping(className, methodName, newClassName, newMethodName, methodArguments, methodReturnType);
203+
methodSet.add(mapping);
204+
}
205+
206+
private static class MethodMapping {
207+
private final String className;
208+
private final String methodName;
209+
210+
private final String newClassName;
211+
private final String newMethodName;
212+
private final String args;
213+
private final String returnType;
214+
215+
public MethodMapping(String className, String methodName,
216+
String newClassName, String newMethodName,
217+
String args, String returnType) {
218+
this.className = className;
219+
this.methodName = methodName;
220+
this.newClassName = newClassName;
221+
this.newMethodName = newMethodName;
222+
this.args = args;
223+
this.returnType = returnType;
224+
}
225+
226+
@Override
227+
public boolean equals(Object o) {
228+
if (this == o) return true;
229+
if (o == null || getClass() != o.getClass()) return false;
72230

231+
MethodMapping that = (MethodMapping) o;
232+
233+
if (!className.equals(that.className)) return false;
234+
if (!methodName.equals(that.methodName)) return false;
235+
if (!newClassName.equals(that.newClassName)) return false;
236+
if (!newMethodName.equals(that.newMethodName)) return false;
237+
if (!args.equals(that.args)) return false;
238+
return returnType.equals(that.returnType);
239+
}
240+
241+
@Override
242+
public int hashCode() {
243+
int result = className.hashCode();
244+
result = 31 * result + methodName.hashCode();
245+
result = 31 * result + newClassName.hashCode();
246+
result = 31 * result + newMethodName.hashCode();
247+
result = 31 * result + args.hashCode();
248+
result = 31 * result + returnType.hashCode();
249+
return result;
250+
}
73251
}
74252
}

nmm-protect/apkprotect/src/main/java/com/nmmedit/apkprotect/dex2c/filters/RegexKeepConfig.java

-36
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.nmmedit.apkprotect.dex2c.filters;
2+
3+
import org.jf.dexlib2.iface.ClassDef;
4+
import org.jf.dexlib2.iface.Method;
5+
6+
public class SimpleConvertConfig implements ClassAndMethodFilter {
7+
private final ClassAndMethodFilter filter;
8+
private final SimpleRule simpleRule;
9+
10+
public SimpleConvertConfig(ClassAndMethodFilter filter, SimpleRule simpleRule) {
11+
this.filter = filter;
12+
this.simpleRule = simpleRule;
13+
}
14+
15+
@Override
16+
public boolean acceptClass(ClassDef classDef) {
17+
if (filter != null && !filter.acceptClass(classDef)) {
18+
return false;
19+
}
20+
return simpleRule != null && simpleRule.matchClass(
21+
classDef.getType(),
22+
classDef.getSuperclass(),
23+
classDef.getInterfaces());
24+
}
25+
26+
@Override
27+
public boolean acceptMethod(Method method) {
28+
if (filter != null && !filter.acceptMethod(method)) {
29+
return false;
30+
}
31+
return simpleRule != null && simpleRule.matchMethod(method.getName());
32+
}
33+
}

0 commit comments

Comments
 (0)